Skip to content

Commit bd86adc

Browse files
alexmalyshevmeta-codesync[bot]
authored andcommitted
Make lightweight frames configurable at runtime
Summary: Adding a new FrameMode for lightweight frames so we can switch between them and normal frames on 3.12. Because there's fewer ENABLE_LIGHTWEIGHT_FRAMES ifdefs more of the code starts compiling for 3.14. This diff fixes some of it but doesn't address all of it. There's still uses of ENABLE_LIGHTWEIGHT_FRAMES so it's not 100% a runtime option just yet. Reviewed By: czardoz Differential Revision: D83871317 fbshipit-source-id: 93ec1314f697b47423788082d75092a181b619b3
1 parent 2f5601d commit bd86adc

16 files changed

Lines changed: 210 additions & 144 deletions

cinderx/Common/py-portability.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,13 +149,18 @@ inline PyCodeObject* frameCode(PyFrameObject* frame) {
149149

150150
// Stack ref compatibility helpers between for 3.14+
151151
#if PY_VERSION_HEX < 0x030E0000
152+
152153
#define Ci_STACK_TYPE PyObject*
153154
#define Ci_STACK_NULL NULL
154155
#define Ci_STACK_STEAL(VAL) VAL
155156
#define Ci_STACK_CLEAR(VAL) Py_CLEAR(VAL)
156157
#define Ci_STACK_XSETREF(DST, VAL) Py_XSETREF(DST, VAL);
157158
#define Ci_STACK_NEWREF(VAL) Py_NewRef(VAL)
159+
#define Ci_STACK_CLOSE(VAL) Py_DECREF(VAL)
160+
#define Ci_STACK_XCLOSE(VAL) Py_XDECREF(VAL)
161+
158162
#else
163+
159164
#define Ci_STACK_TYPE _PyStackRef
160165
#define Ci_STACK_NULL PyStackRef_NULL
161166
#define Ci_STACK_STEAL(VAL) \
@@ -173,6 +178,9 @@ inline PyCodeObject* frameCode(PyFrameObject* frame) {
173178
PyStackRef_XCLOSE(_tmp_old_dst); \
174179
} while (0)
175180
#define Ci_STACK_NEWREF(VAL) _PyStackRef_FromPyObjectNew(VAL)
181+
#define Ci_STACK_CLOSE(VAL) PyStackRef_CLOSE(VAL)
182+
#define Ci_STACK_XCLOSE(VAL) PyStackRef_XCLOSE(VAL)
183+
176184
#endif
177185

178186
#if PY_VERSION_HEX >= 0x030E0000

cinderx/Jit/codegen/frame_asm.cpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -193,16 +193,14 @@ bool FrameAsm::storeConst(
193193
return false;
194194
}
195195

196-
#ifdef ENABLE_LIGHTWEIGHT_FRAMES
197-
198196
void FrameAsm::linkLightWeightFunctionFrame(
199197
RegisterPreserver& preserver,
200198
const arch::Gp& func_reg,
201199
const arch::Gp& tstate_reg) {
202-
#if defined(CINDER_X86_64)
200+
#if defined(CINDER_X86_64) && defined(ENABLE_LIGHTWEIGHT_FRAMES)
203201
// Light weight function headers are allocated on the stack as:
204202
// PyFunctionObject* func_obj
205-
// _PyInterpererFrame
203+
// _PyInterpreterFrame
206204
//
207205
// We need to initialize the f_code, f_funcobj fields of
208206
// the frame along w/ the previous pointer.
@@ -319,10 +317,10 @@ void FrameAsm::linkLightWeightFunctionFrame(
319317
preserver.remap();
320318
}
321319
#else
322-
CINDER_UNSUPPORTED
320+
throw std::runtime_error{
321+
"linkLightWeightFunctionFrame: Lightweight frames are not supported"};
323322
#endif
324323
}
325-
#endif
326324

327325
void FrameAsm::linkNormalFunctionFrame(
328326
RegisterPreserver& preserver,
@@ -362,12 +360,10 @@ void FrameAsm::linkNormalFrame(
362360

363361
if (isGen()) {
364362
linkNormalGeneratorFrame(preserver, func_reg, tstate_reg);
365-
} else {
366-
#ifdef ENABLE_LIGHTWEIGHT_FRAMES
363+
} else if (getConfig().frame_mode == FrameMode::kLightweight) {
367364
linkLightWeightFunctionFrame(preserver, func_reg, tstate_reg);
368-
#else
365+
} else {
369366
linkNormalFunctionFrame(preserver, func_reg, tstate_reg);
370-
#endif
371367
}
372368
}
373369

@@ -442,21 +438,25 @@ void FrameAsm::generateLinkFrame(
442438
case FrameMode::kShadow:
443439
load_tstate_and_move();
444440
break;
445-
case FrameMode::kNormal: {
441+
case FrameMode::kNormal:
446442
linkNormalFrame(preserver, func_reg, tstate_reg);
447443
break;
448-
}
444+
case FrameMode::kLightweight:
445+
JIT_ABORT("Lightweight frames are not supported in 3.10");
446+
break;
449447
}
450448
}
449+
451450
#else
451+
452452
void FrameAsm::generateLinkFrame(
453453
const arch::Gp& func_reg,
454454
const arch::Gp& tstate_reg,
455455
const std::vector<std::pair<const arch::Reg&, const arch::Reg&>>&
456456
save_regs) {
457457
JIT_CHECK(
458-
GetFunction()->frameMode == FrameMode::kNormal,
459-
"3.12 only has normal frames");
458+
GetFunction()->frameMode != FrameMode::kShadow,
459+
"3.12 doesn't have shadow frames");
460460

461461
RegisterPreserver preserver(as_, save_regs);
462462

cinderx/Jit/codegen/gen_asm.cpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,8 @@ void raiseAttributeError(BorrowedRef<> receiver, BorrowedRef<> name) {
126126
name);
127127
}
128128

129-
#if defined(ENABLE_LIGHTWEIGHT_FRAMES)
129+
#if PY_VERSION_HEX >= 0x030C0000
130+
130131
// Helper to recursively reify the lightweight frames. We need to reify the
131132
// outermost lightweight frame first and work inwards to have the frames
132133
// allocated correctly on the slab. We then need to update the inner functions
@@ -157,6 +158,7 @@ _PyInterpreterFrame* reifyLightweightFrames(
157158
}
158159
return cur_frame;
159160
}
161+
160162
#endif
161163

162164
CiPyFrameObjType* prepareForDeopt(
@@ -184,14 +186,16 @@ CiPyFrameObjType* prepareForDeopt(
184186
}
185187
#else
186188
_PyInterpreterFrame* frame = interpFrameFromThreadState(tstate);
187-
#ifdef ENABLE_LIGHTWEIGHT_FRAMES
188-
frame = reifyLightweightFrames(
189-
tstate, deopt_meta, deopt_meta.inline_depth(), frame);
190-
if (frame == nullptr) {
191-
Py_FatalError("Cannot recover from OOM");
189+
190+
if (getConfig().frame_mode == FrameMode::kLightweight) {
191+
frame = reifyLightweightFrames(
192+
tstate, deopt_meta, deopt_meta.inline_depth(), frame);
193+
if (frame == nullptr) {
194+
Py_FatalError("Cannot recover from OOM");
195+
}
196+
setCurrentFrame(tstate, frame);
192197
}
193-
setCurrentFrame(tstate, frame);
194-
#endif
198+
195199
_PyInterpreterFrame* frame_iter = frame;
196200

197201
// Iterate one past the inline depth because that is the caller frame.
@@ -1877,6 +1881,8 @@ void NativeGenerator::generateCode(CodeHolder& codeholder) {
18771881
std::string_view prefix = [&] {
18781882
switch (func->frameMode) {
18791883
case FrameMode::kNormal:
1884+
[[fallthrough]];
1885+
case FrameMode::kLightweight:
18801886
return perf::kFuncSymbolPrefix;
18811887
case FrameMode::kShadow:
18821888
return perf::kShadowFrameSymbolPrefix;

cinderx/Jit/config.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ enum class State : uint8_t {
3131
enum class FrameMode : uint8_t {
3232
kNormal,
3333
kShadow,
34+
kLightweight,
3435
};
3536

3637
// List of HIR optimization passes to run.
@@ -127,7 +128,13 @@ struct Config {
127128
// Ignore other CLI arguments and environment variables, force the JIT
128129
// to be initialized or uninitialized. Intended for testing.
129130
std::optional<bool> force_init;
130-
FrameMode frame_mode{FrameMode::kNormal};
131+
FrameMode frame_mode{
132+
#ifdef ENABLE_LIGHTWEIGHT_FRAMES
133+
FrameMode::kLightweight
134+
#else
135+
FrameMode::kNormal
136+
#endif
137+
};
131138
bool allow_jit_list_wildcards{false};
132139
bool compile_all_static_functions{false};
133140
bool multiple_code_sections{false};

0 commit comments

Comments
 (0)