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