Armin Rigo avatar Armin Rigo committed eec649f

More work on exceptions. Propagate MemoryError.

Comments (0)

Files changed (4)

pypy/jit/backend/llsupport/llmodel.py

 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.rpython.annlowlevel import llhelper, cast_instance_to_base_ptr
 from pypy.rlib.objectmodel import we_are_translated, specialize
 from pypy.jit.metainterp import history
 from pypy.jit.codewriter import heaptracker, longlong
             self._setup_exception_handling_untranslated()
         self.asmmemmgr = AsmMemoryManager()
         self.setup()
-        if translate_support_code:
-            self._setup_on_leave_jitted_translated()
-        else:
-            self._setup_on_leave_jitted_untranslated()
 
     def setup(self):
         pass
             return (rffi.cast(lltype.Signed, _exception_emulator) +
                     rffi.sizeof(lltype.Signed))
 
-        def save_exception():
-            # copy from _exception_emulator to the real attributes on self
-            v_i = _exception_emulator[1]
+        self._memoryerror_emulated = rffi.cast(llmemory.GCREF, -123)
+        self.deadframe_memoryerror = lltype.malloc(jitframe.DEADFRAME, 0)
+        self.deadframe_memoryerror.jf_guard_exc = self._memoryerror_emulated
+
+        def propagate_exception():
+            exc = _exception_emulator[1]
             _exception_emulator[0] = 0
             _exception_emulator[1] = 0
-            self.saved_exc_value = rffi.cast(llmemory.GCREF, v_i)
-
-        def save_exception_memoryerr():
-            save_exception()
-            if not self.saved_exc_value:
-                self.saved_exc_value = "memoryerror!"    # for tests
+            if not exc:
+                deadframe = self.deadframe_memoryerror
+                assert self.propagate_exception_v >= 0
+                faildescr = self.get_fail_descr_from_number(
+                    self.propagate_exception_v)
+                if not deadframe.jf_descr:
+                    deadframe.jf_descr = faildescr.hide(self)
+                else:
+                    assert deadframe.jf_descr == faildescr.hide(self)
+            else:
+                deadframe = lltype.malloc(jitframe.DEADFRAME, 0)
+                deadframe.jf_guard_exc = rffi.cast(llmemory.GCREF, exc)
+                deadframe.jf_descr = self.get_fail_descr_from_number(
+                    self.propagate_exception_v)
+            return lltype.cast_opaque_ptr(llmemory.GCREF, deadframe)
 
         self.pos_exception = pos_exception
         self.pos_exc_value = pos_exc_value
-        self.save_exception = save_exception
-        self.save_exception_memoryerr = save_exception_memoryerr
         self.insert_stack_check = lambda: (0, 0, 0)
-
+        self._propagate_exception = propagate_exception
 
     def _setup_exception_handling_translated(self):
         xxxxxxxxxxx
         self.save_exception_memoryerr = save_exception_memoryerr
         self.insert_stack_check = insert_stack_check
 
-    def _setup_on_leave_jitted_untranslated(self):
-        # assume we don't need a backend leave in this case
-        self.on_leave_jitted_save_exc = self.save_exception
-        self.on_leave_jitted_memoryerr = self.save_exception_memoryerr
-        self.on_leave_jitted_noexc = lambda : None
+    PROPAGATE_EXCEPTION = lltype.Ptr(lltype.FuncType([], llmemory.GCREF))
 
-    def _setup_on_leave_jitted_translated(self):
-        on_leave_jitted_hook = self.get_on_leave_jitted_hook()
-        save_exception = self.save_exception
-        save_exception_memoryerr = self.save_exception_memoryerr
-
-        def on_leave_jitted_noexc():
-            on_leave_jitted_hook()
-
-        def on_leave_jitted_save_exc():
-            save_exception()
-            on_leave_jitted_hook()
-
-        def on_leave_jitted_memoryerr():
-            save_exception_memoryerr()
-            on_leave_jitted_hook()
-
-        self.on_leave_jitted_noexc = on_leave_jitted_noexc
-        self.on_leave_jitted_save_exc = on_leave_jitted_save_exc
-        self.on_leave_jitted_memoryerr = on_leave_jitted_memoryerr
-
-    def get_on_leave_jitted_hook(self):
-        # this function needs to be overridden for things to work with
-        # our framework GCs
-        translation_time_error
-
-    _ON_JIT_LEAVE_FUNC = lltype.Ptr(lltype.FuncType([], lltype.Void))
-
-    def get_on_leave_jitted_int(self, save_exception,
-                                default_to_memoryerror=False):
-        if default_to_memoryerror:
-            f = llhelper(self._ON_JIT_LEAVE_FUNC, self.on_leave_jitted_memoryerr)
-        elif save_exception:
-            f = llhelper(self._ON_JIT_LEAVE_FUNC, self.on_leave_jitted_save_exc)
-        else:
-            f = llhelper(self._ON_JIT_LEAVE_FUNC, self.on_leave_jitted_noexc)
-        return rffi.cast(lltype.Signed, f)
+    def get_propagate_exception(self):
+        return llhelper(self.PROPAGATE_EXCEPTION, self._propagate_exception)
 
     def grab_exc_value(self, deadframe):
         deadframe = lltype.cast_opaque_ptr(jitframe.DEADFRAMEPTR, deadframe)
+        if not we_are_translated() and deadframe == self.deadframe_memoryerror:
+            return "memoryerror!"       # for tests
         return deadframe.jf_guard_exc
 
     def set_savedata_ref(self, deadframe, data):

pypy/jit/backend/test/runner_test.py

             x = self.cpu.get_latest_value_float(deadframe, 0)
             assert longlong.getrealfloat(x) == 1.25 + 3.25
             called.append(self.cpu.get_latest_descr(deadframe))
-            return longlong.getfloatstorage(13.5)
+            return 13.5
 
         FUNCPTR = lltype.Ptr(lltype.FuncType([llmemory.GCREF, llmemory.GCREF],
                                              lltype.Float))
         deadframe = self.cpu.execute_token(looptoken, sys.maxint // 4 + 1)
         fail = self.cpu.get_latest_descr(deadframe)
         assert fail.identifier == excdescr.identifier
-        exc = self.cpu.grab_exc_value()
+        exc = self.cpu.grab_exc_value(deadframe)
         assert exc == "memoryerror!"
 
     def test_math_sqrt(self):

pypy/jit/backend/x86/assembler.py

             return      # not supported (for tests, or non-translated)
         #
         self.mc = codebuf.MachineCodeBlockWrapper()
-        # call on_leave_jitted_save_exc()
-        addr = self.cpu.get_on_leave_jitted_int(save_exception=True,
-                                                default_to_memoryerror=True)
+        #
+        # Call the helper, which will return a dead frame object with
+        # the correct exception set, or MemoryError by default
+        addr = rffi.cast(lltype.Signed, self.cpu.get_propagate_exception())
         self.mc.CALL(imm(addr))
-        self.mc.MOV_ri(eax.value, self.cpu.propagate_exception_v)
+        #
         self._call_footer()
         rawstart = self.mc.materialize(self.cpu.asmmemmgr, [])
         self.propagate_exception_path = rawstart
         addr = self.cpu.get_on_leave_jitted_int(save_exception=True)
         mc.CALL(imm(addr))
         #
+        xxxxxxxxxxxxxxxx
         mc.MOV_ri(eax.value, self.cpu.propagate_exception_v)
         #
         # footer -- note the ADD, which skips the return address of this

pypy/jit/metainterp/pyjitpl.py

             num = self.cpu.get_fail_descr_number(tokens[0].finishdescr)
             setattr(self.cpu, 'done_with_this_frame_%s_v' % name, num)
         #
-        exc_descr = compile.PropagateExceptionDescr()
+        exc_descr = compile.propagate_exception_descr
         num = self.cpu.get_fail_descr_number(exc_descr)
         self.cpu.propagate_exception_v = num
         #
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.