Skip to content

Commit f2c63a1

Browse files
alexmalyshevmeta-codesync[bot]
authored andcommitted
Make _PyJIT_Result into a C++ enum class
Summary: This is only used in C++ code, and we don't bother with exposing a C API into the JIT anymore. Reviewed By: yoney Differential Revision: D95656784 fbshipit-source-id: 6f4e37ac4bc03d8f467e717908c7b134185041e1
1 parent 8706522 commit f2c63a1

4 files changed

Lines changed: 76 additions & 87 deletions

File tree

cinderx/Jit/pyjit.cpp

Lines changed: 44 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,8 @@ PyObject* forcedJitVectorcall(
167167
BorrowedRef<PyFunctionObject> func{func_obj};
168168
BorrowedRef<PyCodeObject> code{func->func_code};
169169

170-
_PyJIT_Result result = compileFunction(func);
171-
if (result == PYJIT_RESULT_OK) {
170+
auto result = compileFunction(func);
171+
if (result == Result::OK) {
172172
JIT_DCHECK(
173173
isJitCompiled(func),
174174
"JIT succeeded for function {} but it is not recognized as compiled",
@@ -180,15 +180,14 @@ PyObject* forcedJitVectorcall(
180180

181181
// Python errors shouldn't happen during compilation, but if they do, bubble
182182
// them up without calling the function.
183-
if (result == PYJIT_RESULT_PYTHON_EXCEPTION) {
183+
if (result == Result::PYTHON_EXCEPTION) {
184184
setVectorcall(func, interp_entry);
185185
return nullptr;
186186
}
187187

188188
// Reset the function's entrypoint if it doesn't seem like there's a chance
189189
// compilation will work "soon".
190-
if (result != PYJIT_RESULT_ALREADY_SCHEDULED &&
191-
result != PYJIT_RESULT_PAUSED) {
190+
if (result != Result::ALREADY_SCHEDULED && result != Result::PAUSED) {
192191
setVectorcall(func, interp_entry);
193192
}
194193

@@ -815,11 +814,11 @@ bool isOverMaxCodeSize() {
815814
return max_code_size && code_allocator->usedBytes() >= max_code_size;
816815
}
817816

818-
_PyJIT_Result compilePreloader(
817+
Result compilePreloader(
819818
const hir::Preloader& preloader,
820819
BorrowedRef<PyFunctionObject> func) {
821820
if (isOverMaxCodeSize()) {
822-
return PYJIT_OVER_MAX_CODE_SIZE;
821+
return Result::OVER_MAX_CODE_SIZE;
823822
}
824823

825824
return compilePreloaderImpl(jitCtx(), preloader, func);
@@ -936,14 +935,13 @@ hir::Preloader* preload(BorrowedRef<> unit) {
936935
// will only use an already-created preloader, it will not preload, and
937936
// therefore it cannot raise a Python exception.
938937
//
939-
// Returns PYJIT_RESULT_NO_PRELOADER if no preloader is available.
940-
_PyJIT_Result tryCompilePreloaded(BorrowedRef<> unit) {
938+
// Returns Result::NO_PRELOADER if no preloader is available.
939+
Result tryCompilePreloaded(BorrowedRef<> unit) {
941940
// func may be null here if we're just compiling a code object for a nested
942941
// function
943942
auto [func, code] = splitUnit(unit);
944943
hir::Preloader* preloader = hir::preloaderManager().find(code);
945-
return preloader ? compilePreloader(*preloader, func)
946-
: PYJIT_RESULT_NO_PRELOADER;
944+
return preloader ? compilePreloader(*preloader, func) : Result::NO_PRELOADER;
947945
}
948946

949947
void compile_worker_thread() {
@@ -954,13 +952,13 @@ void compile_worker_thread() {
954952

955953
while (BorrowedRef<> unit = getThreadedCompileContext().nextUnit()) {
956954
attempts++;
957-
_PyJIT_Result res = tryCompilePreloaded(unit);
958-
if (res == PYJIT_RESULT_ALREADY_SCHEDULED) {
955+
auto result = tryCompilePreloaded(unit);
956+
if (result == Result::ALREADY_SCHEDULED) {
959957
retries++;
960958
getThreadedCompileContext().retryUnit(unit);
961959
}
962960
JIT_CHECK(
963-
res != PYJIT_RESULT_NO_PRELOADER,
961+
result != Result::NO_PRELOADER,
964962
"Cannot find a JIT preloader for {}",
965963
unitFullname(unit));
966964
}
@@ -1666,39 +1664,39 @@ PyObject* force_compile(PyObject* /* self */, PyObject* arg) {
16661664
return nullptr;
16671665
}
16681666

1669-
_PyJIT_Result result = compileFunction(func);
1667+
auto result = compileFunction(func);
16701668
switch (result) {
1671-
case PYJIT_RESULT_OK:
1669+
case Result::OK:
16721670
Py_RETURN_TRUE;
1673-
case PYJIT_RESULT_ALREADY_SCHEDULED:
1671+
case Result::ALREADY_SCHEDULED:
16741672
// Strange case, the function is being compiled by a different thread.
16751673
// Shouldn't happen, but don't die if it does.
16761674
Py_RETURN_FALSE;
1677-
case PYJIT_RESULT_PAUSED:
1675+
case Result::PAUSED:
16781676
PyErr_SetString(
16791677
PyExc_RuntimeError,
16801678
"Compilation failed because the JIT was paused, but that shouldn't "
16811679
"be possible as this case was already checked");
16821680
return nullptr;
1683-
case PYJIT_RESULT_CANNOT_SPECIALIZE:
1681+
case Result::CANNOT_SPECIALIZE:
16841682
PyErr_SetString(PyExc_RuntimeError, "PYJIT_RESULT_CANNOT_SPECIALIZE");
16851683
return nullptr;
1686-
case PYJIT_RESULT_NOT_ON_JITLIST:
1684+
case Result::NOT_ON_JITLIST:
16871685
PyErr_SetString(PyExc_RuntimeError, "PYJIT_RESULT_NOT_ON_JITLIST");
16881686
return nullptr;
1689-
case PYJIT_RESULT_UNKNOWN_ERROR:
1687+
case Result::UNKNOWN_ERROR:
16901688
PyErr_SetString(PyExc_RuntimeError, "PYJIT_RESULT_UNKNOWN_ERROR");
16911689
return nullptr;
1692-
case PYJIT_NOT_INITIALIZED:
1690+
case Result::NOT_INITIALIZED:
16931691
PyErr_SetString(PyExc_RuntimeError, "PYJIT_NOT_INITIALIZED");
16941692
return nullptr;
1695-
case PYJIT_RESULT_NO_PRELOADER:
1693+
case Result::NO_PRELOADER:
16961694
PyErr_SetString(PyExc_RuntimeError, "PYJIT_RESULT_NO_PRELOADER");
16971695
return nullptr;
1698-
case PYJIT_OVER_MAX_CODE_SIZE:
1696+
case Result::OVER_MAX_CODE_SIZE:
16991697
PyErr_SetString(PyExc_RuntimeError, "PYJIT_OVER_MAX_CODE_SIZE");
17001698
return nullptr;
1701-
case PYJIT_RESULT_PYTHON_EXCEPTION:
1699+
case Result::PYTHON_EXCEPTION:
17021700
return nullptr;
17031701
}
17041702
PyErr_Format(
@@ -3151,7 +3149,7 @@ void trackEligibleCodeObjects(
31513149
// Preload a function and its dependencies, then compile them all.
31523150
//
31533151
// Failing to compile a dependent function is a soft failure, and is ignored.
3154-
_PyJIT_Result compile_func(BorrowedRef<PyFunctionObject> func) {
3152+
Result compile_func(BorrowedRef<PyFunctionObject> func) {
31553153
// isolate preloaders state since batch preloading might trigger a call to a
31563154
// jitable function, resulting in a single-function compile
31573155
hir::IsolatedPreloaders ip;
@@ -3170,7 +3168,7 @@ _PyJIT_Result compile_func(BorrowedRef<PyFunctionObject> func) {
31703168
if (targets.empty()) {
31713169
JIT_CHECK(
31723170
PyErr_Occurred(), "Expect a Python exception when preloading fails");
3173-
return PYJIT_RESULT_PYTHON_EXCEPTION;
3171+
return Result::PYTHON_EXCEPTION;
31743172
}
31753173

31763174
if (targets.size() > 1) {
@@ -3182,7 +3180,7 @@ _PyJIT_Result compile_func(BorrowedRef<PyFunctionObject> func) {
31823180

31833181
// Will return unknown error if none of the targets can find a matching
31843182
// preloader.
3185-
_PyJIT_Result result = PYJIT_RESULT_UNKNOWN_ERROR;
3183+
auto result = Result::UNKNOWN_ERROR;
31863184

31873185
for (BorrowedRef<PyFunctionObject> target : targets) {
31883186
auto preloader = hir::preloaderManager().find(target);
@@ -3198,18 +3196,18 @@ _PyJIT_Result compile_func(BorrowedRef<PyFunctionObject> func) {
31983196

31993197
result = compilePreloader(*preloader, target);
32003198
JIT_CHECK(
3201-
result != PYJIT_RESULT_PYTHON_EXCEPTION,
3199+
result != Result::PYTHON_EXCEPTION,
32023200
"Raised a Python exception while JIT-compiling function {}, which is "
32033201
"not allowed",
32043202
funcFullname(target));
32053203
JIT_CHECK(
3206-
result != PYJIT_RESULT_NO_PRELOADER,
3204+
result != Result::NO_PRELOADER,
32073205
"Cannot find a preloader for function {}, despite it just being "
32083206
"preloaded",
32093207
funcFullname(target));
32103208

32113209
// If we hit the max code size limit, stop compiling further functions
3212-
if (result == PYJIT_OVER_MAX_CODE_SIZE) {
3210+
if (result == Result::OVER_MAX_CODE_SIZE) {
32133211
break;
32143212
}
32153213
}
@@ -3226,7 +3224,7 @@ _PyJIT_Result compile_func(BorrowedRef<PyFunctionObject> func) {
32263224
// to pretend everything went okay. It doesn't make sense to return the
32273225
// results of any of the other preloaded functions, as the caller never asked
32283226
// for them in the first place.
3229-
return PYJIT_RESULT_OK;
3227+
return Result::OK;
32303228
}
32313229

32323230
// Call posix.register_at_fork(None, None, cinderjit.after_fork_child), if it
@@ -3727,15 +3725,15 @@ bool scheduleJitCompile(BorrowedRef<PyFunctionObject> func) {
37273725
return true;
37283726
}
37293727

3730-
_PyJIT_Result compileFunction(BorrowedRef<PyFunctionObject> func) {
3728+
Result compileFunction(BorrowedRef<PyFunctionObject> func) {
37313729
if (!isJitInitialized()) {
3732-
return PYJIT_NOT_INITIALIZED;
3730+
return Result::NOT_INITIALIZED;
37333731
}
37343732
if (isJitPaused()) {
3735-
return PYJIT_RESULT_PAUSED;
3733+
return Result::PAUSED;
37363734
}
37373735
if (!isJitUsable()) {
3738-
return PYJIT_RESULT_UNKNOWN_ERROR;
3736+
return Result::UNKNOWN_ERROR;
37393737
}
37403738

37413739
auto& jit_reg_units = cinderx::getModuleState()->registeredCompilationUnits();
@@ -3881,7 +3879,7 @@ void typeNameModified(BorrowedRef<PyTypeObject> type) {
38813879
}
38823880
}
38833881

3884-
_PyJIT_Result compilePreloaderImpl(
3882+
Result compilePreloaderImpl(
38853883
jit::CompilerContext<Compiler>* jit_ctx,
38863884
const hir::Preloader& preloader,
38873885
BorrowedRef<PyFunctionObject> func) {
@@ -3898,7 +3896,7 @@ _PyJIT_Result compilePreloaderImpl(
38983896

38993897
if (code == nullptr) {
39003898
JIT_DLOG("Can't compile {} as it has no code object", preloader.fullname());
3901-
return PYJIT_RESULT_CANNOT_SPECIALIZE;
3899+
return Result::CANNOT_SPECIALIZE;
39023900
}
39033901

39043902
BorrowedRef<PyDictObject> builtins = preloader.builtins();
@@ -3908,13 +3906,13 @@ _PyJIT_Result compilePreloaderImpl(
39083906
JIT_DLOG(
39093907
"Can't compile {} due to missing required code flags",
39103908
preloader.fullname());
3911-
return PYJIT_RESULT_CANNOT_SPECIALIZE;
3909+
return Result::CANNOT_SPECIALIZE;
39123910
}
39133911
if (code->co_flags & CI_CO_SUPPRESS_JIT) {
39143912
JIT_DLOG(
39153913
"Can't compile {} as it has had the JIT suppressed",
39163914
preloader.fullname());
3917-
return PYJIT_RESULT_CANNOT_SPECIALIZE;
3915+
return Result::CANNOT_SPECIALIZE;
39183916
}
39193917
constexpr int forbidden_flags =
39203918
PY_VERSION_HEX >= 0x030C0000 ? CO_ASYNC_GENERATOR : 0;
@@ -3923,7 +3921,7 @@ _PyJIT_Result compilePreloaderImpl(
39233921
"Cannot JIT compile {} as it has prohibited code flags: 0x{:x}",
39243922
preloader.fullname(),
39253923
code->co_flags & forbidden_flags);
3926-
return PYJIT_RESULT_CANNOT_SPECIALIZE;
3924+
return Result::CANNOT_SPECIALIZE;
39273925
}
39283926

39293927
CompilationKey key{code, builtins, globals};
@@ -3938,14 +3936,14 @@ _PyJIT_Result compilePreloaderImpl(
39383936
if (func != nullptr) {
39393937
jit_ctx->finalizeFunc(func, *compiled);
39403938
}
3941-
return PYJIT_RESULT_OK;
3939+
return Result::OK;
39423940
} else if (jit_ctx->hasCompletedCompile(key)) {
39433941
// We're in the multi-threaded scenario we've created the
39443942
// CompiledFunctionData and will create the CompiledFunction at the end
3945-
return PYJIT_RESULT_OK;
3943+
return Result::OK;
39463944
} else if (!jit_ctx->addActiveCompile(key)) {
39473945
// The compilation is in-flight on another thread
3948-
return PYJIT_RESULT_ALREADY_SCHEDULED;
3946+
return Result::ALREADY_SCHEDULED;
39493947
}
39503948
}
39513949

@@ -3959,15 +3957,15 @@ _PyJIT_Result compilePreloaderImpl(
39593957
ThreadedCompileSerialize guard;
39603958
jit_ctx->removeActiveCompile(key);
39613959
if (!compiled_func.has_value()) {
3962-
return PYJIT_RESULT_UNKNOWN_ERROR;
3960+
return Result::UNKNOWN_ERROR;
39633961
}
39643962

39653963
register_pycode_debug_symbol(
39663964
preloader.code(), preloader.fullname().c_str(), *compiled_func);
39673965

39683966
jit_ctx->codeCompiled(func, key, std::move(*compiled_func));
39693967

3970-
return PYJIT_RESULT_OK;
3968+
return Result::OK;
39713969
}
39723970

39733971
} // namespace jit

cinderx/Jit/pyjit.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,8 @@ bool scheduleJitCompile(BorrowedRef<PyFunctionObject> func);
5353
* JIT compile func and patch its entry point.
5454
*
5555
* On success, positional only calls to func will use the JIT compiled version.
56-
*
57-
* Returns PYJIT_RESULT_OK on success.
5856
*/
59-
_PyJIT_Result compileFunction(BorrowedRef<PyFunctionObject> func);
57+
Result compileFunction(BorrowedRef<PyFunctionObject> func);
6058

6159
/*
6260
* Preload a function, along with any functions that it calls that we might want
@@ -85,7 +83,7 @@ void typeModified(BorrowedRef<PyTypeObject> type);
8583
void typeNameModified(BorrowedRef<PyTypeObject> type);
8684

8785
// Exposed for unit tests
88-
_PyJIT_Result compilePreloaderImpl(
86+
Result compilePreloaderImpl(
8987
jit::CompilerContext<Compiler>* jit_ctx,
9088
const hir::Preloader& preloader,
9189
BorrowedRef<PyFunctionObject> func);

cinderx/Jit/pyjit_result.h

Lines changed: 29 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,54 +2,47 @@
22

33
#pragma once
44

5-
#ifndef Py_LIMITED_API
6-
#ifdef __cplusplus
75
#include <fmt/format.h>
86

9-
extern "C" {
10-
#endif
7+
namespace jit {
118

12-
/* Status codes for the result of JIT attempts. */
13-
typedef enum {
14-
PYJIT_RESULT_OK = 0,
9+
// Status codes for the result of JIT attempts.
10+
enum class Result : int32_t {
11+
OK,
1512

16-
/*
17-
* We cannot specialize the input.
18-
*
19-
* For example, we cannot generate a specialized tp_init slot if the __init__
20-
* method of the class is not a function.
21-
*/
22-
PYJIT_RESULT_CANNOT_SPECIALIZE,
13+
// We cannot specialize the input.
14+
//
15+
// For example, we cannot generate a specialized tp_init slot if the __init__
16+
// method of the class is not a function.
17+
CANNOT_SPECIALIZE,
2318

24-
/* A JIT-list is in use and this function is not on it. */
25-
PYJIT_RESULT_NOT_ON_JITLIST,
19+
// A JIT-list is in use and this function is not on it.
20+
NOT_ON_JITLIST,
2621

27-
/* Someone tried to compile a function but the JIT is not initialized. */
28-
PYJIT_NOT_INITIALIZED,
22+
// Someone tried to compile a function but the JIT is not initialized.
23+
NOT_INITIALIZED,
2924

30-
/* Function is being scheduled for compilation across multiple threads. */
31-
PYJIT_RESULT_ALREADY_SCHEDULED,
25+
// Function is being scheduled for compilation across multiple threads.
26+
ALREADY_SCHEDULED,
3227

33-
/* Compilation didn't happen because the JIT is currently paused. */
34-
PYJIT_RESULT_PAUSED,
28+
// Compilation didn't happen because the JIT is currently paused.
29+
PAUSED,
3530

36-
/* We are compiling with preload required, but did not find a preloader. */
37-
PYJIT_RESULT_NO_PRELOADER,
31+
// We are compiling with preload required, but did not find a preloader.
32+
NO_PRELOADER,
3833

39-
PYJIT_RESULT_UNKNOWN_ERROR,
34+
// We are over the maximum amount of code we are allowed to generate.
35+
OVER_MAX_CODE_SIZE,
4036

41-
/* We are over the maximum amount of code we are allowed to generate. */
42-
PYJIT_OVER_MAX_CODE_SIZE,
37+
UNKNOWN_ERROR,
4338

44-
/* The JIT raised a Python exception, like a deferred object failing to be
45-
resolved during preloading. */
46-
PYJIT_RESULT_PYTHON_EXCEPTION = -1
47-
} _PyJIT_Result;
39+
// The JIT raised a Python exception, like a deferred object failing to be
40+
// resolved during preloading.
41+
PYTHON_EXCEPTION = -1,
42+
};
4843

49-
#ifdef __cplusplus
50-
}
51-
inline auto format_as(_PyJIT_Result e) {
44+
} // namespace jit
45+
46+
inline auto format_as(jit::Result e) {
5247
return fmt::underlying(e);
5348
}
54-
#endif
55-
#endif /* Py_LIMITED_API */

cinderx/RuntimeTests/jit_context_test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ foo = "hello"
5151

5252
auto comp_result =
5353
jit::compilePreloaderImpl(jit_ctx_.get(), *preloader, func);
54-
ASSERT_EQ(comp_result, PYJIT_RESULT_OK);
54+
ASSERT_EQ(comp_result, jit::Result::OK);
5555

5656
auto empty_tuple = Ref<>::steal(PyTuple_New(0));
5757
auto result = Ref<>::steal(PyObject_Call(func, empty_tuple, nullptr));

0 commit comments

Comments
 (0)