Author: Carl Friedrich Bolz <[email protected]>
Branch: typed-cells
Changeset: r75467:8ff346f1fd62
Date: 2015-01-21 18:16 +0100
http://bitbucket.org/pypy/pypy/changeset/8ff346f1fd62/

Log:    try to reduce the overhead of writing ints into types (and
        eventually modules) even further, by storing them unboxed

        bit experimental

diff --git a/pypy/objspace/std/test/test_versionedtype.py 
b/pypy/objspace/std/test/test_versionedtype.py
--- a/pypy/objspace/std/test/test_versionedtype.py
+++ b/pypy/objspace/std/test/test_versionedtype.py
@@ -210,6 +210,56 @@
         assert w_A.version_tag() is atag
         assert space.int_w(space.getattr(w_A, w_x)) == 4
 
+    def test_no_cell_when_writing_same_value(self):
+        space = self.space
+        w_x = space.wrap("x")
+        w_A, w_B, w_C = self.get_three_classes()
+        atag = w_A.version_tag()
+        w_val = space.newint(1)
+        space.setattr(w_A, w_x, w_val)
+        space.setattr(w_A, w_x, w_val)
+        w_val1 = w_A._getdictvalue_no_unwrapping(space, "x")
+        assert w_val1 is w_val
+
+    def test_int_cells(self):
+        space = self.space
+        w_x = space.wrap("x")
+        w_A, w_B, w_C = self.get_three_classes()
+        atag = w_A.version_tag()
+        space.setattr(w_A, w_x, space.newint(1))
+        assert w_A.version_tag() is not atag
+        assert space.int_w(space.getattr(w_A, w_x)) == 1
+
+        atag = w_A.version_tag()
+        space.setattr(w_A, w_x, space.newint(2))
+        assert w_A.version_tag() is not atag
+        assert space.int_w(space.getattr(w_A, w_x)) == 2
+        cell = w_A._getdictvalue_no_unwrapping(space, "x")
+        assert cell.intvalue == 2
+
+        atag = w_A.version_tag()
+        space.setattr(w_A, w_x, space.newint(3))
+        assert w_A.version_tag() is atag
+        assert space.int_w(space.getattr(w_A, w_x)) == 3
+        assert cell.intvalue == 3
+
+        space.setattr(w_A, w_x, space.newint(4))
+        assert w_A.version_tag() is atag
+        assert space.int_w(space.getattr(w_A, w_x)) == 4
+        assert cell.intvalue == 4
+
+    def test_int_cell_turns_into_cell(self):
+        space = self.space
+        w_x = space.wrap("x")
+        w_A, w_B, w_C = self.get_three_classes()
+        atag = w_A.version_tag()
+        space.setattr(w_A, w_x, space.newint(1))
+        space.setattr(w_A, w_x, space.newint(2))
+        space.setattr(w_A, w_x, space.newfloat(2.2))
+        cell = w_A._getdictvalue_no_unwrapping(space, "x")
+        assert space.float_w(cell.w_value) == 2.2
+
+
 
 class AppTestVersionedType(test_typeobject.AppTestTypeObject):
     spaceconfig = {"objspace.std.withtypeversion": True}
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -11,18 +11,47 @@
 from rpython.rlib.objectmodel import current_object_addr_as_int, compute_hash
 from rpython.rlib.rarithmetic import intmask, r_uint
 
+class BaseTypeCell(W_Root):
+    def unwrap_cell(self, space):
+        raise NotImplementedError("abstract base")
 
-class TypeCell(W_Root):
+class TypeCell(BaseTypeCell):
     def __init__(self, w_value=None):
         self.w_value = w_value
 
+    def unwrap_cell(self, space):
+        return self.w_value
+
+class IntTypeCell(BaseTypeCell):
+    def __init__(self, intvalue):
+        self.intvalue = intvalue
+
+    def unwrap_cell(self, space):
+        return space.wrap(self.intvalue)
+
 
 def unwrap_cell(space, w_value):
-    if (space.config.objspace.std.withtypeversion and
-            isinstance(w_value, TypeCell)):
-        return w_value.w_value
+    if space.config.objspace.std.withtypeversion:
+        if isinstance(w_value, BaseTypeCell):
+            return w_value.unwrap_cell(space)
     return w_value
 
+def write_cell(space, w_cell, w_value):
+    from pypy.objspace.std.intobject import W_IntObject
+    if isinstance(w_cell, TypeCell):
+        w_cell.w_value = w_value
+        return None
+    elif isinstance(w_cell, IntTypeCell) and type(w_value) is W_IntObject:
+        w_cell.intvalue = w_value.intval
+        return None
+    elif space.is_w(w_cell, w_value):
+        # If the new value and the current value are the same, don't
+        # create a level of indirection, or mutate the version.
+        return None
+    if type(w_value) is W_IntObject:
+        return IntTypeCell(w_value.intval)
+    else:
+        return TypeCell(w_value)
 
 class VersionTag(object):
     pass
@@ -275,10 +304,9 @@
                 w_curr = w_self._pure_getdictvalue_no_unwrapping(
                         space, version_tag, name)
                 if w_curr is not None:
-                    if isinstance(w_curr, TypeCell):
-                        w_curr.w_value = w_value
+                    w_value = write_cell(space, w_curr, w_value)
+                    if w_value is None:
                         return True
-                    w_value = TypeCell(w_value)
         w_self.mutated(name)
         w_self.dict_w[name] = w_value
         return True
@@ -369,8 +397,8 @@
         tup_w = w_self._pure_lookup_where_with_method_cache(name, version_tag)
         w_class, w_value = tup_w
         if (space.config.objspace.std.withtypeversion and
-                isinstance(w_value, TypeCell)):
-            return w_class, w_value.w_value
+                isinstance(w_value, BaseTypeCell)):
+            return w_class, w_value.unwrap_cell(space)
         return tup_w   # don't make a new tuple, reuse the old one
 
     def _pure_lookup_where_possibly_with_method_cache(w_self, name, 
version_tag):
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to