mirror of
https://github.com/python/cpython.git
synced 2025-07-07 19:35:27 +00:00
gh-128563: A new tail-calling interpreter (GH-128718)
Co-authored-by: Garrett Gu <garrettgu777@gmail.com> Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
This commit is contained in:
parent
555dc50c81
commit
cb640b659e
16 changed files with 3883 additions and 623 deletions
113
.github/workflows/tail-call.yml
vendored
Normal file
113
.github/workflows/tail-call.yml
vendored
Normal file
|
@ -0,0 +1,113 @@
|
|||
name: Tail calling interpreter
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'Python/bytecodes.c'
|
||||
- 'Python/ceval.c'
|
||||
- 'Python/ceval_macros.h'
|
||||
push:
|
||||
paths:
|
||||
- 'Python/bytecodes.c'
|
||||
- 'Python/ceval.c'
|
||||
- 'Python/ceval_macros.h'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
|
||||
jobs:
|
||||
tail-call:
|
||||
name: ${{ matrix.target }}
|
||||
runs-on: ${{ matrix.runner }}
|
||||
timeout-minutes: 90
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target:
|
||||
# Un-comment as we add support for more platforms for tail-calling interpreters.
|
||||
# - i686-pc-windows-msvc/msvc
|
||||
# - x86_64-pc-windows-msvc/msvc
|
||||
# - aarch64-pc-windows-msvc/msvc
|
||||
- x86_64-apple-darwin/clang
|
||||
- aarch64-apple-darwin/clang
|
||||
- x86_64-unknown-linux-gnu/gcc
|
||||
- aarch64-unknown-linux-gnu/gcc
|
||||
llvm:
|
||||
- 19
|
||||
include:
|
||||
# - target: i686-pc-windows-msvc/msvc
|
||||
# architecture: Win32
|
||||
# runner: windows-latest
|
||||
# - target: x86_64-pc-windows-msvc/msvc
|
||||
# architecture: x64
|
||||
# runner: windows-latest
|
||||
# - target: aarch64-pc-windows-msvc/msvc
|
||||
# architecture: ARM64
|
||||
# runner: windows-latest
|
||||
- target: x86_64-apple-darwin/clang
|
||||
architecture: x86_64
|
||||
runner: macos-13
|
||||
- target: aarch64-apple-darwin/clang
|
||||
architecture: aarch64
|
||||
runner: macos-14
|
||||
- target: x86_64-unknown-linux-gnu/gcc
|
||||
architecture: x86_64
|
||||
runner: ubuntu-24.04
|
||||
- target: aarch64-unknown-linux-gnu/gcc
|
||||
architecture: aarch64
|
||||
runner: ubuntu-24.04-arm
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Native Windows (debug)
|
||||
if: runner.os == 'Windows' && matrix.architecture != 'ARM64'
|
||||
run: |
|
||||
choco install llvm --allow-downgrade --no-progress --version ${{ matrix.llvm }}.1.0
|
||||
./PCbuild/build.bat --tail-call-interp -d -p ${{ matrix.architecture }}
|
||||
./PCbuild/rt.bat -d -p ${{ matrix.architecture }} -q --multiprocess 0 --timeout 4500 --verbose2 --verbose3
|
||||
|
||||
# No tests (yet):
|
||||
- name: Emulated Windows (release)
|
||||
if: runner.os == 'Windows' && matrix.architecture == 'ARM64'
|
||||
run: |
|
||||
choco install llvm --allow-downgrade --no-progress --version ${{ matrix.llvm }}.1.0
|
||||
./PCbuild/build.bat --tail-call-interp -p ${{ matrix.architecture }}
|
||||
|
||||
# The `find` line is required as a result of https://github.com/actions/runner-images/issues/9966.
|
||||
# This is a bug in the macOS runner image where the pre-installed Python is installed in the same
|
||||
# directory as the Homebrew Python, which causes the build to fail for macos-13. This line removes
|
||||
# the symlink to the pre-installed Python so that the Homebrew Python is used instead.
|
||||
- name: Native macOS (debug)
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
brew update
|
||||
find /usr/local/bin -lname '*/Library/Frameworks/Python.framework/*' -delete
|
||||
brew install llvm@${{ matrix.llvm }}
|
||||
export SDKROOT="$(xcrun --show-sdk-path)"
|
||||
export PATH="/opt/homebrew/opt/llvm/bin:$PATH"
|
||||
export PATH="/usr/local/opt/llvm/bin:$PATH"
|
||||
CC=clang-19 ./configure --with-tail-call-interp --with-pydebug
|
||||
make all --jobs 4
|
||||
./python.exe -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3
|
||||
|
||||
- name: Native Linux (release)
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ matrix.llvm }}
|
||||
export PATH="$(llvm-config-${{ matrix.llvm }} --bindir):$PATH"
|
||||
CC=clang-19 ./configure --with-tail-call-interp
|
||||
make all --jobs 4
|
||||
./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3
|
||||
|
|
@ -304,6 +304,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP);
|
||||
|
@ -322,6 +327,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP);
|
||||
|
@ -343,6 +353,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP);
|
||||
|
@ -365,6 +380,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP);
|
||||
|
@ -388,6 +408,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP);
|
||||
|
@ -414,6 +439,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP);
|
||||
|
@ -442,6 +472,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP1) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP1;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP1);
|
||||
|
@ -453,12 +488,23 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
}
|
||||
|
||||
TARGET(OP3) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP3;
|
||||
(void)(opcode);
|
||||
_Py_CODEUNIT* const this_instr = next_instr;
|
||||
(void)this_instr;
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP3);
|
||||
static_assert(INLINE_CACHE_ENTRIES_OP1 == 0, "incorrect cache size");
|
||||
_PyStackRef res;
|
||||
DEOPT_IF(xxx, OP1);
|
||||
if (xxx) {
|
||||
UPDATE_MISS_STATS(OP1);
|
||||
assert(_PyOpcode_Deopt[opcode] == (OP1));
|
||||
JUMP_TO_PREDICTED(OP1);
|
||||
}
|
||||
res = Py_None;
|
||||
stack_pointer[-1] = res;
|
||||
DISPATCH();
|
||||
|
@ -481,6 +527,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(A) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = A;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(A);
|
||||
|
@ -498,6 +549,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
}
|
||||
|
||||
TARGET(B) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = B;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(B);
|
||||
|
@ -535,11 +591,16 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP);
|
||||
if (cond) {
|
||||
goto label;
|
||||
JUMP_TO_LABEL(label);
|
||||
}
|
||||
DISPATCH();
|
||||
}
|
||||
|
@ -554,11 +615,16 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP);
|
||||
if (cond) {
|
||||
goto label;
|
||||
JUMP_TO_LABEL(label);
|
||||
}
|
||||
// Comment is ok
|
||||
DISPATCH();
|
||||
|
@ -577,6 +643,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP);
|
||||
|
@ -587,7 +658,7 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
left = stack_pointer[-2];
|
||||
SPAM(left, right);
|
||||
if (cond) {
|
||||
goto pop_2_label;
|
||||
JUMP_TO_LABEL(pop_2_label);
|
||||
}
|
||||
res = 0;
|
||||
stack_pointer[-2] = res;
|
||||
|
@ -608,6 +679,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP);
|
||||
|
@ -618,7 +694,7 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
left = stack_pointer[-2];
|
||||
res = SPAM(left, right);
|
||||
if (cond) {
|
||||
goto pop_2_label;
|
||||
JUMP_TO_LABEL(pop_2_label);
|
||||
}
|
||||
stack_pointer[-2] = res;
|
||||
stack_pointer += -1;
|
||||
|
@ -635,8 +711,14 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP) {
|
||||
_Py_CODEUNIT* const this_instr = frame->instr_ptr = next_instr;
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP;
|
||||
(void)(opcode);
|
||||
_Py_CODEUNIT* const this_instr = next_instr;
|
||||
(void)this_instr;
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 4;
|
||||
INSTRUCTION_STATS(OP);
|
||||
uint16_t counter = read_u16(&this_instr[1].cache);
|
||||
|
@ -661,13 +743,18 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP);
|
||||
goto somewhere;
|
||||
JUMP_TO_LABEL(somewhere);
|
||||
}
|
||||
|
||||
somewhere:
|
||||
LABEL(somewhere)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -692,6 +779,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 6;
|
||||
INSTRUCTION_STATS(OP);
|
||||
|
@ -729,8 +821,14 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
}
|
||||
|
||||
TARGET(OP1) {
|
||||
_Py_CODEUNIT* const this_instr = frame->instr_ptr = next_instr;
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP1;
|
||||
(void)(opcode);
|
||||
_Py_CODEUNIT* const this_instr = next_instr;
|
||||
(void)this_instr;
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 2;
|
||||
INSTRUCTION_STATS(OP1);
|
||||
_PyStackRef left;
|
||||
|
@ -746,6 +844,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
}
|
||||
|
||||
TARGET(OP3) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP3;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 6;
|
||||
INSTRUCTION_STATS(OP3);
|
||||
|
@ -777,6 +880,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 4;
|
||||
INSTRUCTION_STATS(OP);
|
||||
|
@ -799,6 +907,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP1) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP1;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP1);
|
||||
|
@ -818,6 +931,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP1) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP1;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP1);
|
||||
|
@ -840,6 +958,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP1) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP1;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP1);
|
||||
|
@ -847,6 +970,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
}
|
||||
|
||||
TARGET(OP2) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP2;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP2);
|
||||
|
@ -864,6 +992,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP);
|
||||
|
@ -887,6 +1020,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP);
|
||||
|
@ -915,6 +1053,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP);
|
||||
|
@ -939,13 +1082,18 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP);
|
||||
if (oparg == 0) {
|
||||
stack_pointer += -1 - oparg;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
goto somewhere;
|
||||
JUMP_TO_LABEL(somewhere);
|
||||
}
|
||||
stack_pointer += -1 - oparg;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
|
@ -965,6 +1113,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP);
|
||||
|
@ -1006,6 +1159,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(M) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = M;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(M);
|
||||
|
@ -1050,6 +1208,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(M) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = M;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(M);
|
||||
|
@ -1083,6 +1246,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP);
|
||||
|
@ -1104,6 +1272,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(M) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = M;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(M);
|
||||
|
@ -1121,6 +1294,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP);
|
||||
|
@ -1139,6 +1317,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(M) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = M;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(M);
|
||||
|
@ -1175,6 +1358,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP);
|
||||
|
@ -1197,6 +1385,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP);
|
||||
|
@ -1235,6 +1428,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(INST) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = INST;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(INST);
|
||||
|
@ -1261,6 +1459,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(TEST) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = TEST;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(TEST);
|
||||
|
@ -1301,6 +1504,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(TEST) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = TEST;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(TEST);
|
||||
|
@ -1340,6 +1548,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(TEST) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = TEST;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(TEST);
|
||||
|
@ -1388,6 +1601,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(TEST) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = TEST;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(TEST);
|
||||
|
@ -1409,7 +1627,7 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
{
|
||||
// Mark j and k as used
|
||||
if (cond) {
|
||||
goto pop_2_error;
|
||||
JUMP_TO_LABEL(pop_2_error);
|
||||
}
|
||||
}
|
||||
stack_pointer += -2;
|
||||
|
@ -1436,6 +1654,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
|
||||
output = """
|
||||
TARGET(TEST) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = TEST;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(TEST);
|
||||
|
@ -1453,7 +1676,7 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
stack_pointer[1] = b;
|
||||
stack_pointer += 2;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
goto error;
|
||||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
}
|
||||
stack_pointer[0] = a;
|
||||
|
@ -1477,17 +1700,27 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP1) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP1;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP1);
|
||||
goto here;
|
||||
JUMP_TO_LABEL(here);
|
||||
}
|
||||
|
||||
TARGET(OP2) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP2;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP2);
|
||||
goto there;
|
||||
JUMP_TO_LABEL(there);
|
||||
}
|
||||
"""
|
||||
self.run_cases_test(input, output)
|
||||
|
@ -1541,6 +1774,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
|
||||
output = """
|
||||
TARGET(BALANCED) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = BALANCED;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(BALANCED);
|
||||
|
@ -1561,6 +1799,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
|
||||
output = """
|
||||
TARGET(BALANCED) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = BALANCED;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(BALANCED);
|
||||
|
@ -1582,6 +1825,13 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
|
||||
output = """
|
||||
TARGET(BALANCED) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = BALANCED;
|
||||
(void)(opcode);
|
||||
_Py_CODEUNIT* const this_instr = next_instr;
|
||||
(void)this_instr;
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(BALANCED);
|
||||
|
@ -1602,6 +1852,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
|
||||
output = """
|
||||
TARGET(OP) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP);
|
||||
|
@ -1637,6 +1892,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP);
|
||||
|
@ -1671,6 +1931,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP);
|
||||
|
@ -1702,6 +1967,11 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
output = """
|
||||
TARGET(OP) {
|
||||
#if defined(Py_TAIL_CALL_INTERP)
|
||||
int opcode;
|
||||
#endif
|
||||
opcode = OP;
|
||||
(void)(opcode);
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(OP);
|
||||
|
@ -1793,26 +2063,26 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
|
||||
output = """
|
||||
other_label:
|
||||
LABEL(other_label)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
other_label2:
|
||||
LABEL(other_label2)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
my_label:
|
||||
LABEL(my_label)
|
||||
{
|
||||
// Comment
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
do_thing();
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (complex) {
|
||||
goto other_label;
|
||||
JUMP_TO_LABEL(other_label);
|
||||
}
|
||||
goto other_label2;
|
||||
JUMP_TO_LABEL(other_label2);
|
||||
}
|
||||
"""
|
||||
self.run_cases_test(input, output)
|
||||
|
@ -1831,17 +2101,17 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
|
||||
output = """
|
||||
one:
|
||||
LABEL(one)
|
||||
{
|
||||
/* STACK SPILLED */
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
goto two;
|
||||
JUMP_TO_LABEL(two);
|
||||
}
|
||||
|
||||
two:
|
||||
LABEL(two)
|
||||
{
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
goto one;
|
||||
JUMP_TO_LABEL(one);
|
||||
}
|
||||
"""
|
||||
self.run_cases_test(input, output)
|
||||
|
@ -1887,20 +2157,26 @@ class TestGeneratedCases(unittest.TestCase):
|
|||
"""
|
||||
|
||||
output = """
|
||||
my_label_1:
|
||||
LABEL(my_label_1)
|
||||
{
|
||||
// Comment
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
do_thing1();
|
||||
goto my_label_2;
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
JUMP_TO_LABEL(my_label_2);
|
||||
}
|
||||
|
||||
my_label_2:
|
||||
LABEL(my_label_2)
|
||||
{
|
||||
// Comment
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
do_thing2();
|
||||
goto my_label_1;
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
JUMP_TO_LABEL(my_label_1);
|
||||
}
|
||||
"""
|
||||
self.run_cases_test(input, output)
|
||||
|
||||
|
||||
class TestGeneratedAbstractCases(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
A new type of interpreter has been added to CPython. This interpreter uses tail calls for its instruction handlers. Preliminary benchmark results suggest 7-11% geometric mean faster on pyperformance (depending on platform), and up to 30% faster on Python-intensive workloads. This interpreter currently only works on newer compilers, such as ``clang-19``. Other compilers will continue using the old interpreter. Patch by Ken Jin, with ideas on how to implement this in CPython by Mark Shannon, Garret Gu, Haoran Xu, and Josh Haberman.
|
|
@ -1387,7 +1387,9 @@ dummy_func(
|
|||
|
||||
tier1 inst(CLEANUP_THROW, (sub_iter_st, last_sent_val_st, exc_value_st -- none, value)) {
|
||||
PyObject *exc_value = PyStackRef_AsPyObjectBorrow(exc_value_st);
|
||||
#ifndef Py_TAIL_CALL_INTERP
|
||||
assert(throwflag);
|
||||
#endif
|
||||
assert(exc_value && PyExceptionInstance_Check(exc_value));
|
||||
|
||||
int matches = PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration);
|
||||
|
@ -5305,6 +5307,9 @@ dummy_func(
|
|||
}
|
||||
#endif
|
||||
RELOAD_STACK();
|
||||
#ifdef Py_TAIL_CALL_INTERP
|
||||
int opcode;
|
||||
#endif
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
|
@ -5351,8 +5356,10 @@ dummy_func(
|
|||
caller loses its exception */
|
||||
assert(!_PyErr_Occurred(tstate));
|
||||
#endif
|
||||
|
||||
RELOAD_STACK();
|
||||
#ifdef Py_TAIL_CALL_INTERP
|
||||
int opcode;
|
||||
#endif
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
|
|
|
@ -768,13 +768,18 @@ _PyObjectArray_Free(PyObject **array, PyObject **scratch)
|
|||
#define PY_EVAL_C_STACK_UNITS 2
|
||||
|
||||
|
||||
#ifdef Py_TAIL_CALL_INTERP
|
||||
#include "opcode_targets.h"
|
||||
#include "generated_cases.c.h"
|
||||
#endif
|
||||
|
||||
PyObject* _Py_HOT_FUNCTION
|
||||
_PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int throwflag)
|
||||
{
|
||||
_Py_EnsureTstateNotNULL(tstate);
|
||||
CALL_STAT_INC(pyeval_calls);
|
||||
|
||||
#if USE_COMPUTED_GOTOS
|
||||
#if USE_COMPUTED_GOTOS && !defined(Py_TAIL_CALL_INTERP)
|
||||
/* Import the static jump table */
|
||||
#include "opcode_targets.h"
|
||||
#endif
|
||||
|
@ -782,10 +787,11 @@ _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 */
|
||||
|
||||
_PyInterpreterFrame entry_frame;
|
||||
#endif
|
||||
_PyInterpreterFrame entry_frame;
|
||||
|
||||
if (_Py_EnterRecursiveCallTstate(tstate, "")) {
|
||||
assert(frame->owner != FRAME_OWNED_BY_INTERPRETER);
|
||||
|
@ -845,7 +851,11 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
|
|||
next_instr = frame->instr_ptr;
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
monitor_throw(tstate, frame, next_instr);
|
||||
#ifdef Py_TAIL_CALL_INTERP
|
||||
return _TAIL_CALL_error(frame, stack_pointer, tstate, next_instr, 0);
|
||||
#else
|
||||
goto error;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(_Py_TIER2) && !defined(_Py_JIT)
|
||||
|
@ -854,9 +864,12 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
|
|||
const _PyUOpInstruction *next_uop = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef Py_TAIL_CALL_INTERP
|
||||
return _TAIL_CALL_start_frame(frame, NULL, tstate, NULL, 0);
|
||||
#else
|
||||
goto start_frame;
|
||||
|
||||
#include "generated_cases.c.h"
|
||||
# include "generated_cases.c.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _Py_TIER2
|
||||
|
|
|
@ -70,12 +70,41 @@
|
|||
#define INSTRUCTION_STATS(op) ((void)0)
|
||||
#endif
|
||||
|
||||
#if USE_COMPUTED_GOTOS
|
||||
#define TAIL_CALL_PARAMS _PyInterpreterFrame *frame, _PyStackRef *stack_pointer, PyThreadState *tstate, _Py_CODEUNIT *next_instr, int oparg
|
||||
#define TAIL_CALL_ARGS frame, stack_pointer, tstate, next_instr, oparg
|
||||
|
||||
#ifdef Py_TAIL_CALL_INTERP
|
||||
// Note: [[clang::musttail]] works for GCC 15, but not __attribute__((musttail)) at the moment.
|
||||
# define Py_MUSTTAIL [[clang::musttail]]
|
||||
# define Py_PRESERVE_NONE_CC __attribute__((preserve_none))
|
||||
Py_PRESERVE_NONE_CC typedef PyObject* (*py_tail_call_funcptr)(TAIL_CALL_PARAMS);
|
||||
|
||||
# define TARGET(op) Py_PRESERVE_NONE_CC PyObject *_TAIL_CALL_##op(TAIL_CALL_PARAMS)
|
||||
# define DISPATCH_GOTO() \
|
||||
do { \
|
||||
Py_MUSTTAIL return (INSTRUCTION_TABLE[opcode])(TAIL_CALL_ARGS); \
|
||||
} while (0)
|
||||
# define JUMP_TO_LABEL(name) \
|
||||
do { \
|
||||
Py_MUSTTAIL return (_TAIL_CALL_##name)(TAIL_CALL_ARGS); \
|
||||
} while (0)
|
||||
# define JUMP_TO_PREDICTED(name) \
|
||||
do { \
|
||||
Py_MUSTTAIL return (_TAIL_CALL_##name)(frame, stack_pointer, tstate, this_instr, oparg); \
|
||||
} while (0)
|
||||
# define LABEL(name) TARGET(name)
|
||||
#elif USE_COMPUTED_GOTOS
|
||||
# define TARGET(op) TARGET_##op:
|
||||
# define DISPATCH_GOTO() goto *opcode_targets[opcode]
|
||||
# define JUMP_TO_LABEL(name) goto name;
|
||||
# define JUMP_TO_PREDICTED(name) goto PREDICTED_##name;
|
||||
# define LABEL(name) name:
|
||||
#else
|
||||
# define TARGET(op) case op: TARGET_##op:
|
||||
# define DISPATCH_GOTO() goto dispatch_opcode
|
||||
# define JUMP_TO_LABEL(name) goto name;
|
||||
# define JUMP_TO_PREDICTED(name) goto PREDICTED_##name;
|
||||
# define LABEL(name) name:
|
||||
#endif
|
||||
|
||||
/* PRE_DISPATCH_GOTO() does lltrace if enabled. Normally a no-op */
|
||||
|
@ -92,7 +121,7 @@ do { \
|
|||
int lltrace = maybe_lltrace_resume_frame(frame, GLOBALS()); \
|
||||
frame->lltrace = lltrace; \
|
||||
if (lltrace < 0) { \
|
||||
goto exit_unwind; \
|
||||
JUMP_TO_LABEL(exit_unwind); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
|
@ -129,11 +158,11 @@ do { \
|
|||
assert((NEW_FRAME)->previous == frame); \
|
||||
frame = tstate->current_frame = (NEW_FRAME); \
|
||||
CALL_STAT_INC(inlined_py_calls); \
|
||||
goto start_frame; \
|
||||
JUMP_TO_LABEL(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) JUMP_TO_LABEL(LABEL)
|
||||
|
||||
/* Tuple access macros */
|
||||
|
||||
|
@ -236,14 +265,6 @@ GETITEM(PyObject *v, Py_ssize_t i) {
|
|||
#define UPDATE_MISS_STATS(INSTNAME) ((void)0)
|
||||
#endif
|
||||
|
||||
#define DEOPT_IF(COND, INSTNAME) \
|
||||
if ((COND)) { \
|
||||
/* This is only a single jump on release builds! */ \
|
||||
UPDATE_MISS_STATS((INSTNAME)); \
|
||||
assert(_PyOpcode_Deopt[opcode] == (INSTNAME)); \
|
||||
goto PREDICTED_##INSTNAME; \
|
||||
}
|
||||
|
||||
|
||||
// Try to lock an object in the free threading build, if it's not already
|
||||
// locked. Use with a DEOPT_IF() to deopt if the object is already locked.
|
||||
|
@ -328,7 +349,7 @@ do { \
|
|||
stack_pointer = _PyFrame_GetStackPointer(frame); \
|
||||
if (next_instr == NULL) { \
|
||||
next_instr = (dest)+1; \
|
||||
goto error; \
|
||||
JUMP_TO_LABEL(error); \
|
||||
} \
|
||||
} \
|
||||
} while (0);
|
||||
|
|
3232
Python/generated_cases.c.h
generated
3232
Python/generated_cases.c.h
generated
File diff suppressed because it is too large
Load diff
505
Python/opcode_targets.h
generated
505
Python/opcode_targets.h
generated
|
@ -1,3 +1,4 @@
|
|||
#ifndef Py_TAIL_CALL_INTERP
|
||||
static void *opcode_targets[256] = {
|
||||
&&TARGET_CACHE,
|
||||
&&TARGET_BINARY_SLICE,
|
||||
|
@ -256,3 +257,507 @@ static void *opcode_targets[256] = {
|
|||
&&TARGET_INSTRUMENTED_LINE,
|
||||
&&TARGET_ENTER_EXECUTOR,
|
||||
};
|
||||
#else /* Py_TAIL_CALL_INTERP */
|
||||
static py_tail_call_funcptr INSTRUCTION_TABLE[256];
|
||||
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_pop_4_error(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_pop_3_error(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_pop_2_error(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_pop_1_error(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_error(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_exception_unwind(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_exit_unwind(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_start_frame(TAIL_CALL_PARAMS);
|
||||
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_OP(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_OP_ADD_FLOAT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_OP_ADD_INT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_OP_ADD_UNICODE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_OP_EXTEND(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_OP_INPLACE_ADD_UNICODE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_OP_MULTIPLY_FLOAT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_OP_MULTIPLY_INT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_OP_SUBTRACT_FLOAT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_OP_SUBTRACT_INT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_SLICE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_SUBSCR(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_SUBSCR_DICT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_SUBSCR_GETITEM(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_SUBSCR_LIST_INT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_SUBSCR_STR_INT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_SUBSCR_TUPLE_INT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BUILD_LIST(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BUILD_MAP(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BUILD_SET(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BUILD_SLICE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BUILD_STRING(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BUILD_TUPLE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CACHE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL_ALLOC_AND_ENTER_INIT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL_BOUND_METHOD_EXACT_ARGS(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL_BOUND_METHOD_GENERAL(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL_BUILTIN_CLASS(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL_BUILTIN_FAST(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL_BUILTIN_FAST_WITH_KEYWORDS(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL_BUILTIN_O(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL_FUNCTION_EX(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL_INTRINSIC_1(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL_INTRINSIC_2(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL_ISINSTANCE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL_KW(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL_KW_BOUND_METHOD(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL_KW_NON_PY(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL_KW_PY(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL_LEN(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL_LIST_APPEND(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL_METHOD_DESCRIPTOR_FAST(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL_METHOD_DESCRIPTOR_NOARGS(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL_METHOD_DESCRIPTOR_O(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL_NON_PY_GENERAL(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL_PY_EXACT_ARGS(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL_PY_GENERAL(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL_STR_1(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL_TUPLE_1(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL_TYPE_1(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CHECK_EG_MATCH(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CHECK_EXC_MATCH(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CLEANUP_THROW(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_COMPARE_OP(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_COMPARE_OP_FLOAT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_COMPARE_OP_INT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_COMPARE_OP_STR(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CONTAINS_OP(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CONTAINS_OP_DICT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CONTAINS_OP_SET(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CONVERT_VALUE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_COPY(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_COPY_FREE_VARS(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_DELETE_ATTR(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_DELETE_DEREF(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_DELETE_FAST(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_DELETE_GLOBAL(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_DELETE_NAME(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_DELETE_SUBSCR(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_DICT_MERGE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_DICT_UPDATE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_END_ASYNC_FOR(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_END_FOR(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_END_SEND(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_ENTER_EXECUTOR(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_EXIT_INIT_CHECK(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_EXTENDED_ARG(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_FORMAT_SIMPLE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_FORMAT_WITH_SPEC(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_FOR_ITER(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_FOR_ITER_GEN(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_FOR_ITER_LIST(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_FOR_ITER_RANGE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_FOR_ITER_TUPLE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_GET_AITER(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_GET_ANEXT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_GET_AWAITABLE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_GET_ITER(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_GET_LEN(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_GET_YIELD_FROM_ITER(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_IMPORT_FROM(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_IMPORT_NAME(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_INSTRUMENTED_CALL(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_INSTRUMENTED_CALL_FUNCTION_EX(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_INSTRUMENTED_CALL_KW(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_INSTRUMENTED_END_FOR(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_INSTRUMENTED_END_SEND(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_INSTRUMENTED_FOR_ITER(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_INSTRUMENTED_INSTRUCTION(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_INSTRUMENTED_JUMP_BACKWARD(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_INSTRUMENTED_JUMP_FORWARD(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_INSTRUMENTED_LINE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_INSTRUMENTED_LOAD_SUPER_ATTR(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_INSTRUMENTED_NOT_TAKEN(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_INSTRUMENTED_POP_ITER(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_INSTRUMENTED_POP_JUMP_IF_FALSE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_INSTRUMENTED_POP_JUMP_IF_NONE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_INSTRUMENTED_POP_JUMP_IF_NOT_NONE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_INSTRUMENTED_POP_JUMP_IF_TRUE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_INSTRUMENTED_RESUME(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_INSTRUMENTED_RETURN_VALUE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_INSTRUMENTED_YIELD_VALUE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_INTERPRETER_EXIT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_IS_OP(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_JUMP_BACKWARD(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_JUMP_BACKWARD_JIT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_JUMP_BACKWARD_NO_INTERRUPT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_JUMP_BACKWARD_NO_JIT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_JUMP_FORWARD(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LIST_APPEND(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LIST_EXTEND(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_ATTR(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_ATTR_CLASS(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_ATTR_CLASS_WITH_METACLASS_CHECK(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_ATTR_INSTANCE_VALUE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_ATTR_METHOD_LAZY_DICT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_ATTR_METHOD_NO_DICT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_ATTR_METHOD_WITH_VALUES(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_ATTR_MODULE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_ATTR_NONDESCRIPTOR_NO_DICT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_ATTR_PROPERTY(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_ATTR_SLOT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_ATTR_WITH_HINT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_BUILD_CLASS(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_COMMON_CONSTANT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_CONST(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_CONST_IMMORTAL(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_CONST_MORTAL(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_DEREF(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_FAST(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_FAST_AND_CLEAR(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_FAST_CHECK(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_FAST_LOAD_FAST(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_FROM_DICT_OR_DEREF(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_FROM_DICT_OR_GLOBALS(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_GLOBAL(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_GLOBAL_BUILTIN(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_GLOBAL_MODULE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_LOCALS(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_NAME(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_SMALL_INT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_SPECIAL(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_SUPER_ATTR(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_SUPER_ATTR_ATTR(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_LOAD_SUPER_ATTR_METHOD(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_MAKE_CELL(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_MAKE_FUNCTION(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_MAP_ADD(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_MATCH_CLASS(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_MATCH_KEYS(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_MATCH_MAPPING(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_MATCH_SEQUENCE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_NOP(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_NOT_TAKEN(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_POP_EXCEPT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_POP_ITER(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_POP_JUMP_IF_FALSE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_POP_JUMP_IF_NONE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_POP_JUMP_IF_NOT_NONE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_POP_JUMP_IF_TRUE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_POP_TOP(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_PUSH_EXC_INFO(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_PUSH_NULL(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_RAISE_VARARGS(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_RERAISE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_RESERVED(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_RESUME(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_RESUME_CHECK(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_RETURN_GENERATOR(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_RETURN_VALUE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_SEND(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_SEND_GEN(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_SETUP_ANNOTATIONS(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_SET_ADD(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_SET_FUNCTION_ATTRIBUTE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_SET_UPDATE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_STORE_ATTR(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_STORE_ATTR_INSTANCE_VALUE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_STORE_ATTR_SLOT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_STORE_ATTR_WITH_HINT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_STORE_DEREF(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_STORE_FAST(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_STORE_FAST_LOAD_FAST(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_STORE_FAST_STORE_FAST(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_STORE_GLOBAL(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_STORE_NAME(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_STORE_SLICE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_STORE_SUBSCR(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_STORE_SUBSCR_DICT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_STORE_SUBSCR_LIST_INT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_SWAP(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_TO_BOOL(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_TO_BOOL_ALWAYS_TRUE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_TO_BOOL_BOOL(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_TO_BOOL_INT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_TO_BOOL_LIST(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_TO_BOOL_NONE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_TO_BOOL_STR(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_UNARY_INVERT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_UNARY_NEGATIVE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_UNARY_NOT(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_UNPACK_EX(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_UNPACK_SEQUENCE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_UNPACK_SEQUENCE_LIST(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_UNPACK_SEQUENCE_TUPLE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_UNPACK_SEQUENCE_TWO_TUPLE(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_WITH_EXCEPT_START(TAIL_CALL_PARAMS);
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_YIELD_VALUE(TAIL_CALL_PARAMS);
|
||||
|
||||
Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_UNKNOWN_OPCODE(TAIL_CALL_PARAMS) {
|
||||
int 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);
|
||||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
|
||||
static py_tail_call_funcptr INSTRUCTION_TABLE[256] = {
|
||||
[BINARY_OP] = _TAIL_CALL_BINARY_OP,
|
||||
[BINARY_OP_ADD_FLOAT] = _TAIL_CALL_BINARY_OP_ADD_FLOAT,
|
||||
[BINARY_OP_ADD_INT] = _TAIL_CALL_BINARY_OP_ADD_INT,
|
||||
[BINARY_OP_ADD_UNICODE] = _TAIL_CALL_BINARY_OP_ADD_UNICODE,
|
||||
[BINARY_OP_EXTEND] = _TAIL_CALL_BINARY_OP_EXTEND,
|
||||
[BINARY_OP_INPLACE_ADD_UNICODE] = _TAIL_CALL_BINARY_OP_INPLACE_ADD_UNICODE,
|
||||
[BINARY_OP_MULTIPLY_FLOAT] = _TAIL_CALL_BINARY_OP_MULTIPLY_FLOAT,
|
||||
[BINARY_OP_MULTIPLY_INT] = _TAIL_CALL_BINARY_OP_MULTIPLY_INT,
|
||||
[BINARY_OP_SUBTRACT_FLOAT] = _TAIL_CALL_BINARY_OP_SUBTRACT_FLOAT,
|
||||
[BINARY_OP_SUBTRACT_INT] = _TAIL_CALL_BINARY_OP_SUBTRACT_INT,
|
||||
[BINARY_SLICE] = _TAIL_CALL_BINARY_SLICE,
|
||||
[BINARY_SUBSCR] = _TAIL_CALL_BINARY_SUBSCR,
|
||||
[BINARY_SUBSCR_DICT] = _TAIL_CALL_BINARY_SUBSCR_DICT,
|
||||
[BINARY_SUBSCR_GETITEM] = _TAIL_CALL_BINARY_SUBSCR_GETITEM,
|
||||
[BINARY_SUBSCR_LIST_INT] = _TAIL_CALL_BINARY_SUBSCR_LIST_INT,
|
||||
[BINARY_SUBSCR_STR_INT] = _TAIL_CALL_BINARY_SUBSCR_STR_INT,
|
||||
[BINARY_SUBSCR_TUPLE_INT] = _TAIL_CALL_BINARY_SUBSCR_TUPLE_INT,
|
||||
[BUILD_LIST] = _TAIL_CALL_BUILD_LIST,
|
||||
[BUILD_MAP] = _TAIL_CALL_BUILD_MAP,
|
||||
[BUILD_SET] = _TAIL_CALL_BUILD_SET,
|
||||
[BUILD_SLICE] = _TAIL_CALL_BUILD_SLICE,
|
||||
[BUILD_STRING] = _TAIL_CALL_BUILD_STRING,
|
||||
[BUILD_TUPLE] = _TAIL_CALL_BUILD_TUPLE,
|
||||
[CACHE] = _TAIL_CALL_CACHE,
|
||||
[CALL] = _TAIL_CALL_CALL,
|
||||
[CALL_ALLOC_AND_ENTER_INIT] = _TAIL_CALL_CALL_ALLOC_AND_ENTER_INIT,
|
||||
[CALL_BOUND_METHOD_EXACT_ARGS] = _TAIL_CALL_CALL_BOUND_METHOD_EXACT_ARGS,
|
||||
[CALL_BOUND_METHOD_GENERAL] = _TAIL_CALL_CALL_BOUND_METHOD_GENERAL,
|
||||
[CALL_BUILTIN_CLASS] = _TAIL_CALL_CALL_BUILTIN_CLASS,
|
||||
[CALL_BUILTIN_FAST] = _TAIL_CALL_CALL_BUILTIN_FAST,
|
||||
[CALL_BUILTIN_FAST_WITH_KEYWORDS] = _TAIL_CALL_CALL_BUILTIN_FAST_WITH_KEYWORDS,
|
||||
[CALL_BUILTIN_O] = _TAIL_CALL_CALL_BUILTIN_O,
|
||||
[CALL_FUNCTION_EX] = _TAIL_CALL_CALL_FUNCTION_EX,
|
||||
[CALL_INTRINSIC_1] = _TAIL_CALL_CALL_INTRINSIC_1,
|
||||
[CALL_INTRINSIC_2] = _TAIL_CALL_CALL_INTRINSIC_2,
|
||||
[CALL_ISINSTANCE] = _TAIL_CALL_CALL_ISINSTANCE,
|
||||
[CALL_KW] = _TAIL_CALL_CALL_KW,
|
||||
[CALL_KW_BOUND_METHOD] = _TAIL_CALL_CALL_KW_BOUND_METHOD,
|
||||
[CALL_KW_NON_PY] = _TAIL_CALL_CALL_KW_NON_PY,
|
||||
[CALL_KW_PY] = _TAIL_CALL_CALL_KW_PY,
|
||||
[CALL_LEN] = _TAIL_CALL_CALL_LEN,
|
||||
[CALL_LIST_APPEND] = _TAIL_CALL_CALL_LIST_APPEND,
|
||||
[CALL_METHOD_DESCRIPTOR_FAST] = _TAIL_CALL_CALL_METHOD_DESCRIPTOR_FAST,
|
||||
[CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = _TAIL_CALL_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS,
|
||||
[CALL_METHOD_DESCRIPTOR_NOARGS] = _TAIL_CALL_CALL_METHOD_DESCRIPTOR_NOARGS,
|
||||
[CALL_METHOD_DESCRIPTOR_O] = _TAIL_CALL_CALL_METHOD_DESCRIPTOR_O,
|
||||
[CALL_NON_PY_GENERAL] = _TAIL_CALL_CALL_NON_PY_GENERAL,
|
||||
[CALL_PY_EXACT_ARGS] = _TAIL_CALL_CALL_PY_EXACT_ARGS,
|
||||
[CALL_PY_GENERAL] = _TAIL_CALL_CALL_PY_GENERAL,
|
||||
[CALL_STR_1] = _TAIL_CALL_CALL_STR_1,
|
||||
[CALL_TUPLE_1] = _TAIL_CALL_CALL_TUPLE_1,
|
||||
[CALL_TYPE_1] = _TAIL_CALL_CALL_TYPE_1,
|
||||
[CHECK_EG_MATCH] = _TAIL_CALL_CHECK_EG_MATCH,
|
||||
[CHECK_EXC_MATCH] = _TAIL_CALL_CHECK_EXC_MATCH,
|
||||
[CLEANUP_THROW] = _TAIL_CALL_CLEANUP_THROW,
|
||||
[COMPARE_OP] = _TAIL_CALL_COMPARE_OP,
|
||||
[COMPARE_OP_FLOAT] = _TAIL_CALL_COMPARE_OP_FLOAT,
|
||||
[COMPARE_OP_INT] = _TAIL_CALL_COMPARE_OP_INT,
|
||||
[COMPARE_OP_STR] = _TAIL_CALL_COMPARE_OP_STR,
|
||||
[CONTAINS_OP] = _TAIL_CALL_CONTAINS_OP,
|
||||
[CONTAINS_OP_DICT] = _TAIL_CALL_CONTAINS_OP_DICT,
|
||||
[CONTAINS_OP_SET] = _TAIL_CALL_CONTAINS_OP_SET,
|
||||
[CONVERT_VALUE] = _TAIL_CALL_CONVERT_VALUE,
|
||||
[COPY] = _TAIL_CALL_COPY,
|
||||
[COPY_FREE_VARS] = _TAIL_CALL_COPY_FREE_VARS,
|
||||
[DELETE_ATTR] = _TAIL_CALL_DELETE_ATTR,
|
||||
[DELETE_DEREF] = _TAIL_CALL_DELETE_DEREF,
|
||||
[DELETE_FAST] = _TAIL_CALL_DELETE_FAST,
|
||||
[DELETE_GLOBAL] = _TAIL_CALL_DELETE_GLOBAL,
|
||||
[DELETE_NAME] = _TAIL_CALL_DELETE_NAME,
|
||||
[DELETE_SUBSCR] = _TAIL_CALL_DELETE_SUBSCR,
|
||||
[DICT_MERGE] = _TAIL_CALL_DICT_MERGE,
|
||||
[DICT_UPDATE] = _TAIL_CALL_DICT_UPDATE,
|
||||
[END_ASYNC_FOR] = _TAIL_CALL_END_ASYNC_FOR,
|
||||
[END_FOR] = _TAIL_CALL_END_FOR,
|
||||
[END_SEND] = _TAIL_CALL_END_SEND,
|
||||
[ENTER_EXECUTOR] = _TAIL_CALL_ENTER_EXECUTOR,
|
||||
[EXIT_INIT_CHECK] = _TAIL_CALL_EXIT_INIT_CHECK,
|
||||
[EXTENDED_ARG] = _TAIL_CALL_EXTENDED_ARG,
|
||||
[FORMAT_SIMPLE] = _TAIL_CALL_FORMAT_SIMPLE,
|
||||
[FORMAT_WITH_SPEC] = _TAIL_CALL_FORMAT_WITH_SPEC,
|
||||
[FOR_ITER] = _TAIL_CALL_FOR_ITER,
|
||||
[FOR_ITER_GEN] = _TAIL_CALL_FOR_ITER_GEN,
|
||||
[FOR_ITER_LIST] = _TAIL_CALL_FOR_ITER_LIST,
|
||||
[FOR_ITER_RANGE] = _TAIL_CALL_FOR_ITER_RANGE,
|
||||
[FOR_ITER_TUPLE] = _TAIL_CALL_FOR_ITER_TUPLE,
|
||||
[GET_AITER] = _TAIL_CALL_GET_AITER,
|
||||
[GET_ANEXT] = _TAIL_CALL_GET_ANEXT,
|
||||
[GET_AWAITABLE] = _TAIL_CALL_GET_AWAITABLE,
|
||||
[GET_ITER] = _TAIL_CALL_GET_ITER,
|
||||
[GET_LEN] = _TAIL_CALL_GET_LEN,
|
||||
[GET_YIELD_FROM_ITER] = _TAIL_CALL_GET_YIELD_FROM_ITER,
|
||||
[IMPORT_FROM] = _TAIL_CALL_IMPORT_FROM,
|
||||
[IMPORT_NAME] = _TAIL_CALL_IMPORT_NAME,
|
||||
[INSTRUMENTED_CALL] = _TAIL_CALL_INSTRUMENTED_CALL,
|
||||
[INSTRUMENTED_CALL_FUNCTION_EX] = _TAIL_CALL_INSTRUMENTED_CALL_FUNCTION_EX,
|
||||
[INSTRUMENTED_CALL_KW] = _TAIL_CALL_INSTRUMENTED_CALL_KW,
|
||||
[INSTRUMENTED_END_FOR] = _TAIL_CALL_INSTRUMENTED_END_FOR,
|
||||
[INSTRUMENTED_END_SEND] = _TAIL_CALL_INSTRUMENTED_END_SEND,
|
||||
[INSTRUMENTED_FOR_ITER] = _TAIL_CALL_INSTRUMENTED_FOR_ITER,
|
||||
[INSTRUMENTED_INSTRUCTION] = _TAIL_CALL_INSTRUMENTED_INSTRUCTION,
|
||||
[INSTRUMENTED_JUMP_BACKWARD] = _TAIL_CALL_INSTRUMENTED_JUMP_BACKWARD,
|
||||
[INSTRUMENTED_JUMP_FORWARD] = _TAIL_CALL_INSTRUMENTED_JUMP_FORWARD,
|
||||
[INSTRUMENTED_LINE] = _TAIL_CALL_INSTRUMENTED_LINE,
|
||||
[INSTRUMENTED_LOAD_SUPER_ATTR] = _TAIL_CALL_INSTRUMENTED_LOAD_SUPER_ATTR,
|
||||
[INSTRUMENTED_NOT_TAKEN] = _TAIL_CALL_INSTRUMENTED_NOT_TAKEN,
|
||||
[INSTRUMENTED_POP_ITER] = _TAIL_CALL_INSTRUMENTED_POP_ITER,
|
||||
[INSTRUMENTED_POP_JUMP_IF_FALSE] = _TAIL_CALL_INSTRUMENTED_POP_JUMP_IF_FALSE,
|
||||
[INSTRUMENTED_POP_JUMP_IF_NONE] = _TAIL_CALL_INSTRUMENTED_POP_JUMP_IF_NONE,
|
||||
[INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = _TAIL_CALL_INSTRUMENTED_POP_JUMP_IF_NOT_NONE,
|
||||
[INSTRUMENTED_POP_JUMP_IF_TRUE] = _TAIL_CALL_INSTRUMENTED_POP_JUMP_IF_TRUE,
|
||||
[INSTRUMENTED_RESUME] = _TAIL_CALL_INSTRUMENTED_RESUME,
|
||||
[INSTRUMENTED_RETURN_VALUE] = _TAIL_CALL_INSTRUMENTED_RETURN_VALUE,
|
||||
[INSTRUMENTED_YIELD_VALUE] = _TAIL_CALL_INSTRUMENTED_YIELD_VALUE,
|
||||
[INTERPRETER_EXIT] = _TAIL_CALL_INTERPRETER_EXIT,
|
||||
[IS_OP] = _TAIL_CALL_IS_OP,
|
||||
[JUMP_BACKWARD] = _TAIL_CALL_JUMP_BACKWARD,
|
||||
[JUMP_BACKWARD_JIT] = _TAIL_CALL_JUMP_BACKWARD_JIT,
|
||||
[JUMP_BACKWARD_NO_INTERRUPT] = _TAIL_CALL_JUMP_BACKWARD_NO_INTERRUPT,
|
||||
[JUMP_BACKWARD_NO_JIT] = _TAIL_CALL_JUMP_BACKWARD_NO_JIT,
|
||||
[JUMP_FORWARD] = _TAIL_CALL_JUMP_FORWARD,
|
||||
[LIST_APPEND] = _TAIL_CALL_LIST_APPEND,
|
||||
[LIST_EXTEND] = _TAIL_CALL_LIST_EXTEND,
|
||||
[LOAD_ATTR] = _TAIL_CALL_LOAD_ATTR,
|
||||
[LOAD_ATTR_CLASS] = _TAIL_CALL_LOAD_ATTR_CLASS,
|
||||
[LOAD_ATTR_CLASS_WITH_METACLASS_CHECK] = _TAIL_CALL_LOAD_ATTR_CLASS_WITH_METACLASS_CHECK,
|
||||
[LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = _TAIL_CALL_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN,
|
||||
[LOAD_ATTR_INSTANCE_VALUE] = _TAIL_CALL_LOAD_ATTR_INSTANCE_VALUE,
|
||||
[LOAD_ATTR_METHOD_LAZY_DICT] = _TAIL_CALL_LOAD_ATTR_METHOD_LAZY_DICT,
|
||||
[LOAD_ATTR_METHOD_NO_DICT] = _TAIL_CALL_LOAD_ATTR_METHOD_NO_DICT,
|
||||
[LOAD_ATTR_METHOD_WITH_VALUES] = _TAIL_CALL_LOAD_ATTR_METHOD_WITH_VALUES,
|
||||
[LOAD_ATTR_MODULE] = _TAIL_CALL_LOAD_ATTR_MODULE,
|
||||
[LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = _TAIL_CALL_LOAD_ATTR_NONDESCRIPTOR_NO_DICT,
|
||||
[LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = _TAIL_CALL_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES,
|
||||
[LOAD_ATTR_PROPERTY] = _TAIL_CALL_LOAD_ATTR_PROPERTY,
|
||||
[LOAD_ATTR_SLOT] = _TAIL_CALL_LOAD_ATTR_SLOT,
|
||||
[LOAD_ATTR_WITH_HINT] = _TAIL_CALL_LOAD_ATTR_WITH_HINT,
|
||||
[LOAD_BUILD_CLASS] = _TAIL_CALL_LOAD_BUILD_CLASS,
|
||||
[LOAD_COMMON_CONSTANT] = _TAIL_CALL_LOAD_COMMON_CONSTANT,
|
||||
[LOAD_CONST] = _TAIL_CALL_LOAD_CONST,
|
||||
[LOAD_CONST_IMMORTAL] = _TAIL_CALL_LOAD_CONST_IMMORTAL,
|
||||
[LOAD_CONST_MORTAL] = _TAIL_CALL_LOAD_CONST_MORTAL,
|
||||
[LOAD_DEREF] = _TAIL_CALL_LOAD_DEREF,
|
||||
[LOAD_FAST] = _TAIL_CALL_LOAD_FAST,
|
||||
[LOAD_FAST_AND_CLEAR] = _TAIL_CALL_LOAD_FAST_AND_CLEAR,
|
||||
[LOAD_FAST_CHECK] = _TAIL_CALL_LOAD_FAST_CHECK,
|
||||
[LOAD_FAST_LOAD_FAST] = _TAIL_CALL_LOAD_FAST_LOAD_FAST,
|
||||
[LOAD_FROM_DICT_OR_DEREF] = _TAIL_CALL_LOAD_FROM_DICT_OR_DEREF,
|
||||
[LOAD_FROM_DICT_OR_GLOBALS] = _TAIL_CALL_LOAD_FROM_DICT_OR_GLOBALS,
|
||||
[LOAD_GLOBAL] = _TAIL_CALL_LOAD_GLOBAL,
|
||||
[LOAD_GLOBAL_BUILTIN] = _TAIL_CALL_LOAD_GLOBAL_BUILTIN,
|
||||
[LOAD_GLOBAL_MODULE] = _TAIL_CALL_LOAD_GLOBAL_MODULE,
|
||||
[LOAD_LOCALS] = _TAIL_CALL_LOAD_LOCALS,
|
||||
[LOAD_NAME] = _TAIL_CALL_LOAD_NAME,
|
||||
[LOAD_SMALL_INT] = _TAIL_CALL_LOAD_SMALL_INT,
|
||||
[LOAD_SPECIAL] = _TAIL_CALL_LOAD_SPECIAL,
|
||||
[LOAD_SUPER_ATTR] = _TAIL_CALL_LOAD_SUPER_ATTR,
|
||||
[LOAD_SUPER_ATTR_ATTR] = _TAIL_CALL_LOAD_SUPER_ATTR_ATTR,
|
||||
[LOAD_SUPER_ATTR_METHOD] = _TAIL_CALL_LOAD_SUPER_ATTR_METHOD,
|
||||
[MAKE_CELL] = _TAIL_CALL_MAKE_CELL,
|
||||
[MAKE_FUNCTION] = _TAIL_CALL_MAKE_FUNCTION,
|
||||
[MAP_ADD] = _TAIL_CALL_MAP_ADD,
|
||||
[MATCH_CLASS] = _TAIL_CALL_MATCH_CLASS,
|
||||
[MATCH_KEYS] = _TAIL_CALL_MATCH_KEYS,
|
||||
[MATCH_MAPPING] = _TAIL_CALL_MATCH_MAPPING,
|
||||
[MATCH_SEQUENCE] = _TAIL_CALL_MATCH_SEQUENCE,
|
||||
[NOP] = _TAIL_CALL_NOP,
|
||||
[NOT_TAKEN] = _TAIL_CALL_NOT_TAKEN,
|
||||
[POP_EXCEPT] = _TAIL_CALL_POP_EXCEPT,
|
||||
[POP_ITER] = _TAIL_CALL_POP_ITER,
|
||||
[POP_JUMP_IF_FALSE] = _TAIL_CALL_POP_JUMP_IF_FALSE,
|
||||
[POP_JUMP_IF_NONE] = _TAIL_CALL_POP_JUMP_IF_NONE,
|
||||
[POP_JUMP_IF_NOT_NONE] = _TAIL_CALL_POP_JUMP_IF_NOT_NONE,
|
||||
[POP_JUMP_IF_TRUE] = _TAIL_CALL_POP_JUMP_IF_TRUE,
|
||||
[POP_TOP] = _TAIL_CALL_POP_TOP,
|
||||
[PUSH_EXC_INFO] = _TAIL_CALL_PUSH_EXC_INFO,
|
||||
[PUSH_NULL] = _TAIL_CALL_PUSH_NULL,
|
||||
[RAISE_VARARGS] = _TAIL_CALL_RAISE_VARARGS,
|
||||
[RERAISE] = _TAIL_CALL_RERAISE,
|
||||
[RESERVED] = _TAIL_CALL_RESERVED,
|
||||
[RESUME] = _TAIL_CALL_RESUME,
|
||||
[RESUME_CHECK] = _TAIL_CALL_RESUME_CHECK,
|
||||
[RETURN_GENERATOR] = _TAIL_CALL_RETURN_GENERATOR,
|
||||
[RETURN_VALUE] = _TAIL_CALL_RETURN_VALUE,
|
||||
[SEND] = _TAIL_CALL_SEND,
|
||||
[SEND_GEN] = _TAIL_CALL_SEND_GEN,
|
||||
[SETUP_ANNOTATIONS] = _TAIL_CALL_SETUP_ANNOTATIONS,
|
||||
[SET_ADD] = _TAIL_CALL_SET_ADD,
|
||||
[SET_FUNCTION_ATTRIBUTE] = _TAIL_CALL_SET_FUNCTION_ATTRIBUTE,
|
||||
[SET_UPDATE] = _TAIL_CALL_SET_UPDATE,
|
||||
[STORE_ATTR] = _TAIL_CALL_STORE_ATTR,
|
||||
[STORE_ATTR_INSTANCE_VALUE] = _TAIL_CALL_STORE_ATTR_INSTANCE_VALUE,
|
||||
[STORE_ATTR_SLOT] = _TAIL_CALL_STORE_ATTR_SLOT,
|
||||
[STORE_ATTR_WITH_HINT] = _TAIL_CALL_STORE_ATTR_WITH_HINT,
|
||||
[STORE_DEREF] = _TAIL_CALL_STORE_DEREF,
|
||||
[STORE_FAST] = _TAIL_CALL_STORE_FAST,
|
||||
[STORE_FAST_LOAD_FAST] = _TAIL_CALL_STORE_FAST_LOAD_FAST,
|
||||
[STORE_FAST_STORE_FAST] = _TAIL_CALL_STORE_FAST_STORE_FAST,
|
||||
[STORE_GLOBAL] = _TAIL_CALL_STORE_GLOBAL,
|
||||
[STORE_NAME] = _TAIL_CALL_STORE_NAME,
|
||||
[STORE_SLICE] = _TAIL_CALL_STORE_SLICE,
|
||||
[STORE_SUBSCR] = _TAIL_CALL_STORE_SUBSCR,
|
||||
[STORE_SUBSCR_DICT] = _TAIL_CALL_STORE_SUBSCR_DICT,
|
||||
[STORE_SUBSCR_LIST_INT] = _TAIL_CALL_STORE_SUBSCR_LIST_INT,
|
||||
[SWAP] = _TAIL_CALL_SWAP,
|
||||
[TO_BOOL] = _TAIL_CALL_TO_BOOL,
|
||||
[TO_BOOL_ALWAYS_TRUE] = _TAIL_CALL_TO_BOOL_ALWAYS_TRUE,
|
||||
[TO_BOOL_BOOL] = _TAIL_CALL_TO_BOOL_BOOL,
|
||||
[TO_BOOL_INT] = _TAIL_CALL_TO_BOOL_INT,
|
||||
[TO_BOOL_LIST] = _TAIL_CALL_TO_BOOL_LIST,
|
||||
[TO_BOOL_NONE] = _TAIL_CALL_TO_BOOL_NONE,
|
||||
[TO_BOOL_STR] = _TAIL_CALL_TO_BOOL_STR,
|
||||
[UNARY_INVERT] = _TAIL_CALL_UNARY_INVERT,
|
||||
[UNARY_NEGATIVE] = _TAIL_CALL_UNARY_NEGATIVE,
|
||||
[UNARY_NOT] = _TAIL_CALL_UNARY_NOT,
|
||||
[UNPACK_EX] = _TAIL_CALL_UNPACK_EX,
|
||||
[UNPACK_SEQUENCE] = _TAIL_CALL_UNPACK_SEQUENCE,
|
||||
[UNPACK_SEQUENCE_LIST] = _TAIL_CALL_UNPACK_SEQUENCE_LIST,
|
||||
[UNPACK_SEQUENCE_TUPLE] = _TAIL_CALL_UNPACK_SEQUENCE_TUPLE,
|
||||
[UNPACK_SEQUENCE_TWO_TUPLE] = _TAIL_CALL_UNPACK_SEQUENCE_TWO_TUPLE,
|
||||
[WITH_EXCEPT_START] = _TAIL_CALL_WITH_EXCEPT_START,
|
||||
[YIELD_VALUE] = _TAIL_CALL_YIELD_VALUE,
|
||||
[118] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[119] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[120] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[121] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[122] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[123] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[124] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[125] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[126] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[127] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[128] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[129] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[130] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[131] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[132] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[133] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[134] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[135] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[136] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[137] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[138] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[139] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[140] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[141] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[142] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[143] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[144] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[145] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[146] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[147] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[148] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[232] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[233] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[234] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
};
|
||||
#endif /* Py_TAIL_CALL_INTERP */
|
||||
|
|
|
@ -675,6 +675,7 @@ NON_ESCAPING_FUNCTIONS = (
|
|||
"assert",
|
||||
"backoff_counter_triggers",
|
||||
"initial_temperature_backoff_counter",
|
||||
"JUMP_TO_LABEL",
|
||||
"maybe_lltrace_resume_frame",
|
||||
"restart_backoff_counter",
|
||||
)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
from pathlib import Path
|
||||
from typing import TextIO
|
||||
|
||||
from analyzer import (
|
||||
Instruction,
|
||||
|
@ -154,28 +153,31 @@ class Emitter:
|
|||
storage: Storage,
|
||||
inst: Instruction | None,
|
||||
) -> bool:
|
||||
self.out.emit_at("DEOPT_IF", tkn)
|
||||
self.out.start_line()
|
||||
self.out.emit("if (")
|
||||
lparen = next(tkn_iter)
|
||||
self.emit(lparen)
|
||||
assert lparen.kind == "LPAREN"
|
||||
first_tkn = tkn_iter.peek()
|
||||
emit_to(self.out, tkn_iter, "RPAREN")
|
||||
self.emit(") {\n")
|
||||
next(tkn_iter) # Semi colon
|
||||
self.out.emit(", ")
|
||||
assert inst is not None
|
||||
assert inst.family is not None
|
||||
self.out.emit(inst.family.name)
|
||||
self.out.emit(");\n")
|
||||
family_name = inst.family.name
|
||||
self.emit(f"UPDATE_MISS_STATS({family_name});\n")
|
||||
self.emit(f"assert(_PyOpcode_Deopt[opcode] == ({family_name}));\n")
|
||||
self.emit(f"JUMP_TO_PREDICTED({family_name});\n")
|
||||
self.emit("}\n")
|
||||
return not always_true(first_tkn)
|
||||
|
||||
exit_if = deopt_if
|
||||
|
||||
def goto_error(self, offset: int, label: str, storage: Storage) -> str:
|
||||
if offset > 0:
|
||||
return f"goto pop_{offset}_{label};"
|
||||
return f"JUMP_TO_LABEL(pop_{offset}_{label});"
|
||||
if offset < 0:
|
||||
storage.copy().flush(self.out)
|
||||
return f"goto {label};"
|
||||
return f"JUMP_TO_LABEL({label});"
|
||||
|
||||
def error_if(
|
||||
self,
|
||||
|
@ -410,8 +412,10 @@ class Emitter:
|
|||
self.emit_save(storage)
|
||||
elif storage.spilled:
|
||||
raise analysis_error("Cannot jump from spilled label without reloading the stack pointer", goto)
|
||||
self.out.emit(goto)
|
||||
self.out.start_line()
|
||||
self.out.emit("JUMP_TO_LABEL(")
|
||||
self.out.emit(label)
|
||||
self.out.emit(")")
|
||||
|
||||
def emit_save(self, storage: Storage) -> None:
|
||||
storage.save(self.out)
|
||||
|
@ -603,7 +607,7 @@ class Emitter:
|
|||
elif tkn.kind == "GOTO":
|
||||
label_tkn = next(tkn_iter)
|
||||
self.goto_label(tkn, label_tkn, storage)
|
||||
reachable = False;
|
||||
reachable = False
|
||||
elif tkn.kind == "IDENTIFIER":
|
||||
if tkn.text in self._replacers:
|
||||
if not self._replacers[tkn.text](tkn, tkn_iter, uop, storage, inst):
|
||||
|
|
|
@ -13,6 +13,7 @@ from generators_common import (
|
|||
DEFAULT_INPUT,
|
||||
ROOT,
|
||||
)
|
||||
from tier1_generator import UNKNOWN_OPCODE_HANDLER
|
||||
from cwriter import CWriter
|
||||
|
||||
|
||||
|
@ -25,11 +26,49 @@ def write_opcode_targets(analysis: Analysis, out: CWriter) -> None:
|
|||
for name, op in analysis.opmap.items():
|
||||
if op < 256:
|
||||
targets[op] = f"&&TARGET_{name},\n"
|
||||
out.emit("#ifndef Py_TAIL_CALL_INTERP\n")
|
||||
out.emit("static void *opcode_targets[256] = {\n")
|
||||
for target in targets:
|
||||
out.emit(target)
|
||||
out.emit("};\n")
|
||||
out.emit("#else /* Py_TAIL_CALL_INTERP */\n")
|
||||
|
||||
def function_proto(name: str) -> str:
|
||||
return f"Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_{name}(TAIL_CALL_PARAMS)"
|
||||
|
||||
|
||||
def write_tailcall_dispatch_table(analysis: Analysis, out: CWriter) -> None:
|
||||
out.emit("static py_tail_call_funcptr INSTRUCTION_TABLE[256];\n")
|
||||
out.emit("\n")
|
||||
|
||||
# Emit function prototypes for labels.
|
||||
for name in analysis.labels:
|
||||
out.emit(f"{function_proto(name)};\n")
|
||||
out.emit("\n")
|
||||
|
||||
# Emit function prototypes for opcode handlers.
|
||||
for name in sorted(analysis.instructions.keys()):
|
||||
out.emit(f"{function_proto(name)};\n")
|
||||
out.emit("\n")
|
||||
|
||||
# Emit unknown opcode handler.
|
||||
out.emit(function_proto("UNKNOWN_OPCODE"))
|
||||
out.emit(" {\n")
|
||||
out.emit("int opcode = next_instr->op.code;\n")
|
||||
out.emit(UNKNOWN_OPCODE_HANDLER)
|
||||
out.emit("}\n")
|
||||
out.emit("\n")
|
||||
|
||||
# Emit the dispatch table.
|
||||
out.emit("static py_tail_call_funcptr INSTRUCTION_TABLE[256] = {\n")
|
||||
for name in sorted(analysis.instructions.keys()):
|
||||
out.emit(f"[{name}] = _TAIL_CALL_{name},\n")
|
||||
named_values = analysis.opmap.values()
|
||||
for rest in range(256):
|
||||
if rest not in named_values:
|
||||
out.emit(f"[{rest}] = _TAIL_CALL_UNKNOWN_OPCODE,\n")
|
||||
out.emit("};\n")
|
||||
outfile.write("#endif /* Py_TAIL_CALL_INTERP */\n")
|
||||
|
||||
arg_parser = argparse.ArgumentParser(
|
||||
description="Generate the file with dispatch targets.",
|
||||
|
@ -52,3 +91,4 @@ if __name__ == "__main__":
|
|||
with open(args.output, "w") as outfile:
|
||||
out = CWriter(outfile, 0, False)
|
||||
write_opcode_targets(data, out)
|
||||
write_tailcall_dispatch_table(data, out)
|
||||
|
|
|
@ -24,10 +24,9 @@ from generators_common import (
|
|||
Emitter,
|
||||
)
|
||||
from cwriter import CWriter
|
||||
from typing import TextIO
|
||||
from typing import TextIO, Callable
|
||||
from stack import Local, Stack, StackError, get_stack_effect, Storage
|
||||
|
||||
|
||||
DEFAULT_OUTPUT = ROOT / "Python/generated_cases.c.h"
|
||||
|
||||
|
||||
|
@ -129,31 +128,52 @@ def uses_this(inst: Instruction) -> bool:
|
|||
for cache in uop.caches:
|
||||
if cache.name != "unused":
|
||||
return True
|
||||
# Can't be merged into the loop above, because
|
||||
# this must strictly be performed at the end.
|
||||
for uop in inst.parts:
|
||||
if not isinstance(uop, Uop):
|
||||
continue
|
||||
for tkn in uop.body:
|
||||
if (tkn.kind == "IDENTIFIER"
|
||||
and (tkn.text in {"DEOPT_IF", "EXIT_IF"})):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
UNKNOWN_OPCODE_HANDLER ="""\
|
||||
_PyErr_Format(tstate, PyExc_SystemError,
|
||||
"%U:%d: unknown opcode %d",
|
||||
_PyFrame_GetCode(frame)->co_filename,
|
||||
PyUnstable_InterpreterFrame_GetLine(frame),
|
||||
opcode);
|
||||
JUMP_TO_LABEL(error);
|
||||
"""
|
||||
|
||||
def generate_tier1(
|
||||
filenames: list[str], analysis: Analysis, outfile: TextIO, lines: bool
|
||||
) -> None:
|
||||
write_header(__file__, filenames, outfile)
|
||||
outfile.write(
|
||||
f"""
|
||||
outfile.write("""
|
||||
#ifdef TIER_TWO
|
||||
#error "This file is for Tier 1 only"
|
||||
#endif
|
||||
#define TIER_ONE 1
|
||||
|
||||
""")
|
||||
outfile.write(f"""
|
||||
#ifndef Py_TAIL_CALL_INTERP
|
||||
#if !USE_COMPUTED_GOTOS
|
||||
dispatch_opcode:
|
||||
switch (opcode)
|
||||
#endif
|
||||
{{
|
||||
#endif /* Py_TAIL_CALL_INTERP */
|
||||
{INSTRUCTION_START_MARKER}
|
||||
"""
|
||||
)
|
||||
generate_tier1_cases(analysis, outfile, lines)
|
||||
outfile.write(f"""
|
||||
{INSTRUCTION_END_MARKER}
|
||||
#ifndef Py_TAIL_CALL_INTERP
|
||||
#if USE_COMPUTED_GOTOS
|
||||
_unknown_opcode:
|
||||
#else
|
||||
|
@ -162,41 +182,41 @@ def generate_tier1(
|
|||
/* 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;
|
||||
{UNKNOWN_OPCODE_HANDLER}
|
||||
|
||||
}}
|
||||
|
||||
/* This should never be reached. Every opcode should end with DISPATCH()
|
||||
or goto error. */
|
||||
Py_UNREACHABLE();
|
||||
#endif /* Py_TAIL_CALL_INTERP */
|
||||
{LABEL_START_MARKER}
|
||||
""")
|
||||
generate_tier1_labels(analysis, outfile, lines)
|
||||
out = CWriter(outfile, 2, lines)
|
||||
emitter = Emitter(out, analysis.labels)
|
||||
generate_tier1_labels(analysis, emitter)
|
||||
outfile.write(f"{LABEL_END_MARKER}\n")
|
||||
outfile.write(FOOTER)
|
||||
|
||||
|
||||
|
||||
def generate_tier1_labels(
|
||||
analysis: Analysis, outfile: TextIO, lines: bool
|
||||
analysis: Analysis, emitter: Emitter
|
||||
) -> None:
|
||||
out = CWriter(outfile, 2, lines)
|
||||
emitter = Emitter(out, analysis.labels)
|
||||
out.emit("\n")
|
||||
emitter.emit("\n")
|
||||
# Emit tail-callable labels as function defintions
|
||||
for name, label in analysis.labels.items():
|
||||
out.emit(f"{name}:\n")
|
||||
out.emit("{\n")
|
||||
emitter.emit(f"LABEL({name})\n")
|
||||
emitter.emit("{\n")
|
||||
storage = Storage(Stack(), [], [], [])
|
||||
if label.spilled:
|
||||
storage.spilled = 1
|
||||
out.emit("/* STACK SPILLED */\n")
|
||||
emitter.emit("/* STACK SPILLED */\n")
|
||||
emitter.emit_tokens(label, storage, None)
|
||||
out.emit("\n")
|
||||
out.emit("}\n")
|
||||
out.emit("\n")
|
||||
emitter.emit("\n")
|
||||
emitter.emit("}\n")
|
||||
emitter.emit("\n")
|
||||
|
||||
|
||||
def generate_tier1_cases(
|
||||
analysis: Analysis, outfile: TextIO, lines: bool
|
||||
|
@ -205,20 +225,26 @@ def generate_tier1_cases(
|
|||
emitter = Emitter(out, analysis.labels)
|
||||
out.emit("\n")
|
||||
for name, inst in sorted(analysis.instructions.items()):
|
||||
needs_this = uses_this(inst)
|
||||
out.emit("\n")
|
||||
out.emit(f"TARGET({name}) {{\n")
|
||||
# We need to ifdef it because this breaks platforms
|
||||
# without computed gotos/tail calling.
|
||||
out.emit(f"#if defined(Py_TAIL_CALL_INTERP)\n")
|
||||
out.emit(f"int opcode;\n")
|
||||
out.emit(f"#endif\n")
|
||||
out.emit(f"opcode = {name};\n")
|
||||
out.emit(f"(void)(opcode);\n")
|
||||
needs_this = uses_this(inst)
|
||||
unused_guard = "(void)this_instr;\n"
|
||||
if inst.properties.needs_prev:
|
||||
out.emit(f"_Py_CODEUNIT* const prev_instr = frame->instr_ptr;\n")
|
||||
|
||||
if needs_this and not inst.is_target:
|
||||
if inst.properties.no_save_ip:
|
||||
out.emit(f"_Py_CODEUNIT* const this_instr = next_instr;\n")
|
||||
else:
|
||||
out.emit(f"_Py_CODEUNIT* const this_instr = frame->instr_ptr = next_instr;\n")
|
||||
out.emit(f"_Py_CODEUNIT* const this_instr = next_instr;\n")
|
||||
out.emit(unused_guard)
|
||||
elif not inst.properties.no_save_ip:
|
||||
if not inst.properties.no_save_ip:
|
||||
out.emit(f"frame->instr_ptr = next_instr;\n")
|
||||
|
||||
out.emit(f"next_instr += {inst.size};\n")
|
||||
out.emit(f"INSTRUCTION_STATS({name});\n")
|
||||
if inst.is_target:
|
||||
|
@ -226,8 +252,6 @@ def generate_tier1_cases(
|
|||
if needs_this:
|
||||
out.emit(f"_Py_CODEUNIT* const this_instr = next_instr - {inst.size};\n")
|
||||
out.emit(unused_guard)
|
||||
if inst.properties.uses_opcode:
|
||||
out.emit(f"opcode = {name};\n")
|
||||
if inst.family is not None:
|
||||
out.emit(
|
||||
f"static_assert({inst.family.size} == {inst.size-1}"
|
||||
|
|
|
@ -32,14 +32,6 @@
|
|||
#undef CURRENT_OPERAND1
|
||||
#define CURRENT_OPERAND1() (_operand1)
|
||||
|
||||
#undef DEOPT_IF
|
||||
#define DEOPT_IF(COND, INSTNAME) \
|
||||
do { \
|
||||
if ((COND)) { \
|
||||
goto deoptimize; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#undef ENABLE_SPECIALIZATION
|
||||
#define ENABLE_SPECIALIZATION (0)
|
||||
|
||||
|
|
48
configure
generated
vendored
48
configure
generated
vendored
|
@ -1122,6 +1122,7 @@ with_platlibdir
|
|||
with_wheel_pkg_dir
|
||||
with_readline
|
||||
with_computed_gotos
|
||||
with_tail_call_interp
|
||||
with_ensurepip
|
||||
with_openssl
|
||||
with_openssl_rpath
|
||||
|
@ -1929,6 +1930,8 @@ Optional Packages:
|
|||
use libedit for backend or disable readline module
|
||||
--with-computed-gotos enable computed gotos in evaluation loop (enabled by
|
||||
default on supported compilers)
|
||||
--tail-call-interp enable tail-calling interpreter in evaluation loop
|
||||
and rest of CPython
|
||||
--with-ensurepip[=install|upgrade|no]
|
||||
"install" or "upgrade" using bundled pip (default is
|
||||
upgrade)
|
||||
|
@ -29246,6 +29249,51 @@ printf "%s\n" "#define HAVE_COMPUTED_GOTOS 1" >>confdefs.h
|
|||
|
||||
esac
|
||||
|
||||
# Check for --with-tail-call-interp
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for --with-tail-call-interp" >&5
|
||||
printf %s "checking for --with-tail-call-interp... " >&6; }
|
||||
|
||||
# Check whether --with-tail-call-interp was given.
|
||||
if test ${with_tail_call_interp+y}
|
||||
then :
|
||||
withval=$with_tail_call_interp;
|
||||
if test "$withval" = yes
|
||||
then
|
||||
|
||||
printf "%s\n" "#define Py_TAIL_CALL_INTERP 1" >>confdefs.h
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
printf "%s\n" "yes" >&6; }
|
||||
fi
|
||||
if test "$withval" = no
|
||||
then
|
||||
|
||||
printf "%s\n" "#define Py_TAIL_CALL_INTERP 0" >>confdefs.h
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
printf "%s\n" "no" >&6; }
|
||||
fi
|
||||
|
||||
else case e in #(
|
||||
e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no value specified" >&5
|
||||
printf "%s\n" "no value specified" >&6; } ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
|
||||
# Do not enable tail-calling interpreter if tier 2 is enabled.
|
||||
if ${tier2_flags:+false} :
|
||||
then :
|
||||
|
||||
case "$ac_cv_tail_call" in yes*)
|
||||
|
||||
printf "%s\n" "#define Py_TAIL_CALL_INTERP 1" >>confdefs.h
|
||||
|
||||
esac
|
||||
|
||||
fi
|
||||
|
||||
|
||||
case $ac_sys_system in
|
||||
AIX*)
|
||||
|
||||
|
|
38
configure.ac
38
configure.ac
|
@ -7017,6 +7017,44 @@ case "$ac_cv_computed_gotos" in yes*)
|
|||
[Define if the C compiler supports computed gotos.])
|
||||
esac
|
||||
|
||||
# Check for --with-tail-call-interp
|
||||
AC_MSG_CHECKING([for --with-tail-call-interp])
|
||||
AC_ARG_WITH(
|
||||
[tail-call-interp],
|
||||
[AS_HELP_STRING(
|
||||
[--tail-call-interp],
|
||||
[enable tail-calling interpreter in evaluation loop and rest of CPython]
|
||||
)],
|
||||
[
|
||||
if test "$withval" = yes
|
||||
then
|
||||
AC_DEFINE([Py_TAIL_CALL_INTERP], [1],
|
||||
[Define if you want to use tail-calling interpreters in CPython.])
|
||||
AC_MSG_RESULT([yes])
|
||||
fi
|
||||
if test "$withval" = no
|
||||
then
|
||||
AC_DEFINE([Py_TAIL_CALL_INTERP], [0],
|
||||
[Define if you want to use tail-calling interpreters in CPython.])
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
],
|
||||
[AC_MSG_RESULT([no value specified])])
|
||||
|
||||
# Do not enable tail-calling interpreter if tier 2 is enabled.
|
||||
AS_VAR_IF(
|
||||
[tier2_flags],
|
||||
[],
|
||||
[
|
||||
case "$ac_cv_tail_call" in yes*)
|
||||
AC_DEFINE([Py_TAIL_CALL_INTERP], [1],
|
||||
[Define if the C compiler supports efficient proper tail calls.])
|
||||
esac
|
||||
],
|
||||
[]
|
||||
)
|
||||
|
||||
|
||||
case $ac_sys_system in
|
||||
AIX*)
|
||||
AC_DEFINE([HAVE_BROKEN_PIPE_BUF], [1],
|
||||
|
|
|
@ -1718,6 +1718,9 @@
|
|||
/* The version of SunOS/Solaris as reported by `uname -r' without the dot. */
|
||||
#undef Py_SUNOS_VERSION
|
||||
|
||||
/* Define if the C compiler supports efficient proper tail calls. */
|
||||
#undef Py_TAIL_CALL_INTERP
|
||||
|
||||
/* Define if you want to enable tracing references for debugging purpose */
|
||||
#undef Py_TRACE_REFS
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue