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