[pypy-svn] r18762 - in pypy/dist/pypy: annotation rpython rpython/ootypesystem rpython/ootypesystem/test

arigo at codespeak.net arigo at codespeak.net
Wed Oct 19 18:27:23 CEST 2005


Author: arigo
Date: Wed Oct 19 18:27:22 2005
New Revision: 18762

Modified:
   pypy/dist/pypy/annotation/builtin.py
   pypy/dist/pypy/rpython/llinterp.py
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
   pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py
   pypy/dist/pypy/rpython/ootypesystem/rclass.py
   pypy/dist/pypy/rpython/ootypesystem/test/test_ooclean.py
   pypy/dist/pypy/rpython/rbuiltin.py
   pypy/dist/pypy/rpython/rtyper.py
Log:
ootyper:

* hash(instances), with a new built-in ootype.ooidentityhash() supported
  by the annotator and producing an operation with the same name.

* moved some ootype-specific code from rbuiltin.py to ootypesystem/rbuiltin.py

* quick fix in gendirectcall() that enables it to work in simple cases



Modified: pypy/dist/pypy/annotation/builtin.py
==============================================================================
--- pypy/dist/pypy/annotation/builtin.py	(original)
+++ pypy/dist/pypy/annotation/builtin.py	Wed Oct 19 18:27:22 2005
@@ -393,11 +393,16 @@
     assert isinstance(c, SomeOOClass)
     return SomeOOInstance(c.ootype)
 
+def ooidentityhash(i):
+    assert isinstance(i, SomeOOInstance)
+    return SomeInteger()
+
 BUILTIN_ANALYZERS[ootype.instanceof] = instanceof
 BUILTIN_ANALYZERS[ootype.new] = new
 BUILTIN_ANALYZERS[ootype.null] = null
 BUILTIN_ANALYZERS[ootype.runtimenew] = runtimenew
 BUILTIN_ANALYZERS[ootype.classof] = classof
+BUILTIN_ANALYZERS[ootype.ooidentityhash] = ooidentityhash
 
 #________________________________
 # non-gc objects

Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py	(original)
+++ pypy/dist/pypy/rpython/llinterp.py	Wed Oct 19 18:27:22 2005
@@ -670,6 +670,9 @@
     def op_subclassof(self, class1, class2):
         return ootype.subclassof(class1, class2)
 
+    def op_ooidentityhash(self, inst):
+        return ootype.ooidentityhash(inst)
+
 # by default we route all logging messages to nothingness
 # e.g. tests can then switch on logging to get more help
 # for failing tests

Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Wed Oct 19 18:27:22 2005
@@ -324,4 +324,10 @@
 def oodowncast(INSTANCE, instance):
     assert instanceof(instance, INSTANCE)
     return instance
-    
+
+def ooidentityhash(inst):
+    assert isinstance(inst, _instance)
+    if inst:
+        return id(inst)
+    else:
+        return 0   # for all null instances

Modified: pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py	Wed Oct 19 18:27:22 2005
@@ -1,11 +1,33 @@
+from pypy.annotation import model as annmodel
 from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.ootypesystem import rclass
 from pypy.objspace.flow.model import Constant
 
 
+def rtype_new(hop):
+    assert hop.args_s[0].is_constant()
+    vlist = hop.inputargs(ootype.Void)
+    return hop.genop('new', vlist,
+                     resulttype = hop.r_result.lowleveltype)
+
+def rtype_classof(hop):
+    assert isinstance(hop.args_s[0], annmodel.SomeOOInstance)
+    return hop.genop('classof', hop.args_v,
+                     resulttype = ootype.Class)
+
+def rtype_runtimenew(hop):
+    assert isinstance(hop.args_s[0], annmodel.SomeOOClass)
+    return hop.genop('runtimenew', hop.args_v,
+                     resulttype = hop.r_result.lowleveltype)
+
+def rtype_ooidentityhash(hop):
+    assert isinstance(hop.args_s[0], annmodel.SomeOOInstance)
+    return hop.genop('ooidentityhash', hop.args_v,
+                     resulttype = ootype.Signed)
+
 def rtype_builtin_isinstance(hop):
     if hop.s_result.is_constant():
-        return hop.inputconst(lltype.Bool, hop.s_result.const)
+        return hop.inputconst(ootype.Bool, hop.s_result.const)
 
     if hop.args_s[1].is_constant() and hop.args_s[1].const == list:
         if hop.args_s[0].knowntype != list:
@@ -25,4 +47,8 @@
 
 
 BUILTIN_TYPER = {}
+BUILTIN_TYPER[ootype.new] = rtype_new
+BUILTIN_TYPER[ootype.classof] = rtype_classof
+BUILTIN_TYPER[ootype.runtimenew] = rtype_runtimenew
+BUILTIN_TYPER[ootype.ooidentityhash] = rtype_ooidentityhash
 BUILTIN_TYPER[isinstance] = rtype_builtin_isinstance

Modified: pypy/dist/pypy/rpython/ootypesystem/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rclass.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rclass.py	Wed Oct 19 18:27:22 2005
@@ -87,6 +87,12 @@
                     fielddefaults[mangled] = getattr(self.classdef.cls, name)
                 except AttributeError:
                     pass
+        #
+        # hash() support
+        if self.rtyper.needs_hash_support(self.classdef.cls):
+            from pypy.rpython import rint
+            allfields['_hash_cache_'] = rint.signed_repr
+            fields['_hash_cache_'] = ootype.Signed
 
         ootype.addFields(self.lowleveltype, fields)
 
@@ -209,6 +215,19 @@
         vinst, = hop.inputargs(self)
         return hop.genop('classof', [vinst], resulttype=ootype.Class)
 
+    def rtype_hash(self, hop):
+        if self.classdef is None:
+            raise TyperError, "hash() not supported for this class"
+        if self.rtyper.needs_hash_support(self.classdef.cls):
+            vinst, = hop.inputargs(self)
+            return hop.gendirectcall(ll_inst_hash, vinst)
+        else:
+            return self.baserepr.rtype_hash(hop)
+
+    def rtype_id(self, hop):
+        vinst, = hop.inputargs(self)
+        return hop.genop('ooidentityhash', [vinst], resulttype=ootype.Signed)
+
     def convert_const(self, value):
         if value is None:
             return ootype.null(self.lowleveltype)
@@ -246,12 +265,12 @@
     def initialize_prebuilt_instance(self, value, result):
         # then add instance attributes from this level
         for mangled, (oot, default) in self.lowleveltype._allfields().items():
-            name = unmangle(mangled)
             if oot is ootype.Void:
                 llattrvalue = None
-            elif name == '_hash_cache_': # hash() support
+            elif mangled == '_hash_cache_': # hash() support
                 llattrvalue = hash(value)
             else:
+                name = unmangle(mangled)
                 try:
                     attrvalue = getattr(value, name)
                 except AttributeError:
@@ -294,3 +313,10 @@
     def rtype_ne(rpair, hop):
         v = rpair.rtype_eq(hop)
         return hop.genop("bool_not", [v], resulttype=ootype.Bool)
+
+
+def ll_inst_hash(ins):
+    cached = ins._hash_cache_
+    if cached == 0:
+        cached = ins._hash_cache_ = ootype.ooidentityhash(ins)
+    return cached

Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_ooclean.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/test/test_ooclean.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_ooclean.py	Wed Oct 19 18:27:22 2005
@@ -436,3 +436,27 @@
     assert res == ~0x0100 & 0x3ff
     res = interpret(f, [3], type_system='ootype')
     assert res == ~0x0200 & 0x3ff
+
+def test_hash_preservation():
+    class C:
+        pass
+    class D(C):
+        pass
+    def f1():
+        d2 = D()
+        # xxx we assume that the identityhash doesn't change from
+        #     one line to the next
+        current_identityhash = id(d2)
+        instance_hash = hash(d2)
+        return current_identityhash == instance_hash
+    res = interpret(f1, [], type_system='ootype')
+    assert res is True
+
+    c = C()
+    d = D()
+    def f2(): return hash(c)
+    def f3(): return hash(d)
+    res = interpret(f2, [], type_system='ootype')
+    assert res == hash(c)
+    res = interpret(f3, [], type_system='ootype')
+    assert res == hash(d)

Modified: pypy/dist/pypy/rpython/rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/rbuiltin.py	(original)
+++ pypy/dist/pypy/rpython/rbuiltin.py	Wed Oct 19 18:27:22 2005
@@ -11,7 +11,6 @@
 from pypy.rpython.rbool import bool_repr
 from pypy.rpython.rdict import rtype_r_dict
 from pypy.tool import sourcetools
-from pypy.rpython.ootypesystem import ootype
 
 class __extend__(annmodel.SomeBuiltin):
     def rtyper_makerepr(self, rtyper):
@@ -265,22 +264,6 @@
     return hop.genop('runtime_type_info', vlist,
                  resulttype = rptr.PtrRepr(lltype.Ptr(lltype.RuntimeTypeInfo)))
 
-def rtype_new(hop):
-    assert hop.args_s[0].is_constant()
-    vlist = hop.inputargs(lltype.Void)
-    return hop.genop('new', vlist,
-                     resulttype = hop.r_result.lowleveltype)
-
-def rtype_classof(hop):
-    assert isinstance(hop.args_s[0], annmodel.SomeOOInstance)
-    return hop.genop('classof', hop.args_v,
-                     resulttype = ootype.Class)
-
-def rtype_runtimenew(hop):
-    assert isinstance(hop.args_s[0], annmodel.SomeOOClass)
-    return hop.genop('runtimenew', hop.args_v,
-                     resulttype = hop.r_result.lowleveltype)
-
 BUILTIN_TYPER[lltype.malloc] = rtype_malloc
 BUILTIN_TYPER[lltype.cast_pointer] = rtype_cast_pointer
 BUILTIN_TYPER[lltype.cast_ptr_to_int] = rtype_cast_ptr_to_int
@@ -294,9 +277,6 @@
 BUILTIN_TYPER[objectmodel.we_are_translated] = rtype_we_are_translated
 
 BUILTIN_TYPER[objectmodel.hlinvoke] = rtype_hlinvoke
-BUILTIN_TYPER[ootype.new] = rtype_new
-BUILTIN_TYPER[ootype.classof] = rtype_classof
-BUILTIN_TYPER[ootype.runtimenew] = rtype_runtimenew
 
 from pypy.rpython import extfunctable
 

Modified: pypy/dist/pypy/rpython/rtyper.py
==============================================================================
--- pypy/dist/pypy/rpython/rtyper.py	(original)
+++ pypy/dist/pypy/rpython/rtyper.py	Wed Oct 19 18:27:22 2005
@@ -775,8 +775,9 @@
         # build the 'direct_call' operation
         f = self.rtyper.getfunctionptr(spec_function)
         c = inputconst(typeOf(f), f)
+        fobj = self.rtyper.type_system_deref(f)
         return self.genop('direct_call', [c]+newargs_v,
-                          resulttype = typeOf(f).TO.RESULT)
+                          resulttype = typeOf(fobj).RESULT)
 
     def genexternalcall(self, fnname, args_v, resulttype=None, **flags):
         if isinstance(resulttype, Repr):



More information about the Pypy-commit mailing list