v8/test/unittests/wasm/wasm-heap-unittest.cc
Mircea Trofin 3d046986f0 Revert "Revert "[wasm] A simple allocator datastructure for off-the heap""
This reverts commit ee5c31f335.

Reason for revert: Fixed compiler failure

Original change's description:
> Revert "[wasm] A simple allocator datastructure for off-the heap"
> 
> This reverts commit 110d9ab005.
> 
> Reason for revert: https://build.chromium.org/p/client.v8/builders/V8%20Linux64%20-%20debug%20builder/builds/26607
> 
> Surprising we're seeing a failure on Linux 64 *after* CQ. Is the compiler there different?
> 
> Original change's description:
> > [wasm] A simple allocator datastructure for off-the heap
> > 
> > We'll use this allocator in a follow-up CL to:
> > - allocate speculative sizes of memory for a module that's being
> > compiled (e.g. 2*size of wasm code).
> > - each module will own such a sub-pool, and then use it to allocate
> > contiguous chunks of memory for code.
> > 
> > The underlying assumptions for the chosen allocation strategy is that:
> > - the allocation granularity for pools is 1 page, so that no one page
> > is owned by more than one wasm module
> > - typical pool sizes (given module sizes) are multiple pages.
> > - modules and module instances are typically few and long lived. Typically,
> > we expect one module and one instance. 
> > 
> > This means we shouldn't expect fragmentations that lead to code being
> > non-allocatable, or prohibitively many ranges.
> > 
> > The data structure just manages ranges of addresses. Virtual memory management
> > will be separate, as part of the responsibility of a "WasmHeap"
> > that will be introduced in the future. So will concurrency control.
> > 
> > Bug: 
> > Change-Id: Id99f46d10c25553b013054d994760f3c2a737c39
> > Reviewed-on: https://chromium-review.googlesource.com/669296
> > Commit-Queue: Mircea Trofin <mtrofin@chromium.org>
> > Reviewed-by: Eric Holk <eholk@chromium.org>
> > Reviewed-by: Brad Nelson <bradnelson@chromium.org>
> > Cr-Commit-Position: refs/heads/master@{#48053}
> 
> TBR=bradnelson@chromium.org,mtrofin@chromium.org,eholk@chromium.org
> 
> Change-Id: Id82fa341b77624e4971f24c4757a9a666a65930c
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Reviewed-on: https://chromium-review.googlesource.com/670141
> Reviewed-by: Mircea Trofin <mtrofin@chromium.org>
> Commit-Queue: Mircea Trofin <mtrofin@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#48054}

TBR=bradnelson@chromium.org,mtrofin@chromium.org,eholk@chromium.org

Change-Id: Ib6a7a3e6098d2689e60cdca85ec77e57e5295e48
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://chromium-review.googlesource.com/670142
Commit-Queue: Mircea Trofin <mtrofin@chromium.org>
Reviewed-by: Mircea Trofin <mtrofin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48055}
2017-09-16 05:23:35 +00:00

156 lines
4.8 KiB
C++

// 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"
#include "src/wasm/wasm-heap.h"
namespace v8 {
namespace internal {
namespace wasm {
class DisjointAllocationPoolTest : public testing::Test {
public:
Address A(size_t n) { return reinterpret_cast<Address>(n); }
void CheckLooksLike(const DisjointAllocationPool& mem,
std::vector<std::pair<size_t, size_t>> expectation);
DisjointAllocationPool Make(std::vector<std::pair<size_t, size_t>> model);
};
void DisjointAllocationPoolTest::CheckLooksLike(
const DisjointAllocationPool& mem,
std::vector<std::pair<size_t, size_t>> expectation) {
const auto& ranges = mem.ranges();
CHECK_EQ(ranges.size(), expectation.size());
auto iter = expectation.begin();
for (auto it = ranges.begin(), e = ranges.end(); it != e; ++it, ++iter) {
CHECK_EQ(it->first, A(iter->first));
CHECK_EQ(it->second, A(iter->second));
}
}
DisjointAllocationPool DisjointAllocationPoolTest::Make(
std::vector<std::pair<size_t, size_t>> model) {
DisjointAllocationPool ret;
for (auto& pair : model) {
ret.Release(DisjointAllocationPool(A(pair.first), A(pair.second)));
}
return ret;
}
TEST_F(DisjointAllocationPoolTest, Construct) {
DisjointAllocationPool a;
CHECK(a.IsEmpty());
CHECK_EQ(a.ranges().size(), 0);
DisjointAllocationPool b = Make({{1, 5}});
CHECK(!b.IsEmpty());
CHECK_EQ(b.ranges().size(), 1);
a.Release(std::move(b));
CheckLooksLike(a, {{1, 5}});
DisjointAllocationPool c;
a.Release(std::move(c));
CheckLooksLike(a, {{1, 5}});
DisjointAllocationPool e, f;
e.Release(std::move(f));
CHECK(e.IsEmpty());
}
TEST_F(DisjointAllocationPoolTest, SimpleExtract) {
DisjointAllocationPool a = Make({{1, 5}});
DisjointAllocationPool b = a.AllocatePool(2);
CheckLooksLike(a, {{3, 5}});
CheckLooksLike(b, {{1, 3}});
a.Release(std::move(b));
CheckLooksLike(a, {{1, 5}});
CHECK_EQ(a.ranges().size(), 1);
CHECK_EQ(a.ranges().front().first, A(1));
CHECK_EQ(a.ranges().front().second, A(5));
}
TEST_F(DisjointAllocationPoolTest, ExtractAll) {
DisjointAllocationPool a(A(1), A(5));
DisjointAllocationPool b = a.AllocatePool(4);
CheckLooksLike(b, {{1, 5}});
CHECK(a.IsEmpty());
a.Release(std::move(b));
CheckLooksLike(a, {{1, 5}});
}
TEST_F(DisjointAllocationPoolTest, ExtractAccross) {
DisjointAllocationPool a = Make({{1, 5}, {10, 20}});
DisjointAllocationPool b = a.AllocatePool(5);
CheckLooksLike(a, {{11, 20}});
CheckLooksLike(b, {{1, 5}, {10, 11}});
a.Release(std::move(b));
CheckLooksLike(a, {{1, 5}, {10, 20}});
}
TEST_F(DisjointAllocationPoolTest, ReassembleOutOfOrder) {
DisjointAllocationPool a = Make({{1, 5}, {10, 15}});
DisjointAllocationPool b = Make({{7, 8}, {20, 22}});
a.Release(std::move(b));
CheckLooksLike(a, {{1, 5}, {7, 8}, {10, 15}, {20, 22}});
DisjointAllocationPool c = Make({{1, 5}, {10, 15}});
DisjointAllocationPool d = Make({{7, 8}, {20, 22}});
d.Release(std::move(c));
CheckLooksLike(d, {{1, 5}, {7, 8}, {10, 15}, {20, 22}});
}
TEST_F(DisjointAllocationPoolTest, FailToExtract) {
DisjointAllocationPool a = Make({{1, 5}});
DisjointAllocationPool b = a.AllocatePool(5);
CheckLooksLike(a, {{1, 5}});
CHECK(b.IsEmpty());
}
TEST_F(DisjointAllocationPoolTest, FailToExtractExact) {
DisjointAllocationPool a = Make({{1, 5}, {10, 14}});
DisjointAllocationPool b = a.Allocate(5);
CheckLooksLike(a, {{1, 5}, {10, 14}});
CHECK(b.IsEmpty());
}
TEST_F(DisjointAllocationPoolTest, ExtractExact) {
DisjointAllocationPool a = Make({{1, 5}, {10, 15}});
DisjointAllocationPool b = a.Allocate(5);
CheckLooksLike(a, {{1, 5}});
CheckLooksLike(b, {{10, 15}});
}
TEST_F(DisjointAllocationPoolTest, Merging) {
DisjointAllocationPool a = Make({{10, 15}, {20, 25}});
a.Release(Make({{15, 20}}));
CheckLooksLike(a, {{10, 25}});
}
TEST_F(DisjointAllocationPoolTest, MergingMore) {
DisjointAllocationPool a = Make({{10, 15}, {20, 25}, {30, 35}});
a.Release(Make({{15, 20}, {25, 30}}));
CheckLooksLike(a, {{10, 35}});
}
TEST_F(DisjointAllocationPoolTest, MergingSkip) {
DisjointAllocationPool a = Make({{10, 15}, {20, 25}, {30, 35}});
a.Release(Make({{25, 30}}));
CheckLooksLike(a, {{10, 15}, {20, 35}});
}
TEST_F(DisjointAllocationPoolTest, MergingSkipLargerSrc) {
DisjointAllocationPool a = Make({{10, 15}, {20, 25}, {30, 35}});
a.Release(Make({{25, 30}, {35, 40}}));
CheckLooksLike(a, {{10, 15}, {20, 40}});
}
TEST_F(DisjointAllocationPoolTest, MergingSkipLargerSrcWithGap) {
DisjointAllocationPool a = Make({{10, 15}, {20, 25}, {30, 35}});
a.Release(Make({{25, 30}, {36, 40}}));
CheckLooksLike(a, {{10, 15}, {20, 35}, {36, 40}});
}
} // namespace wasm
} // namespace internal
} // namespace v8