Update hhvm version.h
[hiphop-php.git] / hphp / util / type-scan-detail.h
blob2356f33abe00e83016d929880aedb55fb576c3cd
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_UTIL_TYPE_SCAN_DETAIL_H_
18 #define incl_HPHP_UTIL_TYPE_SCAN_DETAIL_H_
20 #include <array>
21 #include <tuple>
24 * Here's how all the type scanner machinery works at a high level:
26 * - All "countable" types (basically ones with explicitly managed ref-counts)
27 * have MarkCollectable<> instantiations.
29 * - Any call to getIndexForMalloc<T> or getIndexForScan<T> present in the
30 * source results in an Indexer<> instantiation, which provides a static
31 * storage location for the type index. The type index is assigned
32 * "kIndexUnknown" at start-up (conveniently this has value 0, so they can be
33 * stored in the .bss).
35 * - The type annotation macros spit out various static fields and member
36 * functions with special names. These static fields may have special types
37 * which are template instantiations containing other types.
39 * - The scanner generator is run during the build, after the final link where
40 * the executable is produced. It parses the debug information inside the
41 * final executable, and sees all the MarkCollectable<T> and Indexer<T>
42 * instantiations. Using these instantiations, as well as the presence of the
43 * specially named fields and member functions, the scanner generator
44 * generates scanning functions. Every Indexer<T> instantiation is assigned a
45 * type-index and a scanner function.
47 * - These generated functions, along with metadata to map the type-index to the
48 * function, is emitted as C++ code and compiled into a shared object. The
49 * shared object includes an initialization function which sets all the static
50 * Indexer<T>::s_index instances to the proper type-index. This can be done
51 * because the fixed address of the static instances can be found in the debug
52 * information.
54 * - Since the final executable has already been produced, the shared object is
55 * embedded into the executable in a custom section. The reason for the shared
56 * object and loading at start-up is due to build system limitations. In
57 * addition, generating the scanner functions after the final executable is
58 * produced provides certain advantages (such as having the final relocated
59 * addresses available).
61 * - Sometime at start-up, the init() function is called. This function finds
62 * the shared object in the custom section, loads it dynamically, and calls
63 * the initialization function within it. This function, as described above,
64 * initializes all the type indices to their generated values.
66 * - The memory manager calls getIndexForMalloc<T> for all allocations, and
67 * stores the returned type-index somewhere it can be retrieved later.
69 * - The garbage collector instantiates Scanner, calls Scanner::scan() for
70 * roots, and Scanner::scanByIndex() for values on the request heap (using the
71 * stored type-index). The Scanner is populated with pointers found by the
72 * scanners (both automatically generated and custom). The GC uses these
73 * pointers to further populate the worklist.
76 namespace HPHP { namespace type_scan {
78 ////////////////////////////////////////////////////////////////////////////////
80 struct Scanner;
82 namespace detail {
84 ////////////////////////////////////////////////////////////////////////////////
86 // A special action used internally to designate that this type index does not
87 // represent a type being allocated on the heap. Instead, the type index will
88 // just be used for scanning. This is useful because we won't consider pointers
89 // to such types as being "interesting" (because they can't be sitting in the
90 // request heap).
91 struct ScanAction {};
94 * Instantiations of Indexer<> is the signal to the scanner generator to
95 * allocate a type-index for that particular type and to generate a matching
96 * scanner function.
98 * The static member "s_index" stores the assigned type-index corresponding to
99 * this Indexer<>. At start-up, all Indexer<>::s_index instantiations default to
100 * kIndexUnknown, but when the type scanning infrastructure is initialized, the
101 * generated code will overwrite all the s_index instances with their proper
102 * type-indices. (It can do this because it knows the addresses of all the
103 * instances from the debug information).
105 template <typename T, typename A> struct Indexer {
106 static volatile Index
107 ATTRIBUTE_USED ATTRIBUTE_UNUSED EXTERNALLY_VISIBLE s_index;
108 // This is never used, but Clang needs it or it emits *no* debug information
109 // about A.
110 A m_action;
113 template <typename T, typename A>
114 volatile Index ATTRIBUTE_USED Indexer<T, A>::s_index = kIndexUnknown;
116 // Empty types used as part of type annotations. These types don't really
117 // matter, as the behavior is inferred from the field names.
118 struct IgnoreField {};
119 struct ConservativeField {};
120 struct FlexibleArrayField {};
121 template <typename... T> struct IgnoreBase {};
122 template <typename... T> struct CustomBase {};
123 template <typename... T> struct Custom {};
124 template <typename... T> struct SilenceForbiddenBase {};
126 // Template metaprogramming to determine statically if a type is
127 // uninteresting. This is mainly primitive types (like int), and pointers or
128 // references to such. Also includes some overloads to handle types of such like
129 // pair, tuple, or array.
131 template <typename T, typename = void>
132 struct UninterestingImpl : std::false_type {};
134 template <typename T>
135 struct UninterestingImpl<
137 typename std::enable_if<std::is_pointer<T>::value>::type
138 > : std::conditional<
139 std::is_void<typename std::remove_pointer<T>::type>::value,
140 std::false_type,
141 UninterestingImpl<
142 typename std::remove_cv<typename std::remove_pointer<T>::type>::type
144 >::type {};
146 template <typename T>
147 struct UninterestingImpl<
149 typename std::enable_if<std::is_reference<T>::value>::type
150 > : UninterestingImpl<
151 typename std::remove_cv<typename std::remove_reference<T>::type>::type
152 > {};
154 template <typename T>
155 struct UninterestingImpl<
157 typename std::enable_if<std::is_array<T>::value>::type
158 > : UninterestingImpl<
159 typename std::remove_cv<typename std::remove_all_extents<T>::type>::type
160 > {};
162 template <typename T, std::size_t N>
163 struct UninterestingImpl<std::array<T, N>> :
164 UninterestingImpl<typename std::remove_cv<T>::type> {};
166 template <typename T, typename U>
167 struct UninterestingImpl<std::pair<T, U>> : std::conditional<
168 UninterestingImpl<typename std::remove_cv<T>::type>::value,
169 UninterestingImpl<typename std::remove_cv<U>::type>,
170 std::false_type
171 >::type {};
173 template <typename T, typename... U>
174 struct UninterestingImpl<std::tuple<T, U...>> : std::conditional<
175 UninterestingImpl<typename std::remove_cv<T>::type>::value,
176 UninterestingImpl<std::tuple<typename std::remove_cv<U>::type...>>,
177 std::false_type
178 > {};
179 template <> struct UninterestingImpl<std::tuple<>> : std::true_type {};
181 template <typename T>
182 struct UninterestingImpl<
184 typename std::enable_if<
185 std::is_fundamental<T>::value ||
186 std::is_enum<T>::value ||
187 std::is_member_pointer<T>::value ||
188 std::is_function<T>::value
189 >::type
190 > : std::true_type {};
192 template <typename T> using Uninteresting =
193 UninterestingImpl<typename std::remove_cv<T>::type>;
195 // Template metaprogramming to determine if a type is some kind of pointer to
196 // void. IE, void*, void**, etc, etc, as well as some overloads to handle types
197 // like pair/tuple/array of such.
198 template <typename T, typename = void>
199 struct IsVoidImpl : std::false_type {};
201 template <typename T>
202 struct IsVoidImpl <
204 typename std::enable_if<std::is_pointer<T>::value>::type
205 > : std::conditional<
206 std::is_void<typename std::remove_pointer<T>::type>::value,
207 std::true_type,
208 IsVoidImpl<
209 typename std::remove_cv<typename std::remove_pointer<T>::type>::type
211 >::type {};
213 template <typename T>
214 struct IsVoidImpl<
216 typename std::enable_if<std::is_reference<T>::value>::type
217 > : IsVoidImpl<
218 typename std::remove_cv<typename std::remove_reference<T>::type>::type
219 > {};
221 template <typename T>
222 struct IsVoidImpl<
224 typename std::enable_if<std::is_array<T>::value>::type
225 > : IsVoidImpl<
226 typename std::remove_cv<typename std::remove_all_extents<T>::type>::type
227 > {};
229 template <typename T, std::size_t N>
230 struct IsVoidImpl<std::array<T, N>> :
231 IsVoidImpl<typename std::remove_cv<T>::type> {};
233 template <typename T, typename U>
234 struct IsVoidImpl<std::pair<T, U>> : std::conditional<
235 IsVoidImpl<typename std::remove_cv<T>::type>::value,
236 std::true_type,
237 IsVoidImpl<typename std::remove_cv<U>::type>
238 >::type {};
240 template <typename T, typename... U>
241 struct IsVoidImpl<std::tuple<T, U...>> : std::conditional<
242 IsVoidImpl<typename std::remove_cv<T>::type>::value,
243 std::true_type,
244 IsVoidImpl<std::tuple<typename std::remove_cv<U>::type...>>
245 > {};
246 template <> struct IsVoidImpl<std::tuple<>> : std::false_type {};
248 template <typename T> using IsVoid =
249 IsVoidImpl<typename std::remove_cv<T>::type>;
251 // Template metaprogramming to check for unbounded arrays (arrays with no
252 // specified size).
253 template <typename T> struct UnboundedArrayImpl : std::false_type {};
254 template <typename T> struct UnboundedArrayImpl<T[]> : std::true_type {};
255 // ??? GCC considers a flexible array member as an array of size 0 (not
256 // unbounded).
257 template <typename T> struct UnboundedArrayImpl<T[0]> : std::true_type {};
259 template <typename T> using UnboundedArray =
260 UnboundedArrayImpl<typename std::remove_cv<T>::type>;
262 // Table of type names and scanner function pointers indexed by type-index. At
263 // start-up, this table will just have two fixed entries (for the two "unknown"
264 // type-indices), but initializating the type scanning machinery will replace it
265 // with the proper table.
266 struct Metadata {
267 const char* const m_name;
268 void (*m_scan)(Scanner&, const void*, std::size_t);
270 extern const Metadata* g_metadata_table;
271 extern std::size_t g_metadata_table_size;
273 // Check if a type with the given name is on the list of explicitly ignored
274 // types. Certain types might give the scanner generator problems, but we can't
275 // add annotations because we do not control its definition (IE, a third-party
276 // type). These types usually aren't relevant to GC, so a list of types to
277 // explicitly ignore is maintained. The template portion (if any) of the type
278 // name is ignored.
279 bool isIgnoredType(const std::string& name);
281 // Check if a type with the given name is on the list of template types which
282 // cannot contain request heap allocated types. This is mainly for templates
283 // (like the standard containers) where we have request heap aware versions and
284 // is to prevent people accidently using the standard kind.
285 bool isForbiddenTemplate(const std::string& name);
287 // Check if a type with the given name is on the list of template types which
288 // will always be scanned conservatively.
289 bool isForcedConservativeTemplate(const std::string& name);
291 // Macro trickery to generate field names for type annotations.
292 #define TYPE_SCAN_BUILD_NAME(A,B) TYPE_SCAN_BUILD_NAME_HIDDEN(A,B)
293 #define TYPE_SCAN_BUILD_NAME_HIDDEN(A,B) A##B##_
295 #define TYPE_SCAN_CUSTOM_GUARD_NAME _type_scan_custom_guard_
296 #define TYPE_SCAN_CUSTOM_NAME _type_scan_custom_
297 #define TYPE_SCAN_CUSTOM_FIELD_NAME _type_scan_custom_field_
298 #define TYPE_SCAN_CUSTOM_BASES_NAME _type_scan_custom_bases_
299 #define TYPE_SCAN_CUSTOM_BASES_SCANNER_NAME _type_scan_custom_bases_scanner_
300 #define TYPE_SCAN_IGNORE_NAME _type_scan_ignore_
301 #define TYPE_SCAN_IGNORE_FIELD_NAME _type_scan_ignore_field_
302 #define TYPE_SCAN_IGNORE_BASE_NAME _type_scan_ignore_base_
303 #define TYPE_SCAN_CONSERVATIVE_NAME _type_scan_conservative_
304 #define TYPE_SCAN_CONSERVATIVE_FIELD_NAME _type_scan_conservative_field_
305 #define TYPE_SCAN_FLEXIBLE_ARRAY_FIELD_NAME _type_scan_flexible_array_field_
306 #define TYPE_SCAN_SILENCE_FORBIDDEN_BASE_NAME _type_scan_silence_forbidden_base_
308 constexpr const char* const kInitFuncName = "hphp_type_scan_module_init";
310 #define TYPE_SCAN_STRINGIFY(X) TYPE_SCAN_STRINGIFY_HIDDEN(X)
311 #define TYPE_SCAN_STRINGIFY_HIDDEN(X) #X
313 // Store all the special field names which act as type annotations as static
314 // constants. This lets us the scanner generator use them while ignoring the
315 // macro versions.
316 constexpr const char* const kCustomGuardName =
317 TYPE_SCAN_STRINGIFY(TYPE_SCAN_CUSTOM_GUARD_NAME);
318 constexpr const char* const kCustomName =
319 TYPE_SCAN_STRINGIFY(TYPE_SCAN_CUSTOM_NAME);
320 constexpr const char* const kCustomFieldName =
321 TYPE_SCAN_STRINGIFY(TYPE_SCAN_CUSTOM_FIELD_NAME);
322 constexpr const char* const kCustomBasesName =
323 TYPE_SCAN_STRINGIFY(TYPE_SCAN_CUSTOM_BASES_NAME);
324 constexpr const char* const kCustomBasesScannerName =
325 TYPE_SCAN_STRINGIFY(TYPE_SCAN_CUSTOM_BASES_SCANNER_NAME);
326 constexpr const char* const kIgnoreName =
327 TYPE_SCAN_STRINGIFY(TYPE_SCAN_IGNORE_NAME);
328 constexpr const char* const kIgnoreFieldName =
329 TYPE_SCAN_STRINGIFY(TYPE_SCAN_IGNORE_FIELD_NAME);
330 constexpr const char* const kIgnoreBaseName =
331 TYPE_SCAN_STRINGIFY(TYPE_SCAN_IGNORE_BASE_NAME);
332 constexpr const char* const kConservativeName =
333 TYPE_SCAN_STRINGIFY(TYPE_SCAN_CONSERVATIVE_NAME);
334 constexpr const char* const kConservativeFieldName =
335 TYPE_SCAN_STRINGIFY(TYPE_SCAN_CONSERVATIVE_FIELD_NAME);
336 constexpr const char* const kFlexibleArrayFieldName =
337 TYPE_SCAN_STRINGIFY(TYPE_SCAN_FLEXIBLE_ARRAY_FIELD_NAME);
338 constexpr const char* const kSilenceForbiddenBaseName =
339 TYPE_SCAN_STRINGIFY(TYPE_SCAN_SILENCE_FORBIDDEN_BASE_NAME);
341 #undef TYPE_SCAN_STRINGIFY_HIDDEN
342 #undef TYPE_SCAN_STRINGIFY
344 ////////////////////////////////////////////////////////////////////////////////
348 #endif