Flutter Engine
The Flutter Engine
assembler_ia32.h
Go to the documentation of this file.
1// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_VM_COMPILER_ASSEMBLER_ASSEMBLER_IA32_H_
6#define RUNTIME_VM_COMPILER_ASSEMBLER_ASSEMBLER_IA32_H_
7
8#if defined(DART_PRECOMPILED_RUNTIME)
9#error "AOT runtime should not use compiler sources (including header files)"
10#endif // defined(DART_PRECOMPILED_RUNTIME)
11
12#ifndef RUNTIME_VM_COMPILER_ASSEMBLER_ASSEMBLER_H_
13#error Do not include assembler_ia32.h directly; use assembler.h instead.
14#endif
15
16#include <functional>
17
18#include "platform/assert.h"
19#include "platform/utils.h"
21#include "vm/constants.h"
22#include "vm/constants_x86.h"
23#include "vm/pointer_tagging.h"
24
25namespace dart {
26
27namespace compiler {
28
29class Immediate : public ValueObject {
30 public:
31 explicit Immediate(int32_t value) : value_(value) {}
32
33 Immediate(const Immediate& other) : ValueObject(), value_(other.value_) {}
34
35 int32_t value() const { return value_; }
36
37 bool is_int8() const { return Utils::IsInt(8, value_); }
38 bool is_uint8() const { return Utils::IsUint(8, value_); }
39 bool is_uint16() const { return Utils::IsUint(16, value_); }
40
41 private:
42 const int32_t value_;
43
44 // TODO(5411081): Add DISALLOW_COPY_AND_ASSIGN(Immediate) once the mac
45 // build issue is resolved.
46 // And remove the unnecessary copy constructor.
47};
48
49class Operand : public ValueObject {
50 public:
51 uint8_t mod() const { return (encoding_at(0) >> 6) & 3; }
52
53 Register rm() const { return static_cast<Register>(encoding_at(0) & 7); }
54
56 return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
57 }
58
59 Register index() const {
60 return static_cast<Register>((encoding_at(1) >> 3) & 7);
61 }
62
63 Register base() const { return static_cast<Register>(encoding_at(1) & 7); }
64
65 int8_t disp8() const {
66 ASSERT(length_ >= 2);
67 return static_cast<int8_t>(encoding_[length_ - 1]);
68 }
69
70 int32_t disp32() const {
71 ASSERT(length_ >= 5);
72 return bit_copy<int32_t>(encoding_[length_ - 4]);
73 }
74
75 Operand(const Operand& other) : ValueObject(), length_(other.length_) {
76 memmove(&encoding_[0], &other.encoding_[0], other.length_);
77 }
78
79 Operand& operator=(const Operand& other) {
80 length_ = other.length_;
81 memmove(&encoding_[0], &other.encoding_[0], other.length_);
82 return *this;
83 }
84
85 bool Equals(const Operand& other) const {
86 if (length_ != other.length_) return false;
87 for (uint8_t i = 0; i < length_; i++) {
88 if (encoding_[i] != other.encoding_[i]) return false;
89 }
90 return true;
91 }
92
93 protected:
94 Operand() : length_(0) {} // Needed by subclass Address.
95
96 void SetModRM(int mod, Register rm) {
97 ASSERT((mod & ~3) == 0);
98 encoding_[0] = (mod << 6) | rm;
99 length_ = 1;
100 }
101
103 ASSERT(length_ == 1);
104 ASSERT((scale & ~3) == 0);
105 encoding_[1] = (scale << 6) | (index << 3) | base;
106 length_ = 2;
107 }
108
109 void SetDisp8(int8_t disp) {
110 ASSERT(length_ == 1 || length_ == 2);
111 encoding_[length_++] = static_cast<uint8_t>(disp);
112 }
113
114 void SetDisp32(int32_t disp) {
115 ASSERT(length_ == 1 || length_ == 2);
116 intptr_t disp_size = sizeof(disp);
117 memmove(&encoding_[length_], &disp, disp_size);
118 length_ += disp_size;
119 }
120
121 private:
122 uint8_t length_;
123 uint8_t encoding_[6];
124 uint8_t padding_;
125
126 explicit Operand(Register reg) { SetModRM(3, reg); }
127
128 // Get the operand encoding byte at the given index.
129 uint8_t encoding_at(intptr_t index) const {
130 ASSERT(index >= 0 && index < length_);
131 return encoding_[index];
132 }
133
134 // Returns whether or not this operand is really the given register in
135 // disguise. Used from the assembler to generate better encodings.
136 bool IsRegister(Register reg) const {
137 return ((encoding_[0] & 0xF8) == 0xC0) // Addressing mode is register only.
138 && ((encoding_[0] & 0x07) == reg); // Register codes match.
139 }
140
141 friend class Assembler;
142};
143
144class Address : public Operand {
145 public:
146 Address(Register base, int32_t disp) {
147 if (disp == 0 && base != EBP) {
148 SetModRM(0, base);
149 if (base == ESP) SetSIB(TIMES_1, ESP, base);
150 } else if (Utils::IsInt(8, disp)) {
151 SetModRM(1, base);
152 if (base == ESP) SetSIB(TIMES_1, ESP, base);
153 SetDisp8(disp);
154 } else {
155 SetModRM(2, base);
156 if (base == ESP) SetSIB(TIMES_1, ESP, base);
157 SetDisp32(disp);
158 }
159 }
160
162 ASSERT(index != ESP); // Illegal addressing mode.
163 ASSERT(scale != TIMES_16); // Unsupported scale factor.
164 SetModRM(0, ESP);
166 SetDisp32(disp);
167 }
168
169 // This addressing mode does not exist.
171
173 ASSERT(index != ESP); // Illegal addressing mode.
174 ASSERT(scale != TIMES_16); // Unsupported scale factor.
175 if (disp == 0 && base != EBP) {
176 SetModRM(0, ESP);
178 } else if (Utils::IsInt(8, disp)) {
179 SetModRM(1, ESP);
181 SetDisp8(disp);
182 } else {
183 SetModRM(2, ESP);
185 SetDisp32(disp);
186 }
187 }
188
189 // This addressing mode does not exist.
191
192 Address(const Address& other) : Operand(other) {}
193
194 Address& operator=(const Address& other) {
195 Operand::operator=(other);
196 return *this;
197 }
198
199 static Address Absolute(const uword addr) {
201 result.SetModRM(0, EBP);
202 result.SetDisp32(addr);
203 return result;
204 }
205
206 private:
207 Address() {} // Needed by Address::Absolute.
208};
209
210class FieldAddress : public Address {
211 public:
213 : Address(base, disp - kHeapObjectTag) {}
214
215 // This addressing mode does not exist.
217
219 : Address(base, index, scale, disp - kHeapObjectTag) {}
220
221 // This addressing mode does not exist.
223
224 FieldAddress(const FieldAddress& other) : Address(other) {}
225
227 Address::operator=(other);
228 return *this;
229 }
230};
231
232class Assembler : public AssemblerBase {
233 public:
235 intptr_t far_branch_level = 0)
237 jit_cookie_(0),
238 code_(NewZoneHandle(ThreadState::Current()->zone())) {
239 // This mode is only needed and implemented for ARM.
241 }
243
244 /*
245 * Emit Machine Instructions.
246 */
247 void call(Register reg);
248 void call(const Address& address);
249 void call(Label* label);
250 void call(const ExternalLabel* label);
251
252 static constexpr intptr_t kCallExternalLabelSize = 5;
253
254 void pushl(Register reg);
255 void pushl(const Address& address);
256 void pushl(const Immediate& imm);
258
259 void popl(Register reg);
260 void popl(const Address& address);
261
262 void pushal();
263 void popal();
264
265 void setcc(Condition condition, ByteRegister dst);
266
269
270 void movl(Register dst, const Address& src);
271 void movl(const Address& dst, Register src);
272 void movl(const Address& dst, const Immediate& imm);
273
278 void movb(Register dst, const Address& src);
279 void movb(const Address& dst, Register src);
281 void movb(const Address& dst, const Immediate& imm);
282
287 void movw(Register dst, const Address& src);
288 void movw(const Address& dst, Register src);
289 void movw(const Address& dst, const Immediate& imm);
290
291 void leal(Register dst, const Address& src);
292
298
301
302 void rep_movsb();
303 void rep_movsw();
304 void rep_movsd();
305
309
312
315
324
328
330
333
342
373
374 void set1ps(XmmRegister dst, Register tmp, const Immediate& imm);
376
389
392
395
398
401
403
406
410
413
418
421
423
427
429
433 kRoundUp = 0x2,
434 kRoundToZero = 0x3
435 };
437
438 void flds(const Address& src);
439 void fstps(const Address& dst);
440
441 void fldl(const Address& src);
442 void fstpl(const Address& dst);
443
444 void fnstcw(const Address& dst);
445 void fldcw(const Address& src);
446
447 void fistpl(const Address& dst);
448 void fistps(const Address& dst);
449 void fildl(const Address& src);
450 void filds(const Address& src);
451
452 void fincstp();
453 void ffree(intptr_t value);
454
455 void fsin();
456 void fcos();
457 void fsincos();
458 void fptan();
459
461
462 void cmpw(const Address& address, const Immediate& imm);
463 void cmpb(const Address& address, const Immediate& imm);
464
465 void testl(Register reg1, Register reg2);
466 void testl(Register reg, const Immediate& imm);
467 void testl(const Address& address, const Immediate& imm);
468 void testl(const Address& address, Register reg);
469 void testb(const Address& address, const Immediate& imm);
470 void testb(const Address& address, ByteRegister reg);
471
472 // clang-format off
473// Macro for handling common ALU instructions. Arguments to F:
474// name, opcode, reversed opcode, opcode for the reg field of the modrm byte.
475#define ALU_OPS(F) \
476 F(and, 0x23, 0x21, 4) \
477 F(or, 0x0b, 0x09, 1) \
478 F(xor, 0x33, 0x31, 6) \
479 F(add, 0x03, 0x01, 0) \
480 F(adc, 0x13, 0x11, 2) \
481 F(sub, 0x2b, 0x29, 5) \
482 F(sbb, 0x1b, 0x19, 3) \
483 F(cmp, 0x3b, 0x39, 7)
484 // clang-format on
485
486#define DECLARE_ALU(op, opcode, opcode2, modrm_opcode) \
487 void op##l(Register dst, Register src) { Alu(4, opcode, dst, src); } \
488 void op##w(Register dst, Register src) { Alu(2, opcode, dst, src); } \
489 void op##l(Register dst, const Address& src) { Alu(4, opcode, dst, src); } \
490 void op##w(Register dst, const Address& src) { Alu(2, opcode, dst, src); } \
491 void op##l(const Address& dst, Register src) { Alu(4, opcode2, dst, src); } \
492 void op##w(const Address& dst, Register src) { Alu(2, opcode2, dst, src); } \
493 void op##l(Register dst, const Immediate& imm) { \
494 Alu(modrm_opcode, dst, imm); \
495 } \
496 void op##l(const Address& dst, const Immediate& imm) { \
497 Alu(modrm_opcode, dst, imm); \
498 }
499
501
502#undef DECLARE_ALU
503#undef ALU_OPS
504
505 void cdq();
506
507 void idivl(Register reg);
508
509 void divl(Register reg);
510
512 void imull(Register reg, const Immediate& imm);
513 void imull(Register reg, const Address& address);
514
515 void imull(Register reg);
516 void imull(const Address& address);
517
518 void mull(Register reg);
519 void mull(const Address& address);
520
521 void incl(Register reg);
522 void incl(const Address& address);
523
524 void decl(Register reg);
525 void decl(const Address& address);
526
527 void shll(Register reg, const Immediate& imm);
528 void shll(Register operand, Register shifter);
529 void shll(const Address& operand, Register shifter);
530 void shrl(Register reg, const Immediate& imm);
531 void shrl(Register operand, Register shifter);
532 void sarl(Register reg, const Immediate& imm);
533 void sarl(Register operand, Register shifter);
534 void sarl(const Address& address, Register shifter);
537 void shldl(const Address& operand, Register src, Register shifter);
540 void shrdl(const Address& dst, Register src, Register shifter);
541
542 void negl(Register reg);
543 void notl(Register reg);
544
549
551 void bt(Register base, int bit);
552
553 void enter(const Immediate& imm);
554 void leave();
555
556 void ret();
557 void ret(const Immediate& imm);
558
559 // 'size' indicates size in bytes and must be in the range 1..8.
560 void nop(int size = 1);
561 void int3();
562 void hlt();
563
564 void j(Condition condition, Label* label, JumpDistance distance = kFarJump);
565 void j(Condition condition, const ExternalLabel* label);
566
567 void jmp(Register reg);
568 void jmp(const Address& address);
570 void jmp(const ExternalLabel* label);
571
572 void lock();
573 void cmpxchgl(const Address& address, Register reg);
574
575 void cld();
576 void std();
577
578 void cpuid();
579
580 /*
581 * Macros for High-level operations and implemented on all architectures.
582 */
583
584 void Ret() { ret(); }
585
586 // Sets the return address to [value] as if there was a call.
587 // On IA32 pushes [value].
589
592 }
593
597 }
598 void BranchIf(Condition condition,
599 Label* label,
601 j(condition, label, distance);
602 }
604 Label* label,
606 cmpl(src, Immediate(0));
607 j(ZERO, label, distance);
608 }
610 intptr_t bit_number,
611 Condition condition,
612 Label* label,
614 testl(rn, Immediate(1 << bit_number));
615 j(condition, label, distance);
616 }
617
618 // Arch-specific Load to choose the right operation for [sz].
620 const Address& address,
621 OperandSize sz = kFourBytes) override;
624 int32_t payload_offset,
625 Register index,
627 OperandSize sz = kFourBytes) override {
628 Load(dst, FieldAddress(base, index, scale, payload_offset), sz);
629 }
631 const Address& address,
632 OperandSize sz = kFourBytes) override;
633 void Store(const Object& value, const Address& address);
634 void StoreZero(const Address& address, Register temp = kNoRegister) {
635 movl(address, Immediate(0));
636 }
637 void LoadFromStack(Register dst, intptr_t depth);
638 void StoreToStack(Register src, intptr_t depth);
639 void CompareToStack(Register src, intptr_t depth);
642 }
645 }
646
649 }
652 }
654 if (src != dst) {
655 movaps(dst, src);
656 }
657 }
658
661 }
664 }
666 if (src != dst) {
667 movaps(dst, src);
668 }
669 }
670
672 const Address& address,
673 OperandSize size = kFourBytes) override {
674 // On intel loads have load-acquire behavior (i.e. loads are not re-ordered
675 // with other loads).
676 Load(dst, address, size);
677 if (FLAG_target_thread_sanitizer) {
678 FATAL("No support for TSAN on IA32.");
679 }
680 }
682 const Address& address,
683 OperandSize size = kFourBytes) override {
684 // On intel stores have store-release behavior (i.e. stores are not
685 // re-ordered with other stores).
686 Store(src, address, size);
687 if (FLAG_target_thread_sanitizer) {
688 FATAL("No support for TSAN on IA32.");
689 }
690 }
691
693 Address address,
694 OperandSize size = kFourBytes) override {
696 cmpl(value, address);
697 }
698
699 void ExtendValue(Register to, Register from, OperandSize sz) override;
702
704 PushRegister(r1);
705 PushRegister(r0);
706 }
708 PopRegister(r0);
709 PopRegister(r1);
710 }
711
712 void PushRegistersInOrder(std::initializer_list<Register> regs);
713
714 void AddImmediate(Register reg, const Immediate& imm);
715 void AddImmediate(Register reg, int32_t value) {
717 }
722 Register index,
724 int32_t disp) override {
725 if (base == kNoRegister) {
726 leal(dest, Address(index, scale, disp));
727 } else {
728 leal(dest, Address(base, index, scale, disp));
729 }
730 }
731 void SubImmediate(Register reg, const Immediate& imm);
734 int32_t imm,
735 OperandSize width = kFourBytes) override {
737 if (Utils::IsPowerOfTwo(imm)) {
738 const intptr_t shift = Utils::ShiftForPowerOfTwo(imm);
739 shll(reg, Immediate(shift));
740 } else {
741 imull(reg, Immediate(imm));
742 }
743 }
744 void AndImmediate(Register dst, int32_t value) override {
745 andl(dst, Immediate(value));
746 }
749 andl(dst, Immediate(value));
750 }
752 Register src1,
753 Register src2 = kNoRegister) override;
754 void OrImmediate(Register dst, int32_t value) { orl(dst, Immediate(value)); }
755 void LslImmediate(Register dst, int32_t shift) {
756 shll(dst, Immediate(shift));
757 }
758 void LslRegister(Register dst, Register shift) override {
759 ASSERT_EQUAL(shift, ECX); // IA32 does not have a TMP.
760 shll(dst, shift);
761 }
762 void LsrImmediate(Register dst, int32_t shift) override {
763 shrl(dst, Immediate(shift));
764 }
765
767 int32_t immediate,
768 OperandSize width = kFourBytes) override {
770 cmpl(reg, Immediate(immediate));
771 }
772
773 void LoadImmediate(Register reg, int32_t immediate) override {
774 if (immediate == 0) {
775 xorl(reg, reg);
776 } else {
777 movl(reg, Immediate(immediate));
778 }
779 }
780
781 void LoadImmediate(Register reg, Immediate immediate) {
782 LoadImmediate(reg, immediate.value());
783 }
784
788
789 void Drop(intptr_t stack_elements);
790
793
794 void LoadUniqueObject(Register dst, const Object& object) {
795 LoadObject(dst, object, /*movable_referent=*/true);
796 }
797
799 const Object& object,
800 bool movable_referent = false);
801
802 // If 'object' is a large Smi, xor it with a per-assembler cookie value to
803 // prevent user-controlled immediates from appearing in the code stream.
804 void LoadObjectSafely(Register dst, const Object& object);
805
806 void PushObject(const Object& object);
807 void CompareObject(Register reg, const Object& object);
808
810 Register object,
811 const Address& dest,
812 const Object& value,
813 MemoryOrder memory_order = kRelaxedNonAtomic,
814 OperandSize size = kFourBytes) override;
815
818 CanBeSmi can_be_smi,
819 Register scratch) override;
821 Register slot,
823 CanBeSmi can_be_smi,
824 Register scratch) override;
826
827 // Stores a non-tagged value into a heap object.
829 const Address& dest,
831
832 // Stores a Smi value into a heap object field that always contains a Smi.
835 // Increments a Smi field. Leaves flags in same state as an 'addl'.
836 void IncrementSmiField(const Address& dest, int32_t increment);
837
840
842
843 void LockCmpxchgl(const Address& address, Register reg) {
844 lock();
845 cmpxchgl(address, reg);
846 }
847
848 void EnterFrame(intptr_t frame_space);
850 void ReserveAlignedFrameSpace(intptr_t frame_space);
851
855
856 void CombineHashes(Register dst, Register other) override;
857 void FinalizeHashForSize(intptr_t bit_size,
859 Register scratch = kNoRegister) override;
860
861 // In debug mode, this generates code to check that:
862 // FP + kExitLinkSlotFromEntryFp == SP
863 // or triggers breakpoint otherwise.
864 //
865 // Clobbers EAX.
867
868 // Transitions safepoint and Thread state between generated and native code.
869 // Updates top-exit-frame info, VM tag and execution-state. Leaves/enters a
870 // safepoint.
871 //
872 // Require a temporary register 'tmp'.
873 // Clobber all non-CPU registers (e.g. XMM registers and the "FPU stack").
874 // However XMM0 is saved for convenience.
875 void TransitionGeneratedToNative(Register destination_address,
876 Register new_exit_frame,
877 Register new_exit_through_ffi,
878 bool enter_safepoint);
880 bool exit_safepoint,
881 bool ignore_unwind_in_progress = false,
882 bool set_tag = true);
884 void ExitFullSafepoint(Register scratch, bool ignore_unwind_in_progress);
885
886 // For non-leaf runtime calls. For leaf runtime calls, use LeafRuntimeScope,
887 void CallRuntime(const RuntimeEntry& entry, intptr_t argument_count);
888
889 void Call(const Code& code,
890 bool movable_target = false,
892 // Will not clobber any registers and can therefore be called with 5 live
893 // registers.
894 void CallVmStub(const Code& code);
895
897
899
901
902 void Jmp(const Code& code);
903 void J(Condition condition, const Code& code);
904
906 Register temp,
907 intptr_t low,
908 intptr_t high,
909 RangeCheckCondition condition,
910 Label* target) override;
911
912 /*
913 * Loading and comparing classes of objects.
914 */
916
918
919 void CompareClassId(Register object, intptr_t class_id, Register scratch);
920
925 Register scratch,
926 bool can_be_null = false) override;
927
929 intptr_t class_id,
930 Register scratch,
931 Label* is_smi);
932
933 static bool AddressCanHoldConstantIndex(const Object& constant,
934 bool is_external,
935 intptr_t cid,
936 intptr_t index_scale);
937
938 static Address ElementAddressForIntIndex(bool is_external,
939 intptr_t cid,
940 intptr_t index_scale,
941 Register array,
942 intptr_t index,
943 intptr_t extra_disp = 0);
944
945 static Address ElementAddressForRegIndex(bool is_external,
946 intptr_t cid,
947 intptr_t index_scale,
948 bool index_unboxed,
949 Register array,
950 Register index,
951 intptr_t extra_disp = 0);
952
954 Register field,
955 Register scratch,
956 bool is_shared) {
957 LoadFieldFromOffset(scratch, field,
959 const intptr_t field_table_offset =
962 LoadMemoryValue(address, THR, static_cast<int32_t>(field_table_offset));
963 static_assert(kSmiTagShift == 1, "adjust scale factor");
964 leal(address, Address(address, scratch, TIMES_HALF_WORD_SIZE, 0));
965 }
966
969 Register offset_in_words_as_smi) override {
970 static_assert(kSmiTagShift == 1, "adjust scale factor");
971 leal(address, FieldAddress(instance, offset_in_words_as_smi, TIMES_2, 0));
972 }
973
976 int32_t offset) override {
977 leal(address, FieldAddress(instance, offset));
978 }
979
982 }
983
984 /*
985 * Misc. functionality
986 */
987 void SmiTag(Register reg) override { addl(reg, reg); }
988
990
991 // Truncates upper bits.
993 if (result != value) {
995 value = result;
996 }
997 ASSERT(value == result);
999 SmiUntag(result); // Leaves CF after SmiUntag.
1001 // Undo untagging by multiplying value by 2.
1002 // [reg + reg + disp8] has a shorter encoding than [reg*2 + disp32]
1006 Bind(&done);
1007 }
1008
1010 Label* label,
1013 j(NOT_ZERO, label, distance);
1014 }
1015
1017 Label* label,
1018 JumpDistance distance = kFarJump) override {
1020 j(ZERO, label, distance);
1021 }
1022
1023 void ArithmeticShiftRightImmediate(Register reg, intptr_t shift) override;
1025 Register reg2,
1026 intptr_t offset,
1028 Register temp,
1029 Label* equals) override;
1030
1031 void Align(intptr_t alignment, intptr_t offset);
1032 void Bind(Label* label) override;
1034 jmp(label, distance);
1035 }
1036 // Unconditional jump to a given address in register.
1038
1039 // Moves one word from the memory at [from] to the memory at [to].
1040 // Needs a temporary register.
1042
1043 // Set up a Dart frame on entry with a frame pointer and PC information to
1044 // enable easy access to the RawInstruction object of code corresponding
1045 // to this frame.
1046 // The dart frame layout is as follows:
1047 // ....
1048 // ret PC
1049 // saved EBP <=== EBP
1050 // pc (used to derive the RawInstruction Object of the dart code)
1051 // locals space <=== ESP
1052 // .....
1053 // This code sets this up with the sequence:
1054 // pushl ebp
1055 // movl ebp, esp
1056 // call L
1057 // L: <code to adjust saved pc if there is any intrinsification code>
1058 // .....
1059 void EnterDartFrame(intptr_t frame_size);
1061
1062 // Set up a Dart frame for a function compiled for on-stack replacement.
1063 // The frame layout is a normal Dart frame, but the frame is partially set
1064 // up on entry (it is the frame of the unoptimized code).
1065 void EnterOsrFrame(intptr_t extra_size);
1066
1067 // Set up a stub frame so that the stack traversal code can easily identify
1068 // a stub frame.
1069 // The stub frame layout is as follows:
1070 // ....
1071 // ret PC
1072 // saved EBP
1073 // 0 (used to indicate frame is a stub frame)
1074 // .....
1075 // This code sets this up with the sequence:
1076 // pushl ebp
1077 // movl ebp, esp
1078 // pushl immediate(0)
1079 // .....
1082 static constexpr intptr_t kEnterStubFramePushedWords = 2;
1083
1084 // Set up a frame for calling a C function.
1085 // Automatically save the pinned registers in Dart which are not callee-
1086 // saved in the native calling convention.
1087 // Use together with CallCFunction.
1088 void EnterCFrame(intptr_t frame_space);
1090
1091 // Instruction pattern from entrypoint is used in dart frame prologs
1092 // to set up the frame and save a PC which can be used to figure out the
1093 // RawInstruction object corresponding to the code running in the frame.
1094 // entrypoint:
1095 // pushl ebp (size is 1 byte)
1096 // movl ebp, esp (size is 2 bytes)
1097 // call L (size is 5 bytes)
1098 // L:
1099 static constexpr intptr_t kEntryPointToPcMarkerOffset = 8;
1100 static intptr_t EntryPointToPcMarkerOffset() {
1102 }
1103
1104 // If allocation tracing for |cid| is enabled, will jump to |trace| label,
1105 // which will allocate in the runtime where tracing occurs.
1107 Label* trace,
1108 Register temp_reg,
1109 JumpDistance distance = JumpDistance::kFarJump);
1110
1111 void TryAllocateObject(intptr_t cid,
1112 intptr_t instance_size,
1113 Label* failure,
1115 Register instance_reg,
1116 Register temp_reg) override;
1117
1118 void TryAllocateArray(intptr_t cid,
1119 intptr_t instance_size,
1120 Label* failure,
1123 Register end_address,
1124 Register temp);
1125
1127#if defined(DEBUG)
1128 Label okay;
1129 cmpl(Address(top, 0), Immediate(kAllocationCanary));
1130 j(EQUAL, &okay, Assembler::kNearJump);
1131 Stop("Allocation canary");
1132 Bind(&okay);
1133#endif
1134 }
1136#if defined(DEBUG)
1138#endif
1139 }
1140
1141 // Copy [size] bytes from [src] address to [dst] address.
1142 // [size] should be a multiple of word size.
1143 // Clobbers [src], [dst], [size] and [temp] registers.
1144 // IA32 requires fixed registers for memory copying:
1145 // [src] = ESI, [dst] = EDI, [size] = ECX.
1147 Register dst,
1148 Register size,
1149 Register temp = kNoRegister);
1150
1151 // Debugging and bringup support.
1152 void Breakpoint() override { int3(); }
1153
1154 // Check if the given value is an integer value that can be directly
1155 // embedded into the code without additional XORing with jit_cookie.
1156 // We consider 16-bit integers, powers of two and corresponding masks
1157 // as safe values that can be embedded into the code object.
1158 static bool IsSafeSmi(const Object& object) {
1159 if (!target::IsSmi(object)) {
1160 return false;
1161 }
1162 int64_t value;
1163 if (HasIntegerValue(object, &value)) {
1164 return Utils::IsInt(16, value) || Utils::IsPowerOfTwo(value) ||
1166 }
1167 return false;
1168 }
1169 static bool IsSafe(const Object& object) {
1170 return !target::IsSmi(object) || IsSafeSmi(object);
1171 }
1172
1173 Object& GetSelfHandle() const { return code_; }
1174
1176
1177 private:
1178 void Alu(int bytes, uint8_t opcode, Register dst, Register src);
1179 void Alu(uint8_t modrm_opcode, Register dst, const Immediate& imm);
1180 void Alu(int bytes, uint8_t opcode, Register dst, const Address& src);
1181 void Alu(int bytes, uint8_t opcode, const Address& dst, Register src);
1182 void Alu(uint8_t modrm_opcode, const Address& dst, const Immediate& imm);
1183
1184 inline void EmitUint8(uint8_t value);
1185 inline void EmitInt32(int32_t value);
1186 inline void EmitRegisterOperand(int rm, int reg);
1187 inline void EmitXmmRegisterOperand(int rm, XmmRegister reg);
1188 inline void EmitFixup(AssemblerFixup* fixup);
1189 inline void EmitOperandSizeOverride();
1190
1191 void EmitOperand(int rm, const Operand& operand);
1192 void EmitImmediate(const Immediate& imm);
1193 void EmitComplex(int rm, const Operand& operand, const Immediate& immediate);
1194 void EmitLabel(Label* label, intptr_t instruction_size);
1195 void EmitLabelLink(Label* label);
1196 void EmitNearLabelLink(Label* label);
1197
1198 void EmitGenericShift(int rm, Register reg, const Immediate& imm);
1199 void EmitGenericShift(int rm, const Operand& operand, Register shifter);
1200
1201 int32_t jit_cookie();
1202
1203 int32_t jit_cookie_;
1204 Object& code_;
1205
1206 DISALLOW_ALLOCATION();
1207 DISALLOW_COPY_AND_ASSIGN(Assembler);
1208};
1209
1210inline void Assembler::EmitUint8(uint8_t value) {
1211 buffer_.Emit<uint8_t>(value);
1212}
1213
1214inline void Assembler::EmitInt32(int32_t value) {
1215 buffer_.Emit<int32_t>(value);
1216}
1217
1218inline void Assembler::EmitRegisterOperand(int rm, int reg) {
1219 ASSERT(rm >= 0 && rm < 8);
1220 buffer_.Emit<uint8_t>(0xC0 + (rm << 3) + reg);
1221}
1222
1223inline void Assembler::EmitXmmRegisterOperand(int rm, XmmRegister reg) {
1224 EmitRegisterOperand(rm, static_cast<Register>(reg));
1225}
1226
1227inline void Assembler::EmitFixup(AssemblerFixup* fixup) {
1228 buffer_.EmitFixup(fixup);
1229}
1230
1231inline void Assembler::EmitOperandSizeOverride() {
1232 EmitUint8(0x66);
1233}
1234
1235} // namespace compiler
1236} // namespace dart
1237
1238#endif // RUNTIME_VM_COMPILER_ASSEMBLER_ASSEMBLER_IA32_H_
static void done(const char *config, const char *src, const char *srcOptions, const char *name)
Definition: DM.cpp:263
int count
Definition: FontMgrTest.cpp:50
bool equals(SkDrawable *a, SkDrawable *b)
#define DECLARE_ALU(op, opcode, opcode2, modrm_opcode)
#define ASSERT_EQUAL(expected, actual)
Definition: assert.h:309
static bool IsInt(intptr_t N, T value)
Definition: utils.h:313
static constexpr int ShiftForPowerOfTwo(T x)
Definition: utils.h:81
static bool IsUint(intptr_t N, T value)
Definition: utils.h:328
static constexpr bool IsPowerOfTwo(T x)
Definition: utils.h:76
Address(Register base, Register index, ScaleFactor scale, int32_t disp)
Address(Register index, ScaleFactor scale, int32_t disp)
Address & operator=(const Address &other)
Address(Register base, int32_t disp)
Address(Register base, Register index, ScaleFactor scale, Register r)
Address(Register index, ScaleFactor scale, Register r)
static Address Absolute(const uword addr)
Address(const Address &other)
void Stop(const char *message)
ObjectPoolBuilder & object_pool_builder()
void EmitFixup(AssemblerFixup *fixup)
void PushRegistersInOrder(std::initializer_list< Register > regs)
void mull(const Address &address)
void maxps(XmmRegister dst, XmmRegister src)
void PopRegisterPair(Register r0, Register r1)
void MoveUnboxedDouble(FpuRegister dst, FpuRegister src)
void jmp(Register reg)
void LoadClassId(Register result, Register object)
void imull(Register reg, const Address &address)
void Call(Address target)
void unpcklpd(XmmRegister dst, XmmRegister src)
void imull(Register reg)
void FloatNegate(XmmRegister f)
void AndImmediate(Register dst, Register src, int32_t value)
void call(Label *label)
void cvtdq2pd(XmmRegister dst, XmmRegister src)
void StoreUnboxedDouble(FpuRegister src, Register base, int32_t offset)
void CompareObject(Register reg, const Object &object)
void movsd(XmmRegister dst, XmmRegister src)
void MoveUnboxedSimd128(FpuRegister dst, FpuRegister src)
void minpd(XmmRegister dst, XmmRegister src)
void fildl(const Address &src)
void LoadImmediate(Register reg, int32_t immediate) override
void notl(Register reg)
void CombineHashes(Register dst, Register other) override
void cmovns(Register dst, Register src)
void BranchIfSmi(Register reg, Label *label, JumpDistance distance=kFarJump) override
void Jmp(const Code &code)
void LoadTaggedClassIdMayBeSmi(Register result, Register object)
void AndImmediate(Register dst, int32_t value) override
void movups(XmmRegister dst, const Address &src)
void idivl(Register reg)
void shrdl(Register dst, Register src, const Immediate &imm)
static constexpr intptr_t kEnterStubFramePushedWords
void TransitionNativeToGenerated(Register scratch, bool exit_safepoint, bool ignore_unwind_in_progress=false, bool set_tag=true)
void LoadSImmediate(XmmRegister dst, float value)
void Load(Register reg, const Address &address, OperandSize type, Condition cond)
void BranchIfZero(Register src, Label *label, JumpDistance distance=kFarJump)
void unpckhpd(XmmRegister dst, XmmRegister src)
void movq(const Address &dst, XmmRegister src)
void PushRegisterPair(Register r0, Register r1)
void StoreZero(const Address &address, Register temp=kNoRegister)
void shldl(Register dst, Register src, Register shifter)
void CompareClassId(Register object, intptr_t class_id, Register scratch)
void movl(Register dst, const Address &src)
void divl(Register reg)
void mulss(XmmRegister dst, XmmRegister src)
void IncrementSmiField(const Address &dest, int32_t increment)
void movd(Register dst, XmmRegister src)
void pxor(XmmRegister dst, XmmRegister src)
Assembler(ObjectPoolBuilder *object_pool_builder, intptr_t far_branch_level=0)
void jmp(const ExternalLabel *label)
void movlhps(XmmRegister dst, XmmRegister src)
void Load(Register dst, const Address &address, OperandSize sz=kFourBytes) override
void CallVmStub(const Code &code)
void movzxw(Register dst, const Address &src)
void movl(const Address &dst, Register src)
void ZeroInitSmiField(const Address &dest)
void pcmpeqq(XmmRegister dst, XmmRegister src)
void LoadDImmediate(XmmRegister dst, double value)
void lzcntl(Register dst, Register src)
void LoadFieldFromOffset(Register reg, Register base, int32_t offset, OperandSize type=kFourBytes) override
void decl(Register reg)
void cvtss2si(Register dst, XmmRegister src)
void movl(const Address &dst, const Immediate &imm)
void movd(XmmRegister dst, Register src)
void negateps(XmmRegister dst)
void movl(Register dst, const Immediate &src)
void cvtsi2ss(XmmRegister dst, Register src)
void filds(const Address &src)
void j(Condition condition, Label *label, JumpDistance distance=kFarJump)
void bt(Register base, int bit)
void SmiUntag(Register reg)
void TryAllocateObject(intptr_t cid, intptr_t instance_size, Label *failure, JumpDistance distance, Register instance_reg, Register temp_reg) override
void Jump(Label *label, JumpDistance distance=kFarJump)
void LoadAcquire(Register dst, const Address &address, OperandSize size=kFourBytes) override
void maxpd(XmmRegister dst, XmmRegister src)
void addpd(XmmRegister dst, XmmRegister src)
void LoadFromStack(Register dst, intptr_t depth)
void movss(const Address &dst, XmmRegister src)
void movmskpd(Register dst, XmmRegister src)
void leal(Register dst, const Address &src)
void shufps(XmmRegister dst, XmmRegister src, const Immediate &mask)
void zerowps(XmmRegister dst)
void shll(Register reg, const Immediate &imm)
void movb(const Address &dst, const Immediate &imm)
void shufpd(XmmRegister dst, XmmRegister src, const Immediate &mask)
void ret(const Immediate &imm)
void pushl(Register reg)
void negl(Register reg)
void J(Condition condition, const Code &code)
void CompareWithMemoryValue(Register value, Address address, OperandSize size=kFourBytes) override
void imull(const Address &address)
void PushRegister(Register r)
void Store(Register src, const Address &address, OperandSize sz=kFourBytes) override
void LoadMemoryValue(Register dst, Register base, int32_t offset)
void movups(const Address &dst, XmmRegister src)
void b(Label *label, Condition cond=AL)
void cvtpd2ps(XmmRegister dst, XmmRegister src)
void set1ps(XmmRegister dst, Register tmp, const Immediate &imm)
void orps(XmmRegister dst, XmmRegister src)
void mulps(XmmRegister dst, XmmRegister src)
void divsd(XmmRegister dst, XmmRegister src)
void roundsd(XmmRegister dst, XmmRegister src, RoundingMode mode)
void cmove(Register dst, Register src)
void FinalizeHashForSize(intptr_t bit_size, Register dst, Register scratch=kNoRegister) override
void pextrd(Register dst, XmmRegister src, const Immediate &imm)
void cvtps2pd(XmmRegister dst, XmmRegister src)
void pushl(const Immediate &imm)
void Align(intptr_t alignment, intptr_t offset)
void subpl(XmmRegister dst, XmmRegister src)
void movsxw(Register dst, const Address &src)
void mull(Register reg)
void movw(Register dst, const Address &src)
void Call(const Code &code, bool movable_target=false, CodeEntryKind entry_kind=CodeEntryKind::kNormal)
void cmppsneq(XmmRegister dst, XmmRegister src)
void mulsd(XmmRegister dst, XmmRegister src)
void divpd(XmmRegister dst, XmmRegister src)
void movmskps(Register dst, XmmRegister src)
void Store(const Object &value, const Address &address)
void movsxb(Register dst, const Address &src)
void sqrtss(XmmRegister dst, XmmRegister src)
void jmp(Label *label, JumpDistance distance=kFarJump)
void rsqrtps(XmmRegister dst)
static bool AddressCanHoldConstantIndex(const Object &constant, bool is_external, intptr_t cid, intptr_t index_scale)
void testl(const Address &address, const Immediate &imm)
void cmppseq(XmmRegister dst, XmmRegister src)
void testl(const Address &address, Register reg)
void EnterFullSafepoint(Register scratch)
void LoadClassById(Register result, Register class_id)
void cvtss2sd(XmmRegister dst, XmmRegister src)
void movzxw(Register dst, Register src)
void cmovs(Register dst, Register src)
void movw(const Address &dst, Register src)
void addsd(XmmRegister dst, const Address &src)
void LoadQImmediate(XmmRegister dst, simd128_value_t value)
void MoveMemoryToMemory(Address to, Address from, Register tmp)
void andps(XmmRegister dst, const Address &src)
void PushValueAtOffset(Register base, int32_t offset)
void LoadIsolate(Register dst)
void nop(int size=1)
void xorpd(XmmRegister dst, const Address &src)
void imull(Register reg, const Immediate &imm)
void movsd(XmmRegister dst, const Address &src)
void sarl(const Address &address, Register shifter)
void fistpl(const Address &dst)
void shll(const Address &operand, Register shifter)
void CheckAllocationCanary(Register top)
void addss(XmmRegister dst, const Address &src)
void cmppsnle(XmmRegister dst, XmmRegister src)
void shll(Register operand, Register shifter)
void SetReturnAddress(Register value)
void flds(const Address &src)
void LoadInt32FromBoxOrSmi(Register result, Register value) override
void incl(const Address &address)
void BranchIf(Condition condition, Label *label, JumpDistance distance=kFarJump)
void EnterOsrFrame(intptr_t extra_size)
void divss(XmmRegister dst, const Address &src)
void popl(const Address &address)
void bt(Register base, Register offset)
void comisd(XmmRegister a, XmmRegister b)
void fstps(const Address &dst)
void PushObject(const Object &object)
void pmovsxdq(XmmRegister dst, XmmRegister src)
void AddImmediate(Register reg, const Immediate &imm)
void andpd(XmmRegister dst, XmmRegister src)
void AndRegisters(Register dst, Register src1, Register src2=kNoRegister) override
void sqrtpd(XmmRegister dst)
void testb(const Address &address, const Immediate &imm)
void sarl(Register reg, const Immediate &imm)
void movzxb(Register dst, const Address &src)
void LoadUnboxedSimd128(FpuRegister dst, Register base, int32_t offset)
void StoreMemoryValue(Register src, Register base, int32_t offset)
void divss(XmmRegister dst, XmmRegister src)
void shrdl(const Address &dst, Register src, Register shifter)
void testl(Register reg1, Register reg2)
void TransitionGeneratedToNative(Register destination_address, Register new_exit_frame, Register new_exit_through_ffi, bool enter_safepoint)
void LoadImmediate(Register reg, Immediate immediate)
void mulss(XmmRegister dst, const Address &src)
void cvttsd2si(Register dst, XmmRegister src)
void cmpw(const Address &address, const Immediate &imm)
void AddImmediate(Register dest, Register src, int32_t value)
void mulsd(XmmRegister dst, const Address &src)
void incl(Register reg)
void PushImmediate(int32_t value)
void StoreToStack(Register src, intptr_t depth)
void subpd(XmmRegister dst, XmmRegister src)
void AddScaled(Register dest, Register base, Register index, ScaleFactor scale, int32_t disp) override
void movw(const Address &dst, const Immediate &imm)
void divsd(XmmRegister dst, const Address &src)
void LoadStaticFieldAddress(Register address, Register field, Register scratch, bool is_shared)
void SubRegisters(Register dest, Register src)
void StoreInternalPointer(Register object, const Address &dest, Register value)
void movb(const Address &dst, ByteRegister src)
void CompareRegisters(Register a, Register b)
void MulImmediate(Register reg, int32_t imm, OperandSize width=kFourBytes) override
void StoreObjectIntoObjectNoBarrier(Register object, const Address &dest, const Object &value, MemoryOrder memory_order=kRelaxedNonAtomic, OperandSize size=kFourBytes) override
void AddRegisters(Register dest, Register src)
void cmppslt(XmmRegister dst, XmmRegister src)
void sqrtsd(XmmRegister dst, XmmRegister src)
void andps(XmmRegister dst, XmmRegister src)
void Bind(Label *label) override
void ReserveAlignedFrameSpace(intptr_t frame_space)
void cmppsle(XmmRegister dst, XmmRegister src)
static intptr_t EntryPointToPcMarkerOffset()
void ExtendValue(Register to, Register from, OperandSize sz) override
void cmovno(Register dst, Register src)
void xorpd(XmmRegister dst, XmmRegister src)
void andpd(XmmRegister dst, const Address &src)
void RangeCheck(Register value, Register temp, intptr_t low, intptr_t high, RangeCheckCondition condition, Label *target) override
void cmovne(Register dst, Register src)
void enter(const Immediate &imm)
void setcc(Condition condition, ByteRegister dst)
void cvtsi2sd(XmmRegister dst, Register src)
void PopRegister(Register r)
void ArrayStoreBarrier(Register object, Register slot, Register value, CanBeSmi can_be_smi, Register scratch) override
void LslRegister(Register dst, Register shift) override
void movl(Register dst, Register src)
void xchgl(Register dst, Register src)
void subss(XmmRegister dst, XmmRegister src)
void OrImmediate(Register dst, int32_t value)
void StoreRelease(Register src, const Address &address, OperandSize size=kFourBytes) override
void movq(XmmRegister dst, const Address &src)
void xorps(XmmRegister dst, const Address &src)
void shrl(Register operand, Register shifter)
void subps(XmmRegister dst, XmmRegister src)
void SmiUntagOrCheckClass(Register object, intptr_t class_id, Register scratch, Label *is_smi)
void Call(Address target, Condition cond=AL)
void popcntl(Register dst, Register src)
void TryAllocateArray(intptr_t cid, intptr_t instance_size, Label *failure, JumpDistance distance, Register instance, Register end_address, Register temp)
void CallCFunction(Register target)
void WriteAllocationCanary(Register top)
void subss(XmmRegister dst, const Address &src)
void addpl(XmmRegister dst, XmmRegister src)
void subsd(XmmRegister dst, const Address &src)
void CallRuntime(const RuntimeEntry &entry, intptr_t argument_count)
void LockCmpxchgl(const Address &address, Register reg)
void LoadObject(Register rd, const Object &object, Condition cond=AL)
void CompareRegisters(Register rn, Register rm)
void CopyMemoryWords(Register src, Register dst, Register size, Register temp=kNoRegister)
void fnstcw(const Address &dst)
void negatepd(XmmRegister dst)
void CompareToStack(Register src, intptr_t depth)
void EnterDartFrame(intptr_t frame_size)
void LoadImmediate(Register rd, Immediate value, Condition cond=AL)
void addsd(XmmRegister dst, XmmRegister src)
void LoadObject(Register dst, const Object &object, bool movable_referent=false)
void fldcw(const Address &src)
static Address ElementAddressForRegIndex(bool is_external, intptr_t cid, intptr_t index_scale, bool index_unboxed, Register array, Register index, intptr_t extra_disp=0)
void movb(const Address &dst, Register src)
static Address VMTagAddress()
void LoadUniqueObject(Register dst, const Object &object)
void xorps(XmmRegister dst, XmmRegister src)
void cvtsd2ss(XmmRegister dst, XmmRegister src)
void CompareObjectRegisters(Register a, Register b)
void cvtsd2si(Register dst, XmmRegister src)
void bsfl(Register dst, Register src)
void notps(XmmRegister dst)
void MaybeTraceAllocation(intptr_t cid, Label *trace, Register temp_reg, JumpDistance distance=JumpDistance::kFarJump)
void j(Condition condition, const ExternalLabel *label)
void absps(XmmRegister dst)
void subsd(XmmRegister dst, XmmRegister src)
static bool IsSafeSmi(const Object &object)
void movsxb(Register dst, ByteRegister src)
void Drop(intptr_t stack_elements)
void imull(Register dst, Register src)
void DoubleAbs(XmmRegister reg)
void reciprocalps(XmmRegister dst)
void minps(XmmRegister dst, XmmRegister src)
void EnterCFrame(intptr_t frame_space)
void StoreBarrier(Register object, Register value, CanBeSmi can_be_smi, Register scratch) override
void testb(const Address &address, ByteRegister reg)
void AddImmediate(Register reg, int32_t value)
void call(const Address &address)
void VerifyStoreNeedsNoWriteBarrier(Register object, Register value) override
void CompareWords(Register reg1, Register reg2, intptr_t offset, Register count, Register temp, Label *equals) override
Object & GetSelfHandle() const
void addss(XmmRegister dst, XmmRegister src)
void shldl(Register dst, Register src, const Immediate &imm)
void testl(Register reg, const Immediate &imm)
void SubImmediate(Register reg, const Immediate &imm)
void mulpd(XmmRegister dst, XmmRegister src)
void pmovmskb(Register dst, XmmRegister src)
void movhlps(XmmRegister dst, XmmRegister src)
void movb(Register dst, const Address &src)
void BranchIfNotSmi(Register reg, Label *label, JumpDistance distance=kFarJump)
void CallCFunction(Address target)
void LslImmediate(Register dst, int32_t shift)
void divps(XmmRegister dst, XmmRegister src)
void EnterFrame(intptr_t frame_space)
void popl(Register reg)
static bool IsSafe(const Object &object)
void jmp(const Address &address)
void BranchIfBit(Register rn, intptr_t bit_number, Condition condition, Label *label, JumpDistance distance=kFarJump)
void abspd(XmmRegister dst)
void StoreIntoSmiField(const Address &dest, Register value)
void Jump(Register target)
void addps(XmmRegister dst, XmmRegister src)
void call(const ExternalLabel *label)
void fistps(const Address &dst)
void LoadClassIdMayBeSmi(Register result, Register object)
void sarl(Register operand, Register shifter)
void DoubleNegate(XmmRegister d)
void LoadUnboxedDouble(FpuRegister dst, Register base, int32_t offset)
void LoadIndexedPayload(Register dst, Register base, int32_t payload_offset, Register index, ScaleFactor scale, OperandSize sz=kFourBytes) override
void shrl(Register reg, const Immediate &imm)
void cvttss2si(Register dst, XmmRegister src)
void movss(XmmRegister dst, XmmRegister src)
void LoadIsolateGroup(Register dst)
void LoadFieldAddressForRegOffset(Register address, Register instance, Register offset_in_words_as_smi) override
void cmovgel(Register dst, Register src)
void movsd(const Address &dst, XmmRegister src)
void BranchOnMonomorphicCheckedEntryJIT(Label *label)
void Store(Register reg, const Address &address, OperandSize type, Condition cond)
void movzxb(Register dst, ByteRegister src)
void SmiUntag(Register reg, Condition cond=AL)
void movss(XmmRegister dst, const Address &src)
void cmpxchgl(const Address &address, Register reg)
void MoveRegister(Register rd, Register rm, Condition cond)
void LoadFieldAddressForOffset(Register address, Register instance, int32_t offset) override
void decl(const Address &address)
static constexpr intptr_t kCallExternalLabelSize
void StoreUnboxedSimd128(FpuRegister dst, Register base, int32_t offset)
void sqrtps(XmmRegister dst)
void fldl(const Address &src)
void unpckhps(XmmRegister dst, XmmRegister src)
void cmovlessl(Register dst, Register src)
void EnsureHasClassIdInDEBUG(intptr_t cid, Register src, Register scratch, bool can_be_null=false) override
void orpd(XmmRegister dst, XmmRegister src)
void cmpb(const Address &address, const Immediate &imm)
void call(Register reg)
void LoadObjectSafely(Register dst, const Object &object)
void shrdl(Register dst, Register src, Register shifter)
void pushl(const Address &address)
void AddImmediate(Register rd, int32_t value, Condition cond=AL)
static Address ElementAddressForIntIndex(bool is_external, intptr_t cid, intptr_t index_scale, Register array, intptr_t index, intptr_t extra_disp=0)
void cmppsnlt(XmmRegister dst, XmmRegister src)
void LsrImmediate(Register dst, int32_t shift) override
void ExitFullSafepoint(Register scratch, bool ignore_unwind_in_progress)
void movsxw(Register dst, Register src)
void shldl(const Address &operand, Register src, Register shifter)
void fstpl(const Address &dst)
void bsrl(Register dst, Register src)
static constexpr intptr_t kEntryPointToPcMarkerOffset
void SmiTag(Register reg) override
void unpcklps(XmmRegister dst, XmmRegister src)
void CompareImmediate(Register reg, int32_t immediate, OperandSize width=kFourBytes) override
void comiss(XmmRegister a, XmmRegister b)
void ffree(intptr_t value)
void ArithmeticShiftRightImmediate(Register reg, intptr_t shift) override
void movaps(XmmRegister dst, XmmRegister src)
FieldAddress & operator=(const FieldAddress &other)
FieldAddress(Register base, Register r)
FieldAddress(Register base, Register index, ScaleFactor scale, Register r)
FieldAddress(const FieldAddress &other)
FieldAddress(Register base, Register index, ScaleFactor scale, int32_t disp)
FieldAddress(Register base, int32_t disp)
Immediate(const Immediate &other)
bool Equals(const Operand &other) const
void SetSIB(ScaleFactor scale, Register index, Register base)
Register base() const
int32_t disp32() const
Register index() const
Operand(const Operand &other)
void SetDisp8(int8_t disp)
Operand & operator=(const Operand &other)
void SetModRM(int mod, Register rm)
Register rm() const
void SetDisp32(int32_t disp)
ScaleFactor scale() const
static word host_offset_or_field_id_offset()
static word shared_field_table_values_offset()
static word field_table_values_offset()
#define ASSERT(E)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition: main.cc:19
VkInstance instance
Definition: main.cc:48
struct MyStruct a[10]
#define FATAL(error)
uint8_t value
GAsyncResult * result
uint32_t * target
int argument_count
Definition: fuchsia.cc:52
bool IsSmi(int64_t v)
Definition: runtime_api.cc:31
Object & NewZoneHandle(Zone *zone)
Definition: runtime_api.cc:141
bool HasIntegerValue(const dart::Object &object, int64_t *value)
Definition: runtime_api.cc:239
Definition: dart_vm.cc:33
@ TIMES_16
const Register THR
static constexpr intptr_t kAllocationCanary
Definition: globals.h:181
uintptr_t uword
Definition: globals.h:501
@ NOT_CARRY
Definition: constants_x86.h:35
@ NOT_ZERO
@ kNoRegister
Definition: constants_arm.h:99
const intptr_t cid
@ kSmiTagSize
@ kHeapObjectTag
@ kSmiTagMask
@ kSmiTagShift
COMPILE_ASSERT(kUnreachableReference==WeakTable::kNoValue)
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
Definition: switches.h:228
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
dst
Definition: cp.py:12
dest
Definition: zip.py:79
int32_t width
const Scalar scale
SeparatedVector2 offset