cppgc: Introduce ObjectView

ObjectView abstracts Start/End/Size of an object over the different
internal representations (HeapObjectHeader and LargePage).

Bug: chromium:1056170
Change-Id: I4e888f907fff94c1b02d5e21b4ec3f4a78a471f8
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2892081
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: Omer Katz <omerkatz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#74594}
This commit is contained in:
Michael Lippautz 2021-05-17 12:23:17 +02:00 committed by V8 LUCI CQ
parent 59bb432572
commit 78313016a9
8 changed files with 70 additions and 19 deletions

View File

@ -5034,6 +5034,7 @@ v8_source_set("cppgc_base") {
"src/heap/cppgc/object-poisoner.h",
"src/heap/cppgc/object-size-trait.cc",
"src/heap/cppgc/object-start-bitmap.h",
"src/heap/cppgc/object-view.h",
"src/heap/cppgc/page-memory.cc",
"src/heap/cppgc/page-memory.h",
"src/heap/cppgc/persistent-node.cc",

View File

@ -15,6 +15,7 @@
#include "src/heap/cppgc/heap-visitor.h"
#include "src/heap/cppgc/marker.h"
#include "src/heap/cppgc/marking-verifier.h"
#include "src/heap/cppgc/object-view.h"
#include "src/heap/cppgc/page-memory.h"
#include "src/heap/cppgc/prefinalizer-handler.h"
#include "src/heap/cppgc/stats-collector.h"
@ -35,10 +36,7 @@ class ObjectSizeCounter : private HeapVisitor<ObjectSizeCounter> {
private:
static size_t ObjectSize(const HeapObjectHeader* header) {
return header->IsLargeObject()
? static_cast<const LargePage*>(BasePage::FromPayload(header))
->ObjectSize()
: header->ObjectSize();
return ObjectView(*header).Size();
}
bool VisitHeapObjectHeader(HeapObjectHeader* header) {

View File

@ -219,6 +219,7 @@ void HeapObjectHeader::SetAllocatedSize(size_t size) {
template <AccessMode mode>
size_t HeapObjectHeader::ObjectSize() const {
// The following DCHECK also fails for large objects.
DCHECK_GT(AllocatedSize<mode>(), sizeof(HeapObjectHeader));
return AllocatedSize<mode>() - sizeof(HeapObjectHeader);
}

View File

@ -6,6 +6,7 @@
#include "src/heap/cppgc/heap-object-header.h"
#include "src/heap/cppgc/heap-page.h"
#include "src/heap/cppgc/object-view.h"
namespace cppgc {
namespace internal {
@ -13,11 +14,7 @@ namespace internal {
// static
size_t BaseObjectSizeTrait::GetObjectSizeForGarbageCollected(
const void* object) {
const auto& header = HeapObjectHeader::FromObject(object);
return header.IsLargeObject()
? static_cast<const LargePage*>(BasePage::FromPayload(&header))
->ObjectSize()
: header.ObjectSize();
return ObjectView(HeapObjectHeader::FromObject(object)).Size();
}
// static

View File

@ -0,0 +1,54 @@
// Copyright 2021 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.
#ifndef V8_HEAP_CPPGC_OBJECT_VIEW_H_
#define V8_HEAP_CPPGC_OBJECT_VIEW_H_
#include "include/v8config.h"
#include "src/heap/cppgc/heap-object-header.h"
#include "src/heap/cppgc/heap-page.h"
namespace cppgc {
namespace internal {
// ObjectView allows accessing a header within the bounds of the actual object.
// It is not exposed externally and does not keep the underlying object alive.
class ObjectView final {
public:
V8_INLINE explicit ObjectView(const HeapObjectHeader& header);
V8_INLINE Address Start() const;
V8_INLINE ConstAddress End() const;
V8_INLINE size_t Size() const;
private:
const HeapObjectHeader& header_;
const BasePage* base_page_;
const bool is_large_object_;
};
ObjectView::ObjectView(const HeapObjectHeader& header)
: header_(header),
base_page_(
BasePage::FromPayload(const_cast<HeapObjectHeader*>(&header_))),
is_large_object_(header_.IsLargeObject()) {
DCHECK_EQ(Start() + Size(), End());
}
Address ObjectView::Start() const { return header_.ObjectStart(); }
ConstAddress ObjectView::End() const {
return is_large_object_ ? LargePage::From(base_page_)->PayloadEnd()
: header_.ObjectEnd();
}
size_t ObjectView::Size() const {
return is_large_object_ ? LargePage::From(base_page_)->ObjectSize()
: header_.ObjectSize();
}
} // namespace internal
} // namespace cppgc
#endif // V8_HEAP_CPPGC_OBJECT_VIEW_H_

View File

@ -8,6 +8,7 @@
#include "src/heap/cppgc/gc-info-table.h"
#include "src/heap/cppgc/heap-object-header.h"
#include "src/heap/cppgc/heap-page.h"
#include "src/heap/cppgc/object-view.h"
#include "src/heap/cppgc/page-memory.h"
namespace cppgc {
@ -29,12 +30,9 @@ namespace {
void TraceConservatively(ConservativeTracingVisitor* conservative_visitor,
const HeapObjectHeader& header) {
Address* object = reinterpret_cast<Address*>(header.ObjectStart());
const size_t object_size =
header.IsLargeObject()
? LargePage::From(BasePage::FromPayload(&header))->ObjectSize()
: header.ObjectSize();
for (size_t i = 0; i < (object_size / sizeof(Address)); ++i) {
const auto object_view = ObjectView(header);
Address* object = reinterpret_cast<Address*>(object_view.Start());
for (size_t i = 0; i < (object_view.Size() / sizeof(Address)); ++i) {
Address maybe_ptr = object[i];
#if defined(MEMORY_SANITIZER)
// |object| may be uninitialized by design or just contain padding bytes.

View File

@ -119,6 +119,7 @@ TEST_F(ExplicitManagementTest, GrowAtLAB) {
auto* o =
MakeGarbageCollected<DynamicallySized>(GetHeap()->GetAllocationHandle());
auto& header = HeapObjectHeader::FromObject(o);
ASSERT_TRUE(!header.IsLargeObject());
constexpr size_t size_of_o = sizeof(DynamicallySized);
constexpr size_t kFirstDelta = 8;
EXPECT_TRUE(subtle::Resize(*o, AdditionalBytes(kFirstDelta)));
@ -142,6 +143,7 @@ TEST_F(ExplicitManagementTest, GrowShrinkAtLAB) {
auto* o =
MakeGarbageCollected<DynamicallySized>(GetHeap()->GetAllocationHandle());
auto& header = HeapObjectHeader::FromObject(o);
ASSERT_TRUE(!header.IsLargeObject());
constexpr size_t size_of_o = sizeof(DynamicallySized);
constexpr size_t kDelta = 27;
EXPECT_TRUE(subtle::Resize(*o, AdditionalBytes(kDelta)));
@ -159,6 +161,7 @@ TEST_F(ExplicitManagementTest, ShrinkFreeList) {
// Force returning to free list by removing the LAB.
ResetLinearAllocationBuffers();
auto& header = HeapObjectHeader::FromObject(o);
ASSERT_TRUE(!header.IsLargeObject());
constexpr size_t size_of_o = sizeof(DynamicallySized);
EXPECT_TRUE(subtle::Resize(*o, AdditionalBytes(0)));
EXPECT_EQ(RoundUp<kAllocationGranularity>(size_of_o), header.ObjectSize());
@ -174,6 +177,7 @@ TEST_F(ExplicitManagementTest, ShrinkFreeListBailoutAvoidFragmentation) {
// Force returning to free list by removing the LAB.
ResetLinearAllocationBuffers();
auto& header = HeapObjectHeader::FromObject(o);
ASSERT_TRUE(!header.IsLargeObject());
constexpr size_t size_of_o = sizeof(DynamicallySized);
EXPECT_TRUE(subtle::Resize(*o, AdditionalBytes(0)));
EXPECT_EQ(RoundUp<kAllocationGranularity>(

View File

@ -13,6 +13,7 @@
#include "src/heap/cppgc/globals.h"
#include "src/heap/cppgc/heap-visitor.h"
#include "src/heap/cppgc/heap.h"
#include "src/heap/cppgc/object-view.h"
#include "test/unittests/heap/cppgc/tests.h"
#include "testing/gtest/include/gtest/gtest.h"
@ -206,10 +207,7 @@ class ObjectSizeCounter final : private HeapVisitor<ObjectSizeCounter> {
private:
static size_t ObjectSize(const HeapObjectHeader* header) {
return header->IsLargeObject()
? static_cast<const LargePage*>(BasePage::FromPayload(header))
->ObjectSize()
: header->ObjectSize();
return ObjectView(*header).Size();
}
bool VisitHeapObjectHeader(HeapObjectHeader* header) {