Index: tools/clang/blink_gc_plugin/Edge.h |
diff --git a/tools/clang/blink_gc_plugin/Edge.h b/tools/clang/blink_gc_plugin/Edge.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..eca3158d75f925e1b7430991838ad4bea890c058 |
--- /dev/null |
+++ b/tools/clang/blink_gc_plugin/Edge.h |
@@ -0,0 +1,257 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef TOOLS_BLINK_GC_PLUGIN_EDGE_H_ |
+#define TOOLS_BLINK_GC_PLUGIN_EDGE_H_ |
+ |
+#include <cassert> |
+#include <deque> |
+#include <vector> |
+ |
+#include "TracingStatus.h" |
+ |
+class RecordInfo; |
+ |
+class Edge; |
+class Value; |
+class RawPtr; |
+class RefPtr; |
+class OwnPtr; |
+class Member; |
+class WeakMember; |
+class Persistent; |
+class Collection; |
+ |
+// Bare-bones visitor. |
+class EdgeVisitor { |
+ public: |
+ virtual ~EdgeVisitor() {} |
+ virtual void VisitValue(Value*) {} |
+ virtual void VisitRawPtr(RawPtr*) {} |
+ virtual void VisitRefPtr(RefPtr*) {} |
+ virtual void VisitOwnPtr(OwnPtr*) {} |
+ virtual void VisitMember(Member*) {} |
+ virtual void VisitWeakMember(WeakMember*) {} |
+ virtual void VisitPersistent(Persistent*) {} |
+ virtual void VisitCollection(Collection*) {} |
+}; |
+ |
+// Recursive edge visitor. The traversed path is accessible in context. |
+class RecursiveEdgeVisitor : public EdgeVisitor { |
+ public: |
+ // Overrides that recursively walk the edges and record the path. |
+ void VisitValue(Value*) override; |
+ void VisitRawPtr(RawPtr*) override; |
+ void VisitRefPtr(RefPtr*) override; |
+ void VisitOwnPtr(OwnPtr*) override; |
+ void VisitMember(Member*) override; |
+ void VisitWeakMember(WeakMember*) override; |
+ void VisitPersistent(Persistent*) override; |
+ void VisitCollection(Collection*) override; |
+ |
+ protected: |
+ typedef std::deque<Edge*> Context; |
+ Context& context() { return context_; } |
+ Edge* Parent() { return context_.empty() ? 0 : context_.front(); } |
+ void Enter(Edge* e) { return context_.push_front(e); } |
+ void Leave() { context_.pop_front(); } |
+ |
+ // Default callback to overwrite in visitor subclass. |
+ virtual void AtValue(Value*); |
+ virtual void AtRawPtr(RawPtr*); |
+ virtual void AtRefPtr(RefPtr*); |
+ virtual void AtOwnPtr(OwnPtr*); |
+ virtual void AtMember(Member*); |
+ virtual void AtWeakMember(WeakMember*); |
+ virtual void AtPersistent(Persistent*); |
+ virtual void AtCollection(Collection*); |
+ |
+ private: |
+ Context context_; |
+}; |
+ |
+// Base class for all edges. |
+class Edge { |
+ public: |
+ enum NeedsTracingOption { kRecursive, kNonRecursive }; |
+ enum LivenessKind { kWeak, kStrong, kRoot }; |
+ |
+ virtual ~Edge() {} |
+ virtual LivenessKind Kind() = 0; |
+ virtual void Accept(EdgeVisitor*) = 0; |
+ virtual bool NeedsFinalization() = 0; |
+ virtual TracingStatus NeedsTracing(NeedsTracingOption) { |
+ return TracingStatus::Unknown(); |
+ } |
+ |
+ virtual bool IsValue() { return false; } |
+ virtual bool IsRawPtr() { return false; } |
+ virtual bool IsRawPtrClass() { return false; } |
+ virtual bool IsRefPtr() { return false; } |
+ virtual bool IsOwnPtr() { return false; } |
+ virtual bool IsMember() { return false; } |
+ virtual bool IsWeakMember() { return false; } |
+ virtual bool IsPersistent() { return false; } |
+ virtual bool IsCollection() { return false; } |
+}; |
+ |
+// A value edge is a direct edge to some type, eg, part-object edges. |
+class Value : public Edge { |
+ public: |
+ explicit Value(RecordInfo* value) : value_(value) {}; |
+ bool IsValue() override { return true; } |
+ LivenessKind Kind() override { return kStrong; } |
+ bool NeedsFinalization() override; |
+ TracingStatus NeedsTracing(NeedsTracingOption) override; |
+ void Accept(EdgeVisitor* visitor) override { visitor->VisitValue(this); } |
+ RecordInfo* value() { return value_; } |
+ |
+ private: |
+ RecordInfo* value_; |
+}; |
+ |
+// Shared base for smart-pointer edges. |
+class PtrEdge : public Edge { |
+ public: |
+ ~PtrEdge() { delete ptr_; } |
+ Edge* ptr() { return ptr_; } |
+ protected: |
+ PtrEdge(Edge* ptr) : ptr_(ptr) { |
+ assert(ptr && "EdgePtr pointer must be non-null"); |
+ } |
+ private: |
+ Edge* ptr_; |
+}; |
+ |
+class RawPtr : public PtrEdge { |
+ public: |
+ RawPtr(Edge* ptr, bool is_ptr_class, bool is_ref_type) |
+ : PtrEdge(ptr) |
+ , is_ptr_class_(is_ptr_class) |
+ , is_ref_type_(is_ref_type) |
+ { |
+ assert(!(is_ptr_class_ && is_ref_type_)); |
+ } |
+ |
+ bool IsRawPtr() { return true; } |
+ bool IsRawPtrClass() { return is_ptr_class_; } |
+ LivenessKind Kind() { return kWeak; } |
+ bool NeedsFinalization() { return false; } |
+ TracingStatus NeedsTracing(NeedsTracingOption) { |
+ return TracingStatus::Unneeded(); |
+ } |
+ void Accept(EdgeVisitor* visitor) { visitor->VisitRawPtr(this); } |
+ |
+ bool HasReferenceType() { return is_ref_type_; } |
+ private: |
+ bool is_ptr_class_; |
+ bool is_ref_type_; |
+}; |
+ |
+class RefPtr : public PtrEdge { |
+ public: |
+ explicit RefPtr(Edge* ptr) : PtrEdge(ptr) { } |
+ bool IsRefPtr() { return true; } |
+ LivenessKind Kind() { return kStrong; } |
+ bool NeedsFinalization() { return true; } |
+ TracingStatus NeedsTracing(NeedsTracingOption) { |
+ return TracingStatus::Unneeded(); |
+ } |
+ void Accept(EdgeVisitor* visitor) { visitor->VisitRefPtr(this); } |
+}; |
+ |
+class OwnPtr : public PtrEdge { |
+ public: |
+ explicit OwnPtr(Edge* ptr) : PtrEdge(ptr) { } |
+ bool IsOwnPtr() { return true; } |
+ LivenessKind Kind() { return kStrong; } |
+ bool NeedsFinalization() { return true; } |
+ TracingStatus NeedsTracing(NeedsTracingOption) { |
+ return TracingStatus::Unneeded(); |
+ } |
+ void Accept(EdgeVisitor* visitor) { visitor->VisitOwnPtr(this); } |
+}; |
+ |
+class Member : public PtrEdge { |
+ public: |
+ explicit Member(Edge* ptr) : PtrEdge(ptr) { } |
+ bool IsMember() { return true; } |
+ LivenessKind Kind() { return kStrong; } |
+ bool NeedsFinalization() { return false; } |
+ TracingStatus NeedsTracing(NeedsTracingOption) { |
+ return TracingStatus::Needed(); |
+ } |
+ void Accept(EdgeVisitor* visitor) { visitor->VisitMember(this); } |
+}; |
+ |
+class WeakMember : public PtrEdge { |
+ public: |
+ explicit WeakMember(Edge* ptr) : PtrEdge(ptr) { } |
+ bool IsWeakMember() { return true; } |
+ LivenessKind Kind() { return kWeak; } |
+ bool NeedsFinalization() { return false; } |
+ TracingStatus NeedsTracing(NeedsTracingOption) { |
+ return TracingStatus::Needed(); |
+ } |
+ void Accept(EdgeVisitor* visitor) { visitor->VisitWeakMember(this); } |
+}; |
+ |
+class Persistent : public PtrEdge { |
+ public: |
+ explicit Persistent(Edge* ptr) : PtrEdge(ptr) { } |
+ bool IsPersistent() { return true; } |
+ LivenessKind Kind() { return kRoot; } |
+ bool NeedsFinalization() { return true; } |
+ TracingStatus NeedsTracing(NeedsTracingOption) { |
+ return TracingStatus::Unneeded(); |
+ } |
+ void Accept(EdgeVisitor* visitor) { visitor->VisitPersistent(this); } |
+}; |
+ |
+class Collection : public Edge { |
+ public: |
+ typedef std::vector<Edge*> Members; |
+ Collection(RecordInfo* info, bool on_heap, bool is_root) |
+ : info_(info), |
+ on_heap_(on_heap), |
+ is_root_(is_root) {} |
+ ~Collection() { |
+ for (Members::iterator it = members_.begin(); it != members_.end(); ++it) { |
+ assert(*it && "Collection-edge members must be non-null"); |
+ delete *it; |
+ } |
+ } |
+ bool IsCollection() { return true; } |
+ LivenessKind Kind() { return is_root_ ? kRoot : kStrong; } |
+ bool on_heap() { return on_heap_; } |
+ bool is_root() { return is_root_; } |
+ Members& members() { return members_; } |
+ void Accept(EdgeVisitor* visitor) { visitor->VisitCollection(this); } |
+ void AcceptMembers(EdgeVisitor* visitor) { |
+ for (Members::iterator it = members_.begin(); it != members_.end(); ++it) |
+ (*it)->Accept(visitor); |
+ } |
+ bool NeedsFinalization(); |
+ TracingStatus NeedsTracing(NeedsTracingOption) { |
+ if (is_root_) |
+ return TracingStatus::Unneeded(); |
+ if (on_heap_) |
+ return TracingStatus::Needed(); |
+ // For off-heap collections, determine tracing status of members. |
+ TracingStatus status = TracingStatus::Unneeded(); |
+ for (Members::iterator it = members_.begin(); it != members_.end(); ++it) { |
+ // Do a non-recursive test here since members could equal the holder. |
+ status = status.LUB((*it)->NeedsTracing(kNonRecursive)); |
+ } |
+ return status; |
+ } |
+ |
+ private: |
+ RecordInfo* info_; |
+ Members members_; |
+ bool on_heap_; |
+ bool is_root_; |
+}; |
+ |
+#endif // TOOLS_BLINK_GC_PLUGIN_EDGE_H_ |