[pypy-svn] r63478 - pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp

arigo at codespeak.net arigo at codespeak.net
Wed Apr 1 12:15:55 CEST 2009


Author: arigo
Date: Wed Apr  1 12:15:52 2009
New Revision: 63478

Modified:
   pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py
Log:
Intermediate check-in, continuing to trace after a 'can_enter_jit'
that doesn't close an app-level loop at all.


Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py	Wed Apr  1 12:15:52 2009
@@ -553,7 +553,7 @@
     @arguments("orgpc", "varargs")
     def opimpl_can_enter_jit(self, pc, varargs):
         self.generate_merge_point(pc, varargs)
-        raise GenerateMergePoint(varargs)
+        self.metainterp.reached_can_enter_jit(varargs)
 
     @arguments("orgpc")
     def opimpl_jit_merge_point(self, pc):
@@ -782,6 +782,7 @@
     def delete_history(self):
         self.history = None
         self.framestack = None
+        self.current_merge_points = None
 
     def _all_constants(self, boxes):
         for box in boxes:
@@ -846,32 +847,68 @@
     def compile_and_run_once(self, *args):
         if not we_are_translated():
             history.log.info('Switching from interpreter to compiler')
-        orig_boxes = self.initialize_state_from_start(*args)
+        original_boxes = self.initialize_state_from_start(*args)
+        self.current_merge_points = [(original_boxes, 0)]
+        self.guard_key = None
         try:
             self.interpret()
             assert False, "should always raise"
         except GenerateMergePoint, gmp:
-            compiled_loop = self.compile(orig_boxes, gmp.argboxes)
-            return self.designate_target_loop(gmp, compiled_loop)
+            return self.designate_target_loop(gmp)
 
     def handle_guard_failure(self, guard_failure):
         self.initialize_state_from_guard_failure(guard_failure)
         key = guard_failure.descr
         assert isinstance(key, history.ResumeDescr)
+        self.guard_key = key
         try:
             self.prepare_resume_from_failure(key.guard_op.opnum)
             self.interpret()
             assert False, "should always raise"
         except GenerateMergePoint, gmp:
-            try:
-                target_loop = self.compile_bridge(key, gmp.argboxes)
-            except self.ContinueRunningNormally:
-                key.counter = 0
-                raise
-            return self.designate_target_loop(gmp, target_loop)
+            return self.designate_target_loop(gmp)
+
+    def reached_can_enter_jit(self, live_arg_boxes):
+        # Called whenever we reach the 'can_enter_jit' hint.
+        key = self.guard_key
+        if key is not None:
+            # We only traced so far from a guard failure to the next
+            # 'can_enter_jit'.
+            self.guard_key = None
+            target_loop = self.compile_bridge(key, live_arg_boxes)
+            if target_loop is not None:    # common case, hopefully
+                raise GenerateMergePoint(live_arg_boxes, target_loop)
+            # Failed to compile it as a bridge.  Complete it as a full loop
+            # by inserting a copy of the operations from the old loop branch
+            # before the guard that failed.
+            greenkey = prepare_loop_from_bridge(self, key)
+            original_boxes = greenkey + self.history.inputargs
+            self.current_merge_points = [(original_boxes, 0)]
+
+        # Search in current_merge_points for original_boxes with compatible
+        # green keys, representing the beginning of the same loop as the one
+        # we end now.
+        for j in range(len(self.current_merge_points)-1, -1, -1):
+            original_boxes, start = self.current_merge_points[j]
+            for i in range(self.num_green_args):
+                box1 = original_boxes[i]
+                box2 = live_arg_boxes[i]
+                if not box1.equals(box2):
+                    break
+            else:
+                # Found!  Compile it as a loop.
+                if start > 0:
+                    del self.history.operations[:start]
+                loop = self.compile(original_boxes, live_arg_boxes)
+                raise GenerateMergePoint(live_arg_boxes, loop)
+
+        # Otherwise, no loop found so far, so continue tracing.
+        start = len(self.history.operations)
+        self.current_merge_points.append((live_arg_boxes, start))
 
-    def designate_target_loop(self, gmp, loop):
+    def designate_target_loop(self, gmp):
         self.delete_history()
+        loop = gmp.target_loop
         num_green_args = self.num_green_args
         residual_args = self.get_residual_args(loop,
                                                gmp.argboxes[num_green_args:])
@@ -887,13 +924,6 @@
 
     def compile(self, original_boxes, live_arg_boxes):
         num_green_args = self.num_green_args
-        for i in range(num_green_args):
-            box1 = original_boxes[i]
-            box2 = live_arg_boxes[i]
-            if not box1.equals(box2):
-                if not we_are_translated():
-                    history.log.info('not a valid loop at all')
-                raise self.ContinueRunningNormally(live_arg_boxes)
         self.history.inputargs = original_boxes[num_green_args:]
         greenkey = original_boxes[:num_green_args]
         old_loops = self.compiled_merge_points.setdefault(greenkey, [])
@@ -911,21 +941,13 @@
         try:
             old_loops = self.compiled_merge_points[greenkey]
         except KeyError:
-            pass
-        else:
-            self.history.record(rop.JUMP, live_arg_boxes[num_green_args:],
-                                None)
-            target_loop = compile_new_bridge(self, old_loops, key)
-            if target_loop is not None:
-                return target_loop
-            self.history.operations.pop()     # remove the JUMP
-        # Failed to compile it as a bridge.  Turn it into a complete loop.
-        greenkey = prepare_loop_from_bridge(self, key)
-        original_boxes = greenkey + self.history.inputargs
-        return self.compile(original_boxes, live_arg_boxes)
-        #if not we_are_translated():
-        #    bridge._call_history = self._debug_history
-        #    self.debug_history = []
+            return None
+        self.history.record(rop.JUMP, live_arg_boxes[num_green_args:], None)
+        target_loop = compile_new_bridge(self, old_loops, key)
+        if target_loop is not None:
+            return target_loop
+        self.history.operations.pop()     # remove the JUMP
+        return None
 
     def get_residual_args(self, loop, args):
         if loop.specnodes is None:     # it is None only for tests
@@ -1034,5 +1056,7 @@
 
 
 class GenerateMergePoint(Exception):
-    def __init__(self, args):
+    def __init__(self, args, target_loop):
+        assert target_loop is not None
         self.argboxes = args
+        self.target_loop = target_loop



More information about the Pypy-commit mailing list