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