summaryrefslogtreecommitdiffstats
path: root/Objects/frameobject.c
diff options
context:
space:
mode:
authorDennis Sweeney <36520290+sweeneyde@users.noreply.github.com>2022-05-31 20:32:30 (GMT)
committerGitHub <noreply@github.com>2022-05-31 20:32:30 (GMT)
commitf425f3bb27e826d25aac05139360cc6aa279126e (patch)
tree221a478440fd429943409605bbf8dcaf9bb9c6ee /Objects/frameobject.c
parent8a5e3c2ec6254b2ce06d17545f58a6719e0c8fdb (diff)
downloadcpython-f425f3bb27e826d25aac05139360cc6aa279126e.zip
cpython-f425f3bb27e826d25aac05139360cc6aa279126e.tar.gz
cpython-f425f3bb27e826d25aac05139360cc6aa279126e.tar.bz2
gh-93143: Avoid NULL check in LOAD_FAST based on analysis in the compiler (GH-93144)
Diffstat (limited to 'Objects/frameobject.c')
-rw-r--r--Objects/frameobject.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index 60f0f2f..a448ba3 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -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