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

[WIP] bpo-17611: Move unwinding of stack from interpreter to compiler #2827

Closed
wants to merge 20 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
1 change: 1 addition & 0 deletions Include/opcode.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ extern "C" {
#define END_ITER 117
#define SETUP_EXCEPT 121
#define SETUP_FINALLY 122
#define JUMP_FINALLY 123
#define LOAD_FAST 124
#define STORE_FAST 125
#define DELETE_FAST 126
Expand Down
1 change: 1 addition & 0 deletions Lib/opcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ def jabs_op(name, op):

jrel_op('SETUP_EXCEPT', 121) # Distance to target address
jrel_op('SETUP_FINALLY', 122) # ""
jrel_op('JUMP_FINALLY', 123) # ""

def_op('LOAD_FAST', 124) # Local variable number
haslocal.append(124)
Expand Down
28 changes: 25 additions & 3 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -2075,9 +2075,19 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
PyObject *exc = POP();
PyObject *val = POP();
PyObject *tb = POP();
assert(PyExceptionClass_Check(exc));
PyErr_Restore(exc, val, tb);
goto exception_unwind;
if (exc == Py_None) {
assert(val == Py_None);
assert(tb == Py_None);
Py_DECREF(exc);
Py_DECREF(val);
Py_DECREF(tb);
}
else {
assert(PyExceptionClass_Check(exc));
PyErr_Restore(exc, val, tb);
goto exception_unwind;
}
FAST_DISPATCH();
}

TARGET(LOAD_BUILD_CLASS) {
Expand Down Expand Up @@ -2844,6 +2854,18 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
FAST_DISPATCH();
}

TARGET(JUMP_FINALLY) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we push 3 NULLs?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes.

PyObject *exc = Py_None;
Py_INCREF(exc);
Py_INCREF(exc);
Py_INCREF(exc);
PUSH(exc);
PUSH(exc);
PUSH(exc);
JUMPBY(oparg);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it needed? It seems to me that JUMP_FINALLY always jumps to the next instruction.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That might be, I'll give it a try.

FAST_DISPATCH();
}

PREDICTED(POP_JUMP_IF_FALSE);
TARGET(POP_JUMP_IF_FALSE) {
PyObject *cond = POP();
Expand Down
25 changes: 14 additions & 11 deletions Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -1080,6 +1080,8 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg)
return (oparg & FVS_MASK) == FVS_HAVE_SPEC ? -1 : 0;
case LOAD_METHOD:
return 1;
case JUMP_FINALLY:
return 3;
default:
return PY_INVALID_STACK_EFFECT;
}
Expand Down Expand Up @@ -2695,10 +2697,10 @@ compiler_try_finally(struct compiler *c, stmt_ty s)
int save_u_lineno_set;

body = compiler_new_block(c);
final1 = compiler_new_block(c);
// final1 = compiler_new_block(c);
final2 = compiler_new_block(c);
exit = compiler_new_block(c);
if (body == NULL || final1 == NULL || final2 == NULL || exit == NULL)
if (body == NULL || /*final1 == NULL || */final2 == NULL || exit == NULL)
return 0;

ADDOP_JREL(c, SETUP_FINALLY, final2);
Expand All @@ -2713,19 +2715,20 @@ compiler_try_finally(struct compiler *c, stmt_ty s)
VISIT_SEQ(c, stmt, s->v.Try.body);
}
ADDOP(c, POP_BLOCK);
ADDOP_JREL(c, JUMP_FINALLY, final2);
compiler_pop_fblock(c, FINALLY_TRY, body);
save_u_lineno_set = c->u->u_lineno_set;

/* `finally` block for successful outcome */
compiler_use_next_block(c, final1);
if (!compiler_push_finally_end(c, final1))
return 0;
c->u->u_lineno_set = 0;
VISIT_SEQ(c, stmt, s->v.Try.finalbody);
compiler_pop_fblock(c, FINALLY_END, final1);

c->u->u_lineno_set = save_u_lineno_set;
ADDOP_JABS(c, JUMP_ABSOLUTE, exit);
// compiler_use_next_block(c, final1);
// if (!compiler_push_finally_end(c, final1))
// return 0;
// c->u->u_lineno_set = 0;
// VISIT_SEQ(c, stmt, s->v.Try.finalbody);
// compiler_pop_fblock(c, FINALLY_END, final1);
//
// c->u->u_lineno_set = save_u_lineno_set;
// ADDOP_JABS(c, JUMP_ABSOLUTE, exit);

/* `finally` block for exceptional outcome */
compiler_use_next_block(c, final2);
Expand Down
2 changes: 1 addition & 1 deletion Python/opcode_targets.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ static void *opcode_targets[256] = {
&&_unknown_opcode,
&&TARGET_SETUP_EXCEPT,
&&TARGET_SETUP_FINALLY,
&&_unknown_opcode,
&&TARGET_JUMP_FINALLY,
&&TARGET_LOAD_FAST,
&&TARGET_STORE_FAST,
&&TARGET_DELETE_FAST,
Expand Down
5 changes: 4 additions & 1 deletion Python/peephole.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
#include "opcode.h"
#include "wordcode_helpers.h"

#define UNCONDITIONAL_JUMP(op) (op==JUMP_ABSOLUTE || op==END_ITER || op==JUMP_FORWARD)
#define UNCONDITIONAL_JUMP(op) (op==JUMP_ABSOLUTE || op==END_ITER || \
op==JUMP_FORWARD || op==JUMP_FINALLY)
#define CONDITIONAL_JUMP(op) (op==POP_JUMP_IF_FALSE || op==POP_JUMP_IF_TRUE \
|| op==JUMP_IF_FALSE_OR_POP || op==JUMP_IF_TRUE_OR_POP)
#define ABSOLUTE_JUMP(op) (op==JUMP_ABSOLUTE || op==END_ITER \
Expand Down Expand Up @@ -383,6 +384,7 @@ markblocks(_Py_CODEUNIT *code, Py_ssize_t len)
switch (opcode) {
case FOR_ITER:
case JUMP_FORWARD:
case JUMP_FINALLY:
case JUMP_IF_FALSE_OR_POP:
case JUMP_IF_TRUE_OR_POP:
case POP_JUMP_IF_FALSE:
Expand Down Expand Up @@ -745,6 +747,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,

case FOR_ITER:
case JUMP_FORWARD:
case JUMP_FINALLY:
case SETUP_EXCEPT:
case SETUP_FINALLY:
j = blocks[j / sizeof(_Py_CODEUNIT) + i + 1] - blocks[i] - 1;
Expand Down