PACCage should first cage leaving PAC bits intact then authenticate
[WebKit-https.git] / Source / JavaScriptCore / assembler / testmasm.cpp
1 /*
2  * Copyright (C) 2017-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 #include "config.h"
27
28 #include "CCallHelpers.h"
29 #include "CPU.h"
30 #include "FPRInfo.h"
31 #include "GPRInfo.h"
32 #include "InitializeThreading.h"
33 #include "LinkBuffer.h"
34 #include "ProbeContext.h"
35 #include "StackAlignment.h"
36 #include <limits>
37 #include <wtf/Compiler.h>
38 #include <wtf/DataLog.h>
39 #include <wtf/Function.h>
40 #include <wtf/Lock.h>
41 #include <wtf/NumberOfCores.h>
42 #include <wtf/PtrTag.h>
43 #include <wtf/Threading.h>
44 #include <wtf/text/StringCommon.h>
45
46 // We don't have a NO_RETURN_DUE_TO_EXIT, nor should we. That's ridiculous.
47 static bool hiddenTruthBecauseNoReturnIsStupid() { return true; }
48
49 static void usage()
50 {
51     dataLog("Usage: testmasm [<filter>]\n");
52     if (hiddenTruthBecauseNoReturnIsStupid())
53         exit(1);
54 }
55
56 #if ENABLE(JIT)
57
58 #if ENABLE(MASM_PROBE)
59 namespace WTF {
60
61 static void printInternal(PrintStream& out, void* value)
62 {
63     out.printf("%p", value);
64 }
65
66 } // namespace WTF
67 #endif // ENABLE(MASM_PROBE)
68
69 namespace JSC {
70 namespace Probe {
71
72 JS_EXPORT_PRIVATE void* probeStateForContext(Probe::Context&);
73
74 } // namespace Probe
75 } // namespace JSC
76
77 using namespace JSC;
78
79 namespace {
80
81 #if ENABLE(MASM_PROBE)
82 using CPUState = Probe::CPUState;
83 #endif
84
85 Lock crashLock;
86
87 typedef WTF::Function<void(CCallHelpers&)> Generator;
88
89 template<typename T> T nextID(T id) { return static_cast<T>(id + 1); }
90
91 #define TESTWORD64 0x0c0defefebeef000
92 #define TESTWORD32 0x0beef000
93
94 #define testWord32(x) (TESTWORD32 + static_cast<uint32_t>(x))
95 #define testWord64(x) (TESTWORD64 + static_cast<uint64_t>(x))
96
97 #if USE(JSVALUE64)
98 #define testWord(x) testWord64(x)
99 #else
100 #define testWord(x) testWord32(x)
101 #endif
102
103 // Nothing fancy for now; we just use the existing WTF assertion machinery.
104 #define CHECK_EQ(_actual, _expected) do {                               \
105         if ((_actual) == (_expected))                                   \
106             break;                                                      \
107         crashLock.lock();                                               \
108         dataLog("FAILED while testing " #_actual ": expected: ", _expected, ", actual: ", _actual, "\n"); \
109         WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, "CHECK_EQ("#_actual ", " #_expected ")"); \
110         CRASH();                                                        \
111     } while (false)
112
113 #define CHECK_NOT_EQ(_actual, _expected) do {                               \
114         if ((_actual) != (_expected))                                   \
115             break;                                                      \
116         crashLock.lock();                                               \
117         dataLog("FAILED while testing " #_actual ": expected not: ", _expected, ", actual: ", _actual, "\n"); \
118         WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, "CHECK_NOT_EQ("#_actual ", " #_expected ")"); \
119         CRASH();                                                        \
120     } while (false)
121
122 #if ENABLE(MASM_PROBE)
123 bool isPC(MacroAssembler::RegisterID id)
124 {
125 #if CPU(ARM_THUMB2)
126     return id == ARMRegisters::pc;
127 #else
128     UNUSED_PARAM(id);
129     return false;
130 #endif
131 }
132
133 bool isSP(MacroAssembler::RegisterID id)
134 {
135     return id == MacroAssembler::stackPointerRegister;
136 }
137
138 bool isFP(MacroAssembler::RegisterID id)
139 {
140     return id == MacroAssembler::framePointerRegister;
141 }
142
143 bool isSpecialGPR(MacroAssembler::RegisterID id)
144 {
145     if (isPC(id) || isSP(id) || isFP(id))
146         return true;
147 #if CPU(ARM64)
148     if (id == ARM64Registers::x18)
149         return true;
150 #elif CPU(MIPS)
151     if (id == MIPSRegisters::zero || id == MIPSRegisters::k0 || id == MIPSRegisters::k1)
152         return true;
153 #endif
154     return false;
155 }
156 #endif // ENABLE(MASM_PROBE)
157
158 MacroAssemblerCodeRef<JSEntryPtrTag> compile(Generator&& generate)
159 {
160     CCallHelpers jit;
161     generate(jit);
162     LinkBuffer linkBuffer(jit, nullptr);
163     return FINALIZE_CODE(linkBuffer, JSEntryPtrTag, "testmasm compilation");
164 }
165
166 template<typename T, typename... Arguments>
167 T invoke(const MacroAssemblerCodeRef<JSEntryPtrTag>& code, Arguments... arguments)
168 {
169     void* executableAddress = untagCFunctionPtr<JSEntryPtrTag>(code.code().executableAddress());
170     T (*function)(Arguments...) = bitwise_cast<T(*)(Arguments...)>(executableAddress);
171     return function(arguments...);
172 }
173
174 template<typename T, typename... Arguments>
175 T compileAndRun(Generator&& generator, Arguments... arguments)
176 {
177     return invoke<T>(compile(WTFMove(generator)), arguments...);
178 }
179
180 void testSimple()
181 {
182     CHECK_EQ(compileAndRun<int>([] (CCallHelpers& jit) {
183         jit.emitFunctionPrologue();
184         jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR);
185         jit.emitFunctionEpilogue();
186         jit.ret();
187     }), 42);
188 }
189
190 void testGetEffectiveAddress(size_t pointer, ptrdiff_t length, int32_t offset, CCallHelpers::Scale scale)
191 {
192     CHECK_EQ(compileAndRun<size_t>([=] (CCallHelpers& jit) {
193         jit.emitFunctionPrologue();
194         jit.move(CCallHelpers::TrustedImmPtr(bitwise_cast<void*>(pointer)), GPRInfo::regT0);
195         jit.move(CCallHelpers::TrustedImmPtr(bitwise_cast<void*>(length)), GPRInfo::regT1);
196         jit.getEffectiveAddress(CCallHelpers::BaseIndex(GPRInfo::regT0, GPRInfo::regT1, scale, offset), GPRInfo::returnValueGPR);
197         jit.emitFunctionEpilogue();
198         jit.ret();
199     }), pointer + offset + (static_cast<size_t>(1) << static_cast<int>(scale)) * length);
200 }
201
202 // branchTruncateDoubleToInt32(), when encountering Infinity, -Infinity or a
203 // Nan, should either yield 0 in dest or fail.
204 void testBranchTruncateDoubleToInt32(double val, int32_t expected)
205 {
206     const uint64_t valAsUInt = *reinterpret_cast<uint64_t*>(&val);
207 #if CPU(BIG_ENDIAN)
208     const bool isBigEndian = true;
209 #else
210     const bool isBigEndian = false;
211 #endif
212     CHECK_EQ(compileAndRun<int>([&] (CCallHelpers& jit) {
213         jit.emitFunctionPrologue();
214         jit.subPtr(CCallHelpers::TrustedImm32(stackAlignmentBytes()), MacroAssembler::stackPointerRegister);
215         if (isBigEndian) {
216             jit.store32(CCallHelpers::TrustedImm32(valAsUInt >> 32),
217                 MacroAssembler::stackPointerRegister);
218             jit.store32(CCallHelpers::TrustedImm32(valAsUInt & 0xffffffff),
219                 MacroAssembler::Address(MacroAssembler::stackPointerRegister, 4));
220         } else {
221             jit.store32(CCallHelpers::TrustedImm32(valAsUInt & 0xffffffff),
222                 MacroAssembler::stackPointerRegister);
223             jit.store32(CCallHelpers::TrustedImm32(valAsUInt >> 32),
224                 MacroAssembler::Address(MacroAssembler::stackPointerRegister, 4));
225         }
226         jit.loadDouble(MacroAssembler::stackPointerRegister, FPRInfo::fpRegT0);
227
228         MacroAssembler::Jump done;
229         done = jit.branchTruncateDoubleToInt32(FPRInfo::fpRegT0, GPRInfo::returnValueGPR, MacroAssembler::BranchIfTruncateSuccessful);
230
231         jit.move(CCallHelpers::TrustedImm32(0), GPRInfo::returnValueGPR);
232
233         done.link(&jit);
234         jit.addPtr(CCallHelpers::TrustedImm32(stackAlignmentBytes()), MacroAssembler::stackPointerRegister);
235         jit.emitFunctionEpilogue();
236         jit.ret();
237     }), expected);
238 }
239
240
241 static Vector<double> doubleOperands()
242 {
243     return Vector<double> {
244         0,
245         -0,
246         1,
247         -1,
248         42,
249         -42,
250         std::numeric_limits<double>::max(),
251         std::numeric_limits<double>::min(),
252         std::numeric_limits<double>::lowest(),
253         std::numeric_limits<double>::quiet_NaN(),
254         std::numeric_limits<double>::infinity(),
255         -std::numeric_limits<double>::infinity(),
256     };
257 }
258
259
260 #if CPU(X86) || CPU(X86_64) || CPU(ARM64)
261 static Vector<float> floatOperands()
262 {
263     return Vector<float> {
264         0,
265         -0,
266         1,
267         -1,
268         42,
269         -42,
270         std::numeric_limits<float>::max(),
271         std::numeric_limits<float>::min(),
272         std::numeric_limits<float>::lowest(),
273         std::numeric_limits<float>::quiet_NaN(),
274         std::numeric_limits<float>::infinity(),
275         -std::numeric_limits<float>::infinity(),
276     };
277 }
278 #endif
279
280 static Vector<int32_t> int32Operands()
281 {
282     return Vector<int32_t> {
283         0,
284         1,
285         -1,
286         2,
287         -2,
288         42,
289         -42,
290         64,
291         std::numeric_limits<int32_t>::max(),
292         std::numeric_limits<int32_t>::min(),
293     };
294 }
295
296 void testCompareDouble(MacroAssembler::DoubleCondition condition)
297 {
298     double arg1 = 0;
299     double arg2 = 0;
300
301     auto compareDouble = compile([&, condition] (CCallHelpers& jit) {
302         jit.emitFunctionPrologue();
303
304         jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
305         jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg2), FPRInfo::fpRegT1);
306         jit.move(CCallHelpers::TrustedImm32(-1), GPRInfo::returnValueGPR);
307         jit.compareDouble(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1, GPRInfo::returnValueGPR);
308
309         jit.emitFunctionEpilogue();
310         jit.ret();
311     });
312
313     auto compareDoubleGeneric = compile([&, condition] (CCallHelpers& jit) {
314         jit.emitFunctionPrologue();
315
316         jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
317         jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg2), FPRInfo::fpRegT1);
318         jit.move(CCallHelpers::TrustedImm32(1), GPRInfo::returnValueGPR);
319         auto jump = jit.branchDouble(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1);
320         jit.move(CCallHelpers::TrustedImm32(0), GPRInfo::returnValueGPR);
321         jump.link(&jit);
322
323         jit.emitFunctionEpilogue();
324         jit.ret();
325     });
326
327     auto operands = doubleOperands();
328     for (auto a : operands) {
329         for (auto b : operands) {
330             arg1 = a;
331             arg2 = b;
332             CHECK_EQ(invoke<int>(compareDouble), invoke<int>(compareDoubleGeneric));
333         }
334     }
335 }
336
337 void testMul32WithImmediates()
338 {
339     for (auto immediate : int32Operands()) {
340         auto mul = compile([=] (CCallHelpers& jit) {
341             jit.emitFunctionPrologue();
342
343             jit.mul32(CCallHelpers::TrustedImm32(immediate), GPRInfo::argumentGPR0, GPRInfo::returnValueGPR);
344
345             jit.emitFunctionEpilogue();
346             jit.ret();
347         });
348
349         for (auto value : int32Operands())
350             CHECK_EQ(invoke<int>(mul, value), immediate * value);
351     }
352 }
353
354 #if CPU(X86) || CPU(X86_64) || CPU(ARM64)
355 void testCompareFloat(MacroAssembler::DoubleCondition condition)
356 {
357     float arg1 = 0;
358     float arg2 = 0;
359
360     auto compareFloat = compile([&, condition] (CCallHelpers& jit) {
361         jit.emitFunctionPrologue();
362
363         jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
364         jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg2), FPRInfo::fpRegT1);
365         jit.move(CCallHelpers::TrustedImm32(-1), GPRInfo::returnValueGPR);
366         jit.compareFloat(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1, GPRInfo::returnValueGPR);
367
368         jit.emitFunctionEpilogue();
369         jit.ret();
370     });
371
372     auto compareFloatGeneric = compile([&, condition] (CCallHelpers& jit) {
373         jit.emitFunctionPrologue();
374
375         jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
376         jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg2), FPRInfo::fpRegT1);
377         jit.move(CCallHelpers::TrustedImm32(1), GPRInfo::returnValueGPR);
378         auto jump = jit.branchFloat(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1);
379         jit.move(CCallHelpers::TrustedImm32(0), GPRInfo::returnValueGPR);
380         jump.link(&jit);
381
382         jit.emitFunctionEpilogue();
383         jit.ret();
384     });
385
386     auto operands = floatOperands();
387     for (auto a : operands) {
388         for (auto b : operands) {
389             arg1 = a;
390             arg2 = b;
391             CHECK_EQ(invoke<int>(compareFloat), invoke<int>(compareFloatGeneric));
392         }
393     }
394 }
395 #endif
396
397 #if ENABLE(MASM_PROBE)
398 void testProbeReadsArgumentRegisters()
399 {
400     bool probeWasCalled = false;
401     compileAndRun<void>([&] (CCallHelpers& jit) {
402         jit.emitFunctionPrologue();
403
404         jit.pushPair(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1);
405         jit.pushPair(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3);
406
407         jit.move(CCallHelpers::TrustedImm32(testWord32(0)), GPRInfo::argumentGPR0);
408         jit.convertInt32ToDouble(GPRInfo::argumentGPR0, FPRInfo::fpRegT0);
409         jit.move(CCallHelpers::TrustedImm32(testWord32(1)), GPRInfo::argumentGPR0);
410         jit.convertInt32ToDouble(GPRInfo::argumentGPR0, FPRInfo::fpRegT1);
411 #if USE(JSVALUE64)
412         jit.move(CCallHelpers::TrustedImm64(testWord(0)), GPRInfo::argumentGPR0);
413         jit.move(CCallHelpers::TrustedImm64(testWord(1)), GPRInfo::argumentGPR1);
414         jit.move(CCallHelpers::TrustedImm64(testWord(2)), GPRInfo::argumentGPR2);
415         jit.move(CCallHelpers::TrustedImm64(testWord(3)), GPRInfo::argumentGPR3);
416 #else
417         jit.move(CCallHelpers::TrustedImm32(testWord(0)), GPRInfo::argumentGPR0);
418         jit.move(CCallHelpers::TrustedImm32(testWord(1)), GPRInfo::argumentGPR1);
419         jit.move(CCallHelpers::TrustedImm32(testWord(2)), GPRInfo::argumentGPR2);
420         jit.move(CCallHelpers::TrustedImm32(testWord(3)), GPRInfo::argumentGPR3);
421 #endif
422
423         jit.probe([&] (Probe::Context& context) {
424             auto& cpu = context.cpu;
425             probeWasCalled = true;
426             CHECK_EQ(cpu.gpr(GPRInfo::argumentGPR0), testWord(0));
427             CHECK_EQ(cpu.gpr(GPRInfo::argumentGPR1), testWord(1));
428             CHECK_EQ(cpu.gpr(GPRInfo::argumentGPR2), testWord(2));
429             CHECK_EQ(cpu.gpr(GPRInfo::argumentGPR3), testWord(3));
430
431             CHECK_EQ(cpu.fpr(FPRInfo::fpRegT0), testWord32(0));
432             CHECK_EQ(cpu.fpr(FPRInfo::fpRegT1), testWord32(1));
433         });
434
435         jit.popPair(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3);
436         jit.popPair(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1);
437
438         jit.emitFunctionEpilogue();
439         jit.ret();
440     });
441     CHECK_EQ(probeWasCalled, true);
442 }
443
444 void testProbeWritesArgumentRegisters()
445 {
446     // This test relies on testProbeReadsArgumentRegisters() having already validated
447     // that we can read from argument registers. We'll use that ability to validate
448     // that our writes did take effect.
449     unsigned probeCallCount = 0;
450     compileAndRun<void>([&] (CCallHelpers& jit) {
451         jit.emitFunctionPrologue();
452
453         jit.pushPair(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1);
454         jit.pushPair(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3);
455
456         // Pre-initialize with non-expected values.
457 #if USE(JSVALUE64)
458         jit.move(CCallHelpers::TrustedImm64(0), GPRInfo::argumentGPR0);
459         jit.move(CCallHelpers::TrustedImm64(0), GPRInfo::argumentGPR1);
460         jit.move(CCallHelpers::TrustedImm64(0), GPRInfo::argumentGPR2);
461         jit.move(CCallHelpers::TrustedImm64(0), GPRInfo::argumentGPR3);
462 #else
463         jit.move(CCallHelpers::TrustedImm32(0), GPRInfo::argumentGPR0);
464         jit.move(CCallHelpers::TrustedImm32(0), GPRInfo::argumentGPR1);
465         jit.move(CCallHelpers::TrustedImm32(0), GPRInfo::argumentGPR2);
466         jit.move(CCallHelpers::TrustedImm32(0), GPRInfo::argumentGPR3);
467 #endif
468         jit.convertInt32ToDouble(GPRInfo::argumentGPR0, FPRInfo::fpRegT0);
469         jit.convertInt32ToDouble(GPRInfo::argumentGPR0, FPRInfo::fpRegT1);
470
471         // Write expected values.
472         jit.probe([&] (Probe::Context& context) {
473             auto& cpu = context.cpu;
474             probeCallCount++;
475             cpu.gpr(GPRInfo::argumentGPR0) = testWord(0);
476             cpu.gpr(GPRInfo::argumentGPR1) = testWord(1);
477             cpu.gpr(GPRInfo::argumentGPR2) = testWord(2);
478             cpu.gpr(GPRInfo::argumentGPR3) = testWord(3);
479             
480             cpu.fpr(FPRInfo::fpRegT0) = bitwise_cast<double>(testWord64(0));
481             cpu.fpr(FPRInfo::fpRegT1) = bitwise_cast<double>(testWord64(1));
482         });
483
484         // Validate that expected values were written.
485         jit.probe([&] (Probe::Context& context) {
486             auto& cpu = context.cpu;
487             probeCallCount++;
488             CHECK_EQ(cpu.gpr(GPRInfo::argumentGPR0), testWord(0));
489             CHECK_EQ(cpu.gpr(GPRInfo::argumentGPR1), testWord(1));
490             CHECK_EQ(cpu.gpr(GPRInfo::argumentGPR2), testWord(2));
491             CHECK_EQ(cpu.gpr(GPRInfo::argumentGPR3), testWord(3));
492
493             CHECK_EQ(cpu.fpr<uint64_t>(FPRInfo::fpRegT0), testWord64(0));
494             CHECK_EQ(cpu.fpr<uint64_t>(FPRInfo::fpRegT1), testWord64(1));
495         });
496
497         jit.popPair(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3);
498         jit.popPair(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1);
499
500         jit.emitFunctionEpilogue();
501         jit.ret();
502     });
503     CHECK_EQ(probeCallCount, 2);
504 }
505
506 static NEVER_INLINE NOT_TAIL_CALLED int testFunctionToTrashGPRs(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j)
507 {
508     if (j > 0)
509         return testFunctionToTrashGPRs(a + 1, b + a, c + b, d + 5, e - a, f * 1.5, g ^ a, h - b, i, j - 1);
510     return a + 1;
511 }
512 static NEVER_INLINE NOT_TAIL_CALLED double testFunctionToTrashFPRs(double a, double b, double c, double d, double e, double f, double g, double h, double i, double j)
513 {
514     if (j > 0)
515         return testFunctionToTrashFPRs(a + 1, b + a, c + b, d + 5, e - a, f * 1.5, pow(g, a), h - b, i, j - 1);
516     return a + 1;
517 }
518
519 void testProbePreservesGPRS()
520 {
521     // This test relies on testProbeReadsArgumentRegisters() and testProbeWritesArgumentRegisters()
522     // having already validated that we can read and write from registers. We'll use these abilities
523     // to validate that the probe preserves register values.
524     unsigned probeCallCount = 0;
525     CPUState originalState;
526
527     compileAndRun<void>([&] (CCallHelpers& jit) {
528         jit.emitFunctionPrologue();
529
530         // Write expected values into the registers (except for sp, fp, and pc).
531         jit.probe([&] (Probe::Context& context) {
532             auto& cpu = context.cpu;
533             probeCallCount++;
534             for (auto id = CCallHelpers::firstRegister(); id <= CCallHelpers::lastRegister(); id = nextID(id)) {
535                 originalState.gpr(id) = cpu.gpr(id);
536                 if (isSpecialGPR(id))
537                     continue;
538                 cpu.gpr(id) = testWord(static_cast<int>(id));
539             }
540             for (auto id = CCallHelpers::firstFPRegister(); id <= CCallHelpers::lastFPRegister(); id = nextID(id)) {
541                 originalState.fpr(id) = cpu.fpr(id);
542                 cpu.fpr(id) = bitwise_cast<double>(testWord64(id));
543             }
544         });
545
546         // Invoke the probe to call a lot of functions and trash register values.
547         jit.probe([&] (Probe::Context&) {
548             probeCallCount++;
549             CHECK_EQ(testFunctionToTrashGPRs(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), 10);
550             CHECK_EQ(testFunctionToTrashFPRs(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), 10);
551         });
552
553         // Validate that the registers have the expected values.
554         jit.probe([&] (Probe::Context& context) {
555             auto& cpu = context.cpu;
556             probeCallCount++;
557             for (auto id = CCallHelpers::firstRegister(); id <= CCallHelpers::lastRegister(); id = nextID(id)) {
558                 if (isSP(id) || isFP(id)) {
559                     CHECK_EQ(cpu.gpr(id), originalState.gpr(id));
560                     continue;
561                 }
562                 if (isSpecialGPR(id))
563                     continue;
564                 CHECK_EQ(cpu.gpr(id), testWord(id));
565             }
566             for (auto id = CCallHelpers::firstFPRegister(); id <= CCallHelpers::lastFPRegister(); id = nextID(id))
567 #if CPU(MIPS)
568                 if (!(id & 1))
569 #endif
570                 CHECK_EQ(cpu.fpr<uint64_t>(id), testWord64(id));
571         });
572
573         // Restore the original state.
574         jit.probe([&] (Probe::Context& context) {
575             auto& cpu = context.cpu;
576             probeCallCount++;
577             for (auto id = CCallHelpers::firstRegister(); id <= CCallHelpers::lastRegister(); id = nextID(id)) {
578                 if (isSpecialGPR(id))
579                     continue;
580                 cpu.gpr(id) = originalState.gpr(id);
581             }
582             for (auto id = CCallHelpers::firstFPRegister(); id <= CCallHelpers::lastFPRegister(); id = nextID(id))
583                 cpu.fpr(id) = originalState.fpr(id);
584         });
585
586         // Validate that the original state was restored.
587         jit.probe([&] (Probe::Context& context) {
588             auto& cpu = context.cpu;
589             probeCallCount++;
590             for (auto id = CCallHelpers::firstRegister(); id <= CCallHelpers::lastRegister(); id = nextID(id)) {
591                 if (isSpecialGPR(id))
592                     continue;
593                 CHECK_EQ(cpu.gpr(id), originalState.gpr(id));
594             }
595             for (auto id = CCallHelpers::firstFPRegister(); id <= CCallHelpers::lastFPRegister(); id = nextID(id))
596 #if CPU(MIPS)
597                 if (!(id & 1))
598 #endif
599                 CHECK_EQ(cpu.fpr<uint64_t>(id), originalState.fpr<uint64_t>(id));
600         });
601
602         jit.emitFunctionEpilogue();
603         jit.ret();
604     });
605     CHECK_EQ(probeCallCount, 5);
606 }
607
608 void testProbeModifiesStackPointer(WTF::Function<void*(Probe::Context&)> computeModifiedStackPointer)
609 {
610     unsigned probeCallCount = 0;
611     CPUState originalState;
612     void* originalSP { nullptr };
613     void* modifiedSP { nullptr };
614 #if !(CPU(MIPS))
615     uintptr_t modifiedFlags { 0 };
616 #endif
617     
618 #if CPU(X86) || CPU(X86_64)
619     auto flagsSPR = X86Registers::eflags;
620     uintptr_t flagsMask = 0xc5;
621 #elif CPU(ARM_THUMB2)
622     auto flagsSPR = ARMRegisters::apsr;
623     uintptr_t flagsMask = 0xf8000000;
624 #elif CPU(ARM64)
625     auto flagsSPR = ARM64Registers::nzcv;
626     uintptr_t flagsMask = 0xf0000000;
627 #endif
628
629     compileAndRun<void>([&] (CCallHelpers& jit) {
630         jit.emitFunctionPrologue();
631
632         // Preserve original stack pointer and modify the sp, and
633         // write expected values into other registers (except for fp, and pc).
634         jit.probe([&] (Probe::Context& context) {
635             auto& cpu = context.cpu;
636             probeCallCount++;
637             for (auto id = CCallHelpers::firstRegister(); id <= CCallHelpers::lastRegister(); id = nextID(id)) {
638                 originalState.gpr(id) = cpu.gpr(id);
639                 if (isSpecialGPR(id))
640                     continue;
641                 cpu.gpr(id) = testWord(static_cast<int>(id));
642             }
643             for (auto id = CCallHelpers::firstFPRegister(); id <= CCallHelpers::lastFPRegister(); id = nextID(id)) {
644                 originalState.fpr(id) = cpu.fpr(id);
645                 cpu.fpr(id) = bitwise_cast<double>(testWord64(id));
646             }
647
648 #if !(CPU(MIPS))
649             originalState.spr(flagsSPR) = cpu.spr(flagsSPR);
650             modifiedFlags = originalState.spr(flagsSPR) ^ flagsMask;
651             cpu.spr(flagsSPR) = modifiedFlags;
652 #endif
653
654             originalSP = cpu.sp();
655             modifiedSP = computeModifiedStackPointer(context);
656             cpu.sp() = modifiedSP;
657         });
658
659         // Validate that the registers have the expected values.
660         jit.probe([&] (Probe::Context& context) {
661             auto& cpu = context.cpu;
662             probeCallCount++;
663             for (auto id = CCallHelpers::firstRegister(); id <= CCallHelpers::lastRegister(); id = nextID(id)) {
664                 if (isFP(id)) {
665                     CHECK_EQ(cpu.gpr(id), originalState.gpr(id));
666                     continue;
667                 }
668                 if (isSpecialGPR(id))
669                     continue;
670                 CHECK_EQ(cpu.gpr(id), testWord(id));
671             }
672             for (auto id = CCallHelpers::firstFPRegister(); id <= CCallHelpers::lastFPRegister(); id = nextID(id))
673 #if CPU(MIPS)
674                 if (!(id & 1))
675 #endif
676                 CHECK_EQ(cpu.fpr<uint64_t>(id), testWord64(id));
677 #if !(CPU(MIPS))
678             CHECK_EQ(cpu.spr(flagsSPR) & flagsMask, modifiedFlags & flagsMask);
679 #endif
680             CHECK_EQ(cpu.sp(), modifiedSP);
681         });
682
683         // Restore the original state.
684         jit.probe([&] (Probe::Context& context) {
685             auto& cpu = context.cpu;
686             probeCallCount++;
687             for (auto id = CCallHelpers::firstRegister(); id <= CCallHelpers::lastRegister(); id = nextID(id)) {
688                 if (isSpecialGPR(id))
689                     continue;
690                 cpu.gpr(id) = originalState.gpr(id);
691             }
692             for (auto id = CCallHelpers::firstFPRegister(); id <= CCallHelpers::lastFPRegister(); id = nextID(id))
693                 cpu.fpr(id) = originalState.fpr(id);
694 #if !(CPU(MIPS))
695             cpu.spr(flagsSPR) = originalState.spr(flagsSPR);
696 #endif
697             cpu.sp() = originalSP;
698         });
699
700         // Validate that the original state was restored.
701         jit.probe([&] (Probe::Context& context) {
702             auto& cpu = context.cpu;
703             probeCallCount++;
704             for (auto id = CCallHelpers::firstRegister(); id <= CCallHelpers::lastRegister(); id = nextID(id)) {
705                 if (isSpecialGPR(id))
706                     continue;
707                 CHECK_EQ(cpu.gpr(id), originalState.gpr(id));
708             }
709             for (auto id = CCallHelpers::firstFPRegister(); id <= CCallHelpers::lastFPRegister(); id = nextID(id))
710 #if CPU(MIPS)
711                 if (!(id & 1))
712 #endif
713                 CHECK_EQ(cpu.fpr<uint64_t>(id), originalState.fpr<uint64_t>(id));
714 #if !(CPU(MIPS))
715             CHECK_EQ(cpu.spr(flagsSPR) & flagsMask, originalState.spr(flagsSPR) & flagsMask);
716 #endif
717             CHECK_EQ(cpu.sp(), originalSP);
718         });
719
720         jit.emitFunctionEpilogue();
721         jit.ret();
722     });
723     CHECK_EQ(probeCallCount, 4);
724 }
725
726 void testProbeModifiesStackPointerToInsideProbeStateOnStack()
727 {
728     size_t increment = sizeof(uintptr_t);
729 #if CPU(ARM64)
730     // The ARM64 probe uses ldp and stp which require 16 byte alignment.
731     increment = 2 * sizeof(uintptr_t);
732 #endif
733     for (size_t offset = 0; offset < sizeof(Probe::State); offset += increment) {
734         testProbeModifiesStackPointer([=] (Probe::Context& context) -> void* {
735             return reinterpret_cast<uint8_t*>(probeStateForContext(context)) + offset;
736
737         });
738     }
739 }
740
741 void testProbeModifiesStackPointerToNBytesBelowSP()
742 {
743     size_t increment = sizeof(uintptr_t);
744 #if CPU(ARM64)
745     // The ARM64 probe uses ldp and stp which require 16 byte alignment.
746     increment = 2 * sizeof(uintptr_t);
747 #endif
748     for (size_t offset = 0; offset < 1 * KB; offset += increment) {
749         testProbeModifiesStackPointer([=] (Probe::Context& context) -> void* {
750             return context.cpu.sp<uint8_t*>() - offset;
751         });
752     }
753 }
754
755 void testProbeModifiesProgramCounter()
756 {
757     // This test relies on testProbeReadsArgumentRegisters() and testProbeWritesArgumentRegisters()
758     // having already validated that we can read and write from registers. We'll use these abilities
759     // to validate that the probe preserves register values.
760     unsigned probeCallCount = 0;
761     bool continuationWasReached = false;
762
763     MacroAssemblerCodeRef<JSEntryPtrTag> continuation = compile([&] (CCallHelpers& jit) {
764         // Validate that we reached the continuation.
765         jit.probe([&] (Probe::Context&) {
766             probeCallCount++;
767             continuationWasReached = true;
768         });
769
770         jit.emitFunctionEpilogue();
771         jit.ret();
772     });
773
774     compileAndRun<void>([&] (CCallHelpers& jit) {
775         jit.emitFunctionPrologue();
776
777         // Write expected values into the registers.
778         jit.probe([&] (Probe::Context& context) {
779             probeCallCount++;
780             context.cpu.pc() = untagCodePtr(continuation.code().executableAddress(), JSEntryPtrTag);
781         });
782
783         jit.breakpoint(); // We should never get here.
784     });
785     CHECK_EQ(probeCallCount, 2);
786     CHECK_EQ(continuationWasReached, true);
787 }
788
789 void testProbeModifiesStackValues()
790 {
791     unsigned probeCallCount = 0;
792     CPUState originalState;
793     void* originalSP { nullptr };
794     void* newSP { nullptr };
795 #if !CPU(MIPS)
796     uintptr_t modifiedFlags { 0 };
797 #endif
798     size_t numberOfExtraEntriesToWrite { 10 }; // ARM64 requires that this be 2 word aligned.
799
800 #if CPU(X86) || CPU(X86_64)
801     MacroAssembler::SPRegisterID flagsSPR = X86Registers::eflags;
802     uintptr_t flagsMask = 0xc5;
803 #elif CPU(ARM_THUMB2)
804     MacroAssembler::SPRegisterID flagsSPR = ARMRegisters::apsr;
805     uintptr_t flagsMask = 0xf8000000;
806 #elif CPU(ARM64)
807     MacroAssembler::SPRegisterID flagsSPR = ARM64Registers::nzcv;
808     uintptr_t flagsMask = 0xf0000000;
809 #endif
810
811     compileAndRun<void>([&] (CCallHelpers& jit) {
812         jit.emitFunctionPrologue();
813
814         // Write expected values into the registers.
815         jit.probe([&] (Probe::Context& context) {
816             auto& cpu = context.cpu;
817             auto& stack = context.stack();
818             probeCallCount++;
819
820             // Preserve the original CPU state.
821             for (auto id = CCallHelpers::firstRegister(); id <= CCallHelpers::lastRegister(); id = nextID(id)) {
822                 originalState.gpr(id) = cpu.gpr(id);
823                 if (isSpecialGPR(id))
824                     continue;
825                 cpu.gpr(id) = testWord(static_cast<int>(id));
826             }
827             for (auto id = CCallHelpers::firstFPRegister(); id <= CCallHelpers::lastFPRegister(); id = nextID(id)) {
828                 originalState.fpr(id) = cpu.fpr(id);
829                 cpu.fpr(id) = bitwise_cast<double>(testWord64(id));
830             }
831 #if !(CPU(MIPS))
832             originalState.spr(flagsSPR) = cpu.spr(flagsSPR);
833             modifiedFlags = originalState.spr(flagsSPR) ^ flagsMask;
834             cpu.spr(flagsSPR) = modifiedFlags;
835 #endif
836
837             // Ensure that we'll be writing over the regions of the stack where the Probe::State is.
838             originalSP = cpu.sp();
839             newSP = reinterpret_cast<uintptr_t*>(probeStateForContext(context)) - numberOfExtraEntriesToWrite;
840             cpu.sp() = newSP;
841
842             // Fill the stack with values.
843             uintptr_t* p = reinterpret_cast<uintptr_t*>(newSP);
844             int count = 0;
845             stack.set<double>(p++, 1.234567);
846             if (is32Bit())
847                 p++; // On 32-bit targets, a double takes up 2 uintptr_t.
848             while (p < reinterpret_cast<uintptr_t*>(originalSP))
849                 stack.set<uintptr_t>(p++, testWord(count++));
850         });
851
852         // Validate that the registers and stack have the expected values.
853         jit.probe([&] (Probe::Context& context) {
854             auto& cpu = context.cpu;
855             auto& stack = context.stack();
856             probeCallCount++;
857
858             // Validate the register values.
859             for (auto id = CCallHelpers::firstRegister(); id <= CCallHelpers::lastRegister(); id = nextID(id)) {
860                 if (isFP(id)) {
861                     CHECK_EQ(cpu.gpr(id), originalState.gpr(id));
862                     continue;
863                 }
864                 if (isSpecialGPR(id))
865                     continue;
866                 CHECK_EQ(cpu.gpr(id), testWord(id));
867             }
868             for (auto id = CCallHelpers::firstFPRegister(); id <= CCallHelpers::lastFPRegister(); id = nextID(id))
869 #if CPU(MIPS)
870                 if (!(id & 1))
871 #endif
872                 CHECK_EQ(cpu.fpr<uint64_t>(id), testWord64(id));
873 #if !(CPU(MIPS))
874             CHECK_EQ(cpu.spr(flagsSPR) & flagsMask, modifiedFlags & flagsMask);
875 #endif
876             CHECK_EQ(cpu.sp(), newSP);
877
878             // Validate the stack values.
879             uintptr_t* p = reinterpret_cast<uintptr_t*>(newSP);
880             int count = 0;
881             CHECK_EQ(stack.get<double>(p++), 1.234567);
882             if (is32Bit())
883                 p++; // On 32-bit targets, a double takes up 2 uintptr_t.
884             while (p < reinterpret_cast<uintptr_t*>(originalSP))
885                 CHECK_EQ(stack.get<uintptr_t>(p++), testWord(count++));
886         });
887
888         // Restore the original state.
889         jit.probe([&] (Probe::Context& context) {
890             auto& cpu = context.cpu;
891             probeCallCount++;
892             for (auto id = CCallHelpers::firstRegister(); id <= CCallHelpers::lastRegister(); id = nextID(id)) {
893                 if (isSpecialGPR(id))
894                     continue;
895                 cpu.gpr(id) = originalState.gpr(id);
896             }
897             for (auto id = CCallHelpers::firstFPRegister(); id <= CCallHelpers::lastFPRegister(); id = nextID(id))
898                 cpu.fpr(id) = originalState.fpr(id);
899 #if !(CPU(MIPS))
900             cpu.spr(flagsSPR) = originalState.spr(flagsSPR);
901 #endif
902             cpu.sp() = originalSP;
903         });
904
905         jit.emitFunctionEpilogue();
906         jit.ret();
907     });
908
909     CHECK_EQ(probeCallCount, 3);
910 }
911 #endif // ENABLE(MASM_PROBE)
912
913 void testByteSwap()
914 {
915 #if CPU(X86_64) || CPU(ARM64)
916     auto byteSwap16 = compile([] (CCallHelpers& jit) {
917         jit.emitFunctionPrologue();
918         jit.move(GPRInfo::argumentGPR0, GPRInfo::returnValueGPR);
919         jit.byteSwap16(GPRInfo::returnValueGPR);
920         jit.emitFunctionEpilogue();
921         jit.ret();
922     });
923     CHECK_EQ(invoke<uint64_t>(byteSwap16, 0xaabbccddee001122), static_cast<uint64_t>(0x2211));
924     CHECK_EQ(invoke<uint64_t>(byteSwap16, 0xaabbccddee00ffaa), static_cast<uint64_t>(0xaaff));
925
926     auto byteSwap32 = compile([] (CCallHelpers& jit) {
927         jit.emitFunctionPrologue();
928         jit.move(GPRInfo::argumentGPR0, GPRInfo::returnValueGPR);
929         jit.byteSwap32(GPRInfo::returnValueGPR);
930         jit.emitFunctionEpilogue();
931         jit.ret();
932     });
933     CHECK_EQ(invoke<uint64_t>(byteSwap32, 0xaabbccddee001122), static_cast<uint64_t>(0x221100ee));
934     CHECK_EQ(invoke<uint64_t>(byteSwap32, 0xaabbccddee00ffaa), static_cast<uint64_t>(0xaaff00ee));
935
936     auto byteSwap64 = compile([] (CCallHelpers& jit) {
937         jit.emitFunctionPrologue();
938         jit.move(GPRInfo::argumentGPR0, GPRInfo::returnValueGPR);
939         jit.byteSwap64(GPRInfo::returnValueGPR);
940         jit.emitFunctionEpilogue();
941         jit.ret();
942     });
943     CHECK_EQ(invoke<uint64_t>(byteSwap64, 0xaabbccddee001122), static_cast<uint64_t>(0x221100eeddccbbaa));
944     CHECK_EQ(invoke<uint64_t>(byteSwap64, 0xaabbccddee00ffaa), static_cast<uint64_t>(0xaaff00eeddccbbaa));
945 #endif
946 }
947
948 void testMoveDoubleConditionally32()
949 {
950 #if CPU(X86_64) | CPU(ARM64)
951     double arg1 = 0;
952     double arg2 = 0;
953     const double zero = -0;
954
955     const double chosenDouble = 6.00000059604644775390625;
956     CHECK_EQ(static_cast<double>(static_cast<float>(chosenDouble)) == chosenDouble, false);
957
958     auto sel = compile([&] (CCallHelpers& jit) {
959         jit.emitFunctionPrologue();
960         jit.loadDouble(CCallHelpers::TrustedImmPtr(&zero), FPRInfo::returnValueFPR);
961         jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT1);
962         jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg2), FPRInfo::fpRegT2);
963
964         jit.move(MacroAssembler::TrustedImm32(-1), GPRInfo::regT0);
965         jit.moveDoubleConditionally32(MacroAssembler::Equal, GPRInfo::regT0, GPRInfo::regT0, FPRInfo::fpRegT1, FPRInfo::fpRegT2, FPRInfo::returnValueFPR);
966
967         jit.emitFunctionEpilogue();
968         jit.ret();
969     });
970
971     arg1 = chosenDouble;
972     arg2 = 43;
973     CHECK_EQ(invoke<double>(sel), chosenDouble);
974
975     arg1 = 43;
976     arg2 = chosenDouble;
977     CHECK_EQ(invoke<double>(sel), 43.0);
978
979 #endif
980 }
981
982 void testMoveDoubleConditionally64()
983 {
984 #if CPU(X86_64) | CPU(ARM64)
985     double arg1 = 0;
986     double arg2 = 0;
987     const double zero = -0;
988
989     const double chosenDouble = 6.00000059604644775390625;
990     CHECK_EQ(static_cast<double>(static_cast<float>(chosenDouble)) == chosenDouble, false);
991
992     auto sel = compile([&] (CCallHelpers& jit) {
993         jit.emitFunctionPrologue();
994         jit.loadDouble(CCallHelpers::TrustedImmPtr(&zero), FPRInfo::returnValueFPR);
995         jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT1);
996         jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg2), FPRInfo::fpRegT2);
997
998         jit.move(MacroAssembler::TrustedImm64(-1), GPRInfo::regT0);
999         jit.moveDoubleConditionally64(MacroAssembler::Equal, GPRInfo::regT0, GPRInfo::regT0, FPRInfo::fpRegT1, FPRInfo::fpRegT2, FPRInfo::returnValueFPR);
1000
1001         jit.emitFunctionEpilogue();
1002         jit.ret();
1003     });
1004
1005     arg1 = chosenDouble;
1006     arg2 = 43;
1007     CHECK_EQ(invoke<double>(sel), chosenDouble);
1008
1009     arg1 = 43;
1010     arg2 = chosenDouble;
1011     CHECK_EQ(invoke<double>(sel), 43.0);
1012
1013 #endif
1014 }
1015
1016 static void testCagePreservesPACFailureBit()
1017 {
1018 #if GIGACAGE_ENABLED
1019     ASSERT(!Gigacage::isDisablingPrimitiveGigacageDisabled());
1020     auto cage = compile([] (CCallHelpers& jit) {
1021         jit.emitFunctionPrologue();
1022         jit.cageConditionally(Gigacage::Primitive, GPRInfo::argumentGPR0, GPRInfo::argumentGPR1, GPRInfo::argumentGPR2);
1023         jit.move(GPRInfo::argumentGPR0, GPRInfo::returnValueGPR);
1024         jit.emitFunctionEpilogue();
1025         jit.ret();
1026     });
1027
1028     void* ptr = Gigacage::tryMalloc(Gigacage::Primitive, 1);
1029     void* taggedPtr = tagArrayPtr(ptr, 1);
1030     ASSERT(hasOneBitSet(Gigacage::size(Gigacage::Primitive) << 2));
1031     void* notCagedPtr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(ptr) + (Gigacage::size(Gigacage::Primitive) << 2));
1032     CHECK_NOT_EQ(Gigacage::caged(Gigacage::Primitive, notCagedPtr), notCagedPtr);
1033     void* taggedNotCagedPtr = tagArrayPtr(notCagedPtr, 1);
1034
1035     if (isARM64E()) {
1036         // FIXME: This won't work if authentication failures trap but I don't know how to test for that right now.
1037         CHECK_NOT_EQ(invoke<void*>(cage, taggedPtr, 2), ptr);
1038         CHECK_EQ(invoke<void*>(cage, taggedNotCagedPtr, 1), untagArrayPtr(taggedPtr, 2));
1039     } else
1040         CHECK_EQ(invoke<void*>(cage, taggedPtr, 2), ptr);
1041
1042     CHECK_EQ(invoke<void*>(cage, taggedPtr, 1), ptr);
1043
1044     auto cageWithoutAuthentication = compile([] (CCallHelpers& jit) {
1045         jit.emitFunctionPrologue();
1046         jit.cageWithoutUntagging(Gigacage::Primitive, GPRInfo::argumentGPR0);
1047         jit.move(GPRInfo::argumentGPR0, GPRInfo::returnValueGPR);
1048         jit.emitFunctionEpilogue();
1049         jit.ret();
1050     });
1051
1052     CHECK_EQ(invoke<void*>(cageWithoutAuthentication, taggedPtr), taggedPtr);
1053     if (isARM64E()) {
1054         // FIXME: This won't work if authentication failures trap but I don't know how to test for that right now.
1055         CHECK_NOT_EQ(invoke<void*>(cageWithoutAuthentication, taggedNotCagedPtr), taggedNotCagedPtr);
1056         CHECK_NOT_EQ(untagArrayPtr(invoke<void*>(cageWithoutAuthentication, taggedNotCagedPtr), 1), notCagedPtr);
1057         CHECK_NOT_EQ(invoke<void*>(cageWithoutAuthentication, taggedNotCagedPtr), taggedPtr);
1058         CHECK_NOT_EQ(untagArrayPtr(invoke<void*>(cageWithoutAuthentication, taggedNotCagedPtr), 1), ptr);
1059     }
1060
1061     Gigacage::free(Gigacage::Primitive, ptr);
1062 #endif
1063 }
1064
1065 #define RUN(test) do {                          \
1066         if (!shouldRun(#test))                  \
1067             break;                              \
1068         numberOfTests++;                        \
1069         tasks.append(                           \
1070             createSharedTask<void()>(           \
1071                 [&] () {                        \
1072                     dataLog(#test "...\n");     \
1073                     test;                       \
1074                     dataLog(#test ": OK!\n");   \
1075                 }));                            \
1076     } while (false);
1077
1078 void run(const char* filter)
1079 {
1080     JSC::initializeThreading();
1081     unsigned numberOfTests = 0;
1082
1083     Deque<RefPtr<SharedTask<void()>>> tasks;
1084
1085     auto shouldRun = [&] (const char* testName) -> bool {
1086         return !filter || WTF::findIgnoringASCIICaseWithoutLength(testName, filter) != WTF::notFound;
1087     };
1088
1089     RUN(testSimple());
1090     RUN(testGetEffectiveAddress(0xff00, 42, 8, CCallHelpers::TimesEight));
1091     RUN(testGetEffectiveAddress(0xff00, -200, -300, CCallHelpers::TimesEight));
1092     RUN(testBranchTruncateDoubleToInt32(0, 0));
1093     RUN(testBranchTruncateDoubleToInt32(42, 42));
1094     RUN(testBranchTruncateDoubleToInt32(42.7, 42));
1095     RUN(testBranchTruncateDoubleToInt32(-1234, -1234));
1096     RUN(testBranchTruncateDoubleToInt32(-1234.56, -1234));
1097     RUN(testBranchTruncateDoubleToInt32(std::numeric_limits<double>::infinity(), 0));
1098     RUN(testBranchTruncateDoubleToInt32(-std::numeric_limits<double>::infinity(), 0));
1099     RUN(testBranchTruncateDoubleToInt32(std::numeric_limits<double>::quiet_NaN(), 0));
1100     RUN(testBranchTruncateDoubleToInt32(std::numeric_limits<double>::signaling_NaN(), 0));
1101     RUN(testBranchTruncateDoubleToInt32(std::numeric_limits<double>::max(), 0));
1102     RUN(testBranchTruncateDoubleToInt32(-std::numeric_limits<double>::max(), 0));
1103     // We run this last one to make sure that we don't use flags that were not
1104     // reset to check a conversion result
1105     RUN(testBranchTruncateDoubleToInt32(123, 123));
1106
1107     RUN(testCompareDouble(MacroAssembler::DoubleEqual));
1108     RUN(testCompareDouble(MacroAssembler::DoubleNotEqual));
1109     RUN(testCompareDouble(MacroAssembler::DoubleGreaterThan));
1110     RUN(testCompareDouble(MacroAssembler::DoubleGreaterThanOrEqual));
1111     RUN(testCompareDouble(MacroAssembler::DoubleLessThan));
1112     RUN(testCompareDouble(MacroAssembler::DoubleLessThanOrEqual));
1113     RUN(testCompareDouble(MacroAssembler::DoubleEqualOrUnordered));
1114     RUN(testCompareDouble(MacroAssembler::DoubleNotEqualOrUnordered));
1115     RUN(testCompareDouble(MacroAssembler::DoubleGreaterThanOrUnordered));
1116     RUN(testCompareDouble(MacroAssembler::DoubleGreaterThanOrEqualOrUnordered));
1117     RUN(testCompareDouble(MacroAssembler::DoubleLessThanOrUnordered));
1118     RUN(testCompareDouble(MacroAssembler::DoubleLessThanOrEqualOrUnordered));
1119     RUN(testMul32WithImmediates());
1120
1121 #if CPU(X86) || CPU(X86_64) || CPU(ARM64)
1122     RUN(testCompareFloat(MacroAssembler::DoubleEqual));
1123     RUN(testCompareFloat(MacroAssembler::DoubleNotEqual));
1124     RUN(testCompareFloat(MacroAssembler::DoubleGreaterThan));
1125     RUN(testCompareFloat(MacroAssembler::DoubleGreaterThanOrEqual));
1126     RUN(testCompareFloat(MacroAssembler::DoubleLessThan));
1127     RUN(testCompareFloat(MacroAssembler::DoubleLessThanOrEqual));
1128     RUN(testCompareFloat(MacroAssembler::DoubleEqualOrUnordered));
1129     RUN(testCompareFloat(MacroAssembler::DoubleNotEqualOrUnordered));
1130     RUN(testCompareFloat(MacroAssembler::DoubleGreaterThanOrUnordered));
1131     RUN(testCompareFloat(MacroAssembler::DoubleGreaterThanOrEqualOrUnordered));
1132     RUN(testCompareFloat(MacroAssembler::DoubleLessThanOrUnordered));
1133     RUN(testCompareFloat(MacroAssembler::DoubleLessThanOrEqualOrUnordered));
1134 #endif
1135
1136 #if ENABLE(MASM_PROBE)
1137     RUN(testProbeReadsArgumentRegisters());
1138     RUN(testProbeWritesArgumentRegisters());
1139     RUN(testProbePreservesGPRS());
1140     RUN(testProbeModifiesStackPointerToInsideProbeStateOnStack());
1141     RUN(testProbeModifiesStackPointerToNBytesBelowSP());
1142     RUN(testProbeModifiesProgramCounter());
1143     RUN(testProbeModifiesStackValues());
1144 #endif // ENABLE(MASM_PROBE)
1145
1146     RUN(testByteSwap());
1147     RUN(testMoveDoubleConditionally32());
1148     RUN(testMoveDoubleConditionally64());
1149
1150     RUN(testCagePreservesPACFailureBit());
1151
1152     if (tasks.isEmpty())
1153         usage();
1154
1155     Lock lock;
1156
1157     Vector<Ref<Thread>> threads;
1158     for (unsigned i = filter ? 1 : WTF::numberOfProcessorCores(); i--;) {
1159         threads.append(
1160             Thread::create(
1161                 "testmasm thread",
1162                 [&] () {
1163                     for (;;) {
1164                         RefPtr<SharedTask<void()>> task;
1165                         {
1166                             LockHolder locker(lock);
1167                             if (tasks.isEmpty())
1168                                 return;
1169                             task = tasks.takeFirst();
1170                         }
1171
1172                         task->run();
1173                     }
1174                 }));
1175     }
1176
1177     for (auto& thread : threads)
1178         thread->waitForCompletion();
1179     crashLock.lock();
1180     dataLog("Completed ", numberOfTests, " tests\n");
1181 }
1182
1183 } // anonymous namespace
1184
1185 #else // not ENABLE(JIT)
1186
1187 static void run(const char*)
1188 {
1189     dataLog("JIT is not enabled.\n");
1190 }
1191
1192 #endif // ENABLE(JIT)
1193
1194 int main(int argc, char** argv)
1195 {
1196     const char* filter = nullptr;
1197     switch (argc) {
1198     case 1:
1199         break;
1200     case 2:
1201         filter = argv[1];
1202         break;
1203     default:
1204         usage();
1205         break;
1206     }
1207
1208     run(filter);
1209     return 0;
1210 }
1211
1212 #if OS(WINDOWS)
1213 extern "C" __declspec(dllexport) int WINAPI dllLauncherEntryPoint(int argc, const char* argv[])
1214 {
1215     return main(argc, const_cast<char**>(argv));
1216 }
1217 #endif