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