Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
16 changes: 8 additions & 8 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@
],
"updateContentCommand": {
// Using the shell for `nproc` usage.
"python": "./configure --config-cache --with-pydebug && make -s -j `nproc`",
"docs": [
"make",
"--directory",
"Doc",
"venv",
"html"
]
// "python": "./configure --config-cache --with-pydebug && make -s -j `nproc`",
// "docs": [
// "make",
// "--directory",
// "Doc",
// "venv",
// "html"
// ]
},
"postCreateCommand": {
// https://github.com/orgs/community/discussions/26026
Expand Down
15 changes: 3 additions & 12 deletions Makefile.pre.in
Original file line number Diff line number Diff line change
Expand Up @@ -699,18 +699,7 @@ build_wasm: check-clean-src $(BUILDPYTHON) platform sharedmods \
# Check that the source is clean when building out of source.
.PHONY: check-clean-src
check-clean-src:
@if test -n "$(VPATH)" -a \( \
-f "$(srcdir)/$(BUILDPYTHON)" \
-o -f "$(srcdir)/Programs/python.o" \
-o -f "$(srcdir)/Python/frozen_modules/importlib._bootstrap.h" \
\); then \
echo "Error: The source directory ($(srcdir)) is not clean" ; \
echo "Building Python out of the source tree (in $(abs_builddir)) requires a clean source tree ($(abs_srcdir))" ; \
echo "Build artifacts such as .o files, executables, and Python/frozen_modules/*.h must not exist within $(srcdir)." ; \
echo "Try to run:" ; \
echo " (cd \"$(srcdir)\" && make clean || git clean -fdx -e Doc/venv)" ; \
exit 1; \
fi
echo skipped clean check

# Profile generation build must start from a clean tree.
profile-clean-stamp:
Expand Down Expand Up @@ -1953,6 +1942,8 @@ Python/compile.o Python/assemble.o Python/flowgraph.o Python/instruction_sequenc

Python/ceval.o: \
$(srcdir)/Python/ceval_macros.h \
$(srcdir)/Python/tail_call_funcs.h \
$(srcdir)/Python/opcode_funcs.h \
$(srcdir)/Python/condvar.h \
$(srcdir)/Python/generated_cases.c.h \
$(srcdir)/Python/executor_cases.c.h \
Expand Down
20 changes: 10 additions & 10 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -806,7 +806,7 @@ dummy_func(
if (do_raise(tstate, exc, cause)) {
assert(oparg == 0);
monitor_reraise(tstate, frame, this_instr);
goto exception_unwind;
CEVAL_GOTO(exception_unwind);
}
break;
default:
Expand All @@ -824,7 +824,7 @@ dummy_func(
tstate->current_frame = frame->previous;
assert(!_PyErr_Occurred(tstate));
tstate->c_recursion_remaining += PY_EVAL_C_STACK_UNITS;
return retval;
return (uintptr_t) retval;
}

// The stack effect here is ambiguous.
Expand Down Expand Up @@ -868,7 +868,7 @@ dummy_func(
_PyEval_FrameClearAndPop(tstate, dying);
_PyFrame_StackPush(frame, retval);
LOAD_IP(frame->return_offset);
goto resume_frame;
CEVAL_GOTO(resume_frame);
}

macro(RETURN_CONST) =
Expand All @@ -892,7 +892,7 @@ dummy_func(
_PyEval_FrameClearAndPop(tstate, dying);
_PyFrame_StackPush(frame, retval);
LOAD_IP(frame->return_offset);
goto resume_frame;
CEVAL_GOTO(resume_frame);
}

inst(GET_AITER, (obj -- iter)) {
Expand Down Expand Up @@ -1095,7 +1095,7 @@ dummy_func(
/* We don't know which of these is relevant here, so keep them equal */
assert(INLINE_CACHE_ENTRIES_SEND == INLINE_CACHE_ENTRIES_FOR_ITER);
LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND);
goto resume_frame;
CEVAL_GOTO(resume_frame);
}

inst(YIELD_VALUE, (retval -- value)) {
Expand Down Expand Up @@ -1157,7 +1157,7 @@ dummy_func(
Py_INCREF(exc);
_PyErr_SetRaisedException(tstate, exc);
monitor_reraise(tstate, frame, this_instr);
goto exception_unwind;
CEVAL_GOTO(exception_unwind);
}

tier1 inst(END_ASYNC_FOR, (awaitable, exc -- )) {
Expand All @@ -1169,7 +1169,7 @@ dummy_func(
Py_INCREF(exc);
_PyErr_SetRaisedException(tstate, exc);
monitor_reraise(tstate, frame, this_instr);
goto exception_unwind;
CEVAL_GOTO(exception_unwind);
}
}

Expand All @@ -1184,7 +1184,7 @@ dummy_func(
else {
_PyErr_SetRaisedException(tstate, Py_NewRef(exc_value));
monitor_reraise(tstate, frame, this_instr);
goto exception_unwind;
CEVAL_GOTO(exception_unwind);
}
}

Expand Down Expand Up @@ -3422,7 +3422,7 @@ dummy_func(
* We don't check recursion depth here,
* as it will be checked after start_frame */
tstate->py_recursion_remaining--;
goto start_frame;
CEVAL_GOTO(start_frame);
}

inst(EXIT_INIT_CHECK, (should_be_none -- )) {
Expand Down Expand Up @@ -3615,7 +3615,7 @@ dummy_func(
DEOPT_IF(!PyList_Check(self));
STAT_INC(CALL, hit);
if (_PyList_AppendTakeRef((PyListObject *)self, arg) < 0) {
goto pop_1_error; // Since arg is DECREF'ed already
CEVAL_GOTO(pop_1_error); // Since arg is DECREF'ed already
}
Py_DECREF(self);
Py_DECREF(callable);
Expand Down
14 changes: 14 additions & 0 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

#define _PY_INTERPRETER

#define USE_COMPUTED_GOTOS 0
#define USE_TAIL_CALLS 1

#include "Python.h"
#include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_backoff.h"
Expand Down Expand Up @@ -684,6 +687,11 @@ extern void _PyUOpPrint(const _PyUOpInstruction *uop);
/* This setting is reversed below following _PyEval_EvalFrameDefault */
#endif

#if USE_TAIL_CALLS
#include "tail_call_funcs.h"
#include "opcode_funcs.h"
#endif

PyObject* _Py_HOT_FUNCTION
_PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int throwflag)
{
Expand Down Expand Up @@ -780,9 +788,14 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
assert(!_PyErr_Occurred(tstate));
#endif

#if USE_TAIL_CALLS
ret_state s;
#endif

DISPATCH();

{
#if !USE_TAIL_CALLS
/* Start instructions */
#if !USE_COMPUTED_GOTOS
dispatch_opcode:
Expand Down Expand Up @@ -849,6 +862,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
goto error;

} /* End instructions */
#endif

/* This should never be reached. Every opcode should end with DISPATCH()
or goto error. */
Expand Down
33 changes: 27 additions & 6 deletions Python/ceval_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,24 @@
#define INSTRUCTION_STATS(op) ((void)0)
#endif

typedef struct {
PyThreadState *tstate;
_PyInterpreterFrame *frame;
PyObject **stack_pointer;
_Py_CODEUNIT *next_instr;
int opcode;
int oparg;
} ret_state;

typedef uintptr_t (*OPCODE_FUNC_PTR_TYPE)(PyThreadState *tstate, _PyInterpreterFrame *frame, PyObject **stack_pointer, _Py_CODEUNIT *next_instr, int opcode, int oparg, ret_state *state);
static OPCODE_FUNC_PTR_TYPE opcode_funcs[256];

#if USE_COMPUTED_GOTOS
# define TARGET(op) TARGET_##op:
# define DISPATCH_GOTO() goto *opcode_targets[opcode]
#elif USE_TAIL_CALLS
# define DISPATCH_GOTO() OPCODE_FUNC_PTR_TYPE next = opcode_funcs[opcode]; \
__attribute__((musttail)) return next(tstate, frame, stack_pointer, next_instr, opcode, oparg, state)
#else
# define TARGET(op) case op: TARGET_##op:
# define DISPATCH_GOTO() goto dispatch_opcode
Expand Down Expand Up @@ -127,11 +142,11 @@ do { \
(NEW_FRAME)->previous = frame; \
frame = tstate->current_frame = (NEW_FRAME); \
CALL_STAT_INC(inlined_py_calls); \
goto start_frame; \
CEVAL_GOTO(start_frame); \
} while (0)

// Use this instead of 'goto error' so Tier 2 can go to a different label
#define GOTO_ERROR(LABEL) goto LABEL
#define GOTO_ERROR(LABEL) CEVAL_GOTO(LABEL)

#define CHECK_EVAL_BREAKER() \
_Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); \
Expand Down Expand Up @@ -266,7 +281,13 @@ GETITEM(PyObject *v, Py_ssize_t i) {
GETLOCAL(i) = value; \
Py_XDECREF(tmp); } while (0)

#define GO_TO_INSTRUCTION(op) goto PREDICT_ID(op)
#if USE_TAIL_CALLS
# define GO_TO_INSTRUCTION(OP, SUB) OPCODE_FUNC_PTR_TYPE next = opcode_funcs[OP]; \
next_instr -= SUB; \
__attribute__((musttail)) return next(tstate, frame, stack_pointer, next_instr, opcode, oparg, state)
#else
# define GO_TO_INSTRUCTION(op) goto PREDICT_ID(op)
#endif

#ifdef Py_STATS
#define UPDATE_MISS_STATS(INSTNAME) \
Expand All @@ -282,12 +303,12 @@ GETITEM(PyObject *v, Py_ssize_t i) {
#define UPDATE_MISS_STATS(INSTNAME) ((void)0)
#endif

#define DEOPT_IF(COND, INSTNAME) \
#define DEOPT_IF(COND, INSTNAME, SUB) \
if ((COND)) { \
/* This is only a single jump on release builds! */ \
UPDATE_MISS_STATS((INSTNAME)); \
assert(_PyOpcode_Deopt[opcode] == (INSTNAME)); \
GO_TO_INSTRUCTION(INSTNAME); \
GO_TO_INSTRUCTION(INSTNAME, SUB); \
}


Expand Down Expand Up @@ -366,7 +387,7 @@ do { \
stack_pointer = _PyFrame_GetStackPointer(frame); \
if (next_instr == NULL) { \
next_instr = (dest)+1; \
goto error; \
CEVAL_GOTO(error); \
} \
} \
} while (0);
Expand Down
Loading