Author: Remi Meier <[email protected]>
Branch: stmgc-c4
Changeset: r67492:a58510da97be
Date: 2013-10-21 20:19 +0200
http://bitbucket.org/pypy/pypy/changeset/a58510da97be/

Log:    move the call to stm_transaction_break() into separately piece (not
        inlined in trace anymore)

diff --git a/rpython/jit/backend/llsupport/assembler.py 
b/rpython/jit/backend/llsupport/assembler.py
--- a/rpython/jit/backend/llsupport/assembler.py
+++ b/rpython/jit/backend/llsupport/assembler.py
@@ -95,6 +95,7 @@
         if gc_ll_descr.stm:
             self._build_ptr_eq_slowpath()
             self._build_stm_longjmp_callback()
+            self.stm_transaction_break_path = 
self._build_stm_transaction_break_path()
         else:
             self.ptr_eq_slowpath = None
         # only one of those
diff --git a/rpython/jit/backend/llsupport/rewrite.py 
b/rpython/jit/backend/llsupport/rewrite.py
--- a/rpython/jit/backend/llsupport/rewrite.py
+++ b/rpython/jit/backend/llsupport/rewrite.py
@@ -161,7 +161,7 @@
     def gen_malloc_frame(self, frame_info, frame):
         size_box = history.BoxInt()
         descrs = self.gc_ll_descr.getframedescrs(self.cpu)
-        if self.gc_ll_descr.kind == 'boehm':
+        if self.gc_ll_descr.kind == 'boehm' or self.gc_ll_descr.stm:
             op0 = ResOperation(rop.GETFIELD_GC, [history.ConstInt(frame_info)],
                                size_box,
                                descr=descrs.jfi_frame_depth)
@@ -171,6 +171,7 @@
             self.handle_new_array(descrs.arraydescr, op1)
         else:
             # we read size in bytes here, not the length
+            # jfi_frame_size not set in STM!
             op0 = ResOperation(rop.GETFIELD_GC, [history.ConstInt(frame_info)],
                                size_box,
                                descr=descrs.jfi_frame_size)
diff --git a/rpython/jit/backend/x86/assembler.py 
b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -188,6 +188,50 @@
         mc.RET()
         return mc.materialize(self.cpu.asmmemmgr, [])
 
+    def _build_stm_transaction_break_path(self):
+        """ While arriving on slowpath, we have a gcpattern on stack 0.
+        This function must preserve all registers
+        """
+        mc = codebuf.MachineCodeBlockWrapper()
+        # store the gc pattern
+        ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap')
+        mc.MOV_rs(ecx.value, WORD)
+        mc.MOV_br(ofs, ecx.value)
+        #
+        # align on 16b boundary (there is a retaddr on the stack)
+        mc.SUB_ri(esp.value, 16 - WORD)
+        #
+        # call stm_transaction_break() with the address of the
+        # STM_RESUME_BUF and the custom longjmp function
+        # (rsp + FRAME_FIXED_SIZE + RET_ADDR + ALIGNMENT)
+        mc.LEA_rs(edi.value, (FRAME_FIXED_SIZE+2) * WORD)
+        mc.MOV(esi, imm(self.stm_longjmp_callback_addr))
+        fn = stmtlocal.stm_transaction_break_fn
+        mc.CALL(imm(self.cpu.cast_ptr_to_int(fn)))
+        #
+        mc.ADD_ri(esp.value, 16 - WORD)
+        #
+        self._reload_frame_if_necessary(mc, align_stack=True)
+        # clear the gc pattern
+        mc.MOV_bi(ofs, 0)
+        #
+        # Fill the stm resume buffer.  Don't do it before the call!
+        # The previous transaction may still be aborted during the call
+        # above, so we need the old content of the buffer!
+        # The buffer contains the address of the resume point which
+        # is the RET_ADDR of this called piece of code. This will be
+        # put at offset 0 of the buffer, at offset WORD, there is a
+        # copy of the current shadowstack pointer.
+        mc.POP_r(eax.value) # get ret addr
+        self._load_shadowstack_top_in_ebx(mc, self.cpu.gc_ll_descr.gcrootmap)
+        mc.MOV_sr((FRAME_FIXED_SIZE + 1) * WORD, ebx.value)
+        mc.MOV_sr((FRAME_FIXED_SIZE + 0) * WORD, eax.value)
+        mc.JMP_r(eax.value)
+        #
+        rawstart = mc.materialize(self.cpu.asmmemmgr, [])
+        return rawstart
+
+    
     def _build_malloc_slowpath(self, kind):
         """ While arriving on slowpath, we have a gcpattern on stack 0.
         The arguments are passed in eax and edi, as follows:
@@ -3061,54 +3105,46 @@
         mc.MOV(dest_addr, X86_64_SCRATCH_REG)
 
         
-    def genop_stm_transaction_break(self, op, arglocs, result_loc):
+    def stm_transaction_break(self, check_type, gcmap):
         assert self.cpu.gc_ll_descr.stm
         if not we_are_translated():
             return     # tests only
 
-        # argument is check_type, 0 being a check for inevitable,
-        # 1 being a check with stm_should_break_transaction()
-        assert isinstance(arglocs[0], ImmedLoc)
-        check_type = arglocs[0].getint()
-        
+        # check_type: 0 do a check for inevitable before
+        # doing a check of stm_should_break_transaction().
+        # else, just do stm_should_break_transaction()
         mc = self.mc
         if check_type == 0:
-            # if stm_active == 2
+            # only check stm_should_break_transaction()
+            # if we are inevitable:
             nc = self._get_stm_tl(rstm.get_active_adr())
             self._tl_segment_if_stm(mc)
-            mc.CMP_ji(nc, 2)
-        elif check_type == 1:
-            # "if stm_should_break_transaction()"
-            fn = stmtlocal.stm_should_break_transaction_fn
-            mc.CALL(imm(self.cpu.cast_ptr_to_int(fn)))
-            mc.TEST8(eax.lowest8bits(), eax.lowest8bits())
+            mc.CMP_ji(nc, 1)
+            mc.J_il(rx86.Conditions['Z'], 0xfffff)    # patched later
+            jz_location = mc.get_relative_pos()
+        else:
+            jz_location = 0
+        
+        # if stm_should_break_transaction()
+        fn = stmtlocal.stm_should_break_transaction_fn
+        mc.CALL(imm(self.cpu.cast_ptr_to_int(fn)))
+        mc.TEST8(eax.lowest8bits(), eax.lowest8bits())
         mc.J_il(rx86.Conditions['Z'], 0xfffff)    # patched later
-        jz_location = mc.get_relative_pos()
+        jz_location2 = mc.get_relative_pos()
         #
         # call stm_transaction_break() with the address of the
         # STM_RESUME_BUF and the custom longjmp function
-        mc.LEA_rs(edi.value, FRAME_FIXED_SIZE * WORD)
-        fn = stmtlocal.stm_transaction_break_fn
-        self.simple_call(imm(self.cpu.cast_ptr_to_int(fn)),
-                         [edi, imm(self.stm_longjmp_callback_addr)],
-                         None)
-        #
-        # Fill the stm resume buffer.  Don't do it before the call!
-        # The previous transaction may still be aborted during the call
-        # above, so we need the old content of the buffer!
-        # The buffer contains the address of the resume point in this
-        # piece of code (at "HERE") at offset 0, and at offset WORD it
-        # contains a copy of the current shadowstack pointer.
-        self._load_shadowstack_top_in_ebx(mc, self.cpu.gc_ll_descr.gcrootmap)
-        mc.MOV_sr((FRAME_FIXED_SIZE + 1) * WORD, ebx.value)
-        mc.CALL_l(0)
-        # "HERE"
-        mc.POP_r(eax.value)
-        mc.MOV_sr((FRAME_FIXED_SIZE + 0) * WORD, eax.value)
+        self.push_gcmap(mc, gcmap, mov=True)
+        fn = self.stm_transaction_break_path
+        mc.CALL(imm(fn))
         #
         # patch the JZ above
-        offset = mc.get_relative_pos() - jz_location
-        mc.overwrite32(jz_location-4, offset)
+        if jz_location:
+            offset = mc.get_relative_pos() - jz_location
+            mc.overwrite32(jz_location-4, offset)
+        offset = mc.get_relative_pos() - jz_location2
+        mc.overwrite32(jz_location2-4, offset)
+
 
 
 genop_discard_list = [Assembler386.not_implemented_op_discard] * rop._LAST
diff --git a/rpython/jit/backend/x86/regalloc.py 
b/rpython/jit/backend/x86/regalloc.py
--- a/rpython/jit/backend/x86/regalloc.py
+++ b/rpython/jit/backend/x86/regalloc.py
@@ -1284,13 +1284,18 @@
         self.perform_discard(op, [base_loc, ofs_loc, size_loc])
         
     def consider_stm_transaction_break(self, op):
+        check_type_box = op.getarg(0)
+        assert isinstance(check_type_box, ConstInt)
+        check_type = check_type_box.getint()
+        #
         # XXX use the extra 3 words in the stm resume buffer to save
         # up to 3 registers, too.  For now we just flush them all.
-        check_type = op.getarg(0)
-        assert isinstance(check_type, ConstInt)
         self.xrm.before_call(save_all_regs=1)
         self.rm.before_call(save_all_regs=1)
-        self.perform(op, [self.rm.convert_to_imm(check_type)], None)
+        gcmap = self.get_gcmap() # allocate the gcmap *before*
+        #
+        self.assembler.stm_transaction_break(check_type, gcmap)
+        
 
     def consider_jump(self, op):
         assembler = self.assembler
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to