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