Skip to content

Commit 9db4747

Browse files
jbower-fbfacebook-github-bot
authored andcommitted
Enable generators + coroutines in JIT
Summary: With this remaining grab bag of fixes for tests we can now enable JIT compilation of generators and coroutines in 3.14. Reviewed By: alexmalyshev Differential Revision: D83003857 fbshipit-source-id: 467b7bbfd01d0aa0b90c21c7dfba2b63321d1257
1 parent f262485 commit 9db4747

6 files changed

Lines changed: 31 additions & 8 deletions

File tree

cinderx/Jit/generators_core.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,11 @@ PyObject* JitCoro_GetAwaitableIter(PyObject* o) {
8080

8181
PyErr_Format(
8282
PyExc_TypeError,
83+
#if PY_VERSION_HEX >= 0x030E0000
84+
"'%.100s' object can't be awaited",
85+
#else
8386
"object %.100s can't be used in 'await' expression",
87+
#endif
8488
ot->tp_name);
8589
return nullptr;
8690
}

cinderx/Jit/generators_rt.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,13 @@ PySendResult jitgen_am_send(PyObject* obj, PyObject* arg, PyObject** presult) {
209209
Py_CLEAR(gen->gi_ci_awaiter);
210210
#endif
211211

212+
#if PY_VERSION_HEX < 0x030E0000
212213
_PyErr_ClearExcState(&gen->gi_exc_state);
214+
#else
215+
JIT_DCHECK(
216+
gen->gi_exc_state.exc_value == nullptr,
217+
"Should not have an exception by now");
218+
#endif
213219
JIT_DCHECK(gen->gi_frame_state == FRAME_CLEARED, "Frame not cleared");
214220

215221
*presult = result;

cinderx/Jit/pyjit.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3316,10 +3316,8 @@ Context::CompilationResult compilePreloaderImpl(
33163316
preloader.fullname());
33173317
return {nullptr, PYJIT_RESULT_CANNOT_SPECIALIZE};
33183318
}
3319-
constexpr int forbidden_flags = PY_VERSION_HEX >= 0x030C0000
3320-
? CO_ASYNC_GENERATOR |
3321-
(PY_VERSION_HEX >= 0x030E0000 ? CO_GENERATOR | CO_COROUTINE : 0)
3322-
: 0;
3319+
constexpr int forbidden_flags =
3320+
PY_VERSION_HEX >= 0x030C0000 ? CO_ASYNC_GENERATOR : 0;
33233321
if (code->co_flags & forbidden_flags) {
33243322
JIT_DLOG(
33253323
"Cannot JIT compile {} as it has prohibited code flags: 0x{:x}",

cinderx/Jit/runtime_support.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,17 @@ PyObject g_iterDoneSentinel = {
2323
nullptr};
2424

2525
PyObject* invokeIterNext(PyObject* iterator) {
26-
PyObject* val = (*iterator->ob_type->tp_iternext)(iterator);
26+
iternextfunc internext_f = Py_TYPE(iterator)->tp_iternext;
27+
// This check was introduced in 3.14+ but looks like it would be legit in all
28+
// versions. I'm surprised it wasn't backported.
29+
if (internext_f == nullptr) {
30+
PyErr_Format(
31+
PyExc_TypeError,
32+
"'%.100s' object is not an iterator",
33+
Py_TYPE(iterator)->tp_name);
34+
return nullptr;
35+
}
36+
PyObject* val = internext_f(iterator);
2737
if (val != nullptr) {
2838
return val;
2939
}

cinderx/TestScripts/3.14-opt-failures.txt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,8 @@ test_cinderx.test_compiler_sbs_stdlib_9
7777
test_cinderx.test_cpython_overrides.test_dis
7878
test_cinderx.test_immortalize
7979
test_cinderx.test_jit_attr_cache
80-
test_cinderx.test_jit_coroutines
8180
test_cinderx.test_jit_disable
82-
test_cinderx.test_jit_exception
8381
test_cinderx.test_jit_frame
84-
test_cinderx.test_jit_generators
8582
test_cinderx.test_jit_global_cache
8683
test_cinderx.test_jit_perf_map
8784
test_cinderx.test_jit_preload

cinderx/TestScripts/cinder_jit_ignore_tests.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,3 +154,11 @@ test.test_descr.ClassPropertiesAndMethods.test_dir
154154
# + {'self': <test.test_capi.test_eval.Tests testMethod=test_eval_getlocals>,
155155
# + 'x': 1}
156156
test.test_capi.test_eval.Tests.test_eval_getlocals
157+
158+
# The JIT doesn't follow changes to local variables via the frame objects
159+
test.test_generators.ModifyUnderlyingIterableTest.test_modify_f_locals
160+
161+
# TASK(T239036547) This relies on GC of a function's globals created in a call
162+
# to exec(). However, we keep all "globals" objects alive via the JIT's
163+
# PreloaderManager.
164+
test.test_generators.FinalizationTest.test_generator_resurrect

0 commit comments

Comments
 (0)