| 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
|
|
|