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_
12 #include "TracingStatus.h"
26 // Bare-bones visitor.
29 virtual ~EdgeVisitor() {}
30 virtual void VisitValue(Value
*) {}
31 virtual void VisitRawPtr(RawPtr
*) {}
32 virtual void VisitRefPtr(RefPtr
*) {}
33 virtual void VisitOwnPtr(OwnPtr
*) {}
34 virtual void VisitMember(Member
*) {}
35 virtual void VisitWeakMember(WeakMember
*) {}
36 virtual void VisitPersistent(Persistent
*) {}
37 virtual void VisitCollection(Collection
*) {}
40 // Recursive edge visitor. The traversed path is accessible in context.
41 class RecursiveEdgeVisitor
: public EdgeVisitor
{
43 // Overrides that recursively walk the edges and record the path.
44 void VisitValue(Value
*) override
;
45 void VisitRawPtr(RawPtr
*) override
;
46 void VisitRefPtr(RefPtr
*) override
;
47 void VisitOwnPtr(OwnPtr
*) override
;
48 void VisitMember(Member
*) override
;
49 void VisitWeakMember(WeakMember
*) override
;
50 void VisitPersistent(Persistent
*) override
;
51 void VisitCollection(Collection
*) override
;
54 typedef std::deque
<Edge
*> Context
;
55 Context
& context() { return context_
; }
56 Edge
* Parent() { return context_
.empty() ? 0 : context_
.front(); }
57 void Enter(Edge
* e
) { return context_
.push_front(e
); }
58 void Leave() { context_
.pop_front(); }
60 // Default callback to overwrite in visitor subclass.
61 virtual void AtValue(Value
*);
62 virtual void AtRawPtr(RawPtr
*);
63 virtual void AtRefPtr(RefPtr
*);
64 virtual void AtOwnPtr(OwnPtr
*);
65 virtual void AtMember(Member
*);
66 virtual void AtWeakMember(WeakMember
*);
67 virtual void AtPersistent(Persistent
*);
68 virtual void AtCollection(Collection
*);
74 // Base class for all edges.
77 enum NeedsTracingOption
{ kRecursive
, kNonRecursive
};
78 enum LivenessKind
{ kWeak
, kStrong
, kRoot
};
81 virtual LivenessKind
Kind() = 0;
82 virtual void Accept(EdgeVisitor
*) = 0;
83 virtual bool NeedsFinalization() = 0;
84 virtual TracingStatus
NeedsTracing(NeedsTracingOption
) {
85 return TracingStatus::Unknown();
88 virtual bool IsValue() { return false; }
89 virtual bool IsRawPtr() { return false; }
90 virtual bool IsRawPtrClass() { return false; }
91 virtual bool IsRefPtr() { return false; }
92 virtual bool IsOwnPtr() { return false; }
93 virtual bool IsMember() { return false; }
94 virtual bool IsWeakMember() { return false; }
95 virtual bool IsPersistent() { return false; }
96 virtual bool IsCollection() { return false; }
99 // A value edge is a direct edge to some type, eg, part-object edges.
100 class Value
: public Edge
{
102 explicit Value(RecordInfo
* value
) : value_(value
) {};
103 bool IsValue() override
{ return true; }
104 LivenessKind
Kind() override
{ return kStrong
; }
105 bool NeedsFinalization() override
;
106 TracingStatus
NeedsTracing(NeedsTracingOption
) override
;
107 void Accept(EdgeVisitor
* visitor
) override
{ visitor
->VisitValue(this); }
108 RecordInfo
* value() { return value_
; }
114 // Shared base for smart-pointer edges.
115 class PtrEdge
: public Edge
{
117 ~PtrEdge() { delete ptr_
; }
118 Edge
* ptr() { return ptr_
; }
120 PtrEdge(Edge
* ptr
) : ptr_(ptr
) {
121 assert(ptr
&& "EdgePtr pointer must be non-null");
127 class RawPtr
: public PtrEdge
{
129 RawPtr(Edge
* ptr
, bool is_ptr_class
, bool is_ref_type
)
131 , is_ptr_class_(is_ptr_class
)
132 , is_ref_type_(is_ref_type
)
134 assert(!(is_ptr_class_
&& is_ref_type_
));
137 bool IsRawPtr() { return true; }
138 bool IsRawPtrClass() { return is_ptr_class_
; }
139 LivenessKind
Kind() { return kWeak
; }
140 bool NeedsFinalization() { return false; }
141 TracingStatus
NeedsTracing(NeedsTracingOption
) {
142 return TracingStatus::Unneeded();
144 void Accept(EdgeVisitor
* visitor
) { visitor
->VisitRawPtr(this); }
146 bool HasReferenceType() { return is_ref_type_
; }
152 class RefPtr
: public PtrEdge
{
154 explicit RefPtr(Edge
* ptr
) : PtrEdge(ptr
) { }
155 bool IsRefPtr() { return true; }
156 LivenessKind
Kind() { return kStrong
; }
157 bool NeedsFinalization() { return true; }
158 TracingStatus
NeedsTracing(NeedsTracingOption
) {
159 return TracingStatus::Unneeded();
161 void Accept(EdgeVisitor
* visitor
) { visitor
->VisitRefPtr(this); }
164 class OwnPtr
: public PtrEdge
{
166 explicit OwnPtr(Edge
* ptr
) : PtrEdge(ptr
) { }
167 bool IsOwnPtr() { return true; }
168 LivenessKind
Kind() { return kStrong
; }
169 bool NeedsFinalization() { return true; }
170 TracingStatus
NeedsTracing(NeedsTracingOption
) {
171 return TracingStatus::Unneeded();
173 void Accept(EdgeVisitor
* visitor
) { visitor
->VisitOwnPtr(this); }
176 class Member
: public PtrEdge
{
178 explicit Member(Edge
* ptr
) : PtrEdge(ptr
) { }
179 bool IsMember() { return true; }
180 LivenessKind
Kind() { return kStrong
; }
181 bool NeedsFinalization() { return false; }
182 TracingStatus
NeedsTracing(NeedsTracingOption
) {
183 return TracingStatus::Needed();
185 void Accept(EdgeVisitor
* visitor
) { visitor
->VisitMember(this); }
188 class WeakMember
: public PtrEdge
{
190 explicit WeakMember(Edge
* ptr
) : PtrEdge(ptr
) { }
191 bool IsWeakMember() { return true; }
192 LivenessKind
Kind() { return kWeak
; }
193 bool NeedsFinalization() { return false; }
194 TracingStatus
NeedsTracing(NeedsTracingOption
) {
195 return TracingStatus::Needed();
197 void Accept(EdgeVisitor
* visitor
) { visitor
->VisitWeakMember(this); }
200 class Persistent
: public PtrEdge
{
202 explicit Persistent(Edge
* ptr
) : PtrEdge(ptr
) { }
203 bool IsPersistent() { return true; }
204 LivenessKind
Kind() { return kRoot
; }
205 bool NeedsFinalization() { return true; }
206 TracingStatus
NeedsTracing(NeedsTracingOption
) {
207 return TracingStatus::Unneeded();
209 void Accept(EdgeVisitor
* visitor
) { visitor
->VisitPersistent(this); }
212 class Collection
: public Edge
{
214 typedef std::vector
<Edge
*> Members
;
215 Collection(RecordInfo
* info
, bool on_heap
, bool is_root
)
220 for (Members::iterator it
= members_
.begin(); it
!= members_
.end(); ++it
) {
221 assert(*it
&& "Collection-edge members must be non-null");
225 bool IsCollection() { return true; }
226 LivenessKind
Kind() { return is_root_
? kRoot
: kStrong
; }
227 bool on_heap() { return on_heap_
; }
228 bool is_root() { return is_root_
; }
229 Members
& members() { return members_
; }
230 void Accept(EdgeVisitor
* visitor
) { visitor
->VisitCollection(this); }
231 void AcceptMembers(EdgeVisitor
* visitor
) {
232 for (Members::iterator it
= members_
.begin(); it
!= members_
.end(); ++it
)
233 (*it
)->Accept(visitor
);
235 bool NeedsFinalization();
236 TracingStatus
NeedsTracing(NeedsTracingOption
) {
238 return TracingStatus::Unneeded();
240 return TracingStatus::Needed();
241 // For off-heap collections, determine tracing status of members.
242 TracingStatus status
= TracingStatus::Unneeded();
243 for (Members::iterator it
= members_
.begin(); it
!= members_
.end(); ++it
) {
244 // Do a non-recursive test here since members could equal the holder.
245 status
= status
.LUB((*it
)->NeedsTracing(kNonRecursive
));
257 #endif // TOOLS_BLINK_GC_PLUGIN_EDGE_H_