GH-138378: Move globals-to-consts pass into main optimizer pass (GH-138379)

This commit is contained in:
Mark Shannon 2025-09-18 10:09:59 +01:00 committed by GitHub
parent d22b25081b
commit 3b83257366
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 486 additions and 490 deletions

View file

@ -470,6 +470,7 @@ dummy_func(void) {
}
op(_LOAD_CONST, (-- value)) {
PyCodeObject *co = get_current_code_object(ctx);
PyObject *val = PyTuple_GET_ITEM(co->co_consts, oparg);
REPLACE_OP(this_instr, _LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)val);
value = PyJitRef_Borrow(sym_new_const(ctx, val));
@ -606,7 +607,7 @@ dummy_func(void) {
op(_LOAD_ATTR_CLASS, (descr/4, owner -- attr)) {
(void)descr;
PyTypeObject *type = (PyTypeObject *)sym_get_const(ctx, owner);
PyObject *name = PyTuple_GET_ITEM(co->co_names, oparg >> 1);
PyObject *name = get_co_name(ctx, oparg >> 1);
attr = lookup_attr(ctx, this_instr, type, name,
_POP_TOP_LOAD_CONST_INLINE_BORROW,
_POP_TOP_LOAD_CONST_INLINE);
@ -615,7 +616,7 @@ dummy_func(void) {
op(_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, (descr/4, owner -- attr)) {
(void)descr;
PyTypeObject *type = sym_get_type(owner);
PyObject *name = PyTuple_GET_ITEM(co->co_names, oparg >> 1);
PyObject *name = get_co_name(ctx, oparg >> 1);
attr = lookup_attr(ctx, this_instr, type, name,
_POP_TOP_LOAD_CONST_INLINE_BORROW,
_POP_TOP_LOAD_CONST_INLINE);
@ -624,7 +625,7 @@ dummy_func(void) {
op(_LOAD_ATTR_NONDESCRIPTOR_NO_DICT, (descr/4, owner -- attr)) {
(void)descr;
PyTypeObject *type = sym_get_type(owner);
PyObject *name = PyTuple_GET_ITEM(co->co_names, oparg >> 1);
PyObject *name = get_co_name(ctx, oparg >> 1);
attr = lookup_attr(ctx, this_instr, type, name,
_POP_TOP_LOAD_CONST_INLINE_BORROW,
_POP_TOP_LOAD_CONST_INLINE);
@ -633,7 +634,7 @@ dummy_func(void) {
op(_LOAD_ATTR_METHOD_WITH_VALUES, (descr/4, owner -- attr, self)) {
(void)descr;
PyTypeObject *type = sym_get_type(owner);
PyObject *name = PyTuple_GET_ITEM(co->co_names, oparg >> 1);
PyObject *name = get_co_name(ctx, oparg >> 1);
attr = lookup_attr(ctx, this_instr, type, name,
_LOAD_CONST_UNDER_INLINE_BORROW,
_LOAD_CONST_UNDER_INLINE);
@ -643,7 +644,7 @@ dummy_func(void) {
op(_LOAD_ATTR_METHOD_NO_DICT, (descr/4, owner -- attr, self)) {
(void)descr;
PyTypeObject *type = sym_get_type(owner);
PyObject *name = PyTuple_GET_ITEM(co->co_names, oparg >> 1);
PyObject *name = get_co_name(ctx, oparg >> 1);
attr = lookup_attr(ctx, this_instr, type, name,
_LOAD_CONST_UNDER_INLINE_BORROW,
_LOAD_CONST_UNDER_INLINE);
@ -653,7 +654,7 @@ dummy_func(void) {
op(_LOAD_ATTR_METHOD_LAZY_DICT, (descr/4, owner -- attr, self)) {
(void)descr;
PyTypeObject *type = sym_get_type(owner);
PyObject *name = PyTuple_GET_ITEM(co->co_names, oparg >> 1);
PyObject *name = get_co_name(ctx, oparg >> 1);
attr = lookup_attr(ctx, this_instr, type, name,
_LOAD_CONST_UNDER_INLINE_BORROW,
_LOAD_CONST_UNDER_INLINE);
@ -711,15 +712,13 @@ dummy_func(void) {
op(_INIT_CALL_PY_EXACT_ARGS, (callable, self_or_null, args[oparg] -- new_frame)) {
int argcount = oparg;
PyCodeObject *co = NULL;
assert((this_instr + 2)->opcode == _PUSH_FRAME);
co = get_code_with_logging((this_instr + 2));
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)) {
@ -742,9 +741,8 @@ dummy_func(void) {
}
op(_PY_FRAME_GENERAL, (callable, self_or_null, args[oparg] -- new_frame)) {
PyCodeObject *co = NULL;
assert((this_instr + 2)->opcode == _PUSH_FRAME);
co = get_code_with_logging((this_instr + 2));
PyCodeObject *co = get_code_with_logging((this_instr + 2));
if (co == NULL) {
ctx->done = true;
break;
@ -775,6 +773,7 @@ dummy_func(void) {
JitOptRef temp = PyJitRef_StripReferenceInfo(retval);
DEAD(retval);
SAVE_STACK();
PyCodeObject *co = get_current_code_object(ctx);
ctx->frame->stack_pointer = stack_pointer;
frame_pop(ctx);
stack_pointer = ctx->frame->stack_pointer;
@ -787,17 +786,13 @@ dummy_func(void) {
assert(framesize <= curr_space);
curr_space -= framesize;
co = get_code(this_instr);
if (co == NULL) {
// might be impossible, but bailing is still safe
ctx->done = true;
}
RELOAD_STACK();
res = temp;
}
op(_RETURN_GENERATOR, ( -- res)) {
SYNC_SP();
PyCodeObject *co = get_current_code_object(ctx);
ctx->frame->stack_pointer = stack_pointer;
frame_pop(ctx);
stack_pointer = ctx->frame->stack_pointer;
@ -810,12 +805,6 @@ dummy_func(void) {
assert(framesize > 0);
assert(framesize <= curr_space);
curr_space -= framesize;
co = get_code(this_instr);
if (co == NULL) {
// might be impossible, but bailing is still safe
ctx->done = true;
}
}
op(_YIELD_VALUE, (unused -- value)) {
@ -863,13 +852,16 @@ dummy_func(void) {
ctx->frame = (_Py_UOpsAbstractFrame *)PyJitRef_Unwrap(new_frame);
ctx->curr_frame_depth++;
stack_pointer = ctx->frame->stack_pointer;
co = get_code(this_instr);
if (co == NULL) {
// should be about to _EXIT_TRACE anyway
uint64_t operand = this_instr->operand0;
if (operand == 0 || (operand & 1)) {
// It's either a code object or NULL
ctx->done = true;
break;
}
PyFunctionObject *func = (PyFunctionObject *)operand;
PyCodeObject *co = (PyCodeObject *)func->func_code;
assert(PyFunction_Check(func));
ctx->frame->func = func;
/* Stack space handling */
int framesize = co->co_framesize;
assert(framesize > 0);
@ -1250,6 +1242,96 @@ dummy_func(void) {
}
}
op(_GUARD_GLOBALS_VERSION, (version/1 --)) {
if (ctx->frame->func != NULL) {
PyObject *globals = ctx->frame->func->func_globals;
if (incorrect_keys(globals, version)) {
OPT_STAT_INC(remove_globals_incorrect_keys);
ctx->done = true;
}
else if (get_mutations(globals) >= _Py_MAX_ALLOWED_GLOBALS_MODIFICATIONS) {
/* Do nothing */
}
else {
if (!ctx->frame->globals_watched) {
PyDict_Watch(GLOBALS_WATCHER_ID, globals);
_Py_BloomFilter_Add(dependencies, globals);
ctx->frame->globals_watched = true;
}
if (ctx->frame->globals_checked_version == version) {
REPLACE_OP(this_instr, _NOP, 0, 0);
}
}
}
ctx->frame->globals_checked_version = version;
}
op(_LOAD_GLOBAL_BUILTINS, (version/1, index/1 -- res)) {
(void)version;
(void)index;
PyObject *cnst = NULL;
PyInterpreterState *interp = _PyInterpreterState_GET();
PyObject *builtins = interp->builtins;
if (incorrect_keys(builtins, version)) {
OPT_STAT_INC(remove_globals_incorrect_keys);
ctx->done = true;
}
else if (interp->rare_events.builtin_dict >= _Py_MAX_ALLOWED_BUILTINS_MODIFICATIONS) {
/* Do nothing */
}
else {
if (!ctx->builtins_watched) {
PyDict_Watch(BUILTINS_WATCHER_ID, builtins);
ctx->builtins_watched = true;
}
if (ctx->frame->globals_checked_version != 0 && ctx->frame->globals_watched) {
cnst = convert_global_to_const(this_instr, builtins, false);
}
}
if (cnst == NULL) {
res = sym_new_not_null(ctx);
}
else {
res = sym_new_const(ctx, cnst);
}
}
op(_LOAD_GLOBAL_MODULE, (version/1, unused/1, index/1 -- res)) {
(void)index;
PyObject *cnst = NULL;
if (ctx->frame->func != NULL) {
PyObject *globals = ctx->frame->func->func_globals;
if (incorrect_keys(globals, version)) {
OPT_STAT_INC(remove_globals_incorrect_keys);
ctx->done = true;
}
else if (get_mutations(globals) >= _Py_MAX_ALLOWED_GLOBALS_MODIFICATIONS) {
/* Do nothing */
}
else {
if (!ctx->frame->globals_watched) {
PyDict_Watch(GLOBALS_WATCHER_ID, globals);
_Py_BloomFilter_Add(dependencies, globals);
ctx->frame->globals_watched = true;
}
if (ctx->frame->globals_checked_version != version && this_instr[-1].opcode == _NOP) {
REPLACE_OP(this_instr-1, _GUARD_GLOBALS_VERSION, 0, version);
ctx->frame->globals_checked_version = version;
}
if (ctx->frame->globals_checked_version == version) {
cnst = convert_global_to_const(this_instr, globals, false);
}
}
}
if (cnst == NULL) {
res = sym_new_not_null(ctx);
}
else {
res = sym_new_const(ctx, cnst);
}
}
// END BYTECODES //
}