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