2022-07-15 09:40:23 +00:00
|
|
|
// Copyright 2022 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/heap/mark-compact.h"
|
|
|
|
#include "test/unittests/test-utils.h"
|
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
|
|
|
|
#ifdef V8_ENABLE_INNER_POINTER_RESOLUTION_MB
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
class InnerPointerResolutionTest : public TestWithIsolate {
|
|
|
|
public:
|
|
|
|
struct ObjectRequest {
|
|
|
|
int size; // The only required field.
|
2022-07-27 10:45:49 +00:00
|
|
|
enum { REGULAR, FREE, LARGE } type = REGULAR;
|
2022-07-15 09:40:23 +00:00
|
|
|
enum { WHITE, GREY, BLACK, BLACK_AREA } marked = WHITE;
|
|
|
|
// If index_in_cell >= 0, the object is placed at the lowest address s.t.
|
|
|
|
// Bitmap::IndexInCell(AddressToMarkbitIndex(address)) == index_in_cell.
|
|
|
|
// To achieve this, padding (i.e., introducing a free-space object of the
|
|
|
|
// appropriate size) may be necessary. If padding == CONSECUTIVE, no such
|
|
|
|
// padding is allowed and it is just checked that object layout is as
|
|
|
|
// intended.
|
|
|
|
int index_in_cell = -1;
|
|
|
|
enum { CONSECUTIVE, PAD_WHITE, PAD_BLACK } padding = CONSECUTIVE;
|
2022-07-25 12:00:14 +00:00
|
|
|
// The id of the page on which the object was allocated and its address are
|
|
|
|
// stored here.
|
|
|
|
int page_id = -1;
|
|
|
|
Address address = kNullAddress;
|
2022-07-15 09:40:23 +00:00
|
|
|
};
|
|
|
|
|
2022-07-25 12:00:14 +00:00
|
|
|
InnerPointerResolutionTest() = default;
|
2022-07-15 09:40:23 +00:00
|
|
|
|
|
|
|
~InnerPointerResolutionTest() override {
|
2022-07-25 12:00:14 +00:00
|
|
|
for (auto [id, page] : pages_)
|
|
|
|
allocator()->Free(MemoryAllocator::FreeMode::kImmediately, page);
|
2022-07-15 09:40:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
InnerPointerResolutionTest(const InnerPointerResolutionTest&) = delete;
|
|
|
|
InnerPointerResolutionTest& operator=(const InnerPointerResolutionTest&) =
|
|
|
|
delete;
|
|
|
|
|
|
|
|
Heap* heap() { return isolate()->heap(); }
|
|
|
|
MemoryAllocator* allocator() { return heap()->memory_allocator(); }
|
|
|
|
MarkCompactCollector* collector() { return heap()->mark_compact_collector(); }
|
|
|
|
|
2022-07-27 10:45:49 +00:00
|
|
|
// Create, free and lookup pages, normal or large.
|
2022-07-25 12:00:14 +00:00
|
|
|
|
2022-07-27 10:45:49 +00:00
|
|
|
int CreateNormalPage() {
|
2022-07-25 12:00:14 +00:00
|
|
|
OldSpace* old_space = heap()->old_space();
|
|
|
|
DCHECK_NE(nullptr, old_space);
|
|
|
|
auto* page = allocator()->AllocatePage(
|
|
|
|
MemoryAllocator::AllocationMode::kRegular, old_space, NOT_EXECUTABLE);
|
|
|
|
EXPECT_NE(nullptr, page);
|
|
|
|
int page_id = next_page_id_++;
|
|
|
|
DCHECK_EQ(pages_.end(), pages_.find(page_id));
|
|
|
|
pages_[page_id] = page;
|
|
|
|
return page_id;
|
|
|
|
}
|
|
|
|
|
2022-07-27 10:45:49 +00:00
|
|
|
int CreateLargePage(size_t size) {
|
|
|
|
OldLargeObjectSpace* lo_space = heap()->lo_space();
|
|
|
|
EXPECT_NE(nullptr, lo_space);
|
|
|
|
LargePage* page =
|
|
|
|
allocator()->AllocateLargePage(lo_space, size, NOT_EXECUTABLE);
|
|
|
|
EXPECT_NE(nullptr, page);
|
|
|
|
int page_id = next_page_id_++;
|
|
|
|
DCHECK_EQ(pages_.end(), pages_.find(page_id));
|
|
|
|
pages_[page_id] = page;
|
|
|
|
return page_id;
|
|
|
|
}
|
|
|
|
|
2022-07-25 12:00:14 +00:00
|
|
|
void FreePage(int page_id) {
|
|
|
|
DCHECK_LE(0, page_id);
|
|
|
|
auto it = pages_.find(page_id);
|
|
|
|
DCHECK_NE(pages_.end(), it);
|
|
|
|
allocator()->Free(MemoryAllocator::FreeMode::kImmediately, it->second);
|
|
|
|
pages_.erase(it);
|
|
|
|
}
|
|
|
|
|
2022-07-27 10:45:49 +00:00
|
|
|
MemoryChunk* LookupPage(int page_id) {
|
2022-07-25 12:00:14 +00:00
|
|
|
DCHECK_LE(0, page_id);
|
|
|
|
auto it = pages_.find(page_id);
|
|
|
|
DCHECK_NE(pages_.end(), it);
|
|
|
|
return it->second;
|
|
|
|
}
|
|
|
|
|
2022-07-27 10:45:49 +00:00
|
|
|
bool IsPageAlive(int page_id) {
|
|
|
|
DCHECK_LE(0, page_id);
|
|
|
|
return pages_.find(page_id) != pages_.end();
|
|
|
|
}
|
|
|
|
|
2022-07-25 12:00:14 +00:00
|
|
|
// Creates a list of objects in a page and ensures that the page is iterable.
|
2022-07-27 10:45:49 +00:00
|
|
|
int CreateObjectsInPage(const std::vector<ObjectRequest>& objects) {
|
|
|
|
int page_id = CreateNormalPage();
|
|
|
|
MemoryChunk* page = LookupPage(page_id);
|
2022-07-25 12:00:14 +00:00
|
|
|
Address ptr = page->area_start();
|
|
|
|
for (auto object : objects) {
|
2022-07-27 10:45:49 +00:00
|
|
|
DCHECK_NE(ObjectRequest::LARGE, object.type);
|
2022-07-25 12:00:14 +00:00
|
|
|
DCHECK_EQ(0, object.size % kTaggedSize);
|
2022-07-15 09:40:23 +00:00
|
|
|
|
|
|
|
// Check if padding is needed.
|
2022-07-25 12:00:14 +00:00
|
|
|
int index_in_cell = Bitmap::IndexInCell(page->AddressToMarkbitIndex(ptr));
|
|
|
|
if (object.index_in_cell < 0) {
|
|
|
|
object.index_in_cell = index_in_cell;
|
|
|
|
} else if (object.padding != ObjectRequest::CONSECUTIVE) {
|
|
|
|
DCHECK_LE(0, object.index_in_cell);
|
|
|
|
DCHECK_GT(Bitmap::kBitsPerCell, object.index_in_cell);
|
2022-07-15 09:40:23 +00:00
|
|
|
const int needed_padding_size =
|
2022-07-25 12:00:14 +00:00
|
|
|
((Bitmap::kBitsPerCell + object.index_in_cell - index_in_cell) %
|
2022-07-15 09:40:23 +00:00
|
|
|
Bitmap::kBitsPerCell) *
|
|
|
|
Bitmap::kBytesPerCell;
|
|
|
|
if (needed_padding_size > 0) {
|
2022-07-25 12:00:14 +00:00
|
|
|
ObjectRequest pad{needed_padding_size,
|
|
|
|
ObjectRequest::FREE,
|
|
|
|
object.padding == ObjectRequest::PAD_BLACK
|
|
|
|
? ObjectRequest::BLACK_AREA
|
|
|
|
: ObjectRequest::WHITE,
|
|
|
|
index_in_cell,
|
|
|
|
ObjectRequest::CONSECUTIVE,
|
|
|
|
page_id,
|
|
|
|
ptr};
|
2022-07-15 09:40:23 +00:00
|
|
|
ptr += needed_padding_size;
|
2022-07-25 12:00:14 +00:00
|
|
|
DCHECK_LE(ptr, page->area_end());
|
|
|
|
CreateObject(pad);
|
|
|
|
index_in_cell = Bitmap::IndexInCell(page->AddressToMarkbitIndex(ptr));
|
2022-07-15 09:40:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// This will fail if the marking bitmap's implementation parameters change
|
|
|
|
// (e.g., Bitmap::kBitsPerCell) or the size of the page header changes.
|
|
|
|
// In this case, the tests will need to be revised accordingly.
|
2022-07-25 12:00:14 +00:00
|
|
|
EXPECT_EQ(index_in_cell, object.index_in_cell);
|
2022-07-15 09:40:23 +00:00
|
|
|
|
2022-07-25 12:00:14 +00:00
|
|
|
object.page_id = page_id;
|
|
|
|
object.address = ptr;
|
|
|
|
ptr += object.size;
|
|
|
|
DCHECK_LE(ptr, page->area_end());
|
|
|
|
CreateObject(object);
|
2022-07-15 09:40:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Create one last object that uses the remaining space on the page; this
|
|
|
|
// simulates freeing the page's LAB.
|
2022-07-25 12:00:14 +00:00
|
|
|
const int remaining_size = static_cast<int>(page->area_end() - ptr);
|
|
|
|
const uint32_t index = page->AddressToMarkbitIndex(ptr);
|
2022-07-15 09:40:23 +00:00
|
|
|
const int index_in_cell = Bitmap::IndexInCell(index);
|
2022-07-25 12:00:14 +00:00
|
|
|
ObjectRequest last{remaining_size,
|
|
|
|
ObjectRequest::FREE,
|
|
|
|
ObjectRequest::WHITE,
|
|
|
|
index_in_cell,
|
|
|
|
ObjectRequest::CONSECUTIVE,
|
|
|
|
page_id,
|
|
|
|
ptr};
|
2022-07-15 09:40:23 +00:00
|
|
|
CreateObject(last);
|
2022-07-27 10:45:49 +00:00
|
|
|
return page_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<int> CreateLargeObjects(
|
|
|
|
const std::vector<ObjectRequest>& objects) {
|
|
|
|
std::vector<int> result;
|
|
|
|
for (auto object : objects) {
|
|
|
|
DCHECK_EQ(ObjectRequest::LARGE, object.type);
|
|
|
|
int page_id = CreateLargePage(object.size);
|
|
|
|
MemoryChunk* page = LookupPage(page_id);
|
|
|
|
object.page_id = page_id;
|
|
|
|
object.address = page->area_start();
|
|
|
|
CHECK_EQ(object.address + object.size, page->area_end());
|
|
|
|
CreateObject(object);
|
|
|
|
result.push_back(page_id);
|
|
|
|
}
|
|
|
|
return result;
|
2022-07-15 09:40:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CreateObject(const ObjectRequest& object) {
|
2022-07-25 12:00:14 +00:00
|
|
|
objects_.push_back(object);
|
|
|
|
|
2022-07-15 09:40:23 +00:00
|
|
|
// "Allocate" (i.e., manually place) the object in the page, set the map
|
|
|
|
// and the size.
|
|
|
|
switch (object.type) {
|
2022-07-27 10:45:49 +00:00
|
|
|
case ObjectRequest::REGULAR:
|
|
|
|
case ObjectRequest::LARGE: {
|
2022-07-25 12:00:14 +00:00
|
|
|
DCHECK_LE(2 * kTaggedSize, object.size);
|
2022-07-15 09:40:23 +00:00
|
|
|
ReadOnlyRoots roots(heap());
|
|
|
|
HeapObject heap_object(HeapObject::FromAddress(object.address));
|
|
|
|
heap_object.set_map_after_allocation(roots.unchecked_fixed_array_map(),
|
|
|
|
SKIP_WRITE_BARRIER);
|
|
|
|
FixedArray arr(FixedArray::cast(heap_object));
|
|
|
|
arr.set_length((object.size - FixedArray::SizeFor(0)) / kTaggedSize);
|
2022-07-25 12:00:14 +00:00
|
|
|
DCHECK_EQ(object.size, arr.AllocatedSize());
|
2022-07-15 09:40:23 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ObjectRequest::FREE:
|
|
|
|
heap()->CreateFillerObjectAt(object.address, object.size);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Mark the object in the bitmap, if necessary.
|
|
|
|
switch (object.marked) {
|
|
|
|
case ObjectRequest::WHITE:
|
|
|
|
break;
|
|
|
|
case ObjectRequest::GREY:
|
|
|
|
collector()->marking_state()->WhiteToGrey(
|
|
|
|
HeapObject::FromAddress(object.address));
|
|
|
|
break;
|
|
|
|
case ObjectRequest::BLACK:
|
2022-07-25 12:00:14 +00:00
|
|
|
DCHECK_LE(2 * kTaggedSize, object.size);
|
2022-07-15 09:40:23 +00:00
|
|
|
collector()->marking_state()->WhiteToBlack(
|
|
|
|
HeapObject::FromAddress(object.address));
|
|
|
|
break;
|
2022-07-25 12:00:14 +00:00
|
|
|
case ObjectRequest::BLACK_AREA: {
|
2022-07-27 10:45:49 +00:00
|
|
|
MemoryChunk* page = LookupPage(object.page_id);
|
2022-07-25 12:00:14 +00:00
|
|
|
collector()->marking_state()->bitmap(page)->SetRange(
|
|
|
|
page->AddressToMarkbitIndex(object.address),
|
|
|
|
page->AddressToMarkbitIndex(object.address + object.size));
|
2022-07-15 09:40:23 +00:00
|
|
|
break;
|
2022-07-25 12:00:14 +00:00
|
|
|
}
|
2022-07-15 09:40:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// This must be called with a created object and an offset inside it.
|
|
|
|
void RunTestInside(const ObjectRequest& object, int offset) {
|
2022-07-25 12:00:14 +00:00
|
|
|
DCHECK_LE(0, offset);
|
|
|
|
DCHECK_GT(object.size, offset);
|
2022-07-15 09:40:23 +00:00
|
|
|
Address base_ptr =
|
|
|
|
collector()->FindBasePtrForMarking(object.address + offset);
|
2022-07-27 10:45:49 +00:00
|
|
|
bool should_return_null =
|
|
|
|
!IsPageAlive(object.page_id) || (object.type == ObjectRequest::FREE) ||
|
|
|
|
(object.type == ObjectRequest::REGULAR &&
|
|
|
|
(object.marked == ObjectRequest::BLACK_AREA ||
|
|
|
|
(object.marked == ObjectRequest::BLACK && offset < 2 * kTaggedSize) ||
|
|
|
|
(object.marked == ObjectRequest::GREY && offset < kTaggedSize)));
|
|
|
|
if (should_return_null)
|
2022-07-15 09:40:23 +00:00
|
|
|
EXPECT_EQ(kNullAddress, base_ptr);
|
|
|
|
else
|
|
|
|
EXPECT_EQ(object.address, base_ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
// This must be called with an address not contained in any created object.
|
|
|
|
void RunTestOutside(Address ptr) {
|
|
|
|
Address base_ptr = collector()->FindBasePtrForMarking(ptr);
|
|
|
|
EXPECT_EQ(kNullAddress, base_ptr);
|
|
|
|
}
|
|
|
|
|
2022-07-25 12:00:14 +00:00
|
|
|
void TestAll() {
|
|
|
|
for (auto object : objects_) {
|
2022-07-15 09:40:23 +00:00
|
|
|
RunTestInside(object, 0);
|
|
|
|
RunTestInside(object, 1);
|
|
|
|
RunTestInside(object, object.size / 2);
|
|
|
|
RunTestInside(object, object.size - 1);
|
|
|
|
}
|
2022-07-25 12:00:14 +00:00
|
|
|
for (auto [id, page] : pages_) {
|
|
|
|
const Address outside_ptr = page->area_start() - 42;
|
|
|
|
DCHECK_LE(page->address(), outside_ptr);
|
|
|
|
RunTestOutside(outside_ptr);
|
|
|
|
}
|
2022-07-27 10:45:49 +00:00
|
|
|
RunTestOutside(kNullAddress);
|
|
|
|
RunTestOutside(static_cast<Address>(42));
|
|
|
|
RunTestOutside(static_cast<Address>(kZapValue));
|
2022-07-15 09:40:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2022-07-27 10:45:49 +00:00
|
|
|
std::map<int, MemoryChunk*> pages_;
|
2022-07-25 12:00:14 +00:00
|
|
|
int next_page_id_ = 0;
|
|
|
|
std::vector<ObjectRequest> objects_;
|
2022-07-15 09:40:23 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
TEST_F(InnerPointerResolutionTest, EmptyPage) {
|
|
|
|
if (FLAG_enable_third_party_heap) return;
|
2022-07-25 12:00:14 +00:00
|
|
|
CreateObjectsInPage({});
|
|
|
|
TestAll();
|
2022-07-15 09:40:23 +00:00
|
|
|
}
|
|
|
|
|
2022-07-25 12:00:14 +00:00
|
|
|
// Tests with some objects laid out randomly.
|
2022-07-15 09:40:23 +00:00
|
|
|
|
|
|
|
TEST_F(InnerPointerResolutionTest, NothingMarked) {
|
|
|
|
if (FLAG_enable_third_party_heap) return;
|
2022-07-25 12:00:14 +00:00
|
|
|
CreateObjectsInPage({
|
2022-07-15 09:40:23 +00:00
|
|
|
{64},
|
|
|
|
{48},
|
|
|
|
{52},
|
|
|
|
{512},
|
|
|
|
{4, ObjectRequest::FREE},
|
|
|
|
{60},
|
|
|
|
{8, ObjectRequest::FREE},
|
|
|
|
{8},
|
|
|
|
{42176},
|
|
|
|
});
|
2022-07-25 12:00:14 +00:00
|
|
|
TestAll();
|
2022-07-15 09:40:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(InnerPointerResolutionTest, AllMarked) {
|
|
|
|
if (FLAG_enable_third_party_heap) return;
|
2022-07-25 12:00:14 +00:00
|
|
|
CreateObjectsInPage({
|
2022-07-15 09:40:23 +00:00
|
|
|
{64, ObjectRequest::REGULAR, ObjectRequest::BLACK},
|
|
|
|
{48, ObjectRequest::REGULAR, ObjectRequest::GREY},
|
|
|
|
{52, ObjectRequest::REGULAR, ObjectRequest::BLACK},
|
|
|
|
{512, ObjectRequest::REGULAR, ObjectRequest::BLACK},
|
|
|
|
{4, ObjectRequest::FREE, ObjectRequest::GREY},
|
|
|
|
{60, ObjectRequest::REGULAR, ObjectRequest::BLACK},
|
|
|
|
{8, ObjectRequest::FREE, ObjectRequest::GREY},
|
|
|
|
{8, ObjectRequest::REGULAR, ObjectRequest::BLACK},
|
|
|
|
{42176, ObjectRequest::REGULAR, ObjectRequest::BLACK},
|
|
|
|
});
|
2022-07-25 12:00:14 +00:00
|
|
|
TestAll();
|
2022-07-15 09:40:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(InnerPointerResolutionTest, SomeMarked) {
|
|
|
|
if (FLAG_enable_third_party_heap) return;
|
2022-07-25 12:00:14 +00:00
|
|
|
CreateObjectsInPage({
|
2022-07-15 09:40:23 +00:00
|
|
|
{64, ObjectRequest::REGULAR, ObjectRequest::WHITE},
|
|
|
|
{48, ObjectRequest::REGULAR, ObjectRequest::WHITE},
|
|
|
|
{52, ObjectRequest::REGULAR, ObjectRequest::BLACK},
|
|
|
|
{512, ObjectRequest::REGULAR, ObjectRequest::WHITE},
|
|
|
|
{4, ObjectRequest::FREE, ObjectRequest::GREY},
|
|
|
|
{60, ObjectRequest::REGULAR, ObjectRequest::BLACK},
|
|
|
|
{8, ObjectRequest::FREE, ObjectRequest::GREY},
|
|
|
|
{8, ObjectRequest::REGULAR, ObjectRequest::WHITE},
|
|
|
|
{42176, ObjectRequest::REGULAR, ObjectRequest::GREY},
|
|
|
|
});
|
2022-07-25 12:00:14 +00:00
|
|
|
TestAll();
|
2022-07-15 09:40:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(InnerPointerResolutionTest, BlackAreas) {
|
|
|
|
if (FLAG_enable_third_party_heap) return;
|
2022-07-25 12:00:14 +00:00
|
|
|
CreateObjectsInPage({
|
2022-07-15 09:40:23 +00:00
|
|
|
{64, ObjectRequest::REGULAR, ObjectRequest::WHITE},
|
|
|
|
{48, ObjectRequest::REGULAR, ObjectRequest::BLACK_AREA},
|
|
|
|
{52, ObjectRequest::REGULAR, ObjectRequest::BLACK},
|
|
|
|
{512, ObjectRequest::REGULAR, ObjectRequest::BLACK_AREA},
|
|
|
|
{4, ObjectRequest::FREE, ObjectRequest::GREY},
|
|
|
|
{60, ObjectRequest::REGULAR, ObjectRequest::BLACK},
|
|
|
|
{8, ObjectRequest::FREE, ObjectRequest::GREY},
|
|
|
|
{8, ObjectRequest::REGULAR, ObjectRequest::WHITE},
|
|
|
|
{42176, ObjectRequest::REGULAR, ObjectRequest::GREY},
|
|
|
|
});
|
2022-07-25 12:00:14 +00:00
|
|
|
TestAll();
|
2022-07-15 09:40:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Tests with specific object layout, to cover interesting and corner cases.
|
|
|
|
|
|
|
|
TEST_F(InnerPointerResolutionTest, ThreeMarkedObjectsInSameCell) {
|
|
|
|
if (FLAG_enable_third_party_heap) return;
|
2022-07-25 12:00:14 +00:00
|
|
|
CreateObjectsInPage({
|
2022-07-15 09:40:23 +00:00
|
|
|
// Some initial large unmarked object, followed by a small marked object
|
|
|
|
// towards the end of the cell.
|
|
|
|
{512},
|
|
|
|
{20, ObjectRequest::REGULAR, ObjectRequest::BLACK, 20,
|
|
|
|
ObjectRequest::PAD_WHITE},
|
|
|
|
// Then three marked objects in the same cell.
|
|
|
|
{32, ObjectRequest::REGULAR, ObjectRequest::BLACK, 3,
|
|
|
|
ObjectRequest::PAD_WHITE},
|
|
|
|
{48, ObjectRequest::REGULAR, ObjectRequest::BLACK, 11},
|
|
|
|
{20, ObjectRequest::REGULAR, ObjectRequest::BLACK, 23},
|
|
|
|
// This marked object is in the next cell.
|
|
|
|
{64, ObjectRequest::REGULAR, ObjectRequest::BLACK, 17,
|
|
|
|
ObjectRequest::PAD_WHITE},
|
|
|
|
});
|
2022-07-25 12:00:14 +00:00
|
|
|
TestAll();
|
2022-07-15 09:40:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(InnerPointerResolutionTest, ThreeBlackAreasInSameCell) {
|
|
|
|
if (FLAG_enable_third_party_heap) return;
|
2022-07-25 12:00:14 +00:00
|
|
|
CreateObjectsInPage({
|
2022-07-15 09:40:23 +00:00
|
|
|
// Some initial large unmarked object, followed by a small black area
|
|
|
|
// towards the end of the cell.
|
|
|
|
{512},
|
|
|
|
{20, ObjectRequest::REGULAR, ObjectRequest::BLACK_AREA, 20,
|
|
|
|
ObjectRequest::PAD_WHITE},
|
|
|
|
// Then three black areas in the same cell.
|
|
|
|
{32, ObjectRequest::REGULAR, ObjectRequest::BLACK_AREA, 3,
|
|
|
|
ObjectRequest::PAD_WHITE},
|
|
|
|
{48, ObjectRequest::REGULAR, ObjectRequest::BLACK_AREA, 11},
|
|
|
|
{20, ObjectRequest::REGULAR, ObjectRequest::BLACK_AREA, 23},
|
|
|
|
// This black area is in the next cell.
|
|
|
|
{64, ObjectRequest::REGULAR, ObjectRequest::BLACK_AREA, 17,
|
|
|
|
ObjectRequest::PAD_WHITE},
|
|
|
|
});
|
2022-07-25 12:00:14 +00:00
|
|
|
TestAll();
|
2022-07-15 09:40:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(InnerPointerResolutionTest, SmallBlackAreaAtPageStart) {
|
|
|
|
if (FLAG_enable_third_party_heap) return;
|
2022-07-25 12:00:14 +00:00
|
|
|
CreateObjectsInPage({
|
2022-07-15 09:40:23 +00:00
|
|
|
{64, ObjectRequest::REGULAR, ObjectRequest::WHITE, 30,
|
|
|
|
ObjectRequest::PAD_BLACK},
|
|
|
|
});
|
2022-07-25 12:00:14 +00:00
|
|
|
TestAll();
|
2022-07-15 09:40:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(InnerPointerResolutionTest, SmallBlackAreaAtPageStartUntilCellBoundary) {
|
|
|
|
if (FLAG_enable_third_party_heap) return;
|
2022-07-25 12:00:14 +00:00
|
|
|
CreateObjectsInPage({
|
2022-07-15 09:40:23 +00:00
|
|
|
{8, ObjectRequest::REGULAR, ObjectRequest::BLACK_AREA},
|
|
|
|
{64, ObjectRequest::REGULAR, ObjectRequest::WHITE, 0,
|
|
|
|
ObjectRequest::PAD_BLACK},
|
|
|
|
});
|
2022-07-25 12:00:14 +00:00
|
|
|
TestAll();
|
2022-07-15 09:40:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(InnerPointerResolutionTest, LargeBlackAreaAtPageStart) {
|
|
|
|
if (FLAG_enable_third_party_heap) return;
|
2022-07-25 12:00:14 +00:00
|
|
|
CreateObjectsInPage({
|
2022-07-15 09:40:23 +00:00
|
|
|
{42 * Bitmap::kBitsPerCell * Bitmap::kBytesPerCell,
|
|
|
|
ObjectRequest::REGULAR, ObjectRequest::BLACK_AREA},
|
|
|
|
{64, ObjectRequest::REGULAR, ObjectRequest::WHITE, 30,
|
|
|
|
ObjectRequest::PAD_BLACK},
|
|
|
|
});
|
2022-07-25 12:00:14 +00:00
|
|
|
TestAll();
|
2022-07-15 09:40:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(InnerPointerResolutionTest, LargeBlackAreaAtPageStartUntilCellBoundary) {
|
|
|
|
if (FLAG_enable_third_party_heap) return;
|
2022-07-25 12:00:14 +00:00
|
|
|
CreateObjectsInPage({
|
2022-07-15 09:40:23 +00:00
|
|
|
{42 * Bitmap::kBitsPerCell * Bitmap::kBytesPerCell,
|
|
|
|
ObjectRequest::REGULAR, ObjectRequest::BLACK_AREA},
|
|
|
|
{64, ObjectRequest::REGULAR, ObjectRequest::WHITE, 0,
|
|
|
|
ObjectRequest::PAD_BLACK},
|
|
|
|
});
|
2022-07-25 12:00:14 +00:00
|
|
|
TestAll();
|
2022-07-15 09:40:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(InnerPointerResolutionTest, SmallBlackAreaStartingAtCellBoundary) {
|
|
|
|
if (FLAG_enable_third_party_heap) return;
|
2022-07-25 12:00:14 +00:00
|
|
|
CreateObjectsInPage({
|
2022-07-15 09:40:23 +00:00
|
|
|
{512},
|
|
|
|
{20, ObjectRequest::REGULAR, ObjectRequest::BLACK_AREA, 0,
|
|
|
|
ObjectRequest::PAD_WHITE},
|
|
|
|
});
|
2022-07-25 12:00:14 +00:00
|
|
|
TestAll();
|
2022-07-15 09:40:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(InnerPointerResolutionTest, LargeBlackAreaStartingAtCellBoundary) {
|
|
|
|
if (FLAG_enable_third_party_heap) return;
|
2022-07-25 12:00:14 +00:00
|
|
|
CreateObjectsInPage({
|
2022-07-15 09:40:23 +00:00
|
|
|
{512},
|
|
|
|
{42 * Bitmap::kBitsPerCell * Bitmap::kBytesPerCell + 64,
|
|
|
|
ObjectRequest::REGULAR, ObjectRequest::BLACK_AREA, 0,
|
|
|
|
ObjectRequest::PAD_WHITE},
|
|
|
|
});
|
2022-07-25 12:00:14 +00:00
|
|
|
TestAll();
|
2022-07-15 09:40:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(InnerPointerResolutionTest, SmallBlackAreaEndingAtCellBoundary) {
|
|
|
|
if (FLAG_enable_third_party_heap) return;
|
2022-07-25 12:00:14 +00:00
|
|
|
CreateObjectsInPage({
|
2022-07-15 09:40:23 +00:00
|
|
|
{512},
|
|
|
|
{8, ObjectRequest::REGULAR, ObjectRequest::BLACK_AREA, 13,
|
|
|
|
ObjectRequest::PAD_WHITE},
|
|
|
|
{64, ObjectRequest::REGULAR, ObjectRequest::WHITE, 0,
|
|
|
|
ObjectRequest::PAD_BLACK},
|
|
|
|
});
|
2022-07-25 12:00:14 +00:00
|
|
|
TestAll();
|
2022-07-15 09:40:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(InnerPointerResolutionTest, LargeBlackAreaEndingAtCellBoundary) {
|
|
|
|
if (FLAG_enable_third_party_heap) return;
|
2022-07-25 12:00:14 +00:00
|
|
|
CreateObjectsInPage({
|
2022-07-15 09:40:23 +00:00
|
|
|
{512},
|
|
|
|
{42 * Bitmap::kBitsPerCell * Bitmap::kBytesPerCell + 64,
|
|
|
|
ObjectRequest::REGULAR, ObjectRequest::BLACK_AREA, 0,
|
|
|
|
ObjectRequest::PAD_WHITE},
|
|
|
|
{64, ObjectRequest::REGULAR, ObjectRequest::WHITE, 0,
|
|
|
|
ObjectRequest::PAD_BLACK},
|
|
|
|
});
|
2022-07-25 12:00:14 +00:00
|
|
|
TestAll();
|
2022-07-15 09:40:23 +00:00
|
|
|
}
|
2022-07-25 12:00:14 +00:00
|
|
|
|
2022-07-15 09:40:23 +00:00
|
|
|
TEST_F(InnerPointerResolutionTest, TwoSmallBlackAreasAtCellBoundaries) {
|
|
|
|
if (FLAG_enable_third_party_heap) return;
|
2022-07-25 12:00:14 +00:00
|
|
|
CreateObjectsInPage({
|
2022-07-15 09:40:23 +00:00
|
|
|
{512},
|
|
|
|
{24, ObjectRequest::REGULAR, ObjectRequest::BLACK_AREA, 0,
|
|
|
|
ObjectRequest::PAD_WHITE},
|
|
|
|
{8, ObjectRequest::REGULAR, ObjectRequest::BLACK_AREA, 25,
|
|
|
|
ObjectRequest::PAD_WHITE},
|
|
|
|
{64, ObjectRequest::REGULAR, ObjectRequest::WHITE, 0,
|
|
|
|
ObjectRequest::PAD_BLACK},
|
|
|
|
});
|
2022-07-25 12:00:14 +00:00
|
|
|
TestAll();
|
2022-07-15 09:40:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(InnerPointerResolutionTest, BlackAreaOfOneCell) {
|
|
|
|
if (FLAG_enable_third_party_heap) return;
|
2022-07-25 12:00:14 +00:00
|
|
|
CreateObjectsInPage({
|
2022-07-15 09:40:23 +00:00
|
|
|
{512},
|
|
|
|
{Bitmap::kBitsPerCell * Bitmap::kBytesPerCell, ObjectRequest::REGULAR,
|
|
|
|
ObjectRequest::BLACK_AREA, 0, ObjectRequest::PAD_WHITE},
|
|
|
|
});
|
2022-07-25 12:00:14 +00:00
|
|
|
TestAll();
|
2022-07-15 09:40:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(InnerPointerResolutionTest, BlackAreaOfManyCells) {
|
|
|
|
if (FLAG_enable_third_party_heap) return;
|
2022-07-25 12:00:14 +00:00
|
|
|
CreateObjectsInPage({
|
2022-07-15 09:40:23 +00:00
|
|
|
{512},
|
|
|
|
{17 * Bitmap::kBitsPerCell * Bitmap::kBytesPerCell,
|
|
|
|
ObjectRequest::REGULAR, ObjectRequest::BLACK_AREA, 0,
|
|
|
|
ObjectRequest::PAD_WHITE},
|
|
|
|
});
|
2022-07-25 12:00:14 +00:00
|
|
|
TestAll();
|
|
|
|
}
|
|
|
|
|
2022-07-27 10:45:49 +00:00
|
|
|
// Test with more pages, normal and large.
|
2022-07-25 12:00:14 +00:00
|
|
|
|
|
|
|
TEST_F(InnerPointerResolutionTest, TwoPages) {
|
|
|
|
if (FLAG_enable_third_party_heap) return;
|
|
|
|
CreateObjectsInPage({
|
|
|
|
{64, ObjectRequest::REGULAR, ObjectRequest::WHITE},
|
|
|
|
{52, ObjectRequest::REGULAR, ObjectRequest::BLACK},
|
|
|
|
{512, ObjectRequest::REGULAR, ObjectRequest::WHITE},
|
|
|
|
{60, ObjectRequest::REGULAR, ObjectRequest::BLACK},
|
|
|
|
{42176, ObjectRequest::REGULAR, ObjectRequest::GREY},
|
|
|
|
});
|
|
|
|
CreateObjectsInPage({
|
|
|
|
{512, ObjectRequest::REGULAR, ObjectRequest::BLACK_AREA},
|
|
|
|
{64, ObjectRequest::REGULAR, ObjectRequest::WHITE},
|
|
|
|
{48, ObjectRequest::REGULAR, ObjectRequest::BLACK_AREA},
|
|
|
|
{52, ObjectRequest::REGULAR, ObjectRequest::BLACK},
|
|
|
|
{4, ObjectRequest::FREE, ObjectRequest::GREY},
|
|
|
|
{8, ObjectRequest::FREE, ObjectRequest::GREY},
|
|
|
|
{8, ObjectRequest::REGULAR, ObjectRequest::WHITE},
|
|
|
|
{60, ObjectRequest::REGULAR, ObjectRequest::BLACK},
|
|
|
|
});
|
|
|
|
TestAll();
|
2022-07-15 09:40:23 +00:00
|
|
|
}
|
|
|
|
|
2022-07-27 10:45:49 +00:00
|
|
|
TEST_F(InnerPointerResolutionTest, OneLargePage) {
|
|
|
|
if (FLAG_enable_third_party_heap) return;
|
|
|
|
CreateLargeObjects({
|
|
|
|
{1 * MB, ObjectRequest::LARGE, ObjectRequest::WHITE},
|
|
|
|
});
|
|
|
|
TestAll();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(InnerPointerResolutionTest, SeveralLargePages) {
|
|
|
|
if (FLAG_enable_third_party_heap) return;
|
|
|
|
CreateLargeObjects({
|
|
|
|
{1 * MB, ObjectRequest::LARGE, ObjectRequest::WHITE},
|
|
|
|
{32 * MB, ObjectRequest::LARGE, ObjectRequest::BLACK},
|
|
|
|
});
|
|
|
|
TestAll();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(InnerPointerResolutionTest, PagesOfBothKind) {
|
|
|
|
if (FLAG_enable_third_party_heap) return;
|
|
|
|
CreateObjectsInPage({
|
|
|
|
{64, ObjectRequest::REGULAR, ObjectRequest::WHITE},
|
|
|
|
{52, ObjectRequest::REGULAR, ObjectRequest::BLACK},
|
|
|
|
{512, ObjectRequest::REGULAR, ObjectRequest::WHITE},
|
|
|
|
{60, ObjectRequest::REGULAR, ObjectRequest::BLACK},
|
|
|
|
{42176, ObjectRequest::REGULAR, ObjectRequest::GREY},
|
|
|
|
});
|
|
|
|
CreateObjectsInPage({
|
|
|
|
{512, ObjectRequest::REGULAR, ObjectRequest::BLACK_AREA},
|
|
|
|
{64, ObjectRequest::REGULAR, ObjectRequest::WHITE},
|
|
|
|
{48, ObjectRequest::REGULAR, ObjectRequest::BLACK_AREA},
|
|
|
|
{52, ObjectRequest::REGULAR, ObjectRequest::BLACK},
|
|
|
|
{4, ObjectRequest::FREE, ObjectRequest::GREY},
|
|
|
|
{8, ObjectRequest::FREE, ObjectRequest::GREY},
|
|
|
|
{8, ObjectRequest::REGULAR, ObjectRequest::WHITE},
|
|
|
|
{60, ObjectRequest::REGULAR, ObjectRequest::BLACK},
|
|
|
|
});
|
|
|
|
CreateLargeObjects({
|
|
|
|
{1 * MB, ObjectRequest::LARGE, ObjectRequest::WHITE},
|
|
|
|
{32 * MB, ObjectRequest::LARGE, ObjectRequest::BLACK},
|
|
|
|
});
|
|
|
|
TestAll();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(InnerPointerResolutionTest, FreePages) {
|
|
|
|
if (FLAG_enable_third_party_heap) return;
|
|
|
|
int some_normal_page = CreateObjectsInPage({
|
|
|
|
{64, ObjectRequest::REGULAR, ObjectRequest::WHITE},
|
|
|
|
{52, ObjectRequest::REGULAR, ObjectRequest::BLACK},
|
|
|
|
{512, ObjectRequest::REGULAR, ObjectRequest::WHITE},
|
|
|
|
{60, ObjectRequest::REGULAR, ObjectRequest::BLACK},
|
|
|
|
{42176, ObjectRequest::REGULAR, ObjectRequest::GREY},
|
|
|
|
});
|
|
|
|
CreateObjectsInPage({
|
|
|
|
{512, ObjectRequest::REGULAR, ObjectRequest::BLACK_AREA},
|
|
|
|
{64, ObjectRequest::REGULAR, ObjectRequest::WHITE},
|
|
|
|
{48, ObjectRequest::REGULAR, ObjectRequest::BLACK_AREA},
|
|
|
|
{52, ObjectRequest::REGULAR, ObjectRequest::BLACK},
|
|
|
|
{4, ObjectRequest::FREE, ObjectRequest::GREY},
|
|
|
|
{8, ObjectRequest::FREE, ObjectRequest::GREY},
|
|
|
|
{8, ObjectRequest::REGULAR, ObjectRequest::WHITE},
|
|
|
|
{60, ObjectRequest::REGULAR, ObjectRequest::BLACK},
|
|
|
|
});
|
|
|
|
auto large_pages = CreateLargeObjects({
|
|
|
|
{1 * MB, ObjectRequest::LARGE, ObjectRequest::WHITE},
|
|
|
|
{32 * MB, ObjectRequest::LARGE, ObjectRequest::BLACK},
|
|
|
|
});
|
|
|
|
TestAll();
|
|
|
|
FreePage(some_normal_page);
|
|
|
|
TestAll();
|
|
|
|
FreePage(large_pages[0]);
|
|
|
|
TestAll();
|
|
|
|
}
|
|
|
|
|
2022-07-15 09:40:23 +00:00
|
|
|
#endif // V8_ENABLE_INNER_POINTER_RESOLUTION_MB
|
|
|
|
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|