Teach Call ICs how to call Wasm
[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     template<PtrTag otherTag>
385     MacroAssemblerCodeRef& operator=(const MacroAssemblerCodeRef<otherTag>& otherCodeRef)
386     {
387         m_codePtr = MacroAssemblerCodePtr<tag>::createFromExecutableAddress(otherCodeRef.code().template retaggedExecutableAddress<tag>());
388         m_executableMemory = otherCodeRef.m_executableMemory;
389         return *this;
390     }
391     
392     // Use this only when you know that the codePtr refers to code that is
393     // already being kept alive through some other means. Typically this means
394     // that codePtr is immortal.
395     static MacroAssemblerCodeRef createSelfManagedCodeRef(MacroAssemblerCodePtr<tag> codePtr)
396     {
397         return MacroAssemblerCodeRef(codePtr);
398     }
399     
400     ExecutableMemoryHandle* executableMemory() const
401     {
402         return m_executableMemory.get();
403     }
404     
405     MacroAssemblerCodePtr<tag> code() const
406     {
407         return m_codePtr;
408     }
409
410     template<PtrTag newTag>
411     MacroAssemblerCodePtr<newTag> retaggedCode() const
412     {
413         return m_codePtr.template retagged<newTag>();
414     }
415
416     template<PtrTag newTag>
417     MacroAssemblerCodeRef<newTag> retagged() const
418     {
419         return MacroAssemblerCodeRef<newTag>(*this);
420     }
421
422     size_t size() const
423     {
424         if (!m_executableMemory)
425             return 0;
426         return m_executableMemory->sizeInBytes();
427     }
428
429     bool tryToDisassemble(PrintStream& out, const char* prefix = "") const
430     {
431         return tryToDisassemble(retaggedCode<DisassemblyPtrTag>(), size(), prefix, out);
432     }
433     
434     bool tryToDisassemble(const char* prefix = "") const
435     {
436         return tryToDisassemble(retaggedCode<DisassemblyPtrTag>(), size(), prefix);
437     }
438     
439     CString disassembly() const
440     {
441         return MacroAssemblerCodeRefBase::disassembly(retaggedCode<DisassemblyPtrTag>(), size());
442     }
443     
444     explicit operator bool() const { return !!m_codePtr; }
445     
446     void dump(PrintStream& out) const
447     {
448         m_codePtr.dumpWithName("CodeRef", out);
449     }
450
451 private:
452     template<PtrTag otherTag>
453     MacroAssemblerCodeRef(const MacroAssemblerCodeRef<otherTag>& otherCodeRef)
454     {
455         *this = otherCodeRef;
456     }
457
458     MacroAssemblerCodePtr<tag> m_codePtr;
459     RefPtr<ExecutableMemoryHandle> m_executableMemory;
460
461     template<PtrTag> friend class MacroAssemblerCodeRef;
462 };
463
464 template<PtrTag tag>
465 inline FunctionPtr<tag>::FunctionPtr(MacroAssemblerCodePtr<tag> ptr)
466     : m_value(ptr.executableAddress())
467 {
468 }
469
470 } // namespace JSC
471
472 namespace WTF {
473
474 template<typename T> struct DefaultHash;
475 template<JSC::PtrTag tag> struct DefaultHash<JSC::MacroAssemblerCodePtr<tag>> {
476     typedef JSC::MacroAssemblerCodePtrHash<tag> Hash;
477 };
478
479 template<typename T> struct HashTraits;
480 template<JSC::PtrTag tag> struct HashTraits<JSC::MacroAssemblerCodePtr<tag>> : public CustomHashTraits<JSC::MacroAssemblerCodePtr<tag>> { };
481
482 } // namespace WTF