Skip to content

Commit

Permalink
Catch up with labels-as-dsl branch
Browse files Browse the repository at this point in the history
  • Loading branch information
Fidget-Spinner committed Jan 25, 2025
1 parent 15da9c7 commit 665c0f6
Show file tree
Hide file tree
Showing 9 changed files with 174 additions and 282 deletions.
149 changes: 0 additions & 149 deletions Lib/test/test_generated_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -1697,155 +1697,6 @@ def test_multiple_labels(self):
}
"""

class TestGeneratedTailCallErorHandlers(unittest.TestCase):
def setUp(self) -> None:
super().setUp()
self.maxDiff = None

self.temp_dir = tempfile.gettempdir()
self.temp_input_filename = os.path.join(self.temp_dir, "input.txt")
self.temp_output_filename = os.path.join(self.temp_dir, "output.txt")
self.temp_metadata_filename = os.path.join(self.temp_dir, "metadata.txt")
self.temp_pymetadata_filename = os.path.join(self.temp_dir, "pymetadata.txt")
self.temp_executor_filename = os.path.join(self.temp_dir, "executor.txt")

def tearDown(self) -> None:
for filename in [
self.temp_input_filename,
self.temp_output_filename,
self.temp_metadata_filename,
self.temp_pymetadata_filename,
self.temp_executor_filename,
]:
try:
os.remove(filename)
except:
pass
super().tearDown()

def run_cases_test(self, input: str, expected: str):
with open(self.temp_input_filename, "w+") as temp_input:
temp_input.write(textwrap.dedent(input))
temp_input.flush()

with handle_stderr():
tier1_tail_call_generator.generate_label_handlers_from_files(
self.temp_input_filename, self.temp_output_filename
)

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)

self.assertEqual(actual.strip(), textwrap.dedent(expected).strip())

def test_correctly_finds_pyeval_framedefault(self):
input = """
PyObject* _Py_HOT_FUNCTION
_PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int throwflag)
{
/* END_BASE_INTERPRETER */
}
"""
output = """
"""
self.run_cases_test(input, output)

def test_simple_label(self):
input = """
PyObject* _Py_HOT_FUNCTION
_PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int throwflag)
{
TAIL_CALL_TARGET(error):
DO_THING();
/* END_BASE_INTERPRETER */
}
"""
output = """
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_error(TAIL_CALL_PARAMS);
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_error(TAIL_CALL_PARAMS)
{
DO_THING();
/* END_BASE_INTERPRETER */
}
"""
self.run_cases_test(input, output)

def test_fallthrough_label(self):
input = """
PyObject* _Py_HOT_FUNCTION
_PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int throwflag)
{
TAIL_CALL_TARGET(error):
DO_THING();
TAIL_CALL_TARGET(fallthrough):
DO_THING2();
/* END_BASE_INTERPRETER */
}
"""
output = """
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_error(TAIL_CALL_PARAMS);
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_fallthrough(TAIL_CALL_PARAMS);
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_error(TAIL_CALL_PARAMS)
{
DO_THING();
TAIL_CALL(fallthrough);
}
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_fallthrough(TAIL_CALL_PARAMS)
{
DO_THING2();
/* END_BASE_INTERPRETER */
}
"""
self.run_cases_test(input, output)

def test_transform_gotos(self):
input = """
PyObject* _Py_HOT_FUNCTION
_PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int throwflag)
{
TAIL_CALL_TARGET(error):
if (thing) {
goto fallthrough;
}
DO_THING();
TAIL_CALL_TARGET(fallthrough):
DO_THING2();
/* END_BASE_INTERPRETER */
}
"""
output = """
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_error(TAIL_CALL_PARAMS);
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_fallthrough(TAIL_CALL_PARAMS);
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_error(TAIL_CALL_PARAMS)
{
if (thing) {
TAIL_CALL(fallthrough);
}
DO_THING();
TAIL_CALL(fallthrough);
}
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_fallthrough(TAIL_CALL_PARAMS)
{
DO_THING2();
/* END_BASE_INTERPRETER */
}
"""
self.run_cases_test(input, output)


class TestGeneratedAbstractCases(unittest.TestCase):
def setUp(self) -> None:
Expand Down
9 changes: 8 additions & 1 deletion Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -5287,7 +5287,14 @@ dummy_func(
lltrace_resume_frame(frame);
}
#endif
// This is a little complicated...
// If we are in a tail call handler, we want to tail call (DISPATCH).
// If we're not then we need the shim frame.
#if defined(Py_TAIL_CALL_INTERP) && !defined(IN_TAIL_CALL_INTERP)
return _TAIL_CALL_shim(frame, stack_pointer, tstate, next_instr, 0, 0);
#else
DISPATCH();
#endif
}

label(exit_unwind) {
Expand All @@ -5299,7 +5306,7 @@ dummy_func(
frame = tstate->current_frame = dying->previous;
_PyEval_FrameClearAndPop(tstate, dying);
frame->return_offset = 0;
if (frame == &entry_frame) {
if (frame->owner == FRAME_OWNED_BY_INTERPRETER) {
/* Restore previous frame and exit */
tstate->current_frame = frame->previous;
tstate->c_recursion_remaining += PY_EVAL_C_STACK_UNITS;
Expand Down
7 changes: 0 additions & 7 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -808,7 +808,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
#ifdef Py_STATS
int lastopcode = 0;
#endif
#ifndef Py_TAIL_CALL_INTERP
uint8_t opcode; /* Current opcode */
int oparg; /* Current opcode argument, if any */

Expand All @@ -835,7 +834,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
#endif
/* Push frame */
entry_frame.previous = tstate->current_frame;
entry_frame.is_entry_frame = 1;
frame->previous = &entry_frame;
tstate->current_frame = frame;

Expand Down Expand Up @@ -910,18 +908,13 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
#endif

#ifdef Py_TAIL_CALL_INTERP
#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
#else
DISPATCH();
#endif

#include "generated_cases.c.h"


#ifdef _Py_TIER2

// Tier 2 is also here!
Expand Down
2 changes: 1 addition & 1 deletion Python/ceval_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ GETITEM(PyObject *v, Py_ssize_t i) {
UPDATE_MISS_STATS((INSTNAME)); \
assert(_PyOpcode_Deopt[opcode] == (INSTNAME)); \
Py_MUSTTAIL \
return (INSTRUCTION_TABLE[op])(frame, stack_pointer, tstate, next_instr - 1 - size, opcode, oparg); \
return (INSTRUCTION_TABLE[INSTNAME])(frame, stack_pointer, tstate, next_instr - 1 - SIZE, opcode, oparg); \
}
#else
# define DEOPT_IF(COND, INSTNAME, SIZE) \
Expand Down
12 changes: 11 additions & 1 deletion Python/generated_cases.c.h

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

Loading

0 comments on commit 665c0f6

Please sign in to comment.