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