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