2a75c837c858ef8880a99813918f72f8161cec65
[WebKit-https.git] / Source / JavaScriptCore / llint / LowLevelInterpreter.asm
1 # Copyright (C) 2011-2016 Apple Inc. All rights reserved.
2 #
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions
5 # are met:
6 # 1. Redistributions of source code must retain the above copyright
7 #    notice, this list of conditions and the following disclaimer.
8 # 2. Redistributions in binary form must reproduce the above copyright
9 #    notice, this list of conditions and the following disclaimer in the
10 #    documentation and/or other materials provided with the distribution.
11 #
12 # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
13 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
14 # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
15 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
16 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
17 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
18 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
19 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
20 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
21 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
22 # THE POSSIBILITY OF SUCH DAMAGE.
23
24 # 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 CallOpCodeSize = 9
225
226 if X86_64 or ARM64 or C_LOOP
227     const maxFrameExtentForSlowPathCall = 0
228 elsif ARM or ARMv7_TRADITIONAL or ARMv7 or SH4
229     const maxFrameExtentForSlowPathCall = 24
230 elsif X86 or X86_WIN
231     const maxFrameExtentForSlowPathCall = 40
232 elsif MIPS
233     const maxFrameExtentForSlowPathCall = 40
234 elsif X86_64_WIN
235     const maxFrameExtentForSlowPathCall = 64
236 end
237
238 if X86_64 or X86_64_WIN or ARM64
239     const CalleeSaveSpaceAsVirtualRegisters = 3
240 else
241     const CalleeSaveSpaceAsVirtualRegisters = 0
242 end
243
244 const CalleeSaveSpaceStackAligned = (CalleeSaveSpaceAsVirtualRegisters * SlotSize + StackAlignment - 1) & ~StackAlignmentMask
245
246
247 # Watchpoint states
248 const ClearWatchpoint = 0
249 const IsWatched = 1
250 const IsInvalidated = 2
251
252 # ShadowChicken data
253 const ShadowChickenTailMarker = 0x7a11
254
255 # Some register conventions.
256 if JSVALUE64
257     # - Use a pair of registers to represent the PC: one register for the
258     #   base of the bytecodes, and one register for the index.
259     # - The PC base (or PB for short) must be stored in a callee-save register.
260     # - C calls are still given the Instruction* rather than the PC index.
261     #   This requires an add before the call, and a sub after.
262     const PC = t4 # When changing this, make sure LLIntPC is up to date in LLIntPCRanges.h
263     if ARM64
264         const PB = csr7
265         const tagTypeNumber = csr8
266         const tagMask = csr9
267     elsif X86_64
268         const PB = csr2
269         const tagTypeNumber = csr3
270         const tagMask = csr4
271     elsif X86_64_WIN
272         const PB = csr4
273         const tagTypeNumber = csr5
274         const tagMask = csr6
275     elsif C_LOOP
276         const PB = csr0
277         const tagTypeNumber = csr1
278         const tagMask = csr2
279     end
280
281     macro loadisFromInstruction(offset, dest)
282         loadis offset * 8[PB, PC, 8], dest
283     end
284     
285     macro loadpFromInstruction(offset, dest)
286         loadp offset * 8[PB, PC, 8], dest
287     end
288     
289     macro storepToInstruction(value, offset)
290         storep value, offset * 8[PB, PC, 8]
291     end
292
293 else
294     const PC = t4 # When changing this, make sure LLIntPC is up to date in LLIntPCRanges.h
295     macro loadisFromInstruction(offset, dest)
296         loadis offset * 4[PC], dest
297     end
298     
299     macro loadpFromInstruction(offset, dest)
300         loadp offset * 4[PC], dest
301     end
302 end
303
304 if X86_64_WIN
305     const extraTempReg = t0
306 else
307     const extraTempReg = t5
308 end
309
310 # Constants for reasoning about value representation.
311 if BIG_ENDIAN
312     const TagOffset = 0
313     const PayloadOffset = 4
314 else
315     const TagOffset = 4
316     const PayloadOffset = 0
317 end
318
319 # Constant for reasoning about butterflies.
320 const IsArray                  = 1
321 const IndexingShapeMask        = 30
322 const NoIndexingShape          = 0
323 const Int32Shape               = 20
324 const DoubleShape              = 22
325 const ContiguousShape          = 26
326 const ArrayStorageShape        = 28
327 const SlowPutArrayStorageShape = 30
328
329 # Type constants.
330 const StringType = 6
331 const SymbolType = 7
332 const ObjectType = 20
333 const FinalObjectType = 21
334 const JSFunctionType = 23
335 const ArrayType = 29
336
337 # The typed array types need to be numbered in a particular order because of the manually written
338 # switch statement in get_by_val and put_by_val.
339 const Int8ArrayType = 100
340 const Int16ArrayType = 101
341 const Int32ArrayType = 102
342 const Uint8ArrayType = 103
343 const Uint8ClampedArrayType = 104
344 const Uint16ArrayType = 105
345 const Uint32ArrayType = 106
346 const Float32ArrayType = 107
347 const Float64ArrayType = 108
348
349 const FirstArrayType = Int8ArrayType
350 const LastArrayType = Float64ArrayType
351
352 # Type flags constants.
353 const MasqueradesAsUndefined = 1
354 const ImplementsDefaultHasInstance = 2
355
356 # Bytecode operand constants.
357 const FirstConstantRegisterIndex = 0x40000000
358
359 # Code type constants.
360 const GlobalCode = 0
361 const EvalCode = 1
362 const FunctionCode = 2
363 const ModuleCode = 3
364
365 # The interpreter steals the tag word of the argument count.
366 const LLIntReturnPC = ArgumentCount + TagOffset
367
368 # String flags.
369 const HashFlags8BitBuffer = 8
370
371 # Copied from PropertyOffset.h
372 const firstOutOfLineOffset = 100
373
374 # ResolveType
375 const GlobalProperty = 0
376 const GlobalVar = 1
377 const GlobalLexicalVar = 2
378 const ClosureVar = 3
379 const LocalClosureVar = 4
380 const ModuleVar = 5
381 const GlobalPropertyWithVarInjectionChecks = 6
382 const GlobalVarWithVarInjectionChecks = 7
383 const GlobalLexicalVarWithVarInjectionChecks = 8
384 const ClosureVarWithVarInjectionChecks = 9
385
386 const ResolveTypeMask = 0x3ff
387 const InitializationModeMask = 0xffc00
388 const InitializationModeShift = 10
389 const NotInitialization = 2
390
391 const MarkedBlockSize = 16 * 1024
392 const MarkedBlockMask = ~(MarkedBlockSize - 1)
393
394 # Allocation constants
395 if JSVALUE64
396     const JSFinalObjectSizeClassIndex = 1
397 else
398     const JSFinalObjectSizeClassIndex = 3
399 end
400
401 # This must match wtf/Vector.h
402 const VectorBufferOffset = 0
403 if JSVALUE64
404     const VectorSizeOffset = 12
405 else
406     const VectorSizeOffset = 8
407 end
408
409 # Some common utilities.
410 macro crash()
411     if C_LOOP
412         cloopCrash
413     else
414         call _llint_crash
415     end
416 end
417
418 macro assert(assertion)
419     if ASSERT_ENABLED
420         assertion(.ok)
421         crash()
422     .ok:
423     end
424 end
425
426 macro checkStackPointerAlignment(tempReg, location)
427     if ARM64 or C_LOOP or SH4
428         # ARM64 will check for us!
429         # C_LOOP does not need the alignment, and can use a little perf
430         # improvement from avoiding useless work.
431         # SH4 does not need specific alignment (4 bytes).
432     else
433         if ARM or ARMv7 or ARMv7_TRADITIONAL
434             # ARM can't do logical ops with the sp as a source
435             move sp, tempReg
436             andp StackAlignmentMask, tempReg
437         else
438             andp sp, StackAlignmentMask, tempReg
439         end
440         btpz tempReg, .stackPointerOkay
441         move location, tempReg
442         break
443     .stackPointerOkay:
444     end
445 end
446
447 if C_LOOP or ARM64 or X86_64 or X86_64_WIN
448     const CalleeSaveRegisterCount = 0
449 elsif ARM or ARMv7_TRADITIONAL or ARMv7
450     const CalleeSaveRegisterCount = 7
451 elsif SH4
452     const CalleeSaveRegisterCount = 5
453 elsif MIPS
454     const CalleeSaveRegisterCount = 1
455 elsif X86 or X86_WIN
456     const CalleeSaveRegisterCount = 3
457 end
458
459 const CalleeRegisterSaveSize = CalleeSaveRegisterCount * PtrSize
460
461 # VMEntryTotalFrameSize includes the space for struct VMEntryRecord and the
462 # callee save registers rounded up to keep the stack aligned
463 const VMEntryTotalFrameSize = (CalleeRegisterSaveSize + sizeof VMEntryRecord + StackAlignment - 1) & ~StackAlignmentMask
464
465 macro pushCalleeSaves()
466     if C_LOOP or ARM64 or X86_64 or X86_64_WIN
467     elsif ARM or ARMv7_TRADITIONAL
468         emit "push {r4-r10}"
469     elsif ARMv7
470         emit "push {r4-r6, r8-r11}"
471     elsif MIPS
472         emit "addiu $sp, $sp, -4"
473         emit "sw $s4, 0($sp)"
474         # save $gp to $s4 so that we can restore it after a function call
475         emit "move $s4, $gp"
476     elsif SH4
477         emit "mov.l r13, @-r15"
478         emit "mov.l r11, @-r15"
479         emit "mov.l r10, @-r15"
480         emit "mov.l r9, @-r15"
481         emit "mov.l r8, @-r15"
482     elsif X86
483         emit "push %esi"
484         emit "push %edi"
485         emit "push %ebx"
486     elsif X86_WIN
487         emit "push esi"
488         emit "push edi"
489         emit "push ebx"
490     end
491 end
492
493 macro popCalleeSaves()
494     if C_LOOP or ARM64 or X86_64 or X86_64_WIN
495     elsif ARM or ARMv7_TRADITIONAL
496         emit "pop {r4-r10}"
497     elsif ARMv7
498         emit "pop {r4-r6, r8-r11}"
499     elsif MIPS
500         emit "lw $s4, 0($sp)"
501         emit "addiu $sp, $sp, 4"
502     elsif SH4
503         emit "mov.l @r15+, r8"
504         emit "mov.l @r15+, r9"
505         emit "mov.l @r15+, r10"
506         emit "mov.l @r15+, r11"
507         emit "mov.l @r15+, r13"
508     elsif X86
509         emit "pop %ebx"
510         emit "pop %edi"
511         emit "pop %esi"
512     elsif X86_WIN
513         emit "pop ebx"
514         emit "pop edi"
515         emit "pop esi"
516     end
517 end
518
519 macro preserveCallerPCAndCFR()
520     if C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS or SH4
521         push lr
522         push cfr
523     elsif X86 or X86_WIN or X86_64 or X86_64_WIN
524         push cfr
525     elsif ARM64
526         push cfr, lr
527     else
528         error
529     end
530     move sp, cfr
531 end
532
533 macro restoreCallerPCAndCFR()
534     move cfr, sp
535     if C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS or SH4
536         pop cfr
537         pop lr
538     elsif X86 or X86_WIN or X86_64 or X86_64_WIN
539         pop cfr
540     elsif ARM64
541         pop lr, cfr
542     end
543 end
544
545 macro preserveCalleeSavesUsedByLLInt()
546     subp CalleeSaveSpaceStackAligned, sp
547     if C_LOOP
548     elsif ARM or ARMv7_TRADITIONAL
549     elsif ARMv7
550     elsif ARM64
551         emit "stp x27, x28, [x29, #-16]"
552         emit "stp xzr, x26, [x29, #-32]"
553     elsif MIPS
554     elsif SH4
555     elsif X86
556     elsif X86_WIN
557     elsif X86_64
558         storep csr4, -8[cfr]
559         storep csr3, -16[cfr]
560         storep csr2, -24[cfr]
561     elsif X86_64_WIN
562         storep csr6, -8[cfr]
563         storep csr5, -16[cfr]
564         storep csr4, -24[cfr]
565     end
566 end
567
568 macro restoreCalleeSavesUsedByLLInt()
569     if C_LOOP
570     elsif ARM or ARMv7_TRADITIONAL
571     elsif ARMv7
572     elsif ARM64
573         emit "ldp xzr, x26, [x29, #-32]"
574         emit "ldp x27, x28, [x29, #-16]"
575     elsif MIPS
576     elsif SH4
577     elsif X86
578     elsif X86_WIN
579     elsif X86_64
580         loadp -24[cfr], csr2
581         loadp -16[cfr], csr3
582         loadp -8[cfr], csr4
583     elsif X86_64_WIN
584         loadp -24[cfr], csr4
585         loadp -16[cfr], csr5
586         loadp -8[cfr], csr6
587     end
588 end
589
590 macro copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(vm, temp)
591     if ARM64 or X86_64 or X86_64_WIN
592         loadp VM::topVMEntryFrame[vm], temp
593         vmEntryRecord(temp, temp)
594         leap VMEntryRecord::calleeSaveRegistersBuffer[temp], temp
595         if ARM64
596             storep csr0, [temp]
597             storep csr1, 8[temp]
598             storep csr2, 16[temp]
599             storep csr3, 24[temp]
600             storep csr4, 32[temp]
601             storep csr5, 40[temp]
602             storep csr6, 48[temp]
603             storep csr7, 56[temp]
604             storep csr8, 64[temp]
605             storep csr9, 72[temp]
606             stored csfr0, 80[temp]
607             stored csfr1, 88[temp]
608             stored csfr2, 96[temp]
609             stored csfr3, 104[temp]
610             stored csfr4, 112[temp]
611             stored csfr5, 120[temp]
612             stored csfr6, 128[temp]
613             stored csfr7, 136[temp]
614         elsif X86_64
615             storep csr0, [temp]
616             storep csr1, 8[temp]
617             storep csr2, 16[temp]
618             storep csr3, 24[temp]
619             storep csr4, 32[temp]
620         elsif X86_64_WIN
621             storep csr0, [temp]
622             storep csr1, 8[temp]
623             storep csr2, 16[temp]
624             storep csr3, 24[temp]
625             storep csr4, 32[temp]
626             storep csr5, 40[temp]
627             storep csr6, 48[temp]
628         end
629     end
630 end
631
632 macro restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer(vm, temp)
633     if ARM64 or X86_64 or X86_64_WIN
634         loadp VM::topVMEntryFrame[vm], temp
635         vmEntryRecord(temp, temp)
636         leap VMEntryRecord::calleeSaveRegistersBuffer[temp], temp
637         if ARM64
638             loadp [temp], csr0
639             loadp 8[temp], csr1
640             loadp 16[temp], csr2
641             loadp 24[temp], csr3
642             loadp 32[temp], csr4
643             loadp 40[temp], csr5
644             loadp 48[temp], csr6
645             loadp 56[temp], csr7
646             loadp 64[temp], csr8
647             loadp 72[temp], csr9
648             loadd 80[temp], csfr0
649             loadd 88[temp], csfr1
650             loadd 96[temp], csfr2
651             loadd 104[temp], csfr3
652             loadd 112[temp], csfr4
653             loadd 120[temp], csfr5
654             loadd 128[temp], csfr6
655             loadd 136[temp], csfr7
656         elsif X86_64
657             loadp [temp], csr0
658             loadp 8[temp], csr1
659             loadp 16[temp], csr2
660             loadp 24[temp], csr3
661             loadp 32[temp], csr4
662         elsif X86_64_WIN
663             loadp [temp], csr0
664             loadp 8[temp], csr1
665             loadp 16[temp], csr2
666             loadp 24[temp], csr3
667             loadp 32[temp], csr4
668             loadp 40[temp], csr5
669             loadp 48[temp], csr6
670         end
671     end
672 end
673
674 macro preserveReturnAddressAfterCall(destinationRegister)
675     if C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or ARM64 or MIPS or SH4
676         # In C_LOOP case, we're only preserving the bytecode vPC.
677         move lr, destinationRegister
678     elsif X86 or X86_WIN or X86_64 or X86_64_WIN
679         pop destinationRegister
680     else
681         error
682     end
683 end
684
685 macro functionPrologue()
686     if X86 or X86_WIN or X86_64 or X86_64_WIN
687         push cfr
688     elsif ARM64
689         push cfr, lr
690     elsif C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS or SH4
691         push lr
692         push cfr
693     end
694     move sp, cfr
695 end
696
697 macro functionEpilogue()
698     if X86 or X86_WIN or X86_64 or X86_64_WIN
699         pop cfr
700     elsif ARM64
701         pop lr, cfr
702     elsif C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS or SH4
703         pop cfr
704         pop lr
705     end
706 end
707
708 macro vmEntryRecord(entryFramePointer, resultReg)
709     subp entryFramePointer, VMEntryTotalFrameSize, resultReg
710 end
711
712 macro getFrameRegisterSizeForCodeBlock(codeBlock, size)
713     loadi CodeBlock::m_numCalleeLocals[codeBlock], size
714     lshiftp 3, size
715     addp maxFrameExtentForSlowPathCall, size
716 end
717
718 macro restoreStackPointerAfterCall()
719     loadp CodeBlock[cfr], t2
720     getFrameRegisterSizeForCodeBlock(t2, t2)
721     if ARMv7
722         subp cfr, t2, t2
723         move t2, sp
724     else
725         subp cfr, t2, sp
726     end
727 end
728
729 macro traceExecution()
730     if COLLECT_STATS
731         callSlowPath(_llint_count_opcode)
732     end
733     if EXECUTION_TRACING
734         callSlowPath(_llint_trace)
735     end
736 end
737
738 macro traceSlowPathExecution()
739     if COLLECT_STATS
740         callSlowPath(_llint_count_opcode_slow_path)
741     end
742 end
743
744 macro callOpcodeSlowPath(slowPath)
745     traceSlowPathExecution()
746     callSlowPath(slowPath)
747 end
748
749 macro callTargetFunction(callee)
750     if C_LOOP
751         cloopCallJSFunction callee
752     else
753         call callee
754     end
755     restoreStackPointerAfterCall()
756     dispatchAfterCall()
757 end
758
759 macro prepareForRegularCall(callee, temp1, temp2, temp3)
760     addp CallerFrameAndPCSize, sp
761 end
762
763 # sp points to the new frame
764 macro prepareForTailCall(callee, temp1, temp2, temp3)
765     restoreCalleeSavesUsedByLLInt()
766
767     loadi PayloadOffset + ArgumentCount[cfr], temp2
768     loadp CodeBlock[cfr], temp1
769     loadp CodeBlock::m_numParameters[temp1], temp1
770     bilteq temp1, temp2, .noArityFixup
771     move temp1, temp2
772
773 .noArityFixup:
774     # We assume < 2^28 arguments
775     muli SlotSize, temp2
776     addi StackAlignment - 1 + CallFrameHeaderSize, temp2
777     andi ~StackAlignmentMask, temp2
778
779     move cfr, temp1
780     addp temp2, temp1
781
782     loadi PayloadOffset + ArgumentCount[sp], temp2
783     # We assume < 2^28 arguments
784     muli SlotSize, temp2
785     addi StackAlignment - 1 + CallFrameHeaderSize, temp2
786     andi ~StackAlignmentMask, temp2
787
788     if ARM or ARMv7_TRADITIONAL or ARMv7 or SH4 or ARM64 or C_LOOP or MIPS
789         addp 2 * PtrSize, sp
790         subi 2 * PtrSize, temp2
791         loadp PtrSize[cfr], lr
792     else
793         addp PtrSize, sp
794         subi PtrSize, temp2
795         loadp PtrSize[cfr], temp3
796         storep temp3, [sp]
797     end
798
799     subp temp2, temp1
800     loadp [cfr], cfr
801
802 .copyLoop:
803     subi PtrSize, temp2
804     loadp [sp, temp2, 1], temp3
805     storep temp3, [temp1, temp2, 1]
806     btinz temp2, .copyLoop
807
808     move temp1, sp
809     jmp callee
810 end
811
812 macro slowPathForCall(slowPath, prepareCall)
813     traceSlowPathExecution()
814     callCallSlowPath(
815         slowPath,
816         # Those are r0 and r1
817         macro (callee, calleeFramePtr)
818             btpz calleeFramePtr, .dontUpdateSP
819             move calleeFramePtr, sp
820             prepareCall(callee, t2, t3, t4)
821         .dontUpdateSP:
822             callTargetFunction(callee)
823         end)
824 end
825
826 macro arrayProfile(cellAndIndexingType, profile, scratch)
827     const cell = cellAndIndexingType
828     const indexingType = cellAndIndexingType 
829     loadi JSCell::m_structureID[cell], scratch
830     storei scratch, ArrayProfile::m_lastSeenStructureID[profile]
831     loadb JSCell::m_indexingType[cell], indexingType
832 end
833
834 macro skipIfIsRememberedOrInEden(cell, scratch1, scratch2, continuation)
835     loadb JSCell::m_cellState[cell], scratch1
836     continuation(scratch1)
837 end
838
839 macro notifyWrite(set, slow)
840     bbneq WatchpointSet::m_state[set], IsInvalidated, slow
841 end
842
843 macro checkSwitchToJIT(increment, action)
844     loadp CodeBlock[cfr], t0
845     baddis increment, CodeBlock::m_llintExecuteCounter + BaselineExecutionCounter::m_counter[t0], .continue
846     action()
847     .continue:
848 end
849
850 macro checkSwitchToJITForEpilogue()
851     checkSwitchToJIT(
852         10,
853         macro ()
854             callOpcodeSlowPath(_llint_replace)
855         end)
856 end
857
858 macro assertNotConstant(index)
859     assert(macro (ok) bilt index, FirstConstantRegisterIndex, ok end)
860 end
861
862 macro functionForCallCodeBlockGetter(targetRegister)
863     if JSVALUE64
864         loadp Callee[cfr], targetRegister
865     else
866         loadp Callee + PayloadOffset[cfr], targetRegister
867     end
868     loadp JSFunction::m_executable[targetRegister], targetRegister
869     loadp FunctionExecutable::m_codeBlockForCall[targetRegister], targetRegister
870 end
871
872 macro functionForConstructCodeBlockGetter(targetRegister)
873     if JSVALUE64
874         loadp Callee[cfr], targetRegister
875     else
876         loadp Callee + PayloadOffset[cfr], targetRegister
877     end
878     loadp JSFunction::m_executable[targetRegister], targetRegister
879     loadp FunctionExecutable::m_codeBlockForConstruct[targetRegister], targetRegister
880 end
881
882 macro notFunctionCodeBlockGetter(targetRegister)
883     loadp CodeBlock[cfr], targetRegister
884 end
885
886 macro functionCodeBlockSetter(sourceRegister)
887     storep sourceRegister, CodeBlock[cfr]
888 end
889
890 macro notFunctionCodeBlockSetter(sourceRegister)
891     # Nothing to do!
892 end
893
894 # Do the bare minimum required to execute code. Sets up the PC, leave the CodeBlock*
895 # in t1. May also trigger prologue entry OSR.
896 macro prologue(codeBlockGetter, codeBlockSetter, osrSlowPath, traceSlowPath)
897     # Set up the call frame and check if we should OSR.
898     preserveCallerPCAndCFR()
899
900     if EXECUTION_TRACING
901         subp maxFrameExtentForSlowPathCall, sp
902         callSlowPath(traceSlowPath)
903         addp maxFrameExtentForSlowPathCall, sp
904     end
905     codeBlockGetter(t1)
906     if not C_LOOP
907         baddis 5, CodeBlock::m_llintExecuteCounter + BaselineExecutionCounter::m_counter[t1], .continue
908         if JSVALUE64
909             move cfr, a0
910             move PC, a1
911             cCall2(osrSlowPath)
912         else
913             # We are after the function prologue, but before we have set up sp from the CodeBlock.
914             # Temporarily align stack pointer for this call.
915             subp 8, sp
916             move cfr, a0
917             move PC, a1
918             cCall2(osrSlowPath)
919             addp 8, sp
920         end
921         btpz r0, .recover
922         move cfr, sp # restore the previous sp
923         # pop the callerFrame since we will jump to a function that wants to save it
924         if ARM64
925             pop lr, cfr
926         elsif ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS or SH4
927             pop cfr
928             pop lr
929         else
930             pop cfr
931         end
932         jmp r0
933     .recover:
934         codeBlockGetter(t1)
935     .continue:
936     end
937
938     codeBlockSetter(t1)
939
940     preserveCalleeSavesUsedByLLInt()
941
942     # Set up the PC.
943     if JSVALUE64
944         loadp CodeBlock::m_instructions[t1], PB
945         move 0, PC
946     else
947         loadp CodeBlock::m_instructions[t1], PC
948     end
949
950     # Get new sp in t0 and check stack height.
951     getFrameRegisterSizeForCodeBlock(t1, t0)
952     subp cfr, t0, t0
953     loadp CodeBlock::m_vm[t1], t2
954     if C_LOOP
955         bpbeq VM::m_cloopStackLimit[t2], t0, .stackHeightOK
956     else
957         bpbeq VM::m_osStackLimitWithReserve[t2], t0, .stackHeightOK
958     end
959
960     # Stack height check failed - need to call a slow_path.
961     # Set up temporary stack pointer for call including callee saves
962     subp maxFrameExtentForSlowPathCall, sp
963     callSlowPath(_llint_stack_check)
964     bpeq r1, 0, .stackHeightOKGetCodeBlock
965     move r1, cfr
966     dispatch(0) # Go to exception handler in PC
967
968 .stackHeightOKGetCodeBlock:
969     # Stack check slow path returned that the stack was ok.
970     # Since they were clobbered, need to get CodeBlock and new sp
971     codeBlockGetter(t1)
972     getFrameRegisterSizeForCodeBlock(t1, t0)
973     subp cfr, t0, t0
974
975 .stackHeightOK:
976     move t0, sp
977
978     if JSVALUE64
979         move TagTypeNumber, tagTypeNumber
980         addp TagBitTypeOther, tagTypeNumber, tagMask
981     end
982 end
983
984 # Expects that CodeBlock is in t1, which is what prologue() leaves behind.
985 # Must call dispatch(0) after calling this.
986 macro functionInitialization(profileArgSkip)
987     # Profile the arguments. Unfortunately, we have no choice but to do this. This
988     # code is pretty horrendous because of the difference in ordering between
989     # arguments and value profiles, the desire to have a simple loop-down-to-zero
990     # loop, and the desire to use only three registers so as to preserve the PC and
991     # the code block. It is likely that this code should be rewritten in a more
992     # optimal way for architectures that have more than five registers available
993     # for arbitrary use in the interpreter.
994     loadi CodeBlock::m_numParameters[t1], t0
995     addp -profileArgSkip, t0 # Use addi because that's what has the peephole
996     assert(macro (ok) bpgteq t0, 0, ok end)
997     btpz t0, .argumentProfileDone
998     loadp CodeBlock::m_argumentValueProfiles + VectorBufferOffset[t1], t3
999     mulp sizeof ValueProfile, t0, t2 # Aaaaahhhh! Need strength reduction!
1000     lshiftp 3, t0
1001     addp t2, t3
1002 .argumentProfileLoop:
1003     if JSVALUE64
1004         loadq ThisArgumentOffset - 8 + profileArgSkip * 8[cfr, t0], t2
1005         subp sizeof ValueProfile, t3
1006         storeq t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets[t3]
1007     else
1008         loadi ThisArgumentOffset + TagOffset - 8 + profileArgSkip * 8[cfr, t0], t2
1009         subp sizeof ValueProfile, t3
1010         storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + TagOffset[t3]
1011         loadi ThisArgumentOffset + PayloadOffset - 8 + profileArgSkip * 8[cfr, t0], t2
1012         storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + PayloadOffset[t3]
1013     end
1014     baddpnz -8, t0, .argumentProfileLoop
1015 .argumentProfileDone:
1016 end
1017
1018 macro allocateJSObject(allocator, structure, result, scratch1, slowCase)
1019     const offsetOfFirstFreeCell = 
1020         MarkedAllocator::m_freeList + 
1021         MarkedBlock::FreeList::head
1022
1023     # Get the object from the free list.   
1024     loadp offsetOfFirstFreeCell[allocator], result
1025     btpz result, slowCase
1026     
1027     # Remove the object from the free list.
1028     loadp [result], scratch1
1029     storep scratch1, offsetOfFirstFreeCell[allocator]
1030
1031     # Initialize the object.
1032     storep 0, JSObject::m_butterfly[result]
1033     storeStructureWithTypeInfo(result, structure, scratch1)
1034 end
1035
1036 macro doReturn()
1037     restoreCalleeSavesUsedByLLInt()
1038     restoreCallerPCAndCFR()
1039     ret
1040 end
1041
1042 # stub to call into JavaScript or Native functions
1043 # EncodedJSValue vmEntryToJavaScript(void* code, VM* vm, ProtoCallFrame* protoFrame)
1044 # EncodedJSValue vmEntryToNativeFunction(void* code, VM* vm, ProtoCallFrame* protoFrame)
1045
1046 if C_LOOP
1047     _llint_vm_entry_to_javascript:
1048 else
1049     global _vmEntryToJavaScript
1050     _vmEntryToJavaScript:
1051 end
1052     doVMEntry(makeJavaScriptCall)
1053
1054
1055 if C_LOOP
1056     _llint_vm_entry_to_native:
1057 else
1058     global _vmEntryToNative
1059     _vmEntryToNative:
1060 end
1061     doVMEntry(makeHostFunctionCall)
1062
1063
1064 if not C_LOOP
1065     # void sanitizeStackForVMImpl(VM* vm)
1066     global _sanitizeStackForVMImpl
1067     _sanitizeStackForVMImpl:
1068         # We need three non-aliased caller-save registers. We are guaranteed
1069         # this for a0, a1 and a2 on all architectures.
1070         if X86 or X86_WIN
1071             loadp 4[sp], a0
1072         end
1073         const vm = a0
1074         const address = a1
1075         const zeroValue = a2
1076     
1077         loadp VM::m_lastStackTop[vm], address
1078         bpbeq sp, address, .zeroFillDone
1079     
1080         move 0, zeroValue
1081     .zeroFillLoop:
1082         storep zeroValue, [address]
1083         addp PtrSize, address
1084         bpa sp, address, .zeroFillLoop
1085     
1086     .zeroFillDone:
1087         move sp, address
1088         storep address, VM::m_lastStackTop[vm]
1089         ret
1090     
1091     # VMEntryRecord* vmEntryRecord(const VMEntryFrame* entryFrame)
1092     global _vmEntryRecord
1093     _vmEntryRecord:
1094         if X86 or X86_WIN
1095             loadp 4[sp], a0
1096         end
1097
1098         vmEntryRecord(a0, r0)
1099         ret
1100 end
1101
1102 if C_LOOP
1103     # Dummy entry point the C Loop uses to initialize.
1104     _llint_entry:
1105         crash()
1106 else
1107     macro initPCRelative(pcBase)
1108         if X86_64 or X86_64_WIN or X86 or X86_WIN
1109             call _relativePCBase
1110         _relativePCBase:
1111             pop pcBase
1112         elsif ARM64
1113         elsif ARMv7
1114         _relativePCBase:
1115             move pc, pcBase
1116             subp 3, pcBase   # Need to back up the PC and set the Thumb2 bit
1117         elsif ARM or ARMv7_TRADITIONAL
1118         _relativePCBase:
1119             move pc, pcBase
1120             subp 8, pcBase
1121         elsif MIPS
1122             la _relativePCBase, pcBase
1123             setcallreg pcBase # needed to set $t9 to the right value for the .cpload created by the label.
1124         _relativePCBase:
1125         elsif SH4
1126             mova _relativePCBase, t0
1127             move t0, pcBase
1128             alignformova
1129         _relativePCBase:
1130         end
1131 end
1132
1133 # The PC base is in t1, as this is what _llint_entry leaves behind through
1134 # initPCRelative(t1)
1135 macro setEntryAddress(index, label)
1136     if X86_64 or X86_64_WIN
1137         leap (label - _relativePCBase)[t1], t3
1138         move index, t4
1139         storep t3, [a0, t4, 8]
1140     elsif X86 or X86_WIN
1141         leap (label - _relativePCBase)[t1], t3
1142         move index, t4
1143         storep t3, [a0, t4, 4]
1144     elsif ARM64
1145         pcrtoaddr label, t1
1146         move index, t4
1147         storep t1, [a0, t4, 8]
1148     elsif ARM or ARMv7 or ARMv7_TRADITIONAL
1149         mvlbl (label - _relativePCBase), t4
1150         addp t4, t1, t4
1151         move index, t3
1152         storep t4, [a0, t3, 4]
1153     elsif SH4
1154         move (label - _relativePCBase), t4
1155         addp t4, t1, t4
1156         move index, t3
1157         storep t4, [a0, t3, 4]
1158         flushcp # Force constant pool flush to avoid "pcrel too far" link error.
1159     elsif MIPS
1160         la label, t4
1161         la _relativePCBase, t3
1162         subp t3, t4
1163         addp t4, t1, t4
1164         move index, t3
1165         storep t4, [a0, t3, 4]
1166     end
1167 end
1168
1169 global _llint_entry
1170 # Entry point for the llint to initialize.
1171 _llint_entry:
1172     functionPrologue()
1173     pushCalleeSaves()
1174     if X86 or X86_WIN
1175         loadp 20[sp], a0
1176     end
1177     initPCRelative(t1)
1178
1179     # Include generated bytecode initialization file.
1180     include InitBytecodes
1181
1182     popCalleeSaves()
1183     functionEpilogue()
1184     ret
1185 end
1186
1187 _llint_program_prologue:
1188     prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
1189     dispatch(0)
1190
1191
1192 _llint_module_program_prologue:
1193     prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
1194     dispatch(0)
1195
1196
1197 _llint_eval_prologue:
1198     prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
1199     dispatch(0)
1200
1201
1202 _llint_function_for_call_prologue:
1203     prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call, _llint_trace_prologue_function_for_call)
1204     functionInitialization(0)
1205     dispatch(0)
1206     
1207
1208 _llint_function_for_construct_prologue:
1209     prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct, _llint_trace_prologue_function_for_construct)
1210     functionInitialization(1)
1211     dispatch(0)
1212     
1213
1214 _llint_function_for_call_arity_check:
1215     prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call_arityCheck, _llint_trace_arityCheck_for_call)
1216     functionArityCheck(.functionForCallBegin, _slow_path_call_arityCheck)
1217 .functionForCallBegin:
1218     functionInitialization(0)
1219     dispatch(0)
1220
1221
1222 _llint_function_for_construct_arity_check:
1223     prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct_arityCheck, _llint_trace_arityCheck_for_construct)
1224     functionArityCheck(.functionForConstructBegin, _slow_path_construct_arityCheck)
1225 .functionForConstructBegin:
1226     functionInitialization(1)
1227     dispatch(0)
1228
1229
1230 # Value-representation-specific code.
1231 if JSVALUE64
1232     include LowLevelInterpreter64
1233 else
1234     include LowLevelInterpreter32_64
1235 end
1236
1237
1238 # Value-representation-agnostic code.
1239 _llint_op_create_direct_arguments:
1240     traceExecution()
1241     callOpcodeSlowPath(_slow_path_create_direct_arguments)
1242     dispatch(2)
1243
1244
1245 _llint_op_create_scoped_arguments:
1246     traceExecution()
1247     callOpcodeSlowPath(_slow_path_create_scoped_arguments)
1248     dispatch(3)
1249
1250
1251 _llint_op_create_cloned_arguments:
1252     traceExecution()
1253     callOpcodeSlowPath(_slow_path_create_cloned_arguments)
1254     dispatch(2)
1255
1256
1257 _llint_op_new_func:
1258     traceExecution()
1259     callOpcodeSlowPath(_llint_slow_path_new_func)
1260     dispatch(4)
1261
1262
1263 _llint_op_new_generator_func:
1264     traceExecution()
1265     callOpcodeSlowPath(_llint_slow_path_new_generator_func)
1266     dispatch(4)
1267
1268
1269 _llint_op_new_array:
1270     traceExecution()
1271     callOpcodeSlowPath(_llint_slow_path_new_array)
1272     dispatch(5)
1273
1274
1275 _llint_op_new_array_with_size:
1276     traceExecution()
1277     callOpcodeSlowPath(_llint_slow_path_new_array_with_size)
1278     dispatch(4)
1279
1280
1281 _llint_op_new_array_buffer:
1282     traceExecution()
1283     callOpcodeSlowPath(_llint_slow_path_new_array_buffer)
1284     dispatch(5)
1285
1286
1287 _llint_op_new_regexp:
1288     traceExecution()
1289     callOpcodeSlowPath(_llint_slow_path_new_regexp)
1290     dispatch(3)
1291
1292
1293 _llint_op_less:
1294     traceExecution()
1295     callOpcodeSlowPath(_slow_path_less)
1296     dispatch(4)
1297
1298
1299 _llint_op_lesseq:
1300     traceExecution()
1301     callOpcodeSlowPath(_slow_path_lesseq)
1302     dispatch(4)
1303
1304
1305 _llint_op_greater:
1306     traceExecution()
1307     callOpcodeSlowPath(_slow_path_greater)
1308     dispatch(4)
1309
1310
1311 _llint_op_greatereq:
1312     traceExecution()
1313     callOpcodeSlowPath(_slow_path_greatereq)
1314     dispatch(4)
1315
1316
1317 _llint_op_mod:
1318     traceExecution()
1319     callOpcodeSlowPath(_slow_path_mod)
1320     dispatch(4)
1321
1322
1323 _llint_op_typeof:
1324     traceExecution()
1325     callOpcodeSlowPath(_slow_path_typeof)
1326     dispatch(3)
1327
1328
1329 _llint_op_is_object_or_null:
1330     traceExecution()
1331     callOpcodeSlowPath(_slow_path_is_object_or_null)
1332     dispatch(3)
1333
1334 _llint_op_is_function:
1335     traceExecution()
1336     callOpcodeSlowPath(_slow_path_is_function)
1337     dispatch(3)
1338
1339
1340 _llint_op_in:
1341     traceExecution()
1342     callOpcodeSlowPath(_slow_path_in)
1343     dispatch(4)
1344
1345
1346 _llint_op_try_get_by_id:
1347     traceExecution()
1348     callOpcodeSlowPath(_llint_slow_path_try_get_by_id)
1349     dispatch(4)
1350
1351
1352 _llint_op_del_by_id:
1353     traceExecution()
1354     callOpcodeSlowPath(_llint_slow_path_del_by_id)
1355     dispatch(4)
1356
1357
1358 _llint_op_del_by_val:
1359     traceExecution()
1360     callOpcodeSlowPath(_llint_slow_path_del_by_val)
1361     dispatch(4)
1362
1363
1364 _llint_op_put_by_index:
1365     traceExecution()
1366     callOpcodeSlowPath(_llint_slow_path_put_by_index)
1367     dispatch(4)
1368
1369
1370 _llint_op_put_getter_by_id:
1371     traceExecution()
1372     callOpcodeSlowPath(_llint_slow_path_put_getter_by_id)
1373     dispatch(5)
1374
1375
1376 _llint_op_put_setter_by_id:
1377     traceExecution()
1378     callOpcodeSlowPath(_llint_slow_path_put_setter_by_id)
1379     dispatch(5)
1380
1381
1382 _llint_op_put_getter_setter_by_id:
1383     traceExecution()
1384     callOpcodeSlowPath(_llint_slow_path_put_getter_setter_by_id)
1385     dispatch(6)
1386
1387
1388 _llint_op_put_getter_by_val:
1389     traceExecution()
1390     callOpcodeSlowPath(_llint_slow_path_put_getter_by_val)
1391     dispatch(5)
1392
1393
1394 _llint_op_put_setter_by_val:
1395     traceExecution()
1396     callOpcodeSlowPath(_llint_slow_path_put_setter_by_val)
1397     dispatch(5)
1398
1399
1400 _llint_op_jtrue:
1401     traceExecution()
1402     jumpTrueOrFalse(
1403         macro (value, target) btinz value, target end,
1404         _llint_slow_path_jtrue)
1405
1406
1407 _llint_op_jfalse:
1408     traceExecution()
1409     jumpTrueOrFalse(
1410         macro (value, target) btiz value, target end,
1411         _llint_slow_path_jfalse)
1412
1413
1414 _llint_op_jless:
1415     traceExecution()
1416     compare(
1417         macro (left, right, target) bilt left, right, target end,
1418         macro (left, right, target) bdlt left, right, target end,
1419         _llint_slow_path_jless)
1420
1421
1422 _llint_op_jnless:
1423     traceExecution()
1424     compare(
1425         macro (left, right, target) bigteq left, right, target end,
1426         macro (left, right, target) bdgtequn left, right, target end,
1427         _llint_slow_path_jnless)
1428
1429
1430 _llint_op_jgreater:
1431     traceExecution()
1432     compare(
1433         macro (left, right, target) bigt left, right, target end,
1434         macro (left, right, target) bdgt left, right, target end,
1435         _llint_slow_path_jgreater)
1436
1437
1438 _llint_op_jngreater:
1439     traceExecution()
1440     compare(
1441         macro (left, right, target) bilteq left, right, target end,
1442         macro (left, right, target) bdltequn left, right, target end,
1443         _llint_slow_path_jngreater)
1444
1445
1446 _llint_op_jlesseq:
1447     traceExecution()
1448     compare(
1449         macro (left, right, target) bilteq left, right, target end,
1450         macro (left, right, target) bdlteq left, right, target end,
1451         _llint_slow_path_jlesseq)
1452
1453
1454 _llint_op_jnlesseq:
1455     traceExecution()
1456     compare(
1457         macro (left, right, target) bigt left, right, target end,
1458         macro (left, right, target) bdgtun left, right, target end,
1459         _llint_slow_path_jnlesseq)
1460
1461
1462 _llint_op_jgreatereq:
1463     traceExecution()
1464     compare(
1465         macro (left, right, target) bigteq left, right, target end,
1466         macro (left, right, target) bdgteq left, right, target end,
1467         _llint_slow_path_jgreatereq)
1468
1469
1470 _llint_op_jngreatereq:
1471     traceExecution()
1472     compare(
1473         macro (left, right, target) bilt left, right, target end,
1474         macro (left, right, target) bdltun left, right, target end,
1475         _llint_slow_path_jngreatereq)
1476
1477
1478 _llint_op_loop_hint:
1479     traceExecution()
1480     checkSwitchToJITForLoop()
1481     dispatch(1)
1482
1483
1484 _llint_op_watchdog:
1485     traceExecution()
1486     loadp CodeBlock[cfr], t1
1487     loadp CodeBlock::m_vm[t1], t1
1488     loadp VM::m_watchdog[t1], t0
1489     btpnz t0, .handleWatchdogTimer
1490 .afterWatchdogTimerCheck:
1491     dispatch(1)
1492 .handleWatchdogTimer:
1493     loadb Watchdog::m_timerDidFire[t0], t0
1494     btbz t0, .afterWatchdogTimerCheck
1495     callWatchdogTimerHandler(.throwHandler)
1496     jmp .afterWatchdogTimerCheck
1497 .throwHandler:
1498     jmp _llint_throw_from_slow_path_trampoline
1499
1500
1501 # Returns the packet pointer in t0.
1502 macro acquireShadowChickenPacket(slow)
1503     loadp CodeBlock[cfr], t1
1504     loadp CodeBlock::m_vm[t1], t1
1505     loadp VM::m_shadowChicken[t1], t2
1506     loadp ShadowChicken::m_logCursor[t2], t0
1507     bpaeq t0, ShadowChicken::m_logEnd[t2], slow
1508     addp sizeof ShadowChicken::Packet, t0, t1
1509     storep t1, ShadowChicken::m_logCursor[t2]
1510 end
1511
1512
1513 _llint_op_switch_string:
1514     traceExecution()
1515     callOpcodeSlowPath(_llint_slow_path_switch_string)
1516     dispatch(0)
1517
1518
1519 _llint_op_new_func_exp:
1520     traceExecution()
1521     callOpcodeSlowPath(_llint_slow_path_new_func_exp)
1522     dispatch(4)
1523
1524 _llint_op_new_generator_func_exp:
1525     traceExecution()
1526     callOpcodeSlowPath(_llint_slow_path_new_generator_func_exp)
1527     dispatch(4)
1528
1529 _llint_op_set_function_name:
1530     traceExecution()
1531     callOpcodeSlowPath(_llint_slow_path_set_function_name)
1532     dispatch(3)
1533
1534 _llint_op_call:
1535     traceExecution()
1536     arrayProfileForCall()
1537     doCall(_llint_slow_path_call, prepareForRegularCall)
1538
1539 _llint_op_tail_call:
1540     traceExecution()
1541     arrayProfileForCall()
1542     checkSwitchToJITForEpilogue()
1543     doCall(_llint_slow_path_call, prepareForTailCall)
1544
1545 _llint_op_construct:
1546     traceExecution()
1547     doCall(_llint_slow_path_construct, prepareForRegularCall)
1548
1549 macro doCallVarargs(frameSlowPath, slowPath, prepareCall)
1550     callOpcodeSlowPath(frameSlowPath)
1551     branchIfException(_llint_throw_from_slow_path_trampoline)
1552     # calleeFrame in r1
1553     if JSVALUE64
1554         move r1, sp
1555     else
1556         # The calleeFrame is not stack aligned, move down by CallerFrameAndPCSize to align
1557         if ARMv7
1558             subp r1, CallerFrameAndPCSize, t2
1559             move t2, sp
1560         else
1561             subp r1, CallerFrameAndPCSize, sp
1562         end
1563     end
1564     slowPathForCall(slowPath, prepareCall)
1565 end
1566
1567 _llint_op_call_varargs:
1568     traceExecution()
1569     doCallVarargs(_llint_slow_path_size_frame_for_varargs, _llint_slow_path_call_varargs, prepareForRegularCall)
1570
1571 _llint_op_tail_call_varargs:
1572     traceExecution()
1573     checkSwitchToJITForEpilogue()
1574     # We lie and perform the tail call instead of preparing it since we can't
1575     # prepare the frame for a call opcode
1576     doCallVarargs(_llint_slow_path_size_frame_for_varargs, _llint_slow_path_call_varargs, prepareForTailCall)
1577
1578
1579 _llint_op_tail_call_forward_arguments:
1580     traceExecution()
1581     checkSwitchToJITForEpilogue()
1582     # We lie and perform the tail call instead of preparing it since we can't
1583     # prepare the frame for a call opcode
1584     doCallVarargs(_llint_slow_path_size_frame_for_forward_arguments, _llint_slow_path_tail_call_forward_arguments, prepareForTailCall)
1585
1586
1587 _llint_op_construct_varargs:
1588     traceExecution()
1589     doCallVarargs(_llint_slow_path_size_frame_for_varargs, _llint_slow_path_construct_varargs, prepareForRegularCall)
1590
1591
1592 _llint_op_call_eval:
1593     traceExecution()
1594     
1595     # Eval is executed in one of two modes:
1596     #
1597     # 1) We find that we're really invoking eval() in which case the
1598     #    execution is perfomed entirely inside the slow_path, and it
1599     #    returns the PC of a function that just returns the return value
1600     #    that the eval returned.
1601     #
1602     # 2) We find that we're invoking something called eval() that is not
1603     #    the real eval. Then the slow_path returns the PC of the thing to
1604     #    call, and we call it.
1605     #
1606     # This allows us to handle two cases, which would require a total of
1607     # up to four pieces of state that cannot be easily packed into two
1608     # registers (C functions can return up to two registers, easily):
1609     #
1610     # - The call frame register. This may or may not have been modified
1611     #   by the slow_path, but the convention is that it returns it. It's not
1612     #   totally clear if that's necessary, since the cfr is callee save.
1613     #   But that's our style in this here interpreter so we stick with it.
1614     #
1615     # - A bit to say if the slow_path successfully executed the eval and has
1616     #   the return value, or did not execute the eval but has a PC for us
1617     #   to call.
1618     #
1619     # - Either:
1620     #   - The JS return value (two registers), or
1621     #
1622     #   - The PC to call.
1623     #
1624     # It turns out to be easier to just always have this return the cfr
1625     # and a PC to call, and that PC may be a dummy thunk that just
1626     # returns the JS value that the eval returned.
1627     
1628     slowPathForCall(_llint_slow_path_call_eval, prepareForRegularCall)
1629
1630
1631 _llint_generic_return_point:
1632     dispatchAfterCall()
1633
1634
1635 _llint_op_strcat:
1636     traceExecution()
1637     callOpcodeSlowPath(_slow_path_strcat)
1638     dispatch(4)
1639
1640
1641 _llint_op_push_with_scope:
1642     traceExecution()
1643     callOpcodeSlowPath(_slow_path_push_with_scope)
1644     dispatch(4)
1645
1646
1647 _llint_op_assert:
1648     traceExecution()
1649     callOpcodeSlowPath(_slow_path_assert)
1650     dispatch(3)
1651
1652
1653 _llint_op_save:
1654     traceExecution()
1655     callOpcodeSlowPath(_slow_path_save)
1656     dispatch(4)
1657
1658
1659 _llint_op_resume:
1660     traceExecution()
1661     callOpcodeSlowPath(_slow_path_resume)
1662     dispatch(3)
1663
1664
1665 _llint_op_create_lexical_environment:
1666     traceExecution()
1667     callOpcodeSlowPath(_slow_path_create_lexical_environment)
1668     dispatch(5)
1669
1670
1671 _llint_op_throw:
1672     traceExecution()
1673     callOpcodeSlowPath(_llint_slow_path_throw)
1674     dispatch(2)
1675
1676
1677 _llint_op_throw_static_error:
1678     traceExecution()
1679     callOpcodeSlowPath(_llint_slow_path_throw_static_error)
1680     dispatch(3)
1681
1682
1683 _llint_op_debug:
1684     traceExecution()
1685     loadp CodeBlock[cfr], t0
1686     loadi CodeBlock::m_debuggerRequests[t0], t0
1687     btiz t0, .opDebugDone
1688     callOpcodeSlowPath(_llint_slow_path_debug)
1689 .opDebugDone:                    
1690     dispatch(3)
1691
1692
1693 _llint_native_call_trampoline:
1694     nativeCallTrampoline(NativeExecutable::m_function)
1695
1696
1697 _llint_native_construct_trampoline:
1698     nativeCallTrampoline(NativeExecutable::m_constructor)
1699
1700 _llint_op_get_enumerable_length:
1701     traceExecution()
1702     callOpcodeSlowPath(_slow_path_get_enumerable_length)
1703     dispatch(3)
1704
1705 _llint_op_has_indexed_property:
1706     traceExecution()
1707     callOpcodeSlowPath(_slow_path_has_indexed_property)
1708     dispatch(5)
1709
1710 _llint_op_has_structure_property:
1711     traceExecution()
1712     callOpcodeSlowPath(_slow_path_has_structure_property)
1713     dispatch(5)
1714
1715 _llint_op_has_generic_property:
1716     traceExecution()
1717     callOpcodeSlowPath(_slow_path_has_generic_property)
1718     dispatch(4)
1719
1720 _llint_op_get_direct_pname:
1721     traceExecution()
1722     callOpcodeSlowPath(_slow_path_get_direct_pname)
1723     dispatch(7)
1724
1725 _llint_op_get_property_enumerator:
1726     traceExecution()
1727     callOpcodeSlowPath(_slow_path_get_property_enumerator)
1728     dispatch(3)
1729
1730 _llint_op_enumerator_structure_pname:
1731     traceExecution()
1732     callOpcodeSlowPath(_slow_path_next_structure_enumerator_pname)
1733     dispatch(4)
1734
1735 _llint_op_enumerator_generic_pname:
1736     traceExecution()
1737     callOpcodeSlowPath(_slow_path_next_generic_enumerator_pname)
1738     dispatch(4)
1739
1740 _llint_op_to_index_string:
1741     traceExecution()
1742     callOpcodeSlowPath(_slow_path_to_index_string)
1743     dispatch(3)
1744
1745 _llint_op_copy_rest:
1746     traceExecution()
1747     callOpcodeSlowPath(_slow_path_copy_rest)
1748     dispatch(4)
1749
1750 _llint_op_instanceof:
1751     traceExecution()
1752     callOpcodeSlowPath(_llint_slow_path_instanceof)
1753     dispatch(4)
1754
1755 _llint_op_get_by_id_with_this:
1756     traceExecution()
1757     callOpcodeSlowPath(_slow_path_get_by_id_with_this)
1758     dispatch(5)
1759
1760 _llint_op_get_by_val_with_this:
1761     traceExecution()
1762     callOpcodeSlowPath(_slow_path_get_by_val_with_this)
1763     dispatch(5)
1764
1765 _llint_op_put_by_id_with_this:
1766     traceExecution()
1767     callOpcodeSlowPath(_slow_path_put_by_id_with_this)
1768     dispatch(5)
1769
1770 _llint_op_put_by_val_with_this:
1771     traceExecution()
1772     callOpcodeSlowPath(_slow_path_put_by_val_with_this)
1773     dispatch(5)
1774
1775 # Lastly, make sure that we can link even though we don't support all opcodes.
1776 # These opcodes should never arise when using LLInt or either JIT. We assert
1777 # as much.
1778
1779 macro notSupported()
1780     if ASSERT_ENABLED
1781         crash()
1782     else
1783         # We should use whatever the smallest possible instruction is, just to
1784         # ensure that there is a gap between instruction labels. If multiple
1785         # smallest instructions exist, we should pick the one that is most
1786         # likely result in execution being halted. Currently that is the break
1787         # instruction on all architectures we're interested in. (Break is int3
1788         # on Intel, which is 1 byte, and bkpt on ARMv7, which is 2 bytes.)
1789         break
1790     end
1791 end