14a9b743dc74906c125bb8be004a5efa29220e7e
[WebKit-https.git] / Source / JavaScriptCore / assembler / MacroAssemblerCodeRef.h
1 /*
2  * Copyright (C) 2009-2019 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 "ExecutableAllocator.h"
29 #include "JSCPtrTag.h"
30 #include <wtf/DataLog.h>
31 #include <wtf/PrintStream.h>
32 #include <wtf/RefPtr.h>
33 #include <wtf/text/CString.h>
34
35 // ASSERT_VALID_CODE_POINTER checks that ptr is a non-null pointer, and that it is a valid
36 // instruction address on the platform (for example, check any alignment requirements).
37 #if CPU(ARM_THUMB2) && ENABLE(JIT)
38 // ARM instructions must be 16-bit aligned. Thumb2 code pointers to be loaded into
39 // into the processor are decorated with the bottom bit set, while traditional ARM has
40 // the lower bit clear. Since we don't know what kind of pointer, we check for both
41 // decorated and undecorated null.
42 #define ASSERT_NULL_OR_VALID_CODE_POINTER(ptr) \
43     ASSERT(!ptr || reinterpret_cast<intptr_t>(ptr) & ~1)
44 #define ASSERT_VALID_CODE_POINTER(ptr) \
45     ASSERT(reinterpret_cast<intptr_t>(ptr) & ~1)
46 #define ASSERT_VALID_CODE_OFFSET(offset) \
47     ASSERT(!(offset & 1)) // Must be multiple of 2.
48 #else
49 #define ASSERT_NULL_OR_VALID_CODE_POINTER(ptr) // Anything goes!
50 #define ASSERT_VALID_CODE_POINTER(ptr) \
51     ASSERT(ptr)
52 #define ASSERT_VALID_CODE_OFFSET(offset) // Anything goes!
53 #endif
54
55 namespace JSC {
56
57 template<PtrTag> class MacroAssemblerCodePtr;
58
59 enum OpcodeID : unsigned;
60
61 // FunctionPtr:
62 //
63 // FunctionPtr should be used to wrap pointers to C/C++ functions in JSC
64 // (particularly, the stub functions).
65 template<PtrTag tag = CFunctionPtrTag>
66 class FunctionPtr {
67 public:
68     FunctionPtr() { }
69     FunctionPtr(std::nullptr_t) { }
70
71     template<typename ReturnType, typename... Arguments>
72     FunctionPtr(ReturnType(*value)(Arguments...))
73         : m_value(tagCFunctionPtr<void*, tag>(value))
74     {
75         assertIsNullOrCFunctionPtr(value);
76         ASSERT_NULL_OR_VALID_CODE_POINTER(m_value);
77     }
78
79 // MSVC doesn't seem to treat functions with different calling conventions as
80 // different types; these methods already defined for fastcall, below.
81 #if CALLING_CONVENTION_IS_STDCALL && !OS(WINDOWS)
82
83     template<typename ReturnType, typename... Arguments>
84     FunctionPtr(ReturnType(CDECL *value)(Arguments...))
85         : m_value(tagCFunctionPtr<void*, tag>(value))
86     {
87         assertIsNullOrCFunctionPtr(value);
88         ASSERT_NULL_OR_VALID_CODE_POINTER(m_value);
89     }
90
91 #endif // CALLING_CONVENTION_IS_STDCALL && !OS(WINDOWS)
92
93 #if COMPILER_SUPPORTS(FASTCALL_CALLING_CONVENTION)
94
95     template<typename ReturnType, typename... Arguments>
96     FunctionPtr(ReturnType(FASTCALL *value)(Arguments...))
97         : m_value(tagCFunctionPtr<void*, tag>(value))
98     {
99         assertIsNullOrCFunctionPtr(value);
100         ASSERT_NULL_OR_VALID_CODE_POINTER(m_value);
101     }
102
103 #endif // COMPILER_SUPPORTS(FASTCALL_CALLING_CONVENTION)
104
105     template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_function<typename std::remove_pointer<PtrType>::type>::value>>
106     explicit FunctionPtr(PtrType value)
107         // Using a C-ctyle cast here to avoid compiler error on RVTC:
108         // Error:  #694: reinterpret_cast cannot cast away const or other type qualifiers
109         // (I guess on RVTC function pointers have a different constness to GCC/MSVC?)
110         : m_value(tagCFunctionPtr<void*, tag>(value))
111     {
112         assertIsNullOrCFunctionPtr(value);
113         ASSERT_NULL_OR_VALID_CODE_POINTER(m_value);
114     }
115
116     explicit FunctionPtr(MacroAssemblerCodePtr<tag>);
117
118     template<PtrTag otherTag>
119     FunctionPtr<otherTag> retagged() const
120     {
121         if (!m_value)
122             return FunctionPtr<otherTag>();
123         return FunctionPtr<otherTag>(*this);
124     }
125
126     void* executableAddress() const
127     {
128         return m_value;
129     }
130
131     template<PtrTag newTag>
132     void* retaggedExecutableAddress() const
133     {
134         return retagCodePtr<tag, newTag>(m_value);
135     }
136
137     explicit operator bool() const { return !!m_value; }
138     bool operator!() const { return !m_value; }
139
140     bool operator==(const FunctionPtr& other) const { return m_value == other.m_value; }
141     bool operator!=(const FunctionPtr& other) const { return m_value != other.m_value; }
142
143 private:
144     template<PtrTag otherTag>
145     explicit FunctionPtr(const FunctionPtr<otherTag>& other)
146         : m_value(retagCodePtr<otherTag, tag>(other.executableAddress()))
147     {
148         ASSERT_NULL_OR_VALID_CODE_POINTER(m_value);
149     }
150
151     void* m_value { nullptr };
152
153     template<PtrTag> friend class FunctionPtr;
154 };
155
156 static_assert(sizeof(FunctionPtr<CFunctionPtrTag>) == sizeof(void*), "");
157 #if COMPILER_SUPPORTS(BUILTIN_IS_TRIVIALLY_COPYABLE)
158 static_assert(__is_trivially_copyable(FunctionPtr<CFunctionPtrTag>), "");
159 #endif
160
161 // ReturnAddressPtr:
162 //
163 // ReturnAddressPtr should be used to wrap return addresses generated by processor
164 // 'call' instructions exectued in JIT code.  We use return addresses to look up
165 // exception and optimization information, and to repatch the call instruction
166 // that is the source of the return address.
167 class ReturnAddressPtr {
168 public:
169     ReturnAddressPtr() { }
170
171     explicit ReturnAddressPtr(const void* value)
172         : m_value(value)
173     {
174         ASSERT_VALID_CODE_POINTER(m_value);
175     }
176
177     template<PtrTag tag>
178     explicit ReturnAddressPtr(FunctionPtr<tag> function)
179         : m_value(untagCodePtr<tag>(function.executableAddress()))
180     {
181         ASSERT_VALID_CODE_POINTER(m_value);
182     }
183
184     const void* value() const
185     {
186         return m_value;
187     }
188     
189     void dump(PrintStream& out) const
190     {
191         out.print(RawPointer(m_value));
192     }
193
194 private:
195     const void* m_value { nullptr };
196 };
197
198 // MacroAssemblerCodePtr:
199 //
200 // MacroAssemblerCodePtr should be used to wrap pointers to JIT generated code.
201 class MacroAssemblerCodePtrBase {
202 protected:
203     static void dumpWithName(void* executableAddress, void* dataLocation, const char* name, PrintStream& out);
204 };
205
206 // FIXME: Make JSC MacroAssemblerCodePtr injerit from MetaAllocatorPtr.
207 // https://bugs.webkit.org/show_bug.cgi?id=185145
208 template<PtrTag tag>
209 class MacroAssemblerCodePtr : private MacroAssemblerCodePtrBase {
210 public:
211     MacroAssemblerCodePtr() = default;
212     MacroAssemblerCodePtr(std::nullptr_t) : m_value(nullptr) { }
213
214     explicit MacroAssemblerCodePtr(const void* value)
215 #if CPU(ARM_THUMB2)
216         // Decorate the pointer as a thumb code pointer.
217         : m_value(reinterpret_cast<const char*>(value) + 1)
218 #else
219         : m_value(value)
220 #endif
221     {
222         assertIsTaggedWith(value, tag);
223         ASSERT(value);
224 #if CPU(ARM_THUMB2)
225         ASSERT(!(reinterpret_cast<uintptr_t>(value) & 1));
226 #endif
227         ASSERT_VALID_CODE_POINTER(m_value);
228     }
229
230     static MacroAssemblerCodePtr createFromExecutableAddress(const void* value)
231     {
232         ASSERT(value);
233         ASSERT_VALID_CODE_POINTER(value);
234         assertIsTaggedWith(value, tag);
235         MacroAssemblerCodePtr result;
236         result.m_value = value;
237         return result;
238     }
239
240     explicit MacroAssemblerCodePtr(ReturnAddressPtr ra)
241         : m_value(tagCodePtr<tag>(ra.value()))
242     {
243         assertIsNotTagged(ra.value());
244         ASSERT(ra.value());
245         ASSERT_VALID_CODE_POINTER(m_value);
246     }
247
248     template<PtrTag newTag>
249     MacroAssemblerCodePtr<newTag> retagged() const
250     {
251         if (!m_value)
252             return MacroAssemblerCodePtr<newTag>();
253         return MacroAssemblerCodePtr<newTag>::createFromExecutableAddress(retaggedExecutableAddress<newTag>());
254     }
255
256     template<typename T = void*>
257     T executableAddress() const
258     {
259         return bitwise_cast<T>(m_value);
260     }
261
262     template<typename T = void*>
263     T untaggedExecutableAddress() const
264     {
265         return untagCodePtr<T, tag>(m_value);
266     }
267
268     template<PtrTag newTag, typename T = void*>
269     T retaggedExecutableAddress() const
270     {
271         return retagCodePtr<T, tag, newTag>(m_value);
272     }
273
274 #if CPU(ARM_THUMB2)
275     // To use this pointer as a data address remove the decoration.
276     template<typename T = void*>
277     T dataLocation() const
278     {
279         ASSERT_VALID_CODE_POINTER(m_value);
280         return bitwise_cast<T>(m_value ? bitwise_cast<char*>(m_value) - 1 : nullptr);
281     }
282 #else
283     template<typename T = void*>
284     T dataLocation() const
285     {
286         ASSERT_VALID_CODE_POINTER(m_value);
287         return untagCodePtr<T, tag>(m_value);
288     }
289 #endif
290
291     bool operator!() const
292     {
293         return !m_value;
294     }
295     explicit operator bool() const { return !(!*this); }
296     
297     bool operator==(const MacroAssemblerCodePtr& other) const
298     {
299         return m_value == other.m_value;
300     }
301
302     // Disallow any casting operations (except for booleans). Instead, the client
303     // should be asking executableAddress() explicitly.
304     template<typename T, typename = std::enable_if_t<!std::is_same<T, bool>::value>>
305     operator T() = delete;
306
307     void dumpWithName(const char* name, PrintStream& out) const
308     {
309         MacroAssemblerCodePtrBase::dumpWithName(executableAddress(), dataLocation(), name, out);
310     }
311
312     void dump(PrintStream& out) const { dumpWithName("CodePtr", out); }
313
314     enum EmptyValueTag { EmptyValue };
315     enum DeletedValueTag { DeletedValue };
316     
317     MacroAssemblerCodePtr(EmptyValueTag)
318         : m_value(emptyValue())
319     { }
320     
321     MacroAssemblerCodePtr(DeletedValueTag)
322         : m_value(deletedValue())
323     { }
324     
325     bool isEmptyValue() const { return m_value == emptyValue(); }
326     bool isDeletedValue() const { return m_value == deletedValue(); }
327
328     unsigned hash() const { return PtrHash<const void*>::hash(m_value); }
329
330     static void initialize();
331
332 private:
333     static const void* emptyValue() { return bitwise_cast<void*>(static_cast<intptr_t>(1)); }
334     static const void* deletedValue() { return bitwise_cast<void*>(static_cast<intptr_t>(2)); }
335
336     const void* m_value { nullptr };
337 };
338
339 template<PtrTag tag>
340 struct MacroAssemblerCodePtrHash {
341     static unsigned hash(const MacroAssemblerCodePtr<tag>& ptr) { return ptr.hash(); }
342     static bool equal(const MacroAssemblerCodePtr<tag>& a, const MacroAssemblerCodePtr<tag>& b)
343     {
344         return a == b;
345     }
346     static const bool safeToCompareToEmptyOrDeleted = true;
347 };
348
349 // MacroAssemblerCodeRef:
350 //
351 // A reference to a section of JIT generated code.  A CodeRef consists of a
352 // pointer to the code, and a ref pointer to the pool from within which it
353 // was allocated.
354 class MacroAssemblerCodeRefBase {
355 protected:
356     static bool tryToDisassemble(MacroAssemblerCodePtr<DisassemblyPtrTag>, size_t, const char* prefix, PrintStream& out);
357     static bool tryToDisassemble(MacroAssemblerCodePtr<DisassemblyPtrTag>, size_t, const char* prefix);
358     JS_EXPORT_PRIVATE static CString disassembly(MacroAssemblerCodePtr<DisassemblyPtrTag>, size_t);
359 };
360
361 template<PtrTag tag>
362 class MacroAssemblerCodeRef : private MacroAssemblerCodeRefBase {
363 private:
364     // This is private because it's dangerous enough that we want uses of it
365     // to be easy to find - hence the static create method below.
366     explicit MacroAssemblerCodeRef(MacroAssemblerCodePtr<tag> codePtr)
367         : m_codePtr(codePtr)
368     {
369         ASSERT(m_codePtr);
370     }
371
372 public:
373     MacroAssemblerCodeRef() = default;
374
375     MacroAssemblerCodeRef(Ref<ExecutableMemoryHandle>&& executableMemory)
376         : m_codePtr(executableMemory->start().retaggedPtr<tag>())
377         , m_executableMemory(WTFMove(executableMemory))
378     {
379         ASSERT(m_executableMemory->isManaged());
380         ASSERT(m_executableMemory->start());
381         ASSERT(m_codePtr);
382     }
383     
384     // Use this only when you know that the codePtr refers to code that is
385     // already being kept alive through some other means. Typically this means
386     // that codePtr is immortal.
387     static MacroAssemblerCodeRef createSelfManagedCodeRef(MacroAssemblerCodePtr<tag> codePtr)
388     {
389         return MacroAssemblerCodeRef(codePtr);
390     }
391     
392     ExecutableMemoryHandle* executableMemory() const
393     {
394         return m_executableMemory.get();
395     }
396     
397     MacroAssemblerCodePtr<tag> code() const
398     {
399         return m_codePtr;
400     }
401
402     template<PtrTag newTag>
403     MacroAssemblerCodePtr<newTag> retaggedCode() const
404     {
405         return m_codePtr.template retagged<newTag>();
406     }
407
408     template<PtrTag newTag>
409     MacroAssemblerCodeRef<newTag> retagged() const
410     {
411         return MacroAssemblerCodeRef<newTag>(*this);
412     }
413
414     size_t size() const
415     {
416         if (!m_executableMemory)
417             return 0;
418         return m_executableMemory->sizeInBytes();
419     }
420
421     bool tryToDisassemble(PrintStream& out, const char* prefix = "") const
422     {
423         return tryToDisassemble(retaggedCode<DisassemblyPtrTag>(), size(), prefix, out);
424     }
425     
426     bool tryToDisassemble(const char* prefix = "") const
427     {
428         return tryToDisassemble(retaggedCode<DisassemblyPtrTag>(), size(), prefix);
429     }
430     
431     CString disassembly() const
432     {
433         return MacroAssemblerCodeRefBase::disassembly(retaggedCode<DisassemblyPtrTag>(), size());
434     }
435     
436     explicit operator bool() const { return !!m_codePtr; }
437     
438     void dump(PrintStream& out) const
439     {
440         m_codePtr.dumpWithName("CodeRef", out);
441     }
442
443 private:
444     template<PtrTag otherTag>
445     MacroAssemblerCodeRef(const MacroAssemblerCodeRef<otherTag>& otherCodeRef)
446         : m_codePtr(MacroAssemblerCodePtr<tag>::createFromExecutableAddress(otherCodeRef.code().template retaggedExecutableAddress<tag>()))
447         , m_executableMemory(otherCodeRef.m_executableMemory)
448     { }
449
450     MacroAssemblerCodePtr<tag> m_codePtr;
451     RefPtr<ExecutableMemoryHandle> m_executableMemory;
452
453     template<PtrTag> friend class MacroAssemblerCodeRef;
454 };
455
456 template<PtrTag tag>
457 inline FunctionPtr<tag>::FunctionPtr(MacroAssemblerCodePtr<tag> ptr)
458     : m_value(ptr.executableAddress())
459 {
460 }
461
462 } // namespace JSC
463
464 namespace WTF {
465
466 template<typename T> struct DefaultHash;
467 template<JSC::PtrTag tag> struct DefaultHash<JSC::MacroAssemblerCodePtr<tag>> {
468     typedef JSC::MacroAssemblerCodePtrHash<tag> Hash;
469 };
470
471 template<typename T> struct HashTraits;
472 template<JSC::PtrTag tag> struct HashTraits<JSC::MacroAssemblerCodePtr<tag>> : public CustomHashTraits<JSC::MacroAssemblerCodePtr<tag>> { };
473
474 } // namespace WTF