[pypy-commit] pypy jit-targets: hg merge jit-refactor-tests

hakanardo noreply at buildbot.pypy.org
Sat Nov 26 13:09:13 CET 2011


Author: Hakan Ardo <hakan at debian.org>
Branch: jit-targets
Changeset: r49813:9a9928f8d64d
Date: 2011-11-26 13:08 +0100
http://bitbucket.org/pypy/pypy/changeset/9a9928f8d64d/

Log:	hg merge jit-refactor-tests

diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -188,6 +188,12 @@
 
     # -------------------------------------------------------------------
 
+    def is_w(self, space, w_other):
+        return self is w_other
+
+    def id(self, space):
+        return space.wrap(compute_unique_id(self))
+
     def str_w(self, space):
         w_msg = typed_unwrap_error_msg(space, "string", self)
         raise OperationError(space.w_TypeError, w_msg)
@@ -681,9 +687,17 @@
         """shortcut for space.is_true(space.eq(w_obj1, w_obj2))"""
         return self.is_w(w_obj1, w_obj2) or self.is_true(self.eq(w_obj1, w_obj2))
 
-    def is_w(self, w_obj1, w_obj2):
-        """shortcut for space.is_true(space.is_(w_obj1, w_obj2))"""
-        return self.is_true(self.is_(w_obj1, w_obj2))
+    def is_(self, w_one, w_two):
+        return self.newbool(self.is_w(w_one, w_two))
+
+    def is_w(self, w_one, w_two):
+        # done by a method call on w_two (and not on w_one, because of the
+        # expected programming style where we say "if x is None" or
+        # "if x is object").
+        return w_two.is_w(self, w_one)
+
+    def id(self, w_obj):
+        return w_obj.id(self)
 
     def hash_w(self, w_obj):
         """shortcut for space.int_w(space.hash(w_obj))"""
@@ -1023,9 +1037,6 @@
     def isinstance_w(self, w_obj, w_type):
         return self.is_true(self.isinstance(w_obj, w_type))
 
-    def id(self, w_obj):
-        return self.wrap(compute_unique_id(w_obj))
-
     # The code below only works
     # for the simple case (new-style instance).
     # These methods are patched with the full logic by the __builtin__
diff --git a/pypy/jit/metainterp/test/support.py b/pypy/jit/metainterp/test/support.py
--- a/pypy/jit/metainterp/test/support.py
+++ b/pypy/jit/metainterp/test/support.py
@@ -158,9 +158,6 @@
         get_stats().check_resops(expected=expected, **check)
 
     
-    def check_loops(self, expected=None, everywhere=False, **check):
-        get_stats().check_loops(expected=expected, everywhere=everywhere,
-                                **check)        
 
     def check_trace_count(self, count): # was check_loop_count
         # The number of traces compiled
diff --git a/pypy/jit/metainterp/test/test_fficall.py b/pypy/jit/metainterp/test/test_fficall.py
--- a/pypy/jit/metainterp/test/test_fficall.py
+++ b/pypy/jit/metainterp/test/test_fficall.py
@@ -76,14 +76,14 @@
                 int_add=2,
                 int_lt=2,
                 guard_true=2,
-                jump=1)
+                jump=2)
         else:
             self.check_resops(
                 call_release_gil=0,   # no CALL_RELEASE_GIL
                 int_add=2,
                 int_lt=2,
                 guard_true=2,
-                jump=1)
+                jump=2)
         return res
 
     def test_byval_result(self):
@@ -144,10 +144,8 @@
                     return result_point[0].x * result_point[0].y
 
         assert self.meta_interp(main, [10]) == main(10) == 9000
-        self.check_loops({"int_add": 3, "jump": 1, "int_lt": 1, "guard_true": 1,
-                          "getinteriorfield_raw": 4, "setinteriorfield_raw": 2
-        })
-
+        self.check_resops({'jump': 2, 'int_lt': 2, 'setinteriorfield_raw': 4,
+                           'getinteriorfield_raw': 8, 'int_add': 6, 'guard_true': 2})
 
 class TestFfiCall(FfiCallTests, LLJitMixin):
     supports_all = False
@@ -156,4 +154,4 @@
     supports_all = True     # supports_{floats,longlong,singlefloats}
 
 class TestFfiLookup(FfiLookupTests, LLJitMixin):
-    pass
\ No newline at end of file
+    pass
diff --git a/pypy/module/_weakref/interp__weakref.py b/pypy/module/_weakref/interp__weakref.py
--- a/pypy/module/_weakref/interp__weakref.py
+++ b/pypy/module/_weakref/interp__weakref.py
@@ -1,7 +1,7 @@
 import py
 from pypy.interpreter.baseobjspace import Wrappable, W_Root
 from pypy.interpreter.error import OperationError
-from pypy.interpreter.gateway import interp2app, ObjSpace, NoneNotWrapped
+from pypy.interpreter.gateway import interp2app, ObjSpace
 from pypy.interpreter.typedef import TypeDef
 from pypy.rlib import jit
 import weakref
@@ -294,11 +294,11 @@
     lifeline = getlifelinewithcallbacks(space, w_obj)
     return lifeline.make_proxy_with_callback(w_obj, w_callable)
 
-def proxy(space, w_obj, w_callable=NoneNotWrapped):
+def proxy(space, w_obj, w_callable=None):
     """Create a proxy object that weakly references 'obj'.
 'callback', if given, is called with the proxy as an argument when 'obj'
 is about to be finalized."""
-    if w_callable is None:
+    if space.is_w(w_callable, space.w_None):
         return get_or_make_proxy(space, w_obj)
     else:
         return make_proxy_with_callback(space, w_obj, w_callable)
diff --git a/pypy/module/_weakref/test/test_weakref.py b/pypy/module/_weakref/test/test_weakref.py
--- a/pypy/module/_weakref/test/test_weakref.py
+++ b/pypy/module/_weakref/test/test_weakref.py
@@ -324,6 +324,7 @@
         class A(object): pass
         a = A()
         assert _weakref.proxy(a) is _weakref.proxy(a)
+        assert _weakref.proxy(a) is _weakref.proxy(a, None)
 
     def test_callable_proxy(self):
         import _weakref, gc
diff --git a/pypy/module/micronumpy/test/test_zjit.py b/pypy/module/micronumpy/test/test_zjit.py
--- a/pypy/module/micronumpy/test/test_zjit.py
+++ b/pypy/module/micronumpy/test/test_zjit.py
@@ -78,9 +78,10 @@
 
     def test_add(self):
         result = self.run("add")
-        self.check_loops({'getarrayitem_raw': 2, 'float_add': 1,
-                          'setarrayitem_raw': 1, 'int_add': 3,
-                          'int_ge': 1, 'guard_false': 1, 'jump': 1})
+        self.check_resops({'setarrayitem_raw': 2, 'getfield_gc': 19, 'guard_class': 11,
+                           'int_add': 6, 'guard_isnull': 1, 'jump': 2, 'int_ge': 2,
+                           'getarrayitem_raw': 4, 'float_add': 2, 'guard_false': 2,
+                           'guard_value': 1})
         assert result == 3 + 3
 
     def define_float_add():
@@ -92,9 +93,10 @@
     def test_floatadd(self):
         result = self.run("float_add")
         assert result == 3 + 3
-        self.check_loops({"getarrayitem_raw": 1, "float_add": 1,
-                          "setarrayitem_raw": 1, "int_add": 2,
-                          "int_ge": 1, "guard_false": 1, "jump": 1})
+        self.check_resops({'setarrayitem_raw': 2, 'getfield_gc': 17, 'guard_class': 11,
+                           'int_add': 4, 'guard_isnull': 1, 'jump': 2, 'int_ge': 2,
+                           'getarrayitem_raw': 2, 'float_add': 2, 'guard_false': 2,
+                           'guard_value': 1})
 
     def define_sum():
         return """
@@ -106,9 +108,9 @@
     def test_sum(self):
         result = self.run("sum")
         assert result == 2 * sum(range(30))
-        self.check_loops({"getarrayitem_raw": 2, "float_add": 2,
-                          "int_add": 2,
-                          "int_ge": 1, "guard_false": 1, "jump": 1})
+        self.check_resops({'guard_class': 10, 'getfield_gc': 17, 'jump': 2,
+                           'getarrayitem_raw': 4, 'guard_value': 2, 'int_add': 4,
+                           'guard_isnull': 1, 'int_ge': 2, 'float_add': 4, 'guard_false': 2})
 
     def define_prod():
         return """
@@ -123,9 +125,11 @@
         for i in range(30):
             expected *= i * 2
         assert result == expected
-        self.check_loops({"getarrayitem_raw": 2, "float_add": 1,
-                          "float_mul": 1, "int_add": 2,
-                          "int_ge": 1, "guard_false": 1, "jump": 1})
+        self.check_resops({'guard_class': 10, 'getfield_gc': 17, 'int_add': 4,
+                           'float_mul': 2, 'guard_isnull': 1, 'jump': 2, 'int_ge': 2,
+                           'getarrayitem_raw': 4, 'float_add': 2, 'guard_false': 2,
+                           'guard_value': 2})
+
 
     def test_max(self):
         py.test.skip("broken, investigate")
@@ -149,9 +153,10 @@
         min(b)
         """)
         assert result == -24
-        self.check_loops({"getarrayitem_raw": 2, "float_add": 1,
-                          "float_mul": 1, "int_add": 1,
-                          "int_lt": 1, "guard_true": 1, "jump": 1})
+        self.check_resops({'guard_class': 10, 'getfield_gc': 15, 'guard_value': 1,
+                           'int_add': 4, 'guard_isnull': 1, 'jump': 2, 'int_ge': 2,
+                           'getarrayitem_raw': 4, 'float_add': 2, 'guard_false': 4,
+                           'float_ne': 2})
 
     def define_any():
         return """
@@ -164,10 +169,10 @@
     def test_any(self):
         result = self.run("any")
         assert result == 1
-        self.check_loops({"getarrayitem_raw": 2, "float_add": 1,
-                          "float_ne": 1, "int_add": 2,
-                          "int_ge": 1, "jump": 1,
-                          "guard_false": 2})
+        self.check_resops({'guard_class': 10, 'getfield_gc': 15, 'guard_value': 1,
+                           'int_add': 4, 'guard_isnull': 1, 'jump': 2, 'int_ge': 2,
+                           'getarrayitem_raw': 4, 'float_add': 2, 'guard_false': 4,
+                           'float_ne': 2})
 
     def define_already_forced():
         return """
@@ -184,9 +189,12 @@
         # This is the sum of the ops for both loops, however if you remove the
         # optimization then you end up with 2 float_adds, so we can still be
         # sure it was optimized correctly.
-        self.check_loops({"getarrayitem_raw": 2, "float_mul": 1, "float_add": 1,
-                           "setarrayitem_raw": 2, "int_add": 4,
-                           "int_ge": 2, "guard_false": 2, "jump": 2})
+        self.check_resops({'setarrayitem_raw': 4, 'guard_nonnull': 1, 'getfield_gc': 35,
+                           'guard_class': 22, 'int_add': 8, 'float_mul': 2,
+                           'guard_isnull': 2, 'jump': 4, 'int_ge': 4,
+                           'getarrayitem_raw': 4, 'float_add': 2, 'guard_false': 4,
+                           'guard_value': 2})
+
 
     def define_ufunc():
         return """
@@ -199,10 +207,11 @@
     def test_ufunc(self):
         result = self.run("ufunc")
         assert result == -6
-        self.check_loops({"getarrayitem_raw": 2, "float_add": 1, "float_neg": 1,
-                          "setarrayitem_raw": 1, "int_add": 3,
-                          "int_ge": 1, "guard_false": 1, "jump": 1,
-        })
+        self.check_resops({'setarrayitem_raw': 2, 'getfield_gc': 24, 'guard_class': 14,
+                           'int_add': 6, 'float_neg': 2, 'guard_isnull': 2, 'jump': 2,
+                           'int_ge': 2, 'getarrayitem_raw': 4, 'float_add': 2,
+                           'guard_false': 2, 'guard_value': 2})
+
 
     def define_specialization():
         return """
@@ -255,9 +264,10 @@
     def test_multidim(self):
         result = self.run('multidim')
         assert result == 8
-        self.check_loops({'float_add': 1, 'getarrayitem_raw': 2,
-                          'guard_false': 1, 'int_add': 3, 'int_ge': 1,
-                          'jump': 1, 'setarrayitem_raw': 1})
+        self.check_resops({'setarrayitem_raw': 2, 'getfield_gc': 19, 'guard_class': 11,
+                           'int_add': 6, 'guard_isnull': 1, 'jump': 2, 'int_ge': 2,
+                           'getarrayitem_raw': 4, 'float_add': 2, 'guard_false': 2,
+                           'guard_value': 1})
         # int_add might be 1 here if we try slightly harder with
         # reusing indexes or some optimization
 
diff --git a/pypy/module/pypyjit/test_pypy_c/test_string.py b/pypy/module/pypyjit/test_pypy_c/test_string.py
--- a/pypy/module/pypyjit/test_pypy_c/test_string.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_string.py
@@ -33,8 +33,12 @@
             i24 = int_ge(i19, i12)
             guard_false(i24, descr=...)
             i25 = unicodegetitem(p13, i19)
-            i26 = int_eq(i23, i25)
-            guard_true(i26, descr=...)
+            p27 = newstr(1)
+            strsetitem(p27, 0, i23)
+            p30 = call(ConstClass(ll_str2unicode__rpy_stringPtr), p27, descr=...)
+            guard_no_exception(descr=...)
+            i32 = call(ConstClass(_ll_2_str_eq_checknull_char__rpy_unicodePtr_UniChar), p30, i25, descr=...)
+            guard_true(i32, descr=...)
             i34 = int_add(i6, 1)
             --TICK--
             jump(p0, p1, p2, p3, p4, p5, i34, p7, p8, i9, i10, p11, i12, p13, descr=...)
diff --git a/pypy/objspace/flow/objspace.py b/pypy/objspace/flow/objspace.py
--- a/pypy/objspace/flow/objspace.py
+++ b/pypy/objspace/flow/objspace.py
@@ -96,6 +96,12 @@
         self.executioncontext.recorder = previous_recorder
         self.concrete_mode -= 1
 
+    def is_w(self, w_one, w_two):
+        return self.is_true(self.is_(w_one, w_two))
+
+    is_ = None     # real version added by add_operations()
+    id  = None     # real version added by add_operations()
+
     def newdict(self):
         if self.concrete_mode:
             return Constant({})
diff --git a/pypy/objspace/flow/operation.py b/pypy/objspace/flow/operation.py
--- a/pypy/objspace/flow/operation.py
+++ b/pypy/objspace/flow/operation.py
@@ -315,7 +315,7 @@
 del _add_exceptions, _add_except_ovf
 
 def make_op(fs, name, symbol, arity, specialnames):
-    if hasattr(fs, name):
+    if getattr(fs, name, None) is not None:
         return
 
     op = None
diff --git a/pypy/objspace/std/complexobject.py b/pypy/objspace/std/complexobject.py
--- a/pypy/objspace/std/complexobject.py
+++ b/pypy/objspace/std/complexobject.py
@@ -5,12 +5,46 @@
 from pypy.objspace.std.register_all import register_all
 from pypy.objspace.std.floatobject import W_FloatObject, _hash_float
 from pypy.objspace.std.longobject import W_LongObject
+from pypy.rlib.rbigint import rbigint
 from pypy.rlib.rfloat import (
     formatd, DTSF_STR_PRECISION, isinf, isnan, copysign)
 
 import math
 
-class W_ComplexObject(W_Object):
+
+class W_AbstractComplexObject(W_Object):
+    __slots__ = ()
+
+    def is_w(self, space, w_other):
+        from pypy.rlib.longlong2float import float2longlong
+        if not isinstance(w_other, W_AbstractComplexObject):
+            return False
+        if self.user_overridden_class or w_other.user_overridden_class:
+            return self is w_other
+        real1 = space.float_w(space.getattr(self,    space.wrap("real")))
+        real2 = space.float_w(space.getattr(w_other, space.wrap("real")))
+        imag1 = space.float_w(space.getattr(self,    space.wrap("imag")))
+        imag2 = space.float_w(space.getattr(w_other, space.wrap("imag")))
+        real1 = float2longlong(real1)
+        real2 = float2longlong(real2)
+        imag1 = float2longlong(imag1)
+        imag2 = float2longlong(imag2)
+        return real1 == real2 and imag1 == imag2
+
+    def id(self, space):
+        if self.user_overridden_class:
+            return W_Object.id(self, space)
+        from pypy.rlib.longlong2float import float2longlong
+        from pypy.objspace.std.model import IDTAG_COMPLEX as tag
+        real = space.float_w(space.getattr(self, space.wrap("real")))
+        imag = space.float_w(space.getattr(self, space.wrap("imag")))
+        real_b = rbigint.fromrarith_int(float2longlong(real))
+        imag_b = rbigint.fromrarith_int(float2longlong(imag))
+        val = real_b.lshift(64).or_(imag_b).lshift(3).or_(rbigint.fromint(tag))
+        return space.newlong_from_rbigint(val)
+
+
+class W_ComplexObject(W_AbstractComplexObject):
     """This is a reimplementation of the CPython "PyComplexObject"
     """
     from pypy.objspace.std.complextype import complex_typedef as typedef
diff --git a/pypy/objspace/std/floatobject.py b/pypy/objspace/std/floatobject.py
--- a/pypy/objspace/std/floatobject.py
+++ b/pypy/objspace/std/floatobject.py
@@ -21,10 +21,33 @@
 import math
 from pypy.objspace.std.intobject import W_IntObject
 
-class W_FloatObject(W_Object):
-    """This is a reimplementation of the CPython "PyFloatObject"
-       it is assumed that the constructor takes a real Python float as
-       an argument"""
+class W_AbstractFloatObject(W_Object):
+    __slots__ = ()
+
+    def is_w(self, space, w_other):
+        from pypy.rlib.longlong2float import float2longlong
+        if not isinstance(w_other, W_AbstractFloatObject):
+            return False
+        if self.user_overridden_class or w_other.user_overridden_class:
+            return self is w_other
+        one = float2longlong(space.float_w(self))
+        two = float2longlong(space.float_w(w_other))
+        return one == two
+
+    def id(self, space):
+        if self.user_overridden_class:
+            return W_Object.id(self, space)
+        from pypy.rlib.longlong2float import float2longlong
+        from pypy.objspace.std.model import IDTAG_FLOAT as tag
+        val = float2longlong(space.float_w(self))
+        b = rbigint.fromrarith_int(val)
+        b = b.lshift(3).or_(rbigint.fromint(tag))
+        return space.newlong_from_rbigint(b)
+
+
+class W_FloatObject(W_AbstractFloatObject):
+    """This is a implementation of the app-level 'float' type.
+    The constructor takes an RPython float as an argument."""
     from pypy.objspace.std.floattype import float_typedef as typedef
     _immutable_fields_ = ['floatval']
 
diff --git a/pypy/objspace/std/frame.py b/pypy/objspace/std/frame.py
--- a/pypy/objspace/std/frame.py
+++ b/pypy/objspace/std/frame.py
@@ -3,13 +3,11 @@
 import operator
 
 from pypy.rlib.unroll import unrolling_iterable
-from pypy.interpreter import pyopcode, function
+from pypy.interpreter import pyopcode
 from pypy.interpreter.pyframe import PyFrame
-from pypy.interpreter.error import OperationError, operationerrfmt
-from pypy.module.__builtin__ import Module
+from pypy.interpreter.error import OperationError
 from pypy.objspace.std import intobject, smallintobject
 from pypy.objspace.std.multimethod import FailedToImplement
-from pypy.objspace.std.dictmultiobject import W_DictMultiObject
 from pypy.objspace.std.listobject import W_ListObject
 
 
diff --git a/pypy/objspace/std/intobject.py b/pypy/objspace/std/intobject.py
--- a/pypy/objspace/std/intobject.py
+++ b/pypy/objspace/std/intobject.py
@@ -19,6 +19,22 @@
 class W_AbstractIntObject(W_Object):
     __slots__ = ()
 
+    def is_w(self, space, w_other):
+        if not isinstance(w_other, W_AbstractIntObject):
+            return False
+        if self.user_overridden_class or w_other.user_overridden_class:
+            return self is w_other
+        return space.int_w(self) == space.int_w(w_other)
+
+    def id(self, space):
+        if self.user_overridden_class:
+            return W_Object.id(self, space)
+        from pypy.objspace.std.model import IDTAG_INT as tag
+        b = space.bigint_w(self)
+        b = b.lshift(3).or_(rbigint.fromint(tag))
+        return space.newlong_from_rbigint(b)
+
+
 class W_IntObject(W_AbstractIntObject):
     __slots__ = 'intval'
     _immutable_fields_ = ['intval']
diff --git a/pypy/objspace/std/longobject.py b/pypy/objspace/std/longobject.py
--- a/pypy/objspace/std/longobject.py
+++ b/pypy/objspace/std/longobject.py
@@ -11,6 +11,22 @@
 class W_AbstractLongObject(W_Object):
     __slots__ = ()
 
+    def is_w(self, space, w_other):
+        if not isinstance(w_other, W_AbstractLongObject):
+            return False
+        if self.user_overridden_class or w_other.user_overridden_class:
+            return self is w_other
+        return space.bigint_w(self).eq(space.bigint_w(w_other))
+
+    def id(self, space):
+        if self.user_overridden_class:
+            return W_Object.id(self, space)
+        from pypy.objspace.std.model import IDTAG_LONG as tag
+        b = space.bigint_w(self)
+        b = b.lshift(3).or_(rbigint.fromint(tag))
+        return space.newlong_from_rbigint(b)
+
+
 class W_LongObject(W_AbstractLongObject):
     """This is a wrapper of rbigint."""
     from pypy.objspace.std.longtype import long_typedef as typedef
diff --git a/pypy/objspace/std/model.py b/pypy/objspace/std/model.py
--- a/pypy/objspace/std/model.py
+++ b/pypy/objspace/std/model.py
@@ -29,6 +29,11 @@
                     "proxyobject.W_TransparentDict"],
 }
 
+IDTAG_INT     = 1
+IDTAG_LONG    = 3
+IDTAG_FLOAT   = 5
+IDTAG_COMPLEX = 7
+
 class StdTypeModel:
 
     def __init__(self, config):
diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py
--- a/pypy/objspace/std/objspace.py
+++ b/pypy/objspace/std/objspace.py
@@ -453,77 +453,6 @@
                                  self.wrap("Expected tuple of length 3"))
         return self.int_w(l_w[0]), self.int_w(l_w[1]), self.int_w(l_w[2])
 
-    def is_(self, w_one, w_two):
-        return self.newbool(self.is_w(w_one, w_two))
-
-    def is_w(self, w_one, w_two):
-        from pypy.rlib.longlong2float import float2longlong
-        w_typeone = self.type(w_one)
-        # cannot use self.is_w here to not get infinite recursion
-        if w_typeone is self.w_int:
-            return (self.type(w_two) is self.w_int and
-                    self.int_w(w_one) == self.int_w(w_two))
-        elif w_typeone is self.w_float:
-            if self.type(w_two) is not self.w_float:
-                return False
-            one = float2longlong(self.float_w(w_one))
-            two = float2longlong(self.float_w(w_two))
-            return one == two
-        elif w_typeone is self.w_long:
-            return (self.type(w_two) is self.w_long and
-                    self.bigint_w(w_one).eq(self.bigint_w(w_two)))
-        elif w_typeone is self.w_complex:
-            if self.type(w_two) is not self.w_complex:
-                return False
-            real1 = self.float_w(self.getattr(w_one, self.wrap("real")))
-            real2 = self.float_w(self.getattr(w_two, self.wrap("real")))
-            imag1 = self.float_w(self.getattr(w_one, self.wrap("imag")))
-            imag2 = self.float_w(self.getattr(w_two, self.wrap("imag")))
-            real1 = float2longlong(real1)
-            real2 = float2longlong(real2)
-            imag1 = float2longlong(imag1)
-            imag2 = float2longlong(imag2)
-            return real1 == real2 and imag1 == imag2
-        elif w_typeone is self.w_str:
-            return (self.type(w_two) is self.w_str and
-                    self.str_w(w_one) is self.str_w(w_two))
-        elif w_typeone is self.w_unicode:
-            return (self.type(w_two) is self.w_unicode and
-                    self.unicode_w(w_one) is self.unicode_w(w_two))
-        return w_one is w_two
-
-    def id(self, w_obj):
-        from pypy.rlib.rbigint import rbigint
-        from pypy.rlib import objectmodel
-        from pypy.rlib.longlong2float import float2longlong
-        w_type = self.type(w_obj)
-        if w_type is self.w_int:
-            tag = 1
-            return self.or_(self.lshift(w_obj, self.wrap(3)), self.wrap(tag))
-        elif w_type is self.w_long:
-            tag = 3
-            return self.or_(self.lshift(w_obj, self.wrap(3)), self.wrap(tag))
-        elif w_type is self.w_float:
-            tag = 5
-            val = float2longlong(self.float_w(w_obj))
-            w_obj = self.newlong_from_rbigint(rbigint.fromrarith_int(val))
-            return self.or_(self.lshift(w_obj, self.wrap(3)), self.wrap(tag))
-        elif w_type is self.w_complex:
-            real = self.float_w(self.getattr(w_obj, self.wrap("real")))
-            imag = self.float_w(self.getattr(w_obj, self.wrap("imag")))
-            tag = 5
-            real_b = rbigint.fromrarith_int(float2longlong(real))
-            imag_b = rbigint.fromrarith_int(float2longlong(imag))
-            val = real_b.lshift(8 * 8).or_(imag_b).lshift(3).or_(rbigint.fromint(3))
-            return self.newlong_from_rbigint(val)
-        elif w_type is self.w_str:
-            res = objectmodel.compute_unique_id(self.str_w(w_obj))
-        elif w_type is self.w_unicode:
-            res = objectmodel.compute_unique_id(self.unicode_w(w_obj))
-        else:
-            res = objectmodel.compute_unique_id(w_obj)
-        return self.wrap(res)
-
     def is_true(self, w_obj):
         # a shortcut for performance
         # NOTE! this method is typically overridden by builtinshortcut.py.
diff --git a/pypy/objspace/std/stringobject.py b/pypy/objspace/std/stringobject.py
--- a/pypy/objspace/std/stringobject.py
+++ b/pypy/objspace/std/stringobject.py
@@ -5,6 +5,7 @@
 from pypy.interpreter import gateway
 from pypy.rlib.rarithmetic import ovfcheck
 from pypy.rlib.objectmodel import we_are_translated, compute_hash, specialize
+from pypy.rlib.objectmodel import compute_unique_id
 from pypy.objspace.std.inttype import wrapint
 from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
 from pypy.objspace.std import slicetype, newformat
@@ -22,6 +23,21 @@
 class W_AbstractStringObject(W_Object):
     __slots__ = ()
 
+    def is_w(self, space, w_other):
+        if not isinstance(w_other, W_AbstractStringObject):
+            return False
+        if self is w_other:
+            return True
+        if self.user_overridden_class or w_other.user_overridden_class:
+            return False
+        return space.str_w(self) is space.str_w(w_other)
+
+    def id(self, space):
+        if self.user_overridden_class:
+            return W_Object.id(self, space)
+        return space.wrap(compute_unique_id(space.str_w(self)))
+
+
 class W_StringObject(W_AbstractStringObject):
     from pypy.objspace.std.stringtype import str_typedef as typedef
     _immutable_fields_ = ['_value']
diff --git a/pypy/objspace/std/test/test_obj.py b/pypy/objspace/std/test/test_obj.py
--- a/pypy/objspace/std/test/test_obj.py
+++ b/pypy/objspace/std/test/test_obj.py
@@ -147,6 +147,28 @@
         s = "a"
         assert self.unwrap_wrap_str(s) is s
 
+    def test_is_on_subclasses(self):
+        for typ in [int, long, float, complex, str, unicode]:
+            class mytyp(typ):
+                pass
+            if not self.cpython_apptest and typ not in (str, unicode):
+                assert typ(42) is typ(42)
+            assert mytyp(42) is not mytyp(42)
+            assert mytyp(42) is not typ(42)
+            assert typ(42) is not mytyp(42)
+            x = mytyp(42)
+            assert x is x
+            assert x is not "43"
+            assert x is not None
+            assert "43" is not x
+            assert None is not x
+            x = typ(42)
+            assert x is x
+            assert x is not "43"
+            assert x is not None
+            assert "43" is not x
+            assert None is not x
+
     def test_id_on_primitives(self):
         if self.cpython_apptest:
             skip("cpython behaves differently")
@@ -226,6 +248,12 @@
                 if a is b:
                     assert a == b
 
+    def test_identity_bug(self):
+        x = 0x4000000000000000L
+        y = 2j
+        assert id(x) != id(y)
+
+
 def test_isinstance_shortcut():
     from pypy.objspace.std import objspace
     space = objspace.StdObjSpace()
diff --git a/pypy/objspace/std/unicodeobject.py b/pypy/objspace/std/unicodeobject.py
--- a/pypy/objspace/std/unicodeobject.py
+++ b/pypy/objspace/std/unicodeobject.py
@@ -11,6 +11,7 @@
 from pypy.objspace.std.tupleobject import W_TupleObject
 from pypy.rlib.rarithmetic import intmask, ovfcheck
 from pypy.rlib.objectmodel import compute_hash, specialize
+from pypy.rlib.objectmodel import compute_unique_id
 from pypy.rlib.rstring import UnicodeBuilder
 from pypy.rlib.runicode import unicode_encode_unicode_escape
 from pypy.module.unicodedata import unicodedb
@@ -22,6 +23,21 @@
 class W_AbstractUnicodeObject(W_Object):
     __slots__ = ()
 
+    def is_w(self, space, w_other):
+        if not isinstance(w_other, W_AbstractUnicodeObject):
+            return False
+        if self is w_other:
+            return True
+        if self.user_overridden_class or w_other.user_overridden_class:
+            return False
+        return space.unicode_w(self) is space.unicode_w(w_other)
+
+    def id(self, space):
+        if self.user_overridden_class:
+            return W_Object.id(self, space)
+        return space.wrap(compute_unique_id(space.unicode_w(self)))
+
+
 class W_UnicodeObject(W_AbstractUnicodeObject):
     from pypy.objspace.std.unicodetype import unicode_typedef as typedef
     _immutable_fields_ = ['_value']


More information about the pypy-commit mailing list