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