[pypy-commit] pypy cpyext-gc-support: Fix PyDict_Next (still broken complexity)
arigo
noreply at buildbot.pypy.org
Fri Oct 23 08:04:47 EDT 2015
Author: Armin Rigo <arigo at tunes.org>
Branch: cpyext-gc-support
Changeset: r80409:03b0d3536b4c
Date: 2015-10-23 14:03 +0200
http://bitbucket.org/pypy/pypy/changeset/03b0d3536b4c/
Log: Fix PyDict_Next (still broken complexity)
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
@@ -2,7 +2,7 @@
from pypy.module.cpyext.api import (
cpython_api, CANNOT_FAIL, build_type_checkers, Py_ssize_t,
Py_ssize_tP, CONST_STRING)
-from pypy.module.cpyext.pyobject import PyObject, PyObjectP, as_xpyobj
+from pypy.module.cpyext.pyobject import PyObject, PyObjectP, as_xpyobj, as_pyobj
from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
from pypy.interpreter.error import OperationError
from pypy.objspace.std.dictmultiobject import W_DictMultiObject
@@ -164,28 +164,26 @@
}
Py_DECREF(o);
}"""
- if w_dict is None:
+ if not isinstance(w_dict, W_DictMultiObject):
return 0
- # Note: this is not efficient. Storing an iterator would probably
+ # XXX XXX PyDict_Next is not efficient. Storing an iterator would probably
# work, but we can't work out how to not leak it if iteration does
- # not complete.
- ZZZ
+ # not complete. Alternatively, we could add some RPython-only
+ # dict-iterator method to move forward by N steps.
+ w_dict.ensure_object_strategy()
+ w_iter = space.call_method(space.w_dict, "iteritems", w_dict)
try:
- w_iter = space.call_method(space.w_dict, "iteritems", w_dict)
- pos = ppos[0]
- while pos:
+ for i in range(ppos[0]):
space.call_method(w_iter, "next")
- pos -= 1
w_item = space.call_method(w_iter, "next")
w_key, w_value = space.fixedview(w_item, 2)
- state = space.fromcache(RefcountState)
if pkey:
- pkey[0] = state.make_borrowed(w_dict, w_key)
+ pkey[0] = as_pyobj(space, w_key)
if pvalue:
- pvalue[0] = state.make_borrowed(w_dict, w_value)
+ pvalue[0] = as_pyobj(space, w_value)
ppos[0] += 1
except OperationError, e:
if not e.match(space, space.w_StopIteration):
diff --git a/pypy/module/cpyext/test/test_dictobject.py b/pypy/module/cpyext/test/test_dictobject.py
--- a/pypy/module/cpyext/test/test_dictobject.py
+++ b/pypy/module/cpyext/test/test_dictobject.py
@@ -1,7 +1,7 @@
from rpython.rtyper.lltypesystem import rffi, lltype
from pypy.module.cpyext.test.test_api import BaseApiTest
from pypy.module.cpyext.api import Py_ssize_tP, PyObjectP
-from pypy.module.cpyext.pyobject import from_pyobj
+from pypy.module.cpyext.pyobject import from_pyobj, as_pyobj
from pypy.interpreter.error import OperationError
class TestDictObject(BaseApiTest):
@@ -91,7 +91,6 @@
def test_iter(self, space, api):
w_dict = space.sys.getdict(space)
- py_dict = make_ref(space, w_dict)
ppos = lltype.malloc(Py_ssize_tP.TO, 1, flavor='raw')
ppos[0] = 0
@@ -109,14 +108,11 @@
lltype.free(pkey, flavor='raw')
lltype.free(pvalue, flavor='raw')
- api.Py_DecRef(py_dict) # release borrowed references
-
assert space.eq_w(space.len(w_copy), space.len(w_dict))
assert space.eq_w(w_copy, w_dict)
def test_iterkeys(self, space, api):
w_dict = space.sys.getdict(space)
- py_dict = make_ref(space, w_dict)
ppos = lltype.malloc(Py_ssize_tP.TO, 1, flavor='raw')
pkey = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
@@ -138,8 +134,6 @@
lltype.free(pkey, flavor='raw')
lltype.free(pvalue, flavor='raw')
- api.Py_DecRef(py_dict) # release borrowed references
-
assert space.eq_w(space.newlist(keys_w),
space.call_method(w_dict, "keys"))
assert space.eq_w(space.newlist(values_w),
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
@@ -336,6 +336,11 @@
F: D[k] = F[k]"""
init_or_update(space, self, __args__, 'dict.update')
+ def ensure_object_strategy(self): # for cpyext
+ object_strategy = self.space.fromcache(ObjectDictStrategy)
+ if self.strategy is not object_strategy:
+ self.strategy.switch_to_object_strategy(self)
+
def _add_indirections():
dict_methods = "getitem getitem_str setitem setdefault \
More information about the pypy-commit
mailing list