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