[pypy-svn] r68930 - in pypy/trunk/pypy: config doc/config interpreter interpreter/test jit/tl module/__builtin__ module/__builtin__/test module/operator module/sys module/sys/test objspace objspace/std objspace/std/test
cfbolz at codespeak.net
cfbolz at codespeak.net
Tue Nov 3 11:42:44 CET 2009
Author: cfbolz
Date: Tue Nov 3 11:42:42 2009
New Revision: 68930
Added:
pypy/trunk/pypy/doc/config/objspace.std.withinlineddict.txt (contents, props changed)
pypy/trunk/pypy/objspace/std/inlinedict.py (contents, props changed)
pypy/trunk/pypy/objspace/std/test/test_inlinedict.py (contents, props changed)
Removed:
pypy/trunk/pypy/doc/config/objspace.std.withbucketdict.txt
pypy/trunk/pypy/objspace/std/dictbucket.py
pypy/trunk/pypy/objspace/std/test/test_dictbucket.py
Modified:
pypy/trunk/pypy/config/pypyoption.py
pypy/trunk/pypy/interpreter/baseobjspace.py
pypy/trunk/pypy/interpreter/function.py
pypy/trunk/pypy/interpreter/main.py
pypy/trunk/pypy/interpreter/mixedmodule.py
pypy/trunk/pypy/interpreter/pyopcode.py
pypy/trunk/pypy/interpreter/test/test_function.py
pypy/trunk/pypy/interpreter/test/test_typedef.py
pypy/trunk/pypy/interpreter/typedef.py
pypy/trunk/pypy/jit/tl/pypyjit.py
pypy/trunk/pypy/module/__builtin__/interp_classobj.py
pypy/trunk/pypy/module/__builtin__/test/test_classobj.py
pypy/trunk/pypy/module/operator/__init__.py
pypy/trunk/pypy/module/sys/__init__.py
pypy/trunk/pypy/module/sys/test/test_sysmodule.py
pypy/trunk/pypy/objspace/descroperation.py
pypy/trunk/pypy/objspace/std/callmethod.py
pypy/trunk/pypy/objspace/std/celldict.py
pypy/trunk/pypy/objspace/std/dictmultiobject.py
pypy/trunk/pypy/objspace/std/dicttype.py
pypy/trunk/pypy/objspace/std/marshal_impl.py
pypy/trunk/pypy/objspace/std/model.py
pypy/trunk/pypy/objspace/std/objectobject.py
pypy/trunk/pypy/objspace/std/objecttype.py
pypy/trunk/pypy/objspace/std/objspace.py
pypy/trunk/pypy/objspace/std/proxyobject.py
pypy/trunk/pypy/objspace/std/sharingdict.py
pypy/trunk/pypy/objspace/std/test/test_celldict.py
pypy/trunk/pypy/objspace/std/test/test_dictmultiobject.py
pypy/trunk/pypy/objspace/std/test/test_obj.py
pypy/trunk/pypy/objspace/std/test/test_shadowtracking.py
pypy/trunk/pypy/objspace/std/typeobject.py
pypy/trunk/pypy/objspace/std/typetype.py
pypy/trunk/pypy/objspace/taint.py
Log:
Merge the shrink-multidict branch:
------------------------------------------------------------------------
r68599 | cfbolz | 2009-10-17 18:49:36 +0200 (Sat, 17 Oct 2009) | 2 lines
Changed paths:
A /pypy/branch/shrink-multidict (from /pypy/trunk:68598)
resurrect the branch to try again
------------------------------------------------------------------------
r68749 | cfbolz | 2009-10-26 14:46:32 +0100 (Mon, 26 Oct 2009) | 5 lines
Changed paths:
M /pypy/branch/shrink-multidict/pypy/interpreter/baseobjspace.py
M /pypy/branch/shrink-multidict/pypy/interpreter/typedef.py
M /pypy/branch/shrink-multidict/pypy/module/__builtin__/interp_classobj.py
M /pypy/branch/shrink-multidict/pypy/module/__builtin__/test/test_classobj.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/celldict.py
D /pypy/branch/shrink-multidict/pypy/objspace/std/dictbucket.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/dictmultiobject.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/dicttype.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/marshal_impl.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/objspace.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/sharingdict.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/test/test_celldict.py
D /pypy/branch/shrink-multidict/pypy/objspace/std/test/test_dictbucket.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/test/test_dictmultiobject.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/test/test_shadowtracking.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/typeobject.py
Refactor the multidict to use one level of indirection less. Instead of having
an indirection, all W_DictMultiObjects have an attribute r_dict_content that is
usually None. When the dict devolves, it is set to an r_dict and used instead of
the normal attributes.
------------------------------------------------------------------------
r68751 | cfbolz | 2009-10-26 15:28:38 +0100 (Mon, 26 Oct 2009) | 2 lines
Changed paths:
M /pypy/branch/shrink-multidict/pypy/objspace/std/objectobject.py
don't use * import
------------------------------------------------------------------------
r68752 | cfbolz | 2009-10-26 15:34:37 +0100 (Mon, 26 Oct 2009) | 2 lines
Changed paths:
M /pypy/branch/shrink-multidict/pypy/objspace/std/test/test_obj.py
uh?
------------------------------------------------------------------------
r68753 | cfbolz | 2009-10-26 15:34:58 +0100 (Mon, 26 Oct 2009) | 2 lines
Changed paths:
M /pypy/branch/shrink-multidict/pypy/objspace/std/objecttype.py
remove old commented out code
------------------------------------------------------------------------
r68754 | cfbolz | 2009-10-26 15:43:38 +0100 (Mon, 26 Oct 2009) | 2 lines
Changed paths:
M /pypy/branch/shrink-multidict/pypy/objspace/std/celldict.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/dictmultiobject.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/test/test_dictmultiobject.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/typeobject.py
A number of fixes.
------------------------------------------------------------------------
r68759 | cfbolz | 2009-10-26 16:54:49 +0100 (Mon, 26 Oct 2009) | 12 lines
Changed paths:
M /pypy/branch/shrink-multidict/pypy/config/pypyoption.py
M /pypy/branch/shrink-multidict/pypy/interpreter/test/test_typedef.py
M /pypy/branch/shrink-multidict/pypy/interpreter/typedef.py
A /pypy/branch/shrink-multidict/pypy/objspace/std/inlinedict.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/model.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/objspace.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/sharingdict.py
A /pypy/branch/shrink-multidict/pypy/objspace/std/test/test_inlinedict.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/test/test_shadowtracking.py
Make it possible for objects to not have an applevel dict at all:
- the W_UserDictObjectObject gets the attributes of a StrDictImplementation
inlined. As long as nobody accesses the applevel .__dict__ attribute, only
those are used
- if the __dict__ is requested, we create a dict that forwards all requests to
the instance
- if the __dict__ devolves (e.g. a non-string-key is added), the content is
stored into the r_dict_content of the forwarding dict instance. In this case
the information on the object is invalid.
------------------------------------------------------------------------
r68763 | cfbolz | 2009-10-26 18:42:39 +0100 (Mon, 26 Oct 2009) | 2 lines
Changed paths:
M /pypy/branch/shrink-multidict/pypy/interpreter/function.py
M /pypy/branch/shrink-multidict/pypy/interpreter/test/test_function.py
the repr of bound methods was wrong (and quite confusing)
------------------------------------------------------------------------
r68776 | cfbolz | 2009-10-27 10:01:24 +0100 (Tue, 27 Oct 2009) | 4 lines
Changed paths:
M /pypy/branch/shrink-multidict/pypy/interpreter/baseobjspace.py
M /pypy/branch/shrink-multidict/pypy/interpreter/mixedmodule.py
M /pypy/branch/shrink-multidict/pypy/interpreter/typedef.py
M /pypy/branch/shrink-multidict/pypy/objspace/descroperation.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/callmethod.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/celldict.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/dictmultiobject.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/inlinedict.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/objspace.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/proxyobject.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/sharingdict.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/test/test_dictmultiobject.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/test/test_inlinedict.py
A new shortcut in the objspace: finditem_str that takes an unwrapped string as
the item to find. Please don't ask me how I managed to triplicate the content of
inlinedict.py and test_inlinedict.py
------------------------------------------------------------------------
r68789 | cfbolz | 2009-10-27 14:16:35 +0100 (Tue, 27 Oct 2009) | 2 lines
Changed paths:
D /pypy/branch/shrink-multidict/pypy/doc/config/objspace.std.withbucketdict.txt
this option is gone
------------------------------------------------------------------------
r68792 | cfbolz | 2009-10-27 14:27:30 +0100 (Tue, 27 Oct 2009) | 2 lines
Changed paths:
A /pypy/branch/shrink-multidict/pypy/doc/config/objspace.std.withinlineddict.txt
document the new option
------------------------------------------------------------------------
r68819 | cfbolz | 2009-10-28 15:02:40 +0100 (Wed, 28 Oct 2009) | 2 lines
Changed paths:
M /pypy/branch/shrink-multidict/pypy/module/sys/__init__.py
M /pypy/branch/shrink-multidict/pypy/module/sys/test/test_sysmodule.py
bah, there were no tests for sys.exc_value, .exc_type and .exc_traceback
------------------------------------------------------------------------
r68820 | cfbolz | 2009-10-28 15:26:31 +0100 (Wed, 28 Oct 2009) | 2 lines
Changed paths:
M /pypy/branch/shrink-multidict/pypy/interpreter/baseobjspace.py
M /pypy/branch/shrink-multidict/pypy/interpreter/main.py
M /pypy/branch/shrink-multidict/pypy/interpreter/mixedmodule.py
M /pypy/branch/shrink-multidict/pypy/interpreter/pyopcode.py
M /pypy/branch/shrink-multidict/pypy/module/operator/__init__.py
M /pypy/branch/shrink-multidict/pypy/module/sys/__init__.py
M /pypy/branch/shrink-multidict/pypy/objspace/descroperation.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/callmethod.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/inlinedict.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/objspace.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/proxyobject.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/typeobject.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/typetype.py
M /pypy/branch/shrink-multidict/pypy/objspace/taint.py
make getdictvalue take an unwrapped string and kill getdictvalue_w
------------------------------------------------------------------------
r68821 | cfbolz | 2009-10-28 16:21:35 +0100 (Wed, 28 Oct 2009) | 3 lines
Changed paths:
M /pypy/branch/shrink-multidict/pypy/interpreter/baseobjspace.py
M /pypy/branch/shrink-multidict/pypy/interpreter/pyopcode.py
M /pypy/branch/shrink-multidict/pypy/jit/tl/pypyjit.py
M /pypy/branch/shrink-multidict/pypy/jit/tl/pypyjit_demo.py
M /pypy/branch/shrink-multidict/pypy/module/__builtin__/interp_classobj.py
M /pypy/branch/shrink-multidict/pypy/objspace/descroperation.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/celldict.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/dictmultiobject.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/inlinedict.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/objspace.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/proxyobject.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/sharingdict.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/test/test_inlinedict.py
M /pypy/branch/shrink-multidict/pypy/objspace/taint.py
M /pypy/branch/shrink-multidict/pypy/translator/goal/gcbench.py
Change setdictvalue to also take a string. Now it's asymmetric to deldictvalue,
I might not care though.
------------------------------------------------------------------------
r68912 | cfbolz | 2009-11-02 15:28:38 +0100 (Mon, 02 Nov 2009) | 2 lines
Changed paths:
M /pypy/branch/shrink-multidict/pypy/objspace/std/inlinedict.py
running the tests is generally a good idea
------------------------------------------------------------------------
r68923 | cfbolz | 2009-11-02 18:33:08 +0100 (Mon, 02 Nov 2009) | 3 lines
Changed paths:
M /pypy/branch/shrink-multidict/pypy/objspace/std/celldict.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/dictmultiobject.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/inlinedict.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/sharingdict.py
M /pypy/branch/shrink-multidict/pypy/objspace/std/test/test_inlinedict.py
A bug found by test_descr.py: setting the dict of an object with a devolved dict
runs into an assertion.
------------------------------------------------------------------------
Modified: pypy/trunk/pypy/config/pypyoption.py
==============================================================================
--- pypy/trunk/pypy/config/pypyoption.py (original)
+++ pypy/trunk/pypy/config/pypyoption.py Tue Nov 3 11:42:42 2009
@@ -236,10 +236,10 @@
"about dictionaries",
default=False),
- BoolOption("withbucketdict",
- "use dictionaries with chained hash tables "
- "(default is open addressing)",
- default=False),
+ BoolOption("withinlineddict",
+ "make instances more compact by revoming a level of indirection",
+ default=False,
+ requires=[("objspace.std.withshadowtracking", False)]),
BoolOption("withrangelist",
"enable special range list implementation that does not "
@@ -362,6 +362,7 @@
if type_system != 'ootype':
config.objspace.std.suggest(withsharingdict=True)
config.objspace.std.suggest(withcelldict=True)
+ config.objspace.std.suggest(withinlineddict=True)
def enable_allworkingmodules(config):
Added: pypy/trunk/pypy/doc/config/objspace.std.withinlineddict.txt
==============================================================================
--- (empty file)
+++ pypy/trunk/pypy/doc/config/objspace.std.withinlineddict.txt Tue Nov 3 11:42:42 2009
@@ -0,0 +1,2 @@
+Make instances smaller by creating the __dict__ only when somebody actually
+accesses it. Also makes attribute accesses a tiny bit faster.
Modified: pypy/trunk/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/trunk/pypy/interpreter/baseobjspace.py (original)
+++ pypy/trunk/pypy/interpreter/baseobjspace.py Tue Nov 3 11:42:42 2009
@@ -20,26 +20,24 @@
in a 'normal' object space like StdObjSpace."""
__slots__ = ()
_settled_ = True
+ user_overridden_class = False
def getdict(self):
return None
- def getdictvalue_w(self, space, attr):
- return self.getdictvalue(space, space.wrap(attr))
-
- def getdictvalue(self, space, w_attr):
+ def getdictvalue(self, space, attr):
w_dict = self.getdict()
if w_dict is not None:
- return space.finditem(w_dict, w_attr)
+ return space.finditem_str(w_dict, attr)
return None
- def getdictvalue_attr_is_in_class(self, space, w_attr):
- return self.getdictvalue(space, w_attr)
+ def getdictvalue_attr_is_in_class(self, space, attr):
+ return self.getdictvalue(space, attr)
- def setdictvalue(self, space, w_attr, w_value, shadows_type=True):
+ def setdictvalue(self, space, attr, w_value, shadows_type=True):
w_dict = self.getdict()
if w_dict is not None:
- space.set_str_keyed_item(w_dict, w_attr, w_value, shadows_type)
+ space.set_str_keyed_item(w_dict, attr, w_value, shadows_type)
return True
return False
@@ -281,7 +279,7 @@
self.timer.stop("startup " + modname)
def finish(self):
- w_exitfunc = self.sys.getdictvalue_w(self, 'exitfunc')
+ w_exitfunc = self.sys.getdictvalue(self, 'exitfunc')
if w_exitfunc is not None:
self.call_function(w_exitfunc)
from pypy.interpreter.module import Module
@@ -550,12 +548,6 @@
# that can be defined in term of more primitive ones. Subclasses
# may also override specific functions for performance.
- #def is_(self, w_x, w_y): -- not really useful. Must be subclassed
- # "'x is y'."
- # w_id_x = self.id(w_x)
- # w_id_y = self.id(w_y)
- # return self.eq(w_id_x, w_id_y)
-
def not_(self, w_obj):
return self.wrap(not self.is_true(w_obj))
@@ -571,8 +563,11 @@
"""shortcut for space.int_w(space.hash(w_obj))"""
return self.int_w(self.hash(w_obj))
- def set_str_keyed_item(self, w_obj, w_key, w_value, shadows_type=True):
- return self.setitem(w_obj, w_key, w_value)
+ def set_str_keyed_item(self, w_obj, key, w_value, shadows_type=True):
+ return self.setitem(w_obj, self.wrap(key), w_value)
+
+ def finditem_str(self, w_obj, key):
+ return self.finditem(w_obj, self.wrap(key))
def finditem(self, w_obj, w_key):
try:
@@ -777,7 +772,7 @@
w_type = self.type(w_obj)
w_mro = self.getattr(w_type, self.wrap("__mro__"))
for w_supertype in self.unpackiterable(w_mro):
- w_value = w_supertype.getdictvalue_w(self, name)
+ w_value = w_supertype.getdictvalue(self, name)
if w_value is not None:
return w_value
return None
Modified: pypy/trunk/pypy/interpreter/function.py
==============================================================================
--- pypy/trunk/pypy/interpreter/function.py (original)
+++ pypy/trunk/pypy/interpreter/function.py Tue Nov 3 11:42:42 2009
@@ -494,9 +494,8 @@
return space.wrap(s)
else:
objrepr = space.str_w(space.repr(self.w_instance))
- info = 'bound method %s.%s of %s' % (typename, name, objrepr)
- # info = "method %s of %s object" % (name, typename)
- return self.w_instance.getrepr(self.space, info)
+ s = '<bound method %s.%s of %s>' % (typename, name, objrepr)
+ return space.wrap(s)
def descr_method_getattribute(self, w_attr):
space = self.space
Modified: pypy/trunk/pypy/interpreter/main.py
==============================================================================
--- pypy/trunk/pypy/interpreter/main.py (original)
+++ pypy/trunk/pypy/interpreter/main.py Tue Nov 3 11:42:42 2009
@@ -149,11 +149,11 @@
w_traceback)
# call sys.excepthook if present
- w_hook = space.sys.getdictvalue_w(space, 'excepthook')
+ w_hook = space.sys.getdictvalue(space, 'excepthook')
if w_hook is not None:
# hack: skip it if it wasn't modified by the user,
# to do instead the faster verbose/nonverbose thing below
- w_original = space.sys.getdictvalue_w(space, '__excepthook__')
+ w_original = space.sys.getdictvalue(space, '__excepthook__')
if w_original is None or not space.is_w(w_hook, w_original):
space.call_function(w_hook, w_type, w_value, w_traceback)
return False # done
Modified: pypy/trunk/pypy/interpreter/mixedmodule.py
==============================================================================
--- pypy/trunk/pypy/interpreter/mixedmodule.py (original)
+++ pypy/trunk/pypy/interpreter/mixedmodule.py Tue Nov 3 11:42:42 2009
@@ -32,7 +32,7 @@
def get(self, name):
space = self.space
- w_value = self.getdictvalue_w(space, name)
+ w_value = self.getdictvalue(space, name)
if w_value is None:
raise OperationError(space.w_AttributeError, space.wrap(name))
return w_value
@@ -41,40 +41,41 @@
w_builtin = self.get(name)
return self.space.call_function(w_builtin, *args_w)
- def getdictvalue(self, space, w_name):
- w_value = space.finditem(self.w_dict, w_name)
+ def getdictvalue(self, space, name):
+ w_value = space.finditem_str(self.w_dict, name)
if self.lazy and w_value is None:
- name = space.str_w(w_name)
- w_name = space.new_interned_w_str(w_name)
- try:
- loader = self.loaders[name]
- except KeyError:
- return None
- else:
- #print "trying to load", name
- w_value = loader(space)
- #print "loaded", w_value
- # obscure
- func = space.interpclass_w(w_value)
- # the idea of the following code is that all functions that are
- # directly in a mixed-module are "builtin", e.g. they get a
- # special type without a __get__
- # note that this is not just all functions that contain a
- # builtin code object, as e.g. methods of builtin types have to
- # be normal Functions to get the correct binding behaviour
- if (isinstance(func, Function) and
- type(func) is not BuiltinFunction):
- try:
- bltin = func._builtinversion_
- except AttributeError:
- bltin = BuiltinFunction(func)
- bltin.w_module = self.w_name
- func._builtinversion_ = bltin
- bltin.name = name
- w_value = space.wrap(bltin)
- space.setitem(self.w_dict, w_name, w_value)
+ return self._load_lazily(space, name)
return w_value
+ def _load_lazily(self, space, name):
+ w_name = space.new_interned_str(name)
+ try:
+ loader = self.loaders[name]
+ except KeyError:
+ return None
+ else:
+ w_value = loader(space)
+ func = space.interpclass_w(w_value)
+ # the idea of the following code is that all functions that are
+ # directly in a mixed-module are "builtin", e.g. they get a
+ # special type without a __get__
+ # note that this is not just all functions that contain a
+ # builtin code object, as e.g. methods of builtin types have to
+ # be normal Functions to get the correct binding behaviour
+ if (isinstance(func, Function) and
+ type(func) is not BuiltinFunction):
+ try:
+ bltin = func._builtinversion_
+ except AttributeError:
+ bltin = BuiltinFunction(func)
+ bltin.w_module = self.w_name
+ func._builtinversion_ = bltin
+ bltin.name = name
+ w_value = space.wrap(bltin)
+ space.setitem(self.w_dict, w_name, w_value)
+ return w_value
+
+
def getdict(self):
if self.lazy:
space = self.space
Modified: pypy/trunk/pypy/interpreter/pyopcode.py
==============================================================================
--- pypy/trunk/pypy/interpreter/pyopcode.py (original)
+++ pypy/trunk/pypy/interpreter/pyopcode.py Tue Nov 3 11:42:42 2009
@@ -619,9 +619,9 @@
f.pushvalue(w_newclass)
def STORE_NAME(f, varindex, *ignored):
- w_varname = f.getname_w(varindex)
+ varname = f.getname_u(varindex)
w_newvalue = f.popvalue()
- f.space.set_str_keyed_item(f.w_locals, w_varname, w_newvalue)
+ f.space.set_str_keyed_item(f.w_locals, varname, w_newvalue)
def DELETE_NAME(f, varindex, *ignored):
w_varname = f.getname_w(varindex)
@@ -656,9 +656,9 @@
f.space.delattr(w_obj, w_attributename)
def STORE_GLOBAL(f, nameindex, *ignored):
- w_varname = f.getname_w(nameindex)
+ varname = f.getname_u(nameindex)
w_newvalue = f.popvalue()
- f.space.set_str_keyed_item(f.w_globals, w_varname, w_newvalue)
+ f.space.set_str_keyed_item(f.w_globals, varname, w_newvalue)
def DELETE_GLOBAL(f, nameindex, *ignored):
w_varname = f.getname_w(nameindex)
@@ -673,25 +673,24 @@
return
f.LOAD_GLOBAL(nameindex) # fall-back
- def _load_global(f, w_varname):
- w_value = f.space.finditem(f.w_globals, w_varname)
+ def _load_global(f, varname):
+ w_value = f.space.finditem_str(f.w_globals, varname)
if w_value is None:
# not in the globals, now look in the built-ins
- w_value = f.get_builtin().getdictvalue(f.space, w_varname)
+ w_value = f.get_builtin().getdictvalue(f.space, varname)
if w_value is None:
- f._load_global_failed(w_varname)
+ f._load_global_failed(varname)
return w_value
_load_global._always_inline_ = True
- def _load_global_failed(f, w_varname):
- varname = f.space.str_w(w_varname)
+ def _load_global_failed(f, varname):
message = "global name '%s' is not defined" % varname
raise OperationError(f.space.w_NameError,
f.space.wrap(message))
_load_global_failed._dont_inline_ = True
def LOAD_GLOBAL(f, nameindex, *ignored):
- f.pushvalue(f._load_global(f.getname_w(nameindex)))
+ f.pushvalue(f._load_global(f.getname_u(nameindex)))
LOAD_GLOBAL._always_inline_ = True
def DELETE_FAST(f, varindex, *ignored):
@@ -782,7 +781,7 @@
else:
w_flag = None
- w_import = f.get_builtin().getdictvalue_w(f.space, '__import__')
+ w_import = f.get_builtin().getdictvalue(f.space, '__import__')
if w_import is None:
raise OperationError(space.w_ImportError,
space.wrap("__import__ not found"))
@@ -989,8 +988,8 @@
def CALL_LIKELY_BUILTIN(f, oparg, *ignored):
# overridden by faster version in the standard object space.
from pypy.module.__builtin__ import OPTIMIZED_BUILTINS
- w_varname = f.space.wrap(OPTIMIZED_BUILTINS[oparg >> 8])
- w_function = f._load_global(w_varname)
+ varname = OPTIMIZED_BUILTINS[oparg >> 8]
+ w_function = f._load_global(varname)
nargs = oparg&0xFF
try:
w_result = f.space.call_valuestack(w_function, nargs, f)
Modified: pypy/trunk/pypy/interpreter/test/test_function.py
==============================================================================
--- pypy/trunk/pypy/interpreter/test/test_function.py (original)
+++ pypy/trunk/pypy/interpreter/test/test_function.py Tue Nov 3 11:42:42 2009
@@ -382,11 +382,13 @@
pass
assert repr(A.f) == "<unbound method A.f>"
assert repr(A().f).startswith("<bound method A.f of <")
+ assert repr(A().f).endswith(">>")
class B:
def f(self):
pass
assert repr(B.f) == "<unbound method B.f>"
assert repr(B().f).startswith("<bound method B.f of <")
+ assert repr(A().f).endswith(">>")
def test_method_call(self):
Modified: pypy/trunk/pypy/interpreter/test/test_typedef.py
==============================================================================
--- pypy/trunk/pypy/interpreter/test/test_typedef.py (original)
+++ pypy/trunk/pypy/interpreter/test/test_typedef.py Tue Nov 3 11:42:42 2009
@@ -125,7 +125,7 @@
checks[2], checks[3]))
subclasses = {}
for key, subcls in typedef._subclass_cache.items():
- cls = key[0]
+ cls = key[1]
subclasses.setdefault(cls, {})
subclasses[cls][subcls] = True
for cls, set in subclasses.items():
Modified: pypy/trunk/pypy/interpreter/typedef.py
==============================================================================
--- pypy/trunk/pypy/interpreter/typedef.py (original)
+++ pypy/trunk/pypy/interpreter/typedef.py Tue Nov 3 11:42:42 2009
@@ -97,23 +97,24 @@
# / \
# 5 6
-def get_unique_interplevel_subclass(cls, hasdict, wants_slots, needsdel=False,
- weakrefable=False):
+def get_unique_interplevel_subclass(config, cls, hasdict, wants_slots,
+ needsdel=False, weakrefable=False):
"NOT_RPYTHON: initialization-time only"
if hasattr(cls, '__del__') and getattr(cls, "handle_del_manually", False):
needsdel = False
assert cls.typedef.acceptable_as_base_class
- key = cls, hasdict, wants_slots, needsdel, weakrefable
+ key = config, cls, hasdict, wants_slots, needsdel, weakrefable
try:
return _subclass_cache[key]
except KeyError:
- subcls = _getusercls(cls, hasdict, wants_slots, needsdel, weakrefable)
+ subcls = _getusercls(config, cls, hasdict, wants_slots, needsdel,
+ weakrefable)
_subclass_cache[key] = subcls
return subcls
get_unique_interplevel_subclass._annspecialcase_ = "specialize:memo"
_subclass_cache = {}
-def enum_interplevel_subclasses(cls):
+def enum_interplevel_subclasses(config, cls):
"""Return a list of all the extra interp-level subclasses of 'cls' that
can be built by get_unique_interplevel_subclass()."""
result = []
@@ -121,14 +122,13 @@
for flag2 in (False, True):
for flag3 in (False, True):
for flag4 in (False, True):
- result.append(get_unique_interplevel_subclass(cls, flag1,
- flag2, flag3,
- flag4))
+ result.append(get_unique_interplevel_subclass(
+ config, cls, flag1, flag2, flag3, flag4))
result = dict.fromkeys(result)
assert len(result) <= 6
return result.keys()
-def _getusercls(cls, wants_dict, wants_slots, wants_del, weakrefable):
+def _getusercls(config, cls, wants_dict, wants_slots, wants_del, weakrefable):
typedef = cls.typedef
if wants_dict and typedef.hasdict:
wants_dict = False
@@ -136,47 +136,47 @@
if wants_del:
if wants_dict:
# case 5. Parent class is 3.
- parentcls = get_unique_interplevel_subclass(cls, True, True,
+ parentcls = get_unique_interplevel_subclass(config, cls, True, True,
False, True)
else:
# case 6. Parent class is 4.
- parentcls = get_unique_interplevel_subclass(cls, False, True,
+ parentcls = get_unique_interplevel_subclass(config, cls, False, True,
False, True)
- return _usersubclswithfeature(parentcls, "del")
+ return _usersubclswithfeature(config, parentcls, "del")
elif wants_dict:
if wants_slots:
# case 3. Parent class is 1.
- parentcls = get_unique_interplevel_subclass(cls, True, False,
+ parentcls = get_unique_interplevel_subclass(config, cls, True, False,
False, True)
- return _usersubclswithfeature(parentcls, "slots")
+ return _usersubclswithfeature(config, parentcls, "slots")
else:
# case 1 (we need to add weakrefable unless it's already in 'cls')
if not typedef.weakrefable:
- return _usersubclswithfeature(cls, "user", "dict", "weakref")
+ return _usersubclswithfeature(config, cls, "user", "dict", "weakref")
else:
- return _usersubclswithfeature(cls, "user", "dict")
+ return _usersubclswithfeature(config, cls, "user", "dict")
else:
if weakrefable and not typedef.weakrefable:
# case 4. Parent class is 2.
- parentcls = get_unique_interplevel_subclass(cls, False, True,
+ parentcls = get_unique_interplevel_subclass(config, cls, False, True,
False, False)
- return _usersubclswithfeature(parentcls, "weakref")
+ return _usersubclswithfeature(config, parentcls, "weakref")
else:
# case 2 (if the base is already weakrefable, case 2 == case 4)
- return _usersubclswithfeature(cls, "user", "slots")
+ return _usersubclswithfeature(config, cls, "user", "slots")
-def _usersubclswithfeature(parentcls, *features):
- key = parentcls, features
+def _usersubclswithfeature(config, parentcls, *features):
+ key = config, parentcls, features
try:
return _usersubclswithfeature_cache[key]
except KeyError:
- subcls = _builduserclswithfeature(parentcls, *features)
+ subcls = _builduserclswithfeature(config, parentcls, *features)
_usersubclswithfeature_cache[key] = subcls
return subcls
_usersubclswithfeature_cache = {}
_allusersubcls_cache = {}
-def _builduserclswithfeature(supercls, *features):
+def _builduserclswithfeature(config, supercls, *features):
"NOT_RPYTHON: initialization-time only"
name = supercls.__name__
name += ''.join([name.capitalize() for name in features])
@@ -190,6 +190,8 @@
if "user" in features: # generic feature needed by all subcls
class Proto(object):
+ user_overridden_class = True
+
def getclass(self, space):
return hint(self.w__class__, promote=True)
@@ -242,7 +244,16 @@
return self.slots_w[index]
add(Proto)
- if "dict" in features:
+ wantdict = "dict" in features
+ if wantdict and config.objspace.std.withinlineddict:
+ from pypy.objspace.std.objectobject import W_ObjectObject
+ from pypy.objspace.std.inlinedict import make_mixin
+ if supercls is W_ObjectObject:
+ Mixin = make_mixin(config)
+ add(Mixin)
+ wantdict = False
+
+ if wantdict:
class Proto(object):
def getdict(self):
return self.w__dict__
@@ -253,32 +264,22 @@
def user_setup(self, space, w_subtype):
self.space = space
self.w__class__ = w_subtype
- if space.config.objspace.std.withsharingdict:
- from pypy.objspace.std import dictmultiobject
- self.w__dict__ = dictmultiobject.W_DictMultiObject(space,
- sharing=True)
- elif space.config.objspace.std.withshadowtracking:
- from pypy.objspace.std import dictmultiobject
- self.w__dict__ = dictmultiobject.W_DictMultiObject(space)
- self.w__dict__.implementation = \
- dictmultiobject.ShadowDetectingDictImplementation(
- space, w_subtype)
- else:
- self.w__dict__ = space.newdict()
+ self.w__dict__ = space.newdict(
+ instance=True, classofinstance=w_subtype)
self.user_setup_slots(w_subtype.nslots)
def setclass(self, space, w_subtype):
# only used by descr_set___class__
self.w__class__ = w_subtype
if space.config.objspace.std.withshadowtracking:
- self.w__dict__.implementation.set_shadows_anything()
+ self.w__dict__.set_shadows_anything()
- def getdictvalue_attr_is_in_class(self, space, w_name):
+ def getdictvalue_attr_is_in_class(self, space, name):
w_dict = self.w__dict__
if space.config.objspace.std.withshadowtracking:
- if not w_dict.implementation.shadows_anything():
+ if not w_dict.shadows_anything():
return None
- return space.finditem(w_dict, w_name)
+ return space.finditem_str(w_dict, name)
add(Proto)
Modified: pypy/trunk/pypy/jit/tl/pypyjit.py
==============================================================================
--- pypy/trunk/pypy/jit/tl/pypyjit.py (original)
+++ pypy/trunk/pypy/jit/tl/pypyjit.py Tue Nov 3 11:42:42 2009
@@ -41,6 +41,7 @@
config.objspace.usemodules._weakref = False
config.objspace.usemodules._sre = False
set_pypy_opt_level(config, level='jit')
+config.objspace.std.withinlineddict = True
if BACKEND == 'c':
config.objspace.std.multimethods = 'mrd'
Modified: pypy/trunk/pypy/module/__builtin__/interp_classobj.py
==============================================================================
--- pypy/trunk/pypy/module/__builtin__/interp_classobj.py (original)
+++ pypy/trunk/pypy/module/__builtin__/interp_classobj.py Tue Nov 3 11:42:42 2009
@@ -304,12 +304,7 @@
class W_InstanceObject(Wrappable):
def __init__(self, space, w_class, w_dict=None):
if w_dict is None:
- if space.config.objspace.std.withsharingdict:
- from pypy.objspace.std import dictmultiobject
- w_dict = dictmultiobject.W_DictMultiObject(space,
- sharing=True)
- else:
- w_dict = space.newdict()
+ w_dict = space.newdict(instance=True)
assert isinstance(w_class, W_ClassObject)
self.w_class = w_class
self.w_dict = w_dict
@@ -388,7 +383,7 @@
if w_meth is not None:
space.call_function(w_meth, w_name, w_value)
else:
- self.setdictvalue(space, w_name, w_value)
+ self.setdictvalue(space, name, w_value)
def descr_delattr(self, space, w_name):
name = unwrap_attr(space, w_name)
Modified: pypy/trunk/pypy/module/__builtin__/test/test_classobj.py
==============================================================================
--- pypy/trunk/pypy/module/__builtin__/test/test_classobj.py (original)
+++ pypy/trunk/pypy/module/__builtin__/test/test_classobj.py Tue Nov 3 11:42:42 2009
@@ -772,8 +772,7 @@
def is_sharing(space, w_inst):
from pypy.objspace.std.sharingdict import SharedDictImplementation, W_DictMultiObject
w_d = w_inst.getdict()
- return space.wrap(isinstance(w_d, W_DictMultiObject) and
- isinstance(w_d.implementation, SharedDictImplementation))
+ return space.wrap(isinstance(w_d, SharedDictImplementation))
cls.w_is_sharing = cls.space.wrap(gateway.interp2app(is_sharing))
Modified: pypy/trunk/pypy/module/operator/__init__.py
==============================================================================
--- pypy/trunk/pypy/module/operator/__init__.py (original)
+++ pypy/trunk/pypy/module/operator/__init__.py Tue Nov 3 11:42:42 2009
@@ -9,7 +9,7 @@
def __init__(self, space, w_name):
def create_lambda(name, alsoname):
- return lambda space : self.getdictvalue(space, space.wrap(alsoname))
+ return lambda space : self.getdictvalue(space, alsoname)
MixedModule.__init__(self, space, w_name)
for name, alsoname in self.mapping.iteritems():
Modified: pypy/trunk/pypy/module/sys/__init__.py
==============================================================================
--- pypy/trunk/pypy/module/sys/__init__.py (original)
+++ pypy/trunk/pypy/module/sys/__init__.py Tue Nov 3 11:42:42 2009
@@ -100,12 +100,11 @@
w_modules = self.get('modules')
self.space.setitem(w_modules, w_name, w_module)
- def getdictvalue(self, space, w_attr):
+ def getdictvalue(self, space, attr):
""" specialize access to dynamic exc_* attributes. """
- value = MixedModule.getdictvalue(self, space, w_attr)
+ value = MixedModule.getdictvalue(self, space, attr)
if value is not None:
return value
- attr = space.str_w(w_attr)
if attr == 'exc_type':
operror = space.getexecutioncontext().sys_exc_info()
if operror is None:
Modified: pypy/trunk/pypy/module/sys/test/test_sysmodule.py
==============================================================================
--- pypy/trunk/pypy/module/sys/test/test_sysmodule.py (original)
+++ pypy/trunk/pypy/module/sys/test/test_sysmodule.py Tue Nov 3 11:42:42 2009
@@ -65,6 +65,26 @@
assert exc_val2 ==e2
assert tb2.tb_lineno - tb.tb_lineno == 5
+ def test_dynamic_attributes(self):
+ try:
+ raise Exception
+ except Exception,e:
+ import sys
+ exc_type = sys.exc_type
+ exc_val = sys.exc_value
+ tb = sys.exc_traceback
+ try:
+ raise Exception # 7 lines below the previous one
+ except Exception,e2:
+ exc_type2 = sys.exc_type
+ exc_val2 = sys.exc_value
+ tb2 = sys.exc_traceback
+ assert exc_type ==Exception
+ assert exc_val ==e
+ assert exc_type2 ==Exception
+ assert exc_val2 ==e2
+ assert tb2.tb_lineno - tb.tb_lineno == 7
+
def test_exc_info_normalization(self):
import sys
try:
Modified: pypy/trunk/pypy/objspace/descroperation.py
==============================================================================
--- pypy/trunk/pypy/objspace/descroperation.py (original)
+++ pypy/trunk/pypy/objspace/descroperation.py Tue Nov 3 11:42:42 2009
@@ -36,9 +36,9 @@
if w_descr is not None:
if space.is_data_descr(w_descr):
return space.get(w_descr, w_obj)
- w_value = w_obj.getdictvalue_attr_is_in_class(space, w_name)
+ w_value = w_obj.getdictvalue_attr_is_in_class(space, name)
else:
- w_value = w_obj.getdictvalue(space, w_name)
+ w_value = w_obj.getdictvalue(space, name)
if w_value is not None:
return w_value
if w_descr is not None:
@@ -54,7 +54,7 @@
space.set(w_descr, w_obj, w_value)
return
shadows_type = True
- if w_obj.setdictvalue(space, w_name, w_value, shadows_type):
+ if w_obj.setdictvalue(space, name, w_value, shadows_type):
return
raiseattrerror(space, w_obj, name, w_descr)
Modified: pypy/trunk/pypy/objspace/std/callmethod.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/callmethod.py (original)
+++ pypy/trunk/pypy/objspace/std/callmethod.py Tue Nov 3 11:42:42 2009
@@ -54,11 +54,11 @@
if w_descr is None:
# this handles directly the common case
# module.function(args..)
- w_value = w_obj.getdictvalue(space, w_name)
+ w_value = w_obj.getdictvalue(space, name)
else:
typ = type(w_descr)
if typ is function.Function or typ is function.FunctionWithFixedCode:
- w_value = w_obj.getdictvalue_attr_is_in_class(space, w_name)
+ w_value = w_obj.getdictvalue_attr_is_in_class(space, name)
if w_value is None:
# fast method path: a function object in the class,
# nothing in the instance
@@ -87,16 +87,16 @@
"""An optimized version of space.call_method()
based on the same principle as above.
"""
- w_name = space.wrap(methname)
w_getattribute = space.lookup(w_obj, '__getattribute__')
if w_getattribute is object_getattribute(space):
w_descr = space.lookup(w_obj, methname)
typ = type(w_descr)
if typ is function.Function or typ is function.FunctionWithFixedCode:
- w_value = w_obj.getdictvalue_attr_is_in_class(space, w_name)
+ w_value = w_obj.getdictvalue_attr_is_in_class(space, methname)
if w_value is None:
# fast method path: a function object in the class,
# nothing in the instance
return space.call_function(w_descr, w_obj, *arg_w)
+ w_name = space.wrap(methname)
w_meth = space.getattr(w_obj, w_name)
return space.call_function(w_meth, *arg_w)
Modified: pypy/trunk/pypy/objspace/std/celldict.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/celldict.py (original)
+++ pypy/trunk/pypy/objspace/std/celldict.py Tue Nov 3 11:42:42 2009
@@ -1,5 +1,4 @@
from pypy.interpreter.pycode import CO_CONTAINSGLOBALS
-from pypy.objspace.std.dictmultiobject import DictImplementation
from pypy.objspace.std.dictmultiobject import IteratorImplementation
from pypy.objspace.std.dictmultiobject import W_DictMultiObject, _is_sane_hash
from pypy.rlib import jit
@@ -16,7 +15,7 @@
def __repr__(self):
return "<ModuleCell: %s>" % (self.w_value, )
-class ModuleDictImplementation(DictImplementation):
+class ModuleDictImplementation(W_DictMultiObject):
def __init__(self, space):
self.space = space
self.content = {}
@@ -45,24 +44,21 @@
w_value = cell.invalidate()
cell = impl.content[name] = ModuleCell(w_value)
- def setitem(self, w_key, w_value):
+ def impl_setitem(self, w_key, w_value):
space = self.space
if space.is_w(space.type(w_key), space.w_str):
- return self.setitem_str(w_key, w_value)
+ self.impl_setitem_str(self.space.str_w(w_key), w_value)
else:
- return self._as_rdict().setitem(w_key, w_value)
+ self._as_rdict().setitem(w_key, w_value)
- def setitem_str(self, w_key, w_value, shadows_type=True):
- name = self.space.str_w(w_key)
+ def impl_setitem_str(self, name, w_value, shadows_type=True):
self.getcell(name).w_value = w_value
if name in self.unshadowed_builtins:
self.invalidate_unshadowed_builtin(name)
del self.unshadowed_builtins[name]
- return self
-
- def delitem(self, w_key):
+ def impl_delitem(self, w_key):
space = self.space
w_key_type = space.type(w_key)
if space.is_w(w_key_type, space.w_str):
@@ -72,84 +68,71 @@
raise KeyError
cell.invalidate()
del self.content[key]
- return self
elif _is_sane_hash(space, w_key_type):
raise KeyError
else:
- return self._as_rdict().delitem(w_key)
+ self._as_rdict().delitem(w_key)
- def length(self):
+ def impl_length(self):
return len(self.content)
- def get(self, w_lookup):
+ def impl_getitem(self, w_lookup):
space = self.space
w_lookup_type = space.type(w_lookup)
if space.is_w(w_lookup_type, space.w_str):
- res = self.getcell(space.str_w(w_lookup), False)
- if res is None:
- return None
- return res.w_value
+ return self.impl_getitem_str(space.str_w(w_lookup))
+
elif _is_sane_hash(space, w_lookup_type):
return None
else:
- return self._as_rdict().get(w_lookup)
-
- def iteritems(self):
- return ModuleDictItemIteratorImplementation(self.space, self)
+ return self._as_rdict().getitem(w_lookup)
- def iterkeys(self):
- return ModuleDictKeyIteratorImplementation(self.space, self)
+ def impl_getitem_str(self, lookup):
+ res = self.getcell(lookup, False)
+ if res is None:
+ return None
+ return res.w_value
- def itervalues(self):
- return ModuleDictValueIteratorImplementation(self.space, self)
+ def impl_iter(self):
+ return ModuleDictIteratorImplementation(self.space, self)
- def keys(self):
+ def impl_keys(self):
space = self.space
return [space.wrap(key) for key in self.content.iterkeys()]
- def values(self):
+ def impl_values(self):
return [cell.w_value for cell in self.content.itervalues()]
- def items(self):
+ def impl_items(self):
space = self.space
return [space.newtuple([space.wrap(key), cell.w_value])
for (key, cell) in self.content.iteritems()]
- def _as_rdict(self):
- newimpl = self.space.DefaultDictImpl(self.space)
+ def impl_clear(self):
+ # inefficient, but who cares
for k, cell in self.content.iteritems():
- newimpl.setitem(self.space.wrap(k), cell.w_value)
cell.invalidate()
for k in self.unshadowed_builtins:
self.invalidate_unshadowed_builtin(k)
- return newimpl
-
-# grrrrr. just a copy-paste from StrKeyIteratorImplementation in dictmultiobject
-class ModuleDictKeyIteratorImplementation(IteratorImplementation):
- def __init__(self, space, dictimplementation):
- IteratorImplementation.__init__(self, space, dictimplementation)
- self.iterator = dictimplementation.content.iterkeys()
+ self.content.clear()
+ self.unshadowed_builtins.clear()
- def next_entry(self):
- # note that this 'for' loop only runs once, at most
- for key in self.iterator:
- return self.space.wrap(key)
- else:
- return None
-class ModuleDictValueIteratorImplementation(IteratorImplementation):
- def __init__(self, space, dictimplementation):
- IteratorImplementation.__init__(self, space, dictimplementation)
- self.iterator = dictimplementation.content.itervalues()
+ def _as_rdict(self):
+ r_dict_content = self.initialize_as_rdict()
+ for k, cell in self.content.iteritems():
+ r_dict_content[self.space.wrap(k)] = cell.w_value
+ cell.invalidate()
+ for k in self.unshadowed_builtins:
+ self.invalidate_unshadowed_builtin(k)
+ self._clear_fields()
+ return self
- def next_entry(self):
- # note that this 'for' loop only runs once, at most
- for cell in self.iterator:
- return cell.w_value
- else:
- return None
+ def _clear_fields(self):
+ self.content = None
+ self.unshadowed_builtins = None
-class ModuleDictItemIteratorImplementation(IteratorImplementation):
+class ModuleDictIteratorImplementation(IteratorImplementation):
def __init__(self, space, dictimplementation):
IteratorImplementation.__init__(self, space, dictimplementation)
self.iterator = dictimplementation.content.iteritems()
@@ -157,14 +140,9 @@
def next_entry(self):
# note that this 'for' loop only runs once, at most
for key, cell in self.iterator:
- return self.space.newtuple([self.space.wrap(key), cell.w_value])
+ return (self.space.wrap(key), cell.w_value)
else:
- return None
-
-
-
-
-
+ return None, None
class State(object):
@@ -217,8 +195,8 @@
return None
def getimplementation(w_dict):
- if type(w_dict) is W_DictMultiObject:
- return w_dict.implementation
+ if type(w_dict) is ModuleDictImplementation and w_dict.r_dict_content is None:
+ return w_dict
else:
return None
@@ -251,5 +229,5 @@
if cell is not None:
f.cache_for_globals[nameindex] = cell
return cell.w_value
- return f._load_global(f.getname_w(nameindex))
+ return f._load_global(f.getname_u(nameindex))
load_global_fill_cache._dont_inline_ = True
Modified: pypy/trunk/pypy/objspace/std/dictmultiobject.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/dictmultiobject.py (original)
+++ pypy/trunk/pypy/objspace/std/dictmultiobject.py Tue Nov 3 11:42:42 2009
@@ -22,93 +22,246 @@
space.is_w(w_lookup_type, space.w_float)
)
+class W_DictMultiObject(W_Object):
+ from pypy.objspace.std.dicttype import dict_typedef as typedef
-# DictImplementation lattice
+ r_dict_content = None
-# a dictionary starts with an EmptyDictImplementation, and moves down
-# in this list:
-#
-# EmptyDictImplementation
-# / \
-# | |
-# StrDictImplementation |
-# \ /
-# RDictImplementation
-#
-# (in addition, any dictionary can go back to EmptyDictImplementation)
+ @staticmethod
+ def allocate_and_init_instance(space, w_type=None, module=False,
+ instance=False, classofinstance=None,
+ from_strdict_shared=None):
+ if from_strdict_shared is not None:
+ assert w_type is None
+ assert not module and not instance and classofinstance is None
+ w_self = StrDictImplementation(space)
+ w_self.content = from_strdict_shared
+ return w_self
+ if space.config.objspace.std.withcelldict and module:
+ from pypy.objspace.std.celldict import ModuleDictImplementation
+ assert w_type is None
+ return ModuleDictImplementation(space)
+ elif space.config.objspace.opcodes.CALL_LIKELY_BUILTIN and module:
+ assert w_type is None
+ return WaryDictImplementation(space)
+ elif space.config.objspace.std.withdictmeasurement:
+ assert w_type is None
+ return MeasuringDictImplementation(space)
+ elif space.config.objspace.std.withsharingdict and instance:
+ from pypy.objspace.std.sharingdict import SharedDictImplementation
+ assert w_type is None
+ return SharedDictImplementation(space)
+ elif (space.config.objspace.std.withshadowtracking and instance and
+ classofinstance is not None):
+ assert w_type is None
+ return ShadowDetectingDictImplementation(space, classofinstance)
+ elif instance:
+ assert w_type is None
+ return StrDictImplementation(space)
+ else:
+ if w_type is None:
+ w_type = space.w_dict
+ w_self = space.allocate_instance(W_DictMultiObject, w_type)
+ W_DictMultiObject.__init__(w_self, space)
+ w_self.initialize_as_rdict()
+ return w_self
-class DictImplementation(object):
-
- def get(self, w_lookup):
+ def __init__(self, space):
+ self.space = space
+
+ def initialize_as_rdict(self):
+ assert self.r_dict_content is None
+ self.r_dict_content = r_dict(self.space.eq_w, self.space.hash_w)
+ return self.r_dict_content
+
+
+ def initialize_content(w_self, list_pairs_w):
+ for w_k, w_v in list_pairs_w:
+ w_self.setitem(w_k, w_v)
+
+ def __repr__(w_self):
+ """ representation for debugging purposes """
+ return "%s()" % (w_self.__class__.__name__, )
+
+ def unwrap(w_dict, space):
+ result = {}
+ items = w_dict.items()
+ for w_pair in items:
+ key, val = space.unwrap(w_pair)
+ result[key] = val
+ return result
+
+ def missing_method(w_dict, space, w_key):
+ if not space.is_w(space.type(w_dict), space.w_dict):
+ w_missing = space.lookup(w_dict, "__missing__")
+ if w_missing is None:
+ return None
+ return space.call_function(w_missing, w_dict, w_key)
+ else:
+ return None
+
+ def set_str_keyed_item(w_dict, key, w_value, shadows_type=True):
+ w_dict.setitem_str(key, w_value, shadows_type)
+
+ # _________________________________________________________________
+ # implementation methods
+ def impl_getitem(self, w_key):
#return w_value or None
raise NotImplementedError("abstract base class")
- def setitem_str(self, w_key, w_value, shadows_type=True):
- #return implementation
+ def impl_getitem_str(self, w_key):
+ #return w_value or None
raise NotImplementedError("abstract base class")
- def setitem(self, w_key, w_value):
- #return implementation
+ def impl_setitem_str(self, key, w_value, shadows_type=True):
raise NotImplementedError("abstract base class")
- def delitem(self, w_key):
- #return implementation
- raise NotImplementedError("abstract base class")
-
- def length(self):
+ def impl_setitem(self, w_key, w_value):
raise NotImplementedError("abstract base class")
- def iteritems(self):
+ def impl_delitem(self, w_key):
raise NotImplementedError("abstract base class")
- def iterkeys(self):
+
+ def impl_length(self):
raise NotImplementedError("abstract base class")
- def itervalues(self):
+
+ def impl_iter(self):
raise NotImplementedError("abstract base class")
+ def impl_clear(self):
+ raise NotImplementedError("abstract base class")
- def keys(self):
- iterator = self.iterkeys()
+ def impl_keys(self):
+ iterator = self.impl_iter()
result = []
while 1:
- w_key = iterator.next()
+ w_key, w_value = iterator.next()
if w_key is not None:
result.append(w_key)
else:
return result
- def values(self):
- iterator = self.itervalues()
+ def impl_values(self):
+ iterator = self.impl_iter()
result = []
while 1:
- w_value = iterator.next()
+ w_key, w_value = iterator.next()
if w_value is not None:
result.append(w_value)
else:
return result
- def items(self):
- iterator = self.iteritems()
+ def impl_items(self):
+ iterator = self.impl_iter()
result = []
while 1:
- w_item = iterator.next()
- if w_item is not None:
- result.append(w_item)
+ w_key, w_value = iterator.next()
+ if w_key is not None:
+ result.append(self.space.newtuple([w_key, w_value]))
else:
return result
-# the following method only makes sense when the option to use the
-# CALL_LIKELY_BUILTIN opcode is set. Otherwise it won't even be seen
-# by the annotator
- def get_builtin_indexed(self, i):
- w_key = self.space.wrap(OPTIMIZED_BUILTINS[i])
- return self.get(w_key)
+ # the following method only makes sense when the option to use the
+ # CALL_LIKELY_BUILTIN opcode is set. Otherwise it won't even be seen
+ # by the annotator
+ def impl_get_builtin_indexed(self, i):
+ key = OPTIMIZED_BUILTINS[i]
+ return self.impl_getitem_str(key)
+
+ # this method will only be seen whan a certain config option is used
+ def impl_shadows_anything(self):
+ return True
+
+ def impl_set_shadows_anything(self):
+ pass
+
+ # _________________________________________________________________
+ # fallback implementation methods
+
+ def impl_fallback_setitem(self, w_key, w_value):
+ self.r_dict_content[w_key] = w_value
+
+ def impl_fallback_setitem_str(self, key, w_value, shadows_type=True):
+ return self.impl_fallback_setitem(self.space.wrap(key), w_value)
-# this method will only be seen whan a certain config option is used
- def shadows_anything(self):
+ def impl_fallback_delitem(self, w_key):
+ del self.r_dict_content[w_key]
+
+ def impl_fallback_length(self):
+ return len(self.r_dict_content)
+
+ def impl_fallback_getitem(self, w_key):
+ return self.r_dict_content.get(w_key, None)
+
+ def impl_fallback_getitem_str(self, key):
+ return self.r_dict_content.get(self.space.wrap(key), None)
+
+ def impl_fallback_iter(self):
+ return RDictIteratorImplementation(self.space, self)
+
+ def impl_fallback_keys(self):
+ return self.r_dict_content.keys()
+ def impl_fallback_values(self):
+ return self.r_dict_content.values()
+ def impl_fallback_items(self):
+ return [self.space.newtuple([w_key, w_val])
+ for w_key, w_val in self.r_dict_content.iteritems()]
+
+ def impl_fallback_clear(self):
+ self.r_dict_content.clear()
+
+ def impl_fallback_get_builtin_indexed(self, i):
+ key = OPTIMIZED_BUILTINS[i]
+ return self.impl_fallback_getitem_str(key)
+
+ def impl_fallback_shadows_anything(self):
return True
- def set_shadows_anything(self):
+ def impl_fallback_set_shadows_anything(self):
pass
+implementation_methods = [
+ ("getitem", 1),
+ ("getitem_str", 1),
+ ("length", 0),
+ ("setitem_str", 3),
+ ("setitem", 2),
+ ("delitem", 1),
+ ("iter", 0),
+ ("items", 0),
+ ("values", 0),
+ ("keys", 0),
+ ("clear", 0),
+ ("get_builtin_indexed", 1),
+ ("shadows_anything", 0),
+ ("set_shadows_anything", 0),
+]
+
+
+def _make_method(name, implname, fallback, numargs):
+ args = ", ".join(["a" + str(i) for i in range(numargs)])
+ code = """def %s(self, %s):
+ if self.r_dict_content is not None:
+ return self.%s(%s)
+ return self.%s(%s)""" % (name, args, fallback, args, implname, args)
+ d = {}
+ exec py.code.Source(code).compile() in d
+ implementation_method = d[name]
+ implementation_method.func_defaults = getattr(W_DictMultiObject, implname).func_defaults
+ return implementation_method
+
+def _install_methods():
+ for name, numargs in implementation_methods:
+ implname = "impl_" + name
+ fallbackname = "impl_fallback_" + name
+ func = _make_method(name, implname, fallbackname, numargs)
+ setattr(W_DictMultiObject, name, func)
+_install_methods()
+
+registerimplementation(W_DictMultiObject)
+
+# DictImplementation lattice
+# XXX fix me
+
# Iterator Implementation base classes
class IteratorImplementation(object):
@@ -120,19 +273,19 @@
def next(self):
if self.dictimplementation is None:
- return None
+ return None, None
if self.len != self.dictimplementation.length():
self.len = -1 # Make this error state sticky
raise OperationError(self.space.w_RuntimeError,
self.space.wrap("dictionary changed size during iteration"))
# look for the next entry
- w_result = self.next_entry()
- if w_result is not None:
+ if self.pos < self.len:
+ result = self.next_entry()
self.pos += 1
- return w_result
+ return result
# no more entries
self.dictimplementation = None
- return None
+ return None, None
def next_entry(self):
""" Purely abstract method
@@ -148,170 +301,92 @@
# concrete subclasses of the above
-class EmptyDictImplementation(DictImplementation):
- def __init__(self, space):
- self.space = space
-
- def get(self, w_lookup):
- space = self.space
- if not _is_str(space, w_lookup) and not _is_sane_hash(space,
- space.type(w_lookup)):
- # give hash a chance to raise an exception
- space.hash(w_lookup)
- return None
-
- def setitem(self, w_key, w_value):
- space = self.space
- if _is_str(space, w_key):
- return StrDictImplementation(space).setitem_str(w_key, w_value)
- else:
- return space.DefaultDictImpl(space).setitem(w_key, w_value)
- def setitem_str(self, w_key, w_value, shadows_type=True):
- return StrDictImplementation(self.space).setitem_str(w_key, w_value)
- #return SmallStrDictImplementation(self.space, w_key, w_value)
-
- def delitem(self, w_key):
- space = self.space
- if not _is_str(space, w_key) and not _is_sane_hash(space,
- space.type(w_key)):
- # count hash
- space.hash(w_key)
- raise KeyError
-
- def length(self):
- return 0
-
- def iteritems(self):
- return EmptyIteratorImplementation(self.space, self)
- def iterkeys(self):
- return EmptyIteratorImplementation(self.space, self)
- def itervalues(self):
- return EmptyIteratorImplementation(self.space, self)
-
- def keys(self):
- return []
- def values(self):
- return []
- def items(self):
- return []
-
-class EmptyIteratorImplementation(IteratorImplementation):
- def next_entry(self):
- return None
-
-
-class StrDictImplementation(DictImplementation):
+class StrDictImplementation(W_DictMultiObject):
def __init__(self, space):
self.space = space
self.content = {}
- def setitem(self, w_key, w_value):
+ def impl_setitem(self, w_key, w_value):
space = self.space
if space.is_w(space.type(w_key), space.w_str):
- return self.setitem_str(w_key, w_value)
+ self.impl_setitem_str(self.space.str_w(w_key), w_value)
else:
- return self._as_rdict().setitem(w_key, w_value)
+ self._as_rdict().setitem(w_key, w_value)
- def setitem_str(self, w_key, w_value, shadows_type=True):
- self.content[self.space.str_w(w_key)] = w_value
- return self
+ def impl_setitem_str(self, key, w_value, shadows_type=True):
+ self.content[key] = w_value
- def delitem(self, w_key):
+ def impl_delitem(self, w_key):
space = self.space
w_key_type = space.type(w_key)
if space.is_w(w_key_type, space.w_str):
del self.content[space.str_w(w_key)]
- if self.content:
- return self
- else:
- return space.emptydictimpl
+ return
elif _is_sane_hash(space, w_key_type):
raise KeyError
else:
- return self._as_rdict().delitem(w_key)
+ self._as_rdict().delitem(w_key)
- def length(self):
+ def impl_length(self):
return len(self.content)
- def get(self, w_lookup):
+ def impl_getitem_str(self, key):
+ return self.content.get(key, None)
+
+ def impl_getitem(self, w_key):
space = self.space
# -- This is called extremely often. Hack for performance --
- if type(w_lookup) is space.StringObjectCls:
- return self.content.get(w_lookup.unwrap(space), None)
+ if type(w_key) is space.StringObjectCls:
+ return self.impl_getitem_str(w_key.unwrap(space))
# -- End of performance hack --
- w_lookup_type = space.type(w_lookup)
+ w_lookup_type = space.type(w_key)
if space.is_w(w_lookup_type, space.w_str):
- return self.content.get(space.str_w(w_lookup), None)
+ return self.impl_getitem_str(space.str_w(w_key))
elif _is_sane_hash(space, w_lookup_type):
return None
else:
- return self._as_rdict().get(w_lookup)
+ return self._as_rdict().getitem(w_key)
- def iteritems(self):
- return StrItemIteratorImplementation(self.space, self)
+ def impl_iter(self):
+ return StrIteratorImplementation(self.space, self)
- def iterkeys(self):
- return StrKeyIteratorImplementation(self.space, self)
-
- def itervalues(self):
- return StrValueIteratorImplementation(self.space, self)
-
- def keys(self):
+ def impl_keys(self):
space = self.space
return [space.wrap(key) for key in self.content.iterkeys()]
- def values(self):
+ def impl_values(self):
return self.content.values()
- def items(self):
+ def impl_items(self):
space = self.space
return [space.newtuple([space.wrap(key), w_value])
for (key, w_value) in self.content.iteritems()]
+ def impl_clear(self):
+ self.content.clear()
+
def _as_rdict(self):
- newimpl = self.space.DefaultDictImpl(self.space)
+ r_dict_content = self.initialize_as_rdict()
for k, w_v in self.content.items():
- newimpl.setitem(self.space.wrap(k), w_v)
- return newimpl
-
-# the following are very close copies of the base classes above
-
-class StrKeyIteratorImplementation(IteratorImplementation):
- def __init__(self, space, dictimplementation):
- IteratorImplementation.__init__(self, space, dictimplementation)
- self.iterator = dictimplementation.content.iterkeys()
-
- def next_entry(self):
- # note that this 'for' loop only runs once, at most
- for key in self.iterator:
- return self.space.wrap(key)
- else:
- return None
-
-class StrValueIteratorImplementation(IteratorImplementation):
- def __init__(self, space, dictimplementation):
- IteratorImplementation.__init__(self, space, dictimplementation)
- self.iterator = dictimplementation.content.itervalues()
+ r_dict_content[self.space.wrap(k)] = w_v
+ self._clear_fields()
+ return self
- def next_entry(self):
- # note that this 'for' loop only runs once, at most
- for w_value in self.iterator:
- return w_value
- else:
- return None
+ def _clear_fields(self):
+ self.content = None
-class StrItemIteratorImplementation(IteratorImplementation):
+class StrIteratorImplementation(IteratorImplementation):
def __init__(self, space, dictimplementation):
IteratorImplementation.__init__(self, space, dictimplementation)
self.iterator = dictimplementation.content.iteritems()
def next_entry(self):
# note that this 'for' loop only runs once, at most
- for key, w_value in self.iterator:
- return self.space.newtuple([self.space.wrap(key), w_value])
+ for str, w_value in self.iterator:
+ return self.space.wrap(str), w_value
else:
- return None
+ return None, None
class ShadowDetectingDictImplementation(StrDictImplementation):
@@ -324,29 +399,29 @@
else:
self._shadows_anything = False
- def setitem_str(self, w_key, w_value, shadows_type=True):
+ def impl_setitem_str(self, key, w_value, shadows_type=True):
if shadows_type:
self._shadows_anything = True
- return StrDictImplementation.setitem_str(
- self, w_key, w_value, shadows_type)
+ StrDictImplementation.impl_setitem_str(
+ self, key, w_value, shadows_type)
- def setitem(self, w_key, w_value):
+ def impl_setitem(self, w_key, w_value):
space = self.space
if space.is_w(space.type(w_key), space.w_str):
if not self._shadows_anything:
w_obj = self.w_type.lookup(space.str_w(w_key))
if w_obj is not None:
self._shadows_anything = True
- return StrDictImplementation.setitem_str(
- self, w_key, w_value, False)
+ StrDictImplementation.impl_setitem_str(
+ self, self.space.str_w(w_key), w_value, False)
else:
- return self._as_rdict().setitem(w_key, w_value)
+ self._as_rdict().setitem(w_key, w_value)
- def shadows_anything(self):
+ def impl_shadows_anything(self):
return (self._shadows_anything or
self.w_type.version_tag is not self.original_version_tag)
- def set_shadows_anything(self):
+ def impl_set_shadows_anything(self):
self._shadows_anything = True
class WaryDictImplementation(StrDictImplementation):
@@ -354,15 +429,13 @@
StrDictImplementation.__init__(self, space)
self.shadowed = [None] * len(BUILTIN_TO_INDEX)
- def setitem_str(self, w_key, w_value, shadows_type=True):
- key = self.space.str_w(w_key)
+ def impl_setitem_str(self, key, w_value, shadows_type=True):
i = BUILTIN_TO_INDEX.get(key, -1)
if i != -1:
self.shadowed[i] = w_value
self.content[key] = w_value
- return self
- def delitem(self, w_key):
+ def impl_delitem(self, w_key):
space = self.space
w_key_type = space.type(w_key)
if space.is_w(w_key_type, space.w_str):
@@ -371,96 +444,30 @@
i = BUILTIN_TO_INDEX.get(key, -1)
if i != -1:
self.shadowed[i] = None
- return self
elif _is_sane_hash(space, w_key_type):
raise KeyError
else:
- return self._as_rdict().delitem(w_key)
+ self._as_rdict().delitem(w_key)
- def get_builtin_indexed(self, i):
+ def impl_get_builtin_indexed(self, i):
return self.shadowed[i]
-class RDictImplementation(DictImplementation):
- def __init__(self, space):
- self.space = space
- self.content = r_dict(space.eq_w, space.hash_w)
-
- def __repr__(self):
- return "%s<%s>" % (self.__class__.__name__, self.content)
-
- def setitem(self, w_key, w_value):
- self.content[w_key] = w_value
- return self
-
- def setitem_str(self, w_key, w_value, shadows_type=True):
- return self.setitem(w_key, w_value)
-
- def delitem(self, w_key):
- del self.content[w_key]
- if self.content:
- return self
- else:
- return self.space.emptydictimpl
-
- def length(self):
- return len(self.content)
- def get(self, w_lookup):
- return self.content.get(w_lookup, None)
-
- def iteritems(self):
- return RDictItemIteratorImplementation(self.space, self)
- def iterkeys(self):
- return RDictKeyIteratorImplementation(self.space, self)
- def itervalues(self):
- return RDictValueIteratorImplementation(self.space, self)
-
- def keys(self):
- return self.content.keys()
- def values(self):
- return self.content.values()
- def items(self):
- return [self.space.newtuple([w_key, w_val])
- for w_key, w_val in self.content.iteritems()]
-
-
-class RDictKeyIteratorImplementation(IteratorImplementation):
- def __init__(self, space, dictimplementation):
- IteratorImplementation.__init__(self, space, dictimplementation)
- self.iterator = dictimplementation.content.iterkeys()
-
- def next_entry(self):
- # note that this 'for' loop only runs once, at most
- for w_key in self.iterator:
- return w_key
- else:
- return None
-
-class RDictValueIteratorImplementation(IteratorImplementation):
- def __init__(self, space, dictimplementation):
- IteratorImplementation.__init__(self, space, dictimplementation)
- self.iterator = dictimplementation.content.itervalues()
- def next_entry(self):
- # note that this 'for' loop only runs once, at most
- for w_value in self.iterator:
- return w_value
- else:
- return None
-
-class RDictItemIteratorImplementation(IteratorImplementation):
+class RDictIteratorImplementation(IteratorImplementation):
def __init__(self, space, dictimplementation):
IteratorImplementation.__init__(self, space, dictimplementation)
- self.iterator = dictimplementation.content.iteritems()
+ self.iterator = dictimplementation.r_dict_content.iteritems()
def next_entry(self):
# note that this 'for' loop only runs once, at most
- for w_key, w_value in self.iterator:
- return self.space.newtuple([w_key, w_value])
+ for item in self.iterator:
+ return item
else:
- return None
+ return None, None
+# XXX fix this thing
import time, py
class DictInfo(object):
@@ -518,7 +525,7 @@
def __del__(self):
self.info.lifetime = time.time() - self.info.createtime
-class MeasuringDictImplementation(DictImplementation):
+class MeasuringDictImplementation(W_DictMultiObject):
def __init__(self, space):
self.space = space
self.content = r_dict(space.eq_w, space.hash_w)
@@ -544,7 +551,7 @@
else:
self.info.misses += 1
- def setitem(self, w_key, w_value):
+ def impl_setitem(self, w_key, w_value):
if not self.info.seen_non_string_in_write and not self._is_str(w_key):
self.info.seen_non_string_in_write = True
self.info.size_on_non_string_seen_in_write = len(self.content)
@@ -552,11 +559,10 @@
self.info.writes += 1
self.content[w_key] = w_value
self.info.maxcontents = max(self.info.maxcontents, len(self.content))
- return self
- def setitem_str(self, w_key, w_value, shadows_type=True):
+ def impl_setitem_str(self, key, w_value, shadows_type=True):
self.info.setitem_strs += 1
- return self.setitem(w_key, w_value)
- def delitem(self, w_key):
+ self.impl_setitem(self.space.wrap(key), w_value)
+ def impl_delitem(self, w_key):
if not self.info.seen_non_string_in_write \
and not self.info.seen_non_string_in_read_first \
and not self._is_str(w_key):
@@ -565,38 +571,39 @@
self.info.delitems += 1
self.info.writes += 1
del self.content[w_key]
- return self
- def length(self):
+ def impl_length(self):
self.info.lengths += 1
return len(self.content)
- def get(self, w_lookup):
+ def impl_getitem_str(self, key):
+ return self.impl_getitem(self.space.wrap(key))
+ def impl_getitem(self, w_key):
self.info.gets += 1
- self._read(w_lookup)
- return self.content.get(w_lookup, None)
+ self._read(w_key)
+ return self.content.get(w_key, None)
- def iteritems(self):
+ def impl_iteritems(self):
self.info.iteritems += 1
self.info.iterations += 1
return RDictItemIteratorImplementation(self.space, self)
- def iterkeys(self):
+ def impl_iterkeys(self):
self.info.iterkeys += 1
self.info.iterations += 1
return RDictKeyIteratorImplementation(self.space, self)
- def itervalues(self):
+ def impl_itervalues(self):
self.info.itervalues += 1
self.info.iterations += 1
return RDictValueIteratorImplementation(self.space, self)
- def keys(self):
+ def impl_keys(self):
self.info.keys += 1
self.info.listings += 1
return self.content.keys()
- def values(self):
+ def impl_values(self):
self.info.values += 1
self.info.listings += 1
return self.content.values()
- def items(self):
+ def impl_items(self):
self.info.items += 1
self.info.listings += 1
return [self.space.newtuple([w_key, w_val])
@@ -630,71 +637,6 @@
os.close(fd)
os.write(2, "Reporting done.\n")
-class W_DictMultiObject(W_Object):
- from pypy.objspace.std.dicttype import dict_typedef as typedef
-
- def __init__(w_self, space, module=False, sharing=False):
- if space.config.objspace.std.withcelldict and module:
- from pypy.objspace.std.celldict import ModuleDictImplementation
- w_self.implementation = ModuleDictImplementation(space)
- elif space.config.objspace.opcodes.CALL_LIKELY_BUILTIN and module:
- w_self.implementation = WaryDictImplementation(space)
- elif space.config.objspace.std.withdictmeasurement:
- w_self.implementation = MeasuringDictImplementation(space)
- elif space.config.objspace.std.withsharingdict and sharing:
- from pypy.objspace.std.sharingdict import SharedDictImplementation
- w_self.implementation = SharedDictImplementation(space)
- else:
- w_self.implementation = space.emptydictimpl
- w_self.space = space
-
- def initialize_content(w_self, list_pairs_w):
- impl = w_self.implementation
- for w_k, w_v in list_pairs_w:
- impl = impl.setitem(w_k, w_v)
- w_self.implementation = impl
-
- def initialize_from_strdict_shared(w_self, strdict):
- impl = StrDictImplementation(w_self.space)
- impl.content = strdict
- w_self.implementation = impl
-
- def __repr__(w_self):
- """ representation for debugging purposes """
- return "%s(%s)" % (w_self.__class__.__name__, w_self.implementation)
-
- def unwrap(w_dict, space):
- result = {}
- items = w_dict.implementation.items()
- for w_pair in items:
- key, val = space.unwrap(w_pair)
- result[key] = val
- return result
-
- def missing_method(w_dict, space, w_key):
- if not space.is_w(space.type(w_dict), space.w_dict):
- w_missing = space.lookup(w_dict, "__missing__")
- if w_missing is None:
- return None
- return space.call_function(w_missing, w_dict, w_key)
- else:
- return None
-
- def len(w_self):
- return w_self.implementation.length()
-
- def get(w_dict, w_key, w_default):
- w_value = w_dict.implementation.get(w_key)
- if w_value is not None:
- return w_value
- else:
- return w_default
-
- def set_str_keyed_item(w_dict, w_key, w_value, shadows_type=True):
- w_dict.implementation = w_dict.implementation.setitem_str(
- w_key, w_value, shadows_type)
-
-registerimplementation(W_DictMultiObject)
init_signature = Signature(['seq_or_map'], None, 'kwargs')
@@ -715,7 +657,7 @@
raise OperationError(space.w_ValueError,
space.wrap("dict() takes a sequence of pairs"))
w_k, w_v = pair
- w_dict.implementation = w_dict.implementation.setitem(w_k, w_v)
+ w_dict.setitem(w_k, w_v)
else:
if space.is_true(w_src):
from pypy.objspace.std.dicttype import update1
@@ -724,71 +666,67 @@
from pypy.objspace.std.dicttype import update1
update1(space, w_dict, w_kwds)
-def getitem__DictMulti_ANY(space, w_dict, w_lookup):
- w_value = w_dict.implementation.get(w_lookup)
+def getitem__DictMulti_ANY(space, w_dict, w_key):
+ w_value = w_dict.getitem(w_key)
if w_value is not None:
return w_value
- w_missing_item = w_dict.missing_method(space, w_lookup)
+ w_missing_item = w_dict.missing_method(space, w_key)
if w_missing_item is not None:
return w_missing_item
- space.raise_key_error(w_lookup)
+ space.raise_key_error(w_key)
def setitem__DictMulti_ANY_ANY(space, w_dict, w_newkey, w_newvalue):
- w_dict.implementation = w_dict.implementation.setitem(w_newkey, w_newvalue)
+ w_dict.setitem(w_newkey, w_newvalue)
-def delitem__DictMulti_ANY(space, w_dict, w_lookup):
+def delitem__DictMulti_ANY(space, w_dict, w_key):
try:
- w_dict.implementation = w_dict.implementation.delitem(w_lookup)
+ w_dict.delitem(w_key)
except KeyError:
- space.raise_key_error(w_lookup)
+ space.raise_key_error(w_key)
def len__DictMulti(space, w_dict):
- return space.wrap(w_dict.implementation.length())
+ return space.wrap(w_dict.length())
-def contains__DictMulti_ANY(space, w_dict, w_lookup):
- return space.newbool(w_dict.implementation.get(w_lookup) is not None)
+def contains__DictMulti_ANY(space, w_dict, w_key):
+ return space.newbool(w_dict.getitem(w_key) is not None)
dict_has_key__DictMulti_ANY = contains__DictMulti_ANY
def iter__DictMulti(space, w_dict):
- return W_DictMultiIterObject(space, w_dict.implementation.iterkeys())
+ return W_DictMultiIterObject(space, w_dict.iter(), KEYSITER)
def eq__DictMulti_DictMulti(space, w_left, w_right):
if space.is_w(w_left, w_right):
return space.w_True
- if w_left.implementation.length() != w_right.implementation.length():
+ if w_left.length() != w_right.length():
return space.w_False
- iteratorimplementation = w_left.implementation.iteritems()
+ iteratorimplementation = w_left.iter()
while 1:
- w_item = iteratorimplementation.next()
- if w_item is None:
+ w_key, w_val = iteratorimplementation.next()
+ if w_key is None:
break
- w_key = space.getitem(w_item, space.wrap(0))
- w_val = space.getitem(w_item, space.wrap(1))
- w_rightval = w_right.implementation.get(w_key)
+ w_rightval = w_right.getitem(w_key)
if w_rightval is None:
return space.w_False
if not space.eq_w(w_val, w_rightval):
return space.w_False
return space.w_True
-def characterize(space, aimpl, bimpl):
+def characterize(space, w_a, w_b):
""" (similar to CPython)
returns the smallest key in acontent for which b's value is different or absent and this value """
w_smallest_diff_a_key = None
w_its_value = None
- iteratorimplementation = aimpl.iteritems()
+ iteratorimplementation = w_a.iter()
while 1:
- w_item = iteratorimplementation.next()
- if w_item is None:
+ w_key, w_val = iteratorimplementation.next()
+ if w_key is None:
break
- w_key = space.getitem(w_item, space.wrap(0))
- w_val = space.getitem(w_item, space.wrap(1))
if w_smallest_diff_a_key is None or space.is_true(space.lt(w_key, w_smallest_diff_a_key)):
- w_bvalue = bimpl.get(w_key)
+ w_bvalue = w_b.getitem(w_key)
if w_bvalue is None:
w_its_value = w_val
w_smallest_diff_a_key = w_key
@@ -800,18 +738,16 @@
def lt__DictMulti_DictMulti(space, w_left, w_right):
# Different sizes, no problem
- leftimpl = w_left.implementation
- rightimpl = w_right.implementation
- if leftimpl.length() < rightimpl.length():
+ if w_left.length() < w_right.length():
return space.w_True
- if leftimpl.length() > rightimpl.length():
+ if w_left.length() > w_right.length():
return space.w_False
# Same size
- w_leftdiff, w_leftval = characterize(space, leftimpl, rightimpl)
+ w_leftdiff, w_leftval = characterize(space, w_left, w_right)
if w_leftdiff is None:
return space.w_False
- w_rightdiff, w_rightval = characterize(space, rightimpl, leftimpl)
+ w_rightdiff, w_rightval = characterize(space, w_right, w_left)
if w_rightdiff is None:
# w_leftdiff is not None, w_rightdiff is None
return space.w_True
@@ -824,47 +760,51 @@
def dict_copy__DictMulti(space, w_self):
from pypy.objspace.std.dicttype import update1
- w_new = W_DictMultiObject(space)
+ w_new = W_DictMultiObject.allocate_and_init_instance(space)
update1(space, w_new, w_self)
return w_new
def dict_items__DictMulti(space, w_self):
- return space.newlist(w_self.implementation.items())
+ return space.newlist(w_self.items())
def dict_keys__DictMulti(space, w_self):
- return space.newlist(w_self.implementation.keys())
+ return space.newlist(w_self.keys())
def dict_values__DictMulti(space, w_self):
- return space.newlist(w_self.implementation.values())
+ return space.newlist(w_self.values())
def dict_iteritems__DictMulti(space, w_self):
- return W_DictMultiIterObject(space, w_self.implementation.iteritems())
+ return W_DictMultiIterObject(space, w_self.iter(), ITEMSITER)
def dict_iterkeys__DictMulti(space, w_self):
- return W_DictMultiIterObject(space, w_self.implementation.iterkeys())
+ return W_DictMultiIterObject(space, w_self.iter(), KEYSITER)
def dict_itervalues__DictMulti(space, w_self):
- return W_DictMultiIterObject(space, w_self.implementation.itervalues())
+ return W_DictMultiIterObject(space, w_self.iter(), VALUESITER)
def dict_clear__DictMulti(space, w_self):
- w_self.implementation = space.emptydictimpl
+ w_self.clear()
-def dict_get__DictMulti_ANY_ANY(space, w_dict, w_lookup, w_default):
- return w_dict.get(w_lookup, w_default)
+def dict_get__DictMulti_ANY_ANY(space, w_dict, w_key, w_default):
+ w_value = w_dict.getitem(w_key)
+ if w_value is not None:
+ return w_value
+ else:
+ return w_default
def dict_pop__DictMulti_ANY(space, w_dict, w_key, w_defaults):
defaults = space.unpackiterable(w_defaults)
len_defaults = len(defaults)
if len_defaults > 1:
raise OperationError(space.w_TypeError, space.wrap("pop expected at most 2 arguments, got %d" % (1 + len_defaults, )))
- w_item = w_dict.implementation.get(w_key)
+ w_item = w_dict.getitem(w_key)
if w_item is None:
if len_defaults > 0:
return defaults[0]
else:
space.raise_key_error(w_key)
else:
- w_dict.implementation.delitem(w_key)
+ w_dict.delitem(w_key)
return w_item
app = gateway.applevel('''
@@ -895,7 +835,7 @@
dictrepr = app.interphook("dictrepr")
def repr__DictMulti(space, w_dict):
- if w_dict.implementation.length() == 0:
+ if w_dict.length() == 0:
return space.wrap('{}')
ec = space.getexecutioncontext()
w_currently_in_repr = ec._py_repr
@@ -908,12 +848,17 @@
# Iteration
+KEYSITER = 0
+ITEMSITER = 1
+VALUESITER = 2
+
class W_DictMultiIterObject(W_Object):
from pypy.objspace.std.dicttype import dictiter_typedef as typedef
- def __init__(w_self, space, iteratorimplementation):
+ def __init__(w_self, space, iteratorimplementation, itertype):
w_self.space = space
w_self.iteratorimplementation = iteratorimplementation
+ w_self.itertype = itertype
registerimplementation(W_DictMultiIterObject)
@@ -922,16 +867,19 @@
def next__DictMultiIterObject(space, w_dictiter):
iteratorimplementation = w_dictiter.iteratorimplementation
- w_result = iteratorimplementation.next()
- if w_result is not None:
- return w_result
+ w_key, w_value = iteratorimplementation.next()
+ if w_key is not None:
+ itertype = w_dictiter.itertype
+ if itertype == KEYSITER:
+ return w_key
+ elif itertype == VALUESITER:
+ return w_value
+ elif itertype == ITEMSITER:
+ return space.newtuple([w_key, w_value])
+ else:
+ assert 0, "should be unreachable"
raise OperationError(space.w_StopIteration, space.w_None)
-# XXX __length_hint__()
-##def len__DictMultiIterObject(space, w_dictiter):
-## iteratorimplementation = w_dictiter.iteratorimplementation
-## return space.wrap(iteratorimplementation.length())
-
# ____________________________________________________________
from pypy.objspace.std import dicttype
Modified: pypy/trunk/pypy/objspace/std/dicttype.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/dicttype.py (original)
+++ pypy/trunk/pypy/objspace/std/dicttype.py Tue Nov 3 11:42:42 2009
@@ -141,8 +141,8 @@
# ____________________________________________________________
def descr__new__(space, w_dicttype, __args__):
- w_obj = space.allocate_instance(space.DictObjectCls, w_dicttype)
- space.DictObjectCls.__init__(w_obj, space)
+ from pypy.objspace.std.dictmultiobject import W_DictMultiObject
+ w_obj = W_DictMultiObject.allocate_and_init_instance(space, w_dicttype)
return w_obj
# ____________________________________________________________
Added: pypy/trunk/pypy/objspace/std/inlinedict.py
==============================================================================
--- (empty file)
+++ pypy/trunk/pypy/objspace/std/inlinedict.py Tue Nov 3 11:42:42 2009
@@ -0,0 +1,139 @@
+import py
+from pypy.interpreter.typedef import check_new_dictionary
+from pypy.objspace.std.dictmultiobject import W_DictMultiObject
+from pypy.objspace.std.dictmultiobject import StrDictImplementation
+from pypy.objspace.std.dictmultiobject import IteratorImplementation
+from pypy.objspace.std.dictmultiobject import implementation_methods
+from pypy.tool.sourcetools import func_with_new_name
+
+def make_mixin(config):
+ if config.objspace.std.withsharingdict:
+ from pypy.objspace.std.sharingdict import SharedDictImplementation
+ return make_inlinedict_mixin(SharedDictImplementation, "structure")
+ else:
+ return make_inlinedict_mixin(StrDictImplementation, "content")
+
+def make_indirection_method(methname, numargs):
+ # *args don't work, the call normalization gets confused
+ args = ", ".join(["a" + str(i) for i in range(numargs)])
+ code = """def f(self, %s):
+ return self.w_obj.%s(%s)
+""" % (args, methname, args)
+ d = {}
+ exec py.code.Source(code).compile() in d
+ func = d["f"]
+ func.func_name = methname + "_indirect"
+ func.func_defaults = getattr(W_DictMultiObject, methname).func_defaults
+ return func
+
+def make_inlinedict_mixin(dictimplclass, attrname):
+ assert dictimplclass.__base__ is W_DictMultiObject
+ class IndirectionIterImplementation(IteratorImplementation):
+ def __init__(self, space, dictimpl, itemlist):
+ IteratorImplementation.__init__(self, space, dictimpl)
+ self.itemlist = itemlist
+
+ def next_entry(self):
+ return self.itemlist[self.pos]
+
+ class IndirectionDictImplementation(W_DictMultiObject):
+ def __init__(self, space, w_obj):
+ self.space = space
+ self.w_obj = w_obj
+
+ def impl_iter(self):
+ # XXX sucky
+ items = []
+ for w_item in self.impl_items():
+ w_key, w_value = self.space.viewiterable(w_item)
+ items.append((w_key, w_value))
+ return IndirectionIterImplementation(self.space, self, items)
+
+ IndirectionDictImplementation.__name__ = "IndirectionDictImplementation" + dictimplclass.__name__
+
+ for methname, numargs in implementation_methods:
+ implname = "impl_" + methname
+ if implname != "impl_iter":
+ setattr(IndirectionDictImplementation, implname,
+ make_indirection_method(implname, numargs))
+
+ init_dictattributes = func_with_new_name(dictimplclass.__init__.im_func,
+ "init_dictattributes")
+ make_rdict = func_with_new_name(dictimplclass._as_rdict.im_func,
+ "make_rdict")
+ clear_fields = func_with_new_name(dictimplclass._clear_fields.im_func,
+ "clear_fields")
+
+ class InlineDictMixin(object):
+
+ def user_setup(self, space, w_subtype):
+ self.space = space
+ self.w__class__ = w_subtype
+ self.w__dict__ = None
+ init_dictattributes(self, space)
+ assert getattr(self, attrname) is not None
+ self.user_setup_slots(w_subtype.nslots)
+
+ def getdict(self):
+ w__dict__ = self.w__dict__
+ if w__dict__ is None:
+ w__dict__ = IndirectionDictImplementation(self.space, self)
+ self.w__dict__ = w__dict__
+ assert isinstance(w__dict__, W_DictMultiObject)
+ return w__dict__
+
+ def _inlined_dict_valid(self):
+ return getattr(self, attrname) is not None
+
+ def getdictvalue(self, space, attr):
+ if self._inlined_dict_valid():
+ return self.impl_getitem_str(attr)
+ w_dict = self.getdict()
+ return w_dict.getitem_str(attr)
+
+ def getdictvalue_attr_is_in_class(self, space, attr):
+ return self.getdictvalue(space, attr)
+
+ def setdictvalue(self, space, attr, w_value, shadows_type=True):
+ if self._inlined_dict_valid():
+ # XXX don't ignore shadows_type
+ self.impl_setitem_str(attr, w_value)
+ return True
+ w_dict = self.getdict()
+ w_dict.setitem_str(attr, w_value)
+ return True
+
+ def deldictvalue(self, space, w_attr):
+ if self._inlined_dict_valid():
+ try:
+ self.impl_delitem(w_attr)
+ except KeyError:
+ return False
+ return True
+ w_dict = self.getdict()
+ try:
+ w_dict.delitem(w_attr)
+ except KeyError:
+ return False
+ return True
+
+ def setdict(self, space, w_dict):
+ self._clear_fields() # invalidate attributes on self
+ self.w__dict__ = check_new_dictionary(space, w_dict)
+
+ def _as_rdict(self):
+ make_rdict(self)
+ return self.getdict()
+
+ def initialize_as_rdict(self):
+ return self.getdict().initialize_as_rdict()
+
+ _clear_fields = clear_fields
+
+ for methname, _ in implementation_methods:
+ implname = "impl_" + methname
+ meth = func_with_new_name(getattr(dictimplclass, implname).im_func,
+ implname)
+ if not hasattr(InlineDictMixin, implname):
+ setattr(InlineDictMixin, implname, meth)
+ return InlineDictMixin
Modified: pypy/trunk/pypy/objspace/std/marshal_impl.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/marshal_impl.py (original)
+++ pypy/trunk/pypy/objspace/std/marshal_impl.py Tue Nov 3 11:42:42 2009
@@ -355,7 +355,7 @@
def marshal_w__DictMulti(space, w_dict, m):
m.start(TYPE_DICT)
- for w_tuple in w_dict.implementation.items():
+ for w_tuple in w_dict.items():
w_key, w_value = space.viewiterable(w_tuple, 2)
m.put_w_obj(w_key)
m.put_w_obj(w_value)
Modified: pypy/trunk/pypy/objspace/std/model.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/model.py (original)
+++ pypy/trunk/pypy/objspace/std/model.py Tue Nov 3 11:42:42 2009
@@ -26,6 +26,7 @@
def __init__(self, config):
"""NOT_RPYTHON: inititialization only"""
+ self.config = config
# All the Python types that we want to provide in this StdObjSpace
class result:
from pypy.objspace.std.objecttype import object_typedef
@@ -250,7 +251,7 @@
for cls in self.typeorder:
if (hasattr(cls, 'typedef') and cls.typedef is not None and
cls.typedef.acceptable_as_base_class):
- subclslist = enum_interplevel_subclasses(cls)
+ subclslist = enum_interplevel_subclasses(self.config, cls)
for subcls in subclslist:
if cls in subcls.__bases__: # only direct subclasses
# for user subclasses we only accept "generic"
Modified: pypy/trunk/pypy/objspace/std/objectobject.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/objectobject.py (original)
+++ pypy/trunk/pypy/objspace/std/objectobject.py Tue Nov 3 11:42:42 2009
@@ -1,4 +1,4 @@
-from pypy.objspace.std.objspace import *
+from pypy.objspace.std.objspace import W_Object, register_all
class W_ObjectObject(W_Object):
Modified: pypy/trunk/pypy/objspace/std/objecttype.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/objecttype.py (original)
+++ pypy/trunk/pypy/objspace/std/objecttype.py Tue Nov 3 11:42:42 2009
@@ -63,7 +63,6 @@
space.wrap("default __new__ takes "
"no parameters"))
w_obj = space.allocate_instance(W_ObjectObject, w_type)
- #W_ObjectObject.__init__(w_obj)
return w_obj
def descr__init__(space, w_obj, __args__):
Modified: pypy/trunk/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/objspace.py (original)
+++ pypy/trunk/pypy/objspace/std/objspace.py Tue Nov 3 11:42:42 2009
@@ -140,13 +140,13 @@
w_globals = f.w_globals
num = oparg >> 8
assert isinstance(w_globals, W_DictMultiObject)
- w_value = w_globals.implementation.get_builtin_indexed(num)
+ w_value = w_globals.get_builtin_indexed(num)
if w_value is None:
builtins = f.get_builtin()
assert isinstance(builtins, Module)
w_builtin_dict = builtins.w_dict
assert isinstance(w_builtin_dict, W_DictMultiObject)
- w_value = w_builtin_dict.implementation.get_builtin_indexed(num)
+ w_value = w_builtin_dict.get_builtin_indexed(num)
## if w_value is not None:
## print "CALL_LIKELY_BUILTIN fast"
if w_value is None:
@@ -240,16 +240,9 @@
self.FrameClass = StdObjSpaceFrame
- # XXX store the dict class on the space to access it in various places
+ # store the dict class on the space to access it in various places
from pypy.objspace.std import dictmultiobject
self.DictObjectCls = dictmultiobject.W_DictMultiObject
- self.emptydictimpl = dictmultiobject.EmptyDictImplementation(self)
- if self.config.objspace.std.withbucketdict:
- from pypy.objspace.std import dictbucket
- self.DefaultDictImpl = dictbucket.BucketDictImplementation
- else:
- self.DefaultDictImpl = dictmultiobject.RDictImplementation
- assert self.DictObjectCls in self.model.typeorder
from pypy.objspace.std import tupleobject
self.TupleObjectCls = tupleobject.W_TupleObject
@@ -577,11 +570,13 @@
from pypy.objspace.std.listobject import W_ListObject
return W_ListObject(list_w)
- def newdict(self, module=False):
+ def newdict(self, module=False, instance=False, classofinstance=None,
+ from_strdict_shared=None):
from pypy.objspace.std.dictmultiobject import W_DictMultiObject
- if module:
- return W_DictMultiObject(self, module=True)
- return W_DictMultiObject(self)
+ return W_DictMultiObject.allocate_and_init_instance(
+ self, module=module, instance=instance,
+ classofinstance=classofinstance,
+ from_strdict_shared=from_strdict_shared)
def newslice(self, w_start, w_end, w_step):
return W_SliceObject(w_start, w_end, w_step)
@@ -615,12 +610,14 @@
user-defined type, without actually __init__ializing the instance."""
w_type = self.gettypeobject(cls.typedef)
if self.is_w(w_type, w_subtype):
- instance = instantiate(cls)
+ instance = instantiate(cls)
elif cls.typedef.acceptable_as_base_class:
# the purpose of the above check is to avoid the code below
# to be annotated at all for 'cls' if it is not necessary
w_subtype = w_type.check_user_subclass(w_subtype)
- subcls = get_unique_interplevel_subclass(cls, w_subtype.hasdict, w_subtype.nslots != 0, w_subtype.needsdel, w_subtype.weakrefable)
+ subcls = get_unique_interplevel_subclass(
+ self.config, cls, w_subtype.hasdict, w_subtype.nslots != 0,
+ w_subtype.needsdel, w_subtype.weakrefable)
instance = instantiate(subcls)
instance.user_setup(self, w_subtype)
else:
@@ -672,7 +669,6 @@
return self.int_w(l_w[0]), self.int_w(l_w[1]), self.int_w(l_w[2])
def is_(self, w_one, w_two):
- # XXX a bit of hacking to gain more speed
if w_one is w_two:
return self.w_True
return self.w_False
@@ -712,7 +708,7 @@
e = None
if w_descr is not None:
if not self.is_data_descr(w_descr):
- w_value = w_obj.getdictvalue_attr_is_in_class(self, w_name)
+ w_value = w_obj.getdictvalue_attr_is_in_class(self, name)
if w_value is not None:
return w_value
try:
@@ -721,7 +717,7 @@
if not e.match(self, self.w_AttributeError):
raise
else:
- w_value = w_obj.getdictvalue(self, w_name)
+ w_value = w_obj.getdictvalue(self, name)
if w_value is not None:
return w_value
@@ -733,18 +729,27 @@
else:
raiseattrerror(self, w_obj, name)
+ def finditem_str(self, w_obj, key):
+ # performance shortcut to avoid creating the OperationError(KeyError)
+ if (isinstance(w_obj, self.DictObjectCls) and
+ not w_obj.user_overridden_class):
+ return w_obj.getitem_str(key)
+ return ObjSpace.finditem_str(self, w_obj, key)
+
def finditem(self, w_obj, w_key):
# performance shortcut to avoid creating the OperationError(KeyError)
- if type(w_obj) is self.DictObjectCls:
- return w_obj.get(w_key, None)
+ if (isinstance(w_obj, self.DictObjectCls) and
+ not w_obj.user_overridden_class):
+ return w_obj.getitem(w_key)
return ObjSpace.finditem(self, w_obj, w_key)
- def set_str_keyed_item(self, w_obj, w_key, w_value, shadows_type=True):
+ def set_str_keyed_item(self, w_obj, key, w_value, shadows_type=True):
# performance shortcut to avoid creating the OperationError(KeyError)
- if type(w_obj) is self.DictObjectCls:
- w_obj.set_str_keyed_item(w_key, w_value, shadows_type)
+ if (isinstance(w_obj, self.DictObjectCls) and
+ not w_obj.user_overridden_class):
+ w_obj.set_str_keyed_item(key, w_value, shadows_type)
else:
- self.setitem(w_obj, w_key, w_value)
+ self.setitem(w_obj, self.wrap(key), w_value)
def getindex_w(self, w_obj, w_exception, objdescr=None):
# Performance shortcut for the common case of w_obj being an int.
Modified: pypy/trunk/pypy/objspace/std/proxyobject.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/proxyobject.py (original)
+++ pypy/trunk/pypy/objspace/std/proxyobject.py Tue Nov 3 11:42:42 2009
@@ -34,19 +34,19 @@
raise OperationError(space.w_TypeError,
space.wrap("You cannot override __class__ for transparent proxies"))
- def getdictvalue(self, space, w_attr):
+ def getdictvalue(self, space, attr):
try:
return space.call_function(self.w_controller, space.wrap('__getattribute__'),
- w_attr)
+ space.wrap(attr))
except OperationError, e:
if not e.match(space, space.w_AttributeError):
raise
return None
- def setdictvalue(self, space, w_attr, w_value, shadows_type=True):
+ def setdictvalue(self, space, attr, w_value, shadows_type=True):
try:
space.call_function(self.w_controller, space.wrap('__setattr__'),
- w_attr, w_value)
+ space.wrap(attr), w_value)
return True
except OperationError, e:
if not e.match(space, space.w_AttributeError):
@@ -64,19 +64,12 @@
return False
def getdict(self):
- return self.getdictvalue(self.space, self.space.wrap('__dict__'))
+ return self.getdictvalue(self.space, '__dict__')
def setdict(self, space, w_dict):
- if not self.setdictvalue(space, space.wrap('__dict__'), w_dict):
+ if not self.setdictvalue(space, '__dict__', w_dict):
baseobjspace.W_Root.setdict(self, space, w_dict)
-## def __getattr__(self, attr):
-## # NOT_RPYTHON
-## try:
-## return self.getdictvalue(self.space, self.space.wrap(attr))
-## except OperationError, e:
-## raise AttributeError(attr)
-
W_Transparent.__name__ = name
return W_Transparent
Modified: pypy/trunk/pypy/objspace/std/sharingdict.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/sharingdict.py (original)
+++ pypy/trunk/pypy/objspace/std/sharingdict.py Tue Nov 3 11:42:42 2009
@@ -1,4 +1,3 @@
-from pypy.objspace.std.dictmultiobject import DictImplementation, StrDictImplementation
from pypy.objspace.std.dictmultiobject import IteratorImplementation
from pypy.objspace.std.dictmultiobject import W_DictMultiObject, _is_sane_hash
from pypy.rlib.jit import purefunction, hint, we_are_jitted, unroll_safe
@@ -75,41 +74,42 @@
self.emptylist = []
-class SharedDictImplementation(DictImplementation):
+class SharedDictImplementation(W_DictMultiObject):
def __init__(self, space):
self.space = space
self.structure = space.fromcache(State).empty_structure
self.entries = space.fromcache(State).emptylist
- def get(self, w_lookup):
+ def impl_getitem(self, w_lookup):
space = self.space
w_lookup_type = space.type(w_lookup)
if space.is_w(w_lookup_type, space.w_str):
- lookup = space.str_w(w_lookup)
- i = self.structure.lookup_position(lookup)
- if i == -1:
- return None
- return self.entries[i]
+ return self.impl_getitem_str(space.str_w(w_lookup))
elif _is_sane_hash(space, w_lookup_type):
return None
else:
- return self._as_rdict().get(w_lookup)
+ return self._as_rdict().getitem(w_lookup)
- def setitem(self, w_key, w_value):
+ def impl_getitem_str(self, lookup):
+ i = self.structure.lookup_position(lookup)
+ if i == -1:
+ return None
+ return self.entries[i]
+
+ def impl_setitem(self, w_key, w_value):
space = self.space
if space.is_w(space.type(w_key), space.w_str):
- return self.setitem_str(w_key, w_value)
+ self.impl_setitem_str(self.space.str_w(w_key), w_value)
else:
- return self._as_rdict().setitem(w_key, w_value)
+ self._as_rdict().setitem(w_key, w_value)
@unroll_safe
- def setitem_str(self, w_key, w_value, shadows_type=True):
- key = self.space.str_w(w_key)
+ def impl_setitem_str(self, key, w_value, shadows_type=True):
i = self.structure.lookup_position(key)
if i != -1:
self.entries[i] = w_value
- return self
+ return
new_structure = self.structure.get_next_structure(key)
if new_structure.length > len(self.entries):
new_entries = [None] * new_structure.size_estimate()
@@ -120,9 +120,8 @@
self.entries[new_structure.length - 1] = w_value
assert self.structure.length + 1 == new_structure.length
self.structure = new_structure
- return self
- def delitem(self, w_key):
+ def impl_delitem(self, w_key):
space = self.space
w_key_type = space.type(w_key)
if space.is_w(w_key_type, space.w_str):
@@ -131,64 +130,47 @@
key == self.structure.last_key):
self.entries[self.structure.length - 1] = None
self.structure = self.structure.back_struct
- return self
- return self._as_rdict().delitem(w_key)
+ return
+ self._as_rdict().delitem(w_key)
elif _is_sane_hash(space, w_key_type):
raise KeyError
else:
- return self._as_rdict().delitem(w_key)
+ self._as_rdict().delitem(w_key)
- def length(self):
+ def impl_length(self):
return self.structure.length
- def iteritems(self):
- return SharedItemIteratorImplementation(self.space, self)
-
- def iterkeys(self):
- return SharedKeyIteratorImplementation(self.space, self)
+ def impl_iter(self):
+ return SharedIteratorImplementation(self.space, self)
- def itervalues(self):
- return SharedValueIteratorImplementation(self.space, self)
-
- def keys(self):
+ def impl_keys(self):
space = self.space
return [space.wrap(key)
- for (key, item) in self.structure.keys.iteritems()
- if item >= 0]
+ for (key, item) in self.structure.keys.iteritems()]
- def values(self):
+ def impl_values(self):
return self.entries[:self.structure.length]
- def items(self):
+ def impl_items(self):
space = self.space
return [space.newtuple([space.wrap(key), self.entries[item]])
- for (key, item) in self.structure.keys.iteritems()
- if item >= 0]
-
- def _as_rdict(self, as_strdict=False):
- if as_strdict:
- newimpl = StrDictImplementation(self.space)
- else:
- newimpl = self.space.DefaultDictImpl(self.space)
+ for (key, item) in self.structure.keys.iteritems()]
+ def impl_clear(self):
+ space = self.space
+ self.structure = space.fromcache(State).empty_structure
+ self.entries = space.fromcache(State).emptylist
+ def _as_rdict(self):
+ r_dict_content = self.initialize_as_rdict()
for k, i in self.structure.keys.items():
- if i >= 0:
- newimpl.setitem_str(self.space.wrap(k), self.entries[i])
- return newimpl
+ r_dict_content[self.space.wrap(k)] = self.entries[i]
+ self._clear_fields()
+ return self
+ def _clear_fields(self):
+ self.structure = None
+ self.entries = None
-class SharedValueIteratorImplementation(IteratorImplementation):
- def __init__(self, space, dictimplementation):
- IteratorImplementation.__init__(self, space, dictimplementation)
- self.values = dictimplementation.entries
-
- def next(self):
- if self.pos < self.len:
- return self.values[self.pos]
- else:
- self.values = None
- return None
-
-class SharedItemIteratorImplementation(IteratorImplementation):
+class SharedIteratorImplementation(IteratorImplementation):
def __init__(self, space, dictimplementation):
IteratorImplementation.__init__(self, space, dictimplementation)
self.iterator = dictimplementation.structure.keys.iteritems()
@@ -198,19 +180,6 @@
assert isinstance(implementation, SharedDictImplementation)
for key, index in self.iterator:
w_value = implementation.entries[index]
- return self.space.newtuple([self.space.wrap(key), w_value])
- else:
- return None
-
-class SharedKeyIteratorImplementation(IteratorImplementation):
- def __init__(self, space, dictimplementation):
- IteratorImplementation.__init__(self, space, dictimplementation)
- self.iterator = dictimplementation.structure.keys.iteritems()
-
- def next_entry(self):
- implementation = self.dictimplementation
- assert isinstance(implementation, SharedDictImplementation)
- for key, index in self.iterator:
- return self.space.wrap(key)
+ return self.space.wrap(key), w_value
else:
- return None
+ return None, None
Modified: pypy/trunk/pypy/objspace/std/test/test_celldict.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/test/test_celldict.py (original)
+++ pypy/trunk/pypy/objspace/std/test/test_celldict.py Tue Nov 3 11:42:42 2009
@@ -26,7 +26,7 @@
def rescue_builtins(space):
w_dict = space.builtin.getdict()
content = {}
- for key, cell in w_dict.implementation.content.iteritems():
+ for key, cell in w_dict.content.iteritems():
newcell = ModuleCell()
newcell.w_value = cell.w_value
content[key] = newcell
@@ -35,9 +35,9 @@
cls.w_rescue_builtins = cls.space.wrap(rescue_builtins)
def restore_builtins(space):
w_dict = space.builtin.getdict()
- if not isinstance(w_dict.implementation, ModuleDictImplementation):
- w_dict.implementation = ModuleDictImplementation(space)
- w_dict.implementation.content = stored_builtins.pop()
+ assert isinstance(w_dict, ModuleDictImplementation)
+ w_dict.content = stored_builtins.pop()
+ w_dict.fallback = None
restore_builtins = gateway.interp2app(restore_builtins)
cls.w_restore_builtins = cls.space.wrap(restore_builtins)
Modified: pypy/trunk/pypy/objspace/std/test/test_dictmultiobject.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/test/test_dictmultiobject.py (original)
+++ pypy/trunk/pypy/objspace/std/test/test_dictmultiobject.py Tue Nov 3 11:42:42 2009
@@ -1,10 +1,10 @@
from pypy.interpreter.error import OperationError
from pypy.objspace.std.dictmultiobject import \
W_DictMultiObject, setitem__DictMulti_ANY_ANY, getitem__DictMulti_ANY, \
- EmptyDictImplementation, RDictImplementation, StrDictImplementation, \
- MeasuringDictImplementation
+ StrDictImplementation
from pypy.objspace.std.celldict import ModuleDictImplementation
+from pypy.objspace.std.sharingdict import SharedDictImplementation
from pypy.conftest import gettestobjspace
@@ -15,13 +15,13 @@
def test_empty(self):
space = self.space
- d = self.space.DictObjectCls(space)
+ d = self.space.newdict()
assert not self.space.is_true(d)
def test_nonempty(self):
space = self.space
wNone = space.w_None
- d = self.space.DictObjectCls(space)
+ d = self.space.newdict()
d.initialize_content([(wNone, wNone)])
assert space.is_true(d)
i = space.getitem(d, wNone)
@@ -32,7 +32,7 @@
space = self.space
wk1 = space.wrap('key')
wone = space.wrap(1)
- d = self.space.DictObjectCls(space)
+ d = self.space.newdict()
d.initialize_content([(space.wrap('zero'),space.wrap(0))])
space.setitem(d,wk1,wone)
wback = space.getitem(d,wk1)
@@ -41,7 +41,7 @@
def test_delitem(self):
space = self.space
wk1 = space.wrap('key')
- d = self.space.DictObjectCls(space)
+ d = self.space.newdict()
d.initialize_content( [(space.wrap('zero'),space.wrap(0)),
(space.wrap('one'),space.wrap(1)),
(space.wrap('two'),space.wrap(2))])
@@ -52,7 +52,7 @@
space.getitem,d,space.wrap('one'))
def test_wrap_dict(self):
- assert isinstance(self.space.wrap({}), self.space.DictObjectCls)
+ assert isinstance(self.space.wrap({}), W_DictMultiObject)
def test_dict_compare(self):
@@ -134,8 +134,7 @@
space = self.space
w = space.wrap
d = {"a": w(1), "b": w(2)}
- w_d = space.DictObjectCls(space)
- w_d.initialize_from_strdict_shared(d)
+ w_d = space.newdict(from_strdict_shared=d)
assert self.space.eq_w(space.getitem(w_d, w("a")), w(1))
assert self.space.eq_w(space.getitem(w_d, w("b")), w(2))
@@ -143,8 +142,7 @@
space = self.space
w = space.wrap
d = {"a": w(1), "b": w(2)}
- w_d = space.DictObjectCls(space)
- w_d.initialize_from_strdict_shared(d)
+ w_d = space.newdict(from_strdict_shared=d)
assert self.space.eq_w(space.getitem(w_d, w("a")), w(1))
assert self.space.eq_w(space.getitem(w_d, w("b")), w(2))
d["c"] = w(41)
@@ -552,7 +550,11 @@
raises(KeyError, "d['def']")
-class C: pass
+
+class FakeString(str):
+ def unwrap(self, space):
+ self.unwrapped = True
+ return str(self)
# the minimal 'space' needed to use a W_DictMultiObject
class FakeSpace:
@@ -587,9 +589,25 @@
def newtuple(self, l):
return tuple(l)
+ def newdict(self, module=False, instance=False, classofinstance=None,
+ from_strdict_shared=None):
+ return W_DictMultiObject.allocate_and_init_instance(
+ self, module=module, instance=instance,
+ classofinstance=classofinstance,
+ from_strdict_shared=from_strdict_shared)
+
+ def allocate_instance(self, cls, type):
+ return object.__new__(cls)
+
+ def fromcache(self, cls):
+ return cls(self)
+
w_StopIteration = StopIteration
w_None = None
- StringObjectCls = None # xxx untested: shortcut in StrDictImpl.getitem
+ StringObjectCls = FakeString
+ w_dict = None
+ iter = iter
+ viewiterable = list
class Config:
@@ -599,6 +617,7 @@
withsharingdict = False
withsmalldicts = False
withcelldict = False
+ withshadowtracking = False
class opcodes:
CALL_LIKELY_BUILTIN = False
@@ -608,143 +627,147 @@
class TestDictImplementation:
def setup_method(self,method):
self.space = FakeSpace()
- self.space.emptydictimpl = EmptyDictImplementation(self.space)
- self.space.DefaultDictImpl = RDictImplementation
def test_stressdict(self):
from random import randint
- d = self.space.DictObjectCls(self.space)
+ d = self.space.newdict()
N = 10000
pydict = {}
for i in range(N):
x = randint(-N, N)
setitem__DictMulti_ANY_ANY(self.space, d, x, i)
pydict[x] = i
- for x in pydict:
- assert pydict[x] == getitem__DictMulti_ANY(self.space, d, x)
+ for key, value in pydict.iteritems():
+ assert value == getitem__DictMulti_ANY(self.space, d, key)
-class TestRDictImplementation:
- ImplementionClass = RDictImplementation
- DevolvedClass = RDictImplementation
- EmptyClass = EmptyDictImplementation
- DefaultDictImpl = RDictImplementation
+class BaseTestRDictImplementation:
def setup_method(self,method):
- self.space = FakeSpace()
- self.space.emptydictimpl = EmptyDictImplementation(self.space)
- self.space.DefaultDictImpl = self.DefaultDictImpl
- self.string = self.space.wrap("fish")
- self.string2 = self.space.wrap("fish2")
+ self.fakespace = FakeSpace()
+ self.string = self.fakespace.wrap("fish")
+ self.string2 = self.fakespace.wrap("fish2")
self.impl = self.get_impl()
def get_impl(self):
- "Needs to be empty, or one entry with key self.string"
- return self.ImplementionClass(self.space)
+ return self.ImplementionClass(self.fakespace)
+
+ def fill_impl(self):
+ self.impl.setitem(self.string, 1000)
+ self.impl.setitem(self.string2, 2000)
+
+ def check_not_devolved(self):
+ assert self.impl.r_dict_content is None
def test_setitem(self):
- assert self.impl.setitem(self.string, 1000) is self.impl
+ self.impl.setitem(self.string, 1000)
assert self.impl.length() == 1
- assert self.impl.get(self.string) == 1000
+ assert self.impl.getitem(self.string) == 1000
+ assert self.impl.getitem_str(self.string) == 1000
+ self.check_not_devolved()
def test_setitem_str(self):
- assert self.impl.setitem_str(self.space.str_w(self.string), 1000) is self.impl
+ self.impl.setitem_str(self.fakespace.str_w(self.string), 1000)
assert self.impl.length() == 1
- assert self.impl.get(self.string) == 1000
+ assert self.impl.getitem(self.string) == 1000
+ assert self.impl.getitem_str(self.string) == 1000
+ self.check_not_devolved()
def test_delitem(self):
- self.impl.setitem(self.string, 1000)
- self.impl.setitem(self.string2, 2000)
+ self.fill_impl()
assert self.impl.length() == 2
- newimpl = self.impl.delitem(self.string)
+ self.impl.delitem(self.string2)
assert self.impl.length() == 1
- assert newimpl is self.impl
- newimpl = self.impl.delitem(self.string2)
+ self.impl.delitem(self.string)
assert self.impl.length() == 0
- assert isinstance(newimpl, self.EmptyClass)
+ self.check_not_devolved()
def test_keys(self):
- self.impl.setitem(self.string, 1000)
- self.impl.setitem(self.string2, 2000)
+ self.fill_impl()
keys = self.impl.keys()
keys.sort()
assert keys == [self.string, self.string2]
+ self.check_not_devolved()
def test_values(self):
- self.impl.setitem(self.string, 1000)
- self.impl.setitem(self.string2, 2000)
+ self.fill_impl()
values = self.impl.values()
values.sort()
assert values == [1000, 2000]
+ self.check_not_devolved()
def test_items(self):
- self.impl.setitem(self.string, 1000)
- self.impl.setitem(self.string2, 2000)
+ self.fill_impl()
items = self.impl.items()
items.sort()
assert items == zip([self.string, self.string2], [1000, 2000])
+ self.check_not_devolved()
- def test_iterkeys(self):
- self.impl.setitem(self.string, 1000)
- self.impl.setitem(self.string2, 2000)
- iteratorimplementation = self.impl.iterkeys()
- keys = []
- while 1:
- key = iteratorimplementation.next()
- if key is None:
- break
- keys.append(key)
- keys.sort()
- assert keys == [self.string, self.string2]
-
- def test_itervalues(self):
- self.impl.setitem(self.string, 1000)
- self.impl.setitem(self.string2, 2000)
- iteratorimplementation = self.impl.itervalues()
- values = []
- while 1:
- value = iteratorimplementation.next()
- if value is None:
- break
- values.append(value)
- values.sort()
- assert values == [1000, 2000]
-
- def test_iteritems(self):
- self.impl.setitem(self.string, 1000)
- self.impl.setitem(self.string2, 2000)
- iteratorimplementation = self.impl.iteritems()
+ def test_iter(self):
+ self.fill_impl()
+ iteratorimplementation = self.impl.iter()
items = []
while 1:
item = iteratorimplementation.next()
- if item is None:
+ if item == (None, None):
break
items.append(item)
items.sort()
assert items == zip([self.string, self.string2], [1000, 2000])
+ self.check_not_devolved()
def test_devolve(self):
impl = self.impl
for x in xrange(100):
- impl = impl.setitem(self.space.str_w(str(x)), x)
- impl = impl.setitem(x, x)
- assert isinstance(impl, self.DevolvedClass)
+ impl.setitem(self.fakespace.str_w(str(x)), x)
+ impl.setitem(x, x)
+ assert impl.r_dict_content is not None
-class TestStrDictImplementation(TestRDictImplementation):
+class TestStrDictImplementation(BaseTestRDictImplementation):
ImplementionClass = StrDictImplementation
-class TestMeasuringDictImplementation(TestRDictImplementation):
- ImplementionClass = MeasuringDictImplementation
- DevolvedClass = MeasuringDictImplementation
- EmptyClass = MeasuringDictImplementation
+ def test_str_shortcut(self):
+ self.fill_impl()
+ s = FakeString(self.string)
+ assert self.impl.getitem(s) == 1000
+ assert s.unwrapped
+
+## class TestMeasuringDictImplementation(BaseTestRDictImplementation):
+## ImplementionClass = MeasuringDictImplementation
+## DevolvedClass = MeasuringDictImplementation
+
+class TestModuleDictImplementation(BaseTestRDictImplementation):
+ ImplementionClass = ModuleDictImplementation
-class TestModuleDictImplementation(TestRDictImplementation):
+class TestModuleDictImplementationWithBuiltinNames(BaseTestRDictImplementation):
ImplementionClass = ModuleDictImplementation
- EmptyClass = ModuleDictImplementation
-class TestModuleDictImplementationWithBuiltinNames(TestRDictImplementation):
+ string = "int"
+ string2 = "isinstance"
+
+class TestSharedDictImplementation(BaseTestRDictImplementation):
+ ImplementionClass = SharedDictImplementation
+
+
+class BaseTestDevolvedDictImplementation(BaseTestRDictImplementation):
+ def fill_impl(self):
+ BaseTestRDictImplementation.fill_impl(self)
+ self.impl._as_rdict()
+
+ def check_not_devolved(self):
+ pass
+
+class TestDevolvedStrDictImplementation(BaseTestDevolvedDictImplementation):
+ ImplementionClass = StrDictImplementation
+
+class TestDevolvedModuleDictImplementation(BaseTestDevolvedDictImplementation):
+ ImplementionClass = ModuleDictImplementation
+
+class TestDevolvedModuleDictImplementationWithBuiltinNames(BaseTestDevolvedDictImplementation):
ImplementionClass = ModuleDictImplementation
- EmptyClass = ModuleDictImplementation
string = "int"
string2 = "isinstance"
+class TestDevolvedSharedDictImplementation(BaseTestDevolvedDictImplementation):
+ ImplementionClass = SharedDictImplementation
+
Added: pypy/trunk/pypy/objspace/std/test/test_inlinedict.py
==============================================================================
--- (empty file)
+++ pypy/trunk/pypy/objspace/std/test/test_inlinedict.py Tue Nov 3 11:42:42 2009
@@ -0,0 +1,127 @@
+from pypy.conftest import gettestobjspace
+from pypy.objspace.std.inlinedict import make_inlinedict_mixin
+from pypy.objspace.std.dictmultiobject import StrDictImplementation
+from pypy.objspace.std.test.test_dictmultiobject import FakeSpace
+from pypy.objspace.std.test.test_dictmultiobject import BaseTestRDictImplementation
+from pypy.objspace.std.sharingdict import SharedDictImplementation
+
+class FakeSubtype:
+ nslots = 0
+
+class TestMixin(object):
+ Mixin = make_inlinedict_mixin(StrDictImplementation, "content")
+ class FakeObject(Mixin):
+ def user_setup_slots(self, nslots):
+ pass
+
+ fakespace = FakeSpace()
+
+ def make_obj(self):
+ obj = self.FakeObject()
+ obj.user_setup(self.fakespace, FakeSubtype)
+ obj.setdictvalue(self.fakespace, "hello", 1)
+ obj.setdictvalue(self.fakespace, "world", 2)
+ assert obj._inlined_dict_valid()
+ assert obj.w__dict__ is None
+ return obj
+
+ def test_setgetdel_dictvalue(self):
+ obj = self.make_obj()
+ assert obj.getdictvalue(self.fakespace, "hello") == 1
+ assert obj.getdictvalue(self.fakespace, "world") == 2
+ assert obj.getdictvalue(self.fakespace, "bla") is None
+ assert not obj.deldictvalue(self.fakespace, "bla")
+ obj.deldictvalue(self.fakespace, "world")
+ assert obj.getdictvalue(self.fakespace, "world") is None
+ obj.deldictvalue(self.fakespace, "hello")
+ assert obj.getdictvalue(self.fakespace, "hello") is None
+
+
+ def test_getdict(self):
+ obj = self.make_obj()
+ w_dict = obj.getdict()
+ assert obj.getdict() is w_dict # always get the same dict
+ assert obj.w__dict__ is w_dict
+
+ assert w_dict.getitem("hello") == 1
+ assert w_dict.getitem("world") == 2
+ w_dict.setitem("hello", 4)
+ w_dict.setitem("world", 5)
+ assert obj.getdictvalue(self.fakespace, "hello") == 4
+ assert obj.getdictvalue(self.fakespace, "world") == 5
+
+ def test_setdict(self):
+ obj1 = self.make_obj()
+ w_dict1 = obj1.getdict()
+ obj2 = self.make_obj()
+ w_dict2 = obj2.getdict()
+ w_dict2.setitem(4, 1) # devolve dict
+ w_dict2.setitem(5, 2)
+ obj2.setdict(self.space, w_dict1)
+ assert obj2.getdictvalue(self.fakespace, "hello") == 1
+ assert obj2.getdictvalue(self.fakespace, "world") == 2
+ obj1.setdictvalue(self.fakespace, "hello", 4)
+ obj1.setdictvalue(self.fakespace, "world", 5)
+ assert obj2.getdictvalue(self.fakespace, "hello") == 4
+ assert obj2.getdictvalue(self.fakespace, "world") == 5
+
+
+ def test_dict_devolves_via_dict(self):
+ obj = self.make_obj()
+ w_dict = obj.getdict()
+ w_dict.setitem(4, 1)
+ w_dict.setitem(5, 2)
+ assert dict(w_dict.r_dict_content) == {4: 1, 5: 2, "hello": 1, "world": 2}
+ assert obj.getdictvalue(self.fakespace, "hello") == 1
+ assert obj.getdictvalue(self.fakespace, "world") == 2
+ assert obj.getdictvalue(self.fakespace, 4) == 1
+ assert obj.getdictvalue(self.fakespace, 5) == 2
+ obj.deldictvalue(self.fakespace, "world")
+ assert obj.getdictvalue(self.fakespace, "world") is None
+ obj.deldictvalue(self.fakespace, "hello")
+ assert obj.getdictvalue(self.fakespace, "hello") is None
+
+class TestMixinShared(TestMixin):
+ Mixin = make_inlinedict_mixin(SharedDictImplementation, "structure")
+ class FakeObject(Mixin):
+ def user_setup_slots(self, nslots):
+ pass
+
+class TestIndirectDict(BaseTestRDictImplementation):
+ Mixin = make_inlinedict_mixin(StrDictImplementation, "content")
+ class FakeObject(Mixin):
+ def user_setup_slots(self, nslots):
+ pass
+
+ def get_impl(self):
+ obj = self.FakeObject()
+ obj.user_setup(self.fakespace, FakeSubtype)
+ return obj.getdict()
+
+
+class TestIndirectDictShared(TestIndirectDict):
+ Mixin = make_inlinedict_mixin(SharedDictImplementation, "structure")
+ class FakeObject(Mixin):
+ def user_setup_slots(self, nslots):
+ pass
+
+
+
+
+class TestInlineDict(object):
+ def setup_class(cls):
+ cls.space = gettestobjspace(**{"objspace.std.withinlineddict": True})
+
+ def test_simple(self):
+ w_a = self.space.appexec([], """():
+ class A(object):
+ pass
+ a = A()
+ a.x = 12
+ a.y = 13
+ return a
+ """)
+ assert w_a.w__dict__ is None
+ assert self.space.int_w(w_a.content['x']) == 12
+ assert self.space.int_w(w_a.content['y']) == 13
+
Modified: pypy/trunk/pypy/objspace/std/test/test_obj.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/test/test_obj.py (original)
+++ pypy/trunk/pypy/objspace/std/test/test_obj.py Tue Nov 3 11:42:42 2009
@@ -1,4 +1,3 @@
-# -*- coding: iso-8859-1 -*-
from pypy.conftest import option
class AppTestObject:
Modified: pypy/trunk/pypy/objspace/std/test/test_shadowtracking.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/test/test_shadowtracking.py (original)
+++ pypy/trunk/pypy/objspace/std/test/test_shadowtracking.py Tue Nov 3 11:42:42 2009
@@ -13,15 +13,15 @@
a = A()
return a
""")
- assert not w_inst.w__dict__.implementation.shadows_anything()
+ assert not w_inst.getdict().shadows_anything()
space.appexec([w_inst], """(a):
a.g = "foo"
""")
- assert not w_inst.w__dict__.implementation.shadows_anything()
+ assert not w_inst.getdict().shadows_anything()
space.appexec([w_inst], """(a):
a.f = "foo"
""")
- assert w_inst.w__dict__.implementation.shadows_anything()
+ assert w_inst.getdict().shadows_anything()
def test_shadowing_via__dict__(self):
space = self.space
@@ -32,15 +32,15 @@
a = A()
return a
""")
- assert not w_inst.w__dict__.implementation.shadows_anything()
+ assert not w_inst.getdict().shadows_anything()
space.appexec([w_inst], """(a):
a.__dict__["g"] = "foo"
""")
- assert not w_inst.w__dict__.implementation.shadows_anything()
+ assert not w_inst.getdict().shadows_anything()
space.appexec([w_inst], """(a):
a.__dict__["f"] = "foo"
""")
- assert w_inst.w__dict__.implementation.shadows_anything()
+ assert w_inst.getdict().shadows_anything()
def test_changing__dict__(self):
space = self.space
@@ -51,11 +51,11 @@
a = A()
return a
""")
- assert not w_inst.w__dict__.implementation.shadows_anything()
+ assert not w_inst.getdict().shadows_anything()
space.appexec([w_inst], """(a):
a.__dict__ = {}
""")
- assert w_inst.w__dict__.implementation.shadows_anything()
+ assert w_inst.getdict().shadows_anything()
def test_changing__class__(self):
space = self.space
@@ -66,14 +66,14 @@
a = A()
return a
""")
- assert not w_inst.w__dict__.implementation.shadows_anything()
+ assert not w_inst.getdict().shadows_anything()
space.appexec([w_inst], """(a):
class B(object):
def g(self):
return 42
a.__class__ = B
""")
- assert w_inst.w__dict__.implementation.shadows_anything()
+ assert w_inst.getdict().shadows_anything()
def test_changing_the_type(self):
space = self.space
@@ -84,13 +84,13 @@
a.x = 72
return a
""")
- assert not w_inst.w__dict__.implementation.shadows_anything()
+ assert not w_inst.getdict().shadows_anything()
w_x = space.appexec([w_inst], """(a):
a.__class__.x = 42
return a.x
""")
assert space.unwrap(w_x) == 72
- assert w_inst.w__dict__.implementation.shadows_anything()
+ assert w_inst.getdict().shadows_anything()
class AppTestShadowTracking(object):
def setup_class(cls):
Modified: pypy/trunk/pypy/objspace/std/typeobject.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/typeobject.py (original)
+++ pypy/trunk/pypy/objspace/std/typeobject.py Tue Nov 3 11:42:42 2009
@@ -131,10 +131,7 @@
def compute_default_mro(w_self):
return compute_C3_mro(w_self.space, w_self)
- def getdictvalue(w_self, space, w_attr):
- return w_self.getdictvalue_w(space, space.str_w(w_attr))
-
- def getdictvalue_w(w_self, space, attr):
+ def getdictvalue(w_self, space, attr):
w_value = w_self.dict_w.get(attr, None)
if w_self.lazyloaders and w_value is None:
if attr in w_self.lazyloaders:
@@ -172,7 +169,7 @@
if w_class is w_starttype:
look = True
elif look:
- w_value = w_class.getdictvalue_w(space, name)
+ w_value = w_class.getdictvalue(space, name)
if w_value is not None:
return w_value
return None
@@ -182,7 +179,7 @@
def _lookup(w_self, key):
space = w_self.space
for w_class in w_self.mro_w:
- w_value = w_class.getdictvalue_w(space, key)
+ w_value = w_class.getdictvalue(space, key)
if w_value is not None:
return w_value
return None
@@ -193,7 +190,7 @@
# attribute was found
space = w_self.space
for w_class in w_self.mro_w:
- w_value = w_class.getdictvalue_w(space, key)
+ w_value = w_class.getdictvalue(space, key)
if w_value is not None:
return w_class, w_value
return None, None
@@ -273,7 +270,7 @@
"NOT_RPYTHON. Forces the lazy attributes to be computed."
if 'lazyloaders' in w_self.__dict__:
for attr in w_self.lazyloaders.keys():
- w_self.getdictvalue_w(w_self.space, attr)
+ w_self.getdictvalue(w_self.space, attr)
del w_self.lazyloaders
return False
@@ -281,8 +278,7 @@
if w_self.lazyloaders:
w_self._freeze_() # force un-lazification
space = w_self.space
- newdic = space.DictObjectCls(space)
- newdic.initialize_from_strdict_shared(w_self.dict_w)
+ newdic = space.newdict(from_strdict_shared=w_self.dict_w)
return W_DictProxyObject(newdic)
def unwrap(w_self, space):
Modified: pypy/trunk/pypy/objspace/std/typetype.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/typetype.py (original)
+++ pypy/trunk/pypy/objspace/std/typetype.py Tue Nov 3 11:42:42 2009
@@ -174,7 +174,7 @@
return space.wrap("""type(object) -> the object's type
type(name, bases, dict) -> a new type""")
w_type = _check(space, w_type)
- w_result = w_type.getdictvalue_w(space, '__doc__')
+ w_result = w_type.getdictvalue(space, '__doc__')
if w_result is None:
return space.w_None
else:
Modified: pypy/trunk/pypy/objspace/taint.py
==============================================================================
--- pypy/trunk/pypy/objspace/taint.py (original)
+++ pypy/trunk/pypy/objspace/taint.py Tue Nov 3 11:42:42 2009
@@ -20,14 +20,11 @@
## def getdict(self):
## return taint(self.w_obj.getdict())
-## def getdictvalue_w(self, space, attr):
-## return taint(self.w_obj.getdictvalue_w(space, attr))
+## def getdictvalue(self, space, attr):
+## return taint(self.w_obj.getdictvalue(space, attr))
-## def getdictvalue(self, space, w_attr):
-## return taint(self.w_obj.getdictvalue(space, w_attr))
-
-## def setdictvalue(self, space, w_attr, w_value):
-## return self.w_obj.setdictvalue(space, w_attr, w_value)
+## def setdictvalue(self, space, attr, w_value):
+## return self.w_obj.setdictvalue(space, attr, w_value)
## ...
More information about the Pypy-commit
mailing list