85173bc8262146b0e0d1e0192b706028bbd90683
[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     restoreCalleeSavesFromVMCalleeSavesBuffer(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     loadp JSFunction::m_rareData[t0], t3
601     btpz t3, .opCreateThisSlow
602     loadp FunctionRareData::m_objectAllocationProfile + ObjectAllocationProfile::m_allocator[t3], t1
603     loadp FunctionRareData::m_objectAllocationProfile + ObjectAllocationProfile::m_structure[t3], t2
604     btpz t1, .opCreateThisSlow
605     loadpFromInstruction(4, t3)
606     bpeq t3, 1, .hasSeenMultipleCallee
607     bpneq t3, t0, .opCreateThisSlow
608 .hasSeenMultipleCallee:
609     allocateJSObject(t1, t2, t0, t3, .opCreateThisSlow)
610     loadisFromInstruction(1, t1)
611     storeq t0, [cfr, t1, 8]
612     dispatch(5)
613
614 .opCreateThisSlow:
615     callSlowPath(_slow_path_create_this)
616     dispatch(5)
617
618
619 _llint_op_to_this:
620     traceExecution()
621     loadisFromInstruction(1, t0)
622     loadq [cfr, t0, 8], t0
623     btqnz t0, tagMask, .opToThisSlow
624     bbneq JSCell::m_type[t0], FinalObjectType, .opToThisSlow
625     loadStructureWithScratch(t0, t1, t2)
626     loadpFromInstruction(2, t2)
627     bpneq t1, t2, .opToThisSlow
628     dispatch(4)
629
630 .opToThisSlow:
631     callSlowPath(_slow_path_to_this)
632     dispatch(4)
633
634
635 _llint_op_new_object:
636     traceExecution()
637     loadpFromInstruction(3, t0)
638     loadp ObjectAllocationProfile::m_allocator[t0], t1
639     loadp ObjectAllocationProfile::m_structure[t0], t2
640     allocateJSObject(t1, t2, t0, t3, .opNewObjectSlow)
641     loadisFromInstruction(1, t1)
642     storeq t0, [cfr, t1, 8]
643     dispatch(4)
644
645 .opNewObjectSlow:
646     callSlowPath(_llint_slow_path_new_object)
647     dispatch(4)
648
649
650 _llint_op_check_tdz:
651     traceExecution()
652     loadisFromInstruction(1, t0)
653     loadConstantOrVariable(t0, t1)
654     bqneq t1, ValueEmpty, .opNotTDZ
655     callSlowPath(_slow_path_throw_tdz_error)
656
657 .opNotTDZ:
658     dispatch(2)
659
660
661 _llint_op_mov:
662     traceExecution()
663     loadisFromInstruction(2, t1)
664     loadisFromInstruction(1, t0)
665     loadConstantOrVariable(t1, t2)
666     storeq t2, [cfr, t0, 8]
667     dispatch(3)
668
669
670 _llint_op_not:
671     traceExecution()
672     loadisFromInstruction(2, t0)
673     loadisFromInstruction(1, t1)
674     loadConstantOrVariable(t0, t2)
675     xorq ValueFalse, t2
676     btqnz t2, ~1, .opNotSlow
677     xorq ValueTrue, t2
678     storeq t2, [cfr, t1, 8]
679     dispatch(3)
680
681 .opNotSlow:
682     callSlowPath(_slow_path_not)
683     dispatch(3)
684
685
686 macro equalityComparison(integerComparison, slowPath)
687     traceExecution()
688     loadisFromInstruction(3, t0)
689     loadisFromInstruction(2, t2)
690     loadisFromInstruction(1, t3)
691     loadConstantOrVariableInt32(t0, t1, .slow)
692     loadConstantOrVariableInt32(t2, t0, .slow)
693     integerComparison(t0, t1, t0)
694     orq ValueFalse, t0
695     storeq t0, [cfr, t3, 8]
696     dispatch(4)
697
698 .slow:
699     callSlowPath(slowPath)
700     dispatch(4)
701 end
702
703 _llint_op_eq:
704     equalityComparison(
705         macro (left, right, result) cieq left, right, result end,
706         _slow_path_eq)
707
708
709 _llint_op_neq:
710     equalityComparison(
711         macro (left, right, result) cineq left, right, result end,
712         _slow_path_neq)
713
714
715 macro equalNullComparison()
716     loadisFromInstruction(2, t0)
717     loadq [cfr, t0, 8], t0
718     btqnz t0, tagMask, .immediate
719     btbnz JSCell::m_flags[t0], MasqueradesAsUndefined, .masqueradesAsUndefined
720     move 0, t0
721     jmp .done
722 .masqueradesAsUndefined:
723     loadStructureWithScratch(t0, t2, t1)
724     loadp CodeBlock[cfr], t0
725     loadp CodeBlock::m_globalObject[t0], t0
726     cpeq Structure::m_globalObject[t2], t0, t0
727     jmp .done
728 .immediate:
729     andq ~TagBitUndefined, t0
730     cqeq t0, ValueNull, t0
731 .done:
732 end
733
734 _llint_op_eq_null:
735     traceExecution()
736     equalNullComparison()
737     loadisFromInstruction(1, t1)
738     orq ValueFalse, t0
739     storeq t0, [cfr, t1, 8]
740     dispatch(3)
741
742
743 _llint_op_neq_null:
744     traceExecution()
745     equalNullComparison()
746     loadisFromInstruction(1, t1)
747     xorq ValueTrue, t0
748     storeq t0, [cfr, t1, 8]
749     dispatch(3)
750
751
752 macro strictEq(equalityOperation, slowPath)
753     traceExecution()
754     loadisFromInstruction(3, t0)
755     loadisFromInstruction(2, t2)
756     loadConstantOrVariable(t0, t1)
757     loadConstantOrVariable(t2, t0)
758     move t0, t2
759     orq t1, t2
760     btqz t2, tagMask, .slow
761     bqaeq t0, tagTypeNumber, .leftOK
762     btqnz t0, tagTypeNumber, .slow
763 .leftOK:
764     bqaeq t1, tagTypeNumber, .rightOK
765     btqnz t1, tagTypeNumber, .slow
766 .rightOK:
767     equalityOperation(t0, t1, t0)
768     loadisFromInstruction(1, t1)
769     orq ValueFalse, t0
770     storeq t0, [cfr, t1, 8]
771     dispatch(4)
772
773 .slow:
774     callSlowPath(slowPath)
775     dispatch(4)
776 end
777
778 _llint_op_stricteq:
779     strictEq(
780         macro (left, right, result) cqeq left, right, result end,
781         _slow_path_stricteq)
782
783
784 _llint_op_nstricteq:
785     strictEq(
786         macro (left, right, result) cqneq left, right, result end,
787         _slow_path_nstricteq)
788
789
790 macro preOp(arithmeticOperation, slowPath)
791     traceExecution()
792     loadisFromInstruction(1, t0)
793     loadq [cfr, t0, 8], t1
794     bqb t1, tagTypeNumber, .slow
795     arithmeticOperation(t1, .slow)
796     orq tagTypeNumber, t1
797     storeq t1, [cfr, t0, 8]
798     dispatch(2)
799
800 .slow:
801     callSlowPath(slowPath)
802     dispatch(2)
803 end
804
805 _llint_op_inc:
806     preOp(
807         macro (value, slow) baddio 1, value, slow end,
808         _slow_path_inc)
809
810
811 _llint_op_dec:
812     preOp(
813         macro (value, slow) bsubio 1, value, slow end,
814         _slow_path_dec)
815
816
817 _llint_op_to_number:
818     traceExecution()
819     loadisFromInstruction(2, t0)
820     loadisFromInstruction(1, t1)
821     loadConstantOrVariable(t0, t2)
822     bqaeq t2, tagTypeNumber, .opToNumberIsImmediate
823     btqz t2, tagTypeNumber, .opToNumberSlow
824 .opToNumberIsImmediate:
825     storeq t2, [cfr, t1, 8]
826     dispatch(3)
827
828 .opToNumberSlow:
829     callSlowPath(_slow_path_to_number)
830     dispatch(3)
831
832
833 _llint_op_to_string:
834     traceExecution()
835     loadisFromInstruction(2, t1)
836     loadisFromInstruction(1, t2)
837     loadConstantOrVariable(t1, t0)
838     btqnz t0, tagMask, .opToStringSlow
839     bbneq JSCell::m_type[t0], StringType, .opToStringSlow
840 .opToStringIsString:
841     storeq t0, [cfr, t2, 8]
842     dispatch(3)
843
844 .opToStringSlow:
845     callSlowPath(_slow_path_to_string)
846     dispatch(3)
847
848
849 _llint_op_negate:
850     traceExecution()
851     loadisFromInstruction(2, t0)
852     loadisFromInstruction(1, t1)
853     loadConstantOrVariable(t0, t2)
854     bqb t2, tagTypeNumber, .opNegateNotInt
855     btiz t2, 0x7fffffff, .opNegateSlow
856     negi t2
857     orq tagTypeNumber, t2
858     storeq t2, [cfr, t1, 8]
859     dispatch(3)
860 .opNegateNotInt:
861     btqz t2, tagTypeNumber, .opNegateSlow
862     xorq 0x8000000000000000, t2
863     storeq t2, [cfr, t1, 8]
864     dispatch(3)
865
866 .opNegateSlow:
867     callSlowPath(_slow_path_negate)
868     dispatch(3)
869
870
871 macro binaryOpCustomStore(integerOperationAndStore, doubleOperation, slowPath)
872     loadisFromInstruction(3, t0)
873     loadisFromInstruction(2, t2)
874     loadConstantOrVariable(t0, t1)
875     loadConstantOrVariable(t2, t0)
876     bqb t0, tagTypeNumber, .op1NotInt
877     bqb t1, tagTypeNumber, .op2NotInt
878     loadisFromInstruction(1, t2)
879     integerOperationAndStore(t1, t0, .slow, t2)
880     dispatch(5)
881
882 .op1NotInt:
883     # First operand is definitely not an int, the second operand could be anything.
884     btqz t0, tagTypeNumber, .slow
885     bqaeq t1, tagTypeNumber, .op1NotIntOp2Int
886     btqz t1, tagTypeNumber, .slow
887     addq tagTypeNumber, t1
888     fq2d t1, ft1
889     jmp .op1NotIntReady
890 .op1NotIntOp2Int:
891     ci2d t1, ft1
892 .op1NotIntReady:
893     loadisFromInstruction(1, t2)
894     addq tagTypeNumber, t0
895     fq2d t0, ft0
896     doubleOperation(ft1, ft0)
897     fd2q ft0, t0
898     subq tagTypeNumber, t0
899     storeq t0, [cfr, t2, 8]
900     dispatch(5)
901
902 .op2NotInt:
903     # First operand is definitely an int, the second is definitely not.
904     loadisFromInstruction(1, t2)
905     btqz t1, tagTypeNumber, .slow
906     ci2d t0, ft0
907     addq tagTypeNumber, t1
908     fq2d t1, ft1
909     doubleOperation(ft1, ft0)
910     fd2q ft0, t0
911     subq tagTypeNumber, t0
912     storeq t0, [cfr, t2, 8]
913     dispatch(5)
914
915 .slow:
916     callSlowPath(slowPath)
917     dispatch(5)
918 end
919
920 macro binaryOp(integerOperation, doubleOperation, slowPath)
921     binaryOpCustomStore(
922         macro (left, right, slow, index)
923             integerOperation(left, right, slow)
924             orq tagTypeNumber, right
925             storeq right, [cfr, index, 8]
926         end,
927         doubleOperation, slowPath)
928 end
929
930 _llint_op_add:
931     traceExecution()
932     binaryOp(
933         macro (left, right, slow) baddio left, right, slow end,
934         macro (left, right) addd left, right end,
935         _slow_path_add)
936
937
938 _llint_op_mul:
939     traceExecution()
940     binaryOpCustomStore(
941         macro (left, right, slow, index)
942             # Assume t3 is scratchable.
943             move right, t3
944             bmulio left, t3, slow
945             btinz t3, .done
946             bilt left, 0, slow
947             bilt right, 0, slow
948         .done:
949             orq tagTypeNumber, t3
950             storeq t3, [cfr, index, 8]
951         end,
952         macro (left, right) muld left, right end,
953         _slow_path_mul)
954
955
956 _llint_op_sub:
957     traceExecution()
958     binaryOp(
959         macro (left, right, slow) bsubio left, right, slow end,
960         macro (left, right) subd left, right end,
961         _slow_path_sub)
962
963
964 _llint_op_div:
965     traceExecution()
966     if X86_64 or X86_64_WIN
967         binaryOpCustomStore(
968             macro (left, right, slow, index)
969                 # Assume t3 is scratchable.
970                 btiz left, slow
971                 bineq left, -1, .notNeg2TwoThe31DivByNeg1
972                 bieq right, -2147483648, .slow
973             .notNeg2TwoThe31DivByNeg1:
974                 btinz right, .intOK
975                 bilt left, 0, slow
976             .intOK:
977                 move left, t3
978                 move right, t0
979                 cdqi
980                 idivi t3
981                 btinz t1, slow
982                 orq tagTypeNumber, t0
983                 storeq t0, [cfr, index, 8]
984             end,
985             macro (left, right) divd left, right end,
986             _slow_path_div)
987     else
988         callSlowPath(_slow_path_div)
989         dispatch(5)
990     end
991
992
993 macro bitOp(operation, slowPath, advance)
994     loadisFromInstruction(3, t0)
995     loadisFromInstruction(2, t2)
996     loadisFromInstruction(1, t3)
997     loadConstantOrVariable(t0, t1)
998     loadConstantOrVariable(t2, t0)
999     bqb t0, tagTypeNumber, .slow
1000     bqb t1, tagTypeNumber, .slow
1001     operation(t1, t0)
1002     orq tagTypeNumber, t0
1003     storeq t0, [cfr, t3, 8]
1004     dispatch(advance)
1005
1006 .slow:
1007     callSlowPath(slowPath)
1008     dispatch(advance)
1009 end
1010
1011 _llint_op_lshift:
1012     traceExecution()
1013     bitOp(
1014         macro (left, right) lshifti left, right end,
1015         _slow_path_lshift,
1016         4)
1017
1018
1019 _llint_op_rshift:
1020     traceExecution()
1021     bitOp(
1022         macro (left, right) rshifti left, right end,
1023         _slow_path_rshift,
1024         4)
1025
1026
1027 _llint_op_urshift:
1028     traceExecution()
1029     bitOp(
1030         macro (left, right) urshifti left, right end,
1031         _slow_path_urshift,
1032         4)
1033
1034
1035 _llint_op_unsigned:
1036     traceExecution()
1037     loadisFromInstruction(1, t0)
1038     loadisFromInstruction(2, t1)
1039     loadConstantOrVariable(t1, t2)
1040     bilt t2, 0, .opUnsignedSlow
1041     storeq t2, [cfr, t0, 8]
1042     dispatch(3)
1043 .opUnsignedSlow:
1044     callSlowPath(_slow_path_unsigned)
1045     dispatch(3)
1046
1047
1048 _llint_op_bitand:
1049     traceExecution()
1050     bitOp(
1051         macro (left, right) andi left, right end,
1052         _slow_path_bitand,
1053         5)
1054
1055
1056 _llint_op_bitxor:
1057     traceExecution()
1058     bitOp(
1059         macro (left, right) xori left, right end,
1060         _slow_path_bitxor,
1061         5)
1062
1063
1064 _llint_op_bitor:
1065     traceExecution()
1066     bitOp(
1067         macro (left, right) ori left, right end,
1068         _slow_path_bitor,
1069         5)
1070
1071
1072 _llint_op_overrides_has_instance:
1073     traceExecution()
1074     loadisFromInstruction(1, t3)
1075
1076     loadisFromInstruction(3, t1)
1077     loadConstantOrVariable(t1, t0)
1078     loadp CodeBlock[cfr], t2
1079     loadp CodeBlock::m_globalObject[t2], t2
1080     loadp JSGlobalObject::m_functionProtoHasInstanceSymbolFunction[t2], t2
1081     bqneq t0, t2, .opOverridesHasInstanceNotDefaultSymbol
1082
1083     loadisFromInstruction(2, t1)
1084     loadConstantOrVariable(t1, t0)
1085     tbz JSCell::m_flags[t0], ImplementsDefaultHasInstance, t1
1086     orq ValueFalse, t1
1087     storeq t1, [cfr, t3, 8]
1088     dispatch(4)
1089
1090 .opOverridesHasInstanceNotDefaultSymbol:
1091     storeq ValueTrue, [cfr, t3, 8]
1092     dispatch(4)
1093
1094
1095 _llint_op_instanceof:
1096     traceExecution()
1097     # Actually do the work.
1098     loadisFromInstruction(3, t0)
1099     loadConstantOrVariableCell(t0, t1, .opInstanceofSlow)
1100     bbb JSCell::m_type[t1], ObjectType, .opInstanceofSlow
1101     loadisFromInstruction(2, t0)
1102     loadConstantOrVariableCell(t0, t2, .opInstanceofSlow)
1103     
1104     # Register state: t1 = prototype, t2 = value
1105     move 1, t0
1106 .opInstanceofLoop:
1107     loadStructureAndClobberFirstArg(t2, t3)
1108     loadq Structure::m_prototype[t3], t2
1109     bqeq t2, t1, .opInstanceofDone
1110     btqz t2, tagMask, .opInstanceofLoop
1111
1112     move 0, t0
1113 .opInstanceofDone:
1114     orq ValueFalse, t0
1115     loadisFromInstruction(1, t3)
1116     storeq t0, [cfr, t3, 8]
1117     dispatch(4)
1118
1119 .opInstanceofSlow:
1120     callSlowPath(_llint_slow_path_instanceof)
1121     dispatch(4)
1122
1123 _llint_op_instanceof_custom:
1124     traceExecution()
1125     callSlowPath(_llint_slow_path_instanceof_custom)
1126     dispatch(5)
1127
1128 _llint_op_is_undefined:
1129     traceExecution()
1130     loadisFromInstruction(2, t1)
1131     loadisFromInstruction(1, t2)
1132     loadConstantOrVariable(t1, t0)
1133     btqz t0, tagMask, .opIsUndefinedCell
1134     cqeq t0, ValueUndefined, t3
1135     orq ValueFalse, t3
1136     storeq t3, [cfr, t2, 8]
1137     dispatch(3)
1138 .opIsUndefinedCell:
1139     btbnz JSCell::m_flags[t0], MasqueradesAsUndefined, .masqueradesAsUndefined
1140     move ValueFalse, t1
1141     storeq t1, [cfr, t2, 8]
1142     dispatch(3)
1143 .masqueradesAsUndefined:
1144     loadStructureWithScratch(t0, t3, t1)
1145     loadp CodeBlock[cfr], t1
1146     loadp CodeBlock::m_globalObject[t1], t1
1147     cpeq Structure::m_globalObject[t3], t1, t0
1148     orq ValueFalse, t0
1149     storeq t0, [cfr, t2, 8]
1150     dispatch(3)
1151
1152
1153 _llint_op_is_boolean:
1154     traceExecution()
1155     loadisFromInstruction(2, t1)
1156     loadisFromInstruction(1, t2)
1157     loadConstantOrVariable(t1, t0)
1158     xorq ValueFalse, t0
1159     tqz t0, ~1, t0
1160     orq ValueFalse, t0
1161     storeq t0, [cfr, t2, 8]
1162     dispatch(3)
1163
1164
1165 _llint_op_is_number:
1166     traceExecution()
1167     loadisFromInstruction(2, t1)
1168     loadisFromInstruction(1, t2)
1169     loadConstantOrVariable(t1, t0)
1170     tqnz t0, tagTypeNumber, t1
1171     orq ValueFalse, t1
1172     storeq t1, [cfr, t2, 8]
1173     dispatch(3)
1174
1175
1176 _llint_op_is_string:
1177     traceExecution()
1178     loadisFromInstruction(2, t1)
1179     loadisFromInstruction(1, t2)
1180     loadConstantOrVariable(t1, t0)
1181     btqnz t0, tagMask, .opIsStringNotCell
1182     cbeq JSCell::m_type[t0], StringType, t1
1183     orq ValueFalse, t1
1184     storeq t1, [cfr, t2, 8]
1185     dispatch(3)
1186 .opIsStringNotCell:
1187     storeq ValueFalse, [cfr, t2, 8]
1188     dispatch(3)
1189
1190
1191 _llint_op_is_object:
1192     traceExecution()
1193     loadisFromInstruction(2, t1)
1194     loadisFromInstruction(1, t2)
1195     loadConstantOrVariable(t1, t0)
1196     btqnz t0, tagMask, .opIsObjectNotCell
1197     cbaeq JSCell::m_type[t0], ObjectType, t1
1198     orq ValueFalse, t1
1199     storeq t1, [cfr, t2, 8]
1200     dispatch(3)
1201 .opIsObjectNotCell:
1202     storeq ValueFalse, [cfr, t2, 8]
1203     dispatch(3)
1204
1205
1206 macro loadPropertyAtVariableOffset(propertyOffsetAsInt, objectAndStorage, value, slow)
1207     bilt propertyOffsetAsInt, firstOutOfLineOffset, .isInline
1208     loadp JSObject::m_butterfly[objectAndStorage], objectAndStorage
1209     copyBarrier(objectAndStorage, slow)
1210     negi propertyOffsetAsInt
1211     sxi2q propertyOffsetAsInt, propertyOffsetAsInt
1212     jmp .ready
1213 .isInline:
1214     addp sizeof JSObject - (firstOutOfLineOffset - 2) * 8, objectAndStorage
1215 .ready:
1216     loadq (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffsetAsInt, 8], value
1217 end
1218
1219
1220 macro storePropertyAtVariableOffset(propertyOffsetAsInt, objectAndStorage, value, slow)
1221     bilt propertyOffsetAsInt, firstOutOfLineOffset, .isInline
1222     loadp JSObject::m_butterfly[objectAndStorage], objectAndStorage
1223     copyBarrier(objectAndStorage, slow)
1224     negi propertyOffsetAsInt
1225     sxi2q propertyOffsetAsInt, propertyOffsetAsInt
1226     jmp .ready
1227 .isInline:
1228     addp sizeof JSObject - (firstOutOfLineOffset - 2) * 8, objectAndStorage
1229 .ready:
1230     storeq value, (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffsetAsInt, 8]
1231 end
1232
1233 _llint_op_get_by_id:
1234     traceExecution()
1235     loadisFromInstruction(2, t0)
1236     loadConstantOrVariableCell(t0, t3, .opGetByIdSlow)
1237     loadi JSCell::m_structureID[t3], t1
1238     loadisFromInstruction(4, t2)
1239     bineq t2, t1, .opGetByIdSlow
1240     loadisFromInstruction(5, t1)
1241     loadisFromInstruction(1, t2)
1242     loadPropertyAtVariableOffset(t1, t3, t0, .opGetByIdSlow)
1243     storeq t0, [cfr, t2, 8]
1244     valueProfile(t0, 8, t1)
1245     dispatch(9)
1246
1247 .opGetByIdSlow:
1248     callSlowPath(_llint_slow_path_get_by_id)
1249     dispatch(9)
1250
1251
1252 _llint_op_get_array_length:
1253     traceExecution()
1254     loadisFromInstruction(2, t0)
1255     loadpFromInstruction(4, t1)
1256     loadConstantOrVariableCell(t0, t3, .opGetArrayLengthSlow)
1257     move t3, t2
1258     arrayProfile(t2, t1, t0)
1259     btiz t2, IsArray, .opGetArrayLengthSlow
1260     btiz t2, IndexingShapeMask, .opGetArrayLengthSlow
1261     loadisFromInstruction(1, t1)
1262     loadp JSObject::m_butterfly[t3], t0
1263     copyBarrier(t0, .opGetArrayLengthSlow)
1264     loadi -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], t0
1265     bilt t0, 0, .opGetArrayLengthSlow
1266     orq tagTypeNumber, t0
1267     valueProfile(t0, 8, t2)
1268     storeq t0, [cfr, t1, 8]
1269     dispatch(9)
1270
1271 .opGetArrayLengthSlow:
1272     callSlowPath(_llint_slow_path_get_by_id)
1273     dispatch(9)
1274
1275
1276 _llint_op_put_by_id:
1277     traceExecution()
1278     writeBarrierOnOperands(1, 3)
1279     loadisFromInstruction(1, t3)
1280     loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
1281     loadisFromInstruction(4, t2)
1282     bineq t2, JSCell::m_structureID[t0], .opPutByIdSlow
1283
1284     # At this point, we have:
1285     # t2 -> current structure ID
1286     # t0 -> object base
1287
1288     loadisFromInstruction(3, t1)
1289     loadConstantOrVariable(t1, t3)
1290
1291     loadpFromInstruction(8, t1)
1292
1293     # At this point, we have:
1294     # t0 -> object base
1295     # t1 -> put by id flags
1296     # t2 -> current structure ID
1297     # t3 -> value to put
1298
1299     btpnz t1, PutByIdPrimaryTypeMask, .opPutByIdTypeCheckObjectWithStructureOrOther
1300
1301     # We have one of the non-structure type checks. Find out which one.
1302     andp PutByIdSecondaryTypeMask, t1
1303     bplt t1, PutByIdSecondaryTypeString, .opPutByIdTypeCheckLessThanString
1304
1305     # We are one of the following: String, Symbol, Object, ObjectOrOther, Top
1306     bplt t1, PutByIdSecondaryTypeObjectOrOther, .opPutByIdTypeCheckLessThanObjectOrOther
1307
1308     # We are either ObjectOrOther or Top.
1309     bpeq t1, PutByIdSecondaryTypeTop, .opPutByIdDoneCheckingTypes
1310
1311     # Check if we are ObjectOrOther.
1312     btqz t3, tagMask, .opPutByIdTypeCheckObject
1313 .opPutByIdTypeCheckOther:
1314     andq ~TagBitUndefined, t3
1315     bqeq t3, ValueNull, .opPutByIdDoneCheckingTypes
1316     jmp .opPutByIdSlow
1317
1318 .opPutByIdTypeCheckLessThanObjectOrOther:
1319     # We are either String, Symbol or Object.
1320     btqnz t3, tagMask, .opPutByIdSlow
1321     bpeq t1, PutByIdSecondaryTypeObject, .opPutByIdTypeCheckObject
1322     bpeq t1, PutByIdSecondaryTypeSymbol, .opPutByIdTypeCheckSymbol
1323     bbeq JSCell::m_type[t3], StringType, .opPutByIdDoneCheckingTypes
1324     jmp .opPutByIdSlow
1325 .opPutByIdTypeCheckObject:
1326     bbaeq JSCell::m_type[t3], ObjectType, .opPutByIdDoneCheckingTypes
1327     jmp .opPutByIdSlow
1328 .opPutByIdTypeCheckSymbol:
1329     bbeq JSCell::m_type[t3], SymbolType, .opPutByIdDoneCheckingTypes
1330     jmp .opPutByIdSlow
1331
1332 .opPutByIdTypeCheckLessThanString:
1333     # We are one of the following: Bottom, Boolean, Other, Int32, Number
1334     bplt t1, PutByIdSecondaryTypeInt32, .opPutByIdTypeCheckLessThanInt32
1335
1336     # We are either Int32 or Number.
1337     bpeq t1, PutByIdSecondaryTypeNumber, .opPutByIdTypeCheckNumber
1338
1339     bqaeq t3, tagTypeNumber, .opPutByIdDoneCheckingTypes
1340     jmp .opPutByIdSlow
1341
1342 .opPutByIdTypeCheckNumber:
1343     btqnz t3, tagTypeNumber, .opPutByIdDoneCheckingTypes
1344     jmp .opPutByIdSlow
1345
1346 .opPutByIdTypeCheckLessThanInt32:
1347     # We are one of the following: Bottom, Boolean, Other.
1348     bpneq t1, PutByIdSecondaryTypeBoolean, .opPutByIdTypeCheckBottomOrOther
1349     xorq ValueFalse, t3
1350     btqz t3, ~1, .opPutByIdDoneCheckingTypes
1351     jmp .opPutByIdSlow
1352
1353 .opPutByIdTypeCheckBottomOrOther:
1354     bpeq t1, PutByIdSecondaryTypeOther, .opPutByIdTypeCheckOther
1355     jmp .opPutByIdSlow
1356
1357 .opPutByIdTypeCheckObjectWithStructureOrOther:
1358     btqz t3, tagMask, .opPutByIdTypeCheckObjectWithStructure
1359     btpnz t1, PutByIdPrimaryTypeObjectWithStructureOrOther, .opPutByIdTypeCheckOther
1360     jmp .opPutByIdSlow
1361
1362 .opPutByIdTypeCheckObjectWithStructure:
1363     urshiftp 3, t1
1364     bineq t1, JSCell::m_structureID[t3], .opPutByIdSlow
1365
1366 .opPutByIdDoneCheckingTypes:
1367     loadisFromInstruction(6, t1)
1368     
1369     btiz t1, .opPutByIdNotTransition
1370
1371     # This is the transition case. t1 holds the new structureID. t2 holds the old structure ID.
1372     # If we have a chain, we need to check it. t0 is the base. We may clobber t1 to use it as
1373     # scratch.
1374     loadpFromInstruction(7, t3)
1375     btpz t3, .opPutByIdTransitionDirect
1376
1377     loadp StructureChain::m_vector[t3], t3
1378     assert(macro (ok) btpnz t3, ok end)
1379
1380     structureIDToStructureWithScratch(t2, t1)
1381     loadq Structure::m_prototype[t2], t2
1382     bqeq t2, ValueNull, .opPutByIdTransitionChainDone
1383 .opPutByIdTransitionChainLoop:
1384     # At this point, t2 contains a prototye, and [t3] contains the Structure* that we want that
1385     # prototype to have. We don't want to have to load the Structure* for t2. Instead, we load
1386     # the Structure* from [t3], and then we compare its id to the id in the header of t2.
1387     loadp [t3], t1
1388     loadi JSCell::m_structureID[t2], t2
1389     # Now, t1 has the Structure* and t2 has the StructureID that we want that Structure* to have.
1390     bineq t2, Structure::m_blob + StructureIDBlob::u.fields.structureID[t1], .opPutByIdSlow
1391     addp 8, t3
1392     loadq Structure::m_prototype[t1], t2
1393     bqneq t2, ValueNull, .opPutByIdTransitionChainLoop
1394
1395 .opPutByIdTransitionChainDone:
1396     # Reload the new structure, since we clobbered it above.
1397     loadisFromInstruction(6, t1)
1398
1399 .opPutByIdTransitionDirect:
1400     storei t1, JSCell::m_structureID[t0]
1401
1402 .opPutByIdNotTransition:
1403     # The only thing live right now is t0, which holds the base.
1404     loadisFromInstruction(3, t1)
1405     loadConstantOrVariable(t1, t2)
1406     loadisFromInstruction(5, t1)
1407     storePropertyAtVariableOffset(t1, t0, t2, .opPutByIdSlow)
1408     dispatch(9)
1409
1410 .opPutByIdSlow:
1411     callSlowPath(_llint_slow_path_put_by_id)
1412     dispatch(9)
1413
1414
1415 _llint_op_get_by_val:
1416     traceExecution()
1417     loadisFromInstruction(2, t2)
1418     loadConstantOrVariableCell(t2, t0, .opGetByValSlow)
1419     loadpFromInstruction(4, t3)
1420     move t0, t2
1421     arrayProfile(t2, t3, t1)
1422     loadisFromInstruction(3, t3)
1423     loadConstantOrVariableInt32(t3, t1, .opGetByValSlow)
1424     sxi2q t1, t1
1425     loadp JSObject::m_butterfly[t0], t3
1426     copyBarrier(t3, .opGetByValSlow)
1427     andi IndexingShapeMask, t2
1428     bieq t2, Int32Shape, .opGetByValIsContiguous
1429     bineq t2, ContiguousShape, .opGetByValNotContiguous
1430 .opGetByValIsContiguous:
1431
1432     biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t3], .opGetByValOutOfBounds
1433     loadisFromInstruction(1, t0)
1434     loadq [t3, t1, 8], t2
1435     btqz t2, .opGetByValOutOfBounds
1436     jmp .opGetByValDone
1437
1438 .opGetByValNotContiguous:
1439     bineq t2, DoubleShape, .opGetByValNotDouble
1440     biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t3], .opGetByValOutOfBounds
1441     loadis 8[PB, PC, 8], t0
1442     loadd [t3, t1, 8], ft0
1443     bdnequn ft0, ft0, .opGetByValOutOfBounds
1444     fd2q ft0, t2
1445     subq tagTypeNumber, t2
1446     jmp .opGetByValDone
1447     
1448 .opGetByValNotDouble:
1449     subi ArrayStorageShape, t2
1450     bia t2, SlowPutArrayStorageShape - ArrayStorageShape, .opGetByValSlow
1451     biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t3], .opGetByValOutOfBounds
1452     loadisFromInstruction(1, t0)
1453     loadq ArrayStorage::m_vector[t3, t1, 8], t2
1454     btqz t2, .opGetByValOutOfBounds
1455
1456 .opGetByValDone:
1457     storeq t2, [cfr, t0, 8]
1458     valueProfile(t2, 5, t0)
1459     dispatch(6)
1460
1461 .opGetByValOutOfBounds:
1462     loadpFromInstruction(4, t0)
1463     storeb 1, ArrayProfile::m_outOfBounds[t0]
1464 .opGetByValSlow:
1465     callSlowPath(_llint_slow_path_get_by_val)
1466     dispatch(6)
1467
1468
1469 macro contiguousPutByVal(storeCallback)
1470     biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], .outOfBounds
1471 .storeResult:
1472     loadisFromInstruction(3, t2)
1473     storeCallback(t2, t1, [t0, t3, 8])
1474     dispatch(5)
1475
1476 .outOfBounds:
1477     biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t0], .opPutByValOutOfBounds
1478     loadp 32[PB, PC, 8], t2
1479     storeb 1, ArrayProfile::m_mayStoreToHole[t2]
1480     addi 1, t3, t2
1481     storei t2, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0]
1482     jmp .storeResult
1483 end
1484
1485 macro putByVal(slowPath)
1486     traceExecution()
1487     writeBarrierOnOperands(1, 3)
1488     loadisFromInstruction(1, t0)
1489     loadConstantOrVariableCell(t0, t1, .opPutByValSlow)
1490     loadpFromInstruction(4, t3)
1491     move t1, t2
1492     arrayProfile(t2, t3, t0)
1493     loadisFromInstruction(2, t0)
1494     loadConstantOrVariableInt32(t0, t3, .opPutByValSlow)
1495     sxi2q t3, t3
1496     loadp JSObject::m_butterfly[t1], t0
1497     copyBarrier(t0, .opPutByValSlow)
1498     andi IndexingShapeMask, t2
1499     bineq t2, Int32Shape, .opPutByValNotInt32
1500     contiguousPutByVal(
1501         macro (operand, scratch, address)
1502             loadConstantOrVariable(operand, scratch)
1503             bpb scratch, tagTypeNumber, .opPutByValSlow
1504             storep scratch, address
1505         end)
1506
1507 .opPutByValNotInt32:
1508     bineq t2, DoubleShape, .opPutByValNotDouble
1509     contiguousPutByVal(
1510         macro (operand, scratch, address)
1511             loadConstantOrVariable(operand, scratch)
1512             bqb scratch, tagTypeNumber, .notInt
1513             ci2d scratch, ft0
1514             jmp .ready
1515         .notInt:
1516             addp tagTypeNumber, scratch
1517             fq2d scratch, ft0
1518             bdnequn ft0, ft0, .opPutByValSlow
1519         .ready:
1520             stored ft0, address
1521         end)
1522
1523 .opPutByValNotDouble:
1524     bineq t2, ContiguousShape, .opPutByValNotContiguous
1525     contiguousPutByVal(
1526         macro (operand, scratch, address)
1527             loadConstantOrVariable(operand, scratch)
1528             storep scratch, address
1529         end)
1530
1531 .opPutByValNotContiguous:
1532     bineq t2, ArrayStorageShape, .opPutByValSlow
1533     biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t0], .opPutByValOutOfBounds
1534     btqz ArrayStorage::m_vector[t0, t3, 8], .opPutByValArrayStorageEmpty
1535 .opPutByValArrayStorageStoreResult:
1536     loadisFromInstruction(3, t2)
1537     loadConstantOrVariable(t2, t1)
1538     storeq t1, ArrayStorage::m_vector[t0, t3, 8]
1539     dispatch(5)
1540
1541 .opPutByValArrayStorageEmpty:
1542     loadpFromInstruction(4, t1)
1543     storeb 1, ArrayProfile::m_mayStoreToHole[t1]
1544     addi 1, ArrayStorage::m_numValuesInVector[t0]
1545     bib t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], .opPutByValArrayStorageStoreResult
1546     addi 1, t3, t1
1547     storei t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0]
1548     jmp .opPutByValArrayStorageStoreResult
1549
1550 .opPutByValOutOfBounds:
1551     loadpFromInstruction(4, t0)
1552     storeb 1, ArrayProfile::m_outOfBounds[t0]
1553 .opPutByValSlow:
1554     callSlowPath(slowPath)
1555     dispatch(5)
1556 end
1557
1558 _llint_op_put_by_val:
1559     putByVal(_llint_slow_path_put_by_val)
1560
1561 _llint_op_put_by_val_direct:
1562     putByVal(_llint_slow_path_put_by_val_direct)
1563
1564
1565 _llint_op_jmp:
1566     traceExecution()
1567     dispatchIntIndirect(1)
1568
1569
1570 macro jumpTrueOrFalse(conditionOp, slow)
1571     loadisFromInstruction(1, t1)
1572     loadConstantOrVariable(t1, t0)
1573     xorq ValueFalse, t0
1574     btqnz t0, -1, .slow
1575     conditionOp(t0, .target)
1576     dispatch(3)
1577
1578 .target:
1579     dispatchIntIndirect(2)
1580
1581 .slow:
1582     callSlowPath(slow)
1583     dispatch(0)
1584 end
1585
1586
1587 macro equalNull(cellHandler, immediateHandler)
1588     loadisFromInstruction(1, t0)
1589     assertNotConstant(t0)
1590     loadq [cfr, t0, 8], t0
1591     btqnz t0, tagMask, .immediate
1592     loadStructureWithScratch(t0, t2, t1)
1593     cellHandler(t2, JSCell::m_flags[t0], .target)
1594     dispatch(3)
1595
1596 .target:
1597     dispatchIntIndirect(2)
1598
1599 .immediate:
1600     andq ~TagBitUndefined, t0
1601     immediateHandler(t0, .target)
1602     dispatch(3)
1603 end
1604
1605 _llint_op_jeq_null:
1606     traceExecution()
1607     equalNull(
1608         macro (structure, value, target) 
1609             btbz value, MasqueradesAsUndefined, .notMasqueradesAsUndefined
1610             loadp CodeBlock[cfr], t0
1611             loadp CodeBlock::m_globalObject[t0], t0
1612             bpeq Structure::m_globalObject[structure], t0, target
1613 .notMasqueradesAsUndefined:
1614         end,
1615         macro (value, target) bqeq value, ValueNull, target end)
1616
1617
1618 _llint_op_jneq_null:
1619     traceExecution()
1620     equalNull(
1621         macro (structure, value, target) 
1622             btbz value, MasqueradesAsUndefined, target
1623             loadp CodeBlock[cfr], t0
1624             loadp CodeBlock::m_globalObject[t0], t0
1625             bpneq Structure::m_globalObject[structure], t0, target
1626         end,
1627         macro (value, target) bqneq value, ValueNull, target end)
1628
1629
1630 _llint_op_jneq_ptr:
1631     traceExecution()
1632     loadisFromInstruction(1, t0)
1633     loadisFromInstruction(2, t1)
1634     loadp CodeBlock[cfr], t2
1635     loadp CodeBlock::m_globalObject[t2], t2
1636     loadp JSGlobalObject::m_specialPointers[t2, t1, 8], t1
1637     bpneq t1, [cfr, t0, 8], .opJneqPtrTarget
1638     dispatch(4)
1639
1640 .opJneqPtrTarget:
1641     dispatchIntIndirect(3)
1642
1643
1644 macro compare(integerCompare, doubleCompare, slowPath)
1645     loadisFromInstruction(1, t2)
1646     loadisFromInstruction(2, t3)
1647     loadConstantOrVariable(t2, t0)
1648     loadConstantOrVariable(t3, t1)
1649     bqb t0, tagTypeNumber, .op1NotInt
1650     bqb t1, tagTypeNumber, .op2NotInt
1651     integerCompare(t0, t1, .jumpTarget)
1652     dispatch(4)
1653
1654 .op1NotInt:
1655     btqz t0, tagTypeNumber, .slow
1656     bqb t1, tagTypeNumber, .op1NotIntOp2NotInt
1657     ci2d t1, ft1
1658     jmp .op1NotIntReady
1659 .op1NotIntOp2NotInt:
1660     btqz t1, tagTypeNumber, .slow
1661     addq tagTypeNumber, t1
1662     fq2d t1, ft1
1663 .op1NotIntReady:
1664     addq tagTypeNumber, t0
1665     fq2d t0, ft0
1666     doubleCompare(ft0, ft1, .jumpTarget)
1667     dispatch(4)
1668
1669 .op2NotInt:
1670     ci2d t0, ft0
1671     btqz t1, tagTypeNumber, .slow
1672     addq tagTypeNumber, t1
1673     fq2d t1, ft1
1674     doubleCompare(ft0, ft1, .jumpTarget)
1675     dispatch(4)
1676
1677 .jumpTarget:
1678     dispatchIntIndirect(3)
1679
1680 .slow:
1681     callSlowPath(slowPath)
1682     dispatch(0)
1683 end
1684
1685
1686 _llint_op_switch_imm:
1687     traceExecution()
1688     loadisFromInstruction(3, t2)
1689     loadisFromInstruction(1, t3)
1690     loadConstantOrVariable(t2, t1)
1691     loadp CodeBlock[cfr], t2
1692     loadp CodeBlock::m_rareData[t2], t2
1693     muli sizeof SimpleJumpTable, t3    # FIXME: would be nice to peephole this!
1694     loadp CodeBlock::RareData::m_switchJumpTables + VectorBufferOffset[t2], t2
1695     addp t3, t2
1696     bqb t1, tagTypeNumber, .opSwitchImmNotInt
1697     subi SimpleJumpTable::min[t2], t1
1698     biaeq t1, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchImmFallThrough
1699     loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t3
1700     loadis [t3, t1, 4], t1
1701     btiz t1, .opSwitchImmFallThrough
1702     dispatch(t1)
1703
1704 .opSwitchImmNotInt:
1705     btqnz t1, tagTypeNumber, .opSwitchImmSlow   # Go slow if it's a double.
1706 .opSwitchImmFallThrough:
1707     dispatchIntIndirect(2)
1708
1709 .opSwitchImmSlow:
1710     callSlowPath(_llint_slow_path_switch_imm)
1711     dispatch(0)
1712
1713
1714 _llint_op_switch_char:
1715     traceExecution()
1716     loadisFromInstruction(3, t2)
1717     loadisFromInstruction(1, t3)
1718     loadConstantOrVariable(t2, t1)
1719     loadp CodeBlock[cfr], t2
1720     loadp CodeBlock::m_rareData[t2], t2
1721     muli sizeof SimpleJumpTable, t3
1722     loadp CodeBlock::RareData::m_switchJumpTables + VectorBufferOffset[t2], t2
1723     addp t3, t2
1724     btqnz t1, tagMask, .opSwitchCharFallThrough
1725     bbneq JSCell::m_type[t1], StringType, .opSwitchCharFallThrough
1726     bineq JSString::m_length[t1], 1, .opSwitchCharFallThrough
1727     loadp JSString::m_value[t1], t0
1728     btpz  t0, .opSwitchOnRope
1729     loadp StringImpl::m_data8[t0], t1
1730     btinz StringImpl::m_hashAndFlags[t0], HashFlags8BitBuffer, .opSwitchChar8Bit
1731     loadh [t1], t0
1732     jmp .opSwitchCharReady
1733 .opSwitchChar8Bit:
1734     loadb [t1], t0
1735 .opSwitchCharReady:
1736     subi SimpleJumpTable::min[t2], t0
1737     biaeq t0, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchCharFallThrough
1738     loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t2
1739     loadis [t2, t0, 4], t1
1740     btiz t1, .opSwitchCharFallThrough
1741     dispatch(t1)
1742
1743 .opSwitchCharFallThrough:
1744     dispatchIntIndirect(2)
1745
1746 .opSwitchOnRope:
1747     callSlowPath(_llint_slow_path_switch_char)
1748     dispatch(0)
1749
1750
1751 macro arrayProfileForCall()
1752     loadisFromInstruction(4, t3)
1753     negp t3
1754     loadq ThisArgumentOffset[cfr, t3, 8], t0
1755     btqnz t0, tagMask, .done
1756     loadpFromInstruction((CallOpCodeSize - 2), t1)
1757     loadi JSCell::m_structureID[t0], t3
1758     storei t3, ArrayProfile::m_lastSeenStructureID[t1]
1759 .done:
1760 end
1761
1762 macro doCall(slowPath, prepareCall)
1763     loadisFromInstruction(2, t0)
1764     loadpFromInstruction(5, t1)
1765     loadp LLIntCallLinkInfo::callee[t1], t2
1766     loadConstantOrVariable(t0, t3)
1767     bqneq t3, t2, .opCallSlow
1768     loadisFromInstruction(4, t3)
1769     lshifti 3, t3
1770     negp t3
1771     addp cfr, t3
1772     storeq t2, Callee[t3]
1773     loadisFromInstruction(3, t2)
1774     storei PC, ArgumentCount + TagOffset[cfr]
1775     storei t2, ArgumentCount + PayloadOffset[t3]
1776     move t3, sp
1777     prepareCall(LLIntCallLinkInfo::machineCodeTarget[t1], t2, t3, t4)
1778     callTargetFunction(LLIntCallLinkInfo::machineCodeTarget[t1])
1779
1780 .opCallSlow:
1781     slowPathForCall(slowPath, prepareCall)
1782 end
1783
1784 _llint_op_ret:
1785     traceExecution()
1786     checkSwitchToJITForEpilogue()
1787     loadisFromInstruction(1, t2)
1788     loadConstantOrVariable(t2, r0)
1789     doReturn()
1790
1791
1792 _llint_op_to_primitive:
1793     traceExecution()
1794     loadisFromInstruction(2, t2)
1795     loadisFromInstruction(1, t3)
1796     loadConstantOrVariable(t2, t0)
1797     btqnz t0, tagMask, .opToPrimitiveIsImm
1798     bbaeq JSCell::m_type[t0], ObjectType, .opToPrimitiveSlowCase
1799 .opToPrimitiveIsImm:
1800     storeq t0, [cfr, t3, 8]
1801     dispatch(3)
1802
1803 .opToPrimitiveSlowCase:
1804     callSlowPath(_slow_path_to_primitive)
1805     dispatch(3)
1806
1807
1808 _llint_op_catch:
1809     # This is where we end up from the JIT's throw trampoline (because the
1810     # machine code return address will be set to _llint_op_catch), and from
1811     # the interpreter's throw trampoline (see _llint_throw_trampoline).
1812     # The throwing code must have known that we were throwing to the interpreter,
1813     # and have set VM::targetInterpreterPCForThrow.
1814     loadp Callee[cfr], t3
1815     andp MarkedBlockMask, t3
1816     loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
1817     restoreCalleeSavesFromVMCalleeSavesBuffer(t3, t0)
1818     loadp VM::callFrameForCatch[t3], cfr
1819     storep 0, VM::callFrameForCatch[t3]
1820     restoreStackPointerAfterCall()
1821
1822     loadp CodeBlock[cfr], PB
1823     loadp CodeBlock::m_instructions[PB], PB
1824     loadp VM::targetInterpreterPCForThrow[t3], PC
1825     subp PB, PC
1826     rshiftp 3, PC
1827
1828     callSlowPath(_llint_slow_path_check_if_exception_is_uncatchable_and_notify_profiler)
1829     bpeq r1, 0, .isCatchableException
1830     jmp _llint_throw_from_slow_path_trampoline
1831
1832 .isCatchableException:
1833     loadp Callee[cfr], t3
1834     andp MarkedBlockMask, t3
1835     loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
1836
1837     loadq VM::m_exception[t3], t0
1838     storeq 0, VM::m_exception[t3]
1839     loadisFromInstruction(1, t2)
1840     storeq t0, [cfr, t2, 8]
1841
1842     loadq Exception::m_value[t0], t3
1843     loadisFromInstruction(2, t2)
1844     storeq t3, [cfr, t2, 8]
1845
1846     traceExecution()
1847     dispatch(3)
1848
1849
1850 _llint_op_end:
1851     traceExecution()
1852     checkSwitchToJITForEpilogue()
1853     loadisFromInstruction(1, t0)
1854     assertNotConstant(t0)
1855     loadq [cfr, t0, 8], r0
1856     doReturn()
1857
1858
1859 _llint_throw_from_slow_path_trampoline:
1860     loadp Callee[cfr], t1
1861     andp MarkedBlockMask, t1
1862     loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t1], t1
1863     copyCalleeSavesToVMCalleeSavesBuffer(t1, t2)
1864
1865     callSlowPath(_llint_slow_path_handle_exception)
1866
1867     # When throwing from the interpreter (i.e. throwing from LLIntSlowPaths), so
1868     # the throw target is not necessarily interpreted code, we come to here.
1869     # This essentially emulates the JIT's throwing protocol.
1870     loadp Callee[cfr], t1
1871     andp MarkedBlockMask, t1
1872     loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t1], t1
1873     jmp VM::targetMachinePCForThrow[t1]
1874
1875
1876 _llint_throw_during_call_trampoline:
1877     preserveReturnAddressAfterCall(t2)
1878     jmp _llint_throw_from_slow_path_trampoline
1879
1880
1881 macro nativeCallTrampoline(executableOffsetToFunction)
1882
1883     functionPrologue()
1884     storep 0, CodeBlock[cfr]
1885     loadp Callee[cfr], t0
1886     andp MarkedBlockMask, t0, t1
1887     loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t1], t1
1888     storep cfr, VM::topCallFrame[t1]
1889     if ARM64 or C_LOOP
1890         storep lr, ReturnPC[cfr]
1891     end
1892     move cfr, a0
1893     loadp Callee[cfr], t1
1894     loadp JSFunction::m_executable[t1], t1
1895     checkStackPointerAlignment(t3, 0xdead0001)
1896     if C_LOOP
1897         cloopCallNative executableOffsetToFunction[t1]
1898     else
1899         if X86_64_WIN
1900             subp 32, sp
1901         end
1902         call executableOffsetToFunction[t1]
1903         if X86_64_WIN
1904             addp 32, sp
1905         end
1906     end
1907     loadp Callee[cfr], t3
1908     andp MarkedBlockMask, t3
1909     loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
1910
1911     functionEpilogue()
1912
1913     btqnz VM::m_exception[t3], .handleException
1914     ret
1915
1916 .handleException:
1917     storep cfr, VM::topCallFrame[t3]
1918     restoreStackPointerAfterCall()
1919     jmp _llint_throw_from_slow_path_trampoline
1920 end
1921
1922 macro getConstantScope(dst)
1923     loadpFromInstruction(6, t0)
1924     loadisFromInstruction(dst, t1)
1925     storeq t0, [cfr, t1, 8]
1926 end
1927
1928 macro varInjectionCheck(slowPath)
1929     loadp CodeBlock[cfr], t0
1930     loadp CodeBlock::m_globalObject[t0], t0
1931     loadp JSGlobalObject::m_varInjectionWatchpoint[t0], t0
1932     bbeq WatchpointSet::m_state[t0], IsInvalidated, slowPath
1933 end
1934
1935 macro resolveScope()
1936     loadisFromInstruction(5, t2)
1937     loadisFromInstruction(2, t0)
1938     loadp [cfr, t0, 8], t0
1939     btiz t2, .resolveScopeLoopEnd
1940
1941 .resolveScopeLoop:
1942     loadp JSScope::m_next[t0], t0
1943     subi 1, t2
1944     btinz t2, .resolveScopeLoop
1945
1946 .resolveScopeLoopEnd:
1947     loadisFromInstruction(1, t1)
1948     storeq t0, [cfr, t1, 8]
1949 end
1950
1951
1952 _llint_op_resolve_scope:
1953     traceExecution()
1954     loadisFromInstruction(4, t0)
1955
1956 #rGlobalProperty:
1957     bineq t0, GlobalProperty, .rGlobalVar
1958     getConstantScope(1)
1959     dispatch(7)
1960
1961 .rGlobalVar:
1962     bineq t0, GlobalVar, .rGlobalLexicalVar
1963     getConstantScope(1)
1964     dispatch(7)
1965
1966 .rGlobalLexicalVar:
1967     bineq t0, GlobalLexicalVar, .rClosureVar
1968     getConstantScope(1)
1969     dispatch(7)
1970
1971 .rClosureVar:
1972     bineq t0, ClosureVar, .rModuleVar
1973     resolveScope()
1974     dispatch(7)
1975
1976 .rModuleVar:
1977     bineq t0, ModuleVar, .rGlobalPropertyWithVarInjectionChecks
1978     getConstantScope(1)
1979     dispatch(7)
1980
1981 .rGlobalPropertyWithVarInjectionChecks:
1982     bineq t0, GlobalPropertyWithVarInjectionChecks, .rGlobalVarWithVarInjectionChecks
1983     varInjectionCheck(.rDynamic)
1984     getConstantScope(1)
1985     dispatch(7)
1986
1987 .rGlobalVarWithVarInjectionChecks:
1988     bineq t0, GlobalVarWithVarInjectionChecks, .rGlobalLexicalVarWithVarInjectionChecks
1989     varInjectionCheck(.rDynamic)
1990     getConstantScope(1)
1991     dispatch(7)
1992
1993 .rGlobalLexicalVarWithVarInjectionChecks:
1994     bineq t0, GlobalLexicalVarWithVarInjectionChecks, .rClosureVarWithVarInjectionChecks
1995     varInjectionCheck(.rDynamic)
1996     getConstantScope(1)
1997     dispatch(7)
1998
1999 .rClosureVarWithVarInjectionChecks:
2000     bineq t0, ClosureVarWithVarInjectionChecks, .rDynamic
2001     varInjectionCheck(.rDynamic)
2002     resolveScope()
2003     dispatch(7)
2004
2005 .rDynamic:
2006     callSlowPath(_slow_path_resolve_scope)
2007     dispatch(7)
2008
2009
2010 macro loadWithStructureCheck(operand, slowPath)
2011     loadisFromInstruction(operand, t0)
2012     loadq [cfr, t0, 8], t0
2013     loadStructureWithScratch(t0, t2, t1)
2014     loadpFromInstruction(5, t1)
2015     bpneq t2, t1, slowPath
2016 end
2017
2018 macro getProperty(slow)
2019     loadisFromInstruction(6, t1)
2020     loadPropertyAtVariableOffset(t1, t0, t2, slow)
2021     valueProfile(t2, 7, t0)
2022     loadisFromInstruction(1, t0)
2023     storeq t2, [cfr, t0, 8]
2024 end
2025
2026 macro getGlobalVar(tdzCheckIfNecessary)
2027     loadpFromInstruction(6, t0)
2028     loadq [t0], t0
2029     tdzCheckIfNecessary(t0)
2030     valueProfile(t0, 7, t1)
2031     loadisFromInstruction(1, t1)
2032     storeq t0, [cfr, t1, 8]
2033 end
2034
2035 macro getClosureVar()
2036     loadisFromInstruction(6, t1)
2037     loadq JSEnvironmentRecord_variables[t0, t1, 8], t0
2038     valueProfile(t0, 7, t1)
2039     loadisFromInstruction(1, t1)
2040     storeq t0, [cfr, t1, 8]
2041 end
2042
2043 _llint_op_get_from_scope:
2044     traceExecution()
2045     loadisFromInstruction(4, t0)
2046     andi ResolveTypeMask, t0
2047
2048 #gGlobalProperty:
2049     bineq t0, GlobalProperty, .gGlobalVar
2050     loadWithStructureCheck(2, .gDynamic)
2051     getProperty(.gDynamic)
2052     dispatch(8)
2053
2054 .gGlobalVar:
2055     bineq t0, GlobalVar, .gGlobalLexicalVar
2056     getGlobalVar(macro(v) end)
2057     dispatch(8)
2058
2059 .gGlobalLexicalVar:
2060     bineq t0, GlobalLexicalVar, .gClosureVar
2061     getGlobalVar(
2062         macro (value)
2063             bqeq value, ValueEmpty, .gDynamic
2064         end)
2065     dispatch(8)
2066
2067 .gClosureVar:
2068     bineq t0, ClosureVar, .gGlobalPropertyWithVarInjectionChecks
2069     loadVariable(2, t0)
2070     getClosureVar()
2071     dispatch(8)
2072
2073 .gGlobalPropertyWithVarInjectionChecks:
2074     bineq t0, GlobalPropertyWithVarInjectionChecks, .gGlobalVarWithVarInjectionChecks
2075     loadWithStructureCheck(2, .gDynamic)
2076     getProperty(.gDynamic)
2077     dispatch(8)
2078
2079 .gGlobalVarWithVarInjectionChecks:
2080     bineq t0, GlobalVarWithVarInjectionChecks, .gGlobalLexicalVarWithVarInjectionChecks
2081     varInjectionCheck(.gDynamic)
2082     getGlobalVar(macro(v) end)
2083     dispatch(8)
2084
2085 .gGlobalLexicalVarWithVarInjectionChecks:
2086     bineq t0, GlobalLexicalVarWithVarInjectionChecks, .gClosureVarWithVarInjectionChecks
2087     varInjectionCheck(.gDynamic)
2088     getGlobalVar(
2089         macro (value)
2090             bqeq value, ValueEmpty, .gDynamic
2091         end)
2092     dispatch(8)
2093
2094 .gClosureVarWithVarInjectionChecks:
2095     bineq t0, ClosureVarWithVarInjectionChecks, .gDynamic
2096     varInjectionCheck(.gDynamic)
2097     loadVariable(2, t0)
2098     getClosureVar()
2099     dispatch(8)
2100
2101 .gDynamic:
2102     callSlowPath(_llint_slow_path_get_from_scope)
2103     dispatch(8)
2104
2105
2106 macro putProperty(slow)
2107     loadisFromInstruction(3, t1)
2108     loadConstantOrVariable(t1, t2)
2109     loadisFromInstruction(6, t1)
2110     storePropertyAtVariableOffset(t1, t0, t2, slow)
2111 end
2112
2113 macro putGlobalVariable()
2114     loadisFromInstruction(3, t0)
2115     loadConstantOrVariable(t0, t1)
2116     loadpFromInstruction(5, t2)
2117     loadpFromInstruction(6, t0)
2118     notifyWrite(t2, .pDynamic)
2119     storeq t1, [t0]
2120 end
2121
2122 macro putClosureVar()
2123     loadisFromInstruction(3, t1)
2124     loadConstantOrVariable(t1, t2)
2125     loadisFromInstruction(6, t1)
2126     storeq t2, JSEnvironmentRecord_variables[t0, t1, 8]
2127 end
2128
2129 macro putLocalClosureVar()
2130     loadisFromInstruction(3, t1)
2131     loadConstantOrVariable(t1, t2)
2132     loadpFromInstruction(5, t3)
2133     btpz t3, .noVariableWatchpointSet
2134     notifyWrite(t3, .pDynamic)
2135 .noVariableWatchpointSet:
2136     loadisFromInstruction(6, t1)
2137     storeq t2, JSEnvironmentRecord_variables[t0, t1, 8]
2138 end
2139
2140 macro checkTDZInGlobalPutToScopeIfNecessary()
2141     loadisFromInstruction(4, t0)
2142     andi InitializationModeMask, t0
2143     rshifti InitializationModeShift, t0
2144     bieq t0, Initialization, .noNeedForTDZCheck
2145     loadpFromInstruction(6, t0)
2146     loadq [t0], t0
2147     bqeq t0, ValueEmpty, .pDynamic
2148 .noNeedForTDZCheck:
2149 end
2150
2151
2152 _llint_op_put_to_scope:
2153     traceExecution()
2154     loadisFromInstruction(4, t0)
2155     andi ResolveTypeMask, t0
2156
2157 #pLocalClosureVar:
2158     bineq t0, LocalClosureVar, .pGlobalProperty
2159     writeBarrierOnOperands(1, 3)
2160     loadVariable(1, t0)
2161     putLocalClosureVar()
2162     dispatch(7)
2163
2164 .pGlobalProperty:
2165     bineq t0, GlobalProperty, .pGlobalVar
2166     writeBarrierOnOperands(1, 3)
2167     loadWithStructureCheck(1, .pDynamic)
2168     putProperty(.pDynamic)
2169     dispatch(7)
2170
2171 .pGlobalVar:
2172     bineq t0, GlobalVar, .pGlobalLexicalVar
2173     writeBarrierOnGlobalObject(3)
2174     putGlobalVariable()
2175     dispatch(7)
2176
2177 .pGlobalLexicalVar:
2178     bineq t0, GlobalLexicalVar, .pClosureVar
2179     writeBarrierOnGlobalLexicalEnvironment(3)
2180     checkTDZInGlobalPutToScopeIfNecessary()
2181     putGlobalVariable()
2182     dispatch(7)
2183
2184 .pClosureVar:
2185     bineq t0, ClosureVar, .pGlobalPropertyWithVarInjectionChecks
2186     writeBarrierOnOperands(1, 3)
2187     loadVariable(1, t0)
2188     putClosureVar()
2189     dispatch(7)
2190
2191 .pGlobalPropertyWithVarInjectionChecks:
2192     bineq t0, GlobalPropertyWithVarInjectionChecks, .pGlobalVarWithVarInjectionChecks
2193     writeBarrierOnOperands(1, 3)
2194     loadWithStructureCheck(1, .pDynamic)
2195     putProperty(.pDynamic)
2196     dispatch(7)
2197
2198 .pGlobalVarWithVarInjectionChecks:
2199     bineq t0, GlobalVarWithVarInjectionChecks, .pGlobalLexicalVarWithVarInjectionChecks
2200     writeBarrierOnGlobalObject(3)
2201     varInjectionCheck(.pDynamic)
2202     putGlobalVariable()
2203     dispatch(7)
2204
2205 .pGlobalLexicalVarWithVarInjectionChecks:
2206     bineq t0, GlobalLexicalVarWithVarInjectionChecks, .pClosureVarWithVarInjectionChecks
2207     writeBarrierOnGlobalLexicalEnvironment(3)
2208     varInjectionCheck(.pDynamic)
2209     checkTDZInGlobalPutToScopeIfNecessary()
2210     putGlobalVariable()
2211     dispatch(7)
2212
2213 .pClosureVarWithVarInjectionChecks:
2214     bineq t0, ClosureVarWithVarInjectionChecks, .pModuleVar
2215     writeBarrierOnOperands(1, 3)
2216     varInjectionCheck(.pDynamic)
2217     loadVariable(1, t0)
2218     putClosureVar()
2219     dispatch(7)
2220
2221 .pModuleVar:
2222     bineq t0, ModuleVar, .pDynamic
2223     callSlowPath(_slow_path_throw_strict_mode_readonly_property_write_error)
2224     dispatch(7)
2225
2226 .pDynamic:
2227     callSlowPath(_llint_slow_path_put_to_scope)
2228     dispatch(7)
2229
2230
2231 _llint_op_get_from_arguments:
2232     traceExecution()
2233     loadVariable(2, t0)
2234     loadi 24[PB, PC, 8], t1
2235     loadq DirectArguments_storage[t0, t1, 8], t0
2236     valueProfile(t0, 4, t1)
2237     loadisFromInstruction(1, t1)
2238     storeq t0, [cfr, t1, 8]
2239     dispatch(5)
2240
2241
2242 _llint_op_put_to_arguments:
2243     traceExecution()
2244     writeBarrierOnOperands(1, 3)
2245     loadVariable(1, t0)
2246     loadi 16[PB, PC, 8], t1
2247     loadisFromInstruction(3, t3)
2248     loadConstantOrVariable(t3, t2)
2249     storeq t2, DirectArguments_storage[t0, t1, 8]
2250     dispatch(4)
2251
2252
2253 _llint_op_get_parent_scope:
2254     traceExecution()
2255     loadVariable(2, t0)
2256     loadp JSScope::m_next[t0], t0
2257     loadisFromInstruction(1, t1)
2258     storeq t0, [cfr, t1, 8]
2259     dispatch(3)
2260
2261
2262 _llint_op_profile_type:
2263     traceExecution()
2264     loadp CodeBlock[cfr], t1
2265     loadp CodeBlock::m_vm[t1], t1
2266     # t1 is holding the pointer to the typeProfilerLog.
2267     loadp VM::m_typeProfilerLog[t1], t1
2268     # t2 is holding the pointer to the current log entry.
2269     loadp TypeProfilerLog::m_currentLogEntryPtr[t1], t2
2270
2271     # t0 is holding the JSValue argument.
2272     loadisFromInstruction(1, t3)
2273     loadConstantOrVariable(t3, t0)
2274
2275     bqeq t0, ValueEmpty, .opProfileTypeDone
2276     # Store the JSValue onto the log entry.
2277     storeq t0, TypeProfilerLog::LogEntry::value[t2]
2278     
2279     # Store the TypeLocation onto the log entry.
2280     loadpFromInstruction(2, t3)
2281     storep t3, TypeProfilerLog::LogEntry::location[t2]
2282
2283     btqz t0, tagMask, .opProfileTypeIsCell
2284     storei 0, TypeProfilerLog::LogEntry::structureID[t2]
2285     jmp .opProfileTypeSkipIsCell
2286 .opProfileTypeIsCell:
2287     loadi JSCell::m_structureID[t0], t3
2288     storei t3, TypeProfilerLog::LogEntry::structureID[t2]
2289 .opProfileTypeSkipIsCell:
2290     
2291     # Increment the current log entry.
2292     addp sizeof TypeProfilerLog::LogEntry, t2
2293     storep t2, TypeProfilerLog::m_currentLogEntryPtr[t1]
2294
2295     loadp TypeProfilerLog::m_logEndPtr[t1], t1
2296     bpneq t2, t1, .opProfileTypeDone
2297     callSlowPath(_slow_path_profile_type_clear_log)
2298
2299 .opProfileTypeDone:
2300     dispatch(6)
2301
2302 _llint_op_profile_control_flow:
2303     traceExecution()
2304     loadpFromInstruction(1, t0)
2305     addq 1, BasicBlockLocation::m_executionCount[t0]
2306     dispatch(2)
2307
2308
2309 _llint_op_get_rest_length:
2310     traceExecution()
2311     loadi PayloadOffset + ArgumentCount[cfr], t0
2312     subi 1, t0
2313     loadisFromInstruction(2, t1)
2314     bilteq t0, t1, .storeZero
2315     subi t1, t0
2316     jmp .boxUp
2317 .storeZero:
2318     move 0, t0
2319 .boxUp:
2320     orq tagTypeNumber, t0
2321     loadisFromInstruction(1, t1)
2322     storeq t0, [cfr, t1, 8]
2323     dispatch(3)