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)
65 cloopCallSlowPath function, arg1, arg2
71 macro cCall2Void(function, arg1, arg2)
73 cloopCallSlowPathVoid function, arg1, arg2
75 cCall2(function, arg1, arg2)
79 # This barely works. arg3 and arg4 should probably be immediates.
80 macro cCall4(function, arg1, arg2, arg3, arg4)
81 checkStackPointerAlignment(t4, 0xbad0c004)
101 macro doCallToJavaScript(makeCall)
105 const protoCallFrame = t1
107 const previousCFR = t0
108 const previousPC = t6
112 elsif ARM64 or C_LOOP
115 const protoCallFrame = a2
117 const previousCFR = t5
118 const previousPC = lr
124 callToJavaScriptPrologue()
127 loadp 7*8[sp], previousPC
128 move 6*8[sp], previousCFR
130 move cfr, previousCFR
133 checkStackPointerAlignment(temp2, 0xbad0dc01)
135 # The stack reserved zone ensures that we have adequate space for the
136 # VMEntrySentinelFrame. Proceed with allocating and initializing the
139 subp CallFrameHeaderSlots * 8, cfr
140 storep 0, ArgumentCount[cfr]
141 storep vm, Callee[cfr]
142 loadp VM::topCallFrame[vm], temp2
143 storep temp2, ScopeChain[cfr]
144 storep 1, CodeBlock[cfr]
146 loadp 7*8[sp], previousPC
147 loadp 6*8[sp], previousCFR
149 storep previousPC, ReturnPC[cfr]
150 storep previousCFR, CallerFrame[cfr]
152 loadi ProtoCallFrame::paddedArgCount[protoCallFrame], temp2
153 addp CallFrameHeaderSlots, temp2, temp2
155 subp cfr, temp2, temp1
157 # Ensure that we have enough additional stack capacity for the incoming args,
158 # and the frame for the JS code we're executing. We need to do this check
159 # before we start copying the args from the protoCallFrame below.
160 bpaeq temp1, VM::m_jsStackLimit[vm], .stackHeightOK
167 cloopCallSlowPath _llint_stack_check_at_vm_entry, vm, temp1
168 bpeq t0, 0, .stackCheckFailed
178 cCall2(_llint_throw_stack_overflow_error, vm, protoCallFrame)
179 callToJavaScriptEpilogue()
188 loadq [protoCallFrame, temp1, 8], temp3
189 storeq temp3, CodeBlock[sp, temp1, 8]
190 btinz temp1, .copyHeaderLoop
192 loadi ProtoCallFrame::argCountAndCodeOriginValue[protoCallFrame], temp2
194 loadi ProtoCallFrame::paddedArgCount[protoCallFrame], temp3
197 bieq temp2, temp3, .copyArgs
198 move ValueUndefined, temp1
201 storeq temp1, ThisArgumentOffset + 8[sp, temp3, 8]
202 bineq temp2, temp3, .fillExtraArgsLoop
205 loadp ProtoCallFrame::args[protoCallFrame], temp1
208 btiz temp2, .copyArgsDone
210 loadq [temp1, temp2, 8], temp3
211 storeq temp3, ThisArgumentOffset + 8[sp, temp2, 8]
217 storep temp2, VM::topCallFrame[vm]
219 storep sp, VM::topCallFrame[vm]
222 move 0xffff000000000000, csr1
225 checkStackPointerAlignment(temp3, 0xbad0dc02)
227 makeCall(entry, temp1)
229 checkStackPointerAlignment(temp3, 0xbad0dc03)
231 bpeq CodeBlock[cfr], 1, .calleeFramePopped
232 loadp CallerFrame[cfr], cfr
235 loadp Callee[cfr], temp2 # VM
236 loadp ScopeChain[cfr], temp3 # previous topCallFrame
237 storep temp3, VM::topCallFrame[temp2]
239 checkStackPointerAlignment(temp3, 0xbad0dc04)
244 callToJavaScriptEpilogue()
250 macro makeJavaScriptCall(entry, temp)
253 cloopCallJSFunction entry
261 macro makeHostFunctionCall(entry, temp)
265 elsif ARM64 or C_LOOP
280 _handleUncaughtException:
281 loadp ScopeChain[cfr], t3
282 andp MarkedBlockMask, t3
283 loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
284 loadp VM::callFrameForThrow[t3], cfr
286 # So far, we've unwound the stack to the frame just below the sentinel frame, except
287 # in the case of stack overflow in the first function called from callToJavaScript.
288 # Check if we need to pop to the sentinel frame and do the necessary clean up for
289 # returning to the caller C frame.
290 bpeq CodeBlock[cfr], 1, .handleUncaughtExceptionAlreadyIsSentinel
291 loadp CallerFrame[cfr], cfr
292 .handleUncaughtExceptionAlreadyIsSentinel:
294 loadp Callee[cfr], t3 # VM
295 loadp ScopeChain[cfr], t5 # previous topCallFrame
296 storep t5, VM::topCallFrame[t3]
298 callToJavaScriptEpilogue()
302 macro prepareStateForCCall()
307 macro restoreStateAfterCCall()
314 macro callSlowPath(slowPath)
315 prepareStateForCCall()
316 cCall2(slowPath, cfr, PC)
317 restoreStateAfterCCall()
320 macro traceOperand(fromWhere, operand)
321 prepareStateForCCall()
322 cCall4(_llint_trace_operand, cfr, PC, fromWhere, operand)
323 restoreStateAfterCCall()
326 macro traceValue(fromWhere, operand)
327 prepareStateForCCall()
328 cCall4(_llint_trace_value, cfr, PC, fromWhere, operand)
329 restoreStateAfterCCall()
332 # Call a slow path for call call opcodes.
333 macro callCallSlowPath(slowPath, action)
334 storei PC, ArgumentCount + TagOffset[cfr]
335 prepareStateForCCall()
336 cCall2(slowPath, cfr, PC)
340 macro callWatchdogTimerHandler(throwHandler)
341 storei PC, ArgumentCount + TagOffset[cfr]
342 prepareStateForCCall()
343 cCall2(_llint_slow_path_handle_watchdog_timer, cfr, PC)
344 btpnz t0, throwHandler
346 loadi ArgumentCount + TagOffset[cfr], PC
349 macro checkSwitchToJITForLoop()
353 storei PC, ArgumentCount + TagOffset[cfr]
354 prepareStateForCCall()
355 cCall2(_llint_loop_osr, cfr, PC)
361 loadi ArgumentCount + TagOffset[cfr], PC
365 macro loadVariable(operand, value)
366 loadisFromInstruction(operand, value)
367 loadq [cfr, value, 8], value
370 # Index and value must be different registers. Index may be clobbered.
371 macro loadConstantOrVariable(index, value)
372 bpgteq index, FirstConstantRegisterIndex, .constant
373 loadq [cfr, index, 8], value
376 loadp CodeBlock[cfr], value
377 loadp CodeBlock::m_constantRegisters + VectorBufferOffset[value], value
378 subp FirstConstantRegisterIndex, index
379 loadq [value, index, 8], value
383 macro loadConstantOrVariableInt32(index, value, slow)
384 loadConstantOrVariable(index, value)
385 bqb value, tagTypeNumber, slow
388 macro loadConstantOrVariableCell(index, value, slow)
389 loadConstantOrVariable(index, value)
390 btqnz value, tagMask, slow
393 macro writeBarrierOnOperand(cellOperand)
395 loadisFromInstruction(cellOperand, t1)
396 loadConstantOrVariableCell(t1, t2, .writeBarrierDone)
397 checkMarkByte(t2, t1, t3,
399 btbnz gcData, .writeBarrierDone
401 cCall2Void(_llint_write_barrier_slow, cfr, t2)
409 macro writeBarrierOnOperands(cellOperand, valueOperand)
411 loadisFromInstruction(valueOperand, t1)
412 loadConstantOrVariableCell(t1, t0, .writeBarrierDone)
413 btpz t0, .writeBarrierDone
415 writeBarrierOnOperand(cellOperand)
420 macro writeBarrierOnGlobalObject(valueOperand)
422 loadisFromInstruction(valueOperand, t1)
423 loadConstantOrVariableCell(t1, t0, .writeBarrierDone)
424 btpz t0, .writeBarrierDone
426 loadp CodeBlock[cfr], t3
427 loadp CodeBlock::m_globalObject[t3], t3
428 checkMarkByte(t3, t1, t2,
430 btbnz gcData, .writeBarrierDone
432 cCall2Void(_llint_write_barrier_slow, cfr, t3)
440 macro valueProfile(value, operand, scratch)
441 loadpFromInstruction(operand, scratch)
442 storeq value, ValueProfile::m_buckets[scratch]
445 macro loadStructure(cell, structure)
448 macro loadStructureWithScratch(cell, structure, scratch)
449 loadp CodeBlock[cfr], scratch
450 loadp CodeBlock::m_vm[scratch], scratch
451 loadp VM::heap + Heap::m_structureIDTable + StructureIDTable::m_table[scratch], scratch
452 loadi JSCell::m_structureID[cell], structure
453 loadp [scratch, structure, 8], structure
456 macro loadStructureAndClobberFirstArg(cell, structure)
457 loadi JSCell::m_structureID[cell], structure
458 loadp CodeBlock[cfr], cell
459 loadp CodeBlock::m_vm[cell], cell
460 loadp VM::heap + Heap::m_structureIDTable + StructureIDTable::m_table[cell], cell
461 loadp [cell, structure, 8], structure
464 macro storeStructureWithTypeInfo(cell, structure, scratch)
465 loadq Structure::m_blob + StructureIDBlob::u.doubleWord[structure], scratch
466 storeq scratch, JSCell::m_structureID[cell]
469 # Entrypoints into the interpreter.
471 # Expects that CodeBlock is in t1, which is what prologue() leaves behind.
472 macro functionArityCheck(doneLabel, slowPath)
473 loadi PayloadOffset + ArgumentCount[cfr], t0
474 biaeq t0, CodeBlock::m_numParameters[t1], doneLabel
475 prepareStateForCCall()
476 cCall2(slowPath, cfr, PC) # This slowPath has the protocol: t0 = 0 => no error, t0 != 0 => error
478 move t1, cfr # t1 contains caller frame
479 jmp _llint_throw_from_slow_path_trampoline
482 # t1 points to ArityCheckData.
483 loadp CommonSlowPaths::ArityCheckData::thunkToCall[t1], t2
484 btpz t2, .proceedInline
486 loadp CommonSlowPaths::ArityCheckData::returnPC[t1], t7
487 loadp CommonSlowPaths::ArityCheckData::paddedStackSpace[t1], t0
490 loadp ReturnPC[cfr], t0
496 loadi CommonSlowPaths::ArityCheckData::paddedStackSpace[t1], t1
499 // Move frame up "t1 * 2" slots
503 loadi PayloadOffset + ArgumentCount[cfr], t2
504 addi CallFrameHeaderSlots, t2
507 storeq t0, [t3, t1, 8]
509 bsubinz 1, t2, .copyLoop
511 // Fill new slots with JSUndefined
513 move ValueUndefined, t0
515 storeq t0, [t3, t1, 8]
517 baddinz 1, t2, .fillLoop
524 # Reload CodeBlock and reset PC, since the slow_path clobbered them.
525 loadp CodeBlock[cfr], t1
526 loadp CodeBlock::m_instructions[t1], PB
531 macro branchIfException(label)
532 loadp ScopeChain[cfr], t3
533 andp MarkedBlockMask, t3
534 loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
535 btqz VM::m_exception[t3], .noException
541 # Instruction implementations
545 checkStackPointerAlignment(t2, 0xdead00e1)
546 loadp CodeBlock[cfr], t2 // t2<CodeBlock> = cfr.CodeBlock
547 loadi CodeBlock::m_numVars[t2], t2 // t2<size_t> = t2<CodeBlock>.m_numVars
548 btiz t2, .opEnterDone
549 move ValueUndefined, t0
553 storeq t0, [cfr, t2, 8]
555 btqnz t2, .opEnterLoop
557 callSlowPath(_slow_path_enter)
561 _llint_op_create_activation:
563 loadisFromInstruction(1, t0)
564 bqneq [cfr, t0, 8], ValueEmpty, .opCreateActivationDone
565 callSlowPath(_llint_slow_path_create_activation)
566 .opCreateActivationDone:
570 _llint_op_init_lazy_reg:
572 loadisFromInstruction(1, t0)
573 storeq ValueEmpty, [cfr, t0, 8]
577 _llint_op_create_arguments:
579 loadisFromInstruction(1, t0)
580 bqneq [cfr, t0, 8], ValueEmpty, .opCreateArgumentsDone
581 callSlowPath(_slow_path_create_arguments)
582 .opCreateArgumentsDone:
586 _llint_op_create_this:
588 loadisFromInstruction(2, t0)
589 loadp [cfr, t0, 8], t0
590 loadp JSFunction::m_allocationProfile + ObjectAllocationProfile::m_allocator[t0], t1
591 loadp JSFunction::m_allocationProfile + ObjectAllocationProfile::m_structure[t0], t2
592 btpz t1, .opCreateThisSlow
593 allocateJSObject(t1, t2, t0, t3, .opCreateThisSlow)
594 loadisFromInstruction(1, t1)
595 storeq t0, [cfr, t1, 8]
599 callSlowPath(_slow_path_create_this)
603 _llint_op_get_callee:
605 loadisFromInstruction(1, t0)
606 loadp Callee[cfr], t1
607 loadpFromInstruction(2, t2)
608 bpneq t1, t2, .opGetCalleeSlow
609 storep t1, [cfr, t0, 8]
613 callSlowPath(_slow_path_get_callee)
618 loadisFromInstruction(1, t0)
619 loadq [cfr, t0, 8], t0
620 btqnz t0, tagMask, .opToThisSlow
621 bbneq JSCell::m_type[t0], FinalObjectType, .opToThisSlow
622 loadStructureWithScratch(t0, t1, t2)
623 loadpFromInstruction(2, t2)
624 bpneq t1, t2, .opToThisSlow
628 callSlowPath(_slow_path_to_this)
632 _llint_op_new_object:
634 loadpFromInstruction(3, t0)
635 loadp ObjectAllocationProfile::m_allocator[t0], t1
636 loadp ObjectAllocationProfile::m_structure[t0], t2
637 allocateJSObject(t1, t2, t0, t3, .opNewObjectSlow)
638 loadisFromInstruction(1, t1)
639 storeq t0, [cfr, t1, 8]
643 callSlowPath(_llint_slow_path_new_object)
649 loadisFromInstruction(2, t1)
650 loadisFromInstruction(1, t0)
651 loadConstantOrVariable(t1, t2)
652 storeq t2, [cfr, t0, 8]
656 macro notifyWrite(set, value, scratch, slow)
657 loadb VariableWatchpointSet::m_state[set], scratch
658 bieq scratch, IsInvalidated, .done
659 bineq scratch, ClearWatchpoint, .overwrite
660 storeq value, VariableWatchpointSet::m_inferredValue[set]
661 storeb IsWatched, VariableWatchpointSet::m_state[set]
665 bqeq value, VariableWatchpointSet::m_inferredValue[set], .done
666 btbnz VariableWatchpointSet::m_setIsNotEmpty[set], slow
667 storeq 0, VariableWatchpointSet::m_inferredValue[set]
668 storeb IsInvalidated, VariableWatchpointSet::m_state[set]
673 _llint_op_captured_mov:
675 loadisFromInstruction(2, t1)
676 loadConstantOrVariable(t1, t2)
677 loadpFromInstruction(3, t0)
678 btpz t0, .opCapturedMovReady
679 notifyWrite(t0, t2, t1, .opCapturedMovSlow)
681 loadisFromInstruction(1, t0)
682 storeq t2, [cfr, t0, 8]
686 callSlowPath(_slow_path_captured_mov)
692 loadisFromInstruction(2, t0)
693 loadisFromInstruction(1, t1)
694 loadConstantOrVariable(t0, t2)
696 btqnz t2, ~1, .opNotSlow
698 storeq t2, [cfr, t1, 8]
702 callSlowPath(_slow_path_not)
706 macro equalityComparison(integerComparison, slowPath)
708 loadisFromInstruction(3, t0)
709 loadisFromInstruction(2, t2)
710 loadisFromInstruction(1, t3)
711 loadConstantOrVariableInt32(t0, t1, .slow)
712 loadConstantOrVariableInt32(t2, t0, .slow)
713 integerComparison(t0, t1, t0)
715 storeq t0, [cfr, t3, 8]
719 callSlowPath(slowPath)
725 macro (left, right, result) cieq left, right, result end,
731 macro (left, right, result) cineq left, right, result end,
735 macro equalNullComparison()
736 loadisFromInstruction(2, t0)
737 loadq [cfr, t0, 8], t0
738 btqnz t0, tagMask, .immediate
739 btbnz JSCell::m_flags[t0], MasqueradesAsUndefined, .masqueradesAsUndefined
742 .masqueradesAsUndefined:
743 loadStructureWithScratch(t0, t2, t1)
744 loadp CodeBlock[cfr], t0
745 loadp CodeBlock::m_globalObject[t0], t0
746 cpeq Structure::m_globalObject[t2], t0, t0
749 andq ~TagBitUndefined, t0
750 cqeq t0, ValueNull, t0
756 equalNullComparison()
757 loadisFromInstruction(1, t1)
759 storeq t0, [cfr, t1, 8]
765 equalNullComparison()
766 loadisFromInstruction(1, t1)
768 storeq t0, [cfr, t1, 8]
772 macro strictEq(equalityOperation, slowPath)
774 loadisFromInstruction(3, t0)
775 loadisFromInstruction(2, t2)
776 loadConstantOrVariable(t0, t1)
777 loadConstantOrVariable(t2, t0)
780 btqz t2, tagMask, .slow
781 bqaeq t0, tagTypeNumber, .leftOK
782 btqnz t0, tagTypeNumber, .slow
784 bqaeq t1, tagTypeNumber, .rightOK
785 btqnz t1, tagTypeNumber, .slow
787 equalityOperation(t0, t1, t0)
788 loadisFromInstruction(1, t1)
790 storeq t0, [cfr, t1, 8]
794 callSlowPath(slowPath)
800 macro (left, right, result) cqeq left, right, result end,
806 macro (left, right, result) cqneq left, right, result end,
807 _slow_path_nstricteq)
810 macro preOp(arithmeticOperation, slowPath)
812 loadisFromInstruction(1, t0)
813 loadq [cfr, t0, 8], t1
814 bqb t1, tagTypeNumber, .slow
815 arithmeticOperation(t1, .slow)
816 orq tagTypeNumber, t1
817 storeq t1, [cfr, t0, 8]
821 callSlowPath(slowPath)
827 macro (value, slow) baddio 1, value, slow end,
833 macro (value, slow) bsubio 1, value, slow end,
839 loadisFromInstruction(2, t0)
840 loadisFromInstruction(1, t1)
841 loadConstantOrVariable(t0, t2)
842 bqaeq t2, tagTypeNumber, .opToNumberIsImmediate
843 btqz t2, tagTypeNumber, .opToNumberSlow
844 .opToNumberIsImmediate:
845 storeq t2, [cfr, t1, 8]
849 callSlowPath(_slow_path_to_number)
855 loadisFromInstruction(2, t0)
856 loadisFromInstruction(1, t1)
857 loadConstantOrVariable(t0, t2)
858 bqb t2, tagTypeNumber, .opNegateNotInt
859 btiz t2, 0x7fffffff, .opNegateSlow
861 orq tagTypeNumber, t2
862 storeq t2, [cfr, t1, 8]
865 btqz t2, tagTypeNumber, .opNegateSlow
866 xorq 0x8000000000000000, t2
867 storeq t2, [cfr, t1, 8]
871 callSlowPath(_slow_path_negate)
875 macro binaryOpCustomStore(integerOperationAndStore, doubleOperation, slowPath)
876 loadisFromInstruction(3, t0)
877 loadisFromInstruction(2, t2)
878 loadConstantOrVariable(t0, t1)
879 loadConstantOrVariable(t2, t0)
880 bqb t0, tagTypeNumber, .op1NotInt
881 bqb t1, tagTypeNumber, .op2NotInt
882 loadisFromInstruction(1, t2)
883 integerOperationAndStore(t1, t0, .slow, t2)
887 # First operand is definitely not an int, the second operand could be anything.
888 btqz t0, tagTypeNumber, .slow
889 bqaeq t1, tagTypeNumber, .op1NotIntOp2Int
890 btqz t1, tagTypeNumber, .slow
891 addq tagTypeNumber, t1
897 loadisFromInstruction(1, t2)
898 addq tagTypeNumber, t0
900 doubleOperation(ft1, ft0)
902 subq tagTypeNumber, t0
903 storeq t0, [cfr, t2, 8]
907 # First operand is definitely an int, the second is definitely not.
908 loadisFromInstruction(1, t2)
909 btqz t1, tagTypeNumber, .slow
911 addq tagTypeNumber, t1
913 doubleOperation(ft1, ft0)
915 subq tagTypeNumber, t0
916 storeq t0, [cfr, t2, 8]
920 callSlowPath(slowPath)
924 macro binaryOp(integerOperation, doubleOperation, slowPath)
926 macro (left, right, slow, index)
927 integerOperation(left, right, slow)
928 orq tagTypeNumber, right
929 storeq right, [cfr, index, 8]
931 doubleOperation, slowPath)
937 macro (left, right, slow) baddio left, right, slow end,
938 macro (left, right) addd left, right end,
945 macro (left, right, slow, index)
946 # Assume t3 is scratchable.
948 bmulio left, t3, slow
953 orq tagTypeNumber, t3
954 storeq t3, [cfr, index, 8]
956 macro (left, right) muld left, right end,
963 macro (left, right, slow) bsubio left, right, slow end,
964 macro (left, right) subd left, right end,
972 macro (left, right, slow, index)
973 # Assume t3 is scratchable.
975 bineq left, -1, .notNeg2TwoThe31DivByNeg1
976 bieq right, -2147483648, .slow
977 .notNeg2TwoThe31DivByNeg1:
986 orq tagTypeNumber, t0
987 storeq t0, [cfr, index, 8]
989 macro (left, right) divd left, right end,
992 callSlowPath(_slow_path_div)
997 macro bitOp(operation, slowPath, advance)
998 loadisFromInstruction(3, t0)
999 loadisFromInstruction(2, t2)
1000 loadisFromInstruction(1, t3)
1001 loadConstantOrVariable(t0, t1)
1002 loadConstantOrVariable(t2, t0)
1003 bqb t0, tagTypeNumber, .slow
1004 bqb t1, tagTypeNumber, .slow
1006 orq tagTypeNumber, t0
1007 storeq t0, [cfr, t3, 8]
1011 callSlowPath(slowPath)
1018 macro (left, right) lshifti left, right end,
1026 macro (left, right) rshifti left, right end,
1034 macro (left, right) urshifti left, right end,
1041 loadisFromInstruction(1, t0)
1042 loadisFromInstruction(2, t1)
1043 loadConstantOrVariable(t1, t2)
1044 bilt t2, 0, .opUnsignedSlow
1045 storeq t2, [cfr, t0, 8]
1048 callSlowPath(_slow_path_unsigned)
1055 macro (left, right) andi left, right end,
1063 macro (left, right) xori left, right end,
1071 macro (left, right) ori left, right end,
1076 _llint_op_check_has_instance:
1078 loadisFromInstruction(3, t1)
1079 loadConstantOrVariableCell(t1, t0, .opCheckHasInstanceSlow)
1080 btbz JSCell::m_flags[t0], ImplementsDefaultHasInstance, .opCheckHasInstanceSlow
1083 .opCheckHasInstanceSlow:
1084 callSlowPath(_llint_slow_path_check_has_instance)
1088 _llint_op_instanceof:
1090 # Actually do the work.
1091 loadisFromInstruction(3, t0)
1092 loadConstantOrVariableCell(t0, t1, .opInstanceofSlow)
1093 bbb JSCell::m_type[t1], ObjectType, .opInstanceofSlow
1094 loadisFromInstruction(2, t0)
1095 loadConstantOrVariableCell(t0, t2, .opInstanceofSlow)
1097 # Register state: t1 = prototype, t2 = value
1100 loadStructureAndClobberFirstArg(t2, t3)
1101 loadq Structure::m_prototype[t3], t2
1102 bqeq t2, t1, .opInstanceofDone
1103 btqz t2, tagMask, .opInstanceofLoop
1108 loadisFromInstruction(1, t3)
1109 storeq t0, [cfr, t3, 8]
1113 callSlowPath(_llint_slow_path_instanceof)
1117 _llint_op_is_undefined:
1119 loadisFromInstruction(2, t1)
1120 loadisFromInstruction(1, t2)
1121 loadConstantOrVariable(t1, t0)
1122 btqz t0, tagMask, .opIsUndefinedCell
1123 cqeq t0, ValueUndefined, t3
1125 storeq t3, [cfr, t2, 8]
1128 btbnz JSCell::m_flags[t0], MasqueradesAsUndefined, .masqueradesAsUndefined
1130 storeq t1, [cfr, t2, 8]
1132 .masqueradesAsUndefined:
1133 loadStructureWithScratch(t0, t3, t1)
1134 loadp CodeBlock[cfr], t1
1135 loadp CodeBlock::m_globalObject[t1], t1
1136 cpeq Structure::m_globalObject[t3], t1, t0
1138 storeq t0, [cfr, t2, 8]
1142 _llint_op_is_boolean:
1144 loadisFromInstruction(2, t1)
1145 loadisFromInstruction(1, t2)
1146 loadConstantOrVariable(t1, t0)
1150 storeq t0, [cfr, t2, 8]
1154 _llint_op_is_number:
1156 loadisFromInstruction(2, t1)
1157 loadisFromInstruction(1, t2)
1158 loadConstantOrVariable(t1, t0)
1159 tqnz t0, tagTypeNumber, t1
1161 storeq t1, [cfr, t2, 8]
1165 _llint_op_is_string:
1167 loadisFromInstruction(2, t1)
1168 loadisFromInstruction(1, t2)
1169 loadConstantOrVariable(t1, t0)
1170 btqnz t0, tagMask, .opIsStringNotCell
1171 cbeq JSCell::m_type[t0], StringType, t1
1173 storeq t1, [cfr, t2, 8]
1176 storeq ValueFalse, [cfr, t2, 8]
1180 macro loadPropertyAtVariableOffset(propertyOffsetAsInt, objectAndStorage, value)
1181 bilt propertyOffsetAsInt, firstOutOfLineOffset, .isInline
1182 loadp JSObject::m_butterfly[objectAndStorage], objectAndStorage
1183 negi propertyOffsetAsInt
1184 sxi2q propertyOffsetAsInt, propertyOffsetAsInt
1187 addp sizeof JSObject - (firstOutOfLineOffset - 2) * 8, objectAndStorage
1189 loadq (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffsetAsInt, 8], value
1193 macro storePropertyAtVariableOffset(propertyOffsetAsInt, objectAndStorage, value)
1194 bilt propertyOffsetAsInt, firstOutOfLineOffset, .isInline
1195 loadp JSObject::m_butterfly[objectAndStorage], objectAndStorage
1196 negi propertyOffsetAsInt
1197 sxi2q propertyOffsetAsInt, propertyOffsetAsInt
1200 addp sizeof JSObject - (firstOutOfLineOffset - 2) * 8, objectAndStorage
1202 storeq value, (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffsetAsInt, 8]
1205 _llint_op_init_global_const:
1207 writeBarrierOnGlobalObject(2)
1208 loadisFromInstruction(2, t1)
1209 loadpFromInstruction(1, t0)
1210 loadConstantOrVariable(t1, t2)
1215 macro getById(getPropertyStorage)
1217 # We only do monomorphic get_by_id caching for now, and we do not modify the
1218 # opcode. We do, however, allow for the cache to change anytime if fails, since
1219 # ping-ponging is free. At best we get lucky and the get_by_id will continue
1220 # to take fast path on the new cache. At worst we take slow path, which is what
1221 # we would have been doing anyway.
1222 loadisFromInstruction(2, t0)
1223 loadConstantOrVariableCell(t0, t3, .opGetByIdSlow)
1224 loadStructureWithScratch(t3, t2, t1)
1225 loadpFromInstruction(4, t1)
1226 bpneq t2, t1, .opGetByIdSlow
1230 macro (propertyStorage, scratch)
1231 loadisFromInstruction(5, t2)
1232 loadisFromInstruction(1, t1)
1233 loadq [propertyStorage, t2], scratch
1234 storeq scratch, [cfr, t1, 8]
1235 valueProfile(scratch, 8, t1)
1240 callSlowPath(_llint_slow_path_get_by_id)
1244 _llint_op_get_by_id:
1245 getById(withInlineStorage)
1248 _llint_op_get_by_id_out_of_line:
1249 getById(withOutOfLineStorage)
1252 _llint_op_get_array_length:
1254 loadisFromInstruction(2, t0)
1255 loadpFromInstruction(4, t1)
1256 loadConstantOrVariableCell(t0, t3, .opGetArrayLengthSlow)
1258 arrayProfile(t2, t1, t0)
1259 btiz t2, IsArray, .opGetArrayLengthSlow
1260 btiz t2, IndexingShapeMask, .opGetArrayLengthSlow
1261 loadisFromInstruction(1, t1)
1262 loadp JSObject::m_butterfly[t3], t0
1263 loadi -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], t0
1264 bilt t0, 0, .opGetArrayLengthSlow
1265 orq tagTypeNumber, t0
1266 valueProfile(t0, 8, t2)
1267 storeq t0, [cfr, t1, 8]
1270 .opGetArrayLengthSlow:
1271 callSlowPath(_llint_slow_path_get_by_id)
1275 _llint_op_get_arguments_length:
1277 loadisFromInstruction(2, t0)
1278 loadisFromInstruction(1, t1)
1279 btqnz [cfr, t0, 8], .opGetArgumentsLengthSlow
1280 loadi ArgumentCount + PayloadOffset[cfr], t2
1282 orq tagTypeNumber, t2
1283 storeq t2, [cfr, t1, 8]
1286 .opGetArgumentsLengthSlow:
1287 callSlowPath(_llint_slow_path_get_arguments_length)
1291 macro putById(getPropertyStorage)
1293 writeBarrierOnOperands(1, 3)
1294 loadisFromInstruction(1, t3)
1295 loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
1296 loadStructureWithScratch(t0, t2, t1)
1297 loadpFromInstruction(4, t1)
1298 bpneq t2, t1, .opPutByIdSlow
1302 macro (propertyStorage, scratch)
1303 loadisFromInstruction(5, t1)
1304 loadisFromInstruction(3, t2)
1305 loadConstantOrVariable(t2, scratch)
1306 storeq scratch, [propertyStorage, t1]
1311 _llint_op_put_by_id:
1312 putById(withInlineStorage)
1315 callSlowPath(_llint_slow_path_put_by_id)
1319 _llint_op_put_by_id_out_of_line:
1320 putById(withOutOfLineStorage)
1323 macro putByIdTransition(additionalChecks, getPropertyStorage)
1325 writeBarrierOnOperand(1)
1326 loadisFromInstruction(1, t3)
1327 loadpFromInstruction(4, t1)
1328 loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
1329 loadStructureWithScratch(t0, t2, t3)
1330 bpneq t2, t1, .opPutByIdSlow
1331 additionalChecks(t1, t3, t2)
1332 loadisFromInstruction(3, t2)
1333 loadisFromInstruction(5, t1)
1337 macro (propertyStorage, scratch)
1338 addp t1, propertyStorage, t3
1339 loadConstantOrVariable(t2, t1)
1341 loadpFromInstruction(6, t1)
1342 loadi Structure::m_blob + StructureIDBlob::u.words.word1[t1], t1
1343 storei t1, JSCell::m_structureID[t0]
1348 macro noAdditionalChecks(oldStructure, scratch, scratch2)
1351 macro structureChainChecks(oldStructure, scratch, scratch2)
1352 const protoCell = oldStructure # Reusing the oldStructure register for the proto
1353 loadpFromInstruction(7, scratch)
1354 assert(macro (ok) btpnz scratch, ok end)
1355 loadp StructureChain::m_vector[scratch], scratch
1356 assert(macro (ok) btpnz scratch, ok end)
1357 bqeq Structure::m_prototype[oldStructure], ValueNull, .done
1359 loadq Structure::m_prototype[oldStructure], protoCell
1360 loadStructureAndClobberFirstArg(protoCell, scratch2)
1361 move scratch2, oldStructure
1362 bpneq oldStructure, [scratch], .opPutByIdSlow
1364 bqneq Structure::m_prototype[oldStructure], ValueNull, .loop
1368 _llint_op_put_by_id_transition_direct:
1369 putByIdTransition(noAdditionalChecks, withInlineStorage)
1372 _llint_op_put_by_id_transition_direct_out_of_line:
1373 putByIdTransition(noAdditionalChecks, withOutOfLineStorage)
1376 _llint_op_put_by_id_transition_normal:
1377 putByIdTransition(structureChainChecks, withInlineStorage)
1380 _llint_op_put_by_id_transition_normal_out_of_line:
1381 putByIdTransition(structureChainChecks, withOutOfLineStorage)
1384 _llint_op_get_by_val:
1386 loadisFromInstruction(2, t2)
1387 loadConstantOrVariableCell(t2, t0, .opGetByValSlow)
1388 loadpFromInstruction(4, t3)
1390 arrayProfile(t2, t3, t1)
1391 loadisFromInstruction(3, t3)
1392 loadConstantOrVariableInt32(t3, t1, .opGetByValSlow)
1394 loadp JSObject::m_butterfly[t0], t3
1395 andi IndexingShapeMask, t2
1396 bieq t2, Int32Shape, .opGetByValIsContiguous
1397 bineq t2, ContiguousShape, .opGetByValNotContiguous
1398 .opGetByValIsContiguous:
1400 biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t3], .opGetByValOutOfBounds
1401 loadisFromInstruction(1, t0)
1402 loadq [t3, t1, 8], t2
1403 btqz t2, .opGetByValOutOfBounds
1406 .opGetByValNotContiguous:
1407 bineq t2, DoubleShape, .opGetByValNotDouble
1408 biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t3], .opGetByValOutOfBounds
1409 loadis 8[PB, PC, 8], t0
1410 loadd [t3, t1, 8], ft0
1411 bdnequn ft0, ft0, .opGetByValOutOfBounds
1413 subq tagTypeNumber, t2
1416 .opGetByValNotDouble:
1417 subi ArrayStorageShape, t2
1418 bia t2, SlowPutArrayStorageShape - ArrayStorageShape, .opGetByValSlow
1419 biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t3], .opGetByValOutOfBounds
1420 loadisFromInstruction(1, t0)
1421 loadq ArrayStorage::m_vector[t3, t1, 8], t2
1422 btqz t2, .opGetByValOutOfBounds
1425 storeq t2, [cfr, t0, 8]
1426 valueProfile(t2, 5, t0)
1429 .opGetByValOutOfBounds:
1430 loadpFromInstruction(4, t0)
1431 storeb 1, ArrayProfile::m_outOfBounds[t0]
1433 callSlowPath(_llint_slow_path_get_by_val)
1437 _llint_op_get_argument_by_val:
1438 # FIXME: At some point we should array profile this. Right now it isn't necessary
1439 # since the DFG will never turn a get_argument_by_val into a GetByVal.
1441 loadisFromInstruction(2, t0)
1442 loadisFromInstruction(3, t1)
1443 btqnz [cfr, t0, 8], .opGetArgumentByValSlow
1444 loadConstantOrVariableInt32(t1, t2, .opGetArgumentByValSlow)
1446 loadi ArgumentCount + PayloadOffset[cfr], t1
1447 biaeq t2, t1, .opGetArgumentByValSlow
1448 loadisFromInstruction(1, t3)
1449 loadpFromInstruction(5, t1)
1450 loadq ThisArgumentOffset[cfr, t2, 8], t0
1451 storeq t0, [cfr, t3, 8]
1452 valueProfile(t0, 5, t1)
1455 .opGetArgumentByValSlow:
1456 callSlowPath(_llint_slow_path_get_argument_by_val)
1460 _llint_op_get_by_pname:
1462 loadisFromInstruction(3, t1)
1463 loadConstantOrVariable(t1, t0)
1464 loadisFromInstruction(4, t1)
1465 assertNotConstant(t1)
1466 bqneq t0, [cfr, t1, 8], .opGetByPnameSlow
1467 loadisFromInstruction(2, t2)
1468 loadisFromInstruction(5, t3)
1469 loadConstantOrVariableCell(t2, t0, .opGetByPnameSlow)
1470 assertNotConstant(t3)
1471 loadq [cfr, t3, 8], t1
1472 loadStructureWithScratch(t0, t2, t3)
1473 bpneq t2, JSPropertyNameIterator::m_cachedStructure[t1], .opGetByPnameSlow
1474 loadisFromInstruction(6, t3)
1475 loadi PayloadOffset[cfr, t3, 8], t3
1477 biaeq t3, JSPropertyNameIterator::m_numCacheableSlots[t1], .opGetByPnameSlow
1478 bilt t3, JSPropertyNameIterator::m_cachedStructureInlineCapacity[t1], .opGetByPnameInlineProperty
1479 addi firstOutOfLineOffset, t3
1480 subi JSPropertyNameIterator::m_cachedStructureInlineCapacity[t1], t3
1481 .opGetByPnameInlineProperty:
1482 loadPropertyAtVariableOffset(t3, t0, t0)
1483 loadisFromInstruction(1, t1)
1484 storeq t0, [cfr, t1, 8]
1488 callSlowPath(_llint_slow_path_get_by_pname)
1492 macro contiguousPutByVal(storeCallback)
1493 biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], .outOfBounds
1495 loadisFromInstruction(3, t2)
1496 storeCallback(t2, t1, [t0, t3, 8])
1500 biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t0], .opPutByValOutOfBounds
1501 loadp 32[PB, PC, 8], t2
1502 storeb 1, ArrayProfile::m_mayStoreToHole[t2]
1504 storei t2, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0]
1508 macro putByVal(holeCheck, slowPath)
1510 writeBarrierOnOperands(1, 3)
1511 loadisFromInstruction(1, t0)
1512 loadConstantOrVariableCell(t0, t1, .opPutByValSlow)
1513 loadpFromInstruction(4, t3)
1515 arrayProfile(t2, t3, t0)
1516 loadisFromInstruction(2, t0)
1517 loadConstantOrVariableInt32(t0, t3, .opPutByValSlow)
1519 loadp JSObject::m_butterfly[t1], t0
1520 andi IndexingShapeMask, t2
1521 bineq t2, Int32Shape, .opPutByValNotInt32
1523 macro (operand, scratch, address)
1524 loadConstantOrVariable(operand, scratch)
1525 bpb scratch, tagTypeNumber, .opPutByValSlow
1526 storep scratch, address
1529 .opPutByValNotInt32:
1530 bineq t2, DoubleShape, .opPutByValNotDouble
1532 macro (operand, scratch, address)
1533 loadConstantOrVariable(operand, scratch)
1534 bqb scratch, tagTypeNumber, .notInt
1538 addp tagTypeNumber, scratch
1540 bdnequn ft0, ft0, .opPutByValSlow
1545 .opPutByValNotDouble:
1546 bineq t2, ContiguousShape, .opPutByValNotContiguous
1548 macro (operand, scratch, address)
1549 loadConstantOrVariable(operand, scratch)
1550 storep scratch, address
1553 .opPutByValNotContiguous:
1554 bineq t2, ArrayStorageShape, .opPutByValSlow
1555 biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t0], .opPutByValOutOfBounds
1556 holeCheck(ArrayStorage::m_vector[t0, t3, 8], .opPutByValArrayStorageEmpty)
1557 .opPutByValArrayStorageStoreResult:
1558 loadisFromInstruction(3, t2)
1559 loadConstantOrVariable(t2, t1)
1560 storeq t1, ArrayStorage::m_vector[t0, t3, 8]
1563 .opPutByValArrayStorageEmpty:
1564 loadpFromInstruction(4, t1)
1565 storeb 1, ArrayProfile::m_mayStoreToHole[t1]
1566 addi 1, ArrayStorage::m_numValuesInVector[t0]
1567 bib t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], .opPutByValArrayStorageStoreResult
1569 storei t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0]
1570 jmp .opPutByValArrayStorageStoreResult
1572 .opPutByValOutOfBounds:
1573 loadpFromInstruction(4, t0)
1574 storeb 1, ArrayProfile::m_outOfBounds[t0]
1576 callSlowPath(slowPath)
1580 _llint_op_put_by_val:
1581 putByVal(macro(slot, slowPath)
1583 end, _llint_slow_path_put_by_val)
1585 _llint_op_put_by_val_direct:
1586 putByVal(macro(slot, slowPath)
1587 end, _llint_slow_path_put_by_val_direct)
1592 dispatchIntIndirect(1)
1595 macro jumpTrueOrFalse(conditionOp, slow)
1596 loadisFromInstruction(1, t1)
1597 loadConstantOrVariable(t1, t0)
1600 conditionOp(t0, .target)
1604 dispatchIntIndirect(2)
1612 macro equalNull(cellHandler, immediateHandler)
1613 loadisFromInstruction(1, t0)
1614 assertNotConstant(t0)
1615 loadq [cfr, t0, 8], t0
1616 btqnz t0, tagMask, .immediate
1617 loadStructureWithScratch(t0, t2, t1)
1618 cellHandler(t2, JSCell::m_flags[t0], .target)
1622 dispatchIntIndirect(2)
1625 andq ~TagBitUndefined, t0
1626 immediateHandler(t0, .target)
1633 macro (structure, value, target)
1634 btbz value, MasqueradesAsUndefined, .notMasqueradesAsUndefined
1635 loadp CodeBlock[cfr], t0
1636 loadp CodeBlock::m_globalObject[t0], t0
1637 bpeq Structure::m_globalObject[structure], t0, target
1638 .notMasqueradesAsUndefined:
1640 macro (value, target) bqeq value, ValueNull, target end)
1643 _llint_op_jneq_null:
1646 macro (structure, value, target)
1647 btbz value, MasqueradesAsUndefined, target
1648 loadp CodeBlock[cfr], t0
1649 loadp CodeBlock::m_globalObject[t0], t0
1650 bpneq Structure::m_globalObject[structure], t0, target
1652 macro (value, target) bqneq value, ValueNull, target end)
1657 loadisFromInstruction(1, t0)
1658 loadisFromInstruction(2, t1)
1659 loadp CodeBlock[cfr], t2
1660 loadp CodeBlock::m_globalObject[t2], t2
1661 loadp JSGlobalObject::m_specialPointers[t2, t1, 8], t1
1662 bpneq t1, [cfr, t0, 8], .opJneqPtrTarget
1666 dispatchIntIndirect(3)
1669 macro compare(integerCompare, doubleCompare, slowPath)
1670 loadisFromInstruction(1, t2)
1671 loadisFromInstruction(2, t3)
1672 loadConstantOrVariable(t2, t0)
1673 loadConstantOrVariable(t3, t1)
1674 bqb t0, tagTypeNumber, .op1NotInt
1675 bqb t1, tagTypeNumber, .op2NotInt
1676 integerCompare(t0, t1, .jumpTarget)
1680 btqz t0, tagTypeNumber, .slow
1681 bqb t1, tagTypeNumber, .op1NotIntOp2NotInt
1684 .op1NotIntOp2NotInt:
1685 btqz t1, tagTypeNumber, .slow
1686 addq tagTypeNumber, t1
1689 addq tagTypeNumber, t0
1691 doubleCompare(ft0, ft1, .jumpTarget)
1696 btqz t1, tagTypeNumber, .slow
1697 addq tagTypeNumber, t1
1699 doubleCompare(ft0, ft1, .jumpTarget)
1703 dispatchIntIndirect(3)
1706 callSlowPath(slowPath)
1711 _llint_op_switch_imm:
1713 loadisFromInstruction(3, t2)
1714 loadisFromInstruction(1, t3)
1715 loadConstantOrVariable(t2, t1)
1716 loadp CodeBlock[cfr], t2
1717 loadp CodeBlock::m_rareData[t2], t2
1718 muli sizeof SimpleJumpTable, t3 # FIXME: would be nice to peephole this!
1719 loadp CodeBlock::RareData::m_switchJumpTables + VectorBufferOffset[t2], t2
1721 bqb t1, tagTypeNumber, .opSwitchImmNotInt
1722 subi SimpleJumpTable::min[t2], t1
1723 biaeq t1, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchImmFallThrough
1724 loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t3
1725 loadis [t3, t1, 4], t1
1726 btiz t1, .opSwitchImmFallThrough
1730 btqnz t1, tagTypeNumber, .opSwitchImmSlow # Go slow if it's a double.
1731 .opSwitchImmFallThrough:
1732 dispatchIntIndirect(2)
1735 callSlowPath(_llint_slow_path_switch_imm)
1739 _llint_op_switch_char:
1741 loadisFromInstruction(3, t2)
1742 loadisFromInstruction(1, t3)
1743 loadConstantOrVariable(t2, t1)
1744 loadp CodeBlock[cfr], t2
1745 loadp CodeBlock::m_rareData[t2], t2
1746 muli sizeof SimpleJumpTable, t3
1747 loadp CodeBlock::RareData::m_switchJumpTables + VectorBufferOffset[t2], t2
1749 btqnz t1, tagMask, .opSwitchCharFallThrough
1750 bbneq JSCell::m_type[t1], StringType, .opSwitchCharFallThrough
1751 bineq JSString::m_length[t1], 1, .opSwitchCharFallThrough
1752 loadp JSString::m_value[t1], t0
1753 btpz t0, .opSwitchOnRope
1754 loadp StringImpl::m_data8[t0], t1
1755 btinz StringImpl::m_hashAndFlags[t0], HashFlags8BitBuffer, .opSwitchChar8Bit
1757 jmp .opSwitchCharReady
1761 subi SimpleJumpTable::min[t2], t0
1762 biaeq t0, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchCharFallThrough
1763 loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t2
1764 loadis [t2, t0, 4], t1
1765 btiz t1, .opSwitchCharFallThrough
1768 .opSwitchCharFallThrough:
1769 dispatchIntIndirect(2)
1772 callSlowPath(_llint_slow_path_switch_char)
1778 loadisFromInstruction(3, t2)
1779 btiz t2, .opNewFuncUnchecked
1780 loadisFromInstruction(1, t1)
1781 btqnz [cfr, t1, 8], .opNewFuncDone
1782 .opNewFuncUnchecked:
1783 callSlowPath(_llint_slow_path_new_func)
1788 _llint_op_new_captured_func:
1790 callSlowPath(_slow_path_new_captured_func)
1794 macro arrayProfileForCall()
1795 loadisFromInstruction(4, t3)
1797 loadq ThisArgumentOffset[cfr, t3, 8], t0
1798 btqnz t0, tagMask, .done
1799 loadpFromInstruction((CallOpCodeSize - 2), t1)
1800 loadi JSCell::m_structureID[t0], t3
1801 storei t3, ArrayProfile::m_lastSeenStructureID[t1]
1805 macro doCall(slowPath)
1806 loadisFromInstruction(2, t0)
1807 loadpFromInstruction(5, t1)
1808 loadp LLIntCallLinkInfo::callee[t1], t2
1809 loadConstantOrVariable(t0, t3)
1810 bqneq t3, t2, .opCallSlow
1811 loadisFromInstruction(4, t3)
1815 loadp JSFunction::m_scope[t2], t0
1816 storeq t2, Callee[t3]
1817 storeq t0, ScopeChain[t3]
1818 loadisFromInstruction(3, t2)
1819 storei PC, ArgumentCount + TagOffset[cfr]
1820 storei t2, ArgumentCount + PayloadOffset[t3]
1821 addp CallerFrameAndPCSize, t3
1822 callTargetFunction(t1, t3)
1825 slowPathForCall(slowPath)
1829 _llint_op_tear_off_activation:
1831 loadisFromInstruction(1, t0)
1832 btqz [cfr, t0, 8], .opTearOffActivationNotCreated
1833 callSlowPath(_llint_slow_path_tear_off_activation)
1834 .opTearOffActivationNotCreated:
1838 _llint_op_tear_off_arguments:
1840 loadisFromInstruction(1, t0)
1841 addq 1, t0 # Get the unmodifiedArgumentsRegister
1842 btqz [cfr, t0, 8], .opTearOffArgumentsNotCreated
1843 callSlowPath(_llint_slow_path_tear_off_arguments)
1844 .opTearOffArgumentsNotCreated:
1850 checkSwitchToJITForEpilogue()
1851 loadisFromInstruction(1, t2)
1852 loadConstantOrVariable(t2, t0)
1856 _llint_op_ret_object_or_this:
1858 checkSwitchToJITForEpilogue()
1859 loadisFromInstruction(1, t2)
1860 loadConstantOrVariable(t2, t0)
1861 btqnz t0, tagMask, .opRetObjectOrThisNotObject
1862 bbb JSCell::m_type[t0], ObjectType, .opRetObjectOrThisNotObject
1865 .opRetObjectOrThisNotObject:
1866 loadisFromInstruction(2, t2)
1867 loadConstantOrVariable(t2, t0)
1871 _llint_op_to_primitive:
1873 loadisFromInstruction(2, t2)
1874 loadisFromInstruction(1, t3)
1875 loadConstantOrVariable(t2, t0)
1876 btqnz t0, tagMask, .opToPrimitiveIsImm
1877 bbneq JSCell::m_type[t0], StringType, .opToPrimitiveSlowCase
1878 .opToPrimitiveIsImm:
1879 storeq t0, [cfr, t3, 8]
1882 .opToPrimitiveSlowCase:
1883 callSlowPath(_slow_path_to_primitive)
1887 _llint_op_next_pname:
1889 loadisFromInstruction(3, t1)
1890 loadisFromInstruction(4, t2)
1891 assertNotConstant(t1)
1892 assertNotConstant(t2)
1893 loadi PayloadOffset[cfr, t1, 8], t0
1894 bieq t0, PayloadOffset[cfr, t2, 8], .opNextPnameEnd
1895 loadisFromInstruction(5, t2)
1896 assertNotConstant(t2)
1897 loadp [cfr, t2, 8], t2
1898 loadp JSPropertyNameIterator::m_jsStrings[t2], t3
1899 loadq [t3, t0, 8], t3
1901 storei t0, PayloadOffset[cfr, t1, 8]
1902 loadisFromInstruction(1, t1)
1903 storeq t3, [cfr, t1, 8]
1904 loadisFromInstruction(2, t3)
1905 assertNotConstant(t3)
1906 loadq [cfr, t3, 8], t3
1907 loadStructureWithScratch(t3, t1, t0)
1908 bpneq t1, JSPropertyNameIterator::m_cachedStructure[t2], .opNextPnameSlow
1909 loadp JSPropertyNameIterator::m_cachedPrototypeChain[t2], t0
1910 loadp StructureChain::m_vector[t0], t0
1911 btpz [t0], .opNextPnameTarget
1912 .opNextPnameCheckPrototypeLoop:
1913 bqeq Structure::m_prototype[t1], ValueNull, .opNextPnameSlow
1914 loadq Structure::m_prototype[t1], t2
1915 loadStructureWithScratch(t2, t1, t3)
1916 bpneq t1, [t0], .opNextPnameSlow
1918 btpnz [t0], .opNextPnameCheckPrototypeLoop
1920 dispatchIntIndirect(6)
1926 callSlowPath(_llint_slow_path_next_pname) # This either keeps the PC where it was (causing us to loop) or sets it to target.
1931 # This is where we end up from the JIT's throw trampoline (because the
1932 # machine code return address will be set to _llint_op_catch), and from
1933 # the interpreter's throw trampoline (see _llint_throw_trampoline).
1934 # The throwing code must have known that we were throwing to the interpreter,
1935 # and have set VM::targetInterpreterPCForThrow.
1936 loadp ScopeChain[cfr], t3
1937 andp MarkedBlockMask, t3
1938 loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
1939 loadp VM::callFrameForThrow[t3], cfr
1940 restoreStackPointerAfterCall()
1942 loadp CodeBlock[cfr], PB
1943 loadp CodeBlock::m_instructions[PB], PB
1944 loadp VM::targetInterpreterPCForThrow[t3], PC
1947 loadq VM::m_exception[t3], t0
1948 storeq 0, VM::m_exception[t3]
1949 loadisFromInstruction(1, t2)
1950 storeq t0, [cfr, t2, 8]
1957 checkSwitchToJITForEpilogue()
1958 loadisFromInstruction(1, t0)
1959 assertNotConstant(t0)
1960 loadq [cfr, t0, 8], t0
1964 _llint_throw_from_slow_path_trampoline:
1965 callSlowPath(_llint_slow_path_handle_exception)
1967 # When throwing from the interpreter (i.e. throwing from LLIntSlowPaths), so
1968 # the throw target is not necessarily interpreted code, we come to here.
1969 # This essentially emulates the JIT's throwing protocol.
1970 loadp CodeBlock[cfr], t1
1971 loadp CodeBlock::m_vm[t1], t1
1972 jmp VM::targetMachinePCForThrow[t1]
1975 _llint_throw_during_call_trampoline:
1976 preserveReturnAddressAfterCall(t2)
1977 jmp _llint_throw_from_slow_path_trampoline
1980 macro nativeCallTrampoline(executableOffsetToFunction)
1983 storep 0, CodeBlock[cfr]
1985 loadp ScopeChain[cfr], t0
1986 andp MarkedBlockMask, t0
1987 loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t0], t0
1988 storep cfr, VM::topCallFrame[t0]
1989 loadp CallerFrame[cfr], t0
1990 loadq ScopeChain[t0], t1
1991 storeq t1, ScopeChain[cfr]
1992 move cfr, t4 # t4 = rdi
1993 loadp Callee[cfr], t5 # t5 = rsi
1994 loadp JSFunction::m_executable[t5], t1
1995 checkStackPointerAlignment(t3, 0xdead0001)
1996 call executableOffsetToFunction[t1]
1997 loadp ScopeChain[cfr], t3
1998 andp MarkedBlockMask, t3
1999 loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
2000 elsif ARM64 or C_LOOP
2001 loadp ScopeChain[cfr], t0
2002 andp MarkedBlockMask, t0
2003 loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t0], t0
2004 storep cfr, VM::topCallFrame[t0]
2005 loadp CallerFrame[cfr], t2
2006 loadp ScopeChain[t2], t1
2007 storep t1, ScopeChain[cfr]
2008 preserveReturnAddressAfterCall(t3)
2009 storep t3, ReturnPC[cfr]
2011 loadp Callee[cfr], t1
2012 loadp JSFunction::m_executable[t1], t1
2013 move t2, cfr # Restore cfr to avoid loading from stack
2015 cloopCallNative executableOffsetToFunction[t1]
2017 call executableOffsetToFunction[t1]
2019 restoreReturnAddressBeforeReturn(t3)
2020 loadp ScopeChain[cfr], t3
2021 andp MarkedBlockMask, t3
2022 loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
2029 btqnz VM::m_exception[t3], .handleException
2033 storep cfr, VM::topCallFrame[t3]
2034 restoreStackPointerAfterCall()
2035 jmp _llint_throw_from_slow_path_trampoline
2039 macro getGlobalObject(dst)
2040 loadp CodeBlock[cfr], t0
2041 loadp CodeBlock::m_globalObject[t0], t0
2042 loadisFromInstruction(dst, t1)
2043 storeq t0, [cfr, t1, 8]
2046 macro varInjectionCheck(slowPath)
2047 loadp CodeBlock[cfr], t0
2048 loadp CodeBlock::m_globalObject[t0], t0
2049 loadp JSGlobalObject::m_varInjectionWatchpoint[t0], t0
2050 bbeq WatchpointSet::m_state[t0], IsInvalidated, slowPath
2053 macro resolveScope()
2054 loadp CodeBlock[cfr], t0
2055 loadisFromInstruction(4, t2)
2056 btbz CodeBlock::m_needsActivation[t0], .resolveScopeAfterActivationCheck
2057 loadis CodeBlock::m_activationRegister[t0], t1
2058 btpz [cfr, t1, 8], .resolveScopeAfterActivationCheck
2061 .resolveScopeAfterActivationCheck:
2062 loadp ScopeChain[cfr], t0
2063 btiz t2, .resolveScopeLoopEnd
2066 loadp JSScope::m_next[t0], t0
2068 btinz t2, .resolveScopeLoop
2070 .resolveScopeLoopEnd:
2071 loadisFromInstruction(1, t1)
2072 storeq t0, [cfr, t1, 8]
2076 _llint_op_resolve_scope:
2078 loadisFromInstruction(3, t0)
2081 bineq t0, GlobalProperty, .rGlobalVar
2086 bineq t0, GlobalVar, .rClosureVar
2091 bineq t0, ClosureVar, .rGlobalPropertyWithVarInjectionChecks
2095 .rGlobalPropertyWithVarInjectionChecks:
2096 bineq t0, GlobalPropertyWithVarInjectionChecks, .rGlobalVarWithVarInjectionChecks
2097 varInjectionCheck(.rDynamic)
2101 .rGlobalVarWithVarInjectionChecks:
2102 bineq t0, GlobalVarWithVarInjectionChecks, .rClosureVarWithVarInjectionChecks
2103 varInjectionCheck(.rDynamic)
2107 .rClosureVarWithVarInjectionChecks:
2108 bineq t0, ClosureVarWithVarInjectionChecks, .rDynamic
2109 varInjectionCheck(.rDynamic)
2114 callSlowPath(_llint_slow_path_resolve_scope)
2118 macro loadWithStructureCheck(operand, slowPath)
2119 loadisFromInstruction(operand, t0)
2120 loadq [cfr, t0, 8], t0
2121 loadStructureWithScratch(t0, t2, t1)
2122 loadpFromInstruction(5, t1)
2123 bpneq t2, t1, slowPath
2127 loadisFromInstruction(6, t1)
2128 loadPropertyAtVariableOffset(t1, t0, t2)
2129 valueProfile(t2, 7, t0)
2130 loadisFromInstruction(1, t0)
2131 storeq t2, [cfr, t0, 8]
2134 macro getGlobalVar()
2135 loadpFromInstruction(6, t0)
2137 valueProfile(t0, 7, t1)
2138 loadisFromInstruction(1, t1)
2139 storeq t0, [cfr, t1, 8]
2142 macro getClosureVar()
2143 loadp JSVariableObject::m_registers[t0], t0
2144 loadisFromInstruction(6, t1)
2145 loadq [t0, t1, 8], t0
2146 valueProfile(t0, 7, t1)
2147 loadisFromInstruction(1, t1)
2148 storeq t0, [cfr, t1, 8]
2151 _llint_op_get_from_scope:
2153 loadisFromInstruction(4, t0)
2154 andi ResolveModeMask, t0
2157 bineq t0, GlobalProperty, .gGlobalVar
2158 loadWithStructureCheck(2, .gDynamic)
2163 bineq t0, GlobalVar, .gClosureVar
2168 bineq t0, ClosureVar, .gGlobalPropertyWithVarInjectionChecks
2173 .gGlobalPropertyWithVarInjectionChecks:
2174 bineq t0, GlobalPropertyWithVarInjectionChecks, .gGlobalVarWithVarInjectionChecks
2175 loadWithStructureCheck(2, .gDynamic)
2179 .gGlobalVarWithVarInjectionChecks:
2180 bineq t0, GlobalVarWithVarInjectionChecks, .gClosureVarWithVarInjectionChecks
2181 varInjectionCheck(.gDynamic)
2186 .gClosureVarWithVarInjectionChecks:
2187 bineq t0, ClosureVarWithVarInjectionChecks, .gDynamic
2188 varInjectionCheck(.gDynamic)
2194 callSlowPath(_llint_slow_path_get_from_scope)
2199 loadisFromInstruction(3, t1)
2200 loadConstantOrVariable(t1, t2)
2201 loadisFromInstruction(6, t1)
2202 storePropertyAtVariableOffset(t1, t0, t2)
2205 macro putGlobalVar()
2206 loadisFromInstruction(3, t0)
2207 loadConstantOrVariable(t0, t1)
2208 loadpFromInstruction(5, t2)
2209 notifyWrite(t2, t1, t0, .pDynamic)
2210 loadpFromInstruction(6, t0)
2214 macro putClosureVar()
2215 loadisFromInstruction(3, t1)
2216 loadConstantOrVariable(t1, t2)
2217 loadp JSVariableObject::m_registers[t0], t0
2218 loadisFromInstruction(6, t1)
2219 storeq t2, [t0, t1, 8]
2223 _llint_op_put_to_scope:
2225 loadisFromInstruction(4, t0)
2226 andi ResolveModeMask, t0
2229 bineq t0, GlobalProperty, .pGlobalVar
2230 writeBarrierOnOperands(1, 3)
2231 loadWithStructureCheck(1, .pDynamic)
2236 bineq t0, GlobalVar, .pClosureVar
2237 writeBarrierOnGlobalObject(3)
2242 bineq t0, ClosureVar, .pGlobalPropertyWithVarInjectionChecks
2243 writeBarrierOnOperands(1, 3)
2248 .pGlobalPropertyWithVarInjectionChecks:
2249 bineq t0, GlobalPropertyWithVarInjectionChecks, .pGlobalVarWithVarInjectionChecks
2250 writeBarrierOnOperands(1, 3)
2251 loadWithStructureCheck(1, .pDynamic)
2255 .pGlobalVarWithVarInjectionChecks:
2256 bineq t0, GlobalVarWithVarInjectionChecks, .pClosureVarWithVarInjectionChecks
2257 writeBarrierOnGlobalObject(3)
2258 varInjectionCheck(.pDynamic)
2262 .pClosureVarWithVarInjectionChecks:
2263 bineq t0, ClosureVarWithVarInjectionChecks, .pDynamic
2264 writeBarrierOnOperands(1, 3)
2265 varInjectionCheck(.pDynamic)
2271 callSlowPath(_llint_slow_path_put_to_scope)