2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2014 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_
22 #include "hphp/runtime/ext/ext_generator.h"
24 #include "hphp/runtime/vm/jit/ir-opcode.h"
25 #include "hphp/runtime/vm/jit/types.h"
26 #include "hphp/runtime/vm/bytecode.h"
27 #include "hphp/runtime/vm/srckey.h"
28 #include "hphp/util/arena.h"
29 #include "hphp/util/ringbuffer.h"
31 namespace HPHP
{ namespace jit
{
33 //////////////////////////////////////////////////////////////////////
36 * Some IRInstructions with compile-time-only constants may carry
37 * along extra data in the form of one of these structures.
39 * Note that this isn't really appropriate for compile-time constants
40 * that are actually representing user values (we want them to be
41 * visible to optimization passes, allocatable to registers, etc),
42 * just compile-time metadata.
46 * - Derive from IRExtraData (for overloading purposes)
47 * - Be arena-allocatable (no non-trivial destructors)
48 * - Either CopyConstructible, or implement a clone member
49 * function that takes an arena to clone to
51 * In addition, for extra data used with a cse-able instruction:
53 * - Implement an cseEquals() member that indicates equality for CSE
55 * - Implement a cseHash() method.
57 * Finally, optionally they may implement a show() method for use in
62 * Traits that returns the type of the extra C++ data structure for a
63 * given instruction, if it has one, along with some other information
66 template<Opcode op
> struct OpHasExtraData
{ enum { value
= 0 }; };
67 template<Opcode op
> struct IRExtraDataType
;
69 //////////////////////////////////////////////////////////////////////
71 struct IRExtraData
{};
73 struct LdBindAddrData
: IRExtraData
{
74 explicit LdBindAddrData(SrcKey sk
)
78 std::string
show() const { return showShort(sk
); }
83 struct LdSSwitchData
: IRExtraData
{
85 const StringData
* str
;
89 explicit LdSSwitchData() = default;
90 LdSSwitchData(const LdSSwitchData
&) = delete;
91 LdSSwitchData
& operator=(const LdSSwitchData
&) = delete;
93 LdSSwitchData
* clone(Arena
& arena
) const {
94 LdSSwitchData
* target
= new (arena
) LdSSwitchData
;
95 target
->numCases
= numCases
;
96 target
->defaultSk
= defaultSk
;
97 target
->cases
= new (arena
) Elm
[numCases
];
98 std::copy(cases
, cases
+ numCases
, const_cast<Elm
*>(target
->cases
));
107 struct JmpSwitchData
: IRExtraData
{
108 JmpSwitchData
* clone(Arena
& arena
) const {
109 JmpSwitchData
* sd
= new (arena
) JmpSwitchData
;
111 sd
->bounded
= bounded
;
113 sd
->defaultSk
= defaultSk
;
114 sd
->targets
= new (arena
) SrcKey
[cases
];
115 std::copy(targets
, targets
+ cases
, const_cast<SrcKey
*>(sd
->targets
));
119 int64_t base
; // base of switch case
120 bool bounded
; // whether switch is bounded or not
121 int32_t cases
; // number of cases
122 SrcKey defaultSk
; // srckey of default case
123 SrcKey
* targets
; // srckeys for all targets
126 struct LocalId
: IRExtraData
{
127 explicit LocalId(uint32_t id
)
131 bool cseEquals(LocalId o
) const { return locId
== o
.locId
; }
132 size_t cseHash() const { return std::hash
<uint32_t>()(locId
); }
133 std::string
show() const { return folly::to
<std::string
>(locId
); }
138 struct IterId
: IRExtraData
{
139 explicit IterId(uint32_t id
)
143 bool cseEquals(IterId o
) const { return iterId
== o
.iterId
; }
144 size_t cseHash() const { return std::hash
<uint32_t>()(iterId
); }
145 std::string
show() const { return folly::to
<std::string
>(iterId
); }
150 struct IterData
: IRExtraData
{
151 explicit IterData(uint32_t iter
, uint32_t key
, uint32_t val
)
152 : iterId(iter
), keyId(key
), valId(val
)
154 std::string
show() const {
155 if (keyId
== -1) return folly::format("{}::{}", iterId
, valId
).str();
157 return folly::format("{}::{}::{}", iterId
, keyId
, valId
).str();
165 struct RDSHandleData
: IRExtraData
{
166 explicit RDSHandleData(RDS::Handle handle
)
170 bool cseEquals(RDSHandleData o
) const { return handle
== o
.handle
; }
171 size_t cseHash() const { return std::hash
<uint32_t>()(handle
); }
172 std::string
show() const {
173 return folly::to
<std::string
>(handle
);
179 struct ClassData
: IRExtraData
{
180 explicit ClassData(const Class
* cls
) : cls(cls
) {}
181 std::string
show() const {
182 return folly::to
<std::string
>(cls
->name()->data());
187 struct FuncData
: IRExtraData
{
188 explicit FuncData(const Func
* func
) : func(func
) {}
190 bool cseEquals(FuncData o
) const { return func
== o
.func
; }
191 size_t cseHash() const { return std::hash
<const Func
*>()(func
); }
192 std::string
show() const {
193 return folly::to
<std::string
>(func
->fullName()->data());
199 struct ClsMethodData
: IRExtraData
{
200 ClsMethodData(const StringData
* cls
, const StringData
* method
,
201 const NamedEntity
* ne
= nullptr)
207 std::string
show() const {
208 return folly::format("{}::{}", *clsName
, *methodName
).str();
211 bool cseEquals(const ClsMethodData
& b
) const {
212 // Strings are static so we can use pointer equality
213 return clsName
== b
.clsName
&& methodName
== b
.methodName
;
215 size_t cseHash() const {
216 return hash_int64_pair((uintptr_t)clsName
, (uintptr_t)methodName
);
219 const StringData
* clsName
;
220 const StringData
* methodName
;
221 const NamedEntity
* namedEntity
;
224 struct FPushCufData
: IRExtraData
{
225 FPushCufData(int32_t spOffset
, uint32_t a
, int32_t id
)
231 bool cseEquals(FPushCufData o
) const {
232 return iterId
== o
.iterId
&& args
== o
.args
;
234 size_t cseHash() const {
235 return std::hash
<uint32_t>()(iterId
) ^ std::hash
<uint32_t>()(args
);
237 std::string
show() const {
238 return folly::to
<std::string
>(spOffset
, ',', iterId
, ',', args
);
247 * Information for REQ_RETRANSLATE stubs.
249 struct ReqRetranslateData
: IRExtraData
{
252 explicit ReqRetranslateData(TransFlags trflags
)
256 std::string
show() const {
257 return folly::to
<std::string
>(trflags
.packed
);
262 * Information for REQ_BIND_JMP stubs.
264 struct ReqBindJmpData
: IRExtraData
{
268 explicit ReqBindJmpData(const SrcKey
& dest
,
269 TransFlags trflags
= TransFlags
{})
274 std::string
show() const {
275 return folly::to
<std::string
>(dest
.offset(), ',', trflags
.packed
);
280 * Compile-time metadata about an ActRec allocation.
282 struct ActRecInfo
: IRExtraData
{
284 const StringData
* invName
; // may be nullptr
287 bool isFromFPushCtor() const {
289 ar
.m_numArgsAndFlags
= numArgs
;
290 return ar
.isFromFPushCtor();
293 std::string
show() const {
295 ar
.m_numArgsAndFlags
= numArgs
;
296 return folly::to
<std::string
>(spOffset
, ',',
298 ar
.isFromFPushCtor() ? ",ctor" : "",
299 ar
.resumed() ? ",res" : "",
300 ar
.localsDecRefd() ? ",ldrd" : "",
301 invName
? " M" : "");
305 struct StackOffset
: IRExtraData
{
306 explicit StackOffset(int32_t offset
) : offset(offset
) {}
308 std::string
show() const { return folly::to
<std::string
>(offset
); }
310 bool cseEquals(StackOffset o
) const { return offset
== o
.offset
; }
311 size_t cseHash() const { return std::hash
<int32_t>()(offset
); }
316 struct PropOffset
: IRExtraData
{
317 explicit PropOffset(int32_t offset
) : offsetBytes(offset
) {}
319 std::string
show() const { return folly::to
<std::string
>(offsetBytes
); }
320 bool cseEquals(PropOffset o
) const { return offsetBytes
== o
.offsetBytes
; }
321 size_t cseHash() const { return std::hash
<int32_t>()(offsetBytes
); }
326 struct ProfileStrData
: IRExtraData
{
327 explicit ProfileStrData(const StringData
* key
)
331 std::string
show() const { return key
->data(); }
333 const StringData
* key
;
339 struct TransIDData
: IRExtraData
{
340 explicit TransIDData(TransID transId
) : transId(transId
) {}
341 std::string
show() const { return folly::to
<std::string
>(transId
); }
346 * Information needed to generate a REQ_RETRANSLATE_OPT service request.
348 struct ReqRetransOptData
: IRExtraData
{
349 explicit ReqRetransOptData(TransID transId
, SrcKey sk
)
350 : transId(transId
), sk(sk
) {}
351 std::string
show() const {
352 return folly::to
<std::string
>(transId
, ',', sk
.offset());
359 * Offset to a TypedValue from some base pointer, in bytes. (E.g. to
360 * a object property slot.)
362 struct PropByteOffset
: IRExtraData
{
363 explicit PropByteOffset(size_t offsetBytes
) : offsetBytes(offsetBytes
) {}
364 std::string
show() const { return folly::to
<std::string
>(offsetBytes
); }
369 * DefInlineFP is present when we need to create a frame for inlining. This
370 * instruction also carries some metadata used by IRBuilder to track state
371 * during an inlined call.
373 struct DefInlineFPData
: IRExtraData
{
374 std::string
show() const {
375 return folly::to
<std::string
>(
376 target
->fullName()->data(), "(),",
377 fromFPushCtor
? "ctor," : "",
386 SSATmp
* ctx
; // Ctx, Cls or Nullptr.
389 int32_t spOffset
; // offset from caller SP to callee SP
392 struct CallArrayData
: IRExtraData
{
393 explicit CallArrayData(int32_t spOffset
,
400 , destroyLocals(destroyLocals
)
403 std::string
show() const {
404 return folly::to
<std::string
>(pc
, ",", after
,
405 destroyLocals
? ",destroyLocals" : "");
408 int32_t spOffset
; // offset from StkPtr to bottom of call's ActRec+args
409 Offset pc
; // XXX why isn't this available in the marker?
410 Offset after
; // offset from unit m_bc (unlike m_soff in ActRec)
414 struct CallBuiltinData
: IRExtraData
{
415 explicit CallBuiltinData(int32_t spOffset
,
420 , destroyLocals
{destroyLocals
}
423 std::string
show() const {
424 return folly::to
<std::string
>(
426 callee
->fullName()->data(),
427 destroyLocals
? ",destroyLocals" : ""
431 int32_t spOffset
; // offset from StkPtr to last passed arg
436 struct CallData
: IRExtraData
{
437 explicit CallData(int32_t spOffset
,
443 , numParams(numParams
)
446 , destroyLocals(destroy
)
449 std::string
show() const {
450 return folly::to
<std::string
>(
451 spOffset
, ',', numParams
, ',', after
,
453 ? folly::format(",{}", callee
->fullName()->data()).str()
455 destroyLocals
? ",destroyLocals" : ""
459 int32_t spOffset
; // offset from StkPtr to bottom of call's ActRec+args
461 Offset after
; // m_soff style: offset from func->base()
462 const Func
* callee
; // nullptr if not statically known
466 struct RetCtrlData
: IRExtraData
{
467 explicit RetCtrlData(int32_t spOffset
, bool suspendingResumed
)
469 , suspendingResumed(suspendingResumed
)
472 std::string
show() const {
473 return folly::to
<std::string
>(
475 suspendingResumed
? ",suspendingResumed" : ""
479 // Adjustment we need to make to the stack pointer (for cross-tracelet ABI
480 // purposes) before returning.
483 // Indicates that the current generator frame is being suspended without
484 // decrefing locals. Used by refcount optimizer.
485 bool suspendingResumed
;
489 * Name of a class constant.
491 struct ClsCnsName
: IRExtraData
{
492 explicit ClsCnsName(const StringData
* cls
, const StringData
* cns
)
497 std::string
show() const {
498 return folly::to
<std::string
>(clsName
->data(), "::", cnsName
->data());
501 const StringData
* clsName
;
502 const StringData
* cnsName
;
506 * The name of a static local in a function.
508 struct StaticLocName
: IRExtraData
{
509 StaticLocName(const Func
* func
, const StringData
* name
)
514 std::string
show() const {
515 return folly::to
<std::string
>(
516 func
->fullName()->data(), "$", name
->data()
521 const StringData
* name
;
524 struct LdFuncCachedData
: IRExtraData
{
525 explicit LdFuncCachedData(const StringData
* name
)
529 std::string
show() const {
530 return folly::to
<std::string
>(name
->data());
533 size_t cseHash() const { return name
->hash(); }
534 bool cseEquals(const LdFuncCachedData
& o
) const {
535 return name
== o
.name
;
538 const StringData
* name
;
541 struct LdObjMethodData
: IRExtraData
{
542 explicit LdObjMethodData(int32_t offset
,
543 const StringData
* method
,
550 std::string
show() const {
551 return folly::to
<std::string
>(offset
, ',', method
->data(), ',',
552 fatal
? "fatal" : "warn");
556 const StringData
* method
;
560 struct LdFuncCachedUData
: IRExtraData
{
561 explicit LdFuncCachedUData(const StringData
* name
,
562 const StringData
* fallback
)
567 std::string
show() const {
568 return folly::to
<std::string
>(name
->data(), ',', fallback
->data());
571 size_t cseHash() const {
572 return hash_int64_pair(name
->hash(), fallback
->hash());
574 bool cseEquals(const LdFuncCachedUData
& o
) const {
575 return name
== o
.name
&& fallback
== o
.fallback
;
578 const StringData
* name
;
579 const StringData
* fallback
;
583 * The name of a class, and the expected Class* at runtime.
585 struct CheckDefinedClsData
: IRExtraData
{
586 CheckDefinedClsData(const StringData
* clsName
, const Class
* cls
)
591 std::string
show() const {
592 return folly::to
<std::string
>(clsName
->data());
595 const StringData
* clsName
;
600 * Offset and stack deltas for InterpOne.
602 struct InterpOneData
: IRExtraData
{
604 explicit LocalType(uint32_t id
= 0, Type type
= Type::Bottom
)
613 explicit InterpOneData(int32_t spOffset
)
616 , changedLocals(nullptr)
617 , smashesAllLocals(false)
620 // Delta from the StkPtr src to the top of the stack.
623 // Offset of the instruction to interpret, in the Unit indicated by
624 // the current Marker.
627 // The number of stack cells consumed and produced by the
628 // instruction, respectively. Includes ActRecs.
632 // Opcode, in case we need to fix the stack differently. Some byte-
633 // code instructions modify things below the top of the stack.
636 uint32_t nChangedLocals
;
637 LocalType
* changedLocals
;
639 bool smashesAllLocals
;
641 InterpOneData
* clone(Arena
& arena
) const {
642 auto* id
= new (arena
) InterpOneData(spOffset
);
644 id
->cellsPopped
= cellsPopped
;
645 id
->cellsPushed
= cellsPushed
;
647 id
->nChangedLocals
= nChangedLocals
;
648 id
->changedLocals
= new (arena
) LocalType
[nChangedLocals
];
649 id
->smashesAllLocals
= smashesAllLocals
;
650 std::copy(changedLocals
, changedLocals
+ nChangedLocals
, id
->changedLocals
);
654 std::string
show() const {
655 auto ret
= folly::sformat(
656 "{}: spOff:{}, bcOff:{}, popped:{}, pushed:{}",
657 opcodeToName(opcode
),
663 assert(!smashesAllLocals
|| !nChangedLocals
);
664 if (smashesAllLocals
) ret
+= ", smashes all locals";
665 if (nChangedLocals
) {
666 for (auto i
= 0; i
< nChangedLocals
; ++i
) {
667 ret
+= folly::sformat(", Local {} -> {}",
669 changedLocals
[i
].type
);
677 struct CoerceStkData
: IRExtraData
{
678 explicit CoerceStkData(int64_t off
, const Func
* f
, int64_t arg_num
)
679 : offset(off
), callee(f
), argNum(arg_num
) {}
681 std::string
show() const {
682 return folly::format(
685 callee
->name()->data(),
695 struct CoerceData
: IRExtraData
{
696 explicit CoerceData(const Func
* f
, int64_t arg_num
)
697 : callee(f
), argNum(arg_num
) {}
699 std::string
show() const {
700 return folly::format(
702 callee
->name()->data(),
711 struct RBTraceData
: IRExtraData
{
712 RBTraceData(Trace::RingBufferType t
, SrcKey sk
)
718 RBTraceData(Trace::RingBufferType t
, const StringData
* msg
)
723 assert(msg
->isStatic());
726 std::string
show() const {
727 auto const data
= msg
? msg
->data() : showShort(sk
);
728 return folly::format("{}: {}", ringbufferName(type
), data
).str();
731 Trace::RingBufferType type
;
733 const StringData
* msg
;
736 struct ClassKindData
: IRExtraData
{
737 explicit ClassKindData(ClassKind kind
): kind(uint32_t(kind
)) {}
739 std::string
show() const {
740 switch (static_cast<ClassKind
>(kind
)) {
741 case ClassKind::Class
: return "cls";
742 case ClassKind::Interface
: return "interface";
743 case ClassKind::Trait
: return "trait";
744 case ClassKind::Enum
: return "enum";
749 uint32_t kind
; // ... allows for direct usage in native_call
752 struct NewStructData
: IRExtraData
{
753 std::string
show() const;
759 struct PackedArrayData
: IRExtraData
{
760 explicit PackedArrayData(uint32_t size
) : size(size
) {}
761 std::string
show() const { return folly::format("{}", size
).str(); }
765 struct InitPackedArrayLoopData
: IRExtraData
{
766 explicit InitPackedArrayLoopData(int32_t offset
, uint32_t size
)
771 std::string
show() const {
772 return folly::format("{},{}", offset
, size
).str();
779 struct IndexData
: IRExtraData
{
780 explicit IndexData(uint32_t index
) : index(index
) {}
782 std::string
show() const { return folly::format("{}", index
).str(); }
785 struct ClsNeqData
: IRExtraData
{
786 explicit ClsNeqData(Class
* testClass
) : testClass(testClass
) {}
788 std::string
show() const {
789 return testClass
->name()->data();
792 bool cseEquals(ClsNeqData o
) const { return testClass
== o
.testClass
; }
793 size_t cseHash() const { return std::hash
<Class
*>()(testClass
); }
795 Class
* testClass
; // class we're checking equality with
798 struct MInstrAttrData
: IRExtraData
{
799 explicit MInstrAttrData(MInstrAttr mia
) : mia(mia
) {}
800 std::string
show() const {
801 using U
= std::underlying_type
<MInstrAttr
>::type
;
802 return folly::to
<std::string
>(static_cast<U
>(mia
));
807 struct SetOpData
: IRExtraData
{
808 explicit SetOpData(SetOpOp op
) : op(op
) {}
809 std::string
show() const { return subopToName(op
); }
813 struct IncDecData
: IRExtraData
{
814 explicit IncDecData(IncDecOp op
) : op(op
) {}
815 std::string
show() const { return subopToName(op
); }
819 struct ResumeOffset
: IRExtraData
{
820 explicit ResumeOffset(Offset off
) : off(off
) {}
821 std::string
show() const { return folly::to
<std::string
>(off
); }
825 struct GeneratorState
: IRExtraData
{
826 explicit GeneratorState(BaseGenerator::State state
) : state(state
) {}
827 std::string
show() const {
828 using U
= std::underlying_type
<BaseGenerator::State
>::type
;
829 return folly::to
<std::string
>(static_cast<U
>(state
));
831 BaseGenerator::State state
;
834 struct ContEnterData
: IRExtraData
{
835 explicit ContEnterData(int32_t spOffset
, Offset returnBCOffset
)
837 , returnBCOffset(returnBCOffset
)
840 std::string
show() const {
841 return folly::to
<std::string
>(spOffset
, ',', returnBCOffset
);
845 Offset returnBCOffset
;
848 //////////////////////////////////////////////////////////////////////
850 #define X(op, data) \
851 template<> struct IRExtraDataType<op> { typedef data type; }; \
852 template<> struct OpHasExtraData<op> { enum { value = 1 }; }; \
853 static_assert(boost::has_trivial_destructor<data>::value, \
854 "IR extra data type must be trivially destructible")
856 X(LdBindAddr
, LdBindAddrData
);
857 X(JmpSwitchDest
, JmpSwitchData
);
858 X(LdSSwitchDestFast
, LdSSwitchData
);
859 X(LdSSwitchDestSlow
, LdSSwitchData
);
860 X(GuardLoc
, LocalId
);
861 X(HintLocInner
, LocalId
);
862 X(CheckLoc
, LocalId
);
863 X(AssertLoc
, LocalId
);
864 X(LdLocAddr
, LocalId
);
866 X(LdLocPseudoMain
, LocalId
);
867 X(DecRefLoc
, LocalId
);
869 X(StLocPseudoMain
, LocalId
);
872 X(MIterFree
, IterId
);
873 X(CIterFree
, IterId
);
874 X(DecodeCufIter
, IterId
);
875 X(IterInit
, IterData
);
876 X(IterInitK
, IterData
);
877 X(IterNext
, IterData
);
878 X(IterNextK
, IterData
);
879 X(WIterInit
, IterData
);
880 X(WIterInitK
, IterData
);
881 X(WIterNext
, IterData
);
882 X(WIterNextK
, IterData
);
883 X(MIterInit
, IterData
);
884 X(MIterInitK
, IterData
);
885 X(MIterNext
, IterData
);
886 X(MIterNextK
, IterData
);
887 X(ConstructInstance
, ClassData
);
888 X(CheckInitProps
, ClassData
);
889 X(InitProps
, ClassData
);
890 X(CheckInitSProps
, ClassData
);
891 X(InitSProps
, ClassData
);
892 X(NewInstanceRaw
, ClassData
);
893 X(InitObjProps
, ClassData
);
894 X(CufIterSpillFrame
, FPushCufData
);
895 X(SpillFrame
, ActRecInfo
);
896 X(GuardStk
, StackOffset
);
897 X(HintStkInner
, StackOffset
);
898 X(CheckStk
, StackOffset
);
899 X(CastStk
, StackOffset
);
900 X(StStk
, StackOffset
);
901 X(CoerceStk
, CoerceStkData
);
902 X(CoerceCellToInt
, CoerceData
);
903 X(CoerceCellToDbl
, CoerceData
);
904 X(CoerceCellToBool
, CoerceData
);
905 X(CoerceStrToInt
, CoerceData
);
906 X(CoerceStrToDbl
, CoerceData
);
907 X(AssertStk
, StackOffset
);
908 X(ReDefSP
, StackOffset
);
909 X(DefSP
, StackOffset
);
910 X(ResetSP
, StackOffset
);
911 X(LdStk
, StackOffset
);
912 X(LdStkAddr
, StackOffset
);
913 X(DecRefStk
, StackOffset
);
914 X(DefInlineFP
, DefInlineFPData
);
915 X(ReqRetranslate
, ReqRetranslateData
);
916 X(ReqBindJmp
, ReqBindJmpData
);
917 X(ReqRetranslateOpt
, ReqRetransOptData
);
918 X(CheckCold
, TransIDData
);
919 X(IncProfCounter
, TransIDData
);
921 X(CallBuiltin
, CallBuiltinData
);
922 X(CallArray
, CallArrayData
);
923 X(RetCtrl
, RetCtrlData
);
924 X(LdArrFuncCtx
, StackOffset
);
925 X(LdArrFPushCuf
, StackOffset
);
926 X(LdStrFPushCuf
, StackOffset
);
927 X(LookupClsCns
, ClsCnsName
);
928 X(LookupClsMethod
, StackOffset
);
929 X(LookupClsMethodCache
, ClsMethodData
);
930 X(LdClsMethodCacheFunc
, ClsMethodData
);
931 X(LdClsMethodCacheCls
, ClsMethodData
);
932 X(LdClsMethodFCacheFunc
, ClsMethodData
);
933 X(LookupClsMethodFCache
, ClsMethodData
);
934 X(GetCtxFwdCallDyn
, ClsMethodData
);
935 X(LdStaticLocCached
, StaticLocName
);
936 X(LdFuncCached
, LdFuncCachedData
);
937 X(LdFuncCachedSafe
, LdFuncCachedData
);
938 X(LdFuncCachedU
, LdFuncCachedUData
);
939 X(LdObjMethod
, LdObjMethodData
);
940 X(InterpOne
, InterpOneData
);
941 X(InterpOneCF
, InterpOneData
);
942 X(StClosureFunc
, FuncData
);
943 X(StClosureArg
, PropByteOffset
);
944 X(RBTrace
, RBTraceData
);
945 X(OODeclExists
, ClassKindData
);
946 X(NewStructArray
, NewStructData
);
947 X(AllocPackedArray
, PackedArrayData
);
948 X(InitPackedArrayLoop
, InitPackedArrayLoopData
);
949 X(InitPackedArray
, IndexData
);
950 X(ProfilePackedArray
, RDSHandleData
);
951 X(ProfileStructArray
, RDSHandleData
);
952 X(ProfileStr
, ProfileStrData
);
953 X(LdRDSAddr
, RDSHandleData
);
954 X(ClsNeq
, ClsNeqData
);
955 X(BaseG
, MInstrAttrData
);
956 X(PropX
, MInstrAttrData
);
957 X(PropDX
, MInstrAttrData
);
958 X(ElemX
, MInstrAttrData
);
959 X(ElemDX
, MInstrAttrData
);
960 X(ElemUX
, MInstrAttrData
);
961 X(SetOpProp
, SetOpData
);
962 X(IncDecProp
, IncDecData
);
963 X(SetOpElem
, SetOpData
);
964 X(IncDecElem
, IncDecData
);
965 X(StAsyncArResume
, ResumeOffset
);
966 X(StContArResume
, ResumeOffset
);
967 X(StContArState
, GeneratorState
);
968 X(ContEnter
, ContEnterData
);
969 X(LdARFuncPtr
, StackOffset
);
970 X(EndCatch
, StackOffset
);
971 X(AdjustSP
, StackOffset
);
972 X(DbgTrashStk
, StackOffset
);
973 X(DbgTrashFrame
, StackOffset
);
974 X(LdPropAddr
, PropOffset
);
978 //////////////////////////////////////////////////////////////////////
980 template<bool hasExtra
, Opcode opc
, class T
> struct AssertExtraTypes
{
981 static void doassert() {
982 assert(!"called extra on an opcode without extra data");
984 static void doassert_same() {
985 assert(!"called extra on an opcode without extra data");
989 template<Opcode opc
, class T
> struct AssertExtraTypes
<true,opc
,T
> {
990 typedef typename IRExtraDataType
<opc
>::type ExtraType
;
992 static void doassert() {
993 if (!std::is_base_of
<T
,ExtraType
>::value
) {
994 assert(!"extra<T> was called with an extra data "
995 "type that doesn't match the opcode type");
998 static void doassert_same() {
999 if (!std::is_same
<T
,ExtraType
>::value
) {
1000 assert(!"extra<T> was called with an extra data type that "
1001 "doesn't exactly match the opcode type");
1006 // Asserts that Opcode opc has extradata and it is of type T, or a
1007 // type derived from T.
1008 template<class T
> void assert_opcode_extra(Opcode opc
) {
1009 #define O(opcode, dstinfo, srcinfo, flags) \
1012 OpHasExtraData<opcode>::value,opcode,T \
1015 switch (opc
) { IR_OPCODES
default: not_reached(); }
1019 template<class T
> void assert_opcode_extra_same(Opcode opc
) {
1020 #define O(opcode, dstinfo, srcinfo, flags) \
1023 OpHasExtraData<opcode>::value,opcode,T \
1024 >::doassert_same(); \
1026 switch (opc
) { IR_OPCODES
default: not_reached(); }
1030 size_t cseHashExtra(Opcode opc
, const IRExtraData
* data
);
1031 bool cseEqualsExtra(Opcode opc
, const IRExtraData
* a
, const IRExtraData
* b
);
1032 IRExtraData
* cloneExtra(Opcode opc
, IRExtraData
* data
, Arena
& a
);
1033 std::string
showExtra(Opcode opc
, const IRExtraData
* data
);
1035 //////////////////////////////////////////////////////////////////////