Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

gh-105481: add OPCODE_IS_INSTRUMENTED (generated from bytecodes.c) to replace MIN_INSTRUMENTED_OPCODE (defined in opcode.py) #107276

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
gh-105481: add OPCODE_IS_INSTRUMENTED (generated from bytecodes.c) to…
… replace MIN_INSTRUMENTED_OPCODE (defined in opcode.py)
  • Loading branch information
iritkatriel committed Jul 25, 2023
commit d64208367eadd0c36fc93097819c7bdacfc51df6
1 change: 1 addition & 0 deletions 1 Include/cpython/compile.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ PyAPI_FUNC(int) PyUnstable_OpcodeHasJump(int opcode);
PyAPI_FUNC(int) PyUnstable_OpcodeHasFree(int opcode);
PyAPI_FUNC(int) PyUnstable_OpcodeHasLocal(int opcode);
PyAPI_FUNC(int) PyUnstable_OpcodeHasExc(int opcode);
PyAPI_FUNC(int) PyUnstable_OpcodeIsInstrumented(int opcode);

PyAPI_FUNC(PyObject*) _PyUnstable_GetUnaryIntrinsicName(int index);
PyAPI_FUNC(PyObject*) _PyUnstable_GetBinaryIntrinsicName(int index);
36 changes: 19 additions & 17 deletions 36 Include/internal/pycore_opcode_metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -957,12 +957,14 @@ enum InstructionFormat { INSTR_FMT_IB, INSTR_FMT_IBC, INSTR_FMT_IBC00, INSTR_FMT
#define HAS_JUMP_FLAG (8)
#define HAS_FREE_FLAG (16)
#define HAS_LOCAL_FLAG (32)
#define IS_INSTRUMENTED_FLAG (64)
#define OPCODE_HAS_ARG(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_ARG_FLAG))
#define OPCODE_HAS_CONST(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_CONST_FLAG))
#define OPCODE_HAS_NAME(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_NAME_FLAG))
#define OPCODE_HAS_JUMP(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_JUMP_FLAG))
#define OPCODE_HAS_FREE(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_FREE_FLAG))
#define OPCODE_HAS_LOCAL(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_LOCAL_FLAG))
#define OPCODE_IS_INSTRUMENTED(OP) (_PyOpcode_opcode_metadata[OP].flags & (IS_INSTRUMENTED_FLAG))

struct opcode_metadata {
bool valid_entry;
Expand Down Expand Up @@ -998,7 +1000,7 @@ extern const char * const _PyOpcode_uop_name[OPCODE_UOP_NAME_SIZE];
const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = {
[NOP] = { true, INSTR_FMT_IX, 0 },
[RESUME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
[INSTRUMENTED_RESUME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
[INSTRUMENTED_RESUME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | IS_INSTRUMENTED_FLAG },
[LOAD_CLOSURE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG },
[LOAD_FAST_CHECK] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG },
[LOAD_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG },
Expand All @@ -1012,9 +1014,9 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = {
[POP_TOP] = { true, INSTR_FMT_IX, 0 },
[PUSH_NULL] = { true, INSTR_FMT_IX, 0 },
[END_FOR] = { true, INSTR_FMT_IB, 0 },
[INSTRUMENTED_END_FOR] = { true, INSTR_FMT_IX, 0 },
[INSTRUMENTED_END_FOR] = { true, INSTR_FMT_IX, IS_INSTRUMENTED_FLAG },
[END_SEND] = { true, INSTR_FMT_IX, 0 },
[INSTRUMENTED_END_SEND] = { true, INSTR_FMT_IX, 0 },
[INSTRUMENTED_END_SEND] = { true, INSTR_FMT_IX, IS_INSTRUMENTED_FLAG },
[UNARY_NEGATIVE] = { true, INSTR_FMT_IX, 0 },
[UNARY_NOT] = { true, INSTR_FMT_IX, 0 },
[TO_BOOL] = { true, INSTR_FMT_IXC00, 0 },
Expand Down Expand Up @@ -1051,15 +1053,15 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = {
[RAISE_VARARGS] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
[INTERPRETER_EXIT] = { true, INSTR_FMT_IX, 0 },
[RETURN_VALUE] = { true, INSTR_FMT_IX, 0 },
[INSTRUMENTED_RETURN_VALUE] = { true, INSTR_FMT_IX, 0 },
[INSTRUMENTED_RETURN_VALUE] = { true, INSTR_FMT_IX, IS_INSTRUMENTED_FLAG },
[RETURN_CONST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG },
[INSTRUMENTED_RETURN_CONST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG },
[INSTRUMENTED_RETURN_CONST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG | IS_INSTRUMENTED_FLAG },
[GET_AITER] = { true, INSTR_FMT_IX, 0 },
[GET_ANEXT] = { true, INSTR_FMT_IX, 0 },
[GET_AWAITABLE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
[SEND] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG },
[SEND_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG },
[INSTRUMENTED_YIELD_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
[INSTRUMENTED_YIELD_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | IS_INSTRUMENTED_FLAG },
[YIELD_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
[POP_EXCEPT] = { true, INSTR_FMT_IX, 0 },
[RERAISE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
Expand Down Expand Up @@ -1103,7 +1105,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = {
[DICT_UPDATE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
[DICT_MERGE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
[MAP_ADD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
[INSTRUMENTED_LOAD_SUPER_ATTR] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG },
[INSTRUMENTED_LOAD_SUPER_ATTR] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | IS_INSTRUMENTED_FLAG },
[LOAD_SUPER_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG },
[LOAD_SUPER_METHOD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG },
[LOAD_ZERO_SUPER_METHOD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG },
Expand Down Expand Up @@ -1150,7 +1152,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = {
[GET_ITER] = { true, INSTR_FMT_IX, 0 },
[GET_YIELD_FROM_ITER] = { true, INSTR_FMT_IX, 0 },
[FOR_ITER] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG },
[INSTRUMENTED_FOR_ITER] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
[INSTRUMENTED_FOR_ITER] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | IS_INSTRUMENTED_FLAG },
[FOR_ITER_LIST] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG },
[FOR_ITER_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG },
[FOR_ITER_RANGE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG },
Expand All @@ -1169,7 +1171,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = {
[LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG },
[LOAD_ATTR_METHOD_LAZY_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG },
[KW_NAMES] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG },
[INSTRUMENTED_CALL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
[INSTRUMENTED_CALL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | IS_INSTRUMENTED_FLAG },
[CALL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
[CALL_BOUND_METHOD_EXACT_ARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
[CALL_PY_EXACT_ARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
Expand All @@ -1190,7 +1192,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = {
[CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
[CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
[CALL_NO_KW_METHOD_DESCRIPTOR_FAST] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
[INSTRUMENTED_CALL_FUNCTION_EX] = { true, INSTR_FMT_IX, 0 },
[INSTRUMENTED_CALL_FUNCTION_EX] = { true, INSTR_FMT_IX, IS_INSTRUMENTED_FLAG },
[CALL_FUNCTION_EX] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
[MAKE_FUNCTION] = { true, INSTR_FMT_IX, 0 },
[SET_FUNCTION_ATTRIBUTE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
Expand All @@ -1202,13 +1204,13 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = {
[COPY] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
[BINARY_OP] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG },
[SWAP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
[INSTRUMENTED_INSTRUCTION] = { true, INSTR_FMT_IX, 0 },
[INSTRUMENTED_JUMP_FORWARD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
[INSTRUMENTED_JUMP_BACKWARD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
[INSTRUMENTED_POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
[INSTRUMENTED_POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
[INSTRUMENTED_POP_JUMP_IF_NONE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
[INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
[INSTRUMENTED_INSTRUCTION] = { true, INSTR_FMT_IX, IS_INSTRUMENTED_FLAG },
[INSTRUMENTED_JUMP_FORWARD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | IS_INSTRUMENTED_FLAG },
[INSTRUMENTED_JUMP_BACKWARD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | IS_INSTRUMENTED_FLAG },
[INSTRUMENTED_POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | IS_INSTRUMENTED_FLAG },
[INSTRUMENTED_POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | IS_INSTRUMENTED_FLAG },
[INSTRUMENTED_POP_JUMP_IF_NONE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | IS_INSTRUMENTED_FLAG },
[INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | IS_INSTRUMENTED_FLAG },
[EXTENDED_ARG] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
[CACHE] = { true, INSTR_FMT_IX, 0 },
[RESERVED] = { true, INSTR_FMT_IX, 0 },
Expand Down
1 change: 0 additions & 1 deletion 1 Include/opcode.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion 1 Lib/opcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,6 @@ def pseudo_op(name, op, real_ops):
def_op('ENTER_EXECUTOR', 230)

# Instrumented instructions
MIN_INSTRUMENTED_OPCODE = 237

def_op('INSTRUMENTED_LOAD_SUPER_ATTR', 237)
def_op('INSTRUMENTED_POP_JUMP_IF_NONE', 238)
Expand Down
1 change: 1 addition & 0 deletions 1 Lib/test/test__opcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ def test_invalid_opcodes(self):
self.check_bool_function_result(_opcode.has_free, invalid, False)
self.check_bool_function_result(_opcode.has_local, invalid, False)
self.check_bool_function_result(_opcode.has_exc, invalid, False)
self.check_bool_function_result(_opcode.is_instrumented, invalid, False)

def test_is_valid(self):
names = [
Expand Down
19 changes: 19 additions & 0 deletions 19 Modules/_opcode.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,24 @@ _opcode_has_exc_impl(PyObject *module, int opcode)
PyUnstable_OpcodeHasExc(opcode);
}

/*[clinic input]

_opcode.is_instrumented -> bool

opcode: int

Return True if the opcode is instrumented, False otherwise.
[clinic start generated code]*/

static int
_opcode_is_instrumented_impl(PyObject *module, int opcode)
/*[clinic end generated code: output=dbfb4dce2bef87c8 input=5122645f4009417a]*/
{
return PyUnstable_OpcodeIsValid(opcode) &&
PyUnstable_OpcodeIsInstrumented(opcode);
}


/*[clinic input]

_opcode.get_specialization_stats
Expand Down Expand Up @@ -286,6 +304,7 @@ opcode_functions[] = {
_OPCODE_HAS_FREE_METHODDEF
_OPCODE_HAS_LOCAL_METHODDEF
_OPCODE_HAS_EXC_METHODDEF
_OPCODE_IS_INSTRUMENTED_METHODDEF
_OPCODE_GET_SPECIALIZATION_STATS_METHODDEF
_OPCODE_GET_INTRINSIC1_DESCS_METHODDEF
_OPCODE_GET_INTRINSIC2_DESCS_METHODDEF
Expand Down
65 changes: 64 additions & 1 deletion 65 Modules/clinic/_opcode.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions 6 Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -915,6 +915,12 @@ PyUnstable_OpcodeHasExc(int opcode)
return IS_BLOCK_PUSH_OPCODE(opcode);
}

int
PyUnstable_OpcodeIsInstrumented(int opcode)
{
return OPCODE_IS_INSTRUMENTED(opcode);
}

static int
codegen_addop_noarg(instr_sequence *seq, int opcode, location loc)
{
Expand Down
7 changes: 4 additions & 3 deletions 7 Python/instrumentation.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
#include "pycore_frame.h"
#include "pycore_interp.h"
#include "pycore_long.h"
#include "pycore_modsupport.h" // _PyModule_CreateInitialized()
#include "pycore_modsupport.h" // _PyModule_CreateInitialized()
#include "pycore_namespace.h"
#include "pycore_object.h"
#include "pycore_opcode.h"
#include "pycore_opcode_metadata.h" // OPCODE_IS_INSTRUMENTED
#include "pycore_pyerrors.h"
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "pycore_pystate.h" // _PyInterpreterState_GET()

/* Uncomment this to dump debugging output when assertions fail */
// #define INSTRUMENT_DEBUG 1
Expand Down Expand Up @@ -130,7 +131,7 @@ is_instrumented(int opcode)
{
assert(opcode != 0);
assert(opcode != RESERVED);
return opcode >= MIN_INSTRUMENTED_OPCODE;
return OPCODE_IS_INSTRUMENTED(opcode);
}

#ifndef NDEBUG
Expand Down
7 changes: 4 additions & 3 deletions 7 Python/specialize.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
#include "pycore_long.h"
#include "pycore_moduleobject.h"
#include "pycore_object.h"
#include "pycore_opcode.h" // _PyOpcode_Caches
#include "pycore_pylifecycle.h" // _PyOS_URandomNonblock()
#include "pycore_opcode.h" // _PyOpcode_Caches
#include "pycore_opcode_metadata.h" // OPCODE_IS_INSTRUMENTED
#include "pycore_pylifecycle.h" // _PyOS_URandomNonblock()


#include <stdlib.h> // rand()
Expand Down Expand Up @@ -279,7 +280,7 @@ _PyCode_Quicken(PyCodeObject *code)
_Py_CODEUNIT *instructions = _PyCode_CODE(code);
for (int i = 0; i < Py_SIZE(code); i++) {
opcode = _Py_GetBaseOpcode(code, i);
assert(opcode < MIN_INSTRUMENTED_OPCODE);
assert(!OPCODE_IS_INSTRUMENTED(opcode));
int caches = _PyOpcode_Caches[opcode];
if (caches) {
instructions[i + 1].cache = adaptive_counter_warmup();
Expand Down
3 changes: 0 additions & 3 deletions 3 Tools/build/generate_opcode_h.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ def main(opcode_py,
ENABLE_SPECIALIZATION = opcode["ENABLE_SPECIALIZATION"]
MIN_PSEUDO_OPCODE = opcode["MIN_PSEUDO_OPCODE"]
MAX_PSEUDO_OPCODE = opcode["MAX_PSEUDO_OPCODE"]
MIN_INSTRUMENTED_OPCODE = opcode["MIN_INSTRUMENTED_OPCODE"]

NUM_OPCODES = len(opname)
used = [ False ] * len(opname)
Expand All @@ -103,8 +102,6 @@ def main(opcode_py,
op = opmap[name]
if op == MIN_PSEUDO_OPCODE:
fobj.write(DEFINE.format("MIN_PSEUDO_OPCODE", MIN_PSEUDO_OPCODE))
if op == MIN_INSTRUMENTED_OPCODE:
fobj.write(DEFINE.format("MIN_INSTRUMENTED_OPCODE", MIN_INSTRUMENTED_OPCODE))

fobj.write(DEFINE.format(name, op))

Expand Down
4 changes: 3 additions & 1 deletion 4 Tools/cases_generator/flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class InstructionFlags:
HAS_JUMP_FLAG: bool
HAS_FREE_FLAG: bool
HAS_LOCAL_FLAG: bool
IS_INSTRUMENTED_FLAG: bool

def __post_init__(self):
self.bitmask = {name: (1 << i) for i, name in enumerate(self.names())}
Expand All @@ -38,11 +39,12 @@ def fromInstruction(instr: parsing.Node):
variable_used(instr, "GETLOCAL") or variable_used(instr, "SETLOCAL")
)
and not has_free,
IS_INSTRUMENTED_FLAG=instr.name.startswith("INSTRUMENTED_"),
)

@staticmethod
def newEmpty():
return InstructionFlags(False, False, False, False, False, False)
return InstructionFlags(False, False, False, False, False, False, False)

def add(self, other: "InstructionFlags") -> None:
for name, value in dataclasses.asdict(other).items():
Expand Down
Morty Proxy This is a proxified and sanitized view of the page, visit original site.