diff options
Diffstat (limited to 'chromium/tools/clang/blink_gc_plugin/Edge.h')
-rw-r--r-- | chromium/tools/clang/blink_gc_plugin/Edge.h | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/chromium/tools/clang/blink_gc_plugin/Edge.h b/chromium/tools/clang/blink_gc_plugin/Edge.h new file mode 100644 index 00000000000..d0b78b58a1f --- /dev/null +++ b/chromium/tools/clang/blink_gc_plugin/Edge.h @@ -0,0 +1,245 @@ +// 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 <deque> + +#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 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. + virtual void VisitValue(Value*) override; + virtual void VisitRawPtr(RawPtr*) override; + virtual void VisitRefPtr(RefPtr*) override; + virtual void VisitOwnPtr(OwnPtr*) override; + virtual void VisitMember(Member*) override; + virtual void VisitWeakMember(WeakMember*) override; + virtual void VisitPersistent(Persistent*) override; + virtual 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: + explicit RawPtr(Edge* ptr, bool is_ptr_class) + : PtrEdge(ptr), is_ptr_class_(is_ptr_class) { } + 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); } + private: + bool is_ptr_class_; +}; + +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_ |