• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdbool.h>
2 
3 #include "Python.h"
4 #include "code.h"
5 #include "opcode.h"
6 #include "structmember.h"         // PyMemberDef
7 #include "pycore_code.h"          // _PyOpcache
8 #include "pycore_interp.h"        // PyInterpreterState.co_extra_freefuncs
9 #include "pycore_pystate.h"       // _PyInterpreterState_GET()
10 #include "pycore_tuple.h"         // _PyTuple_ITEMS()
11 #include "clinic/codeobject.c.h"
12 
13 /* Holder for co_extra information */
14 typedef struct {
15     Py_ssize_t ce_size;
16     void *ce_extras[1];
17 } _PyCodeObjectExtra;
18 
19 /*[clinic input]
20 class code "PyCodeObject *" "&PyCode_Type"
21 [clinic start generated code]*/
22 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=78aa5d576683bb4b]*/
23 
24 /* all_name_chars(s): true iff s matches [a-zA-Z0-9_]* */
25 static int
all_name_chars(PyObject * o)26 all_name_chars(PyObject *o)
27 {
28     const unsigned char *s, *e;
29 
30     if (!PyUnicode_IS_ASCII(o))
31         return 0;
32 
33     s = PyUnicode_1BYTE_DATA(o);
34     e = s + PyUnicode_GET_LENGTH(o);
35     for (; s != e; s++) {
36         if (!Py_ISALNUM(*s) && *s != '_')
37             return 0;
38     }
39     return 1;
40 }
41 
42 static int
intern_strings(PyObject * tuple)43 intern_strings(PyObject *tuple)
44 {
45     Py_ssize_t i;
46 
47     for (i = PyTuple_GET_SIZE(tuple); --i >= 0; ) {
48         PyObject *v = PyTuple_GET_ITEM(tuple, i);
49         if (v == NULL || !PyUnicode_CheckExact(v)) {
50             PyErr_SetString(PyExc_SystemError,
51                             "non-string found in code slot");
52             return -1;
53         }
54         PyUnicode_InternInPlace(&_PyTuple_ITEMS(tuple)[i]);
55     }
56     return 0;
57 }
58 
59 /* Intern selected string constants */
60 static int
intern_string_constants(PyObject * tuple,int * modified)61 intern_string_constants(PyObject *tuple, int *modified)
62 {
63     for (Py_ssize_t i = PyTuple_GET_SIZE(tuple); --i >= 0; ) {
64         PyObject *v = PyTuple_GET_ITEM(tuple, i);
65         if (PyUnicode_CheckExact(v)) {
66             if (PyUnicode_READY(v) == -1) {
67                 return -1;
68             }
69 
70             if (all_name_chars(v)) {
71                 PyObject *w = v;
72                 PyUnicode_InternInPlace(&v);
73                 if (w != v) {
74                     PyTuple_SET_ITEM(tuple, i, v);
75                     if (modified) {
76                         *modified = 1;
77                     }
78                 }
79             }
80         }
81         else if (PyTuple_CheckExact(v)) {
82             if (intern_string_constants(v, NULL) < 0) {
83                 return -1;
84             }
85         }
86         else if (PyFrozenSet_CheckExact(v)) {
87             PyObject *w = v;
88             PyObject *tmp = PySequence_Tuple(v);
89             if (tmp == NULL) {
90                 return -1;
91             }
92             int tmp_modified = 0;
93             if (intern_string_constants(tmp, &tmp_modified) < 0) {
94                 Py_DECREF(tmp);
95                 return -1;
96             }
97             if (tmp_modified) {
98                 v = PyFrozenSet_New(tmp);
99                 if (v == NULL) {
100                     Py_DECREF(tmp);
101                     return -1;
102                 }
103 
104                 PyTuple_SET_ITEM(tuple, i, v);
105                 Py_DECREF(w);
106                 if (modified) {
107                     *modified = 1;
108                 }
109             }
110             Py_DECREF(tmp);
111         }
112     }
113     return 0;
114 }
115 
116 PyCodeObject *
PyCode_NewWithPosOnlyArgs(int argcount,int posonlyargcount,int kwonlyargcount,int nlocals,int stacksize,int flags,PyObject * code,PyObject * consts,PyObject * names,PyObject * varnames,PyObject * freevars,PyObject * cellvars,PyObject * filename,PyObject * name,int firstlineno,PyObject * linetable)117 PyCode_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount,
118                           int nlocals, int stacksize, int flags,
119                           PyObject *code, PyObject *consts, PyObject *names,
120                           PyObject *varnames, PyObject *freevars, PyObject *cellvars,
121                           PyObject *filename, PyObject *name, int firstlineno,
122                           PyObject *linetable)
123 {
124     PyCodeObject *co;
125     Py_ssize_t *cell2arg = NULL;
126     Py_ssize_t i, n_cellvars, n_varnames, total_args;
127 
128     /* Check argument types */
129     if (argcount < posonlyargcount || posonlyargcount < 0 ||
130         kwonlyargcount < 0 || nlocals < 0 ||
131         stacksize < 0 || flags < 0 ||
132         code == NULL || !PyBytes_Check(code) ||
133         consts == NULL || !PyTuple_Check(consts) ||
134         names == NULL || !PyTuple_Check(names) ||
135         varnames == NULL || !PyTuple_Check(varnames) ||
136         freevars == NULL || !PyTuple_Check(freevars) ||
137         cellvars == NULL || !PyTuple_Check(cellvars) ||
138         name == NULL || !PyUnicode_Check(name) ||
139         filename == NULL || !PyUnicode_Check(filename) ||
140         linetable == NULL || !PyBytes_Check(linetable)) {
141         PyErr_BadInternalCall();
142         return NULL;
143     }
144 
145     /* Ensure that strings are ready Unicode string */
146     if (PyUnicode_READY(name) < 0) {
147         return NULL;
148     }
149     if (PyUnicode_READY(filename) < 0) {
150         return NULL;
151     }
152 
153     if (intern_strings(names) < 0) {
154         return NULL;
155     }
156     if (intern_strings(varnames) < 0) {
157         return NULL;
158     }
159     if (intern_strings(freevars) < 0) {
160         return NULL;
161     }
162     if (intern_strings(cellvars) < 0) {
163         return NULL;
164     }
165     if (intern_string_constants(consts, NULL) < 0) {
166         return NULL;
167     }
168 
169     /* Make sure that code is indexable with an int, this is
170        a long running assumption in ceval.c and many parts of
171        the interpreter. */
172     if (PyBytes_GET_SIZE(code) > INT_MAX) {
173         PyErr_SetString(PyExc_OverflowError, "co_code larger than INT_MAX");
174         return NULL;
175     }
176 
177     /* Check for any inner or outer closure references */
178     n_cellvars = PyTuple_GET_SIZE(cellvars);
179     if (!n_cellvars && !PyTuple_GET_SIZE(freevars)) {
180         flags |= CO_NOFREE;
181     } else {
182         flags &= ~CO_NOFREE;
183     }
184 
185     n_varnames = PyTuple_GET_SIZE(varnames);
186     if (argcount <= n_varnames && kwonlyargcount <= n_varnames) {
187         /* Never overflows. */
188         total_args = (Py_ssize_t)argcount + (Py_ssize_t)kwonlyargcount +
189                       ((flags & CO_VARARGS) != 0) + ((flags & CO_VARKEYWORDS) != 0);
190     }
191     else {
192         total_args = n_varnames + 1;
193     }
194     if (total_args > n_varnames) {
195         PyErr_SetString(PyExc_ValueError, "code: varnames is too small");
196         return NULL;
197     }
198 
199     /* Create mapping between cells and arguments if needed. */
200     if (n_cellvars) {
201         bool used_cell2arg = false;
202         cell2arg = PyMem_NEW(Py_ssize_t, n_cellvars);
203         if (cell2arg == NULL) {
204             PyErr_NoMemory();
205             return NULL;
206         }
207         /* Find cells which are also arguments. */
208         for (i = 0; i < n_cellvars; i++) {
209             Py_ssize_t j;
210             PyObject *cell = PyTuple_GET_ITEM(cellvars, i);
211             cell2arg[i] = CO_CELL_NOT_AN_ARG;
212             for (j = 0; j < total_args; j++) {
213                 PyObject *arg = PyTuple_GET_ITEM(varnames, j);
214                 int cmp = PyUnicode_Compare(cell, arg);
215                 if (cmp == -1 && PyErr_Occurred()) {
216                     PyMem_Free(cell2arg);
217                     return NULL;
218                 }
219                 if (cmp == 0) {
220                     cell2arg[i] = j;
221                     used_cell2arg = true;
222                     break;
223                 }
224             }
225         }
226         if (!used_cell2arg) {
227             PyMem_Free(cell2arg);
228             cell2arg = NULL;
229         }
230     }
231     co = PyObject_New(PyCodeObject, &PyCode_Type);
232     if (co == NULL) {
233         if (cell2arg)
234             PyMem_Free(cell2arg);
235         return NULL;
236     }
237     co->co_argcount = argcount;
238     co->co_posonlyargcount = posonlyargcount;
239     co->co_kwonlyargcount = kwonlyargcount;
240     co->co_nlocals = nlocals;
241     co->co_stacksize = stacksize;
242     co->co_flags = flags;
243     Py_INCREF(code);
244     co->co_code = code;
245     Py_INCREF(consts);
246     co->co_consts = consts;
247     Py_INCREF(names);
248     co->co_names = names;
249     Py_INCREF(varnames);
250     co->co_varnames = varnames;
251     Py_INCREF(freevars);
252     co->co_freevars = freevars;
253     Py_INCREF(cellvars);
254     co->co_cellvars = cellvars;
255     co->co_cell2arg = cell2arg;
256     Py_INCREF(filename);
257     co->co_filename = filename;
258     Py_INCREF(name);
259     co->co_name = name;
260     co->co_firstlineno = firstlineno;
261     Py_INCREF(linetable);
262     co->co_linetable = linetable;
263     co->co_zombieframe = NULL;
264     co->co_weakreflist = NULL;
265     co->co_extra = NULL;
266 
267     co->co_opcache_map = NULL;
268     co->co_opcache = NULL;
269     co->co_opcache_flag = 0;
270     co->co_opcache_size = 0;
271     return co;
272 }
273 
274 PyCodeObject *
PyCode_New(int argcount,int kwonlyargcount,int nlocals,int stacksize,int flags,PyObject * code,PyObject * consts,PyObject * names,PyObject * varnames,PyObject * freevars,PyObject * cellvars,PyObject * filename,PyObject * name,int firstlineno,PyObject * linetable)275 PyCode_New(int argcount, int kwonlyargcount,
276            int nlocals, int stacksize, int flags,
277            PyObject *code, PyObject *consts, PyObject *names,
278            PyObject *varnames, PyObject *freevars, PyObject *cellvars,
279            PyObject *filename, PyObject *name, int firstlineno,
280            PyObject *linetable)
281 {
282     return PyCode_NewWithPosOnlyArgs(argcount, 0, kwonlyargcount, nlocals,
283                                      stacksize, flags, code, consts, names,
284                                      varnames, freevars, cellvars, filename,
285                                      name, firstlineno, linetable);
286 }
287 
288 int
_PyCode_InitOpcache(PyCodeObject * co)289 _PyCode_InitOpcache(PyCodeObject *co)
290 {
291     Py_ssize_t co_size = PyBytes_Size(co->co_code) / sizeof(_Py_CODEUNIT);
292     co->co_opcache_map = (unsigned char *)PyMem_Calloc(co_size, 1);
293     if (co->co_opcache_map == NULL) {
294         return -1;
295     }
296 
297     const _Py_CODEUNIT *opcodes = (_Py_CODEUNIT*)PyBytes_AS_STRING(co->co_code);
298     Py_ssize_t opts = 0;
299 
300     for (Py_ssize_t i = 0; i < co_size;) {
301         unsigned char opcode = _Py_OPCODE(opcodes[i]);
302         i++;  // 'i' is now aligned to (next_instr - first_instr)
303 
304         // TODO: LOAD_METHOD
305         if (opcode == LOAD_GLOBAL || opcode == LOAD_ATTR) {
306             opts++;
307             co->co_opcache_map[i] = (unsigned char)opts;
308             if (opts > 254) {
309                 break;
310             }
311         }
312     }
313 
314     if (opts) {
315         co->co_opcache = (_PyOpcache *)PyMem_Calloc(opts, sizeof(_PyOpcache));
316         if (co->co_opcache == NULL) {
317             PyMem_Free(co->co_opcache_map);
318             return -1;
319         }
320     }
321     else {
322         PyMem_Free(co->co_opcache_map);
323         co->co_opcache_map = NULL;
324         co->co_opcache = NULL;
325     }
326 
327     co->co_opcache_size = (unsigned char)opts;
328     return 0;
329 }
330 
331 PyCodeObject *
PyCode_NewEmpty(const char * filename,const char * funcname,int firstlineno)332 PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno)
333 {
334     static PyObject *emptystring = NULL;
335     static PyObject *nulltuple = NULL;
336     PyObject *filename_ob = NULL;
337     PyObject *funcname_ob = NULL;
338     PyCodeObject *result = NULL;
339     if (emptystring == NULL) {
340         emptystring = PyBytes_FromString("");
341         if (emptystring == NULL)
342             goto failed;
343     }
344     if (nulltuple == NULL) {
345         nulltuple = PyTuple_New(0);
346         if (nulltuple == NULL)
347             goto failed;
348     }
349     funcname_ob = PyUnicode_FromString(funcname);
350     if (funcname_ob == NULL)
351         goto failed;
352     filename_ob = PyUnicode_DecodeFSDefault(filename);
353     if (filename_ob == NULL)
354         goto failed;
355 
356     result = PyCode_NewWithPosOnlyArgs(
357                 0,                    /* argcount */
358                 0,                              /* posonlyargcount */
359                 0,                              /* kwonlyargcount */
360                 0,                              /* nlocals */
361                 0,                              /* stacksize */
362                 0,                              /* flags */
363                 emptystring,                    /* code */
364                 nulltuple,                      /* consts */
365                 nulltuple,                      /* names */
366                 nulltuple,                      /* varnames */
367                 nulltuple,                      /* freevars */
368                 nulltuple,                      /* cellvars */
369                 filename_ob,                    /* filename */
370                 funcname_ob,                    /* name */
371                 firstlineno,                    /* firstlineno */
372                 emptystring                     /* linetable */
373                 );
374 
375 failed:
376     Py_XDECREF(funcname_ob);
377     Py_XDECREF(filename_ob);
378     return result;
379 }
380 
381 #define OFF(x) offsetof(PyCodeObject, x)
382 
383 static PyMemberDef code_memberlist[] = {
384     {"co_argcount",     T_INT,          OFF(co_argcount),        READONLY},
385     {"co_posonlyargcount",      T_INT,  OFF(co_posonlyargcount), READONLY},
386     {"co_kwonlyargcount",       T_INT,  OFF(co_kwonlyargcount),  READONLY},
387     {"co_nlocals",      T_INT,          OFF(co_nlocals),         READONLY},
388     {"co_stacksize",T_INT,              OFF(co_stacksize),       READONLY},
389     {"co_flags",        T_INT,          OFF(co_flags),           READONLY},
390     {"co_code",         T_OBJECT,       OFF(co_code),            READONLY},
391     {"co_consts",       T_OBJECT,       OFF(co_consts),          READONLY},
392     {"co_names",        T_OBJECT,       OFF(co_names),           READONLY},
393     {"co_varnames",     T_OBJECT,       OFF(co_varnames),        READONLY},
394     {"co_freevars",     T_OBJECT,       OFF(co_freevars),        READONLY},
395     {"co_cellvars",     T_OBJECT,       OFF(co_cellvars),        READONLY},
396     {"co_filename",     T_OBJECT,       OFF(co_filename),        READONLY},
397     {"co_name",         T_OBJECT,       OFF(co_name),            READONLY},
398     {"co_firstlineno",  T_INT,          OFF(co_firstlineno),     READONLY},
399     {"co_linetable",    T_OBJECT,       OFF(co_linetable),       READONLY},
400     {NULL}      /* Sentinel */
401 };
402 
403 static int
emit_pair(PyObject ** bytes,int * offset,int a,int b)404 emit_pair(PyObject **bytes, int *offset, int a, int b)
405 {
406     Py_ssize_t len = PyBytes_GET_SIZE(*bytes);
407     if (*offset + 2 >= len) {
408         if (_PyBytes_Resize(bytes, len * 2) < 0)
409             return 0;
410     }
411     unsigned char *lnotab = (unsigned char *) PyBytes_AS_STRING(*bytes);
412     lnotab += *offset;
413     *lnotab++ = a;
414     *lnotab++ = b;
415     *offset += 2;
416     return 1;
417 }
418 
419 static int
emit_delta(PyObject ** bytes,int bdelta,int ldelta,int * offset)420 emit_delta(PyObject **bytes, int bdelta, int ldelta, int *offset)
421 {
422     while (bdelta > 255) {
423         if (!emit_pair(bytes, offset, 255, 0)) {
424             return 0;
425         }
426         bdelta -= 255;
427     }
428     while (ldelta > 127) {
429         if (!emit_pair(bytes, offset, bdelta, 127)) {
430             return 0;
431         }
432         bdelta = 0;
433         ldelta -= 127;
434     }
435     while (ldelta < -128) {
436         if (!emit_pair(bytes, offset, bdelta, -128)) {
437             return 0;
438         }
439         bdelta = 0;
440         ldelta += 128;
441     }
442     return emit_pair(bytes, offset, bdelta, ldelta);
443 }
444 
445 static PyObject *
code_getlnotab(PyCodeObject * code,void * closure)446 code_getlnotab(PyCodeObject *code, void *closure)
447 {
448     PyCodeAddressRange bounds;
449     PyObject *bytes;
450     int table_offset = 0;
451     int code_offset = 0;
452     int line = code->co_firstlineno;
453     bytes = PyBytes_FromStringAndSize(NULL, 64);
454     if (bytes == NULL) {
455         return NULL;
456     }
457     _PyCode_InitAddressRange(code, &bounds);
458     while (PyLineTable_NextAddressRange(&bounds)) {
459         if (bounds.opaque.computed_line != line) {
460             int bdelta = bounds.ar_start - code_offset;
461             int ldelta = bounds.opaque.computed_line - line;
462             if (!emit_delta(&bytes, bdelta, ldelta, &table_offset)) {
463                 Py_DECREF(bytes);
464                 return NULL;
465             }
466             code_offset = bounds.ar_start;
467             line = bounds.opaque.computed_line;
468         }
469     }
470     _PyBytes_Resize(&bytes, table_offset);
471     return bytes;
472 }
473 
474 
475 static PyGetSetDef code_getsetlist[] = {
476     {"co_lnotab",    (getter)code_getlnotab, NULL, NULL},
477     {0}
478 };
479 
480 
481 /* Helper for code_new: return a shallow copy of a tuple that is
482    guaranteed to contain exact strings, by converting string subclasses
483    to exact strings and complaining if a non-string is found. */
484 static PyObject*
validate_and_copy_tuple(PyObject * tup)485 validate_and_copy_tuple(PyObject *tup)
486 {
487     PyObject *newtuple;
488     PyObject *item;
489     Py_ssize_t i, len;
490 
491     len = PyTuple_GET_SIZE(tup);
492     newtuple = PyTuple_New(len);
493     if (newtuple == NULL)
494         return NULL;
495 
496     for (i = 0; i < len; i++) {
497         item = PyTuple_GET_ITEM(tup, i);
498         if (PyUnicode_CheckExact(item)) {
499             Py_INCREF(item);
500         }
501         else if (!PyUnicode_Check(item)) {
502             PyErr_Format(
503                 PyExc_TypeError,
504                 "name tuples must contain only "
505                 "strings, not '%.500s'",
506                 Py_TYPE(item)->tp_name);
507             Py_DECREF(newtuple);
508             return NULL;
509         }
510         else {
511             item = _PyUnicode_Copy(item);
512             if (item == NULL) {
513                 Py_DECREF(newtuple);
514                 return NULL;
515             }
516         }
517         PyTuple_SET_ITEM(newtuple, i, item);
518     }
519 
520     return newtuple;
521 }
522 
523 /*[clinic input]
524 @classmethod
525 code.__new__ as code_new
526 
527     argcount: int
528     posonlyargcount: int
529     kwonlyargcount: int
530     nlocals: int
531     stacksize: int
532     flags: int
533     codestring as code: object(subclass_of="&PyBytes_Type")
534     constants as consts: object(subclass_of="&PyTuple_Type")
535     names: object(subclass_of="&PyTuple_Type")
536     varnames: object(subclass_of="&PyTuple_Type")
537     filename: unicode
538     name: unicode
539     firstlineno: int
540     linetable: object(subclass_of="&PyBytes_Type")
541     freevars: object(subclass_of="&PyTuple_Type", c_default="NULL") = ()
542     cellvars: object(subclass_of="&PyTuple_Type", c_default="NULL") = ()
543     /
544 
545 Create a code object.  Not for the faint of heart.
546 [clinic start generated code]*/
547 
548 static PyObject *
code_new_impl(PyTypeObject * type,int argcount,int posonlyargcount,int kwonlyargcount,int nlocals,int stacksize,int flags,PyObject * code,PyObject * consts,PyObject * names,PyObject * varnames,PyObject * filename,PyObject * name,int firstlineno,PyObject * linetable,PyObject * freevars,PyObject * cellvars)549 code_new_impl(PyTypeObject *type, int argcount, int posonlyargcount,
550               int kwonlyargcount, int nlocals, int stacksize, int flags,
551               PyObject *code, PyObject *consts, PyObject *names,
552               PyObject *varnames, PyObject *filename, PyObject *name,
553               int firstlineno, PyObject *linetable, PyObject *freevars,
554               PyObject *cellvars)
555 /*[clinic end generated code: output=42c1839b082ba293 input=0ec80da632b99f57]*/
556 {
557     PyObject *co = NULL;
558     PyObject *ournames = NULL;
559     PyObject *ourvarnames = NULL;
560     PyObject *ourfreevars = NULL;
561     PyObject *ourcellvars = NULL;
562 
563     if (PySys_Audit("code.__new__", "OOOiiiiii",
564                     code, filename, name, argcount, posonlyargcount,
565                     kwonlyargcount, nlocals, stacksize, flags) < 0) {
566         goto cleanup;
567     }
568 
569     if (argcount < 0) {
570         PyErr_SetString(
571             PyExc_ValueError,
572             "code: argcount must not be negative");
573         goto cleanup;
574     }
575 
576     if (posonlyargcount < 0) {
577         PyErr_SetString(
578             PyExc_ValueError,
579             "code: posonlyargcount must not be negative");
580         goto cleanup;
581     }
582 
583     if (kwonlyargcount < 0) {
584         PyErr_SetString(
585             PyExc_ValueError,
586             "code: kwonlyargcount must not be negative");
587         goto cleanup;
588     }
589     if (nlocals < 0) {
590         PyErr_SetString(
591             PyExc_ValueError,
592             "code: nlocals must not be negative");
593         goto cleanup;
594     }
595 
596     ournames = validate_and_copy_tuple(names);
597     if (ournames == NULL)
598         goto cleanup;
599     ourvarnames = validate_and_copy_tuple(varnames);
600     if (ourvarnames == NULL)
601         goto cleanup;
602     if (freevars)
603         ourfreevars = validate_and_copy_tuple(freevars);
604     else
605         ourfreevars = PyTuple_New(0);
606     if (ourfreevars == NULL)
607         goto cleanup;
608     if (cellvars)
609         ourcellvars = validate_and_copy_tuple(cellvars);
610     else
611         ourcellvars = PyTuple_New(0);
612     if (ourcellvars == NULL)
613         goto cleanup;
614 
615     co = (PyObject *)PyCode_NewWithPosOnlyArgs(argcount, posonlyargcount,
616                                                kwonlyargcount,
617                                                nlocals, stacksize, flags,
618                                                code, consts, ournames,
619                                                ourvarnames, ourfreevars,
620                                                ourcellvars, filename,
621                                                name, firstlineno, linetable);
622   cleanup:
623     Py_XDECREF(ournames);
624     Py_XDECREF(ourvarnames);
625     Py_XDECREF(ourfreevars);
626     Py_XDECREF(ourcellvars);
627     return co;
628 }
629 
630 static void
code_dealloc(PyCodeObject * co)631 code_dealloc(PyCodeObject *co)
632 {
633     if (co->co_opcache != NULL) {
634         PyMem_Free(co->co_opcache);
635     }
636     if (co->co_opcache_map != NULL) {
637         PyMem_Free(co->co_opcache_map);
638     }
639     co->co_opcache_flag = 0;
640     co->co_opcache_size = 0;
641 
642     if (co->co_extra != NULL) {
643         PyInterpreterState *interp = _PyInterpreterState_GET();
644         _PyCodeObjectExtra *co_extra = co->co_extra;
645 
646         for (Py_ssize_t i = 0; i < co_extra->ce_size; i++) {
647             freefunc free_extra = interp->co_extra_freefuncs[i];
648 
649             if (free_extra != NULL) {
650                 free_extra(co_extra->ce_extras[i]);
651             }
652         }
653 
654         PyMem_Free(co_extra);
655     }
656 
657     Py_XDECREF(co->co_code);
658     Py_XDECREF(co->co_consts);
659     Py_XDECREF(co->co_names);
660     Py_XDECREF(co->co_varnames);
661     Py_XDECREF(co->co_freevars);
662     Py_XDECREF(co->co_cellvars);
663     Py_XDECREF(co->co_filename);
664     Py_XDECREF(co->co_name);
665     Py_XDECREF(co->co_linetable);
666     if (co->co_cell2arg != NULL)
667         PyMem_Free(co->co_cell2arg);
668     if (co->co_zombieframe != NULL)
669         PyObject_GC_Del(co->co_zombieframe);
670     if (co->co_weakreflist != NULL)
671         PyObject_ClearWeakRefs((PyObject*)co);
672     PyObject_Free(co);
673 }
674 
675 static PyObject *
code_sizeof(PyCodeObject * co,PyObject * Py_UNUSED (args))676 code_sizeof(PyCodeObject *co, PyObject *Py_UNUSED(args))
677 {
678     Py_ssize_t res = _PyObject_SIZE(Py_TYPE(co));
679     _PyCodeObjectExtra *co_extra = (_PyCodeObjectExtra*) co->co_extra;
680 
681     if (co->co_cell2arg != NULL && co->co_cellvars != NULL) {
682         res += PyTuple_GET_SIZE(co->co_cellvars) * sizeof(Py_ssize_t);
683     }
684     if (co_extra != NULL) {
685         res += sizeof(_PyCodeObjectExtra) +
686                (co_extra->ce_size-1) * sizeof(co_extra->ce_extras[0]);
687     }
688     if (co->co_opcache != NULL) {
689         assert(co->co_opcache_map != NULL);
690         // co_opcache_map
691         res += PyBytes_GET_SIZE(co->co_code) / sizeof(_Py_CODEUNIT);
692         // co_opcache
693         res += co->co_opcache_size * sizeof(_PyOpcache);
694     }
695     return PyLong_FromSsize_t(res);
696 }
697 
698 /*[clinic input]
699 code.replace
700 
701     *
702     co_argcount: int(c_default="self->co_argcount") = -1
703     co_posonlyargcount: int(c_default="self->co_posonlyargcount") = -1
704     co_kwonlyargcount: int(c_default="self->co_kwonlyargcount") = -1
705     co_nlocals: int(c_default="self->co_nlocals") = -1
706     co_stacksize: int(c_default="self->co_stacksize") = -1
707     co_flags: int(c_default="self->co_flags") = -1
708     co_firstlineno: int(c_default="self->co_firstlineno") = -1
709     co_code: PyBytesObject(c_default="(PyBytesObject *)self->co_code") = None
710     co_consts: object(subclass_of="&PyTuple_Type", c_default="self->co_consts") = None
711     co_names: object(subclass_of="&PyTuple_Type", c_default="self->co_names") = None
712     co_varnames: object(subclass_of="&PyTuple_Type", c_default="self->co_varnames") = None
713     co_freevars: object(subclass_of="&PyTuple_Type", c_default="self->co_freevars") = None
714     co_cellvars: object(subclass_of="&PyTuple_Type", c_default="self->co_cellvars") = None
715     co_filename: unicode(c_default="self->co_filename") = None
716     co_name: unicode(c_default="self->co_name") = None
717     co_linetable: PyBytesObject(c_default="(PyBytesObject *)self->co_linetable") = None
718 
719 Return a copy of the code object with new values for the specified fields.
720 [clinic start generated code]*/
721 
722 static PyObject *
code_replace_impl(PyCodeObject * self,int co_argcount,int co_posonlyargcount,int co_kwonlyargcount,int co_nlocals,int co_stacksize,int co_flags,int co_firstlineno,PyBytesObject * co_code,PyObject * co_consts,PyObject * co_names,PyObject * co_varnames,PyObject * co_freevars,PyObject * co_cellvars,PyObject * co_filename,PyObject * co_name,PyBytesObject * co_linetable)723 code_replace_impl(PyCodeObject *self, int co_argcount,
724                   int co_posonlyargcount, int co_kwonlyargcount,
725                   int co_nlocals, int co_stacksize, int co_flags,
726                   int co_firstlineno, PyBytesObject *co_code,
727                   PyObject *co_consts, PyObject *co_names,
728                   PyObject *co_varnames, PyObject *co_freevars,
729                   PyObject *co_cellvars, PyObject *co_filename,
730                   PyObject *co_name, PyBytesObject *co_linetable)
731 /*[clinic end generated code: output=50d77e668d3b449b input=a5f997b173d7f636]*/
732 {
733 #define CHECK_INT_ARG(ARG) \
734         if (ARG < 0) { \
735             PyErr_SetString(PyExc_ValueError, \
736                             #ARG " must be a positive integer"); \
737             return NULL; \
738         }
739 
740     CHECK_INT_ARG(co_argcount);
741     CHECK_INT_ARG(co_posonlyargcount);
742     CHECK_INT_ARG(co_kwonlyargcount);
743     CHECK_INT_ARG(co_nlocals);
744     CHECK_INT_ARG(co_stacksize);
745     CHECK_INT_ARG(co_flags);
746     CHECK_INT_ARG(co_firstlineno);
747 
748 #undef CHECK_INT_ARG
749 
750     if (PySys_Audit("code.__new__", "OOOiiiiii",
751                     co_code, co_filename, co_name, co_argcount,
752                     co_posonlyargcount, co_kwonlyargcount, co_nlocals,
753                     co_stacksize, co_flags) < 0) {
754         return NULL;
755     }
756 
757     return (PyObject *)PyCode_NewWithPosOnlyArgs(
758         co_argcount, co_posonlyargcount, co_kwonlyargcount, co_nlocals,
759         co_stacksize, co_flags, (PyObject*)co_code, co_consts, co_names,
760         co_varnames, co_freevars, co_cellvars, co_filename, co_name,
761         co_firstlineno, (PyObject*)co_linetable);
762 }
763 
764 static PyObject *
code_repr(PyCodeObject * co)765 code_repr(PyCodeObject *co)
766 {
767     int lineno;
768     if (co->co_firstlineno != 0)
769         lineno = co->co_firstlineno;
770     else
771         lineno = -1;
772     if (co->co_filename && PyUnicode_Check(co->co_filename)) {
773         return PyUnicode_FromFormat(
774             "<code object %U at %p, file \"%U\", line %d>",
775             co->co_name, co, co->co_filename, lineno);
776     } else {
777         return PyUnicode_FromFormat(
778             "<code object %U at %p, file ???, line %d>",
779             co->co_name, co, lineno);
780     }
781 }
782 
783 PyObject*
_PyCode_ConstantKey(PyObject * op)784 _PyCode_ConstantKey(PyObject *op)
785 {
786     PyObject *key;
787 
788     /* Py_None and Py_Ellipsis are singletons. */
789     if (op == Py_None || op == Py_Ellipsis
790        || PyLong_CheckExact(op)
791        || PyUnicode_CheckExact(op)
792           /* code_richcompare() uses _PyCode_ConstantKey() internally */
793        || PyCode_Check(op))
794     {
795         /* Objects of these types are always different from object of other
796          * type and from tuples. */
797         Py_INCREF(op);
798         key = op;
799     }
800     else if (PyBool_Check(op) || PyBytes_CheckExact(op)) {
801         /* Make booleans different from integers 0 and 1.
802          * Avoid BytesWarning from comparing bytes with strings. */
803         key = PyTuple_Pack(2, Py_TYPE(op), op);
804     }
805     else if (PyFloat_CheckExact(op)) {
806         double d = PyFloat_AS_DOUBLE(op);
807         /* all we need is to make the tuple different in either the 0.0
808          * or -0.0 case from all others, just to avoid the "coercion".
809          */
810         if (d == 0.0 && copysign(1.0, d) < 0.0)
811             key = PyTuple_Pack(3, Py_TYPE(op), op, Py_None);
812         else
813             key = PyTuple_Pack(2, Py_TYPE(op), op);
814     }
815     else if (PyComplex_CheckExact(op)) {
816         Py_complex z;
817         int real_negzero, imag_negzero;
818         /* For the complex case we must make complex(x, 0.)
819            different from complex(x, -0.) and complex(0., y)
820            different from complex(-0., y), for any x and y.
821            All four complex zeros must be distinguished.*/
822         z = PyComplex_AsCComplex(op);
823         real_negzero = z.real == 0.0 && copysign(1.0, z.real) < 0.0;
824         imag_negzero = z.imag == 0.0 && copysign(1.0, z.imag) < 0.0;
825         /* use True, False and None singleton as tags for the real and imag
826          * sign, to make tuples different */
827         if (real_negzero && imag_negzero) {
828             key = PyTuple_Pack(3, Py_TYPE(op), op, Py_True);
829         }
830         else if (imag_negzero) {
831             key = PyTuple_Pack(3, Py_TYPE(op), op, Py_False);
832         }
833         else if (real_negzero) {
834             key = PyTuple_Pack(3, Py_TYPE(op), op, Py_None);
835         }
836         else {
837             key = PyTuple_Pack(2, Py_TYPE(op), op);
838         }
839     }
840     else if (PyTuple_CheckExact(op)) {
841         Py_ssize_t i, len;
842         PyObject *tuple;
843 
844         len = PyTuple_GET_SIZE(op);
845         tuple = PyTuple_New(len);
846         if (tuple == NULL)
847             return NULL;
848 
849         for (i=0; i < len; i++) {
850             PyObject *item, *item_key;
851 
852             item = PyTuple_GET_ITEM(op, i);
853             item_key = _PyCode_ConstantKey(item);
854             if (item_key == NULL) {
855                 Py_DECREF(tuple);
856                 return NULL;
857             }
858 
859             PyTuple_SET_ITEM(tuple, i, item_key);
860         }
861 
862         key = PyTuple_Pack(2, tuple, op);
863         Py_DECREF(tuple);
864     }
865     else if (PyFrozenSet_CheckExact(op)) {
866         Py_ssize_t pos = 0;
867         PyObject *item;
868         Py_hash_t hash;
869         Py_ssize_t i, len;
870         PyObject *tuple, *set;
871 
872         len = PySet_GET_SIZE(op);
873         tuple = PyTuple_New(len);
874         if (tuple == NULL)
875             return NULL;
876 
877         i = 0;
878         while (_PySet_NextEntry(op, &pos, &item, &hash)) {
879             PyObject *item_key;
880 
881             item_key = _PyCode_ConstantKey(item);
882             if (item_key == NULL) {
883                 Py_DECREF(tuple);
884                 return NULL;
885             }
886 
887             assert(i < len);
888             PyTuple_SET_ITEM(tuple, i, item_key);
889             i++;
890         }
891         set = PyFrozenSet_New(tuple);
892         Py_DECREF(tuple);
893         if (set == NULL)
894             return NULL;
895 
896         key = PyTuple_Pack(2, set, op);
897         Py_DECREF(set);
898         return key;
899     }
900     else {
901         /* for other types, use the object identifier as a unique identifier
902          * to ensure that they are seen as unequal. */
903         PyObject *obj_id = PyLong_FromVoidPtr(op);
904         if (obj_id == NULL)
905             return NULL;
906 
907         key = PyTuple_Pack(2, obj_id, op);
908         Py_DECREF(obj_id);
909     }
910     return key;
911 }
912 
913 static PyObject *
code_richcompare(PyObject * self,PyObject * other,int op)914 code_richcompare(PyObject *self, PyObject *other, int op)
915 {
916     PyCodeObject *co, *cp;
917     int eq;
918     PyObject *consts1, *consts2;
919     PyObject *res;
920 
921     if ((op != Py_EQ && op != Py_NE) ||
922         !PyCode_Check(self) ||
923         !PyCode_Check(other)) {
924         Py_RETURN_NOTIMPLEMENTED;
925     }
926 
927     co = (PyCodeObject *)self;
928     cp = (PyCodeObject *)other;
929 
930     eq = PyObject_RichCompareBool(co->co_name, cp->co_name, Py_EQ);
931     if (!eq) goto unequal;
932     eq = co->co_argcount == cp->co_argcount;
933     if (!eq) goto unequal;
934     eq = co->co_posonlyargcount == cp->co_posonlyargcount;
935     if (!eq) goto unequal;
936     eq = co->co_kwonlyargcount == cp->co_kwonlyargcount;
937     if (!eq) goto unequal;
938     eq = co->co_nlocals == cp->co_nlocals;
939     if (!eq) goto unequal;
940     eq = co->co_flags == cp->co_flags;
941     if (!eq) goto unequal;
942     eq = co->co_firstlineno == cp->co_firstlineno;
943     if (!eq) goto unequal;
944     eq = PyObject_RichCompareBool(co->co_code, cp->co_code, Py_EQ);
945     if (eq <= 0) goto unequal;
946 
947     /* compare constants */
948     consts1 = _PyCode_ConstantKey(co->co_consts);
949     if (!consts1)
950         return NULL;
951     consts2 = _PyCode_ConstantKey(cp->co_consts);
952     if (!consts2) {
953         Py_DECREF(consts1);
954         return NULL;
955     }
956     eq = PyObject_RichCompareBool(consts1, consts2, Py_EQ);
957     Py_DECREF(consts1);
958     Py_DECREF(consts2);
959     if (eq <= 0) goto unequal;
960 
961     eq = PyObject_RichCompareBool(co->co_names, cp->co_names, Py_EQ);
962     if (eq <= 0) goto unequal;
963     eq = PyObject_RichCompareBool(co->co_varnames, cp->co_varnames, Py_EQ);
964     if (eq <= 0) goto unequal;
965     eq = PyObject_RichCompareBool(co->co_freevars, cp->co_freevars, Py_EQ);
966     if (eq <= 0) goto unequal;
967     eq = PyObject_RichCompareBool(co->co_cellvars, cp->co_cellvars, Py_EQ);
968     if (eq <= 0) goto unequal;
969 
970     if (op == Py_EQ)
971         res = Py_True;
972     else
973         res = Py_False;
974     goto done;
975 
976   unequal:
977     if (eq < 0)
978         return NULL;
979     if (op == Py_NE)
980         res = Py_True;
981     else
982         res = Py_False;
983 
984   done:
985     Py_INCREF(res);
986     return res;
987 }
988 
989 static Py_hash_t
code_hash(PyCodeObject * co)990 code_hash(PyCodeObject *co)
991 {
992     Py_hash_t h, h0, h1, h2, h3, h4, h5, h6;
993     h0 = PyObject_Hash(co->co_name);
994     if (h0 == -1) return -1;
995     h1 = PyObject_Hash(co->co_code);
996     if (h1 == -1) return -1;
997     h2 = PyObject_Hash(co->co_consts);
998     if (h2 == -1) return -1;
999     h3 = PyObject_Hash(co->co_names);
1000     if (h3 == -1) return -1;
1001     h4 = PyObject_Hash(co->co_varnames);
1002     if (h4 == -1) return -1;
1003     h5 = PyObject_Hash(co->co_freevars);
1004     if (h5 == -1) return -1;
1005     h6 = PyObject_Hash(co->co_cellvars);
1006     if (h6 == -1) return -1;
1007     h = h0 ^ h1 ^ h2 ^ h3 ^ h4 ^ h5 ^ h6 ^
1008         co->co_argcount ^ co->co_posonlyargcount ^ co->co_kwonlyargcount ^
1009         co->co_nlocals ^ co->co_flags;
1010     if (h == -1) h = -2;
1011     return h;
1012 }
1013 
1014 typedef struct {
1015     PyObject_HEAD
1016     PyCodeObject *li_code;
1017     PyCodeAddressRange li_line;
1018     char *li_end;
1019 } lineiterator;
1020 
1021 
1022 static void
lineiter_dealloc(lineiterator * li)1023 lineiter_dealloc(lineiterator *li)
1024 {
1025     Py_DECREF(li->li_code);
1026     Py_TYPE(li)->tp_free(li);
1027 }
1028 
1029 static PyObject *
lineiter_next(lineiterator * li)1030 lineiter_next(lineiterator *li)
1031 {
1032     PyCodeAddressRange *bounds = &li->li_line;
1033     if (!PyLineTable_NextAddressRange(bounds)) {
1034         return NULL;
1035     }
1036     PyObject *start = NULL;
1037     PyObject *end = NULL;
1038     PyObject *line = NULL;
1039     PyObject *result = PyTuple_New(3);
1040     start = PyLong_FromLong(bounds->ar_start);
1041     end = PyLong_FromLong(bounds->ar_end);
1042     if (bounds->ar_line < 0) {
1043         Py_INCREF(Py_None);
1044         line = Py_None;
1045     }
1046     else {
1047         line = PyLong_FromLong(bounds->ar_line);
1048     }
1049     if (result == NULL || start == NULL || end == NULL || line == NULL) {
1050         goto error;
1051     }
1052     PyTuple_SET_ITEM(result, 0, start);
1053     PyTuple_SET_ITEM(result, 1, end);
1054     PyTuple_SET_ITEM(result, 2, line);
1055     return result;
1056 error:
1057     Py_XDECREF(start);
1058     Py_XDECREF(end);
1059     Py_XDECREF(line);
1060     Py_XDECREF(result);
1061     return result;
1062 }
1063 
1064 static PyTypeObject LineIterator = {
1065     PyVarObject_HEAD_INIT(&PyType_Type, 0)
1066     "line_iterator",                    /* tp_name */
1067     sizeof(lineiterator),               /* tp_basicsize */
1068     0,                                  /* tp_itemsize */
1069     /* methods */
1070     (destructor)lineiter_dealloc,       /* tp_dealloc */
1071     0,                                  /* tp_vectorcall_offset */
1072     0,                                  /* tp_getattr */
1073     0,                                  /* tp_setattr */
1074     0,                                  /* tp_as_async */
1075     0,                                  /* tp_repr */
1076     0,                                  /* tp_as_number */
1077     0,                                  /* tp_as_sequence */
1078     0,                                  /* tp_as_mapping */
1079     0,                                  /* tp_hash */
1080     0,                                  /* tp_call */
1081     0,                                  /* tp_str */
1082     0,                                  /* tp_getattro */
1083     0,                                  /* tp_setattro */
1084     0,                                  /* tp_as_buffer */
1085     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,       /* tp_flags */
1086     0,                                  /* tp_doc */
1087     0,                                  /* tp_traverse */
1088     0,                                  /* tp_clear */
1089     0,                                  /* tp_richcompare */
1090     0,                                  /* tp_weaklistoffset */
1091     PyObject_SelfIter,                  /* tp_iter */
1092     (iternextfunc)lineiter_next,        /* tp_iternext */
1093     0,                                  /* tp_methods */
1094     0,                                  /* tp_members */
1095     0,                                  /* tp_getset */
1096     0,                                  /* tp_base */
1097     0,                                  /* tp_dict */
1098     0,                                  /* tp_descr_get */
1099     0,                                  /* tp_descr_set */
1100     0,                                  /* tp_dictoffset */
1101     0,                                  /* tp_init */
1102     0,                                  /* tp_alloc */
1103     0,                                  /* tp_new */
1104     PyObject_Del,                       /* tp_free */
1105 };
1106 
1107 static PyObject *
code_linesiterator(PyCodeObject * code,PyObject * Py_UNUSED (args))1108 code_linesiterator(PyCodeObject *code, PyObject *Py_UNUSED(args))
1109 {
1110     lineiterator *li = (lineiterator *)PyType_GenericAlloc(&LineIterator, 0);
1111     if (li == NULL) {
1112         return NULL;
1113     }
1114     Py_INCREF(code);
1115     li->li_code = code;
1116     _PyCode_InitAddressRange(code, &li->li_line);
1117     return (PyObject *)li;
1118 }
1119 
1120 static void
retreat(PyCodeAddressRange * bounds)1121 retreat(PyCodeAddressRange *bounds)
1122 {
1123     int ldelta = ((signed char *)bounds->opaque.lo_next)[-1];
1124     if (ldelta == -128) {
1125         ldelta = 0;
1126     }
1127     bounds->opaque.computed_line -= ldelta;
1128     bounds->opaque.lo_next -= 2;
1129     bounds->ar_end = bounds->ar_start;
1130     bounds->ar_start -= ((unsigned char *)bounds->opaque.lo_next)[-2];
1131     ldelta = ((signed char *)bounds->opaque.lo_next)[-1];
1132     if (ldelta == -128) {
1133         bounds->ar_line = -1;
1134     }
1135     else {
1136         bounds->ar_line = bounds->opaque.computed_line;
1137     }
1138 }
1139 
1140 static void
advance(PyCodeAddressRange * bounds)1141 advance(PyCodeAddressRange *bounds)
1142 {
1143     bounds->ar_start = bounds->ar_end;
1144     int delta = ((unsigned char *)bounds->opaque.lo_next)[0];
1145     bounds->ar_end += delta;
1146     int ldelta = ((signed char *)bounds->opaque.lo_next)[1];
1147     bounds->opaque.lo_next += 2;
1148     if (ldelta == -128) {
1149         bounds->ar_line = -1;
1150     }
1151     else {
1152         bounds->opaque.computed_line += ldelta;
1153         bounds->ar_line = bounds->opaque.computed_line;
1154     }
1155 }
1156 
1157 static inline int
at_end(PyCodeAddressRange * bounds)1158 at_end(PyCodeAddressRange *bounds) {
1159     return bounds->opaque.lo_next >= bounds->opaque.limit;
1160 }
1161 
1162 int
PyLineTable_PreviousAddressRange(PyCodeAddressRange * range)1163 PyLineTable_PreviousAddressRange(PyCodeAddressRange *range)
1164 {
1165     if (range->ar_start <= 0) {
1166         return 0;
1167     }
1168     retreat(range);
1169     while (range->ar_start == range->ar_end) {
1170         assert(range->ar_start > 0);
1171         retreat(range);
1172     }
1173     return 1;
1174 }
1175 
1176 int
PyLineTable_NextAddressRange(PyCodeAddressRange * range)1177 PyLineTable_NextAddressRange(PyCodeAddressRange *range)
1178 {
1179     if (at_end(range)) {
1180         return 0;
1181     }
1182     advance(range);
1183     while (range->ar_start == range->ar_end) {
1184         assert(!at_end(range));
1185         advance(range);
1186     }
1187     return 1;
1188 }
1189 
1190 
1191 /* XXX code objects need to participate in GC? */
1192 
1193 static struct PyMethodDef code_methods[] = {
1194     {"__sizeof__", (PyCFunction)code_sizeof, METH_NOARGS},
1195     {"co_lines", (PyCFunction)code_linesiterator, METH_NOARGS},
1196     CODE_REPLACE_METHODDEF
1197     {NULL, NULL}                /* sentinel */
1198 };
1199 
1200 PyTypeObject PyCode_Type = {
1201     PyVarObject_HEAD_INIT(&PyType_Type, 0)
1202     "code",
1203     sizeof(PyCodeObject),
1204     0,
1205     (destructor)code_dealloc,           /* tp_dealloc */
1206     0,                                  /* tp_vectorcall_offset */
1207     0,                                  /* tp_getattr */
1208     0,                                  /* tp_setattr */
1209     0,                                  /* tp_as_async */
1210     (reprfunc)code_repr,                /* tp_repr */
1211     0,                                  /* tp_as_number */
1212     0,                                  /* tp_as_sequence */
1213     0,                                  /* tp_as_mapping */
1214     (hashfunc)code_hash,                /* tp_hash */
1215     0,                                  /* tp_call */
1216     0,                                  /* tp_str */
1217     PyObject_GenericGetAttr,            /* tp_getattro */
1218     0,                                  /* tp_setattro */
1219     0,                                  /* tp_as_buffer */
1220     Py_TPFLAGS_DEFAULT,                 /* tp_flags */
1221     code_new__doc__,                    /* tp_doc */
1222     0,                                  /* tp_traverse */
1223     0,                                  /* tp_clear */
1224     code_richcompare,                   /* tp_richcompare */
1225     offsetof(PyCodeObject, co_weakreflist),     /* tp_weaklistoffset */
1226     0,                                  /* tp_iter */
1227     0,                                  /* tp_iternext */
1228     code_methods,                       /* tp_methods */
1229     code_memberlist,                    /* tp_members */
1230     code_getsetlist,                    /* tp_getset */
1231     0,                                  /* tp_base */
1232     0,                                  /* tp_dict */
1233     0,                                  /* tp_descr_get */
1234     0,                                  /* tp_descr_set */
1235     0,                                  /* tp_dictoffset */
1236     0,                                  /* tp_init */
1237     0,                                  /* tp_alloc */
1238     code_new,                           /* tp_new */
1239 };
1240 
1241 /* Use co_linetable to compute the line number from a bytecode index, addrq.  See
1242    lnotab_notes.txt for the details of the lnotab representation.
1243 */
1244 
1245 int
PyCode_Addr2Line(PyCodeObject * co,int addrq)1246 PyCode_Addr2Line(PyCodeObject *co, int addrq)
1247 {
1248     if (addrq < 0) {
1249         return co->co_firstlineno;
1250     }
1251     assert(addrq >= 0 && addrq < PyBytes_GET_SIZE(co->co_code));
1252     PyCodeAddressRange bounds;
1253     _PyCode_InitAddressRange(co, &bounds);
1254     return _PyCode_CheckLineNumber(addrq, &bounds);
1255 }
1256 
1257 void
PyLineTable_InitAddressRange(const char * linetable,Py_ssize_t length,int firstlineno,PyCodeAddressRange * range)1258 PyLineTable_InitAddressRange(const char *linetable, Py_ssize_t length, int firstlineno, PyCodeAddressRange *range)
1259 {
1260     range->opaque.lo_next = linetable;
1261     range->opaque.limit = range->opaque.lo_next + length;
1262     range->ar_start = -1;
1263     range->ar_end = 0;
1264     range->opaque.computed_line = firstlineno;
1265     range->ar_line = -1;
1266 }
1267 
1268 int
_PyCode_InitAddressRange(PyCodeObject * co,PyCodeAddressRange * bounds)1269 _PyCode_InitAddressRange(PyCodeObject* co, PyCodeAddressRange *bounds)
1270 {
1271     const char *linetable = PyBytes_AS_STRING(co->co_linetable);
1272     Py_ssize_t length = PyBytes_GET_SIZE(co->co_linetable);
1273     PyLineTable_InitAddressRange(linetable, length, co->co_firstlineno, bounds);
1274     return bounds->ar_line;
1275 }
1276 
1277 /* Update *bounds to describe the first and one-past-the-last instructions in
1278    the same line as lasti.  Return the number of that line, or -1 if lasti is out of bounds. */
1279 int
_PyCode_CheckLineNumber(int lasti,PyCodeAddressRange * bounds)1280 _PyCode_CheckLineNumber(int lasti, PyCodeAddressRange *bounds)
1281 {
1282     while (bounds->ar_end <= lasti) {
1283         if (!PyLineTable_NextAddressRange(bounds)) {
1284             return -1;
1285         }
1286     }
1287     while (bounds->ar_start > lasti) {
1288         if (!PyLineTable_PreviousAddressRange(bounds)) {
1289             return -1;
1290         }
1291     }
1292     return bounds->ar_line;
1293 }
1294 
1295 
1296 int
_PyCode_GetExtra(PyObject * code,Py_ssize_t index,void ** extra)1297 _PyCode_GetExtra(PyObject *code, Py_ssize_t index, void **extra)
1298 {
1299     if (!PyCode_Check(code)) {
1300         PyErr_BadInternalCall();
1301         return -1;
1302     }
1303 
1304     PyCodeObject *o = (PyCodeObject*) code;
1305     _PyCodeObjectExtra *co_extra = (_PyCodeObjectExtra*) o->co_extra;
1306 
1307     if (co_extra == NULL || co_extra->ce_size <= index) {
1308         *extra = NULL;
1309         return 0;
1310     }
1311 
1312     *extra = co_extra->ce_extras[index];
1313     return 0;
1314 }
1315 
1316 
1317 int
_PyCode_SetExtra(PyObject * code,Py_ssize_t index,void * extra)1318 _PyCode_SetExtra(PyObject *code, Py_ssize_t index, void *extra)
1319 {
1320     PyInterpreterState *interp = _PyInterpreterState_GET();
1321 
1322     if (!PyCode_Check(code) || index < 0 ||
1323             index >= interp->co_extra_user_count) {
1324         PyErr_BadInternalCall();
1325         return -1;
1326     }
1327 
1328     PyCodeObject *o = (PyCodeObject*) code;
1329     _PyCodeObjectExtra *co_extra = (_PyCodeObjectExtra *) o->co_extra;
1330 
1331     if (co_extra == NULL || co_extra->ce_size <= index) {
1332         Py_ssize_t i = (co_extra == NULL ? 0 : co_extra->ce_size);
1333         co_extra = PyMem_Realloc(
1334                 co_extra,
1335                 sizeof(_PyCodeObjectExtra) +
1336                 (interp->co_extra_user_count-1) * sizeof(void*));
1337         if (co_extra == NULL) {
1338             return -1;
1339         }
1340         for (; i < interp->co_extra_user_count; i++) {
1341             co_extra->ce_extras[i] = NULL;
1342         }
1343         co_extra->ce_size = interp->co_extra_user_count;
1344         o->co_extra = co_extra;
1345     }
1346 
1347     if (co_extra->ce_extras[index] != NULL) {
1348         freefunc free = interp->co_extra_freefuncs[index];
1349         if (free != NULL) {
1350             free(co_extra->ce_extras[index]);
1351         }
1352     }
1353 
1354     co_extra->ce_extras[index] = extra;
1355     return 0;
1356 }
1357