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