mirror of
https://github.com/python/cpython.git
synced 2025-10-21 06:02:21 +00:00
GH-111485: Generate instruction and uop metadata (GH-113287)
This commit is contained in:
parent
a545a86ec6
commit
e96f26083b
27 changed files with 1738 additions and 1269 deletions
|
@ -4,7 +4,7 @@
|
|||
#include "pycore_code.h" // write_location_entry_start()
|
||||
#include "pycore_compile.h"
|
||||
#include "pycore_opcode_utils.h" // IS_BACKWARDS_JUMP_OPCODE
|
||||
#include "pycore_opcode_metadata.h" // IS_PSEUDO_INSTR, _PyOpcode_Caches
|
||||
#include "pycore_opcode_metadata.h" // is_pseudo_target, _PyOpcode_Caches
|
||||
|
||||
|
||||
#define DEFAULT_CODE_SIZE 128
|
||||
|
@ -710,13 +710,13 @@ resolve_unconditional_jumps(instr_sequence *instrs)
|
|||
bool is_forward = (instr->i_oparg > i);
|
||||
switch(instr->i_opcode) {
|
||||
case JUMP:
|
||||
assert(SAME_OPCODE_METADATA(JUMP, JUMP_FORWARD));
|
||||
assert(SAME_OPCODE_METADATA(JUMP, JUMP_BACKWARD));
|
||||
assert(is_pseudo_target(JUMP, JUMP_FORWARD));
|
||||
assert(is_pseudo_target(JUMP, JUMP_BACKWARD));
|
||||
instr->i_opcode = is_forward ? JUMP_FORWARD : JUMP_BACKWARD;
|
||||
break;
|
||||
case JUMP_NO_INTERRUPT:
|
||||
assert(SAME_OPCODE_METADATA(JUMP_NO_INTERRUPT, JUMP_FORWARD));
|
||||
assert(SAME_OPCODE_METADATA(JUMP_NO_INTERRUPT, JUMP_BACKWARD_NO_INTERRUPT));
|
||||
assert(is_pseudo_target(JUMP_NO_INTERRUPT, JUMP_FORWARD));
|
||||
assert(is_pseudo_target(JUMP_NO_INTERRUPT, JUMP_BACKWARD_NO_INTERRUPT));
|
||||
instr->i_opcode = is_forward ?
|
||||
JUMP_FORWARD : JUMP_BACKWARD_NO_INTERRUPT;
|
||||
break;
|
||||
|
|
|
@ -330,14 +330,14 @@ dummy_func(
|
|||
#endif /* ENABLE_SPECIALIZATION */
|
||||
}
|
||||
|
||||
op(_TO_BOOL, (unused/2, value -- res)) {
|
||||
op(_TO_BOOL, (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;
|
||||
macro(TO_BOOL) = _SPECIALIZE_TO_BOOL + unused/2 + _TO_BOOL;
|
||||
|
||||
inst(TO_BOOL_BOOL, (unused/1, unused/2, value -- value)) {
|
||||
DEOPT_IF(!PyBool_Check(value));
|
||||
|
@ -416,7 +416,7 @@ dummy_func(
|
|||
DEOPT_IF(!PyLong_CheckExact(right));
|
||||
}
|
||||
|
||||
op(_BINARY_OP_MULTIPLY_INT, (unused/1, left, right -- res)) {
|
||||
op(_BINARY_OP_MULTIPLY_INT, (left, right -- res)) {
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
res = _PyLong_Multiply((PyLongObject *)left, (PyLongObject *)right);
|
||||
_Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
|
||||
|
@ -424,7 +424,7 @@ dummy_func(
|
|||
ERROR_IF(res == NULL, error);
|
||||
}
|
||||
|
||||
op(_BINARY_OP_ADD_INT, (unused/1, left, right -- res)) {
|
||||
op(_BINARY_OP_ADD_INT, (left, right -- res)) {
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
res = _PyLong_Add((PyLongObject *)left, (PyLongObject *)right);
|
||||
_Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
|
||||
|
@ -432,7 +432,7 @@ dummy_func(
|
|||
ERROR_IF(res == NULL, error);
|
||||
}
|
||||
|
||||
op(_BINARY_OP_SUBTRACT_INT, (unused/1, left, right -- res)) {
|
||||
op(_BINARY_OP_SUBTRACT_INT, (left, right -- res)) {
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
res = _PyLong_Subtract((PyLongObject *)left, (PyLongObject *)right);
|
||||
_Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
|
||||
|
@ -441,18 +441,18 @@ dummy_func(
|
|||
}
|
||||
|
||||
macro(BINARY_OP_MULTIPLY_INT) =
|
||||
_GUARD_BOTH_INT + _BINARY_OP_MULTIPLY_INT;
|
||||
_GUARD_BOTH_INT + unused/1 + _BINARY_OP_MULTIPLY_INT;
|
||||
macro(BINARY_OP_ADD_INT) =
|
||||
_GUARD_BOTH_INT + _BINARY_OP_ADD_INT;
|
||||
_GUARD_BOTH_INT + unused/1 + _BINARY_OP_ADD_INT;
|
||||
macro(BINARY_OP_SUBTRACT_INT) =
|
||||
_GUARD_BOTH_INT + _BINARY_OP_SUBTRACT_INT;
|
||||
_GUARD_BOTH_INT + unused/1 + _BINARY_OP_SUBTRACT_INT;
|
||||
|
||||
op(_GUARD_BOTH_FLOAT, (left, right -- left, right)) {
|
||||
DEOPT_IF(!PyFloat_CheckExact(left));
|
||||
DEOPT_IF(!PyFloat_CheckExact(right));
|
||||
}
|
||||
|
||||
op(_BINARY_OP_MULTIPLY_FLOAT, (unused/1, left, right -- res)) {
|
||||
op(_BINARY_OP_MULTIPLY_FLOAT, (left, right -- res)) {
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
double dres =
|
||||
((PyFloatObject *)left)->ob_fval *
|
||||
|
@ -460,7 +460,7 @@ dummy_func(
|
|||
DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res);
|
||||
}
|
||||
|
||||
op(_BINARY_OP_ADD_FLOAT, (unused/1, left, right -- res)) {
|
||||
op(_BINARY_OP_ADD_FLOAT, (left, right -- res)) {
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
double dres =
|
||||
((PyFloatObject *)left)->ob_fval +
|
||||
|
@ -468,7 +468,7 @@ dummy_func(
|
|||
DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res);
|
||||
}
|
||||
|
||||
op(_BINARY_OP_SUBTRACT_FLOAT, (unused/1, left, right -- res)) {
|
||||
op(_BINARY_OP_SUBTRACT_FLOAT, (left, right -- res)) {
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
double dres =
|
||||
((PyFloatObject *)left)->ob_fval -
|
||||
|
@ -477,18 +477,18 @@ dummy_func(
|
|||
}
|
||||
|
||||
macro(BINARY_OP_MULTIPLY_FLOAT) =
|
||||
_GUARD_BOTH_FLOAT + _BINARY_OP_MULTIPLY_FLOAT;
|
||||
_GUARD_BOTH_FLOAT + unused/1 + _BINARY_OP_MULTIPLY_FLOAT;
|
||||
macro(BINARY_OP_ADD_FLOAT) =
|
||||
_GUARD_BOTH_FLOAT + _BINARY_OP_ADD_FLOAT;
|
||||
_GUARD_BOTH_FLOAT + unused/1 + _BINARY_OP_ADD_FLOAT;
|
||||
macro(BINARY_OP_SUBTRACT_FLOAT) =
|
||||
_GUARD_BOTH_FLOAT + _BINARY_OP_SUBTRACT_FLOAT;
|
||||
_GUARD_BOTH_FLOAT + unused/1 + _BINARY_OP_SUBTRACT_FLOAT;
|
||||
|
||||
op(_GUARD_BOTH_UNICODE, (left, right -- left, right)) {
|
||||
DEOPT_IF(!PyUnicode_CheckExact(left));
|
||||
DEOPT_IF(!PyUnicode_CheckExact(right));
|
||||
}
|
||||
|
||||
op(_BINARY_OP_ADD_UNICODE, (unused/1, left, right -- res)) {
|
||||
op(_BINARY_OP_ADD_UNICODE, (left, right -- res)) {
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
res = PyUnicode_Concat(left, right);
|
||||
_Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc);
|
||||
|
@ -497,7 +497,7 @@ dummy_func(
|
|||
}
|
||||
|
||||
macro(BINARY_OP_ADD_UNICODE) =
|
||||
_GUARD_BOTH_UNICODE + _BINARY_OP_ADD_UNICODE;
|
||||
_GUARD_BOTH_UNICODE + unused/1 + _BINARY_OP_ADD_UNICODE;
|
||||
|
||||
// This is a subtle one. It's a super-instruction for
|
||||
// BINARY_OP_ADD_UNICODE followed by STORE_FAST
|
||||
|
@ -505,7 +505,7 @@ dummy_func(
|
|||
// So the inputs are the same as for all BINARY_OP
|
||||
// specializations, but there is no output.
|
||||
// At the end we just skip over the STORE_FAST.
|
||||
op(_BINARY_OP_INPLACE_ADD_UNICODE, (unused/1, left, right --)) {
|
||||
op(_BINARY_OP_INPLACE_ADD_UNICODE, (left, right --)) {
|
||||
TIER_ONE_ONLY
|
||||
assert(next_instr->op.code == STORE_FAST);
|
||||
PyObject **target_local = &GETLOCAL(next_instr->op.arg);
|
||||
|
@ -533,7 +533,7 @@ dummy_func(
|
|||
}
|
||||
|
||||
macro(BINARY_OP_INPLACE_ADD_UNICODE) =
|
||||
_GUARD_BOTH_UNICODE + _BINARY_OP_INPLACE_ADD_UNICODE;
|
||||
_GUARD_BOTH_UNICODE + unused/1 + _BINARY_OP_INPLACE_ADD_UNICODE;
|
||||
|
||||
family(BINARY_SUBSCR, INLINE_CACHE_ENTRIES_BINARY_SUBSCR) = {
|
||||
BINARY_SUBSCR_DICT,
|
||||
|
@ -1295,14 +1295,14 @@ dummy_func(
|
|||
#endif /* ENABLE_SPECIALIZATION */
|
||||
}
|
||||
|
||||
op(_STORE_ATTR, (unused/3, v, owner --)) {
|
||||
op(_STORE_ATTR, (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;
|
||||
macro(STORE_ATTR) = _SPECIALIZE_STORE_ATTR + unused/3 + _STORE_ATTR;
|
||||
|
||||
inst(DELETE_ATTR, (owner --)) {
|
||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
|
||||
|
@ -1414,7 +1414,7 @@ dummy_func(
|
|||
#endif /* ENABLE_SPECIALIZATION */
|
||||
}
|
||||
|
||||
op(_LOAD_GLOBAL, (unused/1, unused/1, unused/1 -- res, null if (oparg & 1))) {
|
||||
op(_LOAD_GLOBAL, ( -- res, null if (oparg & 1))) {
|
||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
|
||||
if (PyDict_CheckExact(GLOBALS())
|
||||
&& PyDict_CheckExact(BUILTINS()))
|
||||
|
@ -1451,7 +1451,12 @@ dummy_func(
|
|||
null = NULL;
|
||||
}
|
||||
|
||||
macro(LOAD_GLOBAL) = _SPECIALIZE_LOAD_GLOBAL + _LOAD_GLOBAL;
|
||||
macro(LOAD_GLOBAL) =
|
||||
_SPECIALIZE_LOAD_GLOBAL +
|
||||
counter/1 +
|
||||
globals_version/1 +
|
||||
builtins_version/1 +
|
||||
_LOAD_GLOBAL;
|
||||
|
||||
op(_GUARD_GLOBALS_VERSION, (version/1 --)) {
|
||||
PyDictObject *dict = (PyDictObject *)GLOBALS();
|
||||
|
@ -1853,7 +1858,7 @@ dummy_func(
|
|||
#endif /* ENABLE_SPECIALIZATION */
|
||||
}
|
||||
|
||||
op(_LOAD_ATTR, (unused/8, owner -- attr, self_or_null if (oparg & 1))) {
|
||||
op(_LOAD_ATTR, (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. */
|
||||
|
@ -1886,7 +1891,10 @@ dummy_func(
|
|||
}
|
||||
}
|
||||
|
||||
macro(LOAD_ATTR) = _SPECIALIZE_LOAD_ATTR + _LOAD_ATTR;
|
||||
macro(LOAD_ATTR) =
|
||||
_SPECIALIZE_LOAD_ATTR +
|
||||
unused/8 +
|
||||
_LOAD_ATTR;
|
||||
|
||||
pseudo(LOAD_METHOD) = {
|
||||
LOAD_ATTR,
|
||||
|
@ -2369,7 +2377,7 @@ dummy_func(
|
|||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
}
|
||||
|
||||
replaced op(_POP_JUMP_IF_FALSE, (unused/1, cond -- )) {
|
||||
replaced op(_POP_JUMP_IF_FALSE, (cond -- )) {
|
||||
assert(PyBool_Check(cond));
|
||||
int flag = Py_IsFalse(cond);
|
||||
#if ENABLE_SPECIALIZATION
|
||||
|
@ -2378,7 +2386,7 @@ dummy_func(
|
|||
JUMPBY(oparg * flag);
|
||||
}
|
||||
|
||||
replaced op(_POP_JUMP_IF_TRUE, (unused/1, cond -- )) {
|
||||
replaced op(_POP_JUMP_IF_TRUE, (cond -- )) {
|
||||
assert(PyBool_Check(cond));
|
||||
int flag = Py_IsTrue(cond);
|
||||
#if ENABLE_SPECIALIZATION
|
||||
|
@ -2397,13 +2405,13 @@ dummy_func(
|
|||
}
|
||||
}
|
||||
|
||||
macro(POP_JUMP_IF_TRUE) = _POP_JUMP_IF_TRUE;
|
||||
macro(POP_JUMP_IF_TRUE) = unused/1 + _POP_JUMP_IF_TRUE;
|
||||
|
||||
macro(POP_JUMP_IF_FALSE) = _POP_JUMP_IF_FALSE;
|
||||
macro(POP_JUMP_IF_FALSE) = unused/1 + _POP_JUMP_IF_FALSE;
|
||||
|
||||
macro(POP_JUMP_IF_NONE) = _IS_NONE + _POP_JUMP_IF_TRUE;
|
||||
macro(POP_JUMP_IF_NONE) = unused/1 + _IS_NONE + _POP_JUMP_IF_TRUE;
|
||||
|
||||
macro(POP_JUMP_IF_NOT_NONE) = _IS_NONE + _POP_JUMP_IF_FALSE;
|
||||
macro(POP_JUMP_IF_NOT_NONE) = unused/1 + _IS_NONE + _POP_JUMP_IF_FALSE;
|
||||
|
||||
inst(JUMP_BACKWARD_NO_INTERRUPT, (--)) {
|
||||
TIER_ONE_ONLY
|
||||
|
@ -3010,7 +3018,7 @@ dummy_func(
|
|||
}
|
||||
|
||||
// When calling Python, inline the call using DISPATCH_INLINED().
|
||||
op(_CALL, (unused/2, callable, self_or_null, args[oparg] -- res)) {
|
||||
op(_CALL, (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) {
|
||||
|
@ -3079,7 +3087,7 @@ dummy_func(
|
|||
CHECK_EVAL_BREAKER();
|
||||
}
|
||||
|
||||
macro(CALL) = _SPECIALIZE_CALL + _CALL;
|
||||
macro(CALL) = _SPECIALIZE_CALL + unused/2 + _CALL;
|
||||
|
||||
op(_CHECK_CALL_BOUND_METHOD_EXACT_ARGS, (callable, null, unused[oparg] -- callable, null, unused[oparg])) {
|
||||
DEOPT_IF(null != NULL);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "pycore_sysmodule.h" // _PySys_Audit()
|
||||
#include "pycore_tuple.h" // _PyTuple_ITEMS()
|
||||
#include "pycore_typeobject.h" // _PySuper_Lookup()
|
||||
#include "pycore_uop_ids.h" // Uops
|
||||
#include "pycore_uops.h" // _PyUOpExecutorObject
|
||||
#include "pycore_pyerrors.h"
|
||||
|
||||
|
|
|
@ -796,35 +796,12 @@ stack_effect(int opcode, int oparg, int jump)
|
|||
// Specialized instructions are not supported.
|
||||
return PY_INVALID_STACK_EFFECT;
|
||||
}
|
||||
int popped, pushed;
|
||||
if (jump > 0) {
|
||||
popped = _PyOpcode_num_popped(opcode, oparg, true);
|
||||
pushed = _PyOpcode_num_pushed(opcode, oparg, true);
|
||||
}
|
||||
else {
|
||||
popped = _PyOpcode_num_popped(opcode, oparg, false);
|
||||
pushed = _PyOpcode_num_pushed(opcode, oparg, false);
|
||||
}
|
||||
int popped = _PyOpcode_num_popped(opcode, oparg);
|
||||
int pushed = _PyOpcode_num_pushed(opcode, oparg);
|
||||
if (popped < 0 || pushed < 0) {
|
||||
return PY_INVALID_STACK_EFFECT;
|
||||
}
|
||||
if (jump >= 0) {
|
||||
return pushed - popped;
|
||||
}
|
||||
if (jump < 0) {
|
||||
// Compute max(pushed - popped, alt_pushed - alt_popped)
|
||||
int alt_popped = _PyOpcode_num_popped(opcode, oparg, true);
|
||||
int alt_pushed = _PyOpcode_num_pushed(opcode, oparg, true);
|
||||
if (alt_popped < 0 || alt_pushed < 0) {
|
||||
return PY_INVALID_STACK_EFFECT;
|
||||
}
|
||||
int diff = pushed - popped;
|
||||
int alt_diff = alt_pushed - alt_popped;
|
||||
if (alt_diff > diff) {
|
||||
return alt_diff;
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
return pushed - popped;
|
||||
}
|
||||
|
||||
// Pseudo ops
|
||||
|
@ -1125,7 +1102,7 @@ compiler_addop_name(struct compiler_unit *u, location loc,
|
|||
arg <<= 1;
|
||||
}
|
||||
if (opcode == LOAD_METHOD) {
|
||||
assert(SAME_OPCODE_METADATA(LOAD_METHOD, LOAD_ATTR));
|
||||
assert(is_pseudo_target(LOAD_METHOD, LOAD_ATTR));
|
||||
opcode = LOAD_ATTR;
|
||||
arg <<= 1;
|
||||
arg |= 1;
|
||||
|
@ -1135,18 +1112,18 @@ compiler_addop_name(struct compiler_unit *u, location loc,
|
|||
arg |= 2;
|
||||
}
|
||||
if (opcode == LOAD_SUPER_METHOD) {
|
||||
assert(SAME_OPCODE_METADATA(LOAD_SUPER_METHOD, LOAD_SUPER_ATTR));
|
||||
assert(is_pseudo_target(LOAD_SUPER_METHOD, LOAD_SUPER_ATTR));
|
||||
opcode = LOAD_SUPER_ATTR;
|
||||
arg <<= 2;
|
||||
arg |= 3;
|
||||
}
|
||||
if (opcode == LOAD_ZERO_SUPER_ATTR) {
|
||||
assert(SAME_OPCODE_METADATA(LOAD_ZERO_SUPER_ATTR, LOAD_SUPER_ATTR));
|
||||
assert(is_pseudo_target(LOAD_ZERO_SUPER_ATTR, LOAD_SUPER_ATTR));
|
||||
opcode = LOAD_SUPER_ATTR;
|
||||
arg <<= 2;
|
||||
}
|
||||
if (opcode == LOAD_ZERO_SUPER_METHOD) {
|
||||
assert(SAME_OPCODE_METADATA(LOAD_ZERO_SUPER_METHOD, LOAD_SUPER_ATTR));
|
||||
assert(is_pseudo_target(LOAD_ZERO_SUPER_METHOD, LOAD_SUPER_ATTR));
|
||||
opcode = LOAD_SUPER_ATTR;
|
||||
arg <<= 2;
|
||||
arg |= 1;
|
||||
|
|
|
@ -2258,11 +2258,11 @@ convert_pseudo_ops(basicblock *entryblock)
|
|||
INSTR_SET_OP0(instr, NOP);
|
||||
}
|
||||
else if (instr->i_opcode == LOAD_CLOSURE) {
|
||||
assert(SAME_OPCODE_METADATA(LOAD_CLOSURE, LOAD_FAST));
|
||||
assert(is_pseudo_target(LOAD_CLOSURE, LOAD_FAST));
|
||||
instr->i_opcode = LOAD_FAST;
|
||||
}
|
||||
else if (instr->i_opcode == STORE_FAST_MAYBE_NULL) {
|
||||
assert(SAME_OPCODE_METADATA(STORE_FAST_MAYBE_NULL, STORE_FAST));
|
||||
assert(is_pseudo_target(STORE_FAST_MAYBE_NULL, STORE_FAST));
|
||||
instr->i_opcode = STORE_FAST;
|
||||
}
|
||||
}
|
||||
|
|
19
Python/generated_cases.c.h
generated
19
Python/generated_cases.c.h
generated
|
@ -153,6 +153,7 @@
|
|||
DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP);
|
||||
DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP);
|
||||
}
|
||||
/* Skip 1 cache entry */
|
||||
// _BINARY_OP_ADD_FLOAT
|
||||
{
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
|
@ -181,6 +182,7 @@
|
|||
DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP);
|
||||
DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP);
|
||||
}
|
||||
/* Skip 1 cache entry */
|
||||
// _BINARY_OP_ADD_INT
|
||||
{
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
|
@ -209,6 +211,7 @@
|
|||
DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP);
|
||||
DEOPT_IF(!PyUnicode_CheckExact(right), BINARY_OP);
|
||||
}
|
||||
/* Skip 1 cache entry */
|
||||
// _BINARY_OP_ADD_UNICODE
|
||||
{
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
|
@ -236,6 +239,7 @@
|
|||
DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP);
|
||||
DEOPT_IF(!PyUnicode_CheckExact(right), BINARY_OP);
|
||||
}
|
||||
/* Skip 1 cache entry */
|
||||
// _BINARY_OP_INPLACE_ADD_UNICODE
|
||||
{
|
||||
TIER_ONE_ONLY
|
||||
|
@ -282,6 +286,7 @@
|
|||
DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP);
|
||||
DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP);
|
||||
}
|
||||
/* Skip 1 cache entry */
|
||||
// _BINARY_OP_MULTIPLY_FLOAT
|
||||
{
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
|
@ -310,6 +315,7 @@
|
|||
DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP);
|
||||
DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP);
|
||||
}
|
||||
/* Skip 1 cache entry */
|
||||
// _BINARY_OP_MULTIPLY_INT
|
||||
{
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
|
@ -338,6 +344,7 @@
|
|||
DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP);
|
||||
DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP);
|
||||
}
|
||||
/* Skip 1 cache entry */
|
||||
// _BINARY_OP_SUBTRACT_FLOAT
|
||||
{
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
|
@ -366,6 +373,7 @@
|
|||
DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP);
|
||||
DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP);
|
||||
}
|
||||
/* Skip 1 cache entry */
|
||||
// _BINARY_OP_SUBTRACT_INT
|
||||
{
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
|
@ -763,6 +771,7 @@
|
|||
DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache);
|
||||
#endif /* ENABLE_SPECIALIZATION */
|
||||
}
|
||||
/* Skip 2 cache entries */
|
||||
// _CALL
|
||||
{
|
||||
// oparg counts all of the args, but *not* self:
|
||||
|
@ -3400,6 +3409,7 @@
|
|||
DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache);
|
||||
#endif /* ENABLE_SPECIALIZATION */
|
||||
}
|
||||
/* Skip 8 cache entries */
|
||||
// _LOAD_ATTR
|
||||
{
|
||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
|
||||
|
@ -4096,6 +4106,9 @@
|
|||
DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache);
|
||||
#endif /* ENABLE_SPECIALIZATION */
|
||||
}
|
||||
/* Skip 1 cache entry */
|
||||
/* Skip 1 cache entry */
|
||||
/* Skip 1 cache entry */
|
||||
// _LOAD_GLOBAL
|
||||
{
|
||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
|
||||
|
@ -4564,6 +4577,7 @@
|
|||
next_instr += 2;
|
||||
INSTRUCTION_STATS(POP_JUMP_IF_FALSE);
|
||||
PyObject *cond;
|
||||
/* Skip 1 cache entry */
|
||||
cond = stack_pointer[-1];
|
||||
assert(PyBool_Check(cond));
|
||||
int flag = Py_IsFalse(cond);
|
||||
|
@ -4582,6 +4596,7 @@
|
|||
PyObject *value;
|
||||
PyObject *b;
|
||||
PyObject *cond;
|
||||
/* Skip 1 cache entry */
|
||||
// _IS_NONE
|
||||
value = stack_pointer[-1];
|
||||
{
|
||||
|
@ -4614,6 +4629,7 @@
|
|||
PyObject *value;
|
||||
PyObject *b;
|
||||
PyObject *cond;
|
||||
/* Skip 1 cache entry */
|
||||
// _IS_NONE
|
||||
value = stack_pointer[-1];
|
||||
{
|
||||
|
@ -4644,6 +4660,7 @@
|
|||
next_instr += 2;
|
||||
INSTRUCTION_STATS(POP_JUMP_IF_TRUE);
|
||||
PyObject *cond;
|
||||
/* Skip 1 cache entry */
|
||||
cond = stack_pointer[-1];
|
||||
assert(PyBool_Check(cond));
|
||||
int flag = Py_IsTrue(cond);
|
||||
|
@ -5117,6 +5134,7 @@
|
|||
DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache);
|
||||
#endif /* ENABLE_SPECIALIZATION */
|
||||
}
|
||||
/* Skip 3 cache entries */
|
||||
// _STORE_ATTR
|
||||
v = stack_pointer[-2];
|
||||
{
|
||||
|
@ -5509,6 +5527,7 @@
|
|||
DECREMENT_ADAPTIVE_COUNTER(this_instr[1].cache);
|
||||
#endif /* ENABLE_SPECIALIZATION */
|
||||
}
|
||||
/* Skip 2 cache entries */
|
||||
// _TO_BOOL
|
||||
{
|
||||
int err = PyObject_IsTrue(value);
|
||||
|
|
|
@ -6,14 +6,20 @@
|
|||
#include "pycore_opcode_utils.h" // MAX_REAL_OPCODE
|
||||
#include "pycore_optimizer.h" // _Py_uop_analyze_and_optimize()
|
||||
#include "pycore_pystate.h" // _PyInterpreterState_GET()
|
||||
#include "pycore_uop_ids.h"
|
||||
#include "pycore_uops.h"
|
||||
#include "cpython/optimizer.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define NEED_OPCODE_METADATA
|
||||
#include "pycore_uop_metadata.h" // Uop tables
|
||||
#undef NEED_OPCODE_METADATA
|
||||
|
||||
#define MAX_EXECUTORS_SIZE 256
|
||||
|
||||
|
||||
static bool
|
||||
has_space_for_executor(PyCodeObject *code, _Py_CODEUNIT *instr)
|
||||
{
|
||||
|
@ -327,9 +333,6 @@ uop_dealloc(_PyUOpExecutorObject *self) {
|
|||
const char *
|
||||
_PyUOpName(int index)
|
||||
{
|
||||
if (index <= MAX_REAL_OPCODE) {
|
||||
return _PyOpcode_OpName[index];
|
||||
}
|
||||
return _PyOpcode_uop_name[index];
|
||||
}
|
||||
|
||||
|
@ -388,7 +391,7 @@ PyTypeObject _PyUOpExecutor_Type = {
|
|||
|
||||
/* TO DO -- Generate these tables */
|
||||
static const uint16_t
|
||||
_PyUOp_Replacements[OPCODE_METADATA_SIZE] = {
|
||||
_PyUOp_Replacements[MAX_UOP_ID + 1] = {
|
||||
[_ITER_JUMP_RANGE] = _GUARD_NOT_EXHAUSTED_RANGE,
|
||||
[_ITER_JUMP_LIST] = _GUARD_NOT_EXHAUSTED_LIST,
|
||||
[_ITER_JUMP_TUPLE] = _GUARD_NOT_EXHAUSTED_TUPLE,
|
||||
|
@ -629,14 +632,6 @@ top: // Jump here after _PUSH_FRAME or likely branches
|
|||
oparg += extras;
|
||||
}
|
||||
}
|
||||
if (_PyUOp_Replacements[uop]) {
|
||||
uop = _PyUOp_Replacements[uop];
|
||||
if (uop == _FOR_ITER_TIER_TWO) {
|
||||
target += 1 + INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1;
|
||||
assert(_PyCode_CODE(code)[target-1].op.code == END_FOR ||
|
||||
_PyCode_CODE(code)[target-1].op.code == INSTRUMENTED_END_FOR);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OPARG_CACHE_1:
|
||||
operand = read_u16(&instr[offset].cache);
|
||||
|
@ -657,7 +652,15 @@ top: // Jump here after _PUSH_FRAME or likely branches
|
|||
oparg = offset;
|
||||
assert(uop == _SAVE_RETURN_OFFSET);
|
||||
break;
|
||||
|
||||
case OPARG_REPLACED:
|
||||
uop = _PyUOp_Replacements[uop];
|
||||
assert(uop != 0);
|
||||
if (uop == _FOR_ITER_TIER_TWO) {
|
||||
target += 1 + INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1;
|
||||
assert(_PyCode_CODE(code)[target-1].op.code == END_FOR ||
|
||||
_PyCode_CODE(code)[target-1].op.code == INSTRUMENTED_END_FOR);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,
|
||||
"opcode=%d, oparg=%d; nuops=%d, i=%d; size=%d, offset=%d\n",
|
||||
|
@ -799,7 +802,8 @@ compute_used(_PyUOpInstruction *buffer, uint32_t *used)
|
|||
}
|
||||
/* All other micro-ops fall through, so i+1 is reachable */
|
||||
SET_BIT(used, i+1);
|
||||
if (OPCODE_HAS_JUMP(opcode)) {
|
||||
assert(opcode <= MAX_UOP_ID);
|
||||
if (_PyUop_Flags[opcode] & HAS_JUMP_FLAG) {
|
||||
/* Mark target as reachable */
|
||||
SET_BIT(used, buffer[i].oparg);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "pycore_moduleobject.h"
|
||||
#include "pycore_object.h"
|
||||
#include "pycore_opcode_metadata.h" // _PyOpcode_Caches
|
||||
#include "pycore_uop_metadata.h" // _PyOpcode_uop_name
|
||||
#include "pycore_opcode_utils.h" // RESUME_AT_FUNC_START
|
||||
#include "pycore_pylifecycle.h" // _PyOS_URandomNonblock()
|
||||
#include "pycore_runtime.h" // _Py_ID()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue