Auto generate bytecode information for bytecode parser and LLInt
[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(cellAndIndexingType, profile, scratch)
443     const cell = cellAndIndexingType
444     const indexingType = cellAndIndexingType 
445     loadi JSCell::m_structureID[cell], scratch
446     storei scratch, ArrayProfile::m_lastSeenStructureID[profile]
447     loadb JSCell::m_indexingType[cell], indexingType
448 end
449
450 macro checkMarkByte(cell, scratch1, scratch2, continuation)
451     move cell, scratch1
452     move cell, scratch2
453
454     andp MarkedBlockMask, scratch1
455     andp ~MarkedBlockMask, scratch2
456
457     rshiftp AtomNumberShift + BitMapWordShift, scratch2
458     loadb MarkedBlock::m_marks[scratch1, scratch2, 1], scratch1
459     continuation(scratch1)
460 end
461
462 macro checkSwitchToJIT(increment, action)
463     loadp CodeBlock[cfr], t0
464     baddis increment, CodeBlock::m_llintExecuteCounter + ExecutionCounter::m_counter[t0], .continue
465     action()
466     .continue:
467 end
468
469 macro checkSwitchToJITForEpilogue()
470     checkSwitchToJIT(
471         10,
472         macro ()
473             callSlowPath(_llint_replace)
474         end)
475 end
476
477 macro assertNotConstant(index)
478     assert(macro (ok) bilt index, FirstConstantRegisterIndex, ok end)
479 end
480
481 macro functionForCallCodeBlockGetter(targetRegister)
482     loadp Callee[cfr], targetRegister
483     loadp JSFunction::m_executable[targetRegister], targetRegister
484     loadp FunctionExecutable::m_codeBlockForCall[targetRegister], targetRegister
485 end
486
487 macro functionForConstructCodeBlockGetter(targetRegister)
488     loadp Callee[cfr], targetRegister
489     loadp JSFunction::m_executable[targetRegister], targetRegister
490     loadp FunctionExecutable::m_codeBlockForConstruct[targetRegister], targetRegister
491 end
492
493 macro notFunctionCodeBlockGetter(targetRegister)
494     loadp CodeBlock[cfr], targetRegister
495 end
496
497 macro functionCodeBlockSetter(sourceRegister)
498     storep sourceRegister, CodeBlock[cfr]
499 end
500
501 macro notFunctionCodeBlockSetter(sourceRegister)
502     # Nothing to do!
503 end
504
505 # Do the bare minimum required to execute code. Sets up the PC, leave the CodeBlock*
506 # in t1. May also trigger prologue entry OSR.
507 macro prologue(codeBlockGetter, codeBlockSetter, osrSlowPath, traceSlowPath)
508     # Set up the call frame and check if we should OSR.
509     preserveCallerPCAndCFR()
510
511     if EXECUTION_TRACING
512         subp maxFrameExtentForSlowPathCall, sp
513         callSlowPath(traceSlowPath)
514         addp maxFrameExtentForSlowPathCall, sp
515     end
516     codeBlockGetter(t1)
517 if C_LOOP
518 else
519     baddis 5, CodeBlock::m_llintExecuteCounter + ExecutionCounter::m_counter[t1], .continue
520     if JSVALUE64
521         cCall2(osrSlowPath, cfr, PC)
522     else
523         # We are after the function prologue, but before we have set up sp from the CodeBlock.
524         # Temporarily align stack pointer for this call.
525         subp 8, sp
526         cCall2(osrSlowPath, cfr, PC)
527         addp 8, sp
528     end
529     btpz t0, .recover
530     move cfr, sp # restore the previous sp
531     # pop the callerFrame since we will jump to a function that wants to save it
532     if ARM64
533         popLRAndFP
534     elsif ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS or SH4
535         pop cfr
536         pop lr
537     else
538         pop cfr
539     end
540     jmp t0
541 .recover:
542     codeBlockGetter(t1)
543 .continue:
544 end
545
546     codeBlockSetter(t1)
547     
548     moveStackPointerForCodeBlock(t1, t2)
549
550     # Set up the PC.
551     if JSVALUE64
552         loadp CodeBlock::m_instructions[t1], PB
553         move 0, PC
554     else
555         loadp CodeBlock::m_instructions[t1], PC
556     end
557 end
558
559 # Expects that CodeBlock is in t1, which is what prologue() leaves behind.
560 # Must call dispatch(0) after calling this.
561 macro functionInitialization(profileArgSkip)
562     # Profile the arguments. Unfortunately, we have no choice but to do this. This
563     # code is pretty horrendous because of the difference in ordering between
564     # arguments and value profiles, the desire to have a simple loop-down-to-zero
565     # loop, and the desire to use only three registers so as to preserve the PC and
566     # the code block. It is likely that this code should be rewritten in a more
567     # optimal way for architectures that have more than five registers available
568     # for arbitrary use in the interpreter.
569     loadi CodeBlock::m_numParameters[t1], t0
570     addp -profileArgSkip, t0 # Use addi because that's what has the peephole
571     assert(macro (ok) bpgteq t0, 0, ok end)
572     btpz t0, .argumentProfileDone
573     loadp CodeBlock::m_argumentValueProfiles + VectorBufferOffset[t1], t3
574     mulp sizeof ValueProfile, t0, t2 # Aaaaahhhh! Need strength reduction!
575     lshiftp 3, t0
576     addp t2, t3
577 .argumentProfileLoop:
578     if JSVALUE64
579         loadq ThisArgumentOffset - 8 + profileArgSkip * 8[cfr, t0], t2
580         subp sizeof ValueProfile, t3
581         storeq t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets[t3]
582     else
583         loadi ThisArgumentOffset + TagOffset - 8 + profileArgSkip * 8[cfr, t0], t2
584         subp sizeof ValueProfile, t3
585         storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + TagOffset[t3]
586         loadi ThisArgumentOffset + PayloadOffset - 8 + profileArgSkip * 8[cfr, t0], t2
587         storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + PayloadOffset[t3]
588     end
589     baddpnz -8, t0, .argumentProfileLoop
590 .argumentProfileDone:
591         
592     # Check stack height.
593     loadi CodeBlock::m_numCalleeRegisters[t1], t0
594     loadp CodeBlock::m_vm[t1], t2
595     lshiftp 3, t0
596     addi maxFrameExtentForSlowPathCall, t0
597     subp cfr, t0, t0
598     bpbeq VM::m_jsStackLimit[t2], t0, .stackHeightOK
599
600     # Stack height check failed - need to call a slow_path.
601     callSlowPath(_llint_stack_check)
602     bpeq t1, 0, .stackHeightOK
603     move t1, cfr
604 .stackHeightOK:
605 end
606
607 macro allocateJSObject(allocator, structure, result, scratch1, slowCase)
608     if ALWAYS_ALLOCATE_SLOW
609         jmp slowCase
610     else
611         const offsetOfFirstFreeCell = 
612             MarkedAllocator::m_freeList + 
613             MarkedBlock::FreeList::head
614
615         # Get the object from the free list.   
616         loadp offsetOfFirstFreeCell[allocator], result
617         btpz result, slowCase
618         
619         # Remove the object from the free list.
620         loadp [result], scratch1
621         storep scratch1, offsetOfFirstFreeCell[allocator]
622     
623         # Initialize the object.
624         storep 0, JSObject::m_butterfly[result]
625         storeStructureWithTypeInfo(result, structure, scratch1)
626     end
627 end
628
629 macro doReturn()
630     restoreCallerPCAndCFR()
631     ret
632 end
633
634 # Dummy entry point the C Loop uses to initialize.
635 if C_LOOP
636 _llint_c_loop_init:
637     crash()
638 end
639
640 # stub to call into JavaScript or Native functions
641 # EncodedJSValue callToJavaScript(void* code, ExecState** vmTopCallFrame, ProtoCallFrame* protoFrame)
642 # EncodedJSValue callToNativeFunction(void* code, ExecState** vmTopCallFrame, ProtoCallFrame* protoFrame)
643
644 if C_LOOP
645 _llint_call_to_javascript:
646 else
647 _callToJavaScript:
648 end
649     doCallToJavaScript(makeJavaScriptCall)
650
651
652 if C_LOOP
653 _llint_call_to_native_function:
654 else
655 _callToNativeFunction:
656 end
657     doCallToJavaScript(makeHostFunctionCall)
658
659
660 if C_LOOP
661 else
662 # void sanitizeStackForVMImpl(VM* vm)
663 _sanitizeStackForVMImpl:
664     if X86_64
665         const vm = t4
666         const address = t1
667         const zeroValue = t0
668     elsif X86 or X86_WIN
669         const vm = t2
670         const address = t1
671         const zeroValue = t0
672     else
673         const vm = a0
674         const address = t1
675         const zeroValue = t2
676     end
677
678     if X86 or X86_WIN
679         loadp 4[sp], vm
680     end
681
682     loadp VM::m_lastStackTop[vm], address
683     bpbeq sp, address, .zeroFillDone
684
685     move 0, zeroValue
686 .zeroFillLoop:
687     storep zeroValue, [address]
688     addp PtrSize, address
689     bpa sp, address, .zeroFillLoop
690
691 .zeroFillDone:
692     move sp, address
693     storep address, VM::m_lastStackTop[vm]
694     ret
695 end
696
697
698 _llint_program_prologue:
699     prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
700     dispatch(0)
701
702
703 _llint_eval_prologue:
704     prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
705     dispatch(0)
706
707
708 _llint_function_for_call_prologue:
709     prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call, _llint_trace_prologue_function_for_call)
710     functionInitialization(0)
711     dispatch(0)
712     
713
714 _llint_function_for_construct_prologue:
715     prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct, _llint_trace_prologue_function_for_construct)
716     functionInitialization(1)
717     dispatch(0)
718     
719
720 _llint_function_for_call_arity_check:
721     prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call_arityCheck, _llint_trace_arityCheck_for_call)
722     functionArityCheck(.functionForCallBegin, _slow_path_call_arityCheck)
723 .functionForCallBegin:
724     functionInitialization(0)
725     dispatch(0)
726
727
728 _llint_function_for_construct_arity_check:
729     prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct_arityCheck, _llint_trace_arityCheck_for_construct)
730     functionArityCheck(.functionForConstructBegin, _slow_path_construct_arityCheck)
731 .functionForConstructBegin:
732     functionInitialization(1)
733     dispatch(0)
734
735
736 # Value-representation-specific code.
737 if JSVALUE64
738     include LowLevelInterpreter64
739 else
740     include LowLevelInterpreter32_64
741 end
742
743
744 # Value-representation-agnostic code.
745 _llint_op_touch_entry:
746     traceExecution()
747     callSlowPath(_slow_path_touch_entry)
748     dispatch(1)
749
750
751 _llint_op_new_array:
752     traceExecution()
753     callSlowPath(_llint_slow_path_new_array)
754     dispatch(5)
755
756
757 _llint_op_new_array_with_size:
758     traceExecution()
759     callSlowPath(_llint_slow_path_new_array_with_size)
760     dispatch(4)
761
762
763 _llint_op_new_array_buffer:
764     traceExecution()
765     callSlowPath(_llint_slow_path_new_array_buffer)
766     dispatch(5)
767
768
769 _llint_op_new_regexp:
770     traceExecution()
771     callSlowPath(_llint_slow_path_new_regexp)
772     dispatch(3)
773
774
775 _llint_op_less:
776     traceExecution()
777     callSlowPath(_slow_path_less)
778     dispatch(4)
779
780
781 _llint_op_lesseq:
782     traceExecution()
783     callSlowPath(_slow_path_lesseq)
784     dispatch(4)
785
786
787 _llint_op_greater:
788     traceExecution()
789     callSlowPath(_slow_path_greater)
790     dispatch(4)
791
792
793 _llint_op_greatereq:
794     traceExecution()
795     callSlowPath(_slow_path_greatereq)
796     dispatch(4)
797
798
799 _llint_op_mod:
800     traceExecution()
801     callSlowPath(_slow_path_mod)
802     dispatch(4)
803
804
805 _llint_op_typeof:
806     traceExecution()
807     callSlowPath(_slow_path_typeof)
808     dispatch(3)
809
810
811 _llint_op_is_object:
812     traceExecution()
813     callSlowPath(_slow_path_is_object)
814     dispatch(3)
815
816
817 _llint_op_is_function:
818     traceExecution()
819     callSlowPath(_slow_path_is_function)
820     dispatch(3)
821
822
823 _llint_op_in:
824     traceExecution()
825     callSlowPath(_slow_path_in)
826     dispatch(4)
827
828 macro withInlineStorage(object, propertyStorage, continuation)
829     # Indicate that the object is the property storage, and that the
830     # property storage register is unused.
831     continuation(object, propertyStorage)
832 end
833
834 macro withOutOfLineStorage(object, propertyStorage, continuation)
835     loadp JSObject::m_butterfly[object], propertyStorage
836     # Indicate that the propertyStorage register now points to the
837     # property storage, and that the object register may be reused
838     # if the object pointer is not needed anymore.
839     continuation(propertyStorage, object)
840 end
841
842
843 _llint_op_del_by_id:
844     traceExecution()
845     callSlowPath(_llint_slow_path_del_by_id)
846     dispatch(4)
847
848
849 _llint_op_del_by_val:
850     traceExecution()
851     callSlowPath(_llint_slow_path_del_by_val)
852     dispatch(4)
853
854
855 _llint_op_put_by_index:
856     traceExecution()
857     callSlowPath(_llint_slow_path_put_by_index)
858     dispatch(4)
859
860
861 _llint_op_put_getter_setter:
862     traceExecution()
863     callSlowPath(_llint_slow_path_put_getter_setter)
864     dispatch(5)
865
866
867 _llint_op_jtrue:
868     traceExecution()
869     jumpTrueOrFalse(
870         macro (value, target) btinz value, target end,
871         _llint_slow_path_jtrue)
872
873
874 _llint_op_jfalse:
875     traceExecution()
876     jumpTrueOrFalse(
877         macro (value, target) btiz value, target end,
878         _llint_slow_path_jfalse)
879
880
881 _llint_op_jless:
882     traceExecution()
883     compare(
884         macro (left, right, target) bilt left, right, target end,
885         macro (left, right, target) bdlt left, right, target end,
886         _llint_slow_path_jless)
887
888
889 _llint_op_jnless:
890     traceExecution()
891     compare(
892         macro (left, right, target) bigteq left, right, target end,
893         macro (left, right, target) bdgtequn left, right, target end,
894         _llint_slow_path_jnless)
895
896
897 _llint_op_jgreater:
898     traceExecution()
899     compare(
900         macro (left, right, target) bigt left, right, target end,
901         macro (left, right, target) bdgt left, right, target end,
902         _llint_slow_path_jgreater)
903
904
905 _llint_op_jngreater:
906     traceExecution()
907     compare(
908         macro (left, right, target) bilteq left, right, target end,
909         macro (left, right, target) bdltequn left, right, target end,
910         _llint_slow_path_jngreater)
911
912
913 _llint_op_jlesseq:
914     traceExecution()
915     compare(
916         macro (left, right, target) bilteq left, right, target end,
917         macro (left, right, target) bdlteq left, right, target end,
918         _llint_slow_path_jlesseq)
919
920
921 _llint_op_jnlesseq:
922     traceExecution()
923     compare(
924         macro (left, right, target) bigt left, right, target end,
925         macro (left, right, target) bdgtun left, right, target end,
926         _llint_slow_path_jnlesseq)
927
928
929 _llint_op_jgreatereq:
930     traceExecution()
931     compare(
932         macro (left, right, target) bigteq left, right, target end,
933         macro (left, right, target) bdgteq left, right, target end,
934         _llint_slow_path_jgreatereq)
935
936
937 _llint_op_jngreatereq:
938     traceExecution()
939     compare(
940         macro (left, right, target) bilt left, right, target end,
941         macro (left, right, target) bdltun left, right, target end,
942         _llint_slow_path_jngreatereq)
943
944
945 _llint_op_loop_hint:
946     traceExecution()
947     loadp CodeBlock[cfr], t1
948     loadp CodeBlock::m_vm[t1], t1
949     loadb VM::watchdog+Watchdog::m_timerDidFire[t1], t0
950     btbnz t0, .handleWatchdogTimer
951 .afterWatchdogTimerCheck:
952     checkSwitchToJITForLoop()
953     dispatch(1)
954 .handleWatchdogTimer:
955     callWatchdogTimerHandler(.throwHandler)
956     jmp .afterWatchdogTimerCheck
957 .throwHandler:
958     jmp _llint_throw_from_slow_path_trampoline
959
960 _llint_op_switch_string:
961     traceExecution()
962     callSlowPath(_llint_slow_path_switch_string)
963     dispatch(0)
964
965
966 _llint_op_new_func_exp:
967     traceExecution()
968     callSlowPath(_llint_slow_path_new_func_exp)
969     dispatch(3)
970
971
972 _llint_op_call:
973     traceExecution()
974     arrayProfileForCall()
975     doCall(_llint_slow_path_call)
976
977
978 _llint_op_construct:
979     traceExecution()
980     doCall(_llint_slow_path_construct)
981
982
983 _llint_op_call_varargs:
984     traceExecution()
985     callSlowPath(_llint_slow_path_size_frame_for_varargs)
986     branchIfException(_llint_throw_from_slow_path_trampoline)
987     # calleeFrame in t1
988     if JSVALUE64
989         move t1, sp
990     else
991         # The calleeFrame is not stack aligned, move down by CallerFrameAndPCSize to align
992         if ARMv7
993             subp t1, CallerFrameAndPCSize, t2
994             move t2, sp
995         else
996             subp t1, CallerFrameAndPCSize, sp
997         end
998     end
999     slowPathForCall(_llint_slow_path_call_varargs)
1000
1001
1002 _llint_op_call_eval:
1003     traceExecution()
1004     
1005     # Eval is executed in one of two modes:
1006     #
1007     # 1) We find that we're really invoking eval() in which case the
1008     #    execution is perfomed entirely inside the slow_path, and it
1009     #    returns the PC of a function that just returns the return value
1010     #    that the eval returned.
1011     #
1012     # 2) We find that we're invoking something called eval() that is not
1013     #    the real eval. Then the slow_path returns the PC of the thing to
1014     #    call, and we call it.
1015     #
1016     # This allows us to handle two cases, which would require a total of
1017     # up to four pieces of state that cannot be easily packed into two
1018     # registers (C functions can return up to two registers, easily):
1019     #
1020     # - The call frame register. This may or may not have been modified
1021     #   by the slow_path, but the convention is that it returns it. It's not
1022     #   totally clear if that's necessary, since the cfr is callee save.
1023     #   But that's our style in this here interpreter so we stick with it.
1024     #
1025     # - A bit to say if the slow_path successfully executed the eval and has
1026     #   the return value, or did not execute the eval but has a PC for us
1027     #   to call.
1028     #
1029     # - Either:
1030     #   - The JS return value (two registers), or
1031     #
1032     #   - The PC to call.
1033     #
1034     # It turns out to be easier to just always have this return the cfr
1035     # and a PC to call, and that PC may be a dummy thunk that just
1036     # returns the JS value that the eval returned.
1037     
1038     slowPathForCall(_llint_slow_path_call_eval)
1039
1040
1041 _llint_generic_return_point:
1042     dispatchAfterCall()
1043
1044
1045 _llint_op_strcat:
1046     traceExecution()
1047     callSlowPath(_slow_path_strcat)
1048     dispatch(4)
1049
1050
1051 _llint_op_get_pnames:
1052     traceExecution()
1053     callSlowPath(_llint_slow_path_get_pnames)
1054     dispatch(0) # The slow_path either advances the PC or jumps us to somewhere else.
1055
1056
1057 _llint_op_push_with_scope:
1058     traceExecution()
1059     callSlowPath(_llint_slow_path_push_with_scope)
1060     dispatch(2)
1061
1062
1063 _llint_op_pop_scope:
1064     traceExecution()
1065     callSlowPath(_llint_slow_path_pop_scope)
1066     dispatch(1)
1067
1068
1069 _llint_op_push_name_scope:
1070     traceExecution()
1071     callSlowPath(_llint_slow_path_push_name_scope)
1072     dispatch(4)
1073
1074
1075 _llint_op_throw:
1076     traceExecution()
1077     callSlowPath(_llint_slow_path_throw)
1078     dispatch(2)
1079
1080
1081 _llint_op_throw_static_error:
1082     traceExecution()
1083     callSlowPath(_llint_slow_path_throw_static_error)
1084     dispatch(3)
1085
1086
1087 _llint_op_profile_will_call:
1088     traceExecution()
1089     loadp CodeBlock[cfr], t0
1090     loadp CodeBlock::m_vm[t0], t0
1091     loadi VM::m_enabledProfiler[t0], t0
1092     btpz t0, .opProfilerWillCallDone
1093     callSlowPath(_llint_slow_path_profile_will_call)
1094 .opProfilerWillCallDone:
1095     dispatch(2)
1096
1097
1098 _llint_op_profile_did_call:
1099     traceExecution()
1100     loadp CodeBlock[cfr], t0
1101     loadp CodeBlock::m_vm[t0], t0
1102     loadi VM::m_enabledProfiler[t0], t0
1103     btpz t0, .opProfilerDidCallDone
1104     callSlowPath(_llint_slow_path_profile_did_call)
1105 .opProfilerDidCallDone:
1106     dispatch(2)
1107
1108
1109 _llint_op_debug:
1110     traceExecution()
1111     loadp CodeBlock[cfr], t0
1112     loadi CodeBlock::m_debuggerRequests[t0], t0
1113     btiz t0, .opDebugDone
1114     callSlowPath(_llint_slow_path_debug)
1115 .opDebugDone:                    
1116     dispatch(3)
1117
1118
1119 _llint_native_call_trampoline:
1120     nativeCallTrampoline(NativeExecutable::m_function)
1121
1122
1123 _llint_native_construct_trampoline:
1124     nativeCallTrampoline(NativeExecutable::m_constructor)
1125
1126
1127 # Lastly, make sure that we can link even though we don't support all opcodes.
1128 # These opcodes should never arise when using LLInt or either JIT. We assert
1129 # as much.
1130
1131 macro notSupported()
1132     if ASSERT_ENABLED
1133         crash()
1134     else
1135         # We should use whatever the smallest possible instruction is, just to
1136         # ensure that there is a gap between instruction labels. If multiple
1137         # smallest instructions exist, we should pick the one that is most
1138         # likely result in execution being halted. Currently that is the break
1139         # instruction on all architectures we're interested in. (Break is int3
1140         # on Intel, which is 1 byte, and bkpt on ARMv7, which is 2 bytes.)
1141         break
1142     end
1143 end
1144
1145 _llint_op_init_global_const_nop:
1146     dispatch(5)
1147