[pypy-svn] r67483 - in pypy/trunk/pypy: config doc/config objspace/std objspace/std/test
pedronis at codespeak.net
pedronis at codespeak.net
Fri Sep 4 16:26:37 CEST 2009
Author: pedronis
Date: Fri Sep 4 16:26:36 2009
New Revision: 67483
Added:
pypy/trunk/pypy/doc/config/objspace.std.newshortcut.txt (contents, props changed)
Modified:
pypy/trunk/pypy/config/pypyoption.py
pypy/trunk/pypy/objspace/std/test/test_typeobject.py
pypy/trunk/pypy/objspace/std/typeobject.py
Log:
(micke, pedronis) add a shortcut path to object creation, it speeds up object creation more than 20% for types without a custom __new__
Modified: pypy/trunk/pypy/config/pypyoption.py
==============================================================================
--- pypy/trunk/pypy/config/pypyoption.py (original)
+++ pypy/trunk/pypy/config/pypyoption.py Fri Sep 4 16:26:36 2009
@@ -328,6 +328,9 @@
BoolOption("getattributeshortcut",
"track types that override __getattribute__",
default=False),
+ BoolOption("newshortcut",
+ "cache and shortcut calling __new__ from builtin types",
+ default=False),
BoolOption("logspaceoptypes",
"a instrumentation option: before exit, print the types seen by "
@@ -369,6 +372,7 @@
config.objspace.std.suggest(builtinshortcut=True)
config.objspace.std.suggest(optimized_list_getitem=True)
config.objspace.std.suggest(getattributeshortcut=True)
+ config.objspace.std.suggest(newshortcut=True)
# extra costly optimizations only go in level 3
if level == '3':
Added: pypy/trunk/pypy/doc/config/objspace.std.newshortcut.txt
==============================================================================
--- (empty file)
+++ pypy/trunk/pypy/doc/config/objspace.std.newshortcut.txt Fri Sep 4 16:26:36 2009
@@ -0,0 +1 @@
+Performance only: cache and shortcut calling __new__ from builtin types
Modified: pypy/trunk/pypy/objspace/std/test/test_typeobject.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/test/test_typeobject.py (original)
+++ pypy/trunk/pypy/objspace/std/test/test_typeobject.py Fri Sep 4 16:26:36 2009
@@ -991,3 +991,82 @@
X.__getattribute__ = ga
assert y.x == 'GA'
+
+class TestNewShortcut:
+
+ def setup_class(cls):
+ cls.space = gettestobjspace(
+ **{"objspace.std.newshortcut": True})
+
+ def test_mechanics(self):
+ space = self.space
+ w_tup = space.appexec([], """():
+ class A(object):
+ pass
+ class B(object):
+ __new__ = staticmethod(lambda t: 1)
+ class M(type):
+ pass
+ return A, B, M
+""")
+ w_A, w_B, w_M = space.unpackiterable(w_tup)
+
+ assert w_A.w_bltin_new is None
+ assert w_B.w_bltin_new is None
+ assert w_M.w_bltin_new is None
+
+ _, w_object_newdescr = space.lookup_in_type_where(space.w_object,
+ '__new__')
+ w_object___new__ = space.get(w_object_newdescr, None,
+ w_type=space.w_object)
+
+ w_a = space.call_function(w_A)
+ assert w_A.w_bltin_new is w_object___new__
+
+ # will shortcut
+ w_a = space.call_function(w_A)
+
+ w_b = space.call_function(w_B)
+ assert w_B.w_bltin_new is None
+
+ w_m = space.call_function(w_M, space.wrap('C'), space.newlist([]),
+ space.newdict())
+ assert w_M.w_bltin_new is None
+
+
+class AppTestNewShortcut:
+
+ def setup_class(cls):
+ cls.space = gettestobjspace(
+ **{"objspace.std.newshortcut": True})
+
+ def test_reset_logic(self):
+ class X(object):
+ pass
+
+ class Y(X):
+ pass
+
+ y = Y()
+
+ assert isinstance(y, Y)
+
+
+ X.__new__ = staticmethod(lambda t: 1)
+
+ y = Y()
+
+ assert y == 1
+
+ def test_dont_explode_on_non_types(self):
+ class A:
+ __new__ = staticmethod(lambda t: 1)
+
+ class B(A, object):
+ pass
+
+ b = B()
+
+ assert b == 1
+
+
Modified: pypy/trunk/pypy/objspace/std/typeobject.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/typeobject.py (original)
+++ pypy/trunk/pypy/objspace/std/typeobject.py Fri Sep 4 16:26:36 2009
@@ -52,9 +52,14 @@
_immutable_fields_ = ["__flags__"]
- uses_object_getattribute = False
- # ^^^ for config.objspace.std.getattributeshortcut
+ # for config.objspace.std.getattributeshortcut
# (False is a conservative default, fixed during real usage)
+ uses_object_getattribute = False
+
+ # used to cache the type __new__ function if it comes from a builtin type
+ # != 'type', in that case call__Type will also assumes the result
+ # of the __new__ is an instance of the type
+ w_bltin_new = None
def __init__(w_self, space, name, bases_w, dict_w,
overridetypedef=None):
@@ -87,13 +92,17 @@
def mutated(w_self):
space = w_self.space
if (not space.config.objspace.std.withtypeversion and
- not space.config.objspace.std.getattributeshortcut):
+ not space.config.objspace.std.getattributeshortcut and
+ not space.config.objspace.std.newshortcut):
return
if space.config.objspace.std.getattributeshortcut:
w_self.uses_object_getattribute = False
# ^^^ conservative default, fixed during real usage
+ if space.config.objspace.std.newshortcut:
+ w_self.w_bltin_new = None
+
if (space.config.objspace.std.withtypeversion
and w_self.version_tag is not None):
w_self.version_tag = VersionTag()
@@ -570,10 +579,23 @@
else:
return space.type(w_obj)
# invoke the __new__ of the type
- w_newfunc = space.getattr(w_type, space.wrap('__new__'))
- w_newobject = space.call_obj_args(w_newfunc, w_type, __args__)
+ w_bltin_new = w_type.w_bltin_new
+ call_init = True
+ if w_bltin_new is not None:
+ w_newobject = space.call_obj_args(w_bltin_new, w_type, __args__)
+ else:
+ w_newtype, w_newdescr = w_type.lookup_where('__new__')
+ w_newfunc = space.get(w_newdescr, w_type)
+ if (space.config.objspace.std.newshortcut and
+ isinstance(w_newtype, W_TypeObject) and
+ not w_newtype.is_heaptype() and
+ not space.is_w(w_newtype, space.w_type)):
+ w_type.w_bltin_new = w_newfunc
+ w_newobject = space.call_obj_args(w_newfunc, w_type, __args__)
+ call_init = space.is_true(space.isinstance(w_newobject, w_type))
+
# maybe invoke the __init__ of the type
- if space.is_true(space.isinstance(w_newobject, w_type)):
+ if call_init:
w_descr = space.lookup(w_newobject, '__init__')
w_result = space.get_and_call_args(w_descr, w_newobject, __args__)
if not space.is_w(w_result, space.w_None):
More information about the Pypy-commit
mailing list