summaryrefslogtreecommitdiffstats
path: root/Objects/frameobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/frameobject.c')
-rw-r--r--Objects/frameobject.c39
1 files changed, 30 insertions, 9 deletions
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index 73b6c3d..7ccd300 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -105,8 +105,9 @@ frame_getback(PyFrameObject *f, void *closure)
return res;
}
-/* Given the index of the effective opcode,
- scan back to construct the oparg with EXTENDED_ARG */
+// Given the index of the effective opcode, scan back to construct the oparg
+// with EXTENDED_ARG. This only works correctly with *unquickened* code,
+// obtained via a call to _PyCode_GetCode!
static unsigned int
get_arg(const _Py_CODEUNIT *codestr, Py_ssize_t i)
{
@@ -170,13 +171,17 @@ top_of_stack(int64_t stack)
static int64_t *
mark_stacks(PyCodeObject *code_obj, int len)
{
- const _Py_CODEUNIT *code =
- (const _Py_CODEUNIT *)PyBytes_AS_STRING(code_obj->co_code);
+ PyObject *co_code = _PyCode_GetCode(code_obj);
+ if (co_code == NULL) {
+ return NULL;
+ }
+ _Py_CODEUNIT *code = (_Py_CODEUNIT *)PyBytes_AS_STRING(co_code);
int64_t *stacks = PyMem_New(int64_t, len+1);
int i, j, opcode;
if (stacks == NULL) {
PyErr_NoMemory();
+ Py_DECREF(co_code);
return NULL;
}
for (int i = 1; i <= len; i++) {
@@ -304,6 +309,7 @@ mark_stacks(PyCodeObject *code_obj, int len)
}
}
}
+ Py_DECREF(co_code);
return stacks;
}
@@ -493,7 +499,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore
/* PyCode_NewWithPosOnlyArgs limits co_code to be under INT_MAX so this
* should never overflow. */
- int len = (int)(PyBytes_GET_SIZE(f->f_frame->f_code->co_code) / sizeof(_Py_CODEUNIT));
+ int len = (int)Py_SIZE(f->f_frame->f_code);
int *lines = marklines(f->f_frame->f_code, len);
if (lines == NULL) {
return -1;
@@ -838,12 +844,23 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code,
static int
_PyFrame_OpAlreadyRan(_PyInterpreterFrame *frame, int opcode, int oparg)
{
- const _Py_CODEUNIT *code =
- (const _Py_CODEUNIT *)PyBytes_AS_STRING(frame->f_code->co_code);
+ // This only works when opcode is a non-quickened form:
+ assert(_PyOpcode_Deopt[opcode] == opcode);
+ int check_oparg = 0;
for (int i = 0; i < frame->f_lasti; i++) {
- if (_Py_OPCODE(code[i]) == opcode && _Py_OPARG(code[i]) == oparg) {
+ _Py_CODEUNIT instruction = _PyCode_CODE(frame->f_code)[i];
+ int check_opcode = _PyOpcode_Deopt[_Py_OPCODE(instruction)];
+ check_oparg |= _Py_OPARG(instruction);
+ if (check_opcode == opcode && check_oparg == oparg) {
return 1;
}
+ if (check_opcode == EXTENDED_ARG) {
+ check_oparg <<= 8;
+ }
+ else {
+ check_oparg = 0;
+ }
+ i += _PyOpcode_Caches[check_opcode];
}
return 0;
}
@@ -862,7 +879,10 @@ _PyFrame_FastToLocalsWithError(_PyInterpreterFrame *frame) {
}
co = frame->f_code;
fast = _PyFrame_GetLocalsArray(frame);
- if (frame->f_lasti < 0 && _Py_OPCODE(co->co_firstinstr[0]) == COPY_FREE_VARS) {
+ // COPY_FREE_VARS has no quickened forms, so no need to use _PyOpcode_Deopt
+ // here:
+ if (frame->f_lasti < 0 && _Py_OPCODE(_PyCode_CODE(co)[0]) == COPY_FREE_VARS)
+ {
/* Free vars have not been initialized -- Do that */
PyCodeObject *co = frame->f_code;
PyObject *closure = frame->f_func->func_closure;
@@ -872,6 +892,7 @@ _PyFrame_FastToLocalsWithError(_PyInterpreterFrame *frame) {
Py_INCREF(o);
frame->localsplus[offset + i] = o;
}
+ // COPY_FREE_VARS doesn't have inline CACHEs, either:
frame->f_lasti = 0;
}
for (int i = 0; i < co->co_nlocalsplus; i++) {