Skip to content

Commit 56149ae

Browse files
committed
Handle symbolic constants in tuple queries
1 parent 307ba6c commit 56149ae

File tree

2 files changed

+40
-12
lines changed

2 files changed

+40
-12
lines changed

Include/internal/pycore_optimizer.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -189,8 +189,7 @@ static inline uint16_t uop_get_error_target(const _PyUOpInstruction *inst)
189189

190190

191191
typedef enum _JitSymType {
192-
JIT_SYM_UNKNOWN_TAG = 0,
193-
192+
JIT_SYM_UNKNOWN_TAG = 1,
194193
JIT_SYM_NULL_TAG = 2,
195194
JIT_SYM_NON_NULL_TAG = 3,
196195
JIT_SYM_BOTTOM_TAG = 4,
@@ -216,10 +215,12 @@ typedef struct _jit_opt_known_value {
216215
PyObject *value;
217216
} JitOptKnownValue;
218217

218+
#define MAX_SYMBOLIC_TUPLE_SIZE 7
219+
219220
typedef struct _jit_opt_tuple {
220221
uint8_t tag;
221222
uint8_t length;
222-
uint16_t items[6];
223+
uint16_t items[MAX_SYMBOLIC_TUPLE_SIZE];
223224
} JitOptTuple;
224225

225226
typedef union _jit_opt_symbol {
@@ -231,6 +232,7 @@ typedef union _jit_opt_symbol {
231232
} JitOptSymbol;
232233

233234

235+
234236
struct _Py_UOpsAbstractFrame {
235237
// Max stacklen
236238
int stack_len;

Python/optimizer_symbols.c

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,11 @@ _Py_uop_sym_set_non_null(JitOptContext *ctx, JitOptSymbol *sym)
269269
JitOptSymbol *
270270
_Py_uop_sym_new_unknown(JitOptContext *ctx)
271271
{
272-
return sym_new(ctx);
272+
JitOptSymbol *res = sym_new(ctx);
273+
if (res == NULL) {
274+
return out_of_space(ctx);
275+
}
276+
return res;
273277
}
274278

275279
JitOptSymbol *
@@ -444,7 +448,7 @@ _Py_uop_sym_new_tuple(JitOptContext *ctx, int size, JitOptSymbol **args)
444448
if (res == NULL) {
445449
return out_of_space(ctx);
446450
}
447-
if (size > 6) {
451+
if (size > MAX_SYMBOLIC_TUPLE_SIZE) {
448452
res->tag = JIT_SYM_KNOWN_CLASS_TAG;
449453
res->cls.type = &PyTuple_Type;
450454
}
@@ -461,20 +465,32 @@ _Py_uop_sym_new_tuple(JitOptContext *ctx, int size, JitOptSymbol **args)
461465
JitOptSymbol *
462466
_Py_uop_sym_tuple_getitem(JitOptContext *ctx, JitOptSymbol *sym, int item)
463467
{
464-
465-
if (sym->tag != JIT_SYM_TUPLE_TAG || item < 0 || item >= sym->tuple.length) {
466-
return _Py_uop_sym_new_unknown(ctx);
468+
assert(item >= 0);
469+
if (sym->tag == JIT_SYM_KNOWN_VALUE_TAG) {
470+
PyObject *tuple = sym->value.value;
471+
if (PyTuple_CheckExact(tuple) && item < PyTuple_GET_SIZE(tuple)) {
472+
return _Py_uop_sym_new_const(ctx, PyTuple_GET_ITEM(tuple, item));
473+
}
474+
}
475+
else if (sym->tag == JIT_SYM_TUPLE_TAG && item < sym->tuple.length) {
476+
return allocation_base(ctx) + sym->tuple.items[item];
467477
}
468-
return allocation_base(ctx) + sym->tuple.items[item];
478+
return _Py_uop_sym_new_unknown(ctx);
469479
}
470480

471481
int
472482
_Py_uop_sym_tuple_length(JitOptSymbol *sym)
473483
{
474-
if (sym->tag != JIT_SYM_TUPLE_TAG) {
475-
return -1;
484+
if (sym->tag == JIT_SYM_KNOWN_VALUE_TAG) {
485+
PyObject *tuple = sym->value.value;
486+
if (PyTuple_CheckExact(tuple)) {
487+
return PyTuple_GET_SIZE(tuple);
488+
}
476489
}
477-
return sym->tuple.length;
490+
else if (sym->tag == JIT_SYM_TUPLE_TAG) {
491+
return sym->tuple.length;
492+
}
493+
return -1;
478494
}
479495

480496

@@ -542,6 +558,7 @@ _Py_uop_abstractcontext_fini(JitOptContext *ctx)
542558
void
543559
_Py_uop_abstractcontext_init(JitOptContext *ctx)
544560
{
561+
static_assert(sizeof(JitOptSymbol) <= 2*sizeof(uint64_t));
545562
ctx->limit = ctx->locals_and_stack + MAX_ABSTRACT_INTERP_SIZE;
546563
ctx->n_consumed = ctx->locals_and_stack;
547564
#ifdef Py_DEBUG // Aids debugging a little. There should never be NULL in the abstract interpreter.
@@ -694,16 +711,25 @@ _Py_uop_symbols_test(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
694711
_Py_uop_sym_get_const(_Py_uop_sym_tuple_getitem(ctx, sym, 1)) == val_43,
695712
"tuple item does not match value used to create tuple"
696713
);
714+
PyObject *pair[2] = { val_42, val_43 };
715+
PyObject *tuple = _PyTuple_FromArray(pair, 2);
716+
sym = _Py_uop_sym_new_const(ctx, tuple);
717+
TEST_PREDICATE(
718+
_Py_uop_sym_get_const(_Py_uop_sym_tuple_getitem(ctx, sym, 1)) == val_43,
719+
"tuple item does not match value used to create tuple"
720+
);
697721

698722
_Py_uop_abstractcontext_fini(ctx);
699723
Py_DECREF(val_42);
700724
Py_DECREF(val_43);
725+
Py_DECREF(tuple);
701726
Py_RETURN_NONE;
702727

703728
fail:
704729
_Py_uop_abstractcontext_fini(ctx);
705730
Py_XDECREF(val_42);
706731
Py_XDECREF(val_43);
732+
Py_DECREF(tuple);
707733
return NULL;
708734
}
709735

0 commit comments

Comments
 (0)