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