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