5#ifndef RUNTIME_VM_COMPILER_ASSEMBLER_ASSEMBLER_BASE_H_
6#define RUNTIME_VM_COMPILER_ASSEMBLER_ASSEMBLER_BASE_H_
8#if defined(DART_PRECOMPILED_RUNTIME)
9#error "AOT runtime should not use compiler sources (including header files)"
23#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) || \
24 defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
33#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
50 LRState(
const LRState&) =
default;
51 LRState& operator=(
const LRState&) =
default;
53 bool LRContainsReturnAddress()
const {
55 return (state_ & kLRContainsReturnAddressMask) != 0;
58 LRState SetLRContainsReturnAddress(
bool v)
const {
60 return LRState(frames_, v ? (state_ | 1) : (state_ & ~1));
65 LRState EnterFrame()
const {
68 constexpr auto kMaxFrames = (
sizeof(state_) *
kBitsPerByte) - 1;
71 return LRState(frames_ + 1, state_ << 1);
78 LRState LeaveFrame()
const {
81 return LRState(frames_ - 1, state_ >> 1);
84 bool IsUnknown()
const {
return *
this == Unknown(); }
86 static LRState Unknown() {
return LRState(kUnknownMarker, kUnknownMarker); }
88 static LRState OnEntry() {
return LRState(0, 1); }
90 static LRState Clobbered() {
return LRState(0, 0); }
93 return frames_ == other.frames_ && state_ == other.state_;
97 LRState(uint8_t frames, uint8_t
state) : frames_(frames), state_(
state) {}
100 static constexpr uint8_t kLRContainsReturnAddressMask = 1;
102 static constexpr uint8_t kUnknownMarker = 0xFF;
116#define READS_RETURN_ADDRESS_FROM_LR(block) \
118 RELEASE_ASSERT(__ lr_state().LRContainsReturnAddress()); \
119 constexpr Register LR = LR_DO_NOT_USE_DIRECTLY; \
127#define WRITES_RETURN_ADDRESS_TO_LR(block) READS_RETURN_ADDRESS_FROM_LR(block)
131#define CLOBBERS_LR(block) \
133 RELEASE_ASSERT(!(__ lr_state().LRContainsReturnAddress())); \
134 constexpr Register LR = LR_DO_NOT_USE_DIRECTLY; \
142#define SPILLS_RETURN_ADDRESS_FROM_LR_TO_REGISTER(block) \
144 READS_RETURN_ADDRESS_FROM_LR(block); \
145 __ set_lr_state(__ lr_state().SetLRContainsReturnAddress(false)); \
151#define RESTORES_RETURN_ADDRESS_FROM_REGISTER_TO_LR(block) \
153 CLOBBERS_LR(block); \
154 __ set_lr_state(__ lr_state().SetLRContainsReturnAddress(true)); \
160#define SPILLS_LR_TO_FRAME(block) \
162 constexpr Register LR = LR_DO_NOT_USE_DIRECTLY; \
165 __ set_lr_state(__ lr_state().EnterFrame()); \
172#define RESTORES_LR_FROM_FRAME(block) \
174 CLOBBERS_LR(block); \
175 __ set_lr_state(__ lr_state().LeaveFrame()); \
197#if defined(HAS_SMI_63_BITS)
205#if defined(TARGET_ARCH_IS_64_BIT)
218#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
232 bool IsBound()
const {
return position_ != -1; }
235 return unresolved_cb_ != -1 || unresolved_cj_ != -1 ||
236 unresolved_b_ != -1 || unresolved_j_ != -1 || unresolved_far_ != -1;
240 int32_t position_ = -1;
241 void BindTo(intptr_t position) {
244 position_ = position;
252#define DEFINE_BRANCH_CLASS(name) \
253 int32_t unresolved_##name##_ = -1; \
254 int32_t link_##name(int32_t position) { \
255 ASSERT(position > unresolved_##name##_); \
257 if (unresolved_##name##_ == -1) { \
260 offset = position - unresolved_##name##_; \
261 ASSERT(offset > 0); \
263 unresolved_##name##_ = position; \
266 DEFINE_BRANCH_CLASS(cb);
267 DEFINE_BRANCH_CLASS(cj);
268 DEFINE_BRANCH_CLASS(
b);
269 DEFINE_BRANCH_CLASS(j);
270 DEFINE_BRANCH_CLASS(far);
272 friend class MicroAssembler;
278 Label() : position_(0), unresolved_(0) {
280 for (
int i = 0;
i < kMaxUnresolvedBranches;
i++) {
281 unresolved_near_positions_[
i] = -1;
296 return IsBound() ? -position_ - kBias : position_ - kBias;
301 return position_ - kBias;
306 return unresolved_near_positions_[--unresolved_];
309 bool IsBound()
const {
return position_ < 0; }
310 bool IsUnused()
const {
return position_ == 0 && unresolved_ == 0; }
312 bool HasNear()
const {
return unresolved_ != 0; }
315#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_IA32)
316 static constexpr int kMaxUnresolvedBranches = 20;
318 static constexpr int kMaxUnresolvedBranches = 1;
325 static constexpr int kBias = 4;
328 intptr_t unresolved_;
329 intptr_t unresolved_near_positions_[kMaxUnresolvedBranches];
330#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
335 LRState lr_state_ = LRState::Unknown();
337 void UpdateLRState(LRState new_state) {
338 if (lr_state_.IsUnknown()) {
339 lr_state_ = new_state;
346 void Reinitialize() { position_ = 0; }
348#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
349 void BindTo(intptr_t position, LRState lr_state)
351 void BindTo(intptr_t position)
356 position_ = -position - kBias;
358#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
359 UpdateLRState(lr_state);
363#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
364 void LinkTo(intptr_t position, LRState lr_state)
366 void LinkTo(intptr_t position)
370 position_ = position + kBias;
372#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
373 UpdateLRState(lr_state);
377 void NearLinkTo(intptr_t position) {
379 ASSERT(unresolved_ < kMaxUnresolvedBranches);
380 unresolved_near_positions_[unresolved_++] = position;
401 const uword address_;
422 void set_previous(AssemblerFixup* previous) { previous_ = previous; }
424 intptr_t position()
const {
return position_; }
425 void set_position(intptr_t position) { position_ = position; }
437 template <
typename T>
440#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) || \
441 defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
447 *
reinterpret_cast<T*
>(cursor_) =
value;
449 cursor_ +=
sizeof(
T);
452 template <
typename T>
454 ASSERT(
Size() >=
static_cast<intptr_t
>(
sizeof(
T)));
455 cursor_ -=
sizeof(
T);
461 template <
typename T>
464 position <= (
Size() -
static_cast<intptr_t
>(
sizeof(
T))));
465#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) || \
466 defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
472 return *
reinterpret_cast<T*
>(contents_ + position);
476 template <
typename T>
479 position <= (
Size() -
static_cast<intptr_t
>(
sizeof(
T))));
480#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) || \
481 defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
487 *
reinterpret_cast<T*
>(contents_ + position) =
value;
493 ASSERT(fixups_processed_);
495 return *pointer_offsets_;
498#if defined(TARGET_ARCH_IA32)
500 void EmitObject(
const Object&
object);
505 fixup->set_previous(fixup_);
506 fixup->set_position(
Size());
515 intptr_t
Size()
const {
return cursor_ - contents_; }
540 intptr_t ComputeGap() {
return buffer_->Capacity() - buffer_->
Size(); }
543 bool has_ensured_capacity_;
562 void Reset() { cursor_ = contents_; }
568 static constexpr intptr_t kMinimumGap = 32;
576 bool fixups_processed_;
579 uword cursor()
const {
return cursor_; }
580 uword limit()
const {
return limit_; }
581 intptr_t Capacity()
const {
582 ASSERT(limit_ >= contents_);
583 return (limit_ - contents_) + kMinimumGap;
587 void ProcessFixups(
const MemoryRegion&
region);
592 return data + capacity - kMinimumGap;
595 void ExtendCapacity();
644#if defined(DART_COMPRESSED_POINTERS)
693 intptr_t instance_size,
751 Register offset_in_words_as_smi) = 0;
892#if defined(DART_COMPRESSED_POINTERS)
901 Register offset_in_words_as_smi) = 0;
1075#if !defined(TARGET_ARCH_IS_32_BIT)
1081#if defined(TARGET_ARCH_IS_32_BIT)
1162 bool can_be_null =
false) = 0;
1195 intptr_t pc_offset_;
1234 Stop(
"Expected Smi");
1290 intptr_t frame_size,
1291 bool preserve_registers);
1302 const bool preserve_registers_;
static void done(const char *config, const char *src, const char *srcOptions, const char *name)
static uint32_t hash(const SkShaderBase::GradientInfo &v)
bool equals(SkDrawable *a, SkDrawable *b)
#define RELEASE_ASSERT(cond)
virtual void StoreRelease(Register src, const Address &address, OperandSize size=kWordBytes)=0
void LoadCompressedField(Register dst, const FieldAddress &address)
void LoadCompressedSmiField(Register dst, const FieldAddress &address)
bool has_monomorphic_entry() const
intptr_t CountPointerOffsets() const
virtual void TryAllocateObject(intptr_t cid, intptr_t instance_size, Label *failure, JumpDistance distance, Register instance_reg, Register temp)=0
void FinalizeHash(Register hash, Register scratch=TMP)
void UnrolledMemCopy(Register dst_base, intptr_t dst_offset, Register src_base, intptr_t src_offset, intptr_t size, Register temp)
void LoadCompressedSmi(Register dst, const Address &address)
virtual void StoreBarrier(Register object, Register value, CanBeSmi can_be_smi, Register scratch)=0
intptr_t CodeSize() const
virtual void LoadIndexedPayload(Register dst, Register base, int32_t offset, Register index, ScaleFactor scale, OperandSize sz=kWordBytes)=0
void StoreReleaseCompressedToOffset(Register src, Register base, int32_t offset=0)
virtual void FinalizeHashForSize(intptr_t bit_size, Register hash, Register scratch=TMP)=0
void StoreReleaseCompressed(Register src, const Address &address)
virtual void LoadFieldAddressForOffset(Register reg, Register base, int32_t offset)=0
void Untested(const char *message)
void TryAllocate(const Class &cls, Label *failure, JumpDistance distance, Register instance_reg, Register temp)
void Stop(const char *message)
void LoadCompressed(Register dst, const Address &address)
virtual void LoadInt64FromBoxOrSmi(Register result, Register value)=0
virtual void RangeCheck(Register value, Register temp, intptr_t low, intptr_t high, RangeCheckCondition condition, Label *target)=0
void LoadCompressedFieldFromOffset(Register dst, Register base, int32_t offset)
virtual void LoadInt32FromBoxOrSmi(Register result, Register value)=0
bool has_monomorphic_entry_
ObjectPoolBuilder & object_pool_builder()
virtual void CompareWords(Register reg1, Register reg2, intptr_t offset, Register count, Register temp, Label *equals)=0
void LoadCompressedSmiFromOffset(Register dst, Register base, int32_t offset)
void LoadCompressedSmiFieldFromOffset(Register dst, Register base, int32_t offset)
virtual void LslRegister(Register dst, Register shift)=0
void StoreReleaseToOffset(Register src, Register base, int32_t offset=0, OperandSize size=kWordBytes)
AssemblerBase(ObjectPoolBuilder *object_pool_builder)
intptr_t unchecked_entry_offset_
virtual void MoveRegister(Register dst, Register src)
void LoadWordFromBoxOrSmi(Register result, Register value)
void StoreIntoObjectNoBarrier(Register object, const Address &address, Register value, MemoryOrder memory_order=kRelaxedNonAtomic, OperandSize size=kWordBytes)
void StoreToSlot(Register src, Register base, const Slot &slot, CanBeSmi can_be_smi, MemoryOrder memory_order=kRelaxedNonAtomic, Register scratch=TMP)
void LoadAcquireFromOffset(Register dst, Register base, int32_t offset=0, OperandSize size=kWordBytes)
void LoadCompressedFieldAddressForRegOffset(Register address, Register instance, Register offset_in_words_as_smi)
intptr_t UncheckedEntryOffset() const
virtual void StoreFieldToOffset(Register src, Register base, int32_t offset, OperandSize sz=kWordBytes)
virtual void StoreIntoObjectOffsetNoBarrier(Register object, int32_t offset, Register value, MemoryOrder memory_order=kRelaxedNonAtomic, OperandSize size=kWordBytes)
uword CodeAddress(intptr_t offset)
virtual void SmiTag(Register r)=0
void BindUncheckedEntryPoint()
void LoadCompressedFromOffset(Register dst, Register base, int32_t offset)
const ZoneGrowableArray< intptr_t > & GetPointerOffsets() const
void LoadSmiFieldFromOffset(Register dst, Register base, int32_t offset)
virtual void LoadFieldAddressForRegOffset(Register address, Register instance, Register offset_in_words_as_smi)=0
void LoadField(Register dst, const FieldAddress &address, OperandSize sz=kWordBytes)
virtual void LoadAcquire(Register dst, const Address &address, OperandSize size=kWordBytes)=0
virtual void MoveAndSmiTagRegister(Register dst, Register src)
void FinalizeInstructions(const MemoryRegion ®ion)
void LoadIndexedCompressed(Register dst, Register base, int32_t offset, Register index)
void ExtendNonNegativeSmi(Register dst)
const GrowableArray< CodeComment * > & comments() const
void StoreCompressedIntoObject(Register object, const Address &address, Register value, CanBeSmi can_be_smi=kValueCanBeSmi, MemoryOrder memory_order=kRelaxedNonAtomic, Register scratch=TMP)
bool should_be_aligned() const
void LoadFromSlot(Register dst, Register base, const Slot &slot)
void static bool EmittingComments()
void StoreToSlotNoBarrier(Register src, Register base, const Slot &slot, MemoryOrder memory_order=kRelaxedNonAtomic)
virtual void BranchIfSmi(Register reg, Label *label, JumpDistance distance=kFarJump)=0
virtual void LoadFromOffset(Register dst, Register base, int32_t offset, OperandSize sz=kWordBytes)
virtual void CompareWithMemoryValue(Register value, Address address, OperandSize size=kWordBytes)=0
virtual void ExtendAndSmiTagValue(Register dst, Register src, OperandSize sz)
virtual void CompareImmediate(Register reg, target::word imm, OperandSize width=kWordBytes)=0
void StoreCompressedIntoObjectOffsetNoBarrier(Register object, int32_t offset, Register value, MemoryOrder memory_order=kRelaxedNonAtomic)
void LoadAcquireCompressedFromOffset(Register dst, Register base, int32_t offset)
virtual void ArithmeticShiftRightImmediate(Register reg, intptr_t shift)=0
void StoreObjectIntoObjectOffsetNoBarrier(Register object, int32_t offset, const Object &value, MemoryOrder memory_order=kRelaxedNonAtomic, OperandSize size=kWordBytes)
virtual void VerifyStoreNeedsNoWriteBarrier(Register object, Register value)=0
void LoadTypeClassId(Register dst, Register src)
intptr_t InsertAlignedRelocation(BSS::Relocation reloc)
virtual void CombineHashes(Register dst, Register other)=0
virtual void StoreIntoObjectOffset(Register object, int32_t offset, Register value, CanBeSmi can_be_smi=kValueCanBeSmi, MemoryOrder memory_order=kRelaxedNonAtomic, Register scratch=TMP, OperandSize size=kWordBytes)
virtual void LoadFieldFromOffset(Register dst, Register base, int32_t offset, OperandSize sz=kWordBytes)
virtual void AndRegisters(Register dst, Register src1, Register src2=kNoRegister)=0
void LoadAcquireCompressed(Register dst, const Address &address)
virtual void Load(Register dst, const Address &address, OperandSize sz=kWordBytes)=0
void mark_should_be_aligned()
void StoreCompressedObjectIntoObjectOffsetNoBarrier(Register object, int32_t offset, const Object &value, MemoryOrder memory_order=kRelaxedNonAtomic)
virtual void Bind(Label *label)=0
virtual void ExtendValue(Register dst, Register src, OperandSize sz)=0
void StoreCompressedIntoObjectNoBarrier(Register object, const Address &address, Register value, MemoryOrder memory_order=kRelaxedNonAtomic)
virtual void StoreObjectIntoObjectNoBarrier(Register object, const Address &address, const Object &value, MemoryOrder memory_order=kRelaxedNonAtomic, OperandSize size=kWordBytes)=0
void StoreCompressedIntoObjectOffset(Register object, int32_t offset, Register value, CanBeSmi can_be_smi=kValueCanBeSmi, MemoryOrder memory_order=kRelaxedNonAtomic, Register scratch=TMP)
virtual void AddScaled(Register dst, Register base, Register index, ScaleFactor scale, int32_t disp)=0
virtual void ArrayStoreBarrier(Register object, Register slot, Register value, CanBeSmi can_be_smi, Register scratch)=0
void LoadSmi(Register dst, const Address &address)
virtual void StoreCompressedObjectIntoObjectNoBarrier(Register object, const Address &address, const Object &value, MemoryOrder memory_order=kRelaxedNonAtomic)
bool HasObjectPoolBuilder() const
virtual void StoreToOffset(Register src, Register base, int32_t offset, OperandSize sz=kWordBytes)
void LoadAbstractTypeNullability(Register dst, Register type)
virtual void LsrImmediate(Register dst, int32_t shift)=0
void LoadSmiFromOffset(Register dst, Register base, int32_t offset)
virtual void AndImmediate(Register dst, target::word imm)=0
void StoreIntoArray(Register object, Register slot, Register value, CanBeSmi can_value_be_smi=kValueCanBeSmi, Register scratch=TMP, OperandSize size=kWordBytes)
void StoreCompressedIntoArray(Register object, Register slot, Register value, CanBeSmi can_value_be_smi=kValueCanBeSmi, Register scratch=TMP)
void LoadSmiField(Register dst, const FieldAddress &address)
void Comment(const char *format,...) PRINTF_ATTRIBUTE(2
void StoreIntoObject(Register object, const Address &address, Register value, CanBeSmi can_be_smi=kValueCanBeSmi, MemoryOrder memory_order=kRelaxedNonAtomic, Register scratch=TMP, OperandSize size=kWordBytes)
virtual void MulImmediate(Register dst, target::word imm, OperandSize=kWordBytes)=0
virtual void EnsureHasClassIdInDEBUG(intptr_t cid, Register src, Register scratch, bool can_be_null=false)=0
void MsanUnpoison(Register base, intptr_t length_in_bytes)
void VerifySmi(Register dst)
void CompareAbstractTypeNullabilityWith(Register type, int8_t value, Register scratch)
void Unreachable(const char *message)
intptr_t prologue_offset() const
virtual void LoadImmediate(Register dst, target::word imm)=0
void Unimplemented(const char *message)
virtual void Store(Register src, const Address &address, OperandSize sz=kWordBytes)=0
EnsureCapacity(AssemblerBuffer *buffer)
void Store(intptr_t position, T value)
void EmitFixup(AssemblerFixup *fixup)
const ZoneGrowableArray< intptr_t > & pointer_offsets() const
bool HasEnsuredCapacity() const
T Load(intptr_t position)
void FinalizeInstructions(const MemoryRegion ®ion)
intptr_t CountPointerOffsets() const
intptr_t GetPosition() const
uword Address(intptr_t position)
virtual bool IsPointerOffset() const =0
virtual ~AssemblerFixup()
virtual void Process(const MemoryRegion ®ion, intptr_t position)=0
ExternalLabel(uword address)
intptr_t LinkPosition() const
intptr_t Position() const
LeafRuntimeScope(Assembler *assembler, intptr_t frame_size, bool preserve_registers)
void Call(const RuntimeEntry &entry, intptr_t argument_count)
static uword GetInstanceSize(const dart::Class &handle)
static classid_t GetId(const dart::Class &handle)
uint32_t uint32_t * format
ClipOpAndAA opAA SkRegion region
constexpr OperandSize kWordBytes
constexpr intptr_t kBitsPerByte
constexpr bool operator==(Register r, LinkRegister)
constexpr intptr_t kBitsPerInt32
static T LoadUnaligned(const T *ptr)
static void StoreUnaligned(T *ptr, T value)
static int8_t data[kExtLength]
DECLARE_FLAG(bool, show_invisible_frames)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
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