[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