mirror of
https://github.com/python/cpython.git
synced 2026-02-06 18:01:17 +00:00
GH-144179: Use recorded values to make optimizer more robust (GH-144437)
* Add three new symbol kinds * Do not smuggle code object in _PUSH_FRAME operand * Fix small bug in predicate analysis
This commit is contained in:
parent
b6d8aa436b
commit
b53fc7caa6
16 changed files with 2062 additions and 1507 deletions
170
Python/optimizer_cases.c.h
generated
170
Python/optimizer_cases.c.h
generated
|
|
@ -1115,8 +1115,21 @@
|
|||
}
|
||||
|
||||
case _BINARY_OP_SUBSCR_CHECK_FUNC: {
|
||||
JitOptRef container;
|
||||
JitOptRef getitem;
|
||||
container = stack_pointer[-2];
|
||||
getitem = sym_new_not_null(ctx);
|
||||
PyTypeObject *tp = sym_get_type(container);
|
||||
if (tp == NULL) {
|
||||
PyObject *c = sym_get_probable_value(container);
|
||||
if (c != NULL) {
|
||||
tp = Py_TYPE(c);
|
||||
}
|
||||
}
|
||||
if (tp != NULL) {
|
||||
PyObject *getitem_o = ((PyHeapTypeObject *)tp)->_spec_cache.getitem;
|
||||
sym_set_recorded_value(getitem, getitem_o);
|
||||
}
|
||||
CHECK_STACK_BOUNDS(1);
|
||||
stack_pointer[0] = getitem;
|
||||
stack_pointer += 1;
|
||||
|
|
@ -1125,18 +1138,14 @@
|
|||
}
|
||||
|
||||
case _BINARY_OP_SUBSCR_INIT_CALL: {
|
||||
JitOptRef getitem;
|
||||
JitOptRef sub;
|
||||
JitOptRef container;
|
||||
JitOptRef new_frame;
|
||||
getitem = stack_pointer[-1];
|
||||
sub = stack_pointer[-2];
|
||||
container = stack_pointer[-3];
|
||||
assert((this_instr + 1)->opcode == _PUSH_FRAME);
|
||||
PyCodeObject *co = get_code_with_logging(this_instr + 1);
|
||||
if (co == NULL) {
|
||||
ctx->done = true;
|
||||
break;
|
||||
}
|
||||
_Py_UOpsAbstractFrame *f = frame_new(ctx, co, 0, NULL, 0);
|
||||
_Py_UOpsAbstractFrame *f = frame_new_from_symbol(ctx, getitem, 0, NULL, 0);
|
||||
if (f == NULL) {
|
||||
break;
|
||||
}
|
||||
|
|
@ -1239,7 +1248,9 @@
|
|||
stack_pointer += -1;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
ctx->frame->stack_pointer = stack_pointer;
|
||||
PyCodeObject *returning_code = get_code_with_logging(this_instr);
|
||||
assert(this_instr[1].opcode == _RECORD_CODE);
|
||||
PyCodeObject *returning_code = (PyCodeObject *)this_instr[1].operand0;
|
||||
assert(PyCode_Check(returning_code));
|
||||
if (returning_code == NULL) {
|
||||
ctx->done = true;
|
||||
break;
|
||||
|
|
@ -1248,8 +1259,8 @@
|
|||
if (ctx->curr_frame_depth >= 2) {
|
||||
PyCodeObject *expected_code = ctx->frames[ctx->curr_frame_depth - 2].code;
|
||||
if (expected_code == returning_code) {
|
||||
assert((this_instr + 1)->opcode == _GUARD_IP_RETURN_VALUE);
|
||||
REPLACE_OP((this_instr + 1), _NOP, 0, 0);
|
||||
assert(this_instr[2].opcode == _GUARD_IP_RETURN_VALUE);
|
||||
REPLACE_OP((this_instr + 2), _NOP, 0, 0);
|
||||
}
|
||||
}
|
||||
if (frame_pop(ctx, returning_code, returning_stacklevel)) {
|
||||
|
|
@ -1292,15 +1303,11 @@
|
|||
|
||||
case _SEND_GEN_FRAME: {
|
||||
JitOptRef v;
|
||||
JitOptRef receiver;
|
||||
JitOptRef gen_frame;
|
||||
v = stack_pointer[-1];
|
||||
assert((this_instr + 1)->opcode == _PUSH_FRAME);
|
||||
PyCodeObject *co = get_code_with_logging((this_instr + 1));
|
||||
if (co == NULL) {
|
||||
ctx->done = true;
|
||||
break;
|
||||
}
|
||||
_Py_UOpsAbstractFrame *new_frame = frame_new(ctx, co, 1, NULL, 0);
|
||||
receiver = stack_pointer[-2];
|
||||
_Py_UOpsAbstractFrame *new_frame = frame_new_from_symbol(ctx, receiver, 1, NULL, 0);
|
||||
if (new_frame == NULL) {
|
||||
ctx->done = true;
|
||||
break;
|
||||
|
|
@ -1320,7 +1327,9 @@
|
|||
stack_pointer += -1;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
ctx->frame->stack_pointer = stack_pointer;
|
||||
PyCodeObject *returning_code = get_code_with_logging(this_instr);
|
||||
assert(this_instr[1].opcode == _RECORD_CODE);
|
||||
PyCodeObject *returning_code = (PyCodeObject *)this_instr[1].operand0;
|
||||
assert(PyCode_Check(returning_code));
|
||||
if (returning_code == NULL) {
|
||||
ctx->done = true;
|
||||
break;
|
||||
|
|
@ -1984,12 +1993,7 @@
|
|||
JitOptRef new_frame;
|
||||
owner = stack_pointer[-1];
|
||||
PyObject *fget = (PyObject *)this_instr->operand0;
|
||||
assert((this_instr + 2)->opcode == _PUSH_FRAME);
|
||||
PyCodeObject *co = get_code_with_logging(this_instr + 2);
|
||||
if (co == NULL) {
|
||||
ctx->done = true;
|
||||
break;
|
||||
}
|
||||
PyCodeObject *co = (PyCodeObject *)((PyFunctionObject *)fget)->func_code;
|
||||
_Py_UOpsAbstractFrame *f = frame_new(ctx, co, 0, NULL, 0);
|
||||
if (f == NULL) {
|
||||
break;
|
||||
|
|
@ -2267,16 +2271,7 @@
|
|||
JitOptRef r;
|
||||
right = stack_pointer[-1];
|
||||
left = stack_pointer[-2];
|
||||
int cmp_mask = oparg & (COMPARE_LT_MASK | COMPARE_GT_MASK | COMPARE_EQ_MASK);
|
||||
if (cmp_mask == COMPARE_EQ_MASK) {
|
||||
res = sym_new_predicate(ctx, left, right, JIT_PRED_EQ);
|
||||
}
|
||||
else if (cmp_mask == (COMPARE_LT_MASK | COMPARE_GT_MASK)) {
|
||||
res = sym_new_predicate(ctx, left, right, JIT_PRED_NE);
|
||||
}
|
||||
else {
|
||||
res = sym_new_type(ctx, &PyBool_Type);
|
||||
}
|
||||
res = sym_new_type(ctx, &PyBool_Type);
|
||||
l = left;
|
||||
r = right;
|
||||
if (
|
||||
|
|
@ -2694,14 +2689,10 @@
|
|||
}
|
||||
|
||||
case _FOR_ITER_GEN_FRAME: {
|
||||
JitOptRef iter;
|
||||
JitOptRef gen_frame;
|
||||
assert((this_instr + 1)->opcode == _PUSH_FRAME);
|
||||
PyCodeObject *co = get_code_with_logging((this_instr + 1));
|
||||
if (co == NULL) {
|
||||
ctx->done = true;
|
||||
break;
|
||||
}
|
||||
_Py_UOpsAbstractFrame *new_frame = frame_new(ctx, co, 1, NULL, 0);
|
||||
iter = stack_pointer[-2];
|
||||
_Py_UOpsAbstractFrame *new_frame = frame_new_from_symbol(ctx, iter, 1, NULL, 0);
|
||||
if (new_frame == NULL) {
|
||||
ctx->done = true;
|
||||
break;
|
||||
|
|
@ -2884,14 +2875,10 @@
|
|||
/* _MONITOR_CALL is not a viable micro-op for tier 2 */
|
||||
|
||||
case _PY_FRAME_GENERAL: {
|
||||
JitOptRef callable;
|
||||
JitOptRef new_frame;
|
||||
assert((this_instr + 2)->opcode == _PUSH_FRAME);
|
||||
PyCodeObject *co = get_code_with_logging((this_instr + 2));
|
||||
if (co == NULL) {
|
||||
ctx->done = true;
|
||||
break;
|
||||
}
|
||||
new_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, NULL, 0));
|
||||
callable = stack_pointer[-2 - oparg];
|
||||
new_frame = PyJitRef_WrapInvalid(frame_new_from_symbol(ctx, callable, 0, NULL, 0));
|
||||
CHECK_STACK_BOUNDS(-1 - oparg);
|
||||
stack_pointer[-2 - oparg] = new_frame;
|
||||
stack_pointer += -1 - oparg;
|
||||
|
|
@ -2996,8 +2983,9 @@
|
|||
}
|
||||
|
||||
case _CHECK_STACK_SPACE: {
|
||||
assert((this_instr + 4)->opcode == _PUSH_FRAME);
|
||||
PyCodeObject *co = get_code_with_logging((this_instr + 4));
|
||||
JitOptRef callable;
|
||||
callable = stack_pointer[-2 - oparg];
|
||||
PyCodeObject *co = sym_get_probable_func_code(callable);
|
||||
if (co == NULL) {
|
||||
ctx->done = true;
|
||||
break;
|
||||
|
|
@ -3013,16 +3001,12 @@
|
|||
case _INIT_CALL_PY_EXACT_ARGS: {
|
||||
JitOptRef *args;
|
||||
JitOptRef self_or_null;
|
||||
JitOptRef callable;
|
||||
JitOptRef new_frame;
|
||||
args = &stack_pointer[-oparg];
|
||||
self_or_null = stack_pointer[-1 - oparg];
|
||||
callable = stack_pointer[-2 - oparg];
|
||||
int argcount = oparg;
|
||||
assert((this_instr + 2)->opcode == _PUSH_FRAME);
|
||||
PyCodeObject *co = get_code_with_logging((this_instr + 2));
|
||||
if (co == NULL) {
|
||||
ctx->done = true;
|
||||
break;
|
||||
}
|
||||
assert(!PyJitRef_IsNull(self_or_null));
|
||||
assert(args != NULL);
|
||||
if (sym_is_not_null(self_or_null)) {
|
||||
|
|
@ -3030,9 +3014,9 @@
|
|||
argcount++;
|
||||
}
|
||||
if (sym_is_null(self_or_null) || sym_is_not_null(self_or_null)) {
|
||||
new_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, args, argcount));
|
||||
new_frame = PyJitRef_WrapInvalid(frame_new_from_symbol(ctx, callable, 0, args, argcount));
|
||||
} else {
|
||||
new_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, NULL, 0));
|
||||
new_frame = PyJitRef_WrapInvalid(frame_new_from_symbol(ctx, callable, 0, NULL, 0));
|
||||
}
|
||||
CHECK_STACK_BOUNDS(-1 - oparg);
|
||||
stack_pointer[-2 - oparg] = new_frame;
|
||||
|
|
@ -3053,19 +3037,11 @@
|
|||
ctx->frame = (_Py_UOpsAbstractFrame *)PyJitRef_Unwrap(new_frame);
|
||||
ctx->curr_frame_depth++;
|
||||
stack_pointer = ctx->frame->stack_pointer;
|
||||
uint64_t operand = this_instr->operand0;
|
||||
if (operand == 0) {
|
||||
ctx->done = true;
|
||||
break;
|
||||
}
|
||||
if (!(operand & 1)) {
|
||||
PyFunctionObject *func = (PyFunctionObject *)operand;
|
||||
ctx->frame->func = func;
|
||||
}
|
||||
if ((this_instr-1)->opcode == _CREATE_INIT_FRAME) {
|
||||
assert((this_instr+1)->opcode == _GUARD_IP__PUSH_FRAME);
|
||||
REPLACE_OP(this_instr+1, _NOP, 0, 0);
|
||||
}
|
||||
assert(ctx->frame->locals != NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -3212,9 +3188,11 @@
|
|||
case _CREATE_INIT_FRAME: {
|
||||
JitOptRef *args;
|
||||
JitOptRef self;
|
||||
JitOptRef init;
|
||||
JitOptRef init_frame;
|
||||
args = &stack_pointer[-oparg];
|
||||
self = stack_pointer[-1 - oparg];
|
||||
init = stack_pointer[-2 - oparg];
|
||||
ctx->frame->stack_pointer = stack_pointer - oparg - 2;
|
||||
_Py_UOpsAbstractFrame *shim = frame_new(ctx, (PyCodeObject *)&_Py_InitCleanup, 0, NULL, 0);
|
||||
if (shim == NULL) {
|
||||
|
|
@ -3226,8 +3204,7 @@
|
|||
ctx->frame = shim;
|
||||
ctx->curr_frame_depth++;
|
||||
assert((this_instr + 1)->opcode == _PUSH_FRAME);
|
||||
PyCodeObject *co = get_code_with_logging((this_instr + 1));
|
||||
init_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, args-1, oparg+1));
|
||||
init_frame = PyJitRef_WrapInvalid(frame_new_from_symbol(ctx, init, 0, args-1, oparg+1));
|
||||
CHECK_STACK_BOUNDS(-1 - oparg);
|
||||
stack_pointer[-2 - oparg] = init_frame;
|
||||
stack_pointer += -1 - oparg;
|
||||
|
|
@ -3501,14 +3478,10 @@
|
|||
/* _DO_CALL_KW is not a viable micro-op for tier 2 */
|
||||
|
||||
case _PY_FRAME_KW: {
|
||||
JitOptRef callable;
|
||||
JitOptRef new_frame;
|
||||
assert((this_instr + 2)->opcode == _PUSH_FRAME);
|
||||
PyCodeObject *co = get_code_with_logging((this_instr + 2));
|
||||
if (co == NULL) {
|
||||
ctx->done = true;
|
||||
break;
|
||||
}
|
||||
new_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, NULL, 0));
|
||||
callable = stack_pointer[-3 - oparg];
|
||||
new_frame = PyJitRef_WrapInvalid(frame_new_from_symbol(ctx, callable, 0, NULL, 0));
|
||||
CHECK_STACK_BOUNDS(-2 - oparg);
|
||||
stack_pointer[-3 - oparg] = new_frame;
|
||||
stack_pointer += -2 - oparg;
|
||||
|
|
@ -3553,14 +3526,10 @@
|
|||
}
|
||||
|
||||
case _PY_FRAME_EX: {
|
||||
JitOptRef func_st;
|
||||
JitOptRef ex_frame;
|
||||
assert((this_instr + 2)->opcode == _PUSH_FRAME);
|
||||
PyCodeObject *co = get_code_with_logging((this_instr + 2));
|
||||
if (co == NULL) {
|
||||
ctx->done = true;
|
||||
break;
|
||||
}
|
||||
ex_frame = PyJitRef_WrapInvalid(frame_new(ctx, co, 0, NULL, 0));
|
||||
func_st = stack_pointer[-4];
|
||||
ex_frame = PyJitRef_WrapInvalid(frame_new_from_symbol(ctx, func_st, 0, NULL, 0));
|
||||
CHECK_STACK_BOUNDS(-3);
|
||||
stack_pointer[-4] = ex_frame;
|
||||
stack_pointer += -3;
|
||||
|
|
@ -3602,7 +3571,9 @@
|
|||
case _RETURN_GENERATOR: {
|
||||
JitOptRef res;
|
||||
ctx->frame->stack_pointer = stack_pointer;
|
||||
PyCodeObject *returning_code = get_code_with_logging(this_instr);
|
||||
assert(this_instr[1].opcode == _RECORD_CODE);
|
||||
PyCodeObject *returning_code = (PyCodeObject *)this_instr[1].operand0;
|
||||
assert(PyCode_Check(returning_code));
|
||||
if (returning_code == NULL) {
|
||||
ctx->done = true;
|
||||
break;
|
||||
|
|
@ -4167,6 +4138,10 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _GUARD_CODE: {
|
||||
break;
|
||||
}
|
||||
|
||||
case _GUARD_IP__PUSH_FRAME: {
|
||||
break;
|
||||
}
|
||||
|
|
@ -4184,22 +4159,47 @@
|
|||
}
|
||||
|
||||
case _RECORD_TOS: {
|
||||
JitOptRef tos;
|
||||
tos = stack_pointer[-1];
|
||||
sym_set_recorded_value(tos, (PyObject *)this_instr->operand0);
|
||||
break;
|
||||
}
|
||||
|
||||
case _RECORD_TOS_TYPE: {
|
||||
JitOptRef tos;
|
||||
tos = stack_pointer[-1];
|
||||
PyTypeObject *tp = (PyTypeObject *)this_instr->operand0;
|
||||
sym_set_recorded_type(tos, tp);
|
||||
break;
|
||||
}
|
||||
|
||||
case _RECORD_NOS: {
|
||||
JitOptRef nos;
|
||||
nos = stack_pointer[-2];
|
||||
sym_set_recorded_value(nos, (PyObject *)this_instr->operand0);
|
||||
break;
|
||||
}
|
||||
|
||||
case _RECORD_NOS_GEN_FUNC: {
|
||||
JitOptRef nos;
|
||||
nos = stack_pointer[-2];
|
||||
PyFunctionObject *func = (PyFunctionObject *)this_instr->operand0;
|
||||
assert(func == NULL || PyFunction_Check(func));
|
||||
sym_set_recorded_gen_func(nos, func);
|
||||
break;
|
||||
}
|
||||
|
||||
case _RECORD_4OS: {
|
||||
JitOptRef value;
|
||||
value = stack_pointer[-4];
|
||||
sym_set_recorded_value(value, (PyObject *)this_instr->operand0);
|
||||
break;
|
||||
}
|
||||
|
||||
case _RECORD_CALLABLE: {
|
||||
JitOptRef func;
|
||||
func = stack_pointer[-2 - oparg];
|
||||
sym_set_recorded_value(func, (PyObject *)this_instr->operand0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -4207,7 +4207,7 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _RECORD_CALLER_CODE: {
|
||||
case _RECORD_CODE: {
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue