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