1 # Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved.
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions
6 # 1. Redistributions of source code must retain the above copyright
7 # notice, this list of conditions and the following disclaimer.
8 # 2. Redistributions in binary form must reproduce the above copyright
9 # notice, this list of conditions and the following disclaimer in the
10 # documentation and/or other materials provided with the distribution.
12 # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
13 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
14 # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
15 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
16 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
17 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
18 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
19 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
20 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
21 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
22 # THE POSSIBILITY OF SUCH DAMAGE.
26 macro jumpToInstruction()
30 macro dispatch(advance)
35 macro dispatchInt(advance)
40 macro dispatchIntIndirect(offset)
41 dispatchInt(offset * 8[PB, PC, 8])
44 macro dispatchAfterCall()
45 loadi ArgumentCount + TagOffset[cfr], PC
46 loadp CodeBlock[cfr], PB
47 loadp CodeBlock::m_instructions[PB], PB
48 loadisFromInstruction(1, t1)
49 storeq t0, [cfr, t1, 8]
50 valueProfile(t0, (CallOpCodeSize - 1), t2)
51 dispatch(CallOpCodeSize)
54 macro cCall2(function, arg1, arg2)
55 checkStackPointerAlignment(t4, 0xbad0c002)
61 # Note: this implementation is only correct if the return type size is > 8 bytes.
62 # See macro cCall2Void for an implementation when the return type <= 8 bytes.
63 # On Win64, when the return type is larger than 8 bytes, we need to allocate space on the stack for the return value.
64 # On entry rcx (t2), should contain a pointer to this stack space. The other parameters are shifted to the right,
65 # rdx (t1) should contain the first argument, and r8 (t6) should contain the second argument.
66 # On return, rax contains a pointer to this stack value, and we then need to copy the 16 byte return value into rax (t0) and rdx (t1)
67 # since the return value is expected to be split between the two.
68 # See http://msdn.microsoft.com/en-us/library/7572ztz4.aspx
83 cloopCallSlowPath function, arg1, arg2
89 macro cCall2Void(function, arg1, arg2)
91 cloopCallSlowPathVoid function, arg1, arg2
93 # Note: we cannot use the cCall2 macro for Win64 in this case,
94 # as the Win64 cCall2 implemenation is only correct when the return type size is > 8 bytes.
95 # On Win64, rcx and rdx are used for passing the first two parameters.
96 # We also need to make room on the stack for all four parameter registers.
97 # See http://msdn.microsoft.com/en-us/library/ms235286.aspx
104 cCall2(function, arg1, arg2)
108 # This barely works. arg3 and arg4 should probably be immediates.
109 macro cCall4(function, arg1, arg2, arg3, arg4)
110 checkStackPointerAlignment(t4, 0xbad0c004)
118 # On Win64, rcx, rdx, r8, and r9 are used for passing the first four parameters.
119 # We also need to make room on the stack for all four parameter registers.
120 # See http://msdn.microsoft.com/en-us/library/ms235286.aspx
141 macro doCallToJavaScript(makeCall)
145 const protoCallFrame = t1
147 const previousCFR = t0
148 const previousPC = t6
155 const protoCallFrame = t6
157 const previousCFR = t0
158 const previousPC = t4
162 elsif ARM64 or C_LOOP
165 const protoCallFrame = a2
167 const previousCFR = t5
168 const previousPC = lr
174 callToJavaScriptPrologue()
177 loadp 7*8[sp], previousPC
178 move 6*8[sp], previousCFR
180 # Win64 pushes two more registers
181 loadp 9*8[sp], previousPC
182 move 8*8[sp], previousCFR
184 move cfr, previousCFR
187 checkStackPointerAlignment(temp2, 0xbad0dc01)
189 # The stack reserved zone ensures that we have adequate space for the
190 # VMEntrySentinelFrame. Proceed with allocating and initializing the
193 subp CallFrameHeaderSlots * 8, cfr
194 storep 0, ArgumentCount[cfr]
195 storep vm, Callee[cfr]
196 loadp VM::topCallFrame[vm], temp2
197 storep temp2, ScopeChain[cfr]
198 storep 1, CodeBlock[cfr]
200 storep previousPC, ReturnPC[cfr]
201 storep previousCFR, CallerFrame[cfr]
203 loadi ProtoCallFrame::paddedArgCount[protoCallFrame], temp2
204 addp CallFrameHeaderSlots, temp2, temp2
206 subp cfr, temp2, temp1
208 # Ensure that we have enough additional stack capacity for the incoming args,
209 # and the frame for the JS code we're executing. We need to do this check
210 # before we start copying the args from the protoCallFrame below.
211 bpaeq temp1, VM::m_jsStackLimit[vm], .stackHeightOK
218 cloopCallSlowPath _llint_stack_check_at_vm_entry, vm, temp1
219 bpeq t0, 0, .stackCheckFailed
229 cCall2(_llint_throw_stack_overflow_error, vm, protoCallFrame)
230 callToJavaScriptEpilogue()
239 loadq [protoCallFrame, temp1, 8], temp3
240 storeq temp3, CodeBlock[sp, temp1, 8]
241 btinz temp1, .copyHeaderLoop
243 loadi PayloadOffset + ProtoCallFrame::argCountAndCodeOriginValue[protoCallFrame], temp2
245 loadi ProtoCallFrame::paddedArgCount[protoCallFrame], temp3
248 bieq temp2, temp3, .copyArgs
249 move ValueUndefined, temp1
252 storeq temp1, ThisArgumentOffset + 8[sp, temp3, 8]
253 bineq temp2, temp3, .fillExtraArgsLoop
256 loadp ProtoCallFrame::args[protoCallFrame], temp1
259 btiz temp2, .copyArgsDone
261 loadq [temp1, temp2, 8], temp3
262 storeq temp3, ThisArgumentOffset + 8[sp, temp2, 8]
268 storep temp2, VM::topCallFrame[vm]
270 storep sp, VM::topCallFrame[vm]
273 move 0xffff000000000000, csr1
276 checkStackPointerAlignment(temp3, 0xbad0dc02)
278 makeCall(entry, temp1)
280 checkStackPointerAlignment(temp3, 0xbad0dc03)
282 bpeq CodeBlock[cfr], 1, .calleeFramePopped
283 loadp CallerFrame[cfr], cfr
286 loadp Callee[cfr], temp2 # VM
287 loadp ScopeChain[cfr], temp3 # previous topCallFrame
288 storep temp3, VM::topCallFrame[temp2]
290 checkStackPointerAlignment(temp3, 0xbad0dc04)
292 if X86_64 or X86_64_WIN
295 callToJavaScriptEpilogue()
301 macro makeJavaScriptCall(entry, temp)
304 cloopCallJSFunction entry
312 macro makeHostFunctionCall(entry, temp)
318 elsif ARM64 or C_LOOP
326 # For a host function call, JIT relies on that the CallerFrame (frame pointer) is put on the stack,
327 # On Win64 we need to manually copy the frame pointer to the stack, since MSVC may not maintain a frame pointer on 64-bit.
328 # See http://msdn.microsoft.com/en-us/library/9z1stfyw.aspx where it's stated that rbp MAY be used as a frame pointer.
331 # We need to allocate 32 bytes on the stack for the shadow space.
343 _handleUncaughtException:
344 loadp ScopeChain[cfr], t3
345 andp MarkedBlockMask, t3
346 loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
347 loadp VM::callFrameForThrow[t3], cfr
349 # So far, we've unwound the stack to the frame just below the sentinel frame, except
350 # in the case of stack overflow in the first function called from callToJavaScript.
351 # Check if we need to pop to the sentinel frame and do the necessary clean up for
352 # returning to the caller C frame.
353 bpeq CodeBlock[cfr], 1, .handleUncaughtExceptionAlreadyIsSentinel
354 loadp CallerFrame[cfr], cfr
355 .handleUncaughtExceptionAlreadyIsSentinel:
357 loadp Callee[cfr], t3 # VM
358 loadp ScopeChain[cfr], t5 # previous topCallFrame
359 storep t5, VM::topCallFrame[t3]
361 callToJavaScriptEpilogue()
365 macro prepareStateForCCall()
370 macro restoreStateAfterCCall()
377 macro callSlowPath(slowPath)
378 prepareStateForCCall()
379 cCall2(slowPath, cfr, PC)
380 restoreStateAfterCCall()
383 macro traceOperand(fromWhere, operand)
384 prepareStateForCCall()
385 cCall4(_llint_trace_operand, cfr, PC, fromWhere, operand)
386 restoreStateAfterCCall()
389 macro traceValue(fromWhere, operand)
390 prepareStateForCCall()
391 cCall4(_llint_trace_value, cfr, PC, fromWhere, operand)
392 restoreStateAfterCCall()
395 # Call a slow path for call call opcodes.
396 macro callCallSlowPath(slowPath, action)
397 storei PC, ArgumentCount + TagOffset[cfr]
398 prepareStateForCCall()
399 cCall2(slowPath, cfr, PC)
403 macro callWatchdogTimerHandler(throwHandler)
404 storei PC, ArgumentCount + TagOffset[cfr]
405 prepareStateForCCall()
406 cCall2(_llint_slow_path_handle_watchdog_timer, cfr, PC)
407 btpnz t0, throwHandler
409 loadi ArgumentCount + TagOffset[cfr], PC
412 macro checkSwitchToJITForLoop()
416 storei PC, ArgumentCount + TagOffset[cfr]
417 prepareStateForCCall()
418 cCall2(_llint_loop_osr, cfr, PC)
424 loadi ArgumentCount + TagOffset[cfr], PC
428 macro loadVariable(operand, value)
429 loadisFromInstruction(operand, value)
430 loadq [cfr, value, 8], value
433 # Index and value must be different registers. Index may be clobbered.
434 macro loadConstantOrVariable(index, value)
435 bpgteq index, FirstConstantRegisterIndex, .constant
436 loadq [cfr, index, 8], value
439 loadp CodeBlock[cfr], value
440 loadp CodeBlock::m_constantRegisters + VectorBufferOffset[value], value
441 subp FirstConstantRegisterIndex, index
442 loadq [value, index, 8], value
446 macro loadConstantOrVariableInt32(index, value, slow)
447 loadConstantOrVariable(index, value)
448 bqb value, tagTypeNumber, slow
451 macro loadConstantOrVariableCell(index, value, slow)
452 loadConstantOrVariable(index, value)
453 btqnz value, tagMask, slow
456 macro writeBarrierOnOperand(cellOperand)
458 loadisFromInstruction(cellOperand, t1)
459 loadConstantOrVariableCell(t1, t2, .writeBarrierDone)
460 checkMarkByte(t2, t1, t3,
462 btbnz gcData, .writeBarrierDone
464 cCall2Void(_llint_write_barrier_slow, cfr, t2)
472 macro writeBarrierOnOperands(cellOperand, valueOperand)
474 loadisFromInstruction(valueOperand, t1)
475 loadConstantOrVariableCell(t1, t0, .writeBarrierDone)
476 btpz t0, .writeBarrierDone
478 writeBarrierOnOperand(cellOperand)
483 macro writeBarrierOnGlobalObject(valueOperand)
485 loadisFromInstruction(valueOperand, t1)
486 loadConstantOrVariableCell(t1, t0, .writeBarrierDone)
487 btpz t0, .writeBarrierDone
489 loadp CodeBlock[cfr], t3
490 loadp CodeBlock::m_globalObject[t3], t3
491 checkMarkByte(t3, t1, t2,
493 btbnz gcData, .writeBarrierDone
495 cCall2Void(_llint_write_barrier_slow, cfr, t3)
503 macro valueProfile(value, operand, scratch)
504 loadpFromInstruction(operand, scratch)
505 storeq value, ValueProfile::m_buckets[scratch]
508 macro loadStructure(cell, structure)
511 macro loadStructureWithScratch(cell, structure, scratch)
512 loadp CodeBlock[cfr], scratch
513 loadp CodeBlock::m_vm[scratch], scratch
514 loadp VM::heap + Heap::m_structureIDTable + StructureIDTable::m_table[scratch], scratch
515 loadi JSCell::m_structureID[cell], structure
516 loadp [scratch, structure, 8], structure
519 macro loadStructureAndClobberFirstArg(cell, structure)
520 loadi JSCell::m_structureID[cell], structure
521 loadp CodeBlock[cfr], cell
522 loadp CodeBlock::m_vm[cell], cell
523 loadp VM::heap + Heap::m_structureIDTable + StructureIDTable::m_table[cell], cell
524 loadp [cell, structure, 8], structure
527 macro storeStructureWithTypeInfo(cell, structure, scratch)
528 loadq Structure::m_blob + StructureIDBlob::u.doubleWord[structure], scratch
529 storeq scratch, JSCell::m_structureID[cell]
532 # Entrypoints into the interpreter.
534 # Expects that CodeBlock is in t1, which is what prologue() leaves behind.
535 macro functionArityCheck(doneLabel, slowPath)
536 loadi PayloadOffset + ArgumentCount[cfr], t0
537 biaeq t0, CodeBlock::m_numParameters[t1], doneLabel
538 prepareStateForCCall()
539 cCall2(slowPath, cfr, PC) # This slowPath has the protocol: t0 = 0 => no error, t0 != 0 => error
541 move t1, cfr # t1 contains caller frame
542 jmp _llint_throw_from_slow_path_trampoline
545 # t1 points to ArityCheckData.
546 loadp CommonSlowPaths::ArityCheckData::thunkToCall[t1], t2
547 btpz t2, .proceedInline
549 loadp CommonSlowPaths::ArityCheckData::returnPC[t1], t7
550 loadp CommonSlowPaths::ArityCheckData::paddedStackSpace[t1], t0
553 loadp ReturnPC[cfr], t0
559 loadi CommonSlowPaths::ArityCheckData::paddedStackSpace[t1], t1
562 // Move frame up "t1 * 2" slots
566 loadi PayloadOffset + ArgumentCount[cfr], t2
567 addi CallFrameHeaderSlots, t2
570 storeq t0, [t3, t1, 8]
572 bsubinz 1, t2, .copyLoop
574 // Fill new slots with JSUndefined
576 move ValueUndefined, t0
578 storeq t0, [t3, t1, 8]
580 baddinz 1, t2, .fillLoop
587 # Reload CodeBlock and reset PC, since the slow_path clobbered them.
588 loadp CodeBlock[cfr], t1
589 loadp CodeBlock::m_instructions[t1], PB
594 macro branchIfException(label)
595 loadp ScopeChain[cfr], t3
596 andp MarkedBlockMask, t3
597 loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
598 btqz VM::m_exception[t3], .noException
604 # Instruction implementations
608 checkStackPointerAlignment(t2, 0xdead00e1)
609 loadp CodeBlock[cfr], t2 // t2<CodeBlock> = cfr.CodeBlock
610 loadi CodeBlock::m_numVars[t2], t2 // t2<size_t> = t2<CodeBlock>.m_numVars
611 btiz t2, .opEnterDone
612 move ValueUndefined, t0
616 storeq t0, [cfr, t2, 8]
618 btqnz t2, .opEnterLoop
620 callSlowPath(_slow_path_enter)
624 _llint_op_create_activation:
626 loadisFromInstruction(1, t0)
627 bqneq [cfr, t0, 8], ValueEmpty, .opCreateActivationDone
628 callSlowPath(_llint_slow_path_create_activation)
629 .opCreateActivationDone:
633 _llint_op_init_lazy_reg:
635 loadisFromInstruction(1, t0)
636 storeq ValueEmpty, [cfr, t0, 8]
640 _llint_op_create_arguments:
642 loadisFromInstruction(1, t0)
643 bqneq [cfr, t0, 8], ValueEmpty, .opCreateArgumentsDone
644 callSlowPath(_slow_path_create_arguments)
645 .opCreateArgumentsDone:
649 _llint_op_create_this:
651 loadisFromInstruction(2, t0)
652 loadp [cfr, t0, 8], t0
653 loadp JSFunction::m_allocationProfile + ObjectAllocationProfile::m_allocator[t0], t1
654 loadp JSFunction::m_allocationProfile + ObjectAllocationProfile::m_structure[t0], t2
655 btpz t1, .opCreateThisSlow
656 allocateJSObject(t1, t2, t0, t3, .opCreateThisSlow)
657 loadisFromInstruction(1, t1)
658 storeq t0, [cfr, t1, 8]
662 callSlowPath(_slow_path_create_this)
666 _llint_op_get_callee:
668 loadisFromInstruction(1, t0)
669 loadp Callee[cfr], t1
670 loadpFromInstruction(2, t2)
671 bpneq t1, t2, .opGetCalleeSlow
672 storep t1, [cfr, t0, 8]
676 callSlowPath(_slow_path_get_callee)
681 loadisFromInstruction(1, t0)
682 loadq [cfr, t0, 8], t0
683 btqnz t0, tagMask, .opToThisSlow
684 bbneq JSCell::m_type[t0], FinalObjectType, .opToThisSlow
685 loadStructureWithScratch(t0, t1, t2)
686 loadpFromInstruction(2, t2)
687 bpneq t1, t2, .opToThisSlow
691 callSlowPath(_slow_path_to_this)
695 _llint_op_new_object:
697 loadpFromInstruction(3, t0)
698 loadp ObjectAllocationProfile::m_allocator[t0], t1
699 loadp ObjectAllocationProfile::m_structure[t0], t2
700 allocateJSObject(t1, t2, t0, t3, .opNewObjectSlow)
701 loadisFromInstruction(1, t1)
702 storeq t0, [cfr, t1, 8]
706 callSlowPath(_llint_slow_path_new_object)
712 loadisFromInstruction(2, t1)
713 loadisFromInstruction(1, t0)
714 loadConstantOrVariable(t1, t2)
715 storeq t2, [cfr, t0, 8]
719 macro notifyWrite(set, value, scratch, slow)
720 loadb VariableWatchpointSet::m_state[set], scratch
721 bieq scratch, IsInvalidated, .done
722 bqneq value, VariableWatchpointSet::m_inferredValue[set], slow
726 _llint_op_captured_mov:
728 loadisFromInstruction(2, t1)
729 loadConstantOrVariable(t1, t2)
730 loadpFromInstruction(3, t0)
731 btpz t0, .opCapturedMovReady
732 notifyWrite(t0, t2, t1, .opCapturedMovSlow)
734 loadisFromInstruction(1, t0)
735 storeq t2, [cfr, t0, 8]
739 callSlowPath(_slow_path_captured_mov)
745 loadisFromInstruction(2, t0)
746 loadisFromInstruction(1, t1)
747 loadConstantOrVariable(t0, t2)
749 btqnz t2, ~1, .opNotSlow
751 storeq t2, [cfr, t1, 8]
755 callSlowPath(_slow_path_not)
759 macro equalityComparison(integerComparison, slowPath)
761 loadisFromInstruction(3, t0)
762 loadisFromInstruction(2, t2)
763 loadisFromInstruction(1, t3)
764 loadConstantOrVariableInt32(t0, t1, .slow)
765 loadConstantOrVariableInt32(t2, t0, .slow)
766 integerComparison(t0, t1, t0)
768 storeq t0, [cfr, t3, 8]
772 callSlowPath(slowPath)
778 macro (left, right, result) cieq left, right, result end,
784 macro (left, right, result) cineq left, right, result end,
788 macro equalNullComparison()
789 loadisFromInstruction(2, t0)
790 loadq [cfr, t0, 8], t0
791 btqnz t0, tagMask, .immediate
792 btbnz JSCell::m_flags[t0], MasqueradesAsUndefined, .masqueradesAsUndefined
795 .masqueradesAsUndefined:
796 loadStructureWithScratch(t0, t2, t1)
797 loadp CodeBlock[cfr], t0
798 loadp CodeBlock::m_globalObject[t0], t0
799 cpeq Structure::m_globalObject[t2], t0, t0
802 andq ~TagBitUndefined, t0
803 cqeq t0, ValueNull, t0
809 equalNullComparison()
810 loadisFromInstruction(1, t1)
812 storeq t0, [cfr, t1, 8]
818 equalNullComparison()
819 loadisFromInstruction(1, t1)
821 storeq t0, [cfr, t1, 8]
825 macro strictEq(equalityOperation, slowPath)
827 loadisFromInstruction(3, t0)
828 loadisFromInstruction(2, t2)
829 loadConstantOrVariable(t0, t1)
830 loadConstantOrVariable(t2, t0)
833 btqz t2, tagMask, .slow
834 bqaeq t0, tagTypeNumber, .leftOK
835 btqnz t0, tagTypeNumber, .slow
837 bqaeq t1, tagTypeNumber, .rightOK
838 btqnz t1, tagTypeNumber, .slow
840 equalityOperation(t0, t1, t0)
841 loadisFromInstruction(1, t1)
843 storeq t0, [cfr, t1, 8]
847 callSlowPath(slowPath)
853 macro (left, right, result) cqeq left, right, result end,
859 macro (left, right, result) cqneq left, right, result end,
860 _slow_path_nstricteq)
863 macro preOp(arithmeticOperation, slowPath)
865 loadisFromInstruction(1, t0)
866 loadq [cfr, t0, 8], t1
867 bqb t1, tagTypeNumber, .slow
868 arithmeticOperation(t1, .slow)
869 orq tagTypeNumber, t1
870 storeq t1, [cfr, t0, 8]
874 callSlowPath(slowPath)
880 macro (value, slow) baddio 1, value, slow end,
886 macro (value, slow) bsubio 1, value, slow end,
892 loadisFromInstruction(2, t0)
893 loadisFromInstruction(1, t1)
894 loadConstantOrVariable(t0, t2)
895 bqaeq t2, tagTypeNumber, .opToNumberIsImmediate
896 btqz t2, tagTypeNumber, .opToNumberSlow
897 .opToNumberIsImmediate:
898 storeq t2, [cfr, t1, 8]
902 callSlowPath(_slow_path_to_number)
908 loadisFromInstruction(2, t0)
909 loadisFromInstruction(1, t1)
910 loadConstantOrVariable(t0, t2)
911 bqb t2, tagTypeNumber, .opNegateNotInt
912 btiz t2, 0x7fffffff, .opNegateSlow
914 orq tagTypeNumber, t2
915 storeq t2, [cfr, t1, 8]
918 btqz t2, tagTypeNumber, .opNegateSlow
919 xorq 0x8000000000000000, t2
920 storeq t2, [cfr, t1, 8]
924 callSlowPath(_slow_path_negate)
928 macro binaryOpCustomStore(integerOperationAndStore, doubleOperation, slowPath)
929 loadisFromInstruction(3, t0)
930 loadisFromInstruction(2, t2)
931 loadConstantOrVariable(t0, t1)
932 loadConstantOrVariable(t2, t0)
933 bqb t0, tagTypeNumber, .op1NotInt
934 bqb t1, tagTypeNumber, .op2NotInt
935 loadisFromInstruction(1, t2)
936 integerOperationAndStore(t1, t0, .slow, t2)
940 # First operand is definitely not an int, the second operand could be anything.
941 btqz t0, tagTypeNumber, .slow
942 bqaeq t1, tagTypeNumber, .op1NotIntOp2Int
943 btqz t1, tagTypeNumber, .slow
944 addq tagTypeNumber, t1
950 loadisFromInstruction(1, t2)
951 addq tagTypeNumber, t0
953 doubleOperation(ft1, ft0)
955 subq tagTypeNumber, t0
956 storeq t0, [cfr, t2, 8]
960 # First operand is definitely an int, the second is definitely not.
961 loadisFromInstruction(1, t2)
962 btqz t1, tagTypeNumber, .slow
964 addq tagTypeNumber, t1
966 doubleOperation(ft1, ft0)
968 subq tagTypeNumber, t0
969 storeq t0, [cfr, t2, 8]
973 callSlowPath(slowPath)
977 macro binaryOp(integerOperation, doubleOperation, slowPath)
979 macro (left, right, slow, index)
980 integerOperation(left, right, slow)
981 orq tagTypeNumber, right
982 storeq right, [cfr, index, 8]
984 doubleOperation, slowPath)
990 macro (left, right, slow) baddio left, right, slow end,
991 macro (left, right) addd left, right end,
998 macro (left, right, slow, index)
999 # Assume t3 is scratchable.
1001 bmulio left, t3, slow
1006 orq tagTypeNumber, t3
1007 storeq t3, [cfr, index, 8]
1009 macro (left, right) muld left, right end,
1016 macro (left, right, slow) bsubio left, right, slow end,
1017 macro (left, right) subd left, right end,
1023 if X86_64 or X86_64_WIN
1024 binaryOpCustomStore(
1025 macro (left, right, slow, index)
1026 # Assume t3 is scratchable.
1028 bineq left, -1, .notNeg2TwoThe31DivByNeg1
1029 bieq right, -2147483648, .slow
1030 .notNeg2TwoThe31DivByNeg1:
1039 orq tagTypeNumber, t0
1040 storeq t0, [cfr, index, 8]
1042 macro (left, right) divd left, right end,
1045 callSlowPath(_slow_path_div)
1050 macro bitOp(operation, slowPath, advance)
1051 loadisFromInstruction(3, t0)
1052 loadisFromInstruction(2, t2)
1053 loadisFromInstruction(1, t3)
1054 loadConstantOrVariable(t0, t1)
1055 loadConstantOrVariable(t2, t0)
1056 bqb t0, tagTypeNumber, .slow
1057 bqb t1, tagTypeNumber, .slow
1059 orq tagTypeNumber, t0
1060 storeq t0, [cfr, t3, 8]
1064 callSlowPath(slowPath)
1071 macro (left, right) lshifti left, right end,
1079 macro (left, right) rshifti left, right end,
1087 macro (left, right) urshifti left, right end,
1094 loadisFromInstruction(1, t0)
1095 loadisFromInstruction(2, t1)
1096 loadConstantOrVariable(t1, t2)
1097 bilt t2, 0, .opUnsignedSlow
1098 storeq t2, [cfr, t0, 8]
1101 callSlowPath(_slow_path_unsigned)
1108 macro (left, right) andi left, right end,
1116 macro (left, right) xori left, right end,
1124 macro (left, right) ori left, right end,
1129 _llint_op_check_has_instance:
1131 loadisFromInstruction(3, t1)
1132 loadConstantOrVariableCell(t1, t0, .opCheckHasInstanceSlow)
1133 btbz JSCell::m_flags[t0], ImplementsDefaultHasInstance, .opCheckHasInstanceSlow
1136 .opCheckHasInstanceSlow:
1137 callSlowPath(_llint_slow_path_check_has_instance)
1141 _llint_op_instanceof:
1143 # Actually do the work.
1144 loadisFromInstruction(3, t0)
1145 loadConstantOrVariableCell(t0, t1, .opInstanceofSlow)
1146 bbb JSCell::m_type[t1], ObjectType, .opInstanceofSlow
1147 loadisFromInstruction(2, t0)
1148 loadConstantOrVariableCell(t0, t2, .opInstanceofSlow)
1150 # Register state: t1 = prototype, t2 = value
1153 loadStructureAndClobberFirstArg(t2, t3)
1154 loadq Structure::m_prototype[t3], t2
1155 bqeq t2, t1, .opInstanceofDone
1156 btqz t2, tagMask, .opInstanceofLoop
1161 loadisFromInstruction(1, t3)
1162 storeq t0, [cfr, t3, 8]
1166 callSlowPath(_llint_slow_path_instanceof)
1170 _llint_op_is_undefined:
1172 loadisFromInstruction(2, t1)
1173 loadisFromInstruction(1, t2)
1174 loadConstantOrVariable(t1, t0)
1175 btqz t0, tagMask, .opIsUndefinedCell
1176 cqeq t0, ValueUndefined, t3
1178 storeq t3, [cfr, t2, 8]
1181 btbnz JSCell::m_flags[t0], MasqueradesAsUndefined, .masqueradesAsUndefined
1183 storeq t1, [cfr, t2, 8]
1185 .masqueradesAsUndefined:
1186 loadStructureWithScratch(t0, t3, t1)
1187 loadp CodeBlock[cfr], t1
1188 loadp CodeBlock::m_globalObject[t1], t1
1189 cpeq Structure::m_globalObject[t3], t1, t0
1191 storeq t0, [cfr, t2, 8]
1195 _llint_op_is_boolean:
1197 loadisFromInstruction(2, t1)
1198 loadisFromInstruction(1, t2)
1199 loadConstantOrVariable(t1, t0)
1203 storeq t0, [cfr, t2, 8]
1207 _llint_op_is_number:
1209 loadisFromInstruction(2, t1)
1210 loadisFromInstruction(1, t2)
1211 loadConstantOrVariable(t1, t0)
1212 tqnz t0, tagTypeNumber, t1
1214 storeq t1, [cfr, t2, 8]
1218 _llint_op_is_string:
1220 loadisFromInstruction(2, t1)
1221 loadisFromInstruction(1, t2)
1222 loadConstantOrVariable(t1, t0)
1223 btqnz t0, tagMask, .opIsStringNotCell
1224 cbeq JSCell::m_type[t0], StringType, t1
1226 storeq t1, [cfr, t2, 8]
1229 storeq ValueFalse, [cfr, t2, 8]
1233 macro loadPropertyAtVariableOffset(propertyOffsetAsInt, objectAndStorage, value)
1234 bilt propertyOffsetAsInt, firstOutOfLineOffset, .isInline
1235 loadp JSObject::m_butterfly[objectAndStorage], objectAndStorage
1236 negi propertyOffsetAsInt
1237 sxi2q propertyOffsetAsInt, propertyOffsetAsInt
1240 addp sizeof JSObject - (firstOutOfLineOffset - 2) * 8, objectAndStorage
1242 loadq (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffsetAsInt, 8], value
1246 macro storePropertyAtVariableOffset(propertyOffsetAsInt, objectAndStorage, value)
1247 bilt propertyOffsetAsInt, firstOutOfLineOffset, .isInline
1248 loadp JSObject::m_butterfly[objectAndStorage], objectAndStorage
1249 negi propertyOffsetAsInt
1250 sxi2q propertyOffsetAsInt, propertyOffsetAsInt
1253 addp sizeof JSObject - (firstOutOfLineOffset - 2) * 8, objectAndStorage
1255 storeq value, (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffsetAsInt, 8]
1258 _llint_op_init_global_const:
1260 writeBarrierOnGlobalObject(2)
1261 loadisFromInstruction(2, t1)
1262 loadpFromInstruction(1, t0)
1263 loadConstantOrVariable(t1, t2)
1268 macro getById(getPropertyStorage)
1270 # We only do monomorphic get_by_id caching for now, and we do not modify the
1271 # opcode. We do, however, allow for the cache to change anytime if fails, since
1272 # ping-ponging is free. At best we get lucky and the get_by_id will continue
1273 # to take fast path on the new cache. At worst we take slow path, which is what
1274 # we would have been doing anyway.
1275 loadisFromInstruction(2, t0)
1276 loadConstantOrVariableCell(t0, t3, .opGetByIdSlow)
1277 loadStructureWithScratch(t3, t2, t1)
1278 loadpFromInstruction(4, t1)
1279 bpneq t2, t1, .opGetByIdSlow
1283 macro (propertyStorage, scratch)
1284 loadisFromInstruction(5, t2)
1285 loadisFromInstruction(1, t1)
1286 loadq [propertyStorage, t2], scratch
1287 storeq scratch, [cfr, t1, 8]
1288 valueProfile(scratch, 8, t1)
1293 callSlowPath(_llint_slow_path_get_by_id)
1297 _llint_op_get_by_id:
1298 getById(withInlineStorage)
1301 _llint_op_get_by_id_out_of_line:
1302 getById(withOutOfLineStorage)
1305 _llint_op_get_array_length:
1307 loadisFromInstruction(2, t0)
1308 loadpFromInstruction(4, t1)
1309 loadConstantOrVariableCell(t0, t3, .opGetArrayLengthSlow)
1311 arrayProfile(t2, t1, t0)
1312 btiz t2, IsArray, .opGetArrayLengthSlow
1313 btiz t2, IndexingShapeMask, .opGetArrayLengthSlow
1314 loadisFromInstruction(1, t1)
1315 loadp JSObject::m_butterfly[t3], t0
1316 loadi -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], t0
1317 bilt t0, 0, .opGetArrayLengthSlow
1318 orq tagTypeNumber, t0
1319 valueProfile(t0, 8, t2)
1320 storeq t0, [cfr, t1, 8]
1323 .opGetArrayLengthSlow:
1324 callSlowPath(_llint_slow_path_get_by_id)
1328 _llint_op_get_arguments_length:
1330 loadisFromInstruction(2, t0)
1331 loadisFromInstruction(1, t1)
1332 btqnz [cfr, t0, 8], .opGetArgumentsLengthSlow
1333 loadi ArgumentCount + PayloadOffset[cfr], t2
1335 orq tagTypeNumber, t2
1336 storeq t2, [cfr, t1, 8]
1339 .opGetArgumentsLengthSlow:
1340 callSlowPath(_llint_slow_path_get_arguments_length)
1344 macro putById(getPropertyStorage)
1346 writeBarrierOnOperands(1, 3)
1347 loadisFromInstruction(1, t3)
1348 loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
1349 loadStructureWithScratch(t0, t2, t1)
1350 loadpFromInstruction(4, t1)
1351 bpneq t2, t1, .opPutByIdSlow
1355 macro (propertyStorage, scratch)
1356 loadisFromInstruction(5, t1)
1357 loadisFromInstruction(3, t2)
1358 loadConstantOrVariable(t2, scratch)
1359 storeq scratch, [propertyStorage, t1]
1364 _llint_op_put_by_id:
1365 putById(withInlineStorage)
1368 callSlowPath(_llint_slow_path_put_by_id)
1372 _llint_op_put_by_id_out_of_line:
1373 putById(withOutOfLineStorage)
1376 macro putByIdTransition(additionalChecks, getPropertyStorage)
1378 writeBarrierOnOperand(1)
1379 loadisFromInstruction(1, t3)
1380 loadpFromInstruction(4, t1)
1381 loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
1382 loadStructureWithScratch(t0, t2, t3)
1383 bpneq t2, t1, .opPutByIdSlow
1384 additionalChecks(t1, t3, t2)
1385 loadisFromInstruction(3, t2)
1386 loadisFromInstruction(5, t1)
1390 macro (propertyStorage, scratch)
1391 addp t1, propertyStorage, t3
1392 loadConstantOrVariable(t2, t1)
1394 loadpFromInstruction(6, t1)
1395 loadi Structure::m_blob + StructureIDBlob::u.words.word1[t1], t1
1396 storei t1, JSCell::m_structureID[t0]
1401 macro noAdditionalChecks(oldStructure, scratch, scratch2)
1404 macro structureChainChecks(oldStructure, scratch, scratch2)
1405 const protoCell = oldStructure # Reusing the oldStructure register for the proto
1406 loadpFromInstruction(7, scratch)
1407 assert(macro (ok) btpnz scratch, ok end)
1408 loadp StructureChain::m_vector[scratch], scratch
1409 assert(macro (ok) btpnz scratch, ok end)
1410 bqeq Structure::m_prototype[oldStructure], ValueNull, .done
1412 loadq Structure::m_prototype[oldStructure], protoCell
1413 loadStructureAndClobberFirstArg(protoCell, scratch2)
1414 move scratch2, oldStructure
1415 bpneq oldStructure, [scratch], .opPutByIdSlow
1417 bqneq Structure::m_prototype[oldStructure], ValueNull, .loop
1421 _llint_op_put_by_id_transition_direct:
1422 putByIdTransition(noAdditionalChecks, withInlineStorage)
1425 _llint_op_put_by_id_transition_direct_out_of_line:
1426 putByIdTransition(noAdditionalChecks, withOutOfLineStorage)
1429 _llint_op_put_by_id_transition_normal:
1430 putByIdTransition(structureChainChecks, withInlineStorage)
1433 _llint_op_put_by_id_transition_normal_out_of_line:
1434 putByIdTransition(structureChainChecks, withOutOfLineStorage)
1437 _llint_op_get_by_val:
1439 loadisFromInstruction(2, t2)
1440 loadConstantOrVariableCell(t2, t0, .opGetByValSlow)
1441 loadpFromInstruction(4, t3)
1443 arrayProfile(t2, t3, t1)
1444 loadisFromInstruction(3, t3)
1445 loadConstantOrVariableInt32(t3, t1, .opGetByValSlow)
1447 loadp JSObject::m_butterfly[t0], t3
1448 andi IndexingShapeMask, t2
1449 bieq t2, Int32Shape, .opGetByValIsContiguous
1450 bineq t2, ContiguousShape, .opGetByValNotContiguous
1451 .opGetByValIsContiguous:
1453 biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t3], .opGetByValOutOfBounds
1454 loadisFromInstruction(1, t0)
1455 loadq [t3, t1, 8], t2
1456 btqz t2, .opGetByValOutOfBounds
1459 .opGetByValNotContiguous:
1460 bineq t2, DoubleShape, .opGetByValNotDouble
1461 biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t3], .opGetByValOutOfBounds
1462 loadis 8[PB, PC, 8], t0
1463 loadd [t3, t1, 8], ft0
1464 bdnequn ft0, ft0, .opGetByValOutOfBounds
1466 subq tagTypeNumber, t2
1469 .opGetByValNotDouble:
1470 subi ArrayStorageShape, t2
1471 bia t2, SlowPutArrayStorageShape - ArrayStorageShape, .opGetByValSlow
1472 biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t3], .opGetByValOutOfBounds
1473 loadisFromInstruction(1, t0)
1474 loadq ArrayStorage::m_vector[t3, t1, 8], t2
1475 btqz t2, .opGetByValOutOfBounds
1478 storeq t2, [cfr, t0, 8]
1479 valueProfile(t2, 5, t0)
1482 .opGetByValOutOfBounds:
1483 loadpFromInstruction(4, t0)
1484 storeb 1, ArrayProfile::m_outOfBounds[t0]
1486 callSlowPath(_llint_slow_path_get_by_val)
1490 _llint_op_get_argument_by_val:
1491 # FIXME: At some point we should array profile this. Right now it isn't necessary
1492 # since the DFG will never turn a get_argument_by_val into a GetByVal.
1494 loadisFromInstruction(2, t0)
1495 loadisFromInstruction(3, t1)
1496 btqnz [cfr, t0, 8], .opGetArgumentByValSlow
1497 loadConstantOrVariableInt32(t1, t2, .opGetArgumentByValSlow)
1499 loadi ArgumentCount + PayloadOffset[cfr], t1
1500 biaeq t2, t1, .opGetArgumentByValSlow
1501 loadisFromInstruction(1, t3)
1502 loadpFromInstruction(5, t1)
1503 loadq ThisArgumentOffset[cfr, t2, 8], t0
1504 storeq t0, [cfr, t3, 8]
1505 valueProfile(t0, 5, t1)
1508 .opGetArgumentByValSlow:
1509 callSlowPath(_llint_slow_path_get_argument_by_val)
1513 _llint_op_get_by_pname:
1515 loadisFromInstruction(3, t1)
1516 loadConstantOrVariable(t1, t0)
1517 loadisFromInstruction(4, t1)
1518 assertNotConstant(t1)
1519 bqneq t0, [cfr, t1, 8], .opGetByPnameSlow
1520 loadisFromInstruction(2, t2)
1521 loadisFromInstruction(5, t3)
1522 loadConstantOrVariableCell(t2, t0, .opGetByPnameSlow)
1523 assertNotConstant(t3)
1524 loadq [cfr, t3, 8], t1
1525 loadStructureWithScratch(t0, t2, t3)
1526 bpneq t2, JSPropertyNameIterator::m_cachedStructure[t1], .opGetByPnameSlow
1527 loadisFromInstruction(6, t3)
1528 loadi PayloadOffset[cfr, t3, 8], t3
1530 biaeq t3, JSPropertyNameIterator::m_numCacheableSlots[t1], .opGetByPnameSlow
1531 bilt t3, JSPropertyNameIterator::m_cachedStructureInlineCapacity[t1], .opGetByPnameInlineProperty
1532 addi firstOutOfLineOffset, t3
1533 subi JSPropertyNameIterator::m_cachedStructureInlineCapacity[t1], t3
1534 .opGetByPnameInlineProperty:
1535 loadPropertyAtVariableOffset(t3, t0, t0)
1536 loadisFromInstruction(1, t1)
1537 storeq t0, [cfr, t1, 8]
1541 callSlowPath(_llint_slow_path_get_by_pname)
1545 macro contiguousPutByVal(storeCallback)
1546 biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], .outOfBounds
1548 loadisFromInstruction(3, t2)
1549 storeCallback(t2, t1, [t0, t3, 8])
1553 biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t0], .opPutByValOutOfBounds
1554 loadp 32[PB, PC, 8], t2
1555 storeb 1, ArrayProfile::m_mayStoreToHole[t2]
1557 storei t2, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0]
1561 macro putByVal(slowPath)
1563 writeBarrierOnOperands(1, 3)
1564 loadisFromInstruction(1, t0)
1565 loadConstantOrVariableCell(t0, t1, .opPutByValSlow)
1566 loadpFromInstruction(4, t3)
1568 arrayProfile(t2, t3, t0)
1569 loadisFromInstruction(2, t0)
1570 loadConstantOrVariableInt32(t0, t3, .opPutByValSlow)
1572 loadp JSObject::m_butterfly[t1], t0
1573 andi IndexingShapeMask, t2
1574 bineq t2, Int32Shape, .opPutByValNotInt32
1576 macro (operand, scratch, address)
1577 loadConstantOrVariable(operand, scratch)
1578 bpb scratch, tagTypeNumber, .opPutByValSlow
1579 storep scratch, address
1582 .opPutByValNotInt32:
1583 bineq t2, DoubleShape, .opPutByValNotDouble
1585 macro (operand, scratch, address)
1586 loadConstantOrVariable(operand, scratch)
1587 bqb scratch, tagTypeNumber, .notInt
1591 addp tagTypeNumber, scratch
1593 bdnequn ft0, ft0, .opPutByValSlow
1598 .opPutByValNotDouble:
1599 bineq t2, ContiguousShape, .opPutByValNotContiguous
1601 macro (operand, scratch, address)
1602 loadConstantOrVariable(operand, scratch)
1603 storep scratch, address
1606 .opPutByValNotContiguous:
1607 bineq t2, ArrayStorageShape, .opPutByValSlow
1608 biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t0], .opPutByValOutOfBounds
1609 btqz ArrayStorage::m_vector[t0, t3, 8], .opPutByValArrayStorageEmpty
1610 .opPutByValArrayStorageStoreResult:
1611 loadisFromInstruction(3, t2)
1612 loadConstantOrVariable(t2, t1)
1613 storeq t1, ArrayStorage::m_vector[t0, t3, 8]
1616 .opPutByValArrayStorageEmpty:
1617 loadpFromInstruction(4, t1)
1618 storeb 1, ArrayProfile::m_mayStoreToHole[t1]
1619 addi 1, ArrayStorage::m_numValuesInVector[t0]
1620 bib t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], .opPutByValArrayStorageStoreResult
1622 storei t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0]
1623 jmp .opPutByValArrayStorageStoreResult
1625 .opPutByValOutOfBounds:
1626 loadpFromInstruction(4, t0)
1627 storeb 1, ArrayProfile::m_outOfBounds[t0]
1629 callSlowPath(slowPath)
1633 _llint_op_put_by_val:
1634 putByVal(_llint_slow_path_put_by_val)
1636 _llint_op_put_by_val_direct:
1637 putByVal(_llint_slow_path_put_by_val_direct)
1642 dispatchIntIndirect(1)
1645 macro jumpTrueOrFalse(conditionOp, slow)
1646 loadisFromInstruction(1, t1)
1647 loadConstantOrVariable(t1, t0)
1650 conditionOp(t0, .target)
1654 dispatchIntIndirect(2)
1662 macro equalNull(cellHandler, immediateHandler)
1663 loadisFromInstruction(1, t0)
1664 assertNotConstant(t0)
1665 loadq [cfr, t0, 8], t0
1666 btqnz t0, tagMask, .immediate
1667 loadStructureWithScratch(t0, t2, t1)
1668 cellHandler(t2, JSCell::m_flags[t0], .target)
1672 dispatchIntIndirect(2)
1675 andq ~TagBitUndefined, t0
1676 immediateHandler(t0, .target)
1683 macro (structure, value, target)
1684 btbz value, MasqueradesAsUndefined, .notMasqueradesAsUndefined
1685 loadp CodeBlock[cfr], t0
1686 loadp CodeBlock::m_globalObject[t0], t0
1687 bpeq Structure::m_globalObject[structure], t0, target
1688 .notMasqueradesAsUndefined:
1690 macro (value, target) bqeq value, ValueNull, target end)
1693 _llint_op_jneq_null:
1696 macro (structure, value, target)
1697 btbz value, MasqueradesAsUndefined, target
1698 loadp CodeBlock[cfr], t0
1699 loadp CodeBlock::m_globalObject[t0], t0
1700 bpneq Structure::m_globalObject[structure], t0, target
1702 macro (value, target) bqneq value, ValueNull, target end)
1707 loadisFromInstruction(1, t0)
1708 loadisFromInstruction(2, t1)
1709 loadp CodeBlock[cfr], t2
1710 loadp CodeBlock::m_globalObject[t2], t2
1711 loadp JSGlobalObject::m_specialPointers[t2, t1, 8], t1
1712 bpneq t1, [cfr, t0, 8], .opJneqPtrTarget
1716 dispatchIntIndirect(3)
1719 macro compare(integerCompare, doubleCompare, slowPath)
1720 loadisFromInstruction(1, t2)
1721 loadisFromInstruction(2, t3)
1722 loadConstantOrVariable(t2, t0)
1723 loadConstantOrVariable(t3, t1)
1724 bqb t0, tagTypeNumber, .op1NotInt
1725 bqb t1, tagTypeNumber, .op2NotInt
1726 integerCompare(t0, t1, .jumpTarget)
1730 btqz t0, tagTypeNumber, .slow
1731 bqb t1, tagTypeNumber, .op1NotIntOp2NotInt
1734 .op1NotIntOp2NotInt:
1735 btqz t1, tagTypeNumber, .slow
1736 addq tagTypeNumber, t1
1739 addq tagTypeNumber, t0
1741 doubleCompare(ft0, ft1, .jumpTarget)
1746 btqz t1, tagTypeNumber, .slow
1747 addq tagTypeNumber, t1
1749 doubleCompare(ft0, ft1, .jumpTarget)
1753 dispatchIntIndirect(3)
1756 callSlowPath(slowPath)
1761 _llint_op_switch_imm:
1763 loadisFromInstruction(3, t2)
1764 loadisFromInstruction(1, t3)
1765 loadConstantOrVariable(t2, t1)
1766 loadp CodeBlock[cfr], t2
1767 loadp CodeBlock::m_rareData[t2], t2
1768 muli sizeof SimpleJumpTable, t3 # FIXME: would be nice to peephole this!
1769 loadp CodeBlock::RareData::m_switchJumpTables + VectorBufferOffset[t2], t2
1771 bqb t1, tagTypeNumber, .opSwitchImmNotInt
1772 subi SimpleJumpTable::min[t2], t1
1773 biaeq t1, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchImmFallThrough
1774 loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t3
1775 loadis [t3, t1, 4], t1
1776 btiz t1, .opSwitchImmFallThrough
1780 btqnz t1, tagTypeNumber, .opSwitchImmSlow # Go slow if it's a double.
1781 .opSwitchImmFallThrough:
1782 dispatchIntIndirect(2)
1785 callSlowPath(_llint_slow_path_switch_imm)
1789 _llint_op_switch_char:
1791 loadisFromInstruction(3, t2)
1792 loadisFromInstruction(1, t3)
1793 loadConstantOrVariable(t2, t1)
1794 loadp CodeBlock[cfr], t2
1795 loadp CodeBlock::m_rareData[t2], t2
1796 muli sizeof SimpleJumpTable, t3
1797 loadp CodeBlock::RareData::m_switchJumpTables + VectorBufferOffset[t2], t2
1799 btqnz t1, tagMask, .opSwitchCharFallThrough
1800 bbneq JSCell::m_type[t1], StringType, .opSwitchCharFallThrough
1801 bineq JSString::m_length[t1], 1, .opSwitchCharFallThrough
1802 loadp JSString::m_value[t1], t0
1803 btpz t0, .opSwitchOnRope
1804 loadp StringImpl::m_data8[t0], t1
1805 btinz StringImpl::m_hashAndFlags[t0], HashFlags8BitBuffer, .opSwitchChar8Bit
1807 jmp .opSwitchCharReady
1811 subi SimpleJumpTable::min[t2], t0
1812 biaeq t0, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchCharFallThrough
1813 loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t2
1814 loadis [t2, t0, 4], t1
1815 btiz t1, .opSwitchCharFallThrough
1818 .opSwitchCharFallThrough:
1819 dispatchIntIndirect(2)
1822 callSlowPath(_llint_slow_path_switch_char)
1828 loadisFromInstruction(3, t2)
1829 btiz t2, .opNewFuncUnchecked
1830 loadisFromInstruction(1, t1)
1831 btqnz [cfr, t1, 8], .opNewFuncDone
1832 .opNewFuncUnchecked:
1833 callSlowPath(_llint_slow_path_new_func)
1838 _llint_op_new_captured_func:
1840 callSlowPath(_slow_path_new_captured_func)
1844 macro arrayProfileForCall()
1845 loadisFromInstruction(4, t3)
1847 loadq ThisArgumentOffset[cfr, t3, 8], t0
1848 btqnz t0, tagMask, .done
1849 loadpFromInstruction((CallOpCodeSize - 2), t1)
1850 loadi JSCell::m_structureID[t0], t3
1851 storei t3, ArrayProfile::m_lastSeenStructureID[t1]
1855 macro doCall(slowPath)
1856 loadisFromInstruction(2, t0)
1857 loadpFromInstruction(5, t1)
1858 loadp LLIntCallLinkInfo::callee[t1], t2
1859 loadConstantOrVariable(t0, t3)
1860 bqneq t3, t2, .opCallSlow
1861 loadisFromInstruction(4, t3)
1865 loadp JSFunction::m_scope[t2], t0
1866 storeq t2, Callee[t3]
1867 storeq t0, ScopeChain[t3]
1868 loadisFromInstruction(3, t2)
1869 storei PC, ArgumentCount + TagOffset[cfr]
1870 storei t2, ArgumentCount + PayloadOffset[t3]
1871 addp CallerFrameAndPCSize, t3
1872 callTargetFunction(t1, t3)
1875 slowPathForCall(slowPath)
1879 _llint_op_tear_off_activation:
1881 loadisFromInstruction(1, t0)
1882 btqz [cfr, t0, 8], .opTearOffActivationNotCreated
1883 callSlowPath(_llint_slow_path_tear_off_activation)
1884 .opTearOffActivationNotCreated:
1888 _llint_op_tear_off_arguments:
1890 loadisFromInstruction(1, t0)
1891 addq 1, t0 # Get the unmodifiedArgumentsRegister
1892 btqz [cfr, t0, 8], .opTearOffArgumentsNotCreated
1893 callSlowPath(_llint_slow_path_tear_off_arguments)
1894 .opTearOffArgumentsNotCreated:
1900 checkSwitchToJITForEpilogue()
1901 loadisFromInstruction(1, t2)
1902 loadConstantOrVariable(t2, t0)
1906 _llint_op_ret_object_or_this:
1908 checkSwitchToJITForEpilogue()
1909 loadisFromInstruction(1, t2)
1910 loadConstantOrVariable(t2, t0)
1911 btqnz t0, tagMask, .opRetObjectOrThisNotObject
1912 bbb JSCell::m_type[t0], ObjectType, .opRetObjectOrThisNotObject
1915 .opRetObjectOrThisNotObject:
1916 loadisFromInstruction(2, t2)
1917 loadConstantOrVariable(t2, t0)
1921 _llint_op_to_primitive:
1923 loadisFromInstruction(2, t2)
1924 loadisFromInstruction(1, t3)
1925 loadConstantOrVariable(t2, t0)
1926 btqnz t0, tagMask, .opToPrimitiveIsImm
1927 bbneq JSCell::m_type[t0], StringType, .opToPrimitiveSlowCase
1928 .opToPrimitiveIsImm:
1929 storeq t0, [cfr, t3, 8]
1932 .opToPrimitiveSlowCase:
1933 callSlowPath(_slow_path_to_primitive)
1937 _llint_op_next_pname:
1939 loadisFromInstruction(3, t1)
1940 loadisFromInstruction(4, t2)
1941 assertNotConstant(t1)
1942 assertNotConstant(t2)
1943 loadi PayloadOffset[cfr, t1, 8], t0
1944 bieq t0, PayloadOffset[cfr, t2, 8], .opNextPnameEnd
1945 loadisFromInstruction(5, t2)
1946 assertNotConstant(t2)
1947 loadp [cfr, t2, 8], t2
1948 loadp JSPropertyNameIterator::m_jsStrings[t2], t3
1949 loadq [t3, t0, 8], t3
1951 storei t0, PayloadOffset[cfr, t1, 8]
1952 loadisFromInstruction(1, t1)
1953 storeq t3, [cfr, t1, 8]
1954 loadisFromInstruction(2, t3)
1955 assertNotConstant(t3)
1956 loadq [cfr, t3, 8], t3
1957 loadStructureWithScratch(t3, t1, t0)
1958 bpneq t1, JSPropertyNameIterator::m_cachedStructure[t2], .opNextPnameSlow
1959 loadp JSPropertyNameIterator::m_cachedPrototypeChain[t2], t0
1960 loadp StructureChain::m_vector[t0], t0
1961 btpz [t0], .opNextPnameTarget
1962 .opNextPnameCheckPrototypeLoop:
1963 bqeq Structure::m_prototype[t1], ValueNull, .opNextPnameSlow
1964 loadq Structure::m_prototype[t1], t2
1965 loadStructureWithScratch(t2, t1, t3)
1966 bpneq t1, [t0], .opNextPnameSlow
1968 btpnz [t0], .opNextPnameCheckPrototypeLoop
1970 dispatchIntIndirect(6)
1976 callSlowPath(_llint_slow_path_next_pname) # This either keeps the PC where it was (causing us to loop) or sets it to target.
1981 # Gotta restore the tag registers. We could be throwing from FTL, which may
1983 move TagTypeNumber, tagTypeNumber
1984 move TagMask, tagMask
1986 # This is where we end up from the JIT's throw trampoline (because the
1987 # machine code return address will be set to _llint_op_catch), and from
1988 # the interpreter's throw trampoline (see _llint_throw_trampoline).
1989 # The throwing code must have known that we were throwing to the interpreter,
1990 # and have set VM::targetInterpreterPCForThrow.
1991 loadp ScopeChain[cfr], t3
1992 andp MarkedBlockMask, t3
1993 loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
1994 loadp VM::callFrameForThrow[t3], cfr
1995 restoreStackPointerAfterCall()
1997 loadp CodeBlock[cfr], PB
1998 loadp CodeBlock::m_instructions[PB], PB
1999 loadp VM::targetInterpreterPCForThrow[t3], PC
2002 loadq VM::m_exception[t3], t0
2003 storeq 0, VM::m_exception[t3]
2004 loadisFromInstruction(1, t2)
2005 storeq t0, [cfr, t2, 8]
2012 checkSwitchToJITForEpilogue()
2013 loadisFromInstruction(1, t0)
2014 assertNotConstant(t0)
2015 loadq [cfr, t0, 8], t0
2019 _llint_throw_from_slow_path_trampoline:
2020 callSlowPath(_llint_slow_path_handle_exception)
2022 # When throwing from the interpreter (i.e. throwing from LLIntSlowPaths), so
2023 # the throw target is not necessarily interpreted code, we come to here.
2024 # This essentially emulates the JIT's throwing protocol.
2025 loadp CodeBlock[cfr], t1
2026 loadp CodeBlock::m_vm[t1], t1
2027 jmp VM::targetMachinePCForThrow[t1]
2030 _llint_throw_during_call_trampoline:
2031 preserveReturnAddressAfterCall(t2)
2032 jmp _llint_throw_from_slow_path_trampoline
2035 macro nativeCallTrampoline(executableOffsetToFunction)
2038 storep 0, CodeBlock[cfr]
2039 if X86_64 or X86_64_WIN
2041 const arg1 = t4 # t4 = rdi
2042 const arg2 = t5 # t5 = rsi
2045 const arg1 = t2 # t2 = rcx
2046 const arg2 = t1 # t1 = rdx
2049 loadp ScopeChain[cfr], t0
2050 andp MarkedBlockMask, t0
2051 loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t0], t0
2052 storep cfr, VM::topCallFrame[t0]
2053 loadp CallerFrame[cfr], t0
2054 loadq ScopeChain[t0], t1
2055 storeq t1, ScopeChain[cfr]
2057 loadp Callee[cfr], arg2
2058 loadp JSFunction::m_executable[arg2], temp
2059 checkStackPointerAlignment(t3, 0xdead0001)
2063 call executableOffsetToFunction[temp]
2067 loadp ScopeChain[cfr], t3
2068 andp MarkedBlockMask, t3
2069 loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
2070 elsif ARM64 or C_LOOP
2071 loadp ScopeChain[cfr], t0
2072 andp MarkedBlockMask, t0
2073 loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t0], t0
2074 storep cfr, VM::topCallFrame[t0]
2075 loadp CallerFrame[cfr], t2
2076 loadp ScopeChain[t2], t1
2077 storep t1, ScopeChain[cfr]
2078 preserveReturnAddressAfterCall(t3)
2079 storep t3, ReturnPC[cfr]
2081 loadp Callee[cfr], t1
2082 loadp JSFunction::m_executable[t1], t1
2083 move t2, cfr # Restore cfr to avoid loading from stack
2085 cloopCallNative executableOffsetToFunction[t1]
2087 call executableOffsetToFunction[t1]
2089 restoreReturnAddressBeforeReturn(t3)
2090 loadp ScopeChain[cfr], t3
2091 andp MarkedBlockMask, t3
2092 loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
2099 btqnz VM::m_exception[t3], .handleException
2103 storep cfr, VM::topCallFrame[t3]
2104 restoreStackPointerAfterCall()
2105 jmp _llint_throw_from_slow_path_trampoline
2109 macro getGlobalObject(dst)
2110 loadp CodeBlock[cfr], t0
2111 loadp CodeBlock::m_globalObject[t0], t0
2112 loadisFromInstruction(dst, t1)
2113 storeq t0, [cfr, t1, 8]
2116 macro varInjectionCheck(slowPath)
2117 loadp CodeBlock[cfr], t0
2118 loadp CodeBlock::m_globalObject[t0], t0
2119 loadp JSGlobalObject::m_varInjectionWatchpoint[t0], t0
2120 bbeq WatchpointSet::m_state[t0], IsInvalidated, slowPath
2123 macro resolveScope()
2124 loadp CodeBlock[cfr], t0
2125 loadisFromInstruction(4, t2)
2126 btbz CodeBlock::m_needsActivation[t0], .resolveScopeAfterActivationCheck
2127 loadis CodeBlock::m_activationRegister[t0], t1
2128 btpz [cfr, t1, 8], .resolveScopeAfterActivationCheck
2131 .resolveScopeAfterActivationCheck:
2132 loadp ScopeChain[cfr], t0
2133 btiz t2, .resolveScopeLoopEnd
2136 loadp JSScope::m_next[t0], t0
2138 btinz t2, .resolveScopeLoop
2140 .resolveScopeLoopEnd:
2141 loadisFromInstruction(1, t1)
2142 storeq t0, [cfr, t1, 8]
2146 _llint_op_resolve_scope:
2148 loadisFromInstruction(3, t0)
2151 bineq t0, GlobalProperty, .rGlobalVar
2156 bineq t0, GlobalVar, .rClosureVar
2161 bineq t0, ClosureVar, .rGlobalPropertyWithVarInjectionChecks
2165 .rGlobalPropertyWithVarInjectionChecks:
2166 bineq t0, GlobalPropertyWithVarInjectionChecks, .rGlobalVarWithVarInjectionChecks
2167 varInjectionCheck(.rDynamic)
2171 .rGlobalVarWithVarInjectionChecks:
2172 bineq t0, GlobalVarWithVarInjectionChecks, .rClosureVarWithVarInjectionChecks
2173 varInjectionCheck(.rDynamic)
2177 .rClosureVarWithVarInjectionChecks:
2178 bineq t0, ClosureVarWithVarInjectionChecks, .rDynamic
2179 varInjectionCheck(.rDynamic)
2184 callSlowPath(_llint_slow_path_resolve_scope)
2188 macro loadWithStructureCheck(operand, slowPath)
2189 loadisFromInstruction(operand, t0)
2190 loadq [cfr, t0, 8], t0
2191 loadStructureWithScratch(t0, t2, t1)
2192 loadpFromInstruction(5, t1)
2193 bpneq t2, t1, slowPath
2197 loadisFromInstruction(6, t1)
2198 loadPropertyAtVariableOffset(t1, t0, t2)
2199 valueProfile(t2, 7, t0)
2200 loadisFromInstruction(1, t0)
2201 storeq t2, [cfr, t0, 8]
2204 macro getGlobalVar()
2205 loadpFromInstruction(6, t0)
2207 valueProfile(t0, 7, t1)
2208 loadisFromInstruction(1, t1)
2209 storeq t0, [cfr, t1, 8]
2212 macro getClosureVar()
2213 loadp JSVariableObject::m_registers[t0], t0
2214 loadisFromInstruction(6, t1)
2215 loadq [t0, t1, 8], t0
2216 valueProfile(t0, 7, t1)
2217 loadisFromInstruction(1, t1)
2218 storeq t0, [cfr, t1, 8]
2221 _llint_op_get_from_scope:
2223 loadisFromInstruction(4, t0)
2224 andi ResolveModeMask, t0
2227 bineq t0, GlobalProperty, .gGlobalVar
2228 loadWithStructureCheck(2, .gDynamic)
2233 bineq t0, GlobalVar, .gClosureVar
2238 bineq t0, ClosureVar, .gGlobalPropertyWithVarInjectionChecks
2243 .gGlobalPropertyWithVarInjectionChecks:
2244 bineq t0, GlobalPropertyWithVarInjectionChecks, .gGlobalVarWithVarInjectionChecks
2245 loadWithStructureCheck(2, .gDynamic)
2249 .gGlobalVarWithVarInjectionChecks:
2250 bineq t0, GlobalVarWithVarInjectionChecks, .gClosureVarWithVarInjectionChecks
2251 varInjectionCheck(.gDynamic)
2256 .gClosureVarWithVarInjectionChecks:
2257 bineq t0, ClosureVarWithVarInjectionChecks, .gDynamic
2258 varInjectionCheck(.gDynamic)
2264 callSlowPath(_llint_slow_path_get_from_scope)
2269 loadisFromInstruction(3, t1)
2270 loadConstantOrVariable(t1, t2)
2271 loadisFromInstruction(6, t1)
2272 storePropertyAtVariableOffset(t1, t0, t2)
2275 macro putGlobalVar()
2276 loadisFromInstruction(3, t0)
2277 loadConstantOrVariable(t0, t1)
2278 loadpFromInstruction(5, t2)
2279 notifyWrite(t2, t1, t0, .pDynamic)
2280 loadpFromInstruction(6, t0)
2284 macro putClosureVar()
2285 loadisFromInstruction(3, t1)
2286 loadConstantOrVariable(t1, t2)
2287 loadp JSVariableObject::m_registers[t0], t0
2288 loadisFromInstruction(6, t1)
2289 storeq t2, [t0, t1, 8]
2293 _llint_op_put_to_scope:
2295 loadisFromInstruction(4, t0)
2296 andi ResolveModeMask, t0
2299 bineq t0, GlobalProperty, .pGlobalVar
2300 writeBarrierOnOperands(1, 3)
2301 loadWithStructureCheck(1, .pDynamic)
2306 bineq t0, GlobalVar, .pClosureVar
2307 writeBarrierOnGlobalObject(3)
2312 bineq t0, ClosureVar, .pGlobalPropertyWithVarInjectionChecks
2313 writeBarrierOnOperands(1, 3)
2318 .pGlobalPropertyWithVarInjectionChecks:
2319 bineq t0, GlobalPropertyWithVarInjectionChecks, .pGlobalVarWithVarInjectionChecks
2320 writeBarrierOnOperands(1, 3)
2321 loadWithStructureCheck(1, .pDynamic)
2325 .pGlobalVarWithVarInjectionChecks:
2326 bineq t0, GlobalVarWithVarInjectionChecks, .pClosureVarWithVarInjectionChecks
2327 writeBarrierOnGlobalObject(3)
2328 varInjectionCheck(.pDynamic)
2332 .pClosureVarWithVarInjectionChecks:
2333 bineq t0, ClosureVarWithVarInjectionChecks, .pDynamic
2334 writeBarrierOnOperands(1, 3)
2335 varInjectionCheck(.pDynamic)
2341 callSlowPath(_llint_slow_path_put_to_scope)