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