Commits

Hakan Ardo committed 581436e

Fixes test_virtual_streq_bug by introducing a dict storgin call_pure results indexed by its constant arguments. Breaks test_ztranslation

Comments (0)

Files changed (11)

pypy/jit/metainterp/compile.py

 
 def create_empty_loop(metainterp, name_prefix=''):
     name = metainterp.staticdata.stats.name_for_new_loop()
-    return TreeLoop(name_prefix + name)
+    loop = TreeLoop(name_prefix + name)
+    loop.call_pure_results = metainterp.call_pure_results
+    return loop
+
 
 def make_loop_token(nb_args, jitdriver_sd):
     loop_token = LoopToken()

pypy/jit/metainterp/history.py

     inputargs = None
     operations = None
     token = None
+    call_pure_results = None
 
     def __init__(self, name):
         self.name = name

pypy/jit/metainterp/optimizeopt/optimizer.py

         self.posponedop = None
         self.exception_might_have_happened = False
         self.newoperations = []
+        if loop is not None:
+            self.call_pure_results = loop.call_pure_results
 
         self.set_optimizations(optimizations)
 

pypy/jit/metainterp/optimizeopt/rewrite.py

             self.emit_operation(op)
 
     def optimize_CALL_PURE(self, op):
+        arg_consts = []
         for i in range(op.numargs()):
             arg = op.getarg(i)
-            if self.get_constant_box(arg) is None:
+            const = self.get_constant_box(arg)
+            if const is None:
                 break
+            arg_consts.append(const)
         else:
-            # all constant arguments: constant-fold away
-            self.make_constant(op.result, op.getarg(0))
-            return
+            # all constant arguments: check if we already know the reslut
+            try:
+                result = self.optimizer.call_pure_results[arg_consts]
+            except KeyError:
+                pass
+            else:
+                self.make_constant(op.result, result)
+                return
         # replace CALL_PURE with just CALL
-        args = op.getarglist()[1:]
+        args = op.getarglist()
         self.emit_operation(ResOperation(rop.CALL, args, op.result,
                                          op.getdescr()))
 

pypy/jit/metainterp/optimizeopt/simplify.py

 
 class OptSimplify(Optimization):
     def optimize_CALL_PURE(self, op):
-        args = op.getarglist()[1:]
+        args = op.getarglist()
         self.emit_operation(ResOperation(rop.CALL, args, op.result,
                                          op.getdescr()))
 

pypy/jit/metainterp/optimizeopt/string.py

         if not self.enabled:
             self.emit_operation(op)
             return
-            
+
         opnum = op.getopnum()
         for value, func in optimize_ops:
             if opnum == value:

pypy/jit/metainterp/optimizeutil.py

 
 def args_dict():
     return r_dict(args_eq, args_hash)
+
+def args_dict_box():
+    return r_dict(args_eq, args_hash)

pypy/jit/metainterp/pyjitpl.py

 from pypy.rlib.objectmodel import specialize
 from pypy.jit.codewriter.jitcode import JitCode, SwitchDictDescr, MissingLiveness
 from pypy.jit.codewriter import heaptracker, longlong
-from pypy.jit.metainterp.optimizeutil import RetraceLoop
+from pypy.jit.metainterp.optimizeutil import RetraceLoop, args_dict_box, args_dict
 
 # ____________________________________________________________
 
         self.free_frames_list = []
         self.last_exc_value_box = None
         self.retracing_loop_from = None
+        self.call_pure_results = args_dict_box()
 
     def perform_call(self, jitcode, boxes, greenkey=None):
         # causes the metainterp to enter the given subfunction
             return resbox_as_const
         # not all constants (so far): turn CALL into CALL_PURE, which might
         # be either removed later by optimizeopt or turned back into CALL.
-        newop = op.copy_and_change(rop.CALL_PURE, args=[resbox_as_const]+op.getarglist())
+        arg_consts = [a.constbox() for a in op.getarglist()]
+        self.call_pure_results[arg_consts] = resbox_as_const
+        newop = op.copy_and_change(rop.CALL_PURE, args=op.getarglist())
         self.history.operations[-1] = newop
         return resbox
 

pypy/jit/metainterp/test/test_compile.py

         pass
 
 class FakeMetaInterp:
+    call_pure_results = {}
     class jitdriver_sd:
         warmstate = FakeState()
 

pypy/jit/metainterp/test/test_optimizebasic.py

 from pypy.jit.metainterp import executor, compile, resume, history
 from pypy.jit.metainterp.resoperation import rop, opname, ResOperation
 from pypy.jit.tool.oparser import pure_parse
+from pypy.jit.metainterp.optimizeutil import args_dict
 
 ##class FakeFrame(object):
 ##    parent_resumedata_snapshot = None
         assert equaloplists(optimized.operations,
                             expected.operations, False, remap)
 
-    def optimize_loop(self, ops, optops):
+    def optimize_loop(self, ops, optops, call_pure_results=None):
         loop = self.parse(ops)
         #
         self.loop = loop
+        loop.call_pure_results = args_dict()
+        if call_pure_results is not None:
+            for k, v in call_pure_results.items():
+                loop.call_pure_results[list(k)] = v        
         metainterp_sd = FakeMetaInterpStaticData(self.cpu)
         if hasattr(self, 'vrefinfo'):
             metainterp_sd.virtualref_info = self.vrefinfo
         ops = '''
         [p1, i1]
         setfield_gc(p1, i1, descr=valuedescr)
-        i3 = call_pure(42, p1, descr=plaincalldescr)
+        i3 = call_pure(p1, descr=plaincalldescr)
         setfield_gc(p1, i3, descr=valuedescr)
         jump(p1, i3)
         '''
         # time.  Check that it is either constant-folded (and replaced by
         # the result of the call, recorded as the first arg), or turned into
         # a regular CALL.
+        arg_consts = [ConstInt(i) for i in (123456, 4, 5, 6)]
+        call_pure_results = {tuple(arg_consts): ConstInt(42)}        
         ops = '''
         [i0, i1, i2]
         escape(i1)
         escape(i2)
-        i3 = call_pure(42, 123456, 4, 5, 6, descr=plaincalldescr)
-        i4 = call_pure(43, 123456, 4, i0, 6, descr=plaincalldescr)
+        i3 = call_pure(123456, 4, 5, 6, descr=plaincalldescr)
+        i4 = call_pure(123456, 4, i0, 6, descr=plaincalldescr)
         jump(i0, i3, i4)
         '''
         expected = '''
         i4 = call(123456, 4, i0, 6, descr=plaincalldescr)
         jump(i0, 42, i4)
         '''
-        self.optimize_loop(ops, expected)
+        self.optimize_loop(ops, expected, call_pure_results)
 
     def test_vref_nonvirtual_nonescape(self):
         ops = """

pypy/jit/metainterp/test/test_optimizeopt.py

 from pypy.jit.metainterp.resoperation import rop, opname, ResOperation
 from pypy.jit.tool.oparser import pure_parse
 from pypy.jit.metainterp.test.test_optimizebasic import equaloplists
+from pypy.jit.metainterp.optimizeutil import args_dict
 
 class Fake(object):
     failargs_limit = 1000
         assert equaloplists(optimized.operations,
                             expected.operations, False, remap, text_right)
 
-    def optimize_loop(self, ops, optops, expected_preamble=None):
+    def optimize_loop(self, ops, optops, expected_preamble=None,
+                      call_pure_results=None):
         loop = self.parse(ops)
         if optops != "crash!":
             expected = self.parse(optops)
             expected_preamble = self.parse(expected_preamble)
         #
         self.loop = loop
+        loop.call_pure_results = args_dict()
+        if call_pure_results is not None:
+            for k, v in call_pure_results.items():
+                loop.call_pure_results[list(k)] = v
         loop.preamble = TreeLoop('preamble')
         loop.preamble.inputargs = loop.inputargs
         loop.preamble.token = LoopToken()
         ops = '''
         [p1, i1, i4]
         setfield_gc(p1, i1, descr=valuedescr)
-        i3 = call_pure(42, p1, descr=plaincalldescr)
+        i3 = call_pure(p1, descr=plaincalldescr)
         setfield_gc(p1, i3, descr=valuedescr)
         jump(p1, i4, i3)
         '''
         ops = '''
         [p1, i1, i4]
         setfield_gc(p1, i1, descr=valuedescr)
-        i3 = call_pure(42, p1, descr=plaincalldescr)
+        i3 = call_pure(p1, descr=plaincalldescr)
         setfield_gc(p1, i1, descr=valuedescr)
         jump(p1, i4, i3)
         '''
         # the result of the call, recorded as the first arg), or turned into
         # a regular CALL.
         # XXX can this test be improved with unrolling?
+        arg_consts = [ConstInt(i) for i in (123456, 4, 5, 6)]
+        call_pure_results = {tuple(arg_consts): ConstInt(42)}
         ops = '''
         [i0, i1, i2]
         escape(i1)
         escape(i2)
-        i3 = call_pure(42, 123456, 4, 5, 6, descr=plaincalldescr)
-        i4 = call_pure(43, 123456, 4, i0, 6, descr=plaincalldescr)
+        i3 = call_pure(123456, 4, 5, 6, descr=plaincalldescr)
+        i4 = call_pure(123456, 4, i0, 6, descr=plaincalldescr)
         jump(i0, i3, i4)
         '''
         preamble = '''
         i4 = call(123456, 4, i0, 6, descr=plaincalldescr)
         jump(i0, i4)
         '''
-        self.optimize_loop(ops, expected, preamble)
+        self.optimize_loop(ops, expected, preamble, call_pure_results)
 
     # ----------