Consider removing double load for accessing the instructions from LLInt
[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 const MachineRegisterSize = constexpr (sizeof(CPURegister))
158 const SlotSize = constexpr (sizeof(Register))
159
160 if JSVALUE64
161     const CallFrameHeaderSlots = 5
162 else
163     const CallFrameHeaderSlots = 4
164     const CallFrameAlignSlots = 1
165 end
166
167 const JSLexicalEnvironment_variables = (sizeof JSLexicalEnvironment + SlotSize - 1) & ~(SlotSize - 1)
168 const DirectArguments_storage = (sizeof DirectArguments + SlotSize - 1) & ~(SlotSize - 1)
169
170 const StackAlignment = constexpr (stackAlignmentBytes())
171 const StackAlignmentSlots = constexpr (stackAlignmentRegisters())
172 const StackAlignmentMask = StackAlignment - 1
173
174 const CallerFrameAndPCSize = constexpr (sizeof(CallerFrameAndPC))
175
176 const CallerFrame = 0
177 const ReturnPC = CallerFrame + MachineRegisterSize
178 const CodeBlock = ReturnPC + MachineRegisterSize
179 const Callee = CodeBlock + SlotSize
180 const ArgumentCount = Callee + SlotSize
181 const ThisArgumentOffset = ArgumentCount + SlotSize
182 const FirstArgumentOffset = ThisArgumentOffset + SlotSize
183 const CallFrameHeaderSize = ThisArgumentOffset
184
185 # Some value representation constants.
186 if JSVALUE64
187     const TagBitTypeOther = constexpr TagBitTypeOther
188     const TagBitBool      = constexpr TagBitBool
189     const TagBitUndefined = constexpr TagBitUndefined
190     const ValueEmpty      = constexpr ValueEmpty
191     const ValueFalse      = constexpr ValueFalse
192     const ValueTrue       = constexpr ValueTrue
193     const ValueUndefined  = constexpr ValueUndefined
194     const ValueNull       = constexpr ValueNull
195     const TagTypeNumber   = constexpr TagTypeNumber
196     const TagMask         = constexpr TagMask
197 else
198     const Int32Tag = constexpr JSValue::Int32Tag
199     const BooleanTag = constexpr JSValue::BooleanTag
200     const NullTag = constexpr JSValue::NullTag
201     const UndefinedTag = constexpr JSValue::UndefinedTag
202     const CellTag = constexpr JSValue::CellTag
203     const EmptyValueTag = constexpr JSValue::EmptyValueTag
204     const DeletedValueTag = constexpr JSValue::DeletedValueTag
205     const LowestTag = constexpr JSValue::LowestTag
206 end
207
208 # PutByIdFlags data
209 const PutByIdPrimaryTypeMask = constexpr PutByIdPrimaryTypeMask
210 const PutByIdPrimaryTypeSecondary = constexpr PutByIdPrimaryTypeSecondary
211 const PutByIdPrimaryTypeObjectWithStructure = constexpr PutByIdPrimaryTypeObjectWithStructure
212 const PutByIdPrimaryTypeObjectWithStructureOrOther = constexpr PutByIdPrimaryTypeObjectWithStructureOrOther
213 const PutByIdSecondaryTypeMask = constexpr PutByIdSecondaryTypeMask
214 const PutByIdSecondaryTypeBottom = constexpr PutByIdSecondaryTypeBottom
215 const PutByIdSecondaryTypeBoolean = constexpr PutByIdSecondaryTypeBoolean
216 const PutByIdSecondaryTypeOther = constexpr PutByIdSecondaryTypeOther
217 const PutByIdSecondaryTypeInt32 = constexpr PutByIdSecondaryTypeInt32
218 const PutByIdSecondaryTypeNumber = constexpr PutByIdSecondaryTypeNumber
219 const PutByIdSecondaryTypeString = constexpr PutByIdSecondaryTypeString
220 const PutByIdSecondaryTypeSymbol = constexpr PutByIdSecondaryTypeSymbol
221 const PutByIdSecondaryTypeObject = constexpr PutByIdSecondaryTypeObject
222 const PutByIdSecondaryTypeObjectOrOther = constexpr PutByIdSecondaryTypeObjectOrOther
223 const PutByIdSecondaryTypeTop = constexpr PutByIdSecondaryTypeTop
224
225 const CallOpCodeSize = constexpr op_call_length
226
227 const maxFrameExtentForSlowPathCall = constexpr maxFrameExtentForSlowPathCall
228
229 if X86_64 or X86_64_WIN or ARM64 or ARM64E
230     const CalleeSaveSpaceAsVirtualRegisters = 4
231 elsif C_LOOP
232     const CalleeSaveSpaceAsVirtualRegisters = 1
233 elsif ARMv7
234     const CalleeSaveSpaceAsVirtualRegisters = 1
235 else
236     const CalleeSaveSpaceAsVirtualRegisters = 0
237 end
238
239 const CalleeSaveSpaceStackAligned = (CalleeSaveSpaceAsVirtualRegisters * SlotSize + StackAlignment - 1) & ~StackAlignmentMask
240
241
242 # Watchpoint states
243 const ClearWatchpoint = constexpr ClearWatchpoint
244 const IsWatched = constexpr IsWatched
245 const IsInvalidated = constexpr IsInvalidated
246
247 # ShadowChicken data
248 const ShadowChickenTailMarker = constexpr ShadowChicken::Packet::tailMarkerValue
249
250 # ArithProfile data
251 const ArithProfileInt = constexpr (ArithProfile::observedUnaryInt().bits())
252 const ArithProfileNumber = constexpr (ArithProfile::observedUnaryNumber().bits())
253 const ArithProfileIntInt = constexpr (ArithProfile::observedBinaryIntInt().bits())
254 const ArithProfileNumberInt = constexpr (ArithProfile::observedBinaryNumberInt().bits())
255 const ArithProfileIntNumber = constexpr (ArithProfile::observedBinaryIntNumber().bits())
256 const ArithProfileNumberNumber = constexpr (ArithProfile::observedBinaryNumberNumber().bits())
257
258 # Pointer Tags
259 const BytecodePtrTag = constexpr BytecodePtrTag
260 const JSEntryPtrTag = constexpr JSEntryPtrTag
261 const ExceptionHandlerPtrTag = constexpr ExceptionHandlerPtrTag
262 const NoPtrTag = constexpr NoPtrTag
263 const SlowPathPtrTag = constexpr SlowPathPtrTag
264
265 # Some register conventions.
266 if JSVALUE64
267     # - Use a pair of registers to represent the PC: one register for the
268     #   base of the bytecodes, and one register for the index.
269     # - The PC base (or PB for short) must be stored in a callee-save register.
270     # - C calls are still given the Instruction* rather than the PC index.
271     #   This requires an add before the call, and a sub after.
272     const PC = t4 # When changing this, make sure LLIntPC is up to date in LLIntPCRanges.h
273     if ARM64 or ARM64E
274         const metadataTable = csr6
275         const PB = csr7
276         const tagTypeNumber = csr8
277         const tagMask = csr9
278     elsif X86_64
279         const metadataTable = csr1
280         const PB = csr2
281         const tagTypeNumber = csr3
282         const tagMask = csr4
283     elsif X86_64_WIN
284         const metadataTable = csr3
285         const PB = csr4
286         const tagTypeNumber = csr5
287         const tagMask = csr6
288     elsif C_LOOP
289         const PB = csr0
290         const tagTypeNumber = csr1
291         const tagMask = csr2
292         const metadataTable = csr3
293     end
294
295 else
296     const PC = t4 # When changing this, make sure LLIntPC is up to date in LLIntPCRanges.h
297     if C_LOOP
298         const metadataTable = csr3
299     elsif ARMv7
300         const metadataTable = csr0
301     else
302         error
303     end
304 end
305
306 macro dispatch(advance)
307     addp advance, PC
308     nextInstruction()
309 end
310
311 macro dispatchIndirect(offset)
312     dispatch(offset)
313 end
314
315 macro dispatchOp(size, op)
316     macro dispatchNarrow()
317         dispatch(constexpr %op%_length)
318     end
319
320     macro dispatchWide()
321         dispatch(constexpr %op%_length * 4 + 1)
322     end
323
324     size(dispatchNarrow, dispatchWide, macro (dispatch) dispatch() end)
325 end
326
327 macro getu(size, op, field, dst)
328     size(getuOperandNarrow, getuOperandWide, macro (getu)
329         getu(op, field, dst)
330     end)
331 end
332
333 macro get(size, op, field, dst)
334     size(getOperandNarrow, getOperandWide, macro (get)
335         get(op, field, dst)
336     end)
337 end
338
339 macro narrow(narrowFn, wideFn, k)
340     k(narrowFn)
341 end
342
343 macro wide(narrowFn, wideFn, k)
344     k(wideFn)
345 end
346
347 macro metadata(size, opcode, dst, scratch)
348     loadp constexpr %opcode%::opcodeID * 4[metadataTable], dst # offset = metadataTable<unsigned*>[opcodeID]
349     getu(size, opcode, metadataID, scratch) # scratch = bytecode.metadataID
350     muli sizeof %opcode%::Metadata, scratch # scratch *= sizeof(Op::Metadata)
351     addi scratch, dst # offset += scratch
352     addp metadataTable, dst # return &metadataTable[offset]
353 end
354
355 macro jumpImpl(target)
356     btiz target, .outOfLineJumpTarget
357     dispatchIndirect(target)
358 .outOfLineJumpTarget:
359     callSlowPath(_llint_slow_path_out_of_line_jump_target)
360     nextInstruction()
361 end
362
363 macro commonOp(label, prologue, fn)
364 _%label%:
365     prologue()
366     fn(narrow)
367
368 _%label%_wide:
369     prologue()
370     fn(wide)
371 end
372
373 macro op(l, fn)
374     commonOp(l, macro () end, macro (unused)
375         fn()
376     end)
377 end
378
379 macro llintOp(name, op, fn)
380     commonOp(llint_%name%, traceExecution, macro(size)
381         macro getImpl(field, dst)
382             get(size, op, field, dst)
383         end
384
385         macro dispatchImpl()
386             dispatchOp(size, name)
387         end
388
389         fn(size, getImpl, dispatchImpl)
390     end)
391 end
392
393 macro llintOpWithReturn(name, op, fn)
394     llintOp(name, op, macro(size, get, dispatch)
395         makeReturn(get, dispatch, macro (return)
396             fn(size, get, dispatch, return)
397         end)
398     end)
399 end
400
401 macro llintOpWithMetadata(name, op, fn)
402     llintOpWithReturn(name, op, macro (size, get, dispatch, return)
403         macro meta(dst, scratch)
404             metadata(size, op, dst, scratch)
405         end
406         fn(size, get, dispatch, meta, return)
407     end)
408 end
409
410 macro llintOpWithJump(name, op, impl)
411     llintOpWithMetadata(name, op, macro(size, get, dispatch, metadata, return)
412         macro jump(field)
413             get(field, t0)
414             jumpImpl(t0)
415         end
416
417         impl(size, get, jump, dispatch)
418     end)
419 end
420
421 macro llintOpWithProfile(name, op, fn)
422     llintOpWithMetadata(name, op, macro(size, get, dispatch, metadata, return)
423         makeReturnProfiled(op, get, metadata, dispatch, macro (returnProfiled)
424             fn(size, get, dispatch, returnProfiled)
425         end)
426     end)
427 end
428
429
430 if X86_64_WIN
431     const extraTempReg = t0
432 else
433     const extraTempReg = t5
434 end
435
436 # Constants for reasoning about value representation.
437 const TagOffset = constexpr TagOffset
438 const PayloadOffset = constexpr PayloadOffset
439
440 # Constant for reasoning about butterflies.
441 const IsArray                  = constexpr IsArray
442 const IndexingShapeMask        = constexpr IndexingShapeMask
443 const NoIndexingShape          = constexpr NoIndexingShape
444 const Int32Shape               = constexpr Int32Shape
445 const DoubleShape              = constexpr DoubleShape
446 const ContiguousShape          = constexpr ContiguousShape
447 const ArrayStorageShape        = constexpr ArrayStorageShape
448 const SlowPutArrayStorageShape = constexpr SlowPutArrayStorageShape
449 const CopyOnWrite              = constexpr CopyOnWrite
450
451 # Type constants.
452 const StringType = constexpr StringType
453 const SymbolType = constexpr SymbolType
454 const ObjectType = constexpr ObjectType
455 const FinalObjectType = constexpr FinalObjectType
456 const JSFunctionType = constexpr JSFunctionType
457 const ArrayType = constexpr ArrayType
458 const DerivedArrayType = constexpr DerivedArrayType
459 const ProxyObjectType = constexpr ProxyObjectType
460
461 # The typed array types need to be numbered in a particular order because of the manually written
462 # switch statement in get_by_val and put_by_val.
463 const Int8ArrayType = constexpr Int8ArrayType
464 const Uint8ArrayType = constexpr Uint8ArrayType
465 const Uint8ClampedArrayType = constexpr Uint8ClampedArrayType
466 const Int16ArrayType = constexpr Int16ArrayType
467 const Uint16ArrayType = constexpr Uint16ArrayType
468 const Int32ArrayType = constexpr Int32ArrayType
469 const Uint32ArrayType = constexpr Uint32ArrayType
470 const Float32ArrayType = constexpr Float32ArrayType
471 const Float64ArrayType = constexpr Float64ArrayType
472
473 const FirstTypedArrayType = constexpr FirstTypedArrayType
474 const NumberOfTypedArrayTypesExcludingDataView = constexpr NumberOfTypedArrayTypesExcludingDataView
475
476 # Type flags constants.
477 const MasqueradesAsUndefined = constexpr MasqueradesAsUndefined
478 const ImplementsDefaultHasInstance = constexpr ImplementsDefaultHasInstance
479
480 # Bytecode operand constants.
481 const FirstConstantRegisterIndexNarrow = 16
482 const FirstConstantRegisterIndexWide = constexpr FirstConstantRegisterIndex
483
484 # Code type constants.
485 const GlobalCode = constexpr GlobalCode
486 const EvalCode = constexpr EvalCode
487 const FunctionCode = constexpr FunctionCode
488 const ModuleCode = constexpr ModuleCode
489
490 # The interpreter steals the tag word of the argument count.
491 const LLIntReturnPC = ArgumentCount + TagOffset
492
493 # String flags.
494 const HashFlags8BitBuffer = constexpr StringImpl::s_hashFlag8BitBuffer
495
496 # Copied from PropertyOffset.h
497 const firstOutOfLineOffset = constexpr firstOutOfLineOffset
498
499 # ResolveType
500 const GlobalProperty = constexpr GlobalProperty
501 const GlobalVar = constexpr GlobalVar
502 const GlobalLexicalVar = constexpr GlobalLexicalVar
503 const ClosureVar = constexpr ClosureVar
504 const LocalClosureVar = constexpr LocalClosureVar
505 const ModuleVar = constexpr ModuleVar
506 const GlobalPropertyWithVarInjectionChecks = constexpr GlobalPropertyWithVarInjectionChecks
507 const GlobalVarWithVarInjectionChecks = constexpr GlobalVarWithVarInjectionChecks
508 const GlobalLexicalVarWithVarInjectionChecks = constexpr GlobalLexicalVarWithVarInjectionChecks
509 const ClosureVarWithVarInjectionChecks = constexpr ClosureVarWithVarInjectionChecks
510
511 const ResolveTypeMask = constexpr GetPutInfo::typeBits
512 const InitializationModeMask = constexpr GetPutInfo::initializationBits
513 const InitializationModeShift = constexpr GetPutInfo::initializationShift
514 const NotInitialization = constexpr InitializationMode::NotInitialization
515
516 const MarkedBlockSize = constexpr MarkedBlock::blockSize
517 const MarkedBlockMask = ~(MarkedBlockSize - 1)
518 const MarkedBlockFooterOffset = constexpr MarkedBlock::offsetOfFooter
519
520 const BlackThreshold = constexpr blackThreshold
521
522 const VectorBufferOffset = Vector::m_buffer
523 const VectorSizeOffset = Vector::m_size
524
525 # Some common utilities.
526 macro crash()
527     if C_LOOP
528         cloopCrash
529     else
530         call _llint_crash
531     end
532 end
533
534 macro assert(assertion)
535     if ASSERT_ENABLED
536         assertion(.ok)
537         crash()
538     .ok:
539     end
540 end
541
542 # The probe macro can be used to insert some debugging code without perturbing scalar
543 # registers. Presently, the probe macro only preserves scalar registers. Hence, the
544 # C probe callback function should not trash floating point registers.
545 #
546 # The macro you pass to probe() can pass whatever registers you like to your probe
547 # callback function. However, you need to be mindful of which of the registers are
548 # also used as argument registers, and ensure that you don't trash the register value
549 # before storing it in the probe callback argument register that you desire.
550 #
551 # Here's an example of how it's used:
552 #
553 #     probe(
554 #         macro()
555 #             move cfr, a0 # pass the ExecState* as arg0.
556 #             move t0, a1 # pass the value of register t0 as arg1.
557 #             call _cProbeCallbackFunction # to do whatever you want.
558 #         end
559 #     )
560 #
561 if X86_64 or ARM64 or ARM64E
562     macro probe(action)
563         # save all the registers that the LLInt may use.
564         if ARM64 or ARM64E
565             push cfr, lr
566         end
567         push a0, a1
568         push a2, a3
569         push t0, t1
570         push t2, t3
571         push t4, t5
572         if ARM64 or ARM64E
573             push csr0, csr1
574             push csr2, csr3
575             push csr4, csr5
576             push csr6, csr7
577             push csr8, csr9
578         end
579
580         action()
581
582         # restore all the registers we saved previously.
583         if ARM64 or ARM64E
584             pop csr9, csr8
585             pop csr7, csr6
586             pop csr5, csr4
587             pop csr3, csr2
588             pop csr1, csr0
589         end
590         pop t5, t4
591         pop t3, t2
592         pop t1, t0
593         pop a3, a2
594         pop a1, a0
595         if ARM64 or ARM64E
596             pop lr, cfr
597         end
598     end
599 else
600     macro probe(action)
601     end
602 end
603
604 macro checkStackPointerAlignment(tempReg, location)
605     if ASSERT_ENABLED
606         if ARM64 or ARM64E or C_LOOP
607             # ARM64 and ARM64E will check for us!
608             # C_LOOP does not need the alignment, and can use a little perf
609             # improvement from avoiding useless work.
610         else
611             if ARM or ARMv7 or ARMv7_TRADITIONAL
612                 # ARM can't do logical ops with the sp as a source
613                 move sp, tempReg
614                 andp StackAlignmentMask, tempReg
615             else
616                 andp sp, StackAlignmentMask, tempReg
617             end
618             btpz tempReg, .stackPointerOkay
619             move location, tempReg
620             break
621         .stackPointerOkay:
622         end
623     end
624 end
625
626 if C_LOOP or ARM64 or ARM64E or X86_64 or X86_64_WIN
627     const CalleeSaveRegisterCount = 0
628 elsif ARM or ARMv7_TRADITIONAL or ARMv7
629     const CalleeSaveRegisterCount = 7
630 elsif MIPS
631     const CalleeSaveRegisterCount = 1
632 elsif X86 or X86_WIN
633     const CalleeSaveRegisterCount = 3
634 end
635
636 const CalleeRegisterSaveSize = CalleeSaveRegisterCount * MachineRegisterSize
637
638 # VMEntryTotalFrameSize includes the space for struct VMEntryRecord and the
639 # callee save registers rounded up to keep the stack aligned
640 const VMEntryTotalFrameSize = (CalleeRegisterSaveSize + sizeof VMEntryRecord + StackAlignment - 1) & ~StackAlignmentMask
641
642 macro pushCalleeSaves()
643     if C_LOOP or ARM64 or ARM64E or X86_64 or X86_64_WIN
644     elsif ARM or ARMv7_TRADITIONAL
645         emit "push {r4-r10}"
646     elsif ARMv7
647         emit "push {r4-r6, r8-r11}"
648     elsif MIPS
649         emit "addiu $sp, $sp, -4"
650         emit "sw $s4, 0($sp)"
651         # save $gp to $s4 so that we can restore it after a function call
652         emit "move $s4, $gp"
653     elsif X86
654         emit "push %esi"
655         emit "push %edi"
656         emit "push %ebx"
657     elsif X86_WIN
658         emit "push esi"
659         emit "push edi"
660         emit "push ebx"
661     end
662 end
663
664 macro popCalleeSaves()
665     if C_LOOP or ARM64 or ARM64E or X86_64 or X86_64_WIN
666     elsif ARM or ARMv7_TRADITIONAL
667         emit "pop {r4-r10}"
668     elsif ARMv7
669         emit "pop {r4-r6, r8-r11}"
670     elsif MIPS
671         emit "lw $s4, 0($sp)"
672         emit "addiu $sp, $sp, 4"
673     elsif X86
674         emit "pop %ebx"
675         emit "pop %edi"
676         emit "pop %esi"
677     elsif X86_WIN
678         emit "pop ebx"
679         emit "pop edi"
680         emit "pop esi"
681     end
682 end
683
684 macro preserveCallerPCAndCFR()
685     if C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS
686         push lr
687         push cfr
688     elsif X86 or X86_WIN or X86_64 or X86_64_WIN
689         push cfr
690     elsif ARM64 or ARM64E
691         push cfr, lr
692     else
693         error
694     end
695     move sp, cfr
696 end
697
698 macro restoreCallerPCAndCFR()
699     move cfr, sp
700     if C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS
701         pop cfr
702         pop lr
703     elsif X86 or X86_WIN or X86_64 or X86_64_WIN
704         pop cfr
705     elsif ARM64 or ARM64E
706         pop lr, cfr
707     end
708 end
709
710 macro preserveCalleeSavesUsedByLLInt()
711     subp CalleeSaveSpaceStackAligned, sp
712     if C_LOOP
713         storep metadataTable, -PtrSize[cfr]
714     elsif ARM or ARMv7_TRADITIONAL
715     elsif ARMv7
716         storep metadataTable, -4[cfr]
717     elsif ARM64 or ARM64E
718         emit "stp x27, x28, [x29, #-16]"
719         emit "stp x25, x26, [x29, #-32]"
720     elsif MIPS
721     elsif X86
722     elsif X86_WIN
723     elsif X86_64
724         storep csr4, -8[cfr]
725         storep csr3, -16[cfr]
726         storep csr2, -24[cfr]
727         storep csr1, -32[cfr]
728     elsif X86_64_WIN
729         storep csr6, -8[cfr]
730         storep csr5, -16[cfr]
731         storep csr4, -24[cfr]
732         storep csr3, -32[cfr]
733     end
734 end
735
736 macro restoreCalleeSavesUsedByLLInt()
737     if C_LOOP
738         loadp -PtrSize[cfr], metadataTable
739     elsif ARM or ARMv7_TRADITIONAL
740     elsif ARMv7
741         loadp -4[cfr], metadataTable
742     elsif ARM64 or ARM64E
743         emit "ldp x25, x26, [x29, #-32]"
744         emit "ldp x27, x28, [x29, #-16]"
745     elsif MIPS
746     elsif X86
747     elsif X86_WIN
748     elsif X86_64
749         loadp -32[cfr], csr1
750         loadp -24[cfr], csr2
751         loadp -16[cfr], csr3
752         loadp -8[cfr], csr4
753     elsif X86_64_WIN
754         loadp -32[cfr], csr3
755         loadp -24[cfr], csr4
756         loadp -16[cfr], csr5
757         loadp -8[cfr], csr6
758     end
759 end
760
761 macro copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(vm, temp)
762     if ARM64 or ARM64E or X86_64 or X86_64_WIN
763         loadp VM::topEntryFrame[vm], temp
764         vmEntryRecord(temp, temp)
765         leap VMEntryRecord::calleeSaveRegistersBuffer[temp], temp
766         if ARM64 or ARM64E
767             storeq csr0, [temp]
768             storeq csr1, 8[temp]
769             storeq csr2, 16[temp]
770             storeq csr3, 24[temp]
771             storeq csr4, 32[temp]
772             storeq csr5, 40[temp]
773             storeq csr6, 48[temp]
774             storeq csr7, 56[temp]
775             storeq csr8, 64[temp]
776             storeq csr9, 72[temp]
777             stored csfr0, 80[temp]
778             stored csfr1, 88[temp]
779             stored csfr2, 96[temp]
780             stored csfr3, 104[temp]
781             stored csfr4, 112[temp]
782             stored csfr5, 120[temp]
783             stored csfr6, 128[temp]
784             stored csfr7, 136[temp]
785         elsif X86_64
786             storeq csr0, [temp]
787             storeq csr1, 8[temp]
788             storeq csr2, 16[temp]
789             storeq csr3, 24[temp]
790             storeq csr4, 32[temp]
791         elsif X86_64_WIN
792             storeq csr0, [temp]
793             storeq csr1, 8[temp]
794             storeq csr2, 16[temp]
795             storeq csr3, 24[temp]
796             storeq csr4, 32[temp]
797             storeq csr5, 40[temp]
798             storeq csr6, 48[temp]
799         end
800     end
801 end
802
803 macro restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer(vm, temp)
804     if ARM64 or ARM64E or X86_64 or X86_64_WIN
805         loadp VM::topEntryFrame[vm], temp
806         vmEntryRecord(temp, temp)
807         leap VMEntryRecord::calleeSaveRegistersBuffer[temp], temp
808         if ARM64 or ARM64E
809             loadq [temp], csr0
810             loadq 8[temp], csr1
811             loadq 16[temp], csr2
812             loadq 24[temp], csr3
813             loadq 32[temp], csr4
814             loadq 40[temp], csr5
815             loadq 48[temp], csr6
816             loadq 56[temp], csr7
817             loadq 64[temp], csr8
818             loadq 72[temp], csr9
819             loadd 80[temp], csfr0
820             loadd 88[temp], csfr1
821             loadd 96[temp], csfr2
822             loadd 104[temp], csfr3
823             loadd 112[temp], csfr4
824             loadd 120[temp], csfr5
825             loadd 128[temp], csfr6
826             loadd 136[temp], csfr7
827         elsif X86_64
828             loadq [temp], csr0
829             loadq 8[temp], csr1
830             loadq 16[temp], csr2
831             loadq 24[temp], csr3
832             loadq 32[temp], csr4
833         elsif X86_64_WIN
834             loadq [temp], csr0
835             loadq 8[temp], csr1
836             loadq 16[temp], csr2
837             loadq 24[temp], csr3
838             loadq 32[temp], csr4
839             loadq 40[temp], csr5
840             loadq 48[temp], csr6
841         end
842     end
843 end
844
845 macro preserveReturnAddressAfterCall(destinationRegister)
846     if C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or ARM64 or ARM64E or MIPS
847         # In C_LOOP case, we're only preserving the bytecode vPC.
848         move lr, destinationRegister
849     elsif X86 or X86_WIN or X86_64 or X86_64_WIN
850         pop destinationRegister
851     else
852         error
853     end
854 end
855
856 macro unpoison(poison, field, scratch)
857     if POISON
858         loadp poison, scratch
859         xorp scratch, field
860     end
861 end
862
863 macro functionPrologue()
864     tagReturnAddress sp
865     if X86 or X86_WIN or X86_64 or X86_64_WIN
866         push cfr
867     elsif ARM64 or ARM64E
868         push cfr, lr
869     elsif C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS
870         push lr
871         push cfr
872     end
873     move sp, cfr
874 end
875
876 macro functionEpilogue()
877     if X86 or X86_WIN or X86_64 or X86_64_WIN
878         pop cfr
879     elsif ARM64 or ARM64E
880         pop lr, cfr
881     elsif C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS
882         pop cfr
883         pop lr
884     end
885 end
886
887 macro vmEntryRecord(entryFramePointer, resultReg)
888     subp entryFramePointer, VMEntryTotalFrameSize, resultReg
889 end
890
891 macro getFrameRegisterSizeForCodeBlock(codeBlock, size)
892     loadi CodeBlock::m_numCalleeLocals[codeBlock], size
893     lshiftp 3, size
894     addp maxFrameExtentForSlowPathCall, size
895 end
896
897 macro restoreStackPointerAfterCall()
898     loadp CodeBlock[cfr], t2
899     getFrameRegisterSizeForCodeBlock(t2, t2)
900     if ARMv7
901         subp cfr, t2, t2
902         move t2, sp
903     else
904         subp cfr, t2, sp
905     end
906 end
907
908 macro traceExecution()
909     if TRACING
910         callSlowPath(_llint_trace)
911     end
912 end
913
914 macro callTargetFunction(size, op, dispatch, callee, callPtrTag)
915     if C_LOOP
916         cloopCallJSFunction callee
917     else
918         call callee, callPtrTag
919     end
920     restoreStackPointerAfterCall()
921     dispatchAfterCall(size, op, dispatch)
922 end
923
924 macro prepareForRegularCall(callee, temp1, temp2, temp3, callPtrTag)
925     addp CallerFrameAndPCSize, sp
926 end
927
928 # sp points to the new frame
929 macro prepareForTailCall(callee, temp1, temp2, temp3, callPtrTag)
930     restoreCalleeSavesUsedByLLInt()
931
932     loadi PayloadOffset + ArgumentCount[cfr], temp2
933     loadp CodeBlock[cfr], temp1
934     loadp CodeBlock::m_numParameters[temp1], temp1
935     bilteq temp1, temp2, .noArityFixup
936     move temp1, temp2
937
938 .noArityFixup:
939     # We assume < 2^28 arguments
940     muli SlotSize, temp2
941     addi StackAlignment - 1 + CallFrameHeaderSize, temp2
942     andi ~StackAlignmentMask, temp2
943
944     move cfr, temp1
945     addp temp2, temp1
946
947     loadi PayloadOffset + ArgumentCount[sp], temp2
948     # We assume < 2^28 arguments
949     muli SlotSize, temp2
950     addi StackAlignment - 1 + CallFrameHeaderSize, temp2
951     andi ~StackAlignmentMask, temp2
952
953     if ARM or ARMv7_TRADITIONAL or ARMv7 or ARM64 or ARM64E or C_LOOP or MIPS
954         addp CallerFrameAndPCSize, sp
955         subi CallerFrameAndPCSize, temp2
956         loadp CallerFrameAndPC::returnPC[cfr], lr
957     else
958         addp PtrSize, sp
959         subi PtrSize, temp2
960         loadp PtrSize[cfr], temp3
961         storep temp3, [sp]
962     end
963
964     if POINTER_PROFILING
965         addp 16, cfr, temp3
966         untagReturnAddress temp3
967     end
968
969     subp temp2, temp1
970     loadp [cfr], cfr
971
972 .copyLoop:
973     if ARM64 and not ADDRESS64
974         subi MachineRegisterSize, temp2
975         loadq [sp, temp2, 1], temp3
976         storeq temp3, [temp1, temp2, 1]
977         btinz temp2, .copyLoop
978     else
979         subi PtrSize, temp2
980         loadp [sp, temp2, 1], temp3
981         storep temp3, [temp1, temp2, 1]
982         btinz temp2, .copyLoop
983     end
984
985     move temp1, sp
986     jmp callee, callPtrTag
987 end
988
989 macro slowPathForCall(size, op, dispatch, slowPath, prepareCall)
990     callCallSlowPath(
991         slowPath,
992         # Those are r0 and r1
993         macro (callee, calleeFramePtr)
994             btpz calleeFramePtr, .dontUpdateSP
995             move calleeFramePtr, sp
996             prepareCall(callee, t2, t3, t4, SlowPathPtrTag)
997         .dontUpdateSP:
998             callTargetFunction(size, op, dispatch, callee, SlowPathPtrTag)
999         end)
1000 end
1001
1002 macro arrayProfile(offset, cellAndIndexingType, metadata, scratch)
1003     const cell = cellAndIndexingType
1004     const indexingType = cellAndIndexingType 
1005     loadi JSCell::m_structureID[cell], scratch
1006     storei scratch, offset + ArrayProfile::m_lastSeenStructureID[metadata]
1007     loadb JSCell::m_indexingTypeAndMisc[cell], indexingType
1008 end
1009
1010 macro skipIfIsRememberedOrInEden(cell, slowPath)
1011     memfence
1012     bba JSCell::m_cellState[cell], BlackThreshold, .done
1013     slowPath()
1014 .done:
1015 end
1016
1017 macro notifyWrite(set, slow)
1018     bbneq WatchpointSet::m_state[set], IsInvalidated, slow
1019 end
1020
1021 macro checkSwitchToJIT(increment, action)
1022     loadp CodeBlock[cfr], t0
1023     baddis increment, CodeBlock::m_llintExecuteCounter + BaselineExecutionCounter::m_counter[t0], .continue
1024     action()
1025     .continue:
1026 end
1027
1028 macro checkSwitchToJITForEpilogue()
1029     checkSwitchToJIT(
1030         10,
1031         macro ()
1032             callSlowPath(_llint_replace)
1033         end)
1034 end
1035
1036 macro assertNotConstant(size, index)
1037     size(FirstConstantRegisterIndexNarrow, FirstConstantRegisterIndexWide, macro (FirstConstantRegisterIndex)
1038         assert(macro (ok) bilt index, FirstConstantRegisterIndex, ok end)
1039     end)
1040 end
1041
1042 macro functionForCallCodeBlockGetter(targetRegister, scratch)
1043     if JSVALUE64
1044         loadp Callee[cfr], targetRegister
1045     else
1046         loadp Callee + PayloadOffset[cfr], targetRegister
1047     end
1048     loadp JSFunction::m_executable[targetRegister], targetRegister
1049     unpoison(_g_JSFunctionPoison, targetRegister, scratch)
1050     loadp FunctionExecutable::m_codeBlockForCall[targetRegister], targetRegister
1051     loadp ExecutableToCodeBlockEdge::m_codeBlock[targetRegister], targetRegister
1052 end
1053
1054 macro functionForConstructCodeBlockGetter(targetRegister, scratch)
1055     if JSVALUE64
1056         loadp Callee[cfr], targetRegister
1057     else
1058         loadp Callee + PayloadOffset[cfr], targetRegister
1059     end
1060     loadp JSFunction::m_executable[targetRegister], targetRegister
1061     unpoison(_g_JSFunctionPoison, targetRegister, scratch)
1062     loadp FunctionExecutable::m_codeBlockForConstruct[targetRegister], targetRegister
1063     loadp ExecutableToCodeBlockEdge::m_codeBlock[targetRegister], targetRegister
1064 end
1065
1066 macro notFunctionCodeBlockGetter(targetRegister, ignored)
1067     loadp CodeBlock[cfr], targetRegister
1068 end
1069
1070 macro functionCodeBlockSetter(sourceRegister)
1071     storep sourceRegister, CodeBlock[cfr]
1072 end
1073
1074 macro notFunctionCodeBlockSetter(sourceRegister)
1075     # Nothing to do!
1076 end
1077
1078 # Do the bare minimum required to execute code. Sets up the PC, leave the CodeBlock*
1079 # in t1. May also trigger prologue entry OSR.
1080 macro prologue(codeBlockGetter, codeBlockSetter, osrSlowPath, traceSlowPath)
1081     # Set up the call frame and check if we should OSR.
1082     tagReturnAddress sp
1083     preserveCallerPCAndCFR()
1084
1085     if TRACING
1086         subp maxFrameExtentForSlowPathCall, sp
1087         callSlowPath(traceSlowPath)
1088         addp maxFrameExtentForSlowPathCall, sp
1089     end
1090     codeBlockGetter(t1, t2)
1091     if not C_LOOP
1092         baddis 5, CodeBlock::m_llintExecuteCounter + BaselineExecutionCounter::m_counter[t1], .continue
1093         if JSVALUE64
1094             move cfr, a0
1095             move PC, a1
1096             cCall2(osrSlowPath)
1097         else
1098             # We are after the function prologue, but before we have set up sp from the CodeBlock.
1099             # Temporarily align stack pointer for this call.
1100             subp 8, sp
1101             move cfr, a0
1102             move PC, a1
1103             cCall2(osrSlowPath)
1104             addp 8, sp
1105         end
1106         btpz r0, .recover
1107         move cfr, sp # restore the previous sp
1108         # pop the callerFrame since we will jump to a function that wants to save it
1109         if ARM64 or ARM64E
1110             pop lr, cfr
1111             untagReturnAddress sp
1112         elsif ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS
1113             pop cfr
1114             pop lr
1115         else
1116             pop cfr
1117         end
1118         jmp r0, JSEntryPtrTag
1119     .recover:
1120         codeBlockGetter(t1, t2)
1121     .continue:
1122     end
1123
1124     codeBlockSetter(t1)
1125
1126     preserveCalleeSavesUsedByLLInt()
1127
1128     # Set up the PC.
1129     if JSVALUE64
1130         loadp CodeBlock::m_instructionsRawPointer[t1], PB
1131         unpoison(_g_CodeBlockPoison, PB, t3)
1132         move 0, PC
1133     else
1134         loadp CodeBlock::m_instructionsRawPointer[t1], PC
1135     end
1136
1137     # Get new sp in t0 and check stack height.
1138     getFrameRegisterSizeForCodeBlock(t1, t0)
1139     subp cfr, t0, t0
1140     bpa t0, cfr, .needStackCheck
1141     loadp CodeBlock::m_poisonedVM[t1], t2
1142     unpoison(_g_CodeBlockPoison, t2, t3)
1143     if C_LOOP
1144         bpbeq VM::m_cloopStackLimit[t2], t0, .stackHeightOK
1145     else
1146         bpbeq VM::m_softStackLimit[t2], t0, .stackHeightOK
1147     end
1148
1149 .needStackCheck:
1150     # Stack height check failed - need to call a slow_path.
1151     # Set up temporary stack pointer for call including callee saves
1152     subp maxFrameExtentForSlowPathCall, sp
1153     callSlowPath(_llint_stack_check)
1154     bpeq r1, 0, .stackHeightOKGetCodeBlock
1155
1156     # We're throwing before the frame is fully set up. This frame will be
1157     # ignored by the unwinder. So, let's restore the callee saves before we
1158     # start unwinding. We need to do this before we change the cfr.
1159     restoreCalleeSavesUsedByLLInt()
1160
1161     move r1, cfr
1162     jmp _llint_throw_from_slow_path_trampoline
1163
1164 .stackHeightOKGetCodeBlock:
1165     # Stack check slow path returned that the stack was ok.
1166     # Since they were clobbered, need to get CodeBlock and new sp
1167     codeBlockGetter(t1, t2)
1168     getFrameRegisterSizeForCodeBlock(t1, t0)
1169     subp cfr, t0, t0
1170
1171 .stackHeightOK:
1172     if X86_64 or ARM64
1173         # We need to start zeroing from sp as it has been adjusted after saving callee saves.
1174         move sp, t2
1175         move t0, sp
1176 .zeroStackLoop:
1177         bpeq sp, t2, .zeroStackDone
1178         subp PtrSize, t2
1179         storep 0, [t2]
1180         jmp .zeroStackLoop
1181 .zeroStackDone:
1182     else
1183         move t0, sp
1184     end
1185
1186     loadp CodeBlock::m_metadata[t1], metadataTable
1187
1188     if JSVALUE64
1189         move TagTypeNumber, tagTypeNumber
1190         addq TagBitTypeOther, tagTypeNumber, tagMask
1191     end
1192 end
1193
1194 # Expects that CodeBlock is in t1, which is what prologue() leaves behind.
1195 # Must call dispatch(0) after calling this.
1196 macro functionInitialization(profileArgSkip)
1197     # Profile the arguments. Unfortunately, we have no choice but to do this. This
1198     # code is pretty horrendous because of the difference in ordering between
1199     # arguments and value profiles, the desire to have a simple loop-down-to-zero
1200     # loop, and the desire to use only three registers so as to preserve the PC and
1201     # the code block. It is likely that this code should be rewritten in a more
1202     # optimal way for architectures that have more than five registers available
1203     # for arbitrary use in the interpreter.
1204     loadi CodeBlock::m_numParameters[t1], t0
1205     addp -profileArgSkip, t0 # Use addi because that's what has the peephole
1206     assert(macro (ok) bpgteq t0, 0, ok end)
1207     btpz t0, .argumentProfileDone
1208     loadp CodeBlock::m_argumentValueProfiles + RefCountedArray::m_data[t1], t3
1209     btpz t3, .argumentProfileDone # When we can't JIT, we don't allocate any argument value profiles.
1210     mulp sizeof ValueProfile, t0, t2 # Aaaaahhhh! Need strength reduction!
1211     lshiftp 3, t0
1212     addp t2, t3
1213 .argumentProfileLoop:
1214     if JSVALUE64
1215         loadq ThisArgumentOffset - 8 + profileArgSkip * 8[cfr, t0], t2
1216         subp sizeof ValueProfile, t3
1217         storeq t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets[t3]
1218     else
1219         loadi ThisArgumentOffset + TagOffset - 8 + profileArgSkip * 8[cfr, t0], t2
1220         subp sizeof ValueProfile, t3
1221         storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + TagOffset[t3]
1222         loadi ThisArgumentOffset + PayloadOffset - 8 + profileArgSkip * 8[cfr, t0], t2
1223         storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + PayloadOffset[t3]
1224     end
1225     baddpnz -8, t0, .argumentProfileLoop
1226 .argumentProfileDone:
1227 end
1228
1229 macro doReturn()
1230     restoreCalleeSavesUsedByLLInt()
1231     restoreCallerPCAndCFR()
1232     ret
1233 end
1234
1235 # This break instruction is needed so that the synthesized llintPCRangeStart label
1236 # doesn't point to the exact same location as vmEntryToJavaScript which comes after it.
1237 # Otherwise, libunwind will report vmEntryToJavaScript as llintPCRangeStart in
1238 # stack traces.
1239
1240     break
1241
1242 # stub to call into JavaScript or Native functions
1243 # EncodedJSValue vmEntryToJavaScript(void* code, VM* vm, ProtoCallFrame* protoFrame)
1244 # EncodedJSValue vmEntryToNativeFunction(void* code, VM* vm, ProtoCallFrame* protoFrame)
1245
1246 if C_LOOP
1247     _llint_vm_entry_to_javascript:
1248 else
1249     global _vmEntryToJavaScript
1250     _vmEntryToJavaScript:
1251 end
1252     doVMEntry(makeJavaScriptCall)
1253
1254
1255 if C_LOOP
1256     _llint_vm_entry_to_native:
1257 else
1258     global _vmEntryToNative
1259     _vmEntryToNative:
1260 end
1261     doVMEntry(makeHostFunctionCall)
1262
1263
1264 if not C_LOOP
1265     # void sanitizeStackForVMImpl(VM* vm)
1266     global _sanitizeStackForVMImpl
1267     _sanitizeStackForVMImpl:
1268         tagReturnAddress sp
1269         # We need three non-aliased caller-save registers. We are guaranteed
1270         # this for a0, a1 and a2 on all architectures.
1271         if X86 or X86_WIN
1272             loadp 4[sp], a0
1273         end
1274         const vm = a0
1275         const address = a1
1276         const zeroValue = a2
1277     
1278         loadp VM::m_lastStackTop[vm], address
1279         bpbeq sp, address, .zeroFillDone
1280     
1281         move 0, zeroValue
1282     .zeroFillLoop:
1283         storep zeroValue, [address]
1284         addp PtrSize, address
1285         bpa sp, address, .zeroFillLoop
1286
1287     .zeroFillDone:
1288         move sp, address
1289         storep address, VM::m_lastStackTop[vm]
1290         ret
1291     
1292     # VMEntryRecord* vmEntryRecord(const EntryFrame* entryFrame)
1293     global _vmEntryRecord
1294     _vmEntryRecord:
1295         tagReturnAddress sp
1296         if X86 or X86_WIN
1297             loadp 4[sp], a0
1298         end
1299
1300         vmEntryRecord(a0, r0)
1301         ret
1302 end
1303
1304 if C_LOOP
1305     # Dummy entry point the C Loop uses to initialize.
1306     _llint_entry:
1307         crash()
1308 else
1309     macro initPCRelative(pcBase)
1310         if X86_64 or X86_64_WIN or X86 or X86_WIN
1311             call _relativePCBase
1312         _relativePCBase:
1313             pop pcBase
1314         elsif ARM64 or ARM64E
1315         elsif ARMv7
1316         _relativePCBase:
1317             move pc, pcBase
1318             subp 3, pcBase   # Need to back up the PC and set the Thumb2 bit
1319         elsif ARM or ARMv7_TRADITIONAL
1320         _relativePCBase:
1321             move pc, pcBase
1322             subp 8, pcBase
1323         elsif MIPS
1324             la _relativePCBase, pcBase
1325             setcallreg pcBase # needed to set $t9 to the right value for the .cpload created by the label.
1326         _relativePCBase:
1327         end
1328 end
1329
1330 # The PC base is in t2, as this is what _llint_entry leaves behind through
1331 # initPCRelative(t2)
1332 macro setEntryAddress(index, label)
1333     setEntryAddressCommon(index, label, a0)
1334 end
1335
1336 macro setEntryAddressWide(index, label)
1337      setEntryAddressCommon(index, label, a1)
1338 end
1339
1340 macro setEntryAddressCommon(index, label, map)
1341     if X86_64 or X86_64_WIN
1342         leap (label - _relativePCBase)[t2], t3
1343         move index, t4
1344         storep t3, [map, t4, 8]
1345     elsif X86 or X86_WIN
1346         leap (label - _relativePCBase)[t2], t3
1347         move index, t4
1348         storep t3, [map, t4, 4]
1349     elsif ARM64 or ARM64E
1350         pcrtoaddr label, t2
1351         move index, t4
1352         storep t2, [map, t4, PtrSize]
1353     elsif ARM or ARMv7 or ARMv7_TRADITIONAL
1354         mvlbl (label - _relativePCBase), t4
1355         addp t4, t2, t4
1356         move index, t3
1357         storep t4, [map, t3, 4]
1358     elsif MIPS
1359         la label, t4
1360         la _relativePCBase, t3
1361         subp t3, t4
1362         addp t4, t2, t4
1363         move index, t3
1364         storep t4, [map, t3, 4]
1365     end
1366 end
1367
1368 global _llint_entry
1369 # Entry point for the llint to initialize.
1370 _llint_entry:
1371     functionPrologue()
1372     pushCalleeSaves()
1373     if X86 or X86_WIN
1374         loadp 20[sp], a0
1375         loadp 24[sp], a1
1376     end
1377
1378     initPCRelative(t2)
1379
1380     # Include generated bytecode initialization file.
1381     include InitBytecodes
1382
1383     popCalleeSaves()
1384     functionEpilogue()
1385     ret
1386 end
1387
1388 _llint_op_wide:
1389     nextInstructionWide()
1390
1391 _llint_op_wide_wide:
1392     crash()
1393
1394 _llint_op_enter_wide:
1395     crash()
1396
1397 op(llint_program_prologue, macro ()
1398     prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
1399     dispatch(0)
1400 end)
1401
1402
1403 op(llint_module_program_prologue, macro ()
1404     prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
1405     dispatch(0)
1406 end)
1407
1408
1409 op(llint_eval_prologue, macro ()
1410     prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
1411     dispatch(0)
1412 end)
1413
1414
1415 op(llint_function_for_call_prologue, macro ()
1416     prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call, _llint_trace_prologue_function_for_call)
1417     functionInitialization(0)
1418     dispatch(0)
1419 end)
1420     
1421
1422 op(llint_function_for_construct_prologue, macro ()
1423     prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct, _llint_trace_prologue_function_for_construct)
1424     functionInitialization(1)
1425     dispatch(0)
1426 end)
1427     
1428
1429 op(llint_function_for_call_arity_check, macro ()
1430     prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call_arityCheck, _llint_trace_arityCheck_for_call)
1431     functionArityCheck(.functionForCallBegin, _slow_path_call_arityCheck)
1432 .functionForCallBegin:
1433     functionInitialization(0)
1434     dispatch(0)
1435 end)
1436
1437
1438 op(llint_function_for_construct_arity_check, macro ()
1439     prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct_arityCheck, _llint_trace_arityCheck_for_construct)
1440     functionArityCheck(.functionForConstructBegin, _slow_path_construct_arityCheck)
1441 .functionForConstructBegin:
1442     functionInitialization(1)
1443     dispatch(0)
1444 end)
1445
1446
1447 # Value-representation-specific code.
1448 if JSVALUE64
1449     include LowLevelInterpreter64
1450 else
1451     include LowLevelInterpreter32_64
1452 end
1453
1454
1455 # Value-representation-agnostic code.
1456 macro slowPathOp(op)
1457     llintOp(op_%op%, unused, macro (unused, unused, dispatch)
1458         callSlowPath(_slow_path_%op%)
1459         dispatch()
1460     end)
1461 end
1462
1463 slowPathOp(create_cloned_arguments)
1464 slowPathOp(create_direct_arguments)
1465 slowPathOp(create_lexical_environment)
1466 slowPathOp(create_rest)
1467 slowPathOp(create_scoped_arguments)
1468 slowPathOp(create_this)
1469 slowPathOp(define_accessor_property)
1470 slowPathOp(define_data_property)
1471 slowPathOp(enumerator_generic_pname)
1472 slowPathOp(enumerator_structure_pname)
1473 slowPathOp(get_by_id_with_this)
1474 slowPathOp(get_by_val_with_this)
1475 slowPathOp(get_direct_pname)
1476 slowPathOp(get_enumerable_length)
1477 slowPathOp(get_property_enumerator)
1478 slowPathOp(greater)
1479 slowPathOp(greatereq)
1480 slowPathOp(has_generic_property)
1481 slowPathOp(has_indexed_property)
1482 slowPathOp(has_structure_property)
1483 slowPathOp(in_by_id)
1484 slowPathOp(in_by_val)
1485 slowPathOp(is_function)
1486 slowPathOp(is_object_or_null)
1487 slowPathOp(less)
1488 slowPathOp(lesseq)
1489 slowPathOp(mod)
1490 slowPathOp(new_array_buffer)
1491 slowPathOp(new_array_with_spread)
1492 slowPathOp(pow)
1493 slowPathOp(push_with_scope)
1494 slowPathOp(put_by_id_with_this)
1495 slowPathOp(put_by_val_with_this)
1496 slowPathOp(resolve_scope_for_hoisting_func_decl_in_eval)
1497 slowPathOp(spread)
1498 slowPathOp(strcat)
1499 slowPathOp(throw_static_error)
1500 slowPathOp(to_index_string)
1501 slowPathOp(typeof)
1502 slowPathOp(unreachable)
1503
1504 macro llintSlowPathOp(op)
1505     llintOp(op_%op%, unused, macro (unused, unused, dispatch)
1506         callSlowPath(_llint_slow_path_%op%)
1507         dispatch()
1508     end)
1509 end
1510
1511 llintSlowPathOp(del_by_id)
1512 llintSlowPathOp(del_by_val)
1513 llintSlowPathOp(instanceof)
1514 llintSlowPathOp(instanceof_custom)
1515 llintSlowPathOp(new_array)
1516 llintSlowPathOp(new_array_with_size)
1517 llintSlowPathOp(new_async_func)
1518 llintSlowPathOp(new_async_func_exp)
1519 llintSlowPathOp(new_async_generator_func)
1520 llintSlowPathOp(new_async_generator_func_exp)
1521 llintSlowPathOp(new_func)
1522 llintSlowPathOp(new_func_exp)
1523 llintSlowPathOp(new_generator_func)
1524 llintSlowPathOp(new_generator_func_exp)
1525 llintSlowPathOp(new_object)
1526 llintSlowPathOp(new_regexp)
1527 llintSlowPathOp(put_getter_by_id)
1528 llintSlowPathOp(put_getter_by_val)
1529 llintSlowPathOp(put_getter_setter_by_id)
1530 llintSlowPathOp(put_setter_by_id)
1531 llintSlowPathOp(put_setter_by_val)
1532 llintSlowPathOp(set_function_name)
1533 llintSlowPathOp(super_sampler_begin)
1534 llintSlowPathOp(super_sampler_end)
1535 llintSlowPathOp(throw)
1536 llintSlowPathOp(try_get_by_id)
1537
1538 llintOp(op_switch_string, unused, macro (unused, unused, unused)
1539     callSlowPath(_llint_slow_path_switch_string)
1540     nextInstruction()
1541 end)
1542
1543
1544 equalityComparisonOp(eq, OpEq,
1545     macro (left, right, result) cieq left, right, result end)
1546
1547
1548 equalityComparisonOp(neq, OpNeq,
1549     macro (left, right, result) cineq left, right, result end)
1550
1551
1552 compareUnsignedOp(below, OpBelow,
1553         macro (left, right, result) cib left, right, result end)
1554
1555
1556 compareUnsignedOp(beloweq, OpBeloweq,
1557         macro (left, right, result) cibeq left, right, result end)
1558
1559
1560 llintOpWithJump(op_jmp, OpJmp, macro (size, get, jump, dispatch)
1561     jump(target)
1562 end)
1563
1564
1565 llintJumpTrueOrFalseOp(
1566     jtrue, OpJtrue,
1567     macro (value, target) btinz value, 1, target end)
1568
1569
1570 llintJumpTrueOrFalseOp(
1571     jfalse, OpJfalse,
1572     macro (value, target) btiz value, 1, target end)
1573
1574
1575 compareJumpOp(
1576     jless, OpJless,
1577     macro (left, right, target) bilt left, right, target end,
1578     macro (left, right, target) bdlt left, right, target end)
1579
1580
1581 compareJumpOp(
1582     jnless, OpJnless,
1583     macro (left, right, target) bigteq left, right, target end,
1584     macro (left, right, target) bdgtequn left, right, target end)
1585
1586
1587 compareJumpOp(
1588     jgreater, OpJgreater,
1589     macro (left, right, target) bigt left, right, target end,
1590     macro (left, right, target) bdgt left, right, target end)
1591
1592
1593 compareJumpOp(
1594     jngreater, OpJngreater,
1595     macro (left, right, target) bilteq left, right, target end,
1596     macro (left, right, target) bdltequn left, right, target end)
1597
1598
1599 compareJumpOp(
1600     jlesseq, OpJlesseq,
1601     macro (left, right, target) bilteq left, right, target end,
1602     macro (left, right, target) bdlteq left, right, target end)
1603
1604
1605 compareJumpOp(
1606     jnlesseq, OpJnlesseq,
1607     macro (left, right, target) bigt left, right, target end,
1608     macro (left, right, target) bdgtun left, right, target end)
1609
1610
1611 compareJumpOp(
1612     jgreatereq, OpJgreatereq,
1613     macro (left, right, target) bigteq left, right, target end,
1614     macro (left, right, target) bdgteq left, right, target end)
1615
1616
1617 compareJumpOp(
1618     jngreatereq, OpJngreatereq,
1619     macro (left, right, target) bilt left, right, target end,
1620     macro (left, right, target) bdltun left, right, target end)
1621
1622
1623 equalityJumpOp(
1624     jeq, OpJeq,
1625     macro (left, right, target) bieq left, right, target end)
1626
1627
1628 equalityJumpOp(
1629     jneq, OpJneq,
1630     macro (left, right, target) bineq left, right, target end)
1631
1632
1633 compareUnsignedJumpOp(
1634     jbelow, OpJbelow,
1635     macro (left, right, target) bib left, right, target end)
1636
1637
1638 compareUnsignedJumpOp(
1639     jbeloweq, OpJbeloweq,
1640     macro (left, right, target) bibeq left, right, target end)
1641
1642
1643 preOp(inc, OpInc,
1644     macro (value, slow) baddio 1, value, slow end)
1645
1646
1647 preOp(dec, OpDec,
1648     macro (value, slow) bsubio 1, value, slow end)
1649
1650
1651 llintOp(op_loop_hint, OpLoopHint, macro (unused, unused, dispatch)
1652     checkSwitchToJITForLoop()
1653     dispatch()
1654 end)
1655
1656
1657 llintOp(op_check_traps, OpCheckTraps, macro (unused, unused, dispatch)
1658     loadp CodeBlock[cfr], t1
1659     loadp CodeBlock::m_poisonedVM[t1], t1
1660     unpoison(_g_CodeBlockPoison, t1, t2)
1661     loadb VM::m_traps+VMTraps::m_needTrapHandling[t1], t0
1662     btpnz t0, .handleTraps
1663 .afterHandlingTraps:
1664     dispatch()
1665 .handleTraps:
1666     callTrapHandler(.throwHandler)
1667     jmp .afterHandlingTraps
1668 .throwHandler:
1669     jmp _llint_throw_from_slow_path_trampoline
1670 end)
1671
1672
1673 # Returns the packet pointer in t0.
1674 macro acquireShadowChickenPacket(slow)
1675     loadp CodeBlock[cfr], t1
1676     loadp CodeBlock::m_poisonedVM[t1], t1
1677     unpoison(_g_CodeBlockPoison, t1, t2)
1678     loadp VM::m_shadowChicken[t1], t2
1679     loadp ShadowChicken::m_logCursor[t2], t0
1680     bpaeq t0, ShadowChicken::m_logEnd[t2], slow
1681     addp sizeof ShadowChicken::Packet, t0, t1
1682     storep t1, ShadowChicken::m_logCursor[t2]
1683 end
1684
1685
1686 llintOp(op_nop, OpNop, macro (unused, unused, dispatch)
1687     dispatch()
1688 end)
1689
1690
1691 # we can't use callOp because we can't pass `call` as the opcode name, since it's an instruction name
1692 commonCallOp(op_call, _llint_slow_path_call, OpCall, prepareForRegularCall, macro (getu, metadata)
1693     arrayProfileForCall(OpCall, getu)
1694 end)
1695
1696
1697 macro callOp(name, op, prepareCall, fn)
1698     commonCallOp(op_%name%, _llint_slow_path_%name%, op, prepareCall, fn)
1699 end
1700
1701
1702 callOp(tail_call, OpTailCall, prepareForTailCall, macro (getu, metadata)
1703     arrayProfileForCall(OpTailCall, getu)
1704     checkSwitchToJITForEpilogue()
1705     # reload metadata since checkSwitchToJITForEpilogue() might have trashed t5
1706     metadata(t5, t0)
1707 end)
1708
1709
1710 callOp(construct, OpConstruct, prepareForRegularCall, macro (getu, metadata) end)
1711
1712
1713 macro doCallVarargs(size, op, dispatch, frameSlowPath, slowPath, prepareCall)
1714     callSlowPath(frameSlowPath)
1715     branchIfException(_llint_throw_from_slow_path_trampoline)
1716     # calleeFrame in r1
1717     if JSVALUE64
1718         move r1, sp
1719     else
1720         # The calleeFrame is not stack aligned, move down by CallerFrameAndPCSize to align
1721         if ARMv7
1722             subp r1, CallerFrameAndPCSize, t2
1723             move t2, sp
1724         else
1725             subp r1, CallerFrameAndPCSize, sp
1726         end
1727     end
1728     slowPathForCall(size, op, dispatch, slowPath, prepareCall)
1729 end
1730
1731
1732 llintOp(op_call_varargs, OpCallVarargs, macro (size, get, dispatch)
1733     doCallVarargs(size, OpCallVarargs, dispatch, _llint_slow_path_size_frame_for_varargs, _llint_slow_path_call_varargs, prepareForRegularCall)
1734 end)
1735
1736 llintOp(op_tail_call_varargs, OpTailCallVarargs, macro (size, get, dispatch)
1737     checkSwitchToJITForEpilogue()
1738     # We lie and perform the tail call instead of preparing it since we can't
1739     # prepare the frame for a call opcode
1740     doCallVarargs(size, OpTailCallVarargs, dispatch, _llint_slow_path_size_frame_for_varargs, _llint_slow_path_tail_call_varargs, prepareForTailCall)
1741 end)
1742
1743
1744 llintOp(op_tail_call_forward_arguments, OpTailCallForwardArguments, macro (size, get, dispatch)
1745     checkSwitchToJITForEpilogue()
1746     # We lie and perform the tail call instead of preparing it since we can't
1747     # prepare the frame for a call opcode
1748     doCallVarargs(size, OpTailCallForwardArguments, dispatch, _llint_slow_path_size_frame_for_forward_arguments, _llint_slow_path_tail_call_forward_arguments, prepareForTailCall)
1749 end)
1750
1751
1752 llintOp(op_construct_varargs, OpConstructVarargs, macro (size, get, dispatch)
1753     doCallVarargs(size, OpConstructVarargs, dispatch, _llint_slow_path_size_frame_for_varargs, _llint_slow_path_construct_varargs, prepareForRegularCall)
1754 end)
1755
1756
1757 # Eval is executed in one of two modes:
1758 #
1759 # 1) We find that we're really invoking eval() in which case the
1760 #    execution is perfomed entirely inside the slow_path, and it
1761 #    returns the PC of a function that just returns the return value
1762 #    that the eval returned.
1763 #
1764 # 2) We find that we're invoking something called eval() that is not
1765 #    the real eval. Then the slow_path returns the PC of the thing to
1766 #    call, and we call it.
1767 #
1768 # This allows us to handle two cases, which would require a total of
1769 # up to four pieces of state that cannot be easily packed into two
1770 # registers (C functions can return up to two registers, easily):
1771 #
1772 # - The call frame register. This may or may not have been modified
1773 #   by the slow_path, but the convention is that it returns it. It's not
1774 #   totally clear if that's necessary, since the cfr is callee save.
1775 #   But that's our style in this here interpreter so we stick with it.
1776 #
1777 # - A bit to say if the slow_path successfully executed the eval and has
1778 #   the return value, or did not execute the eval but has a PC for us
1779 #   to call.
1780 #
1781 # - Either:
1782 #   - The JS return value (two registers), or
1783 #
1784 #   - The PC to call.
1785 #
1786 # It turns out to be easier to just always have this return the cfr
1787 # and a PC to call, and that PC may be a dummy thunk that just
1788 # returns the JS value that the eval returned.
1789
1790 _llint_op_call_eval:
1791     slowPathForCall(
1792         narrow,
1793         OpCallEval,
1794         macro () dispatchOp(narrow, op_call_eval) end,
1795         _llint_slow_path_call_eval,
1796         prepareForRegularCall)
1797
1798 _llint_op_call_eval_wide:
1799     slowPathForCall(
1800         wide,
1801         OpCallEval,
1802         macro () dispatchOp(wide, op_call_eval) end,
1803         _llint_slow_path_call_eval_wide,
1804         prepareForRegularCall)
1805
1806 _llint_generic_return_point:
1807     dispatchAfterCall(narrow, OpCallEval, macro ()
1808         dispatchOp(narrow, op_call_eval)
1809     end)
1810
1811 _llint_generic_return_point_wide:
1812     dispatchAfterCall(wide, OpCallEval, macro()
1813         dispatchOp(wide, op_call_eval)
1814     end)
1815
1816 llintOp(op_identity_with_profile, OpIdentityWithProfile, macro (unused, unused, dispatch)
1817     dispatch()
1818 end)
1819
1820
1821 llintOp(op_yield, OpYield, macro (unused, unused, unused)
1822     notSupported()
1823 end)
1824
1825
1826 llintOp(op_debug, OpDebug, macro (unused, unused, dispatch)
1827     loadp CodeBlock[cfr], t0
1828     loadi CodeBlock::m_debuggerRequests[t0], t0
1829     btiz t0, .opDebugDone
1830     callSlowPath(_llint_slow_path_debug)
1831 .opDebugDone:                    
1832     dispatch()
1833 end)
1834
1835
1836 op(llint_native_call_trampoline, macro ()
1837     nativeCallTrampoline(NativeExecutable::m_function)
1838 end)
1839
1840
1841 op(llint_native_construct_trampoline, macro ()
1842     nativeCallTrampoline(NativeExecutable::m_constructor)
1843 end)
1844
1845
1846 op(llint_internal_function_call_trampoline, macro ()
1847     internalFunctionCallTrampoline(InternalFunction::m_functionForCall)
1848 end)
1849
1850
1851 op(llint_internal_function_construct_trampoline, macro ()
1852     internalFunctionCallTrampoline(InternalFunction::m_functionForConstruct)
1853 end)
1854
1855
1856 # Lastly, make sure that we can link even though we don't support all opcodes.
1857 # These opcodes should never arise when using LLInt or either JIT. We assert
1858 # as much.
1859
1860 macro notSupported()
1861     if ASSERT_ENABLED
1862         crash()
1863     else
1864         # We should use whatever the smallest possible instruction is, just to
1865         # ensure that there is a gap between instruction labels. If multiple
1866         # smallest instructions exist, we should pick the one that is most
1867         # likely result in execution being halted. Currently that is the break
1868         # instruction on all architectures we're interested in. (Break is int3
1869         # on Intel, which is 1 byte, and bkpt on ARMv7, which is 2 bytes.)
1870         break
1871     end
1872 end