@@ -51,7 +51,8 @@ PyCode_New(int argcount, int kwonlyargcount,
5151 PyObject * lnotab )
5252{
5353 PyCodeObject * co ;
54- Py_ssize_t i ;
54+ unsigned char * cell2arg = NULL ;
55+ Py_ssize_t i , n_cellvars ;
5556
5657 /* Check argument types */
5758 if (argcount < 0 || kwonlyargcount < 0 || nlocals < 0 ||
@@ -68,48 +69,81 @@ PyCode_New(int argcount, int kwonlyargcount,
6869 PyErr_BadInternalCall ();
6970 return NULL ;
7071 }
72+ n_cellvars = PyTuple_GET_SIZE (cellvars );
7173 intern_strings (names );
7274 intern_strings (varnames );
7375 intern_strings (freevars );
7476 intern_strings (cellvars );
7577 /* Intern selected string constants */
76- for (i = PyTuple_Size (consts ); -- i >= 0 ; ) {
78+ for (i = PyTuple_GET_SIZE (consts ); -- i >= 0 ; ) {
7779 PyObject * v = PyTuple_GetItem (consts , i );
7880 if (!PyUnicode_Check (v ))
7981 continue ;
8082 if (!all_name_chars (PyUnicode_AS_UNICODE (v )))
8183 continue ;
8284 PyUnicode_InternInPlace (& PyTuple_GET_ITEM (consts , i ));
8385 }
86+ /* Create mapping between cells and arguments if needed. */
87+ if (n_cellvars ) {
88+ Py_ssize_t total_args = argcount + kwonlyargcount +
89+ ((flags & CO_VARARGS ) != 0 ) + ((flags & CO_VARKEYWORDS ) != 0 );
90+ Py_ssize_t alloc_size = sizeof (unsigned char ) * n_cellvars ;
91+ int used_cell2arg = 0 ;
92+ cell2arg = PyMem_MALLOC (alloc_size );
93+ if (cell2arg == NULL )
94+ return NULL ;
95+ memset (cell2arg , CO_CELL_NOT_AN_ARG , alloc_size );
96+ /* Find cells which are also arguments. */
97+ for (i = 0 ; i < n_cellvars ; i ++ ) {
98+ Py_ssize_t j ;
99+ PyObject * cell = PyTuple_GET_ITEM (cellvars , i );
100+ for (j = 0 ; j < total_args ; j ++ ) {
101+ PyObject * arg = PyTuple_GET_ITEM (varnames , j );
102+ if (!PyUnicode_Compare (cell , arg )) {
103+ cell2arg [i ] = j ;
104+ used_cell2arg = 1 ;
105+ break ;
106+ }
107+ }
108+ }
109+ if (!used_cell2arg ) {
110+ PyMem_FREE (cell2arg );
111+ cell2arg = NULL ;
112+ }
113+ }
84114 co = PyObject_NEW (PyCodeObject , & PyCode_Type );
85- if (co != NULL ) {
86- co -> co_argcount = argcount ;
87- co -> co_kwonlyargcount = kwonlyargcount ;
88- co -> co_nlocals = nlocals ;
89- co -> co_stacksize = stacksize ;
90- co -> co_flags = flags ;
91- Py_INCREF (code );
92- co -> co_code = code ;
93- Py_INCREF (consts );
94- co -> co_consts = consts ;
95- Py_INCREF (names );
96- co -> co_names = names ;
97- Py_INCREF (varnames );
98- co -> co_varnames = varnames ;
99- Py_INCREF (freevars );
100- co -> co_freevars = freevars ;
101- Py_INCREF (cellvars );
102- co -> co_cellvars = cellvars ;
103- Py_INCREF (filename );
104- co -> co_filename = filename ;
105- Py_INCREF (name );
106- co -> co_name = name ;
107- co -> co_firstlineno = firstlineno ;
108- Py_INCREF (lnotab );
109- co -> co_lnotab = lnotab ;
110- co -> co_zombieframe = NULL ;
111- co -> co_weakreflist = NULL ;
115+ if (co == NULL ) {
116+ if (cell2arg )
117+ PyMem_FREE (cell2arg );
118+ return NULL ;
112119 }
120+ co -> co_argcount = argcount ;
121+ co -> co_kwonlyargcount = kwonlyargcount ;
122+ co -> co_nlocals = nlocals ;
123+ co -> co_stacksize = stacksize ;
124+ co -> co_flags = flags ;
125+ Py_INCREF (code );
126+ co -> co_code = code ;
127+ Py_INCREF (consts );
128+ co -> co_consts = consts ;
129+ Py_INCREF (names );
130+ co -> co_names = names ;
131+ Py_INCREF (varnames );
132+ co -> co_varnames = varnames ;
133+ Py_INCREF (freevars );
134+ co -> co_freevars = freevars ;
135+ Py_INCREF (cellvars );
136+ co -> co_cellvars = cellvars ;
137+ co -> co_cell2arg = cell2arg ;
138+ Py_INCREF (filename );
139+ co -> co_filename = filename ;
140+ Py_INCREF (name );
141+ co -> co_name = name ;
142+ co -> co_firstlineno = firstlineno ;
143+ Py_INCREF (lnotab );
144+ co -> co_lnotab = lnotab ;
145+ co -> co_zombieframe = NULL ;
146+ co -> co_weakreflist = NULL ;
113147 return co ;
114148}
115149
@@ -330,6 +364,8 @@ code_dealloc(PyCodeObject *co)
330364 Py_XDECREF (co -> co_filename );
331365 Py_XDECREF (co -> co_name );
332366 Py_XDECREF (co -> co_lnotab );
367+ if (co -> co_cell2arg != NULL )
368+ PyMem_FREE (co -> co_cell2arg );
333369 if (co -> co_zombieframe != NULL )
334370 PyObject_GC_Del (co -> co_zombieframe );
335371 if (co -> co_weakreflist != NULL )
0 commit comments