gh-93143: Avoid NULL check in LOAD_FAST based on analysis in the compiler (GH-93144)

This commit is contained in:
Dennis Sweeney 2022-05-31 16:32:30 -04:00 committed by GitHub
parent 8a5e3c2ec6
commit f425f3bb27
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 371 additions and 52 deletions

View file

@ -455,6 +455,26 @@ _PyFrame_GetState(PyFrameObject *frame)
Py_UNREACHABLE();
}
static void
add_load_fast_null_checks(PyCodeObject *co)
{
_Py_CODEUNIT *instructions = _PyCode_CODE(co);
for (Py_ssize_t i = 0; i < Py_SIZE(co); i++) {
switch (_Py_OPCODE(instructions[i])) {
case LOAD_FAST:
case LOAD_FAST__LOAD_FAST:
case LOAD_FAST__LOAD_CONST:
_Py_SET_OPCODE(instructions[i], LOAD_FAST_CHECK);
break;
case LOAD_CONST__LOAD_FAST:
_Py_SET_OPCODE(instructions[i], LOAD_CONST);
break;
case STORE_FAST__LOAD_FAST:
_Py_SET_OPCODE(instructions[i], STORE_FAST);
break;
}
}
}
/* Setter for f_lineno - you can set f_lineno from within a trace function in
* order to jump to a given line of code, subject to some restrictions. Most
@ -545,6 +565,8 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore
return -1;
}
add_load_fast_null_checks(f->f_frame->f_code);
/* PyCode_NewWithPosOnlyArgs limits co_code to be under INT_MAX so this
* should never overflow. */
int len = (int)Py_SIZE(f->f_frame->f_code);
@ -1047,6 +1069,7 @@ _PyFrame_LocalsToFast(_PyInterpreterFrame *frame, int clear)
}
fast = _PyFrame_GetLocalsArray(frame);
co = frame->f_code;
bool added_null_checks = false;
PyErr_Fetch(&error_type, &error_value, &error_traceback);
for (int i = 0; i < co->co_nlocalsplus; i++) {
@ -1066,6 +1089,10 @@ _PyFrame_LocalsToFast(_PyInterpreterFrame *frame, int clear)
}
}
PyObject *oldvalue = fast[i];
if (!added_null_checks && oldvalue != NULL && value == NULL) {
add_load_fast_null_checks(co);
added_null_checks = true;
}
PyObject *cell = NULL;
if (kind == CO_FAST_FREE) {
// The cell was set when the frame was created from