[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