[pypy-svn] r76984 - in pypy/branch/jit-generator/pypy/jit: backend/llgraph metainterp metainterp/test

arigo at codespeak.net arigo at codespeak.net
Thu Sep 9 19:38:25 CEST 2010


Author: arigo
Date: Thu Sep  9 19:38:23 2010
New Revision: 76984

Modified:
   pypy/branch/jit-generator/pypy/jit/backend/llgraph/llimpl.py
   pypy/branch/jit-generator/pypy/jit/metainterp/compile.py
   pypy/branch/jit-generator/pypy/jit/metainterp/jitdriver.py
   pypy/branch/jit-generator/pypy/jit/metainterp/pyjitpl.py
   pypy/branch/jit-generator/pypy/jit/metainterp/test/test_compile.py
   pypy/branch/jit-generator/pypy/jit/metainterp/warmstate.py
Log:
In-progress.  Based on compile_tmp_callback() which makes machine code
which actually just calls the portal (and thus the interpreter).  With
this, we can at least always use CALL_ASSEMBLER, even if no real machine
code was produced for the target so far.  The next step is to patch the
machine code's original CALL_ASSEMBLER to jump to the real place.


Modified: pypy/branch/jit-generator/pypy/jit/backend/llgraph/llimpl.py
==============================================================================
--- pypy/branch/jit-generator/pypy/jit/backend/llgraph/llimpl.py	(original)
+++ pypy/branch/jit-generator/pypy/jit/backend/llgraph/llimpl.py	Thu Sep  9 19:38:23 2010
@@ -128,7 +128,7 @@
     'getarrayitem_raw_pure' : (('ref', 'int'), 'intorptr'),
     'arraylen_gc'     : (('ref',), 'int'),
     'call'            : (('ref', 'varargs'), 'intorptr'),
-    'call_assembler'  : (('ref', 'varargs'), 'intorptr'),
+    'call_assembler'  : (('varargs',), 'intorptr'),
     'cond_call_gc_wb' : (('ptr', 'ptr'), None),
     'oosend'          : (('varargs',), 'intorptr'),
     'oosend_pure'     : (('varargs',), 'intorptr'),

Modified: pypy/branch/jit-generator/pypy/jit/metainterp/compile.py
==============================================================================
--- pypy/branch/jit-generator/pypy/jit/metainterp/compile.py	(original)
+++ pypy/branch/jit-generator/pypy/jit/metainterp/compile.py	Thu Sep  9 19:38:23 2010
@@ -14,6 +14,7 @@
 from pypy.jit.metainterp.specnode import NotSpecNode, more_general_specnodes
 from pypy.jit.metainterp.typesystem import llhelper, oohelper
 from pypy.jit.metainterp.optimizeutil import InvalidLoop
+from pypy.jit.codewriter import heaptracker
 
 def giveup():
     from pypy.jit.metainterp.pyjitpl import SwitchToBlackhole
@@ -547,3 +548,51 @@
         descr = target_loop_token.finishdescr
         new_op = ResOperation(rop.FINISH, op.args, None, descr=descr)
         new_loop.operations[-1] = new_op
+
+# ____________________________________________________________
+
+class PropagateExceptionDescr(AbstractFailDescr):
+    def handle_fail(self, metainterp_sd, jitdriver_sd):
+        cpu = metainterp_sd.cpu
+        exception = self.cpu.grab_exc_value()
+        raise metainterp_sd.ExitFrameWithExceptionRef(cpu, exception)
+
+def compile_tmp_callback(cpu, jitdriver_sd, greenkey, redboxes):
+    """Make a LoopToken that corresponds to assembler code that just
+    calls back the interpreter.  Used temporarily: a fully compiled
+    version of the code may end up replacing it.
+    """
+    # 'redboxes' is only used to know the types of red arguments
+    inputargs = [box.clonebox() for box in redboxes]
+    loop_token = make_loop_token(len(inputargs), jitdriver_sd)
+    #
+    k = jitdriver_sd.portal_runner_adr
+    funcbox = history.ConstInt(heaptracker.adr2int(k))
+    args = [funcbox] + greenkey + inputargs
+    #
+    result_type = jitdriver_sd.result_type
+    if result_type == history.INT:
+        result = BoxInt()
+    elif result_type == history.REF:
+        result = BoxPtr()
+    elif result_type == history.FLOAT:
+        result = BoxFloat()
+    elif result_type == history.VOID:
+        result = None
+    else:
+        assert 0, "bad result_type"
+    if result is not None:
+        finishargs = []
+    else:
+        finishargs = [result]
+    #
+    jd = jitdriver_sd
+    faildescr = PropagateExceptionDescr()
+    operations = [
+        ResOperation(rop.CALL, args, result, descr=jd.portal_calldescr),
+        ResOperation(rop.GUARD_NO_EXCEPTION, [], None, descr=faildescr),
+        ResOperation(rop.FINISH, finishargs, None, descr=jd.portal_finishtoken)
+        ]
+    operations[1].fail_args = []
+    cpu.compile_loop(inputargs, operations, loop_token)
+    return loop_token

Modified: pypy/branch/jit-generator/pypy/jit/metainterp/jitdriver.py
==============================================================================
--- pypy/branch/jit-generator/pypy/jit/metainterp/jitdriver.py	(original)
+++ pypy/branch/jit-generator/pypy/jit/metainterp/jitdriver.py	Thu Sep  9 19:38:23 2010
@@ -14,6 +14,7 @@
     #    self.virtualizable_info... pypy.jit.metainterp.warmspot
     #    self.warmstate         ... pypy.jit.metainterp.warmspot
     #    self.handle_jitexc_from_bh pypy.jit.metainterp.warmspot
+    #    self.portal_finishtoken... pypy.jit.metainterp.pyjitpl
     #    self.index             ... pypy.jit.codewriter.call
     #    self.mainjitcode       ... pypy.jit.codewriter.call
 
@@ -21,6 +22,7 @@
     #    self.assembler_helper_adr
     #    self.index_of_virtualizable
     #    self.vable_token_descr
+    #    self.portal_calldescr
 
     # warmspot sets extra attributes starting with '_' for its own use.
 

Modified: pypy/branch/jit-generator/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/jit-generator/pypy/jit/metainterp/pyjitpl.py	(original)
+++ pypy/branch/jit-generator/pypy/jit/metainterp/pyjitpl.py	Thu Sep  9 19:38:23 2010
@@ -696,7 +696,7 @@
                 portal_code = targetjitdriver_sd.mainjitcode
                 return self.metainterp.perform_call(portal_code, allboxes,
                                                     greenkey=greenboxes)
-            token = warmrunnerstate.get_assembler_token(greenboxes)
+            token = warmrunnerstate.get_assembler_token(greenboxes, redboxes)
             # verify that we have all green args, needed to make sure
             # that assembler that we call is still correct
             self.verify_green_args(targetjitdriver_sd, greenboxes)
@@ -829,7 +829,7 @@
             self.pc = saved_pc
         else:
             warmrunnerstate = jitdriver_sd.warmstate
-            token = warmrunnerstate.get_assembler_token(greenboxes)
+            token = warmrunnerstate.get_assembler_token(greenboxes, redboxes)
             # warning! careful here.  We have to return from the current
             # frame containing the jit_merge_point, and then use
             # do_recursive_call() to follow the recursive call.  This is
@@ -1217,6 +1217,7 @@
                     history.FLOAT: 'float',
                     history.VOID: 'void'}[jd.result_type]
             tokens = getattr(self, 'loop_tokens_done_with_this_frame_%s' % name)
+            jd.portal_finishtoken = tokens[0].finishdescr
             num = self.cpu.get_fail_descr_number(tokens[0].finishdescr)
             setattr(self.cpu, 'done_with_this_frame_%s_v' % name, num)
         #

Modified: pypy/branch/jit-generator/pypy/jit/metainterp/test/test_compile.py
==============================================================================
--- pypy/branch/jit-generator/pypy/jit/metainterp/test/test_compile.py	(original)
+++ pypy/branch/jit-generator/pypy/jit/metainterp/test/test_compile.py	Thu Sep  9 19:38:23 2010
@@ -1,10 +1,11 @@
 from pypy.jit.metainterp.history import LoopToken, ConstInt, History, Stats
-from pypy.jit.metainterp.history import BoxInt
+from pypy.jit.metainterp.history import BoxInt, INT
 from pypy.jit.metainterp.specnode import NotSpecNode, ConstantSpecNode
 from pypy.jit.metainterp.compile import insert_loop_token, compile_new_loop
 from pypy.jit.metainterp.compile import ResumeGuardDescr
 from pypy.jit.metainterp.compile import ResumeGuardCountersInt
-from pypy.jit.metainterp import optimize, jitprof, typesystem
+from pypy.jit.metainterp.compile import compile_tmp_callback
+from pypy.jit.metainterp import optimize, jitprof, typesystem, compile
 from pypy.jit.metainterp.test.oparser import parse
 from pypy.jit.metainterp.test.test_optimizefindnode import LLtypeMixin
 
@@ -154,3 +155,47 @@
     count = rgc.see_int(192)
     assert count == 1
     assert rgc.counters == [1, 1, 7, 6, 1]
+
+
+def test_compile_tmp_callback():
+    from pypy.jit.codewriter import heaptracker
+    from pypy.jit.backend.llgraph import runner
+    from pypy.rpython.lltypesystem import lltype, llmemory
+    from pypy.rpython.annlowlevel import llhelper
+    from pypy.rpython.llinterp import LLException
+    #
+    cpu = runner.LLtypeCPU(None)
+    FUNC = lltype.FuncType([lltype.Signed]*4, lltype.Signed)
+    def ll_portal_runner(g1, g2, r3, r4):
+        assert (g1, g2, r3, r4) == (12, 34, -156, -178)
+        if raiseme:
+            raise raiseme
+        else:
+            return 54321
+    #
+    class FakeJitDriverSD:
+        portal_runner_ptr = llhelper(lltype.Ptr(FUNC), ll_portal_runner)
+        portal_runner_adr = llmemory.cast_ptr_to_adr(portal_runner_ptr)
+        portal_calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT)
+        portal_finishtoken = compile.DoneWithThisFrameDescrInt()
+        result_type = INT
+    #
+    loop_token = compile_tmp_callback(cpu, FakeJitDriverSD(),
+                                      [ConstInt(12), ConstInt(34)],
+                                      [BoxInt(56), ConstInt(78)])
+    #
+    raiseme = None
+    cpu.set_future_value_int(0, -156)
+    cpu.set_future_value_int(1, -178)
+    fail_descr = cpu.execute_token(loop_token)
+    assert fail_descr is FakeJitDriverSD().portal_finishtoken
+    #
+    EXC = lltype.GcStruct('EXC')
+    llexc = lltype.malloc(EXC)
+    raiseme = LLException("exception class", llexc)
+    cpu.set_future_value_int(0, -156)
+    cpu.set_future_value_int(1, -178)
+    fail_descr = cpu.execute_token(loop_token)
+    assert isinstance(fail_descr, compile.PropagateExceptionDescr)
+    got = cpu.grab_exc_value()
+    assert lltype.cast_opaque_ptr(lltype.Ptr(EXC), got) == llexc

Modified: pypy/branch/jit-generator/pypy/jit/metainterp/warmstate.py
==============================================================================
--- pypy/branch/jit-generator/pypy/jit/metainterp/warmstate.py	(original)
+++ pypy/branch/jit-generator/pypy/jit/metainterp/warmstate.py	Thu Sep  9 19:38:23 2010
@@ -491,6 +491,8 @@
         #
         unwrap_greenkey = self.make_unwrap_greenkey()
         jit_getter = self.make_jitcell_getter()
+        jd = self.jitdriver_sd
+        cpu = warmrunnerdesc.cpu
 
         def can_inline_greenargs(*greenargs):
             if can_never_inline(*greenargs):
@@ -505,11 +507,14 @@
         self.can_inline_greenargs = can_inline_greenargs
         self.can_inline_callable = can_inline_callable
 
-        def get_assembler_token(greenkey):
+        def get_assembler_token(greenkey, redboxes):
+            # 'redboxes' is only used to know the types of red arguments
             greenargs = unwrap_greenkey(greenkey)
-            cell = jit_getter(False, *greenargs)
-            if cell is None or cell.counter >= 0:
-                return None
+            cell = jit_getter(True, *greenargs)
+            if cell.entry_loop_token is None:
+                from pypy.jit.metainterp.compile import compile_tmp_callback
+                cell.entry_loop_token = compile_tmp_callback(cpu, jd, greenkey,
+                                                             redboxes)
             return cell.entry_loop_token
         self.get_assembler_token = get_assembler_token
         



More information about the Pypy-commit mailing list