Index: test/cctest/test-simulator-arm64.cc |
diff --git a/test/cctest/test-simulator-arm64.cc b/test/cctest/test-simulator-arm64.cc |
index b852a46b0ed8cf10437050a60f0f537322b6308d..73dd75460710f1fccaac316c990a3d6e4f123d9d 100644 |
--- a/test/cctest/test-simulator-arm64.cc |
+++ b/test/cctest/test-simulator-arm64.cc |
@@ -49,8 +49,10 @@ struct MemoryAccess { |
None, |
Load, |
LoadExcl, |
+ LoadAcqExcl, |
Store, |
StoreExcl, |
+ StoreRelExcl, |
}; |
enum class Size { |
@@ -109,6 +111,22 @@ static void AssembleMemoryAccess(MacroAssembler* assembler, MemoryAccess access, |
case MemoryAccess::Kind::LoadExcl: |
switch (access.size) { |
case MemoryAccess::Size::Byte: |
+ __ ldxrb(value_reg, addr_reg); |
+ break; |
+ |
+ case MemoryAccess::Size::HalfWord: |
+ __ ldxrh(value_reg, addr_reg); |
+ break; |
+ |
+ case MemoryAccess::Size::Word: |
+ __ ldxr(value_reg, addr_reg); |
+ break; |
+ } |
+ break; |
+ |
+ case MemoryAccess::Kind::LoadAcqExcl: |
+ switch (access.size) { |
+ case MemoryAccess::Size::Byte: |
__ ldaxrb(value_reg, addr_reg); |
break; |
@@ -145,6 +163,25 @@ static void AssembleMemoryAccess(MacroAssembler* assembler, MemoryAccess access, |
switch (access.size) { |
case MemoryAccess::Size::Byte: |
__ Mov(value_reg, Operand(access.value)); |
+ __ stxrb(dest_reg, value_reg, addr_reg); |
+ break; |
+ |
+ case MemoryAccess::Size::HalfWord: |
+ __ Mov(value_reg, Operand(access.value)); |
+ __ stxrh(dest_reg, value_reg, addr_reg); |
+ break; |
+ |
+ case MemoryAccess::Size::Word: |
+ __ Mov(value_reg, Operand(access.value)); |
+ __ stxr(dest_reg, value_reg, addr_reg); |
+ break; |
+ } |
+ break; |
+ |
+ case MemoryAccess::Kind::StoreRelExcl: |
+ switch (access.size) { |
+ case MemoryAccess::Size::Byte: |
+ __ Mov(value_reg, Operand(access.value)); |
__ stlxrb(dest_reg, value_reg, addr_reg); |
break; |
@@ -164,14 +201,16 @@ static void AssembleMemoryAccess(MacroAssembler* assembler, MemoryAccess access, |
static void AssembleLoadExcl(MacroAssembler* assembler, MemoryAccess access, |
Register value_reg, Register addr_reg) { |
- DCHECK(access.kind == MemoryAccess::Kind::LoadExcl); |
+ DCHECK((access.kind == MemoryAccess::Kind::LoadExcl) || |
+ (access.kind == MemoryAccess::Kind::LoadAcqExcl)); |
AssembleMemoryAccess(assembler, access, no_reg, value_reg, addr_reg); |
} |
static void AssembleStoreExcl(MacroAssembler* assembler, MemoryAccess access, |
Register dest_reg, Register value_reg, |
Register addr_reg) { |
- DCHECK(access.kind == MemoryAccess::Kind::StoreExcl); |
+ DCHECK((access.kind == MemoryAccess::Kind::StoreExcl) || |
+ (access.kind == MemoryAccess::Kind::StoreRelExcl)); |
AssembleMemoryAccess(assembler, access, dest_reg, value_reg, addr_reg); |
} |
@@ -185,7 +224,7 @@ static void TestInvalidateExclusiveAccess( |
AssembleLoadExcl(&masm, access1, w1, x1); |
AssembleMemoryAccess(&masm, access2, w3, w2, x1); |
AssembleStoreExcl(&masm, access3, w0, w3, x1); |
- __ br(lr); |
+ __ Br(lr); |
CodeDesc desc; |
masm.GetCode(&desc); |
@@ -214,24 +253,25 @@ static void TestInvalidateExclusiveAccess( |
} |
} |
-TEST(simulator_invalidate_exclusive_access) { |
+TEST(simulator_invalidate_acquire_release_exclusive_access) { |
using Kind = MemoryAccess::Kind; |
using Size = MemoryAccess::Size; |
- MemoryAccess ldaxr_w(Kind::LoadExcl, Size::Word, offsetof(TestData, w)); |
- MemoryAccess stlxr_w(Kind::StoreExcl, Size::Word, offsetof(TestData, w), 7); |
+ MemoryAccess ldaxr_w(Kind::LoadAcqExcl, Size::Word, offsetof(TestData, w)); |
+ MemoryAccess stlxr_w(Kind::StoreRelExcl, Size::Word, offsetof(TestData, w), |
+ 7); |
// Address mismatch. |
TestInvalidateExclusiveAccess( |
TestData(1), ldaxr_w, |
- MemoryAccess(Kind::LoadExcl, Size::Word, offsetof(TestData, dummy)), |
+ MemoryAccess(Kind::LoadAcqExcl, Size::Word, offsetof(TestData, dummy)), |
stlxr_w, 1, TestData(1)); |
// Size mismatch. |
- TestInvalidateExclusiveAccess( |
- TestData(1), ldaxr_w, MemoryAccess(), |
- MemoryAccess(Kind::StoreExcl, Size::HalfWord, offsetof(TestData, w), 7), |
- 1, TestData(1)); |
+ TestInvalidateExclusiveAccess(TestData(1), ldaxr_w, MemoryAccess(), |
+ MemoryAccess(Kind::StoreRelExcl, Size::HalfWord, |
+ offsetof(TestData, w), 7), |
+ 1, TestData(1)); |
// Load between ldaxr/stlxr. |
TestInvalidateExclusiveAccess( |
@@ -250,6 +290,42 @@ TEST(simulator_invalidate_exclusive_access) { |
0, TestData(7)); |
} |
+TEST(simulator_invalidate_exclusive_access) { |
+ using Kind = MemoryAccess::Kind; |
+ using Size = MemoryAccess::Size; |
+ |
+ MemoryAccess ldxr_w(Kind::LoadExcl, Size::Word, offsetof(TestData, w)); |
+ MemoryAccess stxr_w(Kind::StoreExcl, Size::Word, offsetof(TestData, w), 42); |
+ |
+ // Address mismatch. |
+ TestInvalidateExclusiveAccess( |
+ TestData(1), ldxr_w, |
+ MemoryAccess(Kind::LoadExcl, Size::Word, offsetof(TestData, dummy)), |
+ stxr_w, 1, TestData(1)); |
+ |
+ // Size mismatch. |
+ TestInvalidateExclusiveAccess( |
+ TestData(1), ldxr_w, MemoryAccess(), |
+ MemoryAccess(Kind::StoreExcl, Size::HalfWord, offsetof(TestData, w), 42), |
+ 1, TestData(1)); |
+ |
+ // Load between ldxr/stxr. |
+ TestInvalidateExclusiveAccess( |
+ TestData(1), ldxr_w, |
+ MemoryAccess(Kind::Load, Size::Word, offsetof(TestData, dummy)), stxr_w, |
+ 1, TestData(1)); |
+ |
+ // Store between ldxr/stxr. |
+ TestInvalidateExclusiveAccess( |
+ TestData(1), ldxr_w, |
+ MemoryAccess(Kind::Store, Size::Word, offsetof(TestData, dummy)), stxr_w, |
+ 1, TestData(1)); |
+ |
+ // Match |
+ TestInvalidateExclusiveAccess(TestData(1), ldxr_w, MemoryAccess(), stxr_w, 0, |
+ TestData(42)); |
+} |
+ |
static int ExecuteMemoryAccess(Isolate* isolate, TestData* test_data, |
MemoryAccess access) { |
HandleScope scope(isolate); |
@@ -331,7 +407,7 @@ class MemoryAccessThread : public v8::base::Thread { |
v8::base::ConditionVariable did_request_cv_; |
}; |
-TEST(simulator_invalidate_exclusive_access_threaded) { |
+TEST(simulator_invalidate_acquire_release_exclusive_access_threaded) { |
using Kind = MemoryAccess::Kind; |
using Size = MemoryAccess::Size; |
@@ -343,15 +419,16 @@ TEST(simulator_invalidate_exclusive_access_threaded) { |
MemoryAccessThread thread; |
thread.Start(); |
- MemoryAccess ldaxr_w(Kind::LoadExcl, Size::Word, offsetof(TestData, w)); |
- MemoryAccess stlxr_w(Kind::StoreExcl, Size::Word, offsetof(TestData, w), 7); |
+ MemoryAccess ldaxr_w(Kind::LoadAcqExcl, Size::Word, offsetof(TestData, w)); |
+ MemoryAccess stlxr_w(Kind::StoreRelExcl, Size::Word, offsetof(TestData, w), |
+ 7); |
// Exclusive store completed by another thread first. |
test_data = TestData(1); |
- thread.NextAndWait(&test_data, MemoryAccess(Kind::LoadExcl, Size::Word, |
+ thread.NextAndWait(&test_data, MemoryAccess(Kind::LoadAcqExcl, Size::Word, |
offsetof(TestData, w))); |
ExecuteMemoryAccess(isolate, &test_data, ldaxr_w); |
- thread.NextAndWait(&test_data, MemoryAccess(Kind::StoreExcl, Size::Word, |
+ thread.NextAndWait(&test_data, MemoryAccess(Kind::StoreRelExcl, Size::Word, |
offsetof(TestData, w), 5)); |
CHECK_EQ(1, ExecuteMemoryAccess(isolate, &test_data, stlxr_w)); |
CHECK_EQ(5, test_data.w); |
@@ -360,9 +437,9 @@ TEST(simulator_invalidate_exclusive_access_threaded) { |
// to same |
test_data = TestData(1); |
ExecuteMemoryAccess(isolate, &test_data, ldaxr_w); |
- thread.NextAndWait(&test_data, MemoryAccess(Kind::LoadExcl, Size::Word, |
+ thread.NextAndWait(&test_data, MemoryAccess(Kind::LoadAcqExcl, Size::Word, |
offsetof(TestData, dummy))); |
- thread.NextAndWait(&test_data, MemoryAccess(Kind::StoreExcl, Size::Word, |
+ thread.NextAndWait(&test_data, MemoryAccess(Kind::StoreRelExcl, Size::Word, |
offsetof(TestData, dummy), 5)); |
CHECK_EQ(1, ExecuteMemoryAccess(isolate, &test_data, stlxr_w)); |
CHECK_EQ(1, test_data.w); |
@@ -379,6 +456,54 @@ TEST(simulator_invalidate_exclusive_access_threaded) { |
thread.Join(); |
} |
+TEST(simulator_invalidate_exclusive_access_threaded) { |
+ using Kind = MemoryAccess::Kind; |
+ using Size = MemoryAccess::Size; |
+ |
+ Isolate* isolate = CcTest::i_isolate(); |
+ HandleScope scope(isolate); |
+ |
+ TestData test_data(1); |
+ |
+ MemoryAccessThread thread; |
+ thread.Start(); |
+ |
+ MemoryAccess ldxr_w(Kind::LoadExcl, Size::Word, offsetof(TestData, w)); |
+ MemoryAccess stxr_w(Kind::StoreExcl, Size::Word, offsetof(TestData, w), 7); |
+ |
+ // Exclusive store completed by another thread first. |
+ test_data = TestData(1); |
+ thread.NextAndWait(&test_data, MemoryAccess(Kind::LoadExcl, Size::Word, |
+ offsetof(TestData, w))); |
+ ExecuteMemoryAccess(isolate, &test_data, ldxr_w); |
+ thread.NextAndWait(&test_data, MemoryAccess(Kind::StoreExcl, Size::Word, |
+ offsetof(TestData, w), 5)); |
+ CHECK_EQ(1, ExecuteMemoryAccess(isolate, &test_data, stxr_w)); |
+ CHECK_EQ(5, test_data.w); |
+ |
+ // Exclusive store completed by another thread; different address, but masked |
+ // to same |
+ test_data = TestData(1); |
+ ExecuteMemoryAccess(isolate, &test_data, ldxr_w); |
+ thread.NextAndWait(&test_data, MemoryAccess(Kind::LoadExcl, Size::Word, |
+ offsetof(TestData, dummy))); |
+ thread.NextAndWait(&test_data, MemoryAccess(Kind::StoreExcl, Size::Word, |
+ offsetof(TestData, dummy), 5)); |
+ CHECK_EQ(1, ExecuteMemoryAccess(isolate, &test_data, stxr_w)); |
+ CHECK_EQ(1, test_data.w); |
+ |
+ // Test failure when store between ldxr/stxr. |
+ test_data = TestData(1); |
+ ExecuteMemoryAccess(isolate, &test_data, ldxr_w); |
+ thread.NextAndWait(&test_data, MemoryAccess(Kind::Store, Size::Word, |
+ offsetof(TestData, dummy))); |
+ CHECK_EQ(1, ExecuteMemoryAccess(isolate, &test_data, stxr_w)); |
+ CHECK_EQ(1, test_data.w); |
+ |
+ thread.Finish(); |
+ thread.Join(); |
+} |
+ |
#undef __ |
#endif // USE_SIMULATOR |