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