cppgc: Add composite object tracing to Visitor

This allows embedding objects in each other and recursively trace
through them.

Bug: chromium:1056170
Change-Id: I4e4ae4c1669109c01003cb6b69797cf271a74033
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2198977
Reviewed-by: Omer Katz <omerkatz@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67841}
This commit is contained in:
Michael Lippautz 2020-05-13 10:47:25 +02:00 committed by Commit Bot
parent 99e4ef48e1
commit 1d26770085
4 changed files with 64 additions and 2 deletions

View File

@ -4107,6 +4107,7 @@ v8_source_set("cppgc_base") {
"src/heap/cppgc/stack.h",
"src/heap/cppgc/sweeper.cc",
"src/heap/cppgc/sweeper.h",
"src/heap/cppgc/visitor.cc",
"src/heap/cppgc/worklist.h",
]

View File

@ -35,7 +35,7 @@ class Visitor {
template <typename T>
void Trace(const WeakMember<T>& weak_member) {
static_assert(sizeof(T), "T must be fully defined");
static_assert(sizeof(T), "Pointee type must be fully defined.");
static_assert(internal::IsGarbageCollectedType<T>::value,
"T must be GarabgeCollected or GarbageCollectedMixin type");
@ -81,6 +81,18 @@ class Visitor {
&HandleWeak<WeakPersistent>, &p);
}
template <typename T>
void Trace(const T& object) {
#if V8_ENABLE_CHECKS
// This object is embedded in potentially multiple nested objects. The
// outermost object must not be in construction as such objects are (a) not
// processed immediately, and (b) only processed conservatively if not
// otherwise possible.
CheckObjectNotInConstruction(&object);
#endif // V8_ENABLE_CHECKS
TraceTrait<T>::Trace(this, &object);
}
template <typename T, void (T::*method)(const LivenessBroker&)>
void RegisterWeakCallbackMethod(const T* obj) {
RegisterWeakCallback(&WeakCallbackMethodDelegate<T, method>, obj);
@ -121,7 +133,7 @@ class Visitor {
template <typename T>
void Trace(const T* t) {
static_assert(sizeof(T), "T must be fully defined");
static_assert(sizeof(T), "Pointee type must be fully defined.");
static_assert(internal::IsGarbageCollectedType<T>::value,
"T must be GarabgeCollected or GarbageCollectedMixin type");
if (!t) {
@ -130,6 +142,10 @@ class Visitor {
Visit(t, TraceTrait<T>::GetTraceDescriptor(t));
}
#if V8_ENABLE_CHECKS
V8_EXPORT void CheckObjectNotInConstruction(const void* address);
#endif // V8_ENABLE_CHECKS
friend class internal::VisitorBase;
};

16
src/heap/cppgc/visitor.cc Normal file
View File

@ -0,0 +1,16 @@
// Copyright 2020 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/cppgc/visitor.h"
namespace cppgc {
#ifdef V8_ENABLE_CHECKS
void Visitor::CheckObjectNotInConstruction(const void* address) {
// TODO(chromium:1056170): |address| is an inner pointer of an object. Check
// that the object is not in construction.
}
#endif // V8_ENABLE_CHECKS
} // namespace cppgc

View File

@ -228,5 +228,34 @@ TEST_F(VisitorTest, DispatchRegisterWeakCallbackMethod) {
EXPECT_EQ(1u, WeakCallbackDispatcher::callback_callcount);
}
namespace {
class Composite final {
public:
static size_t callback_callcount;
Composite() { callback_callcount = 0; }
void Trace(Visitor* visitor) const { callback_callcount++; }
};
size_t Composite::callback_callcount;
class GCedWithComposite final : public GarbageCollected<GCedWithComposite> {
public:
void Trace(Visitor* visitor) const { visitor->Trace(composite); }
Composite composite;
};
} // namespace
TEST_F(VisitorTest, DispatchToCompositeObject) {
Member<GCedWithComposite> ref =
MakeGarbageCollected<GCedWithComposite>(GetHeap());
DispatchingVisitor visitor(ref, ref);
EXPECT_EQ(0u, Composite::callback_callcount);
visitor.Trace(ref);
EXPECT_EQ(1u, Composite::callback_callcount);
}
} // namespace internal
} // namespace cppgc