56 "Propagate IC data from unoptimized to optimized IC calls.");
60 "Generate special IC stubs for two args Smi operations");
69 bool include_abstract)
70 : array_handles_(zone),
73 include_abstract_(include_abstract) {}
81 cids_->
Add(klass.
id());
88 if (!array->IsNull()) {
89 for (intptr_t i = 0; i < array->Length(); ++i) {
90 *subclass_or_implementor ^= (*array).At(i);
95 if (!array->IsNull()) {
96 for (intptr_t i = 0; i < array->Length(); ++i) {
97 *subclass_or_implementor ^= (*array).At(i);
107 const bool include_abstract_;
112 bool include_abstract,
115 const intptr_t cid_count =
table->NumCids();
116 std::unique_ptr<CidRangeVector[]>* cid_ranges =
nullptr;
117 if (include_abstract) {
118 cid_ranges = exclude_null ? &cid_subtype_ranges_abstract_nonnullable_
119 : &cid_subtype_ranges_abstract_nullable_;
121 cid_ranges = exclude_null ? &cid_subtype_ranges_nonnullable_
122 : &cid_subtype_ranges_nullable_;
124 if (*cid_ranges ==
nullptr) {
128 if (ranges.
length() == 0) {
129 BuildRangesFor(
table, &ranges, klass, include_abstract, exclude_null);
139 bool include_abstract,
143 supertype_(
AbstractType::Handle(zone(), cls.RareType())),
144 include_abstract_(include_abstract),
145 exclude_null_(exclude_null),
146 to_check_(
Class::Handle(zone())),
151 if (
cid == kTypeArgumentsCid)
return true;
155 if (!exclude_null_ &&
cid ==
kNullCid)
return true;
156 to_check_ = table_->
At(
cid);
158 if (!include_abstract_ && to_check_.
is_abstract())
return true;
165 to_check_ = table_->
At(
cid);
174 Zone* zone()
const {
return thread_->
zone(); }
176 Thread*
const thread_;
177 ClassTable*
const table_;
178 const AbstractType& supertype_;
179 const bool include_abstract_;
180 const bool exclude_null_;
182 AbstractType& subtype_;
188void HierarchyInfo::BuildRangesUsingClassTableFor(ClassTable*
table,
191 bool include_abstract,
193 CidCheckerForRanges checker(
thread(),
table, klass, include_abstract,
196 const intptr_t cid_count =
table->NumCids();
199 for (intptr_t
cid = kInstanceCid;
cid < cid_count; ++
cid) {
202 if (checker.MayInclude(
cid))
continue;
203 if (checker.MustInclude(
cid)) {
207 }
else if (
start != -1) {
221void HierarchyInfo::BuildRangesFor(ClassTable*
table,
223 const Class& dst_klass,
224 bool include_abstract,
228 if (dst_klass.InVMIsolateHeap() || dst_klass.id() == kInstanceCid) {
229 BuildRangesUsingClassTableFor(
table, ranges, dst_klass, include_abstract,
235 GrowableArray<intptr_t> cids;
236 SubtypeFinder finder(zone, &cids, include_abstract);
238 SafepointReadRwLocker ml(
thread(),
240 finder.ScanImplementorClasses(dst_klass);
242 if (cids.is_empty())
return;
245 intptr_t* cids_array = cids.data();
247 qsort(cids_array, cids.length(),
sizeof(intptr_t),
248 [](
const void*
a,
const void*
b) {
251 MSAN_UNPOISON(static_cast<const intptr_t*>(a), sizeof(intptr_t));
252 MSAN_UNPOISON(static_cast<const intptr_t*>(b), sizeof(intptr_t));
253 return static_cast<int>(*static_cast<const intptr_t*>(a) -
254 *static_cast<const intptr_t*>(b));
258 CidCheckerForRanges checker(
thread(),
table, dst_klass, include_abstract,
260 intptr_t left_cid = -1;
261 intptr_t right_cid = -1;
262 intptr_t previous_cid = -1;
263 for (intptr_t i = 0; i < cids.length(); ++i) {
264 const intptr_t current_cid = cids[i];
265 if (current_cid == previous_cid)
continue;
270 if (left_cid != -1) {
271 ASSERT(previous_cid != -1);
273 for (intptr_t j = previous_cid + 1; j < current_cid; ++j) {
275 if (!checker.MayInclude(j)) {
276 ranges->Add({left_cid, right_cid});
277 left_cid = right_cid = -1;
282 previous_cid = current_cid;
284 if (checker.MayInclude(current_cid))
continue;
285 if (checker.MustInclude(current_cid)) {
286 if (left_cid == -1) {
288 left_cid = current_cid;
290 right_cid = current_cid;
291 }
else if (left_cid != -1) {
293 ranges->Add({left_cid, right_cid});
294 left_cid = right_cid = -1;
300 if (left_cid != -1) {
301 ranges->Add(CidRange{left_cid, right_cid});
308 if (!
type.IsInstantiated() || !
type.IsType()) {
320 if (
type.IsFutureOrType()) {
348 if (!
type.IsType() ||
type.IsDartFunctionType()) {
360 if (
type.IsFutureOrType()) {
383 for (intptr_t i = 0; i < num_type_parameters; ++i) {
395 if (!
type.IsRecordType()) {
401 for (intptr_t i = 0, n = rec.
NumFields(); i < n; ++i) {
411 intptr_t* lower_limit,
412 intptr_t* upper_limit) {
414 if (
type.IsNullable()) {
421 const Class& type_class =
427 if (ranges.
length() == 1) {
440#define FOR_EACH_NON_INT_BOXED_REPRESENTATION(M) \
443 M(Float32x4, Float32x4) \
444 M(Float64x2, Float64x2) \
447#define BOXING_IN_SET_CASE(unboxed, boxed) \
448 case kUnboxed##unboxed: \
450#define BOXING_VALUE_OFFSET_CASE(unboxed, boxed) \
451 case kUnboxed##unboxed: \
452 return compiler::target::boxed::value_offset();
453#define BOXING_CID_CASE(unboxed, boxed) \
454 case kUnboxed##unboxed: \
455 return k##boxed##Cid;
471 compiler::target::kSmiBits;
480 return compiler::target::Mint::value_offset();
507#undef BOXING_CID_CASE
508#undef BOXING_VALUE_OFFSET_CASE
509#undef BOXING_IN_SET_CASE
510#undef FOR_EACH_NON_INT_BOXED_REPRESENTATION
524 if (constant_value_ ==
nullptr) {
527 return *constant_value_;
571 if (def->IsConstraint() || def->IsBox() || def->IsUnbox() ||
572 def->IsIntConverter() || def->IsFloatToDouble() ||
573 def->IsDoubleToFloat()) {
578 if (orig == def)
return def;
584 if (def !=
nullptr) {
587 return load->IsImmutableLengthLoad();
596 bool is_static_call) {
618 if (
tag() != other.
tag())
return false;
637 ASSERT((*a)->IsSingleCid());
638 ASSERT((*b)->IsSingleCid());
639 return (*a)->cid_start - (*b)->cid_start;
646 if (target_info_b->
count != target_info_a->
count) {
647 return (target_info_b->
count - target_info_a->
count);
649 return (*a)->
cid_start - (*b)->cid_start;
655 for (
int i = 0; i <
length(); i++) {
666 for (intptr_t i = 0; i <
cid_ranges_.length(); ++i) {
674 for (intptr_t i = 0; i <
cid_ranges_.length(); ++i) {
681 for (
int i = 0; i <
length(); i++) {
697 int argument_number) {
699 for (intptr_t i = 0; i < binary_feedback.feedback_.
length(); i++) {
700 ASSERT((argument_number == 0) || (argument_number == 1));
701 const intptr_t
cid = argument_number == 0
702 ? binary_feedback.feedback_[i].first
703 : binary_feedback.feedback_[i].second;
707 if (cids->
length() != 0) {
712 for (
int src = 1; src < cids->
length(); src++) {
743void CallTargets::CreateHelper(Zone* zone,
const ICData& ic_data) {
746 const intptr_t num_args_tested = ic_data.NumArgsTested();
748 for (
int i = 0, n = ic_data.NumberOfChecks(); i < n; i++) {
749 if (ic_data.GetCountAt(i) == 0) {
754 if (num_args_tested == 0) {
755 }
else if (num_args_tested == 1) {
756 ic_data.GetOneClassCheckAt(i, &
id, &dummy);
758 ASSERT(num_args_tested == 2);
759 GrowableArray<intptr_t> arg_ids;
760 ic_data.GetCheckAt(i, &arg_ids, &dummy);
764 intptr_t
count = ic_data.GetCountAt(i);
766 ic_data.GetExactnessAt(i)));
769 if (ic_data.is_megamorphic()) {
770 ASSERT(num_args_tested == 1);
772 const Array& descriptor =
779 SafepointMutexLocker ml(thread->isolate_group()->type_feedback_mutex());
781 for (intptr_t i = 0, n = entries.Length(); i < n; i++) {
783 Smi::Value(entries[i].Get<MegamorphicCache::kClassIdIndex>());
789 const intptr_t filled_entry_count =
cache.filled_entry_count();
790 ASSERT(filled_entry_count > 0);
800 if (
length() != 1)
return false;
816#define KIND_CASE(name) \
828#define KIND_CASE(name) \
829 if (strcmp(str, #name) == 0) { \
830 *out = Kind::k##name; \
844 is_bit_test_(IsCompactCidRange(cids)),
845 token_pos_(
source.token_pos) {
847 const intptr_t number_of_checks =
cids.
length();
848 ASSERT(number_of_checks > 0);
849 SetInputAt(0,
value);
851 ASSERT(number_of_checks != 1 || !
cids[0].IsSingleCid() ||
852 cids[0].cid_start != kSmiCid);
856 auto const other_check = other.AsCheckClass();
857 ASSERT(other_check !=
nullptr);
862 if (!
cids().IsMonomorphic()) {
876 if (!
cids().IsMonomorphic()) {
884 const intptr_t number_of_checks =
cids.
length();
887 if (number_of_checks <= 2)
return false;
894 return (
max -
min) < compiler::target::kBitsPerWord;
903 const uintptr_t one = 1;
904 intptr_t
min = cids_.ComputeLowestCid();
906 for (intptr_t i = 0; i < cids_.length(); ++i) {
908 uintptr_t range = one + cids_[i].Extent();
909 if (range >=
static_cast<uintptr_t
>(compiler::target::kBitsPerWord)) {
912 run = (one << range) - 1;
914 mask |=
run << (cids_[i].cid_start -
min);
925 intptr_t num_context_variables,
928 num_context_variables_(num_context_variables) {
934 if (!
HasUses())
return nullptr;
939 auto store = use->instruction()->AsStoreField();
940 if ((
store ==
nullptr) ||
941 (use->use_index() != StoreFieldInstr::kInstancePos)) {
953 if (!
HasUses())
return nullptr;
960 const intptr_t kNumTemps = 0;
977 auto object_store =
compiler->isolate_group()->object_store();
981 stub = object_store->allocate_closure_ta_generic_stub();
983 stub = object_store->allocate_closure_ta_stub();
987 stub = object_store->allocate_closure_generic_stub();
989 stub = object_store->allocate_closure_stub();
992 compiler->GenerateStubCall(
source(), stub, UntaggedPcDescriptors::kOther,
998 const intptr_t kNumInputs = 1;
999 const intptr_t kNumTemps = 0;
1000 LocationSummary*
locs =
new (zone)
1012 compiler->GenerateStubCall(
source(), stub, UntaggedPcDescriptors::kOther,
1017 intptr_t index)
const {
1019 return slot_.has_untagged_instance() ? kUntagged : kTagged;
1031 if (is_initialization_ && !
slot().has_untagged_instance() &&
1032 slot().representation() == kTagged &&
1033 (!
slot().IsContextSlot() ||
1034 !
instance()->definition()->IsAllocateUninitializedContext()) &&
1035 value()->BindsToConstantNull()) {
1039 if (
slot().kind() == Slot::Kind::kPointerBase_data &&
1051 return field().
ptr() == other.AsGuardFieldClass()->field().ptr();
1055 return field().
ptr() == other.AsGuardFieldLength()->field().ptr();
1059 return field().
ptr() == other.AsGuardFieldType()->field().ptr();
1069 const auto& constant_instantiator_type_args =
1071 ? TypeArguments::null_type_arguments()
1072 : TypeArguments::Cast(
1074 const auto& constant_function_type_args =
1076 ? TypeArguments::null_type_arguments()
1079 Z, AbstractType::Cast(
sub_type()->BoundConstant()).ptr());
1081 Z, AbstractType::Cast(
super_type()->BoundConstant()).ptr());
1084 &constant_sub_type, &constant_super_type,
1085 constant_instantiator_type_args, constant_function_type_args)) {
1093 auto const other_op = other.AsStrictCompare();
1094 ASSERT(other_op !=
nullptr);
1100 return handle_surrogates_ ? kCaseInsensitiveCompareUTF16RuntimeEntry
1101 : kCaseInsensitiveCompareUCS2RuntimeEntry;
1105 auto const other_op = other.AsMathMinMax();
1106 ASSERT(other_op !=
nullptr);
1107 return (
op_kind() == other_op->op_kind()) &&
1113 auto const other_op = other.AsBinaryIntegerOp();
1114 return (
op_kind() == other_op->op_kind()) &&
1120 auto const other_load = other.AsLoadField();
1121 ASSERT(other_load !=
nullptr);
1122 return &this->slot_ == &other_load->slot_;
1127 return field().
ptr() == other.AsLoadStaticField()->field().ptr();
1163 auto const other_constant = other.AsConstant();
1164 ASSERT(other_constant !=
nullptr);
1165 return (
value().ptr() == other_constant->value().
ptr() &&
1166 representation() == other_constant->representation());
1172 representation_(representation),
1173 constant_address_(0) {
1174 if (representation_ == kUnboxedDouble) {
1186 if (
auto constant =
definition()->OriginalDefinition()->AsConstant()) {
1187 *constant_defn = constant;
1196 return (constant !=
nullptr) && constant->
value().
IsNull();
1202 ASSERT(constant !=
nullptr);
1203 return constant->
value();
1228 parsed_function_(parsed_function),
1230 indirect_entries_(),
1233 spill_slot_count_(0),
1234 fixed_slot_count_(0) {}
1240 if (defn !=
nullptr && defn->
value().
IsNull())
return defn;
1249 for (intptr_t i = 0; i < catch_entries_.length(); ++i) {
1250 if (catch_entries_[i]->catch_try_index() == index)
return catch_entries_[i];
1261#define DEFINE_ACCEPT(ShortName, Attrs) \
1262 void ShortName##Instr::Accept(InstructionVisitor* visitor) { \
1263 visitor->Visit##ShortName(this); \
1271 intptr_t use_index = 0;
1273 Value* use = it.CurrentValue();
1282 it.CurrentValue()->RemoveFromUseList();
1290 Value* use = it.CurrentValue();
1312 ASSERT(next_instr !=
nullptr);
1313 ASSERT(!next_instr->IsBlockEntry());
1314 prev_instr->
LinkTo(next_instr);
1320 return return_previous ? prev_instr : next_instr;
1324 ASSERT(previous_ ==
nullptr);
1325 ASSERT(next_ ==
nullptr);
1327 next_ =
prev->next_;
1328 next_->previous_ =
this;
1329 previous_->next_ =
this;
1333 for (intptr_t i =
InputCount() - 1; i >= 0; --i) {
1343 for (intptr_t i = tail->InputCount() - 1; i >= 0; --i) {
1344 Value* input = tail->InputAt(i);
1354 while ((
result !=
nullptr) && !
result->IsBlockEntry()) {
1362 return (
result !=
nullptr) ?
result->AsBlockEntry() :
nullptr;
1376 for (intptr_t i = 0; i < block_order_->length(); ++i) {
1378 entry->Accept(
this);
1391 if (
value->Type()->IsNull() ||
1392 (
value->Type()->ToNullableCid() == kSmiCid) ||
1393 (
value->Type()->ToNullableCid() == kBoolCid)) {
1401 if (
value->BindsToConstant()) {
1407 value =
value->definition()->RedefinedValue();
1408 }
while (
value !=
nullptr);
1416 intptr_t pred_id = predecessor->
block_id();
1444 value->set_previous_use(
nullptr);
1453 if (
next !=
nullptr)
next->set_previous_use(
nullptr);
1456 if (
next !=
nullptr)
next->set_previous_use(
nullptr);
1475 if (it.Current()->instruction() !=
target)
return false;
1485 ASSERT(other !=
nullptr);
1488 Value* current =
nullptr;
1490 if (
next !=
nullptr) {
1492 while (
next !=
nullptr) {
1502 if (
next !=
nullptr)
next->set_previous_use(current);
1510 if (
next !=
nullptr) {
1511 while (
next !=
nullptr) {
1519 if (
next !=
nullptr)
next->set_previous_use(current);
1526 for (intptr_t i =
InputCount() - 1; i >= 0; --i) {
1530 it.CurrentValue()->RemoveFromUseList();
1539 ASSERT(move_arguments !=
nullptr);
1541 ASSERT((arg_count + after_args_input_count) <=
env()->Length());
1542 const intptr_t env_base =
1543 env()->
Length() - arg_count - after_args_input_count;
1544 for (intptr_t i = 0; i < arg_count; ++i) {
1552 ASSERT(call->env() !=
nullptr);
1554 call->env()->DeepCopyAfterTo(
1555 flow_graph->
zone(),
this, call->ArgumentCount(),
1580 if (block == dom_block) {
1590 curr = curr->next()) {
1591 if (curr ==
this)
return true;
1601 for (intptr_t i = 0; i <
InputCount(); i++) {
1604 if (input_representation != kNoRepresentation &&
1614#define INSTR_ATTRS(type, attrs) InstrAttrs::attrs,
1627 for (intptr_t i = replacement->
InputCount() - 1; i >= 0; --i) {
1640 if ((iterator !=
nullptr) && (
this == iterator->
Current())) {
1642 replacement->
LinkTo(
this);
1664 for (intptr_t i = new_comparison->
InputCount() - 1; i >= 0; --i) {
1671 ASSERT(new_comparison->
env() ==
nullptr);
1675 comparison_ = new_comparison;
1686 return (i >= 0) && (i < preorder->
length()) && ((*preorder)[i] == block);
1702 ASSERT(predecessor !=
nullptr);
1714 intptr_t parent_number =
1716 parent->
Add(parent_number);
1720 preorder->
Add(
this);
1732 last = it.Current();
1735 if (last->IsGoto()) last->AsGoto()->set_block(
this);
1750 const intptr_t osr_id = graph_entry->
osr_id();
1764 instr = it.Current();
1767 ASSERT(instr->IsCheckStackOverflow());
1778 graph_entry, normal_entry->
block_id(), normal_entry->try_index(),
1781 auto goto_join =
new GotoInstr(AsJoinEntry(),
1783 ASSERT(parent !=
nullptr);
1784 goto_join->CopyDeoptIdFrom(*parent);
1785 osr_entry->LinkTo(goto_join);
1809 ASSERT(other !=
nullptr);
1811 while (current !=
nullptr && current !=
this) {
1814 return current ==
this;
1826 return loop_info_ !=
nullptr && loop_info_->
header() ==
this;
1830 return loop_info_ ==
nullptr ? 0 : loop_info_->
NestingDepth();
1847 target->predecessor_ = new_block;
1854 intptr_t old_index = join->IndexOfPredecessor(
this);
1855 intptr_t pred_count = join->PredecessorCount();
1857 ASSERT(old_index < pred_count);
1859 intptr_t new_id = new_block->
block_id();
1860 intptr_t new_index = old_index;
1863 for (; new_index < pred_count - 1; ++new_index) {
1864 if (join->predecessors_[new_index + 1]->block_id() > new_id)
break;
1865 join->predecessors_[new_index] = join->predecessors_[new_index + 1];
1869 for (; new_index > 0; --new_index) {
1870 if (join->predecessors_[new_index - 1]->block_id() < new_id)
break;
1871 join->predecessors_[new_index] = join->predecessors_[new_index - 1];
1874 join->predecessors_[new_index] = new_block;
1876 if ((join->phis() ==
nullptr) || (old_index == new_index))
return;
1885 intptr_t
step = (old_index < new_index) ? 1 : -1;
1886 for (intptr_t use_idx = old_index; use_idx != new_index;
1898 if (join !=
nullptr) {
1900 it.Current()->UnuseAllInputs();
1905 it.Current()->UnuseAllInputs();
1914 if (phis_ ==
nullptr) {
1916 for (intptr_t i = 0; i < var_count; i++) {
1917 phis_->Add(
nullptr);
1920 ASSERT((*phis_)[var_index] ==
nullptr);
1926 if (phis_ ==
nullptr) {
1933 ASSERT(phis_ !=
nullptr);
1934 for (intptr_t index = 0; index < phis_->length(); ++index) {
1935 if (phi == (*phis_)[index]) {
1936 (*phis_)[index] = phis_->Last();
1937 phis_->RemoveLast();
1944 if (phis_ ==
nullptr)
return;
1946 intptr_t to_index = 0;
1947 for (intptr_t from_index = 0; from_index < phis_->length(); ++from_index) {
1948 PhiInstr* phi = (*phis_)[from_index];
1949 if (phi !=
nullptr) {
1951 (*phis_)[to_index++] = phi;
1952 for (intptr_t i = phi->
InputCount() - 1; i >= 0; --i) {
1961 if (to_index == 0) {
1964 phis_->TruncateTo(to_index);
1982 (
osr_entry() ==
nullptr ? 0 : 1) + catch_entries_.length();
1987 if (index == 0)
return normal_entry_;
1998 return catch_entries_[index];
2006 if (index == 0)
return true_successor_;
2007 if (index == 1)
return false_successor_;
2032 if (SpeculativeModeOfInputs() == kNotSpeculative) {
2041 const intptr_t rep_bitsize =
2043 if (
value()->
Type()->ToCid() == kSmiCid &&
2044 compiler::target::kSmiBits <= rep_bitsize) {
2054 case Token::kBIT_AND:
2055 case Token::kBIT_OR:
2056 case Token::kBIT_XOR:
2079 case Token::kBIT_AND:
2080 case Token::kBIT_OR:
2081 case Token::kBIT_XOR:
2094 case Token::kTRUNCDIV:
2108 if (
right()->BindsToConstant()) {
2110 if (!constant.IsInteger())
return false;
2111 return Integer::Cast(constant).AsInt64Value() != 0;
2117 if (!
right()->BindsToConstant())
return false;
2119 if (!constant.IsSmi())
return false;
2120 const intptr_t int_value = Smi::Cast(constant).Value();
2128 return compiler::target::kSmiBits + 1;
2130 case kUnboxedUint32:
2141 return static_cast<int64_t
>(
static_cast<uint64_t
>(-1) >>
2158 if (left_value == 1) {
2159 if (
right->definition()->representation() != kUnboxedDouble) {
2166 return right->definition();
2178 if (!HasUses())
return nullptr;
2179 if (
value()->definition()->IsFloatToDouble()) {
2181 return value()->
definition()->AsFloatToDouble()->value()->definition();
2183 if (
value()->BindsToConstant()) {
2184 double narrowed_val =
2185 static_cast<float>(Double::Cast(
value()->BoundConstant()).value());
2193 if (!HasUses())
return nullptr;
2194 if (
value()->BindsToConstant()) {
2201 if (!HasUses())
return nullptr;
2215 if ((
op_kind() == Token::kMUL) &&
2216 (
left()->definition() ==
right()->definition())) {
2228 return HasUses() ? this :
nullptr;
2237 case Token::kBIT_AND:
2239 case Token::kBIT_OR:
2241 case Token::kBIT_XOR:
2252 SpeculativeMode speculative_mode,
2255 switch (representation) {
2261 case kUnboxedUint32:
2272 if (op ==
nullptr) {
2277 op->set_range(*range);
2280 ASSERT(op->representation() == representation);
2290 SpeculativeMode speculative_mode) {
2292 Range* right_range =
nullptr;
2295 case Token::kTRUNCDIV:
2296 if (representation != kTagged)
break;
2302 right_range =
new Range();
2303 const_def->InferRange(
nullptr, right_range);
2309 switch (representation) {
2319 case kUnboxedUint32:
2322 if (speculative_mode == kNotSpeculative) {
2336 if (speculative_mode == kNotSpeculative) {
2353 ASSERT(op->representation() == representation);
2366 SpeculativeMode speculative_mode) {
2369 if (op ==
nullptr) {
2373 op->set_range(*range);
2390 auto*
const replacement =
2392 if (replacement !=
this) {
2406 auto*
const replacement =
2408 if (replacement !=
this) {
2417 if (
left()->BindsToConstant() &&
right()->BindsToConstant()) {
2427 if (
left()->BindsToConstant() && !
right()->BindsToConstant() &&
2445 case Token::kBIT_AND:
2446 case Token::kBIT_OR:
2447 case Token::kBIT_XOR:
2455 if (IsBinaryUint32Op() && HasUnmatchedInputRepresentations()) {
2466 }
else if (rhs == 0) {
2471 (SpeculativeModeOfInputs() == kNotSpeculative) ? kUnboxedInt64
2476 representation(), Token::kSHL,
left()->CopyWithType(),
2479 if (shift !=
nullptr) {
2482 if (
auto shift_with_range = shift->AsShiftIntegerOp()) {
2483 shift_with_range->set_shift_range(
2490 if (!CanDeoptimize()) {
2491 ASSERT(!shift->CanDeoptimize());
2504 case Token::kBIT_AND:
2511 case Token::kBIT_OR:
2518 case Token::kBIT_XOR:
2523 representation(), Token::kBIT_NOT,
left()->CopyWithType(),
2524 GetDeoptId(), SpeculativeModeOfInputs(), range());
2525 if (bit_not !=
nullptr) {
2538 case Token::kTRUNCDIV:
2541 }
else if (rhs == -1) {
2543 representation(), Token::kNEGATE,
left()->CopyWithType(),
2544 GetDeoptId(), SpeculativeModeOfInputs(), range());
2545 if (negation !=
nullptr) {
2553 if (std::abs(rhs) == 1) {
2555 Object::smi_zero());
2562 Object::smi_zero());
2568 }
else if (rhs < 0) {
2570 if (!CanDeoptimize()) {
2581 Object::smi_zero());
2592 Object::smi_zero());
2593 }
else if ((rhs < 0) || ((rhs >= result_bits) && !
is_truncating())) {
2596 if (!CanDeoptimize()) {
2607 Object::smi_zero());
2666 case kImmutableArrayCid:
2667 case kTypeArgumentsCid:
2675 auto kind =
function.recognized_kind();
2677 case MethodRecognizer::kTypedData_ByteDataView_factory:
2678 case MethodRecognizer::kTypedData_Int8ArrayView_factory:
2679 case MethodRecognizer::kTypedData_Uint8ArrayView_factory:
2680 case MethodRecognizer::kTypedData_Uint8ClampedArrayView_factory:
2681 case MethodRecognizer::kTypedData_Int16ArrayView_factory:
2682 case MethodRecognizer::kTypedData_Uint16ArrayView_factory:
2683 case MethodRecognizer::kTypedData_Int32ArrayView_factory:
2684 case MethodRecognizer::kTypedData_Uint32ArrayView_factory:
2685 case MethodRecognizer::kTypedData_Int64ArrayView_factory:
2686 case MethodRecognizer::kTypedData_Uint64ArrayView_factory:
2687 case MethodRecognizer::kTypedData_Float32ArrayView_factory:
2688 case MethodRecognizer::kTypedData_Float64ArrayView_factory:
2689 case MethodRecognizer::kTypedData_Float32x4ArrayView_factory:
2690 case MethodRecognizer::kTypedData_Int32x4ArrayView_factory:
2691 case MethodRecognizer::kTypedData_Float64x2ArrayView_factory:
2700 auto kind =
function.recognized_kind();
2702 case MethodRecognizer::kTypedData_UnmodifiableByteDataView_factory:
2703 case MethodRecognizer::kTypedData_UnmodifiableInt8ArrayView_factory:
2704 case MethodRecognizer::kTypedData_UnmodifiableUint8ArrayView_factory:
2705 case MethodRecognizer::kTypedData_UnmodifiableUint8ClampedArrayView_factory:
2706 case MethodRecognizer::kTypedData_UnmodifiableInt16ArrayView_factory:
2707 case MethodRecognizer::kTypedData_UnmodifiableUint16ArrayView_factory:
2708 case MethodRecognizer::kTypedData_UnmodifiableInt32ArrayView_factory:
2709 case MethodRecognizer::kTypedData_UnmodifiableUint32ArrayView_factory:
2710 case MethodRecognizer::kTypedData_UnmodifiableInt64ArrayView_factory:
2711 case MethodRecognizer::kTypedData_UnmodifiableUint64ArrayView_factory:
2712 case MethodRecognizer::kTypedData_UnmodifiableFloat32ArrayView_factory:
2713 case MethodRecognizer::kTypedData_UnmodifiableFloat64ArrayView_factory:
2714 case MethodRecognizer::kTypedData_UnmodifiableFloat32x4ArrayView_factory:
2715 case MethodRecognizer::kTypedData_UnmodifiableInt32x4ArrayView_factory:
2716 case MethodRecognizer::kTypedData_UnmodifiableFloat64x2ArrayView_factory:
2724 return HasUses() ? this :
nullptr;
2730 switch (field.
kind()) {
2734 case Slot::Kind::kArgumentsDescriptor_type_args_len:
2742 case Slot::Kind::kArgumentsDescriptor_count:
2750 case Slot::Kind::kArgumentsDescriptor_positional_count:
2758 case Slot::Kind::kArgumentsDescriptor_size:
2771 case Slot::Kind::kTypeArguments_length:
2778 case Slot::Kind::kRecord_shape:
2787 const intptr_t index = compiler::target::Record::field_index_at_offset(
2832 if (
slot().IsIdentical(Slot::PointerBase_data())) {
2847 if (
slot().IsIdentical(Slot::PointerBase_data())) {
2869 if (call->is_known_list_constructor() &&
2871 return call->ArgumentAt(1);
2872 }
else if (call->function().recognized_kind() ==
2873 MethodRecognizer::kByteDataFactory) {
2876 return call->ArgumentAt(1);
2886 return call->ArgumentAt(3);
2888 }
else if (
LoadFieldInstr* load_array = orig_instance->AsLoadField()) {
2891 const Slot&
slot = load_array->slot();
2901 switch (
slot().kind()) {
2902 case Slot::Kind::kArray_length:
2904 return create_array->num_elements()->definition();
2907 case Slot::Kind::kTypedDataBase_length:
2909 orig_instance->AsAllocateTypedData()) {
2910 return alloc_typed_data->num_elements()->definition();
2913 case Slot::Kind::kTypedDataView_typed_data:
2920 return call->ArgumentAt(1);
2924 case Slot::Kind::kTypedDataView_offset_in_bytes:
2930 return call->ArgumentAt(2);
2931 }
else if (call->function().recognized_kind() ==
2932 MethodRecognizer::kByteDataFactory) {
2935 return flow_graph->
GetConstant(Object::smi_zero());
2939 case Slot::Kind::kRecord_shape:
2941 if (
auto* alloc_rec = orig_instance->AsAllocateRecord()) {
2943 }
else if (
auto* alloc_rec = orig_instance->AsAllocateSmallRecord()) {
2947 if (
type->IsRecordType()) {
2949 Smi::Handle(RecordType::Cast(*type).shape().AsSmi()));
2956 if (call->is_known_list_constructor()) {
2957 return call->ArgumentAt(0);
2962 switch (call->function().recognized_kind()) {
2963 case MethodRecognizer::kByteDataFactory:
2964 case MethodRecognizer::kLinkedHashBase_getData:
2965 case MethodRecognizer::kImmutableLinkedHashBase_getData:
2971 orig_instance->AsCreateArray()) {
2972 return create_array->type_arguments()->definition();
2973 }
else if (
LoadFieldInstr* load_array = orig_instance->AsLoadField()) {
2974 const Slot&
slot = load_array->slot();
2983 .GetInstanceTypeArguments(flow_graph->
thread())));
2988 case Slot::Kind::kLinkedHashBase_data:
2996 case Slot::Kind::kPointerBase_data:
3011 if (
instance()->BindsToConstant()) {
3023 if (
auto store = use->instruction()->AsStoreField()) {
3024 if ((use->use_index() == StoreFieldInstr::kInstancePos) &&
3026 if (initializing_store ==
nullptr) {
3027 initializing_store =
store;
3029 initializing_store =
nullptr;
3038 if (initializing_store !=
nullptr &&
3040 ASSERT(IsDominatedBy(initializing_store));
3049 if (FLAG_eliminate_type_checks) {
3050 if (
value()->
Type()->ToCid() == kBoolCid) {
3067 if (!
dst_type()->BindsToConstant())
return this;
3068 const auto& abs_type = AbstractType::Cast(
dst_type()->BoundConstant());
3070 if (abs_type.IsTopTypeForSubtyping() ||
3071 (FLAG_eliminate_type_checks &&
3072 value()->
Type()->IsAssignableTo(abs_type))) {
3075 if (abs_type.IsInstantiated()) {
3095 ? &TypeArguments::null_type_arguments()
3096 : &TypeArguments::Cast(val);
3101 function_type_args =
3103 ? &TypeArguments::null_type_arguments()
3115 if (instantiator_type_args ==
nullptr) {
3118 if (load_type_args->slot().IsTypeArguments()) {
3123 if (load_field->slot().IsDartField() &&
3126 .static_type_exactness_state()
3127 .IsHasExactSuperClass()) {
3130 Z, load_field->slot().field().type()))
3131 .GetInstanceTypeArguments(thread));
3138 if ((instantiator_type_args !=
nullptr) && (function_type_args !=
nullptr)) {
3140 Z, abs_type.InstantiateFrom(*instantiator_type_args,
3142 if (new_dst_type.
IsNull()) {
3156 (FLAG_eliminate_type_checks &&
3157 value()->
Type()->IsAssignableTo(new_dst_type))) {
3165 return HasUses() ? this :
nullptr;
3170 const intptr_t kNumInputs = 0;
3171 const intptr_t kNumTemps = 0;
3182 ASSERT(!coverage_array_.IsNull());
3183 return coverage_array_.At(coverage_index_) !=
Smi::New(0) ? nullptr :
this;
3187 if (input_use_list() ==
nullptr) {
3201 if ((unbox_defn !=
nullptr) &&
3211 if (
value()->BindsToConstant()) {
3212 switch (representation()) {
3213 case kUnboxedFloat64x2:
3216 case kUnboxedFloat32x4:
3219 case kUnboxedInt32x4:
3231 return HasUses() ? this : NULL;
3235 if (!HasUses())
return NULL;
3250 if (input_use_list() ==
nullptr) {
3266 if (replacement !=
this) {
3271 if (
auto unbox =
value()->definition()->AsUnboxInt64()) {
3272 if (unbox->SpeculativeModeOfInputs() == kNotSpeculative) {
3273 return unbox->value()->definition();
3275 }
else if (
auto unbox =
value()->definition()->AsUnboxedConstant()) {
3280 if (
auto conv =
value()->definition()->AsIntConverter()) {
3282 if (conv->from() == kUntagged) {
3285 switch (conv->from()) {
3287 replacement =
new BoxInt32Instr(conv->value()->CopyWithType());
3289 case kUnboxedUint32:
3304 if (!HasUses() && !CanDeoptimize())
return nullptr;
3313 if (box_defn !=
nullptr) {
3338 if (val.IsInteger()) {
3342 return flow_graph->
GetConstant(double_val, kUnboxedDouble);
3343 }
else if (val.IsDouble()) {
3344 return flow_graph->
GetConstant(val, kUnboxedDouble);
3350 if (val.IsInteger()) {
3351 double narrowed_val =
3352 static_cast<float>(Integer::Cast(val).AsDoubleValue());
3356 }
else if (val.IsDouble()) {
3357 double narrowed_val =
static_cast<float>(Double::Cast(val).value());
3368 if (!HasUses() && !CanDeoptimize())
return nullptr;
3378 if (HasUnmatchedInputRepresentations()) {
3384 if (box_defn !=
nullptr && !box_defn->HasUnmatchedInputRepresentations()) {
3402 converter->mark_truncating();
3415 if (
value()->BindsToConstant()) {
3417 if (obj.IsInteger()) {
3421 const int64_t intval = Integer::Cast(obj).AsInt64Value();
3439 if (!HasUses())
return nullptr;
3442 if (
auto constant =
value()->definition()->AsConstant()) {
3443 if (
from() != kUntagged &&
to() != kUntagged &&
3444 constant->representation() ==
from() && constant->value().IsInteger()) {
3445 const int64_t
value = Integer::Cast(constant->value()).AsInt64Value();
3450 box ^= box.Canonicalize(flow_graph->
thread());
3458 if ((first_converter !=
nullptr) &&
3463 if (intermediate_rep == kUntagged) {
3466 }
else if (!
Range::Fits(src_defn->range(), intermediate_rep)) {
3472 if (first_converter->
from() ==
to()) {
3479 if ((first_converter->
from() == kUntagged) || (
to() == kUntagged)) {
3488 converter->mark_truncating();
3495 if (unbox_defn !=
nullptr && (
from() == kUnboxedInt64) &&
3496 (
to() == kUnboxedInt32) && unbox_defn->HasOnlyInputUse(
value())) {
3514 if (comp->IsRelationalOp()) {
3539 if (
type->IsNone()) {
3546 unwrapped_type.
IsObjectType() || unwrapped_type.IsTypeParameter() ||
3559 if (
compare->needs_number_check()) {
3562 compare->set_needs_number_check(
false);
3565 compare->set_needs_number_check(
false);
3570 Value* other =
nullptr;
3572 if (!
compare->IsComparisonWithConstant(&other, &constant_defn)) {
3577 const bool can_merge = is_branch || (other->
Type()->
ToCid() == kBoolCid);
3581 if (!constant.IsBool() || !can_merge) {
3585 const bool constant_value = Bool::Cast(constant).value();
3589 if ((kind == Token::kEQ_STRICT) == constant_value) {
3595 if (
auto comp = other_defn->AsComparison()) {
3612 if (!
right->BindsToConstant() || !
right->BoundConstant().IsSmi()) {
3616 const intptr_t
value = Smi::Cast(
right->BoundConstant()).Value();
3622 if ((mask_op ==
nullptr) || (mask_op->
op_kind() != Token::kBIT_AND) ||
3623 !mask_op->HasOnlyUse(
left)) {
3648 bool negated =
false;
3650 comparison()->AsStrictCompare(), &negated,
true);
3675 if (FLAG_trace_optimization && flow_graph->
should_print()) {
3691 bool negate =
false;
3699 if (bit_and !=
nullptr) {
3700 if (FLAG_trace_optimization && flow_graph->
should_print()) {
3701 THR_Print(
"Merging test smi v%" Pd "\n", bit_and->ssa_temp_index());
3712 bit_and->RemoveFromGraph();
3719 if (!HasUses())
return nullptr;
3721 bool negated =
false;
3724 if (negated && replacement->IsComparison()) {
3725 ASSERT(replacement !=
this);
3726 replacement->AsComparison()->NegateComparison();
3738 ASSERT(operation_cid() == kMintCid);
3746 (kind() == Token::kEQ) ? Token::kEQ_STRICT : Token::kNE_STRICT,
3747 left()->CopyWithType(),
right()->CopyWithType(),
3767 (kind() == Token::kEQ) ? Token::kEQ_STRICT : Token::kNE_STRICT,
3768 left()->CopyWithType(),
right()->CopyWithType(),
3778 if (
index()->BindsToSmiConstant() &&
offset()->BindsToSmiConstant()) {
3780 Utils::MulWithWrapAround<intptr_t>(
index()->BoundSmiConstant(),
3782 offset()->BoundSmiConstant());
3787 auto*
const Z = flow_graph->
zone();
3812 if (!HasUses())
return nullptr;
3823 if (
value()->BindsToConstant()) {
3825 if (constant_value.IsSmi() &&
3826 cids_.
Contains(Smi::Cast(constant_value).Value())) {
3839 ASSERT((kind == Token::kIS) || (kind == Token::kISNOT));
3840 SetInputAt(0,
value);
3841 set_operation_cid(kObjectCid);
3860 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0;
3861 for (intptr_t i = 0; i <
data.length(); i += 2) {
3863 return (
data[i + 1] == true_result)
3869 if (!CanDeoptimize()) {
3871 return (
data[
data.length() - 1] == true_result)
3889 value_representation_(value_representation) {
3891 ASSERT(value_representation == kTagged ||
3893 SetInputAt(0,
value);
3894 set_operation_cid(kObjectCid);
3898 if (
value()->BindsToSmiConstant()) {
3900 bool in_range = lower_ <= val && val <= upper_;
3901 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT));
3903 Bool::Get(in_range == (kind() == Token::kIS)));
3907 if (range !=
nullptr) {
3908 if (range->
IsWithin(lower_, upper_)) {
3911 if (!range->
Overlaps(lower_, upper_)) {
3921 }
else if (
lower > upper_ ||
upper < lower_) {
3940 if (
field().guarded_cid() ==
cid) {
3948 if (!
field().needs_length_check()) {
3959 if (call ==
nullptr) {
3964 if (call->is_known_list_constructor() &&
3966 length = call->ArgumentAt(1)->AsConstant();
3967 }
else if (call->function().recognized_kind() ==
3968 MethodRecognizer::kByteDataFactory) {
3969 length = call->ArgumentAt(1)->AsConstant();
3971 length = call->ArgumentAt(3)->AsConstant();
3974 Smi::Cast(
length->value()).Value() == expected_length) {
3987 return (
value()->
Type()->ToCid() == kSmiCid) ? nullptr :
this;
3991 if ((
left()->
Type()->ToCid() == kDoubleCid) ||
3992 (
right()->
Type()->ToCid() == kDoubleCid)) {
4003 auto const other_check = other.AsCheckNull();
4004 ASSERT(other_check !=
nullptr);
4014 case kUnboxedUint16:
4015#if defined(HAS_SMI_63_BITS)
4017 case kUnboxedUint32:
4021#if !defined(HAS_SMI_63_BITS)
4025 case kUnboxedUint32:
4032 case kUnboxedDouble:
4034 case kUnboxedFloat32x4:
4035 case kUnboxedFloat64x2:
4036 case kUnboxedInt32x4:
4048 SpeculativeMode speculative_mode) {
4053 speculative_mode == SpeculativeMode::kNotSpeculative
4056 value, deopt_id, speculative_mode);
4058 case kUnboxedUint32:
4064 case kUnboxedDouble:
4066 case kUnboxedFloat32x4:
4067 case kUnboxedFloat64x2:
4068 case kUnboxedInt32x4:
4078bool UnboxInstr::CanConvertSmi()
const {
4080 case kUnboxedDouble:
4086 case kUnboxedFloat32x4:
4087 case kUnboxedFloat64x2:
4088 case kUnboxedInt32x4:
4107 result->feedback_.Add({arg_ids[0], arg_ids[1]});
4114 intptr_t receiver_cid,
4115 intptr_t argument_cid) {
4117 result->feedback_.
Add({receiver_cid, argument_cid});
4122 intptr_t receiver_cid,
4125 const intptr_t
count = 1;
4134 targets->CreateHelper(zone, ic_data);
4136 targets->MergeIntoRanges();
4143 targets.CreateHelper(zone, ic_data);
4166 for (
int idx = 0; idx <
length; idx++) {
4167 int lower_limit_cid = (idx == 0) ? -1 : targets[idx - 1].cid_end;
4168 auto target_info = targets.
TargetAt(idx);
4170 if (
target.is_polymorphic_target())
continue;
4171 for (
int i = target_info->cid_start - 1; i > lower_limit_cid; i--) {
4172 bool class_is_abstract =
false;
4174 &class_is_abstract) &&
4176 if (!class_is_abstract) {
4177 target_info->cid_start = i;
4189 for (
int idx = 0; idx <
length; idx++) {
4190 int upper_limit_cid =
4191 (idx ==
length - 1) ? max_cid : targets[idx + 1].cid_start;
4192 auto target_info = targets.
TargetAt(idx);
4194 if (
target.is_polymorphic_target())
continue;
4200 intptr_t cid_end_including_abstract = target_info->cid_end;
4201 for (
int i = target_info->cid_end + 1; i < upper_limit_cid; i++) {
4202 bool class_is_abstract =
false;
4204 &class_is_abstract) &&
4206 cid_end_including_abstract = i;
4207 if (!class_is_abstract) {
4208 target_info->cid_end = i;
4219 if ((cid_end_including_abstract > target_info->cid_end) &&
4221 ((cid_end_including_abstract + 1) == targets[idx + 1].cid_start) &&
4223 target_info->cid_end = cid_end_including_abstract;
4227 targets.MergeIntoRanges();
4231void CallTargets::MergeIntoRanges() {
4241 for (
int src = 1; src <
length(); src++) {
4245 !
target.is_polymorphic_target()) {
4262 for (intptr_t i = 0; i <
length(); i++) {
4274#define __ compiler->assembler()->
4276LocationSummary* GraphEntryInstr::MakeLocationSummary(Zone* zone,
4277 bool optimizing)
const {
4282LocationSummary* JoinEntryInstr::MakeLocationSummary(Zone* zone,
4283 bool optimizing)
const {
4288void JoinEntryInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
4291 compiler->AddCurrentDescriptor(UntaggedPcDescriptors::kDeopt, GetDeoptId(),
4292 InstructionSource());
4299LocationSummary* TargetEntryInstr::MakeLocationSummary(Zone* zone,
4300 bool optimizing)
const {
4305void TargetEntryInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
4311 if (
compiler->NeedsEdgeCounter(
this)) {
4318 compiler->AddCurrentDescriptor(UntaggedPcDescriptors::kDeopt, GetDeoptId(),
4319 InstructionSource());
4329LocationSummary* FunctionEntryInstr::MakeLocationSummary(
4331 bool optimizing)
const {
4336void FunctionEntryInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
4337#if defined(TARGET_ARCH_X64)
4340 if (
__ CodeSize() % 2 == 1) {
4344 if (tag() == Instruction::kFunctionEntry) {
4348 if (
this ==
compiler->flow_graph().graph_entry()->unchecked_entry()) {
4349 __ BindUncheckedEntryPoint();
4360 if (!FLAG_precompiled_mode) {
4361 __ MonomorphicCheckedEntryJIT();
4363 __ MonomorphicCheckedEntryAOT();
4371#if defined(TARGET_USES_OBJECT_POOL)
4372 __ set_constant_pool_allowed(
false);
4380#if defined(TARGET_USES_OBJECT_POOL)
4381 ASSERT(
__ constant_pool_allowed());
4385 if (
compiler->NeedsEdgeCounter(
this)) {
4392 compiler->AddCurrentDescriptor(UntaggedPcDescriptors::kDeopt, GetDeoptId(),
4393 InstructionSource());
4403LocationSummary* NativeEntryInstr::MakeLocationSummary(Zone* zone,
4404 bool optimizing)
const {
4408void NativeEntryInstr::SaveArguments(FlowGraphCompiler*
compiler)
const {
4409 __ Comment(
"SaveArguments");
4413 if (return_loc.IsPointerToMemory()) {
4416 for (intptr_t i = marshaller_.num_args(); i-- > 0;) {
4420 __ Comment(
"SaveArgumentsEnd");
4430 const intptr_t num_regs = reg_loc.
num_regs();
4433 for (intptr_t i = num_regs - 1; i >= 0; i--) {
4434 __ PushRegister(reg_loc.reg_at(i));
4442 compiler->EmitNativeMove(dst, nloc, &temp_alloc);
4445 if (pointer_loc.IsRegisters()) {
4447 ASSERT(regs_loc.num_regs() == 1);
4448 __ PushRegister(regs_loc.reg_at(0));
4450 ASSERT(pointer_loc.IsStack());
4457 for (intptr_t i = num; i-- > 0;) {
4462 const auto& both = nloc.
AsBoth();
4468 bool optimizing)
const {
4473void OsrEntryInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
4481#if defined(TARGET_USES_OBJECT_POOL)
4482 __ set_constant_pool_allowed(
false);
4487#if defined(TARGET_USES_OBJECT_POOL)
4488 ASSERT(
__ constant_pool_allowed());
4507 intptr_t
offset = label->Position();
4515 bool optimizing)
const {
4516 return JoinEntryInstr::MakeLocationSummary(zone, optimizing);
4519void IndirectEntryInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
4520 JoinEntryInstr::EmitNativeCode(
compiler);
4523LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone,
4525 const intptr_t kNumInputs = 0;
4532 LocationSummary* locs =
new (zone) LocationSummary(
4533 zone, kNumInputs, kNumTemps,
4538 : LocationSummary::kCall)
4539 : LocationSummary::kNoCall);
4551void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
4557 const intptr_t field_table_offset =
4558 compiler::target::Thread::field_table_values_offset();
4559 const intptr_t field_offset = compiler::target::FieldTable::OffsetOf(
field());
4561 __ LoadMemoryValue(
result,
THR,
static_cast<int32_t
>(field_table_offset));
4562 __ LoadMemoryValue(
result,
result,
static_cast<int32_t
>(field_offset));
4566 ThrowErrorSlowPathCode* slow_path =
4567 new LateInitializationErrorSlowPath(
this);
4568 compiler->AddSlowPathCode(slow_path);
4570 __ CompareObject(
result, Object::sentinel());
4571 __ BranchIf(
EQUAL, slow_path->entry_label());
4575 auto object_store =
compiler->isolate_group()->object_store();
4578 compiler::Label no_call, call_initializer;
4579 __ CompareObject(
result, Object::sentinel());
4580 if (!
field().is_late()) {
4581 __ BranchIf(
EQUAL, &call_initializer);
4582 __ CompareObject(
result, Object::transition_sentinel());
4587 __ Bind(&call_initializer);
4588 if (
field().needs_load_guard()) {
4589 stub = object_store->init_static_field_stub();
4590 }
else if (
field().is_late()) {
4593 original_field.EnsureInitializerFunction();
4595 ? object_store->init_late_final_static_field_stub()
4596 : object_store->init_late_static_field_stub();
4601 stub = object_store->init_static_field_stub();
4606 UntaggedPcDescriptors::kOther, locs(),
4613LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone,
4615 const intptr_t kNumInputs = 1;
4620void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
4621 Register obj = locs()->in(0).reg();
4627LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone,
4629 const intptr_t kNumInputs = 1;
4630 LocationSummary* locs =
nullptr;
4635 const intptr_t kNumTemps = using_shared_stub ? 1 : 0;
4636 locs =
new (zone) LocationSummary(
4637 zone, kNumInputs, kNumTemps,
4639 : LocationSummary::kCallOnSlowPath);
4640 if (using_shared_stub) {
4647 const intptr_t kNumTemps = 0;
4656 const intptr_t kNumTemps = 0;
4660 if (rep == kTagged || rep == kUntagged) {
4664 if (value_size <= compiler::target::kWordSize) {
4667 ASSERT(value_size == 2 * compiler::target::kWordSize);
4678void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
4679 const Register instance_reg = locs()->in(0).reg();
4680 ASSERT(OffsetInBytes() >= 0);
4682 ASSERT(OffsetInBytes() != 0 ||
slot().has_untagged_instance());
4686 __ LoadFromSlot(locs()->
out(0).reg(), instance_reg,
slot());
4687 EmitNativeCodeForInitializerCall(
compiler);
4688 }
else if (rep == kTagged || rep == kUntagged) {
4689 __ LoadFromSlot(locs()->
out(0).reg(), instance_reg,
slot());
4692 if (value_size <= compiler::target::kWordSize) {
4693 __ LoadFromSlot(locs()->
out(0).reg(), instance_reg,
slot());
4695 auto const result_pair = locs()->out(0).AsPairLocation();
4696 const Register result_lo = result_pair->At(0).reg();
4697 const Register result_hi = result_pair->At(1).reg();
4698 __ LoadFieldFromOffset(result_lo, instance_reg, OffsetInBytes());
4699 __ LoadFieldFromOffset(result_hi, instance_reg,
4700 OffsetInBytes() + compiler::target::kWordSize);
4708 __ LoadUnboxedDouble(
result, instance_reg,
4713 __ LoadUnboxedSimd128(
result, instance_reg,
4722void LoadFieldInstr::EmitNativeCodeForInitializerCall(
4727 ThrowErrorSlowPathCode* slow_path =
4728 new LateInitializationErrorSlowPath(
this);
4729 compiler->AddSlowPathCode(slow_path);
4731 const Register result_reg = locs()->out(0).reg();
4732 __ CompareObject(result_reg, Object::sentinel());
4733 __ BranchIf(
EQUAL, slow_path->entry_label());
4743 compiler::Label no_call;
4749 auto object_store =
compiler->isolate_group()->object_store();
4751 if (field.needs_load_guard()) {
4752 stub = object_store->init_instance_field_stub();
4753 }
else if (field.is_late()) {
4754 if (!field.has_nontrivial_initializer()) {
4755 stub = object_store->init_instance_field_stub();
4759 original_field.EnsureInitializerFunction();
4761 if (field.is_final()) {
4762 stub = object_store->init_late_final_instance_field_stub();
4764 stub = object_store->init_late_instance_field_stub();
4772 UntaggedPcDescriptors::kOther, locs(),
4777LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone,
bool opt)
const {
4778 const intptr_t kNumInputs = 1;
4779 const intptr_t kNumTemps = 0;
4780 LocationSummary* summary =
new (zone)
4786void ThrowInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
4787 auto object_store =
compiler->isolate_group()->object_store();
4788 const auto& throw_stub =
4792 UntaggedPcDescriptors::kOther, locs(),
4803LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone,
bool opt)
const {
4804 const intptr_t kNumInputs = 2;
4805 const intptr_t kNumTemps = 0;
4806 LocationSummary* summary =
new (zone)
4813void ReThrowInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
4814 auto object_store =
compiler->isolate_group()->object_store();
4815 const auto& re_throw_stub =
4820 UntaggedPcDescriptors::kOther, locs(),
4831LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone,
4833 const intptr_t kNumInputs = 1;
4834 const intptr_t kNumTemps = 0;
4835 LocationSummary* locs =
new (zone)
4843 bool optimizing)
const {
4852LocationSummary* RedefinitionInstr::MakeLocationSummary(Zone* zone,
4853 bool optimizing)
const {
4858void RedefinitionInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
4862LocationSummary* ReachabilityFenceInstr::MakeLocationSummary(
4864 bool optimizing)
const {
4865 LocationSummary* summary =
new (zone)
4872void ReachabilityFenceInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
4877LocationSummary* ParameterInstr::MakeLocationSummary(Zone* zone,
4878 bool optimizing)
const {
4883void ParameterInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
4887void NativeParameterInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
4890 constexpr intptr_t
delta =
4894 compiler::ffi::FrameRebase rebase(
compiler->zone(),
4896 delta * compiler::target::kWordSize);
4897 const auto& location =
4898 marshaller_.NativeLocationOfNativeParameter(def_index_);
4900 rebase.Rebase(location.IsPointerToMemory()
4901 ? location.AsPointerToMemory().pointer_location()
4903 NoTemporaryAllocator no_temp;
4904 const Location out_loc = locs()->out(0);
4906 compiler->EmitMoveFromNative(out_loc, out_rep, src, &no_temp);
4909LocationSummary* NativeParameterInstr::MakeLocationSummary(Zone* zone,
4913 if (
representation() == kUnboxedInt64 && compiler::target::kWordSize < 8) {
4926 for (intptr_t i = 0; i < moves_.length(); i++) {
4935 bool optimizing)
const {
4939void ParallelMoveInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
4940 ParallelMoveEmitter(
compiler,
this).EmitNativeCode();
4943LocationSummary* ConstraintInstr::MakeLocationSummary(Zone* zone,
4944 bool optimizing)
const {
4949void ConstraintInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
4955 bool optimizing)
const {
4967 intptr_t* fpu_reg_slots) {
4968 if (registers_remapped_) {
4971 registers_remapped_ =
true;
4973 for (intptr_t i = 0; i <
InputCount(); i++) {
4980 bool optimizing)
const {
4982 null_->InitializeLocationSummary(zone, optimizing);
4983 return null_->locs();
4986void MakeTempInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
4992 bool optimizing)
const {
4997 : LocationSummary::
Make(zone, 0,
Location::NoLocation(),
4998 LocationSummary::kNoCall);
5008LocationSummary* BoxSmallIntInstr::MakeLocationSummary(Zone* zone,
5011 compiler::target::kSmiBits);
5012 const intptr_t kNumInputs = 1;
5013 const intptr_t kNumTemps = 0;
5014 LocationSummary* summary =
new (zone)
5021void BoxSmallIntInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
5026 __ ExtendAndSmiTagValue(
5034 bool needs_number_check,
5037 needs_number_check_(needs_number_check) {
5038 ASSERT((kind == Token::kEQ_STRICT) || (kind == Token::kNE_STRICT));
5039 SetInputAt(0,
left);
5040 SetInputAt(1,
right);
5049 if (
left.IsConstant()) {
5052 return true_condition;
5054 true_condition = EmitComparisonCodeRegConstant(
5056 }
else if (
right.IsConstant()) {
5059 return true_condition;
5061 true_condition = EmitComparisonCodeRegConstant(
compiler, labels,
left.reg(),
5064 true_condition =
compiler->EmitEqualityRegRegCompare(
5074 intptr_t input_index,
5078 if (input_type->
ToCid() == kBoolCid && obj.
GetClassId() == kBoolCid) {
5079 bool invert = (kind() != Token::kEQ_STRICT) ^ !Bool::Cast(obj).value();
5080 *true_condition_out =
5081 compiler->EmitBoolTest(locs()->in(input_index).reg(), labels,
invert);
5089 const intptr_t kNumInputs = 1;
5094void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
5095 const Register object = locs()->in(0).reg();
5097 if (input_can_be_smi_ && this->
object()->
Type()->CanBeSmi()) {
5099 __ LoadTaggedClassIdMayBeSmi(
result,
object);
5101 __ LoadClassIdMayBeSmi(
result,
object);
5111LocationSummary* TestRangeInstr::MakeLocationSummary(Zone* zone,
5113#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) || \
5114 defined(TARGET_ARCH_ARM)
5115 const bool needs_temp =
true;
5117 const bool needs_temp =
false;
5119 const intptr_t kNumInputs = 1;
5120 const intptr_t kNumTemps = needs_temp ? 1 : 0;
5121 LocationSummary* locs =
new (zone)
5132 BranchLabels labels) {
5133 intptr_t
lower = lower_;
5134 intptr_t
upper = upper_;
5135 if (value_representation_ == kTagged) {
5141#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) || \
5142 defined(TARGET_ARCH_ARM)
5143 Register temp = locs()->temp(0).reg();
5147 __ AddImmediate(temp, in, -
lower);
5149 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT));
5154 bool optimizing)
const {
5159 if (!FLAG_two_args_smi_icd) {
5164 return StubCode::SmiAddInlineCache().ptr();
5166 return StubCode::SmiLessInlineCache().ptr();
5168 return StubCode::SmiEqualInlineCache().ptr();
5191 intptr_t idx)
const {
5231#if !defined(DART_PRECOMPILED_RUNTIME)
5232 if (smi_op_target.IsNull() &&
5239 return smi_op_target.ptr();
5247 const Array& arguments_descriptor =
5265 if (!specialized_binary_smi_ic_stub.IsNull()) {
5270 const ICData* call_ic_data =
nullptr;
5271 if (!FLAG_propagate_ic_data || !
compiler->is_optimizing() ||
5273 const Array& arguments_descriptor =
5277 if (receivers_static_type_ !=
nullptr) {
5278 receivers_static_type = receivers_static_type_->ptr();
5281 call_ic_data =
compiler->GetOrAddInstanceCallICData(
5289 if (
ic_data()->NumberOfUsedChecks() > 0) {
5290 const ICData& unary_ic_data =
5309 bool use_specialized_smi_ic_stub =
false;
5310 if (!specialized_binary_smi_ic_stub.IsNull() &&
5311 call_ic_data->NumberOfChecksIs(1)) {
5312 GrowableArray<intptr_t> class_ids(2);
5314 call_ic_data->GetCheckAt(0, &class_ids, &
target);
5315 if (class_ids[0] == kSmiCid && class_ids[1] == kSmiCid &&
5316 target.ptr() == binary_smi_op_target.ptr()) {
5317 use_specialized_smi_ic_stub =
true;
5321 if (use_specialized_smi_ic_stub) {
5323 compiler->EmitInstanceCallJIT(specialized_binary_smi_ic_stub,
5344 args_desc, allow_add);
5348 if (targets_ ==
nullptr) {
5354 ASSERT(targets_->is_empty());
5373 intptr_t idx)
const {
5410 for (intptr_t i = 0; i < call->ArgumentCount(); i++) {
5411 args.Add(call->ArgumentValueAt(i)->CopyWithType());
5416 call->type_args_len(), call->argument_names());
5417 return dispatch_table_call;
5422 const intptr_t kNumInputs = 1;
5423 const intptr_t kNumTemps = 0;
5434 if (
selector()->requires_args_descriptor) {
5437 arguments_descriptor = args_info.ToArgumentsDescriptor();
5441 UntaggedPcDescriptors::kOther,
locs(),
env());
5444 if (receiver->Type()->is_nullable()) {
5455 intptr_t idx)
const {
5478 if (targets_ ==
nullptr) {
5484 ASSERT(targets_->is_empty());
5508 if (
length() == 0)
return false;
5509 for (
int i = 0; i <
length(); i++) {
5524 for (
int i = 1; i <
length(); i++) {
5532 for (
int i = 0; i <
length(); i++) {
5540 const intptr_t len = targets_.length();
5542 for (intptr_t i = 0; i < len; i++) {
5543 target = targets_.TargetAt(i)->target->ptr();
5544 if (!
target.IsDispatcherOrImplicitAccessor()) {
5557 bool optimizing)
const {
5565 compiler->EmitPolymorphicInstanceCall(
5572 bool is_string =
true;
5575 bool is_type =
true;
5578 for (intptr_t i = 0; i < num_checks; i++) {
5603 }
else if (is_type) {
5635 if (new_target ==
nullptr) {
5660 if (
target.recognized_kind() == MethodRecognizer::kObjectRuntimeType) {
5663 if (!
type.IsNull()) {
5673 return targets_.HasSingleRecognizedTarget();
5683 }
else if (
function().has_pragma()) {
5684 const intptr_t recognized_cid =
5695 if (
auto konst = defn->AsConstant()) {
5696 const Object& obj = konst->value();
5697 if (obj.IsString()) {
5698 return String::Cast(obj);
5699 }
else if (obj.IsSmi()) {
5702 }
else if (obj.IsBool()) {
5704 }
else if (obj.
IsNull()) {
5705 return Symbols::null();
5708 return String::null_string();
5713 auto arg0 = call->ArgumentValueAt(0)->definition();
5714 auto create_array = arg0->AsCreateArray();
5715 if (create_array ==
nullptr) {
5718 ASSERT(arg0->IsPhi() || arg0->IsParameter());
5722 Value* num_elements = create_array->num_elements();
5731 for (intptr_t i = 0; i <
length; i++) {
5732 pieces.
Add(Object::null_string());
5737 auto current = it.Current()->instruction();
5738 if (current == call) {
5741 auto store = current->AsStoreIndexed();
5742 if (
store ==
nullptr || !
store->index()->BindsToConstant() ||
5743 !
store->index()->BoundConstant().IsSmi()) {
5746 intptr_t store_index = Smi::Cast(
store->index()->BoundConstant()).Value();
5751 pieces.
SetAt(store_index, piece);
5757 const String& concatenated =
5764 auto arg0 = call->ArgumentValueAt(0)->definition();
5776 if (
function().ptr() == compiler_state.StringBaseInterpolate().
ptr()) {
5779 compiler_state.StringBaseInterpolateSingle().
ptr()) {
5788 if (argument->BindsToConstant()) {
5797 if (argument1->BindsToConstant() && argument2->BindsToConstant()) {
5799 if (
Evaluate(flow_graph, argument1->BoundConstant(),
5800 argument2->BoundConstant(), &
result)) {
5807 if (!compiler_state.is_aot()) {
5811 if (kind == MethodRecognizer::kObjectRuntimeType) {
5827 case MethodRecognizer::kSmi_bitLength: {
5829 if (argument.IsInteger()) {
5834 if (!
value.IsNull()) {
5841 case MethodRecognizer::kStringBaseLength:
5842 case MethodRecognizer::kStringBaseIsEmpty: {
5844 if (argument.IsString()) {
5845 const auto& str = String::Cast(argument);
5846 if (kind == MethodRecognizer::kStringBaseLength) {
5868 case MethodRecognizer::kOneByteString_equality:
5869 case MethodRecognizer::kTwoByteString_equality: {
5870 if (argument1.IsString() && argument2.IsString()) {
5885 bool optimizing)
const {
5891 const ICData* call_ic_data =
nullptr;
5892 if (!FLAG_propagate_ic_data || !
compiler->is_optimizing() ||
5894 const Array& arguments_descriptor =
5896 const int num_args_checked =
5898 call_ic_data =
compiler->GetOrAddStaticCallICData(
5907 locs(), *call_ic_data, rebind_rule_,
5910 TypeUsageInfo* type_usage_info =
compiler->thread()->type_usage_info();
5911 if (type_usage_info !=
nullptr) {
5923 intptr_t type_args_len,
5924 const Array& argument_names,
5930 std::move(arguments),
5932 representation_(representation),
5943#if defined(TARGET_ARCH_IA32)
5945 FATAL(
"Not supported on IA32.");
5950 intptr_t idx)
const {
5973 bool optimizing)
const {
5978#if defined(TARGET_ARCH_IA32)
5981 compiler::Label drop_args,
done;
5982 const intptr_t cacheable_pool_index =
__ object_pool_builder().AddImmediate(
5989 const bool need_to_drop_args = !
compiler->is_optimizing();
5992 "CachableIdempotentCall pool load and check. pool_index = "
5994 cacheable_pool_index);
5995 __ LoadWordFromPoolIndex(dst, cacheable_pool_index);
5996 __ CompareImmediate(dst, 0);
5998 __ Comment(
"CachableIdempotentCall pool load and check - end");
6004 locs(), null_ic_data, ICData::kNoRebind,
6005 Code::EntryKind::kNormal);
6007 __ Comment(
"CachableIdempotentCall pool store");
6008 if (!
function().HasUnboxedReturnValue()) {
6009 __ LoadWordFromBoxOrSmi(dst, dst);
6011 __ StoreWordToPoolIndex(dst, cacheable_pool_index);
6012 if (need_to_drop_args) {
6014 __ Bind(&drop_args);
6015 __ Drop(args_info.size_with_type_args);
6018 __ Comment(
"CachableIdempotentCall pool store - end");
6024 case kParameterCheck:
6026 case kInsertedByFrontend:
6043LocationSummary* AssertSubtypeInstr::MakeLocationSummary(Zone* zone,
6045 const intptr_t kNumInputs = 5;
6046 const intptr_t kNumTemps = 0;
6047 LocationSummary* summary =
new (zone)
6064void AssertSubtypeInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
6066 UntaggedPcDescriptors::kOther, locs(), deopt_id(),
6070LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone,
6072 const intptr_t kNumInputs = 2;
6073 const intptr_t kNumTemps = 0;
6074 LocationSummary* locs =
new (zone)
6085void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
6087 if (
type().IsTypeParameter()) {
6088 const auto& type_parameter = TypeParameter::Cast(
type());
6089 const bool is_function_parameter = type_parameter.IsFunctionTypeParameter();
6091 switch (type_parameter.nullability()) {
6093 stub = is_function_parameter
6094 ? StubCode::InstantiateTypeNonNullableFunctionTypeParameter()
6096 : StubCode::InstantiateTypeNonNullableClassTypeParameter()
6101 is_function_parameter
6102 ? StubCode::InstantiateTypeNullableFunctionTypeParameter().ptr()
6103 : StubCode::InstantiateTypeNullableClassTypeParameter().ptr();
6107 is_function_parameter
6108 ? StubCode::InstantiateTypeLegacyFunctionTypeParameter().ptr()
6109 : StubCode::InstantiateTypeLegacyClassTypeParameter().ptr();
6114 compiler->GenerateStubCall(
source(), stub, UntaggedPcDescriptors::kOther,
6115 locs(), deopt_id(),
env());
6118LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary(
6121 const intptr_t kNumInputs = 3;
6122 const intptr_t kNumTemps = 0;
6123 LocationSummary* locs =
new (zone)
6136void InstantiateTypeArgumentsInstr::EmitNativeCode(
6142 const auto& type_args =
6145 : Object::null_type_arguments();
6146 const intptr_t
len = type_args.Length();
6147 const bool can_function_type_args_be_null =
6150 compiler::Label type_arguments_instantiated;
6151 if (type_args.IsNull()) {
6155 }
else if (type_args.IsRawWhenInstantiatedFromRaw(len) &&
6156 can_function_type_args_be_null) {
6160 compiler::Label non_null_type_args;
6162 Object::null_object());
6171 __ BranchIf(
EQUAL, &type_arguments_instantiated,
6173 __ Bind(&non_null_type_args);
6177 locs(), deopt_id(),
env());
6178 __ Bind(&type_arguments_instantiated);
6181LocationSummary* DeoptimizeInstr::MakeLocationSummary(Zone* zone,
6186void DeoptimizeInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
6187 __ Jump(
compiler->AddDeoptStub(deopt_id(), deopt_reason_));
6190void CheckClassInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
6191 compiler::Label* deopt =
6192 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass);
6198 ASSERT(!cids_.IsMonomorphic() || !cids_.HasClassId(kSmiCid));
6200 Register temp = locs()->temp(0).reg();
6201 compiler::Label is_ok;
6203 __ BranchIfSmi(
value, cids_.HasClassId(kSmiCid) ? &is_ok : deopt);
6208 intptr_t
min = cids_.ComputeLowestCid();
6209 intptr_t
max = cids_.ComputeHighestCid();
6212 const intptr_t num_checks = cids_.length();
6213 const bool use_near_jump = num_checks < 5;
6215 for (intptr_t i = 0; i < num_checks; i++) {
6216 intptr_t cid_start = cids_[i].cid_start;
6217 intptr_t cid_end = cids_[i].cid_end;
6218 if (cid_start == kSmiCid && cid_end == kSmiCid) {
6221 if (cid_start == kSmiCid) cid_start++;
6222 if (cid_end == kSmiCid) cid_end--;
6223 const bool is_last =
6224 (i == num_checks - 1) ||
6225 (i == num_checks - 2 && cids_[i + 1].cid_start == kSmiCid &&
6226 cids_[i + 1].cid_end == kSmiCid);
6227 bias = EmitCheckCid(
compiler, bias, cid_start, cid_end, is_last, &is_ok,
6228 deopt, use_near_jump);
6234LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone,
6236 const intptr_t kNumInputs = 2;
6237 const intptr_t kNumTemps = 0;
6238 LocationSummary* locs =
new (zone) LocationSummary(
6239 zone, kNumInputs, kNumTemps,
6248void GenericCheckBoundInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
6252 RangeErrorSlowPath* slow_path =
new RangeErrorSlowPath(
this);
6253 compiler->AddSlowPathCode(slow_path);
6263 if (index_cid != kSmiCid) {
6264 __ BranchIfNotSmi(
index, slow_path->entry_label());
6274LocationSummary* CheckNullInstr::MakeLocationSummary(Zone* zone,
6276 const intptr_t kNumInputs = 1;
6277 const intptr_t kNumTemps = 0;
6278 LocationSummary* locs =
new (zone) LocationSummary(
6279 zone, kNumInputs, kNumTemps,
6293 __ Comment(
"%s slow path allocation of %s",
instruction()->DebugName(),
6305 ASSERT(!kAllocateMintRuntimeEntry.can_lazy_deopt() &&
6306 !kAllocateDoubleRuntimeEntry.can_lazy_deopt() &&
6307 !kAllocateFloat32x4RuntimeEntry.can_lazy_deopt() &&
6308 !kAllocateFloat64x2RuntimeEntry.can_lazy_deopt());
6309 compiler->GenerateNonLazyDeoptableStubCall(
6311 stub, UntaggedPcDescriptors::kOther, locs);
6313 compiler->RestoreLiveRegisters(locs);
6323 __ TryAllocate(cls,
compiler->intrinsic_slow_path_label(),
6328 compiler->AddSlowPathCode(slow_path);
6330 if (FLAG_inline_alloc && !FLAG_use_slow_path) {
6331 __ TryAllocate(cls, slow_path->entry_label(),
6334 __ Jump(slow_path->entry_label());
6336 __ Bind(slow_path->exit_label());
6341 __ Comment(
"DoubleToIntegerSlowPath");
6349 auto slow_path_env =
6357 StubCode::DoubleToInteger(),
6358 UntaggedPcDescriptors::kOther, locs,
6367 const intptr_t box_cid = BoxCid();
6368 ASSERT(box_cid != kSmiCid);
6369 const Register box = locs()->in(0).reg();
6371 (locs()->temp_count() > 0) ? locs()->temp(0).reg() :
kNoRegister;
6373 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnbox);
6376 if ((
value()->
Type()->ToNullableCid() == box_cid) &&
6378 __ CompareObject(box, Object::null_object());
6381 __ BranchIfSmi(box, CanConvertSmi() ? &is_smi : deopt);
6382 __ CompareClassId(box, box_cid, temp);
6389 compiler::Label
done;
6397void UnboxInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
6398 if (SpeculativeModeOfInputs() == kNotSpeculative) {
6399 if (BoxCid() == kSmiCid) {
6402 return EmitSmiConversion(
compiler);
6405 case kUnboxedDouble:
6407 case kUnboxedFloat32x4:
6408 case kUnboxedFloat64x2:
6409 case kUnboxedInt32x4:
6414 EmitLoadInt32FromBoxOrSmi(
compiler);
6417 case kUnboxedInt64: {
6418 if (
value()->
Type()->ToCid() == kSmiCid) {
6423 EmitLoadInt64FromBoxOrSmi(
compiler);
6432 ASSERT(SpeculativeModeOfInputs() == kGuardInputs);
6434 const intptr_t box_cid = BoxCid();
6436 if (box_cid == kSmiCid || (CanConvertSmi() && (value_cid == kSmiCid))) {
6440 EmitLoadInt32FromBoxOrSmi(
compiler);
6442 EmitLoadInt64FromBoxOrSmi(
compiler);
6443 }
else if ((value_cid == box_cid) || !CanDeoptimize()) {
6446 EmitLoadFromBoxWithDeopt(
compiler);
6453 intptr_t fixed_parameter_count,
6454 intptr_t lazy_deopt_pruning_count,
6458 parsed_function.
function(),
nullptr);
6459 for (intptr_t i = 0; i < definitions.
length(); ++i) {
6460 env->values_.Add(
new (zone)
Value(definitions[i]));
6473 (outer_ ==
nullptr) ?
nullptr : outer_->DeepCopy(zone));
6477 copy->MarkAsHoisted();
6479 if (locations_ !=
nullptr) {
6481 copy->set_locations(new_locations);
6483 for (intptr_t i = 0; i <
length; ++i) {
6484 copy->values_.Add(values_[i]->CopyWithType(zone));
6485 if (locations_ !=
nullptr) {
6486 copy->locations_[i] = locations_[i].
Copy();
6495 it.CurrentValue()->RemoveFromUseList();
6512 it.CurrentValue()->RemoveFromUseList();
6517 copy->SetLazyDeoptPruneCount(0);
6518 for (intptr_t i = 0; i < argc; i++) {
6519 copy->values_.Add(
new (zone)
Value(dead));
6534 intptr_t outer_deopt_id)
const {
6540 outer->SetDeoptId(outer_deopt_id);
6541 outer->SetLazyDeoptPruneCount(0);
6543 intptr_t use_index = instr->
env()->
Length();
6546 value->set_instruction(instr);
6547 value->set_use_index(use_index++);
6568 operation_cid(), deopt_id(),
6569 SpeculativeModeOfInputs());
6592 value_representation_);
6596 auto const other_instr = other.AsTestCids();
6604 if (
cid_results()[i] != other_instr->cid_results()[i]) {
6612 auto const other_instr = other.AsTestRange();
6616 return lower_ == other_instr->lower_ && upper_ == other_instr->upper_ &&
6617 value_representation_ == other_instr->value_representation_;
6627 return is_smi_result &&
6628 !
comparison->AsStrictCompare()->needs_number_check();
6634 return is_smi_result;
6640 for (intptr_t i = 1; i <
InputCount(); ++i) {
6642 if (def != first)
return false;
6654 bool look_for_redefinition =
false;
6655 for (intptr_t i = 1; i <
InputCount(); ++i) {
6657 if ((def != first) && (def !=
this)) {
6659 if ((origin != first_origin) && (origin !=
this))
return nullptr;
6660 look_for_redefinition =
true;
6663 if (look_for_redefinition) {
6667 for (intptr_t i = 1, n =
InputCount(); redef != first_origin && i < n;) {
6672 if ((def == redef) || (def ==
this)) {
6677 }
while (
value !=
nullptr);
6681 ASSERT(redef != first_origin);
6692 for (intptr_t i = 0; i < phi->
InputCount(); i++) {
6710 auto zone = flow_graph->
zone();
6719 if (use->instruction() ==
block()) {
6721 use->set_definition(replacement);
6728 return (replacement !=
nullptr) ? replacement :
this;
6734 (*phis_)[index_] = phis_->Last();
6735 phis_->RemoveLast();
6741 if ((
InputAt(0)->definition()->OriginalDefinition() ==
6742 InputAt(1)->definition()->OriginalDefinition()) &&
6743 strict_compare->kind() == Token::kEQ_STRICT) {
6758 compiler::Label if_true;
6759 compiler::Label* if_false =
6761 BranchLabels labels = {&if_true, if_false, &if_true};
6781 return compiler::target::TypedDataBase::length_offset();
6785 case kGrowableObjectArrayCid:
6786 return compiler::target::GrowableObjectArray::length_offset();
6787 case kOneByteStringCid:
6788 case kTwoByteStringCid:
6789 return compiler::target::String::length_offset();
6791 case kImmutableArrayCid:
6792 return compiler::target::Array::length_offset();
6820 case kUnboxedFloat32x4:
6821 case kUnboxedInt32x4:
6822 case kUnboxedFloat64x2:
6834 intptr_t index_scale,
6841 index_unboxed_(index_unboxed),
6842 index_scale_(index_scale),
6843 class_id_(class_id),
6845 token_pos_(
source.token_pos),
6846 result_type_(result_type) {
6859 if (
auto box =
index()->definition()->AsBoxInt64()) {
6861 if (!box->ComputeCanDeoptimize() && compiler::target::kWordSize == 8) {
6862 auto Z = flow_graph->
zone();
6866 GetDeoptId(),
source(), result_type_);
6884 intptr_t index_scale,
6889 SpeculativeMode speculative_mode)
6891 emit_store_barrier_(emit_store_barrier),
6892 index_unboxed_(index_unboxed),
6893 index_scale_(index_scale),
6894 class_id_(class_id),
6896 token_pos_(
source.token_pos),
6897 speculative_mode_(speculative_mode) {
6911 if (
auto box =
index()->definition()->AsBoxInt64()) {
6913 if (!box->ComputeCanDeoptimize() && compiler::target::kWordSize == 8) {
6914 auto Z = flow_graph->
zone();
6919 GetDeoptId(),
source(), speculative_mode_);
6933 intptr_t idx)
const {
6935 if (idx == 0)
return kNoRepresentation;
6937 if (index_unboxed_) {
6938#if defined(TARGET_ARCH_IS_64_BIT)
6939 return kUnboxedInt64;
6943 return kNoRepresentation;
6953#if defined(TARGET_ARCH_ARM64)
6958 compiler::target::kWordSize;
6965 if (!
length()->BindsToSmiConstant()) {
6967 }
else if (
length()->BoundSmiConstant() == 0) {
6972 if (!
src_start()->BindsToSmiConstant() ||
6982 intptr_t new_element_size = element_size_;
6983 while (((new_length | new_src_start | new_dest_start) & 1) == 0 &&
6986 new_src_start >>= 1;
6987 new_dest_start >>= 1;
6988 new_element_size <<= 1;
6990 if (new_element_size == element_size_) {
6997 auto*
const Z = flow_graph->
zone();
6998 auto*
const length_instr =
7000 auto*
const src_start_instr =
7002 auto*
const dest_start_instr =
7007 element_size_ = new_element_size;
7008 unboxed_inputs_ =
false;
7017 const bool constant_length = length_loc.
IsConstant();
7019 const intptr_t num_elements =
7020 constant_length ? Integer::Cast(length_loc.
constant()).AsInt64Value()
7024 ASSERT(!constant_length || num_elements > 0);
7026#if defined(TARGET_ARCH_IA32)
7032 const Register src_payload_reg = locs()->temp(0).reg();
7033 const Register dest_payload_reg = locs()->temp(1).reg();
7044 EmitComputeStartPointer(
compiler, src_cid_, src_reg, src_payload_reg,
7045 src_rep, src_start_loc);
7046 EmitComputeStartPointer(
compiler, dest_cid_, dest_reg, dest_payload_reg,
7047 dest_rep, dest_start_loc);
7050 compiler::Label copy_forwards,
done;
7051 if (!constant_length) {
7052#if defined(TARGET_ARCH_IA32)
7054 __ PushRegister(
ESI);
7060 __ CompareRegisters(dest_payload_reg, src_payload_reg);
7074#if defined(USING_MEMORY_SANITIZER)
7080 __ Comment(
"Copying backwards");
7081 if (constant_length) {
7083 num_elements,
true);
7086 &
done, ©_forwards);
7088 __ Jump(&
done, jump_distance);
7089 __ Comment(
"Copying forwards");
7091 __ Bind(©_forwards);
7092 if (constant_length) {
7100#if defined(TARGET_ARCH_IA32)
7101 if (!constant_length) {
7103 __ PopRegister(
ESI);
7109#if !defined(TARGET_ARCH_ARM)
7113 intptr_t num_elements,
7115 ASSERT(element_size_ <= 16);
7116 const intptr_t num_bytes = num_elements * element_size_;
7117#if defined(TARGET_ARCH_ARM64)
7119 const intptr_t mov_size = element_size_;
7121 const intptr_t mov_size =
7122 Utils::Minimum<intptr_t>(element_size_, compiler::target::kWordSize);
7124 const intptr_t mov_repeat = num_bytes / mov_size;
7125 ASSERT(num_bytes % mov_size == 0);
7127#if defined(TARGET_ARCH_IA32)
7129 const Register temp_reg = locs()->temp(0).reg();
7133 for (intptr_t i = 0; i < mov_repeat; i++) {
7134 const intptr_t
offset = (reversed ? (mov_repeat - (i + 1)) : i) * mov_size;
7141 __ LoadFromOffset(temp_reg, src_reg,
offset,
7143 __ StoreToOffset(temp_reg, dest_reg,
offset,
7147 __ LoadFromOffset(temp_reg, src_reg,
offset,
7149 __ StoreToOffset(temp_reg, dest_reg,
offset,
7153#if defined(TARGET_ARCH_IS_64_BIT)
7161#if defined(TARGET_ARCH_ARM64)
7178#if defined(USING_MEMORY_SANITIZER) && defined(TARGET_ARCH_X64)
7181 __ PushRegisters(kVolatileRegisterSet);
7182 __ MsanUnpoison(dest_reg, num_bytes);
7183 __ PopRegisters(kVolatileRegisterSet);
7198 recognized_kind_(recognized_kind),
7199 token_pos_(
source.token_pos) {
7206 case MethodRecognizer::kDoubleTruncateToDouble:
7207 case MethodRecognizer::kDoubleFloorToDouble:
7208 case MethodRecognizer::kDoubleCeilToDouble:
7209 case MethodRecognizer::kDoubleRoundToDouble:
7210 case MethodRecognizer::kMathAtan:
7211 case MethodRecognizer::kMathTan:
7212 case MethodRecognizer::kMathAcos:
7213 case MethodRecognizer::kMathAsin:
7214 case MethodRecognizer::kMathSin:
7215 case MethodRecognizer::kMathCos:
7216 case MethodRecognizer::kMathExp:
7217 case MethodRecognizer::kMathLog:
7219 case MethodRecognizer::kDoubleMod:
7220 case MethodRecognizer::kMathDoublePow:
7221 case MethodRecognizer::kMathAtan2:
7230 switch (recognized_kind_) {
7231 case MethodRecognizer::kDoubleTruncateToDouble:
7232 return kLibcTruncRuntimeEntry;
7233 case MethodRecognizer::kDoubleRoundToDouble:
7234 return kLibcRoundRuntimeEntry;
7235 case MethodRecognizer::kDoubleFloorToDouble:
7236 return kLibcFloorRuntimeEntry;
7237 case MethodRecognizer::kDoubleCeilToDouble:
7238 return kLibcCeilRuntimeEntry;
7239 case MethodRecognizer::kMathDoublePow:
7240 return kLibcPowRuntimeEntry;
7241 case MethodRecognizer::kDoubleMod:
7242 return kDartModuloRuntimeEntry;
7243 case MethodRecognizer::kMathTan:
7244 return kLibcTanRuntimeEntry;
7245 case MethodRecognizer::kMathAsin:
7246 return kLibcAsinRuntimeEntry;
7247 case MethodRecognizer::kMathSin:
7248 return kLibcSinRuntimeEntry;
7249 case MethodRecognizer::kMathCos:
7250 return kLibcCosRuntimeEntry;
7251 case MethodRecognizer::kMathAcos:
7252 return kLibcAcosRuntimeEntry;
7253 case MethodRecognizer::kMathAtan:
7254 return kLibcAtanRuntimeEntry;
7255 case MethodRecognizer::kMathAtan2:
7256 return kLibcAtan2RuntimeEntry;
7257 case MethodRecognizer::kMathExp:
7258 return kLibcExpRuntimeEntry;
7259 case MethodRecognizer::kMathLog:
7260 return kLibcLogRuntimeEntry;
7264 return kLibcPowRuntimeEntry;
7275 case Token::kTRUNCDIV:
7286 bool optimizing)
const {
7319 const int num_params =
7321 bool auto_setup_scope =
true;
7323 library,
native_name(), num_params, &auto_setup_scope);
7324 if (native_function ==
nullptr) {
7330 "native function '%s' (%" Pd " arguments) cannot be found",
7334 set_native_c_function(native_function);
7337#if !defined(TARGET_ARCH_ARM) && !defined(TARGET_ARCH_ARM64) && \
7338 !defined(TARGET_ARCH_RISCV32) && !defined(TARGET_ARCH_RISCV64)
7344void BitCastInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
7356 if (marshaller_.IsHandleCType(marshaller_.ArgumentIndex(idx))) {
7359 return marshaller_.RepInFfiCall(idx);
7366 return kNoRepresentation;
7375LocationSummary* FfiCallInstr::MakeLocationSummaryInternal(
7379 auto contains_call =
7382 LocationSummary* summary =
new (zone) LocationSummary(
7388 if ((temps & (1 << reg)) != 0) {
7389 summary->set_temp(reg_i,
7395#if defined(TARGET_ARCH_X64) && !defined(DART_TARGET_OS_WINDOWS)
7398 marshaller_.contains_varargs()
7404#define R(r) (1 << r)
7409 for (intptr_t i = 0, n = marshaller_.NumArgumentDefinitions(); i < n; ++i) {
7410 summary->set_in(i, marshaller_.LocInFfiCall(i));
7413 if (marshaller_.ReturnsCompound()) {
7425 __ Comment(
"EmitParamMoves");
7428 const auto& return_location =
7430 if (return_location.IsPointerToMemory()) {
7431 __ Comment(
"return_location.IsPointerToMemory");
7432 const auto& pointer_location =
7433 return_location.AsPointerToMemory().pointer_location();
7434 const auto& pointer_register =
7435 pointer_location.IsRegisters()
7436 ? pointer_location.AsRegisters().reg_at(0)
7438 __ MoveRegister(pointer_register,
SPREG);
7439 __ AddImmediate(pointer_register, marshaller_.PassByPointerStackOffset(
7442 if (pointer_location.IsStack()) {
7443 const auto& pointer_stack = pointer_location.AsStack();
7444 __ StoreMemoryValue(pointer_register, pointer_stack.base_register(),
7445 pointer_stack.offset_in_bytes());
7453 intptr_t def_index = 0;
7454 for (intptr_t arg_index = 0; arg_index < marshaller_.num_args();
7456 const intptr_t num_defs = marshaller_.NumDefinitions(arg_index);
7457 const auto& arg_target = marshaller_.Location(arg_index);
7458 __ Comment(
"arg_index %" Pd " arg_target %s", arg_index,
7459 arg_target.ToCString());
7463 for (intptr_t i = 0; i < num_defs; i++) {
7464 if ((arg_target.IsPointerToMemory() ||
7465 marshaller_.IsCompoundPointer(arg_index)) &&
7473 __ Comment(
" def_index %" Pd, def_index);
7479 const auto& def_target =
7480 arg_target.payload_type().IsPrimitive() ? arg_target
7481 : arg_target.IsMultiple() ? *arg_target.AsMultiple().locations()[i]
7482 : arg_target.IsPointerToMemory()
7483 ? arg_target.AsPointerToMemory().pointer_location()
7484 : arg_target.Split(
compiler->zone(),
7489 __ Comment(
"origin.IsConstant()");
7490 ASSERT(!marshaller_.IsHandleCType(arg_index));
7491 ASSERT(!marshaller_.IsTypedDataPointer(arg_index));
7492 ASSERT(!marshaller_.IsCompoundPointer(arg_index));
7493 compiler->EmitMoveConst(def_target, origin, origin_rep, &temp_alloc);
7498 __ Comment(
"origin.IsPairLocation() and constant");
7499 ASSERT(!marshaller_.IsHandleCType(arg_index));
7500 ASSERT(!marshaller_.IsTypedDataPointer(arg_index));
7501 ASSERT(!marshaller_.IsCompoundPointer(arg_index));
7502 compiler->EmitMoveConst(def_target, origin, origin_rep, &temp_alloc);
7503 }
else if (marshaller_.IsHandleCType(arg_index)) {
7504 __ Comment(
"marshaller_.IsHandleCType(arg_index)");
7507 ASSERT(origin_rep == kTagged);
7508 ASSERT(compiler::target::LocalHandle::ptr_offset() == 0);
7509 ASSERT(compiler::target::LocalHandle::InstanceSize() ==
7510 compiler::target::kWordSize);
7513 if (def_target.IsRegisters()) {
7514 __ AddImmediate(def_target.AsLocation().reg(), origin.
base_reg(),
7515 origin.
stack_index() * compiler::target::kWordSize);
7517 ASSERT(def_target.IsStack());
7518 const auto& target_stack = def_target.AsStack();
7520 origin.
stack_index() * compiler::target::kWordSize);
7521 __ StoreToOffset(temp0, target_stack.base_register(),
7522 target_stack.offset_in_bytes());
7525 __ Comment(
"def_target %s <- origin %s %s",
7534 if (def_target.IsStack()) {
7535 const auto& def_target_stack = def_target.AsStack();
7536 ASSERT(def_target_stack.offset_in_bytes() +
7537 def_target.payload_type().SizeInBytes() <=
7538 marshaller_.RequiredStackSpaceInBytes());
7541 if (marshaller_.IsTypedDataPointer(arg_index) ||
7542 marshaller_.IsCompoundPointer(arg_index)) {
7544 __ Comment(
"Load typed data base address");
7551 __ LoadFromSlot(origin.
reg(), origin.
reg(), Slot::PointerBase_data());
7552 if (marshaller_.IsCompoundPointer(arg_index)) {
7553 __ Comment(
"Load offset in bytes");
7554 const intptr_t offset_in_bytes_def_index = def_index + 1;
7555 const Location offset_in_bytes_loc =
7556 rebase.
Rebase(
locs()->in(offset_in_bytes_def_index));
7559 offset_in_bytes_reg = offset_in_bytes_loc.
reg();
7561 offset_in_bytes_reg = temp1;
7565 offset_in_bytes_loc, &no_temp);
7567 __ AddRegisters(origin.
reg(), offset_in_bytes_reg);
7570 compiler->EmitMoveToNative(def_target, origin, origin_rep, &temp_alloc);
7579 if (arg_target.IsPointerToMemory()) {
7580 __ Comment(
"arg_target.IsPointerToMemory");
7582 const auto& pointer_loc =
7583 arg_target.AsPointerToMemory().pointer_location();
7587 compiler->zone(), pointer_loc.payload_type(),
7588 pointer_loc.container_type(), temp0);
7589 compiler->EmitNativeMove(dst, pointer_loc, &temp_alloc);
7590 __ LoadFromSlot(temp0, temp0, Slot::PointerBase_data());
7592 __ Comment(
"IsPointerToMemory add offset");
7593 const intptr_t offset_in_bytes_def_index =
7595 const Location offset_in_bytes_loc =
7596 rebase.
Rebase(
locs()->in(offset_in_bytes_def_index));
7599 offset_in_bytes_reg = offset_in_bytes_loc.
reg();
7601 offset_in_bytes_reg = temp1;
7604 offset_in_bytes_loc, &no_temp);
7606 __ AddRegisters(temp0, offset_in_bytes_reg);
7612 __ Comment(
"IsPointerToMemory copy chunks");
7613 const intptr_t sp_offset =
7614 marshaller_.PassByPointerStackOffset(arg_index);
7615 __ UnrolledMemCopy(
SPREG, sp_offset, temp0, 0,
7616 arg_target.payload_type().SizeInBytes(), temp1);
7619 __ MoveRegister(temp0,
SPREG);
7620 __ AddImmediate(temp0, sp_offset);
7622 compiler->zone(), pointer_loc.payload_type(),
7623 pointer_loc.container_type(), temp0);
7624 __ Comment(
"pointer_loc %s <- src %s", pointer_loc.ToCString(),
7626 compiler->EmitNativeMove(pointer_loc, src, &temp_alloc);
7630 __ Comment(
"EmitParamMovesEnd");
7636 const auto& returnLocation =
7638 if (returnLocation.payload_type().IsVoid()) {
7642 __ Comment(
"EmitReturnMoves");
7645 if (returnLocation.IsRegisters() || returnLocation.IsFpuRegisters()) {
7646 const auto& src = returnLocation;
7649 compiler->EmitMoveFromNative(dst_loc, dst_type, src, &no_temp);
7650 }
else if (marshaller_.ReturnsCompound()) {
7651 ASSERT(returnLocation.payload_type().IsCompound());
7670 __ LoadFromSlot(temp0, temp0, Slot::PointerBase_data());
7672 if (returnLocation.IsPointerToMemory()) {
7677 const intptr_t sp_offset =
7679 __ UnrolledMemCopy(temp0, 0,
SPREG, sp_offset,
7680 marshaller_.CompoundReturnSizeInBytes(), temp1);
7682 ASSERT(returnLocation.IsMultiple());
7684 const auto& multiple =
7687 int offset_in_bytes = 0;
7688 for (
int i = 0; i < multiple.locations().
length(); i++) {
7689 const auto& src = *multiple.locations().At(i);
7691 src.payload_type(), src.container_type(), temp0, offset_in_bytes);
7692 compiler->EmitNativeMove(dst, src, &no_temp);
7693 offset_in_bytes += src.payload_type().SizeInBytes();
7700 __ Comment(
"EmitReturnMovesEnd");
7705 const intptr_t kNumInputs = 2;
7706#if defined(TARGET_ARCH_IA32)
7709 const intptr_t kNumTemps = 0;
7716 if (rep == kUntagged) {
7720 if (value_size <= compiler::target::kWordSize) {
7723 ASSERT(value_size == 2 * compiler::target::kWordSize);
7730 summary->
set_in(kValuePos,
7733#if defined(TARGET_ARCH_IA32)
7737#elif defined(TARGET_ARCH_X64)
7741#elif defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_RISCV32) || \
7742 defined(TARGET_ARCH_RISCV64)
7746 if (
auto constant =
value()->definition()->AsConstant()) {
7747 const auto&
value = constant->value();
7752 summary->
set_in(kValuePos, value_loc);
7758 if (kNumTemps == 1) {
7766void StoreFieldInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
7767 const Register instance_reg = locs()->
in(kInstancePos).
reg();
7773 if (rep == kUntagged) {
7774 __ StoreToSlotNoBarrier(locs()->in(kValuePos).reg(), instance_reg,
slot(),
7778 if (value_size <= compiler::target::kWordSize) {
7779 __ StoreToSlotNoBarrier(locs()->in(kValuePos).reg(), instance_reg,
slot(),
7782 ASSERT(
slot().representation() == kUnboxedInt64);
7784 auto const value_pair = locs()->in(kValuePos).AsPairLocation();
7785 const Register value_lo = value_pair->At(0).reg();
7786 const Register value_hi = value_pair->At(1).reg();
7788 __ StoreFieldToOffset(value_hi, instance_reg,
7797 __ StoreUnboxedDouble(
value, instance_reg,
7802 __ StoreUnboxedSimd128(
value, instance_reg,
7810 locs()->temp_count() > 0 ? locs()->temp(0).reg() :
TMP;
7811 __ StoreToSlot(locs()->in(kValuePos).reg(), instance_reg,
slot(),
7813 }
else if (locs()->in(kValuePos).
IsConstant()) {
7814 const auto&
value = locs()->in(kValuePos).constant();
7817 __ StoreObjectIntoObjectOffsetNoBarrier(instance_reg,
OffsetInBytes(),
7818 value, memory_order_, size);
7820 __ StoreToSlotNoBarrier(locs()->in(kValuePos).reg(), instance_reg,
slot(),
7825const Code& DartReturnInstr::GetReturnStub(FlowGraphCompiler*
compiler)
const {
7833 ->return_async_not_future_stub());
7837 compiler->isolate_group()->object_store()->return_async_stub());
7838 }
else if (
function.IsAsyncGenerator()) {
7841 compiler->isolate_group()->object_store()->return_async_star_stub());
7847void NativeReturnInstr::EmitReturnMoves(FlowGraphCompiler*
compiler) {
7849 if (dst1.payload_type().IsVoid()) {
7852 if (dst1.IsMultiple()) {
7853 __ Comment(
"Load TypedDataBase data pointer and apply offset.");
7857 __ LoadFromSlot(typed_data_reg, typed_data_reg, Slot::PointerBase_data());
7861 __ AddRegisters(typed_data_reg, offset_reg);
7863 __ Comment(
"Copy loop");
7864 const auto& multiple = dst1.AsMultiple();
7865 int offset_in_bytes = 0;
7866 for (intptr_t i = 0; i < multiple.locations().
length(); i++) {
7867 const auto&
dst = *multiple.locations().At(i);
7869 dst.AsRegisters().reg_at(0) != typed_data_reg);
7870 const auto&
src = compiler::ffi::NativeStackLocation(
7871 dst.payload_type(),
dst.container_type(), typed_data_reg,
7873 NoTemporaryAllocator no_temp;
7874 compiler->EmitNativeMove(dst, src, &no_temp);
7875 offset_in_bytes +=
dst.payload_type().SizeInBytes();
7879 const auto&
dst = dst1.IsPointerToMemory()
7880 ? dst1.AsPointerToMemory().pointer_return_location()
7885 NoTemporaryAllocator no_temp;
7886 compiler->EmitMoveToNative(dst, src_loc, src_type, &no_temp);
7891 const intptr_t input_count = marshaller_.NumReturnDefinitions();
7892 const intptr_t kNumTemps = 0;
7893 LocationSummary*
locs =
new (zone)
7897 if (native_loc.IsMultiple()) {
7912 const auto& native_return_loc =
7913 native_loc.IsPointerToMemory()
7914 ? native_loc.AsPointerToMemory().pointer_return_location()
7916 locs->
set_in(0, native_return_loc.AsLocation());
7921LocationSummary* RecordCoverageInstr::MakeLocationSummary(Zone* zone,
7923 const intptr_t kNumInputs = 0;
7924 const intptr_t kNumTemps = 2;
7925 LocationSummary* locs =
new (zone)
7932void RecordCoverageInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
7933 const auto array_temp = locs()->temp(0).reg();
7934 const auto value_temp = locs()->temp(1).reg();
7936 __ LoadObject(array_temp, coverage_array_);
7938 __ StoreFieldToOffset(
7939 value_temp, array_temp,
7940 compiler::target::Array::element_offset(coverage_index_),
7947 if (marshaller_.ReturnsCompound()) {
7961 __ MoveRegister(out,
THR);
7974 if ((temps & (1 << reg)) != 0) {
7985 const auto& argument_locations =
7987 for (intptr_t i = 0, n = argument_locations.length(); i < n; ++i) {
7988 const auto& argument_location = *argument_locations.
At(i);
7989 if (argument_location.IsRegisters()) {
7990 const auto& reg_location = argument_location.AsRegisters();
7991 ASSERT(reg_location.num_regs() == 1);
7992 summary->
set_in(i, reg_location.AsLocation());
7993 }
else if (argument_location.IsFpuRegisters()) {
7995 }
else if (argument_location.IsStack()) {
8001 const auto& return_location = native_calling_convention_.
return_location();
8002 ASSERT(return_location.IsRegisters());
8003 summary->
set_out(0, return_location.AsLocation());
8007LeafRuntimeCallInstr::LeafRuntimeCallInstr(
8013 return_representation_(return_representation),
8014 argument_representations_(argument_representations),
8015 native_calling_convention_(native_calling_convention) {
8017 const intptr_t num_inputs = argument_representations.
length() + 1;
8031 const auto& native_function_type =
8033 zone, return_representation, argument_representations);
8034 const auto& native_calling_convention =
8036 zone, native_function_type);
8039 native_calling_convention, std::move(
inputs));
8054 __ Comment(
"EmitParamMoves");
8055 const auto& argument_locations =
8057 for (intptr_t i = 0, n = argument_locations.length(); i < n; ++i) {
8058 const auto& argument_location = *argument_locations.
At(i);
8059 if (argument_location.IsRegisters()) {
8060 const auto& reg_location = argument_location.AsRegisters();
8061 ASSERT(reg_location.num_regs() == 1);
8064 compiler->EmitMoveToNative(argument_location, src_loc, src_rep,
8066 }
else if (argument_location.IsFpuRegisters()) {
8068 }
else if (argument_location.IsStack()) {
8071 __ Comment(
"Param %" Pd ": %s %s -> %s", i, src_loc.
ToCString(),
8073 argument_location.ToCString());
8074 compiler->EmitMoveToNative(argument_location, src_loc, src_rep,
8080 __ Comment(
"EmitParamMovesEnd");
8087 case MethodRecognizer::kFloat32x4Mul:
8088 return SimdOpInstr::kFloat32x4Mul;
8089 case MethodRecognizer::kFloat32x4Div:
8090 return SimdOpInstr::kFloat32x4Div;
8091 case MethodRecognizer::kFloat32x4Add:
8092 return SimdOpInstr::kFloat32x4Add;
8093 case MethodRecognizer::kFloat32x4Sub:
8094 return SimdOpInstr::kFloat32x4Sub;
8095 case MethodRecognizer::kFloat64x2Mul:
8096 return SimdOpInstr::kFloat64x2Mul;
8097 case MethodRecognizer::kFloat64x2Div:
8098 return SimdOpInstr::kFloat64x2Div;
8099 case MethodRecognizer::kFloat64x2Add:
8100 return SimdOpInstr::kFloat64x2Add;
8101 case MethodRecognizer::kFloat64x2Sub:
8102 return SimdOpInstr::kFloat64x2Sub;
8117 case MethodRecognizer::kFloat32x4Mul:
8118 case MethodRecognizer::kFloat32x4Div:
8119 case MethodRecognizer::kFloat32x4Add:
8120 case MethodRecognizer::kFloat32x4Sub:
8121 case MethodRecognizer::kFloat64x2Mul:
8122 case MethodRecognizer::kFloat64x2Div:
8123 case MethodRecognizer::kFloat64x2Add:
8124 case MethodRecognizer::kFloat64x2Sub:
8127#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
8128 case MethodRecognizer::kFloat32x4GreaterThan:
8132 SimdOpInstr(SimdOpInstr::kFloat32x4LessThan, call->deopt_id());
8133 op->
SetInputAt(0, call->ArgumentValueAt(1)->CopyWithType(zone));
8136 case MethodRecognizer::kFloat32x4GreaterThanOrEqual:
8140 SimdOpInstr(SimdOpInstr::kFloat32x4LessThanOrEqual, call->deopt_id());
8141 op->
SetInputAt(0, call->ArgumentValueAt(1)->CopyWithType(zone));
8150 if (receiver !=
nullptr) {
8153 for (intptr_t i = (receiver !=
nullptr ? 1 : 0); i < op->
InputCount(); i++) {
8154 op->
SetInputAt(i, call->ArgumentValueAt(i)->CopyWithType(zone));
8156 if (op->HasMask()) {
8159 ASSERT(call->ArgumentCount() == (op->
InputCount() + (op->HasMask() ? 1 : 0)));
8169 for (intptr_t i = 0; i < op->
InputCount(); i++) {
8171 op->
SetInputAt(i, call->ArgumentValueAt(i + 1)->CopyWithType(zone));
8182 return kFloat32x4Add;
8184 return kFloat32x4Sub;
8186 return kFloat32x4Mul;
8188 return kFloat32x4Div;
8197 return kFloat64x2Add;
8199 return kFloat64x2Sub;
8201 return kFloat64x2Mul;
8203 return kFloat64x2Div;
8215 case Token::kBIT_AND:
8216 return kInt32x4BitAnd;
8217 case Token::kBIT_OR:
8218 return kInt32x4BitOr;
8219 case Token::kBIT_XOR:
8220 return kInt32x4BitXor;
8233#define CASE_METHOD(Arity, Mask, Name, ...) \
8234 case MethodRecognizer::k##Name: \
8236#define CASE_BINARY_OP(Arity, Mask, Name, Args, Result)
8239#undef CASE_BINARY_OP
8262 return rep == kUnboxedInt8 ? kUnboxedInt32 : rep;
8266#define REP(T) (SimdRepresentation(kUnboxed##T))
8269#define ENCODE_INPUTS_0()
8270#define ENCODE_INPUTS_1(In0) REP(In0)
8271#define ENCODE_INPUTS_2(In0, In1) REP(In0), REP(In1)
8272#define ENCODE_INPUTS_3(In0, In1, In2) REP(In0), REP(In1), REP(In2)
8273#define ENCODE_INPUTS_4(In0, In1, In2, In3) \
8274 REP(In0), REP(In1), REP(In2), REP(In3)
8277#define HAS_MASK true
8282#define CASE(Arity, Mask, Name, Args, Result) \
8283 {Arity, HAS_##Mask, REP(Result), {PP_APPLY(ENCODE_INPUTS_##Arity, Args)}},
8289#undef ENCODE_INFORMATION
8292#undef ENCODE_INPUTS_0
8293#undef ENCODE_INPUTS_1
8294#undef ENCODE_INPUTS_2
8295#undef ENCODE_INPUTS_3
8296#undef ENCODE_INPUTS_4
8312bool SimdOpInstr::HasMask()
const {
8317 if ((
kind() == SimdOpInstr::kFloat64x2FromDoubles) &&
8318 InputAt(0)->BindsToConstant() &&
InputAt(1)->BindsToConstant()) {
8321 if (
x.IsDouble() &&
y.IsDouble()) {
8328 if ((
kind() == SimdOpInstr::kFloat32x4FromDoubles) &&
8329 InputAt(0)->BindsToConstant() &&
InputAt(1)->BindsToConstant() &&
8330 InputAt(2)->BindsToConstant() &&
InputAt(3)->BindsToConstant()) {
8335 if (
x.IsDouble() &&
y.IsDouble() && z.IsDouble() &&
w.IsDouble()) {
8343 if ((
kind() == SimdOpInstr::kInt32x4FromInts) &&
8344 InputAt(0)->BindsToConstant() &&
InputAt(1)->BindsToConstant() &&
8345 InputAt(2)->BindsToConstant() &&
InputAt(3)->BindsToConstant()) {
8350 if (
x.IsInteger() &&
y.IsInteger() && z.IsInteger() &&
w.IsInteger()) {
8352 Integer::Cast(
x).AsInt64Value(), Integer::Cast(
y).AsInt64Value(),
8353 Integer::Cast(z).AsInt64Value(), Integer::Cast(
w).AsInt64Value(),
8365 const intptr_t kNumInputs = 1;
8366 const intptr_t kNumTemps = 0;
8389void Call1ArgStubInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
8390 ObjectStore* object_store =
compiler->isolate_group()->object_store();
8394 stub = object_store->clone_suspend_state_stub();
8397 stub = object_store->init_async_stub();
8400 stub = object_store->init_async_star_stub();
8403 stub = object_store->init_sync_star_stub();
8406 stub = object_store->ffi_async_callback_send_stub();
8409 compiler->GenerateStubCall(
source(), stub, UntaggedPcDescriptors::kOther,
8410 locs(), deopt_id(),
env());
8424 const intptr_t kNumTemps = 0;
8435void SuspendInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
8439 ObjectStore* object_store =
compiler->isolate_group()->object_store();
8443 stub = object_store->await_stub();
8446 stub = object_store->await_with_type_check_stub();
8449 stub = object_store->yield_async_star_stub();
8452 stub = object_store->suspend_sync_star_at_start_stub();
8455 stub = object_store->suspend_sync_star_at_yield_stub();
8458 compiler->GenerateStubCall(
source(), stub, UntaggedPcDescriptors::kOther,
8459 locs(), deopt_id(),
env());
8461#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_IA32)
8473 UntaggedPcDescriptors::kOther, locs(),
env());
8479 const intptr_t kNumInputs = 0;
8480 const intptr_t kNumTemps = 0;
8481 LocationSummary*
locs =
new (zone)
8490 compiler->isolate_group()->object_store()->allocate_record_stub());
8493 compiler->GenerateStubCall(
source(), stub, UntaggedPcDescriptors::kOther,
8501 const intptr_t kNumTemps = 0;
8502 LocationSummary*
locs =
new (zone)
8518 auto object_store =
compiler->isolate_group()->object_store();
8520 if (
shape().HasNamedFields()) {
8525 stub = object_store->allocate_record2_named_stub();
8528 stub = object_store->allocate_record3_named_stub();
8536 stub = object_store->allocate_record2_stub();
8539 stub = object_store->allocate_record3_stub();
8545 compiler->GenerateStubCall(
source(), stub, UntaggedPcDescriptors::kOther,
8549LocationSummary* MakePairInstr::MakeLocationSummary(Zone* zone,
8552 const intptr_t kNumInputs = 2;
8553 const intptr_t kNumTemps = 0;
8554 LocationSummary* locs =
new (zone)
8570void MakePairInstr::EmitNativeCode(FlowGraphCompiler*
compiler) {
static int step(int x, SkScalar min, SkScalar max)
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 void is_empty(skiatest::Reporter *reporter, const SkPath &p)
static float next(float f)
static float prev(float f)
static std::unique_ptr< SkEncoder > Make(SkWStream *dst, const SkPixmap *src, const SkYUVAPixmaps *srcYUVA, const SkColorSpace *srcYUVAColorSpace, const SkJpegEncoder::Options &options)
static bool is_integer(SkScalar x)
static bool left(const SkPoint &p0, const SkPoint &p1)
static bool right(const SkPoint &p0, const SkPoint &p1)
#define DEBUG_ASSERT(cond)
#define ASSERT_EQUAL(expected, actual)
#define RELEASE_ASSERT(cond)
bool IsSubtypeOf(const AbstractType &other, Heap::Space space, FunctionTypeMapping *function_type_equivalence=nullptr) const
bool IsTopTypeForSubtyping() const
virtual AbstractTypePtr Canonicalize(Thread *thread) const
bool IsObjectType() const
static bool InstantiateAndTestSubtype(AbstractType *subtype, AbstractType *supertype, const TypeArguments &instantiator_type_args, const TypeArguments &function_type_args)
virtual Definition * Canonicalize(FlowGraph *flow_graph)
virtual intptr_t InputCount() const
bool has_instantiator_type_args() const
@ kInstantiatorTypeArgsPos
virtual Definition * Canonicalize(FlowGraph *flow_graph)
RecordShape shape() const
intptr_t num_fields() const
RecordShape shape() const
virtual intptr_t InputCount() const
classid_t class_id() const
AllocateUninitializedContextInstr(const InstructionSource &source, intptr_t num_context_variables, intptr_t deopt_id)
static bool ParseKind(const char *str, Kind *out)
const String & dst_name() const
virtual intptr_t statistics_tag() const
virtual Definition * Canonicalize(FlowGraph *flow_graph)
virtual Value * RedefinedValue() const
Value * function_type_arguments() const
static const char * KindToCString(Kind kind)
Value * instantiator_type_arguments() const
@ FOR_EACH_ASSERT_ASSIGNABLE_KIND
virtual Value * RedefinedValue() const
virtual Definition * Canonicalize(FlowGraph *flow_graph)
Value * function_type_arguments() const
virtual Instruction * Canonicalize(FlowGraph *flow_graph)
Value * super_type() const
Value * instantiator_type_arguments() const
void RemoveCurrentFromGraph()
const T & At(intptr_t index) const
void SetAt(intptr_t index, const T &t)
Token::Kind op_kind() const
virtual PRINT_OPERANDS_TO_SUPPORT Definition * Canonicalize(FlowGraph *flow_graph)
virtual Representation representation() const
virtual intptr_t DeoptimizationTarget() const
static const BinaryFeedback * CreateMonomorphic(Zone *zone, intptr_t receiver_cid, intptr_t argument_cid)
static const BinaryFeedback * Create(Zone *zone, const ICData &ic_data)
virtual bool ComputeCanDeoptimize() const
static bool IsSupported(Token::Kind op_kind, Value *left, Value *right)
void set_can_overflow(bool overflow)
bool can_overflow() const
bool RightIsNonZero() const
Token::Kind op_kind() const
virtual bool AttributesEqual(const Instruction &other) const
bool RightIsPowerOfTwoConstant() const
static BinaryIntegerOpInstr * Make(Representation representation, Token::Kind op_kind, Value *left, Value *right, intptr_t deopt_id, SpeculativeMode speculative_mode=kGuardInputs)
bool is_truncating() const
virtual Definition * Canonicalize(FlowGraph *flow_graph)
virtual bool ComputeCanDeoptimize() const
Range * right_range() const
static constexpr intptr_t decode(uintptr_t value)
bool Contains(intptr_t i) const
BlockEntryInstr * dominator() const
intptr_t NestingDepth() const
void set_preorder_number(intptr_t number)
bool FindOsrEntryAndRelink(GraphEntryInstr *graph_entry, Instruction *parent, BitVector *block_marks)
virtual void ClearPredecessors()=0
ParallelMoveInstr * parallel_move() const
intptr_t preorder_number() const
bool HasParallelMove() const
intptr_t block_id() const
BlockEntryInstr * ImmediateDominator() const
virtual void AddPredecessor(BlockEntryInstr *predecessor)=0
bool Dominates(BlockEntryInstr *other) const
void ReplaceAsPredecessorWith(BlockEntryInstr *new_block)
bool IsLoopHeader() const
void ClearAllInstructions()
void set_last_instruction(Instruction *instr)
intptr_t stack_depth() const
bool DiscoverBlock(BlockEntryInstr *predecessor, GrowableArray< BlockEntryInstr * > *preorder, GrowableArray< intptr_t > *parent)
Instruction * last_instruction() const
GrowableArray< Definition * > * initial_definitions()
static const Bool & False()
static const Bool & Get(bool value)
static const Bool & True()
virtual Definition * Canonicalize(FlowGraph *flow_graph)
static bool IsBootstrapResolver(Dart_NativeEntryResolver resolver)
static void Allocate(FlowGraphCompiler *compiler, Instruction *instruction, const Class &cls, Register result, Register temp)
virtual void EmitNativeCode(FlowGraphCompiler *compiler)
static BoxInstr * Create(Representation from, Value *value)
Definition * Canonicalize(FlowGraph *flow_graph)
Representation from_representation() const
virtual Definition * Canonicalize(FlowGraph *flow_graph)
virtual Definition * Canonicalize(FlowGraph *flow_graph)
virtual bool ValueFitsSmi() const
Definition * Canonicalize(FlowGraph *flow_graph)
virtual intptr_t SuccessorCount() const
virtual BlockEntryInstr * SuccessorAt(intptr_t index) const
void SetComparison(ComparisonInstr *comp)
ComparisonInstr * comparison() const
virtual Instruction * Canonicalize(FlowGraph *flow_graph)
virtual Representation RequiredInputRepresentation(intptr_t idx) const
virtual Definition * Canonicalize(FlowGraph *flow_graph)
virtual Representation representation() const
CachableIdempotentCallInstr(const InstructionSource &source, Representation representation, const Function &function, intptr_t type_args_len, const Array &argument_names, InputsArray &&arguments, intptr_t deopt_id)
virtual intptr_t ArgumentsSize() const
const Function & function() const
intptr_t index_scale() const
virtual Definition * Canonicalize(FlowGraph *flow_graph)
StringPtr target_name() const
ArrayPtr arguments_descriptor() const
static const CallTargets * CreateMonomorphic(Zone *zone, intptr_t receiver_cid, const Function &target)
const Function & MostPopularTarget() const
static const CallTargets * Create(Zone *zone, const ICData &ic_data)
TargetInfo * TargetAt(int i) const
bool HasSingleTarget() const
static const CallTargets * CreateAndExpand(Zone *zone, const ICData &ic_data)
intptr_t AggregateCallCount() const
const Function & FirstTarget() const
StaticTypeExactnessState MonomorphicExactness() const
bool HasSingleRecognizedTarget() const
static constexpr Register kSecondReturnReg
static constexpr RegList kVolatileXmmRegisters
static constexpr intptr_t kVolatileCpuRegisters
static constexpr Register kFirstNonArgumentRegister
static constexpr Register kFfiAnyNonAbiRegister
static constexpr Register kReturnReg
static constexpr Register kSecondNonArgumentRegister
const RuntimeEntry & TargetFunction() const
static intptr_t LengthOffsetFor(intptr_t class_id)
static bool IsFixedLengthArrayType(intptr_t class_id)
virtual Value * RedefinedValue() const
bool IsRedundant(bool use_loops=false)
virtual Definition * Canonicalize(FlowGraph *flow_graph)
virtual Instruction * Canonicalize(FlowGraph *flow_graph)
bool IsDeoptIfNull() const
DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(CheckClassInstr, TemplateInstruction, FIELD_LIST) private void EmitBitTest(FlowGraphCompiler *compiler, intptr_t min, intptr_t max, intptr_t mask, compiler::Label *deopt)
void EmitNullCheck(FlowGraphCompiler *compiler, compiler::Label *deopt)
CheckClassInstr(Value *value, intptr_t deopt_id, const Cids &cids, const InstructionSource &source)
const Cids & cids() const
virtual Instruction * Canonicalize(FlowGraph *flow_graph)
virtual bool AttributesEqual(const Instruction &other) const
bool IsDeoptIfNotNull() const
intptr_t ComputeCidMask() const
static bool IsCompactCidRange(const Cids &cids)
virtual Instruction * Canonicalize(FlowGraph *flow_graph)
virtual Value * InputAt(intptr_t i) const
ComparisonInstr * comparison() const
virtual Instruction * Canonicalize(FlowGraph *flow_graph)
virtual bool UseSharedSlowPathStub(bool is_optimizing) const
const String & function_name() const
static void AddMetadataForRuntimeCall(CheckNullInstr *check_null, FlowGraphCompiler *compiler)
virtual Definition * Canonicalize(FlowGraph *flow_graph)
virtual Value * RedefinedValue() const
virtual bool AttributesEqual(const Instruction &other) const
ExceptionType exception_type() const
virtual Instruction * Canonicalize(FlowGraph *flow_graph)
virtual Instruction * Canonicalize(FlowGraph *flow_graph)
virtual Value * RedefinedValue() const
virtual Definition * Canonicalize(FlowGraph *flow_graph)
@ kWriteUnmodifiableTypedData
@ kDeeplyImmutableAttachNativeFinalizer
bool MustInclude(intptr_t cid)
CidCheckerForRanges(Thread *thread, ClassTable *table, const Class &cls, bool include_abstract, bool exclude_null)
bool MayInclude(intptr_t cid)
void Sort(int compare(CidRange *const *a, CidRange *const *b))
bool HasClassId(intptr_t cid) const
static Cids * CreateMonomorphic(Zone *zone, intptr_t cid)
intptr_t MonomorphicReceiverCid() const
static Cids * CreateForArgument(Zone *zone, const BinaryFeedback &binary_feedback, int argument_number)
void SetLength(intptr_t len)
intptr_t ComputeLowestCid() const
intptr_t ComputeHighestCid() const
GrowableArray< CidRange * > cid_ranges_
void Add(CidRange *target)
bool Equals(const Cids &other) const
bool IsMonomorphic() const
ClassPtr At(intptr_t cid) const
bool HasValidClassAt(intptr_t cid) const
const char * ScrubbedNameCString() const
LibraryPtr library() const
GrowableObjectArrayPtr direct_subclasses() const
ClassPtr SuperClass(ClassTable *class_table=nullptr) const
GrowableObjectArrayPtr direct_implementors() const
intptr_t NumTypeParameters(Thread *thread) const
static bool IsOptimized(CodePtr code)
@ kTagAssertAssignableFromSource
@ kTagAssertAssignableInsertedByFrontend
@ kTagAssertAssignableParameterCheck
virtual void NegateComparison()
intptr_t operation_cid() const
virtual bool AttributesEqual(const Instruction &other) const
virtual Condition EmitComparisonCode(FlowGraphCompiler *compiler, BranchLabels labels)=0
static CompileType FromCid(intptr_t cid)
const AbstractType * ToAbstractType()
static CompilerState & Current()
static bool IsBackgroundCompilation()
static constexpr intptr_t kNoOSRDeoptId
virtual bool AttributesEqual(const Instruction &other) const
virtual Definition * Canonicalize(FlowGraph *flow_graph)
const Object & value() const
ConstantInstr(const Object &value)
virtual void InferRange(RangeAnalysis *analysis, Range *range)
static ObjectPtr Unknown()
virtual Instruction * Canonicalize(FlowGraph *flow_graph)
static bool IsArrayLength(Definition *def)
Value * env_use_list() const
void ReplaceWith(Definition *other, ForwardInstructionIterator *iterator)
Value * input_use_list() const
Object & constant_value()
virtual Value * RedefinedValue() const
void AddEnvUse(Value *value)
virtual Definition * Canonicalize(FlowGraph *flow_graph)
Definition * OriginalDefinitionIgnoreBoxingAndConstraints()
void ReplaceUsesWith(Definition *other)
bool HasOnlyInputUse(Value *use) const
void AddInputUse(Value *value)
Definition * OriginalDefinition()
void set_ssa_temp_index(intptr_t index)
void set_input_use_list(Value *head)
bool HasOnlyUse(Value *use) const
void ReplaceWithResult(Instruction *replacement, Definition *replacement_for_uses, ForwardInstructionIterator *iterator)
ValueListIterable input_uses() const
intptr_t ssa_temp_index() const
void set_env_use_list(Value *head)
static constexpr intptr_t kNone
static intptr_t ToDeoptAfter(intptr_t deopt_id)
virtual Representation representation() const
virtual intptr_t ArgumentsSize() const
const Function & interface_target() const
static DispatchTableCallInstr * FromCall(Zone *zone, const InstanceCallBaseInstr *call, Value *cid, const Function &interface_target, const compiler::TableSelector *selector)
virtual Representation RequiredInputRepresentation(intptr_t idx) const
virtual Definition * Canonicalize(FlowGraph *flow_graph)
const compiler::TableSelector * selector() const
virtual Definition * Canonicalize(FlowGraph *flow_graph)
virtual ComparisonInstr * CopyWithNewOperands(Value *left, Value *right)
virtual Definition * Canonicalize(FlowGraph *flow_graph)
virtual void EmitNativeCode(FlowGraphCompiler *compiler)
static DoublePtr NewCanonical(double d)
intptr_t num_temps() const
virtual intptr_t InputCount() const
void DeepCopyToOuter(Zone *zone, Instruction *instr, intptr_t outer_deopt_id) const
void PushValue(Value *value)
intptr_t fixed_parameter_count() const
intptr_t LazyDeoptPruneCount() const
bool LazyDeoptToBeforeDeoptId() const
Value * ValueAt(intptr_t ix) const
void DeepCopyAfterTo(Zone *zone, Instruction *instr, intptr_t argc, Definition *dead, Definition *result) const
void DeepCopyTo(Zone *zone, Instruction *instr) const
Environment * DeepCopy(Zone *zone) const
Environment * outer() const
static Environment * From(Zone *zone, const GrowableArray< Definition * > &definitions, intptr_t fixed_parameter_count, intptr_t lazy_deopt_pruning_count, const ParsedFunction &parsed_function)
virtual ComparisonInstr * CopyWithNewOperands(Value *left, Value *right)
virtual Definition * Canonicalize(FlowGraph *flow_graph)
bool is_null_aware() const
void set_null_aware(bool value)
static int64_t TruncateTo(int64_t v, Representation r)
static IntegerPtr BitLengthEvaluate(const Object &value, Representation representation, Thread *thread)
static IntegerPtr BinaryIntegerEvaluate(const Object &left, const Object &right, Token::Kind token_kind, bool is_truncating, Representation representation, Thread *thread)
static bool ToIntegerConstant(Value *value, int64_t *result)
static intptr_t GetResultCidOfListFactory(Zone *zone, const Function &function, intptr_t argument_count)
intptr_t CompoundReturnTypedDataIndex() const
void EmitReturnMoves(FlowGraphCompiler *compiler, const Register temp0, const Register temp1)
virtual Representation RequiredInputRepresentation(intptr_t idx) const
DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(FfiCallInstr, VariadicDefinition, FIELD_LIST) private void EmitParamMoves(FlowGraphCompiler *compiler, const Register saved_fp, const Register temp0, const Register temp1)
virtual Representation representation() const
intptr_t TargetAddressIndex() const
StaticTypeExactnessState static_type_exactness_state() const
intptr_t guarded_cid() const
intptr_t guarded_list_length() const
AbstractTypePtr type() const
static Float32x4Ptr New(float value0, float value1, float value2, float value3, Heap::Space space=Heap::kNew)
static Float64x2Ptr New(double value0, double value1, Heap::Space space=Heap::kNew)
virtual Definition * Canonicalize(FlowGraph *flow_graph)
static bool LookupMethodFor(int class_id, const String &name, const ArgumentsDescriptor &args_desc, Function *fn_return, bool *class_is_abstract_return=nullptr)
static const CallTargets * ResolveCallTargetsForReceiverCid(intptr_t cid, const String &selector, const Array &args_desc_array)
static bool SupportsUnboxedDoubles()
ForwardInstructionIterator * current_iterator_
virtual void VisitBlocks()
ConstantInstr * GetConstant(const Object &object, Representation representation=kTagged)
bool should_print() const
bool IsCompiledForOsr() const
ConstantInstr * constant_dead() const
static Representation ReturnRepresentationOf(const Function &function)
bool should_remove_all_bounds_checks() const
static intptr_t ComputeArgumentsSizeInWords(const Function &function, intptr_t arguments_count)
static Representation ParameterRepresentationAt(const Function &function, intptr_t index)
ConstantInstr * constant_null() const
const Function & function() const
bool is_licm_allowed() const
bool unmatched_representations_allowed() const
Definition * TryCreateConstantReplacementFor(Definition *op, const Object &value)
bool ExtractExternalUntaggedPayload(Instruction *instr, Value *array, classid_t cid)
void CopyDeoptTarget(Instruction *to, Instruction *from)
void InsertBefore(Instruction *next, Instruction *instr, Environment *env, UseKind use_kind)
void InsertAfter(Instruction *prev, Instruction *instr, Environment *env, UseKind use_kind)
Instruction * Current() const
void RemoveCurrentFromGraph()
static bool IsDynamicInvocationForwarderName(const String &name)
static StringPtr DemangleDynamicInvocationForwarderName(const String &name)
MethodRecognizer::Kind recognized_kind() const
AbstractTypePtr result_type() const
virtual Representation RequiredInputRepresentation(intptr_t idx) const
virtual bool UseSharedSlowPathStub(bool is_optimizing) const
virtual Representation representation() const
JoinEntryInstr * successor() const
virtual intptr_t SuccessorCount() const
virtual BlockEntryInstr * SuccessorAt(intptr_t index) const
void RelinkToOsrEntry(Zone *zone, intptr_t max_block_id)
bool IsCompiledForOsr() const
FunctionEntryInstr * normal_entry() const
FunctionEntryInstr * unchecked_entry() const
void set_unchecked_entry(FunctionEntryInstr *target)
void set_normal_entry(FunctionEntryInstr *entry)
virtual BlockEntryInstr * SuccessorAt(intptr_t index) const
CatchBlockEntryInstr * GetCatchEntry(intptr_t index)
ConstantInstr * constant_null()
void set_osr_entry(OsrEntryInstr *entry)
virtual intptr_t SuccessorCount() const
GraphEntryInstr(const ParsedFunction &parsed_function, intptr_t osr_id)
OsrEntryInstr * osr_entry() const
virtual Instruction * Canonicalize(FlowGraph *flow_graph)
virtual bool AttributesEqual(const Instruction &other) const
const Field & field() const
virtual bool AttributesEqual(const Instruction &other) const
virtual Instruction * Canonicalize(FlowGraph *flow_graph)
virtual Instruction * Canonicalize(FlowGraph *flow_graph)
virtual bool AttributesEqual(const Instruction &other) const
bool InstanceOfHasClassRange(const AbstractType &type, intptr_t *lower_limit, intptr_t *upper_limit)
bool CanUseGenericSubtypeRangeCheckFor(const AbstractType &type)
const CidRangeVector & SubtypeRangesForClass(const Class &klass, bool include_abstract, bool exclude_null)
bool CanUseRecordSubtypeRangeCheckFor(const AbstractType &type)
bool CanUseSubtypeRangeCheckFor(const AbstractType &type)
intptr_t NumArgsTested() const
void GetClassIdsAt(intptr_t index, GrowableArray< intptr_t > *class_ids) const
intptr_t GetCountAt(intptr_t index) const
intptr_t NumberOfChecks() const
static bool Supports(ComparisonInstr *comparison, Value *v1, Value *v2)
ComparisonInstr * comparison() const
void ComputeOffsetTable(FlowGraphCompiler *compiler)
virtual intptr_t SuccessorCount() const
virtual TargetEntryInstr * SuccessorAt(intptr_t index) const
void set_ic_data(const ICData *value)
FunctionPtr ResolveForReceiverClass(const Class &cls, bool allow_add=true)
bool CanReceiverBeSmiBasedOnInterfaceTarget(Zone *zone) const
Code::EntryKind entry_kind() const
const ICData * ic_data() const
virtual Representation RequiredInputRepresentation(intptr_t idx) const
void set_receiver_is_not_smi(bool value)
const Function & interface_target() const
Token::Kind token_kind() const
virtual intptr_t ArgumentsSize() const
bool receiver_is_not_smi() const
void UpdateReceiverSminess(Zone *zone)
virtual Representation representation() const
const String & function_name() const
DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(InstanceCallInstr, InstanceCallBaseInstr, FIELD_LIST) private const class BinaryFeedback * binary_
const class BinaryFeedback & BinaryFeedback()
PRINT_OPERANDS_TO_SUPPORT bool MatchesCoreName(const String &name)
const CallTargets & Targets()
void EnsureICData(FlowGraph *graph)
intptr_t checked_argument_count() const
virtual Definition * Canonicalize(FlowGraph *flow_graph)
Value * type_arguments() const
virtual Definition * Canonicalize(FlowGraph *flow_graph)
Value * function_type_arguments() const
const Code & GetStub() const
const AbstractType & type() const
virtual bool AttributesEqual(const Instruction &other) const
virtual void Accept(InstructionVisitor *visitor)=0
Instruction * next() const
virtual intptr_t InputCount() const =0
intptr_t GetDeoptId() const
void set_previous(Instruction *instr)
void SetEnvironment(Environment *deopt_env)
void InheritDeoptTargetAfter(FlowGraph *flow_graph, Definition *call, Definition *result)
void LinkTo(Instruction *next)
void InheritDeoptTarget(Zone *zone, Instruction *other)
virtual Value * InputAt(intptr_t i) const =0
void Goto(JoinEntryInstr *entry)
virtual BlockEntryInstr * SuccessorAt(intptr_t index) const
virtual BlockEntryInstr * GetBlock()
virtual void CopyDeoptIdFrom(const Instruction &instr)
Environment * env() const
virtual LocationSummary * MakeLocationSummary(Zone *zone, bool is_optimizing) const =0
virtual void EmitNativeCode(FlowGraphCompiler *compiler)
bool HasUnmatchedInputRepresentations() const
const char * ToCString() const
virtual uword Hash() const
Instruction * AppendInstruction(Instruction *tail)
void InitializeLocationSummary(Zone *zone, bool optimizing)
void CheckField(const Field &field) const
virtual Representation RequiredInputRepresentation(intptr_t idx) const
virtual bool MayHaveVisibleEffect() const
virtual intptr_t ArgumentCount() const
void set_next(Instruction *instr)
static const intptr_t kInstructionAttrs[kNumInstructions]
bool IsDominatedBy(Instruction *dom)
bool Equals(const Instruction &other) const
static const ICData * GetICData(const ZoneGrowableArray< const ICData * > &ic_data_array, intptr_t deopt_id, bool is_static_call)
Definition * ArgumentAt(intptr_t index) const
void Unsupported(FlowGraphCompiler *compiler)
virtual Instruction * Canonicalize(FlowGraph *flow_graph)
virtual Representation representation() const
bool CanDeoptimize() const
void RepairArgumentUsesInEnvironment() const
void ReplaceInEnvironment(Definition *current, Definition *replacement)
virtual Tag tag() const =0
void SetInputAt(intptr_t i, Value *value)
InstructionSource source() const
Value * ArgumentValueAt(intptr_t index) const
virtual bool has_inlining_id() const
intptr_t deopt_id() const
void InsertAfter(Instruction *prev)
virtual intptr_t SuccessorCount() const
Instruction * RemoveFromGraph(bool return_previous=true)
virtual MoveArgumentsArray * GetMoveArguments() const
virtual bool CanTriggerGC() const
Instruction * previous() const
static LocationSummary * MakeCallSummary(Zone *zone, const Instruction *instr, LocationSummary *locs=nullptr)
static Int32x4Ptr New(int32_t value0, int32_t value1, int32_t value2, int32_t value3, Heap::Space space=Heap::kNew)
virtual Representation representation() const
bool is_truncating() const
virtual bool ComputeCanDeoptimize() const
Representation to() const
Definition * Canonicalize(FlowGraph *flow_graph)
Representation from() const
static IntegerPtr New(const String &str, Heap::Space space=Heap::kNew)
static IntegerPtr NewCanonical(const String &str)
InvokeMathCFunctionInstr(InputsArray &&inputs, intptr_t deopt_id, MethodRecognizer::Kind recognized_kind, const InstructionSource &source)
const RuntimeEntry & TargetFunction() const
static intptr_t ArgumentCountFor(MethodRecognizer::Kind recognized_kind_)
intptr_t optimization_counter_threshold() const
ObjectStore * object_store() const
static IsolateGroup * Current()
ClassTable * class_table() const
void RemoveDeadPhis(Definition *replacement)
PhiInstr * InsertPhi(intptr_t var_index, intptr_t var_count)
virtual void AddPredecessor(BlockEntryInstr *predecessor)
intptr_t IndexOfPredecessor(BlockEntryInstr *pred) const
GrowableArray< BlockEntryInstr * > predecessors_
void RemovePhi(PhiInstr *phi)
virtual intptr_t PredecessorCount() const
virtual Representation RequiredInputRepresentation(intptr_t idx) const
intptr_t TargetAddressIndex() const
void EmitParamMoves(FlowGraphCompiler *compiler, Register saved_fp, Register temp0)
LocationSummary * MakeLocationSummaryInternal(Zone *zone, const RegList temps) const
virtual bool MayCreateUnsafeUntaggedPointer() const
static LeafRuntimeCallInstr * Make(Zone *zone, Representation return_representation, const ZoneGrowableArray< Representation > &argument_representations, InputsArray &&inputs)
Dart_NativeEntryResolver native_entry_resolver() const
static bool IsPrivateCoreLibName(const String &name, const String &member)
virtual Definition * Canonicalize(FlowGraph *flow_graph)
virtual Representation representation() const
bool IsImmutableLengthLoad() const
virtual Definition * Canonicalize(FlowGraph *flow_graph)
void set_loads_inner_pointer(InnerPointerAccess value)
const Slot & slot() const
virtual bool MayCreateUnsafeUntaggedPointer() const
bool IsImmutableLoad() const
static bool IsUnmodifiableTypedDataViewFactory(const Function &function)
InnerPointerAccess loads_inner_pointer() const
bool Evaluate(const Object &instance_value, Object *result)
static bool IsFixedLengthArrayCid(intptr_t cid)
virtual bool AttributesEqual(const Instruction &other) const
virtual Representation representation() const
static bool TryEvaluateLoad(const Object &instance, const Field &field, Object *result)
static bool IsTypedDataViewFactory(const Function &function)
bool MayCreateUntaggedAlias() const
intptr_t class_id() const
virtual Definition * Canonicalize(FlowGraph *flow_graph)
static Representation ReturnRepresentation(intptr_t array_cid)
LoadIndexedInstr(Value *array, Value *index, bool index_unboxed, intptr_t index_scale, intptr_t class_id, AlignmentType alignment, intptr_t deopt_id, const InstructionSource &source, CompileType *result_type=nullptr)
intptr_t index_scale() const
virtual bool AllowsCSE() const
const Field & field() const
virtual bool AttributesEqual(const Instruction &other) const
virtual Representation representation() const
Location out(intptr_t index) const
static LocationSummary * Make(Zone *zone, intptr_t input_count, Location out, ContainsCall contains_call)
void set_temp(intptr_t index, Location loc)
RegisterSet * live_registers()
void set_out(intptr_t index, Location loc)
Location in(intptr_t index) const
void set_in(intptr_t index, Location loc)
static Location NoLocation()
static Location SameAsFirstInput()
static Location Pair(Location first, Location second)
intptr_t ToStackSlotOffset() const
const char * ToCString() const
intptr_t stack_index() const
Register base_reg() const
static Location RegisterLocation(Register reg)
PairLocation * AsPairLocation() const
static Location RequiresRegister()
bool IsPairLocation() const
static Location RequiresFpuRegister()
const Object & constant() const
static Location Constant(const ConstantInstr *obj, int pair_index=0)
BlockEntryInstr * header() const
intptr_t NestingDepth() const
void RemapRegisters(intptr_t *cpu_reg_slots, intptr_t *fpu_reg_slots)
const Location & LocationAt(intptr_t i)
intptr_t result_cid() const
MethodRecognizer::Kind op_kind() const
virtual bool AttributesEqual(const Instruction &other) const
static MegamorphicCachePtr Lookup(Thread *thread, const String &name, const Array &descriptor)
virtual Instruction * Canonicalize(FlowGraph *flow_graph)
DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(MemoryCopyInstr, TemplateInstruction, FIELD_LIST) private void EmitUnrolledCopy(FlowGraphCompiler *compiler, Register dest_reg, Register src_reg, intptr_t num_elements, bool reversed)
Value * src_start() const
void EmitLoopCopy(FlowGraphCompiler *compiler, Register dest_reg, Register src_reg, Register length_reg, compiler::Label *done, compiler::Label *copy_forwards=nullptr)
void PrepareLengthRegForLoop(FlowGraphCompiler *compiler, Register length_reg, compiler::Label *done)
Value * dest_start() const
static intptr_t ResultCidFromPragma(const Object &function_or_field)
static intptr_t NumArgsCheckedForStaticCall(const Function &function)
static const char * KindToCString(Kind kind)
static intptr_t ParameterCountForResolution(const Function &function)
void set_is_bootstrap_native(bool value)
const String & native_name() const
virtual TokenPosition token_pos() const
void set_is_auto_scope(bool value)
bool is_bootstrap_native() const
const Function & function() const
DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(NativeEntryInstr, FunctionEntryInstr, FIELD_LIST) private void SaveArgument(FlowGraphCompiler *compiler, const compiler::ffi::NativeLocation &loc) const
static NativeFunction ResolveNative(const Library &library, const String &function_name, int number_of_arguments, bool *auto_setup_scope)
virtual Representation representation() const
virtual PRINT_OPERANDS_TO_SUPPORT Representation RequiredInputRepresentation(intptr_t idx) const
intptr_t GetClassId() const
bool Contains(uword addr) const
virtual const char * ToCString() const
static Object & ZoneHandle()
Location At(intptr_t i) const
const Function & function() const
JoinEntryInstr * block() const
virtual Definition * Canonicalize(FlowGraph *flow_graph)
Definition * GetReplacementForRedundantPhi() const
PhiInstr * Current() const
void RemoveCurrentFromGraph()
virtual intptr_t CallCount() const
bool IsSureToCallSingleRecognizedTarget() const
static TypePtr ComputeRuntimeType(const CallTargets &targets)
virtual Definition * Canonicalize(FlowGraph *graph)
bool HasOnlyDispatcherOrImplicitAccessorTargets() const
const CallTargets & targets() const
intptr_t total_call_count()
static RangeBoundary FromConstant(int64_t val)
static bool IsSingleton(Range *range)
static bool Overlaps(Range *range, intptr_t min, intptr_t max)
static bool Fits(Range *range, RangeBoundary::RangeSize size)
static bool IsWithin(const Range *range, int64_t min, int64_t max)
static bool IsPositive(Range *range)
static bool CanBeZero(Range *range)
bool IsWithin(int64_t min_int, int64_t max_int) const
static bool IsUnknown(const Range *other)
bool Fits(RangeBoundary::RangeSize size) const
bool Overlaps(int64_t min_int, int64_t max_int) const
intptr_t catch_try_index() const
virtual Instruction * Canonicalize(FlowGraph *flow_graph)
AbstractTypePtr FieldTypeAt(intptr_t index) const
intptr_t NumFields() const
intptr_t num_fields() const
ObjectPtr FieldAt(intptr_t field_index) const
virtual Value * RedefinedValue() const
CompileType * constrained_type() const
virtual Definition * Canonicalize(FlowGraph *flow_graph)
void Remove(Location loc)
virtual ComparisonInstr * CopyWithNewOperands(Value *left, Value *right)
static void MessageF(Kind kind, const Script &script, TokenPosition token_pos, bool report_after_token, const char *format,...) PRINTF_ATTRIBUTE(5
static constexpr bool AtLocation
static FunctionPtr ResolveDynamicAnyArgs(Zone *zone, const Class &receiver_class, const String &function_name, bool allow_add=true)
static FunctionPtr ResolveDynamicForReceiverClass(const Class &receiver_class, const String &function_name, const ArgumentsDescriptor &args_desc, bool allow_add=true)
DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(ShiftIntegerOpInstr, BinaryIntegerOpInstr, FIELD_LIST) protected bool IsShiftCountInRange(int64_t max=kShiftCountLimit) const
Range * shift_range() const
virtual Representation RequiredInputRepresentation(intptr_t idx) const
virtual intptr_t InputCount() const
virtual Value * InputAt(intptr_t i) const
virtual Definition * Canonicalize(FlowGraph *flow_graph)
static SimdOpInstr * CreateFromCall(Zone *zone, MethodRecognizer::Kind kind, Definition *receiver, Instruction *call, intptr_t mask=0)
static SimdOpInstr * CreateFromFactoryCall(Zone *zone, MethodRecognizer::Kind kind, Instruction *call)
static Kind KindForMethod(MethodRecognizer::Kind method_kind)
static Kind KindForOperator(MethodRecognizer::Kind kind)
virtual Representation representation() const
const Field & field() const
Representation representation() const
intptr_t offset_in_bytes() const
bool is_compressed() const
compiler::Label * entry_label()
compiler::Label * exit_label()
static SmiPtr New(intptr_t value)
static intptr_t RawValue(intptr_t value)
static bool IsValid(int64_t value)
const ICData * ic_data() const
virtual Representation RequiredInputRepresentation(intptr_t idx) const
DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(StaticCallInstr, TemplateDartCall, FIELD_LIST) private const class BinaryFeedback * binary_
bool Evaluate(FlowGraph *flow_graph, const Object &argument, Object *result)
virtual intptr_t ArgumentsSize() const
static StaticCallInstr * FromCall(Zone *zone, const C *call, const Function &target, intptr_t call_count)
const Function & function() const
const class BinaryFeedback & BinaryFeedback()
void SetResultType(Zone *zone, CompileType new_type)
void set_is_known_list_constructor(bool value)
Code::EntryKind entry_kind() const
virtual Representation representation() const
bool InitResultType(Zone *zone)
const CallTargets & Targets()
virtual Definition * Canonicalize(FlowGraph *flow_graph)
bool IsTriviallyExact() const
bool NeedsFieldGuard() const
static StaticTypeExactnessState NotTracking()
InnerPointerAccess stores_inner_pointer() const
virtual Representation RequiredInputRepresentation(intptr_t index) const
void set_stores_inner_pointer(InnerPointerAccess value)
bool ShouldEmitStoreBarrier() const
bool is_initialization() const
virtual Instruction * Canonicalize(FlowGraph *flow_graph)
DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(StoreFieldInstr, TemplateInstruction, FIELD_LIST) private intptr_t OffsetInBytes() const
compiler::Assembler::CanBeSmi CanValueBeSmi() const
const Slot & slot() const
virtual Representation RequiredInputRepresentation(intptr_t idx) const
StoreIndexedInstr(Value *array, Value *index, Value *value, StoreBarrierType emit_store_barrier, bool index_unboxed, intptr_t index_scale, intptr_t class_id, AlignmentType alignment, intptr_t deopt_id, const InstructionSource &source, SpeculativeMode speculative_mode=kGuardInputs)
intptr_t class_id() const
static Representation ValueRepresentation(intptr_t array_cid)
virtual Instruction * Canonicalize(FlowGraph *flow_graph)
intptr_t index_scale() const
StrictCompareInstr(const InstructionSource &source, Token::Kind kind, Value *left, Value *right, bool needs_number_check, intptr_t deopt_id)
DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(StrictCompareInstr, TemplateComparison, FIELD_LIST) private bool TryEmitBoolTest(FlowGraphCompiler *compiler, BranchLabels labels, intptr_t input_index, const Object &obj, Condition *condition_out)
virtual Definition * Canonicalize(FlowGraph *flow_graph)
bool AttributesEqual(const Instruction &other) const
bool needs_number_check() const
virtual ComparisonInstr * CopyWithNewOperands(Value *left, Value *right)
bool Equals(const String &str) const
static StringPtr New(const char *cstr, Heap::Space space=Heap::kNew)
static CodePtr GetAllocationStubForClass(const Class &cls)
static CodePtr GetAllocationStubForTypedData(classid_t class_id)
SubtypeFinder(Zone *zone, GrowableArray< intptr_t > *cids, bool include_abstract)
void ScanImplementorClasses(const Class &klass)
bool has_type_args() const
intptr_t resume_deopt_id() const
@ kSuspendSyncStarAtYield
@ kSuspendSyncStarAtStart
Value * type_args() const
virtual PRINT_OPERANDS_TO_SUPPORT Definition * Canonicalize(FlowGraph *flow_graph)
static const String & True()
static const String & False()
static StringPtr FromConcatAll(Thread *thread, const GrowableHandlePtrArray< const String > &strs)
static StringPtr New(Thread *thread, const char *cstr)
virtual Value * InputAt(intptr_t i) const
intptr_t type_args_len() const
const Array & argument_names() const
intptr_t ArgumentCount() const
intptr_t FirstArgIndex() const
intptr_t ArgumentCountWithoutTypeArgs() const
ArrayPtr GetArgumentsDescriptor() const
virtual bool MayThrow() const
bool calls_initializer() const
bool throw_exception_on_initialization() const
virtual bool UseSharedSlowPathStub(bool is_optimizing) const
Instruction * instruction() const
virtual Definition * Canonicalize(FlowGraph *flow_graph)
virtual bool AttributesEqual(const Instruction &other) const
TestCidsInstr(const InstructionSource &source, Token::Kind kind, Value *value, const ZoneGrowableArray< intptr_t > &cid_results, intptr_t deopt_id)
virtual ComparisonInstr * CopyWithNewOperands(Value *left, Value *right)
const ZoneGrowableArray< intptr_t > & cid_results() const
TestRangeInstr(const InstructionSource &source, Value *value, uword lower, uword upper, Representation value_representation)
virtual ComparisonInstr * CopyWithNewOperands(Value *left, Value *right)
virtual bool AttributesEqual(const Instruction &other) const
virtual Definition * Canonicalize(FlowGraph *flow_graph)
virtual ComparisonInstr * CopyWithNewOperands(Value *left, Value *right)
IsolateGroup * isolate_group() const
static Thread * Current()
IsolateGroup * isolate_group() const
static Token::Kind NegateComparison(Token::Kind op)
static intptr_t OutputIndexOf(Token::Kind token)
TruncDivModInstr(Value *lhs, Value *rhs, intptr_t deopt_id)
AbstractTypePtr TypeAt(intptr_t index) const
static TypePtr DartTypeType()
static TypePtr NullableNumber()
static TypePtr StringType()
intptr_t ElementSizeInBytes() const
virtual Definition * Canonicalize(FlowGraph *flow_graph)
static UnaryIntegerOpInstr * Make(Representation representation, Token::Kind op_kind, Value *value, intptr_t deopt_id, SpeculativeMode speculative_mode, Range *range)
Token::Kind op_kind() const
Definition * Canonicalize(FlowGraph *flow_graph)
virtual Representation representation() const
void set_speculative_mode(SpeculativeMode value)
virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const
static UnboxInstr * Create(Representation to, Value *value, intptr_t deopt_id, SpeculativeMode speculative_mode=kGuardInputs)
bool is_truncating() const
virtual bool ComputeCanDeoptimize() const
virtual Definition * Canonicalize(FlowGraph *flow_graph)
Definition * Canonicalize(FlowGraph *flow_graph)
DECLARE_ATTRIBUTES_NAMED(("value", "representation"),(&value(), representation())) private uword constant_address_
UnboxedConstantInstr(const Object &value, Representation representation)
bool IsScanFlagsUnboxed() const
static constexpr int CountOneBitsWord(uword x)
static constexpr T Maximum(T x, T y)
static constexpr int ShiftForPowerOfTwo(T x)
static T Minimum(T x, T y)
static T AddWithWrapAround(T a, T b)
static constexpr bool IsPowerOfTwo(T x)
void BindToEnvironment(Definition *definition)
void set_use_index(intptr_t index)
bool BindsToConstantNull() const
bool BindsToConstant() const
void set_previous_use(Value *previous)
bool CanBe(const Object &value)
static void AddToList(Value *value, Value **list)
bool Equals(const Value &other) const
intptr_t BoundSmiConstant() const
bool BindsToSmiConstant() const
Instruction * instruction() const
void set_next_use(Value *next)
Value * previous_use() const
const Object & BoundConstant() const
void set_definition(Definition *definition)
Value * CopyWithType(Zone *zone)
Definition * definition() const
void BindTo(Definition *definition)
Value(Definition *definition)
void RefineReachingType(CompileType *type)
void set_instruction(Instruction *instruction)
intptr_t InputCount() const
Value * InputAt(intptr_t i) const
ElementType * Alloc(intptr_t length)
void static bool EmittingComments()
const NativeLocation & Rebase(const NativeLocation &loc) const
const NativeLocations & locations() const
static const NativeCallingConvention & FromSignature(Zone *zone, const NativeFunctionType &signature)
const NativeLocation & return_location() const
const NativeLocations & argument_locations() const
intptr_t StackTopInBytes() const
static const NativeFunctionType * FromRepresentations(Zone *zone, Representation return_representation, const ZoneGrowableArray< Representation > &argument_representations)
virtual bool IsMultiple() const
virtual bool IsFpuRegisters() const
virtual bool IsPointerToMemory() const
virtual bool IsBoth() const
const MultipleNativeLocations & AsMultiple() const
virtual bool IsStack() const
const NativeRegistersLocation & AsRegisters() const
const PointerToMemoryLocation & AsPointerToMemory() const
NativeLocation & WidenTo4Bytes(Zone *zone) const
virtual bool IsRegisters() const
const BothNativeLocations & AsBoth() const
const NativeType & payload_type() const
intptr_t num_regs() const
const NativeLocation & pointer_location() const
#define THR_Print(format,...)
Dart_NativeFunction(* Dart_NativeEntryResolver)(Dart_Handle name, int num_of_arguments, bool *auto_setup_scope)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
#define DECLARE_FLAG(type, name)
#define DEFINE_FLAG(type, name, default_value, comment)
Dart_NativeFunction function
#define HANDLESCOPE(thread)
static float max(float r, float g, float b)
static float min(float r, float g, float b)
#define DEFINE_ACCEPT(ShortName, Attrs)
#define INSTR_ATTRS(type, attrs)
#define BOXING_IN_SET_CASE(unboxed, boxed)
#define FOR_EACH_NON_INT_BOXED_REPRESENTATION(M)
#define CASE_BINARY_OP(Arity, Mask, Name, Args, Result)
#define BOXING_CID_CASE(unboxed, boxed)
#define CASE(Arity, Mask, Name, Args, Result)
#define BOXING_VALUE_OFFSET_CASE(unboxed, boxed)
#define CASE_METHOD(Arity, Mask, Name,...)
#define FOR_EACH_INSTRUCTION(M)
#define SIMD_OP_LIST(M, BINARY_OP)
#define DEFINE_BACKEND(Name, Args)
const intptr_t kResultIndex
word ToRawSmi(const dart::Object &a)
constexpr OperandSize kWordBytes
static constexpr int kExitLinkSlotFromEntryFp
static bool Equals(const Object &expected, const Object &actual)
bool IsTypedDataViewClassId(intptr_t index)
Location LocationRegisterOrConstant(Value *value)
static int64_t RepresentationMask(Representation r)
static Definition * CanonicalizeStrictCompare(StrictCompareInstr *compare, bool *negated, bool is_branch)
uword FindDoubleConstant(double value)
static Condition InvertCondition(Condition c)
static Definition * CanonicalizeCommutativeDoubleArithmetic(Token::Kind op, Value *left, Value *right)
static bool BindsToGivenConstant(Value *v, intptr_t expected)
bool IsTypedDataBaseClassId(intptr_t index)
static constexpr const char * kNone
static const Representation kUnboxedBool
static constexpr Representation kUnboxedUword
static bool MayBeNumber(CompileType *type)
static const SimdOpInfo simd_op_information[]
static bool MayBeBoxableNumber(intptr_t cid)
const Register kWriteBarrierValueReg
DART_EXPORT bool IsNull(Dart_Handle object)
bool IsTypeClassId(intptr_t index)
uint32_t CombineHashes(uint32_t hash, uint32_t other_hash)
constexpr intptr_t kIntptrMin
static constexpr int kSavedCallerFpSlotFromFp
bool IsUnmodifiableTypedDataViewClassId(intptr_t index)
constexpr intptr_t kBitsPerByte
MallocGrowableArray< CidRangeValue > CidRangeVector
static int OrderByFrequencyThenId(CidRange *const *a, CidRange *const *b)
void RegisterTypeArgumentsUse(const Function &function, TypeUsageInfo *type_usage_info, const Class &klass, Definition *type_arguments)
static int OrderById(CidRange *const *a, CidRange *const *b)
static bool RecognizeTestPattern(Value *left, Value *right, bool *negate)
static bool IsMarked(BlockEntryInstr *block, GrowableArray< BlockEntryInstr * > *preorder)
Location LocationRemapForSlowPath(Location loc, Definition *def, intptr_t *cpu_reg_slots, intptr_t *fpu_reg_slots)
static AlignmentType StrengthenAlignment(intptr_t cid, AlignmentType alignment)
static constexpr int kCallerSpSlotFromFp
static Definition * CanonicalizeStringInterpolate(StaticCallInstr *call, FlowGraph *flow_graph)
bool IsExternalPayloadClassId(classid_t cid)
constexpr intptr_t kInt32Size
constexpr intptr_t kBitsPerInt32
static Definition * CanonicalizeStringInterpolateSingle(StaticCallInstr *call, FlowGraph *flow_graph)
static bool IsFpCompare(ComparisonInstr *comp)
uint32_t FinalizeHash(uint32_t hash, intptr_t hashbits=kBitsPerInt32)
static constexpr Representation kUnboxedAddress
static bool IsSingleUseUnboxOrConstant(Value *use)
static intptr_t RepresentationBits(Representation r)
static const String & EvaluateToString(Zone *zone, Definition *defn)
static bool IsConstant(Definition *def, int64_t *val)
static constexpr Representation kUnboxedIntPtr
static const intptr_t kMaxElementSizeForEfficientCopy
bool IsIntegerClassId(intptr_t index)
static constexpr Representation SimdRepresentation(Representation rep)
const char *const function_name
static int8_t data[kExtLength]
void(* NativeFunction)(NativeArguments *arguments)
static bool IsCommutative(Token::Kind op)
static constexpr intptr_t kInvalidTryIndex
Location LocationRegisterOrSmiConstant(Value *value, intptr_t min_value, intptr_t max_value)
ArrayOfTuplesView< MegamorphicCache::EntryType, std::tuple< Smi, Object > > MegamorphicCacheEntries
constexpr intptr_t kBitsPerInt64
bool IsExternalTypedDataClassId(intptr_t index)
static FunctionPtr FindBinarySmiOp(Zone *zone, const String &name)
constexpr intptr_t kIntptrMax
bool IsStringClassId(intptr_t index)
static bool AllInputsAreRedefinitions(PhiInstr *phi)
static CodePtr TwoArgsSmiOpInlineCacheEntry(Token::Kind kind)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets Path to the Flutter assets directory enable service port Allow the VM service to fallback to automatic port selection if binding to a specified port fails trace Trace early application lifecycle Automatically switches to an endless trace buffer trace skia Filters out all Skia trace event categories except those that are specified in this comma separated list dump skp on shader Automatically dump the skp that triggers new shader compilations This is useful for writing custom ShaderWarmUp to reduce jank By this is not enabled to reduce the overhead purge persistent cache
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
static constexpr Register kResultReg
static constexpr Register kFunctionReg
static constexpr Register kContextReg
static constexpr Register kResultReg
static constexpr Register kInstantiatorTypeArgsReg
static constexpr Register kShapeReg
static constexpr Register kResultReg
static constexpr Register kResultReg
static constexpr Register kShapeReg
static constexpr Register kValue2Reg
static constexpr Register kValue0Reg
static constexpr Register kValue1Reg
static constexpr Register kLengthReg
static constexpr Register kResultReg
static constexpr Register kObjectReg
static constexpr Register kSubTypeReg
static constexpr Register kSuperTypeReg
static constexpr Register kFunctionTypeArgumentsReg
static constexpr Register kInstantiatorTypeArgumentsReg
static constexpr Register kDstNameReg
static bool RequiresAllocation(Representation rep)
static bool Supports(Representation rep)
static constexpr Representation NativeRepresentation(Representation rep)
static intptr_t BoxCid(Representation rep)
static intptr_t ValueOffset(Representation rep)
bool IsIllegalRange() const
static constexpr Register kSourceReg
static constexpr Register kClassIdReg
static constexpr Register kResultReg
static constexpr Register kRecognizedKindReg
static constexpr FpuRegister kInputReg
static constexpr Register kArgsReg
static constexpr Register kFieldReg
static constexpr Register kResultReg
static constexpr Register kInstanceReg
static constexpr Register kResultReg
static constexpr Register kFieldReg
static constexpr Register kTypeArgsReg
static constexpr Register kFunctionTypeArgumentsReg
static constexpr Register kTypeReg
static constexpr Register kInstantiatorTypeArgumentsReg
static constexpr Register kResultTypeReg
static constexpr Register kInstantiatorTypeArgumentsReg
static constexpr Register kUninstantiatedTypeArgumentsReg
static constexpr Register kResultTypeArgumentsReg
static constexpr Register kFunctionTypeArgumentsReg
static constexpr Register kFieldReg
static constexpr Register kLengthReg
static constexpr Register kIndexReg
static constexpr Register kStackTraceReg
static constexpr Register kExceptionReg
static constexpr size_t ValueSize(Representation rep)
static constexpr bool IsUnboxedInteger(Representation rep)
static bool IsRepresentable(Representation rep, int64_t value)
static int64_t MaxValue(Representation rep)
static compiler::OperandSize OperandSize(Representation rep)
static int64_t MinValue(Representation rep)
static constexpr bool IsUnboxed(Representation rep)
static const char * ToCString(Representation rep)
static Representation RepresentationOfArrayElement(classid_t cid)
static constexpr intptr_t kResumePcDistance
static constexpr Register kArgumentReg
static constexpr Register kTypeArgsReg
StaticTypeExactnessState exactness
static constexpr Register kExceptionReg