diff options
Diffstat (limited to 'Objects/frameobject.c')
-rw-r--r-- | Objects/frameobject.c | 27 |
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 |