[pypy-commit] pypy r15-for-exception: Fix the x86 backend to not touch r15 for normal usage, but handle

arigo noreply at buildbot.pypy.org
Sat Jul 9 12:07:27 CEST 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: r15-for-exception
Changeset: r45434:83b783be61f3
Date: 2011-07-09 12:16 +0200
http://bitbucket.org/pypy/pypy/changeset/83b783be61f3/

Log:	Fix the x86 backend to not touch r15 for normal usage, but handle it
	as the exception marker.

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
@@ -116,9 +116,12 @@
         self.pos_exc_value = pos_exc_value
         self.save_exception = save_exception
         self.insert_stack_check = lambda: (0, 0, 0)
+        self.special_register = None
 
 
     def _setup_exception_handling_translated(self):
+        from pypy.rlib import register
+        from pypy.rlib.register import register_number
 
         def pos_exception():
             addr = llop.get_exception_addr(llmemory.Address)
@@ -129,6 +132,8 @@
             return heaptracker.adr2int(addr)
 
         def save_exception():
+            if register_number is not None:
+                register.store_into_reg(register.nonnull)
             addr = llop.get_exception_addr(llmemory.Address)
             addr.address[0] = llmemory.NULL
             addr = llop.get_exc_value_addr(llmemory.Address)
@@ -153,6 +158,9 @@
         self.pos_exc_value = pos_exc_value
         self.save_exception = save_exception
         self.insert_stack_check = insert_stack_check
+        self.special_register = register_number
+        self.special_register_nonnull = llmemory.cast_adr_to_int(
+                                                          register.nonnull)
 
     def _setup_on_leave_jitted_untranslated(self):
         # assume we don't need a backend leave in this case
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
@@ -6,6 +6,8 @@
 # during a malloc that needs to go via its slow path.
 
 import sys
+from pypy.rlib.register import register_number as special_register
+
 if sys.maxint == (2**31 - 1):
     WORD = 4
     # ebp + ebx + esi + edi + 4 extra words + force_index = 9 words
@@ -14,16 +16,23 @@
     MY_COPY_OF_REGS = -7*WORD
     IS_X86_32 = True
     IS_X86_64 = False
+    assert special_register is None
 else:
     WORD = 8
-    # rbp + rbx + r12 + r13 + r14 + r15 + 11 extra words + force_index = 18
+    # rbp + rbx + r12 + r13 + r14 + r15? + 11 extra words + force_index = 18
     FRAME_FIXED_SIZE = 18
     FORCE_INDEX_OFS = -17*WORD
     MY_COPY_OF_REGS = -16*WORD
     IS_X86_32 = False
     IS_X86_64 = True
+    if special_register is not None:
+        assert special_register == 15
+        # remove r15 from the saved registers and from the extra words
+        FRAME_FIXED_SIZE = 16
+        FORCE_INDEX_OFS = -15*WORD
+        MY_COPY_OF_REGS = -14*WORD
 
 # The extra space has room for almost all registers, apart from eax and edx
 # which are used in the malloc itself.  They are:
 #   ecx, ebx, esi, edi               [32 and 64 bits]
-#   r8, r9, r10, r12, r13, r14, r15    [64 bits only]
+#   r8, r9, r10, r12, r13, r14, r15?   [64 bits only]
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
@@ -263,9 +263,14 @@
         # esp is now aligned to a multiple of 16 again
         mc.CALL(imm(slowpathaddr))
         #
-        mc.MOV(eax, heap(self.cpu.pos_exception()))
-        mc.TEST_rr(eax.value, eax.value)
-        mc.J_il8(rx86.Conditions['NZ'], 0)
+        if self.cpu.special_register is None:
+            mc.MOV(eax, heap(self.cpu.pos_exception()))
+            mc.TEST_rr(eax.value, eax.value)
+            mc.J_il8(rx86.Conditions['NZ'], 0)
+        else:
+            rnum = self.cpu.special_register
+            mc.TEST_rr(rnum, rnum)
+            mc.J_il8(rx86.Conditions['Z'], 0)
         jnz_location = mc.get_relative_pos()
         #
         if IS_X86_32:
@@ -286,8 +291,7 @@
         mc.overwrite(jnz_location-1, chr(offset))
         # clear the exception from the global position
         mc.MOV(eax, heap(self.cpu.pos_exc_value()))
-        mc.MOV(heap(self.cpu.pos_exception()), imm0)
-        mc.MOV(heap(self.cpu.pos_exc_value()), imm0)
+        self.clear_current_exception(mc)
         # save the current exception instance into fail_boxes_ptr[0]
         adr = self.fail_boxes_ptr.get_addr_for_num(0)
         mc.MOV(heap(adr), eax)
@@ -308,6 +312,13 @@
         rawstart = mc.materialize(self.cpu.asmmemmgr, [])
         self.stack_check_slowpath = rawstart
 
+    def clear_current_exception(self, mc):
+        if self.cpu.special_register is not None:
+            mc.MOV_ri(self.cpu.special_register,
+                      self.cpu.special_register_nonnull)
+        mc.MOV(heap(self.cpu.pos_exception()), imm0)
+        mc.MOV(heap(self.cpu.pos_exc_value()), imm0)
+
     @staticmethod
     def _release_gil_asmgcc(css):
         # similar to trackgcroot.py:pypy_asm_stackwalk, first part
@@ -1563,8 +1574,13 @@
 
     def genop_guard_guard_no_exception(self, ign_1, guard_op, guard_token,
                                        locs, ign_2):
-        self.mc.CMP(heap(self.cpu.pos_exception()), imm0)
-        self.implement_guard(guard_token, 'NZ')
+        if self.cpu.special_register is None:
+            self.mc.CMP(heap(self.cpu.pos_exception()), imm0)
+            self.implement_guard(guard_token, 'NZ')
+        else:
+            rnum = self.cpu.special_register
+            self.mc.TEST_rr(rnum, rnum)
+            self.implement_guard(guard_token, 'Z')
 
     def genop_guard_guard_not_invalidated(self, ign_1, guard_op, guard_token,
                                      locs, ign_2):
@@ -1575,14 +1591,11 @@
     def genop_guard_guard_exception(self, ign_1, guard_op, guard_token,
                                     locs, resloc):
         loc = locs[0]
-        loc1 = locs[1]
-        self.mc.MOV(loc1, heap(self.cpu.pos_exception()))
-        self.mc.CMP(loc1, loc)
+        self.mc.CMP(heap(self.cpu.pos_exception()), loc)
         self.implement_guard(guard_token, 'NE')
         if resloc is not None:
             self.mc.MOV(resloc, heap(self.cpu.pos_exc_value()))
-        self.mc.MOV(heap(self.cpu.pos_exception()), imm0)
-        self.mc.MOV(heap(self.cpu.pos_exc_value()), imm0)
+        self.clear_current_exception(self.mc)
 
     def _gen_guard_overflow(self, guard_op, guard_token):
         guard_opnum = guard_op.getopnum()
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
@@ -19,7 +19,7 @@
 from pypy.jit.backend.llsupport.descr import BaseCallDescr, BaseSizeDescr
 from pypy.jit.backend.llsupport.regalloc import FrameManager, RegisterManager,\
      TempBox
-from pypy.jit.backend.x86.arch import WORD, FRAME_FIXED_SIZE
+from pypy.jit.backend.x86.arch import WORD, FRAME_FIXED_SIZE, special_register
 from pypy.jit.backend.x86.arch import IS_X86_32, IS_X86_64, MY_COPY_OF_REGS
 from pypy.rlib.rarithmetic import r_longlong, r_uint
 
@@ -56,8 +56,11 @@
             not_implemented("convert_to_imm: got a %s" % c)
 
 class X86_64_RegisterManager(X86RegisterManager):
-    # r11 omitted because it's used as scratch
-    all_regs = [eax, ecx, edx, ebx, esi, edi, r8, r9, r10, r12, r13, r14, r15]
+    # r11 omitted because it's used as scratch; r15 is omitted if used
+    # as a special register
+    all_regs = [eax, ecx, edx, ebx, esi, edi, r8, r9, r10, r12, r13, r14]
+    if special_register is None:
+        all_regs.append(r15)
     no_lower_byte_regs = []
     save_around_call_regs = [eax, ecx, edx, esi, edi, r8, r9, r10]
 
@@ -79,8 +82,9 @@
         r12: MY_COPY_OF_REGS + 7 * WORD,
         r13: MY_COPY_OF_REGS + 8 * WORD,
         r14: MY_COPY_OF_REGS + 9 * WORD,
-        r15: MY_COPY_OF_REGS + 10 * WORD,
     }
+    if special_register is None:
+        REGLOC_TO_COPY_AREA_OFS[r15] = MY_COPY_OF_REGS + 10 * WORD
 
 class X86XMMRegisterManager(RegisterManager):
 
@@ -518,17 +522,13 @@
 
     def consider_guard_exception(self, op):
         loc = self.rm.make_sure_var_in_reg(op.getarg(0))
-        box = TempBox()
-        args = op.getarglist()
-        loc1 = self.rm.force_allocate_reg(box, args)
         if op.result in self.longevity:
             # this means, is it ever used
-            resloc = self.rm.force_allocate_reg(op.result, args + [box])
+            resloc = self.rm.force_allocate_reg(op.result)
         else:
             resloc = None
-        self.perform_guard(op, [loc, loc1], resloc)
+        self.perform_guard(op, [loc], resloc)
         self.rm.possibly_free_vars_for_op(op)
-        self.rm.possibly_free_var(box)
 
     consider_guard_no_overflow = consider_guard_no_exception
     consider_guard_overflow    = consider_guard_no_exception
diff --git a/pypy/jit/backend/x86/runner.py b/pypy/jit/backend/x86/runner.py
--- a/pypy/jit/backend/x86/runner.py
+++ b/pypy/jit/backend/x86/runner.py
@@ -5,7 +5,7 @@
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.jit.metainterp import history, compile
 from pypy.jit.backend.x86.assembler import Assembler386
-from pypy.jit.backend.x86.arch import FORCE_INDEX_OFS
+from pypy.jit.backend.x86.arch import FORCE_INDEX_OFS, special_register
 from pypy.jit.backend.x86.profagent import ProfileAgent
 from pypy.jit.backend.llsupport.llmodel import AbstractLLCPU
 from pypy.jit.backend.x86 import regloc
@@ -205,7 +205,9 @@
     backend_name = 'x86_64'
     WORD = 8
     NUM_REGS = 16
-    CALLEE_SAVE_REGISTERS = [regloc.ebx, regloc.r12, regloc.r13, regloc.r14, regloc.r15]
+    CALLEE_SAVE_REGISTERS = [regloc.ebx, regloc.r12, regloc.r13, regloc.r14]
+    if special_register is None:
+        CALLEE_SAVE_REGISTERS.append(regloc.r15)
 
     def __init__(self, *args, **kwargs):
         assert sys.maxint == (2**63 - 1)


More information about the pypy-commit mailing list