23#define H (translation_helper_)
24#define T (type_translator_)
25#define I Isolate::Current()
26#define IG IsolateGroup::Current()
27#define B (flow_graph_builder_)
29Class& StreamingFlowGraphBuilder::GetSuperOrDie() {
32 klass = klass.SuperClass();
37FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfFieldInitializer() {
47 ASSERT(!field_helper.IsConst() ||
53 if (initializer_tag != kSomething) {
57 B->graph_entry_ =
new (
Z) GraphEntryInstr(*parsed_function(),
B->osr_id_);
59 auto normal_entry =
B->BuildFunctionEntry(
B->graph_entry_);
60 B->graph_entry_->set_normal_entry(normal_entry);
62 Fragment body(normal_entry);
63 body +=
B->CheckStackOverflowInPrologue(field_helper.position_);
64 body += SetupCapturedParameters(parsed_function()->
function());
65 body += BuildExpression();
66 body += Return(TokenPosition::kNoSource);
68 PrologueInfo prologue_info(-1, -1);
69 if (
B->IsCompiledForOsr()) {
70 B->graph_entry_->RelinkToOsrEntry(
Z,
B->last_used_block_id_ + 1);
72 return new (
Z) FlowGraph(
73 *parsed_function(),
B->graph_entry_,
B->last_used_block_id_,
78void StreamingFlowGraphBuilder::SetupDefaultParameterValues() {
79 intptr_t optional_parameter_count =
81 if (optional_parameter_count > 0) {
82 ZoneGrowableArray<const Instance*>* default_values =
83 new ZoneGrowableArray<const Instance*>(
Z, optional_parameter_count);
85 AlternativeReadingScope alt(&
reader_);
87 function_node_helper.ReadUntilExcluding(
90 if (parsed_function()->
function().HasOptionalNamedParameters()) {
93 for (intptr_t
i = 0;
i < list_length; ++
i) {
99 ASSERT(optional_parameter_count == list_length);
100 ASSERT(!parsed_function()->
function().HasOptionalPositionalParameters());
101 for (intptr_t
i = 0;
i < list_length; ++
i) {
102 Instance* default_value;
108 if (tag == kSomething) {
115 default_values->Add(default_value);
120 ASSERT(list_length == function_node_helper.required_parameter_count_ +
121 optional_parameter_count);
122 ASSERT(parsed_function()->
function().HasOptionalPositionalParameters());
123 for (intptr_t
i = 0;
i < function_node_helper.required_parameter_count_;
127 for (intptr_t
i = 0;
i < optional_parameter_count; ++
i) {
128 Instance* default_value;
134 if (tag == kSomething) {
141 default_values->Add(default_value);
152Fragment StreamingFlowGraphBuilder::BuildFieldInitializer(
154 bool only_for_side_effects) {
156 if (
PeekTag() == kNullLiteral) {
158 if (
H.thread()->IsDartMutatorThread()) {
159 ASSERT(field.IsOriginal());
160 LeaveCompilerScope cs(
H.thread());
161 field.RecordStore(Object::null_object());
163 ASSERT(field.is_nullable_unsafe());
168 Fragment instructions;
169 if (!only_for_side_effects) {
170 instructions += LoadLocal(parsed_function()->receiver_var());
174 closure_owner_ = field.RawOwner();
175 instructions += BuildExpression();
177 if (only_for_side_effects) {
178 instructions += Drop();
186Fragment StreamingFlowGraphBuilder::BuildLateFieldInitializer(
188 bool has_initializer) {
189 if (has_initializer &&
PeekTag() == kNullLiteral) {
191 if (
H.thread()->IsDartMutatorThread()) {
192 LeaveCompilerScope cs(
H.thread());
193 field.RecordStore(Object::null_object());
195 ASSERT(field.is_nullable_unsafe());
200 Fragment instructions;
201 instructions += LoadLocal(parsed_function()->receiver_var());
202 instructions += flow_graph_builder_->
Constant(Object::sentinel());
203 instructions += flow_graph_builder_->
StoreField(
208Fragment StreamingFlowGraphBuilder::BuildInitializers(
209 const Class& parent_class) {
211 Fragment instructions;
214 intptr_t initializers_offset = -1;
216 AlternativeReadingScope alt(&
reader_);
221 bool is_redirecting_constructor =
false;
224 GrowableArray<const Field*> initializer_fields(5);
229 AlternativeReadingScope alt(&
reader_, initializers_offset);
231 const intptr_t list_length =
233 initializer_fields.EnsureLength(list_length,
nullptr);
235 bool has_field_initializers =
false;
236 for (intptr_t
i = 0;
i < list_length; ++
i) {
237 if (
PeekTag() == kRedirectingInitializer) {
238 is_redirecting_constructor =
true;
239 }
else if (
PeekTag() == kFieldInitializer) {
240 has_field_initializers =
true;
247 initializer_fields[
i] = &field;
253 ASSERT(!is_redirecting_constructor || !has_field_initializers);
264 if (!is_redirecting_constructor) {
269 GrowableArray<intptr_t> constructor_initialized_field_offsets(
270 initializer_fields.length());
271 for (
auto field : initializer_fields) {
272 if (field !=
nullptr) {
273 constructor_initialized_field_offsets.Add(field->kernel_offset());
277 constructor_initialized_field_offsets.Sort(
278 [](
const intptr_t*
a,
const intptr_t*
b) {
279 return static_cast<int>(*a) -
static_cast<int>(*b);
281 constructor_initialized_field_offsets.Add(-1);
286 intptr_t next_constructor_initialized_field_index = 0;
287 for (intptr_t
i = 0;
i < class_fields.Length(); ++
i) {
288 class_field ^= class_fields.At(
i);
289 if (!class_field.is_static()) {
290 const intptr_t field_offset = class_field.kernel_offset();
297 bool is_constructor_initialized =
false;
298 const intptr_t constructor_initialized_field_offset =
299 constructor_initialized_field_offsets
300 [next_constructor_initialized_field_index];
301 if (constructor_initialized_field_offset == field_offset) {
302 next_constructor_initialized_field_index++;
303 is_constructor_initialized =
true;
306 kernel_data = class_field.KernelLibrary();
307 ASSERT(!kernel_data.IsNull());
308 AlternativeReadingScopeWithNewData alt(&
reader_, &kernel_data,
313 if (class_field.is_late()) {
314 if (!is_constructor_initialized) {
315 instructions += BuildLateFieldInitializer(
317 initializer_tag == kSomething);
319 }
else if (initializer_tag == kSomething) {
320 EnterScope(field_offset);
324 instructions += BuildFieldInitializer(
326 is_constructor_initialized);
327 ExitScope(field_offset);
340 AlternativeReadingScope alt(&
reader_, initializers_offset);
342 for (intptr_t
i = 0;
i < list_length; ++
i) {
346 case kInvalidInitializer:
349 case kFieldInitializer: {
352 instructions += BuildFieldInitializer(
357 case kAssertInitializer: {
358 instructions += BuildStatement();
361 case kSuperInitializer: {
362 TokenPosition position = ReadPosition();
363 NameIndex canonical_target =
366 instructions += LoadLocal(parsed_function()->receiver_var());
371 instructions += BuildArguments(
376 Class& parent_klass = GetSuperOrDie();
379 Z,
H.LookupConstructorByKernelConstructor(
380 parent_klass,
H.CanonicalNameString(canonical_target)));
381 instructions += StaticCall(
382 isSynthetic ? TokenPosition::kNoSource : position,
target,
384 instructions += Drop();
387 case kRedirectingInitializer: {
388 TokenPosition position = ReadPosition();
389 NameIndex canonical_target =
392 instructions += LoadLocal(parsed_function()->receiver_var());
397 instructions += BuildArguments(
403 Z,
H.LookupConstructorByKernelConstructor(canonical_target));
404 instructions += StaticCall(
405 isSynthetic ? TokenPosition::kNoSource : position,
target,
407 instructions += Drop();
410 case kLocalInitializer: {
432 LocalVariable* variable =
438 ASSERT(!helper.IsConst());
440 if (tag != kSomething) {
444 instructions += BuildExpression();
445 instructions += StoreLocal(TokenPosition::kNoSource, variable);
446 instructions += Drop();
458Fragment StreamingFlowGraphBuilder::DebugStepCheckInPrologue(
459 const Function& dart_function,
460 TokenPosition position) {
461 if (!NeedsDebugStepCheck(dart_function, position)) {
467 const int parameter_count = dart_function.NumParameters();
468 TokenPosition check_pos = TokenPosition::kNoSource;
469 if (parameter_count > 0) {
470 const LocalVariable& parameter =
474 if (!check_pos.IsDebugPause()) {
476 check_pos = position;
477 ASSERT(check_pos.IsDebugPause());
480 return DebugStepCheck(check_pos);
483Fragment StreamingFlowGraphBuilder::TypeArgumentsHandling(
484 const Function& dart_function) {
485 Fragment prologue =
B->BuildDefaultTypeHandling(dart_function);
487 if (dart_function.IsClosureFunction() &&
488 dart_function.NumParentTypeArguments() > 0) {
493 if (dart_function.IsGeneric()) {
494 prologue += LoadLocal(fn_type_args);
496 prologue += LoadLocal(
closure);
497 prologue += LoadNativeField(Slot::Closure_function_type_arguments());
499 prologue += IntConstant(dart_function.NumParentTypeArguments());
501 prologue += IntConstant(dart_function.NumTypeArguments());
503 const auto& prepend_function =
504 flow_graph_builder_->PrependTypeArgumentsFunction();
506 prologue += StaticCall(TokenPosition::kNoSource, prepend_function, 4,
508 prologue += StoreLocal(TokenPosition::kNoSource, fn_type_args);
511 prologue += LoadLocal(
closure);
512 prologue += LoadNativeField(Slot::Closure_function_type_arguments());
513 prologue += StoreLocal(TokenPosition::kNoSource, fn_type_args);
521Fragment StreamingFlowGraphBuilder::CheckStackOverflowInPrologue(
522 const Function& dart_function) {
523 if (dart_function.is_native())
return {};
524 return B->CheckStackOverflowInPrologue(dart_function.token_pos());
527Fragment StreamingFlowGraphBuilder::SetupCapturedParameters(
528 const Function& dart_function) {
530 const LocalScope* scope = parsed_function()->
scope();
531 if (scope->num_context_variables() > 0) {
532 body += flow_graph_builder_->PushContext(scope);
533 LocalVariable* context = MakeTemporary();
536 LocalScope* scope = parsed_function()->
scope();
537 intptr_t parameter_count = dart_function.NumParameters();
538 const ParsedFunction& pf = *flow_graph_builder_->parsed_function_;
539 const Function&
function = pf.function();
541 for (intptr_t
i = 0;
i < parameter_count; ++
i) {
542 LocalVariable* variable = pf.ParameterVariable(
i);
543 if (variable->is_captured()) {
544 LocalVariable& raw_parameter = *pf.RawParameterVariable(
i);
546 raw_parameter.owner() == scope) ||
547 (!
function.MakesCopyOfParameters() &&
548 raw_parameter.owner() ==
nullptr));
549 ASSERT(!raw_parameter.is_captured());
552 body += LoadLocal(context);
553 body += LoadLocal(&raw_parameter);
564Fragment StreamingFlowGraphBuilder::InitSuspendableFunction(
565 const Function& dart_function,
566 const AbstractType* emitted_value_type) {
568 if (dart_function.IsAsyncFunction()) {
569 ASSERT(emitted_value_type !=
nullptr);
571 type_args.SetTypeAt(0, *emitted_value_type);
573 .GetInstanceTypeArguments(
H.thread(), type_args);
574 body += TranslateInstantiatedTypeArguments(type_args);
575 body +=
B->Call1ArgStub(TokenPosition::kNoSource,
578 }
else if (dart_function.IsAsyncGenerator()) {
579 ASSERT(emitted_value_type !=
nullptr);
581 type_args.SetTypeAt(0, *emitted_value_type);
583 .GetInstanceTypeArguments(
H.thread(), type_args);
584 body += TranslateInstantiatedTypeArguments(type_args);
585 body +=
B->Call1ArgStub(TokenPosition::kNoSource,
588 body += NullConstant();
589 body +=
B->Suspend(TokenPosition::kNoSource,
592 }
else if (dart_function.IsSyncGenerator()) {
593 ASSERT(emitted_value_type !=
nullptr);
595 type_args.SetTypeAt(0, *emitted_value_type);
597 .GetInstanceTypeArguments(
H.thread(), type_args);
598 body += TranslateInstantiatedTypeArguments(type_args);
599 body +=
B->Call1ArgStub(TokenPosition::kNoSource,
602 body += NullConstant();
603 body +=
B->Suspend(TokenPosition::kNoSource,
608 const LocalScope* scope = parsed_function()->
scope();
609 if (scope->num_context_variables() > 0) {
610 body += CloneContext(scope->context_slots());
613 ASSERT(emitted_value_type ==
nullptr);
618Fragment StreamingFlowGraphBuilder::ShortcutForUserDefinedEquals(
619 const Function& dart_function,
620 LocalVariable* first_parameter) {
633 if ((dart_function.NumParameters() == 2) &&
634 (dart_function.name() == Symbols::EqualOperator().ptr()) &&
635 (dart_function.Owner() !=
IG->object_store()->object_class())) {
636 TargetEntryInstr* null_entry;
637 TargetEntryInstr* non_null_entry;
639 body += LoadLocal(first_parameter);
640 body += BranchIfNull(&null_entry, &non_null_entry);
645 Fragment null_fragment(null_entry);
647 null_fragment += Return(dart_function.end_token_pos());
649 body = Fragment(body.entry, non_null_entry);
654Fragment StreamingFlowGraphBuilder::BuildFunctionBody(
655 const Function& dart_function,
656 LocalVariable* first_parameter,
664 body += BuildInitializers(
Class::Handle(
Z, dart_function.Owner()));
667 if (body.is_closed())
return body;
672 const bool has_body =
ReadTag() == kSomething;
674 if (dart_function.is_old_native()) {
675 body +=
B->NativeFunctionBody(dart_function, first_parameter);
676 }
else if (dart_function.is_ffi_native()) {
677 body +=
B->FfiNativeFunctionBody(dart_function);
678 }
else if (dart_function.is_external()) {
679 body += ThrowNoSuchMethodError(TokenPosition::kNoSource, dart_function,
681 body += ThrowException(TokenPosition::kNoSource);
682 }
else if (has_body) {
683 body += BuildStatement();
686 if (body.is_open()) {
687 if (parsed_function()->
function().IsSyncGenerator()) {
691 body += NullConstant();
693 body += Return(dart_function.end_token_pos());
699Fragment StreamingFlowGraphBuilder::BuildRegularFunctionPrologue(
700 const Function& dart_function,
701 TokenPosition token_position,
702 LocalVariable* first_parameter) {
704 F += CheckStackOverflowInPrologue(dart_function);
705 F += DebugStepCheckInPrologue(dart_function, token_position);
706 F +=
B->InitConstantParameters();
707 F += SetupCapturedParameters(dart_function);
708 F += ShortcutForUserDefinedEquals(dart_function, first_parameter);
712Fragment StreamingFlowGraphBuilder::ClearRawParameters(
713 const Function& dart_function) {
714 const ParsedFunction& pf = *flow_graph_builder_->parsed_function_;
716 for (intptr_t
i = 0;
i < dart_function.NumParameters(); ++
i) {
717 LocalVariable* variable = pf.ParameterVariable(
i);
719 if (!variable->is_captured())
continue;
723 if (pf.function().HasThisParameter() && pf.has_receiver_var() &&
724 variable == pf.receiver_var()) {
729 variable = pf.RawParameterVariable(
i);
730 code += NullConstant();
731 code += StoreLocal(TokenPosition::kNoSource, variable);
738 const Function& dart_function,
739 const Fragment& implicit_type_checks,
740 const Fragment& regular_function_prologue,
741 const Fragment& type_args_handling) {
742 ASSERT(!dart_function.IsImplicitClosureFunction());
743 if (!dart_function.MayHaveUncheckedEntryPoint() ||
744 implicit_type_checks.is_empty()) {
757 !type_args_handling.is_empty()) {
760 Instruction* instr = regular_function_prologue.entry;
761 if (instr !=
nullptr && instr->IsCheckStackOverflow()) {
762 instr = instr->next();
764 if (instr !=
nullptr && instr->IsDebugStepCheck()) {
765 instr = instr->next();
767 if (instr !=
nullptr) {
774FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfFunction(
775 bool is_constructor) {
776 const Function& dart_function = parsed_function()->
function();
778 LocalVariable* first_parameter =
nullptr;
779 TokenPosition token_position = TokenPosition::kNoSource;
780 const AbstractType* emitted_value_type =
nullptr;
782 AlternativeReadingScope alt(&
reader_);
784 function_node_helper.ReadUntilExcluding(
787 AlternativeReadingScope alt2(&
reader_);
789 if (list_length > 0) {
791 first_parameter = LookupVariable(first_parameter_offset);
794 token_position = function_node_helper.position_;
795 if (dart_function.IsSuspendableFunction()) {
796 function_node_helper.ReadUntilExcluding(
799 emitted_value_type = &
T.BuildType();
806 auto graph_entry = flow_graph_builder_->graph_entry_ =
807 new (
Z) GraphEntryInstr(*parsed_function(), flow_graph_builder_->
osr_id_);
810 graph_entry->set_normal_entry(normal_entry);
812 PrologueInfo prologue_info(-1, -1);
813 BlockEntryInstr* instruction_cursor =
814 flow_graph_builder_->BuildPrologue(normal_entry, &prologue_info);
816 const Fragment regular_prologue = BuildRegularFunctionPrologue(
817 dart_function, token_position, first_parameter);
822 const Fragment type_args_handling = TypeArgumentsHandling(dart_function);
824 Fragment implicit_type_checks;
825 if (dart_function.NeedsTypeArgumentTypeChecks()) {
826 B->BuildTypeArgumentTypeChecks(
828 &implicit_type_checks);
831 Fragment explicit_type_checks;
832 Fragment implicit_redefinitions;
833 if (dart_function.NeedsArgumentTypeChecks()) {
834 B->BuildArgumentTypeChecks(&explicit_type_checks, &implicit_type_checks,
835 &implicit_redefinitions);
840 const Fragment body =
841 ClearRawParameters(dart_function) +
842 InitSuspendableFunction(dart_function, emitted_value_type) +
843 BuildFunctionBody(dart_function, first_parameter, is_constructor);
845 auto extra_entry_point_style =
846 ChooseEntryPointStyle(dart_function, implicit_type_checks,
847 regular_prologue, type_args_handling);
849 Fragment
function(instruction_cursor);
850 FunctionEntryInstr* extra_entry =
nullptr;
851 switch (extra_entry_point_style) {
853 function += regular_prologue + type_args_handling + implicit_type_checks +
854 explicit_type_checks + body;
858 ASSERT(instruction_cursor == normal_entry);
859 ASSERT(type_args_handling.is_empty());
861 const Fragment prologue_copy = BuildRegularFunctionPrologue(
862 dart_function, token_position, first_parameter);
864 extra_entry =
B->BuildSeparateUncheckedEntryPoint(
866 regular_prologue + implicit_type_checks,
868 explicit_type_checks,
873 Fragment prologue(normal_entry, instruction_cursor);
874 prologue += regular_prologue;
875 prologue += type_args_handling;
876 prologue += explicit_type_checks;
877 extra_entry =
B->BuildSharedUncheckedEntryPoint(
879 implicit_type_checks,
880 implicit_redefinitions,
885 if (extra_entry !=
nullptr) {
886 B->RecordUncheckedEntryPoint(graph_entry, extra_entry);
894 graph_entry->RelinkToOsrEntry(
Z,
897 return new (
Z) FlowGraph(
905 ASSERT(flow_graph_builder_ !=
nullptr);
922 ParseKernelASTFunction();
925 case UntaggedFunction::kRegularFunction:
926 case UntaggedFunction::kGetterFunction:
927 case UntaggedFunction::kSetterFunction:
928 case UntaggedFunction::kClosureFunction:
929 case UntaggedFunction::kConstructor: {
931 return B->BuildGraphOfRecognizedMethod(
function);
933 return BuildGraphOfFunction(
function.IsGenerativeConstructor());
935 case UntaggedFunction::kImplicitGetter:
936 case UntaggedFunction::kImplicitStaticGetter:
937 case UntaggedFunction::kImplicitSetter: {
938 return B->BuildGraphOfFieldAccessor(
function);
940 case UntaggedFunction::kFieldInitializer:
941 return BuildGraphOfFieldInitializer();
942 case UntaggedFunction::kDynamicInvocationForwarder:
943 return B->BuildGraphOfDynamicInvocationForwarder(
function);
944 case UntaggedFunction::kMethodExtractor:
945 return flow_graph_builder_->BuildGraphOfMethodExtractor(
function);
946 case UntaggedFunction::kNoSuchMethodDispatcher:
947 return flow_graph_builder_->BuildGraphOfNoSuchMethodDispatcher(
function);
948 case UntaggedFunction::kInvokeFieldDispatcher:
949 return flow_graph_builder_->BuildGraphOfInvokeFieldDispatcher(
function);
950 case UntaggedFunction::kImplicitClosureFunction:
951 return flow_graph_builder_->BuildGraphOfImplicitClosureFunction(
function);
952 case UntaggedFunction::kFfiTrampoline:
953 return flow_graph_builder_->BuildGraphOfFfiTrampoline(
function);
954 case UntaggedFunction::kRecordFieldGetter:
955 return flow_graph_builder_->BuildGraphOfRecordFieldGetter(
function);
956 case UntaggedFunction::kIrregexpFunction:
963void StreamingFlowGraphBuilder::ParseKernelASTFunction() {
966 const intptr_t kernel_offset =
function.kernel_offset();
967 ASSERT(kernel_offset >= 0);
973 case UntaggedFunction::kRegularFunction:
974 case UntaggedFunction::kImplicitClosureFunction:
975 case UntaggedFunction::kGetterFunction:
976 case UntaggedFunction::kSetterFunction:
977 case UntaggedFunction::kClosureFunction:
978 case UntaggedFunction::kConstructor:
979 case UntaggedFunction::kDynamicInvocationForwarder:
986 set_scopes(parsed_function()->EnsureKernelScopes());
989 case UntaggedFunction::kRegularFunction:
990 case UntaggedFunction::kGetterFunction:
991 case UntaggedFunction::kSetterFunction:
992 case UntaggedFunction::kClosureFunction:
993 case UntaggedFunction::kConstructor:
994 case UntaggedFunction::kImplicitClosureFunction:
996 SetupDefaultParameterValues();
998 case UntaggedFunction::kImplicitGetter:
999 case UntaggedFunction::kImplicitStaticGetter:
1000 case UntaggedFunction::kImplicitSetter:
1001 case UntaggedFunction::kFieldInitializer:
1002 case UntaggedFunction::kMethodExtractor:
1003 case UntaggedFunction::kNoSuchMethodDispatcher:
1004 case UntaggedFunction::kInvokeFieldDispatcher:
1005 case UntaggedFunction::kFfiTrampoline:
1006 case UntaggedFunction::kRecordFieldGetter:
1008 case UntaggedFunction::kDynamicInvocationForwarder:
1011 SetupDefaultParameterValues();
1014 case UntaggedFunction::kIrregexpFunction:
1020void StreamingFlowGraphBuilder::ReadForwardingStubTarget(
1022 if (
PeekTag() == kProcedure) {
1023 AlternativeReadingScope alt(&
reader_);
1026 if (procedure_helper.IsForwardingStub() && !procedure_helper.IsAbstract()) {
1027 const NameIndex target_name =
1028 procedure_helper.concrete_forwarding_stub_target_;
1031 ?
H.DartSetterName(target_name)
1032 :
H.DartProcedureName(target_name);
1033 const Function* forwarding_target =
1035 ASSERT(!forwarding_target->IsNull());
1043 return BuildStatement();
1048 uint8_t payload = 0;
1051 case kInvalidExpression:
1052 return BuildInvalidExpression(position);
1054 return BuildVariableGet(position);
1055 case kSpecializedVariableGet:
1056 return BuildVariableGet(payload, position);
1058 return BuildVariableSet(position);
1059 case kSpecializedVariableSet:
1060 return BuildVariableSet(payload, position);
1062 return BuildInstanceGet(position);
1064 return BuildDynamicGet(position);
1065 case kInstanceTearOff:
1066 return BuildInstanceTearOff(position);
1067 case kFunctionTearOff:
1072 return BuildInstanceSet(position);
1074 return BuildDynamicSet(position);
1075 case kAbstractSuperPropertyGet:
1080 case kAbstractSuperPropertySet:
1085 case kSuperPropertyGet:
1086 return BuildSuperPropertyGet(position);
1087 case kSuperPropertySet:
1088 return BuildSuperPropertySet(position);
1090 return BuildStaticGet(position);
1092 return BuildStaticSet(position);
1093 case kInstanceInvocation:
1094 return BuildMethodInvocation(position,
false);
1095 case kDynamicInvocation:
1096 return BuildMethodInvocation(position,
true);
1097 case kLocalFunctionInvocation:
1098 return BuildLocalFunctionInvocation(position);
1099 case kFunctionInvocation:
1100 return BuildFunctionInvocation(position);
1102 return BuildEqualsCall(position);
1104 return BuildEqualsNull(position);
1105 case kAbstractSuperMethodInvocation:
1110 case kSuperMethodInvocation:
1111 return BuildSuperMethodInvocation(position);
1112 case kStaticInvocation:
1113 return BuildStaticInvocation(position);
1114 case kConstructorInvocation:
1115 return BuildConstructorInvocation(position);
1117 return BuildNot(position);
1119 return BuildNullCheck(position);
1120 case kLogicalExpression:
1121 return BuildLogicalExpression(position);
1122 case kConditionalExpression:
1123 return BuildConditionalExpression(position);
1124 case kStringConcatenation:
1125 return BuildStringConcatenation(position);
1127 return BuildIsExpression(position);
1129 return BuildAsExpression(position);
1131 return BuildTypeLiteral(position);
1132 case kThisExpression:
1133 return BuildThisExpression(position);
1135 return BuildRethrow(position);
1137 return BuildThrow(position);
1139 return BuildListLiteral(position);
1146 return BuildMapLiteral(position);
1147 case kRecordLiteral:
1148 return BuildRecordLiteral(position);
1149 case kRecordIndexGet:
1150 return BuildRecordFieldGet(position,
false);
1151 case kRecordNameGet:
1152 return BuildRecordFieldGet(position,
true);
1153 case kFunctionExpression:
1154 return BuildFunctionExpression();
1156 return BuildLet(position);
1157 case kBlockExpression:
1158 return BuildBlockExpression();
1159 case kBigIntLiteral:
1160 return BuildBigIntLiteral(position);
1161 case kStringLiteral:
1162 return BuildStringLiteral(position);
1163 case kSpecializedIntLiteral:
1164 return BuildIntLiteral(payload, position);
1165 case kNegativeIntLiteral:
1166 return BuildIntLiteral(
true, position);
1167 case kPositiveIntLiteral:
1168 return BuildIntLiteral(
false, position);
1169 case kDoubleLiteral:
1170 return BuildDoubleLiteral(position);
1172 return BuildBoolLiteral(
true, position);
1174 return BuildBoolLiteral(
false, position);
1176 return BuildNullLiteral(position);
1177 case kConstantExpression:
1178 case kFileUriConstantExpression:
1179 return BuildConstantExpression(position, tag);
1180 case kInstantiation:
1181 return BuildPartialTearoffInstantiation(position);
1184 case kCheckLibraryIsLoaded:
1185 return BuildLibraryPrefixAction(position, Symbols::CheckLoaded());
1186 case kAwaitExpression:
1187 return BuildAwaitExpression(position);
1188 case kFileUriExpression:
1189 return BuildFileUriExpression(position);
1190 case kConstStaticInvocation:
1191 case kConstConstructorInvocation:
1192 case kConstListLiteral:
1193 case kConstSetLiteral:
1194 case kConstMapLiteral:
1195 case kSymbolLiteral:
1196 case kListConcatenation:
1197 case kSetConcatenation:
1198 case kMapConcatenation:
1199 case kInstanceCreation:
1200 case kStaticTearOff:
1201 case kSwitchExpression:
1202 case kPatternAssignment:
1213Fragment StreamingFlowGraphBuilder::BuildStatement(TokenPosition* position) {
1217 case kExpressionStatement:
1218 return BuildExpressionStatement(position);
1220 return BuildBlock(position);
1221 case kEmptyStatement:
1222 return BuildEmptyStatement();
1224 return BuildAssertBlock(position);
1225 case kAssertStatement:
1226 return BuildAssertStatement(position);
1227 case kLabeledStatement:
1228 return BuildLabeledStatement(position);
1229 case kBreakStatement:
1230 return BuildBreakStatement(position);
1231 case kWhileStatement:
1232 return BuildWhileStatement(position);
1234 return BuildDoStatement(position);
1236 return BuildForStatement(position);
1237 case kSwitchStatement:
1238 return BuildSwitchStatement(position);
1239 case kContinueSwitchStatement:
1240 return BuildContinueSwitchStatement(position);
1242 return BuildIfStatement(position);
1243 case kReturnStatement:
1244 return BuildReturnStatement(position);
1246 return BuildTryCatch(position);
1248 return BuildTryFinally(position);
1249 case kYieldStatement:
1250 return BuildYieldStatement(position);
1251 case kVariableDeclaration:
1252 return BuildVariableDeclaration(position);
1253 case kFunctionDeclaration:
1254 return BuildFunctionDeclaration(position);
1255 case kForInStatement:
1256 case kAsyncForInStatement:
1257 case kIfCaseStatement:
1258 case kPatternSwitchStatement:
1259 case kPatternVariableDeclaration:
1269Fragment StreamingFlowGraphBuilder::BuildStatementWithBranchCoverage(
1270 TokenPosition* position) {
1271 TokenPosition
pos = TokenPosition::kNoSource;
1272 Fragment statement = BuildStatement(&
pos);
1273 if (position !=
nullptr) *position =
pos;
1275 covered_statement += statement;
1276 return covered_statement;
1281 if ((flow_graph_builder_ ==
nullptr) || (parsed_function() ==
nullptr)) {
1285 H.ReportError(
script, TokenPosition::kNoSource,
1286 "Unexpected tag %d (%s) in %s, expected %s", tag,
1288 parsed_function()->
function().ToQualifiedCString(), variant);
1308void StreamingFlowGraphBuilder::loop_depth_inc() {
1309 ++flow_graph_builder_->loop_depth_;
1312void StreamingFlowGraphBuilder::loop_depth_dec() {
1313 --flow_graph_builder_->loop_depth_;
1316void StreamingFlowGraphBuilder::catch_depth_inc() {
1317 ++flow_graph_builder_->catch_depth_;
1320void StreamingFlowGraphBuilder::catch_depth_dec() {
1321 --flow_graph_builder_->catch_depth_;
1324void StreamingFlowGraphBuilder::try_depth_inc() {
1325 ++flow_graph_builder_->try_depth_;
1328void StreamingFlowGraphBuilder::try_depth_dec() {
1329 --flow_graph_builder_->try_depth_;
1332intptr_t StreamingFlowGraphBuilder::block_expression_depth() {
1333 return flow_graph_builder_->block_expression_depth_;
1336void StreamingFlowGraphBuilder::block_expression_depth_inc() {
1337 ++flow_graph_builder_->block_expression_depth_;
1340void StreamingFlowGraphBuilder::block_expression_depth_dec() {
1341 --flow_graph_builder_->block_expression_depth_;
1344void StreamingFlowGraphBuilder::synthetic_error_handler_depth_inc() {
1345 ++synthetic_error_handler_depth_;
1348void StreamingFlowGraphBuilder::synthetic_error_handler_depth_dec() {
1349 --synthetic_error_handler_depth_;
1352intptr_t StreamingFlowGraphBuilder::CurrentTryIndex() {
1356intptr_t StreamingFlowGraphBuilder::AllocateTryIndex() {
1360LocalVariable* StreamingFlowGraphBuilder::CurrentException() {
1361 return flow_graph_builder_->CurrentException();
1364LocalVariable* StreamingFlowGraphBuilder::CurrentStackTrace() {
1365 return flow_graph_builder_->CurrentStackTrace();
1368CatchBlock* StreamingFlowGraphBuilder::catch_block() {
1369 return flow_graph_builder_->catch_block_;
1372ActiveClass* StreamingFlowGraphBuilder::active_class() {
1373 return active_class_;
1376ScopeBuildingResult* StreamingFlowGraphBuilder::scopes() {
1377 return flow_graph_builder_->scopes_;
1380void StreamingFlowGraphBuilder::set_scopes(ScopeBuildingResult* scope) {
1381 flow_graph_builder_->scopes_ = scope;
1384ParsedFunction* StreamingFlowGraphBuilder::parsed_function() {
1385 return flow_graph_builder_->parsed_function_;
1388TryFinallyBlock* StreamingFlowGraphBuilder::try_finally_block() {
1389 return flow_graph_builder_->try_finally_block_;
1392SwitchBlock* StreamingFlowGraphBuilder::switch_block() {
1393 return flow_graph_builder_->switch_block_;
1396BreakableBlock* StreamingFlowGraphBuilder::breakable_block() {
1397 return flow_graph_builder_->breakable_block_;
1400Value* StreamingFlowGraphBuilder::stack() {
1401 return flow_graph_builder_->
stack_;
1404void StreamingFlowGraphBuilder::set_stack(
Value* top) {
1405 flow_graph_builder_->
stack_ = top;
1408void StreamingFlowGraphBuilder::Push(Definition* definition) {
1409 flow_graph_builder_->
Push(definition);
1412Value* StreamingFlowGraphBuilder::Pop() {
1413 return flow_graph_builder_->
Pop();
1416Tag StreamingFlowGraphBuilder::PeekArgumentsFirstPositionalTag() {
1418 AlternativeReadingScope alt(&
reader_);
1425 if (list_length > 0) {
1433const TypeArguments& StreamingFlowGraphBuilder::PeekArgumentsInstantiatedType(
1434 const Class& klass) {
1436 AlternativeReadingScope alt(&
reader_);
1439 return T.BuildInstantiatedTypeArguments(klass, list_length);
1442intptr_t StreamingFlowGraphBuilder::PeekArgumentsCount() {
1446TokenPosition StreamingFlowGraphBuilder::ReadPosition() {
1448 if (synthetic_error_handler_depth_ > 0 && position.IsReal()) {
1454LocalVariable* StreamingFlowGraphBuilder::LookupVariable(
1455 intptr_t kernel_offset) {
1456 return flow_graph_builder_->LookupVariable(kernel_offset);
1459LocalVariable* StreamingFlowGraphBuilder::MakeTemporary(
const char*
suffix) {
1463Fragment StreamingFlowGraphBuilder::DropTemporary(LocalVariable** variable) {
1467Function& StreamingFlowGraphBuilder::FindMatchingFunction(
1472 const Array& argument_names) {
1474 ArgumentsDescriptor args_desc(
1482bool StreamingFlowGraphBuilder::NeedsDebugStepCheck(
const Function&
function,
1483 TokenPosition position) {
1484 return flow_graph_builder_->NeedsDebugStepCheck(
function, position);
1487bool StreamingFlowGraphBuilder::NeedsDebugStepCheck(
Value*
value,
1488 TokenPosition position) {
1489 return flow_graph_builder_->NeedsDebugStepCheck(
value, position);
1492void StreamingFlowGraphBuilder::InlineBailout(
const char* reason) {
1496Fragment StreamingFlowGraphBuilder::DebugStepCheck(TokenPosition position) {
1500Fragment StreamingFlowGraphBuilder::LoadLocal(LocalVariable* variable) {
1501 return flow_graph_builder_->LoadLocal(variable);
1504IndirectGotoInstr* StreamingFlowGraphBuilder::IndirectGoto(
1505 intptr_t target_count) {
1506 return flow_graph_builder_->IndirectGoto(target_count);
1509Fragment StreamingFlowGraphBuilder::Return(TokenPosition position) {
1510 return flow_graph_builder_->Return(position,
1514Fragment StreamingFlowGraphBuilder::EvaluateAssertion() {
1515 return flow_graph_builder_->EvaluateAssertion();
1518Fragment StreamingFlowGraphBuilder::RethrowException(TokenPosition position,
1519 int catch_try_index) {
1520 return flow_graph_builder_->RethrowException(position, catch_try_index);
1523Fragment StreamingFlowGraphBuilder::ThrowNoSuchMethodError(
1524 TokenPosition position,
1526 bool incompatible_arguments) {
1527 return flow_graph_builder_->ThrowNoSuchMethodError(position,
target,
1528 incompatible_arguments);
1531Fragment StreamingFlowGraphBuilder::Constant(
const Object&
value) {
1535Fragment StreamingFlowGraphBuilder::IntConstant(int64_t
value) {
1539Fragment StreamingFlowGraphBuilder::LoadStaticField(
const Field& field,
1540 bool calls_initializer) {
1541 return flow_graph_builder_->
LoadStaticField(field, calls_initializer);
1544Fragment StreamingFlowGraphBuilder::RedefinitionWithType(
1545 const AbstractType&
type) {
1549Fragment StreamingFlowGraphBuilder::CheckNull(TokenPosition position,
1550 LocalVariable* receiver,
1555Fragment StreamingFlowGraphBuilder::StaticCall(TokenPosition position,
1560 Fragment instructions;
1562 instructions += ThrowNoSuchMethodError(position,
target,
1564 return instructions;
1570Fragment StreamingFlowGraphBuilder::StaticCall(
1571 TokenPosition position,
1574 const Array& argument_names,
1576 const InferredTypeMetadata* result_type,
1577 intptr_t type_args_count,
1578 bool use_unchecked_entry) {
1581 Fragment instructions;
1583 instructions += ThrowNoSuchMethodError(position,
target,
1585 return instructions;
1587 return flow_graph_builder_->StaticCall(
1589 result_type, type_args_count, use_unchecked_entry);
1592Fragment StreamingFlowGraphBuilder::StaticCallMissing(
1593 TokenPosition position,
1594 const String& selector,
1598 Fragment instructions;
1600 instructions += flow_graph_builder_->ThrowNoSuchMethodError(
1601 position, selector,
level, kind);
1602 return instructions;
1605Fragment StreamingFlowGraphBuilder::InstanceCall(
1606 TokenPosition position,
1610 intptr_t checked_argument_count) {
1611 const intptr_t kTypeArgsLen = 0;
1612 return flow_graph_builder_->InstanceCall(position,
name, kind, kTypeArgsLen,
1614 checked_argument_count);
1617Fragment StreamingFlowGraphBuilder::InstanceCall(
1618 TokenPosition position,
1621 intptr_t type_args_len,
1623 const Array& argument_names,
1624 intptr_t checked_argument_count,
1625 const Function& interface_target,
1626 const Function& tearoff_interface_target,
1627 const InferredTypeMetadata* result_type,
1628 bool use_unchecked_entry,
1629 const CallSiteAttributesMetadata* call_site_attrs,
1630 bool receiver_is_not_smi,
1631 bool is_call_on_this) {
1632 return flow_graph_builder_->InstanceCall(
1634 checked_argument_count, interface_target, tearoff_interface_target,
1635 result_type, use_unchecked_entry, call_site_attrs, receiver_is_not_smi,
1639Fragment StreamingFlowGraphBuilder::ThrowException(TokenPosition position) {
1643Fragment StreamingFlowGraphBuilder::BooleanNegate() {
1647Fragment StreamingFlowGraphBuilder::TranslateInstantiatedTypeArguments(
1648 const TypeArguments& type_arguments) {
1649 return flow_graph_builder_->TranslateInstantiatedTypeArguments(
1653Fragment StreamingFlowGraphBuilder::StrictCompare(TokenPosition position,
1655 bool number_check) {
1656 return flow_graph_builder_->
StrictCompare(position, kind, number_check);
1659Fragment StreamingFlowGraphBuilder::AllocateObject(TokenPosition position,
1665Fragment StreamingFlowGraphBuilder::AllocateContext(
1666 const ZoneGrowableArray<const Slot*>& context_slots) {
1670Fragment StreamingFlowGraphBuilder::LoadNativeField(
1673 return flow_graph_builder_->
LoadNativeField(field, loads_inner_pointer);
1676Fragment StreamingFlowGraphBuilder::StoreLocal(TokenPosition position,
1677 LocalVariable* variable) {
1678 return flow_graph_builder_->
StoreLocal(position, variable);
1681Fragment StreamingFlowGraphBuilder::StoreStaticField(TokenPosition position,
1682 const Field& field) {
1686Fragment StreamingFlowGraphBuilder::StringInterpolate(TokenPosition position) {
1687 return flow_graph_builder_->StringInterpolate(position);
1690Fragment StreamingFlowGraphBuilder::StringInterpolateSingle(
1691 TokenPosition position) {
1692 return flow_graph_builder_->StringInterpolateSingle(position);
1695Fragment StreamingFlowGraphBuilder::ThrowTypeError() {
1696 return flow_graph_builder_->ThrowTypeError();
1699Fragment StreamingFlowGraphBuilder::LoadInstantiatorTypeArguments() {
1700 return flow_graph_builder_->LoadInstantiatorTypeArguments();
1703Fragment StreamingFlowGraphBuilder::LoadFunctionTypeArguments() {
1704 return flow_graph_builder_->LoadFunctionTypeArguments();
1707Fragment StreamingFlowGraphBuilder::InstantiateType(
const AbstractType&
type) {
1711Fragment StreamingFlowGraphBuilder::CreateArray() {
1715Fragment StreamingFlowGraphBuilder::StoreIndexed(intptr_t class_id) {
1719Fragment StreamingFlowGraphBuilder::CheckStackOverflow(TokenPosition position) {
1722 flow_graph_builder_->loop_depth_);
1725Fragment StreamingFlowGraphBuilder::CloneContext(
1726 const ZoneGrowableArray<const Slot*>& context_slots) {
1727 return flow_graph_builder_->CloneContext(context_slots);
1730Fragment StreamingFlowGraphBuilder::TranslateFinallyFinalizers(
1731 TryFinallyBlock* outer_finally,
1732 intptr_t target_context_depth) {
1735 AlternativeReadingScope alt(&
reader_);
1738 TryFinallyBlock*
const saved_finally_block =
B->try_finally_block_;
1739 TryCatchBlock*
const saved_try_catch_block =
B->CurrentTryCatchBlock();
1740 const intptr_t saved_context_depth =
B->context_depth_;
1741 const ProgramState
state(
B->breakable_block_,
B->switch_block_,
1742 B->loop_depth_,
B->try_depth_,
B->catch_depth_,
1743 B->block_expression_depth_);
1745 Fragment instructions;
1749 while (
B->try_finally_block_ != outer_finally) {
1750 ASSERT(
B->try_finally_block_ !=
nullptr);
1752 B->try_finally_block_->state().assignTo(
B);
1756 instructions +=
B->AdjustContextTo(
B->try_finally_block_->context_depth());
1760 bool changed_try_index =
false;
1761 intptr_t target_try_index =
B->try_finally_block_->try_index();
1762 while (
B->CurrentTryIndex() != target_try_index) {
1763 B->SetCurrentTryCatchBlock(
B->CurrentTryCatchBlock()->outer());
1764 changed_try_index =
true;
1766 if (changed_try_index) {
1767 JoinEntryInstr* entry = BuildJoinEntry();
1768 instructions += Goto(entry);
1769 instructions = Fragment(instructions.entry, entry);
1772 intptr_t finalizer_kernel_offset =
1773 B->try_finally_block_->finalizer_kernel_offset();
1774 B->try_finally_block_ =
B->try_finally_block_->outer();
1779 if (!instructions.is_open())
break;
1782 if (instructions.is_open() && target_context_depth != -1) {
1786 instructions +=
B->AdjustContextTo(target_context_depth);
1790 B->try_finally_block_ = saved_finally_block;
1791 B->SetCurrentTryCatchBlock(saved_try_catch_block);
1792 B->context_depth_ = saved_context_depth;
1795 return instructions;
1798Fragment StreamingFlowGraphBuilder::BranchIfTrue(
1799 TargetEntryInstr** then_entry,
1800 TargetEntryInstr** otherwise_entry,
1802 return flow_graph_builder_->
BranchIfTrue(then_entry, otherwise_entry, negate);
1805Fragment StreamingFlowGraphBuilder::BranchIfEqual(
1806 TargetEntryInstr** then_entry,
1807 TargetEntryInstr** otherwise_entry,
1809 return flow_graph_builder_->
BranchIfEqual(then_entry, otherwise_entry,
1813Fragment StreamingFlowGraphBuilder::BranchIfNull(
1814 TargetEntryInstr** then_entry,
1815 TargetEntryInstr** otherwise_entry,
1817 return flow_graph_builder_->
BranchIfNull(then_entry, otherwise_entry, negate);
1820Fragment StreamingFlowGraphBuilder::CatchBlockEntry(
const Array& handler_types,
1821 intptr_t handler_index,
1822 bool needs_stacktrace,
1823 bool is_synthesized) {
1824 return flow_graph_builder_->CatchBlockEntry(handler_types, handler_index,
1825 needs_stacktrace, is_synthesized);
1828Fragment StreamingFlowGraphBuilder::TryCatch(
int try_handler_index) {
1829 return flow_graph_builder_->TryCatch(try_handler_index);
1832Fragment StreamingFlowGraphBuilder::Drop() {
1833 return flow_graph_builder_->
Drop();
1836Fragment StreamingFlowGraphBuilder::DropArguments(intptr_t
argument_count,
1837 intptr_t type_args_count) {
1838 Fragment instructions;
1840 instructions += Drop();
1842 if (type_args_count != 0) {
1843 instructions += Drop();
1845 return instructions;
1848Fragment StreamingFlowGraphBuilder::DropTempsPreserveTop(
1849 intptr_t num_temps_to_drop) {
1853Fragment StreamingFlowGraphBuilder::MakeTemp() {
1854 return flow_graph_builder_->
MakeTemp();
1857Fragment StreamingFlowGraphBuilder::NullConstant() {
1861JoinEntryInstr* StreamingFlowGraphBuilder::BuildJoinEntry() {
1865JoinEntryInstr* StreamingFlowGraphBuilder::BuildJoinEntry(intptr_t try_index) {
1869Fragment StreamingFlowGraphBuilder::Goto(JoinEntryInstr* destination) {
1870 return flow_graph_builder_->
Goto(destination);
1873Fragment StreamingFlowGraphBuilder::CheckBoolean(TokenPosition position) {
1874 return flow_graph_builder_->CheckBoolean(position);
1877Fragment StreamingFlowGraphBuilder::CheckArgumentType(
1878 LocalVariable* variable,
1879 const AbstractType&
type) {
1880 return flow_graph_builder_->CheckAssignable(
1881 type, variable->name(), AssertAssignableInstr::kParameterCheck);
1884Fragment StreamingFlowGraphBuilder::RecordCoverage(TokenPosition position) {
1888Fragment StreamingFlowGraphBuilder::EnterScope(
1889 intptr_t kernel_offset,
1890 const LocalScope** scope ) {
1891 return flow_graph_builder_->EnterScope(kernel_offset, scope);
1894Fragment StreamingFlowGraphBuilder::ExitScope(intptr_t kernel_offset) {
1895 return flow_graph_builder_->ExitScope(kernel_offset);
1898TestFragment StreamingFlowGraphBuilder::TranslateConditionForControl() {
1900 bool negate =
false;
1908 if (
PeekTag() == kLogicalExpression) {
1914 TestFragment
left = TranslateConditionForControl();
1916 TestFragment
right = TranslateConditionForControl();
1920 left.CreateTrueSuccessor(flow_graph_builder_)->LinkTo(
right.entry);
1921 result.true_successor_addresses =
right.true_successor_addresses;
1922 result.false_successor_addresses =
left.false_successor_addresses;
1923 result.false_successor_addresses->AddArray(
1924 *
right.false_successor_addresses);
1927 left.CreateFalseSuccessor(flow_graph_builder_)->LinkTo(
right.entry);
1928 result.true_successor_addresses =
left.true_successor_addresses;
1929 result.true_successor_addresses->AddArray(
1930 *
right.true_successor_addresses);
1931 result.false_successor_addresses =
right.false_successor_addresses;
1935 TokenPosition position = TokenPosition::kNoSource;
1936 Fragment instructions = BuildExpression(&position);
1941 BranchInstr* branch;
1942 if (stack()->definition()->IsStrictCompare() &&
1943 stack()->definition() == instructions.current) {
1951 branch->comparison()->ClearTempIndex();
1952 ASSERT(instructions.current->previous() !=
nullptr);
1953 instructions.current = instructions.current->previous();
1955 if (NeedsDebugStepCheck(stack(), position)) {
1956 instructions = DebugStepCheck(position) + instructions;
1958 instructions += CheckBoolean(position);
1960 Value* right_value = Pop();
1961 Value* left_value = Pop();
1962 StrictCompareInstr*
compare =
new (
Z) StrictCompareInstr(
1963 InstructionSource(), negate ? Token::kNE_STRICT : Token::kEQ_STRICT,
1964 left_value, right_value,
false,
1970 instructions <<= branch;
1972 result = TestFragment(instructions.entry, branch);
1975 return result.Negate(negate);
1978const TypeArguments& StreamingFlowGraphBuilder::BuildTypeArguments() {
1981 return T.BuildTypeArguments(type_count);
1984Fragment StreamingFlowGraphBuilder::BuildArguments(Array* argument_names,
1986 intptr_t* positional_count) {
1995 AlternativeReadingScope _(&
reader_);
1996 if (positional_count ==
nullptr) positional_count = &dummy;
1999 return BuildArgumentsFromActualArguments(argument_names);
2002Fragment StreamingFlowGraphBuilder::BuildArgumentsFromActualArguments(
2003 Array* argument_names) {
2004 Fragment instructions;
2008 for (intptr_t
i = 0;
i < list_length; ++
i) {
2009 instructions += BuildExpression();
2014 if (argument_names !=
nullptr && list_length > 0) {
2017 for (intptr_t
i = 0;
i < list_length; ++
i) {
2020 instructions += BuildExpression();
2021 if (argument_names !=
nullptr) {
2022 argument_names->SetAt(
i,
name);
2026 return instructions;
2029Fragment StreamingFlowGraphBuilder::BuildInvalidExpression(
2030 TokenPosition* position) {
2034 TokenPosition
pos = ReadPosition();
2035 if (position !=
nullptr) *position =
pos;
2038 if (tag == kSomething) {
2045 H.ReportError(
script, TokenPosition::kNoSource,
"%s",
message.ToCString());
2049Fragment StreamingFlowGraphBuilder::BuildVariableGet(TokenPosition* position) {
2050 const TokenPosition
pos = ReadPosition();
2051 if (position !=
nullptr) *position =
pos;
2052 intptr_t variable_kernel_position =
ReadUInt();
2055 return BuildVariableGetImpl(variable_kernel_position,
pos);
2058Fragment StreamingFlowGraphBuilder::BuildVariableGet(uint8_t payload,
2059 TokenPosition* position) {
2060 const TokenPosition
pos = ReadPosition();
2061 if (position !=
nullptr) *position =
pos;
2062 intptr_t variable_kernel_position =
ReadUInt();
2063 return BuildVariableGetImpl(variable_kernel_position,
pos);
2066Fragment StreamingFlowGraphBuilder::BuildVariableGetImpl(
2067 intptr_t variable_kernel_position,
2068 TokenPosition position) {
2069 LocalVariable* variable = LookupVariable(variable_kernel_position);
2070 if (!variable->is_late()) {
2071 return LoadLocal(variable);
2075 Fragment instructions = LoadLocal(variable);
2076 TargetEntryInstr* is_uninitialized;
2077 TargetEntryInstr* is_initialized;
2078 instructions += Constant(Object::sentinel());
2081 JoinEntryInstr*
join = BuildJoinEntry();
2084 AlternativeReadingScope alt(&
reader_, variable->late_init_offset());
2085 const bool has_initializer = (
ReadTag() != kNothing);
2087 if (has_initializer) {
2089 Fragment initialize(is_uninitialized);
2090 initialize += BuildExpression();
2091 if (variable->is_final()) {
2094 initialize += LoadLocal(variable);
2095 TargetEntryInstr* is_uninitialized_after_init;
2096 TargetEntryInstr* is_initialized_after_init;
2097 initialize += Constant(Object::sentinel());
2099 &is_uninitialized_after_init, &is_initialized_after_init);
2102 Fragment store_result(is_uninitialized_after_init);
2103 store_result += StoreLocal(position, variable);
2104 store_result += Drop();
2105 store_result += Goto(
join);
2110 Fragment already_assigned(is_initialized_after_init);
2111 already_assigned += flow_graph_builder_->ThrowLateInitializationError(
2112 position,
"_throwLocalAssignedDuringInitialization",
2114 already_assigned += Goto(
join);
2118 initialize += StoreLocal(position, variable);
2119 initialize += Drop();
2120 initialize += Goto(
join);
2124 Fragment initialize(is_uninitialized);
2125 initialize += flow_graph_builder_->ThrowLateInitializationError(
2126 position,
"_throwLocalNotInitialized", variable->name());
2127 initialize += Goto(
join);
2133 Fragment already_initialized(is_initialized);
2134 already_initialized += Goto(
join);
2137 Fragment
done = Fragment(instructions.entry,
join);
2138 done += LoadLocal(variable);
2142Fragment StreamingFlowGraphBuilder::BuildVariableSet(TokenPosition*
p) {
2143 TokenPosition position = ReadPosition();
2144 if (
p !=
nullptr) *
p = position;
2146 intptr_t variable_kernel_position =
ReadUInt();
2148 return BuildVariableSetImpl(position, variable_kernel_position);
2151Fragment StreamingFlowGraphBuilder::BuildVariableSet(uint8_t payload,
2153 TokenPosition position = ReadPosition();
2154 if (
p !=
nullptr) *
p = position;
2156 intptr_t variable_kernel_position =
ReadUInt();
2157 return BuildVariableSetImpl(position, variable_kernel_position);
2160Fragment StreamingFlowGraphBuilder::BuildVariableSetImpl(
2161 TokenPosition position,
2162 intptr_t variable_kernel_position) {
2163 Fragment instructions = BuildExpression();
2164 if (NeedsDebugStepCheck(stack(), position)) {
2165 instructions = DebugStepCheck(position) + instructions;
2168 LocalVariable* variable = LookupVariable(variable_kernel_position);
2169 if (variable->is_late() && variable->is_final()) {
2171 LocalVariable* expr_temp = MakeTemporary();
2172 instructions += LoadLocal(variable);
2173 TargetEntryInstr* is_uninitialized;
2174 TargetEntryInstr* is_initialized;
2175 instructions += Constant(Object::sentinel());
2178 JoinEntryInstr*
join = BuildJoinEntry();
2182 Fragment initialize(is_uninitialized);
2183 initialize += LoadLocal(expr_temp);
2184 initialize += StoreLocal(position, variable);
2185 initialize += Drop();
2186 initialize += Goto(
join);
2191 Fragment already_initialized(is_initialized);
2192 already_initialized += flow_graph_builder_->ThrowLateInitializationError(
2193 position,
"_throwLocalAlreadyInitialized", variable->name());
2194 already_initialized += Goto(
join);
2197 instructions = Fragment(instructions.entry,
join);
2199 instructions += StoreLocal(position, variable);
2202 return instructions;
2205Fragment StreamingFlowGraphBuilder::BuildInstanceGet(TokenPosition*
p) {
2208 const TokenPosition position = ReadPosition();
2209 if (
p !=
nullptr) *
p = position;
2211 const DirectCallMetadata direct_call =
2213 const InferredTypeMetadata result_type =
2216 Fragment instructions = BuildExpression();
2219 const NameIndex itarget_name =
2221 ASSERT(!
H.IsRoot(itarget_name) &&
H.IsGetter(itarget_name));
2223 Z,
H.LookupMethodByMember(itarget_name,
H.DartGetterName(itarget_name)));
2224 ASSERT(getter_name.ptr() == interface_target.name());
2226 if (direct_call.check_receiver_for_null_) {
2227 auto receiver = MakeTemporary();
2228 instructions += CheckNull(position, receiver, getter_name);
2231 if (!direct_call.target_.IsNull()) {
2234 StaticCall(position, direct_call.target_, 1, Array::null_array(),
2235 ICData::kNoRebind, &result_type);
2237 const intptr_t kTypeArgsLen = 0;
2238 const intptr_t kNumArgsChecked = 1;
2240 InstanceCall(position, getter_name, Token::kGET, kTypeArgsLen, 1,
2241 Array::null_array(), kNumArgsChecked, interface_target,
2242 Function::null_function(), &result_type);
2245 return instructions;
2248Fragment StreamingFlowGraphBuilder::BuildDynamicGet(TokenPosition*
p) {
2251 const TokenPosition position = ReadPosition();
2252 if (
p !=
nullptr) *
p = position;
2254 const DirectCallMetadata direct_call =
2256 const InferredTypeMetadata result_type =
2259 Fragment instructions = BuildExpression();
2263 const Function* direct_call_target = &direct_call.target_;
2264 if (!direct_call_target->IsNull()) {
2266 direct_call.target_.GetDynamicInvocationForwarder(mangled_name));
2269 if (direct_call.check_receiver_for_null_) {
2270 auto receiver = MakeTemporary();
2271 instructions += CheckNull(position, receiver, getter_name);
2274 if (!direct_call_target->IsNull()) {
2277 StaticCall(position, *direct_call_target, 1, Array::null_array(),
2278 ICData::kNoRebind, &result_type);
2280 const intptr_t kTypeArgsLen = 0;
2281 const intptr_t kNumArgsChecked = 1;
2282 instructions += InstanceCall(position, mangled_name, Token::kGET,
2283 kTypeArgsLen, 1, Array::null_array(),
2284 kNumArgsChecked, Function::null_function(),
2285 Function::null_function(), &result_type);
2288 return instructions;
2291Fragment StreamingFlowGraphBuilder::BuildInstanceTearOff(TokenPosition*
p) {
2294 const TokenPosition position = ReadPosition();
2295 if (
p !=
nullptr) *
p = position;
2297 const DirectCallMetadata direct_call =
2299 const InferredTypeMetadata result_type =
2302 Fragment instructions = BuildExpression();
2305 const NameIndex itarget_name =
2307 ASSERT(!
H.IsRoot(itarget_name) &&
H.IsMethod(itarget_name));
2309 Z,
H.LookupMethodByMember(itarget_name,
H.DartMethodName(itarget_name)));
2311 if (direct_call.check_receiver_for_null_) {
2312 const auto receiver = MakeTemporary();
2313 instructions += CheckNull(position, receiver, getter_name);
2316 if (!direct_call.target_.IsNull()) {
2319 StaticCall(position, direct_call.target_, 1, Array::null_array(),
2320 ICData::kNoRebind, &result_type);
2322 const intptr_t kTypeArgsLen = 0;
2323 const intptr_t kNumArgsChecked = 1;
2324 instructions += InstanceCall(position, getter_name, Token::kGET,
2325 kTypeArgsLen, 1, Array::null_array(),
2326 kNumArgsChecked, Function::null_function(),
2327 tearoff_interface_target, &result_type);
2330 return instructions;
2333Fragment StreamingFlowGraphBuilder::BuildInstanceSet(TokenPosition*
p) {
2337 const DirectCallMetadata direct_call =
2339 const CallSiteAttributesMetadata call_site_attributes =
2341 const InferredTypeMetadata inferred_type =
2345 bool is_unchecked_call = inferred_type.
IsSkipCheck();
2346 if (call_site_attributes.receiver_type !=
nullptr &&
2347 call_site_attributes.receiver_type->HasTypeClass() &&
2348 !
Class::Handle(call_site_attributes.receiver_type->type_class())
2350 is_unchecked_call =
true;
2353 Fragment instructions(MakeTemp());
2354 LocalVariable* variable = MakeTemporary();
2356 const TokenPosition position = ReadPosition();
2357 if (
p !=
nullptr) *
p = position;
2359 const bool is_call_on_this =
PeekTag() == kThisExpression;
2360 if (is_call_on_this) {
2361 is_unchecked_call =
true;
2363 instructions += BuildExpression();
2365 LocalVariable* receiver =
nullptr;
2366 if (direct_call.check_receiver_for_null_) {
2367 receiver = MakeTemporary();
2372 instructions += BuildExpression();
2373 instructions += StoreLocal(TokenPosition::kNoSource, variable);
2375 const NameIndex itarget_name =
2377 ASSERT(!
H.IsRoot(itarget_name));
2379 Z,
H.LookupMethodByMember(itarget_name,
H.DartSetterName(itarget_name)));
2380 ASSERT(setter_name.ptr() == interface_target.name());
2382 if (direct_call.check_receiver_for_null_) {
2383 instructions += CheckNull(position, receiver, setter_name);
2386 if (!direct_call.target_.IsNull()) {
2389 StaticCall(position, direct_call.target_, 2, Array::null_array(),
2390 ICData::kNoRebind,
nullptr,
2394 const intptr_t kTypeArgsLen = 0;
2395 const intptr_t kNumArgsChecked = 1;
2397 instructions += InstanceCall(
2398 position, setter_name, Token::kSET, kTypeArgsLen, 2,
2399 Array::null_array(), kNumArgsChecked, interface_target,
2400 Function::null_function(),
2402 is_unchecked_call, &call_site_attributes,
2403 false, is_call_on_this);
2406 instructions += Drop();
2408 return instructions;
2411Fragment StreamingFlowGraphBuilder::BuildDynamicSet(TokenPosition*
p) {
2415 const DirectCallMetadata direct_call =
2417 const InferredTypeMetadata inferred_type =
2421 const bool is_unchecked_call = inferred_type.
IsSkipCheck();
2423 Fragment instructions(MakeTemp());
2424 LocalVariable* variable = MakeTemporary();
2426 const TokenPosition position = ReadPosition();
2427 if (
p !=
nullptr) *
p = position;
2429 instructions += BuildExpression();
2431 LocalVariable* receiver =
nullptr;
2432 if (direct_call.check_receiver_for_null_) {
2433 receiver = MakeTemporary();
2438 instructions += BuildExpression();
2439 instructions += StoreLocal(TokenPosition::kNoSource, variable);
2441 if (direct_call.check_receiver_for_null_) {
2442 instructions += CheckNull(position, receiver, setter_name);
2445 const Function* direct_call_target = &direct_call.target_;
2448 if (!direct_call_target->IsNull()) {
2450 direct_call.target_.GetDynamicInvocationForwarder(mangled_name));
2453 if (!direct_call_target->IsNull()) {
2456 StaticCall(position, *direct_call_target, 2, Array::null_array(),
2457 ICData::kNoRebind,
nullptr,
2461 const intptr_t kTypeArgsLen = 0;
2462 const intptr_t kNumArgsChecked = 1;
2464 instructions += InstanceCall(
2465 position, mangled_name, Token::kSET, kTypeArgsLen, 2,
2466 Array::null_array(), kNumArgsChecked, Function::null_function(),
2467 Function::null_function(),
2469 is_unchecked_call,
nullptr);
2472 instructions += Drop();
2474 return instructions;
2479 const Class& klass) {
2482 if (!iterate_klass.
IsNull() &&
2484 while (!iterate_klass.
IsNull()) {
2486 Symbols::NoSuchMethod());
2497 return nsm_function;
2501Fragment StreamingFlowGraphBuilder::BuildAllocateInvocationMirrorCall(
2504 intptr_t num_type_arguments,
2505 intptr_t num_arguments,
2506 const Array& argument_names,
2508 Fragment build_rest_of_actuals) {
2509 Fragment instructions;
2512 instructions += LoadLocal(actuals_array);
2513 instructions += IntConstant(num_type_arguments == 0 ? 0 : 1);
2514 instructions += LoadLocal(parsed_function()->receiver_var());
2515 instructions += StoreIndexed(kArrayCid);
2516 instructions += build_rest_of_actuals;
2519 instructions += LoadLocal(parsed_function()->receiver_var());
2526 const Array& args_descriptor =
2528 num_type_arguments, num_arguments, argument_names));
2532 instructions += LoadLocal(actuals_array);
2537 const Class& mirror_class =
2546 instructions += StaticCall(position, allocation_function,
2547 4, ICData::kStatic);
2548 return instructions;
2551Fragment StreamingFlowGraphBuilder::BuildSuperPropertyGet(TokenPosition*
p) {
2553 const TokenPosition position = ReadPosition();
2554 if (
p !=
nullptr) *
p = position;
2556 const InferredTypeMetadata result_type =
2559 Class& klass = GetSuperOrDie();
2562 NameIndex library_reference =
2563 ((
H.StringSize(name_index) >= 1) &&
H.CharacterAt(name_index, 0) ==
'_')
2566 const String& getter_name =
H.DartGetterName(library_reference, name_index);
2567 const String& method_name =
H.DartMethodName(library_reference, name_index);
2574 if (!klass.IsNull() && klass.EnsureIsFinalized(thread()) ==
Error::null()) {
2575 while (!klass.IsNull()) {
2583 return B->BuildImplicitClosureCreation(position,
target);
2587 klass = klass.SuperClass();
2591 Fragment instructions;
2592 if (klass.IsNull()) {
2595 instructions += IntConstant(1);
2596 instructions += CreateArray();
2597 LocalVariable* actuals_array = MakeTemporary();
2599 Class& parent_klass = GetSuperOrDie();
2601 instructions += BuildAllocateInvocationMirrorCall(
2602 position, getter_name,
2605 Object::empty_array(), actuals_array,
2611 2, ICData::kNSMDispatch);
2612 instructions += DropTempsPreserveTop(1);
2617 instructions += LoadLocal(parsed_function()->receiver_var());
2621 1, Array::null_array(),
2622 ICData::kSuper, &result_type);
2625 return instructions;
2628Fragment StreamingFlowGraphBuilder::BuildSuperPropertySet(TokenPosition*
p) {
2629 const TokenPosition position = ReadPosition();
2630 if (
p !=
nullptr) *
p = position;
2632 Class& klass = GetSuperOrDie();
2637 if (klass.EnsureIsFinalized(thread()) ==
Error::null()) {
2641 Fragment instructions(MakeTemp());
2642 LocalVariable*
value = MakeTemporary();
2647 instructions += IntConstant(2);
2648 instructions += CreateArray();
2649 LocalVariable* actuals_array = MakeTemporary();
2651 Fragment build_rest_of_actuals;
2652 build_rest_of_actuals += LoadLocal(actuals_array);
2653 build_rest_of_actuals += IntConstant(1);
2654 build_rest_of_actuals += BuildExpression();
2655 build_rest_of_actuals += StoreLocal(position,
value);
2656 build_rest_of_actuals += StoreIndexed(kArrayCid);
2658 instructions += BuildAllocateInvocationMirrorCall(
2659 position, setter_name, 0,
2661 Object::empty_array(), actuals_array,
2662 build_rest_of_actuals);
2669 2, ICData::kNSMDispatch);
2670 instructions += Drop();
2671 instructions += Drop();
2674 instructions += LoadLocal(parsed_function()->receiver_var());
2676 instructions += BuildExpression();
2677 instructions += StoreLocal(position,
value);
2681 instructions += StaticCall(
2683 2, Array::null_array(), ICData::kSuper,
2686 instructions += Drop();
2689 return instructions;
2692Fragment StreamingFlowGraphBuilder::BuildStaticGet(TokenPosition*
p) {
2696 TokenPosition position = ReadPosition();
2697 if (
p !=
nullptr) *
p = position;
2699 const InferredTypeMetadata result_type =
2706 Z,
H.LookupFieldByKernelGetterOrSetter(
target,
false));
2707 if (!field.IsNull()) {
2708 if (field.is_const()) {
2719 }
else if (field.is_final() && field.has_trivial_initializer()) {
2725 const String& getter_name =
H.DartGetterName(
target);
2726 const Function& getter =
2728 if (!getter.IsNull() && field.NeedsGetter()) {
2729 return StaticCall(position, getter, 0, Array::null_array(),
2730 ICData::kStatic, &result_type);
2732 if (result_type.IsConstant()) {
2733 return Constant(result_type.constant_value);
2735 return LoadStaticField(field,
false);
2741 Z,
H.LookupStaticMethodByKernelProcedure(
target,
false));
2744 return StaticCall(position,
function, 0, Array::null_array(),
2745 ICData::kStatic, &result_type);
2746 }
else if (
H.IsMethod(
target)) {
2747 const auto& closure_function =
2749 const auto& static_closure =
2757 return StaticCallMissing(
2758 position,
H.DartSymbolPlain(
H.CanonicalNameString(
target)),
2760 H.IsLibrary(
H.EnclosingName(
target)) ? InvocationMirror::Level::kTopLevel
2761 : InvocationMirror::Level::kStatic,
2762 InvocationMirror::Kind::kGetter);
2765Fragment StreamingFlowGraphBuilder::BuildStaticSet(TokenPosition*
p) {
2766 TokenPosition position = ReadPosition();
2767 if (
p !=
nullptr) *
p = position;
2773 Fragment instructions = BuildExpression();
2779 Z,
H.LookupStaticMethodByKernelProcedure(
target,
false));
2782 LocalVariable* variable = MakeTemporary();
2785 instructions += LoadLocal(variable);
2788 instructions += StaticCall(position,
function, 1, ICData::kStatic);
2791 return instructions + Drop();
2795 Z,
H.LookupFieldByKernelGetterOrSetter(
target,
false));
2796 if (!field.IsNull()) {
2797 if (NeedsDebugStepCheck(stack(), position)) {
2798 instructions = DebugStepCheck(position) + instructions;
2800 LocalVariable* variable = MakeTemporary();
2801 instructions += LoadLocal(variable);
2802 instructions += StoreStaticField(position, field);
2803 return instructions;
2806 instructions += StaticCallMissing(
2807 position,
H.DartSymbolPlain(
H.CanonicalNameString(
target)),
2809 H.IsLibrary(
H.EnclosingName(
target)) ? InvocationMirror::Level::kTopLevel
2810 : InvocationMirror::Level::kStatic,
2811 InvocationMirror::Kind::kSetter);
2812 return instructions;
2815Fragment StreamingFlowGraphBuilder::BuildMethodInvocation(TokenPosition*
p,
2824 const TokenPosition position = ReadPosition();
2825 if (
p !=
nullptr) *
p = position;
2827 const DirectCallMetadata direct_call =
2829 const InferredTypeMetadata result_type =
2831 const CallSiteAttributesMetadata call_site_attributes =
2836 bool is_unchecked_call = is_invariant || result_type.IsSkipCheck();
2837 if (!is_dynamic && (call_site_attributes.receiver_type !=
nullptr) &&
2838 call_site_attributes.receiver_type->HasTypeClass() &&
2839 !call_site_attributes.receiver_type->IsDynamicType() &&
2840 !
Class::Handle(call_site_attributes.receiver_type->type_class())
2842 is_unchecked_call =
true;
2845 Fragment instructions;
2847 intptr_t type_args_len = 0;
2849 AlternativeReadingScope alt(&
reader_);
2854 if (list_length > 0) {
2855 const TypeArguments& type_arguments =
2856 T.BuildTypeArguments(list_length);
2857 instructions += TranslateInstantiatedTypeArguments(type_arguments);
2859 type_args_len = list_length;
2864 const bool is_call_on_this = (
PeekTag() == kThisExpression) && !is_dynamic;
2865 if (is_call_on_this) {
2866 is_unchecked_call =
true;
2868 instructions += BuildExpression();
2875 if ((token_kind == Token::kEQ || token_kind == Token::kNE) &&
2876 PeekArgumentsCount() == 1 &&
2877 (receiver_tag == kNullLiteral ||
2878 PeekArgumentsFirstPositionalTag() == kNullLiteral)) {
2879 ASSERT(type_args_len == 0);
2882 BuildArguments(
nullptr ,
nullptr ,
2886 token_kind == Token::kEQ ? Token::kEQ_STRICT : Token::kNE_STRICT;
2887 return instructions +
2888 StrictCompare(position, strict_cmp_kind,
true);
2891 LocalVariable* receiver_temp =
nullptr;
2892 if (direct_call.check_receiver_for_null_) {
2893 receiver_temp = MakeTemporary();
2897 intptr_t positional_argument_count;
2901 &positional_argument_count);
2904 intptr_t checked_argument_count = 1;
2907 if (token_kind != Token::kILLEGAL) {
2916 const Function* interface_target = &Function::null_function();
2918 const NameIndex itarget_name =
2923 if (!
H.IsRoot(itarget_name) && !
H.IsGetter(itarget_name)) {
2925 Z,
H.LookupMethodByMember(itarget_name,
2926 H.DartProcedureName(itarget_name)));
2927 ASSERT(
name.ptr() == interface_target->name());
2928 ASSERT(!interface_target->IsGetterFunction());
2931 if (direct_call.check_receiver_for_null_) {
2932 instructions += CheckNull(position, receiver_temp,
name);
2935 const String* mangled_name = &
name;
2940 const Function* direct_call_target = &direct_call.target_;
2941 if (
H.IsRoot(itarget_name) &&
2942 (
name.ptr() != Symbols::EqualOperator().ptr())) {
2945 if (!direct_call_target->IsNull()) {
2947 direct_call_target->GetDynamicInvocationForwarder(*mangled_name));
2951 if (!direct_call_target->IsNull()) {
2958 argument_names, ICData::kNoRebind, &result_type,
2959 type_args_len, is_unchecked_call);
2961 instructions += InstanceCall(
2962 position, *mangled_name, token_kind, type_args_len,
argument_count,
2963 argument_names, checked_argument_count, *interface_target,
2964 Function::null_function(), &result_type,
2965 is_unchecked_call, &call_site_attributes,
2966 result_type.ReceiverNotInt(), is_call_on_this);
2973 if (
name.ptr() == Symbols::AssignIndexToken().ptr()) {
2974 instructions += Drop();
2975 instructions += NullConstant();
2978 return instructions;
2981Fragment StreamingFlowGraphBuilder::BuildLocalFunctionInvocation(
2984 const TokenPosition position = ReadPosition();
2985 if (
p !=
nullptr) *
p = position;
2987 const InferredTypeMetadata result_type =
2991 const intptr_t variable_kernel_position =
ReadUInt();
2994 LocalVariable* variable = LookupVariable(variable_kernel_position);
2995 ASSERT(!variable->is_late());
2999 AlternativeReadingScope alt(
3003 const intptr_t function_node_kernel_offset =
ReaderOffset();
3007 parsed_function()->
function().GetOutermostFunction()),
3008 function_node_kernel_offset);
3012 Fragment instructions;
3015 intptr_t type_args_len = 0;
3017 AlternativeReadingScope alt(&
reader_);
3020 if (list_length > 0) {
3021 const TypeArguments& type_arguments =
3022 T.BuildTypeArguments(list_length);
3023 instructions += TranslateInstantiatedTypeArguments(type_arguments);
3025 type_args_len = list_length;
3029 instructions += LoadLocal(variable);
3032 intptr_t positional_argument_count;
3036 &positional_argument_count);
3042 instructions += LoadLocal(variable);
3043 if (!FLAG_precompiled_mode) {
3044 instructions += LoadNativeField(Slot::Closure_function());
3046 if (parsed_function()->
function().is_debuggable()) {
3048 instructions += DebugStepCheck(position);
3050 instructions +=
B->ClosureCall(target_function, position, type_args_len,
3052 return instructions;
3055Fragment StreamingFlowGraphBuilder::BuildFunctionInvocation(TokenPosition*
p) {
3059 const TokenPosition position = ReadPosition();
3060 if (
p !=
nullptr) *
p = position;
3062 const DirectCallMetadata direct_call =
3064 const InferredTypeMetadata result_type =
3069 const bool is_unchecked_closure_call =
3071 Fragment instructions;
3073 instructions += BuildExpression();
3074 LocalVariable* receiver_temp = MakeTemporary();
3077 intptr_t type_args_len = 0;
3079 AlternativeReadingScope alt(&
reader_);
3082 if (list_length > 0) {
3083 const TypeArguments& type_arguments =
3084 T.BuildTypeArguments(list_length);
3085 instructions += TranslateInstantiatedTypeArguments(type_arguments);
3087 type_args_len = list_length;
3091 instructions += LoadLocal(receiver_temp);
3094 intptr_t positional_argument_count;
3098 &positional_argument_count);
3103 if (is_unchecked_closure_call) {
3104 instructions += CheckNull(position, receiver_temp,
Symbols::call());
3106 instructions += LoadLocal(receiver_temp);
3107 if (!FLAG_precompiled_mode) {
3108 instructions += LoadNativeField(Slot::Closure_function());
3110 if (parsed_function()->
function().is_debuggable()) {
3112 instructions += DebugStepCheck(position);
3115 B->ClosureCall(direct_call.target_, position, type_args_len,
3118 instructions += InstanceCall(
3119 position, Symbols::DynamicCall(), Token::kILLEGAL, type_args_len,
3121 Function::null_function(), &result_type,
3123 result_type.ReceiverNotInt());
3125 instructions += DropTempsPreserveTop(1);
3126 return instructions;
3129Fragment StreamingFlowGraphBuilder::BuildEqualsCall(TokenPosition*
p) {
3131 const TokenPosition position = ReadPosition();
3132 if (
p !=
nullptr) *
p = position;
3134 const DirectCallMetadata direct_call =
3136 ASSERT(!direct_call.check_receiver_for_null_);
3137 const InferredTypeMetadata result_type =
3139 const CallSiteAttributesMetadata call_site_attributes =
3142 Fragment instructions;
3143 instructions += BuildExpression();
3144 instructions += BuildExpression();
3147 const NameIndex itarget_name =
3151 H.LookupMethodByMember(itarget_name,
H.DartProcedureName(itarget_name)));
3152 ASSERT(interface_target.name() == Symbols::EqualOperator().ptr());
3154 const intptr_t kTypeArgsLen = 0;
3155 const intptr_t kNumArgs = 2;
3156 const intptr_t kNumCheckedArgs = 2;
3158 if (!direct_call.target_.IsNull()) {
3161 StaticCall(position, direct_call.target_, kNumArgs, Array::null_array(),
3162 ICData::kNoRebind, &result_type, kTypeArgsLen,
3165 instructions += InstanceCall(
3166 position, Symbols::EqualOperator(), Token::kEQ, kTypeArgsLen, kNumArgs,
3167 Array::null_array(), kNumCheckedArgs, interface_target,
3168 Function::null_function(), &result_type,
3169 true, &call_site_attributes,
3170 result_type.ReceiverNotInt());
3173 return instructions;
3176Fragment StreamingFlowGraphBuilder::BuildEqualsNull(TokenPosition*
p) {
3177 const TokenPosition position = ReadPosition();
3178 if (
p !=
nullptr) *
p = position;
3179 Fragment instructions;
3180 instructions += BuildExpression();
3181 instructions += NullConstant();
3182 if (parsed_function()->
function().is_debuggable()) {
3183 instructions += DebugStepCheck(position);
3186 StrictCompare(position, Token::kEQ_STRICT,
false);
3187 return instructions;
3190Fragment StreamingFlowGraphBuilder::BuildSuperMethodInvocation(
3193 const TokenPosition position = ReadPosition();
3194 if (
p !=
nullptr) *
p = position;
3196 const InferredTypeMetadata result_type =
3199 intptr_t type_args_len = 0;
3201 AlternativeReadingScope alt(&
reader_);
3207 Class& klass = GetSuperOrDie();
3216 AlternativeReadingScope alt(&
reader_);
3222 argument_names =
Array::New(named_list_length,
H.allocation_space());
3223 for (intptr_t
i = 0;
i < named_list_length;
i++) {
3225 argument_names.SetAt(
i, arg_name);
3230 Function&
function = FindMatchingFunction(
3231 klass, method_name, type_args_len,
3238 Fragment instructions;
3242 (type_list_length == 0 ? 0 : 1));
3243 instructions += CreateArray();
3244 LocalVariable* actuals_array = MakeTemporary();
3247 Fragment build_rest_of_actuals;
3248 intptr_t actuals_array_index = 0;
3249 if (type_list_length > 0) {
3250 const TypeArguments& type_arguments =
3251 T.BuildTypeArguments(type_list_length);
3252 build_rest_of_actuals += LoadLocal(actuals_array);
3253 build_rest_of_actuals += IntConstant(actuals_array_index);
3254 build_rest_of_actuals +=
3255 TranslateInstantiatedTypeArguments(type_arguments);
3256 build_rest_of_actuals += StoreIndexed(kArrayCid);
3257 ++actuals_array_index;
3260 ++actuals_array_index;
3264 while (
i < list_length) {
3265 build_rest_of_actuals += LoadLocal(actuals_array);
3266 build_rest_of_actuals += IntConstant(actuals_array_index +
i);
3267 build_rest_of_actuals += BuildExpression();
3268 build_rest_of_actuals += StoreIndexed(kArrayCid);
3273 if (named_list_length > 0) {
3275 while ((
i - list_length) < named_list_length) {
3277 build_rest_of_actuals += LoadLocal(actuals_array);
3278 build_rest_of_actuals += IntConstant(
i + actuals_array_index);
3279 build_rest_of_actuals += BuildExpression();
3280 build_rest_of_actuals += StoreIndexed(kArrayCid);
3284 instructions += BuildAllocateInvocationMirrorCall(
3285 position, method_name, type_list_length,
3287 build_rest_of_actuals);
3292 instructions += StaticCall(TokenPosition::kNoSource,
3294 2, ICData::kNSMDispatch);
3295 instructions += DropTempsPreserveTop(1);
3296 return instructions;
3298 Fragment instructions;
3301 AlternativeReadingScope alt(&
reader_);
3304 if (list_length > 0) {
3305 const TypeArguments& type_arguments =
3306 T.BuildTypeArguments(list_length);
3307 instructions += TranslateInstantiatedTypeArguments(type_arguments);
3312 instructions += LoadLocal(parsed_function()->receiver_var());
3316 instructions += BuildArguments(
3321 return instructions +
3324 &result_type, type_args_len,
3329Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(TokenPosition*
p) {
3331 TokenPosition position = ReadPosition();
3332 if (
p !=
nullptr) *
p = position;
3334 const InferredTypeMetadata result_type =
3337 NameIndex procedure_reference =
3342 procedure_reference,
false));
3345 Fragment instructions;
3348 BuildArguments(&argument_names,
nullptr ,
3350 instructions += StaticCallMissing(
3351 position,
H.DartSymbolPlain(
H.CanonicalNameString(procedure_reference)),
3353 H.IsLibrary(
H.EnclosingName(procedure_reference))
3354 ? InvocationMirror::Level::kTopLevel
3355 : InvocationMirror::Level::kStatic,
3356 InvocationMirror::Kind::kMethod);
3357 return instructions;
3361 if (
target.IsGenerativeConstructor() ||
target.IsFactory()) {
3367 if (
target.IsCachableIdempotent()) {
3368 return BuildCachableIdempotentCall(position,
target);
3371 const auto recognized_kind =
target.recognized_kind();
3372 switch (recognized_kind) {
3373 case MethodRecognizer::kNativeEffect:
3374 return BuildNativeEffect();
3375 case MethodRecognizer::kReachabilityFence:
3376 return BuildReachabilityFence();
3377 case MethodRecognizer::kFfiCall:
3378 return BuildFfiCall();
3379 case MethodRecognizer::kFfiNativeCallbackFunction:
3380 return BuildFfiNativeCallbackFunction(
3382 case MethodRecognizer::kFfiNativeAddressOf:
3383 return BuildFfiNativeAddressOf();
3384 case MethodRecognizer::kFfiNativeIsolateLocalCallbackFunction:
3385 return BuildFfiNativeCallbackFunction(
3387 case MethodRecognizer::kFfiNativeAsyncCallbackFunction:
3389 case MethodRecognizer::kFfiLoadAbiSpecificInt:
3390 return BuildLoadStoreAbiSpecificInt(
false,
3392 case MethodRecognizer::kFfiLoadAbiSpecificIntAtIndex:
3393 return BuildLoadStoreAbiSpecificInt(
false,
3395 case MethodRecognizer::kFfiStoreAbiSpecificInt:
3396 return BuildLoadStoreAbiSpecificInt(
true,
3398 case MethodRecognizer::kFfiStoreAbiSpecificIntAtIndex:
3399 return BuildLoadStoreAbiSpecificInt(
true,
true);
3404 Fragment instructions;
3405 LocalVariable* instance_variable =
nullptr;
3407 const bool special_case_unchecked_cast =
3409 (
target.name() == Symbols::UnsafeCast().ptr());
3411 const bool special_case_identical =
3413 (
target.name() == Symbols::Identical().ptr());
3415 const bool special_case =
3416 special_case_identical || special_case_unchecked_cast;
3427 intptr_t type_args_len = 0;
3428 if (
target.IsGenerativeConstructor()) {
3429 if (klass.NumTypeArguments() > 0) {
3430 const TypeArguments& type_arguments =
3431 PeekArgumentsInstantiatedType(klass);
3432 instructions += TranslateInstantiatedTypeArguments(type_arguments);
3433 instructions += AllocateObject(position, klass, 1);
3435 instructions += AllocateObject(position, klass, 0);
3438 instance_variable = MakeTemporary();
3440 instructions += LoadLocal(instance_variable);
3441 }
else if (
target.IsFactory()) {
3447 const TypeArguments& type_arguments = PeekArgumentsInstantiatedType(klass);
3448 instructions += TranslateInstantiatedTypeArguments(type_arguments);
3449 }
else if (!special_case) {
3450 AlternativeReadingScope alt(&
reader_);
3453 if (list_length > 0) {
3454 const TypeArguments& type_arguments =
3455 T.BuildTypeArguments(list_length);
3456 instructions += TranslateInstantiatedTypeArguments(type_arguments);
3458 type_args_len = list_length;
3463 BuildArguments(&argument_names,
nullptr ,
3472 if (special_case_identical) {
3475 StrictCompare(position, Token::kEQ_STRICT,
true);
3476 }
else if (special_case_unchecked_cast) {
3480 ICData::kStatic, &result_type, type_args_len);
3481 if (
target.IsGenerativeConstructor()) {
3484 instructions += Drop();
3489 if (recognized_kind == MethodRecognizer::kDebugger) {
3490 instructions += DebugStepCheck(position);
3494 return instructions;
3497Fragment StreamingFlowGraphBuilder::BuildConstructorInvocation(
3499 TokenPosition position = ReadPosition();
3500 if (
p !=
nullptr) *
p = position;
3502 NameIndex kernel_name =
3506 Z,
H.LookupClassByKernelClass(
H.EnclosingName(kernel_name),
3508 Fragment instructions;
3509 if (klass.IsNull()) {
3512 instructions += BuildArguments(
3515 instructions += StaticCallMissing(
3516 position,
H.DartSymbolPlain(
H.CanonicalNameString(kernel_name)),
3518 InvocationMirror::Kind::kMethod);
3519 return instructions;
3521 const auto&
error = klass.EnsureIsFinalized(
H.thread());
3524 if (klass.NumTypeArguments() > 0) {
3525 if (!klass.IsGeneric()) {
3527 Z, klass.GetDeclarationInstanceTypeArguments());
3528 instructions += Constant(type_arguments);
3530 const TypeArguments& type_arguments =
3531 PeekArgumentsInstantiatedType(klass);
3532 instructions += TranslateInstantiatedTypeArguments(type_arguments);
3535 instructions += AllocateObject(position, klass, 1);
3537 instructions += AllocateObject(position, klass, 0);
3539 LocalVariable* variable = MakeTemporary();
3541 instructions += LoadLocal(variable);
3545 instructions += BuildArguments(
3551 klass, kernel_name,
false));
3555 instructions += StaticCallMissing(
3556 position,
H.DartSymbolPlain(
H.CanonicalNameString(kernel_name)),
3558 InvocationMirror::Kind::kMethod);
3561 ICData::kStatic,
nullptr);
3563 return instructions + Drop();
3566Fragment StreamingFlowGraphBuilder::BuildNot(TokenPosition*
p) {
3567 TokenPosition position = ReadPosition();
3568 if (
p !=
nullptr) *
p = position;
3570 TokenPosition operand_position = TokenPosition::kNoSource;
3571 Fragment instructions =
3572 BuildExpression(&operand_position);
3573 instructions += CheckBoolean(operand_position);
3574 instructions += BooleanNegate();
3575 return instructions;
3578Fragment StreamingFlowGraphBuilder::BuildNullCheck(TokenPosition*
p) {
3579 const TokenPosition position = ReadPosition();
3580 if (
p !=
nullptr) *
p = position;
3582 TokenPosition operand_position = TokenPosition::kNoSource;
3583 Fragment instructions = BuildExpression(&operand_position);
3584 LocalVariable* expr_temp = MakeTemporary();
3585 instructions += CheckNull(position, expr_temp, String::null_string());
3587 return instructions;
3605Fragment StreamingFlowGraphBuilder::TranslateLogicalExpressionForValue(
3607 TestFragment* side_exits) {
3608 TestFragment
left = TranslateConditionForControl().
Negate(negated);
3616 side_exits->false_successor_addresses->AddArray(
3617 *
left.false_successor_addresses);
3619 side_exits->true_successor_addresses->AddArray(
3620 *
left.true_successor_addresses);
3630 Fragment right_value(op ==
kAnd
3631 ?
left.CreateTrueSuccessor(flow_graph_builder_)
3632 :
left.CreateFalseSuccessor(flow_graph_builder_));
3634 if (
PeekTag() == kLogicalExpression) {
3639 right_value += TranslateLogicalExpressionForValue(negated, side_exits);
3642 TokenPosition position = TokenPosition::kNoSource;
3643 right_value += BuildExpression(&position);
3650 const bool is_bool = top->IsStrictCompare() || top->IsBooleanNegate();
3652 right_value += CheckBoolean(position);
3655 right_value += BooleanNegate();
3657 right_value += StoreLocal(TokenPosition::kNoSource,
3658 parsed_function()->expression_temp_var());
3659 right_value += Drop();
3662 return Fragment(
left.entry, right_value.current);
3665Fragment StreamingFlowGraphBuilder::BuildLogicalExpression(TokenPosition*
p) {
3666 TokenPosition position = ReadPosition();
3667 if (
p !=
nullptr) *
p = position;
3673 JoinEntryInstr*
join = BuildJoinEntry();
3674 Fragment instructions =
3675 TranslateLogicalExpressionForValue(
false, &exits);
3676 instructions += Goto(
join);
3679 if (!exits.true_successor_addresses->is_empty()) {
3680 Fragment constant_fragment(exits.CreateTrueSuccessor(flow_graph_builder_));
3681 constant_fragment += Constant(
Bool::Get(
true));
3682 constant_fragment += StoreLocal(TokenPosition::kNoSource,
3683 parsed_function()->expression_temp_var());
3684 constant_fragment += Drop();
3685 constant_fragment += Goto(
join);
3689 if (!exits.false_successor_addresses->is_empty()) {
3690 Fragment constant_fragment(exits.CreateFalseSuccessor(flow_graph_builder_));
3691 constant_fragment += Constant(
Bool::Get(
false));
3692 constant_fragment += StoreLocal(TokenPosition::kNoSource,
3693 parsed_function()->expression_temp_var());
3694 constant_fragment += Drop();
3695 constant_fragment += Goto(
join);
3698 return Fragment(instructions.entry,
join) +
3699 LoadLocal(parsed_function()->expression_temp_var());
3702Fragment StreamingFlowGraphBuilder::BuildConditionalExpression(
3704 TokenPosition position = ReadPosition();
3705 if (
p !=
nullptr) *
p = position;
3707 TestFragment condition = TranslateConditionForControl();
3709 Value* top = stack();
3710 Fragment then_fragment(condition.CreateTrueSuccessor(flow_graph_builder_));
3711 then_fragment += BuildExpression();
3712 then_fragment += StoreLocal(TokenPosition::kNoSource,
3713 parsed_function()->expression_temp_var());
3714 then_fragment += Drop();
3717 Fragment otherwise_fragment(
3718 condition.CreateFalseSuccessor(flow_graph_builder_));
3719 otherwise_fragment += BuildExpression();
3720 otherwise_fragment += StoreLocal(TokenPosition::kNoSource,
3721 parsed_function()->expression_temp_var());
3722 otherwise_fragment += Drop();
3725 JoinEntryInstr*
join = BuildJoinEntry();
3726 then_fragment += Goto(
join);
3727 otherwise_fragment += Goto(
join);
3731 return Fragment(condition.entry,
join) +
3732 LoadLocal(parsed_function()->expression_temp_var());
3735void StreamingFlowGraphBuilder::FlattenStringConcatenation(
3736 PiecesCollector* collector) {
3741 case kStringLiteral: {
3746 if (!
s.Equals(
"")) {
3747 collector->Add({-1, &
s});
3751 case kStringConcatenation: {
3755 FlattenStringConcatenation(collector);
3759 collector->Add({
offset,
nullptr});
3766Fragment StreamingFlowGraphBuilder::BuildStringConcatenation(TokenPosition*
p) {
3767 TokenPosition position = ReadPosition();
3777 PiecesCollector collector(
Z, &
H);
3778 FlattenStringConcatenation(&collector);
3779 collector.FlushRun();
3781 if (collector.pieces.length() == 1) {
3783 if (collector.pieces[0].literal !=
nullptr) {
3784 return Constant(*collector.pieces[0].literal);
3787 AlternativeReadingScope scope(&
reader_, collector.pieces[0].
offset);
3788 Fragment instructions;
3789 instructions += BuildExpression();
3790 instructions += StringInterpolateSingle(position);
3791 return instructions;
3794 Fragment instructions;
3796 instructions += IntConstant(collector.pieces.length());
3797 instructions += CreateArray();
3798 LocalVariable* array = MakeTemporary();
3799 for (intptr_t
i = 0;
i < collector.pieces.length(); ++
i) {
3802 if (collector.pieces[
i].literal !=
nullptr) {
3803 instructions += LoadLocal(array);
3804 instructions += IntConstant(
i);
3805 instructions += Constant(*collector.pieces[
i].literal);
3807 AlternativeReadingScope scope(&
reader_, collector.pieces[
i].
offset);
3808 instructions += LoadLocal(array);
3809 instructions += IntConstant(
i);
3810 instructions += BuildExpression();
3812 instructions += StoreIndexed(kArrayCid);
3815 instructions += StringInterpolate(position);
3817 return instructions;
3820Fragment StreamingFlowGraphBuilder::BuildIsTest(TokenPosition position,
3821 const AbstractType&
type) {
3822 Fragment instructions;
3825 if (
type.IsTopTypeForInstanceOf()) {
3827 instructions += Drop();
3834 instructions += Constant(
type);
3835 instructions += InstanceCall(
3838 return instructions;
3841 if (
type.IsRecordType()) {
3842 instructions += BuildRecordIsTest(position, RecordType::Cast(
type));
3843 return instructions;
3847 instructions += LoadInstantiatorTypeArguments();
3849 instructions += NullConstant();
3853 instructions += LoadFunctionTypeArguments();
3855 instructions += NullConstant();
3858 instructions += Constant(
type);
3860 instructions += InstanceCall(
3864 return instructions;
3867Fragment StreamingFlowGraphBuilder::BuildRecordIsTest(TokenPosition position,
3868 const RecordType&
type) {
3875 Fragment instructions;
3876 JoinEntryInstr* is_true = BuildJoinEntry();
3877 JoinEntryInstr* is_false = BuildJoinEntry();
3878 LocalVariable*
instance = MakeTemporary();
3881 if (
type.IsNullable()) {
3882 TargetEntryInstr* is_null;
3883 TargetEntryInstr* not_null;
3885 instructions += LoadLocal(
instance);
3886 instructions += BranchIfNull(&is_null, ¬_null);
3887 Fragment(is_null) + Goto(is_true);
3888 instructions.current = not_null;
3893 TargetEntryInstr* is_record;
3894 TargetEntryInstr* not_record;
3896 instructions += LoadLocal(
instance);
3897 instructions +=
B->LoadClassId();
3898 instructions += IntConstant(kRecordCid);
3899 instructions += BranchIfEqual(&is_record, ¬_record);
3900 Fragment(not_record) + Goto(is_false);
3901 instructions.current = is_record;
3906 TargetEntryInstr* same_shape;
3907 TargetEntryInstr* different_shape;
3909 instructions += LoadLocal(
instance);
3910 instructions += LoadNativeField(Slot::Record_shape());
3911 instructions += IntConstant(
type.shape().AsInt());
3912 instructions += BranchIfEqual(&same_shape, &different_shape);
3913 Fragment(different_shape) + Goto(is_false);
3914 instructions.current = same_shape;
3918 for (intptr_t
i = 0, n =
type.NumFields();
i < n; ++
i) {
3919 TargetEntryInstr* success;
3920 TargetEntryInstr* failure;
3922 instructions += LoadLocal(
instance);
3928 instructions += BranchIfEqual(&success, &failure);
3929 Fragment(failure) + Goto(is_false);
3930 instructions.current = success;
3933 instructions += Goto(is_true);
3935 JoinEntryInstr*
join = BuildJoinEntry();
3938 instructions.current = is_true;
3940 instructions += StoreLocal(TokenPosition::kNoSource, expr_temp);
3941 instructions += Drop();
3942 instructions += Goto(
join);
3944 instructions.current = is_false;
3946 instructions += StoreLocal(TokenPosition::kNoSource, expr_temp);
3947 instructions += Drop();
3948 instructions += Goto(
join);
3950 instructions.current =
join;
3951 instructions += Drop();
3952 instructions += LoadLocal(expr_temp);
3954 return instructions;
3957Fragment StreamingFlowGraphBuilder::BuildIsExpression(TokenPosition*
p) {
3958 TokenPosition position = ReadPosition();
3959 if (
p !=
nullptr) *
p = position;
3961 Fragment instructions = BuildExpression();
3963 const AbstractType&
type =
T.BuildType();
3965 instructions += BuildIsTest(position,
type);
3966 return instructions;
3969Fragment StreamingFlowGraphBuilder::BuildAsExpression(TokenPosition*
p) {
3970 TokenPosition position = ReadPosition();
3971 if (
p !=
nullptr) *
p = position;
3977 Fragment instructions = BuildExpression();
3979 const AbstractType&
type =
T.BuildType();
3980 if (is_unchecked_cast ||
3981 (
type.IsInstantiated() &&
type.IsTopTypeForSubtyping())) {
3988 instructions +=
B->AssertAssignableLoadTypeArguments(
3991 AssertAssignableInstr::kInsertedByFrontend);
3993 return instructions;
3996Fragment StreamingFlowGraphBuilder::BuildTypeLiteral(TokenPosition* position) {
3997 TokenPosition
pos = ReadPosition();
3998 if (position !=
nullptr) *position =
pos;
4000 const AbstractType&
type =
T.BuildType();
4001 Fragment instructions;
4002 if (
type.IsInstantiated()) {
4003 instructions += Constant(
type);
4006 instructions += LoadInstantiatorTypeArguments();
4008 instructions += NullConstant();
4011 instructions += LoadFunctionTypeArguments();
4013 instructions += NullConstant();
4015 instructions += InstantiateType(
type);
4017 return instructions;
4020Fragment StreamingFlowGraphBuilder::BuildThisExpression(
4021 TokenPosition* position) {
4023 if (position !=
nullptr) *position = TokenPosition::kNoSource;
4025 return LoadLocal(parsed_function()->receiver_var());
4028Fragment StreamingFlowGraphBuilder::BuildRethrow(TokenPosition*
p) {
4029 TokenPosition position = ReadPosition();
4030 if (
p !=
nullptr) *
p = position;
4032 Fragment instructions = DebugStepCheck(position);
4033 instructions += LoadLocal(catch_block()->exception_var());
4034 instructions += LoadLocal(catch_block()->stack_trace_var());
4035 instructions += RethrowException(position, catch_block()->catch_try_index());
4037 return instructions;
4040Fragment StreamingFlowGraphBuilder::BuildThrow(TokenPosition*
p) {
4041 TokenPosition position = ReadPosition();
4042 if (
p !=
nullptr) *
p = position;
4044 Fragment instructions;
4048 if (is_synthetic_error_handler) {
4049 synthetic_error_handler_depth_inc();
4052 instructions += BuildExpression();
4054 if (NeedsDebugStepCheck(stack(), position)) {
4055 instructions = DebugStepCheck(position) + instructions;
4057 instructions += ThrowException(position);
4058 ASSERT(instructions.is_closed());
4060 if (is_synthetic_error_handler) {
4061 synthetic_error_handler_depth_dec();
4064 return instructions;
4067Fragment StreamingFlowGraphBuilder::BuildListLiteral(TokenPosition*
p) {
4068 TokenPosition position = ReadPosition();
4069 if (
p !=
nullptr) *
p = position;
4071 const TypeArguments& type_arguments =
T.BuildTypeArguments(1);
4076 Fragment instructions = TranslateInstantiatedTypeArguments(type_arguments);
4080 const intptr_t kNumSpecializedListLiteralConstructors = 8;
4081 ASSERT(
length > kNumSpecializedListLiteralConstructors);
4083 LocalVariable*
type = MakeTemporary();
4084 instructions += LoadLocal(
type);
4087 instructions += LoadLocal(
type);
4088 instructions += IntConstant(
length);
4089 instructions += CreateArray();
4091 LocalVariable* array = MakeTemporary();
4093 instructions += LoadLocal(array);
4094 instructions += IntConstant(
i);
4095 instructions += BuildExpression();
4096 instructions += StoreIndexed(kArrayCid);
4099 const Class& growable_list_class =
4101 ASSERT(!growable_list_class.IsNull());
4103 const Function& factory_method =
4105 Symbols::_GrowableListLiteralFactory()));
4106 ASSERT(!factory_method.IsNull());
4108 instructions += StaticCall(position, factory_method, 2, ICData::kStatic);
4109 instructions += DropTempsPreserveTop(1);
4110 return instructions;
4113Fragment StreamingFlowGraphBuilder::BuildMapLiteral(TokenPosition*
p) {
4114 TokenPosition position = ReadPosition();
4115 if (
p !=
nullptr) *
p = position;
4117 const TypeArguments& type_arguments =
4118 T.BuildTypeArguments(2);
4121 Fragment instructions = TranslateInstantiatedTypeArguments(type_arguments);
4127 instructions += Constant(Object::empty_array());
4133 instructions += IntConstant(2 *
length);
4134 instructions += CreateArray();
4136 LocalVariable* array = MakeTemporary();
4138 instructions += LoadLocal(array);
4139 instructions += IntConstant(2 *
i);
4140 instructions += BuildExpression();
4141 instructions += StoreIndexed(kArrayCid);
4143 instructions += LoadLocal(array);
4144 instructions += IntConstant(2 *
i + 1);
4145 instructions += BuildExpression();
4146 instructions += StoreIndexed(kArrayCid);
4150 const Class& map_class =
4153 if (map_class.EnsureIsFinalized(
H.thread()) ==
Error::null()) {
4154 factory_method = map_class.LookupFactory(
4158 return instructions +
4159 StaticCall(position, factory_method, 2, ICData::kStatic);
4162Fragment StreamingFlowGraphBuilder::BuildRecordLiteral(TokenPosition*
p) {
4163 const TokenPosition position = ReadPosition();
4164 if (
p !=
nullptr) *
p = position;
4168 intptr_t named_count = -1;
4169 const Array* field_names = &Object::empty_array();
4171 AlternativeReadingScope alt(&
reader_);
4172 for (intptr_t
i = 0;
i < positional_count; ++
i) {
4176 if (named_count > 0) {
4178 for (intptr_t
i = 0;
i < named_count; ++
i) {
4184 names.MakeImmutable();
4185 field_names = &
names;
4188 const intptr_t num_fields = positional_count + named_count;
4189 const RecordShape shape =
4191 Fragment instructions;
4193 if (num_fields == 2 ||
4196 for (intptr_t
i = 0;
i < positional_count; ++
i) {
4197 instructions += BuildExpression();
4200 for (intptr_t
i = 0;
i < named_count; ++
i) {
4202 instructions += BuildExpression();
4206 instructions +=
B->AllocateSmallRecord(position, shape);
4208 return instructions;
4211 instructions +=
B->AllocateRecord(position, shape);
4212 LocalVariable* record = MakeTemporary();
4216 for (intptr_t
i = 0;
i < positional_count; ++
i, ++
pos) {
4217 instructions += LoadLocal(record);
4218 instructions += BuildExpression();
4219 instructions +=
B->StoreNativeField(
4227 for (intptr_t
i = 0;
i < named_count; ++
i, ++
pos) {
4229 instructions += LoadLocal(record);
4230 instructions += BuildExpression();
4231 instructions +=
B->StoreNativeField(
4239 return instructions;
4242Fragment StreamingFlowGraphBuilder::BuildRecordFieldGet(TokenPosition*
p,
4244 const TokenPosition position = ReadPosition();
4245 if (
p !=
nullptr) *
p = position;
4247 Fragment instructions = BuildExpression();
4248 const RecordType& record_type =
4249 RecordType::Cast(
T.BuildType());
4251 intptr_t field_index = -1;
4252 const Array& field_names =
4254 const intptr_t num_positional_fields =
4255 record_type.NumFields() - field_names.Length();
4258 for (intptr_t
i = 0, n = field_names.Length();
i < n; ++
i) {
4259 if (field_names.At(
i) == field_name.ptr()) {
4264 ASSERT(field_index >= 0 && field_index < field_names.Length());
4265 field_index += num_positional_fields;
4268 ASSERT(field_index < num_positional_fields);
4273 return instructions;
4276Fragment StreamingFlowGraphBuilder::BuildFunctionExpression() {
4279 return BuildFunctionNode(
offset);
4282Fragment StreamingFlowGraphBuilder::BuildLet(TokenPosition*
p) {
4283 const TokenPosition position = ReadPosition();
4284 if (
p !=
nullptr) *
p = position;
4285 Fragment instructions = BuildVariableDeclaration(
nullptr);
4286 instructions += BuildExpression();
4287 return instructions;
4290Fragment StreamingFlowGraphBuilder::BuildBlockExpression() {
4291 block_expression_depth_inc();
4294 Fragment instructions;
4296 instructions += EnterScope(
offset);
4300 for (intptr_t
i = 0;
i < list_length; ++
i) {
4301 instructions += BuildStatement();
4303 instructions += BuildExpression();
4304 instructions += ExitScope(
offset);
4306 block_expression_depth_dec();
4307 return instructions;
4310Fragment StreamingFlowGraphBuilder::BuildBigIntLiteral(
4311 TokenPosition* position) {
4313 if (position !=
nullptr) *position = TokenPosition::kNoSource;
4315 const String&
value =
4318 if (integer.IsNull()) {
4320 H.ReportError(
script, TokenPosition::kNoSource,
4321 "Integer literal %s is out of range",
value.ToCString());
4324 return Constant(integer);
4327Fragment StreamingFlowGraphBuilder::BuildStringLiteral(
4328 TokenPosition* position) {
4330 if (position !=
nullptr) *position = TokenPosition::kNoSource;
4332 return Constant(
H.DartSymbolPlain(
4336Fragment StreamingFlowGraphBuilder::BuildIntLiteral(uint8_t payload,
4337 TokenPosition* position) {
4339 if (position !=
nullptr) *position = TokenPosition::kNoSource;
4342 return IntConstant(
value);
4345Fragment StreamingFlowGraphBuilder::BuildIntLiteral(
bool is_negative,
4346 TokenPosition* position) {
4348 if (position !=
nullptr) *position = TokenPosition::kNoSource;
4350 int64_t
value = is_negative ? -
static_cast<int64_t
>(
ReadUInt())
4352 return IntConstant(
value);
4355Fragment StreamingFlowGraphBuilder::BuildDoubleLiteral(
4356 TokenPosition* position) {
4358 if (position !=
nullptr) *position = TokenPosition::kNoSource;
4362 return Constant(constant);
4365Fragment StreamingFlowGraphBuilder::BuildBoolLiteral(
bool value,
4366 TokenPosition* position) {
4368 if (position !=
nullptr) *position = TokenPosition::kNoSource;
4373Fragment StreamingFlowGraphBuilder::BuildNullLiteral(TokenPosition* position) {
4375 if (position !=
nullptr) *position = TokenPosition::kNoSource;
4380Fragment StreamingFlowGraphBuilder::BuildFutureNullValue(
4381 TokenPosition* position) {
4382 if (position !=
nullptr) *position = TokenPosition::kNoSource;
4383 const Class& future =
Class::Handle(
Z,
IG->object_store()->future_class());
4384 ASSERT(!future.IsNull());
4385 const auto&
error = future.EnsureIsFinalized(thread());
4389 ASSERT(!constructor.IsNull());
4391 Fragment instructions;
4392 instructions += BuildNullLiteral(position);
4393 instructions += StaticCall(TokenPosition::kNoSource, constructor,
4394 1, ICData::kStatic);
4395 return instructions;
4398Fragment StreamingFlowGraphBuilder::BuildConstantExpression(
4399 TokenPosition* position,
4401 TokenPosition
p = TokenPosition::kNoSource;
4402 if (tag == kConstantExpression) {
4405 }
else if (tag == kFileUriConstantExpression) {
4411 if (position !=
nullptr) *position =
p;
4412 const intptr_t constant_index =
ReadUInt();
4413 Fragment
result = Constant(
4418Fragment StreamingFlowGraphBuilder::BuildPartialTearoffInstantiation(
4420 const TokenPosition position = ReadPosition();
4421 if (
p !=
nullptr) *
p = position;
4425 Fragment instructions = BuildExpression();
4426 LocalVariable* original_closure = MakeTemporary();
4429 instructions += LoadLocal(original_closure);
4432 instructions += LoadLocal(original_closure);
4433 instructions += flow_graph_builder_->
LoadNativeField(Slot::Closure_context());
4434 instructions += LoadLocal(original_closure);
4436 Slot::Closure_instantiator_type_arguments());
4438 position,
true,
false,
4440 LocalVariable* new_closure = MakeTemporary();
4443 const TypeArguments& type_args =
T.BuildTypeArguments(num_type_args);
4444 instructions += TranslateInstantiatedTypeArguments(type_args);
4445 LocalVariable* type_args_vec = MakeTemporary(
"type_args");
4452 instructions += LoadLocal(original_closure);
4453 instructions += LoadLocal(type_args_vec);
4456 Z, dart_internal.LookupFunctionAllowPrivate(
4457 Symbols::BoundsCheckForPartialInstantiation()));
4458 ASSERT(!bounds_check_function.IsNull());
4459 instructions += StaticCall(TokenPosition::kNoSource, bounds_check_function, 2,
4461 instructions += Drop();
4463 instructions += LoadLocal(new_closure);
4464 instructions += LoadLocal(type_args_vec);
4466 Slot::Closure_delayed_type_arguments(),
4468 instructions += DropTemporary(&type_args_vec);
4471 instructions += LoadLocal(new_closure);
4472 instructions += LoadLocal(original_closure);
4474 Slot::Closure_function_type_arguments());
4476 Slot::Closure_function_type_arguments(),
4479 instructions += DropTempsPreserveTop(1);
4481 return instructions;
4484Fragment StreamingFlowGraphBuilder::BuildLibraryPrefixAction(
4485 TokenPosition* position,
4486 const String& selector) {
4487 const TokenPosition
pos = ReadPosition();
4488 if (position !=
nullptr) *position =
pos;
4490 const intptr_t dependency_index =
ReadUInt();
4494 const LibraryPrefix&
prefix =
4495 LibraryPrefix::CheckedZoneHandle(
Z,
dependencies.At(dependency_index));
4498 .LookupFunctionAllowPrivate(selector));
4500 Fragment instructions;
4501 instructions += Constant(
prefix);
4502 instructions += StaticCall(
pos,
function, 1, ICData::kStatic);
4503 return instructions;
4506Fragment StreamingFlowGraphBuilder::BuildAwaitExpression(
4507 TokenPosition* position) {
4509 parsed_function()->
function().IsAsyncGenerator());
4510 Fragment instructions;
4512 const TokenPosition
pos = ReadPosition();
4513 if (position !=
nullptr) *position =
pos;
4515 instructions += BuildExpression();
4518 if (
ReadTag() == kSomething) {
4519 const AbstractType&
type =
T.BuildType();
4520 if (!
type.IsType() ||
4522 FATAL(
"Unexpected type for runtime check in await: %s",
type.ToCString());
4525 const auto& type_args =
4527 if (!type_args.IsNull()) {
4529 if (!type_arg.IsTopTypeForSubtyping()) {
4530 instructions += TranslateInstantiatedTypeArguments(type_args);
4536 if (NeedsDebugStepCheck(parsed_function()->
function(),
pos)) {
4537 instructions += DebugStepCheck(
pos);
4539 instructions +=
B->Suspend(
pos, stub_id);
4540 return instructions;
4543Fragment StreamingFlowGraphBuilder::BuildFileUriExpression(
4544 TokenPosition* position) {
4547 const TokenPosition
pos = ReadPosition();
4548 if (position !=
nullptr) *position =
pos;
4550 return BuildExpression(position);
4553Fragment StreamingFlowGraphBuilder::BuildExpressionStatement(
4554 TokenPosition* position) {
4555 Fragment instructions = BuildExpression(position);
4556 instructions += Drop();
4557 return instructions;
4560Fragment StreamingFlowGraphBuilder::BuildBlock(TokenPosition* position) {
4563 Fragment instructions;
4565 instructions += EnterScope(
offset);
4566 const TokenPosition
pos = ReadPosition();
4567 if (position !=
nullptr) *position =
pos;
4572 for (intptr_t
i = 0;
i < list_length; ++
i) {
4573 if (instructions.is_open()) {
4574 instructions += BuildStatement();
4579 instructions += ExitScope(
offset);
4581 return instructions;
4584Fragment StreamingFlowGraphBuilder::BuildEmptyStatement() {
4588Fragment StreamingFlowGraphBuilder::BuildAssertBlock(TokenPosition* position) {
4589 if (!
IG->asserts()) {
4596 Fragment instructions;
4598 instructions += EnterScope(
offset);
4600 for (intptr_t
i = 0;
i < list_length; ++
i) {
4601 if (instructions.is_open()) {
4603 instructions += BuildStatement(
i == 0 ? position :
nullptr);
4608 instructions += ExitScope(
offset);
4610 return instructions;
4613Fragment StreamingFlowGraphBuilder::BuildAssertStatement(
4614 TokenPosition* position) {
4615 if (!
IG->asserts()) {
4621 TargetEntryInstr* then;
4622 TargetEntryInstr* otherwise;
4624 Fragment instructions;
4632 instructions += BuildExpression(position);
4634 const TokenPosition condition_start_offset =
4636 const TokenPosition condition_end_offset =
4639 instructions += EvaluateAssertion();
4640 instructions += RecordCoverage(condition_start_offset);
4641 instructions += CheckBoolean(condition_start_offset);
4643 instructions += BranchIfEqual(&then, &otherwise);
4645 const Class& klass =
4654 Fragment otherwise_fragment(otherwise);
4659 Z, klass.LookupStaticFunctionAllowPrivate(Symbols::ThrowNewSource()));
4665 intptr_t from_line = -1, from_column = -1;
4666 if (
script.GetTokenLocation(condition_start_offset, &from_line,
4669 intptr_t to_line, to_column;
4670 script.GetTokenLocation(condition_end_offset, &to_line, &to_column);
4672 script.GetSnippet(from_line, from_column, to_line, to_column);
4673 condition_text =
Symbols::New(thread(), condition_text);
4675 condition_text = Symbols::OptimizedOut().ptr();
4678 otherwise_fragment += Constant(condition_text);
4680 otherwise_fragment += IntConstant(from_line);
4681 otherwise_fragment += IntConstant(from_column);
4683 if (tag == kSomething) {
4684 otherwise_fragment += BuildExpression();
4688 otherwise_fragment +=
4689 StaticCall(condition_start_offset,
target, 5, ICData::kStatic);
4692 Z, klass.LookupStaticFunctionAllowPrivate(Symbols::ThrowNew()));
4695 otherwise_fragment += IntConstant(condition_start_offset.Pos());
4696 otherwise_fragment += IntConstant(condition_end_offset.Pos());
4698 if (tag == kSomething) {
4699 otherwise_fragment += BuildExpression();
4706 otherwise_fragment +=
4707 StaticCall(condition_start_offset,
target, 3, ICData::kStatic);
4709 otherwise_fragment += ThrowException(TokenPosition::kNoSource);
4710 otherwise_fragment += Drop();
4712 return Fragment(instructions.entry, then);
4715Fragment StreamingFlowGraphBuilder::BuildLabeledStatement(
4716 TokenPosition* position) {
4717 const TokenPosition
pos = ReadPosition();
4718 if (position !=
nullptr) *position =
pos;
4731 BreakableBlock block(flow_graph_builder_);
4732 Fragment instructions = BuildStatement(position);
4733 if (block.HadJumper()) {
4734 if (instructions.is_open()) {
4735 instructions += Goto(block.destination());
4737 return Fragment(instructions.entry, block.destination());
4739 return instructions;
4743Fragment StreamingFlowGraphBuilder::BuildBreakStatement(
4744 TokenPosition* position) {
4745 const TokenPosition
pos = ReadPosition();
4746 if (position !=
nullptr) *position =
pos;
4748 intptr_t target_index =
ReadUInt();
4750 TryFinallyBlock* outer_finally =
nullptr;
4751 intptr_t target_context_depth = -1;
4753 target_index, &outer_finally, &target_context_depth);
4755 Fragment instructions;
4758 if (NeedsDebugStepCheck(parsed_function()->
function(),
pos)) {
4759 instructions += DebugStepCheck(
pos);
4762 TranslateFinallyFinalizers(outer_finally, target_context_depth);
4763 if (instructions.is_open()) {
4764 instructions += Goto(destination);
4766 return instructions;
4769Fragment StreamingFlowGraphBuilder::BuildWhileStatement(
4770 TokenPosition* position) {
4772 const TokenPosition
pos = ReadPosition();
4773 if (position !=
nullptr) *position =
pos;
4775 TestFragment condition = TranslateConditionForControl();
4776 const Fragment body = BuildStatementWithBranchCoverage();
4778 Fragment body_entry(condition.CreateTrueSuccessor(flow_graph_builder_));
4782 if (body_entry.is_open()) {
4783 JoinEntryInstr*
join = BuildJoinEntry();
4784 body_entry += Goto(
join);
4786 Fragment loop(
join);
4787 loop += CheckStackOverflow(
pos);
4788 loop.current->LinkTo(condition.entry);
4792 entry = condition.entry;
4796 return Fragment(entry, condition.CreateFalseSuccessor(flow_graph_builder_));
4799Fragment StreamingFlowGraphBuilder::BuildDoStatement(TokenPosition* position) {
4801 const TokenPosition
pos = ReadPosition();
4802 if (position !=
nullptr) *position =
pos;
4804 Fragment body = BuildStatementWithBranchCoverage();
4806 if (body.is_closed()) {
4812 TestFragment condition = TranslateConditionForControl();
4814 JoinEntryInstr*
join = BuildJoinEntry();
4815 Fragment loop(
join);
4816 loop += CheckStackOverflow(
pos);
4818 loop <<= condition.entry;
4820 condition.IfTrueGoto(flow_graph_builder_,
join);
4825 condition.CreateFalseSuccessor(flow_graph_builder_));
4828Fragment StreamingFlowGraphBuilder::BuildForStatement(TokenPosition* position) {
4831 const TokenPosition
pos = ReadPosition();
4832 if (position !=
nullptr) *position =
pos;
4838 const LocalScope* context_scope =
nullptr;
4842 for (intptr_t
i = 0;
i < list_length; ++
i) {
4847 TestFragment condition;
4848 BlockEntryInstr* body_entry;
4849 BlockEntryInstr* loop_exit;
4850 if (tag != kNothing) {
4851 condition = TranslateConditionForControl();
4852 body_entry = condition.CreateTrueSuccessor(flow_graph_builder_);
4853 loop_exit = condition.CreateFalseSuccessor(flow_graph_builder_);
4855 body_entry = BuildJoinEntry();
4856 loop_exit = BuildJoinEntry();
4861 for (intptr_t
i = 0;
i < list_length; ++
i) {
4862 updates += BuildExpression();
4866 Fragment body(body_entry);
4867 body += BuildStatementWithBranchCoverage();
4869 if (body.is_open()) {
4875 if (context_scope->num_context_variables() > 0) {
4876 body += CloneContext(context_scope->context_slots());
4880 JoinEntryInstr*
join = BuildJoinEntry();
4884 Fragment loop(
join);
4885 loop += CheckStackOverflow(
pos);
4886 if (condition.entry !=
nullptr) {
4887 loop <<= condition.entry;
4889 loop += Goto(body_entry->AsJoinEntry());
4892 if (condition.entry !=
nullptr) {
4901 loop += ExitScope(
offset);
4908Fragment StreamingFlowGraphBuilder::BuildSwitchStatement(
4909 TokenPosition* position) {
4910 const TokenPosition
pos = ReadPosition();
4911 if (position !=
nullptr) *position =
pos;
4912 const bool is_exhaustive =
ReadBool();
4921 SwitchBlock block(flow_graph_builder_, case_count);
4923 Fragment instructions = BuildExpression();
4924 const AbstractType* expression_type = &Object::dynamic_type();
4925 if (
ReadTag() == kSomething) {
4926 expression_type = &
T.BuildType();
4929 StoreLocal(TokenPosition::kNoSource, scopes()->switch_variable);
4930 instructions += Drop();
4934 SwitchHelper helper(
Z,
pos, is_exhaustive, *expression_type, &block,
4939 for (intptr_t
i = 0;
i < case_count; ++
i) {
4940 helper.AddCaseBody(BuildSwitchCase(&helper,
i));
4944 switch (helper.SelectDispatchStrategy()) {
4948 instructions += BuildLinearScanSwitch(&helper);
4951 instructions += BuildBinarySearchSwitch(&helper);
4954 instructions += BuildJumpTableSwitch(&helper);
4958 return instructions;
4961Fragment StreamingFlowGraphBuilder::BuildSwitchCase(SwitchHelper* helper,
4962 intptr_t case_index) {
4972 for (intptr_t j = 0; j < expression_count; ++j) {
4973 const TokenPosition
pos = ReadPosition();
4975 const Instance&
value =
4977 helper->AddExpression(case_index,
pos,
value);
4980 const bool is_default =
ReadBool();
4981 if (is_default) helper->set_default_case(case_index);
4982 Fragment body_fragment = BuildStatementWithBranchCoverage();
4984 if (body_fragment.entry ==
nullptr) {
4986 body_fragment = NullConstant();
4987 body_fragment += Drop();
4993 if (!is_default && body_fragment.is_open() &&
4994 (case_index < (helper->case_count() - 1))) {
4997 body_fragment += Constant(
error);
4998 body_fragment += ThrowException(TokenPosition::kNoSource);
4999 body_fragment += Drop();
5014 if (expression_count > 1) {
5015 helper->switch_block()->DestinationDirect(case_index);
5018 return body_fragment;
5021Fragment StreamingFlowGraphBuilder::BuildLinearScanSwitch(
5022 SwitchHelper* helper) {
5029 SwitchBlock* block = helper->switch_block();
5030 const intptr_t case_count = helper->case_count();
5031 const intptr_t default_case = helper->default_case();
5032 const GrowableArray<Fragment>& case_bodies = helper->case_bodies();
5033 Fragment current_instructions;
5034 intptr_t expression_index = 0;
5036 for (intptr_t
i = 0;
i < case_count; ++
i) {
5037 if (
i == default_case) {
5038 ASSERT(
i == (case_count - 1));
5040 if (block->HadJumper(
i)) {
5043 JoinEntryInstr*
join = block->DestinationDirect(
i);
5044 current_instructions += Goto(
join);
5046 current_instructions = Fragment(current_instructions.entry,
join);
5047 current_instructions += case_bodies[
i];
5049 current_instructions += case_bodies[
i];
5052 JoinEntryInstr* body_join =
nullptr;
5053 if (block->HadJumper(
i)) {
5054 body_join = block->DestinationDirect(
i);
5055 case_bodies[
i] = Fragment(body_join) + case_bodies[
i];
5058 const intptr_t expression_count = helper->case_expression_counts().At(
i);
5059 for (intptr_t j = 0; j < expression_count; ++j) {
5060 TargetEntryInstr* then;
5061 TargetEntryInstr* otherwise;
5063 const SwitchExpression& expression =
5064 helper->expressions().At(expression_index++);
5065 current_instructions += Constant(expression.value());
5066 current_instructions += LoadLocal(scopes()->switch_variable);
5067 current_instructions += InstanceCall(
5068 expression.position(), Symbols::EqualOperator(), Token::kEQ,
5071 current_instructions += BranchIfTrue(&then, &otherwise,
false);
5073 Fragment then_fragment(then);
5075 if (body_join !=
nullptr) {
5079 then_fragment += Goto(body_join);
5083 then_fragment += case_bodies[
i];
5086 current_instructions = Fragment(current_instructions.entry, otherwise);
5091 if (case_count > 0 && !helper->has_default()) {
5097 Fragment& last_body = case_bodies[case_count - 1];
5098 if (last_body.is_open()) {
5099 ASSERT(current_instructions.is_open());
5100 ASSERT(current_instructions.current->IsTargetEntry());
5103 JoinEntryInstr*
join = BuildJoinEntry();
5104 current_instructions += Goto(
join);
5105 last_body += Goto(
join);
5107 current_instructions = Fragment(current_instructions.entry,
join);
5115 return current_instructions;
5118Fragment StreamingFlowGraphBuilder::BuildOptimizedSwitchPrelude(
5119 SwitchHelper* helper,
5120 JoinEntryInstr*
join) {
5121 const TokenPosition
pos = helper->position();
5122 Fragment instructions;
5124 if (helper->is_enum_switch()) {
5128 instructions += LoadLocal(scopes()->switch_variable);
5129 const Field& enum_index_field =
5131 instructions +=
B->LoadField(enum_index_field,
false);
5132 instructions += StoreLocal(
pos, scopes()->switch_variable);
5133 instructions += Drop();
5136 return instructions;
5139Fragment StreamingFlowGraphBuilder::BuildBinarySearchSwitch(
5140 SwitchHelper* helper) {
5150 SwitchBlock* block = helper->switch_block();
5151 const intptr_t case_count = helper->case_count();
5152 const intptr_t default_case = helper->default_case();
5153 const GrowableArray<Fragment>& case_bodies = helper->case_bodies();
5154 const intptr_t expression_count = helper->expressions().length();
5155 const GrowableArray<SwitchExpression*>& sorted_expressions =
5156 helper->sorted_expressions();
5157 TargetEntryInstr* then_entry;
5158 TargetEntryInstr* otherwise_entry;
5162 JoinEntryInstr*
join;
5163 if (helper->has_default()) {
5164 join = block->DestinationDirect(default_case);
5166 join = BuildJoinEntry();
5169 Fragment join_instructions(
join);
5170 if (helper->has_default()) {
5171 join_instructions += case_bodies.At(default_case);
5174 Fragment current_instructions = BuildOptimizedSwitchPrelude(helper,
join);
5176 GrowableArray<SwitchRange> stack;
5179 while (!stack.is_empty()) {
5180 const SwitchRange range = stack.RemoveLast();
5181 Fragment branch_instructions = range.branch_instructions();
5183 if (range.is_leaf()) {
5184 const intptr_t expression_index = range.min();
5185 const SwitchExpression& expression =
5186 *sorted_expressions.At(expression_index);
5188 if (!range.is_bounds_checked() &&
5189 ((helper->RequiresLowerBoundCheck() && expression_index == 0) ||
5190 (helper->RequiresUpperBoundCheck() &&
5191 expression_index == expression_count - 1))) {
5194 branch_instructions += LoadLocal(scopes()->switch_variable);
5195 branch_instructions += Constant(expression.integer());
5196 branch_instructions +=
5197 StrictCompare(expression.position(), Token::kEQ_STRICT,
5199 branch_instructions +=
5200 BranchIfTrue(&then_entry, &otherwise_entry,
false);
5202 Fragment otherwise_instructions(otherwise_entry);
5203 otherwise_instructions += Goto(
join);
5211 const intptr_t case_index = expression.case_index();
5213 if (case_index == default_case) {
5214 branch_instructions += Goto(
join);
5216 if (block->HadJumper(case_index)) {
5217 JoinEntryInstr*
join = block->DestinationDirect(case_index);
5218 branch_instructions += Goto(
join);
5220 if (
join->next() ==
nullptr) {
5223 branch_instructions = Fragment(
join);
5224 branch_instructions += case_bodies.At(case_index);
5227 branch_instructions += case_bodies.At(case_index);
5230 if (!helper->has_default() && case_index == case_count - 1) {
5231 if (branch_instructions.is_open()) {
5232 branch_instructions += Goto(
join);
5237 ASSERT(branch_instructions.is_closed());
5242 const intptr_t middle = range.min() + (range.max() - range.min()) / 2;
5243 const intptr_t
next = middle + 1;
5244 const SwitchExpression& middle_expression =
5245 *sorted_expressions.At(middle);
5246 const SwitchExpression& next_expression = *sorted_expressions.At(
next);
5248 branch_instructions += LoadLocal(scopes()->switch_variable);
5249 branch_instructions += Constant(middle_expression.integer());
5250 branch_instructions +=
5251 B->IntRelationalOp(middle_expression.position(), Token::kLTE);
5252 branch_instructions +=
5253 BranchIfTrue(&then_entry, &otherwise_entry,
false);
5255 Fragment lower_branch_instructions(then_entry);
5256 Fragment upper_branch_instructions(otherwise_entry);
5258 if (next_expression.integer().AsInt64Value() >
5259 middle_expression.integer().AsInt64Value() + 1) {
5263 upper_branch_instructions += LoadLocal(scopes()->switch_variable);
5264 upper_branch_instructions += Constant(next_expression.integer());
5265 upper_branch_instructions +=
5266 B->IntRelationalOp(next_expression.position(), Token::kGTE);
5267 upper_branch_instructions +=
5268 BranchIfTrue(&then_entry, &otherwise_entry,
false);
5270 Fragment otherwise_instructions(otherwise_entry);
5271 otherwise_instructions += Goto(
join);
5273 upper_branch_instructions = Fragment(then_entry);
5282 if (current_instructions.is_empty()) {
5283 current_instructions = branch_instructions;
5287 return Fragment(current_instructions.entry, join_instructions.current);
5290Fragment StreamingFlowGraphBuilder::BuildJumpTableSwitch(SwitchHelper* helper) {
5301 SwitchBlock* block = helper->switch_block();
5302 const TokenPosition
pos = helper->position();
5303 const intptr_t case_count = helper->case_count();
5304 const intptr_t default_case = helper->default_case();
5305 const GrowableArray<Fragment>& case_bodies = helper->case_bodies();
5306 const Integer& expression_min = helper->expression_min();
5307 const Integer& expression_max = helper->expression_max();
5308 TargetEntryInstr* then_entry;
5309 TargetEntryInstr* otherwise_entry;
5313 JoinEntryInstr*
join;
5314 if (helper->has_default()) {
5315 join = block->DestinationDirect(default_case);
5317 join = BuildJoinEntry();
5320 Fragment join_instructions(
join);
5322 Fragment current_instructions = BuildOptimizedSwitchPrelude(helper,
join);
5324 if (helper->RequiresLowerBoundCheck()) {
5325 current_instructions += LoadLocal(scopes()->switch_variable);
5326 current_instructions += Constant(expression_min);
5327 current_instructions +=
B->IntRelationalOp(
pos, Token::kGTE);
5328 current_instructions += BranchIfTrue(&then_entry, &otherwise_entry,
5330 Fragment otherwise_instructions(otherwise_entry);
5331 otherwise_instructions += Goto(
join);
5333 current_instructions = Fragment(current_instructions.entry, then_entry);
5336 if (helper->RequiresUpperBoundCheck()) {
5337 current_instructions += LoadLocal(scopes()->switch_variable);
5338 current_instructions += Constant(expression_max);
5339 current_instructions +=
B->IntRelationalOp(
pos, Token::kLTE);
5340 current_instructions += BranchIfTrue(&then_entry, &otherwise_entry,
5342 Fragment otherwise_instructions(otherwise_entry);
5343 otherwise_instructions += Goto(
join);
5345 current_instructions = Fragment(current_instructions.entry, then_entry);
5348 current_instructions += LoadLocal(scopes()->switch_variable);
5350 if (!expression_min.IsZero()) {
5352 current_instructions += Constant(expression_min);
5353 current_instructions +=
5358 const intptr_t table_size = helper->ExpressionRange();
5359 IndirectGotoInstr* indirect_goto = IndirectGoto(table_size);
5360 current_instructions <<= indirect_goto;
5361 current_instructions = current_instructions.closed();
5363 GrowableArray<TargetEntryInstr*> table_entries(table_size);
5364 table_entries.FillWith(
nullptr, 0, table_size);
5367 intptr_t expression_index = 0;
5368 for (intptr_t
i = 0;
i < case_count; ++
i) {
5369 const int expression_count = helper->case_expression_counts().At(
i);
5372 if (
i != default_case) {
5373 for (intptr_t j = 0; j < expression_count; ++j) {
5374 const SwitchExpression& expression =
5375 helper->expressions().At(expression_index++);
5376 const intptr_t table_offset =
5377 expression.integer().AsInt64Value() - expression_min.AsInt64Value();
5379 IndirectEntryInstr* indirect_entry =
5380 B->BuildIndirectEntry(table_offset, CurrentTryIndex());
5381 Fragment indirect_entry_instructions(indirect_entry);
5382 indirect_entry_instructions += Goto(block->DestinationDirect(
i));
5384 TargetEntryInstr* entry =
B->BuildTargetEntry();
5385 Fragment entry_instructions(entry);
5386 entry_instructions += Goto(indirect_entry);
5388 table_entries[table_offset] = entry;
5393 if (
i == default_case) {
5394 join_instructions += case_bodies.At(
i);
5396 Fragment case_instructions(block->DestinationDirect(
i));
5397 case_instructions += case_bodies.At(
i);
5399 if (
i == case_count - 1) {
5402 if (case_instructions.is_open()) {
5403 case_instructions += Goto(
join);
5407 ASSERT(case_instructions.is_closed());
5412 for (intptr_t
i = 0;
i < table_size;
i++) {
5413 if (table_entries.At(
i) ==
nullptr) {
5414 IndirectEntryInstr* indirect_entry =
5415 B->BuildIndirectEntry(
i, CurrentTryIndex());
5416 Fragment indirect_entry_instructions(indirect_entry);
5417 indirect_entry_instructions += Goto(
join);
5420 Fragment entry_instructions(entry);
5421 entry_instructions += Goto(indirect_entry);
5423 table_entries[
i] = entry;
5428 for (intptr_t
i = 0;
i < table_size;
i++) {
5429 indirect_goto->AddSuccessor(table_entries.At(
i));
5432 return Fragment(current_instructions.entry, join_instructions.current);
5435Fragment StreamingFlowGraphBuilder::BuildContinueSwitchStatement(
5436 TokenPosition* position) {
5437 const TokenPosition
pos = ReadPosition();
5438 if (position !=
nullptr) *position =
pos;
5440 intptr_t target_index =
ReadUInt();
5442 TryFinallyBlock* outer_finally =
nullptr;
5443 intptr_t target_context_depth = -1;
5444 JoinEntryInstr* entry = switch_block()->
Destination(
5445 target_index, &outer_finally, &target_context_depth);
5447 Fragment instructions;
5449 TranslateFinallyFinalizers(outer_finally, target_context_depth);
5450 if (instructions.is_open()) {
5451 if (NeedsDebugStepCheck(parsed_function()->
function(),
pos)) {
5452 instructions += DebugStepCheck(
pos);
5454 instructions += Goto(entry);
5456 return instructions;
5459Fragment StreamingFlowGraphBuilder::BuildIfStatement(TokenPosition* position) {
5460 const TokenPosition
pos = ReadPosition();
5461 if (position !=
nullptr) *position =
pos;
5463 TestFragment condition = TranslateConditionForControl();
5465 Fragment then_fragment(condition.CreateTrueSuccessor(flow_graph_builder_));
5466 then_fragment += BuildStatementWithBranchCoverage();
5468 Fragment otherwise_fragment(
5469 condition.CreateFalseSuccessor(flow_graph_builder_));
5470 otherwise_fragment += BuildStatementWithBranchCoverage();
5472 if (then_fragment.is_open()) {
5473 if (otherwise_fragment.is_open()) {
5474 JoinEntryInstr*
join = BuildJoinEntry();
5475 then_fragment += Goto(
join);
5476 otherwise_fragment += Goto(
join);
5477 return Fragment(condition.entry,
join);
5479 return Fragment(condition.entry, then_fragment.current);
5481 }
else if (otherwise_fragment.is_open()) {
5482 return Fragment(condition.entry, otherwise_fragment.current);
5484 return Fragment(condition.entry,
nullptr);
5488Fragment StreamingFlowGraphBuilder::BuildReturnStatement(
5489 TokenPosition* position) {
5490 const TokenPosition
pos = ReadPosition();
5491 if (position !=
nullptr) *position =
pos;
5495 bool inside_try_finally = try_finally_block() !=
nullptr;
5497 Fragment instructions;
5498 if (parsed_function()->
function().IsSyncGenerator()) {
5501 if (tag != kNothing) {
5507 (tag == kNothing ? NullConstant()
5508 : BuildExpression());
5511 if (instructions.is_open()) {
5512 if (inside_try_finally) {
5513 LocalVariable*
const finally_return_variable =
5515 ASSERT(finally_return_variable !=
nullptr);
5518 instructions += DebugStepCheck(
pos);
5520 instructions += StoreLocal(
pos, finally_return_variable);
5521 instructions += Drop();
5522 const intptr_t target_context_depth =
5523 finally_return_variable->is_captured()
5524 ? finally_return_variable->owner()->context_level()
5526 instructions += TranslateFinallyFinalizers(
nullptr, target_context_depth);
5527 if (instructions.is_open()) {
5528 const intptr_t saved_context_depth =
B->context_depth_;
5529 if (finally_return_variable->is_captured()) {
5530 B->context_depth_ = target_context_depth;
5532 instructions += LoadLocal(finally_return_variable);
5533 instructions += Return(TokenPosition::kNoSource);
5534 B->context_depth_ = saved_context_depth;
5537 instructions += Return(
pos);
5543 return instructions;
5546Fragment StreamingFlowGraphBuilder::BuildTryCatch(TokenPosition* position) {
5547 ASSERT(block_expression_depth() == 0);
5548 InlineBailout(
"kernel::FlowgraphBuilder::VisitTryCatch");
5550 const TokenPosition
pos = ReadPosition();
5551 if (position !=
nullptr) *position =
pos;
5553 intptr_t try_handler_index = AllocateTryIndex();
5554 Fragment try_body = TryCatch(try_handler_index);
5555 JoinEntryInstr* after_try = BuildJoinEntry();
5560 TryCatchBlock block(flow_graph_builder_, try_handler_index);
5561 try_body += BuildStatementWithBranchCoverage(position);
5562 try_body += Goto(after_try);
5566 const int kNeedsStracktraceBit = 1 << 0;
5567 const int kIsSyntheticBit = 1 << 1;
5570 bool needs_stacktrace =
5571 (
flags & kNeedsStracktraceBit) == kNeedsStracktraceBit;
5572 bool is_synthetic = (
flags & kIsSyntheticBit) == kIsSyntheticBit;
5576 const Array& handler_types =
5579 Fragment catch_body = CatchBlockEntry(handler_types, try_handler_index,
5580 needs_stacktrace, is_synthetic);
5582 for (intptr_t
i = 0;
i < catch_count; ++
i) {
5584 TokenPosition
pos = ReadPosition();
5585 const AbstractType& type_guard =
T.BuildType();
5586 handler_types.SetAt(
i, type_guard);
5588 Fragment catch_handler_body = EnterScope(catch_offset);
5591 if (tag == kSomething) {
5592 catch_handler_body += LoadLocal(CurrentException());
5593 catch_handler_body +=
5594 StoreLocal(TokenPosition::kNoSource,
5596 catch_handler_body += Drop();
5601 if (tag == kSomething) {
5602 catch_handler_body += LoadLocal(CurrentStackTrace());
5603 catch_handler_body +=
5604 StoreLocal(TokenPosition::kNoSource,
5606 catch_handler_body += Drop();
5611 CatchBlock block(flow_graph_builder_, CurrentException(),
5612 CurrentStackTrace(), try_handler_index);
5614 catch_handler_body += BuildStatementWithBranchCoverage();
5618 catch_handler_body += ExitScope(catch_offset);
5619 if (catch_handler_body.is_open()) {
5620 catch_handler_body += Goto(after_try);
5624 if (!type_guard.IsCatchAllType()) {
5625 catch_body += LoadLocal(CurrentException());
5628 catch_body += LoadInstantiatorTypeArguments();
5630 catch_body += NullConstant();
5633 if (!type_guard.IsInstantiated(
kFunctions)) {
5634 catch_body += LoadFunctionTypeArguments();
5636 catch_body += NullConstant();
5639 catch_body += Constant(type_guard);
5645 TargetEntryInstr* catch_entry;
5646 TargetEntryInstr* next_catch_entry;
5647 catch_body += BranchIfTrue(&catch_entry, &next_catch_entry,
false);
5649 Fragment(catch_entry) + catch_handler_body;
5650 catch_body = Fragment(next_catch_entry);
5652 catch_body += catch_handler_body;
5659 if (catch_body.is_open()) {
5660 catch_body += LoadLocal(CurrentException());
5661 catch_body += LoadLocal(CurrentStackTrace());
5662 catch_body += RethrowException(TokenPosition::kNoSource, try_handler_index);
5667 return Fragment(try_body.entry, after_try);
5670Fragment StreamingFlowGraphBuilder::BuildTryFinally(TokenPosition* position) {
5676 InlineBailout(
"kernel::FlowgraphBuilder::VisitTryFinally");
5678 const TokenPosition
pos = ReadPosition();
5679 if (position !=
nullptr) *position =
pos;
5703 intptr_t try_handler_index = AllocateTryIndex();
5704 Fragment try_body = TryCatch(try_handler_index);
5705 JoinEntryInstr* after_try = BuildJoinEntry();
5715 TryFinallyBlock tfb(flow_graph_builder_, finalizer_offset);
5716 TryCatchBlock tcb(flow_graph_builder_, try_handler_index);
5717 try_body += BuildStatementWithBranchCoverage(position);
5721 if (try_body.is_open()) {
5725 JoinEntryInstr* finally_entry = BuildJoinEntry();
5727 try_body += Goto(finally_entry);
5729 Fragment finally_body(finally_entry);
5730 finally_body += BuildStatementWithBranchCoverage();
5731 finally_body += Goto(after_try);
5738 handler_types.SetAt(0, Object::dynamic_type());
5740 Fragment finally_body = CatchBlockEntry(handler_types, try_handler_index,
5750 Value*
const saved_stack_top = stack();
5753 finally_body += BuildStatementWithBranchCoverage();
5754 if (finally_body.is_open()) {
5755 finally_body += LoadLocal(CurrentException());
5756 finally_body += LoadLocal(CurrentStackTrace());
5758 RethrowException(TokenPosition::kNoSource, try_handler_index);
5762 ASSERT(stack() ==
nullptr);
5763 set_stack(saved_stack_top);
5766 return Fragment(try_body.entry, after_try);
5769Fragment StreamingFlowGraphBuilder::BuildYieldStatement(
5770 TokenPosition* position) {
5771 const TokenPosition
pos = ReadPosition();
5772 if (position !=
nullptr) *position =
pos;
5776 Fragment instructions;
5783 ASSERT(suspend_state !=
nullptr);
5784 instructions += IntConstant(0);
5785 instructions +=
B->LoadFpRelativeSlot(
5789 instructions += LoadNativeField(Slot::SuspendState_function_data());
5791 instructions += BuildExpression();
5792 if (NeedsDebugStepCheck(parsed_function()->
function(),
pos)) {
5793 instructions += DebugStepCheck(
pos);
5796 if (parsed_function()->
function().IsAsyncGenerator()) {
5819 if (is_yield_star) {
5821 IG->object_store()->async_star_stream_controller_add_stream();
5823 add_method =
IG->object_store()->async_star_stream_controller_add();
5826 StaticCall(TokenPosition::kNoSource, add_method, 2, ICData::kNoRebind);
5828 TargetEntryInstr *return1, *continue1;
5829 instructions += BranchIfTrue(&return1, &continue1,
false);
5830 JoinEntryInstr* return_join = BuildJoinEntry();
5831 Fragment(return1) + Goto(return_join);
5832 instructions = Fragment(instructions.entry, continue1);
5835 instructions += NullConstant();
5838 TargetEntryInstr *return2, *continue2;
5839 instructions += BranchIfTrue(&return2, &continue2,
false);
5840 Fragment(return2) + Goto(return_join);
5841 instructions = Fragment(instructions.entry, continue2);
5843 Fragment do_return(return_join);
5844 do_return += TranslateFinallyFinalizers(
nullptr, -1);
5845 do_return += NullConstant();
5846 do_return += Return(TokenPosition::kNoSource);
5848 }
else if (parsed_function()->
function().IsSyncGenerator()) {
5862 if (is_yield_star) {
5863 field =
IG->object_store()->sync_star_iterator_yield_star_iterable();
5865 field =
IG->object_store()->sync_star_iterator_current();
5867 instructions +=
B->StoreFieldGuarded(field);
5871 instructions += Drop();
5876 return instructions;
5879Fragment StreamingFlowGraphBuilder::BuildVariableDeclaration(
5880 TokenPosition* position) {
5882 LocalVariable* variable = LookupVariable(kernel_position_no_tag);
5887 bool has_initializer = (
ReadTag() != kNothing);
5889 Fragment instructions;
5890 if (variable->is_late()) {
5892 if (has_initializer) {
5895 instructions += Constant(Object::sentinel());
5896 }
else if (!has_initializer) {
5897 instructions += NullConstant();
5900 instructions += BuildExpression();
5905 const TokenPosition debug_position = helper.equals_position_.IsReal()
5906 ? helper.equals_position_
5908 if (position !=
nullptr) *position = helper.position_;
5909 if (NeedsDebugStepCheck(stack(), debug_position) && !helper.IsHoisted()) {
5910 instructions = DebugStepCheck(debug_position) + instructions;
5912 instructions += StoreLocal(helper.position_, variable);
5913 instructions += Drop();
5914 return instructions;
5917Fragment StreamingFlowGraphBuilder::BuildFunctionDeclaration(
5918 TokenPosition* position) {
5920 const TokenPosition
pos = ReadPosition();
5921 if (position !=
nullptr) *position =
pos;
5926 Fragment instructions = DebugStepCheck(
pos);
5927 instructions += BuildFunctionNode(
offset);
5928 instructions += StoreLocal(
pos, LookupVariable(variable_offset));
5929 instructions += Drop();
5930 return instructions;
5933Fragment StreamingFlowGraphBuilder::BuildFunctionNode(
5934 intptr_t func_decl_offset) {
5936 const auto& member_function =
5940 thread(), func_decl_offset, member_function,
5941 parsed_function()->
function(), closure_owner_));
5944 SafepointWriteRwLocker ml(thread(),
5945 thread()->isolate_group()->program_lock());
5957 function.set_context_scope(context_scope);
5965 Fragment instructions;
5966 instructions += Constant(
function);
5967 if (scopes()->IsClosureWithEmptyContext(func_node_offset)) {
5968 instructions += NullConstant();
5970 instructions += LoadLocal(parsed_function()->current_context_var());
5973 const bool has_instantiator_type_args =
5975 if (has_instantiator_type_args) {
5976 instructions += LoadInstantiatorTypeArguments();
5981 LocalVariable*
closure = MakeTemporary();
5985 instructions += LoadLocal(
closure);
5986 instructions += LoadFunctionTypeArguments();
5988 Slot::Closure_function_type_arguments(),
5991 return instructions;
5994Fragment StreamingFlowGraphBuilder::BuildNativeEffect() {
5998 ASSERT(list_length == 0);
6000 const intptr_t positional_count =
6002 ASSERT(positional_count == 1);
6007 const intptr_t named_args_len =
6009 ASSERT(named_args_len == 0);
6012 code += NullConstant();
6016Fragment StreamingFlowGraphBuilder::BuildReachabilityFence() {
6020 ASSERT(list_length == 0);
6023 ASSERT(positional_count == 1);
6029 TokenPosition* position =
nullptr;
6030 Fragment
code = BuildExpression(position);
6033 ASSERT(named_args_len == 0);
6035 code <<=
new (
Z) ReachabilityFenceInstr(Pop());
6036 code += NullConstant();
6041 if (
error !=
nullptr) {
6049Fragment StreamingFlowGraphBuilder::BuildLoadStoreAbiSpecificInt(
6053 const intptr_t expected_argument_count = 2
6054 + (at_index ? 1 : 0)
6055 + (is_store ? 1 : 0);
6060 const TypeArguments& type_arguments =
T.BuildTypeArguments(list_length);
6065 const char*
error =
nullptr;
6066 const auto* native_type =
6074 code += BuildExpression();
6075 code += BuildExpression();
6077 code += BuildExpression();
6078 code += IntConstant(native_type->SizeInBytes());
6079 code +=
B->BinaryIntegerOp(Token::kMUL, kTagged,
true);
6080 code +=
B->BinaryIntegerOp(Token::kADD, kTagged,
true);
6083 code += BuildExpression();
6088 ASSERT(named_args_len == 0);
6101 Z, ffi_library.LookupFunctionAllowPrivate(
6105 const intptr_t static_call_arg_count = 2 + (is_store ? 1 : 0);
6106 code += StaticCall(TokenPosition::kNoSource,
target, static_call_arg_count,
6107 argument_names, ICData::kStatic);
6112Fragment StreamingFlowGraphBuilder::BuildFfiCall() {
6116 T.BuildTypeArguments(list_length);
6119 ASSERT(positional_count == argc);
6123 code += BuildExpression();
6125 code += LoadNativeField(Slot::PointerBase_data(),
6130 ASSERT(named_args_len == 0);
6133 Z, parsed_function()->
function().FfiCSignature());
6136 const char*
error =
nullptr;
6138 if (
error !=
nullptr) {
6145 code +=
B->FfiCallFunctionBody(parsed_function()->
function(), native_type,
6155Fragment StreamingFlowGraphBuilder::BuildArgumentsCachableIdempotentCall(
6161 if (types_list_length != 0) {
6162 FATAL(
"Type arguments for vm:cachable-idempotent not (yet) supported.");
6168 for (intptr_t
i = 0;
i < positional_list_length; ++
i) {
6169 code += BuildExpression();
6170 Definition* target_def =
B->Peek();
6171 if (!target_def->IsConstant()) {
6173 "Arguments for vm:cachable-idempotent must be const, argument on "
6174 "index %" Pd " is not.",
6181 if (named_args_len != 0) {
6182 FATAL(
"Named arguments for vm:cachable-idempotent not (yet) supported.");
6188Fragment StreamingFlowGraphBuilder::BuildCachableIdempotentCall(
6189 TokenPosition position,
6190 const Function&
target) {
6192 if (!parsed_function()->
function().ForceOptimize()) {
6194 "vm:cachable-idempotent functions can only be called from "
6195 "vm:force-optimize functions.");
6198 if (!target_result_type.IsIntType()) {
6199 FATAL(
"The return type vm:cachable-idempotent functions must be int.")
6207 code += flow_graph_builder_->CachableIdempotentCall(
6214Fragment StreamingFlowGraphBuilder::BuildFfiNativeCallbackFunction(
6232 const intptr_t expected_argc =
6233 static_cast<int>(has_target) +
static_cast<int>(has_exceptional_return);
6236 ASSERT(argc == expected_argc);
6239 ASSERT(list_length == 1);
6240 const TypeArguments& type_arguments =
6241 T.BuildTypeArguments(list_length);
6242 ASSERT(type_arguments.Length() == 1 && type_arguments.IsInstantiated());
6243 const FunctionType& native_sig =
6244 FunctionType::CheckedHandle(
Z, type_arguments.TypeAt(0));
6247 const intptr_t positional_count =
6249 ASSERT(positional_count == expected_argc);
6257 code += BuildExpression();
6258 Definition* target_def =
B->Peek();
6259 ASSERT(target_def->IsConstant());
6260 const Closure& target_closure =
6261 Closure::Cast(target_def->AsConstant()->value());
6262 ASSERT(!target_closure.IsNull());
6263 target = target_closure.function();
6269 if (has_exceptional_return) {
6271 code += BuildExpression();
6272 Definition* exceptional_return_def =
B->Peek();
6273 ASSERT(exceptional_return_def->IsConstant());
6274 exceptional_return ^= exceptional_return_def->AsConstant()->value().ptr();
6278 const intptr_t named_args_len =
6280 ASSERT(named_args_len == 0);
6283 const char*
error =
nullptr;
6289 exceptional_return, kind));
6295Fragment StreamingFlowGraphBuilder::BuildFfiNativeAddressOf() {
6299 ASSERT(types_length == 1);
6300 T.BuildTypeArguments(types_length);
6302 ASSERT(positional_count == 1);
6304 Fragment frag = BuildExpression();
6305 ASSERT(frag.entry->IsConstant());
6306 const auto& native_annotation =
6307 Instance::Cast(frag.entry->AsConstant()->value());
6310 const auto& pointer_class =
6312 const auto& type_arguments =
6314 Fragment
code = Constant(type_arguments);
6315 code += AllocateObject(TokenPosition::kNoSource, pointer_class, 1);
6316 code += LoadLocal(MakeTemporary());
6320 code += flow_graph_builder_->FfiNativeLookupAddress(native_annotation);
6326 ASSERT(named_arg_count == 0);
static void done(const char *config, const char *src, const char *srcOptions, const char *name)
static float next(float f)
#define ASSERT_EQUAL(expected, actual)
#define RELEASE_ASSERT(cond)
static ArrayPtr NewBoxed(intptr_t type_args_len, intptr_t num_arguments, const Array &optional_arguments_names, Heap::Space space=Heap::kOld)
static ArrayPtr New(intptr_t len, Heap::Space space=Heap::kNew)
static const Bool & False()
static const Bool & Get(bool value)
static const Bool & True()
FunctionPtr LookupStaticFunction(const String &name) const
ErrorPtr EnsureIsFinalized(Thread *thread) const
ClassPtr SuperClass(ClassTable *class_table=nullptr) const
static FunctionPtr LookupClosureFunction(const Function &member_function, intptr_t kernel_offset)
static CompileType Dynamic()
static CompilerState & Current()
static DoublePtr NewCanonical(double d)
static constexpr CompilationMode CompilationModeFrom(bool is_optimizing)
intptr_t NumOptionalParameters() const
intptr_t NumTypeParameters() const
static StringPtr CreateDynamicInvocationForwarderName(const String &name)
intptr_t NumParameters() const
static IntegerPtr NewCanonical(const String &str)
static LibraryPtr CoreLibrary()
static ClassPtr LookupCoreClass(const String &class_name)
static const String & PrivateCoreLibName(const String &member)
static LibraryPtr InternalLibrary()
static LibraryPtr FfiLibrary()
TokenPosition token_pos() const
static const char * KindToFunctionNameCString(Kind kind)
static Token::Kind RecognizeTokenKind(const String &name)
static ObjectPtr RawCast(ObjectPtr obj)
static Object & ZoneHandle()
LocalVariable * expression_temp_var() const
const Function & function() const
LocalScope * scope() const
void set_default_parameter_values(ZoneGrowableArray< const Instance * > *list)
void MarkForwardingStub(const Function *forwarding_target)
LocalVariable * ParameterVariable(intptr_t i) const
LocalVariable * suspend_state_var() const
LocalVariable * function_type_arguments() const
static RecordShape Register(Thread *thread, intptr_t num_fields, const Array &field_names)
static DART_NORETURN void LongJump(const Error &error)
static FunctionPtr ResolveDynamicFunction(Zone *zone, const Class &receiver_class, const String &function_name)
static FunctionPtr ResolveFunction(Zone *zone, const Class &receiver_class, const String &function_name)
static FunctionPtr ResolveDynamicForReceiverClassAllowPrivate(const Class &receiver_class, const String &function_name, const ArgumentsDescriptor &args_desc)
static const Slot & GetContextVariableSlotFor(Thread *thread, const LocalVariable &var)
static const Slot & GetRecordFieldSlot(Thread *thread, intptr_t offset_in_bytes)
static StringPtr New(const char *cstr, Heap::Space space=Heap::kNew)
@ kSuspendSyncStarAtYield
@ kSuspendSyncStarAtStart
static const String & Empty()
static StringPtr New(Thread *thread, const char *cstr)
static const String & Minus()
static TokenPosition Synthetic(intptr_t value)
static TypeArgumentsPtr New(intptr_t len, Heap::Space space=Heap::kOld)
AbstractTypePtr TypeAt(intptr_t index) const
Definition * definition() const
static const NativeType * FromAbstractType(Zone *zone, const AbstractType &type, const char **error)
static word field_offset(intptr_t index)
Fragment IntConstant(int64_t value)
Fragment StoreNativeField(TokenPosition position, const Slot &slot, InnerPointerAccess stores_inner_pointer, StoreFieldInstr::Kind kind=StoreFieldInstr::Kind::kOther, StoreBarrierType emit_store_barrier=kEmitStoreBarrier, compiler::Assembler::MemoryOrder memory_order=compiler::Assembler::kRelaxedNonAtomic)
Fragment ThrowException(TokenPosition position)
Fragment DebugStepCheck(TokenPosition position)
intptr_t last_used_block_id_
Fragment StoreField(const Field &field, StoreFieldInstr::Kind kind=StoreFieldInstr::Kind::kOther, StoreBarrierType emit_store_barrier=kEmitStoreBarrier)
JoinEntryInstr * BuildJoinEntry()
Fragment CheckNull(TokenPosition position, LocalVariable *receiver, const String &function_name)
Fragment StoreStaticField(TokenPosition position, const Field &field)
void InlineBailout(const char *reason)
Fragment InstantiateType(const AbstractType &type)
Fragment RecordBranchCoverage(TokenPosition position)
Fragment StoreLocal(LocalVariable *variable)
Fragment DropTempsPreserveTop(intptr_t num_temps_to_drop)
FunctionEntryInstr * BuildFunctionEntry(GraphEntryInstr *graph_entry)
intptr_t AllocateTryIndex()
Fragment LoadNativeField(const Slot &native_field, InnerPointerAccess loads_inner_pointer, bool calls_initializer=false)
Fragment StoreFieldGuarded(const Field &field, StoreFieldInstr::Kind kind=StoreFieldInstr::Kind::kOther)
Fragment LoadStaticField(const Field &field, bool calls_initializer)
Fragment BranchIfTrue(TargetEntryInstr **then_entry, TargetEntryInstr **otherwise_entry, bool negate=false)
Fragment BranchIfEqual(TargetEntryInstr **then_entry, TargetEntryInstr **otherwise_entry, bool negate=false)
Fragment RedefinitionWithType(const AbstractType &type)
Fragment RecordCoverage(TokenPosition position)
TargetEntryInstr * BuildTargetEntry()
intptr_t GetStackDepth() const
LocalVariable * MakeTemporary(const char *suffix=nullptr)
Fragment CheckStackOverflow(TokenPosition position, intptr_t stack_depth, intptr_t loop_depth)
intptr_t GetNextDeoptId()
Fragment AllocateClosure(TokenPosition position, bool has_instantiator_type_args, bool is_generic, bool is_tear_off)
Fragment StrictCompare(TokenPosition position, Token::Kind kind, bool number_check=false)
Fragment AllocateObject(TokenPosition position, const Class &klass, intptr_t argument_count)
Fragment Constant(const Object &value)
Fragment StoreIndexed(classid_t class_id)
void Push(Definition *definition)
intptr_t CurrentTryIndex() const
Fragment BranchIfNull(TargetEntryInstr **then_entry, TargetEntryInstr **otherwise_entry, bool negate=false)
Fragment DropTemporary(LocalVariable **temp)
Fragment Goto(JoinEntryInstr *destination)
Fragment AllocateContext(const ZoneGrowableArray< const Slot * > &scope)
Fragment BranchIfStrictEqual(TargetEntryInstr **then_entry, TargetEntryInstr **otherwise_entry)
JoinEntryInstr * BreakDestination(intptr_t label_index, TryFinallyBlock **outer_finally, intptr_t *context_depth)
InstancePtr ReadConstantExpression()
InstancePtr ReadConstant(intptr_t constant_index)
static bool IsRecognizedMethodForFlowGraph(const Function &function)
static FunctionPtr GetClosureFunction(Thread *thread, intptr_t func_decl_offset, const Function &member_function, const Function &parent_function, const Object &closure_owner)
friend class ProcedureHelper
void SetOffset(intptr_t offset)
const String & ReadNameAsGetterName()
const String & ReadNameAsMethodName()
void ReadUntilFunctionNode()
void SkipOptionalDartType()
void SkipListOfDartTypes()
friend class VariableDeclarationHelper
intptr_t data_program_offset_
const String & ReadNameAsSetterName()
intptr_t ReadListLength()
TokenPosition ReadPosition()
Tag ReadTag(uint8_t *payload=nullptr)
void SkipListOfExpressions()
virtual void ReportUnexpectedTag(const char *variant, Tag tag)
Tag PeekTag(uint8_t *payload=nullptr)
NameIndex ReadInterfaceMemberNameReference()
intptr_t ReaderOffset() const
void SkipInterfaceMemberNameReference()
friend class FunctionNodeHelper
NameIndex ReadCanonicalNameReference()
void SkipVariableDeclaration()
void SkipStringReference()
void SkipBytes(intptr_t skip)
StringIndex ReadStringReference()
Nullability ReadNullability()
static constexpr int kInvalidName
static bool HasEmptyPrologue(const Function &function)
Nullability ReadNullability()
Tag ReadTag(uint8_t *payload=nullptr)
static const char * TagName(Tag tag)
Tag PeekTag(uint8_t *payload=nullptr)
LocalVariable * finally_return_variable
GrowableArray< FunctionScope > function_scopes
void ReportUnexpectedTag(const char *variant, Tag tag) override
Fragment BuildStatementAt(intptr_t kernel_offset)
JoinEntryInstr * Destination(intptr_t target_index, TryFinallyBlock **outer_finally=nullptr, intptr_t *context_depth=nullptr)
static SwitchRange Leaf(intptr_t index, Fragment branch_instructions, bool is_bounds_checked=false)
static SwitchRange Branch(intptr_t min, intptr_t max, Fragment branch_instructions)
ZoneGrowableArray< TargetEntryInstr ** > SuccessorAddressArray
TestFragment Negate(bool negate)
FlutterSemanticsFlag flags
const uint8_t uint32_t uint32_t GError ** error
Dart_NativeFunction function
static bool is_bool(const Type &type)
MethodRecognizer::Kind FfiStore(const NativeType &native_type)
FunctionPtr NativeCallbackFunction(const FunctionType &c_signature, const Function &dart_target, const Instance &exceptional_return, FfiCallbackKind kind)
MethodRecognizer::Kind FfiLoad(const NativeType &native_type)
const NativeFunctionType * NativeFunctionTypeFromFunctionType(Zone *zone, const FunctionType &c_signature, const char **error)
static constexpr intptr_t kWordSize
@ kCheckCovariantTypeParameterBounds
static void ReportIfNotNull(const char *error)
static Function & GetNoSuchMethodOrDie(Thread *thread, Zone *zone, const Class &klass)
static constexpr int SpecializedIntLiteralBias
@ kYieldStatementFlagYieldStar
@ kSwitchDispatchLinearScan
@ kSwitchDispatchJumpTable
@ kSwitchDispatchBinarySearch
@ kInstanceInvocationFlagInvariant
@ kAsExpressionFlagUnchecked
@ kAsExpressionFlagTypeError
static const char *const names[]
@ kIsolateLocalClosureCallback
@ kIsolateLocalStaticCallback
bool SimpleInstanceOfType(const AbstractType &type)
DART_WARN_UNUSED_RESULT ErrorPtr VerifyEntryPoint(const Library &lib, const Object &member, const Object &annotated, std::initializer_list< EntryPointPragma > allowed_kinds)
static constexpr Representation kUnboxedAddress
static Dart_Handle LoadLibrary(Thread *T, const ExternalTypedData &td)
const char *const function_name
std::function< void()> closure
int compare(const void *untyped_lhs, const void *untyped_rhs)
static SkString join(const CommandLineFlags::StringArray &)
static constexpr Register kValue2Reg