[pypy-commit] pypy jit-targets: retrace support

hakanardo noreply at buildbot.pypy.org
Sun Nov 6 18:26:19 CET 2011


Author: Hakan Ardo <hakan at debian.org>
Branch: jit-targets
Changeset: r48833:d04c6e6f5e44
Date: 2011-11-06 18:25 +0100
http://bitbucket.org/pypy/pypy/changeset/d04c6e6f5e44/

Log:	retrace support

diff --git a/pypy/jit/metainterp/compile.py b/pypy/jit/metainterp/compile.py
--- a/pypy/jit/metainterp/compile.py
+++ b/pypy/jit/metainterp/compile.py
@@ -93,9 +93,9 @@
 
 # ____________________________________________________________
 
-def compile_procedure(metainterp, greenkey, start,
+def compile_loop(metainterp, greenkey, start,
                       inputargs, jumpargs,
-                      start_resumedescr, full_preamble_needed=True, partial_trace=None):
+                      start_resumedescr, full_preamble_needed=True):
     """Try to compile a new procedure by closing the current history back
     to the first operation.
     """
@@ -105,7 +105,7 @@
     metainterp_sd = metainterp.staticdata
     jitdriver_sd = metainterp.jitdriver_sd
 
-    if partial_trace:
+    if False:
         part = partial_trace
         assert False
         procedur_token = metainterp.get_procedure_token(greenkey)
@@ -155,7 +155,7 @@
     jitcell_token.target_tokens = all_target_tokens
     send_loop_to_backend(greenkey, jitdriver_sd, metainterp_sd, loop, "loop")
     record_loop_or_bridge(metainterp_sd, loop)
-    return jitcell_token
+    return all_target_tokens[0]
 
 
     if False: # FIXME: full_preamble_needed??
@@ -180,6 +180,53 @@
         record_loop_or_bridge(metainterp_sd, loop)
         return loop_token
 
+def compile_retrace(metainterp, greenkey, start,
+                    inputargs, jumpargs,
+                    start_resumedescr, partial_trace, resumekey):
+    """Try to compile a new procedure by closing the current history back
+    to the first operation.
+    """
+    from pypy.jit.metainterp.optimizeopt import optimize_trace
+
+    history = metainterp.history
+    metainterp_sd = metainterp.staticdata
+    jitdriver_sd = metainterp.jitdriver_sd
+
+    loop_jitcell_token = metainterp.get_procedure_token(greenkey)
+    assert loop_jitcell_token
+    assert partial_trace.operations[-1].getopnum() == rop.LABEL
+
+    part = create_empty_loop(metainterp)
+    part.inputargs = inputargs[:]
+    part.start_resumedescr = start_resumedescr
+    h_ops = history.operations    
+    part.operations = [partial_trace.operations[-1]] + \
+                      [h_ops[i].clone() for i in range(start, len(h_ops))] + \
+                      [ResOperation(rop.JUMP, jumpargs, None, descr=loop_jitcell_token)]
+    try:
+        optimize_trace(metainterp_sd, part, jitdriver_sd.warmstate.enable_opts)
+    except InvalidLoop:
+        return None
+    assert part.operations[-1].getopnum() != rop.LABEL
+    label = part.operations[0]
+    assert label.getopnum() == rop.LABEL
+    target_token = label.getdescr()
+    assert isinstance(target_token, TargetToken)
+    assert loop_jitcell_token.target_tokens
+    loop_jitcell_token.target_tokens.append(target_token)
+
+    loop = partial_trace
+    loop.operations = loop.operations[:-1] + part.operations
+
+    for box in loop.inputargs:
+        assert isinstance(box, Box)
+
+    target_token = loop.operations[-1].getdescr()
+    resumekey.compile_and_attach(metainterp, loop)
+    label.getdescr().original_jitcell_token = loop.original_jitcell_token
+    record_loop_or_bridge(metainterp_sd, loop)
+    return target_token
+
 def insert_loop_token(old_loop_tokens, loop_token):
     # Find where in old_loop_tokens we should insert this new loop_token.
     # The following algo means "as late as possible, but before another
diff --git a/pypy/jit/metainterp/history.py b/pypy/jit/metainterp/history.py
--- a/pypy/jit/metainterp/history.py
+++ b/pypy/jit/metainterp/history.py
@@ -778,6 +778,7 @@
     call_pure_results = None
     logops = None
     quasi_immutable_deps = None
+    start_resumedescr = None
 
     def _token(*args):
         raise Exception("TreeLoop.token is killed")
diff --git a/pypy/jit/metainterp/optimizeopt/unroll.py b/pypy/jit/metainterp/optimizeopt/unroll.py
--- a/pypy/jit/metainterp/optimizeopt/unroll.py
+++ b/pypy/jit/metainterp/optimizeopt/unroll.py
@@ -116,9 +116,12 @@
         jump_args = [self.getvalue(a).get_key_box() for a in original_jump_args]
 
         # FIXME: I dont thnik we need this anymore
-        start_resumedescr = self.optimizer.loop.start_resumedescr.clone_if_mutable()
-        assert isinstance(start_resumedescr, ResumeGuardDescr)
-        start_resumedescr.rd_snapshot = self.fix_snapshot(jump_args, start_resumedescr.rd_snapshot)
+        if self.optimizer.loop.start_resumedescr:
+            start_resumedescr = self.optimizer.loop.start_resumedescr.clone_if_mutable()
+            assert isinstance(start_resumedescr, ResumeGuardDescr)
+            start_resumedescr.rd_snapshot = self.fix_snapshot(jump_args, start_resumedescr.rd_snapshot)
+        else:
+            start_resumedescr = None
 
         modifier = VirtualStateAdder(self.optimizer)
         virtual_state = modifier.get_virtual_state(jump_args)
@@ -177,7 +180,8 @@
         self.imported_state = exported_state
         self.inputargs = targetop.getarglist()
         self.initial_virtual_state = target_token.virtual_state
-        self.start_resumedescr = target_token.start_resumedescr
+        #self.start_resumedescr = target_token.start_resumedescr
+        self.start_resumedescr = self.optimizer.loop.start_resumedescr
 
         seen = {}
         for box in self.inputargs:
@@ -324,7 +328,14 @@
         for i in range(len(short)):
             short[i] = inliner.inline_op(short[i])
 
-        target_token.start_resumedescr = target_token.start_resumedescr.clone_if_mutable()
+        if target_token.start_resumedescr is None: # FIXME: Hack!
+            target_token.start_resumedescr = self.start_resumedescr.clone_if_mutable()
+            fix = Inliner(self.optimizer.loop.operations[-1].getarglist(),
+                          self.optimizer.loop.inputargs)
+                          
+            fix.inline_descr_inplace(target_token.start_resumedescr)
+        else:
+            target_token.start_resumedescr = self.start_resumedescr.clone_if_mutable()            
         inliner.inline_descr_inplace(target_token.start_resumedescr)
 
         # Forget the values to allow them to be freed
@@ -497,7 +508,7 @@
 
         retraced_count = cell_token.retraced_count
         limit = self.optimizer.metainterp_sd.warmrunnerdesc.memory_manager.retrace_limit
-        if not self.retraced and retraced_count<limit:
+        if retraced_count<limit:
             cell_token.retraced_count += 1
             return False
 
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -1563,7 +1563,7 @@
 
     def retrace_needed(self, trace):
         self.partial_trace = trace
-        self.retracing_from = len(self.history)
+        self.retracing_from = len(self.history.operations) - 1
         self.heapcache.reset()
         
 
@@ -1935,6 +1935,7 @@
         # - if self.resumekey is a ResumeFromInterpDescr, it starts directly
         #   from the interpreter.
         if not self.partial_trace:
+            # FIXME: Support a retrace to be a bridge as well as a loop
             self.compile_trace(live_arg_boxes)
 
         # raises in case it works -- which is the common case, hopefully,
@@ -1959,7 +1960,7 @@
                 # raises in case it works -- which is the common case
                 if self.partial_trace:
                     assert start == self.retracing_from # FIXME: Giveup
-                self.compile_procedure(original_boxes, live_arg_boxes, start, resumedescr)
+                self.compile_loop(original_boxes, live_arg_boxes, start, resumedescr)
                 # creation of the loop was cancelled!
                 self.staticdata.log('cancelled, tracing more...')
                 #self.staticdata.log('cancelled, stopping tracing')
@@ -2019,20 +2020,27 @@
         cell = self.jitdriver_sd.warmstate.jit_cell_at_key(greenkey)
         return cell.get_procedure_token()
         
-    def compile_procedure(self, original_boxes, live_arg_boxes, start, start_resumedescr):
+    def compile_loop(self, original_boxes, live_arg_boxes, start, start_resumedescr):
         num_green_args = self.jitdriver_sd.num_green_args
         greenkey = original_boxes[:num_green_args]
         if not self.partial_trace:
             assert self.get_procedure_token(greenkey) == None # FIXME: recursion?
-        procedure_token = compile.compile_procedure(self, greenkey, start,
-                                                    original_boxes[num_green_args:],
-                                                    live_arg_boxes[num_green_args:],
-                                                    start_resumedescr, partial_trace=self.partial_trace)
-        if procedure_token is not None: # raise if it *worked* correctly
-            self.jitdriver_sd.warmstate.attach_procedure_to_interp(greenkey, procedure_token)
+        if self.partial_trace:
+            target_token = compile.compile_retrace(self, greenkey, start,
+                                                   original_boxes[num_green_args:],
+                                                   live_arg_boxes[num_green_args:],
+                                                   start_resumedescr, self.partial_trace,
+                                                   self.resumekey)
+        else:
+            target_token = compile.compile_loop(self, greenkey, start,
+                                                original_boxes[num_green_args:],
+                                                live_arg_boxes[num_green_args:],
+                                                start_resumedescr)
+        if target_token is not None: # raise if it *worked* correctly
+            self.jitdriver_sd.warmstate.attach_procedure_to_interp(greenkey, target_token.cell_token)
             self.history.inputargs = None
             self.history.operations = None
-            raise GenerateMergePoint(live_arg_boxes, procedure_token)
+            raise GenerateMergePoint(live_arg_boxes, target_token.cell_token)
 
     def compile_trace(self, live_arg_boxes):
         num_green_args = self.jitdriver_sd.num_green_args
@@ -2114,8 +2122,8 @@
         # FIXME: kill TerminatingLoopToken?
         # FIXME: can we call compile_trace?
         self.history.record(rop.FINISH, exits, None, descr=loop_tokens[0].finishdescr)
-        target_loop_token = compile.compile_trace(self, self.resumekey)
-        if not target_loop_token:
+        target_token = compile.compile_trace(self, self.resumekey)
+        if not target_token:
             compile.giveup()
 
     def compile_exit_frame_with_exception(self, valuebox):


More information about the pypy-commit mailing list