2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_VM_EXTRADATA_H_
18 #define incl_HPHP_VM_EXTRADATA_H_
20 #include "hphp/runtime/base/collections.h"
21 #include "hphp/runtime/base/typed-value.h"
22 #include "hphp/runtime/vm/bytecode.h"
23 #include "hphp/runtime/vm/srckey.h"
25 #include "hphp/runtime/vm/jit/types.h"
26 #include "hphp/runtime/vm/jit/ir-opcode.h"
27 #include "hphp/runtime/vm/jit/stack-offsets.h"
29 #include "hphp/runtime/ext/generator/ext_generator.h"
31 #include "hphp/util/arena.h"
32 #include "hphp/util/ringbuffer.h"
33 #include "hphp/util/safe-cast.h"
35 #include <folly/Conv.h>
36 #include <folly/Hash.h>
37 #include <folly/Optional.h>
38 #include <folly/gen/Base.h>
39 #include <folly/gen/String.h>
44 namespace HPHP
{ namespace jit
{
46 //////////////////////////////////////////////////////////////////////
49 * Some IRInstructions with compile-time-only constants may carry along extra
50 * data in the form of one of these structures.
52 * Note that this isn't really appropriate for compile-time constants that are
53 * actually representing user values (we want them to be visible to
54 * optimization passes, allocatable to registers, etc), just compile-time
59 * - Derive from IRExtraData (for overloading purposes).
60 * - Be arena-allocatable (no non-trivial destructors).
61 * - Either CopyConstructible, or implement a clone member function that
62 * takes an arena to clone to.
64 * In addition, extra data belonging to IRInstructions that may be hashed in
67 * - Implement an equals() member that indicates equality.
68 * - Implement a hash() method.
70 * Finally, optionally they may implement a show() method for use in debug
75 * Traits that returns the type of the extra C++ data structure for a
76 * given instruction, if it has one, along with some other information
79 template<Opcode op
> struct OpHasExtraData
{ enum { value
= 0 }; };
80 template<Opcode op
> struct IRExtraDataType
;
82 //////////////////////////////////////////////////////////////////////
84 struct IRExtraData
{};
86 //////////////////////////////////////////////////////////////////////
89 * Shared IRExtraData classes.
91 * These subtypes represent common parameters (e.g., statically known Func,
92 * local variable ID, stack offset, etc.) that are useful for a variety of HHIR
95 * These are kept separate from the one-off IRExtraDatas to make it easier to
96 * find existing common parameters.
100 * Offset in bytes from a base pointer---e.g., to a object property from an
103 struct ByteOffsetData
: IRExtraData
{
104 explicit ByteOffsetData(ptrdiff_t offset
) : offsetBytes(offset
) {}
106 std::string
show() const { return folly::to
<std::string
>(offsetBytes
); }
108 bool equals(ByteOffsetData o
) const { return offsetBytes
== o
.offsetBytes
; }
109 size_t hash() const { return std::hash
<ptrdiff_t>()(offsetBytes
); }
111 ptrdiff_t offsetBytes
;
117 * Required to be non-null.
119 struct ClassData
: IRExtraData
{
120 explicit ClassData(const Class
* cls
)
123 assertx(cls
!= nullptr);
126 std::string
show() const {
127 return folly::to
<std::string
>(cls
->name()->data());
130 bool equals(const ClassData
& o
) const {
134 size_t hash() const {
135 return pointer_hash
<Class
>()(cls
);
142 * Class pointer, suppress flag, is or as operation flag and range into the
143 * stack (for type structures) needed for resolve type struct instruction
145 * Class pointer could be null.
147 struct ResolveTypeStructData
: IRExtraData
{
148 explicit ResolveTypeStructData(
151 IRSPRelOffset offset
,
162 std::string
show() const {
163 return folly::sformat("{},{},{},{},{}",
164 cls
? cls
->name()->data() : "nullptr",
165 suppress
? "suppress" : "no-suppress",
171 bool equals(const ResolveTypeStructData
& o
) const {
172 return cls
== o
.cls
&& suppress
== o
.suppress
&&
173 offset
== o
.offset
&& size
== o
.size
&& isOrAsOp
== o
.isOrAsOp
;
176 size_t hash() const {
177 return (pointer_hash
<Class
>()(cls
)
178 + std::hash
<int32_t>()(offset
.offset
)
179 + std::hash
<uint32_t>()(size
))
180 ^ ((int64_t)(suppress
? -1 : 0) << 32 | (isOrAsOp
? -1 : 0));
185 IRSPRelOffset offset
;
193 struct ExtendsClassData
: IRExtraData
{
194 explicit ExtendsClassData(const Class
* cls
, bool strictLikely
= false)
195 : cls(cls
), strictLikely(strictLikely
)
197 assertx(cls
!= nullptr);
200 std::string
show() const {
201 return folly::sformat("{}{}",
202 cls
->name(), strictLikely
? ":strictLikely" : "");
205 bool equals(const ExtendsClassData
& o
) const {
206 return cls
== o
.cls
&& strictLikely
== o
.strictLikely
;
209 size_t hash() const {
210 return pointer_hash
<Class
>()(cls
) ^ (strictLikely
? -1 : 0);
218 * Class with method name.
220 struct ClsMethodData
: IRExtraData
{
221 ClsMethodData(const StringData
* cls
, const StringData
* method
,
222 const NamedEntity
* ne
= nullptr)
228 std::string
show() const {
229 return folly::format("{}::{}", clsName
, methodName
).str();
232 bool equals(const ClsMethodData
& o
) const {
233 // The strings are static so we can use pointer equality.
234 return clsName
== o
.clsName
&& methodName
== o
.methodName
;
236 size_t hash() const {
237 return hash_int64_pair((intptr_t)clsName
, (intptr_t)methodName
);
240 const StringData
* clsName
;
241 const StringData
* methodName
;
242 const NamedEntity
* namedEntity
;
245 struct IfaceMethodData
: IRExtraData
{
246 IfaceMethodData(Slot vtableIdx
, Slot methodIdx
)
247 : vtableIdx(vtableIdx
)
248 , methodIdx(methodIdx
)
251 std::string
show() const {
252 return folly::sformat("{}, {}", vtableIdx
, methodIdx
);
255 bool equals(const IfaceMethodData
& o
) const {
256 return vtableIdx
== o
.vtableIdx
&& methodIdx
== o
.methodIdx
;
259 size_t hash() const {
260 return hash_int64((int64_t)vtableIdx
<< 32 | methodIdx
);
270 struct FuncData
: IRExtraData
{
271 explicit FuncData(const Func
* f
)
275 std::string
show() const {
276 return folly::format("{}", func
->fullName()).str();
283 * Func with argument index.
285 struct FuncArgData
: IRExtraData
{
286 explicit FuncArgData(const Func
* f
, int64_t arg
)
291 std::string
show() const {
292 return folly::format("{},{}", func
->name(), argNum
).str();
302 struct LocalId
: IRExtraData
{
303 explicit LocalId(uint32_t id
) : locId(id
) {}
305 std::string
show() const { return folly::to
<std::string
>(locId
); }
307 bool equals(LocalId o
) const { return locId
== o
.locId
; }
308 size_t hash() const { return std::hash
<uint32_t>()(locId
); }
313 struct ClsRefSlotData
: IRExtraData
{
314 explicit ClsRefSlotData(uint32_t slot
) : slot
{slot
} {}
316 std::string
show() const { return folly::to
<std::string
>(slot
); }
318 bool equals(ClsRefSlotData o
) const { return slot
== o
.slot
; }
319 size_t hash() const { return std::hash
<uint32_t>()(slot
); }
325 * Index into, e.g., an array.
327 struct IndexData
: IRExtraData
{
328 explicit IndexData(uint32_t index
) : index(index
) {}
330 std::string
show() const { return folly::format("{}", index
).str(); }
338 struct IterId
: IRExtraData
{
339 explicit IterId(uint32_t id
)
343 std::string
show() const { return folly::to
<std::string
>(iterId
); }
345 bool equals(IterId o
) const { return iterId
== o
.iterId
; }
346 size_t hash() const { return std::hash
<uint32_t>()(iterId
); }
352 * Iter instruction data.
354 * `iterId' is the iterator ID; `keyId' and `valId' are the IDs of the iterator
355 * locals $key => $value. For keyless iterators, we still use this class, with
356 * `keyId` set to -1u.
358 struct IterData
: IRExtraData
{
359 IterData(uint32_t iter
, uint32_t key
, uint32_t val
)
365 std::string
show() const {
366 if (keyId
== -1) return folly::format("{}::{}", iterId
, valId
).str();
367 return folly::format("{}::{}::{}", iterId
, keyId
, valId
).str();
375 struct IterInitData
: public IterData
{
376 IterInitData(uint32_t iter
, uint32_t key
,
377 uint32_t val
, bool stack
)
378 : IterData
{iter
, key
, val
}
387 struct RDSHandleData
: IRExtraData
{
388 explicit RDSHandleData(rds::Handle handle
) : handle(handle
) {}
390 std::string
show() const { return folly::to
<std::string
>(handle
); }
392 bool equals(RDSHandleData o
) const { return handle
== o
.handle
; }
393 size_t hash() const { return std::hash
<uint32_t>()(handle
); }
399 * Array access profile.
401 struct ArrayAccessProfileData
: RDSHandleData
{
402 ArrayAccessProfileData(rds::Handle handle
, bool cowCheck
)
403 : RDSHandleData(handle
), cowCheck(cowCheck
) {}
405 std::string
show() const {
406 return folly::to
<std::string
>(handle
, ",", cowCheck
);
409 bool equals(ArrayAccessProfileData o
) const {
410 return handle
== o
.handle
&& cowCheck
== o
.cowCheck
;
412 size_t hash() const {
413 return folly::hash::hash_combine(std::hash
<uint32_t>()(handle
),
414 std::hash
<bool>()(cowCheck
));
424 * Used with profiling-related instructions.
426 struct TransIDData
: IRExtraData
{
427 explicit TransIDData(TransID transId
) : transId(transId
) {}
429 std::string
show() const { return folly::to
<std::string
>(transId
); }
435 * FP-relative offset.
437 struct FPRelOffsetData
: IRExtraData
{
438 explicit FPRelOffsetData(FPRelOffset offset
) : offset(offset
) {}
440 std::string
show() const {
441 return folly::to
<std::string
>("FPRelOff ", offset
.offset
);
444 bool equals(FPRelOffsetData o
) const { return offset
== o
.offset
; }
445 size_t hash() const { return std::hash
<int32_t>()(offset
.offset
); }
451 * Stack pointer offset.
453 struct FPInvOffsetData
: IRExtraData
{
454 explicit FPInvOffsetData(FPInvOffset offset
) : offset(offset
) {}
456 std::string
show() const {
457 return folly::to
<std::string
>("FPInvOff ", offset
.offset
);
460 bool equals(FPInvOffsetData o
) const { return offset
== o
.offset
; }
461 size_t hash() const { return std::hash
<int32_t>()(offset
.offset
); }
469 struct IRSPRelOffsetData
: IRExtraData
{
470 explicit IRSPRelOffsetData(IRSPRelOffset offset
) : offset(offset
) {}
472 std::string
show() const {
473 return folly::to
<std::string
>("IRSPOff ", offset
.offset
);
476 bool equals(IRSPRelOffsetData o
) const { return offset
== o
.offset
; }
477 size_t hash() const { return std::hash
<int32_t>()(offset
.offset
); }
479 IRSPRelOffset offset
;
482 ///////////////////////////////////////////////////////////////////////////////
485 * One-off IRExtraData classes.
487 * These are used for only one or two instructions and are in no particular
488 * order. Add new IRExtraData types here.
491 struct IsAsyncData
: IRExtraData
{
492 explicit IsAsyncData(bool isAsync
) : isAsync(isAsync
) {}
494 std::string
show() const { return folly::to
<std::string
>(isAsync
); }
495 bool equals(IsAsyncData d
) const { return isAsync
== d
.isAsync
; }
496 size_t hash() const { return std::hash
<int32_t>()(isAsync
); }
501 struct LdBindAddrData
: IRExtraData
{
502 explicit LdBindAddrData(SrcKey sk
, FPInvOffset bcSPOff
)
507 std::string
show() const { return showShort(sk
); }
513 struct LdSSwitchData
: IRExtraData
{
515 const StringData
* str
;
519 explicit LdSSwitchData() = default;
520 LdSSwitchData(const LdSSwitchData
&) = delete;
521 LdSSwitchData
& operator=(const LdSSwitchData
&) = delete;
523 LdSSwitchData
* clone(Arena
& arena
) const {
524 LdSSwitchData
* target
= new (arena
) LdSSwitchData
;
525 target
->numCases
= numCases
;
526 target
->defaultSk
= defaultSk
;
527 target
->cases
= new (arena
) Elm
[numCases
];
528 target
->bcSPOff
= bcSPOff
;
529 std::copy(cases
, cases
+ numCases
, const_cast<Elm
*>(target
->cases
));
533 std::string
show() const {
534 return folly::to
<std::string
>(bcSPOff
.offset
);
543 struct ProfileSwitchData
: IRExtraData
{
544 ProfileSwitchData(rds::Handle handle
, int32_t cases
, int64_t base
)
550 std::string
show() const {
551 return folly::sformat("handle {}, {} cases, base {}", handle
, cases
, base
);
559 struct JmpSwitchData
: IRExtraData
{
560 JmpSwitchData
* clone(Arena
& arena
) const {
561 JmpSwitchData
* sd
= new (arena
) JmpSwitchData
;
563 sd
->targets
= new (arena
) SrcKey
[cases
];
564 sd
->spOffBCFromFP
= spOffBCFromFP
;
565 sd
->spOffBCFromIRSP
= spOffBCFromIRSP
;
566 std::copy(targets
, targets
+ cases
, const_cast<SrcKey
*>(sd
->targets
));
570 std::string
show() const {
571 return folly::sformat("{} cases", cases
);
574 int32_t cases
; // number of cases
575 SrcKey
* targets
; // srckeys for all targets
576 FPInvOffset spOffBCFromFP
;
577 IRSPRelOffset spOffBCFromIRSP
;
580 struct LdTVAuxData
: IRExtraData
{
581 explicit LdTVAuxData(int32_t v
= -1) : valid(v
) {}
583 std::string
show() const {
584 return folly::sformat("{:x}", valid
);
590 struct ReqBindJmpData
: IRExtraData
{
591 explicit ReqBindJmpData(const SrcKey
& target
,
592 FPInvOffset invSPOff
,
593 IRSPRelOffset irSPOff
,
601 std::string
show() const {
602 return folly::sformat(
603 "{}, FPInv {}, IRSP {}, Flags {}",
604 target
.offset(), invSPOff
.offset
, irSPOff
.offset
, trflags
.packed
609 FPInvOffset invSPOff
;
610 IRSPRelOffset irSPOff
;
614 struct ReqRetranslateData
: IRExtraData
{
615 explicit ReqRetranslateData(IRSPRelOffset irSPOff
,
621 std::string
show() const {
622 return folly::to
<std::string
>(irSPOff
.offset
, ',', trflags
.packed
);
625 IRSPRelOffset irSPOff
;
630 * Compile-time metadata about an ActRec allocation.
632 struct ActRecInfo
: IRExtraData
{
633 explicit ActRecInfo(IRSPRelOffset spOffset
, uint32_t numArgs
)
638 std::string
show() const {
639 return folly::to
<std::string
>(spOffset
.offset
, ',', numArgs
);
642 IRSPRelOffset spOffset
;
647 * DefInlineFP is present when we need to create a frame for inlining. This
648 * instruction also carries some metadata used by IRBuilder to track state
649 * during an inlined call.
651 struct DefInlineFPData
: IRExtraData
{
652 std::string
show() const {
653 return folly::to
<std::string
>(
654 target
->fullName()->data(), "(),",
656 retSPOff
.offset
, ',',
662 SSATmp
* ctx
; // Ctx, Cls or Nullptr.
664 FPInvOffset retSPOff
;
665 IRSPRelOffset spOffset
; // offset from caller SP to bottom of callee's ActRec
666 uint32_t numNonDefault
;
667 bool asyncEagerReturn
;
670 struct SyncReturnBCData
: IRExtraData
{
671 SyncReturnBCData(Offset callBCOff
, IRSPRelOffset spOff
)
672 : callBCOffset(callBCOff
)
675 std::string
show() const {
676 return folly::to
<std::string
>(callBCOffset
, ",", spOffset
.offset
);
680 IRSPRelOffset spOffset
;
683 struct CallUnpackData
: IRExtraData
{
684 explicit CallUnpackData(IRSPRelOffset spOffset
,
690 , numParams(numParams
)
692 , callOffset(callOffset
)
695 assertx(numParams
> 0);
698 std::string
show() const {
699 return folly::to
<std::string
>(
702 ? folly::sformat(",{}", callee
->fullName())
706 IRSPRelOffset spOffset
; // offset from StkPtr to bottom of call's ActRec+args
709 Offset callOffset
; // offset from unit m_bc (unlike m_callOff in ActRec)
710 const Func
* callee
; // nullptr if not statically known
713 struct CallBuiltinData
: IRExtraData
{
714 explicit CallBuiltinData(IRSPRelOffset spOffset
,
716 int32_t numNonDefault
)
719 , numNonDefault
{numNonDefault
}
722 std::string
show() const {
723 return folly::to
<std::string
>(
724 spOffset
.offset
, ',',
725 callee
->fullName()->data()
729 IRSPRelOffset spOffset
; // offset from StkPtr to last passed arg
731 int32_t numNonDefault
;
734 struct CallData
: IRExtraData
{
735 explicit CallData(IRSPRelOffset spOffset
,
740 bool asyncEagerReturn
)
742 , numParams(numParams
)
744 , callOffset(callOffset
)
746 , asyncEagerReturn(asyncEagerReturn
)
749 std::string
show() const {
750 return folly::to
<std::string
>(
751 spOffset
.offset
, ',', numParams
, ',', callOffset
,
753 ? folly::format(",{}", callee
->fullName()).str()
755 asyncEagerReturn
? ",asyncEagerReturn" : ""
759 IRSPRelOffset spOffset
; // offset from StkPtr to bottom of call's ActRec+args
761 uint32_t numOut
; // number of values returned via stack from the callee
762 Offset callOffset
; // m_callOff style: offset from func->base()
763 const Func
* callee
; // nullptr if not statically known
764 bool asyncEagerReturn
;
767 struct RetCtrlData
: IRExtraData
{
768 explicit RetCtrlData(IRSPRelOffset offset
, bool suspendingResumed
,
769 folly::Optional
<AuxUnion
> aux
= folly::none
)
771 , suspendingResumed(suspendingResumed
)
775 std::string
show() const {
776 return folly::to
<std::string
>(
778 suspendingResumed
? ",suspendingResumed" : ""
782 // Adjustment we need to make to the stack pointer (for cross-tracelet ABI
783 // purposes) before returning.
784 IRSPRelOffset offset
;
786 // Indicates that the current resumable frame is being suspended without
787 // decrefing locals. Used by refcount optimizer.
788 bool suspendingResumed
;
790 // Optional TV aux value to attach to the function's return value.
791 folly::Optional
<AuxUnion
> aux
;
795 * Name of a class constant in a known class
797 struct ClsCnsName
: IRExtraData
{
798 explicit ClsCnsName(const StringData
* cls
, const StringData
* cns
)
803 std::string
show() const {
804 return folly::to
<std::string
>(clsName
->data(), "::", cnsName
->data());
807 const StringData
* clsName
;
808 const StringData
* cnsName
;
812 * Name of a class constant in an unknown class.
814 struct LdSubClsCnsData
: IRExtraData
{
815 explicit LdSubClsCnsData(const StringData
* cns
, Slot s
)
820 std::string
show() const {
821 return folly::sformat("<cls>::{}({})", cnsName
, slot
);
824 const StringData
* cnsName
;
829 * Name and handle of profiled class constant
831 struct ProfileSubClsCnsData
: IRExtraData
{
832 explicit ProfileSubClsCnsData(const StringData
* cns
, rds::Handle h
)
837 std::string
show() const {
838 return folly::to
<std::string
>("<cls>::", cnsName
->data());
841 const StringData
* cnsName
;
845 struct FuncNameData
: IRExtraData
{
846 explicit FuncNameData(const StringData
* name
)
850 std::string
show() const {
851 return folly::to
<std::string
>(name
->data());
854 size_t hash() const { return name
->hash(); }
855 bool equals(const FuncNameData
& o
) const {
856 return name
== o
.name
;
859 const StringData
* name
;
863 * Offset and stack deltas for InterpOne.
865 struct InterpOneData
: IRExtraData
{
867 explicit LocalType(uint32_t id
= 0, Type type
= TBottom
)
877 explicit ClsRefSlot(uint32_t id
= 0, bool write
= false)
886 explicit InterpOneData(IRSPRelOffset spOffset
)
889 , changedLocals(nullptr)
890 , nChangedClsRefSlots(0)
891 , changedClsRefSlots(nullptr)
892 , smashesAllLocals(false)
895 // Offset of the BC stack top relative to the current IR stack pointer.
896 IRSPRelOffset spOffset
;
898 // Offset of the instruction to interpret, in the Unit indicated by the
902 // The number of eval stack cells consumed and produced by the instruction,
903 // respectively. Includes ActRecs.
907 // Opcode, in case we need to fix the stack differently. Some bytecode
908 // instructions modify things below the top of the stack.
911 uint32_t nChangedLocals
;
912 LocalType
* changedLocals
;
914 uint32_t nChangedClsRefSlots
;
915 ClsRefSlot
* changedClsRefSlots
;
917 bool smashesAllLocals
;
919 InterpOneData
* clone(Arena
& arena
) const {
920 auto* id
= new (arena
) InterpOneData(spOffset
);
922 id
->cellsPopped
= cellsPopped
;
923 id
->cellsPushed
= cellsPushed
;
925 id
->nChangedLocals
= nChangedLocals
;
926 id
->changedLocals
= new (arena
) LocalType
[nChangedLocals
];
927 id
->nChangedClsRefSlots
= nChangedClsRefSlots
;
928 id
->changedClsRefSlots
= new (arena
) ClsRefSlot
[nChangedClsRefSlots
];
929 id
->smashesAllLocals
= smashesAllLocals
;
930 std::copy(changedLocals
, changedLocals
+ nChangedLocals
, id
->changedLocals
);
931 std::copy(changedClsRefSlots
, changedClsRefSlots
+ nChangedClsRefSlots
,
932 id
->changedClsRefSlots
);
936 std::string
show() const {
937 auto ret
= folly::sformat(
938 "{}: spOff:{}, bcOff:{}, popped:{}, pushed:{}",
939 opcodeToName(opcode
),
945 assertx(!smashesAllLocals
|| !nChangedLocals
);
946 if (smashesAllLocals
) ret
+= ", smashes all locals";
947 if (nChangedLocals
) {
948 for (auto i
= 0; i
< nChangedLocals
; ++i
) {
949 ret
+= folly::sformat(", Local {} -> {}",
951 changedLocals
[i
].type
);
954 if (nChangedClsRefSlots
) {
955 for (auto i
= 0; i
< nChangedClsRefSlots
; ++i
) {
956 ret
+= folly::sformat(", Slot {}{}",
957 changedClsRefSlots
[i
].id
,
958 changedClsRefSlots
[i
].write
? "W" : "R");
966 struct CoerceStkData
: IRExtraData
{
967 explicit CoerceStkData(IRSPRelOffset off
, const Func
* f
, int64_t arg_num
)
968 : offset(off
), callee(f
), argNum(arg_num
) {}
970 std::string
show() const {
971 return folly::sformat(
979 IRSPRelOffset offset
;
984 struct CoerceMemData
: IRExtraData
{
985 explicit CoerceMemData(const Func
* f
, int64_t arg_num
)
986 : callee(f
), argNum(arg_num
) {}
988 std::string
show() const {
989 return folly::sformat("{},{}", callee
->name(), argNum
);
996 struct RBEntryData
: IRExtraData
{
997 RBEntryData(Trace::RingBufferType t
, SrcKey sk
)
1002 std::string
show() const {
1003 return folly::sformat("{}: {}", ringbufferName(type
), showShort(sk
));
1006 Trace::RingBufferType type
;
1010 struct RBMsgData
: IRExtraData
{
1011 RBMsgData(Trace::RingBufferType t
, const StringData
* msg
)
1015 assertx(msg
->isStatic());
1018 std::string
show() const {
1019 return folly::sformat("{}: {}", ringbufferName(type
), msg
->data());
1022 Trace::RingBufferType type
;
1023 const StringData
* msg
;
1026 struct ClassKindData
: IRExtraData
{
1027 explicit ClassKindData(ClassKind kind
): kind(uint32_t(kind
)) {}
1029 std::string
show() const {
1030 switch (static_cast<ClassKind
>(kind
)) {
1031 case ClassKind::Class
: return "cls";
1032 case ClassKind::Interface
: return "interface";
1033 case ClassKind::Trait
: return "trait";
1034 case ClassKind::Enum
: return "enum";
1039 uint32_t kind
; // ... allows for direct usage in native_call
1042 struct NewStructData
: IRExtraData
{
1043 std::string
show() const;
1044 IRSPRelOffset offset
;
1049 struct PackedArrayData
: IRExtraData
{
1050 explicit PackedArrayData(uint32_t size
) : size(size
) {}
1051 std::string
show() const { return folly::format("{}", size
).str(); }
1055 struct InitPackedArrayLoopData
: IRExtraData
{
1056 explicit InitPackedArrayLoopData(IRSPRelOffset offset
, uint32_t size
)
1061 std::string
show() const {
1062 return folly::format("{},{}", offset
.offset
, size
).str();
1065 IRSPRelOffset offset
;
1069 struct CreateAAWHData
: IRExtraData
{
1070 explicit CreateAAWHData(uint32_t first
, uint32_t count
)
1075 std::string
show() const {
1076 return folly::format("{},{}", first
, count
).str();
1083 struct CountWHNotDoneData
: IRExtraData
{
1084 explicit CountWHNotDoneData(uint32_t first
, uint32_t count
)
1089 std::string
show() const {
1090 return folly::format("{},{}", first
, count
).str();
1097 struct NewKeysetArrayData
: IRExtraData
{
1098 explicit NewKeysetArrayData(IRSPRelOffset offset
, uint32_t size
)
1103 std::string
show() const {
1104 return folly::format("{},{}", offset
.offset
, size
).str();
1107 IRSPRelOffset offset
;
1111 struct MemoValueStaticData
: IRExtraData
{
1112 explicit MemoValueStaticData(const Func
* func
,
1113 folly::Optional
<bool> asyncEager
,
1116 , asyncEager
{asyncEager
}
1117 , loadAux
{loadAux
} {}
1118 std::string
show() const {
1119 return folly::sformat(
1121 func
->fullName()->toCppString(),
1122 asyncEager
? folly::to
<std::string
>(*asyncEager
) : "-",
1127 folly::Optional
<bool> asyncEager
;
1131 struct MemoValueInstanceData
: IRExtraData
{
1132 explicit MemoValueInstanceData(Slot slot
,
1134 folly::Optional
<bool> asyncEager
,
1138 , asyncEager
{asyncEager
}
1139 , loadAux
{loadAux
} {}
1140 std::string
show() const {
1141 return folly::sformat(
1145 asyncEager
? folly::to
<std::string
>(*asyncEager
) : "-",
1151 folly::Optional
<bool> asyncEager
;
1155 struct MemoCacheStaticData
: IRExtraData
{
1156 MemoCacheStaticData(const Func
* func
,
1159 folly::Optional
<bool> asyncEager
,
1164 , asyncEager
{asyncEager
}
1165 , loadAux
{loadAux
} {}
1167 MemoCacheStaticData
* clone(Arena
& arena
) const {
1169 new (arena
) MemoCacheStaticData(func
, keys
, types
, asyncEager
, loadAux
);
1170 auto tmp
= new (arena
) bool[keys
.count
];
1171 std::copy(types
, types
+ keys
.count
, tmp
);
1173 p
->stackOffset
= stackOffset
;
1177 std::string
show() const {
1180 ret
+= folly::sformat(
1181 "{},IRSPOff {}", func
->fullName(), stackOffset
->offset
1184 ret
+= folly::sformat("{},{}", func
->fullName(), HPHP::show(keys
));
1187 if (keys
.count
> 0) {
1189 for (auto i
= 0; i
< keys
.count
; ++i
) {
1190 if (i
> 0) ret
+= ",";
1191 ret
+= folly::sformat("{}", types
[i
] ? "string" : "int");
1201 folly::Optional
<bool> asyncEager
;
1203 // Should only be present if the frame is given by a StkPtr
1204 folly::Optional
<IRSPRelOffset
> stackOffset
;
1207 struct MemoCacheInstanceData
: IRExtraData
{
1208 MemoCacheInstanceData(Slot slot
,
1213 folly::Optional
<bool> asyncEager
,
1220 , asyncEager
{asyncEager
}
1221 , loadAux
{loadAux
} {}
1223 MemoCacheInstanceData
* clone(Arena
& arena
) const {
1224 auto p
= new (arena
) MemoCacheInstanceData(
1225 slot
, keys
, types
, func
, shared
, asyncEager
, loadAux
1227 auto tmp
= new (arena
) bool[keys
.count
];
1228 std::copy(types
, types
+ keys
.count
, tmp
);
1230 p
->stackOffset
= stackOffset
;
1234 std::string
show() const {
1235 return folly::sformat(
1240 ? folly::sformat("IRSPOff {}", stackOffset
->offset
)
1243 using namespace folly::gen
;
1244 return range
<uint32_t>(0, keys
.count
)
1245 | map([this] (uint32_t i
) { return types
[i
] ? "string" : "int"; })
1246 | unsplit
<std::string
>(",");
1248 shared
? "shared" : "non-shared"
1257 folly::Optional
<bool> asyncEager
;
1259 // Should only be present if the frame is given by a StkPtr
1260 folly::Optional
<IRSPRelOffset
> stackOffset
;
1263 struct MOpModeData
: IRExtraData
{
1264 explicit MOpModeData(MOpMode mode
) : mode
{mode
} {}
1266 std::string
show() const { return subopToName(mode
); }
1271 struct SetOpData
: IRExtraData
{
1272 explicit SetOpData(SetOpOp op
) : op(op
) {}
1273 std::string
show() const { return subopToName(op
); }
1277 struct DecRefData
: IRExtraData
{
1278 explicit DecRefData(int locId
= -1) : locId(locId
) {}
1279 std::string
show() const {
1280 return locId
!= -1 ? folly::to
<std::string
>("Loc", locId
) : "-";
1282 int locId
; // If a known local, this has its id; -1 otherwise.
1285 struct IncDecData
: IRExtraData
{
1286 explicit IncDecData(IncDecOp op
) : op(op
) {}
1287 std::string
show() const { return subopToName(op
); }
1291 struct ResumeOffset
: IRExtraData
{
1292 explicit ResumeOffset(Offset off
) : off(off
) {}
1293 std::string
show() const { return folly::to
<std::string
>(off
); }
1297 struct GeneratorState
: IRExtraData
{
1298 explicit GeneratorState(BaseGenerator::State state
) : state(state
) {}
1299 std::string
show() const {
1300 using U
= std::underlying_type
<BaseGenerator::State
>::type
;
1301 return folly::to
<std::string
>(static_cast<U
>(state
));
1303 BaseGenerator::State state
;
1306 struct ContEnterData
: IRExtraData
{
1307 explicit ContEnterData(IRSPRelOffset spOffset
, Offset callBCOffset
,
1309 : spOffset(spOffset
)
1310 , callBCOffset(callBCOffset
)
1314 std::string
show() const {
1315 return folly::to
<std::string
>(spOffset
.offset
, ',', callBCOffset
,
1316 isAsync
? ",async" : "");
1319 IRSPRelOffset spOffset
;
1320 Offset callBCOffset
;
1324 struct NewColData
: IRExtraData
{
1325 explicit NewColData(CollectionType itype
)
1329 std::string
show() const {
1330 return collections::typeToString(type
)->toCppString();
1333 CollectionType type
;
1336 struct LocalIdRange
: IRExtraData
{
1337 LocalIdRange(uint32_t start
, uint32_t end
)
1342 std::string
show() const {
1343 return folly::format("[{}, {})", start
, end
).str();
1346 uint32_t start
, end
;
1349 struct FuncEntryData
: IRExtraData
{
1350 FuncEntryData(const Func
* func
, uint32_t argc
)
1355 std::string
show() const {
1356 return folly::format(
1367 struct CheckRefsData
: IRExtraData
{
1368 CheckRefsData(unsigned firstBit
, uint64_t mask
, uint64_t vals
)
1369 : firstBit(safe_cast
<int>(firstBit
))
1374 std::string
show() const {
1375 return folly::format("{},{},{}", firstBit
, mask
, vals
).str();
1383 struct LookupClsMethodData
: IRExtraData
{
1384 explicit LookupClsMethodData(IRSPRelOffset offset
, bool forward
, bool dynamic
)
1385 : calleeAROffset(offset
), forward(forward
), dynamic(dynamic
) {}
1387 std::string
show() const {
1388 return folly::to
<std::string
>("IRSPOff ", calleeAROffset
.offset
,
1389 forward
? " forwarded" : "",
1390 dynamic
? " dynamic" : "");
1393 // offset from caller SP to bottom of callee's ActRec
1394 IRSPRelOffset calleeAROffset
;
1400 struct ProfileCallTargetData
: IRExtraData
{
1401 ProfileCallTargetData(IRSPRelOffset bcSPOff
, rds::Handle handle
)
1406 std::string
show() const {
1407 return folly::to
<std::string
>(bcSPOff
.offset
, ",", handle
);
1410 IRSPRelOffset bcSPOff
;
1414 struct FuncGuardData
: IRExtraData
{
1415 FuncGuardData(const Func
* func
, TCA
* prologueAddrPtr
)
1417 , prologueAddrPtr(prologueAddrPtr
)
1420 std::string
show() const {
1421 return folly::sformat("{}=>{}",
1422 func
->fullName(), prologueAddrPtr
1427 TCA
* prologueAddrPtr
;
1430 struct BeginInliningData
: IRExtraData
{
1431 BeginInliningData(IRSPRelOffset offset
, const Func
* func
, int cost
)
1437 std::string
show() const {
1438 return folly::to
<std::string
>("IRSPOff ", offset
.offset
,
1439 " FUNC ", func
->fullName()->data());
1442 IRSPRelOffset offset
;
1447 struct ParamData
: IRExtraData
{
1448 explicit ParamData(int32_t paramId
) : paramId(paramId
) {}
1450 std::string
show() const {
1451 return folly::to
<std::string
>(paramId
);
1457 struct RaiseHackArrNoticeData
: IRExtraData
{
1458 explicit RaiseHackArrNoticeData(AnnotType type
)
1461 std::string
show() const {
1462 if (type
== AnnotType::VArray
) return "varray";
1463 if (type
== AnnotType::DArray
) return "darray";
1464 if (type
== AnnotType::VArrOrDArr
) return "varray_or_darray";
1471 struct RaiseHackArrParamNoticeData
: RaiseHackArrNoticeData
{
1472 RaiseHackArrParamNoticeData(AnnotType type
, int32_t id
, bool isReturn
)
1473 : RaiseHackArrNoticeData
{type
}
1475 , isReturn
{isReturn
} {}
1477 std::string
show() const {
1478 auto const typeStr
= RaiseHackArrNoticeData::show();
1479 return folly::to
<std::string
>(
1482 isReturn
? "true" : "false"
1490 struct RaiseArrayIndexNoticeData
: IRExtraData
{
1491 explicit RaiseArrayIndexNoticeData(bool isInOut
) : isInOut(isInOut
) {}
1493 std::string
show() const {
1494 if (isInOut
) return "inout";
1501 struct RaiseArrayKeyNoticeData
: IRExtraData
{
1502 explicit RaiseArrayKeyNoticeData(bool isInOut
) : isInOut(isInOut
) {}
1504 std::string
show() const {
1505 if (isInOut
) return "inout";
1512 struct AssertReason
: IRExtraData
{
1513 explicit AssertReason(Reason r
) : reason
{r
.file
, r
.line
} {}
1515 std::string
show() const {
1516 return jit::show(reason
);
1522 #define ASSERT_REASON AssertReason{Reason{__FILE__, __LINE__}}
1524 struct EndCatchData
: IRSPRelOffsetData
{
1532 explicit EndCatchData(IRSPRelOffset offset
, CatchMode mode
) :
1533 IRSPRelOffsetData
{offset
}, mode
{mode
} {}
1535 std::string
show() const {
1536 return folly::to
<std::string
>(
1537 IRSPRelOffsetData::show(), ",",
1538 mode
== UnwindOnly
? "UnwindOnly" :
1539 mode
== SwitchMode
? "SwitchMode" :
1540 mode
== BuiltinSwitchMode
?
1541 "BuiltinSwitchMode" : "SideExit");
1547 //////////////////////////////////////////////////////////////////////
1549 #define X(op, data) \
1550 template<> struct IRExtraDataType<op> { typedef data type; }; \
1551 template<> struct OpHasExtraData<op> { enum { value = 1 }; }; \
1552 static_assert(boost::has_trivial_destructor<data>::value, \
1553 "IR extra data type must be trivially destructible")
1555 X(LdBindAddr
, LdBindAddrData
);
1556 X(ProfileSwitchDest
, ProfileSwitchData
);
1557 X(JmpSwitchDest
, JmpSwitchData
);
1558 X(LdSSwitchDestFast
, LdSSwitchData
);
1559 X(LdSSwitchDestSlow
, LdSSwitchData
);
1560 X(HintLocInner
, LocalId
);
1561 X(CheckLoc
, LocalId
);
1562 X(AssertLoc
, LocalId
);
1563 X(LdLocAddr
, LocalId
);
1565 X(LdLocPseudoMain
, LocalId
);
1567 X(StLocPseudoMain
, LocalId
);
1568 X(StLocRange
, LocalIdRange
);
1569 X(LdClsRefCls
, ClsRefSlotData
);
1570 X(LdClsRefTS
, ClsRefSlotData
);
1571 X(StClsRefCls
, ClsRefSlotData
);
1572 X(StClsRefTS
, ClsRefSlotData
);
1573 X(KillClsRefCls
, ClsRefSlotData
);
1574 X(KillClsRefTS
, ClsRefSlotData
);
1575 X(IterFree
, IterId
);
1576 X(IterInit
, IterInitData
);
1577 X(IterInitK
, IterInitData
);
1578 X(IterNext
, IterData
);
1579 X(IterNextK
, IterData
);
1580 X(LIterInit
, IterInitData
);
1581 X(LIterInitK
, IterInitData
);
1582 X(LIterNext
, IterData
);
1583 X(LIterNextK
, IterData
);
1584 X(ConstructInstance
, ClassData
);
1585 X(ConstructClosure
, ClassData
);
1586 X(InitProps
, ClassData
);
1587 X(InitSProps
, ClassData
);
1588 X(NewInstanceRaw
, ClassData
);
1589 X(InitObjProps
, ClassData
);
1590 X(InitObjMemoSlots
, ClassData
);
1591 X(InstanceOfIfaceVtable
, ClassData
);
1592 X(ResolveTypeStruct
, ResolveTypeStructData
);
1593 X(ExtendsClass
, ExtendsClassData
);
1594 X(SpillFrame
, ActRecInfo
);
1595 X(CheckStk
, IRSPRelOffsetData
);
1596 X(HintStkInner
, IRSPRelOffsetData
);
1597 X(StStk
, IRSPRelOffsetData
);
1598 X(StOutValue
, IndexData
);
1599 X(CoerceStk
, CoerceStkData
);
1600 X(CoerceMem
, CoerceMemData
);
1601 X(CoerceCellToInt
, FuncArgData
);
1602 X(CoerceCellToDbl
, FuncArgData
);
1603 X(CoerceCellToBool
, FuncArgData
);
1604 X(CoerceStrToInt
, FuncArgData
);
1605 X(CoerceStrToDbl
, FuncArgData
);
1606 X(AssertStk
, IRSPRelOffsetData
);
1607 X(DefSP
, FPInvOffsetData
);
1608 X(LdStk
, IRSPRelOffsetData
);
1609 X(LdStkAddr
, IRSPRelOffsetData
);
1610 X(DefInlineFP
, DefInlineFPData
);
1611 X(BeginInlining
, BeginInliningData
);
1612 X(SyncReturnBC
, SyncReturnBCData
);
1613 X(InlineReturn
, FPRelOffsetData
);
1614 X(InlineSuspend
, FPRelOffsetData
);
1615 X(InlineReturnNoFrame
, FPRelOffsetData
);
1616 X(ReqRetranslate
, ReqRetranslateData
);
1617 X(ReqBindJmp
, ReqBindJmpData
);
1618 X(ReqRetranslateOpt
, IRSPRelOffsetData
);
1619 X(CheckCold
, TransIDData
);
1620 X(IncProfCounter
, TransIDData
);
1622 X(CallBuiltin
, CallBuiltinData
);
1623 X(CallUnpack
, CallUnpackData
);
1624 X(RetCtrl
, RetCtrlData
);
1625 X(AsyncFuncRet
, IRSPRelOffsetData
);
1626 X(AsyncFuncRetSlow
, IRSPRelOffsetData
);
1627 X(AsyncSwitchFast
, IRSPRelOffsetData
);
1628 X(LdArrFuncCtx
, IRSPRelOffsetData
);
1629 X(LdFunc
, IRSPRelOffsetData
);
1630 X(LookupClsMethod
, LookupClsMethodData
);
1631 X(LookupClsMethodCache
, ClsMethodData
);
1632 X(LdClsMethodCacheFunc
, ClsMethodData
);
1633 X(LdClsMethodCacheCls
, ClsMethodData
);
1634 X(LdClsMethodFCacheFunc
, ClsMethodData
);
1635 X(LookupClsMethodFCache
, ClsMethodData
);
1636 X(LdIfaceMethod
, IfaceMethodData
);
1637 X(LdClsCns
, ClsCnsName
);
1638 X(InitClsCns
, ClsCnsName
);
1639 X(LdSubClsCns
, LdSubClsCnsData
);
1640 X(LdSubClsCnsClsName
, LdSubClsCnsData
);
1641 X(CheckSubClsCns
, LdSubClsCnsData
);
1642 X(ProfileSubClsCns
, ProfileSubClsCnsData
);
1643 X(LdFuncCached
, FuncNameData
);
1644 X(LookupFuncCached
, FuncNameData
);
1645 X(LdObjMethod
, FuncNameData
);
1646 X(RaiseMissingArg
, FuncArgData
);
1647 X(RaiseTooManyArg
, FuncArgData
);
1648 X(ThrowParamRefMismatch
, ParamData
);
1649 X(ThrowParamRefMismatchRange
, CheckRefsData
);
1650 X(RaiseArrayIndexNotice
, RaiseArrayIndexNoticeData
);
1651 X(RaiseArrayKeyNotice
, RaiseArrayKeyNoticeData
);
1652 X(CheckClsReifiedGenericMismatch
,
1654 X(CheckFunReifiedGenericMismatch
,
1656 X(IsFunReifiedGenericsMatched
, FuncData
);
1657 X(InterpOne
, InterpOneData
);
1658 X(InterpOneCF
, InterpOneData
);
1659 X(StClosureArg
, ByteOffsetData
);
1660 X(RBTraceEntry
, RBEntryData
);
1661 X(RBTraceMsg
, RBMsgData
);
1662 X(OODeclExists
, ClassKindData
);
1663 X(NewStructArray
, NewStructData
);
1664 X(NewStructDArray
, NewStructData
);
1665 X(NewStructDict
, NewStructData
);
1666 X(NewRecord
, NewStructData
);
1667 X(AllocPackedArray
, PackedArrayData
);
1668 X(AllocVArray
, PackedArrayData
);
1669 X(AllocVecArray
, PackedArrayData
);
1670 X(NewKeysetArray
, NewKeysetArrayData
);
1671 X(InitPackedLayoutArrayLoop
, InitPackedArrayLoopData
);
1672 X(InitPackedLayoutArray
, IndexData
);
1673 X(CreateAAWH
, CreateAAWHData
);
1674 X(CountWHNotDone
, CountWHNotDoneData
);
1675 X(CheckMixedArrayOffset
, IndexData
);
1676 X(CheckDictOffset
, IndexData
);
1677 X(CheckKeysetOffset
, IndexData
);
1678 X(ElemMixedArrayK
, IndexData
);
1679 X(MixedArrayGetK
, IndexData
);
1680 X(DictGetK
, IndexData
);
1681 X(KeysetGetK
, IndexData
);
1682 X(ElemDictK
, IndexData
);
1683 X(ElemKeysetK
, IndexData
);
1684 X(ProfileArrayKind
, RDSHandleData
);
1685 X(ProfileMixedArrayOffset
, ArrayAccessProfileData
);
1686 X(ProfileDictOffset
, ArrayAccessProfileData
);
1687 X(ProfileKeysetOffset
, ArrayAccessProfileData
);
1688 X(ProfileType
, RDSHandleData
);
1689 X(ProfileFunc
, ProfileCallTargetData
);
1690 X(ProfileMethod
, ProfileCallTargetData
);
1691 X(LdRDSAddr
, RDSHandleData
);
1692 X(CheckRDSInitialized
, RDSHandleData
);
1693 X(MarkRDSInitialized
, RDSHandleData
);
1694 X(LdInitRDSAddr
, RDSHandleData
);
1695 X(BaseG
, MOpModeData
);
1696 X(PropX
, MOpModeData
);
1697 X(PropDX
, MOpModeData
);
1698 X(ElemX
, MOpModeData
);
1699 X(ElemDX
, MOpModeData
);
1700 X(ElemUX
, MOpModeData
);
1701 X(ElemArrayX
, MOpModeData
);
1702 X(ElemDictX
, MOpModeData
);
1703 X(ElemKeysetX
, MOpModeData
);
1704 X(CGetProp
, MOpModeData
);
1705 X(CGetElem
, MOpModeData
);
1706 X(ArrayGet
, MOpModeData
);
1707 X(MemoGetStaticValue
, MemoValueStaticData
);
1708 X(MemoSetStaticValue
, MemoValueStaticData
);
1709 X(MemoGetStaticCache
, MemoCacheStaticData
);
1710 X(MemoSetStaticCache
, MemoCacheStaticData
);
1711 X(MemoGetLSBValue
, MemoValueStaticData
);
1712 X(MemoSetLSBValue
, MemoValueStaticData
);
1713 X(MemoGetLSBCache
, MemoCacheStaticData
);
1714 X(MemoSetLSBCache
, MemoCacheStaticData
);
1715 X(MemoGetInstanceValue
, MemoValueInstanceData
);
1716 X(MemoSetInstanceValue
, MemoValueInstanceData
);
1717 X(MemoGetInstanceCache
, MemoCacheInstanceData
);
1718 X(MemoSetInstanceCache
, MemoCacheInstanceData
);
1719 X(SetOpProp
, SetOpData
);
1720 X(SetOpCell
, SetOpData
);
1721 X(SetOpCellVerify
, SetOpData
);
1722 X(IncDecProp
, IncDecData
);
1723 X(SetOpElem
, SetOpData
);
1724 X(IncDecElem
, IncDecData
);
1725 X(StArResumeAddr
, ResumeOffset
);
1726 X(StContArState
, GeneratorState
);
1727 X(ContEnter
, ContEnterData
);
1728 X(DbgAssertARFunc
, IRSPRelOffsetData
);
1729 X(AssertARFunc
, IRSPRelOffsetData
);
1730 X(LdARFuncPtr
, IRSPRelOffsetData
);
1731 X(LdARIsDynamic
, IRSPRelOffsetData
);
1732 X(LdARCtx
, IRSPRelOffsetData
);
1733 X(EagerSyncVMRegs
, IRSPRelOffsetData
);
1734 X(JmpSSwitchDest
, IRSPRelOffsetData
);
1735 X(DbgTrashStk
, IRSPRelOffsetData
);
1736 X(DbgTrashFrame
, IRSPRelOffsetData
);
1737 X(DbgTraceCall
, IRSPRelOffsetData
);
1738 X(LdPropAddr
, ByteOffsetData
);
1739 X(LdInitPropAddr
, ByteOffsetData
);
1740 X(NewCol
, NewColData
);
1741 X(NewColFromArray
, NewColData
);
1742 X(InitExtraArgs
, FuncEntryData
);
1743 X(CheckSurpriseFlagsEnter
, FuncEntryData
);
1744 X(CheckSurpriseAndStack
, FuncEntryData
);
1745 X(ContPreNext
, IsAsyncData
);
1746 X(ContStartedCheck
, IsAsyncData
);
1747 X(ContValid
, IsAsyncData
);
1748 X(LdContResumeAddr
, IsAsyncData
);
1749 X(LdContActRec
, IsAsyncData
);
1750 X(DecRef
, DecRefData
);
1751 X(DecRefNZ
, DecRefData
);
1752 X(LdTVAux
, LdTVAuxData
);
1753 X(CheckRefs
, CheckRefsData
);
1754 X(FuncGuard
, FuncGuardData
);
1755 X(RaiseHackArrParamNotice
, RaiseHackArrParamNoticeData
);
1756 X(RaiseHackArrPropNotice
, RaiseHackArrNoticeData
);
1757 X(DbgAssertRefCount
, AssertReason
);
1758 X(Unreachable
, AssertReason
);
1759 X(EndBlock
, AssertReason
);
1760 X(VerifyRetCallable
, ParamData
);
1761 X(VerifyRetCls
, ParamData
);
1762 X(VerifyRetFail
, ParamData
);
1763 X(VerifyRetFailHard
, ParamData
);
1764 X(VerifyReifiedLocalType
, ParamData
);
1765 X(EndCatch
, EndCatchData
);
1769 //////////////////////////////////////////////////////////////////////
1771 template<bool hasExtra
, Opcode opc
, class T
> struct AssertExtraTypes
{
1772 static void doassertx() {
1773 assertx(!"called extra on an opcode without extra data");
1775 static void doassert_same() {
1776 assertx(!"called extra on an opcode without extra data");
1780 template<Opcode opc
, class T
> struct AssertExtraTypes
<true,opc
,T
> {
1781 typedef typename IRExtraDataType
<opc
>::type ExtraType
;
1783 static void doassertx() {
1784 if (!std::is_base_of
<T
,ExtraType
>::value
) {
1785 assertx(!"extra<T> was called with an extra data "
1786 "type that doesn't match the opcode type");
1789 static void doassert_same() {
1790 if (!std::is_same
<T
,ExtraType
>::value
) {
1791 fprintf(stderr
, "opcode = %s\n", opcodeName(opc
)); \
1792 assertx(!"extra<T> was called with an extra data type that "
1793 "doesn't exactly match the opcode type");
1798 // Asserts that Opcode opc has extradata and it is of type T, or a
1799 // type derived from T.
1800 template<class T
> void assert_opcode_extra(Opcode opc
) {
1801 #define O(opcode, dstinfo, srcinfo, flags) \
1804 OpHasExtraData<opcode>::value,opcode,T \
1807 switch (opc
) { IR_OPCODES
default: not_reached(); }
1811 template<class T
> void assert_opcode_extra_same(Opcode opc
) {
1812 #define O(opcode, dstinfo, srcinfo, flags) \
1815 OpHasExtraData<opcode>::value,opcode,T \
1816 >::doassert_same(); \
1818 switch (opc
) { IR_OPCODES
default: not_reached(); }
1822 size_t hashExtra(Opcode opc
, const IRExtraData
* data
);
1823 bool equalsExtra(Opcode opc
, const IRExtraData
* a
, const IRExtraData
* b
);
1824 IRExtraData
* cloneExtra(Opcode opc
, IRExtraData
* data
, Arena
& a
);
1825 std::string
showExtra(Opcode opc
, const IRExtraData
* data
);
1827 //////////////////////////////////////////////////////////////////////