FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
cpython/Include/internal/pycore_code.h at main · python/cpython · GitHub
Uh oh!
There was an error while loading.
Please reload this page
.
python
/
cpython
Public
Uh oh!
There was an error while loading.
Please reload this page
.
Notifications
You must be signed in to change notification settings
Fork
35.3k
Star
74.9k
Code
Issues
5k+
Pull requests
2.6k
Actions
Projects
Security and quality
0
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
cpython
/
Include
/
internal
/
pycore_code.h
Copy path
More file actions
More file actions
Latest commit
History
History
History
706 lines (575 loc) · 22.5 KB
Breadcrumbs
cpython
/
Include
/
internal
/
pycore_code.h
Copy path
File metadata and controls
706 lines (575 loc) · 22.5 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
#ifndef
Py_INTERNAL_CODE_H
#define
Py_INTERNAL_CODE_H
#ifdef
__cplusplus
extern
"C"
{
#endif
#ifndef
Py_BUILD_CORE
# error
"this header requires Py_BUILD_CORE define"
#endif
#include
"pycore_backoff.h"
// _Py_BackoffCounter
#include
"pycore_structs.h"
// _Py_CODEUNIT
#include
"pycore_tstate.h"
// _PyThreadStateImpl
#define
_PyCode_CODE
(
CO
) _Py_RVALUE((_Py_CODEUNIT *)(CO)->co_code_adaptive)
#define
_PyCode_NBYTES
(
CO
) (Py_SIZE(CO) * (Py_ssize_t)sizeof(_Py_CODEUNIT))
/* These macros only remain defined for compatibility. */
#define
_Py_OPCODE
(
word
) ((word).op.code)
#define
_Py_OPARG
(
word
) ((word).op.arg)
static
inline
_Py_CODEUNIT
_py_make_codeunit
(
uint8_t
opcode
,
uint8_t
oparg
)
{
// No designated initialisers because of C++ compat
_Py_CODEUNIT
word
;
word
.
op
.
code
=
opcode
;
word
.
op
.
arg
=
oparg
;
return
word
;
}
static
inline
void
_py_set_opcode
(
_Py_CODEUNIT
*
word
,
uint8_t
opcode
)
{
word
->
op
.
code
=
opcode
;
}
#define
_Py_MAKE_CODEUNIT
(
opcode
,
oparg
) _py_make_codeunit((opcode), (oparg))
#define
_Py_SET_OPCODE
(
word
,
opcode
) _py_set_opcode(&(word), (opcode))
// We hide some of the newer PyCodeObject fields behind macros.
// This helps with backporting certain changes to 3.12.
#define
_PyCode_HAS_EXECUTORS
(
CODE
) \
(CODE->co_executors != NULL)
#define
_PyCode_HAS_INSTRUMENTATION
(
CODE
) \
(CODE->_co_instrumentation_version > 0)
extern
PyStatus
_PyCode_Init
(
PyInterpreterState
*
interp
);
extern
void
_PyCode_Fini
(
PyInterpreterState
*
interp
);
/* PEP 659
* Specialization and quickening structs and helper functions
*/
// Inline caches. If you change the number of cache entries for an instruction,
// you must *also* update the number of cache entries in Lib/opcode.py and bump
// the magic number in Lib/importlib/_bootstrap_external.py!
#define
CACHE_ENTRIES
(
cache
) (sizeof(cache)/sizeof(_Py_CODEUNIT))
typedef
struct
{
_Py_BackoffCounter
counter
;
uint16_t
module_keys_version
;
uint16_t
builtin_keys_version
;
uint16_t
index
;
}
_PyLoadGlobalCache
;
#define
INLINE_CACHE_ENTRIES_LOAD_GLOBAL
CACHE_ENTRIES(_PyLoadGlobalCache)
typedef
struct
{
_Py_BackoffCounter
counter
;
uint16_t
external_cache
[
4
];
}
_PyBinaryOpCache
;
#define
INLINE_CACHE_ENTRIES_BINARY_OP
CACHE_ENTRIES(_PyBinaryOpCache)
typedef
struct
{
_Py_BackoffCounter
counter
;
}
_PyUnpackSequenceCache
;
#define
INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE
\
CACHE_ENTRIES(_PyUnpackSequenceCache)
typedef
struct
{
_Py_BackoffCounter
counter
;
}
_PyCompareOpCache
;
#define
INLINE_CACHE_ENTRIES_COMPARE_OP
CACHE_ENTRIES(_PyCompareOpCache)
typedef
struct
{
_Py_BackoffCounter
counter
;
}
_PySuperAttrCache
;
#define
INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR
CACHE_ENTRIES(_PySuperAttrCache)
typedef
struct
{
_Py_BackoffCounter
counter
;
uint16_t
version
[
2
];
uint16_t
index
;
}
_PyAttrCache
;
typedef
struct
{
_Py_BackoffCounter
counter
;
uint16_t
type_version
[
2
];
union
{
uint16_t
keys_version
[
2
];
uint16_t
dict_offset
;
};
uint16_t
descr
[
4
];
}
_PyLoadMethodCache
;
// MUST be the max(_PyAttrCache, _PyLoadMethodCache)
#define
INLINE_CACHE_ENTRIES_LOAD_ATTR
CACHE_ENTRIES(_PyLoadMethodCache)
#define
INLINE_CACHE_ENTRIES_STORE_ATTR
CACHE_ENTRIES(_PyAttrCache)
typedef
struct
{
_Py_BackoffCounter
counter
;
uint16_t
func_version
[
2
];
}
_PyCallCache
;
#define
INLINE_CACHE_ENTRIES_CALL
CACHE_ENTRIES(_PyCallCache)
#define
INLINE_CACHE_ENTRIES_CALL_KW
CACHE_ENTRIES(_PyCallCache)
typedef
struct
{
_Py_BackoffCounter
counter
;
}
_PyStoreSubscrCache
;
#define
INLINE_CACHE_ENTRIES_STORE_SUBSCR
CACHE_ENTRIES(_PyStoreSubscrCache)
typedef
struct
{
_Py_BackoffCounter
counter
;
}
_PyForIterCache
;
#define
INLINE_CACHE_ENTRIES_FOR_ITER
CACHE_ENTRIES(_PyForIterCache)
typedef
struct
{
_Py_BackoffCounter
counter
;
}
_PyGetIterCache
;
#define
INLINE_CACHE_ENTRIES_GET_ITER
CACHE_ENTRIES(_PyGetIterCache)
typedef
struct
{
_Py_BackoffCounter
counter
;
}
_PySendCache
;
#define
INLINE_CACHE_ENTRIES_SEND
CACHE_ENTRIES(_PySendCache)
typedef
struct
{
_Py_BackoffCounter
counter
;
uint16_t
version
[
2
];
}
_PyToBoolCache
;
#define
INLINE_CACHE_ENTRIES_TO_BOOL
CACHE_ENTRIES(_PyToBoolCache)
typedef
struct
{
_Py_BackoffCounter
counter
;
}
_PyContainsOpCache
;
#define
INLINE_CACHE_ENTRIES_CONTAINS_OP
CACHE_ENTRIES(_PyContainsOpCache)
typedef
struct
{
_Py_BackoffCounter
counter
;
}
_PyCallFunctionExCache
;
#define
INLINE_CACHE_ENTRIES_CALL_FUNCTION_EX
CACHE_ENTRIES(_PyCallFunctionExCache)
/* "Locals plus" for a code object is the set of locals + cell vars +
* free vars. This relates to variable names as well as offsets into
* the "fast locals" storage array of execution frames. The compiler
* builds the list of names, their offsets, and the corresponding
* kind of local.
*
* Those kinds represent the source of the initial value and the
* variable's scope (as related to closures). A "local" is an
* argument or other variable defined in the current scope. A "free"
* variable is one that is defined in an outer scope and comes from
* the function's closure. A "cell" variable is a local that escapes
* into an inner function as part of a closure, and thus must be
* wrapped in a cell. Any "local" can also be a "cell", but the
* "free" kind is mutually exclusive with both.
*/
// Note that these all fit within a byte, as do combinations.
#define
CO_FAST_ARG_POS
(0x02) // pos-only, pos-or-kw, varargs
#define
CO_FAST_ARG_KW
(0x04) // kw-only, pos-or-kw, varkwargs
#define
CO_FAST_ARG_VAR
(0x08) // varargs, varkwargs
#define
CO_FAST_ARG
(CO_FAST_ARG_POS | CO_FAST_ARG_KW | CO_FAST_ARG_VAR)
#define
CO_FAST_HIDDEN
(0x10)
#define
CO_FAST_LOCAL
(0x20)
#define
CO_FAST_CELL
(0x40)
#define
CO_FAST_FREE
(0x80)
typedef
unsigned
char
_PyLocals_Kind
;
static
inline
_PyLocals_Kind
_PyLocals_GetKind
(
PyObject
*
kinds
,
int
i
)
{
assert
(
PyBytes_Check
(
kinds
));
assert
(
0
<=
i
&&
i
<
PyBytes_GET_SIZE
(
kinds
));
const
char
*
ptr
=
PyBytes_AS_STRING
(
kinds
);
return
(
_PyLocals_Kind
)(
ptr
[
i
]);
}
static
inline
void
_PyLocals_SetKind
(
PyObject
*
kinds
,
int
i
,
_PyLocals_Kind
kind
)
{
assert
(
PyBytes_Check
(
kinds
));
assert
(
0
<=
i
&&
i
<
PyBytes_GET_SIZE
(
kinds
));
char
*
ptr
=
PyBytes_AS_STRING
(
kinds
);
ptr
[
i
]
=
(
char
)
kind
;
}
struct
_PyCodeConstructor
{
/* metadata */
PyObject
*
filename
;
PyObject
*
name
;
PyObject
*
qualname
;
int
flags
;
/* the code */
PyObject
*
code
;
int
firstlineno
;
PyObject
*
linetable
;
/* used by the code */
PyObject
*
consts
;
PyObject
*
names
;
/* mapping frame offsets to information */
PyObject
*
localsplusnames
;
// Tuple of strings
PyObject
*
localspluskinds
;
// Bytes object, one byte per variable
/* args (within varnames) */
int
argcount
;
int
posonlyargcount
;
// XXX Replace argcount with posorkwargcount (argcount - posonlyargcount).
int
kwonlyargcount
;
/* needed to create the frame */
int
stacksize
;
/* used by the eval loop */
PyObject
*
exceptiontable
;
};
// Using an "arguments struct" like this is helpful for maintainability
// in a case such as this with many parameters. It does bear a risk:
// if the struct changes and callers are not updated properly then the
// compiler will not catch problems (like a missing argument). This can
// cause hard-to-debug problems. The risk is mitigated by the use of
// check_code() in codeobject.c. However, we may decide to switch
// back to a regular function signature. Regardless, this approach
// wouldn't be appropriate if this weren't a strictly internal API.
// (See the comments in https://github.com/python/cpython/pull/26258.)
extern
int
_PyCode_Validate
(
struct
_PyCodeConstructor
*
);
extern
PyCodeObject
*
_PyCode_New
(
struct
_PyCodeConstructor
*
);
/* Private API */
/* Getters for internal PyCodeObject data. */
extern
PyObject
*
_PyCode_GetVarnames
(
PyCodeObject
*
);
extern
PyObject
*
_PyCode_GetCellvars
(
PyCodeObject
*
);
extern
PyObject
*
_PyCode_GetFreevars
(
PyCodeObject
*
);
extern
PyObject
*
_PyCode_GetCode
(
PyCodeObject
*
);
/** API for initializing the line number tables. */
PyAPI_FUNC
(
int
)
_PyCode_InitAddressRange
(
PyCodeObject
*
co
,
PyCodeAddressRange
*
bounds
);
/** Out of process API for initializing the location table. */
extern
void
_PyLineTable_InitAddressRange
(
const
char
*
linetable
,
Py_ssize_t
length
,
int
firstlineno
,
PyCodeAddressRange
*
range
);
/** API for traversing the line number table. */
PyAPI_FUNC
(
int
)
_PyLineTable_NextAddressRange
(
PyCodeAddressRange
*
range
);
extern
int
_PyLineTable_PreviousAddressRange
(
PyCodeAddressRange
*
range
);
// Similar to PyCode_Addr2Line(), but return -1 if the code object is invalid
// and can be called without an attached tstate. Used by dump_frame() in
// Python/traceback.c. The function uses heuristics to detect freed memory,
// it's not 100% reliable.
extern
int
_PyCode_SafeAddr2Line
(
PyCodeObject
*
co
,
int
addr
);
/** API for executors */
extern
void
_PyCode_Clear_Executors
(
PyCodeObject
*
code
);
#define
ENABLE_SPECIALIZATION
1
/* Specialization functions, these are exported only for other re-generated
* interpreters to call */
PyAPI_FUNC
(
void
)
_Py_Specialize_LoadSuperAttr
(
_PyStackRef
global_super
,
_PyStackRef
cls
,
_Py_CODEUNIT
*
instr
,
int
load_method
);
PyAPI_FUNC
(
void
)
_Py_Specialize_LoadAttr
(
_PyStackRef
owner
,
_Py_CODEUNIT
*
instr
,
PyObject
*
name
);
PyAPI_FUNC
(
void
)
_Py_Specialize_StoreAttr
(
_PyStackRef
owner
,
_Py_CODEUNIT
*
instr
,
PyObject
*
name
);
PyAPI_FUNC
(
void
)
_Py_Specialize_LoadGlobal
(
PyObject
*
globals
,
PyObject
*
builtins
,
_Py_CODEUNIT
*
instr
,
PyObject
*
name
);
PyAPI_FUNC
(
void
)
_Py_Specialize_StoreSubscr
(
_PyStackRef
container
,
_PyStackRef
sub
,
_Py_CODEUNIT
*
instr
);
PyAPI_FUNC
(
void
)
_Py_Specialize_Call
(
_PyStackRef
callable
,
_PyStackRef
self_or_null
,
_Py_CODEUNIT
*
instr
,
int
nargs
);
PyAPI_FUNC
(
void
)
_Py_Specialize_CallKw
(
_PyStackRef
callable
,
_Py_CODEUNIT
*
instr
,
int
nargs
);
PyAPI_FUNC
(
void
)
_Py_Specialize_BinaryOp
(
_PyStackRef
lhs
,
_PyStackRef
rhs
,
_Py_CODEUNIT
*
instr
,
int
oparg
,
_PyStackRef
*
locals
);
PyAPI_FUNC
(
void
)
_Py_Specialize_CompareOp
(
_PyStackRef
lhs
,
_PyStackRef
rhs
,
_Py_CODEUNIT
*
instr
,
int
oparg
);
PyAPI_FUNC
(
void
)
_Py_Specialize_UnpackSequence
(
_PyStackRef
seq
,
_Py_CODEUNIT
*
instr
,
int
oparg
);
PyAPI_FUNC
(
void
)
_Py_Specialize_ForIter
(
_PyStackRef
iter
,
_PyStackRef
null_or_index
,
_Py_CODEUNIT
*
instr
,
int
oparg
);
PyAPI_FUNC
(
void
)
_Py_Specialize_Send
(
_PyStackRef
receiver
,
_Py_CODEUNIT
*
instr
);
PyAPI_FUNC
(
void
)
_Py_Specialize_ToBool
(
_PyStackRef
value
,
_Py_CODEUNIT
*
instr
);
PyAPI_FUNC
(
void
)
_Py_Specialize_ContainsOp
(
_PyStackRef
value
,
_Py_CODEUNIT
*
instr
);
PyAPI_FUNC
(
void
)
_Py_GatherStats_GetIter
(
_PyStackRef
iterable
);
PyAPI_FUNC
(
void
)
_Py_Specialize_CallFunctionEx
(
_PyStackRef
func_st
,
_Py_CODEUNIT
*
instr
);
PyAPI_FUNC
(
void
)
_Py_Specialize_Resume
(
_Py_CODEUNIT
*
instr
,
PyThreadState
*
tstate
,
_PyInterpreterFrame
*
frame
);
PyAPI_FUNC
(
void
)
_Py_Specialize_GetIter
(
_PyStackRef
iterable
,
_Py_CODEUNIT
*
instr
);
// Utility functions for reading/writing 32/64-bit values in the inline caches.
// Great care should be taken to ensure that these functions remain correct and
// performant! They should compile to just "move" instructions on all supported
// compilers and platforms.
// We use memcpy to let the C compiler handle unaligned accesses and endianness
// issues for us. It also seems to produce better code than manual copying for
// most compilers (see https://blog.regehr.org/archives/959 for more info).
static
inline
void
write_u32
(
uint16_t
*
p
,
uint32_t
val
)
{
memcpy
(
p
,
&
val
,
sizeof
(
val
));
}
static
inline
void
write_u64
(
uint16_t
*
p
,
uint64_t
val
)
{
memcpy
(
p
,
&
val
,
sizeof
(
val
));
}
static
inline
void
write_ptr
(
uint16_t
*
p
,
void
*
val
)
{
memcpy
(
p
,
&
val
,
sizeof
(
val
));
}
static
inline
uint16_t
read_u16
(
uint16_t
*
p
)
{
return
*
p
;
}
static
inline
uint32_t
read_u32
(
uint16_t
*
p
)
{
uint32_t
val
;
memcpy
(
&
val
,
p
,
sizeof
(
val
));
return
val
;
}
static
inline
uint64_t
read_u64
(
uint16_t
*
p
)
{
uint64_t
val
;
memcpy
(
&
val
,
p
,
sizeof
(
val
));
return
val
;
}
static
inline
PyObject
*
read_obj
(
uint16_t
*
p
)
{
PyObject
*
val
;
memcpy
(
&
val
,
p
,
sizeof
(
val
));
return
val
;
}
/* See InternalDocs/exception_handling.md for details.
*/
static
inline
unsigned
char
*
parse_varint
(
unsigned
char
*
p
,
int
*
result
) {
int
val
=
p
[
0
]
&
63
;
while
(
p
[
0
]
&
64
) {
p
++
;
val
=
(
val
<<
6
) | (
p
[
0
]
&
63
);
}
*
result
=
val
;
return
p
+
1
;
}
static
inline
int
write_varint
(
uint8_t
*
ptr
,
unsigned
int
val
)
{
int
written
=
1
;
while
(
val
>=
64
) {
*
ptr
++
=
64
| (
val
&
63
);
val
>>=
6
;
written
++
;
}
*
ptr
=
(
uint8_t
)
val
;
return
written
;
}
static
inline
int
write_signed_varint
(
uint8_t
*
ptr
,
int
val
)
{
unsigned
int
uval
;
if
(
val
<
0
) {
// (unsigned int)(-val) has an undefined behavior for INT_MIN
uval
=
((
0
-
(
unsigned
int
)
val
) <<
1
) |
1
;
}
else
{
uval
=
(
unsigned
int
)
val
<<
1
;
}
return
write_varint
(
ptr
,
uval
);
}
static
inline
int
write_location_entry_start
(
uint8_t
*
ptr
,
int
code
,
int
length
)
{
assert
((
code
&
15
)
==
code
);
*
ptr
=
128
| (
uint8_t
)(
code
<<
3
) | (
uint8_t
)(
length
-
1
);
return
1
;
}
/** Counters
* The first 16-bit value in each inline cache is a counter.
*
* When counting executions until the next specialization attempt,
* exponential backoff is used to reduce the number of specialization failures.
* See pycore_backoff.h for more details.
* On a specialization failure, the backoff counter is restarted.
*/
// A value of 1 means that we attempt to specialize the *second* time each
// instruction is executed. Executing twice is a much better indicator of
// "hotness" than executing once, but additional warmup delays only prevent
// specialization. Most types stabilize by the second execution, too:
#define
ADAPTIVE_WARMUP_VALUE
1
#define
ADAPTIVE_WARMUP_BACKOFF
1
// A value of 52 means that we attempt to re-specialize after 53 misses (a prime
// number, useful for avoiding artifacts if every nth value is a different type
// or something). Setting the backoff to 0 means that the counter is reset to
// the same state as a warming-up instruction (value == 1, backoff == 1) after
// deoptimization. This isn't strictly necessary, but it is bit easier to reason
// about when thinking about the opcode transitions as a state machine:
#define
ADAPTIVE_COOLDOWN_VALUE
52
#define
ADAPTIVE_COOLDOWN_BACKOFF
0
// Can't assert this in pycore_backoff.h because of header order dependencies
#if
JUMP_BACKWARD_INITIAL_VALUE
<=
ADAPTIVE_COOLDOWN_VALUE
# error
"JIT threshold value should be larger than adaptive cooldown value"
#endif
#if
SIDE_EXIT_INITIAL_VALUE
<=
ADAPTIVE_COOLDOWN_VALUE
# error
"Cold exit value should be larger than adaptive cooldown value"
#endif
static
inline
_Py_BackoffCounter
adaptive_counter_bits
(
uint16_t
value
,
uint16_t
backoff
) {
return
make_backoff_counter
(
value
,
backoff
);
}
static
inline
_Py_BackoffCounter
adaptive_counter_warmup
(
void
) {
return
adaptive_counter_bits
(
ADAPTIVE_WARMUP_VALUE
,
ADAPTIVE_WARMUP_BACKOFF
);
}
static
inline
_Py_BackoffCounter
adaptive_counter_cooldown
(
void
) {
return
adaptive_counter_bits
(
ADAPTIVE_COOLDOWN_VALUE
,
ADAPTIVE_COOLDOWN_BACKOFF
);
}
static
inline
_Py_BackoffCounter
adaptive_counter_backoff
(
_Py_BackoffCounter
counter
) {
return
restart_backoff_counter
(
counter
);
}
/* Specialization Extensions */
/* callbacks for an external specialization */
typedef
int
(
*
binaryopguardfunc
)(
PyObject
*
lhs
,
PyObject
*
rhs
);
typedef
PyObject
*
(
*
binaryopactionfunc
)(
PyObject
*
lhs
,
PyObject
*
rhs
);
typedef
struct
{
int
oparg
;
binaryopguardfunc
guard
;
binaryopactionfunc
action
;
/* Static type of the result, or NULL if unknown. Used by the tier 2
optimizer to propagate type information through _BINARY_OP_EXTEND. */
PyTypeObject
*
result_type
;
/* Nonzero iff `action` always returns a freshly allocated object (not
aliased to either operand). Used by the tier 2 optimizer to enable
inplace follow-up ops. */
int
result_unique
;
/* Expected types of the left and right operands. Used by the tier 2
optimizer to eliminate _GUARD_BINARY_OP_EXTEND when the operand
types are already known. NULL means unknown/don't eliminate. */
PyTypeObject
*
lhs_type
;
PyTypeObject
*
rhs_type
;
}
_PyBinaryOpSpecializationDescr
;
/* Comparison bit masks. */
/* Note this evaluates its arguments twice each */
#define
COMPARISON_BIT
(
x
,
y
) (1 << (2 * ((x) >= (y)) + ((x) <= (y))))
/*
* The following bits are chosen so that the value of
* COMPARSION_BIT(left, right)
* masked by the values below will be non-zero if the
* comparison is true, and zero if it is false */
/* This is for values that are unordered, ie. NaN, not types that are unordered, e.g. sets */
#define
COMPARISON_UNORDERED
1
#define
COMPARISON_LESS_THAN
2
#define
COMPARISON_GREATER_THAN
4
#define
COMPARISON_EQUALS
8
#define
COMPARISON_NOT_EQUALS
(COMPARISON_UNORDERED | COMPARISON_LESS_THAN | COMPARISON_GREATER_THAN)
PyAPI_FUNC
(
int
)
_Py_Instrument
(
PyCodeObject
*
co
,
PyInterpreterState
*
interp
);
// Export for '_testinternalcapi' shared extension
PyAPI_FUNC
(
_Py_CODEUNIT
)
_Py_GetBaseCodeUnit
(
PyCodeObject
*
code
,
int
offset
);
extern
int
_PyInstruction_GetLength
(
PyCodeObject
*
code
,
int
offset
);
extern
PyObject
*
_PyInstrumentation_BranchesIterator
(
PyCodeObject
*
code
);
struct
_PyCode8
_PyCode_DEF
(
8
);
PyAPI_DATA
(
const
struct
_PyCode8
)
_Py_InitCleanup
;
#ifdef
Py_GIL_DISABLED
static
inline
_PyCodeArray
*
_PyCode_GetTLBCArray
(
PyCodeObject
*
co
)
{
return
_Py_STATIC_CAST
(
_PyCodeArray
*
,
_Py_atomic_load_ptr_acquire
(
&
co
->
co_tlbc
));
}
// Return a pointer to the thread-local bytecode for the current thread, if it
// exists.
static
inline
_Py_CODEUNIT
*
_PyCode_GetTLBCFast
(
PyThreadState
*
tstate
,
PyCodeObject
*
co
)
{
_PyCodeArray
*
code
=
_PyCode_GetTLBCArray
(
co
);
int32_t
idx
=
((
_PyThreadStateImpl
*
)
tstate
)
->
tlbc_index
;
if
(
idx
<
code
->
size
&&
code
->
entries
[
idx
]
!=
NULL
) {
return
(
_Py_CODEUNIT
*
)
code
->
entries
[
idx
];
}
return
NULL
;
}
// Return a pointer to the thread-local bytecode for the current thread,
// creating it if necessary.
PyAPI_FUNC
(
_Py_CODEUNIT
*
)
_PyCode_GetTLBC
(
PyCodeObject
*
co
);
// Reserve an index for the current thread into thread-local bytecode
// arrays
//
// Returns the reserved index or -1 on error.
extern
int32_t
_Py_ReserveTLBCIndex
(
PyInterpreterState
*
interp
);
// Release an index returned by _Py_ReserveTLBCIndex() that was never stored
// in a PyThreadState.
extern
void
_Py_UnreserveTLBCIndex
(
PyInterpreterState
*
interp
,
int32_t
index
);
// Release the current thread's index into thread-local bytecode arrays
extern
void
_Py_ClearTLBCIndex
(
_PyThreadStateImpl
*
tstate
);
// Free all TLBC copies not associated with live threads.
//
// Returns 0 on success or -1 on error.
extern
int
_Py_ClearUnusedTLBC
(
PyInterpreterState
*
interp
);
#endif
typedef
struct
{
int
total
;
struct
co_locals_counts
{
int
total
;
struct
{
int
total
;
int
numposonly
;
int
numposorkw
;
int
numkwonly
;
int
varargs
;
int
varkwargs
;
}
args
;
int
numpure
;
struct
{
int
total
;
// numargs does not contribute to locals.total.
int
numargs
;
int
numothers
;
}
cells
;
struct
{
int
total
;
int
numpure
;
int
numcells
;
}
hidden
;
}
locals
;
int
numfree
;
// nonlocal
struct
co_unbound_counts
{
int
total
;
struct
{
int
total
;
int
numglobal
;
int
numbuiltin
;
int
numunknown
;
}
globals
;
int
numattrs
;
int
numunknown
;
}
unbound
;
}
_PyCode_var_counts_t
;
PyAPI_FUNC
(
void
)
_PyCode_GetVarCounts
(
PyCodeObject
*
,
_PyCode_var_counts_t
*
);
PyAPI_FUNC
(
int
)
_PyCode_SetUnboundVarCounts
(
PyThreadState
*
,
PyCodeObject
*
,
_PyCode_var_counts_t
*
,
PyObject
*
globalnames
,
PyObject
*
attrnames
,
PyObject
*
globalsns
,
PyObject
*
builtinsns
);
/* "Stateless" code is a function or code object which does not rely on
* external state or internal state. It may rely on arguments and
* builtins, but not globals or a closure. Thus it does not rely
* on __globals__ or __closure__, and a stateless function
* is equivalent to its code object.
*
* Stateless code also does not keep any persistent state
* of its own, so it can't have any executors, monitoring,
* instrumentation, or "extras" (i.e. co_extra).
*
* Stateless code may create nested functions, including closures.
* However, nested functions must themselves be stateless, except they
* *can* close on the enclosing locals.
*
* Stateless code may return any value, including nested functions and closures.
*
* Stateless code that takes no arguments and doesn't return anything
* may be treated like a script.
*
* We consider stateless code to be "portable" if it does not return
* any object that holds a reference to any of the code's locals. Thus
* generators and coroutines are not portable. Likewise a function
* that returns a closure is not portable. The concept of
* portability is useful in cases where the code is run
* in a different execution context than where
* the return value will be used. */
PyAPI_FUNC
(
int
)
_PyCode_CheckNoInternalState
(
PyCodeObject
*
,
const
char
*
*
);
PyAPI_FUNC
(
int
)
_PyCode_CheckNoExternalState
(
PyCodeObject
*
,
_PyCode_var_counts_t
*
,
const
char
*
*
);
PyAPI_FUNC
(
int
)
_PyCode_VerifyStateless
(
PyThreadState
*
,
PyCodeObject
*
,
PyObject
*
globalnames
,
PyObject
*
globalsns
,
PyObject
*
builtinsns
);
PyAPI_FUNC
(
int
)
_PyCode_CheckPureFunction
(
PyCodeObject
*
,
const
char
*
*
);
PyAPI_FUNC
(
int
)
_PyCode_ReturnsOnlyNone
(
PyCodeObject
*
);
/* Create a comparable key used to compare constants taking in account the
* object type. It is used to make sure types are not coerced (e.g., float and
* complex) _and_ to distinguish 0.0 from -0.0 e.g. on IEEE platforms
*
* Return (type(obj), obj, ...): a tuple with variable size (at least 2 items)
* depending on the type and the value. The type is the first item to not
* compare bytes and str which can raise a BytesWarning exception. */
extern
PyObject
*
_PyCode_ConstantKey
(
PyObject
*
obj
);
#ifdef
__cplusplus
}
#endif
#endif
/* !Py_INTERNAL_CODE_H */
Back
|
FazBrowse Home
|
New Git URL