10#include <private/qv4function_p.h>
11#include <private/qv4runtime_p.h>
12#include <private/qv4stackframe_p.h>
14#include <wtf/Vector.h>
15#include <assembler/MacroAssembler.h>
16#include <assembler/MacroAssemblerCodeRef.h>
17#include <assembler/LinkBuffer.h>
20#undef ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES
28#define ASM_GENERATE_RUNTIME_CALL(function, destination) \
29 pasm()->GENERATE_RUNTIME_CALL(function, destination)
30#define callHelper(x) \
31 PlatformAssemblerCommon::callRuntimeUnchecked(reinterpret_cast<void *>(&x), #x)
45#if QT_POINTER_SIZE == 8 || defined(ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES)
46class PlatformAssembler64 :
public PlatformAssemblerCommon
49 PlatformAssembler64(
const Value *constantTable)
50 : PlatformAssemblerCommon(constantTable)
53 void callRuntime(
const void *funcPtr, CallResultDestination dest)
55 PlatformAssemblerCommon::callRuntime(funcPtr);
56 if (dest == CallResultDestination::InAccumulator)
57 saveReturnValueInAccumulator();
58 else if (AccumulatorRegister == ReturnValueRegister)
62 void saveReturnValueInAccumulator()
64 move(ReturnValueRegister, AccumulatorRegister);
67 void loadUndefined(RegisterID dest = AccumulatorRegister)
69 move(TrustedImm64(0), dest);
72 void copyConst(
int constIndex, Address dest)
75 if (
constant(constIndex).isUndefined()) {
76 loadUndefined(ScratchRegister);
78 load64(loadConstAddress(constIndex, ScratchRegister), ScratchRegister);
80 store64(ScratchRegister, dest);
83 void copyReg(Address
src, Address
dst)
85 load64(
src, ScratchRegister);
86 store64(ScratchRegister,
dst);
89 void loadPointerFromValue(Address
addr, RegisterID dest = AccumulatorRegister)
94 void loadAccumulator(Address
addr)
96 load64(
addr, AccumulatorRegister);
99 void storeAccumulator(Address
addr)
101 store64(AccumulatorRegister,
addr);
104 void moveReg(Address sourceRegAddress, Address destRegAddress)
106 load64(sourceRegAddress, ScratchRegister);
107 store64(ScratchRegister, destRegAddress);
110 void loadString(
int stringId)
112 loadAccumulator(loadStringAddress(stringId));
115 void loadValue(ReturnedValue
value)
117 move(TrustedImm64(
value), AccumulatorRegister);
120 void storeHeapObject(RegisterID
source, Address
addr)
125 void generateCatchTrampoline()
127 PlatformAssemblerCommon::generateCatchTrampoline([
this](){loadUndefined();});
130 void jumpNotUndefined(
int offset)
132 auto jump = branch64(NotEqual, AccumulatorRegister, TrustedImm64(0));
138 return branch64(Equal, AccumulatorRegister, TrustedImm64(Value::emptyValue().asReturnedValue()));
143 return branch64(NotEqual, AccumulatorRegister, TrustedImm64(Value::emptyValue().asReturnedValue()));
146 void toBoolean(std::function<
void(RegisterID)> continuation)
148 urshift64(AccumulatorRegister, TrustedImm32(Value::IsIntegerConvertible_Shift), ScratchRegister);
149 auto needsConversion = branch32(
150 NotEqual, TrustedImm32(Value::IsIntegerConvertible_Value), ScratchRegister);
152 continuation(AccumulatorRegister);
156 needsConversion.link(
this);
157 push(AccumulatorRegister);
158 move(AccumulatorRegister, registerForArg(0));
159 callHelper(Value::toBooleanImpl);
160 and32(TrustedImm32(1), ReturnValueRegister, ScratchRegister);
161 pop(AccumulatorRegister);
162 continuation(ScratchRegister);
169 move(TrustedImm64(Value::NumberMask), ScratchRegister);
170 and64(AccumulatorRegister, ScratchRegister);
171 move(TrustedImm64(Value::NumberDiscriminator), ScratchRegister2);
172 auto isNumber = branch64(GreaterThanOrEqual, ScratchRegister, ScratchRegister2);
174 move(AccumulatorRegister, registerForArg(0));
175 callHelper(toNumberHelper);
176 saveReturnValueInAccumulator();
182 void toInt32LhsAcc(Address lhs, RegisterID lhsTarget)
184 load64(lhs, lhsTarget);
185 urshift64(lhsTarget, TrustedImm32(Value::QuickType_Shift), ScratchRegister2);
186 auto lhsIsInt = branch32(Equal, TrustedImm32(Value::QT_Int), ScratchRegister2);
188 const Address accumulatorStackAddress(JSStackFrameRegister,
189 offsetof(CallData, accumulator));
190 storeAccumulator(accumulatorStackAddress);
191 move(lhsTarget, registerForArg(0));
192 callHelper(toInt32Helper);
193 move(ReturnValueRegister, lhsTarget);
194 loadAccumulator(accumulatorStackAddress);
197 urshift64(AccumulatorRegister, TrustedImm32(Value::QuickType_Shift), ScratchRegister2);
198 auto isInt = branch32(Equal, TrustedImm32(Value::QT_Int), ScratchRegister2);
200 pushAligned(lhsTarget);
201 move(AccumulatorRegister, registerForArg(0));
202 callHelper(toInt32Helper);
203 saveReturnValueInAccumulator();
204 popAligned(lhsTarget);
211 urshift64(AccumulatorRegister, TrustedImm32(Value::QuickType_Shift), ScratchRegister2);
212 auto isInt = branch32(Equal, TrustedImm32(Value::QT_Int), ScratchRegister2);
214 move(AccumulatorRegister, registerForArg(0));
215 callHelper(toInt32Helper);
216 saveReturnValueInAccumulator();
221 void regToInt32(Address srcReg, RegisterID targetReg)
223 load64(srcReg, targetReg);
224 urshift64(targetReg, TrustedImm32(Value::QuickType_Shift), ScratchRegister2);
225 auto isInt = branch32(Equal, TrustedImm32(Value::QT_Int), ScratchRegister2);
227 pushAligned(AccumulatorRegister);
228 move(targetReg, registerForArg(0));
229 callHelper(toInt32Helper);
230 move(ReturnValueRegister, targetReg);
231 popAligned(AccumulatorRegister);
236 void isNullOrUndefined()
238 move(AccumulatorRegister, ScratchRegister);
239 compare64(Equal, ScratchRegister, TrustedImm32(0), AccumulatorRegister);
240 Jump isUndef = branch32(NotEqual, TrustedImm32(0), AccumulatorRegister);
243 rshift64(TrustedImm32(32), ScratchRegister);
245 AccumulatorRegister);
252 urshift64(AccumulatorRegister, TrustedImm32(Value::IsIntegerOrBool_Shift), ScratchRegister);
253 return branch32(Equal, TrustedImm32(Value::IsIntegerOrBool_Value), ScratchRegister);
256 void jumpStrictEqualStackSlotInt(
int lhs,
int rhs,
int offset)
258 Address lhsAddr(JSStackFrameRegister, lhs *
int(
sizeof(Value)));
259 load64(lhsAddr, ScratchRegister);
260 Jump isUndef = branch64(Equal, ScratchRegister, TrustedImm64(0));
261 Jump
equal = branch32(Equal, TrustedImm32(rhs), ScratchRegister);
266 void jumpStrictNotEqualStackSlotInt(
int lhs,
int rhs,
int offset)
268 Address lhsAddr(JSStackFrameRegister, lhs *
int(
sizeof(Value)));
269 load64(lhsAddr, ScratchRegister);
270 Jump isUndef = branch64(Equal, ScratchRegister, TrustedImm64(0));
271 addJumpToOffset(isUndef,
offset);
272 Jump notEqual = branch32(NotEqual, TrustedImm32(rhs), ScratchRegister);
273 addJumpToOffset(notEqual,
offset);
278 if (sourceReg == NoRegister)
279 or64(TrustedImm64(int64_t(
tag) << 32), AccumulatorRegister);
281 or64(TrustedImm64(int64_t(
tag) << 32), sourceReg, AccumulatorRegister);
284 void encodeDoubleIntoAccumulator(FPRegisterID
src)
286 moveDoubleTo64(
src, AccumulatorRegister);
287 move(TrustedImm64(Value::EncodeMask), ScratchRegister);
288 xor64(ScratchRegister, AccumulatorRegister);
291 void pushValueAligned(ReturnedValue
v)
294 pushAligned(AccumulatorRegister);
297 void popValueAligned()
299 addPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
302 Jump binopBothIntPath(Address lhsAddr, std::function<Jump(
void)> fastPath)
304 urshift64(AccumulatorRegister, TrustedImm32(32), ScratchRegister);
305 Jump accNotInt = branch32(NotEqual, TrustedImm32(
int(IntegerTag)), ScratchRegister);
306 load64(lhsAddr, ScratchRegister);
307 urshift64(ScratchRegister, TrustedImm32(32), ScratchRegister2);
308 Jump lhsNotInt = branch32(NotEqual, TrustedImm32(
int(IntegerTag)), ScratchRegister2);
311 Jump failure = fastPath();
317 accNotInt.link(
this);
318 lhsNotInt.link(
this);
323 Jump unopIntPath(std::function<Jump(
void)> fastPath)
325 urshift64(AccumulatorRegister, TrustedImm32(Value::IsIntegerConvertible_Shift), ScratchRegister);
326 Jump accNotIntConvertible = branch32(
327 NotEqual, TrustedImm32(Value::IsIntegerConvertible_Value), ScratchRegister);
330 Jump failure = fastPath();
336 accNotIntConvertible.link(
this);
341 void callWithAccumulatorByValueAsFirstArgument(std::function<
void()> doCall)
343 passAsArg(AccumulatorRegister, 0);
348typedef PlatformAssembler64 PlatformAssembler;
351#if QT_POINTER_SIZE == 4 || defined(ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES)
352class PlatformAssembler32 :
public PlatformAssemblerCommon
355 PlatformAssembler32(
const Value *constantTable)
356 : PlatformAssemblerCommon(constantTable)
359 void callRuntime(
const void *funcPtr, CallResultDestination dest)
361 PlatformAssemblerCommon::callRuntime(funcPtr);
362 if (dest == CallResultDestination::InAccumulator)
363 saveReturnValueInAccumulator();
364 else if (AccumulatorRegisterValue == ReturnValueRegisterValue)
368 void saveReturnValueInAccumulator()
370 move(ReturnValueRegisterValue, AccumulatorRegisterValue);
371 move(ReturnValueRegisterTag, AccumulatorRegisterTag);
376 move(TrustedImm32(0), AccumulatorRegisterValue);
377 move(TrustedImm32(0), AccumulatorRegisterTag);
380 void copyConst(
int constIndex, Address destRegAddr)
383 if (
constant(constIndex).isUndefined()) {
384 move(TrustedImm32(0), ScratchRegister);
385 store32(ScratchRegister, destRegAddr);
386 destRegAddr.offset += 4;
387 store32(ScratchRegister, destRegAddr);
389 Address
src = loadConstAddress(constIndex);
390 loadDouble(
src, FPScratchRegister);
391 storeDouble(FPScratchRegister, destRegAddr);
395 void copyReg(Address
src, Address dest)
397 loadDouble(
src, FPScratchRegister);
398 storeDouble(FPScratchRegister, dest);
401 void loadPointerFromValue(Address
addr, RegisterID dest = AccumulatorRegisterValue)
406 void loadAccumulator(Address
src)
408 load32(
src, AccumulatorRegisterValue);
410 load32(
src, AccumulatorRegisterTag);
413 void storeAccumulator(Address
addr)
415 store32(AccumulatorRegisterValue,
addr);
417 store32(AccumulatorRegisterTag,
addr);
420 void moveReg(Address sourceRegAddress, Address destRegAddress)
422 load32(sourceRegAddress, ScratchRegister);
423 store32(ScratchRegister, destRegAddress);
424 sourceRegAddress.offset += 4;
425 destRegAddress.offset += 4;
426 load32(sourceRegAddress, ScratchRegister);
427 store32(ScratchRegister, destRegAddress);
430 void loadString(
int stringId)
432 load32(loadStringAddress(stringId), AccumulatorRegisterValue);
433 move(TrustedImm32(0), AccumulatorRegisterTag);
436 void loadValue(ReturnedValue
value)
438 move(TrustedImm32(Value::fromReturnedValue(
value).
value()), AccumulatorRegisterValue);
439 move(TrustedImm32(Value::fromReturnedValue(
value).
tag()), AccumulatorRegisterTag);
442 void storeHeapObject(RegisterID
source, Address
addr)
446 store32(TrustedImm32(0),
addr);
450 void generateCatchTrampoline()
452 PlatformAssemblerCommon::generateCatchTrampoline([
this](){loadUndefined();});
457 and32(TrustedImm32(Value::NumberMask >> Value::Tag_Shift),
458 AccumulatorRegisterTag, ScratchRegister);
460 GreaterThanOrEqual, ScratchRegister,
461 TrustedImm32(Value::NumberDiscriminator >> Value::Tag_Shift));
464 if (ArgInRegCount < 2) {
465 subPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
466 push(AccumulatorRegisterTag);
467 push(AccumulatorRegisterValue);
469 move(AccumulatorRegisterValue, registerForArg(0));
470 move(AccumulatorRegisterTag, registerForArg(1));
472 callHelper(toNumberHelper);
473 saveReturnValueInAccumulator();
474 if (ArgInRegCount < 2)
475 addPtr(TrustedImm32(4 * PointerSize), StackPointerRegister);
481 void toInt32LhsAcc(Address lhs, RegisterID lhsTarget)
483 bool accumulatorNeedsSaving = AccumulatorRegisterValue == ReturnValueRegisterValue
484 || AccumulatorRegisterTag == ReturnValueRegisterTag;
486 load32(lhs, lhsTarget);
488 auto lhsIsNotInt = branch32(NotEqual, TrustedImm32(
int(IntegerTag)), lhsTarget);
489 load32(lhs, lhsTarget);
490 auto lhsIsInt =
jump();
492 lhsIsNotInt.link(
this);
495 const Address accumulatorStackAddress(JSStackFrameRegister,
496 offsetof(CallData, accumulator));
497 storeAccumulator(accumulatorStackAddress);
499 if (ArgInRegCount < 2) {
500 subPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
502 load32(lhs, lhsTarget);
505 move(lhsTarget, registerForArg(1));
506 load32(lhs, registerForArg(0));
508 callHelper(toInt32Helper);
509 move(ReturnValueRegisterValue, lhsTarget);
510 if (ArgInRegCount < 2)
511 addPtr(TrustedImm32(4 * PointerSize), StackPointerRegister);
513 if (accumulatorNeedsSaving)
514 loadAccumulator(accumulatorStackAddress);
518 auto rhsIsInt = branch32(Equal, TrustedImm32(
int(IntegerTag)), AccumulatorRegisterTag);
520 pushAligned(lhsTarget);
521 if (ArgInRegCount < 2) {
522 subPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
523 push(AccumulatorRegisterTag);
524 push(AccumulatorRegisterValue);
526 move(AccumulatorRegisterValue, registerForArg(0));
527 move(AccumulatorRegisterTag, registerForArg(1));
529 callHelper(toInt32Helper);
530 saveReturnValueInAccumulator();
531 if (ArgInRegCount < 2)
532 addPtr(TrustedImm32(4 * PointerSize), StackPointerRegister);
533 popAligned(lhsTarget);
540 urshift32(AccumulatorRegisterTag, TrustedImm32(Value::QuickType_Shift - 32), ScratchRegister);
541 auto isInt = branch32(Equal, TrustedImm32(Value::QT_Int), ScratchRegister);
543 if (ArgInRegCount < 2) {
544 subPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
545 push(AccumulatorRegisterTag);
546 push(AccumulatorRegisterValue);
548 move(AccumulatorRegisterValue, registerForArg(0));
549 move(AccumulatorRegisterTag, registerForArg(1));
551 callHelper(toInt32Helper);
552 saveReturnValueInAccumulator();
553 if (ArgInRegCount < 2)
554 addPtr(TrustedImm32(4 * PointerSize), StackPointerRegister);
559 void regToInt32(Address srcReg, RegisterID targetReg)
561 bool accumulatorNeedsSaving = AccumulatorRegisterValue == ReturnValueRegisterValue
562 || AccumulatorRegisterTag == ReturnValueRegisterTag;
563 if (accumulatorNeedsSaving) {
564 push(AccumulatorRegisterTag);
565 push(AccumulatorRegisterValue);
567 if (ArgInRegCount < 2) {
568 if (!accumulatorNeedsSaving)
569 subPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
571 load32(srcReg, targetReg);
574 load32(srcReg, targetReg);
577 if (accumulatorNeedsSaving)
578 subPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
579 load32(srcReg, registerForArg(0));
581 load32(srcReg, registerForArg(1));
583 callHelper(toInt32Helper);
584 move(ReturnValueRegisterValue, targetReg);
585 if (accumulatorNeedsSaving) {
586 addPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
587 pop(AccumulatorRegisterValue);
588 pop(AccumulatorRegisterTag);
589 }
else if (ArgInRegCount < 2) {
590 addPtr(TrustedImm32(4 * PointerSize), StackPointerRegister);
594 void isNullOrUndefined()
596 Jump notUndefOrPtr = branch32(NotEqual, TrustedImm32(0), AccumulatorRegisterTag);
597 compare32(Equal, AccumulatorRegisterValue, TrustedImm32(0), AccumulatorRegisterValue);
601 notUndefOrPtr.link(
this);
603 AccumulatorRegisterValue);
610 urshift32(AccumulatorRegisterTag, TrustedImm32(Value::IsIntegerOrBool_Shift - 32), ScratchRegister);
611 return branch32(Equal, TrustedImm32(Value::IsIntegerOrBool_Value), ScratchRegister);
614 void pushValue(ReturnedValue
v)
616 push(TrustedImm32(
v >> 32));
617 push(TrustedImm32(
v));
620 void jumpNotUndefined(
int offset)
622 move(AccumulatorRegisterTag, ScratchRegister);
623 or32(AccumulatorRegisterValue, ScratchRegister);
624 auto jump = branch32(NotEqual, ScratchRegister, TrustedImm32(0));
630 return branch32(Equal, AccumulatorRegisterTag, TrustedImm32(Value::emptyValue().asReturnedValue() >> 32));
635 return branch32(NotEqual, AccumulatorRegisterTag, TrustedImm32(Value::emptyValue().asReturnedValue() >> 32));
638 void toBoolean(std::function<
void(RegisterID)> continuation)
640 urshift32(AccumulatorRegisterTag, TrustedImm32(Value::IsIntegerConvertible_Shift - 32),
642 auto needsConversion = branch32(
643 NotEqual, TrustedImm32(Value::IsIntegerConvertible_Value), ScratchRegister);
644 continuation(AccumulatorRegisterValue);
648 needsConversion.link(
this);
650 bool accumulatorNeedsSaving = AccumulatorRegisterValue == ReturnValueRegisterValue
651 || AccumulatorRegisterTag == ReturnValueRegisterTag;
652 if (accumulatorNeedsSaving) {
653 push(AccumulatorRegisterTag);
654 push(AccumulatorRegisterValue);
657 if (ArgInRegCount < 2) {
658 if (!accumulatorNeedsSaving)
659 subPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
660 push(AccumulatorRegisterTag);
661 push(AccumulatorRegisterValue);
663 if (accumulatorNeedsSaving)
664 subPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
665 move(AccumulatorRegisterValue, registerForArg(0));
666 move(AccumulatorRegisterTag, registerForArg(1));
668 callHelper(Value::toBooleanImpl);
669 and32(TrustedImm32(1), ReturnValueRegisterValue, ScratchRegister);
670 if (accumulatorNeedsSaving) {
671 addPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
672 pop(AccumulatorRegisterValue);
673 pop(AccumulatorRegisterTag);
674 }
else if (ArgInRegCount < 2) {
675 addPtr(TrustedImm32(4 * PointerSize), StackPointerRegister);
677 continuation(ScratchRegister);
682 void jumpStrictEqualStackSlotInt(
int lhs,
int rhs,
int offset)
684 Address lhsAddr(JSStackFrameRegister, lhs *
int(
sizeof(Value)));
685 load32(lhsAddr, ScratchRegister);
686 Jump notEqInt = branch32(NotEqual, ScratchRegister, TrustedImm32(rhs));
687 Jump notEqUndefVal = branch32(NotEqual, ScratchRegister, TrustedImm32(0));
688 addJumpToOffset(notEqUndefVal,
offset);
690 load32(lhsAddr, ScratchRegister);
691 Jump notEqUndefTag = branch32(NotEqual, ScratchRegister, TrustedImm32(0));
692 addJumpToOffset(notEqUndefTag,
offset);
696 void jumpStrictNotEqualStackSlotInt(
int lhs,
int rhs,
int offset)
698 Address lhsAddr(JSStackFrameRegister, lhs *
int(
sizeof(Value)));
699 load32(lhsAddr, ScratchRegister);
700 Jump notEqual = branch32(NotEqual, TrustedImm32(rhs), ScratchRegister);
701 addJumpToOffset(notEqual,
offset);
702 Jump notUndefValue = branch32(NotEqual, TrustedImm32(0), ScratchRegister);
704 load32(lhsAddr, ScratchRegister);
705 Jump equalUndef = branch32(Equal, TrustedImm32(0), ScratchRegister);
706 addJumpToOffset(equalUndef,
offset);
707 notUndefValue.link(
this);
712 if (sourceReg != NoRegister)
713 move(sourceReg, AccumulatorRegisterValue);
714 move(TrustedImm32(
int(
tag)), AccumulatorRegisterTag);
717 void encodeDoubleIntoAccumulator(FPRegisterID
src)
719 moveDoubleToInts(
src, AccumulatorRegisterValue, AccumulatorRegisterTag);
720 xor32(TrustedImm32(Value::EncodeMask >> 32), AccumulatorRegisterTag);
723 void pushValueAligned(ReturnedValue
v)
728 void popValueAligned()
733 Jump binopBothIntPath(Address lhsAddr, std::function<Jump(
void)> fastPath)
735 Jump accNotInt = branch32(NotEqual, TrustedImm32(
int(IntegerTag)), AccumulatorRegisterTag);
736 Address lhsAddrTag = lhsAddr; lhsAddrTag.offset += Value::tagOffset();
737 load32(lhsAddrTag, ScratchRegister);
738 Jump lhsNotInt = branch32(NotEqual, TrustedImm32(
int(IntegerTag)), ScratchRegister);
741 Address lhsAddrValue = lhsAddr; lhsAddrValue.offset += Value::valueOffset();
742 load32(lhsAddrValue, ScratchRegister);
743 Jump failure = fastPath();
749 accNotInt.link(
this);
750 lhsNotInt.link(
this);
755 Jump unopIntPath(std::function<Jump(
void)> fastPath)
757 Jump accNotInt = branch32(NotEqual, TrustedImm32(
int(IntegerTag)), AccumulatorRegisterTag);
760 Jump failure = fastPath();
766 accNotInt.link(
this);
771 void callWithAccumulatorByValueAsFirstArgument(std::function<
void()> doCall)
773 if (ArgInRegCount < 2) {
774 subPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
775 push(AccumulatorRegisterTag);
776 push(AccumulatorRegisterValue);
778 move(AccumulatorRegisterValue, registerForArg(0));
779 move(AccumulatorRegisterTag, registerForArg(1));
782 if (ArgInRegCount < 2)
783 addPtr(TrustedImm32(4 * PointerSize), StackPointerRegister);
787typedef PlatformAssembler32 PlatformAssembler;
790#define pasm() reinterpret_cast<PlatformAssembler *>(this->d)
792typedef PlatformAssembler::TrustedImmPtr TrustedImmPtr;
793typedef PlatformAssembler::TrustedImm32 TrustedImm32;
794typedef PlatformAssembler::TrustedImm64 TrustedImm64;
795typedef PlatformAssembler::Address Address;
796typedef PlatformAssembler::RegisterID RegisterID;
797typedef PlatformAssembler::FPRegisterID FPRegisterID;
799static Address regAddr(
int reg)
801 return Address(PlatformAssembler::JSStackFrameRegister, reg *
int(
sizeof(
QV4::Value)));
804BaselineAssembler::BaselineAssembler(
const Value *constantTable)
805 :
d(new PlatformAssembler(constantTable))
809BaselineAssembler::~BaselineAssembler()
814void BaselineAssembler::generatePrologue()
816 pasm()->generateFunctionEntry();
819void BaselineAssembler::generateEpilogue()
821 pasm()->generateCatchTrampoline();
824void BaselineAssembler::link(
Function *function)
826 pasm()->link(function,
"BaselineJIT");
829void BaselineAssembler::addLabel(
int offset)
831 pasm()->addLabelForOffset(
offset);
834void BaselineAssembler::loadConst(
int constIndex)
837 if (pasm()->
constant(constIndex).isUndefined()) {
838 pasm()->loadUndefined();
840 pasm()->loadAccumulator(pasm()->loadConstAddress(constIndex));
844void BaselineAssembler::copyConst(
int constIndex,
int destReg)
846 pasm()->copyConst(constIndex, regAddr(destReg));
849void BaselineAssembler::loadReg(
int reg)
851 pasm()->loadAccumulator(regAddr(reg));
854void JIT::BaselineAssembler::moveReg(
int sourceReg,
int destReg)
856 pasm()->moveReg(regAddr(sourceReg), regAddr(destReg));
859void BaselineAssembler::storeReg(
int reg)
861 pasm()->storeAccumulator(regAddr(reg));
864void BaselineAssembler::loadLocal(
int index,
int level)
866 Heap::CallContext
ctx;
868 pasm()->loadPointerFromValue(regAddr(CallData::Context), PlatformAssembler::ScratchRegister);
870 pasm()->loadPtr(Address(PlatformAssembler::ScratchRegister,
ctx.outer.offset), PlatformAssembler::ScratchRegister);
873 pasm()->loadAccumulator(Address(PlatformAssembler::ScratchRegister,
ctx.locals.offset + offsetof(ValueArray<0>,
values) +
sizeof(Value)*
index));
876void BaselineAssembler::storeLocal(
int index,
int level)
878 Heap::CallContext
ctx;
880 pasm()->loadPtr(regAddr(CallData::Context), PlatformAssembler::ScratchRegister);
882 pasm()->loadPtr(Address(PlatformAssembler::ScratchRegister,
ctx.outer.offset), PlatformAssembler::ScratchRegister);
885 pasm()->storeAccumulator(Address(PlatformAssembler::ScratchRegister,
ctx.locals.offset + offsetof(ValueArray<0>,
values) +
sizeof(Value)*
index));
888void BaselineAssembler::loadString(
int stringId)
890 pasm()->loadString(stringId);
893void BaselineAssembler::loadValue(ReturnedValue
value)
895 pasm()->loadValue(
value);
898void BaselineAssembler::storeHeapObject(
int reg)
900 pasm()->storeHeapObject(PlatformAssembler::ReturnValueRegisterValue, regAddr(reg));
903void BaselineAssembler::loadImport(
int index)
905 Address
addr = pasm()->loadCompilationUnitPtr(PlatformAssembler::ScratchRegister);
907 pasm()->loadPtr(
addr, PlatformAssembler::ScratchRegister);
909 pasm()->loadPtr(
addr, PlatformAssembler::ScratchRegister);
910 pasm()->loadAccumulator(Address(PlatformAssembler::ScratchRegister));
913void BaselineAssembler::toNumber()
918void BaselineAssembler::uminus()
920 saveAccumulatorInFrame();
921 pasm()->prepareCallWithArgCount(1);
922 pasm()->passAccumulatorAsArg(0);
923 ASM_GENERATE_RUNTIME_CALL(UMinus, CallResultDestination::InAccumulator);
927void BaselineAssembler::ucompl()
930 pasm()->xor32(TrustedImm32(-1), PlatformAssembler::AccumulatorRegisterValue);
931 pasm()->setAccumulatorTag(IntegerTag);
940 d =
v.toNumberImpl();
941 return Encode(
d + 1.);
944void BaselineAssembler::inc()
946 auto done = pasm()->unopIntPath([
this](){
947 auto overflowed = pasm()->branchAdd32(PlatformAssembler::Overflow,
948 PlatformAssembler::AccumulatorRegisterValue,
950 PlatformAssembler::ScratchRegister);
951 pasm()->setAccumulatorTag(IntegerTag, PlatformAssembler::ScratchRegister);
956 pasm()->callWithAccumulatorByValueAsFirstArgument([
this]() {
957 pasm()->callHelper(incHelper);
958 pasm()->saveReturnValueInAccumulator();
972 d =
v.toNumberImpl();
973 return Encode(
d - 1.);
976void BaselineAssembler::dec()
978 auto done = pasm()->unopIntPath([
this](){
979 auto overflowed = pasm()->branchSub32(PlatformAssembler::Overflow,
980 PlatformAssembler::AccumulatorRegisterValue,
982 PlatformAssembler::ScratchRegister);
983 pasm()->setAccumulatorTag(IntegerTag, PlatformAssembler::ScratchRegister);
988 pasm()->callWithAccumulatorByValueAsFirstArgument([
this]() {
989 pasm()->callHelper(decHelper);
990 pasm()->saveReturnValueInAccumulator();
998void BaselineAssembler::unot()
1000 pasm()->toBoolean([
this](PlatformAssembler::RegisterID resultReg){
1001 pasm()->compare32(PlatformAssembler::Equal, resultReg,
1002 TrustedImm32(0), PlatformAssembler::AccumulatorRegisterValue);
1007void BaselineAssembler::add(
int lhs)
1009 auto done = pasm()->binopBothIntPath(regAddr(lhs), [
this](){
1010 auto overflowed = pasm()->branchAdd32(PlatformAssembler::Overflow,
1011 PlatformAssembler::AccumulatorRegisterValue,
1012 PlatformAssembler::ScratchRegister);
1013 pasm()->setAccumulatorTag(IntegerTag,
1014 PlatformAssembler::ScratchRegister);
1019 saveAccumulatorInFrame();
1020 pasm()->prepareCallWithArgCount(3);
1021 pasm()->passAccumulatorAsArg(2);
1022 pasm()->passJSSlotAsArg(lhs, 1);
1023 pasm()->passEngineAsArg(0);
1024 ASM_GENERATE_RUNTIME_CALL(Add, CallResultDestination::InAccumulator);
1031void BaselineAssembler::bitAnd(
int lhs)
1033 PlatformAssembler::Address lhsAddr = regAddr(lhs);
1034 pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister);
1035 pasm()->and32(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
1036 pasm()->setAccumulatorTag(IntegerTag);
1039void BaselineAssembler::bitOr(
int lhs)
1041 PlatformAssembler::Address lhsAddr = regAddr(lhs);
1042 pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister);
1043 pasm()->or32(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
1044 pasm()->setAccumulatorTag(IntegerTag);
1047void BaselineAssembler::bitXor(
int lhs)
1049 PlatformAssembler::Address lhsAddr = regAddr(lhs);
1050 pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister);
1051 pasm()->xor32(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
1052 pasm()->setAccumulatorTag(IntegerTag);
1055void BaselineAssembler::ushr(
int lhs)
1057 PlatformAssembler::Address lhsAddr = regAddr(lhs);
1058 pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister);
1059 pasm()->and32(TrustedImm32(0x1f), PlatformAssembler::AccumulatorRegisterValue);
1060 pasm()->urshift32(PlatformAssembler::AccumulatorRegisterValue, PlatformAssembler::ScratchRegister);
1061 pasm()->move(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
1062 auto doubleEncode = pasm()->branch32(PlatformAssembler::LessThan,
1063 PlatformAssembler::AccumulatorRegisterValue,
1065 pasm()->setAccumulatorTag(IntegerTag);
1066 auto done = pasm()->jump();
1068 doubleEncode.link(pasm());
1069 pasm()->convertUInt32ToDouble(PlatformAssembler::AccumulatorRegisterValue,
1070 PlatformAssembler::FPScratchRegister,
1071 PlatformAssembler::ScratchRegister);
1072 pasm()->encodeDoubleIntoAccumulator(PlatformAssembler::FPScratchRegister);
1076void BaselineAssembler::shr(
int lhs)
1078 PlatformAssembler::Address lhsAddr = regAddr(lhs);
1079 pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister);
1080 pasm()->and32(TrustedImm32(0x1f), PlatformAssembler::AccumulatorRegisterValue);
1081 pasm()->rshift32(PlatformAssembler::AccumulatorRegisterValue, PlatformAssembler::ScratchRegister);
1082 pasm()->move(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
1083 pasm()->setAccumulatorTag(IntegerTag);
1086void BaselineAssembler::shl(
int lhs)
1088 PlatformAssembler::Address lhsAddr = regAddr(lhs);
1089 pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister);
1090 pasm()->and32(TrustedImm32(0x1f), PlatformAssembler::AccumulatorRegisterValue);
1091 pasm()->lshift32(PlatformAssembler::AccumulatorRegisterValue, PlatformAssembler::ScratchRegister);
1092 pasm()->move(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
1093 pasm()->setAccumulatorTag(IntegerTag);
1096void BaselineAssembler::bitAndConst(
int rhs)
1099 pasm()->and32(TrustedImm32(rhs), PlatformAssembler::AccumulatorRegisterValue);
1100 pasm()->setAccumulatorTag(IntegerTag);
1103void BaselineAssembler::bitOrConst(
int rhs)
1106 pasm()->or32(TrustedImm32(rhs), PlatformAssembler::AccumulatorRegisterValue);
1107 pasm()->setAccumulatorTag(IntegerTag);
1110void BaselineAssembler::bitXorConst(
int rhs)
1113 pasm()->xor32(TrustedImm32(rhs), PlatformAssembler::AccumulatorRegisterValue);
1114 pasm()->setAccumulatorTag(IntegerTag);
1117void BaselineAssembler::ushrConst(
int rhs)
1123 pasm()->urshift32(TrustedImm32(rhs), PlatformAssembler::AccumulatorRegisterValue);
1124 pasm()->setAccumulatorTag(IntegerTag);
1127 auto doubleEncode = pasm()->branch32(PlatformAssembler::LessThan,
1128 PlatformAssembler::AccumulatorRegisterValue,
1130 pasm()->setAccumulatorTag(IntegerTag);
1131 auto done = pasm()->jump();
1133 doubleEncode.link(pasm());
1134 pasm()->convertUInt32ToDouble(PlatformAssembler::AccumulatorRegisterValue,
1135 PlatformAssembler::FPScratchRegister,
1136 PlatformAssembler::ScratchRegister);
1137 pasm()->encodeDoubleIntoAccumulator(PlatformAssembler::FPScratchRegister);
1142void BaselineAssembler::shrConst(
int rhs)
1147 pasm()->rshift32(TrustedImm32(rhs), PlatformAssembler::AccumulatorRegisterValue);
1148 pasm()->setAccumulatorTag(IntegerTag);
1151void BaselineAssembler::shlConst(
int rhs)
1156 pasm()->lshift32(TrustedImm32(rhs), PlatformAssembler::AccumulatorRegisterValue);
1157 pasm()->setAccumulatorTag(IntegerTag);
1160void BaselineAssembler::mul(
int lhs)
1162 auto done = pasm()->binopBothIntPath(regAddr(lhs), [
this](){
1163 auto overflowed = pasm()->branchMul32(PlatformAssembler::Overflow,
1164 PlatformAssembler::AccumulatorRegisterValue,
1165 PlatformAssembler::ScratchRegister);
1166 pasm()->setAccumulatorTag(IntegerTag,
1167 PlatformAssembler::ScratchRegister);
1172 saveAccumulatorInFrame();
1173 pasm()->prepareCallWithArgCount(2);
1174 pasm()->passAccumulatorAsArg(1);
1175 pasm()->passJSSlotAsArg(lhs, 0);
1176 ASM_GENERATE_RUNTIME_CALL(Mul, CallResultDestination::InAccumulator);
1183void BaselineAssembler::div(
int lhs)
1185 saveAccumulatorInFrame();
1186 pasm()->prepareCallWithArgCount(2);
1187 pasm()->passAccumulatorAsArg(1);
1188 pasm()->passJSSlotAsArg(lhs, 0);
1189 ASM_GENERATE_RUNTIME_CALL(Div, CallResultDestination::InAccumulator);
1193void BaselineAssembler::mod(
int lhs)
1195 saveAccumulatorInFrame();
1196 pasm()->prepareCallWithArgCount(2);
1197 pasm()->passAccumulatorAsArg(1);
1198 pasm()->passJSSlotAsArg(lhs, 0);
1199 ASM_GENERATE_RUNTIME_CALL(Mod, CallResultDestination::InAccumulator);
1203void BaselineAssembler::sub(
int lhs)
1205 auto done = pasm()->binopBothIntPath(regAddr(lhs), [
this](){
1206 auto overflowed = pasm()->branchSub32(PlatformAssembler::Overflow,
1207 PlatformAssembler::AccumulatorRegisterValue,
1208 PlatformAssembler::ScratchRegister);
1209 pasm()->setAccumulatorTag(IntegerTag,
1210 PlatformAssembler::ScratchRegister);
1215 saveAccumulatorInFrame();
1216 pasm()->prepareCallWithArgCount(2);
1217 pasm()->passAccumulatorAsArg(1);
1218 pasm()->passJSSlotAsArg(lhs, 0);
1219 ASM_GENERATE_RUNTIME_CALL(Sub, CallResultDestination::InAccumulator);
1226void BaselineAssembler::cmpeqNull()
1228 pasm()->isNullOrUndefined();
1232void BaselineAssembler::cmpneNull()
1234 pasm()->isNullOrUndefined();
1235 pasm()->xor32(TrustedImm32(1), PlatformAssembler::AccumulatorRegisterValue);
1239void BaselineAssembler::cmpeqInt(
int lhs)
1241 auto isIntOrBool = pasm()->isIntOrBool();
1242 saveAccumulatorInFrame();
1243 pasm()->pushValueAligned(Encode(lhs));
1244 if (PlatformAssembler::ArgInRegCount < 2)
1245 pasm()->push(PlatformAssembler::StackPointerRegister);
1247 pasm()->move(PlatformAssembler::StackPointerRegister, pasm()->registerForArg(1));
1248 pasm()->pushAccumulatorAsArg(0);
1249 pasm()->callRuntimeUnchecked((
void*)Runtime::Equal::call);
1250 pasm()->saveReturnValueInAccumulator();
1251 if (PlatformAssembler::ArgInRegCount < 2)
1252 pasm()->addPtr(TrustedImm32(2 * PlatformAssembler::PointerSize), PlatformAssembler::StackPointerRegister);
1253 pasm()->popValueAligned();
1254 auto done = pasm()->jump();
1255 isIntOrBool.link(pasm());
1256 pasm()->compare32(PlatformAssembler::Equal, PlatformAssembler::AccumulatorRegisterValue,
1258 PlatformAssembler::AccumulatorRegisterValue);
1263void BaselineAssembler::cmpneInt(
int lhs)
1265 auto isIntOrBool = pasm()->isIntOrBool();
1266 saveAccumulatorInFrame();
1267 pasm()->pushValueAligned(Encode(lhs));
1268 if (PlatformAssembler::ArgInRegCount < 2)
1269 pasm()->push(PlatformAssembler::StackPointerRegister);
1271 pasm()->move(PlatformAssembler::StackPointerRegister, pasm()->registerForArg(1));
1272 pasm()->pushAccumulatorAsArg(0);
1273 pasm()->callRuntimeUnchecked((
void*)Runtime::NotEqual::call);
1274 pasm()->saveReturnValueInAccumulator();
1275 if (PlatformAssembler::ArgInRegCount < 2)
1276 pasm()->addPtr(TrustedImm32(2 * PlatformAssembler::PointerSize), PlatformAssembler::StackPointerRegister);
1277 pasm()->popValueAligned();
1278 auto done = pasm()->jump();
1279 isIntOrBool.link(pasm());
1280 pasm()->compare32(PlatformAssembler::NotEqual, PlatformAssembler::AccumulatorRegisterValue,
1282 PlatformAssembler::AccumulatorRegisterValue);
1287void BaselineAssembler::cmp(
int cond, CmpFunc function,
int lhs)
1289 auto c =
static_cast<PlatformAssembler::RelationalCondition
>(cond);
1290 auto done = pasm()->binopBothIntPath(regAddr(lhs), [
this,
c](){
1291 pasm()->compare32(
c, PlatformAssembler::ScratchRegister,
1292 PlatformAssembler::AccumulatorRegisterValue,
1293 PlatformAssembler::AccumulatorRegisterValue);
1294 return PlatformAssembler::Jump();
1298 saveAccumulatorInFrame();
1299 pasm()->prepareCallWithArgCount(2);
1300 pasm()->passAccumulatorAsArg(1);
1301 pasm()->passJSSlotAsArg(lhs, 0);
1303 callRuntime(
reinterpret_cast<void*
>(function), CallResultDestination::InAccumulator);
1311void BaselineAssembler::cmpeq(
int lhs)
1313 cmp(PlatformAssembler::Equal, &Runtime::CompareEqual::call, lhs);
1316void BaselineAssembler::cmpne(
int lhs)
1318 cmp(PlatformAssembler::NotEqual, &Runtime::CompareNotEqual::call, lhs);
1321void BaselineAssembler::cmpgt(
int lhs)
1323 cmp(PlatformAssembler::GreaterThan, &Runtime::CompareGreaterThan::call, lhs);
1326void BaselineAssembler::cmpge(
int lhs)
1328 cmp(PlatformAssembler::GreaterThanOrEqual, &Runtime::CompareGreaterEqual::call, lhs);
1331void BaselineAssembler::cmplt(
int lhs)
1333 cmp(PlatformAssembler::LessThan, &Runtime::CompareLessThan::call, lhs);
1336void BaselineAssembler::cmple(
int lhs)
1338 cmp(PlatformAssembler::LessThanOrEqual, &Runtime::CompareLessEqual::call, lhs);
1341void BaselineAssembler::cmpStrictEqual(
int lhs)
1343 cmp(PlatformAssembler::Equal, &Runtime::CompareStrictEqual::call, lhs);
1346void BaselineAssembler::cmpStrictNotEqual(
int lhs)
1348 cmp(PlatformAssembler::NotEqual, &Runtime::CompareStrictNotEqual::call, lhs);
1351int BaselineAssembler::jump(
int offset)
1353 pasm()->addJumpToOffset(pasm()->
jump(),
offset);
1357int BaselineAssembler::jumpTrue(
int offset)
1359 pasm()->toBoolean([
this,
offset](PlatformAssembler::RegisterID resultReg) {
1360 auto jump = pasm()->branch32(PlatformAssembler::NotEqual, TrustedImm32(0), resultReg);
1366int BaselineAssembler::jumpFalse(
int offset)
1368 pasm()->toBoolean([
this,
offset](PlatformAssembler::RegisterID resultReg) {
1369 auto jump = pasm()->branch32(PlatformAssembler::Equal, TrustedImm32(0), resultReg);
1375int BaselineAssembler::jumpNoException(
int offset)
1377 auto jump = pasm()->branch32(
1378 PlatformAssembler::Equal,
1379 PlatformAssembler::Address(PlatformAssembler::EngineRegister,
1380 offsetof(EngineBase, hasException)),
1386int BaselineAssembler::jumpNotUndefined(
int offset)
1388 pasm()->jumpNotUndefined(
offset);
1392int BaselineAssembler::jumpEqNull(
int offset)
1394 saveAccumulatorInFrame();
1397 pasm()->toBoolean([
this,
offset](PlatformAssembler::RegisterID resultReg) {
1398 auto isFalse = pasm()->branch32(PlatformAssembler::Equal, TrustedImm32(0), resultReg);
1399 loadValue(Encode::undefined());
1400 pasm()->addJumpToOffset(pasm()->
jump(),
offset);
1401 isFalse.link(pasm());
1402 loadAccumulatorFromFrame();
1409void BaselineAssembler::prepareCallWithArgCount(
int argc)
1411 pasm()->prepareCallWithArgCount(argc);
1414void BaselineAssembler::storeInstructionPointer(
int instructionOffset)
1416 pasm()->storeInstructionPointer(instructionOffset);
1419void BaselineAssembler::passAccumulatorAsArg(
int arg)
1421 pasm()->passAccumulatorAsArg(
arg);
1424void BaselineAssembler::passFunctionAsArg(
int arg)
1426 pasm()->passFunctionAsArg(
arg);
1429void BaselineAssembler::passEngineAsArg(
int arg)
1431 pasm()->passEngineAsArg(
arg);
1434void BaselineAssembler::passJSSlotAsArg(
int reg,
int arg)
1436 pasm()->passJSSlotAsArg(reg,
arg);
1439void BaselineAssembler::passCppFrameAsArg(
int arg)
1441 pasm()->passCppFrameAsArg(
arg);
1444void BaselineAssembler::passInt32AsArg(
int value,
int arg)
1446 pasm()->passInt32AsArg(
value,
arg);
1449void BaselineAssembler::passPointerAsArg(
void *
ptr,
int arg)
1451 pasm()->passPointerAsArg(
ptr,
arg);
1454void BaselineAssembler::callRuntime(
const void *funcPtr, CallResultDestination dest)
1456 pasm()->callRuntime(funcPtr, dest);
1459void BaselineAssembler::saveAccumulatorInFrame()
1461 pasm()->storeAccumulator(PlatformAssembler::Address(PlatformAssembler::JSStackFrameRegister,
1462 offsetof(CallData, accumulator)));
1465void BaselineAssembler::loadAccumulatorFromFrame()
1467 pasm()->loadAccumulator(PlatformAssembler::Address(PlatformAssembler::JSStackFrameRegister,
1468 offsetof(CallData, accumulator)));
1471static ReturnedValue TheJitIs__Tail_Calling__ToTheRuntimeSoTheJitFrameIsMissing(JSTypesStackFrame *
frame, ExecutionEngine *
engine)
1476void BaselineAssembler::jsTailCall(
int func,
int thisObject,
int argc,
int argv)
1478 Address tos = pasm()->jsAlloca(4);
1480 int32_t argcOffset = tos.offset + int32_t(
sizeof(Value)) * Runtime::StackOffsets::tailCall_argc;
1481 int32_t argvOffset = tos.offset + int32_t(
sizeof(Value)) * Runtime::StackOffsets::tailCall_argv;
1482 int32_t thisOffset = tos.offset + int32_t(
sizeof(Value)) * Runtime::StackOffsets::tailCall_thisObject;
1483 int32_t funcOffset = tos.offset + int32_t(
sizeof(Value)) * Runtime::StackOffsets::tailCall_function;
1485 pasm()->storeInt32AsValue(argc, Address(tos.base, argcOffset));
1486 pasm()->storeInt32AsValue(argv, Address(tos.base, argvOffset));
1487 pasm()->moveReg(regAddr(thisObject), Address(tos.base, thisOffset));
1488 pasm()->moveReg(regAddr(
func), Address(tos.base, funcOffset));
1489 pasm()->tailCallRuntime(
1490 reinterpret_cast<void *
>(TheJitIs__Tail_Calling__ToTheRuntimeSoTheJitFrameIsMissing),
1491 "TheJitIs__Tail_Calling__ToTheRuntimeSoTheJitFrameIsMissing");
1494void BaselineAssembler::checkException()
1496 pasm()->checkException();
1499void BaselineAssembler::gotoCatchException()
1501 pasm()->addCatchyJump(pasm()->
jump());
1504void BaselineAssembler::getException()
1508 Address hasExceptionAddr(PlatformAssembler::EngineRegister,
1509 offsetof(EngineBase, hasException));
1510 PlatformAssembler::Jump nope = pasm()->branch8(PlatformAssembler::Equal,
1513 pasm()->loadPtr(Address(PlatformAssembler::EngineRegister,
1514 offsetof(EngineBase, exceptionValue)),
1515 PlatformAssembler::ScratchRegister);
1516 pasm()->loadAccumulator(Address(PlatformAssembler::ScratchRegister));
1517 pasm()->store8(TrustedImm32(0), hasExceptionAddr);
1518 auto done = pasm()->jump();
1520 pasm()->loadValue(Value::emptyValue().asReturnedValue());
1525void BaselineAssembler::setException()
1527 auto noException = pasm()->jumpEmpty();
1528 Address
addr(PlatformAssembler::EngineRegister, offsetof(EngineBase, exceptionValue));
1529 pasm()->loadPtr(
addr, PlatformAssembler::ScratchRegister);
1530 pasm()->storeAccumulator(Address(PlatformAssembler::ScratchRegister));
1531 addr.offset = offsetof(EngineBase, hasException);
1533 pasm()->store8(TrustedImm32(1),
addr);
1534 noException.link(pasm());
1537int BaselineAssembler::setUnwindHandler(
int offset)
1539 auto l = pasm()->storePtrWithPatch(TrustedImmPtr(
nullptr), pasm()->exceptionHandlerAddress());
1540 pasm()->addEHTarget(l,
offset);
1545void BaselineAssembler::clearUnwindHandler()
1547 pasm()->storePtr(TrustedImmPtr(
nullptr), pasm()->exceptionHandlerAddress());
1550void JIT::BaselineAssembler::unwindDispatch()
1553 pasm()->load32(Address(PlatformAssembler::CppStackFrameRegister, offsetof(JSTypesStackFrame, unwindLevel)), PlatformAssembler::ScratchRegister);
1554 auto noUnwind = pasm()->branch32(PlatformAssembler::Equal, PlatformAssembler::ScratchRegister, TrustedImm32(0));
1555 pasm()->sub32(TrustedImm32(1), PlatformAssembler::ScratchRegister);
1556 pasm()->store32(PlatformAssembler::ScratchRegister, Address(PlatformAssembler::CppStackFrameRegister, offsetof(JSTypesStackFrame, unwindLevel)));
1557 auto jump = pasm()->branch32(PlatformAssembler::Equal, PlatformAssembler::ScratchRegister, TrustedImm32(0));
1558 gotoCatchException();
1561 pasm()->loadPtr(Address(PlatformAssembler::CppStackFrameRegister, offsetof(JSTypesStackFrame, unwindLabel)), PlatformAssembler::ScratchRegister);
1562 pasm()->jump(PlatformAssembler::ScratchRegister);
1564 noUnwind.link(pasm());
1567int JIT::BaselineAssembler::unwindToLabel(
int level,
int offset)
1569 auto l = pasm()->storePtrWithPatch(TrustedImmPtr(
nullptr), Address(PlatformAssembler::CppStackFrameRegister, offsetof(JSTypesStackFrame, unwindLabel)));
1570 pasm()->addEHTarget(l,
offset);
1571 pasm()->store32(TrustedImm32(
level), Address(PlatformAssembler::CppStackFrameRegister, offsetof(JSTypesStackFrame, unwindLevel)));
1572 gotoCatchException();
1576void BaselineAssembler::pushCatchContext(
int index,
int name)
1578 pasm()->prepareCallWithArgCount(3);
1579 pasm()->passInt32AsArg(
name, 2);
1580 pasm()->passInt32AsArg(
index, 1);
1581 pasm()->passEngineAsArg(0);
1582 ASM_GENERATE_RUNTIME_CALL(PushCatchContext, CallResultDestination::Ignore);
1585void BaselineAssembler::popContext()
1587 Heap::CallContext
ctx;
1589 pasm()->loadPointerFromValue(regAddr(CallData::Context), PlatformAssembler::ScratchRegister);
1590 pasm()->loadPtr(Address(PlatformAssembler::ScratchRegister,
ctx.outer.offset), PlatformAssembler::ScratchRegister);
1591 pasm()->storeHeapObject(PlatformAssembler::ScratchRegister, regAddr(CallData::Context));
1594void BaselineAssembler::deadTemporalZoneCheck(
int offsetForSavedIP,
int variableName)
1596 auto valueIsAliveJump = pasm()->jumpNotEmpty();
1597 storeInstructionPointer(offsetForSavedIP);
1598 prepareCallWithArgCount(2);
1599 passInt32AsArg(variableName, 1);
1601 ASM_GENERATE_RUNTIME_CALL(ThrowReferenceError, CallResultDestination::Ignore);
1602 gotoCatchException();
1603 valueIsAliveJump.link(pasm());
1606void BaselineAssembler::ret()
1608 pasm()->generateFunctionExit();
Combined button and popup list for selecting options.
\qmltype Particle \inqmlmodule QtQuick.Particles
#define Q_STATIC_ASSERT(Condition)
AudioChannelLayoutTag tag
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
static void jump(QtMsgType t, const QMessageLogContext &context, const QString &m)
static ControlElement< T > * ptr(QWidget *widget)
static bool isNumber(char s)
GLenum GLsizei GLsizei GLint * values
[15]
GLsizei const GLfloat * v
[13]
GLenum GLuint GLint level
GLenum GLuint GLintptr offset
GLsizei GLsizei GLchar * source
static bool equal(const QChar *a, int l, const char *b)
static int toInt32(Value v)
static const QV4::Value & constant(Function *function, int index)
static constexpr Value fromReturnedValue(ReturnedValue val)