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