mirror of
https://github.com/python/cpython.git
synced 2025-07-23 03:05:38 +00:00
gh-100239: replace BINARY_SUBSCR & family by BINARY_OP with oparg NB_SUBSCR (#129700)
This commit is contained in:
parent
2248a9c153
commit
a1417b211f
30 changed files with 1281 additions and 1447 deletions
|
@ -537,6 +537,11 @@ dummy_func(
|
|||
BINARY_OP_ADD_FLOAT,
|
||||
BINARY_OP_SUBTRACT_FLOAT,
|
||||
BINARY_OP_ADD_UNICODE,
|
||||
BINARY_OP_SUBSCR_LIST_INT,
|
||||
BINARY_OP_SUBSCR_TUPLE_INT,
|
||||
BINARY_OP_SUBSCR_STR_INT,
|
||||
BINARY_OP_SUBSCR_DICT,
|
||||
BINARY_OP_SUBSCR_GETITEM,
|
||||
// BINARY_OP_INPLACE_ADD_UNICODE, // See comments at that opcode.
|
||||
BINARY_OP_EXTEND,
|
||||
};
|
||||
|
@ -787,39 +792,6 @@ dummy_func(
|
|||
macro(BINARY_OP_INPLACE_ADD_UNICODE) =
|
||||
_GUARD_BOTH_UNICODE + unused/5 + _BINARY_OP_INPLACE_ADD_UNICODE;
|
||||
|
||||
family(BINARY_SUBSCR, INLINE_CACHE_ENTRIES_BINARY_SUBSCR) = {
|
||||
BINARY_SUBSCR_DICT,
|
||||
BINARY_SUBSCR_GETITEM,
|
||||
BINARY_SUBSCR_LIST_INT,
|
||||
BINARY_SUBSCR_STR_INT,
|
||||
BINARY_SUBSCR_TUPLE_INT,
|
||||
};
|
||||
|
||||
specializing op(_SPECIALIZE_BINARY_SUBSCR, (counter/1, container, sub -- container, sub)) {
|
||||
#if ENABLE_SPECIALIZATION_FT
|
||||
assert(frame->stackpointer == NULL);
|
||||
if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
|
||||
next_instr = this_instr;
|
||||
_Py_Specialize_BinarySubscr(container, sub, next_instr);
|
||||
DISPATCH_SAME_OPARG();
|
||||
}
|
||||
OPCODE_DEFERRED_INC(BINARY_SUBSCR);
|
||||
ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter);
|
||||
#endif /* ENABLE_SPECIALIZATION_FT */
|
||||
}
|
||||
|
||||
op(_BINARY_SUBSCR, (container, sub -- res)) {
|
||||
PyObject *container_o = PyStackRef_AsPyObjectBorrow(container);
|
||||
PyObject *sub_o = PyStackRef_AsPyObjectBorrow(sub);
|
||||
|
||||
PyObject *res_o = PyObject_GetItem(container_o, sub_o);
|
||||
DECREF_INPUTS();
|
||||
ERROR_IF(res_o == NULL, error);
|
||||
res = PyStackRef_FromPyObjectSteal(res_o);
|
||||
}
|
||||
|
||||
macro(BINARY_SUBSCR) = _SPECIALIZE_BINARY_SUBSCR + _BINARY_SUBSCR;
|
||||
|
||||
specializing op(_SPECIALIZE_BINARY_SLICE, (container, start, stop -- container, start, stop)) {
|
||||
// Placeholder until we implement BINARY_SLICE specialization
|
||||
#if ENABLE_SPECIALIZATION
|
||||
|
@ -871,7 +843,7 @@ dummy_func(
|
|||
|
||||
macro(STORE_SLICE) = _SPECIALIZE_STORE_SLICE + _STORE_SLICE;
|
||||
|
||||
inst(BINARY_SUBSCR_LIST_INT, (unused/1, list_st, sub_st -- res)) {
|
||||
inst(BINARY_OP_SUBSCR_LIST_INT, (unused/5, list_st, sub_st -- res)) {
|
||||
PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st);
|
||||
PyObject *list = PyStackRef_AsPyObjectBorrow(list_st);
|
||||
|
||||
|
@ -884,10 +856,10 @@ dummy_func(
|
|||
#ifdef Py_GIL_DISABLED
|
||||
PyObject *res_o = _PyList_GetItemRef((PyListObject*)list, index);
|
||||
DEOPT_IF(res_o == NULL);
|
||||
STAT_INC(BINARY_SUBSCR, hit);
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
#else
|
||||
DEOPT_IF(index >= PyList_GET_SIZE(list));
|
||||
STAT_INC(BINARY_SUBSCR, hit);
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
PyObject *res_o = PyList_GET_ITEM(list, index);
|
||||
assert(res_o != NULL);
|
||||
Py_INCREF(res_o);
|
||||
|
@ -898,7 +870,7 @@ dummy_func(
|
|||
res = PyStackRef_FromPyObjectSteal(res_o);
|
||||
}
|
||||
|
||||
inst(BINARY_SUBSCR_STR_INT, (unused/1, str_st, sub_st -- res)) {
|
||||
inst(BINARY_OP_SUBSCR_STR_INT, (unused/5, str_st, sub_st -- res)) {
|
||||
PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st);
|
||||
PyObject *str = PyStackRef_AsPyObjectBorrow(str_st);
|
||||
|
||||
|
@ -910,7 +882,7 @@ dummy_func(
|
|||
// Specialize for reading an ASCII character from any string:
|
||||
Py_UCS4 c = PyUnicode_READ_CHAR(str, index);
|
||||
DEOPT_IF(Py_ARRAY_LENGTH(_Py_SINGLETON(strings).ascii) <= c);
|
||||
STAT_INC(BINARY_SUBSCR, hit);
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
PyObject *res_o = (PyObject*)&_Py_SINGLETON(strings).ascii[c];
|
||||
PyStackRef_CLOSE_SPECIALIZED(sub_st, _PyLong_ExactDealloc);
|
||||
DEAD(sub_st);
|
||||
|
@ -918,7 +890,7 @@ dummy_func(
|
|||
res = PyStackRef_FromPyObjectSteal(res_o);
|
||||
}
|
||||
|
||||
inst(BINARY_SUBSCR_TUPLE_INT, (unused/1, tuple_st, sub_st -- res)) {
|
||||
inst(BINARY_OP_SUBSCR_TUPLE_INT, (unused/5, tuple_st, sub_st -- res)) {
|
||||
PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st);
|
||||
PyObject *tuple = PyStackRef_AsPyObjectBorrow(tuple_st);
|
||||
|
||||
|
@ -929,7 +901,7 @@ dummy_func(
|
|||
DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub));
|
||||
Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0];
|
||||
DEOPT_IF(index >= PyTuple_GET_SIZE(tuple));
|
||||
STAT_INC(BINARY_SUBSCR, hit);
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
PyObject *res_o = PyTuple_GET_ITEM(tuple, index);
|
||||
assert(res_o != NULL);
|
||||
Py_INCREF(res_o);
|
||||
|
@ -939,12 +911,12 @@ dummy_func(
|
|||
res = PyStackRef_FromPyObjectSteal(res_o);
|
||||
}
|
||||
|
||||
inst(BINARY_SUBSCR_DICT, (unused/1, dict_st, sub_st -- res)) {
|
||||
inst(BINARY_OP_SUBSCR_DICT, (unused/5, dict_st, sub_st -- res)) {
|
||||
PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st);
|
||||
PyObject *dict = PyStackRef_AsPyObjectBorrow(dict_st);
|
||||
|
||||
DEOPT_IF(!PyDict_CheckExact(dict));
|
||||
STAT_INC(BINARY_SUBSCR, hit);
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
PyObject *res_o;
|
||||
int rc = PyDict_GetItemRef(dict, sub, &res_o);
|
||||
if (rc == 0) {
|
||||
|
@ -955,7 +927,7 @@ dummy_func(
|
|||
res = PyStackRef_FromPyObjectSteal(res_o);
|
||||
}
|
||||
|
||||
op(_BINARY_SUBSCR_CHECK_FUNC, (container, unused -- container, unused, getitem)) {
|
||||
op(_BINARY_OP_SUBSCR_CHECK_FUNC, (container, unused -- container, unused, getitem)) {
|
||||
PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(container));
|
||||
DEOPT_IF(!PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE));
|
||||
PyHeapTypeObject *ht = (PyHeapTypeObject *)tp;
|
||||
|
@ -968,10 +940,10 @@ dummy_func(
|
|||
assert(code->co_argcount == 2);
|
||||
DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize));
|
||||
getitem = PyStackRef_FromPyObjectNew(getitem_o);
|
||||
STAT_INC(BINARY_SUBSCR, hit);
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
}
|
||||
|
||||
op(_BINARY_SUBSCR_INIT_CALL, (container, sub, getitem -- new_frame: _PyInterpreterFrame* )) {
|
||||
op(_BINARY_OP_SUBSCR_INIT_CALL, (container, sub, getitem -- new_frame: _PyInterpreterFrame* )) {
|
||||
new_frame = _PyFrame_PushUnchecked(tstate, getitem, 2, frame);
|
||||
new_frame->localsplus[0] = container;
|
||||
new_frame->localsplus[1] = sub;
|
||||
|
@ -979,11 +951,11 @@ dummy_func(
|
|||
frame->return_offset = INSTRUCTION_SIZE;
|
||||
}
|
||||
|
||||
macro(BINARY_SUBSCR_GETITEM) =
|
||||
unused/1 + // Skip over the counter
|
||||
macro(BINARY_OP_SUBSCR_GETITEM) =
|
||||
unused/5 + // Skip over the counter and cache
|
||||
_CHECK_PEP_523 +
|
||||
_BINARY_SUBSCR_CHECK_FUNC +
|
||||
_BINARY_SUBSCR_INIT_CALL +
|
||||
_BINARY_OP_SUBSCR_CHECK_FUNC +
|
||||
_BINARY_OP_SUBSCR_INIT_CALL +
|
||||
_PUSH_FRAME;
|
||||
|
||||
inst(LIST_APPEND, (list, unused[oparg-1], v -- list, unused[oparg-1])) {
|
||||
|
@ -4816,7 +4788,7 @@ dummy_func(
|
|||
ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter);
|
||||
#endif /* ENABLE_SPECIALIZATION_FT */
|
||||
assert(NB_ADD <= oparg);
|
||||
assert(oparg <= NB_INPLACE_XOR);
|
||||
assert(oparg <= NB_OPARG_LAST);
|
||||
}
|
||||
|
||||
op(_BINARY_OP, (lhs, rhs -- res)) {
|
||||
|
|
|
@ -362,6 +362,7 @@ const binaryfunc _PyEval_BinaryOps[] = {
|
|||
[NB_INPLACE_SUBTRACT] = PyNumber_InPlaceSubtract,
|
||||
[NB_INPLACE_TRUE_DIVIDE] = PyNumber_InPlaceTrueDivide,
|
||||
[NB_INPLACE_XOR] = PyNumber_InPlaceXor,
|
||||
[NB_SUBSCR] = PyObject_GetItem,
|
||||
};
|
||||
|
||||
const conversion_func _PyEval_ConversionFuncs[4] = {
|
||||
|
|
|
@ -5076,7 +5076,7 @@ codegen_augassign(compiler *c, stmt_ty s)
|
|||
VISIT(c, expr, e->v.Subscript.slice);
|
||||
ADDOP_I(c, loc, COPY, 2);
|
||||
ADDOP_I(c, loc, COPY, 2);
|
||||
ADDOP(c, loc, BINARY_SUBSCR);
|
||||
ADDOP_I(c, loc, BINARY_OP, NB_SUBSCR);
|
||||
}
|
||||
break;
|
||||
case Name_kind:
|
||||
|
@ -5242,7 +5242,6 @@ codegen_subscript(compiler *c, expr_ty e)
|
|||
{
|
||||
location loc = LOC(e);
|
||||
expr_context_ty ctx = e->v.Subscript.ctx;
|
||||
int op = 0;
|
||||
|
||||
if (ctx == Load) {
|
||||
RETURN_IF_ERROR(check_subscripter(c, e->v.Subscript.value));
|
||||
|
@ -5265,12 +5264,16 @@ codegen_subscript(compiler *c, expr_ty e)
|
|||
else {
|
||||
VISIT(c, expr, e->v.Subscript.slice);
|
||||
switch (ctx) {
|
||||
case Load: op = BINARY_SUBSCR; break;
|
||||
case Store: op = STORE_SUBSCR; break;
|
||||
case Del: op = DELETE_SUBSCR; break;
|
||||
case Load:
|
||||
ADDOP_I(c, loc, BINARY_OP, NB_SUBSCR);
|
||||
break;
|
||||
case Store:
|
||||
ADDOP(c, loc, STORE_SUBSCR);
|
||||
break;
|
||||
case Del:
|
||||
ADDOP(c, loc, DELETE_SUBSCR);
|
||||
break;
|
||||
}
|
||||
assert(op);
|
||||
ADDOP(c, loc, op);
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
@ -5502,7 +5505,7 @@ pattern_helper_sequence_unpack(compiler *c, location loc,
|
|||
return SUCCESS;
|
||||
}
|
||||
|
||||
// Like pattern_helper_sequence_unpack, but uses BINARY_SUBSCR instead of
|
||||
// Like pattern_helper_sequence_unpack, but uses BINARY_OP/NB_SUBSCR instead of
|
||||
// UNPACK_SEQUENCE / UNPACK_EX. This is more efficient for patterns with a
|
||||
// starred wildcard like [first, *_] / [first, *_, last] / [*_, last] / etc.
|
||||
static int
|
||||
|
@ -5533,7 +5536,7 @@ pattern_helper_sequence_subscr(compiler *c, location loc,
|
|||
ADDOP_LOAD_CONST_NEW(c, loc, PyLong_FromSsize_t(size - i));
|
||||
ADDOP_BINARY(c, loc, Sub);
|
||||
}
|
||||
ADDOP(c, loc, BINARY_SUBSCR);
|
||||
ADDOP_I(c, loc, BINARY_OP, NB_SUBSCR);
|
||||
RETURN_IF_ERROR(codegen_pattern_subpattern(c, pattern, pc));
|
||||
}
|
||||
// Pop the subject, we're done with it:
|
||||
|
|
51
Python/executor_cases.c.h
generated
51
Python/executor_cases.c.h
generated
|
@ -1029,31 +1029,6 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _BINARY_SUBSCR: {
|
||||
_PyStackRef sub;
|
||||
_PyStackRef container;
|
||||
_PyStackRef res;
|
||||
sub = stack_pointer[-1];
|
||||
container = stack_pointer[-2];
|
||||
PyObject *container_o = PyStackRef_AsPyObjectBorrow(container);
|
||||
PyObject *sub_o = PyStackRef_AsPyObjectBorrow(sub);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyObject *res_o = PyObject_GetItem(container_o, sub_o);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
PyStackRef_CLOSE(container);
|
||||
PyStackRef_CLOSE(sub);
|
||||
if (res_o == NULL) {
|
||||
stack_pointer += -2;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
JUMP_TO_ERROR();
|
||||
}
|
||||
res = PyStackRef_FromPyObjectSteal(res_o);
|
||||
stack_pointer[-2] = res;
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
break;
|
||||
}
|
||||
|
||||
case _BINARY_SLICE: {
|
||||
_PyStackRef stop;
|
||||
_PyStackRef start;
|
||||
|
@ -1136,7 +1111,7 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _BINARY_SUBSCR_LIST_INT: {
|
||||
case _BINARY_OP_SUBSCR_LIST_INT: {
|
||||
_PyStackRef sub_st;
|
||||
_PyStackRef list_st;
|
||||
_PyStackRef res;
|
||||
|
@ -1166,13 +1141,13 @@
|
|||
UOP_STAT_INC(uopcode, miss);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
STAT_INC(BINARY_SUBSCR, hit);
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
#else
|
||||
if (index >= PyList_GET_SIZE(list)) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
STAT_INC(BINARY_SUBSCR, hit);
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
PyObject *res_o = PyList_GET_ITEM(list, index);
|
||||
assert(res_o != NULL);
|
||||
Py_INCREF(res_o);
|
||||
|
@ -1190,7 +1165,7 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _BINARY_SUBSCR_STR_INT: {
|
||||
case _BINARY_OP_SUBSCR_STR_INT: {
|
||||
_PyStackRef sub_st;
|
||||
_PyStackRef str_st;
|
||||
_PyStackRef res;
|
||||
|
@ -1221,7 +1196,7 @@
|
|||
UOP_STAT_INC(uopcode, miss);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
STAT_INC(BINARY_SUBSCR, hit);
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
PyObject *res_o = (PyObject*)&_Py_SINGLETON(strings).ascii[c];
|
||||
PyStackRef_CLOSE_SPECIALIZED(sub_st, _PyLong_ExactDealloc);
|
||||
stack_pointer += -2;
|
||||
|
@ -1236,7 +1211,7 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _BINARY_SUBSCR_TUPLE_INT: {
|
||||
case _BINARY_OP_SUBSCR_TUPLE_INT: {
|
||||
_PyStackRef sub_st;
|
||||
_PyStackRef tuple_st;
|
||||
_PyStackRef res;
|
||||
|
@ -1262,7 +1237,7 @@
|
|||
UOP_STAT_INC(uopcode, miss);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
STAT_INC(BINARY_SUBSCR, hit);
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
PyObject *res_o = PyTuple_GET_ITEM(tuple, index);
|
||||
assert(res_o != NULL);
|
||||
Py_INCREF(res_o);
|
||||
|
@ -1279,7 +1254,7 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _BINARY_SUBSCR_DICT: {
|
||||
case _BINARY_OP_SUBSCR_DICT: {
|
||||
_PyStackRef sub_st;
|
||||
_PyStackRef dict_st;
|
||||
_PyStackRef res;
|
||||
|
@ -1291,7 +1266,7 @@
|
|||
UOP_STAT_INC(uopcode, miss);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
STAT_INC(BINARY_SUBSCR, hit);
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
PyObject *res_o;
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
int rc = PyDict_GetItemRef(dict, sub, &res_o);
|
||||
|
@ -1316,7 +1291,7 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _BINARY_SUBSCR_CHECK_FUNC: {
|
||||
case _BINARY_OP_SUBSCR_CHECK_FUNC: {
|
||||
_PyStackRef container;
|
||||
_PyStackRef getitem;
|
||||
container = stack_pointer[-2];
|
||||
|
@ -1344,14 +1319,14 @@
|
|||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
getitem = PyStackRef_FromPyObjectNew(getitem_o);
|
||||
STAT_INC(BINARY_SUBSCR, hit);
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
stack_pointer[0] = getitem;
|
||||
stack_pointer += 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
break;
|
||||
}
|
||||
|
||||
case _BINARY_SUBSCR_INIT_CALL: {
|
||||
case _BINARY_OP_SUBSCR_INIT_CALL: {
|
||||
_PyStackRef getitem;
|
||||
_PyStackRef sub;
|
||||
_PyStackRef container;
|
||||
|
@ -1362,7 +1337,7 @@
|
|||
new_frame = _PyFrame_PushUnchecked(tstate, getitem, 2, frame);
|
||||
new_frame->localsplus[0] = container;
|
||||
new_frame->localsplus[1] = sub;
|
||||
frame->return_offset = 2 ;
|
||||
frame->return_offset = 6 ;
|
||||
stack_pointer[-3].bits = (uintptr_t)new_frame;
|
||||
stack_pointer += -2;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <stdbool.h>
|
||||
|
||||
#include "Python.h"
|
||||
#include "opcode.h"
|
||||
#include "pycore_flowgraph.h"
|
||||
#include "pycore_compile.h"
|
||||
#include "pycore_intrinsics.h"
|
||||
|
@ -1492,10 +1493,14 @@ newop_from_folded(PyObject *newconst, PyObject *consts,
|
|||
}
|
||||
|
||||
static int
|
||||
optimize_if_const_subscr(basicblock *bb, int n, PyObject *consts, PyObject *const_cache)
|
||||
optimize_if_const_op(basicblock *bb, int n, PyObject *consts, PyObject *const_cache)
|
||||
{
|
||||
cfg_instr *subscr = &bb->b_instr[n];
|
||||
assert(subscr->i_opcode == BINARY_SUBSCR);
|
||||
assert(subscr->i_opcode == BINARY_OP);
|
||||
if (subscr->i_oparg != NB_SUBSCR) {
|
||||
/* TODO: support other binary ops */
|
||||
return SUCCESS;
|
||||
}
|
||||
cfg_instr *arg, *idx;
|
||||
if (!find_load_const_pair(bb, n-1, &arg, &idx)) {
|
||||
return SUCCESS;
|
||||
|
@ -2033,8 +2038,8 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
|
|||
INSTR_SET_OP0(inst, NOP);
|
||||
}
|
||||
break;
|
||||
case BINARY_SUBSCR:
|
||||
RETURN_IF_ERROR(optimize_if_const_subscr(bb, i, consts, const_cache));
|
||||
case BINARY_OP:
|
||||
RETURN_IF_ERROR(optimize_if_const_op(bb, i, consts, const_cache));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
699
Python/generated_cases.c.h
generated
699
Python/generated_cases.c.h
generated
|
@ -50,7 +50,7 @@
|
|||
ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter);
|
||||
#endif /* ENABLE_SPECIALIZATION_FT */
|
||||
assert(NB_ADD <= oparg);
|
||||
assert(oparg <= NB_INPLACE_XOR);
|
||||
assert(oparg <= NB_OPARG_LAST);
|
||||
}
|
||||
/* Skip 4 cache entries */
|
||||
// _BINARY_OP
|
||||
|
@ -480,6 +480,328 @@
|
|||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(BINARY_OP_SUBSCR_DICT) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode = BINARY_OP_SUBSCR_DICT;
|
||||
(void)(opcode);
|
||||
#endif
|
||||
_Py_CODEUNIT* const this_instr = next_instr;
|
||||
(void)this_instr;
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 6;
|
||||
INSTRUCTION_STATS(BINARY_OP_SUBSCR_DICT);
|
||||
static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5, "incorrect cache size");
|
||||
_PyStackRef dict_st;
|
||||
_PyStackRef sub_st;
|
||||
_PyStackRef res;
|
||||
/* Skip 5 cache entries */
|
||||
sub_st = stack_pointer[-1];
|
||||
dict_st = stack_pointer[-2];
|
||||
PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st);
|
||||
PyObject *dict = PyStackRef_AsPyObjectBorrow(dict_st);
|
||||
if (!PyDict_CheckExact(dict)) {
|
||||
UPDATE_MISS_STATS(BINARY_OP);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_OP));
|
||||
JUMP_TO_PREDICTED(BINARY_OP);
|
||||
}
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
PyObject *res_o;
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
int rc = PyDict_GetItemRef(dict, sub, &res_o);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (rc == 0) {
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_PyErr_SetKeyError(sub);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
}
|
||||
PyStackRef_CLOSE(dict_st);
|
||||
PyStackRef_CLOSE(sub_st);
|
||||
if (rc <= 0) {
|
||||
JUMP_TO_LABEL(pop_2_error);
|
||||
}
|
||||
// not found or error
|
||||
res = PyStackRef_FromPyObjectSteal(res_o);
|
||||
stack_pointer[-2] = res;
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(BINARY_OP_SUBSCR_GETITEM) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode = BINARY_OP_SUBSCR_GETITEM;
|
||||
(void)(opcode);
|
||||
#endif
|
||||
_Py_CODEUNIT* const this_instr = next_instr;
|
||||
(void)this_instr;
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 6;
|
||||
INSTRUCTION_STATS(BINARY_OP_SUBSCR_GETITEM);
|
||||
static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5, "incorrect cache size");
|
||||
_PyStackRef container;
|
||||
_PyStackRef getitem;
|
||||
_PyStackRef sub;
|
||||
_PyInterpreterFrame *new_frame;
|
||||
/* Skip 5 cache entries */
|
||||
// _CHECK_PEP_523
|
||||
{
|
||||
if (tstate->interp->eval_frame) {
|
||||
UPDATE_MISS_STATS(BINARY_OP);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_OP));
|
||||
JUMP_TO_PREDICTED(BINARY_OP);
|
||||
}
|
||||
}
|
||||
// _BINARY_OP_SUBSCR_CHECK_FUNC
|
||||
{
|
||||
container = stack_pointer[-2];
|
||||
PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(container));
|
||||
if (!PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE)) {
|
||||
UPDATE_MISS_STATS(BINARY_OP);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_OP));
|
||||
JUMP_TO_PREDICTED(BINARY_OP);
|
||||
}
|
||||
PyHeapTypeObject *ht = (PyHeapTypeObject *)tp;
|
||||
PyObject *getitem_o = FT_ATOMIC_LOAD_PTR_ACQUIRE(ht->_spec_cache.getitem);
|
||||
if (getitem_o == NULL) {
|
||||
UPDATE_MISS_STATS(BINARY_OP);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_OP));
|
||||
JUMP_TO_PREDICTED(BINARY_OP);
|
||||
}
|
||||
assert(PyFunction_Check(getitem_o));
|
||||
uint32_t cached_version = FT_ATOMIC_LOAD_UINT32_RELAXED(ht->_spec_cache.getitem_version);
|
||||
if (((PyFunctionObject *)getitem_o)->func_version != cached_version) {
|
||||
UPDATE_MISS_STATS(BINARY_OP);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_OP));
|
||||
JUMP_TO_PREDICTED(BINARY_OP);
|
||||
}
|
||||
PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(getitem_o);
|
||||
assert(code->co_argcount == 2);
|
||||
if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) {
|
||||
UPDATE_MISS_STATS(BINARY_OP);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_OP));
|
||||
JUMP_TO_PREDICTED(BINARY_OP);
|
||||
}
|
||||
getitem = PyStackRef_FromPyObjectNew(getitem_o);
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
}
|
||||
// _BINARY_OP_SUBSCR_INIT_CALL
|
||||
{
|
||||
sub = stack_pointer[-1];
|
||||
new_frame = _PyFrame_PushUnchecked(tstate, getitem, 2, frame);
|
||||
new_frame->localsplus[0] = container;
|
||||
new_frame->localsplus[1] = sub;
|
||||
frame->return_offset = 6 ;
|
||||
}
|
||||
// _PUSH_FRAME
|
||||
{
|
||||
// Write it out explicitly because it's subtly different.
|
||||
// Eventually this should be the only occurrence of this code.
|
||||
assert(tstate->interp->eval_frame == NULL);
|
||||
_PyInterpreterFrame *temp = new_frame;
|
||||
stack_pointer += -2;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
assert(new_frame->previous == frame || new_frame->previous->previous == frame);
|
||||
CALL_STAT_INC(inlined_py_calls);
|
||||
frame = tstate->current_frame = temp;
|
||||
tstate->py_recursion_remaining--;
|
||||
LOAD_SP();
|
||||
LOAD_IP(0);
|
||||
LLTRACE_RESUME_FRAME();
|
||||
}
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(BINARY_OP_SUBSCR_LIST_INT) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode = BINARY_OP_SUBSCR_LIST_INT;
|
||||
(void)(opcode);
|
||||
#endif
|
||||
_Py_CODEUNIT* const this_instr = next_instr;
|
||||
(void)this_instr;
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 6;
|
||||
INSTRUCTION_STATS(BINARY_OP_SUBSCR_LIST_INT);
|
||||
static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5, "incorrect cache size");
|
||||
_PyStackRef list_st;
|
||||
_PyStackRef sub_st;
|
||||
_PyStackRef res;
|
||||
/* Skip 5 cache entries */
|
||||
sub_st = stack_pointer[-1];
|
||||
list_st = stack_pointer[-2];
|
||||
PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st);
|
||||
PyObject *list = PyStackRef_AsPyObjectBorrow(list_st);
|
||||
if (!PyLong_CheckExact(sub)) {
|
||||
UPDATE_MISS_STATS(BINARY_OP);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_OP));
|
||||
JUMP_TO_PREDICTED(BINARY_OP);
|
||||
}
|
||||
if (!PyList_CheckExact(list)) {
|
||||
UPDATE_MISS_STATS(BINARY_OP);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_OP));
|
||||
JUMP_TO_PREDICTED(BINARY_OP);
|
||||
}
|
||||
// Deopt unless 0 <= sub < PyList_Size(list)
|
||||
if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) {
|
||||
UPDATE_MISS_STATS(BINARY_OP);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_OP));
|
||||
JUMP_TO_PREDICTED(BINARY_OP);
|
||||
}
|
||||
Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0];
|
||||
#ifdef Py_GIL_DISABLED
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyObject *res_o = _PyList_GetItemRef((PyListObject*)list, index);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (res_o == NULL) {
|
||||
UPDATE_MISS_STATS(BINARY_OP);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_OP));
|
||||
JUMP_TO_PREDICTED(BINARY_OP);
|
||||
}
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
#else
|
||||
if (index >= PyList_GET_SIZE(list)) {
|
||||
UPDATE_MISS_STATS(BINARY_OP);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_OP));
|
||||
JUMP_TO_PREDICTED(BINARY_OP);
|
||||
}
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
PyObject *res_o = PyList_GET_ITEM(list, index);
|
||||
assert(res_o != NULL);
|
||||
Py_INCREF(res_o);
|
||||
#endif
|
||||
PyStackRef_CLOSE_SPECIALIZED(sub_st, _PyLong_ExactDealloc);
|
||||
stack_pointer += -2;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyStackRef_CLOSE(list_st);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
res = PyStackRef_FromPyObjectSteal(res_o);
|
||||
stack_pointer[0] = res;
|
||||
stack_pointer += 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(BINARY_OP_SUBSCR_STR_INT) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode = BINARY_OP_SUBSCR_STR_INT;
|
||||
(void)(opcode);
|
||||
#endif
|
||||
_Py_CODEUNIT* const this_instr = next_instr;
|
||||
(void)this_instr;
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 6;
|
||||
INSTRUCTION_STATS(BINARY_OP_SUBSCR_STR_INT);
|
||||
static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5, "incorrect cache size");
|
||||
_PyStackRef str_st;
|
||||
_PyStackRef sub_st;
|
||||
_PyStackRef res;
|
||||
/* Skip 5 cache entries */
|
||||
sub_st = stack_pointer[-1];
|
||||
str_st = stack_pointer[-2];
|
||||
PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st);
|
||||
PyObject *str = PyStackRef_AsPyObjectBorrow(str_st);
|
||||
if (!PyLong_CheckExact(sub)) {
|
||||
UPDATE_MISS_STATS(BINARY_OP);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_OP));
|
||||
JUMP_TO_PREDICTED(BINARY_OP);
|
||||
}
|
||||
if (!PyUnicode_CheckExact(str)) {
|
||||
UPDATE_MISS_STATS(BINARY_OP);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_OP));
|
||||
JUMP_TO_PREDICTED(BINARY_OP);
|
||||
}
|
||||
if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) {
|
||||
UPDATE_MISS_STATS(BINARY_OP);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_OP));
|
||||
JUMP_TO_PREDICTED(BINARY_OP);
|
||||
}
|
||||
Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0];
|
||||
if (PyUnicode_GET_LENGTH(str) <= index) {
|
||||
UPDATE_MISS_STATS(BINARY_OP);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_OP));
|
||||
JUMP_TO_PREDICTED(BINARY_OP);
|
||||
}
|
||||
// Specialize for reading an ASCII character from any string:
|
||||
Py_UCS4 c = PyUnicode_READ_CHAR(str, index);
|
||||
if (Py_ARRAY_LENGTH(_Py_SINGLETON(strings).ascii) <= c) {
|
||||
UPDATE_MISS_STATS(BINARY_OP);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_OP));
|
||||
JUMP_TO_PREDICTED(BINARY_OP);
|
||||
}
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
PyObject *res_o = (PyObject*)&_Py_SINGLETON(strings).ascii[c];
|
||||
PyStackRef_CLOSE_SPECIALIZED(sub_st, _PyLong_ExactDealloc);
|
||||
stack_pointer += -2;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyStackRef_CLOSE(str_st);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
res = PyStackRef_FromPyObjectSteal(res_o);
|
||||
stack_pointer[0] = res;
|
||||
stack_pointer += 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(BINARY_OP_SUBSCR_TUPLE_INT) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode = BINARY_OP_SUBSCR_TUPLE_INT;
|
||||
(void)(opcode);
|
||||
#endif
|
||||
_Py_CODEUNIT* const this_instr = next_instr;
|
||||
(void)this_instr;
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 6;
|
||||
INSTRUCTION_STATS(BINARY_OP_SUBSCR_TUPLE_INT);
|
||||
static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5, "incorrect cache size");
|
||||
_PyStackRef tuple_st;
|
||||
_PyStackRef sub_st;
|
||||
_PyStackRef res;
|
||||
/* Skip 5 cache entries */
|
||||
sub_st = stack_pointer[-1];
|
||||
tuple_st = stack_pointer[-2];
|
||||
PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st);
|
||||
PyObject *tuple = PyStackRef_AsPyObjectBorrow(tuple_st);
|
||||
if (!PyLong_CheckExact(sub)) {
|
||||
UPDATE_MISS_STATS(BINARY_OP);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_OP));
|
||||
JUMP_TO_PREDICTED(BINARY_OP);
|
||||
}
|
||||
if (!PyTuple_CheckExact(tuple)) {
|
||||
UPDATE_MISS_STATS(BINARY_OP);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_OP));
|
||||
JUMP_TO_PREDICTED(BINARY_OP);
|
||||
}
|
||||
// Deopt unless 0 <= sub < PyTuple_Size(list)
|
||||
if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) {
|
||||
UPDATE_MISS_STATS(BINARY_OP);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_OP));
|
||||
JUMP_TO_PREDICTED(BINARY_OP);
|
||||
}
|
||||
Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0];
|
||||
if (index >= PyTuple_GET_SIZE(tuple)) {
|
||||
UPDATE_MISS_STATS(BINARY_OP);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_OP));
|
||||
JUMP_TO_PREDICTED(BINARY_OP);
|
||||
}
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
PyObject *res_o = PyTuple_GET_ITEM(tuple, index);
|
||||
assert(res_o != NULL);
|
||||
Py_INCREF(res_o);
|
||||
PyStackRef_CLOSE_SPECIALIZED(sub_st, _PyLong_ExactDealloc);
|
||||
stack_pointer += -2;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyStackRef_CLOSE(tuple_st);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
res = PyStackRef_FromPyObjectSteal(res_o);
|
||||
stack_pointer[0] = res;
|
||||
stack_pointer += 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(BINARY_OP_SUBTRACT_FLOAT) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode = BINARY_OP_SUBTRACT_FLOAT;
|
||||
|
@ -647,381 +969,6 @@
|
|||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(BINARY_SUBSCR) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode = BINARY_SUBSCR;
|
||||
(void)(opcode);
|
||||
#endif
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 2;
|
||||
INSTRUCTION_STATS(BINARY_SUBSCR);
|
||||
PREDICTED_BINARY_SUBSCR:;
|
||||
_Py_CODEUNIT* const this_instr = next_instr - 2;
|
||||
(void)this_instr;
|
||||
_PyStackRef container;
|
||||
_PyStackRef sub;
|
||||
_PyStackRef res;
|
||||
// _SPECIALIZE_BINARY_SUBSCR
|
||||
{
|
||||
sub = stack_pointer[-1];
|
||||
container = stack_pointer[-2];
|
||||
uint16_t counter = read_u16(&this_instr[1].cache);
|
||||
(void)counter;
|
||||
#if ENABLE_SPECIALIZATION_FT
|
||||
assert(frame->stackpointer == NULL);
|
||||
if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
|
||||
next_instr = this_instr;
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_Py_Specialize_BinarySubscr(container, sub, next_instr);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
DISPATCH_SAME_OPARG();
|
||||
}
|
||||
OPCODE_DEFERRED_INC(BINARY_SUBSCR);
|
||||
ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter);
|
||||
#endif /* ENABLE_SPECIALIZATION_FT */
|
||||
}
|
||||
// _BINARY_SUBSCR
|
||||
{
|
||||
PyObject *container_o = PyStackRef_AsPyObjectBorrow(container);
|
||||
PyObject *sub_o = PyStackRef_AsPyObjectBorrow(sub);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyObject *res_o = PyObject_GetItem(container_o, sub_o);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
PyStackRef_CLOSE(container);
|
||||
PyStackRef_CLOSE(sub);
|
||||
if (res_o == NULL) {
|
||||
JUMP_TO_LABEL(pop_2_error);
|
||||
}
|
||||
res = PyStackRef_FromPyObjectSteal(res_o);
|
||||
}
|
||||
stack_pointer[-2] = res;
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(BINARY_SUBSCR_DICT) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode = BINARY_SUBSCR_DICT;
|
||||
(void)(opcode);
|
||||
#endif
|
||||
_Py_CODEUNIT* const this_instr = next_instr;
|
||||
(void)this_instr;
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 2;
|
||||
INSTRUCTION_STATS(BINARY_SUBSCR_DICT);
|
||||
static_assert(INLINE_CACHE_ENTRIES_BINARY_SUBSCR == 1, "incorrect cache size");
|
||||
_PyStackRef dict_st;
|
||||
_PyStackRef sub_st;
|
||||
_PyStackRef res;
|
||||
/* Skip 1 cache entry */
|
||||
sub_st = stack_pointer[-1];
|
||||
dict_st = stack_pointer[-2];
|
||||
PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st);
|
||||
PyObject *dict = PyStackRef_AsPyObjectBorrow(dict_st);
|
||||
if (!PyDict_CheckExact(dict)) {
|
||||
UPDATE_MISS_STATS(BINARY_SUBSCR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_SUBSCR));
|
||||
JUMP_TO_PREDICTED(BINARY_SUBSCR);
|
||||
}
|
||||
STAT_INC(BINARY_SUBSCR, hit);
|
||||
PyObject *res_o;
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
int rc = PyDict_GetItemRef(dict, sub, &res_o);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (rc == 0) {
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_PyErr_SetKeyError(sub);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
}
|
||||
PyStackRef_CLOSE(dict_st);
|
||||
PyStackRef_CLOSE(sub_st);
|
||||
if (rc <= 0) {
|
||||
JUMP_TO_LABEL(pop_2_error);
|
||||
}
|
||||
// not found or error
|
||||
res = PyStackRef_FromPyObjectSteal(res_o);
|
||||
stack_pointer[-2] = res;
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(BINARY_SUBSCR_GETITEM) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode = BINARY_SUBSCR_GETITEM;
|
||||
(void)(opcode);
|
||||
#endif
|
||||
_Py_CODEUNIT* const this_instr = next_instr;
|
||||
(void)this_instr;
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 2;
|
||||
INSTRUCTION_STATS(BINARY_SUBSCR_GETITEM);
|
||||
static_assert(INLINE_CACHE_ENTRIES_BINARY_SUBSCR == 1, "incorrect cache size");
|
||||
_PyStackRef container;
|
||||
_PyStackRef getitem;
|
||||
_PyStackRef sub;
|
||||
_PyInterpreterFrame *new_frame;
|
||||
/* Skip 1 cache entry */
|
||||
// _CHECK_PEP_523
|
||||
{
|
||||
if (tstate->interp->eval_frame) {
|
||||
UPDATE_MISS_STATS(BINARY_SUBSCR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_SUBSCR));
|
||||
JUMP_TO_PREDICTED(BINARY_SUBSCR);
|
||||
}
|
||||
}
|
||||
// _BINARY_SUBSCR_CHECK_FUNC
|
||||
{
|
||||
container = stack_pointer[-2];
|
||||
PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(container));
|
||||
if (!PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE)) {
|
||||
UPDATE_MISS_STATS(BINARY_SUBSCR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_SUBSCR));
|
||||
JUMP_TO_PREDICTED(BINARY_SUBSCR);
|
||||
}
|
||||
PyHeapTypeObject *ht = (PyHeapTypeObject *)tp;
|
||||
PyObject *getitem_o = FT_ATOMIC_LOAD_PTR_ACQUIRE(ht->_spec_cache.getitem);
|
||||
if (getitem_o == NULL) {
|
||||
UPDATE_MISS_STATS(BINARY_SUBSCR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_SUBSCR));
|
||||
JUMP_TO_PREDICTED(BINARY_SUBSCR);
|
||||
}
|
||||
assert(PyFunction_Check(getitem_o));
|
||||
uint32_t cached_version = FT_ATOMIC_LOAD_UINT32_RELAXED(ht->_spec_cache.getitem_version);
|
||||
if (((PyFunctionObject *)getitem_o)->func_version != cached_version) {
|
||||
UPDATE_MISS_STATS(BINARY_SUBSCR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_SUBSCR));
|
||||
JUMP_TO_PREDICTED(BINARY_SUBSCR);
|
||||
}
|
||||
PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(getitem_o);
|
||||
assert(code->co_argcount == 2);
|
||||
if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) {
|
||||
UPDATE_MISS_STATS(BINARY_SUBSCR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_SUBSCR));
|
||||
JUMP_TO_PREDICTED(BINARY_SUBSCR);
|
||||
}
|
||||
getitem = PyStackRef_FromPyObjectNew(getitem_o);
|
||||
STAT_INC(BINARY_SUBSCR, hit);
|
||||
}
|
||||
// _BINARY_SUBSCR_INIT_CALL
|
||||
{
|
||||
sub = stack_pointer[-1];
|
||||
new_frame = _PyFrame_PushUnchecked(tstate, getitem, 2, frame);
|
||||
new_frame->localsplus[0] = container;
|
||||
new_frame->localsplus[1] = sub;
|
||||
frame->return_offset = 2 ;
|
||||
}
|
||||
// _PUSH_FRAME
|
||||
{
|
||||
// Write it out explicitly because it's subtly different.
|
||||
// Eventually this should be the only occurrence of this code.
|
||||
assert(tstate->interp->eval_frame == NULL);
|
||||
_PyInterpreterFrame *temp = new_frame;
|
||||
stack_pointer += -2;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
assert(new_frame->previous == frame || new_frame->previous->previous == frame);
|
||||
CALL_STAT_INC(inlined_py_calls);
|
||||
frame = tstate->current_frame = temp;
|
||||
tstate->py_recursion_remaining--;
|
||||
LOAD_SP();
|
||||
LOAD_IP(0);
|
||||
LLTRACE_RESUME_FRAME();
|
||||
}
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(BINARY_SUBSCR_LIST_INT) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode = BINARY_SUBSCR_LIST_INT;
|
||||
(void)(opcode);
|
||||
#endif
|
||||
_Py_CODEUNIT* const this_instr = next_instr;
|
||||
(void)this_instr;
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 2;
|
||||
INSTRUCTION_STATS(BINARY_SUBSCR_LIST_INT);
|
||||
static_assert(INLINE_CACHE_ENTRIES_BINARY_SUBSCR == 1, "incorrect cache size");
|
||||
_PyStackRef list_st;
|
||||
_PyStackRef sub_st;
|
||||
_PyStackRef res;
|
||||
/* Skip 1 cache entry */
|
||||
sub_st = stack_pointer[-1];
|
||||
list_st = stack_pointer[-2];
|
||||
PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st);
|
||||
PyObject *list = PyStackRef_AsPyObjectBorrow(list_st);
|
||||
if (!PyLong_CheckExact(sub)) {
|
||||
UPDATE_MISS_STATS(BINARY_SUBSCR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_SUBSCR));
|
||||
JUMP_TO_PREDICTED(BINARY_SUBSCR);
|
||||
}
|
||||
if (!PyList_CheckExact(list)) {
|
||||
UPDATE_MISS_STATS(BINARY_SUBSCR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_SUBSCR));
|
||||
JUMP_TO_PREDICTED(BINARY_SUBSCR);
|
||||
}
|
||||
// Deopt unless 0 <= sub < PyList_Size(list)
|
||||
if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) {
|
||||
UPDATE_MISS_STATS(BINARY_SUBSCR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_SUBSCR));
|
||||
JUMP_TO_PREDICTED(BINARY_SUBSCR);
|
||||
}
|
||||
Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0];
|
||||
#ifdef Py_GIL_DISABLED
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyObject *res_o = _PyList_GetItemRef((PyListObject*)list, index);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (res_o == NULL) {
|
||||
UPDATE_MISS_STATS(BINARY_SUBSCR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_SUBSCR));
|
||||
JUMP_TO_PREDICTED(BINARY_SUBSCR);
|
||||
}
|
||||
STAT_INC(BINARY_SUBSCR, hit);
|
||||
#else
|
||||
if (index >= PyList_GET_SIZE(list)) {
|
||||
UPDATE_MISS_STATS(BINARY_SUBSCR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_SUBSCR));
|
||||
JUMP_TO_PREDICTED(BINARY_SUBSCR);
|
||||
}
|
||||
STAT_INC(BINARY_SUBSCR, hit);
|
||||
PyObject *res_o = PyList_GET_ITEM(list, index);
|
||||
assert(res_o != NULL);
|
||||
Py_INCREF(res_o);
|
||||
#endif
|
||||
PyStackRef_CLOSE_SPECIALIZED(sub_st, _PyLong_ExactDealloc);
|
||||
stack_pointer += -2;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyStackRef_CLOSE(list_st);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
res = PyStackRef_FromPyObjectSteal(res_o);
|
||||
stack_pointer[0] = res;
|
||||
stack_pointer += 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(BINARY_SUBSCR_STR_INT) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode = BINARY_SUBSCR_STR_INT;
|
||||
(void)(opcode);
|
||||
#endif
|
||||
_Py_CODEUNIT* const this_instr = next_instr;
|
||||
(void)this_instr;
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 2;
|
||||
INSTRUCTION_STATS(BINARY_SUBSCR_STR_INT);
|
||||
static_assert(INLINE_CACHE_ENTRIES_BINARY_SUBSCR == 1, "incorrect cache size");
|
||||
_PyStackRef str_st;
|
||||
_PyStackRef sub_st;
|
||||
_PyStackRef res;
|
||||
/* Skip 1 cache entry */
|
||||
sub_st = stack_pointer[-1];
|
||||
str_st = stack_pointer[-2];
|
||||
PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st);
|
||||
PyObject *str = PyStackRef_AsPyObjectBorrow(str_st);
|
||||
if (!PyLong_CheckExact(sub)) {
|
||||
UPDATE_MISS_STATS(BINARY_SUBSCR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_SUBSCR));
|
||||
JUMP_TO_PREDICTED(BINARY_SUBSCR);
|
||||
}
|
||||
if (!PyUnicode_CheckExact(str)) {
|
||||
UPDATE_MISS_STATS(BINARY_SUBSCR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_SUBSCR));
|
||||
JUMP_TO_PREDICTED(BINARY_SUBSCR);
|
||||
}
|
||||
if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) {
|
||||
UPDATE_MISS_STATS(BINARY_SUBSCR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_SUBSCR));
|
||||
JUMP_TO_PREDICTED(BINARY_SUBSCR);
|
||||
}
|
||||
Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0];
|
||||
if (PyUnicode_GET_LENGTH(str) <= index) {
|
||||
UPDATE_MISS_STATS(BINARY_SUBSCR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_SUBSCR));
|
||||
JUMP_TO_PREDICTED(BINARY_SUBSCR);
|
||||
}
|
||||
// Specialize for reading an ASCII character from any string:
|
||||
Py_UCS4 c = PyUnicode_READ_CHAR(str, index);
|
||||
if (Py_ARRAY_LENGTH(_Py_SINGLETON(strings).ascii) <= c) {
|
||||
UPDATE_MISS_STATS(BINARY_SUBSCR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_SUBSCR));
|
||||
JUMP_TO_PREDICTED(BINARY_SUBSCR);
|
||||
}
|
||||
STAT_INC(BINARY_SUBSCR, hit);
|
||||
PyObject *res_o = (PyObject*)&_Py_SINGLETON(strings).ascii[c];
|
||||
PyStackRef_CLOSE_SPECIALIZED(sub_st, _PyLong_ExactDealloc);
|
||||
stack_pointer += -2;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyStackRef_CLOSE(str_st);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
res = PyStackRef_FromPyObjectSteal(res_o);
|
||||
stack_pointer[0] = res;
|
||||
stack_pointer += 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(BINARY_SUBSCR_TUPLE_INT) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode = BINARY_SUBSCR_TUPLE_INT;
|
||||
(void)(opcode);
|
||||
#endif
|
||||
_Py_CODEUNIT* const this_instr = next_instr;
|
||||
(void)this_instr;
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 2;
|
||||
INSTRUCTION_STATS(BINARY_SUBSCR_TUPLE_INT);
|
||||
static_assert(INLINE_CACHE_ENTRIES_BINARY_SUBSCR == 1, "incorrect cache size");
|
||||
_PyStackRef tuple_st;
|
||||
_PyStackRef sub_st;
|
||||
_PyStackRef res;
|
||||
/* Skip 1 cache entry */
|
||||
sub_st = stack_pointer[-1];
|
||||
tuple_st = stack_pointer[-2];
|
||||
PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st);
|
||||
PyObject *tuple = PyStackRef_AsPyObjectBorrow(tuple_st);
|
||||
if (!PyLong_CheckExact(sub)) {
|
||||
UPDATE_MISS_STATS(BINARY_SUBSCR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_SUBSCR));
|
||||
JUMP_TO_PREDICTED(BINARY_SUBSCR);
|
||||
}
|
||||
if (!PyTuple_CheckExact(tuple)) {
|
||||
UPDATE_MISS_STATS(BINARY_SUBSCR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_SUBSCR));
|
||||
JUMP_TO_PREDICTED(BINARY_SUBSCR);
|
||||
}
|
||||
// Deopt unless 0 <= sub < PyTuple_Size(list)
|
||||
if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) {
|
||||
UPDATE_MISS_STATS(BINARY_SUBSCR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_SUBSCR));
|
||||
JUMP_TO_PREDICTED(BINARY_SUBSCR);
|
||||
}
|
||||
Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0];
|
||||
if (index >= PyTuple_GET_SIZE(tuple)) {
|
||||
UPDATE_MISS_STATS(BINARY_SUBSCR);
|
||||
assert(_PyOpcode_Deopt[opcode] == (BINARY_SUBSCR));
|
||||
JUMP_TO_PREDICTED(BINARY_SUBSCR);
|
||||
}
|
||||
STAT_INC(BINARY_SUBSCR, hit);
|
||||
PyObject *res_o = PyTuple_GET_ITEM(tuple, index);
|
||||
assert(res_o != NULL);
|
||||
Py_INCREF(res_o);
|
||||
PyStackRef_CLOSE_SPECIALIZED(sub_st, _PyLong_ExactDealloc);
|
||||
stack_pointer += -2;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyStackRef_CLOSE(tuple_st);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
res = PyStackRef_FromPyObjectSteal(res_o);
|
||||
stack_pointer[0] = res;
|
||||
stack_pointer += 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(BUILD_LIST) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode = BUILD_LIST;
|
||||
|
|
39
Python/opcode_targets.h
generated
39
Python/opcode_targets.h
generated
|
@ -2,9 +2,8 @@
|
|||
static void *opcode_targets[256] = {
|
||||
&&TARGET_CACHE,
|
||||
&&TARGET_BINARY_SLICE,
|
||||
&&TARGET_BINARY_SUBSCR,
|
||||
&&TARGET_BINARY_OP_INPLACE_ADD_UNICODE,
|
||||
&&TARGET_CALL_FUNCTION_EX,
|
||||
&&TARGET_BINARY_OP_INPLACE_ADD_UNICODE,
|
||||
&&TARGET_CHECK_EG_MATCH,
|
||||
&&TARGET_CHECK_EXC_MATCH,
|
||||
&&TARGET_CLEANUP_THROW,
|
||||
|
@ -17,8 +16,8 @@ static void *opcode_targets[256] = {
|
|||
&&TARGET_FORMAT_WITH_SPEC,
|
||||
&&TARGET_GET_AITER,
|
||||
&&TARGET_GET_ANEXT,
|
||||
&&TARGET_RESERVED,
|
||||
&&TARGET_GET_ITER,
|
||||
&&TARGET_RESERVED,
|
||||
&&TARGET_GET_LEN,
|
||||
&&TARGET_GET_YIELD_FROM_ITER,
|
||||
&&TARGET_INTERPRETER_EXIT,
|
||||
|
@ -149,6 +148,7 @@ static void *opcode_targets[256] = {
|
|||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_RESUME,
|
||||
&&TARGET_BINARY_OP_ADD_FLOAT,
|
||||
&&TARGET_BINARY_OP_ADD_INT,
|
||||
|
@ -156,13 +156,13 @@ static void *opcode_targets[256] = {
|
|||
&&TARGET_BINARY_OP_EXTEND,
|
||||
&&TARGET_BINARY_OP_MULTIPLY_FLOAT,
|
||||
&&TARGET_BINARY_OP_MULTIPLY_INT,
|
||||
&&TARGET_BINARY_OP_SUBSCR_DICT,
|
||||
&&TARGET_BINARY_OP_SUBSCR_GETITEM,
|
||||
&&TARGET_BINARY_OP_SUBSCR_LIST_INT,
|
||||
&&TARGET_BINARY_OP_SUBSCR_STR_INT,
|
||||
&&TARGET_BINARY_OP_SUBSCR_TUPLE_INT,
|
||||
&&TARGET_BINARY_OP_SUBTRACT_FLOAT,
|
||||
&&TARGET_BINARY_OP_SUBTRACT_INT,
|
||||
&&TARGET_BINARY_SUBSCR_DICT,
|
||||
&&TARGET_BINARY_SUBSCR_GETITEM,
|
||||
&&TARGET_BINARY_SUBSCR_LIST_INT,
|
||||
&&TARGET_BINARY_SUBSCR_STR_INT,
|
||||
&&TARGET_BINARY_SUBSCR_TUPLE_INT,
|
||||
&&TARGET_CALL_ALLOC_AND_ENTER_INIT,
|
||||
&&TARGET_CALL_BOUND_METHOD_EXACT_ARGS,
|
||||
&&TARGET_CALL_BOUND_METHOD_GENERAL,
|
||||
|
@ -277,15 +277,14 @@ Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_OP_EXTEND(TAIL_CALL_PARAM
|
|||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_OP_INPLACE_ADD_UNICODE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_OP_MULTIPLY_FLOAT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_OP_MULTIPLY_INT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_OP_SUBSCR_DICT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_OP_SUBSCR_GETITEM(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_OP_SUBSCR_LIST_INT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_OP_SUBSCR_STR_INT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_OP_SUBSCR_TUPLE_INT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_OP_SUBTRACT_FLOAT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_OP_SUBTRACT_INT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_SLICE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_SUBSCR(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_SUBSCR_DICT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_SUBSCR_GETITEM(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_SUBSCR_LIST_INT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_SUBSCR_STR_INT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_SUBSCR_TUPLE_INT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BUILD_LIST(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BUILD_MAP(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BUILD_SET(TAIL_CALL_PARAMS);
|
||||
|
@ -511,15 +510,14 @@ static py_tail_call_funcptr INSTRUCTION_TABLE[256] = {
|
|||
[BINARY_OP_INPLACE_ADD_UNICODE] = _TAIL_CALL_BINARY_OP_INPLACE_ADD_UNICODE,
|
||||
[BINARY_OP_MULTIPLY_FLOAT] = _TAIL_CALL_BINARY_OP_MULTIPLY_FLOAT,
|
||||
[BINARY_OP_MULTIPLY_INT] = _TAIL_CALL_BINARY_OP_MULTIPLY_INT,
|
||||
[BINARY_OP_SUBSCR_DICT] = _TAIL_CALL_BINARY_OP_SUBSCR_DICT,
|
||||
[BINARY_OP_SUBSCR_GETITEM] = _TAIL_CALL_BINARY_OP_SUBSCR_GETITEM,
|
||||
[BINARY_OP_SUBSCR_LIST_INT] = _TAIL_CALL_BINARY_OP_SUBSCR_LIST_INT,
|
||||
[BINARY_OP_SUBSCR_STR_INT] = _TAIL_CALL_BINARY_OP_SUBSCR_STR_INT,
|
||||
[BINARY_OP_SUBSCR_TUPLE_INT] = _TAIL_CALL_BINARY_OP_SUBSCR_TUPLE_INT,
|
||||
[BINARY_OP_SUBTRACT_FLOAT] = _TAIL_CALL_BINARY_OP_SUBTRACT_FLOAT,
|
||||
[BINARY_OP_SUBTRACT_INT] = _TAIL_CALL_BINARY_OP_SUBTRACT_INT,
|
||||
[BINARY_SLICE] = _TAIL_CALL_BINARY_SLICE,
|
||||
[BINARY_SUBSCR] = _TAIL_CALL_BINARY_SUBSCR,
|
||||
[BINARY_SUBSCR_DICT] = _TAIL_CALL_BINARY_SUBSCR_DICT,
|
||||
[BINARY_SUBSCR_GETITEM] = _TAIL_CALL_BINARY_SUBSCR_GETITEM,
|
||||
[BINARY_SUBSCR_LIST_INT] = _TAIL_CALL_BINARY_SUBSCR_LIST_INT,
|
||||
[BINARY_SUBSCR_STR_INT] = _TAIL_CALL_BINARY_SUBSCR_STR_INT,
|
||||
[BINARY_SUBSCR_TUPLE_INT] = _TAIL_CALL_BINARY_SUBSCR_TUPLE_INT,
|
||||
[BUILD_LIST] = _TAIL_CALL_BUILD_LIST,
|
||||
[BUILD_MAP] = _TAIL_CALL_BUILD_MAP,
|
||||
[BUILD_SET] = _TAIL_CALL_BUILD_SET,
|
||||
|
@ -725,6 +723,7 @@ static py_tail_call_funcptr INSTRUCTION_TABLE[256] = {
|
|||
[UNPACK_SEQUENCE_TWO_TUPLE] = _TAIL_CALL_UNPACK_SEQUENCE_TWO_TUPLE,
|
||||
[WITH_EXCEPT_START] = _TAIL_CALL_WITH_EXCEPT_START,
|
||||
[YIELD_VALUE] = _TAIL_CALL_YIELD_VALUE,
|
||||
[117] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[118] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[119] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[120] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
|
|
|
@ -753,7 +753,7 @@ translate_bytecode_to_trace(
|
|||
assert(i + 1 == nuops);
|
||||
if (opcode == FOR_ITER_GEN ||
|
||||
opcode == LOAD_ATTR_PROPERTY ||
|
||||
opcode == BINARY_SUBSCR_GETITEM ||
|
||||
opcode == BINARY_OP_SUBSCR_GETITEM ||
|
||||
opcode == SEND_GEN)
|
||||
{
|
||||
DPRINTF(2, "Bailing due to dynamic target\n");
|
||||
|
|
|
@ -384,7 +384,7 @@ dummy_func(void) {
|
|||
GETLOCAL(this_instr->operand0) = res;
|
||||
}
|
||||
|
||||
op(_BINARY_SUBSCR_INIT_CALL, (container, sub, getitem -- new_frame: _Py_UOpsAbstractFrame *)) {
|
||||
op(_BINARY_OP_SUBSCR_INIT_CALL, (container, sub, getitem -- new_frame: _Py_UOpsAbstractFrame *)) {
|
||||
new_frame = NULL;
|
||||
ctx->done = true;
|
||||
}
|
||||
|
|
21
Python/optimizer_cases.c.h
generated
21
Python/optimizer_cases.c.h
generated
|
@ -575,15 +575,6 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _BINARY_SUBSCR: {
|
||||
JitOptSymbol *res;
|
||||
res = sym_new_not_null(ctx);
|
||||
stack_pointer[-2] = res;
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
break;
|
||||
}
|
||||
|
||||
case _BINARY_SLICE: {
|
||||
JitOptSymbol *res;
|
||||
res = sym_new_not_null(ctx);
|
||||
|
@ -599,7 +590,7 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _BINARY_SUBSCR_LIST_INT: {
|
||||
case _BINARY_OP_SUBSCR_LIST_INT: {
|
||||
JitOptSymbol *res;
|
||||
res = sym_new_not_null(ctx);
|
||||
stack_pointer[-2] = res;
|
||||
|
@ -608,7 +599,7 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _BINARY_SUBSCR_STR_INT: {
|
||||
case _BINARY_OP_SUBSCR_STR_INT: {
|
||||
JitOptSymbol *res;
|
||||
res = sym_new_not_null(ctx);
|
||||
stack_pointer[-2] = res;
|
||||
|
@ -617,7 +608,7 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _BINARY_SUBSCR_TUPLE_INT: {
|
||||
case _BINARY_OP_SUBSCR_TUPLE_INT: {
|
||||
JitOptSymbol *res;
|
||||
res = sym_new_not_null(ctx);
|
||||
stack_pointer[-2] = res;
|
||||
|
@ -626,7 +617,7 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _BINARY_SUBSCR_DICT: {
|
||||
case _BINARY_OP_SUBSCR_DICT: {
|
||||
JitOptSymbol *res;
|
||||
res = sym_new_not_null(ctx);
|
||||
stack_pointer[-2] = res;
|
||||
|
@ -635,7 +626,7 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _BINARY_SUBSCR_CHECK_FUNC: {
|
||||
case _BINARY_OP_SUBSCR_CHECK_FUNC: {
|
||||
JitOptSymbol *getitem;
|
||||
getitem = sym_new_not_null(ctx);
|
||||
stack_pointer[0] = getitem;
|
||||
|
@ -644,7 +635,7 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _BINARY_SUBSCR_INIT_CALL: {
|
||||
case _BINARY_OP_SUBSCR_INIT_CALL: {
|
||||
_Py_UOpsAbstractFrame *new_frame;
|
||||
new_frame = NULL;
|
||||
ctx->done = true;
|
||||
|
|
|
@ -113,7 +113,6 @@ _Py_GetSpecializationStats(void) {
|
|||
err += add_stat_dict(stats, LOAD_SUPER_ATTR, "load_super_attr");
|
||||
err += add_stat_dict(stats, LOAD_ATTR, "load_attr");
|
||||
err += add_stat_dict(stats, LOAD_GLOBAL, "load_global");
|
||||
err += add_stat_dict(stats, BINARY_SUBSCR, "binary_subscr");
|
||||
err += add_stat_dict(stats, STORE_SUBSCR, "store_subscr");
|
||||
err += add_stat_dict(stats, STORE_ATTR, "store_attr");
|
||||
err += add_stat_dict(stats, CALL, "call");
|
||||
|
@ -553,11 +552,8 @@ _PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, int enable_counters
|
|||
#define SPEC_FAIL_SUBSCR_ARRAY_INT 9
|
||||
#define SPEC_FAIL_SUBSCR_ARRAY_SLICE 10
|
||||
#define SPEC_FAIL_SUBSCR_LIST_SLICE 11
|
||||
#define SPEC_FAIL_SUBSCR_TUPLE_SLICE 12
|
||||
#define SPEC_FAIL_SUBSCR_STRING_SLICE 14
|
||||
#define SPEC_FAIL_SUBSCR_BUFFER_INT 15
|
||||
#define SPEC_FAIL_SUBSCR_BUFFER_SLICE 16
|
||||
#define SPEC_FAIL_SUBSCR_SEQUENCE_INT 17
|
||||
#define SPEC_FAIL_SUBSCR_BUFFER_INT 12
|
||||
#define SPEC_FAIL_SUBSCR_BUFFER_SLICE 13
|
||||
|
||||
/* Store subscr */
|
||||
#define SPEC_FAIL_SUBSCR_BYTEARRAY_INT 18
|
||||
|
@ -593,6 +589,11 @@ _PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, int enable_counters
|
|||
#define SPEC_FAIL_BINARY_OP_OR_DIFFERENT_TYPES 30
|
||||
#define SPEC_FAIL_BINARY_OP_XOR_INT 31
|
||||
#define SPEC_FAIL_BINARY_OP_XOR_DIFFERENT_TYPES 32
|
||||
#define SPEC_FAIL_BINARY_OP_SUBSCR 33
|
||||
#define SPEC_FAIL_BINARY_OP_SUBSCR_LIST_SLICE 34
|
||||
#define SPEC_FAIL_BINARY_OP_SUBSCR_TUPLE_SLICE 35
|
||||
#define SPEC_FAIL_BINARY_OP_SUBSCR_STRING_SLICE 36
|
||||
#define SPEC_FAIL_BINARY_OP_SUBSCR_NOT_HEAP_TYPE 37
|
||||
|
||||
/* Calls */
|
||||
|
||||
|
@ -1761,37 +1762,6 @@ _Py_Specialize_LoadGlobal(
|
|||
Py_END_CRITICAL_SECTION2();
|
||||
}
|
||||
|
||||
#ifdef Py_STATS
|
||||
static int
|
||||
binary_subscr_fail_kind(PyTypeObject *container_type, PyObject *sub)
|
||||
{
|
||||
if (strcmp(container_type->tp_name, "array.array") == 0) {
|
||||
if (PyLong_CheckExact(sub)) {
|
||||
return SPEC_FAIL_SUBSCR_ARRAY_INT;
|
||||
}
|
||||
if (PySlice_Check(sub)) {
|
||||
return SPEC_FAIL_SUBSCR_ARRAY_SLICE;
|
||||
}
|
||||
return SPEC_FAIL_OTHER;
|
||||
}
|
||||
else if (container_type->tp_as_buffer) {
|
||||
if (PyLong_CheckExact(sub)) {
|
||||
return SPEC_FAIL_SUBSCR_BUFFER_INT;
|
||||
}
|
||||
if (PySlice_Check(sub)) {
|
||||
return SPEC_FAIL_SUBSCR_BUFFER_SLICE;
|
||||
}
|
||||
return SPEC_FAIL_OTHER;
|
||||
}
|
||||
else if (container_type->tp_as_sequence) {
|
||||
if (PyLong_CheckExact(sub) && container_type->tp_as_sequence->sq_item) {
|
||||
return SPEC_FAIL_SUBSCR_SEQUENCE_INT;
|
||||
}
|
||||
}
|
||||
return SPEC_FAIL_OTHER;
|
||||
}
|
||||
#endif // Py_STATS
|
||||
|
||||
static int
|
||||
function_kind(PyCodeObject *code) {
|
||||
int flags = code->co_flags;
|
||||
|
@ -1837,107 +1807,6 @@ function_get_version(PyObject *o, int opcode)
|
|||
return version;
|
||||
}
|
||||
|
||||
void
|
||||
_Py_Specialize_BinarySubscr(
|
||||
_PyStackRef container_st, _PyStackRef sub_st, _Py_CODEUNIT *instr)
|
||||
{
|
||||
PyObject *container = PyStackRef_AsPyObjectBorrow(container_st);
|
||||
PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st);
|
||||
|
||||
assert(ENABLE_SPECIALIZATION_FT);
|
||||
assert(_PyOpcode_Caches[BINARY_SUBSCR] ==
|
||||
INLINE_CACHE_ENTRIES_BINARY_SUBSCR);
|
||||
PyTypeObject *container_type = Py_TYPE(container);
|
||||
uint8_t specialized_op;
|
||||
if (container_type == &PyList_Type) {
|
||||
if (PyLong_CheckExact(sub)) {
|
||||
if (_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) {
|
||||
specialized_op = BINARY_SUBSCR_LIST_INT;
|
||||
goto success;
|
||||
}
|
||||
SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_OUT_OF_RANGE);
|
||||
goto fail;
|
||||
}
|
||||
SPECIALIZATION_FAIL(BINARY_SUBSCR,
|
||||
PySlice_Check(sub) ? SPEC_FAIL_SUBSCR_LIST_SLICE : SPEC_FAIL_OTHER);
|
||||
goto fail;
|
||||
}
|
||||
if (container_type == &PyTuple_Type) {
|
||||
if (PyLong_CheckExact(sub)) {
|
||||
if (_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) {
|
||||
specialized_op = BINARY_SUBSCR_TUPLE_INT;
|
||||
goto success;
|
||||
}
|
||||
SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_OUT_OF_RANGE);
|
||||
goto fail;
|
||||
}
|
||||
SPECIALIZATION_FAIL(BINARY_SUBSCR,
|
||||
PySlice_Check(sub) ? SPEC_FAIL_SUBSCR_TUPLE_SLICE : SPEC_FAIL_OTHER);
|
||||
goto fail;
|
||||
}
|
||||
if (container_type == &PyUnicode_Type) {
|
||||
if (PyLong_CheckExact(sub)) {
|
||||
if (_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) {
|
||||
specialized_op = BINARY_SUBSCR_STR_INT;
|
||||
goto success;
|
||||
}
|
||||
SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_OUT_OF_RANGE);
|
||||
goto fail;
|
||||
}
|
||||
SPECIALIZATION_FAIL(BINARY_SUBSCR,
|
||||
PySlice_Check(sub) ? SPEC_FAIL_SUBSCR_STRING_SLICE : SPEC_FAIL_OTHER);
|
||||
goto fail;
|
||||
}
|
||||
if (container_type == &PyDict_Type) {
|
||||
specialized_op = BINARY_SUBSCR_DICT;
|
||||
goto success;
|
||||
}
|
||||
unsigned int tp_version;
|
||||
PyObject *descriptor = _PyType_LookupRefAndVersion(container_type, &_Py_ID(__getitem__), &tp_version);
|
||||
if (descriptor && Py_TYPE(descriptor) == &PyFunction_Type) {
|
||||
if (!(container_type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
|
||||
SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_SUBSCR_NOT_HEAP_TYPE);
|
||||
Py_DECREF(descriptor);
|
||||
goto fail;
|
||||
}
|
||||
PyFunctionObject *func = (PyFunctionObject *)descriptor;
|
||||
PyCodeObject *fcode = (PyCodeObject *)func->func_code;
|
||||
int kind = function_kind(fcode);
|
||||
if (kind != SIMPLE_FUNCTION) {
|
||||
SPECIALIZATION_FAIL(BINARY_SUBSCR, kind);
|
||||
Py_DECREF(descriptor);
|
||||
goto fail;
|
||||
}
|
||||
if (fcode->co_argcount != 2) {
|
||||
SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
|
||||
Py_DECREF(descriptor);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PyHeapTypeObject *ht = (PyHeapTypeObject *)container_type;
|
||||
/* Don't specialize if PEP 523 is active */
|
||||
if (_PyInterpreterState_GET()->eval_frame) {
|
||||
SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_OTHER);
|
||||
Py_DECREF(descriptor);
|
||||
goto fail;
|
||||
}
|
||||
if (_PyType_CacheGetItemForSpecialization(ht, descriptor, (uint32_t)tp_version)) {
|
||||
specialized_op = BINARY_SUBSCR_GETITEM;
|
||||
Py_DECREF(descriptor);
|
||||
goto success;
|
||||
}
|
||||
}
|
||||
Py_XDECREF(descriptor);
|
||||
SPECIALIZATION_FAIL(BINARY_SUBSCR,
|
||||
binary_subscr_fail_kind(container_type, sub));
|
||||
fail:
|
||||
unspecialize(instr);
|
||||
return;
|
||||
success:
|
||||
specialize(instr, specialized_op);
|
||||
}
|
||||
|
||||
|
||||
#ifdef Py_STATS
|
||||
static int
|
||||
store_subscr_fail_kind(PyObject *container, PyObject *sub)
|
||||
|
@ -2431,6 +2300,59 @@ binary_op_fail_kind(int oparg, PyObject *lhs, PyObject *rhs)
|
|||
return SPEC_FAIL_BINARY_OP_XOR_INT;
|
||||
}
|
||||
return SPEC_FAIL_BINARY_OP_XOR;
|
||||
case NB_SUBSCR:
|
||||
if (PyList_CheckExact(lhs)) {
|
||||
if (PyLong_CheckExact(rhs) && !_PyLong_IsNonNegativeCompact((PyLongObject *)rhs)) {
|
||||
return SPEC_FAIL_OUT_OF_RANGE;
|
||||
}
|
||||
if (PySlice_Check(rhs)) {
|
||||
return SPEC_FAIL_BINARY_OP_SUBSCR_LIST_SLICE;
|
||||
}
|
||||
}
|
||||
if (PyTuple_CheckExact(lhs)) {
|
||||
if (PyLong_CheckExact(rhs) && !_PyLong_IsNonNegativeCompact((PyLongObject *)rhs)) {
|
||||
return SPEC_FAIL_OUT_OF_RANGE;
|
||||
}
|
||||
if (PySlice_Check(rhs)) {
|
||||
return SPEC_FAIL_BINARY_OP_SUBSCR_TUPLE_SLICE;
|
||||
}
|
||||
}
|
||||
if (PyUnicode_CheckExact(lhs)) {
|
||||
if (PyLong_CheckExact(rhs) && !_PyLong_IsNonNegativeCompact((PyLongObject *)rhs)) {
|
||||
return SPEC_FAIL_OUT_OF_RANGE;
|
||||
}
|
||||
if (PySlice_Check(rhs)) {
|
||||
return SPEC_FAIL_BINARY_OP_SUBSCR_STRING_SLICE;
|
||||
}
|
||||
}
|
||||
unsigned int tp_version;
|
||||
PyTypeObject *container_type = Py_TYPE(lhs);
|
||||
PyObject *descriptor = _PyType_LookupRefAndVersion(container_type, &_Py_ID(__getitem__), &tp_version);
|
||||
if (descriptor && Py_TYPE(descriptor) == &PyFunction_Type) {
|
||||
if (!(container_type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
|
||||
Py_DECREF(descriptor);
|
||||
return SPEC_FAIL_BINARY_OP_SUBSCR_NOT_HEAP_TYPE;
|
||||
}
|
||||
PyFunctionObject *func = (PyFunctionObject *)descriptor;
|
||||
PyCodeObject *fcode = (PyCodeObject *)func->func_code;
|
||||
int kind = function_kind(fcode);
|
||||
if (kind != SIMPLE_FUNCTION) {
|
||||
Py_DECREF(descriptor);
|
||||
return kind;
|
||||
}
|
||||
if (fcode->co_argcount != 2) {
|
||||
Py_DECREF(descriptor);
|
||||
return SPEC_FAIL_WRONG_NUMBER_ARGUMENTS;
|
||||
}
|
||||
|
||||
if (_PyInterpreterState_GET()->eval_frame) {
|
||||
/* Don't specialize if PEP 523 is active */
|
||||
Py_DECREF(descriptor);
|
||||
return SPEC_FAIL_OTHER;
|
||||
}
|
||||
}
|
||||
Py_XDECREF(descriptor);
|
||||
return SPEC_FAIL_BINARY_OP_SUBSCR;
|
||||
}
|
||||
Py_UNREACHABLE();
|
||||
}
|
||||
|
@ -2536,45 +2458,40 @@ LONG_FLOAT_ACTION(compactlong_float_multiply, *)
|
|||
LONG_FLOAT_ACTION(compactlong_float_true_div, /)
|
||||
#undef LONG_FLOAT_ACTION
|
||||
|
||||
static _PyBinaryOpSpecializationDescr compactlongs_specs[NB_OPARG_LAST+1] = {
|
||||
[NB_OR] = {compactlongs_guard, compactlongs_or},
|
||||
[NB_AND] = {compactlongs_guard, compactlongs_and},
|
||||
[NB_XOR] = {compactlongs_guard, compactlongs_xor},
|
||||
[NB_INPLACE_OR] = {compactlongs_guard, compactlongs_or},
|
||||
[NB_INPLACE_AND] = {compactlongs_guard, compactlongs_and},
|
||||
[NB_INPLACE_XOR] = {compactlongs_guard, compactlongs_xor},
|
||||
};
|
||||
static _PyBinaryOpSpecializationDescr binaryop_extend_descrs[] = {
|
||||
/* long-long arithmetic */
|
||||
{NB_OR, compactlongs_guard, compactlongs_or},
|
||||
{NB_AND, compactlongs_guard, compactlongs_and},
|
||||
{NB_XOR, compactlongs_guard, compactlongs_xor},
|
||||
{NB_INPLACE_OR, compactlongs_guard, compactlongs_or},
|
||||
{NB_INPLACE_AND, compactlongs_guard, compactlongs_and},
|
||||
{NB_INPLACE_XOR, compactlongs_guard, compactlongs_xor},
|
||||
|
||||
static _PyBinaryOpSpecializationDescr float_compactlong_specs[NB_OPARG_LAST+1] = {
|
||||
[NB_ADD] = {float_compactlong_guard, float_compactlong_add},
|
||||
[NB_SUBTRACT] = {float_compactlong_guard, float_compactlong_subtract},
|
||||
[NB_TRUE_DIVIDE] = {nonzero_float_compactlong_guard, float_compactlong_true_div},
|
||||
[NB_MULTIPLY] = {float_compactlong_guard, float_compactlong_multiply},
|
||||
};
|
||||
/* float-long arithemetic */
|
||||
{NB_ADD, float_compactlong_guard, float_compactlong_add},
|
||||
{NB_SUBTRACT, float_compactlong_guard, float_compactlong_subtract},
|
||||
{NB_TRUE_DIVIDE, nonzero_float_compactlong_guard, float_compactlong_true_div},
|
||||
{NB_MULTIPLY, float_compactlong_guard, float_compactlong_multiply},
|
||||
|
||||
static _PyBinaryOpSpecializationDescr compactlong_float_specs[NB_OPARG_LAST+1] = {
|
||||
[NB_ADD] = {compactlong_float_guard, compactlong_float_add},
|
||||
[NB_SUBTRACT] = {compactlong_float_guard, compactlong_float_subtract},
|
||||
[NB_TRUE_DIVIDE] = {nonzero_compactlong_float_guard, compactlong_float_true_div},
|
||||
[NB_MULTIPLY] = {compactlong_float_guard, compactlong_float_multiply},
|
||||
/* float-float arithmetic */
|
||||
{NB_ADD, compactlong_float_guard, compactlong_float_add},
|
||||
{NB_SUBTRACT, compactlong_float_guard, compactlong_float_subtract},
|
||||
{NB_TRUE_DIVIDE, nonzero_compactlong_float_guard, compactlong_float_true_div},
|
||||
{NB_MULTIPLY, compactlong_float_guard, compactlong_float_multiply},
|
||||
};
|
||||
|
||||
static int
|
||||
binary_op_extended_specialization(PyObject *lhs, PyObject *rhs, int oparg,
|
||||
_PyBinaryOpSpecializationDescr **descr)
|
||||
{
|
||||
#define LOOKUP_SPEC(TABLE, OPARG) \
|
||||
if ((TABLE)[(OPARG)].action) { \
|
||||
if ((TABLE)[(OPARG)].guard(lhs, rhs)) { \
|
||||
*descr = &((TABLE)[OPARG]); \
|
||||
return 1; \
|
||||
} \
|
||||
size_t n = sizeof(binaryop_extend_descrs)/sizeof(_PyBinaryOpSpecializationDescr);
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
_PyBinaryOpSpecializationDescr *d = &binaryop_extend_descrs[i];
|
||||
if (d->oparg == oparg && d->guard(lhs, rhs)) {
|
||||
*descr = d;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
LOOKUP_SPEC(compactlong_float_specs, oparg);
|
||||
LOOKUP_SPEC(float_compactlong_specs, oparg);
|
||||
LOOKUP_SPEC(compactlongs_specs, oparg);
|
||||
#undef LOOKUP_SPEC
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2645,6 +2562,47 @@ _Py_Specialize_BinaryOp(_PyStackRef lhs_st, _PyStackRef rhs_st, _Py_CODEUNIT *in
|
|||
return;
|
||||
}
|
||||
break;
|
||||
case NB_SUBSCR:
|
||||
if (PyLong_CheckExact(rhs) && _PyLong_IsNonNegativeCompact((PyLongObject *)rhs)) {
|
||||
if (PyList_CheckExact(lhs)) {
|
||||
specialize(instr, BINARY_OP_SUBSCR_LIST_INT);
|
||||
return;
|
||||
}
|
||||
if (PyTuple_CheckExact(lhs)) {
|
||||
specialize(instr, BINARY_OP_SUBSCR_TUPLE_INT);
|
||||
return;
|
||||
}
|
||||
if (PyUnicode_CheckExact(lhs)) {
|
||||
specialize(instr, BINARY_OP_SUBSCR_STR_INT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (PyDict_CheckExact(lhs)) {
|
||||
specialize(instr, BINARY_OP_SUBSCR_DICT);
|
||||
return;
|
||||
}
|
||||
unsigned int tp_version;
|
||||
PyTypeObject *container_type = Py_TYPE(lhs);
|
||||
PyObject *descriptor = _PyType_LookupRefAndVersion(container_type, &_Py_ID(__getitem__), &tp_version);
|
||||
if (descriptor && Py_TYPE(descriptor) == &PyFunction_Type &&
|
||||
container_type->tp_flags & Py_TPFLAGS_HEAPTYPE)
|
||||
{
|
||||
PyFunctionObject *func = (PyFunctionObject *)descriptor;
|
||||
PyCodeObject *fcode = (PyCodeObject *)func->func_code;
|
||||
int kind = function_kind(fcode);
|
||||
PyHeapTypeObject *ht = (PyHeapTypeObject *)container_type;
|
||||
if (kind == SIMPLE_FUNCTION &&
|
||||
fcode->co_argcount == 2 &&
|
||||
!_PyInterpreterState_GET()->eval_frame && /* Don't specialize if PEP 523 is active */
|
||||
_PyType_CacheGetItemForSpecialization(ht, descriptor, (uint32_t)tp_version))
|
||||
{
|
||||
specialize(instr, BINARY_OP_SUBSCR_GETITEM);
|
||||
Py_DECREF(descriptor);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Py_XDECREF(descriptor);
|
||||
break;
|
||||
}
|
||||
|
||||
_PyBinaryOpSpecializationDescr *descr;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue