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 IsType<T>, D(Bool), S(Cell), NF
107 The first column is the instruction name (and optional Type parameter in <>).
109 The second column describes the result (destination) using one of the D*
110 macros documented in hphp/runtime/vm/jit/ir-opcode.h, or ND for no destination.
112 The third column describes the sources, separated by whitespace, using macros
113 documented in hphp/runtime/vm/jit/ir-opcode.h, or NA if there are no sources.
115 The fourth column contains the flags, described below. The short name of the
116 flag (used in this file) is given first, with the long name that it expands to
117 in hphp/runtime/vm/jit/ir-opcode.cpp in parentheses after it.
121 The instruction has no flags.
125 The instruction may raise an error, and must have an edge to a catch block.
129 The instruction produces a value with an unconsumed reference that must be
130 consumed, either by DecRefing it or storing it somewhere in memory.
134 The instruction consumes a reference to one or more of its sources, either by
135 decreasing its refcount or storing the reference to memory.
139 The instruction has no next instruction; it either jumps, returns, or throws.
143 The instruction has a (sometimes optional) taken edge. Instructions that are
144 conditional branches (i.e. a Branch that is not Terminal) will also have a
149 The value of the instruction's dest is the same as one of its inputs; it
150 differs only in the type of the variable, or some other property that doesn't
151 affect the value of the variable itself.
155 The instruction may affect the type and/or value of its base operand,
156 operating on object properties.
160 The instruction may affect the type and/or value of its base operand,
161 operating on array elements.
167 1. Checks and Asserts
169 Note: Instructions that check boxed types only check that the operand is boxed,
170 and they ignore the type of the value inside the box (the inner type). The
171 inner type is normally checked when the value within the box is about to be
172 loaded, using a separate CheckRefInner instruction.
174 | CheckType<T>, DRefineS(0), S(Gen,Cls), B|P
176 Check that the type of the src S0 is T, and if so copy it to D, and
177 fallthrough. If S0 cannot be proven to be T, branch to block B. Note that
178 this means S0 still /may/ be a subtype of T in block B in some circumstances.
180 Specifically, subtypes of Type::Static may not be checked precisely,
181 depending on the type of the source. This means the instruction may take the
182 branch in some circumstances even when S0 is a subtype of T, if T has a
183 non-empty intersection with Type::Static.
185 Also note that many types are not supported as the typeParam right now.
187 | CheckNullptr, ND, S(CountedStr,Nullptr), B|CRc
189 If S0 is not a null pointer, branch to block B. This is used to check the
190 return value of a native helper that returns a potentially null StringData*.
192 | AssertType, DRefineS(0), S(Gen,Cls,Ctx), P
194 Assert that the type of S0 is T, copying it to D.
196 | CheckTypeMem<T>, ND, S(PtrToGen), B
198 If the value pointed to by S0 is not type T, branch to the block B.
200 | HintLocInner<T,localId>, ND, S(FramePtr), NF
202 Hint that the inner type of a BoxedCell in localId is likely type T, where T
203 is a subtype of BoxedCell. The type must be guarded on before it is known to
204 be true (via CheckRefInner).
206 | HintStkInner<T,offset>, ND, S(StkPtr), NF
208 Hint that the inner type of the BoxedInitCell on the stack pointed to by S0
209 at offset (in cells) is T. The type must be guarded on before it is known to
210 be true (via CheckRefInner).
212 | HintMBaseInner<T>, ND, NA, NF
214 Hint that the inner type of the BoxedInitCell pointed to by the member base
215 register is T. The type must be guarded on before it is known to be true
218 | CheckLoc<T,localId>, ND, S(FramePtr), B
220 Check that type of the given localId on the frame S0 is T; if not, branch to
223 | CheckStk<T,offset>, ND, S(StkPtr), B
225 Check that the type of the cell on the stack pointed to by S0 at offset (in
226 cells) is T; if not, branch to block B.
228 | CheckMBase<T>, ND, S(PtrToGen), B
230 Check that the value pointed to by the member base register S0 has type T; if
231 not, branch to block B. This is functionally the same as CheckTypeMem.
233 | AssertLoc<T,localId>, ND, S(FramePtr), NF
235 Asserts that type of the supplied local on the frame S0 is T. This is used
236 for local type information, and is similar to CheckLoc except it doesn't
237 imply a runtime check (the assertion must've already been proven to be true)
238 and cannot cause control flow.
240 | AssertStk<T,offset>, ND, S(StkPtr), NF
242 Assert that stack element at `offset' (in cells) from S0 has type T. This is
243 similar to a CheckStk except that it does not imply a runtime check and
244 cannot cause control flow.
246 | AssertMBase<T>, ND, NA, NF
248 Assert that the value pointed to by the member base register has type T.
249 This is similar to a CheckMBase except that it does not imply a runtime check
250 and cannot cause control flow.
252 | CastStk<T,offset>, ND, S(StkPtr), Er
254 Cast the stack element at `offset' (in cells) from S0 to type T.
256 | CastMem<T>, ND, S(PtrToGen), Er
258 Cast the TypedValue at S0 to type T.
260 The following instructions deal with parameter coercion (the standard type
261 conversion for arguments to HNI functions). If parameter coercion fails these
262 functions will throw a TVCoercion exception. They may throw other types of
263 exceptions depending on how coercion is implemented.
265 | CoerceStk<T,offset,fn,argNum>, ND, S(StkPtr), Er
267 Converts the stack slot at offset (in cells) to type T, with the semantics
268 needed for calling a builtin function. May throw a TVCoercionException in the
269 case of failed parameter coercion. The callee is f, and the position of the
270 argument being coerced is argNum.
272 | CoerceMem<T,fn,argNum>, ND, S(PtrToGen), Er
274 Coerces the TypedValue at S0 to type T, with the semantics
275 needed for calling a builtin function. May throw a TVCoercionException in the
276 case of failed parameter coercion. The callee is fn, and the position of the
277 argument being coerced is argNum.
279 | CoerceCellToBool<fn,argNum>, D(Bool), S(Cell), Er
281 | CoerceCellToInt<fn,argNum>, D(Int), S(Cell), Er
283 | CoerceStrToInt<fn,argNum>, D(Int), S(Str), Er
285 | CoerceCellToDbl<fn,argNum>, D(Dbl), S(Cell), Er
287 | CoerceStrToDbl<fn,argNum>, D(Dbl), S(Str), Er
289 These instructions convert either a Cell or a Str to a primitive type (Bool,
290 Int, Dbl) and return the resulting value. They may throw an exception upon
291 failed type coercion. They are encoded along with callee Func, fn, and the
292 integer position of the argument, argNum, being coerced.
294 | CheckInit, ND, S(Gen), B
296 If S0's type is Uninit, branch to block B.
298 | CheckInitMem, ND, S(PtrToGen), B
300 If the value pointed to by S0 has type Uninit, branch to block B.
302 | CheckCold<TransID>, ND, NA, B
304 Check if the counter associated with translation TransID is cold (i.e. within
305 a fixed threshold). If it's not (i.e. such translation has reached the
306 "hotness threshold"), then branch to block B.
308 | CheckRefs<firstBit,mask,vals>, ND, S(Func) S(Int), B
310 Perform reffiness guard checks. Operands:
312 S0 - function pointer for the frame
313 S1 - num params expected in the func
314 firstBit - first bit to check, must be a multiple of 64
315 mask - mask to check (RefDeps::Record::m_mask entries)
316 vals - values to check (RefDeps::Record::m_vals entries)
318 If any of the checks fail, branch to block B.
320 | EndGuards, ND, NA, NF
322 A no-op at runtime, this instruction serves to mark the end of the initial
323 sequence of guards in a trace.
325 | CheckNonNull, DSubtract(0, Nullptr), S(Nullptr,Func,PtrToGen,TCA,Cls), B
327 If the value in S0 is Nullptr, branch to block B.
329 | AssertNonNull, DSubtract(0, Nullptr), S(Nullptr,CountedStr,Func), P
331 Returns S0, with Nullptr removed from its type. This instruction currently
332 supports a very limited range of types but can be expanded if needed.
334 | CheckClosureStaticLocInit, ND, S(BoxedCell), B
336 Check if the closure static local represented by S0 is initialized, and if
337 not branch to block B.
341 | AddInt, D(Int), S(Int) S(Int), NF
343 | SubInt, D(Int), S(Int) S(Int), NF
345 | MulInt, D(Int), S(Int) S(Int), NF
347 | AddIntO, D(Int), S(Int) S(Int), B
349 | SubIntO, D(Int), S(Int) S(Int), B
351 | MulIntO, D(Int), S(Int) S(Int), B
353 | AddDbl, D(Dbl), S(Dbl) S(Dbl), NF
355 | SubDbl, D(Dbl), S(Dbl) S(Dbl), NF
357 | MulDbl, D(Dbl), S(Dbl) S(Dbl), NF
359 | DivDbl, D(Dbl), S(Dbl) S(Dbl), NF
361 | DivInt, D(Int), S(Int) S(Int), NF
363 | Floor, D(Dbl), S(Dbl), NF
365 | Ceil, D(Dbl), S(Dbl), NF
367 | AbsDbl, D(Dbl), S(Dbl), NF
369 | Sqrt, D(Dbl), S(Dbl), NF
371 | AndInt, D(Int), S(Int) S(Int), NF
373 | OrInt, D(Int), S(Int) S(Int), NF
375 | XorInt, D(Int), S(Int) S(Int), NF
377 | Shl, D(Int), S(Int) S(Int), NF
379 | Shr, D(Int), S(Int) S(Int), NF
381 Double arithmetic, integer arithmetic, and integer bitwise operations.
382 Performs the operation described by the opcode name on S0 and S1, and puts
385 Undefined behavior occurs if Mod is given a divisor of zero, or if the
386 divisor is -1 and the dividend is the minimum representable integer.
388 AbsDbl computes the absolute value of a double-precision value.
390 DivDbl conforms to IEEE 754. In particular, division by zero returns +/- INF
391 or NAN depending on the dividend; and should the result of a division be zero
392 the sign will follow the normal sign rules for division.
394 DivInt will perform integer division of S1 by S0. S0 should not be zero and
397 Note that Shr is an arithmetic right shift: The MSB is sign-extended.
399 Floor and Ceil will return an integral value not greater, or not less
400 than their input respectively. Their use requires SSE 4.1, availability
401 should be checked before they are emitted.
403 AddIntO, SubIntO, MulIntO perform integer arithmetic on S0 and S1, but will
404 branch to block B on integer overflow.
406 | XorBool, D(Bool), S(Bool) S(Bool), NF
408 Logical XOR of the two sources. (Note that && and || do not have
409 corresponding opcodes because they're handled at the bytecode level, to
410 implement short-circuiting.)
412 | Mod, D(Int), S(Int) S(Int), NF
414 Compute S0 mod S1. If S1 is -1 or 0 the results are undefined.
419 To array conversions:
421 | ConvBoolToArr, D(Arr), S(Bool), PRc
423 | ConvDblToArr, D(Arr), S(Dbl), PRc
425 | ConvIntToArr, D(Arr), S(Int), PRc
427 | ConvObjToArr, D(Arr), S(Obj), Er|PRc|CRc
429 | ConvStrToArr, D(Arr), S(Str), PRc|CRc
431 | ConvVecToArr, D(Arr), S(Vec), PRc|CRc
433 | ConvDictToArr, D(Arr), S(Dict), PRc|CRc
435 | ConvKeysetToArr, D(Arr), S(Keyset), PRc|CRc
437 | ConvCellToArr, D(Arr), S(Cell), Er|PRc|CRc
442 | ConvArrToVec, D(Vec), S(Arr), Er|PRc|CRc
444 | ConvDictToVec, D(Vec), S(Dict), PRc|CRc
446 | ConvKeysetToVec, D(Vec), S(Keyset), PRc|CRc
448 | ConvObjToVec, D(Vec), S(Obj), Er|PRc|CRc
453 | ConvArrToDict, D(Dict), S(Arr), Er|PRc|CRc
455 | ConvVecToDict, D(Dict), S(Vec), PRc|CRc
457 | ConvKeysetToDict, D(Dict), S(Keyset), PRc|CRc
459 | ConvObjToDict, D(Dict), S(Obj), Er|PRc|CRc
462 To keyset conversions:
464 | ConvArrToKeyset, D(Keyset), S(Arr), Er|PRc|CRc
466 | ConvVecToKeyset, D(Keyset), S(Vec), Er|PRc|CRc
468 | ConvDictToKeyset, D(Keyset), S(Dict), Er|PRc|CRc
470 | ConvObjToKeyset, D(Keyset), S(Obj), Er|PRc|CRc
475 | ConvArrToBool, D(Bool), S(Arr), NF
477 | ConvDblToBool, D(Bool), S(Dbl), NF
479 | ConvIntToBool, D(Bool), S(Int), NF
481 | ConvStrToBool, D(Bool), S(Str), NF
483 | ConvObjToBool, D(Bool), S(Obj), NF
485 | ConvCellToBool, D(Bool), S(Cell), NF
487 To double conversions:
489 | ConvArrToDbl, D(Dbl), S(Arr), NF
491 | ConvBoolToDbl, D(Dbl), S(Bool), NF
493 | ConvIntToDbl, D(Dbl), S(Int), NF
495 | ConvObjToDbl, D(Dbl), S(Obj), Er
497 | ConvStrToDbl, D(Dbl), S(Str), NF
499 | ConvResToDbl, D(Dbl), S(Res), NF
501 | ConvCellToDbl, D(Dbl), S(Cell), Er
506 | ConvBoolToInt, D(Int), S(Bool), NF
508 | ConvDblToInt, D(Int), S(Dbl), NF
510 | ConvObjToInt, D(Int), S(Obj), Er
512 | ConvStrToInt, D(Int), S(Str), NF
514 | ConvResToInt, D(Int), S(Res), NF
516 | ConvCellToInt, D(Int), S(Cell), Er
519 To object conversions:
521 | ConvCellToObj, D(Obj), S(Cell), Er|CRc|PRc
524 To string conversions:
526 | ConvDblToStr, D(Str), S(Dbl), PRc
528 | ConvIntToStr, D(Str), S(Int), PRc
530 | ConvObjToStr, D(Str), S(Obj), PRc|Er
532 | ConvResToStr, D(Str), S(Res), PRc|Er
534 | ConvCellToStr, D(Str), S(Cell), PRc|Er
537 All the above opcodes convert S0 from its current type to the destination
538 type, according to the PHP semantics of such a conversion.
540 | ConvClsToCctx, D(Cctx), S(Cls), NF
542 Convert a class to a class context (i.e. the class with a 1 or'd into the low
545 | OrdStr, D(Int), S(Str), NF
547 Convert the first byte in a string to an unsigned integer.
548 Intended as an optimization for ord($str)
550 | OrdStrIdx, D(Int), S(Str) S(Int), Er
552 Convert the character at position S1 in base string S0 to an unsigned
553 integer. Raises a notice if the position is out of bounds.
554 Intended as an optimization for ord($str[$idx]).
556 | ChrInt, D(StaticStr), S(Int), NF
558 Convert the integer S0 to a the one character string with ascii code
561 4. Boolean predicates
563 | GtInt, D(Bool), S(Int) S(Int), NF
565 | GteInt, D(Bool), S(Int) S(Int), NF
567 | LtInt, D(Bool), S(Int) S(Int), NF
569 | LteInt, D(Bool), S(Int) S(Int), NF
571 | EqInt, D(Bool), S(Int) S(Int), NF
573 | NeqInt, D(Bool), S(Int) S(Int), NF
575 | CmpInt, D(Int), S(Int) S(Int), NF
577 Perform 64-bit integer comparisons.
579 | GtDbl, D(Bool), S(Dbl) S(Dbl), NF
581 | GteDbl, D(Bool), S(Dbl) S(Dbl), NF
583 | LtDbl, D(Bool), S(Dbl) S(Dbl), NF
585 | LteDbl, D(Bool), S(Dbl) S(Dbl), NF
587 | EqDbl, D(Bool), S(Dbl) S(Dbl), NF
589 | NeqDbl, D(Bool), S(Dbl) S(Dbl), NF
591 | CmpDbl, D(Int), S(Dbl) S(Dbl), NF
593 Perform comparisons of doubles. Comparisons that are unordered according to
594 IEEE 754 (such as when at least one operand is NaN) result in false.
596 | GtStr, D(Bool), S(Str) S(Str), NF
598 | GteStr, D(Bool), S(Str) S(Str), NF
600 | LtStr, D(Bool), S(Str) S(Str), NF
602 | LteStr, D(Bool), S(Str) S(Str), NF
604 | EqStr, D(Bool), S(Str) S(Str), NF
606 | NeqStr, D(Bool), S(Str) S(Str), NF
608 | SameStr, D(Bool), S(Str) S(Str), NF
610 | NSameStr, D(Bool), S(Str) S(Str), NF
612 | CmpStr, D(Int), S(Str) S(Str), NF
614 Performs comparison of strings using PHP semantics.
616 | GtStrInt, D(Bool), S(Str) S(Int), NF
618 | GteStrInt, D(Bool), S(Str) S(Int), NF
620 | LtStrInt, D(Bool), S(Str) S(Int), NF
622 | LteStrInt, D(Bool), S(Str) S(Int), NF
624 | EqStrInt, D(Bool), S(Str) S(Int), NF
626 | NeqStrInt, D(Bool), S(Str) S(Int), NF
628 | CmpStrInt, D(Int), S(Str) S(Int), NF
630 Performs comparison of strings with integers using PHP semantics.
632 | GtBool, D(Bool), S(Bool) S(Bool), NF
634 | GteBool, D(Bool), S(Bool) S(Bool), NF
636 | LtBool, D(Bool), S(Bool) S(Bool), NF
638 | LteBool, D(Bool), S(Bool) S(Bool), NF
640 | EqBool, D(Bool), S(Bool) S(Bool), NF
642 | NeqBool, D(Bool), S(Bool) S(Bool), NF
644 | CmpBool, D(Int), S(Bool) S(Bool), NF
646 Performs comparison of booleans.
648 | GtObj, D(Bool), S(Obj) S(Obj), Er
650 | GteObj, D(Bool), S(Obj) S(Obj), Er
652 | LtObj, D(Bool), S(Obj) S(Obj), Er
654 | LteObj, D(Bool), S(Obj) S(Obj), Er
656 | EqObj, D(Bool), S(Obj) S(Obj), Er
658 | NeqObj, D(Bool), S(Obj) S(Obj), Er
660 | SameObj, D(Bool), S(Obj) S(Obj), NF
662 | NSameObj, D(Bool), S(Obj) S(Obj), NF
664 | CmpObj, D(Int), S(Obj) S(Obj), Er
666 Perform comparison of objects using PHP semantics. All versions except for
667 SameObj and NSameObj may re-enter the VM and therefore may throw
668 exceptions. SameObj and NSameObj never re-enter or throw.
670 | GtArr, D(Bool), S(Arr) S(Arr), Er
672 | GteArr, D(Bool), S(Arr) S(Arr), Er
674 | LtArr, D(Bool), S(Arr) S(Arr), Er
676 | LteArr, D(Bool), S(Arr) S(Arr), Er
678 | EqArr, D(Bool), S(Arr) S(Arr), Er
680 | NeqArr, D(Bool), S(Arr) S(Arr), Er
682 | SameArr, D(Bool), S(Arr) S(Arr), NF
684 | NSameArr, D(Bool), S(Arr) S(Arr), NF
686 | CmpArr, D(Int), S(Arr) S(Arr), Er
688 Perform comparison of arrays using PHP semantics. All versions except for
689 SameArr and NSameArr may re-enter the VM and therefore may throw
690 exceptions. SameArr and NSameArr never re-enter or throw.
692 | GtVec, D(Bool), S(Vec) S(Vec), Er
694 | GteVec, D(Bool), S(Vec) S(Vec), Er
696 | LtVec, D(Bool), S(Vec) S(Vec), Er
698 | LteVec, D(Bool), S(Vec) S(Vec), Er
700 | EqVec, D(Bool), S(Vec) S(Vec), Er
702 | NeqVec, D(Bool), S(Vec) S(Vec), Er
704 | SameVec, D(Bool), S(Vec) S(Vec), NF
706 | NSameVec, D(Bool), S(Vec) S(Vec), NF
708 | CmpVec, D(Int), S(Vec) S(Vec), Er
710 Perform comparison of vecs. All versions except for SameVec and NSameVec may
711 re-enter the VM and therefore may throw exceptions. SameVec and NSameVec
712 never re-enter or throw.
714 | EqDict, D(Bool), S(Dict) S(Dict), Er
716 | NeqDict, D(Bool), S(Dict) S(Dict), Er
718 | SameDict, D(Bool), S(Dict) S(Dict), NF
720 | NSameDict, D(Bool), S(Dict) S(Dict), NF
722 Perform comparison of dicts. EqDict and NeqDict may re-enter the VM and
723 therefore may throw exceptions. SameDict and NSameDict never re-enter or
724 throw. Relational comparisons for dicts are not supported.
726 | EqKeyset, D(Bool), S(Keyset) S(Keyset), NF
728 | NeqKeyset, D(Bool), S(Keyset) S(Keyset), NF
730 | SameKeyset, D(Bool), S(Keyset) S(Keyset), NF
732 | NSameKeyset, D(Bool), S(Keyset) S(Keyset), NF
734 Perform comparison of keysets. As keysets can only contain ints and strings,
735 comparisons never re-enter or throw. Relational comparisons for keysets are
738 | GtRes, D(Bool), S(Res) S(Res), NF
740 | GteRes, D(Bool), S(Res) S(Res), NF
742 | LtRes, D(Bool), S(Res) S(Res), NF
744 | LteRes, D(Bool), S(Res) S(Res), NF
746 | EqRes, D(Bool), S(Res) S(Res), NF
748 | NeqRes, D(Bool), S(Res) S(Res), NF
750 | CmpRes, D(Int), S(Res) S(Res), NF
752 Perform comparison of resources using PHP semantics. Resource comparisons
753 never re-enter or throw.
755 | EqCls, D(Bool), S(Cls) S(Cls), NF
757 Checks if two Class values are equal.
759 | EqFunc, D(Bool), S(Func) S(Func), NF
761 Checks if two Func values are equal.
763 | EqStrPtr, D(Bool), S(Str) S(Str), NF
765 Checks if two string values represent the same underlying string. That is,
766 that they point at the same underlying storage.
768 | EqArrayDataPtr, D(Bool), S(ArrLike) S(ArrLike), NF
770 Checks if the two arguments represent the same underlying ArrayData. That is,
771 that they point at the same underlying storage.
773 | ProfileInstanceCheck, ND, C(StaticStr), NF
775 Profile that S0 has been used as the RHS of an instance check.
777 | InstanceOf, D(Bool), S(Cls) S(Cls|Nullptr), NF
779 Sets D based on whether S0 is a descendant of the class, interface, or trait
780 in S1. (Note that this is always false for a trait). S1 may be null at
781 runtime if the class is not defined.
783 | InstanceOfIface, D(Bool), S(Cls) CStr, NF
785 Fast path for interface checks. Sets D based on whether S0 implements S1, but
786 S1 must be a unique interface. This should only be used in repo-authoritative
789 | InstanceOfIfaceVtable<iface>, D(Bool), S(Cls), NF
791 Faster path for interface checks. Sets D based on whether S0 implements
792 iface, which must be a unique interface with an assigned vtable slot.
794 | ExtendsClass<cls,strictLikely>, D(Bool), S(Cls), NF
796 A fast-path for instanceof checks. Sets D based on whether S0 is a descendant
797 of cls, where cls must be a unique class that is not an interface or a trait.
799 If strictLikely is true, optimize for the case where S0 is not equal to S1.
801 | InstanceOfBitmask, D(Bool), S(Cls) CStr, NF
803 | NInstanceOfBitmask, D(Bool), S(Cls) CStr, NF
805 A fast-path for instanceof checks. Sets D based on whether S0 is a descendant
806 of the class named by S1, where S1 must have a bit allocated for it in the
807 fast instance check bitvector (see class.h).
809 | InterfaceSupportsArr, D(Bool), S(Str), NF
811 | InterfaceSupportsVec, D(Bool), S(Str), NF
813 | InterfaceSupportsDict, D(Bool), S(Str), NF
815 | InterfaceSupportsKeyset, D(Bool), S(Str), NF
817 | InterfaceSupportsStr, D(Bool), S(Str), NF
819 | InterfaceSupportsInt, D(Bool), S(Str), NF
821 | InterfaceSupportsDbl, D(Bool), S(Str), NF
823 Returns whether t instanceof S0 returns true when t is of the given type.
825 | HasToString, D(Bool), S(Obj), NF
827 Returns whether the object S0 has a toString method.
829 | IsType<T>, D(Bool), S(Cell), NF
831 Sets D to true iff S0 holds a value that is of type T. T must not be a
834 | IsNType<T>, D(Bool), S(Cell), NF
836 Sets D to true iff S0 holds a value that is not of type T. T must not be a
839 | IsTypeMem<T>, D(Bool), S(PtrToGen), NF
841 Sets D to true iff the value referenced by S0 is of type T. T must not be a
844 The value in S0 must not be a pointer into the evaluation stack or frame
847 | IsNTypeMem<T>, D(Bool), S(PtrToGen), NF
849 Sets D to true iff the value referenced by S0 is not of type T. T must not be
852 | IsScalarType, D(Bool), S(Cell), NF
854 Returns true if S0 is of type Int, Bool, Dbl or Str. Returns false otherwise.
856 | IsWaitHandle, D(Bool), S(Obj), NF
858 Sets D to true iff S0 is a subclass of WaitHandle.
860 | IsCol, D(Bool), S(Obj), NF
862 Sets D to true iff S0 is a collection.
867 | JmpZero, ND, S(Int,Bool), B
869 | JmpNZero, ND, S(Int,Bool), B
871 Conditionally jump to based on S0.
873 | JmpSSwitchDest, ND, S(TCA) S(StkPtr) S(FramePtr), T
875 Jump to the target of a sswitch statement, leaving the region, where the
878 | JmpSwitchDest, ND, S(Int) S(StkPtr) S(FramePtr), T
880 Jump to the target of a switch statement, leaving the region, using table
881 metadata <JmpSwitchData> and index S0, which must be a valid index in the
884 | ProfileSwitchDest<handle,nCases>, ND, S(Int), NF
886 Profile a switch statement target.
888 | CheckSurpriseFlags, ND, S(FramePtr,StkPtr), B
890 Tests the implementation-specific surprise flags. If they're true, branches
891 to block B. This is done by comparing an evaluation stack pointer to the RDS
892 stackLimitAndSurprise word. Note that in a resumed, the frame pointer is not
893 pointing into the eval stack, so S0 should be a StkPtr in that case.
895 | ReturnHook, ND, S(FramePtr) S(Gen), Er
897 Surprise flag hook for function returns.
899 | SuspendHookE, ND, S(FramePtr) S(FramePtr) S(Obj), Er
901 Surprise flag hook for suspending eagerly executing async functions or
902 generators. Decrefs S2 if it throws an exception.
904 | SuspendHookR, ND, S(FramePtr) S(Obj|Nullptr), Er
906 Surprise flag hook for suspending resumed async functions or generators. For
907 generators, the second parameter should be Nullptr.
909 | Unreachable, ND, NA, T
911 Indicates an unreachable code path. Any instructions that are post-dominated
912 by an Unreachable may be treated as unreachable by the optimizer, and the
913 behavior of a program that attempts to execute an Unreachable is undefined.
915 | EndBlock, ND, NA, T
917 Halt execution, without implying anything about the reachability of
918 instructions preceding this. Intended for use in internal tests or other code
919 not meant to be executed.
921 | Jmp, ND, SVar(Top), B|T
923 Unconditional jump to block B. In the second form, the target block must
924 start with a DefLabel with the same number of destinations as Jmp's number of
925 sources. Jmp parallel-copies its sources to the DefLabel destinations.
927 | DefLabel, DMulti, NA, NF
929 DefLabel defines variables received from a previous Jmp. A DefLabel with zero
930 destinations is a no-op, and the predecessor blocks may not necessarily end
931 in Jmp. A DefLabel with one or more destinations may only be reached by a Jmp
932 instruction with the same number of sources. Ordinary branch instructions may
933 not pass values to a DefLabel.
935 | Select, DUnion(1,2), S(Bool,Int) S(Top) S(Top), NF
937 If S0 is true/non-zero, return S1, otherwise return S2.
940 6. Reference manipulation
942 | Box, D(BoxedInitCell), S(Cell), CRc|PRc
944 Box S0 and put the resulting BoxedInitCell in D. If S0 is Uninit, then
945 InitNull will be boxed instead.
947 | UnboxPtr, DUnboxPtr, S(PtrToGen), NF
949 If S0 points to a cell that is KindOfRef, dereference the pointer in the
950 TypedValue and return a pointer to the inner-cell in D.
952 | BoxPtr, DBoxPtr, S(PtrToGen), NF
954 Boxes the TypeValue that S0 points to if it is not boxed. The result D points
955 to the same TypedValue as S0 but has a more refined type.
957 S0 may not already point into a RefData (due to VM invariants), although the
958 IR type system does not enforce it.
963 | LdStk<T,offset>, DParamMayRelax(Gen), S(StkPtr), NF
965 Loads from S0 at offset (in cells), and puts the value in D as type T.
967 | LdLoc<T,localId>, DParamMayRelax(Gen), S(FramePtr), NF
969 Loads local slot localId from the frame S0 and puts the value in D as type T.
971 | LdLocPseudoMain<T,localId>, DParam(Gen), S(FramePtr), B
973 Loads local number localId from frame S0 and puts the value in D if the
974 local's type is a subtype of T. If the local's type is not a subtype of T,
975 then the load does not happen, and this instruction branches to B. This
976 instruction is used for loading locals in pseudo-mains, where they can alias
979 | LdClsRef<T,slot>, DParamMayRelax(Cls), S(FramePtr), NF
981 Loads class-ref from slot `slot` in frame S0 and puts the value in D as type
982 T. T must be a sub-type of TCls.
984 | LdStkAddr<T,offset>, D(PtrToStkGen), S(StkPtr), NF
986 Loads the address of the stack slot given by the pointer in S0 at the offset
987 (in cells). T must be a subtype of PtrToStkGen.
989 | LdLocAddr<localId>, D(PtrToFrameGen), S(FramePtr), NF
991 Loads the address of the local slot localId from the frame S0 into D.
993 | LdRDSAddr<T,RDSHandle>, DParam(PtrToGen), NA, NF
995 Load the address of a Gen that lives at the specified RDS handle. The type
996 param must be a subtype of PtrToGen.
998 | LdVectorBase, D(PtrToMembCell), S(Obj), NF
1000 | LdPairBase, D(PtrToMembCell), S(Obj), NF
1002 Loads the base pointer to an array of Cells from the given collection
1005 | LdMem<T>, DParam(Gen), S(PtrToGen), NF
1007 Loads from S0 and puts the value in D.
1009 | LdContField<T>, DParam(Gen), S(Obj) C(Int), NF
1011 Loads a property from the object referenced by S0 at the offset given by S1
1012 and puts the value in D. S0 must be a Generator.
1014 | LdElem, D(Cell), S(PtrToCell) S(Int), NF
1016 Loads the element at index S1 from the base pointer in S0. The index in S1 is
1017 the number of bytes from the base in S0.
1019 | LdColVec, D(Vec), S(Obj), NF
1021 Load the vec array backing a collection instance in S0, which must be a
1022 Vector or ImmVector, and that specific object type must be known at compile
1025 | LdColArray, D(Arr), S(Obj), NF
1027 Load the array backing a collection instance in S0, which must be a Map, Set,
1028 ImmMap, or ImmSet, and that specific object type must be known at compile
1031 | CheckRefInner<T>, ND, S(BoxedCell), B
1033 TODO(#2939547): this should take BoxedInitCell
1035 Check that the inner type of the boxed cell in S0 is T, and if not take the
1038 | LdRef<T>, DParam(Cell), S(BoxedCell), NF
1040 TODO(#2939547): this should take BoxedInitCell
1042 Loads the value held in the box referenced by S0 and puts the value in D. The
1043 inner type of S0 must be a subtype of T (usually ensured with a previous
1046 | LdCtx, DCtx, S(FramePtr), NF
1048 Loads into D the value of the m_this/m_cls field out of the frame pointer S0,
1049 which must be a frame for the function in the LdCtx's marker. The result
1050 could be either an object representing the this pointer or a class context.
1052 | LdCctx, DCtx, S(FramePtr), NF
1054 Loads into D the value of the m_cls field out of the frame pointer S0. The
1055 compiler should generate this only if it can prove that the frame does not
1056 contain a nullptr or $this pointer.
1058 | LdClosure<T>, DParam(Ctx), S(FramePtr), NF
1060 Loads into D the value of the m_this/m_cls field out of the frame pointer S0.
1061 The compiler should generate this only if it can prove that the frame context
1062 is a closure object of type T. Unlike LdCtx and LdCctx, there are no special
1063 rules about the relative positions of LdClosure and InitCtx instructions.
1065 | CheckCtxThis, ND, S(Ctx), B
1067 Check that the context (m_this or m_cls) in S0 is a non-null $this
1068 pointer. If not, branch to B.
1070 | LdClsCtx, DCtxCls, S(Ctx), NF
1072 Loads into D the class representing the current context. Extracts the class
1073 from S0, which can be either the this pointer or the context class.
1075 | LdClsCctx, DCtxCls, S(Cctx), NF
1077 Loads into D the class representing the current context. Extracts the class
1078 from the S0, which is a context class.
1080 | LdClsCtor, D(Func), S(Cls) S(FramePtr), Er
1082 Loads into D the constructor of class S0. If the constructor cannot be called
1083 from the context in S1, raise an error.
1085 | DefCls, D(Cls), S(Int), Er
1087 Define the class corresponding to PreClass S0 in the current unit.
1089 | DefConst<T>, DParam(Top), NA, NF
1091 Define a constant value of type T. D is presumed to be globally available and
1092 the DefConst instruction will not actually appear in the IR instruction
1095 | Conjure<T>, DParam(Top), NA, NF
1097 Define a value of type T. This instruction aborts at runtime; it is meant to
1098 be used in tests or code that is known to be unreachable.
1100 | ConjureUse, ND, S(Gen), NF
1102 Define a "use" of S0 effectively keeping the value alive. As with Conjure it
1103 should not appear in reachable code.
1105 | LdCls, D(Cls), S(Str) C(Cls), Er
1107 Loads the class named S0 in the context of the class S1. Invokes autoload and
1108 may raise an error if the class is not defined. The explicit context
1109 parameter allows the compiler to simplify this instruction to a DefConst in
1110 some cases. If S0 is constant, this instruction may be simplified to a
1113 | LdClsCached, D(Cls), CStr, Er
1115 Loads the class named S0 via the RDS. Invokes autoload and may raise an error
1116 if the class is not defined.
1118 | LdClsCachedSafe, D(Cls), CStr, B
1120 Loads the class whose name is S0 out of the RDS. If the class is not defined,
1123 | LdClsInitData, D(PtrToClsInitCell), S(Cls), NF
1125 Loads the pointer to the property initializer array for class S0.
1127 | LookupClsRDS, D(Cls|Nullptr), S(Str), NF
1129 Lookup the cached-class RDS handle for a given class name. Dereference that
1130 handle and return the associated Class, or null if not present.
1132 | LdCns, DCns, CStr, B|PRc
1134 Load the constant named S0, branching to B if isn't present.
1136 | LookupCns<T,constName>, DCns, CStr, Er|PRc
1138 | LookupCnsE<T,constName>, DCns, CStr, Er|PRc
1140 Load a constant via the RDS. Raises an undefined constant notice if the
1141 constant cannot be defined. The E variant will instead throw a fatal error if
1142 it cannot define the constant. These should only be executed if LdCns on the
1143 same constant has failed.
1145 | LookupCnsU<T,constName,fallbackName>, DCns, CStr CStr, Er|PRc
1147 Load an unqualified constant via the RDS, first by trying constName, then by
1148 trying fallbackName. Raises a notice if neither can be found. Should only
1149 be executed if LdCns on the same constant has failed.
1151 | LdClsCns<className,constantName>, D(PtrToGen), NA, B
1153 Load the address of the constant 'constantName' for the class 'className' in
1154 RDS. If not initialized, branch to B.
1156 | LdClsMethodFCacheFunc<clsName,methodName>, D(Func), NA, B
1158 Loads the target cache entry for a forwarding call to clsName::methodName.
1159 If the method does not exist, or the cache hasn't been filled yet, branch to
1162 | LookupClsMethodFCache<clsName,methodName>,
1163 | D(Func|Nullptr), C(Cls) S(FramePtr),
1166 Lookup clsName::methodName in the forwarding class method cache. S0 should be
1167 the Class named by clsName and S1 should be the current vm frame pointer. May
1168 return Nullptr if lookup fails using a subset of the required lookup paths,
1169 indicating that a more complete lookup path should be taken. May throw if the
1170 method does not exist.
1172 | CheckFuncStatic, ND, S(Func), B
1174 Tests to see if Func::m_attrs & AttrStatic, and if so branch to B.
1175 This instruction is intended to be used in forwarding calls, where we know
1176 that Func is not a closure.
1178 | FwdCtxStaticCall, D(Cctx), S(Ctx), NF
1180 If S0 is an object, this opcode returns S0's class with the low bit set
1181 (i.e., as a Cctx). Otherwise this instruction returns S0.
1183 | LdClsMethodCacheFunc<clsName,methodName>, D(Func), NA, B
1185 Loads the target cache entry for the method clsName::methodName. If the
1186 method does not exist or the cache hasn't been filled yet, branch to B.
1188 | LdClsMethodCacheCls<clsName,methodName>, D(Cctx), NA, NF
1190 Loads the target cache class context entry for a call to clsName::methodName
1191 from the current context. This instruction must only be used when the value
1192 is known to not be empty (i.e., LdClsMethodCacheFunc must have succeeded, or
1193 LookupClsMethodCache returned a non-null value).
1195 | LookupClsMethodCache<clsName,methodName>, D(Func|Nullptr),
1199 Lookup a function in the class method targetcache. The class name and method
1200 name are clsName and methodName, respectively. S0 is the current vm frame
1201 pointer. Returns Nullptr if the method cannot be found using a subset of the
1202 required lookup paths, indicating that a more complete lookup path should be
1203 taken. May throw if the method does not exist.
1205 | LdIfaceMethod<vtableIdx,methodIdx>, D(Func), S(Cls), NF
1207 Load the Func* at methodIdx from the vtable at vtableIdx in S0.
1209 | LdFuncVecLen, D(Int), S(Cls,Cctx), NF
1211 Load the funcVecLen field from S0.
1213 | LdClsMethod, D(Func), S(Cls,Cctx) C(Int), NF
1215 Load a Func* off of the class method table for S0, at offset S1 (in method
1218 | LookupClsMethod<calleeAROffset,forward>,
1220 | S(Cls) S(Str) S(StkPtr) S(FramePtr),
1223 Store a pointer to a class method into an activation record. S0 points to the
1224 class, S1 is the method name, S2 is a stack pointer that has an activation
1225 record to modify at `spToActRecOffset', and S3 is a pointer to the current
1226 frame (used to get the context). `forward` indicates if we should forward the
1227 current context. May throw or fatal if method is not accessible.
1229 | LdPropAddr<T,offset>, DParamPtr(Prop), S(Obj), NF
1231 Load the address of the object property for S0 + `offset' (in bytes). T must
1232 be a subtype of PtrToPropGen.
1234 | LdGblAddr, D(PtrToGblGen), S(Str), B
1236 Loads a pointer to a global. S0 is the global's name. Branches to B if the
1237 global is not defined.
1239 | LdGblAddrDef, D(PtrToGblGen), S(Str), NF
1241 Loads a pointer to a global. S0 is the global's name. Defines the global if
1242 it is not already defined.
1244 | LdClsPropAddrOrNull, D(PtrToSPropGen|Nullptr),
1245 | S(Cls) S(Str) C(Cls),
1248 Loads a pointer to a static class property. S0 points to the class, S1 is the
1249 property name, and S2 is the class representing the context of the code
1250 accessing the property. If class S0 does not have a visible and accessible
1251 static property named S1, then nullptr is returned.
1253 | LdClsPropAddrOrRaise, D(PtrToSPropGen), S(Cls) S(Str) C(Cls), Er
1255 Loads a pointer to a static class property. S0 points to the class, S1 is the
1256 property name, and S2 is the class representing the context of the code
1257 accessing the property. If class S0 does not have a visible and accessible
1258 static property named S1, throw a fatal error.
1260 | LdObjMethod<offset,methodName,fatal>, ND, S(Cls) S(StkPtr), Er
1262 Stores a pointer to an object's method into an activation record. S0 points
1263 to the object's class, S1 has the pre-live activation record at `offset'.
1264 Caches the mapping in the target cache. If `fatal' is true, raises a fatal if
1265 the class does not have an accessible method with the given name and does not
1266 have a __call method; otherwise (if `fatal' is false), raises a warning and
1267 puts func that does nothing and returns null (SystemLib::s_nullFunc) on the
1270 | LdObjInvoke, D(Func), S(Cls), B
1272 Try to load a cached non-static __invoke Func from the Class in S0, or branch
1273 to block B if it is not present.
1275 | LdArrFuncCtx<offset>, ND, S(Arr) S(StkPtr) S(FramePtr), Er
1277 Try to load an array as a function context. This is for use translating
1278 FPushFunc when the callee is an array. This instruction attempts to populate
1279 a partially created ActRec pointed to by S1 + `offset' (in cells).
1281 | LdArrFPushCuf<offset>, ND, S(Arr) S(StkPtr) S(FramePtr), Er
1283 | LdStrFPushCuf<offset>, ND, S(Str) S(StkPtr) S(FramePtr), Er
1285 Try to resolve a method target for FPushCuf when the callee is an Arr or Str,
1286 respectively. These instructions mutate a partially created ActRec pointed to
1287 by S1 + `offset' (in cells).
1289 | LdObjClass, DLdObjCls, S(Obj), NF
1291 Load the class out of the object in S0 and put it in D.
1293 | LdClsName, D(StaticStr), S(Cls), NF
1295 Load the name of the Class* in S0.
1297 | LdFunc<offset>, ND, S(Str) S(StkPtr) S(FramePtr), Er
1299 Loads the Func whose name is S0 into the partially constructed ActRec pointed
1300 to by S1 + `offset` (in cells). Also populate the m_this/m_cls field if
1301 necessary. Fatal if the named function is not defined, and the autoloader
1304 | LdFuncCached<funcName>, D(Func), NA, Er
1306 Loads the Func whose name is funcName from the RDS, invoking autoload if it
1307 not defined yet. Fatal if function autoloader fails to define it.
1309 | LdFuncCachedU<funcName,fallbackName>, D(Func), NA, Er
1311 Try to load a Func named funcName from the RDS, if it isn't defined, try to
1312 load a Func named fallbackName. If that also isn't defined, invoke autoload.
1313 If this still doesn't result in a Func, raise a fatal error.
1315 | LdFuncCachedSafe<funcName>, D(Func), NA, B
1317 Try to load the Func named funcName from the RDS. If the function is not
1318 defined, branch to B.
1320 | LdARFuncPtr<offset>, D(Func), S(StkPtr), NF
1322 Loads the m_func member of an ActRec. S0 is the base address, with `offset'
1323 cells to the ActRec.
1325 | LdARCtx<T,offset>, DParam(Ctx), S(StkPtr), NF
1327 Loads the m_this/m_cls member of an ActRec. S0 is the base address, with
1328 `offset' cells to the ActRec.
1330 | LdARNumParams, D(Int), S(FramePtr), NF
1332 Loads the number of params from an ActRec. S0 is the address of the ActRec
1334 | LdFuncNumParams, D(Int), S(Func), NF
1336 Returns the value of func->numParams().
1338 | LdStrLen, D(Int), S(Str), NF
1340 Load the length of the string in S0.
1342 | LdClosureStaticLoc, D(BoxedCell), CStr S(FramePtr), NF
1344 Get boxed value to initialize static local named S0 in frame S1, where S1
1345 must be either a closure or generatorFromClosure function.
1347 | LdStaticLoc<func,staticLocalName>, D(BoxedInitCell), NA, B
1349 Load the address of the static local variable named 'staticLocalName' for
1350 function 'func' in RDS. If the variable isn't initialized, branch to B.
1354 | AllocObj, DAllocObj, S(Cls), PRc|Er
1356 Allocates a new object of class S1.
1358 | RegisterLiveObj, ND, S(Obj), NF
1360 When EnableObjDestructCall is on, we need to keep track of objects to be able
1361 to call their destructors when a request exists. This instruction is
1362 conditionally emitted to implement that.
1364 | CheckInitProps<class>, ND, NA, B
1366 Check if the properties for class are initialized and branches if not.
1368 | InitProps<class>, ND, NA, Er
1370 Calls the property initializer function (86pinit) for class. May throw.
1372 | CheckInitSProps<class>, ND, NA, B
1374 Check if static properties for class are initialized and branches if not.
1376 | InitSProps<class>, ND, NA, Er
1378 Calls the static property initializer function (86sinit) for class. May
1381 | DebugBacktrace, D(Arr), S(Int), PRc
1383 Obtain stack trace by calling the debug_backtrace() method.
1385 | InitThrowableFileAndLine, ND, S(Obj), NF
1387 Initialize Throwable's file name and line number assuming the stack trace
1388 was already initialized and the current vmfp() is a built-in.
1390 | NewInstanceRaw<class>, DAllocObj, NA, PRc
1392 Allocates an instance of class.
1394 | InitObjProps<class>, ND, S(Obj), NF
1396 Initializes properties of object S0.
1398 | ConstructInstance<class>, DAllocObj, NA, Er
1400 Call the custom instance constructor of an extension class.
1402 | NewArray, D(Arr), C(Int), PRc
1404 Allocate a new array with the expected capacity S0.
1406 | NewMixedArray, D(Arr), C(Int), PRc
1408 Allocate a new array in mixed mode with the expected capacity S0.
1410 | NewDictArray, D(Dict), C(Int), PRc
1412 Allocate a new dict with the expected capacity S0.
1414 | NewKeysetArray<offset,keys>, D(Keyset), S(StkPtr), PRc|CRc|Er
1416 Allocate a new keyset containing N elements off the stack given by S0, at
1417 `offset'. This instruction moves the elements off the stack without
1418 manipulating their reference counts.
1420 | NewLikeArray, D(Arr), S(Arr) C(Int), PRc
1422 Allocate a new array in the same mode as S0 and with expected capacity S1,
1423 unless S1 == 0, in which case the capacity is set to S0's size.
1425 | AllocPackedArray<size>, DArrPacked, NA, PRc
1427 Allocate a new uninitialized packed array with space for size elements in it.
1428 The array will be initialized with values using either InitPackedLayoutArray
1429 or InitPackedLayoutArrayLoop.
1431 | AllocVecArray<size>, D(Vec), NA, PRc
1433 Allocate a new uninitialized vector array with space for size elements in it.
1434 The array will be initialized with values using either InitPackedLayoutArray
1435 or InitPackedLayoutArrayLoop.
1437 | InitPackedLayoutArray<index>, ND, S(Arr,Vec) S(Cell), CRc
1439 Store the S1 into the slot at index in array S0. This instruction assumes
1440 that it doesn't have to incref the value being stored. Used to initialize an
1441 array allocated with AllocPackedArray or AllocVecArray.
1443 | InitPackedLayoutArrayLoop<offset,size>, ND, S(Arr,Vec) S(StkPtr), CRc
1445 Move `size' elements from the stack given by S1, at `offset', into the array
1446 S0. Assumes that the first element on the stack is the last element in the
1447 array. Used to initialize an array allocated with AllocPackedArray or
1448 AllocVecArray that was too big to use a series of InitPackedLayoutArray
1451 | NewStructArray<offset,keys...>, D(Arr), S(StkPtr), PRc|CRc
1453 Allocate a new key/value array, given N immediate keys and taking N elements
1454 off the stack given by S0, at `offset'. This instruction assumes it can take
1455 the values from the stack without increfing them.
1457 | NewCol<type>, DCol, NA, PRc
1459 Create an empty new collection of `type'.
1461 | NewColFromArray<type>, DCol, S(Arr|Vec), PRc|CRc
1463 Create a collection of `type` from an array. `type` cannot be Pair. The array
1464 will be used to back the new collection without duplication or conversion.
1465 Thus it should not contain references. In addition, the array must be in
1466 packed mode when `type` is Vector or ImmVector, and must be in mixed mode
1467 otherwise. Ownership of the array is transferred from $1 to the collection,
1468 without manipulating the refcount.
1470 | Clone, DofS(0), S(Obj), PRc|Er
1472 Allocate an object by cloning S0.
1477 | SpillFrame<offset,numArgs,invName>,
1479 | S(StkPtr) S(Func,Nullptr) S(Ctx,Cls,Nullptr),
1484 S0 - caller stack pointer
1485 S1 - callee Func or nullptr
1486 S2 - object (for FPushObjMethod*), class (for FPushClsMethod*), context
1487 (for FPushClsMethodF), or nullptr (for FPushFunc*).
1489 Defines the fields for an activation record and writes them to the stack
1490 pointed to by S0, at `offset'.
1492 | CufIterSpillFrame<offset,numArgs,iterId>, ND,
1493 | S(StkPtr) S(FramePtr),
1498 S0 - caller stack pointer
1499 S1 - caller frame pointer
1501 Defines the fields for an activation record using data from the iterator
1502 iterId, and writes them to the stack pointed to by S1, at offset.
1504 | FreeActRec, D(FramePtr), S(FramePtr), NF
1506 Load the saved frame pointer from the activation record pointed to by S0 into
1509 | BeginInlining<offset>, ND, S(StkPtr), NF
1511 Marks the start of an inlined function whose stack resides offset cells below
1512 the SP. It has no effect other than to hint to optimization passes that at the
1513 start of the inlined function its stack is dead.
1515 | DefInlineFP<func,retBCOff,retSPOff>, D(FramePtr),
1516 | S(StkPtr) S(FramePtr),
1519 Defines a frame pointer for an inlined function.
1521 `func' is the function being inlined. `retBCOff' and `retSPOff' represent
1522 what the bytecode and stack offsets should be after the FCall instruction in
1525 This instruction is primarily used to represent a frame in the IR in a way
1526 that allows us to eliminate it entirely. When it cannot be eliminated (or if
1527 it is pushed into an unlikely path) it performs callee-side responsibilities
1528 for setting up an activation record (i.e. setting the return ip and m_soff,
1529 storing the frame pointer into D).
1531 The caller frame pointer is passed as S1. This is used to keep track of the
1532 call chain of inlined functions for simplification and dead code elimination.
1534 | InlineReturn<callerFPOff>, ND, S(FramePtr), NF
1536 Unlinks a frame constructed by DefInlineFP. `callerFPOff' is the offset of
1537 the caller's frame pointer relative to S0.
1539 | InlineReturnNoFrame<InlineFrameStart>, ND, NA, NF
1541 Mark the end of an inlined function for which no DefInlineFP was required. The
1542 primary purpose of this instruction is to mark the result of a SpillFrame as
1543 dead. InlineFrameStart is the caller FP-relative offset of the start of the
1544 callee frame. Everything below InlineFrameStart is dead.
1546 | CallArray<spOffset,numParams,callOff,after,funcd,destroyLocals>,
1548 | S(StkPtr) S(FramePtr),
1551 Invoke function corresponding to the current FPI with numParams arguments,
1552 the last of which is an array of the remaining args. Used for FCallArray (in
1553 which case numParams == 1), and FCallUnpack. S0+spOffset points to the stack
1554 resulting after the ActRec for the function and numParams arguments have been
1555 pushed. CallArray pops the array off the stack, pushes the elements of the
1556 array as arguments, and invokes the function in the ActRec.
1558 | SyncReturnBC<spOffset,bcOffset>, ND, S(StkPtr) S(FramePtr), NF
1560 Stores bcOffset into the frame at spOffset from S0 as the return bytecode
1561 address and the frame S1 as the return frame.
1563 | Call<offset,numParams,returnOff,funcd,destroyLocals>, DCall,
1564 | S(StkPtr) S(FramePtr),
1567 Transfer control to a callee, based on the pre-live activation record and set
1568 of args on the stack pointed to by S0 at `offset'. S1 is the current caller
1569 frame pointer. The `funcd' in the extra data is a Func* for the callee if we
1570 know the callee statically.
1572 | NativeImpl<func>, ND, S(FramePtr) S(StkPtr), Er
1574 Execute a call to the native builtin specified by the current function. S0
1575 and S1 should be the current vmfp and vmsp, respectively.
1577 | CallBuiltin, DBuiltin, S(FramePtr) S(StkPtr) SVar(PtrToGen,Gen,Cls,Nullptr), Er|PRc
1579 Call builtin function with N arguments. S0 and S1 should be the current vmfp
1580 and vmsp, respectively.
1582 The source and destination types correspond to C++ parameter and return types
1585 C++ type HHIR type Position
1586 ----------------- --------- --------
1587 bool Bool source, destination
1588 int64_t Int source, destination
1589 double Dbl source, destination
1590 const String& PtrToStr source
1591 const Array& PtrToArr source
1592 const Object& PtrToObj source
1593 const Variant& PtrToGen source
1594 Variant& PtrToGen source (ref param)
1595 String {Str|InitNull} destination
1596 Array {Arr|InitNull} destination
1597 Object {Obj|InitNull} destination
1598 Variant {Gen-UninitNull} destination
1600 | RetCtrl<spOff,suspendingResumed>, ND, S(StkPtr) S(FramePtr) S(Gen), T
1602 Ensure that S0 + `spOff' (in cells) is stored in rvmsp and that S1's saved
1603 frame pointer is stored in rvmfp, then return to the saved return address in
1604 S1. The return value is S2, which is passed via the rret_*() registers to
1605 the caller. The `suspendingResumed' flag indicates when this instruction is
1606 suspending a resumable rather than performing a normal function return.
1608 | AsyncRetCtrl<spOff,suspendingResumed>, ND,
1609 | S(StkPtr) S(FramePtr) S(InitNull),
1612 Ensure that S0 + `spOff` (in cells) is stored in rvmsp and that S1 is stored
1613 in rvmfp. The `suspendingResumed' flag indicates when this instruction is
1614 suspending a resumable rather than performing an async function return.
1615 Returns by leaving the TC to enterTCHelper.
1617 The return value is S2, which is passed via the rret_*() registers, and must
1618 be null---it is only used for enterTCHelper and ignored by everything else;
1619 resumed functions store their real return value into the Resumable object.
1621 | AsyncRetFast<spOff,suspendingResumed>, ND, S(StkPtr) S(FramePtr) S(Cell), T
1623 Packs retVal (S2) into registers, sync stack (S0) and calls the asyncRetCtrl
1624 unique stub. The stub unblocks parents of the async function (represented by
1625 the frame pointer S1) and determines if it's possible to resume parent
1626 directly (fast path).
1628 | AsyncSwitchFast<spOff,suspendingResumed>, ND, S(StkPtr) S(FramePtr) S(Cell), T
1630 Pass control to any pending fast resumable wait handles, bypassing the
1631 scheduler. If no fast resumables are pending, behave like AsyncRetCtrl.
1633 | LdRetVal<T>, DParam(Gen), S(FramePtr), NF
1635 Load the return value from the already-returned-from ActRec pointed to by S0
1636 into the dest. This is used by NativeImpl. TODO(#7150575): We want to make
1637 NativeImpl return a TypedValue in the C++ ABI registers.
1639 | DbgTrashRetVal, ND, S(FramePtr), NF
1641 For debugging purposes. Store kTVTrashJITRetVal to the return value slot on
1642 the activation record pointed to by S0.
1644 | ReleaseVVAndSkip, ND, S(FramePtr), B
1646 Loads the VarEnv slot off the ActRec pointed to by S0. If it is null, does
1647 nothing. If it is an ExtraArgs, deallocates the ExtraArgs structure.
1648 Otherwise it frees the VarEnv and jumps to block B. This instruction may not
1649 occur in an inlined call.
1651 | GenericRetDecRefs, ND, S(FramePtr), NF
1653 Does decrefs of all the current function's locals, where S0 is a pointer to
1654 the relevant activation record. This instruction may not occur in an inlined
1660 | StMem, ND, S(PtrToGen) S(Gen), CRc
1662 Store S1 into the location pointed to by S0.
1664 | StElem, ND, S(PtrToCell) S(Int) S(Cell), CRc
1666 Store S2 into the location given by the index S1 from base pointer S0. The
1667 index in S1 is the number of bytes from the base in S0.
1669 | StLoc<localId>, ND, S(FramePtr) S(Gen), CRc
1671 Store S1 to local number localId on the frame pointed to by S0.
1673 | StLocPseudoMain<localId>, ND, S(FramePtr) S(Gen), CRc
1675 Behaves just like StLoc, except the hard requirement that it is only emitted
1676 for pseudo-mains. We don't optimize StGbl the same way as StLoc, as we need
1677 intraprocedural analysis to know whether the store is truly dead.
1679 | StLocRange<localIds>, ND, S(FramePtr) S(Gen), CRc
1681 Store S1 to the local variables corresponding to localIds, on the frame
1684 | StClsRef<slot>, ND, S(FramePtr) S(Cls), NF
1686 Store S1 to class-ref slot `slot` on the frame pointed to by S0.
1688 | StRef, ND, S(BoxedCell) S(Cell), CRc
1690 Store the value in S1 into the RefData pointed to by S0. Stores the
1691 RefData::m_type also.
1693 | StStk<offset>, ND, S(StkPtr) S(Gen), CRc
1695 Store S1 to the stack pointed to by S0, at a given offset (in cells).
1697 | DbgTrashStk<offset>, ND, S(StkPtr), NF
1699 For debugging purposes. Store kTVTrashJITStk to the stack slot pointed to
1700 by S0, at a given offset (in cells).
1702 | DbgTrashFrame<offset>, ND, S(StkPtr), NF
1704 For debugging purposes. Store kTVTrashJITFrame to kNumActRecCells stack
1705 slots starting at the offset (in cells), and going toward higher memory
1708 | DbgTrashMem, ND, S(PtrToGen), NF
1710 For debugging purposes. Store kTVTrashJITHeap to a heap slot pointed to by
1716 | EagerSyncVMRegs, ND, S(FramePtr) S(StkPtr), NF
1718 Sync the given vmfp and vmsp to their in-memory locations.
1720 | ReqBindJmp<bcOff,transFlags>, ND, S(StkPtr) S(FramePtr), T
1722 Emit a jump to a REQ_BIND_JMP service request to the target offset bcOff.
1724 | ReqRetranslate<transFlags>, ND, S(StkPtr) S(FramePtr), T
1726 Emit a jump to a service request that will chain to a retranslation of this
1729 This instruction is used in exit traces for a type prediction that occurs at
1730 the first bytecode offset of a tracelet.
1732 | ReqRetranslateOpt<transId,bcOff>, ND, S(StkPtr) S(FramePtr), T
1734 Emit a service request to retranslate, with a higher optimization gear,
1735 translation transID, which starts at bcOff. This instruction is used in exit
1736 traces that trigger profile-guided optimizations.
1739 12. Refcounting and copies
1741 | Mov, DofS(0), S(Top), P
1743 Defines D as S0. May imply register-to-register moves at code generation
1744 time. Does not imply an incref or any other manipulation of S0.
1746 | IncRef, ND, S(Gen,Ctx), NF
1748 If S0 is a refcounted type, increment its refcount.
1750 | DecRef<locId>, ND, S(Gen,Ctx), CRc
1752 Decrease the reference count of S0 by one, and call a destructor for types
1753 that require it if it goes to zero.
1755 Note that although DecRef takes a Gen, we don't allow it to use information
1756 about the inner types of a BoxedCell. This is because we don't guard on the
1757 inner types of a BoxedCell except when doing LdRef. For any S0 that is a
1758 strict subtype of BoxedCell, the DecRef must just decref it as if it were a
1761 The locId is just a hint to the runtime indicating which local variable is
1762 being DecRef'd, if any.
1764 | DecRefNZ, ND, S(Gen,Ctx), CRc
1766 Decrease the reference count of S0 by one, do not check if it goes to zero.
1767 This instruction can be used for more efficient code when it is provable that
1768 the reference count cannot go to zero.
1773 | DefFP, D(FramePtr), NA, NF
1775 Creates a temporary D representing the current vm frame pointer.
1777 | DefSP<stackOff>, D(StkPtr), S(FramePtr), NF
1779 Creates a temporary D representing the current vm stack pointer. S0 is a
1780 pointer to the current frame. The 'stackOff' is the logical offset between S0
1781 and the stack pointer, but in the case of generators this is not the
1782 physical offset at runtime.
1784 This instruction is used at the beginning of tracelets to represent the state
1785 of the stack on entry and does not emit code.
1787 | Count, D(Int), S(Cell), Er
1789 Computes the number of elements in S0. The count of an array is the number of
1790 elements it contains, without recursing into containers in the array.
1791 Subtypes of Bool|Int|Dbl|Str|Res have a count of 1, subtypes of Null have a
1792 count of 0. The count of objects that implement the Countable interface is
1793 computed by returning the value of their count method. Objects that do not
1794 implement Countable have a count of 1.
1796 | CountArray, D(Int), S(Arr), NF
1798 | CountArrayFast, D(Int), S(Arr), NF
1800 | CountVec, D(Int), S(Vec), NF
1802 | CountDict, D(Int), S(Dict), NF
1804 | CountKeyset, D(Int), S(Keyset), NF
1806 | CountCollection, D(Int), S(Obj), NF
1808 Computes the number of elements in S0 using the same definition as Count, but
1809 with a restriction on the input type.
1811 CountArray expects any array. CountArrayFast expects an array whose kind is
1812 not kGlobalsKind or kProxyKind. CountCollection expects a collection object.
1816 Does nothing. It's sometimes useful for the simplifier to insert one of these
1817 in the instruction stream.
1819 | ExitPlaceholder, ND, NA, B
1821 Does nothing if executed. Semantically, this instruction carries a taken edge
1822 to a block that was a pure side-exit during initial IR generation. This
1823 allows later passes to test conditions and create new exits from the region
1824 at this point in the program.
1828 | VerifyParamCls, ND, S(Cls) S(Cls|Nullptr) C(Int) C(Int), Er
1830 Verify parameter type for classes or traits. If S0 does not extend (if S1 is
1831 a class) or implement (if S1 is an interface) S1, this instruction will raise
1832 a recoverable fatal error describing the type mismatch.
1834 | VerifyParamCallable, ND, S(Gen) C(Int), Er
1836 If S0 is not callable, as defined by the php function is_callable, this
1837 instruction will raise a recoverable fatal error describing the type
1840 | VerifyParamFail, ND, C(Int), Er
1842 Assumes that parameter number S0 in the current function has failed a its
1843 type check. Depending on the typehint being verified and a number of runtime
1844 options, may coerce the parameter to the correct type or raise a recoverable
1845 fatal error describing the type mismatch.
1847 | VerifyParamFailHard, ND, C(Int), Er|T
1849 A terminal version of VerifyParamFail, to be used when the compiler can
1850 statically prove that this failure will result in a fatal error rather than a
1853 | VerifyRetCallable, ND, S(Gen), Er
1855 Verify a return type hint.
1857 | VerifyRetCls, ND, S(Cls) S(Cls|Nullptr) C(Int) S(Cell), Er
1859 Verify a return type hint.
1861 | VerifyRetFail, ND, S(PtrToGen), Er
1863 Failure to verify a return type hint.
1865 | RaiseUninitLoc<localId>, ND, S(Str), Er
1867 Raise a notice for an uninitialized local variable.
1869 | RaiseUndefProp, ND, S(Obj) CStr, Er
1871 Raise a notice for an undefined property named S1 on the class of S0.
1873 | RaiseMissingArg<func,argc>, ND, NA, Er
1875 Raise a missing argument warning because only S1 arguments were passed to
1878 | RaiseError, ND, S(Str), T|Er
1880 Raises a fatal error with the text in S0 as its message.
1882 | RaiseWarning, ND, S(Str), Er
1884 Raises a warning with the text in S0 as its message.
1886 | RaiseNotice, ND, S(Str), Er
1888 Raises a notice with the text in S0 as its message.
1890 | RaiseArrayIndexNotice, ND, S(Int), Er
1892 Raises a notice that S0 is an undefined index for an array.
1894 | RaiseArrayKeyNotice, ND, S(StaticStr), Er
1896 Raises a notice that S0 is an undefined key for an array.
1898 | RaiseMissingThis, ND, S(Func), Er
1900 Raises an appropriate notice or fatal to indicate that Func was
1901 called with null $this. In most cases its a notice, but for
1902 builtins and special class methods its a fatal.
1904 | FatalMissingThis, ND, S(Func), T|Er
1906 Similar to RaiseMissingThis, but for cases where we know it will fatal.
1908 | RaiseVarEnvDynCall, ND, S(Func), Er
1910 Indicates that Func, which can access the caller's environment, was called
1911 dynamically. Depending on the setting of the `DisallowDynamicVarEnvFuncs`
1912 runtime option, this opcode might fatal, raise a warning, or do nothing. Used
1913 inside generated wrapper functions for builtins which can modify the caller's
1914 frame. These wrapper functions are called instead of the builtin when the
1915 builtin is called dynamically. Func should refer to the builtin, not the
1918 | RaiseHackArrCompatNotice, ND, S(Str), Er
1920 Raises a Hack array compat notice with the text in S0 as its message.
1922 | InitClosureStaticLoc, ND, S(BoxedCell) S(Cell), NF
1924 Assuming S0 is an uninitialized closure static local, initialize it by
1925 setting it to the value in S1.
1927 | InitStaticLoc<func,staticLocalName>, D(BoxedInitCell), S(Cell), NF
1929 Initialize the static local variable named 'staticLocalName' for
1930 function 'func' with S0 and return it.
1932 | InitClsCns<className,constName>, DCns, NA, Er|PRc
1934 Initialize the RDS entry for a constant for a class, invoking autoload if it
1935 is not defined. The initialized value is returned. This instruction may raise
1936 an undefined constant error if autoload cannot define the constant.
1938 | PrintStr, ND, S(Str), Er|CRc
1940 | PrintInt, ND, S(Int), Er|CRc
1942 | PrintBool, ND, S(Bool), Er|CRc
1944 Print for various types.
1946 | ConcatIntStr, D(Str), S(Int) S(Str), Er|PRc
1948 Concatenate S0 and S1 after converting S0 to String.
1950 | ConcatStrInt, D(Str), S(Str) S(Int), Er|CRc|PRc
1952 Concatenate S0 and S1 after converting S1 to String.
1954 | ConcatStrStr, D(Str), S(Str) S(Str), Er|CRc|PRc
1956 Concatenate S0 and S1.
1958 | ConcatStr3, D(Str), S(Str) S(Str) S(Str), Er|CRc|PRc
1960 Concatenate S0, S1, and S2.
1962 | ConcatStr4, D(Str), S(Str) S(Str) S(Str) S(Str), Er|CRc|PRc
1964 Concatenate S0, S1, S2, and S3.
1966 | AddElemStrKey, D(Arr), S(Arr) S(Str) S(Cell), Er|CRc|PRc
1968 Add S2 to the array S0 for the key S1, and return the resulting array.
1970 | AddElemIntKey, D(Arr), S(Arr) S(Int) S(Cell), Er|CRc|PRc
1972 Add S2 to the array S0 for the key S1, and return the resulting array.
1974 | AddNewElem, D(Arr), S(Arr) S(Cell), Er|CRc|PRc
1976 Add S1 as a new element to the array S0. (Note: S1 must actually be a
1977 subtype of InitCell for array invariants, but we can't assert this yet in the
1978 IR because many eval stack slots are not entirely typed wrt initness right
1981 | DictAddElemStrKey, D(Dict), S(Dict) S(Str) S(Cell), Er|CRc|PRc
1983 Add S2 to the dict S0 for the key S1, and return the resulting dict.
1985 | DictAddElemIntKey, D(Dict), S(Dict) S(Int) S(Cell), Er|CRc|PRc
1987 Add S2 to the dict S0 for the key S1, and return the resulting dict.
1989 | ArrayAdd, D(Arr), S(Arr) S(Arr), Er|CRc|PRc
1991 Has the effects of the php + operator on the two source arrays.
1993 | AKExistsArr, D(Bool), S(Arr) S(Int,Str), NF
1995 Has the effects of array_key_exists(S0, S1).
1997 | AKExistsDict, D(Bool), S(Dict) S(Int,Str), NF
1999 Has the effects of array_key_exists(S0, S1).
2001 | AKExistsKeyset, D(Bool), S(Keyset) S(Int,Str), NF
2003 Has the effects of array_key_exists(S0, S1).
2005 | AKExistsObj, D(Bool), S(Obj) S(Int,Str), Er
2007 Has the effects of array_key_exists(S0, S1) on an object S0. This either does
2008 collection accesses, or uses the ArrayAccess API.
2010 | GetMemoKey, DMemoKey, S(Cell), Er|PRc
2012 Given a cell, produces a string or an int that can be used as a memoize cache
2013 key. Valid values for the input include all basic types, arrays and
2014 collections, and objects that implement IMemozieParam. Any other type will
2015 cause GetMemoKey to throw. This op can only be used within functions marked
2016 as memoize wrappers.
2018 | ArrayIdx, D(Gen), S(Arr) S(Int,Str) S(Cell), NF
2020 Checks if S0 contains the key S1, and returns the result if found. Otherwise
2023 | DictIdx, DDictElem, S(Dict) S(Int,Str) S(Cell), NF
2025 Checks if S0 contains the key S1 and returns the result if found. Otherwise
2028 | KeysetIdx, DKeysetElem, S(Keyset) S(Int,Str) S(Cell), NF
2030 Checks if S0 contains the key S1 and returns the result if found. Otherwise
2033 | MapIdx, D(Gen), S(Obj) S(Str) S(Cell), NF
2035 Checks if S0, which must be an HH\Map or an HH\ImmMap, contains the key S1,
2036 and returns the result if found. Otherwise S2 is returned.
2038 | MethodExists, D(Bool), S(Cls) S(Str), NF
2040 Checks if the method named S1 exists on class S0. S0 must be a normal class
2041 that is not abstract.
2043 | LdBindAddr<SrcKey,spOff>, D(TCA), NA, NF
2045 Creates a service request to bind the given target address. Returns a TCA
2046 pointing either to the service request (before the service request is
2047 satisfied) or to the native code for the given target address (once the
2048 service request is satisfied).
2050 | LdSwitchDblIndex, D(Int), S(Dbl) S(Int) S(Int), NF
2052 | LdSwitchStrIndex, D(Int), S(Str) S(Int) S(Int), CRc
2054 | LdSwitchObjIndex, D(Int), S(Obj) S(Int) S(Int), CRc|Er
2056 These instructions are used to determine the target of a switch statement
2057 with target range [S1:S1 + S2), when invoked with the value S0. They call
2058 helper functions to check whether S0 is an numeric integer in the range
2059 [S1:S1 + S2), and if so return the value S1 - (Int)S0. Else, they return the
2060 target of the default target, S2 + 1.
2062 | LdSSwitchDestFast, D(TCA), S(Gen), NF
2064 | LdSSwitchDestSlow, D(TCA), S(Gen), Er
2066 Load string switch destinations (two different compilation strategies).
2068 | InterpOne<T,spOff,bcOff,numPopped,numPushed>, ND,
2069 | S(StkPtr) S(FramePtr),
2072 Call the interpreter implementation function for one opcode. S0 + `spOff' (in
2073 cells) and S1 are, respectively, the VM stack and frame pointers before this
2074 instruction. T is only present if the instruction pushes to the stack, in
2075 which case it is the type of the top stack element after the call. `bcOff' is
2076 the bytecode offset. `numPopped' is the number of stack cells consumed by the
2077 instruction, and `numPushed' is the number of stack cells produced by the
2080 | InterpOneCF<T,bcOff,numPopped,numPushed>, ND,
2081 | S(StkPtr) S(FramePtr),
2084 Similar to InterpOne, but for instructions that may modify vmpc. This is
2085 implemented as a tail call to a stub, so any exceptions thrown will be thrown
2086 in the context of the stub, not the InterpOneCF instruction.
2088 | OODeclExists<kind>, D(Bool), S(Str) S(Bool), Er
2090 Returns a bool indicating whether the class, interface, or trait named by S0
2091 exists. Invokes autoload if S1 is true.
2093 | SetOpCell<op>, ND, S(PtrToCell) S(Cell), Er
2095 Performs S0 <op>= S1.
2097 | GetTime, D(Dbl), NA, NF
2099 Returns a double of the current time in seconds.
2101 | KillClsRef<slot>, ND, S(FramePtr), NF
2103 Mark the class-ref slot `slot` in frame S0 as no longer containing a
2104 meaningful value. This is used to aid in memory analysis. In debugging
2105 builds, it may overwrite the slot with a poison value.
2107 15. Generators & Closures
2109 | LdClosureCtx, DCtx, S(Obj), NF
2111 Load the context from the closure object S0 into D.
2112 May only be used in S0's closure Func.
2114 | StClosureCtx, ND, S(Obj) S(Ctx,Nullptr), CRc
2116 Store the context represented by S1 into the closure object S0. S1 may be a
2117 Nullptr when there is no context (i.e. the closure is being used in a
2120 | StClosureArg<offsetBytes>, ND, S(Obj) S(Gen), CRc
2122 Store one of the closure environment arguments (i.e. from the closure's use
2123 clause) from S1 into the closure object S0.
2125 | CreateCont, D(Obj), S(FramePtr) C(Int) S(TCA,Nullptr) C(Int), PRc
2127 Create a Generator object and suspend the ActRec provided by S0 into its
2128 embedded ActRec, allocating S1 slots for locals/iterators. Set the native
2129 resume address to S2 and resume offset to S3.
2131 | CreateAFWH, DAllocObj,
2132 | S(FramePtr) C(Int) S(TCA,Nullptr) C(Int) S(Obj),
2135 Create an AsyncFunctionWaitHandle object and suspend the ActRec provided by
2136 S0 into its embedded ActRec, allocating S1 slots for locals/iterators. Set
2137 the native resume address to S2, resume offset to S3, and mark it blocked on
2138 non-finished child S4.
2140 | CreateAFWHNoVV, DAllocObj,
2141 | S(FramePtr) C(Int) S(TCA,Nullptr) C(Int) S(Obj),
2144 Create an AsyncFunctionWaitHandle object and suspend the ActRec provided by
2145 S0 into its embedded ActRec, allocating S1 slots for locals/iterators. Set
2146 the native resume address to S2, resume offset to S3, and mark it blocked on
2147 non-finished child S4. This version of the instruction guarantees that the
2150 | CreateSSWH, DAllocObj, S(Cell), CRc|PRc
2152 Call c_StaticWaitHandle::CreateSucceeded.
2154 | AFWHPrepareChild, ND, S(FramePtr) S(Obj), Er
2156 Prepare unfinished WaitableWaitHandle object specified by S1 for getting
2157 awaited by an AsyncFunctionWaitHandle object specified by its ActRec
2160 Injects S1 into the currently running scheduler instance and performs
2161 cross-scheduler and intra-scheduler cycle detection. Throws if the
2162 dependency cannot be established.
2164 | ContEnter<spOffset,returnBCOffset>, ND,
2165 | S(StkPtr) S(FramePtr) S(FramePtr) S(TCA),
2168 Enters a generator body. S0 + `spOffset' (in cells) is a pointer to the
2169 stack, S1 is the current frame pointer, S2 is the generator frame pointer
2170 embedded in the Generator object, and S3 is the address to jump to. The
2171 `returnBCOffset' will be stored to the m_soff field of the pre-live ActRec on
2174 | ContPreNext, ND, S(Obj) C(Bool), B
2176 Performs operations needed for the next() method of Generator object S0.
2177 If the generator is already running or finished, or it was not started yet
2178 and the S1 check-started flag is set, the branch B is taken. Otherwise,
2179 the generator is marked as running.
2181 | ContStartedCheck, ND, S(Obj), B
2183 Checks if the Generator object S0 has started, and if not branches to
2186 | ContValid, D(Bool), S(Obj), NF
2188 Return true if a generator is not done, false otherwise.
2190 | ContStarted, D(Bool), S(Obj), NF
2192 Return true if a generator has been run at least once, i.e. is not in the
2193 Created state, false otherwise.
2195 | ContArIncKey, ND, S(FramePtr), NF
2197 Special-case key update for generator, ActRec of which is S0, which
2198 increments the key of a generator if that generator's key is an Int.
2199 This will cause undefined behavior if the generator's key is not an Int.
2201 | ContArIncIdx, D(Int), S(FramePtr), NF
2203 Increment the internal index in the Generator in S0, and return the new index
2206 | ContArUpdateIdx, ND, S(FramePtr) S(Int), NF
2208 Updates the internal index of generator with S1 if necessary, i.e. if S1
2209 is larger than the index. S0 is the pointer to the embedded ActRec.
2211 | LdContActRec, D(FramePtr), S(Obj), NF
2213 Loads the Generator object's ActRec, given a pointer to the generator
2216 | LdContResumeAddr, D(TCA), S(Obj), NF
2218 Load the resume addr from the Generator in S0.
2220 | StContArState<state>, ND, S(FramePtr), NF
2222 Change the state of the Generator object which has frame pointer S0.
2224 | StContArResume<offset>, ND, S(FramePtr) S(TCA), NF
2226 Store the resume address S1 into the Generator whose ActRec is given by S0,
2227 marking the offset to resume at as `offset'.
2229 | LdContArValue, DParam(Cell), S(FramePtr), PRc
2231 Loads 'value' from the Generator object ActRec of which is S0.
2233 | StContArValue, ND, S(FramePtr) S(Cell), CRc
2235 Stores 'value' into the Generator object ActRec of which is S0. S1 is the
2238 | LdContArKey, DParam(Cell), S(FramePtr), PRc
2240 Loads 'key' from the Generator object ActRec of which is S0.
2242 | StContArKey, ND, S(FramePtr) S(Gen), CRc
2244 Stores 'key' into the Generator object ActRec of which is S0. S1 is the
2247 | StAsyncArSucceeded, ND, S(FramePtr), NF
2249 Mark the AsyncFunctionWaitHandle object whose ActRec is given by S0 as
2252 | StAsyncArResume<offset>, ND, S(FramePtr) S(TCA), NF
2254 Store the resume address S1 into the AsyncFunctionWaitHandle whose ActRec is
2255 given by S0, marking the offset to resume at as `offset'.
2257 | StAsyncArResult, ND, S(FramePtr) S(Cell), CRc
2259 Stores result into the AsyncFunctionWaitHandle object ActRec of which is S0.
2262 | LdAsyncArParentChain, D(ABC), S(FramePtr), NF
2264 Loads the first parent of the AsyncFunctionWaitHandle object ActRec of which
2267 | AFWHBlockOn, ND, S(FramePtr) S(Obj), CRc
2269 Establish dependency between parent AsyncFunctionWaitHandle object, whose
2270 ActRec is given by S0, and child WaitableWaitHandle object referenced by S1.
2272 | ABCUnblock, ND, S(ABC), NF
2274 Calls AsioBlockableChain::Unblock. This instruction may not occur in an
2277 | LdWHState, D(Int), S(Obj), NF
2279 Loads the state of the WaitHandle in S0, which is a value from the wait
2280 handle states in ext_asio.h. This instruction has undefined behavior if S0 is
2283 | LdWHResult, DParam(Gen), S(Obj), NF
2285 Loads the result of the WaitHandle in S0. This instruction has undefined
2286 behavior if S0 is not a WaitHandle, or if S0 is not finished.
2288 | LdAFWHActRec, D(FramePtr), S(Obj), NF
2290 Loads the AsyncFunctionWaitHandle object's ActRec, given a pointer to the
2291 AsyncFunctionWaitHandle object in S0.
2293 | LdResumableArObj, D(Obj), S(FramePtr), NF
2295 Loads the Resumable object, given a Resumable's frame pointer in S0.
2298 16. Debugging, instrumentation, and profiling
2300 | IncStat, ND, C(Int) C(Int) C(Bool), NF
2302 Increment stat counter. S0 is the implementation defined stat counter index,
2303 S1 is the amount to increment the counter (may be negative), and S2 is a
2304 'force' flag. This opcode becomes a noop iff (force == false and runtime
2305 stats are not enabled) at translation time.
2307 | IncStatGrouped, ND, CStr CStr C(Int), NF
2309 Adds the value S2 to the counter named S1, in the category S0.
2311 | IncProfCounter<TransID>, ND, NA, NF
2313 Increment the profiling counter associated with translation TransID.
2315 | DbgAssertRefCount, ND, S(Gen,TCtx), NF
2317 Assert that S0 has a valid refcount. If S0 has a reference counted type and
2318 its count is implausible then execute a hardware trap instruction.
2320 | DbgTraceCall<spOffset>, ND, S(FramePtr) S(StkPtr), NF
2322 When EvalHHIRGenerateAsserts is on, this instruction is inserted at the
2323 start of each region, to emit some sanity checking code.
2325 | DbgAssertARFunc<offset>, ND, S(StkPtr) S(Func), NF
2327 Assert that S1 is the function in the ActRec given by s0+offset. If the
2328 assertion fails, execution is aborted via a hardware exception.
2330 | RBTraceEntry, ND, NA, NF
2332 | RBTraceMsg, ND, NA, NF
2334 Ring buffer tracing.
2336 | ZeroErrorLevel, D(Int), NA, NF
2338 | RestoreErrorLevel, ND, S(Int), NF
2340 Helper instructions for fast implementation of the PHP error silencing
2346 | IterInit<IterData>, D(Bool), S(ArrLike,Obj) S(FramePtr), Er|CRc
2348 | IterInitK<IterData>, D(Bool), S(ArrLike,Obj) S(FramePtr), Er|CRc
2350 | WIterInit<IterData>, D(Bool), S(ArrLike,Obj) S(FramePtr), Er|CRc
2352 | WIterInitK<IterData>, D(Bool), S(ArrLike,Obj) S(FramePtr), Er|CRc
2354 | MIterInit<T,IterData>, D(Bool), S(BoxedCell) S(FramePtr), Er
2356 | MIterInitK<T,IterData>, D(Bool), S(BoxedCell) S(FramePtr), Er
2358 <IterData> consists of three indices, iterId, keyId and valId. iterId is
2359 the index of the iterator variable, keyId and valId are indices of local
2362 Initializes the iterator variable whose index is given by iterId.
2363 This instruction creates the appropriate iterator for the array or object that
2364 S0 references, and rewinds the new iterator to its start. S0 points to the
2365 stack frame containing the iterator and local variables with the indices
2366 iterId, keyId and valId.
2368 If the new iterator is at its end (i.e., has no elements to iterate over),
2369 this instruction decrements the refcount of S0 and returns false; otheriwse,
2370 it stores a reference to S0 in the new iterator and returns true. If the
2371 iterator is not at its end, then this instruction stores the iterator's first
2372 value (and key) into the local variable with index valId (and keyId,
2375 The IterInit and IterInitK instructions always copy the array element by
2378 The WIterInit and WIterInitK instructions copy referenced array elements by
2379 reference, and non-referenced array elements by value.
2381 The MIterInit and MIterInitK instructions always copy the array element by
2382 reference, and take a type parameter indicating the inner type of S0. (This
2383 must have been proven via guards prior to running this opcode.) Right now T
2386 This instruction has the ConsumesRC property because it either decrements the
2387 reference count of S0 or stores a reference to S0 into the new iterator.
2389 | IterNext<IterData>, D(Bool), S(FramePtr), Er
2391 | IterNextK<IterData>, D(Bool), S(FramePtr), Er
2393 | WIterNext<IterData>, D(Bool), S(FramePtr), Er
2395 | WIterNextK<IterData>, D(Bool), S(FramePtr), Er
2397 | MIterNext<IterData>, D(Bool), S(FramePtr), NF
2399 | MIterNextK<IterData>, D(Bool), S(FramePtr), NF
2401 <IterData> consists of three indices, iterId, keyId and valId. iterId is
2402 the index of the iterator variable, keyId and valId are indices of local
2403 variables. S0 points to the stack frame containing the iterator and local
2404 variables with the indices iterId, keyId and valId.
2406 Advances the iterator variable whose index is given by iterId.
2408 If the iterator has reached the end, this instruction frees the iterator
2409 variable and returns false; otherwise, it returns true. If the iterator has
2410 not reached its end, then this instruction stores the iterator's next value
2411 (and key) into the local variable with index valId (and keyId, respectively).
2413 The IterInit and IterInitK instructions always copy the array element by
2414 value. The WIterInit and WIterInitK instructions copy referenced array
2415 elements by reference, and non-referenced array elements by value. The
2416 MIterNext and MIterNextK instructions always copy the array element by
2419 | IterFree, ND, S(FramePtr), NF
2421 | MIterFree, ND, S(FramePtr), NF
2423 Free the iterator variable whose index is given by S1 in the stack frame
2426 | DecodeCufIter<iterId>, D(Bool), S(ArrLike,Obj,Str) S(FramePtr), Er
2428 Decode S0 as a callable, and write the decoded values to the iterator
2429 specified by IterId. Returns true iff it successfully decoded the callable.
2430 Does not raise warnings, or throw exceptions.
2432 | CIterFree<iterId>, ND, S(FramePtr), NF
2434 Free the iterator variable whose index is given by IterId in the stack frame
2438 18. Member instruction support
2440 | LdMIStateAddr, D(PtrToMISGen), C(Int), NF
2442 Load an MInstrState address. Returns a pointer to offset S0 within the
2443 current MInstrState.
2445 | LdMBase, DParam(PtrToGen), NA, NF
2447 Load the current value of the member base register.
2449 | StMBase, ND, S(PtrToGen), NF
2451 Store a new value to the member base register. It is illegal for any
2452 instruction other than StMBase or InterpOne (when interpreting a member
2453 instruction) to modify the member base register.
2455 | FinishMemberOp, ND, NA, NF
2457 Mark the end of a member operation. This has no effect at runtime but exists
2458 to provide information for certain optimizations.
2460 All of the remaining opcodes in this section are simple wrappers around helper
2461 functions (specified in S0) to perform the corresponding vector operation. If
2462 S1 is a ConstCls it represents the context class for the operation.
2464 SetElem, SetProp, and SetNewElem are used to implement part of the SetM hhbc
2465 opcode, which almost always pushes its first stack input or a CountedStr as its
2466 stack result. The combinations of input types that cause SetM to push anything
2467 other than those two values are vanishingly rare in correct PHP programs, so
2468 these three instructions have been optimized for the common cases. SetNewElem
2469 and SetProp have no destination, allowing the compiler to predict that the
2470 SetM's output will be the same as its input (and optimize accordingly). If that
2471 turns out to not be the case at runtime, the instruction will throw an
2472 InvalidSetMException. The exception will hold a Cell containing the value the
2473 SetM should push on the stack instead of its input value. The runtime is
2474 responsible for catching this exception, finishing execution of the SetM
2475 instruction, pushing the value from the exception on the stack, and proceeding
2476 as appropriate (most likely with a side exit to the next bytecode instruction,
2477 since it has pushed an unexpected type onto the stack).
2479 SetElem is similar to SetProp and SetNewElem but can also be used for setting
2480 characters within strings. When given a string base and a valid offset, SetElem
2481 returns a string representation of the newly inserted character. In all other
2482 cases it returns nullptr or throws an InvalidSetMException. It will throw this
2483 exception when it detects invalid input types, or when trying to set a string
2484 offset that would grow the string beyond the maximum supported size.
2486 The input types that will cause the errors described above are listed here:
2488 SetNewElem will fail if the base is not a subtype of {Null|Str|Arr|Obj} and not
2490 SetElem has the same base constraint as SetNewElem. In addition, the key must
2491 not be a subtype of {Arr|Obj}.
2492 SetProp will fail if the base is not a subtype of {Obj|Null}.
2494 Any instructions that take a pointer to an MInstrState struct use the various
2495 fields of that struct for holding intermediate values.
2497 | BaseG, D(PtrToRMembCell), S(Str), Er
2499 Get a base from global named S0.
2501 NB: BaseG returns either a PtrToGblGen, OR a pointer to a ref that is rooted
2502 in a GblGen. (I.e. the unbox happens in the C++ helper that this instruction
2503 calls.) If it is not a defining BaseG it can also return the
2504 init_null_variant, so for now it returns a PtrToRMembCell.
2506 | PropX, D(PtrToMembGen), S(Obj,PtrToGen) S(Cell) S(PtrToMISGen), Er
2508 Lookup intermediate property in S0, with key S1.
2510 | PropQ, D(PtrToMembGen), S(Obj,PtrToGen) S(StaticStr) S(PtrToMISGen), Er
2512 A nullsafe version of PropX, returns null if the base S0 is null.
2514 | PropDX, D(PtrToMembGen), S(Obj,PtrToGen) S(Cell) S(PtrToMISGen), MProp|Er
2516 Like PropX, but used for intermediate element lookups that may modify the
2519 | CGetProp, D(Cell), S(Obj,PtrToGen) S(Cell), PRc|Er
2521 Get property with key S1 from S0.
2523 | CGetPropQ, D(Cell), S(Obj,PtrToGen) S(StaticStr), PRc|Er
2525 A nullsafe version of CGetProp, returns null if the base S0 is null.
2527 | VGetProp, D(BoxedInitCell), S(Obj,PtrToGen) S(Cell), MProp|PRc|Er
2529 Get property with key S1 from base S0 as a reference.
2532 | S(Obj,PtrToGen) S(Cell) S(BoxedCell),
2535 Bind property with key S1 in base S0 to the reference in S2.
2537 | SetProp, ND, S(Obj,PtrToGen) S(Cell) S(Cell), MProp|Er
2539 Set property with key S1 in S0 to S2.
2541 | UnsetProp, ND, S(Obj,PtrToGen) S(Cell), Er
2543 Unset an object property.
2545 | SetOpProp<op>, D(Cell),
2546 | S(Obj,PtrToGen) S(Cell) S(Cell),
2549 Set op propery with key S1 in base S0, using S2 as the right hand side.
2551 | IncDecProp<op>, D(Cell),
2552 | S(Obj,PtrToGen) S(Cell),
2555 Increment/decrement property with key S1 in base S0.
2557 | EmptyProp, D(Bool), S(Obj,PtrToGen) S(Cell), Er
2559 Returns true iff the property with key S1 in base S0 is empty.
2561 | IssetProp, D(Bool), S(Obj,PtrToGen) S(Cell), Er
2563 Returns true iff the property with key S1 in base S0 is set.
2565 | ElemX, D(PtrToMembGen), S(PtrToGen) S(Cell) S(PtrToMISGen), Er
2567 Get intermediate element with key S1 from base S0. The base will not be
2570 | ProfileMixedArrayOffset, ND, S(Arr) S(Int,Str), NF
2572 Profile the offset of the element keyed by S1 in S0.
2574 | CheckMixedArrayOffset<pos>, ND, S(AK(Mixed)) S(Int,Str), B
2576 Check that `pos' is within the usage bounds of S0 (including tombstones), and
2577 that S1 exactly matches the element key of S0 at `pos'. If any of the checks
2578 fail, branch to B. This check is allowed to have false negatives, in the
2579 case of int-like strings.
2581 | CheckArrayCOW, ND, S(ArrLike), B
2583 Check that S0 has a refcount of exactly 1; if not, branch to B.
2585 | ProfileDictOffset, ND, S(Dict) S(Int,Str), NF
2587 Profile the offset of the element keyed by S1 in S0.
2589 | CheckDictOffset<pos>, ND, S(Dict) S(Int,Str), B
2591 Check that `pos' is within the usage bounds of S0 (including tombstones), and
2592 that S1 exactly matches the element key of S0 at `pos'. If any of the checks
2593 fail, branch to B. This check is allowed to have false negatives.
2595 | ProfileKeysetOffset, ND, S(Keyset) S(Int,Str), NF
2597 Profile the offset of the element keyed by S1 in S0.
2599 | CheckKeysetOffset<pos>, ND, S(Keyset) S(Int,Str), B
2601 Check that `pos' is within the usage bounds of S0 (including tombstones), and
2602 that S1 exactly matches the element key of S0 at `pos'. If any of the checks
2603 fail, branch to B. This check is allowed to have false negatives.
2605 | ElemArray, D(PtrToMembGen), S(Arr) S(Int,Str), Er
2607 | ElemArrayW, D(PtrToMembGen), S(Arr) S(Int,Str), Er
2609 | ElemArrayD<T>, D(PtrToElemGen), S(PtrToGen) S(Int,Str), MElem|Er
2611 | ElemArrayU<T>, D(PtrToMembGen), S(PtrToGen) S(Int,Str), MElem|Er
2613 Similar to ElemX, but the base S0 is an array and the key S1 is an int/str.
2614 ElemArrayW is for Warn member instrs, ElemArrayD is for Define member instrs,
2615 and ElemArrayU is for Unset.
2617 ElemArray{D,U} both take a PtrToGen for the base operand, but expect it to be
2618 a PtrToArr or PtrToBoxedArr. T is the type of the base array.
2620 | ElemMixedArrayK<pos>, D(PtrToElemGen), S(AK(Mixed)) S(Int,Str), NF
2622 Like ElemArray, but the element for S1 is at a known position `pos' in S0.
2624 | ElemVecD<T>, D(PtrToElemCell), S(PtrToGen) S(Int), MElem|Er
2626 | ElemVecU<T>, D(PtrToMembCell), S(PtrToGen) S(Int), MElem|Er
2628 Similar to ElemX, but the base S0 is a vec and the key S1 is an int. ElemVecD
2629 is for Define member instrs and ElemVecU is for Unset. (Other variations can
2630 be implemented without special IR instructions).
2632 ElemVec{D,U} both take a PtrToGen for the base operand, but expect it to be a
2633 PtrToVec or PtrToBoxedVec. T is the type of the base vec.
2635 | ElemDict, D(PtrToMembCell), S(Dict) S(Int,Str), Er
2637 | ElemDictW, D(PtrToMembCell), S(Dict) S(Int,Str), Er
2639 | ElemDictD<T>, D(PtrToElemCell), S(PtrToGen) S(Int,Str), MElem|Er
2641 | ElemDictU<T>, D(PtrToMembCell), S(PtrToGen) S(Int,Str), MElem|Er
2643 Similar to ElemX, but the base S0 is a dict and the key S1 is an int/str.
2644 ElemDictW is for Warn member instrs, ElemDictD is for Define member instrs,
2645 and ElemDictU is for Unset.
2647 ElemDict{D,U} both take a PtrToGen for the base operand, but expect it to be
2648 a PtrToDict or PtrToBoxedDict. T is the type of the base array.
2650 | ElemDictK<pos>, D(PtrToElemCell), S(Dict) S(Int,Str), NF
2652 Like ElemDict, but the element for S1 is at a known position `pos' in S0.
2654 | ElemKeyset, D(PtrToMembCell), S(Keyset) S(Int,Str), Er
2656 | ElemKeysetW, D(PtrToMembCell), S(Keyset) S(Int,Str), Er
2658 | ElemKeysetU<T>, D(PtrToMembCell), S(PtrToGen) S(Int,Str), MElem|Er
2660 Similar to ElemX, but the base S0 is a keyset and the key S1 is an int/str.
2661 ElemKeysetW is for Warn member instrs and ElemKeysetU is for Unset.
2663 ElemKeysetU both take a PtrToGen for the base operand, but expect it to be
2664 a PtrToKeyset or PtrToBoxedKeyset. T is the type of the base array.
2666 | ElemKeysetK<pos>, D(PtrToElemCell), S(Keyset) S(Int,Str), NF
2668 Like ElemKeyset, but the element for S1 is at a known position `pos' in S0.
2670 | ElemDX, D(PtrToMembGen), S(PtrToGen) S(Cell) S(PtrToMISGen), MElem|Er
2672 Like ElemX, but used for intermediate element lookups that may modify the
2675 | ElemUX, D(PtrToMembGen), S(PtrToGen) S(Cell) S(PtrToMISGen), MElem|Er
2677 Like ElemX, but used for intermediate element lookups that may modify the
2678 base as part of an unset operation.
2680 | ArrayGet, DArrElem, S(Arr) S(Int,Str), Er
2682 Get element with key S1 from base S0.
2684 | MixedArrayGetK<pos>, DArrElem, S(AK(Mixed)) S(Int,Str), NF
2686 Like ArrayGet, but the element for S1 is at a known position `pos' in S0.
2688 | DictGet, DDictElem, S(Dict) S(Int,Str), Er
2690 Get element with key S1 from base S0, throwing if the element is not present.
2692 | DictGetQuiet, DDictElem, S(Dict) S(Int,Str), NF
2694 Get element with key S1 from base S0, returning null if the element is not
2697 | DictGetK<pos>, DDictElem, S(Dict) S(Int,Str), NF
2699 Like DictGet, but the element for S1 is at a known position `pos' in S0.
2701 | KeysetGet, DKeysetElem, S(Keyset) S(Int,Str), Er
2703 Get element with key S1 from base S0, throwing if the element is not present.
2705 | KeysetGetQuiet, DKeysetElem, S(Keyset) S(Int,Str), NF
2707 Get element with key S1 from base S0, returning null if the element is not
2710 | KeysetGetK<pos>, DKeysetElem, S(Keyset) S(Int,Str), NF
2712 Like KeysetGet, but the element for S1 is at a known position `pos' in S0.
2714 | StringGet, D(StaticStr), S(Str) S(Int), PRc|Er
2716 Get string representing character at position S1 from base string S0. Raises
2717 a notice if the position is out of bounds.
2719 | MapGet, D(Cell), S(Obj) S(Int,Str), PRc|Er
2721 Get element with key S1 from base S0.
2723 | CGetElem, D(Cell), S(PtrToGen) S(Cell), PRc|Er
2725 Get element with key S1 from S0.
2727 | VGetElem, D(BoxedInitCell), S(PtrToGen) S(Cell), MElem|PRc|Er
2729 Get element with key S1 from base S0 as a reference.
2731 | MemoGet<loc-begin, loc-count>, D(Cell), S(FramePtr) S(PtrToGen), PRc
2733 Perform a memoize cache lookup using S1. S1 must point to a dict serving as a
2734 memoize cache, or point to a RefData containing such a dict. The keys used
2735 are read from the exclusive local range [loc_begin, loc_begin+loc_count]
2736 (where S0 is the pointer to the frame containing the locals). If the lookup
2737 is successful, the element is returned (already inc-refd). If the element
2738 is not found, Uninit is returned. This op can only be used inside a function
2739 marked as a memoize wrapper.
2741 | MemoSet<loc-begin, loc-count>, ND, S(FramePtr) S(PtrToGen) S(Cell), MElem
2743 Store S2 in the memoize cache given by S1. S1 must point to a dict serving as
2744 a memoize cache or point to a RefData containing such a dict. They keys used
2745 as read from the exclusive local range [loc_begin, loc_begin+loc_count]
2746 (where S0 is the pointer to the frame containing the locals). S2 must not be
2747 Uninit and will be inc-refd by the operation internally. This op can only be
2748 used inside a function marked as a memoize wrapper.
2750 | BindElem, ND, S(PtrToGen) S(Cell) S(BoxedCell), MElem|Er
2752 Bind element with key S1 in base S0 to the reference S2.
2754 | ArraySet, D(Arr), S(Arr) S(Int,Str) S(Cell), PRc|CRc|Er
2756 Set element with key S1 in S0 to S2. The dest will be a new Array that should
2759 | ArraySetRef, ND, S(Arr) S(Int,Str) S(Cell) S(BoxedCell), CRc|Er
2761 Like ArraySet, but for binding operations on the array. S3 must point to a
2762 RefData with an array type when this instruction is executed, and it must be
2763 the same array that is in S0.
2765 | VecSet, D(Vec), S(Vec) S(Int) S(Cell), PRc|CRc|Er
2767 Set element with key S1 in S0 to S2. The dest will be a new Vec that should
2770 | VecSetRef, ND, S(Vec) S(Int) S(Cell) S(BoxedCell), CRc|Er
2772 Like VecSet, but for binding operations on the vec. S3 must point to a
2773 RefData with a vec type when this instruction is executed, and it must be the
2774 same vec that is in S0.
2776 | DictSet, D(Dict), S(Dict) S(Int,Str) S(Cell), PRc|CRc|Er
2778 Set element with key S1 in S0 to S2. The dest will be a new Dict that should
2781 | DictSetRef, ND, S(Dict) S(Int,Str) S(Cell) S(BoxedCell), CRc|Er
2783 Like DictSet, but for binding operations on the dict. S3 must point to a
2784 RefData with a vec type when this instruction is executed, and it must be the
2785 same dict that is in S0.
2787 | MapSet, ND, S(Obj) S(Int,Str) S(Cell), Er
2789 Set element with key S1 in S0 to S2.
2791 | SetElem, DSetElem, S(PtrToGen) S(Cell) S(Cell), MElem|PRc|Er
2793 Set element with key S1 in S0 to S2. SetElem returns a Nullptr in the common
2794 case, where the logical result of the hhbc SetM is its right hand side. In
2795 the case of string bases, the SetM returns a new string containing the newly
2796 inserted character. So the return value of this instruction is Nullptr unless
2797 SetM needed to create a new counted string.
2799 Furthermore, in the case of "invalid offsets", SetElem may throw an
2800 InvalidSetMException (see discussion above).
2802 | SetWithRefElem, ND, S(PtrToGen) S(Gen) S(Gen), MElem|Er
2804 Set element with key S1 in S0 to S2.
2806 | UnsetElem, ND, S(PtrToGen) S(Cell), MElem|Er
2808 Unsets the element at key S1 in the base S0.
2810 | SetOpElem<op>, D(Cell),
2811 | S(PtrToGen) S(Cell) S(Cell),
2814 Set op elem with key S1 in base S0, using S2 as the right hand side.
2816 | IncDecElem, D(Cell), S(PtrToGen) S(Cell), MElem|PRc|Er
2818 Increment/decrement element with key S1 in base S0.
2820 | SetNewElem, ND, S(PtrToGen) S(Cell), MElem|Er
2822 Append the value in S1 to S0.
2824 | SetNewElemArray, ND, S(PtrToGen) S(Cell), MElem|Er
2826 Append the value in S1 to S0, where S0 must be a pointer to a array.
2828 | SetNewElemVec, ND, S(PtrToGen) S(Cell), MElem|Er
2830 Append the value in S1 to S0, where S0 must be a pointer to a vec.
2832 | SetNewElemKeyset, ND, S(PtrToGen) S(Int,Str), MElem|Er
2834 Append the value in S1 to S0, where S0 must be a pointer to a keyset.
2836 | BindNewElem, ND, S(PtrToGen) S(BoxedCell), MElem|Er
2838 Append the reference in S1 to S0.
2840 | ArrayIsset, D(Bool), S(Arr) S(Int,Str), NF
2842 Returns true iff the element at key S1 in the base S0 is set.
2844 | DictIsset, D(Bool), S(Dict) S(Int,Str), NF
2846 Returns true iff the element at key S1 in the base S0 is set.
2848 | KeysetIsset, D(Bool), S(Keyset) S(Int,Str), NF
2850 Returns true iff the element at key S1 in the base S0 is set.
2852 | StringIsset, D(Bool), S(Str) S(Int), NF
2854 Returns true iff the string S0 has a character at position S1.
2856 | VectorIsset, D(Bool), S(Obj) S(Int), NF
2858 Returns true iff the element at key S1 in the base S0 is set.
2860 | PairIsset, D(Bool), S(Obj) S(Int), NF
2862 Returns true iff the element at key S1 in the base S0 is set.
2864 | MapIsset, D(Bool), S(Obj) S(Int,Str), NF
2866 Returns true iff the element at key S1 in the base S0 is set.
2868 | IssetElem, D(Bool), S(PtrToGen) S(Cell), Er
2870 Returns true iff the element at key S1 in S0 is set.
2872 | EmptyElem, D(Bool), S(PtrToGen) S(Cell), Er
2874 Returns true iff the element at key S1 in S0 is set and not equal (as defined
2875 by the hhbc Eq instruction) to false.
2877 | DictEmptyElem, D(Bool), S(Dict) S(Int,Str), NF
2879 Like EmptyElem, but specialized for dicts.
2881 | KeysetEmptyElem, D(Bool), S(Keyset) S(Int,Str), NF
2883 Like EmptyElem, but specialized for dicts.
2885 | CheckRange, D(Bool), S(Int) S(Int), NF
2887 Returns true iff S0 is in the range [0, S1).
2889 | ThrowOutOfBounds, ND, S(ArrLike|Obj) S(Gen), Er|T
2891 Throws an OutOfBoundsException corresponding to an access of S0 with the key
2894 | ThrowInvalidArrayKey, ND, S(ArrLike) S(Gen), Er|T
2896 Throws an InvalidArgumentException corresponding to an access of S0 with the
2897 key S1, which has a type invalid for that array.
2899 | ThrowInvalidOperation, ND, S(Str), Er|T
2901 Throws an InvalidOperationException with a message indicating S0.
2903 | ThrowArithmeticError, ND, S(Str), Er|T
2905 Throws an ArithmeticError with a message indicating S0.
2907 | ThrowDivisionByZeroError, ND, S(Str), Er|T
2909 Throws a DivisionByZeroError with a message indicating S0.
2911 | ProfileArrayKind, ND, S(Arr), NF
2913 Profile the array kind of S0.
2915 | ProfileType, ND, S(Gen), NF
2917 Profile the type of S0.
2919 | ProfileMethod<rdsHandle,spOff>, ND, S(StkPtr) S(Cls,Nullptr), NF
2921 Profile the Func in the ActRec that was just pushed onto the stack.
2923 | CheckPackedArrayDataBounds, ND, S(AK(Packed),Vec) S(Int), B
2925 Checks that the index in S1 is within the bounds of the packed array or
2926 vector array in S0. Branches to B if the index is out of bounds.
2928 | LdPackedArrayDataElemAddr<T>, DParamPtr(Elem), S(AK(Packed),Vec) S(Int), NF
2930 Loads the address of the element at index S1 of the packed array or vec array
2931 in S0. This instruction assumes the array actually contains an element at
2932 that offset (IE, the array has the proper length).
2934 | ReservePackedArrayDataNewElem, D(Int), S(AK(Packed),Vec), B
2936 If there is room in the packed or vec array (which is assumed to be mutable),
2937 increments the array size and returns the index of the new last element
2938 (which you must initialize); else jumps to the taken branch.
2940 | LdVecElem, DVecElem, S(Vec) S(Int), NF
2942 Loads the element of the vec array in S0 at offset S1. This instruction
2943 assumes that the vec actually contains an element at that offset (IE, the vec
2944 has the proper length).
2946 | LdVectorSize, D(Int), S(Obj), NF
2948 Returns the size of the given Vector collection in S0.
2950 | VectorDoCow, ND, S(Obj), NF
2952 Triggers a copy on write for a Vector that has a live ImmVector sharing
2953 the same copy of the elements.
2955 | VectorHasImmCopy, ND, S(Obj), B
2957 Given a vector, check if it has a immutable copy and jump to the taken branch
2960 | ColAddNewElemC, DofS(0), S(Obj) S(Cell), Er|CRc|P
2962 Adds item S0 to the end of collection S0. Throws a fatal error if S0 is not a
2963 collection. Returns S0.
2965 | MapAddElemC, DofS(0), S(Obj) S(Cell) S(Cell), Er|CRc|P
2967 Adds item to a Map or ImmMap. Inserts item S2 into collection S0 at key S1.
2968 Throws a fatal error if S0 is not a collection. Returns S0.
2970 | ColIsEmpty, D(Bool), S(Obj), NF
2972 | ColIsNEmpty, D(Bool), S(Obj), NF
2974 Returns whether a collection instance is empty or not. S0 must be known to
2975 be an instance of a collection class at compile time.
2978 19. Exception/unwinding support
2980 | BeginCatch, ND, NA, NF
2982 Marks the beginning of a catch region. Exact behavior is implementation and
2983 architecture specific.
2985 | EndCatch<spOffset>, ND, S(FramePtr) S(StkPtr), T
2987 Marks the end of a catch region and returns control to the unwinder. The
2988 `spOffset' field represents a logical adjustment to S1 (in cells) to yield
2989 the vm stack pointer, however the stack pointer is not actually adjusted
2990 before this instruction returns control to the unwinder. The unwinder
2991 instead relies on fixup map information to find the appropriate stack
2992 pointers. Instead it's part of this instruction to facilitate assertions and
2993 memory effect analysis.
2995 | UnwindCheckSideExit, ND, S(FramePtr) S(StkPtr), B
2997 Branches to B if the currently executing catch region should return control
2998 to the unwinder rather than side exiting. Used to control behavior in catch
2999 traces for the InvalidSetMException and TVCoercionException situations.
3001 | LdUnwinderValue<T>, DParam(Cell), NA, PRc
3003 Loads the value contained by the current unwinder exception.
3006 20. Function prologues
3008 | EnterFrame, ND, S(FramePtr), NF
3010 Stash the return address of the call in m_savedRip.
3012 | CheckStackOverflow, ND, S(FramePtr), Er
3014 Check if the stack depth has exceeded its limit. If it has, jump to the
3015 stack overflow helper stub, which will throw.
3017 | InitExtraArgs<func,argc>, ND, S(FramePtr), NF
3019 Set up the ExtraArgs struct on the live ActRec. If extra args are present
3020 and need to be discarded, they will be decref'd and may re-enter to run
3023 | InitCtx, ND, S(FramePtr) S(Ctx,Nullptr), CRc
3025 Store S1 to the m_this/m_cls field in the frame pointer S0.
3027 If InitCtx appears in an IR unit, it must dominate all occurrences of LdCtx
3028 and LdCctx with the same FramePtr.
3030 | CheckSurpriseFlagsEnter<func,argc>, ND, S(FramePtr), Er
3032 Test the implementation-specific surprise flags. If they're nonzero, call
3033 the function enter helper.
3035 | CheckSurpriseAndStack<func,args>, ND, S(FramePtr), Er
3037 Test surprise flags and stack overflow at the same time.
3039 | CheckARMagicFlag, ND, S(FramePtr), B
3041 If the MagicDispatch flags on the ActRec pointed to by the frame pointer S0
3042 are not set, branch to block B.
3044 | LdARNumArgsAndFlags, D(Int), S(FramePtr), NF
3046 Load the value of m_numArgsAndFlags on the ActRec pointed to by the frame
3049 | StARNumArgsAndFlags, ND, S(FramePtr) S(Int), CRc
3051 Store S1 to m_numArgsAndFlags on the ActRec pointed to by the frame pointer
3054 | LdARInvName, D(Str), S(FramePtr), NF
3056 Load the value of m_invName off the ActRec pointed to by the frame pointer S0.
3057 The compiler should generate this only if it knows that m_invName is a
3058 StringData* (rather than, e.g., a VarEnv*).
3060 | StARInvName, ND, S(FramePtr) S(Str,Nullptr), CRc
3062 Store S1 to m_invName on the ActRec pointed to by the frame pointer S0.
3064 | PackMagicArgs, D(Arr), S(FramePtr), PRc
3066 Call PackedArray::MakePacked() with the value of numArgs() on the ActRec
3067 pointed to by the frame pointer S0 as the first argument, and the pointer to
3068 the first parameter in the frame as the second argument.
3070 | LdTVAux<ValidBits>, D(Int), S(Gen), NF
3072 Load the value of m_aux from the TypedValue S0. ValidBits is a mask
3073 specifying which bits are allowed to be set. The runtime may ignore it.
3075 Note that when we pass TypedValues around in registers, we usually use a byte
3076 register for the m_type member, and thus ignore m_aux. LdTVAux is only valid
3077 when we know that S0's m_type and m_aux were both materialized into the same
3080 /* Local Variables: */
3081 /* fill-column: 79 */