[pypy-commit] pypy cpyext-for-merge: merge default into branch
mattip
pypy.commits at gmail.com
Tue Apr 26 15:47:47 EDT 2016
Author: mattip <matti.picus at gmail.com>
Branch: cpyext-for-merge
Changeset: r83918:ae02014e8547
Date: 2016-04-26 22:44 +0300
http://bitbucket.org/pypy/pypy/changeset/ae02014e8547/
Log: merge default into branch
diff too long, truncating to 2000 out of 2734 lines
diff --git a/lib-python/stdlib-upgrade.txt b/lib-python/stdlib-upgrade.txt
--- a/lib-python/stdlib-upgrade.txt
+++ b/lib-python/stdlib-upgrade.txt
@@ -5,15 +5,23 @@
overly detailed
-1. check out the branch vendor/stdlib
+0. make sure your working dir is clean
+1. check out the branch vendor/stdlib (for 2.7) or vendor/stdlib-3-* (for py3k)
+ or create branch vendor/stdlib-3-*
2. upgrade the files there
+ 2a. remove lib-python/2.7/ or lib-python/3/
+ 2b. copy the files from the cpython repo
+ 2c. hg add lib-python/2.7/ or lib-python/3/
+ 2d. hg remove --after
+ 2e. show copied files in cpython repo by running `hg diff --git -r v<old> -r v<new> Lib | grep '^copy \(from\|to\)'`
+ 2f. fix copies / renames manually by running `hg copy --after <from> <to>` for each copied file
3. update stdlib-version.txt with the output of hg -id from the cpython repo
4. commit
-5. update to default/py3k
+5. update to default / py3k
6. create a integration branch for the new stdlib
(just hg branch stdlib-$version)
-7. merge vendor/stdlib
+7. merge vendor/stdlib or vendor/stdlib-3-*
8. commit
10. fix issues
11. commit --close-branch
-12. merge to default
+12. merge to default / py3k
diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -204,15 +204,6 @@
BoolOption("withstrbuf", "use strings optimized for addition (ver 2)",
default=False),
- BoolOption("withprebuiltchar",
- "use prebuilt single-character string objects",
- default=False),
-
- BoolOption("sharesmallstr",
- "always reuse the prebuilt string objects "
- "(the empty string and potentially single-char strings)",
- default=False),
-
BoolOption("withspecialisedtuple",
"use specialised tuples",
default=False),
@@ -222,39 +213,14 @@
default=False,
requires=[("objspace.honor__builtins__", False)]),
- BoolOption("withmapdict",
- "make instances really small but slow without the JIT",
- default=False,
- requires=[("objspace.std.getattributeshortcut", True),
- ("objspace.std.withtypeversion", True),
- ]),
-
- BoolOption("withrangelist",
- "enable special range list implementation that does not "
- "actually create the full list until the resulting "
- "list is mutated",
- default=False),
BoolOption("withliststrategies",
"enable optimized ways to store lists of primitives ",
default=True),
- BoolOption("withtypeversion",
- "version type objects when changing them",
- cmdline=None,
- default=False,
- # weakrefs needed, because of get_subclasses()
- requires=[("translation.rweakref", True)]),
-
- BoolOption("withmethodcache",
- "try to cache method lookups",
- default=False,
- requires=[("objspace.std.withtypeversion", True),
- ("translation.rweakref", True)]),
BoolOption("withmethodcachecounter",
"try to cache methods and provide a counter in __pypy__. "
"for testing purposes only.",
- default=False,
- requires=[("objspace.std.withmethodcache", True)]),
+ default=False),
IntOption("methodcachesizeexp",
" 2 ** methodcachesizeexp is the size of the of the method cache ",
default=11),
@@ -265,22 +231,10 @@
BoolOption("optimized_list_getitem",
"special case the 'list[integer]' expressions",
default=False),
- BoolOption("getattributeshortcut",
- "track types that override __getattribute__",
- default=False,
- # weakrefs needed, because of get_subclasses()
- requires=[("translation.rweakref", True)]),
BoolOption("newshortcut",
"cache and shortcut calling __new__ from builtin types",
- default=False,
- # weakrefs needed, because of get_subclasses()
- requires=[("translation.rweakref", True)]),
+ default=False),
- BoolOption("withidentitydict",
- "track types that override __hash__, __eq__ or __cmp__ and use a special dict strategy for those which do not",
- default=False,
- # weakrefs needed, because of get_subclasses()
- requires=[("translation.rweakref", True)]),
]),
])
@@ -296,15 +250,10 @@
"""
# all the good optimizations for PyPy should be listed here
if level in ['2', '3', 'jit']:
- config.objspace.std.suggest(withrangelist=True)
- config.objspace.std.suggest(withmethodcache=True)
- config.objspace.std.suggest(withprebuiltchar=True)
config.objspace.std.suggest(intshortcut=True)
config.objspace.std.suggest(optimized_list_getitem=True)
- config.objspace.std.suggest(getattributeshortcut=True)
#config.objspace.std.suggest(newshortcut=True)
config.objspace.std.suggest(withspecialisedtuple=True)
- config.objspace.std.suggest(withidentitydict=True)
#if not IS_64_BITS:
# config.objspace.std.suggest(withsmalllong=True)
@@ -317,16 +266,13 @@
# memory-saving optimizations
if level == 'mem':
config.objspace.std.suggest(withprebuiltint=True)
- config.objspace.std.suggest(withrangelist=True)
- config.objspace.std.suggest(withprebuiltchar=True)
- config.objspace.std.suggest(withmapdict=True)
+ config.objspace.std.suggest(withliststrategies=True)
if not IS_64_BITS:
config.objspace.std.suggest(withsmalllong=True)
# extra optimizations with the JIT
if level == 'jit':
config.objspace.std.suggest(withcelldict=True)
- config.objspace.std.suggest(withmapdict=True)
def enable_allworkingmodules(config):
diff --git a/pypy/config/test/test_pypyoption.py b/pypy/config/test/test_pypyoption.py
--- a/pypy/config/test/test_pypyoption.py
+++ b/pypy/config/test/test_pypyoption.py
@@ -11,12 +11,6 @@
assert conf.objspace.usemodules.gc
- conf.objspace.std.withmapdict = True
- assert conf.objspace.std.withtypeversion
- conf = get_pypy_config()
- conf.objspace.std.withtypeversion = False
- py.test.raises(ConfigError, "conf.objspace.std.withmapdict = True")
-
def test_conflicting_gcrootfinder():
conf = get_pypy_config()
conf.translation.gc = "boehm"
@@ -47,18 +41,10 @@
def test_set_pypy_opt_level():
conf = get_pypy_config()
set_pypy_opt_level(conf, '2')
- assert conf.objspace.std.getattributeshortcut
+ assert conf.objspace.std.intshortcut
conf = get_pypy_config()
set_pypy_opt_level(conf, '0')
- assert not conf.objspace.std.getattributeshortcut
-
-def test_rweakref_required():
- conf = get_pypy_config()
- conf.translation.rweakref = False
- set_pypy_opt_level(conf, '3')
-
- assert not conf.objspace.std.withtypeversion
- assert not conf.objspace.std.withmethodcache
+ assert not conf.objspace.std.intshortcut
def test_check_documentation():
def check_file_exists(fn):
diff --git a/pypy/doc/build.rst b/pypy/doc/build.rst
--- a/pypy/doc/build.rst
+++ b/pypy/doc/build.rst
@@ -108,9 +108,9 @@
On Fedora::
- yum install gcc make libffi-devel pkgconfig zlib-devel bzip2-devel \
- lib-sqlite3-devel ncurses-devel expat-devel openssl-devel
- (XXX plus the Febora version of libgdbm-dev and tk-dev)
+ dnf install gcc make libffi-devel pkgconfig zlib-devel bzip2-devel \
+ lib-sqlite3-devel ncurses-devel expat-devel openssl-devel tk-devel \
+ gdbm-devel
For the optional lzma module on PyPy3 you will also need ``xz-devel``.
diff --git a/pypy/doc/config/objspace.std.getattributeshortcut.txt b/pypy/doc/config/objspace.std.getattributeshortcut.txt
deleted file mode 100644
--- a/pypy/doc/config/objspace.std.getattributeshortcut.txt
+++ /dev/null
@@ -1,1 +0,0 @@
-Performance only: track types that override __getattribute__.
diff --git a/pypy/doc/config/objspace.std.methodcachesizeexp.txt b/pypy/doc/config/objspace.std.methodcachesizeexp.txt
--- a/pypy/doc/config/objspace.std.methodcachesizeexp.txt
+++ b/pypy/doc/config/objspace.std.methodcachesizeexp.txt
@@ -1,1 +1,1 @@
-Set the cache size (number of entries) for :config:`objspace.std.withmethodcache`.
+Set the cache size (number of entries) for the method cache.
diff --git a/pypy/doc/config/objspace.std.withidentitydict.txt b/pypy/doc/config/objspace.std.withidentitydict.txt
deleted file mode 100644
--- a/pypy/doc/config/objspace.std.withidentitydict.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-=============================
-objspace.std.withidentitydict
-=============================
-
-* **name:** withidentitydict
-
-* **description:** enable a dictionary strategy for "by identity" comparisons
-
-* **command-line:** --objspace-std-withidentitydict
-
-* **command-line for negation:** --no-objspace-std-withidentitydict
-
-* **option type:** boolean option
-
-* **default:** True
-
-
-Enable a dictionary strategy specialized for instances of classes which
-compares "by identity", which is the default unless you override ``__hash__``,
-``__eq__`` or ``__cmp__``. This strategy will be used only with new-style
-classes.
diff --git a/pypy/doc/config/objspace.std.withmapdict.txt b/pypy/doc/config/objspace.std.withmapdict.txt
deleted file mode 100644
--- a/pypy/doc/config/objspace.std.withmapdict.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Enable the new version of "sharing dictionaries".
-
-See the section in `Standard Interpreter Optimizations`_ for more details.
-
-.. _`Standard Interpreter Optimizations`: ../interpreter-optimizations.html#sharing-dicts
diff --git a/pypy/doc/config/objspace.std.withmethodcache.txt b/pypy/doc/config/objspace.std.withmethodcache.txt
deleted file mode 100644
--- a/pypy/doc/config/objspace.std.withmethodcache.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Enable method caching. See the section "Method Caching" in `Standard
-Interpreter Optimizations <../interpreter-optimizations.html#method-caching>`__.
diff --git a/pypy/doc/config/objspace.std.withmethodcachecounter.txt b/pypy/doc/config/objspace.std.withmethodcachecounter.txt
--- a/pypy/doc/config/objspace.std.withmethodcachecounter.txt
+++ b/pypy/doc/config/objspace.std.withmethodcachecounter.txt
@@ -1,1 +1,1 @@
-Testing/debug option for :config:`objspace.std.withmethodcache`.
+Testing/debug option for the method cache.
diff --git a/pypy/doc/config/objspace.std.withprebuiltchar.txt b/pypy/doc/config/objspace.std.withprebuiltchar.txt
deleted file mode 100644
diff --git a/pypy/doc/config/objspace.std.withrangelist.txt b/pypy/doc/config/objspace.std.withrangelist.txt
deleted file mode 100644
--- a/pypy/doc/config/objspace.std.withrangelist.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-Enable "range list" objects. They are an additional implementation of the Python
-``list`` type, indistinguishable for the normal user. Whenever the ``range``
-builtin is called, an range list is returned. As long as this list is not
-mutated (and for example only iterated over), it uses only enough memory to
-store the start, stop and step of the range. This makes using ``range`` as
-efficient as ``xrange``, as long as the result is only used in a ``for``-loop.
-
-See the section in `Standard Interpreter Optimizations`_ for more details.
-
-.. _`Standard Interpreter Optimizations`: ../interpreter-optimizations.html#range-lists
-
diff --git a/pypy/doc/config/objspace.std.withtypeversion.txt b/pypy/doc/config/objspace.std.withtypeversion.txt
deleted file mode 100644
--- a/pypy/doc/config/objspace.std.withtypeversion.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-This (mostly internal) option enables "type versions": Every type object gets an
-(only internally visible) version that is updated when the type's dict is
-changed. This is e.g. used for invalidating caches. It does not make sense to
-enable this option alone.
-
-.. internal
diff --git a/pypy/doc/interpreter-optimizations.rst b/pypy/doc/interpreter-optimizations.rst
--- a/pypy/doc/interpreter-optimizations.rst
+++ b/pypy/doc/interpreter-optimizations.rst
@@ -62,29 +62,37 @@
Dictionary Optimizations
~~~~~~~~~~~~~~~~~~~~~~~~
-Multi-Dicts
-+++++++++++
+Dict Strategies
+++++++++++++++++
-Multi-dicts are a special implementation of dictionaries. It became clear that
-it is very useful to *change* the internal representation of an object during
-its lifetime. Multi-dicts are a general way to do that for dictionaries: they
-provide generic support for the switching of internal representations for
-dicts.
+Dict strategies are an implementation approach for dictionaries (and lists)
+that make it possible to use a specialized representation of the dictionary's
+data, while still being able to switch back to a general representation should
+that become necessary later.
-If you just enable multi-dicts, special representations for empty dictionaries,
-for string-keyed dictionaries. In addition there are more specialized dictionary
-implementations for various purposes (see below).
+Dict strategies are always enabled, by default there are special strategies for
+dicts with just string keys, just unicode keys and just integer keys. If one of
+those specialized strategies is used, then dict lookup can use much faster
+hashing and comparison for the dict keys. There is of course also a strategy
+for general keys.
-This is now the default implementation of dictionaries in the Python interpreter.
+Identity Dicts
++++++++++++++++
-Sharing Dicts
+We also have a strategy specialized for keys that are instances of classes
+which compares "by identity", which is the default unless you override
+``__hash__``, ``__eq__`` or ``__cmp__``. This strategy will be used only with
+new-style classes.
+
+
+Map Dicts
+++++++++++++
-Sharing dictionaries are a special representation used together with multidicts.
-This dict representation is used only for instance dictionaries and tries to
-make instance dictionaries use less memory (in fact, in the ideal case the
-memory behaviour should be mostly like that of using __slots__).
+Map dictionaries are a special representation used together with dict strategies.
+This dict strategy is used only for instance dictionaries and tries to
+make instance dictionaries use less memory (in fact, usually memory behaviour
+should be mostly like that of using ``__slots__``).
The idea is the following: Most instances of the same class have very similar
attributes, and are even adding these keys to the dictionary in the same order
@@ -95,8 +103,6 @@
dicts:
the representation of the instance dict contains only a list of values.
-A more advanced version of sharing dicts, called *map dicts,* is available
-with the :config:`objspace.std.withmapdict` option.
List Optimizations
@@ -114,8 +120,8 @@
created. This gives the memory and speed behaviour of ``xrange`` and the generality
of use of ``range``, and makes ``xrange`` essentially useless.
-You can enable this feature with the :config:`objspace.std.withrangelist`
-option.
+This feature is enabled by default as part of the
+:config:`objspace.std.withliststrategies` option.
User Class Optimizations
@@ -133,8 +139,7 @@
base classes is changed). On subsequent lookups the cached version can be used,
as long as the instance did not shadow any of its classes attributes.
-You can enable this feature with the :config:`objspace.std.withmethodcache`
-option.
+This feature is enabled by default.
Interpreter Optimizations
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -10,3 +10,9 @@
.. branch: gcheader-decl
Reduce the size of generated C sources.
+
+
+.. branch: remove-objspace-options
+
+Remove a number of options from the build process that were never tested and
+never set. Fix a performance bug in the method cache.
diff --git a/pypy/interpreter/executioncontext.py b/pypy/interpreter/executioncontext.py
--- a/pypy/interpreter/executioncontext.py
+++ b/pypy/interpreter/executioncontext.py
@@ -214,6 +214,7 @@
self._trace(frame, 'exception', None, operationerr)
#operationerr.print_detailed_traceback(self.space)
+ @jit.dont_look_inside
@specialize.arg(1)
def sys_exc_info(self, for_hidden=False):
"""Implements sys.exc_info().
@@ -225,15 +226,7 @@
# NOTE: the result is not the wrapped sys.exc_info() !!!
"""
- frame = self.gettopframe()
- while frame:
- if frame.last_exception is not None:
- if ((for_hidden or not frame.hide()) or
- frame.last_exception is
- get_cleared_operation_error(self.space)):
- return frame.last_exception
- frame = frame.f_backref()
- return None
+ return self.gettopframe()._exc_info_unroll(self.space, for_hidden)
def set_sys_exc_info(self, operror):
frame = self.gettopframe_nohidden()
diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py
--- a/pypy/interpreter/pycode.py
+++ b/pypy/interpreter/pycode.py
@@ -114,6 +114,7 @@
e.write_unraisable(self.space, "new_code_hook()")
def _initialize(self):
+ from pypy.objspace.std.mapdict import init_mapdict_cache
if self.co_cellvars:
argcount = self.co_argcount
assert argcount >= 0 # annotator hint
@@ -149,9 +150,7 @@
self._compute_flatcall()
- if self.space.config.objspace.std.withmapdict:
- from pypy.objspace.std.mapdict import init_mapdict_cache
- init_mapdict_cache(self)
+ init_mapdict_cache(self)
def _init_ready(self):
"This is a hook for the vmprof module, which overrides this method."
diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -4,7 +4,7 @@
from rpython.rlib import jit
from rpython.rlib.debug import make_sure_not_resized, check_nonneg
from rpython.rlib.jit import hint
-from rpython.rlib.objectmodel import we_are_translated, instantiate
+from rpython.rlib.objectmodel import instantiate, specialize, we_are_translated
from rpython.rlib.rarithmetic import intmask, r_uint
from rpython.tool.pairtype import extendabletype
@@ -12,7 +12,8 @@
from pypy.interpreter.argument import Arguments
from pypy.interpreter.astcompiler import consts
from pypy.interpreter.baseobjspace import W_Root
-from pypy.interpreter.error import OperationError, oefmt
+from pypy.interpreter.error import (
+ OperationError, get_cleared_operation_error, oefmt)
from pypy.interpreter.executioncontext import ExecutionContext
from pypy.interpreter.nestedscope import Cell
from pypy.tool import stdlib_opcode
@@ -870,6 +871,22 @@
return space.wrap(self.builtin is not space.builtin)
return space.w_False
+ @jit.unroll_safe
+ @specialize.arg(2)
+ def _exc_info_unroll(self, space, for_hidden=False):
+ """Return the most recent OperationError being handled in the
+ call stack
+ """
+ frame = self
+ while frame:
+ last = frame.last_exception
+ if last is not None:
+ if last is get_cleared_operation_error(self.space):
+ break
+ if for_hidden or not frame.hide():
+ return last
+ frame = frame.f_backref()
+ return None
# ____________________________________________________________
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -739,25 +739,16 @@
unroller = SContinueLoop(startofloop)
return self.unrollstack_and_jump(unroller)
- @jit.unroll_safe
def RAISE_VARARGS(self, nbargs, next_instr):
space = self.space
if nbargs == 0:
- frame = self
- while frame:
- if frame.last_exception is not None:
- operror = frame.last_exception
- break
- frame = frame.f_backref()
- else:
- raise OperationError(space.w_TypeError,
- space.wrap("raise: no active exception to re-raise"))
- if operror.w_type is space.w_None:
- raise OperationError(space.w_TypeError,
- space.wrap("raise: the exception to re-raise was cleared"))
+ last_operr = self._exc_info_unroll(space)
+ if last_operr is None:
+ raise oefmt(space.w_TypeError,
+ "No active exception to reraise")
# re-raise, no new traceback obj will be attached
- self.last_exception = operror
- raise RaiseWithExplicitTraceback(operror)
+ self.last_exception = last_operr
+ raise RaiseWithExplicitTraceback(last_operr)
w_value = w_traceback = space.w_None
if nbargs >= 3:
@@ -951,8 +942,7 @@
def LOAD_ATTR(self, nameindex, next_instr):
"obj.attributename"
w_obj = self.popvalue()
- if (self.space.config.objspace.std.withmapdict
- and not jit.we_are_jitted()):
+ if not jit.we_are_jitted():
from pypy.objspace.std.mapdict import LOAD_ATTR_caching
w_value = LOAD_ATTR_caching(self.getcode(), w_obj, nameindex)
else:
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -98,175 +98,51 @@
# reason is that it is missing a place to store the __dict__, the slots,
# the weakref lifeline, and it typically has no interp-level __del__.
# So we create a few interp-level subclasses of W_XxxObject, which add
-# some combination of features.
-#
-# We don't build 2**4 == 16 subclasses for all combinations of requested
-# features, but limit ourselves to 6, chosen a bit arbitrarily based on
-# typical usage (case 1 is the most common kind of app-level subclasses;
-# case 2 is the memory-saving kind defined with __slots__).
-#
-# +----------------------------------------------------------------+
-# | NOTE: if withmapdict is enabled, the following doesn't apply! |
-# | Map dicts can flexibly allow any slots/__dict__/__weakref__ to |
-# | show up only when needed. In particular there is no way with |
-# | mapdict to prevent some objects from being weakrefable. |
-# +----------------------------------------------------------------+
-#
-# dict slots del weakrefable
-#
-# 1. Y N N Y UserDictWeakref
-# 2. N Y N N UserSlots
-# 3. Y Y N Y UserDictWeakrefSlots
-# 4. N Y N Y UserSlotsWeakref
-# 5. Y Y Y Y UserDictWeakrefSlotsDel
-# 6. N Y Y Y UserSlotsWeakrefDel
-#
-# Note that if the app-level explicitly requests no dict, we should not
-# provide one, otherwise storing random attributes on the app-level
-# instance would unexpectedly work. We don't care too much, though, if
-# an object is weakrefable when it shouldn't really be. It's important
-# that it has a __del__ only if absolutely needed, as this kills the
-# performance of the GCs.
-#
-# Interp-level inheritance is like this:
-#
-# W_XxxObject base
-# / \
-# 1 2
-# / \
-# 3 4
-# / \
-# 5 6
+# some combination of features. This is done using mapdict.
-def get_unique_interplevel_subclass(config, cls, hasdict, wants_slots,
- needsdel=False, weakrefable=False):
+# we need two subclasses of the app-level type, one to add mapdict, and then one
+# to add del to not slow down the GC.
+
+def get_unique_interplevel_subclass(config, cls, needsdel=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 = config, cls, hasdict, wants_slots, needsdel, weakrefable
+ key = config, cls, needsdel
try:
return _subclass_cache[key]
except KeyError:
- subcls = _getusercls(config, cls, hasdict, wants_slots, needsdel,
- weakrefable)
+ # XXX can save a class if cls already has a __del__
+ if needsdel:
+ cls = get_unique_interplevel_subclass(config, cls, False)
+ subcls = _getusercls(config, cls, needsdel)
assert key not in _subclass_cache
_subclass_cache[key] = subcls
return subcls
get_unique_interplevel_subclass._annspecialcase_ = "specialize:memo"
_subclass_cache = {}
-def _getusercls(config, cls, wants_dict, wants_slots, wants_del, weakrefable):
+def _getusercls(config, cls, wants_del, reallywantdict=False):
+ from rpython.rlib import objectmodel
+ from pypy.objspace.std.mapdict import (BaseUserClassMapdict,
+ MapdictDictSupport, MapdictWeakrefSupport,
+ _make_storage_mixin_size_n)
typedef = cls.typedef
- if wants_dict and typedef.hasdict:
- wants_dict = False
- if config.objspace.std.withmapdict and not typedef.hasdict:
- # mapdict only works if the type does not already have a dict
- if wants_del:
- parentcls = get_unique_interplevel_subclass(config, cls, True, True,
- False, True)
- return _usersubclswithfeature(config, parentcls, "del")
- return _usersubclswithfeature(config, cls, "user", "dict", "weakref", "slots")
- # Forest of if's - see the comment above.
+ name = cls.__name__ + "User"
+
+ mixins_needed = [BaseUserClassMapdict, _make_storage_mixin_size_n()]
+ if reallywantdict or not typedef.hasdict:
+ # the type has no dict, mapdict to provide the dict
+ mixins_needed.append(MapdictDictSupport)
+ name += "Dict"
+ if not typedef.weakrefable:
+ # the type does not support weakrefs yet, mapdict to provide weakref
+ # support
+ mixins_needed.append(MapdictWeakrefSupport)
+ name += "Weakrefable"
if wants_del:
- if wants_dict:
- # case 5. Parent class is 3.
- parentcls = get_unique_interplevel_subclass(config, cls, True, True,
- False, True)
- else:
- # case 6. Parent class is 4.
- parentcls = get_unique_interplevel_subclass(config, cls, False, True,
- False, True)
- return _usersubclswithfeature(config, parentcls, "del")
- elif wants_dict:
- if wants_slots:
- # case 3. Parent class is 1.
- parentcls = get_unique_interplevel_subclass(config, cls, True, False,
- False, True)
- 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(config, cls, "user", "dict", "weakref")
- else:
- return _usersubclswithfeature(config, cls, "user", "dict")
- else:
- if weakrefable and not typedef.weakrefable:
- # case 4. Parent class is 2.
- parentcls = get_unique_interplevel_subclass(config, cls, False, True,
- False, False)
- return _usersubclswithfeature(config, parentcls, "weakref")
- else:
- # case 2 (if the base is already weakrefable, case 2 == case 4)
- return _usersubclswithfeature(config, cls, "user", "slots")
-
-def _usersubclswithfeature(config, parentcls, *features):
- key = config, parentcls, features
- try:
- return _usersubclswithfeature_cache[key]
- except KeyError:
- subcls = _builduserclswithfeature(config, parentcls, *features)
- _usersubclswithfeature_cache[key] = subcls
- return subcls
-_usersubclswithfeature_cache = {}
-_allusersubcls_cache = {}
-
-def _builduserclswithfeature(config, supercls, *features):
- "NOT_RPYTHON: initialization-time only"
- name = supercls.__name__
- name += ''.join([name.capitalize() for name in features])
- body = {}
- #print '..........', name, '(', supercls.__name__, ')'
-
- def add(Proto):
- for key, value in Proto.__dict__.items():
- if (not key.startswith('__') and not key.startswith('_mixin_')
- or key == '__del__'):
- if hasattr(value, "func_name"):
- value = func_with_new_name(value, value.func_name)
- body[key] = value
-
- if (config.objspace.std.withmapdict and "dict" in features):
- from pypy.objspace.std.mapdict import BaseMapdictObject, ObjectMixin
- add(BaseMapdictObject)
- add(ObjectMixin)
- body["user_overridden_class"] = True
- features = ()
-
- if "user" in features: # generic feature needed by all subcls
-
- class Proto(object):
- user_overridden_class = True
-
- def getclass(self, space):
- return promote(self.w__class__)
-
- def setclass(self, space, w_subtype):
- # only used by descr_set___class__
- self.w__class__ = w_subtype
-
- def user_setup(self, space, w_subtype):
- self.space = space
- self.w__class__ = w_subtype
- self.user_setup_slots(w_subtype.layout.nslots)
-
- def user_setup_slots(self, nslots):
- assert nslots == 0
- add(Proto)
-
- if "weakref" in features:
- class Proto(object):
- _lifeline_ = None
- def getweakref(self):
- return self._lifeline_
- def setweakref(self, space, weakreflifeline):
- self._lifeline_ = weakreflifeline
- def delweakref(self):
- self._lifeline_ = None
- add(Proto)
-
- if "del" in features:
- parent_destructor = getattr(supercls, '__del__', None)
+ name += "Del"
+ parent_destructor = getattr(cls, '__del__', None)
def call_parent_del(self):
assert isinstance(self, subcls)
parent_destructor(self)
@@ -281,57 +157,16 @@
if parent_destructor is not None:
self.enqueue_for_destruction(self.space, call_parent_del,
'internal destructor of ')
- add(Proto)
+ mixins_needed.append(Proto)
- if "slots" in features:
- class Proto(object):
- slots_w = []
- def user_setup_slots(self, nslots):
- if nslots > 0:
- self.slots_w = [None] * nslots
- def setslotvalue(self, index, w_value):
- self.slots_w[index] = w_value
- def delslotvalue(self, index):
- if self.slots_w[index] is None:
- return False
- self.slots_w[index] = None
- return True
- def getslotvalue(self, index):
- return self.slots_w[index]
- add(Proto)
-
- if "dict" in features:
- base_user_setup = supercls.user_setup.im_func
- if "user_setup" in body:
- base_user_setup = body["user_setup"]
- class Proto(object):
- def getdict(self, space):
- return self.w__dict__
-
- def setdict(self, space, w_dict):
- self.w__dict__ = check_new_dictionary(space, w_dict)
-
- def user_setup(self, space, w_subtype):
- self.w__dict__ = space.newdict(
- instance=True)
- base_user_setup(self, space, w_subtype)
-
- add(Proto)
-
- subcls = type(name, (supercls,), body)
- _allusersubcls_cache[subcls] = True
+ class subcls(cls):
+ user_overridden_class = True
+ for base in mixins_needed:
+ objectmodel.import_from_mixin(base)
+ del subcls.base
+ subcls.__name__ = name
return subcls
-# a couple of helpers for the Proto classes above, factored out to reduce
-# the translated code size
-def check_new_dictionary(space, w_dict):
- if not space.isinstance_w(w_dict, space.w_dict):
- raise OperationError(space.w_TypeError,
- space.wrap("setting dictionary to a non-dict"))
- from pypy.objspace.std import dictmultiobject
- assert isinstance(w_dict, dictmultiobject.W_DictMultiObject)
- return w_dict
-check_new_dictionary._dont_inline_ = True
# ____________________________________________________________
diff --git a/pypy/module/__builtin__/functional.py b/pypy/module/__builtin__/functional.py
--- a/pypy/module/__builtin__/functional.py
+++ b/pypy/module/__builtin__/functional.py
@@ -87,7 +87,7 @@
howmany = get_len_of_range(space, start, stop, step)
- if space.config.objspace.std.withrangelist:
+ if space.config.objspace.std.withliststrategies:
return range_withspecialized_implementation(space, start,
step, howmany)
res_w = [None] * howmany
@@ -99,7 +99,7 @@
def range_withspecialized_implementation(space, start, step, length):
- assert space.config.objspace.std.withrangelist
+ assert space.config.objspace.std.withliststrategies
from pypy.objspace.std.listobject import make_range_list
return make_range_list(space, start, step, length)
diff --git a/pypy/module/__builtin__/interp_classobj.py b/pypy/module/__builtin__/interp_classobj.py
--- a/pypy/module/__builtin__/interp_classobj.py
+++ b/pypy/module/__builtin__/interp_classobj.py
@@ -185,12 +185,19 @@
class Cache:
def __init__(self, space):
- from pypy.interpreter.typedef import _usersubclswithfeature
- # evil
- self.cls_without_del = _usersubclswithfeature(
- space.config, W_InstanceObject, "dict", "weakref")
- self.cls_with_del = _usersubclswithfeature(
- space.config, self.cls_without_del, "del")
+ from pypy.interpreter.typedef import _getusercls
+
+ if hasattr(space, 'is_fake_objspace'):
+ # hack: with the fake objspace, we don't want to see typedef's
+ # _getusercls() at all
+ self.cls_without_del = W_InstanceObject
+ self.cls_with_del = W_InstanceObject
+ return
+
+ self.cls_without_del = _getusercls(
+ space.config, W_InstanceObject, False, reallywantdict=True)
+ self.cls_with_del = _getusercls(
+ space.config, W_InstanceObject, True, reallywantdict=True)
def class_descr_call(space, w_self, __args__):
diff --git a/pypy/module/__builtin__/test/test_builtin.py b/pypy/module/__builtin__/test/test_builtin.py
--- a/pypy/module/__builtin__/test/test_builtin.py
+++ b/pypy/module/__builtin__/test/test_builtin.py
@@ -748,10 +748,6 @@
raises(TypeError, delattr, A(), 42)
-class AppTestGetattrWithGetAttributeShortcut(AppTestGetattr):
- spaceconfig = {"objspace.std.getattributeshortcut": True}
-
-
class TestInternal:
def test_execfile(self, space):
fn = str(udir.join('test_execfile'))
diff --git a/pypy/module/__builtin__/test/test_classobj.py b/pypy/module/__builtin__/test/test_classobj.py
--- a/pypy/module/__builtin__/test/test_classobj.py
+++ b/pypy/module/__builtin__/test/test_classobj.py
@@ -1118,8 +1118,7 @@
assert getattr(c, u"x") == 1
-class AppTestOldStyleMapDict(AppTestOldstyle):
- spaceconfig = {"objspace.std.withmapdict": True}
+class AppTestOldStyleMapDict:
def setup_class(cls):
if cls.runappdirect:
diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py
--- a/pypy/module/__pypy__/__init__.py
+++ b/pypy/module/__pypy__/__init__.py
@@ -110,9 +110,8 @@
'interp_magic.method_cache_counter')
self.extra_interpdef('reset_method_cache_counter',
'interp_magic.reset_method_cache_counter')
- if self.space.config.objspace.std.withmapdict:
- self.extra_interpdef('mapdict_cache_counter',
- 'interp_magic.mapdict_cache_counter')
+ self.extra_interpdef('mapdict_cache_counter',
+ 'interp_magic.mapdict_cache_counter')
PYC_MAGIC = get_pyc_magic(self.space)
self.extra_interpdef('PYC_MAGIC', 'space.wrap(%d)' % PYC_MAGIC)
try:
diff --git a/pypy/module/__pypy__/interp_magic.py b/pypy/module/__pypy__/interp_magic.py
--- a/pypy/module/__pypy__/interp_magic.py
+++ b/pypy/module/__pypy__/interp_magic.py
@@ -37,17 +37,15 @@
cache = space.fromcache(MethodCache)
cache.misses = {}
cache.hits = {}
- if space.config.objspace.std.withmapdict:
- cache = space.fromcache(MapAttrCache)
- cache.misses = {}
- cache.hits = {}
+ cache = space.fromcache(MapAttrCache)
+ cache.misses = {}
+ cache.hits = {}
@unwrap_spec(name=str)
def mapdict_cache_counter(space, name):
"""Return a tuple (index_cache_hits, index_cache_misses) for lookups
in the mapdict cache with the given attribute name."""
assert space.config.objspace.std.withmethodcachecounter
- assert space.config.objspace.std.withmapdict
cache = space.fromcache(MapAttrCache)
return space.newtuple([space.newint(cache.hits.get(name, 0)),
space.newint(cache.misses.get(name, 0))])
diff --git a/pypy/module/__pypy__/test/test_special.py b/pypy/module/__pypy__/test/test_special.py
--- a/pypy/module/__pypy__/test/test_special.py
+++ b/pypy/module/__pypy__/test/test_special.py
@@ -1,8 +1,7 @@
import py
class AppTest(object):
- spaceconfig = {"objspace.usemodules.select": False,
- "objspace.std.withrangelist": True}
+ spaceconfig = {"objspace.usemodules.select": False}
def setup_class(cls):
if cls.runappdirect:
diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py
--- a/pypy/module/cpyext/object.py
+++ b/pypy/module/cpyext/object.py
@@ -54,6 +54,9 @@
@cpython_api([PyObject], lltype.Void)
def PyObject_dealloc(space, obj):
+ # This frees an object after its refcount dropped to zero, so we
+ # assert that it is really zero here.
+ assert obj.c_ob_refcnt == 0
pto = obj.c_ob_type
obj_voidp = rffi.cast(rffi.VOIDP, obj)
generic_cpy_call(space, pto.c_tp_free, obj_voidp)
diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py
--- a/pypy/module/cpyext/test/test_cpyext.py
+++ b/pypy/module/cpyext/test/test_cpyext.py
@@ -140,7 +140,6 @@
'itertools', 'time', 'binascii',
'micronumpy',
])
- spaceconfig['std.withmethodcache'] = True
enable_leak_checking = True
diff --git a/pypy/module/cpyext/unicodeobject.py b/pypy/module/cpyext/unicodeobject.py
--- a/pypy/module/cpyext/unicodeobject.py
+++ b/pypy/module/cpyext/unicodeobject.py
@@ -85,11 +85,10 @@
@cpython_api([PyObject], lltype.Void, header=None)
def unicode_dealloc(space, py_obj):
py_unicode = rffi.cast(PyUnicodeObject, py_obj)
+ Py_DecRef(space, py_unicode.c_defenc)
if py_unicode.c_str:
lltype.free(py_unicode.c_str, flavor="raw")
from pypy.module.cpyext.object import PyObject_dealloc
- if py_unicode.c_defenc:
- PyObject_dealloc(space, py_unicode.c_defenc)
PyObject_dealloc(space, py_obj)
@cpython_api([Py_UNICODE], rffi.INT_real, error=CANNOT_FAIL)
diff --git a/pypy/module/gc/interp_gc.py b/pypy/module/gc/interp_gc.py
--- a/pypy/module/gc/interp_gc.py
+++ b/pypy/module/gc/interp_gc.py
@@ -6,15 +6,14 @@
@unwrap_spec(generation=int)
def collect(space, generation=0):
"Run a full collection. The optional argument is ignored."
- # First clear the method cache. See test_gc for an example of why.
- if space.config.objspace.std.withmethodcache:
- from pypy.objspace.std.typeobject import MethodCache
- cache = space.fromcache(MethodCache)
- cache.clear()
- if space.config.objspace.std.withmapdict:
- from pypy.objspace.std.mapdict import MapAttrCache
- cache = space.fromcache(MapAttrCache)
- cache.clear()
+ # First clear the method and the map cache.
+ # See test_gc for an example of why.
+ from pypy.objspace.std.typeobject import MethodCache
+ from pypy.objspace.std.mapdict import MapAttrCache
+ cache = space.fromcache(MethodCache)
+ cache.clear()
+ cache = space.fromcache(MapAttrCache)
+ cache.clear()
rgc.collect()
return space.wrap(0)
diff --git a/pypy/module/gc/test/test_gc.py b/pypy/module/gc/test/test_gc.py
--- a/pypy/module/gc/test/test_gc.py
+++ b/pypy/module/gc/test/test_gc.py
@@ -106,7 +106,6 @@
class AppTestGcMethodCache(object):
- spaceconfig = {"objspace.std.withmethodcache": True}
def test_clear_method_cache(self):
import gc, weakref
@@ -127,10 +126,6 @@
assert r() is None
-class AppTestGcMapDictIndexCache(AppTestGcMethodCache):
- spaceconfig = {"objspace.std.withmethodcache": True,
- "objspace.std.withmapdict": True}
-
def test_clear_index_cache(self):
import gc, weakref
rlist = []
diff --git a/pypy/module/pypyjit/test_pypy_c/test_weakref.py b/pypy/module/pypyjit/test_pypy_c/test_weakref.py
--- a/pypy/module/pypyjit/test_pypy_c/test_weakref.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_weakref.py
@@ -25,9 +25,9 @@
i61 = int_add(i58, 1)
setfield_gc(p18, i61, descr=<FieldS pypy.module.__builtin__.functional.W_XRangeIterator.inst_current 8>)
guard_not_invalidated(descr=...)
- p65 = getfield_gc_r(p14, descr=<FieldP pypy.objspace.std.mapdict.W_ObjectObjectSize5.inst_map \d+>)
+ p65 = getfield_gc_r(p14, descr=<FieldP .+inst_map \d+>)
guard_value(p65, ConstPtr(ptr45), descr=...)
- p66 = getfield_gc_r(p14, descr=<FieldP pypy.objspace.std.mapdict.W_ObjectObjectSize5.inst__value0 \d+>)
+ p66 = getfield_gc_r(p14, descr=<FieldP .+inst__value0 \d+>)
guard_nonnull_class(p66, ..., descr=...)
p67 = force_token()
setfield_gc(p0, p67, descr=<FieldP pypy.interpreter.pyframe.PyFrame.vable_token \d+>)
diff --git a/pypy/objspace/fake/objspace.py b/pypy/objspace/fake/objspace.py
--- a/pypy/objspace/fake/objspace.py
+++ b/pypy/objspace/fake/objspace.py
@@ -121,6 +121,8 @@
'bytearray', 'buffer', 'set', 'frozenset']
class FakeObjSpace(ObjSpace):
+ is_fake_objspace = True
+
def __init__(self, config=None):
self._seen_extras = []
ObjSpace.__init__(self, config=config)
diff --git a/pypy/objspace/std/bytesobject.py b/pypy/objspace/std/bytesobject.py
--- a/pypy/objspace/std/bytesobject.py
+++ b/pypy/objspace/std/bytesobject.py
@@ -841,34 +841,12 @@
return [s for s in value]
W_BytesObject.EMPTY = W_BytesObject('')
-W_BytesObject.PREBUILT = [W_BytesObject(chr(i)) for i in range(256)]
-del i
def wrapstr(space, s):
- if space.config.objspace.std.sharesmallstr:
- if space.config.objspace.std.withprebuiltchar:
- # share characters and empty string
- if len(s) <= 1:
- if len(s) == 0:
- return W_BytesObject.EMPTY
- else:
- s = s[0] # annotator hint: a single char
- return wrapchar(space, s)
- else:
- # only share the empty string
- if len(s) == 0:
- return W_BytesObject.EMPTY
return W_BytesObject(s)
-def wrapchar(space, c):
- if space.config.objspace.std.withprebuiltchar and not we_are_jitted():
- return W_BytesObject.PREBUILT[ord(c)]
- else:
- return W_BytesObject(c)
-
-
W_BytesObject.typedef = TypeDef(
"str", basestring_typedef,
__new__ = interp2app(W_BytesObject.descr_new),
diff --git a/pypy/objspace/std/callmethod.py b/pypy/objspace/std/callmethod.py
--- a/pypy/objspace/std/callmethod.py
+++ b/pypy/objspace/std/callmethod.py
@@ -23,6 +23,7 @@
def LOOKUP_METHOD(f, nameindex, *ignored):
+ from pypy.objspace.std.typeobject import MutableCell
# stack before after
# -------------- --fast-method----fallback-case------------
#
@@ -33,7 +34,7 @@
space = f.space
w_obj = f.popvalue()
- if space.config.objspace.std.withmapdict and not jit.we_are_jitted():
+ if not jit.we_are_jitted():
# mapdict has an extra-fast version of this function
if LOOKUP_METHOD_mapdict(f, nameindex, w_obj):
return
@@ -44,7 +45,18 @@
w_type = space.type(w_obj)
if w_type.has_object_getattribute():
name = space.str_w(w_name)
- w_descr = w_type.lookup(name)
+ # bit of a mess to use these internal functions, but it allows the
+ # mapdict caching below to work without an additional lookup
+ version_tag = w_type.version_tag()
+ if version_tag is None:
+ _, w_descr = w_type._lookup_where(name)
+ w_descr_cell = None
+ else:
+ _, w_descr_cell = w_type._pure_lookup_where_with_method_cache(
+ name, version_tag)
+ w_descr = w_descr_cell
+ if isinstance(w_descr, MutableCell):
+ w_descr = w_descr.unwrap_cell(space)
if w_descr is None:
# this handles directly the common case
# module.function(args..)
@@ -59,11 +71,11 @@
# nothing in the instance
f.pushvalue(w_descr)
f.pushvalue(w_obj)
- if (space.config.objspace.std.withmapdict and
- not jit.we_are_jitted()):
+ if not jit.we_are_jitted():
# let mapdict cache stuff
LOOKUP_METHOD_mapdict_fill_cache_method(
- space, f.getcode(), name, nameindex, w_obj, w_type)
+ space, f.getcode(), name, nameindex, w_obj, w_type,
+ w_descr_cell)
return
if w_value is None:
w_value = space.getattr(w_obj, w_name)
diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py
--- a/pypy/objspace/std/dictmultiobject.py
+++ b/pypy/objspace/std/dictmultiobject.py
@@ -66,10 +66,10 @@
w_obj = space.allocate_instance(W_ModuleDictObject, space.w_dict)
W_ModuleDictObject.__init__(w_obj, space, strategy, storage)
return w_obj
- elif space.config.objspace.std.withmapdict and instance:
+ elif instance:
from pypy.objspace.std.mapdict import MapDictStrategy
strategy = space.fromcache(MapDictStrategy)
- elif instance or strdict or module:
+ elif strdict or module:
assert w_type is None
strategy = space.fromcache(BytesDictStrategy)
elif kwargs:
@@ -592,7 +592,6 @@
return self.erase(None)
def switch_to_correct_strategy(self, w_dict, w_key):
- withidentitydict = self.space.config.objspace.std.withidentitydict
if type(w_key) is self.space.StringObjectCls:
self.switch_to_bytes_strategy(w_dict)
return
@@ -602,7 +601,7 @@
w_type = self.space.type(w_key)
if self.space.is_w(w_type, self.space.w_int):
self.switch_to_int_strategy(w_dict)
- elif withidentitydict and w_type.compares_by_identity():
+ elif w_type.compares_by_identity():
self.switch_to_identity_strategy(w_dict)
else:
self.switch_to_object_strategy(w_dict)
diff --git a/pypy/objspace/std/mapdict.py b/pypy/objspace/std/mapdict.py
--- a/pypy/objspace/std/mapdict.py
+++ b/pypy/objspace/std/mapdict.py
@@ -67,12 +67,7 @@
@jit.elidable
def find_map_attr(self, name, index):
- if (self.space.config.objspace.std.withmethodcache):
- return self._find_map_attr_cache(name, index)
- return self._find_map_attr(name, index)
-
- @jit.dont_look_inside
- def _find_map_attr_cache(self, name, index):
+ # attr cache
space = self.space
cache = space.fromcache(MapAttrCache)
SHIFT2 = r_uint.BITS - space.config.objspace.std.methodcachesizeexp
@@ -429,7 +424,6 @@
class MapAttrCache(object):
def __init__(self, space):
- assert space.config.objspace.std.withmethodcache
SIZE = 1 << space.config.objspace.std.methodcachesizeexp
self.attrs = [None] * SIZE
self.names = [None] * SIZE
@@ -456,12 +450,19 @@
INVALID = 2
SLOTS_STARTING_FROM = 3
+# a little bit of a mess of mixin classes that implement various pieces of
+# objspace user object functionality in terms of mapdict
-class BaseMapdictObject:
- _mixin_ = True
+class BaseUserClassMapdict:
+ # everything that's needed to use mapdict for a user subclass at all.
+ # This immediately makes slots possible.
- def _init_empty(self, map):
- raise NotImplementedError("abstract base class")
+ # assumes presence of _init_empty, _mapdict_read_storage,
+ # _mapdict_write_storage, _mapdict_storage_length,
+ # _set_mapdict_storage_and_map
+
+ # _____________________________________________
+ # methods needed for mapdict
def _become(self, new_obj):
self._set_mapdict_storage_and_map(new_obj.storage, new_obj.map)
@@ -470,49 +471,11 @@
return jit.promote(self.map)
def _set_mapdict_map(self, map):
self.map = map
+
# _____________________________________________
# objspace interface
- def getdictvalue(self, space, attrname):
- return self._get_mapdict_map().read(self, attrname, DICT)
-
- def setdictvalue(self, space, attrname, w_value):
- return self._get_mapdict_map().write(self, attrname, DICT, w_value)
-
- def deldictvalue(self, space, attrname):
- new_obj = self._get_mapdict_map().delete(self, attrname, DICT)
- if new_obj is None:
- return False
- self._become(new_obj)
- return True
-
- def getdict(self, space):
- w_dict = self._get_mapdict_map().read(self, "dict", SPECIAL)
- if w_dict is not None:
- assert isinstance(w_dict, W_DictMultiObject)
- return w_dict
-
- strategy = space.fromcache(MapDictStrategy)
- storage = strategy.erase(self)
- w_dict = W_DictObject(space, strategy, storage)
- flag = self._get_mapdict_map().write(self, "dict", SPECIAL, w_dict)
- assert flag
- return w_dict
-
- def setdict(self, space, w_dict):
- from pypy.interpreter.typedef import check_new_dictionary
- w_dict = check_new_dictionary(space, w_dict)
- w_olddict = self.getdict(space)
- assert isinstance(w_dict, W_DictMultiObject)
- # The old dict has got 'self' as dstorage, but we are about to
- # change self's ("dict", SPECIAL) attribute to point to the
- # new dict. If the old dict was using the MapDictStrategy, we
- # have to force it now: otherwise it would remain an empty
- # shell that continues to delegate to 'self'.
- if type(w_olddict.get_strategy()) is MapDictStrategy:
- w_olddict.get_strategy().switch_to_object_strategy(w_olddict)
- flag = self._get_mapdict_map().write(self, "dict", SPECIAL, w_dict)
- assert flag
+ # class access
def getclass(self, space):
return self._get_mapdict_map().terminator.w_cls
@@ -525,9 +488,13 @@
from pypy.module.__builtin__.interp_classobj import W_InstanceObject
self.space = space
assert (not self.typedef.hasdict or
+ isinstance(w_subtype.terminator, NoDictTerminator) or
self.typedef is W_InstanceObject.typedef)
self._init_empty(w_subtype.terminator)
+
+ # methods needed for slots
+
def getslotvalue(self, slotindex):
index = SLOTS_STARTING_FROM + slotindex
return self._get_mapdict_map().read(self, "slot", index)
@@ -544,7 +511,9 @@
self._become(new_obj)
return True
- # used by _weakref implemenation
+
+class MapdictWeakrefSupport(object):
+ # stuff used by the _weakref implementation
def getweakref(self):
from pypy.module._weakref.interp__weakref import WeakrefLifeline
@@ -565,8 +534,71 @@
self._get_mapdict_map().write(self, "weakref", SPECIAL, None)
delweakref._cannot_really_call_random_things_ = True
-class ObjectMixin(object):
- _mixin_ = True
+
+class MapdictDictSupport(object):
+
+ # objspace interface for dictionary operations
+
+ def getdictvalue(self, space, attrname):
+ return self._get_mapdict_map().read(self, attrname, DICT)
+
+ def setdictvalue(self, space, attrname, w_value):
+ return self._get_mapdict_map().write(self, attrname, DICT, w_value)
+
+ def deldictvalue(self, space, attrname):
+ new_obj = self._get_mapdict_map().delete(self, attrname, DICT)
+ if new_obj is None:
+ return False
+ self._become(new_obj)
+ return True
+
+ def getdict(self, space):
+ return _obj_getdict(self, space)
+
+ def setdict(self, space, w_dict):
+ _obj_setdict(self, space, w_dict)
+
+# a couple of helpers for the classes above, factored out to reduce
+# the translated code size
+
+ at objectmodel.dont_inline
+def _obj_getdict(self, space):
+ terminator = self._get_mapdict_map().terminator
+ assert isinstance(terminator, DictTerminator) or isinstance(terminator, DevolvedDictTerminator)
+ w_dict = self._get_mapdict_map().read(self, "dict", SPECIAL)
+ if w_dict is not None:
+ assert isinstance(w_dict, W_DictMultiObject)
+ return w_dict
+
+ strategy = space.fromcache(MapDictStrategy)
+ storage = strategy.erase(self)
+ w_dict = W_DictObject(space, strategy, storage)
+ flag = self._get_mapdict_map().write(self, "dict", SPECIAL, w_dict)
+ assert flag
+ return w_dict
+
+ at objectmodel.dont_inline
+def _obj_setdict(self, space, w_dict):
+ from pypy.interpreter.error import OperationError
+ terminator = self._get_mapdict_map().terminator
+ assert isinstance(terminator, DictTerminator) or isinstance(terminator, DevolvedDictTerminator)
+ if not space.isinstance_w(w_dict, space.w_dict):
+ raise OperationError(space.w_TypeError,
+ space.wrap("setting dictionary to a non-dict"))
+ assert isinstance(w_dict, W_DictMultiObject)
+ w_olddict = self.getdict(space)
+ assert isinstance(w_olddict, W_DictMultiObject)
+ # The old dict has got 'self' as dstorage, but we are about to
+ # change self's ("dict", SPECIAL) attribute to point to the
+ # new dict. If the old dict was using the MapDictStrategy, we
+ # have to force it now: otherwise it would remain an empty
+ # shell that continues to delegate to 'self'.
+ if type(w_olddict.get_strategy()) is MapDictStrategy:
+ w_olddict.get_strategy().switch_to_object_strategy(w_olddict)
+ flag = self._get_mapdict_map().write(self, "dict", SPECIAL, w_dict)
+ assert flag
+
+class MapdictStorageMixin(object):
def _init_empty(self, map):
from rpython.rlib.debug import make_sure_not_resized
self.map = map
@@ -585,51 +617,32 @@
self.storage = storage
self.map = map
-class Object(ObjectMixin, BaseMapdictObject, W_Root):
- pass # mainly for tests
+class ObjectWithoutDict(W_Root):
+ # mainly for tests
+ objectmodel.import_from_mixin(MapdictStorageMixin)
-def get_subclass_of_correct_size(space, cls, w_type):
- assert space.config.objspace.std.withmapdict
- map = w_type.terminator
- classes = memo_get_subclass_of_correct_size(space, cls)
- if SUBCLASSES_MIN_FIELDS == SUBCLASSES_MAX_FIELDS:
- return classes[0]
- size = map.size_estimate()
- debug.check_nonneg(size)
- if size < len(classes):
- return classes[size]
- else:
- return classes[len(classes)-1]
-get_subclass_of_correct_size._annspecialcase_ = "specialize:arg(1)"
+ objectmodel.import_from_mixin(BaseUserClassMapdict)
+ objectmodel.import_from_mixin(MapdictWeakrefSupport)
-SUBCLASSES_MIN_FIELDS = 5 # XXX tweak these numbers
-SUBCLASSES_MAX_FIELDS = 5
-def memo_get_subclass_of_correct_size(space, supercls):
- key = space, supercls
- try:
- return _subclass_cache[key]
- except KeyError:
- assert not hasattr(supercls, "__del__")
- result = []
- for i in range(SUBCLASSES_MIN_FIELDS, SUBCLASSES_MAX_FIELDS+1):
- result.append(_make_subclass_size_n(supercls, i))
- for i in range(SUBCLASSES_MIN_FIELDS):
- result.insert(0, result[0])
- if SUBCLASSES_MIN_FIELDS == SUBCLASSES_MAX_FIELDS:
- assert len(set(result)) == 1
- _subclass_cache[key] = result
- return result
-memo_get_subclass_of_correct_size._annspecialcase_ = "specialize:memo"
-_subclass_cache = {}
+class Object(W_Root):
+ # mainly for tests
+ objectmodel.import_from_mixin(MapdictStorageMixin)
-def _make_subclass_size_n(supercls, n):
+ objectmodel.import_from_mixin(BaseUserClassMapdict)
+ objectmodel.import_from_mixin(MapdictWeakrefSupport)
+ objectmodel.import_from_mixin(MapdictDictSupport)
+
+
+SUBCLASSES_NUM_FIELDS = 5
+
+def _make_storage_mixin_size_n(n=SUBCLASSES_NUM_FIELDS):
from rpython.rlib import unroll
rangen = unroll.unrolling_iterable(range(n))
nmin1 = n - 1
rangenmin1 = unroll.unrolling_iterable(range(nmin1))
valnmin1 = "_value%s" % nmin1
- class subcls(BaseMapdictObject, supercls):
+ class subcls(object):
def _init_empty(self, map):
for i in rangenmin1:
setattr(self, "_value%s" % i, None)
@@ -697,7 +710,7 @@
erased = erase_list(storage_list)
setattr(self, "_value%s" % nmin1, erased)
- subcls.__name__ = supercls.__name__ + "Size%s" % n
+ subcls.__name__ = "Size%s" % n
return subcls
# ____________________________________________________________
@@ -964,7 +977,7 @@
name = space.str_w(w_name)
# We need to care for obscure cases in which the w_descr is
# a MutableCell, which may change without changing the version_tag
- _, w_descr = w_type._pure_lookup_where_possibly_with_method_cache(
+ _, w_descr = w_type._pure_lookup_where_with_method_cache(
name, version_tag)
#
attrname, index = ("", INVALID)
@@ -1011,22 +1024,15 @@
return False
def LOOKUP_METHOD_mapdict_fill_cache_method(space, pycode, name, nameindex,
- w_obj, w_type):
+ w_obj, w_type, w_method):
+ if w_method is None or isinstance(w_method, MutableCell):
+ # don't cache the MutableCell XXX could be fixed
+ return
version_tag = w_type.version_tag()
- if version_tag is None:
- return
+ assert version_tag is not None
map = w_obj._get_mapdict_map()
if map is None or isinstance(map.terminator, DevolvedDictTerminator):
return
- # We know here that w_obj.getdictvalue(space, name) just returned None,
- # so the 'name' is not in the instance. We repeat the lookup to find it
- # in the class, this time taking care of the result: it can be either a
- # quasi-constant class attribute, or actually a MutableCell --- which we
- # must not cache. (It should not be None here, but you never know...)
- _, w_method = w_type._pure_lookup_where_possibly_with_method_cache(
- name, version_tag)
- if w_method is None or isinstance(w_method, MutableCell):
- return
_fill_cache(pycode, nameindex, map, version_tag, -1, w_method)
# XXX fix me: if a function contains a loop with both LOAD_ATTR and
diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py
--- a/pypy/objspace/std/objspace.py
+++ b/pypy/objspace/std/objspace.py
@@ -357,15 +357,8 @@
if cls.typedef.applevel_subclasses_base is not None:
cls = cls.typedef.applevel_subclasses_base
#
- if (self.config.objspace.std.withmapdict and cls is W_ObjectObject
- and not w_subtype.needsdel):
- from pypy.objspace.std.mapdict import get_subclass_of_correct_size
- subcls = get_subclass_of_correct_size(self, cls, w_subtype)
- else:
- subcls = get_unique_interplevel_subclass(
- self.config, cls, w_subtype.hasdict,
- w_subtype.layout.nslots != 0,
- w_subtype.needsdel, w_subtype.weakrefable)
+ subcls = get_unique_interplevel_subclass(
+ self.config, cls, w_subtype.needsdel)
instance = instantiate(subcls)
assert isinstance(instance, cls)
instance.user_setup(self, w_subtype)
@@ -518,7 +511,6 @@
return self.int_w(l_w[0]), self.int_w(l_w[1]), self.int_w(l_w[2])
_DescrOperation_is_true = is_true
- _DescrOperation_getattr = getattr
def is_true(self, w_obj):
# a shortcut for performance
@@ -527,8 +519,6 @@
return self._DescrOperation_is_true(w_obj)
def getattr(self, w_obj, w_name):
- if not self.config.objspace.std.getattributeshortcut:
- return self._DescrOperation_getattr(w_obj, w_name)
# an optional shortcut for performance
w_type = self.type(w_obj)
diff --git a/pypy/objspace/std/test/test_bytesobject.py b/pypy/objspace/std/test/test_bytesobject.py
--- a/pypy/objspace/std/test/test_bytesobject.py
+++ b/pypy/objspace/std/test/test_bytesobject.py
@@ -795,13 +795,3 @@
return 42
x = Foo()
assert "hello" + x == 42
-
-class AppTestPrebuilt(AppTestBytesObject):
- spaceconfig = {"objspace.std.withprebuiltchar": True}
-
-class AppTestShare(AppTestBytesObject):
- spaceconfig = {"objspace.std.sharesmallstr": True}
-
-class AppTestPrebuiltShare(AppTestBytesObject):
- spaceconfig = {"objspace.std.withprebuiltchar": True,
- "objspace.std.sharesmallstr": True}
diff --git a/pypy/objspace/std/test/test_callmethod.py b/pypy/objspace/std/test/test_callmethod.py
--- a/pypy/objspace/std/test/test_callmethod.py
+++ b/pypy/objspace/std/test/test_callmethod.py
@@ -97,21 +97,17 @@
else:
raise Exception("did not raise?")
"""
-
+
def test_kwargs(self):
exec """if 1:
class C(object):
def f(self, a):
return a + 2
-
+
assert C().f(a=3) == 5
"""
-class AppTestCallMethodWithGetattributeShortcut(AppTestCallMethod):
- spaceconfig = {"objspace.std.getattributeshortcut": True}
-
-
class TestCallMethod:
def test_space_call_method(self):
space = self.space
diff --git a/pypy/objspace/std/test/test_dictmultiobject.py b/pypy/objspace/std/test/test_dictmultiobject.py
--- a/pypy/objspace/std/test/test_dictmultiobject.py
+++ b/pypy/objspace/std/test/test_dictmultiobject.py
@@ -1113,11 +1113,9 @@
class Config:
class objspace:
class std:
- withsmalldicts = False
withcelldict = False
- withmethodcache = False
- withidentitydict = False
- withmapdict = False
+ methodcachesizeexp = 11
+ withmethodcachecounter = False
FakeSpace.config = Config()
diff --git a/pypy/objspace/std/test/test_identitydict.py b/pypy/objspace/std/test/test_identitydict.py
--- a/pypy/objspace/std/test/test_identitydict.py
+++ b/pypy/objspace/std/test/test_identitydict.py
@@ -1,62 +1,7 @@
import py
from pypy.interpreter.gateway import interp2app
-class AppTestComparesByIdentity:
- spaceconfig = {"objspace.std.withidentitydict": True}
-
- def setup_class(cls):
- from pypy.objspace.std import identitydict
- if cls.runappdirect:
- py.test.skip("interp2app doesn't work on appdirect")
-
- def compares_by_identity(space, w_cls):
- return space.wrap(w_cls.compares_by_identity())
- cls.w_compares_by_identity = cls.space.wrap(interp2app(compares_by_identity))
-
- def test_compares_by_identity(self):
- class Plain(object):
- pass
-
- class CustomEq(object):
- def __eq__(self, other):
- return True
-
- class CustomCmp (object):
- def __cmp__(self, other):
- return 0
-
- class CustomHash(object):
- def __hash__(self):
- return 0
-
- class TypeSubclass(type):
- pass
-
- class TypeSubclassCustomCmp(type):
- def __cmp__(self, other):
- return 0
-
- assert self.compares_by_identity(Plain)
- assert not self.compares_by_identity(CustomEq)
- assert not self.compares_by_identity(CustomCmp)
- assert not self.compares_by_identity(CustomHash)
- assert self.compares_by_identity(type)
- assert self.compares_by_identity(TypeSubclass)
- assert not self.compares_by_identity(TypeSubclassCustomCmp)
-
- def test_modify_class(self):
- class X(object):
- pass
-
- assert self.compares_by_identity(X)
- X.__eq__ = lambda x: None
- assert not self.compares_by_identity(X)
- del X.__eq__
- assert self.compares_by_identity(X)
-
-
class AppTestIdentityDict(object):
- spaceconfig = {"objspace.std.withidentitydict": True}
def setup_class(cls):
if cls.runappdirect:
diff --git a/pypy/objspace/std/test/test_identityset.py b/pypy/objspace/std/test/test_identityset.py
--- a/pypy/objspace/std/test/test_identityset.py
+++ b/pypy/objspace/std/test/test_identityset.py
@@ -3,9 +3,6 @@
class AppTestIdentitySet(object):
- # needed for compares_by_identity
- spaceconfig = {"objspace.std.withidentitydict": True}
-
def setup_class(cls):
from pypy.objspace.std import identitydict
if cls.runappdirect:
diff --git a/pypy/objspace/std/test/test_listobject.py b/pypy/objspace/std/test/test_listobject.py
--- a/pypy/objspace/std/test/test_listobject.py
+++ b/pypy/objspace/std/test/test_listobject.py
@@ -432,6 +432,8 @@
class AppTestListObject(object):
+ spaceconfig = {"objspace.std.withliststrategies": True} # it's the default
+
def setup_class(cls):
import platform
import sys
@@ -1590,20 +1592,13 @@
assert L3.index(-0.0, i) == i
-class AppTestListObjectWithRangeList(AppTestListObject):
- """Run the list object tests with range lists enabled. Tests should go in
- AppTestListObject so they can be run -A against CPython as well.
- """
- spaceconfig = {"objspace.std.withrangelist": True}
-
-
class AppTestRangeListForcing:
"""Tests for range lists that test forcing. Regular tests should go in
AppTestListObject so they can be run -A against CPython as well. Separate
from AppTestListObjectWithRangeList so we don't silently overwrite tests
with the same names.
"""
- spaceconfig = {"objspace.std.withrangelist": True}
+ spaceconfig = {"objspace.std.withliststrategies": True}
def setup_class(cls):
if cls.runappdirect:
diff --git a/pypy/objspace/std/test/test_mapdict.py b/pypy/objspace/std/test/test_mapdict.py
--- a/pypy/objspace/std/test/test_mapdict.py
+++ b/pypy/objspace/std/test/test_mapdict.py
@@ -4,18 +4,16 @@
class Config:
class objspace:
class std:
- withsmalldicts = False
withcelldict = False
- withmethodcache = False
- withidentitydict = False
- withmapdict = True
+ methodcachesizeexp = 11
+ withmethodcachecounter = False
space = FakeSpace()
space.config = Config
class Class(object):
def __init__(self, hasdict=True):
- self.hasdict = True
+ self.hasdict = hasdict
if hasdict:
self.terminator = DictTerminator(space, self)
else:
@@ -24,10 +22,17 @@
def instantiate(self, sp=None):
if sp is None:
sp = space
- result = Object()
+ if self.hasdict:
+ result = Object()
+ else:
+ result = ObjectWithoutDict()
result.user_setup(sp, self)
return result
+class ObjectWithoutDict(ObjectWithoutDict):
+ class typedef:
+ hasdict = False
+
class Object(Object):
class typedef:
hasdict = False
@@ -431,6 +436,9 @@
assert obj.getslotvalue(b) == 60
assert obj.storage == [50, 60]
assert not obj.setdictvalue(space, "a", 70)
+ assert obj.getdict(space) is None
+ assert obj.getdictvalue(space, "a") is None
+
def test_getdict():
cls = Class()
@@ -591,15 +599,20 @@
def test_specialized_class():
+ from pypy.objspace.std.mapdict import _make_storage_mixin_size_n
from pypy.objspace.std.objectobject import W_ObjectObject
- classes = memo_get_subclass_of_correct_size(space, W_ObjectObject)
+ classes = [_make_storage_mixin_size_n(i) for i in range(2, 10)]
w1 = W_Root()
w2 = W_Root()
w3 = W_Root()
w4 = W_Root()
w5 = W_Root()
w6 = W_Root()
- for objectcls in classes:
+ for mixin in classes:
+ class objectcls(W_ObjectObject):
+ objectmodel.import_from_mixin(BaseUserClassMapdict)
+ objectmodel.import_from_mixin(MapdictDictSupport)
+ objectmodel.import_from_mixin(mixin)
cls = Class()
obj = objectcls()
obj.user_setup(space, cls)
@@ -646,7 +659,6 @@
# XXX write more
class AppTestWithMapDict(object):
- spaceconfig = {"objspace.std.withmapdict": True}
def test_simple(self):
class A(object):
@@ -863,8 +875,7 @@
class AppTestWithMapDictAndCounters(object):
- spaceconfig = {"objspace.std.withmapdict": True,
- "objspace.std.withmethodcachecounter": True}
+ spaceconfig = {"objspace.std.withmethodcachecounter": True}
def setup_class(cls):
from pypy.interpreter import gateway
@@ -1207,8 +1218,7 @@
assert got == 'd'
class AppTestGlobalCaching(AppTestWithMapDict):
- spaceconfig = {"objspace.std.withmethodcachecounter": True,
- "objspace.std.withmapdict": True}
+ spaceconfig = {"objspace.std.withmethodcachecounter": True}
def test_mix_classes(self):
import __pypy__
@@ -1265,8 +1275,7 @@
assert 0, "failed: got %r" % ([got[1] for got in seen],)
class TestDictSubclassShortcutBug(object):
- spaceconfig = {"objspace.std.withmapdict": True,
- "objspace.std.withmethodcachecounter": True}
+ spaceconfig = {"objspace.std.withmethodcachecounter": True}
def test_bug(self):
w_dict = self.space.appexec([], """():
diff --git a/pypy/objspace/std/test/test_methodcache.py b/pypy/objspace/std/test/test_methodcache.py
--- a/pypy/objspace/std/test/test_methodcache.py
+++ b/pypy/objspace/std/test/test_methodcache.py
@@ -202,7 +202,8 @@
l = [type.__getattribute__(A, "__new__")(A)] * 10
__pypy__.reset_method_cache_counter()
for i, a in enumerate(l):
- assert a.f() == 42
+ # use getattr to circumvent the mapdict cache
+ assert getattr(a, "f")() == 42
cache_counter = __pypy__.method_cache_counter("f")
assert sum(cache_counter) == 10
if cache_counter == (9, 1):
@@ -225,9 +226,11 @@
assert a.x == i + 1
A.x += 1
cache_counter = __pypy__.method_cache_counter("x")
- assert cache_counter[0] >= 350
+ # XXX this is the bad case for the mapdict cache: looking up
+ # non-method attributes from the class
+ assert cache_counter[0] >= 450
assert cache_counter[1] >= 1
- assert sum(cache_counter) == 400
+ assert sum(cache_counter) == 500
__pypy__.reset_method_cache_counter()
a = A()
diff --git a/pypy/objspace/std/test/test_typeobject.py b/pypy/objspace/std/test/test_typeobject.py
--- a/pypy/objspace/std/test/test_typeobject.py
+++ b/pypy/objspace/std/test/test_typeobject.py
@@ -1,3 +1,4 @@
+import py
from pypy.interpreter.baseobjspace import W_Root
from pypy.interpreter.gateway import interp2app
from pypy.interpreter.typedef import TypeDef
@@ -1105,7 +1106,6 @@
class AppTestGetattributeShortcut:
- spaceconfig = {"objspace.std.getattributeshortcut": True}
def test_reset_logic(self):
class X(object):
@@ -1239,3 +1239,57 @@
class Y:
__metaclass__ = X
assert (Y < Y) is True
+
+
+class AppTestComparesByIdentity:
+
+ def setup_class(cls):
+ if cls.runappdirect:
+ py.test.skip("interp2app doesn't work on appdirect")
+
+ def compares_by_identity(space, w_cls):
+ return space.wrap(w_cls.compares_by_identity())
+ cls.w_compares_by_identity = cls.space.wrap(interp2app(compares_by_identity))
+
+ def test_compares_by_identity(self):
+ class Plain(object):
+ pass
+
+ class CustomEq(object):
+ def __eq__(self, other):
+ return True
+
+ class CustomCmp (object):
+ def __cmp__(self, other):
+ return 0
+
+ class CustomHash(object):
+ def __hash__(self):
+ return 0
+
+ class TypeSubclass(type):
+ pass
+
+ class TypeSubclassCustomCmp(type):
+ def __cmp__(self, other):
+ return 0
+
+ assert self.compares_by_identity(Plain)
+ assert not self.compares_by_identity(CustomEq)
+ assert not self.compares_by_identity(CustomCmp)
+ assert not self.compares_by_identity(CustomHash)
+ assert self.compares_by_identity(type)
+ assert self.compares_by_identity(TypeSubclass)
+ assert not self.compares_by_identity(TypeSubclassCustomCmp)
+
+ def test_modify_class(self):
+ class X(object):
+ pass
+
+ assert self.compares_by_identity(X)
+ X.__eq__ = lambda x: None
+ assert not self.compares_by_identity(X)
+ del X.__eq__
+ assert self.compares_by_identity(X)
+
+
diff --git a/pypy/objspace/std/test/test_userobject.py b/pypy/objspace/std/test/test_userobject.py
--- a/pypy/objspace/std/test/test_userobject.py
+++ b/pypy/objspace/std/test/test_userobject.py
@@ -273,13 +273,3 @@
i += 1
-class AppTestWithGetAttributeShortcut(AppTestUserObject):
- spaceconfig = {"objspace.std.getattributeshortcut": True}
-
-
-class AppTestDescriptorWithGetAttributeShortcut(
- test_descriptor.AppTest_Descriptor):
- # for the individual tests see
- # ====> ../../test/test_descriptor.py
-
- spaceconfig = {"objspace.std.getattributeshortcut": True}
diff --git a/pypy/objspace/std/test/test_versionedtype.py b/pypy/objspace/std/test/test_versionedtype.py
--- a/pypy/objspace/std/test/test_versionedtype.py
+++ b/pypy/objspace/std/test/test_versionedtype.py
@@ -1,7 +1,6 @@
from pypy.objspace.std.test import test_typeobject
class TestVersionedType(test_typeobject.TestTypeObject):
- spaceconfig = {"objspace.std.withtypeversion": True}
def get_three_classes(self):
space = self.space
@@ -261,6 +260,3 @@
-class AppTestVersionedType(test_typeobject.AppTestTypeObject):
- spaceconfig = {"objspace.std.withtypeversion": True}
-
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -1,3 +1,4 @@
+import weakref
from pypy.interpreter import gateway
from pypy.interpreter.baseobjspace import W_Root, SpaceCache
from pypy.interpreter.error import oefmt, OperationError
@@ -9,6 +10,7 @@
from rpython.rlib.jit import (promote, elidable_promote, we_are_jitted,
elidable, dont_look_inside, unroll_safe)
from rpython.rlib.objectmodel import current_object_addr_as_int, compute_hash
+from rpython.rlib.objectmodel import we_are_translated
from rpython.rlib.rarithmetic import intmask, r_uint
class MutableCell(W_Root):
@@ -38,9 +40,8 @@
def unwrap_cell(space, w_value):
- if space.config.objspace.std.withtypeversion:
- if isinstance(w_value, MutableCell):
- return w_value.unwrap_cell(space)
+ if isinstance(w_value, MutableCell):
+ return w_value.unwrap_cell(space)
return w_value
def write_cell(space, w_cell, w_value):
@@ -69,7 +70,6 @@
class MethodCache(object):
def __init__(self, space):
- assert space.config.objspace.std.withmethodcache
SIZE = 1 << space.config.objspace.std.methodcachesizeexp
self.versions = [None] * SIZE
self.names = [None] * SIZE
@@ -87,6 +87,10 @@
for i in range(len(self.lookup_where)):
self.lookup_where[i] = None_None
+class _Global(object):
+ weakref_warning_printed = False
+_global = _Global()
+
class Layout(object):
More information about the pypy-commit
mailing list