| // Copyright 2014 The Chromium Authors |
| // 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 <string> |
| #include <vector> |
| |
| #include "TracingStatus.h" |
| |
| class RecordInfo; |
| |
| class Edge; |
| class Collection; |
| class CrossThreadPersistent; |
| class Iterator; |
| class Member; |
| class Persistent; |
| class RawPtr; |
| class RefPtr; |
| class UniquePtr; |
| class Value; |
| class WeakMember; |
| class TraceWrapperV8Reference; |
| class ArrayEdge; |
| |
| // Bare-bones visitor. |
| class EdgeVisitor { |
| public: |
| virtual ~EdgeVisitor() {} |
| virtual void VisitValue(Value*) {} |
| virtual void VisitRawPtr(RawPtr*) {} |
| virtual void VisitRefPtr(RefPtr*) {} |
| virtual void VisitUniquePtr(UniquePtr*) {} |
| virtual void VisitMember(Member*) {} |
| virtual void VisitWeakMember(WeakMember*) {} |
| virtual void VisitPersistent(Persistent*) {} |
| virtual void VisitCrossThreadPersistent(CrossThreadPersistent*) {} |
| virtual void VisitCollection(Collection*) {} |
| virtual void VisitIterator(Iterator*) {} |
| virtual void VisitTraceWrapperV8Reference(TraceWrapperV8Reference*) {} |
| virtual void VisitArrayEdge(ArrayEdge*) {} |
| }; |
| |
| // 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 VisitUniquePtr(UniquePtr*) override; |
| void VisitMember(Member*) override; |
| void VisitWeakMember(WeakMember*) override; |
| void VisitPersistent(Persistent*) override; |
| void VisitCrossThreadPersistent(CrossThreadPersistent*) override; |
| void VisitCollection(Collection*) override; |
| void VisitIterator(Iterator*) override; |
| void VisitTraceWrapperV8Reference(TraceWrapperV8Reference*) override; |
| void VisitArrayEdge(ArrayEdge*) override; |
| |
| protected: |
| typedef std::deque<Edge*> Context; |
| Context& context() { return context_; } |
| Edge* Parent() { return context_.empty() ? 0 : context_.front(); } |
| Edge* GrandParent() { |
| return Parent() ? (context_.size() > 1 ? context_[1] : nullptr) : nullptr; |
| } |
| 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 AtUniquePtr(UniquePtr*); |
| virtual void AtMember(Member*); |
| virtual void AtWeakMember(WeakMember*); |
| virtual void AtTraceWrapperV8Reference(TraceWrapperV8Reference*); |
| virtual void AtPersistent(Persistent*); |
| virtual void AtCrossThreadPersistent(CrossThreadPersistent*); |
| virtual void AtCollection(Collection*); |
| virtual void AtIterator(Iterator*); |
| virtual void AtArrayEdge(ArrayEdge*); |
| |
| 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 IsRefPtr() { return false; } |
| virtual bool IsUniquePtr() { return false; } |
| virtual bool IsMember() { return false; } |
| virtual bool IsWeakMember() { return false; } |
| virtual bool IsCollection() { return false; } |
| virtual bool IsArray() { return false; } |
| virtual bool IsTraceWrapperV8Reference() { 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_; |
| }; |
| |
| class ArrayEdge : public Edge { |
| public: |
| explicit ArrayEdge(Edge* value) : value_(value){}; |
| LivenessKind Kind() override { return kStrong; } |
| bool NeedsFinalization() override { return false; } |
| TracingStatus NeedsTracing(NeedsTracingOption option) override { |
| return value_->NeedsTracing(option); |
| } |
| void Accept(EdgeVisitor* visitor) override { visitor->VisitArrayEdge(this); } |
| Edge* element() { return value_; } |
| bool IsArray() override { return true; } |
| |
| private: |
| Edge* 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_ref_type) |
| : PtrEdge(ptr) |
| , is_ref_type_(is_ref_type) |
| { |
| } |
| |
| bool IsRawPtr() override { return true; } |
| LivenessKind Kind() override { return kWeak; } |
| bool NeedsFinalization() override { return false; } |
| TracingStatus NeedsTracing(NeedsTracingOption) override { |
| return TracingStatus::Illegal(); |
| } |
| void Accept(EdgeVisitor* visitor) override { visitor->VisitRawPtr(this); } |
| |
| bool HasReferenceType() { return is_ref_type_; } |
| private: |
| bool is_ref_type_; |
| }; |
| |
| class RefPtr : public PtrEdge { |
| public: |
| RefPtr(Edge* ptr, LivenessKind kind) : PtrEdge(ptr), kind_(kind) {} |
| bool IsRefPtr() override { return true; } |
| LivenessKind Kind() override { return kind_; } |
| bool NeedsFinalization() override { return true; } |
| TracingStatus NeedsTracing(NeedsTracingOption) override { |
| return TracingStatus::Illegal(); |
| } |
| void Accept(EdgeVisitor* visitor) override { visitor->VisitRefPtr(this); } |
| |
| private: |
| LivenessKind kind_; |
| }; |
| |
| class UniquePtr : public PtrEdge { |
| public: |
| explicit UniquePtr(Edge* ptr) : PtrEdge(ptr) { } |
| bool IsUniquePtr() override { return true; } |
| LivenessKind Kind() override { return kStrong; } |
| bool NeedsFinalization() override { return true; } |
| TracingStatus NeedsTracing(NeedsTracingOption) override { |
| return TracingStatus::Illegal(); |
| } |
| void Accept(EdgeVisitor* visitor) override { visitor->VisitUniquePtr(this); } |
| }; |
| |
| class Member : public PtrEdge { |
| public: |
| explicit Member(Edge* ptr) : PtrEdge(ptr) { } |
| bool IsMember() override { return true; } |
| LivenessKind Kind() override { return kStrong; } |
| bool NeedsFinalization() override { return false; } |
| TracingStatus NeedsTracing(NeedsTracingOption) override { |
| return TracingStatus::Needed(); |
| } |
| void Accept(EdgeVisitor* visitor) override { visitor->VisitMember(this); } |
| }; |
| |
| class WeakMember : public PtrEdge { |
| public: |
| explicit WeakMember(Edge* ptr) : PtrEdge(ptr) { } |
| bool IsWeakMember() override { return true; } |
| LivenessKind Kind() override { return kWeak; } |
| bool NeedsFinalization() override { return false; } |
| TracingStatus NeedsTracing(NeedsTracingOption) override { |
| return TracingStatus::Needed(); |
| } |
| void Accept(EdgeVisitor* visitor) override { visitor->VisitWeakMember(this); } |
| }; |
| |
| class Persistent : public PtrEdge { |
| public: |
| explicit Persistent(Edge* ptr) : PtrEdge(ptr) { } |
| LivenessKind Kind() override { return kRoot; } |
| bool NeedsFinalization() override { return true; } |
| TracingStatus NeedsTracing(NeedsTracingOption) override { |
| return TracingStatus::Illegal(); |
| } |
| void Accept(EdgeVisitor* visitor) override { visitor->VisitPersistent(this); } |
| }; |
| |
| class CrossThreadPersistent : public PtrEdge { |
| public: |
| explicit CrossThreadPersistent(Edge* ptr) : PtrEdge(ptr) { } |
| LivenessKind Kind() override { return kRoot; } |
| bool NeedsFinalization() override { return true; } |
| TracingStatus NeedsTracing(NeedsTracingOption) override { |
| return TracingStatus::Illegal(); |
| } |
| void Accept(EdgeVisitor* visitor) override { |
| visitor->VisitCrossThreadPersistent(this); |
| } |
| }; |
| |
| class TraceWrapperV8Reference : public PtrEdge { |
| public: |
| explicit TraceWrapperV8Reference(Edge* ptr) : PtrEdge(ptr) {} |
| bool IsTraceWrapperV8Reference() override { return true; } |
| LivenessKind Kind() override { return kStrong; } |
| bool NeedsFinalization() override { return true; } |
| TracingStatus NeedsTracing(NeedsTracingOption) override { |
| return TracingStatus::Needed(); |
| } |
| void Accept(EdgeVisitor* visitor) override { |
| visitor->VisitTraceWrapperV8Reference(this); |
| } |
| }; |
| |
| class Collection : public Edge { |
| public: |
| typedef std::vector<Edge*> Members; |
| Collection(RecordInfo* info, bool on_heap) : info_(info), on_heap_(on_heap) {} |
| ~Collection() { |
| for (Members::iterator it = members_.begin(); it != members_.end(); ++it) { |
| assert(*it && "Collection-edge members must be non-null"); |
| delete *it; |
| } |
| } |
| bool IsCollection() override { return true; } |
| bool IsSTDCollection(); |
| LivenessKind Kind() override { return kStrong; } |
| bool on_heap() { return on_heap_; } |
| Members& members() { return members_; } |
| void Accept(EdgeVisitor* visitor) override { visitor->VisitCollection(this); } |
| void AcceptMembers(EdgeVisitor* visitor) { |
| for (Members::iterator it = members_.begin(); it != members_.end(); ++it) |
| (*it)->Accept(visitor); |
| } |
| bool NeedsFinalization() override; |
| TracingStatus NeedsTracing(NeedsTracingOption) override; |
| std::string GetCollectionName() const; |
| |
| private: |
| RecordInfo* info_; |
| Members members_; |
| bool on_heap_; |
| }; |
| |
| // An iterator edge is a direct edge to some iterator type. |
| class Iterator : public Edge { |
| public: |
| Iterator(RecordInfo* info, bool on_heap) : info_(info), on_heap_(on_heap) {} |
| ~Iterator() {} |
| |
| void Accept(EdgeVisitor* visitor) override { visitor->VisitIterator(this); } |
| LivenessKind Kind() override { return kStrong; } |
| bool NeedsFinalization() override { return false; } |
| TracingStatus NeedsTracing(NeedsTracingOption) override { |
| if (on_heap_) |
| return TracingStatus::Illegal(); |
| return TracingStatus::Unneeded(); |
| } |
| |
| RecordInfo* info() const { return info_; } |
| |
| bool on_heap() const { return on_heap_; } |
| |
| private: |
| RecordInfo* info_; |
| bool on_heap_; |
| }; |
| |
| #endif // TOOLS_BLINK_GC_PLUGIN_EDGE_H_ |