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:
parent
59bb432572
commit
78313016a9
1
BUILD.gn
1
BUILD.gn
@ -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",
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
54
src/heap/cppgc/object-view.h
Normal file
54
src/heap/cppgc/object-view.h
Normal 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_
|
@ -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.
|
||||
|
@ -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>(
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user