mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[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 https://github.com/dart-lang/sdk/issues/37668 Change-Id: I896807060db911714d47a462c34696a0a3def62f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/110919 Commit-Queue: Martin Kustermann <kustermann@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
parent
1e16b74b5b
commit
130c654dcd
|
@ -296,13 +296,19 @@ void _completeOnAsyncReturn(Completer completer, Object value) {
|
|||
|
||||
/// Returns a [StackTrace] object containing the synchronous prefix for this
|
||||
/// asynchronous method.
|
||||
//
|
||||
// This method is recognized. It performs a runtime call if
|
||||
// FLAG_causal_async_stacks is enabled or returns `null` otherwise.
|
||||
@pragma("vm:prefer-inline")
|
||||
Object _asyncStackTraceHelper(Function async_op)
|
||||
native "StackTrace_asyncStackTraceHelper";
|
||||
|
||||
// This method is asm intrinsified.
|
||||
@pragma("vm:entry-point", "call")
|
||||
void _clearAsyncThreadStackTrace()
|
||||
native "StackTrace_clearAsyncThreadStackTrace";
|
||||
|
||||
// This method is asm intrinsified.
|
||||
@pragma("vm:entry-point", "call")
|
||||
void _setAsyncThreadStackTrace(StackTrace stackTrace)
|
||||
native "StackTrace_setAsyncThreadStackTrace";
|
||||
|
|
|
@ -108,7 +108,10 @@ DEFINE_NATIVE_ENTRY(StackTrace_current, 0, 0) {
|
|||
|
||||
DEFINE_NATIVE_ENTRY(StackTrace_asyncStackTraceHelper, 0, 1) {
|
||||
if (!FLAG_causal_async_stacks) {
|
||||
return Object::null();
|
||||
// If causal async stacks are not enabled we should recognize this method
|
||||
// and never call to the NOP runtime.
|
||||
// See kernel_to_il.cc/bytecode_reader.cc/interpreter.cc.
|
||||
UNREACHABLE();
|
||||
}
|
||||
#if !defined(PRODUCT)
|
||||
GET_NATIVE_ARGUMENT(Closure, async_op, arguments->NativeArgAt(0));
|
||||
|
|
|
@ -810,6 +810,15 @@ void BytecodeFlowGraphBuilder::BuildDirectCall() {
|
|||
}
|
||||
}
|
||||
|
||||
if (!FLAG_causal_async_stacks &&
|
||||
target.recognized_kind() == MethodRecognizer::kAsyncStackTraceHelper) {
|
||||
ASSERT(argc == 1);
|
||||
// Drop the ignored parameter to _asyncStackTraceHelper(:async_op).
|
||||
code_ += B->Drop();
|
||||
code_ += B->NullConstant();
|
||||
return;
|
||||
}
|
||||
|
||||
const Array& arg_desc_array =
|
||||
Array::Cast(ConstantAt(DecodeOperandD(), 1).value());
|
||||
const ArgumentsDescriptor arg_desc(arg_desc_array);
|
||||
|
|
|
@ -1040,6 +1040,13 @@ RawTypedData* BytecodeReaderHelper::NativeEntry(const Function& function,
|
|||
case MethodRecognizer::kLinkedHashMap_getDeletedKeys:
|
||||
case MethodRecognizer::kLinkedHashMap_setDeletedKeys:
|
||||
break;
|
||||
case MethodRecognizer::kAsyncStackTraceHelper:
|
||||
// If causal async stacks are disabled the interpreter.cc will handle this
|
||||
// native call specially.
|
||||
if (!FLAG_causal_async_stacks) {
|
||||
break;
|
||||
}
|
||||
FALL_THROUGH;
|
||||
default:
|
||||
kind = MethodRecognizer::kUnknown;
|
||||
}
|
||||
|
|
|
@ -3056,6 +3056,10 @@ Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(bool is_const,
|
|||
Fragment instructions;
|
||||
LocalVariable* instance_variable = NULL;
|
||||
|
||||
const bool special_case_nop_async_stack_trace_helper =
|
||||
!FLAG_causal_async_stacks &&
|
||||
target.recognized_kind() == MethodRecognizer::kAsyncStackTraceHelper;
|
||||
|
||||
const bool special_case_unchecked_cast =
|
||||
klass.IsTopLevel() && (klass.library() == Library::InternalLibrary()) &&
|
||||
(target.name() == Symbols::UnsafeCast().raw());
|
||||
|
@ -3064,8 +3068,9 @@ Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(bool is_const,
|
|||
klass.IsTopLevel() && (klass.library() == Library::CoreLibrary()) &&
|
||||
(target.name() == Symbols::Identical().raw());
|
||||
|
||||
const bool special_case =
|
||||
special_case_identical || special_case_unchecked_cast;
|
||||
const bool special_case = special_case_identical ||
|
||||
special_case_unchecked_cast ||
|
||||
special_case_nop_async_stack_trace_helper;
|
||||
|
||||
// If we cross the Kernel -> VM core library boundary, a [StaticInvocation]
|
||||
// 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,
|
|||
ASSERT(argument_count == 2);
|
||||
instructions +=
|
||||
StrictCompare(position, Token::kEQ_STRICT, /*number_check=*/true);
|
||||
} else if (special_case_nop_async_stack_trace_helper) {
|
||||
ASSERT(argument_count == 1);
|
||||
instructions += Drop();
|
||||
instructions += NullConstant();
|
||||
} else if (special_case_unchecked_cast) {
|
||||
// Simply do nothing: the result value is already pushed on the stack.
|
||||
} else {
|
||||
|
|
|
@ -141,6 +141,7 @@ namespace dart {
|
|||
V(_HashVMBase, get:_deletedKeys, LinkedHashMap_getDeletedKeys, 0x558481c2) \
|
||||
V(_HashVMBase, set:_deletedKeys, LinkedHashMap_setDeletedKeys, 0x5aa9888d) \
|
||||
V(::, _classRangeCheck, ClassRangeCheck, 0x2ae76b84) \
|
||||
V(::, _asyncStackTraceHelper, AsyncStackTraceHelper, 0) \
|
||||
|
||||
// List of intrinsics:
|
||||
// (class-name, function-name, intrinsification method, fingerprint).
|
||||
|
|
|
@ -2124,6 +2124,9 @@ SwitchDispatch:
|
|||
case MethodRecognizer::kClassIDgetID: {
|
||||
SP[0] = InterpreterHelpers::GetClassIdAsSmi(SP[0]);
|
||||
} break;
|
||||
case MethodRecognizer::kAsyncStackTraceHelper: {
|
||||
SP[0] = Object::null();
|
||||
} break;
|
||||
case MethodRecognizer::kGrowableArrayCapacity: {
|
||||
RawGrowableObjectArray* instance =
|
||||
reinterpret_cast<RawGrowableObjectArray*>(SP[0]);
|
||||
|
|
|
@ -12524,6 +12524,7 @@ void Library::CheckFunctionFingerprints() {
|
|||
CORE_LIB_INTRINSIC_LIST(CHECK_FINGERPRINTS2);
|
||||
CORE_INTEGER_LIB_INTRINSIC_LIST(CHECK_FINGERPRINTS2);
|
||||
|
||||
all_libs.Add(&Library::ZoneHandle(Library::AsyncLibrary()));
|
||||
all_libs.Add(&Library::ZoneHandle(Library::MathLibrary()));
|
||||
all_libs.Add(&Library::ZoneHandle(Library::TypedDataLibrary()));
|
||||
all_libs.Add(&Library::ZoneHandle(Library::CollectionLibrary()));
|
||||
|
|
Loading…
Reference in a new issue