Skip to content

Commit fba5dde

Browse files
gh-134584: Decref elimination for float ops in the JIT (GH-134588)
This PR adds a PyJitRef API to the JIT's optimizer that mimics the _PyStackRef API. This allows it to track references and their stack lifetimes properly. Thus opening up the doorway to refcount elimination in the JIT.
1 parent 8dd8b5c commit fba5dde

File tree

14 files changed

+1027
-740
lines changed

14 files changed

+1027
-740
lines changed

Include/internal/pycore_optimizer.h

Lines changed: 75 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ extern "C" {
1010

1111
#include "pycore_typedefs.h" // _PyInterpreterFrame
1212
#include "pycore_uop_ids.h"
13+
#include "pycore_stackref.h"
1314
#include <stdbool.h>
1415

1516

@@ -220,15 +221,58 @@ typedef union _jit_opt_symbol {
220221
} JitOptSymbol;
221222

222223

224+
// This mimics the _PyStackRef API
225+
typedef union {
226+
uintptr_t bits;
227+
} JitOptRef;
228+
229+
#define REF_IS_BORROWED 1
230+
231+
#define JIT_BITS_TO_PTR_MASKED(REF) ((JitOptSymbol *)(((REF).bits) & (~REF_IS_BORROWED)))
232+
233+
static inline JitOptSymbol *
234+
PyJitRef_Unwrap(JitOptRef ref)
235+
{
236+
return JIT_BITS_TO_PTR_MASKED(ref);
237+
}
238+
239+
bool _Py_uop_symbol_is_immortal(JitOptSymbol *sym);
240+
241+
242+
static inline JitOptRef
243+
PyJitRef_Wrap(JitOptSymbol *sym)
244+
{
245+
return (JitOptRef){.bits=(uintptr_t)sym};
246+
}
247+
248+
static inline JitOptRef
249+
PyJitRef_Borrow(JitOptRef ref)
250+
{
251+
return (JitOptRef){ .bits = ref.bits | REF_IS_BORROWED };
252+
}
253+
254+
static const JitOptRef PyJitRef_NULL = {.bits = REF_IS_BORROWED};
255+
256+
static inline bool
257+
PyJitRef_IsNull(JitOptRef ref)
258+
{
259+
return ref.bits == PyJitRef_NULL.bits;
260+
}
261+
262+
static inline int
263+
PyJitRef_IsBorrowed(JitOptRef ref)
264+
{
265+
return (ref.bits & REF_IS_BORROWED) == REF_IS_BORROWED;
266+
}
223267

224268
struct _Py_UOpsAbstractFrame {
225269
// Max stacklen
226270
int stack_len;
227271
int locals_len;
228272

229-
JitOptSymbol **stack_pointer;
230-
JitOptSymbol **stack;
231-
JitOptSymbol **locals;
273+
JitOptRef *stack_pointer;
274+
JitOptRef *stack;
275+
JitOptRef *locals;
232276
};
233277

234278
typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame;
@@ -251,37 +295,36 @@ typedef struct _JitOptContext {
251295
// Arena for the symbolic types.
252296
ty_arena t_arena;
253297

254-
JitOptSymbol **n_consumed;
255-
JitOptSymbol **limit;
256-
JitOptSymbol *locals_and_stack[MAX_ABSTRACT_INTERP_SIZE];
298+
JitOptRef *n_consumed;
299+
JitOptRef *limit;
300+
JitOptRef locals_and_stack[MAX_ABSTRACT_INTERP_SIZE];
257301
} JitOptContext;
258302

259-
extern bool _Py_uop_sym_is_null(JitOptSymbol *sym);
260-
extern bool _Py_uop_sym_is_not_null(JitOptSymbol *sym);
261-
extern bool _Py_uop_sym_is_const(JitOptContext *ctx, JitOptSymbol *sym);
262-
extern PyObject *_Py_uop_sym_get_const(JitOptContext *ctx, JitOptSymbol *sym);
263-
extern JitOptSymbol *_Py_uop_sym_new_unknown(JitOptContext *ctx);
264-
extern JitOptSymbol *_Py_uop_sym_new_not_null(JitOptContext *ctx);
265-
extern JitOptSymbol *_Py_uop_sym_new_type(
303+
extern bool _Py_uop_sym_is_null(JitOptRef sym);
304+
extern bool _Py_uop_sym_is_not_null(JitOptRef sym);
305+
extern bool _Py_uop_sym_is_const(JitOptContext *ctx, JitOptRef sym);
306+
extern PyObject *_Py_uop_sym_get_const(JitOptContext *ctx, JitOptRef sym);
307+
extern JitOptRef _Py_uop_sym_new_unknown(JitOptContext *ctx);
308+
extern JitOptRef _Py_uop_sym_new_not_null(JitOptContext *ctx);
309+
extern JitOptRef _Py_uop_sym_new_type(
266310
JitOptContext *ctx, PyTypeObject *typ);
267-
extern JitOptSymbol *_Py_uop_sym_new_const(JitOptContext *ctx, PyObject *const_val);
268-
extern JitOptSymbol *_Py_uop_sym_new_null(JitOptContext *ctx);
269-
extern bool _Py_uop_sym_has_type(JitOptSymbol *sym);
270-
extern bool _Py_uop_sym_matches_type(JitOptSymbol *sym, PyTypeObject *typ);
271-
extern bool _Py_uop_sym_matches_type_version(JitOptSymbol *sym, unsigned int version);
272-
extern void _Py_uop_sym_set_null(JitOptContext *ctx, JitOptSymbol *sym);
273-
extern void _Py_uop_sym_set_non_null(JitOptContext *ctx, JitOptSymbol *sym);
274-
extern void _Py_uop_sym_set_type(JitOptContext *ctx, JitOptSymbol *sym, PyTypeObject *typ);
275-
extern bool _Py_uop_sym_set_type_version(JitOptContext *ctx, JitOptSymbol *sym, unsigned int version);
276-
extern void _Py_uop_sym_set_const(JitOptContext *ctx, JitOptSymbol *sym, PyObject *const_val);
277-
extern bool _Py_uop_sym_is_bottom(JitOptSymbol *sym);
278-
extern int _Py_uop_sym_truthiness(JitOptContext *ctx, JitOptSymbol *sym);
279-
extern PyTypeObject *_Py_uop_sym_get_type(JitOptSymbol *sym);
280-
extern bool _Py_uop_sym_is_immortal(JitOptSymbol *sym);
281-
extern JitOptSymbol *_Py_uop_sym_new_tuple(JitOptContext *ctx, int size, JitOptSymbol **args);
282-
extern JitOptSymbol *_Py_uop_sym_tuple_getitem(JitOptContext *ctx, JitOptSymbol *sym, int item);
283-
extern int _Py_uop_sym_tuple_length(JitOptSymbol *sym);
284-
extern JitOptSymbol *_Py_uop_sym_new_truthiness(JitOptContext *ctx, JitOptSymbol *value, bool truthy);
311+
extern JitOptRef _Py_uop_sym_new_const(JitOptContext *ctx, PyObject *const_val);
312+
extern JitOptRef _Py_uop_sym_new_null(JitOptContext *ctx);
313+
extern bool _Py_uop_sym_has_type(JitOptRef sym);
314+
extern bool _Py_uop_sym_matches_type(JitOptRef sym, PyTypeObject *typ);
315+
extern bool _Py_uop_sym_matches_type_version(JitOptRef sym, unsigned int version);
316+
extern void _Py_uop_sym_set_null(JitOptContext *ctx, JitOptRef sym);
317+
extern void _Py_uop_sym_set_non_null(JitOptContext *ctx, JitOptRef sym);
318+
extern void _Py_uop_sym_set_type(JitOptContext *ctx, JitOptRef sym, PyTypeObject *typ);
319+
extern bool _Py_uop_sym_set_type_version(JitOptContext *ctx, JitOptRef sym, unsigned int version);
320+
extern void _Py_uop_sym_set_const(JitOptContext *ctx, JitOptRef sym, PyObject *const_val);
321+
extern bool _Py_uop_sym_is_bottom(JitOptRef sym);
322+
extern int _Py_uop_sym_truthiness(JitOptContext *ctx, JitOptRef sym);
323+
extern PyTypeObject *_Py_uop_sym_get_type(JitOptRef sym);
324+
extern JitOptRef _Py_uop_sym_new_tuple(JitOptContext *ctx, int size, JitOptRef *args);
325+
extern JitOptRef _Py_uop_sym_tuple_getitem(JitOptContext *ctx, JitOptRef sym, int item);
326+
extern int _Py_uop_sym_tuple_length(JitOptRef sym);
327+
extern JitOptRef _Py_uop_sym_new_truthiness(JitOptContext *ctx, JitOptRef value, bool truthy);
285328

286329
extern void _Py_uop_abstractcontext_init(JitOptContext *ctx);
287330
extern void _Py_uop_abstractcontext_fini(JitOptContext *ctx);
@@ -290,7 +333,7 @@ extern _Py_UOpsAbstractFrame *_Py_uop_frame_new(
290333
JitOptContext *ctx,
291334
PyCodeObject *co,
292335
int curr_stackentries,
293-
JitOptSymbol **args,
336+
JitOptRef *args,
294337
int arg_len);
295338
extern int _Py_uop_frame_pop(JitOptContext *ctx);
296339

0 commit comments

Comments
 (0)