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