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

Reply via email to