Branch data Line data Source code
1 : : #ifndef Py_INTERNAL_CODE_H
2 : : #define Py_INTERNAL_CODE_H
3 : : #ifdef __cplusplus
4 : : extern "C" {
5 : : #endif
6 : :
7 : : /* PEP 659
8 : : * Specialization and quickening structs and helper functions
9 : : */
10 : :
11 : :
12 : : // Inline caches. If you change the number of cache entries for an instruction,
13 : : // you must *also* update the number of cache entries in Lib/opcode.py and bump
14 : : // the magic number in Lib/importlib/_bootstrap_external.py!
15 : :
16 : : #define CACHE_ENTRIES(cache) (sizeof(cache)/sizeof(_Py_CODEUNIT))
17 : :
18 : : typedef struct {
19 : : _Py_CODEUNIT counter;
20 : : _Py_CODEUNIT index;
21 : : _Py_CODEUNIT module_keys_version[2];
22 : : _Py_CODEUNIT builtin_keys_version;
23 : : } _PyLoadGlobalCache;
24 : :
25 : : #define INLINE_CACHE_ENTRIES_LOAD_GLOBAL CACHE_ENTRIES(_PyLoadGlobalCache)
26 : :
27 : : typedef struct {
28 : : _Py_CODEUNIT counter;
29 : : } _PyBinaryOpCache;
30 : :
31 : : #define INLINE_CACHE_ENTRIES_BINARY_OP CACHE_ENTRIES(_PyBinaryOpCache)
32 : :
33 : : typedef struct {
34 : : _Py_CODEUNIT counter;
35 : : } _PyUnpackSequenceCache;
36 : :
37 : : #define INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE \
38 : : CACHE_ENTRIES(_PyUnpackSequenceCache)
39 : :
40 : : typedef struct {
41 : : _Py_CODEUNIT counter;
42 : : _Py_CODEUNIT mask;
43 : : } _PyCompareOpCache;
44 : :
45 : : #define INLINE_CACHE_ENTRIES_COMPARE_OP CACHE_ENTRIES(_PyCompareOpCache)
46 : :
47 : : typedef struct {
48 : : _Py_CODEUNIT counter;
49 : : _Py_CODEUNIT type_version[2];
50 : : _Py_CODEUNIT func_version;
51 : : } _PyBinarySubscrCache;
52 : :
53 : : #define INLINE_CACHE_ENTRIES_BINARY_SUBSCR CACHE_ENTRIES(_PyBinarySubscrCache)
54 : :
55 : : typedef struct {
56 : : _Py_CODEUNIT counter;
57 : : _Py_CODEUNIT version[2];
58 : : _Py_CODEUNIT index;
59 : : } _PyAttrCache;
60 : :
61 : : typedef struct {
62 : : _Py_CODEUNIT counter;
63 : : _Py_CODEUNIT type_version[2];
64 : : _Py_CODEUNIT keys_version[2];
65 : : _Py_CODEUNIT descr[4];
66 : : } _PyLoadMethodCache;
67 : :
68 : :
69 : : // MUST be the max(_PyAttrCache, _PyLoadMethodCache)
70 : : #define INLINE_CACHE_ENTRIES_LOAD_ATTR CACHE_ENTRIES(_PyLoadMethodCache)
71 : :
72 : : #define INLINE_CACHE_ENTRIES_STORE_ATTR CACHE_ENTRIES(_PyAttrCache)
73 : :
74 : : typedef struct {
75 : : _Py_CODEUNIT counter;
76 : : _Py_CODEUNIT func_version[2];
77 : : _Py_CODEUNIT min_args;
78 : : } _PyCallCache;
79 : :
80 : : #define INLINE_CACHE_ENTRIES_CALL CACHE_ENTRIES(_PyCallCache)
81 : :
82 : : typedef struct {
83 : : _Py_CODEUNIT counter;
84 : : } _PyStoreSubscrCache;
85 : :
86 : : #define INLINE_CACHE_ENTRIES_STORE_SUBSCR CACHE_ENTRIES(_PyStoreSubscrCache)
87 : :
88 : : typedef struct {
89 : : _Py_CODEUNIT counter;
90 : : } _PyForIterCache;
91 : :
92 : : #define INLINE_CACHE_ENTRIES_FOR_ITER CACHE_ENTRIES(_PyForIterCache)
93 : :
94 : : #define QUICKENING_WARMUP_DELAY 8
95 : :
96 : : /* We want to compare to zero for efficiency, so we offset values accordingly */
97 : : #define QUICKENING_INITIAL_WARMUP_VALUE (-QUICKENING_WARMUP_DELAY)
98 : :
99 : : void _PyCode_Quicken(PyCodeObject *code);
100 : :
101 : : static inline void
102 : 10128802 : _PyCode_Warmup(PyCodeObject *code)
103 : : {
104 [ + + ]: 10128802 : if (code->co_warmup != 0) {
105 : 7581171 : code->co_warmup++;
106 [ + + ]: 7581171 : if (code->co_warmup == 0) {
107 : 602238 : _PyCode_Quicken(code);
108 : : }
109 : : }
110 : 10128802 : }
111 : :
112 : : extern uint8_t _PyOpcode_Adaptive[256];
113 : :
114 : : extern Py_ssize_t _Py_QuickenedCount;
115 : :
116 : : // Borrowed references to common callables:
117 : : struct callable_cache {
118 : : PyObject *isinstance;
119 : : PyObject *len;
120 : : PyObject *list_append;
121 : : };
122 : :
123 : : /* "Locals plus" for a code object is the set of locals + cell vars +
124 : : * free vars. This relates to variable names as well as offsets into
125 : : * the "fast locals" storage array of execution frames. The compiler
126 : : * builds the list of names, their offsets, and the corresponding
127 : : * kind of local.
128 : : *
129 : : * Those kinds represent the source of the initial value and the
130 : : * variable's scope (as related to closures). A "local" is an
131 : : * argument or other variable defined in the current scope. A "free"
132 : : * variable is one that is defined in an outer scope and comes from
133 : : * the function's closure. A "cell" variable is a local that escapes
134 : : * into an inner function as part of a closure, and thus must be
135 : : * wrapped in a cell. Any "local" can also be a "cell", but the
136 : : * "free" kind is mutually exclusive with both.
137 : : */
138 : :
139 : : // Note that these all fit within a byte, as do combinations.
140 : : // Later, we will use the smaller numbers to differentiate the different
141 : : // kinds of locals (e.g. pos-only arg, varkwargs, local-only).
142 : : #define CO_FAST_LOCAL 0x20
143 : : #define CO_FAST_CELL 0x40
144 : : #define CO_FAST_FREE 0x80
145 : :
146 : : typedef unsigned char _PyLocals_Kind;
147 : :
148 : : static inline _PyLocals_Kind
149 : 57578339 : _PyLocals_GetKind(PyObject *kinds, int i)
150 : : {
151 : : assert(PyBytes_Check(kinds));
152 : : assert(0 <= i && i < PyBytes_GET_SIZE(kinds));
153 : 57578339 : char *ptr = PyBytes_AS_STRING(kinds);
154 : 57578339 : return (_PyLocals_Kind)(ptr[i]);
155 : : }
156 : :
157 : : static inline void
158 : 1131520 : _PyLocals_SetKind(PyObject *kinds, int i, _PyLocals_Kind kind)
159 : : {
160 : : assert(PyBytes_Check(kinds));
161 : : assert(0 <= i && i < PyBytes_GET_SIZE(kinds));
162 : 1131520 : char *ptr = PyBytes_AS_STRING(kinds);
163 : 1131520 : ptr[i] = (char) kind;
164 : 1131520 : }
165 : :
166 : :
167 : : struct _PyCodeConstructor {
168 : : /* metadata */
169 : : PyObject *filename;
170 : : PyObject *name;
171 : : PyObject *qualname;
172 : : int flags;
173 : :
174 : : /* the code */
175 : : PyObject *code;
176 : : int firstlineno;
177 : : PyObject *linetable;
178 : :
179 : : /* used by the code */
180 : : PyObject *consts;
181 : : PyObject *names;
182 : :
183 : : /* mapping frame offsets to information */
184 : : PyObject *localsplusnames; // Tuple of strings
185 : : PyObject *localspluskinds; // Bytes object, one byte per variable
186 : :
187 : : /* args (within varnames) */
188 : : int argcount;
189 : : int posonlyargcount;
190 : : // XXX Replace argcount with posorkwargcount (argcount - posonlyargcount).
191 : : int kwonlyargcount;
192 : :
193 : : /* needed to create the frame */
194 : : int stacksize;
195 : :
196 : : /* used by the eval loop */
197 : : PyObject *exceptiontable;
198 : : };
199 : :
200 : : // Using an "arguments struct" like this is helpful for maintainability
201 : : // in a case such as this with many parameters. It does bear a risk:
202 : : // if the struct changes and callers are not updated properly then the
203 : : // compiler will not catch problems (like a missing argument). This can
204 : : // cause hard-to-debug problems. The risk is mitigated by the use of
205 : : // check_code() in codeobject.c. However, we may decide to switch
206 : : // back to a regular function signature. Regardless, this approach
207 : : // wouldn't be appropriate if this weren't a strictly internal API.
208 : : // (See the comments in https://github.com/python/cpython/pull/26258.)
209 : : PyAPI_FUNC(int) _PyCode_Validate(struct _PyCodeConstructor *);
210 : : PyAPI_FUNC(PyCodeObject *) _PyCode_New(struct _PyCodeConstructor *);
211 : :
212 : :
213 : : /* Private API */
214 : :
215 : : /* Getters for internal PyCodeObject data. */
216 : : extern PyObject* _PyCode_GetVarnames(PyCodeObject *);
217 : : extern PyObject* _PyCode_GetCellvars(PyCodeObject *);
218 : : extern PyObject* _PyCode_GetFreevars(PyCodeObject *);
219 : : extern PyObject* _PyCode_GetCode(PyCodeObject *);
220 : :
221 : : /** API for initializing the line number tables. */
222 : : extern int _PyCode_InitAddressRange(PyCodeObject* co, PyCodeAddressRange *bounds);
223 : :
224 : : /** Out of process API for initializing the location table. */
225 : : extern void _PyLineTable_InitAddressRange(
226 : : const char *linetable,
227 : : Py_ssize_t length,
228 : : int firstlineno,
229 : : PyCodeAddressRange *range);
230 : :
231 : : /** API for traversing the line number table. */
232 : : extern int _PyLineTable_NextAddressRange(PyCodeAddressRange *range);
233 : : extern int _PyLineTable_PreviousAddressRange(PyCodeAddressRange *range);
234 : :
235 : : /* Specialization functions */
236 : :
237 : : extern int _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr,
238 : : PyObject *name);
239 : : extern int _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr,
240 : : PyObject *name);
241 : : extern int _Py_Specialize_LoadGlobal(PyObject *globals, PyObject *builtins, _Py_CODEUNIT *instr, PyObject *name);
242 : : extern int _Py_Specialize_BinarySubscr(PyObject *sub, PyObject *container, _Py_CODEUNIT *instr);
243 : : extern int _Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub, _Py_CODEUNIT *instr);
244 : : extern int _Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr,
245 : : int nargs, PyObject *kwnames);
246 : : extern void _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
247 : : int oparg, PyObject **locals);
248 : : extern void _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs,
249 : : _Py_CODEUNIT *instr, int oparg);
250 : : extern void _Py_Specialize_UnpackSequence(PyObject *seq, _Py_CODEUNIT *instr,
251 : : int oparg);
252 : : extern void _Py_Specialize_ForIter(PyObject *iter, _Py_CODEUNIT *instr);
253 : :
254 : : /* Deallocator function for static codeobjects used in deepfreeze.py */
255 : : extern void _PyStaticCode_Dealloc(PyCodeObject *co);
256 : : /* Function to intern strings of codeobjects */
257 : : extern int _PyStaticCode_InternStrings(PyCodeObject *co);
258 : :
259 : : #ifdef Py_STATS
260 : :
261 : :
262 : : #define STAT_INC(opname, name) do { if (_py_stats) _py_stats->opcode_stats[opname].specialization.name++; } while (0)
263 : : #define STAT_DEC(opname, name) do { if (_py_stats) _py_stats->opcode_stats[opname].specialization.name--; } while (0)
264 : : #define OPCODE_EXE_INC(opname) do { if (_py_stats) _py_stats->opcode_stats[opname].execution_count++; } while (0)
265 : : #define CALL_STAT_INC(name) do { if (_py_stats) _py_stats->call_stats.name++; } while (0)
266 : : #define OBJECT_STAT_INC(name) do { if (_py_stats) _py_stats->object_stats.name++; } while (0)
267 : : #define OBJECT_STAT_INC_COND(name, cond) \
268 : : do { if (_py_stats && cond) _py_stats->object_stats.name++; } while (0)
269 : : #define EVAL_CALL_STAT_INC(name) do { if (_py_stats) _py_stats->call_stats.eval_calls[name]++; } while (0)
270 : : #define EVAL_CALL_STAT_INC_IF_FUNCTION(name, callable) \
271 : : do { if (_py_stats && PyFunction_Check(callable)) _py_stats->call_stats.eval_calls[name]++; } while (0)
272 : :
273 : : // Used by the _opcode extension which is built as a shared library
274 : : PyAPI_FUNC(PyObject*) _Py_GetSpecializationStats(void);
275 : :
276 : : #else
277 : : #define STAT_INC(opname, name) ((void)0)
278 : : #define STAT_DEC(opname, name) ((void)0)
279 : : #define OPCODE_EXE_INC(opname) ((void)0)
280 : : #define CALL_STAT_INC(name) ((void)0)
281 : : #define OBJECT_STAT_INC(name) ((void)0)
282 : : #define OBJECT_STAT_INC_COND(name, cond) ((void)0)
283 : : #define EVAL_CALL_STAT_INC(name) ((void)0)
284 : : #define EVAL_CALL_STAT_INC_IF_FUNCTION(name, callable) ((void)0)
285 : : #endif // !Py_STATS
286 : :
287 : : // Cache values are only valid in memory, so use native endianness.
288 : : #ifdef WORDS_BIGENDIAN
289 : :
290 : : static inline void
291 : : write_u32(uint16_t *p, uint32_t val)
292 : : {
293 : : p[0] = (uint16_t)(val >> 16);
294 : : p[1] = (uint16_t)(val >> 0);
295 : : }
296 : :
297 : : static inline void
298 : : write_u64(uint16_t *p, uint64_t val)
299 : : {
300 : : p[0] = (uint16_t)(val >> 48);
301 : : p[1] = (uint16_t)(val >> 32);
302 : : p[2] = (uint16_t)(val >> 16);
303 : : p[3] = (uint16_t)(val >> 0);
304 : : }
305 : :
306 : : static inline uint32_t
307 : : read_u32(uint16_t *p)
308 : : {
309 : : uint32_t val = 0;
310 : : val |= (uint32_t)p[0] << 16;
311 : : val |= (uint32_t)p[1] << 0;
312 : : return val;
313 : : }
314 : :
315 : : static inline uint64_t
316 : : read_u64(uint16_t *p)
317 : : {
318 : : uint64_t val = 0;
319 : : val |= (uint64_t)p[0] << 48;
320 : : val |= (uint64_t)p[1] << 32;
321 : : val |= (uint64_t)p[2] << 16;
322 : : val |= (uint64_t)p[3] << 0;
323 : : return val;
324 : : }
325 : :
326 : : #else
327 : :
328 : : static inline void
329 : 4832748 : write_u32(uint16_t *p, uint32_t val)
330 : : {
331 : 4832748 : p[0] = (uint16_t)(val >> 0);
332 : 4832748 : p[1] = (uint16_t)(val >> 16);
333 : 4832748 : }
334 : :
335 : : static inline void
336 : 703792 : write_u64(uint16_t *p, uint64_t val)
337 : : {
338 : 703792 : p[0] = (uint16_t)(val >> 0);
339 : 703792 : p[1] = (uint16_t)(val >> 16);
340 : 703792 : p[2] = (uint16_t)(val >> 32);
341 : 703792 : p[3] = (uint16_t)(val >> 48);
342 : 703792 : }
343 : :
344 : : static inline uint32_t
345 : 1400201006 : read_u32(uint16_t *p)
346 : : {
347 : 1400201006 : uint32_t val = 0;
348 : 1400201006 : val |= (uint32_t)p[0] << 0;
349 : 1400201006 : val |= (uint32_t)p[1] << 16;
350 : 1400201006 : return val;
351 : : }
352 : :
353 : : static inline uint64_t
354 : 261239135 : read_u64(uint16_t *p)
355 : : {
356 : 261239135 : uint64_t val = 0;
357 : 261239135 : val |= (uint64_t)p[0] << 0;
358 : 261239135 : val |= (uint64_t)p[1] << 16;
359 : 261239135 : val |= (uint64_t)p[2] << 32;
360 : 261239135 : val |= (uint64_t)p[3] << 48;
361 : 261239135 : return val;
362 : : }
363 : :
364 : : #endif
365 : :
366 : : static inline void
367 : 703792 : write_obj(uint16_t *p, PyObject *obj)
368 : : {
369 : 703792 : uintptr_t val = (uintptr_t)obj;
370 : : #if SIZEOF_VOID_P == 8
371 : 703792 : write_u64(p, val);
372 : : #elif SIZEOF_VOID_P == 4
373 : : write_u32(p, val);
374 : : #else
375 : : #error "SIZEOF_VOID_P must be 4 or 8"
376 : : #endif
377 : 703792 : }
378 : :
379 : : static inline PyObject *
380 : 261239135 : read_obj(uint16_t *p)
381 : : {
382 : : uintptr_t val;
383 : : #if SIZEOF_VOID_P == 8
384 : 261239135 : val = read_u64(p);
385 : : #elif SIZEOF_VOID_P == 4
386 : : val = read_u32(p);
387 : : #else
388 : : #error "SIZEOF_VOID_P must be 4 or 8"
389 : : #endif
390 : 261239135 : return (PyObject *)val;
391 : : }
392 : :
393 : : /* See Objects/exception_handling_notes.txt for details.
394 : : */
395 : : static inline unsigned char *
396 : 32074115 : parse_varint(unsigned char *p, int *result) {
397 : 32074115 : int val = p[0] & 63;
398 [ + + ]: 44847036 : while (p[0] & 64) {
399 : 12772921 : p++;
400 : 12772921 : val = (val << 6) | (p[0] & 63);
401 : : }
402 : 32074115 : *result = val;
403 : 32074115 : return p+1;
404 : : }
405 : :
406 : : static inline int
407 : 20404389 : write_varint(uint8_t *ptr, unsigned int val)
408 : : {
409 : 20404389 : int written = 1;
410 [ + + ]: 24156758 : while (val >= 64) {
411 : 3752369 : *ptr++ = 64 | (val & 63);
412 : 3752369 : val >>= 6;
413 : 3752369 : written++;
414 : : }
415 : 20404389 : *ptr = val;
416 : 20404389 : return written;
417 : : }
418 : :
419 : : static inline int
420 : 5255301 : write_signed_varint(uint8_t *ptr, int val)
421 : : {
422 [ + + ]: 5255301 : if (val < 0) {
423 : 922906 : val = ((-val)<<1) | 1;
424 : : }
425 : : else {
426 : 4332395 : val = val << 1;
427 : : }
428 : 5255301 : return write_varint(ptr, val);
429 : : }
430 : :
431 : : static inline int
432 : 18662658 : write_location_entry_start(uint8_t *ptr, int code, int length)
433 : : {
434 : : assert((code & 15) == code);
435 : 18662658 : *ptr = 128 | (code << 3) | (length - 1);
436 : 18662658 : return 1;
437 : : }
438 : :
439 : :
440 : : /** Counters
441 : : * The first 16-bit value in each inline cache is a counter.
442 : : * When counting misses, the counter is treated as a simple unsigned value.
443 : : *
444 : : * When counting executions until the next specialization attempt,
445 : : * exponential backoff is used to reduce the number of specialization failures.
446 : : * The high 12 bits store the counter, the low 4 bits store the backoff exponent.
447 : : * On a specialization failure, the backoff exponent is incremented and the
448 : : * counter set to (2**backoff - 1).
449 : : * Backoff == 6 -> starting counter == 63, backoff == 10 -> starting counter == 1023.
450 : : */
451 : :
452 : : /* With a 16-bit counter, we have 12 bits for the counter value, and 4 bits for the backoff */
453 : : #define ADAPTIVE_BACKOFF_BITS 4
454 : : /* The initial counter value is 31 == 2**ADAPTIVE_BACKOFF_START - 1 */
455 : : #define ADAPTIVE_BACKOFF_START 5
456 : :
457 : : #define MAX_BACKOFF_VALUE (16 - ADAPTIVE_BACKOFF_BITS)
458 : :
459 : :
460 : : static inline uint16_t
461 : 5765500 : adaptive_counter_bits(int value, int backoff) {
462 : 11531000 : return (value << ADAPTIVE_BACKOFF_BITS) |
463 : 5765500 : (backoff & ((1<<ADAPTIVE_BACKOFF_BITS)-1));
464 : : }
465 : :
466 : : static inline uint16_t
467 : 1064635 : adaptive_counter_start(void) {
468 : 1064635 : unsigned int value = (1 << ADAPTIVE_BACKOFF_START) - 1;
469 : 1064635 : return adaptive_counter_bits(value, ADAPTIVE_BACKOFF_START);
470 : : }
471 : :
472 : : static inline uint16_t
473 : 4700865 : adaptive_counter_backoff(uint16_t counter) {
474 : 4700865 : unsigned int backoff = counter & ((1<<ADAPTIVE_BACKOFF_BITS)-1);
475 : 4700865 : backoff++;
476 [ + + ]: 4700865 : if (backoff > MAX_BACKOFF_VALUE) {
477 : 85127 : backoff = MAX_BACKOFF_VALUE;
478 : : }
479 : 4700865 : unsigned int value = (1 << backoff) - 1;
480 : 4700865 : return adaptive_counter_bits(value, backoff);
481 : : }
482 : :
483 : :
484 : : /* Line array cache for tracing */
485 : :
486 : : extern int _PyCode_CreateLineArray(PyCodeObject *co);
487 : :
488 : : static inline int
489 : 7410556 : _PyCode_InitLineArray(PyCodeObject *co)
490 : : {
491 [ + + ]: 7410556 : if (co->_co_linearray) {
492 : 7407488 : return 0;
493 : : }
494 : 3068 : return _PyCode_CreateLineArray(co);
495 : : }
496 : :
497 : : static inline int
498 : 13175624 : _PyCode_LineNumberFromArray(PyCodeObject *co, int index)
499 : : {
500 : : assert(co->_co_linearray != NULL);
501 : : assert(index >= 0);
502 : : assert(index < Py_SIZE(co));
503 [ + + ]: 13175624 : if (co->_co_linearray_entry_size == 2) {
504 : 13175543 : return ((int16_t *)co->_co_linearray)[index];
505 : : }
506 : : else {
507 : : assert(co->_co_linearray_entry_size == 4);
508 : 81 : return ((int32_t *)co->_co_linearray)[index];
509 : : }
510 : : }
511 : :
512 : :
513 : : #ifdef __cplusplus
514 : : }
515 : : #endif
516 : : #endif /* !Py_INTERNAL_CODE_H */
|