[pypy-commit] pypy type-specialized-instances: introduced IntAttribute
l.diekmann
noreply at buildbot.pypy.org
Fri Nov 18 14:42:27 CET 2011
Author: Lukas Diekmann <lukas.diekmann at uni-duesseldorf.de>
Branch: type-specialized-instances
Changeset: r49522:b16fead0c3f3
Date: 2011-11-16 18:24 +0100
http://bitbucket.org/pypy/pypy/changeset/b16fead0c3f3/
Log: introduced IntAttribute
diff --git a/pypy/objspace/std/mapdict.py b/pypy/objspace/std/mapdict.py
--- a/pypy/objspace/std/mapdict.py
+++ b/pypy/objspace/std/mapdict.py
@@ -125,15 +125,15 @@
return None
@jit.elidable
- def _get_new_attr(self, name, index):
- selector = name, index
+ def _get_new_attr(self, name, index, attrclass):
+ key = name, index, attrclass
cache = self.cache_attrs
if cache is None:
cache = self.cache_attrs = {}
- attr = cache.get(selector, None)
+ attr = cache.get(key, None)
if attr is None:
- attr = PlainAttribute(selector, self)
- cache[selector] = attr
+ attr = attrclass(key, self)
+ cache[key] = attr
return attr
@jit.look_inside_iff(lambda self, obj, selector, w_value:
@@ -141,8 +141,9 @@
jit.isconstant(selector[0]) and
jit.isconstant(selector[1]))
def add_attr(self, obj, selector, w_value):
+ attrclass = get_attrclass_from_value(self.space, w_value)
# grumble, jit needs this
- attr = self._get_new_attr(selector[0], selector[1])
+ attr = self._get_new_attr(selector[0], selector[1], attrclass)
oldattr = obj._get_mapdict_map()
if not jit.we_are_jitted():
size_est = (oldattr._size_estimate + attr.size_estimate()
@@ -264,8 +265,10 @@
terminator = terminator.devolved_dict_terminator
return Terminator.set_terminator(self, obj, terminator)
-class PlainAttribute(AbstractAttribute):
+class AbstractStoredAttribute(AbstractAttribute):
+
_immutable_fields_ = ['selector', 'position', 'back']
+
def __init__(self, selector, back):
AbstractAttribute.__init__(self, back.space, back.terminator)
self.selector = selector
@@ -277,17 +280,6 @@
w_value = self.read(obj, self.selector)
new_obj._get_mapdict_map().add_attr(new_obj, self.selector, w_value)
- def read_attr(self, obj):
- # XXX do the unerasing (and wrapping) here
- erased = obj._mapdict_read_storage(self.position)
- w_value = unerase_item(erased)
- return w_value
-
- def write_attr(self, obj, w_value):
- # XXX do the unerasing (and unwrapping) here
- erased = erase_item(w_value)
- obj._mapdict_write_storage(self.position, erased)
-
def delete(self, obj, selector):
if selector == self.selector:
# ok, attribute is deleted
@@ -333,6 +325,41 @@
def __repr__(self):
return "<PlainAttribute %s %s %r>" % (self.selector, self.position, self.back)
+class PlainAttribute(AbstractStoredAttribute):
+
+ erase_item, unerase_item = rerased.new_erasing_pair("mapdict storage object item")
+ erase_item = staticmethod(erase_item)
+ unerase_item = staticmethod(unerase_item)
+
+ def read_attr(self, obj):
+ erased = obj._mapdict_read_storage(self.position)
+ w_value = self.unerase_item(erased)
+ return w_value
+
+ def write_attr(self, obj, w_value):
+ erased = self.erase_item(w_value)
+ obj._mapdict_write_storage(self.position, erased)
+
+class IntAttribute(AbstractStoredAttribute):
+
+ erase_item, unerase_item = rerased.erase_int, rerased.unerase_int
+ erase_item = staticmethod(erase_item)
+ unerase_item = staticmethod(unerase_item)
+
+ def read_attr(self, obj):
+ erased = obj._mapdict_read_storage(self.position)
+ value = self.unerase_item(erased)
+ return self.space.wrap(value)
+
+ def write_attr(self, obj, w_value):
+ erased = self.erase_item(self.space.int_w(w_value))
+ obj._mapdict_write_storage(self.position, erased)
+
+def get_attrclass_from_value(space, w_value):
+ if space.is_w(space.type(w_value), space.w_int):
+ return IntAttribute
+ return PlainAttribute
+
def _become(w_obj, new_obj):
# this is like the _become method, really, but we cannot use that due to
# RPython reasons
@@ -524,7 +551,6 @@
memo_get_subclass_of_correct_size._annspecialcase_ = "specialize:memo"
_subclass_cache = {}
-erase_item, unerase_item = rerased.new_erasing_pair("mapdict storage item")
erase_list, unerase_list = rerased.new_erasing_pair("mapdict storage list")
def _make_subclass_size_n(supercls, n):
diff --git a/pypy/objspace/std/test/test_mapdict.py b/pypy/objspace/std/test/test_mapdict.py
--- a/pypy/objspace/std/test/test_mapdict.py
+++ b/pypy/objspace/std/test/test_mapdict.py
@@ -5,12 +5,14 @@
space = FakeSpace()
class Class(object):
- def __init__(self, hasdict=True):
+ def __init__(self, hasdict=True, sp=None):
self.hasdict = True
+ if sp is None:
+ sp = space
if hasdict:
- self.terminator = DictTerminator(space, self)
+ self.terminator = DictTerminator(sp, self)
else:
- self.terminator = NoDictTerminator(space, self)
+ self.terminator = NoDictTerminator(sp, self)
def instantiate(self, sp=None):
if sp is None:
@@ -24,10 +26,10 @@
hasdict = False
def erase_storage_items(items):
- return [erase_item(item) for item in items]
+ return [IntAttribute.erase_item(item) for item in items]
def unerase_storage_items(storage):
- return [unerase_item(item) for item in storage]
+ return [IntAttribute.unerase_item(item) for item in storage]
def test_plain_attribute():
@@ -247,7 +249,6 @@
assert obj.getdict(space) is obj.getdict(space)
assert obj.getdict(space).length() == 3
-
def test_materialize_r_dict():
cls = Class()
obj = cls.instantiate()
@@ -301,6 +302,50 @@
obj.setdictvalue(space, a, 50)
assert c.terminator.size_estimate() in [(i + 10) // 2, (i + 11) // 2]
+class TestTypeSpecializedAttributes(object):
+ def setup_class(cls):
+ cls.space = gettestobjspace(**{"objspace.std.withmapdict": True})
+
+ def test_attributes(self):
+ space = self.space
+ cls = Class(sp=space)
+ obj1 = cls.instantiate()
+ obj1.setdictvalue(space, "x", space.wrap(1))
+ #assert space.eq_w(obj1.getdictvalue(space, "x"), space.wrap(1))
+
+ obj2 = cls.instantiate()
+ w_str = space.wrap("string")
+ obj2.setdictvalue(space, "x", w_str)
+ #assert space.eq_w(obj1.getdictvalue(space, "x"), w_str)
+
+ assert obj1.map is not obj2.map
+ assert isinstance(obj1.map, IntAttribute)
+
+ obj3 = cls.instantiate()
+ obj3.setdictvalue(space, "x", space.wrap(5))
+
+ assert obj1.map is obj3.map
+
+ assert IntAttribute.unerase_item(obj1.storage[0]) == 1
+ assert PlainAttribute.unerase_item(obj2.storage[0]) == w_str
+
+ def test_add_more_attributes(self):
+ space = self.space
+ cls = Class(sp=space)
+
+ obj1 = cls.instantiate()
+ obj1.setdictvalue(space, "x", space.wrap(1))
+ obj1.setdictvalue(space, "y", space.wrap(2))
+
+ def test_switch_attribute_types(self):
+ space = self.space
+ cls = Class(sp=space)
+ obj1 = cls.instantiate()
+ obj1.setdictvalue(space, "x", space.wrap(1))
+ assert isinstance(obj1.map, IntAttribute)
+ obj1.setdictvalue(space, "y", space.wrap("str"))
+ assert isinstance(obj1.map, PlainAttribute)
+
# ___________________________________________________________
# dict tests
More information about the pypy-commit
mailing list