Author: Carl Friedrich Bolz <[email protected]>
Branch: guard-compatible
Changeset: r83140:bae02262ef63
Date: 2016-03-18 14:44 +0100
http://bitbucket.org/pypy/pypy/changeset/bae02262ef63/
Log: simply the interpreter caches a lot to use the version on the map.
Makes the fast path significantly faster.
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
@@ -310,7 +310,7 @@
_immutable_fields_ = ['w_cls', 'version?']
def __init__(self, space, w_cls):
- if w_cls._version_tag is None:
+ if w_cls is None or w_cls._version_tag is None:
self.version = None
else:
self.version = Version()
@@ -961,7 +961,7 @@
# Magic caching
class CacheEntry(object):
- version_tag = None
+ mapversion = None
storageindex = 0
w_method = None # for callmethod
success_counter = 0
@@ -973,35 +973,33 @@
@jit.dont_look_inside
def is_valid_for_map(self, map):
- # note that 'map' can be None here
- mymap = self.map_wref()
- if mymap is not None and mymap is map:
- version_tag = map.terminator.w_cls.version_tag()
- if version_tag is self.version_tag:
- # everything matches, it's incredibly fast
- if map.space.config.objspace.std.withmethodcachecounter:
- self.success_counter += 1
- return True
+ # since map.version can be None, self.mapversion must never be
+ # thus the INVALID_CACHE_ENTRY has a fake but non-None Version()
+ if map is not None and self.mapversion is map.version:
+ # everything matches, it's incredibly fast
+ if map.space.config.objspace.std.withmethodcachecounter:
+ self.success_counter += 1
+ return True
return False
_invalid_cache_entry_map = objectmodel.instantiate(AbstractAttribute)
_invalid_cache_entry_map.terminator = None
INVALID_CACHE_ENTRY = CacheEntry()
-INVALID_CACHE_ENTRY.map_wref = weakref.ref(_invalid_cache_entry_map)
- # different from any real map ^^^
+INVALID_CACHE_ENTRY.mapversion = Version()
+# different from any real map's version ^^^
def init_mapdict_cache(pycode):
num_entries = len(pycode.co_names_w)
pycode._mapdict_caches = [INVALID_CACHE_ENTRY] * num_entries
@jit.dont_look_inside
-def _fill_cache(pycode, nameindex, map, version_tag, storageindex,
w_method=None):
+def _fill_cache(pycode, nameindex, mapversion, storageindex, w_method=None):
+ assert isinstance(mapversion, Version)
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.mapversion = mapversion
entry.storageindex = storageindex
entry.w_method = w_method
if pycode.space.config.objspace.std.withmethodcachecounter:
@@ -1026,8 +1024,10 @@
w_descr = w_type.getattribute_if_not_from_object()
if w_descr is not None:
return space._handle_getattribute(w_descr, w_obj, w_name)
- version_tag = w_type.version_tag()
- if version_tag is not None:
+ mapversion = map.version
+ if mapversion is not None:
+ version_tag = w_type.version_tag()
+ assert version_tag is not None
name = space.str_w(w_name)
# We need to care for obscure cases in which the w_descr is
# a MutableCell, which may change without changing the version_tag
@@ -1059,7 +1059,7 @@
if attr is not None:
# Note that if map.terminator is a DevolvedDictTerminator,
# map.find_map_attr will always return None if index==DICT.
- _fill_cache(pycode, nameindex, map, version_tag,
attr.storageindex)
+ _fill_cache(pycode, nameindex, mapversion,
attr.storageindex)
return w_obj._mapdict_read_storage(attr.storageindex)
if space.config.objspace.std.withmethodcachecounter:
INVALID_CACHE_ENTRY.failure_counter += 1
@@ -1094,7 +1094,7 @@
name, version_tag)
if w_method is None or isinstance(w_method, MutableCell):
return
- _fill_cache(pycode, nameindex, map, version_tag, -1, w_method)
+ _fill_cache(pycode, nameindex, map.version, -1, w_method)
# XXX fix me: if a function contains a loop with both LOAD_ATTR and
# XXX LOOKUP_METHOD on the same attribute name, it keeps trashing and
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit