Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 43b0686

Browse files
committed
try to use the same str object for all code filenames when compiling or unmarshalling (#12190)
This should reduce memory usage.
1 parent d408503 commit 43b0686

5 files changed

Lines changed: 57 additions & 18 deletions

File tree

Lib/test/test_compile.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import unittest
22
import sys
33
import _ast
4+
import types
45
from test import support
56

67
class TestSpecifics(unittest.TestCase):
@@ -433,6 +434,14 @@ def test_compile_ast(self):
433434
ast.body = [_ast.BoolOp()]
434435
self.assertRaises(TypeError, compile, ast, '<ast>', 'exec')
435436

437+
@support.cpython_only
438+
def test_same_filename_used(self):
439+
s = """def f(): pass\ndef g(): pass"""
440+
c = compile(s, "myfile", "exec")
441+
for obj in c.co_consts:
442+
if isinstance(obj, types.CodeType):
443+
self.assertIs(obj.co_filename, c.co_filename)
444+
436445

437446
def test_main():
438447
support.run_unittest(TestSpecifics)

Lib/test/test_marshal.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import sys
66
import unittest
77
import os
8+
import types
89

910
class HelperMixin:
1011
def helper(self, sample, *extra):
@@ -113,6 +114,22 @@ def test_many_codeobjects(self):
113114
codes = (ExceptionTestCase.test_exceptions.__code__,) * count
114115
marshal.loads(marshal.dumps(codes))
115116

117+
def test_different_filenames(self):
118+
co1 = compile("x", "f1", "exec")
119+
co2 = compile("y", "f2", "exec")
120+
co1, co2 = marshal.loads(marshal.dumps((co1, co2)))
121+
self.assertEqual(co1.co_filename, "f1")
122+
self.assertEqual(co2.co_filename, "f2")
123+
124+
@support.cpython_only
125+
def test_same_filename_used(self):
126+
s = """def f(): pass\ndef g(): pass"""
127+
co = compile(s, "myfile", "exec")
128+
co = marshal.loads(marshal.dumps(co))
129+
for obj in co.co_consts:
130+
if isinstance(obj, types.CodeType):
131+
self.assertIs(co.co_filename, obj.co_filename)
132+
116133
class ContainerTestCase(unittest.TestCase, HelperMixin):
117134
d = {'astring': '[email protected]',
118135
'afloat': 7283.43,

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ What's New in Python 3.3 Alpha 1?
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #12190: Try to use the same filename object when compiling unmarshalling
14+
a code objects in the same file.
15+
1316
- Issue #12166: Move implementations of dir() specialized for various types into
1417
the __dir__() methods of those types.
1518

Python/compile.c

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ managed by compiler_enter_scope() and compiler_exit_scope().
135135

136136
struct compiler {
137137
const char *c_filename;
138+
PyObject *c_filename_obj;
138139
struct symtable *c_st;
139140
PyFutureFeatures *c_future; /* pointer to module's __future__ */
140141
PyCompilerFlags *c_flags;
@@ -272,6 +273,9 @@ PyAST_CompileEx(mod_ty mod, const char *filename, PyCompilerFlags *flags,
272273
if (!compiler_init(&c))
273274
return NULL;
274275
c.c_filename = filename;
276+
c.c_filename_obj = PyUnicode_DecodeFSDefault(filename);
277+
if (!c.c_filename_obj)
278+
goto finally;
275279
c.c_arena = arena;
276280
c.c_future = PyFuture_FromAST(mod, filename);
277281
if (c.c_future == NULL)
@@ -324,6 +328,8 @@ compiler_free(struct compiler *c)
324328
PySymtable_Free(c->c_st);
325329
if (c->c_future)
326330
PyObject_Free(c->c_future);
331+
if (c->c_filename_obj)
332+
Py_DECREF(c->c_filename_obj);
327333
Py_DECREF(c->c_stack);
328334
}
329335

@@ -3361,24 +3367,15 @@ compiler_in_loop(struct compiler *c) {
33613367
static int
33623368
compiler_error(struct compiler *c, const char *errstr)
33633369
{
3364-
PyObject *loc, *filename;
3370+
PyObject *loc;
33653371
PyObject *u = NULL, *v = NULL;
33663372

33673373
loc = PyErr_ProgramText(c->c_filename, c->u->u_lineno);
33683374
if (!loc) {
33693375
Py_INCREF(Py_None);
33703376
loc = Py_None;
33713377
}
3372-
if (c->c_filename != NULL) {
3373-
filename = PyUnicode_DecodeFSDefault(c->c_filename);
3374-
if (!filename)
3375-
goto exit;
3376-
}
3377-
else {
3378-
Py_INCREF(Py_None);
3379-
filename = Py_None;
3380-
}
3381-
u = Py_BuildValue("(NiiO)", filename, c->u->u_lineno,
3378+
u = Py_BuildValue("(OiiO)", c->c_filename_obj, c->u->u_lineno,
33823379
c->u->u_col_offset, loc);
33833380
if (!u)
33843381
goto exit;
@@ -3927,7 +3924,6 @@ makecode(struct compiler *c, struct assembler *a)
39273924
PyObject *consts = NULL;
39283925
PyObject *names = NULL;
39293926
PyObject *varnames = NULL;
3930-
PyObject *filename = NULL;
39313927
PyObject *name = NULL;
39323928
PyObject *freevars = NULL;
39333929
PyObject *cellvars = NULL;
@@ -3951,10 +3947,6 @@ makecode(struct compiler *c, struct assembler *a)
39513947
freevars = dict_keys_inorder(c->u->u_freevars, PyTuple_Size(cellvars));
39523948
if (!freevars)
39533949
goto error;
3954-
filename = PyUnicode_DecodeFSDefault(c->c_filename);
3955-
if (!filename)
3956-
goto error;
3957-
39583950
nlocals = PyDict_Size(c->u->u_varnames);
39593951
flags = compute_code_flags(c);
39603952
if (flags < 0)
@@ -3974,14 +3966,13 @@ makecode(struct compiler *c, struct assembler *a)
39743966
nlocals, stackdepth(c), flags,
39753967
bytecode, consts, names, varnames,
39763968
freevars, cellvars,
3977-
filename, c->u->u_name,
3969+
c->c_filename_obj, c->u->u_name,
39783970
c->u->u_firstlineno,
39793971
a->a_lnotab);
39803972
error:
39813973
Py_XDECREF(consts);
39823974
Py_XDECREF(names);
39833975
Py_XDECREF(varnames);
3984-
Py_XDECREF(filename);
39853976
Py_XDECREF(name);
39863977
Py_XDECREF(freevars);
39873978
Py_XDECREF(cellvars);

Python/marshal.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ typedef struct {
5858
int depth;
5959
/* If fp == NULL, the following are valid: */
6060
PyObject *str;
61+
PyObject *current_filename;
6162
char *ptr;
6263
char *end;
6364
int version;
@@ -976,6 +977,18 @@ r_object(RFILE *p)
976977
filename = r_object(p);
977978
if (filename == NULL)
978979
goto code_error;
980+
if (PyUnicode_CheckExact(filename)) {
981+
if (p->current_filename != NULL) {
982+
if (!PyUnicode_Compare(filename, p->current_filename)) {
983+
Py_DECREF(filename);
984+
Py_INCREF(p->current_filename);
985+
filename = p->current_filename;
986+
}
987+
}
988+
else {
989+
p->current_filename = filename;
990+
}
991+
}
979992
name = r_object(p);
980993
if (name == NULL)
981994
goto code_error;
@@ -1037,6 +1050,7 @@ PyMarshal_ReadShortFromFile(FILE *fp)
10371050
RFILE rf;
10381051
assert(fp);
10391052
rf.fp = fp;
1053+
rf.current_filename = NULL;
10401054
rf.end = rf.ptr = NULL;
10411055
return r_short(&rf);
10421056
}
@@ -1046,6 +1060,7 @@ PyMarshal_ReadLongFromFile(FILE *fp)
10461060
{
10471061
RFILE rf;
10481062
rf.fp = fp;
1063+
rf.current_filename = NULL;
10491064
rf.ptr = rf.end = NULL;
10501065
return r_long(&rf);
10511066
}
@@ -1106,6 +1121,7 @@ PyMarshal_ReadObjectFromFile(FILE *fp)
11061121
RFILE rf;
11071122
PyObject *result;
11081123
rf.fp = fp;
1124+
rf.current_filename = NULL;
11091125
rf.depth = 0;
11101126
rf.ptr = rf.end = NULL;
11111127
result = r_object(&rf);
@@ -1118,6 +1134,7 @@ PyMarshal_ReadObjectFromString(char *str, Py_ssize_t len)
11181134
RFILE rf;
11191135
PyObject *result;
11201136
rf.fp = NULL;
1137+
rf.current_filename = NULL;
11211138
rf.ptr = str;
11221139
rf.end = str + len;
11231140
rf.depth = 0;
@@ -1214,6 +1231,7 @@ marshal_load(PyObject *self, PyObject *f)
12141231
if (data == NULL)
12151232
return NULL;
12161233
rf.fp = NULL;
1234+
rf.current_filename = NULL;
12171235
if (PyBytes_Check(data)) {
12181236
rf.ptr = PyBytes_AS_STRING(data);
12191237
rf.end = rf.ptr + PyBytes_GET_SIZE(data);
@@ -1282,6 +1300,7 @@ marshal_loads(PyObject *self, PyObject *args)
12821300
s = p.buf;
12831301
n = p.len;
12841302
rf.fp = NULL;
1303+
rf.current_filename = NULL;
12851304
rf.ptr = s;
12861305
rf.end = s + n;
12871306
rf.depth = 0;

0 commit comments

Comments
 (0)