Skip to content

Commit 2c0a5f1

Browse files
committed
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! ........
1 parent 9241215 commit 2c0a5f1

6 files changed

Lines changed: 39 additions & 6 deletions

File tree

Doc/library/weakref.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,10 @@ is exposed by the :mod:`weakref` module for the benefit of advanced uses.
5959
Not all objects can be weakly referenced; those objects which can include class
6060
instances, functions written in Python (but not in C), instance methods, sets,
6161
frozensets, file objects, :term:`generator`\s, type objects, sockets, arrays,
62-
deques, and regular expression pattern objects.
62+
deques, regular expression pattern objects, and code objects.
6363

6464
.. versionchanged:: 3.2
65-
Added support for thread.lock and threading.Lock.
65+
Added support for thread.lock, threading.Lock, and code objects.
6666

6767
Several built-in types such as :class:`list` and :class:`dict` do not directly
6868
support weak references but can add support through subclassing::

Include/code.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ typedef struct {
2727
PyObject *co_lnotab; /* string (encoding addr<->lineno mapping) See
2828
Objects/lnotab_notes.txt for details. */
2929
void *co_zombieframe; /* for optimization only (see frameobject.c) */
30+
PyObject *co_weakreflist; /* to support weakrefs to code objects */
3031
} PyCodeObject;
3132

3233
/* Masks for co_flags above */

Lib/test/test_code.py

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,10 @@
103103
"""
104104

105105
import unittest
106+
import weakref
106107
import _testcapi
107108

109+
108110
def consts(t):
109111
"""Yield a doctest-safe sequence of object reprs."""
110112
for elt in t:
@@ -131,12 +133,37 @@ def test_newempty(self):
131133
self.assertEquals(co.co_firstlineno, 15)
132134

133135

136+
class CodeWeakRefTest(unittest.TestCase):
137+
138+
def test_basic(self):
139+
# Create a code object in a clean environment so that we know we have
140+
# the only reference to it left.
141+
namespace = {}
142+
exec("def f(): pass", globals(), namespace)
143+
f = namespace["f"]
144+
del namespace
145+
146+
self.called = False
147+
def callback(code):
148+
self.called = True
149+
150+
# f is now the last reference to the function, and through it, the code
151+
# object. While we hold it, check that we can create a weakref and
152+
# deref it. Then delete it, and check that the callback gets called and
153+
# the reference dies.
154+
coderef = weakref.ref(f.__code__, callback)
155+
self.assertTrue(bool(coderef()))
156+
del f
157+
self.assertFalse(bool(coderef()))
158+
self.assertTrue(self.called)
159+
160+
134161
def test_main(verbose=None):
135162
from test.support import run_doctest, run_unittest
136163
from test import test_code
137164
run_doctest(test_code, verbose)
138-
run_unittest(CodeTest)
165+
run_unittest(CodeTest, CodeWeakRefTest)
139166

140167

141-
if __name__ == '__main__':
168+
if __name__ == "__main__":
142169
test_main()

Lib/test/test_sys.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,7 @@ def inner():
588588
return inner
589589
check(get_cell().__closure__[0], size(h + 'P'))
590590
# code
591-
check(get_cell().__code__, size(h + '5i8Pi2P'))
591+
check(get_cell().__code__, size(h + '5i8Pi3P'))
592592
# complex
593593
check(complex(0,1), size(h + '2d'))
594594
# method_descriptor (descriptor object)

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,8 @@ Core and Builtins
233233
instances from being copied with copy.copy(), and bytes subclasses
234234
from being pickled properly.
235235

236+
- Code objects now support weak references.
237+
236238
C-API
237239
-----
238240

Objects/codeobject.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ PyCode_New(int argcount, int kwonlyargcount,
108108
Py_INCREF(lnotab);
109109
co->co_lnotab = lnotab;
110110
co->co_zombieframe = NULL;
111+
co->co_weakreflist = NULL;
111112
}
112113
return co;
113114
}
@@ -331,6 +332,8 @@ code_dealloc(PyCodeObject *co)
331332
Py_XDECREF(co->co_lnotab);
332333
if (co->co_zombieframe != NULL)
333334
PyObject_GC_Del(co->co_zombieframe);
335+
if (co->co_weakreflist != NULL)
336+
PyObject_ClearWeakRefs((PyObject*)co);
334337
PyObject_DEL(co);
335338
}
336339

@@ -462,7 +465,7 @@ PyTypeObject PyCode_Type = {
462465
0, /* tp_traverse */
463466
0, /* tp_clear */
464467
code_richcompare, /* tp_richcompare */
465-
0, /* tp_weaklistoffset */
468+
offsetof(PyCodeObject, co_weakreflist), /* tp_weaklistoffset */
466469
0, /* tp_iter */
467470
0, /* tp_iternext */
468471
0, /* tp_methods */

0 commit comments

Comments
 (0)