[pypy-svn] r67444 - in pypy/trunk/pypy/jit/backend: llsupport x86

arigo at codespeak.net arigo at codespeak.net
Thu Sep 3 13:08:34 CEST 2009


Author: arigo
Date: Thu Sep  3 13:08:34 2009
New Revision: 67444

Modified:
   pypy/trunk/pypy/jit/backend/llsupport/llmodel.py
   pypy/trunk/pypy/jit/backend/x86/assembler.py
   pypy/trunk/pypy/jit/backend/x86/runner.py
Log:
Move most of the support for exception out of the x86 backend, into
llsupport.  This is also needed to handle correctly the write barrier
case mentioned in llmodel.py.


Modified: pypy/trunk/pypy/jit/backend/llsupport/llmodel.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/llsupport/llmodel.py	(original)
+++ pypy/trunk/pypy/jit/backend/llsupport/llmodel.py	Thu Sep  3 13:08:34 2009
@@ -1,8 +1,10 @@
 import sys
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rclass, rstr
+from pypy.rpython.lltypesystem.lloperation import llop
+from pypy.rpython.llinterp import LLInterpreter
+from pypy.rpython.annlowlevel import llhelper
 from pypy.rlib.objectmodel import we_are_translated, specialize
 from pypy.jit.metainterp.history import BoxInt, BoxPtr, set_future_values
-from pypy.jit.metainterp.typesystem import llhelper
 from pypy.jit.backend.model import AbstractCPU
 from pypy.jit.backend.llsupport import symbolic
 from pypy.jit.backend.llsupport.symbolic import WORD, unroll_basic_sizes
@@ -19,7 +21,7 @@
 
 
 class AbstractLLCPU(AbstractCPU):
-    ts = llhelper
+    from pypy.jit.metainterp.typesystem import llhelper as ts
 
     def __init__(self, rtyper, stats, translate_support_code=False,
                  gcdescr=None):
@@ -37,6 +39,11 @@
                                                         translate_support_code)
         self._setup_prebuilt_error('ovf', OverflowError)
         self._setup_prebuilt_error('zer', ZeroDivisionError)
+        if translate_support_code:
+            self._setup_exception_handling_translated()
+        else:
+            self._setup_exception_handling_untranslated()
+        self.clear_exception()
 
     def set_class_sizes(self, class_sizes):
         self.class_sizes = class_sizes
@@ -56,6 +63,91 @@
                 llmemory.cast_ptr_to_adr(ll_inst.typeptr))
         setattr(self, '_%s_error_inst' % prefix, ll_inst)
 
+
+    def _setup_exception_handling_untranslated(self):
+        # for running un-translated only, all exceptions occurring in the
+        # llinterpreter are stored in '_exception_emulator', which is then
+        # read back by the machine code reading at the address given by
+        # pos_exception() and pos_exc_value().
+        _exception_emulator = lltype.malloc(rffi.CArray(lltype.Signed), 2,
+                                            zero=True, flavor='raw')
+        self._exception_emulator = _exception_emulator
+
+        def _store_exception(lle):
+            self._last_exception = lle       # keepalive
+            tp_i = rffi.cast(lltype.Signed, lle.args[0])
+            v_i = rffi.cast(lltype.Signed, lle.args[1])
+            _exception_emulator[0] = tp_i
+            _exception_emulator[1] = v_i
+
+        self.debug_ll_interpreter = LLInterpreter(self.rtyper)
+        self.debug_ll_interpreter._store_exception = _store_exception
+
+        def pos_exception():
+            return rffi.cast(lltype.Signed, _exception_emulator)
+
+        def pos_exc_value():
+            return (rffi.cast(lltype.Signed, _exception_emulator) +
+                    rffi.sizeof(lltype.Signed))
+
+        def save_exception():
+            # copy from _exception_emulator to the real attributes on self
+            tp_i = _exception_emulator[0]
+            v_i  = _exception_emulator[1]
+            _exception_emulator[0] = 0
+            _exception_emulator[1] = 0
+            self.saved_exception = tp_i
+            self.saved_exc_value = self._cast_int_to_gcref(v_i)
+
+        self.pos_exception = pos_exception
+        self.pos_exc_value = pos_exc_value
+        self.save_exception = save_exception
+
+
+    def _setup_exception_handling_translated(self):
+
+        def pos_exception():
+            addr = llop.get_exception_addr(llmemory.Address)
+            return llmemory.cast_adr_to_int(addr)
+
+        def pos_exc_value():
+            addr = llop.get_exc_value_addr(llmemory.Address)
+            return llmemory.cast_adr_to_int(addr)
+
+        def save_exception():
+            addr = llop.get_exception_addr(llmemory.Address)
+            exception = rffi.cast(lltype.Signed, addr.address[0])
+            addr.address[0] = llmemory.NULL
+            addr = llop.get_exc_value_addr(llmemory.Address)
+            exc_value = rffi.cast(llmemory.GCREF, addr.address[0])
+            addr.address[0] = llmemory.NULL
+            # from now on, the state is again consistent -- no more RPython
+            # exception is set.  The following code produces a write barrier
+            # in the assignment to self.saved_exc_value, as needed.
+            self.saved_exception = exception
+            self.saved_exc_value = exc_value
+
+        self.pos_exception = pos_exception
+        self.pos_exc_value = pos_exc_value
+        self.save_exception = save_exception
+
+    _SAVE_EXCEPTION_FUNC = lltype.Ptr(lltype.FuncType([], lltype.Void))
+
+    def get_save_exception_int(self):
+        f = llhelper(self._SAVE_EXCEPTION_FUNC, self.save_exception)
+        return rffi.cast(lltype.Signed, f)
+
+    def get_exception(self):
+        return self.saved_exception
+
+    def get_exc_value(self):
+        return self.saved_exc_value
+
+    def clear_exception(self):
+        self.saved_exception = 0
+        self.saved_exc_value = lltype.nullptr(llmemory.GCREF.TO)
+
+
     # ------------------- helpers and descriptions --------------------
 
     @staticmethod

Modified: pypy/trunk/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/x86/assembler.py	(original)
+++ pypy/trunk/pypy/jit/backend/x86/assembler.py	Thu Sep  3 13:08:34 2009
@@ -5,7 +5,6 @@
 from pypy.rpython.lltypesystem import lltype, rffi, ll2ctypes, rstr, llmemory
 from pypy.rpython.lltypesystem.rclass import OBJECT
 from pypy.rpython.lltypesystem.lloperation import llop
-from pypy.annotation import model as annmodel
 from pypy.tool.uid import fixid
 from pypy.jit.backend.logger import Logger
 from pypy.jit.backend.x86.regalloc import (RegAlloc, WORD, REGS, TempBox,
@@ -79,10 +78,6 @@
         assert self.mcstack[self.counter - 1] is mc
         self.counter -= 1
 
-EXCEPTION_STORAGE = lltype.GcStruct('EXCEPTION_STORAGE',
-                                    ('type', lltype.Signed),
-                                    ('value', llmemory.GCREF))
-
 
 class Assembler386(object):
     mc = None
@@ -97,10 +92,6 @@
         self.malloc_array_func_addr = 0
         self.malloc_str_func_addr = 0
         self.malloc_unicode_func_addr = 0
-        # The '_exception_emulator' is only used when non-translated.
-        # The '_exception_copy' is preallocated, so non-moving.
-        self._exception_emulator = lltype.malloc(EXCEPTION_STORAGE, zero=True)
-        self._exception_copy     = lltype.malloc(EXCEPTION_STORAGE, zero=True)
         self.mcstack = MachineCodeStack()
         self.logger = Logger(cpu.ts)
         self.fail_boxes_int = lltype.malloc(lltype.GcArray(lltype.Signed),
@@ -631,50 +622,20 @@
         self.mc.TEST(loc, loc)
         self.implement_guard(addr, op, self.mc.JZ)
 
-    def pos_exception(self):
-        if we_are_translated():
-            addr = llop.get_exception_addr(llmemory.Address)
-            return llmemory.cast_adr_to_int(addr)
-        else:
-            i = rffi.cast(lltype.Signed, self._exception_emulator)
-            return i + 0 # xxx hard-coded offset of 'type' when non-translated
-
-    def pos_exc_value(self):
-        if we_are_translated():
-            addr = llop.get_exc_value_addr(llmemory.Address)
-            return llmemory.cast_adr_to_int(addr)
-        else:
-            i = rffi.cast(lltype.Signed, self._exception_emulator)
-            return i + 4 # xxx hard-coded offset of 'value' when non-translated
-
-    def pos_exception_copy(self):
-        i = rffi.cast(lltype.Signed, self._exception_copy)
-        if we_are_translated():
-            return i + llmemory.offsetof(EXCEPTION_STORAGE, 'type')
-        else:
-            return i + 0 # xxx hard-coded offset of 'type' when non-translated
-
-    def pos_exc_value_copy(self):
-        i = rffi.cast(lltype.Signed, self._exception_copy)
-        if we_are_translated():
-            return i + llmemory.offsetof(EXCEPTION_STORAGE, 'value')
-        else:
-            return i + 4 # xxx hard-coded offset of 'value' when non-translated
-
     def genop_guard_guard_no_exception(self, op, ign_1, addr, locs, ign_2):
-        self.mc.CMP(heap(self.pos_exception()), imm(0))
+        self.mc.CMP(heap(self.cpu.pos_exception()), imm(0))
         self.implement_guard(addr, op, self.mc.JNZ)
 
     def genop_guard_guard_exception(self, op, ign_1, addr, locs, resloc):
         loc = locs[0]
         loc1 = locs[1]
-        self.mc.MOV(loc1, heap(self.pos_exception()))
+        self.mc.MOV(loc1, heap(self.cpu.pos_exception()))
         self.mc.CMP(loc1, loc)
         self.implement_guard(addr, op, self.mc.JNE)
         if resloc is not None:
-            self.mc.MOV(resloc, heap(self.pos_exc_value()))
-        self.mc.MOV(heap(self.pos_exception()), imm(0))
-        self.mc.MOV(heap(self.pos_exc_value()), imm(0))
+            self.mc.MOV(resloc, heap(self.cpu.pos_exc_value()))
+        self.mc.MOV(heap(self.cpu.pos_exception()), imm(0))
+        self.mc.MOV(heap(self.cpu.pos_exc_value()), imm(0))
 
     def genop_guard_guard_no_overflow(self, op, ign_1, addr, locs, resloc):
         self.implement_guard(addr, op, self.mc.JO)
@@ -740,7 +701,9 @@
                                  imm(len(locs) * WORD)),
                                  eax)
         if exc:
-            self.generate_exception_handling(eax)
+            # note that we don't have to save and restore eax, ecx and edx here
+            addr = self.cpu.get_save_exception_int()
+            self.mc.CALL(rel32(addr))
         # don't break the following code sequence!
         mc = self.mc._mc
         self.places_to_patch_framesize.append(mc.tell())
@@ -753,16 +716,6 @@
         mc.POP(ebp)
         mc.RET()
 
-    def generate_exception_handling(self, loc):
-        self.mc.MOV(loc, heap(self.pos_exception()))
-        self.mc.MOV(heap(self.pos_exception_copy()), loc)
-        self.mc.MOV(loc, heap(self.pos_exc_value()))
-        self.mc.MOV(heap(self.pos_exc_value_copy()), loc)
-        # clean up the original exception, we don't want
-        # to enter more rpython code with exc set
-        self.mc.MOV(heap(self.pos_exception()), imm(0))
-        self.mc.MOV(heap(self.pos_exc_value()), imm(0))
-
     @specialize.arg(3)
     def implement_guard(self, addr, guard_op, emit_jump):
         emit_jump(rel32(addr))

Modified: pypy/trunk/pypy/jit/backend/x86/runner.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/x86/runner.py	(original)
+++ pypy/trunk/pypy/jit/backend/x86/runner.py	Thu Sep  3 13:08:34 2009
@@ -21,16 +21,6 @@
                  gcdescr=None):
         AbstractLLCPU.__init__(self, rtyper, stats, translate_support_code,
                                gcdescr)
-        if not translate_support_code:
-            self.current_interpreter = LLInterpreter(self.rtyper)
-
-            def _store_exception(lle):
-                tp_i = self.cast_ptr_to_int(lle.args[0])
-                v_i = lltype.cast_opaque_ptr(llmemory.GCREF, lle.args[1])
-                self.assembler._exception_emulator.type = tp_i
-                self.assembler._exception_emulator.value = v_i
-            
-            self.current_interpreter._store_exception = _store_exception
         TP = lltype.GcArray(llmemory.GCREF)
         self._bootstrap_cache = {}
         self._guard_list = []
@@ -45,16 +35,6 @@
     def setup_once(self):
         pass
 
-    def get_exception(self):
-        return self.assembler._exception_copy.type
-
-    def get_exc_value(self):
-        return self.assembler._exception_copy.value
-
-    def clear_exception(self):
-        self.assembler._exception_copy.type = 0
-        self.assembler._exception_copy.value= lltype.nullptr(llmemory.GCREF.TO)
-
     def compile_operations(self, tree, bridge=None):
         old_loop = tree._x86_compiled
         if old_loop:
@@ -116,7 +96,7 @@
         prev_interpreter = None
         if not self.translate_support_code:
             prev_interpreter = LLInterpreter.current_interpreter
-            LLInterpreter.current_interpreter = self.current_interpreter
+            LLInterpreter.current_interpreter = self.debug_ll_interpreter
         res = 0
         try:
             self.caught_exception = None



More information about the Pypy-commit mailing list