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#ifndef TOOLS_BLINK_GC_PLUGIN_CONFIG_H_
8#define TOOLS_BLINK_GC_PLUGIN_CONFIG_H_
9
10#include "clang/AST/AST.h"
11#include "clang/AST/Attr.h"
12
13const char kNewOperatorName[] = "operator new";
14const char kCreateName[] = "create";
15const char kTraceName[] = "trace";
16const char kFinalizeName[] = "finalizeGarbageCollectedObject";
17const char kTraceAfterDispatchName[] = "traceAfterDispatch";
18const char kRegisterWeakMembersName[] = "registerWeakMembers";
19const char kHeapAllocatorName[] = "HeapAllocator";
20const char kTraceIfNeededName[] = "TraceIfNeeded";
21
22class Config {
23 public:
24  static bool IsMember(const std::string& name) {
25    return name == "Member";
26  }
27
28  static bool IsWeakMember(const std::string& name) {
29    return name == "WeakMember";
30  }
31
32  static bool IsMemberHandle(const std::string& name) {
33    return IsMember(name) ||
34           IsWeakMember(name);
35  }
36
37  static bool IsPersistent(const std::string& name) {
38    return name == "Persistent";
39  }
40
41  static bool IsPersistentHandle(const std::string& name) {
42    return IsPersistent(name) ||
43           IsPersistentGCCollection(name);
44  }
45
46  static bool IsRawPtr(const std::string& name) {
47    return name == "RawPtr";
48  }
49
50  static bool IsRefPtr(const std::string& name) {
51    return name == "RefPtr";
52  }
53
54  static bool IsOwnPtr(const std::string& name) {
55    return name == "OwnPtr";
56  }
57
58  static bool IsWTFCollection(const std::string& name) {
59    return name == "Vector" ||
60           name == "Deque" ||
61           name == "HashSet" ||
62           name == "ListHashSet" ||
63           name == "LinkedHashSet" ||
64           name == "HashCountedSet" ||
65           name == "HashMap";
66  }
67
68  static bool IsGCCollection(const std::string& name) {
69    return name == "HeapVector" ||
70           name == "HeapDeque" ||
71           name == "HeapHashSet" ||
72           name == "HeapListHashSet" ||
73           name == "HeapLinkedHashSet" ||
74           name == "HeapHashCountedSet" ||
75           name == "HeapHashMap" ||
76           IsPersistentGCCollection(name);
77  }
78
79  static bool IsPersistentGCCollection(const std::string& name) {
80    return name == "PersistentHeapVector" ||
81           name == "PersistentHeapDeque" ||
82           name == "PersistentHeapHashSet" ||
83           name == "PersistentHeapListHashSet" ||
84           name == "PersistentHeapLinkedHashSet" ||
85           name == "PersistentHeapHashCountedSet" ||
86           name == "PersistentHeapHashMap";
87  }
88
89  static bool IsHashMap(const std::string& name) {
90    return name == "HashMap" ||
91           name == "HeapHashMap" ||
92           name == "PersistentHeapHashMap";
93  }
94
95  // Following http://crrev.com/369633033 (Blink r177436),
96  // ignore blink::ScriptWrappable's destructor.
97  // FIXME: remove when its non-Oilpan destructor is removed.
98  static bool HasIgnorableDestructor(const std::string& ns,
99                                     const std::string& name) {
100    return ns == "blink" && name == "ScriptWrappable";
101  }
102
103  // Assumes name is a valid collection name.
104  static size_t CollectionDimension(const std::string& name) {
105    return (IsHashMap(name) || name == "pair") ? 2 : 1;
106  }
107
108  static bool IsDummyBase(const std::string& name) {
109    return name == "DummyBase";
110  }
111
112  static bool IsRefCountedBase(const std::string& name) {
113    return name == "RefCounted" ||
114           name == "ThreadSafeRefCounted";
115  }
116
117  static bool IsGCMixinBase(const std::string& name) {
118    return name == "GarbageCollectedMixin";
119  }
120
121  static bool IsGCFinalizedBase(const std::string& name) {
122    return name == "GarbageCollectedFinalized" ||
123           name == "RefCountedGarbageCollected" ||
124           name == "ThreadSafeRefCountedGarbageCollected";
125  }
126
127  static bool IsGCBase(const std::string& name) {
128    return name == "GarbageCollected" ||
129           IsGCFinalizedBase(name) ||
130           IsGCMixinBase(name);
131  }
132
133  // Returns true of the base classes that do not need a vtable entry for trace
134  // because they cannot possibly initiate a GC during construction.
135  static bool IsSafePolymorphicBase(const std::string& name) {
136    return IsGCBase(name) || IsDummyBase(name) || IsRefCountedBase(name);
137  }
138
139  static bool IsAnnotated(clang::Decl* decl, const std::string& anno) {
140    clang::AnnotateAttr* attr = decl->getAttr<clang::AnnotateAttr>();
141    return attr && (attr->getAnnotation() == anno);
142  }
143
144  static bool IsStackAnnotated(clang::Decl* decl) {
145    return IsAnnotated(decl, "blink_stack_allocated");
146  }
147
148  static bool IsIgnoreAnnotated(clang::Decl* decl) {
149    return IsAnnotated(decl, "blink_gc_plugin_ignore");
150  }
151
152  static bool IsIgnoreCycleAnnotated(clang::Decl* decl) {
153    return IsAnnotated(decl, "blink_gc_plugin_ignore_cycle") ||
154           IsIgnoreAnnotated(decl);
155  }
156
157  static bool IsVisitor(const std::string& name) { return name == "Visitor"; }
158
159  static bool IsTraceMethod(clang::FunctionDecl* method,
160                            bool* isTraceAfterDispatch = 0) {
161    if (method->getNumParams() != 1)
162      return false;
163
164    const std::string& name = method->getNameAsString();
165    if (name != kTraceName && name != kTraceAfterDispatchName)
166      return false;
167
168    const clang::QualType& formal_type = method->getParamDecl(0)->getType();
169    if (!formal_type->isPointerType())
170      return false;
171
172    clang::CXXRecordDecl* pointee_type =
173        formal_type->getPointeeType()->getAsCXXRecordDecl();
174    if (!pointee_type)
175      return false;
176
177    if (!IsVisitor(pointee_type->getName()))
178      return false;
179
180    if (isTraceAfterDispatch)
181      *isTraceAfterDispatch = (name == kTraceAfterDispatchName);
182    return true;
183  }
184
185  static bool StartsWith(const std::string& str, const std::string& prefix) {
186    if (prefix.size() > str.size())
187      return false;
188    return str.compare(0, prefix.size(), prefix) == 0;
189  }
190
191  static bool EndsWith(const std::string& str, const std::string& suffix) {
192    if (suffix.size() > str.size())
193      return false;
194    return str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
195  }
196};
197
198#endif  // TOOLS_BLINK_GC_PLUGIN_CONFIG_H_
199