[pypy-svn] r74338 - pypy/branch/blackhole-improvement/pypy/jit/metainterp

arigo at codespeak.net arigo at codespeak.net
Mon May 3 15:22:29 CEST 2010


Author: arigo
Date: Mon May  3 15:22:28 2010
New Revision: 74338

Modified:
   pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py
   pypy/branch/blackhole-improvement/pypy/jit/metainterp/executor.py
   pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py
   pypy/branch/blackhole-improvement/pypy/jit/metainterp/typesystem.py
Log:
Whack whack whack.


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	Mon May  3 15:22:28 2010
@@ -39,13 +39,13 @@
 
 def get_llexception(cpu, e):
     if we_are_translated():
-        return e
+        return XXX(e)
     if isinstance(e, LLException):
         return e    # ok
     if isinstance(e, OverflowError):
         return get_standard_error_llexception(cpu.rtyper,
                                               OverflowError)
-    raise   # leave other exceptions be propagated
+    raise   # leave other exceptions to be propagated
 
 # ____________________________________________________________
 
@@ -274,8 +274,6 @@
                 self.dispatch_loop(self, code, position)
             except LeaveFrame:
                 return
-            #except JitException:
-            #    ...
             except Exception, e:
                 e = get_llexception(self.cpu, e)
                 position = self.handle_exception_in_frame(e, code)
@@ -313,7 +311,8 @@
         position = self.exception_pc    # <-- just after the insn that raised
         opcode = ord(code[position])
         if opcode != self.op_catch_exception:
-            raise e      # no 'catch_exception' insn follows: just reraise
+            # no 'catch_exception' insn follows: just reraise
+            raise Exception, e
         else:
             # else store the exception on 'self', and jump to the handler
             if not we_are_translated():     # get the lltyped exception

Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/executor.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/executor.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/executor.py	Mon May  3 15:22:28 2010
@@ -12,7 +12,6 @@
 from pypy.jit.metainterp import resoperation
 from pypy.jit.metainterp.resoperation import rop
 from pypy.jit.metainterp.blackhole import BlackholeInterpreter, NULL
-from pypy.jit.metainterp.blackhole import get_llexception
 
 # ____________________________________________________________
 
@@ -47,35 +46,42 @@
     # get the function address as an integer
     func = argboxes[0].getint()
     cpu = metainterp.cpu
-    metainterp.latest_exception_might_be = 'E'         # any Exception
     # do the call using the correct function from the cpu
     rettype = descr.get_return_type()
     if rettype == INT:
         try:
             result = cpu.bh_call_i(func, descr, args_i, args_r, args_f)
         except Exception, e:
-            metainterp.got_exception = get_llexception(cpu, e)
+            metainterp.execute_raised(e)
             result = 0
+        else:
+            metainterp.execute_did_not_raise()
         return BoxInt(result)
     if rettype == REF:
         try:
             result = cpu.bh_call_r(func, descr, args_i, args_r, args_f)
         except Exception, e:
-            metainterp.got_exception = get_llexception(cpu, e)
+            metainterp.execute_raised(e)
             result = NULL
+        else:
+            metainterp.execute_did_not_raise()
         return BoxPtr(result)
     if rettype == FLOAT:
         try:
             result = cpu.bh_call_f(func, descr, args_i, args_r, args_f)
         except Exception, e:
-            metainterp.got_exception = get_llexception(cpu, e)
+            metainterp.execute_raised(e)
             result = 0.0
+        else:
+            metainterp.execute_did_not_raise()
         return BoxFloat(result)
     if rettype == 'v':   # void
         try:
             cpu.bh_call_v(func, descr, args_i, args_r, args_f)
         except Exception, e:
-            metainterp.got_exception = get_llexception(cpu, e)
+            metainterp.execute_raised(e)
+        else:
+            metainterp.execute_did_not_raise()
         return None
     raise AssertionError("bad rettype")
 
@@ -116,36 +122,39 @@
         return BoxInt(cpu.bh_getfield_raw_i(struct, fielddescr))
 
 def do_int_add_ovf(metainterp, box1, box2):
-    metainterp.latest_exception_might_be = 'O'    # only OverflowError
     a = box1.getint()
     b = box2.getint()
     try:
         z = ovfcheck(a + b)
-    except OverflowError, e:
-        metainterp.got_exception = get_llexception(metainterp.cpu, e)
+    except OverflowError:
+        metainterp.execute_raised(OverflowError(), constant=True)
         z = 0
+    else:
+        metainterp.execute_did_not_raise()
     return BoxInt(z)
 
 def do_int_sub_ovf(metainterp, box1, box2):
-    metainterp.latest_exception_might_be = 'O'    # only OverflowError
     a = box1.getint()
     b = box2.getint()
     try:
         z = ovfcheck(a - b)
-    except OverflowError, e:
-        metainterp.got_exception = get_llexception(metainterp.cpu, e)
+    except OverflowError:
+        metainterp.execute_raised(OverflowError(), constant=True)
         z = 0
+    else:
+        metainterp.execute_did_not_raise()
     return BoxInt(z)
 
 def do_int_mul_ovf(metainterp, box1, box2):
-    metainterp.latest_exception_might_be = 'O'    # only OverflowError
     a = box1.getint()
     b = box2.getint()
     try:
         z = ovfcheck(a * b)
-    except OverflowError, e:
-        metainterp.got_exception = get_llexception(metainterp.cpu, e)
+    except OverflowError:
+        metainterp.execute_raised(OverflowError(), constant=True)
         z = 0
+    else:
+        metainterp.execute_did_not_raise()
     return BoxInt(z)
 
 # ____________________________________________________________

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	Mon May  3 15:22:28 2010
@@ -1,6 +1,7 @@
 import py, os
 from pypy.rpython.lltypesystem import llmemory
 from pypy.rpython.ootypesystem import ootype
+from pypy.rpython.llinterp import LLException
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.rlib.debug import debug_start, debug_stop, debug_print
@@ -14,6 +15,7 @@
 from pypy.jit.metainterp.jitprof import EmptyProfiler
 from pypy.jit.metainterp.jitprof import GUARDS, RECORDED_OPS, ABORT_ESCAPE
 from pypy.jit.metainterp.jitprof import ABORT_TOO_LONG, ABORT_BRIDGE
+from pypy.jit.metainterp.blackhole import get_llexception
 from pypy.rlib.rarithmetic import intmask
 from pypy.rlib.objectmodel import specialize
 from pypy.rlib.jit import DEBUG_OFF, DEBUG_PROFILE, DEBUG_STEPS, DEBUG_DETAILED
@@ -44,12 +46,6 @@
 
 class MIFrame(object):
 
-    last_exception = None      # the most recently raised-and-caught exception
-    # ^^^ not to be confused with MetaInterp.got_exception.  The idea is that
-    # got_exception is only briefly != None; as soon as the exception
-    # is caught by opimpl_catch_exception, it is reset to None and
-    # transferred to last_exception here.
-
     # for resume.py operation
     parent_resumedata_snapshot = None
     parent_resumedata_frame_info_list = None
@@ -134,7 +130,6 @@
     # ------------------------------
 
     for _opimpl in ['int_add', 'int_sub', 'int_mul', 'int_floordiv', 'int_mod',
-                    'int_add_ovf', 'int_sub_ovf', 'int_mul_ovf',
                     'int_lt', 'int_le', 'int_eq',
                     'int_ne', 'int_gt', 'int_ge',
                     'int_and', 'int_or', 'int_xor',
@@ -151,6 +146,15 @@
                 return self.execute(rop.%s, b1, b2)
         ''' % (_opimpl, _opimpl.upper())).compile()
 
+    for _opimpl in ['int_add_ovf', 'int_sub_ovf', 'int_mul_ovf']:
+        exec py.code.Source('''
+            @arguments("box", "box")
+            def opimpl_%s(self, b1, b2):
+                resbox = self.execute(rop.%s, b1, b2)
+                self.metainterp.handle_possible_overflow_error()
+                return resbox
+        ''' % (_opimpl, _opimpl.upper())).compile()
+
     for _opimpl in ['int_is_true', 'int_neg', 'int_invert', 'bool_not',
                     'cast_ptr_to_int', 'cast_float_to_int',
                     'cast_int_to_float', 'float_neg', 'float_abs',
@@ -200,34 +204,14 @@
     opimpl_ref_pop   = _opimpl_any_pop
     opimpl_float_pop = _opimpl_any_pop
 
-    @arguments("orgpc", "catched_exception", "label")
-    def opimpl_catch_exception(self, pc, catched_exception, target):
-        if catched_exception is not None:
-            self.last_exception = catched_exception
-            self.pc = target
-        #
-        extraargs = []
-        latest_exception_might_be = self.metainterp.latest_exception_might_be
-        if not we_are_translated():
-            del self.metainterp.latest_exception_might_be
-        if latest_exception_might_be == 'O':
-            # only for int_xxx_ovf operations
-            if catched_exception is None:
-                opnum = rop.GUARD_NO_OVERFLOW
-            else:
-                opnum = rop.GUARD_OVERFLOW
-        else:
-            # for all residual calls
-            if catched_exception is None:
-                opnum = rop.GUARD_NO_EXCEPTION
-            else:
-                etype = catched_exception.typeptr   # XXX use the typesystem
-                etype = llmemory.cast_ptr_to_adr(etype)
-                etype = llmemory.cast_adr_to_int(etype)
-                exception_box = self.metainterp.cpu.ts.get_exception_box(etype)
-                extraargs = [exception_box]
-                opnum = rop.GUARD_EXCEPTION
-        self.generate_guard(pc, opnum, extraargs=extraargs)
+    @arguments("label")
+    def opimpl_catch_exception(self, target):
+        """This is a no-op when run normally.  We can check that
+        last_exc_value_box is None; it should have been set to None
+        by the previous instruction.  If the previous instruction
+        raised instead, finishframe_exception() should have been
+        called and we would not be there."""
+        assert self.metainterp.last_exc_value_box is None
 
     @arguments("label")
     def opimpl_goto(self, target):
@@ -618,26 +602,10 @@
         self.make_result_box(ConstInt(result))
 
     def perform_call(self, jitcode, varargs, greenkey=None):
-        if (self.metainterp.is_blackholing() and
-            jitcode.calldescr is not None):
-            # when producing only a BlackHole, we can implement this by
-            # calling the subfunction directly instead of interpreting it
-            if jitcode.cfnptr is not None:
-                # for non-oosends
-                varargs = [jitcode.cfnptr] + varargs
-                res = self.execute_varargs(rop.CALL, varargs,
-                                             descr=jitcode.calldescr, exc=True)
-            else:
-                # for oosends (ootype only): calldescr is a MethDescr
-                res = self.execute_varargs(rop.OOSEND, varargs,
-                                             descr=jitcode.calldescr, exc=True)
-            self.metainterp.load_fields_from_virtualizable()
-            return res
-        else:
-            # when tracing, this bytecode causes the subfunction to be entered
-            f = self.metainterp.newframe(jitcode, greenkey)
-            f.setup_call(varargs)
-            return True
+        # when tracing, this bytecode causes the subfunction to be entered
+        f = self.metainterp.newframe(jitcode, greenkey)
+        f.setup_call(varargs)
+        return True
 
     @XXX  #arguments("bytecode", "varargs")
     def opimpl_call(self, callee, varargs):
@@ -886,14 +854,6 @@
         self.metainterp.history.record(rop.DEBUG_MERGE_POINT,
                                        [constloc], None)
 
-    @XXX  #arguments("jumptarget")
-    def opimpl_setup_exception_block(self, exception_target):
-        self.exception_target = exception_target
-
-    @XXX  #arguments()
-    def opimpl_teardown_exception_block(self):
-        self.exception_target = -1
-
     @arguments("box", "label")
     def opimpl_goto_if_exception_mismatch(self, vtablebox, next_exc_target):
         # XXX use typesystem.py
@@ -904,16 +864,17 @@
         if not rclass.ll_isinstance(self.last_exception, bounding_class):
             self.pc = next_exc_target
 
-    @XXX  #arguments()
-    def opimpl_raise(self):
-        assert len(self.env) == 2
-        return self.metainterp.finishframe_exception(self.env[0], self.env[1])
+    @arguments("box")
+    def opimpl_raise(self, exc_value_box):
+        self.metainterp.last_exc_value_box = exc_value_box
+        self.metainterp.popframe()
+        self.metainterp.finishframe_exception()
 
     @arguments()
     def opimpl_reraise(self):
-        assert self.last_exception is not None
-        self.metainterp.got_exception = self.last_exception
-        self.metainterp.propagate_exception_out_of_frame()
+        assert self.metainterp.last_exc_value_box is not None
+        self.metainterp.popframe()
+        self.metainterp.finishframe_exception()
 
     @XXX  #arguments("box")
     def opimpl_virtual_ref(self, box):
@@ -972,11 +933,11 @@
         self.pc = 0
         self.env = argboxes
 
-    def setup_resume_at_op(self, pc, exception_target, env):
+    def setup_resume_at_op(self, pc, env):
         if not we_are_translated():
             check_args(*env)
         self.pc = pc
-        self.exception_target = exception_target
+        xxxxxxxxxxxxxxxxxxxxxxx
         self.env = env
         ##  values = ' '.join([box.repr_rpython() for box in self.env])
         ##  log('setup_resume_at_op  %s:%d [%s] %d' % (self.jitcode.name,
@@ -1044,7 +1005,7 @@
             return promoted_box
 
     def cls_of_box(self, box):
-        return self.metainterp.cpu.ts.cls_of_box(self.metainterp.cpu, box)
+        return self.metainterp.cpu.ts.cls_of_box(box)
 
     @specialize.arg(1)
     def execute(self, opnum, *argboxes):
@@ -1056,14 +1017,13 @@
 
     @specialize.arg(1)
     def execute_varargs(self, opnum, argboxes, descr, exc):
-        return self.metainterp.execute_and_record_varargs(opnum, argboxes,
-                                                          descr=descr)
-##        if resbox is not None:
-##            self.make_result_box(resbox)
-##        if exc:
-##            return self.metainterp.handle_exception()
-##        else:
-##            return self.metainterp.assert_no_exception()
+        resbox = self.metainterp.execute_and_record_varargs(opnum, argboxes,
+                                                            descr=descr)
+        if exc:
+            self.metainterp.handle_possible_exception()
+        else:
+            self.metainterp.assert_no_exception()
+        return resbox
 
     def do_residual_call(self, funcbox, descr, argboxes, exc):
         allboxes = [funcbox] + argboxes
@@ -1112,9 +1072,6 @@
         self.indirectcall_values = []
 
         self.warmrunnerdesc = warmrunnerdesc
-        #self._op_goto_if_not = self.find_opcode('goto_if_not')
-        #self._op_ooisnull    = self.find_opcode('ooisnull')
-        #self._op_oononnull   = self.find_opcode('oononnull')
 
         backendmodule = self.cpu.__module__
         backendmodule = backendmodule.split('.')[-2]
@@ -1141,6 +1098,7 @@
             name, argcodes = key.split('/')
             opimpl = _get_opimpl_method(name, argcodes)
             self.opcode_implementations[value] = opimpl
+        self.op_catch_exception = insns.get('catch_exception/L', -1)
 
     def setup_descrs(self, descrs):
         self.opcode_descrs = descrs
@@ -1265,7 +1223,6 @@
 
 class MetaInterp(object):
     in_recursion = 0
-    got_exception = None
     _already_allocated_resume_virtuals = None
 
     def __init__(self, staticdata):
@@ -1309,7 +1266,7 @@
         if self.framestack:
             if resultbox is not None:
                 self.framestack[-1].make_result_box(resultbox)
-            return True
+            raise ChangeFrame
         else:
             if not self.is_blackholing():
                 try:
@@ -1329,7 +1286,7 @@
             else:
                 assert False
 
-    def finishframe_exception(self, exceptionbox, excvaluebox):
+    def finishframe_exception(self):
         # detect and propagate some exceptions early:
         #  - AssertionError
         #  - all subclasses of JitException
@@ -1341,12 +1298,14 @@
         #
         while self.framestack:
             frame = self.framestack[-1]
-            if frame.exception_target >= 0:
-                frame.pc = frame.exception_target
-                frame.exception_target = -1
-                frame.exception_box = exceptionbox
-                frame.exc_value_box = excvaluebox
-                return True
+            code = frame.bytecode
+            position = frame.pc    # <-- just after the insn that raised
+            opcode = ord(code[position])
+            if opcode == self.staticdata.op_catch_exception:
+                # found a 'catch_exception' instruction; jump to the handler
+                target = ord(code[position+1]) | (ord(code[position+2])<<8)
+                frame.pc = target
+                raise ChangeFrame
             self.popframe()
         if not self.is_blackholing():
             try:
@@ -1373,18 +1332,6 @@
                 print jitcode.name
             raise Exception
 
-    def raise_overflow_error(self):
-        etype, evalue = self.cpu.get_overflow_error()
-        return self.finishframe_exception(
-            self.cpu.ts.get_exception_box(etype),
-            self.cpu.ts.get_exc_value_box(evalue))
-
-    def raise_zero_division_error(self):
-        etype, evalue = self.cpu.get_zero_division_error()
-        return self.finishframe_exception(
-            self.cpu.ts.get_exception_box(etype),
-            self.cpu.ts.get_exc_value_box(evalue))
-
     def create_empty_history(self):
         warmrunnerstate = self.staticdata.state
         self.history = history.History()
@@ -1466,6 +1413,24 @@
             op.pc = self.framestack[-1].pc
             op.name = self.framestack[-1].jitcode.name
 
+    def execute_raised(self, exception, constant=False):
+        # Exception handling: when execute.do_call() gets an exception it
+        # calls metainterp.execute_raised(), which puts it into
+        # 'self.last_exc_value_box'.  This is used shortly afterwards
+        # 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:
+            exc_value_box = exc_value_box.constbox()
+        self.last_exc_value_box = exc_value_box
+
+    def execute_did_not_raise(self):
+        self.last_exc_value_box = None
+
     def switch_to_blackhole(self, reason):
         self.staticdata.profiler.count(reason)
         debug_print('~~~ ABORTING TRACING')
@@ -1870,38 +1835,29 @@
         # mark by replacing it with ConstPtr(NULL)
         self.virtualref_boxes[i+1] = self.cpu.ts.CONST_NULL
 
-    def handle_exception(self):
-        etype = self.cpu.get_exception()
-        evalue = self.cpu.get_exc_value()
-        assert bool(etype) == bool(evalue)
-        self.cpu.clear_exception()
+    def handle_possible_exception(self):
         frame = self.framestack[-1]
-        if etype:
-            exception_box = self.cpu.ts.get_exception_box(etype)
-            exc_value_box = self.cpu.ts.get_exc_value_box(evalue)
+        if self.last_exc_value_box:
+            exception_box = self.cpu.ts.cls_of_box(self.last_exc_value_box)
             op = frame.generate_guard(frame.pc, rop.GUARD_EXCEPTION,
                                       None, [exception_box])
             if op:
-                op.result = exc_value_box
-            return self.finishframe_exception(exception_box, exc_value_box)
+                op.result = self.last_exc_value_box
+            self.finishframe_exception()
         else:
             frame.generate_guard(frame.pc, rop.GUARD_NO_EXCEPTION, None, [])
-            return False
 
-    def assert_no_exception(self):
-        assert not self.cpu.get_exception()
-        return False
-
-    def handle_overflow_error(self):
-        xxx
+    def handle_possible_overflow_error(self):
         frame = self.framestack[-1]
-        if self.cpu._overflow_flag:
-            self.cpu._overflow_flag = False
-            frame.generate_guard(frame.pc, rop.GUARD_OVERFLOW, None, [])
-            return self.raise_overflow_error()
+        if self.last_exc_value_box:
+            frame.generate_guard(frame.pc, rop.GUARD_OVERFLOW, None)
+            assert isinstance(self.last_exc_value_box, Const)
+            self.finishframe_exception()
         else:
-            frame.generate_guard(frame.pc, rop.GUARD_NO_OVERFLOW, None, [])
-            return False
+            frame.generate_guard(frame.pc, rop.GUARD_NO_OVERFLOW, None)
+
+    def assert_no_exception(self):
+        assert not self.last_exc_value_box
 
     def rebuild_state_after_failure(self, resumedescr, newboxes):
         vinfo = self.staticdata.virtualizable_info
@@ -2069,7 +2025,8 @@
 # ____________________________________________________________
 
 class ChangeFrame(Exception):
-    pass
+    """Raised after we mutated metainterp.framestack, in order to force
+    it to reload the current top-of-stack frame that gets interpreted."""
 
 def _get_opimpl_method(name, argcodes):
     from pypy.jit.metainterp.blackhole import signedord
@@ -2142,19 +2099,10 @@
                 position = position3 + 1 + length3
             elif argtype == "orgpc":
                 value = orgpc
-            elif argtype == "catched_exception":
-                value = self.metainterp.got_exception
-                self.metainterp.got_exception = None
             else:
                 raise AssertionError("bad argtype: %r" % (argtype,))
             args += (value,)
         #
-        if self.metainterp.got_exception is not None:
-            # the previous operation raised and the current operation
-            # is not catching it.  Propagate it.
-            self.metainterp.propagate_exception_out_of_frame()
-            return
-        #
         num_return_args = len(argcodes) - next_argcode
         assert num_return_args == 0 or num_return_args == 1
         self.pc = position + num_return_args

Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/typesystem.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/typesystem.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/typesystem.py	Mon May  3 15:22:28 2010
@@ -71,7 +71,7 @@
     def cast_fnptr_to_root(self, fnptr):
         return llmemory.cast_ptr_to_adr(fnptr)
 
-    def cls_of_box(self, cpu, box):
+    def cls_of_box(self, box):
         obj = box.getref(lltype.Ptr(rclass.OBJECT))
         cls = llmemory.cast_ptr_to_adr(obj.typeptr)
         return history.ConstInt(llmemory.cast_adr_to_int(cls))



More information about the Pypy-commit mailing list