Author: Armin Rigo <[email protected]>
Branch: mapdict-interp
Changeset: r44269:54e1837aa815
Date: 2011-05-17 17:54 +0200
http://bitbucket.org/pypy/pypy/changeset/54e1837aa815/

Log:    Unsure if this is a good idea: fix (well, minimize at least) the
        issue of trashing the cache described in the XXX that this checkin
        removed; also, avoids creating tons of CacheEntry instances for all
        the code objects that are executed only once or twice.

diff --git a/pypy/objspace/std/callmethod.py b/pypy/objspace/std/callmethod.py
--- a/pypy/objspace/std/callmethod.py
+++ b/pypy/objspace/std/callmethod.py
@@ -65,7 +65,7 @@
                             not jit.we_are_jitted()):
                         # let mapdict cache stuff
                         LOOKUP_METHOD_mapdict_fill_cache_method(
-                            space, f.getcode(), name, nameindex, w_obj, w_type)
+                            f.getcode(), name, nameindex, w_obj, w_type)
                     return
     if w_value is None:
         w_value = space.getattr(w_obj, w_name)
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
@@ -717,11 +717,23 @@
 INVALID_CACHE_ENTRY = CacheEntry()
 INVALID_CACHE_ENTRY.map_wref = weakref.ref(_invalid_cache_entry_map)
                                  # different from any real map ^^^
+INVALID_CACHE_ENTRY.index = 0
+REBUILD_CACHE_FREQUENCY = 5        # xxx tweak?
+
 
 def init_mapdict_cache(pycode):
     num_entries = len(pycode.co_names_w)
     pycode._mapdict_caches = [INVALID_CACHE_ENTRY] * num_entries
 
+def _rebuild_cache_now():
+    if INVALID_CACHE_ENTRY.index == 0:
+        INVALID_CACHE_ENTRY.index = REBUILD_CACHE_FREQUENCY - 1
+        return True
+    else:
+        INVALID_CACHE_ENTRY.index -= 1
+        return False
+_rebuild_cache_now._always_inline_ = True
+
 @jit.dont_look_inside
 def _fill_cache(pycode, nameindex, map, version_tag, index, w_method=None):
     entry = pycode._mapdict_caches[nameindex]
@@ -743,7 +755,12 @@
     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 LOAD_ATTR_slowpath(pycode, w_obj, nameindex, map)
+    #
+    if _rebuild_cache_now():
+        return LOAD_ATTR_slowpath(pycode, w_obj, nameindex, map)
+    else:
+        w_name = pycode.co_names_w[nameindex]
+        return pycode.space.getattr(w_obj, w_name)
 LOAD_ATTR_caching._always_inline_ = True
 
 def LOAD_ATTR_slowpath(pycode, w_obj, nameindex, map):
@@ -807,8 +824,7 @@
             return True
     return False
 
-def LOOKUP_METHOD_mapdict_fill_cache_method(space, pycode, name, nameindex,
-                                            w_obj, w_type):
+def _LOOKUP_METHOD_mapdict_slow_path(pycode, name, nameindex, w_obj, w_type):
     version_tag = w_type.version_tag()
     if version_tag is None:
         return
@@ -820,13 +836,17 @@
     # in the class, this time taking care of the result: it can be either a
     # quasi-constant class attribute, or actually a TypeCell --- which we
     # must not cache.  (It should not be None here, but you never know...)
-    assert space.config.objspace.std.withmethodcache
+    assert pycode.space.config.objspace.std.withmethodcache
     _, w_method = w_type._pure_lookup_where_with_method_cache(name,
                                                               version_tag)
     if w_method is None or isinstance(w_method, TypeCell):
         return
     _fill_cache(pycode, nameindex, map, version_tag, -1, w_method)
+_LOOKUP_METHOD_mapdict_slow_path._dont_inline_ = True
 
-# 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
-# XXX rebuilding the cache
+def LOOKUP_METHOD_mapdict_fill_cache_method(pycode, name, nameindex,
+                                            w_obj, w_type):
+    if _rebuild_cache_now():
+        _LOOKUP_METHOD_mapdict_slow_path(pycode, name, nameindex,
+                                         w_obj, w_type)
+LOOKUP_METHOD_mapdict_fill_cache_method._always_inline_ = True
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
@@ -2,6 +2,12 @@
 from pypy.objspace.std.test.test_dictmultiobject import FakeSpace, 
W_DictMultiObject
 from pypy.objspace.std.mapdict import *
 
+def setup_module(mod):
+    # force this value to 1 during testing...
+    from pypy.objspace.std import mapdict
+    mapdict.REBUILD_CACHE_FREQUENCY = 1
+
+
 space = FakeSpace()
 
 class Class(object):
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to