Author: Carl Friedrich Bolz <cfb...@gmx.de> Branch: guard-compatible Changeset: r83143:befa6a197166 Date: 2016-03-18 18:02 +0100 http://bitbucket.org/pypy/pypy/changeset/befa6a197166/
Log: fix getattr (both in the objspace and in the callmethod version) to not read (and thus promote) the type when we have a mapdict object and we are jitted. 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 @@ -41,10 +41,19 @@ w_name = f.getname_w(nameindex) w_value = None - w_type = space.type(w_obj) - if w_type.has_object_getattribute(): + safe = False + if space.config.objspace.std.withmapdict and jit.we_are_jitted(): + # compute safeness without reading the type + map = w_obj._get_mapdict_map_no_promote() + if map is not None and map._type_safe_to_do_getattr(): + safe = True + else: + w_type = space.type(w_obj) + safe = w_type.has_object_getattribute() + + if safe: name = space.str_w(w_name) - w_descr = w_type.lookup(name) + w_descr = space.lookup(w_obj, name) if w_descr is None: # this handles directly the common case # module.function(args..) @@ -62,6 +71,7 @@ if (space.config.objspace.std.withmapdict and not jit.we_are_jitted()): # let mapdict cache stuff + w_type = space.type(w_obj) LOOKUP_METHOD_mapdict_fill_cache_method( space, f.getcode(), name, nameindex, w_obj, w_type) return @@ -113,8 +123,17 @@ """An optimized version of space.call_method() based on the same principle as above. """ - w_type = space.type(w_obj) - if w_type.has_object_getattribute(): + safe = False + if space.config.objspace.std.withmapdict: + # compute safeness without reading the type + map = w_obj._get_mapdict_map_no_promote() + if map is not None and map._type_safe_to_do_getattr(): + import pdb; pdb.set_trace() + safe = True + else: + w_type = space.type(w_obj) + safe = w_type.has_object_getattribute() + if safe: w_descr = space.lookup(w_obj, methname) typ = type(w_descr) if typ is function.Function or typ is function.FunctionWithFixedCode: 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 @@ -333,7 +333,7 @@ assert version is not None w_type = self.terminator.w_cls w_res = w_type._pure_lookup_where_with_method_cache( - name, w_cls.version_tag()) + name, w_type.version_tag())[1] return w_res 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 @@ -530,15 +530,23 @@ return self._DescrOperation_getattr(w_obj, w_name) # an optional shortcut for performance - w_type = self.type(w_obj) - w_descr = w_type.getattribute_if_not_from_object() - if w_descr is not None: - return self._handle_getattribute(w_descr, w_obj, w_name) + safe = False + if self.config.objspace.std.withmapdict and jit.we_are_jitted(): + # compute safeness without reading the type + map = w_obj._get_mapdict_map_no_promote() + if map is not None and map._type_safe_to_do_getattr(): + safe = True + + if not safe: + w_type = self.type(w_obj) + w_descr = w_type.getattribute_if_not_from_object() + if w_descr is not None: + return self._handle_getattribute(w_descr, w_obj, w_name) # fast path: XXX this is duplicating most of the logic # from the default __getattribute__ and the getattr() method... name = self.str_w(w_name) - w_descr = w_type.lookup(name) + w_descr = self.lookup(w_obj, name) e = None if w_descr is not None: w_get = None @@ -554,6 +562,7 @@ if w_get is not None: # __get__ is allowed to raise an AttributeError to trigger # use of __getattr__. + w_type = self.type(w_obj) try: return self.get_and_call_function(w_get, w_descr, w_obj, w_type) 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 @@ -111,6 +111,9 @@ class AppTestCallMethodWithGetattributeShortcut(AppTestCallMethod): spaceconfig = {"objspace.std.getattributeshortcut": True} +class AppTestCallMethodWithGetattributeShortcutAndMapdict(AppTestCallMethod): + spaceconfig = {"objspace.std.getattributeshortcut": True, + "objspace.std.withmapdict": True} class TestCallMethod: def test_space_call_method(self): @@ -132,3 +135,7 @@ callmethod.LOOKUP_METHOD) assert (self.space.FrameClass.CALL_METHOD.im_func == callmethod.CALL_METHOD) + +class TestCallMethodMapDict(TestCallMethod): + spaceconfig = {"objspace.std.getattributeshortcut": True, + "objspace.std.withmapdict": True} _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit