[pypy-svn] r61852 - pypy/branch/pyjitpl5/pypy/jit/metainterp

fijal at codespeak.net fijal at codespeak.net
Fri Feb 13 21:49:55 CET 2009


Author: fijal
Date: Fri Feb 13 21:49:53 2009
New Revision: 61852

Modified:
   pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py
   pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py
   pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py
   pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
Log:
A bit break everything. In particular
* Introduce guard_builtin that helps keeping in mind that we know the class.
  We likely want to just insert such guard_builtin for lists.
* Propagate getitem/setitem through pyjitpl in order to know that we're
  operating on lists
* Actually use the same machinery as for virtuals for virtual lists. not
  yet completely working



Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py	Fri Feb 13 21:49:53 2009
@@ -510,6 +510,16 @@
             self.emit('jit_merge_point')
             assert ([self.var_position(i) for i in op.args[2:]] ==
                     range(0, 2*(len(op.args) - 2), 2))
+            for i in range(2, len(op.args)):
+                arg = op.args[i]
+                if isinstance(arg.concretetype, lltype.Ptr):
+                    # XXX very complex logic for getting all things
+                    # that are pointers, but not objects
+                    if not (isinstance(arg.concretetype.TO, lltype.GcStruct) and
+                        (heaptracker.get_vtable_for_gcstruct(self.cpu,
+                                               arg.concretetype.TO))):
+                        self.emit('guard_builtin', self.var_position(arg))
+            
         elif op.args[0].value == 'can_enter_jit':
             self.emit('can_enter_jit')
             self.emit_varargs(op.args[2:])
@@ -568,6 +578,10 @@
             opname = 'green_call_%s'
         else:
             opname = 'residual_call_%s'
+        if oopspec_name == 'list.getitem':
+            opname = 'getitem_%s'
+        if oopspec_name == 'list.setitem':
+            opname = 'setitem_%s'
         self.emit(opname % getkind_num(self.cpu, op.result.concretetype))
         self.emit_varargs([c_func] + args)
         self.register_var(op.result)
@@ -610,7 +624,6 @@
                              if x.concretetype is not lltype.Void])
         self.register_var(op.result)
         
-
     def serialize_op_debug_assert(self, op):
         pass     # for now
 

Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py	Fri Feb 13 21:49:53 2009
@@ -80,4 +80,9 @@
 
 operations_without_side_effects = {}
 always_pure_operations = {}
+
+for guard in ['guard_no_exception', 'guard_exception', 'guard_true',
+              'guard_false', 'guard_value', 'guard_class']:
+    always_pure_operations[guard] = True
+
 setup()

Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py	Fri Feb 13 21:49:53 2009
@@ -1,4 +1,4 @@
-from pypy.jit.metainterp.history import (Box, Const, ConstInt,
+from pypy.jit.metainterp.history import (Box, Const, ConstInt, BoxInt,
                                          MergePoint, ResOperation, Jump)
 from pypy.jit.metainterp.heaptracker import (always_pure_operations,
                                              operations_without_side_effects)
@@ -206,9 +206,28 @@
             node = self.nodes[box] = InstanceNode(box, escaped=True)
             return node
 
+    def find_nodes_setfield(self, instnode, ofs, fieldnode):
+        instnode.curfields[ofs] = fieldnode
+        self.dependency_graph.append((instnode, fieldnode))
+
+    def find_nodes_getfield(self, instnode, field, box):
+        if field in instnode.curfields:
+            fieldnode = instnode.curfields[field]
+        elif field in instnode.origfields:
+            fieldnode = instnode.origfields[field]
+        else:
+            fieldnode = InstanceNode(box, escaped=False)
+            if instnode.startbox:
+                fieldnode.startbox = True
+            self.dependency_graph.append((instnode, fieldnode))
+            instnode.origfields[field] = fieldnode
+        self.nodes[box] = fieldnode
+        if self.first_escaping_op:
+            instnode.expanded_fields[field] = None        
+        
     def find_nodes(self):
         # Steps (1) and (2)
-        first_escaping_op = True
+        self.first_escaping_op = True
         for box in self.loop.operations[0].args:
             self.nodes[box] = InstanceNode(box, escaped=False, startbox=True)
 
@@ -219,16 +238,20 @@
                 instnode = InstanceNode(box, escaped=False)
                 instnode.cls = InstanceNode(op.args[1])
                 self.nodes[box] = instnode
-                first_escaping_op = False
+                self.first_escaping_op = False
+                continue
+            elif opname == 'guard_builtin':
+                instnode = self.nodes[op.args[0]]
+                # all builtins have equal classes
+                instnode.cls = InstanceNode(ConstInt(0))
                 continue
             elif opname == 'setfield_gc':
                 instnode = self.getnode(op.args[0])
                 fieldbox = op.args[1]
                 assert isinstance(fieldbox, ConstInt)
                 field = fieldbox.getint()
-                fieldnode = self.getnode(op.args[2])
-                instnode.curfields[field] = fieldnode
-                self.dependency_graph.append((instnode, fieldnode))
+                self.find_nodes_setfield(instnode, field,
+                                         self.getnode(op.args[2]))
                 continue
             elif opname == 'getfield_gc':
                 instnode = self.getnode(op.args[0])
@@ -236,20 +259,24 @@
                 assert isinstance(fieldbox, ConstInt)
                 field = fieldbox.getint()
                 box = op.results[0]
-                if field in instnode.curfields:
-                    fieldnode = instnode.curfields[field]
-                elif field in instnode.origfields:
-                    fieldnode = instnode.origfields[field]
-                else:
-                    fieldnode = InstanceNode(box, escaped=False)
-                    if instnode.startbox:
-                        fieldnode.startbox = True
-                    self.dependency_graph.append((instnode, fieldnode))
-                    instnode.origfields[field] = fieldnode
-                self.nodes[box] = fieldnode
-                if first_escaping_op:
-                    instnode.expanded_fields[field] = None
+                self.find_nodes_getfield(instnode, field, box)
                 continue
+            elif opname == 'getitem':
+                instnode = self.getnode(op.args[1])
+                fieldbox = op.args[2]
+                if isinstance(fieldbox, ConstInt):
+                    field = fieldbox.getint()
+                    box = op.results[0]
+                    self.find_nodes_getfield(instnode, field, box)
+                    continue
+            elif opname == 'setitem':
+                instnode = self.getnode(op.args[1])
+                fieldbox = op.args[2]
+                if isinstance(fieldbox, ConstInt):
+                    field = fieldbox.getint()
+                    self.find_nodes_setfield(instnode, field,
+                                             self.getnode(op.args[3]))
+                    continue
             elif opname == 'guard_class':
                 instnode = self.getnode(op.args[0])
                 if instnode.cls is None:
@@ -262,10 +289,10 @@
                 if instnode.cls is None:
                     instnode.cls = InstanceNode(op.args[1])
                 continue
-            elif opname not in ('oois', 'ooisnot',
-                                'ooisnull', 'oononnull'):
+            elif (opname not in always_pure_operations and
+                  opname not in operations_without_side_effects):
                 # default case
-                first_escaping_op = False
+                self.first_escaping_op = False
                 for box in op.args:
                     if isinstance(box, Box):
                         self.nodes[box].escaped = True
@@ -368,6 +395,26 @@
         op.args = self.new_arguments(op)
         return op
 
+    def optimize_getfield(self, instnode, ofs, box):
+        if instnode.virtual or instnode.virtualized:
+            assert ofs in instnode.curfields    # xxx
+            self.nodes[box] = instnode.curfields[ofs]
+        elif ofs in instnode.cleanfields:
+            self.nodes[box] = instnode.cleanfields[ofs]
+        else:
+            instnode.cleanfields[ofs] = InstanceNode(box)
+            return False
+        return True
+
+    def optimize_setfield(self, instnode, ofs, valuenode, valuebox):
+        if instnode.virtual or instnode.virtualized:
+            instnode.curfields[ofs] = valuenode
+        else:
+            assert not valuenode.virtual
+            instnode.cleanfields[ofs] = self.nodes[valuebox]
+            instnode.dirtyfields[ofs] = self.nodes[valuebox]
+            # we never perform this operation here, note
+
     def optimize_loop(self):
         newoperations = []
         mp = self.loop.operations[0]
@@ -403,6 +450,8 @@
                 op = self.optimize_guard(op)
                 newoperations.append(op)
                 continue
+            elif opname == 'guard_builtin':
+                continue
             elif opname == 'guard_nonvirtualized':
                 instnode = self.nodes[op.args[0]]
                 if instnode.virtualized:
@@ -420,15 +469,15 @@
             elif opname == 'getfield_gc':
                 instnode = self.nodes[op.args[0]]
                 ofs = op.args[1].getint()
-                if instnode.virtual or instnode.virtualized:
-                    assert ofs in instnode.curfields    # xxx
-                    self.nodes[op.results[0]] = instnode.curfields[ofs]
+                if self.optimize_getfield(instnode, ofs, op.results[0]):
                     continue
-                elif ofs in instnode.cleanfields:
-                    self.nodes[op.results[0]] = instnode.cleanfields[ofs]
-                    continue
-                else:
-                    instnode.cleanfields[ofs] = InstanceNode(op.results[0])
+            elif opname == 'getitem':
+                instnode = self.nodes[op.args[1]]
+                ofsbox = op.args[2]
+                if isinstance(ofsbox, ConstInt):
+                    ofs = ofsbox.getint()
+                    if self.optimize_getfield(instnode, ofs, op.results[0]):
+                        continue
             elif opname == 'new_with_vtable':
                 # self.nodes[op.results[0]] keep the value from Steps (1,2)
                 instnode = self.nodes[op.results[0]]
@@ -443,14 +492,16 @@
                 instnode = self.nodes[op.args[0]]
                 valuenode = self.nodes[op.args[2]]
                 ofs = op.args[1].getint()
-                if instnode.virtual or instnode.virtualized:
-                    instnode.curfields[ofs] = valuenode
-                else:
-                    assert not valuenode.virtual
-                    instnode.cleanfields[ofs] = self.nodes[op.args[2]]
-                    instnode.dirtyfields[ofs] = self.nodes[op.args[2]]
-                    # we never perform this operation here, note
+                self.optimize_setfield(instnode, ofs, valuenode, op.args[2])
                 continue
+            elif opname == 'setitem':
+                instnode = self.nodes[op.args[1]]
+                valuenode = self.getnode(op.args[3])
+                ofsbox = op.args[2]
+                if isinstance(ofsbox, ConstInt):
+                    ofs = ofsbox.getint()
+                    self.optimize_setfield(instnode, ofs, valuenode, op.args[3])
+                    continue
             elif opname == 'ooisnull' or opname == 'oononnull':
                 instnode = self.nodes[op.args[0]]
                 if instnode.virtual:
@@ -480,7 +531,6 @@
                     continue
             elif opname not in operations_without_side_effects:
                 self.cleanup_field_caches(newoperations)
-                first_escaping_op = False
             for box in op.results:
                 instnode = InstanceNode(box)
                 self.nodes[box] = instnode
@@ -489,21 +539,6 @@
         newoperations[0].specnodes = self.specnodes
         self.loop.operations = newoperations
 
-    def adjust_operations_before_jump(self, newoperations, args, newargs):
-        xxx
-        xxx
-        for i in range(len(args)):
-            specnode = self.specnodes[i]
-            arg = args[i]
-            if isinstance(specnode, DelayedSpecNode):
-                for ofs, subspecnode in specnode.fields:
-                    source = self.nodes[arg].source
-                    if ofs not in self.nodes[arg].cleanfields:
-                        v = subspecnode.box
-                        newoperations.append(ResOperation('getfield_gc',
-                          [source, ConstInt(ofs)], [v]))
-        self.cleanup_field_caches(newoperations)
-
     def cleanup_field_caches(self, newoperations):
         # we need to invalidate everything
         for node in self.nodes.values():

Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py	Fri Feb 13 21:49:53 2009
@@ -375,6 +375,14 @@
     def opimpl_residual_call_void(self, varargs):
         return self.execute_with_exc('call_void', varargs, 'void')
 
+    @arguments("varargs")
+    def opimpl_getitem__4(self, varargs):
+        return self.execute_with_exc('getitem', varargs, 'int')
+
+    @arguments("varargs")
+    def opimpl_setitem_void(self, varargs):
+        return self.execute_with_exc('setitem', varargs, 'void')
+
     @arguments("indirectcallset", "box", "varargs")
     def opimpl_indirect_call(self, indirectcallset, box, varargs):
         assert isinstance(box, Const) # XXX
@@ -411,6 +419,10 @@
             self.generate_guard(pc, 'guard_class', box, [clsbox])
         return clsbox
 
+    @arguments("orgpc", "box")
+    def opimpl_guard_builtin(self, pc, box):
+        self.generate_guard(pc, "guard_builtin", box)
+
     @arguments("orgpc", "box", "virtualizabledesc", "int")
     def opimpl_guard_nonvirtualized(self, pc, box, vdesc, guard_field):
         clsbox = self.cls_of_box(box)



More information about the Pypy-commit mailing list