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