[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