• 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 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*) {}
VisitUniquePtr(UniquePtr *)35   virtual void VisitUniquePtr(UniquePtr*) {}
VisitMember(Member *)36   virtual void VisitMember(Member*) {}
VisitWeakMember(WeakMember *)37   virtual void VisitWeakMember(WeakMember*) {}
VisitPersistent(Persistent *)38   virtual void VisitPersistent(Persistent*) {}
VisitCrossThreadPersistent(CrossThreadPersistent *)39   virtual void VisitCrossThreadPersistent(CrossThreadPersistent*) {}
VisitCollection(Collection *)40   virtual void VisitCollection(Collection*) {}
VisitIterator(Iterator *)41   virtual void VisitIterator(Iterator*) {}
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 VisitUniquePtr(UniquePtr*) override;
52   void VisitMember(Member*) override;
53   void VisitWeakMember(WeakMember*) override;
54   void VisitPersistent(Persistent*) override;
55   void VisitCrossThreadPersistent(CrossThreadPersistent*) override;
56   void VisitCollection(Collection*) override;
57   void VisitIterator(Iterator*) 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 AtUniquePtr(UniquePtr*);
71   virtual void AtMember(Member*);
72   virtual void AtWeakMember(WeakMember*);
73   virtual void AtPersistent(Persistent*);
74   virtual void AtCrossThreadPersistent(CrossThreadPersistent*);
75   virtual void AtCollection(Collection*);
76   virtual void AtIterator(Iterator*);
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; }
IsUniquePtr()99   virtual bool IsUniquePtr() { return false; }
IsMember()100   virtual bool IsMember() { return false; }
IsWeakMember()101   virtual bool IsWeakMember() { return false; }
IsCollection()102   virtual bool IsCollection() { return false; }
103 };
104 
105 // A value edge is a direct edge to some type, eg, part-object edges.
106 class Value : public Edge {
107  public:
Value(RecordInfo * value)108   explicit Value(RecordInfo* value) : value_(value) {};
IsValue()109   bool IsValue() override { return true; }
Kind()110   LivenessKind Kind() override { return kStrong; }
111   bool NeedsFinalization() override;
112   TracingStatus NeedsTracing(NeedsTracingOption) override;
Accept(EdgeVisitor * visitor)113   void Accept(EdgeVisitor* visitor) override { visitor->VisitValue(this); }
value()114   RecordInfo* value() { return value_; }
115 
116  private:
117   RecordInfo* value_;
118 };
119 
120 // Shared base for smart-pointer edges.
121 class PtrEdge : public Edge {
122  public:
~PtrEdge()123   ~PtrEdge() { delete ptr_; }
ptr()124   Edge* ptr() { return ptr_; }
125  protected:
PtrEdge(Edge * ptr)126   PtrEdge(Edge* ptr) : ptr_(ptr) {
127     assert(ptr && "EdgePtr pointer must be non-null");
128   }
129  private:
130   Edge* ptr_;
131 };
132 
133 class RawPtr : public PtrEdge {
134  public:
RawPtr(Edge * ptr,bool is_ref_type)135   RawPtr(Edge* ptr, bool is_ref_type)
136       : PtrEdge(ptr)
137       , is_ref_type_(is_ref_type)
138   {
139   }
140 
IsRawPtr()141   bool IsRawPtr() override { return true; }
Kind()142   LivenessKind Kind() override { return kWeak; }
NeedsFinalization()143   bool NeedsFinalization() override { return false; }
NeedsTracing(NeedsTracingOption)144   TracingStatus NeedsTracing(NeedsTracingOption) override {
145     return TracingStatus::Illegal();
146   }
Accept(EdgeVisitor * visitor)147   void Accept(EdgeVisitor* visitor) override { visitor->VisitRawPtr(this); }
148 
HasReferenceType()149   bool HasReferenceType() { return is_ref_type_; }
150  private:
151   bool is_ref_type_;
152 };
153 
154 class RefPtr : public PtrEdge {
155  public:
RefPtr(Edge * ptr)156   explicit RefPtr(Edge* ptr) : PtrEdge(ptr) { }
IsRefPtr()157   bool IsRefPtr() override { return true; }
Kind()158   LivenessKind Kind() override { return kStrong; }
NeedsFinalization()159   bool NeedsFinalization() override { return true; }
NeedsTracing(NeedsTracingOption)160   TracingStatus NeedsTracing(NeedsTracingOption) override {
161     return TracingStatus::Illegal();
162   }
Accept(EdgeVisitor * visitor)163   void Accept(EdgeVisitor* visitor) override { visitor->VisitRefPtr(this); }
164 };
165 
166 class UniquePtr : public PtrEdge {
167  public:
UniquePtr(Edge * ptr)168   explicit UniquePtr(Edge* ptr) : PtrEdge(ptr) { }
IsUniquePtr()169   bool IsUniquePtr() override { return true; }
Kind()170   LivenessKind Kind() override { return kStrong; }
NeedsFinalization()171   bool NeedsFinalization() override { return true; }
NeedsTracing(NeedsTracingOption)172   TracingStatus NeedsTracing(NeedsTracingOption) override {
173     return TracingStatus::Illegal();
174   }
Accept(EdgeVisitor * visitor)175   void Accept(EdgeVisitor* visitor) override { visitor->VisitUniquePtr(this); }
176 };
177 
178 class Member : public PtrEdge {
179  public:
Member(Edge * ptr)180   explicit Member(Edge* ptr) : PtrEdge(ptr) { }
IsMember()181   bool IsMember() override { return true; }
Kind()182   LivenessKind Kind() override { return kStrong; }
NeedsFinalization()183   bool NeedsFinalization() override { return false; }
NeedsTracing(NeedsTracingOption)184   TracingStatus NeedsTracing(NeedsTracingOption) override {
185     return TracingStatus::Needed();
186   }
Accept(EdgeVisitor * visitor)187   void Accept(EdgeVisitor* visitor) override { visitor->VisitMember(this); }
188 };
189 
190 class WeakMember : public PtrEdge {
191  public:
WeakMember(Edge * ptr)192   explicit WeakMember(Edge* ptr) : PtrEdge(ptr) { }
IsWeakMember()193   bool IsWeakMember() override { return true; }
Kind()194   LivenessKind Kind() override { return kWeak; }
NeedsFinalization()195   bool NeedsFinalization() override { return false; }
NeedsTracing(NeedsTracingOption)196   TracingStatus NeedsTracing(NeedsTracingOption) override {
197     return TracingStatus::Needed();
198   }
Accept(EdgeVisitor * visitor)199   void Accept(EdgeVisitor* visitor) override { visitor->VisitWeakMember(this); }
200 };
201 
202 class Persistent : public PtrEdge {
203  public:
Persistent(Edge * ptr)204   explicit Persistent(Edge* ptr) : PtrEdge(ptr) { }
Kind()205   LivenessKind Kind() override { return kRoot; }
NeedsFinalization()206   bool NeedsFinalization() override { return true; }
NeedsTracing(NeedsTracingOption)207   TracingStatus NeedsTracing(NeedsTracingOption) override {
208     return TracingStatus::Unneeded();
209   }
Accept(EdgeVisitor * visitor)210   void Accept(EdgeVisitor* visitor) override { visitor->VisitPersistent(this); }
211 };
212 
213 class CrossThreadPersistent : public PtrEdge {
214  public:
CrossThreadPersistent(Edge * ptr)215   explicit CrossThreadPersistent(Edge* ptr) : PtrEdge(ptr) { }
Kind()216   LivenessKind Kind() override { return kRoot; }
NeedsFinalization()217   bool NeedsFinalization() override { return true; }
NeedsTracing(NeedsTracingOption)218   TracingStatus NeedsTracing(NeedsTracingOption) override {
219     return TracingStatus::Illegal();
220   }
Accept(EdgeVisitor * visitor)221   void Accept(EdgeVisitor* visitor) override {
222     visitor->VisitCrossThreadPersistent(this);
223   }
224 };
225 
226 class Collection : public Edge {
227  public:
228   typedef std::vector<Edge*> Members;
Collection(RecordInfo * info,bool on_heap,bool is_root)229   Collection(RecordInfo* info, bool on_heap, bool is_root)
230       : info_(info),
231         on_heap_(on_heap),
232         is_root_(is_root) {}
~Collection()233   ~Collection() {
234     for (Members::iterator it = members_.begin(); it != members_.end(); ++it) {
235       assert(*it && "Collection-edge members must be non-null");
236       delete *it;
237     }
238   }
IsCollection()239   bool IsCollection() override { return true; }
Kind()240   LivenessKind Kind() override { return is_root_ ? kRoot : kStrong; }
on_heap()241   bool on_heap() { return on_heap_; }
is_root()242   bool is_root() { return is_root_; }
members()243   Members& members() { return members_; }
Accept(EdgeVisitor * visitor)244   void Accept(EdgeVisitor* visitor) override { visitor->VisitCollection(this); }
AcceptMembers(EdgeVisitor * visitor)245   void AcceptMembers(EdgeVisitor* visitor) {
246     for (Members::iterator it = members_.begin(); it != members_.end(); ++it)
247       (*it)->Accept(visitor);
248   }
249   bool NeedsFinalization() override;
NeedsTracing(NeedsTracingOption)250   TracingStatus NeedsTracing(NeedsTracingOption) override {
251     if (is_root_)
252       return TracingStatus::Unneeded();
253     if (on_heap_)
254       return TracingStatus::Needed();
255     // For off-heap collections, determine tracing status of members.
256     TracingStatus status = TracingStatus::Unneeded();
257     for (Members::iterator it = members_.begin(); it != members_.end(); ++it) {
258       // Do a non-recursive test here since members could equal the holder.
259       status = status.LUB((*it)->NeedsTracing(kNonRecursive));
260     }
261     return status;
262   }
263 
264  private:
265   RecordInfo* info_;
266   Members members_;
267   bool on_heap_;
268   bool is_root_;
269 };
270 
271 // An iterator edge is a direct edge to some iterator type.
272 class Iterator : public Edge {
273  public:
Iterator(RecordInfo * info,bool on_heap,bool is_unsafe)274   Iterator(RecordInfo* info, bool on_heap, bool is_unsafe)
275       : info_(info), on_heap_(on_heap), is_unsafe_(is_unsafe) {}
~Iterator()276   ~Iterator() {}
277 
Accept(EdgeVisitor * visitor)278   void Accept(EdgeVisitor* visitor) override { visitor->VisitIterator(this); }
Kind()279   LivenessKind Kind() override { return kStrong; }
NeedsFinalization()280   bool NeedsFinalization() override { return false; }
NeedsTracing(NeedsTracingOption)281   TracingStatus NeedsTracing(NeedsTracingOption) override {
282     if (on_heap_)
283       return TracingStatus::Needed();
284     return TracingStatus::Unneeded();
285   }
286 
info()287   RecordInfo* info() const { return info_; }
288 
IsUnsafe()289   bool IsUnsafe() const { return is_unsafe_; }
290 
291  private:
292   RecordInfo* info_;
293   bool on_heap_;
294   bool is_unsafe_;
295 };
296 
297 #endif  // TOOLS_BLINK_GC_PLUGIN_EDGE_H_
298