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 produces a value with an unconsumed reference that must be
126 consumed, either by DecRefing it or storing it somewhere in memory.
130 The instruction consumes a reference to one or more of its sources, either by
131 decreasing its refcount or storing the reference to memory.
135 The instruction has no next instruction; it either jumps, returns, or throws.
139 The instruction has a (sometimes optional) taken edge. Instructions that are
140 conditional branches (i.e. a Branch that is not Terminal) will also have a
145 The value of the instruction's dest is the same as one of its inputs; it
146 differs only in the type of the variable, or some other property that doesn't
147 affect the value of the variable itself.
151 The instruction may affect the type and/or value of its base operand,
152 operating on object properties.
156 The instruction may affect the type and/or value of its base operand,
157 operating on array elements.
161 The instruction is generic over array-like inputs and outputs. Most ops that
162 deal with array-like types can only handle their default ("Vanilla") layouts.
163 We whitelist those ops that are generic over layout.
169 1. Checks and Asserts
171 | CheckType<T>, DRefineS(0), S(Cell), B|P
173 Check that the type of the src S0 is T, and if so copy it to D, and
174 fallthrough. If S0 cannot be proven to be T, branch to block B. Note that
175 this means S0 still /may/ be a subtype of T in block B in some circumstances.
177 Specifically, subtypes of Type::Static may not be checked precisely,
178 depending on the type of the source. This means the instruction may take the
179 branch in some circumstances even when S0 is a subtype of T, if T has a
180 non-empty intersection with Type::Static.
182 Also note that many types are not supported as the typeParam right now.
184 | CheckNullptr, ND, S(Cls|StaticStr|Nullptr), B
186 If S0 is not a null pointer, branch to block B. This is used to check the
187 return value of a native helper that returns a potentially null StringData*.
189 | AssertType<T>, DRefineS(0), S(Cell,MemToCell), P
191 Assert that the type of S0 is T, copying it to D.
193 | CheckTypeMem<T>, ND, S(MemToCell), B
195 If the value pointed to by S0 is not type T, branch to the block B.
197 | CheckIter<iterId,iterType>, ND, S(FramePtr), B
199 Check that specialization type of the given iterator `iterId` on the frame S0
200 is `iterType`; if it is not, branch to block B.
202 | CheckLoc<T,localId>, ND, S(FramePtr), B
204 Check that type of the given localId on the frame S0 is T; if not, branch to
207 | CheckStk<T,offset>, ND, S(StkPtr), B
209 Check that the type of the cell on the stack pointed to by S0 at offset (in
210 cells) is T; if not, branch to block B.
212 | CheckMBase<T>, ND, S(LvalToCell), B
214 Check that the value pointed to by the member base register S0 has type T; if
215 not, branch to block B. This is functionally the same as CheckTypeMem.
217 | AssertLoc<T,localId>, ND, S(FramePtr), NF
219 Asserts that type of the supplied local on the frame S0 is T. This is used
220 for local type information, and is similar to CheckLoc except it doesn't
221 imply a runtime check (the assertion must've already been proven to be true)
222 and cannot cause control flow.
224 | AssertStk<T,offset>, ND, S(StkPtr), NF
226 Assert that stack element at `offset' (in cells) from S0 has type T. This is
227 similar to a CheckStk except that it does not imply a runtime check and
228 cannot cause control flow.
230 | AssertMBase<T>, ND, NA, NF
232 Assert that the value pointed to by the member base register has type T.
233 This is similar to a CheckMBase except that it does not imply a runtime check
234 and cannot cause control flow.
236 These instructions convert either a Cell or a Str to a primitive type (Bool,
237 Int, Dbl) and return the resulting value. They may throw an exception upon
238 failed type coercion. They are encoded along with callee Func, fn, and the
239 integer position of the argument, argNum, being coerced.
241 | CheckInit, ND, S(Cell), B
243 If S0's type is Uninit, branch to block B.
245 | CheckInitMem, ND, S(MemToCell), B
247 If the value pointed to by S0 has type Uninit, branch to block B.
249 | CheckCold<TransID>, ND, NA, B
251 Check if the counter associated with translation TransID is cold (i.e. within
252 a fixed threshold). If it's not (i.e. such translation has reached the
253 "hotness threshold"), then branch to block B.
255 | CheckInOuts<firstBit,mask,vals>, ND, S(Func) S(Int), B
257 Perform inout-ness guard checks. Operands:
259 S0 - function pointer for the callee
260 S1 - num params expected in the func
261 firstBit - first bit to check, must be a multiple of 64
263 vals - values to check
265 For each bit `i` set in the mask, checks whether inout-ness of parameter
266 `firstBit + i` of S0 is equal to the bit `i` of vals.
268 If any of the checks fail, branch to block B.
270 | EndGuards, ND, NA, NF
272 A no-op at runtime, this instruction serves to mark the end of the initial
273 sequence of guards in a trace.
275 | CheckNonNull, DSubtract(0, Nullptr), S(Cls|Func|Obj|Str|MemToCell|TCA|Nullptr), B
277 If the value in S0 is Nullptr, branch to block B. If S0 cannot be Nullptr, or
278 always is Nullptr, this check may be optimized away.
280 | AssertNonNull, DSubtract(0, Nullptr), S(StaticStr|Nullptr), P
282 Returns S0, with Nullptr removed from its type. This instruction currently
283 supports a very limited range of types but can be expanded if needed.
285 | CheckImplicitContextNull, ND, NA, B
287 If the implicit context on RDS is null, branch to block B.
289 | CheckSmashableClass, ND, S(Smashable) S(Cls), B
291 If the lower 32 bits of S0 does not match class pointer S1, branch to block B.
295 | AddInt, D(Int), S(Int) S(Int), NF
297 | SubInt, D(Int), S(Int) S(Int), NF
299 | MulInt, D(Int), S(Int) S(Int), NF
301 | AddIntO, D(Int), S(Int) S(Int), B
303 | SubIntO, D(Int), S(Int) S(Int), B
305 | MulIntO, D(Int), S(Int) S(Int), B
307 | AddDbl, D(Dbl), S(Dbl) S(Dbl), NF
309 | SubDbl, D(Dbl), S(Dbl) S(Dbl), NF
311 | MulDbl, D(Dbl), S(Dbl) S(Dbl), NF
313 | DivDbl, D(Dbl), S(Dbl) S(Dbl), NF
315 | DivInt, D(Int), S(Int) S(Int), NF
317 | Floor, D(Dbl), S(Dbl), NF
319 | Ceil, D(Dbl), S(Dbl), NF
321 | AbsDbl, D(Dbl), S(Dbl), NF
323 | Sqrt, D(Dbl), S(Dbl), NF
325 | AndInt, D(Int), S(Int) S(Int), NF
327 | OrInt, D(Int), S(Int) S(Int), NF
329 | XorInt, D(Int), S(Int) S(Int), NF
331 | Shl, D(Int), S(Int) S(Int), NF
333 | Shr, D(Int), S(Int) S(Int), NF
335 | Lshr, D(Int), S(Int) S(Int), NF
337 Double arithmetic, integer arithmetic, and integer bitwise operations.
338 Performs the operation described by the opcode name on S0 and S1, and puts
341 Undefined behavior occurs if Mod is given a divisor of zero, or if the
342 divisor is -1 and the dividend is the minimum representable integer.
344 AbsDbl computes the absolute value of a double-precision value.
346 DivDbl conforms to IEEE 754. In particular, division by zero returns +/- INF
347 or NAN depending on the dividend; and should the result of a division be zero
348 the sign will follow the normal sign rules for division.
350 DivInt will perform integer division of S1 by S0. S0 should not be zero and
353 Note that Shr is an arithmetic right shift: The MSB is sign-extended.
355 Lshr is logical right shift.
357 Floor and Ceil will return an integral value not greater, or not less
358 than their input respectively. Their use requires SSE 4.1, availability
359 should be checked before they are emitted.
361 AddIntO, SubIntO, MulIntO perform integer arithmetic on S0 and S1, but will
362 branch to block B on integer overflow.
364 | XorBool, D(Bool), S(Bool) S(Bool), NF
366 Logical XOR of the two sources. (Note that && and || do not have
367 corresponding opcodes because they're handled at the bytecode level, to
368 implement short-circuiting.)
370 | Mod, D(Int), S(Int) S(Int), NF
372 Compute S0 mod S1. If S1 is -1 or 0 the results are undefined.
379 | ConvArrToVec, D(Vec), S(Arr), PRc|CRc
381 | ConvDictToVec, D(Vec), S(Dict), PRc|CRc
383 | ConvKeysetToVec, D(Vec), S(Keyset), PRc|CRc
385 | ConvClsMethToVec, D(Vec), S(ClsMeth), PRc|CRc
387 | ConvObjToVec, D(Vec), S(Obj), PRc|CRc
392 | ConvArrToDict, D(Dict), S(Arr), PRc|CRc
394 | ConvVecToDict, D(Dict), S(Vec), PRc|CRc
396 | ConvKeysetToDict, D(Dict), S(Keyset), PRc|CRc
398 | ConvClsMethToDict, D(Dict), S(ClsMeth), PRc|CRc
400 | ConvObjToDict, D(Dict), S(Obj), PRc|CRc
403 To keyset conversions:
405 | ConvArrToKeyset, D(Keyset), S(Arr), PRc|CRc
407 | ConvVecToKeyset, D(Keyset), S(Vec), PRc|CRc
409 | ConvDictToKeyset, D(Keyset), S(Dict), PRc|CRc
411 | ConvClsMethToKeyset, D(Keyset), S(ClsMeth), PRc|CRc
413 | ConvObjToKeyset, D(Keyset), S(Obj), PRc|CRc
416 To varray conversions:
418 | ConvArrToVArr, DVArr, S(Arr), PRc|CRc
420 | ConvVecToVArr, DVArr, S(Vec), PRc|CRc
422 | ConvDictToVArr, DVArr, S(Dict), PRc|CRc
424 | ConvKeysetToVArr, DVArr, S(Keyset), PRc|CRc
426 | ConvClsMethToVArr, DVArr, S(ClsMeth), PRc|CRc
428 | ConvObjToVArr, DVArr, S(Obj), PRc|CRc
431 To darray conversion:
433 | ConvArrToDArr, DDArr, S(Arr), PRc|CRc
435 | ConvVecToDArr, DDArr, S(Vec), PRc|CRc
437 | ConvDictToDArr, DDArr, S(Dict), PRc|CRc
439 | ConvKeysetToDArr, DDArr, S(Keyset), PRc|CRc
441 | ConvClsMethToDArr, DDArr, S(ClsMeth), PRc|CRc
443 | ConvObjToDArr, DDArr, S(Obj), PRc|CRc
448 | ConvDblToBool, D(Bool), S(Dbl), NF
450 | ConvIntToBool, D(Bool), S(Int), NF
452 | ConvStrToBool, D(Bool), S(Str), NF
454 | ConvObjToBool, D(Bool), S(Obj), NF
456 | ConvTVToBool, D(Bool), S(Cell), NF
459 To double conversions:
461 | ConvBoolToDbl, D(Dbl), S(Bool), NF
463 | ConvIntToDbl, D(Dbl), S(Int), NF
465 | ConvObjToDbl, D(Dbl), S(Obj), NF
467 | ConvStrToDbl, D(Dbl), S(Str), NF
469 | ConvResToDbl, D(Dbl), S(Res), NF
471 | ConvTVToDbl, D(Dbl), S(Cell), NF
476 | ConvBoolToInt, D(Int), S(Bool), NF
478 | ConvDblToInt, D(Int), S(Dbl), NF
480 | ConvObjToInt, D(Int), S(Obj), NF
482 | ConvStrToInt, D(Int), S(Str), NF
484 | ConvResToInt, D(Int), S(Res), NF
486 | ConvTVToInt, D(Int), S(Cell), NF
489 To string conversions:
491 | ConvDblToStr, D(Str), S(Dbl), PRc
493 | ConvIntToStr, D(Str), S(Int), PRc
495 | ConvObjToStr, D(Str), S(Obj), PRc
497 | ConvResToStr, D(Str), S(Res), PRc
499 | ConvTVToStr, D(Str), S(Cell), PRc
502 All the above opcodes convert S0 from its current type to the destination
503 type, according to the PHP semantics of such a conversion.
505 | DblAsBits, D(Int), S(Dbl), NF
507 Reinterpret a double as an integer with the same bit pattern.
509 | OrdStr, D(Int), S(Str), NF
511 Convert the first byte in a string to an unsigned integer.
512 Intended as an optimization for ord($str)
514 | OrdStrIdx, D(Int), S(Str) S(Int), NF
516 Convert the character at position S1 in base string S0 to an unsigned
517 integer. Raises a notice if the position is out of bounds.
518 Intended as an optimization for ord($str[$idx]).
520 | ChrInt, D(StaticStr), S(Int), NF
522 Convert the integer S0 to a the one character string with ascii code
525 | StrictlyIntegerConv, D(Str|Int), S(Str), PRc
527 If S0 is a string representing an integer value (same criteria as array key
528 conversion), return that value as an integer. Otherwise return S0.
530 | ConvPtrToLval, DLvalOfPtr, S(PtrToCell), NF
532 Convert S0 to an equivalent lval.
535 4. Boolean predicates
537 | GtInt, D(Bool), S(Int) S(Int), NF
539 | GteInt, D(Bool), S(Int) S(Int), NF
541 | LtInt, D(Bool), S(Int) S(Int), NF
543 | LteInt, D(Bool), S(Int) S(Int), NF
545 | EqInt, D(Bool), S(Int) S(Int), NF
547 | NeqInt, D(Bool), S(Int) S(Int), NF
549 | CmpInt, D(Int), S(Int) S(Int), NF
551 Perform 64-bit integer comparisons.
553 | GtDbl, D(Bool), S(Dbl) S(Dbl), NF
555 | GteDbl, D(Bool), S(Dbl) S(Dbl), NF
557 | LtDbl, D(Bool), S(Dbl) S(Dbl), NF
559 | LteDbl, D(Bool), S(Dbl) S(Dbl), NF
561 | EqDbl, D(Bool), S(Dbl) S(Dbl), NF
563 | NeqDbl, D(Bool), S(Dbl) S(Dbl), NF
565 | CmpDbl, D(Int), S(Dbl) S(Dbl), NF
567 Perform comparisons of doubles. Comparisons that are unordered according to
568 IEEE 754 (such as when at least one operand is NaN) result in false.
570 | GtStr, D(Bool), S(Str) S(Str), NF
572 | GteStr, D(Bool), S(Str) S(Str), NF
574 | LtStr, D(Bool), S(Str) S(Str), NF
576 | LteStr, D(Bool), S(Str) S(Str), NF
578 | EqStr, D(Bool), S(Str) S(Str), NF
580 | NeqStr, D(Bool), S(Str) S(Str), NF
582 | SameStr, D(Bool), S(Str) S(Str), NF
584 | NSameStr, D(Bool), S(Str) S(Str), NF
586 | CmpStr, D(Int), S(Str) S(Str), NF
588 Performs comparison of strings using PHP semantics.
590 | GtStrInt, D(Bool), S(Str) S(Int), NF
592 | GteStrInt, D(Bool), S(Str) S(Int), NF
594 | LtStrInt, D(Bool), S(Str) S(Int), NF
596 | LteStrInt, D(Bool), S(Str) S(Int), NF
598 | EqStrInt, D(Bool), S(Str) S(Int), NF
600 | NeqStrInt, D(Bool), S(Str) S(Int), NF
602 | CmpStrInt, D(Int), S(Str) S(Int), NF
604 Performs comparison of strings with integers using PHP semantics.
606 | GtBool, D(Bool), S(Bool) S(Bool), NF
608 | GteBool, D(Bool), S(Bool) S(Bool), NF
610 | LtBool, D(Bool), S(Bool) S(Bool), NF
612 | LteBool, D(Bool), S(Bool) S(Bool), NF
614 | EqBool, D(Bool), S(Bool) S(Bool), NF
616 | NeqBool, D(Bool), S(Bool) S(Bool), NF
618 | CmpBool, D(Int), S(Bool) S(Bool), NF
620 Performs comparison of booleans.
622 | GtObj, D(Bool), S(Obj) S(Obj), NF
624 | GteObj, D(Bool), S(Obj) S(Obj), NF
626 | LtObj, D(Bool), S(Obj) S(Obj), NF
628 | LteObj, D(Bool), S(Obj) S(Obj), NF
630 | EqObj, D(Bool), S(Obj) S(Obj), NF
632 | NeqObj, D(Bool), S(Obj) S(Obj), NF
634 | SameObj, D(Bool), S(Obj) S(Obj), NF
636 | NSameObj, D(Bool), S(Obj) S(Obj), NF
638 | CmpObj, D(Int), S(Obj) S(Obj), NF
640 Perform comparison of objects using PHP semantics. All versions except for
641 SameObj and NSameObj may re-enter the VM and therefore may throw
642 exceptions. SameObj and NSameObj never re-enter or throw.
644 | GtArr, D(Bool), S(Arr) S(Arr), NF
646 | GteArr, D(Bool), S(Arr) S(Arr), NF
648 | LtArr, D(Bool), S(Arr) S(Arr), NF
650 | LteArr, D(Bool), S(Arr) S(Arr), NF
652 | EqArr, D(Bool), S(Arr) S(Arr), NF
654 | NeqArr, D(Bool), S(Arr) S(Arr), NF
656 | SameArr, D(Bool), S(Arr) S(Arr), NF
658 | NSameArr, D(Bool), S(Arr) S(Arr), NF
660 | CmpArr, D(Int), S(Arr) S(Arr), NF
662 Perform comparison of arrays using PHP semantics. All versions except for
663 SameArr and NSameArr may re-enter the VM and therefore may throw
664 exceptions. SameArr and NSameArr never re-enter or throw.
666 | GtVec, D(Bool), S(Vec) S(Vec), NF
668 | GteVec, D(Bool), S(Vec) S(Vec), NF
670 | LtVec, D(Bool), S(Vec) S(Vec), NF
672 | LteVec, D(Bool), S(Vec) S(Vec), NF
674 | EqVec, D(Bool), S(Vec) S(Vec), NF
676 | NeqVec, D(Bool), S(Vec) S(Vec), NF
678 | SameVec, D(Bool), S(Vec) S(Vec), NF
680 | NSameVec, D(Bool), S(Vec) S(Vec), NF
682 | CmpVec, D(Int), S(Vec) S(Vec), NF
684 Perform comparison of vecs. All versions except for SameVec and NSameVec may
685 re-enter the VM and therefore may throw exceptions. SameVec and NSameVec
686 never re-enter or throw.
688 | EqDict, D(Bool), S(Dict) S(Dict), NF
690 | NeqDict, D(Bool), S(Dict) S(Dict), NF
692 | SameDict, D(Bool), S(Dict) S(Dict), NF
694 | NSameDict, D(Bool), S(Dict) S(Dict), NF
696 Perform comparison of dicts. EqDict and NeqDict may re-enter the VM and
697 therefore may throw exceptions. SameDict and NSameDict never re-enter or
698 throw. Relational comparisons for dicts are not supported.
700 | EqKeyset, D(Bool), S(Keyset) S(Keyset), NF
702 | NeqKeyset, D(Bool), S(Keyset) S(Keyset), NF
704 | SameKeyset, D(Bool), S(Keyset) S(Keyset), NF
706 | NSameKeyset, D(Bool), S(Keyset) S(Keyset), NF
708 Perform comparison of keysets. As keysets can only contain ints and strings,
709 comparisons never re-enter or throw. Relational comparisons for keysets are
712 | GtRes, D(Bool), S(Res) S(Res), NF
714 | GteRes, D(Bool), S(Res) S(Res), NF
716 | LtRes, D(Bool), S(Res) S(Res), NF
718 | LteRes, D(Bool), S(Res) S(Res), NF
720 | EqRes, D(Bool), S(Res) S(Res), NF
722 | NeqRes, D(Bool), S(Res) S(Res), NF
724 | CmpRes, D(Int), S(Res) S(Res), NF
726 Perform comparison of resources using PHP semantics. Resource comparisons
727 never re-enter or throw.
729 | EqCls, D(Bool), S(Cls) S(Cls), NF
731 Checks if two Class values are equal.
733 | EqRecDesc, D(Bool), S(RecDesc) S(RecDesc), NF
735 Checks if two record types are equal.
737 | EqFunc, D(Bool), S(Func) S(Func), NF
739 Checks if two Func values are equal.
741 | EqStrPtr, D(Bool), S(Str) S(Str), NF
743 Checks if two string values represent the same underlying string. That is,
744 that they point at the same underlying storage.
746 | EqArrayDataPtr, D(Bool), S(ArrLike) S(ArrLike), LA
748 Checks if the two arguments represent the same underlying ArrayData. That is,
749 that they point at the same underlying storage.
751 | ProfileInstanceCheck, ND, C(StaticStr), NF
753 Profile that S0 has been used as the RHS of an instance check.
755 | InstanceOf, D(Bool), S(Cls) S(Cls|Nullptr), NF
757 Sets D based on whether S0 is a descendant of the class, interface, or trait
758 in S1. (Note that this is always false for a trait). S1 may be null at
759 runtime if the class is not defined.
761 | InstanceOfIface, D(Bool), S(Cls) CStr, NF
763 Fast path for interface checks. Sets D based on whether S0 implements S1, but
764 S1 must be a unique interface. This should only be used in repo-authoritative
767 | InstanceOfIfaceVtable<iface,canOptimize>, D(Bool), S(Cls), NF
769 Faster path for interface checks. Sets D based on whether S0 implements
770 iface, which must be a unique interface with an assigned vtable slot. In
771 some circumstances, this instruction is ensuring the presence of the
772 vtableVec; in those cases, canOptimize is false to avoid eliminating the
775 | ExtendsClass<cls,strictLikely>, D(Bool), S(Cls), NF
777 A fast-path for instanceof checks. Sets D based on whether S0 is a descendant
778 of cls, where cls must be a unique class that is not an interface or a trait.
780 If strictLikely is true, optimize for the case where S0 is not equal to S1.
782 | InstanceOfBitmask, D(Bool), S(Cls) CStr, NF
784 | NInstanceOfBitmask, D(Bool), S(Cls) CStr, NF
786 A fast-path for instanceof checks. Sets D based on whether S0 is a descendant
787 of the class named by S1, where S1 must have a bit allocated for it in the
788 fast instance check bitvector (see class.h).
790 | InstanceOfRecDesc, D(Bool), S(RecDesc) S(RecDesc), NF
792 Sets D to true if S0 is a descendant of the record in S1, false otherwise.
794 | InterfaceSupportsArr, D(Bool), S(Str), NF
796 | InterfaceSupportsVec, D(Bool), S(Str), NF
798 | InterfaceSupportsDict, D(Bool), S(Str), NF
800 | InterfaceSupportsKeyset, D(Bool), S(Str), NF
802 | InterfaceSupportsStr, D(Bool), S(Str), NF
804 | InterfaceSupportsInt, D(Bool), S(Str), NF
806 | InterfaceSupportsDbl, D(Bool), S(Str), NF
808 Returns whether t instanceof S0 returns true when t is of the given type.
810 | ResolveTypeStruct<class,suppress,offset,size,isOrAsOp>,
811 | DDArr, S(StkPtr) S(Cls|Nullptr), NF
813 Applies class/alias resolution on the type structure that is at the stack
814 offset given by S0 and offset. If size > 1, combine the type structures on
815 the stack into the first one's denoted holes. Returns a copy.
816 S1 is the calling class, used to resolve the this typehint.
817 If isOrAsOp is set, raises an error if S0 contains traits, function types or
819 If there is an error during type structure resolution, this instruction raises
820 an error. If suppress is set, this error is demoted to a warning.
822 | IsTypeStruct<handle>, D(Bool), SDArr S(Cell), NF
824 Returns whether S1 matches the type structure of a defined type in S0 and S1
825 is a subtype of S0. The input type structure (S0) must be resolved.
826 Handle is used for caching purposes.
828 | IsTypeStructCached, D(Bool), SDArr S(Cell), B
830 Checks if S0 is cached in TSClassCache and if so, returns whehter S1 is a
831 subtype of S0. Otherwise, it branches.
833 | ProfileIsTypeStruct<handle>, ND, SDArr, ND
835 Profile S0 to determine whether S0 is a type structure holding a reference to
838 | ThrowAsTypeStructException, ND, SDArr S(Cell), T
840 Throws an exception indicating why S1 does not match the type structure of a
841 defined type in S0 or why S1 is not a subtype of S0. The input type structure
842 (S0) must be resolved.
844 | RaiseErrorOnInvalidIsAsExpressionType, DDArr, SDArr, NF
846 Raises an error if the type hint for is/as expression contains an invalid
847 type such as callables, erased type variables and trait type hints.
848 The input type structure (S0) must be resolved.
850 | HasToString, D(Bool), S(Obj), NF
852 Returns whether the object S0 has a toString method.
854 | IsType<T>, D(Bool), S(Cell), NF
856 Sets D to true iff S0 holds a value that is of type T. T must not be a
859 | IsNType<T>, D(Bool), S(Cell), NF
861 Sets D to true iff S0 holds a value that is not of type T. T must not be a
864 | IsTypeMem<T>, D(Bool), S(MemToCell), NF
866 Sets D to true iff the value referenced by S0 is of type T. T must not be a
869 The value in S0 must not be a pointer into the evaluation stack or frame
872 | IsNTypeMem<T>, D(Bool), S(MemToCell), NF
874 Sets D to true iff the value referenced by S0 is not of type T. T must not be
877 | IsWaitHandle, D(Bool), S(Obj), NF
879 Sets D to true iff S0 is a subclass of WaitHandle.
881 | IsCol, D(Bool), S(Obj), NF
883 Sets D to true iff S0 is a collection.
885 | HasReifiedGenerics, D(Bool), S(Func), NF
887 Set D to true iff S0 is a reified function.
891 | JmpZero, ND, S(Int,Bool), B
893 | JmpNZero, ND, S(Int,Bool), B
895 Conditionally jump to based on S0.
897 | JmpSSwitchDest, ND, S(TCA) S(StkPtr) S(FramePtr), T
899 Jump to the target of a sswitch statement, leaving the region, where the
902 | JmpSwitchDest, ND, S(Int) S(StkPtr) S(FramePtr), T
904 Jump to the target of a switch statement, leaving the region, using table
905 metadata <JmpSwitchData> and index S0, which must be a valid index in the
908 | ProfileSwitchDest<handle,nCases>, ND, S(Int), NF
910 Profile a switch statement target.
912 | CheckSurpriseFlags, ND, S(FramePtr,StkPtr), B
914 Tests the implementation-specific surprise flags. If they're true, branches
915 to block B. This is done by comparing an evaluation stack pointer to the RDS
916 stackLimitAndSurprise word. Note that in a resumed, the frame pointer is not
917 pointing into the eval stack, so S0 should be a StkPtr in that case.
919 | HandleRequestSurprise, ND, NA, NF
921 Generate exceptions based on surprise flags on a per request basis.
922 Make sure CheckSurpriseFlags is true before calling HandleRequestSurprise.
924 | ReturnHook, ND, S(FramePtr) S(Cell), NF
926 Surprise flag hook for function returns.
928 | SuspendHookAwaitEF, ND, S(FramePtr) S(FramePtr) S(Obj), NF
930 Surprise flag hook for suspending eagerly executing async functions. The S0
931 frame was already teleported into S1. Decrefs S2 if it throws an exception.
933 | SuspendHookAwaitEG, ND, S(FramePtr) S(Obj), NF
935 Surprise flag hook for suspending eagerly executing async generators. The S0
936 frame has an associated AG, which is already linked to the newly constructed
937 AGWH in the blocked state. Decrefs S1 if it throws an exception.
939 | SuspendHookAwaitR, ND, S(FramePtr) S(Obj), NF
941 Surprise flag hook for suspending async functions and async generators resumed
942 at Await. The S0 frame has an associated AFWH/AGWH still in the running state,
943 S1 points to the child WH we are going to block on.
945 | SuspendHookCreateCont, ND, S(FramePtr) S(FramePtr) S(Obj), NF
947 Surprise flag hook for suspending generators and async generators during their
948 invocation. The S0 frame was already teleported into S1. Decrefs S2 if it
951 | SuspendHookYield, ND, S(FramePtr), NF
953 Surprise flag hook for suspending generators and async generators at Yield.
955 | Unreachable<AssertReason>, ND, NA, T
957 Indicates an unreachable code path. Any instructions that are post-dominated
958 by an Unreachable may be treated as unreachable by the optimizer, and the
959 behavior of a program that attempts to execute an Unreachable is undefined.
961 | EndBlock<AssertReason>, ND, NA, T
963 Halt execution, without implying anything about the reachability of
964 instructions preceding this. Intended for use in internal tests or other code
965 not meant to be executed.
967 | Jmp, ND, SVar(Top), B|T
969 Unconditional jump to block B. In the second form, the target block must
970 start with a DefLabel with the same number of destinations as Jmp's number of
971 sources. Jmp parallel-copies its sources to the DefLabel destinations.
973 | DefLabel, DMulti, NA, NF
975 DefLabel defines variables received from a previous Jmp. A DefLabel with zero
976 destinations is a no-op, and the predecessor blocks may not necessarily end
977 in Jmp. A DefLabel with one or more destinations may only be reached by a Jmp
978 instruction with the same number of sources. Ordinary branch instructions may
979 not pass values to a DefLabel.
981 | Select, DUnion(1,2), S(Bool,Int) S(Top) S(Top), NF
983 If S0 is true/non-zero, return S1, otherwise return S2.
988 | LdStk<T,offset>, DParamMayRelax(Cell), S(StkPtr), NF
990 Loads from S0 at offset (in cells), and puts the value in D as type T.
992 | LdLoc<T,localId>, DParamMayRelax(Cell), S(FramePtr), NF
994 Loads local slot localId from the frame S0 and puts the value in D as type T.
996 | LdStkAddr<offset>, D(PtrToStkCell), S(StkPtr), NF
998 Loads the address of the stack slot given by the pointer in S0 at the given
999 stack offset (measured in cells).
1001 | LdLocAddr<localId>, D(PtrToFrameCell), S(FramePtr), NF
1003 Loads the address of the local slot localId from the frame S0 into D.
1005 | LdRDSAddr<T,RDSHandle>, DParam(PtrToCell), NA, NF
1007 Load the address of a Cell that lives at the specified RDS handle. The type
1008 param must be a subtype of PtrToCell.
1010 | LdInitRDSAddr<T,RDSHandle>, DParam(PtrToInitCell), NA, B
1012 Load the address of a Cell that lives at the specified RDS handle. Branch if
1013 the value at that address is Uninit. The type param must be a subtype of
1016 | LdPairElem, D(Cell), S(Obj) S(Int), NF
1018 Load the element at S1 out of the Pair collection at S0.
1020 | LdMem<T>, DParam(Cell), S(MemToCell), NF
1022 Loads from S0 and puts the value in D.
1024 | LdContField<T>, DParam(Cell), S(Obj) C(Int), NF
1026 Loads a property from the object referenced by S0 at the offset given by S1
1027 and puts the value in D. S0 must be a Generator.
1029 | LdClsInitElem<idx>, D(Cell), S(PtrToClsInitCell), NF
1031 Load the cell at index `idx` from the class init vector at S0 into D0.
1033 | LdColVec, D(Vec), S(Obj), NF
1035 Load the vec array backing a collection instance in S0, which must be a
1036 Vector or ImmVector, and that specific object type must be known at compile
1039 | LdColDict, D(Dict), S(Obj), NF
1041 Load the dict array backing a collection instance in S0, which must be a
1042 Map, Set, ImmMap, or ImmSet, and that specific object type must be known at
1045 | LdIterBase<T,iterId>, DParam(ArrLike), S(FramePtr), NF
1047 Load the base of the iterator with type `T` at `iterId`. `T` must be a valid,
1048 DataTypeSpecific-or-better type for the iterator's base; for example, it may
1049 be based on an earlier call to CheckIter.
1051 | LdIterPos<T,iterId>, DParam(Int|PtrToElemCell), S(FramePtr), NF
1053 | LdIterEnd<T,iterId>, DParam(Int|PtrToElemCell), S(FramePtr), NF
1055 Load the specified field of the iterator at `iterId`. These ops should only
1056 be generated for iterators known to have a specialized type (via CheckIter).
1057 The type param `T` should be compatible with this type - i.e. `T` should be
1058 either an int or a pointer based on whether it's an index or pointer iter.
1060 | LdFrameThis, DParam(Obj), S(FramePtr), NF
1062 Loads into D the value of m_this from S0.
1064 | LdFrameCls, DParam(Cls), S(FramePtr), NF
1066 Loads into D the value of m_cls from S0.
1068 | LdClsCtor, D(Func), S(Cls) S(Cls|Nullptr), NF
1070 Loads into D the constructor of class S0. If the constructor cannot be called
1071 from the context S1, raise an error.
1073 | LdSmashable, D(Smashable), NA, NF
1075 Loads a smashable value. The initial value is set to (1 << addr) + 1, where
1076 addr is a pointer pointing to the value in TC. The lowest bit is set for
1077 convenience of checking whether the value was already smashed.
1079 | LdSmashableFunc, D(Func), S(Smashable), NF
1081 Loads into D the func pointer stored in the higher 32 bits of S0.
1083 | LdRecDesc, D(RecDesc), S(Record), NF
1085 Load the record type out of the record in S0 and put it in D.
1087 | LdRecDescCached<recName>, D(RecDesc), NA, NF
1089 Loads the record whose name is recName via the RDS. Invokes autoload and may raise an error
1090 if the record is not defined.
1092 | LdRecDescCachedSafe<recName>, D(RecDesc), NA, B
1094 Loads the record whose name is recName out of the RDS. If the record is not
1095 defined, branch to B.
1097 | DefConst<T>, DParam(Top), NA, NF
1099 Define a constant value of type T. D is presumed to be globally available and
1100 the DefConst instruction will not actually appear in the IR instruction
1103 | Conjure<T>, DParam(Top), NA, NF
1105 Define a value of type T. This instruction aborts at runtime; it is meant to
1106 be used in tests or code that is known to be unreachable.
1108 | ConjureUse, ND, S(Cell), NF
1110 Define a "use" of S0 effectively keeping the value alive. As with Conjure it
1111 should not appear in reachable code.
1113 | LdCls, D(Cls), S(Str) C(Cls|Nullptr), NF
1115 Loads the class named S0 in the context of the class S1. Invokes autoload and
1116 may raise an error if the class is not defined. The explicit context
1117 parameter allows the compiler to simplify this instruction to a DefConst in
1118 some cases. If S0 is constant, this instruction may be simplified to a
1121 | LdClsCached, D(Cls), CStr, NF
1123 Loads the class named S0 via the RDS. Invokes autoload and may raise an error
1124 if the class is not defined.
1126 | LdClsCachedSafe, D(Cls), CStr, B
1128 Loads the class whose name is S0 out of the RDS. If the class is not defined,
1131 | LdClsInitData, D(PtrToClsInitCell), S(Cls), NF
1133 Loads the pointer to the property initializer array for class S0.
1135 | LookupClsRDS, D(Cls|Nullptr), S(Str), NF
1137 Lookup the cached-class RDS handle for a given class name. Dereference that
1138 handle and return the associated Class, or null if not present.
1140 | LdCns, DCns, CStr, B
1142 Load the constant named S0, branching to B if isn't present.
1144 | LookupCnsE<T,constName>, DCns, CStr, PRc
1146 Load a constant via the RDS. Raises a fatal error if it cannot define the
1147 constant. This should only be executed if LdCns on the same constant has
1150 | LdClsCns<className,constantName>, D(PtrToCell), NA, B
1152 Load the address of the constant 'constantName' for the class 'className' in
1153 RDS. If not initialized, branch to B.
1155 | LdSubClsCns<constantName,slot>, D(PtrToCell), S(Cls), NF
1157 Load the address of the constant 'constantName' for the class S0. The
1158 constant is known to be in the given slot. If the returned TypedValue is not
1159 UncountedInit, its value should not be used, and a fallback method should be
1162 | LdSubClsCnsClsName<constantName,slot>, D(StaticStr|Nullptr), S(Cls), NF
1164 Loads the name of the class pointed by the constant 'constantName' for the
1165 class S0. The constant is known to be in the given slot. Returns nullptr if
1166 constant is abstract, not type constant or does not point to a class.
1168 | CheckSubClsCns<constantName,slot>, ND, S(Cls), B
1170 Check that the constant 'constantName' lives in the given slot for the class
1171 S0, and branch if not. S0 must have at least slot+1 constants.
1173 | LdClsCnsVecLen, D(Int), S(Cls), NF
1175 Load the size of S0's constant table.
1177 | LdTypeCns, DStaticDArr, S(InitCell), B
1179 Loads the resolved type constant S0 or branches to B if S0 is not resolved or
1180 not a type constant.
1182 | LdClsTypeCns, DStaticDArr, S(Cls) S(Str), NF
1184 Loads type constant S1 of class S0 or raises an error if no such constant
1185 could be found, or if S0::S1 is not a type constant.
1187 | LdClsTypeCnsClsName, D(StaticStr), S(Cls) S(Str), NF
1189 Loads the name of the class pointed by the type constant S1 of class S0 or
1190 raises an error if no such constant could be found, or if S0::S1 is not a
1193 | ProfileSubClsCns<constantName,handle>, D(PtrToCell), S(Cls), NF
1195 Load the address of the constant 'constantName' for the class S0, profiling
1196 the observed slots. If the returned TypedValue is not UncountedInit, its
1197 value should not be used, and a fallback method should be called.
1199 | LdClsMethodFCacheFunc<clsName,methodName>, D(Func), NA, B
1201 Loads the target cache entry for a forwarding call to clsName::methodName.
1202 If the method does not exist, or the cache hasn't been filled yet, branch to
1205 | LookupClsMethodFCache<clsName,methodName>,
1206 | D(Func|Nullptr), C(Cls) S(FramePtr),
1209 Lookup clsName::methodName in the forwarding class method cache. S0 should be
1210 the Class named by clsName and S1 should be the current vm frame pointer. May
1211 return Nullptr if lookup fails using a subset of the required lookup paths,
1212 indicating that a more complete lookup path should be taken. May throw if the
1213 method does not exist.
1215 | LdClsMethodCacheFunc<clsName,methodName>, D(Func), NA, B
1217 Loads the target cache entry for the method clsName::methodName. If the
1218 method does not exist or the cache hasn't been filled yet, branch to B.
1220 | LdClsMethodCacheCls<clsName,methodName>, D(Cls), NA, NF
1222 Loads the target cache class context entry for a call to clsName::methodName
1223 from the current context. This instruction must only be used when the value
1224 is known to not be empty (i.e., LdClsMethodCacheFunc must have succeeded, or
1225 LookupClsMethodCache returned a non-null value).
1227 | LookupClsMethodCache<clsName,methodName>, D(Func|Nullptr), S(FramePtr), NF
1229 Lookup a function in the class method targetcache. The class name and method
1230 name are clsName and methodName, respectively. S0 is the current vm frame
1231 pointer. Returns Nullptr if the method cannot be found using a subset of the
1232 required lookup paths, indicating that a more complete lookup path should be
1233 taken. May throw if the method does not exist.
1235 | LdIfaceMethod<vtableIdx,methodIdx>, D(Func), S(Cls), NF
1237 Load the Func* at methodIdx from the vtable at vtableIdx in S0.
1239 | LdFuncVecLen, D(Int), S(Cls), NF
1241 Load the funcVecLen field from S0.
1243 | LdClsMethod, D(Func), S(Cls) C(Int), NF
1245 Load the Func* in slot S1 of the class method table for class S0. (Note that
1246 this vector is located before the class in memory, so the non-negative slots
1247 will map to negative offset loads.)
1249 | LookupClsMethod, D(Func|Nullptr), S(Cls) S(Str) S(Obj|Nullptr) S(Cls|Nullptr),
1252 Lookup a pointer to a class method for a given class S0 and method name S1,
1253 assuming caller's $this is S2 and caller is defined in a class S3. Throws or
1254 fatals if the method does not exist, is not accessible, or is not a static
1255 method. Returns nullptr if it is an instance method defined in S2's class
1256 hierarchy, indicating that this legacy call should be handled by interpreter.
1258 | LdPropAddr<T,index>, DParam(LvalToPropCell), S(Obj), NF
1260 Load the address of the object property at physical index `index`. T must be a
1261 subtype of PtrToPropInitCell.
1263 | LdInitPropAddr<T,index>, DParam(LvalToPropCell), S(Obj), B
1265 Load the address of the object property at physical index `index`. Branch if
1266 the value at that address is Uninit. T must be a subtype of PtrToPropInitCell.
1268 | LdGblAddr, D(LvalToGblCell|Nullptr), S(Str), NF
1270 Loads a pointer to a global with name S0, or a null lval if that global is
1271 not already defined.
1273 | LdGblAddrDef, D(LvalToGblCell), S(Str), NF
1275 Loads a pointer to a global with name S0, defining it to be InitNull if it
1276 is not already defined.
1278 | LdClsPropAddrOrNull, D(PtrToSPropCell|Nullptr),
1279 | S(Cls) S(Str) C(Cls|Nullptr) C(Bool) C(Bool),
1282 Loads a pointer to a static class property. S0 points to the class, S1 is the
1283 property name, and S2 is the class representing the context of the code
1284 accessing the property. If class S0 does not have a visible and accessible
1285 static property named S1, then nullptr is returned. An exception
1286 will be thrown if the property is marked LateInit and its value is
1287 Uninit, unless S3 is true. An exception is also thrown if S4 is true,
1288 and the property is constant.
1290 | LdClsPropAddrOrRaise, D(PtrToSPropCell),
1291 | S(Cls) S(Str) C(Cls|Nullptr) C(Bool) C(Bool),
1294 Loads a pointer to a static class property. S0 points to the class, S1 is the
1295 property name, and S2 is the class representing the context of the code
1296 accessing the property. If class S0 does not have a visible and accessible
1297 static property named S1, then nullptr is returned. An exception
1298 will be thrown if the property is marked LateInit and its value is
1299 Uninit, unless S3 is true. An exception is also thrown if S4 is true,
1300 and the property is constant.
1302 | LookupSPropSlot, D(Int), S(Cls) S(Str), NF
1304 Lookup the slot index of the static property with the name S1 on the class
1305 S0, returning -1 if not found.
1307 | LdObjMethodD, D(Func), S(Cls) S(Str), NF
1309 Loads a func pointer pointing to the instance method that would be called
1310 if a method named S1 is invoked on an instance of S0. Raises a fatal if the
1311 class does not have an accessible method with the given name.
1313 | LdObjMethodS<methodName>, D(Func), S(Cls) S(Smashable), NF
1315 Loads a func pointer pointing to the instance method that would be called
1316 if a `methodName` is invoked on an instance of S0. Caches the mapping in
1317 the TC cache (using S1) and target cache. Raises a fatal if the class does
1318 not have an accessible method with the given name.
1320 | LdObjInvoke, D(Func), S(Cls), B
1322 Try to load a cached non-static __invoke Func from the Class in S0, or branch
1323 to block B if it is not present.
1325 | LdObjClass, DLdObjCls, S(Obj), NF
1327 Load the class out of the object in S0 and put it in D.
1329 | LdClsName, D(StaticStr), S(Cls), NF
1331 Load the name of the Class* in S0.
1333 | LdLazyClsName, D(StaticStr), S(LazyCls), NF
1335 Load the name of the LazyClass in S0.
1337 | LdFunc, D(Func|Nullptr), S(Str), NF
1339 Loads the Func whose name is S0, invoking autoloader if it is not defined yet.
1340 Fatals if the named function is not defined, and the autoloader fails to
1341 define it. Returns nullptr if S0 contained '::', indicating that this legacy
1342 call should be handled by interpreter.
1344 | LdFuncCached<funcName>, D(Func), NA, NF
1346 Loads the Func whose name is funcName from the RDS, invoking autoload if it
1347 not defined yet. Fatal if function autoloader fails to define it.
1349 | LookupFuncCached<funcName>, D(Func), NA, NF
1351 Loads the Func whose name is given from %1, invoking autoload if it is not
1352 defined yet. Fatal if the function autoload fails to define it. This
1353 instruction does not assume the loaded function will be called immediately,
1354 so it will raise a resolution failure error instead of a call failure error.
1356 | LdFuncNumParams, D(Int), S(Func), NF
1358 Returns the value of func->numParams().
1360 | LdFuncName, D(StaticStr), S(Func), NF
1362 Loads the full name of S0.
1364 | LdMethCallerName<isCls>, D(StaticStr), S(Func), NF
1366 Loads the meth_caller cls or func name.
1368 | LdFuncCls, D(Cls|Nullptr), S(Func), NF
1370 Loads the Class* of S0.
1372 | LdStrLen, D(Int), S(Str), NF
1374 Load the length of the string in S0.
1376 | FuncHasAttr<attr>, D(Bool), S(Func), NF
1378 Tests for Func::m_attrs & attr.
1380 | IsClsDynConstructible, D(Bool), S(Cls), NF
1382 Tests for Class::m_attrCopy & AttrDynamicallyConstructible.
1384 | LdFuncRxLevel, D(Int), S(Func), NF
1386 Returns the value of func->rxLevel().
1388 | LdClsFromClsMeth, D(Cls), S(ClsMeth), NF
1390 Load the Class* of the ClsMethDataRef in S0.
1392 | LdFuncFromClsMeth, D(Func), S(ClsMeth), NF
1394 Load the Func* of the ClsMethDataRef in S0.
1396 | LdClsFromRClsMeth, D(Cls), S(RClsMeth), NF
1398 Load the Class* of the RClsMeth* in S0.
1400 | LdFuncFromRClsMeth, D(Func), S(RClsMeth), NF
1402 Load the Func* of the RClsMeth* in S0.
1404 | LdGenericsFromRClsMeth, DVArr, S(RClsMeth), NF
1406 Load the ArrayData* containing the generics attached to the RClsMeth in S0
1408 | LdFuncFromRFunc, D(Func), S(RFunc), NF
1410 Load the Func* of the RFuncData in S0
1412 | LdGenericsFromRFunc, DVArr, S(RFunc), NF
1414 Load the ArrayData* containing the generics attached to the RFuncData in S0
1418 | AllocObj, DAllocObj, S(Cls), PRc
1420 Allocates a new object of class S1.
1422 | AllocObjReified, DAllocObj, S(Cls) SVArr, PRc
1424 Allocates a new object of class S1 and sets S2 as the reified generics of this
1425 class. If this class is not reified, this instruction raises an error.
1427 | InitProps<class>, ND, NA, NF
1429 Calls the property initializer function (86pinit) for class. May throw.
1431 | InitSProps<class>, ND, NA, NF
1433 Calls the static property initializer functions (86sinit and/or 86linit)
1434 for class. May throw.
1436 | CheckRDSInitialized<RDSHandle>, ND, NA, B
1438 Check if the RDS entry at the specified handle is initialized, and branches
1441 | MarkRDSInitialized<RDSHandle>, ND, NA, NF
1443 Mark the given RDS entry as being initialized.
1445 | PropTypeRedefineCheck, ND, C(Cls) C(Int), NF
1447 Check that the specified property at the slot S1 on S0, which redeclares a
1448 property in the parent, has a declared type equivalent to the parent
1451 | DebugBacktrace, DVArr, S(Int), PRc
1453 Obtain stack trace by calling the debug_backtrace() method.
1455 | DebugBacktraceFast, D(Res), NA, PRc
1457 Obtain compact stack trace resource that can be expanded lazily.
1459 | InitThrowableFileAndLine, ND, S(Obj), NF
1461 Initialize Throwable's file name and line number assuming the stack trace
1462 was already initialized and the current vmfp() is a built-in.
1464 | NewInstanceRaw<class>, DAllocObj, NA, PRc
1466 Allocates an instance of class.
1468 | InitObjProps<class>, ND, S(Obj), NF
1470 Initializes properties of object S0.
1472 | ConstructInstance<class>, DAllocObj, NA, PRc
1474 Call the custom instance constructor of an extension class.
1476 | ConstructClosure<class>, DAllocObj, S(Cls|Obj|Nullptr), CRc|PRc
1478 Call the custom instance constructor of a Closure.
1480 Store the context represented by S0 into the newly constructed closure object.
1481 S0 may be a Nullptr when there is no context (i.e. the closure is being used
1484 | LockObj, ND, S(Obj), NF
1486 Clear the IsBeingConstructed flag on the object.
1488 | NewLoggingArray, DLoggingArrLike, S(VArr,DArr,Vec,Dict,Keyset), PRc|CRc
1490 Maybe create a LoggingArray wrapping the vanilla array-like S0. The decision
1491 may be based on flags or sampling. If we don't create an array, we return S0
1492 unchanged. The result will match S0 in type and static-ness.
1494 | NewDArray, DDArr, C(Int), PRc
1496 Allocate a new dict-like array with the expected capacity S0.
1498 | NewDictArray, D(Dict), C(Int), PRc
1500 Allocate a new dict with the expected capacity S0.
1502 | NewKeysetArray<offset,keys>, D(Keyset), S(StkPtr), PRc|CRc
1504 Allocate a new keyset containing N elements off the stack given by S0, at
1505 `offset'. This instruction moves the elements off the stack without
1506 manipulating their reference counts.
1508 | AllocVArray<size>, DVArr, NA, PRc
1510 Allocate a new uninitialized vec-like array with space for size elements in
1511 it. The array will be initialized with values using either InitVecElem or
1514 | AllocVec<size>, D(Vec), NA, PRc
1516 Allocate a new uninitialized vector array with space for size elements in it.
1517 The array will be initialized with values using either InitVecElem or
1520 | InitVecElem<index>, ND, S(VArr,Vec) S(Cell), CRc
1522 Store the S1 into the slot at index in array S0. This instruction assumes
1523 that it doesn't have to incref the value being stored. Used to initialize an
1524 array allocated with AllocVArray or AllocVec.
1526 | InitVecElemLoop<offset,size>, ND, S(VArr,Vec) S(StkPtr), CRc
1528 Move `size' elements from the stack given by S1, at `offset', into the array
1529 S0. Assumes that the first element on the stack is the last element in the
1530 array. Used to initialize an array allocated with AllocVArray or
1531 AllocVec that was too big to use a series of InitVecElem ops.
1533 | AllocStructDArray<keys...>, DDArr, NA, PRc
1535 | AllocStructDict<keys...>, D(Dict), NA, PRc
1537 Allocate a new key/value dict or mixed-layout array, given N string literal
1538 immediates for keys. This op initializes the header and hash table of the
1539 new array-like, but does not its elements; use InitDictElem for that.
1541 | InitDictElem<index,key>, ND, S(DArr,Dict) S(Cell), NF
1543 Initialize the element at position `index` in array S0 to have the string
1544 literal `key` as its key and S1 as its value. This instruction assumes that
1545 S1 has already been inc-reffed. Used to initialize an array allocated by
1546 AllocStructArray / AllocStructDArray / AllocStructDict.
1548 | NewRecord<offset,keys...>, D(Record), S(RecDesc) S(StkPtr), PRc|CRc
1550 Allocate a new record, given the type S0 and N immediate keys
1551 and taking N elements off the stack given by S1, at `offset'.
1552 This instruction assumes it can take the values from the stack
1553 without increfing them.
1555 | NewStructDArray<offset,keys...>, DDArr, S(StkPtr), PRc|CRc
1557 | NewStructDict<offset,keys...>, D(Dict), S(StkPtr), PRc|CRc
1559 Allocate a new key/value dict or mixed-layout array, given N string literal
1560 immediates for keys and N stack elements at `offset` on stack S0 for values.
1561 This op assumes it can take values from the stack without inc-reffing them.
1563 | NewCol<type>, DCol, NA, PRc
1565 Create an empty new collection of `type'. `type' cannot be Pair.
1567 | NewPair<offset>, DCol, S(Cell) S(Cell), PRc|CRc
1569 Allocate a new Pair and fill it with the given cells. Ownership of the cells
1570 is transferred from $1 and $2 to the pair without manipulating the refcounts.
1572 | NewColFromArray<type>, DCol, S(Vec,Dict), PRc|CRc
1574 Create a collection of `type` from a Vec or Dict kind. `type` cannot be
1575 Pair. S0 must be vec kind when `type` is Vector or ImmVector, and must be
1576 dict kind otherwise. Ownership of S0 is transferred from $1 to the
1577 collection, without manipulating the refcount.
1579 | Clone, DofS(0), S(Obj), PRc
1581 Allocate an object by cloning S0.
1583 | NewClsMeth, D(ClsMeth), S(Cls) S(Func), NF
1585 Allocate a new ClsMethDataRef.
1587 | NewRClsMeth, D(RClsMeth), S(Cls) S(Func) SVArr, PRc
1589 Allocate a new reified class method by storing the Class in S0,
1590 the Func in S1 and the reified generics in S2.
1592 | NewRFunc, D(RFunc), S(Func) SVArr, PRc
1594 Allocate a new reified function pointer given the Func pointer in S0
1595 and reified generics in S1.
1597 | FuncCred, DAllocObj, S(Func), PRc
1599 Allocate a new FunctionCredential
1603 | BeginInlining<func, offset>, D(FramePtr), S(StkPtr) S(FramePtr), NF
1605 Marks the start of an inlined function whose stack resides offset cells below
1608 Defines a new frame pointer for an ActRec at callBCOff for use in an inlined
1609 region. In resumed contexts the new frame is computed relative to S0 as S1 is
1610 not a stack location.
1612 | EndInlining, ND, S(FramePtr), NF
1614 Marks the end of an inlined function. S0 is no longer a valid frame location.
1616 | InlineCall<retSPOff>, ND, S(FramePtr) S(FramePtr), NF
1618 Sets the current vmfp for an inlined call to S0, and the m_sfp of S0 to the
1621 This instruction is primarily used to represent a frame in the IR in a way
1622 that allows us to eliminate it entirely. When it cannot be eliminated (or if
1623 it is pushed into an unlikely path) it performs callee-side responsibilities
1624 for setting up an activation record (i.e. setting the return ip, m_func and
1625 m_callOff, storing the frame pointer into D).
1627 The caller frame pointer is passed as S1. This is used to keep track of the
1628 call chain of inlined functions for simplification and dead code elimination.
1630 | InlineReturn<callerFPOff>, ND, S(FramePtr) S(FramePtr), NF
1632 Unlinks a frame activated with InlineCall. `callerFPOff' is the offset of
1633 the caller's frame pointer, S1, relative to S0. Every InlineCall should be
1634 post-dominated by InlineReturn instructions and terminal instructions on any
1635 path that does not side exit within the callee.
1637 The frame itself is still valid until killed by an EndInlining instruction,
1638 but is no longer part of the m_sfp chain of active frames.
1640 | DefFuncEntryFP<func>,
1642 | S(FramePtr) S(StkPtr) S(Int) S(Int) S(Cls|Obj|Nullptr),
1645 Writes a callee's frame and defines a frame pointer.
1647 `func': the function being called
1648 S0: frame pointer of the caller
1649 S1: stack pointer pointing to the space reserved for the callee's frame
1650 S2: call flags (see CallFlags)
1651 S3: number of passed arguments
1654 | SyncReturnBC<spOffset,callBCOffset>, ND, S(StkPtr) S(FramePtr), NF
1656 Stores callBCOffset into the frame at spOffset from S0 as the call bytecode
1657 address and the frame S1 as the return frame.
1659 | Call<offset,numParams,callOff,destroyLocals>,
1661 | S(StkPtr) S(FramePtr) S(Func) S(Cls|Obj|Nullptr),
1664 Transfer control to a callee S2, based on the pre-live activation record and
1665 set of args on the stack pointed to by S0 at `offset'. S1 is the current
1666 caller frame pointer. S3 is the context (nullptr, $this or static::class).
1668 | NativeImpl<func>, ND, S(FramePtr) S(StkPtr), NF
1670 Execute a call to the native builtin specified by the current function. S0
1671 and S1 should be the current vmfp and vmsp, respectively.
1673 | CallBuiltin, DBuiltin, S(FramePtr) S(StkPtr) SVar(MemToCell,Cell,Nullptr), PRc
1675 Call builtin function with N arguments. S0 and S1 should be the current vmfp
1676 and vmsp, respectively.
1678 The source and destination types correspond to C++ parameter and return types
1681 C++ type HHIR type Position
1682 ----------------- --------- --------
1683 bool Bool source, destination
1684 int64_t Int source, destination
1685 double Dbl source, destination
1686 const String& PtrToStr source
1687 const Array& PtrToArr source
1688 const Object& PtrToObj source
1689 const Variant& PtrToCell source
1690 Variant& PtrToCell source (ref param)
1691 String {Str|InitNull} destination
1692 Array {Arr|InitNull} destination
1693 Object {Obj|InitNull} destination
1694 Variant {Cell-UninitNull} destination
1696 | RetCtrl<spOff,suspendingResumed>, ND, S(StkPtr) S(FramePtr) S(Cell), T
1698 Ensure that S0 + `spOff' (in cells) is stored in rvmsp and that S1's saved
1699 frame pointer is stored in rvmfp, then return to the saved return address in
1700 S1. The return value is S2, which is passed via the rret_*() registers to
1701 the caller. The `suspendingResumed' flag indicates when this instruction is
1702 suspending a resumable rather than performing a normal function return.
1704 | AsyncFuncRet<spOff>, ND, S(StkPtr) S(FramePtr) S(Cell), T
1706 Return from a resumed async function, assuming no surprise. Ensures that
1707 S0 + `spOff` (in cells) is stored in rvmsp and that S1 is stored in rvmfp,
1708 packs return value S2 into registers and calls the `asyncFuncRet` unique
1709 stub. The stub stores the result into the wait handle associated with the
1710 frame pointer, marks it as finished, unblocks its parents and if possible,
1711 directly resumes the first parent (fast path), or a pending fast runnable
1712 ResumableWaitHandle (slower path). Otherwise, it will exit VM and return
1713 control to the asio scheduler (slow path). The stack must contain exactly one
1714 cell containing uninitialized garbage, which will be populated by the stub
1715 either to pass the return value to the resumed function, or to return null
1718 | AsyncFuncRetSlow<spOff>, ND, S(StkPtr) S(FramePtr) S(Cell), T
1720 Return from a resumed async function, assuming unknown surprise flag state
1721 after the previous surprise was handled by executing "return" event hook.
1722 Calls the `asyncFuncRetSlow` stub, which re-checks the surprise flag and
1723 transfers control to the AsyncFuncRet if it was clear, or performs the slow
1724 path of AsyncFuncRet if it was not, without resuming another function, as
1725 we are not able to call a potential "resume await" event hook from the stub.
1727 | AsyncSwitchFast<spOff>, ND, S(StkPtr) S(FramePtr), T
1729 Switch control to another ResumableWaitHandle. Ensures that S0 + `spOff`
1730 (in cells) is stored in rvmsp and that S1 is stored in rvmfp and calls the
1731 `asyncSwitchCtrl` unique stub, which tries to resume a pending fast runnable
1732 ResumableWaitHandle (fast path) if possible, otherwise it will exit VM and
1733 return control to the asio scheduler (slow path). As with AsyncRetFast, the
1734 stack must contain exactly one cell containing uninitialied garbage.
1736 | LdRetVal<T>, DParam(Cell), S(FramePtr), NF
1738 Load the return value from the already-returned-from ActRec pointed to by S0
1739 into the dest. This is used by NativeImpl. TODO(#7150575): We want to make
1740 NativeImpl return a TypedValue in the C++ ABI registers.
1742 | DbgTrashRetVal, ND, S(FramePtr), NF
1744 For debugging purposes. Store kTVTrashJITRetVal to the return value slot on
1745 the activation record pointed to by S0.
1747 | GenericRetDecRefs, ND, S(FramePtr), NF
1749 Does decrefs of all the current function's locals, where S0 is a pointer to
1750 the relevant activation record. This instruction may not occur in an inlined
1753 | DbgCheckLocalsDecRefd, ND, S(FramePtr), NF
1755 In debug builds, if LocalsDecRefd flag is set on S0, causes runtime failure by
1756 emitting a trap instruction. Otherwise, this instruction does nothing.
1760 | StClsInitElem<idx>, ND, S(PtrToClsInitCell) S(Cell), NF
1762 Store S1 into the slot at index `idx` in the class init vector at S0.
1764 | StMem, ND, S(MemToCell) S(Cell), NF
1766 Store S1 into the location pointed to by S0.
1768 | StImplicitContext, ND, S(Obj), NF
1770 Stores the implicit context from RDS to the WaitHandle in S0.
1772 | StLoc<localId>, ND, S(FramePtr) S(Cell), NF
1774 Store S1 to local number localId on the frame pointed to by S0.
1776 | StLocRange<localIds>, ND, S(FramePtr) S(Cell), NF
1778 Store S1 to the local variables corresponding to localIds, on the frame
1781 | StIterBase<iterId>, ND, S(FramePtr) S(ArrLike,Nullptr), NF
1783 Sets the base of the iterator at `iterId` to the pointer S1. The array must
1784 match the specialized type of the iterator, or be null (for local iterators).
1786 | StIterType<iterId,iterType>, ND, S(FramePtr), NF
1788 Sets the type of the iterator at `iterId` to `iterType`. This type must be a
1789 specialized type. Also sets auxiliary fields (like next helper index).
1791 | StIterPos<iterId>, ND, S(FramePtr) S(Int|PtrToElemCell), NF
1793 | StIterEnd<iterId>, ND, S(FramePtr) S(Int|PtrToElemCell), NF
1795 Store S1 to the given field of the iterator at `iterId`. S1 must be an int if
1796 we're doing index iteration and a pointer if we're doing pointer iteration.
1798 | StStk<offset>, ND, S(StkPtr) S(Cell), NF
1800 Store S1 to the stack pointed to by S0, at a given offset (in cells).
1802 | StOutValue<index>, ND, S(FramePtr) S(Cell), NF
1804 Store S1 in a caller allocated out-value vm stack cell index cells above
1807 | LdOutAddr<index>, D(PtrToOtherCell), S(FramePtr), NF
1809 Load the address of the storage for out parameter `index` provided by the
1810 callee (the address will be a location on the callee stack).
1812 | DbgTrashStk<offset>, ND, S(StkPtr), NF
1814 For debugging purposes. Store kTVTrashJITStk to the stack slot pointed to
1815 by S0, at a given offset (in cells).
1817 | DbgTrashFrame<offset>, ND, S(StkPtr), NF
1819 For debugging purposes. Store kTVTrashJITFrame to kNumActRecCells stack
1820 slots starting at the offset (in cells), and going toward higher memory
1823 | DbgTrashMem, ND, S(MemToCell), NF
1825 For debugging purposes. Store kTVTrashJITHeap to a heap slot pointed to by
1828 | RecordReifiedGenericsAndGetTSList, DVArr, SVArr, CRc
1830 Takes a varray of reified generics from the stack and adds them to the reified
1831 generics table and returns the input varray of reified generics, possibly
1834 | StFrameCtx, ND, S(FramePtr) S(Obj,Cls), NF
1836 Store object or class S1 on frame S0.
1838 | StFrameFunc<func>, ND, S(FramePtr), NF
1840 Store the func in m_funcId/m_func for S0.
1842 | StFrameMeta<callBCOff,numArgs,flags>, ND, S(FramePtr), NF
1844 Store the m_callOffAndFlags and m_numArgs fields of S0.
1848 | EagerSyncVMRegs, ND, S(FramePtr) S(StkPtr), NF
1850 Sync the given vmfp and vmsp to their in-memory locations.
1852 | ReqBindJmp<bcOff,transFlags>, ND, S(StkPtr) S(FramePtr), T
1854 Emit a jump to a REQ_BIND_JMP service request to the target offset bcOff.
1856 | ReqRetranslate<transFlags>, ND, S(StkPtr) S(FramePtr), T
1858 Emit a jump to a service request that will chain to a retranslation of this
1861 This instruction is used in exit traces for a type prediction that occurs at
1862 the first bytecode offset of a tracelet.
1864 | ReqRetranslateOpt<transId,bcOff>, ND, S(StkPtr) S(FramePtr), T
1866 Emit a service request to retranslate, with a higher optimization gear,
1867 translation transID, which starts at bcOff. This instruction is used in exit
1868 traces that trigger profile-guided optimizations.
1871 11. Refcounting and copies
1873 | Mov, DofS(0), S(Top), P
1875 Defines D as S0. May imply register-to-register moves at code generation
1876 time. Does not imply an incref or any other manipulation of S0.
1878 | IncRef, ND, S(Cell), NF
1880 If S0 is a refcounted type, increment its refcount.
1882 | DecRef<locId>, ND, S(Cell), CRc
1884 Decrease the reference count of S0 by one, and call a destructor for types
1885 that require it if it goes to zero.
1887 The locId is just a hint to the runtime indicating which local variable is
1888 being DecRef'd, if any.
1890 | DecRefNZ<locId>, ND, S(Cell), CRc
1892 Decrease the reference count of S0 by one, do not check if it goes to zero.
1893 This instruction can be used for more efficient code when it is provable that
1894 the reference count cannot go to zero.
1896 | ProfileDecRef<locId>, ND, S(Cell), NF
1898 Update the DecRefProfile for the given input as if it were dec-ref-ed, but do
1899 not actually dec-ref it. We can use this op for e.g. iterator output locals,
1900 because we don't specialize iterators in profiling translations.
1905 | DefFP, D(FramePtr), NA, NF
1907 Creates a temporary D representing the current vm frame pointer.
1909 | DefFrameRelSP<stackOff>, D(StkPtr), S(FramePtr), NF
1911 Creates a temporary D representing the current VM stack pointer as an offset
1912 `stackOff' from the frame pointer S0.
1914 This instruction is used at the beginning of translations of non-resumed
1915 functions to represent the state of the stack on entry.
1917 | DefRegSP<stackOff>, D(StkPtr), NA, NF
1919 Creates a temporary D representing the current VM stack pointer given by
1920 the rvmsp register. The `stackOff' is a logical offset from a stack base,
1921 which is a stack pointer to the empty logical stack within the translation.
1923 This instruction is used at the beginning of translations of prologues and
1924 resumed functions to represent the state of the stack on entry.
1926 In prologues, the stack base represents a stack without any func arguments,
1927 i.e. it is pointing to the empty space reserved for an ActRec.
1929 In resumables, the stack base represents an empty VM stack.
1931 | DefCallFlags, D(Int), NA, NF
1933 | DefCallFunc, D(Func), NA, NF
1935 | DefCallNumArgs, D(Int), NA, NF
1937 | DefCallCtx, DParam(Cls|Obj), NA, NF
1939 Creates a temporary D representing flags, function pointer, number of
1940 arguments, or context passed to the prologue.
1942 May be used only at the beginning of a prologue or a stub used in a prologue
1945 | Count, D(Int), S(Cell), NF
1947 Computes the number of elements in S0. The count of an array is the number of
1948 elements it contains, without recursing into containers in the array.
1949 Subtypes of Bool|Int|Dbl|Str|Res have a count of 1, subtypes of Null have a
1950 count of 0. The count of objects that implement the Countable interface is
1951 computed by returning the value of their count method. Objects that do not
1952 implement Countable have a count of 1.
1954 | CountVec, D(Int), S(VArr,Vec), LA
1956 | CountDict, D(Int), S(DArr,Dict), LA
1958 | CountKeyset, D(Int), S(Keyset), LA
1960 | CountCollection, D(Int), S(Obj), NF
1962 Computes the number of elements in S0 using the same definition as Count,
1963 but with a restriction on the input type that allows for optimizations.
1967 Does nothing. It's sometimes useful for the simplifier to insert one of these
1968 in the instruction stream.
1970 | JmpPlaceholder, ND, NA, B
1972 Does nothing if executed. Semantically, this instruction carries a taken edge
1973 to a block of speculatively-generated code during initial IR generation, such
1974 as specialized code for an iterator init or next which we may or may not use.
1975 If it survives irgen, it should be eliminated in the first DCE pass.
1979 | VerifyParamCls, ND, S(Cls) S(Cls|Nullptr) C(Int) C(Int), NF
1981 Verify parameter type for classes or traits. If S0 does not extend (if S1 is
1982 a class) or implement (if S1 is an interface) S1, this instruction will raise
1983 a recoverable fatal error describing the type mismatch.
1985 | VerifyParamRecDesc, ND, S(RecDesc) S(RecDesc|Nullptr) C(Int) C(Int), NF
1987 Verify parameter type for records. If S0 does not extend S1 (if S1 is a record
1988 type) or does not satisfy the type hint S2 (if S1 is null pointer),
1989 this instruction will raise a recoverable fatal error describing the type
1990 mismatch for parameter S3.
1992 | VerifyParamCallable, ND, S(Cell) C(Int), NF
1994 If S0 is not callable, as defined by the php function is_callable, this
1995 instruction will raise a recoverable fatal error describing the type
1998 | VerifyParamFail, ND, NA, NF
2000 Assumes that parameter specified in extra-data in the current function
2001 has failed a its type check. Depending on the typehint being verified and
2002 a number of runtime options, may coerce the parameter to the correct type i
2003 or raise a recoverable fatal error describing the type mismatch.
2005 | VerifyParamFailHard, ND, NA, T
2007 A terminal version of VerifyParamFail, to be used when the compiler can
2008 statically prove that this failure will result in a fatal error rather than a
2011 | VerifyRetCallable, ND, S(Cell), NF
2013 Verify a return type hint.
2015 | VerifyRetCls, ND, S(Cls) S(Cls|Nullptr) C(Int) S(Cell), NF
2017 Verify a return type hint for a class.
2019 | VerifyRetRecDesc, ND, S(RecDesc) S(RecDesc|Nullptr) C(Int) S(Cell), NF
2021 Verify a return type hint for a record.
2023 | VerifyRetFail, ND, S(PtrToCell), NF
2025 Failure to verify a return type hint.
2027 | VerifyRetFailHard, ND, S(PtrToCell), T
2029 Terminal version of VerifyRetFail, to be used when the compiler can prove
2030 that this failure will result in a fatal error.
2032 | VerifyPropCls, ND, S(Cls) S(Int) S(Cls|Nullptr) S(Obj) C(Bool), NF
2034 Verify a property type hint with AnnotType::Object against an object
2035 value. S0 is the class of the object containing the property. S1 is the slot
2036 of the property on the class. S3 is the object which is being set in the
2037 property. If S2 is not nullptr, than the type-hint refers to that Class, and
2038 S3 will be checked to see if its an instance of S2. Otherwise, the type-hint
2039 refers to a type-alias, and the alias will be resolved and checked against
2040 S3. S4 is true if this is a static property, false otherwise.
2042 | VerifyPropRecDesc, ND, S(Cls) S(Int) S(RecDesc|Nullptr) S(Record) C(Bool), NF
2044 Verify a property type hint with AnnotType::Record against a record value. S0
2045 is the class of the object containing the property. S1 is the slot of the
2046 property. S3 is the record being set in the property. If S2 is not nullptr,
2047 it is the type hint and S3 will be checked to see if it's an instance of S2.
2048 Otherwise, the type hint refers to a type-alias and the type-alias will be
2049 resolved and checked against S3. S4 is true if this is a static property,
2052 | VerifyPropFail, ND, S(Cls) S(Int) S(Cell) C(Bool), NF
2054 Failure to verify a property type hint. S0 is the class of the object
2055 containing the property. S1 is the slot of the property on the class. S2 is
2056 the value which was being set in the property. S3 is true if this is a static
2057 property, false otherwise.
2059 | VerifyPropFailHard, ND, S(Cls) S(Int) S(Cell) C(Bool), T
2061 Terminal version of VerifyPropFail, to be used when the compiler can prove
2062 that this failure will result in a fatal error.
2064 | VerifyProp, ND, S(Cls) S(Int) S(Cell) C(Bool), NF
2066 Verify that S2 is compatible with the type hint for the property at slot S1
2067 on S0. S3 is true if this is a static property, false otherwise.
2069 | VerifyPropAll, ND, S(Cls) S(Int) S(Cell) C(Bool), NF
2071 Verify that S2 is compatible with the all type hints for the property at slot
2072 S1 on S0 including upper-bounds. S3 is true if this is a static property,
2075 | VerifyPropCoerce, D(InitCell), S(Cls) S(Int) S(Cell) C(Bool), PRc|CRc
2077 Verify that S2 is compatible with the type hint for the property at slot S1
2078 on S0. S3 is true if this is a static property, false otherwise. Once support
2079 for coercing class_meth types is removed this ir instruction can also be
2080 removed (T61738946).
2082 | VerifyPropCoerceAll, D(InitCell), S(Cls) S(Int) S(Cell) C(Bool), PRc|CRc
2084 Verify that S2 is compatible with all type hints for the property at slot S1
2085 on S0, including upper-bounds. S3 is true if this is a static property,
2086 false otherwise. Once support for coercing class_meth types is removed this
2087 ir instruction can also be removed (T61738946).
2089 | VerifyReifiedLocalType<id>, ND, SDArr, NF
2091 Raises a catchable type hint error if the reified generics of function
2092 parameter id does not match the type structure given on S0.
2094 | VerifyReifiedReturnType, ND, S(Cell) SDArr, NF
2096 Raises a catchable type hint error if the reified generics of S0 does not
2097 match the type structure given on S1.
2099 | RaiseArraySerializeNotice, ND, C(Int) S(ArrLike), LA
2101 Raise a serialization notice with provenance information from the given vec or
2102 dict, using S0 as the sink kind as defined in the SerializationSite enum
2104 | RaiseClsMethPropConvertNotice<tc,isSProp>, ND, S(Cls) S(Str), NF
2106 Raise a notice that a class_meth was implicitly converted after being stored
2107 into a property with name S1 expecting type tc on class S0. Once support for
2108 coercing class_meth types is removed this ir instruction can also be removed
2111 | RaiseUninitLoc<localId>, ND, S(Str), NF
2113 Raise a notice for an uninitialized local variable.
2115 | RaiseUndefProp, ND, S(Obj) CStr, NF
2117 Raise a notice for an undefined property named S1 on the class of S0.
2119 | RaiseTooManyArg<func>, ND, S(VArr,Vec), CRc|LA
2121 Raise a too many argument warning because extra arguments stored in S0 were
2122 passed to function func.
2124 | RaiseError, ND, S(Str), T
2126 Raises a fatal error with the text in S0 as its message.
2128 | RaiseWarning, ND, S(Str), NF
2130 Raises a warning with the text in S0 as its message.
2132 | RaiseNotice, ND, S(Str), NF
2134 Raises a notice with the text in S0 as its message.
2136 | ThrowHasThisNeedStatic, ND, S(Func), T
2138 Throws a BadMethodCallException to indicate that func was called on an object
2139 but is a static method.
2141 | ThrowMissingArg<func,argc>, ND, NA, T
2143 Throws a RuntimeExceptionObject to indicate that only argc arguments were
2144 passed to function func.
2146 | ThrowMissingThis, ND, S(Func), T
2148 Throws a BadMethodCallException to indicate that an instance method was called
2151 | ThrowCallReifiedFunctionWithoutGenerics, ND, S(Func), T
2153 Throws a BadMethodCallException to indicate that S0 was called without reified
2156 | RaiseHackArrCompatNotice, ND, S(Str), NF
2158 Raises a Hack array compat notice with the text in S0 as its message.
2160 | ThrowParamInOutMismatch<paramIndex>, ND, S(Func), T
2162 Throw an exception indicating that the inout-ness of a parameter was
2163 incorrectly annotated at the callsite.
2165 | ThrowParamInOutMismatchRange<firstBit,mask,vals>, ND, S(Func), T
2167 Throw an exception indicating that the inout-ness of at least one parameter
2168 within a given range was incorrectly annotated at the callsite.
2170 See CheckInOuts for meaning of firstBit, mask and vals.
2172 | RaiseForbiddenDynCall, ND, S(Func), NF
2174 Depending on the setting of `ForbidDynamicCallsToFunc`,
2175 `ForbidDynamicCallsToClsMeth` and `ForbidDynamicCallsToInstMeth` runtime
2176 options, either raise a warning or throw an exception indicating that the
2177 func specified in S0 was called dynamically (and should not be).
2178 If `ForbidDynamicCallsWithAttr` is false, warnings and exceptions will not be
2179 raised for functions and methods with `__DynamicallyCallable` attribute.
2181 | RaiseForbiddenDynConstruct, ND, S(Cls), NF
2183 Depending on the setting of the `ForbidDynamicConstructs` runtime option, either
2184 raise a warning or throw an exception indicating that the class specified in
2185 S0 was constructed dynamically (and should not be).
2187 | RaiseRxCallViolation, ND, S(FramePtr) S(Func), NF
2189 Depending on the setting of the `RxEnforceCalls` runtime option, either raise
2190 a warning or throw an exception indicating that the caller specified by S0
2191 was violating reactivity constraints when calling the callee specified by S1.
2193 | RaiseStrToClassNotice, ND, S(Str), NF
2195 Raise a notice if a string is implicitly converted to a class.
2197 | CheckClsMethFunc, ND, S(Func), NF
2199 Raises runtime errors if the func in S0 is not a callable static method.
2201 | CheckClsReifiedGenericMismatch<cls>, ND, SVArr, NF
2203 Raises a runtime error unless whether each generic in S0 is reified or erased
2204 matches exactly to the expectations of the cls.
2206 | CheckFunReifiedGenericMismatch, ND, S(Func) SVArr, NF
2208 Raises a runtime error unless whether each generic in S0 is reified or erased
2209 matches exactly to the expectations of the func.
2211 | IsFunReifiedGenericsMatched<func>, D(Bool), S(Int), NF
2213 Load the generics bitmap from call flags given by S0 and check whether the
2214 bitmap proves that the number of given generics and positions of reified vs
2215 erased generics matches the expectations of the callee `func' (which must use
2216 reified generics). If this opcode returned false, further checks implemented
2217 by CheckFunReifiedGenericMismatch are needed.
2219 | InitClsCns<className,constName>, DCns, NA, PRc
2221 Initialize the RDS entry for a constant for a class, invoking autoload if it
2222 is not defined. The initialized value is returned. This instruction may raise
2223 an undefined constant error if autoload cannot define the constant.
2225 | PrintStr, ND, S(Str), CRc
2227 | PrintInt, ND, S(Int), CRc
2229 | PrintBool, ND, S(Bool), CRc
2231 Print for various types.
2233 | ConcatIntStr, D(Str), S(Int) S(Str), PRc
2235 Concatenate S0 and S1 after converting S0 to String.
2237 | ConcatStrInt, D(Str), S(Str) S(Int), CRc|PRc
2239 Concatenate S0 and S1 after converting S1 to String.
2241 | ConcatStrStr, D(Str), S(Str) S(Str), CRc|PRc
2243 Concatenate S0 and S1.
2245 | ConcatStr3, D(Str), S(Str) S(Str) S(Str), CRc|PRc
2247 Concatenate S0, S1, and S2.
2249 | ConcatStr4, D(Str), S(Str) S(Str) S(Str) S(Str), CRc|PRc
2251 Concatenate S0, S1, S2, and S3.
2253 | AddNewElemKeyset, D(Keyset), S(Keyset) S(Cell), CRc|PRc
2255 | AddNewElemVec, DVecSet, S(VArr,Vec) S(Cell), CRc|PRc
2257 Add S1 as a new element to the array/keyset/vec S0. (Note: S1 must actually
2258 be a subtype of InitCell for array invariants, but we can't assert this yet
2259 in the IR because many eval stack slots are not entirely typed wrt initness
2262 | AKExistsDict, D(Bool), S(DArr,Dict) S(Int,Str), NF
2264 Has the effects of array_key_exists(S0, S1).
2266 | AKExistsKeyset, D(Bool), S(Keyset) S(Int,Str), NF
2268 Has the effects of array_key_exists(S0, S1).
2270 | AKExistsObj, D(Bool), S(Obj) S(Int,Str), NF
2272 Has the effects of array_key_exists(S0, S1) on an object S0. This does
2273 collection accesses.
2275 | GetMemoKey, DMemoKey, S(Cell), PRc
2277 Given a cell, produces a string or an int that can be used as a memoize cache
2278 key. Valid values for the input include all basic types, arrays and
2279 collections, and objects that implement IMemoizeParam. Any other type will
2280 cause GetMemoKey to throw. This op can only be used within functions marked
2281 as memoize wrappers.
2283 | GetMemoKeyScalar, DMemoKey, S(Uncounted,Str), PRc
2285 Identical to GetMemoKey but only accepts scalar types and cannot produce
2288 | DictIdx<sizeHint>, DDictElem, S(DArr,Dict) S(Int,Str) S(Cell), NF
2290 Checks if S0 contains the key S1 and returns the result if found. Otherwise
2291 S2 is returned. The optimization data `sizeHint` doesn't affect semantics.
2292 (`sizeHint` describes S0; it's one of {Default, SmallStatic}. Default is a
2293 hash lookup. For SmallStatic, we'll do a linear scan for static string keys.)
2295 | KeysetIdx, DKeysetElem, S(Keyset) S(Int,Str) S(Cell), NF
2297 Checks if S0 contains the key S1 and returns the result if found. Otherwise
2300 | MethodExists, D(Bool), S(Cls) S(Str), NF
2302 Checks if the method named S1 exists on class S0. S0 must be a normal class
2303 that is not abstract.
2305 | LdBindAddr<SrcKey,spOff>, D(TCA), NA, NF
2307 Creates a service request to bind the given target address. Returns a TCA
2308 pointing either to the service request (before the service request is
2309 satisfied) or to the native code for the given target address (once the
2310 service request is satisfied).
2312 | LdSwitchDblIndex, D(Int), S(Dbl) S(Int) S(Int), NF
2314 | LdSwitchStrIndex, D(Int), S(Str) S(Int) S(Int), CRc
2316 | LdSwitchObjIndex, D(Int), S(Obj) S(Int) S(Int), CRc
2318 These instructions are used to determine the target of a switch statement
2319 with target range [S1:S1 + S2), when invoked with the value S0. They call
2320 helper functions to check whether S0 is an numeric integer in the range
2321 [S1:S1 + S2), and if so return the value S1 - (Int)S0. Else, they return the
2322 target of the default target, S2 + 1.
2324 | LdSSwitchDestFast, D(TCA), S(Cell), NF
2326 | LdSSwitchDestSlow, D(TCA), S(Cell), NF
2328 Load string switch destinations (two different compilation strategies).
2330 | InterpOne<T,spOff,bcOff,numPopped,numPushed>, ND,
2331 | S(StkPtr) S(FramePtr),
2334 Call the interpreter implementation function for one opcode. S0 + `spOff' (in
2335 cells) and S1 are, respectively, the VM stack and frame pointers before this
2336 instruction. T is only present if the instruction pushes to the stack, in
2337 which case it is the type of the top stack element after the call. `bcOff' is
2338 the bytecode offset. `numPopped' is the number of stack cells consumed by the
2339 instruction, and `numPushed' is the number of stack cells produced by the
2342 | InterpOneCF<T,bcOff,numPopped,numPushed>, ND,
2343 | S(StkPtr) S(FramePtr),
2346 Similar to InterpOne, but for instructions that may modify vmpc. This is
2347 implemented as a tail call to a stub, so any exceptions thrown will be thrown
2348 in the context of the stub, not the InterpOneCF instruction.
2350 | OODeclExists<kind>, D(Bool), S(Str) S(Bool), NF
2352 Returns a bool indicating whether the class, interface, or trait named by S0
2353 exists. Invokes autoload if S1 is true.
2355 | SetOpTV<op>, ND, S(LvalToCell) S(Cell), NF
2357 Performs S0 <op>= S1.
2359 | OutlineSetOp<op>, D(Cell), S(Cell) S(Cell), NF
2361 Similar to SetOpTV, but does not write back the result to S0, instead it is
2362 returned as the dest. This is useful to handle ops that may require a
2363 type check before writing the value back.
2365 | GetTime, D(Dbl), NA, NF
2367 Returns a double of the current time in seconds.
2369 | GetTimeNs, D(Int), C(Int), NF
2371 Returns the current time of the given clock id specified as clockid_t in
2372 nanoseconds as integer. This will call kernel's clock_gettime_ns() API. Note
2373 that this cannot be used for CLOCK_THREAD_CPUTIME_ID, as HHVM provides
2374 different semantics for that counter.
2376 14. Generators & Closures
2378 | LdClosureCls, DParam(Cls), S(Obj), NF
2380 | LdClosureThis, DParam(Obj), S(Obj), NF
2382 Load the context from the closure object S0 into D, assuming `func' is
2385 | StClosureArg<index>, ND, S(Obj) S(Cell), CRc
2387 Store one of the closure environment arguments (i.e. from the closure's use
2388 clause) from S1 into the closure object S0.
2390 | CreateGen, DAllocObj, S(FramePtr) C(Int) S(TCA,Nullptr) C(Int), PRc
2392 Create a Generator object and suspend the ActRec provided by S0 into its
2393 embedded ActRec, allocating S1 slots for locals/iterators. Set the native
2394 resume address to S2 and resume offset to S3.
2396 | CreateAGen, DAllocObj, S(FramePtr) C(Int) S(TCA,Nullptr) C(Int), PRc
2398 Create an AsyncGenerator object and suspend the ActRec provided by S0 into its
2399 embedded ActRec, allocating S1 slots for locals/iterators. Set the native
2400 resume address to S2 and resume offset to S3.
2402 | CreateAFWH, DAllocObj,
2403 | S(FramePtr) C(Int) S(TCA,Nullptr) C(Int) S(Obj),
2406 Create an AsyncFunctionWaitHandle object and suspend the ActRec provided by
2407 S0 into its embedded ActRec, allocating S1 slots for locals/iterators. Set
2408 the native resume address to S2, resume offset to S3, and mark it blocked on
2409 non-finished child S4.
2411 | CreateAGWH, DAllocObj,
2412 | S(FramePtr) S(TCA,Nullptr) C(Int) S(Obj),
2415 Create an AsyncGeneratorWaitHandle object and link it to the AsyncGenerator
2416 associated with the ActRec provided by S0. Set the native resume address
2417 to S1, resume offset to S2, and mark it blocked on non-finished child S3.
2419 | CreateAAWH<local,count>, DAllocObj, S(FramePtr) S(Int), PRc
2421 Create an AwaitAllWaitHandle and add the count elements from frame contiguous
2422 frame locals beginning at local and extending count locals. S1 denotes the
2423 total number of non-completed waithandles. All locals must be subclasses of
2426 | CreateSSWH, DAllocObj, S(Cell), CRc|PRc
2428 Call c_StaticWaitHandle::CreateSucceeded.
2430 | AFWHPrepareChild, ND, S(FramePtr) S(Obj), NF
2432 Prepare unfinished WaitableWaitHandle object specified by S1 for getting
2433 awaited by an AsyncFunctionWaitHandle object specified by its ActRec
2436 Injects S1 into the currently running scheduler instance and performs
2437 cross-scheduler and intra-scheduler cycle detection. Throws if the
2438 dependency cannot be established.
2440 | AFWHPushTailFrame, ND, S(Obj) C(Int), B
2442 If S0 is eligible for the tail frame optimization and has any free tail
2443 frame ID slots, pushes S1 as a new tail frame ID. Otherwise, branches to B.
2444 This IR op assumes that S0 is an Awaitable in the blocked state.
2446 S0 is eligible for the optimization if it is an AsyncFunctionWaitHandle,
2447 if this site "owns" it (i.e. if it has a refcount of exactly 2 - this site
2448 and its child's back pointer), and if it has space in its tail-frames list.
2450 | StArResumeAddr<offset>, ND, S(FramePtr) S(TCA), NF
2452 Store the resume address S1 into the Resumable whose ActRec is given by S0,
2453 marking the offset to resume at as `offset'.
2455 | ContEnter<spOffset,callBCOffset>,
2457 | S(StkPtr) S(FramePtr) S(FramePtr) S(TCA) S(Cell),
2460 Enters a generator body. S0 + `spOffset' (in cells) is a pointer to the
2461 stack, S1 is the current frame pointer, S2 is the generator frame pointer
2462 embedded in the Generator object, S3 is the address to jump to, and S4 is
2463 the value that will be pushed onto the stack to send it to the output of
2464 the yield statement. The `callBCOffset' will be stored to the m_callOff
2465 field of the ActRec in the generator.
2467 | ContPreNext, ND, S(Obj) C(Bool), B
2469 Performs operations needed for the next() method of Generator object S0.
2470 If the generator is already running or finished, or it was not started yet
2471 and the S1 check-started flag is set, the branch B is taken. Otherwise,
2472 the generator is marked as running.
2474 | ContStartedCheck, ND, S(Obj), B
2476 Checks if the Generator object S0 has started, and if not branches to
2479 | ContValid, D(Bool), S(Obj), NF
2481 Return true if a generator is not done, false otherwise.
2483 | ContStarted, D(Bool), S(Obj), NF
2485 Return true if a generator has been run at least once, i.e. is not in the
2486 Created state, false otherwise.
2488 | ContArIncKey, ND, S(FramePtr), NF
2490 Special-case key update for generator, ActRec of which is S0, which
2491 increments the key of a generator if that generator's key is an Int.
2492 This will cause undefined behavior if the generator's key is not an Int.
2494 | ContArIncIdx, D(Int), S(FramePtr), NF
2496 Increment the internal index in the Generator in S0, and return the new index
2499 | ContArUpdateIdx, ND, S(FramePtr) S(Int), NF
2501 Updates the internal index of generator with S1 if necessary, i.e. if S1
2502 is larger than the index. S0 is the pointer to the embedded ActRec.
2504 | LdContActRec, D(FramePtr), S(Obj), NF
2506 Loads the Generator object's ActRec, given a pointer to the generator
2509 | LdContResumeAddr, D(TCA|Nullptr), S(Obj), NF
2511 Load the resume addr from the Generator in S0.
2513 | StContArState<state>, ND, S(FramePtr), NF
2515 Change the state of the Generator object which has frame pointer S0.
2517 | LdContArValue, DParam(Cell), S(FramePtr), PRc
2519 Loads 'value' from the Generator object ActRec of which is S0.
2521 | StContArValue, ND, S(FramePtr) S(Cell), CRc
2523 Stores 'value' into the Generator object ActRec of which is S0. S1 is the
2526 | LdContArKey, DParam(Cell), S(FramePtr), PRc
2528 Loads 'key' from the Generator object ActRec of which is S0.
2530 | StContArKey, ND, S(FramePtr) S(Cell), CRc
2532 Stores 'key' into the Generator object ActRec of which is S0. S1 is the
2535 | AFWHBlockOn, ND, S(FramePtr) S(Obj), CRc
2537 Establish dependency between parent AsyncFunctionWaitHandle object, whose
2538 ActRec is given by S0, and child WaitableWaitHandle object referenced by S1.
2540 | LdWHState, D(Int), S(Obj), NF
2542 Loads the state of the WaitHandle in S0, which is a value from the wait
2543 handle states in ext_asio.h. This instruction has undefined behavior if S0 is
2546 | LdWHResult, DParam(Cell), S(Obj), NF
2548 Loads the result of the WaitHandle in S0. This instruction has undefined
2549 behavior if S0 is not a WaitHandle, or if S0 is not finished.
2551 | LdWHNotDone, D(Int), S(Obj), NF
2553 Returns 1 if S0 is not finished, and 0 if S0 is finished.
2555 | CountWHNotDone<local,count>, D(Int), S(FramePtr), B
2557 Returns the number of unfinished awaitables contained in the contiguous
2558 locals beginning at local and extending count, skipping all nulls. A branch
2559 is taken if a non-Awaitable non-null value is encountered.
2561 | LdAFWHActRec, D(FramePtr), S(Obj), NF
2563 Loads the AsyncFunctionWaitHandle object's ActRec, given a pointer to the
2564 AsyncFunctionWaitHandle object in S0.
2567 15. Debugging, instrumentation, and profiling
2569 | IncStat, ND, C(Int), NF
2571 Increment stat counter. S0 is the implementation defined stat counter index.
2573 | IncProfCounter<TransID>, ND, NA, NF
2575 Increment the profiling counter associated with translation TransID.
2577 | IncCallCounter, ND, S(FramePtr), NF
2579 Increment the counter associated associated with the last call, namely from
2580 the function containing the previous translation in the call stack into the
2583 | DbgAssertRefCount<AssertReason>, ND, S(Cell), NF
2585 Assert that S0 has a valid refcount. If S0 has a reference counted type and
2586 its count is implausible then execute a hardware trap instruction.
2588 | DbgTraceCall<spOffset>, ND, S(FramePtr) S(StkPtr), NF
2590 When EvalHHIRGenerateAsserts is on, this instruction is inserted at the
2591 start of each region, to emit some sanity checking code.
2593 | DbgAssertFunc, ND, S(FramePtr), NF
2595 Assert that the func on the srckey is the current function in Frame S0.
2596 If the assertion fails, execution is aborted via a hardware exception.
2598 | RBTraceEntry, ND, NA, NF
2600 | RBTraceMsg, ND, NA, NF
2602 Ring buffer tracing.
2604 | ZeroErrorLevel, D(Int), NA, NF
2606 | RestoreErrorLevel, ND, S(Int), NF
2608 Helper instructions for fast implementation of the PHP error silencing
2614 | IterInit<IterData>, D(Bool), S(ArrLike,Obj) S(FramePtr), CRc
2616 | IterInitK<IterData>, D(Bool), S(ArrLike,Obj) S(FramePtr), CRc
2618 | LIterInit<IterData>, D(Bool), S(ArrLike) S(FramePtr), NF
2620 | LIterInitK<IterData>, D(Bool), S(ArrLike) S(FramePtr), NF
2622 <IterData> consists of three indices, iterId, keyId and valId. iterId is
2623 the index of the iterator variable, keyId and valId are indices of local
2626 Initializes the iterator variable whose index is given by iterId.
2627 This instruction creates the appropriate iterator for the array or object that
2628 S0 references, and rewinds the new iterator to its start. S0 points to the
2629 stack frame containing the iterator and local variables with the indices
2630 iterId, keyId and valId.
2632 If the new iterator is at its end (i.e., has no elements to iterate over),
2633 this instruction decrements the refcount of S0 and returns false; otheriwse,
2634 it stores a reference to S0 in the new iterator and returns true. If the
2635 iterator is not at its end, then this instruction stores the iterator's first
2636 value (and key) into the local variable with index valId (and keyId,
2639 The IterInit and IterInitK instructions always copy the array element by
2642 The LIter variations only accept arrays and do not take ownership of their
2643 base. Instead the base is provided on each operation on the iterator. This
2644 avoids having to raise the ref-count of the base (in situations where this is
2647 This instruction has the ConsumesRC property because it either decrements the
2648 reference count of S0 or stores a reference to S0 into the new iterator.
2650 | IterNext<IterData>, D(Bool), S(FramePtr), NF
2652 | IterNextK<IterData>, D(Bool), S(FramePtr), NF
2654 | LIterNext<IterData>, D(Bool), S(ArrLike) S(FramePtr), NF
2656 | LIterNextK<IterData>, D(Bool), S(ArrLike) S(FramePtr), NF
2658 <IterData> consists of three indices, iterId, keyId and valId. iterId is
2659 the index of the iterator variable, keyId and valId are indices of local
2660 variables. S0 points to the stack frame containing the iterator and local
2661 variables with the indices iterId, keyId and valId.
2663 Advances the iterator variable whose index is given by iterId.
2665 If the iterator has reached the end, this instruction frees the iterator
2666 variable and returns false; otherwise, it returns true. If the iterator has
2667 not reached its end, then this instruction stores the iterator's next value
2668 (and key) into the local variable with index valId (and keyId, respectively).
2670 The IterInit and IterInitK instructions always copy the array element by
2673 | IterFree<iterId>, ND, S(FramePtr), NF
2675 Free the iterator variable with id `iterId` in the stack frame of S0.
2676 For non-local iterators, this instruction will dec-ref the stored base.
2678 | KillIter<iterId>, ND, S(FramePtr), NF
2680 Mark the iterator at `iterId` as no longer containing a meaningful value.
2681 We can use this operation to elide stores for iterator fields that do not
2682 get loaded again. In debug builds, it will write poison values to the fields.
2684 | GetDictPtrIter, DPtrIter, S(DArr,Dict) S(Int), NF
2686 | GetVecPtrIter, DPtrIter, S(VArr,Vec) S(Int), NF
2688 Returns a pointer to the elm S1 of a {mixed,packed}-layout array S0. S1 does
2689 not need to be a valid array position; for example, it may equal the size of
2690 the array (so that the "elm" returned is the pointer-iteration end for S0).
2692 | AdvanceDictPtrIter<offset>, DPtrIter, S(PtrToElemCell), NF
2694 | AdvanceVecPtrIter<offset>, DPtrIter, S(PtrToElemCell), NF
2696 Increments the pointer S0 to the array element with the given layout `offset`
2697 positions forward. `offset` is allowed to be negative.
2699 | LdPtrIterKey<T>, DParam(Int|Str), S(PtrToElemCell), NF
2701 | LdPtrIterVal<T>, DPtrIterVal, S(PtrToElemCell), NF
2703 Loads the key or val from the array element pointed to by S0. S0 must be a
2704 valid elm; that is, it can't point to the end of the array data. LdPtrIterKey
2705 can only be used for mixed elms, but LdPtrIterVal supports mixed and packed.
2707 T must be a valid type for the array's keys - i.e., a subtype of TInt|TStr.
2708 For LdPtrIterKey, T is used to type the result; if it's specific enough, we
2709 skip doing a check on the type of the elm. For LdPtrIterVal, it's only used
2710 to constrain the memory effects of the op.
2712 | EqPtrIter, D(Bool), S(PtrToElemCell) S(PtrToElemCell), NF
2714 Compares two pointer iterators for equality.
2717 17. Member instruction support
2719 | LdMIStateAddr, D(PtrToMISCell), C(Int), NF
2721 Load an MInstrState address. Returns a pointer to offset S0 within the
2722 current MInstrState.
2724 | LdMBase, D(LvalToCell), NA, NF
2726 Load the current value of the member base register.
2728 | StMBase, ND, S(LvalToCell), NF
2730 Store a new value to the member base register. It is illegal for any
2731 instruction other than StMBase or InterpOne (when interpreting a member
2732 instruction) to modify the member base register.
2734 | FinishMemberOp, ND, NA, NF
2736 Mark the end of a member operation. This has no effect at runtime but exists
2737 to provide information for certain optimizations.
2739 All of the remaining opcodes in this section are simple wrappers around helper
2740 functions (specified in S0) to perform the corresponding vector operation. If
2741 S1 is a ConstCls it represents the context class for the operation.
2743 SetElem, SetProp, and SetNewElem are used to implement part of the SetM hhbc
2744 opcode, which almost always pushes its first stack input or a StaticStr as its
2745 stack result. The combinations of input types that cause SetM to push anything
2746 other than those two values are vanishingly rare in correct PHP programs, so
2747 these three instructions have been optimized for the common cases. SetNewElem
2748 and SetProp have no destination, allowing the compiler to predict that the
2749 SetM's output will be the same as its input (and optimize accordingly). If that
2750 turns out to not be the case at runtime, the instruction will throw an
2751 InvalidSetMException. The exception will hold a Cell containing the value the
2752 SetM should push on the stack instead of its input value. The runtime is
2753 responsible for catching this exception, finishing execution of the SetM
2754 instruction, pushing the value from the exception on the stack, and proceeding
2755 as appropriate (most likely with a side exit to the next bytecode instruction,
2756 since it has pushed an unexpected type onto the stack).
2758 SetElem is similar to SetProp and SetNewElem but can also be used for setting
2759 characters within strings. When given a string base and a valid offset, SetElem
2760 returns a string representation of the newly inserted character. In all other
2761 cases it returns nullptr or throws an InvalidSetMException. It will throw this
2762 exception when it detects invalid input types, or when trying to set a string
2763 offset that would grow the string beyond the maximum supported size.
2765 The input types that will cause the errors described above are listed here:
2767 SetNewElem will fail if the base is not a subtype of {Null|Str|Arr|Obj} and not
2769 SetElem has the same base constraint as SetNewElem. In addition, the key must
2770 not be a subtype of {Arr|Obj}.
2771 SetProp will fail if the base is not a subtype of {Obj|Null}.
2773 Any instructions that take a pointer to an MInstrState struct use the various
2774 fields of that struct for holding intermediate values.
2776 | BaseG, D(LvalToMembCell), S(Str), NF
2778 Get a base from global named S0. If it is not a defining BaseG it can also
2779 return the init_null_variant, so for now it returns a PtrToMembCell.
2781 | PropX, D(LvalToMembCell), S(Obj,LvalToCell) S(Cell) S(PtrToMISCell), NF
2783 Lookup intermediate property in S0, with key S1.
2785 | PropQ, D(LvalToMembCell), S(Obj,LvalToCell) S(StaticStr) S(PtrToMISCell), NF
2787 A nullsafe version of PropX, returns null if the base S0 is null.
2789 | PropDX, D(LvalToMembCell), S(Obj,LvalToCell) S(Cell) S(PtrToMISCell), MProp
2791 Like PropX, but used for intermediate element lookups that may modify the
2794 | CGetProp, D(Cell), S(Obj,LvalToCell) S(Cell), PRc
2796 Get property with key S1 from S0.
2798 | CGetPropQ, D(Cell), S(Obj,LvalToCell) S(StaticStr), PRc
2800 A nullsafe version of CGetProp, returns null if the base S0 is null.
2802 | SetProp, ND, S(Obj,LvalToCell) S(Cell) S(Cell), MProp
2804 Set property with key S1 in S0 to S2.
2806 | UnsetProp, ND, S(Obj,LvalToCell) S(Cell), NF
2808 Unset an object property.
2810 | SetOpProp<op>, D(Cell), S(Obj,LvalToCell) S(Cell) S(Cell), MProp|PRc
2812 Set op propery with key S1 in base S0, using S2 as the right hand side.
2814 | IncDecProp<op>, D(Cell), S(Obj,LvalToCell) S(Cell), MProp|PRc
2816 Increment/decrement property with key S1 in base S0.
2818 | IssetProp, D(Bool), S(Obj,LvalToCell) S(Cell), NF
2820 Returns true iff the property with key S1 in base S0 is set.
2822 | ElemX, D(Cell), S(LvalToCell) S(Cell), NF
2824 Get intermediate element with key S1 from base S0. The base will not be
2825 modified and the result will not be inc-ref-ed.
2827 | CheckDictKeys<T>, ND, S(DArr,Dict), B
2829 Check that the given mixed array is free of tombstones and that all of its
2830 elements' keys match the type T. If any check fails, branch to block B.
2831 Like CheckMixedArrayOffset, this check is allowed to have false negatives -
2832 it may fail even if the array has keys of the given type.
2834 | CheckMixedArrayOffset<pos>, ND, S(DArr) S(Int,Str), B
2836 Check that `pos' is within the usage bounds of S0 (including tombstones), and
2837 that S1 exactly matches the element key of S0 at `pos'. If any of the checks
2838 fail, branch to B. This check is allowed to have false negatives, in the
2839 case of int-like strings.
2841 | CheckArrayCOW, ND, S(ArrLike), B|LA
2843 Check that S0 has a refcount of exactly 1; if not, branch to B.
2845 | ProfileDictAccess, ND, S(DArr,Dict) S(Int,Str), NF
2847 Profile access of the element keyed by S1 in S0, tracking sizes and offsets.
2849 | CheckDictOffset<pos>, ND, S(DArr,Dict) S(Int,Str), B
2851 Check that `pos' is within the usage bounds of S0 (including tombstones), and
2852 that S1 exactly matches the element key of S0 at `pos'. If any of the checks
2853 fail, branch to B. This check is allowed to have false negatives.
2855 | ProfileKeysetAccess, ND, S(Keyset) S(Int,Str), NF
2857 Profile access of the element keyed by S1 in S0, tracking sizes and offsets.
2859 | CheckKeysetOffset<pos>, ND, S(Keyset) S(Int,Str), B
2861 Check that `pos' is within the usage bounds of S0 (including tombstones), and
2862 that S1 exactly matches the element key of S0 at `pos'. If any of the checks
2863 fail, branch to B. This check is allowed to have false negatives.
2865 | CheckMissingKeyInArrLike, ND, S(ArrLike) S(StaticStr), B
2867 Uses the StrKeyTable to check if S1 is guaranteed to be missing in S0.
2868 If S1 may be present, branches to block B. If we branch here, the key may or
2871 | ElemMixedArrayK, D(LvalToElemInitCell), S(DArr) S(Int,Str) S(Int), NF
2873 Returns an lval to the element of MixedArray S0 at the known position S2 in S1.
2875 | ElemVecD, D(LvalToElemInitCell), S(LvalToVArr,LvalToVec) S(Int), MElem
2877 | ElemVecU, D(LvalToMembInitCell), S(LvalToVArr,LvalToVec) S(Int), MElem
2879 Similar to ElemX, but the base S0 is a vec and the key S1 is an int. ElemVecD
2880 is for Define member instrs and ElemVecU is for Unset. (Other variations can
2881 be implemented without special IR instructions).
2883 | ElemDictD, D(LvalToElemInitCell), S(LvalToDArr,LvalToDict) S(Int,Str), MElem
2885 | ElemDictU, D(LvalToMembInitCell), S(LvalToDArr,LvalToDict) S(Int,Str), MElem
2887 Similar to ElemDX and ElemUX, but specialized for when the base S0 is a
2888 dict and the key S1 is an int/str.
2890 | ElemDictK, D(LvalToElemInitCell), S(DArr,Dict) S(Int,Str) S(Int), NF
2892 Returns an lval to the element of dict S0 at the known position S2 in S1.
2894 | ElemKeysetU, D(LvalToMembInitCell), S(LvalToKeyset) S(Int,Str), MElem
2896 Similar to ElemUX, but specialized for when the base S0 is a keyset and the
2897 key S1 is an int/str. Keysets do not support the define syntax.
2899 | ElemKeysetK, D(LvalToElemInitCell), S(Keyset) S(Int,Str) S(Int), NF
2901 Returns an lval to the element of keyset S0 at the known position S2 in S1.
2903 | ElemDX, D(LvalToMembCell), S(LvalToCell) S(Cell), MElem
2905 Like ElemX, but used for intermediate element lookups that may modify the
2908 | ElemUX, D(LvalToMembCell), S(LvalToCell) S(Cell), MElem
2910 Like ElemX, but used for intermediate element lookups that may modify the
2911 base as part of an unset operation.
2913 | DictGet, DDictElem, S(DArr,Dict) S(Int,Str), NF
2915 Get element with key S1 from base S0, throwing if the element is not present.
2917 | DictGetQuiet, DDictElem, S(DArr,Dict) S(Int,Str), NF
2919 Get element with key S1 from base S0, returning null if the element is not
2922 | DictGetK, DDictElem, S(DArr,Dict) S(Int,Str) S(Int), NF
2924 Like DictGet, but the element for S1 is at a known position S2 in S0.
2926 | KeysetGet, DKeysetElem, S(Keyset) S(Int,Str), NF
2928 Get element with key S1 from base S0, throwing if the element is not present.
2930 | KeysetGetQuiet, DKeysetElem, S(Keyset) S(Int,Str), NF
2932 Get element with key S1 from base S0, returning null if the element is not
2935 | KeysetGetK, DKeysetElem, S(Keyset) S(Int,Str) S(Int), NF
2937 Like KeysetGet, but the element for S1 is at a known position S2 in S0.
2939 | StringGet, D(StaticStr), S(Str) S(Int), PRc
2941 Get string representing character at position S1 from base string S0. Raises
2942 a notice if the position is out of bounds.
2944 | MapGet, D(Cell), S(Obj) S(Int,Str), PRc
2946 Get element with key S1 from base S0.
2948 | CGetElem, D(Cell), S(LvalToCell) S(Cell), PRc
2950 Get element with key S1 from S0.
2952 | MemoGetStaticValue<func,T>, DParam(InitCell), NA, B
2954 Get the memo value associated with the static function "func". If the value
2955 is not present, branch. The returned value is not inc-reffed. This op can
2956 only be used inside a memoize wrapper.
2958 | MemoGetStaticCache<func,keys,T>, DParam(InitCell), S(FramePtr), B
2960 Perform a lookup on the memo cache associated with the static function
2961 "func". The keys for the lookup are read from the locals on the frame pointed
2962 to by S0 (which must be ints or strings). If the lookup fails, branch. The
2963 returned value is not inc-reffed. This op can only be used inside a memoize
2966 | MemoGetLSBValue<func,T>, DParam(InitCell), S(Cls), B
2968 Get the memo value associated with the static function "func" and late static
2969 bound class S0. If the value is not present, branch. The returned value is not
2970 inc-reffed. This op can only be used inside a memoize wrapper.
2972 | MemoGetLSBCache<func,keys,T>, DParam(InitCell), S(FramePtr) S(Cls), B
2974 Perform a lookup on the memo cache associated with the static function
2975 "func" and late static bound class S1. The keys for the lookup are read from
2976 the locals on the frame pointed to by S0 (which must be ints or strings). If
2977 the lookup fails, branch. The returned value is not inc-reffed. This op can
2978 only be used inside a memoize wrapper.
2980 | MemoGetInstanceValue<slot,func,T>, DParam(InitCell), S(Obj), B
2982 Get the memo value at the specified memo slot on S0. If the value is not
2983 present, branch. The returned value is not inc-reffed. This op can only be
2984 used inside a memoize wrapper.
2986 | MemoGetInstanceCache<func,keys,T>, DParam(InitCell), S(FramePtr) S(Obj), B
2988 Perform a lookup on the memo cache at the specified memo slot on S1. The keys
2989 for the lookup are read from the locals on the frame pointed to by S0 (which
2990 must be ints or strings). If the lookup fails, branch. The returned value is
2991 not inc-reffed. This op can only be used inside a memoize wrapper.
2993 | MemoSetStaticValue<func>, ND, S(InitCell), NF
2995 Set S0 as the memo value associated with the static function "func". Store
2996 the value, overwriting any previous value, with appropriate ref-count
2997 manipulations. This op can only be used inside a memoize wrapper.
2999 | MemoSetStaticCache<func,keys>, ND, S(FramePtr) S(InitCell), NF
3001 Store S1 in the memo cache associated with the static function "func". The
3002 keys for the lookup are read from the locals on the frame pointed to be S0
3003 (which must be ints or strings). Store the value, overwriting any previous
3004 value, with appropriate ref-count manipulations. This op can only be used
3005 inside a memoize wrapper.
3007 | MemoSetLSBValue<func>, ND, S(InitCell) S(Cls), NF
3009 Set S0 as the memo value associated with the static function "func" and
3010 late static bound class S1. Store the value, overwriting any previous
3011 value, with appropriate ref-count manipulations. This op can only be used
3012 inside a memoize wrapper.
3014 | MemoSetLSBCache<func,keys>, ND, S(FramePtr) S(Cls) S(InitCell), NF
3016 Store S2 in the memo cache associated with the static function "func" and
3017 late static bound class S1. The keys for the lookup are read from the
3018 locals on the frame pointed to be S0 (which must be ints or strings).
3019 Store the value, overwriting any previous value, with appropriate
3020 ref-count manipulations. This op can only be used inside a memoize wrapper.
3022 | MemoSetInstanceValue<slot,func>, ND, S(Obj) S(InitCell), NF
3024 Set S2 as the memo value at the specified memo slot on S1. Store the value,
3025 overwriting any previous value, with appropriate ref-count
3026 manipulations. This op can only be used inside a memoize wrapper.
3028 | MemoSetInstanceCache<slot,func,keys>, ND, S(FramePtr) S(Obj) S(InitCell), NF
3030 Store S2 in the memo cache at the specified memo slot on S1. Store the value,
3031 overwriting any previous value, with appropriate ref-count
3032 manipulations. This op can only be used inside a memoize wrapper.
3034 | InitObjMemoSlots<class>, ND, S(Obj), NF
3036 Initialize the memoization instance slots for object S0 of the given class.
3038 | VecSet, DVecSet, S(VArr,Vec) S(Int) S(Cell), PRc|CRc
3040 Set element with key S1 in S0 to S2. The dest will be a new Vec that should
3043 | DictSet, DDictSet, S(DArr,Dict) S(Int,Str) S(Cell), PRc|CRc
3045 Set element with key S1 in S0 to S2. The dest will be a new Dict that should
3048 | MapSet, ND, S(Obj) S(Int,Str) S(Cell), CRc
3050 Set element with key S1 in S0 to S2.
3052 | VectorSet, ND, S(Obj) S(Int,Str) S(Cell), CRc
3054 Set element with key S1 in S0 to S2.
3056 | SetElem, DSetElem, S(LvalToCell) S(Cell) S(Cell), MElem
3058 Set element with key S1 in S0 to S2. SetElem returns a Nullptr in the common
3059 case, where the logical result of the hhbc SetM is its right hand side. In
3060 the case of string bases, the SetM returns a new string containing the newly
3061 inserted character. So the return value of this instruction is Nullptr unless
3062 SetM needed to return a static string.
3064 Furthermore, in the case of "invalid offsets", SetElem may throw an
3065 InvalidSetMException (see discussion above).
3067 | SetRange, ND, S(LvalToCell) S(Int) S(Cell) S(Int) S(Int), MElem
3069 | SetRangeRev, ND, S(LvalToCell) S(Int) S(Cell) S(Int) S(Int), MElem
3071 Perform a range set or reverse range set operation, with the same arguments
3072 and semantics as the RangeSet bytecode instruction.
3074 | UnsetElem, ND, S(LvalToCell) S(Cell), MElem
3076 Unsets the element at key S1 in the base S0.
3078 | SetOpElem<op>, D(Cell), S(LvalToCell) S(Cell) S(Cell), MElem|PRc
3080 Set op elem with key S1 in base S0, using S2 as the right hand side.
3082 | IncDecElem, D(Cell), S(LvalToCell) S(Cell), MElem|PRc
3084 Increment/decrement element with key S1 in base S0.
3086 | SetNewElem, ND, S(LvalToCell) S(Cell), MElem
3088 Append the value in S1 to S0.
3090 | SetNewElemDict, ND, S(LvalToDArr,LvalToDict) S(Cell), MElem
3092 | SetNewElemVec, ND, S(LvalToVArr,LvalToVec) S(Cell), MElem
3094 | SetNewElemKeyset, ND, S(LvalToKeyset) S(Int,Str), MElem
3096 Specializations of SetNewElem for pointers to dicts, vecs, and keysets.
3098 | DictIsset, D(Bool), S(DArr,Dict) S(Int,Str), NF
3100 Returns true iff the element at key S1 in the base S0 is set.
3102 | KeysetIsset, D(Bool), S(Keyset) S(Int,Str), NF
3104 Returns true iff the element at key S1 in the base S0 is set.
3106 | StringIsset, D(Bool), S(Str) S(Int), NF
3108 Returns true iff the string S0 has a character at position S1.
3110 | VectorIsset, D(Bool), S(Obj) S(Int), NF
3112 Returns true iff the element at key S1 in the base S0 is set.
3114 | PairIsset, D(Bool), S(Obj) S(Int), NF
3116 Returns true iff the element at key S1 in the base S0 is set.
3118 | MapIsset, D(Bool), S(Obj) S(Int,Str), NF
3120 Returns true iff the element at key S1 in the base S0 is set.
3122 | IssetElem, D(Bool), S(LvalToCell) S(Cell), NF
3124 Returns true iff the element at key S1 in S0 is set.
3126 | CheckRange, D(Bool), S(Int) S(Int), NF
3128 Returns true iff S0 is in the range [0, S1).
3130 | ThrowArrayIndexException, ND, S(ArrLike) S(Int), T
3132 Throws an out of bounds exception if S0 is an undefined index for an array.
3134 | ThrowArrayKeyException, ND, S(ArrLike) S(Str), T
3136 Throws an out of bounds exception if S0 is an undefined key for an array.
3138 | ThrowOutOfBounds, ND, S(ArrLike|Obj) S(Cell), T|LA
3140 Throws an OutOfBoundsException corresponding to an access of S0 with the key
3143 | ThrowInvalidArrayKey, ND, S(ArrLike) S(Cell), T|LA
3145 Throws an InvalidArgumentException corresponding to an access of S0 with the
3146 key S1, which has a type invalid for that array. For varrays, an
3147 OutOfBoundsException will be thrown instead for compatibility.
3149 | ThrowInvalidArrayKeyForSet, ND, S(ArrLike) S(Cell), T|LA
3151 Throws an InvalidArgumentException corresponding to an access of S0 with the
3152 key S1, which has a type invalid for that array.
3154 | ThrowInvalidOperation, ND, S(Str), T
3156 Throws an InvalidOperationException with a message indicating S0.
3158 | ThrowDivisionByZeroException, ND, NA, T
3160 Throws a DivisionByZeroException.
3162 | ThrowLateInitPropError, ND, S(Cls) S(Str) S(Bool), T
3164 Throws an InvalidOperationException indicating an access of a unset LateInit
3165 property. S0 is the class the property was declared on. S1 is the property
3166 name. S2 is true if its a static property, false otherwise.
3168 | ThrowParameterWrongType<expectedType, func, argNum>, ND, S(Cell), T
3170 Throws a RuntimeException if calling a function with an argument that has the
3173 | ProfileType, ND, S(Cell), NF
3175 Profile the type of S0.
3177 | ProfileCall<rdsHandle>, ND, S(Func), NF
3179 Profile the call to a function S0.
3181 | ProfileMethod<rdsHandle>, ND, S(Cls) S(Func), NF
3183 Profile the method S1 called with class context S0.
3185 | ProfileProp, ND, C(StaticStr) C(StaticStr), NF
3187 Profile the access to property S(1) with base class S(0).
3189 | CheckVecBounds, ND, S(VArr,Vec) S(Int), B
3191 Checks that the index in S1 is within the bounds of the packed array or
3192 vector array in S0. Branches to B if the index is out of bounds.
3194 | LdVecElemAddr<T>, DParam(LvalToElemCell), S(VArr,Vec) S(Int), NF
3196 Loads the address of the element at index S1 of the packed array or vec array
3197 in S0. This instruction assumes the array actually contains an element at
3198 that offset (IE, the array has the proper length).
3200 | ReserveVecNewElem, D(Int), S(VArr,Vec), B
3202 If there is room in the packed or vec array (which is assumed to be mutable),
3203 increments the array size and returns the index of the new last element
3204 (which you must initialize); else jumps to the taken branch.
3206 | LdVecElem, DVecElem, S(VArr,Vec) S(Int), NF
3208 Loads the element of the vec array in S0 at offset S1. This instruction
3209 assumes that the vec actually contains an element at that offset (IE, the vec
3210 has the proper length).
3212 | LdVectorSize, D(Int), S(Obj), NF
3214 Returns the size of the given Vector collection in S0.
3216 | ColIsEmpty, D(Bool), S(Obj), NF
3218 | ColIsNEmpty, D(Bool), S(Obj), NF
3220 Returns whether a collection instance is empty or not. S0 must be known to
3221 be an instance of a collection class at compile time.
3223 | VecFirst, DVecFirstElem, S(VArr,Vec), NF
3225 Returns the first value from the packed or vec array in S0.
3226 If the array is empty, it will return NULL.
3228 | VecLast, DVecLastElem, S(VArr,Vec), NF
3230 Returns the last value from the packed or vec array in S0.
3231 If the array is empty, it will return NULL.
3233 | DictFirst, DDictFirstElem, S(DArr,Dict), NF
3235 Returns the first value from the mixed or dict array in S0.
3236 If the array is empty, it will return NULL.
3238 | DictLast, DDictLastElem, S(DArr,Dict), NF
3240 Returns the last value from the mixed or dict array in S0.
3241 If the array is empty, it will return NULL.
3243 | DictFirstKey, DDictFirstKey, S(DArr,Dict), NF
3245 Returns the first key from the mixed or dict array in S0.
3246 If the array is empty, it will return NULL.
3248 | DictLastKey, DDictLastKey, S(DArr,Dict), NF
3250 Returns the last key from the mixed or dict array in S0.
3251 If the array is empty, it will return NULL.
3253 | KeysetFirst, DKeysetFirstElem, S(Keyset), NF
3255 Returns the first value(key) from the keyset in S0.
3256 If the array is empty, it will return NULL.
3258 | KeysetLast, DKeysetLastElem, S(Keyset), NF
3260 Returns the first value(key) from the keyset in S0.
3261 If the array is empty, it will return NULL.
3263 | SetLegacyVec, D(Vec), S(Vec), CRc|PRc
3265 | SetLegacyDict, D(Dict), S(Dict), CRc|PRc
3267 | UnsetLegacyVec, D(Vec), S(Vec), CRc|PRc
3269 | UnsetLegacyDict, D(Dict), S(Dict), CRc|PRc
3271 Enable/disable the legacy bit on the vec/dict in S0, copying it if necessary
3272 and returning the tagged array.
3275 18. Exception/unwinding support
3277 | BeginCatch, ND, NA, NF
3279 Marks the beginning of a catch region. Exact behavior is implementation and
3280 architecture specific.
3282 | EndCatch<spOffset,mode,stublogue>, ND, S(FramePtr) S(StkPtr), T
3284 Marks the end of a catch region and returns control to the unwinder. The
3285 `spOffset' field represents a logical adjustment to S1 (in cells) to yield
3286 the vm stack pointer, however the stack pointer is not actually adjusted
3287 before this instruction returns control to the unwinder. The unwinder
3288 instead relies on fixup map information to find the appropriate stack
3289 pointers. Instead it's part of this instruction to facilitate assertions and
3290 memory effect analysis.
3292 If the `stublogue' flag is set, the native stack pointer is updated to reflect
3293 the state prior to entering the stublogue context.
3295 | UnwindCheckSideExit, ND, S(FramePtr) S(StkPtr), B
3297 Branches to B if the currently executing catch region should return control
3298 to the unwinder rather than side exiting. Used to control behavior in catch
3299 traces for the InvalidSetMException and TVCoercionException situations.
3301 | LdUnwinderValue<T>, DParam(Cell), NA, PRc
3303 Loads the value contained by the current unwinder exception.
3305 | EnterTCUnwind<teardown>, ND, S(Obj), CRc|T
3307 Enters tc_unwind_resume by doing a side enter, i.e. skipping itanium ABI.
3308 Stores the ObjectData* in S0 to UnwindRDS' exn field as well as true to
3310 If teardown is set, it notifies tc_unwind_resume to also teardown the locals.
3312 19. Function prologues
3314 | EnterPrologue, ND, NA, NF
3316 Enter prologue context, which operates in the same mode as unique stubs.
3317 Makes sure the native stack is properly aligned.
3319 | CheckStackOverflow, ND, S(StkPtr), NF
3321 Check if the stack depth has exceeded its limit. If it has, jump to the
3322 stack overflow helper stub, which will throw.
3324 | CheckSurpriseFlagsEnter<func,argc>, ND, S(FramePtr), NF
3326 Test the implementation-specific surprise flags. If they're nonzero, call
3327 the function enter helper.
3329 | CheckSurpriseAndStack<func,args>, ND, S(FramePtr), NF
3331 Test surprise flags and stack overflow at the same time.
3333 | LdARFlags, D(Int), S(FramePtr), NF
3335 Load the flags stored on the ActRec pointed to by the frame
3336 pointer S0. Bits not defined as flags may contain arbitrary garbage.
3338 | LdTVAux<ValidBits>, D(Int), S(Cell), NF
3340 Load the value of m_aux from the TypedValue S0. ValidBits is a mask
3341 specifying which bits are allowed to be set. The runtime may ignore it.
3343 Note that when we pass TypedValues around in registers, we usually use a byte
3344 register for the m_type member, and thus ignore m_aux. LdTVAux is only valid
3345 when we know that S0's m_type and m_aux were both materialized into the same
3348 /* Local Variables: */
3349 /* fill-column: 79 */