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