[pypy-commit] pypy jitframe-on-heap: work on stack check failure, failing to call it so far

fijal noreply at buildbot.pypy.org
Tue Jan 15 12:24:19 CET 2013


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: jitframe-on-heap
Changeset: r60081:2a740e45803a
Date: 2013-01-15 13:23 +0200
http://bitbucket.org/pypy/pypy/changeset/2a740e45803a/

Log:	work on stack check failure, failing to call it so far

diff --git a/pypy/jit/backend/llsupport/llmodel.py b/pypy/jit/backend/llsupport/llmodel.py
--- a/pypy/jit/backend/llsupport/llmodel.py
+++ b/pypy/jit/backend/llsupport/llmodel.py
@@ -45,11 +45,24 @@
         else:
             self._setup_exception_handling_untranslated()
         self.asmmemmgr = AsmMemoryManager()
+        self._setup_frame_realloc()
         self.setup()
 
     def setup(self):
         pass
 
+    def _setup_frame_realloc(self):
+        FUNC_TP = lltype.Ptr(lltype.FuncType([llmemory.GCREF],
+                                             llmemory.GCREF))
+
+        def realloc_frame(frame):
+            frame = lltype.cast_opaque_ptr(jitframe.JITFRAME, frame)
+            import pdb
+            pdb.set_trace()
+            return frame
+        
+        f = llhelper(FUNC_TP, realloc_frame)
+        self.realloc_frame = heaptracker.adr2int(llmemory.cast_ptr_to_adr(f))
 
     def _setup_exception_handling_untranslated(self):
         # for running un-translated only, all exceptions occurring in the
diff --git a/pypy/jit/backend/test/runner_test.py b/pypy/jit/backend/test/runner_test.py
--- a/pypy/jit/backend/test/runner_test.py
+++ b/pypy/jit/backend/test/runner_test.py
@@ -3766,7 +3766,8 @@
                                     EffectInfo.MOST_GENERAL)
 
         def func2(a, b, c, d, e, f, g, h, i, j, k, l):
-            pass
+            import pdb
+            pdb.set_trace()
 
         FUNC2 = self.FuncType([lltype.Signed] * 12, lltype.Void)
         FPTR2 = self.Ptr(FUNC2)
diff --git a/pypy/jit/backend/x86/arch.py b/pypy/jit/backend/x86/arch.py
--- a/pypy/jit/backend/x86/arch.py
+++ b/pypy/jit/backend/x86/arch.py
@@ -51,7 +51,7 @@
     JITFRAME_FIXED_SIZE = 29 # 13 GPR + 16 XMM
                              # reg, we don't save it
 else:
-    # rbp + rbx + r12 + r13 + r14 + r15 + 12 extra words + return address = 18
+    # rbp + rbx + r12 + r13 + r14 + r15 + 12 extra words + return address = 19
     FRAME_FIXED_SIZE = 19
     PASS_ON_MY_FRAME = 12
     JITFRAME_FIXED_SIZE = 29 # 13 GPR + 16 XMM
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
@@ -94,6 +94,7 @@
         self._build_failure_recovery(True)
         self._build_wb_slowpath(False)
         self._build_wb_slowpath(True)
+        self._build_stack_check_failure()
         if self.cpu.supports_floats:
             self._build_failure_recovery(False, withfloats=True)
             self._build_failure_recovery(True, withfloats=True)
@@ -167,6 +168,19 @@
         self.float_const_neg_addr = float_constants
         self.float_const_abs_addr = float_constants + 16
 
+    def _build_stack_check_failure(self):
+        mc = codebuf.MachineCodeBlockWrapper()
+        base_ofs = self.cpu.get_baseofs_of_frame_field()
+        self._push_all_regs_to_frame(mc, self.cpu.supports_floats)
+        assert not IS_X86_32
+        # push first arg
+        mc.LEA_rb(edi.value, -base_ofs)
+        mc.CALL(imm(self.cpu.realloc_frame))
+        mc.LEA_rm(ebp.value, (eax.value, base_ofs))
+        self._pop_all_regs_from_frame(mc, self.cpu.supports_floats)
+        mc.RET()
+        self._stack_check_failure = mc.materialize(self.cpu.asmmemmgr, [])
+
     def _build_malloc_slowpath(self):
         # With asmgcc, we need two helpers, so that we can write two CALL
         # instructions in assembler, with a mark_gc_roots in between.
@@ -571,7 +585,7 @@
         operations = regalloc.prepare_bridge(inputargs, arglocs,
                                              operations,
                                              self.current_clt.allgcrefs)
-        self._check_frame_depth()
+        stack_check_patch_ofs = self._check_frame_depth()
         frame_depth = self._assemble(regalloc, operations)
         codeendpos = self.mc.get_relative_pos()
         self.write_pending_failure_recoveries()
@@ -589,9 +603,10 @@
         # patch the jump from original guard
         self.patch_jump_for_descr(faildescr, rawstart)
         ops_offset = self.mc.ops_offset
-        self.fixup_target_tokens(rawstart)
         frame_depth = max(self.current_clt.frame_info.jfi_frame_depth,
                           frame_depth + JITFRAME_FIXED_SIZE)
+        self._patch_stackadjust(stack_check_patch_ofs + rawstart, frame_depth)
+        self.fixup_target_tokens(rawstart)
         self.current_clt.frame_info.jfi_frame_depth = frame_depth
         self.teardown()
         # oprofile support
@@ -652,8 +667,21 @@
                 mc.copy_to_raw_memory(rawstart + pos_after_jz - 4)
 
     def _check_frame_depth(self):
-        pass
+        descrs = self.cpu.gc_ll_descr.getframedescrs(self.cpu)
+        ofs = self.cpu.unpack_fielddescr(descrs.arraydescr.lendescr)
+        base_ofs = self.cpu.get_baseofs_of_frame_field()
+        self.mc.CMP_bi(ofs - base_ofs, 0xffffff)
+        stack_check_cmp_ofs = self.mc.get_relative_pos() - 4
+        assert not IS_X86_32
+        self.mc.J_il8(rx86.Conditions['G'], 9)
+        self.mc.CALL(imm(self._stack_check_failure))
+        return stack_check_cmp_ofs
 
+    def _patch_stackadjust(self, adr, allocated_depth):
+        mc = codebuf.MachineCodeBlockWrapper()
+        mc.writeimm32(allocated_depth)
+        mc.copy_to_raw_memory(adr)
+        
     def get_asmmemmgr_blocks(self, looptoken):
         clt = looptoken.compiled_loop_token
         if clt.asmmemmgr_blocks is None:
@@ -1858,13 +1886,31 @@
     def setup_failure_recovery(self):
         self.failure_recovery_code = [0, 0, 0, 0]
 
+    def _push_all_regs_to_frame(self, mc, withfloats):
+        # Push all general purpose registers
+        for i, gpr in enumerate(gpr_reg_mgr_cls.all_regs):
+            mc.MOV_br(i * WORD, gpr.value)
+        if withfloats:
+            # Push all XMM regs
+            ofs = len(gpr_reg_mgr_cls.all_regs)
+            for i in range(self.cpu.NUM_REGS):
+                mc.MOVSD_bx((ofs + i) * WORD, i)
+
+    def _pop_all_regs_from_frame(self, mc, withfloats):
+        # Pop all general purpose registers
+        for i, gpr in enumerate(gpr_reg_mgr_cls.all_regs):
+            mc.MOV_rb(gpr.value, i * WORD)
+        if withfloats:
+            # Pop all XMM regs
+            ofs = len(gpr_reg_mgr_cls.all_regs)
+            for i in range(self.cpu.NUM_REGS):
+                mc.MOVSD_xb(i, (ofs + i) * WORD)
+
     def _build_failure_recovery(self, exc, withfloats=False):
         mc = codebuf.MachineCodeBlockWrapper()
         self.mc = mc
 
-        # Push all general purpose registers
-        for i, gpr in enumerate(gpr_reg_mgr_cls.all_regs):
-            mc.MOV_br(i * WORD, gpr.value)
+        self._push_all_regs_to_frame(mc, withfloats)
 
         if exc:
             # We might have an exception pending.  Load it into ebx
@@ -1872,13 +1918,6 @@
             mc.MOV(ebx, heap(self.cpu.pos_exc_value()))
             mc.MOV(heap(self.cpu.pos_exception()), imm0)
             mc.MOV(heap(self.cpu.pos_exc_value()), imm0)
-
-        if withfloats:
-            ofs = len(gpr_reg_mgr_cls.all_regs)
-            for i in range(self.cpu.NUM_REGS):
-                mc.MOVSD_bx((ofs + i) * WORD, i)
-
-        if exc:
             # save ebx into 'jf_guard_exc'
             offset = self.cpu.get_ofs_of_frame_field('jf_guard_exc')
             mc.MOV_br(offset, ebx.value)
@@ -2007,12 +2046,14 @@
         # first, close the stack in the sense of the asmgcc GC root tracker
         gcrootmap = self.cpu.gc_ll_descr.gcrootmap
         if gcrootmap:
+            xxx
             self.call_release_gil(gcrootmap, arglocs)
         # do the call
         fail_index = self._store_force_index(guard_op)
         self._genop_call(op, arglocs, result_loc, fail_index)
         # then reopen the stack
         if gcrootmap:
+            xxx
             self.call_reacquire_gil(gcrootmap, result_loc)
         # finally, the guard_not_forced
         self._emit_guard_not_forced(guard_token)
diff --git a/pypy/jit/backend/x86/regalloc.py b/pypy/jit/backend/x86/regalloc.py
--- a/pypy/jit/backend/x86/regalloc.py
+++ b/pypy/jit/backend/x86/regalloc.py
@@ -212,14 +212,10 @@
         self.min_bytes_before_label = max(self.min_bytes_before_label,
                                           at_least_position)
 
-    def needed_extra_stack_locations(self, n):
-        # call *after* you needed extra stack locations: (%esp), (%esp+4)...
-        min_frame_depth = self.fm.get_frame_depth() + n
+    def get_final_frame_depth(self):
+        min_frame_depth = self.fm.get_frame_depth()
         if min_frame_depth > self.min_frame_depth:
             self.min_frame_depth = min_frame_depth
-
-    def get_final_frame_depth(self):
-        self.needed_extra_stack_locations(0)  # update min_frame_depth
         return self.min_frame_depth
 
     def _set_initial_bindings(self, inputargs):
diff --git a/pypy/jit/backend/x86/test/test_runner.py b/pypy/jit/backend/x86/test/test_runner.py
--- a/pypy/jit/backend/x86/test/test_runner.py
+++ b/pypy/jit/backend/x86/test/test_runner.py
@@ -34,7 +34,7 @@
     # ====> ../../test/runner_test.py
 
     add_loop_instructions = ['mov', 'add', 'test', 'je', 'jmp']
-    bridge_loop_instructions = ['mov', 'jmp']
+    bridge_loop_instructions = ['cmp', 'jg', 'mov', 'call', 'mov', 'jmp']
 
     def setup_method(self, meth):
         self.cpu = CPU(rtyper=None, stats=FakeStats())


More information about the pypy-commit mailing list