FTL arity fixup should work on ARM64
[WebKit-https.git] / Source / JavaScriptCore / llint / LowLevelInterpreter64.asm
1 # Copyright (C) 2011, 2012, 2013, 2014 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 t0, [cfr, t1, 8]
50     valueProfile(t0, (CallOpCodeSize - 1), t2)
51     dispatch(CallOpCodeSize)
52 end
53
54 macro cCall2(function, arg1, arg2)
55     checkStackPointerAlignment(t4, 0xbad0c002)
56     if X86_64
57         move arg1, t4
58         move arg2, t5
59         call function
60     elsif ARM64
61         move arg1, t0
62         move arg2, t1
63         call function
64     elsif C_LOOP
65         cloopCallSlowPath function, arg1, arg2
66     else
67         error
68     end
69 end
70
71 macro cCall2Void(function, arg1, arg2)
72     if C_LOOP
73         cloopCallSlowPathVoid function, arg1, arg2
74     else
75         cCall2(function, arg1, arg2)
76     end
77 end
78
79 # This barely works. arg3 and arg4 should probably be immediates.
80 macro cCall4(function, arg1, arg2, arg3, arg4)
81     checkStackPointerAlignment(t4, 0xbad0c004)
82     if X86_64
83         move arg1, t4
84         move arg2, t5
85         move arg3, t1
86         move arg4, t2
87         call function
88     elsif ARM64
89         move arg1, t0
90         move arg2, t1
91         move arg3, t2
92         move arg4, t3
93         call function
94     elsif C_LOOP
95         error
96     else
97         error
98     end
99 end
100
101 macro doCallToJavaScript(makeCall)
102     if X86_64
103         const entry = t4
104         const vm = t5
105         const protoCallFrame = t1
106
107         const previousCFR = t0
108         const previousPC = t6
109         const temp1 = t0
110         const temp2 = t3
111         const temp3 = t6
112     elsif ARM64 or C_LOOP
113         const entry = a0
114         const vm = a1
115         const protoCallFrame = a2
116
117         const previousCFR = t5
118         const previousPC = lr
119         const temp1 = t3
120         const temp2 = t4
121         const temp3 = t6
122     end
123
124     callToJavaScriptPrologue()
125
126     if X86_64
127         loadp 7*8[sp], previousPC
128         move 6*8[sp], previousCFR
129     elsif ARM64
130         move cfr, previousCFR
131     end
132
133     checkStackPointerAlignment(temp2, 0xbad0dc01)
134
135     # The stack reserved zone ensures that we have adequate space for the
136     # VMEntrySentinelFrame. Proceed with allocating and initializing the
137     # sentinel frame.
138     move sp, cfr
139     subp CallFrameHeaderSlots * 8, cfr
140     storep 0, ArgumentCount[cfr]
141     storep vm, Callee[cfr]
142     loadp VM::topCallFrame[vm], temp2
143     storep temp2, ScopeChain[cfr]
144     storep 1, CodeBlock[cfr]
145     if X86_64
146         loadp 7*8[sp], previousPC
147         loadp 6*8[sp], previousCFR
148     end
149     storep previousPC, ReturnPC[cfr]
150     storep previousCFR, CallerFrame[cfr]
151
152     loadi ProtoCallFrame::paddedArgCount[protoCallFrame], temp2
153     addp CallFrameHeaderSlots, temp2, temp2
154     lshiftp 3, temp2
155     subp cfr, temp2, temp1
156
157     # Ensure that we have enough additional stack capacity for the incoming args,
158     # and the frame for the JS code we're executing. We need to do this check
159     # before we start copying the args from the protoCallFrame below.
160     bpaeq temp1, VM::m_jsStackLimit[vm], .stackHeightOK
161
162     move cfr, sp
163
164     if C_LOOP
165         move entry, temp2
166         move vm, temp3
167         cloopCallSlowPath _llint_stack_check_at_vm_entry, vm, temp1
168         bpeq t0, 0, .stackCheckFailed
169         move temp2, entry
170         move temp3, vm
171         jmp .stackHeightOK
172
173 .stackCheckFailed:
174         move temp2, entry
175         move temp3, vm
176     end
177
178     cCall2(_llint_throw_stack_overflow_error, vm, protoCallFrame)
179     callToJavaScriptEpilogue()
180     ret
181
182 .stackHeightOK:
183     move temp1, sp
184     move 5, temp1
185
186 .copyHeaderLoop:
187     subi 1, temp1
188     loadq [protoCallFrame, temp1, 8], temp3
189     storeq temp3, CodeBlock[sp, temp1, 8]
190     btinz temp1, .copyHeaderLoop
191
192     loadi ProtoCallFrame::argCountAndCodeOriginValue[protoCallFrame], temp2
193     subi 1, temp2
194     loadi ProtoCallFrame::paddedArgCount[protoCallFrame], temp3
195     subi 1, temp3
196
197     bieq temp2, temp3, .copyArgs
198     move ValueUndefined, temp1
199 .fillExtraArgsLoop:
200     subi 1, temp3
201     storeq temp1, ThisArgumentOffset + 8[sp, temp3, 8]
202     bineq temp2, temp3, .fillExtraArgsLoop
203
204 .copyArgs:
205     loadp ProtoCallFrame::args[protoCallFrame], temp1
206
207 .copyArgsLoop:
208     btiz temp2, .copyArgsDone
209     subi 1, temp2
210     loadq [temp1, temp2, 8], temp3
211     storeq temp3, ThisArgumentOffset + 8[sp, temp2, 8]
212     jmp .copyArgsLoop
213
214 .copyArgsDone:
215     if ARM64
216         move sp, temp2
217         storep temp2, VM::topCallFrame[vm]
218     else
219         storep sp, VM::topCallFrame[vm]
220     end
221
222     move 0xffff000000000000, csr1
223     addp 2, csr1, csr2
224
225     checkStackPointerAlignment(temp3, 0xbad0dc02)
226
227     makeCall(entry, temp1)
228
229     checkStackPointerAlignment(temp3, 0xbad0dc03)
230
231     bpeq CodeBlock[cfr], 1, .calleeFramePopped
232     loadp CallerFrame[cfr], cfr
233
234 .calleeFramePopped:
235     loadp Callee[cfr], temp2 # VM
236     loadp ScopeChain[cfr], temp3 # previous topCallFrame
237     storep temp3, VM::topCallFrame[temp2]
238
239     checkStackPointerAlignment(temp3, 0xbad0dc04)
240
241     if X86_64
242         pop t5
243     end
244     callToJavaScriptEpilogue()
245
246     ret
247 end
248
249
250 macro makeJavaScriptCall(entry, temp)
251     addp 16, sp
252     if C_LOOP
253         cloopCallJSFunction entry
254     else
255         call entry
256     end
257     subp 16, sp
258 end
259
260
261 macro makeHostFunctionCall(entry, temp)
262     move entry, temp
263     if X86_64
264         move sp, t4
265     elsif ARM64 or C_LOOP
266         move sp, a0
267     end
268     if C_LOOP
269         storep cfr, [sp]
270         storep lr, 8[sp]
271         cloopCallNative temp
272     else
273         addp 16, sp 
274         call temp
275         subp 16, sp
276     end
277 end
278
279
280 _handleUncaughtException:
281     loadp ScopeChain[cfr], t3
282     andp MarkedBlockMask, t3
283     loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
284     loadp VM::callFrameForThrow[t3], cfr
285
286     # So far, we've unwound the stack to the frame just below the sentinel frame, except
287     # in the case of stack overflow in the first function called from callToJavaScript.
288     # Check if we need to pop to the sentinel frame and do the necessary clean up for
289     # returning to the caller C frame.
290     bpeq CodeBlock[cfr], 1, .handleUncaughtExceptionAlreadyIsSentinel
291     loadp CallerFrame[cfr], cfr
292 .handleUncaughtExceptionAlreadyIsSentinel:
293
294     loadp Callee[cfr], t3 # VM
295     loadp ScopeChain[cfr], t5 # previous topCallFrame
296     storep t5, VM::topCallFrame[t3]
297
298     callToJavaScriptEpilogue()
299     ret
300
301
302 macro prepareStateForCCall()
303     leap [PB, PC, 8], PC
304     move PB, t3
305 end
306
307 macro restoreStateAfterCCall()
308     move t0, PC
309     move t3, PB
310     subp PB, PC
311     rshiftp 3, PC
312 end
313
314 macro callSlowPath(slowPath)
315     prepareStateForCCall()
316     cCall2(slowPath, cfr, PC)
317     restoreStateAfterCCall()
318 end
319
320 macro traceOperand(fromWhere, operand)
321     prepareStateForCCall()
322     cCall4(_llint_trace_operand, cfr, PC, fromWhere, operand)
323     restoreStateAfterCCall()
324 end
325
326 macro traceValue(fromWhere, operand)
327     prepareStateForCCall()
328     cCall4(_llint_trace_value, cfr, PC, fromWhere, operand)
329     restoreStateAfterCCall()
330 end
331
332 # Call a slow path for call call opcodes.
333 macro callCallSlowPath(slowPath, action)
334     storei PC, ArgumentCount + TagOffset[cfr]
335     prepareStateForCCall()
336     cCall2(slowPath, cfr, PC)
337     action(t0)
338 end
339
340 macro callWatchdogTimerHandler(throwHandler)
341     storei PC, ArgumentCount + TagOffset[cfr]
342     prepareStateForCCall()
343     cCall2(_llint_slow_path_handle_watchdog_timer, cfr, PC)
344     btpnz t0, throwHandler
345     move t3, PB
346     loadi ArgumentCount + TagOffset[cfr], PC
347 end
348
349 macro checkSwitchToJITForLoop()
350     checkSwitchToJIT(
351         1,
352         macro()
353             storei PC, ArgumentCount + TagOffset[cfr]
354             prepareStateForCCall()
355             cCall2(_llint_loop_osr, cfr, PC)
356             btpz t0, .recover
357             move t1, sp
358             jmp t0
359         .recover:
360             move t3, PB
361             loadi ArgumentCount + TagOffset[cfr], PC
362         end)
363 end
364
365 macro loadVariable(operand, value)
366     loadisFromInstruction(operand, value)
367     loadq [cfr, value, 8], value
368 end
369
370 # Index and value must be different registers. Index may be clobbered.
371 macro loadConstantOrVariable(index, value)
372     bpgteq index, FirstConstantRegisterIndex, .constant
373     loadq [cfr, index, 8], value
374     jmp .done
375 .constant:
376     loadp CodeBlock[cfr], value
377     loadp CodeBlock::m_constantRegisters + VectorBufferOffset[value], value
378     subp FirstConstantRegisterIndex, index
379     loadq [value, index, 8], value
380 .done:
381 end
382
383 macro loadConstantOrVariableInt32(index, value, slow)
384     loadConstantOrVariable(index, value)
385     bqb value, tagTypeNumber, slow
386 end
387
388 macro loadConstantOrVariableCell(index, value, slow)
389     loadConstantOrVariable(index, value)
390     btqnz value, tagMask, slow
391 end
392
393 macro writeBarrierOnOperand(cellOperand)
394     if GGC
395         loadisFromInstruction(cellOperand, t1)
396         loadConstantOrVariableCell(t1, t2, .writeBarrierDone)
397         checkMarkByte(t2, t1, t3, 
398             macro(gcData)
399                 btbnz gcData, .writeBarrierDone
400                 push PB, PC
401                 cCall2Void(_llint_write_barrier_slow, cfr, t2)
402                 pop PC, PB
403             end
404         )
405     .writeBarrierDone:
406     end
407 end
408
409 macro writeBarrierOnOperands(cellOperand, valueOperand)
410     if GGC
411         loadisFromInstruction(valueOperand, t1)
412         loadConstantOrVariableCell(t1, t0, .writeBarrierDone)
413         btpz t0, .writeBarrierDone
414     
415         writeBarrierOnOperand(cellOperand)
416     .writeBarrierDone:
417     end
418 end
419
420 macro writeBarrierOnGlobalObject(valueOperand)
421     if GGC
422         loadisFromInstruction(valueOperand, t1)
423         loadConstantOrVariableCell(t1, t0, .writeBarrierDone)
424         btpz t0, .writeBarrierDone
425     
426         loadp CodeBlock[cfr], t3
427         loadp CodeBlock::m_globalObject[t3], t3
428         checkMarkByte(t3, t1, t2,
429             macro(gcData)
430                 btbnz gcData, .writeBarrierDone
431                 push PB, PC
432                 cCall2Void(_llint_write_barrier_slow, cfr, t3)
433                 pop PC, PB
434             end
435         )
436     .writeBarrierDone:
437     end
438 end
439
440 macro valueProfile(value, operand, scratch)
441     loadpFromInstruction(operand, scratch)
442     storeq value, ValueProfile::m_buckets[scratch]
443 end
444
445 macro loadStructure(cell, structure)
446 end
447
448 macro loadStructureWithScratch(cell, structure, scratch)
449     loadp CodeBlock[cfr], scratch
450     loadp CodeBlock::m_vm[scratch], scratch
451     loadp VM::heap + Heap::m_structureIDTable + StructureIDTable::m_table[scratch], scratch
452     loadi JSCell::m_structureID[cell], structure
453     loadp [scratch, structure, 8], structure
454 end
455
456 macro loadStructureAndClobberFirstArg(cell, structure)
457     loadi JSCell::m_structureID[cell], structure
458     loadp CodeBlock[cfr], cell
459     loadp CodeBlock::m_vm[cell], cell
460     loadp VM::heap + Heap::m_structureIDTable + StructureIDTable::m_table[cell], cell
461     loadp [cell, structure, 8], structure
462 end
463
464 macro storeStructureWithTypeInfo(cell, structure, scratch)
465     loadq Structure::m_blob + StructureIDBlob::u.doubleWord[structure], scratch
466     storeq scratch, JSCell::m_structureID[cell]
467 end
468
469 # Entrypoints into the interpreter.
470
471 # Expects that CodeBlock is in t1, which is what prologue() leaves behind.
472 macro functionArityCheck(doneLabel, slowPath)
473     loadi PayloadOffset + ArgumentCount[cfr], t0
474     biaeq t0, CodeBlock::m_numParameters[t1], doneLabel
475     prepareStateForCCall()
476     cCall2(slowPath, cfr, PC)   # This slowPath has the protocol: t0 = 0 => no error, t0 != 0 => error
477     btiz t0, .noError
478     move t1, cfr   # t1 contains caller frame
479     jmp _llint_throw_from_slow_path_trampoline
480
481 .noError:
482     # t1 points to ArityCheckData.
483     loadp CommonSlowPaths::ArityCheckData::thunkToCall[t1], t2
484     btpz t2, .proceedInline
485     
486     loadp CommonSlowPaths::ArityCheckData::returnPC[t1], t7
487     loadp CommonSlowPaths::ArityCheckData::paddedStackSpace[t1], t0
488     call t2
489     if ASSERT_ENABLED
490         loadp ReturnPC[cfr], t0
491         loadp [t0], t0
492     end
493     jmp .continue
494
495 .proceedInline:
496     loadi CommonSlowPaths::ArityCheckData::paddedStackSpace[t1], t1
497     btiz t1, .continue
498
499     // Move frame up "t1 * 2" slots
500     lshiftp 1, t1
501     negq t1
502     move cfr, t3
503     loadi PayloadOffset + ArgumentCount[cfr], t2
504     addi CallFrameHeaderSlots, t2
505 .copyLoop:
506     loadq [t3], t0
507     storeq t0, [t3, t1, 8]
508     addp 8, t3
509     bsubinz 1, t2, .copyLoop
510
511     // Fill new slots with JSUndefined
512     move t1, t2
513     move ValueUndefined, t0
514 .fillLoop:
515     storeq t0, [t3, t1, 8]
516     addp 8, t3
517     baddinz 1, t2, .fillLoop
518
519     lshiftp 3, t1
520     addp t1, cfr
521     addp t1, sp
522
523 .continue:
524     # Reload CodeBlock and reset PC, since the slow_path clobbered them.
525     loadp CodeBlock[cfr], t1
526     loadp CodeBlock::m_instructions[t1], PB
527     move 0, PC
528     jmp doneLabel
529 end
530
531 macro branchIfException(label)
532     loadp ScopeChain[cfr], t3
533     andp MarkedBlockMask, t3
534     loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
535     btqz VM::m_exception[t3], .noException
536     jmp label
537 .noException:
538 end
539
540
541 # Instruction implementations
542
543 _llint_op_enter:
544     traceExecution()
545     checkStackPointerAlignment(t2, 0xdead00e1)
546     loadp CodeBlock[cfr], t2                // t2<CodeBlock> = cfr.CodeBlock
547     loadi CodeBlock::m_numVars[t2], t2      // t2<size_t> = t2<CodeBlock>.m_numVars
548     btiz t2, .opEnterDone
549     move ValueUndefined, t0
550     negi t2
551     sxi2q t2, t2
552 .opEnterLoop:
553     storeq t0, [cfr, t2, 8]
554     addq 1, t2
555     btqnz t2, .opEnterLoop
556 .opEnterDone:
557     callSlowPath(_slow_path_enter)
558     dispatch(1)
559
560
561 _llint_op_create_activation:
562     traceExecution()
563     loadisFromInstruction(1, t0)
564     bqneq [cfr, t0, 8], ValueEmpty, .opCreateActivationDone
565     callSlowPath(_llint_slow_path_create_activation)
566 .opCreateActivationDone:
567     dispatch(2)
568
569
570 _llint_op_init_lazy_reg:
571     traceExecution()
572     loadisFromInstruction(1, t0)
573     storeq ValueEmpty, [cfr, t0, 8]
574     dispatch(2)
575
576
577 _llint_op_create_arguments:
578     traceExecution()
579     loadisFromInstruction(1, t0)
580     bqneq [cfr, t0, 8], ValueEmpty, .opCreateArgumentsDone
581     callSlowPath(_slow_path_create_arguments)
582 .opCreateArgumentsDone:
583     dispatch(2)
584
585
586 _llint_op_create_this:
587     traceExecution()
588     loadisFromInstruction(2, t0)
589     loadp [cfr, t0, 8], t0
590     loadp JSFunction::m_allocationProfile + ObjectAllocationProfile::m_allocator[t0], t1
591     loadp JSFunction::m_allocationProfile + ObjectAllocationProfile::m_structure[t0], t2
592     btpz t1, .opCreateThisSlow
593     allocateJSObject(t1, t2, t0, t3, .opCreateThisSlow)
594     loadisFromInstruction(1, t1)
595     storeq t0, [cfr, t1, 8]
596     dispatch(4)
597
598 .opCreateThisSlow:
599     callSlowPath(_slow_path_create_this)
600     dispatch(4)
601
602
603 _llint_op_get_callee:
604     traceExecution()
605     loadisFromInstruction(1, t0)
606     loadp Callee[cfr], t1
607     loadpFromInstruction(2, t2)
608     bpneq t1, t2, .opGetCalleeSlow
609     storep t1, [cfr, t0, 8]
610     dispatch(3)
611
612 .opGetCalleeSlow:
613     callSlowPath(_slow_path_get_callee)
614     dispatch(3)
615
616 _llint_op_to_this:
617     traceExecution()
618     loadisFromInstruction(1, t0)
619     loadq [cfr, t0, 8], t0
620     btqnz t0, tagMask, .opToThisSlow
621     bbneq JSCell::m_type[t0], FinalObjectType, .opToThisSlow
622     loadStructureWithScratch(t0, t1, t2)
623     loadpFromInstruction(2, t2)
624     bpneq t1, t2, .opToThisSlow
625     dispatch(3)
626
627 .opToThisSlow:
628     callSlowPath(_slow_path_to_this)
629     dispatch(3)
630
631
632 _llint_op_new_object:
633     traceExecution()
634     loadpFromInstruction(3, t0)
635     loadp ObjectAllocationProfile::m_allocator[t0], t1
636     loadp ObjectAllocationProfile::m_structure[t0], t2
637     allocateJSObject(t1, t2, t0, t3, .opNewObjectSlow)
638     loadisFromInstruction(1, t1)
639     storeq t0, [cfr, t1, 8]
640     dispatch(4)
641
642 .opNewObjectSlow:
643     callSlowPath(_llint_slow_path_new_object)
644     dispatch(4)
645
646
647 _llint_op_mov:
648     traceExecution()
649     loadisFromInstruction(2, t1)
650     loadisFromInstruction(1, t0)
651     loadConstantOrVariable(t1, t2)
652     storeq t2, [cfr, t0, 8]
653     dispatch(3)
654
655
656 macro notifyWrite(set, value, scratch, slow)
657     loadb VariableWatchpointSet::m_state[set], scratch
658     bieq scratch, IsInvalidated, .done
659     bineq scratch, ClearWatchpoint, .overwrite
660     storeq value, VariableWatchpointSet::m_inferredValue[set]
661     storeb IsWatched, VariableWatchpointSet::m_state[set]
662     jmp .done
663
664 .overwrite:
665     bqeq value, VariableWatchpointSet::m_inferredValue[set], .done
666     btbnz VariableWatchpointSet::m_setIsNotEmpty[set], slow
667     storeq 0, VariableWatchpointSet::m_inferredValue[set]
668     storeb IsInvalidated, VariableWatchpointSet::m_state[set]
669
670 .done:    
671 end
672
673 _llint_op_captured_mov:
674     traceExecution()
675     loadisFromInstruction(2, t1)
676     loadConstantOrVariable(t1, t2)
677     loadpFromInstruction(3, t0)
678     btpz t0, .opCapturedMovReady
679     notifyWrite(t0, t2, t1, .opCapturedMovSlow)
680 .opCapturedMovReady:
681     loadisFromInstruction(1, t0)
682     storeq t2, [cfr, t0, 8]
683     dispatch(4)
684
685 .opCapturedMovSlow:
686     callSlowPath(_slow_path_captured_mov)
687     dispatch(4)
688
689
690 _llint_op_not:
691     traceExecution()
692     loadisFromInstruction(2, t0)
693     loadisFromInstruction(1, t1)
694     loadConstantOrVariable(t0, t2)
695     xorq ValueFalse, t2
696     btqnz t2, ~1, .opNotSlow
697     xorq ValueTrue, t2
698     storeq t2, [cfr, t1, 8]
699     dispatch(3)
700
701 .opNotSlow:
702     callSlowPath(_slow_path_not)
703     dispatch(3)
704
705
706 macro equalityComparison(integerComparison, slowPath)
707     traceExecution()
708     loadisFromInstruction(3, t0)
709     loadisFromInstruction(2, t2)
710     loadisFromInstruction(1, t3)
711     loadConstantOrVariableInt32(t0, t1, .slow)
712     loadConstantOrVariableInt32(t2, t0, .slow)
713     integerComparison(t0, t1, t0)
714     orq ValueFalse, t0
715     storeq t0, [cfr, t3, 8]
716     dispatch(4)
717
718 .slow:
719     callSlowPath(slowPath)
720     dispatch(4)
721 end
722
723 _llint_op_eq:
724     equalityComparison(
725         macro (left, right, result) cieq left, right, result end,
726         _slow_path_eq)
727
728
729 _llint_op_neq:
730     equalityComparison(
731         macro (left, right, result) cineq left, right, result end,
732         _slow_path_neq)
733
734
735 macro equalNullComparison()
736     loadisFromInstruction(2, t0)
737     loadq [cfr, t0, 8], t0
738     btqnz t0, tagMask, .immediate
739     btbnz JSCell::m_flags[t0], MasqueradesAsUndefined, .masqueradesAsUndefined
740     move 0, t0
741     jmp .done
742 .masqueradesAsUndefined:
743     loadStructureWithScratch(t0, t2, t1)
744     loadp CodeBlock[cfr], t0
745     loadp CodeBlock::m_globalObject[t0], t0
746     cpeq Structure::m_globalObject[t2], t0, t0
747     jmp .done
748 .immediate:
749     andq ~TagBitUndefined, t0
750     cqeq t0, ValueNull, t0
751 .done:
752 end
753
754 _llint_op_eq_null:
755     traceExecution()
756     equalNullComparison()
757     loadisFromInstruction(1, t1)
758     orq ValueFalse, t0
759     storeq t0, [cfr, t1, 8]
760     dispatch(3)
761
762
763 _llint_op_neq_null:
764     traceExecution()
765     equalNullComparison()
766     loadisFromInstruction(1, t1)
767     xorq ValueTrue, t0
768     storeq t0, [cfr, t1, 8]
769     dispatch(3)
770
771
772 macro strictEq(equalityOperation, slowPath)
773     traceExecution()
774     loadisFromInstruction(3, t0)
775     loadisFromInstruction(2, t2)
776     loadConstantOrVariable(t0, t1)
777     loadConstantOrVariable(t2, t0)
778     move t0, t2
779     orq t1, t2
780     btqz t2, tagMask, .slow
781     bqaeq t0, tagTypeNumber, .leftOK
782     btqnz t0, tagTypeNumber, .slow
783 .leftOK:
784     bqaeq t1, tagTypeNumber, .rightOK
785     btqnz t1, tagTypeNumber, .slow
786 .rightOK:
787     equalityOperation(t0, t1, t0)
788     loadisFromInstruction(1, t1)
789     orq ValueFalse, t0
790     storeq t0, [cfr, t1, 8]
791     dispatch(4)
792
793 .slow:
794     callSlowPath(slowPath)
795     dispatch(4)
796 end
797
798 _llint_op_stricteq:
799     strictEq(
800         macro (left, right, result) cqeq left, right, result end,
801         _slow_path_stricteq)
802
803
804 _llint_op_nstricteq:
805     strictEq(
806         macro (left, right, result) cqneq left, right, result end,
807         _slow_path_nstricteq)
808
809
810 macro preOp(arithmeticOperation, slowPath)
811     traceExecution()
812     loadisFromInstruction(1, t0)
813     loadq [cfr, t0, 8], t1
814     bqb t1, tagTypeNumber, .slow
815     arithmeticOperation(t1, .slow)
816     orq tagTypeNumber, t1
817     storeq t1, [cfr, t0, 8]
818     dispatch(2)
819
820 .slow:
821     callSlowPath(slowPath)
822     dispatch(2)
823 end
824
825 _llint_op_inc:
826     preOp(
827         macro (value, slow) baddio 1, value, slow end,
828         _slow_path_inc)
829
830
831 _llint_op_dec:
832     preOp(
833         macro (value, slow) bsubio 1, value, slow end,
834         _slow_path_dec)
835
836
837 _llint_op_to_number:
838     traceExecution()
839     loadisFromInstruction(2, t0)
840     loadisFromInstruction(1, t1)
841     loadConstantOrVariable(t0, t2)
842     bqaeq t2, tagTypeNumber, .opToNumberIsImmediate
843     btqz t2, tagTypeNumber, .opToNumberSlow
844 .opToNumberIsImmediate:
845     storeq t2, [cfr, t1, 8]
846     dispatch(3)
847
848 .opToNumberSlow:
849     callSlowPath(_slow_path_to_number)
850     dispatch(3)
851
852
853 _llint_op_negate:
854     traceExecution()
855     loadisFromInstruction(2, t0)
856     loadisFromInstruction(1, t1)
857     loadConstantOrVariable(t0, t2)
858     bqb t2, tagTypeNumber, .opNegateNotInt
859     btiz t2, 0x7fffffff, .opNegateSlow
860     negi t2
861     orq tagTypeNumber, t2
862     storeq t2, [cfr, t1, 8]
863     dispatch(3)
864 .opNegateNotInt:
865     btqz t2, tagTypeNumber, .opNegateSlow
866     xorq 0x8000000000000000, t2
867     storeq t2, [cfr, t1, 8]
868     dispatch(3)
869
870 .opNegateSlow:
871     callSlowPath(_slow_path_negate)
872     dispatch(3)
873
874
875 macro binaryOpCustomStore(integerOperationAndStore, doubleOperation, slowPath)
876     loadisFromInstruction(3, t0)
877     loadisFromInstruction(2, t2)
878     loadConstantOrVariable(t0, t1)
879     loadConstantOrVariable(t2, t0)
880     bqb t0, tagTypeNumber, .op1NotInt
881     bqb t1, tagTypeNumber, .op2NotInt
882     loadisFromInstruction(1, t2)
883     integerOperationAndStore(t1, t0, .slow, t2)
884     dispatch(5)
885
886 .op1NotInt:
887     # First operand is definitely not an int, the second operand could be anything.
888     btqz t0, tagTypeNumber, .slow
889     bqaeq t1, tagTypeNumber, .op1NotIntOp2Int
890     btqz t1, tagTypeNumber, .slow
891     addq tagTypeNumber, t1
892     fq2d t1, ft1
893     jmp .op1NotIntReady
894 .op1NotIntOp2Int:
895     ci2d t1, ft1
896 .op1NotIntReady:
897     loadisFromInstruction(1, t2)
898     addq tagTypeNumber, t0
899     fq2d t0, ft0
900     doubleOperation(ft1, ft0)
901     fd2q ft0, t0
902     subq tagTypeNumber, t0
903     storeq t0, [cfr, t2, 8]
904     dispatch(5)
905
906 .op2NotInt:
907     # First operand is definitely an int, the second is definitely not.
908     loadisFromInstruction(1, t2)
909     btqz t1, tagTypeNumber, .slow
910     ci2d t0, ft0
911     addq tagTypeNumber, t1
912     fq2d t1, ft1
913     doubleOperation(ft1, ft0)
914     fd2q ft0, t0
915     subq tagTypeNumber, t0
916     storeq t0, [cfr, t2, 8]
917     dispatch(5)
918
919 .slow:
920     callSlowPath(slowPath)
921     dispatch(5)
922 end
923
924 macro binaryOp(integerOperation, doubleOperation, slowPath)
925     binaryOpCustomStore(
926         macro (left, right, slow, index)
927             integerOperation(left, right, slow)
928             orq tagTypeNumber, right
929             storeq right, [cfr, index, 8]
930         end,
931         doubleOperation, slowPath)
932 end
933
934 _llint_op_add:
935     traceExecution()
936     binaryOp(
937         macro (left, right, slow) baddio left, right, slow end,
938         macro (left, right) addd left, right end,
939         _slow_path_add)
940
941
942 _llint_op_mul:
943     traceExecution()
944     binaryOpCustomStore(
945         macro (left, right, slow, index)
946             # Assume t3 is scratchable.
947             move right, t3
948             bmulio left, t3, slow
949             btinz t3, .done
950             bilt left, 0, slow
951             bilt right, 0, slow
952         .done:
953             orq tagTypeNumber, t3
954             storeq t3, [cfr, index, 8]
955         end,
956         macro (left, right) muld left, right end,
957         _slow_path_mul)
958
959
960 _llint_op_sub:
961     traceExecution()
962     binaryOp(
963         macro (left, right, slow) bsubio left, right, slow end,
964         macro (left, right) subd left, right end,
965         _slow_path_sub)
966
967
968 _llint_op_div:
969     traceExecution()
970     if X86_64
971         binaryOpCustomStore(
972             macro (left, right, slow, index)
973                 # Assume t3 is scratchable.
974                 btiz left, slow
975                 bineq left, -1, .notNeg2TwoThe31DivByNeg1
976                 bieq right, -2147483648, .slow
977             .notNeg2TwoThe31DivByNeg1:
978                 btinz right, .intOK
979                 bilt left, 0, slow
980             .intOK:
981                 move left, t3
982                 move right, t0
983                 cdqi
984                 idivi t3
985                 btinz t1, slow
986                 orq tagTypeNumber, t0
987                 storeq t0, [cfr, index, 8]
988             end,
989             macro (left, right) divd left, right end,
990             _slow_path_div)
991     else
992         callSlowPath(_slow_path_div)
993         dispatch(5)
994     end
995
996
997 macro bitOp(operation, slowPath, advance)
998     loadisFromInstruction(3, t0)
999     loadisFromInstruction(2, t2)
1000     loadisFromInstruction(1, t3)
1001     loadConstantOrVariable(t0, t1)
1002     loadConstantOrVariable(t2, t0)
1003     bqb t0, tagTypeNumber, .slow
1004     bqb t1, tagTypeNumber, .slow
1005     operation(t1, t0)
1006     orq tagTypeNumber, t0
1007     storeq t0, [cfr, t3, 8]
1008     dispatch(advance)
1009
1010 .slow:
1011     callSlowPath(slowPath)
1012     dispatch(advance)
1013 end
1014
1015 _llint_op_lshift:
1016     traceExecution()
1017     bitOp(
1018         macro (left, right) lshifti left, right end,
1019         _slow_path_lshift,
1020         4)
1021
1022
1023 _llint_op_rshift:
1024     traceExecution()
1025     bitOp(
1026         macro (left, right) rshifti left, right end,
1027         _slow_path_rshift,
1028         4)
1029
1030
1031 _llint_op_urshift:
1032     traceExecution()
1033     bitOp(
1034         macro (left, right) urshifti left, right end,
1035         _slow_path_urshift,
1036         4)
1037
1038
1039 _llint_op_unsigned:
1040     traceExecution()
1041     loadisFromInstruction(1, t0)
1042     loadisFromInstruction(2, t1)
1043     loadConstantOrVariable(t1, t2)
1044     bilt t2, 0, .opUnsignedSlow
1045     storeq t2, [cfr, t0, 8]
1046     dispatch(3)
1047 .opUnsignedSlow:
1048     callSlowPath(_slow_path_unsigned)
1049     dispatch(3)
1050
1051
1052 _llint_op_bitand:
1053     traceExecution()
1054     bitOp(
1055         macro (left, right) andi left, right end,
1056         _slow_path_bitand,
1057         5)
1058
1059
1060 _llint_op_bitxor:
1061     traceExecution()
1062     bitOp(
1063         macro (left, right) xori left, right end,
1064         _slow_path_bitxor,
1065         5)
1066
1067
1068 _llint_op_bitor:
1069     traceExecution()
1070     bitOp(
1071         macro (left, right) ori left, right end,
1072         _slow_path_bitor,
1073         5)
1074
1075
1076 _llint_op_check_has_instance:
1077     traceExecution()
1078     loadisFromInstruction(3, t1)
1079     loadConstantOrVariableCell(t1, t0, .opCheckHasInstanceSlow)
1080     btbz JSCell::m_flags[t0], ImplementsDefaultHasInstance, .opCheckHasInstanceSlow
1081     dispatch(5)
1082
1083 .opCheckHasInstanceSlow:
1084     callSlowPath(_llint_slow_path_check_has_instance)
1085     dispatch(0)
1086
1087
1088 _llint_op_instanceof:
1089     traceExecution()
1090     # Actually do the work.
1091     loadisFromInstruction(3, t0)
1092     loadConstantOrVariableCell(t0, t1, .opInstanceofSlow)
1093     bbb JSCell::m_type[t1], ObjectType, .opInstanceofSlow
1094     loadisFromInstruction(2, t0)
1095     loadConstantOrVariableCell(t0, t2, .opInstanceofSlow)
1096     
1097     # Register state: t1 = prototype, t2 = value
1098     move 1, t0
1099 .opInstanceofLoop:
1100     loadStructureAndClobberFirstArg(t2, t3)
1101     loadq Structure::m_prototype[t3], t2
1102     bqeq t2, t1, .opInstanceofDone
1103     btqz t2, tagMask, .opInstanceofLoop
1104
1105     move 0, t0
1106 .opInstanceofDone:
1107     orq ValueFalse, t0
1108     loadisFromInstruction(1, t3)
1109     storeq t0, [cfr, t3, 8]
1110     dispatch(4)
1111
1112 .opInstanceofSlow:
1113     callSlowPath(_llint_slow_path_instanceof)
1114     dispatch(4)
1115
1116
1117 _llint_op_is_undefined:
1118     traceExecution()
1119     loadisFromInstruction(2, t1)
1120     loadisFromInstruction(1, t2)
1121     loadConstantOrVariable(t1, t0)
1122     btqz t0, tagMask, .opIsUndefinedCell
1123     cqeq t0, ValueUndefined, t3
1124     orq ValueFalse, t3
1125     storeq t3, [cfr, t2, 8]
1126     dispatch(3)
1127 .opIsUndefinedCell:
1128     btbnz JSCell::m_flags[t0], MasqueradesAsUndefined, .masqueradesAsUndefined
1129     move ValueFalse, t1
1130     storeq t1, [cfr, t2, 8]
1131     dispatch(3)
1132 .masqueradesAsUndefined:
1133     loadStructureWithScratch(t0, t3, t1)
1134     loadp CodeBlock[cfr], t1
1135     loadp CodeBlock::m_globalObject[t1], t1
1136     cpeq Structure::m_globalObject[t3], t1, t0
1137     orq ValueFalse, t0
1138     storeq t0, [cfr, t2, 8]
1139     dispatch(3)
1140
1141
1142 _llint_op_is_boolean:
1143     traceExecution()
1144     loadisFromInstruction(2, t1)
1145     loadisFromInstruction(1, t2)
1146     loadConstantOrVariable(t1, t0)
1147     xorq ValueFalse, t0
1148     tqz t0, ~1, t0
1149     orq ValueFalse, t0
1150     storeq t0, [cfr, t2, 8]
1151     dispatch(3)
1152
1153
1154 _llint_op_is_number:
1155     traceExecution()
1156     loadisFromInstruction(2, t1)
1157     loadisFromInstruction(1, t2)
1158     loadConstantOrVariable(t1, t0)
1159     tqnz t0, tagTypeNumber, t1
1160     orq ValueFalse, t1
1161     storeq t1, [cfr, t2, 8]
1162     dispatch(3)
1163
1164
1165 _llint_op_is_string:
1166     traceExecution()
1167     loadisFromInstruction(2, t1)
1168     loadisFromInstruction(1, t2)
1169     loadConstantOrVariable(t1, t0)
1170     btqnz t0, tagMask, .opIsStringNotCell
1171     cbeq JSCell::m_type[t0], StringType, t1
1172     orq ValueFalse, t1
1173     storeq t1, [cfr, t2, 8]
1174     dispatch(3)
1175 .opIsStringNotCell:
1176     storeq ValueFalse, [cfr, t2, 8]
1177     dispatch(3)
1178
1179
1180 macro loadPropertyAtVariableOffset(propertyOffsetAsInt, objectAndStorage, value)
1181     bilt propertyOffsetAsInt, firstOutOfLineOffset, .isInline
1182     loadp JSObject::m_butterfly[objectAndStorage], objectAndStorage
1183     negi propertyOffsetAsInt
1184     sxi2q propertyOffsetAsInt, propertyOffsetAsInt
1185     jmp .ready
1186 .isInline:
1187     addp sizeof JSObject - (firstOutOfLineOffset - 2) * 8, objectAndStorage
1188 .ready:
1189     loadq (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffsetAsInt, 8], value
1190 end
1191
1192
1193 macro storePropertyAtVariableOffset(propertyOffsetAsInt, objectAndStorage, value)
1194     bilt propertyOffsetAsInt, firstOutOfLineOffset, .isInline
1195     loadp JSObject::m_butterfly[objectAndStorage], objectAndStorage
1196     negi propertyOffsetAsInt
1197     sxi2q propertyOffsetAsInt, propertyOffsetAsInt
1198     jmp .ready
1199 .isInline:
1200     addp sizeof JSObject - (firstOutOfLineOffset - 2) * 8, objectAndStorage
1201 .ready:
1202     storeq value, (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffsetAsInt, 8]
1203 end
1204
1205 _llint_op_init_global_const:
1206     traceExecution()
1207     writeBarrierOnGlobalObject(2)
1208     loadisFromInstruction(2, t1)
1209     loadpFromInstruction(1, t0)
1210     loadConstantOrVariable(t1, t2)
1211     storeq t2, [t0]
1212     dispatch(5)
1213
1214
1215 macro getById(getPropertyStorage)
1216     traceExecution()
1217     # We only do monomorphic get_by_id caching for now, and we do not modify the
1218     # opcode. We do, however, allow for the cache to change anytime if fails, since
1219     # ping-ponging is free. At best we get lucky and the get_by_id will continue
1220     # to take fast path on the new cache. At worst we take slow path, which is what
1221     # we would have been doing anyway.
1222     loadisFromInstruction(2, t0)
1223     loadConstantOrVariableCell(t0, t3, .opGetByIdSlow)
1224     loadStructureWithScratch(t3, t2, t1)
1225     loadpFromInstruction(4, t1)
1226     bpneq t2, t1, .opGetByIdSlow
1227     getPropertyStorage(
1228         t3,
1229         t0,
1230         macro (propertyStorage, scratch)
1231             loadisFromInstruction(5, t2)
1232             loadisFromInstruction(1, t1)
1233             loadq [propertyStorage, t2], scratch
1234             storeq scratch, [cfr, t1, 8]
1235             valueProfile(scratch, 8, t1)
1236             dispatch(9)
1237         end)
1238             
1239     .opGetByIdSlow:
1240         callSlowPath(_llint_slow_path_get_by_id)
1241         dispatch(9)
1242 end
1243
1244 _llint_op_get_by_id:
1245     getById(withInlineStorage)
1246
1247
1248 _llint_op_get_by_id_out_of_line:
1249     getById(withOutOfLineStorage)
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     loadi -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], t0
1264     bilt t0, 0, .opGetArrayLengthSlow
1265     orq tagTypeNumber, t0
1266     valueProfile(t0, 8, t2)
1267     storeq t0, [cfr, t1, 8]
1268     dispatch(9)
1269
1270 .opGetArrayLengthSlow:
1271     callSlowPath(_llint_slow_path_get_by_id)
1272     dispatch(9)
1273
1274
1275 _llint_op_get_arguments_length:
1276     traceExecution()
1277     loadisFromInstruction(2, t0)
1278     loadisFromInstruction(1, t1)
1279     btqnz [cfr, t0, 8], .opGetArgumentsLengthSlow
1280     loadi ArgumentCount + PayloadOffset[cfr], t2
1281     subi 1, t2
1282     orq tagTypeNumber, t2
1283     storeq t2, [cfr, t1, 8]
1284     dispatch(4)
1285
1286 .opGetArgumentsLengthSlow:
1287     callSlowPath(_llint_slow_path_get_arguments_length)
1288     dispatch(4)
1289
1290
1291 macro putById(getPropertyStorage)
1292     traceExecution()
1293     writeBarrierOnOperands(1, 3)
1294     loadisFromInstruction(1, t3)
1295     loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
1296     loadStructureWithScratch(t0, t2, t1)
1297     loadpFromInstruction(4, t1)
1298     bpneq t2, t1, .opPutByIdSlow
1299     getPropertyStorage(
1300         t0,
1301         t3,
1302         macro (propertyStorage, scratch)
1303             loadisFromInstruction(5, t1)
1304             loadisFromInstruction(3, t2)
1305             loadConstantOrVariable(t2, scratch)
1306             storeq scratch, [propertyStorage, t1]
1307             dispatch(9)
1308         end)
1309 end
1310
1311 _llint_op_put_by_id:
1312     putById(withInlineStorage)
1313
1314 .opPutByIdSlow:
1315     callSlowPath(_llint_slow_path_put_by_id)
1316     dispatch(9)
1317
1318
1319 _llint_op_put_by_id_out_of_line:
1320     putById(withOutOfLineStorage)
1321
1322
1323 macro putByIdTransition(additionalChecks, getPropertyStorage)
1324     traceExecution()
1325     writeBarrierOnOperand(1)
1326     loadisFromInstruction(1, t3)
1327     loadpFromInstruction(4, t1)
1328     loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
1329     loadStructureWithScratch(t0, t2, t3)
1330     bpneq t2, t1, .opPutByIdSlow
1331     additionalChecks(t1, t3, t2)
1332     loadisFromInstruction(3, t2)
1333     loadisFromInstruction(5, t1)
1334     getPropertyStorage(
1335         t0,
1336         t3,
1337         macro (propertyStorage, scratch)
1338             addp t1, propertyStorage, t3
1339             loadConstantOrVariable(t2, t1)
1340             storeq t1, [t3]
1341             loadpFromInstruction(6, t1)
1342             loadi Structure::m_blob + StructureIDBlob::u.words.word1[t1], t1
1343             storei t1, JSCell::m_structureID[t0]
1344             dispatch(9)
1345         end)
1346 end
1347
1348 macro noAdditionalChecks(oldStructure, scratch, scratch2)
1349 end
1350
1351 macro structureChainChecks(oldStructure, scratch, scratch2)
1352     const protoCell = oldStructure    # Reusing the oldStructure register for the proto
1353     loadpFromInstruction(7, scratch)
1354     assert(macro (ok) btpnz scratch, ok end)
1355     loadp StructureChain::m_vector[scratch], scratch
1356     assert(macro (ok) btpnz scratch, ok end)
1357     bqeq Structure::m_prototype[oldStructure], ValueNull, .done
1358 .loop:
1359     loadq Structure::m_prototype[oldStructure], protoCell
1360     loadStructureAndClobberFirstArg(protoCell, scratch2)
1361     move scratch2, oldStructure
1362     bpneq oldStructure, [scratch], .opPutByIdSlow
1363     addp 8, scratch
1364     bqneq Structure::m_prototype[oldStructure], ValueNull, .loop
1365 .done:
1366 end
1367
1368 _llint_op_put_by_id_transition_direct:
1369     putByIdTransition(noAdditionalChecks, withInlineStorage)
1370
1371
1372 _llint_op_put_by_id_transition_direct_out_of_line:
1373     putByIdTransition(noAdditionalChecks, withOutOfLineStorage)
1374
1375
1376 _llint_op_put_by_id_transition_normal:
1377     putByIdTransition(structureChainChecks, withInlineStorage)
1378
1379
1380 _llint_op_put_by_id_transition_normal_out_of_line:
1381     putByIdTransition(structureChainChecks, withOutOfLineStorage)
1382
1383
1384 _llint_op_get_by_val:
1385     traceExecution()
1386     loadisFromInstruction(2, t2)
1387     loadConstantOrVariableCell(t2, t0, .opGetByValSlow)
1388     loadpFromInstruction(4, t3)
1389     move t0, t2
1390     arrayProfile(t2, t3, t1)
1391     loadisFromInstruction(3, t3)
1392     loadConstantOrVariableInt32(t3, t1, .opGetByValSlow)
1393     sxi2q t1, t1
1394     loadp JSObject::m_butterfly[t0], t3
1395     andi IndexingShapeMask, t2
1396     bieq t2, Int32Shape, .opGetByValIsContiguous
1397     bineq t2, ContiguousShape, .opGetByValNotContiguous
1398 .opGetByValIsContiguous:
1399
1400     biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t3], .opGetByValOutOfBounds
1401     loadisFromInstruction(1, t0)
1402     loadq [t3, t1, 8], t2
1403     btqz t2, .opGetByValOutOfBounds
1404     jmp .opGetByValDone
1405
1406 .opGetByValNotContiguous:
1407     bineq t2, DoubleShape, .opGetByValNotDouble
1408     biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t3], .opGetByValOutOfBounds
1409     loadis 8[PB, PC, 8], t0
1410     loadd [t3, t1, 8], ft0
1411     bdnequn ft0, ft0, .opGetByValOutOfBounds
1412     fd2q ft0, t2
1413     subq tagTypeNumber, t2
1414     jmp .opGetByValDone
1415     
1416 .opGetByValNotDouble:
1417     subi ArrayStorageShape, t2
1418     bia t2, SlowPutArrayStorageShape - ArrayStorageShape, .opGetByValSlow
1419     biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t3], .opGetByValOutOfBounds
1420     loadisFromInstruction(1, t0)
1421     loadq ArrayStorage::m_vector[t3, t1, 8], t2
1422     btqz t2, .opGetByValOutOfBounds
1423
1424 .opGetByValDone:
1425     storeq t2, [cfr, t0, 8]
1426     valueProfile(t2, 5, t0)
1427     dispatch(6)
1428
1429 .opGetByValOutOfBounds:
1430     loadpFromInstruction(4, t0)
1431     storeb 1, ArrayProfile::m_outOfBounds[t0]
1432 .opGetByValSlow:
1433     callSlowPath(_llint_slow_path_get_by_val)
1434     dispatch(6)
1435
1436
1437 _llint_op_get_argument_by_val:
1438     # FIXME: At some point we should array profile this. Right now it isn't necessary
1439     # since the DFG will never turn a get_argument_by_val into a GetByVal.
1440     traceExecution()
1441     loadisFromInstruction(2, t0)
1442     loadisFromInstruction(3, t1)
1443     btqnz [cfr, t0, 8], .opGetArgumentByValSlow
1444     loadConstantOrVariableInt32(t1, t2, .opGetArgumentByValSlow)
1445     addi 1, t2
1446     loadi ArgumentCount + PayloadOffset[cfr], t1
1447     biaeq t2, t1, .opGetArgumentByValSlow
1448     loadisFromInstruction(1, t3)
1449     loadpFromInstruction(5, t1)
1450     loadq ThisArgumentOffset[cfr, t2, 8], t0
1451     storeq t0, [cfr, t3, 8]
1452     valueProfile(t0, 5, t1)
1453     dispatch(6)
1454
1455 .opGetArgumentByValSlow:
1456     callSlowPath(_llint_slow_path_get_argument_by_val)
1457     dispatch(6)
1458
1459
1460 _llint_op_get_by_pname:
1461     traceExecution()
1462     loadisFromInstruction(3, t1)
1463     loadConstantOrVariable(t1, t0)
1464     loadisFromInstruction(4, t1)
1465     assertNotConstant(t1)
1466     bqneq t0, [cfr, t1, 8], .opGetByPnameSlow
1467     loadisFromInstruction(2, t2)
1468     loadisFromInstruction(5, t3)
1469     loadConstantOrVariableCell(t2, t0, .opGetByPnameSlow)
1470     assertNotConstant(t3)
1471     loadq [cfr, t3, 8], t1
1472     loadStructureWithScratch(t0, t2, t3)
1473     bpneq t2, JSPropertyNameIterator::m_cachedStructure[t1], .opGetByPnameSlow
1474     loadisFromInstruction(6, t3)
1475     loadi PayloadOffset[cfr, t3, 8], t3
1476     subi 1, t3
1477     biaeq t3, JSPropertyNameIterator::m_numCacheableSlots[t1], .opGetByPnameSlow
1478     bilt t3, JSPropertyNameIterator::m_cachedStructureInlineCapacity[t1], .opGetByPnameInlineProperty
1479     addi firstOutOfLineOffset, t3
1480     subi JSPropertyNameIterator::m_cachedStructureInlineCapacity[t1], t3
1481 .opGetByPnameInlineProperty:
1482     loadPropertyAtVariableOffset(t3, t0, t0)
1483     loadisFromInstruction(1, t1)
1484     storeq t0, [cfr, t1, 8]
1485     dispatch(7)
1486
1487 .opGetByPnameSlow:
1488     callSlowPath(_llint_slow_path_get_by_pname)
1489     dispatch(7)
1490
1491
1492 macro contiguousPutByVal(storeCallback)
1493     biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], .outOfBounds
1494 .storeResult:
1495     loadisFromInstruction(3, t2)
1496     storeCallback(t2, t1, [t0, t3, 8])
1497     dispatch(5)
1498
1499 .outOfBounds:
1500     biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t0], .opPutByValOutOfBounds
1501     loadp 32[PB, PC, 8], t2
1502     storeb 1, ArrayProfile::m_mayStoreToHole[t2]
1503     addi 1, t3, t2
1504     storei t2, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0]
1505     jmp .storeResult
1506 end
1507
1508 macro putByVal(holeCheck, slowPath)
1509     traceExecution()
1510     writeBarrierOnOperands(1, 3)
1511     loadisFromInstruction(1, t0)
1512     loadConstantOrVariableCell(t0, t1, .opPutByValSlow)
1513     loadpFromInstruction(4, t3)
1514     move t1, t2
1515     arrayProfile(t2, t3, t0)
1516     loadisFromInstruction(2, t0)
1517     loadConstantOrVariableInt32(t0, t3, .opPutByValSlow)
1518     sxi2q t3, t3
1519     loadp JSObject::m_butterfly[t1], t0
1520     andi IndexingShapeMask, t2
1521     bineq t2, Int32Shape, .opPutByValNotInt32
1522     contiguousPutByVal(
1523         macro (operand, scratch, address)
1524             loadConstantOrVariable(operand, scratch)
1525             bpb scratch, tagTypeNumber, .opPutByValSlow
1526             storep scratch, address
1527         end)
1528
1529 .opPutByValNotInt32:
1530     bineq t2, DoubleShape, .opPutByValNotDouble
1531     contiguousPutByVal(
1532         macro (operand, scratch, address)
1533             loadConstantOrVariable(operand, scratch)
1534             bqb scratch, tagTypeNumber, .notInt
1535             ci2d scratch, ft0
1536             jmp .ready
1537         .notInt:
1538             addp tagTypeNumber, scratch
1539             fq2d scratch, ft0
1540             bdnequn ft0, ft0, .opPutByValSlow
1541         .ready:
1542             stored ft0, address
1543         end)
1544
1545 .opPutByValNotDouble:
1546     bineq t2, ContiguousShape, .opPutByValNotContiguous
1547     contiguousPutByVal(
1548         macro (operand, scratch, address)
1549             loadConstantOrVariable(operand, scratch)
1550             storep scratch, address
1551         end)
1552
1553 .opPutByValNotContiguous:
1554     bineq t2, ArrayStorageShape, .opPutByValSlow
1555     biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t0], .opPutByValOutOfBounds
1556     holeCheck(ArrayStorage::m_vector[t0, t3, 8], .opPutByValArrayStorageEmpty)
1557 .opPutByValArrayStorageStoreResult:
1558     loadisFromInstruction(3, t2)
1559     loadConstantOrVariable(t2, t1)
1560     storeq t1, ArrayStorage::m_vector[t0, t3, 8]
1561     dispatch(5)
1562
1563 .opPutByValArrayStorageEmpty:
1564     loadpFromInstruction(4, t1)
1565     storeb 1, ArrayProfile::m_mayStoreToHole[t1]
1566     addi 1, ArrayStorage::m_numValuesInVector[t0]
1567     bib t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], .opPutByValArrayStorageStoreResult
1568     addi 1, t3, t1
1569     storei t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0]
1570     jmp .opPutByValArrayStorageStoreResult
1571
1572 .opPutByValOutOfBounds:
1573     loadpFromInstruction(4, t0)
1574     storeb 1, ArrayProfile::m_outOfBounds[t0]
1575 .opPutByValSlow:
1576     callSlowPath(slowPath)
1577     dispatch(5)
1578 end
1579
1580 _llint_op_put_by_val:
1581     putByVal(macro(slot, slowPath)
1582         btqz slot, slowPath
1583     end, _llint_slow_path_put_by_val)
1584
1585 _llint_op_put_by_val_direct:
1586     putByVal(macro(slot, slowPath)
1587     end, _llint_slow_path_put_by_val_direct)
1588
1589
1590 _llint_op_jmp:
1591     traceExecution()
1592     dispatchIntIndirect(1)
1593
1594
1595 macro jumpTrueOrFalse(conditionOp, slow)
1596     loadisFromInstruction(1, t1)
1597     loadConstantOrVariable(t1, t0)
1598     xorq ValueFalse, t0
1599     btqnz t0, -1, .slow
1600     conditionOp(t0, .target)
1601     dispatch(3)
1602
1603 .target:
1604     dispatchIntIndirect(2)
1605
1606 .slow:
1607     callSlowPath(slow)
1608     dispatch(0)
1609 end
1610
1611
1612 macro equalNull(cellHandler, immediateHandler)
1613     loadisFromInstruction(1, t0)
1614     assertNotConstant(t0)
1615     loadq [cfr, t0, 8], t0
1616     btqnz t0, tagMask, .immediate
1617     loadStructureWithScratch(t0, t2, t1)
1618     cellHandler(t2, JSCell::m_flags[t0], .target)
1619     dispatch(3)
1620
1621 .target:
1622     dispatchIntIndirect(2)
1623
1624 .immediate:
1625     andq ~TagBitUndefined, t0
1626     immediateHandler(t0, .target)
1627     dispatch(3)
1628 end
1629
1630 _llint_op_jeq_null:
1631     traceExecution()
1632     equalNull(
1633         macro (structure, value, target) 
1634             btbz value, MasqueradesAsUndefined, .notMasqueradesAsUndefined
1635             loadp CodeBlock[cfr], t0
1636             loadp CodeBlock::m_globalObject[t0], t0
1637             bpeq Structure::m_globalObject[structure], t0, target
1638 .notMasqueradesAsUndefined:
1639         end,
1640         macro (value, target) bqeq value, ValueNull, target end)
1641
1642
1643 _llint_op_jneq_null:
1644     traceExecution()
1645     equalNull(
1646         macro (structure, value, target) 
1647             btbz value, MasqueradesAsUndefined, target
1648             loadp CodeBlock[cfr], t0
1649             loadp CodeBlock::m_globalObject[t0], t0
1650             bpneq Structure::m_globalObject[structure], t0, target
1651         end,
1652         macro (value, target) bqneq value, ValueNull, target end)
1653
1654
1655 _llint_op_jneq_ptr:
1656     traceExecution()
1657     loadisFromInstruction(1, t0)
1658     loadisFromInstruction(2, t1)
1659     loadp CodeBlock[cfr], t2
1660     loadp CodeBlock::m_globalObject[t2], t2
1661     loadp JSGlobalObject::m_specialPointers[t2, t1, 8], t1
1662     bpneq t1, [cfr, t0, 8], .opJneqPtrTarget
1663     dispatch(4)
1664
1665 .opJneqPtrTarget:
1666     dispatchIntIndirect(3)
1667
1668
1669 macro compare(integerCompare, doubleCompare, slowPath)
1670     loadisFromInstruction(1, t2)
1671     loadisFromInstruction(2, t3)
1672     loadConstantOrVariable(t2, t0)
1673     loadConstantOrVariable(t3, t1)
1674     bqb t0, tagTypeNumber, .op1NotInt
1675     bqb t1, tagTypeNumber, .op2NotInt
1676     integerCompare(t0, t1, .jumpTarget)
1677     dispatch(4)
1678
1679 .op1NotInt:
1680     btqz t0, tagTypeNumber, .slow
1681     bqb t1, tagTypeNumber, .op1NotIntOp2NotInt
1682     ci2d t1, ft1
1683     jmp .op1NotIntReady
1684 .op1NotIntOp2NotInt:
1685     btqz t1, tagTypeNumber, .slow
1686     addq tagTypeNumber, t1
1687     fq2d t1, ft1
1688 .op1NotIntReady:
1689     addq tagTypeNumber, t0
1690     fq2d t0, ft0
1691     doubleCompare(ft0, ft1, .jumpTarget)
1692     dispatch(4)
1693
1694 .op2NotInt:
1695     ci2d t0, ft0
1696     btqz t1, tagTypeNumber, .slow
1697     addq tagTypeNumber, t1
1698     fq2d t1, ft1
1699     doubleCompare(ft0, ft1, .jumpTarget)
1700     dispatch(4)
1701
1702 .jumpTarget:
1703     dispatchIntIndirect(3)
1704
1705 .slow:
1706     callSlowPath(slowPath)
1707     dispatch(0)
1708 end
1709
1710
1711 _llint_op_switch_imm:
1712     traceExecution()
1713     loadisFromInstruction(3, t2)
1714     loadisFromInstruction(1, t3)
1715     loadConstantOrVariable(t2, t1)
1716     loadp CodeBlock[cfr], t2
1717     loadp CodeBlock::m_rareData[t2], t2
1718     muli sizeof SimpleJumpTable, t3    # FIXME: would be nice to peephole this!
1719     loadp CodeBlock::RareData::m_switchJumpTables + VectorBufferOffset[t2], t2
1720     addp t3, t2
1721     bqb t1, tagTypeNumber, .opSwitchImmNotInt
1722     subi SimpleJumpTable::min[t2], t1
1723     biaeq t1, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchImmFallThrough
1724     loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t3
1725     loadis [t3, t1, 4], t1
1726     btiz t1, .opSwitchImmFallThrough
1727     dispatch(t1)
1728
1729 .opSwitchImmNotInt:
1730     btqnz t1, tagTypeNumber, .opSwitchImmSlow   # Go slow if it's a double.
1731 .opSwitchImmFallThrough:
1732     dispatchIntIndirect(2)
1733
1734 .opSwitchImmSlow:
1735     callSlowPath(_llint_slow_path_switch_imm)
1736     dispatch(0)
1737
1738
1739 _llint_op_switch_char:
1740     traceExecution()
1741     loadisFromInstruction(3, t2)
1742     loadisFromInstruction(1, t3)
1743     loadConstantOrVariable(t2, t1)
1744     loadp CodeBlock[cfr], t2
1745     loadp CodeBlock::m_rareData[t2], t2
1746     muli sizeof SimpleJumpTable, t3
1747     loadp CodeBlock::RareData::m_switchJumpTables + VectorBufferOffset[t2], t2
1748     addp t3, t2
1749     btqnz t1, tagMask, .opSwitchCharFallThrough
1750     bbneq JSCell::m_type[t1], StringType, .opSwitchCharFallThrough
1751     bineq JSString::m_length[t1], 1, .opSwitchCharFallThrough
1752     loadp JSString::m_value[t1], t0
1753     btpz  t0, .opSwitchOnRope
1754     loadp StringImpl::m_data8[t0], t1
1755     btinz StringImpl::m_hashAndFlags[t0], HashFlags8BitBuffer, .opSwitchChar8Bit
1756     loadh [t1], t0
1757     jmp .opSwitchCharReady
1758 .opSwitchChar8Bit:
1759     loadb [t1], t0
1760 .opSwitchCharReady:
1761     subi SimpleJumpTable::min[t2], t0
1762     biaeq t0, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchCharFallThrough
1763     loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t2
1764     loadis [t2, t0, 4], t1
1765     btiz t1, .opSwitchCharFallThrough
1766     dispatch(t1)
1767
1768 .opSwitchCharFallThrough:
1769     dispatchIntIndirect(2)
1770
1771 .opSwitchOnRope:
1772     callSlowPath(_llint_slow_path_switch_char)
1773     dispatch(0)
1774
1775
1776 _llint_op_new_func:
1777     traceExecution()
1778     loadisFromInstruction(3, t2)
1779     btiz t2, .opNewFuncUnchecked
1780     loadisFromInstruction(1, t1)
1781     btqnz [cfr, t1, 8], .opNewFuncDone
1782 .opNewFuncUnchecked:
1783     callSlowPath(_llint_slow_path_new_func)
1784 .opNewFuncDone:
1785     dispatch(4)
1786
1787
1788 _llint_op_new_captured_func:
1789     traceExecution()
1790     callSlowPath(_slow_path_new_captured_func)
1791     dispatch(4)
1792
1793
1794 macro arrayProfileForCall()
1795     loadisFromInstruction(4, t3)
1796     negp t3
1797     loadq ThisArgumentOffset[cfr, t3, 8], t0
1798     btqnz t0, tagMask, .done
1799     loadpFromInstruction((CallOpCodeSize - 2), t1)
1800     loadi JSCell::m_structureID[t0], t3
1801     storei t3, ArrayProfile::m_lastSeenStructureID[t1]
1802 .done:
1803 end
1804
1805 macro doCall(slowPath)
1806     loadisFromInstruction(2, t0)
1807     loadpFromInstruction(5, t1)
1808     loadp LLIntCallLinkInfo::callee[t1], t2
1809     loadConstantOrVariable(t0, t3)
1810     bqneq t3, t2, .opCallSlow
1811     loadisFromInstruction(4, t3)
1812     lshifti 3, t3
1813     negp t3
1814     addp cfr, t3
1815     loadp JSFunction::m_scope[t2], t0
1816     storeq t2, Callee[t3]
1817     storeq t0, ScopeChain[t3]
1818     loadisFromInstruction(3, t2)
1819     storei PC, ArgumentCount + TagOffset[cfr]
1820     storei t2, ArgumentCount + PayloadOffset[t3]
1821     addp CallerFrameAndPCSize, t3
1822     callTargetFunction(t1, t3)
1823
1824 .opCallSlow:
1825     slowPathForCall(slowPath)
1826 end
1827
1828
1829 _llint_op_tear_off_activation:
1830     traceExecution()
1831     loadisFromInstruction(1, t0)
1832     btqz [cfr, t0, 8], .opTearOffActivationNotCreated
1833     callSlowPath(_llint_slow_path_tear_off_activation)
1834 .opTearOffActivationNotCreated:
1835     dispatch(2)
1836
1837
1838 _llint_op_tear_off_arguments:
1839     traceExecution()
1840     loadisFromInstruction(1, t0)
1841     addq 1, t0   # Get the unmodifiedArgumentsRegister
1842     btqz [cfr, t0, 8], .opTearOffArgumentsNotCreated
1843     callSlowPath(_llint_slow_path_tear_off_arguments)
1844 .opTearOffArgumentsNotCreated:
1845     dispatch(3)
1846
1847
1848 _llint_op_ret:
1849     traceExecution()
1850     checkSwitchToJITForEpilogue()
1851     loadisFromInstruction(1, t2)
1852     loadConstantOrVariable(t2, t0)
1853     doReturn()
1854
1855
1856 _llint_op_ret_object_or_this:
1857     traceExecution()
1858     checkSwitchToJITForEpilogue()
1859     loadisFromInstruction(1, t2)
1860     loadConstantOrVariable(t2, t0)
1861     btqnz t0, tagMask, .opRetObjectOrThisNotObject
1862     bbb JSCell::m_type[t0], ObjectType, .opRetObjectOrThisNotObject
1863     doReturn()
1864
1865 .opRetObjectOrThisNotObject:
1866     loadisFromInstruction(2, t2)
1867     loadConstantOrVariable(t2, t0)
1868     doReturn()
1869
1870
1871 _llint_op_to_primitive:
1872     traceExecution()
1873     loadisFromInstruction(2, t2)
1874     loadisFromInstruction(1, t3)
1875     loadConstantOrVariable(t2, t0)
1876     btqnz t0, tagMask, .opToPrimitiveIsImm
1877     bbneq JSCell::m_type[t0], StringType, .opToPrimitiveSlowCase
1878 .opToPrimitiveIsImm:
1879     storeq t0, [cfr, t3, 8]
1880     dispatch(3)
1881
1882 .opToPrimitiveSlowCase:
1883     callSlowPath(_slow_path_to_primitive)
1884     dispatch(3)
1885
1886
1887 _llint_op_next_pname:
1888     traceExecution()
1889     loadisFromInstruction(3, t1)
1890     loadisFromInstruction(4, t2)
1891     assertNotConstant(t1)
1892     assertNotConstant(t2)
1893     loadi PayloadOffset[cfr, t1, 8], t0
1894     bieq t0, PayloadOffset[cfr, t2, 8], .opNextPnameEnd
1895     loadisFromInstruction(5, t2)
1896     assertNotConstant(t2)
1897     loadp [cfr, t2, 8], t2
1898     loadp JSPropertyNameIterator::m_jsStrings[t2], t3
1899     loadq [t3, t0, 8], t3
1900     addi 1, t0
1901     storei t0, PayloadOffset[cfr, t1, 8]
1902     loadisFromInstruction(1, t1)
1903     storeq t3, [cfr, t1, 8]
1904     loadisFromInstruction(2, t3)
1905     assertNotConstant(t3)
1906     loadq [cfr, t3, 8], t3
1907     loadStructureWithScratch(t3, t1, t0)
1908     bpneq t1, JSPropertyNameIterator::m_cachedStructure[t2], .opNextPnameSlow
1909     loadp JSPropertyNameIterator::m_cachedPrototypeChain[t2], t0
1910     loadp StructureChain::m_vector[t0], t0
1911     btpz [t0], .opNextPnameTarget
1912 .opNextPnameCheckPrototypeLoop:
1913     bqeq Structure::m_prototype[t1], ValueNull, .opNextPnameSlow
1914     loadq Structure::m_prototype[t1], t2
1915     loadStructureWithScratch(t2, t1, t3)
1916     bpneq t1, [t0], .opNextPnameSlow
1917     addp 8, t0
1918     btpnz [t0], .opNextPnameCheckPrototypeLoop
1919 .opNextPnameTarget:
1920     dispatchIntIndirect(6)
1921
1922 .opNextPnameEnd:
1923     dispatch(7)
1924
1925 .opNextPnameSlow:
1926     callSlowPath(_llint_slow_path_next_pname) # This either keeps the PC where it was (causing us to loop) or sets it to target.
1927     dispatch(0)
1928
1929
1930 _llint_op_catch:
1931     # This is where we end up from the JIT's throw trampoline (because the
1932     # machine code return address will be set to _llint_op_catch), and from
1933     # the interpreter's throw trampoline (see _llint_throw_trampoline).
1934     # The throwing code must have known that we were throwing to the interpreter,
1935     # and have set VM::targetInterpreterPCForThrow.
1936     loadp ScopeChain[cfr], t3
1937     andp MarkedBlockMask, t3
1938     loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
1939     loadp VM::callFrameForThrow[t3], cfr
1940     restoreStackPointerAfterCall()
1941
1942     loadp CodeBlock[cfr], PB
1943     loadp CodeBlock::m_instructions[PB], PB
1944     loadp VM::targetInterpreterPCForThrow[t3], PC
1945     subp PB, PC
1946     rshiftp 3, PC
1947     loadq VM::m_exception[t3], t0
1948     storeq 0, VM::m_exception[t3]
1949     loadisFromInstruction(1, t2)
1950     storeq t0, [cfr, t2, 8]
1951     traceExecution()
1952     dispatch(2)
1953
1954
1955 _llint_op_end:
1956     traceExecution()
1957     checkSwitchToJITForEpilogue()
1958     loadisFromInstruction(1, t0)
1959     assertNotConstant(t0)
1960     loadq [cfr, t0, 8], t0
1961     doReturn()
1962
1963
1964 _llint_throw_from_slow_path_trampoline:
1965     callSlowPath(_llint_slow_path_handle_exception)
1966
1967     # When throwing from the interpreter (i.e. throwing from LLIntSlowPaths), so
1968     # the throw target is not necessarily interpreted code, we come to here.
1969     # This essentially emulates the JIT's throwing protocol.
1970     loadp CodeBlock[cfr], t1
1971     loadp CodeBlock::m_vm[t1], t1
1972     jmp VM::targetMachinePCForThrow[t1]
1973
1974
1975 _llint_throw_during_call_trampoline:
1976     preserveReturnAddressAfterCall(t2)
1977     jmp _llint_throw_from_slow_path_trampoline
1978
1979
1980 macro nativeCallTrampoline(executableOffsetToFunction)
1981
1982     functionPrologue()
1983     storep 0, CodeBlock[cfr]
1984     if X86_64
1985         loadp ScopeChain[cfr], t0
1986         andp MarkedBlockMask, t0
1987         loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t0], t0
1988         storep cfr, VM::topCallFrame[t0]
1989         loadp CallerFrame[cfr], t0
1990         loadq ScopeChain[t0], t1
1991         storeq t1, ScopeChain[cfr]
1992         move cfr, t4  # t4 = rdi
1993         loadp Callee[cfr], t5 # t5 = rsi
1994         loadp JSFunction::m_executable[t5], t1
1995         checkStackPointerAlignment(t3, 0xdead0001)
1996         call executableOffsetToFunction[t1]
1997         loadp ScopeChain[cfr], t3
1998         andp MarkedBlockMask, t3
1999         loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
2000     elsif ARM64 or C_LOOP
2001         loadp ScopeChain[cfr], t0
2002         andp MarkedBlockMask, t0
2003         loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t0], t0
2004         storep cfr, VM::topCallFrame[t0]
2005         loadp CallerFrame[cfr], t2
2006         loadp ScopeChain[t2], t1
2007         storep t1, ScopeChain[cfr]
2008         preserveReturnAddressAfterCall(t3)
2009         storep t3, ReturnPC[cfr]
2010         move cfr, t0
2011         loadp Callee[cfr], t1
2012         loadp JSFunction::m_executable[t1], t1
2013         move t2, cfr # Restore cfr to avoid loading from stack
2014         if C_LOOP
2015             cloopCallNative executableOffsetToFunction[t1]
2016         else
2017             call executableOffsetToFunction[t1]
2018         end
2019         restoreReturnAddressBeforeReturn(t3)
2020         loadp ScopeChain[cfr], t3
2021         andp MarkedBlockMask, t3
2022         loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
2023     else
2024         error
2025     end
2026
2027     functionEpilogue()
2028
2029     btqnz VM::m_exception[t3], .handleException
2030     ret
2031
2032 .handleException:
2033     storep cfr, VM::topCallFrame[t3]
2034     restoreStackPointerAfterCall()
2035     jmp _llint_throw_from_slow_path_trampoline
2036 end
2037
2038
2039 macro getGlobalObject(dst)
2040     loadp CodeBlock[cfr], t0
2041     loadp CodeBlock::m_globalObject[t0], t0
2042     loadisFromInstruction(dst, t1)
2043     storeq t0, [cfr, t1, 8]
2044 end
2045
2046 macro varInjectionCheck(slowPath)
2047     loadp CodeBlock[cfr], t0
2048     loadp CodeBlock::m_globalObject[t0], t0
2049     loadp JSGlobalObject::m_varInjectionWatchpoint[t0], t0
2050     bbeq WatchpointSet::m_state[t0], IsInvalidated, slowPath
2051 end
2052
2053 macro resolveScope()
2054     loadp CodeBlock[cfr], t0
2055     loadisFromInstruction(4, t2)
2056     btbz CodeBlock::m_needsActivation[t0], .resolveScopeAfterActivationCheck
2057     loadis CodeBlock::m_activationRegister[t0], t1
2058     btpz [cfr, t1, 8], .resolveScopeAfterActivationCheck
2059     addi 1, t2
2060
2061 .resolveScopeAfterActivationCheck:
2062     loadp ScopeChain[cfr], t0
2063     btiz t2, .resolveScopeLoopEnd
2064
2065 .resolveScopeLoop:
2066     loadp JSScope::m_next[t0], t0
2067     subi 1, t2
2068     btinz t2, .resolveScopeLoop
2069
2070 .resolveScopeLoopEnd:
2071     loadisFromInstruction(1, t1)
2072     storeq t0, [cfr, t1, 8]
2073 end
2074
2075
2076 _llint_op_resolve_scope:
2077     traceExecution()
2078     loadisFromInstruction(3, t0)
2079
2080 #rGlobalProperty:
2081     bineq t0, GlobalProperty, .rGlobalVar
2082     getGlobalObject(1)
2083     dispatch(6)
2084
2085 .rGlobalVar:
2086     bineq t0, GlobalVar, .rClosureVar
2087     getGlobalObject(1)
2088     dispatch(6)
2089
2090 .rClosureVar:
2091     bineq t0, ClosureVar, .rGlobalPropertyWithVarInjectionChecks
2092     resolveScope()
2093     dispatch(6)
2094
2095 .rGlobalPropertyWithVarInjectionChecks:
2096     bineq t0, GlobalPropertyWithVarInjectionChecks, .rGlobalVarWithVarInjectionChecks
2097     varInjectionCheck(.rDynamic)
2098     getGlobalObject(1)
2099     dispatch(6)
2100
2101 .rGlobalVarWithVarInjectionChecks:
2102     bineq t0, GlobalVarWithVarInjectionChecks, .rClosureVarWithVarInjectionChecks
2103     varInjectionCheck(.rDynamic)
2104     getGlobalObject(1)
2105     dispatch(6)
2106
2107 .rClosureVarWithVarInjectionChecks:
2108     bineq t0, ClosureVarWithVarInjectionChecks, .rDynamic
2109     varInjectionCheck(.rDynamic)
2110     resolveScope()
2111     dispatch(6)
2112
2113 .rDynamic:
2114     callSlowPath(_llint_slow_path_resolve_scope)
2115     dispatch(6)
2116
2117
2118 macro loadWithStructureCheck(operand, slowPath)
2119     loadisFromInstruction(operand, t0)
2120     loadq [cfr, t0, 8], t0
2121     loadStructureWithScratch(t0, t2, t1)
2122     loadpFromInstruction(5, t1)
2123     bpneq t2, t1, slowPath
2124 end
2125
2126 macro getProperty()
2127     loadisFromInstruction(6, t1)
2128     loadPropertyAtVariableOffset(t1, t0, t2)
2129     valueProfile(t2, 7, t0)
2130     loadisFromInstruction(1, t0)
2131     storeq t2, [cfr, t0, 8]
2132 end
2133
2134 macro getGlobalVar()
2135     loadpFromInstruction(6, t0)
2136     loadq [t0], t0
2137     valueProfile(t0, 7, t1)
2138     loadisFromInstruction(1, t1)
2139     storeq t0, [cfr, t1, 8]
2140 end
2141
2142 macro getClosureVar()
2143     loadp JSVariableObject::m_registers[t0], t0
2144     loadisFromInstruction(6, t1)
2145     loadq [t0, t1, 8], t0
2146     valueProfile(t0, 7, t1)
2147     loadisFromInstruction(1, t1)
2148     storeq t0, [cfr, t1, 8]
2149 end
2150
2151 _llint_op_get_from_scope:
2152     traceExecution()
2153     loadisFromInstruction(4, t0)
2154     andi ResolveModeMask, t0
2155
2156 #gGlobalProperty:
2157     bineq t0, GlobalProperty, .gGlobalVar
2158     loadWithStructureCheck(2, .gDynamic)
2159     getProperty()
2160     dispatch(8)
2161
2162 .gGlobalVar:
2163     bineq t0, GlobalVar, .gClosureVar
2164     getGlobalVar()
2165     dispatch(8)
2166
2167 .gClosureVar:
2168     bineq t0, ClosureVar, .gGlobalPropertyWithVarInjectionChecks
2169     loadVariable(2, t0)
2170     getClosureVar()
2171     dispatch(8)
2172
2173 .gGlobalPropertyWithVarInjectionChecks:
2174     bineq t0, GlobalPropertyWithVarInjectionChecks, .gGlobalVarWithVarInjectionChecks
2175     loadWithStructureCheck(2, .gDynamic)
2176     getProperty()
2177     dispatch(8)
2178
2179 .gGlobalVarWithVarInjectionChecks:
2180     bineq t0, GlobalVarWithVarInjectionChecks, .gClosureVarWithVarInjectionChecks
2181     varInjectionCheck(.gDynamic)
2182     loadVariable(2, t0)
2183     getGlobalVar()
2184     dispatch(8)
2185
2186 .gClosureVarWithVarInjectionChecks:
2187     bineq t0, ClosureVarWithVarInjectionChecks, .gDynamic
2188     varInjectionCheck(.gDynamic)
2189     loadVariable(2, t0)
2190     getClosureVar()
2191     dispatch(8)
2192
2193 .gDynamic:
2194     callSlowPath(_llint_slow_path_get_from_scope)
2195     dispatch(8)
2196
2197
2198 macro putProperty()
2199     loadisFromInstruction(3, t1)
2200     loadConstantOrVariable(t1, t2)
2201     loadisFromInstruction(6, t1)
2202     storePropertyAtVariableOffset(t1, t0, t2)
2203 end
2204
2205 macro putGlobalVar()
2206     loadisFromInstruction(3, t0)
2207     loadConstantOrVariable(t0, t1)
2208     loadpFromInstruction(5, t2)
2209     notifyWrite(t2, t1, t0, .pDynamic)
2210     loadpFromInstruction(6, t0)
2211     storeq t1, [t0]
2212 end
2213
2214 macro putClosureVar()
2215     loadisFromInstruction(3, t1)
2216     loadConstantOrVariable(t1, t2)
2217     loadp JSVariableObject::m_registers[t0], t0
2218     loadisFromInstruction(6, t1)
2219     storeq t2, [t0, t1, 8]
2220 end
2221
2222
2223 _llint_op_put_to_scope:
2224     traceExecution()
2225     loadisFromInstruction(4, t0)
2226     andi ResolveModeMask, t0
2227
2228 #pGlobalProperty:
2229     bineq t0, GlobalProperty, .pGlobalVar
2230     writeBarrierOnOperands(1, 3)
2231     loadWithStructureCheck(1, .pDynamic)
2232     putProperty()
2233     dispatch(7)
2234
2235 .pGlobalVar:
2236     bineq t0, GlobalVar, .pClosureVar
2237     writeBarrierOnGlobalObject(3)
2238     putGlobalVar()
2239     dispatch(7)
2240
2241 .pClosureVar:
2242     bineq t0, ClosureVar, .pGlobalPropertyWithVarInjectionChecks
2243     writeBarrierOnOperands(1, 3)
2244     loadVariable(1, t0)
2245     putClosureVar()
2246     dispatch(7)
2247
2248 .pGlobalPropertyWithVarInjectionChecks:
2249     bineq t0, GlobalPropertyWithVarInjectionChecks, .pGlobalVarWithVarInjectionChecks
2250     writeBarrierOnOperands(1, 3)
2251     loadWithStructureCheck(1, .pDynamic)
2252     putProperty()
2253     dispatch(7)
2254
2255 .pGlobalVarWithVarInjectionChecks:
2256     bineq t0, GlobalVarWithVarInjectionChecks, .pClosureVarWithVarInjectionChecks
2257     writeBarrierOnGlobalObject(3)
2258     varInjectionCheck(.pDynamic)
2259     putGlobalVar()
2260     dispatch(7)
2261
2262 .pClosureVarWithVarInjectionChecks:
2263     bineq t0, ClosureVarWithVarInjectionChecks, .pDynamic
2264     writeBarrierOnOperands(1, 3)
2265     varInjectionCheck(.pDynamic)
2266     loadVariable(1, t0)
2267     putClosureVar()
2268     dispatch(7)
2269
2270 .pDynamic:
2271     callSlowPath(_llint_slow_path_put_to_scope)
2272     dispatch(7)