Author: Matti Picus <[email protected]>
Branch: better-PyDict_Next
Changeset: r89006:be0fc891ac83
Date: 2016-12-10 23:33 +0200
http://bitbucket.org/pypy/pypy/changeset/be0fc891ac83/

Log:    create PyObject-W_Root pairs for GetSetProperty when creating a
        tp_dict

diff --git a/pypy/module/cpyext/dictobject.py b/pypy/module/cpyext/dictobject.py
--- a/pypy/module/cpyext/dictobject.py
+++ b/pypy/module/cpyext/dictobject.py
@@ -8,10 +8,9 @@
     Py_ssize_tP, CONST_STRING, PyObjectFields, cpython_struct,
     bootstrap_function)
 from pypy.module.cpyext.pyobject import (PyObject, PyObjectP, as_pyobj, 
-        make_typedescr, track_reference, create_ref, from_ref, Py_DecRef,
+        make_typedescr, track_reference, create_ref, from_ref, decref,
         Py_IncRef)
 from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
-from pypy.module.cpyext.typeobject import W_GetSetPropertyEx, make_GetSet
 
 PyDictObjectStruct = lltype.ForwardReference()
 PyDictObject = lltype.Ptr(PyDictObjectStruct)
@@ -34,6 +33,19 @@
     """
     py_dict = rffi.cast(PyDictObject, py_obj)
     py_dict.c_ob_keys = lltype.nullptr(PyObject.TO)
+    # Problems: if this dict is a typedict, we may have unbound GetSetProperty
+    # functions in the dict. The corresponding PyGetSetDescrObject must be
+    # bound to a class, but the actual w_type will be unavailable later on. 
+    # Solution: use the w_userdata argument when assigning a PyTypeObject's
+    # tp_dict slot to pass a w_type in, and force creation of the pair here
+    if not space.is_w(w_userdata, space.gettypefor(GetSetProperty)):
+        # do not do this for type dict of GetSetProperty, that would recurse
+        w_vals = space.call_method(space.w_dict, "values", w_obj)
+        vals = space.listview(w_vals)
+        for w_v in vals:
+            if isinstance(w_v, GetSetProperty):
+                pyobj = as_pyobj(space, w_v, w_userdata)
+                # refcnt will be REFCNT_FROM_PYPY, no need to inc or dec
 
 def dict_realize(space, py_obj):
     """
@@ -45,7 +57,7 @@
 @cpython_api([PyObject], lltype.Void, header=None)
 def dict_dealloc(space, py_obj):
     py_dict = rffi.cast(PyDictObject, py_obj)
-    Py_DecRef(space, py_dict.c_ob_keys)
+    decref(space, py_dict.c_ob_keys)
     from pypy.module.cpyext.object import _dealloc
     _dealloc(space, py_obj)
 
@@ -250,7 +262,7 @@
     py_dict = rffi.cast(PyDictObject, py_obj)
     if pos == 0:
         # Store the current keys in the PyDictObject.
-        Py_DecRef(space, py_dict.c_ob_keys)
+        decref(space, py_dict.c_ob_keys)
         w_keys = space.call_method(space.w_dict, "keys", w_dict)
         py_dict.c_ob_keys = create_ref(space, w_keys)
         Py_IncRef(space, py_dict.c_ob_keys)
@@ -264,13 +276,7 @@
     if pkey:
         pkey[0]   = as_pyobj(space, w_key)
     if pvalue:
-        w_type = None
-        if isinstance(w_value, GetSetProperty):
-            strategy = w_dict.get_strategy()
-            # for translation
-            assert isinstance(strategy, ClassDictStrategy)
-            w_type = strategy.unerase(w_dict.get_storage())
-        pvalue[0] = as_pyobj(space, w_value, w_type)
+        pvalue[0] = as_pyobj(space, w_value)
     return 1
 
 @specialize.memo()
diff --git a/pypy/module/cpyext/pyobject.py b/pypy/module/cpyext/pyobject.py
--- a/pypy/module/cpyext/pyobject.py
+++ b/pypy/module/cpyext/pyobject.py
@@ -276,14 +276,14 @@
         return hop.inputconst(lltype.Bool, hop.s_result.const)
 
 @specialize.ll()
-def make_ref(space, obj):
+def make_ref(space, obj, w_userdata=None):
     """Increment the reference counter of the PyObject and return it.
     Can be called with either a PyObject or a W_Root.
     """
     if is_pyobj(obj):
         pyobj = rffi.cast(PyObject, obj)
     else:
-        pyobj = as_pyobj(space, obj)
+        pyobj = as_pyobj(space, obj, w_userdata)
     if pyobj:
         assert pyobj.c_ob_refcnt > 0
         pyobj.c_ob_refcnt += 1
diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -941,7 +941,9 @@
     if w_obj.is_cpytype():
         Py_DecRef(space, pto.c_tp_dict)
     w_dict = w_obj.getdict(space)
-    pto.c_tp_dict = make_ref(space, w_dict)
+    # pass in the w_obj to convert any values that are
+    # unbound GetSetProperty into bound PyGetSetDescrObject
+    pto.c_tp_dict = make_ref(space, w_dict, w_obj)
 
 @cpython_api([PyTypeObjectPtr, PyTypeObjectPtr], rffi.INT_real, 
error=CANNOT_FAIL)
 def PyType_IsSubtype(space, a, b):
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
@@ -356,9 +356,6 @@
         if strategy is not object_strategy:
             strategy.switch_to_object_strategy(self)
 
-    def get_storage(self): # for getting the w_type from a ClassDictStrategy
-        return self.dstorage
-
 
 class W_DictObject(W_DictMultiObject):
     """ a regular dict object """
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to