[pypy-svn] pypy jit-virtual_state: Generate guards instead of retracing when it is likely it will pass and thereby make the excisting compiled loop reusable

hakanardo commits-noreply at bitbucket.org
Sun Feb 6 12:58:33 CET 2011


Author: Hakan Ardo <hakan at debian.org>
Branch: jit-virtual_state
Changeset: r41645:22bd566e537d
Date: 2011-02-06 12:56 +0100
http://bitbucket.org/pypy/pypy/changeset/22bd566e537d/

Log:	Generate guards instead of retracing when it is likely it will pass
	and thereby make the excisting compiled loop reusable

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
@@ -105,12 +105,14 @@
             newop.result = newop.result.clonebox()
             self.argmap[old_result] = newop.result
 
-        descr = newop.getdescr()
+        self.inline_descr_inplace(newop.getdescr())
+
+        return newop
+
+    def inline_descr_inplace(self, descr):
         if isinstance(descr, ResumeGuardDescr):
             descr.rd_snapshot = self.inline_snapshot(descr.rd_snapshot)
-
-        return newop
-    
+            
     def inline_arg(self, arg):
         if arg is None:
             return None
@@ -137,6 +139,12 @@
                 return False
         return True
 
+    def generate_guards(self, other, args, cpu, extra_guards):        
+        assert len(self.state) == len(other.state) == len(args)
+        for i in range(len(self.state)):
+            self.state[i].generate_guards(other.state[i], args[i],
+                                          cpu, extra_guards)
+
 class VirtualStateAdder(resume.ResumeDataVirtualAdder):
     def __init__(self, optimizer):
         self.fieldboxes = {}
@@ -200,6 +208,29 @@
                 return False
         return self.intbound.contains_bound(other.intbound)
 
+    def _generate_guards(self, other, box, cpu, extra_guards):
+        if not isinstance(other, NotVirtualInfo):
+            raise InvalidLoop
+        if self.level == LEVEL_KNOWNCLASS and \
+           box.value and \
+           self.known_class.same_constant(cpu.ts.cls_of_box(box)):
+            # Note: This is only a hint on what the class of box was
+            # during the trace. There are actually no guarentees that this
+            # box realy comes from a trace. The hint is used here to choose
+            # between either eimtting a guard_class and jumping to an
+            # excisting compiled loop or retracing the loop. Both
+            # alternatives will always generate correct behaviour, but
+            # performace will differ.
+            op = ResOperation(rop.GUARD_CLASS, [box, self.known_class], None)
+            extra_guards.append(op)
+            return
+        # Remaining cases are probably not interesting
+        raise InvalidLoop
+        if self.level == LEVEL_CONSTANT:
+            import pdb; pdb.set_trace()
+            raise NotImplementedError
+        
+
 class UnrollOptimizer(Optimization):
     """Unroll the loop into two iterations. The first one will
     become the preamble or entry bridge (don't think there is a
@@ -281,6 +312,9 @@
                 short_loop.inputargs = newargs
                 ops = [inliner.inline_op(op) for op in short_loop.operations]
                 short_loop.operations = ops
+                descr = start_resumedescr.clone_if_mutable()
+                inliner.inline_descr_inplace(descr)
+                short_loop.start_resumedescr = descr
 
                 assert isinstance(loop.preamble.token, LoopToken)
                 if loop.preamble.token.short_preamble:
@@ -585,6 +619,7 @@
 class OptInlineShortPreamble(Optimization):
     def __init__(self, retraced):
         self.retraced = retraced
+        self.inliner = None
         
     
     def reconstruct_for_next_iteration(self, optimizer, valuemap):
@@ -604,14 +639,32 @@
                 args = op.getarglist()
                 modifier = VirtualStateAdder(self.optimizer)
                 virtual_state = modifier.get_virtual_state(args)
-                for sh in short:                                        
+                for sh in short:
+                    ok = False
+                    extra_guards = []
                     if sh.virtual_state.generalization_of(virtual_state):
+                        ok = True
+                    else:
+                        try:
+                            cpu = self.optimizer.cpu
+                            sh.virtual_state.generate_guards(virtual_state,
+                                                             args, cpu,
+                                                             extra_guards)
+                            ok = True
+                        except InvalidLoop:
+                            pass
+                    if ok:
                         # FIXME: Do we still need the dry run
                         #if self.inline(sh.operations, sh.inputargs,
                         #               op.getarglist(), dryrun=True):
                         try:
                             self.inline(sh.operations, sh.inputargs,
                                         op.getarglist())
+                            for guard in extra_guards:
+                                descr = sh.start_resumedescr.clone_if_mutable()
+                                self.inliner.inline_descr_inplace(descr)
+                                guard.setdescr(descr)
+                                self.emit_operation(guard)
                         except InvalidLoop:
                             debug_print("Inlining failed unexpectedly",
                                         "jumping to preamble instead")
@@ -624,7 +677,7 @@
         
         
     def inline(self, loop_operations, loop_args, jump_args, dryrun=False):
-        inliner = Inliner(loop_args, jump_args)
+        self.inliner = inliner = Inliner(loop_args, jump_args)
 
         for op in loop_operations:
             newop = inliner.inline_op(op)
@@ -637,7 +690,7 @@
         
         return True
 
-    def inline_arg(self, arg):
-        if isinstance(arg, Const):
-            return arg
-        return self.argmap[arg]
+    #def inline_arg(self, arg):
+    #    if isinstance(arg, Const):
+    #        return arg
+    #    return self.argmap[arg]

diff --git a/pypy/jit/metainterp/resume.py b/pypy/jit/metainterp/resume.py
--- a/pypy/jit/metainterp/resume.py
+++ b/pypy/jit/metainterp/resume.py
@@ -10,6 +10,7 @@
 from pypy.rlib.objectmodel import we_are_translated, specialize
 from pypy.rlib.debug import have_debug_prints, ll_assert
 from pypy.rlib.debug import debug_start, debug_stop, debug_print
+from pypy.jit.metainterp.optimizeutil import InvalidLoop
 
 # Logic to encode the chain of frames and the state of the boxes at a
 # guard operation, and to decode it again.  This is a bit advanced,
@@ -427,12 +428,24 @@
     #    raise NotImplementedError
     def equals(self, fieldnums):
         return tagged_list_eq(self.fieldnums, fieldnums)
+
     def set_content(self, fieldnums):
         self.fieldnums = fieldnums
 
     def debug_prints(self):
         raise NotImplementedError
 
+    def generalization_of(self, other):
+        raise NotImplementedError
+
+    def generate_guards(self, other, box, cpu, extra_guards):
+        if self.generalization_of(other):
+            return
+        self._generate_guards(other, box, cpu, extra_guards)
+
+    def _generate_guards(self, other, box, cpu, extra_guards):
+        raise NotImplementedError
+        
 class AbstractVirtualStructInfo(AbstractVirtualInfo):
     def __init__(self, fielddescrs):
         self.fielddescrs = fielddescrs
@@ -468,6 +481,9 @@
 
     def _generalization_of(self, other):
         raise NotImplementedError
+
+    def _generate_guards(self, other, box, cpu, extra_guards):
+        raise InvalidLoop
             
         
 


More information about the Pypy-commit mailing list