Commits

Armin Rigo  committed f7dc1ac

Revert some more changes

  • Participants
  • Parent commits 005b73c
  • Branches stmgc-c7

Comments (0)

Files changed (4)

File rpython/jit/backend/llsupport/gc.py

     def get_root_stack_top_addr(self):
         rst_addr = llop.gc_adr_of_root_stack_top(llmemory.Address)
         return rffi.cast(lltype.Signed, rst_addr)
-        
-        
-class BarrierDescr(AbstractDescr):
+
+class WriteBarrierDescr(AbstractDescr):
     def __init__(self, gc_ll_descr):
         self.llop1 = gc_ll_descr.llop1
-
-        self.returns_modified_object = False
-        self.gcheaderbuilder = gc_ll_descr.gcheaderbuilder
-        self.HDRPTR = gc_ll_descr.HDRPTR
-        self.b_slowpath = [0, 0, 0, 0, 0]
-
-    def repr_of_descr(self):
-        raise NotImplementedError
-
-    def __repr(self):
-        raise NotImplementedError
-
-    def get_b_slowpath(self, num):
-        return self.b_slowpath[num]
-
-    def set_b_slowpath(self, num, addr):
-        self.b_slowpath[num] = addr
-
-    def get_barrier_funcptr(self, returns_modified_object):
-        raise NotImplementedError
-        
-    def get_barrier_fn(self, cpu, returns_modified_object):
-        # must pass in 'self.returns_modified_object', to make sure that
-        # the callers are fixed for this case
-        funcptr = self.get_barrier_funcptr(returns_modified_object)
-        funcaddr = llmemory.cast_ptr_to_adr(funcptr)
-        return cpu.cast_adr_to_int(funcaddr)
-
-    def get_barrier_from_array_fn(self, cpu):
-        # returns a function with arguments [array, index, newvalue]
-        llop1 = self.llop1
-        funcptr = llop1.get_write_barrier_from_array_failing_case(
-            self.FUNCPTR)
-        funcaddr = llmemory.cast_ptr_to_adr(funcptr)
-        return cpu.cast_adr_to_int(funcaddr)    # this may return 0
-
-    def has_barrier_from_array(self, cpu):
-        return self.get_barrier_from_array_fn(cpu) != 0
-
-
-        
-class WriteBarrierDescr(BarrierDescr):
-    def __init__(self, gc_ll_descr):
-        BarrierDescr.__init__(self, gc_ll_descr)
+        self.WB_FUNCPTR = gc_ll_descr.WB_FUNCPTR
         self.fielddescr_tid = gc_ll_descr.fielddescr_tid
-        self.FUNCPTR = lltype.Ptr(lltype.FuncType(
-            [llmemory.Address], lltype.Void))
-
+        #
         GCClass = gc_ll_descr.GCClass
+        if GCClass is None:     # for tests
+            return
         self.jit_wb_if_flag = GCClass.JIT_WB_IF_FLAG
         self.jit_wb_if_flag_byteofs, self.jit_wb_if_flag_singlebyte = (
             self.extract_flag_byte(self.jit_wb_if_flag))
         else:
             self.jit_wb_cards_set = 0
 
-    def repr_of_descr(self):
-        return 'wbdescr'
-
-    def __repr__(self):
-        return '<WriteBarrierDescr %r>' % (self.repr_of_descr(),)
-
     def extract_flag_byte(self, flag_word):
         # if convenient for the backend, we compute the info about
         # the flag as (byte-offset, single-byte-flag).
-        if flag_word == 0:
-            return (0, 0)
         import struct
         value = struct.pack(lltype.SignedFmt, flag_word)
         assert value.count('\x00') == len(value) - 1    # only one byte is != 0
         while value[i] == '\x00': i += 1
         return (i, struct.unpack('b', value[i])[0])
 
-    def get_barrier_funcptr(self, returns_modified_object):
-        assert not returns_modified_object
-        FUNCTYPE = self.FUNCPTR
-        return self.llop1.get_write_barrier_failing_case(FUNCTYPE)
+    def get_write_barrier_fn(self, cpu):
+        llop1 = self.llop1
+        funcptr = llop1.get_write_barrier_failing_case(self.WB_FUNCPTR)
+        funcaddr = llmemory.cast_ptr_to_adr(funcptr)
+        return cpu.cast_adr_to_int(funcaddr)
 
-    @specialize.arg(2)
-    def _do_barrier(self, gcref_struct, returns_modified_object):
-        assert self.returns_modified_object == returns_modified_object
-        hdr_addr = llmemory.cast_ptr_to_adr(gcref_struct)
-        hdr_addr -= self.gcheaderbuilder.size_gc_header
-        hdr = llmemory.cast_adr_to_ptr(hdr_addr, self.HDRPTR)
-        if self.jit_wb_if_flag == 0 or hdr.tid & self.jit_wb_if_flag:
-            # get a pointer to the 'remember_young_pointer' function from
-            # the GC, and call it immediately
-            funcptr = self.get_barrier_funcptr(returns_modified_object)
-            funcptr(llmemory.cast_ptr_to_adr(gcref_struct))
+    def get_write_barrier_from_array_fn(self, cpu):
+        # returns a function with arguments [array, index, newvalue]
+        llop1 = self.llop1
+        funcptr = llop1.get_write_barrier_from_array_failing_case(
+            self.WB_FUNCPTR)
+        funcaddr = llmemory.cast_ptr_to_adr(funcptr)
+        return cpu.cast_adr_to_int(funcaddr)    # this may return 0
 
-            
-class STMBarrierDescr(BarrierDescr):
-    def __init__(self, gc_ll_descr, stmcat, cfunc_name):
-        BarrierDescr.__init__(self, gc_ll_descr)
-        self.stmcat = stmcat
-        self.returns_modified_object = True
-        self.B_FUNCPTR_MOD = lltype.Ptr(lltype.FuncType(
-            [llmemory.Address], llmemory.Address))
+    def has_write_barrier_from_array(self, cpu):
+        return self.get_write_barrier_from_array_fn(cpu) != 0
 
-        self.b_failing_case_ptr = rffi.llexternal(
-            cfunc_name,
-            self.B_FUNCPTR_MOD.TO.ARGS,
-            self.B_FUNCPTR_MOD.TO.RESULT,
-            sandboxsafe=True,
-            _nowrapper=True)
 
-    def repr_of_descr(self):
-        return self.stmcat
-
-    def __repr__(self):
-        return '<STMBarrierDescr %r>' % (self.repr_of_descr(),)
-
-    def get_barrier_funcptr(self, returns_modified_object):
-        assert returns_modified_object
-        return self.b_failing_case_ptr
-
-    @specialize.arg(2)
-    def _do_barrier(self, gcref_struct, returns_modified_object):
-        raise NotImplementedError("implement in subclasses!")
-        assert self.returns_modified_object == returns_modified_object
-        funcptr = self.get_barrier_funcptr(returns_modified_object)
-        res = funcptr(llmemory.cast_ptr_to_adr(gcref_struct))
-        return llmemory.cast_adr_to_ptr(res, llmemory.GCREF)
-
-
-class STMReadBarrierDescr(STMBarrierDescr):
-    def __init__(self, gc_ll_descr, stmcat):
-        assert stmcat in ['A2R', 'Q2R', 'A2I']
-        func = {'A2R': 'stm_DirectReadBarrier',
-                'Q2R': 'stm_RepeatReadBarrier',
-                'A2I': 'stm_ImmutReadBarrier',
-                }
-        
-        STMBarrierDescr.__init__(self, gc_ll_descr, stmcat,
-                                 func[stmcat])
-
-    @specialize.arg(2)
-    def _do_barrier(self, gcref_struct, returns_modified_object):
-        assert returns_modified_object
-        from rpython.memory.gc.stmgc import StmGC
-        objadr = llmemory.cast_ptr_to_adr(gcref_struct)
-        objhdr = rffi.cast(StmGC.GCHDRP, gcref_struct)
-
-        if self.stmcat == 'A2R':
-            # if h_revision == privat_rev of transaction
-            priv_rev = self.llop1.stm_get_adr_of_private_rev_num(rffi.SIGNEDP)
-            if objhdr.h_revision == priv_rev[0]:
-                return gcref_struct
-
-            # readcache[obj] == obj
-            read_cache = self.llop1.stm_get_adr_of_read_barrier_cache(rffi.SIGNEDP)
-            objint = llmemory.cast_adr_to_int(objadr)
-            assert WORD == 8, "check for 32bit compatibility"
-            index = (objint & StmGC.FX_MASK) / WORD
-            CP = lltype.Ptr(rffi.CArray(lltype.Signed))
-            rcp = rffi.cast(CP, read_cache[0])
-            if rcp[index] == objint:
-                return gcref_struct
-        elif self.stmcat == 'Q2R':
-            # is GCFLAG_PUBLIC_TO_PRIVATE or GCFLAG_MOVED set?
-            if not (objhdr.h_tid &
-                    (StmGC.GCFLAG_PUBLIC_TO_PRIVATE | StmGC.GCFLAG_MOVED)):
-                # no.
-                return gcref_struct
-        else: # A2I
-            # GCFLAG_STUB set?
-            if not (objhdr.h_tid & StmGC.GCFLAG_STUB):
-                return gcref_struct
-        
-        funcptr = self.get_barrier_funcptr(returns_modified_object)
-        res = funcptr(objadr)
-        return llmemory.cast_adr_to_ptr(res, llmemory.GCREF)
-
-        
-class STMWriteBarrierDescr(STMBarrierDescr):
-    def __init__(self, gc_ll_descr, stmcat):
-        assert stmcat in ['A2W', 'V2W', 'A2V']
-        func = {'A2W':'stm_WriteBarrier',
-                'V2W':'stm_RepeatWriteBarrier',
-                'A2V':'stm_WriteBarrier',
-                }
-
-        STMBarrierDescr.__init__(self, gc_ll_descr, stmcat,
-                                 func[stmcat])
-
-
-    @specialize.arg(2)
-    def _do_barrier(self, gcref_struct, returns_modified_object):
-        assert returns_modified_object
-        from rpython.memory.gc.stmgc import StmGC
-        objadr = llmemory.cast_ptr_to_adr(gcref_struct)
-        objhdr = rffi.cast(StmGC.GCHDRP, gcref_struct)
-
-        # for A2W, we check h_revision and WRITE_BARRIER
-        # for V2W, we only check WRITE_BARRIER
-        # for A2V, we only check h_revision
-        
-        # if it is a repeated WB or h_revision == privat_rev of transaction
-        priv_rev = self.llop1.stm_get_adr_of_private_rev_num(rffi.SIGNEDP)
-        if self.stmcat == 'V2W' or objhdr.h_revision == priv_rev[0]:
-            # also WRITE_BARRIER not set?
-            if (self.stmcat == 'A2V'
-                or not (objhdr.h_tid & StmGC.GCFLAG_WRITE_BARRIER)):
-                return gcref_struct
-        
-        funcptr = self.get_barrier_funcptr(returns_modified_object)
-        res = funcptr(objadr)
-        return llmemory.cast_adr_to_ptr(res, llmemory.GCREF)
-    
-        
 class GcLLDescr_framework(GcLLDescription):
     DEBUG = False    # forced to True by x86/test/test_zrpy_gc.py
     kind = 'framework'
     def _initialize_for_tests(self):
         self.layoutbuilder = None
         self.fielddescr_tid = AbstractDescr()
-        self.fielddescr_rev = AbstractDescr()
         self.max_size_of_young_obj = 1000
         self.GCClass = None
         self.gcheaderbuilder = None
     def _setup_tid(self):
         if not self.stm:
             self.fielddescr_tid = get_field_descr(self, self.GCClass.HDR, 'tid')
-            self.fielddescr_rev = None
         else:
+            xxxxxxxx
             self.fielddescr_tid = get_field_descr(self, self.GCClass.GCHDR,
                                                   'h_tid')
-            self.fielddescr_rev = get_field_descr(self, self.GCClass.GCHDR,
-                                                  'h_revision')
-                        
         frame_tid = self.layoutbuilder.get_type_id(jitframe.JITFRAME)
         self.translator._jit2gc['frame_tid'] = frame_tid
 
     def _setup_write_barrier(self):
-        if self.stm:
-            self.A2Rdescr = STMReadBarrierDescr(self, 'A2R')
-            self.A2Idescr = STMReadBarrierDescr(self, 'A2I')
-            self.Q2Rdescr = STMReadBarrierDescr(self, 'Q2R')
-            self.A2Wdescr = STMWriteBarrierDescr(self, 'A2W')
-            self.A2Vdescr = STMWriteBarrierDescr(self, 'A2V')
-            self.V2Wdescr = STMWriteBarrierDescr(self, 'V2W')
-            self.write_barrier_descr = "wbdescr: do not use"
-        else:
-            self.write_barrier_descr = WriteBarrierDescr(self)
+        self.WB_FUNCPTR = lltype.Ptr(lltype.FuncType(
+            [llmemory.Address], lltype.Void))
+        self.write_barrier_descr = WriteBarrierDescr(self)
 
     def _make_functions(self, really_not_translated):
         from rpython.memory.gctypelayout import check_typeid
         hdr.tid = tid
 
     def can_use_nursery_malloc(self, size):
-        return (self.max_size_of_young_obj is not None and
-                size < self.max_size_of_young_obj)
+        return size < self.max_size_of_young_obj
         
     def has_write_barrier_class(self):
         return WriteBarrierDescr
 
     def get_malloc_slowpath_addr(self):
-        if self.max_size_of_young_obj is None:    # stm
-            return None
         return self.get_malloc_fn_addr('malloc_nursery')
 
     def get_malloc_slowpath_array_addr(self):

File rpython/jit/backend/llsupport/rewrite.py

             if op.is_malloc():
                 self.handle_malloc_operation(op)
                 continue
-            elif op.can_malloc():
+            elif op.is_call():
                 self.emitting_an_operation_that_can_collect()
             elif op.getopnum() == rop.LABEL:
                 self.emitting_an_operation_that_can_collect()

File rpython/jit/backend/llsupport/stmrewrite.py

             return
         # ----------  transaction breaks  ----------
         if opnum == rop.STM_TRANSACTION_BREAK:
-            # XXX redo!
-            #self.emitting_an_operation_that_can_collect()
-            #self.next_op_may_be_in_new_transaction()
-            #self.newops.append(op)
+            self.emitting_an_operation_that_can_collect()
+            self.next_op_may_be_in_new_transaction()
+            self.newops.append(op)
             return
         # ----------  pure operations, guards  ----------
         if op.is_always_pure() or op.is_guard() or op.is_ovf():
             return
         # ----------  calls  ----------
         if op.is_call():
+            if opnum == rop.CALL and op.getdescr():
+                d = op.getdescr()
+                assert isinstance(d, CallDescr)
+                ei = d.get_extra_info()
+                if ei and (ei.oopspecindex ==
+                           EffectInfo.OS_JIT_STM_SHOULD_BREAK_TRANSACTION):
+                    self.newops.append(op)
+                    return
+            #
+            self.next_op_may_be_in_new_transaction()
+            #
             if opnum == rop.CALL_RELEASE_GIL:
                 # self.fallback_inevitable(op)
                 # is done by assembler._release_gil_shadowstack()
                 else:
                     self.newops.append(op)
             return
+        # ----------  setters for pure fields  ----------
+        if opnum in (rop.STRSETITEM, rop.UNICODESETITEM):
+            self.handle_setters_for_pure_fields(op)
+            return
         # ----------  copystrcontent  ----------
         if opnum in (rop.COPYSTRCONTENT, rop.COPYUNICODECONTENT):
             self.handle_copystrcontent(op)
-            continue
-        XXX
+            return
         # ----------  raw getfields and setfields  ----------
         if opnum in (rop.GETFIELD_RAW, rop.SETFIELD_RAW):
             if self.maybe_handle_raw_accesses(op):
-                continue
+                return
         # ----------  labels  ----------
         if opnum == rop.LABEL:
-            self.emitting_an_operation_that_can_collect()
+            # note that the parent class also clears some things on a LABEL
             self.next_op_may_be_in_new_transaction()
-            
             self.newops.append(op)
-            continue
-        # ----------  jumps  ----------
-        if opnum == rop.JUMP:
+            return
+        # ----------  jumps, finish, other ignored ops  ----------
+        if opnum in (rop.JUMP, rop.FINISH, rop.FORCE_TOKEN,
+                     rop.READ_TIMESTAMP, rop.MARK_OPAQUE_PTR,
+                     rop.JIT_DEBUG, rop.KEEPALIVE,
+                     rop.QUASIIMMUT_FIELD, rop.RECORD_KNOWN_CLASS,
+                     ):
             self.newops.append(op)
-            continue
-        # ----------  finish, other ignored ops  ----------
-        if opnum in (rop.FINISH, rop.FORCE_TOKEN,
-                    rop.READ_TIMESTAMP, rop.MARK_OPAQUE_PTR,
-                    rop.JIT_DEBUG, rop.KEEPALIVE,
-                    rop.QUASIIMMUT_FIELD, rop.RECORD_KNOWN_CLASS,
-                    ):
-            self.newops.append(op)
-            continue
+            return
         # ----------  fall-back  ----------
-        # Check that none of the ops handled here can_collect
-        # or cause a transaction break. This is not done by
-        # the fallback here
+        # Check that none of the ops handled here can collect.
+        # This is not done by the fallback here
+        assert not op.is_call() and not op.is_malloc()
         self.fallback_inevitable(op)
-        debug_print("fallback for", op.repr())
 
-    def emitting_an_operation_that_can_collect(self):
-        GcRewriterAssembler.emitting_an_operation_that_can_collect(self)
-        self.invalidate_write_categories()
-    
     def next_op_may_be_in_new_transaction(self):
-        self.known_lengths.clear() # XXX: check if really necessary or
-                                   # just for labels
-        self.known_category.clear()
         self.always_inevitable = False
 
-    def invalidate_write_categories(self):
-        for v, c in self.known_category.items():
-            if c == 'W':
-                self.known_category[v] = 'V'
-
-    def invalidate_read_categories(self, reason):
-        # XXX: needs aliasing info to be better
-        # XXX: move to optimizeopt to only invalidate same typed vars?
-        for v, c in self.known_category.items():
-            if c == 'R':
-                self.known_category[v] = 'Q'
-
-    
-    def get_barrier_descr(self, from_cat, to_cat):
-        # compare with translator.stm.funcgen.stm_barrier
-        # XXX: specialize more with info of IMMUTABLE and NOPTR
-        if from_cat >= to_cat:
-            return None
-        
-        gc = self.gc_ll_descr
-        if to_cat == 'W':
-            if from_cat >= 'V':
-                return gc.V2Wdescr
-            return gc.A2Wdescr
-        elif to_cat == 'V':
-            return gc.A2Vdescr
-        elif to_cat == 'R':
-            if from_cat >= 'Q':
-                return gc.Q2Rdescr
-            return gc.A2Rdescr
-        elif to_cat == 'I':
-            return gc.A2Idescr
-
-    def gen_initialize_tid(self, v_newgcobj, tid):
-        GcRewriterAssembler.gen_initialize_tid(self, v_newgcobj, tid)
-        if self.gc_ll_descr.fielddescr_rev is not None:
-            op = ResOperation(rop.STM_SET_REVISION_GC, [v_newgcobj,], None,
-                              descr=self.gc_ll_descr.fielddescr_rev)
-            self.newops.append(op)
-            
-    def gen_write_barrier(self, v):
-        raise NotImplementedError
-
-    def gen_barrier(self, v_base, target_category):
-        v_base = self.unconstifyptr(v_base)
-        assert isinstance(v_base, BoxPtr)
-        source_category = self.known_category.get(v_base, 'A')
-        write_barrier_descr = self.get_barrier_descr(source_category,
-                                                     target_category)
-        if write_barrier_descr is None:
-            return v_base    # no barrier needed
-
-        if target_category in ('W', 'V'):
-            # if *any* of the readable vars is the same object,
-            # it must repeat the read_barrier now
-            self.invalidate_read_categories(v_base)
-
-        args = [v_base,]
-        op = rop.COND_CALL_STM_B
-        self.newops.append(ResOperation(op, args, None,
-                                        descr=write_barrier_descr))
-        
-        self.known_category[v_base] = target_category
-        return v_base
-
-    def unconstifyptr(self, v):
-        if isinstance(v, ConstPtr):
-            v_in = v
-            v_out = BoxPtr()
-            self.newops.append(ResOperation(rop.SAME_AS, [v_in], v_out))
-            v = v_out
-        assert isinstance(v, BoxPtr)
-        return v
-
     def handle_getfields(self, op):
         opnum = op.getopnum()
         descr = op.getdescr()
             self._do_stm_call('stm_try_inevitable', [], None)
             self.always_inevitable = True
         self.newops.append(op)
+        debug_print("fallback for", op.repr())
 
     def _is_null(self, box):
         return isinstance(box, ConstPtr) and not box.value

File rpython/jit/backend/llsupport/test/test_rewrite.py

         register_known_gctype(self.cpu, o_vtable, O)
         #
         tiddescr = self.gc_ll_descr.fielddescr_tid
-        revdescr = self.gc_ll_descr.fielddescr_rev
         wbdescr = self.gc_ll_descr.write_barrier_descr
         WORD = globals()['WORD']
         #
             namespace[funcname + '_descr'] = getattr(self.gc_ll_descr,
                                                      '%s_descr' % funcname)
         #
-        ops = parse(frm_operations, namespace=namespace,
-                    invent_fail_descr=False)
+        ops = parse(frm_operations, namespace=namespace)
         expected = parse(to_operations % Evaluator(namespace),
-                         namespace=namespace,
-                         invent_fail_descr=False)
+                         namespace=namespace)
         operations = self.gc_ll_descr.rewrite_assembler(self.cpu,
                                                         ops.operations,
                                                         [])
         gcdescr = get_description(config_)
         self.gc_ll_descr = GcLLDescr_framework(gcdescr, None, None, None,
                                                really_not_translated=True)
-        self.gc_ll_descr.write_barrier_descr.has_barrier_from_array = (
+        self.gc_ll_descr.write_barrier_descr.has_write_barrier_from_array = (
             lambda cpu: True)
         #
         class FakeCPU(BaseFakeCPU):
         """)
 
     def test_write_barrier_before_array_without_from_array(self):
-        self.gc_ll_descr.write_barrier_descr.has_barrier_from_array = (
+        self.gc_ll_descr.write_barrier_descr.has_write_barrier_from_array = (
             lambda cpu: False)
         self.check_rewrite("""
             [p1, i2, p3]