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) {
491 ASSERT(fn_type_args !=
nullptr && closure !=
nullptr);
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_;
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() {
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);
1183 return BuildLibraryPrefixAction(position, Symbols::LoadLibrary());
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(
1479 klass,
name, args_desc,
false));
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) {
1532 return flow_graph_builder_->
Constant(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();
1915 LogicalOperator op =
static_cast<LogicalOperator
>(
ReadByte());
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) {
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)),
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)),
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))
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)),
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)),
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);
3609 LogicalOperator op =
static_cast<LogicalOperator
>(
ReadByte());
3611 op = (op == kAnd) ? kOr : kAnd;
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) {
3738 for (intptr_t i = 0; i <
length; ++i) {
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);
3924 H.thread(), compiler::target::Record::field_offset(i)));
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;
3963 Fragment instructions = BuildExpression();
3965 const AbstractType&
type =
T.BuildType();
3967 instructions += BuildIsTest(position,
type);
3968 return instructions;
3971Fragment StreamingFlowGraphBuilder::BuildAsExpression(TokenPosition* p) {
3972 TokenPosition position = ReadPosition();
3973 if (p !=
nullptr) *
p = position;
3979 Fragment instructions = BuildExpression();
3981 const AbstractType&
type =
T.BuildType();
3982 if (is_unchecked_cast ||
3983 (
type.IsInstantiated() &&
type.IsTopTypeForSubtyping())) {
3990 instructions +=
B->AssertAssignableLoadTypeArguments(
3993 AssertAssignableInstr::kInsertedByFrontend);
3995 return instructions;
3998Fragment StreamingFlowGraphBuilder::BuildTypeLiteral(TokenPosition* position) {
3999 TokenPosition
pos = ReadPosition();
4000 if (position !=
nullptr) *position =
pos;
4002 const AbstractType&
type =
T.BuildType();
4003 Fragment instructions;
4004 if (
type.IsInstantiated()) {
4005 instructions += Constant(
type);
4008 instructions += LoadInstantiatorTypeArguments();
4010 instructions += NullConstant();
4013 instructions += LoadFunctionTypeArguments();
4015 instructions += NullConstant();
4017 instructions += InstantiateType(
type);
4019 return instructions;
4022Fragment StreamingFlowGraphBuilder::BuildThisExpression(
4023 TokenPosition* position) {
4025 if (position !=
nullptr) *position = TokenPosition::kNoSource;
4027 return LoadLocal(parsed_function()->receiver_var());
4030Fragment StreamingFlowGraphBuilder::BuildRethrow(TokenPosition* p) {
4031 TokenPosition position = ReadPosition();
4032 if (p !=
nullptr) *
p = position;
4034 Fragment instructions = DebugStepCheck(position);
4035 instructions += LoadLocal(catch_block()->exception_var());
4036 instructions += LoadLocal(catch_block()->stack_trace_var());
4037 instructions += RethrowException(position, catch_block()->catch_try_index());
4039 return instructions;
4042Fragment StreamingFlowGraphBuilder::BuildThrow(TokenPosition* p) {
4043 TokenPosition position = ReadPosition();
4044 if (p !=
nullptr) *
p = position;
4046 Fragment instructions;
4050 if (is_synthetic_error_handler) {
4051 synthetic_error_handler_depth_inc();
4054 instructions += BuildExpression();
4056 if (NeedsDebugStepCheck(stack(), position)) {
4057 instructions = DebugStepCheck(position) + instructions;
4059 instructions += ThrowException(position);
4060 ASSERT(instructions.is_closed());
4062 if (is_synthetic_error_handler) {
4063 synthetic_error_handler_depth_dec();
4066 return instructions;
4069Fragment StreamingFlowGraphBuilder::BuildListLiteral(TokenPosition* p) {
4070 TokenPosition position = ReadPosition();
4071 if (p !=
nullptr) *
p = position;
4073 const TypeArguments& type_arguments =
T.BuildTypeArguments(1);
4078 Fragment instructions = TranslateInstantiatedTypeArguments(type_arguments);
4082 const intptr_t kNumSpecializedListLiteralConstructors = 8;
4083 ASSERT(
length > kNumSpecializedListLiteralConstructors);
4085 LocalVariable*
type = MakeTemporary();
4086 instructions += LoadLocal(
type);
4089 instructions += LoadLocal(
type);
4090 instructions += IntConstant(
length);
4091 instructions += CreateArray();
4093 LocalVariable* array = MakeTemporary();
4094 for (intptr_t i = 0; i <
length; ++i) {
4095 instructions += LoadLocal(array);
4096 instructions += IntConstant(i);
4097 instructions += BuildExpression();
4098 instructions += StoreIndexed(kArrayCid);
4101 const Class& growable_list_class =
4103 ASSERT(!growable_list_class.IsNull());
4105 const Function& factory_method =
4107 Symbols::_GrowableListLiteralFactory()));
4108 ASSERT(!factory_method.IsNull());
4110 instructions += StaticCall(position, factory_method, 2, ICData::kStatic);
4111 instructions += DropTempsPreserveTop(1);
4112 return instructions;
4115Fragment StreamingFlowGraphBuilder::BuildMapLiteral(TokenPosition* p) {
4116 TokenPosition position = ReadPosition();
4117 if (p !=
nullptr) *
p = position;
4119 const TypeArguments& type_arguments =
4120 T.BuildTypeArguments(2);
4123 Fragment instructions = TranslateInstantiatedTypeArguments(type_arguments);
4129 instructions += Constant(Object::empty_array());
4135 instructions += IntConstant(2 *
length);
4136 instructions += CreateArray();
4138 LocalVariable* array = MakeTemporary();
4139 for (intptr_t i = 0; i <
length; ++i) {
4140 instructions += LoadLocal(array);
4141 instructions += IntConstant(2 * i);
4142 instructions += BuildExpression();
4143 instructions += StoreIndexed(kArrayCid);
4145 instructions += LoadLocal(array);
4146 instructions += IntConstant(2 * i + 1);
4147 instructions += BuildExpression();
4148 instructions += StoreIndexed(kArrayCid);
4152 const Class& map_class =
4155 if (map_class.EnsureIsFinalized(
H.thread()) ==
Error::null()) {
4156 factory_method = map_class.LookupFactory(
4160 return instructions +
4161 StaticCall(position, factory_method, 2, ICData::kStatic);
4164Fragment StreamingFlowGraphBuilder::BuildRecordLiteral(TokenPosition* p) {
4165 const TokenPosition position = ReadPosition();
4166 if (p !=
nullptr) *
p = position;
4170 intptr_t named_count = -1;
4171 const Array* field_names = &Object::empty_array();
4173 AlternativeReadingScope alt(&
reader_);
4174 for (intptr_t i = 0; i < positional_count; ++i) {
4178 if (named_count > 0) {
4180 for (intptr_t i = 0; i < named_count; ++i) {
4186 names.MakeImmutable();
4187 field_names = &
names;
4190 const intptr_t num_fields = positional_count + named_count;
4191 const RecordShape shape =
4193 Fragment instructions;
4195 if (num_fields == 2 ||
4198 for (intptr_t i = 0; i < positional_count; ++i) {
4199 instructions += BuildExpression();
4202 for (intptr_t i = 0; i < named_count; ++i) {
4204 instructions += BuildExpression();
4208 instructions +=
B->AllocateSmallRecord(position, shape);
4210 return instructions;
4213 instructions +=
B->AllocateRecord(position, shape);
4214 LocalVariable* record = MakeTemporary();
4218 for (intptr_t i = 0; i < positional_count; ++i, ++
pos) {
4219 instructions += LoadLocal(record);
4220 instructions += BuildExpression();
4221 instructions +=
B->StoreNativeField(
4223 compiler::target::Record::field_offset(
pos)),
4229 for (intptr_t i = 0; i < named_count; ++i, ++
pos) {
4231 instructions += LoadLocal(record);
4232 instructions += BuildExpression();
4233 instructions +=
B->StoreNativeField(
4235 compiler::target::Record::field_offset(
pos)),
4241 return instructions;
4244Fragment StreamingFlowGraphBuilder::BuildRecordFieldGet(TokenPosition* p,
4246 const TokenPosition position = ReadPosition();
4247 if (p !=
nullptr) *
p = position;
4249 Fragment instructions = BuildExpression();
4250 const RecordType& record_type =
4251 RecordType::Cast(
T.BuildType());
4253 intptr_t field_index = -1;
4254 const Array& field_names =
4256 const intptr_t num_positional_fields =
4257 record_type.NumFields() - field_names.Length();
4260 for (intptr_t i = 0, n = field_names.Length(); i < n; ++i) {
4261 if (field_names.At(i) == field_name.ptr()) {
4266 ASSERT(field_index >= 0 && field_index < field_names.Length());
4267 field_index += num_positional_fields;
4270 ASSERT(field_index < num_positional_fields);
4274 thread(), compiler::target::Record::field_offset(field_index)));
4275 return instructions;
4278Fragment StreamingFlowGraphBuilder::BuildFunctionExpression() {
4281 return BuildFunctionNode(
offset);
4284Fragment StreamingFlowGraphBuilder::BuildLet(TokenPosition* p) {
4285 const TokenPosition position = ReadPosition();
4286 if (p !=
nullptr) *
p = position;
4287 Fragment instructions = BuildVariableDeclaration(
nullptr);
4288 instructions += BuildExpression();
4289 return instructions;
4292Fragment StreamingFlowGraphBuilder::BuildBlockExpression() {
4293 block_expression_depth_inc();
4296 Fragment instructions;
4298 instructions += EnterScope(
offset);
4302 for (intptr_t i = 0; i < list_length; ++i) {
4303 instructions += BuildStatement();
4305 instructions += BuildExpression();
4306 instructions += ExitScope(
offset);
4308 block_expression_depth_dec();
4309 return instructions;
4312Fragment StreamingFlowGraphBuilder::BuildBigIntLiteral(
4313 TokenPosition* position) {
4315 if (position !=
nullptr) *position = TokenPosition::kNoSource;
4317 const String&
value =
4320 if (integer.IsNull()) {
4322 H.ReportError(script, TokenPosition::kNoSource,
4323 "Integer literal %s is out of range",
value.ToCString());
4326 return Constant(integer);
4329Fragment StreamingFlowGraphBuilder::BuildStringLiteral(
4330 TokenPosition* position) {
4332 if (position !=
nullptr) *position = TokenPosition::kNoSource;
4334 return Constant(
H.DartSymbolPlain(
4338Fragment StreamingFlowGraphBuilder::BuildIntLiteral(uint8_t payload,
4339 TokenPosition* position) {
4341 if (position !=
nullptr) *position = TokenPosition::kNoSource;
4344 return IntConstant(value);
4347Fragment StreamingFlowGraphBuilder::BuildIntLiteral(
bool is_negative,
4348 TokenPosition* position) {
4350 if (position !=
nullptr) *position = TokenPosition::kNoSource;
4352 int64_t
value = is_negative ? -
static_cast<int64_t
>(
ReadUInt())
4354 return IntConstant(value);
4357Fragment StreamingFlowGraphBuilder::BuildDoubleLiteral(
4358 TokenPosition* position) {
4360 if (position !=
nullptr) *position = TokenPosition::kNoSource;
4364 return Constant(constant);
4367Fragment StreamingFlowGraphBuilder::BuildBoolLiteral(
bool value,
4368 TokenPosition* position) {
4370 if (position !=
nullptr) *position = TokenPosition::kNoSource;
4375Fragment StreamingFlowGraphBuilder::BuildNullLiteral(TokenPosition* position) {
4377 if (position !=
nullptr) *position = TokenPosition::kNoSource;
4382Fragment StreamingFlowGraphBuilder::BuildFutureNullValue(
4383 TokenPosition* position) {
4384 if (position !=
nullptr) *position = TokenPosition::kNoSource;
4385 const Class& future =
Class::Handle(
Z,
IG->object_store()->future_class());
4386 ASSERT(!future.IsNull());
4387 const auto&
error = future.EnsureIsFinalized(thread());
4391 ASSERT(!constructor.IsNull());
4393 Fragment instructions;
4394 instructions += BuildNullLiteral(position);
4395 instructions += StaticCall(TokenPosition::kNoSource, constructor,
4396 1, ICData::kStatic);
4397 return instructions;
4400Fragment StreamingFlowGraphBuilder::BuildConstantExpression(
4401 TokenPosition* position,
4403 TokenPosition
p = TokenPosition::kNoSource;
4404 if (tag == kConstantExpression) {
4407 }
else if (tag == kFileUriConstantExpression) {
4413 if (position !=
nullptr) *position =
p;
4414 const intptr_t constant_index =
ReadUInt();
4415 Fragment
result = Constant(
4420Fragment StreamingFlowGraphBuilder::BuildPartialTearoffInstantiation(
4422 const TokenPosition position = ReadPosition();
4423 if (p !=
nullptr) *
p = position;
4427 Fragment instructions = BuildExpression();
4428 LocalVariable* original_closure = MakeTemporary();
4431 instructions += LoadLocal(original_closure);
4434 instructions += LoadLocal(original_closure);
4435 instructions += flow_graph_builder_->
LoadNativeField(Slot::Closure_context());
4436 instructions += LoadLocal(original_closure);
4438 Slot::Closure_instantiator_type_arguments());
4440 position,
true,
false,
4442 LocalVariable* new_closure = MakeTemporary();
4445 const TypeArguments& type_args =
T.BuildTypeArguments(num_type_args);
4446 instructions += TranslateInstantiatedTypeArguments(type_args);
4447 LocalVariable* type_args_vec = MakeTemporary(
"type_args");
4454 instructions += LoadLocal(original_closure);
4455 instructions += LoadLocal(type_args_vec);
4458 Z, dart_internal.LookupFunctionAllowPrivate(
4459 Symbols::BoundsCheckForPartialInstantiation()));
4460 ASSERT(!bounds_check_function.IsNull());
4461 instructions += StaticCall(TokenPosition::kNoSource, bounds_check_function, 2,
4463 instructions += Drop();
4465 instructions += LoadLocal(new_closure);
4466 instructions += LoadLocal(type_args_vec);
4468 Slot::Closure_delayed_type_arguments(),
4470 instructions += DropTemporary(&type_args_vec);
4473 instructions += LoadLocal(new_closure);
4474 instructions += LoadLocal(original_closure);
4476 Slot::Closure_function_type_arguments());
4478 Slot::Closure_function_type_arguments(),
4481 instructions += DropTempsPreserveTop(1);
4483 return instructions;
4486Fragment StreamingFlowGraphBuilder::BuildLibraryPrefixAction(
4487 TokenPosition* position,
4488 const String& selector) {
4489 const TokenPosition
pos = ReadPosition();
4490 if (position !=
nullptr) *position =
pos;
4492 const intptr_t dependency_index =
ReadUInt();
4496 const LibraryPrefix&
prefix =
4497 LibraryPrefix::CheckedZoneHandle(
Z,
dependencies.At(dependency_index));
4500 .LookupFunctionAllowPrivate(selector));
4502 Fragment instructions;
4503 instructions += Constant(prefix);
4504 instructions += StaticCall(
pos,
function, 1, ICData::kStatic);
4505 return instructions;
4508Fragment StreamingFlowGraphBuilder::BuildAwaitExpression(
4509 TokenPosition* position) {
4511 parsed_function()->
function().IsAsyncGenerator());
4512 Fragment instructions;
4514 const TokenPosition
pos = ReadPosition();
4515 if (position !=
nullptr) *position =
pos;
4517 instructions += BuildExpression();
4520 if (
ReadTag() == kSomething) {
4521 const AbstractType&
type =
T.BuildType();
4522 if (!
type.IsType() ||
4524 FATAL(
"Unexpected type for runtime check in await: %s",
type.ToCString());
4527 const auto& type_args =
4529 if (!type_args.IsNull()) {
4531 if (!type_arg.IsTopTypeForSubtyping()) {
4532 instructions += TranslateInstantiatedTypeArguments(type_args);
4538 if (NeedsDebugStepCheck(parsed_function()->
function(),
pos)) {
4539 instructions += DebugStepCheck(
pos);
4541 instructions +=
B->Suspend(
pos, stub_id);
4542 return instructions;
4545Fragment StreamingFlowGraphBuilder::BuildFileUriExpression(
4546 TokenPosition* position) {
4549 const TokenPosition
pos = ReadPosition();
4550 if (position !=
nullptr) *position =
pos;
4552 return BuildExpression(position);
4555Fragment StreamingFlowGraphBuilder::BuildExpressionStatement(
4556 TokenPosition* position) {
4557 Fragment instructions = BuildExpression(position);
4558 instructions += Drop();
4559 return instructions;
4562Fragment StreamingFlowGraphBuilder::BuildBlock(TokenPosition* position) {
4565 Fragment instructions;
4567 instructions += EnterScope(
offset);
4568 const TokenPosition
pos = ReadPosition();
4569 if (position !=
nullptr) *position =
pos;
4574 for (intptr_t i = 0; i < list_length; ++i) {
4575 if (instructions.is_open()) {
4576 instructions += BuildStatement();
4581 instructions += ExitScope(
offset);
4583 return instructions;
4586Fragment StreamingFlowGraphBuilder::BuildEmptyStatement() {
4590Fragment StreamingFlowGraphBuilder::BuildAssertBlock(TokenPosition* position) {
4591 if (!
IG->asserts()) {
4598 Fragment instructions;
4600 instructions += EnterScope(
offset);
4602 for (intptr_t i = 0; i < list_length; ++i) {
4603 if (instructions.is_open()) {
4605 instructions += BuildStatement(i == 0 ? position : nullptr);
4610 instructions += ExitScope(
offset);
4612 return instructions;
4615Fragment StreamingFlowGraphBuilder::BuildAssertStatement(
4616 TokenPosition* position) {
4617 if (!
IG->asserts()) {
4623 TargetEntryInstr* then;
4624 TargetEntryInstr* otherwise;
4626 Fragment instructions;
4634 instructions += BuildExpression(position);
4636 const TokenPosition condition_start_offset =
4638 const TokenPosition condition_end_offset =
4641 instructions += EvaluateAssertion();
4642 instructions += RecordCoverage(condition_start_offset);
4643 instructions += CheckBoolean(condition_start_offset);
4645 instructions += BranchIfEqual(&then, &otherwise);
4647 const Class& klass =
4656 Fragment otherwise_fragment(otherwise);
4661 Z, klass.LookupStaticFunctionAllowPrivate(Symbols::ThrowNewSource()));
4667 intptr_t from_line = -1, from_column = -1;
4668 if (
script.GetTokenLocation(condition_start_offset, &from_line,
4671 intptr_t to_line, to_column;
4672 script.GetTokenLocation(condition_end_offset, &to_line, &to_column);
4674 script.GetSnippet(from_line, from_column, to_line, to_column);
4675 condition_text =
Symbols::New(thread(), condition_text);
4677 condition_text = Symbols::OptimizedOut().ptr();
4680 otherwise_fragment += Constant(condition_text);
4682 otherwise_fragment += IntConstant(from_line);
4683 otherwise_fragment += IntConstant(from_column);
4685 if (tag == kSomething) {
4686 otherwise_fragment += BuildExpression();
4690 otherwise_fragment +=
4691 StaticCall(condition_start_offset,
target, 5, ICData::kStatic);
4694 Z, klass.LookupStaticFunctionAllowPrivate(Symbols::ThrowNew()));
4697 otherwise_fragment += IntConstant(condition_start_offset.Pos());
4698 otherwise_fragment += IntConstant(condition_end_offset.Pos());
4700 if (tag == kSomething) {
4701 otherwise_fragment += BuildExpression();
4708 otherwise_fragment +=
4709 StaticCall(condition_start_offset,
target, 3, ICData::kStatic);
4711 otherwise_fragment += ThrowException(TokenPosition::kNoSource);
4712 otherwise_fragment += Drop();
4714 return Fragment(instructions.entry, then);
4717Fragment StreamingFlowGraphBuilder::BuildLabeledStatement(
4718 TokenPosition* position) {
4719 const TokenPosition
pos = ReadPosition();
4720 if (position !=
nullptr) *position =
pos;
4733 BreakableBlock block(flow_graph_builder_);
4734 Fragment instructions = BuildStatement(position);
4735 if (block.HadJumper()) {
4736 if (instructions.is_open()) {
4737 instructions += Goto(block.destination());
4739 return Fragment(instructions.entry, block.destination());
4741 return instructions;
4745Fragment StreamingFlowGraphBuilder::BuildBreakStatement(
4746 TokenPosition* position) {
4747 const TokenPosition
pos = ReadPosition();
4748 if (position !=
nullptr) *position =
pos;
4750 intptr_t target_index =
ReadUInt();
4752 TryFinallyBlock* outer_finally =
nullptr;
4753 intptr_t target_context_depth = -1;
4755 target_index, &outer_finally, &target_context_depth);
4757 Fragment instructions;
4760 if (NeedsDebugStepCheck(parsed_function()->
function(),
pos)) {
4761 instructions += DebugStepCheck(
pos);
4764 TranslateFinallyFinalizers(outer_finally, target_context_depth);
4765 if (instructions.is_open()) {
4766 instructions += Goto(destination);
4768 return instructions;
4771Fragment StreamingFlowGraphBuilder::BuildWhileStatement(
4772 TokenPosition* position) {
4774 const TokenPosition
pos = ReadPosition();
4775 if (position !=
nullptr) *position =
pos;
4777 TestFragment condition = TranslateConditionForControl();
4778 const Fragment body = BuildStatementWithBranchCoverage();
4780 Fragment body_entry(condition.CreateTrueSuccessor(flow_graph_builder_));
4784 if (body_entry.is_open()) {
4785 JoinEntryInstr*
join = BuildJoinEntry();
4786 body_entry += Goto(join);
4788 Fragment loop(join);
4789 loop += CheckStackOverflow(
pos);
4790 loop.current->LinkTo(condition.entry);
4792 entry = Goto(join).
entry;
4794 entry = condition.entry;
4798 return Fragment(entry, condition.CreateFalseSuccessor(flow_graph_builder_));
4801Fragment StreamingFlowGraphBuilder::BuildDoStatement(TokenPosition* position) {
4803 const TokenPosition
pos = ReadPosition();
4804 if (position !=
nullptr) *position =
pos;
4806 Fragment body = BuildStatementWithBranchCoverage();
4808 if (body.is_closed()) {
4814 TestFragment condition = TranslateConditionForControl();
4816 JoinEntryInstr*
join = BuildJoinEntry();
4817 Fragment loop(join);
4818 loop += CheckStackOverflow(
pos);
4820 loop <<= condition.entry;
4822 condition.IfTrueGoto(flow_graph_builder_, join);
4827 condition.CreateFalseSuccessor(flow_graph_builder_));
4830Fragment StreamingFlowGraphBuilder::BuildForStatement(TokenPosition* position) {
4833 const TokenPosition
pos = ReadPosition();
4834 if (position !=
nullptr) *position =
pos;
4840 const LocalScope* context_scope =
nullptr;
4844 for (intptr_t i = 0; i < list_length; ++i) {
4849 TestFragment condition;
4850 BlockEntryInstr* body_entry;
4851 BlockEntryInstr* loop_exit;
4852 if (tag != kNothing) {
4853 condition = TranslateConditionForControl();
4854 body_entry = condition.CreateTrueSuccessor(flow_graph_builder_);
4855 loop_exit = condition.CreateFalseSuccessor(flow_graph_builder_);
4857 body_entry = BuildJoinEntry();
4858 loop_exit = BuildJoinEntry();
4863 for (intptr_t i = 0; i < list_length; ++i) {
4864 updates += BuildExpression();
4868 Fragment body(body_entry);
4869 body += BuildStatementWithBranchCoverage();
4871 if (body.is_open()) {
4877 if (context_scope->num_context_variables() > 0) {
4878 body += CloneContext(context_scope->context_slots());
4882 JoinEntryInstr*
join = BuildJoinEntry();
4886 Fragment loop(join);
4887 loop += CheckStackOverflow(
pos);
4888 if (condition.entry !=
nullptr) {
4889 loop <<= condition.entry;
4891 loop += Goto(body_entry->AsJoinEntry());
4894 if (condition.entry !=
nullptr) {
4903 loop += ExitScope(
offset);
4910Fragment StreamingFlowGraphBuilder::BuildSwitchStatement(
4911 TokenPosition* position) {
4912 const TokenPosition
pos = ReadPosition();
4913 if (position !=
nullptr) *position =
pos;
4914 const bool is_exhaustive =
ReadBool();
4923 SwitchBlock block(flow_graph_builder_, case_count);
4925 Fragment instructions = BuildExpression();
4926 const AbstractType* expression_type = &Object::dynamic_type();
4927 if (
ReadTag() == kSomething) {
4928 expression_type = &
T.BuildType();
4931 StoreLocal(TokenPosition::kNoSource, scopes()->switch_variable);
4932 instructions += Drop();
4936 SwitchHelper helper(
Z,
pos, is_exhaustive, *expression_type, &block,
4941 for (intptr_t i = 0; i < case_count; ++i) {
4942 helper.AddCaseBody(BuildSwitchCase(&helper, i));
4946 switch (helper.SelectDispatchStrategy()) {
4950 instructions += BuildLinearScanSwitch(&helper);
4953 instructions += BuildBinarySearchSwitch(&helper);
4956 instructions += BuildJumpTableSwitch(&helper);
4960 return instructions;
4963Fragment StreamingFlowGraphBuilder::BuildSwitchCase(SwitchHelper* helper,
4964 intptr_t case_index) {
4974 for (intptr_t j = 0; j < expression_count; ++j) {
4975 const TokenPosition
pos = ReadPosition();
4977 const Instance&
value =
4979 helper->AddExpression(case_index,
pos, value);
4982 const bool is_default =
ReadBool();
4983 if (is_default) helper->set_default_case(case_index);
4984 Fragment body_fragment = BuildStatementWithBranchCoverage();
4986 if (body_fragment.entry ==
nullptr) {
4988 body_fragment = NullConstant();
4989 body_fragment += Drop();
4995 if (!is_default && body_fragment.is_open() &&
4996 (case_index < (helper->case_count() - 1))) {
4999 body_fragment += Constant(
error);
5000 body_fragment += ThrowException(TokenPosition::kNoSource);
5001 body_fragment += Drop();
5016 if (expression_count > 1) {
5017 helper->switch_block()->DestinationDirect(case_index);
5020 return body_fragment;
5023Fragment StreamingFlowGraphBuilder::BuildLinearScanSwitch(
5024 SwitchHelper* helper) {
5031 SwitchBlock* block = helper->switch_block();
5032 const intptr_t case_count = helper->case_count();
5033 const intptr_t default_case = helper->default_case();
5034 const GrowableArray<Fragment>& case_bodies = helper->case_bodies();
5035 Fragment current_instructions;
5036 intptr_t expression_index = 0;
5038 for (intptr_t i = 0; i < case_count; ++i) {
5039 if (i == default_case) {
5040 ASSERT(i == (case_count - 1));
5042 if (block->HadJumper(i)) {
5045 JoinEntryInstr*
join = block->DestinationDirect(i);
5046 current_instructions += Goto(join);
5048 current_instructions = Fragment(current_instructions.entry, join);
5049 current_instructions += case_bodies[i];
5051 current_instructions += case_bodies[i];
5054 JoinEntryInstr* body_join =
nullptr;
5055 if (block->HadJumper(i)) {
5056 body_join = block->DestinationDirect(i);
5057 case_bodies[i] = Fragment(body_join) + case_bodies[i];
5060 const intptr_t expression_count = helper->case_expression_counts().At(i);
5061 for (intptr_t j = 0; j < expression_count; ++j) {
5062 TargetEntryInstr* then;
5063 TargetEntryInstr* otherwise;
5065 const SwitchExpression& expression =
5066 helper->expressions().At(expression_index++);
5067 current_instructions += Constant(expression.value());
5068 current_instructions += LoadLocal(scopes()->switch_variable);
5069 current_instructions += InstanceCall(
5070 expression.position(), Symbols::EqualOperator(), Token::kEQ,
5073 current_instructions += BranchIfTrue(&then, &otherwise,
false);
5075 Fragment then_fragment(then);
5077 if (body_join !=
nullptr) {
5081 then_fragment += Goto(body_join);
5085 then_fragment += case_bodies[i];
5088 current_instructions = Fragment(current_instructions.entry, otherwise);
5093 if (case_count > 0 && !helper->has_default()) {
5099 Fragment& last_body = case_bodies[case_count - 1];
5100 if (last_body.is_open()) {
5101 ASSERT(current_instructions.is_open());
5102 ASSERT(current_instructions.current->IsTargetEntry());
5105 JoinEntryInstr*
join = BuildJoinEntry();
5106 current_instructions += Goto(join);
5107 last_body += Goto(join);
5109 current_instructions = Fragment(current_instructions.entry, join);
5117 return current_instructions;
5120Fragment StreamingFlowGraphBuilder::BuildOptimizedSwitchPrelude(
5121 SwitchHelper* helper,
5122 JoinEntryInstr* join) {
5123 const TokenPosition
pos = helper->position();
5124 Fragment instructions;
5126 if (helper->is_enum_switch()) {
5130 instructions += LoadLocal(scopes()->switch_variable);
5131 const Field& enum_index_field =
5133 instructions +=
B->LoadField(enum_index_field,
false);
5134 instructions += StoreLocal(
pos, scopes()->switch_variable);
5135 instructions += Drop();
5138 return instructions;
5141Fragment StreamingFlowGraphBuilder::BuildBinarySearchSwitch(
5142 SwitchHelper* helper) {
5152 SwitchBlock* block = helper->switch_block();
5153 const intptr_t case_count = helper->case_count();
5154 const intptr_t default_case = helper->default_case();
5155 const GrowableArray<Fragment>& case_bodies = helper->case_bodies();
5156 const intptr_t expression_count = helper->expressions().length();
5157 const GrowableArray<SwitchExpression*>& sorted_expressions =
5158 helper->sorted_expressions();
5159 TargetEntryInstr* then_entry;
5160 TargetEntryInstr* otherwise_entry;
5164 JoinEntryInstr*
join;
5165 if (helper->has_default()) {
5166 join = block->DestinationDirect(default_case);
5168 join = BuildJoinEntry();
5171 Fragment join_instructions(join);
5172 if (helper->has_default()) {
5173 join_instructions += case_bodies.At(default_case);
5176 Fragment current_instructions = BuildOptimizedSwitchPrelude(helper, join);
5178 GrowableArray<SwitchRange> stack;
5181 while (!stack.is_empty()) {
5182 const SwitchRange range = stack.RemoveLast();
5183 Fragment branch_instructions = range.branch_instructions();
5185 if (range.is_leaf()) {
5186 const intptr_t expression_index = range.min();
5187 const SwitchExpression& expression =
5188 *sorted_expressions.At(expression_index);
5190 if (!range.is_bounds_checked() &&
5191 ((helper->RequiresLowerBoundCheck() && expression_index == 0) ||
5192 (helper->RequiresUpperBoundCheck() &&
5193 expression_index == expression_count - 1))) {
5196 branch_instructions += LoadLocal(scopes()->switch_variable);
5197 branch_instructions += Constant(expression.integer());
5198 branch_instructions +=
5199 StrictCompare(expression.position(), Token::kEQ_STRICT,
5201 branch_instructions +=
5202 BranchIfTrue(&then_entry, &otherwise_entry,
false);
5204 Fragment otherwise_instructions(otherwise_entry);
5205 otherwise_instructions += Goto(join);
5213 const intptr_t case_index = expression.case_index();
5215 if (case_index == default_case) {
5216 branch_instructions += Goto(join);
5218 if (block->HadJumper(case_index)) {
5219 JoinEntryInstr*
join = block->DestinationDirect(case_index);
5220 branch_instructions += Goto(join);
5222 if (
join->next() ==
nullptr) {
5225 branch_instructions = Fragment(join);
5226 branch_instructions += case_bodies.At(case_index);
5229 branch_instructions += case_bodies.At(case_index);
5232 if (!helper->has_default() && case_index == case_count - 1) {
5233 if (branch_instructions.is_open()) {
5234 branch_instructions += Goto(join);
5239 ASSERT(branch_instructions.is_closed());
5244 const intptr_t middle = range.min() + (range.max() - range.min()) / 2;
5245 const intptr_t
next = middle + 1;
5246 const SwitchExpression& middle_expression =
5247 *sorted_expressions.At(middle);
5248 const SwitchExpression& next_expression = *sorted_expressions.At(
next);
5250 branch_instructions += LoadLocal(scopes()->switch_variable);
5251 branch_instructions += Constant(middle_expression.integer());
5252 branch_instructions +=
5253 B->IntRelationalOp(middle_expression.position(), Token::kLTE);
5254 branch_instructions +=
5255 BranchIfTrue(&then_entry, &otherwise_entry,
false);
5257 Fragment lower_branch_instructions(then_entry);
5258 Fragment upper_branch_instructions(otherwise_entry);
5260 if (next_expression.integer().AsInt64Value() >
5261 middle_expression.integer().AsInt64Value() + 1) {
5265 upper_branch_instructions += LoadLocal(scopes()->switch_variable);
5266 upper_branch_instructions += Constant(next_expression.integer());
5267 upper_branch_instructions +=
5268 B->IntRelationalOp(next_expression.position(), Token::kGTE);
5269 upper_branch_instructions +=
5270 BranchIfTrue(&then_entry, &otherwise_entry,
false);
5272 Fragment otherwise_instructions(otherwise_entry);
5273 otherwise_instructions += Goto(join);
5275 upper_branch_instructions = Fragment(then_entry);
5284 if (current_instructions.is_empty()) {
5285 current_instructions = branch_instructions;
5289 return Fragment(current_instructions.entry, join_instructions.current);
5292Fragment StreamingFlowGraphBuilder::BuildJumpTableSwitch(SwitchHelper* helper) {
5303 SwitchBlock* block = helper->switch_block();
5304 const TokenPosition
pos = helper->position();
5305 const intptr_t case_count = helper->case_count();
5306 const intptr_t default_case = helper->default_case();
5307 const GrowableArray<Fragment>& case_bodies = helper->case_bodies();
5308 const Integer& expression_min = helper->expression_min();
5309 const Integer& expression_max = helper->expression_max();
5310 TargetEntryInstr* then_entry;
5311 TargetEntryInstr* otherwise_entry;
5315 JoinEntryInstr*
join;
5316 if (helper->has_default()) {
5317 join = block->DestinationDirect(default_case);
5319 join = BuildJoinEntry();
5322 Fragment join_instructions(join);
5324 Fragment current_instructions = BuildOptimizedSwitchPrelude(helper, join);
5326 if (helper->RequiresLowerBoundCheck()) {
5327 current_instructions += LoadLocal(scopes()->switch_variable);
5328 current_instructions += Constant(expression_min);
5329 current_instructions +=
B->IntRelationalOp(
pos, Token::kGTE);
5330 current_instructions += BranchIfTrue(&then_entry, &otherwise_entry,
5332 Fragment otherwise_instructions(otherwise_entry);
5333 otherwise_instructions += Goto(join);
5335 current_instructions = Fragment(current_instructions.entry, then_entry);
5338 if (helper->RequiresUpperBoundCheck()) {
5339 current_instructions += LoadLocal(scopes()->switch_variable);
5340 current_instructions += Constant(expression_max);
5341 current_instructions +=
B->IntRelationalOp(
pos, Token::kLTE);
5342 current_instructions += BranchIfTrue(&then_entry, &otherwise_entry,
5344 Fragment otherwise_instructions(otherwise_entry);
5345 otherwise_instructions += Goto(join);
5347 current_instructions = Fragment(current_instructions.entry, then_entry);
5350 current_instructions += LoadLocal(scopes()->switch_variable);
5352 if (!expression_min.IsZero()) {
5354 current_instructions += Constant(expression_min);
5355 current_instructions +=
5360 const intptr_t table_size = helper->ExpressionRange();
5361 IndirectGotoInstr* indirect_goto = IndirectGoto(table_size);
5362 current_instructions <<= indirect_goto;
5363 current_instructions = current_instructions.closed();
5365 GrowableArray<TargetEntryInstr*> table_entries(table_size);
5366 table_entries.FillWith(
nullptr, 0, table_size);
5369 intptr_t expression_index = 0;
5370 for (intptr_t i = 0; i < case_count; ++i) {
5371 const int expression_count = helper->case_expression_counts().At(i);
5374 if (i != default_case) {
5375 for (intptr_t j = 0; j < expression_count; ++j) {
5376 const SwitchExpression& expression =
5377 helper->expressions().At(expression_index++);
5378 const intptr_t table_offset =
5379 expression.integer().AsInt64Value() - expression_min.AsInt64Value();
5381 IndirectEntryInstr* indirect_entry =
5382 B->BuildIndirectEntry(table_offset, CurrentTryIndex());
5383 Fragment indirect_entry_instructions(indirect_entry);
5384 indirect_entry_instructions += Goto(block->DestinationDirect(i));
5386 TargetEntryInstr* entry =
B->BuildTargetEntry();
5387 Fragment entry_instructions(entry);
5388 entry_instructions += Goto(indirect_entry);
5390 table_entries[table_offset] = entry;
5395 if (i == default_case) {
5396 join_instructions += case_bodies.At(i);
5398 Fragment case_instructions(block->DestinationDirect(i));
5399 case_instructions += case_bodies.At(i);
5401 if (i == case_count - 1) {
5404 if (case_instructions.is_open()) {
5405 case_instructions += Goto(join);
5409 ASSERT(case_instructions.is_closed());
5414 for (intptr_t i = 0; i < table_size; i++) {
5415 if (table_entries.At(i) ==
nullptr) {
5416 IndirectEntryInstr* indirect_entry =
5417 B->BuildIndirectEntry(i, CurrentTryIndex());
5418 Fragment indirect_entry_instructions(indirect_entry);
5419 indirect_entry_instructions += Goto(join);
5422 Fragment entry_instructions(entry);
5423 entry_instructions += Goto(indirect_entry);
5425 table_entries[i] = entry;
5430 for (intptr_t i = 0; i < table_size; i++) {
5431 indirect_goto->AddSuccessor(table_entries.At(i));
5434 return Fragment(current_instructions.entry, join_instructions.current);
5437Fragment StreamingFlowGraphBuilder::BuildContinueSwitchStatement(
5438 TokenPosition* position) {
5439 const TokenPosition
pos = ReadPosition();
5440 if (position !=
nullptr) *position =
pos;
5442 intptr_t target_index =
ReadUInt();
5444 TryFinallyBlock* outer_finally =
nullptr;
5445 intptr_t target_context_depth = -1;
5446 JoinEntryInstr* entry = switch_block()->
Destination(
5447 target_index, &outer_finally, &target_context_depth);
5449 Fragment instructions;
5451 TranslateFinallyFinalizers(outer_finally, target_context_depth);
5452 if (instructions.is_open()) {
5453 if (NeedsDebugStepCheck(parsed_function()->
function(),
pos)) {
5454 instructions += DebugStepCheck(
pos);
5456 instructions += Goto(entry);
5458 return instructions;
5461Fragment StreamingFlowGraphBuilder::BuildIfStatement(TokenPosition* position) {
5462 const TokenPosition
pos = ReadPosition();
5463 if (position !=
nullptr) *position =
pos;
5465 TestFragment condition = TranslateConditionForControl();
5467 Fragment then_fragment(condition.CreateTrueSuccessor(flow_graph_builder_));
5468 then_fragment += BuildStatementWithBranchCoverage();
5470 Fragment otherwise_fragment(
5471 condition.CreateFalseSuccessor(flow_graph_builder_));
5472 otherwise_fragment += BuildStatementWithBranchCoverage();
5474 if (then_fragment.is_open()) {
5475 if (otherwise_fragment.is_open()) {
5476 JoinEntryInstr*
join = BuildJoinEntry();
5477 then_fragment += Goto(join);
5478 otherwise_fragment += Goto(join);
5479 return Fragment(condition.entry, join);
5481 return Fragment(condition.entry, then_fragment.current);
5483 }
else if (otherwise_fragment.is_open()) {
5484 return Fragment(condition.entry, otherwise_fragment.current);
5486 return Fragment(condition.entry,
nullptr);
5490Fragment StreamingFlowGraphBuilder::BuildReturnStatement(
5491 TokenPosition* position) {
5492 const TokenPosition
pos = ReadPosition();
5493 if (position !=
nullptr) *position =
pos;
5497 bool inside_try_finally = try_finally_block() !=
nullptr;
5499 Fragment instructions;
5500 if (parsed_function()->
function().IsSyncGenerator()) {
5503 if (tag != kNothing) {
5509 (tag == kNothing ? NullConstant()
5510 : BuildExpression());
5513 if (instructions.is_open()) {
5514 if (inside_try_finally) {
5515 LocalVariable*
const finally_return_variable =
5517 ASSERT(finally_return_variable !=
nullptr);
5520 instructions += DebugStepCheck(
pos);
5522 instructions += StoreLocal(
pos, finally_return_variable);
5523 instructions += Drop();
5524 const intptr_t target_context_depth =
5525 finally_return_variable->is_captured()
5526 ? finally_return_variable->owner()->context_level()
5528 instructions += TranslateFinallyFinalizers(
nullptr, target_context_depth);
5529 if (instructions.is_open()) {
5530 const intptr_t saved_context_depth =
B->context_depth_;
5531 if (finally_return_variable->is_captured()) {
5532 B->context_depth_ = target_context_depth;
5534 instructions += LoadLocal(finally_return_variable);
5535 instructions += Return(TokenPosition::kNoSource);
5536 B->context_depth_ = saved_context_depth;
5539 instructions += Return(
pos);
5545 return instructions;
5548Fragment StreamingFlowGraphBuilder::BuildTryCatch(TokenPosition* position) {
5549 ASSERT(block_expression_depth() == 0);
5550 InlineBailout(
"kernel::FlowgraphBuilder::VisitTryCatch");
5552 const TokenPosition
pos = ReadPosition();
5553 if (position !=
nullptr) *position =
pos;
5555 intptr_t try_handler_index = AllocateTryIndex();
5556 Fragment try_body = TryCatch(try_handler_index);
5557 JoinEntryInstr* after_try = BuildJoinEntry();
5562 TryCatchBlock block(flow_graph_builder_, try_handler_index);
5563 try_body += BuildStatementWithBranchCoverage(position);
5564 try_body += Goto(after_try);
5568 const int kNeedsStracktraceBit = 1 << 0;
5569 const int kIsSyntheticBit = 1 << 1;
5572 bool needs_stacktrace =
5573 (
flags & kNeedsStracktraceBit) == kNeedsStracktraceBit;
5574 bool is_synthetic = (
flags & kIsSyntheticBit) == kIsSyntheticBit;
5578 const Array& handler_types =
5581 Fragment catch_body = CatchBlockEntry(handler_types, try_handler_index,
5582 needs_stacktrace, is_synthetic);
5584 for (intptr_t i = 0; i < catch_count; ++i) {
5586 TokenPosition
pos = ReadPosition();
5587 const AbstractType& type_guard =
T.BuildType();
5588 handler_types.SetAt(i, type_guard);
5590 Fragment catch_handler_body = EnterScope(catch_offset);
5593 if (tag == kSomething) {
5594 catch_handler_body += LoadLocal(CurrentException());
5595 catch_handler_body +=
5596 StoreLocal(TokenPosition::kNoSource,
5598 catch_handler_body += Drop();
5603 if (tag == kSomething) {
5604 catch_handler_body += LoadLocal(CurrentStackTrace());
5605 catch_handler_body +=
5606 StoreLocal(TokenPosition::kNoSource,
5608 catch_handler_body += Drop();
5613 CatchBlock block(flow_graph_builder_, CurrentException(),
5614 CurrentStackTrace(), try_handler_index);
5616 catch_handler_body += BuildStatementWithBranchCoverage();
5620 catch_handler_body += ExitScope(catch_offset);
5621 if (catch_handler_body.is_open()) {
5622 catch_handler_body += Goto(after_try);
5626 if (!type_guard.IsCatchAllType()) {
5627 catch_body += LoadLocal(CurrentException());
5630 catch_body += LoadInstantiatorTypeArguments();
5632 catch_body += NullConstant();
5635 if (!type_guard.IsInstantiated(
kFunctions)) {
5636 catch_body += LoadFunctionTypeArguments();
5638 catch_body += NullConstant();
5641 catch_body += Constant(type_guard);
5647 TargetEntryInstr* catch_entry;
5648 TargetEntryInstr* next_catch_entry;
5649 catch_body += BranchIfTrue(&catch_entry, &next_catch_entry,
false);
5651 Fragment(catch_entry) + catch_handler_body;
5652 catch_body = Fragment(next_catch_entry);
5654 catch_body += catch_handler_body;
5661 if (catch_body.is_open()) {
5662 catch_body += LoadLocal(CurrentException());
5663 catch_body += LoadLocal(CurrentStackTrace());
5664 catch_body += RethrowException(TokenPosition::kNoSource, try_handler_index);
5669 return Fragment(try_body.entry, after_try);
5672Fragment StreamingFlowGraphBuilder::BuildTryFinally(TokenPosition* position) {
5678 InlineBailout(
"kernel::FlowgraphBuilder::VisitTryFinally");
5680 const TokenPosition
pos = ReadPosition();
5681 if (position !=
nullptr) *position =
pos;
5705 intptr_t try_handler_index = AllocateTryIndex();
5706 Fragment try_body = TryCatch(try_handler_index);
5707 JoinEntryInstr* after_try = BuildJoinEntry();
5717 TryFinallyBlock tfb(flow_graph_builder_, finalizer_offset);
5718 TryCatchBlock tcb(flow_graph_builder_, try_handler_index);
5719 try_body += BuildStatementWithBranchCoverage(position);
5723 if (try_body.is_open()) {
5727 JoinEntryInstr* finally_entry = BuildJoinEntry();
5729 try_body += Goto(finally_entry);
5731 Fragment finally_body(finally_entry);
5732 finally_body += BuildStatementWithBranchCoverage();
5733 finally_body += Goto(after_try);
5740 handler_types.SetAt(0, Object::dynamic_type());
5742 Fragment finally_body = CatchBlockEntry(handler_types, try_handler_index,
5752 Value*
const saved_stack_top = stack();
5755 finally_body += BuildStatementWithBranchCoverage();
5756 if (finally_body.is_open()) {
5757 finally_body += LoadLocal(CurrentException());
5758 finally_body += LoadLocal(CurrentStackTrace());
5760 RethrowException(TokenPosition::kNoSource, try_handler_index);
5764 ASSERT(stack() ==
nullptr);
5765 set_stack(saved_stack_top);
5768 return Fragment(try_body.entry, after_try);
5771Fragment StreamingFlowGraphBuilder::BuildYieldStatement(
5772 TokenPosition* position) {
5773 const TokenPosition
pos = ReadPosition();
5774 if (position !=
nullptr) *position =
pos;
5778 Fragment instructions;
5785 ASSERT(suspend_state !=
nullptr);
5786 instructions += IntConstant(0);
5787 instructions +=
B->LoadFpRelativeSlot(
5788 compiler::target::frame_layout.FrameSlotForVariable(suspend_state) *
5789 compiler::target::kWordSize,
5791 instructions += LoadNativeField(Slot::SuspendState_function_data());
5793 instructions += BuildExpression();
5794 if (NeedsDebugStepCheck(parsed_function()->
function(),
pos)) {
5795 instructions += DebugStepCheck(
pos);
5798 if (parsed_function()->
function().IsAsyncGenerator()) {
5821 if (is_yield_star) {
5823 IG->object_store()->async_star_stream_controller_add_stream();
5825 add_method =
IG->object_store()->async_star_stream_controller_add();
5828 StaticCall(TokenPosition::kNoSource, add_method, 2, ICData::kNoRebind);
5830 TargetEntryInstr *return1, *continue1;
5831 instructions += BranchIfTrue(&return1, &continue1,
false);
5832 JoinEntryInstr* return_join = BuildJoinEntry();
5833 Fragment(return1) + Goto(return_join);
5834 instructions = Fragment(instructions.entry, continue1);
5837 instructions += NullConstant();
5840 TargetEntryInstr *return2, *continue2;
5841 instructions += BranchIfTrue(&return2, &continue2,
false);
5842 Fragment(return2) + Goto(return_join);
5843 instructions = Fragment(instructions.entry, continue2);
5845 Fragment do_return(return_join);
5846 do_return += TranslateFinallyFinalizers(
nullptr, -1);
5847 do_return += NullConstant();
5848 do_return += Return(TokenPosition::kNoSource);
5850 }
else if (parsed_function()->
function().IsSyncGenerator()) {
5864 if (is_yield_star) {
5865 field =
IG->object_store()->sync_star_iterator_yield_star_iterable();
5867 field =
IG->object_store()->sync_star_iterator_current();
5869 instructions +=
B->StoreFieldGuarded(field);
5873 instructions += Drop();
5878 return instructions;
5881Fragment StreamingFlowGraphBuilder::BuildVariableDeclaration(
5882 TokenPosition* position) {
5884 LocalVariable* variable = LookupVariable(kernel_position_no_tag);
5889 bool has_initializer = (
ReadTag() != kNothing);
5891 Fragment instructions;
5892 if (variable->is_late()) {
5894 if (has_initializer) {
5897 instructions += Constant(Object::sentinel());
5898 }
else if (!has_initializer) {
5899 instructions += NullConstant();
5902 instructions += BuildExpression();
5907 const TokenPosition debug_position = helper.equals_position_.IsReal()
5908 ? helper.equals_position_
5910 if (position !=
nullptr) *position = helper.position_;
5911 if (NeedsDebugStepCheck(stack(), debug_position) && !helper.IsHoisted()) {
5912 instructions = DebugStepCheck(debug_position) + instructions;
5914 instructions += StoreLocal(helper.position_, variable);
5915 instructions += Drop();
5916 return instructions;
5919Fragment StreamingFlowGraphBuilder::BuildFunctionDeclaration(
5920 TokenPosition* position) {
5922 const TokenPosition
pos = ReadPosition();
5923 if (position !=
nullptr) *position =
pos;
5928 Fragment instructions = DebugStepCheck(
pos);
5929 instructions += BuildFunctionNode(
offset);
5930 instructions += StoreLocal(
pos, LookupVariable(variable_offset));
5931 instructions += Drop();
5932 return instructions;
5935Fragment StreamingFlowGraphBuilder::BuildFunctionNode(
5936 intptr_t func_decl_offset) {
5938 const auto& member_function =
5942 thread(), func_decl_offset, member_function,
5943 parsed_function()->
function(), closure_owner_));
5946 SafepointWriteRwLocker ml(thread(),
5947 thread()->isolate_group()->program_lock());
5959 function.set_context_scope(context_scope);
5967 Fragment instructions;
5968 instructions += Constant(
function);
5969 if (scopes()->IsClosureWithEmptyContext(func_node_offset)) {
5970 instructions += NullConstant();
5972 instructions += LoadLocal(parsed_function()->current_context_var());
5975 const bool has_instantiator_type_args =
5977 if (has_instantiator_type_args) {
5978 instructions += LoadInstantiatorTypeArguments();
5983 LocalVariable*
closure = MakeTemporary();
5987 instructions += LoadLocal(closure);
5988 instructions += LoadFunctionTypeArguments();
5990 Slot::Closure_function_type_arguments(),
5993 return instructions;
5996Fragment StreamingFlowGraphBuilder::BuildNativeEffect() {
6000 ASSERT(list_length == 0);
6002 const intptr_t positional_count =
6004 ASSERT(positional_count == 1);
6009 const intptr_t named_args_len =
6011 ASSERT(named_args_len == 0);
6014 code += NullConstant();
6018Fragment StreamingFlowGraphBuilder::BuildReachabilityFence() {
6022 ASSERT(list_length == 0);
6025 ASSERT(positional_count == 1);
6031 TokenPosition* position =
nullptr;
6032 Fragment
code = BuildExpression(position);
6035 ASSERT(named_args_len == 0);
6037 code <<=
new (
Z) ReachabilityFenceInstr(Pop());
6038 code += NullConstant();
6043 if (
error !=
nullptr) {
6051Fragment StreamingFlowGraphBuilder::BuildLoadStoreAbiSpecificInt(
6055 const intptr_t expected_argument_count = 2
6056 + (at_index ? 1 : 0)
6057 + (is_store ? 1 : 0);
6062 const TypeArguments& type_arguments =
T.BuildTypeArguments(list_length);
6067 const char*
error =
nullptr;
6068 const auto* native_type =
6076 code += BuildExpression();
6077 code += BuildExpression();
6079 code += BuildExpression();
6080 code += IntConstant(native_type->SizeInBytes());
6081 code +=
B->BinaryIntegerOp(Token::kMUL, kTagged,
true);
6082 code +=
B->BinaryIntegerOp(Token::kADD, kTagged,
true);
6085 code += BuildExpression();
6090 ASSERT(named_args_len == 0);
6103 Z, ffi_library.LookupFunctionAllowPrivate(
6107 const intptr_t static_call_arg_count = 2 + (is_store ? 1 : 0);
6108 code += StaticCall(TokenPosition::kNoSource,
target, static_call_arg_count,
6109 argument_names, ICData::kStatic);
6114Fragment StreamingFlowGraphBuilder::BuildFfiCall() {
6118 T.BuildTypeArguments(list_length);
6121 ASSERT(positional_count == argc);
6125 code += BuildExpression();
6127 code += LoadNativeField(Slot::PointerBase_data(),
6132 ASSERT(named_args_len == 0);
6135 Z, parsed_function()->
function().FfiCSignature());
6138 const char*
error =
nullptr;
6140 if (
error !=
nullptr) {
6147 code +=
B->FfiCallFunctionBody(parsed_function()->
function(), native_type,
6157Fragment StreamingFlowGraphBuilder::BuildArgumentsCachableIdempotentCall(
6163 if (types_list_length != 0) {
6164 FATAL(
"Type arguments for vm:cachable-idempotent not (yet) supported.");
6170 for (intptr_t i = 0; i < positional_list_length; ++i) {
6171 code += BuildExpression();
6172 Definition* target_def =
B->Peek();
6173 if (!target_def->IsConstant()) {
6175 "Arguments for vm:cachable-idempotent must be const, argument on "
6176 "index %" Pd " is not.",
6183 if (named_args_len != 0) {
6184 FATAL(
"Named arguments for vm:cachable-idempotent not (yet) supported.");
6190Fragment StreamingFlowGraphBuilder::BuildCachableIdempotentCall(
6191 TokenPosition position,
6192 const Function&
target) {
6194 if (!parsed_function()->
function().ForceOptimize()) {
6196 "vm:cachable-idempotent functions can only be called from "
6197 "vm:force-optimize functions.");
6200 if (!target_result_type.IsIntType()) {
6201 FATAL(
"The return type vm:cachable-idempotent functions must be int.")
6209 code += flow_graph_builder_->CachableIdempotentCall(
6216Fragment StreamingFlowGraphBuilder::BuildFfiNativeCallbackFunction(
6234 const intptr_t expected_argc =
6235 static_cast<int>(has_target) +
static_cast<int>(has_exceptional_return);
6238 ASSERT(argc == expected_argc);
6241 ASSERT(list_length == 1);
6242 const TypeArguments& type_arguments =
6243 T.BuildTypeArguments(list_length);
6244 ASSERT(type_arguments.Length() == 1 && type_arguments.IsInstantiated());
6245 const FunctionType& native_sig =
6246 FunctionType::CheckedHandle(
Z, type_arguments.TypeAt(0));
6249 const intptr_t positional_count =
6251 ASSERT(positional_count == expected_argc);
6259 code += BuildExpression();
6260 Definition* target_def =
B->Peek();
6261 ASSERT(target_def->IsConstant());
6262 const Closure& target_closure =
6263 Closure::Cast(target_def->AsConstant()->value());
6264 ASSERT(!target_closure.IsNull());
6265 target = target_closure.function();
6271 if (has_exceptional_return) {
6273 code += BuildExpression();
6274 Definition* exceptional_return_def =
B->Peek();
6275 ASSERT(exceptional_return_def->IsConstant());
6276 exceptional_return ^= exceptional_return_def->AsConstant()->value().ptr();
6280 const intptr_t named_args_len =
6282 ASSERT(named_args_len == 0);
6285 const char*
error =
nullptr;
6291 exceptional_return, kind));
6297Fragment StreamingFlowGraphBuilder::BuildFfiNativeAddressOf() {
6301 ASSERT(types_length == 1);
6302 T.BuildTypeArguments(types_length);
6304 ASSERT(positional_count == 1);
6306 Fragment frag = BuildExpression();
6307 ASSERT(frag.entry->IsConstant());
6308 const auto& native_annotation =
6309 Instance::Cast(frag.entry->AsConstant()->value());
6312 const auto& pointer_class =
6314 const auto& type_arguments =
6316 Fragment
code = Constant(type_arguments);
6317 code += AllocateObject(TokenPosition::kNoSource, pointer_class, 1);
6318 code += LoadLocal(MakeTemporary());
6322 code += flow_graph_builder_->FfiNativeLookupAddress(native_annotation);
6328 ASSERT(named_arg_count == 0);
static bool compare(const SkBitmap &ref, const SkIRect &iref, const SkBitmap &test, const SkIRect &itest)
static void done(const char *config, const char *src, const char *srcOptions, const char *name)
static float next(float f)
static bool left(const SkPoint &p0, const SkPoint &p1)
static bool right(const SkPoint &p0, const SkPoint &p1)
#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 kernel_offset() 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, bool allow_add)
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)
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
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)
@ 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
const char *const function_name
std::function< void()> closure
SINT Vec< 2 *N, T > join(const Vec< N, T > &lo, const Vec< N, T > &hi)
static constexpr Register kValue2Reg