• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #ifndef TOOLS_BLINK_GC_PLUGIN_EDGE_H_
6 #define TOOLS_BLINK_GC_PLUGIN_EDGE_H_
7 
8 #include <cassert>
9 #include <deque>
10 #include <vector>
11 
12 #include "TracingStatus.h"
13 
14 class RecordInfo;
15 
16 class Edge;
17 class Collection;
18 class CrossThreadPersistent;
19 class Iterator;
20 class Member;
21 class OwnPtr;
22 class Persistent;
23 class RawPtr;
24 class RefPtr;
25 class UniquePtr;
26 class Value;
27 class WeakMember;
28 
29 // Bare-bones visitor.
30 class EdgeVisitor {
31  public:
~EdgeVisitor()32   virtual ~EdgeVisitor() {}
VisitValue(Value *)33   virtual void VisitValue(Value*) {}
VisitRawPtr(RawPtr *)34   virtual void VisitRawPtr(RawPtr*) {}
VisitRefPtr(RefPtr *)35   virtual void VisitRefPtr(RefPtr*) {}
VisitOwnPtr(OwnPtr *)36   virtual void VisitOwnPtr(OwnPtr*) {}
VisitUniquePtr(UniquePtr *)37   virtual void VisitUniquePtr(UniquePtr*) {}
VisitMember(Member *)38   virtual void VisitMember(Member*) {}
VisitWeakMember(WeakMember *)39   virtual void VisitWeakMember(WeakMember*) {}
VisitPersistent(Persistent *)40   virtual void VisitPersistent(Persistent*) {}
VisitCrossThreadPersistent(CrossThreadPersistent *)41   virtual void VisitCrossThreadPersistent(CrossThreadPersistent*) {}
VisitCollection(Collection *)42   virtual void VisitCollection(Collection*) {}
VisitIterator(Iterator *)43   virtual void VisitIterator(Iterator*) {}
44 };
45 
46 // Recursive edge visitor. The traversed path is accessible in context.
47 class RecursiveEdgeVisitor : public EdgeVisitor {
48  public:
49   // Overrides that recursively walk the edges and record the path.
50   void VisitValue(Value*) override;
51   void VisitRawPtr(RawPtr*) override;
52   void VisitRefPtr(RefPtr*) override;
53   void VisitOwnPtr(OwnPtr*) override;
54   void VisitUniquePtr(UniquePtr*) override;
55   void VisitMember(Member*) override;
56   void VisitWeakMember(WeakMember*) override;
57   void VisitPersistent(Persistent*) override;
58   void VisitCrossThreadPersistent(CrossThreadPersistent*) override;
59   void VisitCollection(Collection*) override;
60   void VisitIterator(Iterator*) override;
61 
62  protected:
63   typedef std::deque<Edge*> Context;
context()64   Context& context() { return context_; }
Parent()65   Edge* Parent() { return context_.empty() ? 0 : context_.front(); }
Enter(Edge * e)66   void Enter(Edge* e) { return context_.push_front(e); }
Leave()67   void Leave() { context_.pop_front(); }
68 
69   // Default callback to overwrite in visitor subclass.
70   virtual void AtValue(Value*);
71   virtual void AtRawPtr(RawPtr*);
72   virtual void AtRefPtr(RefPtr*);
73   virtual void AtOwnPtr(OwnPtr*);
74   virtual void AtUniquePtr(UniquePtr*);
75   virtual void AtMember(Member*);
76   virtual void AtWeakMember(WeakMember*);
77   virtual void AtPersistent(Persistent*);
78   virtual void AtCrossThreadPersistent(CrossThreadPersistent*);
79   virtual void AtCollection(Collection*);
80   virtual void AtIterator(Iterator*);
81 
82  private:
83   Context context_;
84 };
85 
86 // Base class for all edges.
87 class Edge {
88  public:
89   enum NeedsTracingOption { kRecursive, kNonRecursive };
90   enum LivenessKind { kWeak, kStrong, kRoot };
91 
~Edge()92   virtual ~Edge() {}
93   virtual LivenessKind Kind() = 0;
94   virtual void Accept(EdgeVisitor*) = 0;
95   virtual bool NeedsFinalization() = 0;
NeedsTracing(NeedsTracingOption)96   virtual TracingStatus NeedsTracing(NeedsTracingOption) {
97     return TracingStatus::Unknown();
98   }
99 
IsValue()100   virtual bool IsValue() { return false; }
IsRawPtr()101   virtual bool IsRawPtr() { return false; }
IsRefPtr()102   virtual bool IsRefPtr() { return false; }
IsOwnPtr()103   virtual bool IsOwnPtr() { return false; }
IsUniquePtr()104   virtual bool IsUniquePtr() { return false; }
IsMember()105   virtual bool IsMember() { return false; }
IsWeakMember()106   virtual bool IsWeakMember() { return false; }
IsCollection()107   virtual bool IsCollection() { return false; }
108 };
109 
110 // A value edge is a direct edge to some type, eg, part-object edges.
111 class Value : public Edge {
112  public:
Value(RecordInfo * value)113   explicit Value(RecordInfo* value) : value_(value) {};
IsValue()114   bool IsValue() override { return true; }
Kind()115   LivenessKind Kind() override { return kStrong; }
116   bool NeedsFinalization() override;
117   TracingStatus NeedsTracing(NeedsTracingOption) override;
Accept(EdgeVisitor * visitor)118   void Accept(EdgeVisitor* visitor) override { visitor->VisitValue(this); }
value()119   RecordInfo* value() { return value_; }
120 
121  private:
122   RecordInfo* value_;
123 };
124 
125 // Shared base for smart-pointer edges.
126 class PtrEdge : public Edge {
127  public:
~PtrEdge()128   ~PtrEdge() { delete ptr_; }
ptr()129   Edge* ptr() { return ptr_; }
130  protected:
PtrEdge(Edge * ptr)131   PtrEdge(Edge* ptr) : ptr_(ptr) {
132     assert(ptr && "EdgePtr pointer must be non-null");
133   }
134  private:
135   Edge* ptr_;
136 };
137 
138 class RawPtr : public PtrEdge {
139  public:
RawPtr(Edge * ptr,bool is_ref_type)140   RawPtr(Edge* ptr, bool is_ref_type)
141       : PtrEdge(ptr)
142       , is_ref_type_(is_ref_type)
143   {
144   }
145 
IsRawPtr()146   bool IsRawPtr() { return true; }
Kind()147   LivenessKind Kind() { return kWeak; }
NeedsFinalization()148   bool NeedsFinalization() { return false; }
NeedsTracing(NeedsTracingOption)149   TracingStatus NeedsTracing(NeedsTracingOption) {
150     return TracingStatus::Illegal();
151   }
Accept(EdgeVisitor * visitor)152   void Accept(EdgeVisitor* visitor) { visitor->VisitRawPtr(this); }
153 
HasReferenceType()154   bool HasReferenceType() { return is_ref_type_; }
155  private:
156   bool is_ref_type_;
157 };
158 
159 class RefPtr : public PtrEdge {
160  public:
RefPtr(Edge * ptr)161   explicit RefPtr(Edge* ptr) : PtrEdge(ptr) { }
IsRefPtr()162   bool IsRefPtr() { return true; }
Kind()163   LivenessKind Kind() { return kStrong; }
NeedsFinalization()164   bool NeedsFinalization() { return true; }
NeedsTracing(NeedsTracingOption)165   TracingStatus NeedsTracing(NeedsTracingOption) {
166     return TracingStatus::Illegal();
167   }
Accept(EdgeVisitor * visitor)168   void Accept(EdgeVisitor* visitor) { visitor->VisitRefPtr(this); }
169 };
170 
171 class OwnPtr : public PtrEdge {
172  public:
OwnPtr(Edge * ptr)173   explicit OwnPtr(Edge* ptr) : PtrEdge(ptr) { }
IsOwnPtr()174   bool IsOwnPtr() { return true; }
Kind()175   LivenessKind Kind() { return kStrong; }
NeedsFinalization()176   bool NeedsFinalization() { return true; }
NeedsTracing(NeedsTracingOption)177   TracingStatus NeedsTracing(NeedsTracingOption) {
178     return TracingStatus::Illegal();
179   }
Accept(EdgeVisitor * visitor)180   void Accept(EdgeVisitor* visitor) { visitor->VisitOwnPtr(this); }
181 };
182 
183 class UniquePtr : public PtrEdge {
184  public:
UniquePtr(Edge * ptr)185   explicit UniquePtr(Edge* ptr) : PtrEdge(ptr) { }
IsUniquePtr()186   bool IsUniquePtr() { return true; }
Kind()187   LivenessKind Kind() { return kStrong; }
NeedsFinalization()188   bool NeedsFinalization() { return true; }
NeedsTracing(NeedsTracingOption)189   TracingStatus NeedsTracing(NeedsTracingOption) {
190     return TracingStatus::Illegal();
191   }
Accept(EdgeVisitor * visitor)192   void Accept(EdgeVisitor* visitor) { visitor->VisitUniquePtr(this); }
193 };
194 
195 class Member : public PtrEdge {
196  public:
Member(Edge * ptr)197   explicit Member(Edge* ptr) : PtrEdge(ptr) { }
IsMember()198   bool IsMember() { return true; }
Kind()199   LivenessKind Kind() { return kStrong; }
NeedsFinalization()200   bool NeedsFinalization() { return false; }
NeedsTracing(NeedsTracingOption)201   TracingStatus NeedsTracing(NeedsTracingOption) {
202     return TracingStatus::Needed();
203   }
Accept(EdgeVisitor * visitor)204   void Accept(EdgeVisitor* visitor) { visitor->VisitMember(this); }
205 };
206 
207 class WeakMember : public PtrEdge {
208  public:
WeakMember(Edge * ptr)209   explicit WeakMember(Edge* ptr) : PtrEdge(ptr) { }
IsWeakMember()210   bool IsWeakMember() { return true; }
Kind()211   LivenessKind Kind() { return kWeak; }
NeedsFinalization()212   bool NeedsFinalization() { return false; }
NeedsTracing(NeedsTracingOption)213   TracingStatus NeedsTracing(NeedsTracingOption) {
214     return TracingStatus::Needed();
215   }
Accept(EdgeVisitor * visitor)216   void Accept(EdgeVisitor* visitor) { visitor->VisitWeakMember(this); }
217 };
218 
219 class Persistent : public PtrEdge {
220  public:
Persistent(Edge * ptr)221   explicit Persistent(Edge* ptr) : PtrEdge(ptr) { }
Kind()222   LivenessKind Kind() { return kRoot; }
NeedsFinalization()223   bool NeedsFinalization() { return true; }
NeedsTracing(NeedsTracingOption)224   TracingStatus NeedsTracing(NeedsTracingOption) {
225     return TracingStatus::Unneeded();
226   }
Accept(EdgeVisitor * visitor)227   void Accept(EdgeVisitor* visitor) { visitor->VisitPersistent(this); }
228 };
229 
230 class CrossThreadPersistent : public PtrEdge {
231  public:
CrossThreadPersistent(Edge * ptr)232   explicit CrossThreadPersistent(Edge* ptr) : PtrEdge(ptr) { }
Kind()233   LivenessKind Kind() { return kRoot; }
NeedsFinalization()234   bool NeedsFinalization() { return true; }
NeedsTracing(NeedsTracingOption)235   TracingStatus NeedsTracing(NeedsTracingOption) {
236     return TracingStatus::Illegal();
237   }
Accept(EdgeVisitor * visitor)238   void Accept(EdgeVisitor* visitor) {
239     visitor->VisitCrossThreadPersistent(this);
240   }
241 };
242 
243 class Collection : public Edge {
244  public:
245   typedef std::vector<Edge*> Members;
Collection(RecordInfo * info,bool on_heap,bool is_root)246   Collection(RecordInfo* info, bool on_heap, bool is_root)
247       : info_(info),
248         on_heap_(on_heap),
249         is_root_(is_root) {}
~Collection()250   ~Collection() {
251     for (Members::iterator it = members_.begin(); it != members_.end(); ++it) {
252       assert(*it && "Collection-edge members must be non-null");
253       delete *it;
254     }
255   }
IsCollection()256   bool IsCollection() { return true; }
Kind()257   LivenessKind Kind() { return is_root_ ? kRoot : kStrong; }
on_heap()258   bool on_heap() { return on_heap_; }
is_root()259   bool is_root() { return is_root_; }
members()260   Members& members() { return members_; }
Accept(EdgeVisitor * visitor)261   void Accept(EdgeVisitor* visitor) { visitor->VisitCollection(this); }
AcceptMembers(EdgeVisitor * visitor)262   void AcceptMembers(EdgeVisitor* visitor) {
263     for (Members::iterator it = members_.begin(); it != members_.end(); ++it)
264       (*it)->Accept(visitor);
265   }
266   bool NeedsFinalization();
NeedsTracing(NeedsTracingOption)267   TracingStatus NeedsTracing(NeedsTracingOption) {
268     if (is_root_)
269       return TracingStatus::Unneeded();
270     if (on_heap_)
271       return TracingStatus::Needed();
272     // For off-heap collections, determine tracing status of members.
273     TracingStatus status = TracingStatus::Unneeded();
274     for (Members::iterator it = members_.begin(); it != members_.end(); ++it) {
275       // Do a non-recursive test here since members could equal the holder.
276       status = status.LUB((*it)->NeedsTracing(kNonRecursive));
277     }
278     return status;
279   }
280 
281  private:
282   RecordInfo* info_;
283   Members members_;
284   bool on_heap_;
285   bool is_root_;
286 };
287 
288 // An iterator edge is a direct edge to some iterator type.
289 class Iterator : public Edge {
290  public:
Iterator(RecordInfo * info,bool on_heap,bool is_unsafe)291   Iterator(RecordInfo* info, bool on_heap, bool is_unsafe)
292       : info_(info), on_heap_(on_heap), is_unsafe_(is_unsafe) {}
~Iterator()293   ~Iterator() {}
294 
Accept(EdgeVisitor * visitor)295   void Accept(EdgeVisitor* visitor) { visitor->VisitIterator(this); }
Kind()296   LivenessKind Kind() override { return kStrong; }
NeedsFinalization()297   bool NeedsFinalization() { return false; }
NeedsTracing(NeedsTracingOption)298   TracingStatus NeedsTracing(NeedsTracingOption) {
299     if (on_heap_)
300       return TracingStatus::Needed();
301     return TracingStatus::Unneeded();
302   }
303 
info()304   RecordInfo* info() const { return info_; }
305 
IsUnsafe()306   bool IsUnsafe() const { return is_unsafe_; }
307 
308  private:
309   RecordInfo* info_;
310   bool on_heap_;
311   bool is_unsafe_;
312 };
313 
314 #endif  // TOOLS_BLINK_GC_PLUGIN_EDGE_H_
315