1 *******************************************
2 * HipHop Intermediate Representation (HHIR)
3 *******************************************
10 The HipHop Intermediate Representation (IR) is a typed, in-memory,
11 static-single-assignment, intermediate-level representation of HHBC programs
12 used for just in time compilation, with these goals:
14 1. Complete. The IR represents a program or program fragment entirely,
15 without reference to HHBC or other upstream forms of the program.
17 2. Type-Safe. Since the IR deals directly with refined types and internal VM
18 types, all operations are typesafe. All instruction parameters have a
19 parameter type P, and all variables have a type S. Given an instruction
20 with source parameter type P and variable type S, S must be equal to or
21 more refined than P (S == P or S <: P).
23 3. Machine Independent. Since this IR is intended to be used in a JIT
24 compiler, it will always be used in a machine specific context.
25 Nevertheless, we rely on machine independence in order to separate
26 concerns and increase portability of the VM. Passes which manipulate IR
27 based on PHP or HHBC semantics should be portable. Passes which deal with
28 machine specifics (such as register allocation) should be done in the
29 lower level IR (vasm). Types are machine independent.
31 The unit of compilation is the IRUnit, which is a collection of Blocks
32 containing IRInstructions that produce and consume SSATmp values. Blocks are
33 single-entry, single-exit sequences of instructions (i.e. basic
34 blocks). Instructions may be annotated with Type parameter which modifies the
35 instruction's behavior, or with additional compile-time constant data (see
36 extra-data.h). Each SSATmp has a Type which describes the set of values it may
37 hold, over its entire live range. Instructions may have side effects, which
38 occur in execution order.
40 The static single assignment form guarantees the following two invariants for a
41 well-formed compilation unit:
43 1. Each SSATmp is assigned to by exactly one IRInstruction.
45 2. Definitions dominate uses. Every path to an IRInstruction using an SSATmp
46 first executes the IRInstruction defining the SSATmp.
48 Any pass that generates or manipulates IR must preserve these invariants,
49 however it is possible and expected for the invariants to be temporarily broken
50 during IR generation or during an optimization pass.
56 IRUnits have one entry block, zero or more exit blocks, and zero or more catch
57 blocks. Exit blocks leave the compilation unit in the middle of the same PHP
58 function using one of several instructions that exit a compilation unit
59 (e.g. ReqBindJmp). Catch blocks are blocks that are reachable from exceptional
60 control flow edges, and are executed during unwinding if an exception
61 propagates through the instruction that had it as a `taken' edge.
63 No SSATmps are defined on entry to the main Block.
65 Blocks which are join points may start with a DefLabel with destination
66 SSATmps. In that case, each predecessor must be a Jmp passing a matching number
67 of sources. In this case the Jmp acts as a tail-call, passing arguments the
68 same way a plain call would.
70 Together, the sources of the Jmp instructions and the destinations of the
71 DefLabel instructions act as traditional SSA Phi pseudo-functions; The type of
72 the DefLabel's destination is the type-union of the corresponding sources.
73 Because the Jmp sources are at the ends of blocks, they do not violate the SSA
74 dominator rule (rule 2, above).
80 For an overview of the HHIR type system, see the "Type System" section in
81 hackers-guide/jit-core.md.
87 An SSATmp represents a virtual register. Since HHIR uses SSA, an SSATmp may
88 only be assigned to by one instruction. The type of an SSATmp represents the
89 set of values it may hold at the point it is defined, which is invariant over
90 the lifetime of the variable (from the definition point to the last use).
96 An instruction is an executable operation with zero or more inputs (sources),
97 zero or one result (destination), and possible side effects such as accessing
98 memory, doing I/O, and which may branch or throw an exception. Some
99 instructions have a Type parameter which modifies its behavior, or other "extra
100 data" in an arbitrary C++ struct (see extra-data.h).
102 Each instruction has a signature which describes its effect, parameter types,
103 and return type, for example:
105 r:Bool = IsType<T> s:Gen
107 By convention we use infix; destinations on the left, = represents assignment,
108 then the opcode name, and source parameters. Types are to the right of the
109 entities they modify, separated by : for results, sources, and variables, or
110 delimited by <> for instruction modifiers.
112 Instruction flags further describe their behavior:
117 The instruction defines exactly one destination variable (HasDest) or a
118 varying number of destination variables (NaryDest). These flags are mutually
119 exclusive. An instruction with neither of these flags set has zero
120 destination variables.
122 Note that an instruction's destination variable may sometimes be a copy of
123 one of the input variables. (For example, AddElem returns the array it took
128 The instruction is safe to elide through common subexpression elimination.
132 Whether the instruction is essential indicates whether it can be elided
133 through certain types of optimizations.
135 Currently this is just used to flag whether we are allowed to do dead code
140 Indicates that the instruction will call a native helper.
142 The register allocator uses this to optimize register spills around native
143 calls and to bias register allocation toward arguments and return values.
147 The instruction consumes a reference to one or more of its sources, either by
148 decreasing its refcount or storing the reference to memory.
152 The instruction calls decref on one or more of its sources. Unless a source
153 is known to have a refcount > 1 before the instruction executes, it cannot
154 safely be used after the instruction has executed.
158 The instruction produces an incref'd value.
160 This flag is currently unused.
164 The instruction may raise an error, and must have an edge to a catch block.
168 The instruction has no next instruction; it either jumps, returns, or throws.
172 The instruction has a (sometimes optional) taken edge. Instructions that are
173 conditional branches (i.e. a Branch that is not Terminal) will also have a
178 The value of the instruction's dest is the same as one of its inputs; it
179 differs only in the refcount of the underlying object, the type of the
180 variable, or some other property that doesn't affect the value of the
185 The instruction modifies the in-memory evaluation stack in the process of
186 performing its primary work. It will have a StkPtr destination in addition to
187 its primary destination.
191 This instruction has a counterpart that returns a StkPtr in addition to any
192 primary destination. The behavior of the stack-modifying version is otherwise
197 The instruction may affect the type and/or value of its base operand,
198 operating on object properties.
202 The instruction may affect the type and/or value of its base operand,
203 operating on array elements.
209 1. Checks and Asserts
211 Note: Instructions that guard or check boxed types only check that the operand
212 is boxed, and they ignore the type of the value inside the box (the inner
213 type). The inner type is normally checked when the value within the box is
214 about to be loaded, using a separate CheckRefInner instruction.
216 | CheckType<T>, DRefineS(0), S(Gen), B|E|P
218 Check that the type of the src S0 is T, and if so copy it to D. If S0 is not
219 type T, branch to block B.
221 | CheckNullptr, ND, S(CountedStr,Nullptr), B|E|CRc
223 If S0 is not a null pointer, branch to block B. This is used to check the
224 return value of a native helper that returns a potentially null StringData*.
226 | AssertType, DRefineS(0), S(Gen,Cls), C|E|P
228 Assert that the type of S0 is T, copying it to D.
230 | CheckTypeMem<T>, ND, S(PtrToGen), B|E
232 If the value pointed to by S0 is not type T, branch to the block B.
234 | GuardLoc<T,localId>, ND, S(FramePtr) S(StkPtr), E
236 Guard that type of the given localId on the frame S0 is a subtype of the type
237 T; if not, make a fallback jump. (A jump to a service request that chains to
238 a retranslation for this tracelet.)
240 Returns a new frame pointer representing the same frame as S0 but with the
241 knowledge that the guarded local has type T.
243 | HintLocInner<T,localId>, ND, S(FramePtr), E
245 Hint that the inner type of a BoxedCell in localId is likely type T, where T
246 is a subtype of BoxedCell. The type must be guarded on before it is known to
249 | CheckLoc<T,localId>, ND, S(FramePtr), B|E
251 Check that type of the given localId on the frame S0 is T; if not, branch to
254 Returns a new frame pointer representing the same frame as S0 but with the
255 knowledge that the checked local has type T.
257 | AssertLoc<T,localId>, ND, S(FramePtr), E
259 Asserts that type of the supplied local on the frame S0 is T. This is used
260 for local type information, and is similar to GuardLoc except it doesn't
261 imply a runtime check (the assertion must've already been proven to be true)
262 and cannot cause control flow.
264 Returns a new frame pointer representing the same frame as S0 but with the
265 knowledge that the asserted local has type T.
267 | GuardStk<T,offset>, D(StkPtr), S(StkPtr) S(FramePtr), E
269 Guard that the type of the cell on the stack pointed to by S0 at offset (in
270 cells) is T. If not, make a fallback jump. (A jump to a service request that
271 chains to a retranslation for this tracelet.)
273 Returns a new StkPtr that represents the same stack but with the knowledge
274 that the slot at the index S1 has type T.
276 | HintStkInner<T,offset>, D(StkPtr), S(StkPtr), E
278 Hint that the inner type of the BoxedInitCell on the stack pointed to by S0
279 at offset (in cells) is T. The type must be guarded on before it is known to
282 Returns a new StkPtr that represents the same stack but with the prediction
285 | CheckStk<T,offset>, D(StkPtr), S(StkPtr), B|E
287 Check that the type of the cell on the stack pointed to by S0 at offset (in
288 cells) is T; if not, branch to block B.
290 Returns a new StkPtr that represents the same stack but with the knowledge
291 that the slot at the index S1 has type T.
293 | AssertStk<T,offset>, D(StkPtr), S(StkPtr), E
295 Returns a new StkPtr that represents the same stack as S0, but with the
296 knowledge that the slot at offset (in cells) has type T. This is similar to a
297 GuardStk except that it does not imply a runtime check and cannot cause
300 | CastStk<T,offset>, D(StkPtr), S(StkPtr), Er
302 Returns a new StkPtr that represents the same stack as S0, but with the slot
303 at offset (in cells) converted to type T.
305 | CastStkIntToDbl<offset>, D(StkPtr), S(StkPtr), E
307 Returns a new StkPtr where the slot at offset has been converted from an
311 The following instructions deal with paramater coercion (the standard type
312 conversion for arguments to HNI functions). If parameter coercion fails these
313 functions will throw a TVCoercion exception. They may throw other types of
314 exceptions depending on how coercion is implemented.
316 | CoerceStk<T,offset,fn,argNum>, D(StkPtr), S(StkPtr), Er
318 Returns a new StkPtr that represents the same stack as S0, but with the slot
319 at offset (in cells) converted to type T. May throw an exception in the case
320 of failed paramater coercion. The callee is f, and the position of the
321 argument being coerced is argNum.
323 | CoerceCellToBool<fn,argNum>, D(Bool), S(Cell), Er
325 | CoerceCellToInt<fn,argNum>, D(Int), S(Cell), Er
327 | CoerceStrToInt<fn,argNum>, D(Int), S(Str), Er
329 | CoerceCellToDbl<fn,argNum>, D(Dbl), S(Cell), Er
331 | CoerceStrToDbl<fn,argNum>, D(Dbl), S(Str), Er
333 These instructions convert either a Cell or a Str to a primitive type (Bool,
334 Int, Dbl) and return the resulting value. They may throw an exception upon
335 failed type coercion. They are encoded along with callee Func, fn, and the
336 integer position of the argument, argNum, being coerced.
338 | CheckInit, ND, S(Gen), B
340 If S0's type is Uninit, branch to block B.
342 | CheckInitMem, ND, S(PtrToGen) C(Int), B
344 If the value at S0 + S1 (in bytes) has type Uninit, branch to block B.
346 | CheckDefinedClsEq<className,classPtr>, ND, NA, B|E
348 Compare the currently defined class of name `className' with `classPtr'; if
349 they aren't equal or if `className' is not defined, branch to block B.
351 | CheckCold<TransID>, ND, NA, B|E
353 Check if the counter associated with translation TransID is cold (i.e. within
354 a fixed threshold). If it's not (i.e. such translation has reached the
355 "hotness threshold"), then branch to block B.
357 | GuardRefs, ND, S(Func) S(Int) C(Int) S(Int) S(Int) S(FramePtr) S(StkPtr), E
359 Perform reffiness guard checks. Operands:
361 S0 - function pointer for the frame
362 S1 - num params expected in the func
363 S2 - first bit to check, must be a multiple of 64
364 S3 - mask to check (RefDeps::Record::m_mask entires)
365 S4 - values to check (RefDeps::Record::m_vals entires)
366 S5 - Pointer to the current frame
367 S6 - Pointer to the current VM stack
369 If any of the checks fail, make a fallback jump. (Jump to a service request
370 that will chain to a retranslation of this tracelet.)
372 | CheckRefs, ND, S(Func) S(Int) C(Int) S(Int) S(Int), B|E
374 Perform reffiness guard checks. Operands:
376 S0 - function pointer for the frame
377 S1 - num params expected in the func
378 S2 - first bit to check, must be a multiple of 64
379 S3 - mask to check (RefDeps::Record::m_mask entires)
380 S4 - values to check (RefDeps::Record::m_vals entires)
382 If any of the checks fail, branch to block B.
384 | EndGuards, ND, NA, E
386 A no-op at runtime, this instruction serves to mark the end of the initial
387 sequence of guards in a trace.
389 | CheckNonNull, DSubtract(0, Nullptr), S(Nullptr,Func,PtrToGen,TCA,Cls), B
391 If the value in S0 is Nullptr, branch to block B.
393 | AssertNonNull, DSubtract(0, Nullptr), S(Nullptr,CountedStr,Func), P
395 Returns S0, with Nullptr removed from its type. This instruction currently
396 supports a very limited range of types but can be expanded if needed.
398 | CheckStaticLocInit, ND, S(BoxedCell), B
400 Check if the static local (RDS) RefData represented by S0 is initialized, and
401 if not branch to block B.
407 | AbsDbl, D(Dbl), S(Dbl), C
409 | AddInt, D(Int), S(Int) S(Int), C
411 | SubInt, D(Int), S(Int) S(Int), C
413 | MulInt, D(Int), S(Int) S(Int), C
415 | AndInt, D(Int), S(Int) S(Int), C
417 | AddDbl, D(Dbl), S(Dbl) S(Dbl), C
419 | SubDbl, D(Dbl), S(Dbl) S(Dbl), C
421 | MulDbl, D(Dbl), S(Dbl) S(Dbl), C
423 | DivDbl, D(Dbl), S(Dbl) S(Dbl), B|C
425 | Mod, D(Int), S(Int) S(Int), C
427 | Sqrt, D(Dbl), S(Dbl), C
429 | OrInt, D(Int), S(Int) S(Int), C
431 | XorInt, D(Int), S(Int) S(Int), C
433 | Shl, D(Int), S(Int) S(Int), C
435 | Shr, D(Int), S(Int) S(Int), C
437 | Floor, D(Dbl), S(Dbl), C
439 | Ceil, D(Dbl), S(Dbl), C
441 | AddIntO, D(Int), S(Int) S(Int), B|C
443 | SubIntO, D(Int), S(Int) S(Int), B|C
445 | MulIntO, D(Int), S(Int) S(Int), B|C
447 Double arithmetic, integer arithmetic, and integer bitwise operations.
448 Performs the operation described by the opcode name on S0 and S1, and puts
451 Undefined behavior occurs if Mod is given a divisor of zero, or if the
452 divisor is -1 and the dividend is the minimum representable integer.
454 AbsDbl computes the absolute value of a double-precision value.
456 DivDbl will branch to block B when S1 is zero (signed or unsigned). When the
457 result of the division is a real valued number DivDbl conforms to IEEE 754.
458 In particular should the result of a division be zero the sign will follow
459 normal sign rules for division.
461 Note that Shr is an arithmetic right shift: The MSB is sign-extended.
463 Floor and Ceil will return an integral value not greater, or not less
464 than their input respectively. Their use requires SSE 4.1, availability
465 should be checked before they are emitted.
467 AddIntO, SubIntO, MulIntO perform integer arithmetic on S0 and S1, but will
468 branch to block B on integer overflow.
470 | XorBool, D(Bool), S(Bool) S(Bool), C
472 Logical XOR of the two sources. (Note that && and || do not have
473 corresponding opcodes because they're handled at the bytecode level, to
474 implement short-circuiting.)
480 To array conversions:
482 | ConvBoolToArr, D(Arr), S(Bool), C|PRc
484 | ConvDblToArr, D(Arr), S(Dbl), C|PRc
486 | ConvIntToArr, D(Arr), S(Int), C|PRc
488 | ConvObjToArr, D(Arr), S(Obj), Er|PRc|CRc|K
490 | ConvStrToArr, D(Arr), S(Str), PRc|CRc
492 | ConvCellToArr, D(Arr), S(Cell), Er|PRc|CRc|K
497 | ConvArrToBool, D(Bool), S(Arr), NF
499 | ConvDblToBool, D(Bool), S(Dbl), C
501 | ConvIntToBool, D(Bool), S(Int), C
503 | ConvStrToBool, D(Bool), S(Str), NF
505 | ConvObjToBool, D(Bool), S(Obj), NF
507 | ConvCellToBool, D(Bool), S(Cell), NF
510 To double conversions:
512 | ConvArrToDbl, D(Dbl), S(Arr), NF
514 | ConvBoolToDbl, D(Dbl), S(Bool), C
516 | ConvIntToDbl, D(Dbl), S(Int), C
518 | ConvObjToDbl, D(Dbl), S(Obj), Er
520 | ConvStrToDbl, D(Dbl), S(Str), NF
522 | ConvCellToDbl, D(Dbl), S(Cell), Er
527 | ConvArrToInt, D(Int), S(Arr), NF
529 | ConvBoolToInt, D(Int), S(Bool), C
531 | ConvDblToInt, D(Int), S(Dbl), C
533 | ConvObjToInt, D(Int), S(Obj), Er|K
535 | ConvStrToInt, D(Int), S(Str), NF
537 | ConvCellToInt, D(Int), S(Cell), Er|K
540 To object conversions:
542 | ConvCellToObj, D(Obj), S(Cell), Er|CRc|PRc|K
545 To string conversions:
547 | ConvBoolToStr, D(StaticStr), S(Bool), C
549 | ConvDblToStr, D(Str), S(Dbl), PRc
551 | ConvIntToStr, D(Str), S(Int), PRc
553 | ConvObjToStr, D(Str), S(Obj), PRc|Er
555 | ConvResToStr, D(Str), S(Res), PRc|Er
557 | ConvCellToStr, D(Str), S(Cell), PRc|Er
560 All the above opcodes convert S0 from its current type to the destination
561 type, according to the PHP semantics of such a conversion.
563 | ConvClsToCctx, D(Cctx), S(Cls), C
565 Convert a class to a class context (i.e. the class with a 1 or'd into the low
568 4. Boolean predicates
570 | Gt, D(Bool), S(Gen) S(Gen), C
572 | GtX, D(Bool), S(Gen) S(Gen), Er|C
574 | Gte, D(Bool), S(Gen) S(Gen), C
576 | GteX, D(Bool), S(Gen) S(Gen), Er|C
578 | Lt, D(Bool), S(Gen) S(Gen), C
580 | LtX, D(Bool), S(Gen) S(Gen), Er|C
582 | Lte, D(Bool), S(Gen) S(Gen), C
584 | LteX, D(Bool), S(Gen) S(Gen), Er|C
586 | Eq, D(Bool), S(Gen) S(Gen), C
588 | EqX, D(Bool), S(Gen) S(Gen), Er|C
590 | Neq, D(Bool), S(Gen) S(Gen), C
592 | NeqX, D(Bool), S(Gen) S(Gen), Er|C
594 | Same, D(Bool), S(Gen) S(Gen), C
596 | NSame, D(Bool), S(Gen) S(Gen), C
598 Perform comparisons with PHP semantics on S0 and S1, and put the result in D.
599 The -X versions may re-enter the VM when comparing an Object with a string,
600 and therefore may throw exceptions. The non-X versions must not be passed
601 (Object,String) pairs, and do not throw. Note that Same and NSame never
602 re-enter or throw, for any types.
604 | GtInt, D(Bool), S(Int) S(Int), C
606 | GteInt, D(Bool), S(Int) S(Int), C
608 | LtInt, D(Bool), S(Int) S(Int), C
610 | LteInt, D(Bool), S(Int) S(Int), C
612 | EqInt, D(Bool), S(Int) S(Int), C
614 | NeqInt, D(Bool), S(Int) S(Int), C
617 Perform 64-bit integer comparisons.
619 | GtDbl, D(Bool), S(Dbl) S(Dbl), C
621 | GteDbl, D(Bool), S(Dbl) S(Dbl), C
623 | LtDbl, D(Bool), S(Dbl) S(Dbl), C
625 | LteDbl, D(Bool), S(Dbl) S(Dbl), C
627 | EqDbl, D(Bool), S(Dbl) S(Dbl), C
629 | NeqDbl, D(Bool), S(Dbl) S(Dbl), C
631 Perform comparisons of doubles. Comparisons that are unordered according to
632 IEEE 754 (such as when at least one operand is NaN) result in false.
634 | InstanceOf, D(Bool), S(Cls) S(Cls|Nullptr), C
636 Sets D based on whether S0 is a descendant of the class, interface, or trait
637 in S1. (Note that this is always false for a trait). S1 may be null at
638 runtime if the class is not defined.
640 | InstanceOfIface, D(Bool), S(Cls) CStr, C
642 Fast path for interface checks. Sets D based on whether S0 implements S1, but
643 S1 must be a unique interface. This should only be used in repo-authoritative
646 | ExtendsClass, D(Bool), S(Cls) C(Cls), C
648 A fast-path for instanceof checks. Sets D based on whether S0 is a descendant
649 of the class in S1, where S1 must be a unique class that is not an interface
652 | InstanceOfBitmask, D(Bool), S(Cls) CStr, C
654 | NInstanceOfBitmask, D(Bool), S(Cls) CStr, C
656 A fast-path for instanceof checks. Sets D based on whether S0 is a descendant
657 of the class named by S1, where S1 must have a bit allocated for it in the
658 fast instance check bitvector (see class.h).
660 | InterfaceSupportsArr, D(Bool), S(Str), C
662 | InterfaceSupportsStr, D(Bool), S(Str), C
664 | InterfaceSupportsInt, D(Bool), S(Str), C
666 | InterfaceSupportsDbl, D(Bool), S(Str), C
668 Returns whether t instanceof S0 returns true when t is of the given type.
670 | IsType<T>, D(Bool), S(Cell), C
672 Sets D to true iff S0 holds a value that is of type T.
674 | IsNType<T>, D(Bool), S(Cell), C
676 Sets D to true iff S0 holds a value that is not of type T.
678 | IsTypeMem<T>, D(Bool), S(PtrToGen), NF
680 Sets D to true iff the value referenced by S0 is of type T.
682 The value in S0 must not be a pointer into the evaluation stack or frame
685 | IsNTypeMem<T>, D(Bool), S(PtrToGen), NF
687 Sets D to true iff the value referenced by S0 is not of type T.
689 | IsScalarType, D(Bool), S(Cell), C
691 Returns true if S0 is of type Int, Bool, Dbl or Str. Returns false otherwise.
693 | IsWaitHandle, D(Bool), S(Obj), C
695 Sets D to true iff S0 is a subclass of WaitHandle.
701 There is a conditional branch instruction for each predicate above, to enable
702 generating efficient compare-and-branch instruction sequences.
705 | JmpGt, ND, S(Gen) S(Gen), B|E
707 | JmpGte, ND, S(Gen) S(Gen), B|E
709 | JmpLt, ND, S(Gen) S(Gen), B|E
711 | JmpLte, ND, S(Gen) S(Gen), B|E
713 | JmpEq, ND, S(Gen) S(Gen), B|E
715 | JmpNeq, ND, S(Gen) S(Gen), B|E
717 | JmpSame, ND, S(Gen) S(Gen), B|E
719 | JmpNSame, ND, S(Gen) S(Gen), B|E
721 | JmpGtInt, ND, S(Int) S(Int), B|E
723 | JmpGteInt, ND, S(Int) S(Int), B|E
725 | JmpLtInt, ND, S(Int) S(Int), B|E
727 | JmpLteInt, ND, S(Int) S(Int), B|E
729 | JmpEqInt, ND, S(Int) S(Int), B|E
731 | JmpNeqInt, ND, S(Int) S(Int), B|E
733 | JmpInstanceOfBitmask, ND, S(Cls) CStr, B|E
735 | JmpNInstanceOfBitmask, ND, S(Cls) CStr, B|E
737 Fused jump instructions. These all operate exactly as their corresponding
738 query op, but also take a label to jump to when the condition is true.
740 | JmpZero, ND, S(Int,Bool), B|E
742 | JmpNZero, ND, S(Int,Bool), B|E
744 Conditionally jump to based on S0.
746 | JmpSSwitchDest, ND, S(TCA), T|E
748 Jump to the target of a sswitch statement, leaving the tracelet, where the
751 | JmpSwitchDest, ND, S(Int), T|E
753 Jump to the target of a switch statement, leaving the tracelet, using table
754 metadata <JmpSwitchData> and index S0.
756 | CheckSurpriseFlags, ND, NA, B|E
758 Tests the implementation-specific surprise flags. If they're true, branches
761 | FunctionReturnHook, ND, S(FramePtr) S(Gen), Er|E
763 Suprise flag hook for function returns.
765 | FunctionSuspendHook, ND, S(FramePtr) C(Bool), Er|E
767 Suprise flag hook for suspending async functions.
771 Halt execution. Used only in tests, as a terminal instruction that does not
772 require any inputs or any successors.
774 | Jmp, ND, SVar(Top), B|T|E
776 Unconditional jump to block B. In the second form, the target block must
777 start with a DefLabel with the same number of destinations as Jmp's number of
778 sources. Jmp parallel-copies its sources to the DefLabel destinations.
780 | DefLabel, DMulti, NA, E
782 DefLabel defines variables received from a previous Jmp. A DefLabel with zero
783 destinations is a no-op, and the predecessor blocks may not necessarily end
784 in Jmp. A DefLabel with one or more destinations may only be reached by a Jmp
785 instruction with the same number of sources. Ordinary branch instructions may
786 not pass values to a DefLabel.
788 | ClsNeq<class>, D(Bool), S(Cls), C
790 Compare S0 to the class `class', returning true if it is not the same.
793 6. Reference manipulation
796 | Box, DBox(0), S(Gen), E|CRc|PRc
798 Box S0 if it is unboxed, and put the resulting BoxedCell in D.
800 | UnboxPtr, DUnboxPtr, S(PtrToGen), NF
802 If S0 points to a cell that is KindOfRef, dereference the pointer in the
803 TypedValue and return a pointer to the inner-cell in D.
805 | BoxPtr, DBoxPtr, S(PtrToGen), NF
807 Boxes the TypeValue that S0 points to if it is not boxed. The result D points
808 to the same TypedValue as S0 but has a more refined type.
810 S0 may not already point into a RefData (due to VM invariants), although the
811 IR type system does not enforce it.
817 | LdStack<T,offset>, DParamMayRelax, S(StkPtr), NF
819 Loads from S0 at offset (in cells), and puts the value in D as type T.
821 | TakeStack, ND, S(StackElem), E
823 Does nothing at runtime. Acts as a hint to the optimizer that the code is
824 taking ownership of a reference to S0.
826 | LdLoc<T,localId>, DParamMayRelax, S(FramePtr), NF
828 Loads local slot localId from the frame S0 and puts the value in D as type T.
830 | LdLocPseudoMain<T,localId>, DParam, S(FramePtr), B
832 Loads local number localId from frame S0 and puts the value in D if the
833 local's type is a subtype of T. If the local's type is not a subtype of T,
834 then the load does not happen, and this instruction branches to B. This
835 instruction is used for loading locals in pseudo-mains, where they can alias
838 | LdStackAddr<T,offset>, DParamPtr(Stk), S(StkPtr), C
840 Loads the address of the stack slot given by the pointer in S0 at the offset
841 (in cells). T must be a subtype of PtrToStkGen.
843 | LdLocAddr<T,localId>, DParamPtr(Frame), S(FramePtr), C
845 Loads the address of the local slot localId from the frame S0 into D. T must
846 be a subtype of PtrToFrameGen.
848 | LdRDSAddr<T,RDSHandle>, DParam, NA, C
850 Load the address of a Gen that lives at the specified RDS handle. The type
851 param must be a subtype of PtrToGen.
853 | LdVectorBase, D(PtrToMembCell), S(Obj), E
855 | LdPairBase, D(PtrToMembCell), S(Obj), E
857 Loads the base pointer to an array of Cells from the given collection
860 | LdMem<T>, DParam, S(PtrToGen) C(Int), NF
862 Loads from S0 + S1 (in bytes) and puts the value in D.
864 | LdContField<T>, DParam, S(Obj) C(Int), NF
866 Loads a property from the object referenced by S0 at the offset given by S1
867 and puts the value in D. S0 must be a Generator.
869 | LdElem, D(Cell), S(PtrToCell) S(Int), NF
871 Loads the element at index S1 from the base pointer in S0. The index in S1 is
872 the number of bytes from the base in S0.
874 | CheckRefInner<T>, ND, S(BoxedCell), B|E
876 TODO(#2939547): this should take BoxedInitCell
878 Check that the inner type of the boxed cell in S0 is T, and if not take the
881 | LdRef<T>, DParam, S(BoxedCell), NF
883 TODO(#2939547): this should take BoxedInitCell
885 Loads the value held in the box referenced by S0 and puts the value in D. The
886 inner type of S0 must be a subtype of T (usually ensured with a previous
889 | LdCtx, D(Ctx), S(FramePtr), C
891 Loads into D the value of the m_this/m_cls field out of the frame pointer S0,
892 which must be a frame for the function in the LdCtx's Marker. The result
893 could be either an object representing the this pointer or a class context.
895 | CheckCtxThis, ND, S(Ctx), B|E
897 Check that the context (m_this or m_cls) in S0 is a non-null $this
898 pointer. If not, branch to B.
900 | CastCtxThis, DThis, S(Ctx), C
902 Convert a Ctx known to contain a $this pointer to a specific object type,
903 based on the marker func for this instruction.
905 | LdCctx, D(Cctx), S(FramePtr), C
907 Loads into D the value of the m_cls field out of the frame pointer S0. The
908 compiler should generate this only if it can prove that the frame does not
909 contain a $this pointer.
911 | LdClsCtx, D(Cls), S(Ctx), C
913 Loads into D the class representing the current context. Extracts the class
914 from S0, which can be either the this pointer or the context class.
916 | LdClsCctx, D(Cls), S(Cctx), C
918 Loads into D the class representing the current context. Extracts the class
919 from the S0, which is a context class.
921 | LdClsCtor, D(Func), S(Cls), C|Er
923 Loads into D the constructor of class S0. If the constructor cannot be called
924 from the current context, raise an error.
926 | DefConst<T>, DParam, NA, C
928 Define a constant value of type T. D is presumed to be globally available and
929 the DefConst instruction will not actually appear in the IR instruction
932 | Conjure<T>, DParam, NA, NF
934 Define a value of type T. This instruction aborts at runtime; it is meant to
935 be used in tests or code that is known to be unreachable.
937 | LdCls, D(Cls), S(Str) C(Cls), C|E|Er
939 Loads the class named S0 in the context of the class S1. Invokes autoload and
940 may raise an error if the class is not defined. The explicit context
941 parameter allows the compiler to simplify this instruction to a DefConst in
942 some cases. If S0 is constant, this instruction may be simplified to a
945 | LdClsCached, D(Cls), CStr, C|E|Er
947 Loads the class named S0 via the RDS. Invokes autoload and may raise an error
948 if the class is not defined.
950 | LdClsCachedSafe, D(Cls|Nullptr), CStr, NF
952 Loads the class whose name is S0 out of the RDS. If the class is not defined,
953 returns a null pointer.
955 | LdClsInitData, D(PtrToClsInitCell), S(Cls), C
957 Loads the pointer to the property initializer array for class S0.
959 | LookupClsRDSHandle, D(RDSHandle), S(Str), C
961 Look up the cached-class RDS handle for a given class name.
963 | DerefClsRDSHandle, D(Cls), S(RDSHandle), NF
965 Dereference an RDS handle that points to a cached class slot.
967 | LdCns, DCns, CStr, PRc
969 Load the constant named S0.
971 | LookupCns<T,constName>, DCns, CStr, E|Er|PRc
973 | LookupCnsE<T,constName>, DCns, CStr, E|Er|PRc
975 Load a constant via the RDS. Raises an undefined constant notice if the
976 constant cannot be defined. The E variant will instead throw a fatal error if
977 it cannot define the constant.
979 | LookupCnsU<T,constName,fallbackName>, DCns, CStr CStr, E|Er|PRc
981 Load an unqualified constant via the RDS, first by trying constName, then by
982 trying fallbackName. Raises a notice if neither can be found.
984 | LookupClsCns<T,className,constName>, DCns, NA, E|Er|PRc
986 Load a class constant for a class via the RDS, invoking autoload if it is not
987 defined. This instruction may raise an undefined constant error if autoload
988 cannot define the constant.
990 | LdClsMethodFCacheFunc<clsName,methodName>, D(Func|Nullptr), NA, NF
992 Loads the target cache entry for a forwarding call to clsName::methodName.
993 May be Nullptr, if the method does not exist or the cache hasn't been filled
996 | LookupClsMethodFCache<clsName,methodName>,
997 | D(Func|Nullptr), C(Cls) S(FramePtr),
1000 Lookup clsName::methodName in the forwarding class method cache. S0 should be
1001 the Class named by clsName and S1 should be the current vm frame pointer. May
1002 return Nullptr if lookup fails using a subset of the required lookup paths,
1003 indicating that a more complete lookup path should be taken. May throw if the
1004 method does not exist.
1006 | GetCtxFwdCallDyn<clsName,methodName>, D(Ctx), S(Ctx), PRc
1008 If S0 is a Cctx, return S0. If S0 is an object, check if clsName::methodName
1009 is a static method. If it is, return S0's class as a Ctx pointer. If not,
1010 return S0. If S0 is a Ctx, dynamically check if it is an object or Cctx at
1011 runtime and perform the operations described above.
1013 | GetCtxFwdCall, D(Ctx), S(Ctx) C(Func), PRc
1015 If S0 is an object and S1 is static, this opcode returns S0's class. If S0 is
1016 an object and S1 is not static, this opcode increfs S0 and returns it. If S0
1017 is a Cctx, this opcode returns S0.
1019 | LdClsMethodCacheFunc<clsName,methodName>, D(Func|Nullptr), NA, NF
1021 Loads the target cache entry for the method clsName::methodName. The result
1022 may be Nullptr, if the method does not exist or the cache hasn't been filled
1025 | LdClsMethodCacheCls<clsName,methodName>, D(Cctx), NA, NF
1027 Loads the target cache class context entry for a call to clsName::methodName
1028 from the current context. This instruction must only be used when the value
1029 is known to not be empty.
1031 | LookupClsMethodCache<clsName,methodName>, D(Func|Nullptr),
1035 Lookup a function in the class method targetcache. The class name and method
1036 name are clsName and methodName, respectively. S0 is the current vm frame
1037 pointer. Returns Nullptr if the method cannot be found using a subset of the
1038 required lookup paths, indicating that a more complete lookup path should be
1039 taken. May throw if the method does not exist.
1041 | LdClsMethod, D(Func), S(Cls) C(Int), C
1043 Load a Func* off of the class method table for S0, at offset S1 (in method
1046 | LookupClsMethod, ND, S(Cls) S(Str) S(StkPtr) S(FramePtr), E|Er
1048 Store a pointer to a class method into an activation record. S0 points to the
1049 class, S1 is the method name, S2 points to the activation record, and S3 is a
1050 pointer to the current frame (used to get the context). May throw or fatal if
1051 method is not accessible.
1053 | LdPropAddr<T>, DParamPtr(Prop), S(Obj) C(Int), C
1055 Load the address of the object property for S0 at offset S1 (in bytes) into
1056 D. T must be a subtype of PtrToPropGen.
1058 | LdGblAddr, D(PtrToGblGen), S(Str), B
1060 Loads a pointer to a global. S0 is the global's name. Branches to B if the
1061 global is not defined.
1063 | LdGblAddrDef, D(PtrToGblGen), S(Str), E
1065 Loads a pointer to a global. S0 is the global's name. Defines the global if
1066 it is not already defined.
1068 | LdClsPropAddrOrNull, D(PtrToSPropGen|Nullptr),
1069 | S(Cls) S(Str) C(Cls),
1072 Loads a pointer to a static class property. S0 points to the class, S1 is the
1073 property name, and S2 is the class representing the context of the code
1074 accessing the property. If class S0 does not have a visible and accessible
1075 static property named S1, then nullptr is returned.
1077 | LdClsPropAddrOrRaise, D(PtrToSPropGen), S(Cls) S(Str) C(Cls), C|E|Er
1079 Loads a pointer to a static class property. S0 points to the class, S1 is the
1080 property name, and S2 is the class representing the context of the code
1081 accessing the property. If class S0 does not have a visible and accessible
1082 static property named S1, throw a fatal error.
1084 | LdObjMethod<methodName,fatal>, ND, S(Cls) S(StkPtr), E|Er
1086 Stores a pointer to an object's method into an activation record. S0 points
1087 to the object's class, S1 points to the pre-live activation record. Caches
1088 the mapping in the target cache. If `fatal' is true, raises a fatal if the
1089 class does not have an accessible method with the given name and does not
1090 have a __call method; otherwise (if `fatal' is false), raises a warning and
1091 puts func that does nothing and returns null (SystemLib::s_nullFunc) on the
1094 | LdObjInvoke, D(Func), S(Cls), B
1096 Try to load a cached non-static __invoke Func from the Class in S0, or branch
1097 to block B if it is not present.
1099 | LdArrFuncCtx, ND, S(Arr) S(StkPtr) S(FramePtr), E|Er
1101 Try to load an array as a function context. This is for use translating
1102 FPushFunc when the callee is an array. This instruction attempts to populate
1103 a partially created ActRec pointed to by S1.
1105 | LdArrFPushCuf, ND, S(Arr) S(StkPtr) S(FramePtr), E|Er
1107 | LdStrFPushCuf, ND, S(Str) S(StkPtr) S(FramePtr), E|Er
1109 Try to resolve a method target for FPushCuf when the callee is an Arr or Str,
1110 respectively. These instructions mutate a partially created ActRec pointed to
1113 | LdObjClass, D(Cls), S(Obj), C
1115 Load the class out of the object in S0 and put it in D.
1117 | LdClsName, D(StaticStr), S(Cls), C
1119 Load the name of the Class* in S0.
1121 | LdFunc, D(Func), S(Str), E|CRc|Er
1123 Loads the Func whose name is S0. Fatal if the named function is not defined,
1124 and the function autoloader fails to define it.
1126 | LdFuncCached<funcName>, D(Func), NA, E|Er
1128 Loads the Func whose name is funcName from the RDS, invoking autoload if it
1129 not defined yet. Fatal if function autoloader fails to define it.
1131 | LdFuncCachedSafe<funcName>, D(Func|Nullptr), NA, NF
1133 Try to load the Func named funcName from the RDS. If the function is not
1134 defined, returns a null pointer.
1136 | LdFuncCachedU<funcName,fallbackName>, D(Func), NA, E|Er
1138 Try to load a Func named funcName from the RDS, if it isn't defined, try to
1139 load a Func named fallbackName. If that also isn't defined, invoke autoload.
1140 If this still doesn't result in a Func, raise a fatal error.
1142 | LdARFuncPtr, D(Func), S(StkPtr,FramePtr) C(Int), C
1144 Loads the m_func member of an ActRec. S0 is the base address, and S1 is an
1145 offset, such that S0 + S1 points to the base of the ActRec.
1147 | LdFuncNumParams, D(Int), S(Func), NF
1149 Returns the value of func->numParams().
1151 | LdStrLen, D(Int), S(Str), NF
1153 Load the length of the string in S0.
1155 | LdStaticLocCached<func,staticLocalName>, D(BoxedCell), NA, NF
1157 Load the address of the static local RefData from the targetcache for
1158 function `func' with the static local variable named `staticLocalName'.
1164 | AllocObj, DAllocObj, S(Cls), Er
1166 Allocates a new object of class S1.
1168 | RegisterLiveObj, ND, S(Obj), E
1170 When EnableObjDestructCall is on, we need to keep track of objects to be able
1171 to call their destructors when a request exists. This instruction is
1172 conditionally emitted to implement that.
1174 | CheckInitProps<class>, ND, NA, B|E
1176 Check if the properties for class are initialized and branches if not.
1178 | InitProps<class>, ND, NA, E|Er
1180 Calls the property initializer function (86pinit) for class. May throw.
1182 | CheckInitSProps<class>, ND, NA, B|E
1184 Check if static properties for class are initialized and branches if not.
1186 | InitSProps<class>, ND, NA, E|Er
1188 Calls the static property initializer function (86sinit) for class. May
1191 | NewInstanceRaw<class>, DAllocObj, NA, NF
1193 Allocates an instance of class.
1195 | InitObjProps<class>, ND, S(Obj), E
1197 Initializes properties of object S0.
1199 | ConstructInstance<class>, DAllocObj, NA, Er
1201 Call the custom instance constructor of an extension class.
1203 | CustomInstanceInit, DofS(0), S(Obj), Er
1205 Call the custom instance initializer of object S0.
1207 | NewArray, D(Arr), C(Int), PRc
1209 Allocate a new array with the expected capacity S0.
1211 | NewMixedArray, D(Arr), C(Int), PRc
1213 Allocate a new array in mixed mode with the expected capacity S0.
1215 | NewMIArray, D(Arr), C(Int), PRc
1217 Create a new MIArray.
1219 | NewMSArray, D(Arr), C(Int), PRc
1221 Create a new MSArray.
1223 | NewVArray, D(Arr), C(Int), PRc
1225 Create a new VArray.
1227 | NewLikeArray, D(Arr), S(Arr) C(Int), PRc
1229 Allocate a new array in the same mode as S0 and with expected capacity S1,
1230 unless S1 == 0, in which case the capacity is set to S0's size.
1232 | NewPackedArray, DArrPacked, S(StkPtr), E|PRc|CRc
1234 Allocate a new array by taking the top size elements off the stack given by
1235 S0. Note that this instruction assumes it can take the values from the stack
1236 without increfing them.
1238 | AllocPackedArray<size>, DArrPacked, NA, E|PRc
1240 Allocate a new uninitialized packed array with space for size elements in it.
1241 The array will be initialized with values using either InitPackedArray or
1242 InitPackedArrayLoop.
1244 | InitPackedArray<index>, ND, S(Arr) S(Gen), E|CRc
1246 Store the S1 into the slot at index in array S0. This instruction assumes
1247 that it doesn't have to incref the value being stored. Used to initialize an
1248 array allocated with AllocPackedArray.
1250 | InitPackedArrayLoop<size>, ND, S(Arr) S(StkPtr), E|CRc
1252 Store the top size elements on the stack given by S1 into the array S0.
1253 Assumes that the first element on the stack is the last element in the array.
1254 Used to initialize an array allocated with AllocPackedArray that was too big
1255 to use a series of InitPackedArray instructions.
1257 | NewStructArray<keys...>, D(Arr), S(StkPtr), E|PRc|CRc
1259 Allocate a new key/value array, given N immediate keys and taking the top N
1260 elements off the stack given by S0. This instruction assumes it can take the
1261 values from the stack without increfing them.
1263 | NewCol, D(Obj), C(Int) C(Int), PRc
1265 Create a new collection, with type S0 and size S1.
1267 | Clone, D(Obj), S(Obj), E|PRc|Er
1269 Allocate an object by cloning S0.
1274 | SpillFrame<numArgs,invName>, D(StkPtr),
1275 | S(StkPtr) S(Func,Nullptr) S(Ctx,Cls,Nullptr),
1280 S0 - caller stack pointer
1281 S1 - callee Func or nullptr
1282 S2 - object (for FPushObjMethod*), class (for FPushClsMethod*), context
1283 (for FPushClsMethodF), or nullptr (for FPushFunc*).
1285 Defines the fields for an activation record and writes them to the stack
1288 | CufIterSpillFrame<numArgs,iterId>, D(StkPtr),
1289 | S(StkPtr) S(FramePtr),
1294 S0 - caller stack pointer
1295 S1 - caller frame pointer
1297 Defines the fields for an activation record using data from the iterator
1298 iterId, and writes them to the stack pointed to by S1
1300 | FreeActRec, D(FramePtr), S(FramePtr), NF
1302 Load the saved frame pointer from the activation record pointed to by S0 into
1305 | DefInlineFP<func,retBCOff,retSPOff>, D(FramePtr),
1306 | S(StkPtr) S(StkPtr) S(FramePtr),
1309 Defines a frame pointer for an inlined function. S0 is a StkPtr that points
1310 to the ActRec for the callee (i.e. after parameters have been popped). S1 is
1311 a StkPtr that represents what the inlined function will return to (i.e. it
1312 points to the stack after the ActRec in S0 is popped).
1314 `func' is the function being inlined. `retBCOff' and `retSPOff' represent
1315 what the bytecode and stack offsets should be after the FCall instruction in
1318 This instruction is primarily used to represent a frame in the IR in a way
1319 that allows us to eliminate it entirely. When it cannot be eliminated (or if
1320 it is pushed into an unlikely path) it performs callee-side responsibilities
1321 for setting up an activation record (i.e. setting the return ip and m_soff,
1322 storing the frame pointer into D).
1324 The caller frame pointer is passed as S2. This is used to keep track of the
1325 call chain of inlined functions for simplification and dead code elimination.
1327 | InlineReturn, ND, S(FramePtr), E
1329 Unlinks a frame constructed by DefInlineFP.
1331 | CallArray, D(StkPtr), S(StkPtr) S(FramePtr), E|CRc
1333 Invoke function corresponding to the current FPI with array args. S0 points
1334 to the stack resulting after the ActRec for the function and the array of its
1335 arguments is pushed. CallArray pops the array off the stack, pushes the
1336 elements of the array as arguments, and invokes the function in the ActRec.
1338 | Call<numParams,returnOff,funcd,destroyLocals>, D(StkPtr),
1339 | S(StkPtr) S(FramePtr),
1342 Transfer control to a callee, based on the pre-live activation record and set
1343 of args on the stack pointed to by S0. S1 is the current caller frame
1344 pointer. The `funcd' in the extra data is a Func* for the callee if we know
1345 the callee statically.
1347 | NativeImpl<func>, ND, S(FramePtr) S(StkPtr), E
1349 Execute a call to the native builtin specified by the current function. S0
1350 and S1 should be the current vmfp and vmsp, respectively.
1352 | CallBuiltin<T>, DBuiltin, S(FramePtr) S(StkPtr) SVar(PtrToGen,Gen), E|Er|PRc
1354 Call builtin function with N arguments. S0 and S1 should be the current vmfp
1355 and vmsp, respectively.
1357 The source and destination types correspond to C++ parameter and return types
1360 C++ type HHIR type Position
1361 ----------------- --------- --------
1362 bool Bool source, destination
1363 int64_t Int source, destination
1364 double Dbl source, destination
1365 const String& PtrToString source
1366 const Array& PtrToArray source
1367 const Object& PtrToObject source
1368 const Variant& PtrToGen source
1369 Variant& PtrToGen source (ref param)
1370 String {Str|InitNull} destination
1371 Array {Arr|InitNull} destination
1372 Object {Obj|InitNull} destination
1373 Variant {Gen-UninitNull} destination
1375 | LdRetAddr, D(RetAddr), S(FramePtr), NF
1377 Load the return address off of the activation record pointed to by S0. The
1378 return address D is normally provided to a RetCtrl. Between a LdRetAddr and a
1379 RetCtrl, a FreeActRec is normally emitted to free the activation record S0.
1380 This is the reason why LdRetAddr is a separate instruction from RetCtrl.
1382 | RetCtrl, ND, S(StkPtr) S(FramePtr) S(RetAddr), T|E
1384 Ensure that S0 is stored in rVmSp and S1 is stored in rVmFp and then execute
1385 a hardware procedure-return using the return address specified by S2.
1387 | StRetVal, ND, S(FramePtr) S(Gen), E|CRc
1389 Writes the value in S1 to the return value slot on the activation record
1392 | RetAdjustStack, D(StkPtr), S(FramePtr), E
1394 Loads the new VM stack pointer into the destination. S0 is a pointer to the
1395 current activation record.
1397 | ReleaseVVOrExit, ND, S(FramePtr), B|E
1399 Loads the VarEnv slot off the ActRec pointed to by S0. If it is null, does
1400 nothing. If it is an ExtraArgs, deallocates the ExtraArgs structure.
1401 Otherwise jumps to block B.
1403 | GenericRetDecRefs, ND, S(FramePtr), E
1405 Does decrefs of all the current function's locals, where S0 is a pointer to
1406 the relevant activation record.
1408 Semantically similar to a series of DecRefLoc.
1414 | StMem, ND, S(PtrToGen) C(Int) S(Gen), E|CRc
1416 Store S2 into the location S0 + S1 (in bytes).
1418 | StProp, ND, S(Obj) C(Int) S(Gen), E|CRc
1420 Store S2 into the location S0 + S1 (in bytes).
1422 | StElem, ND, S(PtrToCell) S(Int) S(Cell), E|CRc
1424 Store S2 into the location given by the index S1 from base pointer S0. The
1425 index in S1 is the number of bytes from the base in S0.
1427 | StLoc<localId>, ND, S(FramePtr) S(Gen), E|CRc
1429 Store S1 to local number localId on the frame pointed to by S0.
1431 | StLocNT<localId>, ND, S(FramePtr) S(Gen), E|CRc
1433 Store S1 to local number localId on the frame pointed to by S0, without
1436 | StLocPseudoMain<localId>, ND, S(FramePtr) S(Gen), E|CRc
1438 Behaves just like StLoc, except the hard requirement that it is only emitted
1439 for pseudo-mains. We don't optimize StGbl the same way as StLoc, as we need
1440 intraprocedural analysis to know whether the store is truly dead.
1442 | StRef, ND, S(BoxedCell) S(Cell), E|CRc
1444 Store the value in S1 into the RefData pointed to by S0. Stores the
1445 RefData::m_type also.
1447 | SpillStack, D(StkPtr), S(StkPtr) C(Int) SVar(StackElem), CRc
1449 SpillStack synchronizes the virtual execution stack with the physical stack
1450 by storing a variadic list of SSATmps to the physical stack.
1454 S0 - current stack pointer
1456 S1 - stack deficit; indicates the number of elements that need to be
1457 logically popped before the variadic list is pushed
1459 S2... - variadic list of elements to spill, with values representing
1460 cells. A temp with type None means to keep the previous value on
1463 | ExceptionBarrier, D(StkPtr), S(StkPtr), E
1465 An essential instruciton that consumes and produces a stack. This is used in
1466 places that need to ensure the stack goes to memory and cannot be DCE'd.
1467 Mostly unnecessary now (catch traces do the same thing), but there are a few
1468 locations that are not updated.
1474 | SyncABIRegs, ND, S(FramePtr) S(StkPtr), E
1476 Ensures the cross-tracelet ABI registers are in a consistent state in
1477 preparation for an instruction that may leave the trace.
1479 | EagerSyncVMRegs, ND, S(FramePtr) S(StkPtr), E
1481 Sync the given vmfp and vmsp to their in-memory locations.
1483 | ReqBindJmp<bcOff,transFlags>, ND, NA, T|E
1485 Emit a jump to a REQ_BIND_JMP service request to the target offset bcOff.
1487 | ReqRetranslate<transFlags>, ND, NA, T|E
1489 Emit a jump to a service request that will chain to a retranslation of this
1492 This instruction is used in exit traces for a type prediction that occurs at
1493 the first bytecode offset of a tracelet.
1495 | ReqRetranslateOpt<transId,bcOff>, ND, NA, T|E
1497 Emit a service request to retranslate, with a higher optimization gear,
1498 translation transID, which starts at bcOff. This instruction is used in exit
1499 traces that trigger profile-guided optimizations.
1501 | ReqBindJmpGt, ND, S(Gen) S(Gen), T|E
1503 | ReqBindJmpGte, ND, S(Gen) S(Gen), T|E
1505 | ReqBindJmpLt, ND, S(Gen) S(Gen), T|E
1507 | ReqBindJmpLte, ND, S(Gen) S(Gen), T|E
1509 | ReqBindJmpEq, ND, S(Gen) S(Gen), T|E
1511 | ReqBindJmpNeq, ND, S(Gen) S(Gen), T|E
1513 | ReqBindJmpGtInt, ND, S(Int) S(Int), T|E
1515 | ReqBindJmpGteInt, ND, S(Int) S(Int), T|E
1517 | ReqBindJmpLtInt, ND, S(Int) S(Int), T|E
1519 | ReqBindJmpLteInt, ND, S(Int) S(Int), T|E
1521 | ReqBindJmpEqInt, ND, S(Int) S(Int), T|E
1523 | ReqBindJmpNeqInt, ND, S(Int) S(Int), T|E
1525 | ReqBindJmpSame, ND, S(Gen) S(Gen), T|E
1527 | ReqBindJmpNSame, ND, S(Gen) S(Gen), T|E
1529 | ReqBindJmpInstanceOfBitmask, ND, S(Cls) CStr, T|E
1531 | ReqBindJmpNInstanceOfBitmask, ND, S(Cls) CStr, T|E
1533 | ReqBindJmpZero, ND, S(Int,Bool), T|E
1535 | ReqBindJmpNZero, ND, S(Int,Bool), T|E
1537 Test the condition based on the Jmp* op of similar name, and then emit a pair
1538 of smashable jumps to a REQ_BIND_JMPCC_FIRST service request.
1540 | SideExitJmpGt, ND, S(Gen) S(Gen), E
1542 | SideExitJmpGte, ND, S(Gen) S(Gen), E
1544 | SideExitJmpLt, ND, S(Gen) S(Gen), E
1546 | SideExitJmpLte, ND, S(Gen) S(Gen), E
1548 | SideExitJmpEq, ND, S(Gen) S(Gen), E
1550 | SideExitJmpNeq, ND, S(Gen) S(Gen), E
1552 | SideExitJmpGtInt, ND, S(Int) S(Int), E
1554 | SideExitJmpGteInt, ND, S(Int) S(Int), E
1556 | SideExitJmpLtInt, ND, S(Int) S(Int), E
1558 | SideExitJmpLteInt, ND, S(Int) S(Int), E
1560 | SideExitJmpEqInt, ND, S(Int) S(Int), E
1562 | SideExitJmpNeqInt, ND, S(Int) S(Int), E
1564 | SideExitJmpSame, ND, S(Int) S(Int), E
1566 | SideExitJmpNSame, ND, S(Int) S(Int), E
1568 | SideExitJmpInstanceOfBitmask, ND, S(Cls) CStr, E
1570 | SideExitJmpNInstanceOfBitmask, ND, S(Cls) CStr, E
1572 | SideExitJmpZero, ND, S(Int,Bool), E
1574 | SideExitJmpNZero, ND, S(Int,Bool), E
1576 Test the condition based on the Jmp* op of similar name, and then emit a
1577 smashable jump to a REQ_BIND_SIDE_EXIT service request.
1579 | SideExitGuardLoc<T,locId,takenOff>, ND, S(FramePtr), E
1581 Test the type of a local, and if it fails jump to a side exit service
1584 | SideExitGuardStk<T,stackOff,takenOff>, D(StkPtr), S(StkPtr), E
1586 Test the type of a stack cell, and if it fails jump to a side exit service
1590 12. Refcounting and copies
1593 | Mov, DofS(0), S(Top), C|P
1595 Defines D as S0. May imply register-to-register moves at code generation
1596 time. Does not imply an incref or any other manipulation of S0.
1598 | TrackLoc<localId>, ND, S(Gen), E
1600 Defines localId as having value given by S0. This does not generate code; it
1601 is used by the translator to track values that are stored in locals. It can
1602 be thought of as a store (which does not physically store anything).
1604 | IncRef, ND, S(Gen), E
1606 If S0 is a refcounted type, increment its refcount.
1608 | IncRefCtx, ND, S(Ctx), E
1610 If the Ctx in S0 is a $this pointer, IncRef it.
1612 | DecRefLoc<localId>, ND, S(FramePtr), E
1614 DecRef the local given by localId on the frame S0.
1616 | DecRefStack<T,offset>, ND, S(StkPtr), E
1618 DecRef a value of type T at offset on the stack pointed to by S0.
1620 | DecRefThis, ND, S(FramePtr), E
1622 DecRef the $this pointer in the ActRec S0, if it had one. Does nothing if
1623 there was a class context or null $this on the ActRec.
1625 | DecRef, ND, S(Gen), E|K|CRc
1627 Decrease the reference count of S0 by one, and call a destructor for types
1628 that require it if it goes to zero.
1630 Note that although DecRef takes a Gen, we don't allow it to use information
1631 about the inner types of a BoxedCell. This is because we don't guard on the
1632 inner types of a BoxedCell except when doing LdRef. For any S0 that is a
1633 strict subtype of BoxedCell, the DecRef must just decref it as if it were a
1636 | DecRefMem, ND, S(PtrToGen) C(Int), E|CRc
1638 Decref the value pointed to by S0 at offset S1 (in bytes), calling any
1639 appropriate destructor if the refcount goes to zero.
1641 | DecRefNZ, ND, S(Gen), E|CRc
1643 Decrease the reference count of S0 by one, do not check if it goes to zero.
1644 This instruction can be used for more efficient code when it is provable that
1645 the reference count cannot go to zero.
1647 | TakeRef, ND, S(Gen), NF
1649 Produce reference, but do not modify the reference count. Used to inform
1650 refcount optimizer about implicitly owned references.
1656 | DefFP, D(FramePtr), NA, E
1658 Creates a temporary D representing the current vm frame pointer.
1660 | DefSP<stackOff>, D(StkPtr), S(FramePtr), E
1662 Creates a temporary D representing the current vm stack pointer. S0 is a
1663 pointer to the current frame. The 'stackOff' is the logical offset between S0
1664 and the stack pointer, but in the case of generators this is not the
1665 physical offset at runtime.
1667 This instruction is used at the beginning of tracelets to represent the state
1668 of the stack on entry and does not emit code.
1670 | ReDefSP<offset,spansCall>, D(StkPtr), S(StkPtr) S(FramePtr), NF
1672 Re-define a stack in terms of a frame pointer S1 and an offset, putting the
1673 resulting pointer in D. The resulting stack is assumed to give the same view
1674 as S0, which is a previous stack pointer. (I.e. for getStackValue we just
1677 This instruction is used when entering or "returning" from an inlined call.
1678 The one used on entry will generally be DCE'd when the actrec can be
1679 eliminated. The one on exit is only needed until TODO(#2288359).
1681 The spansCall boolean is true if there is possibly a Call instructions
1682 between the definition of S0 and this instruction.
1684 | Count, D(Int), S(Cell), Er
1686 Computes the number of elements in S0. The count of an array is the number of
1687 elements it contains, without recursing into containers in the array.
1688 Subtypes of Bool|Int|Dbl|Str|Res have a count of 1, subtypes of Null have a
1689 count of 0. The count of objects that implement the Countable interface is
1690 computed by returning the value of their count method. Objects that do not
1691 implement Countable have a count of 1.
1693 | CountArray, D(Int), S(Arr), NF
1695 | CountArrayFast, D(Int), S(Arr), NF
1697 | CountCollection, D(Int), S(Obj), NF
1699 Computes the number of elements in S0 using the same definition as Count, but
1700 with a restriction on the input type.
1702 CountArray expects any array. CountArrayFast expects an array whose kind is not
1703 kGlobalsKind. CountCollection expects a collection object.
1707 Does nothing. It's sometimes useful for the simplifier to insert one of these
1708 in the instruction stream.
1714 | VerifyParamCls, ND, S(Cls) S(Cls|Nullptr) C(Int) C(Int), E|Er
1716 Verify parameter type for classes or traits. If S0 does not extend (if S1 is
1717 a class) or implement (if S1 is an interface) S1, this instruction will raise
1718 a recoverable fatal error describing the type mismatch.
1720 | VerifyParamCallable, ND, S(Gen) C(Int), E|Er
1722 If S0 is not callable, as defined by the php function is_callable, this
1723 instruction will raise a recoverable fatal error describing the type
1726 | VerifyParamFail, ND, C(Int), E|Er
1728 Assumes that parameter number S0 in the current function has failed its
1729 typehint and raises a recoverable fatal error describing the type mismatch.
1731 | VerifyRetCallable, ND, S(Gen), E|Er
1733 Verify a return type hint.
1735 | VerifyRetCls, ND, S(Cls) S(Cls|Nullptr) C(Int) S(Cell), E|Er
1737 Verify a return type hint.
1739 | VerifyRetFail, ND, S(Gen), E|Er
1741 Failure to verify a return type hint.
1743 | RaiseUninitLoc<localId>, ND, S(Str), E|Er
1745 Raise a notice for an uninitialized local variable.
1747 | WarnNonObjProp, ND, NA, E|Er
1749 Raise a warning for property access on a non-object base.
1751 | RaiseUndefProp, ND, S(Obj) CStr, E|Er
1753 Raise a notice for an undefined property named S1 on the class of S0.
1755 | RaiseError, ND, S(Str), E|T|Er
1757 Raises a fatal error with the text in S0 as its message.
1759 | RaiseWarning, ND, S(Str), E|Er
1761 Raises a warning with the text in S0 as its message.
1763 | RaiseNotice, ND, S(Str), E|Er
1765 Raises a notice with the text in S0 as its message.
1767 | RaiseArrayIndexNotice, ND, S(Int), E|Er
1769 Raises a notice that S0 is an undefined index for an array.
1771 | ClosureStaticLocInit, D(BoxedCell), CStr S(FramePtr) S(Cell), E
1773 Get boxed value to initialize static local named S0 in frame S1, where S1
1774 must be either a closure or generatorFromClosure function. If the static
1775 local has not yet been initialized, its value will be set to S2.
1777 | StaticLocInitCached, ND, S(BoxedCell) S(Cell), E
1779 Assuming S0 is an uninitialized static local RDS slot, initialize it by
1780 setting it to the value of S1.
1782 | PrintStr, ND, S(Str), E|Er|CRc
1784 | PrintInt, ND, S(Int), E|Er|CRc
1786 | PrintBool, ND, S(Bool), E|Er|CRc
1788 Print for various types.
1790 | ConcatIntStr, D(Str), S(Int) S(Str), Er|PRc
1792 Concatenate S0 and S1 after converting S0 to String.
1794 | ConcatStrInt, D(Str), S(Str) S(Int), Er|CRc|PRc
1796 Concatenate S0 and S1 after converting S1 to String.
1798 | ConcatStrStr, D(Str), S(Str) S(Str), Er|CRc|PRc
1800 Concatenate S0 and S1.
1802 | ConcatCellCell, D(Str), S(Cell) S(Cell), Er|CRc|PRc
1804 Concatenate S0 and S1 after converting them to strings in a way that obeys
1805 php semantics. (Calling object __toString methods, etc.)
1807 | ConcatStr3, D(Str), S(Str) S(Str) S(Str), Er|CRc|PRc
1809 Concatenate S0, S1, and S2.
1811 | ConcatStr4, D(Str), S(Str) S(Str) S(Str) S(Str), Er|CRc|PRc
1813 Concatenate S0, S1, S2, and S3.
1815 | AddElemStrKey, D(Arr), S(Arr) S(Str) S(Cell), Er|CRc|PRc
1817 Add S2 to the array S0 for the key S1, and return the resulting array.
1819 | AddElemIntKey, D(Arr), S(Arr) S(Int) S(Cell), Er|CRc|PRc
1821 Add S2 to the array S0 for the key S1, and return the resulting array.
1823 | AddNewElem, D(Arr), S(Arr) S(Cell), Er|CRc|PRc
1825 Add S1 as a new element to the array S0. (Note: S1 must actually be a
1826 subtype of InitCell for array invariants, but we can't assert this yet in the
1827 IR because many eval stack slots are not entirely typed wrt initness right
1830 | ArrayAdd, D(Arr), S(Arr) S(Arr), Er|CRc|PRc
1832 Has the effects of the php + operator on the two source arrays.
1834 | AKExists, D(Bool), S(Cell) S(Cell), NF
1836 Has the effects of array_key_exists(S0, S1). Note that S0 does not need to be
1837 an array---if it is an Obj the ArrayAccess API will be used, etc.
1839 | ArrayIdx, D(Cell), S(Arr) S(Int,Str) S(Cell), E|PRc
1841 Checks if S0 contains the key S1, and returns the result if found. Otherwise
1844 | GenericIdx, D(Cell), S(Cell) S(Cell) S(Cell), E|PRc|Er
1846 Checks if S0 contains the key S1, and returns the result if found. Otherwise
1847 S2 is returned. If S0 does not support array or indexed access S2 is
1850 | LdBindAddr<SrcKey>, D(TCA), NA, NF
1852 Creates a service request to bind the given target address. Returns a TCA
1853 pointing either to the service request (before the service request is
1854 satisfied) or to the native code for the given target address (once the
1855 service request is satisfied).
1857 | LdSwitchDblIndex, D(Int), S(Dbl) S(Int) S(Int), NF
1859 | LdSwitchStrIndex, D(Int), S(Str) S(Int) S(Int), CRc
1861 | LdSwitchObjIndex, D(Int), S(Obj) S(Int) S(Int), CRc|Er
1863 These instructions are used to determine the target of a switch statement
1864 with target range [S1:S1 + S2), when invoked with the value S0. They call
1865 helper functions to check whether S0 is an numeric integer in the range
1866 [S1:S1 + S2), and if so return the value S1 - (Int)S0. Else, they return the
1867 target of the default target, S2 + 1.
1869 | LdSSwitchDestFast, D(TCA), S(Gen), NF
1871 | LdSSwitchDestSlow, D(TCA), S(Gen), E|Er
1873 Load string switch destinations (two different compilation strategies).
1875 | InterpOne<T,bcOff,numPopped,numPushed>, D(StkPtr),
1876 | S(StkPtr) S(FramePtr),
1879 Call the interpreter implementation function for one opcode. S0 and S1 are,
1880 respectively, the VM stack and frame pointers before this instruction. T is
1881 only present if the instruction pushes to the stack, in which case it is the
1882 type of the top stack element after the call. `bcOff' is the bytecode
1883 offset. `numPopped' is the number of stack cells consumed by the instruction,
1884 and `numPushed' is the number of stack cells produced by the
1885 instruction. This instruction returns the updated VM stack pointer.
1887 | InterpOneCF<T,bcOff,numPopped,numPushed>, D(StkPtr),
1888 | S(StkPtr) S(FramePtr),
1891 Similar to InterpOne, but for instructions that may modify vmpc.
1893 | OODeclExists<kind>, D(Bool), S(Str) S(Bool), E|Er
1895 Returns a bool indicating whether the class, interface, or trait named by S0
1896 exists. Invokes autoload if S1 is true.
1899 15. Generators & Closures
1902 | StClosureCtx, ND, S(Obj) S(Ctx,Nullptr), CRc|E
1904 Store the context represented by S1 into the closure object S0. S1 may be a
1905 Nullptr when there is no context (i.e. the closure is being used in a
1908 | StClosureFunc<func>, ND, S(Obj), E
1910 Store the Func* clone that should be used for calling this closure into the
1913 | StClosureArg<offsetBytes>, ND, S(Obj) S(Gen), CRc|E
1915 Store one of the closure environment arguments (i.e. from the closure's use
1916 clause) from S1 into the closure object S0.
1918 | CreateCont, D(Obj), S(FramePtr) C(Int) S(TCA,Nullptr) C(Int), E|PRc
1920 Create a Generator object and suspend the ActRec provided by S0 into its
1921 embedded ActRec, allocating S1 slots for locals/iterators. Set the native
1922 resume address to S2 and resume offset to S3.
1924 | CreateAFWH, D(Obj),
1925 | S(FramePtr) C(Int) S(TCA,Nullptr) C(Int) S(Obj),
1928 Create an AsyncFunctionWaitHandle object and suspend the ActRec provided by
1929 S0 into its embedded ActRec, allocating S1 slots for locals/iterators. Set
1930 the native resume address to S2, resume offset to S3, and mark it blocked on
1931 non-finished child S4.
1933 | CreateSSWH, D(Obj), S(Cell), CRc|PRc
1935 Call c_StaticWaitHandle::CreateSucceededVM.
1937 | AFWHPrepareChild, ND, S(FramePtr) S(Obj), E|Er
1939 Prepare unfinished WaitableWaitHandle object specified by S1 for getting
1940 awaited by an AsyncFunctionWaitHandle object specified by its ActRec
1943 Injects S1 into the currently running scheduler instance and performs
1944 cross-scheduler and intra-scheduler cycle detection. Throws if the
1945 dependency cannot be established.
1947 | ContEnter, D(StkPtr),
1948 | S(StkPtr) S(FramePtr) S(FramePtr) S(TCA) C(Int),
1951 Enters a generator body. S0 is the current stack pointer pointing to fully
1952 spilled stack, S1 is the current frame pointer, S2 is the generator frame
1953 pointer embedded in the Generator object, S3 is the address to jump to,
1954 and S4 is the bytecode offset in the caller to return to when the generator
1955 suspends or returns.
1957 | ContPreNext, ND, S(Obj) C(Bool), B|E
1959 Performs operations needed for the next() method of Generator object S0.
1960 If the generator is already running or finished, or it was not started yet
1961 and the S1 check-started flag is set, the branch B is taken. Otherwise,
1962 the generator is marked as running.
1964 | ContStartedCheck, ND, S(Obj), B|E
1966 Checks if the Generator object S0 has started, and if not branches to
1969 | ContValid, D(Bool), S(Obj), E
1971 Return true if a generator is not done, false otherwise.
1973 | ContArIncKey, ND, S(FramePtr), E
1975 Special-case key update for generator, ActRec of which is S0, which
1976 increments the key of a generator if that generator's key is an Int.
1977 This will cause undefined behavior if the generator's key is not an Int.
1979 | ContArIncIdx, D(Int), S(FramePtr), E
1981 Increment the internal index in the Generator in S0, and return the new index
1984 | ContArUpdateIdx, ND, S(FramePtr) S(Int), E
1986 Updates the internal index of generator with S1 if necessary, i.e. if S1
1987 is larger than the index. S0 is the pointer to the embedded ActRec.
1989 | LdContActRec, D(FramePtr), S(Obj), C
1991 Loads the Generator object's ActRec, given a pointer to the generator
1994 | LdContResumeAddr, D(TCA), S(Obj), E
1996 Load the resume addr from the Generator in S0.
1998 | StContArState<state>, ND, S(FramePtr), E
2000 Change the state of the Generator object which has frame pointer S0.
2002 | StContArResume<offset>, ND, S(FramePtr) S(TCA), E
2004 Store the resume address S1 into the Generator whose ActRec is given by S0,
2005 marking the offset to resume at as `offset'.
2007 | LdContArValue, DParam, S(FramePtr), PRc
2009 Loads 'value' from the Generator object ActRec of which is S0.
2011 | StContArValue, ND, S(FramePtr) S(Cell), E|CRc
2013 Stores 'value' into the Generator object ActRec of which is S0. S1 is the
2016 | LdContArKey, DParam, S(FramePtr), PRc
2018 Loads 'key' from the Generator object ActRec of which is S0.
2020 | StContArKey, ND, S(FramePtr) S(Gen), E|CRc
2022 Stores 'key' into the Generator object ActRec of which is S0. S1 is the
2025 | StAsyncArSucceeded, ND, S(FramePtr), E
2027 Mark the AsyncFunctionWaitHandle object whose ActRec is given by S0 as
2030 | StAsyncArResume<offset>, ND, S(FramePtr) S(TCA), E
2032 Store the resume address S1 into the AsyncFunctionWaitHandle whose ActRec is
2033 given by S0, marking the offset to resume at as `offset'.
2035 | StAsyncArResult, ND, S(FramePtr) S(Cell), E|CRc
2037 Stores result into the AsyncFunctionWaitHandle object ActRec of which is S0.
2040 | LdAsyncArParentChain, D(ABC), S(FramePtr), NF
2042 Loads the first parent of the AsyncFunctionWaitHandle object ActRec of which
2045 | AFWHBlockOn, ND, S(FramePtr) S(Obj), E|CRc
2047 Establish dependency between parent AsyncFunctionWaitHandle object, whose
2048 ActRec is given by S0, and child WaitableWaitHandle object referenced by S1.
2050 | ABCUnblock, ND, S(ABC), E
2052 Calls AsioBlockableChain::Unblock.
2054 | LdWHState, D(Int), S(Obj), NF
2056 Loads the state of the WaitHandle in S0, which is a value from the wait
2057 handle states in ext_asio.h. This instruction has undefined behavior if S0 is
2060 | LdWHResult, D(Cell), S(Obj), NF
2062 Loads the result of the WaitHandle in S0. This instruction has undefined
2063 behavior if S0 is not a WaitHandle, or if S0 is not finished.
2065 | LdAFWHActRec, D(FramePtr), S(Obj), C
2067 Loads the AsyncFunctionWaitHandle object's ActRec, given a pointer to the
2068 AsyncFunctionWaitHandle object in S0.
2070 | LdResumableArObj, D(Obj), S(FramePtr), C
2072 Loads the Resumable object, given a Resumable's frame pointer in S0.
2075 16. Debugging, instrumentation, and profiling
2077 | IncStat, ND, C(Int) C(Int) C(Bool), E
2079 Increment stat counter. S0 is the implementation defined stat counter index,
2080 S1 is the amount to increment the counter (may be negative), and S2 is a
2081 'force' flag. This opcode becomes a noop iff (force == false and runtime
2082 stats are not enabled) at translation time.
2084 | IncTransCounter, ND, NA, E
2086 Increment a translation counter. This is probably something related to TC
2089 | IncStatGrouped, ND, CStr CStr C(Int), E
2091 Adds the value S2 to the counter named S1, in the category S0.
2093 | IncProfCounter<TransID>, ND, NA, E
2095 Increment the profiling counter associated with translation TransID.
2097 | DbgAssertRefCount, ND, S(Counted,StaticStr,StaticArr), E
2099 Assert that S0 has a valid refcount. S0 must be a type with a valid (counted
2100 or static) _count field. If S0's count is implausible then execute a hardware
2101 trap instruction (int3 on x64).
2103 | DbgAssertPtr, ND, S(PtrToGen), E
2105 Assert that S0 points to plausible TypedValue. If the TypedValue is a type
2106 with a _count field, check that the count field is plausible using the same
2107 logic as DbgAssertRefCount. Internally this uses always_assert(); failures
2108 cause an abort (whatever always_assert does).
2110 | DbgAssertType<T>, ND, S(Cell), E
2112 Assert that S0 is of type T at runtime. If the assertion fails, execution is
2113 aborted via a hardware exception.
2115 | DbgAssertRetAddr, ND, NA, E
2117 Assert that the current hardware return address is the expected value. If the
2118 assertion fails, execution is aborted via a hardware exception.
2120 | RBTrace, ND, NA, E
2122 Ring buffer tracing.
2124 | ZeroErrorLevel, D(Int), NA, E
2126 | RestoreErrorLevel, ND, S(Int), E
2128 Helper instructions for fast implementation of the PHP error silencing
2135 | IterInit<IterData>, D(Bool), S(Arr,Obj) S(FramePtr), Er|E|CRc
2137 | IterInitK<IterData>, D(Bool), S(Arr,Obj) S(FramePtr), Er|E|CRc
2139 | WIterInit<IterData>, D(Bool), S(Arr,Obj) S(FramePtr), Er|E|CRc
2141 | WIterInitK<IterData>, D(Bool), S(Arr,Obj) S(FramePtr), Er|E|CRc
2143 | MIterInit<T,IterData>, D(Bool), S(BoxedCell) S(FramePtr), Er|E
2145 | MIterInitK<T,IterData>, D(Bool), S(BoxedCell) S(FramePtr), Er|E
2147 <IterData> consists of three indices, iterId, keyId and valId. iterId is
2148 the index of the iterator variable, keyId and valId are indices of local
2151 Initializes the iterator variable whose index is given by iterId.
2152 This instruction creates the appropriate iterator for the array or object that
2153 S0 references, and rewinds the new iterator to its start. S0 points to the
2154 stack frame containing the iterator and local variables with the indices
2155 iterId, keyId and valId.
2157 If the new iterator is at its end (i.e., has no elements to iterate over),
2158 this instruction decrements the refcount of S0 and returns false; otheriwse,
2159 it stores a reference to S0 in the new iterator and returns true. If the
2160 iterator is not at its end, then this instruction stores the iterator's first
2161 value (and key) into the local variable with index valId (and keyId,
2164 The IterInit and IterInitK instructions always copy the array element by
2167 The WIterInit and WIterInitK instructions copy referenced array elements by
2168 reference, and non-referenced array elements by value.
2170 The MIterInit and MIterInitK instructions always copy the array element by
2171 reference, and take a type parameter indicating the inner type of S0. (This
2172 must have been proven via guards prior to running this opcode.) Right now T
2175 This instruction has the ConsumesRC property because it either decrements the
2176 reference count of S0 or stores a reference to S0 into the new iterator.
2178 | IterNext<IterData>, D(Bool), S(FramePtr), Er|E
2180 | IterNextK<IterData>, D(Bool), S(FramePtr), Er|E
2182 | WIterNext<IterData>, D(Bool), S(FramePtr), Er|E
2184 | WIterNextK<IterData>, D(Bool), S(FramePtr), Er|E
2186 | MIterNext<IterData>, D(Bool), S(FramePtr), E
2188 | MIterNextK<IterData>, D(Bool), S(FramePtr), E
2190 <IterData> consists of three indices, iterId, keyId and valId. iterId is
2191 the index of the iterator variable, keyId and valId are indices of local
2192 variables. S0 points to the stack frame containing the iterator and local
2193 variables with the indices iterId, keyId and valId.
2195 Advances the iterator variable whose index is given by iterId.
2197 If the iterator has reached the end, this instruction frees the iterator
2198 variable and returns false; otherwise, it returns true. If the iterator has
2199 not reached its end, then this instruction stores the iterator's next value
2200 (and key) into the local variable with index valId (and keyId, respectively).
2202 The IterInit and IterInitK instructions always copy the array element by
2203 value. The WIterInit and WIterInitK instructions copy referenced array
2204 elements by reference, and non-referenced array elements by value. The
2205 MIterNext and MIterNextK instructions always copy the array element by
2208 | IterFree, ND, S(FramePtr), E
2210 | MIterFree, ND, S(FramePtr), E
2212 Free the iterator variable whose index is given by S1 in the stack frame
2215 | DecodeCufIter<iterId>, D(Bool), S(Arr,Obj,Str) S(FramePtr), Er|E
2217 Decode S0 as a callable, and write the decoded values to the iterator
2218 specified by IterId. Returns true iff it successfully decoded the callable.
2219 Does not raise warnings, or throw exceptions.
2221 | CIterFree<iterId>, ND, S(FramePtr), E
2223 Free the iterator variable whose index is given by IterId in the stack frame
2227 18. Member instruction support
2230 | DefMIStateBase, D(PtrToMISGen), NA, NF
2232 Declares a base register for MInstrState. Currently this is always %rsp.
2234 | LdMIStateAddr, DofS(0), S(PtrToMISGen) C(Int), C
2236 Load an MInstrState address. Returns a pointer to (S0 + S1) with the same
2237 type as S0. S0 must be the output of a DefMIStateBase.
2239 All of the remaining opcodes in this section are simple wrappers around helper
2240 functions (specified in S0) to perform the corresponding vector operation. If
2241 S1 is a ConstCls it represents the context class for the operation.
2243 SetElem, SetProp, and SetNewElem are used to implement part of the SetM hhbc
2244 opcode, which almost always pushes its first stack input or a CountedStr as its
2245 stack result. The combinations of input types that cause SetM to push anything
2246 other than those two values are vanishingly rare in correct PHP programs, so
2247 these three instructions have been optimized for the common cases. SetNewElem
2248 and SetProp have no destination, allowing the compiler to predict that the
2249 SetM's output will be the same as its input (and optimize accordingly). If that
2250 turns out to not be the case at runtime, the instruction will throw an
2251 InvalidSetMException. The exception will hold a Cell containing the value the
2252 SetM should push on the stack instead of its input value. The runtime is
2253 responsible for catching this exception, finishing execution of the SetM
2254 instruction, pushing the value from the exception on the stack, and proceeding
2255 as appropriate (most likely with a side exit to the next bytecode instruction,
2256 since it has pushed an unexpected type onto the stack).
2258 SetElem is similar to SetProp and SetNewElem but can also be used for setting
2259 characters within strings. When given a string base and a valid offset, SetElem
2260 returns a string representation of the newly inserted character. In all other
2261 cases it returns nullptr or throws an InvalidSetMException. It will throw this
2262 exception when it detects invalid input types, or when trying to set a string
2263 offset that would grow the string beyond the maximum supported size.
2265 The input types that will cause the errors described above are listed here:
2267 SetNewElem will fail if the base is not a subtype of {Null|Str|Arr|Obj} and not
2269 SetElem has the same base constraint as SetNewElem. In addition, the key must
2270 not be a subtype of {Arr|Obj}.
2271 SetProp will fail if the base is not a subtype of {Obj|Null}.
2273 Any instructions that take a pointer to an MInstrState struct use the various
2274 fields of that struct for holding intermediate values.
2276 | BaseG, D(PtrToRMembCell), S(Str), E|Er
2278 Get a base from global named S0.
2280 NB: BaseG returns either a PtrToGblGen, OR a pointer to a ref that is rooted
2281 in a GblGen. (I.e. the unbox happens in the C++ helper that this instruction
2282 calls.) If it is not a defining BaseG it can also return the
2283 init_null_variant, so for now it returns a PtrToRMembCell.
2285 | PropX, D(PtrToMemGen), S(Obj,PtrToGen) S(Cell) S(PtrToMISGen), E|Er
2287 Lookup intermediate property in S0, with key S1.
2289 |STK PropDX, D(PtrToMemGen), S(Obj,PtrToGen) S(Cell) S(PtrToMISGen), MProp|E|Er
2291 Like PropX, but used for intermediate element lookups that may modify the
2294 | CGetProp, D(Cell), S(Obj,PtrToGen) S(Cell) S(PtrToMISGen), E|PRc|Er
2296 Get property with key S1 from S0.
2298 |STK VGetProp, D(BoxedCell),
2299 | S(Obj,PtrToGen) S(Cell) S(PtrToMISGen),
2302 Get property with key S1 from base S0 as a reference.
2305 | S(Obj,PtrToGen) S(Cell) S(BoxedCell) S(PtrToMISGen),
2308 Bind property with key S1 in base S0 to the reference in S2.
2310 |STK SetProp, ND, S(Obj,PtrToGen) S(Cell) S(Cell), MProp|E|Er
2312 Set property with key S1 in S0 to S2.
2314 | UnsetProp, ND, S(Obj,PtrToGen) S(Cell), E|Er
2316 Unset an object property.
2318 |STK SetOpProp<op>, D(Cell),
2319 | S(Obj,PtrToGen) S(Cell) S(Cell) S(PtrToMISGen),
2322 Set op propery with key S1 in base S0, using S2 as the right hand side.
2324 |STK IncDecProp<op>, D(Cell),
2325 | S(Obj,PtrToGen) S(Cell) S(PtrToMISGen),
2328 Increment/decrement property with key S1 in base S0.
2330 | EmptyProp, D(Bool), S(Obj,PtrToGen) S(Cell), E|Er
2332 Returns true iff the property with key S1 in base S0 is empty.
2334 | IssetProp, D(Bool), S(Obj,PtrToGen) S(Cell), E|Er
2336 Returns true iff the property with key S1 in base S0 is set.
2338 | ElemX, D(PtrToMemGen), S(PtrToGen) S(Cell) S(PtrToMISGen), E|Er
2340 Get intermediate element with key S1 from base S0. The base will not be
2343 | ElemArray, D(PtrToMemGen), S(PtrToGen) S(Int,Str), E|Er
2345 | ElemArrayW, D(PtrToMemGen), S(PtrToGen) S(Int,Str), E|Er
2347 Similar to ElemX, but assumes the base S0 is an array and the key S1 is an
2348 int/str. The ElemArrayW version is for Warn member instrs.
2350 |STK ElemDX, D(PtrToMemGen), S(PtrToGen) S(Cell) S(PtrToMISGen), MElem|E|Er
2352 Like ElemX, but used for intermediate element lookups that may modify the
2355 |STK ElemUX, D(PtrToMemGen), S(PtrToGen) S(Cell) S(PtrToMISGen), MElem|E|Er
2357 Like ElemX, but used for intermediate element lookups that may modify the
2358 base as part of an unset operation.
2360 | ArrayGet, D(Cell), S(Arr) S(Int,Str), PRc|Er
2362 Get element with key S1 from base S0.
2364 | StringGet, D(StaticStr), S(Str) S(Int), PRc|Er
2366 Get string representing character at position S1 from base string S0.
2368 | MapGet, D(Cell), S(Obj) S(Int,Str), E|PRc|Er
2370 Get element with key S1 from base S0.
2372 | CGetElem, D(Cell), S(PtrToGen) S(Cell) S(PtrToMISGen), E|PRc|Er
2374 Get element with key S1 from S0.
2376 |STK VGetElem, D(BoxedCell), S(PtrToGen) S(Cell) S(PtrToMISGen), MElem|E|PRc|Er
2378 Get element with key S1 from base S0 as a reference.
2380 |STK BindElem, ND, S(PtrToGen) S(Cell) S(BoxedCell) S(PtrToMISGen), MElem|E|Er
2382 Bind element with key S1 in base S0 to the reference S2.
2384 | ArraySet, D(Arr), S(Arr) S(Int,Str) S(Cell), E|PRc|CRc|K|Er
2386 Set element with key S1 in S0 to S2. The dest will be a new Array that should
2389 | ArraySetRef, ND, S(Arr) S(Int,Str) S(Cell) S(BoxedCell), E|CRc|K|Er
2391 Like ArraySet, but for binding operations on the array. The parameter in S3
2392 must point to a RefData with an array type when this instruction is executed,
2393 and it must be the same array that is in S0.
2395 | MapSet, ND, S(Obj) S(Int,Str) S(Cell), E|Er
2397 Set element with key S1 in S0 to S2.
2399 |STK SetElem, DSetElem, S(PtrToGen) S(Cell) S(Cell), MElem|E|PRc|Er
2401 Set element with key S1 in S0 to S2.
2403 |STK SetWithRefElem, ND,
2404 | S(PtrToGen) S(Cell) S(PtrToGen) S(PtrToMISGen),
2407 Set element with key S1 in S0 to S2.
2409 |STK UnsetElem, ND, S(PtrToGen) S(Cell), MElem|E|Er
2411 Unsets the element at key S1 in the base S0.
2413 |STK SetOpElem<op>, D(Cell),
2414 | S(PtrToGen) S(Cell) S(Cell) S(PtrToMISGen),
2417 Set op elem with key S1 in base S0, using S2 as the right hand side.
2419 |STK IncDecElem, D(Cell),
2420 | S(PtrToGen) S(Cell) S(PtrToMISGen),
2423 Increment/decrement element with key S1 in base S0.
2425 |STK SetNewElem, ND, S(PtrToGen) S(Cell), MElem|E|Er
2427 Append the value in S1 to S0.
2429 |STK SetNewElemArray, ND, S(PtrToGen) S(Cell), MElem|E|Er
2431 Append the value in S1 to S0, where S0 must be a pointer to an array.
2433 |STK SetWithRefNewElem, ND,
2434 | S(PtrToGen) S(PtrToGen) S(PtrToMISGen),
2437 AppendWithRef the value in S1 to S0.
2439 |STK BindNewElem, ND,
2440 | S(PtrToGen) S(BoxedCell) S(PtrToMISGen),
2443 Append the reference in S1 to S0.
2445 | ArrayIsset, D(Bool), S(Arr) S(Int,Str), E|Er
2447 Returns true iff the element at key S1 in the base S0 is set.
2449 | StringIsset, D(Bool), S(Str) S(Int), NF
2451 Returns true iff the string S0 has a character at position S1.
2453 | VectorIsset, D(Bool), S(Obj) S(Int), E
2455 Returns true iff the element at key S1 in the base S0 is set.
2457 | PairIsset, D(Bool), S(Obj) S(Int), E
2459 Returns true iff the element at key S1 in the base S0 is set.
2461 | MapIsset, D(Bool), S(Obj) S(Int,Str), E
2463 Returns true iff the element at key S1 in the base S0 is set.
2465 | IssetElem, D(Bool), S(PtrToGen) S(Cell) S(PtrToMISGen), E|Er
2467 Returns true iff the element at key S1 in S0 is set.
2469 | EmptyElem, D(Bool), S(PtrToGen) S(Cell) S(PtrToMISGen), E|Er
2471 Returns true iff the element at key S1 in S0 is set and not equal (as defined
2472 by the hhbc Eq instruction) to false.
2474 | CheckBounds, ND, S(Int) S(Int), E|Er
2476 Checks that the index in S0 is between 0 (included) and the values in S1
2477 (excluded). Throws if out of bounds.
2479 | ProfileArray, ND, S(Arr), E
2481 Profile type of array S0 (i.e. whether it is packed or mixed).
2483 | ProfileStr<key>, ND, S(PtrToGen), E
2485 Profile exact type of the value pointed to by S0, which must be known to
2486 point to a string at the time this instruction runs.
2488 | CheckPackedArrayBounds, ND, AK(Packed) S(Int), B|E
2490 Checks that the index in S1 is within the bounds of the packed array in S0.
2491 Branches to B if the index is out of bounds.
2493 | CheckTypePackedArrayElem<T>, ND, AK(Packed) S(Int), B|E
2495 If the array element at S0[S1] is not type T, take the branch.
2497 | IsPackedArrayElemNull, D(Bool), AK(Packed) S(Int), E
2499 Returns true if the element at index S1 of the packed array in S0 is not
2502 | LdPackedArrayElem<T>, DArrElem, AK(Packed) S(Int), E
2504 Loads the element of the packed array in S0 at index S1. If the type param T
2505 is specified, the destination type intersects it with whatever we'd know from
2508 | LdVectorSize, D(Int), S(Obj), E
2510 Returns the size of the given Vector in S0.
2512 | VectorDoCow, ND, S(Obj), E
2514 Triggers a copy on write for a Vector that has a live ImmVector sharing
2515 the same copy of the elements.
2517 | VectorHasImmCopy, ND, S(Obj), B
2519 Given a vector, check if it has a immutable copy and jump to the taken branch
2522 | ColAddNewElemC, D(Obj), S(Obj) S(Cell), Er|CRc|P
2524 Adds item S0 to the end of collection S0. Throws a fatal error if S0 is not a
2525 collection. Returns S0.
2527 | ColAddElemC, D(Obj), S(Obj) S(Cell) S(Cell), Er|CRc|P
2529 Adds item to collection. Inserts item S2 into collection S0 at key S1.
2530 Throws a fatal error if S0 is not a collection. Returns S0.
2532 | ColIsEmpty, D(Bool), S(Obj), NF
2534 | ColIsNEmpty, D(Bool), S(Obj), NF
2536 Returns whether a collection instance is empty or not. S0 must be known to
2537 be an instance of a collection class at compile time.
2539 19. Exception/unwinding support
2541 | BeginCatch, ND, NA, E
2543 Marks the beginning of a catch region. Exact behavior is implementation and
2544 architecture specific.
2546 | EndCatch, ND, S(FramePtr) S(StkPtr), E|T
2548 Marks the end of a catch region and returns control to the unwinder. Exact
2549 behavior is implementation and architecture specific.
2551 | TryEndCatch, ND, S(FramePtr) S(StkPtr), E
2553 Marks a potential end of a catch region and might return control to the
2554 unwinder. Exact behavior is implementation and architecture specific.
2556 | UnwindCheckSideExit, ND, S(FramePtr) S(StkPtr), B|E
2558 Branches to B if the currently executing catch region should return control to
2559 the unwinder rather than side exiting.
2561 | LdUnwinderValue<T>, DParam, NA, PRc
2563 Loads the value contained by the current unwinder exception.
2565 | DeleteUnwinderException, ND, NA, E
2567 Deletes the current unwinder exception.
2569 | TypeProfileFunc<paramIndex,functionName>, ND,
2573 Profiles that function's parameter/return value for a particular parameter
2574 index. Calls into native c++ function.
2577 /* Local Variables: */
2578 /* fill-column: 79 */