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