[pypy-svn] r60280 - in pypy/branch/oo-jit/pypy: jit/hintannotator jit/rainbow/test jit/timeshifter jit/tl jit/tl/test rpython/ootypesystem

antocuni at codespeak.net antocuni at codespeak.net
Tue Dec 2 16:01:18 CET 2008


Author: antocuni
Date: Tue Dec  2 16:01:17 2008
New Revision: 60280

Modified:
   pypy/branch/oo-jit/pypy/jit/hintannotator/policy.py
   pypy/branch/oo-jit/pypy/jit/rainbow/test/test_0tlc.py
   pypy/branch/oo-jit/pypy/jit/timeshifter/vdict.py
   pypy/branch/oo-jit/pypy/jit/tl/test/test_tlc.py
   pypy/branch/oo-jit/pypy/jit/tl/tlc.py
   pypy/branch/oo-jit/pypy/jit/tl/tlopcode.py
   pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py
Log:
(antocuni, arigo around)

implement some basic object-oriented features for tlc; whack around to fix
various bugs until we eliminate all the overhead of dynamic dispatch



Modified: pypy/branch/oo-jit/pypy/jit/hintannotator/policy.py
==============================================================================
--- pypy/branch/oo-jit/pypy/jit/hintannotator/policy.py	(original)
+++ pypy/branch/oo-jit/pypy/jit/hintannotator/policy.py	Tue Dec  2 16:01:17 2008
@@ -24,6 +24,13 @@
         return new
 
     def look_inside_graph(self, graph):
+        try:
+            func = graph.func
+        except AttributeError:
+            return True
+        # explicitly pure functions are always opaque
+        if getattr(func, '_pure_function_', False):
+            return False
         return True
 
 

Modified: pypy/branch/oo-jit/pypy/jit/rainbow/test/test_0tlc.py
==============================================================================
--- pypy/branch/oo-jit/pypy/jit/rainbow/test/test_0tlc.py	(original)
+++ pypy/branch/oo-jit/pypy/jit/rainbow/test/test_0tlc.py	Tue Dec  2 16:01:17 2008
@@ -14,16 +14,30 @@
     small = False
 
     def _get_interp(self):
-        def interp(llbytecode, pc, inputarg):
+        def decode_strlist(s):
+            lists = s.split('|')
+            return [lst.split(',') for lst in lists]
+        
+        def interp(llbytecode, pc, inputarg, llstrlists):
             from pypy.rpython.annlowlevel import hlstr
             bytecode = hlstr(llbytecode)
-            return tlc.interp_without_call(bytecode, pc, inputarg)
+            strlists = hlstr(llstrlists)
+            pool = tlc.ConstantPool()
+            pool.strlists = decode_strlist(strlists)
+            obj = tlc.interp_eval_without_call(bytecode,
+                                               pc,
+                                               tlc.IntObj(inputarg),
+                                               pool)
+            return obj.int_o()
         
         to_rstr = self.to_rstr
         def build_bytecode(s):
             result = ''.join([chr(int(t)) for t in s.split(',')])
             return to_rstr(result)
-        interp.convert_arguments = [build_bytecode, int, int]
+        def build_strlist(items):
+            lists = [','.join(lst) for lst in items]
+            return to_rstr('|'.join(lists))
+        interp.convert_arguments = [build_bytecode, int, int, build_strlist]
         
         return interp
 
@@ -38,7 +52,7 @@
         interp = self._get_interp()
         res = self.timeshift_from_portal(interp,
                                          tlc.interp_eval_without_call,
-                                         [bytecode, 0, n],
+                                         [bytecode, 0, n, []],
                                          policy=P_OOPSPEC)#, backendoptimize=True)
         assert res == expected
         self.check_insns(malloc=1)
@@ -61,10 +75,30 @@
         interp = self._get_interp()
         res = self.timeshift_from_portal(interp,
                                          tlc.interp_eval_without_call,
-                                         [bytecode, 0, 1],
+                                         [bytecode, 0, 1, []],
                                          policy=P_OOPSPEC)#, backendoptimize=True)
         assert res == 20
 
+    def test_getattr(self):
+        from pypy.jit.tl.tlc import interp_eval, nil, ConstantPool
+        pool = ConstantPool()
+        code = tlc.compile("""
+            NEW foo,bar
+            PICK 0
+            PUSH 42
+            SETATTR bar,
+            GETATTR bar,
+        """, pool)
+        bytecode = ','.join([str(ord(c)) for c in code])
+        interp = self._get_interp()
+        res = self.timeshift_from_portal(interp,
+                                         tlc.interp_eval_without_call,
+                                         [bytecode, 0, 0, pool.strlists],
+                                         policy=P_OOPSPEC)
+        assert res == 42
+        self.check_insns(malloc=1)        
+
+
 
 class TestLLType(BaseTestTLC):
     type_system = "lltype"

Modified: pypy/branch/oo-jit/pypy/jit/timeshifter/vdict.py
==============================================================================
--- pypy/branch/oo-jit/pypy/jit/timeshifter/vdict.py	(original)
+++ pypy/branch/oo-jit/pypy/jit/timeshifter/vdict.py	Tue Dec  2 16:01:17 2008
@@ -217,7 +217,8 @@
         return eq, hash # work at least for primitive types
 
     def gen_newdict(self, builder, args_gv):
-        raise NotImplementedError
+        assert len(args_gv) == 0
+        return builder.genop_new(self.alloctoken)
 
     def gen_insertclean(self, builder, args_gv):
         raise NotImplementedError
@@ -387,3 +388,12 @@
 oop_dict_method_set = oop_dict_setitem
 oop_dict_method_get = oop_dict_getitem
 oop_dict_method_contains = oop_dict_contains
+
+def oop_dict_method_length(jitstate, oopspecdesc, deepfrozen, selfbox):
+    content = selfbox.content
+    if isinstance(content, AbstractVirtualDict):
+        return rvalue.ll_fromvalue(jitstate, len(content.item_boxes))
+    else:
+        return oopspecdesc.residual_call(jitstate, [selfbox],
+                                         deepfrozen=deepfrozen)
+oop_dict_getitem.couldfold = True

Modified: pypy/branch/oo-jit/pypy/jit/tl/test/test_tlc.py
==============================================================================
--- pypy/branch/oo-jit/pypy/jit/tl/test/test_tlc.py	(original)
+++ pypy/branch/oo-jit/pypy/jit/tl/test/test_tlc.py	Tue Dec  2 16:01:17 2008
@@ -1,7 +1,16 @@
 import py
-from pypy.jit.tl.tlopcode import compile
+from pypy.jit.tl.tlopcode import compile, NEW
 from pypy.jit.tl.test import test_tl
-
+from pypy.jit.tl.tlc import ConstantPool
+    
+def test_constant_pool():
+    pool = ConstantPool()
+    bytecode = compile("""
+        NEW foo,bar
+    """, pool)
+    expected = test_tl.list2bytecode([NEW, 0])
+    assert expected == bytecode
+    assert pool.strlists == [['foo', 'bar']]
 
 class TestTLC(test_tl.TestTL):
     from pypy.jit.tl.tlc import interp
@@ -110,3 +119,39 @@
         """)
         py.test.raises(TypeError, self.interp, bytecode, 0, 0)
 
+    def test_new_obj(self):
+        from pypy.jit.tl.tlc import interp_eval, InstanceObj
+        pool = ConstantPool()
+        bytecode = compile("""
+            NEW foo,bar
+        """, pool)
+        obj = interp_eval(bytecode, 0, None, pool)
+        assert isinstance(obj, InstanceObj)
+        assert len(obj.values) == 2
+        assert sorted(obj.cls.attributes.keys()) == ['bar', 'foo']
+
+    def test_setattr(self):
+        from pypy.jit.tl.tlc import interp_eval, nil
+        pool = ConstantPool()
+        bytecode = compile("""
+            NEW foo,bar
+            PICK 0
+            PUSH 42
+            SETATTR foo,
+        """, pool)
+        obj = interp_eval(bytecode, 0, None, pool)
+        assert obj.values[0].int_o() == 42
+        assert obj.values[1] is nil
+
+    def test_getattr(self):
+        from pypy.jit.tl.tlc import interp_eval, nil
+        pool = ConstantPool()
+        bytecode = compile("""
+            NEW foo,bar
+            PICK 0
+            PUSH 42
+            SETATTR bar,
+            GETATTR bar,
+        """, pool)
+        res = interp_eval(bytecode, 0, nil, pool)
+        assert res.int_o() == 42

Modified: pypy/branch/oo-jit/pypy/jit/tl/tlc.py
==============================================================================
--- pypy/branch/oo-jit/pypy/jit/tl/tlc.py	(original)
+++ pypy/branch/oo-jit/pypy/jit/tl/tlc.py	Tue Dec  2 16:01:17 2008
@@ -5,6 +5,7 @@
 from pypy.rlib.objectmodel import specialize
 from pypy.jit.tl.tlopcode import *
 from pypy.jit.tl import tlopcode
+from pypy.rlib.jit import hint
 
 class Obj(object):
 
@@ -25,6 +26,63 @@
 
     def _concat(self, other): raise TypeError
 
+    # object oriented features
+    def getattr(self, name): raise TypeError
+    def setattr(self, name, value): raise TypeError
+
+
+class ConstantPool(object):
+
+    def __init__(self):
+        self.strlists = []
+
+    def add_strlist(self, items):
+        idx = len(self.strlists)
+        self.strlists.append(items)
+        return idx
+
+class Class(object):
+
+    classes = [] # [(attributes, cls), ...]
+
+    def get(key):
+        for attributes, cls in Class.classes:
+            if attributes == key:
+                return cls
+        result = Class(key)
+        Class.classes.append((key, result))
+        return result
+    get._pure_function_ = True
+    get = staticmethod(get)
+
+    def __init__(self, attrlist):
+        attributes = {} # attrname -> index
+        for name in attrlist:
+            attributes[name] = len(attributes)
+        self.attributes = hint(attributes, deepfreeze=True)
+        self.length = len(attributes)
+    
+class InstanceObj(Obj):
+
+    def __init__(self, cls):
+        self.cls = cls
+        cls2 = hint(cls, deepfreeze=True)
+        self.values = [nil] * cls2.length
+
+    def getclass(self):
+        # promote and deepfreeze the class
+        cls = hint(self.cls, promote=True)
+        return hint(cls, deepfreeze=True)
+
+    def getattr(self, name):
+        i = self.getclass().attributes[name]
+        return self.values[i]
+
+    def setattr(self, name, value):
+        i = self.getclass().attributes[name]
+        self.values[i] = value
+        return value
+
 class IntObj(Obj):
 
     def __init__(self, value):
@@ -126,10 +184,12 @@
             raise TypeError("code '%s' should be a string" % str(code))
         
         return interp_eval(code, pc, IntObj(inputarg)).int_o()
-    
-    def interp_eval(code, pc, inputarg):
+
+    def interp_eval(code, pc, inputarg, pool2=ConstantPool()):
         code_len = len(code)
         stack = []
+        pool3 = hint(pool2, concrete=True)
+        pool = hint(pool3, deepfreeze=True)
 
         while pc < code_len:
             hint(None, global_merge_point=True)
@@ -272,11 +332,37 @@
             elif opcode == PUSHARG:
                 stack.append(inputarg)
 
+            elif opcode == NEW:
+                idx = char2int(code[pc])
+                pc += 1
+                attributes = pool.strlists[idx]
+                cls = Class.get(attributes)
+                stack.append(InstanceObj(cls))
+
+            elif opcode == GETATTR:
+                idx = char2int(code[pc])
+                pc += 1
+                attributes = pool.strlists[idx]
+                name = attributes[0]
+                a = stack.pop()
+                hint(a, promote_class=True)
+                stack.append(a.getattr(name))
+
+            elif opcode == SETATTR:
+                idx = char2int(code[pc])
+                pc += 1
+                attributes = pool.strlists[idx]
+                name = attributes[0]
+                a, b = stack.pop(), stack.pop()
+                hint(a, promote_class=True)
+                hint(b, promote_class=True)
+                b.setattr(name, a)
+
             else:
                 raise RuntimeError("unknown opcode: " + str(opcode))
 
         return stack[-1]
-
+    
     return interp, interp_eval
 
 

Modified: pypy/branch/oo-jit/pypy/jit/tl/tlopcode.py
==============================================================================
--- pypy/branch/oo-jit/pypy/jit/tl/tlopcode.py	(original)
+++ pypy/branch/oo-jit/pypy/jit/tl/tlopcode.py	Tue Dec  2 16:01:17 2008
@@ -44,11 +44,15 @@
 opcode(26, "CAR")
 opcode(27, "CDR")
 
+# object oriented features of tlc
+opcode(28, "NEW")
+opcode(29, "GETATTR")
+opcode(30, "SETATTR")
 
 del opcode
 
 
-def compile(code=''):
+def compile(code='', pool=None):
     bytecode = []
     labels   = {}       #[key] = pc
     label_usage = []    #(name, pc)
@@ -60,15 +64,27 @@
             continue
         t = s.split()
         if t[0].endswith(':'):
+            assert ',' not in t[0]
             labels[ t[0][:-1] ] = len(bytecode)
             continue
         bytecode.append(names[t[0]])
         if len(t) > 1:
+            arg = t[1]
             try:
-                bytecode.append( int(t[1]) )
+                bytecode.append( int(arg) )
             except ValueError:
-                label_usage.append( (t[1], len(bytecode)) )
-                bytecode.append( 0 )
+                if ',' in arg:
+                    # it's a list of strings
+                    items = arg.split(',')
+                    items = map(str.strip, items)
+                    items = [x for x in items if x]
+                    assert pool is not None
+                    idx = pool.add_strlist(items)
+                    bytecode.append(idx)
+                else:
+                    # it's a label
+                    label_usage.append( (arg, len(bytecode)) )
+                    bytecode.append( 0 )
     for label, pc in label_usage:
         bytecode[pc] = labels[label] - pc - 1
     return ''.join([chr(i & 0xff) for i in bytecode])  

Modified: pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py	Tue Dec  2 16:01:17 2008
@@ -1526,6 +1526,8 @@
     def ll_length(self):
         # NOT_RPYTHON
         return len(self._list)
+    ll_length.oopargcheck = lambda a: bool(a)
+    ll_length.foldable = True
 
     def _ll_resize_ge(self, length):
         # NOT_RPYTHON        
@@ -1553,6 +1555,8 @@
         assert typeOf(index) == Signed
         assert index >= 0
         return self._list[index]
+    ll_getitem_fast.oopargcheck = lambda l, k: bool(l)
+    ll_getitem_fast.couldfold = True # XXX?
 
     def ll_setitem_fast(self, index, item):
         # NOT_RPYTHON
@@ -1607,6 +1611,8 @@
     def ll_length(self):
         # NOT_RPYTHON
         return len(self._dict)
+    ll_length.oopargcheck = lambda a: bool(a)
+    ll_length.foldable = True
 
     def ll_get(self, key):
         # NOT_RPYTHON



More information about the Pypy-commit mailing list