2019-09-09 10:19:34 +00:00
|
|
|
// 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);
|
|
|
|
|
2020-07-09 11:51:58 +00:00
|
|
|
WasmModuleBuilder* builder = zone.New<WasmModuleBuilder>(&zone);
|
2019-09-09 10:19:34 +00:00
|
|
|
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));
|
|
|
|
|
2020-03-30 16:15:05 +00:00
|
|
|
// Grow using an internal Wasm bytecode.
|
2019-09-09 10:19:34 +00:00
|
|
|
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
|