gh-119180: Add LOAD_COMMON_CONSTANT opcode (#119321)

The PEP 649 implementation will require a way to load NotImplementedError
from the bytecode. @markshannon suggested implementing this by converting
LOAD_ASSERTION_ERROR into a more general mechanism for loading constants.

This PR adds this new opcode. I will work on the rest of the implementation
of the PEP separately.

Co-authored-by: Irit Katriel <1055913+iritkatriel@users.noreply.github.com>
This commit is contained in:
Jelle Zijlstra 2024-05-21 20:46:39 -04:00 committed by GitHub
parent 506b1a3ff6
commit 98e855fcc1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 337 additions and 288 deletions

View file

@ -1184,8 +1184,18 @@ dummy_func(
}
}
inst(LOAD_ASSERTION_ERROR, ( -- value)) {
value = Py_NewRef(PyExc_AssertionError);
inst(LOAD_COMMON_CONSTANT, ( -- value)) {
// Keep in sync with _common_constants in opcode.py
switch(oparg) {
case CONSTANT_ASSERTIONERROR:
value = PyExc_AssertionError;
break;
case CONSTANT_NOTIMPLEMENTEDERROR:
value = PyExc_NotImplementedError;
break;
default:
Py_FatalError("bad LOAD_COMMON_CONSTANT oparg");
}
}
inst(LOAD_BUILD_CLASS, ( -- bc)) {

View file

@ -3974,7 +3974,7 @@ compiler_assert(struct compiler *c, stmt_ty s)
}
NEW_JUMP_TARGET_LABEL(c, end);
RETURN_IF_ERROR(compiler_jump_if(c, LOC(s), s->v.Assert.test, end, 1));
ADDOP(c, LOC(s), LOAD_ASSERTION_ERROR);
ADDOP_I(c, LOC(s), LOAD_COMMON_CONSTANT, CONSTANT_ASSERTIONERROR);
if (s->v.Assert.msg) {
VISIT(c, expr, s->v.Assert.msg);
ADDOP_I(c, LOC(s), CALL, 0);

View file

@ -1162,9 +1162,20 @@
break;
}
case _LOAD_ASSERTION_ERROR: {
case _LOAD_COMMON_CONSTANT: {
PyObject *value;
value = Py_NewRef(PyExc_AssertionError);
oparg = CURRENT_OPARG();
// Keep in sync with _common_constants in opcode.py
switch(oparg) {
case CONSTANT_ASSERTIONERROR:
value = PyExc_AssertionError;
break;
case CONSTANT_NOTIMPLEMENTEDERROR:
value = PyExc_NotImplementedError;
break;
default:
Py_FatalError("bad LOAD_COMMON_CONSTANT oparg");
}
stack_pointer[0] = value;
stack_pointer += 1;
break;

View file

@ -3695,17 +3695,6 @@
DISPATCH();
}
TARGET(LOAD_ASSERTION_ERROR) {
frame->instr_ptr = next_instr;
next_instr += 1;
INSTRUCTION_STATS(LOAD_ASSERTION_ERROR);
PyObject *value;
value = Py_NewRef(PyExc_AssertionError);
stack_pointer[0] = value;
stack_pointer += 1;
DISPATCH();
}
TARGET(LOAD_ATTR) {
frame->instr_ptr = next_instr;
next_instr += 10;
@ -4251,6 +4240,27 @@
DISPATCH();
}
TARGET(LOAD_COMMON_CONSTANT) {
frame->instr_ptr = next_instr;
next_instr += 1;
INSTRUCTION_STATS(LOAD_COMMON_CONSTANT);
PyObject *value;
// Keep in sync with _common_constants in opcode.py
switch(oparg) {
case CONSTANT_ASSERTIONERROR:
value = PyExc_AssertionError;
break;
case CONSTANT_NOTIMPLEMENTEDERROR:
value = PyExc_NotImplementedError;
break;
default:
Py_FatalError("bad LOAD_COMMON_CONSTANT oparg");
}
stack_pointer[0] = value;
stack_pointer += 1;
DISPATCH();
}
TARGET(LOAD_CONST) {
frame->instr_ptr = next_instr;
next_instr += 1;

View file

@ -22,7 +22,6 @@ static void *opcode_targets[256] = {
&&TARGET_GET_LEN,
&&TARGET_GET_YIELD_FROM_ITER,
&&TARGET_INTERPRETER_EXIT,
&&TARGET_LOAD_ASSERTION_ERROR,
&&TARGET_LOAD_BUILD_CLASS,
&&TARGET_LOAD_LOCALS,
&&TARGET_MAKE_FUNCTION,
@ -82,6 +81,7 @@ static void *opcode_targets[256] = {
&&TARGET_LIST_APPEND,
&&TARGET_LIST_EXTEND,
&&TARGET_LOAD_ATTR,
&&TARGET_LOAD_COMMON_CONSTANT,
&&TARGET_LOAD_CONST,
&&TARGET_LOAD_DEREF,
&&TARGET_LOAD_FAST,

View file

@ -628,7 +628,7 @@
break;
}
case _LOAD_ASSERTION_ERROR: {
case _LOAD_COMMON_CONSTANT: {
_Py_UopsSymbol *value;
value = sym_new_not_null(ctx);
stack_pointer[0] = value;