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