[pypy-svn] r71041 - in pypy/trunk/pypy/jit/metainterp: . test

arigo at codespeak.net arigo at codespeak.net
Mon Feb 1 19:18:47 CET 2010


Author: arigo
Date: Mon Feb  1 19:18:45 2010
New Revision: 71041

Modified:
   pypy/trunk/pypy/jit/metainterp/codewriter.py
   pypy/trunk/pypy/jit/metainterp/pyjitpl.py
   pypy/trunk/pypy/jit/metainterp/test/test_warmstate.py
   pypy/trunk/pypy/jit/metainterp/warmstate.py
Log:
Probably fixes something...  Hard to write tests :-(
The issue is what if reds show up at places that really
expect greens, like jit_merge_point or recursive_calls.
I think that it's likely that one of these bytecodes
might use the .value in the box without noticing that
it's really a red box, leading to broken generated code.

The fix is to add independent bytecodes before, each one
forcing (if needed) one red box to a green box.



Modified: pypy/trunk/pypy/jit/metainterp/codewriter.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/codewriter.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/codewriter.py	Mon Feb  1 19:18:45 2010
@@ -74,6 +74,7 @@
         self.cpu = None
         self.portal_runner_ptr = None
         self.raise_analyzer = None
+        self.jitdriver = None
 
     def find_all_graphs(self, portal_graph, leave_graph,
                         policy, supports_floats):
@@ -1187,16 +1188,30 @@
                   self.var_position(op.args[3]))
 
     def serialize_op_jit_marker(self, op):
+        jitdriver = op.args[1].value
+        if self.codewriter.jitdriver is None:
+            self.codewriter.jitdriver = jitdriver
+        assert jitdriver is self.codewriter.jitdriver
         key = op.args[0].value
         getattr(self, 'handle_jit_marker__%s' % key)(op)
 
+    def promote_greens(self, args):
+        self.minimize_variables()
+        num_green_args = len(self.codewriter.jitdriver.greens)
+        for i in range(num_green_args):
+            pos = self.var_position(args[i])
+            if (pos % 2) == 0:
+                self.emit('guard_green', pos//2)
+
     def handle_jit_marker__jit_merge_point(self, op):
         assert self.portal, "jit_merge_point in non-main graph!"
+        self.promote_greens(op.args[2:])
         self.emit('jit_merge_point')
         assert ([self.var_position(i) for i in op.args[2:]] ==
                 range(0, 2*(len(op.args) - 2), 2))
 
     def handle_jit_marker__can_enter_jit(self, op):
+        self.promote_greens(op.args[2:])
         self.emit('can_enter_jit')
 
     def serialize_op_direct_call(self, op):
@@ -1266,6 +1281,7 @@
         self.register_var(op.result)
 
     def handle_recursive_call(self, op):
+        self.promote_greens(op.args[1:])
         self.minimize_variables()
         args = op.args[1:]
         calldescr, non_void_args = self.codewriter.getcalldescr(op.args[0],

Modified: pypy/trunk/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/pyjitpl.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/pyjitpl.py	Mon Feb  1 19:18:45 2010
@@ -674,10 +674,10 @@
         call_position = 0
         if token is not None:
             call_position = len(self.metainterp.history.operations)
-            # guard value for all green args, needed to make sure
+            # verify that we have all green args, needed to make sure
             # that assembler that we call is still correct
             greenargs = varargs[1:num_green_args + 1]
-            self.generate_guard_value_for_green_args(pc, greenargs)
+            self.verify_green_args(greenargs)
         res = self.do_residual_call(varargs, descr=calldescr, exc=True)
         if not self.metainterp.is_blackholing() and token is not None:
             # XXX fix the call position, <UGLY!>
@@ -782,6 +782,17 @@
         constbox = self.implement_guard_value(pc, box)
         self.make_result_box(constbox)
 
+    @arguments("orgpc", "int")
+    def opimpl_guard_green(self, pc, boxindex):
+        """Like guard_value, but overwrites the original box with the const.
+        Used to prevent Boxes from showing up in the greenkey of some
+        operations, like jit_merge_point.  The in-place overwriting is
+        convenient for jit_merge_point, which expects self.env to contain
+        not more than the greens+reds described in the jitdriver."""
+        box = self.env[boxindex]
+        constbox = self.implement_guard_value(pc, box)
+        self.env[boxindex] = constbox
+
     @arguments("orgpc", "box")
     def opimpl_guard_class(self, pc, box):
         clsbox = self.cls_of_box(box)
@@ -803,10 +814,10 @@
     def opimpl_keepalive(self, box):
         pass     # xxx?
 
-    def generate_guard_value_for_green_args(self, pc, varargs):
+    def verify_green_args(self, varargs):
         num_green_args = self.metainterp.staticdata.num_green_args
         for i in range(num_green_args):
-            varargs[i] = self.implement_guard_value(pc, varargs[i])
+            assert isinstance(varargs[i], Const)
 
     def blackhole_reached_merge_point(self, varargs):
         if self.metainterp.in_recursion:
@@ -829,8 +840,8 @@
         else:
             raise self.metainterp.staticdata.ContinueRunningNormally(varargs)
 
-    @arguments("orgpc")
-    def opimpl_can_enter_jit(self, pc):
+    @arguments()
+    def opimpl_can_enter_jit(self):
         # Note: when running with a BlackHole history, this 'can_enter_jit'
         # may be completely skipped by the logic that replaces perform_call
         # with rop.CALL.  But in that case, no-one will check the flag anyway,
@@ -840,10 +851,10 @@
             raise CannotInlineCanEnterJit()
         self.metainterp.seen_can_enter_jit = True
 
-    @arguments("orgpc")
-    def opimpl_jit_merge_point(self, pc):
+    @arguments()
+    def opimpl_jit_merge_point(self):
         if not self.metainterp.is_blackholing():
-            self.generate_guard_value_for_green_args(pc, self.env)
+            self.verify_green_args(self.env)
             # xxx we may disable the following line in some context later
             self.debug_merge_point()
             if self.metainterp.seen_can_enter_jit:
@@ -1025,6 +1036,9 @@
         return guard_op
 
     def implement_guard_value(self, pc, box):
+        """Promote the given Box into a Const.  Note: be careful, it's a
+        bit unclear what occurs if a single opcode needs to generate
+        several ones and/or ones not near the beginning."""
         if isinstance(box, Const):
             return box     # no promotion needed, already a Const
         else:

Modified: pypy/trunk/pypy/jit/metainterp/test/test_warmstate.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/test/test_warmstate.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/test/test_warmstate.py	Mon Feb  1 19:18:45 2010
@@ -145,7 +145,7 @@
         green_args_spec = [lltype.Signed, lltype.Float]
     state = WarmEnterState(FakeWarmRunnerDesc())
     unwrap_greenkey = state.make_unwrap_greenkey()
-    greenargs = unwrap_greenkey([BoxInt(42), BoxFloat(42.5)])
+    greenargs = unwrap_greenkey([ConstInt(42), ConstFloat(42.5)])
     assert greenargs == (42, 42.5)
     assert type(greenargs[0]) is int
 
@@ -155,7 +155,8 @@
         get_jitcell_at_ptr = None
     state = WarmEnterState(FakeWarmRunnerDesc())
     get_jitcell = state.make_jitcell_getter()
-    state.attach_unoptimized_bridge_from_interp([BoxInt(5), BoxFloat(2.25)],
+    state.attach_unoptimized_bridge_from_interp([ConstInt(5),
+                                                 ConstFloat(2.25)],
                                                 "entry loop token")
     cell1 = get_jitcell(5, 2.25)
     assert cell1.counter < 0
@@ -174,9 +175,9 @@
         return FakeCell()
     state.jit_getter = jit_getter
     state.make_jitdriver_callbacks()
-    res = state.can_inline_callable([BoxInt(5), BoxFloat(42.5)])
+    res = state.can_inline_callable([ConstInt(5), ConstFloat(42.5)])
     assert res is True
-    res = state.get_location_str([BoxInt(5), BoxFloat(42.5)])
+    res = state.get_location_str([ConstInt(5), ConstFloat(42.5)])
     assert res == '(no jitdriver.get_printable_location!)'
 
 def test_make_jitdriver_callbacks_2():
@@ -199,7 +200,7 @@
         return FakeCell()
     state.jit_getter = jit_getter
     state.make_jitdriver_callbacks()
-    res = state.can_inline_callable([BoxInt(5), BoxFloat(42.5)])
+    res = state.can_inline_callable([ConstInt(5), ConstFloat(42.5)])
     assert res is False
 
 def test_make_jitdriver_callbacks_3():
@@ -218,7 +219,7 @@
         get_jitcell_at_ptr = None
     state = WarmEnterState(FakeWarmRunnerDesc())
     state.make_jitdriver_callbacks()
-    res = state.get_location_str([BoxInt(5), BoxFloat(42.5)])
+    res = state.get_location_str([ConstInt(5), ConstFloat(42.5)])
     assert res == "hi there"
 
 def test_make_jitdriver_callbacks_4():

Modified: pypy/trunk/pypy/jit/metainterp/warmstate.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/warmstate.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/warmstate.py	Mon Feb  1 19:18:45 2010
@@ -277,7 +277,9 @@
             greenargs = ()
             i = 0
             for TYPE in green_args_spec:
-                value = unwrap(TYPE, greenkey[i])
+                greenbox = greenkey[i]
+                assert isinstance(greenbox, history.Const)
+                value = unwrap(TYPE, greenbox)
                 greenargs += (value,)
                 i = i + 1
             return greenargs



More information about the Pypy-commit mailing list