Save the index of a co_extra per thread and use it for accessing the field (PY-22725 )

This commit is contained in:
Elizaveta Shashkova
2017-03-03 11:34:00 +03:00
parent 34231ffcbb
commit 2fe91f6d56
2 changed files with 1138 additions and 865 deletions
File diff suppressed because it is too large Load Diff
@@ -19,7 +19,11 @@ NO_BREAKS_IN_FRAME = 1
class UseCodeExtraHolder:
# Use this flag in order to disable co_extra field
use_code_extra = True
# Keep the index of co_extra in a thread-local storage
local = threading.local()
local.index = -1
def is_use_code_extra():
@@ -36,14 +40,20 @@ cdef PyObject* get_bytecode_while_frame_eval(PyFrameObject *frame_obj, int exc):
cdef bint skip_file = exc
cdef void* extra = NULL
cdef int* extra_value = NULL
cdef int thread_index = -1
if is_use_code_extra():
extra = PyMem_Malloc(sizeof(int))
_PyCode_GetExtra(<PyObject*> frame.f_code, 0, &extra)
if extra is not NULL:
extra_value = <int*> extra
if extra_value[0] == NO_BREAKS_IN_FRAME:
return _PyEval_EvalFrameDefault(frame_obj, exc)
try:
thread_index = UseCodeExtraHolder.local.index
except:
pass
if thread_index != -1:
_PyCode_GetExtra(<PyObject*> frame.f_code, thread_index, &extra)
if extra is not NULL:
extra_value = <int*> extra
if extra_value[0] == NO_BREAKS_IN_FRAME:
return _PyEval_EvalFrameDefault(frame_obj, exc)
for file in AVOID_RECURSION:
# we can't call any other function without this check, because we can get stack overflow
@@ -53,12 +63,11 @@ cdef PyObject* get_bytecode_while_frame_eval(PyFrameObject *frame_obj, int exc):
if not skip_file:
try:
threading.currentThread()
t = threading.currentThread()
except:
skip_file = True
if not skip_file:
t = threading.currentThread()
try:
additional_info = t.additional_info
if additional_info is None:
@@ -66,7 +75,8 @@ cdef PyObject* get_bytecode_while_frame_eval(PyFrameObject *frame_obj, int exc):
except:
additional_info = t.additional_info = PyDBAdditionalThreadInfo()
# request `co_extra` inside every new thread
_PyEval_RequestCodeExtraIndex(PyMem_Free)
thread_index = _PyEval_RequestCodeExtraIndex(PyMem_Free)
UseCodeExtraHolder.local.index = thread_index
if additional_info.is_tracing or getattr(t, 'pydev_do_not_trace', None):
return _PyEval_EvalFrameDefault(frame_obj, exc)
@@ -117,7 +127,12 @@ cdef PyObject* get_bytecode_while_frame_eval(PyFrameObject *frame_obj, int exc):
if not was_break:
extra_value = <int*> PyMem_Malloc(sizeof(int))
extra_value[0] = NO_BREAKS_IN_FRAME
_PyCode_SetExtra(<PyObject*> code_object, 0, extra_value)
try:
thread_index = UseCodeExtraHolder.local.index
except:
pass
if thread_index != -1:
_PyCode_SetExtra(<PyObject*> code_object, thread_index, extra_value)
additional_info.is_tracing = False
return _PyEval_EvalFrameDefault(frame_obj, exc)