6#if defined(TARGET_ARCH_ARM64)
8#define SHOULD_NOT_INCLUDE_RUNTIME
31static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) {
32 __ ldr(
R0, Address(
SP, +0 * target::kWordSize));
33 __ ldr(
R1, Address(
SP, +1 * target::kWordSize));
35 __ BranchIfNotSmi(
TMP, not_smi);
38void AsmIntrinsifier::Integer_shl(Assembler* assembler, Label* normal_ir_body) {
46 TestBothArgumentsSmis(assembler, normal_ir_body);
49 __ b(normal_ir_body,
CS);
58 __ b(normal_ir_body,
NE);
62 __ Bind(normal_ir_body);
66 Label* normal_ir_body,
69 TestBothArgumentsSmis(assembler, normal_ir_body);
71 __ CompareObjectRegisters(
R1,
R0);
76 __ Bind(normal_ir_body);
79void AsmIntrinsifier::Integer_lessThan(Assembler* assembler,
80 Label* normal_ir_body) {
84void AsmIntrinsifier::Integer_greaterThan(Assembler* assembler,
85 Label* normal_ir_body) {
89void AsmIntrinsifier::Integer_lessEqualThan(Assembler* assembler,
90 Label* normal_ir_body) {
94void AsmIntrinsifier::Integer_greaterEqualThan(Assembler* assembler,
95 Label* normal_ir_body) {
101void AsmIntrinsifier::Integer_equalToInteger(Assembler* assembler,
102 Label* normal_ir_body) {
103 Label true_label, check_for_mint;
105 __ ldr(
R0, Address(
SP, 0 * target::kWordSize));
106 __ ldr(
R1, Address(
SP, 1 * target::kWordSize));
107 __ CompareObjectRegisters(
R0,
R1);
108 __ b(&true_label,
EQ);
111 __ BranchIfNotSmi(
R2, &check_for_mint);
117 __ Bind(&true_label);
122 Label receiver_not_smi;
123 __ Bind(&check_for_mint);
125 __ BranchIfNotSmi(
R1, &receiver_not_smi);
131 __ CompareClassId(
R0, kDoubleCid);
132 __ b(normal_ir_body,
EQ);
137 __ Bind(&receiver_not_smi);
140 __ CompareClassId(
R1, kMintCid);
141 __ b(normal_ir_body,
NE);
143 __ BranchIfNotSmi(
R0, normal_ir_body);
148 __ Bind(normal_ir_body);
151void AsmIntrinsifier::Integer_equal(Assembler* assembler,
152 Label* normal_ir_body) {
153 Integer_equalToInteger(assembler, normal_ir_body);
156void AsmIntrinsifier::Smi_bitLength(Assembler* assembler,
157 Label* normal_ir_body) {
158 __ ldr(
R0, Address(
SP, 0 * target::kWordSize));
161#if !defined(DART_COMPRESSED_POINTERS)
164 __ LoadImmediate(
R1, 64);
168 __ LoadImmediate(
R1, 32);
175void AsmIntrinsifier::Bigint_lsh(Assembler* assembler, Label* normal_ir_body) {
181#if defined(DART_COMPRESSED_POINTERS)
184 __ add(
R2,
R2, Operand(2));
185 __ AsrImmediate(
R2,
R2, 2);
188#if defined(DART_COMPRESSED_POINTERS)
193 __ AsrImmediate(
R0,
R5, 6);
206 __ AndImmediate(
R3,
R5, 63);
208 __ LoadImmediate(
R2, 64);
225void AsmIntrinsifier::Bigint_rsh(Assembler* assembler, Label* normal_ir_body) {
231#if defined(DART_COMPRESSED_POINTERS)
234 __ add(
R2,
R2, Operand(2));
235 __ AsrImmediate(
R2,
R2, 2);
238#if defined(DART_COMPRESSED_POINTERS)
243 __ AsrImmediate(
R0,
R5, 6);
250 __ add(
R0,
R0, Operand(1));
254 __ AndImmediate(
R3,
R5, 63);
256 __ LoadImmediate(
R2, 64);
270 __ Bind(&loop_entry);
273 __ str(
R1, Address(
R8, 0));
278void AsmIntrinsifier::Bigint_absAdd(Assembler* assembler,
279 Label* normal_ir_body) {
286#if defined(DART_COMPRESSED_POINTERS)
289 __ add(
R2,
R2, Operand(2));
296#if defined(DART_COMPRESSED_POINTERS)
299 __ add(
R4,
R4, Operand(2));
305 __ ldr(
R6, Address(
SP, 0 * target::kWordSize));
315 __ adds(
R0,
R0, Operand(0));
324 __ cbnz(&add_loop,
R9);
328 __ cbz(&last_carry,
R9);
331 __ Bind(&carry_loop);
337 __ cbnz(&carry_loop,
R9);
339 __ Bind(&last_carry);
342 __ LoadImmediate(
R0, 1);
343 __ str(
R0, Address(
R6, 0));
350void AsmIntrinsifier::Bigint_absSub(Assembler* assembler,
351 Label* normal_ir_body) {
358#if defined(DART_COMPRESSED_POINTERS)
361 __ add(
R2,
R2, Operand(2));
368#if defined(DART_COMPRESSED_POINTERS)
371 __ add(
R4,
R4, Operand(2));
377 __ ldr(
R6, Address(
SP, 0 * target::kWordSize));
387 __ subs(
R0,
R0, Operand(0));
396 __ cbnz(&sub_loop,
R9);
403 __ Bind(&carry_loop);
409 __ cbnz(&carry_loop,
R9);
416void AsmIntrinsifier::Bigint_mulAdd(Assembler* assembler,
417 Label* normal_ir_body) {
450#if defined(DART_COMPRESSED_POINTERS)
454 __ ldr(
R3, FieldAddress(
R1, target::TypedData::payload_offset()));
459 __ ldr(
R6, Address(
SP, 0 * target::kWordSize));
460#if defined(DART_COMPRESSED_POINTERS)
463 __ add(
R6,
R6, Operand(2));
470#if defined(DART_COMPRESSED_POINTERS)
479#if defined(DART_COMPRESSED_POINTERS)
489 __ Bind(&muladd_loop);
501 __ ldr(
R0, Address(
R5, 0));
515 __ subs(
R6,
R6, Operand(1));
516 __ b(&muladd_loop,
NE);
522 __ ldr(
R0, Address(
R5, 0));
527 Label propagate_carry_loop;
528 __ Bind(&propagate_carry_loop);
529 __ ldr(
R0, Address(
R5, 0));
530 __ adds(
R0,
R0, Operand(1));
532 __ b(&propagate_carry_loop,
CS);
539void AsmIntrinsifier::Bigint_sqrAdd(Assembler* assembler,
540 Label* normal_ir_body) {
570#if defined(DART_COMPRESSED_POINTERS)
583 __ ldr(
R1, Address(
SP, 1 * target::kWordSize));
588 __ ldr(
R0, Address(
R5, 0));
599 __ ldr(
R0, Address(
SP, 0 * target::kWordSize));
600#if defined(DART_COMPRESSED_POINTERS)
604 __ add(
R8,
R8, Operand(2));
605 __ movn(
R0, Immediate(1), 0);
631 __ ldr(
R7, Address(
R5, 0));
640 __ subs(
R8,
R8, Operand(1));
645 __ ldr(
R0, Address(
R5, 0));
660void AsmIntrinsifier::Bigint_estimateQuotientDigit(Assembler* assembler,
661 Label* normal_ir_body) {
707 __ ldr(
R4, Address(
SP, 2 * target::kWordSize));
710 __ ldr(
R3, FieldAddress(
R4, target::TypedData::payload_offset()));
715#if defined(DART_COMPRESSED_POINTERS)
719 __ ldr(
R2, FieldAddress(
R1, target::TypedData::payload_offset() -
723 __ movn(
R0, Immediate(0), 0);
728 __ b(&return_qd,
EQ);
731 __ ldr(
R1, FieldAddress(
R1, target::TypedData::payload_offset() -
752 Label qh_adj_loop, qh_adj, qh_ok;
753 __ Bind(&qh_adj_loop);
770 __ sub(
R6,
R6, Operand(1));
807 Label ql_adj_loop, ql_adj, ql_ok;
808 __ Bind(&ql_adj_loop);
825 __ sub(
R6,
R6, Operand(1));
836 __ str(
R0, FieldAddress(
R4, target::TypedData::payload_offset() +
843void AsmIntrinsifier::Montgomery_mulMod(Assembler* assembler,
844 Label* normal_ir_body) {
855 __ ldr(
R4, Address(
SP, 2 * target::kWordSize));
858 __ ldr(
R3, FieldAddress(
R4, target::TypedData::payload_offset() +
864#if defined(DART_COMPRESSED_POINTERS)
868 __ ldr(
R2, FieldAddress(
R1, target::TypedData::payload_offset()));
874 __ str(
R0, FieldAddress(
R4, target::TypedData::payload_offset() +
884static void TestLastArgumentIsDouble(Assembler* assembler,
886 Label* not_double_smi) {
887 __ ldr(
R0, Address(
SP, 0 * target::kWordSize));
888 __ BranchIfSmi(
R0, is_smi);
889 __ CompareClassId(
R0, kDoubleCid);
890 __ b(not_double_smi,
NE);
898static void CompareDoubles(Assembler* assembler,
899 Label* normal_ir_body,
901 Label is_smi, double_op, not_nan;
903 TestLastArgumentIsDouble(assembler, &is_smi, normal_ir_body);
906 __ LoadDFieldFromOffset(
V1,
R0, target::Double::value_offset());
908 __ ldr(
R0, Address(
SP, 1 * target::kWordSize));
909 __ LoadDFieldFromOffset(
V0,
R0, target::Double::value_offset());
925 __ Bind(normal_ir_body);
928void AsmIntrinsifier::Double_greaterThan(Assembler* assembler,
929 Label* normal_ir_body) {
930 CompareDoubles(assembler, normal_ir_body,
HI);
933void AsmIntrinsifier::Double_greaterEqualThan(Assembler* assembler,
934 Label* normal_ir_body) {
935 CompareDoubles(assembler, normal_ir_body,
CS);
938void AsmIntrinsifier::Double_lessThan(Assembler* assembler,
939 Label* normal_ir_body) {
940 CompareDoubles(assembler, normal_ir_body,
CC);
943void AsmIntrinsifier::Double_equal(Assembler* assembler,
944 Label* normal_ir_body) {
945 CompareDoubles(assembler, normal_ir_body,
EQ);
948void AsmIntrinsifier::Double_lessEqualThan(Assembler* assembler,
949 Label* normal_ir_body) {
950 CompareDoubles(assembler, normal_ir_body,
LS);
955static void DoubleArithmeticOperations(Assembler* assembler,
956 Label* normal_ir_body,
958 Label is_smi, double_op;
960 TestLastArgumentIsDouble(assembler, &is_smi, normal_ir_body);
962 __ LoadDFieldFromOffset(
V1,
R0, target::Double::value_offset());
964 __ ldr(
R0, Address(
SP, 1 * target::kWordSize));
965 __ LoadDFieldFromOffset(
V0,
R0, target::Double::value_offset());
984 __ StoreDFieldToOffset(
V0,
R0, target::Double::value_offset());
992 __ Bind(normal_ir_body);
995void AsmIntrinsifier::Double_add(Assembler* assembler, Label* normal_ir_body) {
996 DoubleArithmeticOperations(assembler, normal_ir_body, Token::kADD);
999void AsmIntrinsifier::Double_mul(Assembler* assembler, Label* normal_ir_body) {
1000 DoubleArithmeticOperations(assembler, normal_ir_body, Token::kMUL);
1003void AsmIntrinsifier::Double_sub(Assembler* assembler, Label* normal_ir_body) {
1004 DoubleArithmeticOperations(assembler, normal_ir_body, Token::kSUB);
1007void AsmIntrinsifier::Double_div(Assembler* assembler, Label* normal_ir_body) {
1008 DoubleArithmeticOperations(assembler, normal_ir_body, Token::kDIV);
1012void AsmIntrinsifier::Double_mulFromInteger(Assembler* assembler,
1013 Label* normal_ir_body) {
1015 __ ldr(
R0, Address(
SP, 0 * target::kWordSize));
1016 __ BranchIfNotSmi(
R0, normal_ir_body);
1020 __ ldr(
R0, Address(
SP, 1 * target::kWordSize));
1021 __ LoadDFieldFromOffset(
V0,
R0, target::Double::value_offset());
1025 __ StoreDFieldToOffset(
V0,
R0, target::Double::value_offset());
1027 __ Bind(normal_ir_body);
1030void AsmIntrinsifier::DoubleFromInteger(Assembler* assembler,
1031 Label* normal_ir_body) {
1032 __ ldr(
R0, Address(
SP, 0 * target::kWordSize));
1033 __ BranchIfNotSmi(
R0, normal_ir_body);
1036#if !defined(DART_COMPRESSED_POINTERS)
1043 __ StoreDFieldToOffset(
V0,
R0, target::Double::value_offset());
1045 __ Bind(normal_ir_body);
1048void AsmIntrinsifier::Double_getIsNaN(Assembler* assembler,
1049 Label* normal_ir_body) {
1050 __ ldr(
R0, Address(
SP, 0 * target::kWordSize));
1051 __ LoadDFieldFromOffset(
V0,
R0, target::Double::value_offset());
1059void AsmIntrinsifier::Double_getIsInfinite(Assembler* assembler,
1060 Label* normal_ir_body) {
1061 __ ldr(
R0, Address(
SP, 0 * target::kWordSize));
1062 __ LoadFieldFromOffset(
R0,
R0, target::Double::value_offset());
1064 __ AndImmediate(
R0,
R0, 0x7FFFFFFFFFFFFFFFLL);
1066 __ CompareImmediate(
R0, 0x7FF0000000000000LL);
1073void AsmIntrinsifier::Double_getIsNegative(Assembler* assembler,
1074 Label* normal_ir_body) {
1077 Label is_false, is_true, is_zero;
1079 __ ldr(
R0, Address(
SP, 0 * target::kWordSize));
1080 __ LoadDFieldFromOffset(
V0,
R0, target::Double::value_offset());
1082 __ LoadObject(true_reg, CastHandle<Object>(
TrueObject()));
1083 __ LoadObject(false_reg, CastHandle<Object>(
FalseObject()));
1084 __ b(&is_false,
VS);
1086 __ b(&is_false,
CS);
1089 __ mov(
R0, true_reg);
1097 __ LsrImmediate(
R1,
R1, 63);
1098 __ tsti(
R1, Immediate(1));
1099 __ csel(
R0, true_reg, false_reg,
NE);
1103void AsmIntrinsifier::ObjectEquals(Assembler* assembler,
1104 Label* normal_ir_body) {
1105 __ ldr(
R0, Address(
SP, 0 * target::kWordSize));
1106 __ ldr(
R1, Address(
SP, 1 * target::kWordSize));
1107 __ CompareObjectRegisters(
R0,
R1);
1114static void JumpIfInteger(Assembler* assembler,
1122static void JumpIfNotInteger(Assembler* assembler,
1130static void JumpIfString(Assembler* assembler,
1134 assembler->RangeCheck(
cid, tmp, kOneByteStringCid, kTwoByteStringCid,
1138static void JumpIfNotString(Assembler* assembler,
1142 assembler->RangeCheck(
cid, tmp, kOneByteStringCid, kTwoByteStringCid,
1146static void JumpIfNotList(Assembler* assembler,
1150 assembler->RangeCheck(
cid, tmp, kArrayCid, kGrowableObjectArrayCid,
1154static void JumpIfType(Assembler* assembler,
1159 (kRecordTypeCid == kTypeCid + 2));
1160 assembler->RangeCheck(
cid, tmp, kTypeCid, kRecordTypeCid,
1164static void JumpIfNotType(Assembler* assembler,
1169 (kRecordTypeCid == kTypeCid + 2));
1170 assembler->RangeCheck(
cid, tmp, kTypeCid, kRecordTypeCid,
1175void AsmIntrinsifier::ObjectRuntimeType(Assembler* assembler,
1176 Label* normal_ir_body) {
1177 Label use_declaration_type, not_double, not_integer, not_string;
1178 __ ldr(
R0, Address(
SP, 0 * target::kWordSize));
1179 __ LoadClassIdMayBeSmi(
R1,
R0);
1181 __ CompareImmediate(
R1, kClosureCid);
1182 __ b(normal_ir_body,
EQ);
1184 __ CompareImmediate(
R1, kRecordCid);
1185 __ b(normal_ir_body,
EQ);
1188 __ b(&use_declaration_type,
HI);
1190 __ LoadIsolateGroup(
R2);
1191 __ LoadFromOffset(
R2,
R2, target::IsolateGroup::object_store_offset());
1193 __ CompareImmediate(
R1, kDoubleCid);
1194 __ b(¬_double,
NE);
1195 __ LoadFromOffset(
R0,
R2, target::ObjectStore::double_type_offset());
1198 __ Bind(¬_double);
1199 JumpIfNotInteger(assembler,
R1,
R0, ¬_integer);
1200 __ LoadFromOffset(
R0,
R2, target::ObjectStore::int_type_offset());
1203 __ Bind(¬_integer);
1204 JumpIfNotString(assembler,
R1,
R0, ¬_string);
1205 __ LoadFromOffset(
R0,
R2, target::ObjectStore::string_type_offset());
1208 __ Bind(¬_string);
1209 JumpIfNotType(assembler,
R1,
R0, &use_declaration_type);
1210 __ LoadFromOffset(
R0,
R2, target::ObjectStore::type_type_offset());
1213 __ Bind(&use_declaration_type);
1214 __ LoadClassById(
R2,
R1);
1215 __ ldr(
R3, FieldAddress(
R2, target::Class::num_type_arguments_offset()),
1217 __ cbnz(normal_ir_body,
R3);
1219 __ LoadCompressed(
R0,
1220 FieldAddress(
R2, target::Class::declaration_type_offset()));
1222 __ b(normal_ir_body,
EQ);
1225 __ Bind(normal_ir_body);
1232static void EquivalentClassIds(Assembler* assembler,
1233 Label* normal_ir_body,
1234 Label* equal_may_be_generic,
1235 Label* equal_not_generic,
1240 bool testing_instance_cids) {
1241 Label not_integer, not_integer_or_string, not_integer_or_string_or_list;
1244 __ CompareImmediate(cid1, kClosureCid);
1245 __ b(normal_ir_body,
EQ);
1248 __ CompareImmediate(cid1, kRecordCid);
1249 __ b(normal_ir_body,
EQ);
1254 __ cmp(cid1, Operand(cid2));
1255 __ b(equal_may_be_generic,
EQ);
1261 __ b(not_equal,
HI);
1264 JumpIfNotInteger(assembler, cid1, scratch, ¬_integer);
1267 JumpIfInteger(assembler, cid2, scratch, equal_not_generic);
1271 __ Bind(¬_integer);
1273 JumpIfNotString(assembler, cid1, scratch,
1274 testing_instance_cids ? ¬_integer_or_string : not_equal);
1277 JumpIfString(assembler, cid2, scratch, equal_not_generic);
1281 if (testing_instance_cids) {
1282 __ Bind(¬_integer_or_string);
1284 JumpIfNotList(assembler, cid1, scratch, ¬_integer_or_string_or_list);
1287 JumpIfNotList(assembler, cid2, scratch, not_equal);
1288 ASSERT(compiler::target::Array::type_arguments_offset() ==
1289 compiler::target::GrowableObjectArray::type_arguments_offset());
1290 __ b(equal_may_be_generic);
1292 __ Bind(¬_integer_or_string_or_list);
1296 JumpIfNotType(assembler, cid1, scratch, not_equal);
1299 JumpIfType(assembler, cid2, scratch, equal_not_generic);
1305void AsmIntrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler,
1306 Label* normal_ir_body) {
1308 __ LoadClassIdMayBeSmi(
R2,
R1);
1309 __ LoadClassIdMayBeSmi(
R1,
R0);
1311 Label equal_may_be_generic,
equal, not_equal;
1312 EquivalentClassIds(assembler, normal_ir_body, &equal_may_be_generic, &
equal,
1316 __ Bind(&equal_may_be_generic);
1320 __ LoadClassById(
R0,
R1);
1324 target::Class::host_type_arguments_field_offset_in_words_offset()),
1326 __ CompareImmediate(
R0, target::Class::kNoTypeArguments);
1335 __ CompareObjectRegisters(
R1,
R2);
1336 __ b(normal_ir_body,
NE);
1343 __ Bind(¬_equal);
1347 __ Bind(normal_ir_body);
1350void AsmIntrinsifier::String_getHashCode(Assembler* assembler,
1351 Label* normal_ir_body) {
1352 __ ldr(
R0, Address(
SP, 0 * target::kWordSize));
1353 __ ldr(
R0, FieldAddress(
R0, target::String::hash_offset()),
1356 __ b(normal_ir_body,
EQ);
1359 __ Bind(normal_ir_body);
1362void AsmIntrinsifier::Type_equality(Assembler* assembler,
1363 Label* normal_ir_body) {
1364 Label
equal, not_equal, equiv_cids_may_be_generic, equiv_cids, check_legacy;
1367 __ CompareObjectRegisters(
R1,
R2);
1372 __ LoadClassIdMayBeSmi(
R0,
R1);
1373 __ CompareImmediate(
R0, kTypeCid);
1374 __ b(normal_ir_body,
NE);
1377 __ LoadTypeClassId(
R3,
R1);
1378 __ LoadTypeClassId(
R4,
R2);
1380 EquivalentClassIds(assembler, normal_ir_body, &equiv_cids_may_be_generic,
1381 &equiv_cids, ¬_equal,
R3,
R4,
R0,
1384 __ Bind(&equiv_cids_may_be_generic);
1386 __ LoadCompressed(
R3, FieldAddress(
R1, target::Type::arguments_offset()));
1387 __ LoadCompressed(
R4, FieldAddress(
R2, target::Type::arguments_offset()));
1388 __ CompareObjectRegisters(
R3,
R4);
1389 __ b(normal_ir_body,
NE);
1393 __ Bind(&equiv_cids);
1394 __ LoadAbstractTypeNullability(
R1,
R1);
1395 __ LoadAbstractTypeNullability(
R2,
R2);
1397 __ b(&check_legacy,
NE);
1407 ASSERT(target::Nullability::kNullable < target::Nullability::kNonNullable &&
1408 target::Nullability::kNonNullable < target::Nullability::kLegacy);
1409 __ Bind(&check_legacy);
1410 __ CompareImmediate(
R1, target::Nullability::kNonNullable);
1411 __ b(¬_equal,
LT);
1412 __ CompareImmediate(
R2, target::Nullability::kNonNullable);
1415 __ Bind(¬_equal);
1419 __ Bind(normal_ir_body);
1422void AsmIntrinsifier::AbstractType_getHashCode(Assembler* assembler,
1423 Label* normal_ir_body) {
1424 __ ldr(
R0, Address(
SP, 0 * target::kWordSize));
1425 __ LoadCompressedSmi(
R0,
1426 FieldAddress(
R0, target::AbstractType::hash_offset()));
1430 __ Bind(normal_ir_body);
1433void AsmIntrinsifier::AbstractType_equality(Assembler* assembler,
1434 Label* normal_ir_body) {
1436 __ CompareObjectRegisters(
R1,
R2);
1437 __ b(normal_ir_body,
NE);
1442 __ Bind(normal_ir_body);
1449void AsmIntrinsifier::Object_getHash(Assembler* assembler,
1450 Label* normal_ir_body) {
1451 Label not_yet_computed;
1452 __ ldr(
R0, Address(
SP, 0 * target::kWordSize));
1455 FieldAddress(
R0, target::Object::tags_offset() +
1458 __ cbz(¬_yet_computed,
R0);
1462 __ Bind(¬_yet_computed);
1463 __ LoadFromOffset(
R1,
THR, target::Thread::random_offset());
1464 __ AndImmediate(
R2,
R1, 0xffffffff);
1465 __ LsrImmediate(
R3,
R1, 32);
1466 __ LoadImmediate(
R1, 0xffffda61);
1469 __ StoreToOffset(
R1,
THR, target::Thread::random_offset());
1470 __ AndImmediate(
R1,
R1, 0x3fffffff);
1471 __ cbz(¬_yet_computed,
R1);
1473 __ ldr(
R0, Address(
SP, 0 * target::kWordSize));
1475 __ LslImmediate(
R3,
R1, target::UntaggedObject::kHashTagPos);
1477 Label retry, already_set_in_r4;
1480 __ LsrImmediate(
R4,
R2, target::UntaggedObject::kHashTagPos);
1481 __ cbnz(&already_set_in_r4,
R4);
1484 __ cbnz(&retry,
R4);
1488 __ Bind(&already_set_in_r4);
1494void GenerateSubstringMatchesSpecialization(Assembler* assembler,
1495 intptr_t receiver_cid,
1498 Label* return_false) {
1500 __ LoadCompressedSmi(
1501 R8, FieldAddress(
R0, target::String::length_offset()));
1503 __ LoadCompressedSmi(
1504 R9, FieldAddress(
R2, target::String::length_offset()));
1508 __ cmp(
R9, Operand(0));
1509 __ b(return_true,
EQ);
1512 __ cmp(
R1, Operand(0));
1513 __ b(return_false,
LT);
1518 __ b(return_false,
GT);
1520 if (receiver_cid == kOneByteStringCid) {
1524 ASSERT(receiver_cid == kTwoByteStringCid);
1529 if (other_cid == kOneByteStringCid) {
1532 ASSERT(other_cid == kTwoByteStringCid);
1537 __ LoadImmediate(
R3, 0);
1550 __ b(return_false,
NE);
1553 __ add(
R3,
R3, Operand(1));
1554 __ add(
R0,
R0, Operand(receiver_cid == kOneByteStringCid ? 1 : 2));
1555 __ add(
R2,
R2, Operand(other_cid == kOneByteStringCid ? 1 : 2));
1565void AsmIntrinsifier::StringBaseSubstringMatches(Assembler* assembler,
1566 Label* normal_ir_body) {
1567 Label return_true, return_false, try_two_byte;
1568 __ ldr(
R0, Address(
SP, 2 * target::kWordSize));
1569 __ ldr(
R1, Address(
SP, 1 * target::kWordSize));
1570 __ ldr(
R2, Address(
SP, 0 * target::kWordSize));
1572 __ BranchIfNotSmi(
R1, normal_ir_body);
1574 __ CompareClassId(
R2, kOneByteStringCid);
1575 __ b(normal_ir_body,
NE);
1577 __ CompareClassId(
R0, kOneByteStringCid);
1578 __ b(normal_ir_body,
NE);
1580 GenerateSubstringMatchesSpecialization(assembler, kOneByteStringCid,
1581 kOneByteStringCid, &return_true,
1584 __ Bind(&try_two_byte);
1585 __ CompareClassId(
R0, kTwoByteStringCid);
1586 __ b(normal_ir_body,
NE);
1588 GenerateSubstringMatchesSpecialization(assembler, kTwoByteStringCid,
1589 kOneByteStringCid, &return_true,
1592 __ Bind(&return_true);
1596 __ Bind(&return_false);
1600 __ Bind(normal_ir_body);
1603void AsmIntrinsifier::StringBaseCharAt(Assembler* assembler,
1604 Label* normal_ir_body) {
1605 Label try_two_byte_string;
1607 __ ldr(
R1, Address(
SP, 0 * target::kWordSize));
1608 __ ldr(
R0, Address(
SP, 1 * target::kWordSize));
1609 __ BranchIfNotSmi(
R1, normal_ir_body);
1611 __ LoadCompressedSmi(
R2, FieldAddress(
R0, target::String::length_offset()));
1613 __ b(normal_ir_body,
CS);
1615 __ CompareClassId(
R0, kOneByteStringCid);
1616 __ b(&try_two_byte_string,
NE);
1620 __ CompareImmediate(
R1, target::Symbols::kNumberOfOneCharCodeSymbols);
1621 __ b(normal_ir_body,
GE);
1622 __ ldr(
R0, Address(
THR, target::Thread::predefined_symbols_address_offset()));
1624 R0, target::Symbols::kNullCharCodeSymbolOffset * target::kWordSize);
1628 __ Bind(&try_two_byte_string);
1629 __ CompareClassId(
R0, kTwoByteStringCid);
1630 __ b(normal_ir_body,
NE);
1633#if !defined(DART_COMPRESSED_POINTERS)
1639 __ CompareImmediate(
R1, target::Symbols::kNumberOfOneCharCodeSymbols);
1640 __ b(normal_ir_body,
GE);
1641 __ ldr(
R0, Address(
THR, target::Thread::predefined_symbols_address_offset()));
1643 R0, target::Symbols::kNullCharCodeSymbolOffset * target::kWordSize);
1647 __ Bind(normal_ir_body);
1650void AsmIntrinsifier::StringBaseIsEmpty(Assembler* assembler,
1651 Label* normal_ir_body) {
1652 __ ldr(
R0, Address(
SP, 0 * target::kWordSize));
1653 __ LoadCompressedSmi(
R0, FieldAddress(
R0, target::String::length_offset()));
1661void AsmIntrinsifier::OneByteString_getHashCode(Assembler* assembler,
1662 Label* normal_ir_body) {
1664 __ ldr(
R1, Address(
SP, 0 * target::kWordSize));
1665 __ ldr(
R0, FieldAddress(
R1, target::String::hash_offset()),
1668 __ b(&compute_hash,
EQ);
1671 __ Bind(&compute_hash);
1672 __ LoadCompressedSmi(
R2, FieldAddress(
R1, target::String::length_offset()));
1692 __ add(
R3,
R3, Operand(1));
1699 __ FinalizeHashForSize(target::String::kHashBits,
R0);
1703 __ LslImmediate(
R0,
R0, target::UntaggedObject::kHashTagPos);
1709 __ cbnz(&retry,
R4);
1711 __ LsrImmediate(
R0,
R0, target::UntaggedObject::kHashTagPos);
1719static void TryAllocateString(Assembler* assembler,
1721 intptr_t max_elements,
1724 ASSERT(
cid == kOneByteStringCid ||
cid == kTwoByteStringCid);
1727 __ BranchIfNotSmi(length_reg, failure);
1734 __ mov(
R6, length_reg);
1735 if (
cid == kOneByteStringCid) {
1737 __ SmiUntag(length_reg, length_reg);
1742 const intptr_t fixed_size_plus_alignment_padding =
1743 target::String::InstanceSize() +
1745 __ AddImmediate(length_reg, fixed_size_plus_alignment_padding);
1746 __ andi(length_reg, length_reg,
1749 __ ldr(
R0, Address(
THR, target::Thread::top_offset()));
1752 __ adds(
R1,
R0, Operand(length_reg));
1759 __ ldr(
R7, Address(
THR, target::Thread::end_offset()));
1762 __ CheckAllocationCanary(
R0);
1766 __ str(
R1, Address(
THR, target::Thread::top_offset()));
1778 const intptr_t shift = target::UntaggedObject::kTagBitsSizeTagPos -
1781 __ CompareImmediate(
R2, target::UntaggedObject::kSizeTagMaxSizeTag);
1782 __ LslImmediate(
R2,
R2, shift);
1790 __ LoadImmediate(
TMP, tags);
1792 __ str(
R2, FieldAddress(
R0, target::Object::tags_offset()));
1795#if DART_COMPRESSED_POINTERS
1797 __ str(
ZR, FieldAddress(
R0, target::String::length_offset()));
1800 __ StoreCompressedIntoObjectNoBarrier(
1801 R0, FieldAddress(
R0, target::String::length_offset()),
R6);
1809void AsmIntrinsifier::OneByteString_substringUnchecked(Assembler* assembler,
1810 Label* normal_ir_body) {
1811 const intptr_t kStringOffset = 2 * target::kWordSize;
1812 const intptr_t kStartIndexOffset = 1 * target::kWordSize;
1813 const intptr_t kEndIndexOffset = 0 * target::kWordSize;
1816 __ ldr(
R2, Address(
SP, kEndIndexOffset));
1817 __ ldr(
TMP, Address(
SP, kStartIndexOffset));
1819 __ BranchIfNotSmi(
R3, normal_ir_body);
1822 TryAllocateString(assembler, kOneByteStringCid,
1823 target::OneByteString::kMaxNewSpaceElements, &
ok,
1828 __ ldr(
R3, Address(
SP, kStringOffset));
1829 __ ldr(
R1, Address(
SP, kStartIndexOffset));
1833 __ AddImmediate(
R3, target::OneByteString::data_offset() - 1);
1837 __ ldr(
R2, Address(
SP, kEndIndexOffset));
1848 __ cmp(
R2, Operand(0));
1854 __ AddImmediate(
R6, 1);
1855 __ sub(
R2,
R2, Operand(1));
1856 __ cmp(
R2, Operand(0));
1857 __ str(
R1, FieldAddress(
R7, target::OneByteString::data_offset()),
1859 __ AddImmediate(
R7, 1);
1864 __ Bind(normal_ir_body);
1867void AsmIntrinsifier::WriteIntoOneByteString(Assembler* assembler,
1868 Label* normal_ir_body) {
1869 __ ldr(
R2, Address(
SP, 0 * target::kWordSize));
1870 __ ldr(
R1, Address(
SP, 1 * target::kWordSize));
1871 __ ldr(
R0, Address(
SP, 2 * target::kWordSize));
1880void AsmIntrinsifier::WriteIntoTwoByteString(Assembler* assembler,
1881 Label* normal_ir_body) {
1882 __ ldr(
R2, Address(
SP, 0 * target::kWordSize));
1883 __ ldr(
R1, Address(
SP, 1 * target::kWordSize));
1884 __ ldr(
R0, Address(
SP, 2 * target::kWordSize));
1889#if !defined(DART_COMPRESSED_POINTERS)
1898void AsmIntrinsifier::AllocateOneByteString(Assembler* assembler,
1899 Label* normal_ir_body) {
1902 __ ldr(
R2, Address(
SP, 0 * target::kWordSize));
1903#if defined(DART_COMPRESSED_POINTERS)
1906 TryAllocateString(assembler, kOneByteStringCid,
1907 target::OneByteString::kMaxNewSpaceElements, &
ok,
1913 __ Bind(normal_ir_body);
1916void AsmIntrinsifier::AllocateTwoByteString(Assembler* assembler,
1917 Label* normal_ir_body) {
1920 __ ldr(
R2, Address(
SP, 0 * target::kWordSize));
1921#if defined(DART_COMPRESSED_POINTERS)
1924 TryAllocateString(assembler, kTwoByteStringCid,
1925 target::TwoByteString::kMaxNewSpaceElements, &
ok,
1931 __ Bind(normal_ir_body);
1934void AsmIntrinsifier::OneByteString_equality(Assembler* assembler,
1935 Label* normal_ir_body) {
1936 __ ldr(
R0, Address(
SP, 1 * target::kWordSize));
1937 __ ldr(
R1, Address(
SP, 0 * target::kWordSize));
1939 StringEquality(assembler,
R0,
R1,
R2,
R3,
R0, normal_ir_body,
1943void AsmIntrinsifier::TwoByteString_equality(Assembler* assembler,
1944 Label* normal_ir_body) {
1945 __ ldr(
R0, Address(
SP, 1 * target::kWordSize));
1946 __ ldr(
R1, Address(
SP, 0 * target::kWordSize));
1948 StringEquality(assembler,
R0,
R1,
R2,
R3,
R0, normal_ir_body,
1952void AsmIntrinsifier::IntrinsifyRegExpExecuteMatch(Assembler* assembler,
1953 Label* normal_ir_body,
1955 if (FLAG_interpret_irregexp)
return;
1957 const intptr_t kRegExpParamOffset = 2 * target::kWordSize;
1958 const intptr_t kStringParamOffset = 1 * target::kWordSize;
1968 __ ldr(
R2, Address(
SP, kRegExpParamOffset));
1969 __ ldr(
R1, Address(
SP, kStringParamOffset));
1971 __ AddImmediate(
R1, -kOneByteStringCid);
1972#if !defined(DART_COMPRESSED_POINTERS)
1973 __ add(
R1,
R2, Operand(
R1,
LSL, target::kWordSizeLog2));
1975 __ add(
R1,
R2, Operand(
R1,
LSL, target::kWordSizeLog2 - 1));
1978 FieldAddress(
R1, target::RegExp::function_offset(
1979 kOneByteStringCid, sticky)));
1989 FieldAddress(
FUNCTION_REG, target::Function::entry_point_offset()));
1993void AsmIntrinsifier::UserTag_defaultTag(Assembler* assembler,
1994 Label* normal_ir_body) {
1996 __ ldr(
R0, Address(
R0, target::Isolate::default_tag_offset()));
2000void AsmIntrinsifier::Profiler_getCurrentTag(Assembler* assembler,
2001 Label* normal_ir_body) {
2003 __ ldr(
R0, Address(
R0, target::Isolate::current_tag_offset()));
2007void AsmIntrinsifier::Timeline_isDartStreamEnabled(Assembler* assembler,
2008 Label* normal_ir_body) {
2009#if !defined(SUPPORT_TIMELINE)
2014 __ ldr(
R0, Address(
THR, target::Thread::dart_stream_offset()));
2016 __ ldr(
R0, Address(
R0, target::TimelineStream::enabled_offset()));
2017 __ cmp(
R0, Operand(0));
2025void AsmIntrinsifier::Timeline_getNextTaskId(Assembler* assembler,
2026 Label* normal_ir_body) {
2027#if !defined(SUPPORT_TIMELINE)
2031 __ ldr(
R0, Address(
THR, target::Thread::next_task_id_offset()));
2032 __ add(
R1,
R0, Operand(1));
2033 __ str(
R1, Address(
THR, target::Thread::next_task_id_offset()));
static void done(const char *config, const char *src, const char *srcOptions, const char *name)
static bool equal(const SkBitmap &a, const SkBitmap &b)
static bool ok(int result)
static bool left(const SkPoint &p0, const SkPoint &p1)
static bool right(const SkPoint &p0, const SkPoint &p1)
#define COMPILE_ASSERT(expr)
uword MakeTagWordForNewSpaceObject(classid_t cid, uword instance_size)
word ToRawSmi(const dart::Object &a)
const Bool & TrueObject()
const Bool & FalseObject()
const Object & NullObject()
const Class & DoubleClass()
static bool CompareIntegers(Token::Kind kind, const Integer &left, const Integer &right)
uint32_t CombineHashes(uint32_t hash, uint32_t other_hash)
constexpr intptr_t kBitsPerByte
const Register FUNCTION_REG
const intptr_t kBytesPerBigIntDigit
static constexpr intptr_t kObjectAlignmentLog2
static constexpr intptr_t kObjectAlignment
#define NOT_IN_PRODUCT(code)