Author: Armin Rigo <ar...@tunes.org> Branch: stm-jit Changeset: r56586:4a547da831fd Date: 2012-08-05 16:22 +0200 http://bitbucket.org/pypy/pypy/changeset/4a547da831fd/
Log: in-progress. Missing tests :-( diff --git a/pypy/jit/backend/llsupport/gc.py b/pypy/jit/backend/llsupport/gc.py --- a/pypy/jit/backend/llsupport/gc.py +++ b/pypy/jit/backend/llsupport/gc.py @@ -22,6 +22,7 @@ # ____________________________________________________________ class GcLLDescription(GcCache): + stm = False def __init__(self, gcdescr, translator=None, rtyper=None): GcCache.__init__(self, translator is not None, rtyper) @@ -580,11 +581,12 @@ class WriteBarrierDescr(AbstractDescr): def __init__(self, gc_ll_descr): self.llop1 = gc_ll_descr.llop1 - if not gc_ll_descr.stm: + self.returns_modified_object = gc_ll_descr.stm + if not self.returns_modified_object: self.WB_FUNCPTR = lltype.Ptr(lltype.FuncType( [llmemory.Address], lltype.Void)) else: - self.WB_STM_FUNCPTR = lltype.Ptr(lltype.FuncType( + self.WB_FUNCPTR_MOD = lltype.Ptr(lltype.FuncType( [llmemory.Address], llmemory.Address)) self.fielddescr_tid = gc_ll_descr.fielddescr_tid # @@ -618,9 +620,16 @@ while value[i] == '\x00': i += 1 return (i, struct.unpack('b', value[i])[0]) - def get_write_barrier_fn(self, cpu): + def get_write_barrier_fn(self, cpu, returns_modified_object=False): + # must pass in 'self.returns_modified_object', to make sure that + # the callers are fixed for this case + assert returns_modified_object == self.returns_modified_object + if returns_modified_object: + FUNCTYPE = self.WB_FUNCPTR_MOD + else: + FUNCTYPE = self.WB_FUNCPTR llop1 = self.llop1 - funcptr = llop1.get_write_barrier_failing_case(self.WB_FUNCPTR) + funcptr = llop1.get_write_barrier_failing_case(FUNCTYPE) funcaddr = llmemory.cast_ptr_to_adr(funcptr) return cpu.cast_adr_to_int(funcaddr) @@ -630,6 +639,7 @@ funcptr = llop1.get_write_barrier_from_array_failing_case( self.WB_FUNCPTR) funcaddr = llmemory.cast_ptr_to_adr(funcptr) + assert not (funcaddr and self.returns_modified_object) return cpu.cast_adr_to_int(funcaddr) # this may return 0 def has_write_barrier_from_array(self, cpu): @@ -646,7 +656,10 @@ GcLLDescription.__init__(self, gcdescr, translator, rtyper) self.translator = translator self.llop1 = llop1 - self.stm = translator.config.translation.stm + try: + self.stm = translator.config.translation.stm + except AttributeError: + pass # keep the default of False if really_not_translated: assert not self.translate_support_code # but half does not work self._initialize_for_tests() diff --git a/pypy/jit/backend/llsupport/rewrite.py b/pypy/jit/backend/llsupport/rewrite.py --- a/pypy/jit/backend/llsupport/rewrite.py +++ b/pypy/jit/backend/llsupport/rewrite.py @@ -274,8 +274,8 @@ v = op.getarg(1) if isinstance(v, BoxPtr) or (isinstance(v, ConstPtr) and bool(v.value)): # store a non-NULL + op = self.prepare_write_barrier(op, rop.SETFIELD_RAW) self.gen_write_barrier(op.getarg(0), v) - op = op.copy_and_change(rop.SETFIELD_RAW) self.newops.append(op) def handle_write_barrier_setinteriorfield(self, op): @@ -285,8 +285,8 @@ v = op.getarg(2) if isinstance(v, BoxPtr) or (isinstance(v, ConstPtr) and bool(v.value)): # store a non-NULL + op = self.prepare_write_barrier(op, rop.SETINTERIORFIELD_RAW) self.gen_write_barrier(op.getarg(0), v) - op = op.copy_and_change(rop.SETINTERIORFIELD_RAW) self.newops.append(op) def handle_write_barrier_setarrayitem(self, op): @@ -296,11 +296,21 @@ v = op.getarg(2) if isinstance(v, BoxPtr) or (isinstance(v, ConstPtr) and bool(v.value)): # store a non-NULL + op = self.prepare_write_barrier(op, rop.SETARRAYITEM_RAW) self.gen_write_barrier_array(op.getarg(0), op.getarg(1), v) - op = op.copy_and_change(rop.SETARRAYITEM_RAW) self.newops.append(op) + def prepare_write_barrier(self, op, newopnum): + write_barrier_descr = self.gc_ll_descr.write_barrier_descr + args = op.getarglist() + if (write_barrier_descr.returns_modified_object and + isinstance(op.getarg(0), ConstPtr)): + v_box = BoxPtr() + self.newops.append(ResOperation(rop.SAME_AS, [args[0]], v_box)) + args[0] = v_box + return op.copy_and_change(opnum=newopnum, args=args) + def gen_write_barrier(self, v_base, v_value): write_barrier_descr = self.gc_ll_descr.write_barrier_descr args = [v_base, v_value] @@ -313,6 +323,7 @@ # If we know statically the length of 'v', and it is not too # big, then produce a regular write_barrier. If it's unknown or # too big, produce instead a write_barrier_from_array. + assert not write_barrier_descr.returns_modified_object LARGE = 130 length = self.known_lengths.get(v_base, LARGE) if length >= LARGE: diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py --- a/pypy/jit/backend/x86/assembler.py +++ b/pypy/jit/backend/x86/assembler.py @@ -351,12 +351,17 @@ rawstart = mc.materialize(self.cpu.asmmemmgr, []) self.stack_check_slowpath = rawstart + def _wb_returns_modified_object(self): + descr = self.cpu.gc_ll_descr.write_barrier_descr + return descr.returns_modified_object + def _build_wb_slowpath(self, withcards, withfloats=False): descr = self.cpu.gc_ll_descr.write_barrier_descr if descr is None: return if not withcards: - func = descr.get_write_barrier_fn(self.cpu) + func = descr.get_write_barrier_fn(self.cpu, + descr.returns_modified_object) else: if descr.jit_wb_cards_set == 0: return @@ -402,6 +407,9 @@ mc.MOV_rs(edi.value, (frame_size - 1) * WORD) mc.CALL(imm(func)) # + if descr.returns_modified_object: + mc.MOV_sr(correct_esp_by, eax.value) + # if withcards: # A final TEST8 before the RET, for the caller. Careful to # not follow this instruction with another one that changes @@ -422,7 +430,10 @@ # ADD esp, correct_esp_by --- but cannot use ADD, because # of its effects on the CPU flags mc.LEA_rs(esp.value, correct_esp_by) - mc.RET16_i(WORD) + if not descr.returns_modified_object: + mc.RET16_i(WORD) + else: + mc.RET() # and leave the modified object in [ESP+0] # rawstart = mc.materialize(self.cpu.asmmemmgr, []) self.wb_slowpath[withcards + 2 * withfloats] = rawstart @@ -2480,6 +2491,16 @@ self.mc.PUSH(loc_base) self.mc.CALL(imm(self.wb_slowpath[helper_num])) + if self._wb_returns_modified_object(): + # the value at [ESP] is not popped in this case, but possibly + # updated. We have to use it to update the register at loc_base + assert isinstance(loc_base, RegLoc) + self.mc.POP_r(loc_base.value) + # also update the copy of the same value in the stack, if any + loc_base_2 = self._regalloc.fm.get(op.getarg(0)) + if loc_base_2 is not None: + self.regalloc_mov(loc_base, loc_base_2) + if card_marking: # The helper ends again with a check of the flag in the object. # So here, we can simply write again a 'JNS', which will be _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit