Gardening: Speculative build fix for Windows.
[WebKit-https.git] / Source / WTF / wtf / PtrTag.h
1 /*
2  * Copyright (C) 2018 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #pragma once
27
28 #include <wtf/PointerPreparations.h>
29
30 namespace WTF {
31
32 #define FOR_EACH_BASE_WTF_PTRTAG(v) \
33     v(NoPtrTag) \
34     v(CFunctionPtrTag) \
35
36 #define FOR_EACH_ADDITIONAL_WTF_PTRTAG(v) \
37
38 #define FOR_EACH_WTF_PTRTAG(v) \
39     FOR_EACH_BASE_WTF_PTRTAG(v) \
40     FOR_EACH_ADDITIONAL_WTF_PTRTAG(v) \
41
42 enum PtrTag : uintptr_t {
43     NoPtrTag,
44     CFunctionPtrTag,
45 };
46
47 #ifndef WTF_PTRTAG_HASH
48 template<size_t N>
49 constexpr uintptr_t makePtrTagHash(const char (&str)[N])
50 {
51     uintptr_t result = 134775813;
52     for (size_t i = 0; i < N; ++i)
53         result += ((result * str[i]) ^ (result >> 16));
54     return result & 0xffff;
55 }
56
57 #define WTF_PTRTAG_HASH(tag) WTF::makePtrTagHash(#tag)
58 #endif
59
60 #define WTF_DECLARE_PTRTAG(tag) \
61     constexpr PtrTag tag = static_cast<PtrTag>(WTF_PTRTAG_HASH(#tag)); \
62     static_assert(tag != NoPtrTag && tag != CFunctionPtrTag, "");
63
64 static_assert(static_cast<uintptr_t>(NoPtrTag) == static_cast<uintptr_t>(0), "");
65 static_assert(static_cast<uintptr_t>(CFunctionPtrTag) == static_cast<uintptr_t>(1), "");
66
67 #if COMPILER(MSVC)
68 #pragma warning(push)
69 #pragma warning(disable:4307)
70 #endif
71
72 FOR_EACH_ADDITIONAL_WTF_PTRTAG(WTF_DECLARE_PTRTAG)
73
74 #if COMPILER(MSVC)
75 #pragma warning(pop)
76 #endif
77
78 #if !USE(POINTER_PROFILING)
79
80 inline const char* tagForPtr(const void*) { return "<no tag>"; }
81
82 template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
83 inline constexpr T tagCodePtr(PtrType ptr, PtrTag) { return bitwise_cast<T>(ptr); }
84
85 template<typename T, PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
86 inline T tagCodePtr(PtrType ptr) { return bitwise_cast<T>(ptr); }
87
88 template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
89 inline constexpr PtrType tagCodePtr(PtrType ptr, PtrTag) { return ptr; }
90
91 template<PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
92 inline PtrType tagCodePtr(PtrType ptr) { return ptr; }
93
94 template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
95 inline constexpr T untagCodePtr(PtrType ptr, PtrTag) { return bitwise_cast<T>(ptr); }
96
97 template<typename T, PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
98 inline T untagCodePtr(PtrType ptr)  { return bitwise_cast<T>(ptr); }
99
100 template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
101 inline constexpr PtrType untagCodePtr(PtrType ptr, PtrTag) { return ptr; }
102
103 template<PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
104 inline PtrType untagCodePtr(PtrType ptr) { return ptr; }
105
106 template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
107 inline constexpr T retagCodePtr(PtrType ptr, PtrTag, PtrTag) { return bitwise_cast<T>(ptr); }
108
109 template<typename T, PtrTag, PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
110 inline T retagCodePtr(PtrType ptr) { return bitwise_cast<T>(ptr); }
111
112 template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
113 inline constexpr PtrType retagCodePtr(PtrType ptr, PtrTag, PtrTag) { return ptr; }
114
115 template<PtrTag, PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
116 inline PtrType retagCodePtr(PtrType ptr) { return ptr; }
117
118 template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
119 inline constexpr T removeCodePtrTag(PtrType ptr) { return bitwise_cast<T>(ptr); }
120
121 template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
122 inline constexpr PtrType removeCodePtrTag(PtrType ptr) { return ptr; }
123
124 template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
125 inline T tagCFunctionPtr(PtrType ptr, PtrTag) { return bitwise_cast<T>(ptr); }
126
127 template<typename T, PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
128 inline T tagCFunctionPtr(PtrType ptr) { return bitwise_cast<T>(ptr); }
129
130 template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
131 inline PtrType tagCFunctionPtr(PtrType ptr, PtrTag) { return ptr; }
132
133 template<PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
134 inline PtrType tagCFunctionPtr(PtrType ptr) { return ptr; }
135
136 template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>>
137 inline T untagCFunctionPtr(PtrType ptr, PtrTag) { return bitwise_cast<T>(ptr); }
138
139 template<typename T, PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
140 inline T untagCFunctionPtr(PtrType ptr) { return bitwise_cast<T>(ptr); }
141
142 template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
143 inline PtrType untagCFunctionPtr(PtrType ptr, PtrTag) { return ptr; }
144
145 template<PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>>
146 inline PtrType untagCFunctionPtr(PtrType ptr) { return ptr; }
147
148 template<typename PtrType> void assertIsCFunctionPtr(PtrType) { }
149 template<typename PtrType> void assertIsNullOrCFunctionPtr(PtrType) { }
150
151 template<typename PtrType> void assertIsNotTagged(PtrType) { }
152 template<typename PtrType> void assertIsTagged(PtrType) { }
153 template<typename PtrType> void assertIsNullOrTagged(PtrType) { }
154
155 template<typename PtrType> void assertIsTaggedWith(PtrType, PtrTag) { }
156 template<typename PtrType> void assertIsNullOrTaggedWith(PtrType, PtrTag) { }
157
158 #define CALL_WITH_PTRTAG(callInstructionString, targetRegisterString, tag) \
159     callInstructionString " " targetRegisterString "\n"
160
161 #endif // !USE(POINTER_PROFILING)
162
163 } // namespace WTF
164
165 using WTF::CFunctionPtrTag;
166 using WTF::NoPtrTag;
167 using WTF::PtrTag;
168
169 #if USE(APPLE_INTERNAL_SDK) && __has_include(<WebKitAdditions/PtrTagSupport.h>)
170 #include <WebKitAdditions/PtrTagSupport.h>
171 #endif
172
173 using WTF::tagForPtr;
174
175 using WTF::tagCodePtr;
176 using WTF::untagCodePtr;
177 using WTF::retagCodePtr;
178 using WTF::removeCodePtrTag;
179 using WTF::tagCFunctionPtr;
180 using WTF::untagCFunctionPtr;
181
182 using WTF::assertIsCFunctionPtr;
183 using WTF::assertIsNullOrCFunctionPtr;
184 using WTF::assertIsNotTagged;
185 using WTF::assertIsTagged;
186 using WTF::assertIsNullOrTagged;
187 using WTF::assertIsTaggedWith;
188 using WTF::assertIsNullOrTaggedWith;