Author: Armin Rigo <[email protected]>
Branch: cpyext-gc-support
Changeset: r80405:b19c40f0c0ac
Date: 2015-10-23 12:18 +0200
http://bitbucket.org/pypy/pypy/changeset/b19c40f0c0ac/
Log: Fix a number of make_ref/from_ref/borrow_from.
diff --git a/pypy/module/cpyext/__init__.py b/pypy/module/cpyext/__init__.py
--- a/pypy/module/cpyext/__init__.py
+++ b/pypy/module/cpyext/__init__.py
@@ -61,7 +61,6 @@
import pypy.module.cpyext.funcobject
import pypy.module.cpyext.frameobject
import pypy.module.cpyext.classobject
-import pypy.module.cpyext.pypyintf
import pypy.module.cpyext.memoryobject
import pypy.module.cpyext.codecs
import pypy.module.cpyext.pyfile
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -291,7 +291,6 @@
def unwrapper(space, *args):
from pypy.module.cpyext.pyobject import Py_DecRef, from_xpyobj
from pypy.module.cpyext.pyobject import as_xpyobj, is_pyobj
- from pypy.module.cpyext.pyobject import Reference
newargs = ()
keepalives = ()
assert len(args) == len(api_function.argtypes)
diff --git a/pypy/module/cpyext/bufferobject.py
b/pypy/module/cpyext/bufferobject.py
--- a/pypy/module/cpyext/bufferobject.py
+++ b/pypy/module/cpyext/bufferobject.py
@@ -4,7 +4,7 @@
from pypy.module.cpyext.api import (
cpython_api, Py_ssize_t, cpython_struct, bootstrap_function,
PyObjectFields, PyObject)
-from pypy.module.cpyext.pyobject import make_typedescr, Py_DecRef, make_ref
+from pypy.module.cpyext.pyobject import make_typedescr, Py_DecRef
from pypy.module.array.interp_array import ArrayBuffer
from pypy.objspace.std.bufferobject import W_Buffer
@@ -51,6 +51,7 @@
# reference to buf.
# Otherwise, b_base stays NULL, and we own the b_ptr.
+ ZZZ
if isinstance(buf, StringBuffer):
py_buf.c_b_base = lltype.nullptr(PyObject.TO)
py_buf.c_b_ptr = rffi.cast(rffi.VOIDP, rffi.str2charp(buf.value))
diff --git a/pypy/module/cpyext/cdatetime.py b/pypy/module/cpyext/cdatetime.py
--- a/pypy/module/cpyext/cdatetime.py
+++ b/pypy/module/cpyext/cdatetime.py
@@ -1,5 +1,5 @@
from rpython.rtyper.lltypesystem import rffi, lltype
-from pypy.module.cpyext.pyobject import PyObject, make_ref
+from pypy.module.cpyext.pyobject import PyObject, get_pyobj_and_incref
from pypy.module.cpyext.api import (cpython_api, CANNOT_FAIL, cpython_struct,
PyObjectFields)
from pypy.module.cpyext.import_ import PyImport_Import
@@ -26,19 +26,19 @@
w_type = space.getattr(w_datetime, space.wrap("date"))
datetimeAPI.c_DateType = rffi.cast(
- PyTypeObjectPtr, make_ref(space, w_type))
+ PyTypeObjectPtr, get_pyobj_and_incref(space, w_type))
w_type = space.getattr(w_datetime, space.wrap("datetime"))
datetimeAPI.c_DateTimeType = rffi.cast(
- PyTypeObjectPtr, make_ref(space, w_type))
+ PyTypeObjectPtr, get_pyobj_and_incref(space, w_type))
w_type = space.getattr(w_datetime, space.wrap("time"))
datetimeAPI.c_TimeType = rffi.cast(
- PyTypeObjectPtr, make_ref(space, w_type))
+ PyTypeObjectPtr, get_pyobj_and_incref(space, w_type))
w_type = space.getattr(w_datetime, space.wrap("timedelta"))
datetimeAPI.c_DeltaType = rffi.cast(
- PyTypeObjectPtr, make_ref(space, w_type))
+ PyTypeObjectPtr, get_pyobj_and_incref(space, w_type))
return datetimeAPI
diff --git a/pypy/module/cpyext/classobject.py
b/pypy/module/cpyext/classobject.py
--- a/pypy/module/cpyext/classobject.py
+++ b/pypy/module/cpyext/classobject.py
@@ -2,7 +2,7 @@
from pypy.module.cpyext.api import (
PyObjectFields, CANNOT_FAIL,
cpython_api, bootstrap_function, cpython_struct, build_type_checkers)
-from pypy.module.cpyext.pyobject import PyObject, make_ref, from_ref,
Py_DecRef, make_typedescr
+from pypy.module.cpyext.pyobject import PyObject, Py_DecRef, make_typedescr
from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
from pypy.module.__builtin__.interp_classobj import W_ClassObject,
W_InstanceObject
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,10 +2,11 @@
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, borrow_from
+from pypy.module.cpyext.pyobject import PyObject, PyObjectP
from pypy.module.cpyext.pyobject import RefcountState
from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
from pypy.interpreter.error import OperationError
+from pypy.objspace.std.dictmultiobject import W_DictMultiObject
from rpython.rlib.objectmodel import specialize
@cpython_api([], PyObject)
@@ -16,68 +17,65 @@
@cpython_api([PyObject, PyObject], PyObject, error=CANNOT_FAIL)
def PyDict_GetItem(space, w_dict, w_key):
- try:
- w_res = space.getitem(w_dict, w_key)
- except:
- return None
- return borrow_from(w_dict, w_res)
+ if not isinstance(w_dict, W_DictMultiObject):
+ w_res = None
+ else:
+ w_res = w_dict.getitem(w_key) # possibly None
+ # borrowed result. assumes that the dict *values* are always strongly
+ # referenced from inside the W_DictMultiObject.
+ return as_xpyobj(space, w_res)
@cpython_api([PyObject, PyObject, PyObject], rffi.INT_real, error=-1)
def PyDict_SetItem(space, w_dict, w_key, w_obj):
- if PyDict_Check(space, w_dict):
- space.setitem(w_dict, w_key, w_obj)
- return 0
- else:
+ if not isinstance(w_dict, W_DictMultiObject):
PyErr_BadInternalCall(space)
+ w_dict.setitem(w_key, w_obj)
+ return 0
@cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
def PyDict_DelItem(space, w_dict, w_key):
- if PyDict_Check(space, w_dict):
- space.delitem(w_dict, w_key)
- return 0
- else:
+ if not isinstance(w_dict, W_DictMultiObject):
PyErr_BadInternalCall(space)
+ w_dict.delitem(w_key)
+ return 0
@cpython_api([PyObject, CONST_STRING, PyObject], rffi.INT_real, error=-1)
def PyDict_SetItemString(space, w_dict, key_ptr, w_obj):
- if PyDict_Check(space, w_dict):
- key = rffi.charp2str(key_ptr)
- space.setitem_str(w_dict, key, w_obj)
- return 0
- else:
+ if not isinstance(w_dict, W_DictMultiObject):
PyErr_BadInternalCall(space)
+ key = rffi.charp2str(key_ptr)
+ w_dict.setitem_str(key, w_obj)
+ return 0
@cpython_api([PyObject, CONST_STRING], PyObject, error=CANNOT_FAIL)
def PyDict_GetItemString(space, w_dict, key):
"""This is the same as PyDict_GetItem(), but key is specified as a
char*, rather than a PyObject*."""
- try:
+ if not isinstance(w_dict, W_DictMultiObject):
+ w_res = None
+ else:
w_res = space.finditem_str(w_dict, rffi.charp2str(key))
- except:
- w_res = None
- if w_res is None:
- return None
- return borrow_from(w_dict, w_res)
+ # borrowed result, possibly None
+ return as_xpyobj(space, w_res)
@cpython_api([PyObject, rffi.CCHARP], rffi.INT_real, error=-1)
def PyDict_DelItemString(space, w_dict, key_ptr):
"""Remove the entry in dictionary p which has a key specified by the string
key. Return 0 on success or -1 on failure."""
- if PyDict_Check(space, w_dict):
- key = rffi.charp2str(key_ptr)
- # our dicts dont have a standardized interface, so we need
- # to go through the space
- space.delitem(w_dict, space.wrap(key))
- return 0
- else:
+ if not isinstance(w_dict, W_DictMultiObject):
PyErr_BadInternalCall(space)
+ key = rffi.charp2str(key_ptr)
+ w_dict.delitem(space.wrap(key))
+ return 0
@cpython_api([PyObject], Py_ssize_t, error=-1)
def PyDict_Size(space, w_obj):
"""
Return the number of items in the dictionary. This is equivalent to
len(p) on a dictionary."""
- return space.len_w(w_obj)
+ if not isinstance(w_dict, W_DictMultiObject):
+ PyErr_BadInternalCall(space)
+ return space.wrap(w_dict.length())
@cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
def PyDict_Contains(space, w_obj, w_value):
@@ -173,6 +171,7 @@
# Note: this 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
try:
w_iter = space.call_method(space.w_dict, "iteritems", w_dict)
diff --git a/pypy/module/cpyext/eval.py b/pypy/module/cpyext/eval.py
--- a/pypy/module/cpyext/eval.py
+++ b/pypy/module/cpyext/eval.py
@@ -4,7 +4,7 @@
from pypy.module.cpyext.api import (
cpython_api, CANNOT_FAIL, CONST_STRING, FILEP, fread, feof, Py_ssize_tP,
cpython_struct, is_valid_fp)
-from pypy.module.cpyext.pyobject import PyObject, borrow_from
+from pypy.module.cpyext.pyobject import PyObject, as_pyobj, as_xpyobj
from pypy.module.cpyext.pyerrors import PyErr_SetFromErrno
from pypy.module.cpyext.funcobject import PyCodeObject
from pypy.module.__builtin__ import compiling
@@ -36,7 +36,7 @@
w_builtins = w_builtins.getdict(space)
else:
w_builtins = space.builtin.getdict(space)
- return borrow_from(None, w_builtins)
+ return as_pyobj(space, w_builtins) # borrowed
@cpython_api([], PyObject, error=CANNOT_FAIL)
def PyEval_GetLocals(space):
@@ -44,8 +44,10 @@
frame, or NULL if no frame is currently executing."""
caller = space.getexecutioncontext().gettopframe_nohidden()
if caller is None:
- return None
- return borrow_from(None, caller.getdictscope())
+ w_res = None
+ else:
+ w_res = caller.getdictscope()
+ return as_xpyobj(space, w_res) # borrowed
@cpython_api([], PyObject, error=CANNOT_FAIL)
def PyEval_GetGlobals(space):
@@ -53,8 +55,10 @@
frame, or NULL if no frame is currently executing."""
caller = space.getexecutioncontext().gettopframe_nohidden()
if caller is None:
- return None
- return borrow_from(None, caller.w_globals)
+ w_res = None
+ else:
+ w_res = caller.w_globals
+ return as_xpyobj(space, w_res) # borrowed
@cpython_api([PyCodeObject, PyObject, PyObject], PyObject)
def PyEval_EvalCode(space, w_code, w_globals, w_locals):
diff --git a/pypy/module/cpyext/frameobject.py
b/pypy/module/cpyext/frameobject.py
--- a/pypy/module/cpyext/frameobject.py
+++ b/pypy/module/cpyext/frameobject.py
@@ -3,7 +3,7 @@
cpython_api, bootstrap_function, PyObjectFields, cpython_struct,
CANNOT_FAIL)
from pypy.module.cpyext.pyobject import (
- PyObject, Py_DecRef, make_ref, from_ref, track_reference,
+ PyObject, Py_DecRef, track_reference, get_pyobj_and_xincref,
make_typedescr, get_typedescr)
from pypy.module.cpyext.state import State
from pypy.module.cpyext.pystate import PyThreadState
@@ -33,6 +33,7 @@
"Fills a newly allocated PyFrameObject with a frame object"
frame = space.interp_w(PyFrame, w_obj)
py_frame = rffi.cast(PyFrameObject, py_obj)
+ ZZZ
py_frame.c_f_code = rffi.cast(PyCodeObject, make_ref(space, frame.pycode))
py_frame.c_f_globals = make_ref(space, frame.w_globals)
rffi.setintfield(py_frame, 'c_f_lineno', frame.getorcreatedebug().f_lineno)
@@ -53,6 +54,7 @@
"""
py_frame = rffi.cast(PyFrameObject, py_obj)
py_code = rffi.cast(PyObject, py_frame.c_f_code)
+ ZZZ
w_code = from_ref(space, py_code)
code = space.interp_w(PyCode, w_code)
w_globals = from_ref(space, py_frame.c_f_globals)
@@ -70,8 +72,9 @@
py_obj = typedescr.allocate(space, space.gettypeobject(PyFrame.typedef))
py_frame = rffi.cast(PyFrameObject, py_obj)
space.interp_w(PyCode, w_code) # sanity check
- py_frame.c_f_code = rffi.cast(PyCodeObject, make_ref(space, w_code))
- py_frame.c_f_globals = make_ref(space, w_globals)
+ py_frame.c_f_code = rffi.cast(PyCodeObject,
+ get_pyobj_and_xincref(space, w_code))
+ py_frame.c_f_globals = get_pyobj_and_xincref(space, w_globals)
return py_frame
@cpython_api([PyFrameObject], rffi.INT_real, error=-1)
diff --git a/pypy/module/cpyext/funcobject.py b/pypy/module/cpyext/funcobject.py
--- a/pypy/module/cpyext/funcobject.py
+++ b/pypy/module/cpyext/funcobject.py
@@ -3,7 +3,7 @@
PyObjectFields, generic_cpy_call, CONST_STRING, CANNOT_FAIL, Py_ssize_t,
cpython_api, bootstrap_function, cpython_struct, build_type_checkers)
from pypy.module.cpyext.pyobject import (
- PyObject, make_ref, from_ref, Py_DecRef, make_typedescr, borrow_from)
+ PyObject, Py_DecRef, make_typedescr, as_pyobj, as_xpyobj)
from rpython.rlib.unroll import unrolling_iterable
from pypy.interpreter.error import OperationError
from pypy.interpreter.function import Function, Method
@@ -51,6 +51,7 @@
PyCode_Check, PyCode_CheckExact = build_type_checkers("Code", PyCode)
def function_attach(space, py_obj, w_obj):
+ ZZZ
py_func = rffi.cast(PyFunctionObject, py_obj)
assert isinstance(w_obj, Function)
py_func.c_func_name = make_ref(space, space.wrap(w_obj.name))
@@ -63,6 +64,7 @@
PyObject_dealloc(space, py_obj)
def code_attach(space, py_obj, w_obj):
+ ZZZ
py_code = rffi.cast(PyCodeObject, py_obj)
assert isinstance(w_obj, PyCode)
py_code.c_co_name = make_ref(space, space.wrap(w_obj.co_name))
@@ -84,8 +86,7 @@
def PyFunction_GetCode(space, w_func):
"""Return the code object associated with the function object op."""
func = space.interp_w(Function, w_func)
- w_code = space.wrap(func.code)
- return borrow_from(w_func, w_code)
+ return as_pyobj(space, func.code) # borrowed
@cpython_api([PyObject, PyObject, PyObject], PyObject)
def PyMethod_New(space, w_func, w_self, w_cls):
@@ -100,21 +101,21 @@
def PyMethod_Function(space, w_method):
"""Return the function object associated with the method meth."""
assert isinstance(w_method, Method)
- return borrow_from(w_method, w_method.w_function)
+ return as_pyobj(space, w_method.w_function) # borrowed
@cpython_api([PyObject], PyObject)
def PyMethod_Self(space, w_method):
"""Return the instance associated with the method meth if it is bound,
otherwise return NULL."""
assert isinstance(w_method, Method)
- return borrow_from(w_method, w_method.w_instance)
+ return as_xpyobj(space, w_method.w_instance) # borrowed
@cpython_api([PyObject], PyObject)
def PyMethod_Class(space, w_method):
"""Return the class object from which the method meth was created; if this
was
created from an instance, it will be the class of the instance."""
assert isinstance(w_method, Method)
- return borrow_from(w_method, w_method.w_class)
+ return as_pyobj(space, w_method.w_class) # borrowed
def unwrap_list_of_strings(space, w_list):
return [space.str_w(w_item) for w_item in space.fixedview(w_list)]
diff --git a/pypy/module/cpyext/import_.py b/pypy/module/cpyext/import_.py
--- a/pypy/module/cpyext/import_.py
+++ b/pypy/module/cpyext/import_.py
@@ -1,7 +1,7 @@
from pypy.interpreter import module
from pypy.module.cpyext.api import (
generic_cpy_call, cpython_api, PyObject, CONST_STRING)
-from pypy.module.cpyext.pyobject import borrow_from
+from pypy.module.cpyext.pyobject import as_pyobj
from rpython.rtyper.lltypesystem import lltype, rffi
from pypy.interpreter.error import OperationError
from pypy.interpreter.module import Module
@@ -74,15 +74,16 @@
w_mod = check_sys_modules_w(space, modulename)
if not w_mod or space.is_w(w_mod, space.w_None):
w_mod = Module(space, space.wrap(modulename))
- XXX - "insert it into sys.modules!"
- return borrow_from(None, w_mod)
+ space.setitem(space.sys.get('modules'), space.wrap(modulename), w_mod)
+ # return a borrowed ref --- assumes one copy in sys.modules
+ return as_pyobj(space, w_mod)
@cpython_api([], PyObject)
def PyImport_GetModuleDict(space):
"""Return the dictionary used for the module administration (a.k.a.
sys.modules). Note that this is a per-interpreter variable."""
w_modulesDict = space.sys.get('modules')
- return borrow_from(None, w_modulesDict)
+ return as_pyobj(space, w_modulesDict) # borrowed ref
@cpython_api([rffi.CCHARP, PyObject], PyObject)
def PyImport_ExecCodeModule(space, name, w_code):
diff --git a/pypy/module/cpyext/listobject.py b/pypy/module/cpyext/listobject.py
--- a/pypy/module/cpyext/listobject.py
+++ b/pypy/module/cpyext/listobject.py
@@ -3,7 +3,7 @@
from pypy.module.cpyext.api import (cpython_api, CANNOT_FAIL, Py_ssize_t,
build_type_checkers)
from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
-from pypy.module.cpyext.pyobject import Py_DecRef, PyObject, borrow_from
+from pypy.module.cpyext.pyobject import Py_DecRef, PyObject, as_pyobj
from pypy.objspace.std.listobject import W_ListObject
from pypy.interpreter.error import OperationError
@@ -49,8 +49,9 @@
if index < 0 or index >= w_list.length():
raise OperationError(space.w_IndexError, space.wrap(
"list index out of range"))
- w_item = w_list.getitem(index)
- return borrow_from(w_list, w_item)
+ # force the object strategy: it ensures a borrowed result stays around
+ w_list.ensure_object_strategy()
+ return as_pyobj(space, w_list.getitem(index))
@cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
@@ -77,14 +78,14 @@
@cpython_api([PyObject], Py_ssize_t, error=-1)
-def PyList_Size(space, ref):
+def PyList_Size(space, w_list):
"""Return the length of the list object in list; this is equivalent to
len(list) on a list object.
"""
- if not PyList_Check(space, ref):
+ if not isinstance(w_list, W_ListObject):
raise OperationError(space.w_TypeError,
space.wrap("expected list object"))
- return PyList_GET_SIZE(space, ref)
+ return w_list.length()
@cpython_api([PyObject], PyObject)
def PyList_AsTuple(space, w_list):
diff --git a/pypy/module/cpyext/methodobject.py
b/pypy/module/cpyext/methodobject.py
--- a/pypy/module/cpyext/methodobject.py
+++ b/pypy/module/cpyext/methodobject.py
@@ -12,7 +12,7 @@
METH_STATIC, METH_VARARGS, PyObject, PyObjectFields, bootstrap_function,
build_type_checkers, cpython_api, cpython_struct, generic_cpy_call)
from pypy.module.cpyext.pyobject import (
- Py_DecRef, from_pyobj, make_ref, make_typedescr)
+ Py_DecRef, from_pyobj, make_typedescr)
PyCFunction_typedef = rffi.COpaquePtr(typedef='PyCFunction')
PyCFunction = lltype.Ptr(lltype.FuncType([PyObject, PyObject], PyObject))
diff --git a/pypy/module/cpyext/number.py b/pypy/module/cpyext/number.py
--- a/pypy/module/cpyext/number.py
+++ b/pypy/module/cpyext/number.py
@@ -1,6 +1,6 @@
from pypy.interpreter.error import OperationError
from pypy.module.cpyext.api import cpython_api, CANNOT_FAIL, Py_ssize_t
-from pypy.module.cpyext.pyobject import PyObject, PyObjectP, make_ref,
Py_DecRef
+from pypy.module.cpyext.pyobject import PyObject, PyObjectP, Py_DecRef
from pypy.module.cpyext.pyobject import from_pyobj, get_pyobj_and_incref
from rpython.rtyper.lltypesystem import rffi, lltype
from rpython.tool.sourcetools import func_with_new_name
diff --git a/pypy/module/cpyext/pyerrors.py b/pypy/module/cpyext/pyerrors.py
--- a/pypy/module/cpyext/pyerrors.py
+++ b/pypy/module/cpyext/pyerrors.py
@@ -6,7 +6,8 @@
from pypy.module.cpyext.api import cpython_api, CANNOT_FAIL, CONST_STRING
from pypy.module.exceptions.interp_exceptions import W_RuntimeWarning
from pypy.module.cpyext.pyobject import (
- PyObject, PyObjectP, make_ref, from_ref, Py_DecRef, as_pyobj)
+ PyObject, PyObjectP, Py_DecRef, as_pyobj, get_pyobj_and_incref,
+ get_w_obj_and_decref, from_pyobj, get_pyobj_and_xincref)
from pypy.module.cpyext.state import State
from pypy.module.cpyext.import_ import PyImport_Import
from rpython.rlib import rposix, jit
@@ -56,9 +57,9 @@
state = space.fromcache(State)
operror = state.clear_exception()
if operror:
- ptype[0] = make_ref(space, operror.w_type)
- pvalue[0] = make_ref(space, operror.get_w_value(space))
- ptraceback[0] = make_ref(space, space.wrap(operror.get_traceback()))
+ ptype[0] = get_pyobj_and_incref(space, operror.w_type)
+ pvalue[0] = get_pyobj_and_incref(space, operror.get_w_value(space))
+ ptraceback[0] = get_pyobj_and_xincref(space, operror.get_traceback())
else:
ptype[0] = lltype.nullptr(PyObject.TO)
pvalue[0] = lltype.nullptr(PyObject.TO)
@@ -95,13 +96,11 @@
not an instance of the same class. This function can be used to
instantiate
the class in that case. If the values are already normalized, nothing
happens.
The delayed normalization is implemented to improve performance."""
- operr = OperationError(from_ref(space, exc_p[0]),
- from_ref(space, val_p[0]))
+ operr = OperationError(get_w_obj_and_decref(space, exc_p[0]),
+ get_w_obj_and_decref(space, val_p[0]))
operr.normalize_exception(space)
- Py_DecRef(space, exc_p[0])
- Py_DecRef(space, val_p[0])
- exc_p[0] = make_ref(space, operr.w_type)
- val_p[0] = make_ref(space, operr.get_w_value(space))
+ exc_p[0] = get_pyobj_and_incref(space, operr.w_type)
+ val_p[0] = get_pyobj_and_incref(space, operr.get_w_value(space))
@cpython_api([], rffi.INT_real, error=0)
def PyErr_BadArgument(space):
@@ -303,10 +302,8 @@
PyErr_PrintEx(space, 1)
@cpython_api([PyObject, PyObject, PyObject], lltype.Void)
-def PyErr_Display(space, w_type, w_value, tb):
- if tb:
- w_tb = from_ref(space, tb)
- else:
+def PyErr_Display(space, w_type, w_value, w_tb):
+ if w_tb is None:
w_tb = space.w_None
try:
space.call_function(space.sys.get("excepthook"),
@@ -372,9 +369,9 @@
ec = space.getexecutioncontext()
operror = ec.sys_exc_info()
if operror:
- ptype[0] = make_ref(space, operror.w_type)
- pvalue[0] = make_ref(space, operror.get_w_value(space))
- ptraceback[0] = make_ref(space, space.wrap(operror.get_traceback()))
+ ptype[0] = get_pyobj_and_incref(space, operror.w_type)
+ pvalue[0] = get_pyobj_and_incref(space, operror.get_w_value(space))
+ ptraceback[0] = get_pyobj_and_xincref(space, operror.get_traceback())
else:
ptype[0] = lltype.nullptr(PyObject.TO)
pvalue[0] = lltype.nullptr(PyObject.TO)
diff --git a/pypy/module/cpyext/pyfile.py b/pypy/module/cpyext/pyfile.py
--- a/pypy/module/cpyext/pyfile.py
+++ b/pypy/module/cpyext/pyfile.py
@@ -1,7 +1,7 @@
from rpython.rtyper.lltypesystem import rffi, lltype
from pypy.module.cpyext.api import (
cpython_api, CANNOT_FAIL, CONST_STRING, FILEP, build_type_checkers)
-from pypy.module.cpyext.pyobject import PyObject, borrow_from
+from pypy.module.cpyext.pyobject import PyObject, as_pyobj
from pypy.module.cpyext.object import Py_PRINT_RAW
from pypy.interpreter.error import OperationError
from pypy.module._file.interp_file import W_File
@@ -83,7 +83,8 @@
@cpython_api([PyObject], PyObject)
def PyFile_Name(space, w_p):
"""Return the name of the file specified by p as a string object."""
- return borrow_from(w_p, space.getattr(w_p, space.wrap("name")))
+ w_name = space.getattr(w_p, space.wrap("name"))
+ return as_pyobj(space, w_name) # borrowed result
@cpython_api([PyObject, rffi.INT_real], rffi.INT_real, error=CANNOT_FAIL)
def PyFile_SoftSpace(space, w_p, newflag):
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
@@ -461,35 +461,6 @@
# ----------
-def make_ref(space, w_obj):
- ZZZ
-
-def from_ref(space, ref):
- """
- Finds the interpreter object corresponding to the given reference. If the
- object is not yet realized (see stringobject.py), creates it.
- """
- assert lltype.typeOf(ref) == PyObject
- ZZZ
- if not ref:
- return None
- state = space.fromcache(RefcountState)
- ptr = rffi.cast(ADDR, ref)
-
- try:
- return state.py_objects_r2w[ptr]
- except KeyError:
- pass
-
- # This reference is not yet a real interpreter object.
- # Realize it.
- ref_type = rffi.cast(PyObject, ref.c_ob_type)
- if ref_type == ref: # recursion!
- raise InvalidPointerException(str(ref))
- w_type = from_ref(space, ref_type)
- assert isinstance(w_type, W_TypeObject)
- return get_typedescr(w_type.instancetypedef).realize(space, ref)
-
@cpython_api([PyObject], lltype.Void)
def Py_IncRef(space, obj):
@@ -518,51 +489,6 @@
#___________________________________________________________
-# Support for borrowed references
-
-def make_borrowed_ref(space, w_container, w_borrowed):
- """
- Create a borrowed reference, which will live as long as the container
- has a living reference (as a PyObject!)
- """
- ZZZ
- if w_borrowed is None:
- return lltype.nullptr(PyObject.TO)
-
- state = space.fromcache(RefcountState)
- return state.make_borrowed(w_container, w_borrowed)
-
-class Reference:
- def __init__(self, pyobj):
- ZZZ
- assert not isinstance(pyobj, W_Root)
- self.pyobj = pyobj
-
- def get_ref(self, space):
- return self.pyobj
-
- def get_wrapped(self, space):
- return from_ref(space, self.pyobj)
-
-class BorrowPair(Reference):
- """
- Delays the creation of a borrowed reference.
- """
- def __init__(self, w_container, w_borrowed):
- ZZZ
- self.w_container = w_container
- self.w_borrowed = w_borrowed
-
- def get_ref(self, space):
- return make_borrowed_ref(space, self.w_container, self.w_borrowed)
-
- def get_wrapped(self, space):
- return self.w_borrowed
-
-def borrow_from(container, borrowed):
- return BorrowPair(container, borrowed)
-
-#___________________________________________________________
@cpython_api([rffi.VOIDP], lltype.Signed, error=CANNOT_FAIL)
def _Py_HashPointer(space, ptr):
diff --git a/pypy/module/cpyext/pypyintf.py b/pypy/module/cpyext/pypyintf.py
deleted file mode 100644
--- a/pypy/module/cpyext/pypyintf.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from pypy.module.cpyext.api import cpython_api
-from pypy.module.cpyext.pyobject import PyObject, borrow_from
-
-
-@cpython_api([PyObject, PyObject], PyObject)
-def PyPy_Borrow(space, w_parentobj, w_obj):
- """Returns a borrowed reference to 'obj', borrowing from the 'parentobj'.
- """
- return borrow_from(w_parentobj, w_obj)
diff --git a/pypy/module/cpyext/pystate.py b/pypy/module/cpyext/pystate.py
--- a/pypy/module/cpyext/pystate.py
+++ b/pypy/module/cpyext/pystate.py
@@ -1,6 +1,7 @@
from pypy.module.cpyext.api import (
cpython_api, generic_cpy_call, CANNOT_FAIL, CConfig, cpython_struct)
-from pypy.module.cpyext.pyobject import PyObject, Py_DecRef, make_ref, from_ref
+from pypy.module.cpyext.pyobject import (
+ PyObject, Py_DecRef, get_pyobj_and_incref)
from rpython.rtyper.lltypesystem import rffi, lltype
from rpython.rlib import rthread
@@ -112,7 +113,7 @@
capsule = ThreadStateCapsule(space)
ts = capsule.memory
ts.c_interp = self.interpreter_state
- ts.c_dict = make_ref(space, space.newdict())
+ ts.c_dict = get_pyobj_and_incref(space, space.newdict())
return capsule
diff --git a/pypy/module/cpyext/pytraceback.py
b/pypy/module/cpyext/pytraceback.py
--- a/pypy/module/cpyext/pytraceback.py
+++ b/pypy/module/cpyext/pytraceback.py
@@ -3,7 +3,7 @@
PyObjectFields, generic_cpy_call, CONST_STRING, CANNOT_FAIL, Py_ssize_t,
cpython_api, bootstrap_function, cpython_struct, build_type_checkers)
from pypy.module.cpyext.pyobject import (
- PyObject, make_ref, from_ref, Py_DecRef, make_typedescr, borrow_from)
+ PyObject, Py_DecRef, make_typedescr)
from pypy.module.cpyext.frameobject import PyFrameObject
from rpython.rlib.unroll import unrolling_iterable
from pypy.interpreter.error import OperationError
@@ -36,6 +36,7 @@
w_next_traceback = None
else:
w_next_traceback = space.wrap(traceback.next)
+ ZZZ
py_traceback.c_tb_next = rffi.cast(PyTracebackObject, make_ref(space,
w_next_traceback))
py_traceback.c_tb_frame = rffi.cast(PyFrameObject, make_ref(space,
space.wrap(traceback.frame)))
rffi.setintfield(py_traceback, 'c_tb_lasti', traceback.lasti)
diff --git a/pypy/module/cpyext/sequence.py b/pypy/module/cpyext/sequence.py
--- a/pypy/module/cpyext/sequence.py
+++ b/pypy/module/cpyext/sequence.py
@@ -2,7 +2,7 @@
from pypy.interpreter.error import OperationError, oefmt
from pypy.module.cpyext.api import (
cpython_api, CANNOT_FAIL, CONST_STRING, Py_ssize_t)
-from pypy.module.cpyext.pyobject import PyObject, borrow_from
+from pypy.module.cpyext.pyobject import PyObject, as_pyobj
from rpython.rtyper.lltypesystem import rffi, lltype
from pypy.objspace.std import listobject, tupleobject
@@ -56,11 +56,12 @@
PySequence_Fast(), o is not NULL, and that i is within bounds.
"""
if isinstance(w_obj, listobject.W_ListObject):
+ w_obj.ensure_object_strategy()
w_res = w_obj.getitem(index)
else:
assert isinstance(w_obj, tupleobject.W_TupleObject)
w_res = w_obj.wrappeditems[index]
- return borrow_from(w_obj, w_res)
+ return as_pyobj(space, w_res) # borrowed
@cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL)
def PySequence_Fast_GET_SIZE(space, w_obj):
diff --git a/pypy/module/cpyext/setobject.py b/pypy/module/cpyext/setobject.py
--- a/pypy/module/cpyext/setobject.py
+++ b/pypy/module/cpyext/setobject.py
@@ -2,8 +2,7 @@
from rpython.rtyper.lltypesystem import rffi, lltype
from pypy.module.cpyext.api import (cpython_api, Py_ssize_t, CANNOT_FAIL,
build_type_checkers)
-from pypy.module.cpyext.pyobject import (PyObject, PyObjectP, Py_DecRef,
- borrow_from, make_ref, from_ref)
+from pypy.module.cpyext.pyobject import PyObject, PyObjectP, Py_DecRef
from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
from pypy.objspace.std.setobject import W_SetObject, newset
diff --git a/pypy/module/cpyext/sliceobject.py
b/pypy/module/cpyext/sliceobject.py
--- a/pypy/module/cpyext/sliceobject.py
+++ b/pypy/module/cpyext/sliceobject.py
@@ -3,7 +3,7 @@
cpython_api, cpython_struct, bootstrap_function, build_type_checkers,
CANNOT_FAIL, Py_ssize_t, Py_ssize_tP, PyObjectFields)
from pypy.module.cpyext.pyobject import (
- Py_DecRef, PyObject, make_ref, make_typedescr)
+ Py_DecRef, PyObject, make_typedescr)
from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
from pypy.interpreter.error import OperationError
from pypy.objspace.std.sliceobject import W_SliceObject
@@ -30,6 +30,7 @@
Fills a newly allocated PySliceObject with the given slice object. The
fields must not be modified.
"""
+ ZZZ
py_slice = rffi.cast(PySliceObject, py_obj)
assert isinstance(w_obj, W_SliceObject)
py_slice.c_start = make_ref(space, w_obj.w_start)
diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -11,7 +11,7 @@
ssizessizeargfunc, ssizeobjargproc, iternextfunc, initproc, richcmpfunc,
cmpfunc, hashfunc, descrgetfunc, descrsetfunc, objobjproc, objobjargproc,
readbufferproc)
-from pypy.module.cpyext.pyobject import from_ref
+from pypy.module.cpyext.pyobject import from_pyobj
from pypy.module.cpyext.pyerrors import PyErr_Occurred
from pypy.module.cpyext.state import State
from pypy.interpreter.error import OperationError, oefmt
@@ -311,8 +311,7 @@
@cpython_api([PyTypeObjectPtr, PyObject, PyObject], PyObject, external=False)
def slot_tp_new(space, type, w_args, w_kwds):
from pypy.module.cpyext.tupleobject import PyTuple_Check
- pyo = rffi.cast(PyObject, type)
- w_type = from_ref(space, pyo)
+ w_type = from_pyobj(space, type)
w_func = space.getattr(w_type, space.wrap("__new__"))
assert PyTuple_Check(space, w_args)
args_w = [w_type] + space.fixedview(w_args)
diff --git a/pypy/module/cpyext/src/getargs.c b/pypy/module/cpyext/src/getargs.c
--- a/pypy/module/cpyext/src/getargs.c
+++ b/pypy/module/cpyext/src/getargs.c
@@ -442,7 +442,7 @@
strncpy(msgbuf, "is not retrievable", bufsize);
return msgbuf;
}
- PyPy_Borrow(arg, item);
+ //PyPy_Borrow(arg, item);
msg = convertitem(item, &format, p_va, flags, levels+1,
msgbuf, bufsize, freelist);
/* PySequence_GetItem calls tp->sq_item, which INCREFs */
diff --git a/pypy/module/cpyext/sysmodule.py b/pypy/module/cpyext/sysmodule.py
--- a/pypy/module/cpyext/sysmodule.py
+++ b/pypy/module/cpyext/sysmodule.py
@@ -1,7 +1,7 @@
from pypy.interpreter.error import OperationError
from rpython.rtyper.lltypesystem import rffi, lltype
from pypy.module.cpyext.api import CANNOT_FAIL, cpython_api, CONST_STRING
-from pypy.module.cpyext.pyobject import PyObject, borrow_from
+from pypy.module.cpyext.pyobject import PyObject, as_xpyobj
@cpython_api([CONST_STRING], PyObject, error=CANNOT_FAIL)
def PySys_GetObject(space, name):
@@ -10,7 +10,7 @@
name = rffi.charp2str(name)
w_dict = space.sys.getdict(space)
w_obj = space.finditem_str(w_dict, name)
- return borrow_from(None, w_obj)
+ return as_xpyobj(space, w_obj) # borrowed
@cpython_api([CONST_STRING, PyObject], rffi.INT_real, error=-1)
def PySys_SetObject(space, name, w_obj):
diff --git a/pypy/module/cpyext/test/test_borrow.py
b/pypy/module/cpyext/test/test_borrow.py
--- a/pypy/module/cpyext/test/test_borrow.py
+++ b/pypy/module/cpyext/test/test_borrow.py
@@ -1,20 +1,8 @@
import py
from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
from pypy.module.cpyext.test.test_api import BaseApiTest
-from pypy.module.cpyext.pyobject import make_ref, borrow_from, RefcountState
-class TestBorrowing(BaseApiTest):
- def test_borrowing(self, space, api):
- w_int = space.wrap(1)
- w_tuple = space.newtuple([w_int])
- api.Py_IncRef(w_tuple)
- one_pyo = borrow_from(w_tuple, w_int).get_ref(space)
- api.Py_DecRef(w_tuple)
- state = space.fromcache(RefcountState)
- state.print_refcounts()
- py.test.raises(AssertionError, api.Py_DecRef, one_pyo)
-
class AppTestBorrow(AppTestCpythonExtensionBase):
def test_tuple_borrowing(self):
module = self.import_extension('foo', [
@@ -76,4 +64,5 @@
])
wr = module.run()
# check that the set() object was deallocated
+ self.debug_collect()
assert wr() is None
diff --git a/pypy/module/cpyext/test/test_cpyext.py
b/pypy/module/cpyext/test/test_cpyext.py
--- a/pypy/module/cpyext/test/test_cpyext.py
+++ b/pypy/module/cpyext/test/test_cpyext.py
@@ -353,6 +353,7 @@
interp2app(record_imported_module))
self.w_here = self.space.wrap(
str(py.path.local(pypydir)) + '/module/cpyext/test/')
+ self.w_debug_collect = self.space.wrap(interp2app(debug_collect))
# create the file lock before we count allocations
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
@@ -20,9 +20,9 @@
PyDescr_NewWrapper, PyCFunction_NewEx, PyCFunction_typedef)
from pypy.module.cpyext.modsupport import convert_method_defs
from pypy.module.cpyext.pyobject import (
- PyObject, make_ref, create_ref, get_typedescr, from_pyobj, as_pyobj,
+ PyObject, create_ref, get_typedescr, from_pyobj, as_pyobj,
setup_class_for_cpyext, get_pyobj_and_incref, get_pyobj_and_xincref,
- track_reference, RefcountState, borrow_from, Py_DecRef, RRC_PERMANENT)
+ track_reference, RefcountState, Py_DecRef, RRC_PERMANENT)
from pypy.module.cpyext.slotdefs import (
slotdefs_for_tp_slots, slotdefs_for_wrappers, get_slot_tp_function)
from pypy.module.cpyext.state import State
@@ -376,6 +376,7 @@
def type_alloc(space, w_metatype):
+ ZZZ
metatype = rffi.cast(PyTypeObjectPtr, make_ref(space, w_metatype))
# Don't increase refcount for non-heaptypes
if metatype:
@@ -428,7 +429,7 @@
if pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE:
w_typename = space.getattr(w_type, space.wrap('__name__'))
heaptype = rffi.cast(PyHeapTypeObject, pto)
- heaptype.c_ht_name = make_ref(space, w_typename)
+ heaptype.c_ht_name = get_pyobj_and_incref(space, w_typename)
from pypy.module.cpyext.stringobject import PyString_AsString
pto.c_tp_name = PyString_AsString(space, heaptype.c_ht_name)
else:
@@ -616,7 +617,9 @@
return None
name = space.str_w(w_name)
w_obj = w_type.lookup(name)
- return borrow_from(w_type, w_obj)
+ # return a borrowed ref. assumes lookup() returns already-referenced
+ # objs OR that the result will not be used for long
+ return as_pyobj(space, w_obj)
@cpython_api([PyTypeObjectPtr], lltype.Void)
def PyType_Modified(space, w_obj):
diff --git a/pypy/module/cpyext/typeobjectdefs.py
b/pypy/module/cpyext/typeobjectdefs.py
--- a/pypy/module/cpyext/typeobjectdefs.py
+++ b/pypy/module/cpyext/typeobjectdefs.py
@@ -3,7 +3,7 @@
from pypy.module.cpyext.api import (cpython_struct, Py_ssize_t, Py_ssize_tP,
PyVarObjectFields, PyTypeObject, PyTypeObjectPtr, FILEP,
Py_TPFLAGS_READYING, Py_TPFLAGS_READY, Py_TPFLAGS_HEAPTYPE)
-from pypy.module.cpyext.pyobject import PyObject, make_ref, from_ref
+from pypy.module.cpyext.pyobject import PyObject
from pypy.module.cpyext.modsupport import PyMethodDef
diff --git a/pypy/module/cpyext/unicodeobject.py
b/pypy/module/cpyext/unicodeobject.py
--- a/pypy/module/cpyext/unicodeobject.py
+++ b/pypy/module/cpyext/unicodeobject.py
@@ -7,8 +7,8 @@
CONST_WSTRING)
from pypy.module.cpyext.pyerrors import PyErr_BadArgument
from pypy.module.cpyext.pyobject import (
- PyObject, PyObjectP, Py_DecRef, make_ref, from_ref, track_reference,
- make_typedescr, get_typedescr)
+ PyObject, PyObjectP, Py_DecRef, track_reference, get_pyobj_and_incref,
+ make_typedescr, get_typedescr, from_pyobj)
from pypy.module.cpyext.stringobject import PyString_Check
from pypy.module.sys.interp_encoding import setdefaultencoding
from pypy.module._codecs.interp_codecs import CodecState
@@ -206,7 +206,7 @@
ref_unicode = rffi.cast(PyUnicodeObject, ref)
if not ref_unicode.c_buffer:
# Copy unicode buffer
- w_unicode = from_ref(space, ref)
+ w_unicode = from_pyobj(space, ref)
u = space.unicode_w(w_unicode)
ref_unicode.c_buffer = rffi.unicode2wcharp(u)
return ref_unicode.c_buffer
@@ -216,19 +216,18 @@
"""Return a read-only pointer to the Unicode object's internal Py_UNICODE
buffer, NULL if unicode is not a Unicode object."""
# Don't use PyUnicode_Check, it will realize the object :-(
- w_type = from_ref(space, rffi.cast(PyObject, ref.c_ob_type))
- if not space.is_true(space.issubtype(w_type, space.w_unicode)):
+ if not PyUnicode_Check(space, ref):
raise OperationError(space.w_TypeError,
space.wrap("expected unicode object"))
return PyUnicode_AS_UNICODE(space, ref)
@cpython_api([PyObject], Py_ssize_t, error=-1)
def PyUnicode_GetSize(space, ref):
- if from_ref(space, rffi.cast(PyObject, ref.c_ob_type)) is space.w_unicode:
+ if PyUnicode_Check(space, ref):
ref = rffi.cast(PyUnicodeObject, ref)
return ref.c_size
else:
- w_obj = from_ref(space, ref)
+ w_obj = from_pyobj(space, ref)
return space.len_w(w_obj)
@cpython_api([PyUnicodeObject, rffi.CWCHARP, Py_ssize_t], Py_ssize_t, error=-1)
@@ -330,7 +329,7 @@
is NULL."""
if wchar_p:
s = rffi.wcharpsize2unicode(wchar_p, length)
- return make_ref(space, space.wrap(s))
+ return get_pyobj_and_incref(space, space.wrap(s))
else:
return rffi.cast(PyObject, new_empty_unicode(space, length))
@@ -424,7 +423,7 @@
NULL, the return value might be a shared object. Therefore, modification of
the resulting Unicode object is only allowed when u is NULL."""
if s:
- return make_ref(space, PyUnicode_DecodeUTF8(
+ return get_pyobj_and_incref(space, PyUnicode_DecodeUTF8(
space, s, size, lltype.nullptr(rffi.CCHARP.TO)))
else:
return rffi.cast(PyObject, new_empty_unicode(space, size))
diff --git a/pypy/module/cpyext/weakrefobject.py
b/pypy/module/cpyext/weakrefobject.py
--- a/pypy/module/cpyext/weakrefobject.py
+++ b/pypy/module/cpyext/weakrefobject.py
@@ -1,5 +1,5 @@
from pypy.module.cpyext.api import cpython_api
-from pypy.module.cpyext.pyobject import PyObject, borrow_from
+from pypy.module.cpyext.pyobject import PyObject, as_xpyobj
from pypy.module._weakref.interp__weakref import W_Weakref, proxy
@cpython_api([PyObject, PyObject], PyObject)
@@ -42,12 +42,12 @@
"""Similar to PyWeakref_GetObject(), but implemented as a macro that does
no
error checking.
"""
- return borrow_from(w_ref, space.call_function(w_ref))
+ return as_xpyobj(space.call_function(w_ref)) # borrowed
@cpython_api([PyObject], PyObject)
def PyWeakref_LockObject(space, w_ref):
"""Return the referenced object from a weak reference. If the referent is
no longer live, returns None. This function returns a new reference.
+ (This is a PyPy extension!)
"""
return space.call_function(w_ref)
-
diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -216,6 +216,11 @@
items = [space.unwrap(w_item) for w_item in w_list.getitems()]
return list(items)
+ def ensure_object_strategy(self): # for cpyext
+ object_strategy = self.space.fromcache(ObjectListStrategy)
+ if self.strategy is not object_strategy:
+ self.switch_to_object_strategy()
+
def switch_to_object_strategy(self):
list_w = self.getitems()
object_strategy = self.space.fromcache(ObjectListStrategy)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit