2017-09-16 05:22:38 +00:00
|
|
|
// Copyright 2017 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 "test/unittests/test-utils.h"
|
|
|
|
#include "testing/gmock/include/gmock/gmock.h"
|
|
|
|
|
2018-04-24 13:10:51 +00:00
|
|
|
#include "src/wasm/function-compiler.h"
|
2018-06-19 09:47:17 +00:00
|
|
|
#include "src/wasm/jump-table-assembler.h"
|
2017-12-05 01:47:59 +00:00
|
|
|
#include "src/wasm/wasm-code-manager.h"
|
2018-10-25 13:29:13 +00:00
|
|
|
#include "src/wasm/wasm-engine.h"
|
Revert "Reland x5 [arraybuffer] Rearchitect backing store ownership"
This reverts commit 62e168308c08e0a4c93dce304f29090923a98fee.
Reason for revert: it will be relanded after branch
Original change's description:
> Reland x5 [arraybuffer] Rearchitect backing store ownership
>
> This reverts commit 8fdb23873bd15a6ac61288c627c070616af84ced.
>
> Original change's description:
> > "Reland x4 [arraybuffer] Rearchitect backing store ownership"
> >
> > This is a reland of bc33f5aeba9ceb13f8bfc401c5ba2521c2207ffb
> >
> > Contributed by titzer@chromium.org
> >
> > Original change's description:
> > > [arraybuffer] Rearchitect backing store ownership
> > >
> > > This CL completely rearchitects the ownership of array buffer backing stores,
> > > consolidating ownership into a {BackingStore} C++ object that is tracked
> > > throughout V8 using unique_ptr and shared_ptr where appropriate.
> > >
> > > Overall, lifetime management is simpler and more explicit. The numerous
> > > ways that array buffers were initialized have been streamlined to one
> > > Attach() method on JSArrayBuffer. The array buffer tracker in the
> > > GC implementation now manages std::shared_ptr<BackingStore> pointers,
> > > and the construction and destruction of the BackingStore object itself
> > > handles the underlying page or embedder-allocated memory.
> > >
> > > The embedder API remains unchanged for now. We use the
> > > v8::ArrayBuffer::Contents struct to hide an additional shared_ptr to
> > > keep the backing store alive properly, even in the case of aliases
> > > from live heap objects. Thus the embedder has a lower chance of making
> > > a mistake. Long-term, we should move the embedder to a model where they
> > > manage backing stores using shared_ptr to an opaque backing store object.
> >
> > TBR=yangguo@chromium.org
> >
> > BUG=v8:9380,v8:9221,chromium:986318
> >
> > Change-Id: If671a4a9ca0476e8f084efae46e0d2bf99ed99ef
> > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1731005
> > Commit-Queue: Ulan Degenbaev <ulan@chromium.org>
> > Reviewed-by: Clemens Hammacher <clemensh@chromium.org>
> > Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
> > Cr-Commit-Position: refs/heads/master@{#63041}
>
> TBR=yangguo@chromium.org,clemensh@chromium.org,mstarzinger@chromium.org
>
> Change-Id: Iba55c7ab71e5642b5cb6aeb699d6fc9cf9061486
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1771795
> Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> Commit-Queue: Ulan Degenbaev <ulan@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#63461}
TBR=ulan@chromium.org,mlippautz@chromium.org
Change-Id: Id8f67a68ab398032eb2975b1b24ee125394d9c4b
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1776095
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Commit-Queue: Ulan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63471}
2019-08-30 08:23:26 +00:00
|
|
|
#include "src/wasm/wasm-memory.h"
|
2017-09-16 05:22:38 +00:00
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
namespace wasm {
|
2017-09-28 17:55:52 +00:00
|
|
|
namespace wasm_heap_unittest {
|
2017-09-16 05:22:38 +00:00
|
|
|
|
2017-09-28 17:55:52 +00:00
|
|
|
class DisjointAllocationPoolTest : public ::testing::Test {
|
2017-09-16 05:22:38 +00:00
|
|
|
public:
|
2018-09-24 13:25:40 +00:00
|
|
|
void CheckPool(const DisjointAllocationPool& mem,
|
2018-09-25 14:21:11 +00:00
|
|
|
std::initializer_list<base::AddressRegion> expected_regions);
|
|
|
|
void CheckRange(base::AddressRegion region1, base::AddressRegion region2);
|
|
|
|
DisjointAllocationPool Make(
|
|
|
|
std::initializer_list<base::AddressRegion> regions);
|
2017-09-16 05:22:38 +00:00
|
|
|
};
|
|
|
|
|
2018-09-24 13:25:40 +00:00
|
|
|
void DisjointAllocationPoolTest::CheckPool(
|
2017-09-16 05:22:38 +00:00
|
|
|
const DisjointAllocationPool& mem,
|
2018-09-25 14:21:11 +00:00
|
|
|
std::initializer_list<base::AddressRegion> expected_regions) {
|
|
|
|
const auto& regions = mem.regions();
|
|
|
|
CHECK_EQ(regions.size(), expected_regions.size());
|
|
|
|
auto iter = expected_regions.begin();
|
|
|
|
for (auto it = regions.begin(), e = regions.end(); it != e; ++it, ++iter) {
|
2018-09-24 13:25:40 +00:00
|
|
|
CHECK_EQ(*it, *iter);
|
2017-09-16 05:22:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-25 14:21:11 +00:00
|
|
|
void DisjointAllocationPoolTest::CheckRange(base::AddressRegion region1,
|
|
|
|
base::AddressRegion region2) {
|
|
|
|
CHECK_EQ(region1, region2);
|
2018-06-08 11:05:58 +00:00
|
|
|
}
|
|
|
|
|
2017-09-16 05:22:38 +00:00
|
|
|
DisjointAllocationPool DisjointAllocationPoolTest::Make(
|
2018-09-25 14:21:11 +00:00
|
|
|
std::initializer_list<base::AddressRegion> regions) {
|
2017-09-16 05:22:38 +00:00
|
|
|
DisjointAllocationPool ret;
|
2018-09-25 14:21:11 +00:00
|
|
|
for (auto& region : regions) {
|
|
|
|
ret.Merge(region);
|
2017-09-16 05:22:38 +00:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-06-08 11:05:58 +00:00
|
|
|
TEST_F(DisjointAllocationPoolTest, ConstructEmpty) {
|
2017-09-16 05:22:38 +00:00
|
|
|
DisjointAllocationPool a;
|
|
|
|
CHECK(a.IsEmpty());
|
2018-09-24 13:25:40 +00:00
|
|
|
CheckPool(a, {});
|
2018-09-25 14:21:11 +00:00
|
|
|
a.Merge({1, 4});
|
|
|
|
CheckPool(a, {{1, 4}});
|
2018-06-08 11:05:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DisjointAllocationPoolTest, ConstructWithRange) {
|
2018-09-25 14:21:11 +00:00
|
|
|
DisjointAllocationPool a({1, 4});
|
2018-06-08 11:05:58 +00:00
|
|
|
CHECK(!a.IsEmpty());
|
2018-09-25 14:21:11 +00:00
|
|
|
CheckPool(a, {{1, 4}});
|
2017-09-16 05:22:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DisjointAllocationPoolTest, SimpleExtract) {
|
2018-09-25 14:21:11 +00:00
|
|
|
DisjointAllocationPool a = Make({{1, 4}});
|
|
|
|
base::AddressRegion b = a.Allocate(2);
|
|
|
|
CheckPool(a, {{3, 2}});
|
|
|
|
CheckRange(b, {1, 2});
|
2018-06-08 11:05:58 +00:00
|
|
|
a.Merge(b);
|
2018-09-25 14:21:11 +00:00
|
|
|
CheckPool(a, {{1, 4}});
|
|
|
|
CHECK_EQ(a.regions().size(), 1);
|
|
|
|
CHECK_EQ(a.regions().front().begin(), 1);
|
|
|
|
CHECK_EQ(a.regions().front().end(), 5);
|
2017-09-16 05:22:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DisjointAllocationPoolTest, ExtractAll) {
|
2018-09-25 14:21:11 +00:00
|
|
|
DisjointAllocationPool a({1, 4});
|
|
|
|
base::AddressRegion b = a.Allocate(4);
|
|
|
|
CheckRange(b, {1, 4});
|
2017-09-16 05:22:38 +00:00
|
|
|
CHECK(a.IsEmpty());
|
2018-06-08 11:05:58 +00:00
|
|
|
a.Merge(b);
|
2018-09-25 14:21:11 +00:00
|
|
|
CheckPool(a, {{1, 4}});
|
2017-09-16 05:22:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DisjointAllocationPoolTest, FailToExtract) {
|
2018-09-25 14:21:11 +00:00
|
|
|
DisjointAllocationPool a = Make({{1, 4}});
|
|
|
|
base::AddressRegion b = a.Allocate(5);
|
|
|
|
CheckPool(a, {{1, 4}});
|
2018-06-08 11:05:58 +00:00
|
|
|
CHECK(b.is_empty());
|
2017-09-16 05:22:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DisjointAllocationPoolTest, FailToExtractExact) {
|
2018-09-25 14:21:11 +00:00
|
|
|
DisjointAllocationPool a = Make({{1, 4}, {10, 4}});
|
|
|
|
base::AddressRegion b = a.Allocate(5);
|
|
|
|
CheckPool(a, {{1, 4}, {10, 4}});
|
2018-06-08 11:05:58 +00:00
|
|
|
CHECK(b.is_empty());
|
2017-09-16 05:22:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DisjointAllocationPoolTest, ExtractExact) {
|
2018-09-25 14:21:11 +00:00
|
|
|
DisjointAllocationPool a = Make({{1, 4}, {10, 5}});
|
|
|
|
base::AddressRegion b = a.Allocate(5);
|
|
|
|
CheckPool(a, {{1, 4}});
|
|
|
|
CheckRange(b, {10, 5});
|
2017-09-16 05:22:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DisjointAllocationPoolTest, Merging) {
|
2018-09-25 14:21:11 +00:00
|
|
|
DisjointAllocationPool a = Make({{10, 5}, {20, 5}});
|
|
|
|
a.Merge({15, 5});
|
|
|
|
CheckPool(a, {{10, 15}});
|
2017-09-16 05:22:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DisjointAllocationPoolTest, MergingMore) {
|
2018-09-25 14:21:11 +00:00
|
|
|
DisjointAllocationPool a = Make({{10, 5}, {20, 5}, {30, 5}});
|
|
|
|
a.Merge({15, 5});
|
|
|
|
a.Merge({25, 5});
|
|
|
|
CheckPool(a, {{10, 25}});
|
2017-09-16 05:22:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DisjointAllocationPoolTest, MergingSkip) {
|
2018-09-25 14:21:11 +00:00
|
|
|
DisjointAllocationPool a = Make({{10, 5}, {20, 5}, {30, 5}});
|
|
|
|
a.Merge({25, 5});
|
|
|
|
CheckPool(a, {{10, 5}, {20, 15}});
|
2017-09-16 05:22:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DisjointAllocationPoolTest, MergingSkipLargerSrc) {
|
2018-09-25 14:21:11 +00:00
|
|
|
DisjointAllocationPool a = Make({{10, 5}, {20, 5}, {30, 5}});
|
|
|
|
a.Merge({25, 5});
|
|
|
|
a.Merge({35, 5});
|
|
|
|
CheckPool(a, {{10, 5}, {20, 20}});
|
2017-09-16 05:22:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DisjointAllocationPoolTest, MergingSkipLargerSrcWithGap) {
|
2018-09-25 14:21:11 +00:00
|
|
|
DisjointAllocationPool a = Make({{10, 5}, {20, 5}, {30, 5}});
|
|
|
|
a.Merge({25, 5});
|
|
|
|
a.Merge({36, 4});
|
|
|
|
CheckPool(a, {{10, 5}, {20, 15}, {36, 4}});
|
2017-09-16 05:22:38 +00:00
|
|
|
}
|
|
|
|
|
2018-03-19 12:34:59 +00:00
|
|
|
enum ModuleStyle : int { Fixed = 0, Growable = 1 };
|
|
|
|
|
2018-06-20 11:19:45 +00:00
|
|
|
std::string PrintWasmCodeManageTestParam(
|
|
|
|
::testing::TestParamInfo<ModuleStyle> info) {
|
|
|
|
switch (info.param) {
|
|
|
|
case Fixed:
|
|
|
|
return "Fixed";
|
|
|
|
case Growable:
|
|
|
|
return "Growable";
|
|
|
|
}
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
2018-03-19 12:34:59 +00:00
|
|
|
class WasmCodeManagerTest : public TestWithContext,
|
|
|
|
public ::testing::WithParamInterface<ModuleStyle> {
|
2017-11-20 21:34:04 +00:00
|
|
|
public:
|
2018-06-19 09:47:17 +00:00
|
|
|
static constexpr uint32_t kNumFunctions = 10;
|
2019-05-13 13:22:31 +00:00
|
|
|
static size_t allocate_page_size;
|
|
|
|
static size_t commit_page_size;
|
2019-04-09 11:28:47 +00:00
|
|
|
|
|
|
|
WasmCodeManagerTest() {
|
2019-05-13 13:22:31 +00:00
|
|
|
CHECK_EQ(allocate_page_size == 0, commit_page_size == 0);
|
|
|
|
if (allocate_page_size == 0) {
|
|
|
|
allocate_page_size = AllocatePageSize();
|
|
|
|
commit_page_size = CommitPageSize();
|
|
|
|
}
|
|
|
|
CHECK_NE(0, allocate_page_size);
|
|
|
|
CHECK_NE(0, commit_page_size);
|
2019-08-01 09:08:07 +00:00
|
|
|
manager()->DisableImplicitAllocationsForTesting();
|
2019-04-09 11:28:47 +00:00
|
|
|
}
|
2018-06-19 09:47:17 +00:00
|
|
|
|
2019-03-12 16:10:58 +00:00
|
|
|
using NativeModulePtr = std::shared_ptr<NativeModule>;
|
2017-11-20 21:34:04 +00:00
|
|
|
|
2018-10-25 13:29:13 +00:00
|
|
|
NativeModulePtr AllocModule(size_t size, ModuleStyle style) {
|
2018-06-28 13:23:24 +00:00
|
|
|
std::shared_ptr<WasmModule> module(new WasmModule);
|
|
|
|
module->num_declared_functions = kNumFunctions;
|
2018-06-12 16:43:02 +00:00
|
|
|
bool can_request_more = style == Growable;
|
2019-01-25 10:35:37 +00:00
|
|
|
return engine()->NewNativeModule(i_isolate(), kAllWasmFeatures, size,
|
|
|
|
can_request_more, std::move(module));
|
2017-11-20 21:34:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
WasmCode* AddCode(NativeModule* native_module, uint32_t index, size_t size) {
|
|
|
|
CodeDesc desc;
|
|
|
|
memset(reinterpret_cast<void*>(&desc), 0, sizeof(CodeDesc));
|
|
|
|
std::unique_ptr<byte[]> exec_buff(new byte[size]);
|
|
|
|
desc.buffer = exec_buff.get();
|
|
|
|
desc.instr_size = static_cast<int>(size);
|
[wasm] Split adding code from publishing it
This prepares a refactoring to add and publish compilation results in
batches. For this, we need to separate the two phases, so that we can
lock the module, allocate all the code space, release the lock, copy
the code, lock the module, publish the code, and release the lock
again.
In particular, this CL does the following:
1) It removes the {AddOwnedCode} method. The functionality of creating
the {WasmCode} and memcpy'ing the instruction into that is done in
the other {Add*Code} methods. Adding to {owned_code_} is done in
{PublishCode}.
2) {PublishInterpreterEntry} is now functionally equivalent to
{PublishCode}, so it's removed.
3) After {AddCode}, the caller has to call {PublishCode}. In a
follow-up CL, this will be called in batches (first {AddCode} them
all, then {PublishCode} them all).
4) {AddCompiledCode} now assumes that the {WasmCompilationResult}
succeeded. Otherwise, the caller should directly call {SetError} on
the {CompilationState}.
5) {PublishCode} is now the chokepoint for installing code to the code
table, the owned code vector, the jump table, and setting interpreter
redirections. It replaces previous direct calls to {InstallCode} or
explicitly adding to {owned_code_}.
6) Increasing the {generated_code_size_} counter is now done in
{AllocateForCode}, which is the chokepoint for allocating space for
generated code. This way, we will only increase this counter once
once we allocate in batches.
R=titzer@chromium.org
Bug: v8:8916
Change-Id: I71e02e3a838f21797915cee3ebd373804fb12237
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1530817
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: Ben Titzer <titzer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60369}
2019-03-20 13:04:33 +00:00
|
|
|
std::unique_ptr<WasmCode> code = native_module->AddCode(
|
2019-04-03 15:37:47 +00:00
|
|
|
index, desc, 0, 0, {}, {}, WasmCode::kFunction, ExecutionTier::kNone);
|
2019-04-05 10:36:06 +00:00
|
|
|
return native_module->PublishCode(std::move(code));
|
2017-11-20 21:34:04 +00:00
|
|
|
}
|
|
|
|
|
2019-01-25 10:35:37 +00:00
|
|
|
WasmEngine* engine() { return i_isolate()->wasm_engine(); }
|
|
|
|
|
|
|
|
WasmCodeManager* manager() { return engine()->code_manager(); }
|
2018-09-18 13:05:45 +00:00
|
|
|
|
2018-10-25 13:29:13 +00:00
|
|
|
void SetMaxCommittedMemory(size_t limit) {
|
|
|
|
manager()->SetMaxCommittedMemoryForTesting(limit);
|
|
|
|
}
|
2017-11-20 21:34:04 +00:00
|
|
|
};
|
|
|
|
|
2019-04-09 11:28:47 +00:00
|
|
|
// static
|
2019-05-13 13:22:31 +00:00
|
|
|
size_t WasmCodeManagerTest::allocate_page_size = 0;
|
|
|
|
size_t WasmCodeManagerTest::commit_page_size = 0;
|
2019-04-09 11:28:47 +00:00
|
|
|
|
2019-02-15 16:53:29 +00:00
|
|
|
INSTANTIATE_TEST_SUITE_P(Parameterized, WasmCodeManagerTest,
|
|
|
|
::testing::Values(Fixed, Growable),
|
|
|
|
PrintWasmCodeManageTestParam);
|
2018-03-19 12:34:59 +00:00
|
|
|
|
|
|
|
TEST_P(WasmCodeManagerTest, EmptyCase) {
|
2019-04-09 11:28:47 +00:00
|
|
|
SetMaxCommittedMemory(0);
|
|
|
|
CHECK_EQ(0, manager()->committed_code_space());
|
2018-03-19 12:34:59 +00:00
|
|
|
|
2019-08-01 09:08:07 +00:00
|
|
|
NativeModulePtr native_module = AllocModule(allocate_page_size, GetParam());
|
|
|
|
ASSERT_DEATH_IF_SUPPORTED(AddCode(native_module.get(), 0, kCodeAlignment),
|
2019-05-13 12:27:48 +00:00
|
|
|
"OOM in wasm code commit");
|
2017-11-20 21:34:04 +00:00
|
|
|
}
|
|
|
|
|
2018-03-19 12:34:59 +00:00
|
|
|
TEST_P(WasmCodeManagerTest, AllocateAndGoOverLimit) {
|
2019-05-13 13:22:31 +00:00
|
|
|
SetMaxCommittedMemory(allocate_page_size);
|
2019-04-24 22:01:00 +00:00
|
|
|
|
2019-04-09 11:28:47 +00:00
|
|
|
CHECK_EQ(0, manager()->committed_code_space());
|
2019-05-13 13:22:31 +00:00
|
|
|
NativeModulePtr native_module = AllocModule(allocate_page_size, GetParam());
|
2018-03-19 12:34:59 +00:00
|
|
|
CHECK(native_module);
|
2019-08-01 09:08:07 +00:00
|
|
|
CHECK_EQ(0, manager()->committed_code_space());
|
2019-04-02 10:41:00 +00:00
|
|
|
WasmCodeRefScope code_ref_scope;
|
2018-03-19 12:34:59 +00:00
|
|
|
uint32_t index = 0;
|
|
|
|
WasmCode* code = AddCode(native_module.get(), index++, 1 * kCodeAlignment);
|
|
|
|
CHECK_NOT_NULL(code);
|
2019-05-13 13:22:31 +00:00
|
|
|
CHECK_EQ(commit_page_size, manager()->committed_code_space());
|
2018-03-19 12:34:59 +00:00
|
|
|
|
|
|
|
code = AddCode(native_module.get(), index++, 3 * kCodeAlignment);
|
|
|
|
CHECK_NOT_NULL(code);
|
2019-05-13 13:22:31 +00:00
|
|
|
CHECK_EQ(commit_page_size, manager()->committed_code_space());
|
2018-03-19 12:34:59 +00:00
|
|
|
|
2018-06-19 09:47:17 +00:00
|
|
|
code = AddCode(native_module.get(), index++,
|
2019-08-01 09:08:07 +00:00
|
|
|
allocate_page_size - 4 * kCodeAlignment);
|
2018-03-19 12:34:59 +00:00
|
|
|
CHECK_NOT_NULL(code);
|
2019-05-13 13:22:31 +00:00
|
|
|
CHECK_EQ(allocate_page_size, manager()->committed_code_space());
|
2018-03-19 12:34:59 +00:00
|
|
|
|
2018-09-27 09:20:06 +00:00
|
|
|
// This fails in "reservation" if we cannot extend the code space, or in
|
|
|
|
// "commit" it we can (since we hit the allocation limit in the
|
|
|
|
// WasmCodeManager). Hence don't check for that part of the OOM message.
|
2018-03-19 12:34:59 +00:00
|
|
|
ASSERT_DEATH_IF_SUPPORTED(
|
|
|
|
AddCode(native_module.get(), index++, 1 * kCodeAlignment),
|
2019-05-13 12:27:48 +00:00
|
|
|
"OOM in wasm code");
|
2017-11-20 21:34:04 +00:00
|
|
|
}
|
|
|
|
|
2018-03-19 12:34:59 +00:00
|
|
|
TEST_P(WasmCodeManagerTest, TotalLimitIrrespectiveOfModuleCount) {
|
2019-05-13 13:22:31 +00:00
|
|
|
SetMaxCommittedMemory(3 * allocate_page_size);
|
2019-04-24 22:01:00 +00:00
|
|
|
|
2019-05-13 13:22:31 +00:00
|
|
|
NativeModulePtr nm1 = AllocModule(2 * allocate_page_size, GetParam());
|
|
|
|
NativeModulePtr nm2 = AllocModule(2 * allocate_page_size, GetParam());
|
2018-03-19 12:34:59 +00:00
|
|
|
CHECK(nm1);
|
|
|
|
CHECK(nm2);
|
2019-04-02 10:41:00 +00:00
|
|
|
WasmCodeRefScope code_ref_scope;
|
2019-08-01 09:08:07 +00:00
|
|
|
WasmCode* code = AddCode(nm1.get(), 0, 2 * allocate_page_size);
|
2018-03-19 12:34:59 +00:00
|
|
|
CHECK_NOT_NULL(code);
|
2019-08-01 09:08:07 +00:00
|
|
|
ASSERT_DEATH_IF_SUPPORTED(AddCode(nm2.get(), 0, 2 * allocate_page_size),
|
|
|
|
"OOM in wasm code commit");
|
2017-11-20 21:34:04 +00:00
|
|
|
}
|
|
|
|
|
2018-03-19 12:34:59 +00:00
|
|
|
TEST_P(WasmCodeManagerTest, GrowingVsFixedModule) {
|
2019-05-13 13:22:31 +00:00
|
|
|
SetMaxCommittedMemory(3 * allocate_page_size);
|
2019-04-24 22:01:00 +00:00
|
|
|
|
2019-05-13 13:22:31 +00:00
|
|
|
NativeModulePtr nm = AllocModule(allocate_page_size, GetParam());
|
|
|
|
size_t module_size =
|
|
|
|
GetParam() == Fixed ? kMaxWasmCodeMemory : allocate_page_size;
|
2019-08-01 09:08:07 +00:00
|
|
|
size_t remaining_space_in_module = module_size;
|
2018-03-19 12:34:59 +00:00
|
|
|
if (GetParam() == Fixed) {
|
2018-06-20 11:19:45 +00:00
|
|
|
// Requesting more than the remaining space fails because the module cannot
|
|
|
|
// grow.
|
|
|
|
ASSERT_DEATH_IF_SUPPORTED(
|
|
|
|
AddCode(nm.get(), 0, remaining_space_in_module + kCodeAlignment),
|
2019-05-13 12:27:48 +00:00
|
|
|
"OOM in wasm code reservation");
|
2018-03-19 12:34:59 +00:00
|
|
|
} else {
|
2018-06-20 11:19:45 +00:00
|
|
|
// The module grows by one page. One page remains uncommitted.
|
2019-04-02 10:41:00 +00:00
|
|
|
WasmCodeRefScope code_ref_scope;
|
2018-06-20 11:19:45 +00:00
|
|
|
CHECK_NOT_NULL(
|
|
|
|
AddCode(nm.get(), 0, remaining_space_in_module + kCodeAlignment));
|
2019-05-13 13:22:31 +00:00
|
|
|
CHECK_EQ(commit_page_size + allocate_page_size,
|
|
|
|
manager()->committed_code_space());
|
2017-11-20 21:34:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-19 12:34:59 +00:00
|
|
|
TEST_P(WasmCodeManagerTest, CommitIncrements) {
|
2019-05-13 13:22:31 +00:00
|
|
|
SetMaxCommittedMemory(10 * allocate_page_size);
|
2019-04-24 22:01:00 +00:00
|
|
|
|
2019-05-13 13:22:31 +00:00
|
|
|
NativeModulePtr nm = AllocModule(3 * allocate_page_size, GetParam());
|
2019-04-02 10:41:00 +00:00
|
|
|
WasmCodeRefScope code_ref_scope;
|
2018-03-19 12:34:59 +00:00
|
|
|
WasmCode* code = AddCode(nm.get(), 0, kCodeAlignment);
|
|
|
|
CHECK_NOT_NULL(code);
|
2019-05-13 13:22:31 +00:00
|
|
|
CHECK_EQ(commit_page_size, manager()->committed_code_space());
|
|
|
|
code = AddCode(nm.get(), 1, 2 * allocate_page_size);
|
2018-03-19 12:34:59 +00:00
|
|
|
CHECK_NOT_NULL(code);
|
2019-05-13 13:22:31 +00:00
|
|
|
CHECK_EQ(commit_page_size + 2 * allocate_page_size,
|
|
|
|
manager()->committed_code_space());
|
2019-08-01 09:08:07 +00:00
|
|
|
code = AddCode(nm.get(), 2, allocate_page_size - kCodeAlignment);
|
2018-03-19 12:34:59 +00:00
|
|
|
CHECK_NOT_NULL(code);
|
2019-05-13 13:22:31 +00:00
|
|
|
CHECK_EQ(3 * allocate_page_size, manager()->committed_code_space());
|
2017-11-20 21:34:04 +00:00
|
|
|
}
|
|
|
|
|
2018-03-19 12:34:59 +00:00
|
|
|
TEST_P(WasmCodeManagerTest, Lookup) {
|
2019-05-13 13:22:31 +00:00
|
|
|
SetMaxCommittedMemory(2 * allocate_page_size);
|
2018-03-19 12:34:59 +00:00
|
|
|
|
2019-05-13 13:22:31 +00:00
|
|
|
NativeModulePtr nm1 = AllocModule(allocate_page_size, GetParam());
|
|
|
|
NativeModulePtr nm2 = AllocModule(allocate_page_size, GetParam());
|
2019-04-02 10:41:00 +00:00
|
|
|
Address mid_code1_1;
|
|
|
|
{
|
|
|
|
// The {WasmCodeRefScope} needs to die before {nm1} dies.
|
|
|
|
WasmCodeRefScope code_ref_scope;
|
|
|
|
WasmCode* code1_0 = AddCode(nm1.get(), 0, kCodeAlignment);
|
|
|
|
CHECK_EQ(nm1.get(), code1_0->native_module());
|
|
|
|
WasmCode* code1_1 = AddCode(nm1.get(), 1, kCodeAlignment);
|
|
|
|
WasmCode* code2_0 = AddCode(nm2.get(), 0, kCodeAlignment);
|
|
|
|
WasmCode* code2_1 = AddCode(nm2.get(), 1, kCodeAlignment);
|
|
|
|
CHECK_EQ(nm2.get(), code2_1->native_module());
|
|
|
|
|
|
|
|
CHECK_EQ(0, code1_0->index());
|
|
|
|
CHECK_EQ(1, code1_1->index());
|
|
|
|
CHECK_EQ(0, code2_0->index());
|
|
|
|
CHECK_EQ(1, code2_1->index());
|
|
|
|
|
|
|
|
// we know the manager object is allocated here, so we shouldn't
|
|
|
|
// find any WasmCode* associated with that ptr.
|
|
|
|
WasmCode* not_found =
|
|
|
|
manager()->LookupCode(reinterpret_cast<Address>(manager()));
|
|
|
|
CHECK_NULL(not_found);
|
|
|
|
WasmCode* found = manager()->LookupCode(code1_0->instruction_start());
|
|
|
|
CHECK_EQ(found, code1_0);
|
|
|
|
found = manager()->LookupCode(code2_1->instruction_start() +
|
|
|
|
(code2_1->instructions().size() / 2));
|
|
|
|
CHECK_EQ(found, code2_1);
|
|
|
|
found = manager()->LookupCode(code2_1->instruction_start() +
|
|
|
|
code2_1->instructions().size() - 1);
|
|
|
|
CHECK_EQ(found, code2_1);
|
|
|
|
found = manager()->LookupCode(code2_1->instruction_start() +
|
|
|
|
code2_1->instructions().size());
|
|
|
|
CHECK_NULL(found);
|
|
|
|
mid_code1_1 =
|
|
|
|
code1_1->instruction_start() + (code1_1->instructions().size() / 2);
|
|
|
|
CHECK_EQ(code1_1, manager()->LookupCode(mid_code1_1));
|
|
|
|
}
|
2018-03-19 12:34:59 +00:00
|
|
|
nm1.reset();
|
2018-10-25 13:29:13 +00:00
|
|
|
CHECK_NULL(manager()->LookupCode(mid_code1_1));
|
2017-11-20 21:34:04 +00:00
|
|
|
}
|
|
|
|
|
2018-03-19 12:34:59 +00:00
|
|
|
TEST_P(WasmCodeManagerTest, LookupWorksAfterRewrite) {
|
2019-05-13 13:22:31 +00:00
|
|
|
SetMaxCommittedMemory(2 * allocate_page_size);
|
2018-03-19 12:34:59 +00:00
|
|
|
|
2019-05-13 13:22:31 +00:00
|
|
|
NativeModulePtr nm1 = AllocModule(allocate_page_size, GetParam());
|
2018-03-19 12:34:59 +00:00
|
|
|
|
2019-04-02 10:41:00 +00:00
|
|
|
WasmCodeRefScope code_ref_scope;
|
2018-03-19 12:34:59 +00:00
|
|
|
WasmCode* code0 = AddCode(nm1.get(), 0, kCodeAlignment);
|
|
|
|
WasmCode* code1 = AddCode(nm1.get(), 1, kCodeAlignment);
|
|
|
|
CHECK_EQ(0, code0->index());
|
|
|
|
CHECK_EQ(1, code1->index());
|
2018-10-25 13:29:13 +00:00
|
|
|
CHECK_EQ(code1, manager()->LookupCode(code1->instruction_start()));
|
2018-03-19 12:34:59 +00:00
|
|
|
WasmCode* code1_1 = AddCode(nm1.get(), 1, kCodeAlignment);
|
|
|
|
CHECK_EQ(1, code1_1->index());
|
2018-10-25 13:29:13 +00:00
|
|
|
CHECK_EQ(code1, manager()->LookupCode(code1->instruction_start()));
|
|
|
|
CHECK_EQ(code1_1, manager()->LookupCode(code1_1->instruction_start()));
|
2017-11-20 21:34:04 +00:00
|
|
|
}
|
|
|
|
|
2017-09-28 17:55:52 +00:00
|
|
|
} // namespace wasm_heap_unittest
|
2017-09-16 05:22:38 +00:00
|
|
|
} // namespace wasm
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|