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