bpo-46841: Use *inline* caching for BINARY_OP (GH-31543)

This commit is contained in:
Brandt Bucher 2022-02-25 04:11:34 -08:00 committed by GitHub
parent 18b5dd68c6
commit 0f41aac109
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 429 additions and 351 deletions

View file

@ -1939,6 +1939,7 @@ handle_eval_breaker:
if (prod == NULL) {
goto error;
}
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP);
NOTRACE_DISPATCH();
}
@ -1959,6 +1960,7 @@ handle_eval_breaker:
if (prod == NULL) {
goto error;
}
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP);
NOTRACE_DISPATCH();
}
@ -1977,6 +1979,7 @@ handle_eval_breaker:
if (sub == NULL) {
goto error;
}
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP);
NOTRACE_DISPATCH();
}
@ -1996,6 +1999,7 @@ handle_eval_breaker:
if (sub == NULL) {
goto error;
}
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP);
NOTRACE_DISPATCH();
}
@ -2014,6 +2018,7 @@ handle_eval_breaker:
if (TOP() == NULL) {
goto error;
}
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP);
NOTRACE_DISPATCH();
}
@ -2043,6 +2048,7 @@ handle_eval_breaker:
if (TOP() == NULL) {
goto error;
}
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP);
NOTRACE_DISPATCH();
}
@ -2063,6 +2069,7 @@ handle_eval_breaker:
if (sum == NULL) {
goto error;
}
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP);
NOTRACE_DISPATCH();
}
@ -2081,6 +2088,7 @@ handle_eval_breaker:
if (sum == NULL) {
goto error;
}
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP);
NOTRACE_DISPATCH();
}
@ -5425,23 +5433,23 @@ handle_eval_breaker:
if (res == NULL) {
goto error;
}
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP);
DISPATCH();
}
TARGET(BINARY_OP_ADAPTIVE) {
assert(cframe.use_tracing == 0);
SpecializedCacheEntry *cache = GET_CACHE();
if (cache->adaptive.counter == 0) {
_PyBinaryOpCache *cache = (_PyBinaryOpCache *)next_instr;
if (cache->counter == 0) {
PyObject *lhs = SECOND();
PyObject *rhs = TOP();
next_instr--;
_Py_Specialize_BinaryOp(lhs, rhs, next_instr, cache);
_Py_Specialize_BinaryOp(lhs, rhs, next_instr, oparg);
DISPATCH();
}
else {
STAT_INC(BINARY_OP, deferred);
cache->adaptive.counter--;
oparg = cache->adaptive.original_oparg;
cache->counter--;
JUMP_TO_INSTRUCTION(BINARY_OP);
}
}
@ -5462,6 +5470,10 @@ handle_eval_breaker:
DISPATCH_GOTO();
}
TARGET(CACHE) {
Py_UNREACHABLE();
}
#if USE_COMPUTED_GOTOS
TARGET_DO_TRACING: {
#else
@ -5548,6 +5560,22 @@ opname ## _miss: \
JUMP_TO_INSTRUCTION(opname); \
}
#define MISS_WITH_INLINE_CACHE(opname) \
opname ## _miss: \
{ \
STAT_INC(opcode, miss); \
STAT_INC(opname, miss); \
/* The counter is always the first cache entry: */ \
_Py_CODEUNIT *counter = (_Py_CODEUNIT *)next_instr; \
*counter -= 1; \
if (*counter == 0) { \
next_instr[-1] = _Py_MAKECODEUNIT(opname ## _ADAPTIVE, _Py_OPARG(next_instr[-1])); \
STAT_INC(opname, deopt); \
*counter = ADAPTIVE_CACHE_BACKOFF; \
} \
JUMP_TO_INSTRUCTION(opname); \
}
#define MISS_WITH_OPARG_COUNTER(opname) \
opname ## _miss: \
{ \
@ -5569,7 +5597,7 @@ MISS_WITH_CACHE(LOAD_GLOBAL)
MISS_WITH_CACHE(LOAD_METHOD)
MISS_WITH_CACHE(PRECALL)
MISS_WITH_CACHE(CALL)
MISS_WITH_CACHE(BINARY_OP)
MISS_WITH_INLINE_CACHE(BINARY_OP)
MISS_WITH_CACHE(COMPARE_OP)
MISS_WITH_CACHE(BINARY_SUBSCR)
MISS_WITH_CACHE(UNPACK_SEQUENCE)

View file

@ -33,7 +33,6 @@
#define NEED_OPCODE_JUMP_TABLES
#include "opcode.h" // EXTENDED_ARG
#include "wordcode_helpers.h" // instrsize()
#define DEFAULT_BLOCK_SIZE 16
@ -131,6 +130,43 @@ is_jump(struct instr *i)
return i->i_opcode >= SETUP_WITH || is_bit_set_in_table(_PyOpcode_Jump, i->i_opcode);
}
static int
instr_size(struct instr *instruction)
{
int opcode = instruction->i_opcode;
int oparg = instruction->i_oparg;
int extended_args = (0xFFFFFF < oparg) + (0xFFFF < oparg) + (0xFF < oparg);
int caches = _PyOpcode_InlineCacheEntries[opcode];
return extended_args + 1 + caches;
}
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];
switch (ilen - caches) {
case 4:
*codestr++ = _Py_MAKECODEUNIT(EXTENDED_ARG, (oparg >> 24) & 0xFF);
/* fall through */
case 3:
*codestr++ = _Py_MAKECODEUNIT(EXTENDED_ARG, (oparg >> 16) & 0xFF);
/* fall through */
case 2:
*codestr++ = _Py_MAKECODEUNIT(EXTENDED_ARG, (oparg >> 8) & 0xFF);
/* fall through */
case 1:
*codestr++ = _Py_MAKECODEUNIT(opcode, oparg & 0xFF);
break;
default:
Py_UNREACHABLE();
}
while (caches--) {
*codestr++ = _Py_MAKECODEUNIT(CACHE, 0);
}
}
typedef struct basicblock_ {
/* Each basicblock in a compilation unit is linked via b_list in the
reverse order that the block are allocated. b_list points to the next
@ -854,6 +890,7 @@ stack_effect(int opcode, int oparg, int jump)
case NOP:
case EXTENDED_ARG:
case RESUME:
case CACHE:
return 0;
/* Stack manipulation */
@ -7065,8 +7102,9 @@ blocksize(basicblock *b)
int i;
int size = 0;
for (i = 0; i < b->b_iused; i++)
size += instrsize(b->b_instr[i].i_oparg);
for (i = 0; i < b->b_iused; i++) {
size += instr_size(&b->b_instr[i]);
}
return size;
}
@ -7330,7 +7368,7 @@ assemble_exception_table(struct assembler *a)
start = ioffset;
handler = instr->i_except;
}
ioffset += instrsize(instr->i_oparg);
ioffset += instr_size(instr);
}
}
if (handler != NULL) {
@ -7459,12 +7497,10 @@ assemble_cnotab(struct assembler* a, struct instr* i, int instr_size)
static int
assemble_emit(struct assembler *a, struct instr *i)
{
int size, arg = 0;
Py_ssize_t len = PyBytes_GET_SIZE(a->a_bytecode);
_Py_CODEUNIT *code;
arg = i->i_oparg;
size = instrsize(arg);
int size = instr_size(i);
if (i->i_lineno && !assemble_lnotab(a, i)) {
return 0;
}
@ -7482,7 +7518,7 @@ assemble_emit(struct assembler *a, struct instr *i)
}
code = (_Py_CODEUNIT *)PyBytes_AS_STRING(a->a_bytecode) + a->a_offset;
a->a_offset += size;
write_op_arg(code, i->i_opcode, arg, size);
write_instr(code, i, size);
return 1;
}
@ -7532,7 +7568,7 @@ assemble_jump_offsets(struct assembler *a, struct compiler *c)
bsize = b->b_offset;
for (i = 0; i < b->b_iused; i++) {
struct instr *instr = &b->b_instr[i];
int isize = instrsize(instr->i_oparg);
int isize = instr_size(instr);
/* Relative jumps are computed relative to
the instruction pointer after fetching
the jump instruction.
@ -7543,7 +7579,7 @@ assemble_jump_offsets(struct assembler *a, struct compiler *c)
if (is_relative_jump(instr)) {
instr->i_oparg -= bsize;
}
if (instrsize(instr->i_oparg) != isize) {
if (instr_size(instr) != isize) {
extended_arg_recompile = 1;
}
}
@ -7555,7 +7591,7 @@ assemble_jump_offsets(struct assembler *a, struct compiler *c)
with a better solution.
The issue is that in the first loop blocksize() is called
which calls instrsize() which requires i_oparg be set
which calls instr_size() which requires i_oparg be set
appropriately. There is a bootstrap problem because
i_oparg is calculated in the second loop above.

View file

@ -2,19 +2,20 @@ static void *opcode_targets[256] = {
&&_unknown_opcode,
&&TARGET_POP_TOP,
&&TARGET_PUSH_NULL,
&&TARGET_CACHE,
&&TARGET_BINARY_OP_ADAPTIVE,
&&TARGET_BINARY_OP_ADD_INT,
&&TARGET_BINARY_OP_ADD_FLOAT,
&&TARGET_BINARY_OP_ADD_UNICODE,
&&TARGET_BINARY_OP_INPLACE_ADD_UNICODE,
&&TARGET_BINARY_OP_MULTIPLY_INT,
&&TARGET_NOP,
&&TARGET_UNARY_POSITIVE,
&&TARGET_UNARY_NEGATIVE,
&&TARGET_UNARY_NOT,
&&TARGET_BINARY_OP_MULTIPLY_INT,
&&TARGET_BINARY_OP_MULTIPLY_FLOAT,
&&TARGET_BINARY_OP_SUBTRACT_INT,
&&TARGET_UNARY_INVERT,
&&TARGET_BINARY_OP_SUBTRACT_INT,
&&TARGET_BINARY_OP_SUBTRACT_FLOAT,
&&TARGET_COMPARE_OP_ADAPTIVE,
&&TARGET_COMPARE_OP_FLOAT_JUMP,
@ -23,18 +24,18 @@ static void *opcode_targets[256] = {
&&TARGET_BINARY_SUBSCR_ADAPTIVE,
&&TARGET_BINARY_SUBSCR_GETITEM,
&&TARGET_BINARY_SUBSCR_LIST_INT,
&&TARGET_BINARY_SUBSCR_TUPLE_INT,
&&TARGET_BINARY_SUBSCR,
&&TARGET_BINARY_SUBSCR_TUPLE_INT,
&&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_STORE_SUBSCR_DICT,
&&TARGET_PUSH_EXC_INFO,
&&TARGET_CALL_ADAPTIVE,
&&TARGET_CALL_PY_EXACT_ARGS,
&&TARGET_CALL_PY_WITH_DEFAULTS,
&&TARGET_JUMP_ABSOLUTE_QUICK,
@ -47,40 +48,39 @@ static void *opcode_targets[256] = {
&&TARGET_LOAD_GLOBAL_MODULE,
&&TARGET_LOAD_GLOBAL_BUILTIN,
&&TARGET_LOAD_METHOD_ADAPTIVE,
&&TARGET_LOAD_METHOD_CLASS,
&&TARGET_WITH_EXCEPT_START,
&&TARGET_GET_AITER,
&&TARGET_GET_ANEXT,
&&TARGET_BEFORE_ASYNC_WITH,
&&TARGET_BEFORE_WITH,
&&TARGET_END_ASYNC_FOR,
&&TARGET_LOAD_METHOD_CLASS,
&&TARGET_LOAD_METHOD_MODULE,
&&TARGET_LOAD_METHOD_NO_DICT,
&&TARGET_LOAD_METHOD_WITH_DICT,
&&TARGET_LOAD_METHOD_WITH_VALUES,
&&TARGET_PRECALL_ADAPTIVE,
&&TARGET_STORE_SUBSCR,
&&TARGET_DELETE_SUBSCR,
&&TARGET_PRECALL_ADAPTIVE,
&&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_ISINSTANCE,
&&TARGET_GET_ITER,
&&TARGET_GET_YIELD_FROM_ITER,
&&TARGET_PRINT_EXPR,
&&TARGET_LOAD_BUILD_CLASS,
&&TARGET_PRECALL_NO_KW_LIST_APPEND,
&&TARGET_PRECALL_NO_KW_ISINSTANCE,
&&TARGET_GET_AWAITABLE,
&&TARGET_LOAD_ASSERTION_ERROR,
&&TARGET_RETURN_GENERATOR,
&&TARGET_PRECALL_NO_KW_LIST_APPEND,
&&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_O,
&&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS,
&&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_LIST_TO_TUPLE,
&&TARGET_RETURN_VALUE,
&&TARGET_IMPORT_STAR,
@ -130,7 +130,7 @@ static void *opcode_targets[256] = {
&&TARGET_POP_JUMP_IF_NOT_NONE,
&&TARGET_POP_JUMP_IF_NONE,
&&TARGET_RAISE_VARARGS,
&&TARGET_PRECALL_BOUND_METHOD,
&&TARGET_PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST,
&&TARGET_MAKE_FUNCTION,
&&TARGET_BUILD_SLICE,
&&TARGET_JUMP_NO_INTERRUPT,
@ -139,39 +139,40 @@ static void *opcode_targets[256] = {
&&TARGET_LOAD_DEREF,
&&TARGET_STORE_DEREF,
&&TARGET_DELETE_DEREF,
&&TARGET_PRECALL_BOUND_METHOD,
&&TARGET_PRECALL_PYFUNC,
&&TARGET_RESUME_QUICK,
&&TARGET_CALL_FUNCTION_EX,
&&TARGET_STORE_ATTR_ADAPTIVE,
&&TARGET_RESUME_QUICK,
&&TARGET_EXTENDED_ARG,
&&TARGET_LIST_APPEND,
&&TARGET_SET_ADD,
&&TARGET_MAP_ADD,
&&TARGET_LOAD_CLASSDEREF,
&&TARGET_COPY_FREE_VARS,
&&TARGET_STORE_ATTR_INSTANCE_VALUE,
&&TARGET_STORE_ATTR_ADAPTIVE,
&&TARGET_RESUME,
&&TARGET_MATCH_CLASS,
&&TARGET_STORE_ATTR_INSTANCE_VALUE,
&&TARGET_STORE_ATTR_SLOT,
&&TARGET_STORE_ATTR_WITH_HINT,
&&TARGET_FORMAT_VALUE,
&&TARGET_BUILD_CONST_KEY_MAP,
&&TARGET_BUILD_STRING,
&&TARGET_STORE_ATTR_WITH_HINT,
&&TARGET_UNPACK_SEQUENCE_ADAPTIVE,
&&TARGET_UNPACK_SEQUENCE_LIST,
&&TARGET_LOAD_METHOD,
&&TARGET_UNPACK_SEQUENCE_TUPLE,
&&TARGET_UNPACK_SEQUENCE_LIST,
&&TARGET_LIST_EXTEND,
&&TARGET_SET_UPDATE,
&&TARGET_DICT_MERGE,
&&TARGET_DICT_UPDATE,
&&TARGET_PRECALL,
&&TARGET_UNPACK_SEQUENCE_TUPLE,
&&TARGET_UNPACK_SEQUENCE_TWO_TUPLE,
&&TARGET_LOAD_FAST__LOAD_FAST,
&&TARGET_STORE_FAST__LOAD_FAST,
&&TARGET_LOAD_FAST__LOAD_CONST,
&&TARGET_CALL,
&&TARGET_KW_NAMES,
&&TARGET_LOAD_FAST__LOAD_CONST,
&&TARGET_LOAD_CONST__LOAD_FAST,
&&TARGET_STORE_FAST__STORE_FAST,
&&TARGET_LOAD_FAST__LOAD_ATTR_INSTANCE_VALUE,
@ -253,6 +254,5 @@ static void *opcode_targets[256] = {
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&TARGET_DO_TRACING
};

View file

@ -65,7 +65,6 @@ static uint8_t cache_requirements[256] = {
[CALL] = 2, /* _PyAdaptiveEntry and _PyObjectCache/_PyCallCache */
[PRECALL] = 2, /* _PyAdaptiveEntry and _PyObjectCache/_PyCallCache */
[STORE_ATTR] = 1, // _PyAdaptiveEntry
[BINARY_OP] = 1, // _PyAdaptiveEntry
[COMPARE_OP] = 1, /* _PyAdaptiveEntry */
[UNPACK_SEQUENCE] = 1, // _PyAdaptiveEntry
};
@ -385,29 +384,34 @@ optimize(SpecializedCacheOrInstruction *quickened, int len)
int opcode = _Py_OPCODE(instructions[i]);
int oparg = _Py_OPARG(instructions[i]);
uint8_t adaptive_opcode = adaptive_opcodes[opcode];
if (adaptive_opcode && previous_opcode != EXTENDED_ARG) {
int new_oparg = oparg_from_instruction_and_update_offset(
i, opcode, oparg, &cache_offset
);
if (new_oparg < 0) {
/* Not possible to allocate a cache for this instruction */
previous_opcode = opcode;
continue;
if (adaptive_opcode) {
if (_PyOpcode_InlineCacheEntries[opcode]) {
instructions[i] = _Py_MAKECODEUNIT(adaptive_opcode, oparg);
}
previous_opcode = adaptive_opcode;
int entries_needed = cache_requirements[opcode];
if (entries_needed) {
/* Initialize the adpative cache entry */
int cache0_offset = cache_offset-entries_needed;
SpecializedCacheEntry *cache =
_GetSpecializedCacheEntry(instructions, cache0_offset);
cache->adaptive.original_oparg = oparg;
cache->adaptive.counter = 0;
} else {
// oparg is the adaptive cache counter
new_oparg = 0;
else if (previous_opcode != EXTENDED_ARG) {
int new_oparg = oparg_from_instruction_and_update_offset(
i, opcode, oparg, &cache_offset
);
if (new_oparg < 0) {
/* Not possible to allocate a cache for this instruction */
previous_opcode = opcode;
continue;
}
previous_opcode = adaptive_opcode;
int entries_needed = cache_requirements[opcode];
if (entries_needed) {
/* Initialize the adpative cache entry */
int cache0_offset = cache_offset-entries_needed;
SpecializedCacheEntry *cache =
_GetSpecializedCacheEntry(instructions, cache0_offset);
cache->adaptive.original_oparg = oparg;
cache->adaptive.counter = 0;
} else {
// oparg is the adaptive cache counter
new_oparg = 0;
}
instructions[i] = _Py_MAKECODEUNIT(adaptive_opcode, new_oparg);
}
instructions[i] = _Py_MAKECODEUNIT(adaptive_opcode, new_oparg);
}
else {
/* Super instructions don't use the cache,
@ -1922,10 +1926,12 @@ binary_op_fail_kind(int oparg, PyObject *lhs, PyObject *rhs)
void
_Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
SpecializedCacheEntry *cache)
int oparg)
{
_PyAdaptiveEntry *adaptive = &cache->adaptive;
switch (adaptive->original_oparg) {
assert(_PyOpcode_InlineCacheEntries[BINARY_OP] ==
INLINE_CACHE_ENTRIES_BINARY_OP);
_PyBinaryOpCache *cache = (_PyBinaryOpCache *)(instr + 1);
switch (oparg) {
case NB_ADD:
case NB_INPLACE_ADD:
if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
@ -1934,20 +1940,18 @@ _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
if (PyUnicode_CheckExact(lhs)) {
if (_Py_OPCODE(instr[1]) == STORE_FAST && Py_REFCNT(lhs) == 2) {
*instr = _Py_MAKECODEUNIT(BINARY_OP_INPLACE_ADD_UNICODE,
_Py_OPARG(*instr));
oparg);
goto success;
}
*instr = _Py_MAKECODEUNIT(BINARY_OP_ADD_UNICODE,
_Py_OPARG(*instr));
*instr = _Py_MAKECODEUNIT(BINARY_OP_ADD_UNICODE, oparg);
goto success;
}
if (PyLong_CheckExact(lhs)) {
*instr = _Py_MAKECODEUNIT(BINARY_OP_ADD_INT, _Py_OPARG(*instr));
*instr = _Py_MAKECODEUNIT(BINARY_OP_ADD_INT, oparg);
goto success;
}
if (PyFloat_CheckExact(lhs)) {
*instr = _Py_MAKECODEUNIT(BINARY_OP_ADD_FLOAT,
_Py_OPARG(*instr));
*instr = _Py_MAKECODEUNIT(BINARY_OP_ADD_FLOAT, oparg);
goto success;
}
break;
@ -1957,13 +1961,11 @@ _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
break;
}
if (PyLong_CheckExact(lhs)) {
*instr = _Py_MAKECODEUNIT(BINARY_OP_MULTIPLY_INT,
_Py_OPARG(*instr));
*instr = _Py_MAKECODEUNIT(BINARY_OP_MULTIPLY_INT, oparg);
goto success;
}
if (PyFloat_CheckExact(lhs)) {
*instr = _Py_MAKECODEUNIT(BINARY_OP_MULTIPLY_FLOAT,
_Py_OPARG(*instr));
*instr = _Py_MAKECODEUNIT(BINARY_OP_MULTIPLY_FLOAT, oparg);
goto success;
}
break;
@ -1973,13 +1975,11 @@ _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
break;
}
if (PyLong_CheckExact(lhs)) {
*instr = _Py_MAKECODEUNIT(BINARY_OP_SUBTRACT_INT,
_Py_OPARG(*instr));
*instr = _Py_MAKECODEUNIT(BINARY_OP_SUBTRACT_INT, oparg);
goto success;
}
if (PyFloat_CheckExact(lhs)) {
*instr = _Py_MAKECODEUNIT(BINARY_OP_SUBTRACT_FLOAT,
_Py_OPARG(*instr));
*instr = _Py_MAKECODEUNIT(BINARY_OP_SUBTRACT_FLOAT, oparg);
goto success;
}
break;
@ -1990,18 +1990,17 @@ _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
// back to BINARY_OP (unless we're collecting stats, where it's more
// important to get accurate hit counts for the unadaptive version
// and each of the different failure types):
*instr = _Py_MAKECODEUNIT(BINARY_OP, adaptive->original_oparg);
*instr = _Py_MAKECODEUNIT(BINARY_OP, oparg);
return;
#endif
}
SPECIALIZATION_FAIL(
BINARY_OP, binary_op_fail_kind(adaptive->original_oparg, lhs, rhs));
SPECIALIZATION_FAIL(BINARY_OP, binary_op_fail_kind(oparg, lhs, rhs));
STAT_INC(BINARY_OP, failure);
cache_backoff(adaptive);
cache->counter = ADAPTIVE_CACHE_BACKOFF;
return;
success:
STAT_INC(BINARY_OP, success);
adaptive->counter = initial_counter_value();
cache->counter = initial_counter_value();
}

View file

@ -1,44 +0,0 @@
/* This file contains code shared by the compiler and the peephole
optimizer.
*/
#ifdef WORDS_BIGENDIAN
# define PACKOPARG(opcode, oparg) ((_Py_CODEUNIT)(((opcode) << 8) | (oparg)))
#else
# define PACKOPARG(opcode, oparg) ((_Py_CODEUNIT)(((oparg) << 8) | (opcode)))
#endif
/* Minimum number of code units necessary to encode instruction with
EXTENDED_ARGs */
static int
instrsize(unsigned int oparg)
{
return oparg <= 0xff ? 1 :
oparg <= 0xffff ? 2 :
oparg <= 0xffffff ? 3 :
4;
}
/* Spits out op/oparg pair using ilen bytes. codestr should be pointed at the
desired location of the first EXTENDED_ARG */
static void
write_op_arg(_Py_CODEUNIT *codestr, unsigned char opcode,
unsigned int oparg, int ilen)
{
switch (ilen) {
case 4:
*codestr++ = PACKOPARG(EXTENDED_ARG, (oparg >> 24) & 0xff);
/* fall through */
case 3:
*codestr++ = PACKOPARG(EXTENDED_ARG, (oparg >> 16) & 0xff);
/* fall through */
case 2:
*codestr++ = PACKOPARG(EXTENDED_ARG, (oparg >> 8) & 0xff);
/* fall through */
case 1:
*codestr++ = PACKOPARG(opcode, oparg & 0xff);
break;
default:
Py_UNREACHABLE();
}
}