Commit 9ccf3fba authored by Keishi Hattori's avatar Keishi Hattori Committed by Commit Bot

blink_gc_plugin: Check for untraced TraceWrapperMember and TraceWrapperV8References

Adds checks for untraced TraceWrapperMember and TraceWrapperV8References

Bug: 910023
Change-Id: Iec646a8e51d117d6469e1587062fc0862858112a
Reviewed-on: https://chromium-review.googlesource.com/c/1356442Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Reviewed-by: default avatarMichael Lippautz <mlippautz@chromium.org>
Commit-Queue: Keishi Hattori <keishi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#613429}
parent 6547f968
......@@ -68,6 +68,14 @@ class Config {
return name == "unique_ptr";
}
static bool IsTraceWrapperMember(const std::string& name) {
return name == "TraceWrapperMember";
}
static bool IsTraceWrapperV8Reference(const std::string& name) {
return name == "TraceWrapperV8Reference";
}
static bool IsWTFCollection(const std::string& name) {
return name == "Vector" ||
name == "Deque" ||
......
......@@ -17,9 +17,6 @@ const char kClassRequiresTraceMethod[] =
const char kBaseRequiresTracing[] =
"[blink-gc] Base class %0 of derived class %1 requires tracing.";
const char kBaseRequiresWrapperTracing[] =
"[blink-gc] Base class %0 of derived class %1 requires wrapper tracing.";
const char kBaseRequiresTracingNote[] =
"[blink-gc] Untraced base class %0 declared here:";
......
......@@ -23,6 +23,8 @@ void RecursiveEdgeVisitor::AtPersistent(Persistent*) {}
void RecursiveEdgeVisitor::AtCrossThreadPersistent(CrossThreadPersistent*) {}
void RecursiveEdgeVisitor::AtCollection(Collection*) {}
void RecursiveEdgeVisitor::AtIterator(Iterator*) {}
void RecursiveEdgeVisitor::AtTraceWrapperV8Reference(TraceWrapperV8Reference*) {
}
void RecursiveEdgeVisitor::VisitValue(Value* e) {
AtValue(e);
......@@ -88,3 +90,11 @@ void RecursiveEdgeVisitor::VisitCollection(Collection* e) {
void RecursiveEdgeVisitor::VisitIterator(Iterator* e) {
AtIterator(e);
}
void RecursiveEdgeVisitor::VisitTraceWrapperV8Reference(
TraceWrapperV8Reference* e) {
AtTraceWrapperV8Reference(e);
Enter(e);
e->ptr()->Accept(this);
Leave();
}
......@@ -24,6 +24,7 @@ class RefPtr;
class UniquePtr;
class Value;
class WeakMember;
class TraceWrapperV8Reference;
// Bare-bones visitor.
class EdgeVisitor {
......@@ -39,6 +40,7 @@ class EdgeVisitor {
virtual void VisitCrossThreadPersistent(CrossThreadPersistent*) {}
virtual void VisitCollection(Collection*) {}
virtual void VisitIterator(Iterator*) {}
virtual void VisitTraceWrapperV8Reference(TraceWrapperV8Reference*) {}
};
// Recursive edge visitor. The traversed path is accessible in context.
......@@ -55,6 +57,7 @@ class RecursiveEdgeVisitor : public EdgeVisitor {
void VisitCrossThreadPersistent(CrossThreadPersistent*) override;
void VisitCollection(Collection*) override;
void VisitIterator(Iterator*) override;
void VisitTraceWrapperV8Reference(TraceWrapperV8Reference*) override;
protected:
typedef std::deque<Edge*> Context;
......@@ -70,6 +73,7 @@ class RecursiveEdgeVisitor : public EdgeVisitor {
virtual void AtUniquePtr(UniquePtr*);
virtual void AtMember(Member*);
virtual void AtWeakMember(WeakMember*);
virtual void AtTraceWrapperV8Reference(TraceWrapperV8Reference*);
virtual void AtPersistent(Persistent*);
virtual void AtCrossThreadPersistent(CrossThreadPersistent*);
virtual void AtCollection(Collection*);
......@@ -100,6 +104,8 @@ class Edge {
virtual bool IsMember() { return false; }
virtual bool IsWeakMember() { return false; }
virtual bool IsCollection() { return false; }
virtual bool IsTraceWrapperMember() { return false; }
virtual bool IsTraceWrapperV8Reference() { return false; }
};
// A value edge is a direct edge to some type, eg, part-object edges.
......@@ -223,6 +229,26 @@ class CrossThreadPersistent : public PtrEdge {
}
};
class TraceWrapperMember : public Member {
public:
explicit TraceWrapperMember(Edge* ptr) : Member(ptr) {}
bool IsTraceWrapperMember() override { return true; }
};
class TraceWrapperV8Reference : public PtrEdge {
public:
explicit TraceWrapperV8Reference(Edge* ptr) : PtrEdge(ptr) {}
bool IsTraceWrapperV8Reference() override { return true; }
LivenessKind Kind() override { return kStrong; }
bool NeedsFinalization() override { return true; }
TracingStatus NeedsTracing(NeedsTracingOption) override {
return TracingStatus::Needed();
}
void Accept(EdgeVisitor* visitor) override {
visitor->VisitTraceWrapperV8Reference(this);
}
};
class Collection : public Edge {
public:
typedef std::vector<Edge*> Members;
......
......@@ -718,5 +718,19 @@ Edge* RecordInfo::CreateEdge(const Type* type) {
return edge;
}
if (Config::IsTraceWrapperMember(info->name()) &&
info->GetTemplateArgs(1, &args)) {
if (Edge* ptr = CreateEdge(args[0]))
return new TraceWrapperMember(ptr);
return 0;
}
if (Config::IsTraceWrapperV8Reference(info->name()) &&
info->GetTemplateArgs(1, &args)) {
if (Edge* ptr = CreateEdge(args[0]))
return new TraceWrapperV8Reference(ptr);
return 0;
}
return new Value(info);
}
......@@ -250,6 +250,17 @@ public:
bool operator!() const { return false; }
};
template <class T>
class TraceWrapperMember : public Member<T> {};
template <typename T>
class TraceWrapperV8Reference {
public:
operator T*() const { return 0; }
T* operator->() { return 0; }
bool operator!() const { return false; }
};
class HeapAllocator {
public:
static const bool isGarbageCollected = true;
......
// Copyright 2018 The Chromium 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 "trace_wrapper.h"
namespace blink {
void B::Trace(Visitor* visitor) {
static_cast<C*>(this)->TraceAfterDispatch(visitor);
}
} // namespace blink
// Copyright 2018 The Chromium 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 TRACE_WRAPPER_H_
#define TRACE_WRAPPER_H_
#include "heap/stubs.h"
namespace v8 {
class String;
}
namespace blink {
class A : public GarbageCollected<A> {
public:
void Trace(Visitor*) {
// Missing visitor->Trace(a_);
// Missing visitor->Trace(str_);
}
private:
TraceWrapperMember<A> a_;
TraceWrapperV8Reference<v8::String> str_;
};
class B : public GarbageCollected<A> {
public:
void Trace(Visitor* visitor);
void TraceAfterDispatch(Visitor*) {}
};
class C : public B {
public:
void TraceAfterDispatch(Visitor*) {
// Missing visitor->Trace(a_);
// Missing visitor->Trace(str_);
}
private:
TraceWrapperMember<A> a_;
TraceWrapperV8Reference<v8::String> str_;
};
} // namespace blink
#endif // TRACE_WRAPPER_H_
In file included from trace_wrapper.cpp:5:
./trace_wrapper.h:18:3: warning: [blink-gc] Class 'A' has untraced fields that require tracing.
void Trace(Visitor*) {
^
./trace_wrapper.h:24:3: note: [blink-gc] Untraced field 'a_' declared here:
TraceWrapperMember<A> a_;
^
./trace_wrapper.h:25:3: note: [blink-gc] Untraced field 'str_' declared here:
TraceWrapperV8Reference<v8::String> str_;
^
./trace_wrapper.h:36:3: warning: [blink-gc] Base class 'B' of derived class 'C' requires tracing.
void TraceAfterDispatch(Visitor*) {
^
./trace_wrapper.h:36:3: warning: [blink-gc] Class 'C' has untraced fields that require tracing.
./trace_wrapper.h:42:3: note: [blink-gc] Untraced field 'a_' declared here:
TraceWrapperMember<A> a_;
^
./trace_wrapper.h:43:3: note: [blink-gc] Untraced field 'str_' declared here:
TraceWrapperV8Reference<v8::String> str_;
^
3 warnings generated.
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