a88cb8dbd69d353c24c94bd742bc467a9fe22f00
[WebKit-https.git] / Source / JavaScriptCore / llint / LowLevelInterpreter.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 # First come the common protocols that both interpreters use. Note that each
25 # of these must have an ASSERT() in LLIntData.cpp
26
27 # Work-around for the fact that the toolchain's awareness of armv7s results in
28 # a separate slab in the fat binary, yet the offlineasm doesn't know to expect
29 # it.
30 if ARMv7s
31 end
32
33 # These declarations must match interpreter/JSStack.h.
34
35 if JSVALUE64
36 const PtrSize = 8
37 const CallFrameHeaderSlots = 6
38 else
39 const PtrSize = 4
40 const CallFrameHeaderSlots = 5
41 const CallFrameAlignSlots = 1
42 end
43 const SlotSize = 8
44
45 const CallerFrameAndPCSize = 2 * PtrSize
46
47 const CallerFrame = 0
48 const ReturnPC = CallerFrame + PtrSize
49 const CodeBlock = ReturnPC + PtrSize
50 const ScopeChain = CodeBlock + SlotSize
51 const Callee = ScopeChain + SlotSize
52 const ArgumentCount = Callee + SlotSize
53 const ThisArgumentOffset = ArgumentCount + SlotSize
54 const CallFrameHeaderSize = ThisArgumentOffset
55
56 # Some value representation constants.
57 if JSVALUE64
58 const TagBitTypeOther = 0x2
59 const TagBitBool      = 0x4
60 const TagBitUndefined = 0x8
61 const ValueEmpty      = 0x0
62 const ValueFalse      = TagBitTypeOther | TagBitBool
63 const ValueTrue       = TagBitTypeOther | TagBitBool | 1
64 const ValueUndefined  = TagBitTypeOther | TagBitUndefined
65 const ValueNull       = TagBitTypeOther
66 else
67 const Int32Tag = -1
68 const BooleanTag = -2
69 const NullTag = -3
70 const UndefinedTag = -4
71 const CellTag = -5
72 const EmptyValueTag = -6
73 const DeletedValueTag = -7
74 const LowestTag = DeletedValueTag
75 end
76
77 const CallOpCodeSize = 9
78
79 if X86_64 or ARM64 or C_LOOP
80 const maxFrameExtentForSlowPathCall = 0
81 elsif ARM or ARMv7_TRADITIONAL or ARMv7 or SH4
82 const maxFrameExtentForSlowPathCall = 24
83 elsif X86 or X86_WIN
84 const maxFrameExtentForSlowPathCall = 40
85 elsif MIPS
86 const maxFrameExtentForSlowPathCall = 40
87 end
88
89 # Watchpoint states
90 const ClearWatchpoint = 0
91 const IsWatched = 1
92 const IsInvalidated = 2
93
94 # Some register conventions.
95 if JSVALUE64
96     # - Use a pair of registers to represent the PC: one register for the
97     #   base of the bytecodes, and one register for the index.
98     # - The PC base (or PB for short) should be stored in the csr. It will
99     #   get clobbered on calls to other JS code, but will get saved on calls
100     #   to C functions.
101     # - C calls are still given the Instruction* rather than the PC index.
102     #   This requires an add before the call, and a sub after.
103     const PC = t5
104     const PB = t6
105     const tagTypeNumber = csr1
106     const tagMask = csr2
107     
108     macro loadisFromInstruction(offset, dest)
109         loadis offset * 8[PB, PC, 8], dest
110     end
111     
112     macro loadpFromInstruction(offset, dest)
113         loadp offset * 8[PB, PC, 8], dest
114     end
115     
116     macro storepToInstruction(value, offset)
117         storep value, offset * 8[PB, PC, 8]
118     end
119
120 else
121     const PC = t5
122     macro loadisFromInstruction(offset, dest)
123         loadis offset * 4[PC], dest
124     end
125     
126     macro loadpFromInstruction(offset, dest)
127         loadp offset * 4[PC], dest
128     end
129 end
130
131 # Constants for reasoning about value representation.
132 if BIG_ENDIAN
133     const TagOffset = 0
134     const PayloadOffset = 4
135 else
136     const TagOffset = 4
137     const PayloadOffset = 0
138 end
139
140 # Constant for reasoning about butterflies.
141 const IsArray                  = 1
142 const IndexingShapeMask        = 30
143 const NoIndexingShape          = 0
144 const Int32Shape               = 20
145 const DoubleShape              = 22
146 const ContiguousShape          = 26
147 const ArrayStorageShape        = 28
148 const SlowPutArrayStorageShape = 30
149
150 # Type constants.
151 const StringType = 5
152 const ObjectType = 17
153 const FinalObjectType = 18
154
155 # Type flags constants.
156 const MasqueradesAsUndefined = 1
157 const ImplementsHasInstance = 2
158 const ImplementsDefaultHasInstance = 8
159
160 # Bytecode operand constants.
161 const FirstConstantRegisterIndex = 0x40000000
162
163 # Code type constants.
164 const GlobalCode = 0
165 const EvalCode = 1
166 const FunctionCode = 2
167
168 # The interpreter steals the tag word of the argument count.
169 const LLIntReturnPC = ArgumentCount + TagOffset
170
171 # String flags.
172 const HashFlags8BitBuffer = 32
173
174 # Copied from PropertyOffset.h
175 const firstOutOfLineOffset = 100
176
177 # ResolveType
178 const GlobalProperty = 0
179 const GlobalVar = 1
180 const ClosureVar = 2
181 const GlobalPropertyWithVarInjectionChecks = 3
182 const GlobalVarWithVarInjectionChecks = 4
183 const ClosureVarWithVarInjectionChecks = 5
184 const Dynamic = 6
185
186 const ResolveModeMask = 0xffff
187
188 const MarkedBlockSize = 64 * 1024
189 const MarkedBlockMask = ~(MarkedBlockSize - 1)
190 # Constants for checking mark bits.
191 const AtomNumberShift = 3
192 const BitMapWordShift = 4
193
194 # Allocation constants
195 if JSVALUE64
196     const JSFinalObjectSizeClassIndex = 1
197 else
198     const JSFinalObjectSizeClassIndex = 3
199 end
200
201 # This must match wtf/Vector.h
202 const VectorBufferOffset = 0
203 if JSVALUE64
204     const VectorSizeOffset = 12
205 else
206     const VectorSizeOffset = 8
207 end
208
209 # Some common utilities.
210 macro crash()
211     if C_LOOP
212         cloopCrash
213     else
214         call _llint_crash
215     end
216 end
217
218 macro assert(assertion)
219     if ASSERT_ENABLED
220         assertion(.ok)
221         crash()
222     .ok:
223     end
224 end
225
226 macro checkStackPointerAlignment(tempReg, location)
227     if ARM64 or C_LOOP
228         # ARM64 will check for us!
229         # C_LOOP does not need the alignment, and can use a little perf
230         # improvement from avoiding useless work.
231     else
232         if ARM or ARMv7 or ARMv7_TRADITIONAL
233             # ARM can't do logical ops with the sp as a source
234             move sp, tempReg
235             andp 0xf, tempReg
236         else
237             andp sp, 0xf, tempReg
238         end
239         btpz tempReg, .stackPointerOkay
240         move location, tempReg
241         break
242     .stackPointerOkay:
243     end
244 end
245
246 macro preserveCallerPCAndCFR()
247     if C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS or SH4
248         push lr
249         push cfr
250     elsif X86 or X86_WIN or X86_64
251         push cfr
252     elsif ARM64
253         pushLRAndFP
254     else
255         error
256     end
257     move sp, cfr
258 end
259
260 macro restoreCallerPCAndCFR()
261     move cfr, sp
262     if C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS or SH4
263         pop cfr
264         pop lr
265     elsif X86 or X86_WIN or X86_64
266         pop cfr
267     elsif ARM64
268         popLRAndFP
269     end
270 end
271
272 macro preserveReturnAddressAfterCall(destinationRegister)
273     if C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or ARM64 or MIPS or SH4
274         # In C_LOOP case, we're only preserving the bytecode vPC.
275         move lr, destinationRegister
276     elsif X86 or X86_WIN or X86_64
277         pop destinationRegister
278     else
279         error
280     end
281 end
282
283 macro restoreReturnAddressBeforeReturn(sourceRegister)
284     if C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or ARM64 or MIPS or SH4
285         # In C_LOOP case, we're only restoring the bytecode vPC.
286         move sourceRegister, lr
287     elsif X86 or X86_WIN or X86_64
288         push sourceRegister
289     else
290         error
291     end
292 end
293
294 macro functionPrologue()
295     if X86 or X86_WIN or X86_64
296         push cfr
297     elsif ARM64
298         pushLRAndFP
299     elsif C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS
300         push lr
301         push cfr
302     end
303     move sp, cfr
304 end
305
306 macro functionEpilogue()
307     if X86 or X86_WIN or X86_64
308         pop cfr
309     elsif ARM64
310         popLRAndFP
311     elsif C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS
312         pop cfr
313         pop lr
314     end
315 end
316
317 macro callToJavaScriptPrologue()
318     if X86_64
319         push cfr
320         push t0
321     elsif X86 or X86_WIN
322         push cfr
323     elsif ARM64
324         pushLRAndFP
325     elsif C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS
326         push lr
327         push cfr
328     end
329     pushCalleeSaves
330     if X86
331         subp 12, sp
332     elsif X86_WIN
333         subp 16, sp
334         move sp, t4
335         move t4, t0
336         move t4, t2
337         andp 0xf, t2
338         andp 0xfffffff0, t0
339         move t0, sp
340         storep t4, [sp]
341     elsif ARM or ARMv7 or ARMv7_TRADITIONAL
342         subp 4, sp
343         move sp, t4
344         clrbp t4, 0xf, t5
345         move t5, sp
346         storep t4, [sp]
347     end
348 end
349
350 macro callToJavaScriptEpilogue()
351     if ARMv7
352         addp CallFrameHeaderSlots * 8, cfr, t4
353         move t4, sp
354     else
355         addp CallFrameHeaderSlots * 8, cfr, sp
356     end
357
358     loadp CallerFrame[cfr], cfr
359
360     if X86
361         addp 12, sp
362     elsif X86_WIN
363         pop t4
364         move t4, sp
365         addp 16, sp
366     elsif ARM or ARMv7 or ARMv7_TRADITIONAL
367         pop t4
368         move t4, sp
369         addp 4, sp
370     end
371
372     popCalleeSaves
373     if X86_64
374         pop t2
375         pop cfr
376     elsif X86 or X86_WIN
377         pop cfr
378     elsif ARM64
379         popLRAndFP
380     elsif C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS
381         pop cfr
382         pop lr
383     end
384 end
385
386 macro moveStackPointerForCodeBlock(codeBlock, scratch)
387     loadi CodeBlock::m_numCalleeRegisters[codeBlock], scratch
388     lshiftp 3, scratch
389     addp maxFrameExtentForSlowPathCall, scratch
390     if ARMv7
391         subp cfr, scratch, scratch
392         move scratch, sp
393     else
394         subp cfr, scratch, sp
395     end
396 end
397
398 macro restoreStackPointerAfterCall()
399     loadp CodeBlock[cfr], t2
400     moveStackPointerForCodeBlock(t2, t4)
401 end
402
403 macro traceExecution()
404     if EXECUTION_TRACING
405         callSlowPath(_llint_trace)
406     end
407 end
408
409 macro callTargetFunction(callLinkInfo, calleeFramePtr)
410     move calleeFramePtr, sp
411     if C_LOOP
412         cloopCallJSFunction LLIntCallLinkInfo::machineCodeTarget[callLinkInfo]
413     else
414         call LLIntCallLinkInfo::machineCodeTarget[callLinkInfo]
415     end
416     restoreStackPointerAfterCall()
417     dispatchAfterCall()
418 end
419
420 macro slowPathForCall(slowPath)
421     callCallSlowPath(
422         slowPath,
423         macro (callee)
424             btpz t1, .dontUpdateSP
425             if ARMv7
426                 addp CallerFrameAndPCSize, t1, t1
427                 move t1, sp
428             else
429                 addp CallerFrameAndPCSize, t1, sp
430             end
431         .dontUpdateSP:
432             if C_LOOP
433                 cloopCallJSFunction callee
434             else
435                 call callee
436             end
437             restoreStackPointerAfterCall()
438             dispatchAfterCall()
439         end)
440 end
441
442 macro arrayProfile(structureAndIndexingType, profile, scratch)
443     const structure = structureAndIndexingType
444     const indexingType = structureAndIndexingType
445     storep structure, ArrayProfile::m_lastSeenStructure[profile]
446     loadb Structure::m_indexingType[structure], indexingType
447 end
448
449 macro checkMarkByte(cell, scratch1, scratch2, continuation)
450     move cell, scratch1
451     move cell, scratch2
452
453     andp MarkedBlockMask, scratch1
454     andp ~MarkedBlockMask, scratch2
455
456     rshiftp AtomNumberShift + BitMapWordShift, scratch2
457     loadb MarkedBlock::m_marks[scratch1, scratch2, 1], scratch1
458     continuation(scratch1)
459 end
460
461 macro checkSwitchToJIT(increment, action)
462     loadp CodeBlock[cfr], t0
463     baddis increment, CodeBlock::m_llintExecuteCounter + ExecutionCounter::m_counter[t0], .continue
464     action()
465     .continue:
466 end
467
468 macro checkSwitchToJITForEpilogue()
469     checkSwitchToJIT(
470         10,
471         macro ()
472             callSlowPath(_llint_replace)
473         end)
474 end
475
476 macro assertNotConstant(index)
477     assert(macro (ok) bilt index, FirstConstantRegisterIndex, ok end)
478 end
479
480 macro functionForCallCodeBlockGetter(targetRegister)
481     loadp Callee[cfr], targetRegister
482     loadp JSFunction::m_executable[targetRegister], targetRegister
483     loadp FunctionExecutable::m_codeBlockForCall[targetRegister], targetRegister
484 end
485
486 macro functionForConstructCodeBlockGetter(targetRegister)
487     loadp Callee[cfr], targetRegister
488     loadp JSFunction::m_executable[targetRegister], targetRegister
489     loadp FunctionExecutable::m_codeBlockForConstruct[targetRegister], targetRegister
490 end
491
492 macro notFunctionCodeBlockGetter(targetRegister)
493     loadp CodeBlock[cfr], targetRegister
494 end
495
496 macro functionCodeBlockSetter(sourceRegister)
497     storep sourceRegister, CodeBlock[cfr]
498 end
499
500 macro notFunctionCodeBlockSetter(sourceRegister)
501     # Nothing to do!
502 end
503
504 # Do the bare minimum required to execute code. Sets up the PC, leave the CodeBlock*
505 # in t1. May also trigger prologue entry OSR.
506 macro prologue(codeBlockGetter, codeBlockSetter, osrSlowPath, traceSlowPath)
507     # Set up the call frame and check if we should OSR.
508     preserveCallerPCAndCFR()
509
510     if EXECUTION_TRACING
511         subp maxFrameExtentForSlowPathCall, sp
512         callSlowPath(traceSlowPath)
513         addp maxFrameExtentForSlowPathCall, sp
514     end
515     codeBlockGetter(t1)
516 if C_LOOP
517 else
518     baddis 5, CodeBlock::m_llintExecuteCounter + ExecutionCounter::m_counter[t1], .continue
519     if JSVALUE64
520         cCall2(osrSlowPath, cfr, PC)
521     else
522         # We are after the function prologue, but before we have set up sp from the CodeBlock.
523         # Temporarily align stack pointer for this call.
524         subp 8, sp
525         cCall2(osrSlowPath, cfr, PC)
526         addp 8, sp
527     end
528     btpz t0, .recover
529     move cfr, sp # restore the previous sp
530     # pop the callerFrame since we will jump to a function that wants to save it
531     if ARM64
532         popLRAndFP
533     elsif ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS or SH4
534         pop cfr
535         pop lr
536     else
537         pop cfr
538     end
539     jmp t0
540 .recover:
541     codeBlockGetter(t1)
542 .continue:
543 end
544
545     codeBlockSetter(t1)
546     
547     moveStackPointerForCodeBlock(t1, t2)
548
549     # Set up the PC.
550     if JSVALUE64
551         loadp CodeBlock::m_instructions[t1], PB
552         move 0, PC
553     else
554         loadp CodeBlock::m_instructions[t1], PC
555     end
556 end
557
558 # Expects that CodeBlock is in t1, which is what prologue() leaves behind.
559 # Must call dispatch(0) after calling this.
560 macro functionInitialization(profileArgSkip)
561     # Profile the arguments. Unfortunately, we have no choice but to do this. This
562     # code is pretty horrendous because of the difference in ordering between
563     # arguments and value profiles, the desire to have a simple loop-down-to-zero
564     # loop, and the desire to use only three registers so as to preserve the PC and
565     # the code block. It is likely that this code should be rewritten in a more
566     # optimal way for architectures that have more than five registers available
567     # for arbitrary use in the interpreter.
568     loadi CodeBlock::m_numParameters[t1], t0
569     addp -profileArgSkip, t0 # Use addi because that's what has the peephole
570     assert(macro (ok) bpgteq t0, 0, ok end)
571     btpz t0, .argumentProfileDone
572     loadp CodeBlock::m_argumentValueProfiles + VectorBufferOffset[t1], t3
573     mulp sizeof ValueProfile, t0, t2 # Aaaaahhhh! Need strength reduction!
574     lshiftp 3, t0
575     addp t2, t3
576 .argumentProfileLoop:
577     if JSVALUE64
578         loadq ThisArgumentOffset - 8 + profileArgSkip * 8[cfr, t0], t2
579         subp sizeof ValueProfile, t3
580         storeq t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets[t3]
581     else
582         loadi ThisArgumentOffset + TagOffset - 8 + profileArgSkip * 8[cfr, t0], t2
583         subp sizeof ValueProfile, t3
584         storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + TagOffset[t3]
585         loadi ThisArgumentOffset + PayloadOffset - 8 + profileArgSkip * 8[cfr, t0], t2
586         storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + PayloadOffset[t3]
587     end
588     baddpnz -8, t0, .argumentProfileLoop
589 .argumentProfileDone:
590         
591     # Check stack height.
592     loadi CodeBlock::m_numCalleeRegisters[t1], t0
593     loadp CodeBlock::m_vm[t1], t2
594     lshiftp 3, t0
595     addi maxFrameExtentForSlowPathCall, t0
596     subp cfr, t0, t0
597     bpbeq VM::m_jsStackLimit[t2], t0, .stackHeightOK
598
599     # Stack height check failed - need to call a slow_path.
600     callSlowPath(_llint_stack_check)
601     bpeq t1, 0, .stackHeightOK
602     move t1, cfr
603 .stackHeightOK:
604 end
605
606 macro allocateJSObject(allocator, structure, result, scratch1, slowCase)
607     if ALWAYS_ALLOCATE_SLOW
608         jmp slowCase
609     else
610         const offsetOfFirstFreeCell = 
611             MarkedAllocator::m_freeList + 
612             MarkedBlock::FreeList::head
613
614         # Get the object from the free list.   
615         loadp offsetOfFirstFreeCell[allocator], result
616         btpz result, slowCase
617         
618         # Remove the object from the free list.
619         loadp [result], scratch1
620         storep scratch1, offsetOfFirstFreeCell[allocator]
621     
622         # Initialize the object.
623         storep structure, JSCell::m_structure[result]
624         storep 0, JSObject::m_butterfly[result]
625     end
626 end
627
628 macro doReturn()
629     restoreCallerPCAndCFR()
630     ret
631 end
632
633 # Dummy entry point the C Loop uses to initialize.
634 if C_LOOP
635 _llint_c_loop_init:
636     crash()
637 end
638
639 # stub to call into JavaScript or Native functions
640 # EncodedJSValue callToJavaScript(void* code, ExecState** vmTopCallFrame, ProtoCallFrame* protoFrame)
641 # EncodedJSValue callToNativeFunction(void* code, ExecState** vmTopCallFrame, ProtoCallFrame* protoFrame)
642
643 if C_LOOP
644 _llint_call_to_javascript:
645 else
646 _callToJavaScript:
647 end
648     doCallToJavaScript(makeJavaScriptCall)
649
650
651 if C_LOOP
652 _llint_call_to_native_function:
653 else
654 _callToNativeFunction:
655 end
656     doCallToJavaScript(makeHostFunctionCall)
657
658
659 if C_LOOP
660 else
661 # void sanitizeStackForVMImpl(VM* vm)
662 _sanitizeStackForVMImpl:
663     if X86_64
664         const vm = t4
665         const address = t1
666         const zeroValue = t0
667     elsif X86 or X86_WIN
668         const vm = t2
669         const address = t1
670         const zeroValue = t0
671     else
672         const vm = a0
673         const address = t1
674         const zeroValue = t2
675     end
676
677     if X86 or X86_WIN
678         loadp 4[sp], vm
679     end
680
681     loadp VM::m_lastStackTop[vm], address
682     bpbeq sp, address, .zeroFillDone
683
684     move 0, zeroValue
685 .zeroFillLoop:
686     storep zeroValue, [address]
687     addp PtrSize, address
688     bpa sp, address, .zeroFillLoop
689
690 .zeroFillDone:
691     move sp, address
692     storep address, VM::m_lastStackTop[vm]
693     ret
694 end
695
696
697 _llint_program_prologue:
698     prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
699     dispatch(0)
700
701
702 _llint_eval_prologue:
703     prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
704     dispatch(0)
705
706
707 _llint_function_for_call_prologue:
708     prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call, _llint_trace_prologue_function_for_call)
709     functionInitialization(0)
710     dispatch(0)
711     
712
713 _llint_function_for_construct_prologue:
714     prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct, _llint_trace_prologue_function_for_construct)
715     functionInitialization(1)
716     dispatch(0)
717     
718
719 _llint_function_for_call_arity_check:
720     prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call_arityCheck, _llint_trace_arityCheck_for_call)
721     functionArityCheck(.functionForCallBegin, _slow_path_call_arityCheck)
722 .functionForCallBegin:
723     functionInitialization(0)
724     dispatch(0)
725
726
727 _llint_function_for_construct_arity_check:
728     prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct_arityCheck, _llint_trace_arityCheck_for_construct)
729     functionArityCheck(.functionForConstructBegin, _slow_path_construct_arityCheck)
730 .functionForConstructBegin:
731     functionInitialization(1)
732     dispatch(0)
733
734
735 # Value-representation-specific code.
736 if JSVALUE64
737     include LowLevelInterpreter64
738 else
739     include LowLevelInterpreter32_64
740 end
741
742
743 # Value-representation-agnostic code.
744 _llint_op_touch_entry:
745     traceExecution()
746     callSlowPath(_slow_path_touch_entry)
747     dispatch(1)
748
749
750 _llint_op_new_array:
751     traceExecution()
752     callSlowPath(_llint_slow_path_new_array)
753     dispatch(5)
754
755
756 _llint_op_new_array_with_size:
757     traceExecution()
758     callSlowPath(_llint_slow_path_new_array_with_size)
759     dispatch(4)
760
761
762 _llint_op_new_array_buffer:
763     traceExecution()
764     callSlowPath(_llint_slow_path_new_array_buffer)
765     dispatch(5)
766
767
768 _llint_op_new_regexp:
769     traceExecution()
770     callSlowPath(_llint_slow_path_new_regexp)
771     dispatch(3)
772
773
774 _llint_op_less:
775     traceExecution()
776     callSlowPath(_slow_path_less)
777     dispatch(4)
778
779
780 _llint_op_lesseq:
781     traceExecution()
782     callSlowPath(_slow_path_lesseq)
783     dispatch(4)
784
785
786 _llint_op_greater:
787     traceExecution()
788     callSlowPath(_slow_path_greater)
789     dispatch(4)
790
791
792 _llint_op_greatereq:
793     traceExecution()
794     callSlowPath(_slow_path_greatereq)
795     dispatch(4)
796
797
798 _llint_op_mod:
799     traceExecution()
800     callSlowPath(_slow_path_mod)
801     dispatch(4)
802
803
804 _llint_op_typeof:
805     traceExecution()
806     callSlowPath(_slow_path_typeof)
807     dispatch(3)
808
809
810 _llint_op_is_object:
811     traceExecution()
812     callSlowPath(_slow_path_is_object)
813     dispatch(3)
814
815
816 _llint_op_is_function:
817     traceExecution()
818     callSlowPath(_slow_path_is_function)
819     dispatch(3)
820
821
822 _llint_op_in:
823     traceExecution()
824     callSlowPath(_slow_path_in)
825     dispatch(4)
826
827 macro withInlineStorage(object, propertyStorage, continuation)
828     # Indicate that the object is the property storage, and that the
829     # property storage register is unused.
830     continuation(object, propertyStorage)
831 end
832
833 macro withOutOfLineStorage(object, propertyStorage, continuation)
834     loadp JSObject::m_butterfly[object], propertyStorage
835     # Indicate that the propertyStorage register now points to the
836     # property storage, and that the object register may be reused
837     # if the object pointer is not needed anymore.
838     continuation(propertyStorage, object)
839 end
840
841
842 _llint_op_del_by_id:
843     traceExecution()
844     callSlowPath(_llint_slow_path_del_by_id)
845     dispatch(4)
846
847
848 _llint_op_del_by_val:
849     traceExecution()
850     callSlowPath(_llint_slow_path_del_by_val)
851     dispatch(4)
852
853
854 _llint_op_put_by_index:
855     traceExecution()
856     callSlowPath(_llint_slow_path_put_by_index)
857     dispatch(4)
858
859
860 _llint_op_put_getter_setter:
861     traceExecution()
862     callSlowPath(_llint_slow_path_put_getter_setter)
863     dispatch(5)
864
865
866 _llint_op_jtrue:
867     traceExecution()
868     jumpTrueOrFalse(
869         macro (value, target) btinz value, target end,
870         _llint_slow_path_jtrue)
871
872
873 _llint_op_jfalse:
874     traceExecution()
875     jumpTrueOrFalse(
876         macro (value, target) btiz value, target end,
877         _llint_slow_path_jfalse)
878
879
880 _llint_op_jless:
881     traceExecution()
882     compare(
883         macro (left, right, target) bilt left, right, target end,
884         macro (left, right, target) bdlt left, right, target end,
885         _llint_slow_path_jless)
886
887
888 _llint_op_jnless:
889     traceExecution()
890     compare(
891         macro (left, right, target) bigteq left, right, target end,
892         macro (left, right, target) bdgtequn left, right, target end,
893         _llint_slow_path_jnless)
894
895
896 _llint_op_jgreater:
897     traceExecution()
898     compare(
899         macro (left, right, target) bigt left, right, target end,
900         macro (left, right, target) bdgt left, right, target end,
901         _llint_slow_path_jgreater)
902
903
904 _llint_op_jngreater:
905     traceExecution()
906     compare(
907         macro (left, right, target) bilteq left, right, target end,
908         macro (left, right, target) bdltequn left, right, target end,
909         _llint_slow_path_jngreater)
910
911
912 _llint_op_jlesseq:
913     traceExecution()
914     compare(
915         macro (left, right, target) bilteq left, right, target end,
916         macro (left, right, target) bdlteq left, right, target end,
917         _llint_slow_path_jlesseq)
918
919
920 _llint_op_jnlesseq:
921     traceExecution()
922     compare(
923         macro (left, right, target) bigt left, right, target end,
924         macro (left, right, target) bdgtun left, right, target end,
925         _llint_slow_path_jnlesseq)
926
927
928 _llint_op_jgreatereq:
929     traceExecution()
930     compare(
931         macro (left, right, target) bigteq left, right, target end,
932         macro (left, right, target) bdgteq left, right, target end,
933         _llint_slow_path_jgreatereq)
934
935
936 _llint_op_jngreatereq:
937     traceExecution()
938     compare(
939         macro (left, right, target) bilt left, right, target end,
940         macro (left, right, target) bdltun left, right, target end,
941         _llint_slow_path_jngreatereq)
942
943
944 _llint_op_loop_hint:
945     traceExecution()
946     loadp CodeBlock[cfr], t1
947     loadp CodeBlock::m_vm[t1], t1
948     loadb VM::watchdog+Watchdog::m_timerDidFire[t1], t0
949     btbnz t0, .handleWatchdogTimer
950 .afterWatchdogTimerCheck:
951     checkSwitchToJITForLoop()
952     dispatch(1)
953 .handleWatchdogTimer:
954     callWatchdogTimerHandler(.throwHandler)
955     jmp .afterWatchdogTimerCheck
956 .throwHandler:
957     jmp _llint_throw_from_slow_path_trampoline
958
959 _llint_op_switch_string:
960     traceExecution()
961     callSlowPath(_llint_slow_path_switch_string)
962     dispatch(0)
963
964
965 _llint_op_new_func_exp:
966     traceExecution()
967     callSlowPath(_llint_slow_path_new_func_exp)
968     dispatch(3)
969
970
971 _llint_op_call:
972     traceExecution()
973     arrayProfileForCall()
974     doCall(_llint_slow_path_call)
975
976
977 _llint_op_construct:
978     traceExecution()
979     doCall(_llint_slow_path_construct)
980
981
982 _llint_op_call_varargs:
983     traceExecution()
984     callSlowPath(_llint_slow_path_size_frame_for_varargs)
985     branchIfException(_llint_throw_from_slow_path_trampoline)
986     # calleeFrame in t1
987     if JSVALUE64
988         move t1, sp
989     else
990         # The calleeFrame is not stack aligned, move down by CallerFrameAndPCSize to align
991         if ARMv7
992             subp t1, CallerFrameAndPCSize, t2
993             move t2, sp
994         else
995             subp t1, CallerFrameAndPCSize, sp
996         end
997     end
998     slowPathForCall(_llint_slow_path_call_varargs)
999
1000
1001 _llint_op_call_eval:
1002     traceExecution()
1003     
1004     # Eval is executed in one of two modes:
1005     #
1006     # 1) We find that we're really invoking eval() in which case the
1007     #    execution is perfomed entirely inside the slow_path, and it
1008     #    returns the PC of a function that just returns the return value
1009     #    that the eval returned.
1010     #
1011     # 2) We find that we're invoking something called eval() that is not
1012     #    the real eval. Then the slow_path returns the PC of the thing to
1013     #    call, and we call it.
1014     #
1015     # This allows us to handle two cases, which would require a total of
1016     # up to four pieces of state that cannot be easily packed into two
1017     # registers (C functions can return up to two registers, easily):
1018     #
1019     # - The call frame register. This may or may not have been modified
1020     #   by the slow_path, but the convention is that it returns it. It's not
1021     #   totally clear if that's necessary, since the cfr is callee save.
1022     #   But that's our style in this here interpreter so we stick with it.
1023     #
1024     # - A bit to say if the slow_path successfully executed the eval and has
1025     #   the return value, or did not execute the eval but has a PC for us
1026     #   to call.
1027     #
1028     # - Either:
1029     #   - The JS return value (two registers), or
1030     #
1031     #   - The PC to call.
1032     #
1033     # It turns out to be easier to just always have this return the cfr
1034     # and a PC to call, and that PC may be a dummy thunk that just
1035     # returns the JS value that the eval returned.
1036     
1037     slowPathForCall(_llint_slow_path_call_eval)
1038
1039
1040 _llint_generic_return_point:
1041     dispatchAfterCall()
1042
1043
1044 _llint_op_strcat:
1045     traceExecution()
1046     callSlowPath(_slow_path_strcat)
1047     dispatch(4)
1048
1049
1050 _llint_op_get_pnames:
1051     traceExecution()
1052     callSlowPath(_llint_slow_path_get_pnames)
1053     dispatch(0) # The slow_path either advances the PC or jumps us to somewhere else.
1054
1055
1056 _llint_op_push_with_scope:
1057     traceExecution()
1058     callSlowPath(_llint_slow_path_push_with_scope)
1059     dispatch(2)
1060
1061
1062 _llint_op_pop_scope:
1063     traceExecution()
1064     callSlowPath(_llint_slow_path_pop_scope)
1065     dispatch(1)
1066
1067
1068 _llint_op_push_name_scope:
1069     traceExecution()
1070     callSlowPath(_llint_slow_path_push_name_scope)
1071     dispatch(4)
1072
1073
1074 _llint_op_throw:
1075     traceExecution()
1076     callSlowPath(_llint_slow_path_throw)
1077     dispatch(2)
1078
1079
1080 _llint_op_throw_static_error:
1081     traceExecution()
1082     callSlowPath(_llint_slow_path_throw_static_error)
1083     dispatch(3)
1084
1085
1086 _llint_op_profile_will_call:
1087     traceExecution()
1088     loadp CodeBlock[cfr], t0
1089     loadp CodeBlock::m_vm[t0], t0
1090     loadi VM::m_enabledProfiler[t0], t0
1091     btpz t0, .opProfilerWillCallDone
1092     callSlowPath(_llint_slow_path_profile_will_call)
1093 .opProfilerWillCallDone:
1094     dispatch(2)
1095
1096
1097 _llint_op_profile_did_call:
1098     traceExecution()
1099     loadp CodeBlock[cfr], t0
1100     loadp CodeBlock::m_vm[t0], t0
1101     loadi VM::m_enabledProfiler[t0], t0
1102     btpz t0, .opProfilerDidCallDone
1103     callSlowPath(_llint_slow_path_profile_did_call)
1104 .opProfilerDidCallDone:
1105     dispatch(2)
1106
1107
1108 _llint_op_debug:
1109     traceExecution()
1110     loadp CodeBlock[cfr], t0
1111     loadi CodeBlock::m_debuggerRequests[t0], t0
1112     btiz t0, .opDebugDone
1113     callSlowPath(_llint_slow_path_debug)
1114 .opDebugDone:                    
1115     dispatch(3)
1116
1117
1118 _llint_native_call_trampoline:
1119     nativeCallTrampoline(NativeExecutable::m_function)
1120
1121
1122 _llint_native_construct_trampoline:
1123     nativeCallTrampoline(NativeExecutable::m_constructor)
1124
1125
1126 # Lastly, make sure that we can link even though we don't support all opcodes.
1127 # These opcodes should never arise when using LLInt or either JIT. We assert
1128 # as much.
1129
1130 macro notSupported()
1131     if ASSERT_ENABLED
1132         crash()
1133     else
1134         # We should use whatever the smallest possible instruction is, just to
1135         # ensure that there is a gap between instruction labels. If multiple
1136         # smallest instructions exist, we should pick the one that is most
1137         # likely result in execution being halted. Currently that is the break
1138         # instruction on all architectures we're interested in. (Break is int3
1139         # on Intel, which is 1 byte, and bkpt on ARMv7, which is 2 bytes.)
1140         break
1141     end
1142 end
1143
1144 _llint_op_init_global_const_nop:
1145     dispatch(5)
1146