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 // This file provides a wrapper for CXXRecordDecl that accumulates GC related
      6 // information about a class. Accumulated information is memoized and the info
      7 // objects are stored in a RecordCache.
      8 
      9 #ifndef TOOLS_BLINK_GC_PLUGIN_RECORD_INFO_H_
     10 #define TOOLS_BLINK_GC_PLUGIN_RECORD_INFO_H_
     11 
     12 #include <map>
     13 #include <vector>
     14 
     15 #include "Edge.h"
     16 
     17 #include "clang/AST/AST.h"
     18 #include "clang/AST/CXXInheritance.h"
     19 
     20 class RecordCache;
     21 
     22 // A potentially tracable and/or lifetime affecting point in the object graph.
     23 class GraphPoint {
     24  public:
     25   GraphPoint() : traced_(false) {}
     26   void MarkTraced() { traced_ = true; }
     27   bool IsProperlyTraced() { return traced_ || !NeedsTracing().IsNeeded(); }
     28   virtual const TracingStatus NeedsTracing() = 0;
     29 
     30  private:
     31   bool traced_;
     32 };
     33 
     34 class BasePoint : public GraphPoint {
     35  public:
     36   BasePoint(const clang::CXXBaseSpecifier& spec,
     37             RecordInfo* info,
     38             const TracingStatus& status)
     39       : spec_(spec), info_(info), status_(status) {}
     40   const TracingStatus NeedsTracing() { return status_; }
     41   const clang::CXXBaseSpecifier& spec() { return spec_; }
     42   RecordInfo* info() { return info_; }
     43 
     44  private:
     45   const clang::CXXBaseSpecifier& spec_;
     46   RecordInfo* info_;
     47   TracingStatus status_;
     48 };
     49 
     50 class FieldPoint : public GraphPoint {
     51  public:
     52   FieldPoint(clang::FieldDecl* field, Edge* edge)
     53       : field_(field), edge_(edge) {}
     54   const TracingStatus NeedsTracing() {
     55     return edge_->NeedsTracing(Edge::kRecursive);
     56   }
     57   clang::FieldDecl* field() { return field_; }
     58   Edge* edge() { return edge_; }
     59 
     60  private:
     61   clang::FieldDecl* field_;
     62   Edge* edge_;
     63 
     64   friend class RecordCache;
     65   void deleteEdge() { delete edge_; }
     66 };
     67 
     68 // Wrapper class to lazily collect information about a C++ record.
     69 class RecordInfo {
     70  public:
     71   typedef std::map<clang::CXXRecordDecl*, BasePoint> Bases;
     72   typedef std::map<clang::FieldDecl*, FieldPoint> Fields;
     73   typedef std::vector<const clang::Type*> TemplateArgs;
     74 
     75   ~RecordInfo();
     76 
     77   clang::CXXRecordDecl* record() const { return record_; }
     78   const std::string& name() const { return name_; }
     79   Fields& GetFields();
     80   Bases& GetBases();
     81   clang::CXXMethodDecl* GetTraceMethod();
     82   clang::CXXMethodDecl* GetTraceDispatchMethod();
     83   clang::CXXMethodDecl* GetFinalizeDispatchMethod();
     84 
     85   bool GetTemplateArgs(size_t count, TemplateArgs* output_args);
     86 
     87   bool IsHeapAllocatedCollection();
     88   bool IsGCDerived();
     89   bool IsGCAllocated();
     90   bool IsGCFinalized();
     91   bool IsGCMixin();
     92   bool IsStackAllocated();
     93   bool IsNonNewable();
     94   bool IsOnlyPlacementNewable();
     95   clang::CXXMethodDecl* DeclaresNewOperator();
     96 
     97   bool RequiresTraceMethod();
     98   bool NeedsFinalization();
     99   TracingStatus NeedsTracing(Edge::NeedsTracingOption);
    100   clang::CXXMethodDecl* InheritsNonVirtualTrace();
    101   bool IsConsideredAbstract();
    102 
    103  private:
    104   RecordInfo(clang::CXXRecordDecl* record, RecordCache* cache);
    105 
    106   Fields* CollectFields();
    107   Bases* CollectBases();
    108   void DetermineTracingMethods();
    109   bool InheritsTrace();
    110 
    111   Edge* CreateEdge(const clang::Type* type);
    112 
    113   RecordCache* cache_;
    114   clang::CXXRecordDecl* record_;
    115   const std::string name_;
    116   TracingStatus fields_need_tracing_;
    117   Bases* bases_;
    118   Fields* fields_;
    119 
    120   enum CachedBool { kFalse = 0, kTrue = 1, kNotComputed = 2 };
    121   CachedBool is_stack_allocated_;
    122   CachedBool is_non_newable_;
    123   CachedBool is_only_placement_newable_;
    124   CachedBool does_need_finalization_;
    125 
    126   bool determined_trace_methods_;
    127   clang::CXXMethodDecl* trace_method_;
    128   clang::CXXMethodDecl* trace_dispatch_method_;
    129   clang::CXXMethodDecl* finalize_dispatch_method_;
    130 
    131   bool is_gc_derived_;
    132   clang::CXXBasePaths* base_paths_;
    133 
    134   friend class RecordCache;
    135 };
    136 
    137 class RecordCache {
    138  public:
    139   RecordInfo* Lookup(clang::CXXRecordDecl* record);
    140 
    141   RecordInfo* Lookup(const clang::CXXRecordDecl* record) {
    142     return Lookup(const_cast<clang::CXXRecordDecl*>(record));
    143   }
    144 
    145   RecordInfo* Lookup(clang::DeclContext* decl) {
    146     return Lookup(clang::dyn_cast<clang::CXXRecordDecl>(decl));
    147   }
    148 
    149   RecordInfo* Lookup(const clang::Type* type) {
    150     return Lookup(type->getAsCXXRecordDecl());
    151   }
    152 
    153   RecordInfo* Lookup(const clang::QualType& type) {
    154     return Lookup(type.getTypePtr());
    155   }
    156 
    157   ~RecordCache() {
    158     for (Cache::iterator it = cache_.begin(); it != cache_.end(); ++it) {
    159       if (!it->second.fields_)
    160         continue;
    161       for (RecordInfo::Fields::iterator fit = it->second.fields_->begin();
    162         fit != it->second.fields_->end();
    163         ++fit) {
    164         fit->second.deleteEdge();
    165       }
    166     }
    167   }
    168 
    169  private:
    170   typedef std::map<clang::CXXRecordDecl*, RecordInfo> Cache;
    171   Cache cache_;
    172 };
    173 
    174 #endif  // TOOLS_BLINK_GC_PLUGIN_RECORD_INFO_H_
    175