RecordInfo.h revision effb81e5f8246d0db0270817048dc992db66e9fb
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 20class RecordCache; 21 22// A potentially tracable and/or lifetime affecting point in the object graph. 23class 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 34class 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 // Needed to change the status of bases with a pure-virtual trace. 42 void MarkUnneeded() { status_ = TracingStatus::Unneeded(); } 43 const clang::CXXBaseSpecifier& spec() { return spec_; } 44 RecordInfo* info() { return info_; } 45 46 private: 47 const clang::CXXBaseSpecifier& spec_; 48 RecordInfo* info_; 49 TracingStatus status_; 50}; 51 52class FieldPoint : public GraphPoint { 53 public: 54 FieldPoint(clang::FieldDecl* field, Edge* edge) 55 : field_(field), edge_(edge) {} 56 const TracingStatus NeedsTracing() { 57 return edge_->NeedsTracing(Edge::kRecursive); 58 } 59 clang::FieldDecl* field() { return field_; } 60 Edge* edge() { return edge_; } 61 62 private: 63 clang::FieldDecl* field_; 64 Edge* edge_; 65 66 friend class RecordCache; 67 void deleteEdge() { delete edge_; } 68}; 69 70// Wrapper class to lazily collect information about a C++ record. 71class RecordInfo { 72 public: 73 typedef std::map<clang::CXXRecordDecl*, BasePoint> Bases; 74 typedef std::map<clang::FieldDecl*, FieldPoint> Fields; 75 typedef std::vector<const clang::Type*> TemplateArgs; 76 77 ~RecordInfo(); 78 79 clang::CXXRecordDecl* record() const { return record_; } 80 const std::string& name() const { return name_; } 81 Fields& GetFields(); 82 Bases& GetBases(); 83 clang::CXXMethodDecl* GetTraceMethod(); 84 clang::CXXMethodDecl* GetTraceDispatchMethod(); 85 clang::CXXMethodDecl* GetFinalizeDispatchMethod(); 86 87 bool GetTemplateArgs(size_t count, TemplateArgs* output_args); 88 89 bool IsHeapAllocatedCollection(); 90 bool IsGCDerived(); 91 bool IsGCAllocated(); 92 bool IsGCFinalized(); 93 bool IsGCMixin(); 94 bool IsStackAllocated(); 95 bool IsNonNewable(); 96 bool IsOnlyPlacementNewable(); 97 98 bool RequiresTraceMethod(); 99 bool NeedsFinalization(); 100 TracingStatus NeedsTracing(Edge::NeedsTracingOption); 101 clang::CXXMethodDecl* InheritsNonVirtualTrace(); 102 bool IsConsideredAbstract(); 103 104 private: 105 RecordInfo(clang::CXXRecordDecl* record, RecordCache* cache); 106 107 Fields* CollectFields(); 108 Bases* CollectBases(); 109 void DetermineTracingMethods(); 110 bool InheritsNonPureTrace(); 111 112 Edge* CreateEdge(const clang::Type* type); 113 114 RecordCache* cache_; 115 clang::CXXRecordDecl* record_; 116 const std::string name_; 117 TracingStatus fields_need_tracing_; 118 Bases* bases_; 119 Fields* fields_; 120 121 enum CachedBool { kFalse = 0, kTrue = 1, kNotComputed = 2 }; 122 CachedBool is_stack_allocated_; 123 CachedBool is_non_newable_; 124 CachedBool is_only_placement_newable_; 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 137class 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