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