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.
165 LP (Layout-preserving)
167 The instruction is closed under vanilla array layouts: if the first argument
168 is vanilla, so too is the destination. The first argument must be an
169 array-like type. Layout-preserving implies layout-agnostic.
175 1. Checks and Asserts
177 | CheckType<T>, DRefineS(0), S(Cell), B|P
179 Check that the type of the src S0 is T, and if so copy it to D, and
180 fallthrough. If S0 cannot be proven to be T, branch to block B. Note that
181 this means S0 still /may/ be a subtype of T in block B in some circumstances.
183 Specifically, subtypes of Type::Static may not be checked precisely,
184 depending on the type of the source. This means the instruction may take the
185 branch in some circumstances even when S0 is a subtype of T, if T has a
186 non-empty intersection with Type::Static.
188 Also note that many types are not supported as the typeParam right now.
190 | CheckNullptr, ND, S(Cls|StaticStr|Nullptr), B
192 If S0 is not a null pointer, branch to block B. This is used to check the
193 return value of a native helper that returns a potentially null StringData*.
195 | AssertType<T>, DRefineS(0), S(Cell,MemToCell), P
197 Assert that the type of S0 is T, copying it to D.
199 | CheckTypeMem<T>, ND, S(MemToCell), B
201 If the value pointed to by S0 is not type T, branch to the block B.
203 | CheckIter<iterId,iterType>, ND, S(FramePtr), B
205 Check that specialization type of the given iterator `iterId` on the frame S0
206 is `iterType`; if it is not, branch to block B.
208 | CheckLoc<T,localId>, ND, S(FramePtr), B
210 Check that type of the given localId on the frame S0 is T; if not, branch to
213 | CheckStk<T,offset>, ND, S(StkPtr), B
215 Check that the type of the cell on the stack pointed to by S0 at offset (in
216 cells) is T; if not, branch to block B.
218 | CheckMBase<T>, ND, S(LvalToCell), B
220 Check that the value pointed to by the member base register S0 has type T; if
221 not, branch to block B. This is functionally the same as CheckTypeMem.
223 | AssertLoc<T,localId>, ND, S(FramePtr), NF
225 Asserts that type of the supplied local on the frame S0 is T. This is used
226 for local type information, and is similar to CheckLoc except it doesn't
227 imply a runtime check (the assertion must've already been proven to be true)
228 and cannot cause control flow.
230 | AssertStk<T,offset>, ND, S(StkPtr), NF
232 Assert that stack element at `offset' (in cells) from S0 has type T. This is
233 similar to a CheckStk except that it does not imply a runtime check and
234 cannot cause control flow.
236 | AssertMBase<T>, ND, NA, NF
238 Assert that the value pointed to by the member base register has type T.
239 This is similar to a CheckMBase except that it does not imply a runtime check
240 and cannot cause control flow.
242 These instructions convert either a Cell or a Str to a primitive type (Bool,
243 Int, Dbl) and return the resulting value. They may throw an exception upon
244 failed type coercion. They are encoded along with callee Func, fn, and the
245 integer position of the argument, argNum, being coerced.
247 | CheckInit, ND, S(Cell), B
249 If S0's type is Uninit, branch to block B.
251 | CheckInitMem, ND, S(MemToCell), B
253 If the value pointed to by S0 has type Uninit, branch to block B.
255 | CheckCold<TransID>, ND, NA, B
257 Check if the counter associated with translation TransID is cold (i.e. within
258 a fixed threshold). If it's not (i.e. such translation has reached the
259 "hotness threshold"), then branch to block B.
261 | EndGuards, ND, NA, NF
263 A no-op at runtime, this instruction serves to mark the end of the initial
264 sequence of guards in a trace.
266 | CheckNonNull, DSubtract(0, Nullptr), S(Cls|Func|Obj|Str|MemToCell|TCA|Nullptr), B
268 If the value in S0 is Nullptr, branch to block B. If S0 cannot be Nullptr, or
269 always is Nullptr, this check may be optimized away.
271 | AssertNonNull, DSubtract(0, Nullptr), S(StaticStr|Nullptr), P
273 Returns S0, with Nullptr removed from its type. This instruction currently
274 supports a very limited range of types but can be expanded if needed.
276 | CheckImplicitContextNull, ND, NA, B
278 If the implicit context on RDS is null, branch to block B.
280 | CheckSmashableClass, ND, S(Smashable) S(Cls), B
282 If the lower 32 bits of S0 does not match class pointer S1, branch to block B.
286 | AddInt, D(Int), S(Int) S(Int), NF
288 | SubInt, D(Int), S(Int) S(Int), NF
290 | MulInt, D(Int), S(Int) S(Int), NF
292 | AddIntO, D(Int), S(Int) S(Int), B
294 | SubIntO, D(Int), S(Int) S(Int), B
296 | MulIntO, D(Int), S(Int) S(Int), B
298 | AddDbl, D(Dbl), S(Dbl) S(Dbl), NF
300 | SubDbl, D(Dbl), S(Dbl) S(Dbl), NF
302 | MulDbl, D(Dbl), S(Dbl) S(Dbl), NF
304 | DivDbl, D(Dbl), S(Dbl) S(Dbl), NF
306 | DivInt, D(Int), S(Int) S(Int), NF
308 | Floor, D(Dbl), S(Dbl), NF
310 | Ceil, D(Dbl), S(Dbl), NF
312 | AbsDbl, D(Dbl), S(Dbl), NF
314 | Sqrt, D(Dbl), S(Dbl), NF
316 | AndInt, D(Int), S(Int) S(Int), NF
318 | OrInt, D(Int), S(Int) S(Int), NF
320 | XorInt, D(Int), S(Int) S(Int), NF
322 | Shl, D(Int), S(Int) S(Int), NF
324 | Shr, D(Int), S(Int) S(Int), NF
326 | Lshr, D(Int), S(Int) S(Int), NF
328 Double arithmetic, integer arithmetic, and integer bitwise operations.
329 Performs the operation described by the opcode name on S0 and S1, and puts
332 Undefined behavior occurs if Mod is given a divisor of zero, or if the
333 divisor is -1 and the dividend is the minimum representable integer.
335 AbsDbl computes the absolute value of a double-precision value.
337 DivDbl conforms to IEEE 754. In particular, division by zero returns +/- INF
338 or NAN depending on the dividend; and should the result of a division be zero
339 the sign will follow the normal sign rules for division.
341 DivInt will perform integer division of S1 by S0. S0 should not be zero and
344 Note that Shr is an arithmetic right shift: The MSB is sign-extended.
346 Lshr is logical right shift.
348 Floor and Ceil will return an integral value not greater, or not less
349 than their input respectively. Their use requires SSE 4.1, availability
350 should be checked before they are emitted.
352 AddIntO, SubIntO, MulIntO perform integer arithmetic on S0 and S1, but will
353 branch to block B on integer overflow.
355 | XorBool, D(Bool), S(Bool) S(Bool), NF
357 Logical XOR of the two sources. (Note that && and || do not have
358 corresponding opcodes because they're handled at the bytecode level, to
359 implement short-circuiting.)
361 | Mod, D(Int), S(Int) S(Int), NF
363 Compute S0 mod S1. If S1 is -1 or 0 the results are undefined.
370 | ConvArrLikeToVec, D(Vec), S(ArrLike), PRc|CRc|LP
372 | ConvObjToVec, D(Vec), S(Obj), PRc|CRc
377 | ConvArrLikeToDict, D(Dict), S(ArrLike), PRc|CRc|LP
379 | ConvObjToDict, D(Dict), S(Obj), PRc|CRc
382 To keyset conversions:
384 | ConvArrLikeToKeyset, D(Keyset), S(ArrLike), PRc|CRc|LP
386 | ConvObjToKeyset, D(Keyset), S(Obj), PRc|CRc
391 | ConvDblToBool, D(Bool), S(Dbl), NF
393 | ConvIntToBool, D(Bool), S(Int), NF
395 | ConvStrToBool, D(Bool), S(Str), NF
397 | ConvObjToBool, D(Bool), S(Obj), NF
399 | ConvTVToBool, D(Bool), S(Cell), NF
402 To double conversions:
404 | ConvBoolToDbl, D(Dbl), S(Bool), NF
406 | ConvIntToDbl, D(Dbl), S(Int), NF
408 | ConvObjToDbl, D(Dbl), S(Obj), NF
410 | ConvStrToDbl, D(Dbl), S(Str), NF
412 | ConvResToDbl, D(Dbl), S(Res), NF
414 | ConvTVToDbl, D(Dbl), S(Cell), NF
419 | ConvBoolToInt, D(Int), S(Bool), NF
421 | ConvDblToInt, D(Int), S(Dbl), NF
423 | ConvObjToInt, D(Int), S(Obj), NF
425 | ConvStrToInt, D(Int), S(Str), NF
427 | ConvResToInt, D(Int), S(Res), NF
429 | ConvTVToInt, D(Int), S(Cell), NF
432 To string conversions:
434 | ConvDblToStr, D(Str), S(Dbl), PRc
436 | ConvIntToStr, D(Str), S(Int), PRc
438 | ConvObjToStr, D(Str), S(Obj), PRc
440 | ConvTVToStr, D(Str), S(Cell), PRc
443 All the above opcodes convert S0 from its current type to the destination
444 type, according to the PHP semantics of such a conversion.
446 | DblAsBits, D(Int), S(Dbl), NF
448 Reinterpret a double as an integer with the same bit pattern.
450 | OrdStr, D(Int), S(Str), NF
452 Convert the first byte in a string to an unsigned integer.
453 Intended as an optimization for ord($str)
455 | OrdStrIdx, D(Int), S(Str) S(Int), NF
457 Convert the character at position S1 in base string S0 to an unsigned
458 integer. Raises a notice if the position is out of bounds.
459 Intended as an optimization for ord($str[$idx]).
461 | ChrInt, D(StaticStr), S(Int), NF
463 Convert the integer S0 to a the one character string with ascii code
466 | StrictlyIntegerConv, D(Str|Int), S(Str), PRc
468 If S0 is a string representing an integer value (same criteria as array key
469 conversion), return that value as an integer. Otherwise return S0.
471 | ConvPtrToLval, DLvalOfPtr, S(PtrToCell), NF
473 Convert S0 to an equivalent lval.
476 4. Boolean predicates
478 | GtInt, D(Bool), S(Int) S(Int), NF
480 | GteInt, D(Bool), S(Int) S(Int), NF
482 | LtInt, D(Bool), S(Int) S(Int), NF
484 | LteInt, D(Bool), S(Int) S(Int), NF
486 | EqInt, D(Bool), S(Int) S(Int), NF
488 | NeqInt, D(Bool), S(Int) S(Int), NF
490 | CmpInt, D(Int), S(Int) S(Int), NF
492 Perform 64-bit integer comparisons.
494 | GtDbl, D(Bool), S(Dbl) S(Dbl), NF
496 | GteDbl, D(Bool), S(Dbl) S(Dbl), NF
498 | LtDbl, D(Bool), S(Dbl) S(Dbl), NF
500 | LteDbl, D(Bool), S(Dbl) S(Dbl), NF
502 | EqDbl, D(Bool), S(Dbl) S(Dbl), NF
504 | NeqDbl, D(Bool), S(Dbl) S(Dbl), NF
506 | CmpDbl, D(Int), S(Dbl) S(Dbl), NF
508 Perform comparisons of doubles. Comparisons that are unordered according to
509 IEEE 754 (such as when at least one operand is NaN) result in false.
511 | GtStr, D(Bool), S(Str) S(Str), NF
513 | GteStr, D(Bool), S(Str) S(Str), NF
515 | LtStr, D(Bool), S(Str) S(Str), NF
517 | LteStr, D(Bool), S(Str) S(Str), NF
519 | EqStr, D(Bool), S(Str) S(Str), NF
521 | NeqStr, D(Bool), S(Str) S(Str), NF
523 | SameStr, D(Bool), S(Str) S(Str), NF
525 | NSameStr, D(Bool), S(Str) S(Str), NF
527 | CmpStr, D(Int), S(Str) S(Str), NF
529 Performs comparison of strings
531 | GtBool, D(Bool), S(Bool) S(Bool), NF
533 | GteBool, D(Bool), S(Bool) S(Bool), NF
535 | LtBool, D(Bool), S(Bool) S(Bool), NF
537 | LteBool, D(Bool), S(Bool) S(Bool), NF
539 | EqBool, D(Bool), S(Bool) S(Bool), NF
541 | NeqBool, D(Bool), S(Bool) S(Bool), NF
543 | CmpBool, D(Int), S(Bool) S(Bool), NF
545 Performs comparison of booleans.
547 | GtObj, D(Bool), S(Obj) S(Obj), NF
549 | GteObj, D(Bool), S(Obj) S(Obj), NF
551 | LtObj, D(Bool), S(Obj) S(Obj), NF
553 | LteObj, D(Bool), S(Obj) S(Obj), NF
555 | EqObj, D(Bool), S(Obj) S(Obj), NF
557 | NeqObj, D(Bool), S(Obj) S(Obj), NF
559 | SameObj, D(Bool), S(Obj) S(Obj), NF
561 | NSameObj, D(Bool), S(Obj) S(Obj), NF
563 | CmpObj, D(Int), S(Obj) S(Obj), NF
565 Perform comparison of object. All versions except for SameObj and NSameObj may
566 re-enter the VM and therefore may throw exceptions. SameObj and NSameObj never
569 | GtArrLike, D(Bool), S(ArrLike) S(ArrLike), NF|LA
571 | GteArrLike, D(Bool), S(ArrLike) S(ArrLike), NF|LA
573 | LtArrLike, D(Bool), S(ArrLike) S(ArrLike), NF|LA
575 | LteArrLike, D(Bool), S(ArrLike) S(ArrLike), NF|LA
577 | EqArrLike, D(Bool), S(ArrLike) S(ArrLike), NF|LA
579 | NeqArrLike, D(Bool), S(ArrLike) S(ArrLike), NF|LA
581 | SameArrLike, D(Bool), S(ArrLike) S(ArrLike), NF|LA
583 | NSameArrLike, D(Bool), S(ArrLike) S(ArrLike), NF|LA
585 | CmpArrLike, D(Int), S(ArrLike) S(ArrLike), NF|LA
587 Perform comparison of array-likes. All versions except for SameArrLike and
588 NSameArrLike may re-enter the VM and therefore may throw exceptions.
589 SameArrLike and NSameArrLike never re-enter or throw. Relational comparisons
590 for dicts and keysets are not supported. As keysets only contain ints and
591 strings, comparisons never re-enter or throw.
593 | GtRes, D(Bool), S(Res) S(Res), NF
595 | GteRes, D(Bool), S(Res) S(Res), NF
597 | LtRes, D(Bool), S(Res) S(Res), NF
599 | LteRes, D(Bool), S(Res) S(Res), NF
601 | EqRes, D(Bool), S(Res) S(Res), NF
603 | NeqRes, D(Bool), S(Res) S(Res), NF
605 | CmpRes, D(Int), S(Res) S(Res), NF
607 Perform comparison of resources using PHP semantics. Resource comparisons
608 never re-enter or throw.
610 | EqCls, D(Bool), S(Cls) S(Cls), NF
612 Checks if two Class values are equal.
614 | EqLazyCls, D(Bool), S(LazyCls) S(LazyCls), NF
616 Checks if two Lazy class values are equal.
618 | EqFunc, D(Bool), S(Func) S(Func), NF
620 Checks if two Func values are equal.
622 | EqStrPtr, D(Bool), S(Str) S(Str), NF
624 Checks if two string values represent the same underlying string. That is,
625 that they point at the same underlying storage.
627 | EqArrayDataPtr, D(Bool), S(ArrLike) S(ArrLike), LA
629 Checks if the two arguments represent the same underlying ArrayData. That is,
630 that they point at the same underlying storage.
632 | ProfileInstanceCheck, ND, C(StaticStr), NF
634 Profile that S0 has been used as the RHS of an instance check.
636 | InstanceOf, D(Bool), S(Cls) S(Cls|Nullptr), NF
638 Sets D based on whether S0 is a descendant of the class, interface, or trait
639 in S1. (Note that this is always false for a trait). S1 may be null at
640 runtime if the class is not defined.
642 | InstanceOfIface, D(Bool), S(Cls) CStr, NF
644 Fast path for interface checks. Sets D based on whether S0 implements S1, but
645 S1 must be a unique interface. This should only be used in repo-authoritative
648 | InstanceOfIfaceVtable<iface,canOptimize>, D(Bool), S(Cls), NF
650 Faster path for interface checks. Sets D based on whether S0 implements
651 iface, which must be a unique interface with an assigned vtable slot. In
652 some circumstances, this instruction is ensuring the presence of the
653 vtableVec; in those cases, canOptimize is false to avoid eliminating the
656 | ExtendsClass<cls,strictLikely>, D(Bool), S(Cls), NF
658 A fast-path for instanceof checks. Sets D based on whether S0 is a descendant
659 of cls, where cls must be a unique class that is not an interface or a trait.
661 If strictLikely is true, optimize for the case where S0 is not equal to S1.
663 | InstanceOfBitmask, D(Bool), S(Cls) CStr, NF
665 | NInstanceOfBitmask, D(Bool), S(Cls) CStr, NF
667 A fast-path for instanceof checks. Sets D based on whether S0 is a descendant
668 of the class named by S1, where S1 must have a bit allocated for it in the
669 fast instance check bitvector (see class.h).
671 | InterfaceSupportsArrLike, D(Bool), S(Str), NF
673 | InterfaceSupportsStr, D(Bool), S(Str), NF
675 | InterfaceSupportsInt, D(Bool), S(Str), NF
677 | InterfaceSupportsDbl, D(Bool), S(Str), NF
679 Returns whether t instanceof S0 returns true when t is of the given type.
681 | ResolveTypeStruct<class,suppress,offset,size,isOrAsOp>,
682 | D(Dict), S(StkPtr) S(Cls|Nullptr), NF
684 Applies class/alias resolution on the type structure that is at the stack
685 offset given by S0 and offset. If size > 1, combine the type structures on
686 the stack into the first one's denoted holes. Returns a copy.
687 S1 is the calling class, used to resolve the this typehint.
688 If isOrAsOp is set, raises an error if S0 contains traits, function types or
690 If there is an error during type structure resolution, this instruction raises
691 an error. If suppress is set, this error is demoted to a warning.
693 | IsTypeStruct<handle>, D(Bool), S(Dict) S(Cell), LA
695 Returns whether S1 matches the type structure of a defined type in S0 and S1
696 is a subtype of S0. The input type structure (S0) must be resolved.
697 Handle is used for caching purposes.
699 | IsTypeStructCached, D(Bool), S(Dict) S(Cell), B|LA
701 Checks if S0 is cached in TSClassCache and if so, returns whehter S1 is a
702 subtype of S0. Otherwise, it branches.
704 | ProfileIsTypeStruct<handle>, ND, S(Dict), LA|ND
706 Profile S0 to determine whether S0 is a type structure holding a reference to
709 | ThrowAsTypeStructException, ND, S(Dict) S(Cell), LA|T
711 Throws an exception indicating why S1 does not match the type structure of a
712 defined type in S0 or why S1 is not a subtype of S0. The input type structure
713 (S0) must be resolved.
715 | RaiseErrorOnInvalidIsAsExpressionType, D(Dict), S(Dict), LA
717 Raises an error if the type hint for is/as expression contains an invalid
718 type such as callables, erased type variables and trait type hints.
719 The input type structure (S0) must be resolved.
721 | HasToString, D(Bool), S(Obj), NF
723 Returns whether the object S0 has a toString method.
725 | IsType<T>, D(Bool), S(Cell), NF
727 Sets D to true iff S0 holds a value that is of type T. T must not be a
730 | IsNType<T>, D(Bool), S(Cell), NF
732 Sets D to true iff S0 holds a value that is not of type T. T must not be a
735 | IsTypeMem<T>, D(Bool), S(MemToCell), NF
737 Sets D to true iff the value referenced by S0 is of type T. T must not be a
740 The value in S0 must not be a pointer into the evaluation stack or frame
743 | IsNTypeMem<T>, D(Bool), S(MemToCell), NF
745 Sets D to true iff the value referenced by S0 is not of type T. T must not be
748 | IsWaitHandle, D(Bool), S(Obj), NF
750 Sets D to true iff S0 is a subclass of WaitHandle.
752 | IsCol, D(Bool), S(Obj), NF
754 Sets D to true iff S0 is a collection.
756 | HasReifiedGenerics, D(Bool), S(Func), NF
758 Set D to true iff S0 is a reified function.
762 | JmpZero, ND, S(Int,Bool), B
764 | JmpNZero, ND, S(Int,Bool), B
766 Conditionally jump to based on S0.
768 | JmpSSwitchDest, ND, S(TCA) S(StkPtr) S(FramePtr), T
770 Jump to the target of a sswitch statement, leaving the region, where the
773 | JmpSwitchDest, ND, S(Int) S(StkPtr) S(FramePtr), T
775 Jump to the target of a switch statement, leaving the region, using table
776 metadata <JmpSwitchData> and index S0, which must be a valid index in the
779 | ProfileSwitchDest<handle,nCases>, ND, S(Int), NF
781 Profile a switch statement target.
783 | CheckSurpriseFlags, ND, S(FramePtr,StkPtr), B
785 Tests the implementation-specific surprise flags. If they're true, branches
786 to block B. This is done by comparing an evaluation stack pointer to the RDS
787 stackLimitAndSurprise word. Note that in a resumed, the frame pointer is not
788 pointing into the eval stack, so S0 should be a StkPtr in that case.
790 | HandleRequestSurprise, ND, NA, NF
792 Generate exceptions based on surprise flags on a per request basis.
793 Make sure CheckSurpriseFlags is true before calling HandleRequestSurprise.
795 | ReturnHook, ND, S(FramePtr) S(Cell), NF
797 Surprise flag hook for function returns.
799 | SuspendHookAwaitEF, ND, S(FramePtr) S(FramePtr) S(Obj), NF
801 Surprise flag hook for suspending eagerly executing async functions. The S0
802 frame was already teleported into S1. Decrefs S2 if it throws an exception.
804 | SuspendHookAwaitEG, ND, S(FramePtr) S(Obj), NF
806 Surprise flag hook for suspending eagerly executing async generators. The S0
807 frame has an associated AG, which is already linked to the newly constructed
808 AGWH in the blocked state. Decrefs S1 if it throws an exception.
810 | SuspendHookAwaitR, ND, S(FramePtr) S(Obj), NF
812 Surprise flag hook for suspending async functions and async generators resumed
813 at Await. The S0 frame has an associated AFWH/AGWH still in the running state,
814 S1 points to the child WH we are going to block on.
816 | SuspendHookCreateCont, ND, S(FramePtr) S(FramePtr) S(Obj), NF
818 Surprise flag hook for suspending generators and async generators during their
819 invocation. The S0 frame was already teleported into S1. Decrefs S2 if it
822 | SuspendHookYield, ND, S(FramePtr), NF
824 Surprise flag hook for suspending generators and async generators at Yield.
826 | Unreachable<AssertReason>, ND, NA, T
828 Indicates an unreachable code path. Any instructions that are post-dominated
829 by an Unreachable may be treated as unreachable by the optimizer, and the
830 behavior of a program that attempts to execute an Unreachable is undefined.
832 | EndBlock<AssertReason>, ND, NA, T
834 Halt execution, without implying anything about the reachability of
835 instructions preceding this. Intended for use in internal tests or other code
836 not meant to be executed.
838 | Jmp, ND, SVar(Top), B|T
840 Unconditional jump to block B. In the second form, the target block must
841 start with a DefLabel with the same number of destinations as Jmp's number of
842 sources. Jmp parallel-copies its sources to the DefLabel destinations.
844 | DefLabel, DMulti, NA, NF
846 DefLabel defines variables received from a previous Jmp. A DefLabel with zero
847 destinations is a no-op, and the predecessor blocks may not necessarily end
848 in Jmp. A DefLabel with one or more destinations may only be reached by a Jmp
849 instruction with the same number of sources. Ordinary branch instructions may
850 not pass values to a DefLabel.
852 | Select, DUnion(1,2), S(Bool,Int) S(Top) S(Top), NF
854 If S0 is true/non-zero, return S1, otherwise return S2.
859 | LdStk<T,offset>, DParam(Cell), S(StkPtr), NF
861 Loads from S0 at offset (in cells), and puts the value in D as type T.
863 | LdLoc<T,localId>, DParam(Cell), S(FramePtr), NF
865 Loads local slot localId from the frame S0 and puts the value in D as type T.
867 | LdLocForeign<T>, DParam(Cell), S(FramePtr) S(Int), NF
869 Loads local slot S1 from the frame S0 and puts the value in D as type T.
870 Note that it does not perform the local optimizations that LdLoc does.
871 Users of this opcode need to ensure that the local is not optimized away.
873 | LdStkAddr<offset>, D(PtrToStkCell), S(StkPtr), NF
875 Loads the address of the stack slot given by the pointer in S0 at the given
876 stack offset (measured in cells).
878 | LdLocAddr<localId>, D(PtrToFrameCell), S(FramePtr), NF
880 Loads the address of the local slot localId from the frame S0 into D.
882 | LdRDSAddr<T,RDSHandle>, DParam(PtrToCell), NA, NF
884 Load the address of a Cell that lives at the specified RDS handle. The type
885 param must be a subtype of PtrToCell.
887 | LdInitRDSAddr<T,RDSHandle>, DParam(PtrToInitCell), NA, B
889 Load the address of a Cell that lives at the specified RDS handle. Branch if
890 the value at that address is Uninit. The type param must be a subtype of
893 | LdPairElem, D(InitCell), S(Obj) S(Int), NF
895 Load the element at S1 out of the Pair collection at S0.
897 | LdMem<T>, DParam(Cell), S(MemToCell), NF
899 Loads from S0 and puts the value in D.
901 | LdTVFromRDS<T,RDSHandle,includeAux>, DParam(InitCell), NA, NF
903 Load the TypedValue from the specified RDS handle. Must load the aux bits if
904 `includeAux` is true.
906 | LdContField<T>, DParam(Cell), S(Obj) C(Int), NF
908 Loads a property from the object referenced by S0 at the offset given by S1
909 and puts the value in D. S0 must be a Generator.
911 | LdClsInitElem<idx>, D(Cell), S(PtrToClsInitCell), NF
913 Load the cell at index `idx` from the class init vector at S0 into D0.
915 | LdColVec, D(Vec), S(Obj), NF
917 Load the vec array backing a collection instance in S0, which must be a
918 Vector or ImmVector, and that specific object type must be known at compile
921 | LdColDict, D(Dict), S(Obj), NF
923 Load the dict array backing a collection instance in S0, which must be a
924 Map, Set, ImmMap, or ImmSet, and that specific object type must be known at
927 | LdIterBase<T,iterId>, DParam(ArrLike), S(FramePtr), LA
929 Load the base of the iterator with type `T` at `iterId`. `T` must be a valid,
930 DataTypeSpecific-or-better type for the iterator's base; for example, it may
931 be based on an earlier call to CheckIter.
933 | LdIterPos<T,iterId>, DParam(Int|PtrToElemCell), S(FramePtr), NF
935 | LdIterEnd<T,iterId>, DParam(Int|PtrToElemCell), S(FramePtr), NF
937 Load the specified field of the iterator at `iterId`. These ops should only
938 be generated for iterators known to have a specialized type (via CheckIter).
939 The type param `T` should be compatible with this type - i.e. `T` should be
940 either an int or a pointer based on whether it's an index or pointer iter.
942 | LdFrameThis, DParam(Obj), S(FramePtr), NF
944 Loads into D the value of m_this from S0.
946 | LdFrameCls, DParam(Cls), S(FramePtr), NF
948 Loads into D the value of m_cls from S0.
950 | LdClsCtor, D(Func), S(Cls) S(Cls|Nullptr), NF
952 Loads into D the constructor of class S0. If the constructor cannot be called
953 from the context S1, raise an error.
955 | LdSmashable, D(Smashable), NA, NF
957 Loads a smashable value. The initial value is set to (1 << addr) + 1, where
958 addr is a pointer pointing to the value in TC. The lowest bit is set for
959 convenience of checking whether the value was already smashed.
961 | LdSmashableFunc, D(Func), S(Smashable), NF
963 Loads into D the func pointer stored in the higher 32 bits of S0.
965 | DefConst<T>, DParam(Top), NA, NF
967 Define a constant value of type T. D is presumed to be globally available and
968 the DefConst instruction will not actually appear in the IR instruction
971 | Conjure<T>, DParam(Top), NA, NF
973 Define a value of type T. This instruction aborts at runtime; it is meant to
974 be used in tests or code that is known to be unreachable.
976 | ConjureUse, ND, S(Cell), NF
978 Define a "use" of S0 effectively keeping the value alive. As with Conjure it
979 should not appear in reachable code.
981 | LdCls, D(Cls), S(Str) C(Cls|Nullptr), NF
983 Loads the class named S0 in the context of the class S1. Invokes autoload and
984 may raise an error if the class is not defined. The explicit context
985 parameter allows the compiler to simplify this instruction to a DefConst in
986 some cases. If S0 is constant, this instruction may be simplified to a
989 | LdClsCached, D(Cls), CStr, NF
991 Loads the class named S0 via the RDS. Invokes autoload and may raise an error
992 if the class is not defined.
994 | LdClsCachedSafe, D(Cls), CStr, B
996 Loads the class whose name is S0 out of the RDS. If the class is not defined,
999 | LdClsInitData, D(PtrToClsInitCell), S(Cls), NF
1001 Loads the pointer to the property initializer array for class S0.
1003 | LookupClsRDS, D(Cls|Nullptr), S(Str), NF
1005 Lookup the cached-class RDS handle for a given class name. Dereference that
1006 handle and return the associated Class, or null if not present.
1008 | LdCns, D(InitCell), CStr, B
1010 Load the constant named S0, branching to B if isn't present.
1012 | LookupCnsE<T,constName>, D(InitCell), CStr, PRc
1014 Load a constant via the RDS. Raises a fatal error if it cannot define the
1015 constant. This should only be executed if LdCns on the same constant has
1018 | LdClsCns<className,constantName>, DParam(InitCell), NA, B
1020 Load the constant 'constantName' for the class 'className'. If not
1021 initialized, branch to B.
1023 | LookupClsCns, D(InitCell), S(Cls) S(Str), NF
1025 Lookup a class constant. May raise errors if either the class or constant are
1028 | LookupClsCtxCns, D(Int), S(Cls) S(Str), NF
1030 Lookup a class context constant. May raise errors if the context constant
1031 is not defined, is abstract or is a type/value constant.
1033 | LdSubClsCns<constantName,slot>, D(Uncounted), S(Cls), NF
1035 Load the constant 'constantName' for the class S0. The constant is known to
1036 be in the given slot. If the returned value is Uninit, the constant is not
1037 initialized and it must be loaded using InitSubClsCns. Counted constants will
1038 never have their slot be initialized and thus always take the slow path.
1040 | InitSubClsCns<constantName,slot>, D(InitCell), S(Cls), NF
1042 Slow path for LdSubClsCns. Used when LdSubClsCns indicates the slot is
1045 | CheckSubClsCns<constantName,slot>, ND, S(Cls), B
1047 Check that the constant 'constantName' lives in the given slot for the class
1048 S0, and branch if not. S0 must have at least slot+1 constants.
1050 | ProfileSubClsCns<constantName,handle>, D(Cell), S(Cls), NF
1052 Load the constant 'constantName' for the class S0, profiling the observed
1053 slots. If the returned value is Uninit, the constant does not exist or is
1054 abstract or is a type-constant.
1056 | LdClsCnsVecLen, D(Int), S(Cls), NF
1058 Load the size of S0's constant table.
1060 | LdResolvedTypeCns<slot>, D(StaticDict), S(Cls), B
1062 Loads the resolved type constant in the slot `slot' on S0 or branches to B if
1063 the type constant is not resolved.
1065 | LdResolvedTypeCnsNoCheck<slot>, D(StaticDict), S(Cls), NF
1067 Loads the resolved type constant in the slot `slot' on S0. The type constant
1068 is assumed to be present and resolved.
1070 | LdTypeCns, D(StaticDict), S(Cls) S(Str), NF
1072 Loads type constant with name S1 from class S0, performing any necessary
1073 resolution. Raises an error if no such constant could be found, if S0::S1 is
1074 not a type constant, if resolution fails, or if S0::S1 is abstract.
1076 | LdTypeCnsNoThrow, D(StaticDict), S(Cls) S(Str), NF
1078 Loads type constant with name S1 from class S0, performing any necessary
1079 resolution. If no such constant can be found, if S0::S1 is not a type
1080 constant, if resolution fails, or if S0::S1 is abstract, then a "fake"
1081 invalid type-structure is returned.
1083 | LdResolvedTypeCnsClsName<slot>, DTypeCnsClsName, S(Cls), NF
1085 Loads the cached 'classname' field from the resolved type constant in the
1086 slot `slot' on S0. If there is no cached field, returns nullptr.
1088 | LdTypeCnsClsName, D(StaticStr), S(Cls) S(Str), NF
1090 Loads and resolved type constant with name S1 from class S0, as if by
1091 LdTypeCns. Returns the 'classname' field from that type constant. Raises an
1092 error if the type constant loading fails, or if there is no 'classname' field
1095 | LdClsMethodFCacheFunc<clsName,methodName>, D(Func), NA, B
1097 Loads the target cache entry for a forwarding call to clsName::methodName.
1098 If the method does not exist, or the cache hasn't been filled yet, branch to
1101 | LookupClsMethodFCache<clsName,methodName>,
1102 | D(Func|Nullptr), C(Cls) S(FramePtr),
1105 Lookup clsName::methodName in the forwarding class method cache. S0 should be
1106 the Class named by clsName and S1 should be the current vm frame pointer. May
1107 return Nullptr if lookup fails using a subset of the required lookup paths,
1108 indicating that a more complete lookup path should be taken. May throw if the
1109 method does not exist.
1111 | LdClsMethodCacheFunc<clsName,methodName>, D(Func), NA, B
1113 Loads the target cache entry for the method clsName::methodName. If the
1114 method does not exist or the cache hasn't been filled yet, branch to B.
1116 | LdClsMethodCacheCls<clsName,methodName>, D(Cls), NA, NF
1118 Loads the target cache class context entry for a call to clsName::methodName
1119 from the current context. This instruction must only be used when the value
1120 is known to not be empty (i.e., LdClsMethodCacheFunc must have succeeded, or
1121 LookupClsMethodCache returned a non-null value).
1123 | LookupClsMethodCache<clsName,methodName>, D(Func|Nullptr), S(FramePtr), NF
1125 Lookup a function in the class method targetcache. The class name and method
1126 name are clsName and methodName, respectively. S0 is the current vm frame
1127 pointer. Returns Nullptr if the method cannot be found using a subset of the
1128 required lookup paths, indicating that a more complete lookup path should be
1129 taken. May throw if the method does not exist.
1131 | LdIfaceMethod<vtableIdx,methodIdx>, D(Func), S(Cls), NF
1133 Load the Func* at methodIdx from the vtable at vtableIdx in S0.
1135 If methodIdx represents an instance method, S0 must be a non-abstract class.
1136 This requirement is naturally satisfied if S0 comes from LdObjClass.
1138 | LdFuncVecLen, D(Int), S(Cls), NF
1140 Load the funcVecLen field from S0.
1142 | LdClsMethod, D(Func), S(Cls) C(Int), NF
1144 Load the Func* in slot S1 of the class method table for class S0. (Note that
1145 this vector is located before the class in memory, so the non-negative slots
1146 will map to negative offset loads.)
1148 | LookupClsMethod, D(Func|Nullptr), S(Cls) S(Str) S(Obj|Nullptr) S(Cls|Nullptr),
1151 Lookup a pointer to a class method for a given class S0 and method name S1,
1152 assuming caller's $this is S2 and caller is defined in a class S3. Throws or
1153 fatals if the method does not exist, is not accessible, or is not a static
1154 method. Returns nullptr if it is an instance method defined in S2's class
1155 hierarchy, indicating that this legacy call should be handled by interpreter.
1157 | LdPropAddr<T,index>, DParam(LvalToPropCell), S(Obj), NF
1159 Load the address of the object property at physical index `index`. T must be a
1160 subtype of PtrToPropInitCell.
1162 | LdInitPropAddr<T,index>, DParam(LvalToPropCell), S(Obj), B
1164 Load the address of the object property at physical index `index`. Branch if
1165 the value at that address is Uninit. T must be a subtype of PtrToPropInitCell.
1167 | LdGblAddr, D(LvalToGblCell|Nullptr), S(Str), NF
1169 Loads a pointer to a global with name S0, or a null lval if that global is
1170 not already defined.
1172 | LdGblAddrDef, D(LvalToGblCell), S(Str), NF
1174 Loads a pointer to a global with name S0, defining it to be InitNull if it
1175 is not already defined.
1177 | ProfileGlobal, ND, S(Str), NF
1179 Profile an (attempted) access of a global with name S0.
1181 | LdClsPropAddrOrNull<readonly op>, D(PtrToSPropCell|Nullptr), S(Cls) S(Str)
1182 | C(Cls|Nullptr) C(Bool) C(Bool), NF
1184 Loads a pointer to a static class property. S0 points to the class, S1 is the
1185 property name, and S2 is the class representing the context of the code
1186 accessing the property. If class S0 does not have a visible and accessible
1187 static property named S1, then nullptr is returned. An exception
1188 will be thrown if the property is marked LateInit and its value is
1189 Uninit, unless S3 is true. An exception is thrown if S4 is true,
1190 and the property is constant. An exception is also thrown if there is a
1191 readonly violation with the readonly op.
1193 | LdClsPropAddrOrRaise<readonly op>, D(PtrToSPropCell), S(Cls) S(Str)
1194 | C(Cls|Nullptr) C(Bool) C(Bool), NF
1196 Loads a pointer to a static class property. S0 points to the class, S1 is the
1197 property name, and S2 is the class representing the context of the code
1198 accessing the property. If class S0 does not have a visible and accessible
1199 static property named S1, then nullptr is returned. An exception
1200 will be thrown if the property is marked LateInit and its value is
1201 Uninit, unless S3 is true. An exception is thrown if S4 is true,
1202 and the property is constant. An exception is also thrown if there is a
1203 readonly violation with the readonly op.
1205 | LookupSPropSlot, D(Int), S(Cls) S(Str), NF
1207 Lookup the slot index of the static property with the name S1 on the class
1208 S0, returning -1 if not found.
1210 | LdObjMethodD, D(Func), S(Cls) S(Str), NF
1212 Loads a func pointer pointing to the instance method that would be called
1213 if a method named S1 is invoked on an instance of S0. Raises a fatal if the
1214 class does not have an accessible method with the given name.
1216 | LdObjMethodS<methodName>, D(Func), S(Cls) S(Smashable), NF
1218 Loads a func pointer pointing to the instance method that would be called
1219 if a `methodName` is invoked on an instance of S0. Caches the mapping in
1220 the TC cache (using S1) and target cache. Raises a fatal if the class does
1221 not have an accessible method with the given name.
1223 | LdObjInvoke, D(Func), S(Cls), B
1225 Try to load a cached non-static __invoke Func from the Class in S0, or branch
1226 to block B if it is not present.
1228 | LdObjClass, DLdObjCls, S(Obj), NF
1230 Load the class out of the object in S0 and put it in D.
1232 | LdClsName, D(StaticStr), S(Cls), NF
1234 Load the name of the Class* in S0.
1236 | LdLazyCls, D(LazyCls), S(Cls), NF
1238 Load a lazy class corresponding to the Class* in S0.
1240 | LdLazyClsName, D(StaticStr), S(LazyCls), NF
1242 Load the name of the LazyClass in S0.
1244 | LdFunc, D(Func|Nullptr), S(Str), NF
1246 Loads the Func whose name is S0, invoking autoloader if it is not defined yet.
1247 Fatals if the named function is not defined, and the autoloader fails to
1248 define it. Returns nullptr if S0 contained '::', indicating that this legacy
1249 call should be handled by interpreter.
1251 | LdFuncCached<funcName>, D(Func), NA, NF
1253 Loads the Func whose name is funcName from the RDS, invoking autoload if it
1254 not defined yet. Fatal if function autoloader fails to define it.
1256 | LookupFuncCached<funcName>, D(Func), NA, NF
1258 Loads the Func whose name is given from %1, invoking autoload if it is not
1259 defined yet. Fatal if the function autoload fails to define it. This
1260 instruction does not assume the loaded function will be called immediately,
1261 so it will raise a resolution failure error instead of a call failure error.
1263 | LdFuncNumParams, D(Int), S(Func), NF
1265 Returns the value of func->numParams().
1267 | LdFuncInOutBits, D(Int), S(Func), NF
1269 Loads the Func::m_inoutBits field.
1271 | LdARFunc, D(Func), S(FramePtr), NF
1273 Loads the result of ar->func() where ar is S0.
1274 Users of this opcode need to ensure that the writing of m_funcId to S0 is
1277 | LdFuncName, D(StaticStr), S(Func), NF
1279 Loads the full name of S0.
1281 | LdMethCallerName<isCls>, D(StaticStr), S(Func), NF
1283 Loads the meth_caller cls or func name.
1285 | LdFuncCls, D(Cls|Nullptr), S(Func), NF
1287 Loads the Class* of S0.
1289 | LdStrLen, D(Int), S(Str), NF
1291 Load the length of the string in S0.
1293 | FuncHasAttr<attr>, D(Bool), S(Func), NF
1295 Tests for Func::m_attrs & attr.
1297 | ClassHasAttr<attr>, D(Bool), S(Cls), NF
1299 Tests for Class::m_attrsCopy & attr.
1301 | LdFuncRequiredCoeffects, D(Int), S(Func), NF
1303 Returns the value of func->requiredCoeffects().
1305 | LdClsFromClsMeth, D(Cls), S(ClsMeth), NF
1307 Load the Class* of the ClsMethDataRef in S0.
1309 | LdFuncFromClsMeth, D(Func), S(ClsMeth), NF
1311 Load the Func* of the ClsMethDataRef in S0.
1313 | LdClsFromRClsMeth, D(Cls), S(RClsMeth), NF
1315 Load the Class* of the RClsMeth* in S0.
1317 | LdFuncFromRClsMeth, D(Func), S(RClsMeth), NF
1319 Load the Func* of the RClsMeth* in S0.
1321 | LdGenericsFromRClsMeth, D(Vec), S(RClsMeth), NF
1323 Load the ArrayData* containing the generics attached to the RClsMeth in S0
1325 | LdFuncFromRFunc, D(Func), S(RFunc), NF
1327 Load the Func* of the RFuncData in S0
1329 | LdGenericsFromRFunc, D(Vec), S(RFunc), NF
1331 Load the ArrayData* containing the generics attached to the RFuncData in S0
1335 | AllocObj, DAllocObj, S(Cls), PRc
1337 Allocates a new object of class S1.
1339 | AllocObjReified, DAllocObj, S(Cls) S(Vec), LA|PRc
1341 Allocates a new object of class S1 and sets S2 as the reified generics of
1342 this class. If this class is not reified, this instruction raises an error.
1344 | InitProps<class>, ND, NA, NF
1346 Calls the property initializer function (86pinit) for class. May throw.
1348 | InitSProps<class>, ND, NA, NF
1350 Calls the static property initializer functions (86sinit and/or 86linit)
1351 for class. May throw.
1353 | CheckRDSInitialized<RDSHandle>, ND, NA, B
1355 Check if the RDS entry at the specified handle is initialized, and branches
1358 | MarkRDSInitialized<RDSHandle>, ND, NA, NF
1360 Mark the given RDS entry as being initialized.
1362 | MarkRDSAccess<RDSHandle>, ND, NA, NF
1364 Mark the given RDS entry as being accessed for profiling.
1366 | PropTypeRedefineCheck, ND, C(Cls) C(Int), NF
1368 Check that the specified property at the slot S1 on S0, which redeclares a
1369 property in the parent, has a declared type equivalent to the parent
1372 | DebugBacktrace, D(Vec), S(Int), PRc
1374 Obtain stack trace by calling the debug_backtrace() method.
1376 | InitThrowableFileAndLine, ND, S(Obj), NF
1378 Initialize Throwable's file name and line number assuming the stack trace
1379 was already initialized and the current vmfp() is a built-in.
1381 | NewInstanceRaw<class>, DAllocObj, NA, PRc
1383 Allocates an instance of class.
1385 | InitObjProps<class>, ND, S(Obj), NF
1387 Initializes properties of object S0.
1389 | ConstructInstance<class>, DAllocObj, NA, PRc
1391 Call the custom instance constructor of an extension class.
1393 | ConstructClosure<class>, DAllocObj, S(Cls|Obj|Nullptr), CRc|PRc
1395 Call the custom instance constructor of a Closure.
1397 Store the context represented by S0 into the newly constructed closure object.
1398 S0 may be a Nullptr when there is no context (i.e. the closure is being used
1401 | LockObj, ND, S(Obj), NF
1403 Clear the IsBeingConstructed flag on the object.
1405 | NewLoggingArray, DLoggingArrLike, S(Vec,Dict,Keyset), PRc|CRc|LA
1407 Maybe create a LoggingArray wrapping the vanilla array-like S0. The decision
1408 may be based on flags or sampling. If we don't create an array, we return S0
1409 unchanged. The result will match S0 in type. For static array constructors
1410 (including property initial values), the result will be static.
1412 | ProfileArrLikeProps, ND, S(Obj), NF
1414 Maybe create LoggingArrays wrapping each of the vanilla array-likes in the
1415 properties of the newly-initialized object S0. The decision may be based on
1416 flags or sampling. This op mutates the object's props in place.
1418 | LogArrayReach<TransSrcKey>, ND, S(ArrLike), LA
1420 If the supplied array is a LoggingArray, log the current tracelet and SrcKey
1421 for use during specialization.
1423 | LogGuardFailure<T>, ND, S(ArrLike), LA
1425 Log that we failed to guard input S0 to the given type. Useful for catching
1426 performance bugs in bespoke layout selection, but may have more general use.
1428 | NewDictArray, D(Dict), C(Int), PRc
1430 Allocate a new dict with the expected capacity S0.
1432 | NewKeysetArray<offset,keys>, D(Keyset), S(StkPtr), PRc|CRc
1434 Allocate a new keyset containing N elements off the stack given by S0, at
1435 `offset'. This instruction moves the elements off the stack without
1436 manipulating their reference counts.
1438 | AllocVec<size>, D(Vec), NA, PRc
1440 Allocate a new uninitialized vector array with space for size elements in it.
1441 The array will be initialized with values using either InitVecElem or
1444 | InitVecElem<index>, ND, S(Vec) S(Cell), CRc
1446 Store the S1 into the slot at index in array S0. This instruction assumes
1447 that it doesn't have to incref the value being stored. Used to initialize an
1448 array allocated with AllocVec.
1450 | InitVecElemLoop<offset,size>, ND, S(Vec) S(StkPtr), CRc
1452 Move `size' elements from the stack given by S1, at `offset', into the array
1453 S0. Assumes that the first element on the stack is the last element in the
1454 array. Used to initialize an array allocated with or AllocVec that was too
1455 big for us to use a series of InitVecElem ops.
1457 | AllocStructDict<keys...>, D(Dict), NA, PRc
1459 Allocate a new key/value dict or mixed-layout array, given N string literal
1460 immediates for keys. This op initializes the header and hash table of the
1461 new array-like, but does not its elements; use InitDictElem for that.
1463 | InitDictElem<index,key>, ND, S(Dict) S(Cell), NF
1465 Initialize the element at position `index` in array S0 to have the string
1466 literal `key` as its key and S1 as its value. This instruction assumes that
1467 S1 has already been inc-reffed. Used with the result of AllocStructDict.
1469 | NewStructDict<offset,keys...>, D(Dict), S(StkPtr), PRc|CRc
1471 Allocate a new key/value dict, given N string literal immediates for keys
1472 and N stack elements at `offset` on stack S0 for values. This op assumes it
1473 can move values from the stack without inc-reffing them.
1475 | AllocBespokeStructDict<layout>, DStructDict, NA, PRc
1477 Allocate a new, empty dict with the bespoke StructLayout `layout`.
1479 | InitStructPositions<slots>, ND, SStructDict, NF
1481 Initialize the size and iterator positions of the bespoke StructDict S0 for
1482 the fields specified by `slots`. This instruction does not set the elements
1483 of the dict; use InitStructElem for that.
1485 | InitStructElem<slot,key>, ND, SStructDict S(InitCell), CRc
1487 Initialize the element at slot `slot` corresponding to `key` in StructDict S0
1488 with S1. This instruction assumes that S1 has already been inc-reffed.
1489 Used with the result of AllocUninitBespokeStructDict.
1491 | NewBespokeStructDict<offset,layout,slots...>, DStructDict, S(StkPtr), PRc|CRc
1493 Allocate a new dict with the bespoke StructLayout `layout`. Then, init the
1494 N fields with the given `slots` with N stack elements starting at `offset`.
1495 This op moves stack values with no refcounting.
1497 | NewCol<type>, DCol, NA, PRc
1499 Create an empty new collection of `type'. `type' cannot be Pair.
1501 | NewPair<offset>, DCol, S(Cell) S(Cell), PRc|CRc
1503 Allocate a new Pair and fill it with the given cells. Ownership of the cells
1504 is transferred from $1 and $2 to the pair without manipulating the refcounts.
1506 | NewColFromArray<type>, DCol, S(Vec,Dict), PRc|CRc
1508 Create a collection of `type` from a Vec or Dict kind. `type` cannot be
1509 Pair. S0 must be vec kind when `type` is Vector or ImmVector, and must be
1510 dict kind otherwise. Ownership of S0 is transferred from $1 to the
1511 collection, without manipulating the refcount.
1513 | Clone, DofS(0), S(Obj), PRc
1515 Allocate an object by cloning S0.
1517 | NewClsMeth, D(ClsMeth), S(Cls) S(Func), NF
1519 Allocate a new ClsMethDataRef.
1521 | NewRClsMeth, D(RClsMeth), S(Cls) S(Func) S(Vec), LA|PRc
1523 Allocate a new reified class method by storing the Class in S0,
1524 the Func in S1 and the reified generics in S2.
1526 | NewRFunc, D(RFunc), S(Func) S(Vec), LA|PRc
1528 Allocate a new reified function pointer given the Func pointer in S0
1529 and reified generics in S1.
1531 | FuncCred, DAllocObj, S(Func), PRc
1533 Allocate a new FunctionCredential
1537 | BeginInlining<func, offset>, D(FramePtr), S(StkPtr) S(FramePtr), NF
1539 Marks the start of an inlined function whose stack resides offset cells below
1542 Defines a new frame pointer for an ActRec at callBCOff for use in an inlined
1543 region. In resumed contexts the new frame is computed relative to S0 as S1 is
1544 not a stack location.
1546 | EndInlining, ND, S(FramePtr), NF
1548 Marks the end of an inlined function. S0 is no longer a valid frame location.
1550 | InlineCall<retSPOff>, ND, S(FramePtr) S(FramePtr), NF
1552 Sets the current vmfp for an inlined call to S0, and the m_sfp of S0 to the
1555 This instruction is primarily used to represent an inlined frame in the IR
1556 when it cannot be eliminated during a side-exit. It performs callee-side
1557 responsibilities for setting up an activation record (i.e. setting the return
1558 ip, m_func and m_callOff, storing the frame pointer into D).
1560 The caller frame pointer is passed as S1. This is used to keep track of the
1561 call chain of inlined functions for simplification and dead code elimination.
1563 | DefFuncEntryFP<func>,
1565 | S(FramePtr) S(StkPtr) S(Int) S(Cls|Obj|Nullptr),
1568 Writes a callee's frame and defines a frame pointer.
1570 `func': the function being called
1571 S0: frame pointer of the caller
1572 S1: stack pointer pointing to the space reserved for the callee's frame
1573 S2: call flags (see CallFlags)
1576 | Call<offset,numParams,callOff,destroyLocals>,
1578 | S(StkPtr) S(FramePtr) S(Func) S(Cls|Obj|Nullptr) S(Int),
1581 Transfer control to a callee S2, based on the pre-live activation record and
1582 set of args on the stack pointed to by S0 at `offset'. S1 is the current
1583 caller frame pointer. S3 is the context (nullptr, $this or static::class).
1584 S4 is the ambient coeffects.
1586 | NativeImpl<func>, ND, S(FramePtr) S(StkPtr), NF
1588 Execute a call to the native builtin specified by the current function. S0
1589 and S1 should be the current vmfp and vmsp, respectively.
1591 | CallBuiltin, DBuiltin, S(FramePtr) S(StkPtr) SVar(MemToCell,Cell,Nullptr), PRc
1593 Call builtin function with N arguments. S0 and S1 should be the current vmfp
1594 and vmsp, respectively.
1596 The source and destination types correspond to C++ parameter and return types
1599 C++ type HHIR type Position
1600 ----------------- --------- --------
1601 bool Bool source, destination
1602 int64_t Int source, destination
1603 double Dbl source, destination
1604 const String& PtrToStr source
1605 const Array& PtrToArr source
1606 const Object& PtrToObj source
1607 const Variant& PtrToCell source
1608 Variant& PtrToCell source (ref param)
1609 String {Str|InitNull} destination
1610 Array {Arr|InitNull} destination
1611 Object {Obj|InitNull} destination
1612 Variant {Cell-UninitNull} destination
1614 | RetCtrl<spOff,suspendingResumed>, ND, S(StkPtr) S(FramePtr) S(Cell), T
1616 Ensure that S0 + `spOff' (in cells) is stored in rvmsp and that S1's saved
1617 frame pointer is stored in rvmfp, then return to the saved return address in
1618 S1. The return value is S2, which is passed via the rret_*() registers to
1619 the caller. The `suspendingResumed' flag indicates when this instruction is
1620 suspending a resumable rather than performing a normal function return.
1622 | AsyncFuncRetPrefetch, ND, S(FramePtr), NF
1624 Prefetch the WaitHandle that the current (async, resume-mode) frame's AFWH
1625 is blocking. If this AFWH is blocking multiple WaitHandles, we will only
1626 prefetch the first one; in any case, this IR op has no visible semantics.
1628 | AsyncFuncRet<spOff>, ND, S(StkPtr) S(FramePtr) S(Cell), T
1630 Return from a resumed async function, assuming no surprise. Ensures that
1631 S0 + `spOff` (in cells) is stored in rvmsp and that S1 is stored in rvmfp,
1632 packs return value S2 into registers and calls the `asyncFuncRet` unique
1633 stub. The stub stores the result into the wait handle associated with the
1634 frame pointer, marks it as finished, unblocks its parents and if possible,
1635 directly resumes the first parent (fast path), or a pending fast runnable
1636 ResumableWaitHandle (slower path). Otherwise, it will exit VM and return
1637 control to the asio scheduler (slow path). The stack must contain exactly one
1638 cell containing uninitialized garbage, which will be populated by the stub
1639 either to pass the return value to the resumed function, or to return null
1642 | AsyncFuncRetSlow<spOff>, ND, S(StkPtr) S(FramePtr) S(Cell), T
1644 Return from a resumed async function, assuming unknown surprise flag state
1645 after the previous surprise was handled by executing "return" event hook.
1646 Calls the `asyncFuncRetSlow` stub, which re-checks the surprise flag and
1647 transfers control to the AsyncFuncRet if it was clear, or performs the slow
1648 path of AsyncFuncRet if it was not, without resuming another function, as
1649 we are not able to call a potential "resume await" event hook from the stub.
1651 | AsyncGenRetR<spOff>, ND, S(StkPtr) S(FramePtr), T
1653 Return from an async generator resumed at Await, assuming unknown surprise
1654 flag state. Ensures that S0 + `spOff` (in cells) is stored in rvmsp and that
1655 S1 is stored in rvmfp and calls the `asyncGenRetR` unique stub. The stub
1656 stores `null` result indicating end of iteration into the async generator
1657 wait handle associated with the generator associated with the frame pointer,
1658 marks the wait handle as finished and unblocks its parents. If the surprise
1659 flag was not set and there is a pending fast runnable ResumableWaitHandle,
1660 it resumes it directly (slow path). Otherwise, it will exit VM and return
1661 control to the asio scheduler (turtle path). The stack must contain exactly
1662 one cell containing uninitialized garbage, which will be populated by the
1663 stub either to pass the return value to the resumed function, or to return
1664 null to the scheduler.
1666 | AsyncGenYieldR<spOff>, ND, S(StkPtr) S(FramePtr) S(Cell) S(Cell), T
1668 Yield from an async generator resumed at Await, assuming unknown surprise
1669 flag state. Works the same as `AsyncGenRetR`, except the async generator
1670 wait handle is populated with `tuple($key, $value)` result of the iteration
1671 step, where `$key` is given by S2 and `$value` by S3.
1673 | AsyncSwitchFast<spOff>, ND, S(StkPtr) S(FramePtr), T
1675 Switch control to another ResumableWaitHandle. Ensures that S0 + `spOff`
1676 (in cells) is stored in rvmsp and that S1 is stored in rvmfp and calls the
1677 `asyncSwitchCtrl` unique stub, which tries to resume a pending fast runnable
1678 ResumableWaitHandle (fast path) if possible, otherwise it will exit VM and
1679 return control to the asio scheduler (slow path). As with AsyncRetFast, the
1680 stack must contain exactly one cell containing uninitialied garbage.
1682 | LdRetVal<T>, DParam(InitCell), S(FramePtr), NF
1684 Load the return value from the already-returned-from ActRec pointed to by S0
1685 into the dest. This is used by NativeImpl. TODO(#7150575): We want to make
1686 NativeImpl return a TypedValue in the C++ ABI registers.
1688 | GenericRetDecRefs, ND, S(FramePtr), NF
1690 Does decrefs of all the current function's locals, where S0 is a pointer to
1691 the relevant activation record. This instruction may not occur in an inlined
1696 | StClsInitElem<idx>, ND, S(PtrToClsInitCell) S(Cell), NF
1698 Store S1 into the slot at index `idx` in the class init vector at S0.
1700 | StMem, ND, S(MemToCell) S(Cell), NF
1702 Store S1 into the location pointed to by S0.
1704 | StTVInRDS<RDSHandle,includeAux>, ND, S(InitCell), NF
1706 Store the TypedValue in S0 into the specified RDS handle. Must store the aux
1707 bits if `includeAux` is true.
1709 | StImplicitContext, ND, S(Obj), NF
1711 Stores the implicit context from RDS to the WaitHandle in S0.
1713 | StLoc<localId>, ND, S(FramePtr) S(Cell), NF
1715 Store S1 to local number localId on the frame pointed to by S0.
1717 | StLocRange<localIds>, ND, S(FramePtr) S(Cell), NF
1719 Store S1 to the local variables corresponding to localIds, on the frame
1722 | StIterBase<iterId>, ND, S(FramePtr) S(ArrLike,Nullptr), LA
1724 Sets the base of the iterator at `iterId` to the pointer S1. The array must
1725 match the specialized type of the iterator, or be null (for local iterators).
1727 | StIterType<iterId,iterType>, ND, S(FramePtr), NF
1729 Sets the type of the iterator at `iterId` to `iterType`. This type must be a
1730 specialized type. Also sets auxiliary fields (like next helper index).
1732 | StIterPos<iterId>, ND, S(FramePtr) S(Int|PtrToElemCell), NF
1734 | StIterEnd<iterId>, ND, S(FramePtr) S(Int|PtrToElemCell), NF
1736 Store S1 to the given field of the iterator at `iterId`. S1 must be an int if
1737 we're doing index iteration and a pointer if we're doing pointer iteration.
1739 | StStk<offset>, ND, S(StkPtr) S(Cell), NF
1741 Store S1 to the stack pointed to by S0, at a given offset (in cells).
1743 | StStkRange<offsets>, ND, S(StkPtr) S(Cell), NF
1745 Store S1 to the stack slots at the given offsets from S0.
1747 | StOutValue<index>, ND, S(FramePtr) S(Cell), NF
1749 Store S1 in a caller allocated out-value vm stack cell index cells above
1752 | LdOutAddr<index>, D(PtrToOtherCell), S(FramePtr), NF
1754 Load the address of the storage for out parameter `index` provided by the
1755 callee (the address will be a location on the callee stack).
1757 | LdOutAddrInlined<index>, D(PtrToStkCell), S(FramePtr), NF
1759 Load the address of the storage for out parameter `index`. For an inlined
1760 frame, this is an address on the caller's stack.
1762 | RecordReifiedGenericsAndGetTSList, D(Vec), S(Vec), CRc|LA
1764 Takes a varray of reified generics from the stack and adds them to the reified
1765 generics table and returns the input varray of reified generics, possibly
1768 | StFrameCtx, ND, S(FramePtr) S(Obj,Cls), NF
1770 Store object or class S1 on frame S0.
1772 | StFrameFunc<func>, ND, S(FramePtr), NF
1774 Store the func in m_funcId/m_func for S0.
1776 | StFrameMeta<callBCOff,flags>, ND, S(FramePtr), NF
1778 Store the m_callOffAndFlags field of S0.
1782 | StVMFP, ND, S(FramePtr), NF
1784 | StVMSP, ND, S(StkPtr), NF
1786 | StVMPC, ND, C(Int), NF
1788 | StVMReturnAddr, ND, C(Int), NF
1790 | StVMRegState, ND, C(Int), NF
1792 Sets the VM register state to the specified state. This is used
1793 to track whether the register state is clean or dirty as
1794 EagerSyncVMRegs is moved around by store elimination.
1796 | ReqBindJmp<target,invSPOff,irSPOff>, ND, S(StkPtr) S(FramePtr), T
1798 Emit a jump to a translation starting at `target'. If it does not exist, jump
1799 to a service request that will translate the code and bind this jump to it.
1801 | ReqRetranslate<irSPOff>, ND, S(StkPtr) S(FramePtr), T
1803 Emit a jump to a service request that will chain to a retranslation of this
1806 This instruction is used in exit traces for a type prediction that occurs at
1807 the first bytecode offset of a tracelet.
1809 | ReqRetranslateOpt<irSPOff>, ND, S(StkPtr) S(FramePtr), T
1811 Emit a service request to retranslate the current function with a higher
1812 optimization gear. This instruction is used in exit traces that trigger
1813 profile-guided optimizations.
1815 | ReqInterpBBNoTranslate<target,invSPOff,irSPOff>, ND, S(StkPtr) S(FramePtr), T
1817 Jump to the `interpHelperNoTranslate' stub, which first interprets the basic
1818 block starting at `target' and then continues interpreting basic blocks until
1819 an already existing translation is found.
1822 11. Refcounting and copies
1824 | Mov, DofS(0), S(Top), P
1826 Defines D as S0. May imply register-to-register moves at code generation
1827 time. Does not imply an incref or any other manipulation of S0.
1829 | IncRef, ND, S(Cell), NF
1831 If S0 is a refcounted type, increment its refcount.
1833 | DecRef<locId>, ND, S(Cell), CRc
1835 Decrease the reference count of S0 by one, and call a destructor for types
1836 that require it if it goes to zero.
1838 The locId is just a hint to the runtime indicating which local variable is
1839 being DecRef'd, if any.
1841 | DecRefNZ<locId>, ND, S(Cell), CRc
1843 Decrease the reference count of S0 by one, do not check if it goes to zero.
1844 This instruction can be used for more efficient code when it is provable that
1845 the reference count cannot go to zero.
1847 | ProfileDecRef<locId>, ND, S(Cell), NF
1849 Update the DecRefProfile for the given input as if it were dec-ref-ed, but do
1850 not actually dec-ref it. We can use this op for e.g. iterator output locals,
1851 because we don't specialize iterators in profiling translations.
1856 | DefFP<offset>, D(FramePtr), NA, NF
1858 Creates a temporary D representing the current VM frame pointer.
1860 If the offset is specified, the frame is located at that offset from the SP,
1861 otherwise the frame either lives on the heap, or its position on the stack
1864 | DefFrameRelSP<irSPOff, bcSPOff>, D(StkPtr), S(FramePtr), NF
1866 | DefRegSP<irSPOff, bcSPOff>, D(StkPtr), NA, NF
1868 Defines a stack positioned relative to the frame or the rvmsp register.
1870 Creates a temporary D representing the current VM stack pointer:
1871 - DefFrameRelSP: D points to the same location as the frame pointer S0
1872 - DefRegSP: D is the memory address given by the rvmsp register
1874 The logical stack starts at the stack base and its position and size is
1875 defined by these values:
1876 - `irSPOff' is the offset from the stack base to D
1877 - `bcSPOff' is the offset from the stack base to the top of the stack
1879 DefFrameRelSP is used at the beginning of translations of non-resumed
1880 functions to represent the state of the stack on entry.
1882 DegRegSP is used at the beginning of translations of prologues and
1883 resumed functions to represent the state of the stack on entry.
1885 In prologues, the stack base represents a stack without any func arguments,
1886 i.e. it is pointing to the empty space reserved for an ActRec.
1888 In resumables, the stack base represents an empty VM stack.
1890 | LoadBCSP<irSPOff>, D(StkPtr), S(StkPtr), NF
1892 Gets the bytecode stack pointer from IR stack pointer, for use in eager
1895 | DefCallFlags, D(Int), NA, NF
1897 | DefCallFunc, D(Func), NA, NF
1899 | DefCallNumArgs, D(Int), NA, NF
1901 | DefCallCtx, DParam(Cls|Obj), NA, NF
1903 Creates a temporary D representing flags, function pointer, number of
1904 arguments, or context passed to the prologue.
1906 May be used only at the beginning of a prologue or a stub used in a prologue
1909 | Count, D(Int), S(Cell), NF
1911 Computes the number of elements in S0. The count of an array is the number of
1912 elements it contains, without recursing into containers in the array.
1913 Subtypes of Bool|Int|Dbl|Str|Res have a count of 1, subtypes of Null have a
1914 count of 0. The count of objects that implement the Countable interface is
1915 computed by returning the value of their count method. Objects that do not
1916 implement Countable have a count of 1.
1918 | CountVec, D(Int), S(Vec), LA
1920 | CountDict, D(Int), S(Dict), LA
1922 | CountKeyset, D(Int), S(Keyset), LA
1924 | CountCollection, D(Int), S(Obj), NF
1926 Computes the number of elements in S0 using the same definition as Count,
1927 but with a restriction on the input type that allows for optimizations.
1931 Does nothing. It's sometimes useful for the simplifier to insert one of these
1932 in the instruction stream.
1934 | JmpPlaceholder, ND, NA, B
1936 Does nothing if executed. Semantically, this instruction carries a taken edge
1937 to a block of speculatively-generated code during initial IR generation, such
1938 as specialized code for an iterator init or next which we may or may not use.
1939 If it survives irgen, it should be eliminated in the first DCE pass.
1941 | CheckFuncNeedsCoverage<Func>, ND, NA, B
1943 Checks if Func needs to have coverage information recorded for the current
1946 | RecordFuncCall<Func>, ND, NA, NF
1948 Records a call to Func for a function call based code coverage report.
1950 | SetImplicitContextByIndex, D(Int), S(Int), NF
1952 Sets the implicit context to S0 index on the g_context->m_implicitContexts
1953 table and returns the index of the previous implicit context.
1954 If S0 is equal to ImplicitContext::kEmptyIndex, implicit context is set to
1959 | VerifyParamCls<func,param,tc>, ND, S(Obj) S(Cls) S(Cls|Nullptr), NF
1961 Verify parameter type for classes or traits. If S1 does not extend (if S2 is
1962 a class) or implement (if S2 is an interface) S2, this instruction will raise
1963 a recoverable fatal error describing the type mismatch.
1965 | VerifyParamCallable<func,param>, ND, S(Cell), NF
1967 If S0 is not callable, as defined by the php function is_callable, this
1968 instruction will raise a recoverable fatal error describing the type
1971 | VerifyParamFail<func,param,tc>, DVerifyParamFail, S(Cell) S(Cls|Nullptr), NF
1973 Assumes that parameter specified in extra-data in the current function
1974 has failed a its type check. Depending on the typehint being verified and
1975 a number of runtime options, may coerce the parameter to the correct type i
1976 or raise a recoverable fatal error describing the type mismatch.
1978 | VerifyParamFailHard<func,param,tc>, ND, S(Cell) S(Cls|Nullptr), T
1980 A terminal version of VerifyParamFail, to be used when the compiler can
1981 statically prove that this failure will result in a fatal error rather than a
1984 | VerifyRetCallable<func,param>, ND, S(Cell), NF
1986 Verify a return type hint.
1988 | VerifyRetCls<func,param,tc>, ND, S(Obj) S(Cls) S(Cls|Nullptr), NF
1990 Verify a return type hint for a class.
1992 | VerifyRetFail<func,param,tc>, DVerifyParamFail, S(Cell) S(Cls|Nullptr), NF
1994 Failure to verify a return type hint.
1996 | VerifyRetFailHard<func,param,tc>, ND, S(Cell) S(Cls|Nullptr), T
1998 Terminal version of VerifyRetFail, to be used when the compiler can prove
1999 that this failure will result in a fatal error.
2001 | VerifyPropCls, ND, S(Cls) S(Int) S(Cls|Nullptr) S(Obj) C(Bool), NF
2003 Verify a property type hint with AnnotType::Object against an object
2004 value. S0 is the class of the object containing the property. S1 is the slot
2005 of the property on the class. S3 is the object which is being set in the
2006 property. If S2 is not nullptr, than the type-hint refers to that Class, and
2007 S3 will be checked to see if its an instance of S2. Otherwise, the type-hint
2008 refers to a type-alias, and the alias will be resolved and checked against
2009 S3. S4 is true if this is a static property, false otherwise.
2011 | VerifyPropFail, ND, S(Cls) S(Int) S(Cell) C(Bool), NF
2013 Failure to verify a property type hint. S0 is the class of the object
2014 containing the property. S1 is the slot of the property on the class. S2 is
2015 the value which was being set in the property. S3 is true if this is a static
2016 property, false otherwise.
2018 | VerifyPropFailHard, ND, S(Cls) S(Int) S(Cell) C(Bool), T
2020 Terminal version of VerifyPropFail, to be used when the compiler can prove
2021 that this failure will result in a fatal error.
2023 | VerifyProp, ND, S(Cls) S(Int) S(Cell) C(Bool), NF
2025 Verify that S2 is compatible with the type hint for the property at slot S1
2026 on S0. S3 is true if this is a static property, false otherwise.
2028 | VerifyPropAll, ND, S(Cls) S(Int) S(Cell) C(Bool), NF
2030 Verify that S2 is compatible with the all type hints for the property at slot
2031 S1 on S0 including upper-bounds. S3 is true if this is a static property,
2034 | VerifyPropCoerce, D(InitCell), S(Cls) S(Int) S(Cell) C(Bool), PRc|CRc
2036 Verify that S2 is compatible with the type hint for the property at slot S1
2037 on S0. S3 is true if this is a static property, false otherwise. Once support
2038 for coercing class_meth types is removed this ir instruction can also be
2039 removed (T61738946).
2041 | VerifyPropCoerceAll, D(InitCell), S(Cls) S(Int) S(Cell) C(Bool), PRc|CRc
2043 Verify that S2 is compatible with all type hints for the property at slot S1
2044 on S0, including upper-bounds. S3 is true if this is a static property,
2045 false otherwise. Once support for coercing class_meth types is removed this
2046 ir instruction can also be removed (T61738946).
2048 | VerifyReifiedLocalType<func,paramId>, ND, S(Cell) S(Dict) S(Cls|Nullptr), LA
2050 Raises a catchable type hint error if the reified generics of function
2051 parameter id does not match the type structure given on S0.
2053 | VerifyReifiedReturnType<func>, ND, S(Cell) S(Dict) S(Cls|Nullptr), LA
2055 Raises a catchable type hint error if the reified generics of S0 does not
2056 match the type structure given on S1.
2058 | ThrowUninitLoc<localId>, ND, S(Str), T
2060 Throws an UndefinedVariableException on an uninitialized local variable.
2062 | ThrowUndefPropException, ND, S(Obj) CStr, T
2064 Throws an UndefinedPropertyException on an undefined property named S1 on the
2067 | RaiseTooManyArg<func>, ND, S(Vec), CRc|LA
2069 Raise a too many argument warning because extra arguments stored in S0 were
2070 passed to function func.
2072 | RaiseError, ND, S(Str), T
2074 Raises a fatal error with the text in S0 as its message.
2076 | RaiseWarning, ND, S(Str), NF
2078 Raises a warning with the text in S0 as its message.
2080 | RaiseNotice, ND, S(Str), NF
2082 Raises a notice with the text in S0 as its message.
2084 | ThrowHasThisNeedStatic, ND, S(Func), T
2086 Throws a BadMethodCallException to indicate that func was called on an object
2087 but is a static method.
2089 | ThrowMissingArg<func,argc>, ND, NA, T
2091 Throws a RuntimeExceptionObject to indicate that only argc arguments were
2092 passed to function func.
2094 | ThrowMissingThis, ND, S(Func), T
2096 Throws a BadMethodCallException to indicate that an instance method was called
2099 | ThrowCallReifiedFunctionWithoutGenerics, ND, S(Func), T
2101 Throws a BadMethodCallException to indicate that S0 was called without reified
2104 | CheckInOutMismatch<numArgs, inoutArgs>, ND, S(Func), NF
2106 | ThrowInOutMismatch<numArgs, inoutArgs>, ND, S(Func), T
2108 Throw an exception if the inout-ness of passed arguments given by `inoutArgs'
2109 does not match the inout-ness of parameters of the callee S0. There must be
2110 a mismatch if ThrowInOutMismatch is used.
2112 These don't verify that if there are packed args they are not in a position
2113 that require inout. You will still need verify that when unpacking.
2115 | CheckReadonlyMismatch<numArgs, readonlyArgs>, ND, S(Func), NF
2117 Checks whether readonly-ness of the caller matches that of callees
2119 | ThrowReadonlyMismatch<numArgs, readonlyArgs>, ND, S(Func), NF
2121 Throw an exception if the readonly-ness of passed arguments given by `readonlyArgs'
2122 does not match the readonly-ness of parameters of the callee S0. There must be
2123 a mismatch if ThrowReadonlyMismatch is used.
2125 These don't verify that packed args are not in a position that require
2126 readonly. You will still need verify that when unpacking.
2128 | RaiseForbiddenDynCall, ND, S(Func), NF
2130 Depending on the setting of `ForbidDynamicCallsToFunc`,
2131 `ForbidDynamicCallsToClsMeth` and `ForbidDynamicCallsToInstMeth` runtime
2132 options, either raise a warning or throw an exception indicating that the
2133 func specified in S0 was called dynamically (and should not be).
2135 | RaiseForbiddenDynConstruct, ND, S(Cls), NF
2137 Depending on the setting of the `ForbidDynamicConstructs` runtime option, either
2138 raise a warning or throw an exception indicating that the class specified in
2139 S0 was constructed dynamically (and should not be).
2141 | RaiseCoeffectsCallViolation<func>, ND, S(Int) S(Int), NF
2143 Depending on the setting of the `CoeffectEnforcementLevels` runtime option,
2144 either raise a warning or throw an exception indicating that the caller
2145 was violating coeffects enforcement when calling the callee
2146 specified by func. S0 is used to pass the coeffects provided by the caller.
2147 S1 is used to pass the required coeffects of the callee.
2149 | RaiseCoeffectsFunParamTypeViolation<paramIdx>, ND, S(Cell), NF
2151 Raises a warning to indicate a violation for the expected type for S0
2152 at position paramIdx for the coeffect rule FunParam.
2154 | RaiseCoeffectsFunParamCoeffectRulesViolation, ND, S(Func), NF
2156 Raises a warning to indicate a violation for the input S0 to coeffect rule
2157 FunParam uses polymorphic coeffect rules.
2159 | RaiseStrToClassNotice, ND, S(Str), NF
2161 Raise a notice if a string is implicitly converted to a class.
2163 | CheckClsMethFunc, ND, S(Func), NF
2165 Raises runtime errors if the func in S0 is not a callable static method.
2167 | CheckClsReifiedGenericMismatch<cls>, ND, S(Vec), LA
2169 Raises a runtime error unless whether each generic in S0 is reified or erased
2170 matches exactly to the expectations of the cls.
2172 | CheckFunReifiedGenericMismatch, ND, S(Func) S(Vec), LA
2174 Raises a runtime error unless whether each generic in S0 is reified or erased
2175 matches exactly to the expectations of the func.
2177 | IsFunReifiedGenericsMatched<func>, D(Bool), S(Int), NF
2179 Load the generics bitmap from call flags given by S0 and check whether the
2180 bitmap proves that the number of given generics and positions of reified vs
2181 erased generics matches the expectations of the callee `func' (which must use
2182 reified generics). If this opcode returned false, further checks implemented
2183 by CheckFunReifiedGenericMismatch are needed.
2185 | InitClsCns<className,constName>, DParam(InitCell), NA, NF
2187 Initialize the RDS entry for a constant for a class, invoking autoload if it
2188 is not defined. The initialized value is returned. This instruction may raise
2189 an undefined constant error if autoload cannot define the constant.
2191 | PrintStr, ND, S(Str), CRc
2193 | PrintInt, ND, S(Int), CRc
2195 | PrintBool, ND, S(Bool), CRc
2197 Print for various types.
2199 | ConcatIntStr, D(Str), S(Int) S(Str), PRc
2201 Concatenate S0 and S1 after converting S0 to String.
2203 | ConcatStrInt, D(Str), S(Str) S(Int), CRc|PRc
2205 Concatenate S0 and S1 after converting S1 to String.
2207 | ConcatStrStr, D(Str), S(Str) S(Str), CRc|PRc
2209 Concatenate S0 and S1.
2211 | ConcatStr3, D(Str), S(Str) S(Str) S(Str), CRc|PRc
2213 Concatenate S0, S1, and S2.
2215 | ConcatStr4, D(Str), S(Str) S(Str) S(Str) S(Str), CRc|PRc
2217 Concatenate S0, S1, S2, and S3.
2219 | AddNewElemKeyset, D(Keyset), S(Keyset) S(InitCell), CRc|PRc
2221 | AddNewElemVec, DModified(0), S(Vec) S(InitCell), CRc|PRc
2223 Add S1 as a new element to the array/keyset/vec S0. (Note: S1 must actually
2224 be a subtype of InitCell for array invariants, but we can't assert this yet
2225 in the IR because many eval stack slots are not entirely typed wrt initness
2228 | AKExistsDict, D(Bool), S(Dict) S(Int,Str), NF
2230 Has the effects of array_key_exists(S0, S1).
2232 | AKExistsKeyset, D(Bool), S(Keyset) S(Int,Str), NF
2234 Has the effects of array_key_exists(S0, S1).
2236 | AKExistsObj, D(Bool), S(Obj) S(Int,Str), NF
2238 Has the effects of array_key_exists(S0, S1) on an object S0. This does
2239 collection accesses.
2241 | GetMemoKey, DMemoKey, S(Cell), PRc
2243 Given a cell, produces a string or an int that can be used as a memoize cache
2244 key. Valid values for the input include all basic types, arrays and
2245 collections, and objects that implement IMemoizeParam. Any other type will
2246 cause GetMemoKey to throw. This op can only be used within functions marked
2247 as memoize wrappers.
2249 | GetMemoKeyScalar, DMemoKey, S(Uncounted,Str), PRc
2251 Identical to GetMemoKey but only accepts scalar types and cannot produce
2254 | DictIdx<sizeHint>, DDictElem, S(Dict) S(Int,Str) S(Cell), NF
2256 Checks if S0 contains the key S1 and returns the result if found. Otherwise
2257 S2 is returned. The optimization data `sizeHint` doesn't affect semantics.
2258 (`sizeHint` describes S0; it's one of {Default, SmallStatic}. Default is a
2259 hash lookup. For SmallStatic, we'll do a linear scan for static string keys.)
2261 | KeysetIdx, DKeysetElem, S(Keyset) S(Int,Str) S(Cell), NF
2263 Checks if S0 contains the key S1 and returns the result if found. Otherwise
2266 | MethodExists, D(Bool), S(Cls) S(Str), NF
2268 Checks if the method named S1 exists on class S0. S0 must be a normal class
2269 that is not abstract.
2271 | LdBindAddr<SrcKey,spOff>, D(TCA), NA, NF
2273 Creates a service request to bind the given target address. Returns a TCA
2274 pointing either to the service request (before the service request is
2275 satisfied) or to the native code for the given target address (once the
2276 service request is satisfied).
2278 | LdSSwitchDest<numCases, cases, defaultOffset, bcSPOff>, D(TCA), S(Str), NF
2280 Using the cases in the extra data, create a hash table for destination lookup.
2281 Then, lookup the destination for the switched value in the table and yield the
2282 default if not present.
2284 | InterpOne<T,spOff,bcOff,numPopped,numPushed>, ND,
2285 | S(StkPtr) S(FramePtr),
2288 Call the interpreter implementation function for one opcode. S0 + `spOff' (in
2289 cells) and S1 are, respectively, the VM stack and frame pointers before this
2290 instruction. T is only present if the instruction pushes to the stack, in
2291 which case it is the type of the top stack element after the call. `bcOff' is
2292 the bytecode offset. `numPopped' is the number of stack cells consumed by the
2293 instruction, and `numPushed' is the number of stack cells produced by the
2296 | InterpOneCF<T,bcOff,numPopped,numPushed>, ND,
2297 | S(StkPtr) S(FramePtr),
2300 Similar to InterpOne, but for instructions that may modify vmpc. This is
2301 implemented as a tail call to a stub, so any exceptions thrown will be thrown
2302 in the context of the stub, not the InterpOneCF instruction.
2304 | OODeclExists<kind>, D(Bool), S(Str) S(Bool), NF
2306 Returns a bool indicating whether the class, interface, or trait named by S0
2307 exists. Invokes autoload if S1 is true.
2309 | SetOpTV<op>, ND, S(LvalToCell) S(Cell), NF
2311 Performs S0 <op>= S1.
2313 | OutlineSetOp<op>, D(InitCell), S(Cell) S(Cell), NF
2315 Similar to SetOpTV, but does not write back the result to S0, instead it is
2316 returned as the dest. This is useful to handle ops that may require a
2317 type check before writing the value back.
2319 | GetTime, D(Dbl), NA, NF
2321 Returns a double of the current time in seconds.
2323 | GetTimeNs, D(Int), C(Int), NF
2325 Returns the current time of the given clock id specified as clockid_t in
2326 nanoseconds as integer. This will call kernel's clock_gettime_ns() API. Note
2327 that this cannot be used for CLOCK_THREAD_CPUTIME_ID, as HHVM provides
2328 different semantics for that counter.
2330 | LdUnitPerRequestFilepath<handle>, D(StaticStr), NA, NF
2332 Returns the filepath currently bound to the current unit (stored in the given
2333 RDS handle). The RDS handle must be an initialized normal handle. Only valid
2334 when Eval.ReuseUnitsByHash is enabled.
2336 | DirFromFilepath, D(StaticStr), S(StaticStr), NF
2338 Given a string representing a filepath in S0, return only the directory
2339 portion of the path.
2341 14. Generators & Closures
2343 | LdClosureCls, DParam(Cls), S(Obj), NF
2345 | LdClosureThis, DParam(Obj), S(Obj), NF
2347 Load the context from the closure object S0 into D, assuming `func' is
2350 | StClosureArg<index>, ND, S(Obj) S(Cell), CRc
2352 Store one of the closure environment arguments (i.e. from the closure's use
2353 clause) from S1 into the closure object S0.
2355 | CreateGen, DAllocObj, S(FramePtr) C(Int) S(TCA,Nullptr) C(Int), PRc
2357 Create a Generator object and suspend the ActRec provided by S0 into its
2358 embedded ActRec, allocating S1 slots for locals/iterators. Set the native
2359 resume address to S2 and resume offset to S3.
2361 | CreateAGen, DAllocObj, S(FramePtr) C(Int) S(TCA,Nullptr) C(Int), PRc
2363 Create an AsyncGenerator object and suspend the ActRec provided by S0 into its
2364 embedded ActRec, allocating S1 slots for locals/iterators. Set the native
2365 resume address to S2 and resume offset to S3.
2367 | CreateAFWH, DAllocObj,
2368 | S(FramePtr) C(Int) S(TCA,Nullptr) C(Int) S(Obj),
2371 Create an AsyncFunctionWaitHandle object and suspend the ActRec provided by
2372 S0 into its embedded ActRec, allocating S1 slots for locals/iterators. Set
2373 the native resume address to S2, resume offset to S3, and mark it blocked on
2374 non-finished child S4.
2376 | CreateAGWH, DAllocObj,
2377 | S(FramePtr) S(TCA,Nullptr) C(Int) S(Obj),
2380 Create an AsyncGeneratorWaitHandle object and link it to the AsyncGenerator
2381 associated with the ActRec provided by S0. Set the native resume address
2382 to S1, resume offset to S2, and mark it blocked on non-finished child S3.
2384 | CreateAAWH<local,count>, DAllocObj, S(FramePtr) S(Int), PRc
2386 Create an AwaitAllWaitHandle and add the count elements from frame contiguous
2387 frame locals beginning at local and extending count locals. S1 denotes the
2388 total number of non-completed waithandles. All locals must be subclasses of
2391 | CreateSSWH, DAllocObj, S(Cell), CRc|PRc
2393 Call c_StaticWaitHandle::CreateSucceeded.
2395 | AFWHPrepareChild, ND, S(FramePtr) S(Obj), NF
2397 Prepare unfinished WaitableWaitHandle object specified by S1 for getting
2398 awaited by an AsyncFunctionWaitHandle object specified by its ActRec
2401 Injects S1 into the currently running scheduler instance and performs
2402 cross-scheduler and intra-scheduler cycle detection. Throws if the
2403 dependency cannot be established.
2405 | AFWHPushTailFrame, ND, S(Obj) C(Int), B
2407 If S0 is eligible for the tail frame optimization and has any free tail
2408 frame ID slots, pushes S1 as a new tail frame ID. Otherwise, branches to B.
2409 This IR op assumes that S0 is an Awaitable in the blocked state.
2411 S0 is eligible for the optimization if it is an AsyncFunctionWaitHandle,
2412 if this site "owns" it (i.e. if it has a refcount of exactly 2 - this site
2413 and its child's back pointer), and if it has space in its tail-frames list.
2415 | StArResumeAddr<offset>, ND, S(FramePtr) S(TCA), NF
2417 Store the resume address S1 into the Resumable whose ActRec is given by S0,
2418 marking the offset to resume at as `offset'.
2420 | ContEnter<spOffset,callBCOffset>,
2422 | S(StkPtr) S(FramePtr) S(FramePtr) S(TCA) S(Cell),
2425 Enters a generator body. S0 + `spOffset' (in cells) is a pointer to the
2426 stack, S1 is the current frame pointer, S2 is the generator frame pointer
2427 embedded in the Generator object, S3 is the address to jump to, and S4 is
2428 the value that will be pushed onto the stack to send it to the output of
2429 the yield statement. The `callBCOffset' will be stored to the m_callOff
2430 field of the ActRec in the generator.
2432 | ContCheckNext, ND, S(Obj) C(Bool), B
2434 Check whether the generator S0 can be iterated. If the generator is already
2435 running or finished, or it was not started yet and the S1 check-started flag
2436 is set, the branch B is taken.
2438 | ContValid, D(Bool), S(Obj), NF
2440 Return true if a generator is not done, false otherwise.
2442 | ContArIncKey, ND, S(FramePtr), NF
2444 Special-case key update for generator, ActRec of which is S0, which
2445 increments the key of a generator if that generator's key is an Int.
2446 This will cause undefined behavior if the generator's key is not an Int.
2448 | ContArIncIdx, D(Int), S(FramePtr), NF
2450 Increment the internal index in the Generator in S0, and return the new index
2453 | ContArUpdateIdx, ND, S(FramePtr) S(Int), NF
2455 Updates the internal index of generator with S1 if necessary, i.e. if S1
2456 is larger than the index. S0 is the pointer to the embedded ActRec.
2458 | LdContActRec, D(FramePtr), S(Obj), NF
2460 Loads the Generator object's ActRec, given a pointer to the generator
2463 | LdContResumeAddr, D(TCA|Nullptr), S(Obj), NF
2465 Load the resume addr from the Generator in S0.
2467 | StContArState<state>, ND, S(FramePtr), NF
2469 Change the state of the Generator object which has frame pointer S0.
2471 | LdContArValue, DParam(InitCell), S(FramePtr), PRc
2473 Loads 'value' from the Generator object ActRec of which is S0.
2475 | StContArValue, ND, S(FramePtr) S(InitCell), CRc
2477 Stores 'value' into the Generator object ActRec of which is S0. S1 is the
2480 | LdContArKey, DParam(InitCell), S(FramePtr), PRc
2482 Loads 'key' from the Generator object ActRec of which is S0.
2484 | StContArKey, ND, S(FramePtr) S(InitCell), CRc
2486 Stores 'key' into the Generator object ActRec of which is S0. S1 is the
2489 | AFWHBlockOn, ND, S(FramePtr) S(Obj), CRc
2491 Establish dependency between parent AsyncFunctionWaitHandle object, whose
2492 ActRec is given by S0, and child WaitableWaitHandle object referenced by S1.
2494 | LdWHState, D(Int), S(Obj), NF
2496 Loads the state of the WaitHandle in S0, which is a value from the wait
2497 handle states in ext_asio.h. This instruction has undefined behavior if S0 is
2500 | LdWHResult, DParam(InitCell), S(Obj), NF
2502 Loads the result of the WaitHandle in S0. This instruction has undefined
2503 behavior if S0 is not a WaitHandle, or if S0 is not finished.
2505 | LdWHNotDone, D(Int), S(Obj), NF
2507 Returns 1 if S0 is not finished, and 0 if S0 is finished.
2509 | CountWHNotDone<local,count>, D(Int), S(FramePtr), B
2511 Returns the number of unfinished awaitables contained in the contiguous
2512 locals beginning at local and extending count, skipping all nulls. A branch
2513 is taken if a non-Awaitable non-null value is encountered.
2515 | LdAFWHActRec, D(FramePtr), S(Obj), NF
2517 Loads the AsyncFunctionWaitHandle object's ActRec, given a pointer to the
2518 AsyncFunctionWaitHandle object in S0.
2521 15. Debugging, instrumentation, and profiling
2523 | IncStat, ND, C(Int), NF
2525 Increment stat counter. S0 is the implementation defined stat counter index.
2527 | IncProfCounter<TransID>, ND, NA, NF
2529 Increment the profiling counter associated with translation TransID.
2531 | IncCallCounter, ND, S(FramePtr), NF
2533 Increment the counter associated associated with the last call, namely from
2534 the function containing the previous translation in the call stack into the
2537 | DbgAssertRefCount<AssertReason>, ND, S(Cell), NF
2539 Assert that S0 has a valid refcount. If S0 has a reference counted type and
2540 its count is implausible then execute a hardware trap instruction.
2542 | DbgTraceCall<spOffset>, ND, S(FramePtr) S(StkPtr), NF
2544 When EvalHHIRGenerateAsserts is on, this instruction is inserted at the
2545 start of each region, to emit some sanity checking code.
2547 | DbgAssertFunc, ND, S(FramePtr), NF
2549 Assert that the func on the srckey is the current function in Frame S0.
2550 If the assertion fails, execution is aborted via a hardware exception.
2552 | DbgCheckLocalsDecRefd, ND, S(FramePtr), NF
2554 In debug builds, if LocalsDecRefd flag is set on S0, causes runtime failure by
2555 emitting a trap instruction. Otherwise, this instruction does nothing.
2557 | DbgTrashStk<offset>, ND, S(StkPtr), NF
2559 For debugging purposes. Store kTVTrashJITStk to the stack slot pointed to
2560 by S0, at a given offset (in cells).
2562 | DbgTrashFrame<offset>, ND, S(StkPtr), NF
2564 For debugging purposes. Store kTVTrashJITFrame to kNumActRecCells stack
2565 slots starting at the offset (in cells), and going toward higher memory
2568 | DbgTrashMem, ND, S(MemToCell), NF
2570 For debugging purposes. Store kTVTrashJITHeap to a heap slot pointed to by
2573 | RBTraceEntry, ND, NA, NF
2575 | RBTraceMsg, ND, NA, NF
2577 Ring buffer tracing.
2579 | ZeroErrorLevel, D(Int), NA, NF
2581 | RestoreErrorLevel, ND, S(Int), NF
2583 Helper instructions for fast implementation of the PHP error silencing
2589 | IterInit<IterData>, D(Bool), S(ArrLike,Obj) S(FramePtr), CRc|LA
2591 | IterInitK<IterData>, D(Bool), S(ArrLike,Obj) S(FramePtr), CRc|LA
2593 | LIterInit<IterData>, D(Bool), S(ArrLike) S(FramePtr), LA
2595 | LIterInitK<IterData>, D(Bool), S(ArrLike) S(FramePtr), LA
2597 <IterData> consists of three indices, iterId, keyId and valId. iterId is
2598 the index of the iterator variable, keyId and valId are indices of local
2601 Initializes the iterator variable whose index is given by iterId.
2602 This instruction creates the appropriate iterator for the array or object that
2603 S0 references, and rewinds the new iterator to its start. S0 points to the
2604 stack frame containing the iterator and local variables with the indices
2605 iterId, keyId and valId.
2607 If the new iterator is at its end (i.e., has no elements to iterate over),
2608 this instruction decrements the refcount of S0 and returns false; otheriwse,
2609 it stores a reference to S0 in the new iterator and returns true. If the
2610 iterator is not at its end, then this instruction stores the iterator's first
2611 value (and key) into the local variable with index valId (and keyId,
2614 The LIter variations only accept arrays and do not take ownership of their
2615 base. Instead, the base is provided on each operation on the iterator, so
2616 that we can avoid inc-ref-ing the base (in cases where that's safe).
2618 This instruction has the ConsumesRC property because it either decrements the
2619 reference count of S0 or stores a reference to S0 into the new iterator.
2621 | IterNext<IterData>, D(Bool), S(FramePtr), NF
2623 | IterNextK<IterData>, D(Bool), S(FramePtr), NF
2625 | LIterNext<IterData>, D(Bool), S(ArrLike) S(FramePtr), LA
2627 | LIterNextK<IterData>, D(Bool), S(ArrLike) S(FramePtr), LA
2629 <IterData> consists of three indices, iterId, keyId and valId. iterId is
2630 the index of the iterator variable, keyId and valId are indices of local
2631 variables. S0 points to the stack frame containing the iterator and local
2632 variables with the indices iterId, keyId and valId.
2634 Advances the iterator variable whose index is given by iterId.
2636 If the iterator has reached the end, this instruction frees the iterator
2637 variable and returns false; otherwise, it returns true. If the iterator has
2638 not reached its end, then this instruction stores the iterator's next value
2639 (and key) into the local variable with index valId (and keyId, respectively).
2641 | IterFree<iterId>, ND, S(FramePtr), NF
2643 Free the iterator variable with id `iterId` in the stack frame of S0.
2644 For non-local iterators, this instruction will dec-ref the stored base.
2646 | KillIter<iterId>, ND, S(FramePtr), NF
2648 Mark the iterator at `iterId` as no longer containing a meaningful value.
2649 We can use this operation to elide stores for iterator fields that do not
2650 get loaded again. In debug builds, it will write poison values to the fields.
2652 | GetDictPtrIter, DPtrIter, S(Dict) S(Int), NF
2654 Returns a pointer to the elm S1 of a mixed-layout array S0. S1 does not need
2655 to be a valid array position; for example, it may equal the size of the array
2656 (so that the "elm" returned is the pointer-iteration end for S0).
2658 | AdvanceDictPtrIter<offset>, DPtrIter, S(PtrToElemCell), NF
2660 Increments the pointer S0 to the array element with the given layout `offset`
2661 positions forward. `offset` is allowed to be negative.
2663 | LdPtrIterKey<T>, DParam(Int|Str), S(PtrToElemCell), NF
2665 | LdPtrIterVal<T>, DPtrIterVal, S(PtrToElemCell), NF
2667 Loads the key or val from the array element pointed to by S0. S0 must be a
2668 valid elm; that is, it can't point to the end of the array data. LdPtrIterKey
2669 can only be used for mixed elms, but LdPtrIterVal supports mixed and packed.
2671 T must be a valid type for the array's keys - i.e., a subtype of TInt|TStr.
2672 For LdPtrIterKey, T is used to type the result; if it's specific enough, we
2673 skip doing a check on the type of the elm. For LdPtrIterVal, it's only used
2674 to constrain the memory effects of the op.
2676 | EqPtrIter, D(Bool), S(PtrToElemCell) S(PtrToElemCell), NF
2678 Compares two pointer iterators for equality.
2681 17. Member instruction support
2683 | LdMIStateAddr, D(PtrToMISCell), C(Int), NF
2685 Load an MInstrState address. Returns a pointer to offset S0 within the
2686 current MInstrState.
2688 | LdMBase, DParam(LvalToCell), NA, NF
2690 Load the current value of the member base register.
2692 | StMBase, ND, S(LvalToCell), NF
2694 Store a new value to the member base register. It is illegal for any
2695 instruction other than StMBase or InterpOne (when interpreting a member
2696 instruction) to modify the member base register.
2698 | LdMROProp, D(Bool), NA, NF
2700 Load the current value of the roProp field of MInstrState
2702 | StMROProp, ND, S(Bool), NF
2704 Set the roProp field of MInstrState to S0.
2706 | FinishMemberOp, ND, NA, NF
2708 Mark the end of a member operation. This has no effect at runtime but exists
2709 to provide information for certain optimizations.
2711 All of the remaining opcodes in this section are simple wrappers around helper
2712 functions (specified in S0) to perform the corresponding vector operation. If
2713 S1 is a ConstCls it represents the context class for the operation.
2715 SetElem, SetProp, and SetNewElem are used to implement part of the SetM hhbc
2716 opcode, which almost always pushes its first stack input or a StaticStr as its
2717 stack result. The combinations of input types that cause SetM to push anything
2718 other than those two values are vanishingly rare in correct PHP programs, so
2719 these three instructions have been optimized for the common cases. SetNewElem
2720 and SetProp have no destination, allowing the compiler to predict that the
2721 SetM's output will be the same as its input (and optimize accordingly). If that
2722 turns out to not be the case at runtime, the instruction will throw an
2723 InvalidSetMException. The exception will hold a Cell containing the value the
2724 SetM should push on the stack instead of its input value. The runtime is
2725 responsible for catching this exception, finishing execution of the SetM
2726 instruction, pushing the value from the exception on the stack, and proceeding
2727 as appropriate (most likely with a side exit to the next bytecode instruction,
2728 since it has pushed an unexpected type onto the stack).
2730 SetElem is similar to SetProp and SetNewElem but can also be used for setting
2731 characters within strings. When given a string base and a valid offset, SetElem
2732 returns a string representation of the newly inserted character. In all other
2733 cases it returns nullptr or throws an InvalidSetMException. It will throw this
2734 exception when it detects invalid input types, or when trying to set a string
2735 offset that would grow the string beyond the maximum supported size.
2737 The input types that will cause the errors described above are listed here:
2739 SetNewElem will fail if the base is not a subtype of {Null|Str|Arr|Obj} and not
2741 SetElem has the same base constraint as SetNewElem. In addition, the key must
2742 not be a subtype of {Arr|Obj}.
2743 SetProp will fail if the base is not a subtype of {Obj|Null}.
2745 Any instructions that take a pointer to an MInstrState struct use the various
2746 fields of that struct for holding intermediate values.
2748 | BaseG, D(LvalToMembCell), S(Str), NF
2750 Get a base from global named S0. If it is not a defining BaseG it can also
2751 return the init_null_variant, so for now it returns a PtrToMembCell.
2753 | PropX, D(LvalToMembCell), S(Obj,LvalToCell) S(Cell) S(PtrToMISCell), NF
2755 Lookup intermediate property in S0, with key S1. An exception is thrown if
2756 the property is Readonly when it was required to be Mutable.
2758 | PropQ, D(LvalToMembCell), S(Obj,LvalToCell) S(StaticStr) S(PtrToMISCell), NF
2760 A nullsafe version of PropX, returns null if the base S0 is null. An exception
2761 is thrown if the property is Readonly when it was required to be Mutable.
2763 | PropDX, D(LvalToMembCell), S(Obj,LvalToCell) S(Cell) S(PtrToMISCell), MProp
2765 Like PropX, but used for intermediate element lookups that may modify the
2766 base. An exception is thrown if the property is Readonly when it was
2767 required to be Mutable.
2769 | CGetProp, D(InitCell), S(Obj,LvalToCell) S(Cell), PRc
2771 Get property with key S1 from S0.
2773 | CGetPropQ, D(InitCell), S(Obj,LvalToCell) S(StaticStr), PRc
2775 A nullsafe version of CGetProp, returns null if the base S0 is null.
2777 | SetProp, ND, S(Obj,LvalToCell) S(Cell) S(Cell), MProp
2779 Set property with key S1 in S0 to S2.
2781 | UnsetProp, ND, S(Obj,LvalToCell) S(Cell), NF
2783 Unset an object property.
2785 | SetOpProp<op>, D(InitCell), S(Obj,LvalToCell) S(Cell) S(Cell), MProp|PRc
2787 Set op propery with key S1 in base S0, using S2 as the right hand side.
2789 | IncDecProp<op>, D(InitCell), S(Obj,LvalToCell) S(Cell), MProp|PRc
2791 Increment/decrement property with key S1 in base S0.
2793 | IssetProp, D(Bool), S(Obj,LvalToCell) S(Cell), NF
2795 Returns true iff the property with key S1 in base S0 is set.
2797 | ElemX, D(InitCell), S(LvalToCell) S(Cell), NF
2799 Get intermediate element with key S1 from base S0. The base will not be
2800 modified and the result will not be inc-ref-ed.
2802 | CheckDictKeys<T>, ND, S(Dict), B
2804 Check that the given mixed array is free of tombstones and that all of its
2805 elements' keys match the type T. If any check fails, branch to block B.
2806 Like CheckMixedArrayOffset, this check is allowed to have false negatives -
2807 it may fail even if the array has keys of the given type.
2809 | CheckArrayCOW, ND, S(ArrLike), B|LA
2811 Check that S0 has a refcount of exactly 1; if not, branch to B.
2813 | ProfileDictAccess, ND, S(Dict) S(Int,Str), NF
2815 Profile access of the element keyed by S1 in S0, tracking sizes and offsets.
2817 | CheckDictOffset<pos>, ND, S(Dict) S(Int,Str), B
2819 Check that `pos' is within the usage bounds of S0 (including tombstones), and
2820 that S1 exactly matches the element key of S0 at `pos'. If any of the checks
2821 fail, branch to B. This check is allowed to have false negatives.
2823 | ProfileKeysetAccess, ND, S(Keyset) S(Int,Str), NF
2825 Profile access of the element keyed by S1 in S0, tracking sizes and offsets.
2827 | CheckKeysetOffset<pos>, ND, S(Keyset) S(Int,Str), B
2829 Check that `pos' is within the usage bounds of S0 (including tombstones), and
2830 that S1 exactly matches the element key of S0 at `pos'. If any of the checks
2831 fail, branch to B. This check is allowed to have false negatives.
2833 | CheckMissingKeyInArrLike, ND, S(ArrLike) S(StaticStr), B
2835 Uses the StrKeyTable to check if S1 is guaranteed to be missing in S0.
2836 If S1 may be present, branches to block B. If we branch here, the key may or
2839 | ElemVecD, D(LvalToElemInitCell), S(LvalToVec) S(Int), MElem
2841 | ElemVecU, D(LvalToMembInitCell), S(LvalToVec) S(Int), MElem
2843 Similar to ElemX, but the base S0 is a vec and the key S1 is an int. ElemVecD
2844 is for Define member instrs and ElemVecU is for Unset. (Other variations can
2845 be implemented without special IR instructions).
2847 | ElemDictD, D(LvalToElemInitCell), S(LvalToDict) S(Int,Str), MElem
2849 | ElemDictU, D(LvalToMembInitCell), S(LvalToDict) S(Int,Str), MElem
2851 Similar to ElemDX and ElemUX, but specialized for when the base S0 is a
2852 dict and the key S1 is an int/str.
2854 | ElemDictK, D(LvalToElemInitCell), S(Dict) S(Int,Str) S(Int), NF
2856 Returns an lval to the element of dict S0 at the known position S2 in S1.
2858 | ElemKeysetU, D(LvalToMembInitCell), S(LvalToKeyset) S(Int,Str), MElem
2860 Similar to ElemUX, but specialized for when the base S0 is a keyset and the
2861 key S1 is an int/str. Keysets do not support the define syntax.
2863 | ElemKeysetK, D(LvalToElemInitCell), S(Keyset) S(Int,Str) S(Int), NF
2865 Returns an lval to the element of keyset S0 at the known position S2 in S1.
2867 | ElemDX, D(LvalToMembCell), S(LvalToCell) S(Cell), MElem
2869 Like ElemX, but used for intermediate element lookups that may modify the
2872 | ElemUX, D(LvalToMembCell), S(LvalToCell) S(Cell), MElem
2874 Like ElemX, but used for intermediate element lookups that may modify the
2875 base as part of an unset operation.
2877 | DictGet, DDictElem, S(Dict) S(Int,Str), NF
2879 Get element with key S1 from base S0, throwing if the element is not present.
2881 | DictGetQuiet, DDictElem, S(Dict) S(Int,Str), NF
2883 Get element with key S1 from base S0, returning null if the element is not
2886 | DictGetK, DDictElem, S(Dict) S(Int,Str) S(Int), NF
2888 Like DictGet, but the element for S1 is at a known position S2 in S0.
2890 | KeysetGet, DKeysetElem, S(Keyset) S(Int,Str), NF
2892 Get element with key S1 from base S0, throwing if the element is not present.
2894 | KeysetGetQuiet, DKeysetElem, S(Keyset) S(Int,Str), NF
2896 Get element with key S1 from base S0, returning null if the element is not
2899 | KeysetGetK, DKeysetElem, S(Keyset) S(Int,Str) S(Int), NF
2901 Like KeysetGet, but the element for S1 is at a known position S2 in S0.
2903 | StringGet, D(StaticStr), S(Str) S(Int), PRc
2905 Get string representing character at position S1 from base string S0. Raises
2906 a notice if the position is out of bounds.
2908 | MapGet, D(InitCell), S(Obj) S(Int,Str), PRc
2910 Get element with key S1 from base S0.
2912 | CGetElem, D(InitCell), S(LvalToCell) S(Cell), PRc
2914 Get element with key S1 from S0.
2916 | MemoGetStaticValue<func,T>, DParam(InitCell), NA, B
2918 Get the memo value associated with the static function "func". If the value
2919 is not present, branch. The returned value is not inc-reffed. This op can
2920 only be used inside a memoize wrapper.
2922 | MemoGetStaticCache<func,keys,T>, DParam(InitCell), S(FramePtr), B
2924 Perform a lookup on the memo cache associated with the static function
2925 "func". The keys for the lookup are read from the locals on the frame pointed
2926 to by S0 (which must be ints or strings). If the lookup fails, branch. The
2927 returned value is not inc-reffed. This op can only be used inside a memoize
2930 | MemoGetLSBValue<func,T>, DParam(InitCell), S(Cls), B
2932 Get the memo value associated with the static function "func" and late static
2933 bound class S0. If the value is not present, branch. The returned value is not
2934 inc-reffed. This op can only be used inside a memoize wrapper.
2936 | MemoGetLSBCache<func,keys,T>, DParam(InitCell), S(FramePtr) S(Cls), B
2938 Perform a lookup on the memo cache associated with the static function
2939 "func" and late static bound class S1. The keys for the lookup are read from
2940 the locals on the frame pointed to by S0 (which must be ints or strings). If
2941 the lookup fails, branch. The returned value is not inc-reffed. This op can
2942 only be used inside a memoize wrapper.
2944 | MemoGetInstanceValue<slot,func,T>, DParam(InitCell), S(Obj), B
2946 Get the memo value at the specified memo slot on S0. If the value is not
2947 present, branch. The returned value is not inc-reffed. This op can only be
2948 used inside a memoize wrapper.
2950 | MemoGetInstanceCache<func,keys,T>, DParam(InitCell), S(FramePtr) S(Obj), B
2952 Perform a lookup on the memo cache at the specified memo slot on S1. The keys
2953 for the lookup are read from the locals on the frame pointed to by S0 (which
2954 must be ints or strings). If the lookup fails, branch. The returned value is
2955 not inc-reffed. This op can only be used inside a memoize wrapper.
2957 | MemoSetStaticValue<func>, ND, S(InitCell), NF
2959 Set S0 as the memo value associated with the static function "func". Store
2960 the value, overwriting any previous value, with appropriate ref-count
2961 manipulations. This op can only be used inside a memoize wrapper.
2963 | MemoSetStaticCache<func,keys>, ND, S(FramePtr) S(InitCell), NF
2965 Store S1 in the memo cache associated with the static function "func". The
2966 keys for the lookup are read from the locals on the frame pointed to be S0
2967 (which must be ints or strings). Store the value, overwriting any previous
2968 value, with appropriate ref-count manipulations. This op can only be used
2969 inside a memoize wrapper.
2971 | MemoSetLSBValue<func>, ND, S(InitCell) S(Cls), NF
2973 Set S0 as the memo value associated with the static function "func" and
2974 late static bound class S1. Store the value, overwriting any previous
2975 value, with appropriate ref-count manipulations. This op can only be used
2976 inside a memoize wrapper.
2978 | MemoSetLSBCache<func,keys>, ND, S(FramePtr) S(Cls) S(InitCell), NF
2980 Store S2 in the memo cache associated with the static function "func" and
2981 late static bound class S1. The keys for the lookup are read from the
2982 locals on the frame pointed to be S0 (which must be ints or strings).
2983 Store the value, overwriting any previous value, with appropriate
2984 ref-count manipulations. This op can only be used inside a memoize wrapper.
2986 | MemoSetInstanceValue<slot,func>, ND, S(Obj) S(InitCell), NF
2988 Set S2 as the memo value at the specified memo slot on S1. Store the value,
2989 overwriting any previous value, with appropriate ref-count
2990 manipulations. This op can only be used inside a memoize wrapper.
2992 | MemoSetInstanceCache<slot,func,keys>, ND, S(FramePtr) S(Obj) S(InitCell), NF
2994 Store S2 in the memo cache at the specified memo slot on S1. Store the value,
2995 overwriting any previous value, with appropriate ref-count
2996 manipulations. This op can only be used inside a memoize wrapper.
2998 | InitObjMemoSlots<class>, ND, S(Obj), NF
3000 Initialize the memoization instance slots for object S0 of the given class.
3002 | VecSet, DModified(0), S(Vec) S(Int) S(InitCell), PRc|CRc
3004 Set element with key S1 in S0 to S2. The dest will be a new Vec that should
3005 replace S0; this op produces a ref on the test and consumes one on S0.
3007 | DictSet, DModified(0), S(Dict) S(Int,Str) S(InitCell), PRc|CRc
3009 Set element with key S1 in S0 to S2. The dest will be a new Dict that should
3012 | BespokeGet, DBespokeElemUninit, S(Vec,Dict,Keyset) S(Int,Str), LA
3014 Get element with key S1 in the array S0, which may have an arbitrary layout.
3015 This op returns TUninit if the key is not in the array.
3017 | BespokeGetThrow, DBespokeElem, S(Vec,Dict,Keyset) S(Int,Str), LA
3019 Get element with key S1 in the array S0, which may have an arbitrary layout.
3020 This op throws if the key is not in the array.
3022 | BespokeElem, DBespokeElemLval, S(LvalToArrLike) S(Int,Str) C(Bool), LA|MElem
3024 Get a half-lval to an element of type T with key S1 in the array S0, which
3025 may have an arbitrary layout. The op will copy or escalate the S0 as needed,
3026 with ElemInt/ElemStr semantics.
3028 If the key is missing in the array, we'll use S2 to determine what to do.
3029 If S2 is true, we'll throw; else, we'll return an immutable lval to null.
3031 | BespokeSet, DArrLikeSet, S(Vec,Dict,Keyset) S(Int,Str) S(InitCell), LA|PRc|CRc
3033 Set element with key S1 in the array S0, which may have an arbitrary layout.
3034 This op has SetMove semantics; it consumes a refcount on the input array and
3035 produces one on the output, and does no refcounting to the value S2.
3037 | BespokeUnset, DArrLikeUnset, S(Vec,Dict,Keyset) S(Int,Str), LA|PRc|CRc
3039 Unset element with key S1 in the array S0, which may have an arbitrary layout.
3041 | BespokeAppend, DArrLikeAppend, S(Vec,Dict,Keyset) S(InitCell), LA|PRc|CRc
3043 Set element with key S1 in the array S0, which may have an arbitrary layout.
3044 This op has AppendMove semantics; it consumes a refcount on the input array
3045 and produces one on the output, and does no refcounting to the value S2.
3047 | BespokeIterFirstPos, D(Int), S(ArrLike), LA
3049 Obtain the pos coresponding to the first valid element in the non-empty
3050 array S0, which may have an arbitrary layout.
3052 | BespokeIterLastPos, D(Int), S(ArrLike), LA
3054 Obtain the pos coresponding to the last valid element in the non-empty
3055 array S0, which may have an arbitrary layout.
3057 | BespokeIterEnd, D(Int), S(ArrLike), LA
3059 Returns the "end" iterator position for the given array. Unlike the "last"
3060 iterator position, the end is never a valid iterator position.
3062 | BespokeIterGetKey, DBespokePosKey, S(ArrLike) S(Int), LA
3064 Obtain the key at the valid pos S1 in the array S0.
3066 | BespokeIterGetVal, DBespokePosVal, S(ArrLike) S(Int), LA
3068 Obtain the value at the valid pos S1 in the array S0.
3070 | BespokeEscalateToVanilla<Layout>, DEscalateToVanilla, SBespokeArr CStr, PRc
3072 Escalate the bespoke array S0 to a vanilla array for the reason S1.
3074 | LdMonotypeDictTombstones, D(Int), SMonotypeDict, NF
3076 Returns the number of tombstones in the given MonotypeDict's value array.
3077 The MonotypeDict's IterEnd is equal to its size plus its tombstone count.
3079 | LdMonotypeDictKey, DBespokePosKey, SMonotypeDict S(Int), NF
3081 | LdMonotypeDictVal, DBespokePosVal, SMonotypeDict S(Int), NF
3083 Specializations of BespokeIterGetKey and BespokeIterGetVal for when the base
3084 is a monotype dict. The GetKey and GetVal ops require that S1 is a valid
3085 iterator position for S0.
3087 | LdMonotypeVecElem, DBespokeElem, SMonotypeVec S(Int), NF
3089 Loads the element of the monotype vec in S0 at offset S1. This instruction
3090 assumes that the vec actually contains an element at that offset (i.e. the
3091 index is within bounds).
3093 | LdStructDictElem, DBespokeElemUninit, SStructDict C(StaticStr), NF
3095 Loads the element of the StructDict in S0 at the constant string key S1.
3097 | StructDictSet, DArrLikeSet, SStructDict C(StaticStr) S(InitCell), PRc|CRc
3099 Set element with key S1 in the struct-layout dict S0 to the value S2.
3100 This op has SetMove semantics; it consumes a refcount on the input array
3101 and produces one on the output, and does no refcounting to the value S2.
3103 | StructDictUnset, DArrLikeUnset, SStructDict C(StaticStr), PRc|CRc
3105 Unset element with key S1 in the struct-layout dict S0. This op has move
3106 semantics: it consumes a refcount on S0 and produces one on the output.
3108 | StructDictGetWithColor, DBespokeElemUninit, SStructDict S(Str), NF
3110 Loads the element of the StructDict in S0 at the string key S1. If S1 is
3111 static at runtime, the StructDict perfect hash table will be used. Otherwise,
3112 we use the standard accessor method. This is only valid to use after the
3113 bespoke hierarcy is finalized.
3115 | MapSet, ND, S(Obj) S(Int,Str) S(InitCell), CRc
3117 Set element with key S1 in S0 to S2.
3119 | VectorSet, ND, S(Obj) S(Int,Str) S(InitCell), CRc
3121 Set element with key S1 in S0 to S2.
3123 | SetElem, DSetElem, S(LvalToCell) S(Cell) S(InitCell), MElem
3125 Set element with key S1 in S0 to S2. SetElem returns a Nullptr in the common
3126 case, where the logical result of the hhbc SetM is its right hand side. In
3127 the case of string bases, the SetM returns a new string containing the newly
3128 inserted character. So the return value of this instruction is Nullptr unless
3129 SetM needed to return a static string.
3131 Furthermore, in the case of "invalid offsets", SetElem may throw an
3132 InvalidSetMException (see discussion above).
3134 | SetRange, ND, S(LvalToCell) S(Int) S(Cell) S(Int) S(Int), MElem
3136 | SetRangeRev, ND, S(LvalToCell) S(Int) S(Cell) S(Int) S(Int), MElem
3138 Perform a range set or reverse range set operation, with the same arguments
3139 and semantics as the RangeSet bytecode instruction.
3141 | UnsetElem, ND, S(LvalToCell) S(Cell), MElem
3143 Unsets the element at key S1 in the base S0.
3145 | SetOpElem<op>, D(InitCell), S(LvalToCell) S(Cell) S(Cell), MElem|PRc
3147 Set op elem with key S1 in base S0, using S2 as the right hand side.
3149 | IncDecElem, D(InitCell), S(LvalToCell) S(Cell), MElem|PRc
3151 Increment/decrement element with key S1 in base S0.
3153 | SetNewElem, ND, S(LvalToCell) S(InitCell), MElem
3155 Append the value in S1 to S0.
3157 | SetNewElemDict, ND, S(LvalToDict) S(InitCell), MElem
3159 | SetNewElemVec, ND, S(LvalToVec) S(InitCell), MElem
3161 | SetNewElemKeyset, ND, S(LvalToKeyset) S(Int,Str), MElem
3163 Specializations of SetNewElem for pointers to dicts, vecs, and keysets.
3165 | DictIsset, D(Bool), S(Dict) S(Int,Str), NF
3167 Returns true iff the element at key S1 in the base S0 is set.
3169 | KeysetIsset, D(Bool), S(Keyset) S(Int,Str), NF
3171 Returns true iff the element at key S1 in the base S0 is set.
3173 | StringIsset, D(Bool), S(Str) S(Int), NF
3175 Returns true iff the string S0 has a character at position S1.
3177 | VectorIsset, D(Bool), S(Obj) S(Int), NF
3179 Returns true iff the element at key S1 in the base S0 is set.
3181 | PairIsset, D(Bool), S(Obj) S(Int), NF
3183 Returns true iff the element at key S1 in the base S0 is set.
3185 | MapIsset, D(Bool), S(Obj) S(Int,Str), NF
3187 Returns true iff the element at key S1 in the base S0 is set.
3189 | IssetElem, D(Bool), S(LvalToCell) S(Cell), NF
3191 Returns true iff the element at key S1 in S0 is set.
3193 | CheckRange, D(Bool), S(Int) S(Int), NF
3195 Returns true iff S0 is in the range [0, S1).
3197 | ThrowArrayIndexException, ND, S(ArrLike) S(Int), T
3199 Throws an OutOfBoundsException if S0 is an undefined index for an array.
3201 | ThrowArrayKeyException, ND, S(Dict) S(Str), T|LA
3203 Throws an OutOfBoundsException if S0 is an undefined key for a darray or dict.
3205 | ThrowOutOfBounds, ND, S(ArrLike|Obj) S(Cell), T|LA
3207 Throws an OutOfBoundsException corresponding to an access of S0 with the key
3210 | ThrowInvalidArrayKey, ND, S(ArrLike) S(Cell), T|LA
3212 Throws an InvalidArgumentException corresponding to an access of S0 with the
3213 key S1, which has a type invalid for that array.
3215 | ThrowInvalidOperation, ND, S(Str), T
3217 Throws an InvalidOperationException with a message indicating S0.
3219 | ThrowDivisionByZeroException, ND, NA, T
3221 Throws a DivisionByZeroException.
3223 | ThrowLateInitPropError, ND, S(Cls) S(Str) S(Bool), T
3225 Throws an InvalidOperationException indicating an access of a unset LateInit
3226 property. S0 is the class the property was declared on. S1 is the property
3227 name. S2 is true if its a static property, false otherwise.
3229 | ThrowParameterWrongType<expectedType, func, argNum>, ND, S(Cell), T
3231 Throws a RuntimeException if calling a function with an argument that has the
3234 | ThrowOrWarnMustBeMutableException<cls>, ND, S(Str), NF
3236 Throws an InvalidOperationException indicating a readonly semantics violation
3237 where the property was required to be mutable. cls is the class the property
3238 was declared on. S0 is the property name. Raises a warning if
3239 EnableReadonlyPropertyEnforcement=1.
3241 | ThrowOrWarnMustBeReadonlyException<cls>, ND, S(Str), NF
3243 Throws an InvalidOperationException indicating a readonly semantics violation
3244 where the property was required to be readonly. cls is the class the property
3245 was declared on. S0 is the property name. Raises a warning if
3246 EnableReadonlyPropertyEnforcement=1.
3248 | ThrowOrWarnLocalMustBeValueTypeException, ND, S(Str), NF
3250 Throws an InvalidOperationException indicating a readonly semantics violation
3251 where the local was required to be a value type. S0 is the local name. Raises
3252 a warning if EnableReadonlyPropertyEnforcement=1.
3254 | ThrowOrWarnMustBeValueTypeException<cls>, ND, S(Str), NF
3256 Throws an InvalidOperationException indicating a readonly semantics violation
3257 where the property was required to be a value type. S0 is the property
3258 name. cls is the class the property was declared on. Raises a warning if
3259 EnableReadonlyPropertyEnforcement=1.
3261 | ThrowOrWarnMustBeEnclosedInReadonly<cls>, ND, S(Str), NF
3263 Throws an InvalidOperationException indicating a readonly semantics violation
3264 where the property was required to be enclosed in a readonly expression. cls
3265 is the class the property was declared on. S0 is the property name. Raises a
3266 warning if EnableReadonlyPropertyEnforcement=1.
3268 | ThrowOrWarnCannotModifyReadonlyCollection, ND, NA, NF
3270 Throws an InvalidOperationException indicating a readonly semantics violation
3271 where a collection is modified. Raises a warning if
3272 EnableReadonlyPropertyEnforcement=1.
3274 | ProfileType, ND, S(Cell), NF
3276 Profile the type of S0.
3278 | ProfileCall<rdsHandle>, ND, S(Func), NF
3280 Profile the call to a function S0.
3282 | ProfileMethod<rdsHandle>, ND, S(Cls) S(Func), NF
3284 Profile the method S1 called with class context S0.
3286 | ProfileProp, ND, C(StaticStr) C(StaticStr), NF
3288 Profile the access to property S(1) with base class S(0).
3290 | CheckVecBounds, ND, S(Vec) S(Int), B|LA
3292 Checks that the index in S1 is within the bounds of the packed array or
3293 vector array in S0. Branches to B if the index is out of bounds.
3295 | LdVecElemAddr<T>, DParam(LvalToElemCell), S(Vec) S(Int), NF
3297 Loads the address of the element at index S1 of the packed array or vec array
3298 in S0. This instruction assumes the array actually contains an element at
3299 that offset (IE, the array has the proper length).
3301 | ReserveVecNewElem, D(Int), S(Vec), B
3303 If there is room in the packed or vec array (which is assumed to be mutable),
3304 increments the array size and returns the index of the new last element
3305 (which you must initialize); else jumps to the taken branch.
3307 | LdVecElem, DVecElem, S(Vec) S(Int), NF
3309 Loads the element of the vec array in S0 at offset S1. This instruction
3310 assumes that the vec actually contains an element at that offset (IE, the vec
3311 has the proper length).
3313 | LdVectorSize, D(Int), S(Obj), NF
3315 Returns the size of the given Vector collection in S0.
3317 | ColIsEmpty, D(Bool), S(Obj), NF
3319 | ColIsNEmpty, D(Bool), S(Obj), NF
3321 Returns whether a collection instance is empty or not. S0 must be known to
3322 be an instance of a collection class at compile time.
3324 | VecFirst, DFirstElem, S(Vec), NF
3326 Returns the first value from the packed or vec array in S0.
3327 If the array is empty, it will return NULL.
3329 | VecLast, DLastElem, S(Vec), NF
3331 Returns the last value from the packed or vec array in S0.
3332 If the array is empty, it will return NULL.
3334 | DictFirst, DFirstElem, S(Dict), NF
3336 Returns the first value from the mixed or dict array in S0.
3337 If the array is empty, it will return NULL.
3339 | DictLast, DLastElem, S(Dict), NF
3341 Returns the last value from the mixed or dict array in S0.
3342 If the array is empty, it will return NULL.
3344 | DictFirstKey, DFirstKey, S(Dict), NF
3346 Returns the first key from the mixed or dict array in S0.
3347 If the array is empty, it will return NULL.
3349 | DictLastKey, DLastKey, S(Dict), NF
3351 Returns the last key from the mixed or dict array in S0.
3352 If the array is empty, it will return NULL.
3354 | KeysetFirst, DFirstElem, S(Keyset), NF
3356 Returns the first value(key) from the keyset in S0.
3357 If the array is empty, it will return NULL.
3359 | KeysetLast, DLastElem, S(Keyset), NF
3361 Returns the first value(key) from the keyset in S0.
3362 If the array is empty, it will return NULL.
3364 | IsLegacyArrLike, D(Bool), S(Vec|Dict), LA
3366 Returns true iff the given array has the legacy bit set.
3368 | ArrayMarkLegacyShallow, DModified(0), S(Vec,Dict), CRc|PRc|LA
3370 | ArrayMarkLegacyRecursive, DModified(0), S(Vec,Dict), CRc|PRc|LA
3372 | ArrayUnmarkLegacyShallow, DModified(0), S(Vec,Dict), CRc|PRc|LA
3374 | ArrayUnmarkLegacyRecursive, DModified(0), S(Vec,Dict), CRc|PRc|LA
3376 Set or unset the legacy bit on the array-like in S0, copying it if needed.
3377 The recursive variants traverse through the array-like's transitive elements
3378 but stop traversal at any non-array-like.
3381 18. Exception/unwinding support
3383 | BeginCatch, ND, NA, NF
3385 Marks the beginning of a catch region. Exact behavior is implementation and
3386 architecture specific.
3388 | EndCatch<spOffset,mode,stublogue>, ND, S(FramePtr) S(StkPtr), T
3390 Marks the end of a catch region and returns control to the unwinder. The
3391 `spOffset' field represents a logical adjustment to S1 (in cells) to yield
3392 the vm stack pointer, however the stack pointer is not actually adjusted
3393 before this instruction returns control to the unwinder. The unwinder
3394 instead relies on fixup map information to find the appropriate stack
3395 pointers. Instead it's part of this instruction to facilitate assertions and
3396 memory effect analysis.
3398 If the `stublogue' flag is set, the native stack pointer is updated to reflect
3399 the state prior to entering the stublogue context.
3401 | UnwindCheckSideExit, ND, S(FramePtr) S(StkPtr), B
3403 Branches to B if the currently executing catch region should return control
3404 to the unwinder rather than side exiting. Used to control behavior in catch
3405 traces for the InvalidSetMException and TVCoercionException situations.
3407 | LdUnwinderValue<T>, DParam(Cell), NA, PRc
3409 Loads the value contained by the current unwinder exception.
3411 | EnterTCUnwind<spOff,teardown>, ND, S(Obj), CRc|T
3413 Enters tc_unwind_resume by doing a side enter, i.e. skipping
3414 itanium ABI. Stores the exception given by S0 to UnwindRDS's exn
3415 field as well as true to sideEnter field.
3417 If teardown is set, it notifies tc_unwind_resume to also teardown the locals.
3419 19. Function prologues
3421 | EnterPrologue, ND, NA, NF
3423 Enter prologue context, which operates in the same mode as unique stubs.
3424 Makes sure the native stack is properly aligned.
3426 | CheckStackOverflow, ND, S(StkPtr), NF
3428 Check if the stack depth has exceeded its limit. If it has, jump to the
3429 stack overflow helper stub, which will throw.
3431 | CheckSurpriseFlagsEnter<func,argc>, ND, S(FramePtr), NF
3433 Test the implementation-specific surprise flags. If they're nonzero, call
3434 the function enter helper.
3436 | CheckSurpriseAndStack<func,args>, ND, S(FramePtr), NF
3438 Test surprise flags and stack overflow at the same time.
3440 | LdARFlags, D(Int), S(FramePtr), NF
3442 Load the flags stored on the ActRec pointed to by the frame
3443 pointer S0. Bits not defined as flags may contain arbitrary garbage.
3445 | LdTVAux<ValidBits>, D(Int), S(Cell), NF
3447 Load the value of m_aux from the TypedValue S0. ValidBits is a mask
3448 specifying which bits are allowed to be set. The runtime may ignore it.
3450 Note that when we pass TypedValues around in registers, we usually use a byte
3451 register for the m_type member, and thus ignore m_aux. LdTVAux is only valid
3452 when we know that S0's m_type and m_aux were both materialized into the same
3455 /* Local Variables: */
3456 /* fill-column: 79 */