Merged revisions 79060 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r79060 | collin.winter | 2010-03-18 14:54:01 -0700 (Thu, 18 Mar 2010) | 4 lines

  Add support for weak references to code objects. This will be used by an optimization in the incoming Python 3 JIT.

  Patch by Reid Kleckner!
........
This commit is contained in:
Collin Winter 2010-03-18 22:46:40 +00:00
parent b3a482962d
commit 4222e9c07c
6 changed files with 39 additions and 6 deletions

View File

@ -59,10 +59,10 @@ is exposed by the :mod:`weakref` module for the benefit of advanced uses.
Not all objects can be weakly referenced; those objects which can include class Not all objects can be weakly referenced; those objects which can include class
instances, functions written in Python (but not in C), instance methods, sets, instances, functions written in Python (but not in C), instance methods, sets,
frozensets, file objects, :term:`generator`\s, type objects, sockets, arrays, frozensets, file objects, :term:`generator`\s, type objects, sockets, arrays,
deques, and regular expression pattern objects. deques, regular expression pattern objects, and code objects.
.. versionchanged:: 3.2 .. versionchanged:: 3.2
Added support for thread.lock and threading.Lock. Added support for thread.lock, threading.Lock, and code objects.
Several built-in types such as :class:`list` and :class:`dict` do not directly Several built-in types such as :class:`list` and :class:`dict` do not directly
support weak references but can add support through subclassing:: support weak references but can add support through subclassing::

View File

@ -27,6 +27,7 @@ typedef struct {
PyObject *co_lnotab; /* string (encoding addr<->lineno mapping) See PyObject *co_lnotab; /* string (encoding addr<->lineno mapping) See
Objects/lnotab_notes.txt for details. */ Objects/lnotab_notes.txt for details. */
void *co_zombieframe; /* for optimization only (see frameobject.c) */ void *co_zombieframe; /* for optimization only (see frameobject.c) */
PyObject *co_weakreflist; /* to support weakrefs to code objects */
} PyCodeObject; } PyCodeObject;
/* Masks for co_flags above */ /* Masks for co_flags above */

View File

@ -103,8 +103,10 @@ consts: ('None',)
""" """
import unittest import unittest
import weakref
import _testcapi import _testcapi
def consts(t): def consts(t):
"""Yield a doctest-safe sequence of object reprs.""" """Yield a doctest-safe sequence of object reprs."""
for elt in t: for elt in t:
@ -131,12 +133,37 @@ class CodeTest(unittest.TestCase):
self.assertEquals(co.co_firstlineno, 15) self.assertEquals(co.co_firstlineno, 15)
class CodeWeakRefTest(unittest.TestCase):
def test_basic(self):
# Create a code object in a clean environment so that we know we have
# the only reference to it left.
namespace = {}
exec("def f(): pass", globals(), namespace)
f = namespace["f"]
del namespace
self.called = False
def callback(code):
self.called = True
# f is now the last reference to the function, and through it, the code
# object. While we hold it, check that we can create a weakref and
# deref it. Then delete it, and check that the callback gets called and
# the reference dies.
coderef = weakref.ref(f.__code__, callback)
self.assertTrue(bool(coderef()))
del f
self.assertFalse(bool(coderef()))
self.assertTrue(self.called)
def test_main(verbose=None): def test_main(verbose=None):
from test.support import run_doctest, run_unittest from test.support import run_doctest, run_unittest
from test import test_code from test import test_code
run_doctest(test_code, verbose) run_doctest(test_code, verbose)
run_unittest(CodeTest) run_unittest(CodeTest, CodeWeakRefTest)
if __name__ == '__main__': if __name__ == "__main__":
test_main() test_main()

View File

@ -588,7 +588,7 @@ class SizeofTest(unittest.TestCase):
return inner return inner
check(get_cell().__closure__[0], size(h + 'P')) check(get_cell().__closure__[0], size(h + 'P'))
# code # code
check(get_cell().__code__, size(h + '5i8Pi2P')) check(get_cell().__code__, size(h + '5i8Pi3P'))
# complex # complex
check(complex(0,1), size(h + '2d')) check(complex(0,1), size(h + '2d'))
# method_descriptor (descriptor object) # method_descriptor (descriptor object)

View File

@ -233,6 +233,8 @@ Core and Builtins
instances from being copied with copy.copy(), and bytes subclasses instances from being copied with copy.copy(), and bytes subclasses
from being pickled properly. from being pickled properly.
- Code objects now support weak references.
C-API C-API
----- -----

View File

@ -108,6 +108,7 @@ PyCode_New(int argcount, int kwonlyargcount,
Py_INCREF(lnotab); Py_INCREF(lnotab);
co->co_lnotab = lnotab; co->co_lnotab = lnotab;
co->co_zombieframe = NULL; co->co_zombieframe = NULL;
co->co_weakreflist = NULL;
} }
return co; return co;
} }
@ -331,6 +332,8 @@ code_dealloc(PyCodeObject *co)
Py_XDECREF(co->co_lnotab); Py_XDECREF(co->co_lnotab);
if (co->co_zombieframe != NULL) if (co->co_zombieframe != NULL)
PyObject_GC_Del(co->co_zombieframe); PyObject_GC_Del(co->co_zombieframe);
if (co->co_weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject*)co);
PyObject_DEL(co); PyObject_DEL(co);
} }
@ -462,7 +465,7 @@ PyTypeObject PyCode_Type = {
0, /* tp_traverse */ 0, /* tp_traverse */
0, /* tp_clear */ 0, /* tp_clear */
code_richcompare, /* tp_richcompare */ code_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */ offsetof(PyCodeObject, co_weakreflist), /* tp_weaklistoffset */
0, /* tp_iter */ 0, /* tp_iter */
0, /* tp_iternext */ 0, /* tp_iternext */
0, /* tp_methods */ 0, /* tp_methods */