Edge.h 9.9 KB

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