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