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

Reply via email to