mirror of
https://github.com/python/cpython.git
synced 2025-08-29 05:05:03 +00:00
GH-130415: Use boolean guards to narrow types to values in the JIT (GH-130659)
This commit is contained in:
parent
c6513f7a62
commit
7afa476874
7 changed files with 348 additions and 166 deletions
|
@ -136,26 +136,6 @@ incorrect_keys(_PyUOpInstruction *inst, PyObject *obj)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
check_next_uop(_PyUOpInstruction *buffer, int size, int pc, uint16_t expected)
|
||||
{
|
||||
if (pc + 1 >= size) {
|
||||
DPRINTF(1, "Cannot rewrite %s at pc %d: buffer too small\n",
|
||||
_PyOpcode_uop_name[buffer[pc].opcode], pc);
|
||||
return 0;
|
||||
}
|
||||
uint16_t next_opcode = buffer[pc + 1].opcode;
|
||||
if (next_opcode != expected) {
|
||||
DPRINTF(1,
|
||||
"Cannot rewrite %s at pc %d: unexpected next opcode %s, "
|
||||
"expected %s\n",
|
||||
_PyOpcode_uop_name[buffer[pc].opcode], pc,
|
||||
_PyOpcode_uop_name[next_opcode], _PyOpcode_uop_name[expected]);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Returns 1 if successfully optimized
|
||||
* 0 if the trace is not suitable for optimization (yet)
|
||||
* -1 if there was an error. */
|
||||
|
@ -363,6 +343,7 @@ remove_globals(_PyInterpreterFrame *frame, _PyUOpInstruction *buffer,
|
|||
#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
|
||||
#define sym_new_truthiness _Py_uop_sym_new_truthiness
|
||||
|
||||
static int
|
||||
optimize_to_bool(
|
||||
|
@ -376,7 +357,7 @@ optimize_to_bool(
|
|||
*result_ptr = value;
|
||||
return 1;
|
||||
}
|
||||
int truthiness = sym_truthiness(value);
|
||||
int truthiness = sym_truthiness(ctx, value);
|
||||
if (truthiness >= 0) {
|
||||
PyObject *load = truthiness ? Py_True : Py_False;
|
||||
REPLACE_OP(this_instr, _POP_TOP_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)load);
|
||||
|
|
|
@ -34,6 +34,7 @@ typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame;
|
|||
#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
|
||||
#define sym_new_truthiness _Py_uop_sym_new_truthiness
|
||||
|
||||
extern int
|
||||
optimize_to_bool(
|
||||
|
@ -198,11 +199,11 @@ dummy_func(void) {
|
|||
// Case C:
|
||||
res = sym_new_type(ctx, &PyFloat_Type);
|
||||
}
|
||||
else if (!sym_is_const(right)) {
|
||||
else if (!sym_is_const(ctx, right)) {
|
||||
// Case A or B... can't know without the sign of the RHS:
|
||||
res = sym_new_unknown(ctx);
|
||||
}
|
||||
else if (_PyLong_IsNegative((PyLongObject *)sym_get_const(right))) {
|
||||
else if (_PyLong_IsNegative((PyLongObject *)sym_get_const(ctx, right))) {
|
||||
// Case B:
|
||||
res = sym_new_type(ctx, &PyFloat_Type);
|
||||
}
|
||||
|
@ -223,13 +224,13 @@ dummy_func(void) {
|
|||
}
|
||||
|
||||
op(_BINARY_OP_ADD_INT, (left, right -- res)) {
|
||||
if (sym_is_const(left) && sym_is_const(right) &&
|
||||
if (sym_is_const(ctx, left) && sym_is_const(ctx, right) &&
|
||||
sym_matches_type(left, &PyLong_Type) && sym_matches_type(right, &PyLong_Type))
|
||||
{
|
||||
assert(PyLong_CheckExact(sym_get_const(left)));
|
||||
assert(PyLong_CheckExact(sym_get_const(right)));
|
||||
PyObject *temp = _PyLong_Add((PyLongObject *)sym_get_const(left),
|
||||
(PyLongObject *)sym_get_const(right));
|
||||
assert(PyLong_CheckExact(sym_get_const(ctx, left)));
|
||||
assert(PyLong_CheckExact(sym_get_const(ctx, right)));
|
||||
PyObject *temp = _PyLong_Add((PyLongObject *)sym_get_const(ctx, left),
|
||||
(PyLongObject *)sym_get_const(ctx, right));
|
||||
if (temp == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -244,13 +245,13 @@ dummy_func(void) {
|
|||
}
|
||||
|
||||
op(_BINARY_OP_SUBTRACT_INT, (left, right -- res)) {
|
||||
if (sym_is_const(left) && sym_is_const(right) &&
|
||||
if (sym_is_const(ctx, left) && sym_is_const(ctx, right) &&
|
||||
sym_matches_type(left, &PyLong_Type) && sym_matches_type(right, &PyLong_Type))
|
||||
{
|
||||
assert(PyLong_CheckExact(sym_get_const(left)));
|
||||
assert(PyLong_CheckExact(sym_get_const(right)));
|
||||
PyObject *temp = _PyLong_Subtract((PyLongObject *)sym_get_const(left),
|
||||
(PyLongObject *)sym_get_const(right));
|
||||
assert(PyLong_CheckExact(sym_get_const(ctx, left)));
|
||||
assert(PyLong_CheckExact(sym_get_const(ctx, right)));
|
||||
PyObject *temp = _PyLong_Subtract((PyLongObject *)sym_get_const(ctx, left),
|
||||
(PyLongObject *)sym_get_const(ctx, right));
|
||||
if (temp == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -265,13 +266,13 @@ dummy_func(void) {
|
|||
}
|
||||
|
||||
op(_BINARY_OP_MULTIPLY_INT, (left, right -- res)) {
|
||||
if (sym_is_const(left) && sym_is_const(right) &&
|
||||
if (sym_is_const(ctx, left) && sym_is_const(ctx, right) &&
|
||||
sym_matches_type(left, &PyLong_Type) && sym_matches_type(right, &PyLong_Type))
|
||||
{
|
||||
assert(PyLong_CheckExact(sym_get_const(left)));
|
||||
assert(PyLong_CheckExact(sym_get_const(right)));
|
||||
PyObject *temp = _PyLong_Multiply((PyLongObject *)sym_get_const(left),
|
||||
(PyLongObject *)sym_get_const(right));
|
||||
assert(PyLong_CheckExact(sym_get_const(ctx, left)));
|
||||
assert(PyLong_CheckExact(sym_get_const(ctx, right)));
|
||||
PyObject *temp = _PyLong_Multiply((PyLongObject *)sym_get_const(ctx, left),
|
||||
(PyLongObject *)sym_get_const(ctx, right));
|
||||
if (temp == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -286,14 +287,14 @@ dummy_func(void) {
|
|||
}
|
||||
|
||||
op(_BINARY_OP_ADD_FLOAT, (left, right -- res)) {
|
||||
if (sym_is_const(left) && sym_is_const(right) &&
|
||||
if (sym_is_const(ctx, left) && sym_is_const(ctx, right) &&
|
||||
sym_matches_type(left, &PyFloat_Type) && sym_matches_type(right, &PyFloat_Type))
|
||||
{
|
||||
assert(PyFloat_CheckExact(sym_get_const(left)));
|
||||
assert(PyFloat_CheckExact(sym_get_const(right)));
|
||||
assert(PyFloat_CheckExact(sym_get_const(ctx, left)));
|
||||
assert(PyFloat_CheckExact(sym_get_const(ctx, right)));
|
||||
PyObject *temp = PyFloat_FromDouble(
|
||||
PyFloat_AS_DOUBLE(sym_get_const(left)) +
|
||||
PyFloat_AS_DOUBLE(sym_get_const(right)));
|
||||
PyFloat_AS_DOUBLE(sym_get_const(ctx, left)) +
|
||||
PyFloat_AS_DOUBLE(sym_get_const(ctx, right)));
|
||||
if (temp == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -308,14 +309,14 @@ dummy_func(void) {
|
|||
}
|
||||
|
||||
op(_BINARY_OP_SUBTRACT_FLOAT, (left, right -- res)) {
|
||||
if (sym_is_const(left) && sym_is_const(right) &&
|
||||
if (sym_is_const(ctx, left) && sym_is_const(ctx, right) &&
|
||||
sym_matches_type(left, &PyFloat_Type) && sym_matches_type(right, &PyFloat_Type))
|
||||
{
|
||||
assert(PyFloat_CheckExact(sym_get_const(left)));
|
||||
assert(PyFloat_CheckExact(sym_get_const(right)));
|
||||
assert(PyFloat_CheckExact(sym_get_const(ctx, left)));
|
||||
assert(PyFloat_CheckExact(sym_get_const(ctx, right)));
|
||||
PyObject *temp = PyFloat_FromDouble(
|
||||
PyFloat_AS_DOUBLE(sym_get_const(left)) -
|
||||
PyFloat_AS_DOUBLE(sym_get_const(right)));
|
||||
PyFloat_AS_DOUBLE(sym_get_const(ctx, left)) -
|
||||
PyFloat_AS_DOUBLE(sym_get_const(ctx, right)));
|
||||
if (temp == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -330,14 +331,14 @@ dummy_func(void) {
|
|||
}
|
||||
|
||||
op(_BINARY_OP_MULTIPLY_FLOAT, (left, right -- res)) {
|
||||
if (sym_is_const(left) && sym_is_const(right) &&
|
||||
if (sym_is_const(ctx, left) && sym_is_const(ctx, right) &&
|
||||
sym_matches_type(left, &PyFloat_Type) && sym_matches_type(right, &PyFloat_Type))
|
||||
{
|
||||
assert(PyFloat_CheckExact(sym_get_const(left)));
|
||||
assert(PyFloat_CheckExact(sym_get_const(right)));
|
||||
assert(PyFloat_CheckExact(sym_get_const(ctx, left)));
|
||||
assert(PyFloat_CheckExact(sym_get_const(ctx, right)));
|
||||
PyObject *temp = PyFloat_FromDouble(
|
||||
PyFloat_AS_DOUBLE(sym_get_const(left)) *
|
||||
PyFloat_AS_DOUBLE(sym_get_const(right)));
|
||||
PyFloat_AS_DOUBLE(sym_get_const(ctx, left)) *
|
||||
PyFloat_AS_DOUBLE(sym_get_const(ctx, right)));
|
||||
if (temp == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -352,9 +353,9 @@ dummy_func(void) {
|
|||
}
|
||||
|
||||
op(_BINARY_OP_ADD_UNICODE, (left, right -- res)) {
|
||||
if (sym_is_const(left) && sym_is_const(right) &&
|
||||
if (sym_is_const(ctx, left) && sym_is_const(ctx, 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));
|
||||
PyObject *temp = PyUnicode_Concat(sym_get_const(ctx, left), sym_get_const(ctx, right));
|
||||
if (temp == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -368,9 +369,9 @@ dummy_func(void) {
|
|||
|
||||
op(_BINARY_OP_INPLACE_ADD_UNICODE, (left, right -- )) {
|
||||
JitOptSymbol *res;
|
||||
if (sym_is_const(left) && sym_is_const(right) &&
|
||||
if (sym_is_const(ctx, left) && sym_is_const(ctx, 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));
|
||||
PyObject *temp = PyUnicode_Concat(sym_get_const(ctx, left), sym_get_const(ctx, right));
|
||||
if (temp == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -391,14 +392,14 @@ dummy_func(void) {
|
|||
|
||||
op(_TO_BOOL, (value -- res)) {
|
||||
if (!optimize_to_bool(this_instr, ctx, value, &res)) {
|
||||
res = sym_new_type(ctx, &PyBool_Type);
|
||||
res = sym_new_truthiness(ctx, value, true);
|
||||
}
|
||||
}
|
||||
|
||||
op(_TO_BOOL_BOOL, (value -- res)) {
|
||||
if (!optimize_to_bool(this_instr, ctx, value, &res)) {
|
||||
sym_set_type(value, &PyBool_Type);
|
||||
res = value;
|
||||
res = sym_new_truthiness(ctx, value, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -430,6 +431,11 @@ dummy_func(void) {
|
|||
}
|
||||
}
|
||||
|
||||
op(_UNARY_NOT, (value -- res)) {
|
||||
sym_set_type(value, &PyBool_Type);
|
||||
res = sym_new_truthiness(ctx, value, false);
|
||||
}
|
||||
|
||||
op(_COMPARE_OP, (left, right -- res)) {
|
||||
if (oparg & 16) {
|
||||
res = sym_new_type(ctx, &PyBool_Type);
|
||||
|
@ -521,8 +527,8 @@ dummy_func(void) {
|
|||
(void)dict_version;
|
||||
(void)index;
|
||||
attr = NULL;
|
||||
if (sym_is_const(owner)) {
|
||||
PyModuleObject *mod = (PyModuleObject *)sym_get_const(owner);
|
||||
if (sym_is_const(ctx, owner)) {
|
||||
PyModuleObject *mod = (PyModuleObject *)sym_get_const(ctx, owner);
|
||||
if (PyModule_CheckExact(mod)) {
|
||||
PyObject *dict = mod->md_dict;
|
||||
uint64_t watched_mutations = get_mutations(dict);
|
||||
|
@ -599,19 +605,19 @@ dummy_func(void) {
|
|||
}
|
||||
|
||||
op(_CHECK_FUNCTION_VERSION, (func_version/2, callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) {
|
||||
if (sym_is_const(callable) && sym_matches_type(callable, &PyFunction_Type)) {
|
||||
assert(PyFunction_Check(sym_get_const(callable)));
|
||||
if (sym_is_const(ctx, callable) && sym_matches_type(callable, &PyFunction_Type)) {
|
||||
assert(PyFunction_Check(sym_get_const(ctx, callable)));
|
||||
REPLACE_OP(this_instr, _CHECK_FUNCTION_VERSION_INLINE, 0, func_version);
|
||||
this_instr->operand1 = (uintptr_t)sym_get_const(callable);
|
||||
this_instr->operand1 = (uintptr_t)sym_get_const(ctx, callable);
|
||||
}
|
||||
sym_set_type(callable, &PyFunction_Type);
|
||||
}
|
||||
|
||||
op(_CHECK_FUNCTION_EXACT_ARGS, (callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) {
|
||||
assert(sym_matches_type(callable, &PyFunction_Type));
|
||||
if (sym_is_const(callable)) {
|
||||
if (sym_is_const(ctx, callable)) {
|
||||
if (sym_is_null(self_or_null) || sym_is_not_null(self_or_null)) {
|
||||
PyFunctionObject *func = (PyFunctionObject *)sym_get_const(callable);
|
||||
PyFunctionObject *func = (PyFunctionObject *)sym_get_const(ctx, callable);
|
||||
PyCodeObject *co = (PyCodeObject *)func->func_code;
|
||||
if (co->co_argcount == oparg + !sym_is_null(self_or_null)) {
|
||||
REPLACE_OP(this_instr, _NOP, 0 ,0);
|
||||
|
@ -812,24 +818,26 @@ dummy_func(void) {
|
|||
}
|
||||
|
||||
op(_GUARD_IS_TRUE_POP, (flag -- )) {
|
||||
if (sym_is_const(flag)) {
|
||||
PyObject *value = sym_get_const(flag);
|
||||
if (sym_is_const(ctx, flag)) {
|
||||
PyObject *value = sym_get_const(ctx, flag);
|
||||
assert(value != NULL);
|
||||
eliminate_pop_guard(this_instr, value != Py_True);
|
||||
}
|
||||
sym_set_const(flag, Py_True);
|
||||
}
|
||||
|
||||
op(_GUARD_IS_FALSE_POP, (flag -- )) {
|
||||
if (sym_is_const(flag)) {
|
||||
PyObject *value = sym_get_const(flag);
|
||||
if (sym_is_const(ctx, flag)) {
|
||||
PyObject *value = sym_get_const(ctx, flag);
|
||||
assert(value != NULL);
|
||||
eliminate_pop_guard(this_instr, value != Py_False);
|
||||
}
|
||||
sym_set_const(flag, Py_False);
|
||||
}
|
||||
|
||||
op(_GUARD_IS_NONE_POP, (flag -- )) {
|
||||
if (sym_is_const(flag)) {
|
||||
PyObject *value = sym_get_const(flag);
|
||||
if (sym_is_const(ctx, flag)) {
|
||||
PyObject *value = sym_get_const(ctx, flag);
|
||||
assert(value != NULL);
|
||||
eliminate_pop_guard(this_instr, !Py_IsNone(value));
|
||||
}
|
||||
|
@ -837,11 +845,12 @@ dummy_func(void) {
|
|||
assert(!sym_matches_type(flag, &_PyNone_Type));
|
||||
eliminate_pop_guard(this_instr, true);
|
||||
}
|
||||
sym_set_const(flag, Py_None);
|
||||
}
|
||||
|
||||
op(_GUARD_IS_NOT_NONE_POP, (flag -- )) {
|
||||
if (sym_is_const(flag)) {
|
||||
PyObject *value = sym_get_const(flag);
|
||||
if (sym_is_const(ctx, flag)) {
|
||||
PyObject *value = sym_get_const(ctx, flag);
|
||||
assert(value != NULL);
|
||||
eliminate_pop_guard(this_instr, Py_IsNone(value));
|
||||
}
|
||||
|
|
114
Python/optimizer_cases.c.h
generated
114
Python/optimizer_cases.c.h
generated
|
@ -140,8 +140,11 @@
|
|||
}
|
||||
|
||||
case _UNARY_NOT: {
|
||||
JitOptSymbol *value;
|
||||
JitOptSymbol *res;
|
||||
res = sym_new_not_null(ctx);
|
||||
value = stack_pointer[-1];
|
||||
sym_set_type(value, &PyBool_Type);
|
||||
res = sym_new_truthiness(ctx, value, false);
|
||||
stack_pointer[-1] = res;
|
||||
break;
|
||||
}
|
||||
|
@ -151,7 +154,7 @@
|
|||
JitOptSymbol *res;
|
||||
value = stack_pointer[-1];
|
||||
if (!optimize_to_bool(this_instr, ctx, value, &res)) {
|
||||
res = sym_new_type(ctx, &PyBool_Type);
|
||||
res = sym_new_truthiness(ctx, value, true);
|
||||
}
|
||||
stack_pointer[-1] = res;
|
||||
break;
|
||||
|
@ -163,7 +166,7 @@
|
|||
value = stack_pointer[-1];
|
||||
if (!optimize_to_bool(this_instr, ctx, value, &res)) {
|
||||
sym_set_type(value, &PyBool_Type);
|
||||
res = value;
|
||||
res = sym_new_truthiness(ctx, value, true);
|
||||
}
|
||||
stack_pointer[-1] = res;
|
||||
break;
|
||||
|
@ -268,15 +271,15 @@
|
|||
JitOptSymbol *res;
|
||||
right = stack_pointer[-1];
|
||||
left = stack_pointer[-2];
|
||||
if (sym_is_const(left) && sym_is_const(right) &&
|
||||
if (sym_is_const(ctx, left) && sym_is_const(ctx, right) &&
|
||||
sym_matches_type(left, &PyLong_Type) && sym_matches_type(right, &PyLong_Type))
|
||||
{
|
||||
assert(PyLong_CheckExact(sym_get_const(left)));
|
||||
assert(PyLong_CheckExact(sym_get_const(right)));
|
||||
assert(PyLong_CheckExact(sym_get_const(ctx, left)));
|
||||
assert(PyLong_CheckExact(sym_get_const(ctx, right)));
|
||||
stack_pointer += -2;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
PyObject *temp = _PyLong_Multiply((PyLongObject *)sym_get_const(left),
|
||||
(PyLongObject *)sym_get_const(right));
|
||||
PyObject *temp = _PyLong_Multiply((PyLongObject *)sym_get_const(ctx, left),
|
||||
(PyLongObject *)sym_get_const(ctx, right));
|
||||
if (temp == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -303,15 +306,15 @@
|
|||
JitOptSymbol *res;
|
||||
right = stack_pointer[-1];
|
||||
left = stack_pointer[-2];
|
||||
if (sym_is_const(left) && sym_is_const(right) &&
|
||||
if (sym_is_const(ctx, left) && sym_is_const(ctx, right) &&
|
||||
sym_matches_type(left, &PyLong_Type) && sym_matches_type(right, &PyLong_Type))
|
||||
{
|
||||
assert(PyLong_CheckExact(sym_get_const(left)));
|
||||
assert(PyLong_CheckExact(sym_get_const(right)));
|
||||
assert(PyLong_CheckExact(sym_get_const(ctx, left)));
|
||||
assert(PyLong_CheckExact(sym_get_const(ctx, right)));
|
||||
stack_pointer += -2;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
PyObject *temp = _PyLong_Add((PyLongObject *)sym_get_const(left),
|
||||
(PyLongObject *)sym_get_const(right));
|
||||
PyObject *temp = _PyLong_Add((PyLongObject *)sym_get_const(ctx, left),
|
||||
(PyLongObject *)sym_get_const(ctx, right));
|
||||
if (temp == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -338,15 +341,15 @@
|
|||
JitOptSymbol *res;
|
||||
right = stack_pointer[-1];
|
||||
left = stack_pointer[-2];
|
||||
if (sym_is_const(left) && sym_is_const(right) &&
|
||||
if (sym_is_const(ctx, left) && sym_is_const(ctx, right) &&
|
||||
sym_matches_type(left, &PyLong_Type) && sym_matches_type(right, &PyLong_Type))
|
||||
{
|
||||
assert(PyLong_CheckExact(sym_get_const(left)));
|
||||
assert(PyLong_CheckExact(sym_get_const(right)));
|
||||
assert(PyLong_CheckExact(sym_get_const(ctx, left)));
|
||||
assert(PyLong_CheckExact(sym_get_const(ctx, right)));
|
||||
stack_pointer += -2;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
PyObject *temp = _PyLong_Subtract((PyLongObject *)sym_get_const(left),
|
||||
(PyLongObject *)sym_get_const(right));
|
||||
PyObject *temp = _PyLong_Subtract((PyLongObject *)sym_get_const(ctx, left),
|
||||
(PyLongObject *)sym_get_const(ctx, right));
|
||||
if (temp == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -404,14 +407,14 @@
|
|||
JitOptSymbol *res;
|
||||
right = stack_pointer[-1];
|
||||
left = stack_pointer[-2];
|
||||
if (sym_is_const(left) && sym_is_const(right) &&
|
||||
if (sym_is_const(ctx, left) && sym_is_const(ctx, right) &&
|
||||
sym_matches_type(left, &PyFloat_Type) && sym_matches_type(right, &PyFloat_Type))
|
||||
{
|
||||
assert(PyFloat_CheckExact(sym_get_const(left)));
|
||||
assert(PyFloat_CheckExact(sym_get_const(right)));
|
||||
assert(PyFloat_CheckExact(sym_get_const(ctx, left)));
|
||||
assert(PyFloat_CheckExact(sym_get_const(ctx, right)));
|
||||
PyObject *temp = PyFloat_FromDouble(
|
||||
PyFloat_AS_DOUBLE(sym_get_const(left)) *
|
||||
PyFloat_AS_DOUBLE(sym_get_const(right)));
|
||||
PyFloat_AS_DOUBLE(sym_get_const(ctx, left)) *
|
||||
PyFloat_AS_DOUBLE(sym_get_const(ctx, right)));
|
||||
if (temp == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -438,14 +441,14 @@
|
|||
JitOptSymbol *res;
|
||||
right = stack_pointer[-1];
|
||||
left = stack_pointer[-2];
|
||||
if (sym_is_const(left) && sym_is_const(right) &&
|
||||
if (sym_is_const(ctx, left) && sym_is_const(ctx, right) &&
|
||||
sym_matches_type(left, &PyFloat_Type) && sym_matches_type(right, &PyFloat_Type))
|
||||
{
|
||||
assert(PyFloat_CheckExact(sym_get_const(left)));
|
||||
assert(PyFloat_CheckExact(sym_get_const(right)));
|
||||
assert(PyFloat_CheckExact(sym_get_const(ctx, left)));
|
||||
assert(PyFloat_CheckExact(sym_get_const(ctx, right)));
|
||||
PyObject *temp = PyFloat_FromDouble(
|
||||
PyFloat_AS_DOUBLE(sym_get_const(left)) +
|
||||
PyFloat_AS_DOUBLE(sym_get_const(right)));
|
||||
PyFloat_AS_DOUBLE(sym_get_const(ctx, left)) +
|
||||
PyFloat_AS_DOUBLE(sym_get_const(ctx, right)));
|
||||
if (temp == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -472,14 +475,14 @@
|
|||
JitOptSymbol *res;
|
||||
right = stack_pointer[-1];
|
||||
left = stack_pointer[-2];
|
||||
if (sym_is_const(left) && sym_is_const(right) &&
|
||||
if (sym_is_const(ctx, left) && sym_is_const(ctx, right) &&
|
||||
sym_matches_type(left, &PyFloat_Type) && sym_matches_type(right, &PyFloat_Type))
|
||||
{
|
||||
assert(PyFloat_CheckExact(sym_get_const(left)));
|
||||
assert(PyFloat_CheckExact(sym_get_const(right)));
|
||||
assert(PyFloat_CheckExact(sym_get_const(ctx, left)));
|
||||
assert(PyFloat_CheckExact(sym_get_const(ctx, right)));
|
||||
PyObject *temp = PyFloat_FromDouble(
|
||||
PyFloat_AS_DOUBLE(sym_get_const(left)) -
|
||||
PyFloat_AS_DOUBLE(sym_get_const(right)));
|
||||
PyFloat_AS_DOUBLE(sym_get_const(ctx, left)) -
|
||||
PyFloat_AS_DOUBLE(sym_get_const(ctx, right)));
|
||||
if (temp == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -520,9 +523,9 @@
|
|||
JitOptSymbol *res;
|
||||
right = stack_pointer[-1];
|
||||
left = stack_pointer[-2];
|
||||
if (sym_is_const(left) && sym_is_const(right) &&
|
||||
if (sym_is_const(ctx, left) && sym_is_const(ctx, 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));
|
||||
PyObject *temp = PyUnicode_Concat(sym_get_const(ctx, left), sym_get_const(ctx, right));
|
||||
if (temp == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -547,9 +550,9 @@
|
|||
right = stack_pointer[-1];
|
||||
left = stack_pointer[-2];
|
||||
JitOptSymbol *res;
|
||||
if (sym_is_const(left) && sym_is_const(right) &&
|
||||
if (sym_is_const(ctx, left) && sym_is_const(ctx, 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));
|
||||
PyObject *temp = PyUnicode_Concat(sym_get_const(ctx, left), sym_get_const(ctx, right));
|
||||
if (temp == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -1159,8 +1162,8 @@
|
|||
(void)dict_version;
|
||||
(void)index;
|
||||
attr = NULL;
|
||||
if (sym_is_const(owner)) {
|
||||
PyModuleObject *mod = (PyModuleObject *)sym_get_const(owner);
|
||||
if (sym_is_const(ctx, owner)) {
|
||||
PyModuleObject *mod = (PyModuleObject *)sym_get_const(ctx, owner);
|
||||
if (PyModule_CheckExact(mod)) {
|
||||
PyObject *dict = mod->md_dict;
|
||||
stack_pointer[-1] = attr;
|
||||
|
@ -1655,10 +1658,10 @@
|
|||
JitOptSymbol *callable;
|
||||
callable = stack_pointer[-2 - oparg];
|
||||
uint32_t func_version = (uint32_t)this_instr->operand0;
|
||||
if (sym_is_const(callable) && sym_matches_type(callable, &PyFunction_Type)) {
|
||||
assert(PyFunction_Check(sym_get_const(callable)));
|
||||
if (sym_is_const(ctx, callable) && sym_matches_type(callable, &PyFunction_Type)) {
|
||||
assert(PyFunction_Check(sym_get_const(ctx, callable)));
|
||||
REPLACE_OP(this_instr, _CHECK_FUNCTION_VERSION_INLINE, 0, func_version);
|
||||
this_instr->operand1 = (uintptr_t)sym_get_const(callable);
|
||||
this_instr->operand1 = (uintptr_t)sym_get_const(ctx, callable);
|
||||
}
|
||||
sym_set_type(callable, &PyFunction_Type);
|
||||
break;
|
||||
|
@ -1724,9 +1727,9 @@
|
|||
self_or_null = stack_pointer[-1 - oparg];
|
||||
callable = stack_pointer[-2 - oparg];
|
||||
assert(sym_matches_type(callable, &PyFunction_Type));
|
||||
if (sym_is_const(callable)) {
|
||||
if (sym_is_const(ctx, callable)) {
|
||||
if (sym_is_null(self_or_null) || sym_is_not_null(self_or_null)) {
|
||||
PyFunctionObject *func = (PyFunctionObject *)sym_get_const(callable);
|
||||
PyFunctionObject *func = (PyFunctionObject *)sym_get_const(ctx, callable);
|
||||
PyCodeObject *co = (PyCodeObject *)func->func_code;
|
||||
if (co->co_argcount == oparg + !sym_is_null(self_or_null)) {
|
||||
REPLACE_OP(this_instr, _NOP, 0 ,0);
|
||||
|
@ -2160,12 +2163,12 @@
|
|||
res = sym_new_type(ctx, &PyFloat_Type);
|
||||
}
|
||||
else {
|
||||
if (!sym_is_const(right)) {
|
||||
if (!sym_is_const(ctx, right)) {
|
||||
// Case A or B... can't know without the sign of the RHS:
|
||||
res = sym_new_unknown(ctx);
|
||||
}
|
||||
else {
|
||||
if (_PyLong_IsNegative((PyLongObject *)sym_get_const(right))) {
|
||||
if (_PyLong_IsNegative((PyLongObject *)sym_get_const(ctx, right))) {
|
||||
// Case B:
|
||||
res = sym_new_type(ctx, &PyFloat_Type);
|
||||
}
|
||||
|
@ -2230,8 +2233,8 @@
|
|||
case _GUARD_IS_TRUE_POP: {
|
||||
JitOptSymbol *flag;
|
||||
flag = stack_pointer[-1];
|
||||
if (sym_is_const(flag)) {
|
||||
PyObject *value = sym_get_const(flag);
|
||||
if (sym_is_const(ctx, flag)) {
|
||||
PyObject *value = sym_get_const(ctx, flag);
|
||||
assert(value != NULL);
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
|
@ -2239,6 +2242,7 @@
|
|||
stack_pointer += 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
sym_set_const(flag, Py_True);
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
break;
|
||||
|
@ -2247,8 +2251,8 @@
|
|||
case _GUARD_IS_FALSE_POP: {
|
||||
JitOptSymbol *flag;
|
||||
flag = stack_pointer[-1];
|
||||
if (sym_is_const(flag)) {
|
||||
PyObject *value = sym_get_const(flag);
|
||||
if (sym_is_const(ctx, flag)) {
|
||||
PyObject *value = sym_get_const(ctx, flag);
|
||||
assert(value != NULL);
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
|
@ -2256,6 +2260,7 @@
|
|||
stack_pointer += 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
sym_set_const(flag, Py_False);
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
break;
|
||||
|
@ -2264,8 +2269,8 @@
|
|||
case _GUARD_IS_NONE_POP: {
|
||||
JitOptSymbol *flag;
|
||||
flag = stack_pointer[-1];
|
||||
if (sym_is_const(flag)) {
|
||||
PyObject *value = sym_get_const(flag);
|
||||
if (sym_is_const(ctx, flag)) {
|
||||
PyObject *value = sym_get_const(ctx, flag);
|
||||
assert(value != NULL);
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
|
@ -2283,14 +2288,15 @@
|
|||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
}
|
||||
sym_set_const(flag, Py_None);
|
||||
break;
|
||||
}
|
||||
|
||||
case _GUARD_IS_NOT_NONE_POP: {
|
||||
JitOptSymbol *flag;
|
||||
flag = stack_pointer[-1];
|
||||
if (sym_is_const(flag)) {
|
||||
PyObject *value = sym_get_const(flag);
|
||||
if (sym_is_const(ctx, flag)) {
|
||||
PyObject *value = sym_get_const(ctx, flag);
|
||||
assert(value != NULL);
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
|
|
|
@ -48,6 +48,12 @@ static JitOptSymbol NO_SPACE_SYMBOL = {
|
|||
.tag = JIT_SYM_BOTTOM_TAG
|
||||
};
|
||||
|
||||
static JitOptSymbol *
|
||||
allocation_base(JitOptContext *ctx)
|
||||
{
|
||||
return ctx->t_arena.arena;
|
||||
}
|
||||
|
||||
JitOptSymbol *
|
||||
out_of_space(JitOptContext *ctx)
|
||||
{
|
||||
|
@ -70,6 +76,12 @@ sym_new(JitOptContext *ctx)
|
|||
return self;
|
||||
}
|
||||
|
||||
static void make_const(JitOptSymbol *sym, PyObject *val)
|
||||
{
|
||||
sym->tag = JIT_SYM_KNOWN_VALUE_TAG;
|
||||
sym->value.value = Py_NewRef(val);
|
||||
}
|
||||
|
||||
static inline void
|
||||
sym_set_bottom(JitOptContext *ctx, JitOptSymbol *sym)
|
||||
{
|
||||
|
@ -90,9 +102,21 @@ _Py_uop_sym_is_not_null(JitOptSymbol *sym) {
|
|||
}
|
||||
|
||||
bool
|
||||
_Py_uop_sym_is_const(JitOptSymbol *sym)
|
||||
_Py_uop_sym_is_const(JitOptContext *ctx, JitOptSymbol *sym)
|
||||
{
|
||||
return sym->tag == JIT_SYM_KNOWN_VALUE_TAG;
|
||||
if (sym->tag == JIT_SYM_KNOWN_VALUE_TAG) {
|
||||
return true;
|
||||
}
|
||||
if (sym->tag == JIT_SYM_TRUTHINESS_TAG) {
|
||||
JitOptSymbol *value = allocation_base(ctx) + sym->truthiness.value;
|
||||
int truthiness = _Py_uop_sym_truthiness(ctx, value);
|
||||
if (truthiness < 0) {
|
||||
return false;
|
||||
}
|
||||
make_const(sym, (truthiness ^ sym->truthiness.not) ? Py_True : Py_False);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -103,11 +127,21 @@ _Py_uop_sym_is_null(JitOptSymbol *sym)
|
|||
|
||||
|
||||
PyObject *
|
||||
_Py_uop_sym_get_const(JitOptSymbol *sym)
|
||||
_Py_uop_sym_get_const(JitOptContext *ctx, JitOptSymbol *sym)
|
||||
{
|
||||
if (sym->tag == JIT_SYM_KNOWN_VALUE_TAG) {
|
||||
return sym->value.value;
|
||||
}
|
||||
if (sym->tag == JIT_SYM_TRUTHINESS_TAG) {
|
||||
JitOptSymbol *value = allocation_base(ctx) + sym->truthiness.value;
|
||||
int truthiness = _Py_uop_sym_truthiness(ctx, value);
|
||||
if (truthiness < 0) {
|
||||
return NULL;
|
||||
}
|
||||
PyObject *res = (truthiness ^ sym->truthiness.not) ? Py_True : Py_False;
|
||||
make_const(sym, res);
|
||||
return res;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -153,6 +187,11 @@ _Py_uop_sym_set_type(JitOptContext *ctx, JitOptSymbol *sym, PyTypeObject *typ)
|
|||
sym->cls.version = 0;
|
||||
sym->cls.type = typ;
|
||||
return;
|
||||
case JIT_SYM_TRUTHINESS_TAG:
|
||||
if (typ != &PyBool_Type) {
|
||||
sym_set_bottom(ctx, sym);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -193,16 +232,16 @@ _Py_uop_sym_set_type_version(JitOptContext *ctx, JitOptSymbol *sym, unsigned int
|
|||
sym->tag = JIT_SYM_TYPE_VERSION_TAG;
|
||||
sym->version.version = version;
|
||||
return true;
|
||||
case JIT_SYM_TRUTHINESS_TAG:
|
||||
if (version != PyBool_Type.tp_version_tag) {
|
||||
sym_set_bottom(ctx, sym);
|
||||
return false;
|
||||
}
|
||||
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(JitOptContext *ctx, JitOptSymbol *sym, PyObject *const_val)
|
||||
{
|
||||
|
@ -240,6 +279,29 @@ _Py_uop_sym_set_const(JitOptContext *ctx, JitOptSymbol *sym, PyObject *const_val
|
|||
case JIT_SYM_UNKNOWN_TAG:
|
||||
make_const(sym, const_val);
|
||||
return;
|
||||
case JIT_SYM_TRUTHINESS_TAG:
|
||||
if (!PyBool_Check(const_val) ||
|
||||
(_Py_uop_sym_is_const(ctx, sym) &&
|
||||
_Py_uop_sym_get_const(ctx, sym) != const_val))
|
||||
{
|
||||
sym_set_bottom(ctx, sym);
|
||||
return;
|
||||
}
|
||||
JitOptSymbol *value = allocation_base(ctx) + sym->truthiness.value;
|
||||
PyTypeObject *type = _Py_uop_sym_get_type(value);
|
||||
if (const_val == (sym->truthiness.not ? Py_False : Py_True)) {
|
||||
// value is truthy. This is only useful for bool:
|
||||
if (type == &PyBool_Type) {
|
||||
_Py_uop_sym_set_const(ctx, value, Py_True);
|
||||
}
|
||||
}
|
||||
// value is falsey:
|
||||
else if (type == &PyBool_Type) {
|
||||
_Py_uop_sym_set_const(ctx, value, Py_False);
|
||||
}
|
||||
// TODO: More types (GH-130415)!
|
||||
make_const(sym, const_val);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -339,6 +401,8 @@ _Py_uop_sym_get_type(JitOptSymbol *sym)
|
|||
return Py_TYPE(sym->value.value);
|
||||
case JIT_SYM_TUPLE_TAG:
|
||||
return &PyTuple_Type;
|
||||
case JIT_SYM_TRUTHINESS_TAG:
|
||||
return &PyBool_Type;
|
||||
}
|
||||
Py_UNREACHABLE();
|
||||
}
|
||||
|
@ -361,6 +425,8 @@ _Py_uop_sym_get_type_version(JitOptSymbol *sym)
|
|||
return Py_TYPE(sym->value.value)->tp_version_tag;
|
||||
case JIT_SYM_TUPLE_TAG:
|
||||
return PyTuple_Type.tp_version_tag;
|
||||
case JIT_SYM_TRUTHINESS_TAG:
|
||||
return PyBool_Type.tp_version_tag;
|
||||
}
|
||||
Py_UNREACHABLE();
|
||||
}
|
||||
|
@ -379,6 +445,7 @@ _Py_uop_sym_has_type(JitOptSymbol *sym)
|
|||
case JIT_SYM_KNOWN_CLASS_TAG:
|
||||
case JIT_SYM_KNOWN_VALUE_TAG:
|
||||
case JIT_SYM_TUPLE_TAG:
|
||||
case JIT_SYM_TRUTHINESS_TAG:
|
||||
return true;
|
||||
}
|
||||
Py_UNREACHABLE();
|
||||
|
@ -398,7 +465,7 @@ _Py_uop_sym_matches_type_version(JitOptSymbol *sym, unsigned int version)
|
|||
}
|
||||
|
||||
int
|
||||
_Py_uop_sym_truthiness(JitOptSymbol *sym)
|
||||
_Py_uop_sym_truthiness(JitOptContext *ctx, JitOptSymbol *sym)
|
||||
{
|
||||
switch(sym->tag) {
|
||||
case JIT_SYM_NULL_TAG:
|
||||
|
@ -416,6 +483,16 @@ _Py_uop_sym_truthiness(JitOptSymbol *sym)
|
|||
break;
|
||||
case JIT_SYM_TUPLE_TAG:
|
||||
return sym->tuple.length != 0;
|
||||
case JIT_SYM_TRUTHINESS_TAG:
|
||||
;
|
||||
JitOptSymbol *value = allocation_base(ctx) + sym->truthiness.value;
|
||||
int truthiness = _Py_uop_sym_truthiness(ctx, value);
|
||||
if (truthiness < 0) {
|
||||
return truthiness;
|
||||
}
|
||||
truthiness ^= sym->truthiness.not;
|
||||
make_const(sym, truthiness ? Py_True : Py_False);
|
||||
return truthiness;
|
||||
}
|
||||
PyObject *value = sym->value.value;
|
||||
/* Only handle a few known safe types */
|
||||
|
@ -435,12 +512,6 @@ _Py_uop_sym_truthiness(JitOptSymbol *sym)
|
|||
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)
|
||||
{
|
||||
|
@ -503,9 +574,36 @@ _Py_uop_sym_is_immortal(JitOptSymbol *sym)
|
|||
if (sym->tag == JIT_SYM_KNOWN_CLASS_TAG) {
|
||||
return sym->cls.type == &PyBool_Type;
|
||||
}
|
||||
if (sym->tag == JIT_SYM_TRUTHINESS_TAG) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
JitOptSymbol *
|
||||
_Py_uop_sym_new_truthiness(JitOptContext *ctx, JitOptSymbol *value, bool truthy)
|
||||
{
|
||||
// It's clearer to invert this in the signature:
|
||||
bool not = !truthy;
|
||||
if (value->tag == JIT_SYM_TRUTHINESS_TAG && value->truthiness.not == not) {
|
||||
return value;
|
||||
}
|
||||
JitOptSymbol *res = sym_new(ctx);
|
||||
if (res == NULL) {
|
||||
return out_of_space(ctx);
|
||||
}
|
||||
int truthiness = _Py_uop_sym_truthiness(ctx, value);
|
||||
if (truthiness < 0) {
|
||||
res->tag = JIT_SYM_TRUTHINESS_TAG;
|
||||
res->truthiness.not = not;
|
||||
res->truthiness.value = (uint16_t)(value - allocation_base(ctx));
|
||||
}
|
||||
else {
|
||||
make_const(res, (truthiness ^ not) ? Py_True : Py_False);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// 0 on success, -1 on error.
|
||||
_Py_UOpsAbstractFrame *
|
||||
_Py_uop_frame_new(
|
||||
|
@ -570,7 +668,7 @@ _Py_uop_abstractcontext_fini(JitOptContext *ctx)
|
|||
void
|
||||
_Py_uop_abstractcontext_init(JitOptContext *ctx)
|
||||
{
|
||||
static_assert(sizeof(JitOptSymbol) <= 2*sizeof(uint64_t));
|
||||
static_assert(sizeof(JitOptSymbol) <= 2 * sizeof(uint64_t), "JitOptSymbol has grown");
|
||||
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.
|
||||
|
@ -625,6 +723,7 @@ _Py_uop_symbols_test(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
|
|||
_Py_uop_abstractcontext_init(ctx);
|
||||
PyObject *val_42 = NULL;
|
||||
PyObject *val_43 = NULL;
|
||||
PyObject *tuple = NULL;
|
||||
|
||||
// Use a single 'sym' variable so copy-pasting tests is easier.
|
||||
JitOptSymbol *sym = _Py_uop_sym_new_unknown(ctx);
|
||||
|
@ -634,8 +733,8 @@ _Py_uop_symbols_test(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
|
|||
TEST_PREDICATE(!_Py_uop_sym_is_null(sym), "top is NULL");
|
||||
TEST_PREDICATE(!_Py_uop_sym_is_not_null(sym), "top is not NULL");
|
||||
TEST_PREDICATE(!_Py_uop_sym_matches_type(sym, &PyLong_Type), "top matches a type");
|
||||
TEST_PREDICATE(!_Py_uop_sym_is_const(sym), "top is a constant");
|
||||
TEST_PREDICATE(_Py_uop_sym_get_const(sym) == NULL, "top as constant is not NULL");
|
||||
TEST_PREDICATE(!_Py_uop_sym_is_const(ctx, sym), "top is a constant");
|
||||
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, sym) == NULL, "top as constant is not NULL");
|
||||
TEST_PREDICATE(!_Py_uop_sym_is_bottom(sym), "top is bottom");
|
||||
|
||||
sym = make_bottom(ctx);
|
||||
|
@ -645,8 +744,8 @@ _Py_uop_symbols_test(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
|
|||
TEST_PREDICATE(!_Py_uop_sym_is_null(sym), "bottom is NULL is not false");
|
||||
TEST_PREDICATE(!_Py_uop_sym_is_not_null(sym), "bottom is not NULL is not false");
|
||||
TEST_PREDICATE(!_Py_uop_sym_matches_type(sym, &PyLong_Type), "bottom matches a type");
|
||||
TEST_PREDICATE(!_Py_uop_sym_is_const(sym), "bottom is a constant is not false");
|
||||
TEST_PREDICATE(_Py_uop_sym_get_const(sym) == NULL, "bottom as constant is not NULL");
|
||||
TEST_PREDICATE(!_Py_uop_sym_is_const(ctx, sym), "bottom is a constant is not false");
|
||||
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, sym) == NULL, "bottom as constant is not NULL");
|
||||
TEST_PREDICATE(_Py_uop_sym_is_bottom(sym), "bottom isn't bottom");
|
||||
|
||||
sym = _Py_uop_sym_new_type(ctx, &PyLong_Type);
|
||||
|
@ -657,8 +756,8 @@ _Py_uop_symbols_test(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
|
|||
TEST_PREDICATE(_Py_uop_sym_is_not_null(sym), "int isn't not NULL");
|
||||
TEST_PREDICATE(_Py_uop_sym_matches_type(sym, &PyLong_Type), "int isn't int");
|
||||
TEST_PREDICATE(!_Py_uop_sym_matches_type(sym, &PyFloat_Type), "int matches float");
|
||||
TEST_PREDICATE(!_Py_uop_sym_is_const(sym), "int is a constant");
|
||||
TEST_PREDICATE(_Py_uop_sym_get_const(sym) == NULL, "int as constant is not NULL");
|
||||
TEST_PREDICATE(!_Py_uop_sym_is_const(ctx, sym), "int is a constant");
|
||||
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, sym) == NULL, "int as constant is not NULL");
|
||||
|
||||
_Py_uop_sym_set_type(ctx, sym, &PyLong_Type); // Should be a no-op
|
||||
TEST_PREDICATE(_Py_uop_sym_matches_type(sym, &PyLong_Type), "(int and int) isn't int");
|
||||
|
@ -679,19 +778,19 @@ _Py_uop_symbols_test(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
|
|||
goto fail;
|
||||
}
|
||||
_Py_uop_sym_set_const(ctx, sym, val_42);
|
||||
TEST_PREDICATE(_Py_uop_sym_truthiness(sym) == 1, "bool(42) is not True");
|
||||
TEST_PREDICATE(_Py_uop_sym_truthiness(ctx, sym) == 1, "bool(42) is not True");
|
||||
TEST_PREDICATE(!_Py_uop_sym_is_null(sym), "42 is NULL");
|
||||
TEST_PREDICATE(_Py_uop_sym_is_not_null(sym), "42 isn't not NULL");
|
||||
TEST_PREDICATE(_Py_uop_sym_matches_type(sym, &PyLong_Type), "42 isn't an int");
|
||||
TEST_PREDICATE(!_Py_uop_sym_matches_type(sym, &PyFloat_Type), "42 matches float");
|
||||
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_const(ctx, sym), "42 is not a constant");
|
||||
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, sym) != NULL, "42 as constant is NULL");
|
||||
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, 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");
|
||||
TEST_PREDICATE(_Py_uop_sym_get_const(sym) == val_42, "(42 and 42) as constant isn't 42");
|
||||
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, sym) == val_42, "(42 and 42) as constant isn't 42");
|
||||
|
||||
_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");
|
||||
|
@ -709,11 +808,11 @@ _Py_uop_symbols_test(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
|
|||
|
||||
|
||||
sym = _Py_uop_sym_new_const(ctx, Py_None);
|
||||
TEST_PREDICATE(_Py_uop_sym_truthiness(sym) == 0, "bool(None) is not False");
|
||||
TEST_PREDICATE(_Py_uop_sym_truthiness(ctx, sym) == 0, "bool(None) is not False");
|
||||
sym = _Py_uop_sym_new_const(ctx, Py_False);
|
||||
TEST_PREDICATE(_Py_uop_sym_truthiness(sym) == 0, "bool(False) is not False");
|
||||
TEST_PREDICATE(_Py_uop_sym_truthiness(ctx, sym) == 0, "bool(False) is not False");
|
||||
sym = _Py_uop_sym_new_const(ctx, PyLong_FromLong(0));
|
||||
TEST_PREDICATE(_Py_uop_sym_truthiness(sym) == 0, "bool(0) is not False");
|
||||
TEST_PREDICATE(_Py_uop_sym_truthiness(ctx, 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);
|
||||
|
@ -724,17 +823,31 @@ _Py_uop_symbols_test(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
|
|||
"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,
|
||||
_Py_uop_sym_get_const(ctx, _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);
|
||||
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,
|
||||
_Py_uop_sym_get_const(ctx, _Py_uop_sym_tuple_getitem(ctx, sym, 1)) == val_43,
|
||||
"tuple item does not match value used to create tuple"
|
||||
);
|
||||
|
||||
JitOptSymbol *value = _Py_uop_sym_new_type(ctx, &PyBool_Type);
|
||||
sym = _Py_uop_sym_new_truthiness(ctx, value, false);
|
||||
TEST_PREDICATE(_Py_uop_sym_matches_type(sym, &PyBool_Type), "truthiness is not boolean");
|
||||
TEST_PREDICATE(_Py_uop_sym_truthiness(ctx, sym) == -1, "truthiness is not unknown");
|
||||
TEST_PREDICATE(_Py_uop_sym_is_const(ctx, sym) == false, "truthiness is constant");
|
||||
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, sym) == NULL, "truthiness is not NULL");
|
||||
TEST_PREDICATE(_Py_uop_sym_is_const(ctx, value) == false, "value is constant");
|
||||
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, value) == NULL, "value is not NULL");
|
||||
_Py_uop_sym_set_const(ctx, sym, Py_False);
|
||||
TEST_PREDICATE(_Py_uop_sym_matches_type(sym, &PyBool_Type), "truthiness is not boolean");
|
||||
TEST_PREDICATE(_Py_uop_sym_truthiness(ctx, sym) == 0, "truthiness is not True");
|
||||
TEST_PREDICATE(_Py_uop_sym_is_const(ctx, sym) == true, "truthiness is not constant");
|
||||
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, sym) == Py_False, "truthiness is not False");
|
||||
TEST_PREDICATE(_Py_uop_sym_is_const(ctx, value) == true, "value is not constant");
|
||||
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, value) == Py_True, "value is not True");
|
||||
_Py_uop_abstractcontext_fini(ctx);
|
||||
Py_DECREF(val_42);
|
||||
Py_DECREF(val_43);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue