1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef TOOLS_BLINK_GC_PLUGIN_EDGE_H_
6 #define TOOLS_BLINK_GC_PLUGIN_EDGE_H_
10 #include "TracingStatus.h"
24 // Bare-bones visitor.
27 virtual ~EdgeVisitor() {}
28 virtual void VisitValue(Value
*) {}
29 virtual void VisitRawPtr(RawPtr
*) {}
30 virtual void VisitRefPtr(RefPtr
*) {}
31 virtual void VisitOwnPtr(OwnPtr
*) {}
32 virtual void VisitMember(Member
*) {}
33 virtual void VisitWeakMember(WeakMember
*) {}
34 virtual void VisitPersistent(Persistent
*) {}
35 virtual void VisitCollection(Collection
*) {}
38 // Recursive edge visitor. The traversed path is accessible in context.
39 class RecursiveEdgeVisitor
: public EdgeVisitor
{
41 // Overrides that recursively walk the edges and record the path.
42 void VisitValue(Value
*) override
;
43 void VisitRawPtr(RawPtr
*) override
;
44 void VisitRefPtr(RefPtr
*) override
;
45 void VisitOwnPtr(OwnPtr
*) override
;
46 void VisitMember(Member
*) override
;
47 void VisitWeakMember(WeakMember
*) override
;
48 void VisitPersistent(Persistent
*) override
;
49 void VisitCollection(Collection
*) override
;
52 typedef std::deque
<Edge
*> Context
;
53 Context
& context() { return context_
; }
54 Edge
* Parent() { return context_
.empty() ? 0 : context_
.front(); }
55 void Enter(Edge
* e
) { return context_
.push_front(e
); }
56 void Leave() { context_
.pop_front(); }
58 // Default callback to overwrite in visitor subclass.
59 virtual void AtValue(Value
*);
60 virtual void AtRawPtr(RawPtr
*);
61 virtual void AtRefPtr(RefPtr
*);
62 virtual void AtOwnPtr(OwnPtr
*);
63 virtual void AtMember(Member
*);
64 virtual void AtWeakMember(WeakMember
*);
65 virtual void AtPersistent(Persistent
*);
66 virtual void AtCollection(Collection
*);
72 // Base class for all edges.
75 enum NeedsTracingOption
{ kRecursive
, kNonRecursive
};
76 enum LivenessKind
{ kWeak
, kStrong
, kRoot
};
79 virtual LivenessKind
Kind() = 0;
80 virtual void Accept(EdgeVisitor
*) = 0;
81 virtual bool NeedsFinalization() = 0;
82 virtual TracingStatus
NeedsTracing(NeedsTracingOption
) {
83 return TracingStatus::Unknown();
86 virtual bool IsValue() { return false; }
87 virtual bool IsRawPtr() { return false; }
88 virtual bool IsRawPtrClass() { return false; }
89 virtual bool IsRefPtr() { return false; }
90 virtual bool IsOwnPtr() { return false; }
91 virtual bool IsMember() { return false; }
92 virtual bool IsWeakMember() { return false; }
93 virtual bool IsPersistent() { return false; }
94 virtual bool IsCollection() { return false; }
97 // A value edge is a direct edge to some type, eg, part-object edges.
98 class Value
: public Edge
{
100 explicit Value(RecordInfo
* value
) : value_(value
) {};
101 bool IsValue() override
{ return true; }
102 LivenessKind
Kind() override
{ return kStrong
; }
103 bool NeedsFinalization() override
;
104 TracingStatus
NeedsTracing(NeedsTracingOption
) override
;
105 void Accept(EdgeVisitor
* visitor
) override
{ visitor
->VisitValue(this); }
106 RecordInfo
* value() { return value_
; }
112 // Shared base for smart-pointer edges.
113 class PtrEdge
: public Edge
{
115 ~PtrEdge() { delete ptr_
; }
116 Edge
* ptr() { return ptr_
; }
118 PtrEdge(Edge
* ptr
) : ptr_(ptr
) {
119 assert(ptr
&& "EdgePtr pointer must be non-null");
125 class RawPtr
: public PtrEdge
{
127 RawPtr(Edge
* ptr
, bool is_ptr_class
, bool is_ref_type
)
129 , is_ptr_class_(is_ptr_class
)
130 , is_ref_type_(is_ref_type
)
132 assert(!(is_ptr_class_
&& is_ref_type_
));
135 bool IsRawPtr() { return true; }
136 bool IsRawPtrClass() { return is_ptr_class_
; }
137 LivenessKind
Kind() { return kWeak
; }
138 bool NeedsFinalization() { return false; }
139 TracingStatus
NeedsTracing(NeedsTracingOption
) {
140 return TracingStatus::Unneeded();
142 void Accept(EdgeVisitor
* visitor
) { visitor
->VisitRawPtr(this); }
144 bool HasReferenceType() { return is_ref_type_
; }
150 class RefPtr
: public PtrEdge
{
152 explicit RefPtr(Edge
* ptr
) : PtrEdge(ptr
) { }
153 bool IsRefPtr() { return true; }
154 LivenessKind
Kind() { return kStrong
; }
155 bool NeedsFinalization() { return true; }
156 TracingStatus
NeedsTracing(NeedsTracingOption
) {
157 return TracingStatus::Unneeded();
159 void Accept(EdgeVisitor
* visitor
) { visitor
->VisitRefPtr(this); }
162 class OwnPtr
: public PtrEdge
{
164 explicit OwnPtr(Edge
* ptr
) : PtrEdge(ptr
) { }
165 bool IsOwnPtr() { return true; }
166 LivenessKind
Kind() { return kStrong
; }
167 bool NeedsFinalization() { return true; }
168 TracingStatus
NeedsTracing(NeedsTracingOption
) {
169 return TracingStatus::Unneeded();
171 void Accept(EdgeVisitor
* visitor
) { visitor
->VisitOwnPtr(this); }
174 class Member
: public PtrEdge
{
176 explicit Member(Edge
* ptr
) : PtrEdge(ptr
) { }
177 bool IsMember() { return true; }
178 LivenessKind
Kind() { return kStrong
; }
179 bool NeedsFinalization() { return false; }
180 TracingStatus
NeedsTracing(NeedsTracingOption
) {
181 return TracingStatus::Needed();
183 void Accept(EdgeVisitor
* visitor
) { visitor
->VisitMember(this); }
186 class WeakMember
: public PtrEdge
{
188 explicit WeakMember(Edge
* ptr
) : PtrEdge(ptr
) { }
189 bool IsWeakMember() { return true; }
190 LivenessKind
Kind() { return kWeak
; }
191 bool NeedsFinalization() { return false; }
192 TracingStatus
NeedsTracing(NeedsTracingOption
) {
193 return TracingStatus::Needed();
195 void Accept(EdgeVisitor
* visitor
) { visitor
->VisitWeakMember(this); }
198 class Persistent
: public PtrEdge
{
200 explicit Persistent(Edge
* ptr
) : PtrEdge(ptr
) { }
201 bool IsPersistent() { return true; }
202 LivenessKind
Kind() { return kRoot
; }
203 bool NeedsFinalization() { return true; }
204 TracingStatus
NeedsTracing(NeedsTracingOption
) {
205 return TracingStatus::Unneeded();
207 void Accept(EdgeVisitor
* visitor
) { visitor
->VisitPersistent(this); }
210 class Collection
: public Edge
{
212 typedef std::vector
<Edge
*> Members
;
213 Collection(RecordInfo
* info
, bool on_heap
, bool is_root
)
218 for (Members::iterator it
= members_
.begin(); it
!= members_
.end(); ++it
) {
219 assert(*it
&& "Collection-edge members must be non-null");
223 bool IsCollection() { return true; }
224 LivenessKind
Kind() { return is_root_
? kRoot
: kStrong
; }
225 bool on_heap() { return on_heap_
; }
226 bool is_root() { return is_root_
; }
227 Members
& members() { return members_
; }
228 void Accept(EdgeVisitor
* visitor
) { visitor
->VisitCollection(this); }
229 void AcceptMembers(EdgeVisitor
* visitor
) {
230 for (Members::iterator it
= members_
.begin(); it
!= members_
.end(); ++it
)
231 (*it
)->Accept(visitor
);
233 bool NeedsFinalization();
234 TracingStatus
NeedsTracing(NeedsTracingOption
) {
236 return TracingStatus::Unneeded();
238 return TracingStatus::Needed();
239 // For off-heap collections, determine tracing status of members.
240 TracingStatus status
= TracingStatus::Unneeded();
241 for (Members::iterator it
= members_
.begin(); it
!= members_
.end(); ++it
) {
242 // Do a non-recursive test here since members could equal the holder.
243 status
= status
.LUB((*it
)->NeedsTracing(kNonRecursive
));
255 #endif // TOOLS_BLINK_GC_PLUGIN_EDGE_H_