Commit b7981e3b authored by Michael Lippautz's avatar Michael Lippautz Committed by Commit Bot

cppgc: Visitor: Add custom weak callback support

This adds support for custom weak callbacks through static callbacks and
instance methods.

Bug: chromium:1056170
Change-Id: Ie4bd32539e0d933b192f07edb2d45e0070c2128d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2148784
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: 's avatarAnton Bikineev <bikineev@chromium.org>
Reviewed-by: 's avatarOmer Katz <omerkatz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67167}
parent 0b392da2
......@@ -80,6 +80,13 @@ class Visitor {
VisitWeakRoot(&p, &HandleWeak<Persistent>);
}
template <typename T, void (T::*method)(const LivenessBroker&)>
void RegisterWeakCallbackMethod(const T* obj) {
RegisterWeakCallback(&WeakCallbackMethodDelegate<T, method>, obj);
}
virtual void RegisterWeakCallback(WeakCallback, const void*) {}
protected:
virtual void Visit(const void* self, TraceDescriptor) {}
virtual void VisitWeak(const void* self, TraceDescriptor, WeakCallback,
......@@ -89,6 +96,14 @@ class Visitor {
virtual void VisitWeakRoot(const void*, WeakCallback) {}
private:
template <typename T, void (T::*method)(const LivenessBroker&)>
static void WeakCallbackMethodDelegate(const LivenessBroker& info,
const void* self) {
// Callback is registered through a potential const Trace method but needs
// to be able to modify fields. See HandleWeak.
(const_cast<T*>(static_cast<const T*>(self))->*method)(info);
}
template <typename PointerType>
static void HandleWeak(const LivenessBroker& info, const void* object) {
const PointerType* weak = static_cast<const PointerType*>(object);
......
......@@ -50,31 +50,6 @@ class GCedMixinApplication : public GCed,
}
};
class DispatchingVisitor final : public VisitorBase {
public:
DispatchingVisitor(const void* object, const void* payload)
: object_(object), payload_(payload) {}
protected:
void Visit(const void* t, TraceDescriptor desc) final {
EXPECT_EQ(object_, t);
EXPECT_EQ(payload_, desc.base_object_payload);
desc.callback(this, desc.base_object_payload);
}
void VisitWeak(const void* t, TraceDescriptor desc, WeakCallback callback,
const void* weak_member) final {
EXPECT_EQ(object_, t);
EXPECT_EQ(payload_, desc.base_object_payload);
LivenessBroker broker = LivenessBrokerFactory::Create();
callback(broker, weak_member);
}
private:
const void* object_;
const void* payload_;
};
} // namespace
TEST_F(TraceTraitTest, GetObjectStartGCed) {
......@@ -123,6 +98,35 @@ TEST_F(TraceTraitTest, TraceGCedMixinThroughTraceDescriptor) {
EXPECT_EQ(1u, GCed::trace_callcount);
}
namespace {
class DispatchingVisitor final : public VisitorBase {
public:
DispatchingVisitor(const void* object, const void* payload)
: object_(object), payload_(payload) {}
protected:
void Visit(const void* t, TraceDescriptor desc) final {
EXPECT_EQ(object_, t);
EXPECT_EQ(payload_, desc.base_object_payload);
desc.callback(this, desc.base_object_payload);
}
void VisitWeak(const void* t, TraceDescriptor desc, WeakCallback callback,
const void* weak_member) final {
EXPECT_EQ(object_, t);
EXPECT_EQ(payload_, desc.base_object_payload);
LivenessBroker broker = LivenessBrokerFactory::Create();
callback(broker, weak_member);
}
private:
const void* object_;
const void* payload_;
};
} // namespace
TEST_F(VisitorTest, DispatchTraceGCed) {
Member<GCed> ref = MakeGarbageCollected<GCed>(GetHeap());
DispatchingVisitor visitor(ref, ref);
......@@ -163,5 +167,66 @@ TEST_F(VisitorTest, DispatchTraceWeakGCedMixin) {
EXPECT_EQ(nullptr, ref.Get());
}
namespace {
class WeakCallbackVisitor final : public VisitorBase {
public:
void RegisterWeakCallback(WeakCallback callback, const void* param) final {
LivenessBroker broker = LivenessBrokerFactory::Create();
callback(broker, param);
}
};
struct WeakCallbackDispatcher {
static size_t callback_callcount;
static const void* callback_param;
static void Setup(const void* expected_param) {
callback_callcount = 0;
callback_param = expected_param;
}
static void Call(const LivenessBroker& broker, const void* param) {
EXPECT_EQ(callback_param, param);
callback_callcount++;
}
};
size_t WeakCallbackDispatcher::callback_callcount;
const void* WeakCallbackDispatcher::callback_param;
class GCedWithCustomWeakCallback final
: public GarbageCollected<GCedWithCustomWeakCallback> {
public:
void CustomWeakCallbackMethod(const LivenessBroker& broker) {
WeakCallbackDispatcher::Call(broker, this);
}
void Trace(cppgc::Visitor* visitor) {
visitor->RegisterWeakCallbackMethod<
GCedWithCustomWeakCallback,
&GCedWithCustomWeakCallback::CustomWeakCallbackMethod>(this);
}
};
} // namespace
TEST_F(VisitorTest, DispatchRegisterWeakCallback) {
WeakCallbackVisitor visitor;
WeakCallbackDispatcher::Setup(&visitor);
EXPECT_EQ(0u, WeakCallbackDispatcher::callback_callcount);
visitor.RegisterWeakCallback(WeakCallbackDispatcher::Call, &visitor);
EXPECT_EQ(1u, WeakCallbackDispatcher::callback_callcount);
}
TEST_F(VisitorTest, DispatchRegisterWeakCallbackMethod) {
WeakCallbackVisitor visitor;
auto* gced = MakeGarbageCollected<GCedWithCustomWeakCallback>(GetHeap());
WeakCallbackDispatcher::Setup(gced);
EXPECT_EQ(0u, WeakCallbackDispatcher::callback_callcount);
gced->Trace(&visitor);
EXPECT_EQ(1u, WeakCallbackDispatcher::callback_callcount);
}
} // namespace internal
} // namespace cppgc
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment