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