/home/mdboom/Work/builds/cpython/Objects/codeobject.c
Line | Count | Source (jump to first uncovered line) |
1 | #include <stdbool.h> |
2 | |
3 | #include "Python.h" |
4 | #include "opcode.h" |
5 | #include "structmember.h" // PyMemberDef |
6 | #include "pycore_code.h" // _PyCodeConstructor |
7 | #include "pycore_frame.h" // FRAME_SPECIALS_SIZE |
8 | #include "pycore_interp.h" // PyInterpreterState.co_extra_freefuncs |
9 | #include "pycore_opcode.h" // _PyOpcode_Deopt |
10 | #include "pycore_pystate.h" // _PyInterpreterState_GET() |
11 | #include "pycore_tuple.h" // _PyTuple_ITEMS() |
12 | #include "clinic/codeobject.c.h" |
13 | |
14 | |
15 | /****************** |
16 | * generic helpers |
17 | ******************/ |
18 | |
19 | /* all_name_chars(s): true iff s matches [a-zA-Z0-9_]* */ |
20 | static int |
21 | all_name_chars(PyObject *o) |
22 | { |
23 | const unsigned char *s, *e; |
24 | |
25 | if (!PyUnicode_IS_ASCII(o)) Branch (25:9): [True: 7.74k, False: 1.36M]
|
26 | return 0; |
27 | |
28 | s = PyUnicode_1BYTE_DATA(o); |
29 | e = s + PyUnicode_GET_LENGTH(o); |
30 | for (; s != e; s++7.78M ) { Branch (30:12): [True: 8.30M, False: 845k]
|
31 | if (!Py_ISALNUM(*s) && *s != '_'982k ) Branch (31:13): [True: 982k, False: 7.32M]
Branch (31:32): [True: 523k, False: 458k]
|
32 | return 0; |
33 | } |
34 | return 1; |
35 | } |
36 | |
37 | static int |
38 | intern_strings(PyObject *tuple) |
39 | { |
40 | Py_ssize_t i; |
41 | |
42 | for (i = PyTuple_GET_SIZE955k (tuple); --i >= 0; ) { Branch (42:39): [True: 3.86M, False: 955k]
|
43 | PyObject *v = PyTuple_GET_ITEM(tuple, i); |
44 | if (v == NULL || !PyUnicode_CheckExact(v)) { Branch (44:13): [True: 0, False: 3.86M]
Branch (44:26): [True: 0, False: 3.86M]
|
45 | PyErr_SetString(PyExc_SystemError, |
46 | "non-string found in code slot"); |
47 | return -1; |
48 | } |
49 | PyUnicode_InternInPlace(&_PyTuple_ITEMS(tuple)[i]); |
50 | } |
51 | return 0; |
52 | } |
53 | |
54 | /* Intern selected string constants */ |
55 | static int |
56 | intern_string_constants(PyObject *tuple, int *modified) |
57 | { |
58 | for (Py_ssize_t i = PyTuple_GET_SIZE657k (tuple); --i >= 0; ) { Branch (58:50): [True: 2.98M, False: 657k]
|
59 | PyObject *v = PyTuple_GET_ITEM(tuple, i); |
60 | if (PyUnicode_CheckExact(v)) { |
61 | if (PyUnicode_READY(v) == -1) { Branch (61:17): [True: 0, False: 1.37M]
|
62 | return -1; |
63 | } |
64 | |
65 | if (all_name_chars(v)) { Branch (65:17): [True: 845k, False: 531k]
|
66 | PyObject *w = v; |
67 | PyUnicode_InternInPlace(&v); |
68 | if (w != v) { Branch (68:21): [True: 19.1k, False: 825k]
|
69 | PyTuple_SET_ITEM(tuple, i, v); |
70 | if (modified) { Branch (70:25): [True: 199, False: 18.9k]
|
71 | *modified = 1; |
72 | } |
73 | } |
74 | } |
75 | } |
76 | else if (PyTuple_CheckExact(v)) { |
77 | if (intern_string_constants(v, NULL) < 0) { Branch (77:17): [True: 0, False: 179k]
|
78 | return -1; |
79 | } |
80 | } |
81 | else if (PyFrozenSet_CheckExact(v)) { |
82 | PyObject *w = v; |
83 | PyObject *tmp = PySequence_Tuple(v); |
84 | if (tmp == NULL) { Branch (84:17): [True: 0, False: 541]
|
85 | return -1; |
86 | } |
87 | int tmp_modified = 0; |
88 | if (intern_string_constants(tmp, &tmp_modified) < 0) { Branch (88:17): [True: 0, False: 541]
|
89 | Py_DECREF(tmp); |
90 | return -1; |
91 | } |
92 | if (tmp_modified) { Branch (92:17): [True: 61, False: 480]
|
93 | v = PyFrozenSet_New(tmp); |
94 | if (v == NULL) { Branch (94:21): [True: 0, False: 61]
|
95 | Py_DECREF(tmp); |
96 | return -1; |
97 | } |
98 | |
99 | PyTuple_SET_ITEM(tuple, i, v); |
100 | Py_DECREF(w); |
101 | if (modified) { Branch (101:21): [True: 0, False: 61]
|
102 | *modified = 1; |
103 | } |
104 | } |
105 | Py_DECREF(tmp); |
106 | } |
107 | } |
108 | return 0; |
109 | } |
110 | |
111 | /* Return a shallow copy of a tuple that is |
112 | guaranteed to contain exact strings, by converting string subclasses |
113 | to exact strings and complaining if a non-string is found. */ |
114 | static PyObject* |
115 | validate_and_copy_tuple(PyObject *tup) |
116 | { |
117 | PyObject *newtuple; |
118 | PyObject *item; |
119 | Py_ssize_t i, len; |
120 | |
121 | len = PyTuple_GET_SIZE(tup); |
122 | newtuple = PyTuple_New(len); |
123 | if (newtuple == NULL) Branch (123:9): [True: 0, False: 12]
|
124 | return NULL; |
125 | |
126 | for (i = 0; 12 i < len; i++2 ) { Branch (126:17): [True: 2, False: 12]
|
127 | item = PyTuple_GET_ITEM(tup, i); |
128 | if (PyUnicode_CheckExact(item)) { |
129 | Py_INCREF(item); |
130 | } |
131 | else if (!PyUnicode_Check(item)) { Branch (131:18): [True: 0, False: 0]
|
132 | PyErr_Format( |
133 | PyExc_TypeError, |
134 | "name tuples must contain only " |
135 | "strings, not '%.500s'", |
136 | Py_TYPE(item)->tp_name); |
137 | Py_DECREF(newtuple); |
138 | return NULL; |
139 | } |
140 | else { |
141 | item = _PyUnicode_Copy(item); |
142 | if (item == NULL) { Branch (142:17): [True: 0, False: 0]
|
143 | Py_DECREF(newtuple); |
144 | return NULL; |
145 | } |
146 | } |
147 | PyTuple_SET_ITEM(newtuple, i, item); |
148 | } |
149 | |
150 | return newtuple; |
151 | } |
152 | |
153 | |
154 | /****************** |
155 | * _PyCode_New() |
156 | ******************/ |
157 | |
158 | // This is also used in compile.c. |
159 | void |
160 | _Py_set_localsplus_info(int offset, PyObject *name, _PyLocals_Kind kind, |
161 | PyObject *names, PyObject *kinds) |
162 | { |
163 | Py_INCREF(name); |
164 | PyTuple_SET_ITEM(names, offset, name); |
165 | _PyLocals_SetKind(kinds, offset, kind); |
166 | } |
167 | |
168 | static void |
169 | get_localsplus_counts(PyObject *names, PyObject *kinds, |
170 | int *pnlocals, int *pnplaincellvars, int *pncellvars, |
171 | int *pnfreevars) |
172 | { |
173 | int nlocals = 0; |
174 | int nplaincellvars = 0; |
175 | int ncellvars = 0; |
176 | int nfreevars = 0; |
177 | Py_ssize_t nlocalsplus = PyTuple_GET_SIZE(names); |
178 | for (int i = 0; i < nlocalsplus; i++1.24M ) { Branch (178:21): [True: 1.24M, False: 526k]
|
179 | _PyLocals_Kind kind = _PyLocals_GetKind(kinds, i); |
180 | if (kind & CO_FAST_LOCAL) { Branch (180:13): [True: 1.15M, False: 93.6k]
|
181 | nlocals += 1; |
182 | if (kind & CO_FAST_CELL) { Branch (182:17): [True: 19.6k, False: 1.13M]
|
183 | ncellvars += 1; |
184 | } |
185 | } |
186 | else if (kind & CO_FAST_CELL) { Branch (186:18): [True: 26.7k, False: 66.8k]
|
187 | ncellvars += 1; |
188 | nplaincellvars += 1; |
189 | } |
190 | else if (kind & CO_FAST_FREE) { Branch (190:18): [True: 66.8k, False: 0]
|
191 | nfreevars += 1; |
192 | } |
193 | } |
194 | if (pnlocals != NULL) { Branch (194:9): [True: 526k, False: 0]
|
195 | *pnlocals = nlocals; |
196 | } |
197 | if (pnplaincellvars != NULL) { Branch (197:9): [True: 263k, False: 263k]
|
198 | *pnplaincellvars = nplaincellvars; |
199 | } |
200 | if (pncellvars != NULL) { Branch (200:9): [True: 263k, False: 263k]
|
201 | *pncellvars = ncellvars; |
202 | } |
203 | if (pnfreevars != NULL) { Branch (203:9): [True: 263k, False: 263k]
|
204 | *pnfreevars = nfreevars; |
205 | } |
206 | } |
207 | |
208 | static PyObject * |
209 | get_localsplus_names(PyCodeObject *co, _PyLocals_Kind kind, int num) |
210 | { |
211 | PyObject *names = PyTuple_New(num); |
212 | if (names == NULL) { Branch (212:9): [True: 0, False: 3.35k]
|
213 | return NULL; |
214 | } |
215 | int index = 0; |
216 | for (int offset = 0; offset < co->co_nlocalsplus; offset++10.2k ) { Branch (216:26): [True: 10.2k, False: 3.35k]
|
217 | _PyLocals_Kind k = _PyLocals_GetKind(co->co_localspluskinds, offset); |
218 | if ((k & kind) == 0) { Branch (218:13): [True: 479, False: 9.74k]
|
219 | continue; |
220 | } |
221 | assert(index < num); |
222 | PyObject *name = PyTuple_GET_ITEM(co->co_localsplusnames, offset); |
223 | Py_INCREF(name); |
224 | PyTuple_SET_ITEM(names, index, name); |
225 | index += 1; |
226 | } |
227 | assert(index == num); |
228 | return names; |
229 | } |
230 | |
231 | int |
232 | _PyCode_Validate(struct _PyCodeConstructor *con) |
233 | { |
234 | /* Check argument types */ |
235 | if (con->argcount < con->posonlyargcount || con->posonlyargcount < 0 || Branch (235:9): [True: 0, False: 263k]
Branch (235:49): [True: 0, False: 263k]
|
236 | con->kwonlyargcount < 0 || Branch (236:9): [True: 0, False: 263k]
|
237 | con->stacksize < 0 || con->flags < 0 || Branch (237:9): [True: 0, False: 263k]
Branch (237:31): [True: 0, False: 263k]
|
238 | con->code == NULL || !PyBytes_Check(con->code) || Branch (238:9): [True: 0, False: 263k]
Branch (238:30): [True: 0, False: 263k]
|
239 | con->consts == NULL || !PyTuple_Check(con->consts) || Branch (239:9): [True: 0, False: 263k]
Branch (239:32): [True: 0, False: 263k]
|
240 | con->names == NULL || !PyTuple_Check(con->names) || Branch (240:9): [True: 0, False: 263k]
Branch (240:31): [True: 0, False: 263k]
|
241 | con->localsplusnames == NULL || !PyTuple_Check(con->localsplusnames) || Branch (241:9): [True: 0, False: 263k]
Branch (241:41): [True: 0, False: 263k]
|
242 | con->localspluskinds == NULL || !PyBytes_Check(con->localspluskinds) || Branch (242:9): [True: 0, False: 263k]
Branch (242:41): [True: 0, False: 263k]
|
243 | PyTuple_GET_SIZE(con->localsplusnames) Branch (243:9): [True: 0, False: 263k]
|
244 | != PyBytes_GET_SIZE(con->localspluskinds) || |
245 | con->name == NULL || !PyUnicode_Check(con->name) || Branch (245:9): [True: 0, False: 263k]
Branch (245:30): [True: 0, False: 263k]
|
246 | con->qualname == NULL || !PyUnicode_Check(con->qualname) || Branch (246:9): [True: 0, False: 263k]
Branch (246:34): [True: 0, False: 263k]
|
247 | con->filename == NULL || !PyUnicode_Check(con->filename) || Branch (247:9): [True: 0, False: 263k]
Branch (247:34): [True: 0, False: 263k]
|
248 | con->linetable == NULL || !PyBytes_Check(con->linetable) || Branch (248:9): [True: 0, False: 263k]
Branch (248:35): [True: 0, False: 263k]
|
249 | con->exceptiontable == NULL || !PyBytes_Check(con->exceptiontable) Branch (249:9): [True: 0, False: 263k]
Branch (249:40): [True: 0, False: 263k]
|
250 | ) { |
251 | PyErr_BadInternalCall(); |
252 | return -1; |
253 | } |
254 | |
255 | /* Make sure that code is indexable with an int, this is |
256 | a long running assumption in ceval.c and many parts of |
257 | the interpreter. */ |
258 | if (PyBytes_GET_SIZE(con->code) > INT_MAX) { Branch (258:9): [True: 0, False: 263k]
|
259 | PyErr_SetString(PyExc_OverflowError, |
260 | "code: co_code larger than INT_MAX"); |
261 | return -1; |
262 | } |
263 | if (PyBytes_GET_SIZE(con->code) % sizeof(_Py_CODEUNIT) != 0 || Branch (263:9): [True: 0, False: 263k]
|
264 | !_Py_IS_ALIGNED(PyBytes_AS_STRING(con->code), sizeof(_Py_CODEUNIT)) Branch (264:9): [True: 0, False: 263k]
|
265 | ) { |
266 | PyErr_SetString(PyExc_ValueError, "code: co_code is malformed"); |
267 | return -1; |
268 | } |
269 | |
270 | /* Ensure that the co_varnames has enough names to cover the arg counts. |
271 | * Note that totalargs = nlocals - nplainlocals. We check nplainlocals |
272 | * here to avoid the possibility of overflow (however remote). */ |
273 | int nlocals; |
274 | get_localsplus_counts(con->localsplusnames, con->localspluskinds, |
275 | &nlocals, NULL, NULL, NULL); |
276 | int nplainlocals = nlocals - |
277 | con->argcount - |
278 | con->kwonlyargcount - |
279 | ((con->flags & CO_VARARGS) != 0) - |
280 | ((con->flags & CO_VARKEYWORDS) != 0); |
281 | if (nplainlocals < 0) { Branch (281:9): [True: 0, False: 263k]
|
282 | PyErr_SetString(PyExc_ValueError, "code: co_varnames is too small"); |
283 | return -1; |
284 | } |
285 | |
286 | return 0; |
287 | } |
288 | |
289 | static void |
290 | init_code(PyCodeObject *co, struct _PyCodeConstructor *con) |
291 | { |
292 | int nlocalsplus = (int)PyTuple_GET_SIZE(con->localsplusnames); |
293 | int nlocals, nplaincellvars, ncellvars, nfreevars; |
294 | get_localsplus_counts(con->localsplusnames, con->localspluskinds, |
295 | &nlocals, &nplaincellvars, &ncellvars, &nfreevars); |
296 | |
297 | Py_INCREF(con->filename); |
298 | co->co_filename = con->filename; |
299 | Py_INCREF(con->name); |
300 | co->co_name = con->name; |
301 | Py_INCREF(con->qualname); |
302 | co->co_qualname = con->qualname; |
303 | co->co_flags = con->flags; |
304 | |
305 | co->co_firstlineno = con->firstlineno; |
306 | Py_INCREF(con->linetable); |
307 | co->co_linetable = con->linetable; |
308 | |
309 | Py_INCREF(con->consts); |
310 | co->co_consts = con->consts; |
311 | Py_INCREF(con->names); |
312 | co->co_names = con->names; |
313 | |
314 | Py_INCREF(con->localsplusnames); |
315 | co->co_localsplusnames = con->localsplusnames; |
316 | Py_INCREF(con->localspluskinds); |
317 | co->co_localspluskinds = con->localspluskinds; |
318 | |
319 | co->co_argcount = con->argcount; |
320 | co->co_posonlyargcount = con->posonlyargcount; |
321 | co->co_kwonlyargcount = con->kwonlyargcount; |
322 | |
323 | co->co_stacksize = con->stacksize; |
324 | |
325 | Py_INCREF(con->exceptiontable); |
326 | co->co_exceptiontable = con->exceptiontable; |
327 | |
328 | /* derived values */ |
329 | co->co_nlocalsplus = nlocalsplus; |
330 | co->co_nlocals = nlocals; |
331 | co->co_framesize = nlocalsplus + con->stacksize + FRAME_SPECIALS_SIZE; |
332 | co->co_nplaincellvars = nplaincellvars; |
333 | co->co_ncellvars = ncellvars; |
334 | co->co_nfreevars = nfreevars; |
335 | |
336 | /* not set */ |
337 | co->co_weakreflist = NULL; |
338 | co->co_extra = NULL; |
339 | co->_co_code = NULL; |
340 | |
341 | co->co_warmup = QUICKENING_INITIAL_WARMUP_VALUE; |
342 | co->_co_linearray_entry_size = 0; |
343 | co->_co_linearray = NULL; |
344 | memcpy(_PyCode_CODE(co), PyBytes_AS_STRING(con->code), |
345 | PyBytes_GET_SIZE(con->code)); |
346 | int entry_point = 0; |
347 | while (entry_point < Py_SIZE(co) && Branch (347:12): [True: 327k, False: 0]
|
348 | _Py_OPCODE(_PyCode_CODE(co)[entry_point]) != RESUME) { Branch (348:9): [True: 64.3k, False: 263k]
|
349 | entry_point++; |
350 | } |
351 | co->_co_firsttraceable = entry_point; |
352 | } |
353 | |
354 | static int |
355 | scan_varint(const uint8_t *ptr) |
356 | { |
357 | unsigned int read = *ptr++; |
358 | unsigned int val = read & 63; |
359 | unsigned int shift = 0; |
360 | while (read & 64) { Branch (360:12): [True: 234k, False: 36.3M]
|
361 | read = *ptr++; |
362 | shift += 6; |
363 | val |= (read & 63) << shift; |
364 | } |
365 | return val; |
366 | } |
367 | |
368 | static int |
369 | scan_signed_varint(const uint8_t *ptr) |
370 | { |
371 | unsigned int uval = scan_varint(ptr); |
372 | if (uval & 1) { Branch (372:9): [True: 3.41M, False: 32.9M]
|
373 | return -(int)(uval >> 1); |
374 | } |
375 | else { |
376 | return uval >> 1; |
377 | } |
378 | } |
379 | |
380 | static int |
381 | get_line_delta(const uint8_t *ptr) |
382 | { |
383 | int code = ((*ptr) >> 3) & 15; |
384 | switch (code) { |
385 | case PY_CODE_LOCATION_INFO_NONE: Branch (385:9): [True: 1.26M, False: 155M]
|
386 | return 0; |
387 | case PY_CODE_LOCATION_INFO_NO_COLUMNS: Branch (387:9): [True: 9.99M, False: 146M]
|
388 | case PY_CODE_LOCATION_INFO_LONG: Branch (388:9): [True: 26.3M, False: 130M]
|
389 | return scan_signed_varint(ptr+1); |
390 | case PY_CODE_LOCATION_INFO_ONE_LINE0: Branch (390:9): [True: 31.2M, False: 125M]
|
391 | return 0; |
392 | case PY_CODE_LOCATION_INFO_ONE_LINE1: Branch (392:9): [True: 15.0M, False: 141M]
|
393 | return 1; |
394 | case PY_CODE_LOCATION_INFO_ONE_LINE2: Branch (394:9): [True: 2.75M, False: 153M]
|
395 | return 2; |
396 | default: Branch (396:9): [True: 69.6M, False: 86.7M]
|
397 | /* Same line */ |
398 | return 0; |
399 | } |
400 | } |
401 | |
402 | static PyObject * |
403 | remove_column_info(PyObject *locations) |
404 | { |
405 | int offset = 0; |
406 | const uint8_t *data = (const uint8_t *)PyBytes_AS_STRING(locations); |
407 | PyObject *res = PyBytes_FromStringAndSize(NULL, 32); |
408 | if (res == NULL) { Branch (408:9): [True: 0, False: 2.35k]
|
409 | PyErr_NoMemory(); |
410 | return NULL; |
411 | } |
412 | uint8_t *output = (uint8_t *)PyBytes_AS_STRING(res); |
413 | while (offset < PyBytes_GET_SIZE(locations)) { Branch (413:12): [True: 114k, False: 2.35k]
|
414 | Py_ssize_t write_offset = output - (uint8_t *)PyBytes_AS_STRING(res); |
415 | if (write_offset + 16 >= PyBytes_GET_SIZE(res)) { Branch (415:13): [True: 3.54k, False: 111k]
|
416 | if (_PyBytes_Resize(&res, PyBytes_GET_SIZE(res) * 2) < 0) { Branch (416:17): [True: 0, False: 3.54k]
|
417 | return NULL; |
418 | } |
419 | output = (uint8_t *)PyBytes_AS_STRING(res) + write_offset; |
420 | } |
421 | int code = (data[offset] >> 3) & 15; |
422 | if (code == PY_CODE_LOCATION_INFO_NONE) { Branch (422:13): [True: 2.21k, False: 112k]
|
423 | *output++ = data[offset]; |
424 | } |
425 | else { |
426 | int blength = (data[offset] & 7)+1; |
427 | output += write_location_entry_start( |
428 | output, PY_CODE_LOCATION_INFO_NO_COLUMNS, blength); |
429 | int ldelta = get_line_delta(&data[offset]); |
430 | output += write_signed_varint(output, ldelta); |
431 | } |
432 | offset++; |
433 | while (offset < PyBytes_GET_SIZE(locations) && Branch (433:16): [True: 341k, False: 2.35k]
|
434 | (data[offset] & 128) == 0341k ) { Branch (434:13): [True: 229k, False: 112k]
|
435 | offset++; |
436 | } |
437 | } |
438 | Py_ssize_t write_offset = output - (uint8_t *)PyBytes_AS_STRING(res); |
439 | if (_PyBytes_Resize(&res, write_offset)) { Branch (439:9): [True: 0, False: 2.35k]
|
440 | return NULL; |
441 | } |
442 | return res; |
443 | } |
444 | |
445 | /* The caller is responsible for ensuring that the given data is valid. */ |
446 | |
447 | PyCodeObject * |
448 | _PyCode_New(struct _PyCodeConstructor *con) |
449 | { |
450 | /* Ensure that strings are ready Unicode string */ |
451 | if (PyUnicode_READY(con->name) < 0) { Branch (451:9): [True: 0, False: 263k]
|
452 | return NULL; |
453 | } |
454 | if (PyUnicode_READY(con->qualname) < 0) { Branch (454:9): [True: 0, False: 263k]
|
455 | return NULL; |
456 | } |
457 | if (PyUnicode_READY(con->filename) < 0) { Branch (457:9): [True: 0, False: 263k]
|
458 | return NULL; |
459 | } |
460 | |
461 | if (intern_strings(con->names) < 0) { Branch (461:9): [True: 0, False: 263k]
|
462 | return NULL; |
463 | } |
464 | if (intern_string_constants(con->consts, NULL) < 0) { Branch (464:9): [True: 0, False: 263k]
|
465 | return NULL; |
466 | } |
467 | if (intern_strings(con->localsplusnames) < 0) { Branch (467:9): [True: 0, False: 263k]
|
468 | return NULL; |
469 | } |
470 | |
471 | PyObject *replacement_locations = NULL; |
472 | // Compact the linetable if we are opted out of debug |
473 | // ranges. |
474 | if (!_Py_GetConfig()->code_debug_ranges) { Branch (474:9): [True: 2.35k, False: 261k]
|
475 | replacement_locations = remove_column_info(con->linetable); |
476 | if (replacement_locations == NULL) { Branch (476:13): [True: 0, False: 2.35k]
|
477 | return NULL; |
478 | } |
479 | con->linetable = replacement_locations; |
480 | } |
481 | |
482 | Py_ssize_t size = PyBytes_GET_SIZE(con->code) / sizeof(_Py_CODEUNIT); |
483 | PyCodeObject *co = PyObject_NewVar(PyCodeObject, &PyCode_Type, size); |
484 | if (co == NULL) { Branch (484:9): [True: 0, False: 263k]
|
485 | Py_XDECREF(replacement_locations); |
486 | PyErr_NoMemory(); |
487 | return NULL; |
488 | } |
489 | init_code(co, con); |
490 | Py_XDECREF(replacement_locations); |
491 | return co; |
492 | } |
493 | |
494 | |
495 | /****************** |
496 | * the legacy "constructors" |
497 | ******************/ |
498 | |
499 | PyCodeObject * |
500 | PyCode_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount, |
501 | int nlocals, int stacksize, int flags, |
502 | PyObject *code, PyObject *consts, PyObject *names, |
503 | PyObject *varnames, PyObject *freevars, PyObject *cellvars, |
504 | PyObject *filename, PyObject *name, |
505 | PyObject *qualname, int firstlineno, |
506 | PyObject *linetable, |
507 | PyObject *exceptiontable) |
508 | { |
509 | PyCodeObject *co = NULL; |
510 | PyObject *localsplusnames = NULL; |
511 | PyObject *localspluskinds = NULL; |
512 | |
513 | if (varnames == NULL || !PyTuple_Check(varnames) || Branch (513:9): [True: 0, False: 70]
Branch (513:29): [True: 0, False: 70]
|
514 | cellvars == NULL || !PyTuple_Check(cellvars) || Branch (514:9): [True: 0, False: 70]
Branch (514:29): [True: 0, False: 70]
|
515 | freevars == NULL || !PyTuple_Check(freevars) Branch (515:9): [True: 0, False: 70]
Branch (515:29): [True: 0, False: 70]
|
516 | ) { |
517 | PyErr_BadInternalCall(); |
518 | return NULL; |
519 | } |
520 | |
521 | // Set the "fast locals plus" info. |
522 | int nvarnames = (int)PyTuple_GET_SIZE(varnames); |
523 | int ncellvars = (int)PyTuple_GET_SIZE(cellvars); |
524 | int nfreevars = (int)PyTuple_GET_SIZE(freevars); |
525 | int nlocalsplus = nvarnames + ncellvars + nfreevars; |
526 | localsplusnames = PyTuple_New(nlocalsplus); |
527 | if (localsplusnames == NULL) { Branch (527:9): [True: 0, False: 70]
|
528 | goto error; |
529 | } |
530 | localspluskinds = PyBytes_FromStringAndSize(NULL, nlocalsplus); |
531 | if (localspluskinds == NULL) { Branch (531:9): [True: 0, False: 70]
|
532 | goto error; |
533 | } |
534 | int offset = 0; |
535 | for (int i = 0; i < nvarnames; i++, offset++53 ) { Branch (535:21): [True: 53, False: 70]
|
536 | PyObject *name = PyTuple_GET_ITEM(varnames, i); |
537 | _Py_set_localsplus_info(offset, name, CO_FAST_LOCAL, |
538 | localsplusnames, localspluskinds); |
539 | } |
540 | for (int i = 0; i < ncellvars; i++, offset++2 ) { Branch (540:21): [True: 2, False: 70]
|
541 | PyObject *name = PyTuple_GET_ITEM(cellvars, i); |
542 | int argoffset = -1; |
543 | for (int j = 0; j < nvarnames; j++1 ) { Branch (543:25): [True: 2, False: 1]
|
544 | int cmp = PyUnicode_Compare(PyTuple_GET_ITEM(varnames, j), |
545 | name); |
546 | assert(!PyErr_Occurred()); |
547 | if (cmp == 0) { Branch (547:17): [True: 1, False: 1]
|
548 | argoffset = j; |
549 | break; |
550 | } |
551 | } |
552 | if (argoffset >= 0) { Branch (552:13): [True: 1, False: 1]
|
553 | // Merge the localsplus indices. |
554 | nlocalsplus -= 1; |
555 | offset -= 1; |
556 | _PyLocals_Kind kind = _PyLocals_GetKind(localspluskinds, argoffset); |
557 | _PyLocals_SetKind(localspluskinds, argoffset, kind | CO_FAST_CELL); |
558 | continue; |
559 | } |
560 | _Py_set_localsplus_info(offset, name, CO_FAST_CELL, |
561 | localsplusnames, localspluskinds); |
562 | } |
563 | for (int i = 0; i < nfreevars; i++, offset++7 ) { Branch (563:21): [True: 7, False: 70]
|
564 | PyObject *name = PyTuple_GET_ITEM(freevars, i); |
565 | _Py_set_localsplus_info(offset, name, CO_FAST_FREE, |
566 | localsplusnames, localspluskinds); |
567 | } |
568 | // If any cells were args then nlocalsplus will have shrunk. |
569 | if (nlocalsplus != PyTuple_GET_SIZE(localsplusnames)) { Branch (569:9): [True: 1, False: 69]
|
570 | if (_PyTuple_Resize(&localsplusnames, nlocalsplus) < 0 Branch (570:13): [True: 0, False: 1]
|
571 | || _PyBytes_Resize(&localspluskinds, nlocalsplus) < 0) { Branch (571:20): [True: 0, False: 1]
|
572 | goto error; |
573 | } |
574 | } |
575 | |
576 | struct _PyCodeConstructor con = { |
577 | .filename = filename, |
578 | .name = name, |
579 | .qualname = qualname, |
580 | .flags = flags, |
581 | |
582 | .code = code, |
583 | .firstlineno = firstlineno, |
584 | .linetable = linetable, |
585 | |
586 | .consts = consts, |
587 | .names = names, |
588 | |
589 | .localsplusnames = localsplusnames, |
590 | .localspluskinds = localspluskinds, |
591 | |
592 | .argcount = argcount, |
593 | .posonlyargcount = posonlyargcount, |
594 | .kwonlyargcount = kwonlyargcount, |
595 | |
596 | .stacksize = stacksize, |
597 | |
598 | .exceptiontable = exceptiontable, |
599 | }; |
600 | |
601 | if (_PyCode_Validate(&con) < 0) { Branch (601:9): [True: 0, False: 70]
|
602 | goto error; |
603 | } |
604 | assert(PyBytes_GET_SIZE(code) % sizeof(_Py_CODEUNIT) == 0); |
605 | assert(_Py_IS_ALIGNED(PyBytes_AS_STRING(code), sizeof(_Py_CODEUNIT))); |
606 | if (nlocals != PyTuple_GET_SIZE(varnames)) { Branch (606:9): [True: 4, False: 66]
|
607 | PyErr_SetString(PyExc_ValueError, |
608 | "code: co_nlocals != len(co_varnames)"); |
609 | goto error; |
610 | } |
611 | |
612 | co = _PyCode_New(&con); |
613 | if (co == NULL) { Branch (613:9): [True: 0, False: 66]
|
614 | goto error; |
615 | } |
616 | |
617 | error: |
618 | Py_XDECREF(localsplusnames); |
619 | Py_XDECREF(localspluskinds); |
620 | return co; |
621 | } |
622 | |
623 | PyCodeObject * |
624 | PyCode_New(int argcount, int kwonlyargcount, |
625 | int nlocals, int stacksize, int flags, |
626 | PyObject *code, PyObject *consts, PyObject *names, |
627 | PyObject *varnames, PyObject *freevars, PyObject *cellvars, |
628 | PyObject *filename, PyObject *name, PyObject *qualname, |
629 | int firstlineno, |
630 | PyObject *linetable, |
631 | PyObject *exceptiontable) |
632 | { |
633 | return PyCode_NewWithPosOnlyArgs(argcount, 0, kwonlyargcount, nlocals, |
634 | stacksize, flags, code, consts, names, |
635 | varnames, freevars, cellvars, filename, |
636 | name, qualname, firstlineno, |
637 | linetable, |
638 | exceptiontable); |
639 | } |
640 | |
641 | static const char assert0[6] = { |
642 | RESUME, 0, |
643 | LOAD_ASSERTION_ERROR, 0, |
644 | RAISE_VARARGS, 1 |
645 | }; |
646 | |
647 | PyCodeObject * |
648 | PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno) |
649 | { |
650 | PyObject *nulltuple = NULL; |
651 | PyObject *filename_ob = NULL; |
652 | PyObject *funcname_ob = NULL; |
653 | PyObject *code_ob = NULL; |
654 | PyCodeObject *result = NULL; |
655 | |
656 | nulltuple = PyTuple_New(0); |
657 | if (nulltuple == NULL) { Branch (657:9): [True: 0, False: 32]
|
658 | goto failed; |
659 | } |
660 | funcname_ob = PyUnicode_FromString(funcname); |
661 | if (funcname_ob == NULL) { Branch (661:9): [True: 0, False: 32]
|
662 | goto failed; |
663 | } |
664 | filename_ob = PyUnicode_DecodeFSDefault(filename); |
665 | if (filename_ob == NULL) { Branch (665:9): [True: 0, False: 32]
|
666 | goto failed; |
667 | } |
668 | code_ob = PyBytes_FromStringAndSize(assert0, 6); |
669 | if (code_ob == NULL) { Branch (669:9): [True: 0, False: 32]
|
670 | goto failed; |
671 | } |
672 | |
673 | #define emptystring (PyObject *)&_Py_SINGLETON(bytes_empty) |
674 | struct _PyCodeConstructor con = { |
675 | .filename = filename_ob, |
676 | .name = funcname_ob, |
677 | .qualname = funcname_ob, |
678 | .code = code_ob, |
679 | .firstlineno = firstlineno, |
680 | .linetable = emptystring, |
681 | .consts = nulltuple, |
682 | .names = nulltuple, |
683 | .localsplusnames = nulltuple, |
684 | .localspluskinds = emptystring, |
685 | .exceptiontable = emptystring, |
686 | .stacksize = 1, |
687 | }; |
688 | result = _PyCode_New(&con); |
689 | |
690 | failed: |
691 | Py_XDECREF(nulltuple); |
692 | Py_XDECREF(funcname_ob); |
693 | Py_XDECREF(filename_ob); |
694 | Py_XDECREF(code_ob); |
695 | return result; |
696 | } |
697 | |
698 | |
699 | /****************** |
700 | * source location tracking (co_lines/co_positions) |
701 | ******************/ |
702 | |
703 | /* Use co_linetable to compute the line number from a bytecode index, addrq. See |
704 | lnotab_notes.txt for the details of the lnotab representation. |
705 | */ |
706 | |
707 | int |
708 | _PyCode_CreateLineArray(PyCodeObject *co) |
709 | { |
710 | assert(co->_co_linearray == NULL); |
711 | PyCodeAddressRange bounds; |
712 | int size; |
713 | int max_line = 0; |
714 | _PyCode_InitAddressRange(co, &bounds); |
715 | while(_PyLineTable_NextAddressRange(&bounds)) { Branch (715:11): [True: 60.9k, False: 1.71k]
|
716 | if (bounds.ar_line > max_line) { Branch (716:13): [True: 11.6k, False: 49.3k]
|
717 | max_line = bounds.ar_line; |
718 | } |
719 | } |
720 | if (max_line < (1 << 15)) { Branch (720:9): [True: 1.71k, False: 0]
|
721 | size = 2; |
722 | } |
723 | else { |
724 | size = 4; |
725 | } |
726 | co->_co_linearray = PyMem_Malloc(Py_SIZE(co)*size); |
727 | if (co->_co_linearray == NULL) { Branch (727:9): [True: 0, False: 1.71k]
|
728 | PyErr_NoMemory(); |
729 | return -1; |
730 | } |
731 | co->_co_linearray_entry_size = size; |
732 | _PyCode_InitAddressRange(co, &bounds); |
733 | while(_PyLineTable_NextAddressRange(&bounds)) { Branch (733:11): [True: 60.9k, False: 1.71k]
|
734 | int start = bounds.ar_start / sizeof(_Py_CODEUNIT); |
735 | int end = bounds.ar_end / sizeof(_Py_CODEUNIT); |
736 | for (int index = start; index < end; index++145k ) { Branch (736:33): [True: 145k, False: 60.9k]
|
737 | assert(index < (int)Py_SIZE(co)); |
738 | if (size == 2) { Branch (738:17): [True: 145k, False: 0]
|
739 | assert(((int16_t)bounds.ar_line) == bounds.ar_line); |
740 | ((int16_t *)co->_co_linearray)[index] = bounds.ar_line; |
741 | } |
742 | else { |
743 | assert(size == 4); |
744 | ((int32_t *)co->_co_linearray)[index] = bounds.ar_line; |
745 | } |
746 | } |
747 | } |
748 | return 0; |
749 | } |
750 | |
751 | int |
752 | PyCode_Addr2Line(PyCodeObject *co, int addrq) |
753 | { |
754 | if (addrq < 0) { Branch (754:9): [True: 0, False: 6.93M]
|
755 | return co->co_firstlineno; |
756 | } |
757 | assert(addrq >= 0 && addrq < _PyCode_NBYTES(co)); |
758 | if (co->_co_linearray) { Branch (758:9): [True: 914k, False: 6.02M]
|
759 | return _PyCode_LineNumberFromArray(co, addrq / sizeof(_Py_CODEUNIT)); |
760 | } |
761 | PyCodeAddressRange bounds; |
762 | _PyCode_InitAddressRange(co, &bounds); |
763 | return _PyCode_CheckLineNumber(addrq, &bounds); |
764 | } |
765 | |
766 | void |
767 | _PyLineTable_InitAddressRange(const char *linetable, Py_ssize_t length, int firstlineno, PyCodeAddressRange *range) |
768 | { |
769 | range->opaque.lo_next = (const uint8_t *)linetable; |
770 | range->opaque.limit = range->opaque.lo_next + length; |
771 | range->ar_start = -1; |
772 | range->ar_end = 0; |
773 | range->opaque.computed_line = firstlineno; |
774 | range->ar_line = -1; |
775 | } |
776 | |
777 | int |
778 | _PyCode_InitAddressRange(PyCodeObject* co, PyCodeAddressRange *bounds) |
779 | { |
780 | assert(co->co_linetable != NULL); |
781 | const char *linetable = PyBytes_AS_STRING(co->co_linetable); |
782 | Py_ssize_t length = PyBytes_GET_SIZE(co->co_linetable); |
783 | _PyLineTable_InitAddressRange(linetable, length, co->co_firstlineno, bounds); |
784 | return bounds->ar_line; |
785 | } |
786 | |
787 | /* Update *bounds to describe the first and one-past-the-last instructions in |
788 | the same line as lasti. Return the number of that line, or -1 if lasti is out of bounds. */ |
789 | int |
790 | _PyCode_CheckLineNumber(int lasti, PyCodeAddressRange *bounds) |
791 | { |
792 | while (bounds->ar_end <= lasti) { Branch (792:12): [True: 155M, False: 6.02M]
|
793 | if (!_PyLineTable_NextAddressRange(bounds)) { Branch (793:13): [True: 1, False: 155M]
|
794 | return -1; |
795 | } |
796 | } |
797 | while (bounds->ar_start > lasti) { Branch (797:12): [True: 0, False: 6.02M]
|
798 | if (!_PyLineTable_PreviousAddressRange(bounds)) { Branch (798:13): [True: 0, False: 0]
|
799 | return -1; |
800 | } |
801 | } |
802 | return bounds->ar_line; |
803 | } |
804 | |
805 | static int |
806 | is_no_line_marker(uint8_t b) |
807 | { |
808 | return (b >> 3) == 0x1f; |
809 | } |
810 | |
811 | |
812 | #define ASSERT_VALID_BOUNDS(bounds) \ |
813 | assert(bounds->opaque.lo_next <= bounds->opaque.limit && \ |
814 | (bounds->ar_line == -1 || bounds->ar_line == bounds->opaque.computed_line) && \ |
815 | (bounds->opaque.lo_next == bounds->opaque.limit || \ |
816 | (*bounds->opaque.lo_next) & 128)) |
817 | |
818 | static int |
819 | next_code_delta(PyCodeAddressRange *bounds) |
820 | { |
821 | assert((*bounds->opaque.lo_next) & 128); |
822 | return (((*bounds->opaque.lo_next) & 7) + 1) * sizeof(_Py_CODEUNIT); |
823 | } |
824 | |
825 | static int |
826 | previous_code_delta(PyCodeAddressRange *bounds) |
827 | { |
828 | if (bounds->ar_start == 0) { Branch (828:9): [True: 1, False: 254]
|
829 | // If we looking at the first entry, the |
830 | // "previous" entry has an implicit length of 1. |
831 | return 1; |
832 | } |
833 | const uint8_t *ptr = bounds->opaque.lo_next-1; |
834 | while (((*ptr) & 128) == 0) { Branch (834:12): [True: 390, False: 254]
|
835 | ptr--; |
836 | } |
837 | return (((*ptr) & 7) + 1) * sizeof(_Py_CODEUNIT); |
838 | } |
839 | |
840 | static int |
841 | read_byte(PyCodeAddressRange *bounds) |
842 | { |
843 | return *bounds->opaque.lo_next++; |
844 | } |
845 | |
846 | static int |
847 | read_varint(PyCodeAddressRange *bounds) |
848 | { |
849 | unsigned int read = read_byte(bounds); |
850 | unsigned int val = read & 63; |
851 | unsigned int shift = 0; |
852 | while (read & 64) { Branch (852:12): [True: 55.3k, False: 189k]
|
853 | read = read_byte(bounds); |
854 | shift += 6; |
855 | val |= (read & 63) << shift; |
856 | } |
857 | return val; |
858 | } |
859 | |
860 | static int |
861 | read_signed_varint(PyCodeAddressRange *bounds) |
862 | { |
863 | unsigned int uval = read_varint(bounds); |
864 | if (uval & 1) { Branch (864:9): [True: 3.62k, False: 43.9k]
|
865 | return -(int)(uval >> 1); |
866 | } |
867 | else { |
868 | return uval >> 1; |
869 | } |
870 | } |
871 | |
872 | static void |
873 | retreat(PyCodeAddressRange *bounds) |
874 | { |
875 | ASSERT_VALID_BOUNDS(bounds); |
876 | assert(bounds->ar_start >= 0); |
877 | do { |
878 | bounds->opaque.lo_next--; |
879 | } while (((*bounds->opaque.lo_next) & 128) == 0); Branch (879:14): [True: 381, False: 255]
|
880 | bounds->opaque.computed_line -= get_line_delta(bounds->opaque.lo_next); |
881 | bounds->ar_end = bounds->ar_start; |
882 | bounds->ar_start -= previous_code_delta(bounds); |
883 | if (is_no_line_marker(bounds->opaque.lo_next[-1])) { Branch (883:9): [True: 1, False: 254]
|
884 | bounds->ar_line = -1; |
885 | } |
886 | else { |
887 | bounds->ar_line = bounds->opaque.computed_line; |
888 | } |
889 | ASSERT_VALID_BOUNDS(bounds); |
890 | } |
891 | |
892 | static void |
893 | advance(PyCodeAddressRange *bounds) |
894 | { |
895 | ASSERT_VALID_BOUNDS(bounds); |
896 | bounds->opaque.computed_line += get_line_delta(bounds->opaque.lo_next); |
897 | if (is_no_line_marker(*bounds->opaque.lo_next)) { Branch (897:9): [True: 1.26M, False: 155M]
|
898 | bounds->ar_line = -1; |
899 | } |
900 | else { |
901 | bounds->ar_line = bounds->opaque.computed_line; |
902 | } |
903 | bounds->ar_start = bounds->ar_end; |
904 | bounds->ar_end += next_code_delta(bounds); |
905 | do { |
906 | bounds->opaque.lo_next++; |
907 | } while (bounds->opaque.lo_next < bounds->opaque.limit && Branch (907:14): [True: 443M, False: 44.1k]
|
908 | ((*bounds->opaque.lo_next) & 128) == 0443M ); Branch (908:9): [True: 287M, False: 156M]
|
909 | ASSERT_VALID_BOUNDS(bounds); |
910 | } |
911 | |
912 | static void |
913 | advance_with_locations(PyCodeAddressRange *bounds, int *endline, int *column, int *endcolumn) |
914 | { |
915 | ASSERT_VALID_BOUNDS(bounds); |
916 | int first_byte = read_byte(bounds); |
917 | int code = (first_byte >> 3) & 15; |
918 | bounds->ar_start = bounds->ar_end; |
919 | bounds->ar_end = bounds->ar_start + ((first_byte & 7) + 1) * sizeof(_Py_CODEUNIT); |
920 | switch(code) { |
921 | case PY_CODE_LOCATION_INFO_NONE: Branch (921:9): [True: 5.11k, False: 336k]
|
922 | bounds->ar_line = *endline = -1; |
923 | *column = *endcolumn = -1; |
924 | break; |
925 | case PY_CODE_LOCATION_INFO_LONG: Branch (925:9): [True: 47.2k, False: 294k]
|
926 | { |
927 | bounds->opaque.computed_line += read_signed_varint(bounds); |
928 | bounds->ar_line = bounds->opaque.computed_line; |
929 | *endline = bounds->ar_line + read_varint(bounds); |
930 | *column = read_varint(bounds)-1; |
931 | *endcolumn = read_varint(bounds)-1; |
932 | break; |
933 | } |
934 | case PY_CODE_LOCATION_INFO_NO_COLUMNS: Branch (934:9): [True: 289, False: 341k]
|
935 | { |
936 | /* No column */ |
937 | bounds->opaque.computed_line += read_signed_varint(bounds); |
938 | *endline = bounds->ar_line = bounds->opaque.computed_line; |
939 | *column = *endcolumn = -1; |
940 | break; |
941 | } |
942 | case PY_CODE_LOCATION_INFO_ONE_LINE0: Branch (942:9): [True: 54.6k, False: 287k]
|
943 | case PY_CODE_LOCATION_INFO_ONE_LINE1: Branch (943:9): [True: 75.6k, False: 266k]
|
944 | case PY_CODE_LOCATION_INFO_ONE_LINE2: Branch (944:9): [True: 6.28k, False: 335k]
|
945 | { |
946 | /* one line form */ |
947 | int line_delta = code - 10; |
948 | bounds->opaque.computed_line += line_delta; |
949 | *endline = bounds->ar_line = bounds->opaque.computed_line; |
950 | *column = read_byte(bounds); |
951 | *endcolumn = read_byte(bounds); |
952 | break; |
953 | } |
954 | default: Branch (954:9): [True: 152k, False: 189k]
|
955 | { |
956 | /* Short forms */ |
957 | int second_byte = read_byte(bounds); |
958 | assert((second_byte & 128) == 0); |
959 | *endline = bounds->ar_line = bounds->opaque.computed_line; |
960 | *column = code << 3 | (second_byte >> 4); |
961 | *endcolumn = *column + (second_byte & 15); |
962 | } |
963 | } |
964 | ASSERT_VALID_BOUNDS(bounds); |
965 | } |
966 | int |
967 | PyCode_Addr2Location(PyCodeObject *co, int addrq, |
968 | int *start_line, int *start_column, |
969 | int *end_line, int *end_column) |
970 | { |
971 | if (addrq < 0) { Branch (971:9): [True: 0, False: 255]
|
972 | *start_line = *end_line = co->co_firstlineno; |
973 | *start_column = *end_column = 0; |
974 | } |
975 | assert(addrq >= 0 && addrq < _PyCode_NBYTES(co)); |
976 | PyCodeAddressRange bounds; |
977 | _PyCode_InitAddressRange(co, &bounds); |
978 | _PyCode_CheckLineNumber(addrq, &bounds); |
979 | retreat(&bounds); |
980 | advance_with_locations(&bounds, end_line, start_column, end_column); |
981 | *start_line = bounds.ar_line; |
982 | return 1; |
983 | } |
984 | |
985 | |
986 | static inline int |
987 | at_end(PyCodeAddressRange *bounds) { |
988 | return bounds->opaque.lo_next >= bounds->opaque.limit; |
989 | } |
990 | |
991 | int |
992 | _PyLineTable_PreviousAddressRange(PyCodeAddressRange *range) |
993 | { |
994 | if (range->ar_start <= 0) { Branch (994:9): [True: 0, False: 0]
|
995 | return 0; |
996 | } |
997 | retreat(range); |
998 | assert(range->ar_end > range->ar_start); |
999 | return 1; |
1000 | } |
1001 | |
1002 | int |
1003 | _PyLineTable_NextAddressRange(PyCodeAddressRange *range) |
1004 | { |
1005 | if (at_end(range)) { Branch (1005:9): [True: 8.14k, False: 156M]
|
1006 | return 0; |
1007 | } |
1008 | advance(range); |
1009 | assert(range->ar_end > range->ar_start); |
1010 | return 1; |
1011 | } |
1012 | |
1013 | int |
1014 | _PyLineTable_StartsLine(PyCodeAddressRange *range) |
1015 | { |
1016 | if (range->ar_start <= 0) { Branch (1016:9): [True: 0, False: 0]
|
1017 | return 0; |
1018 | } |
1019 | const uint8_t *ptr = range->opaque.lo_next; |
1020 | do { |
1021 | ptr--; |
1022 | } while (((*ptr) & 128) == 0); Branch (1022:14): [True: 0, False: 0]
|
1023 | int code = ((*ptr)>> 3) & 15; |
1024 | switch(code) { |
1025 | case PY_CODE_LOCATION_INFO_LONG: Branch (1025:9): [True: 0, False: 0]
|
1026 | return 0; |
1027 | case PY_CODE_LOCATION_INFO_NO_COLUMNS: Branch (1027:9): [True: 0, False: 0]
|
1028 | case PY_CODE_LOCATION_INFO_NONE: Branch (1028:9): [True: 0, False: 0]
|
1029 | return ptr[1] != 0; |
1030 | case PY_CODE_LOCATION_INFO_ONE_LINE0: Branch (1030:9): [True: 0, False: 0]
|
1031 | return 0; |
1032 | case PY_CODE_LOCATION_INFO_ONE_LINE1: Branch (1032:9): [True: 0, False: 0]
|
1033 | case PY_CODE_LOCATION_INFO_ONE_LINE2: Branch (1033:9): [True: 0, False: 0]
|
1034 | return 1; |
1035 | default: Branch (1035:9): [True: 0, False: 0]
|
1036 | return 0; |
1037 | } |
1038 | } |
1039 | |
1040 | static int |
1041 | emit_pair(PyObject **bytes, int *offset, int a, int b) |
1042 | { |
1043 | Py_ssize_t len = PyBytes_GET_SIZE(*bytes); |
1044 | if (*offset + 2 >= len) { Branch (1044:9): [True: 0, False: 0]
|
1045 | if (_PyBytes_Resize(bytes, len * 2) < 0) Branch (1045:13): [True: 0, False: 0]
|
1046 | return 0; |
1047 | } |
1048 | unsigned char *lnotab = (unsigned char *) PyBytes_AS_STRING(*bytes); |
1049 | lnotab += *offset; |
1050 | *lnotab++ = a; |
1051 | *lnotab++ = b; |
1052 | *offset += 2; |
1053 | return 1; |
1054 | } |
1055 | |
1056 | static int |
1057 | emit_delta(PyObject **bytes, int bdelta, int ldelta, int *offset) |
1058 | { |
1059 | while (bdelta > 255) { Branch (1059:12): [True: 0, False: 0]
|
1060 | if (!emit_pair(bytes, offset, 255, 0)) { Branch (1060:13): [True: 0, False: 0]
|
1061 | return 0; |
1062 | } |
1063 | bdelta -= 255; |
1064 | } |
1065 | while (ldelta > 127) { Branch (1065:12): [True: 0, False: 0]
|
1066 | if (!emit_pair(bytes, offset, bdelta, 127)) { Branch (1066:13): [True: 0, False: 0]
|
1067 | return 0; |
1068 | } |
1069 | bdelta = 0; |
1070 | ldelta -= 127; |
1071 | } |
1072 | while (ldelta < -128) { Branch (1072:12): [True: 0, False: 0]
|
1073 | if (!emit_pair(bytes, offset, bdelta, -128)) { Branch (1073:13): [True: 0, False: 0]
|
1074 | return 0; |
1075 | } |
1076 | bdelta = 0; |
1077 | ldelta += 128; |
1078 | } |
1079 | return emit_pair(bytes, offset, bdelta, ldelta); |
1080 | } |
1081 | |
1082 | static PyObject * |
1083 | decode_linetable(PyCodeObject *code) |
1084 | { |
1085 | PyCodeAddressRange bounds; |
1086 | PyObject *bytes; |
1087 | int table_offset = 0; |
1088 | int code_offset = 0; |
1089 | int line = code->co_firstlineno; |
1090 | bytes = PyBytes_FromStringAndSize(NULL, 64); |
1091 | if (bytes == NULL) { Branch (1091:9): [True: 0, False: 0]
|
1092 | return NULL; |
1093 | } |
1094 | _PyCode_InitAddressRange(code, &bounds); |
1095 | while (_PyLineTable_NextAddressRange(&bounds)) { Branch (1095:12): [True: 0, False: 0]
|
1096 | if (bounds.opaque.computed_line != line) { Branch (1096:13): [True: 0, False: 0]
|
1097 | int bdelta = bounds.ar_start - code_offset; |
1098 | int ldelta = bounds.opaque.computed_line - line; |
1099 | if (!emit_delta(&bytes, bdelta, ldelta, &table_offset)) { Branch (1099:17): [True: 0, False: 0]
|
1100 | Py_DECREF(bytes); |
1101 | return NULL; |
1102 | } |
1103 | code_offset = bounds.ar_start; |
1104 | line = bounds.opaque.computed_line; |
1105 | } |
1106 | } |
1107 | _PyBytes_Resize(&bytes, table_offset); |
1108 | return bytes; |
1109 | } |
1110 | |
1111 | |
1112 | typedef struct { |
1113 | PyObject_HEAD |
1114 | PyCodeObject *li_code; |
1115 | PyCodeAddressRange li_line; |
1116 | } lineiterator; |
1117 | |
1118 | |
1119 | static void |
1120 | lineiter_dealloc(lineiterator *li) |
1121 | { |
1122 | Py_DECREF(li->li_code); |
1123 | Py_TYPE(li)->tp_free(li); |
1124 | } |
1125 | |
1126 | static PyObject * |
1127 | lineiter_next(lineiterator *li) |
1128 | { |
1129 | PyCodeAddressRange *bounds = &li->li_line; |
1130 | if (!_PyLineTable_NextAddressRange(bounds)) { Branch (1130:9): [True: 4.61k, False: 184k]
|
1131 | return NULL; |
1132 | } |
1133 | PyObject *start = NULL; |
1134 | PyObject *end = NULL; |
1135 | PyObject *line = NULL; |
1136 | PyObject *result = PyTuple_New(3); |
1137 | start = PyLong_FromLong(bounds->ar_start); |
1138 | end = PyLong_FromLong(bounds->ar_end); |
1139 | if (bounds->ar_line < 0) { Branch (1139:9): [True: 2.52k, False: 182k]
|
1140 | Py_INCREF(Py_None); |
1141 | line = Py_None; |
1142 | } |
1143 | else { |
1144 | line = PyLong_FromLong(bounds->ar_line); |
1145 | } |
1146 | if (result == NULL || start == NULL || end == NULL || line == NULL) { Branch (1146:9): [True: 0, False: 184k]
Branch (1146:27): [True: 0, False: 184k]
Branch (1146:44): [True: 0, False: 184k]
Branch (1146:59): [True: 0, False: 184k]
|
1147 | goto error; |
1148 | } |
1149 | PyTuple_SET_ITEM(result, 0, start); |
1150 | PyTuple_SET_ITEM(result, 1, end); |
1151 | PyTuple_SET_ITEM(result, 2, line); |
1152 | return result; |
1153 | error: |
1154 | Py_XDECREF(start); |
1155 | Py_XDECREF(end); |
1156 | Py_XDECREF(line); |
1157 | Py_XDECREF(result); |
1158 | return result; |
1159 | } |
1160 | |
1161 | PyTypeObject _PyLineIterator = { |
1162 | PyVarObject_HEAD_INIT(&PyType_Type, 0) |
1163 | "line_iterator", /* tp_name */ |
1164 | sizeof(lineiterator), /* tp_basicsize */ |
1165 | 0, /* tp_itemsize */ |
1166 | /* methods */ |
1167 | (destructor)lineiter_dealloc, /* tp_dealloc */ |
1168 | 0, /* tp_vectorcall_offset */ |
1169 | 0, /* tp_getattr */ |
1170 | 0, /* tp_setattr */ |
1171 | 0, /* tp_as_async */ |
1172 | 0, /* tp_repr */ |
1173 | 0, /* tp_as_number */ |
1174 | 0, /* tp_as_sequence */ |
1175 | 0, /* tp_as_mapping */ |
1176 | 0, /* tp_hash */ |
1177 | 0, /* tp_call */ |
1178 | 0, /* tp_str */ |
1179 | 0, /* tp_getattro */ |
1180 | 0, /* tp_setattro */ |
1181 | 0, /* tp_as_buffer */ |
1182 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ |
1183 | 0, /* tp_doc */ |
1184 | 0, /* tp_traverse */ |
1185 | 0, /* tp_clear */ |
1186 | 0, /* tp_richcompare */ |
1187 | 0, /* tp_weaklistoffset */ |
1188 | PyObject_SelfIter, /* tp_iter */ |
1189 | (iternextfunc)lineiter_next, /* tp_iternext */ |
1190 | 0, /* tp_methods */ |
1191 | 0, /* tp_members */ |
1192 | 0, /* tp_getset */ |
1193 | 0, /* tp_base */ |
1194 | 0, /* tp_dict */ |
1195 | 0, /* tp_descr_get */ |
1196 | 0, /* tp_descr_set */ |
1197 | 0, /* tp_dictoffset */ |
1198 | 0, /* tp_init */ |
1199 | 0, /* tp_alloc */ |
1200 | 0, /* tp_new */ |
1201 | PyObject_Del, /* tp_free */ |
1202 | }; |
1203 | |
1204 | static lineiterator * |
1205 | new_linesiterator(PyCodeObject *code) |
1206 | { |
1207 | lineiterator *li = (lineiterator *)PyType_GenericAlloc(&_PyLineIterator, 0); |
1208 | if (li == NULL) { Branch (1208:9): [True: 0, False: 4.61k]
|
1209 | return NULL; |
1210 | } |
1211 | Py_INCREF(code); |
1212 | li->li_code = code; |
1213 | _PyCode_InitAddressRange(code, &li->li_line); |
1214 | return li; |
1215 | } |
1216 | |
1217 | /* co_positions iterator object. */ |
1218 | typedef struct { |
1219 | PyObject_HEAD |
1220 | PyCodeObject* pi_code; |
1221 | PyCodeAddressRange pi_range; |
1222 | int pi_offset; |
1223 | int pi_endline; |
1224 | int pi_column; |
1225 | int pi_endcolumn; |
1226 | } positionsiterator; |
1227 | |
1228 | static void |
1229 | positionsiter_dealloc(positionsiterator* pi) |
1230 | { |
1231 | Py_DECREF(pi->pi_code); |
1232 | Py_TYPE(pi)->tp_free(pi); |
1233 | } |
1234 | |
1235 | static PyObject* |
1236 | _source_offset_converter(int* value) { |
1237 | if (*value == -1) { Branch (1237:9): [True: 21.0k, False: 2.66M]
|
1238 | Py_RETURN_NONE; |
1239 | } |
1240 | return PyLong_FromLong(*value); |
1241 | } |
1242 | |
1243 | static PyObject* |
1244 | positionsiter_next(positionsiterator* pi) |
1245 | { |
1246 | if (pi->pi_offset >= pi->pi_range.ar_end) { Branch (1246:9): [True: 341k, False: 329k]
|
1247 | assert(pi->pi_offset == pi->pi_range.ar_end); |
1248 | if (at_end(&pi->pi_range)) { Branch (1248:13): [True: 26, False: 341k]
|
1249 | return NULL; |
1250 | } |
1251 | advance_with_locations(&pi->pi_range, &pi->pi_endline, &pi->pi_column, &pi->pi_endcolumn); |
1252 | } |
1253 | pi->pi_offset += 2; |
1254 | return Py_BuildValue("(O&O&O&O&)", |
1255 | _source_offset_converter, &pi->pi_range.ar_line, |
1256 | _source_offset_converter, &pi->pi_endline, |
1257 | _source_offset_converter, &pi->pi_column, |
1258 | _source_offset_converter, &pi->pi_endcolumn); |
1259 | } |
1260 | |
1261 | PyTypeObject _PyPositionsIterator = { |
1262 | PyVarObject_HEAD_INIT(&PyType_Type, 0) |
1263 | "positions_iterator", /* tp_name */ |
1264 | sizeof(positionsiterator), /* tp_basicsize */ |
1265 | 0, /* tp_itemsize */ |
1266 | /* methods */ |
1267 | (destructor)positionsiter_dealloc, /* tp_dealloc */ |
1268 | 0, /* tp_vectorcall_offset */ |
1269 | 0, /* tp_getattr */ |
1270 | 0, /* tp_setattr */ |
1271 | 0, /* tp_as_async */ |
1272 | 0, /* tp_repr */ |
1273 | 0, /* tp_as_number */ |
1274 | 0, /* tp_as_sequence */ |
1275 | 0, /* tp_as_mapping */ |
1276 | 0, /* tp_hash */ |
1277 | 0, /* tp_call */ |
1278 | 0, /* tp_str */ |
1279 | 0, /* tp_getattro */ |
1280 | 0, /* tp_setattro */ |
1281 | 0, /* tp_as_buffer */ |
1282 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ |
1283 | 0, /* tp_doc */ |
1284 | 0, /* tp_traverse */ |
1285 | 0, /* tp_clear */ |
1286 | 0, /* tp_richcompare */ |
1287 | 0, /* tp_weaklistoffset */ |
1288 | PyObject_SelfIter, /* tp_iter */ |
1289 | (iternextfunc)positionsiter_next, /* tp_iternext */ |
1290 | 0, /* tp_methods */ |
1291 | 0, /* tp_members */ |
1292 | 0, /* tp_getset */ |
1293 | 0, /* tp_base */ |
1294 | 0, /* tp_dict */ |
1295 | 0, /* tp_descr_get */ |
1296 | 0, /* tp_descr_set */ |
1297 | 0, /* tp_dictoffset */ |
1298 | 0, /* tp_init */ |
1299 | 0, /* tp_alloc */ |
1300 | 0, /* tp_new */ |
1301 | PyObject_Del, /* tp_free */ |
1302 | }; |
1303 | |
1304 | static PyObject* |
1305 | code_positionsiterator(PyCodeObject* code, PyObject* Py_UNUSED(args)) |
1306 | { |
1307 | positionsiterator* pi = (positionsiterator*)PyType_GenericAlloc(&_PyPositionsIterator, 0); |
1308 | if (pi == NULL) { Branch (1308:9): [True: 0, False: 8.41k]
|
1309 | return NULL; |
1310 | } |
1311 | Py_INCREF(code); |
1312 | pi->pi_code = code; |
1313 | _PyCode_InitAddressRange(code, &pi->pi_range); |
1314 | pi->pi_offset = pi->pi_range.ar_end; |
1315 | return (PyObject*)pi; |
1316 | } |
1317 | |
1318 | |
1319 | /****************** |
1320 | * "extra" frame eval info (see PEP 523) |
1321 | ******************/ |
1322 | |
1323 | /* Holder for co_extra information */ |
1324 | typedef struct { |
1325 | Py_ssize_t ce_size; |
1326 | void *ce_extras[1]; |
1327 | } _PyCodeObjectExtra; |
1328 | |
1329 | |
1330 | int |
1331 | _PyCode_GetExtra(PyObject *code, Py_ssize_t index, void **extra) |
1332 | { |
1333 | if (!PyCode_Check(code)) { Branch (1333:9): [True: 1, False: 2]
|
1334 | PyErr_BadInternalCall(); |
1335 | return -1; |
1336 | } |
1337 | |
1338 | PyCodeObject *o = (PyCodeObject*) code; |
1339 | _PyCodeObjectExtra *co_extra = (_PyCodeObjectExtra*) o->co_extra; |
1340 | |
1341 | if (co_extra == NULL || co_extra->ce_size <= index1 ) { Branch (1341:9): [True: 1, False: 1]
Branch (1341:29): [True: 0, False: 1]
|
1342 | *extra = NULL; |
1343 | return 0; |
1344 | } |
1345 | |
1346 | *extra = co_extra->ce_extras[index]; |
1347 | return 0; |
1348 | } |
1349 | |
1350 | |
1351 | int |
1352 | _PyCode_SetExtra(PyObject *code, Py_ssize_t index, void *extra) |
1353 | { |
1354 | PyInterpreterState *interp = _PyInterpreterState_GET(); |
1355 | |
1356 | if (!PyCode_Check(code) || index < 05 || Branch (1356:9): [True: 1, False: 5]
Branch (1356:32): [True: 0, False: 5]
|
1357 | index >= interp->co_extra_user_count5 ) { Branch (1357:13): [True: 1, False: 4]
|
1358 | PyErr_BadInternalCall(); |
1359 | return -1; |
1360 | } |
1361 | |
1362 | PyCodeObject *o = (PyCodeObject*) code; |
1363 | _PyCodeObjectExtra *co_extra = (_PyCodeObjectExtra *) o->co_extra; |
1364 | |
1365 | if (co_extra == NULL || co_extra->ce_size <= index1 ) { Branch (1365:9): [True: 3, False: 1]
Branch (1365:29): [True: 0, False: 1]
|
1366 | Py_ssize_t i = (co_extra == NULL ? 0 : co_extra->ce_size0 ); Branch (1366:25): [True: 3, False: 0]
|
1367 | co_extra = PyMem_Realloc( |
1368 | co_extra, |
1369 | sizeof(_PyCodeObjectExtra) + |
1370 | (interp->co_extra_user_count-1) * sizeof(void*)); |
1371 | if (co_extra == NULL) { Branch (1371:13): [True: 0, False: 3]
|
1372 | return -1; |
1373 | } |
1374 | for (; 3 i < interp->co_extra_user_count; i++3 ) { Branch (1374:16): [True: 3, False: 3]
|
1375 | co_extra->ce_extras[i] = NULL; |
1376 | } |
1377 | co_extra->ce_size = interp->co_extra_user_count; |
1378 | o->co_extra = co_extra; |
1379 | } |
1380 | |
1381 | if (co_extra->ce_extras[index] != NULL) { Branch (1381:9): [True: 1, False: 3]
|
1382 | freefunc free = interp->co_extra_freefuncs[index]; |
1383 | if (free != NULL) { Branch (1383:13): [True: 1, False: 0]
|
1384 | free(co_extra->ce_extras[index]); |
1385 | } |
1386 | } |
1387 | |
1388 | co_extra->ce_extras[index] = extra; |
1389 | return 0; |
1390 | } |
1391 | |
1392 | |
1393 | /****************** |
1394 | * other PyCodeObject accessor functions |
1395 | ******************/ |
1396 | |
1397 | PyObject * |
1398 | _PyCode_GetVarnames(PyCodeObject *co) |
1399 | { |
1400 | return get_localsplus_names(co, CO_FAST_LOCAL, co->co_nlocals); |
1401 | } |
1402 | |
1403 | PyObject * |
1404 | _PyCode_GetCellvars(PyCodeObject *co) |
1405 | { |
1406 | return get_localsplus_names(co, CO_FAST_CELL, co->co_ncellvars); |
1407 | } |
1408 | |
1409 | PyObject * |
1410 | _PyCode_GetFreevars(PyCodeObject *co) |
1411 | { |
1412 | return get_localsplus_names(co, CO_FAST_FREE, co->co_nfreevars); |
1413 | } |
1414 | |
1415 | static void |
1416 | deopt_code(_Py_CODEUNIT *instructions, Py_ssize_t len) |
1417 | { |
1418 | for (int i = 0; i < len; i++3.10M ) { Branch (1418:21): [True: 3.10M, False: 82.9k]
|
1419 | _Py_CODEUNIT instruction = instructions[i]; |
1420 | int opcode = _PyOpcode_Original[_Py_OPCODE(instruction)]; |
1421 | int caches = _PyOpcode_Caches[opcode]; |
1422 | instructions[i] = _Py_MAKECODEUNIT(opcode, _Py_OPARG(instruction)); |
1423 | while (caches--) { Branch (1423:16): [True: 4.10M, False: 3.10M]
|
1424 | instructions[++i] = _Py_MAKECODEUNIT(CACHE, 0); |
1425 | } |
1426 | } |
1427 | } |
1428 | |
1429 | PyObject * |
1430 | _PyCode_GetCode(PyCodeObject *co) |
1431 | { |
1432 | if (co->_co_code != NULL) { Branch (1432:9): [True: 3.03k, False: 3.50k]
|
1433 | return Py_NewRef(co->_co_code); |
1434 | } |
1435 | PyObject *code = PyBytes_FromStringAndSize((const char *)_PyCode_CODE(co), |
1436 | _PyCode_NBYTES(co)); |
1437 | if (code == NULL) { Branch (1437:9): [True: 0, False: 3.50k]
|
1438 | return NULL; |
1439 | } |
1440 | deopt_code((_Py_CODEUNIT *)PyBytes_AS_STRING(code), Py_SIZE(co)); |
1441 | assert(co->_co_code == NULL); |
1442 | co->_co_code = Py_NewRef(code); |
1443 | return code; |
1444 | } |
1445 | |
1446 | PyObject * |
1447 | PyCode_GetCode(PyCodeObject *co) |
1448 | { |
1449 | return _PyCode_GetCode(co); |
1450 | } |
1451 | |
1452 | /****************** |
1453 | * PyCode_Type |
1454 | ******************/ |
1455 | |
1456 | /*[clinic input] |
1457 | class code "PyCodeObject *" "&PyCode_Type" |
1458 | [clinic start generated code]*/ |
1459 | /*[clinic end generated code: output=da39a3ee5e6b4b0d input=78aa5d576683bb4b]*/ |
1460 | |
1461 | /*[clinic input] |
1462 | @classmethod |
1463 | code.__new__ as code_new |
1464 | |
1465 | argcount: int |
1466 | posonlyargcount: int |
1467 | kwonlyargcount: int |
1468 | nlocals: int |
1469 | stacksize: int |
1470 | flags: int |
1471 | codestring as code: object(subclass_of="&PyBytes_Type") |
1472 | constants as consts: object(subclass_of="&PyTuple_Type") |
1473 | names: object(subclass_of="&PyTuple_Type") |
1474 | varnames: object(subclass_of="&PyTuple_Type") |
1475 | filename: unicode |
1476 | name: unicode |
1477 | qualname: unicode |
1478 | firstlineno: int |
1479 | linetable: object(subclass_of="&PyBytes_Type") |
1480 | exceptiontable: object(subclass_of="&PyBytes_Type") |
1481 | freevars: object(subclass_of="&PyTuple_Type", c_default="NULL") = () |
1482 | cellvars: object(subclass_of="&PyTuple_Type", c_default="NULL") = () |
1483 | / |
1484 | |
1485 | Create a code object. Not for the faint of heart. |
1486 | [clinic start generated code]*/ |
1487 | |
1488 | static PyObject * |
1489 | code_new_impl(PyTypeObject *type, int argcount, int posonlyargcount, |
1490 | int kwonlyargcount, int nlocals, int stacksize, int flags, |
1491 | PyObject *code, PyObject *consts, PyObject *names, |
1492 | PyObject *varnames, PyObject *filename, PyObject *name, |
1493 | PyObject *qualname, int firstlineno, PyObject *linetable, |
1494 | PyObject *exceptiontable, PyObject *freevars, |
1495 | PyObject *cellvars) |
1496 | /*[clinic end generated code: output=069fa20d299f9dda input=e31da3c41ad8064a]*/ |
1497 | { |
1498 | PyObject *co = NULL; |
1499 | PyObject *ournames = NULL; |
1500 | PyObject *ourvarnames = NULL; |
1501 | PyObject *ourfreevars = NULL; |
1502 | PyObject *ourcellvars = NULL; |
1503 | |
1504 | if (PySys_Audit("code.__new__", "OOOiiiiii", Branch (1504:9): [True: 0, False: 3]
|
1505 | code, filename, name, argcount, posonlyargcount, |
1506 | kwonlyargcount, nlocals, stacksize, flags) < 0) { |
1507 | goto cleanup; |
1508 | } |
1509 | |
1510 | if (argcount < 0) { Branch (1510:9): [True: 0, False: 3]
|
1511 | PyErr_SetString( |
1512 | PyExc_ValueError, |
1513 | "code: argcount must not be negative"); |
1514 | goto cleanup; |
1515 | } |
1516 | |
1517 | if (posonlyargcount < 0) { Branch (1517:9): [True: 0, False: 3]
|
1518 | PyErr_SetString( |
1519 | PyExc_ValueError, |
1520 | "code: posonlyargcount must not be negative"); |
1521 | goto cleanup; |
1522 | } |
1523 | |
1524 | if (kwonlyargcount < 0) { Branch (1524:9): [True: 0, False: 3]
|
1525 | PyErr_SetString( |
1526 | PyExc_ValueError, |
1527 | "code: kwonlyargcount must not be negative"); |
1528 | goto cleanup; |
1529 | } |
1530 | if (nlocals < 0) { Branch (1530:9): [True: 0, False: 3]
|
1531 | PyErr_SetString( |
1532 | PyExc_ValueError, |
1533 | "code: nlocals must not be negative"); |
1534 | goto cleanup; |
1535 | } |
1536 | |
1537 | ournames = validate_and_copy_tuple(names); |
1538 | if (ournames == NULL) Branch (1538:9): [True: 0, False: 3]
|
1539 | goto cleanup; |
1540 | ourvarnames = validate_and_copy_tuple(varnames); |
1541 | if (ourvarnames == NULL) Branch (1541:9): [True: 0, False: 3]
|
1542 | goto cleanup; |
1543 | if (freevars) Branch (1543:9): [True: 3, False: 0]
|
1544 | ourfreevars = validate_and_copy_tuple(freevars); |
1545 | else |
1546 | ourfreevars = PyTuple_New(0); |
1547 | if (ourfreevars == NULL) Branch (1547:9): [True: 0, False: 3]
|
1548 | goto cleanup; |
1549 | if (cellvars) Branch (1549:9): [True: 3, False: 0]
|
1550 | ourcellvars = validate_and_copy_tuple(cellvars); |
1551 | else |
1552 | ourcellvars = PyTuple_New(0); |
1553 | if (ourcellvars == NULL) Branch (1553:9): [True: 0, False: 3]
|
1554 | goto cleanup; |
1555 | |
1556 | co = (PyObject *)PyCode_NewWithPosOnlyArgs(argcount, posonlyargcount, |
1557 | kwonlyargcount, |
1558 | nlocals, stacksize, flags, |
1559 | code, consts, ournames, |
1560 | ourvarnames, ourfreevars, |
1561 | ourcellvars, filename, |
1562 | name, qualname, firstlineno, |
1563 | linetable, |
1564 | exceptiontable |
1565 | ); |
1566 | cleanup: |
1567 | Py_XDECREF(ournames); |
1568 | Py_XDECREF(ourvarnames); |
1569 | Py_XDECREF(ourfreevars); |
1570 | Py_XDECREF(ourcellvars); |
1571 | return co; |
1572 | } |
1573 | |
1574 | static void |
1575 | code_dealloc(PyCodeObject *co) |
1576 | { |
1577 | if (co->co_extra != NULL) { Branch (1577:9): [True: 3, False: 261k]
|
1578 | PyInterpreterState *interp = _PyInterpreterState_GET(); |
1579 | _PyCodeObjectExtra *co_extra = co->co_extra; |
1580 | |
1581 | for (Py_ssize_t i = 0; i < co_extra->ce_size; i++3 ) { Branch (1581:32): [True: 3, False: 3]
|
1582 | freefunc free_extra = interp->co_extra_freefuncs[i]; |
1583 | |
1584 | if (free_extra != NULL) { Branch (1584:17): [True: 3, False: 0]
|
1585 | free_extra(co_extra->ce_extras[i]); |
1586 | } |
1587 | } |
1588 | |
1589 | PyMem_Free(co_extra); |
1590 | } |
1591 | |
1592 | Py_XDECREF(co->co_consts); |
1593 | Py_XDECREF(co->co_names); |
1594 | Py_XDECREF(co->co_localsplusnames); |
1595 | Py_XDECREF(co->co_localspluskinds); |
1596 | Py_XDECREF(co->co_filename); |
1597 | Py_XDECREF(co->co_name); |
1598 | Py_XDECREF(co->co_qualname); |
1599 | Py_XDECREF(co->co_linetable); |
1600 | Py_XDECREF(co->co_exceptiontable); |
1601 | Py_XDECREF(co->_co_code); |
1602 | if (co->co_weakreflist != NULL) { Branch (1602:9): [True: 1, False: 261k]
|
1603 | PyObject_ClearWeakRefs((PyObject*)co); |
1604 | } |
1605 | if (co->_co_linearray) { Branch (1605:9): [True: 1.62k, False: 259k]
|
1606 | PyMem_Free(co->_co_linearray); |
1607 | } |
1608 | if (co->co_warmup == 0) { Branch (1608:9): [True: 24.6k, False: 236k]
|
1609 | _Py_QuickenedCount--; |
1610 | } |
1611 | PyObject_Free(co); |
1612 | } |
1613 | |
1614 | static PyObject * |
1615 | code_repr(PyCodeObject *co) |
1616 | { |
1617 | int lineno; |
1618 | if (co->co_firstlineno != 0) Branch (1618:9): [True: 59, False: 0]
|
1619 | lineno = co->co_firstlineno; |
1620 | else |
1621 | lineno = -1; |
1622 | if (co->co_filename && PyUnicode_Check(co->co_filename)) { Branch (1622:9): [True: 59, False: 0]
|
1623 | return PyUnicode_FromFormat( |
1624 | "<code object %U at %p, file \"%U\", line %d>", |
1625 | co->co_name, co, co->co_filename, lineno); |
1626 | } else { |
1627 | return PyUnicode_FromFormat( |
1628 | "<code object %U at %p, file ???, line %d>", |
1629 | co->co_name, co, lineno); |
1630 | } |
1631 | } |
1632 | |
1633 | static PyObject * |
1634 | code_richcompare(PyObject *self, PyObject *other, int op) |
1635 | { |
1636 | PyCodeObject *co, *cp; |
1637 | int eq; |
1638 | PyObject *consts1, *consts2; |
1639 | PyObject *res; |
1640 | |
1641 | if ((op != Py_EQ && op != 97 Py_NE97 ) || Branch (1641:10): [True: 97, False: 26.9k]
Branch (1641:25): [True: 0, False: 97]
|
1642 | !PyCode_Check(self) || Branch (1642:9): [True: 0, False: 27.0k]
|
1643 | !PyCode_Check(other)) { Branch (1643:9): [True: 0, False: 27.0k]
|
1644 | Py_RETURN_NOTIMPLEMENTED; |
1645 | } |
1646 | |
1647 | co = (PyCodeObject *)self; |
1648 | cp = (PyCodeObject *)other; |
1649 | |
1650 | eq = PyObject_RichCompareBool(co->co_name, cp->co_name, Py_EQ); |
1651 | if (!eq) goto unequal23.3k ; Branch (1651:9): [True: 23.3k, False: 3.70k]
|
1652 | eq = co->co_argcount == cp->co_argcount; |
1653 | if (!eq) goto unequal1 ; Branch (1653:9): [True: 1, False: 3.70k]
|
1654 | eq = co->co_posonlyargcount == cp->co_posonlyargcount; |
1655 | if (!eq) goto unequal0 ; Branch (1655:9): [True: 0, False: 3.70k]
|
1656 | eq = co->co_kwonlyargcount == cp->co_kwonlyargcount; |
1657 | if (!eq) goto unequal0 ; Branch (1657:9): [True: 0, False: 3.70k]
|
1658 | eq = co->co_flags == cp->co_flags; |
1659 | if (!eq) goto unequal0 ; Branch (1659:9): [True: 0, False: 3.70k]
|
1660 | eq = co->co_firstlineno == cp->co_firstlineno; |
1661 | if (!eq) goto unequal1.43k ; Branch (1661:9): [True: 1.43k, False: 2.27k]
|
1662 | eq = Py_SIZE(co) == Py_SIZE(cp); |
1663 | if (!eq) { Branch (1663:9): [True: 0, False: 2.27k]
|
1664 | goto unequal; |
1665 | } |
1666 | for (int i = 0; 2.27k i < Py_SIZE(co); i++65.3k ) { Branch (1666:21): [True: 65.3k, False: 2.27k]
|
1667 | _Py_CODEUNIT co_instr = _PyCode_CODE(co)[i]; |
1668 | _Py_CODEUNIT cp_instr = _PyCode_CODE(cp)[i]; |
1669 | _Py_SET_OPCODE(co_instr, _PyOpcode_Deopt[_Py_OPCODE(co_instr)]); |
1670 | _Py_SET_OPCODE(cp_instr, _PyOpcode_Deopt[_Py_OPCODE(cp_instr)]); |
1671 | eq = co_instr == cp_instr; |
1672 | if (!eq) { Branch (1672:13): [True: 0, False: 65.3k]
|
1673 | goto unequal; |
1674 | } |
1675 | i += _PyOpcode_Caches[_Py_OPCODE(co_instr)]; |
1676 | } |
1677 | |
1678 | /* compare constants */ |
1679 | consts1 = _PyCode_ConstantKey(co->co_consts); |
1680 | if (!consts1) Branch (1680:9): [True: 0, False: 2.27k]
|
1681 | return NULL; |
1682 | consts2 = _PyCode_ConstantKey(cp->co_consts); |
1683 | if (!consts2) { Branch (1683:9): [True: 0, False: 2.27k]
|
1684 | Py_DECREF(consts1); |
1685 | return NULL; |
1686 | } |
1687 | eq = PyObject_RichCompareBool(consts1, consts2, Py_EQ); |
1688 | Py_DECREF(consts1); |
1689 | Py_DECREF(consts2); |
1690 | if (eq <= 0) goto unequal32 ; Branch (1690:9): [True: 32, False: 2.24k]
|
1691 | |
1692 | eq = PyObject_RichCompareBool(co->co_names, cp->co_names, Py_EQ); |
1693 | if (eq <= 0) goto unequal0 ; Branch (1693:9): [True: 0, False: 2.24k]
|
1694 | eq = PyObject_RichCompareBool(co->co_localsplusnames, |
1695 | cp->co_localsplusnames, Py_EQ); |
1696 | if (eq <= 0) goto unequal0 ; Branch (1696:9): [True: 0, False: 2.24k]
|
1697 | |
1698 | if (op == Py_EQ) Branch (1698:9): [True: 2.15k, False: 90]
|
1699 | res = Py_True; |
1700 | else |
1701 | res = Py_False; |
1702 | goto done; |
1703 | |
1704 | unequal: |
1705 | if (eq < 0) Branch (1705:9): [True: 0, False: 24.7k]
|
1706 | return NULL; |
1707 | if (op == Py_NE) Branch (1707:9): [True: 7, False: 24.7k]
|
1708 | res = Py_True; |
1709 | else |
1710 | res = Py_False; |
1711 | |
1712 | done: |
1713 | Py_INCREF(res); |
1714 | return res; |
1715 | } |
1716 | |
1717 | static Py_hash_t |
1718 | code_hash(PyCodeObject *co) |
1719 | { |
1720 | Py_hash_t h, h0, h1, h2, h3; |
1721 | h0 = PyObject_Hash(co->co_name); |
1722 | if (h0 == -1) return -10 ; Branch (1722:9): [True: 0, False: 192k]
|
1723 | h1 = PyObject_Hash(co->co_consts); |
1724 | if (h1 == -1) return -10 ; Branch (1724:9): [True: 0, False: 192k]
|
1725 | h2 = PyObject_Hash(co->co_names); |
1726 | if (h2 == -1) return -10 ; Branch (1726:9): [True: 0, False: 192k]
|
1727 | h3 = PyObject_Hash(co->co_localsplusnames); |
1728 | if (h3 == -1) return -10 ; Branch (1728:9): [True: 0, False: 192k]
|
1729 | h = h0 ^ h1 ^ h2 ^ h3 ^ |
1730 | co->co_argcount ^ co->co_posonlyargcount ^ co->co_kwonlyargcount ^ |
1731 | co->co_flags; |
1732 | if (h == -1) h = -20 ; Branch (1732:9): [True: 0, False: 192k]
|
1733 | return h; |
1734 | } |
1735 | |
1736 | |
1737 | #define OFF(x) offsetof(PyCodeObject, x) |
1738 | |
1739 | static PyMemberDef code_memberlist[] = { |
1740 | {"co_argcount", T_INT, OFF(co_argcount), READONLY}, |
1741 | {"co_posonlyargcount", T_INT, OFF(co_posonlyargcount), READONLY}, |
1742 | {"co_kwonlyargcount", T_INT, OFF(co_kwonlyargcount), READONLY}, |
1743 | {"co_stacksize", T_INT, OFF(co_stacksize), READONLY}, |
1744 | {"co_flags", T_INT, OFF(co_flags), READONLY}, |
1745 | {"co_nlocals", T_INT, OFF(co_nlocals), READONLY}, |
1746 | {"co_consts", T_OBJECT, OFF(co_consts), READONLY}, |
1747 | {"co_names", T_OBJECT, OFF(co_names), READONLY}, |
1748 | {"co_filename", T_OBJECT, OFF(co_filename), READONLY}, |
1749 | {"co_name", T_OBJECT, OFF(co_name), READONLY}, |
1750 | {"co_qualname", T_OBJECT, OFF(co_qualname), READONLY}, |
1751 | {"co_firstlineno", T_INT, OFF(co_firstlineno), READONLY}, |
1752 | {"co_linetable", T_OBJECT, OFF(co_linetable), READONLY}, |
1753 | {"co_exceptiontable", T_OBJECT, OFF(co_exceptiontable), READONLY}, |
1754 | {NULL} /* Sentinel */ |
1755 | }; |
1756 | |
1757 | |
1758 | static PyObject * |
1759 | code_getlnotab(PyCodeObject *code, void *closure) |
1760 | { |
1761 | return decode_linetable(code); |
1762 | } |
1763 | |
1764 | static PyObject * |
1765 | code_getvarnames(PyCodeObject *code, void *closure) |
1766 | { |
1767 | return _PyCode_GetVarnames(code); |
1768 | } |
1769 | |
1770 | static PyObject * |
1771 | code_getcellvars(PyCodeObject *code, void *closure) |
1772 | { |
1773 | return _PyCode_GetCellvars(code); |
1774 | } |
1775 | |
1776 | static PyObject * |
1777 | code_getfreevars(PyCodeObject *code, void *closure) |
1778 | { |
1779 | return _PyCode_GetFreevars(code); |
1780 | } |
1781 | |
1782 | static PyObject * |
1783 | code_getcodeadaptive(PyCodeObject *code, void *closure) |
1784 | { |
1785 | return PyBytes_FromStringAndSize(code->co_code_adaptive, |
1786 | _PyCode_NBYTES(code)); |
1787 | } |
1788 | |
1789 | static PyObject * |
1790 | code_getcode(PyCodeObject *code, void *closure) |
1791 | { |
1792 | return _PyCode_GetCode(code); |
1793 | } |
1794 | |
1795 | static PyGetSetDef code_getsetlist[] = { |
1796 | {"co_lnotab", (getter)code_getlnotab, NULL, NULL}, |
1797 | {"_co_code_adaptive", (getter)code_getcodeadaptive, NULL, NULL}, |
1798 | // The following old names are kept for backward compatibility. |
1799 | {"co_varnames", (getter)code_getvarnames, NULL, NULL}, |
1800 | {"co_cellvars", (getter)code_getcellvars, NULL, NULL}, |
1801 | {"co_freevars", (getter)code_getfreevars, NULL, NULL}, |
1802 | {"co_code", (getter)code_getcode, NULL, NULL}, |
1803 | {0} |
1804 | }; |
1805 | |
1806 | |
1807 | static PyObject * |
1808 | code_sizeof(PyCodeObject *co, PyObject *Py_UNUSED(args)) |
1809 | { |
1810 | Py_ssize_t res = _PyObject_VAR_SIZE(Py_TYPE(co), Py_SIZE(co)); |
1811 | |
1812 | _PyCodeObjectExtra *co_extra = (_PyCodeObjectExtra*) co->co_extra; |
1813 | if (co_extra != NULL) { Branch (1813:9): [True: 0, False: 3]
|
1814 | res += sizeof(_PyCodeObjectExtra) + |
1815 | (co_extra->ce_size-1) * sizeof(co_extra->ce_extras[0]); |
1816 | } |
1817 | |
1818 | return PyLong_FromSsize_t(res); |
1819 | } |
1820 | |
1821 | static PyObject * |
1822 | code_linesiterator(PyCodeObject *code, PyObject *Py_UNUSED(args)) |
1823 | { |
1824 | return (PyObject *)new_linesiterator(code); |
1825 | } |
1826 | |
1827 | /*[clinic input] |
1828 | code.replace |
1829 | |
1830 | * |
1831 | co_argcount: int(c_default="self->co_argcount") = -1 |
1832 | co_posonlyargcount: int(c_default="self->co_posonlyargcount") = -1 |
1833 | co_kwonlyargcount: int(c_default="self->co_kwonlyargcount") = -1 |
1834 | co_nlocals: int(c_default="self->co_nlocals") = -1 |
1835 | co_stacksize: int(c_default="self->co_stacksize") = -1 |
1836 | co_flags: int(c_default="self->co_flags") = -1 |
1837 | co_firstlineno: int(c_default="self->co_firstlineno") = -1 |
1838 | co_code: PyBytesObject(c_default="NULL") = None |
1839 | co_consts: object(subclass_of="&PyTuple_Type", c_default="self->co_consts") = None |
1840 | co_names: object(subclass_of="&PyTuple_Type", c_default="self->co_names") = None |
1841 | co_varnames: object(subclass_of="&PyTuple_Type", c_default="NULL") = None |
1842 | co_freevars: object(subclass_of="&PyTuple_Type", c_default="NULL") = None |
1843 | co_cellvars: object(subclass_of="&PyTuple_Type", c_default="NULL") = None |
1844 | co_filename: unicode(c_default="self->co_filename") = None |
1845 | co_name: unicode(c_default="self->co_name") = None |
1846 | co_qualname: unicode(c_default="self->co_qualname") = None |
1847 | co_linetable: PyBytesObject(c_default="(PyBytesObject *)self->co_linetable") = None |
1848 | co_exceptiontable: PyBytesObject(c_default="(PyBytesObject *)self->co_exceptiontable") = None |
1849 | |
1850 | Return a copy of the code object with new values for the specified fields. |
1851 | [clinic start generated code]*/ |
1852 | |
1853 | static PyObject * |
1854 | code_replace_impl(PyCodeObject *self, int co_argcount, |
1855 | int co_posonlyargcount, int co_kwonlyargcount, |
1856 | int co_nlocals, int co_stacksize, int co_flags, |
1857 | int co_firstlineno, PyBytesObject *co_code, |
1858 | PyObject *co_consts, PyObject *co_names, |
1859 | PyObject *co_varnames, PyObject *co_freevars, |
1860 | PyObject *co_cellvars, PyObject *co_filename, |
1861 | PyObject *co_name, PyObject *co_qualname, |
1862 | PyBytesObject *co_linetable, |
1863 | PyBytesObject *co_exceptiontable) |
1864 | /*[clinic end generated code: output=b6cd9988391d5711 input=f6f68e03571f8d7c]*/ |
1865 | { |
1866 | #define CHECK_INT_ARG(ARG) \ |
1867 | if (ARG < 0) { \ |
1868 | PyErr_SetString(PyExc_ValueError, \ |
1869 | #ARG " must be a positive integer"); \ |
1870 | return NULL; \ |
1871 | } |
1872 | |
1873 | CHECK_INT_ARG(co_argcount); |
1874 | CHECK_INT_ARG(co_posonlyargcount); |
1875 | CHECK_INT_ARG(co_kwonlyargcount); |
1876 | CHECK_INT_ARG(co_nlocals); |
1877 | CHECK_INT_ARG(co_stacksize); |
1878 | CHECK_INT_ARG(co_flags); |
1879 | CHECK_INT_ARG(co_firstlineno); |
1880 | |
1881 | #undef CHECK_INT_ARG |
1882 | |
1883 | PyObject *code = NULL; |
1884 | if (co_code == NULL) { Branch (1884:9): [True: 65, False: 2]
|
1885 | code = _PyCode_GetCode(self); |
1886 | if (code == NULL) { Branch (1886:13): [True: 0, False: 65]
|
1887 | return NULL; |
1888 | } |
1889 | co_code = (PyBytesObject *)code; |
1890 | } |
1891 | |
1892 | if (PySys_Audit("code.__new__", "OOOiiiiii", Branch (1892:9): [True: 0, False: 67]
|
1893 | co_code, co_filename, co_name, co_argcount, |
1894 | co_posonlyargcount, co_kwonlyargcount, co_nlocals, |
1895 | co_stacksize, co_flags) < 0) { |
1896 | return NULL; |
1897 | } |
1898 | |
1899 | PyCodeObject *co = NULL; |
1900 | PyObject *varnames = NULL; |
1901 | PyObject *cellvars = NULL; |
1902 | PyObject *freevars = NULL; |
1903 | if (co_varnames == NULL) { Branch (1903:9): [True: 65, False: 2]
|
1904 | varnames = get_localsplus_names(self, CO_FAST_LOCAL, self->co_nlocals); |
1905 | if (varnames == NULL) { Branch (1905:13): [True: 0, False: 65]
|
1906 | goto error; |
1907 | } |
1908 | co_varnames = varnames; |
1909 | } |
1910 | if (co_cellvars == NULL) { Branch (1910:9): [True: 66, False: 1]
|
1911 | cellvars = get_localsplus_names(self, CO_FAST_CELL, self->co_ncellvars); |
1912 | if (cellvars == NULL) { Branch (1912:13): [True: 0, False: 66]
|
1913 | goto error; |
1914 | } |
1915 | co_cellvars = cellvars; |
1916 | } |
1917 | if (co_freevars == NULL) { Branch (1917:9): [True: 65, False: 2]
|
1918 | freevars = get_localsplus_names(self, CO_FAST_FREE, self->co_nfreevars); |
1919 | if (freevars == NULL) { Branch (1919:13): [True: 0, False: 65]
|
1920 | goto error; |
1921 | } |
1922 | co_freevars = freevars; |
1923 | } |
1924 | |
1925 | co = PyCode_NewWithPosOnlyArgs( |
1926 | co_argcount, co_posonlyargcount, co_kwonlyargcount, co_nlocals, |
1927 | co_stacksize, co_flags, (PyObject*)co_code, co_consts, co_names, |
1928 | co_varnames, co_freevars, co_cellvars, co_filename, co_name, |
1929 | co_qualname, co_firstlineno, |
1930 | (PyObject*)co_linetable, (PyObject*)co_exceptiontable); |
1931 | |
1932 | error: |
1933 | Py_XDECREF(code); |
1934 | Py_XDECREF(varnames); |
1935 | Py_XDECREF(cellvars); |
1936 | Py_XDECREF(freevars); |
1937 | return (PyObject *)co; |
1938 | } |
1939 | |
1940 | /*[clinic input] |
1941 | code._varname_from_oparg |
1942 | |
1943 | oparg: int |
1944 | |
1945 | (internal-only) Return the local variable name for the given oparg. |
1946 | |
1947 | WARNING: this method is for internal use only and may change or go away. |
1948 | [clinic start generated code]*/ |
1949 | |
1950 | static PyObject * |
1951 | code__varname_from_oparg_impl(PyCodeObject *self, int oparg) |
1952 | /*[clinic end generated code: output=1fd1130413184206 input=c5fa3ee9bac7d4ca]*/ |
1953 | { |
1954 | PyObject *name = PyTuple_GetItem(self->co_localsplusnames, oparg); |
1955 | if (name == NULL) { Branch (1955:9): [True: 0, False: 8.94k]
|
1956 | return NULL; |
1957 | } |
1958 | Py_INCREF(name); |
1959 | return name; |
1960 | } |
1961 | |
1962 | /* XXX code objects need to participate in GC? */ |
1963 | |
1964 | static struct PyMethodDef code_methods[] = { |
1965 | {"__sizeof__", (PyCFunction)code_sizeof, METH_NOARGS}, |
1966 | {"co_lines", (PyCFunction)code_linesiterator, METH_NOARGS}, |
1967 | {"co_positions", (PyCFunction)code_positionsiterator, METH_NOARGS}, |
1968 | CODE_REPLACE_METHODDEF |
1969 | CODE__VARNAME_FROM_OPARG_METHODDEF |
1970 | {NULL, NULL} /* sentinel */ |
1971 | }; |
1972 | |
1973 | |
1974 | PyTypeObject PyCode_Type = { |
1975 | PyVarObject_HEAD_INIT(&PyType_Type, 0) |
1976 | "code", |
1977 | offsetof(PyCodeObject, co_code_adaptive), |
1978 | sizeof(_Py_CODEUNIT), |
1979 | (destructor)code_dealloc, /* tp_dealloc */ |
1980 | 0, /* tp_vectorcall_offset */ |
1981 | 0, /* tp_getattr */ |
1982 | 0, /* tp_setattr */ |
1983 | 0, /* tp_as_async */ |
1984 | (reprfunc)code_repr, /* tp_repr */ |
1985 | 0, /* tp_as_number */ |
1986 | 0, /* tp_as_sequence */ |
1987 | 0, /* tp_as_mapping */ |
1988 | (hashfunc)code_hash, /* tp_hash */ |
1989 | 0, /* tp_call */ |
1990 | 0, /* tp_str */ |
1991 | PyObject_GenericGetAttr, /* tp_getattro */ |
1992 | 0, /* tp_setattro */ |
1993 | 0, /* tp_as_buffer */ |
1994 | Py_TPFLAGS_DEFAULT, /* tp_flags */ |
1995 | code_new__doc__, /* tp_doc */ |
1996 | 0, /* tp_traverse */ |
1997 | 0, /* tp_clear */ |
1998 | code_richcompare, /* tp_richcompare */ |
1999 | offsetof(PyCodeObject, co_weakreflist), /* tp_weaklistoffset */ |
2000 | 0, /* tp_iter */ |
2001 | 0, /* tp_iternext */ |
2002 | code_methods, /* tp_methods */ |
2003 | code_memberlist, /* tp_members */ |
2004 | code_getsetlist, /* tp_getset */ |
2005 | 0, /* tp_base */ |
2006 | 0, /* tp_dict */ |
2007 | 0, /* tp_descr_get */ |
2008 | 0, /* tp_descr_set */ |
2009 | 0, /* tp_dictoffset */ |
2010 | 0, /* tp_init */ |
2011 | 0, /* tp_alloc */ |
2012 | code_new, /* tp_new */ |
2013 | }; |
2014 | |
2015 | |
2016 | /****************** |
2017 | * other API |
2018 | ******************/ |
2019 | |
2020 | PyObject* |
2021 | _PyCode_ConstantKey(PyObject *op) |
2022 | { |
2023 | PyObject *key; |
2024 | |
2025 | /* Py_None and Py_Ellipsis are singletons. */ |
2026 | if (op == Py_None || op == 1.94M Py_Ellipsis1.94M Branch (2026:9): [True: 41.5k, False: 1.94M]
Branch (2026:26): [True: 439, False: 1.94M]
|
2027 | || PyLong_CheckExact(op) |
2028 | || PyUnicode_CheckExact(op) |
2029 | /* code_richcompare() uses _PyCode_ConstantKey() internally */ |
2030 | || PyCode_Check537k (op)) |
2031 | { |
2032 | /* Objects of these types are always different from object of other |
2033 | * type and from tuples. */ |
2034 | Py_INCREF(op); |
2035 | key = op; |
2036 | } |
2037 | else if (PyBool_Check(op) || PyBytes_CheckExact477k (op)) { |
2038 | /* Make booleans different from integers 0 and 1. |
2039 | * Avoid BytesWarning from comparing bytes with strings. */ |
2040 | key = PyTuple_Pack(2, Py_TYPE(op), op); |
2041 | } |
2042 | else if (PyFloat_CheckExact(op)) { |
2043 | double d = PyFloat_AS_DOUBLE(op); |
2044 | /* all we need is to make the tuple different in either the 0.0 |
2045 | * or -0.0 case from all others, just to avoid the "coercion". |
2046 | */ |
2047 | if (d == 0.0 && copysign(1.0, d) < 0.0339 ) Branch (2047:13): [True: 339, False: 6.20k]
Branch (2047:25): [True: 34, False: 305]
|
2048 | key = PyTuple_Pack(3, Py_TYPE(op), op, Py_None); |
2049 | else |
2050 | key = PyTuple_Pack(2, Py_TYPE(op), op); |
2051 | } |
2052 | else if (PyComplex_CheckExact(op)) { |
2053 | Py_complex z; |
2054 | int real_negzero, imag_negzero; |
2055 | /* For the complex case we must make complex(x, 0.) |
2056 | different from complex(x, -0.) and complex(0., y) |
2057 | different from complex(-0., y), for any x and y. |
2058 | All four complex zeros must be distinguished.*/ |
2059 | z = PyComplex_AsCComplex(op); |
2060 | real_negzero = z.real == 0.0 && copysign(1.0, z.real) < 0.0476 ; Branch (2060:24): [True: 476, False: 410]
Branch (2060:41): [True: 80, False: 396]
|
2061 | imag_negzero = z.imag == 0.0 && copysign(1.0, z.imag) < 0.0262 ; Branch (2061:24): [True: 262, False: 624]
Branch (2061:41): [True: 52, False: 210]
|
2062 | /* use True, False and None singleton as tags for the real and imag |
2063 | * sign, to make tuples different */ |
2064 | if (real_negzero && imag_negzero80 ) { Branch (2064:13): [True: 80, False: 806]
Branch (2064:29): [True: 52, False: 28]
|
2065 | key = PyTuple_Pack(3, Py_TYPE(op), op, Py_True); |
2066 | } |
2067 | else if (imag_negzero) { Branch (2067:18): [True: 0, False: 834]
|
2068 | key = PyTuple_Pack(3, Py_TYPE(op), op, Py_False); |
2069 | } |
2070 | else if (real_negzero) { Branch (2070:18): [True: 28, False: 806]
|
2071 | key = PyTuple_Pack(3, Py_TYPE(op), op, Py_None); |
2072 | } |
2073 | else { |
2074 | key = PyTuple_Pack(2, Py_TYPE(op), op); |
2075 | } |
2076 | } |
2077 | else if (PyTuple_CheckExact(op)) { |
2078 | Py_ssize_t i, len; |
2079 | PyObject *tuple; |
2080 | |
2081 | len = PyTuple_GET_SIZE(op); |
2082 | tuple = PyTuple_New(len); |
2083 | if (tuple == NULL) Branch (2083:13): [True: 0, False: 244k]
|
2084 | return NULL; |
2085 | |
2086 | for (i=0; 244k i < len; i++955k ) { Branch (2086:19): [True: 955k, False: 244k]
|
2087 | PyObject *item, *item_key; |
2088 | |
2089 | item = PyTuple_GET_ITEM(op, i); |
2090 | item_key = _PyCode_ConstantKey(item); |
2091 | if (item_key == NULL) { Branch (2091:17): [True: 0, False: 955k]
|
2092 | Py_DECREF(tuple); |
2093 | return NULL; |
2094 | } |
2095 | |
2096 | PyTuple_SET_ITEM(tuple, i, item_key); |
2097 | } |
2098 | |
2099 | key = PyTuple_Pack(2, tuple, op); |
2100 | Py_DECREF(tuple); |
2101 | } |
2102 | else if (PyFrozenSet_CheckExact(op)) { |
2103 | Py_ssize_t pos = 0; |
2104 | PyObject *item; |
2105 | Py_hash_t hash; |
2106 | Py_ssize_t i, len; |
2107 | PyObject *tuple, *set; |
2108 | |
2109 | len = PySet_GET_SIZE(op); |
2110 | tuple = PyTuple_New(len); |
2111 | if (tuple == NULL) Branch (2111:13): [True: 0, False: 277]
|
2112 | return NULL; |
2113 | |
2114 | i = 0; |
2115 | while (_PySet_NextEntry(op, &pos, &item, &hash)) { Branch (2115:16): [True: 633, False: 277]
|
2116 | PyObject *item_key; |
2117 | |
2118 | item_key = _PyCode_ConstantKey(item); |
2119 | if (item_key == NULL) { Branch (2119:17): [True: 0, False: 633]
|
2120 | Py_DECREF(tuple); |
2121 | return NULL; |
2122 | } |
2123 | |
2124 | assert(i < len); |
2125 | PyTuple_SET_ITEM(tuple, i, item_key); |
2126 | i++; |
2127 | } |
2128 | set = PyFrozenSet_New(tuple); |
2129 | Py_DECREF(tuple); |
2130 | if (set == NULL) Branch (2130:13): [True: 0, False: 277]
|
2131 | return NULL; |
2132 | |
2133 | key = PyTuple_Pack(2, set, op); |
2134 | Py_DECREF(set); |
2135 | return key; |
2136 | } |
2137 | else { |
2138 | /* for other types, use the object identifier as a unique identifier |
2139 | * to ensure that they are seen as unequal. */ |
2140 | PyObject *obj_id = PyLong_FromVoidPtr(op); |
2141 | if (obj_id == NULL) Branch (2141:13): [True: 0, False: 0]
|
2142 | return NULL; |
2143 | |
2144 | key = PyTuple_Pack(2, obj_id, op); |
2145 | Py_DECREF(obj_id); |
2146 | } |
2147 | return key; |
2148 | } |
2149 | |
2150 | void |
2151 | _PyStaticCode_Dealloc(PyCodeObject *co) |
2152 | { |
2153 | if (co->co_warmup == 0) { Branch (2153:9): [True: 8.49k, False: 70.9k]
|
2154 | _Py_QuickenedCount--; |
2155 | } |
2156 | deopt_code(_PyCode_CODE(co), Py_SIZE(co)); |
2157 | co->co_warmup = QUICKENING_INITIAL_WARMUP_VALUE; |
2158 | PyMem_Free(co->co_extra); |
2159 | Py_CLEAR(co->_co_code); |
2160 | co->co_extra = NULL; |
2161 | if (co->co_weakreflist != NULL) { Branch (2161:9): [True: 0, False: 79.4k]
|
2162 | PyObject_ClearWeakRefs((PyObject *)co); |
2163 | co->co_weakreflist = NULL; |
2164 | } |
2165 | if (co->_co_linearray) { Branch (2165:9): [True: 84, False: 79.3k]
|
2166 | PyMem_Free(co->_co_linearray); |
2167 | co->_co_linearray = NULL; |
2168 | } |
2169 | } |
2170 | |
2171 | int |
2172 | _PyStaticCode_InternStrings(PyCodeObject *co) |
2173 | { |
2174 | int res = intern_strings(co->co_names); |
2175 | if (res < 0) { Branch (2175:9): [True: 0, False: 214k]
|
2176 | return -1; |
2177 | } |
2178 | res = intern_string_constants(co->co_consts, NULL); |
2179 | if (res < 0) { Branch (2179:9): [True: 0, False: 214k]
|
2180 | return -1; |
2181 | } |
2182 | res = intern_strings(co->co_localsplusnames); |
2183 | if (res < 0) { Branch (2183:9): [True: 0, False: 214k]
|
2184 | return -1; |
2185 | } |
2186 | return 0; |
2187 | } |