Author: Maciej Fijalkowski <[email protected]>
Branch: result-in-resops
Changeset: r57402:777e6f776800
Date: 2012-09-20 14:31 +0200
http://bitbucket.org/pypy/pypy/changeset/777e6f776800/
Log: hashes on resops
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
@@ -170,13 +170,13 @@
x = op1.getarg(i)
y = op2.getarg(i)
assert x.same_box(remap.get(y, y))
- if op2.result in remap:
- if op2.result is None:
- assert op1.result == remap[op2.result]
+ if op2 in remap:
+ if op2 is None:
+ assert op1 == remap[op2]
else:
- assert op1.result.same_box(remap[op2.result])
+ assert op1.same_box(remap[op2])
else:
- remap[op2.result] = op1.result
+ remap[op2] = op1
if op1.getopnum() not in (rop.JUMP, rop.LABEL): # xxx obscure
assert op1.getdescr() == op2.getdescr()
if op1.getfailargs() or op2.getfailargs():
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
@@ -5,7 +5,7 @@
from pypy.rlib.objectmodel import compute_identity_hash, newlist_hint,\
compute_unique_id, Symbolic
from pypy.jit.codewriter import heaptracker
-from pypy.rlib.rarithmetic import is_valid_int
+from pypy.rlib.rarithmetic import is_valid_int, intmask
INT = 'i'
REF = 'r'
@@ -552,6 +552,7 @@
# debug
name = ""
pc = 0
+ _hash = 0
opnum = 0
DOCUMENTED_KEYS = {
@@ -595,6 +596,20 @@
return object.__hash__(self)
raise Exception("Should not hash resops, use get/set extra instead")
+ def _get_hash_(self):
+ # rpython level implementation of hash, cache it because computations
+ # depending on the arguments might be a little tricky
+ if self._hash != 0:
+ return self._hash
+ hash = (intmask(self.getopnum() << 18) +
+ intmask(self.get_result_hash() << 13) +
+ intmask(self.get_descr_hash() << 5) +
+ self.get_arg_hash())
+ if hash == 0:
+ hash = -1
+ self._hash = hash
+ return hash
+
# methods implemented by the arity mixins
# ---------------------------------------
@@ -742,6 +757,9 @@
def getresultrepr(self):
return None
+ def get_result_hash(self):
+ return 0
+
class ResOpInt(object):
_mixin_ = True
type = INT
@@ -761,6 +779,9 @@
def wrap_constant(intval):
return ConstInt(intval)
+ def get_result_hash(self):
+ return make_hashable_int(self.intval)
+
class ResOpFloat(object):
_mixin_ = True
type = FLOAT
@@ -781,6 +802,9 @@
def wrap_constant(floatval):
return ConstFloat(floatval)
+ def get_result_hash(self):
+ return longlong.gethash(self.floatval)
+
class ResOpPointer(object):
_mixin_ = True
type = REF
@@ -797,6 +821,12 @@
# XXX what do we want to put in here?
return str(self.pval)
+ def get_result_hash(self):
+ if self.pval:
+ return lltype.identityhash(self.pval)
+ else:
+ return 0
+
@staticmethod
def wrap_constant(pval):
return ConstPtr(pval)
@@ -806,7 +836,8 @@
# ===================
class PlainResOp(AbstractResOp):
- pass
+ def get_descr_hash(self):
+ return 0
class ResOpWithDescr(AbstractResOp):
@@ -835,6 +866,8 @@
from pypy.jit.metainterp.history import check_descr
check_descr(descr)
+ def get_descr_hash(self):
+ return self._descr._get_hash_()
class GuardResOp(ResOpWithDescr):
@@ -880,7 +913,7 @@
raise IndexError
def foreach_arg(self, func):
- pass
+ pass
@specialize.arg(1)
def copy_and_change(self, newopnum, descr=None):
@@ -890,6 +923,9 @@
def copy_if_modified_by_optimization(self, opt):
return self
+ def get_arg_hash(self):
+ return 0
+
class UnaryOp(object):
_mixin_ = True
_arg0 = None
@@ -929,6 +965,9 @@
return create_resop_1(newopnum, self.getresult(), arg0 or self._arg0,
descr or self.getdescr())
+ def get_arg_hash(self):
+ return self._arg0._get_hash_()
+
class BinaryOp(object):
_mixin_ = True
_arg0 = None
@@ -976,6 +1015,10 @@
arg1 or self._arg1,
descr or self.getdescr())
+ def get_arg_hash(self):
+ return (intmask(self._arg0._get_hash_() << 16) +
+ self._arg1._get_hash_())
+
class TernaryOp(object):
_mixin_ = True
_arg0 = None
@@ -1033,6 +1076,11 @@
assert not r.is_guard()
return r
+ def get_arg_hash(self):
+ return (intmask(self._arg0._get_hash_() << 24) +
+ intmask(self._arg1._get_hash_() << 16) +
+ self._arg2._get_hash_())
+
class N_aryOp(object):
_mixin_ = True
_args = None
@@ -1083,6 +1131,12 @@
assert not r.is_guard()
return r
+ def get_arg_hash(self):
+ hash = 0
+ for i, arg in enumerate(self._args):
+ hash += intmask(arg._get_hash_() << (i & 15))
+ return hash
+
# ____________________________________________________________
_oplist = [
diff --git a/pypy/jit/metainterp/test/test_resoperation.py
b/pypy/jit/metainterp/test/test_resoperation.py
--- a/pypy/jit/metainterp/test/test_resoperation.py
+++ b/pypy/jit/metainterp/test/test_resoperation.py
@@ -1,6 +1,7 @@
import py
from pypy.jit.metainterp import resoperation as rop
from pypy.jit.metainterp.history import AbstractDescr
+from pypy.rpython.lltypesystem import lltype, llmemory
class FakeBox(object):
def __init__(self, v):
@@ -27,6 +28,9 @@
def __repr__(self):
return 'descr'
+ def _get_hash_(self):
+ return id(self)
+
def test_arity_mixins():
cases = [
(0, rop.NullaryOp),
@@ -186,3 +190,52 @@
op = rop.create_resop_2(rop.rop.INT_ADD, 3, FakeBox("a"), FakeBox("b"))
op.set_extra("failargs", 2)
assert op.get_extra("failargs") == 2
+
+def test_hashes():
+ arg1 = rop.create_resop_1(rop.rop.FLOAT_NEG, 12.5, rop.BoxFloat(3.5))
+ op = rop.create_resop_2(rop.rop.FLOAT_ADD, 13.5, rop.ConstFloat(3.0),
+ arg1)
+ op1 = rop.create_resop_2(rop.rop.FLOAT_ADD, 13.5, rop.ConstFloat(3.0),
+ rop.ConstFloat(1.0))
+ op2 = rop.create_resop_2(rop.rop.FLOAT_ADD, 13.5, rop.ConstFloat(2.0),
+ arg1)
+ op3 = rop.create_resop_2(rop.rop.FLOAT_ADD, 13.2, rop.ConstFloat(3.0),
+ arg1)
+ assert op1._get_hash_() != op._get_hash_()
+ assert op2._get_hash_() != op._get_hash_()
+ assert op3._get_hash_() != op._get_hash_()
+
+ op = rop.create_resop_0(rop.rop.FORCE_TOKEN, 13)
+ op1 = rop.create_resop_0(rop.rop.FORCE_TOKEN, 15)
+ assert op._get_hash_() != op1._get_hash_()
+ S = lltype.GcStruct('S')
+ s = lltype.malloc(S)
+ nonnull_ref = lltype.cast_opaque_ptr(llmemory.GCREF, s)
+ nullref = lltype.nullptr(llmemory.GCREF.TO)
+ op = rop.create_resop_1(rop.rop.NEWSTR, nullref, rop.BoxInt(5))
+ op1 = rop.create_resop_1(rop.rop.NEWSTR, nonnull_ref, rop.BoxInt(5))
+ assert op._get_hash_() != op1._get_hash_()
+ op = rop.create_resop_1(rop.rop.NEWSTR, nullref, rop.BoxInt(5))
+ op1 = rop.create_resop_1(rop.rop.NEWSTR, nullref, rop.BoxInt(15))
+ assert op._get_hash_() != op1._get_hash_()
+
+ descr = FakeDescr()
+ descr2 = FakeDescr()
+ op = rop.create_resop(rop.rop.CALL_i, 12, [rop.BoxInt(0),
rop.BoxFloat(2.0),
+ rop.BoxPtr(nullref)], descr)
+ op1 = rop.create_resop(rop.rop.CALL_i, 12, [rop.BoxInt(0),
+ rop.BoxFloat(2.0),
+ rop.BoxPtr(nullref)], descr2)
+ op2 = rop.create_resop(rop.rop.CALL_i, 12, [rop.BoxInt(0),
+ rop.BoxFloat(2.5),
+ rop.BoxPtr(nullref)], descr)
+ op3 = rop.create_resop(rop.rop.CALL_i, 15, [rop.BoxInt(0),
+ rop.BoxFloat(2.0),
+ rop.BoxPtr(nullref)], descr)
+ op4 = rop.create_resop(rop.rop.CALL_i, 12, [rop.BoxInt(0),
+ rop.BoxFloat(2.0),
+ rop.BoxPtr(nonnull_ref)],
descr)
+ assert op1._get_hash_() != op._get_hash_()
+ assert op2._get_hash_() != op._get_hash_()
+ assert op3._get_hash_() != op._get_hash_()
+ assert op4._get_hash_() != op._get_hash_()
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit