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 defines the names used by GC infrastructure. |
| 6 |
| 7 // TODO: Restructure the name determination to use fully qualified names (ala, |
| 8 // blink::Foo) so that the plugin can be enabled for all of chromium. Doing so |
| 9 // would allow us to catch errors with structures outside of blink that might |
| 10 // have unsafe pointers to GC allocated blink structures. |
| 11 |
| 12 #ifndef TOOLS_BLINK_GC_PLUGIN_CONFIG_H_ |
| 13 #define TOOLS_BLINK_GC_PLUGIN_CONFIG_H_ |
| 14 |
| 15 #include <cassert> |
| 16 |
| 17 #include "clang/AST/AST.h" |
| 18 #include "clang/AST/Attr.h" |
| 19 |
| 20 const char kNewOperatorName[] = "operator new"; |
| 21 const char kCreateName[] = "create"; |
| 22 const char kTraceName[] = "trace"; |
| 23 const char kTraceImplName[] = "traceImpl"; |
| 24 const char kFinalizeName[] = "finalizeGarbageCollectedObject"; |
| 25 const char kTraceAfterDispatchName[] = "traceAfterDispatch"; |
| 26 const char kTraceAfterDispatchImplName[] = "traceAfterDispatchImpl"; |
| 27 const char kRegisterWeakMembersName[] = "registerWeakMembers"; |
| 28 const char kHeapAllocatorName[] = "HeapAllocator"; |
| 29 const char kTraceIfNeededName[] = "TraceIfNeeded"; |
| 30 const char kVisitorDispatcherName[] = "VisitorDispatcher"; |
| 31 const char kVisitorVarName[] = "visitor"; |
| 32 const char kAdjustAndMarkName[] = "adjustAndMark"; |
| 33 const char kIsHeapObjectAliveName[] = "isHeapObjectAlive"; |
| 34 const char kIsEagerlyFinalizedName[] = "IsEagerlyFinalizedMarker"; |
| 35 |
| 36 class Config { |
| 37 public: |
| 38 static bool IsMember(const std::string& name) { |
| 39 return name == "Member"; |
| 40 } |
| 41 |
| 42 static bool IsWeakMember(const std::string& name) { |
| 43 return name == "WeakMember"; |
| 44 } |
| 45 |
| 46 static bool IsMemberHandle(const std::string& name) { |
| 47 return IsMember(name) || |
| 48 IsWeakMember(name); |
| 49 } |
| 50 |
| 51 static bool IsPersistent(const std::string& name) { |
| 52 return name == "Persistent"; |
| 53 } |
| 54 |
| 55 static bool IsPersistentHandle(const std::string& name) { |
| 56 return IsPersistent(name) || |
| 57 IsPersistentGCCollection(name); |
| 58 } |
| 59 |
| 60 static bool IsRawPtr(const std::string& name) { |
| 61 return name == "RawPtr"; |
| 62 } |
| 63 |
| 64 static bool IsRefPtr(const std::string& name) { |
| 65 return name == "RefPtr"; |
| 66 } |
| 67 |
| 68 static bool IsOwnPtr(const std::string& name) { |
| 69 return name == "OwnPtr"; |
| 70 } |
| 71 |
| 72 static bool IsWTFCollection(const std::string& name) { |
| 73 return name == "Vector" || |
| 74 name == "Deque" || |
| 75 name == "HashSet" || |
| 76 name == "ListHashSet" || |
| 77 name == "LinkedHashSet" || |
| 78 name == "HashCountedSet" || |
| 79 name == "HashMap"; |
| 80 } |
| 81 |
| 82 static bool IsGCCollection(const std::string& name) { |
| 83 return name == "HeapVector" || |
| 84 name == "HeapDeque" || |
| 85 name == "HeapHashSet" || |
| 86 name == "HeapListHashSet" || |
| 87 name == "HeapLinkedHashSet" || |
| 88 name == "HeapHashCountedSet" || |
| 89 name == "HeapHashMap" || |
| 90 IsPersistentGCCollection(name); |
| 91 } |
| 92 |
| 93 static bool IsPersistentGCCollection(const std::string& name) { |
| 94 return name == "PersistentHeapVector" || |
| 95 name == "PersistentHeapDeque" || |
| 96 name == "PersistentHeapHashSet" || |
| 97 name == "PersistentHeapListHashSet" || |
| 98 name == "PersistentHeapLinkedHashSet" || |
| 99 name == "PersistentHeapHashCountedSet" || |
| 100 name == "PersistentHeapHashMap"; |
| 101 } |
| 102 |
| 103 static bool IsHashMap(const std::string& name) { |
| 104 return name == "HashMap" || |
| 105 name == "HeapHashMap" || |
| 106 name == "PersistentHeapHashMap"; |
| 107 } |
| 108 |
| 109 // Following http://crrev.com/369633033 (Blink r177436), |
| 110 // ignore blink::ScriptWrappable's destructor. |
| 111 // TODO: remove when its non-Oilpan destructor is removed. |
| 112 static bool HasIgnorableDestructor(const std::string& ns, |
| 113 const std::string& name) { |
| 114 return ns == "blink" && name == "ScriptWrappable"; |
| 115 } |
| 116 |
| 117 // Assumes name is a valid collection name. |
| 118 static size_t CollectionDimension(const std::string& name) { |
| 119 return (IsHashMap(name) || name == "pair") ? 2 : 1; |
| 120 } |
| 121 |
| 122 static bool IsDummyBase(const std::string& name) { |
| 123 return name == "DummyBase"; |
| 124 } |
| 125 |
| 126 static bool IsRefCountedBase(const std::string& name) { |
| 127 return name == "RefCounted" || |
| 128 name == "ThreadSafeRefCounted"; |
| 129 } |
| 130 |
| 131 static bool IsGCMixinBase(const std::string& name) { |
| 132 return name == "GarbageCollectedMixin"; |
| 133 } |
| 134 |
| 135 static bool IsGCFinalizedBase(const std::string& name) { |
| 136 return name == "GarbageCollectedFinalized" || |
| 137 name == "RefCountedGarbageCollected" || |
| 138 name == "ThreadSafeRefCountedGarbageCollected"; |
| 139 } |
| 140 |
| 141 static bool IsGCBase(const std::string& name) { |
| 142 return name == "GarbageCollected" || |
| 143 IsGCFinalizedBase(name) || |
| 144 IsGCMixinBase(name); |
| 145 } |
| 146 |
| 147 // Returns true of the base classes that do not need a vtable entry for trace |
| 148 // because they cannot possibly initiate a GC during construction. |
| 149 static bool IsSafePolymorphicBase(const std::string& name) { |
| 150 return IsGCBase(name) || IsDummyBase(name) || IsRefCountedBase(name); |
| 151 } |
| 152 |
| 153 static bool IsAnnotated(clang::Decl* decl, const std::string& anno) { |
| 154 clang::AnnotateAttr* attr = decl->getAttr<clang::AnnotateAttr>(); |
| 155 return attr && (attr->getAnnotation() == anno); |
| 156 } |
| 157 |
| 158 static bool IsStackAnnotated(clang::Decl* decl) { |
| 159 return IsAnnotated(decl, "blink_stack_allocated"); |
| 160 } |
| 161 |
| 162 static bool IsIgnoreAnnotated(clang::Decl* decl) { |
| 163 return IsAnnotated(decl, "blink_gc_plugin_ignore"); |
| 164 } |
| 165 |
| 166 static bool IsIgnoreCycleAnnotated(clang::Decl* decl) { |
| 167 return IsAnnotated(decl, "blink_gc_plugin_ignore_cycle") || |
| 168 IsIgnoreAnnotated(decl); |
| 169 } |
| 170 |
| 171 static bool IsVisitor(const std::string& name) { |
| 172 return name == "Visitor" || name == "VisitorHelper"; |
| 173 } |
| 174 |
| 175 static bool IsVisitorPtrType(const clang::QualType& formal_type) { |
| 176 if (!formal_type->isPointerType()) |
| 177 return false; |
| 178 |
| 179 clang::CXXRecordDecl* pointee_type = |
| 180 formal_type->getPointeeType()->getAsCXXRecordDecl(); |
| 181 if (!pointee_type) |
| 182 return false; |
| 183 |
| 184 if (!IsVisitor(pointee_type->getName())) |
| 185 return false; |
| 186 |
| 187 return true; |
| 188 } |
| 189 |
| 190 static bool IsVisitorDispatcherType(const clang::QualType& formal_type) { |
| 191 if (const clang::SubstTemplateTypeParmType* subst_type = |
| 192 clang::dyn_cast<clang::SubstTemplateTypeParmType>( |
| 193 formal_type.getTypePtr())) { |
| 194 if (IsVisitorPtrType(subst_type->getReplacementType())) { |
| 195 // VisitorDispatcher template parameter substituted to Visitor*. |
| 196 return true; |
| 197 } |
| 198 } else if (const clang::TemplateTypeParmType* parm_type = |
| 199 clang::dyn_cast<clang::TemplateTypeParmType>( |
| 200 formal_type.getTypePtr())) { |
| 201 if (parm_type->getDecl()->getName() == kVisitorDispatcherName) { |
| 202 // Unresolved, but its parameter name is VisitorDispatcher. |
| 203 return true; |
| 204 } |
| 205 } |
| 206 |
| 207 return IsVisitorPtrType(formal_type); |
| 208 } |
| 209 |
| 210 enum TraceMethodType { |
| 211 NOT_TRACE_METHOD, |
| 212 TRACE_METHOD, |
| 213 TRACE_AFTER_DISPATCH_METHOD, |
| 214 TRACE_IMPL_METHOD, |
| 215 TRACE_AFTER_DISPATCH_IMPL_METHOD |
| 216 }; |
| 217 |
| 218 static TraceMethodType GetTraceMethodType(const clang::FunctionDecl* method) { |
| 219 if (method->getNumParams() != 1) |
| 220 return NOT_TRACE_METHOD; |
| 221 |
| 222 const std::string& name = method->getNameAsString(); |
| 223 if (name != kTraceName && name != kTraceAfterDispatchName && |
| 224 name != kTraceImplName && name != kTraceAfterDispatchImplName) |
| 225 return NOT_TRACE_METHOD; |
| 226 |
| 227 const clang::QualType& formal_type = method->getParamDecl(0)->getType(); |
| 228 if (name == kTraceImplName || name == kTraceAfterDispatchImplName) { |
| 229 if (!IsVisitorDispatcherType(formal_type)) |
| 230 return NOT_TRACE_METHOD; |
| 231 } else if (!IsVisitorPtrType(formal_type)) { |
| 232 return NOT_TRACE_METHOD; |
| 233 } |
| 234 |
| 235 if (name == kTraceName) |
| 236 return TRACE_METHOD; |
| 237 if (name == kTraceAfterDispatchName) |
| 238 return TRACE_AFTER_DISPATCH_METHOD; |
| 239 if (name == kTraceImplName) |
| 240 return TRACE_IMPL_METHOD; |
| 241 if (name == kTraceAfterDispatchImplName) |
| 242 return TRACE_AFTER_DISPATCH_IMPL_METHOD; |
| 243 |
| 244 assert(false && "Should not reach here"); |
| 245 return NOT_TRACE_METHOD; |
| 246 } |
| 247 |
| 248 static bool IsTraceMethod(const clang::FunctionDecl* method) { |
| 249 return GetTraceMethodType(method) != NOT_TRACE_METHOD; |
| 250 } |
| 251 |
| 252 static bool IsTraceImplName(const std::string& name) { |
| 253 return name == kTraceImplName || name == kTraceAfterDispatchImplName; |
| 254 } |
| 255 |
| 256 static bool StartsWith(const std::string& str, const std::string& prefix) { |
| 257 if (prefix.size() > str.size()) |
| 258 return false; |
| 259 return str.compare(0, prefix.size(), prefix) == 0; |
| 260 } |
| 261 |
| 262 static bool EndsWith(const std::string& str, const std::string& suffix) { |
| 263 if (suffix.size() > str.size()) |
| 264 return false; |
| 265 return str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; |
| 266 } |
| 267 |
| 268 // Test if a template specialization is an instantiation. |
| 269 static bool IsTemplateInstantiation(clang::CXXRecordDecl* record); |
| 270 }; |
| 271 |
| 272 #endif // TOOLS_BLINK_GC_PLUGIN_CONFIG_H_ |
OLD | NEW |