[pypy-svn] r61935 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test

fijal at codespeak.net fijal at codespeak.net
Sun Feb 15 14:32:11 CET 2009


Author: fijal
Date: Sun Feb 15 14:32:09 2009
New Revision: 61935

Modified:
   pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py
   pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py
   pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
   pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py
   pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py
Log:
A bit of support for virtual lists with length. Right now escaping
rules are messy, ie it will all explode if you try to escape


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	Sun Feb 15 14:32:09 2009
@@ -18,10 +18,14 @@
     pass
 
 class ListDescr(BuiltinDescr):
-    def __init__(self, getfunc, setfunc, malloc_func, tp):
+    def __init__(self, getfunc, setfunc, malloc_func, append_func,
+                 pop_func, len_func, tp):
         self.setfunc     = setfunc
         self.getfunc     = getfunc
         self.malloc_func = malloc_func
+        self.append_func = append_func
+        self.pop_func    = pop_func
+        self.len_func    = len_func
         self.tp          = tp
     
     def equals(self, other):
@@ -145,22 +149,46 @@
         try:
             return self.list_cache[TP.TO]
         except KeyError:
+            if isinstance(TP.TO, lltype.GcStruct):
+                OF = TP.TO.items.TO.OF
+            else:
+                OF = TP.TO.OF
             rtyper = self.rtyper
-            args = [TP, lltype.Signed, TP.TO.OF]
+            args = [TP, lltype.Signed, OF]
             setfunc, _ = support.builtin_func_for_spec(rtyper, 'list.setitem',
                                                        args, lltype.Void)
             getfunc, _ = support.builtin_func_for_spec(rtyper, 'list.getitem',
-                                                       args[:-1], TP.TO.OF)
+                                                       args[:-1], OF)
             malloc_func, _ = support.builtin_func_for_spec(rtyper, 'newlist',
                                                            [lltype.Signed], TP)
-            if isinstance(TP.TO.OF, lltype.Number):
+            len_func, _ = support.builtin_func_for_spec(rtyper, 'list.len',
+                                                        [TP], lltype.Signed)
+
+            if isinstance(TP.TO, lltype.GcStruct):
+                append_func, _ = support.builtin_func_for_spec(rtyper,
+                                                               'list.append',
+                                                        [TP, OF], lltype.Void)
+                pop_func, _ = support.builtin_func_for_spec(rtyper, 'list.pop',
+                                                            [TP], OF)
+            if isinstance(OF, lltype.Number):
                 tp = "int"
             else:
                 tp = "ptr"
-            ld = ListDescr(history.ConstAddr(getfunc.value, self.cpu),
-                           history.ConstAddr(setfunc.value, self.cpu),
-                           history.ConstAddr(malloc_func.value, self.cpu),
-                           tp)
+            if isinstance(TP.TO, lltype.GcStruct):
+                ld = ListDescr(history.ConstAddr(getfunc.value, self.cpu),
+                               history.ConstAddr(setfunc.value, self.cpu),
+                               history.ConstAddr(malloc_func.value, self.cpu),
+                               history.ConstAddr(append_func.value, self.cpu),
+                               history.ConstAddr(pop_func.value, self.cpu),
+                               history.ConstAddr(len_func.value, self.cpu),
+                               tp)
+            else:
+                ld = ListDescr(history.ConstAddr(getfunc.value, self.cpu),
+                               history.ConstAddr(setfunc.value, self.cpu),
+                               history.ConstAddr(malloc_func.value, self.cpu),
+                               None, None,
+                               history.ConstAddr(len_func.value, self.cpu),
+                               tp)
             self.list_cache[TP.TO] = ld
             return ld
 
@@ -560,15 +588,23 @@
             self.emit('can_enter_jit')
             self.emit_varargs(op.args[2:])
 
-    def _eventualy_builtin(self, arg):
+    def _eventualy_builtin(self, arg, need_length=True):
         if isinstance(arg.concretetype, lltype.Ptr):
             # XXX very complex logic for getting all things
             # that are pointers, but not objects
+            is_list = False
             if isinstance(arg.concretetype.TO, lltype.GcArray):
+                is_list = True
+            if isinstance(arg.concretetype.TO, lltype.GcStruct):
+                if arg.concretetype.TO._hints.get('list'):
+                    is_list = True
+            if is_list:
                 descr = self.codewriter.list_descr_for_tp(arg.concretetype)
                 self.emit('guard_builtin', self.var_position(arg),
                           self.get_position(descr))
-
+                if need_length:
+                    self.emit('guard_len', self.var_position(arg),
+                              self.get_position(descr))
 
     #def serialize_op_direct_call(self, op):
     #    color = support.guess_call_kind(self.codewriter.hannotator, op)
@@ -609,14 +645,19 @@
         c_func, TP = support.builtin_func_for_spec(self.codewriter.rtyper,
                                                    oopspec_name, ll_args,
                                                    op.result.concretetype)
-        if ((oopspec_name.startswith('list') or oopspec_name == 'newlist') and
-            not isinstance(TP.TO, lltype.GcStruct)):
+        if oopspec_name.startswith('list') or oopspec_name == 'newlist':
             if oopspec_name.startswith('list.getitem'):
                 opname = oopspec_name[len('list.'):]
             elif oopspec_name.startswith('list.setitem'):
                 opname = oopspec_name[len('list.'):]
             elif oopspec_name == 'newlist':
                 opname = 'newlist'
+            elif oopspec_name == 'list.append':
+                opname = 'append'
+            elif oopspec_name == 'list.pop':
+                opname = 'pop'
+            elif oopspec_name == 'list.len':
+                opname = 'len'
             else:
                 raise NotImplementedError("not supported %s" % oopspec_name)
             self.emit(opname)
@@ -625,7 +666,7 @@
             self.emit_varargs(args)
             self.register_var(op.result)
             if opname == 'newlist':
-                self._eventualy_builtin(op.result)
+                self._eventualy_builtin(op.result, False)
             return
         if oopspec_name.endswith('_foldable'):
             opname = 'green_call_%s'

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	Sun Feb 15 14:32:09 2009
@@ -56,9 +56,7 @@
                 assert isinstance(ld, ListDescr)
                 alloc_offset = len(self.list_allocations)
                 malloc_func = ld.malloc_func
-                if instnode.known_length == -1:
-                    # XXX
-                    instnode.known_length = 42
+                assert instnode.known_length != -1
                 self.list_allocations.append((malloc_func,
                                               instnode.known_length))
                 res = (alloc_offset + 1) << 16
@@ -145,6 +143,9 @@
                 return FixedListSpecNode(known_class)
             return FixedClassSpecNode(known_class)
         if not other.escaped:
+            if (isinstance(known_class, ListDescr)
+                and self.known_length != other.known_length):
+                XXX # XXX think
             fields = []
             if self is other:
                 d = other.curfields
@@ -162,7 +163,8 @@
                     specnode = NotSpecNode()
                 fields.append((ofs, specnode))
             if isinstance(known_class, ListDescr):
-                return VirtualListSpecNode(known_class, fields)
+                return VirtualListSpecNode(known_class, fields,
+                                           other.known_length)
             return VirtualInstanceSpecNode(known_class, fields)
         if not other.virtualized and self.expanded_fields:
             fields = []
@@ -279,10 +281,10 @@
     def find_nodes(self):
         # Steps (1) and (2)
         self.first_escaping_op = True
+        # only catch can have consts
         for box in self.loop.operations[0].args:
             self.nodes[box] = InstanceNode(box, escaped=False, startbox=True,
                                            const=isinstance(box, Const))
-
         for op in self.loop.operations[1:-1]:
             opname = op.opname
             if opname == 'new_with_vtable':
@@ -308,6 +310,10 @@
                 # all builtins have equal classes
                 instnode.cls = InstanceNode(op.args[1])
                 continue
+            elif opname == 'guard_len':
+                instnode = self.nodes[op.args[0]]
+                instnode.known_length = op.args[1].getint()
+                continue
             elif opname == 'setfield_gc':
                 instnode = self.getnode(op.args[0])
                 fieldbox = op.args[1]
@@ -335,6 +341,29 @@
                     continue
                 else:
                     instnode.escaped = True
+            elif opname == 'append':
+                instnode = self.getnode(op.args[1])
+                assert isinstance(instnode.cls.source, ListDescr)
+                assert instnode.known_length != -1
+                field = instnode.known_length
+                instnode.known_length += 1
+                self.find_nodes_setfield(instnode, field,
+                                         self.getnode(op.args[2]))
+                continue
+            elif opname == 'pop':
+                instnode = self.getnode(op.args[1])
+                assert isinstance(instnode.cls.source, ListDescr)
+                assert instnode.known_length != -1
+                instnode.known_length -= 1
+                field = instnode.known_length
+                self.find_nodes_getfield(instnode, field, op.results[0])
+                continue
+            elif opname == 'len':
+                instnode = self.getnode(op.args[1])
+                assert instnode.known_length != -1
+                lgtbox = op.results[0].constbox()
+                self.nodes[op.results[0]] = InstanceNode(lgtbox, const=True)
+                continue
             elif opname == 'setitem':
                 instnode = self.getnode(op.args[1])
                 fieldbox = op.args[2]
@@ -554,6 +583,13 @@
                 if instnode.cls is None:
                     instnode.cls = InstanceNode(op.args[1])
                 continue
+            elif opname == 'guard_len':
+                # it should be completely gone, because if it escapes
+                # we don't virtualize it anymore
+                if not instnode.escaped:
+                    instnode = self.nodes[op.args[0]]
+                    instnode.known_length = op.args[1].getint()
+                continue
             elif opname == 'guard_nonvirtualized':
                 instnode = self.nodes[op.args[0]]
                 if instnode.virtualized:
@@ -608,12 +644,33 @@
                     instnode.virtual = True
                     valuesource = self.getsource(op.args[2])
                     assert isinstance(valuesource, Const)
-                    for i in range(instnode.known_length):
+                    maxlength = max(instnode.curfields.keys() +
+                                    instnode.origfields.keys())
+                    for i in range(maxlength + 1):
                         instnode.curfields[i] = InstanceNode(valuesource,
                                                              const=True)
                     for ofs, item in instnode.origfields.items():
                         self.nodes[item.source] = instnode.curfields[ofs]
+                    instnode.known_length = op.args[1].getint()
+                    continue
+            elif opname == 'append':
+                instnode = self.nodes[op.args[1]]
+                valuenode = self.nodes[op.args[2]]
+                ofs = instnode.known_length
+                instnode.known_length += 1
+                assert ofs != -1
+                self.optimize_setfield(instnode, ofs, valuenode, op.args[2])
+                continue
+            elif opname == 'pop':
+                instnode = self.nodes[op.args[1]]
+                instnode.known_length -= 1
+                ofs = instnode.known_length
+                if self.optimize_getfield(instnode, ofs, op.results[0]):
                     continue
+            elif opname == 'len':
+                instnode = self.nodes[op.args[1]]
+                assert instnode.known_length
+                continue
             elif opname == 'setfield_gc':
                 instnode = self.nodes[op.args[0]]
                 valuenode = self.nodes[op.args[2]]

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	Sun Feb 15 14:32:09 2009
@@ -404,7 +404,22 @@
                 args.append(ConstInt(0))
             else:
                 args.append(ConstPtr(lltype.nullptr(llmemory.GCREF.TO)))
-        op = self.execute_with_exc('newlist', args, 'ptr')
+        self.execute_with_exc('newlist', args, 'ptr')
+
+    @arguments("builtin", "varargs")
+    def opimpl_append(self, descr, varargs):
+        args = [descr.append_func] + varargs
+        self.execute_with_exc('append', args, 'void')
+
+    @arguments("builtin", "varargs")
+    def opimpl_pop(self, descr, varargs):
+        args = [descr.pop_func] + varargs
+        self.execute_with_exc('pop', args, descr.tp)
+
+    @arguments("builtin", "varargs")
+    def opimpl_len(self, descr, varargs):
+        args = [descr.len_func] + varargs
+        self.execute_with_exc('len', args, 'int')
 
     @arguments("indirectcallset", "box", "varargs")
     def opimpl_indirect_call(self, indirectcallset, box, varargs):
@@ -446,6 +461,12 @@
     def opimpl_guard_builtin(self, pc, box, builtin):
         self.generate_guard(pc, "guard_builtin", box, [builtin])
 
+    @arguments("orgpc", "box", "builtin")
+    def opimpl_guard_len(self, pc, box, builtin):
+        intbox = self.metainterp.cpu.execute_operation(
+            'len', [builtin.len_func, box], 'int')
+        self.generate_guard(pc, "guard_len", box, [intbox])
+
     @arguments("orgpc", "box", "virtualizabledesc", "int")
     def opimpl_guard_nonvirtualized(self, pc, box, vdesc, guard_field):
         clsbox = self.cls_of_box(box)

Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py	Sun Feb 15 14:32:09 2009
@@ -217,6 +217,14 @@
 
 class VirtualListSpecNode(VirtualSpecNode):
 
+    def __init__(self, known_class, fields, known_length):
+        VirtualSpecNode.__init__(self, known_class, fields)
+        self.known_length = known_length
+
+    def mutate_nodes(self, instnode):
+        VirtualSpecNode.mutate_nodes(self, instnode)
+        instnode.known_length = self.known_length
+
     def equals(self, other):
         if not isinstance(other, VirtualListSpecNode):
             return False

Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py	Sun Feb 15 14:32:09 2009
@@ -9,7 +9,7 @@
 
     def check_all_virtualized(self):
         self.check_loops(new=0, newlist=0,
-                         getitem=0, setitem=0)
+                         getitem=0, setitem=0, append=0, pop=0, len=0)
 
     def test_simple_array(self):
         jitdriver = JitDriver(greens = [], reds = ['n'])
@@ -78,9 +78,11 @@
         assert res == f(10)
         
     def test_append_pop(self):
-        py.test.skip("XXX")
+        jitdriver = JitDriver(greens = [], reds = ['n'])
         def f(n):
             while n > 0:
+                jitdriver.can_enter_jit(n=n)
+                jitdriver.jit_merge_point(n=n)
                 lst = []
                 lst.append(5)
                 lst.append(n)



More information about the Pypy-commit mailing list