Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9633c52

Browse files
authored
GH-126910: Build/link the JIT shim in the Python interpreter (#148872)
1 parent 29917d5 commit 9633c52

16 files changed

Lines changed: 202 additions & 209 deletions

File tree

Include/internal/pycore_ceval.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -121,18 +121,11 @@ _PyEval_EvalFrame(PyThreadState *tstate, _PyInterpreterFrame *frame, int throwfl
121121
}
122122

123123
#ifdef _Py_TIER2
124-
#ifdef _Py_JIT
125-
_Py_CODEUNIT *_Py_LazyJitShim(
126-
struct _PyExecutorObject *current_executor, _PyInterpreterFrame *frame,
127-
_PyStackRef *stack_pointer, PyThreadState *tstate
128-
);
129-
#else
130124
_Py_CODEUNIT *_PyTier2Interpreter(
131125
struct _PyExecutorObject *current_executor, _PyInterpreterFrame *frame,
132126
_PyStackRef *stack_pointer, PyThreadState *tstate
133127
);
134128
#endif
135-
#endif
136129

137130
extern _PyJitEntryFuncPtr _Py_jit_entry;
138131

Include/internal/pycore_jit.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,13 @@ typedef _Py_CODEUNIT *(*jit_func)(
2323
_PyStackRef _tos_cache0, _PyStackRef _tos_cache1, _PyStackRef _tos_cache2
2424
);
2525

26+
_Py_CODEUNIT *_PyJIT(
27+
_PyExecutorObject *executor, _PyInterpreterFrame *frame,
28+
_PyStackRef *stack_pointer, PyThreadState *tstate
29+
);
30+
2631
int _PyJIT_Compile(_PyExecutorObject *executor, const _PyUOpInstruction *trace, size_t length);
2732
void _PyJIT_Free(_PyExecutorObject *executor);
28-
void _PyJIT_Fini(void);
2933
PyAPI_FUNC(int) _PyJIT_AddressInJitCode(PyInterpreterState *interp, uintptr_t addr);
3034

3135
#endif // _Py_JIT

Makefile.pre.in

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ LDLIBRARYDIR= @LDLIBRARYDIR@
290290
INSTSONAME= @INSTSONAME@
291291
LIBRARY_DEPS= @LIBRARY_DEPS@
292292
LINK_PYTHON_DEPS=@LINK_PYTHON_DEPS@
293+
JIT_OBJS= @JIT_SHIM_O@
293294
PY_ENABLE_SHARED= @PY_ENABLE_SHARED@
294295
STATIC_LIBPYTHON= @STATIC_LIBPYTHON@
295296

@@ -469,6 +470,7 @@ PYTHON_OBJS= \
469470
Python/instruction_sequence.o \
470471
Python/intrinsics.o \
471472
Python/jit.o \
473+
$(JIT_OBJS) \
472474
Python/legacy_tracing.o \
473475
Python/lock.o \
474476
Python/marshal.o \
@@ -3204,21 +3206,37 @@ Python/emscripten_trampoline_inner.wasm: $(srcdir)/Python/emscripten_trampoline_
32043206
Python/emscripten_trampoline_wasm.c: Python/emscripten_trampoline_inner.wasm
32053207
$(PYTHON_FOR_REGEN) $(srcdir)/Platforms/emscripten/prepare_external_wasm.py $< $@ getWasmTrampolineModule
32063208

3209+
JIT_SHIM_BUILD_OBJS= @JIT_SHIM_BUILD_O@
3210+
JIT_BUILD_TARGETS= jit_stencils.h @JIT_STENCILS_H@ $(JIT_SHIM_BUILD_OBJS)
3211+
JIT_TARGETS= $(JIT_BUILD_TARGETS) $(filter-out $(JIT_SHIM_BUILD_OBJS),$(JIT_OBJS))
3212+
JIT_GENERATED_STAMP= .jit-stamp
3213+
32073214
JIT_DEPS = \
32083215
$(srcdir)/Tools/jit/*.c \
3216+
$(srcdir)/Tools/jit/*.h \
32093217
$(srcdir)/Tools/jit/*.py \
32103218
$(srcdir)/Python/executor_cases.c.h \
32113219
pyconfig.h
32123220

3213-
jit_stencils.h @JIT_STENCILS_H@: $(JIT_DEPS)
3221+
$(JIT_GENERATED_STAMP): $(JIT_DEPS)
32143222
@REGEN_JIT_COMMAND@
3223+
@touch $@
3224+
3225+
$(JIT_BUILD_TARGETS): $(JIT_GENERATED_STAMP)
3226+
@if test ! -f "$@"; then \
3227+
rm -f $(JIT_GENERATED_STAMP); \
3228+
$(MAKE) $(JIT_GENERATED_STAMP); \
3229+
test -f "$@"; \
3230+
fi
3231+
3232+
jit_shim-universal2-apple-darwin.o: jit_shim-aarch64-apple-darwin.o jit_shim-x86_64-apple-darwin.o
3233+
lipo -create -output $@ jit_shim-aarch64-apple-darwin.o jit_shim-x86_64-apple-darwin.o
32153234

32163235
Python/jit.o: $(srcdir)/Python/jit.c @JIT_STENCILS_H@
32173236
$(CC) -c $(PY_CORE_CFLAGS) -o $@ $<
32183237

32193238
.PHONY: regen-jit
3220-
regen-jit:
3221-
@REGEN_JIT_COMMAND@
3239+
regen-jit: $(JIT_TARGETS)
32223240

32233241
# Some make's put the object file in the current directory
32243242
.c.o:
@@ -3342,7 +3360,7 @@ clean-profile: clean-retain-profile clean-bolt
33423360
# gh-141808: The JIT stencils are deliberately kept in clean-profile
33433361
.PHONY: clean-jit-stencils
33443362
clean-jit-stencils:
3345-
-rm -f jit_stencils*.h
3363+
-rm -f $(JIT_TARGETS) $(JIT_GENERATED_STAMP) jit_stencils*.h jit_shim*.o
33463364

33473365
.PHONY: clean
33483366
clean: clean-profile clean-jit-stencils

PCbuild/pyproject.props

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@
1212
<IntDir>$(IntDir.Replace(`\\`, `\`))</IntDir>
1313
<GeneratedFrozenModulesDir>$(Py_IntDir)\$(MajorVersionNumber)$(MinorVersionNumber)_frozen\</GeneratedFrozenModulesDir>
1414
<GeneratedZlibNgDir>$(Py_IntDir)\$(MajorVersionNumber)$(MinorVersionNumber)$(ArchName)_$(Configuration)\zlib-ng\</GeneratedZlibNgDir>
15-
<GeneratedJitStencilsDir>$(Py_IntDir)\$(MajorVersionNumber)$(MinorVersionNumber)_$(Configuration)</GeneratedJitStencilsDir>
16-
<GeneratedJitStencilsDir Condition="$(Configuration) == 'PGUpdate'">$(Py_IntDir)\$(MajorVersionNumber)$(MinorVersionNumber)_PGInstrument</GeneratedJitStencilsDir>
15+
<GeneratedJitStencilsDir>$(Py_IntDir)\$(MajorVersionNumber)$(MinorVersionNumber)_$(Configuration)\</GeneratedJitStencilsDir>
16+
<GeneratedJitStencilsDir Condition="$(Configuration) == 'PGUpdate'">$(Py_IntDir)\$(MajorVersionNumber)$(MinorVersionNumber)_PGInstrument\</GeneratedJitStencilsDir>
17+
<GeneratedJitStencilsDir>$(GeneratedJitStencilsDir.Replace(`\\`, `\`))</GeneratedJitStencilsDir>
1718
<TargetName Condition="'$(TargetName)' == ''">$(ProjectName)</TargetName>
1819
<TargetName>$(TargetName)$(PyDebugExt)</TargetName>
1920
<GenerateManifest>false</GenerateManifest>

PCbuild/pythoncore.vcxproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@
115115
<Link>
116116
<AdditionalDependencies>version.lib;ws2_32.lib;pathcch.lib;bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>
117117
<AdditionalDependencies Condition="$(IncludeExternals)">zlib-ng$(PyDebugExt).lib;%(AdditionalDependencies)</AdditionalDependencies>
118+
<AdditionalDependencies Condition="'$(UseJIT)' == 'true' and $(Platform) == 'ARM64'">$(GeneratedJitStencilsDir)jit_shim-aarch64-pc-windows-msvc.o;%(AdditionalDependencies)</AdditionalDependencies>
119+
<AdditionalDependencies Condition="'$(UseJIT)' == 'true' and $(Platform) == 'Win32'">$(GeneratedJitStencilsDir)jit_shim-i686-pc-windows-msvc.o;%(AdditionalDependencies)</AdditionalDependencies>
120+
<AdditionalDependencies Condition="'$(UseJIT)' == 'true' and $(Platform) == 'x64'">$(GeneratedJitStencilsDir)jit_shim-x86_64-pc-windows-msvc.o;%(AdditionalDependencies)</AdditionalDependencies>
118121
</Link>
119122
</ItemDefinitionGroup>
120123
<ItemGroup>

PCbuild/regen.targets

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@
3535
<_JITOutputs Include="$(GeneratedJitStencilsDir)jit_stencils-aarch64-pc-windows-msvc.h" Condition="$(Platform) == 'ARM64'"/>
3636
<_JITOutputs Include="$(GeneratedJitStencilsDir)jit_stencils-i686-pc-windows-msvc.h" Condition="$(Platform) == 'Win32'"/>
3737
<_JITOutputs Include="$(GeneratedJitStencilsDir)jit_stencils-x86_64-pc-windows-msvc.h" Condition="$(Platform) == 'x64'"/>
38+
<_JITOutputs Include="$(GeneratedJitStencilsDir)jit_shim-aarch64-pc-windows-msvc.o" Condition="$(Platform) == 'ARM64'"/>
39+
<_JITOutputs Include="$(GeneratedJitStencilsDir)jit_shim-i686-pc-windows-msvc.o" Condition="$(Platform) == 'Win32'"/>
40+
<_JITOutputs Include="$(GeneratedJitStencilsDir)jit_shim-x86_64-pc-windows-msvc.o" Condition="$(Platform) == 'x64'"/>
3841
<_CasesSources Include="$(PySourcePath)Python\bytecodes.c;$(PySourcePath)Python\optimizer_bytecodes.c;"/>
3942
<_CasesOutputs Include="$(PySourcePath)Python\generated_cases.c.h;$(PySourcePath)Include\opcode_ids.h;$(PySourcePath)Include\internal\pycore_uop_ids.h;$(PySourcePath)Python\opcode_targets.h;$(PySourcePath)Include\internal\pycore_opcode_metadata.h;$(PySourcePath)Include\internal\pycore_uop_metadata.h;$(PySourcePath)Python\optimizer_cases.c.h;$(PySourcePath)Lib\_opcode_metadata.py"/>
4043
<_SbomSources Include="$(PySourcePath)PCbuild\get_externals.bat" />
@@ -129,7 +132,7 @@
129132
<JITArgs Condition="$(Platform) == 'x64'">x86_64-pc-windows-msvc</JITArgs>
130133
<JITArgs Condition="$(Configuration) == 'Debug'">$(JITArgs) --debug</JITArgs>
131134
</PropertyGroup>
132-
<Exec Command='$(PythonForBuild) "$(PySourcePath)Tools\jit\build.py" $(JITArgs) --output-dir "$(GeneratedJitStencilsDir)" --pyconfig-dir "$(PySourcePath)PC" --llvm-version="$(LLVM_VERSION)" --llvm-tools-install-dir="$(LLVM_TOOLS_INSTALL_DIR)"'/>
135+
<Exec Command='$(PythonForBuild) "$(PySourcePath)Tools\jit\build.py" $(JITArgs) --output-dir "$(GeneratedJitStencilsDir.TrimEnd(`\`))" --pyconfig-dir "$(PySourcePath)PC" --llvm-version="$(LLVM_VERSION)" --llvm-tools-install-dir="$(LLVM_TOOLS_INSTALL_DIR)"'/>
133136
</Target>
134137
<Target Name="_CleanJIT" AfterTargets="Clean">
135138
<Delete Files="@(_JITOutputs)"/>

Python/ceval.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1305,7 +1305,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
13051305
}
13061306
#ifdef _Py_TIER2
13071307
#ifdef _Py_JIT
1308-
_PyJitEntryFuncPtr _Py_jit_entry = _Py_LazyJitShim;
1308+
_PyJitEntryFuncPtr _Py_jit_entry = _PyJIT;
13091309
#else
13101310
_PyJitEntryFuncPtr _Py_jit_entry = _PyTier2Interpreter;
13111311
#endif

Python/jit.c

Lines changed: 0 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,6 @@ jit_error(const char *message)
6060
PyErr_Format(PyExc_RuntimeWarning, "JIT %s (%d)", message, hint);
6161
}
6262

63-
static size_t _Py_jit_shim_size = 0;
64-
6563
static int
6664
address_in_executor_array(_PyExecutorObject **ptrs, size_t count, uintptr_t addr)
6765
{
@@ -104,13 +102,6 @@ _PyJIT_AddressInJitCode(PyInterpreterState *interp, uintptr_t addr)
104102
if (interp == NULL) {
105103
return 0;
106104
}
107-
if (_Py_jit_entry != _Py_LazyJitShim && _Py_jit_shim_size != 0) {
108-
uintptr_t start = (uintptr_t)_Py_jit_entry;
109-
uintptr_t end = start + _Py_jit_shim_size;
110-
if (addr >= start && addr < end) {
111-
return 1;
112-
}
113-
}
114105
if (address_in_executor_array(interp->executor_ptrs, interp->executor_count, addr)) {
115106
return 1;
116107
}
@@ -727,75 +718,6 @@ _PyJIT_Compile(_PyExecutorObject *executor, const _PyUOpInstruction trace[], siz
727718
return 0;
728719
}
729720

730-
/* One-off compilation of the jit entry shim
731-
* We compile this once only as it effectively a normal
732-
* function, but we need to use the JIT because it needs
733-
* to understand the jit-specific calling convention.
734-
* Don't forget to call _PyJIT_Fini later!
735-
*/
736-
static _PyJitEntryFuncPtr
737-
compile_shim(void)
738-
{
739-
_PyExecutorObject dummy;
740-
const StencilGroup *group;
741-
size_t code_size = 0;
742-
size_t data_size = 0;
743-
jit_state state = {0};
744-
group = &shim;
745-
code_size += group->code_size;
746-
data_size += group->data_size;
747-
combine_symbol_mask(group->trampoline_mask, state.trampolines.mask);
748-
combine_symbol_mask(group->got_mask, state.got_symbols.mask);
749-
// Round up to the nearest page:
750-
size_t page_size = get_page_size();
751-
assert((page_size & (page_size - 1)) == 0);
752-
size_t code_padding = DATA_ALIGN - ((code_size + state.trampolines.size) & (DATA_ALIGN - 1));
753-
size_t padding = page_size - ((code_size + state.trampolines.size + code_padding + data_size + state.got_symbols.size) & (page_size - 1));
754-
size_t total_size = code_size + state.trampolines.size + code_padding + data_size + state.got_symbols.size + padding;
755-
unsigned char *memory = jit_alloc(total_size);
756-
if (memory == NULL) {
757-
return NULL;
758-
}
759-
unsigned char *code = memory;
760-
state.trampolines.mem = memory + code_size;
761-
unsigned char *data = memory + code_size + state.trampolines.size + code_padding;
762-
state.got_symbols.mem = data + data_size;
763-
// Compile the shim, which handles converting between the native
764-
// calling convention and the calling convention used by jitted code
765-
// (which may be different for efficiency reasons).
766-
group = &shim;
767-
group->emit(code, data, &dummy, NULL, &state);
768-
code += group->code_size;
769-
data += group->data_size;
770-
assert(code == memory + code_size);
771-
assert(data == memory + code_size + state.trampolines.size + code_padding + data_size);
772-
if (mark_executable(memory, total_size)) {
773-
jit_free(memory, total_size);
774-
return NULL;
775-
}
776-
_Py_jit_shim_size = total_size;
777-
return (_PyJitEntryFuncPtr)memory;
778-
}
779-
780-
static PyMutex lazy_jit_mutex = { 0 };
781-
782-
_Py_CODEUNIT *
783-
_Py_LazyJitShim(
784-
_PyExecutorObject *executor, _PyInterpreterFrame *frame, _PyStackRef *stack_pointer, PyThreadState *tstate
785-
) {
786-
PyMutex_Lock(&lazy_jit_mutex);
787-
if (_Py_jit_entry == _Py_LazyJitShim) {
788-
_PyJitEntryFuncPtr shim = compile_shim();
789-
if (shim == NULL) {
790-
PyMutex_Unlock(&lazy_jit_mutex);
791-
Py_FatalError("Cannot allocate core JIT code");
792-
}
793-
_Py_jit_entry = shim;
794-
}
795-
PyMutex_Unlock(&lazy_jit_mutex);
796-
return _Py_jit_entry(executor, frame, stack_pointer, tstate);
797-
}
798-
799721
// Free executor's memory allocated with _PyJIT_Compile
800722
void
801723
_PyJIT_Free(_PyExecutorObject *executor)
@@ -812,22 +734,4 @@ _PyJIT_Free(_PyExecutorObject *executor)
812734
}
813735
}
814736

815-
// Free shim memory allocated with compile_shim
816-
void
817-
_PyJIT_Fini(void)
818-
{
819-
PyMutex_Lock(&lazy_jit_mutex);
820-
unsigned char *memory = (unsigned char *)_Py_jit_entry;
821-
size_t size = _Py_jit_shim_size;
822-
if (size) {
823-
_Py_jit_entry = _Py_LazyJitShim;
824-
_Py_jit_shim_size = 0;
825-
if (jit_free(memory, size)) {
826-
PyErr_FormatUnraisable("Exception ignored while "
827-
"freeing JIT entry code");
828-
}
829-
}
830-
PyMutex_Unlock(&lazy_jit_mutex);
831-
}
832-
833737
#endif // _Py_JIT

Python/pylifecycle.c

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,6 @@
3737
#include "pycore_uniqueid.h" // _PyObject_FinalizeUniqueIdPool()
3838
#include "pycore_warnings.h" // _PyWarnings_InitState()
3939
#include "pycore_weakref.h" // _PyWeakref_GET_REF()
40-
#ifdef _Py_JIT
41-
#include "pycore_jit.h" // _PyJIT_Fini()
42-
#endif
4340

4441
#if defined(PYMALLOC_USE_HUGEPAGES) && defined(MS_WINDOWS)
4542
#include <Windows.h>
@@ -2531,11 +2528,6 @@ _Py_Finalize(_PyRuntimeState *runtime)
25312528

25322529
finalize_interp_clear(tstate);
25332530

2534-
#ifdef _Py_JIT
2535-
/* Free JIT shim memory */
2536-
_PyJIT_Fini();
2537-
#endif
2538-
25392531
#ifdef Py_TRACE_REFS
25402532
/* Display addresses (& refcnts) of all objects still alive.
25412533
* An address can be used to find the repr of the object, printed

Python/pystate.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -489,11 +489,6 @@ free_interpreter(PyInterpreterState *interp)
489489
static inline int check_interpreter_whence(long);
490490
#endif
491491

492-
extern _Py_CODEUNIT *
493-
_Py_LazyJitShim(
494-
struct _PyExecutorObject *exec, _PyInterpreterFrame *frame, _PyStackRef *stack_pointer, PyThreadState *tstate
495-
);
496-
497492
/* Get the interpreter state to a minimal consistent state.
498493
Further init happens in pylifecycle.c before it can be used.
499494
All fields not initialized here are expected to be zeroed out,

0 commit comments

Comments
 (0)