Skip to content

Commit

Permalink
Squashed commit of the following:
Browse files Browse the repository at this point in the history
commit f89f147
Author: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Date:   Sat Jan 25 11:18:43 2025 +0800

    Address review

commit e4a9de7
Author: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Date:   Thu Jan 23 02:05:13 2025 +0800

    Regen files

commit 5d56130
Author: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Date:   Thu Jan 23 02:00:44 2025 +0800

    Address review by removing in test cases generator

commit e1f9475
Author: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Date:   Wed Jan 22 09:39:54 2025 +0800

    Remove entry_frame

commit 15ca6dd
Author: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Date:   Wed Jan 22 09:27:37 2025 +0800

    fix upstream changes

commit fdd4540
Merge: 1ec8033 86c1a60
Author: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Date:   Wed Jan 22 09:27:31 2025 +0800

    Merge remote-tracking branch 'upstream/main' into labels-in-dsl

commit 1ec8033
Author: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Date:   Tue Jan 21 20:16:42 2025 +0800

    Lint

commit c6df7a1
Author: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Date:   Tue Jan 21 20:14:10 2025 +0800

    cleanup diff

commit 63a88ab
Author: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Date:   Tue Jan 21 20:13:12 2025 +0800

    remove outdated file

commit b911bb1
Author: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Date:   Tue Jan 21 20:11:27 2025 +0800

    Move labels into tier 1 generator

commit af4bf1a
Author: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Date:   Tue Jan 21 15:52:53 2025 +0800

    Add to generated files

commit 3ae88a5
Author: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Date:   Tue Jan 21 09:01:39 2025 +0800

    lint

commit 5cccb98
Author: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Date:   Tue Jan 21 08:58:53 2025 +0800

    Fix mypy

commit 2082537
Author: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Date:   Tue Jan 21 08:54:50 2025 +0800

    Move labels in ceval.c to bytecodes.c
  • Loading branch information
Fidget-Spinner committed Jan 25, 2025
1 parent 1a21607 commit 15da9c7
Show file tree
Hide file tree
Showing 9 changed files with 435 additions and 155 deletions.
67 changes: 61 additions & 6 deletions Lib/test/test_generated_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,12 +250,12 @@ def run_cases_test(self, input: str, expected: str):
)

with open(self.temp_output_filename) as temp_output:
lines = temp_output.readlines()
while lines and lines[0].startswith(("// ", "#", " #", "\n")):
lines.pop(0)
while lines and lines[-1].startswith(("#", "\n")):
lines.pop(-1)
actual = "".join(lines)
lines = temp_output.read()
_, rest = lines.split(tier1_generator.INSTRUCTION_START_MARKER)
instructions, labels_with_prelude_and_postlude = rest.split(tier1_generator.INSTRUCTION_END_MARKER)
_, labels_with_postlude = labels_with_prelude_and_postlude.split(tier1_generator.LABEL_START_MARKER)
labels, _ = labels_with_postlude.split(tier1_generator.LABEL_END_MARKER)
actual = instructions + labels
# if actual.strip() != expected.strip():
# print("Actual:")
# print(actual)
Expand Down Expand Up @@ -1641,6 +1641,61 @@ def test_kill_in_wrong_order(self):
with self.assertRaises(SyntaxError):
self.run_cases_test(input, "")

def test_complex_label(self):
input = """
label(my_label) {
// Comment
do_thing()
if (complex) {
goto other_label;
}
goto other_label2;
}
"""

output = """
my_label:
{
// Comment
do_thing()
if (complex) {
goto other_label;
}
goto other_label2;
}
"""
self.run_cases_test(input, output)

def test_multiple_labels(self):
input = """
label(my_label_1) {
// Comment
do_thing1();
goto my_label_2;
}
label(my_label_2) {
// Comment
do_thing2();
goto my_label_3;
}
"""

output = """
my_label_1:
{
// Comment
do_thing1();
goto my_label_2;
}
my_label_2:
{
// Comment
do_thing2();
goto my_label_3;
}
"""

class TestGeneratedTailCallErorHandlers(unittest.TestCase):
def setUp(self) -> None:
Expand Down
120 changes: 120 additions & 0 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
#define super(name) static int SUPER_##name
#define family(name, ...) static int family_##name
#define pseudo(name) static int pseudo_##name
#define label(name) name:

/* Annotations */
#define guard
Expand Down Expand Up @@ -5193,6 +5194,125 @@ dummy_func(
assert(tstate->tracing || eval_breaker == FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version));
}

label(pop_4_error) {
STACK_SHRINK(1);
goto pop_3_error;
}

label(pop_3_error) {
STACK_SHRINK(1);
goto pop_2_error;
}

label(pop_2_error) {
STACK_SHRINK(1);
goto pop_1_error;
}

label(pop_1_error) {
STACK_SHRINK(1);
goto error;
}

label(error) {
/* Double-check exception status. */
#ifdef NDEBUG
if (!_PyErr_Occurred(tstate)) {
_PyErr_SetString(tstate, PyExc_SystemError,
"error return without exception set");
}
#else
assert(_PyErr_Occurred(tstate));
#endif

/* Log traceback info. */
assert(frame->owner != FRAME_OWNED_BY_INTERPRETER);
if (!_PyFrame_IsIncomplete(frame)) {
PyFrameObject *f = _PyFrame_GetFrameObject(frame);
if (f != NULL) {
PyTraceBack_Here(f);
}
}
_PyEval_MonitorRaise(tstate, frame, next_instr-1);
goto exception_unwind;
}

label(exception_unwind) {
/* We can't use frame->instr_ptr here, as RERAISE may have set it */
int offset = INSTR_OFFSET()-1;
int level, handler, lasti;
if (get_exception_handler(_PyFrame_GetCode(frame), offset, &level, &handler, &lasti) == 0) {
// No handlers, so exit.
assert(_PyErr_Occurred(tstate));

/* Pop remaining stack entries. */
_PyStackRef *stackbase = _PyFrame_Stackbase(frame);
while (stack_pointer > stackbase) {
PyStackRef_XCLOSE(POP());
}
assert(STACK_LEVEL() == 0);
_PyFrame_SetStackPointer(frame, stack_pointer);
monitor_unwind(tstate, frame, next_instr-1);
goto exit_unwind;
}

assert(STACK_LEVEL() >= level);
_PyStackRef *new_top = _PyFrame_Stackbase(frame) + level;
while (stack_pointer > new_top) {
PyStackRef_XCLOSE(POP());
}
if (lasti) {
int frame_lasti = _PyInterpreterFrame_LASTI(frame);
PyObject *lasti = PyLong_FromLong(frame_lasti);
if (lasti == NULL) {
goto exception_unwind;
}
PUSH(PyStackRef_FromPyObjectSteal(lasti));
}

/* Make the raw exception data
available to the handler,
so a program can emulate the
Python main loop. */
PyObject *exc = _PyErr_GetRaisedException(tstate);
PUSH(PyStackRef_FromPyObjectSteal(exc));
next_instr = _PyFrame_GetBytecode(frame) + handler;

if (monitor_handled(tstate, frame, next_instr, exc) < 0) {
goto exception_unwind;
}
/* Resume normal execution */
#ifdef LLTRACE
if (frame->lltrace >= 5) {
lltrace_resume_frame(frame);
}
#endif
DISPATCH();
}

label(exit_unwind) {
assert(_PyErr_Occurred(tstate));
_Py_LeaveRecursiveCallPy(tstate);
assert(frame->owner != FRAME_OWNED_BY_INTERPRETER);
// GH-99729: We need to unlink the frame *before* clearing it:
_PyInterpreterFrame *dying = frame;
frame = tstate->current_frame = dying->previous;
_PyEval_FrameClearAndPop(tstate, dying);
frame->return_offset = 0;
if (frame == &entry_frame) {
/* Restore previous frame and exit */
tstate->current_frame = frame->previous;
tstate->c_recursion_remaining += PY_EVAL_C_STACK_UNITS;
return NULL;
}
goto resume_with_error;
}

label(resume_with_error) {
next_instr = frame->instr_ptr;
stack_pointer = _PyFrame_GetStackPointer(frame);
goto error;
}
// END BYTECODES //

}
Expand Down
145 changes: 0 additions & 145 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -919,154 +919,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
DISPATCH();
#endif

#ifndef Py_TAIL_CALL_INTERP
/* Start instructions */
#if !USE_COMPUTED_GOTOS
dispatch_opcode:
switch (opcode)
#endif
{
#include "generated_cases.c.h"


#if USE_COMPUTED_GOTOS
_unknown_opcode:
#else
EXTRA_CASES // From pycore_opcode_metadata.h, a 'case' for each unused opcode
#endif
/* Tell C compilers not to hold the opcode variable in the loop.
next_instr points the current instruction without TARGET(). */
opcode = next_instr->op.code;
_PyErr_Format(tstate, PyExc_SystemError,
"%U:%d: unknown opcode %d",
_PyFrame_GetCode(frame)->co_filename,
PyUnstable_InterpreterFrame_GetLine(frame),
opcode);
goto error;

} /* End instructions */

/* This should never be reached. Every opcode should end with DISPATCH()
or goto error. */
Py_UNREACHABLE();
#endif
TAIL_CALL_TARGET(pop_4_error):
STACK_SHRINK(1);
TAIL_CALL_TARGET(pop_3_error):
STACK_SHRINK(1);
TAIL_CALL_TARGET(pop_2_error):
STACK_SHRINK(1);
TAIL_CALL_TARGET(pop_1_error):
STACK_SHRINK(1);
TAIL_CALL_TARGET(error):
/* Double-check exception status. */
#ifdef NDEBUG
if (!_PyErr_Occurred(tstate)) {
_PyErr_SetString(tstate, PyExc_SystemError,
"error return without exception set");
}
#else
assert(_PyErr_Occurred(tstate));
#endif

/* Log traceback info. */
assert(!frame->is_entry_frame);
if (!_PyFrame_IsIncomplete(frame)) {
PyFrameObject *f = _PyFrame_GetFrameObject(frame);
if (f != NULL) {
PyTraceBack_Here(f);
}
}
_PyEval_MonitorRaise(tstate, frame, next_instr-1);
TAIL_CALL_TARGET(exception_unwind):
{
/* We can't use frame->instr_ptr here, as RERAISE may have set it */
int offset = INSTR_OFFSET()-1;
int level, handler, lasti;
if (get_exception_handler(_PyFrame_GetCode(frame), offset, &level, &handler, &lasti) == 0) {
// No handlers, so exit.
assert(_PyErr_Occurred(tstate));

/* Pop remaining stack entries. */
_PyStackRef *stackbase = _PyFrame_Stackbase(frame);
while (stack_pointer > stackbase) {
PyStackRef_XCLOSE(POP());
}
assert(STACK_LEVEL() == 0);
_PyFrame_SetStackPointer(frame, stack_pointer);
monitor_unwind(tstate, frame, next_instr-1);
goto exit_unwind;
}

assert(STACK_LEVEL() >= level);
_PyStackRef *new_top = _PyFrame_Stackbase(frame) + level;
while (stack_pointer > new_top) {
PyStackRef_XCLOSE(POP());
}
if (lasti) {
int frame_lasti = _PyInterpreterFrame_LASTI(frame);
PyObject *lasti = PyLong_FromLong(frame_lasti);
if (lasti == NULL) {
goto exception_unwind;
}
PUSH(PyStackRef_FromPyObjectSteal(lasti));
}

/* Make the raw exception data
available to the handler,
so a program can emulate the
Python main loop. */
PyObject *exc = _PyErr_GetRaisedException(tstate);
PUSH(PyStackRef_FromPyObjectSteal(exc));
next_instr = _PyFrame_GetBytecode(frame) + handler;

if (monitor_handled(tstate, frame, next_instr, exc) < 0) {
goto exception_unwind;
}
/* Resume normal execution */
#ifdef LLTRACE
if (frame->lltrace >= 5) {
lltrace_resume_frame(frame);
}
#endif

#ifdef Py_TAIL_CALL_INTERP
# ifdef IN_TAIL_CALL_INTERP
DISPATCH();
# else
# ifdef LLTRACE
return _TAIL_CALL_shim(frame, stack_pointer, tstate, next_instr, 0, 0, lltrace);
# else
return _TAIL_CALL_shim(frame, stack_pointer, tstate, next_instr, 0, 0);
# endif
# endif
#else
DISPATCH();
#endif
}

TAIL_CALL_TARGET(exit_unwind):
assert(_PyErr_Occurred(tstate));
_Py_LeaveRecursiveCallPy(tstate);
assert(!frame->is_entry_frame);
// GH-99729: We need to unlink the frame *before* clearing it:
_PyInterpreterFrame *dying = frame;
frame = tstate->current_frame = dying->previous;
_PyEval_FrameClearAndPop(tstate, dying);
frame->return_offset = 0;
if (frame->is_entry_frame) {
/* Restore previous frame and exit */
tstate->current_frame = frame->previous;
tstate->c_recursion_remaining += PY_EVAL_C_STACK_UNITS;
return NULL;
}

TAIL_CALL_TARGET(resume_with_error):
next_instr = frame->instr_ptr;
stack_pointer = _PyFrame_GetStackPointer(frame);
goto error;

/* END_BASE_INTERPRETER */
#ifdef _Py_TIER2

// Tier 2 is also here!
Expand Down
Loading

0 comments on commit 15da9c7

Please sign in to comment.