Skip to content

Commit 130c654

Browse files
mkustermanncommit-bot@chromium.org
authored andcommitted
[vm/compiler] Avoid runtime call for _asyncStackTraceHelper if !FLAG_causal_async_stacks
Even though the FLAG_causal_async_stacks can be used to disable causal async stack traces, the generated code would still call to the runtime, which would simply return `null`. To avoid this runtime call we recognize the method in the 2 flow graph builders. Issue #37668 Change-Id: I896807060db911714d47a462c34696a0a3def62f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/110919 Commit-Queue: Martin Kustermann <[email protected]> Reviewed-by: Alexander Markov <[email protected]>
1 parent 1e16b74 commit 130c654

8 files changed

+42
-3
lines changed

runtime/lib/async_patch.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,13 +296,19 @@ void _completeOnAsyncReturn(Completer completer, Object value) {
296296

297297
/// Returns a [StackTrace] object containing the synchronous prefix for this
298298
/// asynchronous method.
299+
//
300+
// This method is recognized. It performs a runtime call if
301+
// FLAG_causal_async_stacks is enabled or returns `null` otherwise.
302+
@pragma("vm:prefer-inline")
299303
Object _asyncStackTraceHelper(Function async_op)
300304
native "StackTrace_asyncStackTraceHelper";
301305

306+
// This method is asm intrinsified.
302307
@pragma("vm:entry-point", "call")
303308
void _clearAsyncThreadStackTrace()
304309
native "StackTrace_clearAsyncThreadStackTrace";
305310

311+
// This method is asm intrinsified.
306312
@pragma("vm:entry-point", "call")
307313
void _setAsyncThreadStackTrace(StackTrace stackTrace)
308314
native "StackTrace_setAsyncThreadStackTrace";

runtime/lib/stacktrace.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,10 @@ DEFINE_NATIVE_ENTRY(StackTrace_current, 0, 0) {
108108

109109
DEFINE_NATIVE_ENTRY(StackTrace_asyncStackTraceHelper, 0, 1) {
110110
if (!FLAG_causal_async_stacks) {
111-
return Object::null();
111+
// If causal async stacks are not enabled we should recognize this method
112+
// and never call to the NOP runtime.
113+
// See kernel_to_il.cc/bytecode_reader.cc/interpreter.cc.
114+
UNREACHABLE();
112115
}
113116
#if !defined(PRODUCT)
114117
GET_NATIVE_ARGUMENT(Closure, async_op, arguments->NativeArgAt(0));

runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -810,6 +810,15 @@ void BytecodeFlowGraphBuilder::BuildDirectCall() {
810810
}
811811
}
812812

813+
if (!FLAG_causal_async_stacks &&
814+
target.recognized_kind() == MethodRecognizer::kAsyncStackTraceHelper) {
815+
ASSERT(argc == 1);
816+
// Drop the ignored parameter to _asyncStackTraceHelper(:async_op).
817+
code_ += B->Drop();
818+
code_ += B->NullConstant();
819+
return;
820+
}
821+
813822
const Array& arg_desc_array =
814823
Array::Cast(ConstantAt(DecodeOperandD(), 1).value());
815824
const ArgumentsDescriptor arg_desc(arg_desc_array);

runtime/vm/compiler/frontend/bytecode_reader.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,13 @@ RawTypedData* BytecodeReaderHelper::NativeEntry(const Function& function,
10401040
case MethodRecognizer::kLinkedHashMap_getDeletedKeys:
10411041
case MethodRecognizer::kLinkedHashMap_setDeletedKeys:
10421042
break;
1043+
case MethodRecognizer::kAsyncStackTraceHelper:
1044+
// If causal async stacks are disabled the interpreter.cc will handle this
1045+
// native call specially.
1046+
if (!FLAG_causal_async_stacks) {
1047+
break;
1048+
}
1049+
FALL_THROUGH;
10431050
default:
10441051
kind = MethodRecognizer::kUnknown;
10451052
}

runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3056,6 +3056,10 @@ Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(bool is_const,
30563056
Fragment instructions;
30573057
LocalVariable* instance_variable = NULL;
30583058

3059+
const bool special_case_nop_async_stack_trace_helper =
3060+
!FLAG_causal_async_stacks &&
3061+
target.recognized_kind() == MethodRecognizer::kAsyncStackTraceHelper;
3062+
30593063
const bool special_case_unchecked_cast =
30603064
klass.IsTopLevel() && (klass.library() == Library::InternalLibrary()) &&
30613065
(target.name() == Symbols::UnsafeCast().raw());
@@ -3064,8 +3068,9 @@ Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(bool is_const,
30643068
klass.IsTopLevel() && (klass.library() == Library::CoreLibrary()) &&
30653069
(target.name() == Symbols::Identical().raw());
30663070

3067-
const bool special_case =
3068-
special_case_identical || special_case_unchecked_cast;
3071+
const bool special_case = special_case_identical ||
3072+
special_case_unchecked_cast ||
3073+
special_case_nop_async_stack_trace_helper;
30693074

30703075
// If we cross the Kernel -> VM core library boundary, a [StaticInvocation]
30713076
// can appear, but the thing we're calling is not a static method, but a
@@ -3130,6 +3135,10 @@ Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(bool is_const,
31303135
ASSERT(argument_count == 2);
31313136
instructions +=
31323137
StrictCompare(position, Token::kEQ_STRICT, /*number_check=*/true);
3138+
} else if (special_case_nop_async_stack_trace_helper) {
3139+
ASSERT(argument_count == 1);
3140+
instructions += Drop();
3141+
instructions += NullConstant();
31333142
} else if (special_case_unchecked_cast) {
31343143
// Simply do nothing: the result value is already pushed on the stack.
31353144
} else {

runtime/vm/compiler/recognized_methods_list.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ namespace dart {
141141
V(_HashVMBase, get:_deletedKeys, LinkedHashMap_getDeletedKeys, 0x558481c2) \
142142
V(_HashVMBase, set:_deletedKeys, LinkedHashMap_setDeletedKeys, 0x5aa9888d) \
143143
V(::, _classRangeCheck, ClassRangeCheck, 0x2ae76b84) \
144+
V(::, _asyncStackTraceHelper, AsyncStackTraceHelper, 0) \
144145

145146
// List of intrinsics:
146147
// (class-name, function-name, intrinsification method, fingerprint).

runtime/vm/interpreter.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2124,6 +2124,9 @@ RawObject* Interpreter::Call(RawFunction* function,
21242124
case MethodRecognizer::kClassIDgetID: {
21252125
SP[0] = InterpreterHelpers::GetClassIdAsSmi(SP[0]);
21262126
} break;
2127+
case MethodRecognizer::kAsyncStackTraceHelper: {
2128+
SP[0] = Object::null();
2129+
} break;
21272130
case MethodRecognizer::kGrowableArrayCapacity: {
21282131
RawGrowableObjectArray* instance =
21292132
reinterpret_cast<RawGrowableObjectArray*>(SP[0]);

runtime/vm/object.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12524,6 +12524,7 @@ void Library::CheckFunctionFingerprints() {
1252412524
CORE_LIB_INTRINSIC_LIST(CHECK_FINGERPRINTS2);
1252512525
CORE_INTEGER_LIB_INTRINSIC_LIST(CHECK_FINGERPRINTS2);
1252612526

12527+
all_libs.Add(&Library::ZoneHandle(Library::AsyncLibrary()));
1252712528
all_libs.Add(&Library::ZoneHandle(Library::MathLibrary()));
1252812529
all_libs.Add(&Library::ZoneHandle(Library::TypedDataLibrary()));
1252912530
all_libs.Add(&Library::ZoneHandle(Library::CollectionLibrary()));

0 commit comments

Comments
 (0)