[pypy-commit] pypy pypy-dont-copy-ops: start working on lack of copying of ops

fijal noreply at buildbot.pypy.org
Thu Dec 25 21:47:15 CET 2014


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: pypy-dont-copy-ops
Changeset: r75121:1fd614fe5b30
Date: 2014-12-25 22:35 +0200
http://bitbucket.org/pypy/pypy/changeset/1fd614fe5b30/

Log:	start working on lack of copying of ops

diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py
--- a/rpython/jit/metainterp/compile.py
+++ b/rpython/jit/metainterp/compile.py
@@ -123,9 +123,10 @@
     part = create_empty_loop(metainterp)
     part.inputargs = inputargs[:]
     h_ops = history.operations
-    part.operations = [ResOperation(rop.LABEL, inputargs, None, descr=TargetToken(jitcell_token))] + \
-                      [h_ops[i].clone() for i in range(start, len(h_ops))] + \
-                      [ResOperation(rop.LABEL, jumpargs, None, descr=jitcell_token)]
+    label = ResOperation(rop.LABEL, inputargs, None,
+                         descr=TargetToken(jitcell_token))
+    end_label = ResOperation(rop.LABEL, jumpargs, None, descr=jitcell_token)
+    part.operations = [label] + h_ops + [end_label]
 
     try:
         start_state = optimize_trace(metainterp_sd, part, enable_opts,
@@ -203,7 +204,7 @@
     h_ops = history.operations
 
     part.operations = [partial_trace.operations[-1]] + \
-                      [h_ops[i].clone() for i in range(start, len(h_ops))] + \
+                      h_ops + \
                       [ResOperation(rop.JUMP, jumpargs, None, descr=loop_jitcell_token)]
     label = part.operations[0]
     orignial_label = label.clone()
@@ -783,7 +784,7 @@
     new_trace.inputargs = metainterp.history.inputargs[:]
     # clone ops, as optimize_bridge can mutate the ops
 
-    new_trace.operations = [op.clone() for op in metainterp.history.operations]
+    new_trace.operations = metainterp.history.operations[:]
     metainterp_sd = metainterp.staticdata
     state = metainterp.jitdriver_sd.warmstate
     if isinstance(resumekey, ResumeAtPositionDescr):
diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py b/rpython/jit/metainterp/optimizeopt/optimizer.py
--- a/rpython/jit/metainterp/optimizeopt/optimizer.py
+++ b/rpython/jit/metainterp/optimizeopt/optimizer.py
@@ -74,7 +74,7 @@
         if other.getlevel() == LEVEL_CONSTANT:
             self.make_constant(other.get_key_box())
         elif other.getlevel() == LEVEL_KNOWNCLASS:
-            self.make_constant_class(other.get_known_class(), None)
+            self.make_constant_class(None, other.get_known_class())
         else:
             if other.getlevel() == LEVEL_NONNULL:
                 self.ensure_nonnull()
@@ -192,7 +192,7 @@
         self.box = constbox
         self.setlevel(LEVEL_CONSTANT)
 
-    def get_last_guard(self):
+    def get_last_guard(self, optimizer):
         return None
 
     def get_known_class(self):
@@ -208,10 +208,10 @@
         return None
 
 class PtrOptValue(OptValue):
-    _attrs_ = ('known_class', 'last_guard', 'lenbound')
+    _attrs_ = ('known_class', 'last_guard_pos', 'lenbound')
 
     known_class = None
-    last_guard = None
+    last_guard_pos = -1
     lenbound = None
 
     def __init__(self, box, level=None, known_class=None, intbound=None):
@@ -224,7 +224,7 @@
         self.box = other_value.box
         self.known_class = other_value.known_class
         self._tag = other_value._tag
-        self.last_guard = other_value.last_guard
+        self.last_guard_pos = other_value.last_guard_pos
         self.lenbound = other_value.lenbound
 
     def make_len_gt(self, mode, descr, val):
@@ -235,16 +235,17 @@
         else:
             self.lenbound = LenBound(mode, descr, IntLowerBound(val + 1))
 
-    def make_nonnull(self, guardop):
+    def make_nonnull(self, optimizer):
         assert self.getlevel() < LEVEL_NONNULL
         self.setlevel(LEVEL_NONNULL)
-        self.last_guard = guardop
+        self.last_guard_pos = len(optimizer._newoperations)
 
-    def make_constant_class(self, classbox, guardop):
+    def make_constant_class(self, optimizer, classbox):
         assert self.getlevel() < LEVEL_KNOWNCLASS
         self.known_class = classbox
         self.setlevel(LEVEL_KNOWNCLASS)
-        self.last_guard = guardop
+        if optimizer is not None:
+            self.last_guard_pos = len(optimizer._newoperations)
 
     def import_from(self, other, optimizer):
         OptValue.import_from(self, other, optimizer)
@@ -299,8 +300,10 @@
     def getlenbound(self):
         return self.lenbound
 
-    def get_last_guard(self):
-        return self.last_guard
+    def get_last_guard(self, optimizer):
+        if self.last_guard_pos == -1:
+            return None
+        return optimizer._newoperations[self.last_guard_pos]
 
     def get_known_class(self):
         return self.known_class
@@ -345,7 +348,7 @@
                 return True
         return False
 
-    def make_nonnull(self, guardop):
+    def make_nonnull(self, optimizer):
         assert self.getlevel() < LEVEL_NONNULL
         self.setlevel(LEVEL_NONNULL)
 
@@ -545,6 +548,12 @@
 
         self.optimizations  = optimizations
 
+    def replace_guard(self, op, value):
+        assert isinstance(value, PtrOptValue)
+        if value.last_guard_pos == -1:
+            return
+        self.replaces_guard[op] = value.last_guard_pos
+
     def force_at_end_of_preamble(self):
         for o in self.optimizations:
             o.force_at_end_of_preamble()
@@ -705,6 +714,8 @@
     @specialize.argtype(0)
     def _emit_operation(self, op):
         assert op.getopnum() != rop.CALL_PURE
+        changed = False
+        orig_op = op
         for i in range(op.numargs()):
             arg = op.getarg(i)
             try:
@@ -713,32 +724,31 @@
                 pass
             else:
                 self.ensure_imported(value)
-                op.setarg(i, value.force_box(self))
+                newbox = value.force_box(self)
+                if not changed and arg is not newbox:
+                    op = op.clone()
+                    changed = True
+                    op.setarg(i, newbox)
         self.metainterp_sd.profiler.count(jitprof.Counters.OPT_OPS)
         if op.is_guard():
             self.metainterp_sd.profiler.count(jitprof.Counters.OPT_GUARDS)
             pendingfields = self.pendingfields
             self.pendingfields = None
-            if self.replaces_guard and op in self.replaces_guard:
-                self.replace_op(self.replaces_guard[op], op)
+            if self.replaces_guard and orig_op in self.replaces_guard:
+                self.replace_op(self.replaces_guard[orig_op], op)
                 del self.replaces_guard[op]
                 return
             else:
-                op = self.store_final_boxes_in_guard(op, pendingfields)
+                guard_op = op.clone()
+                op = self.store_final_boxes_in_guard(guard_op, pendingfields)
         elif op.can_raise():
             self.exception_might_have_happened = True
         self._newoperations.append(op)
 
-    def replace_op(self, old_op, new_op):
-        # XXX: Do we want to cache indexes to prevent search?
-        i = len(self._newoperations)
-        while i > 0:
-            i -= 1
-            if self._newoperations[i] is old_op:
-                self._newoperations[i] = new_op
-                break
-        else:
-            assert False
+    def replace_op(self, old_op_pos, new_op):
+        old_op = self._newoperations[old_op_pos]
+        assert old_op.is_guard()
+        self._newoperations[old_op_pos] = new_op
 
     def store_final_boxes_in_guard(self, op, pendingfields):
         assert pendingfields is not None
diff --git a/rpython/jit/metainterp/optimizeopt/rewrite.py b/rpython/jit/metainterp/optimizeopt/rewrite.py
--- a/rpython/jit/metainterp/optimizeopt/rewrite.py
+++ b/rpython/jit/metainterp/optimizeopt/rewrite.py
@@ -284,7 +284,7 @@
             raise InvalidLoop('A GUARD_NONNULL (%s) was proven to always fail'
                               % r)
         self.emit_operation(op)
-        value.make_nonnull(op)
+        value.make_nonnull(self.optimizer)
 
     def optimize_GUARD_VALUE(self, op):
         value = self.getvalue(op.getarg(0))
@@ -296,11 +296,11 @@
             else:
                 name = "<unknown>"
             raise InvalidLoop('A promote of a virtual %s (a recently allocated object) never makes sense!' % name)
-        if value.get_last_guard():
+        old_guard_op = value.get_last_guard(self.optimizer)
+        if old_guard_op:
             # there already has been a guard_nonnull or guard_class or
             # guard_nonnull_class on this value, which is rather silly.
             # replace the original guard with a guard_value
-            old_guard_op = value.get_last_guard()
             if old_guard_op.getopnum() != rop.GUARD_NONNULL:
                 # This is only safe if the class of the guard_value matches the
                 # class of the guard_*_class, otherwise the intermediate ops might
@@ -314,7 +314,7 @@
                     raise InvalidLoop('A GUARD_VALUE (%s) was proven to always fail' % r)
             op = old_guard_op.copy_and_change(rop.GUARD_VALUE,
                                       args = [old_guard_op.getarg(0), op.getarg(1)])
-            self.optimizer.replaces_guard[op] = old_guard_op
+            self.optimizer.replace_guard(op, value)
             # hack hack hack.  Change the guard_opnum on
             # new_guard_op.getdescr() so that when resuming,
             # the operation is not skipped by pyjitpl.py.
@@ -324,7 +324,7 @@
             descr.make_a_counter_per_value(op)
             # to be safe
             if isinstance(value, PtrOptValue):
-                value.last_guard = None
+                value.last_guard_pos = -1
         constbox = op.getarg(1)
         assert isinstance(constbox, Const)
         self.optimize_guard(op, constbox)
@@ -343,7 +343,7 @@
         if realclassbox is not None:
             assert realclassbox.same_constant(expectedclassbox)
             return
-        value.make_constant_class(expectedclassbox, None)
+        value.make_constant_class(None, expectedclassbox)
 
     def optimize_GUARD_CLASS(self, op):
         value = self.getvalue(op.getarg(0))
@@ -357,16 +357,16 @@
             raise InvalidLoop('A GUARD_CLASS (%s) was proven to always fail'
                               % r)
         assert isinstance(value, PtrOptValue)
-        if value.last_guard:
+        old_guard_op = value.get_last_guard(self.optimizer)
+        if old_guard_op:
             # there already has been a guard_nonnull or guard_class or
             # guard_nonnull_class on this value.
-            old_guard_op = value.last_guard
             if old_guard_op.getopnum() == rop.GUARD_NONNULL:
                 # it was a guard_nonnull, which we replace with a
                 # guard_nonnull_class.
                 op = old_guard_op.copy_and_change (rop.GUARD_NONNULL_CLASS,
                                          args = [old_guard_op.getarg(0), op.getarg(1)])
-                self.optimizer.replaces_guard[op] = old_guard_op
+                self.optimizer.replace_guard(op, value)
                 # hack hack hack.  Change the guard_opnum on
                 # new_guard_op.getdescr() so that when resuming,
                 # the operation is not skipped by pyjitpl.py.
@@ -374,7 +374,7 @@
                 assert isinstance(descr, compile.ResumeGuardDescr)
                 descr.guard_opnum = rop.GUARD_NONNULL_CLASS
         self.emit_operation(op)
-        value.make_constant_class(expectedclassbox, op)
+        value.make_constant_class(self.optimizer, expectedclassbox)
 
     def optimize_GUARD_NONNULL_CLASS(self, op):
         value = self.getvalue(op.getarg(0))
diff --git a/rpython/jit/metainterp/optimizeopt/simplify.py b/rpython/jit/metainterp/optimizeopt/simplify.py
--- a/rpython/jit/metainterp/optimizeopt/simplify.py
+++ b/rpython/jit/metainterp/optimizeopt/simplify.py
@@ -48,6 +48,7 @@
 
     def optimize_JUMP(self, op):
         if not self.unroll:
+            op = op.clone()
             descr = op.getdescr()
             assert isinstance(descr, JitCellToken)
             if not descr.target_tokens:
diff --git a/rpython/jit/metainterp/optimizeopt/unroll.py b/rpython/jit/metainterp/optimizeopt/unroll.py
--- a/rpython/jit/metainterp/optimizeopt/unroll.py
+++ b/rpython/jit/metainterp/optimizeopt/unroll.py
@@ -134,6 +134,7 @@
                 else:
                     debug_print("Retrace count reached, jumping to preamble")
                     assert cell_token.target_tokens[0].virtual_state is None
+                    jumpop = jumpop.clone()
                     jumpop.setdescr(cell_token.target_tokens[0])
                     self.optimizer.send_extra_operation(jumpop)
                     return
@@ -506,6 +507,7 @@
             self.import_box(a, inputargs, short_jumpargs, jumpargs)
 
     def jump_to_already_compiled_trace(self, jumpop, patchguardop):
+        jumpop = jumpop.clone()
         assert jumpop.getopnum() == rop.JUMP
         cell_token = jumpop.getdescr()
 


More information about the pypy-commit mailing list