OLD | NEW |
(Empty) | |
| 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 virtual ~GraphPoint() {} |
| 27 void MarkTraced() { traced_ = true; } |
| 28 bool IsProperlyTraced() { return traced_ || !NeedsTracing().IsNeeded(); } |
| 29 virtual const TracingStatus NeedsTracing() = 0; |
| 30 |
| 31 private: |
| 32 bool traced_; |
| 33 }; |
| 34 |
| 35 class BasePoint : public GraphPoint { |
| 36 public: |
| 37 BasePoint(const clang::CXXBaseSpecifier& spec, |
| 38 RecordInfo* info, |
| 39 const TracingStatus& status) |
| 40 : spec_(spec), info_(info), status_(status) {} |
| 41 const TracingStatus NeedsTracing() { return status_; } |
| 42 const clang::CXXBaseSpecifier& spec() { return spec_; } |
| 43 RecordInfo* info() { return info_; } |
| 44 |
| 45 private: |
| 46 const clang::CXXBaseSpecifier& spec_; |
| 47 RecordInfo* info_; |
| 48 TracingStatus status_; |
| 49 }; |
| 50 |
| 51 class FieldPoint : public GraphPoint { |
| 52 public: |
| 53 FieldPoint(clang::FieldDecl* field, Edge* edge) |
| 54 : field_(field), edge_(edge) {} |
| 55 const TracingStatus NeedsTracing() { |
| 56 return edge_->NeedsTracing(Edge::kRecursive); |
| 57 } |
| 58 clang::FieldDecl* field() { return field_; } |
| 59 Edge* edge() { return edge_; } |
| 60 |
| 61 private: |
| 62 clang::FieldDecl* field_; |
| 63 Edge* edge_; |
| 64 |
| 65 friend class RecordCache; |
| 66 void deleteEdge() { delete edge_; } |
| 67 }; |
| 68 |
| 69 // Wrapper class to lazily collect information about a C++ record. |
| 70 class RecordInfo { |
| 71 public: |
| 72 typedef std::map<clang::CXXRecordDecl*, BasePoint> Bases; |
| 73 typedef std::map<clang::FieldDecl*, FieldPoint> Fields; |
| 74 typedef std::vector<const clang::Type*> TemplateArgs; |
| 75 |
| 76 ~RecordInfo(); |
| 77 |
| 78 clang::CXXRecordDecl* record() const { return record_; } |
| 79 const std::string& name() const { return name_; } |
| 80 Fields& GetFields(); |
| 81 Bases& GetBases(); |
| 82 clang::CXXMethodDecl* GetTraceMethod(); |
| 83 clang::CXXMethodDecl* GetTraceDispatchMethod(); |
| 84 clang::CXXMethodDecl* GetFinalizeDispatchMethod(); |
| 85 |
| 86 bool GetTemplateArgs(size_t count, TemplateArgs* output_args); |
| 87 |
| 88 bool IsHeapAllocatedCollection(); |
| 89 bool IsGCDerived(); |
| 90 bool IsGCAllocated(); |
| 91 bool IsGCFinalized(); |
| 92 bool IsGCMixin(); |
| 93 bool IsStackAllocated(); |
| 94 bool IsNonNewable(); |
| 95 bool IsOnlyPlacementNewable(); |
| 96 bool IsGCMixinInstance(); |
| 97 bool IsEagerlyFinalized(); |
| 98 |
| 99 bool HasDefinition(); |
| 100 |
| 101 clang::CXXMethodDecl* DeclaresNewOperator(); |
| 102 |
| 103 bool RequiresTraceMethod(); |
| 104 bool NeedsFinalization(); |
| 105 bool DeclaresGCMixinMethods(); |
| 106 bool DeclaresLocalTraceMethod(); |
| 107 TracingStatus NeedsTracing(Edge::NeedsTracingOption); |
| 108 clang::CXXMethodDecl* InheritsNonVirtualTrace(); |
| 109 bool IsConsideredAbstract(); |
| 110 |
| 111 static clang::CXXRecordDecl* GetDependentTemplatedDecl(const clang::Type&); |
| 112 |
| 113 private: |
| 114 RecordInfo(clang::CXXRecordDecl* record, RecordCache* cache); |
| 115 |
| 116 void walkBases(); |
| 117 |
| 118 Fields* CollectFields(); |
| 119 Bases* CollectBases(); |
| 120 void DetermineTracingMethods(); |
| 121 bool InheritsTrace(); |
| 122 |
| 123 Edge* CreateEdge(const clang::Type* type); |
| 124 |
| 125 RecordCache* cache_; |
| 126 clang::CXXRecordDecl* record_; |
| 127 const std::string name_; |
| 128 TracingStatus fields_need_tracing_; |
| 129 Bases* bases_; |
| 130 Fields* fields_; |
| 131 |
| 132 enum CachedBool { kFalse = 0, kTrue = 1, kNotComputed = 2 }; |
| 133 CachedBool is_stack_allocated_; |
| 134 CachedBool is_non_newable_; |
| 135 CachedBool is_only_placement_newable_; |
| 136 CachedBool does_need_finalization_; |
| 137 CachedBool has_gc_mixin_methods_; |
| 138 CachedBool is_declaring_local_trace_; |
| 139 CachedBool is_eagerly_finalized_; |
| 140 |
| 141 bool determined_trace_methods_; |
| 142 clang::CXXMethodDecl* trace_method_; |
| 143 clang::CXXMethodDecl* trace_dispatch_method_; |
| 144 clang::CXXMethodDecl* finalize_dispatch_method_; |
| 145 |
| 146 bool is_gc_derived_; |
| 147 |
| 148 std::vector<std::string> gc_base_names_; |
| 149 |
| 150 friend class RecordCache; |
| 151 }; |
| 152 |
| 153 class RecordCache { |
| 154 public: |
| 155 RecordInfo* Lookup(clang::CXXRecordDecl* record); |
| 156 |
| 157 RecordInfo* Lookup(const clang::CXXRecordDecl* record) { |
| 158 return Lookup(const_cast<clang::CXXRecordDecl*>(record)); |
| 159 } |
| 160 |
| 161 RecordInfo* Lookup(clang::DeclContext* decl) { |
| 162 return Lookup(clang::dyn_cast<clang::CXXRecordDecl>(decl)); |
| 163 } |
| 164 |
| 165 RecordInfo* Lookup(const clang::Type* type) { |
| 166 return Lookup(type->getAsCXXRecordDecl()); |
| 167 } |
| 168 |
| 169 RecordInfo* Lookup(const clang::QualType& type) { |
| 170 return Lookup(type.getTypePtr()); |
| 171 } |
| 172 |
| 173 ~RecordCache() { |
| 174 for (Cache::iterator it = cache_.begin(); it != cache_.end(); ++it) { |
| 175 if (!it->second.fields_) |
| 176 continue; |
| 177 for (RecordInfo::Fields::iterator fit = it->second.fields_->begin(); |
| 178 fit != it->second.fields_->end(); |
| 179 ++fit) { |
| 180 fit->second.deleteEdge(); |
| 181 } |
| 182 } |
| 183 } |
| 184 |
| 185 private: |
| 186 typedef std::map<clang::CXXRecordDecl*, RecordInfo> Cache; |
| 187 Cache cache_; |
| 188 }; |
| 189 |
| 190 #endif // TOOLS_BLINK_GC_PLUGIN_RECORD_INFO_H_ |
OLD | NEW |