Skip to content
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

gh-98831: rewrite PUSH_EXC_INFO and conditional jumps in the instruction definition DSL #101481

Merged
merged 10 commits into from
Feb 1, 2023
71 changes: 28 additions & 43 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -1898,9 +1898,7 @@ dummy_func(
CHECK_EVAL_BREAKER();
}

// stack effect: (__0 -- )
inst(POP_JUMP_IF_FALSE) {
PyObject *cond = POP();
inst(POP_JUMP_IF_FALSE, (cond -- )) {
if (Py_IsTrue(cond)) {
_Py_DECREF_NO_DEALLOC(cond);
}
Expand All @@ -1911,19 +1909,16 @@ dummy_func(
else {
int err = PyObject_IsTrue(cond);
Py_DECREF(cond);
if (err > 0)
;
else if (err == 0) {
if (err == 0) {
JUMPBY(oparg);
}
else
goto error;
else {
ERROR_IF(err < 0, error);
}
}
}

// stack effect: (__0 -- )
inst(POP_JUMP_IF_TRUE) {
PyObject *cond = POP();
inst(POP_JUMP_IF_TRUE, (cond -- )) {
if (Py_IsFalse(cond)) {
_Py_DECREF_NO_DEALLOC(cond);
}
Expand All @@ -1937,25 +1932,23 @@ dummy_func(
if (err > 0) {
JUMPBY(oparg);
}
else if (err == 0)
;
else
goto error;
else {
ERROR_IF(err < 0, error);
}
}
}

// stack effect: (__0 -- )
inst(POP_JUMP_IF_NOT_NONE) {
PyObject *value = POP();
inst(POP_JUMP_IF_NOT_NONE, (value -- )) {
if (!Py_IsNone(value)) {
Py_DECREF(value);
JUMPBY(oparg);
}
Py_DECREF(value);
else {
_Py_DECREF_NO_DEALLOC(value);
}
}

// stack effect: (__0 -- )
inst(POP_JUMP_IF_NONE) {
PyObject *value = POP();
inst(POP_JUMP_IF_NONE, (value -- )) {
if (Py_IsNone(value)) {
_Py_DECREF_NO_DEALLOC(value);
JUMPBY(oparg);
Expand All @@ -1965,50 +1958,48 @@ dummy_func(
}
}

// error: JUMP_IF_FALSE_OR_POP stack effect depends on jump flag
inst(JUMP_IF_FALSE_OR_POP) {
PyObject *cond = TOP();
inst(JUMP_IF_FALSE_OR_POP, (cond -- cond if (jump))) {
bool jump = false;
int err;
if (Py_IsTrue(cond)) {
STACK_SHRINK(1);
_Py_DECREF_NO_DEALLOC(cond);
}
else if (Py_IsFalse(cond)) {
JUMPBY(oparg);
jump = true;
}
else {
err = PyObject_IsTrue(cond);
if (err > 0) {
STACK_SHRINK(1);
Py_DECREF(cond);
}
else if (err == 0) {
JUMPBY(oparg);
jump = true;
}
else {
goto error;
}
}
}

// error: JUMP_IF_TRUE_OR_POP stack effect depends on jump flag
inst(JUMP_IF_TRUE_OR_POP) {
PyObject *cond = TOP();
inst(JUMP_IF_TRUE_OR_POP, (cond -- cond if (jump))) {
bool jump = false;
int err;
if (Py_IsFalse(cond)) {
STACK_SHRINK(1);
_Py_DECREF_NO_DEALLOC(cond);
}
else if (Py_IsTrue(cond)) {
JUMPBY(oparg);
jump = true;
}
else {
err = PyObject_IsTrue(cond);
if (err > 0) {
JUMPBY(oparg);
jump = true;
}
else if (err == 0) {
STACK_SHRINK(1);
Py_DECREF(cond);
}
else {
Expand Down Expand Up @@ -2321,22 +2312,16 @@ dummy_func(
ERROR_IF(res == NULL, error);
}

// stack effect: ( -- __0)
inst(PUSH_EXC_INFO) {
PyObject *value = TOP();

inst(PUSH_EXC_INFO, (new_exc -- prev_exc, new_exc)) {
_PyErr_StackItem *exc_info = tstate->exc_info;
if (exc_info->exc_value != NULL) {
SET_TOP(exc_info->exc_value);
prev_exc = exc_info->exc_value;
}
else {
SET_TOP(Py_NewRef(Py_None));
prev_exc = Py_NewRef(Py_None);
}

PUSH(Py_NewRef(value));
assert(PyExceptionInstance_Check(value));
exc_info->exc_value = value;

assert(PyExceptionInstance_Check(new_exc));
exc_info->exc_value = Py_NewRef(new_exc);
}

inst(LOAD_ATTR_METHOD_WITH_VALUES, (unused/1, type_version/2, keys_version/2, descr/4, self -- res2 if (oparg & 1), res)) {
Expand Down
24 changes: 13 additions & 11 deletions Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -8630,17 +8630,19 @@ opcode_metadata_is_sane(cfg_builder *g) {
int opcode = instr->i_opcode;
int oparg = instr->i_oparg;
assert(opcode <= MAX_REAL_OPCODE);
int popped = _PyOpcode_num_popped(opcode, oparg);
int pushed = _PyOpcode_num_pushed(opcode, oparg);
assert((pushed < 0) == (popped < 0));
if (pushed >= 0) {
assert(_PyOpcode_opcode_metadata[opcode].valid_entry);
int effect = stack_effect(opcode, instr->i_oparg, -1);
if (effect != pushed - popped) {
fprintf(stderr,
"op=%d: stack_effect (%d) != pushed (%d) - popped (%d)\n",
opcode, effect, pushed, popped);
result = false;
for (int jump = 0; jump <= 1; jump++) {
int popped = _PyOpcode_num_popped(opcode, oparg, jump ? true : false);
int pushed = _PyOpcode_num_pushed(opcode, oparg, jump ? true : false);
assert((pushed < 0) == (popped < 0));
if (pushed >= 0) {
assert(_PyOpcode_opcode_metadata[opcode].valid_entry);
int effect = stack_effect(opcode, instr->i_oparg, jump);
if (effect != pushed - popped) {
fprintf(stderr,
"op=%d arg=%d jump=%d: stack_effect (%d) != pushed (%d) - popped (%d)\n",
opcode, oparg, jump, effect, pushed, popped);
result = false;
}
}
}
}
Expand Down
68 changes: 40 additions & 28 deletions Python/generated_cases.c.h

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

Loading