daf5786414d07940bb7f1663b908744e32715592
[WebKit-https.git] / Source / JavaScriptCore / llint / LowLevelInterpreter.asm
1 # Copyright (C) 2011-2015 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 # Crash course on the language that this is written in (which I just call
25 # "assembly" even though it's more than that):
26 #
27 # - Mostly gas-style operand ordering. The last operand tends to be the
28 #   destination. So "a := b" is written as "mov b, a". But unlike gas,
29 #   comparisons are in-order, so "if (a < b)" is written as
30 #   "bilt a, b, ...".
31 #
32 # - "b" = byte, "h" = 16-bit word, "i" = 32-bit word, "p" = pointer.
33 #   For 32-bit, "i" and "p" are interchangeable except when an op supports one
34 #   but not the other.
35 #
36 # - In general, valid operands for macro invocations and instructions are
37 #   registers (eg "t0"), addresses (eg "4[t0]"), base-index addresses
38 #   (eg "7[t0, t1, 2]"), absolute addresses (eg "0xa0000000[]"), or labels
39 #   (eg "_foo" or ".foo"). Macro invocations can also take anonymous
40 #   macros as operands. Instructions cannot take anonymous macros.
41 #
42 # - Labels must have names that begin with either "_" or ".".  A "." label
43 #   is local and gets renamed before code gen to minimize namespace
44 #   pollution. A "_" label is an extern symbol (i.e. ".globl"). The "_"
45 #   may or may not be removed during code gen depending on whether the asm
46 #   conventions for C name mangling on the target platform mandate a "_"
47 #   prefix.
48 #
49 # - A "macro" is a lambda expression, which may be either anonymous or
50 #   named. But this has caveats. "macro" can take zero or more arguments,
51 #   which may be macros or any valid operands, but it can only return
52 #   code. But you can do Turing-complete things via continuation passing
53 #   style: "macro foo (a, b) b(a, a) end foo(foo, foo)". Actually, don't do
54 #   that, since you'll just crash the assembler.
55 #
56 # - An "if" is a conditional on settings. Any identifier supplied in the
57 #   predicate of an "if" is assumed to be a #define that is available
58 #   during code gen. So you can't use "if" for computation in a macro, but
59 #   you can use it to select different pieces of code for different
60 #   platforms.
61 #
62 # - Arguments to macros follow lexical scoping rather than dynamic scoping.
63 #   Const's also follow lexical scoping and may override (hide) arguments
64 #   or other consts. All variables (arguments and constants) can be bound
65 #   to operands. Additionally, arguments (but not constants) can be bound
66 #   to macros.
67
68 # The following general-purpose registers are available:
69 #
70 #  - cfr and sp hold the call frame and (native) stack pointer respectively.
71 #  They are callee-save registers, and guaranteed to be distinct from all other
72 #  registers on all architectures.
73 #
74 #  - lr is defined on non-X86 architectures (ARM64, ARMv7, ARM,
75 #  ARMv7_TRADITIONAL, MIPS, SH4 and CLOOP) and holds the return PC
76 #
77 #  - pc holds the (native) program counter on 32-bits ARM architectures (ARM,
78 #  ARMv7, ARMv7_TRADITIONAL)
79 #
80 #  - t0, t1, t2, t3, t4 and optionally t5 are temporary registers that can get trashed on
81 #  calls, and are pairwise distinct registers. t4 holds the JS program counter, so use
82 #  with caution in opcodes (actually, don't use it in opcodes at all, except as PC).
83 #
84 #  - r0 and r1 are the platform's customary return registers, and thus are
85 #  two distinct registers
86 #
87 #  - a0, a1, a2 and a3 are the platform's customary argument registers, and
88 #  thus are pairwise distinct registers. Be mindful that:
89 #    + On X86, there are no argument registers. a0 and a1 are edx and
90 #    ecx following the fastcall convention, but you should still use the stack
91 #    to pass your arguments. The cCall2 and cCall4 macros do this for you.
92 #    + On X86_64_WIN, you should allocate space on the stack for the arguments,
93 #    and the return convention is weird for > 8 bytes types. The only place we
94 #    use > 8 bytes return values is on a cCall, and cCall2 and cCall4 handle
95 #    this for you.
96 #
97 #  - The only registers guaranteed to be caller-saved are r0, r1, a0, a1 and a2, and
98 #  you should be mindful of that in functions that are called directly from C.
99 #  If you need more registers, you should push and pop them like a good
100 #  assembly citizen, because any other register will be callee-saved on X86.
101 #
102 # You can additionally assume:
103 #
104 #  - a3, t2, t3, t4 and t5 are never return registers; t0, t1, a0, a1 and a2
105 #  can be return registers.
106 #
107 #  - t4 and t5 are never argument registers, t3 can only be a3, t1 can only be
108 #  a1; but t0 and t2 can be either a0 or a2.
109 #
110 #  - On 64 bits, there are callee-save registers named csr0, csr1, ... csrN.
111 #  The last three csr registers are used used to store the PC base and
112 #  two special tag values. Don't use them for anything else.
113 #
114 # Additional platform-specific details (you shouldn't rely on this remaining
115 # true):
116 #
117 #  - For consistency with the baseline JIT, t0 is always r0 (and t1 is always
118 #  r1 on 32 bits platforms). You should use the r version when you need return
119 #  registers, and the t version otherwise: code using t0 (or t1) should still
120 #  work if swapped with e.g. t3, while code using r0 (or r1) should not. There
121 #  *may* be legacy code relying on this.
122 #
123 #  - On all platforms other than X86, t0 can only be a0 and t2 can only be a2.
124 #
125 #  - On all platforms other than X86 and X86_64, a2 is not a return register.
126 #  a2 is r0 on X86 (because we have so few registers) and r1 on X86_64 (because
127 #  the ABI enforces it).
128 #
129 # The following floating-point registers are available:
130 #
131 #  - ft0-ft5 are temporary floating-point registers that get trashed on calls,
132 #  and are pairwise distinct.
133 #
134 #  - fa0 and fa1 are the platform's customary floating-point argument
135 #  registers, and are both distinct. On 64-bits platforms, fa2 and fa3 are
136 #  additional floating-point argument registers.
137 #
138 #  - fr is the platform's customary floating-point return register
139 #
140 # You can assume that ft1-ft5 or fa1-fa3 are never fr, and that ftX is never
141 # faY if X != Y.
142
143 # First come the common protocols that both interpreters use. Note that each
144 # of these must have an ASSERT() in LLIntData.cpp
145
146 # Work-around for the fact that the toolchain's awareness of armv7k / armv7s
147 # results in a separate slab in the fat binary, yet the offlineasm doesn't know
148 # to expect it.
149 if ARMv7k
150 end
151 if ARMv7s
152 end
153
154 # These declarations must match interpreter/JSStack.h.
155
156 if JSVALUE64
157     const PtrSize = 8
158     const CallFrameHeaderSlots = 5
159 else
160     const PtrSize = 4
161     const CallFrameHeaderSlots = 4
162     const CallFrameAlignSlots = 1
163 end
164 const SlotSize = 8
165
166 const JSEnvironmentRecord_variables = (sizeof JSEnvironmentRecord + SlotSize - 1) & ~(SlotSize - 1)
167 const DirectArguments_storage = (sizeof DirectArguments + SlotSize - 1) & ~(SlotSize - 1)
168
169 const StackAlignment = 16
170 const StackAlignmentSlots = 2
171 const StackAlignmentMask = StackAlignment - 1
172
173 const CallerFrameAndPCSize = 2 * PtrSize
174
175 const CallerFrame = 0
176 const ReturnPC = CallerFrame + PtrSize
177 const CodeBlock = ReturnPC + PtrSize
178 const Callee = CodeBlock + SlotSize
179 const ArgumentCount = Callee + SlotSize
180 const ThisArgumentOffset = ArgumentCount + SlotSize
181 const FirstArgumentOffset = ThisArgumentOffset + SlotSize
182 const CallFrameHeaderSize = ThisArgumentOffset
183
184 # Some value representation constants.
185 if JSVALUE64
186     const TagBitTypeOther = 0x2
187     const TagBitBool      = 0x4
188     const TagBitUndefined = 0x8
189     const ValueEmpty      = 0x0
190     const ValueFalse      = TagBitTypeOther | TagBitBool
191     const ValueTrue       = TagBitTypeOther | TagBitBool | 1
192     const ValueUndefined  = TagBitTypeOther | TagBitUndefined
193     const ValueNull       = TagBitTypeOther
194     const TagTypeNumber   = 0xffff000000000000
195     const TagMask         = TagTypeNumber | TagBitTypeOther
196 else
197     const Int32Tag = -1
198     const BooleanTag = -2
199     const NullTag = -3
200     const UndefinedTag = -4
201     const CellTag = -5
202     const EmptyValueTag = -6
203     const DeletedValueTag = -7
204     const LowestTag = DeletedValueTag
205 end
206
207 # NOTE: The values below must be in sync with what is in PutByIdFlags.h.
208 const PutByIdPrimaryTypeMask = 0x6
209 const PutByIdPrimaryTypeSecondary = 0x0
210 const PutByIdPrimaryTypeObjectWithStructure = 0x2
211 const PutByIdPrimaryTypeObjectWithStructureOrOther = 0x4
212 const PutByIdSecondaryTypeMask = -0x8
213 const PutByIdSecondaryTypeBottom = 0x0
214 const PutByIdSecondaryTypeBoolean = 0x8
215 const PutByIdSecondaryTypeOther = 0x10
216 const PutByIdSecondaryTypeInt32 = 0x18
217 const PutByIdSecondaryTypeNumber = 0x20
218 const PutByIdSecondaryTypeString = 0x28
219 const PutByIdSecondaryTypeSymbol = 0x30
220 const PutByIdSecondaryTypeObject = 0x38
221 const PutByIdSecondaryTypeObjectOrOther = 0x40
222 const PutByIdSecondaryTypeTop = 0x48
223
224 const CopyBarrierSpaceBits = 3
225
226 const CallOpCodeSize = 9
227
228 if X86_64 or ARM64 or C_LOOP
229     const maxFrameExtentForSlowPathCall = 0
230 elsif ARM or ARMv7_TRADITIONAL or ARMv7 or SH4
231     const maxFrameExtentForSlowPathCall = 24
232 elsif X86 or X86_WIN
233     const maxFrameExtentForSlowPathCall = 40
234 elsif MIPS
235     const maxFrameExtentForSlowPathCall = 40
236 elsif X86_64_WIN
237     const maxFrameExtentForSlowPathCall = 64
238 end
239
240 if X86_64 or X86_64_WIN or ARM64
241     const CalleeSaveSpaceAsVirtualRegisters = 3
242 else
243     const CalleeSaveSpaceAsVirtualRegisters = 0
244 end
245
246 const CalleeSaveSpaceStackAligned = (CalleeSaveSpaceAsVirtualRegisters * SlotSize + StackAlignment - 1) & ~StackAlignmentMask
247
248
249 # Watchpoint states
250 const ClearWatchpoint = 0
251 const IsWatched = 1
252 const IsInvalidated = 2
253
254 # Some register conventions.
255 if JSVALUE64
256     # - Use a pair of registers to represent the PC: one register for the
257     #   base of the bytecodes, and one register for the index.
258     # - The PC base (or PB for short) must be stored in a callee-save register.
259     # - C calls are still given the Instruction* rather than the PC index.
260     #   This requires an add before the call, and a sub after.
261     const PC = t4
262     if ARM64
263         const PB = csr7
264         const tagTypeNumber = csr8
265         const tagMask = csr9
266     elsif X86_64
267         const PB = csr2
268         const tagTypeNumber = csr3
269         const tagMask = csr4
270     elsif X86_64_WIN
271         const PB = csr4
272         const tagTypeNumber = csr5
273         const tagMask = csr6
274     elsif C_LOOP
275         const PB = csr0
276         const tagTypeNumber = csr1
277         const tagMask = csr2
278     end
279
280     macro loadisFromInstruction(offset, dest)
281         loadis offset * 8[PB, PC, 8], dest
282     end
283     
284     macro loadpFromInstruction(offset, dest)
285         loadp offset * 8[PB, PC, 8], dest
286     end
287     
288     macro storepToInstruction(value, offset)
289         storep value, offset * 8[PB, PC, 8]
290     end
291
292 else
293     const PC = t4
294     macro loadisFromInstruction(offset, dest)
295         loadis offset * 4[PC], dest
296     end
297     
298     macro loadpFromInstruction(offset, dest)
299         loadp offset * 4[PC], dest
300     end
301 end
302
303 if X86_64_WIN
304     const extraTempReg = t0
305 else
306     const extraTempReg = t5
307 end
308
309 # Constants for reasoning about value representation.
310 if BIG_ENDIAN
311     const TagOffset = 0
312     const PayloadOffset = 4
313 else
314     const TagOffset = 4
315     const PayloadOffset = 0
316 end
317
318 # Constant for reasoning about butterflies.
319 const IsArray                  = 1
320 const IndexingShapeMask        = 30
321 const NoIndexingShape          = 0
322 const Int32Shape               = 20
323 const DoubleShape              = 22
324 const ContiguousShape          = 26
325 const ArrayStorageShape        = 28
326 const SlowPutArrayStorageShape = 30
327
328 # Type constants.
329 const StringType = 6
330 const SymbolType = 7
331 const ObjectType = 21
332 const FinalObjectType = 22
333
334 # Type flags constants.
335 const MasqueradesAsUndefined = 1
336 const ImplementsHasInstance = 2
337 const ImplementsDefaultHasInstance = 8
338
339 # Bytecode operand constants.
340 const FirstConstantRegisterIndex = 0x40000000
341
342 # Code type constants.
343 const GlobalCode = 0
344 const EvalCode = 1
345 const FunctionCode = 2
346 const ModuleCode = 3
347
348 # The interpreter steals the tag word of the argument count.
349 const LLIntReturnPC = ArgumentCount + TagOffset
350
351 # String flags.
352 const HashFlags8BitBuffer = 8
353
354 # Copied from PropertyOffset.h
355 const firstOutOfLineOffset = 100
356
357 # ResolveType
358 const GlobalProperty = 0
359 const GlobalVar = 1
360 const GlobalLexicalVar = 2
361 const ClosureVar = 3
362 const LocalClosureVar = 4
363 const ModuleVar = 5
364 const GlobalPropertyWithVarInjectionChecks = 6
365 const GlobalVarWithVarInjectionChecks = 7
366 const GlobalLexicalVarWithVarInjectionChecks = 8
367 const ClosureVarWithVarInjectionChecks = 9
368
369 const ResolveTypeMask = 0x3ff
370 const InitializationModeMask = 0xffc00
371 const InitializationModeShift = 10
372 const Initialization = 0
373
374 const MarkedBlockSize = 16 * 1024
375 const MarkedBlockMask = ~(MarkedBlockSize - 1)
376
377 # Allocation constants
378 if JSVALUE64
379     const JSFinalObjectSizeClassIndex = 1
380 else
381     const JSFinalObjectSizeClassIndex = 3
382 end
383
384 # This must match wtf/Vector.h
385 const VectorBufferOffset = 0
386 if JSVALUE64
387     const VectorSizeOffset = 12
388 else
389     const VectorSizeOffset = 8
390 end
391
392 # Some common utilities.
393 macro crash()
394     if C_LOOP
395         cloopCrash
396     else
397         call _llint_crash
398     end
399 end
400
401 macro assert(assertion)
402     if ASSERT_ENABLED
403         assertion(.ok)
404         crash()
405     .ok:
406     end
407 end
408
409 macro checkStackPointerAlignment(tempReg, location)
410     if ARM64 or C_LOOP or SH4
411         # ARM64 will check for us!
412         # C_LOOP does not need the alignment, and can use a little perf
413         # improvement from avoiding useless work.
414         # SH4 does not need specific alignment (4 bytes).
415     else
416         if ARM or ARMv7 or ARMv7_TRADITIONAL
417             # ARM can't do logical ops with the sp as a source
418             move sp, tempReg
419             andp StackAlignmentMask, tempReg
420         else
421             andp sp, StackAlignmentMask, tempReg
422         end
423         btpz tempReg, .stackPointerOkay
424         move location, tempReg
425         break
426     .stackPointerOkay:
427     end
428 end
429
430 if C_LOOP or ARM64 or X86_64 or X86_64_WIN
431     const CalleeSaveRegisterCount = 0
432 elsif ARM or ARMv7_TRADITIONAL or ARMv7
433     const CalleeSaveRegisterCount = 7
434 elsif SH4 or MIPS
435     const CalleeSaveRegisterCount = 5
436 elsif X86 or X86_WIN
437     const CalleeSaveRegisterCount = 3
438 end
439
440 const CalleeRegisterSaveSize = CalleeSaveRegisterCount * PtrSize
441
442 # VMEntryTotalFrameSize includes the space for struct VMEntryRecord and the
443 # callee save registers rounded up to keep the stack aligned
444 const VMEntryTotalFrameSize = (CalleeRegisterSaveSize + sizeof VMEntryRecord + StackAlignment - 1) & ~StackAlignmentMask
445
446 macro pushCalleeSaves()
447     if C_LOOP or ARM64 or X86_64 or X86_64_WIN
448     elsif ARM or ARMv7_TRADITIONAL
449         emit "push {r4-r10}"
450     elsif ARMv7
451         emit "push {r4-r6, r8-r11}"
452     elsif MIPS
453         emit "addiu $sp, $sp, -20"
454         emit "sw $20, 16($sp)"
455         emit "sw $19, 12($sp)"
456         emit "sw $18, 8($sp)"
457         emit "sw $17, 4($sp)"
458         emit "sw $16, 0($sp)"
459     elsif SH4
460         emit "mov.l r13, @-r15"
461         emit "mov.l r11, @-r15"
462         emit "mov.l r10, @-r15"
463         emit "mov.l r9, @-r15"
464         emit "mov.l r8, @-r15"
465     elsif X86
466         emit "push %esi"
467         emit "push %edi"
468         emit "push %ebx"
469     elsif X86_WIN
470         emit "push esi"
471         emit "push edi"
472         emit "push ebx"
473     end
474 end
475
476 macro popCalleeSaves()
477     if C_LOOP or ARM64 or X86_64 or X86_64_WIN
478     elsif ARM or ARMv7_TRADITIONAL
479         emit "pop {r4-r10}"
480     elsif ARMv7
481         emit "pop {r4-r6, r8-r11}"
482     elsif MIPS
483         emit "lw $16, 0($sp)"
484         emit "lw $17, 4($sp)"
485         emit "lw $18, 8($sp)"
486         emit "lw $19, 12($sp)"
487         emit "lw $20, 16($sp)"
488         emit "addiu $sp, $sp, 20"
489     elsif SH4
490         emit "mov.l @r15+, r8"
491         emit "mov.l @r15+, r9"
492         emit "mov.l @r15+, r10"
493         emit "mov.l @r15+, r11"
494         emit "mov.l @r15+, r13"
495     elsif X86
496         emit "pop %ebx"
497         emit "pop %edi"
498         emit "pop %esi"
499     elsif X86_WIN
500         emit "pop ebx"
501         emit "pop edi"
502         emit "pop esi"
503     end
504 end
505
506 macro preserveCallerPCAndCFR()
507     if C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS or SH4
508         push lr
509         push cfr
510     elsif X86 or X86_WIN or X86_64 or X86_64_WIN
511         push cfr
512     elsif ARM64
513         push cfr, lr
514     else
515         error
516     end
517     move sp, cfr
518 end
519
520 macro restoreCallerPCAndCFR()
521     move cfr, sp
522     if C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS or SH4
523         pop cfr
524         pop lr
525     elsif X86 or X86_WIN or X86_64 or X86_64_WIN
526         pop cfr
527     elsif ARM64
528         pop lr, cfr
529     end
530 end
531
532 macro preserveCalleeSavesUsedByLLInt()
533     subp CalleeSaveSpaceStackAligned, sp
534     if C_LOOP
535     elsif ARM or ARMv7_TRADITIONAL
536     elsif ARMv7
537     elsif ARM64
538         emit "stp x27, x28, [x29, #-16]"
539         emit "stp xzr, x26, [x29, #-32]"
540     elsif MIPS
541     elsif SH4
542     elsif X86
543     elsif X86_WIN
544     elsif X86_64
545         storep csr4, -8[cfr]
546         storep csr3, -16[cfr]
547         storep csr2, -24[cfr]
548     elsif X86_64_WIN
549         storep csr6, -8[cfr]
550         storep csr5, -16[cfr]
551         storep csr4, -24[cfr]
552     end
553 end
554
555 macro restoreCalleeSavesUsedByLLInt()
556     if C_LOOP
557     elsif ARM or ARMv7_TRADITIONAL
558     elsif ARMv7
559     elsif ARM64
560         emit "ldp xzr, x26, [x29, #-32]"
561         emit "ldp x27, x28, [x29, #-16]"
562     elsif MIPS
563     elsif SH4
564     elsif X86
565     elsif X86_WIN
566     elsif X86_64
567         loadp -24[cfr], csr2
568         loadp -16[cfr], csr3
569         loadp -8[cfr], csr4
570     elsif X86_64_WIN
571         loadp -24[cfr], csr4
572         loadp -16[cfr], csr5
573         loadp -8[cfr], csr6
574     end
575 end
576
577 macro copyCalleeSavesToVMCalleeSavesBuffer(vm, temp)
578     if ARM64 or X86_64 or X86_64_WIN
579         leap VM::calleeSaveRegistersBuffer[vm], temp
580         if ARM64
581             storep csr0, [temp]
582             storep csr1, 8[temp]
583             storep csr2, 16[temp]
584             storep csr3, 24[temp]
585             storep csr4, 32[temp]
586             storep csr5, 40[temp]
587             storep csr6, 48[temp]
588             storep csr7, 56[temp]
589             storep csr8, 64[temp]
590             storep csr9, 72[temp]
591             stored csfr0, 80[temp]
592             stored csfr1, 88[temp]
593             stored csfr2, 96[temp]
594             stored csfr3, 104[temp]
595             stored csfr4, 112[temp]
596             stored csfr5, 120[temp]
597             stored csfr6, 128[temp]
598             stored csfr7, 136[temp]
599         elsif X86_64
600             storep csr0, [temp]
601             storep csr1, 8[temp]
602             storep csr2, 16[temp]
603             storep csr3, 24[temp]
604             storep csr4, 32[temp]
605         elsif X86_64_WIN
606             storep csr0, [temp]
607             storep csr1, 8[temp]
608             storep csr2, 16[temp]
609             storep csr3, 24[temp]
610             storep csr4, 32[temp]
611             storep csr5, 40[temp]
612             storep csr6, 48[temp]
613         end
614     end
615 end
616
617 macro restoreCalleeSavesFromVMCalleeSavesBuffer(vm, temp)
618     if ARM64 or X86_64 or X86_64_WIN
619         leap VM::calleeSaveRegistersBuffer[vm], temp
620         if ARM64
621             loadp [temp], csr0
622             loadp 8[temp], csr1
623             loadp 16[temp], csr2
624             loadp 24[temp], csr3
625             loadp 32[temp], csr4
626             loadp 40[temp], csr5
627             loadp 48[temp], csr6
628             loadp 56[temp], csr7
629             loadp 64[temp], csr8
630             loadp 72[temp], csr9
631             loadd 80[temp], csfr0
632             loadd 88[temp], csfr1
633             loadd 96[temp], csfr2
634             loadd 104[temp], csfr3
635             loadd 112[temp], csfr4
636             loadd 120[temp], csfr5
637             loadd 128[temp], csfr6
638             loadd 136[temp], csfr7
639         elsif X86_64
640             loadp [temp], csr0
641             loadp 8[temp], csr1
642             loadp 16[temp], csr2
643             loadp 24[temp], csr3
644             loadp 32[temp], csr4
645         elsif X86_64_WIN
646             loadp [temp], csr0
647             loadp 8[temp], csr1
648             loadp 16[temp], csr2
649             loadp 24[temp], csr3
650             loadp 32[temp], csr4
651             loadp 40[temp], csr5
652             loadp 48[temp], csr6
653         end
654     end
655 end
656
657 macro preserveReturnAddressAfterCall(destinationRegister)
658     if C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or ARM64 or MIPS or SH4
659         # In C_LOOP case, we're only preserving the bytecode vPC.
660         move lr, destinationRegister
661     elsif X86 or X86_WIN or X86_64 or X86_64_WIN
662         pop destinationRegister
663     else
664         error
665     end
666 end
667
668 macro copyBarrier(value, slow)
669     btpnz value, CopyBarrierSpaceBits, slow
670 end
671
672 macro functionPrologue()
673     if X86 or X86_WIN or X86_64 or X86_64_WIN
674         push cfr
675     elsif ARM64
676         push cfr, lr
677     elsif C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS or SH4
678         push lr
679         push cfr
680     end
681     move sp, cfr
682 end
683
684 macro functionEpilogue()
685     if X86 or X86_WIN or X86_64 or X86_64_WIN
686         pop cfr
687     elsif ARM64
688         pop lr, cfr
689     elsif C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS or SH4
690         pop cfr
691         pop lr
692     end
693 end
694
695 macro vmEntryRecord(entryFramePointer, resultReg)
696     subp entryFramePointer, VMEntryTotalFrameSize, resultReg
697 end
698
699 macro getFrameRegisterSizeForCodeBlock(codeBlock, size)
700     loadi CodeBlock::m_numCalleeRegisters[codeBlock], size
701     lshiftp 3, size
702     addp maxFrameExtentForSlowPathCall, size
703 end
704
705 macro restoreStackPointerAfterCall()
706     loadp CodeBlock[cfr], t2
707     getFrameRegisterSizeForCodeBlock(t2, t2)
708     if ARMv7
709         subp cfr, t2, t2
710         move t2, sp
711     else
712         subp cfr, t2, sp
713     end
714 end
715
716 macro traceExecution()
717     if EXECUTION_TRACING
718         callSlowPath(_llint_trace)
719     end
720 end
721
722 macro callTargetFunction(callee)
723     if C_LOOP
724         cloopCallJSFunction callee
725     else
726         call callee
727     end
728     restoreStackPointerAfterCall()
729     dispatchAfterCall()
730 end
731
732 macro prepareForRegularCall(callee, temp1, temp2, temp3)
733     addp CallerFrameAndPCSize, sp
734 end
735
736 # sp points to the new frame
737 macro prepareForTailCall(callee, temp1, temp2, temp3)
738     restoreCalleeSavesUsedByLLInt()
739
740     loadi PayloadOffset + ArgumentCount[cfr], temp2
741     loadp CodeBlock[cfr], temp1
742     loadp CodeBlock::m_numParameters[temp1], temp1
743     bilteq temp1, temp2, .noArityFixup
744     move temp1, temp2
745
746 .noArityFixup:
747     # We assume < 2^28 arguments
748     muli SlotSize, temp2
749     addi StackAlignment - 1 + CallFrameHeaderSize, temp2
750     andi ~StackAlignmentMask, temp2
751
752     move cfr, temp1
753     addp temp2, temp1
754
755     loadi PayloadOffset + ArgumentCount[sp], temp2
756     # We assume < 2^28 arguments
757     muli SlotSize, temp2
758     addi StackAlignment - 1 + CallFrameHeaderSize, temp2
759     andi ~StackAlignmentMask, temp2
760
761     if ARM or ARMv7_TRADITIONAL or ARMv7 or SH4 or ARM64 or C_LOOP or MIPS
762         addp 2 * PtrSize, sp
763         subi 2 * PtrSize, temp2
764         loadp PtrSize[cfr], lr
765     else
766         addp PtrSize, sp
767         subi PtrSize, temp2
768         loadp PtrSize[cfr], temp3
769         storep temp3, [sp]
770     end
771
772     subp temp2, temp1
773     loadp [cfr], cfr
774
775 .copyLoop:
776     subi PtrSize, temp2
777     loadp [sp, temp2, 1], temp3
778     storep temp3, [temp1, temp2, 1]
779     btinz temp2, .copyLoop
780
781     move temp1, sp
782     jmp callee
783 end
784
785 macro slowPathForCall(slowPath, prepareCall)
786     callCallSlowPath(
787         slowPath,
788         # Those are r0 and r1
789         macro (callee, calleeFramePtr)
790             btpz calleeFramePtr, .dontUpdateSP
791             move calleeFramePtr, sp
792             prepareCall(callee, t2, t3, t4)
793         .dontUpdateSP:
794             callTargetFunction(callee)
795         end)
796 end
797
798 macro arrayProfile(cellAndIndexingType, profile, scratch)
799     const cell = cellAndIndexingType
800     const indexingType = cellAndIndexingType 
801     loadi JSCell::m_structureID[cell], scratch
802     storei scratch, ArrayProfile::m_lastSeenStructureID[profile]
803     loadb JSCell::m_indexingType[cell], indexingType
804 end
805
806 macro skipIfIsRememberedOrInEden(cell, scratch1, scratch2, continuation)
807     loadb JSCell::m_cellState[cell], scratch1
808     continuation(scratch1)
809 end
810
811 macro notifyWrite(set, slow)
812     bbneq WatchpointSet::m_state[set], IsInvalidated, slow
813 end
814
815 macro checkSwitchToJIT(increment, action)
816     loadp CodeBlock[cfr], t0
817     baddis increment, CodeBlock::m_llintExecuteCounter + BaselineExecutionCounter::m_counter[t0], .continue
818     action()
819     .continue:
820 end
821
822 macro checkSwitchToJITForEpilogue()
823     checkSwitchToJIT(
824         10,
825         macro ()
826             callSlowPath(_llint_replace)
827         end)
828 end
829
830 macro assertNotConstant(index)
831     assert(macro (ok) bilt index, FirstConstantRegisterIndex, ok end)
832 end
833
834 macro functionForCallCodeBlockGetter(targetRegister)
835     if JSVALUE64
836         loadp Callee[cfr], targetRegister
837     else
838         loadp Callee + PayloadOffset[cfr], targetRegister
839     end
840     loadp JSFunction::m_executable[targetRegister], targetRegister
841     loadp FunctionExecutable::m_codeBlockForCall[targetRegister], targetRegister
842 end
843
844 macro functionForConstructCodeBlockGetter(targetRegister)
845     if JSVALUE64
846         loadp Callee[cfr], targetRegister
847     else
848         loadp Callee + PayloadOffset[cfr], targetRegister
849     end
850     loadp JSFunction::m_executable[targetRegister], targetRegister
851     loadp FunctionExecutable::m_codeBlockForConstruct[targetRegister], targetRegister
852 end
853
854 macro notFunctionCodeBlockGetter(targetRegister)
855     loadp CodeBlock[cfr], targetRegister
856 end
857
858 macro functionCodeBlockSetter(sourceRegister)
859     storep sourceRegister, CodeBlock[cfr]
860 end
861
862 macro notFunctionCodeBlockSetter(sourceRegister)
863     # Nothing to do!
864 end
865
866 # Do the bare minimum required to execute code. Sets up the PC, leave the CodeBlock*
867 # in t1. May also trigger prologue entry OSR.
868 macro prologue(codeBlockGetter, codeBlockSetter, osrSlowPath, traceSlowPath)
869     # Set up the call frame and check if we should OSR.
870     preserveCallerPCAndCFR()
871
872     if EXECUTION_TRACING
873         subp maxFrameExtentForSlowPathCall, sp
874         callSlowPath(traceSlowPath)
875         addp maxFrameExtentForSlowPathCall, sp
876     end
877     codeBlockGetter(t1)
878     if not C_LOOP
879         baddis 5, CodeBlock::m_llintExecuteCounter + BaselineExecutionCounter::m_counter[t1], .continue
880         if JSVALUE64
881             move cfr, a0
882             move PC, a1
883             cCall2(osrSlowPath)
884         else
885             # We are after the function prologue, but before we have set up sp from the CodeBlock.
886             # Temporarily align stack pointer for this call.
887             subp 8, sp
888             move cfr, a0
889             move PC, a1
890             cCall2(osrSlowPath)
891             addp 8, sp
892         end
893         btpz r0, .recover
894         move cfr, sp # restore the previous sp
895         # pop the callerFrame since we will jump to a function that wants to save it
896         if ARM64
897             pop lr, cfr
898         elsif ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS or SH4
899             pop cfr
900             pop lr
901         else
902             pop cfr
903         end
904         jmp r0
905     .recover:
906         codeBlockGetter(t1)
907     .continue:
908     end
909
910     codeBlockSetter(t1)
911
912     preserveCalleeSavesUsedByLLInt()
913
914     # Set up the PC.
915     if JSVALUE64
916         loadp CodeBlock::m_instructions[t1], PB
917         move 0, PC
918     else
919         loadp CodeBlock::m_instructions[t1], PC
920     end
921
922     # Get new sp in t0 and check stack height.
923     getFrameRegisterSizeForCodeBlock(t1, t0)
924     subp cfr, t0, t0
925     loadp CodeBlock::m_vm[t1], t2
926     bpbeq VM::m_jsStackLimit[t2], t0, .stackHeightOK
927
928     # Stack height check failed - need to call a slow_path.
929     # Set up temporary stack pointer for call including callee saves
930     subp maxFrameExtentForSlowPathCall, sp
931     callSlowPath(_llint_stack_check)
932     bpeq r1, 0, .stackHeightOKGetCodeBlock
933     move r1, cfr
934     dispatch(0) # Go to exception handler in PC
935
936 .stackHeightOKGetCodeBlock:
937     # Stack check slow path returned that the stack was ok.
938     # Since they were clobbered, need to get CodeBlock and new sp
939     codeBlockGetter(t1)
940     getFrameRegisterSizeForCodeBlock(t1, t0)
941     subp cfr, t0, t0
942
943 .stackHeightOK:
944     move t0, sp
945
946     if JSVALUE64
947         move TagTypeNumber, tagTypeNumber
948         addp TagBitTypeOther, tagTypeNumber, tagMask
949     end
950 end
951
952 # Expects that CodeBlock is in t1, which is what prologue() leaves behind.
953 # Must call dispatch(0) after calling this.
954 macro functionInitialization(profileArgSkip)
955     # Profile the arguments. Unfortunately, we have no choice but to do this. This
956     # code is pretty horrendous because of the difference in ordering between
957     # arguments and value profiles, the desire to have a simple loop-down-to-zero
958     # loop, and the desire to use only three registers so as to preserve the PC and
959     # the code block. It is likely that this code should be rewritten in a more
960     # optimal way for architectures that have more than five registers available
961     # for arbitrary use in the interpreter.
962     loadi CodeBlock::m_numParameters[t1], t0
963     addp -profileArgSkip, t0 # Use addi because that's what has the peephole
964     assert(macro (ok) bpgteq t0, 0, ok end)
965     btpz t0, .argumentProfileDone
966     loadp CodeBlock::m_argumentValueProfiles + VectorBufferOffset[t1], t3
967     mulp sizeof ValueProfile, t0, t2 # Aaaaahhhh! Need strength reduction!
968     lshiftp 3, t0
969     addp t2, t3
970 .argumentProfileLoop:
971     if JSVALUE64
972         loadq ThisArgumentOffset - 8 + profileArgSkip * 8[cfr, t0], t2
973         subp sizeof ValueProfile, t3
974         storeq t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets[t3]
975     else
976         loadi ThisArgumentOffset + TagOffset - 8 + profileArgSkip * 8[cfr, t0], t2
977         subp sizeof ValueProfile, t3
978         storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + TagOffset[t3]
979         loadi ThisArgumentOffset + PayloadOffset - 8 + profileArgSkip * 8[cfr, t0], t2
980         storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + PayloadOffset[t3]
981     end
982     baddpnz -8, t0, .argumentProfileLoop
983 .argumentProfileDone:
984 end
985
986 macro allocateJSObject(allocator, structure, result, scratch1, slowCase)
987     const offsetOfFirstFreeCell = 
988         MarkedAllocator::m_freeList + 
989         MarkedBlock::FreeList::head
990
991     # Get the object from the free list.   
992     loadp offsetOfFirstFreeCell[allocator], result
993     btpz result, slowCase
994     
995     # Remove the object from the free list.
996     loadp [result], scratch1
997     storep scratch1, offsetOfFirstFreeCell[allocator]
998
999     # Initialize the object.
1000     storep 0, JSObject::m_butterfly[result]
1001     storeStructureWithTypeInfo(result, structure, scratch1)
1002 end
1003
1004 macro doReturn()
1005     restoreCalleeSavesUsedByLLInt()
1006     restoreCallerPCAndCFR()
1007     ret
1008 end
1009
1010 # stub to call into JavaScript or Native functions
1011 # EncodedJSValue vmEntryToJavaScript(void* code, VM* vm, ProtoCallFrame* protoFrame)
1012 # EncodedJSValue vmEntryToNativeFunction(void* code, VM* vm, ProtoCallFrame* protoFrame)
1013
1014 if C_LOOP
1015     _llint_vm_entry_to_javascript:
1016 else
1017     global _vmEntryToJavaScript
1018     _vmEntryToJavaScript:
1019 end
1020     doVMEntry(makeJavaScriptCall)
1021
1022
1023 if C_LOOP
1024     _llint_vm_entry_to_native:
1025 else
1026     global _vmEntryToNative
1027     _vmEntryToNative:
1028 end
1029     doVMEntry(makeHostFunctionCall)
1030
1031
1032 if not C_LOOP
1033     # void sanitizeStackForVMImpl(VM* vm)
1034     global _sanitizeStackForVMImpl
1035     _sanitizeStackForVMImpl:
1036         # We need three non-aliased caller-save registers. We are guaranteed
1037         # this for a0, a1 and a2 on all architectures.
1038         if X86 or X86_WIN
1039             loadp 4[sp], a0
1040         end
1041         const vm = a0
1042         const address = a1
1043         const zeroValue = a2
1044     
1045         loadp VM::m_lastStackTop[vm], address
1046         bpbeq sp, address, .zeroFillDone
1047     
1048         move 0, zeroValue
1049     .zeroFillLoop:
1050         storep zeroValue, [address]
1051         addp PtrSize, address
1052         bpa sp, address, .zeroFillLoop
1053     
1054     .zeroFillDone:
1055         move sp, address
1056         storep address, VM::m_lastStackTop[vm]
1057         ret
1058     
1059     # VMEntryRecord* vmEntryRecord(const VMEntryFrame* entryFrame)
1060     global _vmEntryRecord
1061     _vmEntryRecord:
1062         if X86 or X86_WIN
1063             loadp 4[sp], a0
1064         end
1065
1066         vmEntryRecord(a0, r0)
1067         ret
1068 end
1069
1070 if C_LOOP
1071     # Dummy entry point the C Loop uses to initialize.
1072     _llint_entry:
1073         crash()
1074 else
1075     macro initPCRelative(pcBase)
1076         if X86_64 or X86_64_WIN or X86 or X86_WIN
1077             call _relativePCBase
1078         _relativePCBase:
1079             pop pcBase
1080         elsif ARM64
1081         elsif ARMv7
1082         _relativePCBase:
1083             move pc, pcBase
1084             subp 3, pcBase   # Need to back up the PC and set the Thumb2 bit
1085         elsif ARM or ARMv7_TRADITIONAL
1086         _relativePCBase:
1087             move pc, pcBase
1088             subp 8, pcBase
1089         elsif MIPS
1090             la _relativePCBase, pcBase
1091         _relativePCBase:
1092         elsif SH4
1093             mova _relativePCBase, t0
1094             move t0, pcBase
1095             alignformova
1096         _relativePCBase:
1097         end
1098 end
1099
1100 # The PC base is in t1, as this is what _llint_entry leaves behind through
1101 # initPCRelative(t1)
1102 macro setEntryAddress(index, label)
1103     if X86_64 or X86_64_WIN
1104         leap (label - _relativePCBase)[t1], t3
1105         move index, t4
1106         storep t3, [a0, t4, 8]
1107     elsif X86 or X86_WIN
1108         leap (label - _relativePCBase)[t1], t3
1109         move index, t4
1110         storep t3, [a0, t4, 4]
1111     elsif ARM64
1112         pcrtoaddr label, t1
1113         move index, t4
1114         storep t1, [a0, t4, 8]
1115     elsif ARM or ARMv7 or ARMv7_TRADITIONAL
1116         mvlbl (label - _relativePCBase), t4
1117         addp t4, t1, t4
1118         move index, t3
1119         storep t4, [a0, t3, 4]
1120     elsif SH4
1121         move (label - _relativePCBase), t4
1122         addp t4, t1, t4
1123         move index, t3
1124         storep t4, [a0, t3, 4]
1125         flushcp # Force constant pool flush to avoid "pcrel too far" link error.
1126     elsif MIPS
1127         la label, t4
1128         la _relativePCBase, t3
1129         subp t3, t4
1130         addp t4, t1, t4
1131         move index, t3
1132         storep t4, [a0, t3, 4]
1133     end
1134 end
1135
1136 global _llint_entry
1137 # Entry point for the llint to initialize.
1138 _llint_entry:
1139     functionPrologue()
1140     pushCalleeSaves()
1141     if X86 or X86_WIN
1142         loadp 20[sp], a0
1143     end
1144     initPCRelative(t1)
1145
1146     # Include generated bytecode initialization file.
1147     include InitBytecodes
1148
1149     popCalleeSaves()
1150     functionEpilogue()
1151     ret
1152 end
1153
1154 _llint_program_prologue:
1155     prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
1156     dispatch(0)
1157
1158
1159 _llint_module_program_prologue:
1160     prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
1161     dispatch(0)
1162
1163
1164 _llint_eval_prologue:
1165     prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
1166     dispatch(0)
1167
1168
1169 _llint_function_for_call_prologue:
1170     prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call, _llint_trace_prologue_function_for_call)
1171     functionInitialization(0)
1172     dispatch(0)
1173     
1174
1175 _llint_function_for_construct_prologue:
1176     prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct, _llint_trace_prologue_function_for_construct)
1177     functionInitialization(1)
1178     dispatch(0)
1179     
1180
1181 _llint_function_for_call_arity_check:
1182     prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call_arityCheck, _llint_trace_arityCheck_for_call)
1183     functionArityCheck(.functionForCallBegin, _slow_path_call_arityCheck)
1184 .functionForCallBegin:
1185     functionInitialization(0)
1186     dispatch(0)
1187
1188
1189 _llint_function_for_construct_arity_check:
1190     prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct_arityCheck, _llint_trace_arityCheck_for_construct)
1191     functionArityCheck(.functionForConstructBegin, _slow_path_construct_arityCheck)
1192 .functionForConstructBegin:
1193     functionInitialization(1)
1194     dispatch(0)
1195
1196
1197 # Value-representation-specific code.
1198 if JSVALUE64
1199     include LowLevelInterpreter64
1200 else
1201     include LowLevelInterpreter32_64
1202 end
1203
1204
1205 # Value-representation-agnostic code.
1206 _llint_op_create_direct_arguments:
1207     traceExecution()
1208     callSlowPath(_slow_path_create_direct_arguments)
1209     dispatch(2)
1210
1211
1212 _llint_op_create_scoped_arguments:
1213     traceExecution()
1214     callSlowPath(_slow_path_create_scoped_arguments)
1215     dispatch(3)
1216
1217
1218 _llint_op_create_out_of_band_arguments:
1219     traceExecution()
1220     callSlowPath(_slow_path_create_out_of_band_arguments)
1221     dispatch(2)
1222
1223
1224 _llint_op_new_func:
1225     traceExecution()
1226     callSlowPath(_llint_slow_path_new_func)
1227     dispatch(4)
1228
1229
1230 _llint_op_new_array:
1231     traceExecution()
1232     callSlowPath(_llint_slow_path_new_array)
1233     dispatch(5)
1234
1235
1236 _llint_op_new_array_with_size:
1237     traceExecution()
1238     callSlowPath(_llint_slow_path_new_array_with_size)
1239     dispatch(4)
1240
1241
1242 _llint_op_new_array_buffer:
1243     traceExecution()
1244     callSlowPath(_llint_slow_path_new_array_buffer)
1245     dispatch(5)
1246
1247
1248 _llint_op_new_regexp:
1249     traceExecution()
1250     callSlowPath(_llint_slow_path_new_regexp)
1251     dispatch(3)
1252
1253
1254 _llint_op_less:
1255     traceExecution()
1256     callSlowPath(_slow_path_less)
1257     dispatch(4)
1258
1259
1260 _llint_op_lesseq:
1261     traceExecution()
1262     callSlowPath(_slow_path_lesseq)
1263     dispatch(4)
1264
1265
1266 _llint_op_greater:
1267     traceExecution()
1268     callSlowPath(_slow_path_greater)
1269     dispatch(4)
1270
1271
1272 _llint_op_greatereq:
1273     traceExecution()
1274     callSlowPath(_slow_path_greatereq)
1275     dispatch(4)
1276
1277
1278 _llint_op_mod:
1279     traceExecution()
1280     callSlowPath(_slow_path_mod)
1281     dispatch(4)
1282
1283
1284 _llint_op_typeof:
1285     traceExecution()
1286     callSlowPath(_slow_path_typeof)
1287     dispatch(3)
1288
1289
1290 _llint_op_is_object_or_null:
1291     traceExecution()
1292     callSlowPath(_slow_path_is_object_or_null)
1293     dispatch(3)
1294
1295 _llint_op_is_function:
1296     traceExecution()
1297     callSlowPath(_slow_path_is_function)
1298     dispatch(3)
1299
1300
1301 _llint_op_in:
1302     traceExecution()
1303     callSlowPath(_slow_path_in)
1304     dispatch(4)
1305
1306
1307 _llint_op_del_by_id:
1308     traceExecution()
1309     callSlowPath(_llint_slow_path_del_by_id)
1310     dispatch(4)
1311
1312
1313 _llint_op_del_by_val:
1314     traceExecution()
1315     callSlowPath(_llint_slow_path_del_by_val)
1316     dispatch(4)
1317
1318
1319 _llint_op_put_by_index:
1320     traceExecution()
1321     callSlowPath(_llint_slow_path_put_by_index)
1322     dispatch(4)
1323
1324
1325 _llint_op_put_getter_by_id:
1326     traceExecution()
1327     callSlowPath(_llint_slow_path_put_getter_by_id)
1328     dispatch(5)
1329
1330
1331 _llint_op_put_setter_by_id:
1332     traceExecution()
1333     callSlowPath(_llint_slow_path_put_setter_by_id)
1334     dispatch(5)
1335
1336
1337 _llint_op_put_getter_setter:
1338     traceExecution()
1339     callSlowPath(_llint_slow_path_put_getter_setter)
1340     dispatch(6)
1341
1342
1343 _llint_op_put_getter_by_val:
1344     traceExecution()
1345     callSlowPath(_llint_slow_path_put_getter_by_val)
1346     dispatch(5)
1347
1348
1349 _llint_op_put_setter_by_val:
1350     traceExecution()
1351     callSlowPath(_llint_slow_path_put_setter_by_val)
1352     dispatch(5)
1353
1354
1355 _llint_op_jtrue:
1356     traceExecution()
1357     jumpTrueOrFalse(
1358         macro (value, target) btinz value, target end,
1359         _llint_slow_path_jtrue)
1360
1361
1362 _llint_op_jfalse:
1363     traceExecution()
1364     jumpTrueOrFalse(
1365         macro (value, target) btiz value, target end,
1366         _llint_slow_path_jfalse)
1367
1368
1369 _llint_op_jless:
1370     traceExecution()
1371     compare(
1372         macro (left, right, target) bilt left, right, target end,
1373         macro (left, right, target) bdlt left, right, target end,
1374         _llint_slow_path_jless)
1375
1376
1377 _llint_op_jnless:
1378     traceExecution()
1379     compare(
1380         macro (left, right, target) bigteq left, right, target end,
1381         macro (left, right, target) bdgtequn left, right, target end,
1382         _llint_slow_path_jnless)
1383
1384
1385 _llint_op_jgreater:
1386     traceExecution()
1387     compare(
1388         macro (left, right, target) bigt left, right, target end,
1389         macro (left, right, target) bdgt left, right, target end,
1390         _llint_slow_path_jgreater)
1391
1392
1393 _llint_op_jngreater:
1394     traceExecution()
1395     compare(
1396         macro (left, right, target) bilteq left, right, target end,
1397         macro (left, right, target) bdltequn left, right, target end,
1398         _llint_slow_path_jngreater)
1399
1400
1401 _llint_op_jlesseq:
1402     traceExecution()
1403     compare(
1404         macro (left, right, target) bilteq left, right, target end,
1405         macro (left, right, target) bdlteq left, right, target end,
1406         _llint_slow_path_jlesseq)
1407
1408
1409 _llint_op_jnlesseq:
1410     traceExecution()
1411     compare(
1412         macro (left, right, target) bigt left, right, target end,
1413         macro (left, right, target) bdgtun left, right, target end,
1414         _llint_slow_path_jnlesseq)
1415
1416
1417 _llint_op_jgreatereq:
1418     traceExecution()
1419     compare(
1420         macro (left, right, target) bigteq left, right, target end,
1421         macro (left, right, target) bdgteq left, right, target end,
1422         _llint_slow_path_jgreatereq)
1423
1424
1425 _llint_op_jngreatereq:
1426     traceExecution()
1427     compare(
1428         macro (left, right, target) bilt left, right, target end,
1429         macro (left, right, target) bdltun left, right, target end,
1430         _llint_slow_path_jngreatereq)
1431
1432
1433 _llint_op_loop_hint:
1434     traceExecution()
1435     loadp CodeBlock[cfr], t1
1436     loadp CodeBlock::m_vm[t1], t1
1437     loadp VM::watchdog[t1], t0
1438     btpnz t0, .handleWatchdogTimer
1439 .afterWatchdogTimerCheck:
1440     checkSwitchToJITForLoop()
1441     dispatch(1)
1442 .handleWatchdogTimer:
1443     loadb Watchdog::m_timerDidFire[t0], t0
1444     btbz t0, .afterWatchdogTimerCheck
1445     callWatchdogTimerHandler(.throwHandler)
1446     jmp .afterWatchdogTimerCheck
1447 .throwHandler:
1448     jmp _llint_throw_from_slow_path_trampoline
1449
1450 _llint_op_switch_string:
1451     traceExecution()
1452     callSlowPath(_llint_slow_path_switch_string)
1453     dispatch(0)
1454
1455
1456 _llint_op_new_func_exp:
1457     traceExecution()
1458     callSlowPath(_llint_slow_path_new_func_exp)
1459     dispatch(4)
1460
1461 _llint_op_new_arrow_func_exp:
1462     traceExecution()
1463     callSlowPath(_llint_slow_path_new_arrow_func_exp)
1464     dispatch(5)
1465
1466 _llint_op_call:
1467     traceExecution()
1468     arrayProfileForCall()
1469     doCall(_llint_slow_path_call, prepareForRegularCall)
1470
1471 _llint_op_tail_call:
1472     traceExecution()
1473     arrayProfileForCall()
1474     checkSwitchToJITForEpilogue()
1475     doCall(_llint_slow_path_call, prepareForTailCall)
1476
1477 _llint_op_construct:
1478     traceExecution()
1479     doCall(_llint_slow_path_construct, prepareForRegularCall)
1480
1481 macro doCallVarargs(slowPath, prepareCall)
1482     callSlowPath(_llint_slow_path_size_frame_for_varargs)
1483     branchIfException(_llint_throw_from_slow_path_trampoline)
1484     # calleeFrame in r1
1485     if JSVALUE64
1486         move r1, sp
1487     else
1488         # The calleeFrame is not stack aligned, move down by CallerFrameAndPCSize to align
1489         if ARMv7
1490             subp r1, CallerFrameAndPCSize, t2
1491             move t2, sp
1492         else
1493             subp r1, CallerFrameAndPCSize, sp
1494         end
1495     end
1496     slowPathForCall(slowPath, prepareCall)
1497 end
1498
1499 _llint_op_call_varargs:
1500     traceExecution()
1501     doCallVarargs(_llint_slow_path_call_varargs, prepareForRegularCall)
1502
1503 _llint_op_tail_call_varargs:
1504     traceExecution()
1505     checkSwitchToJITForEpilogue()
1506     # We lie and perform the tail call instead of preparing it since we can't
1507     # prepare the frame for a call opcode
1508     doCallVarargs(_llint_slow_path_call_varargs, prepareForTailCall)
1509
1510 _llint_op_construct_varargs:
1511     traceExecution()
1512     doCallVarargs(_llint_slow_path_construct_varargs, prepareForRegularCall)
1513
1514
1515 _llint_op_call_eval:
1516     traceExecution()
1517     
1518     # Eval is executed in one of two modes:
1519     #
1520     # 1) We find that we're really invoking eval() in which case the
1521     #    execution is perfomed entirely inside the slow_path, and it
1522     #    returns the PC of a function that just returns the return value
1523     #    that the eval returned.
1524     #
1525     # 2) We find that we're invoking something called eval() that is not
1526     #    the real eval. Then the slow_path returns the PC of the thing to
1527     #    call, and we call it.
1528     #
1529     # This allows us to handle two cases, which would require a total of
1530     # up to four pieces of state that cannot be easily packed into two
1531     # registers (C functions can return up to two registers, easily):
1532     #
1533     # - The call frame register. This may or may not have been modified
1534     #   by the slow_path, but the convention is that it returns it. It's not
1535     #   totally clear if that's necessary, since the cfr is callee save.
1536     #   But that's our style in this here interpreter so we stick with it.
1537     #
1538     # - A bit to say if the slow_path successfully executed the eval and has
1539     #   the return value, or did not execute the eval but has a PC for us
1540     #   to call.
1541     #
1542     # - Either:
1543     #   - The JS return value (two registers), or
1544     #
1545     #   - The PC to call.
1546     #
1547     # It turns out to be easier to just always have this return the cfr
1548     # and a PC to call, and that PC may be a dummy thunk that just
1549     # returns the JS value that the eval returned.
1550     
1551     slowPathForCall(_llint_slow_path_call_eval, prepareForRegularCall)
1552
1553
1554 _llint_generic_return_point:
1555     dispatchAfterCall()
1556
1557
1558 _llint_op_strcat:
1559     traceExecution()
1560     callSlowPath(_slow_path_strcat)
1561     dispatch(4)
1562
1563
1564 _llint_op_push_with_scope:
1565     traceExecution()
1566     callSlowPath(_slow_path_push_with_scope)
1567     dispatch(4)
1568
1569
1570 _llint_op_create_lexical_environment:
1571     traceExecution()
1572     callSlowPath(_slow_path_create_lexical_environment)
1573     dispatch(5)
1574
1575
1576 _llint_op_throw:
1577     traceExecution()
1578     callSlowPath(_llint_slow_path_throw)
1579     dispatch(2)
1580
1581
1582 _llint_op_throw_static_error:
1583     traceExecution()
1584     callSlowPath(_llint_slow_path_throw_static_error)
1585     dispatch(3)
1586
1587
1588 _llint_op_profile_will_call:
1589     traceExecution()
1590     loadp CodeBlock[cfr], t0
1591     loadp CodeBlock::m_vm[t0], t0
1592     loadi VM::m_enabledProfiler[t0], t0
1593     btpz t0, .opProfilerWillCallDone
1594     callSlowPath(_llint_slow_path_profile_will_call)
1595 .opProfilerWillCallDone:
1596     dispatch(2)
1597
1598
1599 _llint_op_profile_did_call:
1600     traceExecution()
1601     loadp CodeBlock[cfr], t0
1602     loadp CodeBlock::m_vm[t0], t0
1603     loadi VM::m_enabledProfiler[t0], t0
1604     btpz t0, .opProfilerDidCallDone
1605     callSlowPath(_llint_slow_path_profile_did_call)
1606 .opProfilerDidCallDone:
1607     dispatch(2)
1608
1609
1610 _llint_op_debug:
1611     traceExecution()
1612     loadp CodeBlock[cfr], t0
1613     loadi CodeBlock::m_debuggerRequests[t0], t0
1614     btiz t0, .opDebugDone
1615     callSlowPath(_llint_slow_path_debug)
1616 .opDebugDone:                    
1617     dispatch(3)
1618
1619
1620 _llint_native_call_trampoline:
1621     nativeCallTrampoline(NativeExecutable::m_function)
1622
1623
1624 _llint_native_construct_trampoline:
1625     nativeCallTrampoline(NativeExecutable::m_constructor)
1626
1627 _llint_op_get_enumerable_length:
1628     traceExecution()
1629     callSlowPath(_slow_path_get_enumerable_length)
1630     dispatch(3)
1631
1632 _llint_op_has_indexed_property:
1633     traceExecution()
1634     callSlowPath(_slow_path_has_indexed_property)
1635     dispatch(5)
1636
1637 _llint_op_has_structure_property:
1638     traceExecution()
1639     callSlowPath(_slow_path_has_structure_property)
1640     dispatch(5)
1641
1642 _llint_op_has_generic_property:
1643     traceExecution()
1644     callSlowPath(_slow_path_has_generic_property)
1645     dispatch(4)
1646
1647 _llint_op_get_direct_pname:
1648     traceExecution()
1649     callSlowPath(_slow_path_get_direct_pname)
1650     dispatch(7)
1651
1652 _llint_op_get_property_enumerator:
1653     traceExecution()
1654     callSlowPath(_slow_path_get_property_enumerator)
1655     dispatch(3)
1656
1657 _llint_op_enumerator_structure_pname:
1658     traceExecution()
1659     callSlowPath(_slow_path_next_structure_enumerator_pname)
1660     dispatch(4)
1661
1662 _llint_op_enumerator_generic_pname:
1663     traceExecution()
1664     callSlowPath(_slow_path_next_generic_enumerator_pname)
1665     dispatch(4)
1666
1667 _llint_op_to_index_string:
1668     traceExecution()
1669     callSlowPath(_slow_path_to_index_string)
1670     dispatch(3)
1671
1672 _llint_op_profile_control_flow:
1673     traceExecution()
1674     loadpFromInstruction(1, t0)
1675     storeb 1, BasicBlockLocation::m_hasExecuted[t0]
1676     dispatch(2)
1677
1678 # Lastly, make sure that we can link even though we don't support all opcodes.
1679 # These opcodes should never arise when using LLInt or either JIT. We assert
1680 # as much.
1681
1682 macro notSupported()
1683     if ASSERT_ENABLED
1684         crash()
1685     else
1686         # We should use whatever the smallest possible instruction is, just to
1687         # ensure that there is a gap between instruction labels. If multiple
1688         # smallest instructions exist, we should pick the one that is most
1689         # likely result in execution being halted. Currently that is the break
1690         # instruction on all architectures we're interested in. (Break is int3
1691         # on Intel, which is 1 byte, and bkpt on ARMv7, which is 2 bytes.)
1692         break
1693     end
1694 end