Author: Lukas Diekmann <[email protected]>
Branch: type-specialized-instances
Changeset: r49473:c905b06f965f
Date: 2011-11-16 14:17 +0100
http://bitbucket.org/pypy/pypy/changeset/c905b06f965f/
Log: read attributes only through Attribute class. fixed tests
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
@@ -84,7 +84,6 @@
if space.config.objspace.std.withmethodcachecounter:
name = selector[0]
cache.hits[name] = cache.hits.get(name, 0) + 1
- # XXX return the correct Attribute here
return attr
attr = self._findmap(selector)
if attr is None:
@@ -160,7 +159,7 @@
# the order is important here: first change the map, then the storage,
# for the benefit of the special subclasses
obj._set_mapdict_map(attr)
- obj._mapdict_write_storage(attr.position, w_value)
+ attr.write_attr(obj, w_value)
#obj._mapdict_write_storage(attr.position, w_value)
def materialize_r_dict(self, space, obj, dict_w):
raise NotImplementedError("abstract base class")
@@ -280,11 +279,14 @@
def read_attr(self, obj):
# XXX do the unerasing (and wrapping) here
- return obj._mapdict_read_storage(self.position)
+ 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
- obj._mapdict_write_storage(self.position, w_value)
+ erased = erase_item(w_value)
+ obj._mapdict_write_storage(self.position, erased)
def delete(self, obj, selector):
if selector == self.selector:
@@ -317,7 +319,7 @@
new_obj = self.back.materialize_r_dict(space, obj, dict_w)
if self.selector[1] == DICT:
w_attr = space.wrap(self.selector[0])
- dict_w[w_attr] = obj._mapdict_read_storage(self.position)
+ dict_w[w_attr] = self.read_attr(obj)
else:
self._copy_attr(obj, new_obj)
return new_obj
@@ -550,20 +552,19 @@
for i in rangenmin1:
if index == i:
erased = getattr(self, "_value%s" % i)
- return unerase_item(erased)
+ return erased
if self._has_storage_list():
return self._mapdict_get_storage_list()[index - nmin1]
erased = getattr(self, "_value%s" % nmin1)
- return unerase_item(erased)
+ return erased
- def _mapdict_write_storage(self, index, value):
- erased = erase_item(value)
+ def _mapdict_write_storage(self, index, erased):
for i in rangenmin1:
if index == i:
setattr(self, "_value%s" % i, erased)
return
if self._has_storage_list():
- self._mapdict_get_storage_list()[index - nmin1] = value
+ self._mapdict_get_storage_list()[index - nmin1] = erased
return
setattr(self, "_value%s" % nmin1, erased)
@@ -577,21 +578,23 @@
len_storage = len(storage)
for i in rangenmin1:
if i < len_storage:
- erased = erase_item(storage[i])
+ erased = storage[i]
else:
+ # XXX later: use correct erase method from attribute
erased = erase_item(None)
setattr(self, "_value%s" % i, erased)
has_storage_list = self._has_storage_list()
if len_storage < n:
assert not has_storage_list
+ # XXX later: use correct erase method from attribute
erased = erase_item(None)
elif len_storage == n:
assert not has_storage_list
- erased = erase_item(storage[nmin1])
+ erased = storage[nmin1]
elif not has_storage_list:
# storage is longer than self.map.length() only due to
# overallocation
- erased = erase_item(storage[nmin1])
+ erased = storage[nmin1]
# in theory, we should be ultra-paranoid and check all entries,
# but checking just one should catch most problems anyway:
assert storage[n] is None
@@ -771,14 +774,14 @@
pycode._mapdict_caches = [INVALID_CACHE_ENTRY] * num_entries
@jit.dont_look_inside
-def _fill_cache(pycode, nameindex, map, version_tag, index, w_method=None):
+def _fill_cache(pycode, nameindex, map, version_tag, attr, w_method=None):
entry = pycode._mapdict_caches[nameindex]
if entry is INVALID_CACHE_ENTRY:
entry = CacheEntry()
pycode._mapdict_caches[nameindex] = entry
entry.map_wref = weakref.ref(map)
entry.version_tag = version_tag
- entry.index = index
+ entry.attr = attr
entry.w_method = w_method
if pycode.space.config.objspace.std.withmethodcachecounter:
entry.failure_counter += 1
@@ -790,7 +793,7 @@
map = w_obj._get_mapdict_map()
if entry.is_valid_for_map(map) and entry.w_method is None:
# everything matches, it's incredibly fast
- return w_obj._mapdict_read_storage(entry.index)
+ return entry.attr.read_attr(w_obj) #._mapdict_read_storage(entry.index)
return LOAD_ATTR_slowpath(pycode, w_obj, nameindex, map)
LOAD_ATTR_caching._always_inline_ = True
@@ -836,7 +839,7 @@
if attr is not None:
# Note that if map.terminator is a DevolvedDictTerminator,
# map.index() will always return -1 if selector[1]==DICT.
- _fill_cache(pycode, nameindex, map, version_tag,
attr.position)
+ _fill_cache(pycode, nameindex, map, version_tag, attr)
return attr.read_attr(w_obj)
#w_obj._mapdict_read_storage(index)
if space.config.objspace.std.withmethodcachecounter:
INVALID_CACHE_ENTRY.failure_counter += 1
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
@@ -23,7 +23,14 @@
class typedef:
hasdict = False
+def erase_storage_items(items):
+ return [erase_item(item) for item in items]
+
+def unerase_storage_items(storage):
+ return [unerase_item(item) for item in storage]
+
def test_plain_attribute():
+
w_cls = "class"
aa = PlainAttribute(("b", DICT),
PlainAttribute(("a", DICT),
@@ -33,18 +40,18 @@
assert aa.get_terminator() is aa.terminator
obj = Object()
- obj.map, obj.storage = aa, [10, 20]
+ obj.map, obj.storage = aa, erase_storage_items([10, 20])
assert obj.getdictvalue(space, "a") == 10
assert obj.getdictvalue(space, "b") == 20
assert obj.getdictvalue(space, "c") is None
obj = Object()
- obj.map, obj.storage = aa, [30, 40]
+ obj.map, obj.storage = aa, erase_storage_items([30, 40])
obj.setdictvalue(space, "a", 50)
- assert obj.storage == [50, 40]
+ assert unerase_storage_items(obj.storage) == [50, 40]
assert obj.getdictvalue(space, "a") == 50
obj.setdictvalue(space, "b", 60)
- assert obj.storage == [50, 60]
+ assert unerase_storage_items(obj.storage) == [50, 60]
assert obj.getdictvalue(space, "b") == 60
assert aa.length() == 2
@@ -73,7 +80,7 @@
cls = Class()
obj = cls.instantiate()
obj.setdictvalue(space, "a", 10)
- assert obj.storage == [10]
+ assert unerase_storage_items(obj.storage) == [10]
assert obj.getdictvalue(space, "a") == 10
assert obj.getdictvalue(space, "b") is None
assert obj.getdictvalue(space, "c") is None
@@ -83,7 +90,7 @@
assert obj.getdictvalue(space, "c") is None
obj.setdictvalue(space, "b", 30)
- assert obj.storage == [20, 30]
+ assert unerase_storage_items(obj.storage) == [20, 30]
assert obj.getdictvalue(space, "a") == 20
assert obj.getdictvalue(space, "b") == 30
assert obj.getdictvalue(space, "c") is None
@@ -106,12 +113,12 @@
obj.setdictvalue(space, "a", 50)
obj.setdictvalue(space, "b", 60)
obj.setdictvalue(space, "c", 70)
- assert obj.storage == [50, 60, 70]
+ assert unerase_storage_items(obj.storage) == [50, 60, 70]
res = obj.deldictvalue(space, dattr)
assert res
s = [50, 60, 70]
del s[i]
- assert obj.storage == s
+ assert unerase_storage_items(obj.storage) == s
obj = c.instantiate()
obj.setdictvalue(space, "a", 50)
@@ -134,7 +141,7 @@
c2 = Class()
obj.setclass(space, c2)
assert obj.getclass(space) is c2
- assert obj.storage == [50, 60, 70]
+ assert unerase_storage_items(obj.storage) == [50, 60, 70]
def test_special():
from pypy.module._weakref.interp__weakref import WeakrefLifeline
@@ -150,7 +157,7 @@
assert obj.getdictvalue(space, "a") == 50
assert obj.getdictvalue(space, "b") == 60
assert obj.getdictvalue(space, "c") == 70
- assert obj.storage == [50, 60, 70, lifeline1]
+ assert unerase_storage_items(obj.storage) == [50, 60, 70, lifeline1]
assert obj.getweakref() is lifeline1
obj2 = c.instantiate()
@@ -158,7 +165,7 @@
obj2.setdictvalue(space, "b", 160)
obj2.setdictvalue(space, "c", 170)
obj2.setweakref(space, lifeline2)
- assert obj2.storage == [150, 160, 170, lifeline2]
+ assert unerase_storage_items(obj2.storage) == [150, 160, 170, lifeline2]
assert obj2.getweakref() is lifeline2
assert obj2.map is obj.map
@@ -188,7 +195,7 @@
assert obj.getslotvalue(a) == 50
assert obj.getslotvalue(b) == 60
assert obj.getslotvalue(c) == 70
- assert obj.storage == [50, 60, 70]
+ assert unerase_storage_items(obj.storage) == [50, 60, 70]
obj.setdictvalue(space, "a", 5)
obj.setdictvalue(space, "b", 6)
@@ -199,7 +206,7 @@
assert obj.getslotvalue(a) == 50
assert obj.getslotvalue(b) == 60
assert obj.getslotvalue(c) == 70
- assert obj.storage == [50, 60, 70, 5, 6, 7]
+ assert unerase_storage_items(obj.storage) == [50, 60, 70, 5, 6, 7]
obj2 = cls.instantiate()
obj2.setslotvalue(a, 501)
@@ -208,13 +215,13 @@
obj2.setdictvalue(space, "a", 51)
obj2.setdictvalue(space, "b", 61)
obj2.setdictvalue(space, "c", 71)
- assert obj2.storage == [501, 601, 701, 51, 61, 71]
+ assert unerase_storage_items(obj2.storage) == [501, 601, 701, 51, 61, 71]
assert obj.map is obj2.map
assert obj2.getslotvalue(b) == 601
assert obj2.delslotvalue(b)
assert obj2.getslotvalue(b) is None
- assert obj2.storage == [501, 701, 51, 61, 71]
+ assert unerase_storage_items(obj2.storage) == [501, 701, 51, 61, 71]
assert not obj2.delslotvalue(b)
@@ -228,7 +235,7 @@
obj.setslotvalue(b, 60)
assert obj.getslotvalue(a) == 50
assert obj.getslotvalue(b) == 60
- assert obj.storage == [50, 60]
+ assert unerase_storage_items(obj.storage) == [50, 60]
assert not obj.setdictvalue(space, "a", 70)
def test_getdict():
@@ -253,7 +260,7 @@
obj.setdictvalue(space, "a", 5)
obj.setdictvalue(space, "b", 6)
obj.setdictvalue(space, "c", 7)
- assert obj.storage == [50, 60, 70, 5, 6, 7]
+ assert unerase_storage_items(obj.storage) == [50, 60, 70, 5, 6, 7]
class FakeDict(W_DictMultiObject):
def __init__(self, d):
@@ -270,7 +277,7 @@
assert flag
materialize_r_dict(space, obj, d)
assert d == {"a": 5, "b": 6, "c": 7}
- assert obj.storage == [50, 60, 70, w_d]
+ assert unerase_storage_items(obj.storage) == [50, 60, 70, w_d]
def test_size_prediction():
@@ -442,6 +449,17 @@
def setup_class(cls):
cls.space = gettestobjspace(**{"objspace.std.withmapdict": True})
+ def test_reading_twice(self):
+ class A(object):
+ pass
+ a = A()
+ a.x = 42
+
+ assert a.x == 42
+ print "read once"
+ assert a.x == 42
+ print "read twice"
+
def test_simple(self):
class A(object):
pass
@@ -664,6 +682,7 @@
INVALID_CACHE_ENTRY.failure_counter = 0
#
w_res = space.call_function(w_func)
+ print w_res
assert space.eq_w(w_res, space.wrap(42))
#
entry = w_code._mapdict_caches[nameindex]
@@ -677,6 +696,15 @@
check.unwrap_spec = [gateway.ObjSpace, gateway.W_Root, str]
cls.w_check = cls.space.wrap(gateway.interp2app(check))
+ def test_do_not_change_while_counting(self):
+ class A(object):
+ pass
+ a = A()
+ a.x = 42
+
+ assert a.x == 42
+ assert a.x == 42
+
def test_simple(self):
class A(object):
pass
@@ -685,7 +713,14 @@
def f():
return a.x
#
+ print "1"
+ assert a.x == 42
+ print "2"
+ assert a.x == 42
+ print "3"
+ print "first check"
res = self.check(f, 'x')
+ print "second check"
assert res == (1, 0, 0)
res = self.check(f, 'x')
assert res == (0, 1, 0)
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit