1 # Copyright (C) 2011, 2012 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.
25 # Some value representation constants.
26 const TagBitTypeOther = 0x2
27 const TagBitBool = 0x4
28 const TagBitUndefined = 0x8
29 const ValueEmpty = 0x0
30 const ValueFalse = TagBitTypeOther | TagBitBool
31 const ValueTrue = TagBitTypeOther | TagBitBool | 1
32 const ValueUndefined = TagBitTypeOther | TagBitUndefined
33 const ValueNull = TagBitTypeOther
36 macro dispatch(advance)
41 macro dispatchInt(advance)
46 macro dispatchAfterCall()
47 loadi ArgumentCount + TagOffset[cfr], PC
48 loadp CodeBlock[cfr], PB
49 loadp CodeBlock::m_instructions[PB], PB
53 macro cCall2(function, arg1, arg2)
59 # This barely works. arg3 and arg4 should probably be immediates.
60 macro cCall4(function, arg1, arg2, arg3, arg4)
68 macro prepareStateForCCall()
73 macro restoreStateAfterCCall()
81 macro callSlowPath(slowPath)
82 prepareStateForCCall()
83 cCall2(slowPath, cfr, PC)
84 restoreStateAfterCCall()
87 macro traceOperand(fromWhere, operand)
88 prepareStateForCCall()
89 cCall4(_llint_trace_operand, cfr, PC, fromWhere, operand)
90 restoreStateAfterCCall()
93 macro traceValue(fromWhere, operand)
94 prepareStateForCCall()
95 cCall4(_llint_trace_value, cfr, PC, fromWhere, operand)
96 restoreStateAfterCCall()
99 # Call a slow path for call call opcodes.
100 macro callCallSlowPath(advance, slowPath, action)
102 storei t0, ArgumentCount + TagOffset[cfr]
103 prepareStateForCCall()
104 cCall2(slowPath, cfr, PC)
109 macro checkSwitchToJITForLoop()
113 storei PC, ArgumentCount + TagOffset[cfr]
114 prepareStateForCCall()
115 cCall2(_llint_loop_osr, cfr, PC)
121 loadi ArgumentCount + TagOffset[cfr], PC
125 # Index and value must be different registers. Index may be clobbered.
126 macro loadConstantOrVariable(index, value)
127 bpgteq index, FirstConstantRegisterIndex, .constant
128 loadp [cfr, index, 8], value
131 loadp CodeBlock[cfr], value
132 loadp CodeBlock::m_constantRegisters + VectorBufferOffset[value], value
133 subp FirstConstantRegisterIndex, index
134 loadp [value, index, 8], value
138 macro loadConstantOrVariableInt32(index, value, slow)
139 loadConstantOrVariable(index, value)
140 bpb value, tagTypeNumber, slow
143 macro loadConstantOrVariableCell(index, value, slow)
144 loadConstantOrVariable(index, value)
145 btpnz value, tagMask, slow
148 macro writeBarrier(value)
149 # Nothing to do, since we don't have a generational or incremental collector.
152 macro valueProfile(value, profile)
154 storep value, ValueProfile::m_buckets[profile]
159 # Entrypoints into the interpreter.
161 # Expects that CodeBlock is in t1, which is what prologue() leaves behind.
162 macro functionArityCheck(doneLabel, slow_path)
163 loadi PayloadOffset + ArgumentCount[cfr], t0
164 biaeq t0, CodeBlock::m_numParameters[t1], doneLabel
165 prepareStateForCCall()
166 cCall2(slow_path, cfr, PC) # This slow_path has a simple protocol: t0 = 0 => no error, t0 != 0 => error
169 loadp JITStackFrame::globalData[sp], t1
170 loadp JSGlobalData::callFrameForThrow[t1], t0
171 jmp JSGlobalData::targetMachinePCForThrow[t1]
173 # Reload CodeBlock and reset PC, since the slow_path clobbered them.
174 loadp CodeBlock[cfr], t1
175 loadp CodeBlock::m_instructions[t1], PB
181 # Instruction implementations
185 loadp CodeBlock[cfr], t2
186 loadi CodeBlock::m_numVars[t2], t2
187 btiz t2, .opEnterDone
188 move ValueUndefined, t0
191 storep t0, [cfr, t2, 8]
192 btinz t2, .opEnterLoop
197 _llint_op_create_activation:
199 loadis 8[PB, PC, 8], t0
200 bpneq [cfr, t0, 8], ValueEmpty, .opCreateActivationDone
201 callSlowPath(_llint_slow_path_create_activation)
202 .opCreateActivationDone:
206 _llint_op_init_lazy_reg:
208 loadis 8[PB, PC, 8], t0
209 storep ValueEmpty, [cfr, t0, 8]
213 _llint_op_create_arguments:
215 loadis 8[PB, PC, 8], t0
216 bpneq [cfr, t0, 8], ValueEmpty, .opCreateArgumentsDone
217 callSlowPath(_llint_slow_path_create_arguments)
218 .opCreateArgumentsDone:
222 _llint_op_create_this:
224 loadis 16[PB, PC, 8], t0
225 assertNotConstant(t0)
226 loadp [cfr, t0, 8], t0
227 btpnz t0, tagMask, .opCreateThisSlow
228 loadp JSCell::m_structure[t0], t1
229 bbb Structure::m_typeInfo + TypeInfo::m_type[t1], ObjectType, .opCreateThisSlow
230 loadp JSObject::m_inheritorID[t0], t2
231 btpz t2, .opCreateThisSlow
232 allocateBasicJSObject(JSFinalObjectSizeClassIndex, JSGlobalData::jsFinalObjectClassInfo, t2, t0, t1, t3, .opCreateThisSlow)
233 loadis 8[PB, PC, 8], t1
234 storep t0, [cfr, t1, 8]
238 callSlowPath(_llint_slow_path_create_this)
242 _llint_op_get_callee:
244 loadis 8[PB, PC, 8], t0
245 loadp Callee[cfr], t1
246 storep t1, [cfr, t0, 8]
250 _llint_op_convert_this:
252 loadis 8[PB, PC, 8], t0
253 loadp [cfr, t0, 8], t0
254 btpnz t0, tagMask, .opConvertThisSlow
255 loadp JSCell::m_structure[t0], t0
256 bbb Structure::m_typeInfo + TypeInfo::m_type[t0], ObjectType, .opConvertThisSlow
260 callSlowPath(_llint_slow_path_convert_this)
264 _llint_op_new_object:
266 loadp CodeBlock[cfr], t0
267 loadp CodeBlock::m_globalObject[t0], t0
268 loadp JSGlobalObject::m_emptyObjectStructure[t0], t1
269 allocateBasicJSObject(JSFinalObjectSizeClassIndex, JSGlobalData::jsFinalObjectClassInfo, t1, t0, t2, t3, .opNewObjectSlow)
270 loadis 8[PB, PC, 8], t1
271 storep t0, [cfr, t1, 8]
275 callSlowPath(_llint_slow_path_new_object)
281 loadis 16[PB, PC, 8], t1
282 loadis 8[PB, PC, 8], t0
283 loadConstantOrVariable(t1, t2)
284 storep t2, [cfr, t0, 8]
290 loadis 16[PB, PC, 8], t0
291 loadis 8[PB, PC, 8], t1
292 loadConstantOrVariable(t0, t2)
294 btpnz t2, ~1, .opNotSlow
296 storep t2, [cfr, t1, 8]
300 callSlowPath(_llint_slow_path_not)
304 macro equalityComparison(integerComparison, slowPath)
306 loadis 24[PB, PC, 8], t0
307 loadis 16[PB, PC, 8], t2
308 loadis 8[PB, PC, 8], t3
309 loadConstantOrVariableInt32(t0, t1, .slow)
310 loadConstantOrVariableInt32(t2, t0, .slow)
311 integerComparison(t0, t1, t0)
313 storep t0, [cfr, t3, 8]
317 callSlowPath(slowPath)
323 macro (left, right, result) cieq left, right, result end,
329 macro (left, right, result) cineq left, right, result end,
330 _llint_slow_path_neq)
333 macro equalNullComparison()
334 loadis 16[PB, PC, 8], t0
335 loadp [cfr, t0, 8], t0
336 btpnz t0, tagMask, .immediate
337 loadp JSCell::m_structure[t0], t2
338 tbnz Structure::m_typeInfo + TypeInfo::m_flags[t2], MasqueradesAsUndefined, t0
341 andp ~TagBitUndefined, t0
342 cpeq t0, ValueNull, t0
348 equalNullComparison()
349 loadis 8[PB, PC, 8], t1
351 storep t0, [cfr, t1, 8]
357 equalNullComparison()
358 loadis 8[PB, PC, 8], t1
360 storep t0, [cfr, t1, 8]
364 macro strictEq(equalityOperation, slowPath)
366 loadis 24[PB, PC, 8], t0
367 loadis 16[PB, PC, 8], t2
368 loadConstantOrVariable(t0, t1)
369 loadConstantOrVariable(t2, t0)
372 btpz t2, tagMask, .slow
373 bpaeq t0, tagTypeNumber, .leftOK
374 btpnz t0, tagTypeNumber, .slow
376 bpaeq t1, tagTypeNumber, .rightOK
377 btpnz t1, tagTypeNumber, .slow
379 equalityOperation(t0, t1, t0)
380 loadis 8[PB, PC, 8], t1
382 storep t0, [cfr, t1, 8]
386 callSlowPath(slowPath)
392 macro (left, right, result) cpeq left, right, result end,
393 _llint_slow_path_stricteq)
398 macro (left, right, result) cpneq left, right, result end,
399 _llint_slow_path_nstricteq)
402 macro preOp(arithmeticOperation, slowPath)
404 loadis 8[PB, PC, 8], t0
405 loadp [cfr, t0, 8], t1
406 bpb t1, tagTypeNumber, .slow
407 arithmeticOperation(t1, .slow)
408 orp tagTypeNumber, t1
409 storep t1, [cfr, t0, 8]
413 callSlowPath(slowPath)
419 macro (value, slow) baddio 1, value, slow end,
420 _llint_slow_path_pre_inc)
425 macro (value, slow) bsubio 1, value, slow end,
426 _llint_slow_path_pre_dec)
429 macro postOp(arithmeticOperation, slowPath)
431 loadis 16[PB, PC, 8], t0
432 loadis 8[PB, PC, 8], t1
433 loadp [cfr, t0, 8], t2
435 bpb t2, tagTypeNumber, .slow
437 arithmeticOperation(t3, .slow)
438 orp tagTypeNumber, t3
439 storep t2, [cfr, t1, 8]
440 storep t3, [cfr, t0, 8]
445 callSlowPath(slowPath)
451 macro (value, slow) baddio 1, value, slow end,
452 _llint_slow_path_post_inc)
457 macro (value, slow) bsubio 1, value, slow end,
458 _llint_slow_path_post_dec)
461 _llint_op_to_jsnumber:
463 loadis 16[PB, PC, 8], t0
464 loadis 8[PB, PC, 8], t1
465 loadConstantOrVariable(t0, t2)
466 bpaeq t2, tagTypeNumber, .opToJsnumberIsImmediate
467 btpz t2, tagTypeNumber, .opToJsnumberSlow
468 .opToJsnumberIsImmediate:
469 storep t2, [cfr, t1, 8]
473 callSlowPath(_llint_slow_path_to_jsnumber)
479 loadis 16[PB, PC, 8], t0
480 loadis 8[PB, PC, 8], t1
481 loadConstantOrVariable(t0, t2)
482 bpb t2, tagTypeNumber, .opNegateNotInt
483 btiz t2, 0x7fffffff, .opNegateSlow
485 orp tagTypeNumber, t2
486 storep t2, [cfr, t1, 8]
489 btpz t2, tagTypeNumber, .opNegateSlow
490 xorp 0x8000000000000000, t2
491 storep t2, [cfr, t1, 8]
495 callSlowPath(_llint_slow_path_negate)
499 macro binaryOpCustomStore(integerOperationAndStore, doubleOperation, slowPath)
500 loadis 24[PB, PC, 8], t0
501 loadis 16[PB, PC, 8], t2
502 loadConstantOrVariable(t0, t1)
503 loadConstantOrVariable(t2, t0)
504 bpb t0, tagTypeNumber, .op1NotInt
505 bpb t1, tagTypeNumber, .op2NotInt
506 loadis 8[PB, PC, 8], t2
507 integerOperationAndStore(t1, t0, .slow, t2)
511 # First operand is definitely not an int, the second operand could be anything.
512 btpz t0, tagTypeNumber, .slow
513 bpaeq t1, tagTypeNumber, .op1NotIntOp2Int
514 btpz t1, tagTypeNumber, .slow
515 addp tagTypeNumber, t1
521 loadis 8[PB, PC, 8], t2
522 addp tagTypeNumber, t0
524 doubleOperation(ft1, ft0)
526 subp tagTypeNumber, t0
527 storep t0, [cfr, t2, 8]
531 # First operand is definitely an int, the second is definitely not.
532 loadis 8[PB, PC, 8], t2
533 btpz t1, tagTypeNumber, .slow
535 addp tagTypeNumber, t1
537 doubleOperation(ft1, ft0)
539 subp tagTypeNumber, t0
540 storep t0, [cfr, t2, 8]
544 callSlowPath(slowPath)
548 macro binaryOp(integerOperation, doubleOperation, slowPath)
550 macro (left, right, slow, index)
551 integerOperation(left, right, slow)
552 orp tagTypeNumber, right
553 storep right, [cfr, index, 8]
555 doubleOperation, slowPath)
561 macro (left, right, slow) baddio left, right, slow end,
562 macro (left, right) addd left, right end,
563 _llint_slow_path_add)
569 macro (left, right, slow, index)
570 # Assume t3 is scratchable.
572 bmulio left, t3, slow
577 orp tagTypeNumber, t3
578 storep t3, [cfr, index, 8]
580 macro (left, right) muld left, right end,
581 _llint_slow_path_mul)
587 macro (left, right, slow) bsubio left, right, slow end,
588 macro (left, right) subd left, right end,
589 _llint_slow_path_sub)
595 macro (left, right, slow, index)
596 # Assume t3 is scratchable.
598 bineq left, -1, .notNeg2TwoThe31DivByNeg1
599 bieq right, -2147483648, .slow
600 .notNeg2TwoThe31DivByNeg1:
609 orp tagTypeNumber, t0
610 storep t0, [cfr, index, 8]
612 macro (left, right) divd left, right end,
613 _llint_slow_path_div)
616 macro bitOp(operation, slowPath, advance)
617 loadis 24[PB, PC, 8], t0
618 loadis 16[PB, PC, 8], t2
619 loadis 8[PB, PC, 8], t3
620 loadConstantOrVariable(t0, t1)
621 loadConstantOrVariable(t2, t0)
622 bpb t0, tagTypeNumber, .slow
623 bpb t1, tagTypeNumber, .slow
624 operation(t1, t0, .slow)
625 orp tagTypeNumber, t0
626 storep t0, [cfr, t3, 8]
630 callSlowPath(slowPath)
637 macro (left, right, slow) lshifti left, right end,
638 _llint_slow_path_lshift,
645 macro (left, right, slow) rshifti left, right end,
646 _llint_slow_path_rshift,
653 macro (left, right, slow)
657 _llint_slow_path_urshift,
664 macro (left, right, slow) andi left, right end,
665 _llint_slow_path_bitand,
672 macro (left, right, slow) xori left, right end,
673 _llint_slow_path_bitxor,
680 macro (left, right, slow) ori left, right end,
681 _llint_slow_path_bitor,
685 _llint_op_check_has_instance:
687 loadis 8[PB, PC, 8], t1
688 loadConstantOrVariableCell(t1, t0, .opCheckHasInstanceSlow)
689 loadp JSCell::m_structure[t0], t0
690 btbz Structure::m_typeInfo + TypeInfo::m_flags[t0], ImplementsHasInstance, .opCheckHasInstanceSlow
693 .opCheckHasInstanceSlow:
694 callSlowPath(_llint_slow_path_check_has_instance)
698 _llint_op_instanceof:
700 # Check that baseVal implements the default HasInstance behavior.
701 # FIXME: This should be deprecated.
702 loadis 24[PB, PC, 8], t1
703 loadConstantOrVariable(t1, t0)
704 loadp JSCell::m_structure[t0], t0
705 btbz Structure::m_typeInfo + TypeInfo::m_flags[t0], ImplementsDefaultHasInstance, .opInstanceofSlow
707 # Actually do the work.
708 loadis 32[PB, PC, 8], t0
709 loadis 8[PB, PC, 8], t3
710 loadConstantOrVariableCell(t0, t1, .opInstanceofSlow)
711 loadp JSCell::m_structure[t1], t2
712 bbb Structure::m_typeInfo + TypeInfo::m_type[t2], ObjectType, .opInstanceofSlow
713 loadis 16[PB, PC, 8], t0
714 loadConstantOrVariableCell(t0, t2, .opInstanceofSlow)
716 # Register state: t1 = prototype, t2 = value
719 loadp JSCell::m_structure[t2], t2
720 loadp Structure::m_prototype[t2], t2
721 bpeq t2, t1, .opInstanceofDone
722 btpz t2, tagMask, .opInstanceofLoop
727 storep t0, [cfr, t3, 8]
731 callSlowPath(_llint_slow_path_instanceof)
735 _llint_op_is_undefined:
737 loadis 16[PB, PC, 8], t1
738 loadis 8[PB, PC, 8], t2
739 loadConstantOrVariable(t1, t0)
740 btpz t0, tagMask, .opIsUndefinedCell
741 cpeq t0, ValueUndefined, t3
743 storep t3, [cfr, t2, 8]
746 loadp JSCell::m_structure[t0], t0
747 tbnz Structure::m_typeInfo + TypeInfo::m_flags[t0], MasqueradesAsUndefined, t1
749 storep t1, [cfr, t2, 8]
753 _llint_op_is_boolean:
755 loadis 16[PB, PC, 8], t1
756 loadis 8[PB, PC, 8], t2
757 loadConstantOrVariable(t1, t0)
761 storep t0, [cfr, t2, 8]
767 loadis 16[PB, PC, 8], t1
768 loadis 8[PB, PC, 8], t2
769 loadConstantOrVariable(t1, t0)
770 tpnz t0, tagTypeNumber, t1
772 storep t1, [cfr, t2, 8]
778 loadis 16[PB, PC, 8], t1
779 loadis 8[PB, PC, 8], t2
780 loadConstantOrVariable(t1, t0)
781 btpnz t0, tagMask, .opIsStringNotCell
782 loadp JSCell::m_structure[t0], t0
783 cbeq Structure::m_typeInfo + TypeInfo::m_type[t0], StringType, t1
785 storep t1, [cfr, t2, 8]
788 storep ValueFalse, [cfr, t2, 8]
792 macro resolveGlobal(size, slow)
793 # Operands are as follows:
794 # 8[PB, PC, 8] Destination for the load.
795 # 16[PB, PC, 8] Property identifier index in the code block.
796 # 24[PB, PC, 8] Structure pointer, initialized to 0 by bytecode generator.
797 # 32[PB, PC, 8] Offset in global object, initialized to 0 by bytecode generator.
798 loadp CodeBlock[cfr], t0
799 loadp CodeBlock::m_globalObject[t0], t0
800 loadp JSCell::m_structure[t0], t1
801 bpneq t1, 24[PB, PC, 8], slow
802 loadis 32[PB, PC, 8], t1
803 loadp JSObject::m_propertyStorage[t0], t0
804 loadp [t0, t1, 8], t2
805 loadis 8[PB, PC, 8], t0
806 storep t2, [cfr, t0, 8]
807 loadp (size - 1) * 8[PB, PC, 8], t0
811 _llint_op_resolve_global:
813 resolveGlobal(6, .opResolveGlobalSlow)
816 .opResolveGlobalSlow:
817 callSlowPath(_llint_slow_path_resolve_global)
821 # Gives you the scope in t0, while allowing you to optionally perform additional checks on the
822 # scopes as they are traversed. scopeCheck() is called with two arguments: the register
823 # holding the scope, and a register that can be used for scratch. Note that this does not
824 # use t3, so you can hold stuff in t3 if need be.
825 macro getScope(deBruijinIndexOperand, scopeCheck)
826 loadp ScopeChain[cfr], t0
827 loadis deBruijinIndexOperand, t2
831 loadp CodeBlock[cfr], t1
832 bineq CodeBlock::m_codeType[t1], FunctionCode, .loop
833 btbz CodeBlock::m_needsFullScopeChain[t1], .loop
835 loadis CodeBlock::m_activationRegister[t1], t1
837 # Need to conditionally skip over one scope.
838 btpz [cfr, t1, 8], .noActivation
840 loadp ScopeChainNode::next[t0], t0
847 loadp ScopeChainNode::next[t0], t0
854 _llint_op_resolve_global_dynamic:
856 loadp JITStackFrame::globalData[sp], t3
857 loadp JSGlobalData::activationStructure[t3], t3
860 macro (scope, scratch)
861 loadp ScopeChainNode::object[scope], scratch
862 bpneq JSCell::m_structure[scratch], t3, .opResolveGlobalDynamicSuperSlow
864 resolveGlobal(7, .opResolveGlobalDynamicSlow)
867 .opResolveGlobalDynamicSuperSlow:
868 callSlowPath(_llint_slow_path_resolve_for_resolve_global_dynamic)
871 .opResolveGlobalDynamicSlow:
872 callSlowPath(_llint_slow_path_resolve_global_dynamic)
876 _llint_op_get_scoped_var:
878 # Operands are as follows:
879 # 8[PB, PC, 8] Destination for the load
880 # 16[PB, PC, 8] Index of register in the scope
881 # 24[PB, PC, 8] De Bruijin index.
882 getScope(24[PB, PC, 8], macro (scope, scratch) end)
883 loadis 8[PB, PC, 8], t1
884 loadis 16[PB, PC, 8], t2
885 loadp ScopeChainNode::object[t0], t0
886 loadp JSVariableObject::m_registers[t0], t0
887 loadp [t0, t2, 8], t3
888 storep t3, [cfr, t1, 8]
889 loadp 32[PB, PC, 8], t1
894 _llint_op_put_scoped_var:
896 getScope(16[PB, PC, 8], macro (scope, scratch) end)
897 loadis 24[PB, PC, 8], t1
898 loadConstantOrVariable(t1, t3)
899 loadis 8[PB, PC, 8], t1
901 loadp ScopeChainNode::object[t0], t0
902 loadp JSVariableObject::m_registers[t0], t0
903 storep t3, [t0, t1, 8]
907 _llint_op_get_global_var:
909 loadis 16[PB, PC, 8], t1
910 loadis 8[PB, PC, 8], t3
911 loadp CodeBlock[cfr], t0
912 loadp CodeBlock::m_globalObject[t0], t0
913 loadp JSGlobalObject::m_registers[t0], t0
914 loadp [t0, t1, 8], t2
915 storep t2, [cfr, t3, 8]
916 loadp 24[PB, PC, 8], t3
921 _llint_op_put_global_var:
923 loadis 16[PB, PC, 8], t1
924 loadp CodeBlock[cfr], t0
925 loadp CodeBlock::m_globalObject[t0], t0
926 loadp JSGlobalObject::m_registers[t0], t0
927 loadConstantOrVariable(t1, t2)
928 loadis 8[PB, PC, 8], t1
930 storep t2, [t0, t1, 8]
936 # We only do monomorphic get_by_id caching for now, and we do not modify the
937 # opcode. We do, however, allow for the cache to change anytime if fails, since
938 # ping-ponging is free. At best we get lucky and the get_by_id will continue
939 # to take fast path on the new cache. At worst we take slow path, which is what
940 # we would have been doing anyway.
941 loadis 16[PB, PC, 8], t0
942 loadp 32[PB, PC, 8], t1
943 loadConstantOrVariableCell(t0, t3, .opGetByIdSlow)
944 loadis 40[PB, PC, 8], t2
945 loadp JSObject::m_propertyStorage[t3], t0
946 bpneq JSCell::m_structure[t3], t1, .opGetByIdSlow
947 loadis 8[PB, PC, 8], t1
949 storep t3, [cfr, t1, 8]
950 loadp 64[PB, PC, 8], t1
955 callSlowPath(_llint_slow_path_get_by_id)
959 _llint_op_get_arguments_length:
961 loadis 16[PB, PC, 8], t0
962 loadis 8[PB, PC, 8], t1
963 btpnz [cfr, t0, 8], .opGetArgumentsLengthSlow
964 loadi ArgumentCount + PayloadOffset[cfr], t2
966 orp tagTypeNumber, t2
967 storep t2, [cfr, t1, 8]
970 .opGetArgumentsLengthSlow:
971 callSlowPath(_llint_slow_path_get_arguments_length)
977 loadis 8[PB, PC, 8], t3
978 loadp 32[PB, PC, 8], t1
979 loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
980 loadis 24[PB, PC, 8], t2
981 loadp JSObject::m_propertyStorage[t0], t3
982 bpneq JSCell::m_structure[t0], t1, .opPutByIdSlow
983 loadis 40[PB, PC, 8], t1
984 loadConstantOrVariable(t2, t0)
990 callSlowPath(_llint_slow_path_put_by_id)
994 macro putByIdTransition(additionalChecks)
996 loadis 8[PB, PC, 8], t3
997 loadp 32[PB, PC, 8], t1
998 loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
999 loadis 24[PB, PC, 8], t2
1000 bpneq JSCell::m_structure[t0], t1, .opPutByIdSlow
1001 additionalChecks(t1, t3, .opPutByIdSlow)
1002 loadis 40[PB, PC, 8], t1
1003 loadp JSObject::m_propertyStorage[t0], t3
1005 loadConstantOrVariable(t2, t1)
1008 loadp 48[PB, PC, 8], t1
1009 storep t1, JSCell::m_structure[t0]
1013 _llint_op_put_by_id_transition_direct:
1014 putByIdTransition(macro (oldStructure, scratch, slow) end)
1017 _llint_op_put_by_id_transition_normal:
1019 macro (oldStructure, scratch, slow)
1020 const protoCell = oldStructure # Reusing the oldStructure register for the proto
1021 loadp 56[PB, PC, 8], scratch
1022 assert(macro (ok) btpnz scratch, ok end)
1023 loadp StructureChain::m_vector[scratch], scratch
1024 assert(macro (ok) btpnz scratch, ok end)
1025 bpeq Structure::m_prototype[oldStructure], ValueNull, .done
1027 loadp Structure::m_prototype[oldStructure], protoCell
1028 loadp JSCell::m_structure[protoCell], oldStructure
1029 bpneq oldStructure, [scratch], slow
1031 bpneq Structure::m_prototype[oldStructure], ValueNull, .loop
1036 _llint_op_get_by_val:
1038 loadp CodeBlock[cfr], t1
1039 loadis 16[PB, PC, 8], t2
1040 loadis 24[PB, PC, 8], t3
1041 loadp CodeBlock::m_globalData[t1], t1
1042 loadConstantOrVariableCell(t2, t0, .opGetByValSlow)
1043 loadp JSGlobalData::jsArrayClassInfo[t1], t2
1044 loadConstantOrVariableInt32(t3, t1, .opGetByValSlow)
1046 bpneq [t0], t2, .opGetByValSlow
1047 loadp JSArray::m_storage[t0], t3
1048 biaeq t1, JSArray::m_vectorLength[t0], .opGetByValSlow
1049 loadis 8[PB, PC, 8], t0
1050 loadp ArrayStorage::m_vector[t3, t1, 8], t2
1051 btpz t2, .opGetByValSlow
1052 storep t2, [cfr, t0, 8]
1053 loadp 32[PB, PC, 8], t0
1054 valueProfile(t2, t0)
1058 callSlowPath(_llint_slow_path_get_by_val)
1062 _llint_op_get_argument_by_val:
1064 loadis 16[PB, PC, 8], t0
1065 loadis 24[PB, PC, 8], t1
1066 btpnz [cfr, t0, 8], .opGetArgumentByValSlow
1067 loadConstantOrVariableInt32(t1, t2, .opGetArgumentByValSlow)
1069 loadi ArgumentCount + PayloadOffset[cfr], t1
1070 biaeq t2, t1, .opGetArgumentByValSlow
1073 loadis 8[PB, PC, 8], t3
1074 loadp ThisArgumentOffset[cfr, t2, 8], t0
1075 storep t0, [cfr, t3, 8]
1078 .opGetArgumentByValSlow:
1079 callSlowPath(_llint_slow_path_get_argument_by_val)
1083 _llint_op_get_by_pname:
1085 loadis 24[PB, PC, 8], t1
1086 loadConstantOrVariable(t1, t0)
1087 loadis 32[PB, PC, 8], t1
1088 assertNotConstant(t1)
1089 bpneq t0, [cfr, t1, 8], .opGetByPnameSlow
1090 loadis 16[PB, PC, 8], t2
1091 loadis 40[PB, PC, 8], t3
1092 loadConstantOrVariableCell(t2, t0, .opGetByPnameSlow)
1093 assertNotConstant(t3)
1094 loadp [cfr, t3, 8], t1
1095 loadp JSCell::m_structure[t0], t2
1096 bpneq t2, JSPropertyNameIterator::m_cachedStructure[t1], .opGetByPnameSlow
1097 loadis 48[PB, PC, 8], t3
1098 loadi PayloadOffset[cfr, t3, 8], t3
1100 biaeq t3, JSPropertyNameIterator::m_numCacheableSlots[t1], .opGetByPnameSlow
1101 loadp JSObject::m_propertyStorage[t0], t0
1102 loadp [t0, t3, 8], t0
1103 loadis 8[PB, PC, 8], t1
1104 storep t0, [cfr, t1, 8]
1108 callSlowPath(_llint_slow_path_get_by_pname)
1112 _llint_op_put_by_val:
1114 loadis 8[PB, PC, 8], t0
1115 loadConstantOrVariableCell(t0, t1, .opPutByValSlow)
1116 loadis 16[PB, PC, 8], t0
1117 loadConstantOrVariableInt32(t0, t2, .opPutByValSlow)
1119 loadp CodeBlock[cfr], t0
1120 loadp CodeBlock::m_globalData[t0], t0
1121 loadp JSGlobalData::jsArrayClassInfo[t0], t0
1122 bpneq [t1], t0, .opPutByValSlow
1123 biaeq t2, JSArray::m_vectorLength[t1], .opPutByValSlow
1124 loadp JSArray::m_storage[t1], t0
1125 btpz ArrayStorage::m_vector[t0, t2, 8], .opPutByValEmpty
1126 .opPutByValStoreResult:
1127 loadis 24[PB, PC, 8], t3
1128 loadConstantOrVariable(t3, t1)
1130 storep t1, ArrayStorage::m_vector[t0, t2, 8]
1134 addi 1, ArrayStorage::m_numValuesInVector[t0]
1135 bib t2, ArrayStorage::m_length[t0], .opPutByValStoreResult
1137 storei t1, ArrayStorage::m_length[t0]
1138 jmp .opPutByValStoreResult
1141 callSlowPath(_llint_slow_path_put_by_val)
1149 dispatchInt(8[PB, PC, 8])
1152 macro jumpTrueOrFalse(conditionOp, slow)
1153 loadis 8[PB, PC, 8], t1
1154 loadConstantOrVariable(t1, t0)
1157 conditionOp(t0, .target)
1161 dispatchInt(16[PB, PC, 8])
1169 macro equalNull(cellHandler, immediateHandler)
1170 loadis 8[PB, PC, 8], t0
1171 assertNotConstant(t0)
1172 loadp [cfr, t0, 8], t0
1173 btpnz t0, tagMask, .immediate
1174 loadp JSCell::m_structure[t0], t2
1175 cellHandler(Structure::m_typeInfo + TypeInfo::m_flags[t2], .target)
1179 dispatch(16[PB, PC, 8])
1182 andp ~TagBitUndefined, t0
1183 immediateHandler(t0, .target)
1190 macro (value, target) btbnz value, MasqueradesAsUndefined, target end,
1191 macro (value, target) bpeq value, ValueNull, target end)
1194 _llint_op_jneq_null:
1197 macro (value, target) btbz value, MasqueradesAsUndefined, target end,
1198 macro (value, target) bpneq value, ValueNull, target end)
1203 loadis 8[PB, PC, 8], t0
1204 loadp 16[PB, PC, 8], t1
1205 bpneq t1, [cfr, t0, 8], .opJneqPtrTarget
1209 dispatchInt(24[PB, PC, 8])
1212 macro compare(integerCompare, doubleCompare, slowPath)
1213 loadis 8[PB, PC, 8], t2
1214 loadis 16[PB, PC, 8], t3
1215 loadConstantOrVariable(t2, t0)
1216 loadConstantOrVariable(t3, t1)
1217 bpb t0, tagTypeNumber, .op1NotInt
1218 bpb t1, tagTypeNumber, .op2NotInt
1219 integerCompare(t0, t1, .jumpTarget)
1223 btpz t0, tagTypeNumber, .slow
1224 bpb t1, tagTypeNumber, .op1NotIntOp2NotInt
1227 .op1NotIntOp2NotInt:
1228 btpz t1, tagTypeNumber, .slow
1229 addp tagTypeNumber, t1
1232 addp tagTypeNumber, t0
1234 doubleCompare(ft0, ft1, .jumpTarget)
1239 btpz t1, tagTypeNumber, .slow
1240 addp tagTypeNumber, t1
1242 doubleCompare(ft0, ft1, .jumpTarget)
1246 dispatchInt(24[PB, PC, 8])
1249 callSlowPath(slowPath)
1254 _llint_op_switch_imm:
1256 loadis 24[PB, PC, 8], t2
1257 loadis 8[PB, PC, 8], t3
1258 loadConstantOrVariable(t2, t1)
1259 loadp CodeBlock[cfr], t2
1260 loadp CodeBlock::m_rareData[t2], t2
1261 muli sizeof SimpleJumpTable, t3 # FIXME: would be nice to peephole this!
1262 loadp CodeBlock::RareData::m_immediateSwitchJumpTables + VectorBufferOffset[t2], t2
1264 bpb t1, tagTypeNumber, .opSwitchImmNotInt
1265 subi SimpleJumpTable::min[t2], t1
1266 biaeq t1, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchImmFallThrough
1267 loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t3
1268 loadis [t3, t1, 4], t1
1269 btiz t1, .opSwitchImmFallThrough
1273 btpnz t1, tagTypeNumber, .opSwitchImmSlow # Go slow if it's a double.
1274 .opSwitchImmFallThrough:
1275 dispatchInt(16[PB, PC, 8])
1278 callSlowPath(_llint_slow_path_switch_imm)
1282 _llint_op_switch_char:
1284 loadis 24[PB, PC, 8], t2
1285 loadis 8[PB, PC, 8], t3
1286 loadConstantOrVariable(t2, t1)
1287 loadp CodeBlock[cfr], t2
1288 loadp CodeBlock::m_rareData[t2], t2
1289 muli sizeof SimpleJumpTable, t3
1290 loadp CodeBlock::RareData::m_characterSwitchJumpTables + VectorBufferOffset[t2], t2
1292 btpnz t1, tagMask, .opSwitchCharFallThrough
1293 loadp JSCell::m_structure[t1], t0
1294 bbneq Structure::m_typeInfo + TypeInfo::m_type[t0], StringType, .opSwitchCharFallThrough
1295 bineq JSString::m_length[t1], 1, .opSwitchCharFallThrough
1296 loadp JSString::m_value[t1], t0
1297 btpz t0, .opSwitchOnRope
1298 loadp StringImpl::m_data8[t0], t1
1299 btinz StringImpl::m_hashAndFlags[t0], HashFlags8BitBuffer, .opSwitchChar8Bit
1301 jmp .opSwitchCharReady
1305 subi SimpleJumpTable::min[t2], t0
1306 biaeq t0, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchCharFallThrough
1307 loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t2
1308 loadis [t2, t0, 4], t1
1309 btiz t1, .opSwitchCharFallThrough
1312 .opSwitchCharFallThrough:
1313 dispatchInt(16[PB, PC, 8])
1316 callSlowPath(_llint_slow_path_switch_char)
1322 btiz 24[PB, PC, 8], .opNewFuncUnchecked
1323 loadis 8[PB, PC, 8], t1
1324 btpnz [cfr, t1, 8], .opNewFuncDone
1325 .opNewFuncUnchecked:
1326 callSlowPath(_llint_slow_path_new_func)
1331 macro doCall(slowPath)
1332 loadis 8[PB, PC, 8], t0
1333 loadp 32[PB, PC, 8], t1
1334 loadp LLIntCallLinkInfo::callee[t1], t2
1335 loadConstantOrVariable(t0, t3)
1336 bpneq t3, t2, .opCallSlow
1337 loadis 24[PB, PC, 8], t3
1341 loadp JSFunction::m_scopeChain[t2], t0
1342 storep t2, Callee[t3]
1343 storep t0, ScopeChain[t3]
1344 loadis 16 - 48[PB, PC, 8], t2
1345 storei PC, ArgumentCount + TagOffset[cfr]
1346 storep cfr, CallerFrame[t3]
1347 storei t2, ArgumentCount + PayloadOffset[t3]
1349 call LLIntCallLinkInfo::machineCodeTarget[t1]
1353 slowPathForCall(6, slowPath)
1357 _llint_op_tear_off_activation:
1359 loadis 8[PB, PC, 8], t0
1360 loadis 16[PB, PC, 8], t1
1361 btpnz [cfr, t0, 8], .opTearOffActivationCreated
1362 btpz [cfr, t1, 8], .opTearOffActivationNotCreated
1363 .opTearOffActivationCreated:
1364 callSlowPath(_llint_slow_path_tear_off_activation)
1365 .opTearOffActivationNotCreated:
1369 _llint_op_tear_off_arguments:
1371 loadis 8[PB, PC, 8], t0
1372 subi 1, t0 # Get the unmodifiedArgumentsRegister
1373 btpz [cfr, t0, 8], .opTearOffArgumentsNotCreated
1374 callSlowPath(_llint_slow_path_tear_off_arguments)
1375 .opTearOffArgumentsNotCreated:
1381 checkSwitchToJITForEpilogue()
1382 loadis 8[PB, PC, 8], t2
1383 loadConstantOrVariable(t2, t0)
1387 _llint_op_call_put_result:
1388 loadis 8[PB, PC, 8], t2
1389 loadp 16[PB, PC, 8], t3
1390 storep t0, [cfr, t2, 8]
1391 valueProfile(t0, t3)
1396 _llint_op_ret_object_or_this:
1398 checkSwitchToJITForEpilogue()
1399 loadis 8[PB, PC, 8], t2
1400 loadConstantOrVariable(t2, t0)
1401 btpnz t0, tagMask, .opRetObjectOrThisNotObject
1402 loadp JSCell::m_structure[t0], t2
1403 bbb Structure::m_typeInfo + TypeInfo::m_type[t2], ObjectType, .opRetObjectOrThisNotObject
1406 .opRetObjectOrThisNotObject:
1407 loadis 16[PB, PC, 8], t2
1408 loadConstantOrVariable(t2, t0)
1412 _llint_op_to_primitive:
1414 loadis 16[PB, PC, 8], t2
1415 loadis 8[PB, PC, 8], t3
1416 loadConstantOrVariable(t2, t0)
1417 btpnz t0, tagMask, .opToPrimitiveIsImm
1418 loadp JSCell::m_structure[t0], t2
1419 bbneq Structure::m_typeInfo + TypeInfo::m_type[t2], StringType, .opToPrimitiveSlowCase
1420 .opToPrimitiveIsImm:
1421 storep t0, [cfr, t3, 8]
1424 .opToPrimitiveSlowCase:
1425 callSlowPath(_llint_slow_path_to_primitive)
1429 _llint_op_next_pname:
1431 loadis 24[PB, PC, 8], t1
1432 loadis 32[PB, PC, 8], t2
1433 assertNotConstant(t1)
1434 assertNotConstant(t2)
1435 loadi PayloadOffset[cfr, t1, 8], t0
1436 bieq t0, PayloadOffset[cfr, t2, 8], .opNextPnameEnd
1437 loadis 40[PB, PC, 8], t2
1438 assertNotConstant(t2)
1439 loadp [cfr, t2, 8], t2
1440 loadp JSPropertyNameIterator::m_jsStrings[t2], t3
1441 loadp [t3, t0, 8], t3
1443 storei t0, PayloadOffset[cfr, t1, 8]
1444 loadis 8[PB, PC, 8], t1
1445 storep t3, [cfr, t1, 8]
1446 loadis 16[PB, PC, 8], t3
1447 assertNotConstant(t3)
1448 loadp [cfr, t3, 8], t3
1449 loadp JSCell::m_structure[t3], t1
1450 bpneq t1, JSPropertyNameIterator::m_cachedStructure[t2], .opNextPnameSlow
1451 loadp JSPropertyNameIterator::m_cachedPrototypeChain[t2], t0
1452 loadp StructureChain::m_vector[t0], t0
1453 btpz [t0], .opNextPnameTarget
1454 .opNextPnameCheckPrototypeLoop:
1455 bpeq Structure::m_prototype[t1], ValueNull, .opNextPnameSlow
1456 loadp Structure::m_prototype[t1], t2
1457 loadp JSCell::m_structure[t2], t1
1458 bpneq t1, [t0], .opNextPnameSlow
1460 btpnz [t0], .opNextPnameCheckPrototypeLoop
1462 dispatchInt(48[PB, PC, 8])
1468 callSlowPath(_llint_slow_path_next_pname) # This either keeps the PC where it was (causing us to loop) or sets it to target.
1473 # This is where we end up from the JIT's throw trampoline (because the
1474 # machine code return address will be set to _llint_op_catch), and from
1475 # the interpreter's throw trampoline (see _llint_throw_trampoline).
1476 # The JIT throwing protocol calls for the cfr to be in t0. The throwing
1477 # code must have known that we were throwing to the interpreter, and have
1478 # set JSGlobalData::targetInterpreterPCForThrow.
1480 loadp CodeBlock[cfr], PB
1481 loadp CodeBlock::m_instructions[PB], PB
1482 loadp JITStackFrame::globalData[sp], t3
1483 loadp JSGlobalData::targetInterpreterPCForThrow[t3], PC
1486 loadp JSGlobalData::exception[t3], t0
1487 storep 0, JSGlobalData::exception[t3]
1488 loadis 8[PB, PC, 8], t2
1489 storep t0, [cfr, t2, 8]
1496 checkSwitchToJITForEpilogue()
1497 loadis 8[PB, PC, 8], t0
1498 assertNotConstant(t0)
1499 loadp [cfr, t0, 8], t0
1503 _llint_throw_from_slow_path_trampoline:
1504 # When throwing from the interpreter (i.e. throwing from LLIntSlowPaths), so
1505 # the throw target is not necessarily interpreted code, we come to here.
1506 # This essentially emulates the JIT's throwing protocol.
1507 loadp JITStackFrame::globalData[sp], t1
1508 loadp JSGlobalData::callFrameForThrow[t1], t0
1509 jmp JSGlobalData::targetMachinePCForThrow[t1]
1512 _llint_throw_during_call_trampoline:
1513 preserveReturnAddressAfterCall(t2)
1514 loadp JITStackFrame::globalData[sp], t1
1515 loadp JSGlobalData::callFrameForThrow[t1], t0
1516 jmp JSGlobalData::targetMachinePCForThrow[t1]
1519 macro nativeCallTrampoline(executableOffsetToFunction)
1520 storep 0, CodeBlock[cfr]
1521 loadp JITStackFrame::globalData + 8[sp], t0
1522 storep cfr, JSGlobalData::topCallFrame[t0]
1523 loadp CallerFrame[cfr], t0
1524 loadp ScopeChain[t0], t1
1525 storep t1, ScopeChain[cfr]
1527 storep t1, ReturnPC[cfr]
1528 move cfr, t5 # t5 = rdi
1530 loadp Callee[cfr], t4 # t4 = rsi
1531 loadp JSFunction::m_executable[t4], t1
1532 move t0, cfr # Restore cfr to avoid loading from stack
1533 call executableOffsetToFunction[t1]
1535 loadp JITStackFrame::globalData + 8[sp], t3
1536 btpnz JSGlobalData::exception[t3], .exception
1539 preserveReturnAddressAfterCall(t1)
1540 loadi ArgumentCount + TagOffset[cfr], PC
1541 loadp CodeBlock[cfr], PB
1542 loadp CodeBlock::m_instructions[PB], PB
1543 loadp JITStackFrame::globalData[sp], t0
1544 storep cfr, JSGlobalData::topCallFrame[t0]
1545 callSlowPath(_llint_throw_from_native_call)
1546 jmp _llint_throw_from_slow_path_trampoline