Commit f60d5770 authored by Marius Wachtler's avatar Marius Wachtler

unwinder: fix 'isDeopt' check

We used to not detect deopt frames in release mode this was because we are looking for 'astInterpretDeopt'
in the call stack but this did not work because the compiler optimized this function to a jmp to astInterpretDeoptInner.

I tested different compiler attributes but I ended up implementing this small wrapper function in assembler
because I think it's the most reliable way to make sure it does appear in the call stack.
parent b00e7a93
......@@ -1857,10 +1857,11 @@ Box* astInterpretFunctionEval(FunctionMetadata* md, Box* globals, Box* boxedLoca
return v ? v : None;
}
static Box* astInterpretDeoptInner(FunctionMetadata* md, AST_expr* after_expr, AST_stmt* enclosing_stmt, Box* expr_val,
FrameStackState frame_state) __attribute__((noinline));
static Box* astInterpretDeoptInner(FunctionMetadata* md, AST_expr* after_expr, AST_stmt* enclosing_stmt, Box* expr_val,
FrameStackState frame_state) {
// caution when changing the function arguments: this function gets called from an assembler wrapper!
extern "C" Box* astInterpretDeoptFromASM(FunctionMetadata* md, AST_expr* after_expr, AST_stmt* enclosing_stmt,
Box* expr_val, FrameStackState frame_state) {
static_assert(sizeof(FrameStackState) <= 2 * 8, "astInterpretDeopt assumes that all args get passed in regs!");
assert(md);
assert(enclosing_stmt);
assert(frame_state.locals);
......@@ -1958,11 +1959,6 @@ static Box* astInterpretDeoptInner(FunctionMetadata* md, AST_expr* after_expr, A
return v ? v : None;
}
Box* astInterpretDeopt(FunctionMetadata* md, AST_expr* after_expr, AST_stmt* enclosing_stmt, Box* expr_val,
FrameStackState frame_state) {
return astInterpretDeoptInner(md, after_expr, enclosing_stmt, expr_val, frame_state);
}
extern "C" void printExprHelper(Box* obj) {
Box* displayhook = PySys_GetObject("displayhook");
if (!displayhook)
......
......@@ -77,8 +77,9 @@ struct Value {
Box* astInterpretFunction(FunctionMetadata* f, Box* closure, Box* generator, Box* globals, Box* arg1, Box* arg2,
Box* arg3, Box** args);
Box* astInterpretFunctionEval(FunctionMetadata* cf, Box* globals, Box* boxedLocals);
Box* astInterpretDeopt(FunctionMetadata* cf, AST_expr* after_expr, AST_stmt* enclosing_stmt, Box* expr_val,
FrameStackState frame_state);
// this function is implemented in the src/codegen/ast_interpreter_exec.S assembler file
extern "C" Box* astInterpretDeopt(FunctionMetadata* cf, AST_expr* after_expr, AST_stmt* enclosing_stmt, Box* expr_val,
FrameStackState frame_state);
struct FrameInfo;
FrameInfo* getFrameInfoForInterpretedFrame(void* frame_ptr);
......
......@@ -32,11 +32,36 @@ executeInnerAndSetupFrame:
sub $16, %rsp
mov %rdi, -8(%rbp)
call executeInnerFromASM
leave
add $16, %rsp
pop %rbp
.cfi_def_cfa rsp,8
ret
.cfi_endproc
.size executeInnerAndSetupFrame,.-executeInnerAndSetupFrame
// This function is just a small wrapper around astInterpretDeoptFromASM.
// Our unwinder must be able to detect deopt frames and by writting this wrapper in assembler we can be sure to correctly
// detect the frame independent of compiler optimizations because this function will always appear in the call stack.
//
// Box* astInterpretDeopt(FunctionMetadata* cf, AST_expr* after_expr, AST_stmt* enclosing_stmt, Box* expr_val,
// FrameStackState frame_state);
.text
.globl astInterpretDeopt
.type astInterpretDeopt,@function
.align 16
astInterpretDeopt:
.cfi_startproc
push %rbp
.cfi_def_cfa_offset 16
.cfi_offset rbp,-16
mov %rsp, %rbp
.cfi_def_cfa_register rbp
call astInterpretDeoptFromASM
pop %rbp
.cfi_def_cfa rsp,8
ret
.cfi_endproc
.size astInterpretDeopt,.-astInterpretDeopt
.section .note.GNU-stack,"",%progbits // we don't need executable stack
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment