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