11#include <private/qv4function_p.h>
12#include <private/qv4runtime_p.h>
13#include <private/qv4stackframe_p.h>
15#include <wtf/Vector.h>
16#include <assembler/MacroAssembler.h>
17#include <assembler/MacroAssemblerCodeRef.h>
18#include <assembler/LinkBuffer.h>
21#undef ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES
29#define ASM_GENERATE_RUNTIME_CALL(function, destination)
30 pasm()->GENERATE_RUNTIME_CALL(function, destination)
32 PlatformAssemblerCommon::callRuntimeUnchecked(reinterpret_cast<void *>(&x), #x)
34const QV4::Value::ValueTypeInternal IntegerTag = QV4::Value::ValueTypeInternal::Integer;
36static ReturnedValue toNumberHelper(ReturnedValue v)
38 return Encode(Value::fromReturnedValue(v).toNumber());
41static ReturnedValue toInt32Helper(ReturnedValue v)
43 return Encode(Value::fromReturnedValue(v).toInt32());
46#if QT_POINTER_SIZE == 8
|| defined(ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES)
47class PlatformAssembler64 :
public PlatformAssemblerCommon
50 PlatformAssembler64(
const Value *constantTable)
51 : PlatformAssemblerCommon(constantTable)
54 void callRuntime(
const void *funcPtr, CallResultDestination dest)
56 PlatformAssemblerCommon::callRuntime(funcPtr);
57 if (dest == CallResultDestination::InAccumulator)
58 saveReturnValueInAccumulator();
59 else if (AccumulatorRegister == ReturnValueRegister)
63 void saveReturnValueInAccumulator()
65 move(ReturnValueRegister, AccumulatorRegister);
68 void loadUndefined(RegisterID dest = AccumulatorRegister)
70 move(TrustedImm64(0), dest);
73 void copyConst(
int constIndex, Address dest)
76 if (constant(constIndex).isUndefined()) {
77 loadUndefined(ScratchRegister);
79 load64(loadConstAddress(constIndex, ScratchRegister), ScratchRegister);
81 store64(ScratchRegister, dest);
84 void copyReg(Address src, Address dst)
86 load64(src, ScratchRegister);
87 store64(ScratchRegister, dst);
90 void loadPointerFromValue(Address addr, RegisterID dest = AccumulatorRegister)
95 void loadAccumulator(Address addr)
97 load64(addr, AccumulatorRegister);
100 void storeAccumulator(Address addr)
102 store64(AccumulatorRegister, addr);
105 void moveReg(Address sourceRegAddress, Address destRegAddress)
107 load64(sourceRegAddress, ScratchRegister);
108 store64(ScratchRegister, destRegAddress);
111 void loadString(
int stringId)
113 loadAccumulator(loadStringAddress(stringId));
116 void loadValue(ReturnedValue value)
118 move(TrustedImm64(value), AccumulatorRegister);
121 void storeHeapObject(RegisterID source, Address addr)
123 store64(source, addr);
126 void generateCatchTrampoline()
128 PlatformAssemblerCommon::generateCatchTrampoline([
this](){loadUndefined();});
131 void jumpNotUndefined(
int offset)
133 auto jump = branch64(NotEqual, AccumulatorRegister, TrustedImm64(0));
134 addJumpToOffset(jump, offset);
139 return branch64(Equal, AccumulatorRegister, TrustedImm64(Value::emptyValue().asReturnedValue()));
144 return branch64(NotEqual, AccumulatorRegister, TrustedImm64(Value::emptyValue().asReturnedValue()));
147 void toBoolean(std::function<
void(RegisterID)> continuation)
149 urshift64(AccumulatorRegister, TrustedImm32(Value::IsIntegerConvertible_Shift), ScratchRegister);
150 auto needsConversion = branch32(
151 NotEqual, TrustedImm32(Value::IsIntegerConvertible_Value), ScratchRegister);
153 continuation(AccumulatorRegister);
157 needsConversion.link(
this);
158 push(AccumulatorRegister);
159 move(AccumulatorRegister, registerForArg(0));
160 callHelper(Value::toBooleanImpl);
161 and32(TrustedImm32(1), ReturnValueRegister, ScratchRegister);
162 pop(AccumulatorRegister);
163 continuation(ScratchRegister);
170 move(TrustedImm64(Value::NumberMask), ScratchRegister);
171 and64(AccumulatorRegister, ScratchRegister);
172 move(TrustedImm64(Value::NumberDiscriminator), ScratchRegister2);
173 auto isNumber = branch64(GreaterThanOrEqual, ScratchRegister, ScratchRegister2);
175 move(AccumulatorRegister, registerForArg(0));
176 callHelper(toNumberHelper);
177 saveReturnValueInAccumulator();
183 void toInt32LhsAcc(Address lhs, RegisterID lhsTarget)
185 load64(lhs, lhsTarget);
186 urshift64(lhsTarget, TrustedImm32(Value::QuickType_Shift), ScratchRegister2);
187 auto lhsIsInt = branch32(Equal, TrustedImm32(Value::QT_Int), ScratchRegister2);
189 const Address accumulatorStackAddress(JSStackFrameRegister,
190 offsetof(CallData, accumulator));
191 storeAccumulator(accumulatorStackAddress);
192 move(lhsTarget, registerForArg(0));
193 callHelper(toInt32Helper);
194 move(ReturnValueRegister, lhsTarget);
195 loadAccumulator(accumulatorStackAddress);
198 urshift64(AccumulatorRegister, TrustedImm32(Value::QuickType_Shift), ScratchRegister2);
199 auto isInt = branch32(Equal, TrustedImm32(Value::QT_Int), ScratchRegister2);
201 pushAligned(lhsTarget);
202 move(AccumulatorRegister, registerForArg(0));
203 callHelper(toInt32Helper);
204 saveReturnValueInAccumulator();
205 popAligned(lhsTarget);
212 urshift64(AccumulatorRegister, TrustedImm32(Value::QuickType_Shift), ScratchRegister2);
213 auto isInt = branch32(Equal, TrustedImm32(Value::QT_Int), ScratchRegister2);
215 move(AccumulatorRegister, registerForArg(0));
216 callHelper(toInt32Helper);
217 saveReturnValueInAccumulator();
222 void regToInt32(Address srcReg, RegisterID targetReg)
224 load64(srcReg, targetReg);
225 urshift64(targetReg, TrustedImm32(Value::QuickType_Shift), ScratchRegister2);
226 auto isInt = branch32(Equal, TrustedImm32(Value::QT_Int), ScratchRegister2);
228 pushAligned(AccumulatorRegister);
229 move(targetReg, registerForArg(0));
230 callHelper(toInt32Helper);
231 move(ReturnValueRegister, targetReg);
232 popAligned(AccumulatorRegister);
237 void isNullOrUndefined()
239 move(AccumulatorRegister, ScratchRegister);
240 compare64(Equal, ScratchRegister, TrustedImm32(0), AccumulatorRegister);
241 Jump isUndef = branch32(NotEqual, TrustedImm32(0), AccumulatorRegister);
244 rshift64(TrustedImm32(32), ScratchRegister);
245 compare32(Equal, ScratchRegister, TrustedImm32(
int(QV4::Value::ValueTypeInternal::Null)),
246 AccumulatorRegister);
253 urshift64(AccumulatorRegister, TrustedImm32(Value::IsIntegerOrBool_Shift), ScratchRegister);
254 return branch32(Equal, TrustedImm32(Value::IsIntegerOrBool_Value), ScratchRegister);
257 void jumpStrictEqualStackSlotInt(
int lhs,
int rhs,
int offset)
259 Address lhsAddr(JSStackFrameRegister, lhs *
int(
sizeof(Value)));
260 load64(lhsAddr, ScratchRegister);
261 Jump isUndef = branch64(Equal, ScratchRegister, TrustedImm64(0));
262 Jump equal = branch32(Equal, TrustedImm32(rhs), ScratchRegister);
263 addJumpToOffset(equal, offset);
267 void jumpStrictNotEqualStackSlotInt(
int lhs,
int rhs,
int offset)
269 Address lhsAddr(JSStackFrameRegister, lhs *
int(
sizeof(Value)));
270 load64(lhsAddr, ScratchRegister);
271 Jump isUndef = branch64(Equal, ScratchRegister, TrustedImm64(0));
272 addJumpToOffset(isUndef, offset);
273 Jump notEqual = branch32(NotEqual, TrustedImm32(rhs), ScratchRegister);
274 addJumpToOffset(notEqual, offset);
277 void setAccumulatorTag(QV4::Value::ValueTypeInternal tag, RegisterID sourceReg = NoRegister)
279 if (sourceReg == NoRegister)
280 or64(TrustedImm64(int64_t(tag) << 32), AccumulatorRegister);
282 or64(TrustedImm64(int64_t(tag) << 32), sourceReg, AccumulatorRegister);
285 void encodeDoubleIntoAccumulator(FPRegisterID src)
287 moveDoubleTo64(src, AccumulatorRegister);
288 move(TrustedImm64(Value::EncodeMask), ScratchRegister);
289 xor64(ScratchRegister, AccumulatorRegister);
292 void pushValueAligned(ReturnedValue v)
295 pushAligned(AccumulatorRegister);
298 void popValueAligned()
300 addPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
303 Jump binopBothIntPath(Address lhsAddr, std::function<Jump(
void)> fastPath)
305 urshift64(AccumulatorRegister, TrustedImm32(32), ScratchRegister);
306 Jump accNotInt = branch32(NotEqual, TrustedImm32(
int(IntegerTag)), ScratchRegister);
307 load64(lhsAddr, ScratchRegister);
308 urshift64(ScratchRegister, TrustedImm32(32), ScratchRegister2);
309 Jump lhsNotInt = branch32(NotEqual, TrustedImm32(
int(IntegerTag)), ScratchRegister2);
312 Jump failure = fastPath();
318 accNotInt.link(
this);
319 lhsNotInt.link(
this);
324 Jump unopIntPath(std::function<Jump(
void)> fastPath)
326 urshift64(AccumulatorRegister, TrustedImm32(Value::IsIntegerConvertible_Shift), ScratchRegister);
327 Jump accNotIntConvertible = branch32(
328 NotEqual, TrustedImm32(Value::IsIntegerConvertible_Value), ScratchRegister);
331 Jump failure = fastPath();
337 accNotIntConvertible.link(
this);
342 void callWithAccumulatorByValueAsFirstArgument(std::function<
void()> doCall)
344 passAsArg(AccumulatorRegister, 0);
349typedef PlatformAssembler64 PlatformAssembler;
352#if QT_POINTER_SIZE == 4
|| defined(ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES)
353class PlatformAssembler32 :
public PlatformAssemblerCommon
356 PlatformAssembler32(
const Value *constantTable)
357 : PlatformAssemblerCommon(constantTable)
360 void callRuntime(
const void *funcPtr, CallResultDestination dest)
362 PlatformAssemblerCommon::callRuntime(funcPtr);
363 if (dest == CallResultDestination::InAccumulator)
364 saveReturnValueInAccumulator();
365 else if (AccumulatorRegisterValue == ReturnValueRegisterValue)
369 void saveReturnValueInAccumulator()
371 move(ReturnValueRegisterValue, AccumulatorRegisterValue);
372 move(ReturnValueRegisterTag, AccumulatorRegisterTag);
377 move(TrustedImm32(0), AccumulatorRegisterValue);
378 move(TrustedImm32(0), AccumulatorRegisterTag);
381 void copyConst(
int constIndex, Address destRegAddr)
384 if (constant(constIndex).isUndefined()) {
385 move(TrustedImm32(0), ScratchRegister);
386 store32(ScratchRegister, destRegAddr);
387 destRegAddr.offset += 4;
388 store32(ScratchRegister, destRegAddr);
390 Address src = loadConstAddress(constIndex);
391 loadDouble(src, FPScratchRegister);
392 storeDouble(FPScratchRegister, destRegAddr);
396 void copyReg(Address src, Address dest)
398 loadDouble(src, FPScratchRegister);
399 storeDouble(FPScratchRegister, dest);
402 void loadPointerFromValue(Address addr, RegisterID dest = AccumulatorRegisterValue)
407 void loadAccumulator(Address src)
409 load32(src, AccumulatorRegisterValue);
411 load32(src, AccumulatorRegisterTag);
414 void storeAccumulator(Address addr)
416 store32(AccumulatorRegisterValue, addr);
418 store32(AccumulatorRegisterTag, addr);
421 void moveReg(Address sourceRegAddress, Address destRegAddress)
423 load32(sourceRegAddress, ScratchRegister);
424 store32(ScratchRegister, destRegAddress);
425 sourceRegAddress.offset += 4;
426 destRegAddress.offset += 4;
427 load32(sourceRegAddress, ScratchRegister);
428 store32(ScratchRegister, destRegAddress);
431 void loadString(
int stringId)
433 load32(loadStringAddress(stringId), AccumulatorRegisterValue);
434 move(TrustedImm32(0), AccumulatorRegisterTag);
437 void loadValue(ReturnedValue value)
439 move(TrustedImm32(Value::fromReturnedValue(value).value()), AccumulatorRegisterValue);
440 move(TrustedImm32(Value::fromReturnedValue(value).tag()), AccumulatorRegisterTag);
443 void storeHeapObject(RegisterID source, Address addr)
445 store32(source, addr);
447 store32(TrustedImm32(0), addr);
451 void generateCatchTrampoline()
453 PlatformAssemblerCommon::generateCatchTrampoline([
this](){loadUndefined();});
458 and32(TrustedImm32(Value::NumberMask >> Value::Tag_Shift),
459 AccumulatorRegisterTag, ScratchRegister);
460 auto isNumber = branch32(
461 GreaterThanOrEqual, ScratchRegister,
462 TrustedImm32(Value::NumberDiscriminator >> Value::Tag_Shift));
465 if (ArgInRegCount < 2) {
466 subPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
467 push(AccumulatorRegisterTag);
468 push(AccumulatorRegisterValue);
470 move(AccumulatorRegisterValue, registerForArg(0));
471 move(AccumulatorRegisterTag, registerForArg(1));
473 callHelper(toNumberHelper);
474 saveReturnValueInAccumulator();
475 if (ArgInRegCount < 2)
476 addPtr(TrustedImm32(4 * PointerSize), StackPointerRegister);
482 void toInt32LhsAcc(Address lhs, RegisterID lhsTarget)
484 bool accumulatorNeedsSaving = AccumulatorRegisterValue == ReturnValueRegisterValue
485 || AccumulatorRegisterTag == ReturnValueRegisterTag;
487 load32(lhs, lhsTarget);
489 auto lhsIsNotInt = branch32(NotEqual, TrustedImm32(
int(IntegerTag)), lhsTarget);
490 load32(lhs, lhsTarget);
491 auto lhsIsInt = jump();
493 lhsIsNotInt.link(
this);
496 const Address accumulatorStackAddress(JSStackFrameRegister,
497 offsetof(CallData, accumulator));
498 storeAccumulator(accumulatorStackAddress);
500 if (ArgInRegCount < 2) {
501 subPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
503 load32(lhs, lhsTarget);
506 move(lhsTarget, registerForArg(1));
507 load32(lhs, registerForArg(0));
509 callHelper(toInt32Helper);
510 move(ReturnValueRegisterValue, lhsTarget);
511 if (ArgInRegCount < 2)
512 addPtr(TrustedImm32(4 * PointerSize), StackPointerRegister);
514 if (accumulatorNeedsSaving)
515 loadAccumulator(accumulatorStackAddress);
519 auto rhsIsInt = branch32(Equal, TrustedImm32(
int(IntegerTag)), AccumulatorRegisterTag);
521 pushAligned(lhsTarget);
522 if (ArgInRegCount < 2) {
523 subPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
524 push(AccumulatorRegisterTag);
525 push(AccumulatorRegisterValue);
527 move(AccumulatorRegisterValue, registerForArg(0));
528 move(AccumulatorRegisterTag, registerForArg(1));
530 callHelper(toInt32Helper);
531 saveReturnValueInAccumulator();
532 if (ArgInRegCount < 2)
533 addPtr(TrustedImm32(4 * PointerSize), StackPointerRegister);
534 popAligned(lhsTarget);
541 urshift32(AccumulatorRegisterTag, TrustedImm32(Value::QuickType_Shift - 32), ScratchRegister);
542 auto isInt = branch32(Equal, TrustedImm32(Value::QT_Int), ScratchRegister);
544 if (ArgInRegCount < 2) {
545 subPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
546 push(AccumulatorRegisterTag);
547 push(AccumulatorRegisterValue);
549 move(AccumulatorRegisterValue, registerForArg(0));
550 move(AccumulatorRegisterTag, registerForArg(1));
552 callHelper(toInt32Helper);
553 saveReturnValueInAccumulator();
554 if (ArgInRegCount < 2)
555 addPtr(TrustedImm32(4 * PointerSize), StackPointerRegister);
560 void regToInt32(Address srcReg, RegisterID targetReg)
562 bool accumulatorNeedsSaving = AccumulatorRegisterValue == ReturnValueRegisterValue
563 || AccumulatorRegisterTag == ReturnValueRegisterTag;
564 if (accumulatorNeedsSaving) {
565 push(AccumulatorRegisterTag);
566 push(AccumulatorRegisterValue);
568 if (ArgInRegCount < 2) {
569 if (!accumulatorNeedsSaving)
570 subPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
572 load32(srcReg, targetReg);
575 load32(srcReg, targetReg);
578 if (accumulatorNeedsSaving)
579 subPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
580 load32(srcReg, registerForArg(0));
582 load32(srcReg, registerForArg(1));
584 callHelper(toInt32Helper);
585 move(ReturnValueRegisterValue, targetReg);
586 if (accumulatorNeedsSaving) {
587 addPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
588 pop(AccumulatorRegisterValue);
589 pop(AccumulatorRegisterTag);
590 }
else if (ArgInRegCount < 2) {
591 addPtr(TrustedImm32(4 * PointerSize), StackPointerRegister);
595 void isNullOrUndefined()
597 Jump notUndefOrPtr = branch32(NotEqual, TrustedImm32(0), AccumulatorRegisterTag);
598 compare32(Equal, AccumulatorRegisterValue, TrustedImm32(0), AccumulatorRegisterValue);
602 notUndefOrPtr.link(
this);
603 compare32(Equal, AccumulatorRegisterTag, TrustedImm32(
int(QV4::Value::ValueTypeInternal::Null)),
604 AccumulatorRegisterValue);
611 urshift32(AccumulatorRegisterTag, TrustedImm32(Value::IsIntegerOrBool_Shift - 32), ScratchRegister);
612 return branch32(Equal, TrustedImm32(Value::IsIntegerOrBool_Value), ScratchRegister);
615 void pushValue(ReturnedValue v)
617 push(TrustedImm32(v >> 32));
618 push(TrustedImm32(v));
621 void jumpNotUndefined(
int offset)
623 move(AccumulatorRegisterTag, ScratchRegister);
624 or32(AccumulatorRegisterValue, ScratchRegister);
625 auto jump = branch32(NotEqual, ScratchRegister, TrustedImm32(0));
626 addJumpToOffset(jump, offset);
631 return branch32(Equal, AccumulatorRegisterTag, TrustedImm32(Value::emptyValue().asReturnedValue() >> 32));
636 return branch32(NotEqual, AccumulatorRegisterTag, TrustedImm32(Value::emptyValue().asReturnedValue() >> 32));
639 void toBoolean(std::function<
void(RegisterID)> continuation)
641 urshift32(AccumulatorRegisterTag, TrustedImm32(Value::IsIntegerConvertible_Shift - 32),
643 auto needsConversion = branch32(
644 NotEqual, TrustedImm32(Value::IsIntegerConvertible_Value), ScratchRegister);
645 continuation(AccumulatorRegisterValue);
649 needsConversion.link(
this);
651 bool accumulatorNeedsSaving = AccumulatorRegisterValue == ReturnValueRegisterValue
652 || AccumulatorRegisterTag == ReturnValueRegisterTag;
653 if (accumulatorNeedsSaving) {
654 push(AccumulatorRegisterTag);
655 push(AccumulatorRegisterValue);
658 if (ArgInRegCount < 2) {
659 if (!accumulatorNeedsSaving)
660 subPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
661 push(AccumulatorRegisterTag);
662 push(AccumulatorRegisterValue);
664 if (accumulatorNeedsSaving)
665 subPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
666 move(AccumulatorRegisterValue, registerForArg(0));
667 move(AccumulatorRegisterTag, registerForArg(1));
669 callHelper(Value::toBooleanImpl);
670 and32(TrustedImm32(1), ReturnValueRegisterValue, ScratchRegister);
671 if (accumulatorNeedsSaving) {
672 addPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
673 pop(AccumulatorRegisterValue);
674 pop(AccumulatorRegisterTag);
675 }
else if (ArgInRegCount < 2) {
676 addPtr(TrustedImm32(4 * PointerSize), StackPointerRegister);
678 continuation(ScratchRegister);
683 void jumpStrictEqualStackSlotInt(
int lhs,
int rhs,
int offset)
685 Address lhsAddr(JSStackFrameRegister, lhs *
int(
sizeof(Value)));
686 load32(lhsAddr, ScratchRegister);
687 Jump notEqInt = branch32(NotEqual, ScratchRegister, TrustedImm32(rhs));
688 Jump notEqUndefVal = branch32(NotEqual, ScratchRegister, TrustedImm32(0));
689 addJumpToOffset(notEqUndefVal, offset);
691 load32(lhsAddr, ScratchRegister);
692 Jump notEqUndefTag = branch32(NotEqual, ScratchRegister, TrustedImm32(0));
693 addJumpToOffset(notEqUndefTag, offset);
697 void jumpStrictNotEqualStackSlotInt(
int lhs,
int rhs,
int offset)
699 Address lhsAddr(JSStackFrameRegister, lhs *
int(
sizeof(Value)));
700 load32(lhsAddr, ScratchRegister);
701 Jump notEqual = branch32(NotEqual, TrustedImm32(rhs), ScratchRegister);
702 addJumpToOffset(notEqual, offset);
703 Jump notUndefValue = branch32(NotEqual, TrustedImm32(0), ScratchRegister);
705 load32(lhsAddr, ScratchRegister);
706 Jump equalUndef = branch32(Equal, TrustedImm32(0), ScratchRegister);
707 addJumpToOffset(equalUndef, offset);
708 notUndefValue.link(
this);
711 void setAccumulatorTag(QV4::Value::ValueTypeInternal tag, RegisterID sourceReg = NoRegister)
713 if (sourceReg != NoRegister)
714 move(sourceReg, AccumulatorRegisterValue);
715 move(TrustedImm32(
int(tag)), AccumulatorRegisterTag);
718 void encodeDoubleIntoAccumulator(FPRegisterID src)
720 moveDoubleToInts(src, AccumulatorRegisterValue, AccumulatorRegisterTag);
721 xor32(TrustedImm32(Value::EncodeMask >> 32), AccumulatorRegisterTag);
724 void pushValueAligned(ReturnedValue v)
729 void popValueAligned()
734 Jump binopBothIntPath(Address lhsAddr, std::function<Jump(
void)> fastPath)
736 Jump accNotInt = branch32(NotEqual, TrustedImm32(
int(IntegerTag)), AccumulatorRegisterTag);
737 Address lhsAddrTag = lhsAddr; lhsAddrTag.offset += Value::tagOffset();
738 load32(lhsAddrTag, ScratchRegister);
739 Jump lhsNotInt = branch32(NotEqual, TrustedImm32(
int(IntegerTag)), ScratchRegister);
742 Address lhsAddrValue = lhsAddr; lhsAddrValue.offset += Value::valueOffset();
743 load32(lhsAddrValue, ScratchRegister);
744 Jump failure = fastPath();
750 accNotInt.link(
this);
751 lhsNotInt.link(
this);
756 Jump unopIntPath(std::function<Jump(
void)> fastPath)
758 Jump accNotInt = branch32(NotEqual, TrustedImm32(
int(IntegerTag)), AccumulatorRegisterTag);
761 Jump failure = fastPath();
767 accNotInt.link(
this);
772 void callWithAccumulatorByValueAsFirstArgument(std::function<
void()> doCall)
774 if (ArgInRegCount < 2) {
775 subPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
776 push(AccumulatorRegisterTag);
777 push(AccumulatorRegisterValue);
779 move(AccumulatorRegisterValue, registerForArg(0));
780 move(AccumulatorRegisterTag, registerForArg(1));
783 if (ArgInRegCount < 2)
784 addPtr(TrustedImm32(4 * PointerSize), StackPointerRegister);
788typedef PlatformAssembler32 PlatformAssembler;
791#define pasm() reinterpret_cast<PlatformAssembler *>(this->d)
793typedef PlatformAssembler::TrustedImmPtr TrustedImmPtr;
794typedef PlatformAssembler::TrustedImm32 TrustedImm32;
795typedef PlatformAssembler::TrustedImm64 TrustedImm64;
796typedef PlatformAssembler::Address Address;
797typedef PlatformAssembler::RegisterID RegisterID;
798typedef PlatformAssembler::FPRegisterID FPRegisterID;
800static Address regAddr(
int reg)
802 return Address(PlatformAssembler::JSStackFrameRegister, reg *
int(
sizeof(QV4::Value)));
805BaselineAssembler::BaselineAssembler(
const Value *constantTable)
806 : d(
new PlatformAssembler(constantTable))
810BaselineAssembler::~BaselineAssembler()
815void BaselineAssembler::generatePrologue()
817 pasm()->generateFunctionEntry();
820void BaselineAssembler::generateEpilogue()
822 pasm()->generateCatchTrampoline();
825void BaselineAssembler::link(Function *function)
827 pasm()->link(function,
"BaselineJIT");
830void BaselineAssembler::addLabel(
int offset)
832 pasm()->addLabelForOffset(offset);
835void BaselineAssembler::loadConst(
int constIndex)
838 if (pasm()->constant(constIndex).isUndefined()) {
839 pasm()->loadUndefined();
841 pasm()->loadAccumulator(pasm()->loadConstAddress(constIndex));
845void BaselineAssembler::copyConst(
int constIndex,
int destReg)
847 pasm()->copyConst(constIndex, regAddr(destReg));
850void BaselineAssembler::loadReg(
int reg)
852 pasm()->loadAccumulator(regAddr(reg));
855void JIT::BaselineAssembler::moveReg(
int sourceReg,
int destReg)
857 pasm()->moveReg(regAddr(sourceReg), regAddr(destReg));
860void BaselineAssembler::storeReg(
int reg)
862 pasm()->storeAccumulator(regAddr(reg));
865void BaselineAssembler::loadLocal(
int index,
int level)
867 Heap::CallContext ctx;
869 pasm()->loadPointerFromValue(regAddr(CallData::Context), PlatformAssembler::ScratchRegister);
871 pasm()->loadPtr(Address(PlatformAssembler::ScratchRegister, ctx.outer.offset), PlatformAssembler::ScratchRegister);
874 pasm()->loadAccumulator(Address(PlatformAssembler::ScratchRegister, ctx.locals.offset + offsetof(ValueArray<0>, values) +
sizeof(Value)*index));
877void BaselineAssembler::storeLocal(
int index,
int level)
879 Heap::CallContext ctx;
881 pasm()->loadPtr(regAddr(CallData::Context), PlatformAssembler::ScratchRegister);
883 pasm()->loadPtr(Address(PlatformAssembler::ScratchRegister, ctx.outer.offset), PlatformAssembler::ScratchRegister);
886 pasm()->storeAccumulator(Address(PlatformAssembler::ScratchRegister, ctx.locals.offset + offsetof(ValueArray<0>, values) +
sizeof(Value)*index));
888 auto skipBarrier = pasm()->branch8(
889 PlatformAssembler::Equal,
890 PlatformAssembler::Address(PlatformAssembler::EngineRegister,
891 offsetof(EngineBase, isGCOngoing)),
893 saveAccumulatorInFrame();
895 pasm()->prepareCallWithArgCount(1);
896 pasm()->passAccumulatorAsArg(0);
897 pasm()->callRuntime((
void*)Runtime::MarkCustom::call, CallResultDestination::Ignore);
898 loadAccumulatorFromFrame();
899 skipBarrier.link(pasm());
903void BaselineAssembler::loadString(
int stringId)
905 pasm()->loadString(stringId);
908void BaselineAssembler::loadValue(ReturnedValue value)
910 pasm()->loadValue(value);
913void BaselineAssembler::storeHeapObject(
int reg)
915 pasm()->storeHeapObject(PlatformAssembler::ReturnValueRegisterValue, regAddr(reg));
918void BaselineAssembler::loadImport(
int index)
920 Address addr = pasm()->loadCompilationUnitPtr(PlatformAssembler::ScratchRegister);
921 addr.offset = offsetof(QV4::CompilationUnitRuntimeData, imports);
922 pasm()->loadPtr(addr, PlatformAssembler::ScratchRegister);
923 addr.offset = index *
int(
sizeof(QV4::Value*));
924 pasm()->loadPtr(addr, PlatformAssembler::ScratchRegister);
925 pasm()->loadAccumulator(Address(PlatformAssembler::ScratchRegister));
928void BaselineAssembler::toNumber()
933void BaselineAssembler::uminus()
935 saveAccumulatorInFrame();
936 pasm()->prepareCallWithArgCount(1);
937 pasm()->passAccumulatorAsArg(0);
938 ASM_GENERATE_RUNTIME_CALL(UMinus, CallResultDestination::InAccumulator);
942void BaselineAssembler::ucompl()
945 pasm()->xor32(TrustedImm32(-1), PlatformAssembler::AccumulatorRegisterValue);
946 pasm()->setAccumulatorTag(IntegerTag);
949static ReturnedValue incHelper(
const Value v)
952 if (Q_LIKELY(v.isDouble()))
955 d = v.toNumberImpl();
956 return Encode(d + 1.);
959void BaselineAssembler::inc()
961 auto done = pasm()->unopIntPath([
this](){
962 auto overflowed = pasm()->branchAdd32(PlatformAssembler::Overflow,
963 PlatformAssembler::AccumulatorRegisterValue,
965 PlatformAssembler::ScratchRegister);
966 pasm()->setAccumulatorTag(IntegerTag, PlatformAssembler::ScratchRegister);
971 pasm()->callWithAccumulatorByValueAsFirstArgument([
this]() {
972 pasm()->callHelper(incHelper);
973 pasm()->saveReturnValueInAccumulator();
981static ReturnedValue decHelper(
const Value v)
984 if (Q_LIKELY(v.isDouble()))
987 d = v.toNumberImpl();
988 return Encode(d - 1.);
991void BaselineAssembler::dec()
993 auto done = pasm()->unopIntPath([
this](){
994 auto overflowed = pasm()->branchSub32(PlatformAssembler::Overflow,
995 PlatformAssembler::AccumulatorRegisterValue,
997 PlatformAssembler::ScratchRegister);
998 pasm()->setAccumulatorTag(IntegerTag, PlatformAssembler::ScratchRegister);
1003 pasm()->callWithAccumulatorByValueAsFirstArgument([
this]() {
1004 pasm()->callHelper(decHelper);
1005 pasm()->saveReturnValueInAccumulator();
1013void BaselineAssembler::unot()
1015 pasm()->toBoolean([
this](PlatformAssembler::RegisterID resultReg){
1016 pasm()->compare32(PlatformAssembler::Equal, resultReg,
1017 TrustedImm32(0), PlatformAssembler::AccumulatorRegisterValue);
1018 pasm()->setAccumulatorTag(QV4::Value::ValueTypeInternal::Boolean);
1022void BaselineAssembler::add(
int lhs)
1024 auto done = pasm()->binopBothIntPath(regAddr(lhs), [
this](){
1025 auto overflowed = pasm()->branchAdd32(PlatformAssembler::Overflow,
1026 PlatformAssembler::AccumulatorRegisterValue,
1027 PlatformAssembler::ScratchRegister);
1028 pasm()->setAccumulatorTag(IntegerTag,
1029 PlatformAssembler::ScratchRegister);
1034 saveAccumulatorInFrame();
1035 pasm()->prepareCallWithArgCount(3);
1036 pasm()->passAccumulatorAsArg(2);
1037 pasm()->passJSSlotAsArg(lhs, 1);
1038 pasm()->passEngineAsArg(0);
1039 ASM_GENERATE_RUNTIME_CALL(Add, CallResultDestination::InAccumulator);
1046void BaselineAssembler::bitAnd(
int lhs)
1048 PlatformAssembler::Address lhsAddr = regAddr(lhs);
1049 pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister);
1050 pasm()->and32(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
1051 pasm()->setAccumulatorTag(IntegerTag);
1054void BaselineAssembler::bitOr(
int lhs)
1056 PlatformAssembler::Address lhsAddr = regAddr(lhs);
1057 pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister);
1058 pasm()->or32(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
1059 pasm()->setAccumulatorTag(IntegerTag);
1062void BaselineAssembler::bitXor(
int lhs)
1064 PlatformAssembler::Address lhsAddr = regAddr(lhs);
1065 pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister);
1066 pasm()->xor32(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
1067 pasm()->setAccumulatorTag(IntegerTag);
1070void BaselineAssembler::ushr(
int lhs)
1072 PlatformAssembler::Address lhsAddr = regAddr(lhs);
1073 pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister);
1074 pasm()->and32(TrustedImm32(0x1f), PlatformAssembler::AccumulatorRegisterValue);
1075 pasm()->urshift32(PlatformAssembler::AccumulatorRegisterValue, PlatformAssembler::ScratchRegister);
1076 pasm()->move(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
1077 auto doubleEncode = pasm()->branch32(PlatformAssembler::LessThan,
1078 PlatformAssembler::AccumulatorRegisterValue,
1080 pasm()->setAccumulatorTag(IntegerTag);
1081 auto done = pasm()->jump();
1083 doubleEncode.link(pasm());
1084 pasm()->convertUInt32ToDouble(PlatformAssembler::AccumulatorRegisterValue,
1085 PlatformAssembler::FPScratchRegister,
1086 PlatformAssembler::ScratchRegister);
1087 pasm()->encodeDoubleIntoAccumulator(PlatformAssembler::FPScratchRegister);
1091void BaselineAssembler::shr(
int lhs)
1093 PlatformAssembler::Address lhsAddr = regAddr(lhs);
1094 pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister);
1095 pasm()->and32(TrustedImm32(0x1f), PlatformAssembler::AccumulatorRegisterValue);
1096 pasm()->rshift32(PlatformAssembler::AccumulatorRegisterValue, PlatformAssembler::ScratchRegister);
1097 pasm()->move(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
1098 pasm()->setAccumulatorTag(IntegerTag);
1101void BaselineAssembler::shl(
int lhs)
1103 PlatformAssembler::Address lhsAddr = regAddr(lhs);
1104 pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister);
1105 pasm()->and32(TrustedImm32(0x1f), PlatformAssembler::AccumulatorRegisterValue);
1106 pasm()->lshift32(PlatformAssembler::AccumulatorRegisterValue, PlatformAssembler::ScratchRegister);
1107 pasm()->move(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
1108 pasm()->setAccumulatorTag(IntegerTag);
1111void BaselineAssembler::bitAndConst(
int rhs)
1114 pasm()->and32(TrustedImm32(rhs), PlatformAssembler::AccumulatorRegisterValue);
1115 pasm()->setAccumulatorTag(IntegerTag);
1118void BaselineAssembler::bitOrConst(
int rhs)
1121 pasm()->or32(TrustedImm32(rhs), PlatformAssembler::AccumulatorRegisterValue);
1122 pasm()->setAccumulatorTag(IntegerTag);
1125void BaselineAssembler::bitXorConst(
int rhs)
1128 pasm()->xor32(TrustedImm32(rhs), PlatformAssembler::AccumulatorRegisterValue);
1129 pasm()->setAccumulatorTag(IntegerTag);
1132void BaselineAssembler::ushrConst(
int rhs)
1138 pasm()->urshift32(TrustedImm32(rhs), PlatformAssembler::AccumulatorRegisterValue);
1139 pasm()->setAccumulatorTag(IntegerTag);
1142 auto doubleEncode = pasm()->branch32(PlatformAssembler::LessThan,
1143 PlatformAssembler::AccumulatorRegisterValue,
1145 pasm()->setAccumulatorTag(IntegerTag);
1146 auto done = pasm()->jump();
1148 doubleEncode.link(pasm());
1149 pasm()->convertUInt32ToDouble(PlatformAssembler::AccumulatorRegisterValue,
1150 PlatformAssembler::FPScratchRegister,
1151 PlatformAssembler::ScratchRegister);
1152 pasm()->encodeDoubleIntoAccumulator(PlatformAssembler::FPScratchRegister);
1157void BaselineAssembler::shrConst(
int rhs)
1162 pasm()->rshift32(TrustedImm32(rhs), PlatformAssembler::AccumulatorRegisterValue);
1163 pasm()->setAccumulatorTag(IntegerTag);
1166void BaselineAssembler::shlConst(
int rhs)
1171 pasm()->lshift32(TrustedImm32(rhs), PlatformAssembler::AccumulatorRegisterValue);
1172 pasm()->setAccumulatorTag(IntegerTag);
1175void BaselineAssembler::mul(
int lhs)
1177 auto done = pasm()->binopBothIntPath(regAddr(lhs), [
this](){
1178 auto overflowed = pasm()->branchMul32(PlatformAssembler::Overflow,
1179 PlatformAssembler::AccumulatorRegisterValue,
1180 PlatformAssembler::ScratchRegister);
1181 pasm()->setAccumulatorTag(IntegerTag,
1182 PlatformAssembler::ScratchRegister);
1187 saveAccumulatorInFrame();
1188 pasm()->prepareCallWithArgCount(2);
1189 pasm()->passAccumulatorAsArg(1);
1190 pasm()->passJSSlotAsArg(lhs, 0);
1191 ASM_GENERATE_RUNTIME_CALL(Mul, CallResultDestination::InAccumulator);
1198void BaselineAssembler::div(
int lhs)
1200 saveAccumulatorInFrame();
1201 pasm()->prepareCallWithArgCount(2);
1202 pasm()->passAccumulatorAsArg(1);
1203 pasm()->passJSSlotAsArg(lhs, 0);
1204 ASM_GENERATE_RUNTIME_CALL(Div, CallResultDestination::InAccumulator);
1208void BaselineAssembler::mod(
int lhs)
1210 saveAccumulatorInFrame();
1211 pasm()->prepareCallWithArgCount(2);
1212 pasm()->passAccumulatorAsArg(1);
1213 pasm()->passJSSlotAsArg(lhs, 0);
1214 ASM_GENERATE_RUNTIME_CALL(Mod, CallResultDestination::InAccumulator);
1218void BaselineAssembler::sub(
int lhs)
1220 auto done = pasm()->binopBothIntPath(regAddr(lhs), [
this](){
1221 auto overflowed = pasm()->branchSub32(PlatformAssembler::Overflow,
1222 PlatformAssembler::AccumulatorRegisterValue,
1223 PlatformAssembler::ScratchRegister);
1224 pasm()->setAccumulatorTag(IntegerTag,
1225 PlatformAssembler::ScratchRegister);
1230 saveAccumulatorInFrame();
1231 pasm()->prepareCallWithArgCount(2);
1232 pasm()->passAccumulatorAsArg(1);
1233 pasm()->passJSSlotAsArg(lhs, 0);
1234 ASM_GENERATE_RUNTIME_CALL(Sub, CallResultDestination::InAccumulator);
1241void BaselineAssembler::cmpeqNull()
1243 pasm()->isNullOrUndefined();
1244 pasm()->setAccumulatorTag(QV4::Value::ValueTypeInternal::Boolean);
1247void BaselineAssembler::cmpneNull()
1249 pasm()->isNullOrUndefined();
1250 pasm()->xor32(TrustedImm32(1), PlatformAssembler::AccumulatorRegisterValue);
1251 pasm()->setAccumulatorTag(QV4::Value::ValueTypeInternal::Boolean);
1254void BaselineAssembler::cmpeqInt(
int lhs)
1256 auto isIntOrBool = pasm()->isIntOrBool();
1257 saveAccumulatorInFrame();
1258 pasm()->pushValueAligned(Encode(lhs));
1259 if (PlatformAssembler::ArgInRegCount < 2)
1260 pasm()->push(PlatformAssembler::StackPointerRegister);
1262 pasm()->move(PlatformAssembler::StackPointerRegister, pasm()->registerForArg(1));
1263 pasm()->pushAccumulatorAsArg(0);
1264 pasm()->callRuntimeUnchecked((
void*)Runtime::Equal::call);
1265 pasm()->saveReturnValueInAccumulator();
1266 if (PlatformAssembler::ArgInRegCount < 2)
1267 pasm()->addPtr(TrustedImm32(2 * PlatformAssembler::PointerSize), PlatformAssembler::StackPointerRegister);
1268 pasm()->popValueAligned();
1269 auto done = pasm()->jump();
1270 isIntOrBool.link(pasm());
1271 pasm()->compare32(PlatformAssembler::Equal, PlatformAssembler::AccumulatorRegisterValue,
1273 PlatformAssembler::AccumulatorRegisterValue);
1274 pasm()->setAccumulatorTag(QV4::Value::ValueTypeInternal::Boolean);
1278void BaselineAssembler::cmpneInt(
int lhs)
1280 auto isIntOrBool = pasm()->isIntOrBool();
1281 saveAccumulatorInFrame();
1282 pasm()->pushValueAligned(Encode(lhs));
1283 if (PlatformAssembler::ArgInRegCount < 2)
1284 pasm()->push(PlatformAssembler::StackPointerRegister);
1286 pasm()->move(PlatformAssembler::StackPointerRegister, pasm()->registerForArg(1));
1287 pasm()->pushAccumulatorAsArg(0);
1288 pasm()->callRuntimeUnchecked((
void*)Runtime::NotEqual::call);
1289 pasm()->saveReturnValueInAccumulator();
1290 if (PlatformAssembler::ArgInRegCount < 2)
1291 pasm()->addPtr(TrustedImm32(2 * PlatformAssembler::PointerSize), PlatformAssembler::StackPointerRegister);
1292 pasm()->popValueAligned();
1293 auto done = pasm()->jump();
1294 isIntOrBool.link(pasm());
1295 pasm()->compare32(PlatformAssembler::NotEqual, PlatformAssembler::AccumulatorRegisterValue,
1297 PlatformAssembler::AccumulatorRegisterValue);
1298 pasm()->setAccumulatorTag(QV4::Value::ValueTypeInternal::Boolean);
1302void BaselineAssembler::cmp(
int cond, CmpFunc function,
int lhs)
1304 auto c =
static_cast<PlatformAssembler::RelationalCondition>(cond);
1305 auto done = pasm()->binopBothIntPath(regAddr(lhs), [
this, c](){
1306 pasm()->compare32(c, PlatformAssembler::ScratchRegister,
1307 PlatformAssembler::AccumulatorRegisterValue,
1308 PlatformAssembler::AccumulatorRegisterValue);
1309 return PlatformAssembler::Jump();
1313 saveAccumulatorInFrame();
1314 pasm()->prepareCallWithArgCount(2);
1315 pasm()->passAccumulatorAsArg(1);
1316 pasm()->passJSSlotAsArg(lhs, 0);
1318 callRuntime(
reinterpret_cast<
void*>(function), CallResultDestination::InAccumulator);
1323 pasm()->setAccumulatorTag(QV4::Value::ValueTypeInternal::Boolean);
1326void BaselineAssembler::cmpeq(
int lhs)
1328 cmp(PlatformAssembler::Equal, &Runtime::CompareEqual::call, lhs);
1331void BaselineAssembler::cmpne(
int lhs)
1333 cmp(PlatformAssembler::NotEqual, &Runtime::CompareNotEqual::call, lhs);
1336void BaselineAssembler::cmpgt(
int lhs)
1338 cmp(PlatformAssembler::GreaterThan, &Runtime::CompareGreaterThan::call, lhs);
1341void BaselineAssembler::cmpge(
int lhs)
1343 cmp(PlatformAssembler::GreaterThanOrEqual, &Runtime::CompareGreaterEqual::call, lhs);
1346void BaselineAssembler::cmplt(
int lhs)
1348 cmp(PlatformAssembler::LessThan, &Runtime::CompareLessThan::call, lhs);
1351void BaselineAssembler::cmple(
int lhs)
1353 cmp(PlatformAssembler::LessThanOrEqual, &Runtime::CompareLessEqual::call, lhs);
1356void BaselineAssembler::cmpStrictEqual(
int lhs)
1358 cmp(PlatformAssembler::Equal, &Runtime::CompareStrictEqual::call, lhs);
1361void BaselineAssembler::cmpStrictNotEqual(
int lhs)
1363 cmp(PlatformAssembler::NotEqual, &Runtime::CompareStrictNotEqual::call, lhs);
1366int BaselineAssembler::jump(
int offset)
1368 pasm()->addJumpToOffset(pasm()->jump(), offset);
1372int BaselineAssembler::jumpTrue(
int offset)
1374 pasm()->toBoolean([
this, offset](PlatformAssembler::RegisterID resultReg) {
1375 auto jump = pasm()->branch32(PlatformAssembler::NotEqual, TrustedImm32(0), resultReg);
1376 pasm()->addJumpToOffset(jump, offset);
1381int BaselineAssembler::jumpFalse(
int offset)
1383 pasm()->toBoolean([
this, offset](PlatformAssembler::RegisterID resultReg) {
1384 auto jump = pasm()->branch32(PlatformAssembler::Equal, TrustedImm32(0), resultReg);
1385 pasm()->addJumpToOffset(jump, offset);
1390int BaselineAssembler::jumpNoException(
int offset)
1392 auto jump = pasm()->branch32(
1393 PlatformAssembler::Equal,
1394 PlatformAssembler::Address(PlatformAssembler::EngineRegister,
1395 offsetof(EngineBase, hasException)),
1397 pasm()->addJumpToOffset(jump, offset);
1401int BaselineAssembler::jumpNotUndefined(
int offset)
1403 pasm()->jumpNotUndefined(offset);
1407int BaselineAssembler::jumpEqNull(
int offset)
1409 saveAccumulatorInFrame();
1412 pasm()->toBoolean([
this, offset](PlatformAssembler::RegisterID resultReg) {
1413 auto isFalse = pasm()->branch32(PlatformAssembler::Equal, TrustedImm32(0), resultReg);
1414 loadValue(Encode::undefined());
1415 pasm()->addJumpToOffset(pasm()->jump(), offset);
1416 isFalse.link(pasm());
1417 loadAccumulatorFromFrame();
1424void BaselineAssembler::prepareCallWithArgCount(
int argc)
1426 pasm()->prepareCallWithArgCount(argc);
1429void BaselineAssembler::storeInstructionPointer(
int instructionOffset)
1431 pasm()->storeInstructionPointer(instructionOffset);
1434void BaselineAssembler::passAccumulatorAsArg(
int arg)
1436 pasm()->passAccumulatorAsArg(arg);
1439void BaselineAssembler::passFunctionAsArg(
int arg)
1441 pasm()->passFunctionAsArg(arg);
1444void BaselineAssembler::passEngineAsArg(
int arg)
1446 pasm()->passEngineAsArg(arg);
1449void BaselineAssembler::passJSSlotAsArg(
int reg,
int arg)
1451 pasm()->passJSSlotAsArg(reg, arg);
1454void BaselineAssembler::passCppFrameAsArg(
int arg)
1456 pasm()->passCppFrameAsArg(arg);
1459void BaselineAssembler::passInt32AsArg(
int value,
int arg)
1461 pasm()->passInt32AsArg(value, arg);
1464void BaselineAssembler::passPointerAsArg(
void *ptr,
int arg)
1466 pasm()->passPointerAsArg(ptr, arg);
1469void BaselineAssembler::callRuntime(
const void *funcPtr, CallResultDestination dest)
1471 pasm()->callRuntime(funcPtr, dest);
1474void BaselineAssembler::saveAccumulatorInFrame()
1476 pasm()->storeAccumulator(PlatformAssembler::Address(PlatformAssembler::JSStackFrameRegister,
1477 offsetof(CallData, accumulator)));
1480void BaselineAssembler::loadAccumulatorFromFrame()
1482 pasm()->loadAccumulator(PlatformAssembler::Address(PlatformAssembler::JSStackFrameRegister,
1483 offsetof(CallData, accumulator)));
1486static ReturnedValue TheJitIs__Tail_Calling__ToTheRuntimeSoTheJitFrameIsMissing(JSTypesStackFrame *frame, ExecutionEngine *engine)
1488 return Runtime::TailCall::call(frame, engine);
1491void BaselineAssembler::jsTailCall(
int func,
int thisObject,
int argc,
int argv)
1493 Address tos = pasm()->jsAlloca(4);
1495 int32_t argcOffset = tos.offset + int32_t(
sizeof(Value)) * Runtime::StackOffsets::tailCall_argc;
1496 int32_t argvOffset = tos.offset + int32_t(
sizeof(Value)) * Runtime::StackOffsets::tailCall_argv;
1497 int32_t thisOffset = tos.offset + int32_t(
sizeof(Value)) * Runtime::StackOffsets::tailCall_thisObject;
1498 int32_t funcOffset = tos.offset + int32_t(
sizeof(Value)) * Runtime::StackOffsets::tailCall_function;
1500 pasm()->storeInt32AsValue(argc, Address(tos.base, argcOffset));
1501 pasm()->storeInt32AsValue(argv, Address(tos.base, argvOffset));
1502 pasm()->moveReg(regAddr(thisObject), Address(tos.base, thisOffset));
1503 pasm()->moveReg(regAddr(func), Address(tos.base, funcOffset));
1504 pasm()->tailCallRuntime(
1505 reinterpret_cast<
void *>(TheJitIs__Tail_Calling__ToTheRuntimeSoTheJitFrameIsMissing),
1506 "TheJitIs__Tail_Calling__ToTheRuntimeSoTheJitFrameIsMissing");
1509void BaselineAssembler::checkException()
1511 pasm()->checkException();
1514void BaselineAssembler::gotoCatchException()
1516 pasm()->addCatchyJump(pasm()->jump());
1519void BaselineAssembler::getException()
1521 Q_STATIC_ASSERT(
sizeof(QV4::EngineBase::hasException) == 1);
1523 Address hasExceptionAddr(PlatformAssembler::EngineRegister,
1524 offsetof(EngineBase, hasException));
1525 PlatformAssembler::Jump nope = pasm()->branch8(PlatformAssembler::Equal,
1528 pasm()->loadPtr(Address(PlatformAssembler::EngineRegister,
1529 offsetof(EngineBase, exceptionValue)),
1530 PlatformAssembler::ScratchRegister);
1531 pasm()->loadAccumulator(Address(PlatformAssembler::ScratchRegister));
1532 pasm()->store8(TrustedImm32(0), hasExceptionAddr);
1533 auto done = pasm()->jump();
1535 pasm()->loadValue(Value::emptyValue().asReturnedValue());
1540void BaselineAssembler::setException()
1542 auto noException = pasm()->jumpEmpty();
1543 Address addr(PlatformAssembler::EngineRegister, offsetof(EngineBase, exceptionValue));
1544 pasm()->loadPtr(addr, PlatformAssembler::ScratchRegister);
1545 pasm()->storeAccumulator(Address(PlatformAssembler::ScratchRegister));
1546 addr.offset = offsetof(EngineBase, hasException);
1547 Q_STATIC_ASSERT(
sizeof(QV4::EngineBase::hasException) == 1);
1548 pasm()->store8(TrustedImm32(1), addr);
1549 noException.link(pasm());
1552int BaselineAssembler::setUnwindHandler(
int offset)
1554 auto l = pasm()->storePtrWithPatch(TrustedImmPtr(
nullptr), pasm()->exceptionHandlerAddress());
1555 pasm()->addEHTarget(l, offset);
1560void BaselineAssembler::clearUnwindHandler()
1562 pasm()->storePtr(TrustedImmPtr(
nullptr), pasm()->exceptionHandlerAddress());
1565void JIT::BaselineAssembler::unwindDispatch()
1568 pasm()->load32(Address(PlatformAssembler::CppStackFrameRegister, offsetof(JSTypesStackFrame, unwindLevel)), PlatformAssembler::ScratchRegister);
1569 auto noUnwind = pasm()->branch32(PlatformAssembler::Equal, PlatformAssembler::ScratchRegister, TrustedImm32(0));
1570 pasm()->sub32(TrustedImm32(1), PlatformAssembler::ScratchRegister);
1571 pasm()->store32(PlatformAssembler::ScratchRegister, Address(PlatformAssembler::CppStackFrameRegister, offsetof(JSTypesStackFrame, unwindLevel)));
1572 auto jump = pasm()->branch32(PlatformAssembler::Equal, PlatformAssembler::ScratchRegister, TrustedImm32(0));
1573 gotoCatchException();
1576 pasm()->loadPtr(Address(PlatformAssembler::CppStackFrameRegister, offsetof(JSTypesStackFrame, unwindLabel)), PlatformAssembler::ScratchRegister);
1577 pasm()->jump(PlatformAssembler::ScratchRegister);
1579 noUnwind.link(pasm());
1582int JIT::BaselineAssembler::unwindToLabel(
int level,
int offset)
1584 auto l = pasm()->storePtrWithPatch(TrustedImmPtr(
nullptr), Address(PlatformAssembler::CppStackFrameRegister, offsetof(JSTypesStackFrame, unwindLabel)));
1585 pasm()->addEHTarget(l, offset);
1586 pasm()->store32(TrustedImm32(level), Address(PlatformAssembler::CppStackFrameRegister, offsetof(JSTypesStackFrame, unwindLevel)));
1587 gotoCatchException();
1591void BaselineAssembler::pushCatchContext(
int index,
int name)
1593 pasm()->prepareCallWithArgCount(3);
1594 pasm()->passInt32AsArg(name, 2);
1595 pasm()->passInt32AsArg(index, 1);
1596 pasm()->passEngineAsArg(0);
1597 ASM_GENERATE_RUNTIME_CALL(PushCatchContext, CallResultDestination::Ignore);
1600void BaselineAssembler::popContext()
1602 Heap::CallContext ctx;
1604 pasm()->loadPointerFromValue(regAddr(CallData::Context), PlatformAssembler::ScratchRegister);
1605 pasm()->loadPtr(Address(PlatformAssembler::ScratchRegister, ctx.outer.offset), PlatformAssembler::ScratchRegister);
1606 pasm()->storeHeapObject(PlatformAssembler::ScratchRegister, regAddr(CallData::Context));
1609void BaselineAssembler::deadTemporalZoneCheck(
int offsetForSavedIP,
int variableName)
1611 auto valueIsAliveJump = pasm()->jumpNotEmpty();
1612 storeInstructionPointer(offsetForSavedIP);
1613 prepareCallWithArgCount(2);
1614 passInt32AsArg(variableName, 1);
1616 ASM_GENERATE_RUNTIME_CALL(ThrowReferenceError, CallResultDestination::Ignore);
1617 gotoCatchException();
1618 valueIsAliveJump.link(pasm());
1621void BaselineAssembler::ret()
1623 pasm()->generateFunctionExit();