Index: test/cctest/test-simulator-arm64.cc |
diff --git a/test/cctest/test-simulator-arm64.cc b/test/cctest/test-simulator-arm64.cc |
deleted file mode 100644 |
index ef2e6854a18cb6fc76a950033a1d791260482446..0000000000000000000000000000000000000000 |
--- a/test/cctest/test-simulator-arm64.cc |
+++ /dev/null |
@@ -1,383 +0,0 @@ |
-// Copyright 2017 the V8 project authors. All rights reserved. |
-// Redistribution and use in source and binary forms, with or without |
-// modification, are permitted provided that the following conditions are |
-// met: |
-// |
-// * Redistributions of source code must retain the above copyright |
-// notice, this list of conditions and the following disclaimer. |
-// * Redistributions in binary form must reproduce the above |
-// copyright notice, this list of conditions and the following |
-// disclaimer in the documentation and/or other materials provided |
-// with the distribution. |
-// * Neither the name of Google Inc. nor the names of its |
-// contributors may be used to endorse or promote products derived |
-// from this software without specific prior written permission. |
-// |
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
- |
-#include "src/v8.h" |
-#include "test/cctest/cctest.h" |
- |
-#include "src/arm64/simulator-arm64.h" |
-#include "src/factory.h" |
-#include "src/macro-assembler.h" |
- |
-#if defined(USE_SIMULATOR) |
- |
-#ifndef V8_TARGET_LITTLE_ENDIAN |
-#error Expected ARM to be little-endian |
-#endif |
- |
-using namespace v8::base; |
-using namespace v8::internal; |
- |
-#define __ masm. |
- |
-struct MemoryAccess { |
- enum class Kind { |
- None, |
- Load, |
- LoadExcl, |
- Store, |
- StoreExcl, |
- }; |
- |
- enum class Size { |
- Byte, |
- HalfWord, |
- Word, |
- }; |
- |
- MemoryAccess() : kind(Kind::None) {} |
- MemoryAccess(Kind kind, Size size, size_t offset, int value = 0) |
- : kind(kind), size(size), offset(offset), value(value) {} |
- |
- Kind kind; |
- Size size; |
- size_t offset; |
- int value; |
-}; |
- |
-struct TestData { |
- explicit TestData(int w) : w(w) {} |
- |
- union { |
- int32_t w; |
- int16_t h; |
- int8_t b; |
- }; |
- int dummy; |
-}; |
- |
-static void AssembleMemoryAccess(MacroAssembler* assembler, MemoryAccess access, |
- Register dest_reg, Register value_reg, |
- Register addr_reg) { |
- MacroAssembler& masm = *assembler; |
- __ Add(addr_reg, x0, Operand(access.offset)); |
- |
- switch (access.kind) { |
- case MemoryAccess::Kind::None: |
- break; |
- |
- case MemoryAccess::Kind::Load: |
- switch (access.size) { |
- case MemoryAccess::Size::Byte: |
- __ ldrb(value_reg, MemOperand(addr_reg)); |
- break; |
- |
- case MemoryAccess::Size::HalfWord: |
- __ ldrh(value_reg, MemOperand(addr_reg)); |
- break; |
- |
- case MemoryAccess::Size::Word: |
- __ ldr(value_reg, MemOperand(addr_reg)); |
- break; |
- } |
- break; |
- |
- case MemoryAccess::Kind::LoadExcl: |
- switch (access.size) { |
- case MemoryAccess::Size::Byte: |
- __ ldaxrb(value_reg, addr_reg); |
- break; |
- |
- case MemoryAccess::Size::HalfWord: |
- __ ldaxrh(value_reg, addr_reg); |
- break; |
- |
- case MemoryAccess::Size::Word: |
- __ ldaxr(value_reg, addr_reg); |
- break; |
- } |
- break; |
- |
- case MemoryAccess::Kind::Store: |
- switch (access.size) { |
- case MemoryAccess::Size::Byte: |
- __ Mov(value_reg, Operand(access.value)); |
- __ strb(value_reg, MemOperand(addr_reg)); |
- break; |
- |
- case MemoryAccess::Size::HalfWord: |
- __ Mov(value_reg, Operand(access.value)); |
- __ strh(value_reg, MemOperand(addr_reg)); |
- break; |
- |
- case MemoryAccess::Size::Word: |
- __ Mov(value_reg, Operand(access.value)); |
- __ str(value_reg, MemOperand(addr_reg)); |
- break; |
- } |
- break; |
- |
- case MemoryAccess::Kind::StoreExcl: |
- switch (access.size) { |
- case MemoryAccess::Size::Byte: |
- __ Mov(value_reg, Operand(access.value)); |
- __ stlxrb(dest_reg, value_reg, addr_reg); |
- break; |
- |
- case MemoryAccess::Size::HalfWord: |
- __ Mov(value_reg, Operand(access.value)); |
- __ stlxrh(dest_reg, value_reg, addr_reg); |
- break; |
- |
- case MemoryAccess::Size::Word: |
- __ Mov(value_reg, Operand(access.value)); |
- __ stlxr(dest_reg, value_reg, addr_reg); |
- break; |
- } |
- break; |
- } |
-} |
- |
-static void AssembleLoadExcl(MacroAssembler* assembler, MemoryAccess access, |
- Register value_reg, Register addr_reg) { |
- DCHECK(access.kind == MemoryAccess::Kind::LoadExcl); |
- 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); |
- AssembleMemoryAccess(assembler, access, dest_reg, value_reg, addr_reg); |
-} |
- |
-static void TestInvalidateExclusiveAccess( |
- TestData initial_data, MemoryAccess access1, MemoryAccess access2, |
- MemoryAccess access3, int expected_res, TestData expected_data) { |
- Isolate* isolate = CcTest::i_isolate(); |
- HandleScope scope(isolate); |
- MacroAssembler masm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); |
- |
- AssembleLoadExcl(&masm, access1, w1, x1); |
- AssembleMemoryAccess(&masm, access2, w3, w2, x1); |
- AssembleStoreExcl(&masm, access3, w0, w3, x1); |
- __ br(lr); |
- |
- CodeDesc desc; |
- masm.GetCode(&desc); |
- Handle<Code> code = isolate->factory()->NewCode( |
- desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
- TestData t = initial_data; |
- Simulator::CallArgument args[] = { |
- Simulator::CallArgument(reinterpret_cast<uintptr_t>(&t)), |
- Simulator::CallArgument::End()}; |
- Simulator::current(isolate)->CallVoid(code->entry(), args); |
- int res = Simulator::current(isolate)->wreg(0); |
- |
- CHECK_EQ(expected_res, res); |
- switch (access3.size) { |
- case MemoryAccess::Size::Byte: |
- CHECK_EQ(expected_data.b, t.b); |
- break; |
- |
- case MemoryAccess::Size::HalfWord: |
- CHECK_EQ(expected_data.h, t.h); |
- break; |
- |
- case MemoryAccess::Size::Word: |
- CHECK_EQ(expected_data.w, t.w); |
- break; |
- } |
-} |
- |
-TEST(simulator_invalidate_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); |
- |
- // Address mismatch. |
- TestInvalidateExclusiveAccess( |
- TestData(1), ldaxr_w, |
- MemoryAccess(Kind::LoadExcl, 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)); |
- |
- // Load between ldaxr/stlxr. |
- TestInvalidateExclusiveAccess( |
- TestData(1), ldaxr_w, |
- MemoryAccess(Kind::Load, Size::Word, offsetof(TestData, dummy)), stlxr_w, |
- 1, TestData(1)); |
- |
- // Store between ldaxr/stlxr. |
- TestInvalidateExclusiveAccess( |
- TestData(1), ldaxr_w, |
- MemoryAccess(Kind::Store, Size::Word, offsetof(TestData, dummy)), stlxr_w, |
- 1, TestData(1)); |
- |
- // Match |
- TestInvalidateExclusiveAccess(TestData(1), ldaxr_w, MemoryAccess(), stlxr_w, |
- 0, TestData(7)); |
-} |
- |
-static int ExecuteMemoryAccess(Isolate* isolate, TestData* test_data, |
- MemoryAccess access) { |
- HandleScope scope(isolate); |
- MacroAssembler masm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); |
- AssembleMemoryAccess(&masm, access, w0, w2, x1); |
- __ br(lr); |
- |
- CodeDesc desc; |
- masm.GetCode(&desc); |
- Handle<Code> code = isolate->factory()->NewCode( |
- desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
- Simulator::CallArgument args[] = { |
- Simulator::CallArgument(reinterpret_cast<uintptr_t>(test_data)), |
- Simulator::CallArgument::End()}; |
- Simulator::current(isolate)->CallVoid(code->entry(), args); |
- return Simulator::current(isolate)->wreg(0); |
-} |
- |
-class MemoryAccessThread : public v8::base::Thread { |
- public: |
- MemoryAccessThread() |
- : Thread(Options("MemoryAccessThread")), |
- test_data_(NULL), |
- is_finished_(false), |
- has_request_(false), |
- did_request_(false) {} |
- |
- virtual void Run() { |
- v8::Isolate::CreateParams create_params; |
- create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); |
- v8::Isolate* isolate = v8::Isolate::New(create_params); |
- Isolate* i_isolate = reinterpret_cast<Isolate*>(isolate); |
- v8::Isolate::Scope scope(isolate); |
- |
- v8::base::LockGuard<v8::base::Mutex> lock_guard(&mutex_); |
- while (!is_finished_) { |
- while (!(has_request_ || is_finished_)) { |
- has_request_cv_.Wait(&mutex_); |
- } |
- |
- if (is_finished_) { |
- break; |
- } |
- |
- ExecuteMemoryAccess(i_isolate, test_data_, access_); |
- has_request_ = false; |
- did_request_ = true; |
- did_request_cv_.NotifyOne(); |
- } |
- } |
- |
- void NextAndWait(TestData* test_data, MemoryAccess access) { |
- DCHECK(!has_request_); |
- v8::base::LockGuard<v8::base::Mutex> lock_guard(&mutex_); |
- test_data_ = test_data; |
- access_ = access; |
- has_request_ = true; |
- has_request_cv_.NotifyOne(); |
- while (!did_request_) { |
- did_request_cv_.Wait(&mutex_); |
- } |
- did_request_ = false; |
- } |
- |
- void Finish() { |
- v8::base::LockGuard<v8::base::Mutex> lock_guard(&mutex_); |
- is_finished_ = true; |
- has_request_cv_.NotifyOne(); |
- } |
- |
- private: |
- TestData* test_data_; |
- MemoryAccess access_; |
- bool is_finished_; |
- bool has_request_; |
- bool did_request_; |
- v8::base::Mutex mutex_; |
- v8::base::ConditionVariable has_request_cv_; |
- v8::base::ConditionVariable did_request_cv_; |
-}; |
- |
-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 ldaxr_w(Kind::LoadExcl, Size::Word, offsetof(TestData, w)); |
- MemoryAccess stlxr_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, ldaxr_w); |
- thread.NextAndWait(&test_data, MemoryAccess(Kind::StoreExcl, Size::Word, |
- offsetof(TestData, w), 5)); |
- CHECK_EQ(1, ExecuteMemoryAccess(isolate, &test_data, stlxr_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, ldaxr_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, stlxr_w)); |
- CHECK_EQ(1, test_data.w); |
- |
- // Test failure when store between ldaxr/stlxr. |
- test_data = TestData(1); |
- ExecuteMemoryAccess(isolate, &test_data, ldaxr_w); |
- thread.NextAndWait(&test_data, MemoryAccess(Kind::Store, Size::Word, |
- offsetof(TestData, dummy))); |
- CHECK_EQ(1, ExecuteMemoryAccess(isolate, &test_data, stlxr_w)); |
- CHECK_EQ(1, test_data.w); |
- |
- thread.Finish(); |
- thread.Join(); |
-} |
- |
-#undef __ |
- |
-#endif // USE_SIMULATOR |