Skip to content

Commit 8f62067

Browse files
Massive refactor from JitOptSymbol to JitRef
1 parent 1535133 commit 8f62067

File tree

7 files changed

+1189
-1168
lines changed

7 files changed

+1189
-1168
lines changed

Include/internal/pycore_optimizer.h

Lines changed: 82 additions & 48 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

@@ -180,13 +181,10 @@ typedef enum _JitSymType {
180181
JIT_SYM_TRUTHINESS_TAG = 9,
181182
} JitSymType;
182183

183-
#define DONT_SKIP_REFCOUNT 0
184-
#define SKIP_REFCOUNT 1
185184

186185
typedef struct _jit_opt_known_class {
187186
struct {
188187
uint8_t tag;
189-
uint8_t skip_refcount;
190188
};
191189
uint32_t version;
192190
PyTypeObject *type;
@@ -195,15 +193,13 @@ typedef struct _jit_opt_known_class {
195193
typedef struct _jit_opt_known_version {
196194
struct {
197195
uint8_t tag;
198-
uint8_t skip_refcount;
199196
};
200197
uint32_t version;
201198
} JitOptKnownVersion;
202199

203200
typedef struct _jit_opt_known_value {
204201
struct {
205202
uint8_t tag;
206-
uint8_t skip_refcount;
207203
};
208204
PyObject *value;
209205
} JitOptKnownValue;
@@ -213,7 +209,6 @@ typedef struct _jit_opt_known_value {
213209
typedef struct _jit_opt_tuple {
214210
struct {
215211
uint8_t tag;
216-
uint8_t skip_refcount;
217212
};
218213
uint8_t length;
219214
uint16_t items[MAX_SYMBOLIC_TUPLE_SIZE];
@@ -222,7 +217,6 @@ typedef struct _jit_opt_tuple {
222217
typedef struct {
223218
struct {
224219
uint8_t tag;
225-
uint8_t skip_refcount;
226220
};
227221
bool invert;
228222
uint16_t value;
@@ -231,11 +225,6 @@ typedef struct {
231225
typedef union _jit_opt_symbol {
232226
struct {
233227
uint8_t tag;
234-
// Whether this object skips refcount on the stack
235-
// (using the _PyStackRef API), or not.
236-
// 0 - normal refcounting
237-
// 1 - skip refcounting
238-
int8_t skip_refcount;
239228
};
240229
JitOptKnownClass cls;
241230
JitOptKnownValue value;
@@ -245,15 +234,65 @@ typedef union _jit_opt_symbol {
245234
} JitOptSymbol;
246235

247236

237+
// This mimics the _PyStackRef API
238+
typedef union {
239+
uintptr_t bits;
240+
} JitOptRef;
241+
242+
#define JIT_BITS_TO_PTR(REF) ((JitOptSymbol *)((REF).bits))
243+
#define JIT_BITS_TO_PTR_MASKED(REF) ((JitOptSymbol *)(((REF).bits) & (~Py_TAG_REFCNT)))
244+
245+
static inline JitOptSymbol *
246+
PyJitRef_AsSymbolBorrow(JitOptRef ref)
247+
{
248+
return JIT_BITS_TO_PTR_MASKED(ref);
249+
}
250+
251+
bool _Py_uop_sym_is_immortal(JitOptSymbol *sym);
252+
253+
static inline JitOptRef
254+
PyJitRef_FromSymbolSteal(JitOptSymbol *sym)
255+
{
256+
if (sym == NULL || _Py_uop_sym_is_immortal(sym)) {
257+
return (JitOptRef){.bits=(uintptr_t)sym | Py_TAG_REFCNT};
258+
}
259+
return (JitOptRef){.bits=(uintptr_t)sym};
260+
}
261+
262+
static inline JitOptRef
263+
PyJitRef_FromSymbolBorrow(JitOptSymbol *sym)
264+
{
265+
return (JitOptRef){.bits=(uintptr_t)sym | Py_TAG_REFCNT};
266+
}
267+
268+
static inline JitOptRef
269+
PyJitRef_Borrow(JitOptRef ref)
270+
{
271+
return (JitOptRef){ .bits = ref.bits | Py_TAG_REFCNT };
272+
}
273+
274+
static const JitOptRef PyJitRef_NULL = { .bits = PyStackRef_NULL_BITS };
275+
276+
static inline bool
277+
PyJitRef_IsNull(JitOptRef ref)
278+
{
279+
return ref.bits == PyStackRef_NULL_BITS;
280+
}
281+
282+
static inline int
283+
PyJitRef_IsBorrowed(JitOptRef ref)
284+
{
285+
return (ref.bits & Py_TAG_REFCNT) == Py_TAG_REFCNT;
286+
}
248287

249288
struct _Py_UOpsAbstractFrame {
250289
// Max stacklen
251290
int stack_len;
252291
int locals_len;
253292

254-
JitOptSymbol **stack_pointer;
255-
JitOptSymbol **stack;
256-
JitOptSymbol **locals;
293+
JitOptRef *stack_pointer;
294+
JitOptRef *stack;
295+
JitOptRef *locals;
257296
};
258297

259298
typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame;
@@ -276,41 +315,36 @@ typedef struct _JitOptContext {
276315
// Arena for the symbolic types.
277316
ty_arena t_arena;
278317

279-
JitOptSymbol **n_consumed;
280-
JitOptSymbol **limit;
281-
JitOptSymbol *locals_and_stack[MAX_ABSTRACT_INTERP_SIZE];
318+
JitOptRef *n_consumed;
319+
JitOptRef *limit;
320+
JitOptRef locals_and_stack[MAX_ABSTRACT_INTERP_SIZE];
282321
} JitOptContext;
283322

284-
extern bool _Py_uop_sym_is_null(JitOptSymbol *sym);
285-
extern bool _Py_uop_sym_is_not_null(JitOptSymbol *sym);
286-
extern bool _Py_uop_sym_is_const(JitOptContext *ctx, JitOptSymbol *sym);
287-
extern PyObject *_Py_uop_sym_get_const(JitOptContext *ctx, JitOptSymbol *sym);
288-
extern JitOptSymbol *_Py_uop_sym_new_unknown(JitOptContext *ctx);
289-
extern JitOptSymbol *_Py_uop_sym_new_not_null(JitOptContext *ctx);
290-
extern JitOptSymbol *_Py_uop_sym_new_type(
323+
extern bool _Py_uop_ref_is_null(JitOptRef sym);
324+
extern bool _Py_uop_ref_is_not_null(JitOptRef sym);
325+
extern bool _Py_uop_ref_is_const(JitOptContext *ctx, JitOptRef sym);
326+
extern PyObject *_Py_uop_ref_get_const(JitOptContext *ctx, JitOptRef sym);
327+
extern JitOptRef _Py_uop_ref_new_unknown(JitOptContext *ctx);
328+
extern JitOptRef _Py_uop_ref_new_not_null(JitOptContext *ctx);
329+
extern JitOptRef _Py_uop_ref_new_type(
291330
JitOptContext *ctx, PyTypeObject *typ);
292-
extern JitOptSymbol *_Py_uop_sym_new_const(JitOptContext *ctx, PyObject *const_val);
293-
extern JitOptSymbol *_Py_uop_sym_new_null(JitOptContext *ctx);
294-
extern bool _Py_uop_sym_has_type(JitOptSymbol *sym);
295-
extern bool _Py_uop_sym_matches_type(JitOptSymbol *sym, PyTypeObject *typ);
296-
extern bool _Py_uop_sym_matches_type_version(JitOptSymbol *sym, unsigned int version);
297-
extern void _Py_uop_sym_set_null(JitOptContext *ctx, JitOptSymbol *sym);
298-
extern void _Py_uop_sym_set_non_null(JitOptContext *ctx, JitOptSymbol *sym);
299-
extern void _Py_uop_sym_set_type(JitOptContext *ctx, JitOptSymbol *sym, PyTypeObject *typ);
300-
extern bool _Py_uop_sym_set_type_version(JitOptContext *ctx, JitOptSymbol *sym, unsigned int version);
301-
extern void _Py_uop_sym_set_const(JitOptContext *ctx, JitOptSymbol *sym, PyObject *const_val);
302-
extern bool _Py_uop_sym_is_bottom(JitOptSymbol *sym);
303-
extern int _Py_uop_sym_truthiness(JitOptContext *ctx, JitOptSymbol *sym);
304-
extern PyTypeObject *_Py_uop_sym_get_type(JitOptSymbol *sym);
305-
extern bool _Py_uop_sym_is_immortal(JitOptSymbol *sym);
306-
extern JitOptSymbol *_Py_uop_sym_new_tuple(JitOptContext *ctx, int size, JitOptSymbol **args);
307-
extern JitOptSymbol *_Py_uop_sym_tuple_getitem(JitOptContext *ctx, JitOptSymbol *sym, int item);
308-
extern int _Py_uop_sym_tuple_length(JitOptSymbol *sym);
309-
extern JitOptSymbol *_Py_uop_sym_new_truthiness(JitOptContext *ctx, JitOptSymbol *value, bool truthy);
310-
311-
extern void _Py_uop_sym_set_dont_skip_refcount(JitOptContext *ctx, JitOptSymbol *sym);
312-
extern bool _Py_uop_sym_is_skip_refcount(JitOptContext *ctx, JitOptSymbol *sym);
313-
extern void _Py_uop_sym_set_skip_refcount(JitOptContext *ctx, JitOptSymbol *sym);
331+
extern JitOptRef _Py_uop_ref_new_const(JitOptContext *ctx, PyObject *const_val);
332+
extern JitOptRef _Py_uop_ref_new_null(JitOptContext *ctx);
333+
extern bool _Py_uop_ref_has_type(JitOptRef sym);
334+
extern bool _Py_uop_ref_matches_type(JitOptRef sym, PyTypeObject *typ);
335+
extern bool _Py_uop_ref_matches_type_version(JitOptRef sym, unsigned int version);
336+
extern void _Py_uop_ref_set_null(JitOptContext *ctx, JitOptRef sym);
337+
extern void _Py_uop_ref_set_non_null(JitOptContext *ctx, JitOptRef sym);
338+
extern void _Py_uop_ref_set_type(JitOptContext *ctx, JitOptRef sym, PyTypeObject *typ);
339+
extern bool _Py_uop_ref_set_type_version(JitOptContext *ctx, JitOptRef sym, unsigned int version);
340+
extern void _Py_uop_ref_set_const(JitOptContext *ctx, JitOptRef sym, PyObject *const_val);
341+
extern bool _Py_uop_ref_is_bottom(JitOptRef sym);
342+
extern int _Py_uop_ref_truthiness(JitOptContext *ctx, JitOptRef sym);
343+
extern PyTypeObject *_Py_uop_ref_get_type(JitOptRef sym);
344+
extern JitOptRef _Py_uop_ref_new_tuple(JitOptContext *ctx, int size, JitOptRef *args);
345+
extern JitOptRef _Py_uop_ref_tuple_getitem(JitOptContext *ctx, JitOptRef sym, int item);
346+
extern int _Py_uop_ref_tuple_length(JitOptRef sym);
347+
extern JitOptRef _Py_uop_ref_new_truthiness(JitOptContext *ctx, JitOptRef value, bool truthy);
314348

315349
extern void _Py_uop_abstractcontext_init(JitOptContext *ctx);
316350
extern void _Py_uop_abstractcontext_fini(JitOptContext *ctx);
@@ -319,7 +353,7 @@ extern _Py_UOpsAbstractFrame *_Py_uop_frame_new(
319353
JitOptContext *ctx,
320354
PyCodeObject *co,
321355
int curr_stackentries,
322-
JitOptSymbol **args,
356+
JitOptRef *args,
323357
int arg_len);
324358
extern int _Py_uop_frame_pop(JitOptContext *ctx);
325359

Python/optimizer_analysis.c

Lines changed: 34 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -315,54 +315,51 @@ remove_globals(_PyInterpreterFrame *frame, _PyUOpInstruction *buffer,
315315
INST->operand0 = OPERAND;
316316

317317
/* Shortened forms for convenience, used in optimizer_bytecodes.c */
318-
#define sym_is_not_null _Py_uop_sym_is_not_null
319-
#define sym_is_const _Py_uop_sym_is_const
320-
#define sym_get_const _Py_uop_sym_get_const
321-
#define sym_new_unknown _Py_uop_sym_new_unknown
322-
#define sym_new_not_null _Py_uop_sym_new_not_null
323-
#define sym_new_type _Py_uop_sym_new_type
324-
#define sym_is_null _Py_uop_sym_is_null
325-
#define sym_new_const _Py_uop_sym_new_const
326-
#define sym_new_null _Py_uop_sym_new_null
327-
#define sym_has_type _Py_uop_sym_has_type
328-
#define sym_get_type _Py_uop_sym_get_type
329-
#define sym_matches_type _Py_uop_sym_matches_type
330-
#define sym_matches_type_version _Py_uop_sym_matches_type_version
331-
#define sym_set_null(SYM) _Py_uop_sym_set_null(ctx, SYM)
332-
#define sym_set_non_null(SYM) _Py_uop_sym_set_non_null(ctx, SYM)
333-
#define sym_set_type(SYM, TYPE) _Py_uop_sym_set_type(ctx, SYM, TYPE)
334-
#define sym_set_type_version(SYM, VERSION) _Py_uop_sym_set_type_version(ctx, SYM, VERSION)
335-
#define sym_set_const(SYM, CNST) _Py_uop_sym_set_const(ctx, SYM, CNST)
336-
#define sym_is_bottom _Py_uop_sym_is_bottom
337-
#define sym_truthiness _Py_uop_sym_truthiness
318+
#define ref_is_not_null _Py_uop_ref_is_not_null
319+
#define ref_is_const _Py_uop_ref_is_const
320+
#define ref_get_const _Py_uop_ref_get_const
321+
#define ref_new_unknown _Py_uop_ref_new_unknown
322+
#define ref_new_not_null _Py_uop_ref_new_not_null
323+
#define ref_new_type _Py_uop_ref_new_type
324+
#define ref_is_null _Py_uop_ref_is_null
325+
#define ref_new_const _Py_uop_ref_new_const
326+
#define ref_new_null _Py_uop_ref_new_null
327+
#define ref_has_type _Py_uop_ref_has_type
328+
#define ref_get_type _Py_uop_ref_get_type
329+
#define ref_matches_type _Py_uop_ref_matches_type
330+
#define ref_matches_type_version _Py_uop_ref_matches_type_version
331+
#define ref_set_null(SYM) _Py_uop_ref_set_null(ctx, SYM)
332+
#define ref_set_non_null(SYM) _Py_uop_ref_set_non_null(ctx, SYM)
333+
#define ref_set_type(SYM, TYPE) _Py_uop_ref_set_type(ctx, SYM, TYPE)
334+
#define ref_set_type_version(SYM, VERSION) _Py_uop_ref_set_type_version(ctx, SYM, VERSION)
335+
#define ref_set_const(SYM, CNST) _Py_uop_ref_set_const(ctx, SYM, CNST)
336+
#define ref_is_bottom _Py_uop_ref_is_bottom
337+
#define ref_truthiness _Py_uop_ref_truthiness
338338
#define frame_new _Py_uop_frame_new
339339
#define frame_pop _Py_uop_frame_pop
340-
#define sym_new_tuple _Py_uop_sym_new_tuple
341-
#define sym_tuple_getitem _Py_uop_sym_tuple_getitem
342-
#define sym_tuple_length _Py_uop_sym_tuple_length
343-
#define sym_is_immortal _Py_uop_sym_is_immortal
344-
#define sym_new_truthiness _Py_uop_sym_new_truthiness
345-
#define sym_set_skip_refcount _Py_uop_sym_set_skip_refcount
346-
#define sym_set_dont_skip_refcount _Py_uop_sym_set_dont_skip_refcount
347-
#define sym_is_skip_refcount _Py_uop_sym_is_skip_refcount
340+
#define ref_new_tuple _Py_uop_ref_new_tuple
341+
#define ref_tuple_getitem _Py_uop_ref_tuple_getitem
342+
#define ref_tuple_length _Py_uop_ref_tuple_length
343+
#define ref_is_immortal _Py_uop_ref_is_immortal
344+
#define ref_new_truthiness _Py_uop_ref_new_truthiness
348345

349346
static int
350347
optimize_to_bool(
351348
_PyUOpInstruction *this_instr,
352349
JitOptContext *ctx,
353-
JitOptSymbol *value,
354-
JitOptSymbol **result_ptr)
350+
JitOptRef value,
351+
JitOptRef *result_ptr)
355352
{
356-
if (sym_matches_type(value, &PyBool_Type)) {
353+
if (ref_matches_type(value, &PyBool_Type)) {
357354
REPLACE_OP(this_instr, _NOP, 0, 0);
358355
*result_ptr = value;
359356
return 1;
360357
}
361-
int truthiness = sym_truthiness(ctx, value);
358+
int truthiness = ref_truthiness(ctx, value);
362359
if (truthiness >= 0) {
363360
PyObject *load = truthiness ? Py_True : Py_False;
364361
REPLACE_OP(this_instr, _POP_TOP_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)load);
365-
*result_ptr = sym_new_const(ctx, load);
362+
*result_ptr = ref_new_const(ctx, load);
366363
return 1;
367364
}
368365
return 0;
@@ -378,7 +375,7 @@ eliminate_pop_guard(_PyUOpInstruction *this_instr, bool exit)
378375
}
379376
}
380377

381-
static JitOptSymbol *
378+
static JitOptRef
382379
lookup_attr(JitOptContext *ctx, _PyUOpInstruction *this_instr,
383380
PyTypeObject *type, PyObject *name, uint16_t immortal,
384381
uint16_t mortal)
@@ -389,10 +386,10 @@ lookup_attr(JitOptContext *ctx, _PyUOpInstruction *this_instr,
389386
if (lookup) {
390387
int opcode = _Py_IsImmortal(lookup) ? immortal : mortal;
391388
REPLACE_OP(this_instr, opcode, 0, (uintptr_t)lookup);
392-
return sym_new_const(ctx, lookup);
389+
return ref_new_const(ctx, lookup);
393390
}
394391
}
395-
return sym_new_not_null(ctx);
392+
return ref_new_not_null(ctx);
396393
}
397394

398395
/* _PUSH_FRAME/_RETURN_VALUE's operand can be 0, a PyFunctionObject *, or a
@@ -487,7 +484,7 @@ optimize_uops(
487484

488485
int oparg = this_instr->oparg;
489486
opcode = this_instr->opcode;
490-
JitOptSymbol **stack_pointer = ctx->frame->stack_pointer;
487+
JitOptRef *stack_pointer = ctx->frame->stack_pointer;
491488

492489
#ifdef Py_DEBUG
493490
if (get_lltrace() >= 3) {

0 commit comments

Comments
 (0)