[pypy-svn] r74572 - in pypy/branch/blackhole-improvement/pypy/jit: backend backend/llgraph metainterp

arigo at codespeak.net arigo at codespeak.net
Wed May 19 15:37:11 CEST 2010


Author: arigo
Date: Wed May 19 15:37:09 2010
New Revision: 74572

Modified:
   pypy/branch/blackhole-improvement/pypy/jit/backend/llgraph/llimpl.py
   pypy/branch/blackhole-improvement/pypy/jit/backend/llgraph/runner.py
   pypy/branch/blackhole-improvement/pypy/jit/backend/model.py
   pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py
   pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py
Log:
Whack at exception handling until test_div_overflow passes.


Modified: pypy/branch/blackhole-improvement/pypy/jit/backend/llgraph/llimpl.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/backend/llgraph/llimpl.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/backend/llgraph/llimpl.py	Wed May 19 15:37:09 2010
@@ -766,6 +766,8 @@
             raise NotImplementedError
 
     def op_call(self, calldescr, func, *args):
+        global _last_exception
+        assert _last_exception is None, "exception left behind"
         assert _call_args_i == _call_args_r == _call_args_f == []
         for x in args:
             T = lltype.typeOf(x)
@@ -777,7 +779,15 @@
                 _call_args_f.append(x)
             else:
                 raise TypeError(x)
-        return _do_call_common(func)
+        try:
+            return _do_call_common(func)
+        except LLException, lle:
+            _last_exception = lle
+            d = {'v': None,
+                 REF: lltype.nullptr(llmemory.GCREF.TO),
+                 INT: 0,
+                 FLOAT: 0.0}
+            return d[calldescr.typeinfo]
 
     op_call_pure = op_call
 
@@ -1088,55 +1098,38 @@
 
 _last_exception = None
 
-def get_exception():
-    if _last_exception:
-        return llmemory.cast_ptr_to_adr(_last_exception.args[0])
-    else:
-        return llmemory.NULL
-
-def get_exc_value():
-    if _last_exception:
-        return lltype.cast_opaque_ptr(llmemory.GCREF, _last_exception.args[1])
+def grab_exc_value():
+    global _last_exception
+    if _last_exception is not None:
+        result = _last_exception.args[1]
+        _last_exception = None
+        return  lltype.cast_opaque_ptr(llmemory.GCREF, result)
     else:
         return lltype.nullptr(llmemory.GCREF.TO)
 
-def clear_exception():
-    global _last_exception
-    _last_exception = None
-
-_pseudo_exceptions = {}
+##_pseudo_exceptions = {}
 
-def _get_error(Class):
-    if _llinterp.typer is not None:
-        llframe = _llinterp.frame_class(None, None, _llinterp)
-        try:
-            llframe.make_llexception(Class())
-        except LLException, e:
-            return e
-        else:
-            assert 0, "should have raised"
-    else:
-        # for tests, a random emulated ll_inst will do
-        if Class not in _pseudo_exceptions:
-            ll_inst = lltype.malloc(rclass.OBJECT, zero=True)
-            ll_inst.typeptr = lltype.malloc(rclass.OBJECT_VTABLE,
-                                            immortal=True)
-            _pseudo_exceptions[Class] = LLException(ll_inst.typeptr, ll_inst)
-        return _pseudo_exceptions[Class]
-
-def get_overflow_error():
-    return llmemory.cast_ptr_to_adr(_get_error(OverflowError).args[0])
-
-def get_overflow_error_value():
-    return lltype.cast_opaque_ptr(llmemory.GCREF,
-                                  _get_error(OverflowError).args[1])
-
-def get_zero_division_error():
-    return llmemory.cast_ptr_to_adr(_get_error(ZeroDivisionError).args[0])
-
-def get_zero_division_error_value():
-    return lltype.cast_opaque_ptr(llmemory.GCREF,
-                                  _get_error(ZeroDivisionError).args[1])
+##def _get_error(Class):
+##    if _llinterp.typer is not None:
+##        llframe = _llinterp.frame_class(None, None, _llinterp)
+##        try:
+##            llframe.make_llexception(Class())
+##        except LLException, e:
+##            return e
+##        else:
+##            assert 0, "should have raised"
+##    else:
+##        # for tests, a random emulated ll_inst will do
+##        if Class not in _pseudo_exceptions:
+##            ll_inst = lltype.malloc(rclass.OBJECT, zero=True)
+##            ll_inst.typeptr = lltype.malloc(rclass.OBJECT_VTABLE,
+##                                            immortal=True)
+##            _pseudo_exceptions[Class] = LLException(ll_inst.typeptr, ll_inst)
+##        return _pseudo_exceptions[Class]
+
+##def get_overflow_error_value():
+##    return lltype.cast_opaque_ptr(llmemory.GCREF,
+##                                  _get_error(OverflowError).args[1])
 
 def force(opaque_frame):
     frame = _from_opaque(opaque_frame)
@@ -1513,13 +1506,7 @@
 setannotation(frame_ptr_getvalue, annmodel.SomePtr(llmemory.GCREF))
 setannotation(frame_float_getvalue, annmodel.SomeFloat())
 
-setannotation(get_exception, annmodel.SomeAddress())
-setannotation(get_exc_value, annmodel.SomePtr(llmemory.GCREF))
-setannotation(clear_exception, annmodel.s_None)
-setannotation(get_overflow_error, annmodel.SomeAddress())
-setannotation(get_overflow_error_value, annmodel.SomePtr(llmemory.GCREF))
-setannotation(get_zero_division_error, annmodel.SomeAddress())
-setannotation(get_zero_division_error_value, annmodel.SomePtr(llmemory.GCREF))
+setannotation(grab_exc_value, annmodel.SomePtr(llmemory.GCREF))
 setannotation(force, annmodel.SomeInteger())
 setannotation(get_forced_token_frame, s_Frame)
 setannotation(get_frame_forced_token, annmodel.SomeAddress())

Modified: pypy/branch/blackhole-improvement/pypy/jit/backend/llgraph/runner.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/backend/llgraph/runner.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/backend/llgraph/runner.py	Wed May 19 15:37:09 2010
@@ -274,11 +274,8 @@
         token = history.getkind(RESULT)
         return self.getdescr(0, token[0], extrainfo=extrainfo)
 
-    def get_exception(self):
-        return self.cast_adr_to_int(llimpl.get_exception())
-
-    def get_exc_value(self):
-        return llimpl.get_exc_value()
+    def grab_exc_value(self):
+        return llimpl.grab_exc_value()
 
     def arraydescrof(self, A):
         assert isinstance(A, lltype.GcArray)

Modified: pypy/branch/blackhole-improvement/pypy/jit/backend/model.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/backend/model.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/backend/model.py	Wed May 19 15:37:09 2010
@@ -100,19 +100,8 @@
         they no longer keep objects alive)."""
         raise NotImplementedError
 
-    def get_exception(self):
-        raise NotImplementedError
-
-    def get_exc_value(self):
-        raise NotImplementedError
-
-    def clear_exception(self):
-        raise NotImplementedError
-
-    def get_overflow_error(self):
-        raise NotImplementedError
-
-    def get_zero_division_error(self):
+    def grab_exc_value(self):
+        """Return and clear the exception set by the latest execute_token()."""
         raise NotImplementedError
 
     @staticmethod

Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py	Wed May 19 15:37:09 2010
@@ -32,21 +32,19 @@
 
 NULL = lltype.nullptr(llmemory.GCREF.TO)
 
-def get_standard_error_llexception(rtyper, Class):
+def _get_standard_error(rtyper, Class):
     exdata = rtyper.getexceptiondata()
     clsdef = rtyper.annotator.bookkeeper.getuniqueclassdef(Class)
     evalue = exdata.get_standard_ll_exc_instance(rtyper, clsdef)
-    etype = rclass.ll_type(evalue)
-    return LLException(etype, evalue)
+    return evalue
 
 def get_llexception(cpu, e):
     if we_are_translated():
         return XXX(e)
     if isinstance(e, LLException):
-        return e    # ok
+        return e.args[1]    # ok
     if isinstance(e, OverflowError):
-        return get_standard_error_llexception(cpu.rtyper,
-                                              OverflowError)
+        return _get_standard_error(cpu.rtyper, OverflowError)
     raise   # leave other exceptions to be propagated
 
 # ____________________________________________________________
@@ -180,7 +178,7 @@
                     print '-> %s!' % (e.__class__.__name__,)
                 if resulttype == 'i' or resulttype == 'r' or resulttype == 'f':
                     position += 1
-                self.exception_pc = position
+                self.position = position
                 raise
 
             if verbose and not we_are_translated():
@@ -291,21 +289,21 @@
         self.registers_f[index] = value
 
     def run(self):
-        code = self.jitcode.code
-        position = self.position
         while True:
             try:
-                self.dispatch_loop(self, code, position)
+                self.dispatch_loop(self, self.jitcode.code, self.position)
             except LeaveFrame:
                 break
             except Exception, e:
                 e = get_llexception(self.cpu, e)
-                position = self.handle_exception_in_frame(e, code)
+                self.handle_exception_in_frame(e)
 
     def get_result_i(self):
+        assert self._return_type == 'i'
         return self.tmpreg_i
 
     def get_result_r(self):
+        assert self._return_type == 'r'
         result = self.tmpreg_r
         if we_are_translated():
             self.tmpreg_r = NULL
@@ -314,14 +312,18 @@
         return result
 
     def get_result_f(self):
+        assert self._return_type == 'f'
         return self.tmpreg_f
 
+    def get_result_v(self):
+        assert self._return_type == 'v'
+
     def _get_result_anytype(self):
         "NOT_RPYTHON"
-        if self._return_type == 'int': return self.get_result_i()
-        if self._return_type == 'ref': return self.get_result_r()
-        if self._return_type == 'float': return self.get_result_f()
-        if self._return_type == 'void': return None
+        if self._return_type == 'i': return self.get_result_i()
+        if self._return_type == 'r': return self.get_result_r()
+        if self._return_type == 'f': return self.get_result_f()
+        if self._return_type == 'v': return None
         raise ValueError(self._return_type)
 
     def cleanup_registers(self):
@@ -332,21 +334,24 @@
             self.registers_r[i] = NULL
         self.exception_last_value = None
 
-    def handle_exception_in_frame(self, e, code):
+    def handle_exception_in_frame(self, e):
         # This frame raises an exception.  First try to see if
         # the exception is handled in the frame itself.
-        position = self.exception_pc    # <-- just after the insn that raised
+        code = self.jitcode.code
+        position = self.position
         opcode = ord(code[position])
         if opcode != self.op_catch_exception:
             # no 'catch_exception' insn follows: just reraise
-            raise Exception, e
+            if we_are_translated():
+                raise Exception, e
+            else:
+                etype = rclass.ll_type(e)
+                raise LLException(etype, e)
         else:
             # else store the exception on 'self', and jump to the handler
-            if not we_are_translated():     # get the lltyped exception
-                e = e.args[1]               #   object out of the LLException
             self.exception_last_value = e
             target = ord(code[position+1]) | (ord(code[position+2])<<8)
-            return target
+            self.position = target
 
     # XXX must be specialized
     def copy_constants(self, registers, constants):
@@ -586,28 +591,24 @@
     @arguments("self", "i")
     def bhimpl_int_return(self, a):
         self.tmpreg_i = a
-        if not we_are_translated():
-            self._return_type = "int"
+        self._return_type = 'i'
         raise LeaveFrame
 
     @arguments("self", "r")
     def bhimpl_ref_return(self, a):
         self.tmpreg_r = a
-        if not we_are_translated():
-            self._return_type = "ref"
+        self._return_type = 'r'
         raise LeaveFrame
 
     @arguments("self", "f")
     def bhimpl_float_return(self, a):
         self.tmpreg_f = a
-        if not we_are_translated():
-            self._return_type = "float"
+        self._return_type = 'f'
         raise LeaveFrame
 
     @arguments("self")
     def bhimpl_void_return(self):
-        if not we_are_translated():
-            self._return_type = "void"
+        self._return_type = 'v'
         raise LeaveFrame
 
     @arguments("i", "L", "pc", returns="L")
@@ -935,6 +936,80 @@
     def bhimpl_unicodesetitem(cpu, unicode, index, newchr):
         cpu.bh_unicodesetitem(unicode, index, newchr)
 
+    # ----------
+    # helpers to resume running in blackhole mode when a guard failed
+
+    def _resume_mainloop(self, current_exc):
+        try:
+            # if there is a current exception, raise it now
+            # (it may be caught by a catch_operation in this frame)
+            if current_exc:
+                self.handle_exception_in_frame(current_exc)
+            # unless the call above raised again the exception,
+            # we now proceed to interpret the bytecode in this frame
+            self.run()
+        #
+        except Exception, e:
+            # if we get an exception, return it to the caller frame
+            current_exc = get_llexception(self.cpu, e)
+            if not self.nextblackholeinterp:
+                self._exit_frame_with_exception(current_exc)
+            return current_exc
+        #
+        # pass the frame's return value to the caller
+        caller = self.nextblackholeinterp
+        if not caller:
+            self._done_with_this_frame()
+        kind = self._return_type
+        if kind == 'i':
+            caller._setup_return_value_i(self.get_result_i())
+        elif kind == 'r':
+            caller._setup_return_value_r(self.get_result_r())
+        elif kind == 'f':
+            caller._setup_return_value_f(self.get_result_f())
+        else:
+            assert kind == 'v'
+        return NULL
+
+    def _prepare_resume_from_failure(self, opnum):
+        from pypy.jit.metainterp.resoperation import rop
+        if opnum == rop.GUARD_TRUE:     # a goto_if_not_xxx that jumps only now
+            self.position = self.jitcode.follow_jump(self.position)
+        elif opnum == rop.GUARD_FALSE:  # a goto_if_not that stops jumping
+            pass
+        elif opnum == rop.GUARD_NO_EXCEPTION or opnum == rop.GUARD_EXCEPTION:
+            pass
+        else:
+            raise NotImplementedError(opnum)
+
+    # connect the return of values from the called frame to the
+    # 'xxx_call_yyy' instructions from the caller frame
+    def _setup_return_value_i(self, result):
+        self.registers_i[ord(self.jitcode.code[position-1])] = result
+    def _setup_return_value_r(self, result):
+        self.registers_r[ord(self.jitcode.code[position-1])] = result
+    def _setup_return_value_f(self, result):
+        self.registers_f[ord(self.jitcode.code[position-1])] = result
+
+    def _exit_frame_with_exception(self, e):
+        xxx
+
+    def _done_with_this_frame(self):
+        # rare case: we only get there if the blackhole interps all returned
+        # normally (in general we get a ContinueRunningNormally exception).
+        sd = self.builder.metainterp_sd
+        if sd.result_type == 'void':
+            self.get_result_v()
+            raise sd.DoneWithThisFrameVoid()
+        elif sd.result_type == 'int':
+            raise sd.DoneWithThisFrameInt(self.get_result_i())
+        elif sd.result_type == 'ref':
+            raise sd.DoneWithThisFrameRef(self.get_result_r())
+        elif sd.result_type == 'float':
+            raise sd.DoneWithThisFrameFloat(self.get_result_f())
+        else:
+            assert False
+
 # ____________________________________________________________
 
 def resume_in_blackhole(metainterp_sd, resumedescr):
@@ -947,47 +1022,13 @@
         False)  # XXX
     # XXX virtualrefs
     # XXX virtualizable
-    _prepare_resume_from_failure(blackholeinterp, resumedescr.guard_opnum)
+    blackholeinterp._prepare_resume_from_failure(resumedescr.guard_opnum)
     try:
-        blackholeinterp = _resume_mainloop(blackholeinterp)
+        current_exc = blackholeinterp.cpu.grab_exc_value()
+        current_exc = lltype.cast_opaque_ptr(rclass.OBJECTPTR, current_exc)
+        while True:
+            current_exc = blackholeinterp._resume_mainloop(current_exc)
+            blackholeinterp = blackholeinterp.nextblackholeinterp
     finally:
         metainterp_sd.profiler.end_blackhole()
         debug_stop('jit-blackhole')
-    # rare case: we only get there if the blackhole interps all returned
-    # normally (in general we get a ContinueRunningNormally exception).
-    _done_with_this_frame(blackholeinterp)
-
-def _resume_mainloop(blackholeinterp):
-    while True:
-        try:
-            blackholeinterp.run()
-        finally:
-            blackholeinterp.builder.release_interp(blackholeinterp)
-        #...x.x.x...
-        assert blackholeinterp.nextblackholeinterp is None  # XXX
-        break
-        xxx
-    return blackholeinterp
-
-def _prepare_resume_from_failure(blackholeinterp, opnum):
-    from pypy.jit.metainterp.resoperation import rop
-    if opnum == rop.GUARD_TRUE:      # a goto_if_not_xxx that jumps only now
-        blackholeinterp.position = blackholeinterp.jitcode.follow_jump(
-            blackholeinterp.position)
-    elif opnum == rop.GUARD_FALSE:   # a goto_if_not that stops jumping
-        pass
-    else:
-        raise NotImplementedError(opnum)
-
-def _done_with_this_frame(blackholeinterp):
-    sd = blackholeinterp.builder.metainterp_sd
-    if sd.result_type == 'void':
-        raise sd.DoneWithThisFrameVoid()
-    elif sd.result_type == 'int':
-        raise sd.DoneWithThisFrameInt(blackholeinterp.get_result_i())
-    elif sd.result_type == 'ref':
-        raise sd.DoneWithThisFrameRef(blackholeinterp.get_result_r())
-    elif sd.result_type == 'float':
-        raise sd.DoneWithThisFrameFloat(blackholeinterp.get_result_f())
-    else:
-        assert False

Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py	Wed May 19 15:37:09 2010
@@ -1413,8 +1413,6 @@
         # to generate either GUARD_EXCEPTION or GUARD_NO_EXCEPTION, and also
         # to handle the following opcodes 'goto_if_exception_mismatch'.
         llexception = get_llexception(self.cpu, exception)
-        if not we_are_translated():
-            llexception = llexception.args[1]
         llexception = self.cpu.ts.cast_to_ref(llexception)
         exc_value_box = self.cpu.ts.get_exc_value_box(llexception)
         if constant:
@@ -1600,7 +1598,12 @@
             pass
         elif (opnum == rop.GUARD_NO_EXCEPTION or opnum == rop.GUARD_EXCEPTION
               or opnum == rop.GUARD_NOT_FORCED):
-            xxx #self.handle_exception()
+            exception = self.cpu.grab_exc_value()
+            if exception:
+                self.execute_raised(exception)
+            else:
+                self.execute_did_not_raise()
+            self.handle_possible_exception()
         elif opnum == rop.GUARD_NO_OVERFLOW:   # an overflow now detected
             xxx #self.raise_overflow_error()
         elif opnum == rop.GUARD_NONNULL or opnum == rop.GUARD_ISNULL:



More information about the Pypy-commit mailing list