Author: Maciej Fijalkowski <[email protected]>
Branch: result-in-resops
Changeset: r57559:a68b82aa7b91
Date: 2012-09-25 11:40 +0200
http://bitbucket.org/pypy/pypy/changeset/a68b82aa7b91/
Log: Carefully read values of boxes. Note that for call_pure this is
safe, because we're checking the equality of actually encountered
boxes with proven constants
diff --git a/pypy/jit/metainterp/optimizeopt/pure.py
b/pypy/jit/metainterp/optimizeopt/pure.py
--- a/pypy/jit/metainterp/optimizeopt/pure.py
+++ b/pypy/jit/metainterp/optimizeopt/pure.py
@@ -1,12 +1,12 @@
from pypy.jit.metainterp.optimizeopt.optimizer import Optimization, REMOVED
-from pypy.jit.metainterp.resoperation import rop, create_resop_2, create_resop
+from pypy.jit.metainterp.resoperation import rop, create_resop_2
from pypy.jit.metainterp.optimizeopt.util import make_dispatcher_method,\
- ArgsDict
+ ArgsSet
class OptPure(Optimization):
def __init__(self):
self.posponedop = None
- self.pure_operations = ArgsDict()
+ self.pure_operations = ArgsSet()
self.emitted_pure_operations = []
def propagate_forward(self, op):
diff --git a/pypy/jit/metainterp/optimizeopt/rewrite.py
b/pypy/jit/metainterp/optimizeopt/rewrite.py
--- a/pypy/jit/metainterp/optimizeopt/rewrite.py
+++ b/pypy/jit/metainterp/optimizeopt/rewrite.py
@@ -447,24 +447,15 @@
return False
def optimize_CALL_PURE_i(self, op):
- arg_consts = []
for i in range(op.numargs()):
arg = op.getarg(i)
const = self.get_constant_box(arg)
- if const is None:
+ if const is None or not const.eq_value(arg):
break
- arg_consts.append(const)
else:
- # all constant arguments: check if we already know the result
- try:
- result = self.optimizer.call_pure_results[arg_consts]
- except KeyError:
- pass
- else:
- # this removes a CALL_PURE with all constant arguments.
- self.make_constant(op, result)
- self.last_emitted_operation = REMOVED
- return
+ self.make_constant(op, op.constbox())
+ self.last_emitted_operation = REMOVED
+ return
self.emit_operation(op)
optimize_CALL_PURE_f = optimize_CALL_PURE_i
optimize_CALL_PURE_p = optimize_CALL_PURE_i
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
@@ -114,15 +114,15 @@
enable_opts = "intbounds:rewrite:virtualize:string:earlyforce:pure:heap"
- def optimize_loop(self, ops, optops, call_pure_results=None):
- loop = self.parse(ops)
+ def optimize_loop(self, ops, optops, results=None):
+ loop = self.parse(ops, results=results)
token = JitCellToken()
loop.operations = [create_resop(rop.LABEL, None, loop.inputargs,
descr=TargetToken(token))] + \
loop.operations
if loop.operations[-1].getopnum() == rop.JUMP:
loop.operations[-1]._descr = token
expected = convert_old_style_to_targets(self.parse(optops), jump=True)
- self._do_optimize_loop(loop, call_pure_results)
+ self._do_optimize_loop(loop)
print '\n'.join([str(o) for o in loop.operations])
self.assert_equal(loop, expected)
@@ -717,12 +717,10 @@
self.optimize_loop(ops, expected)
def test_remove_guard_no_exception_with_call_pure_on_constant_args(self):
- arg_consts = [ConstInt(i) for i in (123456, 81)]
- call_pure_results = {tuple(arg_consts): ConstInt(5)}
ops = """
[i1]
- i3 = same_as(81)
- i2 = call_pure(123456, i3, descr=nonwritedescr)
+ i3 = same_as_i(81)
+ i2 = call_pure_i(123456, i3, descr=nonwritedescr)
guard_no_exception() [i1, i2]
jump(i2)
"""
@@ -730,7 +728,7 @@
[i1]
jump(5)
"""
- self.optimize_loop(ops, expected, call_pure_results)
+ self.optimize_loop(ops, expected, results=[81, 5, None, None])
def test_remove_guard_no_exception_with_duplicated_call_pure(self):
ops = """
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_util.py
b/pypy/jit/metainterp/optimizeopt/test/test_util.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_util.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_util.py
@@ -8,7 +8,7 @@
from pypy.jit.metainterp.history import (TreeLoop, AbstractDescr,
JitCellToken, TargetToken)
from pypy.jit.metainterp.optimizeopt.util import sort_descrs, equaloplists,\
- ArgsDict
+ ArgsDict, ArgsSet
from pypy.jit.codewriter.effectinfo import EffectInfo
from pypy.jit.codewriter.heaptracker import register_known_gctype
from pypy.jit.tool.oparser import parse, pure_parse
@@ -17,7 +17,7 @@
from pypy.jit.metainterp.jitprof import EmptyProfiler
from pypy.config.pypyoption import get_pypy_config
from pypy.jit.metainterp.resoperation import rop, create_resop, BoxPtr,\
- create_resop_0, REF, INT, FLOAT
+ create_resop_0, REF, INT, FLOAT, create_resop_2, BoxInt
def test_sort_descrs():
class PseudoDescr(AbstractDescr):
@@ -71,12 +71,31 @@
"equaloplists(loop1.operations, loop3.operations)")
-def test_argsdict():
- d = ArgsDict()
+def test_argsset():
+ d = ArgsSet()
op = create_resop_0(rop.FORCE_TOKEN, 13)
assert d.get(op) is None
d.add(op)
assert d.get(op) is op
+ d2 = d.copy()
+ op2 = create_resop_2(rop.INT_ADD, 15, BoxInt(0), BoxInt(1))
+ d2.add(op2)
+ assert d2.get(op) is op
+ assert d2.get(op2) is op2
+ assert d.get(op2) is None
+
+def test_argdict():
+ d = ArgsDict()
+ op = create_resop_0(rop.FORCE_TOKEN, 13)
+ assert d.get(op) is None
+ d.set(op, 3)
+ assert d.get(op) == 3
+ d2 = d.copy()
+ op2 = create_resop_2(rop.INT_ADD, 15, BoxInt(0), BoxInt(1))
+ d2.set(op2, 5)
+ assert d2.get(op2) == 5
+ assert d2.get(op) == 3
+ assert d.get(op2) is None
# ____________________________________________________________
@@ -378,10 +397,11 @@
class BaseTest(object):
- def parse(self, s, boxkinds=None):
+ def parse(self, s, boxkinds=None, results=None):
return parse(s, self.cpu, self.namespace,
type_system=self.type_system,
- boxkinds=boxkinds)
+ boxkinds=boxkinds,
+ results=results)
def invent_fail_descr(self, model, fail_args):
xxx
@@ -402,12 +422,10 @@
assert equaloplists(optimized.operations,
expected.operations, False, remap, text_right)
- def _do_optimize_loop(self, loop, call_pure_results):
+ def _do_optimize_loop(self, loop):
from pypy.jit.metainterp.optimizeopt import optimize_trace
self.loop = loop
- if call_pure_results is not None:
- loop.call_pure_results = call_pure_results.copy()
metainterp_sd = FakeMetaInterpStaticData(self.cpu)
if hasattr(self, 'vrefinfo'):
metainterp_sd.virtualref_info = self.vrefinfo
@@ -421,7 +439,7 @@
op._rd_snapshot = resume.Snapshot(None, _sortboxes(fail_args))
optimize_trace(metainterp_sd, loop, self.enable_opts)
- def unroll_and_optimize(self, loop, call_pure_results=None):
+ def unroll_and_optimize(self, loop):
operations = loop.operations
jumpop = operations[-1]
assert jumpop.getopnum() == rop.JUMP
@@ -440,7 +458,7 @@
operations + \
[create_resop(rop.LABEL, None, jump_args,
descr=token)]
- self._do_optimize_loop(preamble, call_pure_results)
+ self._do_optimize_loop(preamble)
assert preamble.operations[-1].getopnum() == rop.LABEL
@@ -454,7 +472,7 @@
assert loop.operations[0].getopnum() == rop.LABEL
loop.inputargs = loop.operations[0].getarglist()
- self._do_optimize_loop(loop, call_pure_results)
+ self._do_optimize_loop(loop)
extra_same_as = []
while loop.operations[0].getopnum() != rop.LABEL:
extra_same_as.append(loop.operations[0])
diff --git a/pypy/jit/metainterp/optimizeopt/util.py
b/pypy/jit/metainterp/optimizeopt/util.py
--- a/pypy/jit/metainterp/optimizeopt/util.py
+++ b/pypy/jit/metainterp/optimizeopt/util.py
@@ -87,35 +87,50 @@
BUCKET_SIZE = 1024
-class ArgsDict(object):
- """ An imprecise dict. If you look it up and it's there, it's correct,
- however we don't care about collisions, so a colliding element can
- kick someone else out
- """
- def __init__(self, bucket_size=BUCKET_SIZE):
- self.buckets = [None] * bucket_size
- self.bucket_size = bucket_size - 1
+def new_args_set(has_value=False):
+ class ArgsSet(object):
+ """ An imprecise dict. If you look it up and it's there, it's correct,
+ however we don't care about collisions, so a colliding element can
+ kick someone else out
+ """
+ def __init__(self, bucket_size=BUCKET_SIZE):
+ self.buckets = [None] * bucket_size
+ if has_value:
+ self.values = [None] * bucket_size
+ self.bucket_size = bucket_size - 1
- def get(self, op):
- hash = op._get_hash_() & self.bucket_size
- candidate = self.buckets[hash]
- if candidate is None:
+ def get(self, op):
+ hash = op._get_hash_() & self.bucket_size
+ candidate = self.buckets[hash]
+ if candidate is None:
+ return None
+ if candidate.__class__ != op.__class__:
+ return None # collision
+ if op.eq(candidate):
+ if has_value:
+ return self.values[hash]
+ return candidate
return None
- if candidate.__class__ != op.__class__:
- return None # collision
- if op.eq(candidate):
- return candidate
- return None
- def add(self, op):
- hash = op._get_hash_() & self.bucket_size
- self.buckets[hash] = op # don't care about collisions
+ if has_value:
+ def set(self, op, v):
+ hash = op._get_hash_() & self.bucket_size
+ self.buckets[hash] = op # don't care about collisions
+ self.values[hash] = v
+ else:
+ def add(self, op):
+ hash = op._get_hash_() & self.bucket_size
+ self.buckets[hash] = op # don't care about collisions
- def copy(self):
- a = ArgsDict()
- a.buckets = self.buckets[:]
- return a
-
+ def copy(self):
+ a = ArgsSet()
+ a.buckets = self.buckets[:]
+ if has_value:
+ a.values = self.values[:]
+ return a
+ return ArgsSet
+ArgsSet = new_args_set()
+ArgsDict = new_args_set(True)
# ____________________________________________________________
diff --git a/pypy/jit/metainterp/resoperation.py
b/pypy/jit/metainterp/resoperation.py
--- a/pypy/jit/metainterp/resoperation.py
+++ b/pypy/jit/metainterp/resoperation.py
@@ -461,6 +461,9 @@
def getint(self):
return self.value
+ def eq_value(self, other):
+ return self.value == other.getint() # crash if incompatible type
+
def getaddr(self):
return heaptracker.int2adr(self.value)
@@ -499,6 +502,10 @@
def getfloatstorage(self):
return self.value
+ def eq_value(self, other):
+ return self.value == other.getfloatstorage()
+ # crash if incompatible type
+
def _get_hash_(self):
return longlong.gethash(self.value)
@@ -537,6 +544,10 @@
return lltype.cast_opaque_ptr(PTR, self.getref_base())
getref._annspecialcase_ = 'specialize:arg(1)'
+ def eq_value(self, other):
+ return self.value == other.getref_base()
+ # crash if incompatible type
+
def _get_hash_(self):
if self.value:
return lltype.identityhash(self.value)
@@ -826,6 +837,9 @@
def wrap_constant(intval):
return ConstInt(intval)
+ def constbox(self):
+ return ConstInt(self.intval)
+
def get_result_hash(self):
return make_hashable_int(self.intval)
@@ -853,6 +867,9 @@
def wrap_constant(floatval):
return ConstFloat(floatval)
+ def constbox(self):
+ return ConstFloat(self.floatval)
+
def get_result_hash(self):
return longlong.gethash(self.floatval)
@@ -886,6 +903,9 @@
def wrap_constant(pval):
return ConstPtr(pval)
+ def constbox(self):
+ return ConstPtr(self.pval)
+
def result_eq(self, other):
assert isinstance(other, self.__class__)
return self.pval == other.pval
@@ -990,7 +1010,9 @@
pass
@specialize.arg(1)
- def copy_and_change(self, newopnum, descr=None):
+ def copy_and_change(self, newopnum=-1, descr=None):
+ if newopnum == -1:
+ newopnum = self.getopnum()
res = create_resop_0(newopnum, self.getresult(),
descr or self.getdescr())
if self.is_guard():
@@ -1042,7 +1064,9 @@
return res
@specialize.arg(1)
- def copy_and_change(self, newopnum, arg0=None, descr=None):
+ def copy_and_change(self, newopnum=-1, arg0=None, descr=None):
+ if newopnum == -1:
+ newopnum = self.getopnum()
res = create_resop_1(newopnum, self.getresult(), arg0 or self._arg0,
descr or self.getdescr())
if self.is_guard():
@@ -1099,7 +1123,9 @@
return res
@specialize.arg(1)
- def copy_and_change(self, newopnum, arg0=None, arg1=None, descr=None):
+ def copy_and_change(self, newopnum=-1, arg0=None, arg1=None, descr=None):
+ if newopnum == -1:
+ newopnum = self.getopnum()
res = create_resop_2(newopnum, self.getresult(), arg0 or self._arg0,
arg1 or self._arg1,
descr or self.getdescr())
@@ -1161,8 +1187,10 @@
self.getdescr())
@specialize.arg(1)
- def copy_and_change(self, newopnum, arg0=None, arg1=None, arg2=None,
+ def copy_and_change(self, newopnum=-1, arg0=None, arg1=None, arg2=None,
descr=None):
+ if newopnum == -1:
+ newopnum = self.getopnum()
r = create_resop_3(newopnum, self.getresult(), arg0 or self._arg0,
arg1 or self._arg1, arg2 or self._arg2,
descr or self.getdescr())
@@ -1219,7 +1247,9 @@
newargs, self.getdescr())
@specialize.arg(1)
- def copy_and_change(self, newopnum, newargs=None, descr=None):
+ def copy_and_change(self, newopnum=-1, newargs=None, descr=None):
+ if newopnum == -1:
+ newopnum = self.getopnum()
r = create_resop(newopnum, self.getresult(),
newargs or self.getarglist(),
descr or self.getdescr())
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit