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