5#ifndef QV4PLATFORMASSEMBLER_P_H
6#define QV4PLATFORMASSEMBLER_P_H
19#include <private/qv4engine_p.h>
20#include <private/qv4function_p.h>
21#include <private/qv4global_p.h>
22#include <private/qv4stackframe_p.h>
24#include <wtf/Vector.h>
25#include <assembler/MacroAssembler.h>
27#include <QtCore/qhash.h>
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)
39class PlatformAssembler_X86_64_SysV :
public JSC::MacroAssembler<JSC::MacroAssemblerX86_64>
42 static constexpr int NativeStackAlignment = 16;
44 static const RegisterID NoRegister = RegisterID::none;
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;
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;
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;
72 addPtr(TrustedImmPtr(
sizeof(ReturnedValue)), StackPointerRegister);
75 void generatePlatformFunctionEntry()
77 push(FramePointerRegister);
78 move(StackPointerRegister, FramePointerRegister);
79 move(TrustedImmPtr(
nullptr), AccumulatorRegister); push(AccumulatorRegister);
80 push(JSStackFrameRegister);
81 push(CppStackFrameRegister);
83 move(Arg0Reg, CppStackFrameRegister);
84 move(Arg1Reg, EngineRegister);
87 void generatePlatformFunctionExit(
bool tailCall =
false)
90 pop(CppStackFrameRegister);
91 pop(JSStackFrameRegister);
93 pop(FramePointerRegister);
98 void callAbsolute(
const void *funcPtr)
100 move(TrustedImmPtr(funcPtr), ScratchRegister);
101 call(ScratchRegister);
104 void jumpAbsolute(
const void *funcPtr)
106 move(TrustedImmPtr(funcPtr), ScratchRegister);
107 jump(ScratchRegister);
110 void pushAligned(RegisterID reg)
112 subPtr(TrustedImm32(PointerSize), StackPointerRegister);
116 void popAligned(RegisterID reg)
119 addPtr(TrustedImm32(PointerSize), StackPointerRegister);
123typedef PlatformAssembler_X86_64_SysV PlatformAssemblerBase;
128class PlatformAssembler_Win64 :
public JSC::MacroAssembler<JSC::MacroAssemblerX86_64>
131 static const RegisterID NoRegister = RegisterID::none;
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;
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;
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;
158 addPtr(TrustedImmPtr(
sizeof(ReturnedValue)), StackPointerRegister);
161 void generatePlatformFunctionEntry()
163 push(FramePointerRegister);
164 move(StackPointerRegister, FramePointerRegister);
165 move(TrustedImmPtr(
nullptr), AccumulatorRegister); push(AccumulatorRegister);
166 push(JSStackFrameRegister);
167 push(CppStackFrameRegister);
168 push(EngineRegister);
169 move(Arg0Reg, CppStackFrameRegister);
170 move(Arg1Reg, EngineRegister);
173 void generatePlatformFunctionExit(
bool tailCall =
false)
176 pop(CppStackFrameRegister);
177 pop(JSStackFrameRegister);
179 pop(FramePointerRegister);
184 void callAbsolute(
const void *funcPtr)
186 move(TrustedImmPtr(funcPtr), ScratchRegister);
187 subPtr(TrustedImm32(4 * PointerSize), StackPointerRegister);
188 call(ScratchRegister);
189 addPtr(TrustedImm32(4 * PointerSize), StackPointerRegister);
192 void jumpAbsolute(
const void *funcPtr)
194 move(TrustedImmPtr(funcPtr), ScratchRegister);
195 jump(ScratchRegister);
198 void pushAligned(RegisterID reg)
200 subPtr(TrustedImm32(PointerSize), StackPointerRegister);
204 void popAligned(RegisterID reg)
207 addPtr(TrustedImm32(PointerSize), StackPointerRegister);
211typedef PlatformAssembler_Win64 PlatformAssemblerBase;
216#if (defined(Q_PROCESSOR_X86) && !defined(Q_PROCESSOR_X86_64)) || defined(ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES)
218class PlatformAssembler_X86_All :
public JSC::MacroAssembler<JSC::MacroAssemblerX86>
221 static const RegisterID NoRegister = RegisterID::none;
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;
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;
247 addPtr(TrustedImmPtr(
sizeof(ReturnedValue)), StackPointerRegister);
250 void generatePlatformFunctionEntry()
252 push(RegisterID::ebp);
253 move(RegisterID::esp, RegisterID::ebp);
254 move(TrustedImmPtr(
nullptr), AccumulatorRegisterValue); push(AccumulatorRegisterValue);
255 push(JSStackFrameRegister);
256 push(CppStackFrameRegister);
257 push(EngineRegister);
260 subPtr(TrustedImm32(8), StackPointerRegister);
261 loadPtr(Address(FramePointerRegister, 2 * PointerSize), CppStackFrameRegister);
262 loadPtr(Address(FramePointerRegister, 3 * PointerSize), EngineRegister);
265 void generatePlatformFunctionExit(
bool tailCall =
false)
267 addPtr(TrustedImm32(8), StackPointerRegister);
269 pop(CppStackFrameRegister);
270 pop(JSStackFrameRegister);
272 pop(RegisterID::ebp);
277 void callAbsolute(
const void *funcPtr)
279 move(TrustedImmPtr(funcPtr), ScratchRegister);
280 call(ScratchRegister);
283 void jumpAbsolute(
const void *funcPtr)
285 move(TrustedImmPtr(funcPtr), ScratchRegister);
286 jump(ScratchRegister);
289 void pushAligned(RegisterID reg)
291 subPtr(TrustedImm32(3 * PointerSize), StackPointerRegister);
295 void popAligned(RegisterID reg)
298 addPtr(TrustedImm32(3 * PointerSize), StackPointerRegister);
302typedef PlatformAssembler_X86_All PlatformAssemblerBase;
306#if defined(Q_PROCESSOR_ARM_64) || defined(ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES)
308class PlatformAssembler_ARM64 :
public JSC::MacroAssembler<JSC::MacroAssemblerARM64>
311 static const RegisterID NoRegister = RegisterID::none;
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;
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;
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;
336 void push(RegisterID src)
341 void pop(RegisterID dest)
348 add64(TrustedImm32(16), stackPointerRegister);
356 void generatePlatformFunctionEntry()
358 pushPair(JSC::ARM64Registers::fp, JSC::ARM64Registers::lr);
359 move(RegisterID::sp, RegisterID::fp);
360 move(TrustedImmPtr(
nullptr), AccumulatorRegister);
361 pushPair(JSStackFrameRegister, AccumulatorRegister);
362 pushPair(EngineRegister, CppStackFrameRegister);
363 move(Arg0Reg, CppStackFrameRegister);
364 move(Arg1Reg, EngineRegister);
367 void generatePlatformFunctionExit(
bool tailCall =
false)
370 move(AccumulatorRegister, ReturnValueRegister);
371 popPair(EngineRegister, CppStackFrameRegister);
372 popPair(JSStackFrameRegister, AccumulatorRegister);
373 popPair(JSC::ARM64Registers::fp, JSC::ARM64Registers::lr);
378 void callAbsolute(
const void *funcPtr)
380 move(TrustedImmPtr(funcPtr), ScratchRegister);
381 call(ScratchRegister);
384 void jumpAbsolute(
const void *funcPtr)
386 move(TrustedImmPtr(funcPtr), ScratchRegister);
387 jump(ScratchRegister);
390 void pushAligned(RegisterID reg)
395 void popAligned(RegisterID reg)
401typedef PlatformAssembler_ARM64 PlatformAssemblerBase;
405#if defined(Q_PROCESSOR_ARM_32) || defined(ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES)
407class PlatformAssembler_ARM32 :
public JSC::MacroAssembler<JSC::MacroAssemblerARMv7>
410 static const RegisterID NoRegister = RegisterID::none;
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;
418 static const RegisterID JSStackFrameRegister = JSC::ARMRegisters::r8;
419 static const RegisterID CppStackFrameRegister = JSC::ARMRegisters::r10;
421 static const RegisterID FramePointerRegister = JSC::ARMRegisters::r7;
422 static const RegisterID EngineRegister = JSC::ARMRegisters::r11;
424 static const RegisterID FramePointerRegister = JSC::ARMRegisters::r11;
425 static const RegisterID EngineRegister = JSC::ARMRegisters::r7;
427 static const RegisterID StackPointerRegister = JSC::ARMRegisters::r13;
428 static const FPRegisterID FPScratchRegister = JSC::ARMRegisters::d1;
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;
442 addPtr(TrustedImm32(
sizeof(ReturnedValue)), StackPointerRegister);
445 void generatePlatformFunctionEntry()
447 push(JSC::ARMRegisters::lr);
448 push(FramePointerRegister);
449 move(StackPointerRegister, FramePointerRegister);
450 push(TrustedImm32(0));
451 push(AccumulatorRegisterValue);
452 push(AccumulatorRegisterTag);
453 push(addressTempRegister);
454 push(JSStackFrameRegister);
455 push(CppStackFrameRegister);
456 push(EngineRegister);
457 subPtr(TrustedImm32(4), StackPointerRegister);
458 move(Arg0Reg, CppStackFrameRegister);
459 move(Arg1Reg, EngineRegister);
462 void generatePlatformFunctionExit(
bool tailCall =
false)
465 move(AccumulatorRegisterValue, ReturnValueRegisterValue);
466 move(AccumulatorRegisterTag, ReturnValueRegisterTag);
468 addPtr(TrustedImm32(4), StackPointerRegister);
470 pop(CppStackFrameRegister);
471 pop(JSStackFrameRegister);
472 pop(addressTempRegister);
473 pop(AccumulatorRegisterTag);
474 pop(AccumulatorRegisterValue);
476 pop(FramePointerRegister);
477 pop(JSC::ARMRegisters::lr);
482 void callAbsolute(
const void *funcPtr)
484 move(TrustedImmPtr(funcPtr), dataTempRegister);
485 call(dataTempRegister);
488 void jumpAbsolute(
const void *funcPtr)
490 move(TrustedImmPtr(funcPtr), dataTempRegister);
491 jump(dataTempRegister);
494 void pushAligned(RegisterID reg)
496 subPtr(TrustedImm32(PointerSize), StackPointerRegister);
500 void popAligned(RegisterID reg)
503 addPtr(TrustedImm32(PointerSize), StackPointerRegister);
507typedef PlatformAssembler_ARM32 PlatformAssemblerBase;
510class PlatformAssemblerCommon :
public JIT::PlatformAssemblerBase
513 PlatformAssemblerCommon(
const Value *constantTable)
514 : constantTable(constantTable)
517 virtual ~PlatformAssemblerCommon();
519 Address exceptionHandlerAddress()
const
521 return Address(FramePointerRegister, -1 * PointerSize);
524 Address contextAddress()
const
526 return Address(JSStackFrameRegister, offsetof(CallData, context));
529 RegisterID registerForArg(
int arg)
const
532 Q_ASSERT(arg < ArgInRegCount);
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;
548 Address loadFunctionPtr(RegisterID target)
550 Address addr(CppStackFrameRegister, offsetof(JSTypesStackFrame, v4Function));
551 loadPtr(addr, target);
552 return Address(target);
555 Address loadCompilationUnitPtr(RegisterID target)
557 Address addr = loadFunctionPtr(target);
558 addr.offset = offsetof(QV4::FunctionData, compilationUnit);
559 loadPtr(addr, target);
560 return Address(target);
563 Address loadConstAddress(
int constIndex, RegisterID baseReg = ScratchRegister)
565 Address addr = loadCompilationUnitPtr(baseReg);
566 addr.offset = offsetof(QV4::CompilationUnitRuntimeData, constants);
567 loadPtr(addr, baseReg);
568 addr.offset = constIndex *
int(
sizeof(QV4::Value));
572 Address loadStringAddress(
int stringId)
574 Address addr = loadCompilationUnitPtr(ScratchRegister);
575 addr.offset = offsetof(QV4::CompilationUnitRuntimeData, runtimeStrings);
576 loadPtr(addr, ScratchRegister);
577 return Address(ScratchRegister, stringId * PointerSize);
580 void passAsArg(RegisterID src,
int arg)
582 move(src, registerForArg(arg));
585 void generateCatchTrampoline(std::function<
void()> loadUndefined)
587 for (Jump j : catchyJumps)
594 loadPtr(exceptionHandlerAddress(), ScratchRegister);
595 Jump exitFunction = branchPtr(Equal, ScratchRegister, TrustedImmPtr(0));
596 jump(ScratchRegister);
597 exitFunction.link(
this);
599 if (functionExit.isSet())
602 generateFunctionExit();
605 void checkException()
611 Address(EngineRegister, offsetof(EngineBase, hasException)),
615 void addCatchyJump(Jump j)
618 catchyJumps.push_back(j);
621 void generateFunctionEntry()
623 generatePlatformFunctionEntry();
624 loadPtr(Address(CppStackFrameRegister, offsetof(JSTypesStackFrame, jsFrame)),
625 JSStackFrameRegister);
626 allocateStackSpace();
629 virtual void allocateStackSpace() {}
631 void generateFunctionExit()
633 if (functionExit.isSet()) {
638 functionExit = label();
640 generatePlatformFunctionExit();
643 virtual void freeStackSpace() {}
645 void addLabelForOffset(
int offset)
647 if (!labelForOffset.contains(offset))
648 labelForOffset.insert(offset, label());
651 void addJumpToOffset(
const Jump &jump,
int offset)
653 jumpsToLink.push_back({ jump, offset });
656 void addEHTarget(
const DataLabelPtr &label,
int offset)
658 ehTargets.push_back({ label, offset });
661 void link(Function *function,
const char *jitKind);
663 Value constant(
int idx)
const
664 {
return constantTable[idx]; }
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);
686 void passAccumulatorAsArg_internal(
int arg,
bool doPush);
687 static Address argStackAddress(
int arg);
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;
701 enum { NoCall = -1 };
702 int remainingArgcForCall = NoCall;
704 int argcOnStackForCall = 0;
QV4::ExecutionEngine * v4engine() const
QV4::ReturnedValue operator[](int idx) const
void setReturnValue(QV4::ReturnedValue rv)
~ExecutionEngineCallDepthRecorder()
ExecutionEngineCallDepthRecorder(ExecutionEngine *e)