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