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