diff options
author | shadchin <shadchin@yandex-team.ru> | 2022-02-10 16:44:30 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:30 +0300 |
commit | 2598ef1d0aee359b4b6d5fdd1758916d5907d04f (patch) | |
tree | 012bb94d777798f1f56ac1cec429509766d05181 /contrib/tools/python3/src/Objects/frameobject.c | |
parent | 6751af0b0c1b952fede40b19b71da8025b5d8bcf (diff) | |
download | ydb-2598ef1d0aee359b4b6d5fdd1758916d5907d04f.tar.gz |
Restoring authorship annotation for <shadchin@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/tools/python3/src/Objects/frameobject.c')
-rw-r--r-- | contrib/tools/python3/src/Objects/frameobject.c | 1068 |
1 files changed, 534 insertions, 534 deletions
diff --git a/contrib/tools/python3/src/Objects/frameobject.c b/contrib/tools/python3/src/Objects/frameobject.c index 4ae17bcfc2..acd0e52f0d 100644 --- a/contrib/tools/python3/src/Objects/frameobject.c +++ b/contrib/tools/python3/src/Objects/frameobject.c @@ -1,19 +1,19 @@ /* Frame object implementation */ #include "Python.h" -#include "pycore_object.h" -#include "pycore_gc.h" // _PyObject_GC_IS_TRACKED() +#include "pycore_object.h" +#include "pycore_gc.h" // _PyObject_GC_IS_TRACKED() #include "code.h" #include "frameobject.h" #include "opcode.h" -#include "structmember.h" // PyMemberDef +#include "structmember.h" // PyMemberDef #define OFF(x) offsetof(PyFrameObject, x) static PyMemberDef frame_memberlist[] = { {"f_back", T_OBJECT, OFF(f_back), READONLY}, - {"f_code", T_OBJECT, OFF(f_code), READONLY|READ_RESTRICTED}, + {"f_code", T_OBJECT, OFF(f_code), READONLY|READ_RESTRICTED}, {"f_builtins", T_OBJECT, OFF(f_builtins), READONLY}, {"f_globals", T_OBJECT, OFF(f_globals), READONLY}, {"f_lasti", T_INT, OFF(f_lasti), READONLY}, @@ -34,13 +34,13 @@ frame_getlocals(PyFrameObject *f, void *closure) int PyFrame_GetLineNumber(PyFrameObject *f) { - assert(f != NULL); - if (f->f_trace) { + assert(f != NULL); + if (f->f_trace) { return f->f_lineno; - } - else { + } + else { return PyCode_Addr2Line(f->f_code, f->f_lasti); - } + } } static PyObject * @@ -49,266 +49,266 @@ frame_getlineno(PyFrameObject *f, void *closure) return PyLong_FromLong(PyFrame_GetLineNumber(f)); } - -/* Given the index of the effective opcode, - scan back to construct the oparg with EXTENDED_ARG */ -static unsigned int -get_arg(const _Py_CODEUNIT *codestr, Py_ssize_t i) -{ - _Py_CODEUNIT word; - unsigned int oparg = _Py_OPARG(codestr[i]); - if (i >= 1 && _Py_OPCODE(word = codestr[i-1]) == EXTENDED_ARG) { - oparg |= _Py_OPARG(word) << 8; - if (i >= 2 && _Py_OPCODE(word = codestr[i-2]) == EXTENDED_ARG) { - oparg |= _Py_OPARG(word) << 16; - if (i >= 3 && _Py_OPCODE(word = codestr[i-3]) == EXTENDED_ARG) { - oparg |= _Py_OPARG(word) << 24; - } - } - } - return oparg; -} - -typedef enum kind { - With = 1, - Loop = 2, - Try = 3, - Except = 4, -} Kind; - -#define BITS_PER_BLOCK 3 - -static inline int64_t -push_block(int64_t stack, Kind kind) -{ - assert(stack < ((int64_t)1)<<(BITS_PER_BLOCK*CO_MAXBLOCKS)); - return (stack << BITS_PER_BLOCK) | kind; -} - -static inline int64_t -pop_block(int64_t stack) -{ - assert(stack > 0); - return stack >> BITS_PER_BLOCK; -} - -static inline Kind -top_block(int64_t stack) -{ - return stack & ((1<<BITS_PER_BLOCK)-1); -} - -static int64_t * -markblocks(PyCodeObject *code_obj, int len) -{ - const _Py_CODEUNIT *code = - (const _Py_CODEUNIT *)PyBytes_AS_STRING(code_obj->co_code); - int64_t *blocks = PyMem_New(int64_t, len+1); - int i, j, opcode; - - if (blocks == NULL) { - PyErr_NoMemory(); - return NULL; - } - memset(blocks, -1, (len+1)*sizeof(int64_t)); - blocks[0] = 0; - int todo = 1; - while (todo) { - todo = 0; - for (i = 0; i < len; i++) { - int64_t block_stack = blocks[i]; - int64_t except_stack; - if (block_stack == -1) { - continue; - } - opcode = _Py_OPCODE(code[i]); - switch (opcode) { - case JUMP_IF_FALSE_OR_POP: - case JUMP_IF_TRUE_OR_POP: - case POP_JUMP_IF_FALSE: - case POP_JUMP_IF_TRUE: - case JUMP_IF_NOT_EXC_MATCH: - j = get_arg(code, i) / sizeof(_Py_CODEUNIT); - assert(j < len); - if (blocks[j] == -1 && j < i) { - todo = 1; - } - assert(blocks[j] == -1 || blocks[j] == block_stack); - blocks[j] = block_stack; - blocks[i+1] = block_stack; - break; - case JUMP_ABSOLUTE: - j = get_arg(code, i) / sizeof(_Py_CODEUNIT); - assert(j < len); - if (blocks[j] == -1 && j < i) { - todo = 1; - } - assert(blocks[j] == -1 || blocks[j] == block_stack); - blocks[j] = block_stack; - break; - case SETUP_FINALLY: - j = get_arg(code, i) / sizeof(_Py_CODEUNIT) + i + 1; - assert(j < len); - except_stack = push_block(block_stack, Except); - assert(blocks[j] == -1 || blocks[j] == except_stack); - blocks[j] = except_stack; - block_stack = push_block(block_stack, Try); - blocks[i+1] = block_stack; - break; - case SETUP_WITH: - case SETUP_ASYNC_WITH: - j = get_arg(code, i) / sizeof(_Py_CODEUNIT) + i + 1; - assert(j < len); - except_stack = push_block(block_stack, Except); - assert(blocks[j] == -1 || blocks[j] == except_stack); - blocks[j] = except_stack; - block_stack = push_block(block_stack, With); - blocks[i+1] = block_stack; - break; - case JUMP_FORWARD: - j = get_arg(code, i) / sizeof(_Py_CODEUNIT) + i + 1; - assert(j < len); - assert(blocks[j] == -1 || blocks[j] == block_stack); - blocks[j] = block_stack; - break; - case GET_ITER: - case GET_AITER: - block_stack = push_block(block_stack, Loop); - blocks[i+1] = block_stack; - break; - case FOR_ITER: - blocks[i+1] = block_stack; - block_stack = pop_block(block_stack); - j = get_arg(code, i) / sizeof(_Py_CODEUNIT) + i + 1; - assert(j < len); - assert(blocks[j] == -1 || blocks[j] == block_stack); - blocks[j] = block_stack; - break; - case POP_BLOCK: - case POP_EXCEPT: - block_stack = pop_block(block_stack); - blocks[i+1] = block_stack; - break; - case END_ASYNC_FOR: - block_stack = pop_block(pop_block(block_stack)); - blocks[i+1] = block_stack; - break; - case RETURN_VALUE: - case RAISE_VARARGS: - case RERAISE: - /* End of block */ - break; - default: - blocks[i+1] = block_stack; - - } - } - } - return blocks; -} - -static int -compatible_block_stack(int64_t from_stack, int64_t to_stack) -{ - if (to_stack < 0) { - return 0; - } - while(from_stack > to_stack) { - from_stack = pop_block(from_stack); - } - return from_stack == to_stack; -} - -static const char * -explain_incompatible_block_stack(int64_t to_stack) -{ - Kind target_kind = top_block(to_stack); - switch(target_kind) { - case Except: - return "can't jump into an 'except' block as there's no exception"; - case Try: - return "can't jump into the body of a try statement"; - case With: - return "can't jump into the body of a with statement"; - case Loop: - return "can't jump into the body of a for loop"; - default: - Py_UNREACHABLE(); - } -} - -static int * -marklines(PyCodeObject *code, int len) -{ - int *linestarts = PyMem_New(int, len); - if (linestarts == NULL) { - return NULL; - } - Py_ssize_t size = PyBytes_GET_SIZE(code->co_lnotab) / 2; - unsigned char *p = (unsigned char*)PyBytes_AS_STRING(code->co_lnotab); - int line = code->co_firstlineno; - int addr = 0; - int index = 0; - while (--size >= 0) { - addr += *p++; - if (index*2 < addr) { - linestarts[index++] = line; - } - while (index*2 < addr) { - linestarts[index++] = -1; - if (index >= len) { - break; - } - } - line += (signed char)*p; - p++; - } - if (index < len) { - linestarts[index++] = line; - } - while (index < len) { - linestarts[index++] = -1; - } - assert(index == len); - return linestarts; -} - -static int -first_line_not_before(int *lines, int len, int line) -{ - int result = INT_MAX; - for (int i = 0; i < len; i++) { - if (lines[i] < result && lines[i] >= line) { - result = lines[i]; - } - } - if (result == INT_MAX) { - return -1; - } - return result; -} - -static void -frame_stack_pop(PyFrameObject *f) -{ - PyObject *v = (*--f->f_stacktop); - Py_DECREF(v); -} - -static void -frame_block_unwind(PyFrameObject *f) -{ - assert(f->f_iblock > 0); - f->f_iblock--; - PyTryBlock *b = &f->f_blockstack[f->f_iblock]; - intptr_t delta = (f->f_stacktop - f->f_valuestack) - b->b_level; - while (delta > 0) { - frame_stack_pop(f); - delta--; - } -} - - + +/* Given the index of the effective opcode, + scan back to construct the oparg with EXTENDED_ARG */ +static unsigned int +get_arg(const _Py_CODEUNIT *codestr, Py_ssize_t i) +{ + _Py_CODEUNIT word; + unsigned int oparg = _Py_OPARG(codestr[i]); + if (i >= 1 && _Py_OPCODE(word = codestr[i-1]) == EXTENDED_ARG) { + oparg |= _Py_OPARG(word) << 8; + if (i >= 2 && _Py_OPCODE(word = codestr[i-2]) == EXTENDED_ARG) { + oparg |= _Py_OPARG(word) << 16; + if (i >= 3 && _Py_OPCODE(word = codestr[i-3]) == EXTENDED_ARG) { + oparg |= _Py_OPARG(word) << 24; + } + } + } + return oparg; +} + +typedef enum kind { + With = 1, + Loop = 2, + Try = 3, + Except = 4, +} Kind; + +#define BITS_PER_BLOCK 3 + +static inline int64_t +push_block(int64_t stack, Kind kind) +{ + assert(stack < ((int64_t)1)<<(BITS_PER_BLOCK*CO_MAXBLOCKS)); + return (stack << BITS_PER_BLOCK) | kind; +} + +static inline int64_t +pop_block(int64_t stack) +{ + assert(stack > 0); + return stack >> BITS_PER_BLOCK; +} + +static inline Kind +top_block(int64_t stack) +{ + return stack & ((1<<BITS_PER_BLOCK)-1); +} + +static int64_t * +markblocks(PyCodeObject *code_obj, int len) +{ + const _Py_CODEUNIT *code = + (const _Py_CODEUNIT *)PyBytes_AS_STRING(code_obj->co_code); + int64_t *blocks = PyMem_New(int64_t, len+1); + int i, j, opcode; + + if (blocks == NULL) { + PyErr_NoMemory(); + return NULL; + } + memset(blocks, -1, (len+1)*sizeof(int64_t)); + blocks[0] = 0; + int todo = 1; + while (todo) { + todo = 0; + for (i = 0; i < len; i++) { + int64_t block_stack = blocks[i]; + int64_t except_stack; + if (block_stack == -1) { + continue; + } + opcode = _Py_OPCODE(code[i]); + switch (opcode) { + case JUMP_IF_FALSE_OR_POP: + case JUMP_IF_TRUE_OR_POP: + case POP_JUMP_IF_FALSE: + case POP_JUMP_IF_TRUE: + case JUMP_IF_NOT_EXC_MATCH: + j = get_arg(code, i) / sizeof(_Py_CODEUNIT); + assert(j < len); + if (blocks[j] == -1 && j < i) { + todo = 1; + } + assert(blocks[j] == -1 || blocks[j] == block_stack); + blocks[j] = block_stack; + blocks[i+1] = block_stack; + break; + case JUMP_ABSOLUTE: + j = get_arg(code, i) / sizeof(_Py_CODEUNIT); + assert(j < len); + if (blocks[j] == -1 && j < i) { + todo = 1; + } + assert(blocks[j] == -1 || blocks[j] == block_stack); + blocks[j] = block_stack; + break; + case SETUP_FINALLY: + j = get_arg(code, i) / sizeof(_Py_CODEUNIT) + i + 1; + assert(j < len); + except_stack = push_block(block_stack, Except); + assert(blocks[j] == -1 || blocks[j] == except_stack); + blocks[j] = except_stack; + block_stack = push_block(block_stack, Try); + blocks[i+1] = block_stack; + break; + case SETUP_WITH: + case SETUP_ASYNC_WITH: + j = get_arg(code, i) / sizeof(_Py_CODEUNIT) + i + 1; + assert(j < len); + except_stack = push_block(block_stack, Except); + assert(blocks[j] == -1 || blocks[j] == except_stack); + blocks[j] = except_stack; + block_stack = push_block(block_stack, With); + blocks[i+1] = block_stack; + break; + case JUMP_FORWARD: + j = get_arg(code, i) / sizeof(_Py_CODEUNIT) + i + 1; + assert(j < len); + assert(blocks[j] == -1 || blocks[j] == block_stack); + blocks[j] = block_stack; + break; + case GET_ITER: + case GET_AITER: + block_stack = push_block(block_stack, Loop); + blocks[i+1] = block_stack; + break; + case FOR_ITER: + blocks[i+1] = block_stack; + block_stack = pop_block(block_stack); + j = get_arg(code, i) / sizeof(_Py_CODEUNIT) + i + 1; + assert(j < len); + assert(blocks[j] == -1 || blocks[j] == block_stack); + blocks[j] = block_stack; + break; + case POP_BLOCK: + case POP_EXCEPT: + block_stack = pop_block(block_stack); + blocks[i+1] = block_stack; + break; + case END_ASYNC_FOR: + block_stack = pop_block(pop_block(block_stack)); + blocks[i+1] = block_stack; + break; + case RETURN_VALUE: + case RAISE_VARARGS: + case RERAISE: + /* End of block */ + break; + default: + blocks[i+1] = block_stack; + + } + } + } + return blocks; +} + +static int +compatible_block_stack(int64_t from_stack, int64_t to_stack) +{ + if (to_stack < 0) { + return 0; + } + while(from_stack > to_stack) { + from_stack = pop_block(from_stack); + } + return from_stack == to_stack; +} + +static const char * +explain_incompatible_block_stack(int64_t to_stack) +{ + Kind target_kind = top_block(to_stack); + switch(target_kind) { + case Except: + return "can't jump into an 'except' block as there's no exception"; + case Try: + return "can't jump into the body of a try statement"; + case With: + return "can't jump into the body of a with statement"; + case Loop: + return "can't jump into the body of a for loop"; + default: + Py_UNREACHABLE(); + } +} + +static int * +marklines(PyCodeObject *code, int len) +{ + int *linestarts = PyMem_New(int, len); + if (linestarts == NULL) { + return NULL; + } + Py_ssize_t size = PyBytes_GET_SIZE(code->co_lnotab) / 2; + unsigned char *p = (unsigned char*)PyBytes_AS_STRING(code->co_lnotab); + int line = code->co_firstlineno; + int addr = 0; + int index = 0; + while (--size >= 0) { + addr += *p++; + if (index*2 < addr) { + linestarts[index++] = line; + } + while (index*2 < addr) { + linestarts[index++] = -1; + if (index >= len) { + break; + } + } + line += (signed char)*p; + p++; + } + if (index < len) { + linestarts[index++] = line; + } + while (index < len) { + linestarts[index++] = -1; + } + assert(index == len); + return linestarts; +} + +static int +first_line_not_before(int *lines, int len, int line) +{ + int result = INT_MAX; + for (int i = 0; i < len; i++) { + if (lines[i] < result && lines[i] >= line) { + result = lines[i]; + } + } + if (result == INT_MAX) { + return -1; + } + return result; +} + +static void +frame_stack_pop(PyFrameObject *f) +{ + PyObject *v = (*--f->f_stacktop); + Py_DECREF(v); +} + +static void +frame_block_unwind(PyFrameObject *f) +{ + assert(f->f_iblock > 0); + f->f_iblock--; + PyTryBlock *b = &f->f_blockstack[f->f_iblock]; + intptr_t delta = (f->f_stacktop - f->f_valuestack) - b->b_level; + while (delta > 0) { + frame_stack_pop(f); + delta--; + } +} + + /* 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 * lines are OK to jump to because they don't make any assumptions about the @@ -319,11 +319,11 @@ frame_block_unwind(PyFrameObject *f) * o Lines with an 'except' statement on them can't be jumped to, because * they expect an exception to be on the top of the stack. * o Lines that live in a 'finally' block can't be jumped from or to, since - * we cannot be sure which state the interpreter was in or would be in - * during execution of the finally block. - * o 'try', 'with' and 'async with' blocks can't be jumped into because - * the blockstack needs to be set up before their code runs. - * o 'for' and 'async for' loops can't be jumped into because the + * we cannot be sure which state the interpreter was in or would be in + * during execution of the finally block. + * o 'try', 'with' and 'async with' blocks can't be jumped into because + * the blockstack needs to be set up before their code runs. + * o 'for' and 'async for' loops can't be jumped into because the * iterator needs to be on the stack. * o Jumps cannot be made from within a trace function invoked with a * 'return' or 'exception' event since the eval loop has been exited at @@ -372,18 +372,18 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore return -1; } - int new_lineno; - - /* Fail if the line falls outside the code block and - select first line with actual code. */ - int overflow; - long l_new_lineno = PyLong_AsLongAndOverflow(p_new_lineno, &overflow); + int new_lineno; + + /* Fail if the line falls outside the code block and + select first line with actual code. */ + int overflow; + long l_new_lineno = PyLong_AsLongAndOverflow(p_new_lineno, &overflow); if (overflow #if SIZEOF_LONG > SIZEOF_INT || l_new_lineno > INT_MAX || l_new_lineno < INT_MIN #endif - ) { + ) { PyErr_SetString(PyExc_ValueError, "lineno out of range"); return -1; @@ -392,92 +392,92 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore if (new_lineno < f->f_code->co_firstlineno) { PyErr_Format(PyExc_ValueError, - "line %d comes before the current code block", - new_lineno); + "line %d comes before the current code block", + new_lineno); return -1; } - /* PyCode_NewWithPosOnlyArgs limits co_code to be under INT_MAX so this - * should never overflow. */ - int len = (int)(PyBytes_GET_SIZE(f->f_code->co_code) / sizeof(_Py_CODEUNIT)); - int *lines = marklines(f->f_code, len); - if (lines == NULL) { + /* PyCode_NewWithPosOnlyArgs limits co_code to be under INT_MAX so this + * should never overflow. */ + int len = (int)(PyBytes_GET_SIZE(f->f_code->co_code) / sizeof(_Py_CODEUNIT)); + int *lines = marklines(f->f_code, len); + if (lines == NULL) { return -1; } - new_lineno = first_line_not_before(lines, len, new_lineno); - if (new_lineno < 0) { - PyErr_Format(PyExc_ValueError, - "line %d comes after the current code block", - (int)l_new_lineno); - PyMem_Free(lines); + new_lineno = first_line_not_before(lines, len, new_lineno); + if (new_lineno < 0) { + PyErr_Format(PyExc_ValueError, + "line %d comes after the current code block", + (int)l_new_lineno); + PyMem_Free(lines); return -1; } - int64_t *blocks = markblocks(f->f_code, len); - if (blocks == NULL) { - PyMem_Free(lines); + int64_t *blocks = markblocks(f->f_code, len); + if (blocks == NULL) { + PyMem_Free(lines); return -1; } - int64_t target_block_stack = -1; - int64_t best_block_stack = -1; - int best_addr = -1; - int64_t start_block_stack = blocks[f->f_lasti/sizeof(_Py_CODEUNIT)]; - const char *msg = "cannot find bytecode for specified line"; - for (int i = 0; i < len; i++) { - if (lines[i] == new_lineno) { - target_block_stack = blocks[i]; - if (compatible_block_stack(start_block_stack, target_block_stack)) { - msg = NULL; - if (target_block_stack > best_block_stack) { - best_block_stack = target_block_stack; - best_addr = i*sizeof(_Py_CODEUNIT); - } + int64_t target_block_stack = -1; + int64_t best_block_stack = -1; + int best_addr = -1; + int64_t start_block_stack = blocks[f->f_lasti/sizeof(_Py_CODEUNIT)]; + const char *msg = "cannot find bytecode for specified line"; + for (int i = 0; i < len; i++) { + if (lines[i] == new_lineno) { + target_block_stack = blocks[i]; + if (compatible_block_stack(start_block_stack, target_block_stack)) { + msg = NULL; + if (target_block_stack > best_block_stack) { + best_block_stack = target_block_stack; + best_addr = i*sizeof(_Py_CODEUNIT); + } } - else if (msg) { - if (target_block_stack >= 0) { - msg = explain_incompatible_block_stack(target_block_stack); - } - else { - msg = "code may be unreachable."; + else if (msg) { + if (target_block_stack >= 0) { + msg = explain_incompatible_block_stack(target_block_stack); } + else { + msg = "code may be unreachable."; + } } } - } - PyMem_Free(blocks); - PyMem_Free(lines); - if (msg != NULL) { - PyErr_SetString(PyExc_ValueError, msg); - return -1; - } - - /* Unwind block stack. */ - while (start_block_stack > best_block_stack) { - Kind kind = top_block(start_block_stack); - switch(kind) { - case Loop: - frame_stack_pop(f); - break; - case Try: - frame_block_unwind(f); - break; - case With: - frame_block_unwind(f); - // Pop the exit function - frame_stack_pop(f); - break; - case Except: - PyErr_SetString(PyExc_ValueError, - "can't jump out of an 'except' block"); - return -1; + } + PyMem_Free(blocks); + PyMem_Free(lines); + if (msg != NULL) { + PyErr_SetString(PyExc_ValueError, msg); + return -1; + } + + /* Unwind block stack. */ + while (start_block_stack > best_block_stack) { + Kind kind = top_block(start_block_stack); + switch(kind) { + case Loop: + frame_stack_pop(f); + break; + case Try: + frame_block_unwind(f); + break; + case With: + frame_block_unwind(f); + // Pop the exit function + frame_stack_pop(f); + break; + case Except: + PyErr_SetString(PyExc_ValueError, + "can't jump out of an 'except' block"); + return -1; } - start_block_stack = pop_block(start_block_stack); + start_block_stack = pop_block(start_block_stack); } /* Finally set the new f_lineno and f_lasti and return OK. */ f->f_lineno = new_lineno; - f->f_lasti = best_addr; + f->f_lasti = best_addr; return 0; } @@ -558,13 +558,13 @@ static PyGetSetDef frame_getsetlist[] = { free_list. Else programs creating lots of cyclic trash involving frames could provoke free_list into growing without bound. */ -/* max value for numfree */ -#define PyFrame_MAXFREELIST 200 +/* max value for numfree */ +#define PyFrame_MAXFREELIST 200 -#if PyFrame_MAXFREELIST > 0 +#if PyFrame_MAXFREELIST > 0 static PyFrameObject *free_list = NULL; static int numfree = 0; /* number of frames currently in free_list */ -#endif +#endif static void _Py_HOT_FUNCTION frame_dealloc(PyFrameObject *f) @@ -575,7 +575,7 @@ frame_dealloc(PyFrameObject *f) if (_PyObject_GC_IS_TRACKED(f)) _PyObject_GC_UNTRACK(f); - Py_TRASHCAN_BEGIN(f, frame_dealloc); + Py_TRASHCAN_BEGIN(f, frame_dealloc); /* Kill all local variables */ valuestack = f->f_valuestack; for (p = f->f_localsplus; p < valuestack; p++) @@ -594,33 +594,33 @@ frame_dealloc(PyFrameObject *f) Py_CLEAR(f->f_trace); co = f->f_code; - if (co->co_zombieframe == NULL) { + if (co->co_zombieframe == NULL) { co->co_zombieframe = f; - } -#if PyFrame_MAXFREELIST > 0 + } +#if PyFrame_MAXFREELIST > 0 else if (numfree < PyFrame_MAXFREELIST) { ++numfree; f->f_back = free_list; free_list = f; } -#endif - else { +#endif + else { PyObject_GC_Del(f); - } + } Py_DECREF(co); - Py_TRASHCAN_END; -} - -static inline Py_ssize_t -frame_nslots(PyFrameObject *frame) -{ - PyCodeObject *code = frame->f_code; - return (code->co_nlocals - + PyTuple_GET_SIZE(code->co_cellvars) - + PyTuple_GET_SIZE(code->co_freevars)); + Py_TRASHCAN_END; } +static inline Py_ssize_t +frame_nslots(PyFrameObject *frame) +{ + PyCodeObject *code = frame->f_code; + return (code->co_nlocals + + PyTuple_GET_SIZE(code->co_cellvars) + + PyTuple_GET_SIZE(code->co_freevars)); +} + static int frame_traverse(PyFrameObject *f, visitproc visit, void *arg) { @@ -632,16 +632,16 @@ frame_traverse(PyFrameObject *f, visitproc visit, void *arg) Py_VISIT(f->f_trace); /* locals */ - PyObject **fastlocals = f->f_localsplus; - for (Py_ssize_t i = frame_nslots(f); --i >= 0; ++fastlocals) { + PyObject **fastlocals = f->f_localsplus; + for (Py_ssize_t i = frame_nslots(f); --i >= 0; ++fastlocals) { Py_VISIT(*fastlocals); - } + } /* stack */ if (f->f_stacktop != NULL) { - for (PyObject **p = f->f_valuestack; p < f->f_stacktop; p++) { + for (PyObject **p = f->f_valuestack; p < f->f_stacktop; p++) { Py_VISIT(*p); - } + } } return 0; } @@ -654,29 +654,29 @@ frame_tp_clear(PyFrameObject *f) * frame may also point to this frame, believe itself to still be * active, and try cleaning up this frame again. */ - PyObject **oldtop = f->f_stacktop; + PyObject **oldtop = f->f_stacktop; f->f_stacktop = NULL; f->f_executing = 0; Py_CLEAR(f->f_trace); /* locals */ - PyObject **fastlocals = f->f_localsplus; - for (Py_ssize_t i = frame_nslots(f); --i >= 0; ++fastlocals) { + PyObject **fastlocals = f->f_localsplus; + for (Py_ssize_t i = frame_nslots(f); --i >= 0; ++fastlocals) { Py_CLEAR(*fastlocals); - } + } /* stack */ if (oldtop != NULL) { - for (PyObject **p = f->f_valuestack; p < oldtop; p++) { + for (PyObject **p = f->f_valuestack; p < oldtop; p++) { Py_CLEAR(*p); - } + } } return 0; } static PyObject * -frame_clear(PyFrameObject *f, PyObject *Py_UNUSED(ignored)) +frame_clear(PyFrameObject *f, PyObject *Py_UNUSED(ignored)) { if (f->f_executing) { PyErr_SetString(PyExc_RuntimeError, @@ -695,14 +695,14 @@ PyDoc_STRVAR(clear__doc__, "F.clear(): clear most references held by the frame"); static PyObject * -frame_sizeof(PyFrameObject *f, PyObject *Py_UNUSED(ignored)) +frame_sizeof(PyFrameObject *f, PyObject *Py_UNUSED(ignored)) { Py_ssize_t res, extras, ncells, nfrees; - PyCodeObject *code = f->f_code; - ncells = PyTuple_GET_SIZE(code->co_cellvars); - nfrees = PyTuple_GET_SIZE(code->co_freevars); - extras = code->co_stacksize + code->co_nlocals + ncells + nfrees; + PyCodeObject *code = f->f_code; + ncells = PyTuple_GET_SIZE(code->co_cellvars); + nfrees = PyTuple_GET_SIZE(code->co_freevars); + extras = code->co_stacksize + code->co_nlocals + ncells + nfrees; /* subtract one as it is already included in PyFrameObject */ res = sizeof(PyFrameObject) + (extras-1) * sizeof(PyObject *); @@ -716,10 +716,10 @@ static PyObject * frame_repr(PyFrameObject *f) { int lineno = PyFrame_GetLineNumber(f); - PyCodeObject *code = f->f_code; + PyCodeObject *code = f->f_code; return PyUnicode_FromFormat( "<frame at %p, file %R, line %d, code %S>", - f, code->co_filename, lineno, code->co_name); + f, code->co_filename, lineno, code->co_name); } static PyMethodDef frame_methods[] = { @@ -736,10 +736,10 @@ PyTypeObject PyFrame_Type = { sizeof(PyFrameObject), sizeof(PyObject *), (destructor)frame_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ + 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ - 0, /* tp_as_async */ + 0, /* tp_as_async */ (reprfunc)frame_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ @@ -767,127 +767,127 @@ PyTypeObject PyFrame_Type = { _Py_IDENTIFIER(__builtins__); -static inline PyFrameObject* -frame_alloc(PyCodeObject *code) +static inline PyFrameObject* +frame_alloc(PyCodeObject *code) { PyFrameObject *f; - f = code->co_zombieframe; - if (f != NULL) { - code->co_zombieframe = NULL; - _Py_NewReference((PyObject *)f); - assert(f->f_code == code); - return f; - } - - Py_ssize_t ncells = PyTuple_GET_SIZE(code->co_cellvars); - Py_ssize_t nfrees = PyTuple_GET_SIZE(code->co_freevars); - Py_ssize_t extras = code->co_stacksize + code->co_nlocals + ncells + nfrees; -#if PyFrame_MAXFREELIST > 0 - if (free_list == NULL) + f = code->co_zombieframe; + if (f != NULL) { + code->co_zombieframe = NULL; + _Py_NewReference((PyObject *)f); + assert(f->f_code == code); + return f; + } + + Py_ssize_t ncells = PyTuple_GET_SIZE(code->co_cellvars); + Py_ssize_t nfrees = PyTuple_GET_SIZE(code->co_freevars); + Py_ssize_t extras = code->co_stacksize + code->co_nlocals + ncells + nfrees; +#if PyFrame_MAXFREELIST > 0 + if (free_list == NULL) #endif - { - f = PyObject_GC_NewVar(PyFrameObject, &PyFrame_Type, extras); - if (f == NULL) { - return NULL; + { + f = PyObject_GC_NewVar(PyFrameObject, &PyFrame_Type, extras); + if (f == NULL) { + return NULL; } - } -#if PyFrame_MAXFREELIST > 0 - else { - assert(numfree > 0); - --numfree; - f = free_list; - free_list = free_list->f_back; - if (Py_SIZE(f) < extras) { - PyFrameObject *new_f = PyObject_GC_Resize(PyFrameObject, f, extras); - if (new_f == NULL) { - PyObject_GC_Del(f); - return NULL; - } - f = new_f; + } +#if PyFrame_MAXFREELIST > 0 + else { + assert(numfree > 0); + --numfree; + f = free_list; + free_list = free_list->f_back; + if (Py_SIZE(f) < extras) { + PyFrameObject *new_f = PyObject_GC_Resize(PyFrameObject, f, extras); + if (new_f == NULL) { + PyObject_GC_Del(f); + return NULL; + } + f = new_f; } - _Py_NewReference((PyObject *)f); - } -#endif - - f->f_code = code; - extras = code->co_nlocals + ncells + nfrees; - f->f_valuestack = f->f_localsplus + extras; - for (Py_ssize_t i=0; i<extras; i++) { - f->f_localsplus[i] = NULL; - } - f->f_locals = NULL; - f->f_trace = NULL; - return f; -} - - -static inline PyObject * -frame_get_builtins(PyFrameObject *back, PyObject *globals) -{ - PyObject *builtins; - - if (back != NULL && back->f_globals == globals) { + _Py_NewReference((PyObject *)f); + } +#endif + + f->f_code = code; + extras = code->co_nlocals + ncells + nfrees; + f->f_valuestack = f->f_localsplus + extras; + for (Py_ssize_t i=0; i<extras; i++) { + f->f_localsplus[i] = NULL; + } + f->f_locals = NULL; + f->f_trace = NULL; + return f; +} + + +static inline PyObject * +frame_get_builtins(PyFrameObject *back, PyObject *globals) +{ + PyObject *builtins; + + if (back != NULL && back->f_globals == globals) { /* If we share the globals, we share the builtins. Save a lookup and a call. */ builtins = back->f_builtins; assert(builtins != NULL); Py_INCREF(builtins); - return builtins; - } - - builtins = _PyDict_GetItemIdWithError(globals, &PyId___builtins__); - if (builtins != NULL && PyModule_Check(builtins)) { - builtins = PyModule_GetDict(builtins); - assert(builtins != NULL); - } - if (builtins != NULL) { - Py_INCREF(builtins); - return builtins; - } - - if (PyErr_Occurred()) { - return NULL; - } - - /* No builtins! Make up a minimal one. - Give them 'None', at least. */ - builtins = PyDict_New(); - if (builtins == NULL) { - return NULL; - } - if (PyDict_SetItemString(builtins, "None", Py_None) < 0) { - Py_DECREF(builtins); - return NULL; - } - return builtins; -} - - -PyFrameObject* _Py_HOT_FUNCTION -_PyFrame_New_NoTrack(PyThreadState *tstate, PyCodeObject *code, - PyObject *globals, PyObject *locals) -{ -#ifdef Py_DEBUG - if (code == NULL || globals == NULL || !PyDict_Check(globals) || - (locals != NULL && !PyMapping_Check(locals))) { - PyErr_BadInternalCall(); - return NULL; - } -#endif - - PyFrameObject *back = tstate->frame; - PyObject *builtins = frame_get_builtins(back, globals); - if (builtins == NULL) { - return NULL; - } - - PyFrameObject *f = frame_alloc(code); - if (f == NULL) { - Py_DECREF(builtins); - return NULL; - } - + return builtins; + } + + builtins = _PyDict_GetItemIdWithError(globals, &PyId___builtins__); + if (builtins != NULL && PyModule_Check(builtins)) { + builtins = PyModule_GetDict(builtins); + assert(builtins != NULL); + } + if (builtins != NULL) { + Py_INCREF(builtins); + return builtins; + } + + if (PyErr_Occurred()) { + return NULL; + } + + /* No builtins! Make up a minimal one. + Give them 'None', at least. */ + builtins = PyDict_New(); + if (builtins == NULL) { + return NULL; + } + if (PyDict_SetItemString(builtins, "None", Py_None) < 0) { + Py_DECREF(builtins); + return NULL; + } + return builtins; +} + + +PyFrameObject* _Py_HOT_FUNCTION +_PyFrame_New_NoTrack(PyThreadState *tstate, PyCodeObject *code, + PyObject *globals, PyObject *locals) +{ +#ifdef Py_DEBUG + if (code == NULL || globals == NULL || !PyDict_Check(globals) || + (locals != NULL && !PyMapping_Check(locals))) { + PyErr_BadInternalCall(); + return NULL; + } +#endif + + PyFrameObject *back = tstate->frame; + PyObject *builtins = frame_get_builtins(back, globals); + if (builtins == NULL) { + return NULL; + } + + PyFrameObject *f = frame_alloc(code); + if (f == NULL) { + Py_DECREF(builtins); + return NULL; + } + f->f_stacktop = f->f_valuestack; f->f_builtins = builtins; Py_XINCREF(back); @@ -922,8 +922,8 @@ _PyFrame_New_NoTrack(PyThreadState *tstate, PyCodeObject *code, f->f_trace_opcodes = 0; f->f_trace_lines = 1; - assert(f->f_code != NULL); - + assert(f->f_code != NULL); + return f; } @@ -944,9 +944,9 @@ void PyFrame_BlockSetup(PyFrameObject *f, int type, int handler, int level) { PyTryBlock *b; - if (f->f_iblock >= CO_MAXBLOCKS) { - Py_FatalError("block stack overflow"); - } + if (f->f_iblock >= CO_MAXBLOCKS) { + Py_FatalError("block stack overflow"); + } b = &f->f_blockstack[f->f_iblock++]; b->b_type = type; b->b_level = level; @@ -957,9 +957,9 @@ PyTryBlock * PyFrame_BlockPop(PyFrameObject *f) { PyTryBlock *b; - if (f->f_iblock <= 0) { - Py_FatalError("block stack underflow"); - } + if (f->f_iblock <= 0) { + Py_FatalError("block stack underflow"); + } b = &f->f_blockstack[--f->f_iblock]; return b; } @@ -1176,10 +1176,10 @@ PyFrame_LocalsToFast(PyFrameObject *f, int clear) } /* Clear out the free list */ -void -_PyFrame_ClearFreeList(void) +void +_PyFrame_ClearFreeList(void) { -#if PyFrame_MAXFREELIST > 0 +#if PyFrame_MAXFREELIST > 0 while (free_list != NULL) { PyFrameObject *f = free_list; free_list = free_list->f_back; @@ -1187,43 +1187,43 @@ _PyFrame_ClearFreeList(void) --numfree; } assert(numfree == 0); -#endif +#endif } void -_PyFrame_Fini(void) +_PyFrame_Fini(void) { - _PyFrame_ClearFreeList(); + _PyFrame_ClearFreeList(); } /* Print summary info about the state of the optimized allocator */ void _PyFrame_DebugMallocStats(FILE *out) { -#if PyFrame_MAXFREELIST > 0 +#if PyFrame_MAXFREELIST > 0 _PyDebugAllocatorStats(out, "free PyFrameObject", numfree, sizeof(PyFrameObject)); -#endif +#endif } - -PyCodeObject * -PyFrame_GetCode(PyFrameObject *frame) -{ - assert(frame != NULL); - PyCodeObject *code = frame->f_code; - assert(code != NULL); - Py_INCREF(code); - return code; -} - - -PyFrameObject* -PyFrame_GetBack(PyFrameObject *frame) -{ - assert(frame != NULL); - PyFrameObject *back = frame->f_back; - Py_XINCREF(back); - return back; -} + +PyCodeObject * +PyFrame_GetCode(PyFrameObject *frame) +{ + assert(frame != NULL); + PyCodeObject *code = frame->f_code; + assert(code != NULL); + Py_INCREF(code); + return code; +} + + +PyFrameObject* +PyFrame_GetBack(PyFrameObject *frame) +{ + assert(frame != NULL); + PyFrameObject *back = frame->f_back; + Py_XINCREF(back); + return back; +} |