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