[JSC] Avoid cloned arguments allocation in ArrayPrototype methods
[WebKit.git] / Source / JavaScriptCore / llint / LowLevelInterpreter64.asm
1 # Copyright (C) 2011-2016 Apple Inc. All rights reserved.
2 #
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions
5 # are met:
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.
11 #
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.
23
24
25 # Utilities.
26 macro jumpToInstruction()
27     jmp [PB, PC, 8]
28 end
29
30 macro dispatch(advance)
31     addp advance, PC
32     jumpToInstruction()
33 end
34
35 macro dispatchInt(advance)
36     addi advance, PC
37     jumpToInstruction()
38 end
39
40 macro dispatchIntIndirect(offset)
41     dispatchInt(offset * 8[PB, PC, 8])
42 end
43
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 r0, [cfr, t1, 8]
50     valueProfile(r0, (CallOpCodeSize - 1), t3)
51     dispatch(CallOpCodeSize)
52 end
53
54 macro cCall2(function)
55     checkStackPointerAlignment(t4, 0xbad0c002)
56     if X86_64 or ARM64
57         call function
58     elsif X86_64_WIN
59         # Note: this implementation is only correct if the return type size is > 8 bytes.
60         # See macro cCall2Void for an implementation when the return type <= 8 bytes.
61         # On Win64, when the return type is larger than 8 bytes, we need to allocate space on the stack for the return value.
62         # On entry rcx (a0), should contain a pointer to this stack space. The other parameters are shifted to the right,
63         # rdx (a1) should contain the first argument, and r8 (a2) should contain the second argument.
64         # On return, rax contains a pointer to this stack value, and we then need to copy the 16 byte return value into rax (r0) and rdx (r1)
65         # since the return value is expected to be split between the two.
66         # See http://msdn.microsoft.com/en-us/library/7572ztz4.aspx
67         move a1, a2
68         move a0, a1
69         subp 48, sp
70         move sp, a0
71         addp 32, a0
72         call function
73         addp 48, sp
74         move 8[r0], r1
75         move [r0], r0
76     elsif C_LOOP
77         cloopCallSlowPath function, a0, a1
78     else
79         error
80     end
81 end
82
83 macro cCall2Void(function)
84     if C_LOOP
85         cloopCallSlowPathVoid function, a0, a1
86     elsif X86_64_WIN
87         # Note: we cannot use the cCall2 macro for Win64 in this case,
88         # as the Win64 cCall2 implemenation is only correct when the return type size is > 8 bytes.
89         # On Win64, rcx and rdx are used for passing the first two parameters.
90         # We also need to make room on the stack for all four parameter registers.
91         # See http://msdn.microsoft.com/en-us/library/ms235286.aspx
92         subp 32, sp 
93         call function
94         addp 32, sp 
95     else
96         cCall2(function)
97     end
98 end
99
100 # This barely works. arg3 and arg4 should probably be immediates.
101 macro cCall4(function)
102     checkStackPointerAlignment(t4, 0xbad0c004)
103     if X86_64 or ARM64
104         call function
105     elsif X86_64_WIN
106         # On Win64, rcx, rdx, r8, and r9 are used for passing the first four parameters.
107         # We also need to make room on the stack for all four parameter registers.
108         # See http://msdn.microsoft.com/en-us/library/ms235286.aspx
109         subp 64, sp
110         call function
111         addp 64, sp
112     else
113         error
114     end
115 end
116
117 macro doVMEntry(makeCall)
118     functionPrologue()
119     pushCalleeSaves()
120
121     const entry = a0
122     const vm = a1
123     const protoCallFrame = a2
124
125     vmEntryRecord(cfr, sp)
126
127     checkStackPointerAlignment(t4, 0xbad0dc01)
128
129     storep vm, VMEntryRecord::m_vm[sp]
130     loadp VM::topCallFrame[vm], t4
131     storep t4, VMEntryRecord::m_prevTopCallFrame[sp]
132     loadp VM::topVMEntryFrame[vm], t4
133     storep t4, VMEntryRecord::m_prevTopVMEntryFrame[sp]
134
135     loadi ProtoCallFrame::paddedArgCount[protoCallFrame], t4
136     addp CallFrameHeaderSlots, t4, t4
137     lshiftp 3, t4
138     subp sp, t4, t3
139
140     # Ensure that we have enough additional stack capacity for the incoming args,
141     # and the frame for the JS code we're executing. We need to do this check
142     # before we start copying the args from the protoCallFrame below.
143     if C_LOOP
144         bpaeq t3, VM::m_cloopStackLimit[vm], .stackHeightOK
145     else
146         bpaeq t3, VM::m_softStackLimit[vm], .stackHeightOK
147     end
148
149     if C_LOOP
150         move entry, t4
151         move vm, t5
152         cloopCallSlowPath _llint_stack_check_at_vm_entry, vm, t3
153         bpeq t0, 0, .stackCheckFailed
154         move t4, entry
155         move t5, vm
156         jmp .stackHeightOK
157
158 .stackCheckFailed:
159         move t4, entry
160         move t5, vm
161     end
162
163     move vm, a0
164     move protoCallFrame, a1
165     cCall2(_llint_throw_stack_overflow_error)
166
167     vmEntryRecord(cfr, t4)
168
169     loadp VMEntryRecord::m_vm[t4], vm
170     loadp VMEntryRecord::m_prevTopCallFrame[t4], extraTempReg
171     storep extraTempReg, VM::topCallFrame[vm]
172     loadp VMEntryRecord::m_prevTopVMEntryFrame[t4], extraTempReg
173     storep extraTempReg, VM::topVMEntryFrame[vm]
174
175     subp cfr, CalleeRegisterSaveSize, sp
176
177     popCalleeSaves()
178     functionEpilogue()
179     ret
180
181 .stackHeightOK:
182     move t3, sp
183     move 4, t3
184
185 .copyHeaderLoop:
186     subi 1, t3
187     loadq [protoCallFrame, t3, 8], extraTempReg
188     storeq extraTempReg, CodeBlock[sp, t3, 8]
189     btinz t3, .copyHeaderLoop
190
191     loadi PayloadOffset + ProtoCallFrame::argCountAndCodeOriginValue[protoCallFrame], t4
192     subi 1, t4
193     loadi ProtoCallFrame::paddedArgCount[protoCallFrame], extraTempReg
194     subi 1, extraTempReg
195
196     bieq t4, extraTempReg, .copyArgs
197     move ValueUndefined, t3
198 .fillExtraArgsLoop:
199     subi 1, extraTempReg
200     storeq t3, ThisArgumentOffset + 8[sp, extraTempReg, 8]
201     bineq t4, extraTempReg, .fillExtraArgsLoop
202
203 .copyArgs:
204     loadp ProtoCallFrame::args[protoCallFrame], t3
205
206 .copyArgsLoop:
207     btiz t4, .copyArgsDone
208     subi 1, t4
209     loadq [t3, t4, 8], extraTempReg
210     storeq extraTempReg, ThisArgumentOffset + 8[sp, t4, 8]
211     jmp .copyArgsLoop
212
213 .copyArgsDone:
214     if ARM64
215         move sp, t4
216         storep t4, VM::topCallFrame[vm]
217     else
218         storep sp, VM::topCallFrame[vm]
219     end
220     storep cfr, VM::topVMEntryFrame[vm]
221
222     checkStackPointerAlignment(extraTempReg, 0xbad0dc02)
223
224     makeCall(entry, t3)
225
226     # We may have just made a call into a JS function, so we can't rely on sp
227     # for anything but the fact that our own locals (ie the VMEntryRecord) are
228     # not below it. It also still has to be aligned, though.
229     checkStackPointerAlignment(t2, 0xbad0dc03)
230
231     vmEntryRecord(cfr, t4)
232
233     loadp VMEntryRecord::m_vm[t4], vm
234     loadp VMEntryRecord::m_prevTopCallFrame[t4], t2
235     storep t2, VM::topCallFrame[vm]
236     loadp VMEntryRecord::m_prevTopVMEntryFrame[t4], t2
237     storep t2, VM::topVMEntryFrame[vm]
238
239     subp cfr, CalleeRegisterSaveSize, sp
240
241     popCalleeSaves()
242     functionEpilogue()
243
244     ret
245 end
246
247
248 macro makeJavaScriptCall(entry, temp)
249     addp 16, sp
250     if C_LOOP
251         cloopCallJSFunction entry
252     else
253         call entry
254     end
255     subp 16, sp
256 end
257
258
259 macro makeHostFunctionCall(entry, temp)
260     move entry, temp
261     storep cfr, [sp]
262     move sp, a0
263     if C_LOOP
264         storep lr, 8[sp]
265         cloopCallNative temp
266     elsif X86_64_WIN
267         # We need to allocate 32 bytes on the stack for the shadow space.
268         subp 32, sp
269         call temp
270         addp 32, sp
271     else
272         call temp
273     end
274 end
275
276
277 _handleUncaughtException:
278     loadp Callee[cfr], t3
279     andp MarkedBlockMask, t3
280     loadp MarkedBlock::m_vm[t3], t3
281     restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer(t3, t0)
282     loadp VM::callFrameForCatch[t3], cfr
283     storep 0, VM::callFrameForCatch[t3]
284
285     loadp CallerFrame[cfr], cfr
286     vmEntryRecord(cfr, t2)
287
288     loadp VMEntryRecord::m_vm[t2], t3
289     loadp VMEntryRecord::m_prevTopCallFrame[t2], extraTempReg
290     storep extraTempReg, VM::topCallFrame[t3]
291     loadp VMEntryRecord::m_prevTopVMEntryFrame[t2], extraTempReg
292     storep extraTempReg, VM::topVMEntryFrame[t3]
293
294     subp cfr, CalleeRegisterSaveSize, sp
295
296     popCalleeSaves()
297     functionEpilogue()
298     ret
299
300
301 macro prepareStateForCCall()
302     leap [PB, PC, 8], PC
303 end
304
305 macro restoreStateAfterCCall()
306     move r0, PC
307     subp PB, PC
308     rshiftp 3, PC
309 end
310
311 macro callSlowPath(slowPath)
312     prepareStateForCCall()
313     move cfr, a0
314     move PC, a1
315     cCall2(slowPath)
316     restoreStateAfterCCall()
317 end
318
319 macro traceOperand(fromWhere, operand)
320     prepareStateForCCall()
321     move fromWhere, a2
322     move operand, a3
323     move cfr, a0
324     move PC, a1
325     cCall4(_llint_trace_operand)
326     restoreStateAfterCCall()
327 end
328
329 macro traceValue(fromWhere, operand)
330     prepareStateForCCall()
331     move fromWhere, a2
332     move operand, a3
333     move cfr, a0
334     move PC, a1
335     cCall4(_llint_trace_value)
336     restoreStateAfterCCall()
337 end
338
339 # Call a slow path for call call opcodes.
340 macro callCallSlowPath(slowPath, action)
341     storei PC, ArgumentCount + TagOffset[cfr]
342     prepareStateForCCall()
343     move cfr, a0
344     move PC, a1
345     cCall2(slowPath)
346     action(r0, r1)
347 end
348
349 macro callWatchdogTimerHandler(throwHandler)
350     storei PC, ArgumentCount + TagOffset[cfr]
351     prepareStateForCCall()
352     move cfr, a0
353     move PC, a1
354     cCall2(_llint_slow_path_handle_watchdog_timer)
355     btpnz r0, throwHandler
356     loadi ArgumentCount + TagOffset[cfr], PC
357 end
358
359 macro checkSwitchToJITForLoop()
360     checkSwitchToJIT(
361         1,
362         macro()
363             storei PC, ArgumentCount + TagOffset[cfr]
364             prepareStateForCCall()
365             move cfr, a0
366             move PC, a1
367             cCall2(_llint_loop_osr)
368             btpz r0, .recover
369             move r1, sp
370             jmp r0
371         .recover:
372             loadi ArgumentCount + TagOffset[cfr], PC
373         end)
374 end
375
376 macro loadVariable(operand, value)
377     loadisFromInstruction(operand, value)
378     loadq [cfr, value, 8], value
379 end
380
381 # Index and value must be different registers. Index may be clobbered.
382 macro loadConstantOrVariable(index, value)
383     bpgteq index, FirstConstantRegisterIndex, .constant
384     loadq [cfr, index, 8], value
385     jmp .done
386 .constant:
387     loadp CodeBlock[cfr], value
388     loadp CodeBlock::m_constantRegisters + VectorBufferOffset[value], value
389     subp FirstConstantRegisterIndex, index
390     loadq [value, index, 8], value
391 .done:
392 end
393
394 macro loadConstantOrVariableInt32(index, value, slow)
395     loadConstantOrVariable(index, value)
396     bqb value, tagTypeNumber, slow
397 end
398
399 macro loadConstantOrVariableCell(index, value, slow)
400     loadConstantOrVariable(index, value)
401     btqnz value, tagMask, slow
402 end
403
404 macro writeBarrierOnOperand(cellOperand)
405     loadisFromInstruction(cellOperand, t1)
406     loadConstantOrVariableCell(t1, t2, .writeBarrierDone)
407     skipIfIsRememberedOrInEden(
408         t2,
409         macro()
410             push PB, PC
411             move t2, a1 # t2 can be a0 (not on 64 bits, but better safe than sorry)
412             move cfr, a0
413             cCall2Void(_llint_write_barrier_slow)
414             pop PC, PB
415         end)
416 .writeBarrierDone:
417 end
418
419 macro writeBarrierOnOperands(cellOperand, valueOperand)
420     loadisFromInstruction(valueOperand, t1)
421     loadConstantOrVariableCell(t1, t0, .writeBarrierDone)
422     btpz t0, .writeBarrierDone
423
424     writeBarrierOnOperand(cellOperand)
425 .writeBarrierDone:
426 end
427
428 macro writeBarrierOnGlobal(valueOperand, loadHelper)
429     loadisFromInstruction(valueOperand, t1)
430     loadConstantOrVariableCell(t1, t0, .writeBarrierDone)
431     btpz t0, .writeBarrierDone
432
433     loadHelper(t3)
434     skipIfIsRememberedOrInEden(
435         t3,
436         macro()
437             push PB, PC
438             move cfr, a0
439             move t3, a1
440             cCall2Void(_llint_write_barrier_slow)
441             pop PC, PB
442         end
443     )
444 .writeBarrierDone:
445 end
446
447 macro writeBarrierOnGlobalObject(valueOperand)
448     writeBarrierOnGlobal(valueOperand,
449         macro(registerToStoreGlobal)
450             loadp CodeBlock[cfr], registerToStoreGlobal
451             loadp CodeBlock::m_globalObject[registerToStoreGlobal], registerToStoreGlobal
452         end)
453 end
454
455 macro writeBarrierOnGlobalLexicalEnvironment(valueOperand)
456     writeBarrierOnGlobal(valueOperand,
457         macro(registerToStoreGlobal)
458             loadp CodeBlock[cfr], registerToStoreGlobal
459             loadp CodeBlock::m_globalObject[registerToStoreGlobal], registerToStoreGlobal
460             loadp JSGlobalObject::m_globalLexicalEnvironment[registerToStoreGlobal], registerToStoreGlobal
461         end)
462 end
463
464 macro valueProfile(value, operand, scratch)
465     loadpFromInstruction(operand, scratch)
466     storeq value, ValueProfile::m_buckets[scratch]
467 end
468
469 macro structureIDToStructureWithScratch(structureIDThenStructure, scratch)
470     loadp CodeBlock[cfr], scratch
471     loadp CodeBlock::m_vm[scratch], scratch
472     loadp VM::heap + Heap::m_structureIDTable + StructureIDTable::m_table[scratch], scratch
473     loadp [scratch, structureIDThenStructure, 8], structureIDThenStructure
474 end
475
476 macro loadStructureWithScratch(cell, structure, scratch)
477     loadi JSCell::m_structureID[cell], structure
478     structureIDToStructureWithScratch(structure, scratch)
479 end
480
481 macro loadStructureAndClobberFirstArg(cell, structure)
482     loadi JSCell::m_structureID[cell], structure
483     loadp CodeBlock[cfr], cell
484     loadp CodeBlock::m_vm[cell], cell
485     loadp VM::heap + Heap::m_structureIDTable + StructureIDTable::m_table[cell], cell
486     loadp [cell, structure, 8], structure
487 end
488
489 # Entrypoints into the interpreter.
490
491 # Expects that CodeBlock is in t1, which is what prologue() leaves behind.
492 macro functionArityCheck(doneLabel, slowPath)
493     loadi PayloadOffset + ArgumentCount[cfr], t0
494     biaeq t0, CodeBlock::m_numParameters[t1], doneLabel
495     prepareStateForCCall()
496     move cfr, a0
497     move PC, a1
498     cCall2(slowPath)   # This slowPath has the protocol: r0 = 0 => no error, r0 != 0 => error
499     btiz r0, .noError
500     move r1, cfr   # r1 contains caller frame
501     jmp _llint_throw_from_slow_path_trampoline
502
503 .noError:
504     loadi CommonSlowPaths::ArityCheckData::paddedStackSpace[r1], t1
505     btiz t1, .continue
506     loadi PayloadOffset + ArgumentCount[cfr], t2
507     addi CallFrameHeaderSlots, t2
508
509     // Check if there are some unaligned slots we can use
510     move t1, t3
511     andi StackAlignmentSlots - 1, t3
512     btiz t3, .noExtraSlot
513     move ValueUndefined, t0
514 .fillExtraSlots:
515     storeq t0, [cfr, t2, 8]
516     addi 1, t2
517     bsubinz 1, t3, .fillExtraSlots
518     andi ~(StackAlignmentSlots - 1), t1
519     btiz t1, .continue
520
521 .noExtraSlot:
522     // Move frame up t1 slots
523     negq t1
524     move cfr, t3
525     subp CalleeSaveSpaceAsVirtualRegisters * 8, t3
526     addi CalleeSaveSpaceAsVirtualRegisters, t2
527 .copyLoop:
528     loadq [t3], t0
529     storeq t0, [t3, t1, 8]
530     addp 8, t3
531     bsubinz 1, t2, .copyLoop
532
533     // Fill new slots with JSUndefined
534     move t1, t2
535     move ValueUndefined, t0
536 .fillLoop:
537     storeq t0, [t3, t1, 8]
538     addp 8, t3
539     baddinz 1, t2, .fillLoop
540
541     lshiftp 3, t1
542     addp t1, cfr
543     addp t1, sp
544
545 .continue:
546     # Reload CodeBlock and reset PC, since the slow_path clobbered them.
547     loadp CodeBlock[cfr], t1
548     loadp CodeBlock::m_instructions[t1], PB
549     move 0, PC
550     jmp doneLabel
551 end
552
553 macro branchIfException(label)
554     loadp Callee[cfr], t3
555     andp MarkedBlockMask, t3
556     loadp MarkedBlock::m_vm[t3], t3
557     btqz VM::m_exception[t3], .noException
558     jmp label
559 .noException:
560 end
561
562
563 # Instruction implementations
564 _llint_op_enter:
565     traceExecution()
566     checkStackPointerAlignment(t2, 0xdead00e1)
567     loadp CodeBlock[cfr], t2                // t2<CodeBlock> = cfr.CodeBlock
568     loadi CodeBlock::m_numVars[t2], t2      // t2<size_t> = t2<CodeBlock>.m_numVars
569     subq CalleeSaveSpaceAsVirtualRegisters, t2
570     move cfr, t1
571     subq CalleeSaveSpaceAsVirtualRegisters * 8, t1
572     btiz t2, .opEnterDone
573     move ValueUndefined, t0
574     negi t2
575     sxi2q t2, t2
576 .opEnterLoop:
577     storeq t0, [t1, t2, 8]
578     addq 1, t2
579     btqnz t2, .opEnterLoop
580 .opEnterDone:
581     callOpcodeSlowPath(_slow_path_enter)
582     dispatch(1)
583
584
585 _llint_op_get_argument:
586     traceExecution()
587     loadisFromInstruction(1, t1)
588     loadisFromInstruction(2, t2)
589     loadi PayloadOffset + ArgumentCount[cfr], t0
590     bilteq t0, t2, .opGetArgumentOutOfBounds
591     loadq ThisArgumentOffset[cfr, t2, 8], t0
592     storeq t0, [cfr, t1, 8]
593     valueProfile(t0, 3, t2)
594     dispatch(4)
595
596 .opGetArgumentOutOfBounds:
597     storeq ValueUndefined, [cfr, t1, 8]
598     valueProfile(ValueUndefined, 3, t2)
599     dispatch(4)
600
601
602 _llint_op_argument_count:
603     traceExecution()
604     loadisFromInstruction(1, t1)
605     loadi PayloadOffset + ArgumentCount[cfr], t0
606     subi 1, t0
607     orq TagTypeNumber, t0
608     storeq t0, [cfr, t1, 8]
609     dispatch(2)
610
611
612 _llint_op_get_scope:
613     traceExecution()
614     loadp Callee[cfr], t0
615     loadp JSCallee::m_scope[t0], t0
616     loadisFromInstruction(1, t1)
617     storeq t0, [cfr, t1, 8]
618     dispatch(2)
619
620
621 _llint_op_to_this:
622     traceExecution()
623     loadisFromInstruction(1, t0)
624     loadq [cfr, t0, 8], t0
625     btqnz t0, tagMask, .opToThisSlow
626     bbneq JSCell::m_type[t0], FinalObjectType, .opToThisSlow
627     loadStructureWithScratch(t0, t1, t2)
628     loadpFromInstruction(2, t2)
629     bpneq t1, t2, .opToThisSlow
630     dispatch(4)
631
632 .opToThisSlow:
633     callOpcodeSlowPath(_slow_path_to_this)
634     dispatch(4)
635
636
637 _llint_op_check_tdz:
638     traceExecution()
639     loadisFromInstruction(1, t0)
640     loadConstantOrVariable(t0, t1)
641     bqneq t1, ValueEmpty, .opNotTDZ
642     callOpcodeSlowPath(_slow_path_throw_tdz_error)
643
644 .opNotTDZ:
645     dispatch(2)
646
647
648 _llint_op_mov:
649     traceExecution()
650     loadisFromInstruction(2, t1)
651     loadisFromInstruction(1, t0)
652     loadConstantOrVariable(t1, t2)
653     storeq t2, [cfr, t0, 8]
654     dispatch(3)
655
656
657 _llint_op_not:
658     traceExecution()
659     loadisFromInstruction(2, t0)
660     loadisFromInstruction(1, t1)
661     loadConstantOrVariable(t0, t2)
662     xorq ValueFalse, t2
663     btqnz t2, ~1, .opNotSlow
664     xorq ValueTrue, t2
665     storeq t2, [cfr, t1, 8]
666     dispatch(3)
667
668 .opNotSlow:
669     callOpcodeSlowPath(_slow_path_not)
670     dispatch(3)
671
672
673 macro equalityComparison(integerComparison, slowPath)
674     traceExecution()
675     loadisFromInstruction(3, t0)
676     loadisFromInstruction(2, t2)
677     loadisFromInstruction(1, t3)
678     loadConstantOrVariableInt32(t0, t1, .slow)
679     loadConstantOrVariableInt32(t2, t0, .slow)
680     integerComparison(t0, t1, t0)
681     orq ValueFalse, t0
682     storeq t0, [cfr, t3, 8]
683     dispatch(4)
684
685 .slow:
686     callOpcodeSlowPath(slowPath)
687     dispatch(4)
688 end
689
690 _llint_op_eq:
691     equalityComparison(
692         macro (left, right, result) cieq left, right, result end,
693         _slow_path_eq)
694
695
696 _llint_op_neq:
697     equalityComparison(
698         macro (left, right, result) cineq left, right, result end,
699         _slow_path_neq)
700
701
702 macro equalNullComparison()
703     loadisFromInstruction(2, t0)
704     loadq [cfr, t0, 8], t0
705     btqnz t0, tagMask, .immediate
706     btbnz JSCell::m_flags[t0], MasqueradesAsUndefined, .masqueradesAsUndefined
707     move 0, t0
708     jmp .done
709 .masqueradesAsUndefined:
710     loadStructureWithScratch(t0, t2, t1)
711     loadp CodeBlock[cfr], t0
712     loadp CodeBlock::m_globalObject[t0], t0
713     cpeq Structure::m_globalObject[t2], t0, t0
714     jmp .done
715 .immediate:
716     andq ~TagBitUndefined, t0
717     cqeq t0, ValueNull, t0
718 .done:
719 end
720
721 _llint_op_eq_null:
722     traceExecution()
723     equalNullComparison()
724     loadisFromInstruction(1, t1)
725     orq ValueFalse, t0
726     storeq t0, [cfr, t1, 8]
727     dispatch(3)
728
729
730 _llint_op_neq_null:
731     traceExecution()
732     equalNullComparison()
733     loadisFromInstruction(1, t1)
734     xorq ValueTrue, t0
735     storeq t0, [cfr, t1, 8]
736     dispatch(3)
737
738
739 macro strictEq(equalityOperation, slowPath)
740     traceExecution()
741     loadisFromInstruction(3, t0)
742     loadisFromInstruction(2, t2)
743     loadConstantOrVariable(t0, t1)
744     loadConstantOrVariable(t2, t0)
745     move t0, t2
746     orq t1, t2
747     btqz t2, tagMask, .slow
748     bqaeq t0, tagTypeNumber, .leftOK
749     btqnz t0, tagTypeNumber, .slow
750 .leftOK:
751     bqaeq t1, tagTypeNumber, .rightOK
752     btqnz t1, tagTypeNumber, .slow
753 .rightOK:
754     equalityOperation(t0, t1, t0)
755     loadisFromInstruction(1, t1)
756     orq ValueFalse, t0
757     storeq t0, [cfr, t1, 8]
758     dispatch(4)
759
760 .slow:
761     callOpcodeSlowPath(slowPath)
762     dispatch(4)
763 end
764
765 _llint_op_stricteq:
766     strictEq(
767         macro (left, right, result) cqeq left, right, result end,
768         _slow_path_stricteq)
769
770
771 _llint_op_nstricteq:
772     strictEq(
773         macro (left, right, result) cqneq left, right, result end,
774         _slow_path_nstricteq)
775
776
777 macro preOp(arithmeticOperation, slowPath)
778     traceExecution()
779     loadisFromInstruction(1, t0)
780     loadq [cfr, t0, 8], t1
781     bqb t1, tagTypeNumber, .slow
782     arithmeticOperation(t1, .slow)
783     orq tagTypeNumber, t1
784     storeq t1, [cfr, t0, 8]
785     dispatch(2)
786
787 .slow:
788     callOpcodeSlowPath(slowPath)
789     dispatch(2)
790 end
791
792 _llint_op_inc:
793     preOp(
794         macro (value, slow) baddio 1, value, slow end,
795         _slow_path_inc)
796
797
798 _llint_op_dec:
799     preOp(
800         macro (value, slow) bsubio 1, value, slow end,
801         _slow_path_dec)
802
803
804 _llint_op_to_number:
805     traceExecution()
806     loadisFromInstruction(2, t0)
807     loadisFromInstruction(1, t1)
808     loadConstantOrVariable(t0, t2)
809     bqaeq t2, tagTypeNumber, .opToNumberIsImmediate
810     btqz t2, tagTypeNumber, .opToNumberSlow
811 .opToNumberIsImmediate:
812     storeq t2, [cfr, t1, 8]
813     valueProfile(t2, 3, t0)
814     dispatch(4)
815
816 .opToNumberSlow:
817     callOpcodeSlowPath(_slow_path_to_number)
818     dispatch(4)
819
820
821 _llint_op_to_string:
822     traceExecution()
823     loadisFromInstruction(2, t1)
824     loadisFromInstruction(1, t2)
825     loadConstantOrVariable(t1, t0)
826     btqnz t0, tagMask, .opToStringSlow
827     bbneq JSCell::m_type[t0], StringType, .opToStringSlow
828 .opToStringIsString:
829     storeq t0, [cfr, t2, 8]
830     dispatch(3)
831
832 .opToStringSlow:
833     callOpcodeSlowPath(_slow_path_to_string)
834     dispatch(3)
835
836
837 _llint_op_negate:
838     traceExecution()
839     loadisFromInstruction(2, t0)
840     loadisFromInstruction(1, t1)
841     loadConstantOrVariable(t0, t3)
842     loadisFromInstruction(3, t2)
843     bqb t3, tagTypeNumber, .opNegateNotInt
844     btiz t3, 0x7fffffff, .opNegateSlow
845     negi t3
846     ori ArithProfileInt, t2
847     orq tagTypeNumber, t3
848     storeisToInstruction(t2, 3)
849     storeq t3, [cfr, t1, 8]
850     dispatch(4)
851 .opNegateNotInt:
852     btqz t3, tagTypeNumber, .opNegateSlow
853     xorq 0x8000000000000000, t3
854     ori ArithProfileNumber, t2
855     storeq t3, [cfr, t1, 8]
856     storeisToInstruction(t2, 3)
857     dispatch(4)
858
859 .opNegateSlow:
860     callOpcodeSlowPath(_slow_path_negate)
861     dispatch(4)
862
863
864 macro binaryOpCustomStore(integerOperationAndStore, doubleOperation, slowPath)
865     loadisFromInstruction(3, t0)
866     loadisFromInstruction(2, t2)
867     loadConstantOrVariable(t0, t1)
868     loadConstantOrVariable(t2, t0)
869     bqb t0, tagTypeNumber, .op1NotInt
870     bqb t1, tagTypeNumber, .op2NotInt
871     loadisFromInstruction(1, t2)
872     integerOperationAndStore(t1, t0, .slow, t2)
873     loadisFromInstruction(4, t1)
874     ori ArithProfileIntInt, t1
875     storeisToInstruction(t1, 4)
876     dispatch(5)
877
878 .op1NotInt:
879     # First operand is definitely not an int, the second operand could be anything.
880     btqz t0, tagTypeNumber, .slow
881     bqaeq t1, tagTypeNumber, .op1NotIntOp2Int
882     btqz t1, tagTypeNumber, .slow
883     addq tagTypeNumber, t1
884     fq2d t1, ft1
885     loadisFromInstruction(4, t2)
886     ori ArithProfileNumberNumber, t2
887     storeisToInstruction(t2, 4)
888     jmp .op1NotIntReady
889 .op1NotIntOp2Int:
890     loadisFromInstruction(4, t2)
891     ori ArithProfileNumberInt, t2
892     storeisToInstruction(t2, 4)
893     ci2d t1, ft1
894 .op1NotIntReady:
895     loadisFromInstruction(1, t2)
896     addq tagTypeNumber, t0
897     fq2d t0, ft0
898     doubleOperation(ft1, ft0)
899     fd2q ft0, t0
900     subq tagTypeNumber, t0
901     storeq t0, [cfr, t2, 8]
902     dispatch(5)
903
904 .op2NotInt:
905     # First operand is definitely an int, the second is definitely not.
906     loadisFromInstruction(1, t2)
907     btqz t1, tagTypeNumber, .slow
908     loadisFromInstruction(4, t3)
909     ori ArithProfileIntNumber, t3
910     storeisToInstruction(t3, 4)
911     ci2d t0, ft0
912     addq tagTypeNumber, t1
913     fq2d t1, ft1
914     doubleOperation(ft1, ft0)
915     fd2q ft0, t0
916     subq tagTypeNumber, t0
917     storeq t0, [cfr, t2, 8]
918     dispatch(5)
919
920 .slow:
921     callOpcodeSlowPath(slowPath)
922     dispatch(5)
923 end
924
925 macro binaryOp(integerOperation, doubleOperation, slowPath)
926     binaryOpCustomStore(
927         macro (left, right, slow, index)
928             integerOperation(left, right, slow)
929             orq tagTypeNumber, right
930             storeq right, [cfr, index, 8]
931         end,
932         doubleOperation, slowPath)
933 end
934
935 _llint_op_add:
936     traceExecution()
937     binaryOp(
938         macro (left, right, slow) baddio left, right, slow end,
939         macro (left, right) addd left, right end,
940         _slow_path_add)
941
942
943 _llint_op_mul:
944     traceExecution()
945     binaryOpCustomStore(
946         macro (left, right, slow, index)
947             # Assume t3 is scratchable.
948             move right, t3
949             bmulio left, t3, slow
950             btinz t3, .done
951             bilt left, 0, slow
952             bilt right, 0, slow
953         .done:
954             orq tagTypeNumber, t3
955             storeq t3, [cfr, index, 8]
956         end,
957         macro (left, right) muld left, right end,
958         _slow_path_mul)
959
960
961 _llint_op_sub:
962     traceExecution()
963     binaryOp(
964         macro (left, right, slow) bsubio left, right, slow end,
965         macro (left, right) subd left, right end,
966         _slow_path_sub)
967
968
969 _llint_op_div:
970     traceExecution()
971     if X86_64 or X86_64_WIN
972         binaryOpCustomStore(
973             macro (left, right, slow, index)
974                 # Assume t3 is scratchable.
975                 btiz left, slow
976                 bineq left, -1, .notNeg2TwoThe31DivByNeg1
977                 bieq right, -2147483648, .slow
978             .notNeg2TwoThe31DivByNeg1:
979                 btinz right, .intOK
980                 bilt left, 0, slow
981             .intOK:
982                 move left, t3
983                 move right, t0
984                 cdqi
985                 idivi t3
986                 btinz t1, slow
987                 orq tagTypeNumber, t0
988                 storeq t0, [cfr, index, 8]
989             end,
990             macro (left, right) divd left, right end,
991             _slow_path_div)
992     else
993         callOpcodeSlowPath(_slow_path_div)
994         dispatch(5)
995     end
996
997
998 macro bitOp(operation, slowPath, advance)
999     loadisFromInstruction(3, t0)
1000     loadisFromInstruction(2, t2)
1001     loadisFromInstruction(1, t3)
1002     loadConstantOrVariable(t0, t1)
1003     loadConstantOrVariable(t2, t0)
1004     bqb t0, tagTypeNumber, .slow
1005     bqb t1, tagTypeNumber, .slow
1006     operation(t1, t0)
1007     orq tagTypeNumber, t0
1008     storeq t0, [cfr, t3, 8]
1009     dispatch(advance)
1010
1011 .slow:
1012     callOpcodeSlowPath(slowPath)
1013     dispatch(advance)
1014 end
1015
1016 _llint_op_lshift:
1017     traceExecution()
1018     bitOp(
1019         macro (left, right) lshifti left, right end,
1020         _slow_path_lshift,
1021         4)
1022
1023
1024 _llint_op_rshift:
1025     traceExecution()
1026     bitOp(
1027         macro (left, right) rshifti left, right end,
1028         _slow_path_rshift,
1029         4)
1030
1031
1032 _llint_op_urshift:
1033     traceExecution()
1034     bitOp(
1035         macro (left, right) urshifti left, right end,
1036         _slow_path_urshift,
1037         4)
1038
1039
1040 _llint_op_unsigned:
1041     traceExecution()
1042     loadisFromInstruction(1, t0)
1043     loadisFromInstruction(2, t1)
1044     loadConstantOrVariable(t1, t2)
1045     bilt t2, 0, .opUnsignedSlow
1046     storeq t2, [cfr, t0, 8]
1047     dispatch(3)
1048 .opUnsignedSlow:
1049     callOpcodeSlowPath(_slow_path_unsigned)
1050     dispatch(3)
1051
1052
1053 _llint_op_bitand:
1054     traceExecution()
1055     bitOp(
1056         macro (left, right) andi left, right end,
1057         _slow_path_bitand,
1058         5)
1059
1060
1061 _llint_op_bitxor:
1062     traceExecution()
1063     bitOp(
1064         macro (left, right) xori left, right end,
1065         _slow_path_bitxor,
1066         5)
1067
1068
1069 _llint_op_bitor:
1070     traceExecution()
1071     bitOp(
1072         macro (left, right) ori left, right end,
1073         _slow_path_bitor,
1074         5)
1075
1076
1077 _llint_op_overrides_has_instance:
1078     traceExecution()
1079     loadisFromInstruction(1, t3)
1080
1081     loadisFromInstruction(3, t1)
1082     loadConstantOrVariable(t1, t0)
1083     loadp CodeBlock[cfr], t2
1084     loadp CodeBlock::m_globalObject[t2], t2
1085     loadp JSGlobalObject::m_functionProtoHasInstanceSymbolFunction[t2], t2
1086     bqneq t0, t2, .opOverridesHasInstanceNotDefaultSymbol
1087
1088     loadisFromInstruction(2, t1)
1089     loadConstantOrVariable(t1, t0)
1090     tbz JSCell::m_flags[t0], ImplementsDefaultHasInstance, t1
1091     orq ValueFalse, t1
1092     storeq t1, [cfr, t3, 8]
1093     dispatch(4)
1094
1095 .opOverridesHasInstanceNotDefaultSymbol:
1096     storeq ValueTrue, [cfr, t3, 8]
1097     dispatch(4)
1098
1099
1100 _llint_op_instanceof_custom:
1101     traceExecution()
1102     callOpcodeSlowPath(_llint_slow_path_instanceof_custom)
1103     dispatch(5)
1104
1105
1106 _llint_op_is_empty:
1107     traceExecution()
1108     loadisFromInstruction(2, t1)
1109     loadisFromInstruction(1, t2)
1110     loadConstantOrVariable(t1, t0)
1111     cqeq t0, ValueEmpty, t3
1112     orq ValueFalse, t3
1113     storeq t3, [cfr, t2, 8]
1114     dispatch(3)
1115
1116
1117 _llint_op_is_undefined:
1118     traceExecution()
1119     loadisFromInstruction(2, t1)
1120     loadisFromInstruction(1, t2)
1121     loadConstantOrVariable(t1, t0)
1122     btqz t0, tagMask, .opIsUndefinedCell
1123     cqeq t0, ValueUndefined, t3
1124     orq ValueFalse, t3
1125     storeq t3, [cfr, t2, 8]
1126     dispatch(3)
1127 .opIsUndefinedCell:
1128     btbnz JSCell::m_flags[t0], MasqueradesAsUndefined, .masqueradesAsUndefined
1129     move ValueFalse, t1
1130     storeq t1, [cfr, t2, 8]
1131     dispatch(3)
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
1137     orq ValueFalse, t0
1138     storeq t0, [cfr, t2, 8]
1139     dispatch(3)
1140
1141
1142 _llint_op_is_boolean:
1143     traceExecution()
1144     loadisFromInstruction(2, t1)
1145     loadisFromInstruction(1, t2)
1146     loadConstantOrVariable(t1, t0)
1147     xorq ValueFalse, t0
1148     tqz t0, ~1, t0
1149     orq ValueFalse, t0
1150     storeq t0, [cfr, t2, 8]
1151     dispatch(3)
1152
1153
1154 _llint_op_is_number:
1155     traceExecution()
1156     loadisFromInstruction(2, t1)
1157     loadisFromInstruction(1, t2)
1158     loadConstantOrVariable(t1, t0)
1159     tqnz t0, tagTypeNumber, t1
1160     orq ValueFalse, t1
1161     storeq t1, [cfr, t2, 8]
1162     dispatch(3)
1163
1164
1165 _llint_op_is_cell_with_type:
1166     traceExecution()
1167     loadisFromInstruction(3, t0)
1168     loadisFromInstruction(2, t1)
1169     loadisFromInstruction(1, t2)
1170     loadConstantOrVariable(t1, t3)
1171     btqnz t3, tagMask, .notCellCase
1172     cbeq JSCell::m_type[t3], t0, t1
1173     orq ValueFalse, t1
1174     storeq t1, [cfr, t2, 8]
1175     dispatch(4)
1176 .notCellCase:
1177     storeq ValueFalse, [cfr, t2, 8]
1178     dispatch(4)
1179
1180
1181 _llint_op_is_object:
1182     traceExecution()
1183     loadisFromInstruction(2, t1)
1184     loadisFromInstruction(1, t2)
1185     loadConstantOrVariable(t1, t0)
1186     btqnz t0, tagMask, .opIsObjectNotCell
1187     cbaeq JSCell::m_type[t0], ObjectType, t1
1188     orq ValueFalse, t1
1189     storeq t1, [cfr, t2, 8]
1190     dispatch(3)
1191 .opIsObjectNotCell:
1192     storeq ValueFalse, [cfr, t2, 8]
1193     dispatch(3)
1194
1195
1196 macro loadPropertyAtVariableOffset(propertyOffsetAsInt, objectAndStorage, value)
1197     bilt propertyOffsetAsInt, firstOutOfLineOffset, .isInline
1198     loadp JSObject::m_butterfly[objectAndStorage], objectAndStorage
1199     negi propertyOffsetAsInt
1200     sxi2q propertyOffsetAsInt, propertyOffsetAsInt
1201     jmp .ready
1202 .isInline:
1203     addp sizeof JSObject - (firstOutOfLineOffset - 2) * 8, objectAndStorage
1204 .ready:
1205     loadq (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffsetAsInt, 8], value
1206 end
1207
1208
1209 macro storePropertyAtVariableOffset(propertyOffsetAsInt, objectAndStorage, value)
1210     bilt propertyOffsetAsInt, firstOutOfLineOffset, .isInline
1211     loadp JSObject::m_butterfly[objectAndStorage], objectAndStorage
1212     negi propertyOffsetAsInt
1213     sxi2q propertyOffsetAsInt, propertyOffsetAsInt
1214     jmp .ready
1215 .isInline:
1216     addp sizeof JSObject - (firstOutOfLineOffset - 2) * 8, objectAndStorage
1217 .ready:
1218     storeq value, (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffsetAsInt, 8]
1219 end
1220
1221 _llint_op_get_by_id:
1222     traceExecution()
1223     loadisFromInstruction(2, t0)
1224     loadConstantOrVariableCell(t0, t3, .opGetByIdSlow)
1225     loadi JSCell::m_structureID[t3], t1
1226     loadisFromInstruction(4, t2)
1227     bineq t2, t1, .opGetByIdSlow
1228     loadisFromInstruction(5, t1)
1229     loadisFromInstruction(1, t2)
1230     loadPropertyAtVariableOffset(t1, t3, t0)
1231     storeq t0, [cfr, t2, 8]
1232     valueProfile(t0, 8, t1)
1233     dispatch(9)
1234
1235 .opGetByIdSlow:
1236     callOpcodeSlowPath(_llint_slow_path_get_by_id)
1237     dispatch(9)
1238
1239
1240 _llint_op_get_by_id_proto_load:
1241     traceExecution()
1242     loadisFromInstruction(2, t0)
1243     loadConstantOrVariableCell(t0, t3, .opGetByIdProtoSlow)
1244     loadi JSCell::m_structureID[t3], t1
1245     loadisFromInstruction(4, t2)
1246     bineq t2, t1, .opGetByIdProtoSlow
1247     loadisFromInstruction(5, t1)
1248     loadpFromInstruction(6, t3)
1249     loadisFromInstruction(1, t2)
1250     loadPropertyAtVariableOffset(t1, t3, t0)
1251     storeq t0, [cfr, t2, 8]
1252     valueProfile(t0, 8, t1)
1253     dispatch(9)
1254
1255 .opGetByIdProtoSlow:
1256     callOpcodeSlowPath(_llint_slow_path_get_by_id)
1257     dispatch(9)
1258
1259
1260 _llint_op_get_by_id_unset:
1261     traceExecution()
1262     loadisFromInstruction(2, t0)
1263     loadConstantOrVariableCell(t0, t3, .opGetByIdUnsetSlow)
1264     loadi JSCell::m_structureID[t3], t1
1265     loadisFromInstruction(4, t2)
1266     bineq t2, t1, .opGetByIdUnsetSlow
1267     loadisFromInstruction(1, t2)
1268     storeq ValueUndefined, [cfr, t2, 8]
1269     valueProfile(ValueUndefined, 8, t1)
1270     dispatch(9)
1271
1272 .opGetByIdUnsetSlow:
1273     callOpcodeSlowPath(_llint_slow_path_get_by_id)
1274     dispatch(9)
1275
1276
1277 _llint_op_get_array_length:
1278     traceExecution()
1279     loadisFromInstruction(2, t0)
1280     loadpFromInstruction(4, t1)
1281     loadConstantOrVariableCell(t0, t3, .opGetArrayLengthSlow)
1282     move t3, t2
1283     arrayProfile(t2, t1, t0)
1284     btiz t2, IsArray, .opGetArrayLengthSlow
1285     btiz t2, IndexingShapeMask, .opGetArrayLengthSlow
1286     loadisFromInstruction(1, t1)
1287     loadp JSObject::m_butterfly[t3], t0
1288     loadi -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], t0
1289     bilt t0, 0, .opGetArrayLengthSlow
1290     orq tagTypeNumber, t0
1291     valueProfile(t0, 8, t2)
1292     storeq t0, [cfr, t1, 8]
1293     dispatch(9)
1294
1295 .opGetArrayLengthSlow:
1296     callOpcodeSlowPath(_llint_slow_path_get_by_id)
1297     dispatch(9)
1298
1299
1300 _llint_op_put_by_id:
1301     traceExecution()
1302     loadisFromInstruction(1, t3)
1303     loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
1304     loadisFromInstruction(4, t2)
1305     bineq t2, JSCell::m_structureID[t0], .opPutByIdSlow
1306
1307     # At this point, we have:
1308     # t2 -> current structure ID
1309     # t0 -> object base
1310
1311     loadisFromInstruction(3, t1)
1312     loadConstantOrVariable(t1, t3)
1313
1314     loadpFromInstruction(8, t1)
1315
1316     # At this point, we have:
1317     # t0 -> object base
1318     # t1 -> put by id flags
1319     # t2 -> current structure ID
1320     # t3 -> value to put
1321
1322     btpnz t1, PutByIdPrimaryTypeMask, .opPutByIdTypeCheckObjectWithStructureOrOther
1323
1324     # We have one of the non-structure type checks. Find out which one.
1325     andp PutByIdSecondaryTypeMask, t1
1326     bplt t1, PutByIdSecondaryTypeString, .opPutByIdTypeCheckLessThanString
1327
1328     # We are one of the following: String, Symbol, Object, ObjectOrOther, Top
1329     bplt t1, PutByIdSecondaryTypeObjectOrOther, .opPutByIdTypeCheckLessThanObjectOrOther
1330
1331     # We are either ObjectOrOther or Top.
1332     bpeq t1, PutByIdSecondaryTypeTop, .opPutByIdDoneCheckingTypes
1333
1334     # Check if we are ObjectOrOther.
1335     btqz t3, tagMask, .opPutByIdTypeCheckObject
1336 .opPutByIdTypeCheckOther:
1337     andq ~TagBitUndefined, t3
1338     bqeq t3, ValueNull, .opPutByIdDoneCheckingTypes
1339     jmp .opPutByIdSlow
1340
1341 .opPutByIdTypeCheckLessThanObjectOrOther:
1342     # We are either String, Symbol or Object.
1343     btqnz t3, tagMask, .opPutByIdSlow
1344     bpeq t1, PutByIdSecondaryTypeObject, .opPutByIdTypeCheckObject
1345     bpeq t1, PutByIdSecondaryTypeSymbol, .opPutByIdTypeCheckSymbol
1346     bbeq JSCell::m_type[t3], StringType, .opPutByIdDoneCheckingTypes
1347     jmp .opPutByIdSlow
1348 .opPutByIdTypeCheckObject:
1349     bbaeq JSCell::m_type[t3], ObjectType, .opPutByIdDoneCheckingTypes
1350     jmp .opPutByIdSlow
1351 .opPutByIdTypeCheckSymbol:
1352     bbeq JSCell::m_type[t3], SymbolType, .opPutByIdDoneCheckingTypes
1353     jmp .opPutByIdSlow
1354
1355 .opPutByIdTypeCheckLessThanString:
1356     # We are one of the following: Bottom, Boolean, Other, Int32, Number
1357     bplt t1, PutByIdSecondaryTypeInt32, .opPutByIdTypeCheckLessThanInt32
1358
1359     # We are either Int32 or Number.
1360     bpeq t1, PutByIdSecondaryTypeNumber, .opPutByIdTypeCheckNumber
1361
1362     bqaeq t3, tagTypeNumber, .opPutByIdDoneCheckingTypes
1363     jmp .opPutByIdSlow
1364
1365 .opPutByIdTypeCheckNumber:
1366     btqnz t3, tagTypeNumber, .opPutByIdDoneCheckingTypes
1367     jmp .opPutByIdSlow
1368
1369 .opPutByIdTypeCheckLessThanInt32:
1370     # We are one of the following: Bottom, Boolean, Other.
1371     bpneq t1, PutByIdSecondaryTypeBoolean, .opPutByIdTypeCheckBottomOrOther
1372     xorq ValueFalse, t3
1373     btqz t3, ~1, .opPutByIdDoneCheckingTypes
1374     jmp .opPutByIdSlow
1375
1376 .opPutByIdTypeCheckBottomOrOther:
1377     bpeq t1, PutByIdSecondaryTypeOther, .opPutByIdTypeCheckOther
1378     jmp .opPutByIdSlow
1379
1380 .opPutByIdTypeCheckObjectWithStructureOrOther:
1381     btqz t3, tagMask, .opPutByIdTypeCheckObjectWithStructure
1382     btpnz t1, PutByIdPrimaryTypeObjectWithStructureOrOther, .opPutByIdTypeCheckOther
1383     jmp .opPutByIdSlow
1384
1385 .opPutByIdTypeCheckObjectWithStructure:
1386     urshiftp 3, t1
1387     bineq t1, JSCell::m_structureID[t3], .opPutByIdSlow
1388
1389 .opPutByIdDoneCheckingTypes:
1390     loadisFromInstruction(6, t1)
1391     
1392     btiz t1, .opPutByIdNotTransition
1393
1394     # This is the transition case. t1 holds the new structureID. t2 holds the old structure ID.
1395     # If we have a chain, we need to check it. t0 is the base. We may clobber t1 to use it as
1396     # scratch.
1397     loadpFromInstruction(7, t3)
1398     btpz t3, .opPutByIdTransitionDirect
1399
1400     loadp StructureChain::m_vector[t3], t3
1401     assert(macro (ok) btpnz t3, ok end)
1402
1403     structureIDToStructureWithScratch(t2, t1)
1404     loadq Structure::m_prototype[t2], t2
1405     bqeq t2, ValueNull, .opPutByIdTransitionChainDone
1406 .opPutByIdTransitionChainLoop:
1407     # At this point, t2 contains a prototye, and [t3] contains the Structure* that we want that
1408     # prototype to have. We don't want to have to load the Structure* for t2. Instead, we load
1409     # the Structure* from [t3], and then we compare its id to the id in the header of t2.
1410     loadp [t3], t1
1411     loadi JSCell::m_structureID[t2], t2
1412     # Now, t1 has the Structure* and t2 has the StructureID that we want that Structure* to have.
1413     bineq t2, Structure::m_blob + StructureIDBlob::u.fields.structureID[t1], .opPutByIdSlow
1414     addp 8, t3
1415     loadq Structure::m_prototype[t1], t2
1416     bqneq t2, ValueNull, .opPutByIdTransitionChainLoop
1417
1418 .opPutByIdTransitionChainDone:
1419     # Reload the new structure, since we clobbered it above.
1420     loadisFromInstruction(6, t1)
1421
1422 .opPutByIdTransitionDirect:
1423     storei t1, JSCell::m_structureID[t0]
1424     writeBarrierOnOperand(1)
1425     # Reload base into t0
1426     loadisFromInstruction(1, t1)
1427     loadConstantOrVariable(t1, t0)
1428
1429 .opPutByIdNotTransition:
1430     # The only thing live right now is t0, which holds the base.
1431     loadisFromInstruction(3, t1)
1432     loadConstantOrVariable(t1, t2)
1433     loadisFromInstruction(5, t1)
1434     storePropertyAtVariableOffset(t1, t0, t2)
1435     writeBarrierOnOperands(1, 3)
1436     dispatch(9)
1437
1438 .opPutByIdSlow:
1439     callOpcodeSlowPath(_llint_slow_path_put_by_id)
1440     dispatch(9)
1441
1442 macro finishGetByVal(result, scratch)
1443     loadisFromInstruction(1, scratch)
1444     storeq result, [cfr, scratch, 8]
1445     valueProfile(result, 5, scratch)
1446     dispatch(6)
1447 end
1448
1449 macro finishIntGetByVal(result, scratch)
1450     orq tagTypeNumber, result
1451     finishGetByVal(result, scratch)
1452 end
1453
1454 macro finishDoubleGetByVal(result, scratch1, scratch2)
1455     fd2q result, scratch1
1456     subq tagTypeNumber, scratch1
1457     finishGetByVal(scratch1, scratch2)
1458 end
1459
1460 _llint_op_get_by_val:
1461     traceExecution()
1462     loadisFromInstruction(2, t2)
1463     loadConstantOrVariableCell(t2, t0, .opGetByValSlow)
1464     loadpFromInstruction(4, t3)
1465     move t0, t2
1466     arrayProfile(t2, t3, t1)
1467     loadisFromInstruction(3, t3)
1468     loadConstantOrVariableInt32(t3, t1, .opGetByValSlow)
1469     sxi2q t1, t1
1470     loadp JSObject::m_butterfly[t0], t3
1471     andi IndexingShapeMask, t2
1472     bieq t2, Int32Shape, .opGetByValIsContiguous
1473     bineq t2, ContiguousShape, .opGetByValNotContiguous
1474 .opGetByValIsContiguous:
1475
1476     biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t3], .opGetByValOutOfBounds
1477     loadisFromInstruction(1, t0)
1478     loadq [t3, t1, 8], t2
1479     btqz t2, .opGetByValOutOfBounds
1480     jmp .opGetByValDone
1481
1482 .opGetByValNotContiguous:
1483     bineq t2, DoubleShape, .opGetByValNotDouble
1484     biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t3], .opGetByValOutOfBounds
1485     loadis 8[PB, PC, 8], t0
1486     loadd [t3, t1, 8], ft0
1487     bdnequn ft0, ft0, .opGetByValOutOfBounds
1488     fd2q ft0, t2
1489     subq tagTypeNumber, t2
1490     jmp .opGetByValDone
1491     
1492 .opGetByValNotDouble:
1493     subi ArrayStorageShape, t2
1494     bia t2, SlowPutArrayStorageShape - ArrayStorageShape, .opGetByValNotIndexedStorage
1495     biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t3], .opGetByValOutOfBounds
1496     loadisFromInstruction(1, t0)
1497     loadq ArrayStorage::m_vector[t3, t1, 8], t2
1498     btqz t2, .opGetByValOutOfBounds
1499
1500 .opGetByValDone:
1501     storeq t2, [cfr, t0, 8]
1502     valueProfile(t2, 5, t0)
1503     dispatch(6)
1504
1505 .opGetByValOutOfBounds:
1506     loadpFromInstruction(4, t0)
1507     storeb 1, ArrayProfile::m_outOfBounds[t0]
1508
1509 .opGetByValNotIndexedStorage:
1510     # First lets check if we even have a typed array. This lets us do some boilerplate up front.
1511     loadb JSCell::m_type[t0], t2
1512     subi FirstArrayType, t2
1513     bia t2, LastArrayType - FirstArrayType, .opGetByValSlow
1514     
1515     # Sweet, now we know that we have a typed array. Do some basic things now.
1516     loadp JSArrayBufferView::m_vector[t0], t3
1517     biaeq t1, JSArrayBufferView::m_length[t0], .opGetByValSlow
1518     
1519     # Now bisect through the various types. Note that we can treat Uint8ArrayType and
1520     # Uint8ClampedArrayType the same.
1521     bia t2, Uint8ClampedArrayType - FirstArrayType, .opGetByValAboveUint8ClampedArray
1522     
1523     # We have one of Int8ArrayType .. Uint8ClampedArrayType.
1524     bia t2, Int16ArrayType - FirstArrayType, .opGetByValInt32ArrayOrUint8Array
1525     
1526     # We have one of Int8ArrayType or Int16ArrayType
1527     bineq t2, Int8ArrayType - FirstArrayType, .opGetByValInt16Array
1528     
1529     # We have Int8ArrayType
1530     loadbs [t3, t1], t0
1531     finishIntGetByVal(t0, t1)
1532
1533 .opGetByValInt16Array:
1534     loadhs [t3, t1, 2], t0
1535     finishIntGetByVal(t0, t1)
1536
1537 .opGetByValInt32ArrayOrUint8Array:
1538     # We have one of Int16Array, Uint8Array, or Uint8ClampedArray.
1539     bieq t2, Int32ArrayType - FirstArrayType, .opGetByValInt32Array
1540     
1541     # We have either Uint8Array or Uint8ClampedArray. They behave the same so that's cool.
1542     loadb [t3, t1], t0
1543     finishIntGetByVal(t0, t1)
1544
1545 .opGetByValInt32Array:
1546     loadi [t3, t1, 4], t0
1547     finishIntGetByVal(t0, t1)
1548
1549 .opGetByValAboveUint8ClampedArray:
1550     # We have one of Uint16ArrayType .. Float64ArrayType.
1551     bia t2, Uint32ArrayType - FirstArrayType, .opGetByValAboveUint32Array
1552     
1553     # We have either Uint16ArrayType or Uint32ArrayType.
1554     bieq t2, Uint32ArrayType - FirstArrayType, .opGetByValUint32Array
1555
1556     # We have Uint16ArrayType.
1557     loadh [t3, t1, 2], t0
1558     finishIntGetByVal(t0, t1)
1559
1560 .opGetByValUint32Array:
1561     # This is the hardest part because of large unsigned values.
1562     loadi [t3, t1, 4], t0
1563     bilt t0, 0, .opGetByValSlow # This case is still awkward to implement in LLInt.
1564     finishIntGetByVal(t0, t1)
1565
1566 .opGetByValAboveUint32Array:
1567     # We have one of Float32ArrayType or Float64ArrayType. Sadly, we cannot handle Float32Array
1568     # inline yet. That would require some offlineasm changes.
1569     bieq t2, Float32ArrayType - FirstArrayType, .opGetByValSlow
1570
1571     # We have Float64ArrayType.
1572     loadd [t3, t1, 8], ft0
1573     bdnequn ft0, ft0, .opGetByValSlow
1574     finishDoubleGetByVal(ft0, t0, t1)
1575
1576 .opGetByValSlow:
1577     callOpcodeSlowPath(_llint_slow_path_get_by_val)
1578     dispatch(6)
1579
1580
1581 macro contiguousPutByVal(storeCallback)
1582     biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], .outOfBounds
1583 .storeResult:
1584     loadisFromInstruction(3, t2)
1585     storeCallback(t2, t1, [t0, t3, 8])
1586     dispatch(5)
1587
1588 .outOfBounds:
1589     biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t0], .opPutByValOutOfBounds
1590     loadp 32[PB, PC, 8], t2
1591     storeb 1, ArrayProfile::m_mayStoreToHole[t2]
1592     addi 1, t3, t2
1593     storei t2, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0]
1594     jmp .storeResult
1595 end
1596
1597 macro putByVal(slowPath)
1598     traceExecution()
1599     loadisFromInstruction(1, t0)
1600     loadConstantOrVariableCell(t0, t1, .opPutByValSlow)
1601     loadpFromInstruction(4, t3)
1602     move t1, t2
1603     arrayProfile(t2, t3, t0)
1604     loadisFromInstruction(2, t0)
1605     loadConstantOrVariableInt32(t0, t3, .opPutByValSlow)
1606     sxi2q t3, t3
1607     loadp JSObject::m_butterfly[t1], t0
1608     andi IndexingShapeMask, t2
1609     bineq t2, Int32Shape, .opPutByValNotInt32
1610     contiguousPutByVal(
1611         macro (operand, scratch, address)
1612             loadConstantOrVariable(operand, scratch)
1613             bpb scratch, tagTypeNumber, .opPutByValSlow
1614             storep scratch, address
1615             writeBarrierOnOperands(1, 3)
1616         end)
1617
1618 .opPutByValNotInt32:
1619     bineq t2, DoubleShape, .opPutByValNotDouble
1620     contiguousPutByVal(
1621         macro (operand, scratch, address)
1622             loadConstantOrVariable(operand, scratch)
1623             bqb scratch, tagTypeNumber, .notInt
1624             ci2d scratch, ft0
1625             jmp .ready
1626         .notInt:
1627             addp tagTypeNumber, scratch
1628             fq2d scratch, ft0
1629             bdnequn ft0, ft0, .opPutByValSlow
1630         .ready:
1631             stored ft0, address
1632             writeBarrierOnOperands(1, 3)
1633         end)
1634
1635 .opPutByValNotDouble:
1636     bineq t2, ContiguousShape, .opPutByValNotContiguous
1637     contiguousPutByVal(
1638         macro (operand, scratch, address)
1639             loadConstantOrVariable(operand, scratch)
1640             storep scratch, address
1641             writeBarrierOnOperands(1, 3)
1642         end)
1643
1644 .opPutByValNotContiguous:
1645     bineq t2, ArrayStorageShape, .opPutByValSlow
1646     biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t0], .opPutByValOutOfBounds
1647     btqz ArrayStorage::m_vector[t0, t3, 8], .opPutByValArrayStorageEmpty
1648 .opPutByValArrayStorageStoreResult:
1649     loadisFromInstruction(3, t2)
1650     loadConstantOrVariable(t2, t1)
1651     storeq t1, ArrayStorage::m_vector[t0, t3, 8]
1652     writeBarrierOnOperands(1, 3)
1653     dispatch(5)
1654
1655 .opPutByValArrayStorageEmpty:
1656     loadpFromInstruction(4, t1)
1657     storeb 1, ArrayProfile::m_mayStoreToHole[t1]
1658     addi 1, ArrayStorage::m_numValuesInVector[t0]
1659     bib t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], .opPutByValArrayStorageStoreResult
1660     addi 1, t3, t1
1661     storei t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0]
1662     jmp .opPutByValArrayStorageStoreResult
1663
1664 .opPutByValOutOfBounds:
1665     loadpFromInstruction(4, t0)
1666     storeb 1, ArrayProfile::m_outOfBounds[t0]
1667 .opPutByValSlow:
1668     callOpcodeSlowPath(slowPath)
1669     dispatch(5)
1670 end
1671
1672 _llint_op_put_by_val:
1673     putByVal(_llint_slow_path_put_by_val)
1674
1675 _llint_op_put_by_val_direct:
1676     putByVal(_llint_slow_path_put_by_val_direct)
1677
1678
1679 _llint_op_jmp:
1680     traceExecution()
1681     dispatchIntIndirect(1)
1682
1683
1684 macro jumpTrueOrFalse(conditionOp, slow)
1685     loadisFromInstruction(1, t1)
1686     loadConstantOrVariable(t1, t0)
1687     xorq ValueFalse, t0
1688     btqnz t0, -1, .slow
1689     conditionOp(t0, .target)
1690     dispatch(3)
1691
1692 .target:
1693     dispatchIntIndirect(2)
1694
1695 .slow:
1696     callOpcodeSlowPath(slow)
1697     dispatch(0)
1698 end
1699
1700
1701 macro equalNull(cellHandler, immediateHandler)
1702     loadisFromInstruction(1, t0)
1703     assertNotConstant(t0)
1704     loadq [cfr, t0, 8], t0
1705     btqnz t0, tagMask, .immediate
1706     loadStructureWithScratch(t0, t2, t1)
1707     cellHandler(t2, JSCell::m_flags[t0], .target)
1708     dispatch(3)
1709
1710 .target:
1711     dispatchIntIndirect(2)
1712
1713 .immediate:
1714     andq ~TagBitUndefined, t0
1715     immediateHandler(t0, .target)
1716     dispatch(3)
1717 end
1718
1719 _llint_op_jeq_null:
1720     traceExecution()
1721     equalNull(
1722         macro (structure, value, target) 
1723             btbz value, MasqueradesAsUndefined, .notMasqueradesAsUndefined
1724             loadp CodeBlock[cfr], t0
1725             loadp CodeBlock::m_globalObject[t0], t0
1726             bpeq Structure::m_globalObject[structure], t0, target
1727 .notMasqueradesAsUndefined:
1728         end,
1729         macro (value, target) bqeq value, ValueNull, target end)
1730
1731
1732 _llint_op_jneq_null:
1733     traceExecution()
1734     equalNull(
1735         macro (structure, value, target) 
1736             btbz value, MasqueradesAsUndefined, target
1737             loadp CodeBlock[cfr], t0
1738             loadp CodeBlock::m_globalObject[t0], t0
1739             bpneq Structure::m_globalObject[structure], t0, target
1740         end,
1741         macro (value, target) bqneq value, ValueNull, target end)
1742
1743
1744 _llint_op_jneq_ptr:
1745     traceExecution()
1746     loadisFromInstruction(1, t0)
1747     loadisFromInstruction(2, t1)
1748     loadp CodeBlock[cfr], t2
1749     loadp CodeBlock::m_globalObject[t2], t2
1750     loadp JSGlobalObject::m_specialPointers[t2, t1, 8], t1
1751     bpneq t1, [cfr, t0, 8], .opJneqPtrTarget
1752     dispatch(5)
1753
1754 .opJneqPtrTarget:
1755     storei 1, 32[PB, PC, 8]
1756     dispatchIntIndirect(3)
1757
1758
1759 macro compare(integerCompare, doubleCompare, slowPath)
1760     loadisFromInstruction(1, t2)
1761     loadisFromInstruction(2, t3)
1762     loadConstantOrVariable(t2, t0)
1763     loadConstantOrVariable(t3, t1)
1764     bqb t0, tagTypeNumber, .op1NotInt
1765     bqb t1, tagTypeNumber, .op2NotInt
1766     integerCompare(t0, t1, .jumpTarget)
1767     dispatch(4)
1768
1769 .op1NotInt:
1770     btqz t0, tagTypeNumber, .slow
1771     bqb t1, tagTypeNumber, .op1NotIntOp2NotInt
1772     ci2d t1, ft1
1773     jmp .op1NotIntReady
1774 .op1NotIntOp2NotInt:
1775     btqz t1, tagTypeNumber, .slow
1776     addq tagTypeNumber, t1
1777     fq2d t1, ft1
1778 .op1NotIntReady:
1779     addq tagTypeNumber, t0
1780     fq2d t0, ft0
1781     doubleCompare(ft0, ft1, .jumpTarget)
1782     dispatch(4)
1783
1784 .op2NotInt:
1785     ci2d t0, ft0
1786     btqz t1, tagTypeNumber, .slow
1787     addq tagTypeNumber, t1
1788     fq2d t1, ft1
1789     doubleCompare(ft0, ft1, .jumpTarget)
1790     dispatch(4)
1791
1792 .jumpTarget:
1793     dispatchIntIndirect(3)
1794
1795 .slow:
1796     callOpcodeSlowPath(slowPath)
1797     dispatch(0)
1798 end
1799
1800
1801 _llint_op_switch_imm:
1802     traceExecution()
1803     loadisFromInstruction(3, t2)
1804     loadisFromInstruction(1, t3)
1805     loadConstantOrVariable(t2, t1)
1806     loadp CodeBlock[cfr], t2
1807     loadp CodeBlock::m_rareData[t2], t2
1808     muli sizeof SimpleJumpTable, t3    # FIXME: would be nice to peephole this!
1809     loadp CodeBlock::RareData::m_switchJumpTables + VectorBufferOffset[t2], t2
1810     addp t3, t2
1811     bqb t1, tagTypeNumber, .opSwitchImmNotInt
1812     subi SimpleJumpTable::min[t2], t1
1813     biaeq t1, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchImmFallThrough
1814     loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t3
1815     loadis [t3, t1, 4], t1
1816     btiz t1, .opSwitchImmFallThrough
1817     dispatch(t1)
1818
1819 .opSwitchImmNotInt:
1820     btqnz t1, tagTypeNumber, .opSwitchImmSlow   # Go slow if it's a double.
1821 .opSwitchImmFallThrough:
1822     dispatchIntIndirect(2)
1823
1824 .opSwitchImmSlow:
1825     callOpcodeSlowPath(_llint_slow_path_switch_imm)
1826     dispatch(0)
1827
1828
1829 _llint_op_switch_char:
1830     traceExecution()
1831     loadisFromInstruction(3, t2)
1832     loadisFromInstruction(1, t3)
1833     loadConstantOrVariable(t2, t1)
1834     loadp CodeBlock[cfr], t2
1835     loadp CodeBlock::m_rareData[t2], t2
1836     muli sizeof SimpleJumpTable, t3
1837     loadp CodeBlock::RareData::m_switchJumpTables + VectorBufferOffset[t2], t2
1838     addp t3, t2
1839     btqnz t1, tagMask, .opSwitchCharFallThrough
1840     bbneq JSCell::m_type[t1], StringType, .opSwitchCharFallThrough
1841     bineq JSString::m_length[t1], 1, .opSwitchCharFallThrough
1842     loadp JSString::m_value[t1], t0
1843     btpz  t0, .opSwitchOnRope
1844     loadp StringImpl::m_data8[t0], t1
1845     btinz StringImpl::m_hashAndFlags[t0], HashFlags8BitBuffer, .opSwitchChar8Bit
1846     loadh [t1], t0
1847     jmp .opSwitchCharReady
1848 .opSwitchChar8Bit:
1849     loadb [t1], t0
1850 .opSwitchCharReady:
1851     subi SimpleJumpTable::min[t2], t0
1852     biaeq t0, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchCharFallThrough
1853     loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t2
1854     loadis [t2, t0, 4], t1
1855     btiz t1, .opSwitchCharFallThrough
1856     dispatch(t1)
1857
1858 .opSwitchCharFallThrough:
1859     dispatchIntIndirect(2)
1860
1861 .opSwitchOnRope:
1862     callOpcodeSlowPath(_llint_slow_path_switch_char)
1863     dispatch(0)
1864
1865
1866 macro arrayProfileForCall()
1867     loadisFromInstruction(4, t3)
1868     negp t3
1869     loadq ThisArgumentOffset[cfr, t3, 8], t0
1870     btqnz t0, tagMask, .done
1871     loadpFromInstruction((CallOpCodeSize - 2), t1)
1872     loadi JSCell::m_structureID[t0], t3
1873     storei t3, ArrayProfile::m_lastSeenStructureID[t1]
1874 .done:
1875 end
1876
1877 macro doCall(slowPath, prepareCall)
1878     loadisFromInstruction(2, t0)
1879     loadpFromInstruction(5, t1)
1880     loadp LLIntCallLinkInfo::callee[t1], t2
1881     loadConstantOrVariable(t0, t3)
1882     bqneq t3, t2, .opCallSlow
1883     loadisFromInstruction(4, t3)
1884     lshifti 3, t3
1885     negp t3
1886     addp cfr, t3
1887     storeq t2, Callee[t3]
1888     loadisFromInstruction(3, t2)
1889     storei PC, ArgumentCount + TagOffset[cfr]
1890     storei t2, ArgumentCount + PayloadOffset[t3]
1891     move t3, sp
1892     prepareCall(LLIntCallLinkInfo::machineCodeTarget[t1], t2, t3, t4)
1893     callTargetFunction(LLIntCallLinkInfo::machineCodeTarget[t1])
1894
1895 .opCallSlow:
1896     slowPathForCall(slowPath, prepareCall)
1897 end
1898
1899 _llint_op_ret:
1900     traceExecution()
1901     checkSwitchToJITForEpilogue()
1902     loadisFromInstruction(1, t2)
1903     loadConstantOrVariable(t2, r0)
1904     doReturn()
1905
1906
1907 _llint_op_to_primitive:
1908     traceExecution()
1909     loadisFromInstruction(2, t2)
1910     loadisFromInstruction(1, t3)
1911     loadConstantOrVariable(t2, t0)
1912     btqnz t0, tagMask, .opToPrimitiveIsImm
1913     bbaeq JSCell::m_type[t0], ObjectType, .opToPrimitiveSlowCase
1914 .opToPrimitiveIsImm:
1915     storeq t0, [cfr, t3, 8]
1916     dispatch(3)
1917
1918 .opToPrimitiveSlowCase:
1919     callOpcodeSlowPath(_slow_path_to_primitive)
1920     dispatch(3)
1921
1922
1923 _llint_op_catch:
1924     # This is where we end up from the JIT's throw trampoline (because the
1925     # machine code return address will be set to _llint_op_catch), and from
1926     # the interpreter's throw trampoline (see _llint_throw_trampoline).
1927     # The throwing code must have known that we were throwing to the interpreter,
1928     # and have set VM::targetInterpreterPCForThrow.
1929     loadp Callee[cfr], t3
1930     andp MarkedBlockMask, t3
1931     loadp MarkedBlock::m_vm[t3], t3
1932     restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer(t3, t0)
1933     loadp VM::callFrameForCatch[t3], cfr
1934     storep 0, VM::callFrameForCatch[t3]
1935     restoreStackPointerAfterCall()
1936
1937     loadp CodeBlock[cfr], PB
1938     loadp CodeBlock::m_instructions[PB], PB
1939     loadp VM::targetInterpreterPCForThrow[t3], PC
1940     subp PB, PC
1941     rshiftp 3, PC
1942
1943     callOpcodeSlowPath(_llint_slow_path_check_if_exception_is_uncatchable_and_notify_profiler)
1944     bpeq r1, 0, .isCatchableException
1945     jmp _llint_throw_from_slow_path_trampoline
1946
1947 .isCatchableException:
1948     loadp Callee[cfr], t3
1949     andp MarkedBlockMask, t3
1950     loadp MarkedBlock::m_vm[t3], t3
1951
1952     loadq VM::m_exception[t3], t0
1953     storeq 0, VM::m_exception[t3]
1954     loadisFromInstruction(1, t2)
1955     storeq t0, [cfr, t2, 8]
1956
1957     loadq Exception::m_value[t0], t3
1958     loadisFromInstruction(2, t2)
1959     storeq t3, [cfr, t2, 8]
1960
1961     traceExecution()
1962     dispatch(3)
1963
1964
1965 _llint_op_end:
1966     traceExecution()
1967     checkSwitchToJITForEpilogue()
1968     loadisFromInstruction(1, t0)
1969     assertNotConstant(t0)
1970     loadq [cfr, t0, 8], r0
1971     doReturn()
1972
1973
1974 _llint_throw_from_slow_path_trampoline:
1975     loadp Callee[cfr], t1
1976     andp MarkedBlockMask, t1
1977     loadp MarkedBlock::m_vm[t1], t1
1978     copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(t1, t2)
1979
1980     callSlowPath(_llint_slow_path_handle_exception)
1981
1982     # When throwing from the interpreter (i.e. throwing from LLIntSlowPaths), so
1983     # the throw target is not necessarily interpreted code, we come to here.
1984     # This essentially emulates the JIT's throwing protocol.
1985     loadp Callee[cfr], t1
1986     andp MarkedBlockMask, t1
1987     loadp MarkedBlock::m_vm[t1], t1
1988     jmp VM::targetMachinePCForThrow[t1]
1989
1990
1991 _llint_throw_during_call_trampoline:
1992     preserveReturnAddressAfterCall(t2)
1993     jmp _llint_throw_from_slow_path_trampoline
1994
1995
1996 macro nativeCallTrampoline(executableOffsetToFunction)
1997
1998     functionPrologue()
1999     storep 0, CodeBlock[cfr]
2000     loadp Callee[cfr], t0
2001     andp MarkedBlockMask, t0, t1
2002     loadp MarkedBlock::m_vm[t1], t1
2003     storep cfr, VM::topCallFrame[t1]
2004     if ARM64 or C_LOOP
2005         storep lr, ReturnPC[cfr]
2006     end
2007     move cfr, a0
2008     loadp Callee[cfr], t1
2009     loadp JSFunction::m_executable[t1], t1
2010     checkStackPointerAlignment(t3, 0xdead0001)
2011     if C_LOOP
2012         cloopCallNative executableOffsetToFunction[t1]
2013     else
2014         if X86_64_WIN
2015             subp 32, sp
2016         end
2017         call executableOffsetToFunction[t1]
2018         if X86_64_WIN
2019             addp 32, sp
2020         end
2021     end
2022     loadp Callee[cfr], t3
2023     andp MarkedBlockMask, t3
2024     loadp MarkedBlock::m_vm[t3], t3
2025
2026     functionEpilogue()
2027
2028     btqnz VM::m_exception[t3], .handleException
2029     ret
2030
2031 .handleException:
2032     storep cfr, VM::topCallFrame[t3]
2033     restoreStackPointerAfterCall()
2034     jmp _llint_throw_from_slow_path_trampoline
2035 end
2036
2037 macro getConstantScope(dst)
2038     loadpFromInstruction(6, t0)
2039     loadisFromInstruction(dst, t1)
2040     storeq t0, [cfr, t1, 8]
2041 end
2042
2043 macro varInjectionCheck(slowPath)
2044     loadp CodeBlock[cfr], t0
2045     loadp CodeBlock::m_globalObject[t0], t0
2046     loadp JSGlobalObject::m_varInjectionWatchpoint[t0], t0
2047     bbeq WatchpointSet::m_state[t0], IsInvalidated, slowPath
2048 end
2049
2050 macro resolveScope()
2051     loadisFromInstruction(5, t2)
2052     loadisFromInstruction(2, t0)
2053     loadp [cfr, t0, 8], t0
2054     btiz t2, .resolveScopeLoopEnd
2055
2056 .resolveScopeLoop:
2057     loadp JSScope::m_next[t0], t0
2058     subi 1, t2
2059     btinz t2, .resolveScopeLoop
2060
2061 .resolveScopeLoopEnd:
2062     loadisFromInstruction(1, t1)
2063     storeq t0, [cfr, t1, 8]
2064 end
2065
2066
2067 _llint_op_resolve_scope:
2068     traceExecution()
2069     loadisFromInstruction(4, t0)
2070
2071 #rGlobalProperty:
2072     bineq t0, GlobalProperty, .rGlobalVar
2073     getConstantScope(1)
2074     dispatch(7)
2075
2076 .rGlobalVar:
2077     bineq t0, GlobalVar, .rGlobalLexicalVar
2078     getConstantScope(1)
2079     dispatch(7)
2080
2081 .rGlobalLexicalVar:
2082     bineq t0, GlobalLexicalVar, .rClosureVar
2083     getConstantScope(1)
2084     dispatch(7)
2085
2086 .rClosureVar:
2087     bineq t0, ClosureVar, .rModuleVar
2088     resolveScope()
2089     dispatch(7)
2090
2091 .rModuleVar:
2092     bineq t0, ModuleVar, .rGlobalPropertyWithVarInjectionChecks
2093     getConstantScope(1)
2094     dispatch(7)
2095
2096 .rGlobalPropertyWithVarInjectionChecks:
2097     bineq t0, GlobalPropertyWithVarInjectionChecks, .rGlobalVarWithVarInjectionChecks
2098     varInjectionCheck(.rDynamic)
2099     getConstantScope(1)
2100     dispatch(7)
2101
2102 .rGlobalVarWithVarInjectionChecks:
2103     bineq t0, GlobalVarWithVarInjectionChecks, .rGlobalLexicalVarWithVarInjectionChecks
2104     varInjectionCheck(.rDynamic)
2105     getConstantScope(1)
2106     dispatch(7)
2107
2108 .rGlobalLexicalVarWithVarInjectionChecks:
2109     bineq t0, GlobalLexicalVarWithVarInjectionChecks, .rClosureVarWithVarInjectionChecks
2110     varInjectionCheck(.rDynamic)
2111     getConstantScope(1)
2112     dispatch(7)
2113
2114 .rClosureVarWithVarInjectionChecks:
2115     bineq t0, ClosureVarWithVarInjectionChecks, .rDynamic
2116     varInjectionCheck(.rDynamic)
2117     resolveScope()
2118     dispatch(7)
2119
2120 .rDynamic:
2121     callOpcodeSlowPath(_slow_path_resolve_scope)
2122     dispatch(7)
2123
2124
2125 macro loadWithStructureCheck(operand, slowPath)
2126     loadisFromInstruction(operand, t0)
2127     loadq [cfr, t0, 8], t0
2128     loadStructureWithScratch(t0, t2, t1)
2129     loadpFromInstruction(5, t1)
2130     bpneq t2, t1, slowPath
2131 end
2132
2133 macro getProperty()
2134     loadisFromInstruction(6, t1)
2135     loadPropertyAtVariableOffset(t1, t0, t2)
2136     valueProfile(t2, 7, t0)
2137     loadisFromInstruction(1, t0)
2138     storeq t2, [cfr, t0, 8]
2139 end
2140
2141 macro getGlobalVar(tdzCheckIfNecessary)
2142     loadpFromInstruction(6, t0)
2143     loadq [t0], t0
2144     tdzCheckIfNecessary(t0)
2145     valueProfile(t0, 7, t1)
2146     loadisFromInstruction(1, t1)
2147     storeq t0, [cfr, t1, 8]
2148 end
2149
2150 macro getClosureVar()
2151     loadisFromInstruction(6, t1)
2152     loadq JSEnvironmentRecord_variables[t0, t1, 8], t0
2153     valueProfile(t0, 7, t1)
2154     loadisFromInstruction(1, t1)
2155     storeq t0, [cfr, t1, 8]
2156 end
2157
2158 _llint_op_get_from_scope:
2159     traceExecution()
2160     loadisFromInstruction(4, t0)
2161     andi ResolveTypeMask, t0
2162
2163 #gGlobalProperty:
2164     bineq t0, GlobalProperty, .gGlobalVar
2165     loadWithStructureCheck(2, .gDynamic)
2166     getProperty()
2167     dispatch(8)
2168
2169 .gGlobalVar:
2170     bineq t0, GlobalVar, .gGlobalLexicalVar
2171     getGlobalVar(macro(v) end)
2172     dispatch(8)
2173
2174 .gGlobalLexicalVar:
2175     bineq t0, GlobalLexicalVar, .gClosureVar
2176     getGlobalVar(
2177         macro (value)
2178             bqeq value, ValueEmpty, .gDynamic
2179         end)
2180     dispatch(8)
2181
2182 .gClosureVar:
2183     bineq t0, ClosureVar, .gGlobalPropertyWithVarInjectionChecks
2184     loadVariable(2, t0)
2185     getClosureVar()
2186     dispatch(8)
2187
2188 .gGlobalPropertyWithVarInjectionChecks:
2189     bineq t0, GlobalPropertyWithVarInjectionChecks, .gGlobalVarWithVarInjectionChecks
2190     loadWithStructureCheck(2, .gDynamic)
2191     getProperty()
2192     dispatch(8)
2193
2194 .gGlobalVarWithVarInjectionChecks:
2195     bineq t0, GlobalVarWithVarInjectionChecks, .gGlobalLexicalVarWithVarInjectionChecks
2196     varInjectionCheck(.gDynamic)
2197     getGlobalVar(macro(v) end)
2198     dispatch(8)
2199
2200 .gGlobalLexicalVarWithVarInjectionChecks:
2201     bineq t0, GlobalLexicalVarWithVarInjectionChecks, .gClosureVarWithVarInjectionChecks
2202     varInjectionCheck(.gDynamic)
2203     getGlobalVar(
2204         macro (value)
2205             bqeq value, ValueEmpty, .gDynamic
2206         end)
2207     dispatch(8)
2208
2209 .gClosureVarWithVarInjectionChecks:
2210     bineq t0, ClosureVarWithVarInjectionChecks, .gDynamic
2211     varInjectionCheck(.gDynamic)
2212     loadVariable(2, t0)
2213     getClosureVar()
2214     dispatch(8)
2215
2216 .gDynamic:
2217     callOpcodeSlowPath(_llint_slow_path_get_from_scope)
2218     dispatch(8)
2219
2220
2221 macro putProperty()
2222     loadisFromInstruction(3, t1)
2223     loadConstantOrVariable(t1, t2)
2224     loadisFromInstruction(6, t1)
2225     storePropertyAtVariableOffset(t1, t0, t2)
2226 end
2227
2228 macro putGlobalVariable()
2229     loadisFromInstruction(3, t0)
2230     loadConstantOrVariable(t0, t1)
2231     loadpFromInstruction(5, t2)
2232     loadpFromInstruction(6, t0)
2233     notifyWrite(t2, .pDynamic)
2234     storeq t1, [t0]
2235 end
2236
2237 macro putClosureVar()
2238     loadisFromInstruction(3, t1)
2239     loadConstantOrVariable(t1, t2)
2240     loadisFromInstruction(6, t1)
2241     storeq t2, JSEnvironmentRecord_variables[t0, t1, 8]
2242 end
2243
2244 macro putLocalClosureVar()
2245     loadisFromInstruction(3, t1)
2246     loadConstantOrVariable(t1, t2)
2247     loadpFromInstruction(5, t3)
2248     btpz t3, .noVariableWatchpointSet
2249     notifyWrite(t3, .pDynamic)
2250 .noVariableWatchpointSet:
2251     loadisFromInstruction(6, t1)
2252     storeq t2, JSEnvironmentRecord_variables[t0, t1, 8]
2253 end
2254
2255 macro checkTDZInGlobalPutToScopeIfNecessary()
2256     loadisFromInstruction(4, t0)
2257     andi InitializationModeMask, t0
2258     rshifti InitializationModeShift, t0
2259     bineq t0, NotInitialization, .noNeedForTDZCheck
2260     loadpFromInstruction(6, t0)
2261     loadq [t0], t0
2262     bqeq t0, ValueEmpty, .pDynamic
2263 .noNeedForTDZCheck:
2264 end
2265
2266
2267 _llint_op_put_to_scope:
2268     traceExecution()
2269     loadisFromInstruction(4, t0)
2270     andi ResolveTypeMask, t0
2271
2272 #pLocalClosureVar:
2273     bineq t0, LocalClosureVar, .pGlobalProperty
2274     loadVariable(1, t0)
2275     putLocalClosureVar()
2276     writeBarrierOnOperands(1, 3)
2277     dispatch(7)
2278
2279 .pGlobalProperty:
2280     bineq t0, GlobalProperty, .pGlobalVar
2281     loadWithStructureCheck(1, .pDynamic)
2282     putProperty()
2283     writeBarrierOnOperands(1, 3)
2284     dispatch(7)
2285
2286 .pGlobalVar:
2287     bineq t0, GlobalVar, .pGlobalLexicalVar
2288     writeBarrierOnGlobalObject(3)
2289     putGlobalVariable()
2290     dispatch(7)
2291
2292 .pGlobalLexicalVar:
2293     bineq t0, GlobalLexicalVar, .pClosureVar
2294     writeBarrierOnGlobalLexicalEnvironment(3)
2295     checkTDZInGlobalPutToScopeIfNecessary()
2296     putGlobalVariable()
2297     dispatch(7)
2298
2299 .pClosureVar:
2300     bineq t0, ClosureVar, .pGlobalPropertyWithVarInjectionChecks
2301     loadVariable(1, t0)
2302     putClosureVar()
2303     writeBarrierOnOperands(1, 3)
2304     dispatch(7)
2305
2306 .pGlobalPropertyWithVarInjectionChecks:
2307     bineq t0, GlobalPropertyWithVarInjectionChecks, .pGlobalVarWithVarInjectionChecks
2308     loadWithStructureCheck(1, .pDynamic)
2309     putProperty()
2310     writeBarrierOnOperands(1, 3)
2311     dispatch(7)
2312
2313 .pGlobalVarWithVarInjectionChecks:
2314     bineq t0, GlobalVarWithVarInjectionChecks, .pGlobalLexicalVarWithVarInjectionChecks
2315     writeBarrierOnGlobalObject(3)
2316     varInjectionCheck(.pDynamic)
2317     putGlobalVariable()
2318     dispatch(7)
2319
2320 .pGlobalLexicalVarWithVarInjectionChecks:
2321     bineq t0, GlobalLexicalVarWithVarInjectionChecks, .pClosureVarWithVarInjectionChecks
2322     writeBarrierOnGlobalLexicalEnvironment(3)
2323     varInjectionCheck(.pDynamic)
2324     checkTDZInGlobalPutToScopeIfNecessary()
2325     putGlobalVariable()
2326     dispatch(7)
2327
2328 .pClosureVarWithVarInjectionChecks:
2329     bineq t0, ClosureVarWithVarInjectionChecks, .pModuleVar
2330     varInjectionCheck(.pDynamic)
2331     loadVariable(1, t0)
2332     putClosureVar()
2333     writeBarrierOnOperands(1, 3)
2334     dispatch(7)
2335
2336 .pModuleVar:
2337     bineq t0, ModuleVar, .pDynamic
2338     callOpcodeSlowPath(_slow_path_throw_strict_mode_readonly_property_write_error)
2339     dispatch(7)
2340
2341 .pDynamic:
2342     callOpcodeSlowPath(_llint_slow_path_put_to_scope)
2343     dispatch(7)
2344
2345
2346 _llint_op_get_from_arguments:
2347     traceExecution()
2348     loadVariable(2, t0)
2349     loadi 24[PB, PC, 8], t1
2350     loadq DirectArguments_storage[t0, t1, 8], t0
2351     valueProfile(t0, 4, t1)
2352     loadisFromInstruction(1, t1)
2353     storeq t0, [cfr, t1, 8]
2354     dispatch(5)
2355
2356
2357 _llint_op_put_to_arguments:
2358     traceExecution()
2359     loadVariable(1, t0)
2360     loadi 16[PB, PC, 8], t1
2361     loadisFromInstruction(3, t3)
2362     loadConstantOrVariable(t3, t2)
2363     storeq t2, DirectArguments_storage[t0, t1, 8]
2364     writeBarrierOnOperands(1, 3)
2365     dispatch(4)
2366
2367
2368 _llint_op_get_parent_scope:
2369     traceExecution()
2370     loadVariable(2, t0)
2371     loadp JSScope::m_next[t0], t0
2372     loadisFromInstruction(1, t1)
2373     storeq t0, [cfr, t1, 8]
2374     dispatch(3)
2375
2376
2377 _llint_op_profile_type:
2378     traceExecution()
2379     loadp CodeBlock[cfr], t1
2380     loadp CodeBlock::m_vm[t1], t1
2381     # t1 is holding the pointer to the typeProfilerLog.
2382     loadp VM::m_typeProfilerLog[t1], t1
2383     # t2 is holding the pointer to the current log entry.
2384     loadp TypeProfilerLog::m_currentLogEntryPtr[t1], t2
2385
2386     # t0 is holding the JSValue argument.
2387     loadisFromInstruction(1, t3)
2388     loadConstantOrVariable(t3, t0)
2389
2390     bqeq t0, ValueEmpty, .opProfileTypeDone
2391     # Store the JSValue onto the log entry.
2392     storeq t0, TypeProfilerLog::LogEntry::value[t2]
2393     
2394     # Store the TypeLocation onto the log entry.
2395     loadpFromInstruction(2, t3)
2396     storep t3, TypeProfilerLog::LogEntry::location[t2]
2397
2398     btqz t0, tagMask, .opProfileTypeIsCell
2399     storei 0, TypeProfilerLog::LogEntry::structureID[t2]
2400     jmp .opProfileTypeSkipIsCell
2401 .opProfileTypeIsCell:
2402     loadi JSCell::m_structureID[t0], t3
2403     storei t3, TypeProfilerLog::LogEntry::structureID[t2]
2404 .opProfileTypeSkipIsCell:
2405     
2406     # Increment the current log entry.
2407     addp sizeof TypeProfilerLog::LogEntry, t2
2408     storep t2, TypeProfilerLog::m_currentLogEntryPtr[t1]
2409
2410     loadp TypeProfilerLog::m_logEndPtr[t1], t1
2411     bpneq t2, t1, .opProfileTypeDone
2412     callOpcodeSlowPath(_slow_path_profile_type_clear_log)
2413
2414 .opProfileTypeDone:
2415     dispatch(6)
2416
2417 _llint_op_profile_control_flow:
2418     traceExecution()
2419     loadpFromInstruction(1, t0)
2420     addq 1, BasicBlockLocation::m_executionCount[t0]
2421     dispatch(2)
2422
2423
2424 _llint_op_get_rest_length:
2425     traceExecution()
2426     loadi PayloadOffset + ArgumentCount[cfr], t0
2427     subi 1, t0
2428     loadisFromInstruction(2, t1)
2429     bilteq t0, t1, .storeZero
2430     subi t1, t0
2431     jmp .boxUp
2432 .storeZero:
2433     move 0, t0
2434 .boxUp:
2435     orq tagTypeNumber, t0
2436     loadisFromInstruction(1, t1)
2437     storeq t0, [cfr, t1, 8]
2438     dispatch(3)
2439
2440
2441 _llint_op_log_shadow_chicken_prologue:
2442     traceExecution()
2443     acquireShadowChickenPacket(.opLogShadowChickenPrologueSlow)
2444     storep cfr, ShadowChicken::Packet::frame[t0]
2445     loadp CallerFrame[cfr], t1
2446     storep t1, ShadowChicken::Packet::callerFrame[t0]
2447     loadp Callee[cfr], t1
2448     storep t1, ShadowChicken::Packet::callee[t0]
2449     loadVariable(1, t1)
2450     storep t1, ShadowChicken::Packet::scope[t0]
2451     dispatch(2)
2452 .opLogShadowChickenPrologueSlow:
2453     callOpcodeSlowPath(_llint_slow_path_log_shadow_chicken_prologue)
2454     dispatch(2)
2455
2456
2457 _llint_op_log_shadow_chicken_tail:
2458     traceExecution()
2459     acquireShadowChickenPacket(.opLogShadowChickenTailSlow)
2460     storep cfr, ShadowChicken::Packet::frame[t0]
2461     storep ShadowChickenTailMarker, ShadowChicken::Packet::callee[t0]
2462     loadVariable(1, t1)
2463     storep t1, ShadowChicken::Packet::thisValue[t0]
2464     loadVariable(2, t1)
2465     storep t1, ShadowChicken::Packet::scope[t0]
2466     loadp CodeBlock[cfr], t1
2467     storep t1, ShadowChicken::Packet::codeBlock[t0]
2468     storei PC, ShadowChicken::Packet::callSiteIndex[t0]
2469     dispatch(3)
2470 .opLogShadowChickenTailSlow:
2471     callOpcodeSlowPath(_llint_slow_path_log_shadow_chicken_tail)
2472     dispatch(3)