Author: Hakan Ardo <[email protected]>
Branch: jit-short_from_state
Changeset: r44525:edf56e2eb1ae
Date: 2011-05-26 20:00 +0200
http://bitbucket.org/pypy/pypy/changeset/edf56e2eb1ae/
Log: Allow a VirtualState with two separate boxes to be considered a
generaltiation of a VirtualState where those two boxes are assumed
equal. Verify that the VirtualState at the end of a loop is
compatible with the VirtualState at the start of the loop which
makes it allowed to close the loop.
diff --git a/pypy/jit/metainterp/optimizeopt/optimizer.py
b/pypy/jit/metainterp/optimizeopt/optimizer.py
--- a/pypy/jit/metainterp/optimizeopt/optimizer.py
+++ b/pypy/jit/metainterp/optimizeopt/optimizer.py
@@ -40,7 +40,10 @@
if intbound:
self.intbound = intbound
else:
- self.intbound = IntBound(MININT, MAXINT) #IntUnbounded()
+ if isinstance(box, BoxInt):
+ self.intbound = IntBound(MININT, MAXINT)
+ else:
+ self.intbound = IntUnbounded()
if isinstance(box, Const):
self.make_constant(box)
diff --git a/pypy/jit/metainterp/optimizeopt/unroll.py
b/pypy/jit/metainterp/optimizeopt/unroll.py
--- a/pypy/jit/metainterp/optimizeopt/unroll.py
+++ b/pypy/jit/metainterp/optimizeopt/unroll.py
@@ -283,6 +283,7 @@
self.boxes_created_this_iteration = {}
assert jumpop
+ original_jumpargs = jumpop.getarglist()[:]
values = [self.getvalue(arg) for arg in jumpop.getarglist()]
jumpargs = virtual_state.make_inputargs(values)
jumpop.initarglist(jumpargs)
@@ -326,6 +327,18 @@
jumpop.initarglist(jumpargs)
self.optimizer.send_extra_operation(jumpop)
short.append(ResOperation(rop.JUMP, short_jumpargs, None))
+
+ modifier = VirtualStateAdder(self.optimizer)
+ final_virtual_state = modifier.get_virtual_state(original_jumpargs)
+ if not virtual_state.generalization_of(final_virtual_state):
+ # We ended up with a virtual state that is not compatible
+ # and we are thus unable to jump to the start of the loop
+ # XXX Is it possible to end up here? If so, consider:
+ # - Fallback on having the preamble jump to itself?
+ # - Would virtual_state.generate_guards make sense here?
+ debug_print("Bad virtual state at end of loop")
+ raise InvalidLoop
+
return inputargs, short_inputargs, short
def add_op_to_short(self, op, short, short_seen):
diff --git a/pypy/jit/metainterp/optimizeopt/virtualstate.py
b/pypy/jit/metainterp/optimizeopt/virtualstate.py
--- a/pypy/jit/metainterp/optimizeopt/virtualstate.py
+++ b/pypy/jit/metainterp/optimizeopt/virtualstate.py
@@ -14,12 +14,14 @@
class AbstractVirtualStateInfo(resume.AbstractVirtualInfo):
position = -1
- def generalization_of(self, other):
+ def generalization_of(self, other, renum):
raise NotImplementedError
- def generate_guards(self, other, box, cpu, extra_guards):
- if self.generalization_of(other):
+ def generate_guards(self, other, box, cpu, extra_guards, renum):
+ if self.generalization_of(other, renum):
return
+ if renum[self.position] != other.position:
+ raise InvalidLoop
self._generate_guards(other, box, cpu, extra_guards)
def _generate_guards(self, other, box, cpu, extra_guards):
@@ -42,10 +44,11 @@
def __init__(self, fielddescrs):
self.fielddescrs = fielddescrs
- def generalization_of(self, other):
+ def generalization_of(self, other, renum):
assert self.position != -1
- if self.position != other.position:
- return False
+ if self.position in renum:
+ return renum[self.position] == other.position
+ renum[self.position] = other.position
if not self._generalization_of(other):
return False
assert len(self.fielddescrs) == len(self.fieldstate)
@@ -56,7 +59,7 @@
for i in range(len(self.fielddescrs)):
if other.fielddescrs[i] is not self.fielddescrs[i]:
return False
- if not self.fieldstate[i].generalization_of(other.fieldstate[i]):
+ if not self.fieldstate[i].generalization_of(other.fieldstate[i],
renum):
return False
return True
@@ -82,7 +85,7 @@
AbstractVirtualStructStateInfo.__init__(self, fielddescrs)
self.known_class = known_class
- def _generalization_of(self, other):
+ def _generalization_of(self, other):
if not isinstance(other, VirtualStateInfo):
return False
if not self.known_class.same_constant(other.known_class):
@@ -105,16 +108,17 @@
def __init__(self, arraydescr):
self.arraydescr = arraydescr
- def generalization_of(self, other):
+ def generalization_of(self, other, renum):
assert self.position != -1
- if self.position != other.position:
- return False
+ if self.position in renum:
+ return renum[self.position] == other.position
+ renum[self.position] = other.position
if self.arraydescr is not other.arraydescr:
return False
if len(self.fieldstate) != len(other.fieldstate):
return False
for i in range(len(self.fieldstate)):
- if not self.fieldstate[i].generalization_of(other.fieldstate[i]):
+ if not self.fieldstate[i].generalization_of(other.fieldstate[i],
renum):
return False
return True
@@ -145,12 +149,13 @@
self.constbox = None
self.position_in_notvirtuals = -1
- def generalization_of(self, other):
+ def generalization_of(self, other, renum):
# XXX This will always retrace instead of forcing anything which
# might be what we want sometimes?
assert self.position != -1
- if self.position != other.position:
- return False
+ if self.position in renum:
+ return renum[self.position] == other.position
+ renum[self.position] = other.position
if not isinstance(other, NotVirtualStateInfo):
return False
if other.level < self.level:
@@ -241,16 +246,18 @@
def generalization_of(self, other):
assert len(self.state) == len(other.state)
+ renum = {}
for i in range(len(self.state)):
- if not self.state[i].generalization_of(other.state[i]):
+ if not self.state[i].generalization_of(other.state[i], renum):
return False
return True
def generate_guards(self, other, args, cpu, extra_guards):
assert len(self.state) == len(other.state) == len(args)
+ renum = {}
for i in range(len(self.state)):
self.state[i].generate_guards(other.state[i], args[i],
- cpu, extra_guards)
+ cpu, extra_guards, renum)
def make_inputargs(self, values, keyboxes=False):
assert len(values) == len(self.state)
diff --git a/pypy/jit/metainterp/test/test_ajit.py
b/pypy/jit/metainterp/test/test_ajit.py
--- a/pypy/jit/metainterp/test/test_ajit.py
+++ b/pypy/jit/metainterp/test/test_ajit.py
@@ -2387,6 +2387,28 @@
return sa
assert self.meta_interp(f, [20, 1, 2]) == f(20, 1, 2)
+ def test_args_becomming_not_equal_boxed1(self):
+ class A(object):
+ def __init__(self, a, b):
+ self.a = a
+ self.b = b
+ myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'sa', 'a', 'b',
'node'])
+
+ def f(n, a, b):
+ sa = i = 0
+ node = A(b, b)
+ while i < n:
+ myjitdriver.jit_merge_point(n=n, i=i, sa=sa, a=a, b=b,
node=node)
+ sa += node.a
+ sa *= node.b
+ if i > n/2:
+ node = A(a, b)
+ else:
+ node = A(b, b)
+ i += 1
+ return sa
+ assert self.meta_interp(f, [20, 1, 2]) == f(20, 1, 2)
+
def test_args_becomming_equal_boxed2(self):
class A(object):
def __init__(self, a, b):
diff --git a/pypy/jit/metainterp/test/test_optimizeopt.py
b/pypy/jit/metainterp/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/test/test_optimizeopt.py
@@ -1292,38 +1292,6 @@
"""
self.optimize_loop(ops, expected)
- def test_virtual_field_forced_by_later_jumpargs(self):
- # FIXME: Can that occure? How to test?!?
- ops = """
- [i0, p1, p3, p3next]
- i28 = int_add(i0, 1)
- p30 = new_with_vtable(ConstClass(node_vtable))
- setfield_gc(p30, i28, descr=nextdescr)
- i29 = int_add(i28, 1)
- p3v = new_with_vtable(ConstClass(node_vtable))
- setfield_gc(p3v, p30, descr=valuedescr)
- p45 = getfield_gc(p3next, descr=valuedescr)
- jump(i29, p45, p3next, p3v)
- """
- preamble = """
- [i0, p1, p3, p3next]
- i28 = int_add(i0, 1)
- i29 = int_add(i28, 1)
- p45 = getfield_gc(p3next, descr=valuedescr)
- jump(i29, p45, p3next, i28)
- """
- expected = """
- [i0, p1, p3, i1]
- i28 = int_add(i0, 1)
- i29 = int_add(i28, 1)
- p3v = new_with_vtable(ConstClass(node_vtable))
- p30 = new_with_vtable(ConstClass(node_vtable))
- setfield_gc(p30, i1, descr=nextdescr)
- setfield_gc(p3v, p30, descr=valuedescr)
- jump(i29, i28, p3v)
- """
- self.optimize_loop(ops, expected, preamble)
-
def test_virtual_field_forced_by_lazy_setfield(self):
ops = """
[i0, p1, p3]
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit