19#define IG (isolate_group())
25 it.Current()->RefineReachingType(new_type);
42 return (
cid == kSmiCid) || (
cid == kDoubleCid);
74 !block_it.Done(); block_it.Advance()) {
80 if (instr->IsInstanceCall()) {
82 if (call->HasICData()) {
84 VisitInstanceCall(call);
87 }
else if (
auto static_call = instr->AsStaticCall()) {
91 }
else if (instr->IsPolymorphicInstanceCall()) {
92 SpecializePolymorphicInstanceCall(instr->AsPolymorphicInstanceCall());
100 ASSERT(call->HasICData());
102 if (call->Targets().length() > 0) {
108 const intptr_t receiver_index = call->FirstArgIndex();
110 ASSERT(call->ic_data()->NumArgsTested() <=
111 call->ArgumentCountWithoutTypeArgs());
112 for (intptr_t i = 0; i < call->ic_data()->NumArgsTested(); i++) {
113 class_ids.
Add(call->ArgumentValueAt(receiver_index + i)->Type()->ToCid());
124 if (call->CanReceiverBeSmiBasedOnInterfaceTarget(
zone())) {
125 const intptr_t cid_0 = class_ids[0];
126 const intptr_t cid_1 = class_ids[1];
128 class_ids[0] = cid_1;
130 class_ids[1] = cid_0;
136 bool all_cids_known =
true;
137 for (intptr_t i = 0; i < class_ids.
length(); i++) {
140 all_cids_known =
false;
145 if (all_cids_known) {
146 const intptr_t receiver_cid = class_ids[0];
147 if (receiver_cid == kSentinelCid) {
151 const Class& receiver_class =
160 Z, call->ResolveForReceiverClass(receiver_class,
false));
170 if (class_ids.
length() == 2) {
171 call->SetBinaryFeedback(
180void CallSpecializer::SpecializePolymorphicInstanceCall(
182 if (!FLAG_polymorphic_with_deopt) {
187 const intptr_t receiver_cid = call->Receiver()->Type()->ToCid();
192 const ICData& ic_data = *
call->ic_data();
194 const CallTargets* targets =
198 if (targets ==
nullptr) {
203 ASSERT(targets->HasSingleTarget());
204 const Function&
target = targets->FirstTarget();
205 StaticCallInstr* specialized =
213 ASSERT(!call->HasMoveArguments());
215 ASSERT(replacement->IsDefinition());
226void CallSpecializer::AddCheckSmi(
Definition* to_check,
231 if (to_check->
Type()->
ToCid() != kSmiCid) {
252 int argument_number) {
255 AddCheckClass(argument, *cids, call->deopt_id(), call->env(), call);
266 deopt_id, insert_before->
source());
267 if (FLAG_trace_strong_mode_types) {
268 THR_Print(
"[Strong mode] Inserted %s\n", check_null->ToCString());
270 InsertBefore(insert_before, check_null, deopt_environment,
278 if (
d->IsConstant()) {
279 const Object& obj =
d->AsConstant()->value();
280 if (obj.IsString()) {
281 return String::Cast(obj).Length() == 1;
286 return d->IsOneByteStringFromCharCode();
293bool CallSpecializer::TryStringLengthOneEquality(InstanceCallInstr* call,
295 ASSERT(call->BinaryFeedback().OperandsAre(kOneByteStringCid));
298 Definition*
left = call->ArgumentAt(0);
299 Definition*
right = call->ArgumentAt(1);
300 Value* left_val =
nullptr;
301 Definition* to_remove_left =
nullptr;
304 Definition* temp =
left;
311 if (
left->IsConstant()) {
312 ConstantInstr* left_const =
left->AsConstant();
313 const String& str = String::Cast(left_const->value());
314 ASSERT(str.Length() == 1);
317 left_val =
new (
Z)
Value(char_code_left);
318 }
else if (
left->IsOneByteStringFromCharCode()) {
320 OneByteStringFromCharCodeInstr* instr =
321 left->AsOneByteStringFromCharCode();
322 left_val =
new (
Z)
Value(instr->char_code()->definition());
323 to_remove_left = instr;
329 Definition* to_remove_right =
nullptr;
330 Value* right_val =
nullptr;
331 if (
right->IsOneByteStringFromCharCode()) {
333 OneByteStringFromCharCodeInstr* right_instr =
334 right->AsOneByteStringFromCharCode();
335 right_val =
new (
Z)
Value(right_instr->char_code()->definition());
336 to_remove_right = right_instr;
338 AddChecksForArgNr(call,
right, 1);
341 StringToCharCodeInstr* char_code_right =
new (
Z)
342 StringToCharCodeInstr(
new (
Z)
Value(
right), kOneByteStringCid);
344 right_val =
new (
Z)
Value(char_code_right);
348 EqualityCompareInstr* comp =
349 new (
Z) EqualityCompareInstr(
call->source(), op_kind, left_val,
350 right_val, kSmiCid,
call->deopt_id());
354 if ((to_remove_left !=
nullptr) &&
355 (to_remove_left->input_use_list() ==
nullptr)) {
356 to_remove_left->ReplaceUsesWith(
flow_graph()->constant_null());
357 to_remove_left->RemoveFromGraph();
359 if ((to_remove_right !=
nullptr) &&
360 (to_remove_right->input_use_list() ==
nullptr)) {
361 to_remove_right->ReplaceUsesWith(
flow_graph()->constant_null());
362 to_remove_right->RemoveFromGraph();
370 return compiler::target::kSmiBits < 53;
377 ASSERT(call->type_args_len() == 0);
378 ASSERT(call->ArgumentCount() == 2);
383 if (binary_feedback.
OperandsAre(kOneByteStringCid)) {
384 return TryStringLengthOneEquality(call, op_kind);
420 AddChecksForArgNr(call,
left, 0);
421 AddChecksForArgNr(call,
right, 1);
430 if ((right_const !=
nullptr && right_const->
value().
IsNull()) ||
431 (left_const !=
nullptr && left_const->
value().
IsNull())) {
452 ASSERT(call->type_args_len() == 0);
453 ASSERT(call->ArgumentCount() == 2);
504 ASSERT(call->HasICData());
514 call->ic_data()->HasDeoptReason(ICData::kDeoptBinarySmiOp)
520 if (call->ic_data()->HasDeoptReason(ICData::kDeoptBinaryInt64Op))
522 operands_type = kMintCid;
524 operands_type = kDoubleCid;
525 }
else if (binary_feedback.
OperandsAre(kFloat32x4Cid)) {
526 operands_type = kFloat32x4Cid;
527 }
else if (binary_feedback.
OperandsAre(kInt32x4Cid)) {
528 ASSERT(op_kind != Token::kMUL);
529 operands_type = kInt32x4Cid;
530 }
else if (binary_feedback.
OperandsAre(kFloat64x2Cid)) {
531 operands_type = kFloat64x2Cid;
539 operands_type = kDoubleCid;
540 }
else if (binary_feedback.
OperandsAre(kFloat32x4Cid)) {
541 operands_type = kFloat32x4Cid;
542 }
else if (binary_feedback.
OperandsAre(kFloat64x2Cid)) {
543 operands_type = kFloat64x2Cid;
548 case Token::kBIT_AND:
550 case Token::kBIT_XOR:
552 operands_type = kSmiCid;
554 operands_type = kMintCid;
555 }
else if (binary_feedback.
OperandsAre(kInt32x4Cid)) {
556 operands_type = kInt32x4Cid;
568 if (call->ic_data()->HasDeoptReason(ICData::kDeoptBinaryInt64Op)) {
572 call->ic_data()->HasDeoptReason(ICData::kDeoptBinarySmiOp)
579 if (call->ic_data()->HasDeoptReason(ICData::kDeoptBinaryInt64Op)) {
583 operands_type = kMintCid;
589 case Token::kTRUNCDIV:
591 if (call->ic_data()->HasDeoptReason(ICData::kDeoptBinarySmiOp)) {
594 operands_type = kSmiCid;
603 ASSERT(call->type_args_len() == 0);
604 ASSERT(call->ArgumentCount() == 2);
607 if (operands_type == kDoubleCid) {
614 if (op_kind != Token::kDIV) {
624 call->deopt_id(), call->source());
626 }
else if (operands_type == kMintCid) {
627 if ((op_kind == Token::kSHL) || (op_kind == Token::kSHR) ||
628 (op_kind == Token::kUSHR)) {
638 }
else if ((operands_type == kFloat32x4Cid) ||
639 (operands_type == kInt32x4Cid) ||
640 (operands_type == kFloat64x2Cid)) {
641 return InlineSimdBinaryOp(call, operands_type, op_kind);
642 }
else if (op_kind == Token::kMOD) {
643 ASSERT(operands_type == kSmiCid);
644 if (
right->IsConstant()) {
651 call->deopt_id(), call->source()),
657 new (
Z)
Value(constant), call->deopt_id());
664 AddCheckSmi(
left, call->deopt_id(), call->env(), call);
665 AddCheckSmi(
right, call->deopt_id(), call->env(), call);
670 ASSERT(operands_type == kSmiCid);
673 AddCheckSmi(
left, call->deopt_id(), call->env(), call);
674 AddCheckSmi(
right, call->deopt_id(), call->env(), call);
675 if (
left->IsConstant() &&
676 ((op_kind == Token::kADD) || (op_kind == Token::kMUL))) {
691 ASSERT(call->type_args_len() == 0);
692 ASSERT(call->ArgumentCount() == 1);
695 if (call->Targets().ReceiverIs(kSmiCid)) {
702 }
else if ((op_kind == Token::kBIT_NOT) &&
703 call->Targets().ReceiverIsSmiOrMint()) {
706 }
else if (call->Targets().ReceiverIs(kDoubleCid) &&
714 ASSERT(unary_op !=
nullptr);
734 call, UntaggedFunction::kImplicitGetter)) {
753 const Field& field) {
760 new (
Z)
Value(receiver), slot, call->source(), calls_initializer,
768 if (!calls_initializer) {
770 call->RemoveEnvironment();
777 it.Current()->SetReachingType(
nullptr);
790 if (
target.kind() != UntaggedFunction::kImplicitSetter) {
807 instr, UntaggedFunction::kImplicitSetter)) {
810 instr->
env(), instr);
823 bool is_unchecked_call =
false;
830 is_unchecked_call =
true;
834 if (
IG->use_field_guards()) {
865 bool needs_check =
true;
877 needs_check = !(is_unchecked_call ||
878 (instr->
entry_kind() == Code::EntryKind::kUnchecked));
903 new (
Z)
Value(instantiator_type_args),
904 new (
Z)
Value(function_type_args),
931 ASSERT(call->type_args_len() == 0);
932 ASSERT(call->ArgumentCount() == 2);
933 Definition*
const left = call->ArgumentAt(0);
934 Definition*
const right = call->ArgumentAt(1);
936 AddChecksForArgNr(call,
left, 0);
937 AddChecksForArgNr(call,
right, 1);
956 if (
target.kind() != UntaggedFunction::kImplicitGetter) {
964 return TryInlineImplicitInstanceGetter(call);
980 (recognized_kind == MethodRecognizer::kIntegerToDouble)) {
981 if (receiver_cid == kSmiCid) {
996 if (receiver_cid == kDoubleCid) {
1000 switch (recognized_kind) {
1001 case MethodRecognizer::kDoubleToInteger: {
1003 ASSERT(call->HasICData());
1004 const ICData& ic_data = *call->ic_data();
1010 new (
Z)
Value(input), recognized_kind, call->deopt_id());
1024 return TryReplaceInstanceCallWithInline(flow_graph_,
current_iterator(), call,
1035BoolPtr CallSpecializer::InstanceOfAsBool(
1041 if (
type.IsFunctionType() ||
type.IsDartFunctionType() ||
1042 type.IsRecordType() || !
type.IsInstantiated()) {
1046 const intptr_t num_type_args = type_class.NumTypeArguments();
1047 if (num_type_args > 0) {
1050 const TypeArguments& type_arguments =
1052 const bool is_raw_type = type_arguments.IsNull() ||
1053 type_arguments.IsRaw(0, type_arguments.Length());
1060 const ClassTable& class_table = *
IG->class_table();
1064 bool results_differ =
false;
1066 for (
int i = 0; i < number_of_checks; i++) {
1068 if (cls.NumTypeArguments() > 0) {
1071 bool is_subtype =
false;
1072 if (cls.IsNullClass()) {
1076 const AbstractType& unwrapped_type =
1078 ASSERT(unwrapped_type.IsInstantiated());
1079 is_subtype = unwrapped_type.IsTopTypeForInstanceOf() ||
1080 unwrapped_type.IsNullable() ||
1081 (unwrapped_type.IsLegacy() && unwrapped_type.IsNeverType());
1087 results->
Add(cls.id());
1088 results->
Add(
static_cast<intptr_t
>(is_subtype));
1089 if (
prev.IsNull()) {
1092 if (is_subtype !=
prev.value()) {
1093 results_differ =
true;
1101bool CallSpecializer::TypeCheckAsClassEquality(
const AbstractType&
type,
1102 intptr_t* type_cid) {
1106 if (!
type.IsInstantiated())
return false;
1108 if (
type.IsFunctionType() ||
type.IsRecordType())
return false;
1115 const intptr_t num_type_args = type_class.NumTypeArguments();
1116 if (num_type_args > 0) {
1119 const TypeArguments& type_arguments =
1121 const bool is_raw_type = type_arguments.IsNull() ||
1122 type_arguments.IsRaw(0, type_arguments.Length());
1127 if (
type.IsNullable() ||
type.IsTopTypeForInstanceOf() ||
1128 type.IsNeverType()) {
1144bool CallSpecializer::TryOptimizeInstanceOfUsingStaticTypes(
1148 if (!
type.IsInstantiated()) {
1152 Value* left_value = call->Receiver();
1153 if (left_value->Type()->IsInstanceOf(
type)) {
1155 call->ReplaceUsesWith(replacement);
1166 if ((
type.IsNullable() && !
type.IsNullType()) ||
type.IsFutureOrType()) {
1174 if (
type.IsNullType() || (
type.IsNeverType() &&
type.IsLegacy()) ||
1175 left_value->Type()->IsSubtypeOf(
type)) {
1176 Definition* replacement =
new (
Z) StrictCompareInstr(
1178 (
type.IsNullType() || (
type.IsNeverType() &&
type.IsLegacy()))
1180 : Token::kNE_STRICT,
1181 left_value->CopyWithType(
Z),
1184 if (FLAG_trace_strong_mode_types) {
1185 THR_Print(
"[Strong mode] replacing %s with %s (%s < %s)\n",
1186 call->ToCString(), replacement->ToCString(),
1187 left_value->Type()->ToAbstractType()->ToCString(),
1200 Definition* instantiator_type_args =
nullptr;
1203 ASSERT(call->type_args_len() == 0);
1204 if (call->ArgumentCount() == 2) {
1207 ASSERT(call->MatchesCoreName(Symbols::_simpleInstanceOf()));
1208 type = AbstractType::Cast(call->ArgumentAt(1)->AsConstant()->value()).ptr();
1210 ASSERT(call->ArgumentCount() == 4);
1211 instantiator_type_args = call->ArgumentAt(1);
1212 function_type_args = call->ArgumentAt(2);
1213 type = AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()).ptr();
1216 if (TryOptimizeInstanceOfUsingStaticTypes(call,
type)) {
1221 if (TypeCheckAsClassEquality(
type, &type_cid)) {
1228 call->source(), Token::kEQ,
new Value(load_cid),
1239 const ICData& unary_checks =
1242 if (number_of_checks > 0 && number_of_checks <= FLAG_max_polymorphic_checks) {
1245 const Bool& as_bool =
1248 if (results->
length() == number_of_checks * 2) {
1249 const bool can_deopt = SpecializeTestCidsForNumericTypes(results,
type);
1256 call->source(), Token::kIS,
new (
Z)
Value(
left), *results,
1266 ASSERT(!call->HasMoveArguments());
1267 call->ReplaceUsesWith(bool_const);
1276 new (
Z)
Value(instantiator_type_args),
new (
Z)
Value(function_type_args),
1277 type, call->deopt_id());
1294 switch (recognized_kind) {
1295 case MethodRecognizer::kMathMin:
1296 case MethodRecognizer::kMathMax: {
1300 (call->FirstArgIndex() == 0)) {
1303 result_cid = kDoubleCid;
1305 result_cid = kSmiCid;
1309 recognized_kind,
new (
Z)
Value(call->ArgumentAt(0)),
1310 new (
Z)
Value(call->ArgumentAt(1)), call->deopt_id(),
1314 call->deopt_id(), call->env(), call);
1316 call->deopt_id(), call->env(), call);
1323 case MethodRecognizer::kDoubleFromInteger: {
1325 (call->FirstArgIndex() == 0)) {
1329 AddCheckSmi(arg, call->deopt_id(), call->env(), call);
1333 }
else if (binary_feedback.
ArgumentIs(kMintCid) &&
1357#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM)
1363 intptr_t test_cid) {
1364 for (intptr_t i = 0; i < results.
length(); i += 2) {
1365 if (results[i] == test_cid)
return true;
1374 results->
Add(test_cid);
1375 results->
Add(
static_cast<intptr_t
>(
result));
1385 for (intptr_t i = 2; i < results->
length(); i += 2) {
1386 if (results->
At(i + 1) != 0) {
1387 (*results)[dest++] = results->
At(i);
1388 (*results)[dest++] = results->
At(i + 1);
1394bool CallSpecializer::SpecializeTestCidsForNumericTypes(
1395 ZoneGrowableArray<intptr_t>* results,
1396 const AbstractType&
type) {
1397 ASSERT(results->length() >= 2);
1399 if ((*results)[0] != kSmiCid) {
1400 const Class& smi_class =
Class::Handle(class_table.At(kSmiCid));
1401 const bool smi_is_subtype =
1404 results->Add((*results)[results->length() - 2]);
1405 results->Add((*results)[results->length() - 2]);
1406 for (intptr_t i = results->length() - 3; i > 1; --i) {
1407 (*results)[i] = (*results)[i - 2];
1409 (*results)[0] = kSmiCid;
1410 (*results)[1] =
static_cast<intptr_t
>(smi_is_subtype);
1414 ASSERT(results->length() >= 2);
1415 if (
type.IsSmiType()) {
1416 ASSERT((*results)[0] == kSmiCid);
1419 }
else if (
type.IsIntType()) {
1420 ASSERT((*results)[0] == kSmiCid);
1425 }
else if (
type.IsNumberType()) {
1426 ASSERT((*results)[0] == kSmiCid);
1431 }
else if (
type.IsDoubleType()) {
1432 ASSERT((*results)[0] == kSmiCid);
1445void TypedDataSpecializer::EnsureIsInitialized() {
1446 if (initialized_)
return;
1448 initialized_ =
true;
1460#define INIT_HANDLE(iface, member_name, type, cid) \
1461 td_class = typed_data.LookupClass(Symbols::iface()); \
1462 ASSERT(!td_class.IsNull()); \
1463 direct_implementors = td_class.direct_implementors(); \
1464 member_name = td_class.RareType();
1471 TryInlineCall(call);
1477 ASSERT(call->ArgumentCount() > 0);
1478 TryInlineCall(call);
1483 const bool is_length_getter = call->Selector() == Symbols::GetLength().ptr();
1484 const bool is_index_get = call->Selector() == Symbols::IndexToken().ptr();
1485 const bool is_index_set =
1486 call->Selector() == Symbols::AssignIndexToken().ptr();
1488 if (is_length_getter || is_index_get || is_index_set) {
1489 EnsureIsInitialized();
1491 const intptr_t receiver_index = call->FirstArgIndex();
1494 call->ArgumentValueAt(receiver_index + 0)->Type();
1497 if (is_index_get || is_index_set) {
1498 index_type = call->ArgumentValueAt(receiver_index + 1)->Type();
1501 CompileType* value_type =
nullptr;
1503 value_type = call->ArgumentValueAt(receiver_index + 2)->Type();
1507#define TRY_INLINE(iface, member_name, type, cid) \
1508 if (!member_name.IsNull()) { \
1509 auto const rep = RepresentationUtils::RepresentationOfArrayElement(cid); \
1510 const bool is_float_access = \
1511 rep == kUnboxedFloat || rep == kUnboxedDouble; \
1512 if (receiver_type->IsAssignableTo(member_name)) { \
1513 if (is_length_getter) { \
1514 type_class = member_name.type_class(); \
1515 ReplaceWithLengthGetter(call); \
1516 } else if (is_index_get) { \
1517 if (is_float_access && !FlowGraphCompiler::SupportsUnboxedDoubles()) { \
1520 if (!index_type->IsNullableInt()) return; \
1521 type_class = member_name.type_class(); \
1522 ReplaceWithIndexGet(call, cid); \
1524 if (is_float_access && !FlowGraphCompiler::SupportsUnboxedDoubles()) { \
1527 if (!index_type->IsNullableInt()) return; \
1528 if (!value_type->IsAssignableTo(type)) return; \
1529 type_class = member_name.type_class(); \
1530 ReplaceWithIndexSet(call, cid); \
1540void TypedDataSpecializer::ReplaceWithLengthGetter(TemplateDartCall<0>* call) {
1541 const intptr_t receiver_idx =
call->FirstArgIndex();
1542 auto array =
call->ArgumentAt(receiver_idx + 0);
1544 if (array->Type()->is_nullable()) {
1545 AppendNullCheck(call, &array);
1547 Definition*
length = AppendLoadLength(call, array);
1552void TypedDataSpecializer::ReplaceWithIndexGet(TemplateDartCall<0>* call,
1554 const intptr_t receiver_idx =
call->FirstArgIndex();
1555 auto array =
call->ArgumentAt(receiver_idx + 0);
1556 auto index =
call->ArgumentAt(receiver_idx + 1);
1558 if (array->Type()->is_nullable()) {
1559 AppendNullCheck(call, &array);
1561 if (index->Type()->is_nullable()) {
1562 AppendNullCheck(call, &index);
1564 AppendBoundsCheck(call, array, &index);
1565 Definition*
value = AppendLoadIndexed(call, array, index,
cid);
1570void TypedDataSpecializer::ReplaceWithIndexSet(TemplateDartCall<0>* call,
1572 const intptr_t receiver_idx =
call->FirstArgIndex();
1573 auto array =
call->ArgumentAt(receiver_idx + 0);
1574 auto index =
call->ArgumentAt(receiver_idx + 1);
1575 auto value =
call->ArgumentAt(receiver_idx + 2);
1577 if (array->Type()->is_nullable()) {
1578 AppendNullCheck(call, &array);
1580 if (index->Type()->is_nullable()) {
1581 AppendNullCheck(call, &index);
1583 if (
value->Type()->is_nullable()) {
1584 AppendNullCheck(call, &value);
1586 AppendMutableCheck(call, &array);
1587 AppendBoundsCheck(call, array, &index);
1588 AppendStoreIndexed(call, array, index, value,
cid);
1594void TypedDataSpecializer::AppendNullCheck(TemplateDartCall<0>* call,
1595 Definition** value) {
1597 new (
Z) CheckNullInstr(
new (
Z)
Value(*value), Symbols::OptimizedOut(),
1605void TypedDataSpecializer::AppendMutableCheck(TemplateDartCall<0>* call,
1606 Definition** value) {
1607 auto check =
new (
Z) CheckWritableInstr(
new (
Z)
Value(*value),
1615void TypedDataSpecializer::AppendBoundsCheck(TemplateDartCall<0>* call,
1617 Definition** index) {
1618 auto length =
new (
Z) LoadFieldInstr(
1619 new (
Z)
Value(array), Slot::TypedDataBase_length(),
call->source());
1622 auto check =
new (
Z) GenericCheckBoundInstr(
1630Definition* TypedDataSpecializer::AppendLoadLength(TemplateDartCall<0>* call,
1631 Definition* array) {
1632 auto length =
new (
Z) LoadFieldInstr(
1633 new (
Z)
Value(array), Slot::TypedDataBase_length(),
call->source());
1638Definition* TypedDataSpecializer::AppendLoadIndexed(TemplateDartCall<0>* call,
1646 Definition*
load =
new (
Z) LoadIndexedInstr(
1651 if (rep == kUnboxedFloat) {
1659void TypedDataSpecializer::AppendStoreIndexed(TemplateDartCall<0>* call,
1668 const auto deopt_id =
call->deopt_id();
1676 }
else if (rep == kUnboxedFloat) {
1677 value =
new (
Z) DoubleToFloatInstr(
new (
Z)
Value(value), deopt_id,
1682 auto store =
new (
Z) StoreIndexedInstr(
1705 if (
auto static_call = call->AsStaticCall()) {
1706 return static_call->result_type();
1707 }
else if (
auto instance_call = call->AsInstanceCall()) {
1708 return instance_call->result_type();
1715#define Z (flow_graph->zone())
1728 (*entry)->InheritDeoptTarget(
Z, call);
1739 auto*
const null_check =
1742 cursor = flow_graph->
AppendTo(cursor, null_check, call->env(),
1768 if (array_cid == kGrowableObjectArrayCid) {
1777 array_cid = kArrayCid;
1780 new (
Z)
Value(*array), Slot::PointerBase_data(),
1791 bool is_dynamic_call,
1804 if (!can_speculate && is_dynamic_call && !index->
Type()->
IsInt()) {
1811 (*entry)->InheritDeoptTarget(
Z, call);
1818 intptr_t index_scale = compiler::target::Instance::ElementSizeFor(array_cid);
1822 call->deopt_id(), call->source(),
ResultType(call));
1851 Definition* stored_value = call->ArgumentAt(2);
1856 (*entry)->InheritDeoptTarget(
Z, call);
1859 bool is_unchecked_call =
false;
1862 static_call->entry_kind() == Code::EntryKind::kUnchecked;
1865 instance_call->entry_kind() == Code::EntryKind::kUnchecked;
1867 call->AsPolymorphicInstanceCall()) {
1869 instance_call->entry_kind() == Code::EntryKind::kUnchecked;
1872 if (!is_unchecked_call &&
1873 (kind != MethodRecognizer::kObjectArraySetIndexedUnchecked &&
1874 kind != MethodRecognizer::kGrowableArraySetIndexedUnchecked)) {
1881 if (rep == kTagged) {
1886 flow_graph->
thread(), instantiator_class),
1888 *last = flow_graph->
AppendTo(*last, load_type_args, call->env(),
1890 type_args = load_type_args;
1897 if (rep == kUnboxedFloat || rep == kUnboxedDouble) {
1899 }
else if (rep == kUnboxedFloat32x4) {
1901 }
else if (rep == kUnboxedInt32x4) {
1903 }
else if (rep == kUnboxedFloat64x2) {
1912 if (exactness !=
nullptr && exactness->
is_exact) {
1915 auto const function_type_args = flow_graph->
constant_null();
1916 auto const dst_type = flow_graph->
GetConstant(value_type);
1919 new (
Z)
Value(type_args),
new (
Z)
Value(function_type_args),
1920 Symbols::Value(), call->deopt_id());
1935 if (rep == kUnboxedFloat) {
1936 stored_value =
new (
Z)
1938 *last = flow_graph->
AppendTo(*last, stored_value, call->env(),
1946 *last = flow_graph->
AppendTo(*last, stored_value, call->env(),
1950 const intptr_t index_scale =
1951 compiler::target::Instance::ElementSizeFor(array_cid);
1954 needs_store_barrier,
false, index_scale, array_cid,
1980 (*entry)->InheritDeoptTarget(
Z, call);
1984 call->deopt_id(), call->source());
1986 *last = double_bin_op;
1987 *
result = double_bin_op->AsDefinition();
2007 (*entry)->InheritDeoptTarget(
Z, call);
2011 kind,
new (
Z)
Value(receiver), call->deopt_id(), call->source());
2013 *last = double_test_op;
2014 *
result = double_test_op->AsDefinition();
2034 (*entry)->InheritDeoptTarget(
Z, call);
2039 store_barrier_type, call->source());
2058 (*entry)->InheritDeoptTarget(
Z, call);
2063 *
result = load_cid->AsDefinition();
2083 auto*
const null_check =
new (
Z)
2086 cursor = flow_graph->
AppendTo(cursor, null_check, call->env(),
2095 call->deopt_id(), call->source());
2114 if (
cid != kOneByteStringCid) {
2123 (*entry)->InheritDeoptTarget(
Z, call);
2132 *
result = char_at->AsDefinition();
2146 ASSERT(call->IsStaticCall());
2148 }
else if ((
cid != kOneByteStringCid) && (
cid != kTwoByteStringCid)) {
2157 (*entry)->InheritDeoptTarget(
Z, call);
2160 *
result = (*last)->AsDefinition();
2166bool CallSpecializer::TryReplaceInstanceCallWithInline(
2167 FlowGraph* flow_graph,
2168 ForwardInstructionIterator* iterator,
2169 InstanceCallInstr* call,
2170 SpeculativeInliningPolicy* policy) {
2171 const CallTargets& targets = call->Targets();
2172 ASSERT(targets.IsMonomorphic());
2173 const intptr_t receiver_cid = targets.MonomorphicReceiverCid();
2174 const Function&
target = targets.FirstTarget();
2175 const auto exactness = targets.MonomorphicExactness();
2176 ExactnessInfo exactness_info{exactness.IsExact(),
false};
2178 FunctionEntryInstr* entry =
nullptr;
2179 Instruction* last =
nullptr;
2180 Definition*
result =
nullptr;
2181 if (CallSpecializer::TryInlineRecognizedMethod(
2183 call->Receiver()->definition(),
call->source(),
call->ic_data(),
2184 nullptr, &entry, &last, &
result, policy,
2189 (
target.recognized_kind() == MethodRecognizer::kObjectConstructor));
2194 if (
target.is_polymorphic_target() ||
2195 (
target.recognized_kind() == MethodRecognizer::kStringBaseCodeUnitAt)) {
2205 call->Receiver()->definition(), targets,
call->deopt_id(),
2212 Instruction* check_null =
new (
Z) CheckNullInstr(
2213 call->Receiver()->CopyWithType(
Z),
call->function_name(),
2223 if (exactness_info.emit_exactness_guard && exactness.IsTriviallyExact()) {
2230 if (
call->HasUses()) {
2236 if (entry->next() !=
nullptr) {
2237 call->previous()->LinkTo(entry->next());
2239 entry->UnuseAllInputs();
2240 if (last !=
nullptr) {
2241 ASSERT(
call->GetBlock() == last->GetBlock());
2245 ASSERT(iterator->Current() == call);
2246 iterator->RemoveCurrentFromGraph();
2247 call->set_previous(
nullptr);
2248 call->set_next(
nullptr);
2254bool CallSpecializer::TryReplaceStaticCallWithInline(
2255 FlowGraph* flow_graph,
2256 ForwardInstructionIterator* iterator,
2257 StaticCallInstr* call,
2258 SpeculativeInliningPolicy* policy) {
2259 FunctionEntryInstr* entry =
nullptr;
2260 Instruction* last =
nullptr;
2261 Definition*
result =
nullptr;
2262 Definition* receiver =
nullptr;
2264 if (!
call->function().is_static()) {
2265 receiver =
call->Receiver()->definition();
2266 receiver_cid =
call->Receiver()->Type()->ToCid();
2268 if (CallSpecializer::TryInlineRecognizedMethod(
2270 call->source(),
call->ic_data(),
nullptr, &entry,
2271 &last, &
result, policy)) {
2275 (
call->function().recognized_kind() ==
2276 MethodRecognizer::kObjectConstructor));
2279 if (
call->HasUses()) {
2285 if (entry !=
nullptr) {
2286 if (entry->next() !=
nullptr) {
2287 call->previous()->LinkTo(entry->next());
2289 entry->UnuseAllInputs();
2290 if (last !=
nullptr) {
2291 BlockEntryInstr*
link =
call->GetBlock();
2292 BlockEntryInstr*
exit = last->GetBlock();
2297 for (intptr_t i = 0, n =
link->dominated_blocks().length(); i < n;
2299 exit->AddDominatedBlock(
link->dominated_blocks()[i]);
2301 link->ClearDominatedBlocks();
2302 for (intptr_t i = 0, n = entry->dominated_blocks().length(); i < n;
2304 link->AddDominatedBlock(entry->dominated_blocks()[i]);
2306 Instruction* scan =
exit;
2307 while (scan->next() !=
nullptr) {
2308 scan = scan->next();
2318 if (iterator !=
nullptr) {
2319 ASSERT(iterator->Current() == call);
2320 iterator->RemoveCurrentFromGraph();
2322 call->RemoveFromGraph();
2330 if (!definition->IsConstant())
return false;
2331 ConstantInstr* constant_instruction = definition->AsConstant();
2332 const Object& constant_mask = constant_instruction->
value();
2333 if (!constant_mask.IsSmi())
return false;
2334 const intptr_t mask = Smi::Cast(constant_mask).Value();
2335 if ((mask < 0) || (mask > 255)) {
2350 : flow_graph_(flow_graph),
2352 graph_entry_(graph_entry),
2356 *entry_ =
new (zone())
2365 case MethodRecognizer::kInt32x4FromInts:
2366 UnboxScalar(0, kUnboxedInt32, 4);
2367 UnboxScalar(1, kUnboxedInt32, 4);
2368 UnboxScalar(2, kUnboxedInt32, 4);
2369 UnboxScalar(3, kUnboxedInt32, 4);
2371 BoxVector(kUnboxedInt32, 4);
2373 case MethodRecognizer::kInt32x4FromBools:
2379 BoxVector(kUnboxedInt32, 4);
2381 case MethodRecognizer::kInt32x4GetFlagX:
2382 UnboxVector(0, kUnboxedInt32, kMintCid, 4);
2386 case MethodRecognizer::kInt32x4GetFlagY:
2387 UnboxVector(0, kUnboxedInt32, kMintCid, 4);
2391 case MethodRecognizer::kInt32x4GetFlagZ:
2392 UnboxVector(0, kUnboxedInt32, kMintCid, 4);
2396 case MethodRecognizer::kInt32x4GetFlagW:
2397 UnboxVector(0, kUnboxedInt32, kMintCid, 4);
2401 case MethodRecognizer::kInt32x4WithFlagX:
2402 UnboxVector(0, kUnboxedInt32, kMintCid, 4);
2405 BoxVector(kUnboxedInt32, 4);
2407 case MethodRecognizer::kInt32x4WithFlagY:
2408 UnboxVector(0, kUnboxedInt32, kMintCid, 4);
2411 BoxVector(kUnboxedInt32, 4);
2413 case MethodRecognizer::kInt32x4WithFlagZ:
2414 UnboxVector(0, kUnboxedInt32, kMintCid, 4);
2417 BoxVector(kUnboxedInt32, 4);
2419 case MethodRecognizer::kInt32x4WithFlagW:
2420 UnboxVector(0, kUnboxedInt32, kMintCid, 4);
2423 BoxVector(kUnboxedInt32, 4);
2425 case MethodRecognizer::kInt32x4Shuffle: {
2429 if (!
CheckMask(mask_definition, &mask)) {
2432 UnboxVector(0, kUnboxedInt32, kMintCid, 4);
2434 BoxVector(kUnboxedInt32, 4);
2437 case MethodRecognizer::kInt32x4ShuffleMix: {
2441 if (!
CheckMask(mask_definition, &mask)) {
2444 UnboxVector(0, kUnboxedInt32, kMintCid, 4);
2445 UnboxVector(1, kUnboxedInt32, kMintCid, 4);
2447 BoxVector(kUnboxedInt32, 4);
2450 case MethodRecognizer::kInt32x4GetSignMask:
2451 case MethodRecognizer::kInt32x4Select:
2456 case MethodRecognizer::kFloat32x4Abs:
2457 Float32x4Unary(Token::kABS);
2459 case MethodRecognizer::kFloat32x4Negate:
2460 Float32x4Unary(Token::kNEGATE);
2462 case MethodRecognizer::kFloat32x4Sqrt:
2463 Float32x4Unary(Token::kSQRT);
2465 case MethodRecognizer::kFloat32x4Reciprocal:
2466 Float32x4Unary(Token::kRECIPROCAL);
2468 case MethodRecognizer::kFloat32x4ReciprocalSqrt:
2469 Float32x4Unary(Token::kRECIPROCAL_SQRT);
2471 case MethodRecognizer::kFloat32x4GetSignMask:
2474 case MethodRecognizer::kFloat32x4Equal:
2475 Float32x4Compare(Token::kEQ);
2477 case MethodRecognizer::kFloat32x4GreaterThan:
2478 Float32x4Compare(Token::kGT);
2480 case MethodRecognizer::kFloat32x4GreaterThanOrEqual:
2481 Float32x4Compare(Token::kGTE);
2483 case MethodRecognizer::kFloat32x4LessThan:
2484 Float32x4Compare(Token::kLT);
2486 case MethodRecognizer::kFloat32x4LessThanOrEqual:
2487 Float32x4Compare(Token::kLTE);
2489 case MethodRecognizer::kFloat32x4Add:
2490 Float32x4Binary(Token::kADD);
2492 case MethodRecognizer::kFloat32x4Sub:
2493 Float32x4Binary(Token::kSUB);
2495 case MethodRecognizer::kFloat32x4Mul:
2496 Float32x4Binary(Token::kMUL);
2498 case MethodRecognizer::kFloat32x4Div:
2499 Float32x4Binary(Token::kDIV);
2501 case MethodRecognizer::kFloat32x4Min:
2502 Float32x4Binary(Token::kMIN);
2504 case MethodRecognizer::kFloat32x4Max:
2505 Float32x4Binary(Token::kMAX);
2507 case MethodRecognizer::kFloat32x4Scale:
2508 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
2509 UnboxScalar(1, kUnboxedFloat, 4);
2510 BinaryDoubleOp(Token::kMUL, kUnboxedFloat, 4);
2511 BoxVector(kUnboxedFloat, 4);
2513 case MethodRecognizer::kFloat32x4Splat:
2514 UnboxScalar(0, kUnboxedFloat, 4);
2516 BoxVector(kUnboxedFloat, 4);
2518 case MethodRecognizer::kFloat32x4WithX:
2519 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
2520 UnboxScalar(1, kUnboxedFloat, 4);
2522 BoxVector(kUnboxedFloat, 4);
2524 case MethodRecognizer::kFloat32x4WithY:
2525 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
2526 UnboxScalar(1, kUnboxedFloat, 4);
2528 BoxVector(kUnboxedFloat, 4);
2530 case MethodRecognizer::kFloat32x4WithZ:
2531 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
2532 UnboxScalar(1, kUnboxedFloat, 4);
2534 BoxVector(kUnboxedFloat, 4);
2536 case MethodRecognizer::kFloat32x4WithW:
2537 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
2538 UnboxScalar(1, kUnboxedFloat, 4);
2540 BoxVector(kUnboxedFloat, 4);
2542 case MethodRecognizer::kFloat32x4Zero:
2543 UnboxDoubleZero(kUnboxedFloat, 4);
2544 BoxVector(kUnboxedFloat, 4);
2546 case MethodRecognizer::kFloat32x4FromDoubles:
2547 UnboxScalar(0, kUnboxedFloat, 4);
2548 UnboxScalar(1, kUnboxedFloat, 4);
2549 UnboxScalar(2, kUnboxedFloat, 4);
2550 UnboxScalar(3, kUnboxedFloat, 4);
2552 BoxVector(kUnboxedFloat, 4);
2554 case MethodRecognizer::kFloat32x4GetX:
2555 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
2556 BoxScalar(0, kUnboxedFloat);
2558 case MethodRecognizer::kFloat32x4GetY:
2559 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
2560 BoxScalar(1, kUnboxedFloat);
2562 case MethodRecognizer::kFloat32x4GetZ:
2563 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
2564 BoxScalar(2, kUnboxedFloat);
2566 case MethodRecognizer::kFloat32x4GetW:
2567 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
2568 BoxScalar(3, kUnboxedFloat);
2570 case MethodRecognizer::kFloat32x4Shuffle: {
2574 if (!
CheckMask(mask_definition, &mask)) {
2577 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
2579 BoxVector(kUnboxedFloat, 4);
2582 case MethodRecognizer::kFloat32x4ShuffleMix: {
2586 if (!
CheckMask(mask_definition, &mask)) {
2589 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
2590 UnboxVector(1, kUnboxedFloat, kDoubleCid, 4);
2592 BoxVector(kUnboxedFloat, 4);
2597 case MethodRecognizer::kFloat64x2Abs:
2598 Float64x2Unary(Token::kABS);
2600 case MethodRecognizer::kFloat64x2Negate:
2601 Float64x2Unary(Token::kNEGATE);
2603 case MethodRecognizer::kFloat64x2Sqrt:
2604 Float64x2Unary(Token::kSQRT);
2606 case MethodRecognizer::kFloat64x2Add:
2607 Float64x2Binary(Token::kADD);
2609 case MethodRecognizer::kFloat64x2Sub:
2610 Float64x2Binary(Token::kSUB);
2612 case MethodRecognizer::kFloat64x2Mul:
2613 Float64x2Binary(Token::kMUL);
2615 case MethodRecognizer::kFloat64x2Div:
2616 Float64x2Binary(Token::kDIV);
2618 case MethodRecognizer::kFloat64x2Min:
2619 Float64x2Binary(Token::kMIN);
2621 case MethodRecognizer::kFloat64x2Max:
2622 Float64x2Binary(Token::kMAX);
2624 case MethodRecognizer::kFloat64x2Scale:
2625 UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
2626 UnboxScalar(1, kUnboxedDouble, 2);
2627 BinaryDoubleOp(Token::kMUL, kUnboxedDouble, 2);
2628 BoxVector(kUnboxedDouble, 2);
2630 case MethodRecognizer::kFloat64x2Splat:
2631 UnboxScalar(0, kUnboxedDouble, 2);
2633 BoxVector(kUnboxedDouble, 2);
2635 case MethodRecognizer::kFloat64x2WithX:
2636 UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
2637 UnboxScalar(1, kUnboxedDouble, 2);
2639 BoxVector(kUnboxedDouble, 2);
2641 case MethodRecognizer::kFloat64x2WithY:
2642 UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
2643 UnboxScalar(1, kUnboxedDouble, 2);
2645 BoxVector(kUnboxedDouble, 2);
2647 case MethodRecognizer::kFloat64x2Zero:
2648 UnboxDoubleZero(kUnboxedDouble, 2);
2649 BoxVector(kUnboxedDouble, 2);
2651 case MethodRecognizer::kFloat64x2FromDoubles:
2652 UnboxScalar(0, kUnboxedDouble, 2);
2653 UnboxScalar(1, kUnboxedDouble, 2);
2655 BoxVector(kUnboxedDouble, 2);
2657 case MethodRecognizer::kFloat64x2GetX:
2658 UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
2659 BoxScalar(0, kUnboxedDouble);
2661 case MethodRecognizer::kFloat64x2GetY:
2662 UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
2663 BoxScalar(1, kUnboxedDouble);
2667 case MethodRecognizer::kFloat32x4ToFloat64x2: {
2668 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4, 1);
2669 Float32x4ToFloat64x2();
2670 BoxVector(kUnboxedDouble, 2);
2673 case MethodRecognizer::kFloat64x2ToFloat32x4: {
2674 UnboxVector(0, kUnboxedDouble, kDoubleCid, 2, 1);
2675 Float64x2ToFloat32x4();
2676 BoxVector(kUnboxedFloat, 4);
2679 case MethodRecognizer::kInt32x4ToFloat32x4:
2680 UnboxVector(0, kUnboxedInt32, kMintCid, 4, 1);
2681 Int32x4ToFloat32x4();
2682 BoxVector(kUnboxedFloat, 4);
2684 case MethodRecognizer::kFloat32x4ToInt32x4:
2685 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4, 1);
2686 Float32x4ToInt32x4();
2687 BoxVector(kUnboxedInt32, 4);
2696 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
2697 UnaryDoubleOp(op, kUnboxedFloat, 4);
2698 BoxVector(kUnboxedFloat, 4);
2701 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
2702 UnboxVector(1, kUnboxedFloat, kDoubleCid, 4);
2703 BinaryDoubleOp(op, kUnboxedFloat, 4);
2704 BoxVector(kUnboxedFloat, 4);
2707 UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
2708 UnboxVector(1, kUnboxedFloat, kDoubleCid, 4);
2710 BoxVector(kUnboxedInt32, 4);
2713 UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
2714 UnaryDoubleOp(op, kUnboxedDouble, 2);
2715 BoxVector(kUnboxedDouble, 2);
2718 UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
2719 UnboxVector(1, kUnboxedDouble, kDoubleCid, 2);
2720 BinaryDoubleOp(op, kUnboxedDouble, 2);
2721 BoxVector(kUnboxedDouble, 2);
2724 void UnboxVector(intptr_t i,
2728 intptr_t type_args = 0) {
2729 Definition* arg = call_->
ArgumentAt(i + type_args);
2735 arg = AddDefinition(
new (zone()) CheckNullInstr(
2736 new (zone())
Value(arg), Symbols::SecondArg(), call_->
deopt_id(),
2739 for (intptr_t lane = 0; lane < n; lane++) {
2740 in_[i][lane] = AddDefinition(
2741 new (zone()) UnboxLaneInstr(
new (zone())
Value(arg), lane, rep,
cid));
2745 void UnboxScalar(intptr_t i,
2748 intptr_t type_args = 0) {
2749 Definition* arg = call_->
ArgumentAt(i + type_args);
2755 arg = AddDefinition(
new (zone()) CheckNullInstr(
2756 new (zone())
Value(arg), Symbols::SecondArg(), call_->
deopt_id(),
2759 Definition* unbox = AddDefinition(
2762 for (intptr_t lane = 0; lane < n; lane++) {
2763 in_[i][lane] = unbox;
2767 void UnboxBool(intptr_t i, intptr_t n) {
2768 Definition* unbox = AddDefinition(
new (zone()) BoolToIntInstr(
2770 for (intptr_t lane = 0; lane < n; lane++) {
2771 in_[i][lane] = unbox;
2778 for (intptr_t lane = 0; lane < n; lane++) {
2784 for (intptr_t lane = 0; lane < n; lane++) {
2785 op_[lane] = AddDefinition(
new (zone()) UnaryDoubleOpInstr(
2792 for (intptr_t lane = 0; lane < n; lane++) {
2793 op_[lane] = AddDefinition(
new (zone()) BinaryDoubleOpInstr(
2794 op,
new (zone())
Value(in_[0][lane]),
2801 for (intptr_t lane = 0; lane < 4; lane++) {
2802 op_[lane] = AddDefinition(
2803 new (zone()) FloatCompareInstr(op,
new (zone())
Value(in_[0][lane]),
2804 new (zone())
Value(in_[1][lane])));
2808 void With(intptr_t i) {
2809 for (intptr_t lane = 0; lane < 4; lane++) {
2810 op_[lane] = in_[0][lane];
2814 void Splat(intptr_t n) {
2815 for (intptr_t lane = 0; lane < n; lane++) {
2816 op_[lane] = in_[0][0];
2819 void Gather(intptr_t n) {
2820 for (intptr_t lane = 0; lane < n; lane++) {
2821 op_[lane] = in_[lane][0];
2824 void Shuffle(intptr_t mask) {
2825 op_[0] = in_[0][(mask >> 0) & 3];
2826 op_[1] = in_[0][(mask >> 2) & 3];
2827 op_[2] = in_[0][(mask >> 4) & 3];
2828 op_[3] = in_[0][(mask >> 6) & 3];
2830 void ShuffleMix(intptr_t mask) {
2831 op_[0] = in_[0][(mask >> 0) & 3];
2832 op_[1] = in_[0][(mask >> 2) & 3];
2833 op_[2] = in_[1][(mask >> 4) & 3];
2834 op_[3] = in_[1][(mask >> 6) & 3];
2836 void Float32x4ToFloat64x2() {
2837 for (intptr_t lane = 0; lane < 2; lane++) {
2838 op_[lane] = AddDefinition(
new (zone()) FloatToDoubleInstr(
2842 void Float64x2ToFloat32x4() {
2843 for (intptr_t lane = 0; lane < 2; lane++) {
2844 op_[lane] = AddDefinition(
new (zone()) DoubleToFloatInstr(
2852 void Int32x4ToFloat32x4() {
2853 for (intptr_t lane = 0; lane < 4; lane++) {
2854 op_[lane] = AddDefinition(
new (zone()) BitCastInstr(
2855 kUnboxedInt32, kUnboxedFloat,
new (zone())
Value(in_[0][lane])));
2858 void Float32x4ToInt32x4() {
2859 for (intptr_t lane = 0; lane < 4; lane++) {
2860 op_[lane] = AddDefinition(
new (zone()) BitCastInstr(
2861 kUnboxedFloat, kUnboxedInt32,
new (zone())
Value(in_[0][lane])));
2865 for (intptr_t lane = 0; lane < 4; lane++) {
2866 op_[lane] = AddDefinition(
2867 new (zone()) IntToBoolInstr(
new (zone())
Value(in_[0][lane])));
2874 box =
new (zone()) BoxLanesInstr(rep,
new (zone())
Value(op_[0]),
2875 new (zone())
Value(op_[1]));
2878 box =
new (zone()) BoxLanesInstr(
2879 rep,
new (zone())
Value(op_[0]),
new (zone())
Value(op_[1]),
2880 new (zone())
Value(op_[2]),
new (zone())
Value(op_[3]));
2882 Done(AddDefinition(box));
2887 Done(AddDefinition(box));
2890 void Return(intptr_t lane) { Done(op_[lane]); }
2892 void Done(Definition*
result) {
2896 (*entry_)->InheritDeoptTarget(zone(), call_);
2900 Definition* AddDefinition(Definition* def) {
2906 Zone* zone() {
return flow_graph_->
zone(); }
2908 FlowGraph* flow_graph_;
2910 GraphEntryInstr* graph_entry_;
2911 FunctionEntryInstr** entry_;
2912 Instruction** last_;
2913 Definition** result_;
2916 Definition* in_[4][4];
2922 bool is_dynamic_call,
2930 if (is_dynamic_call && call->ArgumentCount() > 1) {
2944 if (!FLAG_enable_simd_inline) {
2949#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
2962 case MethodRecognizer::kInt32x4Shuffle:
2963 case MethodRecognizer::kInt32x4ShuffleMix:
2964 case MethodRecognizer::kFloat32x4Shuffle:
2965 case MethodRecognizer::kFloat32x4ShuffleMix: {
2966 Definition* mask_definition = call->ArgumentAt(call->ArgumentCount() - 1);
2968 if (!
CheckMask(mask_definition, &mask)) {
2975 case MethodRecognizer::kFloat32x4WithX:
2976 case MethodRecognizer::kFloat32x4WithY:
2977 case MethodRecognizer::kFloat32x4WithZ:
2978 case MethodRecognizer::kFloat32x4WithW:
2979 case MethodRecognizer::kFloat32x4Scale: {
2992 case MethodRecognizer::kFloat32x4Zero:
2993 case MethodRecognizer::kFloat32x4ToFloat64x2:
2994 case MethodRecognizer::kFloat64x2ToFloat32x4:
2995 case MethodRecognizer::kFloat32x4ToInt32x4:
2996 case MethodRecognizer::kInt32x4ToFloat32x4:
2997 case MethodRecognizer::kFloat64x2Zero:
3000 case MethodRecognizer::kFloat32x4Mul:
3001 case MethodRecognizer::kFloat32x4Div:
3002 case MethodRecognizer::kFloat32x4Add:
3003 case MethodRecognizer::kFloat32x4Sub:
3004 case MethodRecognizer::kFloat64x2Mul:
3005 case MethodRecognizer::kFloat64x2Div:
3006 case MethodRecognizer::kFloat64x2Add:
3007 case MethodRecognizer::kFloat64x2Sub:
3016 call->deopt_id(), call->source());
3019 new (
Z)
Value(call->ArgumentAt(1)), Symbols::SecondArg(),
3022 (*last)->SetInputAt(0,
new (
Z)
Value(check1));
3023 (*last)->SetInputAt(1,
new (
Z)
Value(check2));
3036 (*entry)->InheritDeoptTarget(
Z, call);
3038 cursor, *last, call->deopt_id() !=
DeoptId::kNone ? call->env() :
nullptr,
3040 *
result = (*last)->AsDefinition();
3066 Value*
x = call->ArgumentValueAt(0);
3067 Value*
y = call->ArgumentValueAt(1);
3069 const intptr_t small_exponent = 5;
3073 *
result = (*last)->AsDefinition();
3075 }
else if (val == 1) {
3076 *last =
x->definition();
3077 *
result = (*last)->AsDefinition();
3079 }
else if (1 < val && val <= small_exponent) {
3084 (*entry)->InheritDeoptTarget(
Z, call);
3087 InlineMul(flow_graph, *entry, x_def, x_def)->AsDefinition();
3095 *
result = (*last)->AsDefinition();
3099 *
result = (*last)->AsDefinition();
3104 *
result = (*last)->AsDefinition();
3112 *last =
x->definition();
3120bool CallSpecializer::TryInlineRecognizedMethod(
3121 FlowGraph* flow_graph,
3122 intptr_t receiver_cid,
3125 Definition* receiver,
3126 const InstructionSource&
source,
3127 const ICData* ic_data,
3128 GraphEntryInstr* graph_entry,
3129 FunctionEntryInstr** entry,
3132 SpeculativeInliningPolicy* policy,
3133 CallSpecializer::ExactnessInfo* exactness) {
3136 if (receiver_cid == kSentinelCid) {
3143 const bool can_speculate =
policy->IsAllowedForInlining(
call->deopt_id());
3149 case MethodRecognizer::kTypedDataIndexCheck:
3151 entry, last,
result, Symbols::Index());
3152 case MethodRecognizer::kByteDataByteOffsetCheck:
3155 Symbols::byteOffset());
3157 case MethodRecognizer::kObjectArrayGetIndexed:
3158 case MethodRecognizer::kGrowableArrayGetIndexed:
3159 case MethodRecognizer::kInt8ArrayGetIndexed:
3160 case MethodRecognizer::kUint8ArrayGetIndexed:
3161 case MethodRecognizer::kUint8ClampedArrayGetIndexed:
3162 case MethodRecognizer::kExternalUint8ArrayGetIndexed:
3163 case MethodRecognizer::kExternalUint8ClampedArrayGetIndexed:
3164 case MethodRecognizer::kInt16ArrayGetIndexed:
3165 case MethodRecognizer::kUint16ArrayGetIndexed:
3167 call, receiver, graph_entry, entry, last,
result);
3168 case MethodRecognizer::kFloat32ArrayGetIndexed:
3169 case MethodRecognizer::kFloat64ArrayGetIndexed:
3174 call, receiver, graph_entry, entry, last,
result);
3175 case MethodRecognizer::kFloat32x4ArrayGetIndexed:
3176 case MethodRecognizer::kFloat64x2ArrayGetIndexed:
3181 call, receiver, graph_entry, entry, last,
result);
3182 case MethodRecognizer::kInt32ArrayGetIndexed:
3183 case MethodRecognizer::kUint32ArrayGetIndexed:
3185 call, receiver, graph_entry, entry, last,
result);
3186 case MethodRecognizer::kInt64ArrayGetIndexed:
3187 case MethodRecognizer::kUint64ArrayGetIndexed:
3189 call, receiver, graph_entry, entry, last,
result);
3190 case MethodRecognizer::kClassIDgetID:
3198 if (!can_speculate) {
3203 case MethodRecognizer::kUint8ClampedArraySetIndexed:
3204 case MethodRecognizer::kExternalUint8ClampedArraySetIndexed:
3210 case MethodRecognizer::kObjectArraySetIndexed:
3211 case MethodRecognizer::kGrowableArraySetIndexed:
3212 case MethodRecognizer::kObjectArraySetIndexedUnchecked:
3213 case MethodRecognizer::kGrowableArraySetIndexedUnchecked:
3214 case MethodRecognizer::kInt8ArraySetIndexed:
3215 case MethodRecognizer::kUint8ArraySetIndexed:
3216 case MethodRecognizer::kExternalUint8ArraySetIndexed:
3217 case MethodRecognizer::kInt16ArraySetIndexed:
3218 case MethodRecognizer::kUint16ArraySetIndexed:
3219 case MethodRecognizer::kInt32ArraySetIndexed:
3220 case MethodRecognizer::kUint32ArraySetIndexed:
3221 case MethodRecognizer::kInt64ArraySetIndexed:
3222 case MethodRecognizer::kUint64ArraySetIndexed:
3224 exactness, graph_entry, entry, last,
result);
3226 case MethodRecognizer::kFloat32ArraySetIndexed:
3227 case MethodRecognizer::kFloat64ArraySetIndexed: {
3232 exactness, graph_entry, entry, last,
result);
3234 case MethodRecognizer::kFloat32x4ArraySetIndexed: {
3239 exactness, graph_entry, entry, last,
result);
3241 case MethodRecognizer::kFloat64x2ArraySetIndexed: {
3246 exactness, graph_entry, entry, last,
result);
3248 case MethodRecognizer::kStringBaseCodeUnitAt:
3250 receiver_cid, graph_entry, entry, last,
3252 case MethodRecognizer::kStringBaseCharAt:
3254 graph_entry, entry, last,
result);
3255 case MethodRecognizer::kDoubleAdd:
3257 graph_entry, entry, last,
result);
3258 case MethodRecognizer::kDoubleSub:
3260 graph_entry, entry, last,
result);
3261 case MethodRecognizer::kDoubleMul:
3263 graph_entry, entry, last,
result);
3264 case MethodRecognizer::kDoubleDiv:
3266 graph_entry, entry, last,
result);
3267 case MethodRecognizer::kDouble_getIsNaN:
3268 case MethodRecognizer::kDouble_getIsInfinite:
3269 case MethodRecognizer::kDouble_getIsNegative:
3272 case MethodRecognizer::kGrowableArraySetData:
3273 ASSERT((receiver_cid == kGrowableObjectArrayCid) ||
3277 receiver, graph_entry, entry, last,
result);
3278 case MethodRecognizer::kGrowableArraySetLength:
3279 ASSERT((receiver_cid == kGrowableObjectArrayCid) ||
3283 receiver, graph_entry, entry, last,
result);
3285 case MethodRecognizer::kFloat32x4Abs:
3286 case MethodRecognizer::kFloat32x4Clamp:
3287 case MethodRecognizer::kFloat32x4FromDoubles:
3288 case MethodRecognizer::kFloat32x4Equal:
3289 case MethodRecognizer::kFloat32x4GetSignMask:
3290 case MethodRecognizer::kFloat32x4GreaterThan:
3291 case MethodRecognizer::kFloat32x4GreaterThanOrEqual:
3292 case MethodRecognizer::kFloat32x4LessThan:
3293 case MethodRecognizer::kFloat32x4LessThanOrEqual:
3294 case MethodRecognizer::kFloat32x4Max:
3295 case MethodRecognizer::kFloat32x4Min:
3296 case MethodRecognizer::kFloat32x4Negate:
3297 case MethodRecognizer::kFloat32x4NotEqual:
3298 case MethodRecognizer::kFloat32x4Reciprocal:
3299 case MethodRecognizer::kFloat32x4ReciprocalSqrt:
3300 case MethodRecognizer::kFloat32x4Scale:
3301 case MethodRecognizer::kFloat32x4GetW:
3302 case MethodRecognizer::kFloat32x4GetX:
3303 case MethodRecognizer::kFloat32x4GetY:
3304 case MethodRecognizer::kFloat32x4GetZ:
3305 case MethodRecognizer::kFloat32x4Splat:
3306 case MethodRecognizer::kFloat32x4Sqrt:
3307 case MethodRecognizer::kFloat32x4ToFloat64x2:
3308 case MethodRecognizer::kFloat32x4ToInt32x4:
3309 case MethodRecognizer::kFloat32x4WithW:
3310 case MethodRecognizer::kFloat32x4WithX:
3311 case MethodRecognizer::kFloat32x4WithY:
3312 case MethodRecognizer::kFloat32x4WithZ:
3313 case MethodRecognizer::kFloat32x4Zero:
3314 case MethodRecognizer::kFloat64x2Abs:
3315 case MethodRecognizer::kFloat64x2Clamp:
3316 case MethodRecognizer::kFloat64x2FromDoubles:
3317 case MethodRecognizer::kFloat64x2GetSignMask:
3318 case MethodRecognizer::kFloat64x2GetX:
3319 case MethodRecognizer::kFloat64x2GetY:
3320 case MethodRecognizer::kFloat64x2Max:
3321 case MethodRecognizer::kFloat64x2Min:
3322 case MethodRecognizer::kFloat64x2Negate:
3323 case MethodRecognizer::kFloat64x2Scale:
3324 case MethodRecognizer::kFloat64x2Splat:
3325 case MethodRecognizer::kFloat64x2Sqrt:
3326 case MethodRecognizer::kFloat64x2ToFloat32x4:
3327 case MethodRecognizer::kFloat64x2WithX:
3328 case MethodRecognizer::kFloat64x2WithY:
3329 case MethodRecognizer::kFloat64x2Zero:
3330 case MethodRecognizer::kInt32x4FromBools:
3331 case MethodRecognizer::kInt32x4FromInts:
3332 case MethodRecognizer::kInt32x4GetFlagW:
3333 case MethodRecognizer::kInt32x4GetFlagX:
3334 case MethodRecognizer::kInt32x4GetFlagY:
3335 case MethodRecognizer::kInt32x4GetFlagZ:
3336 case MethodRecognizer::kInt32x4GetSignMask:
3337 case MethodRecognizer::kInt32x4Select:
3338 case MethodRecognizer::kInt32x4ToFloat32x4:
3339 case MethodRecognizer::kInt32x4WithFlagW:
3340 case MethodRecognizer::kInt32x4WithFlagX:
3341 case MethodRecognizer::kInt32x4WithFlagY:
3342 case MethodRecognizer::kInt32x4WithFlagZ:
3343 case MethodRecognizer::kFloat32x4ShuffleMix:
3344 case MethodRecognizer::kInt32x4ShuffleMix:
3345 case MethodRecognizer::kFloat32x4Shuffle:
3346 case MethodRecognizer::kInt32x4Shuffle:
3347 case MethodRecognizer::kFloat32x4Mul:
3348 case MethodRecognizer::kFloat32x4Div:
3349 case MethodRecognizer::kFloat32x4Add:
3350 case MethodRecognizer::kFloat32x4Sub:
3351 case MethodRecognizer::kFloat64x2Mul:
3352 case MethodRecognizer::kFloat64x2Div:
3353 case MethodRecognizer::kFloat64x2Add:
3354 case MethodRecognizer::kFloat64x2Sub:
3356 graph_entry, entry, last,
result);
3358 case MethodRecognizer::kMathIntPow:
3362 case MethodRecognizer::kObjectConstructor: {
3366 (*entry)->InheritDeoptTarget(
Z, call);
3374 case MethodRecognizer::kObjectArrayAllocate: {
3383 (*entry)->InheritDeoptTarget(
Z, call);
3384 *last =
new (
Z) CreateArrayInstr(
call->source(),
type, num_elements,
3390 *
result = (*last)->AsDefinition();
3397 case MethodRecognizer::kObjectRuntimeType: {
3403 }
else if (receiver_cid == kDoubleCid) {
3409 }
else if ((receiver_cid != kClosureCid) &&
3410 (receiver_cid != kRecordCid)) {
3413 if (!cls.IsGeneric()) {
3414 type = cls.DeclarationType();
3418 if (!
type.IsNull()) {
3422 (*entry)->InheritDeoptTarget(
Z, call);
3426 RedefinitionInstr* redef =
3427 new (
Z) RedefinitionInstr(
new (
Z)
Value(ctype));
3438 case MethodRecognizer::kWriteIntoOneByteString:
3439 case MethodRecognizer::kWriteIntoTwoByteString: {
3446 Definition* str =
call->ArgumentAt(0);
3447 Definition* index =
call->ArgumentAt(1);
3448 Definition*
value =
call->ArgumentAt(2);
3450 const bool is_onebyte = kind == MethodRecognizer::kWriteIntoOneByteString;
3451 const intptr_t index_scale = is_onebyte ? 1 : 2;
3452 const intptr_t
cid = is_onebyte ? kOneByteStringCid : kTwoByteStringCid;
3461 *last =
new (
Z) StoreIndexedInstr(
static float prev(float f)
#define check(reporter, ref, unref, make, kill)
static bool left(const SkPoint &p0, const SkPoint &p1)
static bool right(const SkPoint &p0, const SkPoint &p1)
static const char kValue[]
#define RELEASE_ASSERT(cond)
#define INIT_HANDLE(iface, member_name, type, cid)
#define TRY_INLINE(iface, member_name, 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 SupportsUnboxedDoubles()
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
virtual intptr_t ArgumentCount() const
Definition * ArgumentAt(intptr_t index) const
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 DartTypeType()
static TypePtr StringType()
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
#define COMPILER_TIMINGS_TIMER_SCOPE(thread, timer_id)
#define THR_Print(format,...)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
#define DECLARE_FLAG(type, name)
Dart_NativeFunction function
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 bool CanUnboxDouble()
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)
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)