Skip to content

Commit e36f8db

Browse files
gh-143414: Implement unique reference tracking for JIT, optimize unpacking of such tuples (GH-144300)
Co-authored-by: Ken Jin <kenjin4096@gmail.com>
1 parent 1ceb1fb commit e36f8db

File tree

13 files changed

+1414
-911
lines changed

13 files changed

+1414
-911
lines changed

Include/internal/pycore_optimizer.h

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -290,9 +290,13 @@ static inline uint16_t uop_get_error_target(const _PyUOpInstruction *inst)
290290

291291

292292
#define REF_IS_BORROWED 1
293-
#define REF_IS_INVALID 2
293+
#define REF_IS_UNIQUE 2
294+
#define REF_IS_INVALID 3
294295
#define REF_TAG_BITS 3
295296

297+
#define REF_GET_TAG(x) ((uintptr_t)(x) & (REF_TAG_BITS))
298+
#define REF_CLEAR_TAG(x) ((uintptr_t)(x) & (~REF_TAG_BITS))
299+
296300
#define JIT_BITS_TO_PTR_MASKED(REF) ((JitOptSymbol *)(((REF).bits) & (~REF_TAG_BITS)))
297301

298302
static inline JitOptSymbol *
@@ -313,13 +317,34 @@ PyJitRef_Wrap(JitOptSymbol *sym)
313317
static inline JitOptRef
314318
PyJitRef_WrapInvalid(void *ptr)
315319
{
316-
return (JitOptRef){.bits=(uintptr_t)ptr | REF_IS_INVALID};
320+
return (JitOptRef){.bits = REF_CLEAR_TAG((uintptr_t)ptr) | REF_IS_INVALID};
317321
}
318322

319323
static inline bool
320324
PyJitRef_IsInvalid(JitOptRef ref)
321325
{
322-
return (ref.bits & REF_IS_INVALID) == REF_IS_INVALID;
326+
return REF_GET_TAG(ref.bits) == REF_IS_INVALID;
327+
}
328+
329+
static inline JitOptRef
330+
PyJitRef_MakeUnique(JitOptRef ref)
331+
{
332+
return (JitOptRef){ REF_CLEAR_TAG(ref.bits) | REF_IS_UNIQUE };
333+
}
334+
335+
static inline bool
336+
PyJitRef_IsUnique(JitOptRef ref)
337+
{
338+
return REF_GET_TAG(ref.bits) == REF_IS_UNIQUE;
339+
}
340+
341+
static inline JitOptRef
342+
PyJitRef_StripBorrowInfo(JitOptRef ref)
343+
{
344+
if (PyJitRef_IsUnique(ref)) {
345+
return ref;
346+
}
347+
return (JitOptRef){ .bits = REF_CLEAR_TAG(ref.bits) };
323348
}
324349

325350
static inline JitOptRef
@@ -328,10 +353,19 @@ PyJitRef_StripReferenceInfo(JitOptRef ref)
328353
return PyJitRef_Wrap(PyJitRef_Unwrap(ref));
329354
}
330355

356+
static inline JitOptRef
357+
PyJitRef_RemoveUnique(JitOptRef ref)
358+
{
359+
if (PyJitRef_IsUnique(ref)) {
360+
ref = PyJitRef_StripReferenceInfo(ref);
361+
}
362+
return ref;
363+
}
364+
331365
static inline JitOptRef
332366
PyJitRef_Borrow(JitOptRef ref)
333367
{
334-
return (JitOptRef){ .bits = ref.bits | REF_IS_BORROWED };
368+
return (JitOptRef){ .bits = REF_CLEAR_TAG(ref.bits) | REF_IS_BORROWED };
335369
}
336370

337371
static const JitOptRef PyJitRef_NULL = {.bits = REF_IS_BORROWED};
@@ -345,7 +379,7 @@ PyJitRef_IsNull(JitOptRef ref)
345379
static inline int
346380
PyJitRef_IsBorrowed(JitOptRef ref)
347381
{
348-
return (ref.bits & REF_IS_BORROWED) == REF_IS_BORROWED;
382+
return REF_GET_TAG(ref.bits) == REF_IS_BORROWED;
349383
}
350384

351385
extern bool _Py_uop_sym_is_null(JitOptRef sym);

Include/internal/pycore_tuple.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ extern PyStatus _PyTuple_InitGlobalObjects(PyInterpreterState *);
2121

2222
/* other API */
2323

24+
PyAPI_FUNC(void) _PyStolenTuple_Free(PyObject *self);
25+
2426
#define _PyTuple_ITEMS(op) _Py_RVALUE(_PyTuple_CAST(op)->ob_item)
2527

2628
PyAPI_FUNC(PyObject *)_PyTuple_FromStackRefStealOnSuccess(const union _PyStackRef *, Py_ssize_t);

0 commit comments

Comments
 (0)