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