Skip to content

Commit 9de8166

Browse files
alexmalyshevfacebook-github-bot
authored andcommitted
Always initialize the CinderX JIT
Summary: Remove the need for having one of `PYTHONJIT{,ALL,AUTO,LISTFILE}` defined to use the JIT. It is now unconditionally initialized. As long as the application has `cinderx` as a dependency, it can call `cinderx.jit.force_compile()` to JIT-compile functions. Having `cinderx` automatically compile code still requires applying one of `PYTHONJIT{AUTO,ALL,LISTFILE}` to the environment before running the binary, or calling `cinderx.jit.{append,read}_jit_list()` at runtime. `cinderx.jit.enable()` does not yet allow the user to specify the JitAuto threshold or to enable JitAll mode, that will come later. Reviewed By: DinoV Differential Revision: D80621511 fbshipit-source-id: b64d17cecee7855369fbe3528a6194644de21a1f
1 parent e8c4a9a commit 9de8166

4 files changed

Lines changed: 24 additions & 83 deletions

File tree

cinderx/Jit/pyjit.cpp

Lines changed: 8 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,6 @@ std::atomic<int> g_compile_workers_retries;
141141

142142
int jit_help = 0;
143143

144-
// Temporary boolean for when `-X jit` or `PYTHONJIT=1` are used.
145-
bool bare_jit = false;
146-
147144
uint64_t countCalls(PyCodeObject* code) {
148145
#if SHADOWCODE_SUPPORTED
149146
return code->co_mutable->ncalls;
@@ -343,18 +340,11 @@ size_t parse_sized_argument(const std::string& val) {
343340

344341
FlagProcessor initFlagProcessor() {
345342
jit_help = 0;
346-
bare_jit = false;
347343

348344
FlagProcessor flag_processor;
349345

350346
// Flags are inspected in order of definition below.
351347

352-
flag_processor.addOption(
353-
"jit",
354-
"PYTHONJIT",
355-
bare_jit,
356-
"Initialize the JIT but don't automatically compile any functions");
357-
358348
flag_processor.addOption(
359349
"jit-all",
360350
"PYTHONJITALL",
@@ -1322,7 +1312,7 @@ PyObject* enable_jit(PyObject* /* self */, PyObject* /* arg */) {
13221312
if (jitCtx() == nullptr) {
13231313
PyErr_SetString(
13241314
PyExc_RuntimeError,
1325-
"Trying to re-enable the JIT but it was never initialized");
1315+
"Trying to re-enable the JIT but the JIT context is missing");
13261316
return nullptr;
13271317
}
13281318
if (isJitUsable()) {
@@ -2231,10 +2221,9 @@ PyObject* disable_specialized_opcodes(PyObject* /* self */, PyObject*) {
22312221
// and return 1. Otherwise, return 0.
22322222
int deopt_gen_impl(PyGenObject* gen) {
22332223
#if PY_VERSION_HEX >= 0x030C0000
2234-
if (deopt_jit_gen(gen)) {
2235-
return 1;
2236-
}
2237-
return 0;
2224+
// deopt_jit_gen optimistically succeeds when the generator isn't a JIT
2225+
// generator.
2226+
return JitGenObject::cast(gen) != nullptr && deopt_jit_gen(gen);
22382227
#else
22392228
GenDataFooter* footer = genDataFooter(gen);
22402229
if (footer == nullptr || Ci_GenIsCompleted(gen)) {
@@ -2915,33 +2904,18 @@ int initialize() {
29152904
jit_list = jit::JITList::create();
29162905
}
29172906
if (jit_list == nullptr) {
2918-
JIT_LOG("Failed to allocate JIT list");
2907+
PyErr_SetString(PyExc_RuntimeError, "Failed to allocate JIT list");
29192908
return -1;
29202909
}
29212910

29222911
try {
29232912
jit_list->parseFile(getConfig().jit_list.filename.c_str());
29242913
} catch (const std::exception& exn) {
2925-
if (getConfig().jit_list.error_on_parse) {
2926-
PyErr_SetString(PyExc_RuntimeError, exn.what());
2927-
return -1;
2928-
}
2929-
2930-
JIT_LOG("{}", exn.what());
2931-
JIT_LOG("Continuing on with the JIT disabled");
2932-
return 0;
2914+
PyErr_SetString(PyExc_RuntimeError, exn.what());
2915+
return -1;
29332916
}
29342917
}
29352918

2936-
auto const& config = getConfig();
2937-
bool use_jit = bare_jit || config.compile_all ||
2938-
config.jit_list.filename != "" || config.auto_jit_threshold > 0;
2939-
if (use_jit || config.force_init.value_or(false)) {
2940-
JIT_DLOG("Initializing the JIT");
2941-
} else {
2942-
return 0;
2943-
}
2944-
29452919
#if PY_VERSION_HEX >= 0x030C0000
29462920
jit::init_jit_genobject_type();
29472921
#endif
@@ -2963,12 +2937,10 @@ int initialize() {
29632937
return -1;
29642938
}
29652939

2966-
getMutableConfig().state = use_jit ? State::kRunning : State::kPaused;
2940+
getMutableConfig().state = State::kRunning;
29672941

29682942
g_jit_list = jit_list.release();
29692943

2970-
JIT_DLOG("JIT is {}", isJitUsable() ? "enabled" : "disabled");
2971-
29722944
return 0;
29732945
}
29742946

cinderx/PythonLib/test_cinderx/test_jitlist.py

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -151,13 +151,10 @@ def func():
151151
return 24
152152
153153
assert not cinderx.jit.is_jit_compiled(func)
154-
155154
cinderx.jit.lazy_compile(func)
155+
assert not cinderx.jit.is_jit_compiled(func)
156156
157-
# This has to use multiple threads otherwise this will take many minutes to run.
158-
# It'll be compiling all functions that were loaded and not-yet-run in JitAll
159-
# mode.
160-
assert cinderx.jit.precompile_all(workers=10)
157+
assert cinderx.jit.precompile_all(workers=2)
161158
assert cinderx.jit.is_jit_compiled(func)
162159
163160
print(func())
@@ -169,7 +166,7 @@ def func():
169166
codepath = dirpath / "mod.py"
170167
codepath.write_text(code)
171168
proc = subprocess.run(
172-
[sys.executable, "-X", "jit", "mod.py"],
169+
[sys.executable, "mod.py"],
173170
stdout=subprocess.PIPE,
174171
cwd=tmp,
175172
encoding=ENCODING,
@@ -218,32 +215,6 @@ def test_precompile_all_bad_args(self) -> None:
218215
with self.assertRaises(ValueError):
219216
cinderx.jit.precompile_all(workers=200000)
220217

221-
def test_default_parse_error_behavior_startup(self) -> None:
222-
code = 'print("Hello world!")'
223-
jitlist = "OH NO"
224-
with tempfile.TemporaryDirectory() as tmp:
225-
dirpath = Path(tmp)
226-
codepath = dirpath / "mod.py"
227-
jitlistpath = dirpath / "jitlist.txt"
228-
codepath.write_text(code)
229-
jitlistpath.write_text(jitlist)
230-
proc = subprocess.run(
231-
[
232-
sys.executable,
233-
"-X",
234-
"jit-list-file=jitlist.txt",
235-
"mod.py",
236-
],
237-
capture_output=True,
238-
cwd=tmp,
239-
encoding=ENCODING,
240-
env={"PYTHONPATH": CINDERX_PATH},
241-
)
242-
self.assertEqual(proc.returncode, 0, proc)
243-
self.assertIn(
244-
"Error while parsing line 1 in JIT list file jitlist.txt", proc.stderr
245-
)
246-
247218
def test_fail_on_parse_error_startup(self) -> None:
248219
code = 'print("Hello world!")'
249220
jitlist = "OH NO"

cinderx/RuntimeTests/cmdline_test.cpp

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -285,29 +285,21 @@ TEST_F(CmdLineTest, JITEnable) {
285285
[]() {},
286286
[]() {
287287
ASSERT_TRUE(isJitUsable());
288+
ASSERT_TRUE(getConfig().compile_all);
288289
ASSERT_EQ(is_intel_syntax(), 0); // default to AT&T syntax
289290
}),
290291
0);
291292

292-
ASSERT_EQ(
293-
try_flag_and_envvar_effect(
294-
L"jit", "PYTHONJIT=1", []() {}, []() { ASSERT_TRUE(isJitUsable()); }),
295-
0);
296-
297293
ASSERT_EQ(
298294
try_flag_and_envvar_effect(
299295
L"jit-all=0",
300296
"PYTHONJITALL=0",
301297
[]() {},
302-
[]() { ASSERT_FALSE(isJitUsable()); }),
303-
0);
304-
305-
ASSERT_EQ(
306-
try_flag_and_envvar_effect(
307-
L"jit=0",
308-
"PYTHONJIT=0",
309-
[]() {},
310-
[]() { ASSERT_FALSE(isJitUsable()); }),
298+
[]() {
299+
// JIT still usable when JitAll is not enabled.
300+
ASSERT_TRUE(isJitUsable());
301+
ASSERT_FALSE(getConfig().compile_all);
302+
}),
311303
0);
312304
}
313305

cinderx/TestScripts/3.14-opt-failures.txt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,16 @@ test_cinderx.test_compiler_sbs_stdlib_7
8181
test_cinderx.test_compiler_sbs_stdlib_8
8282
test_cinderx.test_compiler_sbs_stdlib_9
8383
test_cinderx.test_cpython_overrides.test_dis
84-
test_cinderx.test_cpython_overrides.test_inspect
8584
test_cinderx.test_immortalize
8685
test_cinderx.test_jit_attr_cache
8786
test_cinderx.test_jit_coroutines
87+
test_cinderx.test_jit_disable
88+
test_cinderx.test_jit_exception
89+
test_cinderx.test_jit_frame
90+
test_cinderx.test_jit_generators
8891
test_cinderx.test_jit_global_cache
92+
test_cinderx.test_jit_perf_map
8993
test_cinderx.test_jit_preload
94+
test_cinderx.test_jit_specialization
95+
test_cinderx.test_jit_type_annotations
9096
test_cinderx.test_parallel_gc

0 commit comments

Comments
 (0)