[vm] Use dmb ishst instead of dmb ish for store-store fence.
TEST=ci Change-Id: Id7fb33bb4d9626ad420fd5aac2df86b47bd5c7bf Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/459662 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Aprelev <aam@google.com>
This commit is contained in:
committed by
Commit Queue
parent
c1fff5ea8f
commit
8c73b534f5
@@ -153,6 +153,28 @@ static inline T LoadRelaxed(const T* ptr) {
|
||||
std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
inline void StoreStoreFence() {
|
||||
#if defined(HOST_ARCH_ARM) && defined(_MSC_VER)
|
||||
__dmb(_ARM_BARRIER_ISHST);
|
||||
#elif defined(HOST_ARCH_ARM64) && defined(_MSC_VER)
|
||||
__dmb(_ARM64_BARRIER_ISHST);
|
||||
#elif defined(HOST_ARCH_ARM64) && defined(__GNUC__)
|
||||
__asm__ __volatile__("dmb ishst" : : : "memory");
|
||||
#elif defined(HOST_ARCH_ARM) && defined(__GNUC__)
|
||||
__asm__ __volatile__("dmb ishst" : : : "memory");
|
||||
#elif defined(HOST_ARCH_RISCV32) && defined(__GNUC__)
|
||||
__asm__ __volatile__("fence w,w" : : : "memory");
|
||||
#elif defined(HOST_ARCH_RISCV64) && defined(__GNUC__)
|
||||
__asm__ __volatile__("fence w,w" : : : "memory");
|
||||
#else
|
||||
// GCC warns that TSAN doesn't understand thread fences.
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic ignored "-Wtsan"
|
||||
#endif
|
||||
std::atomic_thread_fence(std::memory_order_release);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace dart
|
||||
|
||||
#endif // RUNTIME_PLATFORM_ATOMIC_H_
|
||||
|
||||
@@ -527,11 +527,6 @@ void Assembler::strex(Register rd, Register rt, Register rn, Condition cond) {
|
||||
Emit(encoding);
|
||||
}
|
||||
|
||||
void Assembler::dmb() {
|
||||
// Emit a `dmb ish` instruction.
|
||||
Emit(kDataMemoryBarrier);
|
||||
}
|
||||
|
||||
static int32_t BitFieldExtractEncoding(bool sign_extend,
|
||||
Register rd,
|
||||
Register rn,
|
||||
|
||||
@@ -438,12 +438,12 @@ class Assembler : public AssemblerBase {
|
||||
const Address& address,
|
||||
OperandSize size = kFourBytes) override {
|
||||
Load(dst, address, size);
|
||||
dmb();
|
||||
dmb_ish();
|
||||
}
|
||||
void StoreRelease(Register src,
|
||||
const Address& address,
|
||||
OperandSize size = kFourBytes) override {
|
||||
dmb();
|
||||
dmb_ish();
|
||||
Store(src, address, size);
|
||||
}
|
||||
|
||||
@@ -469,6 +469,8 @@ class Assembler : public AssemblerBase {
|
||||
// Debugging and bringup support.
|
||||
void Breakpoint() override { bkpt(0); }
|
||||
|
||||
void StoreStoreFence() override { dmb_ishst(); }
|
||||
|
||||
// Data-processing instructions.
|
||||
void and_(Register rd, Register rn, Operand o, Condition cond = AL);
|
||||
void ands(Register rd, Register rn, Operand o, Condition cond = AL);
|
||||
@@ -601,7 +603,8 @@ class Assembler : public AssemblerBase {
|
||||
void ldrex(Register rd, Register rn, Condition cond = AL);
|
||||
void strex(Register rd, Register rt, Register rn, Condition cond = AL);
|
||||
|
||||
void dmb();
|
||||
void dmb_ish() { Emit(kDMB_ISH); }
|
||||
void dmb_ishst() { Emit(kDMB_ISHST); }
|
||||
|
||||
// Media instructions.
|
||||
void sbfx(Register rd,
|
||||
@@ -1041,13 +1044,13 @@ class Assembler : public AssemblerBase {
|
||||
void InitializeHeader(Register tags, Register object) {
|
||||
str(tags, FieldAddress(object, target::Object::tags_offset()));
|
||||
#if defined(TARGET_HAS_FAST_WRITE_WRITE_FENCE)
|
||||
dmb();
|
||||
StoreStoreFence();
|
||||
#endif
|
||||
}
|
||||
void InitializeHeaderUntagged(Register tags, Register object) {
|
||||
str(tags, Address(object, target::Object::tags_offset()));
|
||||
#if defined(TARGET_HAS_FAST_WRITE_WRITE_FENCE)
|
||||
dmb();
|
||||
StoreStoreFence();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -564,6 +564,8 @@ class Assembler : public AssemblerBase {
|
||||
// Debugging and bringup support.
|
||||
void Breakpoint() override { brk(0); }
|
||||
|
||||
void StoreStoreFence() override { dmb_ishst(); }
|
||||
|
||||
void SetPrologueOffset() {
|
||||
if (prologue_offset_ == -1) {
|
||||
prologue_offset_ = CodeSize();
|
||||
@@ -1242,7 +1244,8 @@ class Assembler : public AssemblerBase {
|
||||
// Breakpoint.
|
||||
void brk(uint16_t imm) { EmitExceptionGenOp(BRK, imm); }
|
||||
|
||||
void dmb() { Emit(kDataMemoryBarrier); }
|
||||
void dmb_ish() { Emit(kDMB_ISH); }
|
||||
void dmb_ishst() { Emit(kDMB_ISHST); }
|
||||
|
||||
// Double floating point.
|
||||
bool fmovdi(VRegister vd, double immd) {
|
||||
@@ -1963,13 +1966,13 @@ class Assembler : public AssemblerBase {
|
||||
void InitializeHeader(Register header, Register object) {
|
||||
str(header, FieldAddress(object, target::Object::tags_offset()));
|
||||
#if defined(TARGET_HAS_FAST_WRITE_WRITE_FENCE)
|
||||
dmb();
|
||||
StoreStoreFence();
|
||||
#endif
|
||||
}
|
||||
void InitializeHeaderUntagged(Register header, Register object) {
|
||||
str(header, Address(object, target::Object::tags_offset()));
|
||||
#if defined(TARGET_HAS_FAST_WRITE_WRITE_FENCE)
|
||||
dmb();
|
||||
StoreStoreFence();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -630,6 +630,8 @@ class AssemblerBase : public StackResource {
|
||||
|
||||
virtual void Breakpoint() = 0;
|
||||
|
||||
virtual void StoreStoreFence() = 0;
|
||||
|
||||
virtual void SmiTag(Register r) = 0;
|
||||
|
||||
virtual void Bind(Label* label) = 0;
|
||||
|
||||
@@ -1199,6 +1199,8 @@ class Assembler : public AssemblerBase {
|
||||
// Debugging and bringup support.
|
||||
void Breakpoint() override { int3(); }
|
||||
|
||||
void StoreStoreFence() override {}
|
||||
|
||||
// Check if the given value is an integer value that can be directly
|
||||
// embedded into the code without additional XORing with jit_cookie.
|
||||
// We consider 16-bit integers, powers of two and corresponding masks
|
||||
|
||||
@@ -1027,6 +1027,8 @@ class Assembler : public MicroAssembler {
|
||||
// Debugging and bringup support.
|
||||
void Breakpoint() override { trap(); }
|
||||
|
||||
void StoreStoreFence() override { fence(kWrite, kWrite); }
|
||||
|
||||
void SetPrologueOffset() {
|
||||
if (prologue_offset_ == -1) {
|
||||
prologue_offset_ = CodeSize();
|
||||
|
||||
@@ -1345,6 +1345,8 @@ class Assembler : public AssemblerBase {
|
||||
// Debugging and bringup support.
|
||||
void Breakpoint() override { int3(); }
|
||||
|
||||
void StoreStoreFence() override {}
|
||||
|
||||
static bool AddressCanHoldConstantIndex(const Object& constant,
|
||||
bool is_external,
|
||||
intptr_t cid,
|
||||
|
||||
@@ -1444,9 +1444,10 @@ void ARMDecoder::InstructionDecode(uword pc) {
|
||||
if (instr->ConditionField() == kSpecialCondition) {
|
||||
if (instr->InstructionBits() == static_cast<int32_t>(0xf57ff01f)) {
|
||||
Format(instr, "clrex");
|
||||
} else if (instr->InstructionBits() ==
|
||||
static_cast<int32_t>(kDataMemoryBarrier)) {
|
||||
} else if (instr->InstructionBits() == static_cast<int32_t>(kDMB_ISH)) {
|
||||
Format(instr, "dmb ish");
|
||||
} else if (instr->InstructionBits() == static_cast<int32_t>(kDMB_ISHST)) {
|
||||
Format(instr, "dmb ishst");
|
||||
} else {
|
||||
if (instr->IsSIMDDataProcessing()) {
|
||||
DecodeSIMDDataProcessing(instr);
|
||||
|
||||
@@ -994,10 +994,14 @@ void ARM64Decoder::DecodeSystem(Instr* instr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (instr->InstructionBits() == kDataMemoryBarrier) {
|
||||
if (instr->InstructionBits() == kDMB_ISH) {
|
||||
Format(instr, "dmb ish");
|
||||
return;
|
||||
}
|
||||
if (instr->InstructionBits() == kDMB_ISHST) {
|
||||
Format(instr, "dmb ishst");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((instr->Bits(0, 8) == 0x1f) && (instr->Bits(12, 4) == 2) &&
|
||||
(instr->Bits(16, 3) == 3) && (instr->Bits(19, 2) == 0) &&
|
||||
|
||||
@@ -1318,8 +1318,9 @@ float ReciprocalStep(float op1, float op2);
|
||||
float ReciprocalSqrtEstimate(float op);
|
||||
float ReciprocalSqrtStep(float op1, float op2);
|
||||
|
||||
constexpr uword kBreakInstructionFiller = 0xE1200070; // bkpt #0
|
||||
constexpr uword kDataMemoryBarrier = 0xf57ff050 | 0xb; // dmb ish
|
||||
constexpr uword kBreakInstructionFiller = 0xE1200070; // bkpt #0
|
||||
constexpr uword kDMB_ISH = 0xf57ff05b; // dmb ish
|
||||
constexpr uword kDMB_ISHST = 0xf57ff05a; // dmb ishst
|
||||
|
||||
struct LinkRegister {
|
||||
const int32_t code = LR;
|
||||
|
||||
@@ -1633,7 +1633,8 @@ class Instr {
|
||||
};
|
||||
|
||||
const uint64_t kBreakInstructionFiller = 0xD4200000D4200000L; // brk #0; brk #0
|
||||
constexpr int32_t kDataMemoryBarrier = 0xD5033BBF; // dmb ish
|
||||
constexpr int32_t kDMB_ISH = 0xD5033BBF; // dmb ish
|
||||
constexpr int32_t kDMB_ISHST = 0xD5033ABF; // dmb ishst
|
||||
|
||||
struct LinkRegister {};
|
||||
|
||||
|
||||
@@ -1555,7 +1555,7 @@ VM_UNIT_TEST_CASE(MutatorMarkerRace_Fence) {
|
||||
for (size_t i = 0; i < kExistingObjectSlotCount; i++) {
|
||||
NewObject* new_object = &new_page->objects[i];
|
||||
new_object->header.store(2u, std::memory_order_relaxed);
|
||||
std::atomic_thread_fence(std::memory_order_release);
|
||||
StoreStoreFence();
|
||||
for (size_t j = 0; j < kNewObjectSlotCount; j++) {
|
||||
new_object->slots[j].store(existing_object,
|
||||
std::memory_order_relaxed);
|
||||
|
||||
@@ -2846,11 +2846,7 @@ void Object::InitializeObject(uword address,
|
||||
|
||||
reinterpret_cast<UntaggedObject*>(address)->tags_ = tags;
|
||||
#if defined(HOST_HAS_FAST_WRITE_WRITE_FENCE)
|
||||
// GCC warns that TSAN doesn't understand thread fences.
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic ignored "-Wtsan"
|
||||
#endif
|
||||
std::atomic_thread_fence(std::memory_order_release);
|
||||
StoreStoreFence();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -3413,11 +3413,14 @@ DART_FORCE_INLINE void Simulator::InstructionDecodeImpl(Instr* instr) {
|
||||
if (instr->InstructionBits() == static_cast<int32_t>(0xf57ff01f)) {
|
||||
// Format(instr, "clrex");
|
||||
ClearExclusive();
|
||||
} else if (instr->InstructionBits() ==
|
||||
static_cast<int32_t>(kDataMemoryBarrier)) {
|
||||
} else if (instr->InstructionBits() == static_cast<int32_t>(kDMB_ISH)) {
|
||||
// Format(instr, "dmb ish");
|
||||
memory_.FlushAll();
|
||||
std::atomic_thread_fence(std::memory_order_seq_cst);
|
||||
} else if (instr->InstructionBits() == static_cast<int32_t>(kDMB_ISHST)) {
|
||||
// Format(instr, "dmb ishst");
|
||||
memory_.FlushAll();
|
||||
StoreStoreFence();
|
||||
} else {
|
||||
if (instr->IsSIMDDataProcessing()) {
|
||||
DecodeSIMDDataProcessing(instr);
|
||||
|
||||
@@ -1982,12 +1982,18 @@ void Simulator::DecodeSystem(Instr* instr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (instr->InstructionBits() == kDataMemoryBarrier) {
|
||||
if (instr->InstructionBits() == kDMB_ISH) {
|
||||
// Format(instr, "dmb ish");
|
||||
memory_.FlushAll();
|
||||
std::atomic_thread_fence(std::memory_order_seq_cst);
|
||||
return;
|
||||
}
|
||||
if (instr->InstructionBits() == kDMB_ISHST) {
|
||||
// Format(instr, "dmb ishst");
|
||||
memory_.FlushAll();
|
||||
StoreStoreFence();
|
||||
return;
|
||||
}
|
||||
|
||||
if ((instr->Bits(0, 8) == 0x1f) && (instr->Bits(12, 4) == 2) &&
|
||||
(instr->Bits(16, 3) == 3) && (instr->Bits(19, 2) == 0) &&
|
||||
|
||||
Reference in New Issue
Block a user