Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
allendowney
GitHub Repository: allendowney/cpython
Path: blob/main/Include/internal/pycore_code.h
12 views
1
#ifndef Py_INTERNAL_CODE_H
2
#define Py_INTERNAL_CODE_H
3
#ifdef __cplusplus
4
extern "C" {
5
#endif
6
7
#define CODE_MAX_WATCHERS 8
8
9
/* PEP 659
10
* Specialization and quickening structs and helper functions
11
*/
12
13
14
// Inline caches. If you change the number of cache entries for an instruction,
15
// you must *also* update the number of cache entries in Lib/opcode.py and bump
16
// the magic number in Lib/importlib/_bootstrap_external.py!
17
18
#define CACHE_ENTRIES(cache) (sizeof(cache)/sizeof(_Py_CODEUNIT))
19
20
typedef struct {
21
uint16_t counter;
22
uint16_t index;
23
uint16_t module_keys_version;
24
uint16_t builtin_keys_version;
25
} _PyLoadGlobalCache;
26
27
#define INLINE_CACHE_ENTRIES_LOAD_GLOBAL CACHE_ENTRIES(_PyLoadGlobalCache)
28
29
typedef struct {
30
uint16_t counter;
31
} _PyBinaryOpCache;
32
33
#define INLINE_CACHE_ENTRIES_BINARY_OP CACHE_ENTRIES(_PyBinaryOpCache)
34
35
typedef struct {
36
uint16_t counter;
37
} _PyUnpackSequenceCache;
38
39
#define INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE \
40
CACHE_ENTRIES(_PyUnpackSequenceCache)
41
42
typedef struct {
43
uint16_t counter;
44
} _PyCompareOpCache;
45
46
#define INLINE_CACHE_ENTRIES_COMPARE_OP CACHE_ENTRIES(_PyCompareOpCache)
47
48
typedef struct {
49
uint16_t counter;
50
} _PyBinarySubscrCache;
51
52
#define INLINE_CACHE_ENTRIES_BINARY_SUBSCR CACHE_ENTRIES(_PyBinarySubscrCache)
53
54
typedef struct {
55
uint16_t counter;
56
} _PySuperAttrCache;
57
58
#define INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR CACHE_ENTRIES(_PySuperAttrCache)
59
60
typedef struct {
61
uint16_t counter;
62
uint16_t version[2];
63
uint16_t index;
64
} _PyAttrCache;
65
66
typedef struct {
67
uint16_t counter;
68
uint16_t type_version[2];
69
uint16_t keys_version[2];
70
uint16_t descr[4];
71
} _PyLoadMethodCache;
72
73
74
// MUST be the max(_PyAttrCache, _PyLoadMethodCache)
75
#define INLINE_CACHE_ENTRIES_LOAD_ATTR CACHE_ENTRIES(_PyLoadMethodCache)
76
77
#define INLINE_CACHE_ENTRIES_STORE_ATTR CACHE_ENTRIES(_PyAttrCache)
78
79
typedef struct {
80
uint16_t counter;
81
uint16_t func_version[2];
82
} _PyCallCache;
83
84
#define INLINE_CACHE_ENTRIES_CALL CACHE_ENTRIES(_PyCallCache)
85
86
typedef struct {
87
uint16_t counter;
88
} _PyStoreSubscrCache;
89
90
#define INLINE_CACHE_ENTRIES_STORE_SUBSCR CACHE_ENTRIES(_PyStoreSubscrCache)
91
92
typedef struct {
93
uint16_t counter;
94
} _PyForIterCache;
95
96
#define INLINE_CACHE_ENTRIES_FOR_ITER CACHE_ENTRIES(_PyForIterCache)
97
98
typedef struct {
99
uint16_t counter;
100
} _PySendCache;
101
102
#define INLINE_CACHE_ENTRIES_SEND CACHE_ENTRIES(_PySendCache)
103
104
typedef struct {
105
uint16_t counter;
106
uint16_t version[2];
107
} _PyToBoolCache;
108
109
#define INLINE_CACHE_ENTRIES_TO_BOOL CACHE_ENTRIES(_PyToBoolCache)
110
111
// Borrowed references to common callables:
112
struct callable_cache {
113
PyObject *isinstance;
114
PyObject *len;
115
PyObject *list_append;
116
PyObject *object__getattribute__;
117
};
118
119
/* "Locals plus" for a code object is the set of locals + cell vars +
120
* free vars. This relates to variable names as well as offsets into
121
* the "fast locals" storage array of execution frames. The compiler
122
* builds the list of names, their offsets, and the corresponding
123
* kind of local.
124
*
125
* Those kinds represent the source of the initial value and the
126
* variable's scope (as related to closures). A "local" is an
127
* argument or other variable defined in the current scope. A "free"
128
* variable is one that is defined in an outer scope and comes from
129
* the function's closure. A "cell" variable is a local that escapes
130
* into an inner function as part of a closure, and thus must be
131
* wrapped in a cell. Any "local" can also be a "cell", but the
132
* "free" kind is mutually exclusive with both.
133
*/
134
135
// Note that these all fit within a byte, as do combinations.
136
// Later, we will use the smaller numbers to differentiate the different
137
// kinds of locals (e.g. pos-only arg, varkwargs, local-only).
138
#define CO_FAST_HIDDEN 0x10
139
#define CO_FAST_LOCAL 0x20
140
#define CO_FAST_CELL 0x40
141
#define CO_FAST_FREE 0x80
142
143
typedef unsigned char _PyLocals_Kind;
144
145
static inline _PyLocals_Kind
146
_PyLocals_GetKind(PyObject *kinds, int i)
147
{
148
assert(PyBytes_Check(kinds));
149
assert(0 <= i && i < PyBytes_GET_SIZE(kinds));
150
char *ptr = PyBytes_AS_STRING(kinds);
151
return (_PyLocals_Kind)(ptr[i]);
152
}
153
154
static inline void
155
_PyLocals_SetKind(PyObject *kinds, int i, _PyLocals_Kind kind)
156
{
157
assert(PyBytes_Check(kinds));
158
assert(0 <= i && i < PyBytes_GET_SIZE(kinds));
159
char *ptr = PyBytes_AS_STRING(kinds);
160
ptr[i] = (char) kind;
161
}
162
163
164
struct _PyCodeConstructor {
165
/* metadata */
166
PyObject *filename;
167
PyObject *name;
168
PyObject *qualname;
169
int flags;
170
171
/* the code */
172
PyObject *code;
173
int firstlineno;
174
PyObject *linetable;
175
176
/* used by the code */
177
PyObject *consts;
178
PyObject *names;
179
180
/* mapping frame offsets to information */
181
PyObject *localsplusnames; // Tuple of strings
182
PyObject *localspluskinds; // Bytes object, one byte per variable
183
184
/* args (within varnames) */
185
int argcount;
186
int posonlyargcount;
187
// XXX Replace argcount with posorkwargcount (argcount - posonlyargcount).
188
int kwonlyargcount;
189
190
/* needed to create the frame */
191
int stacksize;
192
193
/* used by the eval loop */
194
PyObject *exceptiontable;
195
};
196
197
// Using an "arguments struct" like this is helpful for maintainability
198
// in a case such as this with many parameters. It does bear a risk:
199
// if the struct changes and callers are not updated properly then the
200
// compiler will not catch problems (like a missing argument). This can
201
// cause hard-to-debug problems. The risk is mitigated by the use of
202
// check_code() in codeobject.c. However, we may decide to switch
203
// back to a regular function signature. Regardless, this approach
204
// wouldn't be appropriate if this weren't a strictly internal API.
205
// (See the comments in https://github.com/python/cpython/pull/26258.)
206
PyAPI_FUNC(int) _PyCode_Validate(struct _PyCodeConstructor *);
207
PyAPI_FUNC(PyCodeObject *) _PyCode_New(struct _PyCodeConstructor *);
208
209
210
/* Private API */
211
212
/* Getters for internal PyCodeObject data. */
213
extern PyObject* _PyCode_GetVarnames(PyCodeObject *);
214
extern PyObject* _PyCode_GetCellvars(PyCodeObject *);
215
extern PyObject* _PyCode_GetFreevars(PyCodeObject *);
216
extern PyObject* _PyCode_GetCode(PyCodeObject *);
217
218
/** API for initializing the line number tables. */
219
extern int _PyCode_InitAddressRange(PyCodeObject* co, PyCodeAddressRange *bounds);
220
221
/** Out of process API for initializing the location table. */
222
extern void _PyLineTable_InitAddressRange(
223
const char *linetable,
224
Py_ssize_t length,
225
int firstlineno,
226
PyCodeAddressRange *range);
227
228
/** API for traversing the line number table. */
229
extern int _PyLineTable_NextAddressRange(PyCodeAddressRange *range);
230
extern int _PyLineTable_PreviousAddressRange(PyCodeAddressRange *range);
231
232
/* Specialization functions */
233
234
extern void _Py_Specialize_LoadSuperAttr(PyObject *global_super, PyObject *cls,
235
_Py_CODEUNIT *instr, int load_method);
236
extern void _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr,
237
PyObject *name);
238
extern void _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr,
239
PyObject *name);
240
extern void _Py_Specialize_LoadGlobal(PyObject *globals, PyObject *builtins,
241
_Py_CODEUNIT *instr, PyObject *name);
242
extern void _Py_Specialize_BinarySubscr(PyObject *sub, PyObject *container,
243
_Py_CODEUNIT *instr);
244
extern void _Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub,
245
_Py_CODEUNIT *instr);
246
extern void _Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr,
247
int nargs, PyObject *kwnames);
248
extern void _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
249
int oparg, PyObject **locals);
250
extern void _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs,
251
_Py_CODEUNIT *instr, int oparg);
252
extern void _Py_Specialize_UnpackSequence(PyObject *seq, _Py_CODEUNIT *instr,
253
int oparg);
254
extern void _Py_Specialize_ForIter(PyObject *iter, _Py_CODEUNIT *instr, int oparg);
255
extern void _Py_Specialize_Send(PyObject *receiver, _Py_CODEUNIT *instr);
256
extern void _Py_Specialize_ToBool(PyObject *value, _Py_CODEUNIT *instr);
257
258
/* Finalizer function for static codeobjects used in deepfreeze.py */
259
extern void _PyStaticCode_Fini(PyCodeObject *co);
260
/* Function to intern strings of codeobjects and quicken the bytecode */
261
extern int _PyStaticCode_Init(PyCodeObject *co);
262
263
#ifdef Py_STATS
264
265
266
#define STAT_INC(opname, name) do { if (_py_stats) _py_stats->opcode_stats[opname].specialization.name++; } while (0)
267
#define STAT_DEC(opname, name) do { if (_py_stats) _py_stats->opcode_stats[opname].specialization.name--; } while (0)
268
#define OPCODE_EXE_INC(opname) do { if (_py_stats) _py_stats->opcode_stats[opname].execution_count++; } while (0)
269
#define CALL_STAT_INC(name) do { if (_py_stats) _py_stats->call_stats.name++; } while (0)
270
#define OBJECT_STAT_INC(name) do { if (_py_stats) _py_stats->object_stats.name++; } while (0)
271
#define OBJECT_STAT_INC_COND(name, cond) \
272
do { if (_py_stats && cond) _py_stats->object_stats.name++; } while (0)
273
#define EVAL_CALL_STAT_INC(name) do { if (_py_stats) _py_stats->call_stats.eval_calls[name]++; } while (0)
274
#define EVAL_CALL_STAT_INC_IF_FUNCTION(name, callable) \
275
do { if (_py_stats && PyFunction_Check(callable)) _py_stats->call_stats.eval_calls[name]++; } while (0)
276
277
// Used by the _opcode extension which is built as a shared library
278
PyAPI_FUNC(PyObject*) _Py_GetSpecializationStats(void);
279
280
#else
281
#define STAT_INC(opname, name) ((void)0)
282
#define STAT_DEC(opname, name) ((void)0)
283
#define OPCODE_EXE_INC(opname) ((void)0)
284
#define CALL_STAT_INC(name) ((void)0)
285
#define OBJECT_STAT_INC(name) ((void)0)
286
#define OBJECT_STAT_INC_COND(name, cond) ((void)0)
287
#define EVAL_CALL_STAT_INC(name) ((void)0)
288
#define EVAL_CALL_STAT_INC_IF_FUNCTION(name, callable) ((void)0)
289
#endif // !Py_STATS
290
291
// Utility functions for reading/writing 32/64-bit values in the inline caches.
292
// Great care should be taken to ensure that these functions remain correct and
293
// performant! They should compile to just "move" instructions on all supported
294
// compilers and platforms.
295
296
// We use memcpy to let the C compiler handle unaligned accesses and endianness
297
// issues for us. It also seems to produce better code than manual copying for
298
// most compilers (see https://blog.regehr.org/archives/959 for more info).
299
300
static inline void
301
write_u32(uint16_t *p, uint32_t val)
302
{
303
memcpy(p, &val, sizeof(val));
304
}
305
306
static inline void
307
write_u64(uint16_t *p, uint64_t val)
308
{
309
memcpy(p, &val, sizeof(val));
310
}
311
312
static inline void
313
write_obj(uint16_t *p, PyObject *val)
314
{
315
memcpy(p, &val, sizeof(val));
316
}
317
318
static inline uint16_t
319
read_u16(uint16_t *p)
320
{
321
return *p;
322
}
323
324
static inline uint32_t
325
read_u32(uint16_t *p)
326
{
327
uint32_t val;
328
memcpy(&val, p, sizeof(val));
329
return val;
330
}
331
332
static inline uint64_t
333
read_u64(uint16_t *p)
334
{
335
uint64_t val;
336
memcpy(&val, p, sizeof(val));
337
return val;
338
}
339
340
static inline PyObject *
341
read_obj(uint16_t *p)
342
{
343
PyObject *val;
344
memcpy(&val, p, sizeof(val));
345
return val;
346
}
347
348
/* See Objects/exception_handling_notes.txt for details.
349
*/
350
static inline unsigned char *
351
parse_varint(unsigned char *p, int *result) {
352
int val = p[0] & 63;
353
while (p[0] & 64) {
354
p++;
355
val = (val << 6) | (p[0] & 63);
356
}
357
*result = val;
358
return p+1;
359
}
360
361
static inline int
362
write_varint(uint8_t *ptr, unsigned int val)
363
{
364
int written = 1;
365
while (val >= 64) {
366
*ptr++ = 64 | (val & 63);
367
val >>= 6;
368
written++;
369
}
370
*ptr = val;
371
return written;
372
}
373
374
static inline int
375
write_signed_varint(uint8_t *ptr, int val)
376
{
377
if (val < 0) {
378
val = ((-val)<<1) | 1;
379
}
380
else {
381
val = val << 1;
382
}
383
return write_varint(ptr, val);
384
}
385
386
static inline int
387
write_location_entry_start(uint8_t *ptr, int code, int length)
388
{
389
assert((code & 15) == code);
390
*ptr = 128 | (code << 3) | (length - 1);
391
return 1;
392
}
393
394
395
/** Counters
396
* The first 16-bit value in each inline cache is a counter.
397
* When counting misses, the counter is treated as a simple unsigned value.
398
*
399
* When counting executions until the next specialization attempt,
400
* exponential backoff is used to reduce the number of specialization failures.
401
* The high 12 bits store the counter, the low 4 bits store the backoff exponent.
402
* On a specialization failure, the backoff exponent is incremented and the
403
* counter set to (2**backoff - 1).
404
* Backoff == 6 -> starting counter == 63, backoff == 10 -> starting counter == 1023.
405
*/
406
407
/* With a 16-bit counter, we have 12 bits for the counter value, and 4 bits for the backoff */
408
#define ADAPTIVE_BACKOFF_BITS 4
409
410
// A value of 1 means that we attempt to specialize the *second* time each
411
// instruction is executed. Executing twice is a much better indicator of
412
// "hotness" than executing once, but additional warmup delays only prevent
413
// specialization. Most types stabilize by the second execution, too:
414
#define ADAPTIVE_WARMUP_VALUE 1
415
#define ADAPTIVE_WARMUP_BACKOFF 1
416
417
// A value of 52 means that we attempt to re-specialize after 53 misses (a prime
418
// number, useful for avoiding artifacts if every nth value is a different type
419
// or something). Setting the backoff to 0 means that the counter is reset to
420
// the same state as a warming-up instruction (value == 1, backoff == 1) after
421
// deoptimization. This isn't strictly necessary, but it is bit easier to reason
422
// about when thinking about the opcode transitions as a state machine:
423
#define ADAPTIVE_COOLDOWN_VALUE 52
424
#define ADAPTIVE_COOLDOWN_BACKOFF 0
425
426
#define MAX_BACKOFF_VALUE (16 - ADAPTIVE_BACKOFF_BITS)
427
428
429
static inline uint16_t
430
adaptive_counter_bits(int value, int backoff) {
431
return (value << ADAPTIVE_BACKOFF_BITS) |
432
(backoff & ((1<<ADAPTIVE_BACKOFF_BITS)-1));
433
}
434
435
static inline uint16_t
436
adaptive_counter_warmup(void) {
437
return adaptive_counter_bits(ADAPTIVE_WARMUP_VALUE,
438
ADAPTIVE_WARMUP_BACKOFF);
439
}
440
441
static inline uint16_t
442
adaptive_counter_cooldown(void) {
443
return adaptive_counter_bits(ADAPTIVE_COOLDOWN_VALUE,
444
ADAPTIVE_COOLDOWN_BACKOFF);
445
}
446
447
static inline uint16_t
448
adaptive_counter_backoff(uint16_t counter) {
449
unsigned int backoff = counter & ((1<<ADAPTIVE_BACKOFF_BITS)-1);
450
backoff++;
451
if (backoff > MAX_BACKOFF_VALUE) {
452
backoff = MAX_BACKOFF_VALUE;
453
}
454
unsigned int value = (1 << backoff) - 1;
455
return adaptive_counter_bits(value, backoff);
456
}
457
458
extern uint32_t _Py_next_func_version;
459
460
461
/* Comparison bit masks. */
462
463
/* Note this evaluates its arguments twice each */
464
#define COMPARISON_BIT(x, y) (1 << (2 * ((x) >= (y)) + ((x) <= (y))))
465
466
/*
467
* The following bits are chosen so that the value of
468
* COMPARSION_BIT(left, right)
469
* masked by the values below will be non-zero if the
470
* comparison is true, and zero if it is false */
471
472
/* This is for values that are unordered, ie. NaN, not types that are unordered, e.g. sets */
473
#define COMPARISON_UNORDERED 1
474
475
#define COMPARISON_LESS_THAN 2
476
#define COMPARISON_GREATER_THAN 4
477
#define COMPARISON_EQUALS 8
478
479
#define COMPARISON_NOT_EQUALS (COMPARISON_UNORDERED | COMPARISON_LESS_THAN | COMPARISON_GREATER_THAN)
480
481
extern int _Py_Instrument(PyCodeObject *co, PyInterpreterState *interp);
482
483
extern int _Py_GetBaseOpcode(PyCodeObject *code, int offset);
484
485
extern int _PyInstruction_GetLength(PyCodeObject *code, int offset);
486
487
#ifdef __cplusplus
488
}
489
#endif
490
#endif /* !Py_INTERNAL_CODE_H */
491
492