diff options
Diffstat (limited to 'deps/v8/test/cctest/wasm')
-rw-r--r-- | deps/v8/test/cctest/wasm/OWNERS | 2 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/test-grow-memory.cc | 131 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/test-jump-table-assembler.cc | 24 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/test-run-wasm-64.cc | 4 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/test-run-wasm-bulk-memory.cc | 104 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/test-run-wasm-interpreter.cc | 2 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/test-run-wasm-module.cc | 162 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/test-run-wasm-simd.cc | 416 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/test-run-wasm.cc | 31 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/test-streaming-compilation.cc | 40 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/test-wasm-breakpoints.cc | 182 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/test-wasm-import-wrapper-cache.cc | 4 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/test-wasm-interpreter-entry.cc | 42 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/test-wasm-serialization.cc | 30 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/test-wasm-shared-engine.cc | 116 | ||||
-rw-r--r-- | deps/v8/test/cctest/wasm/wasm-run-utils.cc | 34 |
16 files changed, 879 insertions, 445 deletions
diff --git a/deps/v8/test/cctest/wasm/OWNERS b/deps/v8/test/cctest/wasm/OWNERS index dc68b39733..16b08f3b3b 100644 --- a/deps/v8/test/cctest/wasm/OWNERS +++ b/deps/v8/test/cctest/wasm/OWNERS @@ -1,5 +1,5 @@ ahaas@chromium.org -clemensh@chromium.org +clemensb@chromium.org titzer@chromium.org # COMPONENT: Blink>JavaScript>WebAssembly diff --git a/deps/v8/test/cctest/wasm/test-grow-memory.cc b/deps/v8/test/cctest/wasm/test-grow-memory.cc new file mode 100644 index 0000000000..a188707cae --- /dev/null +++ b/deps/v8/test/cctest/wasm/test-grow-memory.cc @@ -0,0 +1,131 @@ +// Copyright 2019 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "src/wasm/wasm-objects-inl.h" +#include "src/wasm/wasm-opcodes.h" + +#include "src/wasm/wasm-module-builder.h" +#include "test/cctest/cctest.h" +#include "test/cctest/manually-externalized-buffer.h" +#include "test/common/wasm/flag-utils.h" +#include "test/common/wasm/test-signatures.h" +#include "test/common/wasm/wasm-macro-gen.h" +#include "test/common/wasm/wasm-module-runner.h" + +namespace v8 { +namespace internal { +namespace wasm { +namespace test_grow_memory { + +using testing::CompileAndInstantiateForTesting; +using v8::internal::testing::ManuallyExternalizedBuffer; + +namespace { +void ExportAsMain(WasmFunctionBuilder* f) { + f->builder()->AddExport(CStrVector("main"), f); +} +#define EMIT_CODE_WITH_END(f, code) \ + do { \ + f->EmitCode(code, sizeof(code)); \ + f->Emit(kExprEnd); \ + } while (false) + +void Cleanup(Isolate* isolate = CcTest::InitIsolateOnce()) { + // By sending a low memory notifications, we will try hard to collect all + // garbage and will therefore also invoke all weak callbacks of actually + // unreachable persistent handles. + reinterpret_cast<v8::Isolate*>(isolate)->LowMemoryNotification(); +} +} // namespace + +TEST(GrowMemDetaches) { + { + Isolate* isolate = CcTest::InitIsolateOnce(); + HandleScope scope(isolate); + Handle<WasmMemoryObject> memory_object = + WasmMemoryObject::New(isolate, 16, 100, SharedFlag::kNotShared) + .ToHandleChecked(); + Handle<JSArrayBuffer> buffer(memory_object->array_buffer(), isolate); + int32_t result = WasmMemoryObject::Grow(isolate, memory_object, 0); + CHECK_EQ(16, result); + CHECK_NE(*buffer, memory_object->array_buffer()); + CHECK(buffer->was_detached()); + } + Cleanup(); +} + +TEST(Externalized_GrowMemMemSize) { + { + Isolate* isolate = CcTest::InitIsolateOnce(); + HandleScope scope(isolate); + Handle<WasmMemoryObject> memory_object = + WasmMemoryObject::New(isolate, 16, 100, SharedFlag::kNotShared) + .ToHandleChecked(); + ManuallyExternalizedBuffer external( + handle(memory_object->array_buffer(), isolate)); + int32_t result = WasmMemoryObject::Grow(isolate, memory_object, 0); + CHECK_EQ(16, result); + CHECK_NE(*external.buffer_, memory_object->array_buffer()); + CHECK(external.buffer_->was_detached()); + } + Cleanup(); +} + +TEST(Run_WasmModule_Buffer_Externalized_GrowMem) { + { + Isolate* isolate = CcTest::InitIsolateOnce(); + HandleScope scope(isolate); + TestSignatures sigs; + v8::internal::AccountingAllocator allocator; + Zone zone(&allocator, ZONE_NAME); + + WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone); + WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v()); + ExportAsMain(f); + byte code[] = {WASM_GROW_MEMORY(WASM_I32V_1(6)), WASM_DROP, + WASM_MEMORY_SIZE}; + EMIT_CODE_WITH_END(f, code); + + ZoneBuffer buffer(&zone); + builder->WriteTo(&buffer); + testing::SetupIsolateForWasmModule(isolate); + ErrorThrower thrower(isolate, "Test"); + const Handle<WasmInstanceObject> instance = + CompileAndInstantiateForTesting( + isolate, &thrower, ModuleWireBytes(buffer.begin(), buffer.end())) + .ToHandleChecked(); + Handle<WasmMemoryObject> memory_object(instance->memory_object(), isolate); + + // Fake the Embedder flow by externalizing the array buffer. + ManuallyExternalizedBuffer external1( + handle(memory_object->array_buffer(), isolate)); + + // Grow using the API. + uint32_t result = WasmMemoryObject::Grow(isolate, memory_object, 4); + CHECK_EQ(16, result); + CHECK(external1.buffer_->was_detached()); // growing always detaches + CHECK_EQ(0, external1.buffer_->byte_length()); + + CHECK_NE(*external1.buffer_, memory_object->array_buffer()); + + // Fake the Embedder flow by externalizing the array buffer. + ManuallyExternalizedBuffer external2( + handle(memory_object->array_buffer(), isolate)); + + // Grow using an internal WASM bytecode. + result = testing::RunWasmModuleForTesting(isolate, instance, 0, nullptr); + CHECK_EQ(26, result); + CHECK(external2.buffer_->was_detached()); // growing always detaches + CHECK_EQ(0, external2.buffer_->byte_length()); + CHECK_NE(*external2.buffer_, memory_object->array_buffer()); + } + Cleanup(); +} + +} // namespace test_grow_memory +} // namespace wasm +} // namespace internal +} // namespace v8 + +#undef EMIT_CODE_WITH_END diff --git a/deps/v8/test/cctest/wasm/test-jump-table-assembler.cc b/deps/v8/test/cctest/wasm/test-jump-table-assembler.cc index 556d74daef..d3aa75a64e 100644 --- a/deps/v8/test/cctest/wasm/test-jump-table-assembler.cc +++ b/deps/v8/test/cctest/wasm/test-jump-table-assembler.cc @@ -36,7 +36,7 @@ constexpr size_t kThunkBufferSize = AssemblerBase::kMinimalBufferSize; #if V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_X64 constexpr uint32_t kAvailableBufferSlots = - (kMaxWasmCodeMemory - kJumpTableSize) / kThunkBufferSize; + (kMaxWasmCodeSpaceSize - kJumpTableSize) / kThunkBufferSize; constexpr uint32_t kBufferSlotStartOffset = RoundUp<kThunkBufferSize>(kJumpTableSize); #else @@ -49,7 +49,7 @@ Address AllocateJumpTableThunk( std::vector<std::unique_ptr<TestingAssemblerBuffer>>* thunk_buffers) { #if V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_X64 // To guarantee that the branch range lies within the near-call range, - // generate the thunk in the same (kMaxWasmCodeMemory-sized) buffer as the + // generate the thunk in the same (kMaxWasmCodeSpaceSize-sized) buffer as the // jump_target itself. // // Allocate a slot that we haven't already used. This is necessary because @@ -181,11 +181,13 @@ class JumpTablePatcher : public v8::base::Thread { // Then, repeatedly patch the jump table to jump to one of the two thunks. constexpr int kNumberOfPatchIterations = 64; for (int i = 0; i < kNumberOfPatchIterations; ++i) { - TRACE(" patcher %p patch slot " V8PRIxPTR_FMT " to thunk #%d\n", this, - slot_address, i % 2); + TRACE(" patcher %p patch slot " V8PRIxPTR_FMT + " to thunk #%d (" V8PRIxPTR_FMT ")\n", + this, slot_address, i % 2, thunks_[i % 2]); base::MutexGuard jump_table_guard(jump_table_mutex_); JumpTableAssembler::PatchJumpTableSlot( - slot_start_, slot_index_, thunks_[i % 2], WasmCode::kFlushICache); + slot_start_ + JumpTableAssembler::JumpSlotIndexToOffset(slot_index_), + kNullAddress, thunks_[i % 2]); } TRACE("Patcher %p is stopping ...\n", this); } @@ -219,11 +221,8 @@ TEST(JumpTablePatchingStress) { // is not reliable enough to guarantee that we can always achieve this with // separate allocations, so for Arm64 we generate all code in a single // kMaxMasmCodeMemory-sized chunk. - // - // TODO(wasm): Currently {kMaxWasmCodeMemory} limits code sufficiently, so - // that the jump table only supports {near_call} distances. - STATIC_ASSERT(kMaxWasmCodeMemory >= kJumpTableSize); - auto buffer = AllocateAssemblerBuffer(kMaxWasmCodeMemory); + STATIC_ASSERT(kMaxWasmCodeSpaceSize >= kJumpTableSize); + auto buffer = AllocateAssemblerBuffer(kMaxWasmCodeSpaceSize); byte* thunk_slot_buffer = buffer->start() + kBufferSlotStartOffset; #else auto buffer = AllocateAssemblerBuffer(kJumpTableSize); @@ -242,8 +241,9 @@ TEST(JumpTablePatchingStress) { std::vector<std::unique_ptr<TestingAssemblerBuffer>> thunk_buffers; // Patch the jump table slot to jump to itself. This will later be patched // by the patchers. - JumpTableAssembler::PatchJumpTableSlot( - slot_start, slot, slot_start + slot_offset, WasmCode::kFlushICache); + Address slot_addr = + slot_start + JumpTableAssembler::JumpSlotIndexToOffset(slot); + JumpTableAssembler::PatchJumpTableSlot(slot_addr, kNullAddress, slot_addr); // For each patcher, generate two thunks where this patcher can emit code // which finally jumps back to {slot} in the jump table. std::vector<Address> patcher_thunks; diff --git a/deps/v8/test/cctest/wasm/test-run-wasm-64.cc b/deps/v8/test/cctest/wasm/test-run-wasm-64.cc index 3f96f8720f..09d1eb7fda 100644 --- a/deps/v8/test/cctest/wasm/test-run-wasm-64.cc +++ b/deps/v8/test/cctest/wasm/test-run-wasm-64.cc @@ -1502,7 +1502,7 @@ static void CompileCallIndirectMany(ExecutionTier tier, ValueType param) { std::vector<byte> code; for (byte p = 0; p < num_params; p++) { - ADD_CODE(code, kExprGetLocal, p); + ADD_CODE(code, kExprLocalGet, p); } ADD_CODE(code, kExprI32Const, 0); ADD_CODE(code, kExprCallIndirect, 1, TABLE_ZERO); @@ -1563,7 +1563,7 @@ static void Run_WasmMixedCall_N(ExecutionTier execution_tier, int start) { // Store the result in a local. byte local_index = r.AllocateLocal(ValueTypes::ValueTypeFor(result)); - ADD_CODE(code, kExprSetLocal, local_index); + ADD_CODE(code, kExprLocalSet, local_index); // Store the result in memory. ADD_CODE(code, diff --git a/deps/v8/test/cctest/wasm/test-run-wasm-bulk-memory.cc b/deps/v8/test/cctest/wasm/test-run-wasm-bulk-memory.cc index e794c00ece..d2ac3434df 100644 --- a/deps/v8/test/cctest/wasm/test-run-wasm-bulk-memory.cc +++ b/deps/v8/test/cctest/wasm/test-run-wasm-bulk-memory.cc @@ -13,11 +13,10 @@ namespace wasm { namespace test_run_wasm_bulk_memory { namespace { -void CheckMemoryEquals( - TestingModuleBuilder& builder, // NOLINT(runtime/references) - size_t index, const std::vector<byte>& expected) { - const byte* mem_start = builder.raw_mem_start<byte>(); - const byte* mem_end = builder.raw_mem_end<byte>(); +void CheckMemoryEquals(TestingModuleBuilder* builder, size_t index, + const std::vector<byte>& expected) { + const byte* mem_start = builder->raw_mem_start<byte>(); + const byte* mem_end = builder->raw_mem_end<byte>(); size_t mem_size = mem_end - mem_start; CHECK_LE(index, mem_size); CHECK_LE(index + expected.size(), mem_size); @@ -26,11 +25,10 @@ void CheckMemoryEquals( } } -void CheckMemoryEqualsZero( - TestingModuleBuilder& builder, // NOLINT(runtime/references) - size_t index, size_t length) { - const byte* mem_start = builder.raw_mem_start<byte>(); - const byte* mem_end = builder.raw_mem_end<byte>(); +void CheckMemoryEqualsZero(TestingModuleBuilder* builder, size_t index, + size_t length) { + const byte* mem_start = builder->raw_mem_start<byte>(); + const byte* mem_end = builder->raw_mem_end<byte>(); size_t mem_size = mem_end - mem_start; CHECK_LE(index, mem_size); CHECK_LE(index + length, mem_size); @@ -39,12 +37,11 @@ void CheckMemoryEqualsZero( } } -void CheckMemoryEqualsFollowedByZeroes( - TestingModuleBuilder& builder, // NOLINT(runtime/references) - const std::vector<byte>& expected) { +void CheckMemoryEqualsFollowedByZeroes(TestingModuleBuilder* builder, + const std::vector<byte>& expected) { CheckMemoryEquals(builder, 0, expected); CheckMemoryEqualsZero(builder, expected.size(), - builder.mem_size() - expected.size()); + builder->mem_size() - expected.size()); } } // namespace @@ -60,24 +57,24 @@ WASM_EXEC_TEST(MemoryInit) { kExprI32Const, 0); // All zeroes. - CheckMemoryEqualsZero(r.builder(), 0, kWasmPageSize); + CheckMemoryEqualsZero(&r.builder(), 0, kWasmPageSize); // Copy all bytes from data segment 0, to memory at [10, 20). CHECK_EQ(0, r.Call(10, 0, 10)); CheckMemoryEqualsFollowedByZeroes( - r.builder(), + &r.builder(), {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); // Copy bytes in range [5, 10) from data segment 0, to memory at [0, 5). CHECK_EQ(0, r.Call(0, 5, 5)); CheckMemoryEqualsFollowedByZeroes( - r.builder(), + &r.builder(), {5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); // Copy 0 bytes does nothing. CHECK_EQ(0, r.Call(10, 1, 0)); CheckMemoryEqualsFollowedByZeroes( - r.builder(), + &r.builder(), {5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); // Copy 0 at end of memory region or data segment is OK. @@ -100,12 +97,12 @@ WASM_EXEC_TEST(MemoryInitOutOfBoundsData) { // Write all values up to the out-of-bounds write. CHECK_EQ(0xDEADBEEF, r.Call(kWasmPageSize - 5, 0, 6)); - CheckMemoryEquals(r.builder(), last_5_bytes, {0, 1, 2, 3, 4}); + CheckMemoryEquals(&r.builder(), last_5_bytes, {0, 1, 2, 3, 4}); // Write all values up to the out-of-bounds read. r.builder().BlankMemory(); CHECK_EQ(0xDEADBEEF, r.Call(0, 5, 6)); - CheckMemoryEqualsFollowedByZeroes(r.builder(), {5, 6, 7, 8, 9}); + CheckMemoryEqualsFollowedByZeroes(&r.builder(), {5, 6, 7, 8, 9}); } WASM_EXEC_TEST(MemoryInitOutOfBounds) { @@ -155,13 +152,13 @@ WASM_EXEC_TEST(MemoryCopy) { // Copy from [1, 8] to [10, 16]. CHECK_EQ(0, r.Call(10, 1, 8)); CheckMemoryEqualsFollowedByZeroes( - r.builder(), + &r.builder(), {0, 11, 22, 33, 44, 55, 66, 77, 0, 0, 11, 22, 33, 44, 55, 66, 77}); // Copy 0 bytes does nothing. CHECK_EQ(0, r.Call(10, 2, 0)); CheckMemoryEqualsFollowedByZeroes( - r.builder(), + &r.builder(), {0, 11, 22, 33, 44, 55, 66, 77, 0, 0, 11, 22, 33, 44, 55, 66, 77}); // Copy 0 at end of memory region is OK. @@ -184,12 +181,12 @@ WASM_EXEC_TEST(MemoryCopyOverlapping) { // Copy from [0, 3] -> [2, 5]. The copy must not overwrite 30 before copying // it (i.e. cannot copy forward in this case). CHECK_EQ(0, r.Call(2, 0, 3)); - CheckMemoryEqualsFollowedByZeroes(r.builder(), {10, 20, 10, 20, 30}); + CheckMemoryEqualsFollowedByZeroes(&r.builder(), {10, 20, 10, 20, 30}); // Copy from [2, 5] -> [0, 3]. The copy must not write the first 10 (i.e. // cannot copy backward in this case). CHECK_EQ(0, r.Call(0, 2, 3)); - CheckMemoryEqualsFollowedByZeroes(r.builder(), {10, 20, 30, 20, 30}); + CheckMemoryEqualsFollowedByZeroes(&r.builder(), {10, 20, 30, 20, 30}); } WASM_EXEC_TEST(MemoryCopyOutOfBoundsData) { @@ -209,21 +206,21 @@ WASM_EXEC_TEST(MemoryCopyOutOfBoundsData) { // Copy with source < destination. Copy would happen backwards, // but the first byte to copy is out-of-bounds, so no data should be written. CHECK_EQ(0xDEADBEEF, r.Call(last_5_bytes, 0, 6)); - CheckMemoryEquals(r.builder(), last_5_bytes, {0, 0, 0, 0, 0}); + CheckMemoryEquals(&r.builder(), last_5_bytes, {0, 0, 0, 0, 0}); // Copy overlapping with destination < source. Copy will happen forwards, up // to the out-of-bounds access. r.builder().BlankMemory(); memcpy(mem + last_5_bytes, data, 5); CHECK_EQ(0xDEADBEEF, r.Call(0, last_5_bytes, kWasmPageSize)); - CheckMemoryEquals(r.builder(), 0, {11, 22, 33, 44, 55}); + CheckMemoryEquals(&r.builder(), 0, {11, 22, 33, 44, 55}); // Copy overlapping with source < destination. Copy would happen backwards, // but the first byte to copy is out-of-bounds, so no data should be written. r.builder().BlankMemory(); memcpy(mem, data, 5); CHECK_EQ(0xDEADBEEF, r.Call(last_5_bytes, 0, kWasmPageSize)); - CheckMemoryEquals(r.builder(), last_5_bytes, {0, 0, 0, 0, 0}); + CheckMemoryEquals(&r.builder(), last_5_bytes, {0, 0, 0, 0, 0}); } WASM_EXEC_TEST(MemoryCopyOutOfBounds) { @@ -265,15 +262,15 @@ WASM_EXEC_TEST(MemoryFill) { WASM_MEMORY_FILL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1), WASM_GET_LOCAL(2)), kExprI32Const, 0); CHECK_EQ(0, r.Call(1, 33, 5)); - CheckMemoryEqualsFollowedByZeroes(r.builder(), {0, 33, 33, 33, 33, 33}); + CheckMemoryEqualsFollowedByZeroes(&r.builder(), {0, 33, 33, 33, 33, 33}); CHECK_EQ(0, r.Call(4, 66, 4)); - CheckMemoryEqualsFollowedByZeroes(r.builder(), + CheckMemoryEqualsFollowedByZeroes(&r.builder(), {0, 33, 33, 33, 66, 66, 66, 66}); // Fill 0 bytes does nothing. CHECK_EQ(0, r.Call(4, 66, 0)); - CheckMemoryEqualsFollowedByZeroes(r.builder(), + CheckMemoryEqualsFollowedByZeroes(&r.builder(), {0, 33, 33, 33, 66, 66, 66, 66}); // Fill 0 at end of memory region is OK. @@ -290,7 +287,7 @@ WASM_EXEC_TEST(MemoryFillValueWrapsToByte) { kExprI32Const, 0); CHECK_EQ(0, r.Call(0, 1000, 3)); const byte expected = 1000 & 255; - CheckMemoryEqualsFollowedByZeroes(r.builder(), + CheckMemoryEqualsFollowedByZeroes(&r.builder(), {expected, expected, expected}); } @@ -304,7 +301,7 @@ WASM_EXEC_TEST(MemoryFillOutOfBoundsData) { kExprI32Const, 0); const byte v = 123; CHECK_EQ(0xDEADBEEF, r.Call(kWasmPageSize - 5, v, 999)); - CheckMemoryEquals(r.builder(), kWasmPageSize - 6, {0, v, v, v, v, v}); + CheckMemoryEquals(&r.builder(), kWasmPageSize - 6, {0, v, v, v, v, v}); } WASM_EXEC_TEST(MemoryFillOutOfBounds) { @@ -408,14 +405,13 @@ void CheckTable(Isolate* isolate, Handle<WasmTableObject> table, Args... args) { template <typename WasmRunner, typename... Args> void CheckTableCall(Isolate* isolate, Handle<WasmTableObject> table, - WasmRunner& r, // NOLINT(runtime/references) - uint32_t function_index, Args... args) { + WasmRunner* r, uint32_t function_index, Args... args) { uint32_t args_length = static_cast<uint32_t>(sizeof...(args)); CHECK_EQ(table->current_length(), args_length); double expected[] = {args...}; for (uint32_t i = 0; i < args_length; ++i) { Handle<Object> buffer[] = {isolate->factory()->NewNumber(i)}; - r.CheckCallApplyViaJS(expected[i], function_index, buffer, 1); + r->CheckCallApplyViaJS(expected[i], function_index, buffer, 1); } } } // namespace @@ -462,7 +458,7 @@ void TestTableInitElems(ExecutionTier execution_tier, int table_index) { isolate); const double null = 0xDEADBEEF; - CheckTableCall(isolate, table, r, call_index, null, null, null, null, null); + CheckTableCall(isolate, table, &r, call_index, null, null, null, null, null); // 0 count is ok in bounds, and at end of regions. r.CheckCallViaJS(0, 0, 0, 0); @@ -471,19 +467,19 @@ void TestTableInitElems(ExecutionTier execution_tier, int table_index) { // Test actual writes. r.CheckCallViaJS(0, 0, 0, 1); - CheckTableCall(isolate, table, r, call_index, 0, null, null, null, null); + CheckTableCall(isolate, table, &r, call_index, 0, null, null, null, null); r.CheckCallViaJS(0, 0, 0, 2); - CheckTableCall(isolate, table, r, call_index, 0, 1, null, null, null); + CheckTableCall(isolate, table, &r, call_index, 0, 1, null, null, null); r.CheckCallViaJS(0, 0, 0, 3); - CheckTableCall(isolate, table, r, call_index, 0, 1, 2, null, null); + CheckTableCall(isolate, table, &r, call_index, 0, 1, 2, null, null); r.CheckCallViaJS(0, 3, 0, 2); - CheckTableCall(isolate, table, r, call_index, 0, 1, 2, 0, 1); + CheckTableCall(isolate, table, &r, call_index, 0, 1, 2, 0, 1); r.CheckCallViaJS(0, 3, 1, 2); - CheckTableCall(isolate, table, r, call_index, 0, 1, 2, 1, 2); + CheckTableCall(isolate, table, &r, call_index, 0, 1, 2, 1, 2); r.CheckCallViaJS(0, 3, 2, 2); - CheckTableCall(isolate, table, r, call_index, 0, 1, 2, 2, 3); + CheckTableCall(isolate, table, &r, call_index, 0, 1, 2, 2, 3); r.CheckCallViaJS(0, 3, 3, 2); - CheckTableCall(isolate, table, r, call_index, 0, 1, 2, 3, 4); + CheckTableCall(isolate, table, &r, call_index, 0, 1, 2, 3, 4); } WASM_EXEC_TEST(TableInitElems0) { TestTableInitElems(execution_tier, 0); } @@ -534,15 +530,15 @@ void TestTableInitOob(ExecutionTier execution_tier, int table_index) { isolate); const double null = 0xDEADBEEF; - CheckTableCall(isolate, table, r, call_index, null, null, null, null, null); + CheckTableCall(isolate, table, &r, call_index, null, null, null, null, null); // Write all values up to the out-of-bounds write. r.CheckCallViaJS(0xDEADBEEF, 3, 0, 3); - CheckTableCall(isolate, table, r, call_index, null, null, null, 0, 1); + CheckTableCall(isolate, table, &r, call_index, null, null, null, 0, 1); // Write all values up to the out-of-bounds read. r.CheckCallViaJS(0xDEADBEEF, 0, 3, 3); - CheckTableCall(isolate, table, r, call_index, 3, 4, null, 0, 1); + CheckTableCall(isolate, table, &r, call_index, 3, 4, null, 0, 1); // 0-count is never oob. r.CheckCallViaJS(0, kTableSize + 1, 0, 0); @@ -696,21 +692,21 @@ void TestTableCopyCalls(ExecutionTier execution_tier, int table_dst, isolate); if (table_dst == table_src) { - CheckTableCall(isolate, table, r, call_index, 0, 1, 2, 3, 4); + CheckTableCall(isolate, table, &r, call_index, 0, 1, 2, 3, 4); r.CheckCallViaJS(0, 0, 1, 1); - CheckTableCall(isolate, table, r, call_index, 1, 1, 2, 3, 4); + CheckTableCall(isolate, table, &r, call_index, 1, 1, 2, 3, 4); r.CheckCallViaJS(0, 0, 1, 2); - CheckTableCall(isolate, table, r, call_index, 1, 2, 2, 3, 4); + CheckTableCall(isolate, table, &r, call_index, 1, 2, 2, 3, 4); r.CheckCallViaJS(0, 3, 0, 2); - CheckTableCall(isolate, table, r, call_index, 1, 2, 2, 1, 2); + CheckTableCall(isolate, table, &r, call_index, 1, 2, 2, 1, 2); } else { - CheckTableCall(isolate, table, r, call_index, 0, 1, 2, 3, 4); + CheckTableCall(isolate, table, &r, call_index, 0, 1, 2, 3, 4); r.CheckCallViaJS(0, 0, 1, 1); - CheckTableCall(isolate, table, r, call_index, 1, 1, 2, 3, 4); + CheckTableCall(isolate, table, &r, call_index, 1, 1, 2, 3, 4); r.CheckCallViaJS(0, 0, 1, 2); - CheckTableCall(isolate, table, r, call_index, 1, 2, 2, 3, 4); + CheckTableCall(isolate, table, &r, call_index, 1, 2, 2, 3, 4); r.CheckCallViaJS(0, 3, 0, 2); - CheckTableCall(isolate, table, r, call_index, 1, 2, 2, 0, 1); + CheckTableCall(isolate, table, &r, call_index, 1, 2, 2, 0, 1); } } diff --git a/deps/v8/test/cctest/wasm/test-run-wasm-interpreter.cc b/deps/v8/test/cctest/wasm/test-run-wasm-interpreter.cc index 4c1842b537..1b64135cb8 100644 --- a/deps/v8/test/cctest/wasm/test-run-wasm-interpreter.cc +++ b/deps/v8/test/cctest/wasm/test-run-wasm-interpreter.cc @@ -278,7 +278,7 @@ TEST(Breakpoint_I32Add) { static const int kNumBreakpoints = 3; byte code[] = {WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))}; std::unique_ptr<int[]> offsets = - Find(code, sizeof(code), kNumBreakpoints, kExprGetLocal, kExprGetLocal, + Find(code, sizeof(code), kNumBreakpoints, kExprLocalGet, kExprLocalGet, kExprI32Add); WasmRunner<int32_t, uint32_t, uint32_t> r(ExecutionTier::kInterpreter); diff --git a/deps/v8/test/cctest/wasm/test-run-wasm-module.cc b/deps/v8/test/cctest/wasm/test-run-wasm-module.cc index 51d97650d4..5f70ab6c7b 100644 --- a/deps/v8/test/cctest/wasm/test-run-wasm-module.cc +++ b/deps/v8/test/cctest/wasm/test-run-wasm-module.cc @@ -11,7 +11,6 @@ #include "src/utils/version.h" #include "src/wasm/module-decoder.h" #include "src/wasm/wasm-engine.h" -#include "src/wasm/wasm-memory.h" #include "src/wasm/wasm-module-builder.h" #include "src/wasm/wasm-module.h" #include "src/wasm/wasm-objects-inl.h" @@ -943,154 +942,6 @@ TEST(MemoryWithOOBEmptyDataSegment) { Cleanup(); } -// Utility to free the allocated memory for a buffer that is manually -// externalized in a test. -struct ManuallyExternalizedBuffer { - Isolate* isolate_; - Handle<JSArrayBuffer> buffer_; - void* allocation_base_; - size_t allocation_length_; - bool const should_free_; - - ManuallyExternalizedBuffer(JSArrayBuffer buffer, Isolate* isolate) - : isolate_(isolate), - buffer_(buffer, isolate), - allocation_base_(buffer.allocation_base()), - allocation_length_(buffer.allocation_length()), - should_free_(!isolate_->wasm_engine()->memory_tracker()->IsWasmMemory( - buffer.backing_store())) { - if (!isolate_->wasm_engine()->memory_tracker()->IsWasmMemory( - buffer.backing_store())) { - v8::Utils::ToLocal(buffer_)->Externalize(); - } - } - ~ManuallyExternalizedBuffer() { - if (should_free_) { - buffer_->FreeBackingStoreFromMainThread(); - } - } -}; - -TEST(Run_WasmModule_Buffer_Externalized_GrowMem) { - { - Isolate* isolate = CcTest::InitIsolateOnce(); - HandleScope scope(isolate); - TestSignatures sigs; - v8::internal::AccountingAllocator allocator; - Zone zone(&allocator, ZONE_NAME); - - WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone); - WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v()); - ExportAsMain(f); - byte code[] = {WASM_GROW_MEMORY(WASM_I32V_1(6)), WASM_DROP, - WASM_MEMORY_SIZE}; - EMIT_CODE_WITH_END(f, code); - - ZoneBuffer buffer(&zone); - builder->WriteTo(&buffer); - testing::SetupIsolateForWasmModule(isolate); - ErrorThrower thrower(isolate, "Test"); - const Handle<WasmInstanceObject> instance = - CompileAndInstantiateForTesting( - isolate, &thrower, ModuleWireBytes(buffer.begin(), buffer.end())) - .ToHandleChecked(); - Handle<WasmMemoryObject> memory_object(instance->memory_object(), isolate); - - // Fake the Embedder flow by externalizing the array buffer. - ManuallyExternalizedBuffer buffer1(memory_object->array_buffer(), isolate); - - // Grow using the API. - uint32_t result = WasmMemoryObject::Grow(isolate, memory_object, 4); - CHECK_EQ(16, result); - CHECK(buffer1.buffer_->was_detached()); // growing always detaches - CHECK_EQ(0, buffer1.buffer_->byte_length()); - - CHECK_NE(*buffer1.buffer_, memory_object->array_buffer()); - - // Fake the Embedder flow by externalizing the array buffer. - ManuallyExternalizedBuffer buffer2(memory_object->array_buffer(), isolate); - - // Grow using an internal WASM bytecode. - result = testing::RunWasmModuleForTesting(isolate, instance, 0, nullptr); - CHECK_EQ(26, result); - CHECK(buffer2.buffer_->was_detached()); // growing always detaches - CHECK_EQ(0, buffer2.buffer_->byte_length()); - CHECK_NE(*buffer2.buffer_, memory_object->array_buffer()); - } - Cleanup(); -} - -TEST(Run_WasmModule_Buffer_Externalized_GrowMemMemSize) { - { - Isolate* isolate = CcTest::InitIsolateOnce(); - HandleScope scope(isolate); - Handle<JSArrayBuffer> buffer; - CHECK(wasm::NewArrayBuffer(isolate, 16 * kWasmPageSize).ToHandle(&buffer)); - Handle<WasmMemoryObject> mem_obj = - WasmMemoryObject::New(isolate, buffer, 100); - auto const contents = v8::Utils::ToLocal(buffer)->Externalize(); - int32_t result = WasmMemoryObject::Grow(isolate, mem_obj, 0); - CHECK_EQ(16, result); - constexpr bool is_wasm_memory = true; - const JSArrayBuffer::Allocation allocation{contents.AllocationBase(), - contents.AllocationLength(), - contents.Data(), is_wasm_memory}; - JSArrayBuffer::FreeBackingStore(isolate, allocation); - } - Cleanup(); -} - -TEST(Run_WasmModule_Buffer_Externalized_Detach) { - { - // Regression test for - // https://bugs.chromium.org/p/chromium/issues/detail?id=731046 - Isolate* isolate = CcTest::InitIsolateOnce(); - HandleScope scope(isolate); - Handle<JSArrayBuffer> buffer; - CHECK(wasm::NewArrayBuffer(isolate, 16 * kWasmPageSize).ToHandle(&buffer)); - auto const contents = v8::Utils::ToLocal(buffer)->Externalize(); - wasm::DetachMemoryBuffer(isolate, buffer, true); - constexpr bool is_wasm_memory = true; - const JSArrayBuffer::Allocation allocation{contents.AllocationBase(), - contents.AllocationLength(), - contents.Data(), is_wasm_memory}; - JSArrayBuffer::FreeBackingStore(isolate, allocation); - } - Cleanup(); -} - -TEST(Run_WasmModule_Buffer_Externalized_Regression_UseAfterFree) { - // Regresion test for https://crbug.com/813876 - Isolate* isolate = CcTest::InitIsolateOnce(); - HandleScope scope(isolate); - Handle<JSArrayBuffer> buffer; - CHECK(wasm::NewArrayBuffer(isolate, 16 * kWasmPageSize).ToHandle(&buffer)); - Handle<WasmMemoryObject> mem = WasmMemoryObject::New(isolate, buffer, 128); - auto contents = v8::Utils::ToLocal(buffer)->Externalize(); - WasmMemoryObject::Grow(isolate, mem, 0); - constexpr bool is_wasm_memory = true; - JSArrayBuffer::FreeBackingStore( - isolate, JSArrayBuffer::Allocation(contents.AllocationBase(), - contents.AllocationLength(), - contents.Data(), is_wasm_memory)); - // Make sure we can write to the buffer without crashing - uint32_t* int_buffer = - reinterpret_cast<uint32_t*>(mem->array_buffer().backing_store()); - int_buffer[0] = 0; -} - -#if V8_TARGET_ARCH_64_BIT -TEST(Run_WasmModule_Reclaim_Memory) { - // Make sure we can allocate memories without running out of address space. - Isolate* isolate = CcTest::InitIsolateOnce(); - Handle<JSArrayBuffer> buffer; - for (int i = 0; i < 256; ++i) { - HandleScope scope(isolate); - CHECK(NewArrayBuffer(isolate, kWasmPageSize).ToHandle(&buffer)); - } -} -#endif - TEST(AtomicOpDisassembly) { { EXPERIMENTAL_FLAG_SCOPE(threads); @@ -1118,12 +969,15 @@ TEST(AtomicOpDisassembly) { ErrorThrower thrower(isolate, "Test"); auto enabled_features = WasmFeaturesFromIsolate(isolate); - MaybeHandle<WasmModuleObject> module_object = - isolate->wasm_engine()->SyncCompile( - isolate, enabled_features, &thrower, - ModuleWireBytes(buffer.begin(), buffer.end())); + Handle<WasmModuleObject> module_object = + isolate->wasm_engine() + ->SyncCompile(isolate, enabled_features, &thrower, + ModuleWireBytes(buffer.begin(), buffer.end())) + .ToHandleChecked(); + NativeModule* native_module = module_object->native_module(); + ModuleWireBytes wire_bytes(native_module->wire_bytes()); - module_object.ToHandleChecked()->DisassembleFunction(0); + DisassembleWasmFunction(native_module->module(), wire_bytes, 0); } Cleanup(); } diff --git a/deps/v8/test/cctest/wasm/test-run-wasm-simd.cc b/deps/v8/test/cctest/wasm/test-run-wasm-simd.cc index b48321df40..d76c4c3643 100644 --- a/deps/v8/test/cctest/wasm/test-run-wasm-simd.cc +++ b/deps/v8/test/cctest/wasm/test-run-wasm-simd.cc @@ -184,13 +184,20 @@ T UnsignedGreaterEqual(T a, T b) { template <typename T> T LogicalShiftLeft(T a, int shift) { using UnsignedT = typename std::make_unsigned<T>::type; - return static_cast<UnsignedT>(a) << shift; + return static_cast<UnsignedT>(a) << (shift % (sizeof(T) * 8)); } template <typename T> T LogicalShiftRight(T a, int shift) { using UnsignedT = typename std::make_unsigned<T>::type; - return static_cast<UnsignedT>(a) >> shift; + return static_cast<UnsignedT>(a) >> (shift % (sizeof(T) * 8)); +} + +// Define our own ArithmeticShiftRight instead of using the one from utils.h +// because the shift amount needs to be taken modulo lane width. +template <typename T> +T ArithmeticShiftRight(T a, int shift) { + return a >> (shift % (sizeof(T) * 8)); } template <typename T> @@ -279,7 +286,7 @@ T Sqrt(T a) { return std::sqrt(a); } -#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 +#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_IA32 // only used for F64x2 tests below int64_t Equal(double a, double b) { return a == b ? -1 : 0; } @@ -292,14 +299,106 @@ int64_t GreaterEqual(double a, double b) { return a >= b ? -1 : 0; } int64_t Less(double a, double b) { return a < b ? -1 : 0; } int64_t LessEqual(double a, double b) { return a <= b ? -1 : 0; } + +#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 +// Only used for qfma and qfms tests below. + +// FMOperation holds the params (a, b, c) for a Multiply-Add or +// Multiply-Subtract operation, and the expected result if the operation was +// fused, rounded only once for the entire operation, or unfused, rounded after +// multiply and again after add/subtract. +template <typename T> +struct FMOperation { + const T a; + const T b; + const T c; + const T fused_result; + const T unfused_result; +}; + +// large_n is large number that overflows T when multiplied by itself, this is a +// useful constant to test fused/unfused behavior. +template <typename T> +constexpr T large_n = T(0); + +template <> +constexpr double large_n<double> = 1e200; + +template <> +constexpr float large_n<float> = 1e20; + +// Fused Multiply-Add performs a + b * c. +template <typename T> +static constexpr FMOperation<T> qfma_array[] = { + {1.0f, 2.0f, 3.0f, 7.0f, 7.0f}, + // fused: a + b * c = -inf + (positive overflow) = -inf + // unfused: a + b * c = -inf + inf = NaN + {-std::numeric_limits<T>::infinity(), large_n<T>, large_n<T>, + -std::numeric_limits<T>::infinity(), std::numeric_limits<T>::quiet_NaN()}, + // fused: a + b * c = inf + (negative overflow) = inf + // unfused: a + b * c = inf + -inf = NaN + {std::numeric_limits<T>::infinity(), -large_n<T>, large_n<T>, + std::numeric_limits<T>::infinity(), std::numeric_limits<T>::quiet_NaN()}, + // NaN + {std::numeric_limits<T>::quiet_NaN(), 2.0f, 3.0f, + std::numeric_limits<T>::quiet_NaN(), std::numeric_limits<T>::quiet_NaN()}, + // -NaN + {-std::numeric_limits<T>::quiet_NaN(), 2.0f, 3.0f, + std::numeric_limits<T>::quiet_NaN(), std::numeric_limits<T>::quiet_NaN()}}; + +template <typename T> +static constexpr Vector<const FMOperation<T>> qfma_vector() { + return ArrayVector(qfma_array<T>); +} + +// Fused Multiply-Subtract performs a - b * c. +template <typename T> +static constexpr FMOperation<T> qfms_array[]{ + {1.0f, 2.0f, 3.0f, -5.0f, -5.0f}, + // fused: a - b * c = inf - (positive overflow) = inf + // unfused: a - b * c = inf - inf = NaN + {std::numeric_limits<T>::infinity(), large_n<T>, large_n<T>, + std::numeric_limits<T>::infinity(), std::numeric_limits<T>::quiet_NaN()}, + // fused: a - b * c = -inf - (negative overflow) = -inf + // unfused: a - b * c = -inf - -inf = NaN + {-std::numeric_limits<T>::infinity(), -large_n<T>, large_n<T>, + -std::numeric_limits<T>::infinity(), std::numeric_limits<T>::quiet_NaN()}, + // NaN + {std::numeric_limits<T>::quiet_NaN(), 2.0f, 3.0f, + std::numeric_limits<T>::quiet_NaN(), std::numeric_limits<T>::quiet_NaN()}, + // -NaN + {-std::numeric_limits<T>::quiet_NaN(), 2.0f, 3.0f, + std::numeric_limits<T>::quiet_NaN(), std::numeric_limits<T>::quiet_NaN()}}; + +template <typename T> +static constexpr Vector<const FMOperation<T>> qfms_vector() { + return ArrayVector(qfms_array<T>); +} + +// Fused results only when fma3 feature is enabled, and running on TurboFan. +bool ExpectFused(ExecutionTier tier) { +#ifdef V8_TARGET_ARCH_X64 + return CpuFeatures::IsSupported(FMA3) && (tier == ExecutionTier::kTurbofan); +#else + return (tier == ExecutionTier::kTurbofan); +#endif +} #endif // V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 +#endif // V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_IA32 } // namespace -#define WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lane_value, lane_index) \ - WASM_IF(WASM_##LANE_TYPE##_NE(WASM_GET_LOCAL(lane_value), \ - WASM_SIMD_##TYPE##_EXTRACT_LANE( \ - lane_index, WASM_GET_LOCAL(value))), \ +#define WASM_SIMD_CHECK_LANE_S(TYPE, value, LANE_TYPE, lane_value, lane_index) \ + WASM_IF(WASM_##LANE_TYPE##_NE(WASM_GET_LOCAL(lane_value), \ + WASM_SIMD_##TYPE##_EXTRACT_LANE( \ + lane_index, WASM_GET_LOCAL(value))), \ + WASM_RETURN1(WASM_ZERO)) + +// Unsigned Extracts are only available for I8x16, I16x8 types +#define WASM_SIMD_CHECK_LANE_U(TYPE, value, LANE_TYPE, lane_value, lane_index) \ + WASM_IF(WASM_##LANE_TYPE##_NE(WASM_GET_LOCAL(lane_value), \ + WASM_SIMD_##TYPE##_EXTRACT_LANE_U( \ + lane_index, WASM_GET_LOCAL(value))), \ WASM_RETURN1(WASM_ZERO)) #define TO_BYTE(val) static_cast<byte>(val) @@ -338,13 +437,17 @@ int64_t LessEqual(double a, double b) { return a <= b ? -1 : 0; } #define WASM_SIMD_I16x8_SPLAT(x) WASM_SIMD_SPLAT(I16x8, x) #define WASM_SIMD_I16x8_EXTRACT_LANE(lane, x) \ - x, WASM_SIMD_OP(kExprI16x8ExtractLane), TO_BYTE(lane) + x, WASM_SIMD_OP(kExprI16x8ExtractLaneS), TO_BYTE(lane) +#define WASM_SIMD_I16x8_EXTRACT_LANE_U(lane, x) \ + x, WASM_SIMD_OP(kExprI16x8ExtractLaneU), TO_BYTE(lane) #define WASM_SIMD_I16x8_REPLACE_LANE(lane, x, y) \ x, y, WASM_SIMD_OP(kExprI16x8ReplaceLane), TO_BYTE(lane) #define WASM_SIMD_I8x16_SPLAT(x) WASM_SIMD_SPLAT(I8x16, x) #define WASM_SIMD_I8x16_EXTRACT_LANE(lane, x) \ - x, WASM_SIMD_OP(kExprI8x16ExtractLane), TO_BYTE(lane) + x, WASM_SIMD_OP(kExprI8x16ExtractLaneS), TO_BYTE(lane) +#define WASM_SIMD_I8x16_EXTRACT_LANE_U(lane, x) \ + x, WASM_SIMD_OP(kExprI8x16ExtractLaneU), TO_BYTE(lane) #define WASM_SIMD_I8x16_REPLACE_LANE(lane, x, y) \ x, y, WASM_SIMD_OP(kExprI8x16ReplaceLane), TO_BYTE(lane) @@ -357,8 +460,17 @@ int64_t LessEqual(double a, double b) { return a <= b ? -1 : 0; } #define WASM_SIMD_LOAD_MEM(index) \ index, WASM_SIMD_OP(kExprS128LoadMem), ZERO_ALIGNMENT, ZERO_OFFSET +#define WASM_SIMD_LOAD_MEM_OFFSET(offset, index) \ + index, WASM_SIMD_OP(kExprS128LoadMem), ZERO_ALIGNMENT, offset #define WASM_SIMD_STORE_MEM(index, val) \ index, val, WASM_SIMD_OP(kExprS128StoreMem), ZERO_ALIGNMENT, ZERO_OFFSET +#define WASM_SIMD_STORE_MEM_OFFSET(offset, index, val) \ + index, val, WASM_SIMD_OP(kExprS128StoreMem), ZERO_ALIGNMENT, offset + +#define WASM_SIMD_F64x2_QFMA(a, b, c) a, b, c, WASM_SIMD_OP(kExprF64x2Qfma) +#define WASM_SIMD_F64x2_QFMS(a, b, c) a, b, c, WASM_SIMD_OP(kExprF64x2Qfms) +#define WASM_SIMD_F32x4_QFMA(a, b, c) a, b, c, WASM_SIMD_OP(kExprF32x4Qfma) +#define WASM_SIMD_F32x4_QFMS(a, b, c) a, b, c, WASM_SIMD_OP(kExprF32x4Qfms) // Runs tests of compiled code, using the interpreter as a reference. #define WASM_SIMD_COMPILED_TEST(name) \ @@ -589,10 +701,15 @@ void RunF32x4UnOpTest(ExecutionTier execution_tier, LowerSimd lower_simd, WASM_SIMD_TEST(F32x4Abs) { RunF32x4UnOpTest(execution_tier, lower_simd, kExprF32x4Abs, std::abs); } + WASM_SIMD_TEST(F32x4Neg) { RunF32x4UnOpTest(execution_tier, lower_simd, kExprF32x4Neg, Negate); } +WASM_SIMD_TEST(F32x4Sqrt) { + RunF32x4UnOpTest(execution_tier, lower_simd, kExprF32x4Sqrt, Sqrt); +} + WASM_SIMD_TEST(F32x4RecipApprox) { RunF32x4UnOpTest(execution_tier, lower_simd, kExprF32x4RecipApprox, base::Recip, false /* !exact */); @@ -725,6 +842,57 @@ WASM_SIMD_TEST(F32x4Le) { } #if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 +WASM_SIMD_TEST_NO_LOWERING(F32x4Qfma) { + WasmRunner<int32_t, float, float, float> r(execution_tier, lower_simd); + // Set up global to hold mask output. + float* g = r.builder().AddGlobal<float>(kWasmS128); + // Build fn to splat test values, perform compare op, and write the result. + byte value1 = 0, value2 = 1, value3 = 2; + BUILD(r, + WASM_SET_GLOBAL(0, WASM_SIMD_F32x4_QFMA( + WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value1)), + WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value2)), + WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value3)))), + WASM_ONE); + + for (FMOperation<float> x : qfma_vector<float>()) { + r.Call(x.a, x.b, x.c); + float expected = + ExpectFused(execution_tier) ? x.fused_result : x.unfused_result; + for (int i = 0; i < 4; i++) { + float actual = ReadLittleEndianValue<float>(&g[i]); + CheckFloatResult(x.a, x.b, expected, actual, true /* exact */); + } + } +} + +WASM_SIMD_TEST_NO_LOWERING(F32x4Qfms) { + WasmRunner<int32_t, float, float, float> r(execution_tier, lower_simd); + // Set up global to hold mask output. + float* g = r.builder().AddGlobal<float>(kWasmS128); + // Build fn to splat test values, perform compare op, and write the result. + byte value1 = 0, value2 = 1, value3 = 2; + BUILD(r, + WASM_SET_GLOBAL(0, WASM_SIMD_F32x4_QFMS( + WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value1)), + WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value2)), + WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value3)))), + WASM_ONE); + + for (FMOperation<float> x : qfms_vector<float>()) { + r.Call(x.a, x.b, x.c); + float expected = + ExpectFused(execution_tier) ? x.fused_result : x.unfused_result; + for (int i = 0; i < 4; i++) { + float actual = ReadLittleEndianValue<float>(&g[i]); + CheckFloatResult(x.a, x.b, expected, actual, true /* exact */); + } + } +} +#endif // V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 + +#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_IA32 +#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 WASM_SIMD_TEST_NO_LOWERING(I64x2Splat) { WasmRunner<int32_t, int64_t> r(execution_tier, lower_simd); // Set up a global to hold output vector. @@ -803,7 +971,8 @@ WASM_SIMD_TEST_NO_LOWERING(I64x2Neg) { void RunI64x2ShiftOpTest(ExecutionTier execution_tier, LowerSimd lower_simd, WasmOpcode opcode, Int64ShiftOp expected_op) { - for (int shift = 1; shift < 64; shift++) { + // Intentionally shift by 64, should be no-op. + for (int shift = 1; shift <= 64; shift++) { WasmRunner<int32_t, int64_t> r(execution_tier, lower_simd); int64_t* g = r.builder().AddGlobal<int64_t>(kWasmS128); byte value = 0; @@ -918,6 +1087,7 @@ WASM_SIMD_TEST_NO_LOWERING(I64x2GeU) { RunI64x2BinOpTest(execution_tier, lower_simd, kExprI64x2GeU, UnsignedGreaterEqual); } +#endif // V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 WASM_SIMD_TEST_NO_LOWERING(F64x2Splat) { WasmRunner<int32_t, double> r(execution_tier, lower_simd); @@ -941,6 +1111,7 @@ WASM_SIMD_TEST_NO_LOWERING(F64x2Splat) { } } +#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 WASM_SIMD_TEST_NO_LOWERING(F64x2ExtractLaneWithI64x2) { WasmRunner<int64_t> r(execution_tier, lower_simd); BUILD(r, WASM_IF_ELSE_L( @@ -950,6 +1121,7 @@ WASM_SIMD_TEST_NO_LOWERING(F64x2ExtractLaneWithI64x2) { WASM_I64V(1), WASM_I64V(0))); CHECK_EQ(1, r.Call()); } +#endif // V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 WASM_SIMD_TEST_NO_LOWERING(F64x2ExtractLane) { WasmRunner<double, double> r(execution_tier, lower_simd); @@ -973,6 +1145,7 @@ WASM_SIMD_TEST_NO_LOWERING(F64x2ExtractLane) { } } +#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 WASM_SIMD_TEST_NO_LOWERING(I64x2ExtractWithF64x2) { WasmRunner<int64_t> r(execution_tier, lower_simd); BUILD(r, WASM_IF_ELSE_L( @@ -982,6 +1155,7 @@ WASM_SIMD_TEST_NO_LOWERING(I64x2ExtractWithF64x2) { WASM_I64V(1), WASM_I64V(0))); CHECK_EQ(1, r.Call()); } +#endif // V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 WASM_SIMD_TEST_NO_LOWERING(F64x2ReplaceLane) { WasmRunner<int32_t> r(execution_tier, lower_simd); @@ -1124,6 +1298,10 @@ WASM_SIMD_TEST_NO_LOWERING(F64x2Neg) { RunF64x2UnOpTest(execution_tier, lower_simd, kExprF64x2Neg, Negate); } +WASM_SIMD_TEST_NO_LOWERING(F64x2Sqrt) { + RunF64x2UnOpTest(execution_tier, lower_simd, kExprF64x2Sqrt, Sqrt); +} + void RunF64x2BinOpTest(ExecutionTier execution_tier, LowerSimd lower_simd, WasmOpcode opcode, DoubleBinOp expected_op) { WasmRunner<int32_t, double, double> r(execution_tier, lower_simd); @@ -1249,12 +1427,14 @@ WASM_SIMD_TEST_NO_LOWERING(F64x2Max) { RunF64x2BinOpTest(execution_tier, lower_simd, kExprF64x2Max, JSMax); } -#if V8_TARGET_ARCH_X64 +#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 WASM_SIMD_TEST_NO_LOWERING(I64x2Mul) { RunI64x2BinOpTest(execution_tier, lower_simd, kExprI64x2Mul, base::MulWithWraparound); } +#endif // V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 +#if V8_TARGET_ARCH_X64 WASM_SIMD_TEST_NO_LOWERING(I64x2MinS) { RunI64x2BinOpTest(execution_tier, lower_simd, kExprI64x2MinS, Minimum); } @@ -1273,7 +1453,57 @@ WASM_SIMD_TEST_NO_LOWERING(I64x2MaxU) { UnsignedMaximum); } #endif // V8_TARGET_ARCH_X64 + +#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 +WASM_SIMD_TEST_NO_LOWERING(F64x2Qfma) { + WasmRunner<int32_t, double, double, double> r(execution_tier, lower_simd); + // Set up global to hold mask output. + double* g = r.builder().AddGlobal<double>(kWasmS128); + // Build fn to splat test values, perform compare op, and write the result. + byte value1 = 0, value2 = 1, value3 = 2; + BUILD(r, + WASM_SET_GLOBAL(0, WASM_SIMD_F64x2_QFMA( + WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(value1)), + WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(value2)), + WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(value3)))), + WASM_ONE); + + for (FMOperation<double> x : qfma_vector<double>()) { + r.Call(x.a, x.b, x.c); + double expected = + ExpectFused(execution_tier) ? x.fused_result : x.unfused_result; + for (int i = 0; i < 2; i++) { + double actual = ReadLittleEndianValue<double>(&g[i]); + CheckDoubleResult(x.a, x.b, expected, actual, true /* exact */); + } + } +} + +WASM_SIMD_TEST_NO_LOWERING(F64x2Qfms) { + WasmRunner<int32_t, double, double, double> r(execution_tier, lower_simd); + // Set up global to hold mask output. + double* g = r.builder().AddGlobal<double>(kWasmS128); + // Build fn to splat test values, perform compare op, and write the result. + byte value1 = 0, value2 = 1, value3 = 2; + BUILD(r, + WASM_SET_GLOBAL(0, WASM_SIMD_F64x2_QFMS( + WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(value1)), + WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(value2)), + WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(value3)))), + WASM_ONE); + + for (FMOperation<double> x : qfms_vector<double>()) { + r.Call(x.a, x.b, x.c); + double expected = + ExpectFused(execution_tier) ? x.fused_result : x.unfused_result; + for (int i = 0; i < 2; i++) { + double actual = ReadLittleEndianValue<double>(&g[i]); + CheckDoubleResult(x.a, x.b, expected, actual, true /* exact */); + } + } +} #endif // V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 +#endif // V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_IA32 WASM_SIMD_TEST(I32x4Splat) { WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd); @@ -1652,7 +1882,8 @@ WASM_SIMD_TEST(I32x4GeU) { void RunI32x4ShiftOpTest(ExecutionTier execution_tier, LowerSimd lower_simd, WasmOpcode opcode, Int32ShiftOp expected_op) { - for (int shift = 1; shift < 32; shift++) { + // Intentionally shift by 32, should be no-op. + for (int shift = 1; shift <= 32; shift++) { WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd); int32_t* g = r.builder().AddGlobal<int32_t>(kWasmS128); byte value = 0; @@ -1902,7 +2133,8 @@ WASM_SIMD_TEST(I16x8LeU) { void RunI16x8ShiftOpTest(ExecutionTier execution_tier, LowerSimd lower_simd, WasmOpcode opcode, Int16ShiftOp expected_op) { - for (int shift = 1; shift < 16; shift++) { + // Intentionally shift by 16, should be no-op. + for (int shift = 1; shift <= 16; shift++) { WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd); int16_t* g = r.builder().AddGlobal<int16_t>(kWasmS128); byte value = 0; @@ -1917,7 +2149,7 @@ void RunI16x8ShiftOpTest(ExecutionTier execution_tier, LowerSimd lower_simd, FOR_INT16_INPUTS(x) { r.Call(x); - float expected = expected_op(x, shift); + int16_t expected = expected_op(x, shift); for (int i = 0; i < 8; i++) { CHECK_EQ(expected, ReadLittleEndianValue<int16_t>(&g[i])); } @@ -2118,7 +2350,8 @@ WASM_SIMD_TEST(I8x16Mul) { void RunI8x16ShiftOpTest(ExecutionTier execution_tier, LowerSimd lower_simd, WasmOpcode opcode, Int8ShiftOp expected_op) { - for (int shift = 1; shift < 8; shift++) { + // Intentionally shift by 8, should be no-op. + for (int shift = 1; shift <= 8; shift++) { WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd); int8_t* g = r.builder().AddGlobal<int8_t>(kWasmS128); byte value = 0; @@ -2184,10 +2417,10 @@ WASM_SIMD_TEST_NO_LOWERING(I8x16ShrU) { format, WASM_GET_LOCAL(src1), WASM_GET_LOCAL(src2), \ WASM_SIMD_BINOP(kExprI##format##Ne, WASM_GET_LOCAL(mask), \ WASM_GET_LOCAL(zero)))), \ - WASM_SIMD_CHECK_LANE(I##format, mask, I32, val2, 0), \ - WASM_SIMD_CHECK_LANE(I##format, mask, I32, val1, 1), \ - WASM_SIMD_CHECK_LANE(I##format, mask, I32, val1, 2), \ - WASM_SIMD_CHECK_LANE(I##format, mask, I32, val2, 3), WASM_ONE); \ + WASM_SIMD_CHECK_LANE_S(I##format, mask, I32, val2, 0), \ + WASM_SIMD_CHECK_LANE_S(I##format, mask, I32, val1, 1), \ + WASM_SIMD_CHECK_LANE_S(I##format, mask, I32, val1, 2), \ + WASM_SIMD_CHECK_LANE_S(I##format, mask, I32, val2, 3), WASM_ONE); \ \ CHECK_EQ(1, r.Call(0x12, 0x34)); \ } @@ -2222,10 +2455,10 @@ WASM_SIMD_SELECT_TEST(8x16) WASM_SET_LOCAL(mask, WASM_SIMD_SELECT(format, WASM_GET_LOCAL(src1), \ WASM_GET_LOCAL(src2), \ WASM_GET_LOCAL(mask))), \ - WASM_SIMD_CHECK_LANE(I##format, mask, I32, val2, 0), \ - WASM_SIMD_CHECK_LANE(I##format, mask, I32, combined, 1), \ - WASM_SIMD_CHECK_LANE(I##format, mask, I32, combined, 2), \ - WASM_SIMD_CHECK_LANE(I##format, mask, I32, val2, 3), WASM_ONE); \ + WASM_SIMD_CHECK_LANE_S(I##format, mask, I32, val2, 0), \ + WASM_SIMD_CHECK_LANE_S(I##format, mask, I32, combined, 1), \ + WASM_SIMD_CHECK_LANE_S(I##format, mask, I32, combined, 2), \ + WASM_SIMD_CHECK_LANE_S(I##format, mask, I32, val2, 3), WASM_ONE); \ \ CHECK_EQ(1, r.Call(0x12, 0x34, 0x32)); \ } @@ -2454,6 +2687,62 @@ WASM_SIMD_TEST(S8x16Concat) { } } +#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM64 +struct SwizzleTestArgs { + const Shuffle input; + const Shuffle indices; + const Shuffle expected; +}; + +static constexpr SwizzleTestArgs swizzle_test_args[] = { + {{15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, + {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}}, + {{15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, + {15, 0, 14, 1, 13, 2, 12, 3, 11, 4, 10, 5, 9, 6, 8, 7}, + {0, 15, 1, 14, 2, 13, 3, 12, 4, 11, 5, 10, 6, 9, 7, 8}}, + {{15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, + {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30}, + {15, 13, 11, 9, 7, 5, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0}}, + // all indices are out of range + {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {16, 17, 18, 19, 20, 124, 125, 126, 127, -1, -2, -3, -4, -5, -6, -7}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}; + +static constexpr Vector<const SwizzleTestArgs> swizzle_test_vector = + ArrayVector(swizzle_test_args); + +WASM_SIMD_TEST(S8x16Swizzle) { + // RunBinaryLaneOpTest set up the two globals to be consecutive integers, + // [0-15] and [16-31]. Using [0-15] as the indices will not sufficiently test + // swizzle since the expected result is a no-op, using [16-31] will result in + // all 0s. + WasmRunner<int32_t> r(execution_tier, lower_simd); + static const int kElems = kSimd128Size / sizeof(uint8_t); + uint8_t* dst = r.builder().AddGlobal<uint8_t>(kWasmS128); + uint8_t* src0 = r.builder().AddGlobal<uint8_t>(kWasmS128); + uint8_t* src1 = r.builder().AddGlobal<uint8_t>(kWasmS128); + BUILD( + r, + WASM_SET_GLOBAL(0, WASM_SIMD_BINOP(kExprS8x16Swizzle, WASM_GET_GLOBAL(1), + WASM_GET_GLOBAL(2))), + WASM_ONE); + + for (SwizzleTestArgs si : swizzle_test_vector) { + for (int i = 0; i < kElems; i++) { + WriteLittleEndianValue<uint8_t>(&src0[i], si.input[i]); + WriteLittleEndianValue<uint8_t>(&src1[i], si.indices[i]); + } + + CHECK_EQ(1, r.Call()); + + for (int i = 0; i < kElems; i++) { + CHECK_EQ(ReadLittleEndianValue<uint8_t>(&dst[i]), si.expected[i]); + } + } +} +#endif // V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM64 + // Combine 3 shuffles a, b, and c by applying both a and b and then applying c // to those two results. Shuffle Combine(const Shuffle& a, const Shuffle& b, const Shuffle& c) { @@ -2487,7 +2776,7 @@ void AppendShuffle(const Shuffle& shuffle, std::vector<byte>* buffer) { for (size_t i = 0; i < kSimd128Size; ++i) buffer->push_back((shuffle[i])); } -void BuildShuffle(std::vector<Shuffle>& shuffles, // NOLINT(runtime/references) +void BuildShuffle(const std::vector<Shuffle>& shuffles, std::vector<byte>* buffer) { // Perform the leaf shuffles on globals 0 and 1. size_t row_index = (shuffles.size() - 1) / 2; @@ -2504,7 +2793,7 @@ void BuildShuffle(std::vector<Shuffle>& shuffles, // NOLINT(runtime/references) } row_index /= 2; } while (row_index != 0); - byte epilog[] = {kExprSetGlobal, static_cast<byte>(0), WASM_ONE}; + byte epilog[] = {kExprGlobalSet, static_cast<byte>(0), WASM_ONE}; for (size_t j = 0; j < arraysize(epilog); ++j) buffer->push_back(epilog[j]); } @@ -2895,11 +3184,34 @@ WASM_SIMD_TEST(SimdLoadStoreLoad) { r.builder().AddMemoryElems<int32_t>(kWasmPageSize / sizeof(int32_t)); // Load memory, store it, then reload it and extract the first lane. Use a // non-zero offset into the memory of 1 lane (4 bytes) to test indexing. - BUILD(r, WASM_SIMD_STORE_MEM(WASM_I32V(4), WASM_SIMD_LOAD_MEM(WASM_I32V(4))), - WASM_SIMD_I32x4_EXTRACT_LANE(0, WASM_SIMD_LOAD_MEM(WASM_I32V(4)))); + BUILD(r, WASM_SIMD_STORE_MEM(WASM_I32V(8), WASM_SIMD_LOAD_MEM(WASM_I32V(4))), + WASM_SIMD_I32x4_EXTRACT_LANE(0, WASM_SIMD_LOAD_MEM(WASM_I32V(8)))); + + FOR_INT32_INPUTS(i) { + int32_t expected = i; + r.builder().WriteMemory(&memory[1], expected); + CHECK_EQ(expected, r.Call()); + } +} + +WASM_SIMD_TEST(SimdLoadStoreLoadMemargOffset) { + WasmRunner<int32_t> r(execution_tier, lower_simd); + int32_t* memory = + r.builder().AddMemoryElems<int32_t>(kWasmPageSize / sizeof(int32_t)); + constexpr byte offset_1 = 4; + constexpr byte offset_2 = 8; + // Load from memory at offset_1, store to offset_2, load from offset_2, and + // extract first lane. We use non-zero memarg offsets to test offset decoding. + BUILD( + r, + WASM_SIMD_STORE_MEM_OFFSET( + offset_2, WASM_ZERO, WASM_SIMD_LOAD_MEM_OFFSET(offset_1, WASM_ZERO)), + WASM_SIMD_I32x4_EXTRACT_LANE( + 0, WASM_SIMD_LOAD_MEM_OFFSET(offset_2, WASM_ZERO))); FOR_INT32_INPUTS(i) { int32_t expected = i; + // Index 1 of memory (int32_t) will be bytes 4 to 8. r.builder().WriteMemory(&memory[1], expected); CHECK_EQ(expected, r.Call()); } @@ -3040,8 +3352,48 @@ WASM_SIMD_TEST_NO_LOWERING(I16x8GtUMixed) { UnsignedGreater); } +#define WASM_EXTRACT_I16x8_TEST(Sign, Type) \ + WASM_SIMD_TEST(I16X8ExtractLane##Sign) { \ + WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd); \ + byte int_val = r.AllocateLocal(kWasmI32); \ + byte simd_val = r.AllocateLocal(kWasmS128); \ + BUILD(r, \ + WASM_SET_LOCAL(simd_val, \ + WASM_SIMD_I16x8_SPLAT(WASM_GET_LOCAL(int_val))), \ + WASM_SIMD_CHECK_LANE_U(I16x8, simd_val, I32, int_val, 0), \ + WASM_SIMD_CHECK_LANE_U(I16x8, simd_val, I32, int_val, 2), \ + WASM_SIMD_CHECK_LANE_U(I16x8, simd_val, I32, int_val, 4), \ + WASM_SIMD_CHECK_LANE_U(I16x8, simd_val, I32, int_val, 6), WASM_ONE); \ + FOR_##Type##_INPUTS(x) { CHECK_EQ(1, r.Call(x)); } \ + } +WASM_EXTRACT_I16x8_TEST(S, UINT16) WASM_EXTRACT_I16x8_TEST(I, INT16) +#undef WASM_EXTRACT_I16x8_TEST + +#define WASM_EXTRACT_I8x16_TEST(Sign, Type) \ + WASM_SIMD_TEST(I8x16ExtractLane##Sign) { \ + WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd); \ + byte int_val = r.AllocateLocal(kWasmI32); \ + byte simd_val = r.AllocateLocal(kWasmS128); \ + BUILD(r, \ + WASM_SET_LOCAL(simd_val, \ + WASM_SIMD_I8x16_SPLAT(WASM_GET_LOCAL(int_val))), \ + WASM_SIMD_CHECK_LANE_U(I8x16, simd_val, I32, int_val, 1), \ + WASM_SIMD_CHECK_LANE_U(I8x16, simd_val, I32, int_val, 3), \ + WASM_SIMD_CHECK_LANE_U(I8x16, simd_val, I32, int_val, 5), \ + WASM_SIMD_CHECK_LANE_U(I8x16, simd_val, I32, int_val, 7), \ + WASM_SIMD_CHECK_LANE_U(I8x16, simd_val, I32, int_val, 9), \ + WASM_SIMD_CHECK_LANE_U(I8x16, simd_val, I32, int_val, 10), \ + WASM_SIMD_CHECK_LANE_U(I8x16, simd_val, I32, int_val, 11), \ + WASM_SIMD_CHECK_LANE_U(I8x16, simd_val, I32, int_val, 13), \ + WASM_ONE); \ + FOR_##Type##_INPUTS(x) { CHECK_EQ(1, r.Call(x)); } \ + } + WASM_EXTRACT_I8x16_TEST(S, UINT8) WASM_EXTRACT_I8x16_TEST(I, INT8) +#undef WASM_EXTRACT_I8x16_TEST + #undef WASM_SIMD_TEST -#undef WASM_SIMD_CHECK_LANE +#undef WASM_SIMD_CHECK_LANE_S +#undef WASM_SIMD_CHECK_LANE_U #undef TO_BYTE #undef WASM_SIMD_OP #undef WASM_SIMD_SPLAT @@ -3064,13 +3416,17 @@ WASM_SIMD_TEST_NO_LOWERING(I16x8GtUMixed) { #undef WASM_SIMD_I32x4_REPLACE_LANE #undef WASM_SIMD_I16x8_SPLAT #undef WASM_SIMD_I16x8_EXTRACT_LANE +#undef WASM_SIMD_I16x8_EXTRACT_LANE_U #undef WASM_SIMD_I16x8_REPLACE_LANE #undef WASM_SIMD_I8x16_SPLAT #undef WASM_SIMD_I8x16_EXTRACT_LANE +#undef WASM_SIMD_I8x16_EXTRACT_LANE_U #undef WASM_SIMD_I8x16_REPLACE_LANE #undef WASM_SIMD_S8x16_SHUFFLE_OP #undef WASM_SIMD_LOAD_MEM +#undef WASM_SIMD_LOAD_MEM_OFFSET #undef WASM_SIMD_STORE_MEM +#undef WASM_SIMD_STORE_MEM_OFFSET #undef WASM_SIMD_SELECT_TEST #undef WASM_SIMD_NON_CANONICAL_SELECT_TEST #undef WASM_SIMD_COMPILED_TEST @@ -3078,6 +3434,10 @@ WASM_SIMD_TEST_NO_LOWERING(I16x8GtUMixed) { #undef WASM_SIMD_TEST_NO_LOWERING #undef WASM_SIMD_ANYTRUE_TEST #undef WASM_SIMD_ALLTRUE_TEST +#undef WASM_SIMD_F64x2_QFMA +#undef WASM_SIMD_F64x2_QFMS +#undef WASM_SIMD_F32x4_QFMA +#undef WASM_SIMD_F32x4_QFMS } // namespace test_run_wasm_simd } // namespace wasm diff --git a/deps/v8/test/cctest/wasm/test-run-wasm.cc b/deps/v8/test/cctest/wasm/test-run-wasm.cc index 26df61ceb8..aa6195b8b3 100644 --- a/deps/v8/test/cctest/wasm/test-run-wasm.cc +++ b/deps/v8/test/cctest/wasm/test-run-wasm.cc @@ -49,8 +49,8 @@ WASM_EXEC_TEST(Int32Const_many) { WASM_EXEC_TEST(GraphTrimming) { // This WebAssembly code requires graph trimming in the TurboFan compiler. WasmRunner<int32_t, int32_t> r(execution_tier); - BUILD(r, kExprGetLocal, 0, kExprGetLocal, 0, kExprGetLocal, 0, kExprI32RemS, - kExprI32Eq, kExprGetLocal, 0, kExprI32DivS, kExprUnreachable); + BUILD(r, kExprLocalGet, 0, kExprLocalGet, 0, kExprLocalGet, 0, kExprI32RemS, + kExprI32Eq, kExprLocalGet, 0, kExprI32DivS, kExprUnreachable); r.Call(1); } @@ -1810,18 +1810,18 @@ WASM_EXEC_TEST(CheckMachIntsZero) { BUILD(r, // -- /**/ kExprLoop, kLocalVoid, // -- - /* */ kExprGetLocal, 0, // -- + /* */ kExprLocalGet, 0, // -- /* */ kExprIf, kLocalVoid, // -- - /* */ kExprGetLocal, 0, // -- + /* */ kExprLocalGet, 0, // -- /* */ kExprI32LoadMem, 0, 0, // -- /* */ kExprIf, kLocalVoid, // -- /* */ kExprI32Const, 127, // -- /* */ kExprReturn, // -- /* */ kExprEnd, // -- - /* */ kExprGetLocal, 0, // -- + /* */ kExprLocalGet, 0, // -- /* */ kExprI32Const, 4, // -- /* */ kExprI32Sub, // -- - /* */ kExprTeeLocal, 0, // -- + /* */ kExprLocalTee, 0, // -- /* */ kExprBr, DEPTH_0, // -- /* */ kExprEnd, // -- /**/ kExprEnd, // -- @@ -2012,16 +2012,16 @@ static void TestBuildGraphForSimpleExpression(WasmOpcode opcode) { FunctionSig* sig = WasmOpcodes::Signature(opcode); if (sig->parameter_count() == 1) { - byte code[] = {WASM_NO_LOCALS, kExprGetLocal, 0, static_cast<byte>(opcode), + byte code[] = {WASM_NO_LOCALS, kExprLocalGet, 0, static_cast<byte>(opcode), WASM_END}; TestBuildingGraph(&zone, &jsgraph, nullptr, sig, nullptr, code, code + arraysize(code)); } else { CHECK_EQ(2, sig->parameter_count()); byte code[] = {WASM_NO_LOCALS, - kExprGetLocal, + kExprLocalGet, 0, - kExprGetLocal, + kExprLocalGet, 1, static_cast<byte>(opcode), WASM_END}; @@ -2667,7 +2667,7 @@ static void Run_WasmMixedCall_N(ExecutionTier execution_tier, int start) { // Store the result in a local. byte local_index = r.AllocateLocal(ValueTypes::ValueTypeFor(result)); - ADD_CODE(code, kExprSetLocal, local_index); + ADD_CODE(code, kExprLocalSet, local_index); // Store the result in memory. ADD_CODE(code, @@ -2761,10 +2761,11 @@ void RunMultiReturnSelect(ExecutionTier execution_tier, const T* inputs) { WASM_GET_LOCAL(3)), WASM_DROP); } else { - BUILD(r, WASM_CALL_FUNCTION(r1.function_index(), WASM_GET_LOCAL(0), - WASM_GET_LOCAL(1), WASM_GET_LOCAL(2), - WASM_GET_LOCAL(3)), - kExprSetLocal, 0, WASM_DROP, WASM_GET_LOCAL(0)); + BUILD(r, + WASM_CALL_FUNCTION(r1.function_index(), WASM_GET_LOCAL(0), + WASM_GET_LOCAL(1), WASM_GET_LOCAL(2), + WASM_GET_LOCAL(3)), + kExprLocalSet, 0, WASM_DROP, WASM_GET_LOCAL(0)); } T expected = inputs[k == 0 ? i : j]; @@ -3330,7 +3331,7 @@ static void CompileCallIndirectMany(ExecutionTier tier, ValueType param) { std::vector<byte> code; for (byte p = 0; p < num_params; ++p) { - ADD_CODE(code, kExprGetLocal, p); + ADD_CODE(code, kExprLocalGet, p); } ADD_CODE(code, kExprI32Const, 0); ADD_CODE(code, kExprCallIndirect, 1, TABLE_ZERO); diff --git a/deps/v8/test/cctest/wasm/test-streaming-compilation.cc b/deps/v8/test/cctest/wasm/test-streaming-compilation.cc index 795fa30e72..f9089b7821 100644 --- a/deps/v8/test/cctest/wasm/test-streaming-compilation.cc +++ b/deps/v8/test/cctest/wasm/test-streaming-compilation.cc @@ -194,17 +194,17 @@ ZoneBuffer GetValidModuleBytes(Zone* zone) { WasmModuleBuilder builder(zone); { WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii()); - uint8_t code[] = {kExprGetLocal, 0, kExprEnd}; + uint8_t code[] = {kExprLocalGet, 0, kExprEnd}; f->EmitCode(code, arraysize(code)); } { WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii()); - uint8_t code[] = {kExprGetLocal, 1, kExprEnd}; + uint8_t code[] = {kExprLocalGet, 1, kExprEnd}; f->EmitCode(code, arraysize(code)); } { WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii()); - uint8_t code[] = {kExprGetLocal, 2, kExprEnd}; + uint8_t code[] = {kExprLocalGet, 2, kExprEnd}; f->EmitCode(code, arraysize(code)); } builder.WriteTo(&buffer); @@ -317,17 +317,17 @@ ZoneBuffer GetModuleWithInvalidSection(Zone* zone) { WasmInitExpr(WasmInitExpr::kGlobalIndex, 12)); { WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii()); - uint8_t code[] = {kExprGetLocal, 0, kExprEnd}; + uint8_t code[] = {kExprLocalGet, 0, kExprEnd}; f->EmitCode(code, arraysize(code)); } { WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii()); - uint8_t code[] = {kExprGetLocal, 1, kExprEnd}; + uint8_t code[] = {kExprLocalGet, 1, kExprEnd}; f->EmitCode(code, arraysize(code)); } { WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii()); - uint8_t code[] = {kExprGetLocal, 2, kExprEnd}; + uint8_t code[] = {kExprLocalGet, 2, kExprEnd}; f->EmitCode(code, arraysize(code)); } builder.WriteTo(&buffer); @@ -442,7 +442,7 @@ STREAM_TEST(TestErrorInCodeSectionDetectedByModuleDecoder) { uint8_t code[] = { U32V_1(4), // body size U32V_1(0), // locals count - kExprGetLocal, 0, kExprEnd // body + kExprLocalGet, 0, kExprEnd // body }; const uint8_t bytes[] = { @@ -481,7 +481,7 @@ STREAM_TEST(TestErrorInCodeSectionDetectedByStreamingDecoder) { uint8_t code[] = { U32V_1(26), // !!! invalid body size !!! U32V_1(0), // locals count - kExprGetLocal, 0, kExprEnd // body + kExprLocalGet, 0, kExprEnd // body }; const uint8_t bytes[] = { @@ -520,7 +520,7 @@ STREAM_TEST(TestErrorInCodeSectionDetectedByCompiler) { uint8_t code[] = { U32V_1(4), // !!! invalid body size !!! U32V_1(0), // locals count - kExprGetLocal, 0, kExprEnd // body + kExprLocalGet, 0, kExprEnd // body }; uint8_t invalid_code[] = { @@ -679,7 +679,7 @@ STREAM_TEST(TestAbortAfterFunctionGotCompiled1) { uint8_t code[] = { U32V_1(4), // !!! invalid body size !!! U32V_1(0), // locals count - kExprGetLocal, 0, kExprEnd // body + kExprLocalGet, 0, kExprEnd // body }; const uint8_t bytes[] = { @@ -713,7 +713,7 @@ STREAM_TEST(TestAbortAfterFunctionGotCompiled2) { uint8_t code[] = { U32V_1(4), // !!! invalid body size !!! U32V_1(0), // locals count - kExprGetLocal, 0, kExprEnd // body + kExprLocalGet, 0, kExprEnd // body }; const uint8_t bytes[] = { @@ -745,7 +745,7 @@ STREAM_TEST(TestAbortAfterCodeSection1) { uint8_t code[] = { U32V_1(4), // body size U32V_1(0), // locals count - kExprGetLocal, 0, kExprEnd // body + kExprLocalGet, 0, kExprEnd // body }; const uint8_t bytes[] = { @@ -781,7 +781,7 @@ STREAM_TEST(TestAbortAfterCodeSection2) { uint8_t code[] = { U32V_1(4), // body size U32V_1(0), // locals count - kExprGetLocal, 0, kExprEnd // body + kExprLocalGet, 0, kExprEnd // body }; const uint8_t bytes[] = { @@ -815,7 +815,7 @@ STREAM_TEST(TestAbortAfterCompilationError1) { uint8_t code[] = { U32V_1(4), // !!! invalid body size !!! U32V_1(0), // locals count - kExprGetLocal, 0, kExprEnd // body + kExprLocalGet, 0, kExprEnd // body }; uint8_t invalid_code[] = { @@ -857,7 +857,7 @@ STREAM_TEST(TestAbortAfterCompilationError2) { uint8_t code[] = { U32V_1(4), // !!! invalid body size !!! U32V_1(0), // locals count - kExprGetLocal, 0, kExprEnd // body + kExprLocalGet, 0, kExprEnd // body }; uint8_t invalid_code[] = { @@ -934,7 +934,7 @@ STREAM_TEST(TestModuleWithMultipleFunctions) { uint8_t code[] = { U32V_1(4), // body size U32V_1(0), // locals count - kExprGetLocal, 0, kExprEnd // body + kExprLocalGet, 0, kExprEnd // body }; const uint8_t bytes[] = { @@ -970,7 +970,7 @@ STREAM_TEST(TestModuleWithDataSection) { uint8_t code[] = { U32V_1(4), // body size U32V_1(0), // locals count - kExprGetLocal, 0, kExprEnd // body + kExprLocalGet, 0, kExprEnd // body }; const uint8_t bytes[] = { @@ -1016,7 +1016,7 @@ STREAM_TEST(TestModuleWithImportedFunction) { builder.AddImport(ArrayVector("Test"), sigs.i_iii()); { WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii()); - uint8_t code[] = {kExprGetLocal, 0, kExprEnd}; + uint8_t code[] = {kExprLocalGet, 0, kExprEnd}; f->EmitCode(code, arraysize(code)); } builder.WriteTo(&buffer); @@ -1047,7 +1047,7 @@ STREAM_TEST(TestModuleWithErrorAfterDataSection) { U32V_1(1), // functions count U32V_1(4), // body size U32V_1(0), // locals count - kExprGetLocal, // some code + kExprLocalGet, // some code 0, // some code kExprEnd, // some code kDataSectionCode, // section code @@ -1133,7 +1133,7 @@ STREAM_TEST(TestSetModuleCompiledCallback) { uint8_t code[] = { U32V_1(4), // body size U32V_1(0), // locals count - kExprGetLocal, 0, kExprEnd // body + kExprLocalGet, 0, kExprEnd // body }; const uint8_t bytes[] = { diff --git a/deps/v8/test/cctest/wasm/test-wasm-breakpoints.cc b/deps/v8/test/cctest/wasm/test-wasm-breakpoints.cc index e287b1139e..798e1d46da 100644 --- a/deps/v8/test/cctest/wasm/test-wasm-breakpoints.cc +++ b/deps/v8/test/cctest/wasm/test-wasm-breakpoints.cc @@ -22,10 +22,11 @@ namespace wasm { namespace { void CheckLocations( - WasmModuleObject module_object, debug::Location start, debug::Location end, + NativeModule* native_module, debug::Location start, debug::Location end, std::initializer_list<debug::Location> expected_locations_init) { std::vector<debug::BreakLocation> locations; - bool success = module_object.GetPossibleBreakpoints(start, end, &locations); + bool success = WasmModuleObject::GetPossibleBreakpoints(native_module, start, + end, &locations); CHECK(success); printf("got %d locations: ", static_cast<int>(locations.size())); @@ -45,10 +46,11 @@ void CheckLocations( } } -void CheckLocationsFail(WasmModuleObject module_object, debug::Location start, +void CheckLocationsFail(NativeModule* native_module, debug::Location start, debug::Location end) { std::vector<debug::BreakLocation> locations; - bool success = module_object.GetPossibleBreakpoints(start, end, &locations); + bool success = WasmModuleObject::GetPossibleBreakpoints(native_module, start, + end, &locations); CHECK(!success); } @@ -63,8 +65,12 @@ class BreakHandler : public debug::DebugDelegate { struct BreakPoint { int position; Action action; + std::function<void(void)> pre_action; BreakPoint(int position, Action action) - : position(position), action(action) {} + : position(position), action(action), pre_action([]() {}) {} + BreakPoint(int position, Action action, + std::function<void(void)> pre_action) + : position(position), action(action), pre_action(pre_action) {} }; explicit BreakHandler(Isolate* isolate, @@ -96,6 +102,7 @@ class BreakHandler : public debug::DebugDelegate { auto summ = FrameSummary::GetTop(frame_it.frame()).AsWasmInterpreted(); CHECK_EQ(expected_breaks_[count_].position, summ.byte_offset()); + expected_breaks_[count_].pre_action(); Action next_action = expected_breaks_[count_].action; switch (next_action) { case Continue: @@ -112,22 +119,21 @@ class BreakHandler : public debug::DebugDelegate { } }; -void SetBreakpoint(WasmRunnerBase& runner, // NOLINT(runtime/references) - int function_index, int byte_offset, - int expected_set_byte_offset = -1) { +Handle<BreakPoint> SetBreakpoint(WasmRunnerBase* runner, int function_index, + int byte_offset, + int expected_set_byte_offset = -1) { int func_offset = - runner.builder().GetFunctionAt(function_index)->code.offset(); + runner->builder().GetFunctionAt(function_index)->code.offset(); int code_offset = func_offset + byte_offset; if (expected_set_byte_offset == -1) expected_set_byte_offset = byte_offset; - Handle<WasmInstanceObject> instance = runner.builder().instance_object(); - Handle<WasmModuleObject> module_object(instance->module_object(), - runner.main_isolate()); + Handle<WasmInstanceObject> instance = runner->builder().instance_object(); + Handle<Script> script(instance->module_object().script(), + runner->main_isolate()); static int break_index = 0; Handle<BreakPoint> break_point = - runner.main_isolate()->factory()->NewBreakPoint( - break_index++, runner.main_isolate()->factory()->empty_string()); - CHECK(WasmModuleObject::SetBreakPoint(module_object, &code_offset, - break_point)); + runner->main_isolate()->factory()->NewBreakPoint( + break_index++, runner->main_isolate()->factory()->empty_string()); + CHECK(WasmModuleObject::SetBreakPoint(script, &code_offset, break_point)); int set_byte_offset = code_offset - func_offset; CHECK_EQ(expected_set_byte_offset, set_byte_offset); // Also set breakpoint on the debug info of the instance directly, since the @@ -135,6 +141,24 @@ void SetBreakpoint(WasmRunnerBase& runner, // NOLINT(runtime/references) Handle<WasmDebugInfo> debug_info = WasmInstanceObject::GetOrCreateDebugInfo(instance); WasmDebugInfo::SetBreakpoint(debug_info, function_index, set_byte_offset); + + return break_point; +} + +void ClearBreakpoint(WasmRunnerBase* runner, int function_index, + int byte_offset, Handle<BreakPoint> break_point) { + int func_offset = + runner->builder().GetFunctionAt(function_index)->code.offset(); + int code_offset = func_offset + byte_offset; + Handle<WasmInstanceObject> instance = runner->builder().instance_object(); + Handle<Script> script(instance->module_object().script(), + runner->main_isolate()); + CHECK(WasmModuleObject::ClearBreakPoint(script, code_offset, break_point)); + // Also clear breakpoint on the debug info of the instance directly, since the + // instance chain is not setup properly in tests. + Handle<WasmDebugInfo> debug_info = + WasmInstanceObject::GetOrCreateDebugInfo(instance); + WasmDebugInfo::ClearBreakpoint(debug_info, function_index, byte_offset); } // Wrapper with operator<<. @@ -247,25 +271,25 @@ WASM_COMPILED_EXEC_TEST(WasmCollectPossibleBreakpoints) { BUILD(runner, WASM_NOP, WASM_I32_ADD(WASM_ZERO, WASM_ONE)); WasmInstanceObject instance = *runner.builder().instance_object(); - WasmModuleObject module_object = instance.module_object(); + NativeModule* native_module = instance.module_object().native_module(); std::vector<debug::Location> locations; // Check all locations for function 0. - CheckLocations(module_object, {0, 0}, {1, 0}, + CheckLocations(native_module, {0, 0}, {1, 0}, {{0, 1}, {0, 2}, {0, 4}, {0, 6}, {0, 7}}); // Check a range ending at an instruction. - CheckLocations(module_object, {0, 2}, {0, 4}, {{0, 2}}); + CheckLocations(native_module, {0, 2}, {0, 4}, {{0, 2}}); // Check a range ending one behind an instruction. - CheckLocations(module_object, {0, 2}, {0, 5}, {{0, 2}, {0, 4}}); + CheckLocations(native_module, {0, 2}, {0, 5}, {{0, 2}, {0, 4}}); // Check a range starting at an instruction. - CheckLocations(module_object, {0, 7}, {0, 8}, {{0, 7}}); + CheckLocations(native_module, {0, 7}, {0, 8}, {{0, 7}}); // Check from an instruction to beginning of next function. - CheckLocations(module_object, {0, 7}, {1, 0}, {{0, 7}}); + CheckLocations(native_module, {0, 7}, {1, 0}, {{0, 7}}); // Check from end of one function (no valid instruction position) to beginning // of next function. Must be empty, but not fail. - CheckLocations(module_object, {0, 8}, {1, 0}, {}); + CheckLocations(native_module, {0, 8}, {1, 0}, {}); // Check from one after the end of the function. Must fail. - CheckLocationsFail(module_object, {0, 9}, {1, 0}); + CheckLocationsFail(native_module, {0, 9}, {1, 0}); } WASM_COMPILED_EXEC_TEST(WasmSimpleBreak) { @@ -276,7 +300,7 @@ WASM_COMPILED_EXEC_TEST(WasmSimpleBreak) { Handle<JSFunction> main_fun_wrapper = runner.builder().WrapCode(runner.function_index()); - SetBreakpoint(runner, runner.function_index(), 4, 4); + SetBreakpoint(&runner, runner.function_index(), 4, 4); BreakHandler count_breaks(isolate, {{4, BreakHandler::Continue}}); @@ -298,7 +322,7 @@ WASM_COMPILED_EXEC_TEST(WasmSimpleStepping) { runner.builder().WrapCode(runner.function_index()); // Set breakpoint at the first I32Const. - SetBreakpoint(runner, runner.function_index(), 1, 1); + SetBreakpoint(&runner, runner.function_index(), 1, 1); BreakHandler count_breaks(isolate, { @@ -340,12 +364,12 @@ WASM_COMPILED_EXEC_TEST(WasmStepInAndOut) { Handle<JSFunction> main_fun_wrapper = runner.builder().WrapCode(f2.function_index()); - // Set first breakpoint on the GetLocal (offset 19) before the Call. - SetBreakpoint(runner, f2.function_index(), 19, 19); + // Set first breakpoint on the LocalGet (offset 19) before the Call. + SetBreakpoint(&runner, f2.function_index(), 19, 19); BreakHandler count_breaks(isolate, { - {19, BreakHandler::StepIn}, // GetLocal + {19, BreakHandler::StepIn}, // LocalGet {21, BreakHandler::StepIn}, // Call {1, BreakHandler::StepOut}, // in f2 {23, BreakHandler::Continue} // After Call @@ -377,7 +401,7 @@ WASM_COMPILED_EXEC_TEST(WasmGetLocalsAndStack) { // Set breakpoint at the first instruction (7 bytes for local decls: num // entries + 3x<count, type>). - SetBreakpoint(runner, runner.function_index(), 7, 7); + SetBreakpoint(&runner, runner.function_index(), 7, 7); CollectValuesBreakHandler break_handler( isolate, @@ -401,6 +425,104 @@ WASM_COMPILED_EXEC_TEST(WasmGetLocalsAndStack) { CHECK(!Execution::Call(isolate, main_fun_wrapper, global, 1, args).is_null()); } +WASM_COMPILED_EXEC_TEST(WasmRemoveBreakPoint) { + WasmRunner<int> runner(execution_tier); + Isolate* isolate = runner.main_isolate(); + + BUILD(runner, WASM_NOP, WASM_NOP, WASM_NOP, WASM_NOP, WASM_NOP, + WASM_I32V_1(14)); + + Handle<JSFunction> main_fun_wrapper = + runner.builder().WrapCode(runner.function_index()); + + SetBreakpoint(&runner, runner.function_index(), 1, 1); + SetBreakpoint(&runner, runner.function_index(), 2, 2); + Handle<BreakPoint> to_delete = + SetBreakpoint(&runner, runner.function_index(), 3, 3); + SetBreakpoint(&runner, runner.function_index(), 4, 4); + + BreakHandler count_breaks(isolate, {{1, BreakHandler::Continue}, + {2, BreakHandler::Continue, + [&runner, &to_delete]() { + ClearBreakpoint( + &runner, runner.function_index(), + 3, to_delete); + }}, + {4, BreakHandler::Continue}}); + + Handle<Object> global(isolate->context().global_object(), isolate); + MaybeHandle<Object> retval = + Execution::Call(isolate, main_fun_wrapper, global, 0, nullptr); + CHECK(!retval.is_null()); + int result; + CHECK(retval.ToHandleChecked()->ToInt32(&result)); + CHECK_EQ(14, result); +} + +WASM_COMPILED_EXEC_TEST(WasmRemoveLastBreakPoint) { + WasmRunner<int> runner(execution_tier); + Isolate* isolate = runner.main_isolate(); + + BUILD(runner, WASM_NOP, WASM_NOP, WASM_NOP, WASM_NOP, WASM_NOP, + WASM_I32V_1(14)); + + Handle<JSFunction> main_fun_wrapper = + runner.builder().WrapCode(runner.function_index()); + + SetBreakpoint(&runner, runner.function_index(), 1, 1); + SetBreakpoint(&runner, runner.function_index(), 2, 2); + Handle<BreakPoint> to_delete = + SetBreakpoint(&runner, runner.function_index(), 3, 3); + + BreakHandler count_breaks( + isolate, {{1, BreakHandler::Continue}, + {2, BreakHandler::Continue, [&runner, &to_delete]() { + ClearBreakpoint(&runner, runner.function_index(), 3, + to_delete); + }}}); + + Handle<Object> global(isolate->context().global_object(), isolate); + MaybeHandle<Object> retval = + Execution::Call(isolate, main_fun_wrapper, global, 0, nullptr); + CHECK(!retval.is_null()); + int result; + CHECK(retval.ToHandleChecked()->ToInt32(&result)); + CHECK_EQ(14, result); +} + +WASM_COMPILED_EXEC_TEST(WasmRemoveAllBreakPoint) { + WasmRunner<int> runner(execution_tier); + Isolate* isolate = runner.main_isolate(); + + BUILD(runner, WASM_NOP, WASM_NOP, WASM_NOP, WASM_NOP, WASM_NOP, + WASM_I32V_1(14)); + + Handle<JSFunction> main_fun_wrapper = + runner.builder().WrapCode(runner.function_index()); + + Handle<BreakPoint> bp1 = + SetBreakpoint(&runner, runner.function_index(), 1, 1); + Handle<BreakPoint> bp2 = + SetBreakpoint(&runner, runner.function_index(), 2, 2); + Handle<BreakPoint> bp3 = + SetBreakpoint(&runner, runner.function_index(), 3, 3); + + BreakHandler count_breaks( + isolate, {{1, BreakHandler::Continue, [&runner, &bp1, &bp2, &bp3]() { + ClearBreakpoint(&runner, runner.function_index(), 1, bp1); + ClearBreakpoint(&runner, runner.function_index(), 3, bp3); + ClearBreakpoint(&runner, runner.function_index(), 2, bp2); + }}}); + + Handle<Object> global(isolate->context().global_object(), isolate); + MaybeHandle<Object> retval = + Execution::Call(isolate, main_fun_wrapper, global, 0, nullptr); + CHECK(!retval.is_null()); + int result; + CHECK(retval.ToHandleChecked()->ToInt32(&result)); + CHECK_EQ(14, result); +} + } // namespace wasm } // namespace internal } // namespace v8 diff --git a/deps/v8/test/cctest/wasm/test-wasm-import-wrapper-cache.cc b/deps/v8/test/cctest/wasm/test-wasm-import-wrapper-cache.cc index 299c039698..15267215e1 100644 --- a/deps/v8/test/cctest/wasm/test-wasm-import-wrapper-cache.cc +++ b/deps/v8/test/cctest/wasm/test-wasm-import-wrapper-cache.cc @@ -22,10 +22,8 @@ std::shared_ptr<NativeModule> NewModule(Isolate* isolate) { std::shared_ptr<WasmModule> module(new WasmModule); bool can_request_more = false; size_t size = 16384; - auto native_module = isolate->wasm_engine()->NewNativeModule( + return isolate->wasm_engine()->NewNativeModule( isolate, kAllWasmFeatures, size, can_request_more, std::move(module)); - native_module->SetRuntimeStubs(isolate); - return native_module; } TEST(CacheHit) { diff --git a/deps/v8/test/cctest/wasm/test-wasm-interpreter-entry.cc b/deps/v8/test/cctest/wasm/test-wasm-interpreter-entry.cc index 736475ff55..75e927fafe 100644 --- a/deps/v8/test/cctest/wasm/test-wasm-interpreter-entry.cc +++ b/deps/v8/test/cctest/wasm/test-wasm-interpreter-entry.cc @@ -32,28 +32,27 @@ namespace { template <typename T> class ArgPassingHelper { public: - ArgPassingHelper( - WasmRunnerBase& runner, // NOLINT(runtime/references) - WasmFunctionCompiler& inner_compiler, // NOLINT(runtime/references) - std::initializer_list<uint8_t> bytes_inner_function, - std::initializer_list<uint8_t> bytes_outer_function, - const T& expected_lambda) - : isolate_(runner.main_isolate()), + ArgPassingHelper(WasmRunnerBase* runner, WasmFunctionCompiler* inner_compiler, + std::initializer_list<uint8_t> bytes_inner_function, + std::initializer_list<uint8_t> bytes_outer_function, + const T& expected_lambda) + : isolate_(runner->main_isolate()), expected_lambda_(expected_lambda), debug_info_(WasmInstanceObject::GetOrCreateDebugInfo( - runner.builder().instance_object())) { + runner->builder().instance_object())) { std::vector<uint8_t> inner_code{bytes_inner_function}; - inner_compiler.Build(inner_code.data(), - inner_code.data() + inner_code.size()); + inner_compiler->Build(inner_code.data(), + inner_code.data() + inner_code.size()); std::vector<uint8_t> outer_code{bytes_outer_function}; - runner.Build(outer_code.data(), outer_code.data() + outer_code.size()); + runner->Build(outer_code.data(), outer_code.data() + outer_code.size()); - int funcs_to_redict[] = {static_cast<int>(inner_compiler.function_index())}; - runner.builder().SetExecutable(); + int funcs_to_redict[] = { + static_cast<int>(inner_compiler->function_index())}; + runner->builder().SetExecutable(); WasmDebugInfo::RedirectToInterpreter(debug_info_, ArrayVector(funcs_to_redict)); - main_fun_wrapper_ = runner.builder().WrapCode(runner.function_index()); + main_fun_wrapper_ = runner->builder().WrapCode(runner->function_index()); } template <typename... Args> @@ -82,8 +81,7 @@ class ArgPassingHelper { template <typename T> static ArgPassingHelper<T> GetHelper( - WasmRunnerBase& runner, // NOLINT(runtime/references) - WasmFunctionCompiler& inner_compiler, // NOLINT(runtime/references) + WasmRunnerBase* runner, WasmFunctionCompiler* inner_compiler, std::initializer_list<uint8_t> bytes_inner_function, std::initializer_list<uint8_t> bytes_outer_function, const T& expected_lambda) { @@ -99,7 +97,7 @@ TEST(TestArgumentPassing_int32) { WasmFunctionCompiler& f2 = runner.NewFunction<int32_t, int32_t>(); auto helper = GetHelper( - runner, f2, + &runner, &f2, {// Return 2*<0> + 1. WASM_I32_ADD(WASM_I32_MUL(WASM_I32V_1(2), WASM_GET_LOCAL(0)), WASM_ONE)}, {// Call f2 with param <0>. @@ -117,7 +115,7 @@ TEST(TestArgumentPassing_double_int64) { WasmFunctionCompiler& f2 = runner.NewFunction<double, int64_t>(); auto helper = GetHelper( - runner, f2, + &runner, &f2, {// Return (double)<0>. WASM_F64_SCONVERT_I64(WASM_GET_LOCAL(0))}, {// Call f2 with param (<0> | (<1> << 32)). @@ -150,7 +148,7 @@ TEST(TestArgumentPassing_int64_double) { WasmFunctionCompiler& f2 = runner.NewFunction<int64_t, double>(); auto helper = GetHelper( - runner, f2, + &runner, &f2, {// Return (int64_t)<0>. WASM_I64_SCONVERT_F64(WASM_GET_LOCAL(0))}, {// Call f2 with param <0>, convert returned value back to double. @@ -169,7 +167,7 @@ TEST(TestArgumentPassing_float_double) { WasmFunctionCompiler& f2 = runner.NewFunction<double, float>(); auto helper = GetHelper( - runner, f2, + &runner, &f2, {// Return 2*(double)<0> + 1. WASM_F64_ADD( WASM_F64_MUL(WASM_F64(2), WASM_F64_CONVERT_F32(WASM_GET_LOCAL(0))), @@ -186,7 +184,7 @@ TEST(TestArgumentPassing_double_double) { WasmRunner<double, double, double> runner(ExecutionTier::kTurbofan); WasmFunctionCompiler& f2 = runner.NewFunction<double, double, double>(); - auto helper = GetHelper(runner, f2, + auto helper = GetHelper(&runner, &f2, {// Return <0> + <1>. WASM_F64_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))}, {// Call f2 with params <0>, <1>. @@ -208,7 +206,7 @@ TEST(TestArgumentPassing_AllTypes) { runner.NewFunction<double, int32_t, int64_t, float, double>(); auto helper = GetHelper( - runner, f2, + &runner, &f2, { // Convert all arguments to double, add them and return the sum. WASM_F64_ADD( // <0+1+2> + <3> diff --git a/deps/v8/test/cctest/wasm/test-wasm-serialization.cc b/deps/v8/test/cctest/wasm/test-wasm-serialization.cc index 1ff2a899ad..c6486650ef 100644 --- a/deps/v8/test/cctest/wasm/test-wasm-serialization.cc +++ b/deps/v8/test/cctest/wasm/test-wasm-serialization.cc @@ -11,7 +11,6 @@ #include "src/utils/version.h" #include "src/wasm/module-decoder.h" #include "src/wasm/wasm-engine.h" -#include "src/wasm/wasm-memory.h" #include "src/wasm/wasm-module-builder.h" #include "src/wasm/wasm-module.h" #include "src/wasm/wasm-objects-inl.h" @@ -272,9 +271,8 @@ TEST(BlockWasmCodeGenAtDeserialization) { Cleanup(); } -namespace { - -void TestTransferrableWasmModules(bool should_share) { +UNINITIALIZED_TEST(CompiledWasmModulesTransfer) { + FlagScope<bool> flag_scope_engine(&FLAG_wasm_shared_engine, true); i::wasm::WasmEngine::InitializeOncePerProcess(); v8::internal::AccountingAllocator allocator; Zone zone(&allocator, ZONE_NAME); @@ -285,7 +283,7 @@ void TestTransferrableWasmModules(bool should_share) { v8::Isolate::CreateParams create_params; create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); v8::Isolate* from_isolate = v8::Isolate::New(create_params); - std::vector<v8::WasmModuleObject::TransferrableModule> store; + std::vector<v8::CompiledWasmModule> store; std::shared_ptr<NativeModule> original_native_module; { v8::HandleScope scope(from_isolate); @@ -293,7 +291,7 @@ void TestTransferrableWasmModules(bool should_share) { Isolate* from_i_isolate = reinterpret_cast<Isolate*>(from_isolate); testing::SetupIsolateForWasmModule(from_i_isolate); - ErrorThrower thrower(from_i_isolate, "TestTransferrableWasmModules"); + ErrorThrower thrower(from_i_isolate, "TestCompiledWasmModulesTransfer"); auto enabled_features = WasmFeaturesFromIsolate(from_i_isolate); MaybeHandle<WasmModuleObject> maybe_module_object = from_i_isolate->wasm_engine()->SyncCompile( @@ -304,7 +302,7 @@ void TestTransferrableWasmModules(bool should_share) { v8::Local<v8::WasmModuleObject> v8_module = v8::Local<v8::WasmModuleObject>::Cast( v8::Utils::ToLocal(Handle<JSObject>::cast(module_object))); - store.push_back(v8_module->GetTransferrableModule()); + store.push_back(v8_module->GetCompiledModule()); original_native_module = module_object->shared_native_module(); } @@ -315,14 +313,13 @@ void TestTransferrableWasmModules(bool should_share) { LocalContext env(to_isolate); v8::MaybeLocal<v8::WasmModuleObject> transferred_module = - v8::WasmModuleObject::FromTransferrableModule(to_isolate, store[0]); + v8::WasmModuleObject::FromCompiledModule(to_isolate, store[0]); CHECK(!transferred_module.IsEmpty()); Handle<WasmModuleObject> module_object = Handle<WasmModuleObject>::cast( v8::Utils::OpenHandle(*transferred_module.ToLocalChecked())); std::shared_ptr<NativeModule> transferred_native_module = module_object->shared_native_module(); - bool is_sharing = (original_native_module == transferred_native_module); - CHECK_EQ(should_share, is_sharing); + CHECK_EQ(original_native_module, transferred_native_module); } to_isolate->Dispose(); } @@ -330,19 +327,6 @@ void TestTransferrableWasmModules(bool should_share) { from_isolate->Dispose(); } -} // namespace - -UNINITIALIZED_TEST(TransferrableWasmModulesCloned) { - FlagScope<bool> flag_scope_code(&FLAG_wasm_shared_code, false); - TestTransferrableWasmModules(false); -} - -UNINITIALIZED_TEST(TransferrableWasmModulesShared) { - FlagScope<bool> flag_scope_engine(&FLAG_wasm_shared_engine, true); - FlagScope<bool> flag_scope_code(&FLAG_wasm_shared_code, true); - TestTransferrableWasmModules(true); -} - #undef EMIT_CODE_WITH_END } // namespace test_wasm_serialization diff --git a/deps/v8/test/cctest/wasm/test-wasm-shared-engine.cc b/deps/v8/test/cctest/wasm/test-wasm-shared-engine.cc index b5bacf57d4..2d6e930397 100644 --- a/deps/v8/test/cctest/wasm/test-wasm-shared-engine.cc +++ b/deps/v8/test/cctest/wasm/test-wasm-shared-engine.cc @@ -27,7 +27,7 @@ namespace test_wasm_shared_engine { class SharedEngine { public: explicit SharedEngine(size_t max_committed = kMaxWasmCodeMemory) - : wasm_engine_(base::make_unique<WasmEngine>()) {} + : wasm_engine_(std::make_unique<WasmEngine>()) {} ~SharedEngine() { // Ensure no remaining uses exist. CHECK(wasm_engine_.unique()); @@ -112,19 +112,19 @@ class SharedEngineIsolate { class SharedEngineThread : public v8::base::Thread { public: SharedEngineThread(SharedEngine* engine, - std::function<void(SharedEngineIsolate&)> callback) + std::function<void(SharedEngineIsolate*)> callback) : Thread(Options("SharedEngineThread")), engine_(engine), callback_(callback) {} void Run() override { SharedEngineIsolate isolate(engine_); - callback_(isolate); + callback_(&isolate); } private: SharedEngine* engine_; - std::function<void(SharedEngineIsolate&)> callback_; + std::function<void(SharedEngineIsolate*)> callback_; }; namespace { @@ -159,43 +159,39 @@ class MockInstantiationResolver : public InstantiationResultResolver { class MockCompilationResolver : public CompilationResultResolver { public: - MockCompilationResolver( - SharedEngineIsolate& isolate, // NOLINT(runtime/references) - Handle<Object>* out_instance) + MockCompilationResolver(SharedEngineIsolate* isolate, + Handle<Object>* out_instance) : isolate_(isolate), out_instance_(out_instance) {} void OnCompilationSucceeded(Handle<WasmModuleObject> result) override { - isolate_.isolate()->wasm_engine()->AsyncInstantiate( - isolate_.isolate(), - base::make_unique<MockInstantiationResolver>(out_instance_), result, - {}); + isolate_->isolate()->wasm_engine()->AsyncInstantiate( + isolate_->isolate(), + std::make_unique<MockInstantiationResolver>(out_instance_), result, {}); } void OnCompilationFailed(Handle<Object> error_reason) override { UNREACHABLE(); } private: - SharedEngineIsolate& isolate_; + SharedEngineIsolate* isolate_; Handle<Object>* out_instance_; }; -void PumpMessageLoop( - SharedEngineIsolate& isolate) { // NOLINT(runtime/references) +void PumpMessageLoop(SharedEngineIsolate* isolate) { v8::platform::PumpMessageLoop(i::V8::GetCurrentPlatform(), - isolate.v8_isolate(), + isolate->v8_isolate(), platform::MessageLoopBehavior::kWaitForWork); - isolate.isolate()->default_microtask_queue()->RunMicrotasks( - isolate.isolate()); + isolate->isolate()->default_microtask_queue()->RunMicrotasks( + isolate->isolate()); } Handle<WasmInstanceObject> CompileAndInstantiateAsync( - SharedEngineIsolate& isolate, // NOLINT(runtime/references) - ZoneBuffer* buffer) { - Handle<Object> maybe_instance = handle(Smi::kZero, isolate.isolate()); - auto enabled_features = WasmFeaturesFromIsolate(isolate.isolate()); + SharedEngineIsolate* isolate, ZoneBuffer* buffer) { + Handle<Object> maybe_instance = handle(Smi::kZero, isolate->isolate()); + auto enabled_features = WasmFeaturesFromIsolate(isolate->isolate()); constexpr const char* kAPIMethodName = "Test.CompileAndInstantiateAsync"; - isolate.isolate()->wasm_engine()->AsyncCompile( - isolate.isolate(), enabled_features, - base::make_unique<MockCompilationResolver>(isolate, &maybe_instance), + isolate->isolate()->wasm_engine()->AsyncCompile( + isolate->isolate(), enabled_features, + std::make_unique<MockCompilationResolver>(isolate, &maybe_instance), ModuleWireBytes(buffer->begin(), buffer->end()), true, kAPIMethodName); while (!maybe_instance->IsWasmInstanceObject()) PumpMessageLoop(isolate); Handle<WasmInstanceObject> instance = @@ -261,17 +257,19 @@ TEST(SharedEngineRunImported) { TEST(SharedEngineRunThreadedBuildingSync) { SharedEngine engine; - SharedEngineThread thread1(&engine, [](SharedEngineIsolate& isolate) { - HandleScope scope(isolate.isolate()); - ZoneBuffer* buffer = BuildReturnConstantModule(isolate.zone(), 23); - Handle<WasmInstanceObject> instance = isolate.CompileAndInstantiate(buffer); - CHECK_EQ(23, isolate.Run(instance)); + SharedEngineThread thread1(&engine, [](SharedEngineIsolate* isolate) { + HandleScope scope(isolate->isolate()); + ZoneBuffer* buffer = BuildReturnConstantModule(isolate->zone(), 23); + Handle<WasmInstanceObject> instance = + isolate->CompileAndInstantiate(buffer); + CHECK_EQ(23, isolate->Run(instance)); }); - SharedEngineThread thread2(&engine, [](SharedEngineIsolate& isolate) { - HandleScope scope(isolate.isolate()); - ZoneBuffer* buffer = BuildReturnConstantModule(isolate.zone(), 42); - Handle<WasmInstanceObject> instance = isolate.CompileAndInstantiate(buffer); - CHECK_EQ(42, isolate.Run(instance)); + SharedEngineThread thread2(&engine, [](SharedEngineIsolate* isolate) { + HandleScope scope(isolate->isolate()); + ZoneBuffer* buffer = BuildReturnConstantModule(isolate->zone(), 42); + Handle<WasmInstanceObject> instance = + isolate->CompileAndInstantiate(buffer); + CHECK_EQ(42, isolate->Run(instance)); }); CHECK(thread1.Start()); CHECK(thread2.Start()); @@ -281,19 +279,19 @@ TEST(SharedEngineRunThreadedBuildingSync) { TEST(SharedEngineRunThreadedBuildingAsync) { SharedEngine engine; - SharedEngineThread thread1(&engine, [](SharedEngineIsolate& isolate) { - HandleScope scope(isolate.isolate()); - ZoneBuffer* buffer = BuildReturnConstantModule(isolate.zone(), 23); + SharedEngineThread thread1(&engine, [](SharedEngineIsolate* isolate) { + HandleScope scope(isolate->isolate()); + ZoneBuffer* buffer = BuildReturnConstantModule(isolate->zone(), 23); Handle<WasmInstanceObject> instance = CompileAndInstantiateAsync(isolate, buffer); - CHECK_EQ(23, isolate.Run(instance)); + CHECK_EQ(23, isolate->Run(instance)); }); - SharedEngineThread thread2(&engine, [](SharedEngineIsolate& isolate) { - HandleScope scope(isolate.isolate()); - ZoneBuffer* buffer = BuildReturnConstantModule(isolate.zone(), 42); + SharedEngineThread thread2(&engine, [](SharedEngineIsolate* isolate) { + HandleScope scope(isolate->isolate()); + ZoneBuffer* buffer = BuildReturnConstantModule(isolate->zone(), 42); Handle<WasmInstanceObject> instance = CompileAndInstantiateAsync(isolate, buffer); - CHECK_EQ(42, isolate.Run(instance)); + CHECK_EQ(42, isolate->Run(instance)); }); CHECK(thread1.Start()); CHECK(thread2.Start()); @@ -311,15 +309,15 @@ TEST(SharedEngineRunThreadedExecution) { Handle<WasmInstanceObject> instance = isolate.CompileAndInstantiate(buffer); module = isolate.ExportInstance(instance); } - SharedEngineThread thread1(&engine, [module](SharedEngineIsolate& isolate) { - HandleScope scope(isolate.isolate()); - Handle<WasmInstanceObject> instance = isolate.ImportInstance(module); - CHECK_EQ(23, isolate.Run(instance)); + SharedEngineThread thread1(&engine, [module](SharedEngineIsolate* isolate) { + HandleScope scope(isolate->isolate()); + Handle<WasmInstanceObject> instance = isolate->ImportInstance(module); + CHECK_EQ(23, isolate->Run(instance)); }); - SharedEngineThread thread2(&engine, [module](SharedEngineIsolate& isolate) { - HandleScope scope(isolate.isolate()); - Handle<WasmInstanceObject> instance = isolate.ImportInstance(module); - CHECK_EQ(23, isolate.Run(instance)); + SharedEngineThread thread2(&engine, [module](SharedEngineIsolate* isolate) { + HandleScope scope(isolate->isolate()); + Handle<WasmInstanceObject> instance = isolate->ImportInstance(module); + CHECK_EQ(23, isolate->Run(instance)); }); CHECK(thread1.Start()); CHECK(thread2.Start()); @@ -340,23 +338,23 @@ TEST(SharedEngineRunThreadedTierUp) { constexpr int kNumberOfThreads = 5; std::list<SharedEngineThread> threads; for (int i = 0; i < kNumberOfThreads; ++i) { - threads.emplace_back(&engine, [module](SharedEngineIsolate& isolate) { + threads.emplace_back(&engine, [module](SharedEngineIsolate* isolate) { constexpr int kNumberOfIterations = 100; - HandleScope scope(isolate.isolate()); - Handle<WasmInstanceObject> instance = isolate.ImportInstance(module); + HandleScope scope(isolate->isolate()); + Handle<WasmInstanceObject> instance = isolate->ImportInstance(module); for (int j = 0; j < kNumberOfIterations; ++j) { - CHECK_EQ(23, isolate.Run(instance)); + CHECK_EQ(23, isolate->Run(instance)); } }); } - threads.emplace_back(&engine, [module](SharedEngineIsolate& isolate) { - HandleScope scope(isolate.isolate()); - Handle<WasmInstanceObject> instance = isolate.ImportInstance(module); + threads.emplace_back(&engine, [module](SharedEngineIsolate* isolate) { + HandleScope scope(isolate->isolate()); + Handle<WasmInstanceObject> instance = isolate->ImportInstance(module); WasmFeatures detected = kNoWasmFeatures; WasmCompilationUnit::CompileWasmFunction( - isolate.isolate(), module.get(), &detected, + isolate->isolate(), module.get(), &detected, &module->module()->functions[0], ExecutionTier::kTurbofan); - CHECK_EQ(23, isolate.Run(instance)); + CHECK_EQ(23, isolate->Run(instance)); }); for (auto& thread : threads) CHECK(thread.Start()); for (auto& thread : threads) thread.Join(); diff --git a/deps/v8/test/cctest/wasm/wasm-run-utils.cc b/deps/v8/test/cctest/wasm/wasm-run-utils.cc index 528d71f53c..09d64e5d97 100644 --- a/deps/v8/test/cctest/wasm/wasm-run-utils.cc +++ b/deps/v8/test/cctest/wasm/wasm-run-utils.cc @@ -10,7 +10,6 @@ #include "src/wasm/graph-builder-interface.h" #include "src/wasm/module-compiler.h" #include "src/wasm/wasm-import-wrapper-cache.h" -#include "src/wasm/wasm-memory.h" #include "src/wasm/wasm-objects-inl.h" namespace v8 { @@ -75,29 +74,23 @@ byte* TestingModuleBuilder::AddMemory(uint32_t size, SharedFlag shared) { CHECK_NULL(mem_start_); CHECK_EQ(0, mem_size_); DCHECK(!instance_object_->has_memory_object()); - DCHECK_IMPLIES(test_module_->origin == kWasmOrigin, - size % kWasmPageSize == 0); + uint32_t initial_pages = RoundUp(size, kWasmPageSize) / kWasmPageSize; + uint32_t maximum_pages = (test_module_->maximum_pages != 0) + ? test_module_->maximum_pages + : initial_pages; test_module_->has_memory = true; - uint32_t max_size = - (test_module_->maximum_pages != 0) ? test_module_->maximum_pages : size; - uint32_t alloc_size = RoundUp(size, kWasmPageSize); - Handle<JSArrayBuffer> new_buffer; - if (shared == SharedFlag::kShared) { - CHECK(NewSharedArrayBuffer(isolate_, alloc_size, max_size) - .ToHandle(&new_buffer)); - } else { - CHECK(NewArrayBuffer(isolate_, alloc_size).ToHandle(&new_buffer)); - } - CHECK(!new_buffer.is_null()); - mem_start_ = reinterpret_cast<byte*>(new_buffer->backing_store()); - mem_size_ = size; - CHECK(size == 0 || mem_start_); - memset(mem_start_, 0, size); // Create the WasmMemoryObject. Handle<WasmMemoryObject> memory_object = - WasmMemoryObject::New(isolate_, new_buffer, max_size); + WasmMemoryObject::New(isolate_, initial_pages, maximum_pages, shared) + .ToHandleChecked(); instance_object_->set_memory_object(*memory_object); + + mem_start_ = + reinterpret_cast<byte*>(memory_object->array_buffer().backing_store()); + mem_size_ = size; + CHECK(size == 0 || mem_start_); + WasmMemoryObject::AddInstance(isolate_, memory_object, instance_object_); // TODO(wasm): Delete the following two lines when test-run-wasm will use a // multiple of kPageSize as memory size. At the moment, the effect of these @@ -328,7 +321,6 @@ Handle<WasmInstanceObject> TestingModuleBuilder::InitInstanceObject() { auto native_module = isolate_->wasm_engine()->NewNativeModule( isolate_, enabled_features_, test_module_); native_module->SetWireBytes(OwnedVector<const uint8_t>()); - native_module->SetRuntimeStubs(isolate_); Handle<WasmModuleObject> module_object = WasmModuleObject::New(isolate_, std::move(native_module), script); @@ -487,7 +479,7 @@ Handle<Code> WasmFunctionWrapper::GetWrapperCode() { CodeTracer::Scope tracing_scope(isolate->GetCodeTracer()); OFStream os(tracing_scope.file()); - code->Disassemble("wasm wrapper", os); + code->Disassemble("wasm wrapper", os, isolate); } #endif } |