[YARR] Extend size of fixed characters bulk matching in 64bit platform
[WebKit-https.git] / Source / JavaScriptCore / assembler / LinkBuffer.h
1 /*
2  * Copyright (C) 2009-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 #if ENABLE(ASSEMBLER)
29
30 #define DUMP_LINK_STATISTICS 0
31 #define DUMP_CODE 0
32
33 #define GLOBAL_THUNK_ID reinterpret_cast<void*>(static_cast<intptr_t>(-1))
34 #define REGEXP_CODE_ID reinterpret_cast<void*>(static_cast<intptr_t>(-2))
35 #define CSS_CODE_ID reinterpret_cast<void*>(static_cast<intptr_t>(-3))
36
37 #include "JITCompilationEffort.h"
38 #include "MacroAssembler.h"
39 #include "MacroAssemblerCodeRef.h"
40 #include <wtf/DataLog.h>
41 #include <wtf/FastMalloc.h>
42 #include <wtf/Noncopyable.h>
43
44 namespace JSC {
45
46 class CodeBlock;
47
48 // LinkBuffer:
49 //
50 // This class assists in linking code generated by the macro assembler, once code generation
51 // has been completed, and the code has been copied to is final location in memory.  At this
52 // time pointers to labels within the code may be resolved, and relative offsets to external
53 // addresses may be fixed.
54 //
55 // Specifically:
56 //   * Jump objects may be linked to external targets,
57 //   * The address of Jump objects may taken, such that it can later be relinked.
58 //   * The return address of a Call may be acquired.
59 //   * The address of a Label pointing into the code may be resolved.
60 //   * The value referenced by a DataLabel may be set.
61 //
62 class LinkBuffer {
63     WTF_MAKE_NONCOPYABLE(LinkBuffer); WTF_MAKE_FAST_ALLOCATED;
64     
65     template<PtrTag tag> using CodePtr = MacroAssemblerCodePtr<tag>;
66     template<PtrTag tag> using CodeRef = MacroAssemblerCodeRef<tag>;
67     typedef MacroAssembler::Label Label;
68     typedef MacroAssembler::Jump Jump;
69     typedef MacroAssembler::PatchableJump PatchableJump;
70     typedef MacroAssembler::JumpList JumpList;
71     typedef MacroAssembler::Call Call;
72     typedef MacroAssembler::DataLabelCompact DataLabelCompact;
73     typedef MacroAssembler::DataLabel32 DataLabel32;
74     typedef MacroAssembler::DataLabelPtr DataLabelPtr;
75     typedef MacroAssembler::ConvertibleLoadLabel ConvertibleLoadLabel;
76 #if ENABLE(BRANCH_COMPACTION)
77     typedef MacroAssembler::LinkRecord LinkRecord;
78     typedef MacroAssembler::JumpLinkType JumpLinkType;
79 #endif
80
81 public:
82     LinkBuffer(MacroAssembler& macroAssembler, void* ownerUID, JITCompilationEffort effort = JITCompilationMustSucceed)
83         : m_size(0)
84         , m_didAllocate(false)
85 #ifndef NDEBUG
86         , m_completed(false)
87 #endif
88     {
89         linkCode(macroAssembler, ownerUID, effort);
90     }
91
92     template<PtrTag tag>
93     LinkBuffer(MacroAssembler& macroAssembler, MacroAssemblerCodePtr<tag> code, size_t size, JITCompilationEffort effort = JITCompilationMustSucceed, bool shouldPerformBranchCompaction = true)
94         : m_size(size)
95         , m_didAllocate(false)
96         , m_code(code.template retagged<LinkBufferPtrTag>())
97 #ifndef NDEBUG
98         , m_completed(false)
99 #endif
100     {
101 #if ENABLE(BRANCH_COMPACTION)
102         m_shouldPerformBranchCompaction = shouldPerformBranchCompaction;
103 #else
104         UNUSED_PARAM(shouldPerformBranchCompaction);
105 #endif
106         linkCode(macroAssembler, 0, effort);
107     }
108
109     ~LinkBuffer()
110     {
111     }
112     
113     bool didFailToAllocate() const
114     {
115         return !m_didAllocate;
116     }
117
118     bool isValid() const
119     {
120         return !didFailToAllocate();
121     }
122     
123     // These methods are used to link or set values at code generation time.
124
125     template<PtrTag tag, typename Func, typename = std::enable_if_t<std::is_function<typename std::remove_pointer<Func>::type>::value>>
126     void link(Call call, Func funcName)
127     {
128         FunctionPtr<tag> function(funcName);
129         link(call, function);
130     }
131
132     template<PtrTag tag>
133     void link(Call call, FunctionPtr<tag> function)
134     {
135         ASSERT(call.isFlagSet(Call::Linkable));
136         call.m_label = applyOffset(call.m_label);
137         MacroAssembler::linkCall(code(), call, function);
138     }
139     
140     template<PtrTag tag>
141     void link(Call call, CodeLocationLabel<tag> label)
142     {
143         link(call, FunctionPtr<tag>(label));
144     }
145     
146     template<PtrTag tag>
147     void link(Jump jump, CodeLocationLabel<tag> label)
148     {
149         jump.m_label = applyOffset(jump.m_label);
150         MacroAssembler::linkJump(code(), jump, label);
151     }
152
153     template<PtrTag tag>
154     void link(const JumpList& list, CodeLocationLabel<tag> label)
155     {
156         for (const Jump& jump : list.jumps())
157             link(jump, label);
158     }
159
160     void patch(DataLabelPtr label, void* value)
161     {
162         AssemblerLabel target = applyOffset(label.m_label);
163         MacroAssembler::linkPointer(code(), target, value);
164     }
165
166     template<PtrTag tag>
167     void patch(DataLabelPtr label, CodeLocationLabel<tag> value)
168     {
169         AssemblerLabel target = applyOffset(label.m_label);
170         MacroAssembler::linkPointer(code(), target, value);
171     }
172
173     // These methods are used to obtain handles to allow the code to be relinked / repatched later.
174     
175     template<PtrTag tag>
176     CodeLocationLabel<tag> entrypoint()
177     {
178         return CodeLocationLabel<tag>(tagCodePtr<tag>(code()));
179     }
180
181     template<PtrTag tag>
182     CodeLocationCall<tag> locationOf(Call call)
183     {
184         ASSERT(call.isFlagSet(Call::Linkable));
185         ASSERT(!call.isFlagSet(Call::Near));
186         return CodeLocationCall<tag>(MacroAssembler::getLinkerAddress<tag>(code(), applyOffset(call.m_label)));
187     }
188
189     template<PtrTag tag>
190     CodeLocationNearCall<tag> locationOfNearCall(Call call)
191     {
192         ASSERT(call.isFlagSet(Call::Linkable));
193         ASSERT(call.isFlagSet(Call::Near));
194         return CodeLocationNearCall<tag>(MacroAssembler::getLinkerAddress<tag>(code(), applyOffset(call.m_label)),
195             call.isFlagSet(Call::Tail) ? NearCallMode::Tail : NearCallMode::Regular);
196     }
197
198     template<PtrTag tag>
199     CodeLocationLabel<tag> locationOf(PatchableJump jump)
200     {
201         return CodeLocationLabel<tag>(MacroAssembler::getLinkerAddress<tag>(code(), applyOffset(jump.m_jump.m_label)));
202     }
203
204     template<PtrTag tag>
205     CodeLocationLabel<tag> locationOf(Label label)
206     {
207         return CodeLocationLabel<tag>(MacroAssembler::getLinkerAddress<tag>(code(), applyOffset(label.m_label)));
208     }
209
210     template<PtrTag tag>
211     CodeLocationDataLabelPtr<tag> locationOf(DataLabelPtr label)
212     {
213         return CodeLocationDataLabelPtr<tag>(MacroAssembler::getLinkerAddress<tag>(code(), applyOffset(label.m_label)));
214     }
215
216     template<PtrTag tag>
217     CodeLocationDataLabel32<tag> locationOf(DataLabel32 label)
218     {
219         return CodeLocationDataLabel32<tag>(MacroAssembler::getLinkerAddress<tag>(code(), applyOffset(label.m_label)));
220     }
221     
222     template<PtrTag tag>
223     CodeLocationDataLabelCompact<tag> locationOf(DataLabelCompact label)
224     {
225         return CodeLocationDataLabelCompact<tag>(MacroAssembler::getLinkerAddress<tag>(code(), applyOffset(label.m_label)));
226     }
227
228     template<PtrTag tag>
229     CodeLocationConvertibleLoad<tag> locationOf(ConvertibleLoadLabel label)
230     {
231         return CodeLocationConvertibleLoad<tag>(MacroAssembler::getLinkerAddress<tag>(code(), applyOffset(label.m_label)));
232     }
233
234     // This method obtains the return address of the call, given as an offset from
235     // the start of the code.
236     unsigned returnAddressOffset(Call call)
237     {
238         call.m_label = applyOffset(call.m_label);
239         return MacroAssembler::getLinkerCallReturnOffset(call);
240     }
241
242     uint32_t offsetOf(Label label)
243     {
244         return applyOffset(label.m_label).m_offset;
245     }
246
247     unsigned offsetOf(PatchableJump jump)
248     {
249         return applyOffset(jump.m_jump.m_label).m_offset;
250     }
251
252     // Upon completion of all patching 'FINALIZE_CODE()' should be called once to
253     // complete generation of the code. Alternatively, call
254     // finalizeCodeWithoutDisassembly() directly if you have your own way of
255     // displaying disassembly.
256
257     template<PtrTag tag>
258     CodeRef<tag> finalizeCodeWithoutDisassembly()
259     {
260         return finalizeCodeWithoutDisassemblyImpl().template retagged<tag>();
261     }
262
263     template<PtrTag tag, typename... Args>
264     CodeRef<tag> finalizeCodeWithDisassembly(const char* format, Args... args)
265     {
266 #if COMPILER(GCC_OR_CLANG)
267 #pragma GCC diagnostic push
268 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
269 #pragma GCC diagnostic ignored "-Wformat-security"
270 #endif
271         return finalizeCodeWithDisassemblyImpl(format, args...).template retagged<tag>();
272 #if COMPILER(GCC_OR_CLANG)
273 #pragma GCC diagnostic pop
274 #endif
275     }
276
277     template<PtrTag tag>
278     CodePtr<tag> trampolineAt(Label label)
279     {
280         return CodePtr<tag>(MacroAssembler::AssemblerType_T::getRelocatedAddress(code(), applyOffset(label.m_label)));
281     }
282
283     void* debugAddress()
284     {
285         return m_code.dataLocation();
286     }
287
288     size_t size() const { return m_size; }
289     
290     bool wasAlreadyDisassembled() const { return m_alreadyDisassembled; }
291     void didAlreadyDisassemble() { m_alreadyDisassembled = true; }
292
293 private:
294     JS_EXPORT_PRIVATE CodeRef<LinkBufferPtrTag> finalizeCodeWithoutDisassemblyImpl();
295     JS_EXPORT_PRIVATE CodeRef<LinkBufferPtrTag> finalizeCodeWithDisassemblyImpl(const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3);
296
297 #if ENABLE(BRANCH_COMPACTION)
298     int executableOffsetFor(int location)
299     {
300         // Returning 0 in this case works because at location <
301         // sizeof(int32_t), no compaction could have happened before this
302         // point as the assembler could not have placed a branch instruction
303         // within this space that required compaction.
304         if (location < static_cast<int>(sizeof(int32_t)))
305             return 0;
306         return bitwise_cast<int32_t*>(m_assemblerStorage.buffer())[location / sizeof(int32_t) - 1];
307     }
308 #endif
309     
310     template <typename T> T applyOffset(T src)
311     {
312 #if ENABLE(BRANCH_COMPACTION)
313         src.m_offset -= executableOffsetFor(src.m_offset);
314 #endif
315         return src;
316     }
317
318     // Keep this private! - the underlying code should only be obtained externally via finalizeCode().
319     void* code()
320     {
321         return m_code.dataLocation();
322     }
323     
324     void allocate(MacroAssembler&, void* ownerUID, JITCompilationEffort);
325
326     JS_EXPORT_PRIVATE void linkCode(MacroAssembler&, void* ownerUID, JITCompilationEffort);
327 #if ENABLE(BRANCH_COMPACTION)
328     template <typename InstructionType>
329     void copyCompactAndLinkCode(MacroAssembler&, void* ownerUID, JITCompilationEffort);
330 #endif
331
332     void performFinalization();
333
334 #if DUMP_LINK_STATISTICS
335     static void dumpLinkStatistics(void* code, size_t initialSize, size_t finalSize);
336 #endif
337     
338 #if DUMP_CODE
339     static void dumpCode(void* code, size_t);
340 #endif
341     
342     RefPtr<ExecutableMemoryHandle> m_executableMemory;
343     size_t m_size;
344 #if ENABLE(BRANCH_COMPACTION)
345     AssemblerData m_assemblerStorage;
346     bool m_shouldPerformBranchCompaction { true };
347 #endif
348     bool m_didAllocate;
349     MacroAssemblerCodePtr<LinkBufferPtrTag> m_code;
350 #ifndef NDEBUG
351     bool m_completed;
352 #endif
353     bool m_alreadyDisassembled { false };
354     Vector<RefPtr<SharedTask<void(LinkBuffer&)>>> m_linkTasks;
355 };
356
357 #define FINALIZE_CODE_IF(condition, linkBufferReference, resultPtrTag, ...)  \
358     (UNLIKELY((condition))                                              \
359         ? (linkBufferReference).finalizeCodeWithDisassembly<resultPtrTag>(__VA_ARGS__) \
360         : (linkBufferReference).finalizeCodeWithoutDisassembly<resultPtrTag>())
361
362 bool shouldDumpDisassemblyFor(CodeBlock*);
363
364 #define FINALIZE_CODE_FOR(codeBlock, linkBufferReference, resultPtrTag, ...)  \
365     FINALIZE_CODE_IF((shouldDumpDisassemblyFor(codeBlock) || Options::asyncDisassembly()), linkBufferReference, resultPtrTag, __VA_ARGS__)
366
367 // Use this to finalize code, like so:
368 //
369 // CodeRef code = FINALIZE_CODE(linkBuffer, tag, "my super thingy number %d", number);
370 //
371 // Which, in disassembly mode, will print:
372 //
373 // Generated JIT code for my super thingy number 42:
374 //     Code at [0x123456, 0x234567]:
375 //         0x123456: mov $0, 0
376 //         0x12345a: ret
377 //
378 // ... and so on.
379 //
380 // Note that the format string and print arguments are only evaluated when dumpDisassembly
381 // is true, so you can hide expensive disassembly-only computations inside there.
382
383 #define FINALIZE_CODE(linkBufferReference, resultPtrTag, ...)  \
384     FINALIZE_CODE_IF((JSC::Options::asyncDisassembly() || JSC::Options::dumpDisassembly()), linkBufferReference, resultPtrTag, __VA_ARGS__)
385
386 #define FINALIZE_DFG_CODE(linkBufferReference, resultPtrTag, ...)  \
387     FINALIZE_CODE_IF((JSC::Options::asyncDisassembly() || JSC::Options::dumpDisassembly() || Options::dumpDFGDisassembly()), linkBufferReference, resultPtrTag, __VA_ARGS__)
388
389 #define FINALIZE_REGEXP_CODE(linkBufferReference, resultPtrTag, dataLogFArgumentsForHeading)  \
390     FINALIZE_CODE_IF(JSC::Options::asyncDisassembly() || JSC::Options::dumpDisassembly() || Options::dumpRegExpDisassembly(), linkBufferReference, resultPtrTag, dataLogFArgumentsForHeading)
391
392 } // namespace JSC
393
394 #endif // ENABLE(ASSEMBLER)