[pypy-svn] r7360 - in pypy/trunk/src: goal pypy/annotation pypy/interpreter pypy/interpreter/test pypy/objspace/flow pypy/objspace/std pypy/tool pypy/tool/test
hpk at codespeak.net
hpk at codespeak.net
Thu Nov 18 11:18:30 CET 2004
Author: hpk
Date: Thu Nov 18 11:18:30 2004
New Revision: 7360
Added:
pypy/trunk/src/pypy/tool/cache.py
- copied, changed from r7351, pypy/trunk/src/pypy/tool/frozendict.py
pypy/trunk/src/pypy/tool/test/test_cache.py
Removed:
pypy/trunk/src/pypy/tool/frozendict.py
Modified:
pypy/trunk/src/goal/buildcache.py
pypy/trunk/src/goal/translate_pypy.py
pypy/trunk/src/pypy/annotation/model.py
pypy/trunk/src/pypy/interpreter/baseobjspace.py
pypy/trunk/src/pypy/interpreter/gateway.py
pypy/trunk/src/pypy/interpreter/pycode.py
pypy/trunk/src/pypy/interpreter/pyopcode.py
pypy/trunk/src/pypy/interpreter/test/test_code.py
pypy/trunk/src/pypy/objspace/flow/specialcase.py
pypy/trunk/src/pypy/objspace/std/fake.py
pypy/trunk/src/pypy/objspace/std/multimethod.py
pypy/trunk/src/pypy/objspace/std/objspace.py
Log:
frozendict is dead, long live the freezable Cache class.
for any code reachable by the annotator/translator you need to/should
use pypy.tool.cache.Cache(). When the annotator sees such a
cache it calls the "freeze()" method on it after which it cannot be
modified anymore and also becomes hashable as a side effect.
A Cache has a getorbuild() method where you pass in a key, a builder
and a space. In case the key is not in the cache yet and the cache
is not frozen, builder(key, space) will be called to obtain the
value.
Various places now use Cache instead of plain dictionaries.
Modified: pypy/trunk/src/goal/buildcache.py
==============================================================================
--- pypy/trunk/src/goal/buildcache.py (original)
+++ pypy/trunk/src/goal/buildcache.py Thu Nov 18 11:18:30 2004
@@ -1,6 +1,5 @@
from pypy.tool import option, autopath, testit
from pypy.interpreter import gateway
-from pypy.tool.frozendict import frozendict
import os
#######################################################
@@ -32,14 +31,21 @@
gateway.importall(globals()) # app_xxx() -> xxx()
#######################################################
+from pypy.objspace.std import stdtypedef
def buildcache(space):
print "triggering cache build for %r" % space
triggerall(space)
triggerexec(space)
- space._typecache = frozendict(space._typecache)
- space._faketypecache = frozendict(space._faketypecache)
- space._gatewaycache = frozendict(space._gatewaycache)
+ #testit.main(os.path.join(autopath.pypydir, 'objspace', 'std'))
+ #Cache.freeze()
+ #space._typecache = frozendict(space._typecache)
+ #space._faketypecache = frozendict(space._faketypecache)
+ #space._gatewaycache = frozendict(space._gatewaycache)
+ #space = option.objspace('std')
+ #buildcache(space)
+ #for x in stdtypedef._temp:
+ # x.cache_table = frozendict(x.cache_table)
print "cache build finished, caches are 'frozen' now"
if __name__ == '__main__':
Modified: pypy/trunk/src/goal/translate_pypy.py
==============================================================================
--- pypy/trunk/src/goal/translate_pypy.py (original)
+++ pypy/trunk/src/goal/translate_pypy.py Thu Nov 18 11:18:30 2004
@@ -6,9 +6,9 @@
from pypy.objspace.std.intobject import W_IntObject
from pypy.translator.translator import Translator
from pypy.annotation import model as annmodel
+from pypy.tool.cache import Cache
-import buildcache
-
+#from buildcache import buildcache
# __________ Entry point __________
def entry_point():
@@ -22,12 +22,13 @@
def analyse(entry_point=entry_point):
global t, space
space = StdObjSpace()
- buildcache.buildcache(space)
+ # call the entry_point once to trigger building of all
+ # caches (as far as analyzing the entry_point is concerned)
+ entry_point()
t = Translator(entry_point, verbose=True, simplifying=True)
a = t.annotate([])
a.simplify()
-
if __name__ == '__main__':
def about(x):
Modified: pypy/trunk/src/pypy/annotation/model.py
==============================================================================
--- pypy/trunk/src/pypy/annotation/model.py (original)
+++ pypy/trunk/src/pypy/annotation/model.py Thu Nov 18 11:18:30 2004
@@ -33,6 +33,7 @@
import pypy
from pypy.annotation.pairtype import pair, extendabletype
from pypy.objspace.flow.model import Constant
+from pypy.tool.cache import Cache
class SomeObject:
"""The set of all objects. Each instance stands
@@ -215,6 +216,8 @@
else:
result = SomeCallable({x : True})
elif hasattr(x, '__class__') and x.__class__.__module__ != '__builtin__':
+ if isinstance(x, Cache) and not x.frozen:
+ x.freeze()
result = SomePrebuiltConstant({x: True}) # pre-built inst:
else:
result = SomeObject()
Modified: pypy/trunk/src/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/baseobjspace.py (original)
+++ pypy/trunk/src/pypy/interpreter/baseobjspace.py Thu Nov 18 11:18:30 2004
@@ -2,7 +2,7 @@
from pypy.interpreter.error import OperationError
from pypy.interpreter.miscutils import getthreadlocals
from pypy.interpreter.argument import Arguments
-from pypy.tool.frozendict import frozendict
+from pypy.tool.cache import Cache
__all__ = ['ObjSpace', 'OperationError', 'Wrappable', 'BaseWrappable',
'W_Root']
@@ -33,21 +33,10 @@
def __init__(self):
"Basic initialization of objects."
- self._gatewaycache = {}
+ self._gatewaycache = Cache()
# sets all the internal descriptors
self.initialize()
- def loadfromcache(self, key, builder, cache):
- try:
- return cache[key]
- except KeyError:
- assert not isinstance(cache, frozendict)
- #print "building for key %r" % key
- return cache.setdefault(key, builder(key, self))
- # note to annotator: we want loadfromcache() to be
- # specialized for the different cache types
- loadfromcache.specialize = True
-
def make_builtins(self, for_builtins):
# initializing builtins may require creating a frame which in
# turn already accesses space.w_builtins, provide a dummy one ...
@@ -101,6 +90,10 @@
"""Abstract method that should put some minimal content into the
w_builtins."""
+ def loadfromcache(self, key, builder, cache):
+ return cache.getorbuild(key, builder, self)
+ loadfromcache.specialize = True
+
def getexecutioncontext(self):
"Return what we consider to be the active execution context."
ec = getthreadlocals().executioncontext
Modified: pypy/trunk/src/pypy/interpreter/gateway.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/gateway.py (original)
+++ pypy/trunk/src/pypy/interpreter/gateway.py Thu Nov 18 11:18:30 2004
@@ -15,7 +15,7 @@
from pypy.interpreter.function import Function, Method
from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.argument import Arguments
-
+from pypy.tool.cache import Cache
class BuiltinCode(eval.Code):
"The code object implementing a built-in (interpreter-level) hook."
@@ -358,10 +358,10 @@
# temporary/initialization purposes
class app2interp_temp(app2interp):
def getcache(self, space):
- return self.__dict__.setdefault(space, {})
+ return self.__dict__.setdefault(space, Cache())
# ^^^^^
# armin suggested this
class interp2app_temp(interp2app):
def getcache(self, space):
- return self.__dict__.setdefault(space, {})
+ return self.__dict__.setdefault(space, Cache())
Modified: pypy/trunk/src/pypy/interpreter/pycode.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/pycode.py (original)
+++ pypy/trunk/src/pypy/interpreter/pycode.py Thu Nov 18 11:18:30 2004
@@ -6,6 +6,7 @@
import dis
from pypy.interpreter import eval
+from pypy.tool.cache import Cache
# code object contants, for co_flags below
CO_OPTIMIZED = 0x0001
@@ -130,7 +131,7 @@
code.co_cellvars = space.unwrap(w_cellvars)
return space.wrap(code)
-def enhanceclass(baseclass, newclass, cache={}):
+def enhanceclass(baseclass, newclass, cache=Cache()):
# this is a bit too dynamic for RPython, but it looks nice
# and I assume that we can easily change it into a static
# pre-computed table
@@ -140,20 +141,8 @@
try:
return cache[baseclass, newclass]
except KeyError:
+ assert not cache.frozen
class Mixed(newclass, baseclass):
pass
cache[baseclass, newclass] = Mixed
return Mixed
-
-def keys():
- from pypy.interpreter.pyopcode import PyInterpFrame as Frame
- from pypy.interpreter.nestedscope import PyNestedScopeFrame
- from pypy.interpreter.generator import GeneratorFrame
-
- return [
- (Frame, PyNestedScopeFrame),
- (Frame, GeneratorFrame),
- (enhanceclass(Frame, PyNestedScopeFrame), GeneratorFrame),
- ]
-
-enhanceclass.keys = keys
Modified: pypy/trunk/src/pypy/interpreter/pyopcode.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/pyopcode.py (original)
+++ pypy/trunk/src/pypy/interpreter/pyopcode.py Thu Nov 18 11:18:30 2004
@@ -342,7 +342,7 @@
w_globals = f.valuestack.pop()
w_prog = f.valuestack.pop()
w_resulttuple = f.prepare_exec(w_prog, w_globals, w_locals)
- w_prog, w_globals, w_locals = f.space.unpacktuple(w_resulttuple)
+ w_prog, w_globals, w_locals = f.space.unpacktuple(w_resulttuple, 3)
plain = f.space.is_true(f.space.is_(w_locals, f.w_locals))
if plain:
Modified: pypy/trunk/src/pypy/interpreter/test/test_code.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/test/test_code.py (original)
+++ pypy/trunk/src/pypy/interpreter/test/test_code.py Thu Nov 18 11:18:30 2004
@@ -92,15 +92,5 @@
exec co in d
self.assertEquals(d['c'], 3)
-class TestCodeEnhanceClass(testit.IntTestCase):
- def test_enhanceclass_for_translator(self):
- from pypy.interpreter.pycode import enhanceclass
- assert hasattr(enhanceclass, 'keys')
- arglist = enhanceclass.keys()
- for args in arglist:
- enhanceclass(*args)
-
-
-
if __name__ == '__main__':
testit.main()
Modified: pypy/trunk/src/pypy/objspace/flow/specialcase.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/flow/specialcase.py (original)
+++ pypy/trunk/src/pypy/objspace/flow/specialcase.py Thu Nov 18 11:18:30 2004
@@ -43,15 +43,6 @@
# this function returns a real tuple that can be handled
# by FlowObjSpace.unpacktuple()
-def loadfromcache(space, args):
- # XXX need some way to know how to fully initialize the cache
- print space, args
- assert len(args.args_w) == 2 and args.kwds_w == {}
- w_key, w_builder = args.args_w
- w_cache = Constant('space_cache') # temporary
- return space.do_operation('getitem', w_cache, w_key)
-
-
def import_(space, args):
assert len(args.args_w) == 4 and args.kwds_w == {}
unwrapped_args = []
@@ -63,6 +54,4 @@
def setup(space):
fn = pyframe.normalize_exception.get_function(space)
space.specialcases[fn] = normalize_exception
- fn = baseobjspace.ObjSpace.loadfromcache.im_func
- space.specialcases[fn] = loadfromcache
space.specialcases[__import__] = import_
Modified: pypy/trunk/src/pypy/objspace/std/fake.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/fake.py (original)
+++ pypy/trunk/src/pypy/objspace/std/fake.py Thu Nov 18 11:18:30 2004
@@ -4,6 +4,7 @@
from pypy.objspace.std.stdtypedef import *
from pypy.objspace.std.objspace import W_Object, StdObjSpace
from pypy.objspace.std.default import UnwrapError
+from pypy.tool.cache import Cache
# this file automatically generates non-reimplementations of CPython
# types that we do not yet implement in the standard object space
@@ -11,7 +12,7 @@
import sys
-_fake_type_cache = {}
+_fake_type_cache = Cache()
# real-to-wrapped exceptions
def wrap_exception(space):
@@ -35,6 +36,7 @@
assert type(cpy_type) is type
if cpy_type in _fake_type_cache:
return _fake_type_cache[cpy_type]
+ assert not _fake_type_cache.frozen
print 'faking %r'%(cpy_type,)
kw = {}
for s, v in cpy_type.__dict__.items():
Modified: pypy/trunk/src/pypy/objspace/std/multimethod.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/multimethod.py (original)
+++ pypy/trunk/src/pypy/objspace/std/multimethod.py Thu Nov 18 11:18:30 2004
@@ -1,6 +1,5 @@
from pypy.interpreter.baseobjspace import OperationError
-from pypy.tool.frozendict import frozendict
-
+from pypy.tool.cache import Cache
class FailedToImplement(Exception):
"Signals the dispatcher to try harder."
@@ -43,7 +42,7 @@
self.arity = arity
self.operatorsymbol = operatorsymbol
self.dispatch_table = {}
- self.cache_table = {}
+ self.cache_table = Cache()
self.cache_delegator_key = None
self.dispatch_arity = 0
@@ -76,7 +75,7 @@
try:
return self.cache_table[argclasses]
except KeyError:
- assert not isinstance(self.cache_table, frozendict)
+ assert not self.cache_table.frozen
calllist = []
self.internal_buildcalllist(argclasses, delegate, calllist)
result = self.internal_compilecalllist(argclasses, calllist)
Modified: pypy/trunk/src/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/objspace.py (original)
+++ pypy/trunk/src/pypy/objspace/std/objspace.py Thu Nov 18 11:18:30 2004
@@ -2,6 +2,7 @@
from pypy.interpreter.baseobjspace import *
from pypy.interpreter.typedef import get_unique_interplevel_subclass
from pypy.interpreter.typedef import instantiate
+from pypy.tool.cache import Cache
from pypy.objspace.std.multimethod import *
from pypy.objspace.descroperation import DescrOperation
from pypy.objspace.std import stdtypedef
@@ -135,8 +136,8 @@
return done
def initialize(self):
- self._typecache = {}
- self._faketypecache = {}
+ self._typecache = Cache()
+ self._faketypecache = Cache()
# The object implementations that we want to 'link' into PyPy must be
# imported here. This registers them into the multimethod tables,
Copied: pypy/trunk/src/pypy/tool/cache.py (from r7351, pypy/trunk/src/pypy/tool/frozendict.py)
==============================================================================
--- pypy/trunk/src/pypy/tool/frozendict.py (original)
+++ pypy/trunk/src/pypy/tool/cache.py Thu Nov 18 11:18:30 2004
@@ -1,16 +1,36 @@
+class basecache(dict):
+ pass
+
# hacks += 1
-class frozendict(dict):
- _hash_cache = None
- def __setitem__(self, *args):
- raise TypeError, "this dict is already frozen, you are too late!"
- __delitem__ = setdefault = update = pop = popitem = clear = __setitem__
+class Cache(dict):
+ frozen = True
+
+ def __init__(self, *args):
+ self.frozen = False
+ dict.__init__(self, *args)
+ for x in ('__setitem__', '__delitem__', 'setdefault', 'update',
+ 'pop', 'popitem', 'clear'):
+ l=["def %s(self, *args):",
+ " assert not self.frozen, 'cache already frozen'",
+ " return dict.%s(self, *args)"]
+ exec "\n".join(l) % (x,x)
+
def __hash__(self):
- rval = self._hash_cache
- if rval is None:
- dct = self.items()
- dct.sort()
- rval = self._hash_cache = hash(tuple(dct)) ^ 0x18293742
- return rval
+ if not self.frozen:
+ raise TypeError, "cannot get hash of un-frozen cache"
+ return id(self)
+
+ def getorbuild(self, key, builder, space):
+ try:
+ return self[key]
+ except KeyError:
+ assert not self.frozen, "cannot build %r, cache already frozen" % key
+ return self.setdefault(key, builder(key, space))
+ # note to annotator: we want loadfromcache() to be
+ # specialized for the different cache types
+ getorbuild.specialize = True
+ def freeze(self):
+ del self.frozen
Deleted: /pypy/trunk/src/pypy/tool/frozendict.py
==============================================================================
--- /pypy/trunk/src/pypy/tool/frozendict.py Thu Nov 18 11:18:30 2004
+++ (empty file)
@@ -1,16 +0,0 @@
-
-# hacks += 1
-class frozendict(dict):
- _hash_cache = None
- def __setitem__(self, *args):
- raise TypeError, "this dict is already frozen, you are too late!"
- __delitem__ = setdefault = update = pop = popitem = clear = __setitem__
-
- def __hash__(self):
- rval = self._hash_cache
- if rval is None:
- dct = self.items()
- dct.sort()
- rval = self._hash_cache = hash(tuple(dct)) ^ 0x18293742
- return rval
-
Added: pypy/trunk/src/pypy/tool/test/test_cache.py
==============================================================================
--- (empty file)
+++ pypy/trunk/src/pypy/tool/test/test_cache.py Thu Nov 18 11:18:30 2004
@@ -0,0 +1,17 @@
+import autopath
+import unittest
+from pypy.tool.cache import Cache
+
+class TestCache(unittest.TestCase):
+ def test_getorbuild(self):
+ cache = Cache()
+ cache.getorbuild(1, lambda k,s: 42, None)
+ assert 1 in cache
+ assert cache[1] == 42
+ assert cache.getorbuild(1, lambda k,s: 44, None) == 42
+ self.assertRaises(TypeError, hash, cache)
+ cache.freeze()
+ hash(cache)
+
+if __name__ == '__main__':
+ unittest.main()
More information about the Pypy-commit
mailing list