Enable causal stacktrace in kernel
R=kustermann@google.com Review-Url: https://codereview.chromium.org/2690873005 .
This commit is contained in:
@@ -198,6 +198,8 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
|
||||
new VariableDeclaration(":async_op_then");
|
||||
final VariableDeclaration catchErrorContinuationVariable =
|
||||
new VariableDeclaration(":async_op_error");
|
||||
final VariableDeclaration asyncStackTrace =
|
||||
new VariableDeclaration(":async_stack_trace");
|
||||
|
||||
LabeledStatement labeledBody;
|
||||
|
||||
@@ -215,6 +217,9 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
|
||||
// var :async_op_error;
|
||||
statements.add(catchErrorContinuationVariable);
|
||||
|
||||
// var :async_stack_trace;
|
||||
statements.add(asyncStackTrace);
|
||||
|
||||
// :async_op([:result, :exception, :stack_trace]) {
|
||||
// modified <node.body>;
|
||||
// }
|
||||
@@ -258,6 +263,13 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
|
||||
new VariableSet(
|
||||
catchErrorContinuationVariable, boundCatchErrorClosure));
|
||||
statements.add(catchErrorClosureVariableAssign);
|
||||
|
||||
// :async_stack_trace = _asyncStackTraceHelper();
|
||||
final boundAsyncStackTrace = new StaticInvocation(
|
||||
helper.asyncStackTraceHelper, new Arguments.empty());
|
||||
final asyncStackTraceVariableAssign = new ExpressionStatement(
|
||||
new VariableSet(asyncStackTrace, boundAsyncStackTrace));
|
||||
statements.add(asyncStackTraceVariableAssign);
|
||||
}
|
||||
|
||||
Statement buildWrappedBody() {
|
||||
@@ -874,6 +886,7 @@ class HelperNodes {
|
||||
final Constructor streamIteratorConstructor;
|
||||
final Procedure asyncThenWrapper;
|
||||
final Procedure asyncErrorWrapper;
|
||||
final Procedure asyncStackTraceHelper;
|
||||
final Procedure awaitHelper;
|
||||
final CoreTypes coreTypes;
|
||||
|
||||
@@ -891,6 +904,7 @@ class HelperNodes {
|
||||
this.streamControllerConstructor,
|
||||
this.asyncThenWrapper,
|
||||
this.asyncErrorWrapper,
|
||||
this.asyncStackTraceHelper,
|
||||
this.awaitHelper,
|
||||
this.coreTypes);
|
||||
|
||||
@@ -973,6 +987,7 @@ class HelperNodes {
|
||||
findConstructor(streamControllerClass, ''),
|
||||
findProcedure(asyncLibrary, '_asyncThenWrapperHelper'),
|
||||
findProcedure(asyncLibrary, '_asyncErrorWrapperHelper'),
|
||||
findProcedure(asyncLibrary, '_asyncStackTraceHelper'),
|
||||
findProcedure(asyncLibrary, '_awaitHelper'),
|
||||
new CoreTypes(program));
|
||||
}
|
||||
|
||||
@@ -720,6 +720,15 @@ void ScopeBuilder::VisitFunctionNode(FunctionNode* node) {
|
||||
scope_->CaptureVariable(temp);
|
||||
}
|
||||
}
|
||||
if (FLAG_causal_async_stacks) {
|
||||
// TODO(28777): Either remove the variable here, or update the dart side
|
||||
// so we don't always generate it if this flag is not set.
|
||||
LocalVariable* temp =
|
||||
scope_->LookupVariable(Symbols::AsyncStackTraceVar(), true);
|
||||
if (temp != NULL) {
|
||||
scope_->CaptureVariable(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2555,6 +2564,17 @@ Fragment FlowGraphBuilder::Return(TokenPosition position) {
|
||||
new (Z) DebugStepCheckInstr(position, RawPcDescriptors::kRuntimeCall);
|
||||
}
|
||||
|
||||
if (FLAG_causal_async_stacks &&
|
||||
function.name() == Symbols::AsyncOperation().raw()) {
|
||||
// We are returning from an asynchronous closure. Before we do that, be
|
||||
// sure to clear the thread's asynchronous stack trace.
|
||||
const Function& target = Function::ZoneHandle(
|
||||
Z, I->object_store()->async_clear_thread_stack_trace());
|
||||
ASSERT(!target.IsNull());
|
||||
instructions += StaticCall(TokenPosition::kNoSource, target, 0);
|
||||
instructions += Drop();
|
||||
}
|
||||
|
||||
ReturnInstr* return_instr = new (Z) ReturnInstr(position, value);
|
||||
if (exit_collector_ != NULL) exit_collector_->AddExit(return_instr);
|
||||
|
||||
@@ -3171,7 +3191,7 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfFunction(FunctionNode* function,
|
||||
// The code we are building will be executed right after we enter
|
||||
// the function and before any nested contexts are allocated.
|
||||
// Reset current context_depth_ to match this.
|
||||
intptr_t current_context_depth = context_depth_;
|
||||
const intptr_t current_context_depth = context_depth_;
|
||||
context_depth_ = scopes_->yield_jump_variable->owner()->context_level();
|
||||
|
||||
// Prepend an entry corresponding to normal entry to the function.
|
||||
@@ -3237,6 +3257,37 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfFunction(FunctionNode* function,
|
||||
context_depth_ = current_context_depth;
|
||||
}
|
||||
|
||||
if (FLAG_causal_async_stacks &&
|
||||
dart_function.name() == Symbols::AsyncOperation().raw()) {
|
||||
// The code we are building will be executed right after we enter
|
||||
// the function and before any nested contexts are allocated.
|
||||
// Reset current context_depth_ to match this.
|
||||
const intptr_t current_context_depth = context_depth_;
|
||||
context_depth_ = scopes_->yield_jump_variable->owner()->context_level();
|
||||
|
||||
Fragment instructions;
|
||||
LocalScope* scope = parsed_function_->node_sequence()->scope();
|
||||
|
||||
const Function& target = Function::ZoneHandle(
|
||||
Z, I->object_store()->async_set_thread_stack_trace());
|
||||
ASSERT(!target.IsNull());
|
||||
|
||||
// Fetch and load :async_stack_trace
|
||||
LocalVariable* async_stack_trace_var =
|
||||
scope->LookupVariable(Symbols::AsyncStackTraceVar(), false);
|
||||
ASSERT((async_stack_trace_var != NULL) &&
|
||||
async_stack_trace_var->is_captured());
|
||||
instructions += LoadLocal(async_stack_trace_var);
|
||||
instructions += PushArgument();
|
||||
|
||||
// Call _asyncSetThreadStackTrace
|
||||
instructions += StaticCall(TokenPosition::kNoSource, target, 1);
|
||||
instructions += Drop();
|
||||
|
||||
body = instructions + body;
|
||||
context_depth_ = current_context_depth;
|
||||
}
|
||||
|
||||
if (FLAG_support_debugger && function->position().IsDebugPause() &&
|
||||
!dart_function.is_native() && dart_function.is_debuggable()) {
|
||||
// If a switch was added above: Start the switch by injecting a debugable
|
||||
|
||||
@@ -44,7 +44,7 @@ vm/debug_break_enabled_vm_test/01: CompileTimeError
|
||||
vm/debug_break_enabled_vm_test/none: CompileTimeError
|
||||
vm/reflect_core_vm_test: CompileTimeError
|
||||
vm/regress_27201_test: CompileTimeError
|
||||
vm/regress_28325_test: RuntimeError # Issue 28055.
|
||||
# vm/regress_28325_test: RuntimeError # Issue 28055. Passes by mistake.
|
||||
|
||||
# dartk: JIT failures
|
||||
[ $compiler == dartk && $runtime == vm ]
|
||||
@@ -203,9 +203,8 @@ library_env_test/has_no_mirror_support: RuntimeError
|
||||
main_not_a_function_test/01: Crash
|
||||
redirecting_factory_reflection_test: RuntimeError
|
||||
|
||||
# Casual async stack traces are not implemented for Kernel.
|
||||
# Casual async stack traces does not give exactly same stacktrace on kernel
|
||||
vm/causal_async_exception_stack_test: RuntimeError
|
||||
vm/causal_async_exception_stack2_test: RuntimeError
|
||||
|
||||
# dartk: JIT failures (debug)
|
||||
[ $compiler == dartk && $runtime == vm && $mode == debug ]
|
||||
|
||||
Reference in New Issue
Block a user