mirror of
https://github.com/python/cpython.git
synced 2025-08-31 14:07:50 +00:00
bpo-46841: Quicken code in-place (GH-31888)
* Moves the bytecode to the end of the corresponding PyCodeObject, and quickens it in-place. * Removes the almost-always-unused co_varnames, co_freevars, and co_cellvars member caches * _PyOpcode_Deopt is a new mapping from all opcodes to their un-quickened forms. * _PyOpcode_InlineCacheEntries is renamed to _PyOpcode_Caches * _Py_IncrementCountAndMaybeQuicken is renamed to _PyCode_Warmup * _Py_Quicken is renamed to _PyCode_Quicken * _co_quickened is renamed to _co_code_adaptive (and is now a read-only memoryview). * Do not emit unused nonzero opargs anymore in the compiler.
This commit is contained in:
parent
08eb754d84
commit
2bde6827ea
18 changed files with 832 additions and 688 deletions
|
@ -1327,9 +1327,8 @@ eval_frame_handle_pending(PyThreadState *tstate)
|
|||
|
||||
/* Get opcode and oparg from original instructions, not quickened form. */
|
||||
#define TRACING_NEXTOPARG() do { \
|
||||
_Py_CODEUNIT word = ((_Py_CODEUNIT *)PyBytes_AS_STRING(frame->f_code->co_code))[INSTR_OFFSET()]; \
|
||||
opcode = _Py_OPCODE(word); \
|
||||
oparg = _Py_OPARG(word); \
|
||||
NEXTOPARG(); \
|
||||
opcode = _PyOpcode_Deopt[opcode]; \
|
||||
} while (0)
|
||||
|
||||
/* OpCode prediction macros
|
||||
|
@ -1650,9 +1649,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
|
|||
PyCodeObject *co = frame->f_code; \
|
||||
names = co->co_names; \
|
||||
consts = co->co_consts; \
|
||||
first_instr = co->co_firstinstr; \
|
||||
first_instr = _PyCode_CODE(co); \
|
||||
} \
|
||||
assert(frame->f_lasti >= -1); \
|
||||
/* Jump back to the last instruction executed... */ \
|
||||
next_instr = first_instr + frame->f_lasti + 1; \
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame); \
|
||||
/* Set stackdepth to -1. \
|
||||
|
@ -1722,16 +1722,7 @@ handle_eval_breaker:
|
|||
}
|
||||
|
||||
TARGET(RESUME) {
|
||||
int err = _Py_IncrementCountAndMaybeQuicken(frame->f_code);
|
||||
if (err) {
|
||||
if (err < 0) {
|
||||
goto error;
|
||||
}
|
||||
/* Update first_instr and next_instr to point to newly quickened code */
|
||||
int nexti = INSTR_OFFSET();
|
||||
first_instr = frame->f_code->co_firstinstr;
|
||||
next_instr = first_instr + nexti;
|
||||
}
|
||||
_PyCode_Warmup(frame->f_code);
|
||||
JUMP_TO_INSTRUCTION(RESUME_QUICK);
|
||||
}
|
||||
|
||||
|
@ -4067,16 +4058,7 @@ handle_eval_breaker:
|
|||
|
||||
TARGET(JUMP_ABSOLUTE) {
|
||||
PREDICTED(JUMP_ABSOLUTE);
|
||||
int err = _Py_IncrementCountAndMaybeQuicken(frame->f_code);
|
||||
if (err) {
|
||||
if (err < 0) {
|
||||
goto error;
|
||||
}
|
||||
/* Update first_instr and next_instr to point to newly quickened code */
|
||||
int nexti = INSTR_OFFSET();
|
||||
first_instr = frame->f_code->co_firstinstr;
|
||||
next_instr = first_instr + nexti;
|
||||
}
|
||||
_PyCode_Warmup(frame->f_code);
|
||||
JUMP_TO_INSTRUCTION(JUMP_ABSOLUTE_QUICK);
|
||||
}
|
||||
|
||||
|
@ -5425,6 +5407,7 @@ handle_eval_breaker:
|
|||
}
|
||||
|
||||
TARGET(EXTENDED_ARG) {
|
||||
assert(oparg);
|
||||
int oldoparg = oparg;
|
||||
NEXTOPARG();
|
||||
oparg |= oldoparg << 8;
|
||||
|
@ -6739,8 +6722,8 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
|
|||
*/
|
||||
initialize_trace_info(&tstate->trace_info, frame);
|
||||
int entry_point = 0;
|
||||
_Py_CODEUNIT *code = (_Py_CODEUNIT *)PyBytes_AS_STRING(frame->f_code->co_code);
|
||||
while (_Py_OPCODE(code[entry_point]) != RESUME) {
|
||||
_Py_CODEUNIT *code = _PyCode_CODE(frame->f_code);
|
||||
while (_PyOpcode_Deopt[_Py_OPCODE(code[entry_point])] != RESUME) {
|
||||
entry_point++;
|
||||
}
|
||||
int lastline;
|
||||
|
@ -6759,7 +6742,9 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
|
|||
/* Trace backward edges (except in 'yield from') or if line number has changed */
|
||||
int trace = line != lastline ||
|
||||
(frame->f_lasti < instr_prev &&
|
||||
_Py_OPCODE(frame->f_code->co_firstinstr[frame->f_lasti]) != SEND);
|
||||
// SEND has no quickened forms, so no need to use _PyOpcode_Deopt
|
||||
// here:
|
||||
_Py_OPCODE(_PyCode_CODE(frame->f_code)[frame->f_lasti]) != SEND);
|
||||
if (trace) {
|
||||
result = call_trace(func, obj, tstate, frame, PyTrace_LINE, Py_None);
|
||||
}
|
||||
|
|
|
@ -134,9 +134,9 @@ static int
|
|||
instr_size(struct instr *instruction)
|
||||
{
|
||||
int opcode = instruction->i_opcode;
|
||||
int oparg = instruction->i_oparg;
|
||||
int oparg = HAS_ARG(opcode) ? instruction->i_oparg : 0;
|
||||
int extended_args = (0xFFFFFF < oparg) + (0xFFFF < oparg) + (0xFF < oparg);
|
||||
int caches = _PyOpcode_InlineCacheEntries[opcode];
|
||||
int caches = _PyOpcode_Caches[opcode];
|
||||
return extended_args + 1 + caches;
|
||||
}
|
||||
|
||||
|
@ -144,8 +144,8 @@ static void
|
|||
write_instr(_Py_CODEUNIT *codestr, struct instr *instruction, int ilen)
|
||||
{
|
||||
int opcode = instruction->i_opcode;
|
||||
int oparg = instruction->i_oparg;
|
||||
int caches = _PyOpcode_InlineCacheEntries[opcode];
|
||||
int oparg = HAS_ARG(opcode) ? instruction->i_oparg : 0;
|
||||
int caches = _PyOpcode_Caches[opcode];
|
||||
switch (ilen - caches) {
|
||||
case 4:
|
||||
*codestr++ = _Py_MAKECODEUNIT(EXTENDED_ARG, (oparg >> 24) & 0xFF);
|
||||
|
|
|
@ -544,13 +544,18 @@ w_complex_object(PyObject *v, char flag, WFILE *p)
|
|||
}
|
||||
else if (PyCode_Check(v)) {
|
||||
PyCodeObject *co = (PyCodeObject *)v;
|
||||
PyObject *co_code = _PyCode_GetCode(co);
|
||||
if (co_code == NULL) {
|
||||
p->error = WFERR_NOMEMORY;
|
||||
return;
|
||||
}
|
||||
W_TYPE(TYPE_CODE, p);
|
||||
w_long(co->co_argcount, p);
|
||||
w_long(co->co_posonlyargcount, p);
|
||||
w_long(co->co_kwonlyargcount, p);
|
||||
w_long(co->co_stacksize, p);
|
||||
w_long(co->co_flags, p);
|
||||
w_object(co->co_code, p);
|
||||
w_object(co_code, p);
|
||||
w_object(co->co_consts, p);
|
||||
w_object(co->co_names, p);
|
||||
w_object(co->co_localsplusnames, p);
|
||||
|
@ -563,6 +568,7 @@ w_complex_object(PyObject *v, char flag, WFILE *p)
|
|||
w_object(co->co_endlinetable, p);
|
||||
w_object(co->co_columntable, p);
|
||||
w_object(co->co_exceptiontable, p);
|
||||
Py_DECREF(co_code);
|
||||
}
|
||||
else if (PyObject_CheckBuffer(v)) {
|
||||
/* Write unknown bytes-like objects as a bytes object */
|
||||
|
|
72
Python/opcode_targets.h
generated
72
Python/opcode_targets.h
generated
|
@ -3,49 +3,49 @@ static void *opcode_targets[256] = {
|
|||
&&TARGET_POP_TOP,
|
||||
&&TARGET_PUSH_NULL,
|
||||
&&TARGET_BINARY_OP_ADAPTIVE,
|
||||
&&TARGET_BINARY_OP_ADD_INT,
|
||||
&&TARGET_BINARY_OP_ADD_FLOAT,
|
||||
&&TARGET_BINARY_OP_ADD_INT,
|
||||
&&TARGET_BINARY_OP_ADD_UNICODE,
|
||||
&&TARGET_BINARY_OP_INPLACE_ADD_UNICODE,
|
||||
&&TARGET_BINARY_OP_MULTIPLY_INT,
|
||||
&&TARGET_BINARY_OP_MULTIPLY_FLOAT,
|
||||
&&TARGET_NOP,
|
||||
&&TARGET_UNARY_POSITIVE,
|
||||
&&TARGET_UNARY_NEGATIVE,
|
||||
&&TARGET_UNARY_NOT,
|
||||
&&TARGET_BINARY_OP_MULTIPLY_FLOAT,
|
||||
&&TARGET_BINARY_OP_SUBTRACT_INT,
|
||||
&&TARGET_UNARY_INVERT,
|
||||
&&TARGET_BINARY_OP_MULTIPLY_INT,
|
||||
&&TARGET_BINARY_OP_SUBTRACT_FLOAT,
|
||||
&&TARGET_UNARY_INVERT,
|
||||
&&TARGET_BINARY_OP_SUBTRACT_INT,
|
||||
&&TARGET_BINARY_SUBSCR_ADAPTIVE,
|
||||
&&TARGET_BINARY_SUBSCR_DICT,
|
||||
&&TARGET_BINARY_SUBSCR_GETITEM,
|
||||
&&TARGET_BINARY_SUBSCR_LIST_INT,
|
||||
&&TARGET_BINARY_SUBSCR_TUPLE_INT,
|
||||
&&TARGET_CALL_ADAPTIVE,
|
||||
&&TARGET_CALL_PY_EXACT_ARGS,
|
||||
&&TARGET_CALL_PY_WITH_DEFAULTS,
|
||||
&&TARGET_BINARY_SUBSCR,
|
||||
&&TARGET_COMPARE_OP_ADAPTIVE,
|
||||
&&TARGET_COMPARE_OP_FLOAT_JUMP,
|
||||
&&TARGET_COMPARE_OP_INT_JUMP,
|
||||
&&TARGET_COMPARE_OP_STR_JUMP,
|
||||
&&TARGET_BINARY_SUBSCR_ADAPTIVE,
|
||||
&&TARGET_BINARY_SUBSCR_GETITEM,
|
||||
&&TARGET_BINARY_SUBSCR_LIST_INT,
|
||||
&&TARGET_BINARY_SUBSCR_TUPLE_INT,
|
||||
&&TARGET_BINARY_SUBSCR,
|
||||
&&TARGET_BINARY_SUBSCR_DICT,
|
||||
&&TARGET_STORE_SUBSCR_ADAPTIVE,
|
||||
&&TARGET_STORE_SUBSCR_LIST_INT,
|
||||
&&TARGET_STORE_SUBSCR_DICT,
|
||||
&&TARGET_GET_LEN,
|
||||
&&TARGET_MATCH_MAPPING,
|
||||
&&TARGET_MATCH_SEQUENCE,
|
||||
&&TARGET_MATCH_KEYS,
|
||||
&&TARGET_CALL_ADAPTIVE,
|
||||
&&TARGET_PUSH_EXC_INFO,
|
||||
&&TARGET_CALL_PY_EXACT_ARGS,
|
||||
&&TARGET_CALL_PY_WITH_DEFAULTS,
|
||||
&&TARGET_JUMP_ABSOLUTE_QUICK,
|
||||
&&TARGET_PUSH_EXC_INFO,
|
||||
&&TARGET_LOAD_ATTR_ADAPTIVE,
|
||||
&&TARGET_LOAD_ATTR_INSTANCE_VALUE,
|
||||
&&TARGET_LOAD_ATTR_WITH_HINT,
|
||||
&&TARGET_LOAD_ATTR_SLOT,
|
||||
&&TARGET_LOAD_ATTR_MODULE,
|
||||
&&TARGET_LOAD_ATTR_SLOT,
|
||||
&&TARGET_LOAD_ATTR_WITH_HINT,
|
||||
&&TARGET_LOAD_CONST__LOAD_FAST,
|
||||
&&TARGET_LOAD_FAST__LOAD_CONST,
|
||||
&&TARGET_LOAD_FAST__LOAD_FAST,
|
||||
&&TARGET_LOAD_GLOBAL_ADAPTIVE,
|
||||
&&TARGET_LOAD_GLOBAL_MODULE,
|
||||
&&TARGET_LOAD_GLOBAL_BUILTIN,
|
||||
&&TARGET_LOAD_GLOBAL_MODULE,
|
||||
&&TARGET_LOAD_METHOD_ADAPTIVE,
|
||||
&&TARGET_LOAD_METHOD_CLASS,
|
||||
&&TARGET_WITH_EXCEPT_START,
|
||||
|
@ -61,26 +61,26 @@ static void *opcode_targets[256] = {
|
|||
&&TARGET_PRECALL_ADAPTIVE,
|
||||
&&TARGET_STORE_SUBSCR,
|
||||
&&TARGET_DELETE_SUBSCR,
|
||||
&&TARGET_PRECALL_BOUND_METHOD,
|
||||
&&TARGET_PRECALL_BUILTIN_CLASS,
|
||||
&&TARGET_PRECALL_NO_KW_BUILTIN_O,
|
||||
&&TARGET_PRECALL_NO_KW_BUILTIN_FAST,
|
||||
&&TARGET_PRECALL_BUILTIN_FAST_WITH_KEYWORDS,
|
||||
&&TARGET_PRECALL_NO_KW_LEN,
|
||||
&&TARGET_PRECALL_NO_KW_BUILTIN_FAST,
|
||||
&&TARGET_PRECALL_NO_KW_BUILTIN_O,
|
||||
&&TARGET_PRECALL_NO_KW_ISINSTANCE,
|
||||
&&TARGET_GET_ITER,
|
||||
&&TARGET_GET_YIELD_FROM_ITER,
|
||||
&&TARGET_PRINT_EXPR,
|
||||
&&TARGET_LOAD_BUILD_CLASS,
|
||||
&&TARGET_PRECALL_NO_KW_LEN,
|
||||
&&TARGET_PRECALL_NO_KW_LIST_APPEND,
|
||||
&&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_O,
|
||||
&&TARGET_LOAD_ASSERTION_ERROR,
|
||||
&&TARGET_RETURN_GENERATOR,
|
||||
&&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST,
|
||||
&&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS,
|
||||
&&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_O,
|
||||
&&TARGET_PRECALL_NO_KW_STR_1,
|
||||
&&TARGET_PRECALL_NO_KW_TUPLE_1,
|
||||
&&TARGET_PRECALL_NO_KW_TYPE_1,
|
||||
&&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST,
|
||||
&&TARGET_PRECALL_BOUND_METHOD,
|
||||
&&TARGET_LIST_TO_TUPLE,
|
||||
&&TARGET_RETURN_VALUE,
|
||||
&&TARGET_IMPORT_STAR,
|
||||
|
@ -157,23 +157,23 @@ static void *opcode_targets[256] = {
|
|||
&&TARGET_FORMAT_VALUE,
|
||||
&&TARGET_BUILD_CONST_KEY_MAP,
|
||||
&&TARGET_BUILD_STRING,
|
||||
&&TARGET_UNPACK_SEQUENCE_ADAPTIVE,
|
||||
&&TARGET_UNPACK_SEQUENCE_LIST,
|
||||
&&TARGET_STORE_FAST__LOAD_FAST,
|
||||
&&TARGET_STORE_FAST__STORE_FAST,
|
||||
&&TARGET_LOAD_METHOD,
|
||||
&&TARGET_UNPACK_SEQUENCE_TUPLE,
|
||||
&&TARGET_STORE_SUBSCR_ADAPTIVE,
|
||||
&&TARGET_LIST_EXTEND,
|
||||
&&TARGET_SET_UPDATE,
|
||||
&&TARGET_DICT_MERGE,
|
||||
&&TARGET_DICT_UPDATE,
|
||||
&&TARGET_PRECALL,
|
||||
&&TARGET_UNPACK_SEQUENCE_TWO_TUPLE,
|
||||
&&TARGET_LOAD_FAST__LOAD_FAST,
|
||||
&&TARGET_STORE_FAST__LOAD_FAST,
|
||||
&&TARGET_LOAD_FAST__LOAD_CONST,
|
||||
&&TARGET_STORE_SUBSCR_DICT,
|
||||
&&TARGET_STORE_SUBSCR_LIST_INT,
|
||||
&&TARGET_UNPACK_SEQUENCE_ADAPTIVE,
|
||||
&&TARGET_UNPACK_SEQUENCE_LIST,
|
||||
&&TARGET_CALL,
|
||||
&&TARGET_KW_NAMES,
|
||||
&&TARGET_LOAD_CONST__LOAD_FAST,
|
||||
&&TARGET_STORE_FAST__STORE_FAST,
|
||||
&&TARGET_UNPACK_SEQUENCE_TUPLE,
|
||||
&&TARGET_UNPACK_SEQUENCE_TWO_TUPLE,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
|
|
|
@ -15,31 +15,6 @@
|
|||
* ./adaptive.md
|
||||
*/
|
||||
|
||||
|
||||
/* We layout the quickened data as a bi-directional array:
|
||||
* Instructions upwards, cache entries downwards.
|
||||
* first_instr is aligned to a SpecializedCacheEntry.
|
||||
* The nth instruction is located at first_instr[n]
|
||||
* The nth cache is located at ((SpecializedCacheEntry *)first_instr)[-1-n]
|
||||
* The first (index 0) cache entry is reserved for the count, to enable finding
|
||||
* the first instruction from the base pointer.
|
||||
* The cache_count argument must include space for the count.
|
||||
* We use the SpecializedCacheOrInstruction union to refer to the data
|
||||
* to avoid type punning.
|
||||
|
||||
Layout of quickened data, each line 8 bytes for M cache entries and N instructions:
|
||||
|
||||
<cache_count> <---- co->co_quickened
|
||||
<cache M-1>
|
||||
<cache M-2>
|
||||
...
|
||||
<cache 0>
|
||||
<instr 0> <instr 1> <instr 2> <instr 3> <--- co->co_first_instr
|
||||
<instr 4> <instr 5> <instr 6> <instr 7>
|
||||
...
|
||||
<instr N-1>
|
||||
*/
|
||||
|
||||
/* Map from opcode to adaptive opcode.
|
||||
Values of zero are ignored. */
|
||||
static uint8_t adaptive_opcodes[256] = {
|
||||
|
@ -275,26 +250,14 @@ _Py_PrintSpecializationStats(int to_file)
|
|||
#define SPECIALIZATION_FAIL(opcode, kind) ((void)0)
|
||||
#endif
|
||||
|
||||
static _Py_CODEUNIT *
|
||||
allocate(int instruction_count)
|
||||
// Insert adaptive instructions and superinstructions. This cannot fail.
|
||||
void
|
||||
_PyCode_Quicken(PyCodeObject *code)
|
||||
{
|
||||
assert(instruction_count > 0);
|
||||
void *array = PyMem_Malloc(sizeof(_Py_CODEUNIT) * instruction_count);
|
||||
if (array == NULL) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
_Py_QuickenedCount++;
|
||||
return (_Py_CODEUNIT *)array;
|
||||
}
|
||||
|
||||
|
||||
// Insert adaptive instructions and superinstructions.
|
||||
static void
|
||||
optimize(_Py_CODEUNIT *instructions, int len)
|
||||
{
|
||||
int previous_opcode = -1;
|
||||
for(int i = 0; i < len; i++) {
|
||||
_Py_CODEUNIT *instructions = _PyCode_CODE(code);
|
||||
for (int i = 0; i < Py_SIZE(code); i++) {
|
||||
int opcode = _Py_OPCODE(instructions[i]);
|
||||
uint8_t adaptive_opcode = adaptive_opcodes[opcode];
|
||||
if (adaptive_opcode) {
|
||||
|
@ -302,10 +265,10 @@ optimize(_Py_CODEUNIT *instructions, int len)
|
|||
// Make sure the adaptive counter is zero:
|
||||
assert(instructions[i + 1] == 0);
|
||||
previous_opcode = -1;
|
||||
i += _PyOpcode_InlineCacheEntries[opcode];
|
||||
i += _PyOpcode_Caches[opcode];
|
||||
}
|
||||
else {
|
||||
assert(!_PyOpcode_InlineCacheEntries[opcode]);
|
||||
assert(!_PyOpcode_Caches[opcode]);
|
||||
switch (opcode) {
|
||||
case JUMP_ABSOLUTE:
|
||||
_Py_SET_OPCODE(instructions[i], JUMP_ABSOLUTE_QUICK);
|
||||
|
@ -347,28 +310,6 @@ optimize(_Py_CODEUNIT *instructions, int len)
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
_Py_Quicken(PyCodeObject *code) {
|
||||
if (code->co_quickened) {
|
||||
return 0;
|
||||
}
|
||||
Py_ssize_t size = PyBytes_GET_SIZE(code->co_code);
|
||||
int instr_count = (int)(size/sizeof(_Py_CODEUNIT));
|
||||
if (instr_count > MAX_SIZE_TO_QUICKEN) {
|
||||
code->co_warmup = QUICKENING_WARMUP_COLDEST;
|
||||
return 0;
|
||||
}
|
||||
_Py_CODEUNIT *quickened = allocate(instr_count);
|
||||
if (quickened == NULL) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(quickened, code->co_firstinstr, size);
|
||||
optimize(quickened, instr_count);
|
||||
code->co_quickened = quickened;
|
||||
code->co_firstinstr = quickened;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
initial_counter_value(void) {
|
||||
/* Starting value for the counter.
|
||||
|
@ -705,8 +646,7 @@ specialize_dict_access(
|
|||
int
|
||||
_Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name)
|
||||
{
|
||||
assert(_PyOpcode_InlineCacheEntries[LOAD_ATTR] ==
|
||||
INLINE_CACHE_ENTRIES_LOAD_ATTR);
|
||||
assert(_PyOpcode_Caches[LOAD_ATTR] == INLINE_CACHE_ENTRIES_LOAD_ATTR);
|
||||
_PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
|
||||
if (PyModule_CheckExact(owner)) {
|
||||
int err = specialize_module_load_attr(owner, instr, name, LOAD_ATTR,
|
||||
|
@ -804,8 +744,7 @@ success:
|
|||
int
|
||||
_Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name)
|
||||
{
|
||||
assert(_PyOpcode_InlineCacheEntries[STORE_ATTR] ==
|
||||
INLINE_CACHE_ENTRIES_STORE_ATTR);
|
||||
assert(_PyOpcode_Caches[STORE_ATTR] == INLINE_CACHE_ENTRIES_STORE_ATTR);
|
||||
_PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
|
||||
PyTypeObject *type = Py_TYPE(owner);
|
||||
if (PyModule_CheckExact(owner)) {
|
||||
|
@ -965,8 +904,7 @@ typedef enum {
|
|||
int
|
||||
_Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name)
|
||||
{
|
||||
assert(_PyOpcode_InlineCacheEntries[LOAD_METHOD] ==
|
||||
INLINE_CACHE_ENTRIES_LOAD_METHOD);
|
||||
assert(_PyOpcode_Caches[LOAD_METHOD] == INLINE_CACHE_ENTRIES_LOAD_METHOD);
|
||||
_PyLoadMethodCache *cache = (_PyLoadMethodCache *)(instr + 1);
|
||||
PyTypeObject *owner_cls = Py_TYPE(owner);
|
||||
|
||||
|
@ -1098,8 +1036,7 @@ _Py_Specialize_LoadGlobal(
|
|||
PyObject *globals, PyObject *builtins,
|
||||
_Py_CODEUNIT *instr, PyObject *name)
|
||||
{
|
||||
assert(_PyOpcode_InlineCacheEntries[LOAD_GLOBAL] ==
|
||||
INLINE_CACHE_ENTRIES_LOAD_GLOBAL);
|
||||
assert(_PyOpcode_Caches[LOAD_GLOBAL] == INLINE_CACHE_ENTRIES_LOAD_GLOBAL);
|
||||
/* Use inline cache */
|
||||
_PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)(instr + 1);
|
||||
assert(PyUnicode_CheckExact(name));
|
||||
|
@ -1235,7 +1172,7 @@ int
|
|||
_Py_Specialize_BinarySubscr(
|
||||
PyObject *container, PyObject *sub, _Py_CODEUNIT *instr)
|
||||
{
|
||||
assert(_PyOpcode_InlineCacheEntries[BINARY_SUBSCR] ==
|
||||
assert(_PyOpcode_Caches[BINARY_SUBSCR] ==
|
||||
INLINE_CACHE_ENTRIES_BINARY_SUBSCR);
|
||||
_PyBinarySubscrCache *cache = (_PyBinarySubscrCache *)(instr + 1);
|
||||
PyTypeObject *container_type = Py_TYPE(container);
|
||||
|
@ -1663,8 +1600,7 @@ int
|
|||
_Py_Specialize_Precall(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
|
||||
PyObject *kwnames, int oparg)
|
||||
{
|
||||
assert(_PyOpcode_InlineCacheEntries[PRECALL] ==
|
||||
INLINE_CACHE_ENTRIES_PRECALL);
|
||||
assert(_PyOpcode_Caches[PRECALL] == INLINE_CACHE_ENTRIES_PRECALL);
|
||||
_PyPrecallCache *cache = (_PyPrecallCache *)(instr + 1);
|
||||
int fail;
|
||||
if (PyCFunction_CheckExact(callable)) {
|
||||
|
@ -1710,7 +1646,7 @@ int
|
|||
_Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
|
||||
PyObject *kwnames)
|
||||
{
|
||||
assert(_PyOpcode_InlineCacheEntries[CALL] == INLINE_CACHE_ENTRIES_CALL);
|
||||
assert(_PyOpcode_Caches[CALL] == INLINE_CACHE_ENTRIES_CALL);
|
||||
_PyCallCache *cache = (_PyCallCache *)(instr + 1);
|
||||
int fail;
|
||||
if (PyFunction_Check(callable)) {
|
||||
|
@ -1808,8 +1744,7 @@ void
|
|||
_Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
|
||||
int oparg)
|
||||
{
|
||||
assert(_PyOpcode_InlineCacheEntries[BINARY_OP] ==
|
||||
INLINE_CACHE_ENTRIES_BINARY_OP);
|
||||
assert(_PyOpcode_Caches[BINARY_OP] == INLINE_CACHE_ENTRIES_BINARY_OP);
|
||||
_PyBinaryOpCache *cache = (_PyBinaryOpCache *)(instr + 1);
|
||||
switch (oparg) {
|
||||
case NB_ADD:
|
||||
|
@ -1936,8 +1871,7 @@ void
|
|||
_Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
|
||||
int oparg)
|
||||
{
|
||||
assert(_PyOpcode_InlineCacheEntries[COMPARE_OP] ==
|
||||
INLINE_CACHE_ENTRIES_COMPARE_OP);
|
||||
assert(_PyOpcode_Caches[COMPARE_OP] == INLINE_CACHE_ENTRIES_COMPARE_OP);
|
||||
_PyCompareOpCache *cache = (_PyCompareOpCache *)(instr + 1);
|
||||
int next_opcode = _Py_OPCODE(instr[INLINE_CACHE_ENTRIES_COMPARE_OP + 1]);
|
||||
if (next_opcode != POP_JUMP_IF_FALSE && next_opcode != POP_JUMP_IF_TRUE) {
|
||||
|
@ -2019,7 +1953,7 @@ unpack_sequence_fail_kind(PyObject *seq)
|
|||
void
|
||||
_Py_Specialize_UnpackSequence(PyObject *seq, _Py_CODEUNIT *instr, int oparg)
|
||||
{
|
||||
assert(_PyOpcode_InlineCacheEntries[UNPACK_SEQUENCE] ==
|
||||
assert(_PyOpcode_Caches[UNPACK_SEQUENCE] ==
|
||||
INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE);
|
||||
_PyUnpackSequenceCache *cache = (_PyUnpackSequenceCache *)(instr + 1);
|
||||
if (PyTuple_CheckExact(seq)) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue