Unreviewed, rolling out r218869.
[WebKit-https.git] / Source / JavaScriptCore / llint / LowLevelInterpreter32_64.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 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
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
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 callTrapHandler(throwHandler)
381     storei PC, ArgumentCount + TagOffset[cfr]
382     move cfr, a0
383     move PC, a1
384     cCall2(_llint_slow_path_handle_traps)
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     move t1, t0
617     lshiftp 3, t0
618     addp t0, cfr
619     addp t0, sp
620 .copyLoop:
621     loadi PayloadOffset[t3], t0
622     storei t0, PayloadOffset[t3, t1, 8]
623     loadi TagOffset[t3], t0
624     storei t0, TagOffset[t3, t1, 8]
625     addp 8, t3
626     bsubinz 1, t2, .copyLoop
627
628     // Fill new slots with JSUndefined
629     move t1, t2
630 .fillLoop:
631     move 0, t0
632     storei t0, PayloadOffset[t3, t1, 8]
633     move UndefinedTag, t0
634     storei t0, TagOffset[t3, t1, 8]
635     addp 8, t3
636     baddinz 1, t2, .fillLoop
637
638 .continue:
639     # Reload CodeBlock and PC, since the slow_path clobbered it.
640     loadp CodeBlock[cfr], t1
641     loadp CodeBlock::m_instructions[t1], PC
642     jmp doneLabel
643 end
644
645 macro branchIfException(label)
646     loadp Callee + PayloadOffset[cfr], t3
647     andp MarkedBlockMask, t3
648     loadp MarkedBlock::m_vm[t3], t3
649     btiz VM::m_exception[t3], .noException
650     jmp label
651 .noException:
652 end
653
654
655 # Instruction implementations
656
657 _llint_op_enter:
658     traceExecution()
659     checkStackPointerAlignment(t2, 0xdead00e1)
660     loadp CodeBlock[cfr], t2                // t2<CodeBlock> = cfr.CodeBlock
661     loadi CodeBlock::m_numVars[t2], t2      // t2<size_t> = t2<CodeBlock>.m_numVars
662     btiz t2, .opEnterDone
663     move UndefinedTag, t0
664     move 0, t1
665     negi t2
666 .opEnterLoop:
667     storei t0, TagOffset[cfr, t2, 8]
668     storei t1, PayloadOffset[cfr, t2, 8]
669     addi 1, t2
670     btinz t2, .opEnterLoop
671 .opEnterDone:
672     callOpcodeSlowPath(_slow_path_enter)
673     dispatch(1)
674
675
676 _llint_op_get_argument:
677     traceExecution()
678     loadisFromInstruction(1, t1)
679     loadisFromInstruction(2, t2)
680     loadi PayloadOffset + ArgumentCount[cfr], t0
681     bilteq t0, t2, .opGetArgumentOutOfBounds
682     loadi ThisArgumentOffset + TagOffset[cfr, t2, 8], t0
683     loadi ThisArgumentOffset + PayloadOffset[cfr, t2, 8], t3
684     storei t0, TagOffset[cfr, t1, 8]
685     storei t3, PayloadOffset[cfr, t1, 8]
686     valueProfile(t0, t3, 12, t1)
687     dispatch(4)
688
689 .opGetArgumentOutOfBounds:
690     storei UndefinedTag, TagOffset[cfr, t1, 8]
691     storei 0, PayloadOffset[cfr, t1, 8]
692     valueProfile(UndefinedTag, 0, 12, t1)
693     dispatch(4)
694
695
696 _llint_op_argument_count:
697     traceExecution()
698     loadisFromInstruction(1, t2)
699     loadi PayloadOffset + ArgumentCount[cfr], t0
700     subi 1, t0
701     move Int32Tag, t1
702     storei t1, TagOffset[cfr, t2, 8]
703     storei t0, PayloadOffset[cfr, t2, 8]
704     dispatch(2)
705
706
707 _llint_op_get_scope:
708     traceExecution()
709     loadi Callee + PayloadOffset[cfr], t0
710     loadi JSCallee::m_scope[t0], t0
711     loadisFromInstruction(1, t1)
712     storei CellTag, TagOffset[cfr, t1, 8]
713     storei t0, PayloadOffset[cfr, t1, 8]
714     dispatch(2)
715
716
717 _llint_op_to_this:
718     traceExecution()
719     loadi 4[PC], t0
720     bineq TagOffset[cfr, t0, 8], CellTag, .opToThisSlow
721     loadi PayloadOffset[cfr, t0, 8], t0
722     bbneq JSCell::m_type[t0], FinalObjectType, .opToThisSlow
723     loadpFromInstruction(2, t2)
724     bpneq JSCell::m_structureID[t0], t2, .opToThisSlow
725     dispatch(4)
726
727 .opToThisSlow:
728     callOpcodeSlowPath(_slow_path_to_this)
729     dispatch(4)
730
731
732 _llint_op_check_tdz:
733     traceExecution()
734     loadisFromInstruction(1, t0)
735     loadConstantOrVariableTag(t0, t1)
736     bineq t1, EmptyValueTag, .opNotTDZ
737     callOpcodeSlowPath(_slow_path_throw_tdz_error)
738
739 .opNotTDZ:
740     dispatch(2)
741
742
743 _llint_op_mov:
744     traceExecution()
745     loadi 8[PC], t1
746     loadi 4[PC], t0
747     loadConstantOrVariable(t1, t2, t3)
748     storei t2, TagOffset[cfr, t0, 8]
749     storei t3, PayloadOffset[cfr, t0, 8]
750     dispatch(3)
751
752
753 _llint_op_not:
754     traceExecution()
755     loadi 8[PC], t0
756     loadi 4[PC], t1
757     loadConstantOrVariable(t0, t2, t3)
758     bineq t2, BooleanTag, .opNotSlow
759     xori 1, t3
760     storei t2, TagOffset[cfr, t1, 8]
761     storei t3, PayloadOffset[cfr, t1, 8]
762     dispatch(3)
763
764 .opNotSlow:
765     callOpcodeSlowPath(_slow_path_not)
766     dispatch(3)
767
768
769 _llint_op_eq:
770     traceExecution()
771     loadi 12[PC], t2
772     loadi 8[PC], t0
773     loadConstantOrVariable(t2, t3, t1)
774     loadConstantOrVariable2Reg(t0, t2, t0)
775     bineq t2, t3, .opEqSlow
776     bieq t2, CellTag, .opEqSlow
777     bib t2, LowestTag, .opEqSlow
778     loadi 4[PC], t2
779     cieq t0, t1, t0
780     storei BooleanTag, TagOffset[cfr, t2, 8]
781     storei t0, PayloadOffset[cfr, t2, 8]
782     dispatch(4)
783
784 .opEqSlow:
785     callOpcodeSlowPath(_slow_path_eq)
786     dispatch(4)
787
788
789 _llint_op_eq_null:
790     traceExecution()
791     loadi 8[PC], t0
792     loadi 4[PC], t3
793     assertNotConstant(t0)
794     loadi TagOffset[cfr, t0, 8], t1
795     loadi PayloadOffset[cfr, t0, 8], t0
796     bineq t1, CellTag, .opEqNullImmediate
797     btbnz JSCell::m_flags[t0], MasqueradesAsUndefined, .opEqNullMasqueradesAsUndefined
798     move 0, t1
799     jmp .opEqNullNotImmediate
800 .opEqNullMasqueradesAsUndefined:
801     loadp JSCell::m_structureID[t0], t1
802     loadp CodeBlock[cfr], t0
803     loadp CodeBlock::m_globalObject[t0], t0
804     cpeq Structure::m_globalObject[t1], t0, t1
805     jmp .opEqNullNotImmediate
806 .opEqNullImmediate:
807     cieq t1, NullTag, t2
808     cieq t1, UndefinedTag, t1
809     ori t2, t1
810 .opEqNullNotImmediate:
811     storei BooleanTag, TagOffset[cfr, t3, 8]
812     storei t1, PayloadOffset[cfr, t3, 8]
813     dispatch(3)
814
815
816 _llint_op_neq:
817     traceExecution()
818     loadi 12[PC], t2
819     loadi 8[PC], t0
820     loadConstantOrVariable(t2, t3, t1)
821     loadConstantOrVariable2Reg(t0, t2, t0)
822     bineq t2, t3, .opNeqSlow
823     bieq t2, CellTag, .opNeqSlow
824     bib t2, LowestTag, .opNeqSlow
825     loadi 4[PC], t2
826     cineq t0, t1, t0
827     storei BooleanTag, TagOffset[cfr, t2, 8]
828     storei t0, PayloadOffset[cfr, t2, 8]
829     dispatch(4)
830
831 .opNeqSlow:
832     callOpcodeSlowPath(_slow_path_neq)
833     dispatch(4)
834     
835
836 _llint_op_neq_null:
837     traceExecution()
838     loadi 8[PC], t0
839     loadi 4[PC], t3
840     assertNotConstant(t0)
841     loadi TagOffset[cfr, t0, 8], t1
842     loadi PayloadOffset[cfr, t0, 8], t0
843     bineq t1, CellTag, .opNeqNullImmediate
844     btbnz JSCell::m_flags[t0], MasqueradesAsUndefined, .opNeqNullMasqueradesAsUndefined
845     move 1, t1
846     jmp .opNeqNullNotImmediate
847 .opNeqNullMasqueradesAsUndefined:
848     loadp JSCell::m_structureID[t0], t1
849     loadp CodeBlock[cfr], t0
850     loadp CodeBlock::m_globalObject[t0], t0
851     cpneq Structure::m_globalObject[t1], t0, t1
852     jmp .opNeqNullNotImmediate
853 .opNeqNullImmediate:
854     cineq t1, NullTag, t2
855     cineq t1, UndefinedTag, t1
856     andi t2, t1
857 .opNeqNullNotImmediate:
858     storei BooleanTag, TagOffset[cfr, t3, 8]
859     storei t1, PayloadOffset[cfr, t3, 8]
860     dispatch(3)
861
862
863 macro strictEq(equalityOperation, slowPath)
864     loadi 12[PC], t2
865     loadi 8[PC], t0
866     loadConstantOrVariable(t2, t3, t1)
867     loadConstantOrVariable2Reg(t0, t2, t0)
868     bineq t2, t3, .slow
869     bib t2, LowestTag, .slow
870     bineq t2, CellTag, .notStringOrSymbol
871     bbaeq JSCell::m_type[t0], ObjectType, .notStringOrSymbol
872     bbb JSCell::m_type[t1], ObjectType, .slow
873 .notStringOrSymbol:
874     loadi 4[PC], t2
875     equalityOperation(t0, t1, t0)
876     storei BooleanTag, TagOffset[cfr, t2, 8]
877     storei t0, PayloadOffset[cfr, t2, 8]
878     dispatch(4)
879
880 .slow:
881     callOpcodeSlowPath(slowPath)
882     dispatch(4)
883 end
884
885 _llint_op_stricteq:
886     traceExecution()
887     strictEq(macro (left, right, result) cieq left, right, result end, _slow_path_stricteq)
888
889
890 _llint_op_nstricteq:
891     traceExecution()
892     strictEq(macro (left, right, result) cineq left, right, result end, _slow_path_nstricteq)
893
894
895 _llint_op_inc:
896     traceExecution()
897     loadi 4[PC], t0
898     bineq TagOffset[cfr, t0, 8], Int32Tag, .opIncSlow
899     loadi PayloadOffset[cfr, t0, 8], t1
900     baddio 1, t1, .opIncSlow
901     storei t1, PayloadOffset[cfr, t0, 8]
902     dispatch(2)
903
904 .opIncSlow:
905     callOpcodeSlowPath(_slow_path_inc)
906     dispatch(2)
907
908
909 _llint_op_dec:
910     traceExecution()
911     loadi 4[PC], t0
912     bineq TagOffset[cfr, t0, 8], Int32Tag, .opDecSlow
913     loadi PayloadOffset[cfr, t0, 8], t1
914     bsubio 1, t1, .opDecSlow
915     storei t1, PayloadOffset[cfr, t0, 8]
916     dispatch(2)
917
918 .opDecSlow:
919     callOpcodeSlowPath(_slow_path_dec)
920     dispatch(2)
921
922
923 _llint_op_to_number:
924     traceExecution()
925     loadi 8[PC], t0
926     loadi 4[PC], t1
927     loadConstantOrVariable(t0, t2, t3)
928     bieq t2, Int32Tag, .opToNumberIsInt
929     biaeq t2, LowestTag, .opToNumberSlow
930 .opToNumberIsInt:
931     storei t2, TagOffset[cfr, t1, 8]
932     storei t3, PayloadOffset[cfr, t1, 8]
933     valueProfile(t2, t3, 12, t1)
934     dispatch(4)
935
936 .opToNumberSlow:
937     callOpcodeSlowPath(_slow_path_to_number)
938     dispatch(4)
939
940
941 _llint_op_to_string:
942     traceExecution()
943     loadi 8[PC], t0
944     loadi 4[PC], t1
945     loadConstantOrVariable(t0, t2, t3)
946     bineq t2, CellTag, .opToStringSlow
947     bbneq JSCell::m_type[t3], StringType, .opToStringSlow
948 .opToStringIsString:
949     storei t2, TagOffset[cfr, t1, 8]
950     storei t3, PayloadOffset[cfr, t1, 8]
951     dispatch(3)
952
953 .opToStringSlow:
954     callOpcodeSlowPath(_slow_path_to_string)
955     dispatch(3)
956
957
958 _llint_op_negate:
959     traceExecution()
960     loadi 8[PC], t0
961     loadi 4[PC], t3
962     loadConstantOrVariable(t0, t1, t2)
963     loadisFromInstruction(3, t0)
964     bineq t1, Int32Tag, .opNegateSrcNotInt
965     btiz t2, 0x7fffffff, .opNegateSlow
966     negi t2
967     ori ArithProfileInt, t0
968     storei Int32Tag, TagOffset[cfr, t3, 8]
969     storeisToInstruction(t0, 3)
970     storei t2, PayloadOffset[cfr, t3, 8]
971     dispatch(4)
972 .opNegateSrcNotInt:
973     bia t1, LowestTag, .opNegateSlow
974     xori 0x80000000, t1
975     ori ArithProfileNumber, t0
976     storei t2, PayloadOffset[cfr, t3, 8]
977     storeisToInstruction(t0, 3)
978     storei t1, TagOffset[cfr, t3, 8]
979     dispatch(4)
980
981 .opNegateSlow:
982     callOpcodeSlowPath(_slow_path_negate)
983     dispatch(4)
984
985
986 macro binaryOpCustomStore(integerOperationAndStore, doubleOperation, slowPath)
987     loadi 12[PC], t2
988     loadi 8[PC], t0
989     loadConstantOrVariable(t2, t3, t1)
990     loadConstantOrVariable2Reg(t0, t2, t0)
991     bineq t2, Int32Tag, .op1NotInt
992     bineq t3, Int32Tag, .op2NotInt
993     loadisFromInstruction(4, t5)
994     ori ArithProfileIntInt, t5
995     storeisToInstruction(t5, 4)
996     loadi 4[PC], t2
997     integerOperationAndStore(t3, t1, t0, .slow, t2)
998     dispatch(5)
999
1000 .op1NotInt:
1001     # First operand is definitely not an int, the second operand could be anything.
1002     bia t2, LowestTag, .slow
1003     bib t3, LowestTag, .op1NotIntOp2Double
1004     bineq t3, Int32Tag, .slow
1005     loadisFromInstruction(4, t5)
1006     ori ArithProfileNumberInt, t5
1007     storeisToInstruction(t5, 4)
1008     ci2d t1, ft1
1009     jmp .op1NotIntReady
1010 .op1NotIntOp2Double:
1011     fii2d t1, t3, ft1
1012     loadisFromInstruction(4, t5)
1013     ori ArithProfileNumberNumber, t5
1014     storeisToInstruction(t5, 4)
1015 .op1NotIntReady:
1016     loadi 4[PC], t1
1017     fii2d t0, t2, ft0
1018     doubleOperation(ft1, ft0)
1019     stored ft0, [cfr, t1, 8]
1020     dispatch(5)
1021
1022 .op2NotInt:
1023     # First operand is definitely an int, the second operand is definitely not.
1024     loadi 4[PC], t2
1025     bia t3, LowestTag, .slow
1026     loadisFromInstruction(4, t5)
1027     ori ArithProfileIntNumber, t5
1028     storeisToInstruction(t5, 4)
1029     ci2d t0, ft0
1030     fii2d t1, t3, ft1
1031     doubleOperation(ft1, ft0)
1032     stored ft0, [cfr, t2, 8]
1033     dispatch(5)
1034
1035 .slow:
1036     callOpcodeSlowPath(slowPath)
1037     dispatch(5)
1038 end
1039
1040 macro binaryOp(integerOperation, doubleOperation, slowPath)
1041     binaryOpCustomStore(
1042         macro (int32Tag, left, right, slow, index)
1043             integerOperation(left, right, slow)
1044             storei int32Tag, TagOffset[cfr, index, 8]
1045             storei right, PayloadOffset[cfr, index, 8]
1046         end,
1047         doubleOperation, slowPath)
1048 end
1049
1050 _llint_op_add:
1051     traceExecution()
1052     binaryOp(
1053         macro (left, right, slow) baddio left, right, slow end,
1054         macro (left, right) addd left, right end,
1055         _slow_path_add)
1056
1057
1058 _llint_op_mul:
1059     traceExecution()
1060     binaryOpCustomStore(
1061         macro (int32Tag, left, right, slow, index)
1062             const scratch = int32Tag   # We know that we can reuse the int32Tag register since it has a constant.
1063             move right, scratch
1064             bmulio left, scratch, slow
1065             btinz scratch, .done
1066             bilt left, 0, slow
1067             bilt right, 0, slow
1068         .done:
1069             storei Int32Tag, TagOffset[cfr, index, 8]
1070             storei scratch, PayloadOffset[cfr, index, 8]
1071         end,
1072         macro (left, right) muld left, right end,
1073         _slow_path_mul)
1074
1075
1076 _llint_op_sub:
1077     traceExecution()
1078     binaryOp(
1079         macro (left, right, slow) bsubio left, right, slow end,
1080         macro (left, right) subd left, right end,
1081         _slow_path_sub)
1082
1083
1084 _llint_op_div:
1085     traceExecution()
1086     binaryOpCustomStore(
1087         macro (int32Tag, left, right, slow, index)
1088             ci2d left, ft0
1089             ci2d right, ft1
1090             divd ft0, ft1
1091             bcd2i ft1, right, .notInt
1092             storei int32Tag, TagOffset[cfr, index, 8]
1093             storei right, PayloadOffset[cfr, index, 8]
1094             jmp .done
1095         .notInt:
1096             stored ft1, [cfr, index, 8]
1097         .done:
1098         end,
1099         macro (left, right) divd left, right end,
1100         _slow_path_div)
1101
1102
1103 macro bitOp(operation, slowPath, advance)
1104     loadi 12[PC], t2
1105     loadi 8[PC], t0
1106     loadConstantOrVariable(t2, t3, t1)
1107     loadConstantOrVariable2Reg(t0, t2, t0)
1108     bineq t3, Int32Tag, .slow
1109     bineq t2, Int32Tag, .slow
1110     loadi 4[PC], t2
1111     operation(t1, t0)
1112     storei t3, TagOffset[cfr, t2, 8]
1113     storei t0, PayloadOffset[cfr, t2, 8]
1114     dispatch(advance)
1115
1116 .slow:
1117     callOpcodeSlowPath(slowPath)
1118     dispatch(advance)
1119 end
1120
1121 _llint_op_lshift:
1122     traceExecution()
1123     bitOp(
1124         macro (left, right) lshifti left, right end,
1125         _slow_path_lshift,
1126         4)
1127
1128
1129 _llint_op_rshift:
1130     traceExecution()
1131     bitOp(
1132         macro (left, right) rshifti left, right end,
1133         _slow_path_rshift,
1134         4)
1135
1136
1137 _llint_op_urshift:
1138     traceExecution()
1139     bitOp(
1140         macro (left, right) urshifti left, right end,
1141         _slow_path_urshift,
1142         4)
1143
1144
1145 _llint_op_unsigned:
1146     traceExecution()
1147     loadi 4[PC], t0
1148     loadi 8[PC], t1
1149     loadConstantOrVariablePayload(t1, Int32Tag, t2, .opUnsignedSlow)
1150     bilt t2, 0, .opUnsignedSlow
1151     storei t2, PayloadOffset[cfr, t0, 8]
1152     storei Int32Tag, TagOffset[cfr, t0, 8]
1153     dispatch(3)
1154 .opUnsignedSlow:
1155     callOpcodeSlowPath(_slow_path_unsigned)
1156     dispatch(3)
1157
1158
1159 _llint_op_bitand:
1160     traceExecution()
1161     bitOp(
1162         macro (left, right) andi left, right end,
1163         _slow_path_bitand,
1164         5)
1165
1166
1167 _llint_op_bitxor:
1168     traceExecution()
1169     bitOp(
1170         macro (left, right) xori left, right end,
1171         _slow_path_bitxor,
1172         5)
1173
1174
1175 _llint_op_bitor:
1176     traceExecution()
1177     bitOp(
1178         macro (left, right) ori left, right end,
1179         _slow_path_bitor,
1180         5)
1181
1182
1183 _llint_op_overrides_has_instance:
1184     traceExecution()
1185
1186     loadisFromInstruction(1, t3)
1187     storei BooleanTag, TagOffset[cfr, t3, 8]
1188
1189     # First check if hasInstanceValue is the one on Function.prototype[Symbol.hasInstance]
1190     loadisFromInstruction(3, t0)
1191     loadConstantOrVariablePayload(t0, CellTag, t2, .opOverrideshasInstanceValueNotCell)
1192     loadConstantOrVariable(t0, t1, t2)
1193     bineq t1, CellTag, .opOverrideshasInstanceValueNotCell
1194
1195     # We don't need hasInstanceValue's tag register anymore.
1196     loadp CodeBlock[cfr], t1
1197     loadp CodeBlock::m_globalObject[t1], t1
1198     loadp JSGlobalObject::m_functionProtoHasInstanceSymbolFunction[t1], t1
1199     bineq t1, t2, .opOverrideshasInstanceValueNotDefault
1200
1201     # We know the constructor is a cell.
1202     loadisFromInstruction(2, t0)
1203     loadConstantOrVariablePayloadUnchecked(t0, t1)
1204     tbz JSCell::m_flags[t1], ImplementsDefaultHasInstance, t0
1205     storei t0, PayloadOffset[cfr, t3, 8]
1206     dispatch(4)
1207
1208 .opOverrideshasInstanceValueNotCell:
1209 .opOverrideshasInstanceValueNotDefault:
1210     storei 1, PayloadOffset[cfr, t3, 8]
1211     dispatch(4)
1212
1213 _llint_op_instanceof_custom:
1214     traceExecution()
1215     callOpcodeSlowPath(_llint_slow_path_instanceof_custom)
1216     dispatch(5)
1217
1218
1219 _llint_op_is_empty:
1220     traceExecution()
1221     loadi 8[PC], t1
1222     loadi 4[PC], t0
1223     loadConstantOrVariable(t1, t2, t3)
1224     cieq t2, EmptyValueTag, t3
1225     storei BooleanTag, TagOffset[cfr, t0, 8]
1226     storei t3, PayloadOffset[cfr, t0, 8]
1227     dispatch(3)
1228
1229
1230 _llint_op_is_undefined:
1231     traceExecution()
1232     loadi 8[PC], t1
1233     loadi 4[PC], t0
1234     loadConstantOrVariable(t1, t2, t3)
1235     storei BooleanTag, TagOffset[cfr, t0, 8]
1236     bieq t2, CellTag, .opIsUndefinedCell
1237     cieq t2, UndefinedTag, t3
1238     storei t3, PayloadOffset[cfr, t0, 8]
1239     dispatch(3)
1240 .opIsUndefinedCell:
1241     btbnz JSCell::m_flags[t3], MasqueradesAsUndefined, .opIsUndefinedMasqueradesAsUndefined
1242     move 0, t1
1243     storei t1, PayloadOffset[cfr, t0, 8]
1244     dispatch(3)
1245 .opIsUndefinedMasqueradesAsUndefined:
1246     loadp JSCell::m_structureID[t3], t1
1247     loadp CodeBlock[cfr], t3
1248     loadp CodeBlock::m_globalObject[t3], t3
1249     cpeq Structure::m_globalObject[t1], t3, t1
1250     storei t1, PayloadOffset[cfr, t0, 8]
1251     dispatch(3)
1252
1253
1254 _llint_op_is_boolean:
1255     traceExecution()
1256     loadi 8[PC], t1
1257     loadi 4[PC], t2
1258     loadConstantOrVariableTag(t1, t0)
1259     cieq t0, BooleanTag, t0
1260     storei BooleanTag, TagOffset[cfr, t2, 8]
1261     storei t0, PayloadOffset[cfr, t2, 8]
1262     dispatch(3)
1263
1264
1265 _llint_op_is_number:
1266     traceExecution()
1267     loadi 8[PC], t1
1268     loadi 4[PC], t2
1269     loadConstantOrVariableTag(t1, t0)
1270     storei BooleanTag, TagOffset[cfr, t2, 8]
1271     addi 1, t0
1272     cib t0, LowestTag + 1, t1
1273     storei t1, PayloadOffset[cfr, t2, 8]
1274     dispatch(3)
1275
1276
1277 _llint_op_is_cell_with_type:
1278     traceExecution()
1279     loadi 8[PC], t1
1280     loadi 4[PC], t2
1281     loadConstantOrVariable(t1, t0, t3)
1282     storei BooleanTag, TagOffset[cfr, t2, 8]
1283     bineq t0, CellTag, .notCellCase
1284     loadi 12[PC], t0
1285     cbeq JSCell::m_type[t3], t0, t1
1286     storei t1, PayloadOffset[cfr, t2, 8]
1287     dispatch(4)
1288 .notCellCase:
1289     storep 0, PayloadOffset[cfr, t2, 8]
1290     dispatch(4)
1291
1292
1293 _llint_op_is_object:
1294     traceExecution()
1295     loadi 8[PC], t1
1296     loadi 4[PC], t2
1297     loadConstantOrVariable(t1, t0, t3)
1298     storei BooleanTag, TagOffset[cfr, t2, 8]
1299     bineq t0, CellTag, .opIsObjectNotCell
1300     cbaeq JSCell::m_type[t3], ObjectType, t1
1301     storei t1, PayloadOffset[cfr, t2, 8]
1302     dispatch(3)
1303 .opIsObjectNotCell:
1304     storep 0, PayloadOffset[cfr, t2, 8]
1305     dispatch(3)
1306
1307
1308 macro loadPropertyAtVariableOffsetKnownNotInline(propertyOffset, objectAndStorage, tag, payload)
1309     assert(macro (ok) bigteq propertyOffset, firstOutOfLineOffset, ok end)
1310     negi propertyOffset
1311     loadp JSObject::m_butterfly[objectAndStorage], objectAndStorage
1312     loadi TagOffset + (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffset, 8], tag
1313     loadi PayloadOffset + (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffset, 8], payload
1314 end
1315
1316 macro loadPropertyAtVariableOffset(propertyOffset, objectAndStorage, tag, payload)
1317     bilt propertyOffset, firstOutOfLineOffset, .isInline
1318     loadp JSObject::m_butterfly[objectAndStorage], objectAndStorage
1319     negi propertyOffset
1320     jmp .ready
1321 .isInline:
1322     addp sizeof JSObject - (firstOutOfLineOffset - 2) * 8, objectAndStorage
1323 .ready:
1324     loadi TagOffset + (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffset, 8], tag
1325     loadi PayloadOffset + (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffset, 8], payload
1326 end
1327
1328 macro storePropertyAtVariableOffset(propertyOffsetAsInt, objectAndStorage, tag, payload)
1329     bilt propertyOffsetAsInt, firstOutOfLineOffset, .isInline
1330     loadp JSObject::m_butterfly[objectAndStorage], objectAndStorage
1331     negi propertyOffsetAsInt
1332     jmp .ready
1333 .isInline:
1334     addp sizeof JSObject - (firstOutOfLineOffset - 2) * 8, objectAndStorage
1335 .ready:
1336     storei tag, TagOffset + (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffsetAsInt, 8]
1337     storei payload, PayloadOffset + (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffsetAsInt, 8]
1338 end
1339
1340
1341 # We only do monomorphic get_by_id caching for now, and we do not modify the
1342 # opcode for own properties. We also allow for the cache to change anytime it fails,
1343 # since ping-ponging is free. At best we get lucky and the get_by_id will continue
1344 # to take fast path on the new cache. At worst we take slow path, which is what
1345 # we would have been doing anyway. For prototype/unset properties, we will attempt to
1346 # convert opcode into a get_by_id_proto_load/get_by_id_unset, respectively, after an
1347 # execution counter hits zero.
1348
1349 _llint_op_get_by_id:
1350     traceExecution()
1351     loadi 8[PC], t0
1352     loadi 16[PC], t1
1353     loadConstantOrVariablePayload(t0, CellTag, t3, .opGetByIdSlow)
1354     loadi 20[PC], t2
1355     bineq JSCell::m_structureID[t3], t1, .opGetByIdSlow
1356     loadPropertyAtVariableOffset(t2, t3, t0, t1)
1357     loadi 4[PC], t2
1358     storei t0, TagOffset[cfr, t2, 8]
1359     storei t1, PayloadOffset[cfr, t2, 8]
1360     valueProfile(t0, t1, 32, t2)
1361     dispatch(9)
1362
1363 .opGetByIdSlow:
1364     callOpcodeSlowPath(_llint_slow_path_get_by_id)
1365     dispatch(9)
1366
1367
1368 _llint_op_get_by_id_proto_load:
1369     traceExecution()
1370     loadi 8[PC], t0
1371     loadi 16[PC], t1
1372     loadConstantOrVariablePayload(t0, CellTag, t3, .opGetByIdProtoSlow)
1373     loadi 20[PC], t2
1374     bineq JSCell::m_structureID[t3], t1, .opGetByIdProtoSlow
1375     loadpFromInstruction(6, t3)
1376     loadPropertyAtVariableOffset(t2, t3, t0, t1)
1377     loadi 4[PC], t2
1378     storei t0, TagOffset[cfr, t2, 8]
1379     storei t1, PayloadOffset[cfr, t2, 8]
1380     valueProfile(t0, t1, 32, t2)
1381     dispatch(9)
1382
1383 .opGetByIdProtoSlow:
1384     callOpcodeSlowPath(_llint_slow_path_get_by_id)
1385     dispatch(9)
1386
1387
1388 _llint_op_get_by_id_unset:
1389     traceExecution()
1390     loadi 8[PC], t0
1391     loadi 16[PC], t1
1392     loadConstantOrVariablePayload(t0, CellTag, t3, .opGetByIdUnsetSlow)
1393     bineq JSCell::m_structureID[t3], t1, .opGetByIdUnsetSlow
1394     loadi 4[PC], t2
1395     storei UndefinedTag, TagOffset[cfr, t2, 8]
1396     storei 0, PayloadOffset[cfr, t2, 8]
1397     valueProfile(UndefinedTag, 0, 32, t2)
1398     dispatch(9)
1399
1400 .opGetByIdUnsetSlow:
1401     callOpcodeSlowPath(_llint_slow_path_get_by_id)
1402     dispatch(9)
1403
1404
1405 _llint_op_get_array_length:
1406     traceExecution()
1407     loadi 8[PC], t0
1408     loadp 16[PC], t1
1409     loadConstantOrVariablePayload(t0, CellTag, t3, .opGetArrayLengthSlow)
1410     move t3, t2
1411     arrayProfile(t2, t1, t0)
1412     btiz t2, IsArray, .opGetArrayLengthSlow
1413     btiz t2, IndexingShapeMask, .opGetArrayLengthSlow
1414     loadi 4[PC], t1
1415     loadp JSObject::m_butterfly[t3], t0
1416     loadi -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], t0
1417     bilt t0, 0, .opGetArrayLengthSlow
1418     valueProfile(Int32Tag, t0, 32, t2)
1419     storep t0, PayloadOffset[cfr, t1, 8]
1420     storep Int32Tag, TagOffset[cfr, t1, 8]
1421     dispatch(9)
1422
1423 .opGetArrayLengthSlow:
1424     callOpcodeSlowPath(_llint_slow_path_get_by_id)
1425     dispatch(9)
1426
1427
1428 _llint_op_put_by_id:
1429     traceExecution()
1430     writeBarrierOnOperands(1, 3)
1431     loadi 4[PC], t3
1432     loadConstantOrVariablePayload(t3, CellTag, t0, .opPutByIdSlow)
1433     loadi JSCell::m_structureID[t0], t2
1434     bineq t2, 16[PC], .opPutByIdSlow
1435
1436     # At this point, we have:
1437     # t2 -> currentStructureID
1438     # t0 -> object base
1439     # We will lose currentStructureID in the shenanigans below.
1440
1441     loadi 12[PC], t1
1442     loadConstantOrVariable(t1, t2, t3)
1443     loadi 32[PC], t1
1444
1445     # At this point, we have:
1446     # t0 -> object base
1447     # t1 -> put by id flags
1448     # t2 -> value tag
1449     # t3 -> value payload
1450
1451     btinz t1, PutByIdPrimaryTypeMask, .opPutByIdTypeCheckObjectWithStructureOrOther
1452
1453     # We have one of the non-structure type checks. Find out which one.
1454     andi PutByIdSecondaryTypeMask, t1
1455     bilt t1, PutByIdSecondaryTypeString, .opPutByIdTypeCheckLessThanString
1456
1457     # We are one of the following: String, Symbol, Object, ObjectOrOther, Top
1458     bilt t1, PutByIdSecondaryTypeObjectOrOther, .opPutByIdTypeCheckLessThanObjectOrOther
1459
1460     # We are either ObjectOrOther or Top.
1461     bieq t1, PutByIdSecondaryTypeTop, .opPutByIdDoneCheckingTypes
1462
1463     # Check if we are ObjectOrOther.
1464     bieq t2, CellTag, .opPutByIdTypeCheckObject
1465 .opPutByIdTypeCheckOther:
1466     bieq t2, NullTag, .opPutByIdDoneCheckingTypes
1467     bieq t2, UndefinedTag, .opPutByIdDoneCheckingTypes
1468     jmp .opPutByIdSlow
1469
1470 .opPutByIdTypeCheckLessThanObjectOrOther:
1471     # We are either String, Symbol or Object.
1472     bineq t2, CellTag, .opPutByIdSlow
1473     bieq t1, PutByIdSecondaryTypeObject, .opPutByIdTypeCheckObject
1474     bieq t1, PutByIdSecondaryTypeSymbol, .opPutByIdTypeCheckSymbol
1475     bbeq JSCell::m_type[t3], StringType, .opPutByIdDoneCheckingTypes
1476     jmp .opPutByIdSlow
1477 .opPutByIdTypeCheckObject:
1478     bbaeq JSCell::m_type[t3], ObjectType, .opPutByIdDoneCheckingTypes
1479     jmp .opPutByIdSlow
1480 .opPutByIdTypeCheckSymbol:
1481     bbeq JSCell::m_type[t3], SymbolType, .opPutByIdDoneCheckingTypes
1482     jmp .opPutByIdSlow
1483
1484 .opPutByIdTypeCheckLessThanString:
1485     # We are one of the following: Bottom, Boolean, Other, Int32, Number.
1486     bilt t1, PutByIdSecondaryTypeInt32, .opPutByIdTypeCheckLessThanInt32
1487
1488     # We are either Int32 or Number.
1489     bieq t1, PutByIdSecondaryTypeNumber, .opPutByIdTypeCheckNumber
1490
1491     bieq t2, Int32Tag, .opPutByIdDoneCheckingTypes
1492     jmp .opPutByIdSlow
1493
1494 .opPutByIdTypeCheckNumber:
1495     bib t2, LowestTag + 1, .opPutByIdDoneCheckingTypes
1496     jmp .opPutByIdSlow
1497
1498 .opPutByIdTypeCheckLessThanInt32:
1499     # We are one of the following: Bottom, Boolean, Other
1500     bineq t1, PutByIdSecondaryTypeBoolean, .opPutByIdTypeCheckBottomOrOther
1501     bieq t2, BooleanTag, .opPutByIdDoneCheckingTypes
1502     jmp .opPutByIdSlow
1503
1504 .opPutByIdTypeCheckBottomOrOther:
1505     bieq t1, PutByIdSecondaryTypeOther, .opPutByIdTypeCheckOther
1506     jmp .opPutByIdSlow
1507
1508 .opPutByIdTypeCheckObjectWithStructureOrOther:
1509     bieq t2, CellTag, .opPutByIdTypeCheckObjectWithStructure
1510     btinz t1, PutByIdPrimaryTypeObjectWithStructureOrOther, .opPutByIdTypeCheckOther
1511     jmp .opPutByIdSlow
1512
1513 .opPutByIdTypeCheckObjectWithStructure:
1514     andi PutByIdSecondaryTypeMask, t1
1515     bineq t1, JSCell::m_structureID[t3], .opPutByIdSlow
1516
1517 .opPutByIdDoneCheckingTypes:
1518     loadi 24[PC], t1
1519
1520     btiz t1, .opPutByIdNotTransition
1521
1522     # This is the transition case. t1 holds the new Structure*. If we have a chain, we need to
1523     # check it. t0 is the base. We may clobber t1 to use it as scratch.
1524     loadp 28[PC], t3
1525     btpz t3, .opPutByIdTransitionDirect
1526
1527     loadi 16[PC], t2 # Need old structure again.
1528     loadp StructureChain::m_vector[t3], t3
1529     assert(macro (ok) btpnz t3, ok end)
1530
1531     loadp Structure::m_prototype[t2], t2
1532     btpz t2, .opPutByIdTransitionChainDone
1533 .opPutByIdTransitionChainLoop:
1534     loadp [t3], t1
1535     bpneq t1, JSCell::m_structureID[t2], .opPutByIdSlow
1536     addp 4, t3
1537     loadp Structure::m_prototype[t1], t2
1538     btpnz t2, .opPutByIdTransitionChainLoop
1539
1540 .opPutByIdTransitionChainDone:
1541     loadi 24[PC], t1
1542
1543 .opPutByIdTransitionDirect:
1544     storei t1, JSCell::m_structureID[t0]
1545     loadi 12[PC], t1
1546     loadConstantOrVariable(t1, t2, t3)
1547     loadi 20[PC], t1
1548     storePropertyAtVariableOffset(t1, t0, t2, t3)
1549     writeBarrierOnOperand(1)
1550     dispatch(9)
1551
1552 .opPutByIdNotTransition:
1553     # The only thing live right now is t0, which holds the base.
1554     loadi 12[PC], t1
1555     loadConstantOrVariable(t1, t2, t3)
1556     loadi 20[PC], t1
1557     storePropertyAtVariableOffset(t1, t0, t2, t3)
1558     dispatch(9)
1559
1560 .opPutByIdSlow:
1561     callOpcodeSlowPath(_llint_slow_path_put_by_id)
1562     dispatch(9)
1563
1564
1565 _llint_op_get_by_val:
1566     traceExecution()
1567     loadi 8[PC], t2
1568     loadConstantOrVariablePayload(t2, CellTag, t0, .opGetByValSlow)
1569     move t0, t2
1570     loadp 16[PC], t3
1571     arrayProfile(t2, t3, t1)
1572     loadi 12[PC], t3
1573     loadConstantOrVariablePayload(t3, Int32Tag, t1, .opGetByValSlow)
1574     loadp JSObject::m_butterfly[t0], t3
1575     andi IndexingShapeMask, t2
1576     bieq t2, Int32Shape, .opGetByValIsContiguous
1577     bineq t2, ContiguousShape, .opGetByValNotContiguous
1578 .opGetByValIsContiguous:
1579     
1580     biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t3], .opGetByValOutOfBounds
1581     loadi TagOffset[t3, t1, 8], t2
1582     loadi PayloadOffset[t3, t1, 8], t1
1583     jmp .opGetByValDone
1584
1585 .opGetByValNotContiguous:
1586     bineq t2, DoubleShape, .opGetByValNotDouble
1587     biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t3], .opGetByValOutOfBounds
1588     loadd [t3, t1, 8], ft0
1589     bdnequn ft0, ft0, .opGetByValSlow
1590     # FIXME: This could be massively optimized.
1591     fd2ii ft0, t1, t2
1592     loadi 4[PC], t0
1593     jmp .opGetByValNotEmpty
1594
1595 .opGetByValNotDouble:
1596     subi ArrayStorageShape, t2
1597     bia t2, SlowPutArrayStorageShape - ArrayStorageShape, .opGetByValSlow
1598     biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t3], .opGetByValOutOfBounds
1599     loadi ArrayStorage::m_vector + TagOffset[t3, t1, 8], t2
1600     loadi ArrayStorage::m_vector + PayloadOffset[t3, t1, 8], t1
1601
1602 .opGetByValDone:
1603     loadi 4[PC], t0
1604     bieq t2, EmptyValueTag, .opGetByValOutOfBounds
1605 .opGetByValNotEmpty:
1606     storei t2, TagOffset[cfr, t0, 8]
1607     storei t1, PayloadOffset[cfr, t0, 8]
1608     valueProfile(t2, t1, 20, t0)
1609     dispatch(6)
1610
1611 .opGetByValOutOfBounds:
1612     loadpFromInstruction(4, t0)
1613     storeb 1, ArrayProfile::m_outOfBounds[t0]
1614 .opGetByValSlow:
1615     callOpcodeSlowPath(_llint_slow_path_get_by_val)
1616     dispatch(6)
1617
1618
1619 macro contiguousPutByVal(storeCallback)
1620     biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], .outOfBounds
1621 .storeResult:
1622     loadi 12[PC], t2
1623     storeCallback(t2, t1, t0, t3)
1624     dispatch(5)
1625
1626 .outOfBounds:
1627     biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t0], .opPutByValOutOfBounds
1628     loadp 16[PC], t2
1629     storeb 1, ArrayProfile::m_mayStoreToHole[t2]
1630     addi 1, t3, t2
1631     storei t2, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0]
1632     jmp .storeResult
1633 end
1634
1635 macro putByVal(slowPath)
1636     traceExecution()
1637     writeBarrierOnOperands(1, 3)
1638     loadi 4[PC], t0
1639     loadConstantOrVariablePayload(t0, CellTag, t1, .opPutByValSlow)
1640     move t1, t2
1641     loadp 16[PC], t3
1642     arrayProfile(t2, t3, t0)
1643     loadi 8[PC], t0
1644     loadConstantOrVariablePayload(t0, Int32Tag, t3, .opPutByValSlow)
1645     loadp JSObject::m_butterfly[t1], t0
1646     andi IndexingShapeMask, t2
1647     bineq t2, Int32Shape, .opPutByValNotInt32
1648     contiguousPutByVal(
1649         macro (operand, scratch, base, index)
1650             loadConstantOrVariablePayload(operand, Int32Tag, scratch, .opPutByValSlow)
1651             storei Int32Tag, TagOffset[base, index, 8]
1652             storei scratch, PayloadOffset[base, index, 8]
1653         end)
1654
1655 .opPutByValNotInt32:
1656     bineq t2, DoubleShape, .opPutByValNotDouble
1657     contiguousPutByVal(
1658         macro (operand, scratch, base, index)
1659             const tag = scratch
1660             const payload = operand
1661             loadConstantOrVariable2Reg(operand, tag, payload)
1662             bineq tag, Int32Tag, .notInt
1663             ci2d payload, ft0
1664             jmp .ready
1665         .notInt:
1666             fii2d payload, tag, ft0
1667             bdnequn ft0, ft0, .opPutByValSlow
1668         .ready:
1669             stored ft0, [base, index, 8]
1670         end)
1671
1672 .opPutByValNotDouble:
1673     bineq t2, ContiguousShape, .opPutByValNotContiguous
1674     contiguousPutByVal(
1675         macro (operand, scratch, base, index)
1676             const tag = scratch
1677             const payload = operand
1678             loadConstantOrVariable2Reg(operand, tag, payload)
1679             storei tag, TagOffset[base, index, 8]
1680             storei payload, PayloadOffset[base, index, 8]
1681         end)
1682
1683 .opPutByValNotContiguous:
1684     bineq t2, ArrayStorageShape, .opPutByValSlow
1685     biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t0], .opPutByValOutOfBounds
1686     bieq ArrayStorage::m_vector + TagOffset[t0, t3, 8], EmptyValueTag, .opPutByValArrayStorageEmpty
1687 .opPutByValArrayStorageStoreResult:
1688     loadi 12[PC], t2
1689     loadConstantOrVariable2Reg(t2, t1, t2)
1690     storei t1, ArrayStorage::m_vector + TagOffset[t0, t3, 8]
1691     storei t2, ArrayStorage::m_vector + PayloadOffset[t0, t3, 8]
1692     dispatch(5)
1693
1694 .opPutByValArrayStorageEmpty:
1695     loadp 16[PC], t1
1696     storeb 1, ArrayProfile::m_mayStoreToHole[t1]
1697     addi 1, ArrayStorage::m_numValuesInVector[t0]
1698     bib t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], .opPutByValArrayStorageStoreResult
1699     addi 1, t3, t1
1700     storei t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0]
1701     jmp .opPutByValArrayStorageStoreResult
1702
1703 .opPutByValOutOfBounds:
1704     loadpFromInstruction(4, t0)
1705     storeb 1, ArrayProfile::m_outOfBounds[t0]
1706 .opPutByValSlow:
1707     callOpcodeSlowPath(slowPath)
1708     dispatch(5)
1709 end
1710
1711 _llint_op_put_by_val:
1712     putByVal(_llint_slow_path_put_by_val)
1713
1714 _llint_op_put_by_val_direct:
1715     putByVal(_llint_slow_path_put_by_val_direct)
1716
1717 _llint_op_jmp:
1718     traceExecution()
1719     dispatchBranch(4[PC])
1720
1721
1722 macro jumpTrueOrFalse(conditionOp, slow)
1723     loadi 4[PC], t1
1724     loadConstantOrVariablePayload(t1, BooleanTag, t0, .slow)
1725     conditionOp(t0, .target)
1726     dispatch(3)
1727
1728 .target:
1729     dispatchBranch(8[PC])
1730
1731 .slow:
1732     callOpcodeSlowPath(slow)
1733     dispatch(0)
1734 end
1735
1736
1737 macro equalNull(cellHandler, immediateHandler)
1738     loadi 4[PC], t0
1739     assertNotConstant(t0)
1740     loadi TagOffset[cfr, t0, 8], t1
1741     loadi PayloadOffset[cfr, t0, 8], t0
1742     bineq t1, CellTag, .immediate
1743     loadp JSCell::m_structureID[t0], t2
1744     cellHandler(t2, JSCell::m_flags[t0], .target)
1745     dispatch(3)
1746
1747 .target:
1748     dispatchBranch(8[PC])
1749
1750 .immediate:
1751     ori 1, t1
1752     immediateHandler(t1, .target)
1753     dispatch(3)
1754 end
1755
1756 _llint_op_jeq_null:
1757     traceExecution()
1758     equalNull(
1759         macro (structure, value, target) 
1760             btbz value, MasqueradesAsUndefined, .opJeqNullNotMasqueradesAsUndefined
1761             loadp CodeBlock[cfr], t0
1762             loadp CodeBlock::m_globalObject[t0], t0
1763             bpeq Structure::m_globalObject[structure], t0, target
1764 .opJeqNullNotMasqueradesAsUndefined:
1765         end,
1766         macro (value, target) bieq value, NullTag, target end)
1767     
1768
1769 _llint_op_jneq_null:
1770     traceExecution()
1771     equalNull(
1772         macro (structure, value, target) 
1773             btbz value, MasqueradesAsUndefined, target 
1774             loadp CodeBlock[cfr], t0
1775             loadp CodeBlock::m_globalObject[t0], t0
1776             bpneq Structure::m_globalObject[structure], t0, target
1777         end,
1778         macro (value, target) bineq value, NullTag, target end)
1779
1780
1781 _llint_op_jneq_ptr:
1782     traceExecution()
1783     loadi 4[PC], t0
1784     loadi 8[PC], t1
1785     loadp CodeBlock[cfr], t2
1786     loadp CodeBlock::m_globalObject[t2], t2
1787     bineq TagOffset[cfr, t0, 8], CellTag, .opJneqPtrBranch
1788     loadp JSGlobalObject::m_specialPointers[t2, t1, 4], t1
1789     bpeq PayloadOffset[cfr, t0, 8], t1, .opJneqPtrFallThrough
1790 .opJneqPtrBranch:
1791     storei 1, 16[PC]
1792     dispatchBranch(12[PC])
1793 .opJneqPtrFallThrough:
1794     dispatch(5)
1795
1796
1797 macro compare(integerCompare, doubleCompare, slowPath)
1798     loadi 4[PC], t2
1799     loadi 8[PC], t3
1800     loadConstantOrVariable(t2, t0, t1)
1801     loadConstantOrVariable2Reg(t3, t2, t3)
1802     bineq t0, Int32Tag, .op1NotInt
1803     bineq t2, Int32Tag, .op2NotInt
1804     integerCompare(t1, t3, .jumpTarget)
1805     dispatch(4)
1806
1807 .op1NotInt:
1808     bia t0, LowestTag, .slow
1809     bib t2, LowestTag, .op1NotIntOp2Double
1810     bineq t2, Int32Tag, .slow
1811     ci2d t3, ft1
1812     jmp .op1NotIntReady
1813 .op1NotIntOp2Double:
1814     fii2d t3, t2, ft1
1815 .op1NotIntReady:
1816     fii2d t1, t0, ft0
1817     doubleCompare(ft0, ft1, .jumpTarget)
1818     dispatch(4)
1819
1820 .op2NotInt:
1821     ci2d t1, ft0
1822     bia t2, LowestTag, .slow
1823     fii2d t3, t2, ft1
1824     doubleCompare(ft0, ft1, .jumpTarget)
1825     dispatch(4)
1826
1827 .jumpTarget:
1828     dispatchBranch(12[PC])
1829
1830 .slow:
1831     callOpcodeSlowPath(slowPath)
1832     dispatch(0)
1833 end
1834
1835
1836 _llint_op_switch_imm:
1837     traceExecution()
1838     loadi 12[PC], t2
1839     loadi 4[PC], t3
1840     loadConstantOrVariable(t2, t1, t0)
1841     loadp CodeBlock[cfr], t2
1842     loadp CodeBlock::m_rareData[t2], t2
1843     muli sizeof SimpleJumpTable, t3   # FIXME: would be nice to peephole this!
1844     loadp CodeBlock::RareData::m_switchJumpTables + VectorBufferOffset[t2], t2
1845     addp t3, t2
1846     bineq t1, Int32Tag, .opSwitchImmNotInt
1847     subi SimpleJumpTable::min[t2], t0
1848     biaeq t0, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchImmFallThrough
1849     loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t3
1850     loadi [t3, t0, 4], t1
1851     btiz t1, .opSwitchImmFallThrough
1852     dispatchBranchWithOffset(t1)
1853
1854 .opSwitchImmNotInt:
1855     bib t1, LowestTag, .opSwitchImmSlow  # Go to slow path if it's a double.
1856 .opSwitchImmFallThrough:
1857     dispatchBranch(8[PC])
1858
1859 .opSwitchImmSlow:
1860     callOpcodeSlowPath(_llint_slow_path_switch_imm)
1861     dispatch(0)
1862
1863
1864 _llint_op_switch_char:
1865     traceExecution()
1866     loadi 12[PC], t2
1867     loadi 4[PC], t3
1868     loadConstantOrVariable(t2, t1, t0)
1869     loadp CodeBlock[cfr], t2
1870     loadp CodeBlock::m_rareData[t2], t2
1871     muli sizeof SimpleJumpTable, t3
1872     loadp CodeBlock::RareData::m_switchJumpTables + VectorBufferOffset[t2], t2
1873     addp t3, t2
1874     bineq t1, CellTag, .opSwitchCharFallThrough
1875     bbneq JSCell::m_type[t0], StringType, .opSwitchCharFallThrough
1876     bineq JSString::m_length[t0], 1, .opSwitchCharFallThrough
1877     loadp JSString::m_value[t0], t0
1878     btpz  t0, .opSwitchOnRope
1879     loadp StringImpl::m_data8[t0], t1
1880     btinz StringImpl::m_hashAndFlags[t0], HashFlags8BitBuffer, .opSwitchChar8Bit
1881     loadh [t1], t0
1882     jmp .opSwitchCharReady
1883 .opSwitchChar8Bit:
1884     loadb [t1], t0
1885 .opSwitchCharReady:
1886     subi SimpleJumpTable::min[t2], t0
1887     biaeq t0, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchCharFallThrough
1888     loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t2
1889     loadi [t2, t0, 4], t1
1890     btiz t1, .opSwitchCharFallThrough
1891     dispatchBranchWithOffset(t1)
1892
1893 .opSwitchCharFallThrough:
1894     dispatchBranch(8[PC])
1895
1896 .opSwitchOnRope:
1897     callOpcodeSlowPath(_llint_slow_path_switch_char)
1898     dispatch(0)
1899
1900
1901 macro arrayProfileForCall()
1902     loadi 16[PC], t3
1903     negi t3
1904     bineq ThisArgumentOffset + TagOffset[cfr, t3, 8], CellTag, .done
1905     loadi ThisArgumentOffset + PayloadOffset[cfr, t3, 8], t0
1906     loadp JSCell::m_structureID[t0], t0
1907     loadpFromInstruction(CallOpCodeSize - 2, t1)
1908     storep t0, ArrayProfile::m_lastSeenStructureID[t1]
1909 .done:
1910 end
1911
1912 macro doCall(slowPath, prepareCall)
1913     loadi 8[PC], t0
1914     loadi 20[PC], t1
1915     loadp LLIntCallLinkInfo::callee[t1], t2
1916     loadConstantOrVariablePayload(t0, CellTag, t3, .opCallSlow)
1917     bineq t3, t2, .opCallSlow
1918     loadi 16[PC], t3
1919     lshifti 3, t3
1920     negi t3
1921     addp cfr, t3  # t3 contains the new value of cfr
1922     storei t2, Callee + PayloadOffset[t3]
1923     loadi 12[PC], t2
1924     storei PC, ArgumentCount + TagOffset[cfr]
1925     storei t2, ArgumentCount + PayloadOffset[t3]
1926     storei CellTag, Callee + TagOffset[t3]
1927     move t3, sp
1928     prepareCall(LLIntCallLinkInfo::machineCodeTarget[t1], t2, t3, t4)
1929     callTargetFunction(LLIntCallLinkInfo::machineCodeTarget[t1])
1930
1931 .opCallSlow:
1932     slowPathForCall(slowPath, prepareCall)
1933 end
1934
1935 _llint_op_ret:
1936     traceExecution()
1937     checkSwitchToJITForEpilogue()
1938     loadi 4[PC], t2
1939     loadConstantOrVariable(t2, t1, t0)
1940     doReturn()
1941
1942
1943 _llint_op_to_primitive:
1944     traceExecution()
1945     loadi 8[PC], t2
1946     loadi 4[PC], t3
1947     loadConstantOrVariable(t2, t1, t0)
1948     bineq t1, CellTag, .opToPrimitiveIsImm
1949     bbaeq JSCell::m_type[t0], ObjectType, .opToPrimitiveSlowCase
1950 .opToPrimitiveIsImm:
1951     storei t1, TagOffset[cfr, t3, 8]
1952     storei t0, PayloadOffset[cfr, t3, 8]
1953     dispatch(3)
1954
1955 .opToPrimitiveSlowCase:
1956     callOpcodeSlowPath(_slow_path_to_primitive)
1957     dispatch(3)
1958
1959
1960 _llint_op_catch:
1961     # This is where we end up from the JIT's throw trampoline (because the
1962     # machine code return address will be set to _llint_op_catch), and from
1963     # the interpreter's throw trampoline (see _llint_throw_trampoline).
1964     # The throwing code must have known that we were throwing to the interpreter,
1965     # and have set VM::targetInterpreterPCForThrow.
1966     loadp Callee + PayloadOffset[cfr], t3
1967     andp MarkedBlockMask, t3
1968     loadp MarkedBlock::m_vm[t3], t3
1969     restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer(t3, t0)
1970     loadp VM::callFrameForCatch[t3], cfr
1971     storep 0, VM::callFrameForCatch[t3]
1972     restoreStackPointerAfterCall()
1973
1974     loadi VM::targetInterpreterPCForThrow[t3], PC
1975
1976     callOpcodeSlowPath(_llint_slow_path_check_if_exception_is_uncatchable_and_notify_profiler)
1977     bpeq r1, 0, .isCatchableException
1978     jmp _llint_throw_from_slow_path_trampoline
1979
1980 .isCatchableException:
1981     loadp Callee + PayloadOffset[cfr], t3
1982     andp MarkedBlockMask, t3
1983     loadp MarkedBlock::m_vm[t3], t3
1984
1985     loadi VM::m_exception[t3], t0
1986     storei 0, VM::m_exception[t3]
1987     loadi 4[PC], t2
1988     storei t0, PayloadOffset[cfr, t2, 8]
1989     storei CellTag, TagOffset[cfr, t2, 8]
1990
1991     loadi Exception::m_value + TagOffset[t0], t1
1992     loadi Exception::m_value + PayloadOffset[t0], t0
1993     loadi 8[PC], t2
1994     storei t0, PayloadOffset[cfr, t2, 8]
1995     storei t1, TagOffset[cfr, t2, 8]
1996
1997     traceExecution()  # This needs to be here because we don't want to clobber t0, t1, t2, t3 above.
1998     dispatch(3)
1999
2000 _llint_op_end:
2001     traceExecution()
2002     checkSwitchToJITForEpilogue()
2003     loadi 4[PC], t0
2004     assertNotConstant(t0)
2005     loadi TagOffset[cfr, t0, 8], t1
2006     loadi PayloadOffset[cfr, t0, 8], t0
2007     doReturn()
2008
2009
2010 _llint_throw_from_slow_path_trampoline:
2011     callSlowPath(_llint_slow_path_handle_exception)
2012
2013     # When throwing from the interpreter (i.e. throwing from LLIntSlowPaths), so
2014     # the throw target is not necessarily interpreted code, we come to here.
2015     # This essentially emulates the JIT's throwing protocol.
2016     loadp Callee[cfr], t1
2017     andp MarkedBlockMask, t1
2018     loadp MarkedBlock::m_vm[t1], t1
2019     copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(t1, t2)
2020     jmp VM::targetMachinePCForThrow[t1]
2021
2022
2023 _llint_throw_during_call_trampoline:
2024     preserveReturnAddressAfterCall(t2)
2025     jmp _llint_throw_from_slow_path_trampoline
2026
2027
2028 macro nativeCallTrampoline(executableOffsetToFunction)
2029
2030     functionPrologue()
2031     storep 0, CodeBlock[cfr]
2032     loadi Callee + PayloadOffset[cfr], t1
2033     // Callee is still in t1 for code below
2034     if X86 or X86_WIN
2035         subp 8, sp # align stack pointer
2036         andp MarkedBlockMask, t1
2037         loadp MarkedBlock::m_vm[t1], t3
2038         storep cfr, VM::topCallFrame[t3]
2039         move cfr, a0  # a0 = ecx
2040         storep a0, [sp]
2041         loadi Callee + PayloadOffset[cfr], t1
2042         loadp JSFunction::m_executable[t1], t1
2043         checkStackPointerAlignment(t3, 0xdead0001)
2044         call executableOffsetToFunction[t1]
2045         loadp Callee + PayloadOffset[cfr], t3
2046         andp MarkedBlockMask, t3
2047         loadp MarkedBlock::m_vm[t3], t3
2048         addp 8, sp
2049     elsif ARM or ARMv7 or ARMv7_TRADITIONAL or C_LOOP or MIPS
2050         subp 8, sp # align stack pointer
2051         # t1 already contains the Callee.
2052         andp MarkedBlockMask, t1
2053         loadp MarkedBlock::m_vm[t1], t1
2054         storep cfr, VM::topCallFrame[t1]
2055         move cfr, a0
2056         loadi Callee + PayloadOffset[cfr], t1
2057         loadp JSFunction::m_executable[t1], t1
2058         checkStackPointerAlignment(t3, 0xdead0001)
2059         if C_LOOP
2060             cloopCallNative executableOffsetToFunction[t1]
2061         else
2062             call executableOffsetToFunction[t1]
2063         end
2064         loadp Callee + PayloadOffset[cfr], t3
2065         andp MarkedBlockMask, t3
2066         loadp MarkedBlock::m_vm[t3], t3
2067         addp 8, sp
2068     else
2069         error
2070     end
2071     
2072     btinz VM::m_exception[t3], .handleException
2073
2074     functionEpilogue()
2075     ret
2076
2077 .handleException:
2078     storep cfr, VM::topCallFrame[t3]
2079     jmp _llint_throw_from_slow_path_trampoline
2080 end
2081
2082
2083 macro getConstantScope(dst)
2084     loadpFromInstruction(6, t0)
2085     loadisFromInstruction(dst, t1)
2086     storei CellTag, TagOffset[cfr, t1, 8]
2087     storei t0, PayloadOffset[cfr, t1, 8]
2088 end
2089
2090 macro varInjectionCheck(slowPath)
2091     loadp CodeBlock[cfr], t0
2092     loadp CodeBlock::m_globalObject[t0], t0
2093     loadp JSGlobalObject::m_varInjectionWatchpoint[t0], t0
2094     bbeq WatchpointSet::m_state[t0], IsInvalidated, slowPath
2095 end
2096
2097 macro resolveScope()
2098     loadp CodeBlock[cfr], t0
2099     loadisFromInstruction(5, t2)
2100
2101     loadisFromInstruction(2, t0)
2102     loadp PayloadOffset[cfr, t0, 8], t0
2103     btiz t2, .resolveScopeLoopEnd
2104
2105 .resolveScopeLoop:
2106     loadp JSScope::m_next[t0], t0
2107     subi 1, t2
2108     btinz t2, .resolveScopeLoop
2109
2110 .resolveScopeLoopEnd:
2111     loadisFromInstruction(1, t1)
2112     storei CellTag, TagOffset[cfr, t1, 8]
2113     storei t0, PayloadOffset[cfr, t1, 8]
2114 end
2115
2116
2117 _llint_op_resolve_scope:
2118     traceExecution()
2119     loadisFromInstruction(4, t0)
2120
2121 #rGlobalProperty:
2122     bineq t0, GlobalProperty, .rGlobalVar
2123     getConstantScope(1)
2124     dispatch(7)
2125
2126 .rGlobalVar:
2127     bineq t0, GlobalVar, .rGlobalLexicalVar
2128     getConstantScope(1)
2129     dispatch(7)
2130
2131 .rGlobalLexicalVar:
2132     bineq t0, GlobalLexicalVar, .rClosureVar
2133     getConstantScope(1)
2134     dispatch(7)
2135
2136 .rClosureVar:
2137     bineq t0, ClosureVar, .rModuleVar
2138     resolveScope()
2139     dispatch(7)
2140
2141 .rModuleVar:
2142     bineq t0, ModuleVar, .rGlobalPropertyWithVarInjectionChecks
2143     getConstantScope(1)
2144     dispatch(7)
2145
2146 .rGlobalPropertyWithVarInjectionChecks:
2147     bineq t0, GlobalPropertyWithVarInjectionChecks, .rGlobalVarWithVarInjectionChecks
2148     varInjectionCheck(.rDynamic)
2149     getConstantScope(1)
2150     dispatch(7)
2151
2152 .rGlobalVarWithVarInjectionChecks:
2153     bineq t0, GlobalVarWithVarInjectionChecks, .rGlobalLexicalVarWithVarInjectionChecks
2154     varInjectionCheck(.rDynamic)
2155     getConstantScope(1)
2156     dispatch(7)
2157
2158 .rGlobalLexicalVarWithVarInjectionChecks:
2159     bineq t0, GlobalLexicalVarWithVarInjectionChecks, .rClosureVarWithVarInjectionChecks
2160     varInjectionCheck(.rDynamic)
2161     getConstantScope(1)
2162     dispatch(7)
2163
2164 .rClosureVarWithVarInjectionChecks:
2165     bineq t0, ClosureVarWithVarInjectionChecks, .rDynamic
2166     varInjectionCheck(.rDynamic)
2167     resolveScope()
2168     dispatch(7)
2169
2170 .rDynamic:
2171     callOpcodeSlowPath(_slow_path_resolve_scope)
2172     dispatch(7)
2173
2174
2175 macro loadWithStructureCheck(operand, slowPath)
2176     loadisFromInstruction(operand, t0)
2177     loadp PayloadOffset[cfr, t0, 8], t0
2178     loadpFromInstruction(5, t1)
2179     bpneq JSCell::m_structureID[t0], t1, slowPath
2180 end
2181
2182 macro getProperty()
2183     loadisFromInstruction(6, t3)
2184     loadPropertyAtVariableOffset(t3, t0, t1, t2)
2185     valueProfile(t1, t2, 28, t0)
2186     loadisFromInstruction(1, t0)
2187     storei t1, TagOffset[cfr, t0, 8]
2188     storei t2, PayloadOffset[cfr, t0, 8]
2189 end
2190
2191 macro getGlobalVar(tdzCheckIfNecessary)
2192     loadpFromInstruction(6, t0)
2193     loadp TagOffset[t0], t1
2194     loadp PayloadOffset[t0], t2
2195     tdzCheckIfNecessary(t1)
2196     valueProfile(t1, t2, 28, t0)
2197     loadisFromInstruction(1, t0)
2198     storei t1, TagOffset[cfr, t0, 8]
2199     storei t2, PayloadOffset[cfr, t0, 8]
2200 end
2201
2202 macro getClosureVar()
2203     loadisFromInstruction(6, t3)
2204     loadp JSEnvironmentRecord_variables + TagOffset[t0, t3, 8], t1
2205     loadp JSEnvironmentRecord_variables + PayloadOffset[t0, t3, 8], t2
2206     valueProfile(t1, t2, 28, t0)
2207     loadisFromInstruction(1, t0)
2208     storei t1, TagOffset[cfr, t0, 8]
2209     storei t2, PayloadOffset[cfr, t0, 8]
2210 end
2211
2212 _llint_op_get_from_scope:
2213     traceExecution()
2214     loadisFromInstruction(4, t0)
2215     andi ResolveTypeMask, t0
2216
2217 #gGlobalProperty:
2218     bineq t0, GlobalProperty, .gGlobalVar
2219     loadWithStructureCheck(2, .gDynamic)
2220     getProperty()
2221     dispatch(8)
2222
2223 .gGlobalVar:
2224     bineq t0, GlobalVar, .gGlobalLexicalVar
2225     getGlobalVar(macro(t) end)
2226     dispatch(8)
2227
2228 .gGlobalLexicalVar:
2229     bineq t0, GlobalLexicalVar, .gClosureVar
2230     getGlobalVar(
2231         macro(tag)
2232             bieq tag, EmptyValueTag, .gDynamic
2233         end)
2234     dispatch(8)
2235
2236 .gClosureVar:
2237     bineq t0, ClosureVar, .gGlobalPropertyWithVarInjectionChecks
2238     loadVariable(2, t2, t1, t0)
2239     getClosureVar()
2240     dispatch(8)
2241
2242 .gGlobalPropertyWithVarInjectionChecks:
2243     bineq t0, GlobalPropertyWithVarInjectionChecks, .gGlobalVarWithVarInjectionChecks
2244     loadWithStructureCheck(2, .gDynamic)
2245     getProperty()
2246     dispatch(8)
2247
2248 .gGlobalVarWithVarInjectionChecks:
2249     bineq t0, GlobalVarWithVarInjectionChecks, .gGlobalLexicalVarWithVarInjectionChecks
2250     varInjectionCheck(.gDynamic)
2251     getGlobalVar(macro(t) end)
2252     dispatch(8)
2253
2254 .gGlobalLexicalVarWithVarInjectionChecks:
2255     bineq t0, GlobalLexicalVarWithVarInjectionChecks, .gClosureVarWithVarInjectionChecks
2256     varInjectionCheck(.gDynamic)
2257     getGlobalVar(
2258         macro(tag)
2259             bieq tag, EmptyValueTag, .gDynamic
2260         end)
2261     dispatch(8)
2262
2263 .gClosureVarWithVarInjectionChecks:
2264     bineq t0, ClosureVarWithVarInjectionChecks, .gDynamic
2265     varInjectionCheck(.gDynamic)
2266     loadVariable(2, t2, t1, t0)
2267     getClosureVar()
2268     dispatch(8)
2269
2270 .gDynamic:
2271     callOpcodeSlowPath(_llint_slow_path_get_from_scope)
2272     dispatch(8)
2273
2274
2275 macro putProperty()
2276     loadisFromInstruction(3, t1)
2277     loadConstantOrVariable(t1, t2, t3)
2278     loadisFromInstruction(6, t1)
2279     storePropertyAtVariableOffset(t1, t0, t2, t3)
2280 end
2281
2282 macro putGlobalVariable()
2283     loadisFromInstruction(3, t0)
2284     loadConstantOrVariable(t0, t1, t2)
2285     loadpFromInstruction(5, t3)
2286     notifyWrite(t3, .pDynamic)
2287     loadpFromInstruction(6, t0)
2288     storei t1, TagOffset[t0]
2289     storei t2, PayloadOffset[t0]
2290 end
2291
2292 macro putClosureVar()
2293     loadisFromInstruction(3, t1)
2294     loadConstantOrVariable(t1, t2, t3)
2295     loadisFromInstruction(6, t1)
2296     storei t2, JSEnvironmentRecord_variables + TagOffset[t0, t1, 8]
2297     storei t3, JSEnvironmentRecord_variables + PayloadOffset[t0, t1, 8]
2298 end
2299
2300 macro putLocalClosureVar()
2301     loadisFromInstruction(3, t1)
2302     loadConstantOrVariable(t1, t2, t3)
2303     loadpFromInstruction(5, t5)
2304     btpz t5, .noVariableWatchpointSet
2305     notifyWrite(t5, .pDynamic)
2306 .noVariableWatchpointSet:
2307     loadisFromInstruction(6, t1)
2308     storei t2, JSEnvironmentRecord_variables + TagOffset[t0, t1, 8]
2309     storei t3, JSEnvironmentRecord_variables + PayloadOffset[t0, t1, 8]
2310 end
2311
2312
2313 _llint_op_put_to_scope:
2314     traceExecution()
2315     loadisFromInstruction(4, t0)
2316     andi ResolveTypeMask, t0
2317
2318 #pLocalClosureVar:
2319     bineq t0, LocalClosureVar, .pGlobalProperty
2320     writeBarrierOnOperands(1, 3)
2321     loadVariable(1, t2, t1, t0)
2322     putLocalClosureVar()
2323     dispatch(7)
2324
2325 .pGlobalProperty:
2326     bineq t0, GlobalProperty, .pGlobalVar
2327     writeBarrierOnOperands(1, 3)
2328     loadWithStructureCheck(1, .pDynamic)
2329     putProperty()
2330     dispatch(7)
2331
2332 .pGlobalVar:
2333     bineq t0, GlobalVar, .pGlobalLexicalVar
2334     writeBarrierOnGlobalObject(3)
2335     putGlobalVariable()
2336     dispatch(7)
2337
2338 .pGlobalLexicalVar:
2339     bineq t0, GlobalLexicalVar, .pClosureVar
2340     writeBarrierOnGlobalLexicalEnvironment(3)
2341     putGlobalVariable()
2342     dispatch(7)
2343
2344 .pClosureVar:
2345     bineq t0, ClosureVar, .pGlobalPropertyWithVarInjectionChecks
2346     writeBarrierOnOperands(1, 3)
2347     loadVariable(1, t2, t1, t0)
2348     putClosureVar()
2349     dispatch(7)
2350
2351 .pGlobalPropertyWithVarInjectionChecks:
2352     bineq t0, GlobalPropertyWithVarInjectionChecks, .pGlobalVarWithVarInjectionChecks
2353     writeBarrierOnOperands(1, 3)
2354     loadWithStructureCheck(1, .pDynamic)
2355     putProperty()
2356     dispatch(7)
2357
2358 .pGlobalVarWithVarInjectionChecks:
2359     bineq t0, GlobalVarWithVarInjectionChecks, .pGlobalLexicalVarWithVarInjectionChecks
2360     writeBarrierOnGlobalObject(3)
2361     varInjectionCheck(.pDynamic)
2362     putGlobalVariable()
2363     dispatch(7)
2364
2365 .pGlobalLexicalVarWithVarInjectionChecks:
2366     bineq t0, GlobalLexicalVarWithVarInjectionChecks, .pClosureVarWithVarInjectionChecks
2367     writeBarrierOnGlobalLexicalEnvironment(3)
2368     varInjectionCheck(.pDynamic)
2369     putGlobalVariable()
2370     dispatch(7)
2371
2372 .pClosureVarWithVarInjectionChecks:
2373     bineq t0, ClosureVarWithVarInjectionChecks, .pModuleVar
2374     writeBarrierOnOperands(1, 3)
2375     varInjectionCheck(.pDynamic)
2376     loadVariable(1, t2, t1, t0)
2377     putClosureVar()
2378     dispatch(7)
2379
2380 .pModuleVar:
2381     bineq t0, ModuleVar, .pDynamic
2382     callOpcodeSlowPath(_slow_path_throw_strict_mode_readonly_property_write_error)
2383     dispatch(7)
2384
2385 .pDynamic:
2386     callOpcodeSlowPath(_llint_slow_path_put_to_scope)
2387     dispatch(7)
2388
2389
2390 _llint_op_get_from_arguments:
2391     traceExecution()
2392     loadisFromInstruction(2, t0)
2393     loadi PayloadOffset[cfr, t0, 8], t0
2394     loadi 12[PC], t1
2395     loadi DirectArguments_storage + TagOffset[t0, t1, 8], t2
2396     loadi DirectArguments_storage + PayloadOffset[t0, t1, 8], t3
2397     loadisFromInstruction(1, t1)
2398     valueProfile(t2, t3, 16, t0)
2399     storei t2, TagOffset[cfr, t1, 8]
2400     storei t3, PayloadOffset[cfr, t1, 8]
2401     dispatch(5)
2402
2403
2404 _llint_op_put_to_arguments:
2405     traceExecution()
2406     writeBarrierOnOperands(1, 3)
2407     loadisFromInstruction(1, t0)
2408     loadi PayloadOffset[cfr, t0, 8], t0
2409     loadisFromInstruction(3, t1)
2410     loadConstantOrVariable(t1, t2, t3)
2411     loadi 8[PC], t1
2412     storei t2, DirectArguments_storage + TagOffset[t0, t1, 8]
2413     storei t3, DirectArguments_storage + PayloadOffset[t0, t1, 8]
2414     dispatch(4)
2415
2416
2417 _llint_op_get_parent_scope:
2418     traceExecution()
2419     loadisFromInstruction(2, t0)
2420     loadp PayloadOffset[cfr, t0, 8], t0
2421     loadp JSScope::m_next[t0], t0
2422     loadisFromInstruction(1, t1)
2423     storei CellTag, TagOffset[cfr, t1, 8]
2424     storei t0, PayloadOffset[cfr, t1, 8]
2425     dispatch(3)
2426
2427
2428 _llint_op_profile_type:
2429     traceExecution()
2430     loadp CodeBlock[cfr], t1
2431     loadp CodeBlock::m_vm[t1], t1
2432     # t1 is holding the pointer to the typeProfilerLog.
2433     loadp VM::m_typeProfilerLog[t1], t1
2434
2435     # t0 is holding the payload, t5 is holding the tag.
2436     loadisFromInstruction(1, t2)
2437     loadConstantOrVariable(t2, t5, t0)
2438
2439     bieq t5, EmptyValueTag, .opProfileTypeDone
2440
2441     # t2 is holding the pointer to the current log entry.
2442     loadp TypeProfilerLog::m_currentLogEntryPtr[t1], t2
2443
2444     # Store the JSValue onto the log entry.
2445     storei t5, TypeProfilerLog::LogEntry::value + TagOffset[t2]
2446     storei t0, TypeProfilerLog::LogEntry::value + PayloadOffset[t2]
2447
2448     # Store the TypeLocation onto the log entry.
2449     loadpFromInstruction(2, t3)
2450     storep t3, TypeProfilerLog::LogEntry::location[t2]
2451
2452     bieq t5, CellTag, .opProfileTypeIsCell
2453     storei 0, TypeProfilerLog::LogEntry::structureID[t2]
2454     jmp .opProfileTypeSkipIsCell
2455 .opProfileTypeIsCell:
2456     loadi JSCell::m_structureID[t0], t3
2457     storei t3, TypeProfilerLog::LogEntry::structureID[t2]
2458 .opProfileTypeSkipIsCell:
2459     
2460     # Increment the current log entry.
2461     addp sizeof TypeProfilerLog::LogEntry, t2
2462     storep t2, TypeProfilerLog::m_currentLogEntryPtr[t1]
2463
2464     loadp TypeProfilerLog::m_logEndPtr[t1], t1
2465     bpneq t2, t1, .opProfileTypeDone
2466     callOpcodeSlowPath(_slow_path_profile_type_clear_log)
2467
2468 .opProfileTypeDone:
2469     dispatch(6)
2470
2471
2472 _llint_op_profile_control_flow:
2473     traceExecution()
2474     loadpFromInstruction(1, t0)
2475     loadi BasicBlockLocation::m_executionCount[t0], t1
2476     addi 1, t1
2477     bieq t1, 0, .done # We overflowed.
2478     storei t1, BasicBlockLocation::m_executionCount[t0]
2479 .done:
2480     dispatch(2)
2481
2482
2483 _llint_op_get_rest_length:
2484     traceExecution()
2485     loadi PayloadOffset + ArgumentCount[cfr], t0
2486     subi 1, t0
2487     loadisFromInstruction(2, t1)
2488     bilteq t0, t1, .storeZero
2489     subi t1, t0
2490     jmp .finish
2491 .storeZero:
2492     move 0, t0
2493 .finish:
2494     loadisFromInstruction(1, t1)
2495     storei t0, PayloadOffset[cfr, t1, 8]
2496     storei Int32Tag, TagOffset[cfr, t1, 8]
2497     dispatch(3)
2498
2499
2500 _llint_op_log_shadow_chicken_prologue:
2501     traceExecution()
2502     acquireShadowChickenPacket(.opLogShadowChickenPrologueSlow)
2503     storep cfr, ShadowChicken::Packet::frame[t0]
2504     loadp CallerFrame[cfr], t1
2505     storep t1, ShadowChicken::Packet::callerFrame[t0]
2506     loadp Callee + PayloadOffset[cfr], t1
2507     storep t1, ShadowChicken::Packet::callee[t0]
2508     loadisFromInstruction(1, t1)
2509     loadi PayloadOffset[cfr, t1, 8], t1
2510     storep t1, ShadowChicken::Packet::scope[t0]
2511     dispatch(2)
2512 .opLogShadowChickenPrologueSlow:
2513     callOpcodeSlowPath(_llint_slow_path_log_shadow_chicken_prologue)
2514     dispatch(2)
2515
2516
2517 _llint_op_log_shadow_chicken_tail:
2518     traceExecution()
2519     acquireShadowChickenPacket(.opLogShadowChickenTailSlow)
2520     storep cfr, ShadowChicken::Packet::frame[t0]
2521     storep ShadowChickenTailMarker, ShadowChicken::Packet::callee[t0]
2522     loadVariable(1, t3, t2, t1)
2523     storei t2, TagOffset + ShadowChicken::Packet::thisValue[t0]
2524     storei t1, PayloadOffset + ShadowChicken::Packet::thisValue[t0]
2525     loadisFromInstruction(2, t1)
2526     loadi PayloadOffset[cfr, t1, 8], t1
2527     storep t1, ShadowChicken::Packet::scope[t0]
2528     loadp CodeBlock[cfr], t1
2529     storep t1, ShadowChicken::Packet::codeBlock[t0]
2530     storei PC, ShadowChicken::Packet::callSiteIndex[t0]
2531     dispatch(3)
2532 .opLogShadowChickenTailSlow:
2533     callOpcodeSlowPath(_llint_slow_path_log_shadow_chicken_tail)
2534     dispatch(3)