7#if defined(TARGET_ARCH_IA32)
28#define __ compiler->assembler()->
29#define Z (compiler->zone())
36 const Instruction* instr,
37 LocationSummary* locs) {
40 ASSERT(instr->representation() == kTagged);
41 const intptr_t kNumInputs = 0;
42 const intptr_t kNumTemps = 0;
43 LocationSummary*
result =
new (zone)
50 ASSERT(instr->RequiredInputRepresentation(0) == kTagged);
51 ASSERT(instr->representation() == kTagged);
52 __ movl(
out, compiler::Address(instr->base_reg(), index,
TIMES_2,
61 ASSERT(instr->RequiredInputRepresentation(
63 __ movl(compiler::Address(instr->base_reg(), index,
TIMES_2, instr->offset()),
72 Fixed<Register, ARGS_DESC_REG>,
73 Temp<Register> temp)) {
88 const bool remove_loop =
90 const intptr_t kNumInputs = 5;
91 const intptr_t kNumTemps = remove_loop ? 1 : 0;
92 LocationSummary*
locs =
new (zone)
100 const bool needs_writable_inputs =
101 (((element_size_ == 1) && !unboxed_inputs_) ||
102 ((element_size_ == 16) && unboxed_inputs_));
104 needs_writable_inputs
108 needs_writable_inputs
126static inline intptr_t SizeOfMemoryCopyElements(intptr_t
element_size) {
132 compiler::Label*
done) {
133 const intptr_t mov_size = SizeOfMemoryCopyElements(element_size_);
141 __ SmiUntag(length_reg);
142 }
else if (shift > 0) {
143 __ shll(length_reg, compiler::Immediate(shift));
151 compiler::Label*
done,
152 compiler::Label* copy_forwards) {
153 const intptr_t mov_size = SizeOfMemoryCopyElements(element_size_);
154 const bool reversed = copy_forwards !=
nullptr;
158 __ BranchIfZero(length_reg,
done);
162 __ leal(
ESI, compiler::Address(src_reg, length_reg,
scale, -mov_size));
163 __ CompareRegisters(dest_reg,
ESI);
169 compiler::Address(dest_reg, length_reg,
scale, -mov_size));
173 __ movl(
ESI, src_reg);
193void MemoryCopyInstr::EmitComputeStartPointer(FlowGraphCompiler*
compiler,
200 if (array_rep != kTagged) {
211 case kOneByteStringCid:
215 case kTwoByteStringCid:
224 ASSERT(start_loc.IsRegister() || start_loc.IsConstant());
225 if (start_loc.IsConstant()) {
226 const auto& constant = start_loc.constant();
227 ASSERT(constant.IsInteger());
228 const int64_t start_value = Integer::Cast(constant).AsInt64Value();
230 Utils::MulWithWrapAround<intptr_t>(start_value, element_size_),
offset);
231 __ leal(payload_reg, compiler::Address(array_reg, add_value));
235 const Register start_reg = start_loc.reg();
236 bool index_unboxed = unboxed_inputs_;
239 if (element_size_ == 1 && !index_unboxed) {
241 __ SmiUntag(start_reg);
242 index_unboxed =
true;
243 }
else if (element_size_ == 16 && index_unboxed) {
246 __ SmiTag(start_reg);
247 index_unboxed =
false;
250 __ leal(payload_reg, compiler::Address(array_reg, start_reg,
scale,
offset));
255 const intptr_t kNumInputs = 1;
256 const intptr_t kNumTemps = 0;
257 LocationSummary*
locs =
new (zone)
269 if (
value.IsConstant()) {
279 const intptr_t kNumInputs = 1;
280 const intptr_t kNumTemps = 0;
281 LocationSummary*
locs =
new (zone)
295 if (
compiler->parsed_function().function().IsAsyncFunction() ||
296 compiler->parsed_function().function().IsAsyncGenerator()) {
298 const Code& stub = GetReturnStub(
compiler);
303 if (!
compiler->flow_graph().graph_entry()->NeedsFrame()) {
309 __ Comment(
"Stack Check");
310 compiler::Label
done;
311 const intptr_t fp_sp_dist =
318 __ cmpl(
EDI, compiler::Immediate(fp_sp_dist));
331 bool return_in_st0 =
false;
336 return_in_st0 =
true;
360 const Register old_exit_through_ffi_reg = tmp;
362 __ popl(old_exit_frame_reg);
371 __ movl(old_exit_through_ffi_reg, vm_tag_reg);
377 __ TransitionGeneratedToNative(vm_tag_reg, old_exit_frame_reg,
378 old_exit_through_ffi_reg,
385 .SizeInBytes() == 8) {
387 __ fldl(compiler::Address(
SPREG, -8));
390 __ flds(compiler::Address(
SPREG, -4));
399#if defined(DART_TARGET_OS_FUCHSIA) && defined(USING_SHADOW_CALL_STACK)
412 const intptr_t kNumInputs = 0;
413 const intptr_t stack_index =
427 const intptr_t kNumInputs = 1;
436 __ movl(compiler::Address(
443 const intptr_t kNumInputs = 0;
455 if (
out.IsRegister()) {
464 intptr_t pair_index) {
465 if (destination.IsRegister()) {
470 if (value_.IsSmi() &&
476 __ movl(destination.reg(),
481 __ LoadObjectSafely(destination.reg(), value_);
483 }
else if (destination.IsFpuRegister()) {
486 __ LoadSImmediate(destination.fpu_reg(),
487 static_cast<float>(Double::Cast(value_).value()));
489 case kUnboxedDouble: {
490 const double value_as_double = Double::Cast(value_).value();
494 __ LoadObject(
EAX, value_);
495 __ movsd(destination.fpu_reg(),
499 __ xorps(destination.fpu_reg(), destination.fpu_reg());
505 case kUnboxedFloat64x2:
506 __ LoadQImmediate(destination.fpu_reg(),
507 Float64x2::Cast(value_).value());
509 case kUnboxedFloat32x4:
510 __ LoadQImmediate(destination.fpu_reg(),
511 Float32x4::Cast(value_).value());
513 case kUnboxedInt32x4:
514 __ LoadQImmediate(destination.fpu_reg(), Int32x4::Cast(value_).value());
519 }
else if (destination.IsDoubleStackSlot()) {
520 const double value_as_double = Double::Cast(value_).value();
524 __ LoadObject(
EAX, value_);
533 }
else if (destination.IsQuadStackSlot()) {
535 case kUnboxedFloat64x2:
538 case kUnboxedFloat32x4:
541 case kUnboxedInt32x4:
549 ASSERT(destination.IsStackSlot());
559 bit_cast<int32_t, float>(Double::Cast(value_).
value());
566 compiler::Immediate(
static_cast<int32_t
>(value_.ptr())));
569 __ LoadObjectSafely(
EAX, value_);
579 const bool is_unboxed_int =
583 const intptr_t kNumInputs = 0;
584 const intptr_t kNumTemps =
586 LocationSummary*
locs =
new (zone)
594 if (kNumTemps == 1) {
602 if (!
locs()->
out(0).IsInvalid()) {
610 const intptr_t kNumTemps = 0;
611 LocationSummary* summary =
new (zone)
629 auto object_store =
compiler->isolate_group()->object_store();
630 const auto& assert_boolean_stub =
633 compiler::Label
done;
639 UntaggedPcDescriptors::kOther,
locs(),
666 const intptr_t kNumInputs = 2;
667 if (operation_cid() == kMintCid) {
668 const intptr_t kNumTemps = 0;
669 LocationSummary*
locs =
new (zone)
678 if (operation_cid() == kDoubleCid) {
679 const intptr_t kNumTemps = 0;
680 LocationSummary*
locs =
new (zone)
687 if (operation_cid() == kSmiCid || operation_cid() == kIntegerCid) {
688 const intptr_t kNumTemps = 0;
689 LocationSummary*
locs =
new (zone)
705static void LoadValueCid(FlowGraphCompiler*
compiler,
708 compiler::Label* value_is_smi =
nullptr) {
709 compiler::Label
done;
710 if (value_is_smi ==
nullptr) {
711 __ movl(value_cid_reg, compiler::Immediate(kSmiCid));
714 if (value_is_smi ==
nullptr) {
719 __ LoadClassId(value_cid_reg, value_reg);
751static void EmitBranchOnCondition(
757 if (labels.fall_through == labels.false_label) {
759 __ j(true_condition, labels.true_label, jump_distance);
763 __ j(false_condition, labels.false_label, jump_distance);
766 if (labels.fall_through != labels.true_label) {
767 __ jmp(labels.true_label, jump_distance);
773 const LocationSummary& locs,
775 BranchLabels labels) {
780 Condition true_condition = TokenKindToIntCondition(kind);
782 if (
left.IsConstant()) {
784 true_condition = FlipCondition(true_condition);
785 }
else if (
right.IsConstant()) {
787 }
else if (
right.IsStackSlot()) {
792 return true_condition;
796 const LocationSummary& locs,
798 BranchLabels labels) {
803 Condition true_condition = TokenKindToIntCondition(kind);
805 if (
left.IsConstant()) {
808 static_cast<uword>(Integer::Cast(
left.constant()).AsInt64Value()));
809 true_condition = FlipCondition(true_condition);
810 }
else if (
right.IsConstant()) {
813 static_cast<uword>(Integer::Cast(
right.constant()).AsInt64Value()));
814 }
else if (
right.IsStackSlot()) {
819 return true_condition;
823 const LocationSummary& locs,
825 BranchLabels labels) {
827 PairLocation* left_pair = locs.in(0).AsPairLocation();
828 Register left1 = left_pair->At(0).reg();
829 Register left2 = left_pair->At(1).reg();
830 PairLocation* right_pair = locs.in(1).AsPairLocation();
831 Register right1 = right_pair->At(0).reg();
832 Register right2 = right_pair->At(1).reg();
833 compiler::Label
done;
835 __ cmpl(left1, right1);
838 __ cmpl(left2, right2);
840 Condition true_condition = TokenKindToIntCondition(kind);
841 return true_condition;
845 const LocationSummary& locs,
847 BranchLabels labels) {
848 PairLocation* left_pair = locs.in(0).AsPairLocation();
849 Register left1 = left_pair->At(0).reg();
850 Register left2 = left_pair->At(1).reg();
851 PairLocation* right_pair = locs.in(1).AsPairLocation();
852 Register right1 = right_pair->At(0).reg();
853 Register right2 = right_pair->At(1).reg();
878 __ cmpl(left2, right2);
879 __ j(hi_cond, labels.true_label);
880 __ j(FlipCondition(hi_cond), labels.false_label);
883 __ cmpl(left1, right1);
908 const LocationSummary& locs,
910 BranchLabels labels) {
914 __ comisd(left, right);
916 Condition true_condition = TokenKindToDoubleCondition(kind);
917 compiler::Label* nan_result =
918 (true_condition ==
NOT_EQUAL) ? labels.true_label : labels.false_label;
920 return true_condition;
924 BranchLabels labels) {
929 if (operation_cid() == kSmiCid) {
930 return EmitSmiComparisonOp(
compiler, *
locs(), kind(), labels);
931 }
else if (operation_cid() == kMintCid) {
932 return EmitUnboxedMintEqualityOp(
compiler, *
locs(), kind(), labels);
933 }
else if (operation_cid() == kIntegerCid) {
934 return EmitWordComparisonOp(
compiler, *
locs(), kind(), labels);
936 ASSERT(operation_cid() == kDoubleCid);
937 return EmitDoubleComparisonOp(
compiler, *
locs(), kind(), labels);
942 compiler::Label is_true, is_false;
943 BranchLabels labels = {&is_true, &is_false, &is_false};
946 EmitBranchOnCondition(
compiler, true_condition, labels,
951 compiler::Label
done;
961 BranchInstr* branch) {
962 BranchLabels labels =
compiler->CreateBranchLabels(branch);
965 EmitBranchOnCondition(
compiler, true_condition, labels);
971 const intptr_t kNumInputs = 2;
972 const intptr_t kNumTemps = 0;
973 LocationSummary*
locs =
new (zone)
984 BranchLabels labels) {
987 if (
right.IsConstant()) {
989 compiler::Immediate(
static_cast<int32_t
>(ComputeImmediateMask())));
994 return true_condition;
999 const intptr_t kNumInputs = 1;
1000 const intptr_t kNumTemps = 1;
1001 LocationSummary*
locs =
new (zone)
1010 BranchLabels labels) {
1011 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT));
1015 compiler::Label* deopt =
1020 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0;
1025 __ j(
ZERO,
result ? labels.true_label : labels.false_label);
1026 __ LoadClassId(cid_reg, val_reg);
1027 for (intptr_t
i = 2;
i <
data.length();
i += 2) {
1028 const intptr_t test_cid =
data[
i];
1029 ASSERT(test_cid != kSmiCid);
1031 __ cmpl(cid_reg, compiler::Immediate(test_cid));
1032 __ j(
EQUAL,
result ? labels.true_label : labels.false_label);
1035 if (deopt ==
nullptr) {
1039 compiler::Label*
target =
result ? labels.false_label : labels.true_label;
1040 if (
target != labels.fall_through) {
1053 const intptr_t kNumInputs = 2;
1054 const intptr_t kNumTemps = 0;
1055 if (operation_cid() == kMintCid) {
1056 const intptr_t kNumTemps = 0;
1057 LocationSummary*
locs =
new (zone)
1066 if (operation_cid() == kDoubleCid) {
1067 LocationSummary* summary =
new (zone)
1074 ASSERT(operation_cid() == kSmiCid);
1075 LocationSummary* summary =
new (zone)
1080 summary->set_in(1, summary->in(0).IsConstant()
1088 BranchLabels labels) {
1089 if (operation_cid() == kSmiCid) {
1090 return EmitSmiComparisonOp(
compiler, *
locs(), kind(), labels);
1091 }
else if (operation_cid() == kMintCid) {
1092 return EmitUnboxedMintComparisonOp(
compiler, *
locs(), kind(), labels);
1094 ASSERT(operation_cid() == kDoubleCid);
1095 return EmitDoubleComparisonOp(
compiler, *
locs(), kind(), labels);
1107 __ movl(
EDX, compiler::Immediate(argc_tag));
1114 stub = &StubCode::CallBootstrapNative();
1116 stub = &StubCode::CallAutoScopeNative();
1118 stub = &StubCode::CallNoScopeNative();
1120 const compiler::ExternalLabel label(
1122 __ movl(
ECX, compiler::Immediate(label.address()));
1125 compiler->GenerateNonLazyDeoptableStubCall(
1126 source(), *stub, UntaggedPcDescriptors::kOther,
locs());
1132#define R(r) (1 << r)
1135 bool is_optimizing)
const {
1138 return MakeLocationSummaryInternal(
1139 zone, is_optimizing,
1163 intptr_t stack_required = marshaller_.RequiredStackSpaceInBytes();
1170 __ pushl(compiler::Immediate(0));
1173 __ LoadObject(
CODE_REG, Object::null_object());
1174 __ EnterDartFrame(0);
1178 __ ReserveAlignedFrameSpace(stack_required);
1184 locs()->temp(1).reg());
1190 __ movl(compiler::Address(
SPREG, marshaller_.RequiredStackSpaceInBytes()),
1195 __ Comment(is_leaf_ ?
"Leaf Call" :
"Call");
1199#if !defined(PRODUCT)
1202 __ movl(compiler::Address(
1210#if !defined(PRODUCT)
1213 __ movl(compiler::Address(
1215 compiler::Immediate(0));
1221 compiler::Label get_pc;
1224 UntaggedPcDescriptors::Kind::kOther,
locs(),
1238 THR, compiler::target::Thread::
1239 call_native_through_safepoint_entry_point_offset()));
1246 __ Comment(
"Check Dart_Handle for Error.");
1247 compiler::Label not_error;
1251 __ BranchIfSmi(temp, ¬_error);
1252 __ LoadClassId(temp, temp);
1257 __ Comment(
"Slow path: call Dart_PropagateError through stub.");
1260 THR, compiler::target::Thread::
1261 call_native_through_safepoint_entry_point_offset()));
1263 __ movl(
EAX, compiler::Address(
1264 THR, kPropagateErrorRuntimeEntry.OffsetFromThread()));
1303 compiler::Address(
SPREG, marshaller_.RequiredStackSpaceInBytes()));
1306 __ LeaveDartFrame();
1325#if defined(DART_TARGET_OS_FUCHSIA) && defined(USING_SHADOW_CALL_STACK)
1344 compiler::Immediate(0));
1346 __ pushl(compiler::Address(
1350 __ pushl(compiler::Address(
1355 __ EmitEntryFrameVerification();
1358 __ TransitionNativeToGenerated(
EAX,
false,
1365 const Function& target_function = marshaller_.dart_signature();
1366 const intptr_t callback_id = target_function.FfiCallbackId();
1367 __ movl(
EAX, compiler::Address(
1369 __ movl(
EAX, compiler::Address(
1374 __ movl(
EAX, compiler::FieldAddress(
1381 __ movl(compiler::Address(
FPREG,
1393 __ pushl(compiler::FieldAddress(
1405#define R(r) (1 << r)
1409 bool is_optimizing)
const {
1412 static_assert(saved_fp < temp0,
"Unexpected ordering of registers in set.");
1422 __ MoveRegister(saved_fp,
FPREG);
1423 const intptr_t frame_space = native_calling_convention_.
StackTopInBytes();
1424 __ EnterCFrame(frame_space);
1430 __ CallCFunction(target_address);
1432 compiler::Immediate(VMTag::kDartTagId));
1440 const intptr_t kNumInputs = 1;
1450 __ movl(
result, compiler::Immediate(
1454 TIMES_HALF_WORD_SIZE,
1460 const intptr_t kNumInputs = 1;
1466 ASSERT(cid_ == kOneByteStringCid);
1469 compiler::Label is_one,
done;
1483 const intptr_t kNumInputs = 5;
1484 const intptr_t kNumTemps = 0;
1485 LocationSummary* summary =
new (zone)
1503 const Register bytes_ptr_reg = start_reg;
1504 const Register flags_reg = end_reg;
1505 const Register temp_reg = bytes_reg;
1511 const intptr_t kSizeMask = 0x03;
1512 const intptr_t kFlagsMask = 0x3C;
1514 compiler::Label scan_ascii, ascii_loop, ascii_loop_in, nonascii_loop;
1515 compiler::Label rest, rest_loop, rest_loop_in,
done;
1518 __ LoadFromSlot(bytes_reg, bytes_reg, Slot::PointerBase_data());
1521 __ leal(bytes_ptr_reg, compiler::Address(bytes_reg, start_reg,
TIMES_1, 0));
1522 __ leal(temp_reg, compiler::Address(bytes_reg, end_reg,
TIMES_1, 0));
1524 __ leal(temp_reg, compiler::Address(temp_reg, -16));
1528 __ xorl(size_reg, size_reg);
1529 __ xorl(flags_reg, flags_reg);
1539 __ addl(bytes_ptr_reg, compiler::Immediate(16));
1543 __ cmpl(bytes_ptr_reg, compiler::Address(
ESP, kBytesEndMinus16TempOffset));
1550 __ movups(vector_reg, compiler::Address(bytes_ptr_reg, 0));
1551 __ pmovmskb(temp_reg, vector_reg);
1552 __ bsfl(temp_reg, temp_reg);
1556 __ addl(bytes_ptr_reg, temp_reg);
1557 __ addl(size_reg, bytes_ptr_reg);
1560 __ movzxb(temp_reg, compiler::Address(bytes_ptr_reg, 0));
1564 __ addl(bytes_ptr_reg, compiler::Immediate(1));
1567 __ movzxb(temp_reg, compiler::FieldAddress(
1570 __ orl(flags_reg, temp_reg);
1571 __ andl(temp_reg, compiler::Immediate(kSizeMask));
1572 __ addl(size_reg, temp_reg);
1575 __ cmpl(bytes_ptr_reg, compiler::Address(
ESP, kBytesEndTempOffset));
1579 __ movzxb(temp_reg, compiler::Address(bytes_ptr_reg, 0));
1580 __ testl(temp_reg, compiler::Immediate(0x80));
1585 __ subl(size_reg, bytes_ptr_reg);
1586 __ jmp(&ascii_loop_in);
1592 __ addl(size_reg, bytes_ptr_reg);
1598 __ movzxb(temp_reg, compiler::Address(bytes_ptr_reg, 0));
1599 __ addl(bytes_ptr_reg, compiler::Immediate(1));
1602 __ movzxb(temp_reg, compiler::FieldAddress(
1605 __ orl(flags_reg, temp_reg);
1606 __ andl(temp_reg, compiler::Immediate(kSizeMask));
1607 __ addl(size_reg, temp_reg);
1611 __ cmpl(bytes_ptr_reg, compiler::Address(
ESP, kBytesEndTempOffset));
1619 __ andl(flags_reg, compiler::Immediate(kFlagsMask));
1621 __ SmiTag(flags_reg);
1625 if (decoder_location.IsStackSlot()) {
1627 decoder_reg = temp_reg;
1629 decoder_reg = decoder_location.reg();
1631 const auto scan_flags_field_offset = scan_flags_field_.offset_in_bytes();
1632 __ orl(compiler::FieldAddress(decoder_reg, scan_flags_field_offset),
1643 const intptr_t kNumInputs = 2;
1644 const intptr_t kNumTemps = 0;
1645 LocationSummary*
locs =
new (zone)
1650 const bool need_writable_index_register =
index_scale() == 1;
1651 const bool can_be_constant =
1664 if (rep == kUnboxedInt64) {
1683 bool index_unboxed = index_unboxed_;
1685 if (
index.IsRegister()) {
1687 index_unboxed =
true;
1693 compiler::Address element_address =
1697 :
compiler::Assembler::ElementAddressForIntIndex(
1705 if (rep == kUnboxedInt64) {
1708 const Register result_lo = result_pair->At(0).reg();
1709 const Register result_hi = result_pair->At(1).reg();
1710 __ movl(result_lo, element_address);
1716 :
compiler::Assembler::ElementAddressForIntIndex(
1719 __ movl(result_hi, element_address);
1726 if (rep == kUnboxedFloat) {
1728 }
else if (rep == kUnboxedDouble) {
1731 ASSERT(rep == kUnboxedInt32x4 || rep == kUnboxedFloat32x4 ||
1732 rep == kUnboxedFloat64x2);
1733 __ movups(
result, element_address);
1751 const intptr_t kNumInputs = 3;
1752 const intptr_t kNumTemps =
1754 LocationSummary*
locs =
new (zone)
1759 const bool need_writable_index_register =
index_scale() == 1;
1760 const bool can_be_constant =
1772 if (rep == kUnboxedUint8 || rep == kUnboxedInt8) {
1776 }
else if (rep == kUnboxedInt64) {
1785 }
else if (
class_id() == kArrayCid) {
1804 bool index_unboxed = index_unboxed_;
1807 index_unboxed =
true;
1809 compiler::Address element_address =
1813 :
compiler::Assembler::ElementAddressForIntIndex(
1821 ASSERT(rep == kUnboxedUint8);
1823 const Smi& constant = Smi::Cast(
locs()->in(2).constant());
1828 }
else if (
value < 0) {
1831 __ movb(element_address, compiler::Immediate(
static_cast<int8_t
>(
value)));
1834 compiler::Label store_value, store_0xff;
1835 __ cmpl(
EAX, compiler::Immediate(0xFF));
1842 __ movl(
EAX, compiler::Immediate(0xFF));
1844 __ movb(element_address,
AL);
1847 if (rep == kUnboxedUint8 || rep == kUnboxedInt8) {
1849 const Smi& constant = Smi::Cast(
locs()->in(2).constant());
1850 __ movb(element_address,
1851 compiler::Immediate(
static_cast<int8_t
>(constant.Value())));
1854 __ movb(element_address,
AL);
1856 }
else if (rep == kUnboxedInt64) {
1859 const Register value_lo = value_pair->At(0).reg();
1860 const Register value_hi = value_pair->At(1).reg();
1861 __ movl(element_address, value_lo);
1867 :
compiler::Assembler::ElementAddressForIntIndex(
1870 __ movl(element_address, value_hi);
1876 if (rep == kUnboxedFloat) {
1877 __ movss(element_address,
locs()->in(2).fpu_reg());
1878 }
else if (rep == kUnboxedDouble) {
1879 __ movsd(element_address,
locs()->in(2).fpu_reg());
1881 ASSERT(rep == kUnboxedInt32x4 || rep == kUnboxedFloat32x4 ||
1882 rep == kUnboxedFloat64x2);
1883 __ movups(element_address,
locs()->in(2).fpu_reg());
1885 }
else if (
class_id() == kArrayCid) {
1891 __ leal(slot, element_address);
1892 __ StoreIntoArray(
array, slot,
value, CanValueBeSmi(), scratch);
1895 __ StoreObjectIntoObjectNoBarrier(
array, element_address, constant);
1898 __ StoreIntoObjectNoBarrier(
array, element_address,
value);
1909 const intptr_t kNumInputs = 1;
1914 const bool emit_full_guard = !opt || (field_cid ==
kIllegalCid);
1915 const bool needs_value_cid_temp_reg =
1916 (value_cid ==
kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid));
1917 const bool needs_field_temp_reg = emit_full_guard;
1919 intptr_t num_temps = 0;
1920 if (needs_value_cid_temp_reg) {
1923 if (needs_field_temp_reg) {
1927 LocationSummary* summary =
new (zone)
1931 for (intptr_t
i = 0;
i < num_temps;
i++) {
1940 ASSERT(
sizeof(UntaggedField::guarded_cid_) == 4);
1941 ASSERT(
sizeof(UntaggedField::is_nullable_) == 4);
1951 const bool emit_full_guard =
1954 const bool needs_value_cid_temp_reg =
1955 (value_cid ==
kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid));
1957 const bool needs_field_temp_reg = emit_full_guard;
1964 const Register field_reg = needs_field_temp_reg
1968 compiler::Label
ok, fail_label;
1970 compiler::Label* deopt =
nullptr;
1975 compiler::Label*
fail = (deopt !=
nullptr) ? deopt : &fail_label;
1977 if (emit_full_guard) {
1980 compiler::FieldAddress field_cid_operand(field_reg,
1982 compiler::FieldAddress field_nullability_operand(
1986 LoadValueCid(
compiler, value_cid_reg, value_reg);
1987 __ cmpl(value_cid_reg, field_cid_operand);
1989 __ cmpl(value_cid_reg, field_nullability_operand);
1990 }
else if (value_cid ==
kNullCid) {
1993 __ cmpl(field_nullability_operand, compiler::Immediate(value_cid));
1997 __ cmpl(field_cid_operand, compiler::Immediate(value_cid));
2007 if (!
field().needs_length_check()) {
2010 __ cmpl(field_cid_operand, compiler::Immediate(
kIllegalCid));
2017 __ movl(field_cid_operand, value_cid_reg);
2018 __ movl(field_nullability_operand, value_cid_reg);
2021 __ movl(field_cid_operand, compiler::Immediate(value_cid));
2022 __ movl(field_nullability_operand, compiler::Immediate(value_cid));
2028 if (deopt ==
nullptr) {
2035 __ pushl(field_reg);
2036 __ pushl(value_reg);
2038 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2);
2045 ASSERT(deopt !=
nullptr);
2053 if (field_cid != kSmiCid) {
2055 __ LoadClassId(value_cid_reg, value_reg);
2056 __ cmpl(value_cid_reg, compiler::Immediate(field_cid));
2061 if (field_cid != kSmiCid) {
2062 __ cmpl(value_cid_reg, compiler::Immediate(
kNullCid));
2064 const compiler::Immediate& raw_null =
2065 compiler::Immediate(
static_cast<intptr_t
>(
Object::null()));
2066 __ cmpl(value_reg, raw_null);
2070 }
else if (value_cid == field_cid) {
2075 ASSERT(value_cid != nullability);
2084 const intptr_t kNumInputs = 1;
2086 const intptr_t kNumTemps = 3;
2087 LocationSummary* summary =
new (zone)
2096 LocationSummary* summary =
new (zone)
2109 compiler::Label* deopt =
2128 compiler::FieldAddress(
2130 __ movl(length_reg, compiler::FieldAddress(
2133 __ cmpl(offset_reg, compiler::Immediate(0));
2140 __ cmpl(length_reg, compiler::Address(value_reg, offset_reg,
TIMES_1, 0));
2142 if (deopt ==
nullptr) {
2145 __ pushl(field_reg);
2146 __ pushl(value_reg);
2148 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2);
2158 ASSERT(
field().guarded_list_length_in_object_offset() !=
2161 __ cmpl(compiler::FieldAddress(
2162 value_reg,
field().guarded_list_length_in_object_offset()),
2170 LocationSummary*
locs =
2198 const intptr_t kNumInputs = 3;
2199 const intptr_t kNumTemps = 0;
2200 LocationSummary* summary =
new (zone)
2225 const intptr_t kNumInputs = 2;
2226 const intptr_t kNumTemps = 0;
2227 LocationSummary*
locs =
new (zone)
2238static void InlineArrayAllocation(FlowGraphCompiler*
compiler,
2239 intptr_t num_elements,
2240 compiler::Label* slow_path,
2241 compiler::Label*
done) {
2242 const int kInlineArraySize = 12;
2247 __ TryAllocateArray(kArrayCid, instance_size, slow_path,
2254 __ StoreIntoObjectNoBarrier(
2261 __ StoreIntoObjectNoBarrier(
2272 if (num_elements > 0) {
2273 const intptr_t array_size = instance_size -
sizeof(UntaggedArray);
2274 const compiler::Immediate& raw_null =
2275 compiler::Immediate(
static_cast<intptr_t
>(
Object::null()));
2277 sizeof(UntaggedArray)));
2278 if (array_size < (kInlineArraySize *
kWordSize)) {
2279 intptr_t current_offset = 0;
2280 __ movl(
EBX, raw_null);
2281 while (current_offset < array_size) {
2283 compiler::Address(
EDI, current_offset),
2288 compiler::Label init_loop;
2291 compiler::Address(
EDI, 0),
2292 Object::null_object());
2302 compiler::Label slow_path,
done;
2303 if (!FLAG_use_slow_path && FLAG_inline_alloc) {
2315 auto object_store =
compiler->isolate_group()->object_store();
2316 const auto& allocate_array_stub =
2328 const intptr_t kNumInputs = 0;
2329 const intptr_t kNumTemps = 2;
2330 LocationSummary*
locs =
new (zone) LocationSummary(
2338class AllocateContextSlowPath
2339 :
public TemplateSlowPathCode<AllocateUninitializedContextInstr> {
2341 explicit AllocateContextSlowPath(
2342 AllocateUninitializedContextInstr* instruction)
2343 : TemplateSlowPathCode(instruction) {}
2345 virtual void EmitNativeCode(FlowGraphCompiler*
compiler) {
2346 __ Comment(
"AllocateContextSlowPath");
2349 LocationSummary* locs = instruction()->locs();
2350 ASSERT(!locs->live_registers()->Contains(locs->out(0)));
2354 auto slow_path_env =
compiler->SlowPathEnvironmentFor(
2356 ASSERT(slow_path_env !=
nullptr);
2358 __ movl(
EDX, compiler::Immediate(instruction()->num_context_variables()));
2360 StubCode::AllocateContext(),
2361 UntaggedPcDescriptors::kOther, locs,
2362 instruction()->deopt_id(), slow_path_env);
2364 compiler->RestoreLiveRegisters(instruction()->locs());
2365 __ jmp(exit_label());
2376 AllocateContextSlowPath* slow_path =
new AllocateContextSlowPath(
this);
2377 compiler->AddSlowPathCode(slow_path);
2380 if (!FLAG_use_slow_path && FLAG_inline_alloc) {
2381 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(),
2391 __ Jump(slow_path->entry_label());
2394 __ Bind(slow_path->exit_label());
2399 const intptr_t kNumInputs = 0;
2400 const intptr_t kNumTemps = 1;
2401 LocationSummary*
locs =
new (zone)
2413 compiler->GenerateStubCall(
source(), StubCode::AllocateContext(),
2420 const intptr_t kNumInputs = 1;
2421 const intptr_t kNumTemps = 0;
2422 LocationSummary*
locs =
new (zone)
2434 UntaggedPcDescriptors::kOther,
locs(),
2445 compiler->AddExceptionHandler(
this);
2452 const intptr_t fp_sp_dist =
2457 __ leal(
ESP, compiler::Address(
EBP, fp_sp_dist));
2460 if (raw_exception_var_ !=
nullptr) {
2461 __ movl(compiler::Address(
EBP,
2463 raw_exception_var_)),
2466 if (raw_stacktrace_var_ !=
nullptr) {
2467 __ movl(compiler::Address(
EBP,
2469 raw_stacktrace_var_)),
2477 const intptr_t kNumInputs = 0;
2478 const intptr_t kNumTemps = opt ? 0 : 1;
2479 LocationSummary* summary =
new (zone) LocationSummary(
2487class CheckStackOverflowSlowPath
2488 :
public TemplateSlowPathCode<CheckStackOverflowInstr> {
2490 static constexpr intptr_t kNumSlowPathArgs = 0;
2492 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction)
2493 : TemplateSlowPathCode(instruction) {}
2495 virtual void EmitNativeCode(FlowGraphCompiler*
compiler) {
2496 if (
compiler->isolate_group()->use_osr() && osr_entry_label()->IsLinked()) {
2497 __ Comment(
"CheckStackOverflowSlowPathOsr");
2498 __ Bind(osr_entry_label());
2502 __ Comment(
"CheckStackOverflowSlowPath");
2504 compiler->SaveLiveRegisters(instruction()->locs());
2508 Environment*
env =
compiler->SlowPathEnvironmentFor(
2512 __ CallRuntime(kInterruptOrStackOverflowRuntimeEntry, kNumSlowPathArgs);
2514 instruction()->
source(), instruction()->deopt_id(),
2515 UntaggedPcDescriptors::kOther, instruction()->locs(),
env);
2518 instruction()->in_loop()) {
2520 compiler->AddCurrentDescriptor(UntaggedPcDescriptors::kOsrEntry,
2521 instruction()->deopt_id(),
2522 InstructionSource());
2524 compiler->pending_deoptimization_env_ =
nullptr;
2525 compiler->RestoreLiveRegisters(instruction()->locs());
2526 __ jmp(exit_label());
2529 compiler::Label* osr_entry_label() {
2531 return &osr_entry_label_;
2535 compiler::Label osr_entry_label_;
2539 CheckStackOverflowSlowPath* slow_path =
new CheckStackOverflowSlowPath(
this);
2540 compiler->AddSlowPathCode(slow_path);
2549 const intptr_t configured_optimization_counter_threshold =
2550 compiler->thread()->isolate_group()->optimization_counter_threshold();
2551 const int32_t threshold =
2552 configured_optimization_counter_threshold * (
loop_depth() + 1);
2553 __ incl(compiler::FieldAddress(
EDI, Function::usage_counter_offset()));
2554 __ cmpl(compiler::FieldAddress(
EDI, Function::usage_counter_offset()),
2555 compiler::Immediate(threshold));
2558 if (
compiler->ForceSlowPathForStackOverflow()) {
2561 __ jmp(slow_path->entry_label());
2563 __ Bind(slow_path->exit_label());
2566static void EmitSmiShiftLeft(FlowGraphCompiler*
compiler,
2567 BinarySmiOpInstr* shift_left) {
2568 const LocationSummary& locs = *shift_left->locs();
2572 compiler::Label* deopt =
2573 shift_left->CanDeoptimize()
2574 ?
compiler->AddDeoptStub(shift_left->deopt_id(),
2575 ICData::kDeoptBinarySmiOp)
2577 if (locs.in(1).IsConstant()) {
2578 const Object& constant = locs.in(1).constant();
2579 ASSERT(constant.IsSmi());
2581 const intptr_t kCountLimit = 0x1F;
2582 const intptr_t
value = Smi::Cast(constant).Value();
2584 if (shift_left->can_overflow()) {
2587 __ shll(left, compiler::Immediate(1));
2592 Register temp = locs.temp(0).reg();
2593 __ movl(temp, left);
2594 __ shll(left, compiler::Immediate(
value));
2595 __ sarl(left, compiler::Immediate(
value));
2596 __ cmpl(left, temp);
2600 __ shll(left, compiler::Immediate(
value));
2606 Range* right_range = shift_left->right_range();
2607 if (shift_left->left()->BindsToConstant() && shift_left->can_overflow()) {
2610 const Object& obj = shift_left->left()->BoundConstant();
2612 const intptr_t left_int = Smi::Cast(obj).Value();
2613 if (left_int == 0) {
2614 __ cmpl(right, compiler::Immediate(0));
2619 const bool right_needs_check =
2621 if (right_needs_check) {
2623 compiler::Immediate(
static_cast<int32_t
>(
Smi::New(max_right))));
2627 __ shll(left, right);
2632 const bool right_needs_check =
2635 if (!shift_left->can_overflow()) {
2636 if (right_needs_check) {
2638 ASSERT(shift_left->CanDeoptimize());
2639 __ cmpl(right, compiler::Immediate(0));
2642 compiler::Label
done, is_not_zero;
2646 __ xorl(left, left);
2650 __ shll(left, right);
2654 __ shll(left, right);
2657 if (right_needs_check) {
2658 ASSERT(shift_left->CanDeoptimize());
2664 Register temp = locs.temp(0).reg();
2666 __ movl(temp, left);
2669 __ shll(left, right);
2670 __ sarl(left, right);
2671 __ cmpl(left, temp);
2674 __ shll(left, right);
2679 return constant.IsSmi() && (Smi::Cast(constant).Value() ==
value);
2684 const intptr_t kNumInputs = 2;
2685 if (
op_kind() == Token::kTRUNCDIV) {
2686 const intptr_t kNumTemps = 1;
2687 LocationSummary* summary =
new (zone)
2705 }
else if (
op_kind() == Token::kMOD) {
2706 const intptr_t kNumTemps = 1;
2707 LocationSummary* summary =
new (zone)
2716 }
else if ((
op_kind() == Token::kSHR) || (
op_kind() == Token::kUSHR)) {
2717 const intptr_t kNumTemps = 0;
2718 LocationSummary* summary =
new (zone)
2724 }
else if (
op_kind() == Token::kSHL) {
2727 const bool shiftBy1 =
2728 (right_constant !=
nullptr) &&
IsSmiValue(right_constant->value(), 1);
2729 const intptr_t kNumTemps = (
can_overflow() && !shiftBy1) ? 1 : 0;
2730 LocationSummary* summary =
new (zone)
2734 if (kNumTemps == 1) {
2740 const intptr_t kNumTemps = 0;
2741 LocationSummary* summary =
new (zone)
2745 if (constant !=
nullptr) {
2755template <
typename OperandType>
2756static void EmitIntegerArithmetic(FlowGraphCompiler*
compiler,
2759 const OperandType& right,
2760 compiler::Label* deopt) {
2763 __ addl(left, right);
2766 __ subl(left, right);
2768 case Token::kBIT_AND:
2769 __ andl(left, right);
2771 case Token::kBIT_OR:
2772 __ orl(left, right);
2774 case Token::kBIT_XOR:
2775 __ xorl(left, right);
2778 __ imull(left, right);
2787 if (
op_kind() == Token::kSHL) {
2795 compiler::Label* deopt =
nullptr;
2802 ASSERT(constant.IsSmi());
2803 const intptr_t
value = Smi::Cast(constant).Value();
2807 case Token::kBIT_AND:
2808 case Token::kBIT_OR:
2809 case Token::kBIT_XOR:
2811 const intptr_t imm =
2814 compiler::Immediate(imm), deopt);
2818 case Token::kTRUNCDIV: {
2821 const intptr_t shift_count =
2826 __ sarl(temp, compiler::Immediate(31));
2828 __ shrl(temp, compiler::Immediate(32 - shift_count));
2831 __ sarl(
left, compiler::Immediate(shift_count));
2841 const intptr_t kCountLimit = 0x1F;
2842 __ sarl(
left, compiler::Immediate(
2848 case Token::kUSHR: {
2867 if (deopt !=
nullptr) {
2887 __ sarl(
left, compiler::Immediate(31));
2901 if (
locs()->in(1).IsStackSlot()) {
2903 if (
op_kind() == Token::kMUL) {
2915 case Token::kBIT_AND:
2916 case Token::kBIT_OR:
2917 case Token::kBIT_XOR:
2919 if (
op_kind() == Token::kMUL) {
2925 case Token::kTRUNCDIV: {
2942 __ cmpl(
result, compiler::Immediate(0x40000000));
2971 compiler::Label
done;
2972 __ cmpl(
result, compiler::Immediate(0));
2978 __ cmpl(
right, compiler::Immediate(0));
2997 __ cmpl(
right, compiler::Immediate(0));
3002 const intptr_t kCountLimit = 0x1F;
3004 __ cmpl(
right, compiler::Immediate(kCountLimit));
3005 compiler::Label count_ok;
3007 __ movl(
right, compiler::Immediate(kCountLimit));
3016 case Token::kUSHR: {
3017 compiler::Label
done;
3037 compiler::Label shift_less_34;
3042 compiler::Label shift_less_64;
3054 __ subl(
right, compiler::Immediate(32));
3055 __ sarl(
left, compiler::Immediate(31));
3064 if (deopt !=
nullptr) {
3077 compiler::Label shift_less_30;
3113 const intptr_t kNumInputs = 2;
3114 if (
op_kind() == Token::kTRUNCDIV) {
3117 }
else if (
op_kind() == Token::kMOD) {
3120 }
else if ((
op_kind() == Token::kSHR) || (
op_kind() == Token::kUSHR)) {
3121 const intptr_t kNumTemps = 0;
3122 LocationSummary* summary =
new (zone)
3128 }
else if (
op_kind() == Token::kSHL) {
3130 LocationSummary* summary =
new (zone)
3140 const intptr_t kNumTemps = 0;
3141 LocationSummary* summary =
new (zone)
3145 if (constant !=
nullptr) {
3155static void EmitInt32ShiftLeft(FlowGraphCompiler*
compiler,
3156 BinaryInt32OpInstr* shift_left) {
3157 const LocationSummary& locs = *shift_left->
locs();
3161 compiler::Label* deopt =
3162 shift_left->CanDeoptimize()
3163 ?
compiler->AddDeoptStub(shift_left->deopt_id(),
3164 ICData::kDeoptBinarySmiOp)
3166 ASSERT(locs.in(1).IsConstant());
3168 const Object& constant = locs.in(1).constant();
3169 ASSERT(constant.IsSmi());
3171 const intptr_t kCountLimit = 0x1F;
3172 const intptr_t
value = Smi::Cast(constant).Value();
3174 if (shift_left->can_overflow()) {
3176 Register temp = locs.temp(0).reg();
3177 __ movl(temp, left);
3178 __ shll(left, compiler::Immediate(
value));
3179 __ sarl(left, compiler::Immediate(
value));
3180 __ cmpl(left, temp);
3184 __ shll(left, compiler::Immediate(
value));
3188 if (
op_kind() == Token::kSHL) {
3189 EmitInt32ShiftLeft(
compiler,
this);
3196 compiler::Label* deopt =
nullptr;
3203 ASSERT(constant.IsSmi());
3204 const intptr_t
value = Smi::Cast(constant).Value();
3209 case Token::kBIT_AND:
3210 case Token::kBIT_OR:
3211 case Token::kBIT_XOR:
3213 compiler::Immediate(
value), deopt);
3216 case Token::kTRUNCDIV: {
3223 const intptr_t kCountLimit = 0x1F;
3228 case Token::kUSHR: {
3243 if (deopt !=
nullptr) {
3262 __ sarl(
left, compiler::Immediate(31));
3275 if (
locs()->in(1).IsStackSlot()) {
3287 case Token::kBIT_AND:
3288 case Token::kBIT_OR:
3289 case Token::kBIT_XOR:
3301 const intptr_t kNumInputs = 2;
3302 const intptr_t kNumTemps = (
op_kind() == Token::kMUL) ? 1 : 0;
3303 LocationSummary* summary =
new (zone)
3305 if (
op_kind() == Token::kMUL) {
3322 case Token::kBIT_AND:
3323 case Token::kBIT_OR:
3324 case Token::kBIT_XOR:
3344 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid));
3345 const intptr_t kNumInputs = 2;
3347 (left_cid != kSmiCid) && (right_cid != kSmiCid);
3348 const intptr_t kNumTemps = need_temp ? 1 : 0;
3349 LocationSummary* summary =
new (zone)
3358 compiler::Label* deopt =
3364 if (this->
left()->definition() == this->
right()->definition()) {
3366 }
else if (left_cid == kSmiCid) {
3368 }
else if (right_cid == kSmiCid) {
3380 const intptr_t kNumInputs = 1;
3381 const intptr_t kNumTemps = 1;
3382 LocationSummary* summary =
new (zone) LocationSummary(
3396 out_reg,
locs()->temp(0).reg());
3399 case kUnboxedDouble:
3400 __ movsd(compiler::FieldAddress(out_reg, ValueOffset()),
value);
3404 __ movsd(compiler::FieldAddress(out_reg, ValueOffset()),
FpuTMP);
3406 case kUnboxedFloat32x4:
3407 case kUnboxedFloat64x2:
3408 case kUnboxedInt32x4:
3409 __ movups(compiler::FieldAddress(out_reg, ValueOffset()),
value);
3418 ASSERT(BoxCid() != kSmiCid);
3419 const bool needs_temp =
3423 const intptr_t kNumInputs = 1;
3424 const intptr_t kNumTemps = needs_temp ? 1 : 0;
3425 LocationSummary* summary =
new (zone)
3442void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler*
compiler) {
3446 case kUnboxedInt64: {
3449 __ movl(
result->At(0).reg(), compiler::FieldAddress(box, ValueOffset()));
3451 compiler::FieldAddress(box, ValueOffset() +
kWordSize));
3455 case kUnboxedDouble: {
3457 __ movsd(
result, compiler::FieldAddress(box, ValueOffset()));
3461 case kUnboxedFloat: {
3463 __ movsd(
result, compiler::FieldAddress(box, ValueOffset()));
3468 case kUnboxedFloat32x4:
3469 case kUnboxedFloat64x2:
3470 case kUnboxedInt32x4: {
3472 __ movups(
result, compiler::FieldAddress(box, ValueOffset()));
3482void UnboxInstr::EmitSmiConversion(FlowGraphCompiler*
compiler) {
3486 case kUnboxedInt64: {
3496 case kUnboxedDouble: {
3511void UnboxInstr::EmitLoadInt32FromBoxOrSmi(FlowGraphCompiler*
compiler) {
3517void UnboxInstr::EmitLoadInt64FromBoxOrSmi(FlowGraphCompiler*
compiler) {
3522 compiler::Label
done;
3531 const intptr_t kNumInputs = 1;
3534 LocationSummary* summary =
new (zone)
3541 LocationSummary* summary =
new (zone) LocationSummary(
3567 compiler::Label
done;
3572 __ testl(
value, compiler::Immediate(0xC0000000));
3585 locs()->temp(0).reg());
3590 __ sarl(
value, compiler::Immediate(31));
3595 compiler::Immediate(0));
3602 const intptr_t kNumInputs = 1;
3604 LocationSummary* summary =
new (zone)
3605 LocationSummary(zone, kNumInputs, kNumTemps,
3620 Register value_lo = value_pair->At(0).reg();
3622 __ movl(out_reg, value_lo);
3628 Register value_lo = value_pair->At(0).reg();
3629 Register value_hi = value_pair->At(1).reg();
3634 __ movl(out_reg, value_hi);
3638 compiler::Label not_smi,
done;
3642 __ addl(value_lo, compiler::Immediate(0x40000000));
3643 __ adcl(out_reg, compiler::Immediate(0));
3645 __ cmpl(value_lo, compiler::Immediate(0x80000000));
3646 __ sbbl(out_reg, compiler::Immediate(0));
3649 __ subl(value_lo, compiler::Immediate(0x40000000));
3650 __ movl(out_reg, value_lo);
3655 __ subl(value_lo, compiler::Immediate(0x40000000));
3658 out_reg,
locs()->temp(0).reg());
3668 const intptr_t kNumInputs = 1;
3669 intptr_t kNumTemps = 0;
3672 if ((value_cid != kSmiCid) && (value_cid != kMintCid) && !
is_truncating()) {
3679 LocationSummary* summary =
new (zone)
3682 for (
int i = 0;
i < kNumTemps;
i++) {
3685 summary->set_out(0, ((value_cid == kSmiCid) || (value_cid != kMintCid))
3691static void LoadInt32FromMint(FlowGraphCompiler*
compiler,
3693 const compiler::Address& lo,
3694 const compiler::Address& hi,
3696 compiler::Label* deopt) {
3698 if (deopt !=
nullptr) {
3701 __ sarl(temp, compiler::Immediate(31));
3712 compiler::Label* deopt =
nullptr;
3716 compiler::Label* out_of_range = !
is_truncating() ? deopt :
nullptr;
3721 if (value_cid == kSmiCid) {
3724 }
else if (value_cid == kMintCid) {
3728 compiler::FieldAddress(
value, hi_offset), temp, out_of_range);
3731 compiler::Label
done;
3738 compiler::Label
done;
3739 __ SmiUntagOrCheckClass(
value, kMintCid, temp, &
done);
3741 if (out_of_range !=
nullptr) {
3748 compiler::Address(
value,
TIMES_2, hi_offset), temp, out_of_range);
3756 const intptr_t kNumInputs = 2;
3757 const intptr_t kNumTemps = might_box ? 2 : 0;
3758 LocationSummary* summary =
new (zone) LocationSummary(
3759 zone, kNumInputs, kNumTemps,
3787 bool index_unboxed =
false;
3790 index_unboxed =
true;
3792 compiler::Address element_address =
3801 Register result1 = result_pair->At(0).reg();
3802 Register result2 = result_pair->At(1).reg();
3805 case kOneByteStringCid:
3807 __ movl(result1, element_address);
3808 __ xorl(result2, result2);
3810 case kTwoByteStringCid:
3812 __ movl(result1, element_address);
3813 __ xorl(result2, result2);
3822 case kOneByteStringCid:
3825 __ movzxb(
result, element_address);
3828 __ movzxw(
result, element_address);
3837 case kTwoByteStringCid:
3840 __ movzxw(
result, element_address);
3868 compiler::Label
done;
3869 __ testl(temp, compiler::Immediate(0xC0000000));
3875 compiler::Immediate(0));
3883 const intptr_t kNumInputs = 2;
3884 const intptr_t kNumTemps = 0;
3885 LocationSummary* summary =
new (zone)
3919 const intptr_t kNumInputs = 1;
3920 const intptr_t kNumTemps =
3921 op_kind() == MethodRecognizer::kDouble_getIsNegative
3923 : (
op_kind() == MethodRecognizer::kDouble_getIsInfinite ? 1 : 0);
3924 LocationSummary* summary =
new (zone)
3927 if (kNumTemps > 0) {
3929 if (
op_kind() == MethodRecognizer::kDouble_getIsNegative) {
3938 BranchLabels labels) {
3941 const bool is_negated = kind() != Token::kEQ;
3944 case MethodRecognizer::kDouble_getIsNaN: {
3948 case MethodRecognizer::kDouble_getIsInfinite: {
3950 compiler::Label check_upper;
3953 __ movl(temp, compiler::Address(
ESP, 0));
3955 __ cmpl(temp, compiler::Immediate(0));
3958 __ jmp(is_negated ? labels.true_label : labels.false_label);
3964 __ andl(temp, compiler::Immediate(0x7FFFFFFF));
3966 __ cmpl(temp, compiler::Immediate(0x7FF00000));
3969 case MethodRecognizer::kDouble_getIsNegative: {
3972 compiler::Label not_zero;
3973 __ xorpd(temp_fpu, temp_fpu);
3976 __ j(
PARITY_EVEN, is_negated ? labels.true_label : labels.false_label);
3979 __ testl(temp, compiler::Immediate(1));
3989#define DEFINE_EMIT(Name, Args) \
3990 static void Emit##Name(FlowGraphCompiler* compiler, SimdOpInstr* instr, \
3991 PP_APPLY(PP_UNPACK, Args))
3993#define SIMD_OP_FLOAT_ARITH(V, Name, op) \
3994 V(Float32x4##Name, op##ps) \
3995 V(Float64x2##Name, op##pd)
3997#define SIMD_OP_SIMPLE_BINARY(V) \
3998 SIMD_OP_FLOAT_ARITH(V, Add, add) \
3999 SIMD_OP_FLOAT_ARITH(V, Sub, sub) \
4000 SIMD_OP_FLOAT_ARITH(V, Mul, mul) \
4001 SIMD_OP_FLOAT_ARITH(V, Div, div) \
4002 SIMD_OP_FLOAT_ARITH(V, Min, min) \
4003 SIMD_OP_FLOAT_ARITH(V, Max, max) \
4004 V(Int32x4Add, addpl) \
4005 V(Int32x4Sub, subpl) \
4006 V(Int32x4BitAnd, andps) \
4007 V(Int32x4BitOr, orps) \
4008 V(Int32x4BitXor, xorps) \
4009 V(Float32x4Equal, cmppseq) \
4010 V(Float32x4NotEqual, cmppsneq) \
4011 V(Float32x4LessThan, cmppslt) \
4012 V(Float32x4LessThanOrEqual, cmppsle)
4014DEFINE_EMIT(SimdBinaryOp,
4016 switch (instr->kind()) {
4017#define EMIT(Name, op) \
4018 case SimdOpInstr::k##Name: \
4019 __ op(left, right); \
4021 SIMD_OP_SIMPLE_BINARY(EMIT)
4023 case SimdOpInstr::kFloat32x4Scale:
4024 __ cvtsd2ss(left, left);
4025 __ shufps(left, left, compiler::Immediate(0x00));
4026 __ mulps(left, right);
4028 case SimdOpInstr::kFloat32x4ShuffleMix:
4029 case SimdOpInstr::kInt32x4ShuffleMix:
4030 __ shufps(left, right, compiler::Immediate(instr->mask()));
4032 case SimdOpInstr::kFloat64x2FromDoubles:
4036 __ shufpd(left, right, compiler::Immediate(0x0));
4038 case SimdOpInstr::kFloat64x2Scale:
4039 __ shufpd(right, right, compiler::Immediate(0x00));
4040 __ mulpd(left, right);
4042 case SimdOpInstr::kFloat64x2WithX:
4043 case SimdOpInstr::kFloat64x2WithY: {
4046 (SimdOpInstr::kFloat64x2WithX + 1));
4047 const intptr_t lane_index = instr->kind() - SimdOpInstr::kFloat64x2WithX;
4048 ASSERT(0 <= lane_index && lane_index < 2);
4050 __ movups(compiler::Address(
ESP, 0), left);
4052 __ movups(left, compiler::Address(
ESP, 0));
4056 case SimdOpInstr::kFloat32x4WithX:
4057 case SimdOpInstr::kFloat32x4WithY:
4058 case SimdOpInstr::kFloat32x4WithZ:
4059 case SimdOpInstr::kFloat32x4WithW: {
4064 SimdOpInstr::kFloat32x4WithY == (SimdOpInstr::kFloat32x4WithX + 1) &&
4065 SimdOpInstr::kFloat32x4WithZ == (SimdOpInstr::kFloat32x4WithX + 2) &&
4066 SimdOpInstr::kFloat32x4WithW == (SimdOpInstr::kFloat32x4WithX + 3));
4067 const intptr_t lane_index = instr->kind() - SimdOpInstr::kFloat32x4WithX;
4068 ASSERT(0 <= lane_index && lane_index < 4);
4069 __ cvtsd2ss(left, left);
4071 __ movups(compiler::Address(
ESP, 0), right);
4073 __ movups(left, compiler::Address(
ESP, 0));
4082#define SIMD_OP_SIMPLE_UNARY(V) \
4083 SIMD_OP_FLOAT_ARITH(V, Sqrt, sqrt) \
4084 SIMD_OP_FLOAT_ARITH(V, Negate, negate) \
4085 SIMD_OP_FLOAT_ARITH(V, Abs, abs) \
4086 V(Float32x4Reciprocal, reciprocalps) \
4087 V(Float32x4ReciprocalSqrt, rsqrtps)
4093 switch (instr->kind()) {
4094#define EMIT(Name, op) \
4095 case SimdOpInstr::k##Name: \
4098 SIMD_OP_SIMPLE_UNARY(EMIT)
4100 case SimdOpInstr::kFloat32x4GetX:
4104 case SimdOpInstr::kFloat32x4GetY:
4108 case SimdOpInstr::kFloat32x4GetZ:
4112 case SimdOpInstr::kFloat32x4GetW:
4116 case SimdOpInstr::kFloat32x4Shuffle:
4117 case SimdOpInstr::kInt32x4Shuffle:
4118 __ shufps(
value,
value, compiler::Immediate(instr->mask()));
4120 case SimdOpInstr::kFloat32x4Splat:
4126 case SimdOpInstr::kFloat64x2ToFloat32x4:
4129 case SimdOpInstr::kFloat32x4ToFloat64x2:
4132 case SimdOpInstr::kFloat32x4ToInt32x4:
4133 case SimdOpInstr::kInt32x4ToFloat32x4:
4138 case SimdOpInstr::kFloat64x2GetX:
4141 case SimdOpInstr::kFloat64x2GetY:
4144 case SimdOpInstr::kFloat64x2Splat:
4153 switch (instr->kind()) {
4154 case SimdOpInstr::kFloat32x4GetSignMask:
4155 case SimdOpInstr::kInt32x4GetSignMask:
4158 case SimdOpInstr::kFloat64x2GetSignMask:
4168 Float32x4FromDoubles,
4174 for (intptr_t
i = 0;
i < 4;
i++) {
4175 __ cvtsd2ss(
out, instr->locs()->in(
i).fpu_reg());
4178 __ movups(
out, compiler::Address(
ESP, 0));
4190DEFINE_EMIT(Float32x4Clamp,
4195 __ minps(left, upper);
4199DEFINE_EMIT(Float64x2Clamp,
4204 __ minpd(left, upper);
4208DEFINE_EMIT(Int32x4FromInts,
4212 for (intptr_t
i = 0;
i < 4;
i++) {
4219DEFINE_EMIT(Int32x4FromBools,
4223 for (intptr_t
i = 0;
i < 4;
i++) {
4224 compiler::Label store_false,
done;
4228 compiler::Immediate(0xFFFFFFFF));
4241 SimdOpInstr::kInt32x4GetFlagY == (SimdOpInstr::kInt32x4GetFlagX + 1) &&
4242 SimdOpInstr::kInt32x4GetFlagZ == (SimdOpInstr::kInt32x4GetFlagX + 2) &&
4243 SimdOpInstr::kInt32x4GetFlagW == (SimdOpInstr::kInt32x4GetFlagX + 3));
4244 const intptr_t lane_index = instr->kind() - SimdOpInstr::kInt32x4GetFlagX;
4245 ASSERT(0 <= lane_index && lane_index < 4);
4260 compiler::Address(
THR,
EDX,
TIMES_4, Thread::bool_true_offset()));
4264DEFINE_EMIT(Int32x4WithFlag,
4268 Temp<Fixed<Register, EDX> > temp)) {
4270 SimdOpInstr::kInt32x4WithFlagY == (SimdOpInstr::kInt32x4WithFlagX + 1) &&
4271 SimdOpInstr::kInt32x4WithFlagZ == (SimdOpInstr::kInt32x4WithFlagX + 2) &&
4272 SimdOpInstr::kInt32x4WithFlagW == (SimdOpInstr::kInt32x4WithFlagX + 3));
4273 const intptr_t lane_index = instr->kind() - SimdOpInstr::kInt32x4WithFlagX;
4274 ASSERT(0 <= lane_index && lane_index < 4);
4278 __ movups(compiler::Address(
ESP, 0), mask);
4289 __ movups(mask, compiler::Address(
ESP, 0));
4293DEFINE_EMIT(Int32x4Select,
4298 Temp<XmmRegister> temp)) {
4300 __ movaps(temp, mask);
4304 __ andps(mask, trueValue);
4306 __ andps(temp, falseValue);
4308 __ orps(mask, temp);
4317#define SIMD_OP_VARIANTS(CASE, ____, SIMPLE) \
4318 SIMD_OP_SIMPLE_BINARY(CASE) \
4319 CASE(Float32x4Scale) \
4320 CASE(Float32x4ShuffleMix) \
4321 CASE(Int32x4ShuffleMix) \
4322 CASE(Float64x2FromDoubles) \
4323 CASE(Float64x2Scale) \
4324 CASE(Float64x2WithX) \
4325 CASE(Float64x2WithY) \
4326 CASE(Float32x4WithX) \
4327 CASE(Float32x4WithY) \
4328 CASE(Float32x4WithZ) \
4329 CASE(Float32x4WithW) \
4330 ____(SimdBinaryOp) \
4331 SIMD_OP_SIMPLE_UNARY(CASE) \
4332 CASE(Float32x4GetX) \
4333 CASE(Float32x4GetY) \
4334 CASE(Float32x4GetZ) \
4335 CASE(Float32x4GetW) \
4336 CASE(Float32x4Shuffle) \
4337 CASE(Int32x4Shuffle) \
4338 CASE(Float32x4Splat) \
4339 CASE(Float32x4ToFloat64x2) \
4340 CASE(Float64x2ToFloat32x4) \
4341 CASE(Int32x4ToFloat32x4) \
4342 CASE(Float32x4ToInt32x4) \
4343 CASE(Float64x2GetX) \
4344 CASE(Float64x2GetY) \
4345 CASE(Float64x2Splat) \
4347 CASE(Float32x4GetSignMask) \
4348 CASE(Int32x4GetSignMask) \
4349 CASE(Float64x2GetSignMask) \
4350 ____(SimdGetSignMask) \
4351 SIMPLE(Float32x4FromDoubles) \
4352 SIMPLE(Int32x4FromInts) \
4353 SIMPLE(Int32x4FromBools) \
4354 SIMPLE(Float32x4Zero) \
4355 SIMPLE(Float64x2Zero) \
4356 SIMPLE(Float32x4Clamp) \
4357 SIMPLE(Float64x2Clamp) \
4358 CASE(Int32x4GetFlagX) \
4359 CASE(Int32x4GetFlagY) \
4360 CASE(Int32x4GetFlagZ) \
4361 CASE(Int32x4GetFlagW) \
4362 ____(Int32x4GetFlag) \
4363 CASE(Int32x4WithFlagX) \
4364 CASE(Int32x4WithFlagY) \
4365 CASE(Int32x4WithFlagZ) \
4366 CASE(Int32x4WithFlagW) \
4367 ____(Int32x4WithFlag) \
4368 SIMPLE(Int32x4Select)
4372#define CASE(Name, ...) case k##Name:
4374 return MakeLocationSummaryFromEmitter(zone, this, &Emit##Name);
4375#define SIMPLE(Name) CASE(Name) EMIT(Name)
4380 case SimdOpInstr::kFloat32x4GreaterThan:
4381 case SimdOpInstr::kFloat32x4GreaterThanOrEqual:
4392#define CASE(Name, ...) case k##Name:
4394 InvokeEmitter(compiler, this, &Emit##Name); \
4396#define SIMPLE(Name) CASE(Name) EMIT(Name)
4401 case SimdOpInstr::kFloat32x4GreaterThan:
4402 case SimdOpInstr::kFloat32x4GreaterThanOrEqual:
4414 const intptr_t kNumTemps = 0;
4415 LocationSummary* summary =
new (zone)
4426 compiler::LeafRuntimeScope rt(
compiler->assembler(),
4439 const intptr_t kNumInputs = 2;
4440 const intptr_t kNumTemps = 1;
4441 LocationSummary* summary =
new (zone)
4452 const intptr_t kNumInputs = 2;
4453 const intptr_t kNumTemps = 0;
4454 LocationSummary* summary =
new (zone)
4465 (
op_kind() == MethodRecognizer::kMathMax));
4466 const bool is_min = (
op_kind() == MethodRecognizer::kMathMin);
4477 is_min ? TokenKindToDoubleCondition(Token::kLT)
4478 : TokenKindToDoubleCondition(Token::kGT);
4485 static double kNaN = NAN;
4491 compiler::Label left_is_negative;
4499 __ testl(temp, compiler::Immediate(1));
4528 const intptr_t kNumInputs = 1;
4537 case Token::kNEGATE: {
4538 compiler::Label* deopt =
4544 case Token::kBIT_NOT:
4556 const intptr_t kNumInputs = 1;
4557 const intptr_t kNumTemps = 0;
4558 LocationSummary* summary =
new (zone)
4570 case Token::kNEGATE:
4576 case Token::kSQUARE:
4579 case Token::kTRUNCATE:
4585 case Token::kCEILING:
4595 const intptr_t kNumInputs = 1;
4596 const intptr_t kNumTemps = 0;
4597 LocationSummary*
result =
new (zone)
4612 const intptr_t kNumInputs = 1;
4613 const intptr_t kNumTemps = 0;
4614 LocationSummary*
result =
new (zone)
4630 const intptr_t kNumInputs = 1;
4631 const intptr_t kNumTemps = 0;
4632 LocationSummary*
result =
new (zone)
4642 Register in_lo = pair->At(0).reg();
4643 Register in_hi = pair->At(1).reg();
4652 __ fildl(compiler::Address(
ESP, 0));
4654 __ fstpl(compiler::Address(
ESP, 0));
4663 const intptr_t kNumInputs = 1;
4664 const intptr_t kNumTemps = 0;
4665 LocationSummary*
result =
new (zone) LocationSummary(
4677 DoubleToIntegerSlowPath* slow_path =
4678 new DoubleToIntegerSlowPath(
this, value_double);
4679 compiler->AddSlowPathCode(slow_path);
4681 __ cvttsd2si(
result, value_double);
4684 __ cmpl(
result, compiler::Immediate(0xC0000000));
4687 __ Bind(slow_path->exit_label());
4692 const intptr_t kNumInputs = 1;
4693 const intptr_t kNumTemps = 0;
4694 LocationSummary*
result =
new (zone)
4702 compiler::Label* deopt =
4708 __ cmpl(
result, compiler::Immediate(0xC0000000));
4715 const intptr_t kNumInputs = 1;
4716 const intptr_t kNumTemps = 0;
4717 LocationSummary*
result =
new (zone)
4725 __ cvtsd2ss(
locs()->
out(0).fpu_reg(),
locs()->in(0).fpu_reg());
4730 const intptr_t kNumInputs = 1;
4731 const intptr_t kNumTemps = 0;
4732 LocationSummary*
result =
new (zone)
4740 __ cvtss2sd(
locs()->
out(0).fpu_reg(),
locs()->in(0).fpu_reg());
4756 const intptr_t kNumTemps =
4758 LocationSummary*
result =
new (zone)
4794static void InvokeDoublePow(FlowGraphCompiler*
compiler,
4795 InvokeMathCFunctionInstr* instr) {
4796 ASSERT(instr->recognized_kind() == MethodRecognizer::kMathDoublePow);
4797 const intptr_t kInputCount = 2;
4798 ASSERT(instr->InputCount() == kInputCount);
4799 LocationSummary* locs = instr->locs();
4808 __ xorps(zero_temp, zero_temp);
4812 compiler::Label check_base, skip_call;
4814 __ comisd(exp, zero_temp);
4820 compiler::Label return_base;
4827 compiler::Label return_base_times_2;
4846 __ Bind(&return_base_times_2);
4856 compiler::Label return_nan;
4862 compiler::Label try_sqrt;
4870 compiler::Label do_pow, return_zero;
4886 __ comisd(
base, zero_temp);
4898 compiler::LeafRuntimeScope rt(
compiler->assembler(),
4901 for (intptr_t
i = 0;
i < kInputCount;
i++) {
4904 rt.Call(instr->TargetFunction(), kInputCount);
4905 __ fstpl(compiler::Address(
ESP, 0));
4906 __ movsd(locs->out(0).fpu_reg(), compiler::Address(
ESP, 0));
4918 compiler::LeafRuntimeScope rt(
compiler->assembler(),
4923 locs()->in(
i).fpu_reg());
4926 __ fstpl(compiler::Address(
ESP, 0));
4927 __ movsd(
locs()->
out(0).fpu_reg(), compiler::Address(
ESP, 0));
4935 const intptr_t kNumInputs = 1;
4936 LocationSummary* summary =
5001 const intptr_t kNumInputs = 2;
5002 const intptr_t kNumTemps = 0;
5003 LocationSummary* summary =
new (zone)
5016 compiler::Label* deopt =
5022 Register result1 = pair->At(0).reg();
5023 Register result2 = pair->At(1).reg();
5026 __ testl(right, right);
5042 __ cmpl(
EAX, compiler::Immediate(0x40000000));
5053 compiler::Label
done;
5054 __ cmpl(
EDX, compiler::Immediate(0));
5059 __ cmpl(right, compiler::Immediate(0));
5061 __ addl(
EDX, right);
5064 __ subl(
EDX, right);
5065 }
else if (divisor_range()->IsPositive()) {
5067 __ addl(
EDX, right);
5070 __ subl(
EDX, right);
5079static void EmitHashIntegerCodeSequence(FlowGraphCompiler*
compiler,
5083 __ movl(
EDX, compiler::Immediate(0x2d51));
5086 __ movl(
EAX, value_hi);
5087 __ movl(value_hi,
EDX);
5088 __ movl(
EDX, compiler::Immediate(0x2d51));
5090 __ addl(
EAX, value_hi);
5094 __ andl(
EAX, compiler::Immediate(0x3fffffff));
5099 const intptr_t kNumInputs = 1;
5100 const intptr_t kNumTemps = 4;
5101 LocationSummary* summary =
new (zone)
5120 ASSERT(result_pair->At(0).reg() ==
EAX);
5121 ASSERT(result_pair->At(1).reg() ==
EDX);
5124 compiler::Label hash_double, try_convert;
5128 __ pextrd(temp,
value, compiler::Immediate(1));
5135 __ andl(temp, compiler::Immediate(0x7FF00000));
5136 __ cmpl(temp, compiler::Immediate(0x7FF00000));
5139 compiler::Label slow_path;
5143 __ cmpl(
EAX, compiler::Immediate(0x80000000));
5145 __ cvtsi2sd(temp_double,
EAX);
5146 __ comisd(
value, temp_double);
5151 compiler::Label hash_integer,
done;
5163 compiler::LeafRuntimeScope rt(
5170 rt.Call(kTryDoubleAsIntegerRuntimeEntry, 1);
5174 __ j(
ZERO, &hash_double);
5182 __ jmp(&hash_integer);
5186 __ pextrd(
EAX,
value, compiler::Immediate(0));
5187 __ pextrd(temp,
value, compiler::Immediate(1));
5191 __ movl(
EAX, compiler::Address(
ESP, 0));
5204 const intptr_t kNumInputs = 1;
5205 const intptr_t kNumTemps = 3;
5206 LocationSummary* summary =
new (zone)
5229 __ LoadFieldFromOffset(temp,
EAX,
5245 EmitHashIntegerCodeSequence(
compiler,
EAX, temp, temp1);
5262 const intptr_t kNumInputs = 1;
5263 const bool need_mask_temp =
IsBitTest();
5264 const intptr_t kNumTemps = !
IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0;
5265 LocationSummary* summary =
new (zone)
5270 if (need_mask_temp) {
5278 compiler::Label* deopt) {
5279 const compiler::Immediate& raw_null =
5280 compiler::Immediate(
static_cast<intptr_t
>(
Object::null()));
5281 __ cmpl(
locs()->in(0).reg(), raw_null);
5291 compiler::Label* deopt) {
5293 __ subl(biased_cid, compiler::Immediate(
min));
5294 __ cmpl(biased_cid, compiler::Immediate(
max -
min));
5298 __ movl(mask_reg, compiler::Immediate(mask));
5299 __ bt(mask_reg, biased_cid);
5303int CheckClassInstr::EmitCheckCid(FlowGraphCompiler*
compiler,
5308 compiler::Label* is_ok,
5309 compiler::Label* deopt,
5310 bool use_near_jump) {
5313 if (cid_start == cid_end) {
5314 __ cmpl(biased_cid, compiler::Immediate(cid_start - bias));
5320 __ addl(biased_cid, compiler::Immediate(bias - cid_start));
5322 __ cmpl(biased_cid, compiler::Immediate(cid_end - cid_start));
5328 __ j(no_match, deopt);
5330 if (use_near_jump) {
5341 const intptr_t kNumInputs = 1;
5342 const intptr_t kNumTemps = 0;
5343 LocationSummary* summary =
new (zone)
5351 compiler::Label* deopt =
5353 __ BranchIfNotSmi(
value, deopt);
5357 ThrowErrorSlowPathCode* slow_path =
new NullErrorSlowPath(
this);
5358 compiler->AddSlowPathCode(slow_path);
5363 __ CompareObject(value_reg, Object::null_object());
5364 __ BranchIf(
EQUAL, slow_path->entry_label());
5369 const intptr_t kNumInputs = 1;
5370 const intptr_t kNumTemps = 0;
5371 LocationSummary* summary =
new (zone)
5380 compiler::Label* deopt =
5382 if (cids_.IsSingleCid()) {
5397 const intptr_t kNumInputs = 2;
5398 const intptr_t kNumTemps = 0;
5399 LocationSummary*
locs =
new (zone)
5412 compiler::Label* deopt =
5418 if (length_loc.IsConstant() && index_loc.IsConstant()) {
5419 ASSERT((Smi::Cast(length_loc.constant()).Value() <=
5420 Smi::Cast(index_loc.constant()).Value()) ||
5421 (Smi::Cast(index_loc.constant()).Value() < 0));
5429 if (length_loc.IsConstant()) {
5431 if (index_cid != kSmiCid) {
5432 __ BranchIfNotSmi(
index, deopt);
5434 const Smi&
length = Smi::Cast(length_loc.constant());
5439 __ cmpl(
index, compiler::Immediate(
static_cast<int32_t
>(
length.ptr())));
5442 }
else if (index_loc.IsConstant()) {
5443 const Smi&
index = Smi::Cast(index_loc.constant());
5444 if (length_loc.IsStackSlot()) {
5446 __ cmpl(
length, compiler::Immediate(
static_cast<int32_t
>(
index.ptr())));
5449 __ cmpl(
length, compiler::Immediate(
static_cast<int32_t
>(
index.ptr())));
5452 }
else if (length_loc.IsStackSlot()) {
5455 if (index_cid != kSmiCid) {
5456 __ BranchIfNotSmi(
index, deopt);
5463 if (index_cid != kSmiCid) {
5464 __ BranchIfNotSmi(
index, deopt);
5473 const intptr_t kNumInputs = 1;
5474 const intptr_t kNumTemps = 1;
5475 LocationSummary*
locs =
new (zone) LocationSummary(
5476 zone, kNumInputs, kNumTemps,
5485 WriteErrorSlowPath* slow_path =
new WriteErrorSlowPath(
this);
5487 compiler->AddSlowPathCode(slow_path);
5489 compiler::FieldAddress(
locs()->in(0).reg(),
5491 __ testl(temp, compiler::Immediate(
5498 const intptr_t kNumInputs = 2;
5500 case Token::kBIT_AND:
5501 case Token::kBIT_OR:
5502 case Token::kBIT_XOR:
5505 const intptr_t kNumTemps = 0;
5506 LocationSummary* summary =
new (zone) LocationSummary(
5516 const intptr_t kNumTemps = 1;
5517 LocationSummary* summary =
new (zone) LocationSummary(
5535 Register left_lo = left_pair->At(0).reg();
5536 Register left_hi = left_pair->At(1).reg();
5538 Register right_lo = right_pair->At(0).reg();
5539 Register right_hi = right_pair->At(1).reg();
5541 Register out_lo = out_pair->At(0).reg();
5542 Register out_hi = out_pair->At(1).reg();
5543 ASSERT(out_lo == left_lo);
5544 ASSERT(out_hi == left_hi);
5549 case Token::kBIT_AND:
5550 __ andl(left_lo, right_lo);
5551 __ andl(left_hi, right_hi);
5553 case Token::kBIT_OR:
5554 __ orl(left_lo, right_lo);
5555 __ orl(left_hi, right_hi);
5557 case Token::kBIT_XOR:
5558 __ xorl(left_lo, right_lo);
5559 __ xorl(left_hi, right_hi);
5563 if (
op_kind() == Token::kADD) {
5564 __ addl(left_lo, right_lo);
5565 __ adcl(left_hi, right_hi);
5567 __ subl(left_lo, right_lo);
5568 __ sbbl(left_hi, right_hi);
5579 __ movl(temp, left_lo);
5580 __ imull(left_hi, right_lo);
5581 __ imull(temp, right_hi);
5582 __ addl(temp, left_hi);
5595static void EmitShiftInt64ByConstant(FlowGraphCompiler*
compiler,
5599 const Object& right) {
5600 const int64_t shift = Integer::Cast(right).AsInt64Value();
5605 __ movl(left_lo, left_hi);
5606 __ sarl(left_hi, compiler::Immediate(31));
5608 __ sarl(left_lo, compiler::Immediate(shift > 63 ? 31 : shift - 32));
5611 __ shrdl(left_lo, left_hi, compiler::Immediate(shift));
5612 __ sarl(left_hi, compiler::Immediate(shift));
5616 case Token::kUSHR: {
5619 __ movl(left_lo, left_hi);
5620 __ xorl(left_hi, left_hi);
5622 __ shrl(left_lo, compiler::Immediate(shift - 32));
5625 __ shrdl(left_lo, left_hi, compiler::Immediate(shift));
5626 __ shrl(left_hi, compiler::Immediate(shift));
5633 __ movl(left_hi, left_lo);
5634 __ xorl(left_lo, left_lo);
5636 __ shll(left_hi, compiler::Immediate(shift - 32));
5639 __ shldl(left_hi, left_lo, compiler::Immediate(shift));
5640 __ shll(left_lo, compiler::Immediate(shift));
5649static void EmitShiftInt64ByECX(FlowGraphCompiler*
compiler,
5655 compiler::Label
done, large_shift;
5658 __ cmpl(
ECX, compiler::Immediate(31));
5661 __ shrdl(left_lo, left_hi,
ECX);
5662 __ sarl(left_hi,
ECX);
5667 __ movl(left_lo, left_hi);
5668 __ sarl(left_hi, compiler::Immediate(31));
5669 __ sarl(left_lo,
ECX);
5672 case Token::kUSHR: {
5673 __ cmpl(
ECX, compiler::Immediate(31));
5676 __ shrdl(left_lo, left_hi,
ECX);
5677 __ shrl(left_hi,
ECX);
5682 __ movl(left_lo, left_hi);
5683 __ xorl(left_hi, left_hi);
5684 __ shrl(left_lo,
ECX);
5688 __ cmpl(
ECX, compiler::Immediate(31));
5691 __ shldl(left_hi, left_lo,
ECX);
5692 __ shll(left_lo,
ECX);
5697 __ movl(left_hi, left_lo);
5698 __ xorl(left_lo, left_lo);
5699 __ shll(left_hi,
ECX);
5708static void EmitShiftUint32ByConstant(FlowGraphCompiler*
compiler,
5711 const Object& right) {
5712 const int64_t shift = Integer::Cast(right).AsInt64Value();
5714 __ xorl(left, left);
5718 case Token::kUSHR: {
5719 __ shrl(left, compiler::Immediate(shift));
5723 __ shll(left, compiler::Immediate(shift));
5732static void EmitShiftUint32ByECX(FlowGraphCompiler*
compiler,
5737 case Token::kUSHR: {
5750class ShiftInt64OpSlowPath :
public ThrowErrorSlowPathCode {
5752 explicit ShiftInt64OpSlowPath(ShiftInt64OpInstr* instruction)
5753 : ThrowErrorSlowPathCode(instruction,
5754 kArgumentErrorUnboxedInt64RuntimeEntry) {}
5756 const char*
name()
override {
return "int64 shift"; }
5758 void EmitCodeAtSlowPathEntry(FlowGraphCompiler*
compiler)
override {
5759 PairLocation* right_pair = instruction()->locs()->in(1).AsPairLocation();
5760 Register right_lo = right_pair->At(0).reg();
5761 Register right_hi = right_pair->At(1).reg();
5762 PairLocation* out_pair = instruction()->locs()->out(0).AsPairLocation();
5763 Register out_lo = out_pair->At(0).reg();
5764 Register out_hi = out_pair->At(1).reg();
5766 PairLocation* left_pair = instruction()->locs()->in(0).AsPairLocation();
5767 Register left_lo = left_pair->At(0).reg();
5768 Register left_hi = left_pair->At(1).reg();
5769 ASSERT(out_lo == left_lo);
5770 ASSERT(out_hi == left_hi);
5773 compiler::Label throw_error;
5774 __ testl(right_hi, right_hi);
5777 switch (instruction()->AsShiftInt64Op()->op_kind()) {
5779 __ sarl(out_hi, compiler::Immediate(31));
5780 __ movl(out_lo, out_hi);
5784 __ xorl(out_lo, out_lo);
5785 __ xorl(out_hi, out_hi);
5791 __ jmp(exit_label());
5800 __ movl(compiler::Address(
5803 __ movl(compiler::Address(
5812 const intptr_t kNumInputs = 2;
5813 const intptr_t kNumTemps = 0;
5814 LocationSummary* summary =
new (zone) LocationSummary(
5832 Register left_lo = left_pair->At(0).reg();
5833 Register left_hi = left_pair->At(1).reg();
5835 Register out_lo = out_pair->At(0).reg();
5836 Register out_hi = out_pair->At(1).reg();
5837 ASSERT(out_lo == left_lo);
5838 ASSERT(out_hi == left_hi);
5843 locs()->in(1).constant());
5850 ShiftInt64OpSlowPath* slow_path =
nullptr;
5852 slow_path =
new (
Z) ShiftInt64OpSlowPath(
this);
5853 compiler->AddSlowPathCode(slow_path);
5854 __ testl(right_hi, right_hi);
5856 __ cmpl(
ECX, compiler::Immediate(kShiftCountLimit));
5857 __ j(
ABOVE, slow_path->entry_label());
5862 if (slow_path !=
nullptr) {
5863 __ Bind(slow_path->exit_label());
5871 const intptr_t kNumInputs = 2;
5872 const intptr_t kNumTemps = 0;
5873 LocationSummary* summary =
new (zone)
5884 Register left_lo = left_pair->At(0).reg();
5885 Register left_hi = left_pair->At(1).reg();
5887 Register out_lo = out_pair->At(0).reg();
5888 Register out_hi = out_pair->At(1).reg();
5889 ASSERT(out_lo == left_lo);
5890 ASSERT(out_hi == left_hi);
5895 locs()->in(1).constant());
5903 compiler::Label* deopt =
5905 __ cmpl(
ECX, compiler::Immediate(kShiftCountLimit));
5913class ShiftUint32OpSlowPath :
public ThrowErrorSlowPathCode {
5915 explicit ShiftUint32OpSlowPath(ShiftUint32OpInstr* instruction)
5916 : ThrowErrorSlowPathCode(instruction,
5917 kArgumentErrorUnboxedInt64RuntimeEntry) {}
5919 const char*
name()
override {
return "uint32 shift"; }
5921 void EmitCodeAtSlowPathEntry(FlowGraphCompiler*
compiler)
override {
5922 PairLocation* right_pair = instruction()->locs()->in(1).AsPairLocation();
5923 Register right_lo = right_pair->At(0).reg();
5924 Register right_hi = right_pair->At(1).reg();
5925 const Register out = instruction()->locs()->out(0).reg();
5926 ASSERT(
out == instruction()->locs()->in(0).reg());
5928 compiler::Label throw_error;
5929 __ testl(right_hi, right_hi);
5933 __ jmp(exit_label());
5942 __ movl(compiler::Address(
5945 __ movl(compiler::Address(
5954 const intptr_t kNumInputs = 2;
5955 const intptr_t kNumTemps = 0;
5956 LocationSummary* summary =
new (zone) LocationSummary(
5978 locs()->in(1).constant());
5985 ShiftUint32OpSlowPath* slow_path =
nullptr;
5987 slow_path =
new (
Z) ShiftUint32OpSlowPath(
this);
5988 compiler->AddSlowPathCode(slow_path);
5990 __ testl(right_hi, right_hi);
5992 __ cmpl(
ECX, compiler::Immediate(kUint32ShiftCountLimit));
5993 __ j(
ABOVE, slow_path->entry_label());
5998 if (slow_path !=
nullptr) {
5999 __ Bind(slow_path->exit_label());
6007 const intptr_t kNumInputs = 2;
6008 const intptr_t kNumTemps = 0;
6009 LocationSummary* summary =
new (zone)
6025 locs()->in(1).constant());
6034 compiler::Label* deopt =
6041 compiler::Label cont;
6042 __ cmpl(
ECX, compiler::Immediate(kUint32ShiftCountLimit));
6056 const intptr_t kNumInputs = 1;
6057 const intptr_t kNumTemps = 0;
6058 LocationSummary* summary =
new (zone)
6068 Register left_lo = left_pair->At(0).reg();
6069 Register left_hi = left_pair->At(1).reg();
6071 Register out_lo = out_pair->At(0).reg();
6072 Register out_hi = out_pair->At(1).reg();
6073 ASSERT(out_lo == left_lo);
6074 ASSERT(out_hi == left_hi);
6076 case Token::kBIT_NOT:
6080 case Token::kNEGATE:
6082 __ adcl(left_hi, compiler::Immediate(0));
6092 const intptr_t kNumInputs = 1;
6093 const intptr_t kNumTemps = 0;
6094 LocationSummary* summary =
new (zone)
6112 const intptr_t kNumInputs = 1;
6113 const intptr_t kNumTemps = 0;
6114 LocationSummary* summary =
new (zone)
6117 if (
from() == kUntagged ||
to() == kUntagged) {
6118 ASSERT((
from() == kUntagged &&
to() == kUnboxedInt32) ||
6119 (
from() == kUntagged &&
to() == kUnboxedUint32) ||
6120 (
from() == kUnboxedInt32 &&
to() == kUntagged) ||
6121 (
from() == kUnboxedUint32 &&
to() == kUntagged));
6125 }
else if ((
from() == kUnboxedInt32 ||
from() == kUnboxedUint32) &&
6126 (
to() == kUnboxedInt32 ||
to() == kUnboxedUint32)) {
6129 }
else if (
from() == kUnboxedInt64) {
6135 }
else if (
from() == kUnboxedUint32) {
6139 }
else if (
from() == kUnboxedInt32) {
6149 const bool is_nop_conversion =
6150 (
from() == kUntagged &&
to() == kUnboxedInt32) ||
6151 (
from() == kUntagged &&
to() == kUnboxedUint32) ||
6152 (
from() == kUnboxedInt32 &&
to() == kUntagged) ||
6153 (
from() == kUnboxedUint32 &&
to() == kUntagged);
6154 if (is_nop_conversion) {
6159 if (
from() == kUnboxedInt32 &&
to() == kUnboxedUint32) {
6162 }
else if (
from() == kUnboxedUint32 &&
to() == kUnboxedInt32) {
6166 compiler::Label* deopt =
6171 }
else if (
from() == kUnboxedInt64) {
6176 ASSERT(
to() == kUnboxedInt32 ||
to() == kUnboxedUint32);
6178 Register in_lo = in_pair->At(0).reg();
6179 Register in_hi = in_pair->At(1).reg();
6182 __ movl(
out, in_lo);
6184 compiler::Label* deopt =
6186 __ sarl(in_lo, compiler::Immediate(31));
6187 __ cmpl(in_lo, in_hi);
6190 }
else if (
from() == kUnboxedUint32) {
6194 Register out_lo = out_pair->At(0).reg();
6195 Register out_hi = out_pair->At(1).reg();
6197 __ movl(out_lo, in);
6199 __ xorl(out_hi, out_hi);
6200 }
else if (
from() == kUnboxedInt32) {
6203 Register out_lo = out_pair->At(0).reg();
6204 Register out_hi = out_pair->At(1).reg();
6223 if (entry !=
nullptr) {
6224 if (!
compiler->CanFallThroughTo(entry)) {
6225 FATAL(
"Checked function entry must have no offset");
6229 if (!
compiler->CanFallThroughTo(entry)) {
6241 if (FLAG_reorder_basic_blocks) {
6247 InstructionSource());
6262 const intptr_t kNumInputs = 1;
6263 const intptr_t kNumTemps = 2;
6265 LocationSummary* summary =
new (zone)
6283 false, kTypedDataInt32ArrayCid,
6285 false,
offset, index_reg));
6305 const intptr_t kNumInputs = 2;
6306 const intptr_t kNumTemps = 0;
6308 LocationSummary*
locs =
new (zone)
6315 LocationSummary*
locs =
new (zone)
6327Condition StrictCompareInstr::EmitComparisonCodeRegConstant(
6329 BranchLabels labels,
6331 const Object& obj) {
6337static bool IsPowerOfTwoKind(intptr_t v1, intptr_t
v2) {
6361 BranchLabels labels = {
nullptr,
nullptr,
nullptr};
6365 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_);
6367 intptr_t true_value = if_true_;
6368 intptr_t false_value = if_false_;
6370 if (is_power_of_two_kind) {
6371 if (true_value == 0) {
6376 if (true_value == 0) {
6378 intptr_t temp = true_value;
6379 true_value = false_value;
6386 __ setcc(true_condition,
DL);
6388 if (is_power_of_two_kind) {
6389 const intptr_t shift =
6396 if (false_value != 0) {
6404 const intptr_t kNumInputs = 1;
6405 const intptr_t kNumTemps = 0;
6406 LocationSummary* summary =
new (zone)
6416 const Array& arguments_descriptor =
6431 UntaggedPcDescriptors::kOther,
locs(),
env());
6445 __ xorl(
result, compiler::Immediate(
6471 const intptr_t kNumInputs = (
type_arguments() !=
nullptr) ? 1 : 0;
6472 const intptr_t kNumTemps = 0;
6473 LocationSummary*
locs =
new (zone)
6486 compiler->GenerateStubCall(
source(), stub, UntaggedPcDescriptors::kOther,
6495 __ Call(StubCode::DebugStepCheck());
static void done(const char *config, const char *src, const char *srcOptions, const char *name)
static void fail(const SkString &err)
static bool are_equal(skiatest::Reporter *reporter, const SkMatrix &a, const SkMatrix &b)
static int float_bits(float f)
static bool ok(int result)
static bool subtract(const R &a, const R &b, R *out)
#define ASSERT_EQUAL(expected, actual)
#define RELEASE_ASSERT(cond)
intptr_t num_context_variables() const
Value * type_arguments() const
const Class & cls() const
intptr_t num_context_variables() const
static intptr_t type_arguments_offset()
static intptr_t InstanceSize()
static constexpr bool IsValidLength(intptr_t len)
static intptr_t length_offset()
Token::Kind op_kind() const
bool can_overflow() const
Token::Kind op_kind() const
bool RightIsPowerOfTwoConstant() const
Range * right_range() const
ParallelMoveInstr * parallel_move() const
bool HasParallelMove() const
static const Bool & False()
static const Bool & True()
static void Allocate(FlowGraphCompiler *compiler, Instruction *instruction, const Class &cls, Register result, Register temp)
Representation from_representation() const
virtual bool ValueFitsSmi() const
ComparisonInstr * comparison() const
static constexpr Register kFfiAnyNonAbiRegister
static constexpr Register kReturnReg
static constexpr Register kSecondNonArgumentRegister
static constexpr bool kUsesRet4
const RuntimeEntry & TargetFunction() const
bool IsDeoptIfNull() const
DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(CheckClassInstr, TemplateInstruction, FIELD_LIST) private void EmitBitTest(FlowGraphCompiler *compiler, intptr_t min, intptr_t max, intptr_t mask, compiler::Label *deopt)
void EmitNullCheck(FlowGraphCompiler *compiler, compiler::Label *deopt)
bool IsDeoptIfNotNull() const
intptr_t loop_depth() const
static intptr_t instructions_offset()
static intptr_t entry_point_offset(EntryKind kind=EntryKind::kNormal)
virtual void EmitBranchCode(FlowGraphCompiler *compiler, BranchInstr *branch)
virtual void EmitNativeCode(FlowGraphCompiler *compiler)
virtual Condition EmitComparisonCode(FlowGraphCompiler *compiler, BranchLabels labels)=0
const Object & value() const
void EmitMoveToLocation(FlowGraphCompiler *compiler, const Location &destination, Register tmp=kNoRegister, intptr_t pair_index=0)
static intptr_t num_variables_offset()
static intptr_t InstanceSize()
virtual Value * num_elements() const
virtual Representation representation() const
Definition * OriginalDefinition()
MethodRecognizer::Kind op_kind() const
MethodRecognizer::Kind recognized_kind() const
static intptr_t value_offset()
static DoublePtr NewCanonical(double d)
bool is_null_aware() const
void EmitReturnMoves(FlowGraphCompiler *compiler, const Register temp0, const Register temp1)
DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(FfiCallInstr, VariadicDefinition, FIELD_LIST) private void EmitParamMoves(FlowGraphCompiler *compiler, const Register saved_fp, const Register temp0, const Register temp1)
virtual Representation representation() const
static bool CanExecuteGeneratedCodeInSafepoint()
intptr_t TargetAddressIndex() const
static intptr_t guarded_cid_offset()
static intptr_t guarded_list_length_in_object_offset_offset()
intptr_t guarded_cid() const
static intptr_t is_nullable_offset()
static intptr_t guarded_list_length_offset()
static intptr_t entry_point_offset(CodeEntryKind entry_kind=CodeEntryKind::kNormal)
ParallelMoveInstr * parallel_move() const
BlockEntryInstr * block() const
bool HasParallelMove() const
JoinEntryInstr * successor() const
FunctionEntryInstr * normal_entry() const
OsrEntryInstr * osr_entry() const
const Field & field() const
ComparisonInstr * comparison() const
virtual Representation RequiredInputRepresentation(intptr_t idx) const
const AbstractType & type() const
intptr_t GetDeoptId() const
virtual bool UseSharedSlowPathStub(bool is_optimizing) const
Environment * env() const
virtual LocationSummary * MakeLocationSummary(Zone *zone, bool is_optimizing) const =0
virtual void EmitNativeCode(FlowGraphCompiler *compiler)
void InitializeLocationSummary(Zone *zone, bool optimizing)
virtual Representation representation() const
bool CanDeoptimize() const
friend class BlockEntryInstr
InstructionSource source() const
intptr_t deopt_id() const
static LocationSummary * MakeCallSummary(Zone *zone, const Instruction *instr, LocationSummary *locs=nullptr)
static intptr_t HeaderSize()
Representation to() const
Representation from() const
const RuntimeEntry & TargetFunction() const
MethodRecognizer::Kind recognized_kind() const
static constexpr intptr_t kDoubleTempIndex
static constexpr intptr_t kObjectTempIndex
static IsolateGroup * Current()
intptr_t TargetAddressIndex() const
void EmitParamMoves(FlowGraphCompiler *compiler, Register saved_fp, Register temp0)
LocationSummary * MakeLocationSummaryInternal(Zone *zone, const RegList temps) const
virtual Representation representation() const
intptr_t index_scale() const
bool can_pack_into_smi() const
intptr_t element_count() const
intptr_t class_id() const
intptr_t class_id() const
intptr_t index_scale() const
Representation representation() const
const LocalVariable & local() const
Location temp(intptr_t index) const
Location out(intptr_t index) const
static LocationSummary * Make(Zone *zone, intptr_t input_count, Location out, ContainsCall contains_call)
void set_temp(intptr_t index, Location loc)
RegisterSet * live_registers()
void set_out(intptr_t index, Location loc)
Location in(intptr_t index) const
void set_in(intptr_t index, Location loc)
static Location StackSlot(intptr_t stack_index, Register base)
static Location NoLocation()
static Location SameAsFirstInput()
static Location Pair(Location first, Location second)
static Location FpuRegisterLocation(FpuRegister reg)
static Location WritableRegister()
static Location RegisterLocation(Register reg)
static Location PrefersRegister()
PairLocation * AsPairLocation() const
static Location RequiresRegister()
static Location RequiresFpuRegister()
FpuRegister fpu_reg() const
const Object & constant() const
static Location Constant(const ConstantInstr *obj, int pair_index=0)
intptr_t result_cid() const
MethodRecognizer::Kind op_kind() const
bool unboxed_inputs() const
Value * src_start() const
void EmitLoopCopy(FlowGraphCompiler *compiler, Register dest_reg, Register src_reg, Register length_reg, compiler::Label *done, compiler::Label *copy_forwards=nullptr)
void PrepareLengthRegForLoop(FlowGraphCompiler *compiler, Register length_reg, compiler::Label *done)
Value * dest_start() const
static intptr_t value_offset()
virtual Representation representation() const
Location location() const
static int ComputeArgcTag(const Function &function)
bool is_auto_scope() const
bool is_bootstrap_native() const
const Function & function() const
NativeFunction native_c_function() const
static constexpr intptr_t kVMTagOffsetFromFp
static Object & ZoneHandle()
Value * char_code() const
static intptr_t data_offset()
Location At(intptr_t i) const
static bool Overlaps(Range *range, intptr_t min, intptr_t max)
static bool OnlyLessThanOrEqualTo(Range *range, intptr_t value)
static bool IsWithin(const Range *range, int64_t min, int64_t max)
static bool IsPositive(Range *range)
static bool CanBeZero(Range *range)
void Add(Location loc, Representation rep=kTagged)
DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(ShiftIntegerOpInstr, BinaryIntegerOpInstr, FIELD_LIST) protected bool IsShiftCountInRange(int64_t max=kShiftCountLimit) const
Range * shift_range() const
static constexpr intptr_t kBits
static SmiPtr New(intptr_t value)
static constexpr intptr_t kMaxValue
static intptr_t RawValue(intptr_t value)
const char * message() const
bool ShouldEmitStoreBarrier() const
virtual Representation RequiredInputRepresentation(intptr_t idx) const
intptr_t class_id() const
intptr_t index_scale() const
const LocalVariable & local() const
const Field & field() const
bool needs_number_check() const
static intptr_t length_offset()
static CodePtr GetAllocationStubForClass(const Class &cls)
static constexpr int kNullCharCodeSymbolOffset
static StringPtr * PredefinedAddress()
static bool sse4_1_supported()
intptr_t ArgumentCount() const
ArrayPtr GetArgumentsDescriptor() const
virtual intptr_t InputCount() const
const ZoneGrowableArray< intptr_t > & cid_results() const
static intptr_t stack_limit_offset()
static intptr_t stack_overflow_flags_offset()
static bool IsEqualityOperator(Kind tok)
virtual Representation representation() const
Token::Kind op_kind() const
Token::Kind op_kind() const
virtual Representation representation() const
bool is_truncating() const
uword constant_address() const
virtual Representation representation() const
bool IsScanFlagsUnboxed() const
static int32_t Low32Bits(int64_t value)
static constexpr T Maximum(T x, T y)
static constexpr int ShiftForPowerOfTwo(T x)
static int32_t High32Bits(int64_t value)
static T Minimum(T x, T y)
static T AddWithWrapAround(T a, T b)
static bool DoublesBitEqual(const double a, const double b)
static constexpr size_t HighestBit(int64_t v)
static constexpr bool IsPowerOfTwo(T x)
bool BindsToConstant() const
intptr_t BoundSmiConstant() const
bool BindsToSmiConstant() const
Definition * definition() const
Value(Definition *definition)
intptr_t InputCount() const
static Address Absolute(const uword addr)
void static bool EmittingComments()
Address ElementAddressForRegIndex(bool is_load, bool is_external, intptr_t cid, intptr_t index_scale, bool index_unboxed, Register array, Register index)
static Address VMTagAddress()
static bool AddressCanHoldConstantIndex(const Object &constant, bool is_load, bool is_external, intptr_t cid, intptr_t index_scale, bool *needs_base=nullptr)
static bool IsSafeSmi(const Object &object)
static bool IsSafe(const Object &object)
intptr_t StackTopInBytes() const
static word data_offset()
static word entry_point_offset(CodeEntryKind kind=CodeEntryKind::kNormal)
static word OffsetOf(const dart::Field &field)
static word data_offset()
static word object_store_offset()
static word ffi_callback_code_offset()
static word tags_offset()
static word data_offset()
static word unboxed_runtime_arg_offset()
static word shared_field_table_values_offset()
static uword vm_tag_dart_id()
static word isolate_group_offset()
static word field_table_values_offset()
static word exit_through_ffi_offset()
static word invoke_dart_code_stub_offset()
static word top_exit_frame_info_offset()
static word top_resource_offset()
static word data_offset()
static word payload_offset()
static const word kImmutableBit
static const word kClassIdTagSize
FlutterSemanticsFlag flag
FlutterSemanticsFlag flags
static float max(float r, float g, float b)
static float min(float r, float g, float b)
#define CASE(Arity, Mask, Name, Args, Result)
#define DEFINE_UNIMPLEMENTED_INSTRUCTION(Name)
const intptr_t kResultIndex
intptr_t FrameOffsetInBytesForVariable(const LocalVariable *variable)
static constexpr intptr_t kWordSize
constexpr intptr_t kSmiBits
bool HasIntegerValue(const dart::Object &object, int64_t *value)
Location LocationRegisterOrConstant(Value *value)
const Register kWriteBarrierSlotReg
uword FindDoubleConstant(double value)
static Condition InvertCondition(Condition c)
static constexpr int kSavedCallerPcSlotFromFp
bool IsTypedDataBaseClassId(intptr_t index)
static bool IsSmiValue(Value *val, intptr_t *int_val)
const Register kExceptionObjectReg
const Register kWriteBarrierObjectReg
const Register kWriteBarrierValueReg
static constexpr bool IsCalleeSavedRegister(Register reg)
constexpr intptr_t kIntptrMin
static const ClassId kLastErrorCid
constexpr intptr_t kSimd128Size
static const ClassId kFirstErrorCid
const Register ARGS_DESC_REG
bool IsClampedTypedDataBaseClassId(intptr_t index)
Location LocationFixedRegisterOrConstant(Value *value, Register reg)
bool IsExternalPayloadClassId(classid_t cid)
constexpr intptr_t kInt32Size
DEFINE_BACKEND(LoadThread,(Register out))
static constexpr int kPcMarkerSlotFromFp
const Register FUNCTION_REG
const Register IC_DATA_REG
compiler::Address LocationToStackSlotAddress(Location loc)
constexpr intptr_t kWordSize
Location LocationWritableRegisterOrConstant(Value *value)
static bool IsConstant(Definition *def, int64_t *val)
constexpr intptr_t kFloatSize
constexpr bool FLAG_target_memory_sanitizer
const Register kStackTraceObjectReg
static int8_t data[kExtLength]
constexpr intptr_t kDoubleSize
Location LocationFixedRegisterOrSmiConstant(Value *value, Register reg)
static ScaleFactor ToScaleFactor(intptr_t index_scale, bool index_unboxed)
Location LocationRegisterOrSmiConstant(Value *value, intptr_t min_value, intptr_t max_value)
constexpr intptr_t kBitsPerInt64
COMPILE_ASSERT(kUnreachableReference==WeakTable::kNoValue)
static bool Bind(PassBindingsCacheMTL &pass, ShaderStage stage, size_t bind_index, const BufferView &view)
SIN Vec< N, uint16_t > mull(const Vec< N, uint8_t > &x, const Vec< N, uint8_t > &y)
static constexpr Register kResultReg
static constexpr Register kLengthReg
static constexpr Register kTypeArgumentsReg
static constexpr Register kTypeArgumentsReg
static constexpr Register kResultReg
static constexpr Register kObjectReg
static constexpr Representation NativeRepresentation(Representation rep)
intptr_t first_local_from_fp
intptr_t FrameSlotForVariable(const LocalVariable *variable) const
static constexpr intptr_t kBoolVsNullMask
static constexpr intptr_t kBoolValueMask
static constexpr size_t ValueSize(Representation rep)
static constexpr bool IsUnboxedInteger(Representation rep)
static compiler::OperandSize OperandSize(Representation rep)
static constexpr bool IsUnboxed(Representation rep)
static bool IsUnsignedInteger(Representation rep)
static Representation RepresentationOfArrayElement(classid_t cid)
static constexpr Register kDstTypeReg
static constexpr Register kInstanceReg
static constexpr Register kFunctionTypeArgumentsReg
static constexpr Register kInstantiatorTypeArgumentsReg
#define ASSERT_BOOL_FALSE_FOLLOWS_BOOL_TRUE()