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 OwnPtr; 22 class Persistent; 23 class RawPtr; 24 class RefPtr; 25 class UniquePtr; 26 class Value; 27 class WeakMember; 28 29 // Bare-bones visitor. 30 class EdgeVisitor { 31 public: 32 virtual ~EdgeVisitor() {} 33 virtual void VisitValue(Value*) {} 34 virtual void VisitRawPtr(RawPtr*) {} 35 virtual void VisitRefPtr(RefPtr*) {} 36 virtual void VisitOwnPtr(OwnPtr*) {} 37 virtual void VisitUniquePtr(UniquePtr*) {} 38 virtual void VisitMember(Member*) {} 39 virtual void VisitWeakMember(WeakMember*) {} 40 virtual void VisitPersistent(Persistent*) {} 41 virtual void VisitCrossThreadPersistent(CrossThreadPersistent*) {} 42 virtual void VisitCollection(Collection*) {} 43 virtual void VisitIterator(Iterator*) {} 44 }; 45 46 // Recursive edge visitor. The traversed path is accessible in context. 47 class RecursiveEdgeVisitor : public EdgeVisitor { 48 public: 49 // Overrides that recursively walk the edges and record the path. 50 void VisitValue(Value*) override; 51 void VisitRawPtr(RawPtr*) override; 52 void VisitRefPtr(RefPtr*) override; 53 void VisitOwnPtr(OwnPtr*) override; 54 void VisitUniquePtr(UniquePtr*) override; 55 void VisitMember(Member*) override; 56 void VisitWeakMember(WeakMember*) override; 57 void VisitPersistent(Persistent*) override; 58 void VisitCrossThreadPersistent(CrossThreadPersistent*) override; 59 void VisitCollection(Collection*) override; 60 void VisitIterator(Iterator*) override; 61 62 protected: 63 typedef std::deque<Edge*> Context; 64 Context& context() { return context_; } 65 Edge* Parent() { return context_.empty() ? 0 : context_.front(); } 66 void Enter(Edge* e) { return context_.push_front(e); } 67 void Leave() { context_.pop_front(); } 68 69 // Default callback to overwrite in visitor subclass. 70 virtual void AtValue(Value*); 71 virtual void AtRawPtr(RawPtr*); 72 virtual void AtRefPtr(RefPtr*); 73 virtual void AtOwnPtr(OwnPtr*); 74 virtual void AtUniquePtr(UniquePtr*); 75 virtual void AtMember(Member*); 76 virtual void AtWeakMember(WeakMember*); 77 virtual void AtPersistent(Persistent*); 78 virtual void AtCrossThreadPersistent(CrossThreadPersistent*); 79 virtual void AtCollection(Collection*); 80 virtual void AtIterator(Iterator*); 81 82 private: 83 Context context_; 84 }; 85 86 // Base class for all edges. 87 class Edge { 88 public: 89 enum NeedsTracingOption { kRecursive, kNonRecursive }; 90 enum LivenessKind { kWeak, kStrong, kRoot }; 91 92 virtual ~Edge() {} 93 virtual LivenessKind Kind() = 0; 94 virtual void Accept(EdgeVisitor*) = 0; 95 virtual bool NeedsFinalization() = 0; 96 virtual TracingStatus NeedsTracing(NeedsTracingOption) { 97 return TracingStatus::Unknown(); 98 } 99 100 virtual bool IsValue() { return false; } 101 virtual bool IsRawPtr() { return false; } 102 virtual bool IsRefPtr() { return false; } 103 virtual bool IsOwnPtr() { return false; } 104 virtual bool IsUniquePtr() { return false; } 105 virtual bool IsMember() { return false; } 106 virtual bool IsWeakMember() { return false; } 107 virtual bool IsCollection() { return false; } 108 }; 109 110 // A value edge is a direct edge to some type, eg, part-object edges. 111 class Value : public Edge { 112 public: 113 explicit Value(RecordInfo* value) : value_(value) {}; 114 bool IsValue() override { return true; } 115 LivenessKind Kind() override { return kStrong; } 116 bool NeedsFinalization() override; 117 TracingStatus NeedsTracing(NeedsTracingOption) override; 118 void Accept(EdgeVisitor* visitor) override { visitor->VisitValue(this); } 119 RecordInfo* value() { return value_; } 120 121 private: 122 RecordInfo* value_; 123 }; 124 125 // Shared base for smart-pointer edges. 126 class PtrEdge : public Edge { 127 public: 128 ~PtrEdge() { delete ptr_; } 129 Edge* ptr() { return ptr_; } 130 protected: 131 PtrEdge(Edge* ptr) : ptr_(ptr) { 132 assert(ptr && "EdgePtr pointer must be non-null"); 133 } 134 private: 135 Edge* ptr_; 136 }; 137 138 class RawPtr : public PtrEdge { 139 public: 140 RawPtr(Edge* ptr, bool is_ref_type) 141 : PtrEdge(ptr) 142 , is_ref_type_(is_ref_type) 143 { 144 } 145 146 bool IsRawPtr() { return true; } 147 LivenessKind Kind() { return kWeak; } 148 bool NeedsFinalization() { return false; } 149 TracingStatus NeedsTracing(NeedsTracingOption) { 150 return TracingStatus::Illegal(); 151 } 152 void Accept(EdgeVisitor* visitor) { visitor->VisitRawPtr(this); } 153 154 bool HasReferenceType() { return is_ref_type_; } 155 private: 156 bool is_ref_type_; 157 }; 158 159 class RefPtr : public PtrEdge { 160 public: 161 explicit RefPtr(Edge* ptr) : PtrEdge(ptr) { } 162 bool IsRefPtr() { return true; } 163 LivenessKind Kind() { return kStrong; } 164 bool NeedsFinalization() { return true; } 165 TracingStatus NeedsTracing(NeedsTracingOption) { 166 return TracingStatus::Illegal(); 167 } 168 void Accept(EdgeVisitor* visitor) { visitor->VisitRefPtr(this); } 169 }; 170 171 class OwnPtr : public PtrEdge { 172 public: 173 explicit OwnPtr(Edge* ptr) : PtrEdge(ptr) { } 174 bool IsOwnPtr() { return true; } 175 LivenessKind Kind() { return kStrong; } 176 bool NeedsFinalization() { return true; } 177 TracingStatus NeedsTracing(NeedsTracingOption) { 178 return TracingStatus::Illegal(); 179 } 180 void Accept(EdgeVisitor* visitor) { visitor->VisitOwnPtr(this); } 181 }; 182 183 class UniquePtr : public PtrEdge { 184 public: 185 explicit UniquePtr(Edge* ptr) : PtrEdge(ptr) { } 186 bool IsUniquePtr() { return true; } 187 LivenessKind Kind() { return kStrong; } 188 bool NeedsFinalization() { return true; } 189 TracingStatus NeedsTracing(NeedsTracingOption) { 190 return TracingStatus::Illegal(); 191 } 192 void Accept(EdgeVisitor* visitor) { visitor->VisitUniquePtr(this); } 193 }; 194 195 class Member : public PtrEdge { 196 public: 197 explicit Member(Edge* ptr) : PtrEdge(ptr) { } 198 bool IsMember() { return true; } 199 LivenessKind Kind() { return kStrong; } 200 bool NeedsFinalization() { return false; } 201 TracingStatus NeedsTracing(NeedsTracingOption) { 202 return TracingStatus::Needed(); 203 } 204 void Accept(EdgeVisitor* visitor) { visitor->VisitMember(this); } 205 }; 206 207 class WeakMember : public PtrEdge { 208 public: 209 explicit WeakMember(Edge* ptr) : PtrEdge(ptr) { } 210 bool IsWeakMember() { return true; } 211 LivenessKind Kind() { return kWeak; } 212 bool NeedsFinalization() { return false; } 213 TracingStatus NeedsTracing(NeedsTracingOption) { 214 return TracingStatus::Needed(); 215 } 216 void Accept(EdgeVisitor* visitor) { visitor->VisitWeakMember(this); } 217 }; 218 219 class Persistent : public PtrEdge { 220 public: 221 explicit Persistent(Edge* ptr) : PtrEdge(ptr) { } 222 LivenessKind Kind() { return kRoot; } 223 bool NeedsFinalization() { return true; } 224 TracingStatus NeedsTracing(NeedsTracingOption) { 225 return TracingStatus::Unneeded(); 226 } 227 void Accept(EdgeVisitor* visitor) { visitor->VisitPersistent(this); } 228 }; 229 230 class CrossThreadPersistent : public PtrEdge { 231 public: 232 explicit CrossThreadPersistent(Edge* ptr) : PtrEdge(ptr) { } 233 LivenessKind Kind() { return kRoot; } 234 bool NeedsFinalization() { return true; } 235 TracingStatus NeedsTracing(NeedsTracingOption) { 236 return TracingStatus::Illegal(); 237 } 238 void Accept(EdgeVisitor* visitor) { 239 visitor->VisitCrossThreadPersistent(this); 240 } 241 }; 242 243 class Collection : public Edge { 244 public: 245 typedef std::vector<Edge*> Members; 246 Collection(RecordInfo* info, bool on_heap, bool is_root) 247 : info_(info), 248 on_heap_(on_heap), 249 is_root_(is_root) {} 250 ~Collection() { 251 for (Members::iterator it = members_.begin(); it != members_.end(); ++it) { 252 assert(*it && "Collection-edge members must be non-null"); 253 delete *it; 254 } 255 } 256 bool IsCollection() { return true; } 257 LivenessKind Kind() { return is_root_ ? kRoot : kStrong; } 258 bool on_heap() { return on_heap_; } 259 bool is_root() { return is_root_; } 260 Members& members() { return members_; } 261 void Accept(EdgeVisitor* visitor) { visitor->VisitCollection(this); } 262 void AcceptMembers(EdgeVisitor* visitor) { 263 for (Members::iterator it = members_.begin(); it != members_.end(); ++it) 264 (*it)->Accept(visitor); 265 } 266 bool NeedsFinalization(); 267 TracingStatus NeedsTracing(NeedsTracingOption) { 268 if (is_root_) 269 return TracingStatus::Unneeded(); 270 if (on_heap_) 271 return TracingStatus::Needed(); 272 // For off-heap collections, determine tracing status of members. 273 TracingStatus status = TracingStatus::Unneeded(); 274 for (Members::iterator it = members_.begin(); it != members_.end(); ++it) { 275 // Do a non-recursive test here since members could equal the holder. 276 status = status.LUB((*it)->NeedsTracing(kNonRecursive)); 277 } 278 return status; 279 } 280 281 private: 282 RecordInfo* info_; 283 Members members_; 284 bool on_heap_; 285 bool is_root_; 286 }; 287 288 // An iterator edge is a direct edge to some iterator type. 289 class Iterator : public Edge { 290 public: 291 Iterator(RecordInfo* info, bool on_heap, bool is_unsafe) 292 : info_(info), on_heap_(on_heap), is_unsafe_(is_unsafe) {} 293 ~Iterator() {} 294 295 void Accept(EdgeVisitor* visitor) { visitor->VisitIterator(this); } 296 LivenessKind Kind() override { return kStrong; } 297 bool NeedsFinalization() { return false; } 298 TracingStatus NeedsTracing(NeedsTracingOption) { 299 if (on_heap_) 300 return TracingStatus::Needed(); 301 return TracingStatus::Unneeded(); 302 } 303 304 RecordInfo* info() const { return info_; } 305 306 bool IsUnsafe() const { return is_unsafe_; } 307 308 private: 309 RecordInfo* info_; 310 bool on_heap_; 311 bool is_unsafe_; 312 }; 313 314 #endif // TOOLS_BLINK_GC_PLUGIN_EDGE_H_ 315