WebAssembly: perform stack checks
[WebKit-https.git] / Source / JavaScriptCore / llint / 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 if JSVALUE64
157     const PtrSize = 8
158     const CallFrameHeaderSlots = 5
159 else
160     const PtrSize = 4
161     const CallFrameHeaderSlots = 4
162     const CallFrameAlignSlots = 1
163 end
164 const SlotSize = 8
165
166 const JSEnvironmentRecord_variables = (sizeof JSEnvironmentRecord + SlotSize - 1) & ~(SlotSize - 1)
167 const DirectArguments_storage = (sizeof DirectArguments + SlotSize - 1) & ~(SlotSize - 1)
168
169 const StackAlignment = 16
170 const StackAlignmentSlots = 2
171 const StackAlignmentMask = StackAlignment - 1
172
173 const CallerFrameAndPCSize = 2 * PtrSize
174
175 const CallerFrame = 0
176 const ReturnPC = CallerFrame + PtrSize
177 const CodeBlock = ReturnPC + PtrSize
178 const Callee = CodeBlock + SlotSize
179 const ArgumentCount = Callee + SlotSize
180 const ThisArgumentOffset = ArgumentCount + SlotSize
181 const FirstArgumentOffset = ThisArgumentOffset + SlotSize
182 const CallFrameHeaderSize = ThisArgumentOffset
183
184 # Some value representation constants.
185 if JSVALUE64
186     const TagBitTypeOther = 0x2
187     const TagBitBool      = 0x4
188     const TagBitUndefined = 0x8
189     const ValueEmpty      = 0x0
190     const ValueFalse      = TagBitTypeOther | TagBitBool
191     const ValueTrue       = TagBitTypeOther | TagBitBool | 1
192     const ValueUndefined  = TagBitTypeOther | TagBitUndefined
193     const ValueNull       = TagBitTypeOther
194     const TagTypeNumber   = 0xffff000000000000
195     const TagMask         = TagTypeNumber | TagBitTypeOther
196 else
197     const Int32Tag = -1
198     const BooleanTag = -2
199     const NullTag = -3
200     const UndefinedTag = -4
201     const CellTag = -5
202     const EmptyValueTag = -6
203     const DeletedValueTag = -7
204     const LowestTag = DeletedValueTag
205 end
206
207 # NOTE: The values below must be in sync with what is in PutByIdFlags.h.
208 const PutByIdPrimaryTypeMask = 0x6
209 const PutByIdPrimaryTypeSecondary = 0x0
210 const PutByIdPrimaryTypeObjectWithStructure = 0x2
211 const PutByIdPrimaryTypeObjectWithStructureOrOther = 0x4
212 const PutByIdSecondaryTypeMask = -0x8
213 const PutByIdSecondaryTypeBottom = 0x0
214 const PutByIdSecondaryTypeBoolean = 0x8
215 const PutByIdSecondaryTypeOther = 0x10
216 const PutByIdSecondaryTypeInt32 = 0x18
217 const PutByIdSecondaryTypeNumber = 0x20
218 const PutByIdSecondaryTypeString = 0x28
219 const PutByIdSecondaryTypeSymbol = 0x30
220 const PutByIdSecondaryTypeObject = 0x38
221 const PutByIdSecondaryTypeObjectOrOther = 0x40
222 const PutByIdSecondaryTypeTop = 0x48
223
224 const CallOpCodeSize = 9
225
226 if X86_64 or ARM64 or C_LOOP
227     const maxFrameExtentForSlowPathCall = 0
228 elsif ARM or ARMv7_TRADITIONAL or ARMv7
229     const maxFrameExtentForSlowPathCall = 24
230 elsif X86 or X86_WIN
231     const maxFrameExtentForSlowPathCall = 40
232 elsif MIPS
233     const maxFrameExtentForSlowPathCall = 40
234 elsif X86_64_WIN
235     const maxFrameExtentForSlowPathCall = 64
236 end
237
238 if X86_64 or X86_64_WIN or ARM64
239     const CalleeSaveSpaceAsVirtualRegisters = 3
240 else
241     const CalleeSaveSpaceAsVirtualRegisters = 0
242 end
243
244 const CalleeSaveSpaceStackAligned = (CalleeSaveSpaceAsVirtualRegisters * SlotSize + StackAlignment - 1) & ~StackAlignmentMask
245
246
247 # Watchpoint states
248 const ClearWatchpoint = 0
249 const IsWatched = 1
250 const IsInvalidated = 2
251
252 # ShadowChicken data
253 const ShadowChickenTailMarker = 0x7a11
254
255 # ArithProfile data
256 const ArithProfileInt = 0x100000
257 const ArithProfileIntInt = 0x120000
258 const ArithProfileNumber = 0x200000
259 const ArithProfileNumberInt = 0x220000
260 const ArithProfileNumberNumber = 0x240000
261 const ArithProfileIntNumber = 0x140000
262
263 # Some register conventions.
264 if JSVALUE64
265     # - Use a pair of registers to represent the PC: one register for the
266     #   base of the bytecodes, and one register for the index.
267     # - The PC base (or PB for short) must be stored in a callee-save register.
268     # - C calls are still given the Instruction* rather than the PC index.
269     #   This requires an add before the call, and a sub after.
270     const PC = t4 # When changing this, make sure LLIntPC is up to date in LLIntPCRanges.h
271     if ARM64
272         const PB = csr7
273         const tagTypeNumber = csr8
274         const tagMask = csr9
275     elsif X86_64
276         const PB = csr2
277         const tagTypeNumber = csr3
278         const tagMask = csr4
279     elsif X86_64_WIN
280         const PB = csr4
281         const tagTypeNumber = csr5
282         const tagMask = csr6
283     elsif C_LOOP
284         const PB = csr0
285         const tagTypeNumber = csr1
286         const tagMask = csr2
287     end
288
289     macro loadisFromInstruction(offset, dest)
290         loadis offset * 8[PB, PC, 8], dest
291     end
292     
293     macro loadpFromInstruction(offset, dest)
294         loadp offset * 8[PB, PC, 8], dest
295     end
296     
297     macro storeisToInstruction(value, offset)
298         storei value, offset * 8[PB, PC, 8]
299     end
300
301     macro storepToInstruction(value, offset)
302         storep value, offset * 8[PB, PC, 8]
303     end
304
305 else
306     const PC = t4 # When changing this, make sure LLIntPC is up to date in LLIntPCRanges.h
307     macro loadisFromInstruction(offset, dest)
308         loadis offset * 4[PC], dest
309     end
310     
311     macro loadpFromInstruction(offset, dest)
312         loadp offset * 4[PC], dest
313     end
314
315     macro storeisToInstruction(value, offset)
316         storei value, offset * 4[PC]
317     end
318 end
319
320 if X86_64_WIN
321     const extraTempReg = t0
322 else
323     const extraTempReg = t5
324 end
325
326 # Constants for reasoning about value representation.
327 if BIG_ENDIAN
328     const TagOffset = 0
329     const PayloadOffset = 4
330 else
331     const TagOffset = 4
332     const PayloadOffset = 0
333 end
334
335 # Constant for reasoning about butterflies.
336 const IsArray                  = 0x01
337 const IndexingShapeMask        = 0x0E
338 const NoIndexingShape          = 0x00
339 const Int32Shape               = 0x04
340 const DoubleShape              = 0x06
341 const ContiguousShape          = 0x08
342 const ArrayStorageShape        = 0x0A
343 const SlowPutArrayStorageShape = 0x0C
344
345 # Type constants.
346 const StringType = 6
347 const SymbolType = 7
348 const ObjectType = 23
349 const FinalObjectType = 24
350 const JSFunctionType = 26
351 const ArrayType = 34
352 const DerivedArrayType = 35
353 const ProxyObjectType = 53
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 = 36
358 const Int16ArrayType = 37
359 const Int32ArrayType = 38
360 const Uint8ArrayType = 39
361 const Uint8ClampedArrayType = 40
362 const Uint16ArrayType = 41
363 const Uint32ArrayType = 42
364 const Float32ArrayType = 43
365 const Float64ArrayType = 44
366
367 const FirstArrayType = Int8ArrayType
368 const LastArrayType = Float64ArrayType
369
370 # Type flags constants.
371 const MasqueradesAsUndefined = 1
372 const ImplementsDefaultHasInstance = 2
373
374 # Bytecode operand constants.
375 const FirstConstantRegisterIndex = 0x40000000
376
377 # Code type constants.
378 const GlobalCode = 0
379 const EvalCode = 1
380 const FunctionCode = 2
381 const ModuleCode = 3
382
383 # The interpreter steals the tag word of the argument count.
384 const LLIntReturnPC = ArgumentCount + TagOffset
385
386 # String flags.
387 const HashFlags8BitBuffer = 8
388
389 # Copied from PropertyOffset.h
390 const firstOutOfLineOffset = 100
391
392 # ResolveType
393 const GlobalProperty = 0
394 const GlobalVar = 1
395 const GlobalLexicalVar = 2
396 const ClosureVar = 3
397 const LocalClosureVar = 4
398 const ModuleVar = 5
399 const GlobalPropertyWithVarInjectionChecks = 6
400 const GlobalVarWithVarInjectionChecks = 7
401 const GlobalLexicalVarWithVarInjectionChecks = 8
402 const ClosureVarWithVarInjectionChecks = 9
403
404 const ResolveTypeMask = 0x3ff
405 const InitializationModeMask = 0xffc00
406 const InitializationModeShift = 10
407 const NotInitialization = 2
408
409 const MarkedBlockSize = 16 * 1024
410 const MarkedBlockMask = ~(MarkedBlockSize - 1)
411
412 const BlackThreshold = 0
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     loadp CodeBlock::m_vm[t1], t2
998     if C_LOOP
999         bpbeq VM::m_cloopStackLimit[t2], t0, .stackHeightOK
1000     else
1001         bpbeq VM::m_softStackLimit[t2], t0, .stackHeightOK
1002     end
1003
1004     # Stack height check failed - need to call a slow_path.
1005     # Set up temporary stack pointer for call including callee saves
1006     subp maxFrameExtentForSlowPathCall, sp
1007     callSlowPath(_llint_stack_check)
1008     bpeq r1, 0, .stackHeightOKGetCodeBlock
1009     move r1, cfr
1010     dispatch(0) # Go to exception handler in PC
1011
1012 .stackHeightOKGetCodeBlock:
1013     # Stack check slow path returned that the stack was ok.
1014     # Since they were clobbered, need to get CodeBlock and new sp
1015     codeBlockGetter(t1)
1016     getFrameRegisterSizeForCodeBlock(t1, t0)
1017     subp cfr, t0, t0
1018
1019 .stackHeightOK:
1020     move t0, sp
1021
1022     if JSVALUE64
1023         move TagTypeNumber, tagTypeNumber
1024         addp TagBitTypeOther, tagTypeNumber, tagMask
1025     end
1026 end
1027
1028 # Expects that CodeBlock is in t1, which is what prologue() leaves behind.
1029 # Must call dispatch(0) after calling this.
1030 macro functionInitialization(profileArgSkip)
1031     # Profile the arguments. Unfortunately, we have no choice but to do this. This
1032     # code is pretty horrendous because of the difference in ordering between
1033     # arguments and value profiles, the desire to have a simple loop-down-to-zero
1034     # loop, and the desire to use only three registers so as to preserve the PC and
1035     # the code block. It is likely that this code should be rewritten in a more
1036     # optimal way for architectures that have more than five registers available
1037     # for arbitrary use in the interpreter.
1038     loadi CodeBlock::m_numParameters[t1], t0
1039     addp -profileArgSkip, t0 # Use addi because that's what has the peephole
1040     assert(macro (ok) bpgteq t0, 0, ok end)
1041     btpz t0, .argumentProfileDone
1042     loadp CodeBlock::m_argumentValueProfiles + VectorBufferOffset[t1], t3
1043     mulp sizeof ValueProfile, t0, t2 # Aaaaahhhh! Need strength reduction!
1044     lshiftp 3, t0
1045     addp t2, t3
1046 .argumentProfileLoop:
1047     if JSVALUE64
1048         loadq ThisArgumentOffset - 8 + profileArgSkip * 8[cfr, t0], t2
1049         subp sizeof ValueProfile, t3
1050         storeq t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets[t3]
1051     else
1052         loadi ThisArgumentOffset + TagOffset - 8 + profileArgSkip * 8[cfr, t0], t2
1053         subp sizeof ValueProfile, t3
1054         storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + TagOffset[t3]
1055         loadi ThisArgumentOffset + PayloadOffset - 8 + profileArgSkip * 8[cfr, t0], t2
1056         storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + PayloadOffset[t3]
1057     end
1058     baddpnz -8, t0, .argumentProfileLoop
1059 .argumentProfileDone:
1060 end
1061
1062 macro doReturn()
1063     restoreCalleeSavesUsedByLLInt()
1064     restoreCallerPCAndCFR()
1065     ret
1066 end
1067
1068 # stub to call into JavaScript or Native functions
1069 # EncodedJSValue vmEntryToJavaScript(void* code, VM* vm, ProtoCallFrame* protoFrame)
1070 # EncodedJSValue vmEntryToNativeFunction(void* code, VM* vm, ProtoCallFrame* protoFrame)
1071
1072 if C_LOOP
1073     _llint_vm_entry_to_javascript:
1074 else
1075     global _vmEntryToJavaScript
1076     _vmEntryToJavaScript:
1077 end
1078     doVMEntry(makeJavaScriptCall)
1079
1080
1081 if C_LOOP
1082     _llint_vm_entry_to_native:
1083 else
1084     global _vmEntryToNative
1085     _vmEntryToNative:
1086 end
1087     doVMEntry(makeHostFunctionCall)
1088
1089
1090 if not C_LOOP
1091     # void sanitizeStackForVMImpl(VM* vm)
1092     global _sanitizeStackForVMImpl
1093     _sanitizeStackForVMImpl:
1094         # We need three non-aliased caller-save registers. We are guaranteed
1095         # this for a0, a1 and a2 on all architectures.
1096         if X86 or X86_WIN
1097             loadp 4[sp], a0
1098         end
1099         const vm = a0
1100         const address = a1
1101         const zeroValue = a2
1102     
1103         loadp VM::m_lastStackTop[vm], address
1104         bpbeq sp, address, .zeroFillDone
1105     
1106         move 0, zeroValue
1107     .zeroFillLoop:
1108         storep zeroValue, [address]
1109         addp PtrSize, address
1110         bpa sp, address, .zeroFillLoop
1111     
1112     .zeroFillDone:
1113         move sp, address
1114         storep address, VM::m_lastStackTop[vm]
1115         ret
1116     
1117     # VMEntryRecord* vmEntryRecord(const VMEntryFrame* entryFrame)
1118     global _vmEntryRecord
1119     _vmEntryRecord:
1120         if X86 or X86_WIN
1121             loadp 4[sp], a0
1122         end
1123
1124         vmEntryRecord(a0, r0)
1125         ret
1126 end
1127
1128 if C_LOOP
1129     # Dummy entry point the C Loop uses to initialize.
1130     _llint_entry:
1131         crash()
1132 else
1133     macro initPCRelative(pcBase)
1134         if X86_64 or X86_64_WIN or X86 or X86_WIN
1135             call _relativePCBase
1136         _relativePCBase:
1137             pop pcBase
1138         elsif ARM64
1139         elsif ARMv7
1140         _relativePCBase:
1141             move pc, pcBase
1142             subp 3, pcBase   # Need to back up the PC and set the Thumb2 bit
1143         elsif ARM or ARMv7_TRADITIONAL
1144         _relativePCBase:
1145             move pc, pcBase
1146             subp 8, pcBase
1147         elsif MIPS
1148             la _relativePCBase, pcBase
1149             setcallreg pcBase # needed to set $t9 to the right value for the .cpload created by the label.
1150         _relativePCBase:
1151         end
1152 end
1153
1154 # The PC base is in t1, as this is what _llint_entry leaves behind through
1155 # initPCRelative(t1)
1156 macro setEntryAddress(index, label)
1157     if X86_64 or X86_64_WIN
1158         leap (label - _relativePCBase)[t1], t3
1159         move index, t4
1160         storep t3, [a0, t4, 8]
1161     elsif X86 or X86_WIN
1162         leap (label - _relativePCBase)[t1], t3
1163         move index, t4
1164         storep t3, [a0, t4, 4]
1165     elsif ARM64
1166         pcrtoaddr label, t1
1167         move index, t4
1168         storep t1, [a0, t4, 8]
1169     elsif ARM or ARMv7 or ARMv7_TRADITIONAL
1170         mvlbl (label - _relativePCBase), t4
1171         addp t4, t1, t4
1172         move index, t3
1173         storep t4, [a0, t3, 4]
1174     elsif MIPS
1175         la label, t4
1176         la _relativePCBase, t3
1177         subp t3, t4
1178         addp t4, t1, t4
1179         move index, t3
1180         storep t4, [a0, t3, 4]
1181     end
1182 end
1183
1184 global _llint_entry
1185 # Entry point for the llint to initialize.
1186 _llint_entry:
1187     functionPrologue()
1188     pushCalleeSaves()
1189     if X86 or X86_WIN
1190         loadp 20[sp], a0
1191     end
1192     initPCRelative(t1)
1193
1194     # Include generated bytecode initialization file.
1195     include InitBytecodes
1196
1197     popCalleeSaves()
1198     functionEpilogue()
1199     ret
1200 end
1201
1202 _llint_program_prologue:
1203     prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
1204     dispatch(0)
1205
1206
1207 _llint_module_program_prologue:
1208     prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
1209     dispatch(0)
1210
1211
1212 _llint_eval_prologue:
1213     prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
1214     dispatch(0)
1215
1216
1217 _llint_function_for_call_prologue:
1218     prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call, _llint_trace_prologue_function_for_call)
1219     functionInitialization(0)
1220     dispatch(0)
1221     
1222
1223 _llint_function_for_construct_prologue:
1224     prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct, _llint_trace_prologue_function_for_construct)
1225     functionInitialization(1)
1226     dispatch(0)
1227     
1228
1229 _llint_function_for_call_arity_check:
1230     prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call_arityCheck, _llint_trace_arityCheck_for_call)
1231     functionArityCheck(.functionForCallBegin, _slow_path_call_arityCheck)
1232 .functionForCallBegin:
1233     functionInitialization(0)
1234     dispatch(0)
1235
1236
1237 _llint_function_for_construct_arity_check:
1238     prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct_arityCheck, _llint_trace_arityCheck_for_construct)
1239     functionArityCheck(.functionForConstructBegin, _slow_path_construct_arityCheck)
1240 .functionForConstructBegin:
1241     functionInitialization(1)
1242     dispatch(0)
1243
1244
1245 # Value-representation-specific code.
1246 if JSVALUE64
1247     include LowLevelInterpreter64
1248 else
1249     include LowLevelInterpreter32_64
1250 end
1251
1252
1253 # Value-representation-agnostic code.
1254 _llint_op_create_direct_arguments:
1255     traceExecution()
1256     callOpcodeSlowPath(_slow_path_create_direct_arguments)
1257     dispatch(2)
1258
1259
1260 _llint_op_create_scoped_arguments:
1261     traceExecution()
1262     callOpcodeSlowPath(_slow_path_create_scoped_arguments)
1263     dispatch(3)
1264
1265
1266 _llint_op_create_cloned_arguments:
1267     traceExecution()
1268     callOpcodeSlowPath(_slow_path_create_cloned_arguments)
1269     dispatch(2)
1270
1271
1272 _llint_op_create_this:
1273     traceExecution()
1274     callOpcodeSlowPath(_slow_path_create_this)
1275     dispatch(5)
1276
1277
1278 _llint_op_new_object:
1279     traceExecution()
1280     callOpcodeSlowPath(_llint_slow_path_new_object)
1281     dispatch(4)
1282
1283
1284 _llint_op_new_func:
1285     traceExecution()
1286     callOpcodeSlowPath(_llint_slow_path_new_func)
1287     dispatch(4)
1288
1289
1290 _llint_op_new_generator_func:
1291     traceExecution()
1292     callOpcodeSlowPath(_llint_slow_path_new_generator_func)
1293     dispatch(4)
1294
1295
1296 _llint_op_new_async_func:
1297     traceExecution()
1298     callSlowPath(_llint_slow_path_new_async_func)
1299     dispatch(4)
1300
1301
1302 _llint_op_new_array:
1303     traceExecution()
1304     callOpcodeSlowPath(_llint_slow_path_new_array)
1305     dispatch(5)
1306
1307
1308 _llint_op_new_array_with_spread:
1309     traceExecution()
1310     callOpcodeSlowPath(_slow_path_new_array_with_spread)
1311     dispatch(5)
1312
1313
1314 _llint_op_spread:
1315     traceExecution()
1316     callOpcodeSlowPath(_slow_path_spread)
1317     dispatch(3)
1318
1319
1320 _llint_op_new_array_with_size:
1321     traceExecution()
1322     callOpcodeSlowPath(_llint_slow_path_new_array_with_size)
1323     dispatch(4)
1324
1325
1326 _llint_op_new_array_buffer:
1327     traceExecution()
1328     callOpcodeSlowPath(_llint_slow_path_new_array_buffer)
1329     dispatch(5)
1330
1331
1332 _llint_op_new_regexp:
1333     traceExecution()
1334     callOpcodeSlowPath(_llint_slow_path_new_regexp)
1335     dispatch(3)
1336
1337
1338 _llint_op_less:
1339     traceExecution()
1340     callOpcodeSlowPath(_slow_path_less)
1341     dispatch(4)
1342
1343
1344 _llint_op_lesseq:
1345     traceExecution()
1346     callOpcodeSlowPath(_slow_path_lesseq)
1347     dispatch(4)
1348
1349
1350 _llint_op_greater:
1351     traceExecution()
1352     callOpcodeSlowPath(_slow_path_greater)
1353     dispatch(4)
1354
1355
1356 _llint_op_greatereq:
1357     traceExecution()
1358     callOpcodeSlowPath(_slow_path_greatereq)
1359     dispatch(4)
1360
1361
1362 _llint_op_mod:
1363     traceExecution()
1364     callOpcodeSlowPath(_slow_path_mod)
1365     dispatch(4)
1366
1367
1368 _llint_op_pow:
1369     traceExecution()
1370     callOpcodeSlowPath(_slow_path_pow)
1371     dispatch(4)
1372
1373
1374 _llint_op_typeof:
1375     traceExecution()
1376     callOpcodeSlowPath(_slow_path_typeof)
1377     dispatch(3)
1378
1379
1380 _llint_op_is_object_or_null:
1381     traceExecution()
1382     callOpcodeSlowPath(_slow_path_is_object_or_null)
1383     dispatch(3)
1384
1385 _llint_op_is_function:
1386     traceExecution()
1387     callOpcodeSlowPath(_slow_path_is_function)
1388     dispatch(3)
1389
1390
1391 _llint_op_in:
1392     traceExecution()
1393     callOpcodeSlowPath(_slow_path_in)
1394     dispatch(5)
1395
1396
1397 _llint_op_try_get_by_id:
1398     traceExecution()
1399     callOpcodeSlowPath(_llint_slow_path_try_get_by_id)
1400     dispatch(5)
1401
1402
1403 _llint_op_del_by_id:
1404     traceExecution()
1405     callOpcodeSlowPath(_llint_slow_path_del_by_id)
1406     dispatch(4)
1407
1408
1409 _llint_op_del_by_val:
1410     traceExecution()
1411     callOpcodeSlowPath(_llint_slow_path_del_by_val)
1412     dispatch(4)
1413
1414
1415 _llint_op_put_by_index:
1416     traceExecution()
1417     callOpcodeSlowPath(_llint_slow_path_put_by_index)
1418     dispatch(4)
1419
1420
1421 _llint_op_put_getter_by_id:
1422     traceExecution()
1423     callOpcodeSlowPath(_llint_slow_path_put_getter_by_id)
1424     dispatch(5)
1425
1426
1427 _llint_op_put_setter_by_id:
1428     traceExecution()
1429     callOpcodeSlowPath(_llint_slow_path_put_setter_by_id)
1430     dispatch(5)
1431
1432
1433 _llint_op_put_getter_setter_by_id:
1434     traceExecution()
1435     callOpcodeSlowPath(_llint_slow_path_put_getter_setter_by_id)
1436     dispatch(6)
1437
1438
1439 _llint_op_put_getter_by_val:
1440     traceExecution()
1441     callOpcodeSlowPath(_llint_slow_path_put_getter_by_val)
1442     dispatch(5)
1443
1444
1445 _llint_op_put_setter_by_val:
1446     traceExecution()
1447     callOpcodeSlowPath(_llint_slow_path_put_setter_by_val)
1448     dispatch(5)
1449
1450
1451 _llint_op_define_data_property:
1452     traceExecution()
1453     callOpcodeSlowPath(_slow_path_define_data_property)
1454     dispatch(5)
1455
1456
1457 _llint_op_define_accessor_property:
1458     traceExecution()
1459     callOpcodeSlowPath(_slow_path_define_accessor_property)
1460     dispatch(6)
1461
1462
1463 _llint_op_jtrue:
1464     traceExecution()
1465     jumpTrueOrFalse(
1466         macro (value, target) btinz value, target end,
1467         _llint_slow_path_jtrue)
1468
1469
1470 _llint_op_jfalse:
1471     traceExecution()
1472     jumpTrueOrFalse(
1473         macro (value, target) btiz value, target end,
1474         _llint_slow_path_jfalse)
1475
1476
1477 _llint_op_jless:
1478     traceExecution()
1479     compare(
1480         macro (left, right, target) bilt left, right, target end,
1481         macro (left, right, target) bdlt left, right, target end,
1482         _llint_slow_path_jless)
1483
1484
1485 _llint_op_jnless:
1486     traceExecution()
1487     compare(
1488         macro (left, right, target) bigteq left, right, target end,
1489         macro (left, right, target) bdgtequn left, right, target end,
1490         _llint_slow_path_jnless)
1491
1492
1493 _llint_op_jgreater:
1494     traceExecution()
1495     compare(
1496         macro (left, right, target) bigt left, right, target end,
1497         macro (left, right, target) bdgt left, right, target end,
1498         _llint_slow_path_jgreater)
1499
1500
1501 _llint_op_jngreater:
1502     traceExecution()
1503     compare(
1504         macro (left, right, target) bilteq left, right, target end,
1505         macro (left, right, target) bdltequn left, right, target end,
1506         _llint_slow_path_jngreater)
1507
1508
1509 _llint_op_jlesseq:
1510     traceExecution()
1511     compare(
1512         macro (left, right, target) bilteq left, right, target end,
1513         macro (left, right, target) bdlteq left, right, target end,
1514         _llint_slow_path_jlesseq)
1515
1516
1517 _llint_op_jnlesseq:
1518     traceExecution()
1519     compare(
1520         macro (left, right, target) bigt left, right, target end,
1521         macro (left, right, target) bdgtun left, right, target end,
1522         _llint_slow_path_jnlesseq)
1523
1524
1525 _llint_op_jgreatereq:
1526     traceExecution()
1527     compare(
1528         macro (left, right, target) bigteq left, right, target end,
1529         macro (left, right, target) bdgteq left, right, target end,
1530         _llint_slow_path_jgreatereq)
1531
1532
1533 _llint_op_jngreatereq:
1534     traceExecution()
1535     compare(
1536         macro (left, right, target) bilt left, right, target end,
1537         macro (left, right, target) bdltun left, right, target end,
1538         _llint_slow_path_jngreatereq)
1539
1540
1541 _llint_op_loop_hint:
1542     traceExecution()
1543     checkSwitchToJITForLoop()
1544     dispatch(1)
1545
1546
1547 _llint_op_check_traps:
1548     traceExecution()
1549     loadp CodeBlock[cfr], t1
1550     loadp CodeBlock::m_vm[t1], t1
1551     loadb VM::m_traps+VMTraps::m_needTrapHandling[t1], t0
1552     btpnz t0, .handleTraps
1553 .afterHandlingTraps:
1554     dispatch(1)
1555 .handleTraps:
1556     callTrapHandler(.throwHandler)
1557     jmp .afterHandlingTraps
1558 .throwHandler:
1559     jmp _llint_throw_from_slow_path_trampoline
1560
1561
1562 # Returns the packet pointer in t0.
1563 macro acquireShadowChickenPacket(slow)
1564     loadp CodeBlock[cfr], t1
1565     loadp CodeBlock::m_vm[t1], t1
1566     loadp VM::m_shadowChicken[t1], t2
1567     loadp ShadowChicken::m_logCursor[t2], t0
1568     bpaeq t0, ShadowChicken::m_logEnd[t2], slow
1569     addp sizeof ShadowChicken::Packet, t0, t1
1570     storep t1, ShadowChicken::m_logCursor[t2]
1571 end
1572
1573
1574 _llint_op_switch_string:
1575     traceExecution()
1576     callOpcodeSlowPath(_llint_slow_path_switch_string)
1577     dispatch(0)
1578
1579
1580 _llint_op_new_func_exp:
1581     traceExecution()
1582     callOpcodeSlowPath(_llint_slow_path_new_func_exp)
1583     dispatch(4)
1584
1585 _llint_op_new_generator_func_exp:
1586     traceExecution()
1587     callOpcodeSlowPath(_llint_slow_path_new_generator_func_exp)
1588     dispatch(4)
1589
1590 _llint_op_new_async_func_exp:
1591     traceExecution()
1592     callSlowPath(_llint_slow_path_new_async_func_exp)
1593     dispatch(4)
1594
1595
1596 _llint_op_set_function_name:
1597     traceExecution()
1598     callOpcodeSlowPath(_llint_slow_path_set_function_name)
1599     dispatch(3)
1600
1601 _llint_op_call:
1602     traceExecution()
1603     arrayProfileForCall()
1604     doCall(_llint_slow_path_call, prepareForRegularCall)
1605
1606 _llint_op_tail_call:
1607     traceExecution()
1608     arrayProfileForCall()
1609     checkSwitchToJITForEpilogue()
1610     doCall(_llint_slow_path_call, prepareForTailCall)
1611
1612 _llint_op_construct:
1613     traceExecution()
1614     doCall(_llint_slow_path_construct, prepareForRegularCall)
1615
1616 macro doCallVarargs(frameSlowPath, slowPath, prepareCall)
1617     callOpcodeSlowPath(frameSlowPath)
1618     branchIfException(_llint_throw_from_slow_path_trampoline)
1619     # calleeFrame in r1
1620     if JSVALUE64
1621         move r1, sp
1622     else
1623         # The calleeFrame is not stack aligned, move down by CallerFrameAndPCSize to align
1624         if ARMv7
1625             subp r1, CallerFrameAndPCSize, t2
1626             move t2, sp
1627         else
1628             subp r1, CallerFrameAndPCSize, sp
1629         end
1630     end
1631     slowPathForCall(slowPath, prepareCall)
1632 end
1633
1634 _llint_op_call_varargs:
1635     traceExecution()
1636     doCallVarargs(_llint_slow_path_size_frame_for_varargs, _llint_slow_path_call_varargs, prepareForRegularCall)
1637
1638 _llint_op_tail_call_varargs:
1639     traceExecution()
1640     checkSwitchToJITForEpilogue()
1641     # We lie and perform the tail call instead of preparing it since we can't
1642     # prepare the frame for a call opcode
1643     doCallVarargs(_llint_slow_path_size_frame_for_varargs, _llint_slow_path_call_varargs, prepareForTailCall)
1644
1645
1646 _llint_op_tail_call_forward_arguments:
1647     traceExecution()
1648     checkSwitchToJITForEpilogue()
1649     # We lie and perform the tail call instead of preparing it since we can't
1650     # prepare the frame for a call opcode
1651     doCallVarargs(_llint_slow_path_size_frame_for_forward_arguments, _llint_slow_path_tail_call_forward_arguments, prepareForTailCall)
1652
1653
1654 _llint_op_construct_varargs:
1655     traceExecution()
1656     doCallVarargs(_llint_slow_path_size_frame_for_varargs, _llint_slow_path_construct_varargs, prepareForRegularCall)
1657
1658
1659 _llint_op_call_eval:
1660     traceExecution()
1661     
1662     # Eval is executed in one of two modes:
1663     #
1664     # 1) We find that we're really invoking eval() in which case the
1665     #    execution is perfomed entirely inside the slow_path, and it
1666     #    returns the PC of a function that just returns the return value
1667     #    that the eval returned.
1668     #
1669     # 2) We find that we're invoking something called eval() that is not
1670     #    the real eval. Then the slow_path returns the PC of the thing to
1671     #    call, and we call it.
1672     #
1673     # This allows us to handle two cases, which would require a total of
1674     # up to four pieces of state that cannot be easily packed into two
1675     # registers (C functions can return up to two registers, easily):
1676     #
1677     # - The call frame register. This may or may not have been modified
1678     #   by the slow_path, but the convention is that it returns it. It's not
1679     #   totally clear if that's necessary, since the cfr is callee save.
1680     #   But that's our style in this here interpreter so we stick with it.
1681     #
1682     # - A bit to say if the slow_path successfully executed the eval and has
1683     #   the return value, or did not execute the eval but has a PC for us
1684     #   to call.
1685     #
1686     # - Either:
1687     #   - The JS return value (two registers), or
1688     #
1689     #   - The PC to call.
1690     #
1691     # It turns out to be easier to just always have this return the cfr
1692     # and a PC to call, and that PC may be a dummy thunk that just
1693     # returns the JS value that the eval returned.
1694     
1695     slowPathForCall(_llint_slow_path_call_eval, prepareForRegularCall)
1696
1697
1698 _llint_generic_return_point:
1699     dispatchAfterCall()
1700
1701
1702 _llint_op_strcat:
1703     traceExecution()
1704     callOpcodeSlowPath(_slow_path_strcat)
1705     dispatch(4)
1706
1707
1708 _llint_op_push_with_scope:
1709     traceExecution()
1710     callOpcodeSlowPath(_slow_path_push_with_scope)
1711     dispatch(4)
1712
1713
1714 _llint_op_assert:
1715     traceExecution()
1716     callOpcodeSlowPath(_slow_path_assert)
1717     dispatch(3)
1718
1719
1720 _llint_op_yield:
1721     notSupported()
1722
1723
1724 _llint_op_create_lexical_environment:
1725     traceExecution()
1726     callOpcodeSlowPath(_slow_path_create_lexical_environment)
1727     dispatch(5)
1728
1729
1730 _llint_op_throw:
1731     traceExecution()
1732     callOpcodeSlowPath(_llint_slow_path_throw)
1733     dispatch(2)
1734
1735
1736 _llint_op_throw_static_error:
1737     traceExecution()
1738     callOpcodeSlowPath(_slow_path_throw_static_error)
1739     dispatch(3)
1740
1741
1742 _llint_op_debug:
1743     traceExecution()
1744     loadp CodeBlock[cfr], t0
1745     loadi CodeBlock::m_debuggerRequests[t0], t0
1746     btiz t0, .opDebugDone
1747     callOpcodeSlowPath(_llint_slow_path_debug)
1748 .opDebugDone:                    
1749     dispatch(3)
1750
1751
1752 _llint_native_call_trampoline:
1753     nativeCallTrampoline(NativeExecutable::m_function)
1754
1755
1756 _llint_native_construct_trampoline:
1757     nativeCallTrampoline(NativeExecutable::m_constructor)
1758
1759 _llint_op_get_enumerable_length:
1760     traceExecution()
1761     callOpcodeSlowPath(_slow_path_get_enumerable_length)
1762     dispatch(3)
1763
1764 _llint_op_has_indexed_property:
1765     traceExecution()
1766     callOpcodeSlowPath(_slow_path_has_indexed_property)
1767     dispatch(5)
1768
1769 _llint_op_has_structure_property:
1770     traceExecution()
1771     callOpcodeSlowPath(_slow_path_has_structure_property)
1772     dispatch(5)
1773
1774 _llint_op_has_generic_property:
1775     traceExecution()
1776     callOpcodeSlowPath(_slow_path_has_generic_property)
1777     dispatch(4)
1778
1779 _llint_op_get_direct_pname:
1780     traceExecution()
1781     callOpcodeSlowPath(_slow_path_get_direct_pname)
1782     dispatch(7)
1783
1784 _llint_op_get_property_enumerator:
1785     traceExecution()
1786     callOpcodeSlowPath(_slow_path_get_property_enumerator)
1787     dispatch(3)
1788
1789 _llint_op_enumerator_structure_pname:
1790     traceExecution()
1791     callOpcodeSlowPath(_slow_path_next_structure_enumerator_pname)
1792     dispatch(4)
1793
1794 _llint_op_enumerator_generic_pname:
1795     traceExecution()
1796     callOpcodeSlowPath(_slow_path_next_generic_enumerator_pname)
1797     dispatch(4)
1798
1799 _llint_op_to_index_string:
1800     traceExecution()
1801     callOpcodeSlowPath(_slow_path_to_index_string)
1802     dispatch(3)
1803
1804 _llint_op_create_rest:
1805     traceExecution()
1806     callOpcodeSlowPath(_slow_path_create_rest)
1807     dispatch(4)
1808
1809 _llint_op_instanceof:
1810     traceExecution()
1811     callOpcodeSlowPath(_llint_slow_path_instanceof)
1812     dispatch(4)
1813
1814 _llint_op_get_by_id_with_this:
1815     traceExecution()
1816     callOpcodeSlowPath(_slow_path_get_by_id_with_this)
1817     dispatch(6)
1818
1819 _llint_op_get_by_val_with_this:
1820     traceExecution()
1821     callOpcodeSlowPath(_slow_path_get_by_val_with_this)
1822     dispatch(6)
1823
1824 _llint_op_put_by_id_with_this:
1825     traceExecution()
1826     callOpcodeSlowPath(_slow_path_put_by_id_with_this)
1827     dispatch(5)
1828
1829 _llint_op_put_by_val_with_this:
1830     traceExecution()
1831     callOpcodeSlowPath(_slow_path_put_by_val_with_this)
1832     dispatch(5)
1833
1834 _llint_op_resolve_scope_for_hoisting_func_decl_in_eval:
1835     traceExecution()
1836     callOpcodeSlowPath(_slow_path_resolve_scope_for_hoisting_func_decl_in_eval)
1837     dispatch(4)
1838
1839 # Lastly, make sure that we can link even though we don't support all opcodes.
1840 # These opcodes should never arise when using LLInt or either JIT. We assert
1841 # as much.
1842
1843 macro notSupported()
1844     if ASSERT_ENABLED
1845         crash()
1846     else
1847         # We should use whatever the smallest possible instruction is, just to
1848         # ensure that there is a gap between instruction labels. If multiple
1849         # smallest instructions exist, we should pick the one that is most
1850         # likely result in execution being halted. Currently that is the break
1851         # instruction on all architectures we're interested in. (Break is int3
1852         # on Intel, which is 1 byte, and bkpt on ARMv7, which is 2 bytes.)
1853         break
1854     end
1855 end