19#define IG (isolate_group())
25 it.Current()->RefineReachingType(new_type);
38 return (
cid == kSmiCid) || (
cid == kDoubleCid);
65 !block_it.
Done(); block_it.Advance()) {
71 if (instr->IsInstanceCall()) {
73 if (
call->HasICData()) {
75 VisitInstanceCall(
call);
78 }
else if (
auto static_call = instr->AsStaticCall()) {
82 }
else if (instr->IsPolymorphicInstanceCall()) {
83 SpecializePolymorphicInstanceCall(instr->AsPolymorphicInstanceCall());
93 if (
call->Targets().length() > 0) {
99 const intptr_t receiver_index =
call->FirstArgIndex();
102 call->ArgumentCountWithoutTypeArgs());
103 for (intptr_t
i = 0;
i <
call->ic_data()->NumArgsTested();
i++) {
104 class_ids.
Add(
call->ArgumentValueAt(receiver_index +
i)->Type()->ToCid());
115 if (
call->CanReceiverBeSmiBasedOnInterfaceTarget(
zone())) {
116 const intptr_t cid_0 = class_ids[0];
117 const intptr_t cid_1 = class_ids[1];
119 class_ids[0] = cid_1;
121 class_ids[1] = cid_0;
127 bool all_cids_known =
true;
128 for (intptr_t
i = 0;
i < class_ids.
length();
i++) {
131 all_cids_known =
false;
136 if (all_cids_known) {
137 const intptr_t receiver_cid = class_ids[0];
138 if (receiver_cid == kSentinelCid) {
142 const Class& receiver_class =
151 Z,
call->ResolveForReceiverClass(receiver_class,
false));
161 if (class_ids.
length() == 2) {
162 call->SetBinaryFeedback(
171void CallSpecializer::SpecializePolymorphicInstanceCall(
173 if (!FLAG_polymorphic_with_deopt) {
178 const intptr_t receiver_cid =
call->Receiver()->Type()->ToCid();
183 const ICData& ic_data = *
call->ic_data();
185 const CallTargets* targets =
189 if (targets ==
nullptr) {
194 ASSERT(targets->HasSingleTarget());
195 const Function&
target = targets->FirstTarget();
196 StaticCallInstr* specialized =
206 ASSERT(replacement->IsDefinition());
217void CallSpecializer::AddCheckSmi(
Definition* to_check,
222 if (to_check->
Type()->
ToCid() != kSmiCid) {
243 int argument_number) {
257 deopt_id, insert_before->
source());
258 if (FLAG_trace_strong_mode_types) {
261 InsertBefore(insert_before, check_null, deopt_environment,
269 if (
d->IsConstant()) {
270 const Object& obj =
d->AsConstant()->value();
271 if (obj.IsString()) {
272 return String::Cast(obj).Length() == 1;
277 return d->IsOneByteStringFromCharCode();
284bool CallSpecializer::TryStringLengthOneEquality(InstanceCallInstr*
call,
286 ASSERT(
call->BinaryFeedback().OperandsAre(kOneByteStringCid));
289 Definition* left =
call->ArgumentAt(0);
290 Definition* right =
call->ArgumentAt(1);
291 Value* left_val =
nullptr;
292 Definition* to_remove_left =
nullptr;
295 Definition* temp = left;
302 if (
left->IsConstant()) {
303 ConstantInstr* left_const =
left->AsConstant();
304 const String& str = String::Cast(left_const->value());
305 ASSERT(str.Length() == 1);
308 left_val =
new (
Z)
Value(char_code_left);
309 }
else if (
left->IsOneByteStringFromCharCode()) {
311 OneByteStringFromCharCodeInstr* instr =
312 left->AsOneByteStringFromCharCode();
313 left_val =
new (
Z)
Value(instr->char_code()->definition());
314 to_remove_left = instr;
320 Definition* to_remove_right =
nullptr;
321 Value* right_val =
nullptr;
322 if (
right->IsOneByteStringFromCharCode()) {
324 OneByteStringFromCharCodeInstr* right_instr =
325 right->AsOneByteStringFromCharCode();
326 right_val =
new (
Z)
Value(right_instr->char_code()->definition());
327 to_remove_right = right_instr;
329 AddChecksForArgNr(
call, right, 1);
332 StringToCharCodeInstr* char_code_right =
new (
Z)
333 StringToCharCodeInstr(
new (
Z)
Value(right), kOneByteStringCid);
335 right_val =
new (
Z)
Value(char_code_right);
339 EqualityCompareInstr* comp =
340 new (
Z) EqualityCompareInstr(
call->source(), op_kind, left_val,
341 right_val, kSmiCid,
call->deopt_id());
345 if ((to_remove_left !=
nullptr) &&
346 (to_remove_left->input_use_list() ==
nullptr)) {
347 to_remove_left->ReplaceUsesWith(
flow_graph()->constant_null());
348 to_remove_left->RemoveFromGraph();
350 if ((to_remove_right !=
nullptr) &&
351 (to_remove_right->input_use_list() ==
nullptr)) {
352 to_remove_right->ReplaceUsesWith(
flow_graph()->constant_null());
353 to_remove_right->RemoveFromGraph();
374 if (binary_feedback.
OperandsAre(kOneByteStringCid)) {
375 return TryStringLengthOneEquality(
call, op_kind);
411 AddChecksForArgNr(
call, left, 0);
412 AddChecksForArgNr(
call, right, 1);
421 if ((right_const !=
nullptr && right_const->
value().
IsNull()) ||
422 (left_const !=
nullptr && left_const->
value().
IsNull())) {
505 call->ic_data()->HasDeoptReason(ICData::kDeoptBinarySmiOp)
511 if (
call->ic_data()->HasDeoptReason(ICData::kDeoptBinaryInt64Op))
513 operands_type = kMintCid;
515 operands_type = kDoubleCid;
516 }
else if (binary_feedback.
OperandsAre(kFloat32x4Cid)) {
517 operands_type = kFloat32x4Cid;
518 }
else if (binary_feedback.
OperandsAre(kInt32x4Cid)) {
519 ASSERT(op_kind != Token::kMUL);
520 operands_type = kInt32x4Cid;
521 }
else if (binary_feedback.
OperandsAre(kFloat64x2Cid)) {
522 operands_type = kFloat64x2Cid;
530 operands_type = kDoubleCid;
531 }
else if (binary_feedback.
OperandsAre(kFloat32x4Cid)) {
532 operands_type = kFloat32x4Cid;
533 }
else if (binary_feedback.
OperandsAre(kFloat64x2Cid)) {
534 operands_type = kFloat64x2Cid;
539 case Token::kBIT_AND:
541 case Token::kBIT_XOR:
543 operands_type = kSmiCid;
545 operands_type = kMintCid;
546 }
else if (binary_feedback.
OperandsAre(kInt32x4Cid)) {
547 operands_type = kInt32x4Cid;
559 if (
call->ic_data()->HasDeoptReason(ICData::kDeoptBinaryInt64Op)) {
563 call->ic_data()->HasDeoptReason(ICData::kDeoptBinarySmiOp)
570 if (
call->ic_data()->HasDeoptReason(ICData::kDeoptBinaryInt64Op)) {
574 operands_type = kMintCid;
580 case Token::kTRUNCDIV:
582 if (
call->ic_data()->HasDeoptReason(ICData::kDeoptBinarySmiOp)) {
585 operands_type = kSmiCid;
598 if (operands_type == kDoubleCid) {
602 if (op_kind != Token::kDIV) {
614 }
else if (operands_type == kMintCid) {
615 if ((op_kind == Token::kSHL) || (op_kind == Token::kSHR) ||
616 (op_kind == Token::kUSHR)) {
626 }
else if ((operands_type == kFloat32x4Cid) ||
627 (operands_type == kInt32x4Cid) ||
628 (operands_type == kFloat64x2Cid)) {
629 return InlineSimdBinaryOp(
call, operands_type, op_kind);
630 }
else if (op_kind == Token::kMOD) {
631 ASSERT(operands_type == kSmiCid);
632 if (right->IsConstant()) {
633 const Object& obj = right->AsConstant()->value();
653 AddCheckSmi(right,
call->deopt_id(),
call->env(),
call);
658 ASSERT(operands_type == kSmiCid);
662 AddCheckSmi(right,
call->deopt_id(),
call->env(),
call);
663 if (left->IsConstant() &&
664 ((op_kind == Token::kADD) || (op_kind == Token::kMUL))) {
683 if (
call->Targets().ReceiverIs(kSmiCid)) {
690 }
else if ((op_kind == Token::kBIT_NOT) &&
691 call->Targets().ReceiverIsSmiOrMint()) {
694 }
else if (
call->Targets().ReceiverIs(kDoubleCid) &&
695 (op_kind == Token::kNEGATE)) {
702 ASSERT(unary_op !=
nullptr);
722 call, UntaggedFunction::kImplicitGetter)) {
741 const Field& field) {
748 new (
Z)
Value(receiver), slot,
call->source(), calls_initializer,
756 if (!calls_initializer) {
758 call->RemoveEnvironment();
765 it.Current()->SetReachingType(
nullptr);
778 if (
target.kind() != UntaggedFunction::kImplicitSetter) {
795 instr, UntaggedFunction::kImplicitSetter)) {
798 instr->
env(), instr);
811 bool is_unchecked_call =
false;
818 is_unchecked_call =
true;
822 if (
IG->use_field_guards()) {
853 bool needs_check =
true;
865 needs_check = !(is_unchecked_call ||
866 (instr->
entry_kind() == Code::EntryKind::kUnchecked));
891 new (
Z)
Value(instantiator_type_args),
892 new (
Z)
Value(function_type_args),
921 Definition*
const left =
call->ArgumentAt(0);
922 Definition*
const right =
call->ArgumentAt(1);
924 AddChecksForArgNr(
call, left, 0);
925 AddChecksForArgNr(
call, right, 1);
944 if (
target.kind() != UntaggedFunction::kImplicitGetter) {
952 return TryInlineImplicitInstanceGetter(
call);
967 if (recognized_kind == MethodRecognizer::kIntegerToDouble) {
968 if (receiver_cid == kSmiCid) {
983 if (receiver_cid == kDoubleCid) {
984 switch (recognized_kind) {
985 case MethodRecognizer::kDoubleToInteger: {
994 new (
Z)
Value(input), recognized_kind,
call->deopt_id());
1019BoolPtr CallSpecializer::InstanceOfAsBool(
1025 if (
type.IsFunctionType() ||
type.IsDartFunctionType() ||
1026 type.IsRecordType() || !
type.IsInstantiated()) {
1030 const intptr_t num_type_args = type_class.NumTypeArguments();
1031 if (num_type_args > 0) {
1034 const TypeArguments& type_arguments =
1036 const bool is_raw_type = type_arguments.IsNull() ||
1037 type_arguments.IsRaw(0, type_arguments.Length());
1044 const ClassTable& class_table = *
IG->class_table();
1048 bool results_differ =
false;
1050 for (
int i = 0;
i < number_of_checks;
i++) {
1052 if (cls.NumTypeArguments() > 0) {
1055 bool is_subtype =
false;
1056 if (cls.IsNullClass()) {
1060 const AbstractType& unwrapped_type =
1062 ASSERT(unwrapped_type.IsInstantiated());
1063 is_subtype = unwrapped_type.IsTopTypeForInstanceOf() ||
1064 unwrapped_type.IsNullable();
1070 results->
Add(cls.id());
1071 results->
Add(
static_cast<intptr_t
>(is_subtype));
1072 if (
prev.IsNull()) {
1075 if (is_subtype !=
prev.value()) {
1076 results_differ =
true;
1084bool CallSpecializer::TypeCheckAsClassEquality(
const AbstractType&
type,
1085 intptr_t* type_cid) {
1089 if (!
type.IsInstantiated())
return false;
1091 if (
type.IsFunctionType() ||
type.IsRecordType())
return false;
1098 const intptr_t num_type_args = type_class.NumTypeArguments();
1099 if (num_type_args > 0) {
1102 const TypeArguments& type_arguments =
1104 const bool is_raw_type = type_arguments.IsNull() ||
1105 type_arguments.IsRaw(0, type_arguments.Length());
1110 if (
type.IsNullable() ||
type.IsTopTypeForInstanceOf() ||
1111 type.IsNeverType()) {
1127bool CallSpecializer::TryOptimizeInstanceOfUsingStaticTypes(
1131 if (!
type.IsInstantiated()) {
1136 if (left_value->Type()->IsInstanceOf(
type)) {
1138 call->ReplaceUsesWith(replacement);
1149 if ((
type.IsNullable() && !
type.IsNullType()) ||
type.IsFutureOrType()) {
1157 if (
type.IsNullType() || left_value->Type()->IsSubtypeOf(
type)) {
1158 Definition* replacement =
new (
Z) StrictCompareInstr(
1160 type.IsNullType() ? Token::kEQ_STRICT : Token::kNE_STRICT,
1161 left_value->CopyWithType(
Z),
1164 if (FLAG_trace_strong_mode_types) {
1165 THR_Print(
"[Strong mode] replacing %s with %s (%s < %s)\n",
1166 call->ToCString(), replacement->ToCString(),
1167 left_value->Type()->ToAbstractType()->ToCString(),
1180 Definition* instantiator_type_args =
nullptr;
1184 if (
call->ArgumentCount() == 2) {
1187 ASSERT(
call->MatchesCoreName(Symbols::_simpleInstanceOf()));
1188 type = AbstractType::Cast(
call->ArgumentAt(1)->AsConstant()->value()).ptr();
1191 instantiator_type_args =
call->ArgumentAt(1);
1192 function_type_args =
call->ArgumentAt(2);
1193 type = AbstractType::Cast(
call->ArgumentAt(3)->AsConstant()->value()).ptr();
1196 if (TryOptimizeInstanceOfUsingStaticTypes(
call,
type)) {
1201 if (TypeCheckAsClassEquality(
type, &type_cid)) {
1208 call->source(), Token::kEQ,
new Value(load_cid),
1219 const ICData& unary_checks =
1222 if (number_of_checks > 0 && number_of_checks <= FLAG_max_polymorphic_checks) {
1225 const Bool& as_bool =
1228 if (results->
length() == number_of_checks * 2) {
1229 const bool can_deopt = SpecializeTestCidsForNumericTypes(results,
type);
1236 call->source(), Token::kIS,
new (
Z)
Value(left), *results,
1247 call->ReplaceUsesWith(bool_const);
1256 new (
Z)
Value(instantiator_type_args),
new (
Z)
Value(function_type_args),
1274 switch (recognized_kind) {
1275 case MethodRecognizer::kMathMin:
1276 case MethodRecognizer::kMathMax: {
1282 result_cid = kDoubleCid;
1284 result_cid = kSmiCid;
1288 recognized_kind,
new (
Z)
Value(
call->ArgumentAt(0)),
1302 case MethodRecognizer::kDoubleFromInteger: {
1304 (
call->FirstArgIndex() == 0)) {
1311 }
else if (binary_feedback.
ArgumentIs(kMintCid) &&
1334#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM)
1340 intptr_t test_cid) {
1341 for (intptr_t
i = 0;
i < results.
length();
i += 2) {
1342 if (results[
i] == test_cid)
return true;
1351 results->
Add(test_cid);
1352 results->
Add(
static_cast<intptr_t
>(
result));
1362 for (intptr_t
i = 2;
i < results->
length();
i += 2) {
1363 if (results->
At(
i + 1) != 0) {
1364 (*results)[
dest++] = results->
At(
i);
1365 (*results)[
dest++] = results->
At(
i + 1);
1371bool CallSpecializer::SpecializeTestCidsForNumericTypes(
1372 ZoneGrowableArray<intptr_t>* results,
1373 const AbstractType&
type) {
1374 ASSERT(results->length() >= 2);
1376 if ((*results)[0] != kSmiCid) {
1377 const Class& smi_class =
Class::Handle(class_table.At(kSmiCid));
1378 const bool smi_is_subtype =
1381 results->Add((*results)[results->length() - 2]);
1382 results->Add((*results)[results->length() - 2]);
1383 for (intptr_t
i = results->length() - 3;
i > 1; --
i) {
1384 (*results)[
i] = (*results)[
i - 2];
1386 (*results)[0] = kSmiCid;
1387 (*results)[1] =
static_cast<intptr_t
>(smi_is_subtype);
1391 ASSERT(results->length() >= 2);
1392 if (
type.IsSmiType()) {
1393 ASSERT((*results)[0] == kSmiCid);
1396 }
else if (
type.IsIntType()) {
1397 ASSERT((*results)[0] == kSmiCid);
1402 }
else if (
type.IsNumberType()) {
1403 ASSERT((*results)[0] == kSmiCid);
1408 }
else if (
type.IsDoubleType()) {
1409 ASSERT((*results)[0] == kSmiCid);
1422void TypedDataSpecializer::EnsureIsInitialized() {
1423 if (initialized_)
return;
1425 initialized_ =
true;
1440#define INIT_HANDLE(iface, type, cid) \
1441 td_class = typed_data.LookupClass(Symbols::iface()); \
1442 ASSERT(!td_class.IsNull()); \
1443 direct_implementors = td_class.direct_implementors(); \
1444 typed_data_variants_[k##iface##Index].array_type = td_class.RareType(); \
1445 typed_data_variants_[k##iface##Index].array_cid = cid; \
1446 typed_data_variants_[k##iface##Index].element_type = type.ptr();
1453 TryInlineCall(
call);
1460 TryInlineCall(
call);
1465 const bool is_length_getter =
call->Selector() == Symbols::GetLength().ptr();
1466 const bool is_index_get =
call->Selector() == Symbols::IndexToken().ptr();
1467 const bool is_index_set =
1468 call->Selector() == Symbols::AssignIndexToken().ptr();
1470 if (!(is_length_getter || is_index_get || is_index_set)) {
1474 EnsureIsInitialized();
1476 const intptr_t receiver_index =
call->FirstArgIndex();
1478 CompileType* receiver_type =
1479 call->ArgumentValueAt(receiver_index + 0)->Type();
1481 CompileType* index_type =
nullptr;
1482 if (is_index_get || is_index_set) {
1483 index_type =
call->ArgumentValueAt(receiver_index + 1)->Type();
1486 CompileType* value_type =
nullptr;
1488 value_type =
call->ArgumentValueAt(receiver_index + 2)->Type();
1492 for (
auto& variant : typed_data_variants_) {
1493 if (!receiver_type->IsAssignableTo(variant.array_type)) {
1497 if (is_length_getter) {
1498 type_class = variant.array_type.type_class();
1499 ReplaceWithLengthGetter(
call);
1505 const bool is_simd_access = rep == kUnboxedInt32x4 ||
1506 rep == kUnboxedFloat32x4 ||
1507 rep == kUnboxedFloat64x2;
1513 if (!index_type->IsNullableInt()) {
1518 type_class = variant.array_type.type_class();
1519 ReplaceWithIndexGet(
call, variant.array_cid);
1521 if (!value_type->IsAssignableTo(variant.element_type)) {
1524 type_class = variant.array_type.type_class();
1525 ReplaceWithIndexSet(
call, variant.array_cid);
1532void TypedDataSpecializer::ReplaceWithLengthGetter(TemplateDartCall<0>*
call) {
1533 const intptr_t receiver_idx =
call->FirstArgIndex();
1534 auto array =
call->ArgumentAt(receiver_idx + 0);
1536 if (array->Type()->is_nullable()) {
1537 AppendNullCheck(
call, &array);
1539 Definition*
length = AppendLoadLength(
call, array);
1544void TypedDataSpecializer::ReplaceWithIndexGet(TemplateDartCall<0>*
call,
1546 const intptr_t receiver_idx =
call->FirstArgIndex();
1547 auto array =
call->ArgumentAt(receiver_idx + 0);
1548 auto index =
call->ArgumentAt(receiver_idx + 1);
1550 if (array->Type()->is_nullable()) {
1551 AppendNullCheck(
call, &array);
1553 if (index->Type()->is_nullable()) {
1554 AppendNullCheck(
call, &index);
1556 AppendBoundsCheck(
call, array, &index);
1557 Definition*
value = AppendLoadIndexed(
call, array, index,
cid);
1562void TypedDataSpecializer::ReplaceWithIndexSet(TemplateDartCall<0>*
call,
1564 const intptr_t receiver_idx =
call->FirstArgIndex();
1565 auto array =
call->ArgumentAt(receiver_idx + 0);
1566 auto index =
call->ArgumentAt(receiver_idx + 1);
1567 auto value =
call->ArgumentAt(receiver_idx + 2);
1569 if (array->Type()->is_nullable()) {
1570 AppendNullCheck(
call, &array);
1572 if (index->Type()->is_nullable()) {
1573 AppendNullCheck(
call, &index);
1575 if (
value->Type()->is_nullable()) {
1578 AppendMutableCheck(
call, &array);
1579 AppendBoundsCheck(
call, array, &index);
1586void TypedDataSpecializer::AppendNullCheck(TemplateDartCall<0>*
call,
1587 Definition**
value) {
1589 new (
Z) CheckNullInstr(
new (
Z)
Value(*
value), Symbols::OptimizedOut(),
1597void TypedDataSpecializer::AppendMutableCheck(TemplateDartCall<0>*
call,
1598 Definition**
value) {
1607void TypedDataSpecializer::AppendBoundsCheck(TemplateDartCall<0>*
call,
1609 Definition** index) {
1610 auto length =
new (
Z) LoadFieldInstr(
1614 auto check =
new (
Z) GenericCheckBoundInstr(
1622Definition* TypedDataSpecializer::AppendLoadLength(TemplateDartCall<0>*
call,
1623 Definition* array) {
1624 auto length =
new (
Z) LoadFieldInstr(
1630Definition* TypedDataSpecializer::AppendLoadIndexed(TemplateDartCall<0>*
call,
1638 Definition*
load =
new (
Z) LoadIndexedInstr(
1643 if (rep == kUnboxedFloat) {
1651void TypedDataSpecializer::AppendStoreIndexed(TemplateDartCall<0>*
call,
1660 const auto deopt_id =
call->deopt_id();
1668 }
else if (rep == kUnboxedFloat) {
1674 auto store =
new (
Z) StoreIndexedInstr(
1697 if (
auto static_call =
call->AsStaticCall()) {
1698 return static_call->result_type();
1699 }
else if (
auto instance_call =
call->AsInstanceCall()) {
1700 return instance_call->result_type();
1707#define Z (flow_graph->zone())
1731 auto*
const null_check =
1734 cursor = flow_graph->
AppendTo(cursor, null_check,
call->env(),
1760 if (array_cid == kGrowableObjectArrayCid) {
1769 array_cid = kArrayCid;
1772 new (
Z)
Value(*array), Slot::PointerBase_data(),
1783 bool is_dynamic_call,
1796 if (!can_speculate && is_dynamic_call && !index->
Type()->
IsInt()) {
1851 bool is_unchecked_call =
false;
1854 static_call->entry_kind() == Code::EntryKind::kUnchecked;
1857 instance_call->entry_kind() == Code::EntryKind::kUnchecked;
1859 call->AsPolymorphicInstanceCall()) {
1861 instance_call->entry_kind() == Code::EntryKind::kUnchecked;
1864 if (!is_unchecked_call &&
1865 (kind != MethodRecognizer::kObjectArraySetIndexedUnchecked &&
1866 kind != MethodRecognizer::kGrowableArraySetIndexedUnchecked)) {
1873 if (rep == kTagged) {
1878 flow_graph->
thread(), instantiator_class),
1880 *last = flow_graph->
AppendTo(*last, load_type_args,
call->env(),
1882 type_args = load_type_args;
1889 if (rep == kUnboxedFloat || rep == kUnboxedDouble) {
1891 }
else if (rep == kUnboxedFloat32x4) {
1893 }
else if (rep == kUnboxedInt32x4) {
1895 }
else if (rep == kUnboxedFloat64x2) {
1904 if (exactness !=
nullptr && exactness->
is_exact) {
1907 auto const function_type_args = flow_graph->
constant_null();
1908 auto const dst_type = flow_graph->
GetConstant(value_type);
1911 new (
Z)
Value(type_args),
new (
Z)
Value(function_type_args),
1912 Symbols::Value(),
call->deopt_id());
1927 if (rep == kUnboxedFloat) {
1928 stored_value =
new (
Z)
1930 *last = flow_graph->
AppendTo(*last, stored_value,
call->env(),
1938 *last = flow_graph->
AppendTo(*last, stored_value,
call->env(),
1942 const intptr_t index_scale =
1946 needs_store_barrier,
false, index_scale, array_cid,
1975 *last = double_bin_op;
1996 kind,
new (
Z)
Value(receiver),
call->deopt_id(),
call->source());
1998 *last = double_test_op;
2024 store_barrier_type,
call->source());
2048 *
result = load_cid->AsDefinition();
2068 auto*
const null_check =
new (
Z)
2071 cursor = flow_graph->
AppendTo(cursor, null_check,
call->env(),
2099 if (
cid != kOneByteStringCid) {
2133 }
else if ((
cid != kOneByteStringCid) && (
cid != kTwoByteStringCid)) {
2145 *
result = (*last)->AsDefinition();
2151bool CallSpecializer::TryReplaceInstanceCallWithInline(
2152 FlowGraph* flow_graph,
2153 ForwardInstructionIterator* iterator,
2154 InstanceCallInstr*
call,
2155 SpeculativeInliningPolicy*
policy) {
2156 const CallTargets& targets =
call->Targets();
2157 ASSERT(targets.IsMonomorphic());
2158 const intptr_t receiver_cid = targets.MonomorphicReceiverCid();
2159 const Function&
target = targets.FirstTarget();
2160 const auto exactness = targets.MonomorphicExactness();
2161 ExactnessInfo exactness_info{exactness.IsExact(),
false};
2163 FunctionEntryInstr* entry =
nullptr;
2164 Instruction* last =
nullptr;
2165 Definition*
result =
nullptr;
2166 if (CallSpecializer::TryInlineRecognizedMethod(
2168 call->Receiver()->definition(),
call->source(),
call->ic_data(),
2174 (
target.recognized_kind() == MethodRecognizer::kObjectConstructor));
2179 if (
target.is_polymorphic_target() ||
2180 (
target.recognized_kind() == MethodRecognizer::kStringBaseCodeUnitAt)) {
2190 call->Receiver()->definition(), targets,
call->deopt_id(),
2197 Instruction* check_null =
new (
Z) CheckNullInstr(
2198 call->Receiver()->CopyWithType(
Z),
call->function_name(),
2208 if (exactness_info.emit_exactness_guard && exactness.IsTriviallyExact()) {
2215 if (
call->HasUses()) {
2221 if (entry->next() !=
nullptr) {
2222 call->previous()->LinkTo(entry->next());
2224 entry->UnuseAllInputs();
2225 if (last !=
nullptr) {
2226 ASSERT(
call->GetBlock() == last->GetBlock());
2231 iterator->RemoveCurrentFromGraph();
2232 call->set_previous(
nullptr);
2233 call->set_next(
nullptr);
2239bool CallSpecializer::TryReplaceStaticCallWithInline(
2240 FlowGraph* flow_graph,
2241 ForwardInstructionIterator* iterator,
2242 StaticCallInstr*
call,
2243 SpeculativeInliningPolicy*
policy) {
2244 FunctionEntryInstr* entry =
nullptr;
2245 Instruction* last =
nullptr;
2246 Definition*
result =
nullptr;
2247 Definition* receiver =
nullptr;
2249 if (!
call->function().is_static()) {
2250 receiver =
call->Receiver()->definition();
2251 receiver_cid =
call->Receiver()->Type()->ToCid();
2253 if (CallSpecializer::TryInlineRecognizedMethod(
2255 call->source(),
call->ic_data(),
nullptr, &entry,
2260 (
call->function().recognized_kind() ==
2261 MethodRecognizer::kObjectConstructor));
2264 if (
call->HasUses()) {
2270 if (entry !=
nullptr) {
2271 if (entry->next() !=
nullptr) {
2272 call->previous()->LinkTo(entry->next());
2274 entry->UnuseAllInputs();
2275 if (last !=
nullptr) {
2276 BlockEntryInstr*
link =
call->GetBlock();
2277 BlockEntryInstr*
exit = last->GetBlock();
2282 for (intptr_t
i = 0, n =
link->dominated_blocks().length();
i < n;
2284 exit->AddDominatedBlock(
link->dominated_blocks()[
i]);
2286 link->ClearDominatedBlocks();
2287 for (intptr_t
i = 0, n = entry->dominated_blocks().length();
i < n;
2289 link->AddDominatedBlock(entry->dominated_blocks()[
i]);
2291 Instruction* scan =
exit;
2292 while (scan->next() !=
nullptr) {
2293 scan = scan->next();
2303 if (iterator !=
nullptr) {
2305 iterator->RemoveCurrentFromGraph();
2307 call->RemoveFromGraph();
2315 if (!definition->IsConstant())
return false;
2316 ConstantInstr* constant_instruction = definition->AsConstant();
2317 const Object& constant_mask = constant_instruction->
value();
2318 if (!constant_mask.IsSmi())
return false;
2319 const intptr_t mask = Smi::Cast(constant_mask).Value();
2320 if ((mask < 0) || (mask > 255)) {
2335 : flow_graph_(flow_graph),
2337 graph_entry_(graph_entry),
2341 *entry_ =
new (zone())
2350 case MethodRecognizer::kInt32x4FromInts:
2351 UnboxScalar(0, kUnboxedInt32, 4);
2352 UnboxScalar(1, kUnboxedInt32, 4);
2353 UnboxScalar(2, kUnboxedInt32, 4);
2354 UnboxScalar(3, kUnboxedInt32, 4);
2356 BoxVector(kUnboxedInt32, 4);
2358 case MethodRecognizer::kInt32x4FromBools:
2364 BoxVector(kUnboxedInt32, 4);
2366 case MethodRecognizer::kInt32x4GetFlagX:
2367 UnboxVector(0, kUnboxedInt32, kMintCid, 4);
2371 case MethodRecognizer::kInt32x4GetFlagY:
2372 UnboxVector(0, kUnboxedInt32, kMintCid, 4);
2376 case MethodRecognizer::kInt32x4GetFlagZ:
2377 UnboxVector(0, kUnboxedInt32, kMintCid, 4);
2381 case MethodRecognizer::kInt32x4GetFlagW:
2382 UnboxVector(0, kUnboxedInt32, kMintCid, 4);
2386 case MethodRecognizer::kInt32x4WithFlagX:
2387 UnboxVector(0, kUnboxedInt32, kMintCid, 4);
2390 BoxVector(kUnboxedInt32, 4);
2392 case MethodRecognizer::kInt32x4WithFlagY:
2393 UnboxVector(0, kUnboxedInt32, kMintCid, 4);
2396 BoxVector(kUnboxedInt32, 4);
2398 case MethodRecognizer::kInt32x4WithFlagZ:
2399 UnboxVector(0, kUnboxedInt32, kMintCid, 4);
2402 BoxVector(kUnboxedInt32, 4);
2404 case MethodRecognizer::kInt32x4WithFlagW:
2405 UnboxVector(0, kUnboxedInt32, kMintCid, 4);
2408 BoxVector(kUnboxedInt32, 4);
2410 case MethodRecognizer::kInt32x4Shuffle: {
2414 if (!
CheckMask(mask_definition, &mask)) {
2417 UnboxVector(0, kUnboxedInt32, kMintCid, 4);
2419 BoxVector(kUnboxedInt32, 4);
2422 case MethodRecognizer::kInt32x4ShuffleMix: {
2426 if (!
CheckMask(mask_definition, &mask)) {
2429 UnboxVector(0, kUnboxedInt32, kMintCid, 4);
2430 UnboxVector(1, kUnboxedInt32, kMintCid, 4);
2432 BoxVector(kUnboxedInt32, 4);
2435 case MethodRecognizer::kInt32x4GetSignMask:
2436 case MethodRecognizer::kInt32x4Select:
2441 case MethodRecognizer::kFloat32x4Abs:
2442 Float32x4Unary(Token::kABS);
2444 case MethodRecognizer::kFloat32x4Negate:
2445 Float32x4Unary(Token::kNEGATE);
2447 case MethodRecognizer::kFloat32x4Sqrt:
2448 Float32x4Unary(Token::kSQRT);
2450 case MethodRecognizer::kFloat32x4Reciprocal:
2451 Float32x4Unary(Token::kRECIPROCAL);
2453 case MethodRecognizer::kFloat32x4ReciprocalSqrt:
2454 Float32x4Unary(Token::kRECIPROCAL_SQRT);
2456 case MethodRecognizer::kFloat32x4GetSignMask:
2459 case MethodRecognizer::kFloat32x4Equal:
2460 Float32x4Compare(Token::kEQ);
2462 case MethodRecognizer::kFloat32x4GreaterThan:
2463 Float32x4Compare(Token::kGT);
2465 case MethodRecognizer::kFloat32x4GreaterThanOrEqual:
2466 Float32x4Compare(Token::kGTE);
2468 case MethodRecognizer::kFloat32x4LessThan:
2469 Float32x4Compare(Token::kLT);
2471 case MethodRecognizer::kFloat32x4LessThanOrEqual:
2472 Float32x4Compare(Token::kLTE);
2474 case MethodRecognizer::kFloat32x4Add:
2475 Float32x4Binary(Token::kADD);
2477 case MethodRecognizer::kFloat32x4Sub:
2478 Float32x4Binary(Token::kSUB);
2480 case MethodRecognizer::kFloat32x4Mul:
2481 Float32x4Binary(Token::kMUL);
2483 case MethodRecognizer::kFloat32x4Div:
2484 Float32x4Binary(Token::kDIV);
2486 case MethodRecognizer::kFloat32x4Min:
2487 Float32x4Binary(Token::kMIN);
2489 case MethodRecognizer::kFloat32x4Max:
2490 Float32x4Binary(Token::kMAX);
2492 case MethodRecognizer::kFloat32x4Scale:
2493 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
2494 UnboxScalar(1, kUnboxedFloat, 4);
2495 BinaryDoubleOp(Token::kMUL, kUnboxedFloat, 4);
2496 BoxVector(kUnboxedFloat, 4);
2498 case MethodRecognizer::kFloat32x4Splat:
2499 UnboxScalar(0, kUnboxedFloat, 4);
2501 BoxVector(kUnboxedFloat, 4);
2503 case MethodRecognizer::kFloat32x4WithX:
2504 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
2505 UnboxScalar(1, kUnboxedFloat, 4);
2507 BoxVector(kUnboxedFloat, 4);
2509 case MethodRecognizer::kFloat32x4WithY:
2510 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
2511 UnboxScalar(1, kUnboxedFloat, 4);
2513 BoxVector(kUnboxedFloat, 4);
2515 case MethodRecognizer::kFloat32x4WithZ:
2516 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
2517 UnboxScalar(1, kUnboxedFloat, 4);
2519 BoxVector(kUnboxedFloat, 4);
2521 case MethodRecognizer::kFloat32x4WithW:
2522 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
2523 UnboxScalar(1, kUnboxedFloat, 4);
2525 BoxVector(kUnboxedFloat, 4);
2527 case MethodRecognizer::kFloat32x4Zero:
2528 UnboxDoubleZero(kUnboxedFloat, 4);
2529 BoxVector(kUnboxedFloat, 4);
2531 case MethodRecognizer::kFloat32x4FromDoubles:
2532 UnboxScalar(0, kUnboxedFloat, 4);
2533 UnboxScalar(1, kUnboxedFloat, 4);
2534 UnboxScalar(2, kUnboxedFloat, 4);
2535 UnboxScalar(3, kUnboxedFloat, 4);
2537 BoxVector(kUnboxedFloat, 4);
2539 case MethodRecognizer::kFloat32x4GetX:
2540 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
2541 BoxScalar(0, kUnboxedFloat);
2543 case MethodRecognizer::kFloat32x4GetY:
2544 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
2545 BoxScalar(1, kUnboxedFloat);
2547 case MethodRecognizer::kFloat32x4GetZ:
2548 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
2549 BoxScalar(2, kUnboxedFloat);
2551 case MethodRecognizer::kFloat32x4GetW:
2552 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
2553 BoxScalar(3, kUnboxedFloat);
2555 case MethodRecognizer::kFloat32x4Shuffle: {
2559 if (!
CheckMask(mask_definition, &mask)) {
2562 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
2564 BoxVector(kUnboxedFloat, 4);
2567 case MethodRecognizer::kFloat32x4ShuffleMix: {
2571 if (!
CheckMask(mask_definition, &mask)) {
2574 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
2575 UnboxVector(1, kUnboxedFloat, kDoubleCid, 4);
2577 BoxVector(kUnboxedFloat, 4);
2582 case MethodRecognizer::kFloat64x2Abs:
2583 Float64x2Unary(Token::kABS);
2585 case MethodRecognizer::kFloat64x2Negate:
2586 Float64x2Unary(Token::kNEGATE);
2588 case MethodRecognizer::kFloat64x2Sqrt:
2589 Float64x2Unary(Token::kSQRT);
2591 case MethodRecognizer::kFloat64x2Add:
2592 Float64x2Binary(Token::kADD);
2594 case MethodRecognizer::kFloat64x2Sub:
2595 Float64x2Binary(Token::kSUB);
2597 case MethodRecognizer::kFloat64x2Mul:
2598 Float64x2Binary(Token::kMUL);
2600 case MethodRecognizer::kFloat64x2Div:
2601 Float64x2Binary(Token::kDIV);
2603 case MethodRecognizer::kFloat64x2Min:
2604 Float64x2Binary(Token::kMIN);
2606 case MethodRecognizer::kFloat64x2Max:
2607 Float64x2Binary(Token::kMAX);
2609 case MethodRecognizer::kFloat64x2Scale:
2610 UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
2611 UnboxScalar(1, kUnboxedDouble, 2);
2612 BinaryDoubleOp(Token::kMUL, kUnboxedDouble, 2);
2613 BoxVector(kUnboxedDouble, 2);
2615 case MethodRecognizer::kFloat64x2Splat:
2616 UnboxScalar(0, kUnboxedDouble, 2);
2618 BoxVector(kUnboxedDouble, 2);
2620 case MethodRecognizer::kFloat64x2WithX:
2621 UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
2622 UnboxScalar(1, kUnboxedDouble, 2);
2624 BoxVector(kUnboxedDouble, 2);
2626 case MethodRecognizer::kFloat64x2WithY:
2627 UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
2628 UnboxScalar(1, kUnboxedDouble, 2);
2630 BoxVector(kUnboxedDouble, 2);
2632 case MethodRecognizer::kFloat64x2Zero:
2633 UnboxDoubleZero(kUnboxedDouble, 2);
2634 BoxVector(kUnboxedDouble, 2);
2636 case MethodRecognizer::kFloat64x2FromDoubles:
2637 UnboxScalar(0, kUnboxedDouble, 2);
2638 UnboxScalar(1, kUnboxedDouble, 2);
2640 BoxVector(kUnboxedDouble, 2);
2642 case MethodRecognizer::kFloat64x2GetX:
2643 UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
2644 BoxScalar(0, kUnboxedDouble);
2646 case MethodRecognizer::kFloat64x2GetY:
2647 UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
2648 BoxScalar(1, kUnboxedDouble);
2652 case MethodRecognizer::kFloat32x4ToFloat64x2: {
2653 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4, 1);
2654 Float32x4ToFloat64x2();
2655 BoxVector(kUnboxedDouble, 2);
2658 case MethodRecognizer::kFloat64x2ToFloat32x4: {
2659 UnboxVector(0, kUnboxedDouble, kDoubleCid, 2, 1);
2660 Float64x2ToFloat32x4();
2661 BoxVector(kUnboxedFloat, 4);
2664 case MethodRecognizer::kInt32x4ToFloat32x4:
2665 UnboxVector(0, kUnboxedInt32, kMintCid, 4, 1);
2666 Int32x4ToFloat32x4();
2667 BoxVector(kUnboxedFloat, 4);
2669 case MethodRecognizer::kFloat32x4ToInt32x4:
2670 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4, 1);
2671 Float32x4ToInt32x4();
2672 BoxVector(kUnboxedInt32, 4);
2681 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
2682 UnaryDoubleOp(op, kUnboxedFloat, 4);
2683 BoxVector(kUnboxedFloat, 4);
2686 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
2687 UnboxVector(1, kUnboxedFloat, kDoubleCid, 4);
2688 BinaryDoubleOp(op, kUnboxedFloat, 4);
2689 BoxVector(kUnboxedFloat, 4);
2692 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
2693 UnboxVector(1, kUnboxedFloat, kDoubleCid, 4);
2695 BoxVector(kUnboxedInt32, 4);
2698 UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
2699 UnaryDoubleOp(op, kUnboxedDouble, 2);
2700 BoxVector(kUnboxedDouble, 2);
2703 UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
2704 UnboxVector(1, kUnboxedDouble, kDoubleCid, 2);
2705 BinaryDoubleOp(op, kUnboxedDouble, 2);
2706 BoxVector(kUnboxedDouble, 2);
2709 void UnboxVector(intptr_t
i,
2713 intptr_t type_args = 0) {
2714 Definition* arg = call_->
ArgumentAt(
i + type_args);
2720 arg = AddDefinition(
new (zone()) CheckNullInstr(
2721 new (zone())
Value(arg), Symbols::SecondArg(), call_->
deopt_id(),
2724 for (intptr_t lane = 0; lane < n; lane++) {
2725 in_[
i][lane] = AddDefinition(
2726 new (zone()) UnboxLaneInstr(
new (zone())
Value(arg), lane, rep,
cid));
2730 void UnboxScalar(intptr_t
i,
2733 intptr_t type_args = 0) {
2734 Definition* arg = call_->
ArgumentAt(
i + type_args);
2740 arg = AddDefinition(
new (zone()) CheckNullInstr(
2741 new (zone())
Value(arg), Symbols::SecondArg(), call_->
deopt_id(),
2744 Definition* unbox = AddDefinition(
2747 for (intptr_t lane = 0; lane < n; lane++) {
2748 in_[
i][lane] = unbox;
2752 void UnboxBool(intptr_t
i, intptr_t n) {
2753 Definition* unbox = AddDefinition(
new (zone()) BoolToIntInstr(
2755 for (intptr_t lane = 0; lane < n; lane++) {
2756 in_[
i][lane] = unbox;
2763 for (intptr_t lane = 0; lane < n; lane++) {
2769 for (intptr_t lane = 0; lane < n; lane++) {
2770 op_[lane] = AddDefinition(
new (zone()) UnaryDoubleOpInstr(
2777 for (intptr_t lane = 0; lane < n; lane++) {
2778 op_[lane] = AddDefinition(
new (zone()) BinaryDoubleOpInstr(
2779 op,
new (zone())
Value(in_[0][lane]),
2786 for (intptr_t lane = 0; lane < 4; lane++) {
2787 op_[lane] = AddDefinition(
2788 new (zone()) FloatCompareInstr(op,
new (zone())
Value(in_[0][lane]),
2789 new (zone())
Value(in_[1][lane])));
2793 void With(intptr_t
i) {
2794 for (intptr_t lane = 0; lane < 4; lane++) {
2795 op_[lane] = in_[0][lane];
2799 void Splat(intptr_t n) {
2800 for (intptr_t lane = 0; lane < n; lane++) {
2801 op_[lane] = in_[0][0];
2804 void Gather(intptr_t n) {
2805 for (intptr_t lane = 0; lane < n; lane++) {
2806 op_[lane] = in_[lane][0];
2809 void Shuffle(intptr_t mask) {
2810 op_[0] = in_[0][(mask >> 0) & 3];
2811 op_[1] = in_[0][(mask >> 2) & 3];
2812 op_[2] = in_[0][(mask >> 4) & 3];
2813 op_[3] = in_[0][(mask >> 6) & 3];
2815 void ShuffleMix(intptr_t mask) {
2816 op_[0] = in_[0][(mask >> 0) & 3];
2817 op_[1] = in_[0][(mask >> 2) & 3];
2818 op_[2] = in_[1][(mask >> 4) & 3];
2819 op_[3] = in_[1][(mask >> 6) & 3];
2821 void Float32x4ToFloat64x2() {
2822 for (intptr_t lane = 0; lane < 2; lane++) {
2823 op_[lane] = AddDefinition(
new (zone()) FloatToDoubleInstr(
2827 void Float64x2ToFloat32x4() {
2828 for (intptr_t lane = 0; lane < 2; lane++) {
2829 op_[lane] = AddDefinition(
new (zone()) DoubleToFloatInstr(
2837 void Int32x4ToFloat32x4() {
2838 for (intptr_t lane = 0; lane < 4; lane++) {
2839 op_[lane] = AddDefinition(
new (zone()) BitCastInstr(
2840 kUnboxedInt32, kUnboxedFloat,
new (zone())
Value(in_[0][lane])));
2843 void Float32x4ToInt32x4() {
2844 for (intptr_t lane = 0; lane < 4; lane++) {
2845 op_[lane] = AddDefinition(
new (zone()) BitCastInstr(
2846 kUnboxedFloat, kUnboxedInt32,
new (zone())
Value(in_[0][lane])));
2850 for (intptr_t lane = 0; lane < 4; lane++) {
2851 op_[lane] = AddDefinition(
2852 new (zone()) IntToBoolInstr(
new (zone())
Value(in_[0][lane])));
2859 box =
new (zone()) BoxLanesInstr(rep,
new (zone())
Value(op_[0]),
2860 new (zone())
Value(op_[1]));
2863 box =
new (zone()) BoxLanesInstr(
2864 rep,
new (zone())
Value(op_[0]),
new (zone())
Value(op_[1]),
2865 new (zone())
Value(op_[2]),
new (zone())
Value(op_[3]));
2867 Done(AddDefinition(box));
2872 Done(AddDefinition(box));
2875 void Return(intptr_t lane) { Done(op_[lane]); }
2877 void Done(Definition*
result) {
2881 (*entry_)->InheritDeoptTarget(zone(), call_);
2885 Definition* AddDefinition(Definition* def) {
2891 Zone* zone() {
return flow_graph_->
zone(); }
2893 FlowGraph* flow_graph_;
2895 GraphEntryInstr* graph_entry_;
2896 FunctionEntryInstr** entry_;
2897 Instruction** last_;
2898 Definition** result_;
2901 Definition* in_[4][4];
2907 bool is_dynamic_call,
2915 if (is_dynamic_call &&
call->ArgumentCount() > 1) {
2929 if (!FLAG_enable_simd_inline) {
2934#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
2947 case MethodRecognizer::kInt32x4Shuffle:
2948 case MethodRecognizer::kInt32x4ShuffleMix:
2949 case MethodRecognizer::kFloat32x4Shuffle:
2950 case MethodRecognizer::kFloat32x4ShuffleMix: {
2953 if (!
CheckMask(mask_definition, &mask)) {
2960 case MethodRecognizer::kFloat32x4WithX:
2961 case MethodRecognizer::kFloat32x4WithY:
2962 case MethodRecognizer::kFloat32x4WithZ:
2963 case MethodRecognizer::kFloat32x4WithW:
2964 case MethodRecognizer::kFloat32x4Scale: {
2977 case MethodRecognizer::kFloat32x4Zero:
2978 case MethodRecognizer::kFloat32x4ToFloat64x2:
2979 case MethodRecognizer::kFloat64x2ToFloat32x4:
2980 case MethodRecognizer::kFloat32x4ToInt32x4:
2981 case MethodRecognizer::kInt32x4ToFloat32x4:
2982 case MethodRecognizer::kFloat64x2Zero:
2985 case MethodRecognizer::kFloat32x4Mul:
2986 case MethodRecognizer::kFloat32x4Div:
2987 case MethodRecognizer::kFloat32x4Add:
2988 case MethodRecognizer::kFloat32x4Sub:
2989 case MethodRecognizer::kFloat64x2Mul:
2990 case MethodRecognizer::kFloat64x2Div:
2991 case MethodRecognizer::kFloat64x2Add:
2992 case MethodRecognizer::kFloat64x2Sub:
3004 new (
Z)
Value(
call->ArgumentAt(1)), Symbols::SecondArg(),
3008 (*last)->SetInputAt(1,
new (
Z)
Value(check2));
3021 (*entry)->InheritDeoptTarget(
Z,
call);
3025 *
result = (*last)->AsDefinition();
3054 const intptr_t small_exponent = 5;
3058 *
result = (*last)->AsDefinition();
3060 }
else if (val == 1) {
3061 *last =
x->definition();
3062 *
result = (*last)->AsDefinition();
3064 }
else if (1 < val && val <= small_exponent) {
3072 InlineMul(flow_graph, *entry, x_def, x_def)->AsDefinition();
3080 *
result = (*last)->AsDefinition();
3084 *
result = (*last)->AsDefinition();
3089 *
result = (*last)->AsDefinition();
3097 *last =
x->definition();
3105bool CallSpecializer::TryInlineRecognizedMethod(
3106 FlowGraph* flow_graph,
3107 intptr_t receiver_cid,
3110 Definition* receiver,
3111 const InstructionSource&
source,
3112 const ICData* ic_data,
3113 GraphEntryInstr* graph_entry,
3114 FunctionEntryInstr** entry,
3117 SpeculativeInliningPolicy*
policy,
3118 CallSpecializer::ExactnessInfo* exactness) {
3121 if (receiver_cid == kSentinelCid) {
3128 const bool can_speculate =
policy->IsAllowedForInlining(
call->deopt_id());
3134 case MethodRecognizer::kTypedDataIndexCheck:
3136 entry, last,
result, Symbols::Index());
3137 case MethodRecognizer::kByteDataByteOffsetCheck:
3140 Symbols::byteOffset());
3142 case MethodRecognizer::kObjectArrayGetIndexed:
3143 case MethodRecognizer::kGrowableArrayGetIndexed:
3144 case MethodRecognizer::kInt8ArrayGetIndexed:
3145 case MethodRecognizer::kUint8ArrayGetIndexed:
3146 case MethodRecognizer::kUint8ClampedArrayGetIndexed:
3147 case MethodRecognizer::kExternalUint8ArrayGetIndexed:
3148 case MethodRecognizer::kExternalUint8ClampedArrayGetIndexed:
3149 case MethodRecognizer::kInt16ArrayGetIndexed:
3150 case MethodRecognizer::kUint16ArrayGetIndexed:
3152 call, receiver, graph_entry, entry, last,
result);
3153 case MethodRecognizer::kFloat32ArrayGetIndexed:
3154 case MethodRecognizer::kFloat64ArrayGetIndexed:
3156 call, receiver, graph_entry, entry, last,
result);
3157 case MethodRecognizer::kFloat32x4ArrayGetIndexed:
3158 case MethodRecognizer::kFloat64x2ArrayGetIndexed:
3163 call, receiver, graph_entry, entry, last,
result);
3164 case MethodRecognizer::kInt32ArrayGetIndexed:
3165 case MethodRecognizer::kUint32ArrayGetIndexed:
3167 call, receiver, graph_entry, entry, last,
result);
3168 case MethodRecognizer::kInt64ArrayGetIndexed:
3169 case MethodRecognizer::kUint64ArrayGetIndexed:
3171 call, receiver, graph_entry, entry, last,
result);
3172 case MethodRecognizer::kClassIDgetID:
3180 if (!can_speculate) {
3185 case MethodRecognizer::kUint8ClampedArraySetIndexed:
3186 case MethodRecognizer::kExternalUint8ClampedArraySetIndexed:
3192 case MethodRecognizer::kObjectArraySetIndexed:
3193 case MethodRecognizer::kGrowableArraySetIndexed:
3194 case MethodRecognizer::kObjectArraySetIndexedUnchecked:
3195 case MethodRecognizer::kGrowableArraySetIndexedUnchecked:
3196 case MethodRecognizer::kInt8ArraySetIndexed:
3197 case MethodRecognizer::kUint8ArraySetIndexed:
3198 case MethodRecognizer::kExternalUint8ArraySetIndexed:
3199 case MethodRecognizer::kInt16ArraySetIndexed:
3200 case MethodRecognizer::kUint16ArraySetIndexed:
3201 case MethodRecognizer::kInt32ArraySetIndexed:
3202 case MethodRecognizer::kUint32ArraySetIndexed:
3203 case MethodRecognizer::kInt64ArraySetIndexed:
3204 case MethodRecognizer::kUint64ArraySetIndexed:
3206 exactness, graph_entry, entry, last,
result);
3208 case MethodRecognizer::kFloat32ArraySetIndexed:
3209 case MethodRecognizer::kFloat64ArraySetIndexed: {
3211 exactness, graph_entry, entry, last,
result);
3213 case MethodRecognizer::kFloat32x4ArraySetIndexed: {
3218 exactness, graph_entry, entry, last,
result);
3220 case MethodRecognizer::kFloat64x2ArraySetIndexed: {
3225 exactness, graph_entry, entry, last,
result);
3227 case MethodRecognizer::kStringBaseCodeUnitAt:
3229 receiver_cid, graph_entry, entry, last,
3231 case MethodRecognizer::kStringBaseCharAt:
3233 graph_entry, entry, last,
result);
3234 case MethodRecognizer::kDoubleAdd:
3236 graph_entry, entry, last,
result);
3237 case MethodRecognizer::kDoubleSub:
3239 graph_entry, entry, last,
result);
3240 case MethodRecognizer::kDoubleMul:
3242 graph_entry, entry, last,
result);
3243 case MethodRecognizer::kDoubleDiv:
3245 graph_entry, entry, last,
result);
3246 case MethodRecognizer::kDouble_getIsNaN:
3247 case MethodRecognizer::kDouble_getIsInfinite:
3248 case MethodRecognizer::kDouble_getIsNegative:
3251 case MethodRecognizer::kGrowableArraySetData:
3252 ASSERT((receiver_cid == kGrowableObjectArrayCid) ||
3256 receiver, graph_entry, entry, last,
result);
3257 case MethodRecognizer::kGrowableArraySetLength:
3258 ASSERT((receiver_cid == kGrowableObjectArrayCid) ||
3262 receiver, graph_entry, entry, last,
result);
3264 case MethodRecognizer::kFloat32x4Abs:
3265 case MethodRecognizer::kFloat32x4Clamp:
3266 case MethodRecognizer::kFloat32x4FromDoubles:
3267 case MethodRecognizer::kFloat32x4Equal:
3268 case MethodRecognizer::kFloat32x4GetSignMask:
3269 case MethodRecognizer::kFloat32x4GreaterThan:
3270 case MethodRecognizer::kFloat32x4GreaterThanOrEqual:
3271 case MethodRecognizer::kFloat32x4LessThan:
3272 case MethodRecognizer::kFloat32x4LessThanOrEqual:
3273 case MethodRecognizer::kFloat32x4Max:
3274 case MethodRecognizer::kFloat32x4Min:
3275 case MethodRecognizer::kFloat32x4Negate:
3276 case MethodRecognizer::kFloat32x4NotEqual:
3277 case MethodRecognizer::kFloat32x4Reciprocal:
3278 case MethodRecognizer::kFloat32x4ReciprocalSqrt:
3279 case MethodRecognizer::kFloat32x4Scale:
3280 case MethodRecognizer::kFloat32x4GetW:
3281 case MethodRecognizer::kFloat32x4GetX:
3282 case MethodRecognizer::kFloat32x4GetY:
3283 case MethodRecognizer::kFloat32x4GetZ:
3284 case MethodRecognizer::kFloat32x4Splat:
3285 case MethodRecognizer::kFloat32x4Sqrt:
3286 case MethodRecognizer::kFloat32x4ToFloat64x2:
3287 case MethodRecognizer::kFloat32x4ToInt32x4:
3288 case MethodRecognizer::kFloat32x4WithW:
3289 case MethodRecognizer::kFloat32x4WithX:
3290 case MethodRecognizer::kFloat32x4WithY:
3291 case MethodRecognizer::kFloat32x4WithZ:
3292 case MethodRecognizer::kFloat32x4Zero:
3293 case MethodRecognizer::kFloat64x2Abs:
3294 case MethodRecognizer::kFloat64x2Clamp:
3295 case MethodRecognizer::kFloat64x2FromDoubles:
3296 case MethodRecognizer::kFloat64x2GetSignMask:
3297 case MethodRecognizer::kFloat64x2GetX:
3298 case MethodRecognizer::kFloat64x2GetY:
3299 case MethodRecognizer::kFloat64x2Max:
3300 case MethodRecognizer::kFloat64x2Min:
3301 case MethodRecognizer::kFloat64x2Negate:
3302 case MethodRecognizer::kFloat64x2Scale:
3303 case MethodRecognizer::kFloat64x2Splat:
3304 case MethodRecognizer::kFloat64x2Sqrt:
3305 case MethodRecognizer::kFloat64x2ToFloat32x4:
3306 case MethodRecognizer::kFloat64x2WithX:
3307 case MethodRecognizer::kFloat64x2WithY:
3308 case MethodRecognizer::kFloat64x2Zero:
3309 case MethodRecognizer::kInt32x4FromBools:
3310 case MethodRecognizer::kInt32x4FromInts:
3311 case MethodRecognizer::kInt32x4GetFlagW:
3312 case MethodRecognizer::kInt32x4GetFlagX:
3313 case MethodRecognizer::kInt32x4GetFlagY:
3314 case MethodRecognizer::kInt32x4GetFlagZ:
3315 case MethodRecognizer::kInt32x4GetSignMask:
3316 case MethodRecognizer::kInt32x4Select:
3317 case MethodRecognizer::kInt32x4ToFloat32x4:
3318 case MethodRecognizer::kInt32x4WithFlagW:
3319 case MethodRecognizer::kInt32x4WithFlagX:
3320 case MethodRecognizer::kInt32x4WithFlagY:
3321 case MethodRecognizer::kInt32x4WithFlagZ:
3322 case MethodRecognizer::kFloat32x4ShuffleMix:
3323 case MethodRecognizer::kInt32x4ShuffleMix:
3324 case MethodRecognizer::kFloat32x4Shuffle:
3325 case MethodRecognizer::kInt32x4Shuffle:
3326 case MethodRecognizer::kFloat32x4Mul:
3327 case MethodRecognizer::kFloat32x4Div:
3328 case MethodRecognizer::kFloat32x4Add:
3329 case MethodRecognizer::kFloat32x4Sub:
3330 case MethodRecognizer::kFloat64x2Mul:
3331 case MethodRecognizer::kFloat64x2Div:
3332 case MethodRecognizer::kFloat64x2Add:
3333 case MethodRecognizer::kFloat64x2Sub:
3335 graph_entry, entry, last,
result);
3337 case MethodRecognizer::kMathIntPow:
3341 case MethodRecognizer::kObjectConstructor: {
3345 (*entry)->InheritDeoptTarget(
Z,
call);
3353 case MethodRecognizer::kObjectArrayAllocate: {
3362 (*entry)->InheritDeoptTarget(
Z,
call);
3363 *last =
new (
Z) CreateArrayInstr(
call->source(),
type, num_elements,
3369 *
result = (*last)->AsDefinition();
3376 case MethodRecognizer::kObjectRuntimeType: {
3382 }
else if (receiver_cid == kDoubleCid) {
3388 }
else if ((receiver_cid != kClosureCid) &&
3389 (receiver_cid != kRecordCid)) {
3392 if (!cls.IsGeneric()) {
3393 type = cls.DeclarationType();
3397 if (!
type.IsNull()) {
3401 (*entry)->InheritDeoptTarget(
Z,
call);
3405 RedefinitionInstr* redef =
3406 new (
Z) RedefinitionInstr(
new (
Z)
Value(ctype));
3417 case MethodRecognizer::kWriteIntoOneByteString:
3418 case MethodRecognizer::kWriteIntoTwoByteString: {
3424 (*entry)->InheritDeoptTarget(
Z,
call);
3425 Definition* str =
call->ArgumentAt(0);
3426 Definition* index =
call->ArgumentAt(1);
3427 Definition*
value =
call->ArgumentAt(2);
3429 const bool is_onebyte = kind == MethodRecognizer::kWriteIntoOneByteString;
3430 const intptr_t index_scale = is_onebyte ? 1 : 2;
3431 const intptr_t
cid = is_onebyte ? kOneByteStringCid : kTwoByteStringCid;
3440 *last =
new (
Z) StoreIndexedInstr(
static float prev(float f)
#define check(reporter, ref, unref, make, kill)
#define RELEASE_ASSERT(cond)
#define INIT_HANDLE(iface, type, cid)
#define PUBLIC_TYPED_DATA_CLASS_LIST(V)
bool IsTopTypeForSubtyping() const
bool IsInt32x4Type() const
bool IsFloat64x2Type() const
virtual bool IsInstantiated(Genericity genericity=kAny, intptr_t num_free_fun_type_params=kAllFree) const
bool IsDoubleType() const
bool IsFloat32x4Type() const
static constexpr bool IsValidLength(intptr_t len)
const T & At(intptr_t index) const
void SetLength(intptr_t new_length)
bool OperandsAre(intptr_t cid) const
bool OperandsAreSmiOrMint() const
bool IncludesOperands(intptr_t cid) const
bool OperandsAreSmiOrNull() const
bool ArgumentIs(intptr_t cid) const
static const BinaryFeedback * CreateMonomorphic(Zone *zone, intptr_t receiver_cid, intptr_t argument_cid)
bool OperandsAreSmiOrDouble() const
intptr_t try_index() const
static const Bool & Get(bool value)
static const Bool & True()
static BoxInstr * Create(Representation from, Value *value)
static bool HasSingleConcreteImplementation(const Class &interface, intptr_t *implementation_cid)
virtual void VisitStaticCall(StaticCallInstr *instr)
void AddReceiverCheck(InstanceCallInstr *call)
bool TryReplaceWithEqualityOp(InstanceCallInstr *call, Token::Kind op_kind)
FlowGraph * flow_graph() const
void AddCheckNull(Value *to_check, const String &function_name, intptr_t deopt_id, Environment *deopt_environment, Instruction *insert_before)
void AddCheckClass(Definition *to_check, const Cids &cids, intptr_t deopt_id, Environment *deopt_environment, Instruction *insert_before)
void ReplaceCall(Definition *call, Definition *replacement)
bool TryInlineInstanceSetter(InstanceCallInstr *call)
void InsertBefore(Instruction *next, Instruction *instr, Environment *env, FlowGraph::UseKind use_kind)
const bool should_clone_fields_
void ReplaceCallWithResult(Definition *call, Instruction *replacement, Definition *result)
virtual void VisitLoadCodeUnits(LoadCodeUnitsInstr *instr)
virtual bool TryCreateICData(InstanceCallInstr *call)
void InlineImplicitInstanceGetter(Definition *call, const Field &field)
bool TryInlineInstanceGetter(InstanceCallInstr *call)
bool TryReplaceWithRelationalOp(InstanceCallInstr *call, Token::Kind op_kind)
virtual bool TryOptimizeStaticCallUsingStaticTypes(StaticCallInstr *call)=0
bool TryReplaceWithUnaryOp(InstanceCallInstr *call, Token::Kind op_kind)
SpeculativeInliningPolicy * speculative_policy_
const Function & function() const
virtual void ReplaceInstanceCallsWithDispatchTableCalls()
void ReplaceWithInstanceOf(InstanceCallInstr *instr)
bool TryReplaceWithBinaryOp(InstanceCallInstr *call, Token::Kind op_kind)
bool TryInlineInstanceMethod(InstanceCallInstr *call)
virtual bool TryReplaceInstanceOfWithRangeCheck(InstanceCallInstr *call, const AbstractType &type)
void InsertSpeculativeBefore(Instruction *next, Instruction *instr, Environment *env, FlowGraph::UseKind use_kind)
static const CallTargets * CreateMonomorphic(Zone *zone, intptr_t receiver_cid, const Function &target)
bool HasSingleTarget() const
const Function & FirstTarget() const
StaticTypeExactnessState MonomorphicExactness() 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)
bool IsMonomorphic() const
ClassPtr At(intptr_t cid) const
intptr_t NumTypeArguments() const
static bool IsSubtypeOf(const Class &cls, const TypeArguments &type_arguments, Nullability nullability, const AbstractType &other, Heap::Space space, FunctionTypeMapping *function_type_equivalence=nullptr)
bool is_finalized() const
static CompilerState & Current()
const Object & value() const
Value * input_use_list() const
virtual Definition * AsDefinition()
static constexpr intptr_t kNone
static DoublePtr NewCanonical(double d)
bool NeedsInitializationCheckOnLoad() const
FieldPtr CloneFromOriginal() const
bool needs_length_check() const
StaticTypeExactnessState static_type_exactness_state() const
bool needs_load_guard() const
bool is_covariant() const
intptr_t guarded_cid() const
bool is_generic_covariant_impl() const
AbstractTypePtr type() const
static const CallTargets * ResolveCallTargetsForReceiverCid(intptr_t cid, const String &selector, const Array &args_desc_array)
static bool SupportsUnboxedSimd128()
static bool CanConvertInt64ToDouble()
ForwardInstructionIterator * current_iterator() const
ForwardInstructionIterator * current_iterator_
virtual void VisitBlocks()
ConstantInstr * GetConstant(const Object &object, Representation representation=kTagged)
IsolateGroup * isolate_group() const
Instruction * AppendTo(Instruction *prev, Instruction *instr, Environment *env, UseKind use_kind)
void ReplaceCurrentInstruction(ForwardInstructionIterator *iterator, Instruction *current, Instruction *replacement)
Instruction * AppendSpeculativeTo(Instruction *prev, Instruction *instr, Environment *env, UseKind use_kind)
ToCheck CheckForInstanceCall(InstanceCallInstr *call, UntaggedFunction::Kind kind) const
void AddExactnessGuard(InstanceCallInstr *call, intptr_t receiver_cid)
Definition * CreateCheckBound(Definition *length, Definition *index, intptr_t deopt_id)
ConstantInstr * constant_null() const
Instruction * CreateCheckClass(Definition *to_check, const Cids &cids, intptr_t deopt_id, const InstructionSource &source)
const ParsedFunction & parsed_function() const
BlockIterator reverse_postorder_iterator() const
void InsertBefore(Instruction *next, Instruction *instr, Environment *env, UseKind use_kind)
intptr_t allocate_block_id()
Instruction * Current() const
void RemoveCurrentFromGraph()
static bool IsDynamicInvocationForwarderName(const String &name)
bool IsInvokeFieldDispatcher() const
FieldPtr accessor_field() const
intptr_t NumArgsTested() const
bool HasDeoptReason(ICData::DeoptReasonId reason) const
intptr_t GetReceiverClassIdAt(intptr_t index) const
intptr_t NumberOfChecks() const
Code::EntryKind entry_kind() const
const Function & interface_target() const
const String & function_name() const
const CallTargets & Targets()
static intptr_t ElementSizeFor(intptr_t cid)
void InheritDeoptTarget(Zone *zone, Instruction *other)
virtual BlockEntryInstr * GetBlock()
Environment * env() const
const char * ToCString() const
virtual intptr_t ArgumentCount() const
Definition * ArgumentAt(intptr_t index) const
void SetInputAt(intptr_t i, Value *value)
InstructionSource source() const
Value * ArgumentValueAt(intptr_t index) const
intptr_t deopt_id() const
SafepointRwLock * program_lock()
static IsolateGroup * Current()
ClassTable * class_table() const
static LibraryPtr LookupLibrary(Thread *thread, const String &url)
bool can_pack_into_smi() const
void set_representation(Representation repr)
static Representation ReturnRepresentation(intptr_t array_cid)
static intptr_t MethodKindToReceiverCid(Kind kind)
static Object & ZoneHandle()
bool TryInline(MethodRecognizer::Kind kind)
SimdLowering(FlowGraph *flow_graph, Instruction *call, GraphEntryInstr *graph_entry, FunctionEntryInstr **entry, Instruction **last, Definition **result)
static SimdOpInstr * Create(Kind kind, Value *left, Value *right, intptr_t deopt_id)
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 KindForOperator(MethodRecognizer::Kind kind)
static const Slot & Get(const Field &field, const ParsedFunction *parsed_function)
static const Slot & GetLengthFieldForArrayCid(intptr_t array_cid)
static const Slot & GetTypeArgumentsSlotFor(Thread *thread, const Class &cls)
static SmiPtr New(intptr_t value)
bool IsAllowedForInlining(intptr_t call_deopt_id) const
static StaticCallInstr * FromCall(Zone *zone, const C *call, const Function &target, intptr_t call_count)
bool IsTriviallyExact() const
bool NeedsFieldGuard() const
static Representation ValueRepresentation(intptr_t array_cid)
intptr_t FirstArgIndex() const
IsolateGroup * isolate_group() const
static bool IsTypeTestOperator(Kind tok)
static bool IsRelationalOperator(Kind tok)
static bool IsBinaryOperator(Token::Kind token)
static bool IsEqualityOperator(Kind tok)
static TypePtr StringType()
static TypePtr Float64x2()
static TypePtr Float32x4()
static TypePtr DartTypeType()
virtual void VisitStaticCall(StaticCallInstr *instr)
virtual void VisitInstanceCall(InstanceCallInstr *instr)
static void Optimize(FlowGraph *flow_graph)
static UnboxInstr * Create(Representation to, Value *value, intptr_t deopt_id, SpeculativeMode speculative_mode=kGuardInputs)
static constexpr bool IsPowerOfTwo(T x)
bool BindsToConstant() const
const Object & BoundConstant() const
Value * CopyWithType(Zone *zone)
Definition * definition() const
static word ElementSizeFor(intptr_t cid)
#define COMPILER_TIMINGS_TIMER_SCOPE(thread, timer_id)
#define THR_Print(format,...)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Dart_NativeFunction function
constexpr intptr_t kSmiBits
def link(from_root, to_root)
static bool CanConvertInt64ToDouble()
static bool CidTestResultsContains(const ZoneGrowableArray< intptr_t > &results, intptr_t test_cid)
static bool ShouldInlineSimd()
static bool InlineDoubleTestOp(FlowGraph *flow_graph, Instruction *call, Definition *receiver, MethodRecognizer::Kind kind, GraphEntryInstr *graph_entry, FunctionEntryInstr **entry, Instruction **last, Definition **result)
bool IsTypedDataBaseClassId(intptr_t index)
static bool IsSmiValue(Value *val, intptr_t *int_val)
static constexpr Representation kUnboxedUword
static bool IsLengthOneString(Definition *d)
static bool InlineMathIntPow(FlowGraph *flow_graph, Instruction *call, GraphEntryInstr *graph_entry, FunctionEntryInstr **entry, Instruction **last, Definition **result)
bool IsTypeClassId(intptr_t index)
static bool InlineSetIndexed(FlowGraph *flow_graph, MethodRecognizer::Kind kind, const Function &target, Instruction *call, Definition *receiver, const InstructionSource &source, CallSpecializer::ExactnessInfo *exactness, GraphEntryInstr *graph_entry, FunctionEntryInstr **entry, Instruction **last, Definition **result)
static bool CheckMask(Definition *definition, intptr_t *mask_ptr)
static void RefineUseTypes(Definition *instr)
static bool InlineDoubleOp(FlowGraph *flow_graph, Token::Kind op_kind, Instruction *call, Definition *receiver, GraphEntryInstr *graph_entry, FunctionEntryInstr **entry, Instruction **last, Definition **result)
static bool ShouldSpecializeForDouble(const BinaryFeedback &binary_feedback)
static bool InlineGetIndexed(FlowGraph *flow_graph, bool can_speculate, bool is_dynamic_call, MethodRecognizer::Kind kind, Definition *call, Definition *receiver, GraphEntryInstr *graph_entry, FunctionEntryInstr **entry, Instruction **last, Definition **result)
static void TryAddTest(ZoneGrowableArray< intptr_t > *results, intptr_t test_cid, bool result)
static intptr_t PrepareInlineIndexedOp(FlowGraph *flow_graph, Instruction *call, intptr_t array_cid, Definition **array, Definition **index, Instruction **cursor)
static bool InlineStringBaseCodeUnitAt(FlowGraph *flow_graph, Instruction *call, Definition *receiver, intptr_t cid, GraphEntryInstr *graph_entry, FunctionEntryInstr **entry, Instruction **last, Definition **result)
static Instruction * InlineMul(FlowGraph *flow_graph, Instruction *cursor, Definition *x, Definition *y)
static bool InlineSimdOp(FlowGraph *flow_graph, bool is_dynamic_call, Instruction *call, Definition *receiver, MethodRecognizer::Kind kind, GraphEntryInstr *graph_entry, FunctionEntryInstr **entry, Instruction **last, Definition **result)
static bool IsNumberCid(intptr_t cid)
static void PurgeNegativeTestCidsEntries(ZoneGrowableArray< intptr_t > *results)
static constexpr Representation kUnboxedIntPtr
static bool InlineGrowableArraySetter(FlowGraph *flow_graph, const Slot &field, StoreBarrierType store_barrier_type, Instruction *call, Definition *receiver, GraphEntryInstr *graph_entry, FunctionEntryInstr **entry, Instruction **last, Definition **result)
bool IsIntegerClassId(intptr_t index)
static bool InlineStringBaseCharAt(FlowGraph *flow_graph, Instruction *call, Definition *receiver, intptr_t cid, GraphEntryInstr *graph_entry, FunctionEntryInstr **entry, Instruction **last, Definition **result)
static bool InlineLoadClassId(FlowGraph *flow_graph, Instruction *call, GraphEntryInstr *graph_entry, FunctionEntryInstr **entry, Instruction **last, Definition **result)
const char *const function_name
static CompileType * ResultType(Definition *call)
static Definition * PrepareInlineStringIndexOp(FlowGraph *flow_graph, Instruction *call, intptr_t cid, Definition *str, Definition *index, Instruction *cursor)
static bool InlineTypedDataIndexCheck(FlowGraph *flow_graph, Instruction *call, Definition *receiver, GraphEntryInstr *graph_entry, FunctionEntryInstr **entry, Instruction **last, Definition **result, const String &symbol)
static bool SmiFitsInDouble()
bool IsExternalTypedDataClassId(intptr_t index)
bool IsStringClassId(intptr_t index)
DECLARE_FLAG(bool, show_invisible_frames)
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 policy
bool emit_exactness_guard
static constexpr bool IsUnboxedInteger(Representation rep)
static constexpr bool IsUnboxed(Representation rep)
static Representation RepresentationOfArrayElement(classid_t cid)