extern PyTypeObject _PyUOpExecutor_Type;
extern PyTypeObject _PyUOpOptimizer_Type;
-/* Symbols */
-/* See explanation in optimizer_symbols.c */
-
-struct _Py_UopsSymbol {
- int flags; // 0 bits: Top; 2 or more bits: Bottom
- PyTypeObject *typ; // Borrowed reference
- PyObject *const_val; // Owned reference (!)
- unsigned int type_version; // currently stores type version
-};
#define UOP_FORMAT_TARGET 0
#define UOP_FORMAT_JUMP 1
// handle before rejoining the rest of the program.
#define MAX_CHAIN_DEPTH 4
-typedef struct _Py_UopsSymbol _Py_UopsSymbol;
+/* Symbols */
+/* See explanation in optimizer_symbols.c */
+
+
+typedef enum _JitSymType {
+ JIT_SYM_UNKNOWN_TAG = 1,
+ JIT_SYM_NULL_TAG = 2,
+ JIT_SYM_NON_NULL_TAG = 3,
+ JIT_SYM_BOTTOM_TAG = 4,
+ JIT_SYM_TYPE_VERSION_TAG = 5,
+ JIT_SYM_KNOWN_CLASS_TAG = 6,
+ JIT_SYM_KNOWN_VALUE_TAG = 7,
+ JIT_SYM_TUPLE_TAG = 8,
+} JitSymType;
+
+typedef struct _jit_opt_known_class {
+ uint8_t tag;
+ uint32_t version;
+ PyTypeObject *type;
+} JitOptKnownClass;
+
+typedef struct _jit_opt_known_version {
+ uint8_t tag;
+ uint32_t version;
+} JitOptKnownVersion;
+
+typedef struct _jit_opt_known_value {
+ uint8_t tag;
+ PyObject *value;
+} JitOptKnownValue;
+
+#define MAX_SYMBOLIC_TUPLE_SIZE 7
+
+typedef struct _jit_opt_tuple {
+ uint8_t tag;
+ uint8_t length;
+ uint16_t items[MAX_SYMBOLIC_TUPLE_SIZE];
+} JitOptTuple;
+
+typedef union _jit_opt_symbol {
+ uint8_t tag;
+ JitOptKnownClass cls;
+ JitOptKnownValue value;
+ JitOptKnownVersion version;
+ JitOptTuple tuple;
+} JitOptSymbol;
+
+
struct _Py_UOpsAbstractFrame {
// Max stacklen
int stack_len;
int locals_len;
- _Py_UopsSymbol **stack_pointer;
- _Py_UopsSymbol **stack;
- _Py_UopsSymbol **locals;
+ JitOptSymbol **stack_pointer;
+ JitOptSymbol **stack;
+ JitOptSymbol **locals;
};
typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame;
typedef struct ty_arena {
int ty_curr_number;
int ty_max_number;
- _Py_UopsSymbol arena[TY_ARENA_SIZE];
+ JitOptSymbol arena[TY_ARENA_SIZE];
} ty_arena;
-struct _Py_UOpsContext {
+typedef struct _JitOptContext {
char done;
char out_of_space;
bool contradiction;
// Arena for the symbolic types.
ty_arena t_arena;
- _Py_UopsSymbol **n_consumed;
- _Py_UopsSymbol **limit;
- _Py_UopsSymbol *locals_and_stack[MAX_ABSTRACT_INTERP_SIZE];
-};
-
-typedef struct _Py_UOpsContext _Py_UOpsContext;
-
-extern bool _Py_uop_sym_is_null(_Py_UopsSymbol *sym);
-extern bool _Py_uop_sym_is_not_null(_Py_UopsSymbol *sym);
-extern bool _Py_uop_sym_is_const(_Py_UopsSymbol *sym);
-extern PyObject *_Py_uop_sym_get_const(_Py_UopsSymbol *sym);
-extern _Py_UopsSymbol *_Py_uop_sym_new_unknown(_Py_UOpsContext *ctx);
-extern _Py_UopsSymbol *_Py_uop_sym_new_not_null(_Py_UOpsContext *ctx);
-extern _Py_UopsSymbol *_Py_uop_sym_new_type(
- _Py_UOpsContext *ctx, PyTypeObject *typ);
-extern _Py_UopsSymbol *_Py_uop_sym_new_const(_Py_UOpsContext *ctx, PyObject *const_val);
-extern _Py_UopsSymbol *_Py_uop_sym_new_null(_Py_UOpsContext *ctx);
-extern bool _Py_uop_sym_has_type(_Py_UopsSymbol *sym);
-extern bool _Py_uop_sym_matches_type(_Py_UopsSymbol *sym, PyTypeObject *typ);
-extern bool _Py_uop_sym_matches_type_version(_Py_UopsSymbol *sym, unsigned int version);
-extern void _Py_uop_sym_set_null(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym);
-extern void _Py_uop_sym_set_non_null(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym);
-extern void _Py_uop_sym_set_type(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym, PyTypeObject *typ);
-extern bool _Py_uop_sym_set_type_version(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym, unsigned int version);
-extern void _Py_uop_sym_set_const(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym, PyObject *const_val);
-extern bool _Py_uop_sym_is_bottom(_Py_UopsSymbol *sym);
-extern int _Py_uop_sym_truthiness(_Py_UopsSymbol *sym);
-extern PyTypeObject *_Py_uop_sym_get_type(_Py_UopsSymbol *sym);
-
-
-extern void _Py_uop_abstractcontext_init(_Py_UOpsContext *ctx);
-extern void _Py_uop_abstractcontext_fini(_Py_UOpsContext *ctx);
+ JitOptSymbol **n_consumed;
+ JitOptSymbol **limit;
+ JitOptSymbol *locals_and_stack[MAX_ABSTRACT_INTERP_SIZE];
+} JitOptContext;
+
+extern bool _Py_uop_sym_is_null(JitOptSymbol *sym);
+extern bool _Py_uop_sym_is_not_null(JitOptSymbol *sym);
+extern bool _Py_uop_sym_is_const(JitOptSymbol *sym);
+extern PyObject *_Py_uop_sym_get_const(JitOptSymbol *sym);
+extern JitOptSymbol *_Py_uop_sym_new_unknown(JitOptContext *ctx);
+extern JitOptSymbol *_Py_uop_sym_new_not_null(JitOptContext *ctx);
+extern JitOptSymbol *_Py_uop_sym_new_type(
+ JitOptContext *ctx, PyTypeObject *typ);
+extern JitOptSymbol *_Py_uop_sym_new_const(JitOptContext *ctx, PyObject *const_val);
+extern JitOptSymbol *_Py_uop_sym_new_null(JitOptContext *ctx);
+extern bool _Py_uop_sym_has_type(JitOptSymbol *sym);
+extern bool _Py_uop_sym_matches_type(JitOptSymbol *sym, PyTypeObject *typ);
+extern bool _Py_uop_sym_matches_type_version(JitOptSymbol *sym, unsigned int version);
+extern void _Py_uop_sym_set_null(JitOptContext *ctx, JitOptSymbol *sym);
+extern void _Py_uop_sym_set_non_null(JitOptContext *ctx, JitOptSymbol *sym);
+extern void _Py_uop_sym_set_type(JitOptContext *ctx, JitOptSymbol *sym, PyTypeObject *typ);
+extern bool _Py_uop_sym_set_type_version(JitOptContext *ctx, JitOptSymbol *sym, unsigned int version);
+extern void _Py_uop_sym_set_const(JitOptContext *ctx, JitOptSymbol *sym, PyObject *const_val);
+extern bool _Py_uop_sym_is_bottom(JitOptSymbol *sym);
+extern int _Py_uop_sym_truthiness(JitOptSymbol *sym);
+extern PyTypeObject *_Py_uop_sym_get_type(JitOptSymbol *sym);
+extern bool _Py_uop_sym_is_immortal(JitOptSymbol *sym);
+extern JitOptSymbol *_Py_uop_sym_new_tuple(JitOptContext *ctx, int size, JitOptSymbol **args);
+extern JitOptSymbol *_Py_uop_sym_tuple_getitem(JitOptContext *ctx, JitOptSymbol *sym, int item);
+extern int _Py_uop_sym_tuple_length(JitOptSymbol *sym);
+
+extern void _Py_uop_abstractcontext_init(JitOptContext *ctx);
+extern void _Py_uop_abstractcontext_fini(JitOptContext *ctx);
extern _Py_UOpsAbstractFrame *_Py_uop_frame_new(
- _Py_UOpsContext *ctx,
+ JitOptContext *ctx,
PyCodeObject *co,
int curr_stackentries,
- _Py_UopsSymbol **args,
+ JitOptSymbol **args,
int arg_len);
-extern int _Py_uop_frame_pop(_Py_UOpsContext *ctx);
+extern int _Py_uop_frame_pop(JitOptContext *ctx);
PyAPI_FUNC(PyObject *) _Py_uop_symbols_test(PyObject *self, PyObject *ignored);
with self.subTest(l=l, r=r, x=x, y=y):
script_helper.assert_python_ok("-c", s)
+ def test_symbols_flow_through_tuples(self):
+ def testfunc(n):
+ for _ in range(n):
+ a = 1
+ b = 2
+ t = a, b
+ x, y = t
+ r = x + y
+ return r
+
+ res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD)
+ self.assertEqual(res, 3)
+ self.assertIsNotNone(ex)
+ uops = get_opnames(ex)
+ self.assertIn("_BINARY_OP_ADD_INT", uops)
+ self.assertNotIn("_GUARD_BOTH_INT", uops)
+ self.assertNotIn("_GUARD_NOS_INT", uops)
+ self.assertNotIn("_GUARD_TOS_INT", uops)
+
def test_decref_escapes(self):
class Convert9999ToNone:
def __del__(self):
"""
output = """
case OP: {
- _Py_UopsSymbol *arg1;
- _Py_UopsSymbol *out;
+ JitOptSymbol *arg1;
+ JitOptSymbol *out;
arg1 = stack_pointer[-1];
out = EGGS(arg1);
stack_pointer[-1] = out;
}
case OP2: {
- _Py_UopsSymbol *out;
+ JitOptSymbol *out;
out = sym_new_not_null(ctx);
stack_pointer[-1] = out;
break;
"""
output = """
case OP: {
- _Py_UopsSymbol *out;
+ JitOptSymbol *out;
out = sym_new_not_null(ctx);
stack_pointer[-1] = out;
break;
}
case OP2: {
- _Py_UopsSymbol *out;
+ JitOptSymbol *out;
out = NULL;
stack_pointer[-1] = out;
break;
#include "pycore_instruction_sequence.h" // _PyInstructionSequence_New()
#include "pycore_long.h" // _PyLong_Sign()
#include "pycore_object.h" // _PyObject_IsFreed()
-#include "pycore_optimizer.h" // _Py_UopsSymbol, etc.
+#include "pycore_optimizer.h" // JitOptSymbol, etc.
#include "pycore_pathconfig.h" // _PyPathConfig_ClearGlobal()
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
#include "pycore_pylifecycle.h" // _PyInterpreterConfig_AsDict()
#define sym_truthiness _Py_uop_sym_truthiness
#define frame_new _Py_uop_frame_new
#define frame_pop _Py_uop_frame_pop
+#define sym_new_tuple _Py_uop_sym_new_tuple
+#define sym_tuple_getitem _Py_uop_sym_tuple_getitem
+#define sym_tuple_length _Py_uop_sym_tuple_length
+#define sym_is_immortal _Py_uop_sym_is_immortal
static int
optimize_to_bool(
_PyUOpInstruction *this_instr,
- _Py_UOpsContext *ctx,
- _Py_UopsSymbol *value,
- _Py_UopsSymbol **result_ptr)
+ JitOptContext *ctx,
+ JitOptSymbol *value,
+ JitOptSymbol **result_ptr)
{
if (sym_matches_type(value, &PyBool_Type)) {
REPLACE_OP(this_instr, _NOP, 0, 0);
)
{
- _Py_UOpsContext context;
- _Py_UOpsContext *ctx = &context;
+ JitOptContext context;
+ JitOptContext *ctx = &context;
uint32_t opcode = UINT16_MAX;
int curr_space = 0;
int max_space = 0;
int oparg = this_instr->oparg;
opcode = this_instr->opcode;
- _Py_UopsSymbol **stack_pointer = ctx->frame->stack_pointer;
+ JitOptSymbol **stack_pointer = ctx->frame->stack_pointer;
#ifdef Py_DEBUG
if (get_lltrace() >= 3) {
#define op(name, ...) /* NAME is ignored */
-typedef struct _Py_UopsSymbol _Py_UopsSymbol;
-typedef struct _Py_UOpsContext _Py_UOpsContext;
typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame;
/* Shortened forms for convenience */
#define sym_is_bottom _Py_uop_sym_is_bottom
#define frame_new _Py_uop_frame_new
#define frame_pop _Py_uop_frame_pop
+#define sym_new_tuple _Py_uop_sym_new_tuple
+#define sym_tuple_getitem _Py_uop_sym_tuple_getitem
+#define sym_tuple_length _Py_uop_sym_tuple_length
+#define sym_is_immortal _Py_uop_sym_is_immortal
extern int
optimize_to_bool(
_PyUOpInstruction *this_instr,
- _Py_UOpsContext *ctx,
- _Py_UopsSymbol *value,
- _Py_UopsSymbol **result_ptr);
+ JitOptContext *ctx,
+ JitOptSymbol *value,
+ JitOptSymbol **result_ptr);
extern void
eliminate_pop_guard(_PyUOpInstruction *this_instr, bool exit);
PyCodeObject *co;
int oparg;
- _Py_UopsSymbol *flag;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *value;
- _Py_UopsSymbol *res;
- _Py_UopsSymbol *iter;
- _Py_UopsSymbol *top;
- _Py_UopsSymbol *bottom;
+ JitOptSymbol *flag;
+ JitOptSymbol *left;
+ JitOptSymbol *right;
+ JitOptSymbol *value;
+ JitOptSymbol *res;
+ JitOptSymbol *iter;
+ JitOptSymbol *top;
+ JitOptSymbol *bottom;
_Py_UOpsAbstractFrame *frame;
_Py_UOpsAbstractFrame *new_frame;
- _Py_UOpsContext *ctx;
+ JitOptContext *ctx;
_PyUOpInstruction *this_instr;
_PyBloomFilter *dependencies;
int modified;
op(_LOAD_FAST_AND_CLEAR, (-- value)) {
value = GETLOCAL(oparg);
- _Py_UopsSymbol *temp = sym_new_null(ctx);
+ JitOptSymbol *temp = sym_new_null(ctx);
GETLOCAL(oparg) = temp;
}
}
op(_BINARY_OP_INPLACE_ADD_UNICODE, (left, right -- )) {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
if (sym_is_const(left) && sym_is_const(right) &&
sym_matches_type(left, &PyUnicode_Type) && sym_matches_type(right, &PyUnicode_Type)) {
PyObject *temp = PyUnicode_Concat(sym_get_const(left), sym_get_const(right));
res = sym_new_const(ctx, Py_True);
}
+ op(_BUILD_TUPLE, (values[oparg] -- tup)) {
+ tup = sym_new_tuple(ctx, oparg, values);
+ }
+
+ op(_UNPACK_SEQUENCE_TWO_TUPLE, (seq -- val1, val0)) {
+ val0 = sym_tuple_getitem(ctx, seq, 0);
+ val1 = sym_tuple_getitem(ctx, seq, 1);
+ }
+
+ op(_UNPACK_SEQUENCE_TUPLE, (seq -- values[oparg])) {
+ for (int i = 0; i < oparg; i++) {
+ values[i] = sym_tuple_getitem(ctx, seq, i);
+ }
+ }
+
+
// END BYTECODES //
}
/* _MONITOR_RESUME is not a viable micro-op for tier 2 */
case _LOAD_FAST_CHECK: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
value = GETLOCAL(oparg);
// We guarantee this will error - just bail and don't optimize it.
if (sym_is_null(value)) {
}
case _LOAD_FAST: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
value = GETLOCAL(oparg);
stack_pointer[0] = value;
stack_pointer += 1;
}
case _LOAD_FAST_AND_CLEAR: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
value = GETLOCAL(oparg);
- _Py_UopsSymbol *temp = sym_new_null(ctx);
+ JitOptSymbol *temp = sym_new_null(ctx);
GETLOCAL(oparg) = temp;
stack_pointer[0] = value;
stack_pointer += 1;
/* _LOAD_CONST is not a viable micro-op for tier 2 */
case _LOAD_CONST_MORTAL: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
PyObject *val = PyTuple_GET_ITEM(co->co_consts, this_instr->oparg);
int opcode = _Py_IsImmortal(val) ? _LOAD_CONST_INLINE_BORROW : _LOAD_CONST_INLINE;
REPLACE_OP(this_instr, opcode, 0, (uintptr_t)val);
}
case _LOAD_CONST_IMMORTAL: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
PyObject *val = PyTuple_GET_ITEM(co->co_consts, this_instr->oparg);
REPLACE_OP(this_instr, _LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)val);
value = sym_new_const(ctx, val);
}
case _LOAD_SMALL_INT: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
PyObject *val = PyLong_FromLong(this_instr->oparg);
value = sym_new_const(ctx, val);
stack_pointer[0] = value;
}
case _STORE_FAST: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
value = stack_pointer[-1];
GETLOCAL(oparg) = value;
stack_pointer += -1;
}
case _PUSH_NULL: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_null(ctx);
stack_pointer[0] = res;
stack_pointer += 1;
}
case _END_SEND: {
- _Py_UopsSymbol *val;
+ JitOptSymbol *val;
val = sym_new_not_null(ctx);
stack_pointer[-2] = val;
stack_pointer += -1;
}
case _UNARY_NEGATIVE: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-1] = res;
break;
}
case _UNARY_NOT: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-1] = res;
break;
}
case _TO_BOOL: {
- _Py_UopsSymbol *value;
- _Py_UopsSymbol *res;
+ JitOptSymbol *value;
+ JitOptSymbol *res;
value = stack_pointer[-1];
if (!optimize_to_bool(this_instr, ctx, value, &res)) {
res = sym_new_type(ctx, &PyBool_Type);
}
case _TO_BOOL_BOOL: {
- _Py_UopsSymbol *value;
- _Py_UopsSymbol *res;
+ JitOptSymbol *value;
+ JitOptSymbol *res;
value = stack_pointer[-1];
if (!optimize_to_bool(this_instr, ctx, value, &res)) {
sym_set_type(value, &PyBool_Type);
}
case _TO_BOOL_INT: {
- _Py_UopsSymbol *value;
- _Py_UopsSymbol *res;
+ JitOptSymbol *value;
+ JitOptSymbol *res;
value = stack_pointer[-1];
if (!optimize_to_bool(this_instr, ctx, value, &res)) {
sym_set_type(value, &PyLong_Type);
}
case _TO_BOOL_LIST: {
- _Py_UopsSymbol *value;
- _Py_UopsSymbol *res;
+ JitOptSymbol *value;
+ JitOptSymbol *res;
value = stack_pointer[-1];
if (!optimize_to_bool(this_instr, ctx, value, &res)) {
sym_set_type(value, &PyList_Type);
}
case _TO_BOOL_NONE: {
- _Py_UopsSymbol *value;
- _Py_UopsSymbol *res;
+ JitOptSymbol *value;
+ JitOptSymbol *res;
value = stack_pointer[-1];
if (!optimize_to_bool(this_instr, ctx, value, &res)) {
sym_set_const(value, Py_None);
}
case _TO_BOOL_STR: {
- _Py_UopsSymbol *value;
- _Py_UopsSymbol *res;
+ JitOptSymbol *value;
+ JitOptSymbol *res;
value = stack_pointer[-1];
if (!optimize_to_bool(this_instr, ctx, value, &res)) {
res = sym_new_type(ctx, &PyBool_Type);
}
case _REPLACE_WITH_TRUE: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_const(ctx, Py_True);
stack_pointer[-1] = res;
break;
}
case _UNARY_INVERT: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-1] = res;
break;
}
case _GUARD_BOTH_INT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_matches_type(left, &PyLong_Type)) {
}
case _BINARY_OP_MULTIPLY_INT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_is_const(left) && sym_is_const(right) &&
}
case _BINARY_OP_ADD_INT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_is_const(left) && sym_is_const(right) &&
}
case _BINARY_OP_SUBTRACT_INT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_is_const(left) && sym_is_const(right) &&
}
case _GUARD_BOTH_FLOAT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_matches_type(left, &PyFloat_Type)) {
}
case _BINARY_OP_MULTIPLY_FLOAT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_is_const(left) && sym_is_const(right) &&
}
case _BINARY_OP_ADD_FLOAT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_is_const(left) && sym_is_const(right) &&
}
case _BINARY_OP_SUBTRACT_FLOAT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_is_const(left) && sym_is_const(right) &&
}
case _GUARD_BOTH_UNICODE: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_matches_type(left, &PyUnicode_Type) &&
}
case _BINARY_OP_ADD_UNICODE: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_is_const(left) && sym_is_const(right) &&
}
case _BINARY_OP_INPLACE_ADD_UNICODE: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
right = stack_pointer[-1];
left = stack_pointer[-2];
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
if (sym_is_const(left) && sym_is_const(right) &&
sym_matches_type(left, &PyUnicode_Type) && sym_matches_type(right, &PyUnicode_Type)) {
PyObject *temp = PyUnicode_Concat(sym_get_const(left), sym_get_const(right));
}
case _BINARY_OP_EXTEND: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2] = res;
stack_pointer += -1;
}
case _BINARY_SUBSCR: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2] = res;
stack_pointer += -1;
}
case _BINARY_SLICE: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-3] = res;
stack_pointer += -2;
}
case _BINARY_SUBSCR_LIST_INT: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2] = res;
stack_pointer += -1;
}
case _BINARY_SUBSCR_STR_INT: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2] = res;
stack_pointer += -1;
}
case _BINARY_SUBSCR_TUPLE_INT: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2] = res;
stack_pointer += -1;
}
case _BINARY_SUBSCR_DICT: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2] = res;
stack_pointer += -1;
}
case _BINARY_SUBSCR_CHECK_FUNC: {
- _Py_UopsSymbol *getitem;
+ JitOptSymbol *getitem;
getitem = sym_new_not_null(ctx);
stack_pointer[0] = getitem;
stack_pointer += 1;
}
case _BINARY_SUBSCR_INIT_CALL: {
- _Py_UopsSymbol *getitem;
- _Py_UopsSymbol *sub;
- _Py_UopsSymbol *container;
+ JitOptSymbol *getitem;
+ JitOptSymbol *sub;
+ JitOptSymbol *container;
_Py_UOpsAbstractFrame *new_frame;
getitem = stack_pointer[-1];
sub = stack_pointer[-2];
(void)getitem;
new_frame = NULL;
ctx->done = true;
- stack_pointer[-3] = (_Py_UopsSymbol *)new_frame;
+ stack_pointer[-3] = (JitOptSymbol *)new_frame;
stack_pointer += -2;
assert(WITHIN_STACK_BOUNDS());
break;
}
case _CALL_INTRINSIC_1: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-1] = res;
break;
}
case _CALL_INTRINSIC_2: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2] = res;
stack_pointer += -1;
}
case _RETURN_VALUE: {
- _Py_UopsSymbol *retval;
- _Py_UopsSymbol *res;
+ JitOptSymbol *retval;
+ JitOptSymbol *res;
retval = stack_pointer[-1];
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
}
case _GET_AITER: {
- _Py_UopsSymbol *iter;
+ JitOptSymbol *iter;
iter = sym_new_not_null(ctx);
stack_pointer[-1] = iter;
break;
}
case _GET_ANEXT: {
- _Py_UopsSymbol *awaitable;
+ JitOptSymbol *awaitable;
awaitable = sym_new_not_null(ctx);
stack_pointer[0] = awaitable;
stack_pointer += 1;
}
case _GET_AWAITABLE: {
- _Py_UopsSymbol *iter;
+ JitOptSymbol *iter;
iter = sym_new_not_null(ctx);
stack_pointer[-1] = iter;
break;
}
case _YIELD_VALUE: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_unknown(ctx);
stack_pointer[-1] = res;
break;
}
case _LOAD_COMMON_CONSTANT: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
value = sym_new_not_null(ctx);
stack_pointer[0] = value;
stack_pointer += 1;
}
case _LOAD_BUILD_CLASS: {
- _Py_UopsSymbol *bc;
+ JitOptSymbol *bc;
bc = sym_new_not_null(ctx);
stack_pointer[0] = bc;
stack_pointer += 1;
}
case _UNPACK_SEQUENCE: {
- _Py_UopsSymbol *seq;
- _Py_UopsSymbol **values;
+ JitOptSymbol *seq;
+ JitOptSymbol **values;
seq = stack_pointer[-1];
values = &stack_pointer[-1];
/* This has to be done manually */
}
case _UNPACK_SEQUENCE_TWO_TUPLE: {
- _Py_UopsSymbol *val1;
- _Py_UopsSymbol *val0;
- val1 = sym_new_not_null(ctx);
- val0 = sym_new_not_null(ctx);
+ JitOptSymbol *seq;
+ JitOptSymbol *val1;
+ JitOptSymbol *val0;
+ seq = stack_pointer[-1];
+ val0 = sym_tuple_getitem(ctx, seq, 0);
+ val1 = sym_tuple_getitem(ctx, seq, 1);
stack_pointer[-1] = val1;
stack_pointer[0] = val0;
stack_pointer += 1;
}
case _UNPACK_SEQUENCE_TUPLE: {
- _Py_UopsSymbol **values;
+ JitOptSymbol *seq;
+ JitOptSymbol **values;
+ seq = stack_pointer[-1];
values = &stack_pointer[-1];
- for (int _i = oparg; --_i >= 0;) {
- values[_i] = sym_new_not_null(ctx);
+ for (int i = 0; i < oparg; i++) {
+ values[i] = sym_tuple_getitem(ctx, seq, i);
}
stack_pointer += -1 + oparg;
assert(WITHIN_STACK_BOUNDS());
}
case _UNPACK_SEQUENCE_LIST: {
- _Py_UopsSymbol **values;
+ JitOptSymbol **values;
values = &stack_pointer[-1];
for (int _i = oparg; --_i >= 0;) {
values[_i] = sym_new_not_null(ctx);
}
case _UNPACK_EX: {
- _Py_UopsSymbol *seq;
- _Py_UopsSymbol **values;
+ JitOptSymbol *seq;
+ JitOptSymbol **values;
seq = stack_pointer[-1];
values = &stack_pointer[-1];
/* This has to be done manually */
}
case _LOAD_LOCALS: {
- _Py_UopsSymbol *locals;
+ JitOptSymbol *locals;
locals = sym_new_not_null(ctx);
stack_pointer[0] = locals;
stack_pointer += 1;
/* _LOAD_FROM_DICT_OR_GLOBALS is not a viable micro-op for tier 2 */
case _LOAD_NAME: {
- _Py_UopsSymbol *v;
+ JitOptSymbol *v;
v = sym_new_not_null(ctx);
stack_pointer[0] = v;
stack_pointer += 1;
}
case _LOAD_GLOBAL: {
- _Py_UopsSymbol **res;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol **res;
+ JitOptSymbol *null = NULL;
res = &stack_pointer[0];
res[0] = sym_new_not_null(ctx);
null = sym_new_null(ctx);
}
case _GUARD_GLOBALS_VERSION_PUSH_KEYS: {
- _Py_UopsSymbol *globals_keys;
+ JitOptSymbol *globals_keys;
uint16_t version = (uint16_t)this_instr->operand0;
globals_keys = sym_new_unknown(ctx);
(void)version;
}
case _GUARD_BUILTINS_VERSION_PUSH_KEYS: {
- _Py_UopsSymbol *builtins_keys;
+ JitOptSymbol *builtins_keys;
uint16_t version = (uint16_t)this_instr->operand0;
builtins_keys = sym_new_unknown(ctx);
(void)version;
}
case _LOAD_GLOBAL_MODULE_FROM_KEYS: {
- _Py_UopsSymbol *res;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *res;
+ JitOptSymbol *null = NULL;
res = sym_new_not_null(ctx);
null = sym_new_null(ctx);
stack_pointer[-1] = res;
}
case _LOAD_GLOBAL_BUILTINS_FROM_KEYS: {
- _Py_UopsSymbol *res;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *res;
+ JitOptSymbol *null = NULL;
res = sym_new_not_null(ctx);
null = sym_new_null(ctx);
stack_pointer[-1] = res;
}
case _LOAD_FROM_DICT_OR_DEREF: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
value = sym_new_not_null(ctx);
stack_pointer[-1] = value;
break;
}
case _LOAD_DEREF: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
value = sym_new_not_null(ctx);
stack_pointer[0] = value;
stack_pointer += 1;
}
case _BUILD_STRING: {
- _Py_UopsSymbol *str;
+ JitOptSymbol *str;
str = sym_new_not_null(ctx);
stack_pointer[-oparg] = str;
stack_pointer += 1 - oparg;
}
case _BUILD_TUPLE: {
- _Py_UopsSymbol *tup;
- tup = sym_new_not_null(ctx);
+ JitOptSymbol **values;
+ JitOptSymbol *tup;
+ values = &stack_pointer[-oparg];
+ tup = sym_new_tuple(ctx, oparg, values);
stack_pointer[-oparg] = tup;
stack_pointer += 1 - oparg;
assert(WITHIN_STACK_BOUNDS());
}
case _BUILD_LIST: {
- _Py_UopsSymbol *list;
+ JitOptSymbol *list;
list = sym_new_not_null(ctx);
stack_pointer[-oparg] = list;
stack_pointer += 1 - oparg;
}
case _BUILD_SET: {
- _Py_UopsSymbol *set;
+ JitOptSymbol *set;
set = sym_new_not_null(ctx);
stack_pointer[-oparg] = set;
stack_pointer += 1 - oparg;
}
case _BUILD_MAP: {
- _Py_UopsSymbol *map;
+ JitOptSymbol *map;
map = sym_new_not_null(ctx);
stack_pointer[-oparg*2] = map;
stack_pointer += 1 - oparg*2;
/* _INSTRUMENTED_LOAD_SUPER_ATTR is not a viable micro-op for tier 2 */
case _LOAD_SUPER_ATTR_ATTR: {
- _Py_UopsSymbol *attr_st;
+ JitOptSymbol *attr_st;
attr_st = sym_new_not_null(ctx);
stack_pointer[-3] = attr_st;
stack_pointer += -2;
}
case _LOAD_SUPER_ATTR_METHOD: {
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *self_or_null;
+ JitOptSymbol *attr;
+ JitOptSymbol *self_or_null;
attr = sym_new_not_null(ctx);
self_or_null = sym_new_not_null(ctx);
stack_pointer[-3] = attr;
}
case _LOAD_ATTR: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *self_or_null = NULL;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *self_or_null = NULL;
owner = stack_pointer[-1];
(void)owner;
attr = sym_new_not_null(ctx);
}
case _GUARD_TYPE_VERSION: {
- _Py_UopsSymbol *owner;
+ JitOptSymbol *owner;
owner = stack_pointer[-1];
uint32_t type_version = (uint32_t)this_instr->operand0;
assert(type_version);
}
case _LOAD_ATTR_INSTANCE_VALUE: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *null = NULL;
owner = stack_pointer[-1];
uint16_t offset = (uint16_t)this_instr->operand0;
attr = sym_new_not_null(ctx);
}
case _CHECK_ATTR_MODULE_PUSH_KEYS: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *mod_keys;
+ JitOptSymbol *owner;
+ JitOptSymbol *mod_keys;
owner = stack_pointer[-1];
uint32_t dict_version = (uint32_t)this_instr->operand0;
(void)dict_version;
}
case _LOAD_ATTR_MODULE_FROM_KEYS: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *null = NULL;
owner = stack_pointer[-2];
uint16_t index = (uint16_t)this_instr->operand0;
(void)index;
}
case _CHECK_ATTR_WITH_HINT: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *dict;
+ JitOptSymbol *owner;
+ JitOptSymbol *dict;
owner = stack_pointer[-1];
dict = sym_new_not_null(ctx);
(void)owner;
}
case _LOAD_ATTR_WITH_HINT: {
- _Py_UopsSymbol *dict;
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *dict;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *null = NULL;
dict = stack_pointer[-1];
owner = stack_pointer[-2];
uint16_t hint = (uint16_t)this_instr->operand0;
}
case _LOAD_ATTR_SLOT: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *null = NULL;
owner = stack_pointer[-1];
uint16_t index = (uint16_t)this_instr->operand0;
attr = sym_new_not_null(ctx);
}
case _LOAD_ATTR_CLASS: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *null = NULL;
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)this_instr->operand0;
attr = sym_new_not_null(ctx);
}
case _LOAD_ATTR_PROPERTY_FRAME: {
- _Py_UopsSymbol *owner;
+ JitOptSymbol *owner;
_Py_UOpsAbstractFrame *new_frame;
owner = stack_pointer[-1];
PyObject *fget = (PyObject *)this_instr->operand0;
(void)owner;
new_frame = NULL;
ctx->done = true;
- stack_pointer[-1] = (_Py_UopsSymbol *)new_frame;
+ stack_pointer[-1] = (JitOptSymbol *)new_frame;
break;
}
}
case _COMPARE_OP: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
(void)left;
}
case _COMPARE_OP_FLOAT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
(void)left;
}
case _COMPARE_OP_INT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
(void)left;
}
case _COMPARE_OP_STR: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
(void)left;
}
case _IS_OP: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
(void)left;
}
case _CONTAINS_OP: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
(void)left;
}
case _CONTAINS_OP_SET: {
- _Py_UopsSymbol *b;
+ JitOptSymbol *b;
b = sym_new_not_null(ctx);
stack_pointer[-2] = b;
stack_pointer += -1;
}
case _CONTAINS_OP_DICT: {
- _Py_UopsSymbol *b;
+ JitOptSymbol *b;
b = sym_new_not_null(ctx);
stack_pointer[-2] = b;
stack_pointer += -1;
}
case _CHECK_EG_MATCH: {
- _Py_UopsSymbol *rest;
- _Py_UopsSymbol *match;
+ JitOptSymbol *rest;
+ JitOptSymbol *match;
rest = sym_new_not_null(ctx);
match = sym_new_not_null(ctx);
stack_pointer[-2] = rest;
}
case _CHECK_EXC_MATCH: {
- _Py_UopsSymbol *b;
+ JitOptSymbol *b;
b = sym_new_not_null(ctx);
stack_pointer[-1] = b;
break;
}
case _IMPORT_NAME: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2] = res;
stack_pointer += -1;
}
case _IMPORT_FROM: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[0] = res;
stack_pointer += 1;
/* _POP_JUMP_IF_TRUE is not a viable micro-op for tier 2 */
case _IS_NONE: {
- _Py_UopsSymbol *b;
+ JitOptSymbol *b;
b = sym_new_not_null(ctx);
stack_pointer[-1] = b;
break;
}
case _GET_LEN: {
- _Py_UopsSymbol *len;
+ JitOptSymbol *len;
len = sym_new_not_null(ctx);
stack_pointer[0] = len;
stack_pointer += 1;
}
case _MATCH_CLASS: {
- _Py_UopsSymbol *attrs;
+ JitOptSymbol *attrs;
attrs = sym_new_not_null(ctx);
stack_pointer[-3] = attrs;
stack_pointer += -2;
}
case _MATCH_MAPPING: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[0] = res;
stack_pointer += 1;
}
case _MATCH_SEQUENCE: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[0] = res;
stack_pointer += 1;
}
case _MATCH_KEYS: {
- _Py_UopsSymbol *values_or_none;
+ JitOptSymbol *values_or_none;
values_or_none = sym_new_not_null(ctx);
stack_pointer[0] = values_or_none;
stack_pointer += 1;
}
case _GET_ITER: {
- _Py_UopsSymbol *iter;
+ JitOptSymbol *iter;
iter = sym_new_not_null(ctx);
stack_pointer[-1] = iter;
break;
}
case _GET_YIELD_FROM_ITER: {
- _Py_UopsSymbol *iter;
+ JitOptSymbol *iter;
iter = sym_new_not_null(ctx);
stack_pointer[-1] = iter;
break;
/* _FOR_ITER is not a viable micro-op for tier 2 */
case _FOR_ITER_TIER_TWO: {
- _Py_UopsSymbol *next;
+ JitOptSymbol *next;
next = sym_new_not_null(ctx);
stack_pointer[0] = next;
stack_pointer += 1;
}
case _ITER_NEXT_LIST: {
- _Py_UopsSymbol *next;
+ JitOptSymbol *next;
next = sym_new_not_null(ctx);
stack_pointer[0] = next;
stack_pointer += 1;
}
case _ITER_NEXT_TUPLE: {
- _Py_UopsSymbol *next;
+ JitOptSymbol *next;
next = sym_new_not_null(ctx);
stack_pointer[0] = next;
stack_pointer += 1;
}
case _ITER_NEXT_RANGE: {
- _Py_UopsSymbol *iter;
- _Py_UopsSymbol *next;
+ JitOptSymbol *iter;
+ JitOptSymbol *next;
iter = stack_pointer[-1];
next = sym_new_type(ctx, &PyLong_Type);
(void)iter;
}
case _LOAD_SPECIAL: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *self_or_null;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *self_or_null;
owner = stack_pointer[-1];
(void)owner;
attr = sym_new_not_null(ctx);
}
case _WITH_EXCEPT_START: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[0] = res;
stack_pointer += 1;
}
case _PUSH_EXC_INFO: {
- _Py_UopsSymbol *prev_exc;
- _Py_UopsSymbol *new_exc;
+ JitOptSymbol *prev_exc;
+ JitOptSymbol *new_exc;
prev_exc = sym_new_not_null(ctx);
new_exc = sym_new_not_null(ctx);
stack_pointer[-1] = prev_exc;
}
case _LOAD_ATTR_METHOD_WITH_VALUES: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *self = NULL;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *self = NULL;
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)this_instr->operand0;
(void)descr;
}
case _LOAD_ATTR_METHOD_NO_DICT: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *self = NULL;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *self = NULL;
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)this_instr->operand0;
(void)descr;
}
case _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES: {
- _Py_UopsSymbol *attr;
+ JitOptSymbol *attr;
attr = sym_new_not_null(ctx);
stack_pointer[-1] = attr;
break;
}
case _LOAD_ATTR_NONDESCRIPTOR_NO_DICT: {
- _Py_UopsSymbol *attr;
+ JitOptSymbol *attr;
attr = sym_new_not_null(ctx);
stack_pointer[-1] = attr;
break;
}
case _LOAD_ATTR_METHOD_LAZY_DICT: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *self = NULL;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *self = NULL;
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)this_instr->operand0;
(void)descr;
}
case _MAYBE_EXPAND_METHOD: {
- _Py_UopsSymbol **args;
- _Py_UopsSymbol *self_or_null;
- _Py_UopsSymbol *callable;
- _Py_UopsSymbol *func;
- _Py_UopsSymbol *maybe_self;
+ JitOptSymbol **args;
+ JitOptSymbol *self_or_null;
+ JitOptSymbol *callable;
+ JitOptSymbol *func;
+ JitOptSymbol *maybe_self;
args = &stack_pointer[-oparg];
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
/* _MONITOR_CALL is not a viable micro-op for tier 2 */
case _PY_FRAME_GENERAL: {
- _Py_UopsSymbol *self_or_null;
- _Py_UopsSymbol *callable;
+ JitOptSymbol *self_or_null;
+ JitOptSymbol *callable;
_Py_UOpsAbstractFrame *new_frame;
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
break;
}
new_frame = frame_new(ctx, co, 0, NULL, 0);
- stack_pointer[0] = (_Py_UopsSymbol *)new_frame;
+ stack_pointer[0] = (JitOptSymbol *)new_frame;
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
break;
}
case _CHECK_FUNCTION_VERSION: {
- _Py_UopsSymbol *self_or_null;
- _Py_UopsSymbol *callable;
+ JitOptSymbol *self_or_null;
+ JitOptSymbol *callable;
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
uint32_t func_version = (uint32_t)this_instr->operand0;
}
case _EXPAND_METHOD: {
- _Py_UopsSymbol **method;
- _Py_UopsSymbol **self;
+ JitOptSymbol **method;
+ JitOptSymbol **self;
method = &stack_pointer[-2 - oparg];
self = &stack_pointer[-1 - oparg];
method[0] = sym_new_not_null(ctx);
}
case _CALL_NON_PY_GENERAL: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
}
case _CHECK_CALL_BOUND_METHOD_EXACT_ARGS: {
- _Py_UopsSymbol *null;
- _Py_UopsSymbol *callable;
+ JitOptSymbol *null;
+ JitOptSymbol *callable;
null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
sym_set_null(null);
}
case _INIT_CALL_BOUND_METHOD_EXACT_ARGS: {
- _Py_UopsSymbol *callable;
- _Py_UopsSymbol *func;
- _Py_UopsSymbol *self;
+ JitOptSymbol *callable;
+ JitOptSymbol *func;
+ JitOptSymbol *self;
callable = stack_pointer[-2 - oparg];
(void)callable;
func = sym_new_not_null(ctx);
}
case _CHECK_FUNCTION_EXACT_ARGS: {
- _Py_UopsSymbol *self_or_null;
- _Py_UopsSymbol *callable;
+ JitOptSymbol *self_or_null;
+ JitOptSymbol *callable;
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
assert(sym_matches_type(callable, &PyFunction_Type));
}
case _INIT_CALL_PY_EXACT_ARGS: {
- _Py_UopsSymbol **args;
- _Py_UopsSymbol *self_or_null;
- _Py_UopsSymbol *callable;
+ JitOptSymbol **args;
+ JitOptSymbol *self_or_null;
+ JitOptSymbol *callable;
_Py_UOpsAbstractFrame *new_frame;
args = &stack_pointer[-oparg];
self_or_null = stack_pointer[-1 - oparg];
} else {
new_frame = frame_new(ctx, co, 0, NULL, 0);
}
- stack_pointer[0] = (_Py_UopsSymbol *)new_frame;
+ stack_pointer[0] = (JitOptSymbol *)new_frame;
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
break;
}
case _CALL_TYPE_1: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-3] = res;
stack_pointer += -2;
}
case _CALL_STR_1: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-3] = res;
stack_pointer += -2;
}
case _CALL_TUPLE_1: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-3] = res;
stack_pointer += -2;
}
case _CHECK_AND_ALLOCATE_OBJECT: {
- _Py_UopsSymbol **args;
- _Py_UopsSymbol *null;
- _Py_UopsSymbol *callable;
- _Py_UopsSymbol *self;
- _Py_UopsSymbol *init;
+ JitOptSymbol **args;
+ JitOptSymbol *null;
+ JitOptSymbol *callable;
+ JitOptSymbol *self;
+ JitOptSymbol *init;
args = &stack_pointer[-oparg];
null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
}
case _CREATE_INIT_FRAME: {
- _Py_UopsSymbol **args;
- _Py_UopsSymbol *init;
- _Py_UopsSymbol *self;
+ JitOptSymbol **args;
+ JitOptSymbol *init;
+ JitOptSymbol *self;
_Py_UOpsAbstractFrame *init_frame;
args = &stack_pointer[-oparg];
init = stack_pointer[-1 - oparg];
(void)args;
init_frame = NULL;
ctx->done = true;
- stack_pointer[-2 - oparg] = (_Py_UopsSymbol *)init_frame;
+ stack_pointer[-2 - oparg] = (JitOptSymbol *)init_frame;
stack_pointer += -1 - oparg;
assert(WITHIN_STACK_BOUNDS());
break;
}
case _CALL_BUILTIN_CLASS: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
}
case _CALL_BUILTIN_O: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
}
case _CALL_BUILTIN_FAST: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
}
case _CALL_BUILTIN_FAST_WITH_KEYWORDS: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
}
case _CALL_LEN: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
}
case _CALL_ISINSTANCE: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
}
case _CALL_METHOD_DESCRIPTOR_O: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
}
case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
}
case _CALL_METHOD_DESCRIPTOR_NOARGS: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
}
case _CALL_METHOD_DESCRIPTOR_FAST: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
/* _INSTRUMENTED_CALL_KW is not a viable micro-op for tier 2 */
case _MAYBE_EXPAND_METHOD_KW: {
- _Py_UopsSymbol **func;
- _Py_UopsSymbol **maybe_self;
- _Py_UopsSymbol **args;
- _Py_UopsSymbol *kwnames_out;
+ JitOptSymbol **func;
+ JitOptSymbol **maybe_self;
+ JitOptSymbol **args;
+ JitOptSymbol *kwnames_out;
func = &stack_pointer[-3 - oparg];
maybe_self = &stack_pointer[-2 - oparg];
args = &stack_pointer[-1 - oparg];
/* _DO_CALL_KW is not a viable micro-op for tier 2 */
case _PY_FRAME_KW: {
- _Py_UopsSymbol *kwnames;
- _Py_UopsSymbol **args;
- _Py_UopsSymbol *self_or_null;
- _Py_UopsSymbol *callable;
+ JitOptSymbol *kwnames;
+ JitOptSymbol **args;
+ JitOptSymbol *self_or_null;
+ JitOptSymbol *callable;
_Py_UOpsAbstractFrame *new_frame;
kwnames = stack_pointer[-1];
args = &stack_pointer[-1 - oparg];
(void)kwnames;
new_frame = NULL;
ctx->done = true;
- stack_pointer[-3 - oparg] = (_Py_UopsSymbol *)new_frame;
+ stack_pointer[-3 - oparg] = (JitOptSymbol *)new_frame;
stack_pointer += -2 - oparg;
assert(WITHIN_STACK_BOUNDS());
break;
}
case _EXPAND_METHOD_KW: {
- _Py_UopsSymbol **method;
- _Py_UopsSymbol **self;
+ JitOptSymbol **method;
+ JitOptSymbol **self;
method = &stack_pointer[-3 - oparg];
self = &stack_pointer[-2 - oparg];
method[0] = sym_new_not_null(ctx);
}
case _CALL_KW_NON_PY: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-3 - oparg] = res;
stack_pointer += -2 - oparg;
/* _INSTRUMENTED_CALL_FUNCTION_EX is not a viable micro-op for tier 2 */
case _MAKE_CALLARGS_A_TUPLE: {
- _Py_UopsSymbol *tuple;
- _Py_UopsSymbol *kwargs_out = NULL;
+ JitOptSymbol *tuple;
+ JitOptSymbol *kwargs_out = NULL;
tuple = sym_new_not_null(ctx);
kwargs_out = sym_new_not_null(ctx);
stack_pointer[-1 - (oparg & 1)] = tuple;
/* _DO_CALL_FUNCTION_EX is not a viable micro-op for tier 2 */
case _MAKE_FUNCTION: {
- _Py_UopsSymbol *func;
+ JitOptSymbol *func;
func = sym_new_not_null(ctx);
stack_pointer[-1] = func;
break;
}
case _SET_FUNCTION_ATTRIBUTE: {
- _Py_UopsSymbol *func_out;
+ JitOptSymbol *func_out;
func_out = sym_new_not_null(ctx);
stack_pointer[-2] = func_out;
stack_pointer += -1;
}
case _RETURN_GENERATOR: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
ctx->frame->stack_pointer = stack_pointer;
frame_pop(ctx);
stack_pointer = ctx->frame->stack_pointer;
}
case _BUILD_SLICE: {
- _Py_UopsSymbol *slice;
+ JitOptSymbol *slice;
slice = sym_new_not_null(ctx);
stack_pointer[-2 - ((oparg == 3) ? 1 : 0)] = slice;
stack_pointer += -1 - ((oparg == 3) ? 1 : 0);
}
case _CONVERT_VALUE: {
- _Py_UopsSymbol *result;
+ JitOptSymbol *result;
result = sym_new_not_null(ctx);
stack_pointer[-1] = result;
break;
}
case _FORMAT_SIMPLE: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-1] = res;
break;
}
case _FORMAT_WITH_SPEC: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2] = res;
stack_pointer += -1;
}
case _COPY: {
- _Py_UopsSymbol *bottom;
- _Py_UopsSymbol *top;
+ JitOptSymbol *bottom;
+ JitOptSymbol *top;
bottom = stack_pointer[-1 - (oparg-1)];
assert(oparg > 0);
top = bottom;
}
case _BINARY_OP: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
bool lhs_int = sym_matches_type(left, &PyLong_Type);
}
case _SWAP: {
- _Py_UopsSymbol *top_in;
- _Py_UopsSymbol *bottom_in;
- _Py_UopsSymbol *top_out;
- _Py_UopsSymbol *bottom_out;
+ JitOptSymbol *top_in;
+ JitOptSymbol *bottom_in;
+ JitOptSymbol *top_out;
+ JitOptSymbol *bottom_out;
top_in = stack_pointer[-1];
bottom_in = stack_pointer[-2 - (oparg-2)];
bottom_out = bottom_in;
/* _INSTRUMENTED_POP_JUMP_IF_NOT_NONE is not a viable micro-op for tier 2 */
case _GUARD_IS_TRUE_POP: {
- _Py_UopsSymbol *flag;
+ JitOptSymbol *flag;
flag = stack_pointer[-1];
if (sym_is_const(flag)) {
PyObject *value = sym_get_const(flag);
}
case _GUARD_IS_FALSE_POP: {
- _Py_UopsSymbol *flag;
+ JitOptSymbol *flag;
flag = stack_pointer[-1];
if (sym_is_const(flag)) {
PyObject *value = sym_get_const(flag);
}
case _GUARD_IS_NONE_POP: {
- _Py_UopsSymbol *flag;
+ JitOptSymbol *flag;
flag = stack_pointer[-1];
if (sym_is_const(flag)) {
PyObject *value = sym_get_const(flag);
}
case _GUARD_IS_NOT_NONE_POP: {
- _Py_UopsSymbol *flag;
+ JitOptSymbol *flag;
flag = stack_pointer[-1];
if (sym_is_const(flag)) {
PyObject *value = sym_get_const(flag);
}
case _LOAD_CONST_INLINE: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
PyObject *ptr = (PyObject *)this_instr->operand0;
value = sym_new_const(ctx, ptr);
stack_pointer[0] = value;
}
case _LOAD_CONST_INLINE_BORROW: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
PyObject *ptr = (PyObject *)this_instr->operand0;
value = sym_new_const(ctx, ptr);
stack_pointer[0] = value;
}
case _POP_TOP_LOAD_CONST_INLINE_BORROW: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
value = sym_new_not_null(ctx);
stack_pointer[-1] = value;
break;
}
case _LOAD_CONST_INLINE_WITH_NULL: {
- _Py_UopsSymbol *value;
- _Py_UopsSymbol *null;
+ JitOptSymbol *value;
+ JitOptSymbol *null;
PyObject *ptr = (PyObject *)this_instr->operand0;
value = sym_new_const(ctx, ptr);
null = sym_new_null(ctx);
}
case _LOAD_CONST_INLINE_BORROW_WITH_NULL: {
- _Py_UopsSymbol *value;
- _Py_UopsSymbol *null;
+ JitOptSymbol *value;
+ JitOptSymbol *null;
PyObject *ptr = (PyObject *)this_instr->operand0;
value = sym_new_const(ctx, ptr);
null = sym_new_null(ctx);
}
case _LOAD_GLOBAL_MODULE: {
- _Py_UopsSymbol *res;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *res;
+ JitOptSymbol *null = NULL;
res = sym_new_not_null(ctx);
null = sym_new_null(ctx);
stack_pointer[0] = res;
}
case _LOAD_GLOBAL_BUILTINS: {
- _Py_UopsSymbol *res;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *res;
+ JitOptSymbol *null = NULL;
res = sym_new_not_null(ctx);
null = sym_new_null(ctx);
stack_pointer[0] = res;
}
case _LOAD_ATTR_MODULE: {
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *attr;
+ JitOptSymbol *null = NULL;
attr = sym_new_not_null(ctx);
null = sym_new_null(ctx);
stack_pointer[-1] = attr;
- Bottom: IS_NULL and NOT_NULL flags set, type and const_val NULL.
*/
-// Flags for below.
-#define IS_NULL 1 << 0
-#define NOT_NULL 1 << 1
-#define NO_SPACE 1 << 2
-
#ifdef Py_DEBUG
static inline int get_lltrace(void) {
char *uop_debug = Py_GETENV("PYTHON_OPT_DEBUG");
#define DPRINTF(level, ...)
#endif
-static _Py_UopsSymbol NO_SPACE_SYMBOL = {
- .flags = IS_NULL | NOT_NULL | NO_SPACE,
- .typ = NULL,
- .const_val = NULL,
- .type_version = 0,
+
+static JitOptSymbol NO_SPACE_SYMBOL = {
+ .tag = JIT_SYM_BOTTOM_TAG
};
-_Py_UopsSymbol *
-out_of_space(_Py_UOpsContext *ctx)
+JitOptSymbol *
+out_of_space(JitOptContext *ctx)
{
ctx->done = true;
ctx->out_of_space = true;
return &NO_SPACE_SYMBOL;
}
-static _Py_UopsSymbol *
-sym_new(_Py_UOpsContext *ctx)
+static JitOptSymbol *
+sym_new(JitOptContext *ctx)
{
- _Py_UopsSymbol *self = &ctx->t_arena.arena[ctx->t_arena.ty_curr_number];
+ JitOptSymbol *self = &ctx->t_arena.arena[ctx->t_arena.ty_curr_number];
if (ctx->t_arena.ty_curr_number >= ctx->t_arena.ty_max_number) {
OPT_STAT_INC(optimizer_failure_reason_no_memory);
DPRINTF(1, "out of space for symbolic expression type\n");
return NULL;
}
ctx->t_arena.ty_curr_number++;
- self->flags = 0;
- self->typ = NULL;
- self->const_val = NULL;
- self->type_version = 0;
-
+ self->tag = JIT_SYM_UNKNOWN_TAG;
return self;
}
static inline void
-sym_set_flag(_Py_UopsSymbol *sym, int flag)
-{
- sym->flags |= flag;
-}
-
-static inline void
-sym_set_bottom(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym)
+sym_set_bottom(JitOptContext *ctx, JitOptSymbol *sym)
{
- sym_set_flag(sym, IS_NULL | NOT_NULL);
- sym->typ = NULL;
- Py_CLEAR(sym->const_val);
+ sym->tag = JIT_SYM_BOTTOM_TAG;
ctx->done = true;
ctx->contradiction = true;
}
bool
-_Py_uop_sym_is_bottom(_Py_UopsSymbol *sym)
+_Py_uop_sym_is_bottom(JitOptSymbol *sym)
{
- if ((sym->flags & IS_NULL) && (sym->flags & NOT_NULL)) {
- assert(sym->flags == (IS_NULL | NOT_NULL));
- assert(sym->typ == NULL);
- assert(sym->const_val == NULL);
- return true;
- }
- return false;
+ return sym->tag == JIT_SYM_BOTTOM_TAG;
}
bool
-_Py_uop_sym_is_not_null(_Py_UopsSymbol *sym)
-{
- return sym->flags == NOT_NULL;
+_Py_uop_sym_is_not_null(JitOptSymbol *sym) {
+ return sym->tag == JIT_SYM_NON_NULL_TAG || sym->tag > JIT_SYM_BOTTOM_TAG;
}
bool
-_Py_uop_sym_is_null(_Py_UopsSymbol *sym)
+_Py_uop_sym_is_const(JitOptSymbol *sym)
{
- return sym->flags == IS_NULL;
+ return sym->tag == JIT_SYM_KNOWN_VALUE_TAG;
}
bool
-_Py_uop_sym_is_const(_Py_UopsSymbol *sym)
+_Py_uop_sym_is_null(JitOptSymbol *sym)
{
- return sym->const_val != NULL;
+ return sym->tag == JIT_SYM_NULL_TAG;
}
+
PyObject *
-_Py_uop_sym_get_const(_Py_UopsSymbol *sym)
+_Py_uop_sym_get_const(JitOptSymbol *sym)
{
- return sym->const_val;
+ if (sym->tag == JIT_SYM_KNOWN_VALUE_TAG) {
+ return sym->value.value;
+ }
+ return NULL;
}
void
-_Py_uop_sym_set_type(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym, PyTypeObject *typ)
+_Py_uop_sym_set_type(JitOptContext *ctx, JitOptSymbol *sym, PyTypeObject *typ)
{
- assert(typ != NULL && PyType_Check(typ));
- if (sym->flags & IS_NULL) {
- sym_set_bottom(ctx, sym);
- return;
- }
- if (sym->typ != NULL) {
- if (sym->typ != typ) {
+ JitSymType tag = sym->tag;
+ switch(tag) {
+ case JIT_SYM_NULL_TAG:
sym_set_bottom(ctx, sym);
return;
- }
- }
- else {
- sym_set_flag(sym, NOT_NULL);
- sym->typ = typ;
+ case JIT_SYM_KNOWN_CLASS_TAG:
+ if (sym->cls.type != typ) {
+ sym_set_bottom(ctx, sym);
+ }
+ return;
+ case JIT_SYM_TYPE_VERSION_TAG:
+ if (sym->version.version == typ->tp_version_tag) {
+ sym->tag = JIT_SYM_KNOWN_CLASS_TAG;
+ sym->cls.type = typ;
+ sym->cls.version = typ->tp_version_tag;
+ }
+ else {
+ sym_set_bottom(ctx, sym);
+ }
+ return;
+ case JIT_SYM_KNOWN_VALUE_TAG:
+ if (Py_TYPE(sym->value.value) != typ) {
+ Py_CLEAR(sym->value.value);
+ sym_set_bottom(ctx, sym);
+ }
+ return;
+ case JIT_SYM_TUPLE_TAG:
+ if (typ != &PyTuple_Type) {
+ sym_set_bottom(ctx, sym);
+ }
+ return;
+ case JIT_SYM_BOTTOM_TAG:
+ return;
+ case JIT_SYM_NON_NULL_TAG:
+ case JIT_SYM_UNKNOWN_TAG:
+ sym->tag = JIT_SYM_KNOWN_CLASS_TAG;
+ sym->cls.version = 0;
+ sym->cls.type = typ;
+ return;
}
}
bool
-_Py_uop_sym_set_type_version(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym, unsigned int version)
+_Py_uop_sym_set_type_version(JitOptContext *ctx, JitOptSymbol *sym, unsigned int version)
{
- // if the type version was already set, then it must be different and we should set it to bottom
- if (sym->type_version) {
- sym_set_bottom(ctx, sym);
- return false;
+ JitSymType tag = sym->tag;
+ switch(tag) {
+ case JIT_SYM_NULL_TAG:
+ sym_set_bottom(ctx, sym);
+ return false;
+ case JIT_SYM_KNOWN_CLASS_TAG:
+ if (sym->cls.type->tp_version_tag != version) {
+ sym_set_bottom(ctx, sym);
+ return false;
+ }
+ else {
+ sym->cls.version = version;
+ return true;
+ }
+ case JIT_SYM_KNOWN_VALUE_TAG:
+ Py_CLEAR(sym->value.value);
+ sym_set_bottom(ctx, sym);
+ return false;
+ case JIT_SYM_TUPLE_TAG:
+ sym_set_bottom(ctx, sym);
+ return false;
+ case JIT_SYM_TYPE_VERSION_TAG:
+ if (sym->version.version == version) {
+ return true;
+ }
+ sym_set_bottom(ctx, sym);
+ return false;
+ case JIT_SYM_BOTTOM_TAG:
+ return false;
+ case JIT_SYM_NON_NULL_TAG:
+ case JIT_SYM_UNKNOWN_TAG:
+ sym->tag = JIT_SYM_TYPE_VERSION_TAG;
+ sym->version.version = version;
+ return true;
}
- sym->type_version = version;
- return true;
+ Py_UNREACHABLE();
+}
+
+static void make_const(JitOptSymbol *sym, PyObject *val)
+{
+ sym->tag = JIT_SYM_KNOWN_VALUE_TAG;
+ sym->value.value = Py_NewRef(val);
}
void
-_Py_uop_sym_set_const(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym, PyObject *const_val)
+_Py_uop_sym_set_const(JitOptContext *ctx, JitOptSymbol *sym, PyObject *const_val)
{
- assert(const_val != NULL);
- if (sym->flags & IS_NULL) {
- sym_set_bottom(ctx, sym);
- }
- PyTypeObject *typ = Py_TYPE(const_val);
- if (sym->typ != NULL && sym->typ != typ) {
- sym_set_bottom(ctx, sym);
- }
- if (sym->const_val != NULL) {
- if (sym->const_val != const_val) {
- // TODO: What if they're equal?
+ JitSymType tag = sym->tag;
+ switch(tag) {
+ case JIT_SYM_NULL_TAG:
sym_set_bottom(ctx, sym);
- }
- }
- else {
- sym_set_flag(sym, NOT_NULL);
- sym->typ = typ;
- sym->const_val = Py_NewRef(const_val);
+ return;
+ case JIT_SYM_KNOWN_CLASS_TAG:
+ if (sym->cls.type != Py_TYPE(const_val)) {
+ sym_set_bottom(ctx, sym);
+ return;
+ }
+ make_const(sym, const_val);
+ return;
+ case JIT_SYM_KNOWN_VALUE_TAG:
+ if (sym->value.value != const_val) {
+ Py_CLEAR(sym->value.value);
+ sym_set_bottom(ctx, sym);
+ }
+ return;
+ case JIT_SYM_TUPLE_TAG:
+ sym_set_bottom(ctx, sym);
+ return;
+ case JIT_SYM_TYPE_VERSION_TAG:
+ if (sym->version.version != Py_TYPE(const_val)->tp_version_tag) {
+ sym_set_bottom(ctx, sym);
+ return;
+ }
+ make_const(sym, const_val);
+ return;
+ case JIT_SYM_BOTTOM_TAG:
+ return;
+ case JIT_SYM_NON_NULL_TAG:
+ case JIT_SYM_UNKNOWN_TAG:
+ make_const(sym, const_val);
+ return;
}
}
void
-_Py_uop_sym_set_null(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym)
+_Py_uop_sym_set_null(JitOptContext *ctx, JitOptSymbol *sym)
{
- if (_Py_uop_sym_is_not_null(sym)) {
+ if (sym->tag == JIT_SYM_UNKNOWN_TAG) {
+ sym->tag = JIT_SYM_NULL_TAG;
+ }
+ else if (sym->tag > JIT_SYM_NULL_TAG) {
sym_set_bottom(ctx, sym);
}
- sym_set_flag(sym, IS_NULL);
}
void
-_Py_uop_sym_set_non_null(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym)
+_Py_uop_sym_set_non_null(JitOptContext *ctx, JitOptSymbol *sym)
{
- if (_Py_uop_sym_is_null(sym)) {
+ if (sym->tag == JIT_SYM_UNKNOWN_TAG) {
+ sym->tag = JIT_SYM_NON_NULL_TAG;
+ }
+ else if (sym->tag == JIT_SYM_NULL_TAG) {
sym_set_bottom(ctx, sym);
}
- sym_set_flag(sym, NOT_NULL);
}
-_Py_UopsSymbol *
-_Py_uop_sym_new_unknown(_Py_UOpsContext *ctx)
+JitOptSymbol *
+_Py_uop_sym_new_unknown(JitOptContext *ctx)
{
- return sym_new(ctx);
+ JitOptSymbol *res = sym_new(ctx);
+ if (res == NULL) {
+ return out_of_space(ctx);
+ }
+ return res;
}
-_Py_UopsSymbol *
-_Py_uop_sym_new_not_null(_Py_UOpsContext *ctx)
+JitOptSymbol *
+_Py_uop_sym_new_not_null(JitOptContext *ctx)
{
- _Py_UopsSymbol *res = _Py_uop_sym_new_unknown(ctx);
+ JitOptSymbol *res = sym_new(ctx);
if (res == NULL) {
return out_of_space(ctx);
}
- sym_set_flag(res, NOT_NULL);
+ res->tag = JIT_SYM_NON_NULL_TAG;
return res;
}
-_Py_UopsSymbol *
-_Py_uop_sym_new_type(_Py_UOpsContext *ctx, PyTypeObject *typ)
+JitOptSymbol *
+_Py_uop_sym_new_type(JitOptContext *ctx, PyTypeObject *typ)
{
- _Py_UopsSymbol *res = sym_new(ctx);
+ JitOptSymbol *res = sym_new(ctx);
if (res == NULL) {
return out_of_space(ctx);
}
}
// Adds a new reference to const_val, owned by the symbol.
-_Py_UopsSymbol *
-_Py_uop_sym_new_const(_Py_UOpsContext *ctx, PyObject *const_val)
+JitOptSymbol *
+_Py_uop_sym_new_const(JitOptContext *ctx, PyObject *const_val)
{
assert(const_val != NULL);
- _Py_UopsSymbol *res = sym_new(ctx);
+ JitOptSymbol *res = sym_new(ctx);
if (res == NULL) {
return out_of_space(ctx);
}
return res;
}
-_Py_UopsSymbol *
-_Py_uop_sym_new_null(_Py_UOpsContext *ctx)
+JitOptSymbol *
+_Py_uop_sym_new_null(JitOptContext *ctx)
{
- _Py_UopsSymbol *null_sym = _Py_uop_sym_new_unknown(ctx);
+ JitOptSymbol *null_sym = sym_new(ctx);
if (null_sym == NULL) {
return out_of_space(ctx);
}
}
PyTypeObject *
-_Py_uop_sym_get_type(_Py_UopsSymbol *sym)
+_Py_uop_sym_get_type(JitOptSymbol *sym)
{
- if (_Py_uop_sym_is_bottom(sym)) {
- return NULL;
- }
- return sym->typ;
+ JitSymType tag = sym->tag;
+ switch(tag) {
+ case JIT_SYM_NULL_TAG:
+ case JIT_SYM_TYPE_VERSION_TAG:
+ case JIT_SYM_BOTTOM_TAG:
+ case JIT_SYM_NON_NULL_TAG:
+ case JIT_SYM_UNKNOWN_TAG:
+ return NULL;
+ case JIT_SYM_KNOWN_CLASS_TAG:
+ return sym->cls.type;
+ case JIT_SYM_KNOWN_VALUE_TAG:
+ return Py_TYPE(sym->value.value);
+ case JIT_SYM_TUPLE_TAG:
+ return &PyTuple_Type;
+ }
+ Py_UNREACHABLE();
}
unsigned int
-_Py_uop_sym_get_type_version(_Py_UopsSymbol *sym)
+_Py_uop_sym_get_type_version(JitOptSymbol *sym)
{
- return sym->type_version;
+ JitSymType tag = sym->tag;
+ switch(tag) {
+ case JIT_SYM_NULL_TAG:
+ case JIT_SYM_BOTTOM_TAG:
+ case JIT_SYM_NON_NULL_TAG:
+ case JIT_SYM_UNKNOWN_TAG:
+ return 0;
+ case JIT_SYM_TYPE_VERSION_TAG:
+ return sym->version.version;
+ case JIT_SYM_KNOWN_CLASS_TAG:
+ return sym->cls.version;
+ case JIT_SYM_KNOWN_VALUE_TAG:
+ return Py_TYPE(sym->value.value)->tp_version_tag;
+ case JIT_SYM_TUPLE_TAG:
+ return PyTuple_Type.tp_version_tag;
+ }
+ Py_UNREACHABLE();
}
bool
-_Py_uop_sym_has_type(_Py_UopsSymbol *sym)
+_Py_uop_sym_has_type(JitOptSymbol *sym)
{
- if (_Py_uop_sym_is_bottom(sym)) {
- return false;
- }
- return sym->typ != NULL;
+ JitSymType tag = sym->tag;
+ switch(tag) {
+ case JIT_SYM_NULL_TAG:
+ case JIT_SYM_TYPE_VERSION_TAG:
+ case JIT_SYM_BOTTOM_TAG:
+ case JIT_SYM_NON_NULL_TAG:
+ case JIT_SYM_UNKNOWN_TAG:
+ return false;
+ case JIT_SYM_KNOWN_CLASS_TAG:
+ case JIT_SYM_KNOWN_VALUE_TAG:
+ case JIT_SYM_TUPLE_TAG:
+ return true;
+ }
+ Py_UNREACHABLE();
}
bool
-_Py_uop_sym_matches_type(_Py_UopsSymbol *sym, PyTypeObject *typ)
+_Py_uop_sym_matches_type(JitOptSymbol *sym, PyTypeObject *typ)
{
assert(typ != NULL && PyType_Check(typ));
return _Py_uop_sym_get_type(sym) == typ;
}
bool
-_Py_uop_sym_matches_type_version(_Py_UopsSymbol *sym, unsigned int version)
+_Py_uop_sym_matches_type_version(JitOptSymbol *sym, unsigned int version)
{
return _Py_uop_sym_get_type_version(sym) == version;
}
-
int
-_Py_uop_sym_truthiness(_Py_UopsSymbol *sym)
-{
- /* There are some non-constant values for
- * which `bool(val)` always evaluates to
- * True or False, such as tuples with known
- * length, but unknown contents, or bound-methods.
- * This function will need updating
- * should we support those values.
- */
- if (_Py_uop_sym_is_bottom(sym)) {
- return -1;
- }
- if (!_Py_uop_sym_is_const(sym)) {
- return -1;
- }
- PyObject *value = _Py_uop_sym_get_const(sym);
+_Py_uop_sym_truthiness(JitOptSymbol *sym)
+{
+ switch(sym->tag) {
+ case JIT_SYM_NULL_TAG:
+ case JIT_SYM_TYPE_VERSION_TAG:
+ case JIT_SYM_BOTTOM_TAG:
+ case JIT_SYM_NON_NULL_TAG:
+ case JIT_SYM_UNKNOWN_TAG:
+ return -1;
+ case JIT_SYM_KNOWN_CLASS_TAG:
+ /* TODO :
+ * Instances of some classes are always
+ * true. We should return 1 in those cases */
+ return -1;
+ case JIT_SYM_KNOWN_VALUE_TAG:
+ break;
+ case JIT_SYM_TUPLE_TAG:
+ return sym->tuple.length != 0;
+ }
+ PyObject *value = sym->value.value;
+ /* Only handle a few known safe types */
if (value == Py_None) {
return 0;
}
- /* Only handle a few known safe types */
PyTypeObject *tp = Py_TYPE(value);
if (tp == &PyLong_Type) {
return !_PyLong_IsZero((PyLongObject *)value);
return -1;
}
+static JitOptSymbol *
+allocation_base(JitOptContext *ctx)
+{
+ return ctx->t_arena.arena;
+}
+
+JitOptSymbol *
+_Py_uop_sym_new_tuple(JitOptContext *ctx, int size, JitOptSymbol **args)
+{
+ JitOptSymbol *res = sym_new(ctx);
+ if (res == NULL) {
+ return out_of_space(ctx);
+ }
+ if (size > MAX_SYMBOLIC_TUPLE_SIZE) {
+ res->tag = JIT_SYM_KNOWN_CLASS_TAG;
+ res->cls.type = &PyTuple_Type;
+ }
+ else {
+ res->tag = JIT_SYM_TUPLE_TAG;
+ res->tuple.length = size;
+ for (int i = 0; i < size; i++) {
+ res->tuple.items[i] = (uint16_t)(args[i] - allocation_base(ctx));
+ }
+ }
+ return res;
+}
+
+JitOptSymbol *
+_Py_uop_sym_tuple_getitem(JitOptContext *ctx, JitOptSymbol *sym, int item)
+{
+ assert(item >= 0);
+ if (sym->tag == JIT_SYM_KNOWN_VALUE_TAG) {
+ PyObject *tuple = sym->value.value;
+ if (PyTuple_CheckExact(tuple) && item < PyTuple_GET_SIZE(tuple)) {
+ return _Py_uop_sym_new_const(ctx, PyTuple_GET_ITEM(tuple, item));
+ }
+ }
+ else if (sym->tag == JIT_SYM_TUPLE_TAG && item < sym->tuple.length) {
+ return allocation_base(ctx) + sym->tuple.items[item];
+ }
+ return _Py_uop_sym_new_unknown(ctx);
+}
+
+int
+_Py_uop_sym_tuple_length(JitOptSymbol *sym)
+{
+ if (sym->tag == JIT_SYM_KNOWN_VALUE_TAG) {
+ PyObject *tuple = sym->value.value;
+ if (PyTuple_CheckExact(tuple)) {
+ return PyTuple_GET_SIZE(tuple);
+ }
+ }
+ else if (sym->tag == JIT_SYM_TUPLE_TAG) {
+ return sym->tuple.length;
+ }
+ return -1;
+}
+
+// Return true if known to be immortal.
+bool
+_Py_uop_sym_is_immortal(JitOptSymbol *sym)
+{
+ if (sym->tag == JIT_SYM_KNOWN_VALUE_TAG) {
+ return _Py_IsImmortal(sym->value.value);
+ }
+ if (sym->tag == JIT_SYM_KNOWN_CLASS_TAG) {
+ return sym->cls.type == &PyBool_Type;
+ }
+ return false;
+}
+
// 0 on success, -1 on error.
_Py_UOpsAbstractFrame *
_Py_uop_frame_new(
- _Py_UOpsContext *ctx,
+ JitOptContext *ctx,
PyCodeObject *co,
int curr_stackentries,
- _Py_UopsSymbol **args,
+ JitOptSymbol **args,
int arg_len)
{
assert(ctx->curr_frame_depth < MAX_ABSTRACT_FRAME_DEPTH);
}
for (int i = arg_len; i < co->co_nlocalsplus; i++) {
- _Py_UopsSymbol *local = _Py_uop_sym_new_unknown(ctx);
+ JitOptSymbol *local = _Py_uop_sym_new_unknown(ctx);
frame->locals[i] = local;
}
// Initialize the stack as well
for (int i = 0; i < curr_stackentries; i++) {
- _Py_UopsSymbol *stackvar = _Py_uop_sym_new_unknown(ctx);
+ JitOptSymbol *stackvar = _Py_uop_sym_new_unknown(ctx);
frame->stack[i] = stackvar;
}
}
void
-_Py_uop_abstractcontext_fini(_Py_UOpsContext *ctx)
+_Py_uop_abstractcontext_fini(JitOptContext *ctx)
{
if (ctx == NULL) {
return;
ctx->curr_frame_depth = 0;
int tys = ctx->t_arena.ty_curr_number;
for (int i = 0; i < tys; i++) {
- Py_CLEAR(ctx->t_arena.arena[i].const_val);
+ JitOptSymbol *sym = &ctx->t_arena.arena[i];
+ if (sym->tag == JIT_SYM_KNOWN_VALUE_TAG) {
+ Py_CLEAR(sym->value.value);
+ }
}
}
void
-_Py_uop_abstractcontext_init(_Py_UOpsContext *ctx)
+_Py_uop_abstractcontext_init(JitOptContext *ctx)
{
+ static_assert(sizeof(JitOptSymbol) <= 2*sizeof(uint64_t));
ctx->limit = ctx->locals_and_stack + MAX_ABSTRACT_INTERP_SIZE;
ctx->n_consumed = ctx->locals_and_stack;
#ifdef Py_DEBUG // Aids debugging a little. There should never be NULL in the abstract interpreter.
}
int
-_Py_uop_frame_pop(_Py_UOpsContext *ctx)
+_Py_uop_frame_pop(JitOptContext *ctx)
{
_Py_UOpsAbstractFrame *frame = ctx->frame;
ctx->n_consumed = frame->locals;
} \
} while (0)
-static _Py_UopsSymbol *
-make_bottom(_Py_UOpsContext *ctx)
+static JitOptSymbol *
+make_bottom(JitOptContext *ctx)
{
- _Py_UopsSymbol *sym = _Py_uop_sym_new_unknown(ctx);
- _Py_uop_sym_set_null(ctx, sym);
- _Py_uop_sym_set_non_null(ctx, sym);
+ JitOptSymbol *sym = sym_new(ctx);
+ sym->tag = JIT_SYM_BOTTOM_TAG;
return sym;
}
PyObject *
_Py_uop_symbols_test(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
{
- _Py_UOpsContext context;
- _Py_UOpsContext *ctx = &context;
+ JitOptContext context;
+ JitOptContext *ctx = &context;
_Py_uop_abstractcontext_init(ctx);
PyObject *val_42 = NULL;
PyObject *val_43 = NULL;
// Use a single 'sym' variable so copy-pasting tests is easier.
- _Py_UopsSymbol *sym = _Py_uop_sym_new_unknown(ctx);
+ JitOptSymbol *sym = _Py_uop_sym_new_unknown(ctx);
if (sym == NULL) {
goto fail;
}
TEST_PREDICATE(_Py_uop_sym_is_const(sym), "42 is not a constant");
TEST_PREDICATE(_Py_uop_sym_get_const(sym) != NULL, "42 as constant is NULL");
TEST_PREDICATE(_Py_uop_sym_get_const(sym) == val_42, "42 as constant isn't 42");
+ TEST_PREDICATE(_Py_uop_sym_is_immortal(sym), "42 is not immortal");
_Py_uop_sym_set_type(ctx, sym, &PyLong_Type); // Should be a no-op
TEST_PREDICATE(_Py_uop_sym_matches_type(sym, &PyLong_Type), "(42 and 42) isn't an int");
_Py_uop_sym_set_type(ctx, sym, &PyFloat_Type); // Should make it bottom
TEST_PREDICATE(_Py_uop_sym_is_bottom(sym), "(42 and float) isn't bottom");
+ sym = _Py_uop_sym_new_type(ctx, &PyBool_Type);
+ TEST_PREDICATE(_Py_uop_sym_is_immortal(sym), "a bool is not immortal");
+
sym = _Py_uop_sym_new_type(ctx, &PyLong_Type);
if (sym == NULL) {
goto fail;
sym = _Py_uop_sym_new_const(ctx, PyLong_FromLong(0));
TEST_PREDICATE(_Py_uop_sym_truthiness(sym) == 0, "bool(0) is not False");
+ JitOptSymbol *i1 = _Py_uop_sym_new_type(ctx, &PyFloat_Type);
+ JitOptSymbol *i2 = _Py_uop_sym_new_const(ctx, val_43);
+ JitOptSymbol *array[2] = { i1, i2 };
+ sym = _Py_uop_sym_new_tuple(ctx, 2, array);
+ TEST_PREDICATE(
+ _Py_uop_sym_matches_type(_Py_uop_sym_tuple_getitem(ctx, sym, 0), &PyFloat_Type),
+ "tuple item does not match value used to create tuple"
+ );
+ TEST_PREDICATE(
+ _Py_uop_sym_get_const(_Py_uop_sym_tuple_getitem(ctx, sym, 1)) == val_43,
+ "tuple item does not match value used to create tuple"
+ );
+ PyObject *pair[2] = { val_42, val_43 };
+ PyObject *tuple = _PyTuple_FromArray(pair, 2);
+ sym = _Py_uop_sym_new_const(ctx, tuple);
+ TEST_PREDICATE(
+ _Py_uop_sym_get_const(_Py_uop_sym_tuple_getitem(ctx, sym, 1)) == val_43,
+ "tuple item does not match value used to create tuple"
+ );
+
_Py_uop_abstractcontext_fini(ctx);
Py_DECREF(val_42);
Py_DECREF(val_43);
+ Py_DECREF(tuple);
Py_RETURN_NONE;
fail:
_Py_uop_abstractcontext_fini(ctx);
Py_XDECREF(val_42);
Py_XDECREF(val_43);
+ Py_DECREF(tuple);
return NULL;
}
def type_name(var: StackItem) -> str:
if var.is_array():
- return f"_Py_UopsSymbol **"
+ return f"JitOptSymbol **"
if var.type:
return var.type
- return f"_Py_UopsSymbol *"
+ return f"JitOptSymbol *"
def declare_variables(uop: Uop, out: CWriter, skip_inputs: bool) -> None:
var.defined = False
storage = emitter.emit_tokens(override, storage, None)
out.start_line()
- storage.flush(out, cast_type="_Py_UopsSymbol *")
+ storage.flush(out, cast_type="JitOptSymbol *")
else:
emit_default(out, uop, stack)
out.start_line()
- stack.flush(out, cast_type="_Py_UopsSymbol *")
+ stack.flush(out, cast_type="JitOptSymbol *")
except StackError as ex:
raise analysis_error(ex.args[0], prototype.body[0]) # from None