Author: Manuel Jacob
Branch: kill-multimethod
Changeset: r69401:fa0cc2a86b87
Date: 2014-02-25 05:59 +0100
http://bitbucket.org/pypy/pypy/changeset/fa0cc2a86b87/
Log: I *think* it's safe to remove builtinshortcut because it seems that
it only speeds up multimethods.
diff --git a/pypy/objspace/std/builtinshortcut.py
b/pypy/objspace/std/builtinshortcut.py
deleted file mode 100644
--- a/pypy/objspace/std/builtinshortcut.py
+++ /dev/null
@@ -1,136 +0,0 @@
-from pypy.interpreter.baseobjspace import ObjSpace
-from pypy.interpreter.error import OperationError
-from pypy.objspace.descroperation import DescrOperation
-from pypy.objspace.std.boolobject import W_BoolObject
-from rpython.tool.sourcetools import func_with_new_name
-
-# ____________________________________________________________
-#
-# The sole purpose of this file is performance.
-# It speeds up the dispatch of operations between
-# built-in objects.
-#
-
-# this is a selection... a few operations are missing because they are
-# thought to be very rare or most commonly used with non-builtin types
-METHODS_WITH_SHORTCUT = dict.fromkeys(
- ['add', 'sub', 'mul', 'truediv', 'floordiv', 'div',
- 'mod', 'lshift', 'rshift', 'and_', 'or_', 'xor', 'pow',
- 'lt', 'le', 'eq', 'ne', 'gt', 'ge', 'contains',
- # unary
- 'len', 'nonzero', 'repr', 'str', 'hash',
- 'neg', 'invert', 'index', 'iter', 'next', 'buffer',
- 'getitem', 'setitem', 'int',
- # in-place
- 'inplace_add', 'inplace_sub', 'inplace_mul', 'inplace_truediv',
- 'inplace_floordiv', 'inplace_div', 'inplace_mod', 'inplace_pow',
- 'inplace_lshift', 'inplace_rshift', 'inplace_and', 'inplace_or',
- 'inplace_xor',
- # other
- 'format',
- ])
-
-KNOWN_MISSING = ['getattr', # mostly non-builtins or optimized by CALL_METHOD
- 'setattr', 'delattr', 'userdel', # mostly for non-builtins
- 'get', 'set', 'delete', # uncommon (except on functions)
- 'getslice', 'setslice', 'delslice', # see below
- 'delitem', 'trunc', # rare stuff?
- 'abs', 'hex', 'oct', # rare stuff?
- 'pos', 'divmod', 'cmp', # rare stuff?
- 'float', 'long', 'coerce', # rare stuff?
- 'isinstance', 'issubtype',
- ]
-# We cannot support {get,set,del}slice right now because
-# DescrOperation.{get,set,del}slice do a bit more work than just call
-# the special methods: they call old_slice_range(). See e.g.
-# test_builtinshortcut.AppTestString.
-
-for _name, _, _, _specialmethods in ObjSpace.MethodTable:
- if _specialmethods:
- assert _name in METHODS_WITH_SHORTCUT or _name in KNOWN_MISSING, (
- "operation %r should be in METHODS_WITH_SHORTCUT or KNOWN_MISSING"
- % (_name,))
-
-
-def filter_out_conversions(typeorder):
- res = {}
- for cls, order in typeorder.iteritems():
- res[cls] = [(target_type, converter) for (target_type, converter) in
- order if converter is None]
- return res
-
-
-def install(space, mm, fallback_mm=None):
- """Install a function <name>() on the space instance which invokes
- a shortcut for built-in types. Returns the shortcutting multimethod
- object or None.
- """
- name = mm.name
- if name not in METHODS_WITH_SHORTCUT:
- return None
-
- # can be called multiple times without re-installing
- if name in space.__dict__:
- mm1, shortcut_method = space.__dict__[name].builtinshortcut
- assert mm1 is mm
- return shortcut_method
-
- #print 'installing shortcut for:', name
- assert hasattr(DescrOperation, name)
-
- base_method = getattr(space.__class__, name)
-
- # Basic idea: we first try to dispatch the operation using purely
- # the multimethod. If this is done naively, subclassing a built-in
- # type like 'int' and overriding a special method like '__add__'
- # doesn't work any more, because the multimethod will accept the int
- # subclass and compute the result in the built-in way. To avoid
- # this issue, we tweak the shortcut multimethods so that these ones
- # (and only these ones) never match the interp-level subclasses
- # built in pypy.interpreter.typedef.get_unique_interplevel_subclass.
- expanded_order = space.model.get_typeorder_with_empty_usersubcls()
- if fallback_mm:
- mm = mm.merge_with(fallback_mm)
- shortcut_method =
mm.install_not_sliced(filter_out_conversions(expanded_order))
-
- def operate(*args_w):
- try:
- return shortcut_method(space, *args_w)
- except FailedToImplement:
- pass
- return base_method(space, *args_w)
-
- operate = func_with_new_name(operate, name)
- operate.builtinshortcut = (mm, shortcut_method)
- setattr(space, name, operate)
- return shortcut_method
-
-
-def install_is_true(space, mm_nonzero, mm_len):
- shortcut = install(space, mm_nonzero, fallback_mm = mm_len)
- assert 'is_true' not in space.__dict__
-
- def is_true(w_obj):
- # a bit of duplication of the logic from DescrOperation.is_true...
- try:
- w_res = shortcut(space, w_obj)
- except FailedToImplement:
- pass
- else:
- # the __nonzero__ method of built-in objects should
- # always directly return a Bool; however, the __len__ method
- # of built-in objects typically returns an unwrappable integer
- if isinstance(w_res, W_BoolObject):
- return bool(w_res.intval)
- try:
- return space.int_w(w_res) != 0
- except OperationError:
- # I think no OperationError other than w_OverflowError
- # could occur here
- w_obj = w_res
-
- # general case fallback
- return _DescrOperation_is_true(space, w_obj)
-
- _DescrOperation_is_true = DescrOperation.is_true.im_func
- space.is_true = is_true
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
@@ -4,7 +4,7 @@
from pypy.interpreter.baseobjspace import ObjSpace, W_Root
from pypy.interpreter.error import OperationError, oefmt
from pypy.interpreter.typedef import get_unique_interplevel_subclass
-from pypy.objspace.std import (builtinshortcut, stdtypedef, frame, model,
+from pypy.objspace.std import (stdtypedef, frame, model,
transparent, callmethod)
from pypy.objspace.descroperation import DescrOperation, raiseattrerror
from rpython.rlib.objectmodel import instantiate, specialize,
is_annotation_constant
@@ -485,7 +485,6 @@
def is_true(self, w_obj):
# a shortcut for performance
- # NOTE! this method is typically overridden by builtinshortcut.py.
if type(w_obj) is W_BoolObject:
return bool(w_obj.intval)
return self._DescrOperation_is_true(w_obj)
diff --git a/pypy/objspace/std/test/test_builtinshortcut.py
b/pypy/objspace/std/test/test_builtinshortcut.py
deleted file mode 100644
--- a/pypy/objspace/std/test/test_builtinshortcut.py
+++ /dev/null
@@ -1,98 +0,0 @@
-from pypy.objspace.std.test import test_userobject
-from pypy.objspace.std.test import test_setobject
-from pypy.objspace.std.test import test_bytesobject
-
-WITH_BUILTINSHORTCUT = {'objspace.std.builtinshortcut': True}
-
-class AppTestUserObject(test_userobject.AppTestUserObject):
- spaceconfig = WITH_BUILTINSHORTCUT
-
-class AppTestBug:
- spaceconfig = WITH_BUILTINSHORTCUT
-
- def test_frozen_subtype(self):
- class S(set): pass
- assert set("abc") == S("abc")
- assert S("abc") == set("abc")
- class F(frozenset): pass
- assert frozenset("abc") == F("abc")
- assert F("abc") == frozenset("abc")
-
- assert S("abc") in set([frozenset("abc")])
- assert F("abc") in set([frozenset("abc")])
-
- s = set([frozenset("abc")])
- s.discard(S("abc"))
- assert not s
-
- s = set([frozenset("abc")])
- s.discard(F("abc"))
- assert not s
-
- def test_inplace_methods(self):
- assert '__iadd__' not in int.__dict__
- assert '__iadd__' not in float.__dict__
- x = 5
- x += 6.5
- assert x == 11.5
-
- def test_inplace_user_subclasses(self):
- class I(int): pass
- class F(float): pass
- x = I(5)
- x += F(6.5)
- assert x == 11.5
- assert type(x) is float
-
- def test_inplace_override(self):
- class I(int):
- def __iadd__(self, other):
- return 'foo'
- x = I(5)
- x += 6
- assert x == 'foo'
- x = I(5)
- x += 6.5
- assert x == 'foo'
- assert 5 + 6.5 == 11.5
-
- def test_unicode_string_compares(self):
- assert u'a' == 'a'
- assert 'a' == u'a'
- assert not u'a' == 'b'
- assert not 'a' == u'b'
- assert u'a' != 'b'
- assert 'a' != u'b'
- assert not (u'a' == 5)
- assert u'a' != 5
- assert u'a' < 5 or u'a' > 5
-
- s = chr(128)
- u = unichr(128)
- assert not s == u # UnicodeWarning
- assert s != u
- assert not u == s
- assert u != s
-
-
-class AppTestSet(test_setobject.AppTestAppSetTest):
- spaceconfig = WITH_BUILTINSHORTCUT
- # this tests tons of funny comparison combinations that can easily go wrong
- def setup_class(cls):
- w_fakeint = cls.space.appexec([], """():
- class FakeInt(object):
- def __init__(self, value):
- self.value = value
- def __hash__(self):
- return hash(self.value)
-
- def __eq__(self, other):
- if other == self.value:
- return True
- return False
- return FakeInt
- """)
- cls.w_FakeInt = w_fakeint
-
-class AppTestString(test_bytesobject.AppTestBytesObject):
- spaceconfig = WITH_BUILTINSHORTCUT
diff --git a/pypy/objspace/test/test_descroperation.py
b/pypy/objspace/test/test_descroperation.py
--- a/pypy/objspace/test/test_descroperation.py
+++ b/pypy/objspace/test/test_descroperation.py
@@ -721,8 +721,3 @@
return CannotConvertToBool()
x = X()
raises(MyError, "'foo' in x")
-
-
-
-class AppTestWithBuiltinShortcut(AppTest_Descroperation):
- spaceconfig = {'objspace.std.builtinshortcut': True}
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit