1// Copyright (C) 2018 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QV4PLATFORMASSEMBLER_P_H
5#define QV4PLATFORMASSEMBLER_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <private/qv4engine_p.h>
19#include <private/qv4function_p.h>
20#include <private/qv4global_p.h>
21#include <private/qv4stackframe_p.h>
22
23#include <wtf/Vector.h>
24#include <assembler/MacroAssembler.h>
25
26#include <QtCore/qhash.h>
27
28#if QT_CONFIG(qml_jit)
29
30QT_BEGIN_NAMESPACE
31
32namespace QV4 {
33namespace JIT {
34
35#if defined(Q_PROCESSOR_X86_64) || defined(ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES)
36#if defined(Q_OS_LINUX) || defined(Q_OS_QNX) || defined(Q_OS_FREEBSD) || defined(Q_OS_DARWIN) || defined(Q_OS_SOLARIS)
37
38class PlatformAssembler_X86_64_SysV : public JSC::MacroAssembler<JSC::MacroAssemblerX86_64>
39{
40public:
41 static constexpr int NativeStackAlignment = 16;
42
43 static const RegisterID NoRegister = RegisterID::none;
44
45 static const RegisterID ReturnValueRegister = RegisterID::eax;
46 static const RegisterID ReturnValueRegisterValue = ReturnValueRegister;
47 static const RegisterID AccumulatorRegister = RegisterID::eax;
48 static const RegisterID AccumulatorRegisterValue = AccumulatorRegister;
49 static const RegisterID ScratchRegister = RegisterID::r10;
50 static const RegisterID ScratchRegister2 = RegisterID::r9; // Note: overlaps with Arg5Reg, so do not use while setting up a call!
51 static const RegisterID JSStackFrameRegister = RegisterID::r12;
52 static const RegisterID CppStackFrameRegister = RegisterID::r13;
53 static const RegisterID EngineRegister = RegisterID::r14;
54 static const RegisterID StackPointerRegister = RegisterID::esp;
55 static const RegisterID FramePointerRegister = RegisterID::ebp;
56 static const FPRegisterID FPScratchRegister = FPRegisterID::xmm1;
57 static const FPRegisterID FPScratchRegister2 = FPRegisterID::xmm2;
58
59 static const RegisterID Arg0Reg = RegisterID::edi;
60 static const RegisterID Arg1Reg = RegisterID::esi;
61 static const RegisterID Arg2Reg = RegisterID::edx;
62 static const RegisterID Arg3Reg = RegisterID::ecx;
63 static const RegisterID Arg4Reg = RegisterID::r8;
64 static const RegisterID Arg5Reg = RegisterID::r9;
65 static const RegisterID Arg6Reg = NoRegister;
66 static const RegisterID Arg7Reg = NoRegister;
67 static const int ArgInRegCount = 6;
68
69 void popValue()
70 {
71 addPtr(imm: TrustedImmPtr(sizeof(ReturnedValue)), dest: StackPointerRegister);
72 }
73
74 void generatePlatformFunctionEntry()
75 {
76 push(src: FramePointerRegister);
77 move(src: StackPointerRegister, dest: FramePointerRegister);
78 move(imm: TrustedImmPtr(nullptr), dest: AccumulatorRegister); push(src: AccumulatorRegister); // exceptionHandler
79 push(src: JSStackFrameRegister);
80 push(src: CppStackFrameRegister);
81 push(src: EngineRegister);
82 move(src: Arg0Reg, dest: CppStackFrameRegister);
83 move(src: Arg1Reg, dest: EngineRegister);
84 }
85
86 void generatePlatformFunctionExit(bool tailCall = false)
87 {
88 pop(dest: EngineRegister);
89 pop(dest: CppStackFrameRegister);
90 pop(dest: JSStackFrameRegister);
91 pop(); // exceptionHandler
92 pop(dest: FramePointerRegister);
93 if (!tailCall)
94 ret();
95 }
96
97 void callAbsolute(const void *funcPtr)
98 {
99 move(imm: TrustedImmPtr(funcPtr), dest: ScratchRegister);
100 call(target: ScratchRegister);
101 }
102
103 void jumpAbsolute(const void *funcPtr)
104 {
105 move(imm: TrustedImmPtr(funcPtr), dest: ScratchRegister);
106 jump(target: ScratchRegister);
107 }
108
109 void pushAligned(RegisterID reg)
110 {
111 subPtr(imm: TrustedImm32(PointerSize), dest: StackPointerRegister);
112 push(src: reg);
113 }
114
115 void popAligned(RegisterID reg)
116 {
117 pop(dest: reg);
118 addPtr(imm: TrustedImm32(PointerSize), srcDest: StackPointerRegister);
119 }
120};
121
122typedef PlatformAssembler_X86_64_SysV PlatformAssemblerBase;
123
124#endif
125#if defined(Q_OS_WIN)
126
127class PlatformAssembler_Win64 : public JSC::MacroAssembler<JSC::MacroAssemblerX86_64>
128{
129public:
130 static const RegisterID NoRegister = RegisterID::none;
131
132 static const RegisterID ReturnValueRegister = RegisterID::eax;
133 static const RegisterID ReturnValueRegisterValue = ReturnValueRegister;
134 static const RegisterID AccumulatorRegister = RegisterID::eax;
135 static const RegisterID AccumulatorRegisterValue = AccumulatorRegister;
136 static const RegisterID ScratchRegister = RegisterID::r10;
137 static const RegisterID ScratchRegister2 = RegisterID::r9; // Note: overlaps with Arg3Reg, so do not use while setting up a call!
138 static const RegisterID JSStackFrameRegister = RegisterID::r12;
139 static const RegisterID CppStackFrameRegister = RegisterID::r13;
140 static const RegisterID EngineRegister = RegisterID::r14;
141 static const RegisterID StackPointerRegister = RegisterID::esp;
142 static const RegisterID FramePointerRegister = RegisterID::ebp;
143 static const FPRegisterID FPScratchRegister = FPRegisterID::xmm1;
144
145 static const RegisterID Arg0Reg = RegisterID::ecx;
146 static const RegisterID Arg1Reg = RegisterID::edx;
147 static const RegisterID Arg2Reg = RegisterID::r8;
148 static const RegisterID Arg3Reg = RegisterID::r9;
149 static const RegisterID Arg4Reg = NoRegister;
150 static const RegisterID Arg5Reg = NoRegister;
151 static const RegisterID Arg6Reg = NoRegister;
152 static const RegisterID Arg7Reg = NoRegister;
153 static const int ArgInRegCount = 4;
154
155 void popValue()
156 {
157 addPtr(TrustedImmPtr(sizeof(ReturnedValue)), StackPointerRegister);
158 }
159
160 void generatePlatformFunctionEntry()
161 {
162 push(FramePointerRegister);
163 move(StackPointerRegister, FramePointerRegister);
164 move(TrustedImmPtr(nullptr), AccumulatorRegister); push(AccumulatorRegister); // exceptionHandler
165 push(JSStackFrameRegister);
166 push(CppStackFrameRegister);
167 push(EngineRegister);
168 move(Arg0Reg, CppStackFrameRegister);
169 move(Arg1Reg, EngineRegister);
170 }
171
172 void generatePlatformFunctionExit(bool tailCall = false)
173 {
174 pop(EngineRegister);
175 pop(CppStackFrameRegister);
176 pop(JSStackFrameRegister);
177 pop(); // exceptionHandler
178 pop(FramePointerRegister);
179 if (!tailCall)
180 ret();
181 }
182
183 void callAbsolute(const void *funcPtr)
184 {
185 move(TrustedImmPtr(funcPtr), ScratchRegister);
186 subPtr(TrustedImm32(4 * PointerSize), StackPointerRegister);
187 call(ScratchRegister);
188 addPtr(TrustedImm32(4 * PointerSize), StackPointerRegister);
189 }
190
191 void jumpAbsolute(const void *funcPtr)
192 {
193 move(TrustedImmPtr(funcPtr), ScratchRegister);
194 jump(ScratchRegister);
195 }
196
197 void pushAligned(RegisterID reg)
198 {
199 subPtr(TrustedImm32(PointerSize), StackPointerRegister);
200 push(reg);
201 }
202
203 void popAligned(RegisterID reg)
204 {
205 pop(reg);
206 addPtr(TrustedImm32(PointerSize), StackPointerRegister);
207 }
208};
209
210typedef PlatformAssembler_Win64 PlatformAssemblerBase;
211
212#endif
213#endif
214
215#if (defined(Q_PROCESSOR_X86) && !defined(Q_PROCESSOR_X86_64)) || defined(ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES)
216
217class PlatformAssembler_X86_All : public JSC::MacroAssembler<JSC::MacroAssemblerX86>
218{
219public:
220 static const RegisterID NoRegister = RegisterID::none;
221
222 static const RegisterID ReturnValueRegisterValue = RegisterID::eax;
223 static const RegisterID ReturnValueRegisterTag = RegisterID::edx;
224 static const RegisterID ScratchRegister = RegisterID::ecx;
225 static const RegisterID AccumulatorRegisterValue = ReturnValueRegisterValue;
226 static const RegisterID AccumulatorRegisterTag = ReturnValueRegisterTag;
227 static const RegisterID JSStackFrameRegister = RegisterID::ebx;
228 static const RegisterID CppStackFrameRegister = RegisterID::esi;
229 static const RegisterID EngineRegister = RegisterID::edi;
230 static const RegisterID StackPointerRegister = RegisterID::esp;
231 static const RegisterID FramePointerRegister = RegisterID::ebp;
232 static const FPRegisterID FPScratchRegister = FPRegisterID::xmm1;
233
234 static const RegisterID Arg0Reg = NoRegister;
235 static const RegisterID Arg1Reg = NoRegister;
236 static const RegisterID Arg2Reg = NoRegister;
237 static const RegisterID Arg3Reg = NoRegister;
238 static const RegisterID Arg4Reg = NoRegister;
239 static const RegisterID Arg5Reg = NoRegister;
240 static const RegisterID Arg6Reg = NoRegister;
241 static const RegisterID Arg7Reg = NoRegister;
242 static const int ArgInRegCount = 0;
243
244 void popValue()
245 {
246 addPtr(TrustedImmPtr(sizeof(ReturnedValue)), StackPointerRegister);
247 }
248
249 void generatePlatformFunctionEntry()
250 {
251 push(RegisterID::ebp);
252 move(RegisterID::esp, RegisterID::ebp);
253 move(TrustedImmPtr(nullptr), AccumulatorRegisterValue); push(AccumulatorRegisterValue); // exceptionHandler
254 push(JSStackFrameRegister);
255 push(CppStackFrameRegister);
256 push(EngineRegister);
257 // Ensure the stack is 16-byte aligned in order for compiler generated aligned SSE2
258 // instructions to be able to target the stack.
259 subPtr(TrustedImm32(8), StackPointerRegister);
260 loadPtr(Address(FramePointerRegister, 2 * PointerSize), CppStackFrameRegister);
261 loadPtr(Address(FramePointerRegister, 3 * PointerSize), EngineRegister);
262 }
263
264 void generatePlatformFunctionExit(bool tailCall = false)
265 {
266 addPtr(TrustedImm32(8), StackPointerRegister);
267 pop(EngineRegister);
268 pop(CppStackFrameRegister);
269 pop(JSStackFrameRegister);
270 pop(); // exceptionHandler
271 pop(RegisterID::ebp);
272 if (!tailCall)
273 ret();
274 }
275
276 void callAbsolute(const void *funcPtr)
277 {
278 move(TrustedImmPtr(funcPtr), ScratchRegister);
279 call(ScratchRegister);
280 }
281
282 void jumpAbsolute(const void *funcPtr)
283 {
284 move(TrustedImmPtr(funcPtr), ScratchRegister);
285 jump(ScratchRegister);
286 }
287
288 void pushAligned(RegisterID reg)
289 {
290 subPtr(TrustedImm32(3 * PointerSize), StackPointerRegister);
291 push(reg);
292 }
293
294 void popAligned(RegisterID reg)
295 {
296 pop(reg);
297 addPtr(TrustedImm32(3 * PointerSize), StackPointerRegister);
298 }
299};
300
301typedef PlatformAssembler_X86_All PlatformAssemblerBase;
302
303#endif
304
305#if defined(Q_PROCESSOR_ARM_64) || defined(ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES)
306
307class PlatformAssembler_ARM64 : public JSC::MacroAssembler<JSC::MacroAssemblerARM64>
308{
309public:
310 static const RegisterID NoRegister = RegisterID::none;
311
312 static const RegisterID ReturnValueRegister = JSC::ARM64Registers::x0;
313 static const RegisterID ReturnValueRegisterValue = ReturnValueRegister;
314 static const RegisterID AccumulatorRegister = JSC::ARM64Registers::x9;
315 static const RegisterID AccumulatorRegisterValue = AccumulatorRegister;
316 static const RegisterID ScratchRegister = JSC::ARM64Registers::x10;
317 static const RegisterID ScratchRegister2 = JSC::ARM64Registers::x7; // Note: overlaps with Arg7Reg, so do not use while setting up a call!
318 static const RegisterID JSStackFrameRegister = JSC::ARM64Registers::x19;
319 static const RegisterID CppStackFrameRegister = JSC::ARM64Registers::x20;
320 static const RegisterID EngineRegister = JSC::ARM64Registers::x21;
321 static const RegisterID StackPointerRegister = JSC::ARM64Registers::sp;
322 static const RegisterID FramePointerRegister = JSC::ARM64Registers::fp;
323 static const FPRegisterID FPScratchRegister = JSC::ARM64Registers::q1;
324
325 static const RegisterID Arg0Reg = JSC::ARM64Registers::x0;
326 static const RegisterID Arg1Reg = JSC::ARM64Registers::x1;
327 static const RegisterID Arg2Reg = JSC::ARM64Registers::x2;
328 static const RegisterID Arg3Reg = JSC::ARM64Registers::x3;
329 static const RegisterID Arg4Reg = JSC::ARM64Registers::x4;
330 static const RegisterID Arg5Reg = JSC::ARM64Registers::x5;
331 static const RegisterID Arg6Reg = JSC::ARM64Registers::x6;
332 static const RegisterID Arg7Reg = JSC::ARM64Registers::x7;
333 static const int ArgInRegCount = 8;
334
335 void push(RegisterID src)
336 {
337 pushToSave(src);
338 }
339
340 void pop(RegisterID dest)
341 {
342 popToRestore(dest);
343 }
344
345 void pop()
346 {
347 add64(TrustedImm32(16), stackPointerRegister);
348 }
349
350 void popValue()
351 {
352 pop();
353 }
354
355 void generatePlatformFunctionEntry()
356 {
357 pushPair(JSC::ARM64Registers::fp, JSC::ARM64Registers::lr);
358 move(RegisterID::sp, RegisterID::fp);
359 move(TrustedImmPtr(nullptr), AccumulatorRegister); // exceptionHandler
360 pushPair(JSStackFrameRegister, AccumulatorRegister);
361 pushPair(EngineRegister, CppStackFrameRegister);
362 move(Arg0Reg, CppStackFrameRegister);
363 move(Arg1Reg, EngineRegister);
364 }
365
366 void generatePlatformFunctionExit(bool tailCall = false)
367 {
368 if (!tailCall) // do not overwrite arg0 (used in the tail call)
369 move(AccumulatorRegister, ReturnValueRegister);
370 popPair(EngineRegister, CppStackFrameRegister);
371 popPair(JSStackFrameRegister, AccumulatorRegister);
372 popPair(JSC::ARM64Registers::fp, JSC::ARM64Registers::lr);
373 if (!tailCall)
374 ret();
375 }
376
377 void callAbsolute(const void *funcPtr)
378 {
379 move(TrustedImmPtr(funcPtr), ScratchRegister);
380 call(ScratchRegister);
381 }
382
383 void jumpAbsolute(const void *funcPtr)
384 {
385 move(TrustedImmPtr(funcPtr), ScratchRegister);
386 jump(ScratchRegister);
387 }
388
389 void pushAligned(RegisterID reg)
390 {
391 pushToSave(reg);
392 }
393
394 void popAligned(RegisterID reg)
395 {
396 popToRestore(reg);
397 }
398};
399
400typedef PlatformAssembler_ARM64 PlatformAssemblerBase;
401
402#endif
403
404#if defined(Q_PROCESSOR_ARM_32) || defined(ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES)
405
406class PlatformAssembler_ARM32 : public JSC::MacroAssembler<JSC::MacroAssemblerARMv7>
407{
408public:
409 static const RegisterID NoRegister = RegisterID::none;
410
411 static const RegisterID ReturnValueRegisterValue = JSC::ARMRegisters::r0;
412 static const RegisterID ReturnValueRegisterTag = JSC::ARMRegisters::r1;
413 static const RegisterID ScratchRegister = JSC::ARMRegisters::r2;
414 static const RegisterID AccumulatorRegisterValue = JSC::ARMRegisters::r4;
415 static const RegisterID AccumulatorRegisterTag = JSC::ARMRegisters::r5;
416 // r6 is used by MacroAssemblerARMv7
417 static const RegisterID JSStackFrameRegister = JSC::ARMRegisters::r8;
418 static const RegisterID CppStackFrameRegister = JSC::ARMRegisters::r10;
419#if CPU(ARM_THUMB2)
420 static const RegisterID FramePointerRegister = JSC::ARMRegisters::r7;
421 static const RegisterID EngineRegister = JSC::ARMRegisters::r11;
422#else // Thumbs down
423 static const RegisterID FramePointerRegister = JSC::ARMRegisters::r11;
424 static const RegisterID EngineRegister = JSC::ARMRegisters::r7;
425#endif
426 static const RegisterID StackPointerRegister = JSC::ARMRegisters::r13;
427 static const FPRegisterID FPScratchRegister = JSC::ARMRegisters::d1;
428
429 static const RegisterID Arg0Reg = JSC::ARMRegisters::r0;
430 static const RegisterID Arg1Reg = JSC::ARMRegisters::r1;
431 static const RegisterID Arg2Reg = JSC::ARMRegisters::r2;
432 static const RegisterID Arg3Reg = JSC::ARMRegisters::r3;
433 static const RegisterID Arg4Reg = NoRegister;
434 static const RegisterID Arg5Reg = NoRegister;
435 static const RegisterID Arg6Reg = NoRegister;
436 static const RegisterID Arg7Reg = NoRegister;
437 static const int ArgInRegCount = 4;
438
439 void popValue()
440 {
441 addPtr(TrustedImm32(sizeof(ReturnedValue)), StackPointerRegister);
442 }
443
444 void generatePlatformFunctionEntry()
445 {
446 push(JSC::ARMRegisters::lr);
447 push(FramePointerRegister);
448 move(StackPointerRegister, FramePointerRegister);
449 push(TrustedImm32(0)); // exceptionHandler
450 push(AccumulatorRegisterValue);
451 push(AccumulatorRegisterTag);
452 push(addressTempRegister);
453 push(JSStackFrameRegister);
454 push(CppStackFrameRegister);
455 push(EngineRegister);
456 subPtr(TrustedImm32(4), StackPointerRegister); // stack alignment
457 move(Arg0Reg, CppStackFrameRegister);
458 move(Arg1Reg, EngineRegister);
459 }
460
461 void generatePlatformFunctionExit(bool tailCall = false)
462 {
463 if (!tailCall) { // do not overwrite arg0 and arg1 (used in the tail call)
464 move(AccumulatorRegisterValue, ReturnValueRegisterValue);
465 move(AccumulatorRegisterTag, ReturnValueRegisterTag);
466 }
467 addPtr(TrustedImm32(4), StackPointerRegister); // stack alignment
468 pop(EngineRegister);
469 pop(CppStackFrameRegister);
470 pop(JSStackFrameRegister);
471 pop(addressTempRegister);
472 pop(AccumulatorRegisterTag);
473 pop(AccumulatorRegisterValue);
474 pop(); // exceptionHandler
475 pop(FramePointerRegister);
476 pop(JSC::ARMRegisters::lr);
477 if (!tailCall)
478 ret();
479 }
480
481 void callAbsolute(const void *funcPtr)
482 {
483 move(TrustedImmPtr(funcPtr), dataTempRegister);
484 call(dataTempRegister);
485 }
486
487 void jumpAbsolute(const void *funcPtr)
488 {
489 move(TrustedImmPtr(funcPtr), dataTempRegister);
490 jump(dataTempRegister);
491 }
492
493 void pushAligned(RegisterID reg)
494 {
495 subPtr(TrustedImm32(PointerSize), StackPointerRegister);
496 push(reg);
497 }
498
499 void popAligned(RegisterID reg)
500 {
501 pop(reg);
502 addPtr(TrustedImm32(PointerSize), StackPointerRegister);
503 }
504};
505
506typedef PlatformAssembler_ARM32 PlatformAssemblerBase;
507#endif
508
509class PlatformAssemblerCommon : public JIT::PlatformAssemblerBase
510{
511public:
512 PlatformAssemblerCommon(const Value *constantTable)
513 : constantTable(constantTable)
514 {}
515
516 virtual ~PlatformAssemblerCommon();
517
518 Address exceptionHandlerAddress() const
519 {
520 return Address(FramePointerRegister, -1 * PointerSize);
521 }
522
523 Address contextAddress() const
524 {
525 return Address(JSStackFrameRegister, offsetof(CallData, context));
526 }
527
528 RegisterID registerForArg(int arg) const
529 {
530 Q_ASSERT(arg >= 0);
531 Q_ASSERT(arg < ArgInRegCount);
532 switch (arg) {
533 case 0: return Arg0Reg;
534 case 1: return Arg1Reg;
535 case 2: return Arg2Reg;
536 case 3: return Arg3Reg;
537 case 4: return Arg4Reg;
538 case 5: return Arg5Reg;
539 case 6: return Arg6Reg;
540 case 7: return Arg7Reg;
541 default:
542 Q_UNIMPLEMENTED();
543 Q_UNREACHABLE();
544 }
545 }
546
547 Address loadFunctionPtr(RegisterID target)
548 {
549 Address addr(CppStackFrameRegister, offsetof(JSTypesStackFrame, v4Function));
550 loadPtr(address: addr, dest: target);
551 return Address(target);
552 }
553
554 Address loadCompilationUnitPtr(RegisterID target)
555 {
556 Address addr = loadFunctionPtr(target);
557 addr.offset = offsetof(QV4::FunctionData, compilationUnit);
558 loadPtr(address: addr, dest: target);
559 return Address(target);
560 }
561
562 Address loadConstAddress(int constIndex, RegisterID baseReg = ScratchRegister)
563 {
564 Address addr = loadCompilationUnitPtr(target: baseReg);
565 addr.offset = offsetof(QV4::CompiledData::CompilationUnitBase, constants);
566 loadPtr(address: addr, dest: baseReg);
567 addr.offset = constIndex * int(sizeof(QV4::Value));
568 return addr;
569 }
570
571 Address loadStringAddress(int stringId)
572 {
573 Address addr = loadCompilationUnitPtr(target: ScratchRegister);
574 addr.offset = offsetof(QV4::CompiledData::CompilationUnitBase, runtimeStrings);
575 loadPtr(address: addr, dest: ScratchRegister);
576 return Address(ScratchRegister, stringId * PointerSize);
577 }
578
579 void passAsArg(RegisterID src, int arg)
580 {
581 move(src, dest: registerForArg(arg));
582 }
583
584 void generateCatchTrampoline(std::function<void()> loadUndefined)
585 {
586 for (Jump j : catchyJumps)
587 j.link(masm: this);
588
589 // We don't need to check for isInterrupted here because if that is set,
590 // then the first checkException() in any exception handler will find another "exception"
591 // and jump out of the exception handler.
592 loadPtr(address: exceptionHandlerAddress(), dest: ScratchRegister);
593 Jump exitFunction = branchPtr(cond: Equal, left: ScratchRegister, right: TrustedImmPtr(0));
594 loadUndefined();
595 jump(target: ScratchRegister);
596 exitFunction.link(masm: this);
597
598 if (functionExit.isSet())
599 jump(target: functionExit);
600 else
601 generateFunctionExit();
602 }
603
604 void checkException()
605 {
606 // This actually reads 4 bytes, starting at hasException.
607 // Therefore, it also reads the isInterrupted flag, and triggers an exception on that.
608 addCatchyJump(
609 j: branch32(cond: NotEqual,
610 left: Address(EngineRegister, offsetof(EngineBase, hasException)),
611 right: TrustedImm32(0)));
612 }
613
614 void addCatchyJump(Jump j)
615 {
616 Q_ASSERT(j.isSet());
617 catchyJumps.push_back(x: j);
618 }
619
620 void generateFunctionEntry()
621 {
622 generatePlatformFunctionEntry();
623 loadPtr(address: Address(CppStackFrameRegister, offsetof(JSTypesStackFrame, jsFrame)),
624 dest: JSStackFrameRegister);
625 allocateStackSpace();
626 }
627
628 virtual void allocateStackSpace() {}
629
630 void generateFunctionExit()
631 {
632 if (functionExit.isSet()) {
633 jump(target: functionExit);
634 return;
635 }
636
637 functionExit = label();
638 freeStackSpace();
639 generatePlatformFunctionExit();
640 }
641
642 virtual void freeStackSpace() {}
643
644 void addLabelForOffset(int offset)
645 {
646 if (!labelForOffset.contains(key: offset))
647 labelForOffset.insert(key: offset, value: label());
648 }
649
650 void addJumpToOffset(const Jump &jump, int offset)
651 {
652 jumpsToLink.push_back(x: { .jump: jump, .offset: offset });
653 }
654
655 void addEHTarget(const DataLabelPtr &label, int offset)
656 {
657 ehTargets.push_back(x: { .label: label, .offset: offset });
658 }
659
660 void link(Function *function, const char *jitKind);
661
662 Value constant(int idx) const
663 { return constantTable[idx]; }
664
665 // stuff for runtime calls
666 void prepareCallWithArgCount(int argc);
667 void storeInstructionPointer(int instructionOffset);
668 void passAccumulatorAsArg(int arg);
669 void pushAccumulatorAsArg(int arg);
670 void passFunctionAsArg(int arg);
671 void passEngineAsArg(int arg);
672 void passJSSlotAsArg(int reg, int arg);
673 void passAddressAsArg(Address addr, int arg);
674 void passCppFrameAsArg(int arg);
675 void passInt32AsArg(int value, int arg);
676 void passPointerAsArg(void *ptr, int arg);
677 void callRuntime(const void *funcPtr, const char *functionName = nullptr);
678 void callRuntimeUnchecked(const void *funcPtr, const char *functionName = nullptr);
679 void tailCallRuntime(const void *funcPtr, const char *functionName = nullptr);
680 void setTailCallArg(RegisterID src, int arg);
681 Address jsAlloca(int slotCount);
682 void storeInt32AsValue(int srcInt, Address destAddr);
683
684private:
685 void passAccumulatorAsArg_internal(int arg, bool doPush);
686 static Address argStackAddress(int arg);
687
688private:
689 const Value* constantTable;
690 struct JumpTarget { JSC::MacroAssemblerBase::Jump jump; int offset; };
691 std::vector<JumpTarget> jumpsToLink;
692 struct ExceptionHanlderTarget { JSC::MacroAssemblerBase::DataLabelPtr label; int offset; };
693 std::vector<ExceptionHanlderTarget> ehTargets;
694 QHash<int, JSC::MacroAssemblerBase::Label> labelForOffset;
695 QHash<const void *, const char *> functions;
696 std::vector<Jump> catchyJumps;
697 Label functionExit;
698
699#ifndef QT_NO_DEBUG
700 enum { NoCall = -1 };
701 int remainingArgcForCall = NoCall;
702#endif
703 int argcOnStackForCall = 0;
704};
705
706} // JIT namespace
707} // QV4 namespace
708
709QT_END_NAMESPACE
710
711#endif // QT_CONFIG(qml_jit)
712
713#endif // QV4PLATFORMASSEMBLER_P_H
714

source code of qtdeclarative/src/qml/jit/qv4assemblercommon_p.h