[pypy-svn] r66459 - in pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp: . test
arigo at codespeak.net
arigo at codespeak.net
Mon Jul 20 22:57:22 CEST 2009
Author: arigo
Date: Mon Jul 20 22:57:21 2009
New Revision: 66459
Modified:
pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/optimizeopt.py
pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/test/test_optimizeopt.py
Log:
In-progress: refactoring the data model.
Modified: pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/optimizeopt.py
==============================================================================
--- pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/optimizeopt.py (original)
+++ pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/optimizeopt.py Mon Jul 20 22:57:21 2009
@@ -1,6 +1,6 @@
from pypy.jit.metainterp.history import Const, Box, BoxInt, BoxPtr, BoxObj
from pypy.jit.metainterp import history
-from pypy.jit.metainterp.resoperation import rop
+from pypy.jit.metainterp.resoperation import rop, ResOperation
from pypy.jit.metainterp.specnode import SpecNode
from pypy.jit.metainterp.specnode import VirtualInstanceSpecNode
from pypy.jit.metainterp.optimizeutil import av_newdict, _findall
@@ -19,12 +19,84 @@
# ____________________________________________________________
-class VirtualBox(history.AbstractValue):
- def __init__(self):
- self.fields = av_newdict() # ofs -> Box
+LEVEL_UNKNOWN = 0
+LEVEL_NONNULL = 1
+LEVEL_KNOWNCLASS = 2
+LEVEL_CONSTANT = 3
+
+
+class InstanceValue(object):
+ level = LEVEL_UNKNOWN
+
+ def __init__(self, box):
+ self.box = box
+ if isinstance(box, Const):
+ self.level = LEVEL_CONSTANT
+
+ def force_box(self):
+ return self.box
+
+ def is_constant(self):
+ return self.level == LEVEL_CONSTANT
+
+ def is_null(self):
+ return self.is_constant() and not self.box.nonnull()
+
+ def make_constant(self):
+ """Mark 'self' as actually representing a Const value."""
+ self.box = self.force_box().constbox()
+ self.level = LEVEL_CONSTANT
+
+ def has_constant_class(self):
+ return self.level >= LEVEL_KNOWNCLASS
+
+ def make_constant_class(self):
+ if self.level < LEVEL_KNOWNCLASS:
+ self.level = LEVEL_KNOWNCLASS
+
+ def is_nonnull(self):
+ level = self.level
+ if level == LEVEL_NONNULL or level == LEVEL_KNOWNCLASS:
+ return True
+ elif level == LEVEL_CONSTANT:
+ return self.box.nonnull()
+ else:
+ return False
+
+ def make_nonnull(self):
+ if self.level < LEVEL_NONNULL:
+ self.level = LEVEL_NONNULL
+
+ def is_virtual(self):
+ return self.box is None
+
+
+class ConstantValue(InstanceValue):
+ level = LEVEL_CONSTANT
+
+ def __init__(self, box):
+ self.box = box
+
+
+class VirtualValue(InstanceValue):
+ box = None
+ level = LEVEL_KNOWNCLASS
+
+ def __init__(self, optimizer):
+ self.optimizer = optimizer
+ self._fields = av_newdict()
- def nonnull(self):
- return True
+ def getfield(self, ofs):
+ return self._fields[ofs]
+
+ def setfield(self, ofs, fieldvalue):
+ self._fields[ofs] = fieldvalue
+
+ def force_box(self):
+ if self.box is None:
+ optimizer = self.optimizer
+ xxxx
+ return self.box
class __extend__(SpecNode):
@@ -35,18 +107,19 @@
class __extend__(VirtualInstanceSpecNode):
def setup_virtual_node(self, optimizer, box, newinputargs):
+ import py; py.test.skip("in-progress")
vbox = optimizer.make_virtual(box, self.known_class)
for ofs, subspecnode in self.fields:
- subbox = optimizer.make_box(ofs)
+ subbox = optimizer.new_box(ofs)
vbox.fields[ofs] = subbox
subspecnode.setup_virtual_node(optimizer, subbox, newinputargs)
def teardown_virtual_node(self, optimizer, box, newexitargs):
- assert isinstance(box, VirtualBox)
+ assert isinstance(box, VirtualBox) and box.escaped_to is None
for ofs, subspecnode in self.fields:
try:
subbox = box.fields[ofs]
except KeyError:
- subbox = optimizer.make_const(ofs)
+ subbox = optimizer.new_const(ofs)
subspecnode.teardown_virtual_node(optimizer, subbox, newexitargs)
@@ -55,53 +128,34 @@
def __init__(self, cpu, loop):
self.cpu = cpu
self.loop = loop
- # Boxes used a keys to _equals have been proven to be equal to
- # something else: another Box, a Const, or a VirtualBox. Boxes
- # and VirtualBoxes can also be listed in _known_classes if we
- # know their class (or just know that they are non-null, in which
- # case we use None). Boxes *must not* be keys in both dicts.
- self._equals = {} # mapping Box -> Box/Const/VirtualBox
- self._known_classes = {} # mapping Box -> ConstClass/None
-
- def deref(self, box):
- """Maps a Box/Const to the corresponding Box/Const/VirtualBox
- by following the dict _equals.
- """
- box = self._equals.get(box, box)
- assert box not in self._equals
- return box
-
- def _make_equal(self, box, box2):
- assert isinstance(box, Box)
- assert box not in self._equals
- assert box not in self._known_classes
- self._equals[box] = box2
+ self.values = {}
+
+ def getvalue(self, box):
+ try:
+ value = self.values[box]
+ except KeyError:
+ value = self.values[box] = InstanceValue(box)
+ return value
+
+ def is_constant(self, box):
+ if isinstance(box, Const):
+ return True
+ try:
+ return self.values[box].is_constant()
+ except KeyError:
+ return False
+
+ def make_equal_to(self, box, value):
+ assert box not in self.values
+ self.values[box] = value
def make_constant(self, box):
- """Mark the given Box as actually representing a Const value."""
- self._make_equal(box, box.constbox())
+ self.make_equal_to(box, ConstantValue(box.constbox()))
- def make_virtual(self, box, clsbox):
- """Mark the given Box as actually representing a VirtualBox value."""
- vbox = VirtualBox()
- self._make_equal(box, vbox)
- self.make_constant_class(vbox, clsbox)
- return vbox
-
- def has_constant_class(self, box):
- return (isinstance(box, Const) or
- self._known_classes.get(box, None) is not None)
-
- def make_constant_class(self, box, clsbox):
- assert isinstance(clsbox, Const)
- assert box not in self._equals
- self._known_classes[box] = clsbox
-
- def make_nonnull(self, box):
- assert box not in self._equals
- self._known_classes.setdefault(box, None)
+ def known_nonnull(self, box):
+ return self.getvalue(box).is_nonnull()
- def make_box(self, fieldofs):
+ def new_box(self, fieldofs):
if fieldofs.is_pointer_field():
if not self.cpu.is_oo:
return BoxPtr()
@@ -110,7 +164,7 @@
else:
return BoxInt()
- def make_const(self, fieldofs):
+ def new_const(self, fieldofs):
if fieldofs.is_pointer_field():
if not self.cpu.is_oo:
return history.CONST_NULL
@@ -119,12 +173,6 @@
else:
return history.CONST_FALSE
- def known_nonnull(self, box):
- if isinstance(box, Box):
- return box in self._known_classes
- else:
- return box.nonnull() # Consts or VirtualBoxes
-
# ----------
def setup_virtuals(self):
@@ -141,26 +189,32 @@
def propagate_forward(self):
self.newoperations = []
for op in self.loop.operations:
- op2 = op.clone()
- op2.args = [self.deref(box) for box in op.args]
- opnum = op2.opnum
+ opnum = op.opnum
for value, func in optimize_ops:
if opnum == value:
- func(self, op2)
+ func(self, op)
break
else:
- self.optimize_default(op2)
+ self.optimize_default(op)
self.loop.operations = self.newoperations
def emit_operation(self, op):
- for x in op.args:
- assert not isinstance(x, VirtualBox)
+ must_clone = True
+ for i in range(len(op.args)):
+ arg = op.args[i]
+ if arg in self.values:
+ box = self.values[arg].force_box()
+ if box is not arg:
+ if must_clone:
+ op = op.clone()
+ must_clone = False
+ op.args[i] = box
self.newoperations.append(op)
def optimize_default(self, op):
if op.is_always_pure():
- for box in op.args:
- if not isinstance(box, Const):
+ for arg in op.args:
+ if not self.is_constant(arg):
break
else:
# all constant arguments: constant-fold away
@@ -169,7 +223,7 @@
# otherwise, the operation remains
self.emit_operation(op)
- def optimize_JUMP(self, op):
+ def XXX_optimize_JUMP(self, op):
orgop = self.loop.operations[-1]
exitargs = []
specnodes = orgop.jump_target.specnodes
@@ -177,34 +231,34 @@
for i in range(len(specnodes)):
specnodes[i].teardown_virtual_node(self, op.args[i], exitargs)
op.args = exitargs
+ #XXX return op
+
+ def optimize_guard(self, op):
+ value = self.getvalue(op.args[0])
+ if value.is_constant():
+ return
self.emit_operation(op)
+ value.make_constant()
def optimize_GUARD_VALUE(self, op):
assert isinstance(op.args[1], Const)
- assert op.args[0].get_() == op.args[1].get_()
- if not isinstance(op.args[0], Const):
- self.emit_operation(op)
- self.make_constant(op.args[0])
+ self.optimize_guard(op)
def optimize_GUARD_TRUE(self, op):
assert op.args[0].getint()
- if not isinstance(op.args[0], Const):
- self.emit_operation(op)
- self.make_constant(op.args[0])
+ self.optimize_guard(op)
def optimize_GUARD_FALSE(self, op):
assert not op.args[0].getint()
- if not isinstance(op.args[0], Const):
- self.emit_operation(op)
- self.make_constant(op.args[0])
+ self.optimize_guard(op)
def optimize_GUARD_CLASS(self, op):
- instbox = op.args[0]
- clsbox = op.args[1]
# XXX should probably assert that the class is right
- if not self.has_constant_class(instbox):
- self.emit_operation(op)
- self.make_constant_class(instbox, clsbox)
+ value = self.getvalue(op.args[0])
+ if value.has_constant_class():
+ return
+ self.emit_operation(op)
+ value.make_constant_class()
def optimize_OONONNULL(self, op):
if self.known_nonnull(op.args[0]):
@@ -221,56 +275,56 @@
self.optimize_default(op)
def optimize_OOISNOT(self, op):
- if (isinstance(op.args[0], VirtualBox) or
- isinstance(op.args[1], VirtualBox)):
+ value0 = self.getvalue(op.args[0])
+ value1 = self.getvalue(op.args[1])
+ if value0.is_virtual() or value1.is_virtual():
self.make_constant(op.result)
- elif self.known_nonnull(op.args[1]):
- op.opnum = rop.OONONNULL
- del op.args[1]
+ elif value1.is_null():
+ op = ResOperation(rop.OONONNULL, [op.args[0]], op.result)
self.optimize_OONONNULL(op)
- elif self.known_nonnull(op.args[0]):
- op.opnum = rop.OONONNULL
- del op.args[0]
+ elif value0.is_null():
+ op = ResOperation(rop.OONONNULL, [op.args[1]], op.result)
self.optimize_OONONNULL(op)
else:
self.optimize_default(op)
def optimize_OOIS(self, op):
- if (isinstance(op.args[0], VirtualBox) or
- isinstance(op.args[1], VirtualBox)):
+ value0 = self.getvalue(op.args[0])
+ value1 = self.getvalue(op.args[1])
+ if value0.is_virtual() or value1.is_virtual():
self.make_constant(op.result)
- elif self.known_nonnull(op.args[1]):
- op.opnum = rop.OOISNULL
- del op.args[1]
+ elif value1.is_null():
+ op = ResOperation(rop.OOISNULL, [op.args[0]], op.result)
self.optimize_OOISNULL(op)
- elif self.known_nonnull(op.args[0]):
- op.opnum = rop.OOISNULL
- del op.args[0]
+ elif value0.is_null():
+ op = ResOperation(rop.OOISNULL, [op.args[1]], op.result)
self.optimize_OOISNULL(op)
else:
self.optimize_default(op)
def optimize_GETFIELD_GC(self, op):
- instbox = op.args[0]
- if isinstance(instbox, VirtualBox):
- # optimizefindnode should ensure that 'op.descr in instbox.fields'
- self._make_equal(op.result, instbox.fields[op.descr])
+ value = self.getvalue(op.args[0])
+ if value.is_virtual():
+ # optimizefindnode should ensure that we don't get a KeyError
+ fieldvalue = value.getfield(op.descr)
+ self.make_equal_to(op.result, fieldvalue)
else:
- self.make_nonnull(instbox)
+ value.make_nonnull()
self.optimize_default(op)
- optimize_GETFIELD_PURE_GC = optimize_GETFIELD_GC
+ def optimize_GETFIELD_PURE_GC(self, op):
+ xxx # optimize_GETFIELD_GC
def optimize_SETFIELD_GC(self, op):
- instbox = op.args[0]
- if isinstance(instbox, VirtualBox):
- instbox.fields[op.descr] = op.args[1]
+ value = self.getvalue(op.args[0])
+ if value.is_virtual():
+ value.setfield(op.descr, self.getvalue(op.args[1]))
else:
- self.make_nonnull(instbox)
+ value.make_nonnull()
self.optimize_default(op)
def optimize_NEW_WITH_VTABLE(self, op):
- self.make_virtual(op.result, op.args[0])
+ import py; py.test.skip("in-progress")
optimize_ops = _findall(Optimizer, 'optimize_')
Modified: pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/test/test_optimizeopt.py
==============================================================================
--- pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/test/test_optimizeopt.py (original)
+++ pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/test/test_optimizeopt.py Mon Jul 20 22:57:21 2009
@@ -400,6 +400,57 @@
self.optimize_loop(ops, 'Virtual(node_vtable, valuedescr=Not)',
expected)
+ def test_virtual_3(self):
+ ops = """
+ [i]
+ p1 = new_with_vtable(ConstClass(node_vtable), descr=nodesize)
+ setfield_gc(p1, i, descr=valuedescr)
+ i0 = getfield_gc(p1, descr=valuedescr)
+ i1 = int_add(i0, 1)
+ jump(i1)
+ """
+ expected = """
+ [i]
+ i1 = int_add(i, 1)
+ jump(i1)
+ """
+ self.optimize_loop(ops, 'Not', expected)
+
+ def test_nonvirtual_1(self):
+ ops = """
+ [i]
+ p1 = new_with_vtable(ConstClass(node_vtable), descr=nodesize)
+ setfield_gc(p1, i, descr=valuedescr)
+ i0 = getfield_gc(p1, descr=valuedescr)
+ i1 = int_add(i0, 1)
+ escape(p1)
+ escape(p1)
+ jump(i1)
+ """
+ expected = """
+ [i]
+ i1 = int_add(i, 1)
+ p9 = new_with_vtable(ConstClass(node_vtable), descr=nodesize)
+ setfield_gc(p9, i, descr=valuedescr)
+ escape(p9)
+ escape(p9)
+ jump(i1)
+ """
+ self.optimize_loop(ops, 'Not', expected)
+
+ def test_nonvirtual_2(self):
+ ops = """
+ [i, p0]
+ i0 = getfield_gc(p0, descr=valuedescr)
+ escape(p0)
+ i1 = int_add(i0, i)
+ p1 = new_with_vtable(ConstClass(node_vtable), descr=nodesize)
+ setfield_gc(p1, i1, descr=valuedescr)
+ jump(i, p1)
+ """
+ expected = ops
+ self.optimize_loop(ops, 'Not, Not', expected)
+
class TestLLtype(BaseTestOptimizeOpt, LLtypeMixin):
pass
More information about the Pypy-commit
mailing list