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

Reply via email to