mirror of
https://github.com/python/cpython.git
synced 2025-08-02 08:02:56 +00:00
gh-105481: add pseudo-instructions to the bytecodes DSL (#105506)
This commit is contained in:
parent
20a56d8bec
commit
58f5227d7c
8 changed files with 507 additions and 267 deletions
|
@ -4,6 +4,7 @@
|
|||
#include "pycore_code.h" // write_location_entry_start()
|
||||
#include "pycore_compile.h"
|
||||
#include "pycore_opcode.h" // _PyOpcode_Caches[] and opcode category macros
|
||||
#include "opcode_metadata.h" // IS_PSEUDO_INSTR
|
||||
|
||||
|
||||
#define DEFAULT_CODE_SIZE 128
|
||||
|
@ -338,7 +339,8 @@ static void
|
|||
write_instr(_Py_CODEUNIT *codestr, instruction *instr, int ilen)
|
||||
{
|
||||
int opcode = instr->i_opcode;
|
||||
assert(!IS_PSEUDO_OPCODE(opcode));
|
||||
assert(IS_PSEUDO_OPCODE(opcode) == IS_PSEUDO_INSTR(opcode));
|
||||
assert(!IS_PSEUDO_INSTR(opcode));
|
||||
int oparg = instr->i_oparg;
|
||||
assert(HAS_ARG(opcode) || oparg == 0);
|
||||
int caches = _PyOpcode_Caches[opcode];
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#define macro(name) static int MACRO_##name
|
||||
#define super(name) static int SUPER_##name
|
||||
#define family(name, ...) static int family_##name
|
||||
#define pseudo(name) static int pseudo_##name
|
||||
|
||||
// Dummy variables for stack effects.
|
||||
static PyObject *value, *value1, *value2, *left, *right, *res, *sum, *prod, *sub;
|
||||
|
@ -218,6 +219,10 @@ dummy_func(
|
|||
SETLOCAL(oparg, value);
|
||||
}
|
||||
|
||||
pseudo(STORE_FAST_MAYBE_NULL) = {
|
||||
STORE_FAST,
|
||||
};
|
||||
|
||||
inst(STORE_FAST_LOAD_FAST, (value1 -- value2)) {
|
||||
uint32_t oparg1 = oparg >> 4;
|
||||
uint32_t oparg2 = oparg & 15;
|
||||
|
@ -1674,6 +1679,18 @@ dummy_func(
|
|||
ERROR_IF(res == NULL, error);
|
||||
}
|
||||
|
||||
pseudo(LOAD_SUPER_METHOD) = {
|
||||
LOAD_SUPER_ATTR,
|
||||
};
|
||||
|
||||
pseudo(LOAD_ZERO_SUPER_METHOD) = {
|
||||
LOAD_SUPER_ATTR,
|
||||
};
|
||||
|
||||
pseudo(LOAD_ZERO_SUPER_ATTR) = {
|
||||
LOAD_SUPER_ATTR,
|
||||
};
|
||||
|
||||
inst(LOAD_SUPER_ATTR_ATTR, (unused/1, global_super, class, self -- res2 if (oparg & 1), res)) {
|
||||
assert(!(oparg & 1));
|
||||
DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR);
|
||||
|
@ -1772,6 +1789,10 @@ dummy_func(
|
|||
}
|
||||
}
|
||||
|
||||
pseudo(LOAD_METHOD) = {
|
||||
LOAD_ATTR,
|
||||
};
|
||||
|
||||
inst(LOAD_ATTR_INSTANCE_VALUE, (unused/1, type_version/2, index/1, unused/5, owner -- res2 if (oparg & 1), res)) {
|
||||
PyTypeObject *tp = Py_TYPE(owner);
|
||||
assert(type_version != 0);
|
||||
|
@ -2142,6 +2163,16 @@ dummy_func(
|
|||
CHECK_EVAL_BREAKER();
|
||||
}
|
||||
|
||||
pseudo(JUMP) = {
|
||||
JUMP_FORWARD,
|
||||
JUMP_BACKWARD,
|
||||
};
|
||||
|
||||
pseudo(JUMP_NO_INTERRUPT) = {
|
||||
JUMP_FORWARD,
|
||||
JUMP_BACKWARD_NO_INTERRUPT,
|
||||
};
|
||||
|
||||
inst(ENTER_EXECUTOR, (--)) {
|
||||
_PyExecutorObject *executor = (_PyExecutorObject *)frame->f_code->co_executors->executors[oparg];
|
||||
Py_INCREF(executor);
|
||||
|
@ -2530,6 +2561,22 @@ dummy_func(
|
|||
ERROR_IF(res == NULL, error);
|
||||
}
|
||||
|
||||
pseudo(SETUP_FINALLY) = {
|
||||
NOP,
|
||||
};
|
||||
|
||||
pseudo(SETUP_CLEANUP) = {
|
||||
NOP,
|
||||
};
|
||||
|
||||
pseudo(SETUP_WITH) = {
|
||||
NOP,
|
||||
};
|
||||
|
||||
pseudo(POP_BLOCK) = {
|
||||
NOP,
|
||||
};
|
||||
|
||||
inst(PUSH_EXC_INFO, (new_exc -- prev_exc, new_exc)) {
|
||||
_PyErr_StackItem *exc_info = tstate->exc_info;
|
||||
if (exc_info->exc_value != NULL) {
|
||||
|
|
|
@ -134,7 +134,8 @@ enum {
|
|||
int
|
||||
_PyCompile_InstrSize(int opcode, int oparg)
|
||||
{
|
||||
assert(!IS_PSEUDO_OPCODE(opcode));
|
||||
assert(IS_PSEUDO_OPCODE(opcode) == IS_PSEUDO_INSTR(opcode));
|
||||
assert(!IS_PSEUDO_INSTR(opcode));
|
||||
assert(HAS_ARG(opcode) || oparg == 0);
|
||||
int extended_args = (0xFFFFFF < oparg) + (0xFFFF < oparg) + (0xFF < oparg);
|
||||
int caches = _PyOpcode_Caches[opcode];
|
||||
|
@ -241,9 +242,14 @@ instr_sequence_use_label(instr_sequence *seq, int lbl) {
|
|||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#define MAX_OPCODE 511
|
||||
|
||||
static int
|
||||
instr_sequence_addop(instr_sequence *seq, int opcode, int oparg, location loc)
|
||||
{
|
||||
assert(0 <= opcode && opcode <= MAX_OPCODE);
|
||||
assert(IS_PSEUDO_OPCODE(opcode) == IS_PSEUDO_INSTR(opcode));
|
||||
assert(IS_WITHIN_OPCODE_RANGE(opcode));
|
||||
assert(HAS_ARG(opcode) || HAS_TARGET(opcode) || oparg == 0);
|
||||
assert(0 <= oparg && oparg < (1 << 30));
|
||||
|
@ -1055,6 +1061,7 @@ compiler_addop_name(struct compiler_unit *u, location loc,
|
|||
arg <<= 1;
|
||||
}
|
||||
if (opcode == LOAD_METHOD) {
|
||||
assert(SAME_OPCODE_METADATA(LOAD_METHOD, LOAD_ATTR));
|
||||
opcode = LOAD_ATTR;
|
||||
arg <<= 1;
|
||||
arg |= 1;
|
||||
|
@ -1064,15 +1071,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));
|
||||
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));
|
||||
opcode = LOAD_SUPER_ATTR;
|
||||
arg <<= 2;
|
||||
}
|
||||
if (opcode == LOAD_ZERO_SUPER_METHOD) {
|
||||
assert(SAME_OPCODE_METADATA(LOAD_ZERO_SUPER_METHOD, LOAD_SUPER_ATTR));
|
||||
opcode = LOAD_SUPER_ATTR;
|
||||
arg <<= 2;
|
||||
arg |= 1;
|
||||
|
|
|
@ -416,9 +416,13 @@ normalize_jumps_in_block(cfg_builder *g, basicblock *b) {
|
|||
bool is_forward = last->i_target->b_visited == 0;
|
||||
switch(last->i_opcode) {
|
||||
case JUMP:
|
||||
assert(SAME_OPCODE_METADATA(JUMP, JUMP_FORWARD));
|
||||
assert(SAME_OPCODE_METADATA(JUMP, JUMP_BACKWARD));
|
||||
last->i_opcode = is_forward ? JUMP_FORWARD : JUMP_BACKWARD;
|
||||
return SUCCESS;
|
||||
case JUMP_NO_INTERRUPT:
|
||||
assert(SAME_OPCODE_METADATA(JUMP_NO_INTERRUPT, JUMP_FORWARD));
|
||||
assert(SAME_OPCODE_METADATA(JUMP_NO_INTERRUPT, JUMP_BACKWARD_NO_INTERRUPT));
|
||||
last->i_opcode = is_forward ?
|
||||
JUMP_FORWARD : JUMP_BACKWARD_NO_INTERRUPT;
|
||||
return SUCCESS;
|
||||
|
@ -2071,9 +2075,11 @@ _PyCfg_ConvertPseudoOps(basicblock *entryblock)
|
|||
for (int i = 0; i < b->b_iused; i++) {
|
||||
cfg_instr *instr = &b->b_instr[i];
|
||||
if (is_block_push(instr) || instr->i_opcode == POP_BLOCK) {
|
||||
assert(SAME_OPCODE_METADATA(instr->i_opcode, NOP));
|
||||
INSTR_SET_OP0(instr, NOP);
|
||||
}
|
||||
else if (instr->i_opcode == STORE_FAST_MAYBE_NULL) {
|
||||
assert(SAME_OPCODE_METADATA(STORE_FAST_MAYBE_NULL, STORE_FAST));
|
||||
instr->i_opcode = STORE_FAST;
|
||||
}
|
||||
}
|
||||
|
|
506
Python/generated_cases.c.h
generated
506
Python/generated_cases.c.h
generated
File diff suppressed because it is too large
Load diff
|
@ -3,6 +3,21 @@
|
|||
// Python/bytecodes.c
|
||||
// Do not edit!
|
||||
|
||||
|
||||
#define IS_PSEUDO_INSTR(OP) \
|
||||
((OP) == STORE_FAST_MAYBE_NULL) || \
|
||||
((OP) == LOAD_SUPER_METHOD) || \
|
||||
((OP) == LOAD_ZERO_SUPER_METHOD) || \
|
||||
((OP) == LOAD_ZERO_SUPER_ATTR) || \
|
||||
((OP) == LOAD_METHOD) || \
|
||||
((OP) == JUMP) || \
|
||||
((OP) == JUMP_NO_INTERRUPT) || \
|
||||
((OP) == SETUP_FINALLY) || \
|
||||
((OP) == SETUP_CLEANUP) || \
|
||||
((OP) == SETUP_WITH) || \
|
||||
((OP) == POP_BLOCK) || \
|
||||
0
|
||||
|
||||
#ifndef NEED_OPCODE_METADATA
|
||||
extern int _PyOpcode_num_popped(int opcode, int oparg, bool jump);
|
||||
#else
|
||||
|
@ -29,6 +44,8 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
|
|||
return 0;
|
||||
case STORE_FAST:
|
||||
return 1;
|
||||
case STORE_FAST_MAYBE_NULL:
|
||||
return 1;
|
||||
case STORE_FAST_LOAD_FAST:
|
||||
return 1;
|
||||
case STORE_FAST_STORE_FAST:
|
||||
|
@ -211,12 +228,20 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
|
|||
return 3;
|
||||
case LOAD_SUPER_ATTR:
|
||||
return 3;
|
||||
case LOAD_SUPER_METHOD:
|
||||
return 3;
|
||||
case LOAD_ZERO_SUPER_METHOD:
|
||||
return 3;
|
||||
case LOAD_ZERO_SUPER_ATTR:
|
||||
return 3;
|
||||
case LOAD_SUPER_ATTR_ATTR:
|
||||
return 3;
|
||||
case LOAD_SUPER_ATTR_METHOD:
|
||||
return 3;
|
||||
case LOAD_ATTR:
|
||||
return 1;
|
||||
case LOAD_METHOD:
|
||||
return 1;
|
||||
case LOAD_ATTR_INSTANCE_VALUE:
|
||||
return 1;
|
||||
case LOAD_ATTR_MODULE:
|
||||
|
@ -261,6 +286,10 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
|
|||
return 0;
|
||||
case JUMP_BACKWARD:
|
||||
return 0;
|
||||
case JUMP:
|
||||
return 0;
|
||||
case JUMP_NO_INTERRUPT:
|
||||
return 0;
|
||||
case ENTER_EXECUTOR:
|
||||
return 0;
|
||||
case POP_JUMP_IF_FALSE:
|
||||
|
@ -305,6 +334,14 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
|
|||
return 1;
|
||||
case WITH_EXCEPT_START:
|
||||
return 4;
|
||||
case SETUP_FINALLY:
|
||||
return 0;
|
||||
case SETUP_CLEANUP:
|
||||
return 0;
|
||||
case SETUP_WITH:
|
||||
return 0;
|
||||
case POP_BLOCK:
|
||||
return 0;
|
||||
case PUSH_EXC_INFO:
|
||||
return 1;
|
||||
case LOAD_ATTR_METHOD_WITH_VALUES:
|
||||
|
@ -423,6 +460,8 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
|
|||
return 1;
|
||||
case STORE_FAST:
|
||||
return 0;
|
||||
case STORE_FAST_MAYBE_NULL:
|
||||
return 0;
|
||||
case STORE_FAST_LOAD_FAST:
|
||||
return 1;
|
||||
case STORE_FAST_STORE_FAST:
|
||||
|
@ -605,12 +644,20 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
|
|||
return ((oparg & 1) ? 1 : 0) + 1;
|
||||
case LOAD_SUPER_ATTR:
|
||||
return ((oparg & 1) ? 1 : 0) + 1;
|
||||
case LOAD_SUPER_METHOD:
|
||||
return ((oparg & 1) ? 1 : 0) + 1;
|
||||
case LOAD_ZERO_SUPER_METHOD:
|
||||
return ((oparg & 1) ? 1 : 0) + 1;
|
||||
case LOAD_ZERO_SUPER_ATTR:
|
||||
return ((oparg & 1) ? 1 : 0) + 1;
|
||||
case LOAD_SUPER_ATTR_ATTR:
|
||||
return ((oparg & 1) ? 1 : 0) + 1;
|
||||
case LOAD_SUPER_ATTR_METHOD:
|
||||
return 2;
|
||||
case LOAD_ATTR:
|
||||
return ((oparg & 1) ? 1 : 0) + 1;
|
||||
case LOAD_METHOD:
|
||||
return ((oparg & 1) ? 1 : 0) + 1;
|
||||
case LOAD_ATTR_INSTANCE_VALUE:
|
||||
return ((oparg & 1) ? 1 : 0) + 1;
|
||||
case LOAD_ATTR_MODULE:
|
||||
|
@ -655,6 +702,10 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
|
|||
return 0;
|
||||
case JUMP_BACKWARD:
|
||||
return 0;
|
||||
case JUMP:
|
||||
return 0;
|
||||
case JUMP_NO_INTERRUPT:
|
||||
return 0;
|
||||
case ENTER_EXECUTOR:
|
||||
return 0;
|
||||
case POP_JUMP_IF_FALSE:
|
||||
|
@ -699,6 +750,14 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
|
|||
return 2;
|
||||
case WITH_EXCEPT_START:
|
||||
return 5;
|
||||
case SETUP_FINALLY:
|
||||
return 0;
|
||||
case SETUP_CLEANUP:
|
||||
return 0;
|
||||
case SETUP_WITH:
|
||||
return 0;
|
||||
case POP_BLOCK:
|
||||
return 0;
|
||||
case PUSH_EXC_INFO:
|
||||
return 2;
|
||||
case LOAD_ATTR_METHOD_WITH_VALUES:
|
||||
|
@ -797,10 +856,14 @@ struct opcode_metadata {
|
|||
enum InstructionFormat instr_format;
|
||||
};
|
||||
|
||||
#define OPCODE_METADATA_FMT(OP) (_PyOpcode_opcode_metadata[(OP)].instr_format)
|
||||
#define SAME_OPCODE_METADATA(OP1, OP2) \
|
||||
(OPCODE_METADATA_FMT(OP1) == OPCODE_METADATA_FMT(OP2))
|
||||
|
||||
#ifndef NEED_OPCODE_METADATA
|
||||
extern const struct opcode_metadata _PyOpcode_opcode_metadata[256];
|
||||
extern const struct opcode_metadata _PyOpcode_opcode_metadata[512];
|
||||
#else
|
||||
const struct opcode_metadata _PyOpcode_opcode_metadata[256] = {
|
||||
const struct opcode_metadata _PyOpcode_opcode_metadata[512] = {
|
||||
[NOP] = { true, INSTR_FMT_IX },
|
||||
[RESUME] = { true, INSTR_FMT_IB },
|
||||
[INSTRUMENTED_RESUME] = { true, INSTR_FMT_IB },
|
||||
|
@ -811,6 +874,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[256] = {
|
|||
[LOAD_FAST_LOAD_FAST] = { true, INSTR_FMT_IB },
|
||||
[LOAD_CONST] = { true, INSTR_FMT_IB },
|
||||
[STORE_FAST] = { true, INSTR_FMT_IB },
|
||||
[STORE_FAST_MAYBE_NULL] = { true, INSTR_FMT_IB },
|
||||
[STORE_FAST_LOAD_FAST] = { true, INSTR_FMT_IB },
|
||||
[STORE_FAST_STORE_FAST] = { true, INSTR_FMT_IB },
|
||||
[POP_TOP] = { true, INSTR_FMT_IX },
|
||||
|
@ -902,9 +966,13 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[256] = {
|
|||
[MAP_ADD] = { true, INSTR_FMT_IB },
|
||||
[INSTRUMENTED_LOAD_SUPER_ATTR] = { true, INSTR_FMT_IBC00000000 },
|
||||
[LOAD_SUPER_ATTR] = { true, INSTR_FMT_IBC },
|
||||
[LOAD_SUPER_METHOD] = { true, INSTR_FMT_IBC },
|
||||
[LOAD_ZERO_SUPER_METHOD] = { true, INSTR_FMT_IBC },
|
||||
[LOAD_ZERO_SUPER_ATTR] = { true, INSTR_FMT_IBC },
|
||||
[LOAD_SUPER_ATTR_ATTR] = { true, INSTR_FMT_IBC },
|
||||
[LOAD_SUPER_ATTR_METHOD] = { true, INSTR_FMT_IBC },
|
||||
[LOAD_ATTR] = { true, INSTR_FMT_IBC00000000 },
|
||||
[LOAD_METHOD] = { true, INSTR_FMT_IBC00000000 },
|
||||
[LOAD_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IBC00000000 },
|
||||
[LOAD_ATTR_MODULE] = { true, INSTR_FMT_IBC00000000 },
|
||||
[LOAD_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC00000000 },
|
||||
|
@ -927,6 +995,8 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[256] = {
|
|||
[IMPORT_FROM] = { true, INSTR_FMT_IB },
|
||||
[JUMP_FORWARD] = { true, INSTR_FMT_IB },
|
||||
[JUMP_BACKWARD] = { true, INSTR_FMT_IB },
|
||||
[JUMP] = { true, INSTR_FMT_IB },
|
||||
[JUMP_NO_INTERRUPT] = { true, INSTR_FMT_IB },
|
||||
[ENTER_EXECUTOR] = { true, INSTR_FMT_IB },
|
||||
[POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IB },
|
||||
[POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IB },
|
||||
|
@ -949,6 +1019,10 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[256] = {
|
|||
[BEFORE_ASYNC_WITH] = { true, INSTR_FMT_IX },
|
||||
[BEFORE_WITH] = { true, INSTR_FMT_IX },
|
||||
[WITH_EXCEPT_START] = { true, INSTR_FMT_IX },
|
||||
[SETUP_FINALLY] = { true, INSTR_FMT_IX },
|
||||
[SETUP_CLEANUP] = { true, INSTR_FMT_IX },
|
||||
[SETUP_WITH] = { true, INSTR_FMT_IX },
|
||||
[POP_BLOCK] = { true, INSTR_FMT_IX },
|
||||
[PUSH_EXC_INFO] = { true, INSTR_FMT_IX },
|
||||
[LOAD_ATTR_METHOD_WITH_VALUES] = { true, INSTR_FMT_IBC00000000 },
|
||||
[LOAD_ATTR_METHOD_NO_DICT] = { true, INSTR_FMT_IBC00000000 },
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue