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