mirror of
https://github.com/dart-lang/sdk
synced 2024-09-18 21:01:20 +00:00
[vm,bytecode] Generate calls for causal-async-stacks more consistently
In order to support causal-async-stacks, the following synthetic calls are inserted: _asyncStackTraceHelper, _setAsyncThreadStackTrace and _clearAsyncThreadStackTrace. _asyncStackTraceHelper is always generated in the async transformation. _setAsyncThreadStackTrace and _clearAsyncThreadStackTrace are inserted during bytecode generation (or in the flow graph builder in case of AST pipeline). If bytecode generation options are set inconsistently with --causal-async-stacks VM option, then it was possible that _asyncStackTraceHelper was generated but other calls were not generated, causing incorrect (full, non-truncated) async stack traces. This also causes performance regression as collecting full stack traces takes much more time. This change makes generation of all these calls more consistent: if causal async stacks are disabled during bytecode generation, then all three calls are omitted. Also, in case these calls were generated and present in bytecode, but VM option --causal-async-stacks is disabled, then bytecode flow graph builder turns all these three calls into no-ops. Change-Id: I93eb1d83c675ee093799bb8e37ca3d60a3c5c19d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/120927 Commit-Queue: Alexander Markov <alexmarkov@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Régis Crelier <regis@google.com>
This commit is contained in:
parent
f4f0831c69
commit
62ee78eeec
|
@ -3511,6 +3511,19 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
_generateNode(args.positional.single);
|
||||
return;
|
||||
}
|
||||
if (!options.causalAsyncStacks &&
|
||||
target == coreTypes.asyncStackTraceHelperProcedure) {
|
||||
// Eliminate calls to _asyncStackTraceHelper as causal async stacks are
|
||||
// disabled. These calls are inserted by async transformation
|
||||
// (pkg/kernel/lib/transformations/continuation.dart), but they should be
|
||||
// consistent with _setAsyncThreadStackTrace and
|
||||
// _clearAsyncThreadStackTrace calls generated by bytecode generator.
|
||||
//
|
||||
// Push null as _asyncStackTraceHelper call should leave result
|
||||
// on the stack.
|
||||
asm.emitPushNull();
|
||||
return;
|
||||
}
|
||||
if (target.isFactory) {
|
||||
final constructedClass = target.enclosingClass;
|
||||
if (hasInstantiatorTypeArguments(constructedClass)) {
|
||||
|
|
|
@ -63,17 +63,15 @@ ConstantPool {
|
|||
[26] = Reserved
|
||||
[27] = InstanceField dart:core::_Closure::_function (field)
|
||||
[28] = Reserved
|
||||
[29] = DirectCall 'dart:async::_asyncStackTraceHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[29] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[30] = Reserved
|
||||
[31] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[31] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[32] = Reserved
|
||||
[33] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[33] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
|
||||
[34] = Reserved
|
||||
[35] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
|
||||
[35] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[36] = Reserved
|
||||
[37] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[38] = Reserved
|
||||
[39] = EndClosureFunctionScope
|
||||
[37] = EndClosureFunctionScope
|
||||
}
|
||||
Closure #lib::asyncInFieldInitializer (field)::'<anonymous closure>' async (dart:async::Future < dart:core::int > x) -> dart:async::Future < dart:core::Null >
|
||||
ClosureCode {
|
||||
|
@ -144,29 +142,27 @@ L1:
|
|||
Push r0
|
||||
StoreFieldTOS CP#1
|
||||
StoreContextVar 0, 8
|
||||
Push r0
|
||||
LoadContextVar 0, 8
|
||||
DirectCall CP#29, 1
|
||||
PushNull
|
||||
PopLocal r3
|
||||
Push r0
|
||||
Push r0
|
||||
LoadContextVar 0, 8
|
||||
DirectCall CP#31, 1
|
||||
DirectCall CP#29, 1
|
||||
StoreContextVar 0, 3
|
||||
Push r0
|
||||
Push r0
|
||||
LoadContextVar 0, 8
|
||||
DirectCall CP#33, 1
|
||||
DirectCall CP#31, 1
|
||||
StoreContextVar 0, 4
|
||||
Push r0
|
||||
LoadContextVar 0, 1
|
||||
Push r0
|
||||
LoadContextVar 0, 8
|
||||
DynamicCall CP#35, 2
|
||||
DynamicCall CP#33, 2
|
||||
Drop1
|
||||
Push r0
|
||||
LoadContextVar 0, 1
|
||||
InterfaceCall CP#37, 1
|
||||
InterfaceCall CP#35, 1
|
||||
ReturnTOS
|
||||
}
|
||||
|
||||
|
@ -309,23 +305,22 @@ Bytecode {
|
|||
Push r0
|
||||
StoreFieldTOS CP#6
|
||||
PopLocal r6
|
||||
Push r6
|
||||
DirectCall CP#23, 1
|
||||
PushNull
|
||||
PopLocal r3
|
||||
Push r6
|
||||
DirectCall CP#25, 1
|
||||
DirectCall CP#23, 1
|
||||
PopLocal r4
|
||||
Push r6
|
||||
DirectCall CP#27, 1
|
||||
DirectCall CP#25, 1
|
||||
PopLocal r5
|
||||
Push r0
|
||||
LoadContextVar 0, 0
|
||||
Push r6
|
||||
DynamicCall CP#29, 2
|
||||
DynamicCall CP#27, 2
|
||||
Drop1
|
||||
Push r0
|
||||
LoadContextVar 0, 0
|
||||
InterfaceCall CP#31, 1
|
||||
InterfaceCall CP#29, 1
|
||||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
|
@ -352,16 +347,14 @@ ConstantPool {
|
|||
[20] = Reserved
|
||||
[21] = InstanceField dart:core::_Closure::_function (field)
|
||||
[22] = Reserved
|
||||
[23] = DirectCall 'dart:async::_asyncStackTraceHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[23] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[24] = Reserved
|
||||
[25] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[25] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[26] = Reserved
|
||||
[27] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[27] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
|
||||
[28] = Reserved
|
||||
[29] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
|
||||
[29] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[30] = Reserved
|
||||
[31] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[32] = Reserved
|
||||
}
|
||||
Closure #lib::foo::':async_op' ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
|
||||
ClosureCode {
|
||||
|
@ -487,29 +480,27 @@ Bytecode {
|
|||
Push r0
|
||||
StoreFieldTOS CP#6
|
||||
StoreContextVar 0, 10
|
||||
Push r0
|
||||
LoadContextVar 0, 10
|
||||
DirectCall CP#27, 1
|
||||
PushNull
|
||||
PopLocal r3
|
||||
Push r0
|
||||
Push r0
|
||||
LoadContextVar 0, 10
|
||||
DirectCall CP#29, 1
|
||||
DirectCall CP#27, 1
|
||||
StoreContextVar 0, 4
|
||||
Push r0
|
||||
Push r0
|
||||
LoadContextVar 0, 10
|
||||
DirectCall CP#31, 1
|
||||
DirectCall CP#29, 1
|
||||
StoreContextVar 0, 5
|
||||
Push r0
|
||||
LoadContextVar 0, 2
|
||||
Push r0
|
||||
LoadContextVar 0, 10
|
||||
DynamicCall CP#33, 2
|
||||
DynamicCall CP#31, 2
|
||||
Drop1
|
||||
Push r0
|
||||
LoadContextVar 0, 2
|
||||
InterfaceCall CP#35, 1
|
||||
InterfaceCall CP#33, 1
|
||||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
|
@ -540,16 +531,14 @@ ConstantPool {
|
|||
[24] = Reserved
|
||||
[25] = InstanceField dart:core::_Closure::_function (field)
|
||||
[26] = Reserved
|
||||
[27] = DirectCall 'dart:async::_asyncStackTraceHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[27] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[28] = Reserved
|
||||
[29] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[29] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[30] = Reserved
|
||||
[31] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[31] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
|
||||
[32] = Reserved
|
||||
[33] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
|
||||
[33] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[34] = Reserved
|
||||
[35] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[36] = Reserved
|
||||
}
|
||||
Closure #lib::simpleAsyncAwait::':async_op' ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
|
||||
ClosureCode {
|
||||
|
@ -742,29 +731,27 @@ Bytecode {
|
|||
Push r0
|
||||
StoreFieldTOS CP#6
|
||||
StoreContextVar 0, 10
|
||||
Push r0
|
||||
LoadContextVar 0, 10
|
||||
DirectCall CP#35, 1
|
||||
PushNull
|
||||
PopLocal r3
|
||||
Push r0
|
||||
Push r0
|
||||
LoadContextVar 0, 10
|
||||
DirectCall CP#37, 1
|
||||
DirectCall CP#35, 1
|
||||
StoreContextVar 0, 3
|
||||
Push r0
|
||||
Push r0
|
||||
LoadContextVar 0, 10
|
||||
DirectCall CP#39, 1
|
||||
DirectCall CP#37, 1
|
||||
StoreContextVar 0, 4
|
||||
Push r0
|
||||
LoadContextVar 0, 1
|
||||
Push r0
|
||||
LoadContextVar 0, 10
|
||||
DynamicCall CP#41, 2
|
||||
DynamicCall CP#39, 2
|
||||
Drop1
|
||||
Push r0
|
||||
LoadContextVar 0, 1
|
||||
InterfaceCall CP#43, 1
|
||||
InterfaceCall CP#41, 1
|
||||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
|
@ -803,16 +790,14 @@ ConstantPool {
|
|||
[32] = Reserved
|
||||
[33] = InstanceField dart:core::_Closure::_function (field)
|
||||
[34] = Reserved
|
||||
[35] = DirectCall 'dart:async::_asyncStackTraceHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[35] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[36] = Reserved
|
||||
[37] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[37] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[38] = Reserved
|
||||
[39] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[39] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
|
||||
[40] = Reserved
|
||||
[41] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
|
||||
[41] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[42] = Reserved
|
||||
[43] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[44] = Reserved
|
||||
}
|
||||
Closure #lib::loops::':async_op' ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
|
||||
ClosureCode {
|
||||
|
@ -1142,29 +1127,27 @@ Bytecode {
|
|||
Push r0
|
||||
StoreFieldTOS CP#6
|
||||
StoreContextVar 0, 17
|
||||
Push r0
|
||||
LoadContextVar 0, 17
|
||||
DirectCall CP#33, 1
|
||||
PushNull
|
||||
PopLocal r3
|
||||
Push r0
|
||||
Push r0
|
||||
LoadContextVar 0, 17
|
||||
DirectCall CP#35, 1
|
||||
DirectCall CP#33, 1
|
||||
StoreContextVar 0, 5
|
||||
Push r0
|
||||
Push r0
|
||||
LoadContextVar 0, 17
|
||||
DirectCall CP#37, 1
|
||||
DirectCall CP#35, 1
|
||||
StoreContextVar 0, 6
|
||||
Push r0
|
||||
LoadContextVar 0, 3
|
||||
Push r0
|
||||
LoadContextVar 0, 17
|
||||
DynamicCall CP#39, 2
|
||||
DynamicCall CP#37, 2
|
||||
Drop1
|
||||
Push r0
|
||||
LoadContextVar 0, 3
|
||||
InterfaceCall CP#41, 1
|
||||
InterfaceCall CP#39, 1
|
||||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
|
@ -1201,16 +1184,14 @@ ConstantPool {
|
|||
[30] = Reserved
|
||||
[31] = InstanceField dart:core::_Closure::_function (field)
|
||||
[32] = Reserved
|
||||
[33] = DirectCall 'dart:async::_asyncStackTraceHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[33] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[34] = Reserved
|
||||
[35] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[35] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[36] = Reserved
|
||||
[37] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[37] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
|
||||
[38] = Reserved
|
||||
[39] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
|
||||
[39] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[40] = Reserved
|
||||
[41] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[42] = Reserved
|
||||
}
|
||||
Closure #lib::tryCatchRethrow::':async_op' ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
|
||||
ClosureCode {
|
||||
|
@ -1698,17 +1679,15 @@ ConstantPool {
|
|||
[26] = Reserved
|
||||
[27] = InstanceField dart:core::_Closure::_function (field)
|
||||
[28] = Reserved
|
||||
[29] = DirectCall 'dart:async::_asyncStackTraceHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[29] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[30] = Reserved
|
||||
[31] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[31] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[32] = Reserved
|
||||
[33] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[33] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
|
||||
[34] = Reserved
|
||||
[35] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
|
||||
[35] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[36] = Reserved
|
||||
[37] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[38] = Reserved
|
||||
[39] = EndClosureFunctionScope
|
||||
[37] = EndClosureFunctionScope
|
||||
}
|
||||
Closure #lib::closure::'nested' async () -> dart:async::Future < dart:core::int >
|
||||
ClosureCode {
|
||||
|
@ -1774,29 +1753,27 @@ ClosureCode {
|
|||
Push r0
|
||||
StoreFieldTOS CP#1
|
||||
StoreContextVar 1, 8
|
||||
Push r0
|
||||
LoadContextVar 1, 8
|
||||
DirectCall CP#29, 1
|
||||
PushNull
|
||||
PopLocal r3
|
||||
Push r0
|
||||
Push r0
|
||||
LoadContextVar 1, 8
|
||||
DirectCall CP#31, 1
|
||||
DirectCall CP#29, 1
|
||||
StoreContextVar 1, 2
|
||||
Push r0
|
||||
Push r0
|
||||
LoadContextVar 1, 8
|
||||
DirectCall CP#33, 1
|
||||
DirectCall CP#31, 1
|
||||
StoreContextVar 1, 3
|
||||
Push r0
|
||||
LoadContextVar 1, 0
|
||||
Push r0
|
||||
LoadContextVar 1, 8
|
||||
DynamicCall CP#35, 2
|
||||
DynamicCall CP#33, 2
|
||||
Drop1
|
||||
Push r0
|
||||
LoadContextVar 1, 0
|
||||
InterfaceCall CP#37, 1
|
||||
InterfaceCall CP#35, 1
|
||||
ReturnTOS
|
||||
}
|
||||
|
||||
|
@ -2018,29 +1995,27 @@ Bytecode {
|
|||
Push r0
|
||||
StoreFieldTOS CP#6
|
||||
StoreContextVar 0, 8
|
||||
Push r0
|
||||
LoadContextVar 0, 8
|
||||
DirectCall CP#29, 1
|
||||
PushNull
|
||||
PopLocal r3
|
||||
Push r0
|
||||
Push r0
|
||||
LoadContextVar 0, 8
|
||||
DirectCall CP#31, 1
|
||||
DirectCall CP#29, 1
|
||||
StoreContextVar 0, 3
|
||||
Push r0
|
||||
Push r0
|
||||
LoadContextVar 0, 8
|
||||
DirectCall CP#33, 1
|
||||
DirectCall CP#31, 1
|
||||
StoreContextVar 0, 4
|
||||
Push r0
|
||||
LoadContextVar 0, 1
|
||||
Push r0
|
||||
LoadContextVar 0, 8
|
||||
DynamicCall CP#35, 2
|
||||
DynamicCall CP#33, 2
|
||||
Drop1
|
||||
Push r0
|
||||
LoadContextVar 0, 1
|
||||
InterfaceCall CP#37, 1
|
||||
InterfaceCall CP#35, 1
|
||||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
|
@ -2073,16 +2048,14 @@ ConstantPool {
|
|||
[26] = Reserved
|
||||
[27] = InstanceField dart:core::_Closure::_function (field)
|
||||
[28] = Reserved
|
||||
[29] = DirectCall 'dart:async::_asyncStackTraceHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[29] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[30] = Reserved
|
||||
[31] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[31] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[32] = Reserved
|
||||
[33] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[33] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
|
||||
[34] = Reserved
|
||||
[35] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
|
||||
[35] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[36] = Reserved
|
||||
[37] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
|
||||
[38] = Reserved
|
||||
}
|
||||
Closure #lib::testAssert::':async_op' ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
|
||||
ClosureCode {
|
||||
|
|
|
@ -845,41 +845,48 @@ void BytecodeFlowGraphBuilder::BuildDirectCallCommon(bool is_unchecked_call) {
|
|||
const intptr_t argc = DecodeOperandF().value();
|
||||
|
||||
const auto recognized_kind = MethodRecognizer::RecognizeKind(target);
|
||||
if (recognized_kind == MethodRecognizer::kFfiAsFunctionInternal) {
|
||||
BuildFfiAsFunction();
|
||||
return;
|
||||
} else if (FLAG_precompiled_mode &&
|
||||
recognized_kind == MethodRecognizer::kFfiNativeCallbackFunction) {
|
||||
BuildFfiNativeCallbackFunction();
|
||||
return;
|
||||
}
|
||||
|
||||
// Recognize identical() call.
|
||||
// Note: similar optimization is performed in AST flow graph builder - see
|
||||
// StreamingFlowGraphBuilder::BuildStaticInvocation, special_case_identical.
|
||||
// TODO(alexmarkov): find a better place for this optimization.
|
||||
if (target.name() == Symbols::Identical().raw()) {
|
||||
const auto& owner = Class::Handle(Z, target.Owner());
|
||||
if (owner.IsTopLevel() && (owner.library() == Library::CoreLibrary())) {
|
||||
switch (recognized_kind) {
|
||||
case MethodRecognizer::kFfiAsFunctionInternal:
|
||||
BuildFfiAsFunction();
|
||||
return;
|
||||
case MethodRecognizer::kFfiNativeCallbackFunction:
|
||||
if (FLAG_precompiled_mode) {
|
||||
BuildFfiNativeCallbackFunction();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case MethodRecognizer::kObjectIdentical:
|
||||
// Note: similar optimization is performed in AST flow graph builder -
|
||||
// see StreamingFlowGraphBuilder::BuildStaticInvocation,
|
||||
// special_case_identical.
|
||||
// TODO(alexmarkov): find a better place for this optimization.
|
||||
ASSERT(argc == 2);
|
||||
code_ += B->StrictCompare(Token::kEQ_STRICT, /*number_check=*/true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!FLAG_causal_async_stacks &&
|
||||
recognized_kind == MethodRecognizer::kAsyncStackTraceHelper) {
|
||||
ASSERT(argc == 1);
|
||||
// Drop the ignored parameter to _asyncStackTraceHelper(:async_op).
|
||||
code_ += B->Drop();
|
||||
code_ += B->NullConstant();
|
||||
return;
|
||||
}
|
||||
|
||||
if (recognized_kind == MethodRecognizer::kStringBaseInterpolate) {
|
||||
ASSERT(argc == 1);
|
||||
code_ += B->StringInterpolate(position_);
|
||||
return;
|
||||
case MethodRecognizer::kAsyncStackTraceHelper:
|
||||
case MethodRecognizer::kSetAsyncThreadStackTrace:
|
||||
if (!FLAG_causal_async_stacks) {
|
||||
ASSERT(argc == 1);
|
||||
// Drop the ignored parameter to _asyncStackTraceHelper(:async_op) or
|
||||
// _setAsyncThreadStackTrace(stackTrace).
|
||||
code_ += B->Drop();
|
||||
code_ += B->NullConstant();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case MethodRecognizer::kClearAsyncThreadStackTrace:
|
||||
if (!FLAG_causal_async_stacks) {
|
||||
ASSERT(argc == 0);
|
||||
code_ += B->NullConstant();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case MethodRecognizer::kStringBaseInterpolate:
|
||||
ASSERT(argc == 1);
|
||||
code_ += B->StringInterpolate(position_);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const Array& arg_desc_array =
|
||||
|
|
Loading…
Reference in a new issue