mirror of
https://github.com/python/cpython.git
synced 2025-08-23 18:24:46 +00:00
GH-111485: Use micro-ops to split specialization code from base action (GH-111561)
This commit is contained in:
parent
eaf67e37a2
commit
b14e882428
9 changed files with 864 additions and 583 deletions
|
@ -311,9 +311,10 @@ dummy_func(
|
|||
TO_BOOL_STR,
|
||||
};
|
||||
|
||||
inst(TO_BOOL, (unused/1, unused/2, value -- res)) {
|
||||
op(_SPECIALIZE_TO_BOOL, (counter/1, value -- value)) {
|
||||
TIER_ONE_ONLY
|
||||
#if ENABLE_SPECIALIZATION
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(this_instr[1].cache)) {
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
|
||||
next_instr = this_instr;
|
||||
_Py_Specialize_ToBool(value, next_instr);
|
||||
DISPATCH_SAME_OPARG();
|
||||
|
@ -321,12 +322,17 @@ dummy_func(
|
|||
STAT_INC(TO_BOOL, deferred);
|
||||
DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache);
|
||||
#endif /* ENABLE_SPECIALIZATION */
|
||||
}
|
||||
|
||||
op(_TO_BOOL, (unused/2, value -- res)) {
|
||||
int err = PyObject_IsTrue(value);
|
||||
DECREF_INPUTS();
|
||||
ERROR_IF(err < 0, error);
|
||||
res = err ? Py_True : Py_False;
|
||||
}
|
||||
|
||||
macro(TO_BOOL) = _SPECIALIZE_TO_BOOL + _TO_BOOL;
|
||||
|
||||
inst(TO_BOOL_BOOL, (unused/1, unused/2, value -- value)) {
|
||||
DEOPT_IF(!PyBool_Check(value));
|
||||
STAT_INC(TO_BOOL, hit);
|
||||
|
@ -530,9 +536,10 @@ dummy_func(
|
|||
BINARY_SUBSCR_TUPLE_INT,
|
||||
};
|
||||
|
||||
inst(BINARY_SUBSCR, (unused/1, container, sub -- res)) {
|
||||
op(_SPECIALIZE_BINARY_SUBSCR, (counter/1, container, sub -- container, sub)) {
|
||||
TIER_ONE_ONLY
|
||||
#if ENABLE_SPECIALIZATION
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(this_instr[1].cache)) {
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
|
||||
next_instr = this_instr;
|
||||
_Py_Specialize_BinarySubscr(container, sub, next_instr);
|
||||
DISPATCH_SAME_OPARG();
|
||||
|
@ -540,11 +547,16 @@ dummy_func(
|
|||
STAT_INC(BINARY_SUBSCR, deferred);
|
||||
DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache);
|
||||
#endif /* ENABLE_SPECIALIZATION */
|
||||
}
|
||||
|
||||
op(_BINARY_SUBSCR, (container, sub -- res)) {
|
||||
res = PyObject_GetItem(container, sub);
|
||||
DECREF_INPUTS();
|
||||
ERROR_IF(res == NULL, error);
|
||||
}
|
||||
|
||||
macro(BINARY_SUBSCR) = _SPECIALIZE_BINARY_SUBSCR + _BINARY_SUBSCR;
|
||||
|
||||
inst(BINARY_SLICE, (container, start, stop -- res)) {
|
||||
PyObject *slice = _PyBuildSlice_ConsumeRefs(start, stop);
|
||||
// Can't use ERROR_IF() here, because we haven't
|
||||
|
@ -677,9 +689,10 @@ dummy_func(
|
|||
STORE_SUBSCR_LIST_INT,
|
||||
};
|
||||
|
||||
inst(STORE_SUBSCR, (unused/1, v, container, sub -- )) {
|
||||
op(_SPECIALIZE_STORE_SUBSCR, (counter/1, container, sub -- container, sub)) {
|
||||
TIER_ONE_ONLY
|
||||
#if ENABLE_SPECIALIZATION
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(this_instr[1].cache)) {
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
|
||||
next_instr = this_instr;
|
||||
_Py_Specialize_StoreSubscr(container, sub, next_instr);
|
||||
DISPATCH_SAME_OPARG();
|
||||
|
@ -687,12 +700,17 @@ dummy_func(
|
|||
STAT_INC(STORE_SUBSCR, deferred);
|
||||
DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache);
|
||||
#endif /* ENABLE_SPECIALIZATION */
|
||||
}
|
||||
|
||||
op(_STORE_SUBSCR, (v, container, sub -- )) {
|
||||
/* container[sub] = v */
|
||||
int err = PyObject_SetItem(container, sub, v);
|
||||
DECREF_INPUTS();
|
||||
ERROR_IF(err, error);
|
||||
}
|
||||
|
||||
macro(STORE_SUBSCR) = _SPECIALIZE_STORE_SUBSCR + _STORE_SUBSCR;
|
||||
|
||||
inst(STORE_SUBSCR_LIST_INT, (unused/1, value, list, sub -- )) {
|
||||
DEOPT_IF(!PyLong_CheckExact(sub));
|
||||
DEOPT_IF(!PyList_CheckExact(list));
|
||||
|
@ -956,9 +974,10 @@ dummy_func(
|
|||
SEND_GEN,
|
||||
};
|
||||
|
||||
inst(SEND, (unused/1, receiver, v -- receiver, retval)) {
|
||||
op(_SPECIALIZE_SEND, (counter/1, receiver, unused -- receiver, unused)) {
|
||||
TIER_ONE_ONLY
|
||||
#if ENABLE_SPECIALIZATION
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(this_instr[1].cache)) {
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
|
||||
next_instr = this_instr;
|
||||
_Py_Specialize_Send(receiver, next_instr);
|
||||
DISPATCH_SAME_OPARG();
|
||||
|
@ -966,6 +985,9 @@ dummy_func(
|
|||
STAT_INC(SEND, deferred);
|
||||
DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache);
|
||||
#endif /* ENABLE_SPECIALIZATION */
|
||||
}
|
||||
|
||||
op(_SEND, (receiver, v -- receiver, retval)) {
|
||||
assert(frame != &entry_frame);
|
||||
if ((tstate->interp->eval_frame == NULL) &&
|
||||
(Py_TYPE(receiver) == &PyGen_Type || Py_TYPE(receiver) == &PyCoro_Type) &&
|
||||
|
@ -1004,6 +1026,8 @@ dummy_func(
|
|||
Py_DECREF(v);
|
||||
}
|
||||
|
||||
macro(SEND) = _SPECIALIZE_SEND + _SEND;
|
||||
|
||||
inst(SEND_GEN, (unused/1, receiver, v -- receiver, unused)) {
|
||||
DEOPT_IF(tstate->interp->eval_frame);
|
||||
PyGenObject *gen = (PyGenObject *)receiver;
|
||||
|
@ -1182,9 +1206,9 @@ dummy_func(
|
|||
UNPACK_SEQUENCE_LIST,
|
||||
};
|
||||
|
||||
inst(UNPACK_SEQUENCE, (unused/1, seq -- unused[oparg])) {
|
||||
op(_SPECIALIZE_UNPACK_SEQUENCE, (counter/1, seq -- seq)) {
|
||||
#if ENABLE_SPECIALIZATION
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(this_instr[1].cache)) {
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
|
||||
next_instr = this_instr;
|
||||
_Py_Specialize_UnpackSequence(seq, next_instr, oparg);
|
||||
DISPATCH_SAME_OPARG();
|
||||
|
@ -1192,12 +1216,17 @@ dummy_func(
|
|||
STAT_INC(UNPACK_SEQUENCE, deferred);
|
||||
DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache);
|
||||
#endif /* ENABLE_SPECIALIZATION */
|
||||
}
|
||||
|
||||
op(_UNPACK_SEQUENCE, (seq -- unused[oparg])) {
|
||||
PyObject **top = stack_pointer + oparg - 1;
|
||||
int res = _PyEval_UnpackIterable(tstate, seq, oparg, -1, top);
|
||||
DECREF_INPUTS();
|
||||
ERROR_IF(res == 0, error);
|
||||
}
|
||||
|
||||
macro(UNPACK_SEQUENCE) = _SPECIALIZE_UNPACK_SEQUENCE + _UNPACK_SEQUENCE;
|
||||
|
||||
inst(UNPACK_SEQUENCE_TWO_TUPLE, (unused/1, seq -- values[oparg])) {
|
||||
DEOPT_IF(!PyTuple_CheckExact(seq));
|
||||
DEOPT_IF(PyTuple_GET_SIZE(seq) != 2);
|
||||
|
@ -1244,9 +1273,10 @@ dummy_func(
|
|||
STORE_ATTR_WITH_HINT,
|
||||
};
|
||||
|
||||
inst(STORE_ATTR, (unused/1, unused/3, v, owner --)) {
|
||||
op(_SPECIALIZE_STORE_ATTR, (counter/1, owner -- owner)) {
|
||||
TIER_ONE_ONLY
|
||||
#if ENABLE_SPECIALIZATION
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(this_instr[1].cache)) {
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
|
||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
|
||||
next_instr = this_instr;
|
||||
_Py_Specialize_StoreAttr(owner, next_instr, name);
|
||||
|
@ -1255,12 +1285,17 @@ dummy_func(
|
|||
STAT_INC(STORE_ATTR, deferred);
|
||||
DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache);
|
||||
#endif /* ENABLE_SPECIALIZATION */
|
||||
}
|
||||
|
||||
op(_STORE_ATTR, (unused/3, v, owner --)) {
|
||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
|
||||
int err = PyObject_SetAttr(owner, name, v);
|
||||
DECREF_INPUTS();
|
||||
ERROR_IF(err, error);
|
||||
}
|
||||
|
||||
macro(STORE_ATTR) = _SPECIALIZE_STORE_ATTR + _STORE_ATTR;
|
||||
|
||||
inst(DELETE_ATTR, (owner --)) {
|
||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
|
||||
int err = PyObject_DelAttr(owner, name);
|
||||
|
@ -1365,9 +1400,10 @@ dummy_func(
|
|||
LOAD_GLOBAL_BUILTIN,
|
||||
};
|
||||
|
||||
inst(LOAD_GLOBAL, (unused/1, unused/1, unused/1, unused/1 -- res, null if (oparg & 1))) {
|
||||
op(_SPECIALIZE_LOAD_GLOBAL, (counter/1 -- )) {
|
||||
TIER_ONE_ONLY
|
||||
#if ENABLE_SPECIALIZATION
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(this_instr[1].cache)) {
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
|
||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
|
||||
next_instr = this_instr;
|
||||
_Py_Specialize_LoadGlobal(GLOBALS(), BUILTINS(), next_instr, name);
|
||||
|
@ -1376,6 +1412,9 @@ dummy_func(
|
|||
STAT_INC(LOAD_GLOBAL, deferred);
|
||||
DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache);
|
||||
#endif /* ENABLE_SPECIALIZATION */
|
||||
}
|
||||
|
||||
op(_LOAD_GLOBAL, (unused/1, unused/1, unused/1 -- res, null if (oparg & 1))) {
|
||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
|
||||
if (PyDict_CheckExact(GLOBALS())
|
||||
&& PyDict_CheckExact(BUILTINS()))
|
||||
|
@ -1396,7 +1435,6 @@ dummy_func(
|
|||
}
|
||||
else {
|
||||
/* Slow-path if globals or builtins is not a dict */
|
||||
|
||||
/* namespace 1: globals */
|
||||
ERROR_IF(PyMapping_GetOptionalItem(GLOBALS(), name, &res) < 0, error);
|
||||
if (res == NULL) {
|
||||
|
@ -1413,6 +1451,8 @@ dummy_func(
|
|||
null = NULL;
|
||||
}
|
||||
|
||||
macro(LOAD_GLOBAL) = _SPECIALIZE_LOAD_GLOBAL + _LOAD_GLOBAL;
|
||||
|
||||
op(_GUARD_GLOBALS_VERSION, (version/1 --)) {
|
||||
PyDictObject *dict = (PyDictObject *)GLOBALS();
|
||||
DEOPT_IF(!PyDict_CheckExact(dict));
|
||||
|
@ -1701,12 +1741,11 @@ dummy_func(
|
|||
LOAD_SUPER_ATTR_METHOD,
|
||||
};
|
||||
|
||||
inst(LOAD_SUPER_ATTR, (unused/1, global_super, class, self -- attr, null if (oparg & 1))) {
|
||||
op(_SPECIALIZE_LOAD_SUPER_ATTR, (counter/1, global_super, class, unused -- global_super, class, unused)) {
|
||||
TIER_ONE_ONLY
|
||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2);
|
||||
#if ENABLE_SPECIALIZATION
|
||||
int load_method = oparg & 1;
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(this_instr[1].cache)) {
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
|
||||
next_instr = this_instr;
|
||||
_Py_Specialize_LoadSuperAttr(global_super, class, next_instr, load_method);
|
||||
DISPATCH_SAME_OPARG();
|
||||
|
@ -1714,7 +1753,10 @@ dummy_func(
|
|||
STAT_INC(LOAD_SUPER_ATTR, deferred);
|
||||
DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache);
|
||||
#endif /* ENABLE_SPECIALIZATION */
|
||||
}
|
||||
|
||||
op(_LOAD_SUPER_ATTR, (global_super, class, self -- attr, null if (oparg & 1))) {
|
||||
TIER_ONE_ONLY
|
||||
if (opcode == INSTRUMENTED_LOAD_SUPER_ATTR) {
|
||||
PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING;
|
||||
int err = _Py_call_instrumentation_2args(
|
||||
|
@ -1722,7 +1764,6 @@ dummy_func(
|
|||
frame, this_instr, global_super, arg);
|
||||
ERROR_IF(err, error);
|
||||
}
|
||||
|
||||
// we make no attempt to optimize here; specializations should
|
||||
// handle any case whose performance we care about
|
||||
PyObject *stack[] = {class, self};
|
||||
|
@ -1745,12 +1786,15 @@ dummy_func(
|
|||
}
|
||||
DECREF_INPUTS();
|
||||
ERROR_IF(super == NULL, error);
|
||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2);
|
||||
attr = PyObject_GetAttr(super, name);
|
||||
Py_DECREF(super);
|
||||
ERROR_IF(attr == NULL, error);
|
||||
null = NULL;
|
||||
}
|
||||
|
||||
macro(LOAD_SUPER_ATTR) = _SPECIALIZE_LOAD_SUPER_ATTR + _LOAD_SUPER_ATTR;
|
||||
|
||||
pseudo(LOAD_SUPER_METHOD) = {
|
||||
LOAD_SUPER_ATTR,
|
||||
};
|
||||
|
@ -1813,9 +1857,10 @@ dummy_func(
|
|||
LOAD_ATTR_NONDESCRIPTOR_NO_DICT,
|
||||
};
|
||||
|
||||
inst(LOAD_ATTR, (unused/9, owner -- attr, self_or_null if (oparg & 1))) {
|
||||
op(_SPECIALIZE_LOAD_ATTR, (counter/1, owner -- owner)) {
|
||||
TIER_ONE_ONLY
|
||||
#if ENABLE_SPECIALIZATION
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(this_instr[1].cache)) {
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
|
||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
|
||||
next_instr = this_instr;
|
||||
_Py_Specialize_LoadAttr(owner, next_instr, name);
|
||||
|
@ -1824,6 +1869,9 @@ dummy_func(
|
|||
STAT_INC(LOAD_ATTR, deferred);
|
||||
DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache);
|
||||
#endif /* ENABLE_SPECIALIZATION */
|
||||
}
|
||||
|
||||
op(_LOAD_ATTR, (unused/8, owner -- attr, self_or_null if (oparg & 1))) {
|
||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
|
||||
if (oparg & 1) {
|
||||
/* Designed to work in tandem with CALL, pushes two values. */
|
||||
|
@ -1831,7 +1879,6 @@ dummy_func(
|
|||
if (_PyObject_GetMethod(owner, name, &attr)) {
|
||||
/* We can bypass temporary bound method object.
|
||||
meth is unbound method and obj is self.
|
||||
|
||||
meth | self | arg1 | ... | argN
|
||||
*/
|
||||
assert(attr != NULL); // No errors on this branch
|
||||
|
@ -1842,7 +1889,6 @@ dummy_func(
|
|||
something was returned by a descriptor protocol). Set
|
||||
the second element of the stack to NULL, to signal
|
||||
CALL that it's not a method call.
|
||||
|
||||
NULL | meth | arg1 | ... | argN
|
||||
*/
|
||||
DECREF_INPUTS();
|
||||
|
@ -1858,6 +1904,8 @@ dummy_func(
|
|||
}
|
||||
}
|
||||
|
||||
macro(LOAD_ATTR) = _SPECIALIZE_LOAD_ATTR + _LOAD_ATTR;
|
||||
|
||||
pseudo(LOAD_METHOD) = {
|
||||
LOAD_ATTR,
|
||||
};
|
||||
|
@ -2133,9 +2181,10 @@ dummy_func(
|
|||
COMPARE_OP_STR,
|
||||
};
|
||||
|
||||
inst(COMPARE_OP, (unused/1, left, right -- res)) {
|
||||
op(_SPECIALIZE_COMPARE_OP, (counter/1, left, right -- left, right)) {
|
||||
TIER_ONE_ONLY
|
||||
#if ENABLE_SPECIALIZATION
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(this_instr[1].cache)) {
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
|
||||
next_instr = this_instr;
|
||||
_Py_Specialize_CompareOp(left, right, next_instr, oparg);
|
||||
DISPATCH_SAME_OPARG();
|
||||
|
@ -2143,6 +2192,9 @@ dummy_func(
|
|||
STAT_INC(COMPARE_OP, deferred);
|
||||
DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache);
|
||||
#endif /* ENABLE_SPECIALIZATION */
|
||||
}
|
||||
|
||||
op(_COMPARE_OP, (left, right -- res)) {
|
||||
assert((oparg >> 5) <= Py_GE);
|
||||
res = PyObject_RichCompare(left, right, oparg >> 5);
|
||||
DECREF_INPUTS();
|
||||
|
@ -2155,6 +2207,8 @@ dummy_func(
|
|||
}
|
||||
}
|
||||
|
||||
macro(COMPARE_OP) = _SPECIALIZE_COMPARE_OP + _COMPARE_OP;
|
||||
|
||||
inst(COMPARE_OP_FLOAT, (unused/1, left, right -- res)) {
|
||||
DEOPT_IF(!PyFloat_CheckExact(left));
|
||||
DEOPT_IF(!PyFloat_CheckExact(right));
|
||||
|
@ -2448,9 +2502,10 @@ dummy_func(
|
|||
FOR_ITER_GEN,
|
||||
};
|
||||
|
||||
inst(FOR_ITER, (unused/1, iter -- iter, next)) {
|
||||
op(_SPECIALIZE_FOR_ITER, (counter/1, iter -- iter)) {
|
||||
TIER_ONE_ONLY
|
||||
#if ENABLE_SPECIALIZATION
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(this_instr[1].cache)) {
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
|
||||
next_instr = this_instr;
|
||||
_Py_Specialize_ForIter(iter, next_instr, oparg);
|
||||
DISPATCH_SAME_OPARG();
|
||||
|
@ -2458,6 +2513,9 @@ dummy_func(
|
|||
STAT_INC(FOR_ITER, deferred);
|
||||
DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache);
|
||||
#endif /* ENABLE_SPECIALIZATION */
|
||||
}
|
||||
|
||||
op(_FOR_ITER, (iter -- iter, next)) {
|
||||
/* before: [iter]; after: [iter, iter()] *or* [] (and jump over END_FOR.) */
|
||||
next = (*Py_TYPE(iter)->tp_iternext)(iter);
|
||||
if (next == NULL) {
|
||||
|
@ -2480,6 +2538,8 @@ dummy_func(
|
|||
// Common case: no jump, leave it to the code generator
|
||||
}
|
||||
|
||||
macro(FOR_ITER) = _SPECIALIZE_FOR_ITER + _FOR_ITER;
|
||||
|
||||
inst(INSTRUMENTED_FOR_ITER, (unused/1 -- )) {
|
||||
_Py_CODEUNIT *target;
|
||||
PyObject *iter = TOP();
|
||||
|
@ -2937,24 +2997,28 @@ dummy_func(
|
|||
CALL_ALLOC_AND_ENTER_INIT,
|
||||
};
|
||||
|
||||
op(_SPECIALIZE_CALL, (counter/1, callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) {
|
||||
TIER_ONE_ONLY
|
||||
#if ENABLE_SPECIALIZATION
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
|
||||
next_instr = this_instr;
|
||||
_Py_Specialize_Call(callable, next_instr, oparg + (self_or_null != NULL));
|
||||
DISPATCH_SAME_OPARG();
|
||||
}
|
||||
STAT_INC(CALL, deferred);
|
||||
DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache);
|
||||
#endif /* ENABLE_SPECIALIZATION */
|
||||
}
|
||||
|
||||
// When calling Python, inline the call using DISPATCH_INLINED().
|
||||
inst(CALL, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) {
|
||||
op(_CALL, (unused/2, callable, self_or_null, args[oparg] -- res)) {
|
||||
// oparg counts all of the args, but *not* self:
|
||||
int total_args = oparg;
|
||||
if (self_or_null != NULL) {
|
||||
args--;
|
||||
total_args++;
|
||||
}
|
||||
#if ENABLE_SPECIALIZATION
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(this_instr[1].cache)) {
|
||||
next_instr = this_instr;
|
||||
_Py_Specialize_Call(callable, next_instr, total_args);
|
||||
DISPATCH_SAME_OPARG();
|
||||
}
|
||||
STAT_INC(CALL, deferred);
|
||||
DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache);
|
||||
#endif /* ENABLE_SPECIALIZATION */
|
||||
if (self_or_null == NULL && Py_TYPE(callable) == &PyMethod_Type) {
|
||||
else if (Py_TYPE(callable) == &PyMethod_Type) {
|
||||
args--;
|
||||
total_args++;
|
||||
PyObject *self = ((PyMethodObject *)callable)->im_self;
|
||||
|
@ -3017,6 +3081,8 @@ dummy_func(
|
|||
CHECK_EVAL_BREAKER();
|
||||
}
|
||||
|
||||
macro(CALL) = _SPECIALIZE_CALL + _CALL;
|
||||
|
||||
op(_CHECK_CALL_BOUND_METHOD_EXACT_ARGS, (callable, null, unused[oparg] -- callable, null, unused[oparg])) {
|
||||
DEOPT_IF(null != NULL);
|
||||
DEOPT_IF(Py_TYPE(callable) != &PyMethod_Type);
|
||||
|
@ -3799,9 +3865,10 @@ dummy_func(
|
|||
top = Py_NewRef(bottom);
|
||||
}
|
||||
|
||||
inst(BINARY_OP, (unused/1, lhs, rhs -- res)) {
|
||||
op(_SPECIALIZE_BINARY_OP, (counter/1, lhs, rhs -- lhs, rhs)) {
|
||||
TIER_ONE_ONLY
|
||||
#if ENABLE_SPECIALIZATION
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(this_instr[1].cache)) {
|
||||
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
|
||||
next_instr = this_instr;
|
||||
_Py_Specialize_BinaryOp(lhs, rhs, next_instr, oparg, LOCALS_ARRAY);
|
||||
DISPATCH_SAME_OPARG();
|
||||
|
@ -3811,12 +3878,17 @@ dummy_func(
|
|||
#endif /* ENABLE_SPECIALIZATION */
|
||||
assert(NB_ADD <= oparg);
|
||||
assert(oparg <= NB_INPLACE_XOR);
|
||||
}
|
||||
|
||||
op(_BINARY_OP, (lhs, rhs -- res)) {
|
||||
assert(_PyEval_BinaryOps[oparg]);
|
||||
res = _PyEval_BinaryOps[oparg](lhs, rhs);
|
||||
DECREF_INPUTS();
|
||||
ERROR_IF(res == NULL, error);
|
||||
}
|
||||
|
||||
macro(BINARY_OP) = _SPECIALIZE_BINARY_OP + _BINARY_OP;
|
||||
|
||||
inst(SWAP, (bottom, unused[oparg-2], top --
|
||||
top, unused[oparg-2], bottom)) {
|
||||
assert(oparg >= 2);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue