Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
Pyston
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
Pyston
Commits
20d98b25
Commit
20d98b25
authored
Jun 12, 2015
by
Chris Toshok
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
create an UnwindSession type (gc allocated) per thread to contain all the python unwinding state.
parent
8e88774f
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
145 additions
and
94 deletions
+145
-94
src/codegen/ast_interpreter.cpp
src/codegen/ast_interpreter.cpp
+2
-13
src/codegen/irgen/irgenerator.cpp
src/codegen/irgen/irgenerator.cpp
+4
-4
src/codegen/unwinding.cpp
src/codegen/unwinding.cpp
+109
-29
src/codegen/unwinding.h
src/codegen/unwinding.h
+8
-1
src/core/threading.cpp
src/core/threading.cpp
+1
-10
src/core/threading.h
src/core/threading.h
+0
-25
src/core/types.h
src/core/types.h
+2
-1
src/runtime/cxx_unwind.cpp
src/runtime/cxx_unwind.cpp
+12
-6
src/runtime/stacktrace.cpp
src/runtime/stacktrace.cpp
+6
-5
src/runtime/types.cpp
src/runtime/types.cpp
+1
-0
No files found.
src/codegen/ast_interpreter.cpp
View file @
20d98b25
...
...
@@ -632,19 +632,8 @@ Value ASTInterpreter::visit_invoke(AST_Invoke* node) {
next_block
=
node
->
normal_dest
;
}
catch
(
ExcInfo
e
)
{
if
(
threading
::
ThreadStateInternal
::
getUnwindState
()
==
UNWIND_STATE_NORMAL
)
{
// when generating the traceback incrementally we only
// include an interpreter frame if we unwind through
// ASTInterpreter::execute_inner. this will keep a toplevel
// invoke from showing up, since we catch the exception
// here.
auto
source
=
getCF
()
->
clfunc
->
source
.
get
();
BoxedTraceback
::
Here
(
LineInfo
(
node
->
lineno
,
node
->
col_offset
,
source
->
fn
,
source
->
getName
()),
reinterpret_cast
<
BoxedTraceback
**>
(
&
e
.
traceback
));
}
threading
::
ThreadStateInternal
::
setUnwindState
(
UNWIND_STATE_NORMAL
);
auto
source
=
getCF
()
->
clfunc
->
source
.
get
();
exceptionCaughtInInterpreter
(
LineInfo
(
node
->
lineno
,
node
->
col_offset
,
source
->
fn
,
source
->
getName
()),
&
e
);
next_block
=
node
->
exc_dest
;
last_exception
=
e
;
...
...
src/codegen/irgen/irgenerator.cpp
View file @
20d98b25
...
...
@@ -110,8 +110,8 @@ static llvm::Value* getClosureElementGep(IREmitter& emitter, llvm::Value* closur
static
llvm
::
Value
*
getBoxedLocalsGep
(
llvm
::
IRBuilder
<
true
>&
builder
,
llvm
::
Value
*
v
)
{
static_assert
(
offsetof
(
FrameInfo
,
exc
)
==
0
,
""
);
static_assert
(
sizeof
(
ExcInfo
)
==
24
,
""
);
static_assert
(
offsetof
(
FrameInfo
,
boxedLocals
)
==
24
,
""
);
static_assert
(
sizeof
(
ExcInfo
)
==
32
,
""
);
static_assert
(
offsetof
(
FrameInfo
,
boxedLocals
)
==
32
,
""
);
return
builder
.
CreateConstInBoundsGEP2_32
(
v
,
0
,
1
);
}
...
...
@@ -122,9 +122,9 @@ static llvm::Value* getExcinfoGep(llvm::IRBuilder<true>& builder, llvm::Value* v
static
llvm
::
Value
*
getFrameObjGep
(
llvm
::
IRBuilder
<
true
>&
builder
,
llvm
::
Value
*
v
)
{
static_assert
(
offsetof
(
FrameInfo
,
exc
)
==
0
,
""
);
static_assert
(
sizeof
(
ExcInfo
)
==
24
,
""
);
static_assert
(
sizeof
(
ExcInfo
)
==
32
,
""
);
static_assert
(
sizeof
(
Box
*
)
==
8
,
""
);
static_assert
(
offsetof
(
FrameInfo
,
frame_obj
)
==
32
,
""
);
static_assert
(
offsetof
(
FrameInfo
,
frame_obj
)
==
40
,
""
);
return
builder
.
CreateConstInBoundsGEP2_32
(
v
,
0
,
2
);
// TODO: this could be made more resilient by doing something like
// gep->accumulateConstantOffset(g.tm->getDataLayout(), ap_offset)
...
...
src/codegen/unwinding.cpp
View file @
20d98b25
...
...
@@ -58,6 +58,10 @@ struct uw_table_entry {
namespace
pyston
{
namespace
{
static
BoxedClass
*
unwind_session_cls
;
}
// Parse an .eh_frame section, and construct a "binary search table" such as you would find in a .eh_frame_hdr section.
// Currently only supports .eh_frame sections with exactly one fde.
// See http://www.airs.com/blog/archives/460 for some useful info.
...
...
@@ -441,8 +445,7 @@ static inline unw_word_t get_cursor_bp(unw_cursor_t* cursor) {
return
get_cursor_reg
(
cursor
,
UNW_TDEP_BP
);
}
template
<
typename
FrameFunc
>
bool
unwindProcessFrame
(
unw_word_t
ip
,
unw_word_t
bp
,
unw_cursor_t
*
cursor
,
FrameFunc
func
)
{
bool
unwindProcessFrame
(
unw_word_t
ip
,
unw_word_t
bp
,
unw_cursor_t
*
cursor
,
PythonFrameIteratorImpl
*
info
)
{
CompiledFunction
*
cf
=
getCFForAddress
(
ip
);
bool
jitted
=
cf
!=
NULL
;
if
(
!
cf
)
{
...
...
@@ -455,7 +458,7 @@ bool unwindProcessFrame(unw_word_t ip, unw_word_t bp, unw_cursor_t* cursor, Fram
if
(
!
cf
)
return
false
;
PythonFrameIteratorImpl
info
(
jitted
?
PythonFrameId
::
COMPILED
:
PythonFrameId
::
INTERPRETED
,
ip
,
bp
,
cf
);
*
info
=
PythonFrameIteratorImpl
(
jitted
?
PythonFrameId
::
COMPILED
:
PythonFrameId
::
INTERPRETED
,
ip
,
bp
,
cf
);
if
(
jitted
)
{
// Try getting all the callee-save registers, and save the ones we were able to get.
// Some of them may be inaccessible, I think because they weren't defined by that
...
...
@@ -467,22 +470,56 @@ bool unwindProcessFrame(unw_word_t ip, unw_word_t bp, unw_cursor_t* cursor, Fram
int
code
=
unw_get_reg
(
cursor
,
i
,
&
r
);
ASSERT
(
code
==
0
||
code
==
-
UNW_EBADREG
,
"%d %d"
,
code
,
i
);
if
(
code
==
0
)
{
info
.
regs
[
i
]
=
r
;
info
.
regs_valid
|=
(
1
<<
i
);
info
->
regs
[
i
]
=
r
;
info
->
regs_valid
|=
(
1
<<
i
);
}
}
}
return
func
(
&
info
)
;
return
true
;
}
class
UnwindSession
:
public
Box
{
ExcInfo
exc_info
;
bool
skip
;
public:
DEFAULT_CLASS_SIMPLE
(
unwind_session_cls
);
UnwindSession
()
:
exc_info
(
NULL
,
NULL
,
NULL
),
skip
(
false
)
{}
ExcInfo
*
getExcInfoStorage
()
{
return
&
exc_info
;
}
bool
shouldSkipFrame
()
const
{
return
skip
;
}
void
setShouldSkipNextFrame
(
bool
skip
)
{
this
->
skip
=
skip
;
}
void
clear
()
{
exc_info
=
ExcInfo
(
NULL
,
NULL
,
NULL
);
skip
=
false
;
}
void
addTraceback
(
const
LineInfo
&
line_info
)
{
if
(
exc_info
.
reraise
)
{
exc_info
.
reraise
=
false
;
return
;
}
BoxedTraceback
::
Here
(
line_info
,
reinterpret_cast
<
BoxedTraceback
**>
(
&
exc_info
.
traceback
));
}
static
void
gcHandler
(
GCVisitor
*
v
,
Box
*
_o
)
{
// assert(_o->cls == unwind_session_cls)
UnwindSession
*
o
=
static_cast
<
UnwindSession
*>
(
_o
);
v
->
visitIf
(
o
->
exc_info
.
type
);
v
->
visitIf
(
o
->
exc_info
.
value
);
v
->
visitIf
(
o
->
exc_info
.
traceback
);
}
};
// While I'm not a huge fan of the callback-passing style, libunwind cursors are only valid for
// the stack frame that they were created in, so we need to use this approach (as opposed to
// C++11 range loops, for example).
// Return true from the handler to stop iteration at that frame.
template
<
typename
Func
>
void
unwindPythonStack
(
Func
func
)
{
threading
::
ThreadStateInternal
::
setUnwindState
(
UNWIND_STATE_NORMAL
);
// ensure we won't be skipping any python frames at the start
UnwindSession
*
unwind_state
=
(
UnwindSession
*
)
beginUnwind
();
unw_context_t
ctx
;
unw_cursor_t
cursor
;
unw_getcontext
(
&
ctx
);
...
...
@@ -498,20 +535,20 @@ template <typename Func> void unwindPythonStack(Func func) {
unw_word_t
ip
=
get_cursor_ip
(
&
cursor
);
unw_word_t
bp
=
get_cursor_bp
(
&
cursor
);
bool
stop_unwinding
=
unwindProcessFrame
(
ip
,
bp
,
&
cursor
,
[
&
](
PythonFrameIteratorImpl
*
frame_iter
)
{
bool
rtn
=
false
;
if
(
threading
::
ThreadStateInternal
::
getUnwindState
()
==
UNWIND_STATE_NORMAL
)
rtn
=
func
(
frame_iter
);
bool
stop_unwinding
=
false
;
threading
::
ThreadStateInternal
::
setUnwindState
(
(
bool
)
frame_iter
->
cf
->
entry_descriptor
?
UNWIND_STATE_SKIPNEXT
:
UNWIND_STATE_NORMAL
);
return
rtn
;
}
);
PythonFrameIteratorImpl
frame_iter
;
if
(
unwindProcessFrame
(
ip
,
bp
,
&
cursor
,
&
frame_iter
))
{
if
(
!
unwind_state
->
shouldSkipFrame
())
stop_unwinding
=
func
(
&
frame_iter
);
if
(
stop_unwinding
)
{
break
;
// frame_iter->cf->entry_descriptor will be non-null for OSR frames.
unwind_state
->
setShouldSkipNextFrame
((
bool
)
frame_iter
.
cf
->
entry_descriptor
)
;
}
if
(
stop_unwinding
)
break
;
if
(
inGeneratorEntry
(
ip
))
{
// for generators continue unwinding in the context in which the generator got called
Context
*
remote_ctx
=
getReturnContextForGeneratorFrame
((
void
*
)
bp
);
...
...
@@ -530,6 +567,8 @@ template <typename Func> void unwindPythonStack(Func func) {
// keep unwinding
}
endUnwind
(
unwind_state
);
}
static
std
::
unique_ptr
<
PythonFrameIteratorImpl
>
getTopPythonFrame
()
{
...
...
@@ -552,23 +591,58 @@ static const LineInfo lineInfoForFrame(PythonFrameIteratorImpl* frame_it) {
return
LineInfo
(
current_stmt
->
lineno
,
current_stmt
->
col_offset
,
source
->
fn
,
source
->
getName
());
}
void
maybeTracebackHere
(
void
*
unw_cursor
)
{
void
exceptionCaughtInInterpreter
(
LineInfo
line_info
,
ExcInfo
*
exc_info
)
{
if
(
exc_info
->
reraise
)
{
exc_info
->
reraise
=
false
;
return
;
}
BoxedTraceback
::
Here
(
line_info
,
reinterpret_cast
<
BoxedTraceback
**>
(
&
exc_info
->
traceback
));
}
static
__thread
UnwindSession
*
cur_unwind
;
void
*
beginUnwind
()
{
if
(
!
cur_unwind
)
{
cur_unwind
=
new
UnwindSession
();
pyston
::
gc
::
registerPermanentRoot
(
cur_unwind
);
}
// if we can figure out a way to make endUnwind in cxx_uwind.cpp work, we can remove this.
cur_unwind
->
clear
();
return
cur_unwind
;
}
void
*
getUnwind
()
{
RELEASE_ASSERT
(
cur_unwind
,
""
);
return
cur_unwind
;
}
void
endUnwind
(
void
*
unwind
)
{
RELEASE_ASSERT
(
unwind
&&
unwind
==
cur_unwind
,
""
);
cur_unwind
->
clear
();
}
void
*
getExceptionFerry
(
void
*
unwind
)
{
RELEASE_ASSERT
(
unwind
&&
unwind
==
cur_unwind
,
""
);
UnwindSession
*
state
=
static_cast
<
UnwindSession
*>
(
unwind
);
return
state
->
getExcInfoStorage
();
}
void
maybeTracebackHere
(
void
*
unw_cursor
,
void
*
unwind_token
)
{
unw_cursor_t
*
cursor
=
(
unw_cursor_t
*
)
unw_cursor
;
UnwindSession
*
state
=
(
UnwindSession
*
)
unwind_token
;
unw_word_t
ip
=
get_cursor_ip
(
cursor
);
unw_word_t
bp
=
get_cursor_bp
(
cursor
);
BoxedTraceback
**
tb_loc
=
reinterpret_cast
<
BoxedTraceback
**>
(
&
threading
::
ThreadStateInternal
::
getExceptionFerry
()
->
traceback
);
unwindProcessFrame
(
ip
,
bp
,
cursor
,
[
&
](
PythonFrameIteratorImpl
*
frame_iter
)
{
if
(
threading
::
ThreadStateInternal
::
getUnwindState
()
==
UNWIND_STATE_NORMAL
)
BoxedTraceback
::
Here
(
lineInfoForFrame
(
frame_iter
),
tb_loc
);
PythonFrameIteratorImpl
frame_iter
;
if
(
unwindProcessFrame
(
ip
,
bp
,
cursor
,
&
frame_iter
))
{
if
(
!
state
->
shouldSkipFrame
())
{
state
->
addTraceback
(
lineInfoForFrame
(
&
frame_iter
));
}
threading
::
ThreadStateInternal
::
setUnwindState
((
bool
)
frame_iter
->
cf
->
entry_descriptor
?
UNWIND_STATE_SKIPNEXT
:
UNWIND_STATE_NORMAL
);
return
false
;
});
// frame_iter->cf->entry_descriptor will be non-null for OSR frames.
state
->
setShouldSkipNextFrame
((
bool
)
frame_iter
.
cf
->
entry_descriptor
);
}
}
// To produce a traceback, we:
...
...
@@ -1053,4 +1127,10 @@ void logByCurrentPythonLine(const std::string& stat_name) {
llvm
::
JITEventListener
*
makeTracebacksListener
()
{
return
new
TracebacksEventListener
();
}
void
setupUnwinding
()
{
unwind_session_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
UnwindSession
::
gcHandler
,
0
,
0
,
sizeof
(
UnwindSession
),
false
,
"unwind_session"
);
unwind_session_cls
->
freeze
();
}
}
src/codegen/unwinding.h
View file @
20d98b25
...
...
@@ -29,6 +29,7 @@ struct FrameInfo;
void
registerDynamicEhFrame
(
uint64_t
code_addr
,
size_t
code_size
,
uint64_t
eh_frame_addr
,
size_t
eh_frame_size
);
void
setupUnwinding
();
BoxedModule
*
getCurrentModule
();
Box
*
getGlobals
();
// returns either the module or a globals dict
Box
*
getGlobalsDict
();
// always returns a dict-like object
...
...
@@ -36,7 +37,13 @@ CompiledFunction* getCFForAddress(uint64_t addr);
BoxedTraceback
*
getTraceback
();
void
maybeTracebackHere
(
void
*
unw_cursor
);
void
*
beginUnwind
();
void
*
getUnwind
();
void
endUnwind
(
void
*
unwind_token
);
void
*
getExceptionFerry
(
void
*
unwind_token
);
void
exceptionCaughtInInterpreter
(
LineInfo
line_info
,
ExcInfo
*
exc_info
);
void
maybeTracebackHere
(
void
*
unw_cursor
,
void
*
unwind_token
);
struct
ExecutionPoint
{
CompiledFunction
*
cf
;
...
...
src/core/threading.cpp
View file @
20d98b25
...
...
@@ -52,12 +52,7 @@ PthreadFastMutex threading_lock;
int
num_starting_threads
(
0
);
ThreadStateInternal
::
ThreadStateInternal
(
void
*
stack_start
,
pthread_t
pthread_id
,
PyThreadState
*
public_thread_state
)
:
saved
(
false
),
stack_start
(
stack_start
),
pthread_id
(
pthread_id
),
unwind_state
(
UNWIND_STATE_NORMAL
),
exc_info
(
NULL
,
NULL
,
NULL
),
public_thread_state
(
public_thread_state
)
{
:
saved
(
false
),
stack_start
(
stack_start
),
pthread_id
(
pthread_id
),
public_thread_state
(
public_thread_state
)
{
}
void
ThreadStateInternal
::
accept
(
gc
::
GCVisitor
*
v
)
{
...
...
@@ -67,10 +62,6 @@ void ThreadStateInternal::accept(gc::GCVisitor* v) {
v
->
visitIf
(
pub_state
->
curexc_traceback
);
v
->
visitIf
(
pub_state
->
dict
);
v
->
visitIf
(
exc_info
.
type
);
v
->
visitIf
(
exc_info
.
value
);
v
->
visitIf
(
exc_info
.
traceback
);
for
(
auto
&
stack_info
:
previous_stacks
)
{
v
->
visit
(
stack_info
.
next_generator
);
#if STACK_GROWS_DOWN
...
...
src/core/threading.h
View file @
20d98b25
...
...
@@ -32,13 +32,6 @@ namespace gc {
class
GCVisitor
;
}
// somewhat similar to CPython's WHY_* enum
// UNWIND_STATE_NORMAL : == WHY_EXCEPTION. we call it "NORMAL" since we often unwind due to things other than
// exceptions (getGlobals, getLocals, etc)
// UNWIND_STATE_SKIPNEXT: skip this frame (do not include it in tracebacks). this happens when re-raising an exception
// and also when dealing with osr replacements (we skip the frame we OSR).
enum
UnwindState
{
UNWIND_STATE_NORMAL
=
0
,
UNWIND_STATE_SKIPNEXT
};
namespace
threading
{
class
ThreadStateInternal
{
...
...
@@ -82,9 +75,6 @@ public:
std
::
vector
<
StackInfo
>
previous_stacks
;
pthread_t
pthread_id
;
UnwindState
unwind_state
;
ExcInfo
exc_info
;
PyThreadState
*
public_thread_state
;
ThreadStateInternal
(
void
*
stack_start
,
pthread_t
pthread_id
,
PyThreadState
*
public_thread_state
);
...
...
@@ -117,21 +107,6 @@ public:
assert
(
ThreadStateInternal
::
current
);
current
->
_popGenerator
();
}
inline
static
void
setUnwindState
(
UnwindState
state
)
{
assert
(
ThreadStateInternal
::
current
);
current
->
unwind_state
=
state
;
}
inline
static
UnwindState
getUnwindState
()
{
assert
(
ThreadStateInternal
::
current
);
return
current
->
unwind_state
;
}
static
ExcInfo
*
getExceptionFerry
()
{
assert
(
ThreadStateInternal
::
current
);
return
&
current
->
exc_info
;
}
};
// Whether or not a second thread was ever started:
...
...
src/core/types.h
View file @
20d98b25
...
...
@@ -679,11 +679,12 @@ public:
struct
ExcInfo
{
Box
*
type
,
*
value
,
*
traceback
;
bool
reraise
;
#ifndef NDEBUG
ExcInfo
(
Box
*
type
,
Box
*
value
,
Box
*
traceback
);
#else
ExcInfo
(
Box
*
type
,
Box
*
value
,
Box
*
traceback
)
:
type
(
type
),
value
(
value
),
traceback
(
traceback
)
{}
ExcInfo
(
Box
*
type
,
Box
*
value
,
Box
*
traceback
)
:
type
(
type
),
value
(
value
),
traceback
(
traceback
)
,
reraise
(
false
)
{}
#endif
bool
matches
(
BoxedClass
*
cls
)
const
;
void
printExcAndTraceback
()
const
;
...
...
src/runtime/cxx_unwind.cpp
View file @
20d98b25
...
...
@@ -493,12 +493,14 @@ static inline void unwind_loop(ExcInfo* exc_data) {
unw_getcontext
(
&
uc
);
unw_init_local
(
&
cursor
,
&
uc
);
void
*
unwind_token
=
getUnwind
();
while
(
unw_step
(
&
cursor
)
>
0
)
{
unw_proc_info_t
pip
;
{
// NB. unw_get_proc_info is slow; a significant chunk of all time spent unwinding is spent here.
check
(
unw_get_proc_info
(
&
cursor
,
&
pip
));
}
// NB. unw_get_proc_info is slow; a significant chunk of all time spent unwinding is spent here.
check
(
unw_get_proc_info
(
&
cursor
,
&
pip
));
assert
((
pip
.
lsda
==
0
)
==
(
pip
.
handler
==
0
));
assert
(
pip
.
flags
==
0
);
...
...
@@ -506,7 +508,7 @@ static inline void unwind_loop(ExcInfo* exc_data) {
print_frame
(
&
cursor
,
&
pip
);
}
maybeTracebackHere
(
&
cursor
);
maybeTracebackHere
(
&
cursor
,
unwind_token
);
// Skip frames without handlers
if
(
pip
.
handler
==
0
)
{
...
...
@@ -554,6 +556,10 @@ static inline void unwind_loop(ExcInfo* exc_data) {
}
int64_t
switch_value
=
determine_action
(
&
info
,
&
entry
);
if
(
switch_value
!=
CLEANUP_ACTION
)
{
// printf ("cleanup action == %ld, should end unwind session\n", switch_value);
// endUnwind(unwind_token);
}
resume
(
&
cursor
,
entry
.
landing_pad
,
switch_value
,
exc_data
);
}
...
...
@@ -631,7 +637,7 @@ extern "C" void* __cxa_allocate_exception(size_t size) noexcept {
// our exception info in curexc_*, and then unset these in __cxa_end_catch, then we'll wipe our exception info
// during unwinding!
return
pyston
::
threading
::
ThreadStateInternal
::
getExceptionFerry
(
);
return
pyston
::
getExceptionFerry
(
pyston
::
getUnwind
()
);
}
// Takes the value that resume() sent us in RAX, and returns a pointer to the exception object actually thrown. In our
...
...
src/runtime/stacktrace.cpp
View file @
20d98b25
...
...
@@ -72,11 +72,12 @@ void raiseRaw(const ExcInfo& e) {
#endif
#endif
// printf ("beginning unwind\n");
beginUnwind
();
throw
e
;
}
void
raiseExc
(
Box
*
exc_obj
)
{
threading
::
ThreadStateInternal
::
setUnwindState
(
UNWIND_STATE_NORMAL
);
raiseRaw
(
ExcInfo
(
exc_obj
->
cls
,
exc_obj
,
new
BoxedTraceback
()));
}
...
...
@@ -205,13 +206,13 @@ extern "C" void raise0() {
if
(
exc_info
->
type
==
None
)
raiseExcHelper
(
TypeError
,
"exceptions must be old-style classes or derived from BaseException, not NoneType"
);
threading
::
ThreadStateInternal
::
setUnwindState
(
UNWIND_STATE_SKIPNEXT
);
exc_info
->
reraise
=
true
;
raiseRaw
(
*
exc_info
);
}
#ifndef NDEBUG
ExcInfo
::
ExcInfo
(
Box
*
type
,
Box
*
value
,
Box
*
traceback
)
:
type
(
type
),
value
(
value
),
traceback
(
traceback
)
{
ExcInfo
::
ExcInfo
(
Box
*
type
,
Box
*
value
,
Box
*
traceback
)
:
type
(
type
),
value
(
value
),
traceback
(
traceback
),
reraise
(
false
)
{
}
#endif
...
...
@@ -286,7 +287,7 @@ extern "C" void raise3(Box* arg0, Box* arg1, Box* arg2) {
bool
reraise
=
arg2
!=
NULL
&&
arg2
!=
None
;
auto
exc_info
=
excInfoForRaise
(
arg0
,
arg1
,
arg2
);
threading
::
ThreadStateInternal
::
setUnwindState
(
reraise
?
UNWIND_STATE_SKIPNEXT
:
UNWIND_STATE_NORMAL
)
;
exc_info
.
reraise
=
reraise
;
raiseRaw
(
exc_info
);
}
...
...
src/runtime/types.cpp
View file @
20d98b25
...
...
@@ -2703,6 +2703,7 @@ void setupRuntime() {
closure_cls
->
freeze
();
setupUnwinding
();
setupInterpreter
();
setupCAPI
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment