Author: Carl Friedrich Bolz <[email protected]>
Branch: value-profiling
Changeset: r78995:c0aea2847f70
Date: 2015-08-15 18:59 +0200
http://bitbucket.org/pypy/pypy/changeset/c0aea2847f70/
Log: track when lists store instances of the same (rpython level) class
diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -40,6 +40,19 @@
UNROLL_CUTOFF = 5
+class FixedClsStrategyCache(object):
+ def __init__(self, space):
+ self.space = space
+ self.generic_strategy = space.fromcache(ObjectListStrategy)
+ self.cache = {}
+
+ @jit.elidable
+ def get_or_build(self, cls):
+ strategy = self.cache.get(cls, None)
+ if strategy is None:
+ strategy = ObjectListStrategy(self.space, cls)
+ self.cache[cls] = strategy
+ return strategy
def make_range_list(space, start, step, length):
if length <= 0:
@@ -125,7 +138,15 @@
else:
return space.fromcache(IntOrFloatListStrategy)
- return space.fromcache(ObjectListStrategy)
+ cache = space.fromcache(FixedClsStrategyCache)
+
+ # check for all the same class
+ for i in range(1, len(list_w)):
+ if type(list_w[i]) is not type(w_firstobj):
+ break
+ else:
+ return cache.get_or_build(type(w_firstobj))
+ return cache.generic_strategy
def _get_printable_location(w_type):
@@ -685,7 +706,7 @@
if has_key:
sorterclass = CustomKeySort
else:
- if self.strategy is space.fromcache(ObjectListStrategy):
+ if isinstance(self.strategy, ObjectListStrategy):
sorterclass = SimpleSort
else:
self.sort(reverse)
@@ -936,7 +957,8 @@
elif type(w_item) is W_FloatObject:
strategy = self.space.fromcache(FloatListStrategy)
else:
- strategy = self.space.fromcache(ObjectListStrategy)
+ cache = self.space.fromcache(FixedClsStrategyCache)
+ strategy = cache.get_or_build(type(w_item))
storage = strategy.get_empty_storage(self.get_sizehint())
w_list.strategy = strategy
@@ -1418,9 +1440,8 @@
w_list.append(w_item)
def insert(self, w_list, index, w_item):
- l = self.unerase(w_list.lstorage)
-
if self.is_correct_type(w_item):
+ l = self.unerase(w_list.lstorage)
l.insert(index, self.unwrap(w_item))
return
@@ -1428,8 +1449,8 @@
w_list.insert(index, w_item)
def _extend_from_list(self, w_list, w_other):
- l = self.unerase(w_list.lstorage)
if self.list_is_correct_type(w_other):
+ l = self.unerase(w_list.lstorage)
l += self.unerase(w_other.lstorage)
return
elif w_other.strategy.is_empty_strategy():
@@ -1581,14 +1602,30 @@
class ObjectListStrategy(ListStrategy):
+ _immutable_fields_ = ['_known_cls']
+
import_from_mixin(AbstractUnwrappedStrategy)
_none_value = None
+ def __init__(self, space, known_cls=None):
+ self.space = space
+ self._known_cls = known_cls
+
+ def __repr__(self):
+ return "ObjectListStrategy(space, %s)" % (self._known_cls, )
+
+ @jit.elidable_promote('0')
+ def get_known_cls(self):
+ return self._known_cls
+
def unwrap(self, w_obj):
return w_obj
def wrap(self, item):
+ cls = self.get_known_cls()
+ if cls is not None:
+ jit.record_exact_class(item, cls)
return item
erase, unerase = rerased.new_erasing_pair("object")
@@ -1596,10 +1633,13 @@
unerase = staticmethod(unerase)
def is_correct_type(self, w_obj):
+ cls = self.get_known_cls()
+ if cls is not None:
+ return type(w_obj) is cls
return True
def list_is_correct_type(self, w_list):
- return w_list.strategy is self.space.fromcache(ObjectListStrategy)
+ return w_list.strategy is self
def init_from_list_w(self, w_list, list_w):
w_list.lstorage = self.erase(list_w)
diff --git a/pypy/objspace/std/test/test_liststrategies.py
b/pypy/objspace/std/test/test_liststrategies.py
--- a/pypy/objspace/std/test/test_liststrategies.py
+++ b/pypy/objspace/std/test/test_liststrategies.py
@@ -8,6 +8,8 @@
from pypy.objspace.std import listobject
from pypy.objspace.std.test.test_listobject import TestW_ListObject
+from rpython.rlib import jit
+
class TestW_ListStrategies(TestW_ListObject):
def test_check_strategy(self):
@@ -1035,6 +1037,93 @@
(int, 5), (float, 1.2), (int, 1), (float, 1.0)]
+class TestKnownClasListStrategy:
+ def test_create_from_list(self):
+ space = self.space
+ w_tup = space.wrap((1, 2))
+ w_l = W_ListObject(space, [w_tup, w_tup])
+ assert isinstance(w_l.strategy, ObjectListStrategy)
+ assert w_l.strategy._known_cls is type(w_tup)
+
+ w_l1 = W_ListObject(space, [w_tup, w_tup])
+ assert w_l1.strategy is w_l.strategy
+
+ def test_create_empty(self):
+ space = self.space
+ w_l = W_ListObject(space, [])
+ w_tup = space.wrap((1, 2))
+ w_l.append(w_tup)
+ assert isinstance(w_l.strategy, ObjectListStrategy)
+ assert w_l.strategy._known_cls is type(w_tup)
+ w_l.append(w_tup)
+ assert w_l.strategy._known_cls is type(w_tup)
+
+ def test_append(self):
+ space = self.space
+ w_tup = space.wrap((1, 2))
+ w_l = W_ListObject(space, [w_tup, w_tup])
+ strategy = w_l.strategy
+ w_l.append(w_tup)
+ assert strategy is w_l.strategy
+ w_l.append(w_l)
+ assert w_l.strategy.get_known_cls() is None
+
+ def test_setitem(self):
+ space = self.space
+ w_tup = space.wrap((1, 2))
+ w_l = W_ListObject(space, [w_tup, w_tup])
+ w_l.setitem(0, w_tup)
+ assert w_l.strategy.get_known_cls() is type(w_tup)
+ w_l.setitem(0, w_l)
+ assert w_l.strategy.get_known_cls() is None
+
+ def test_extend(self):
+ space = self.space
+ w_tup = space.wrap((1, 2))
+ w_l = W_ListObject(space, [w_tup, w_tup])
+ w_l1 = W_ListObject(space, [w_tup, w_tup])
+ w_l.extend(w_l1)
+ assert w_l.strategy.get_known_cls() is type(w_tup)
+
+ w_l2 = W_ListObject(space, [w_l, w_l])
+ w_l.extend(w_l2)
+ assert w_l.strategy.get_known_cls() is None
+
+ def test_getslice(self):
+ space = self.space
+ w_tup = space.wrap((1, 2))
+ w_l = W_ListObject(space, [w_tup, w_tup, w_tup])
+ w_l1 = w_l.getslice(0, 1, 1, 1)
+ assert w_l.strategy is w_l1.strategy
+
+ def test_setslice(self):
+ space = self.space
+ w_tup = space.wrap((1, 2))
+ w_l = W_ListObject(space, [w_tup, w_tup, w_tup])
+ w_l.setslice(0, 1, 2, W_ListObject(space, [w_tup, w_tup, w_tup]))
+ assert w_l.strategy.get_known_cls() is type(w_tup)
+ w_l.setslice(0, 1, 2, W_ListObject(space, [w_l, w_tup, w_tup]))
+ assert w_l.strategy.get_known_cls() is None
+
+ def test_propagate_cls_knowledge(self, monkeypatch):
+ l = []
+ def record_exact_class(obj, cls):
+ assert type(obj) is cls
+ l.append((obj, cls))
+ monkeypatch.setattr(jit, 'record_exact_class', record_exact_class)
+
+ space = self.space
+ w_tup = space.wrap((1, 2))
+ w_l = W_ListObject(space, [w_tup, w_tup, w_tup])
+ w_tup1 = w_l.getitem(0)
+ assert w_tup1 is w_tup
+ assert l == [(w_tup, type(w_tup))] * 1
+
+ w_tup1 = w_l.pop_end()
+ assert w_tup1 is w_tup
+ assert l == [(w_tup, type(w_tup))] * 2
+
+
class TestW_ListStrategiesDisabled:
spaceconfig = {"objspace.std.withliststrategies": False}
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit