Unbox vector helper keys in translated code

Instead of creating a template specialization of each helper
that unboxes the key, do the unboxing in the TC when applicable. This
will shift a few instructions from helpers to the TC but greatly
reduces the number of helpers needed by the vector translator.
Esse commit está contido em:
bsimmers
2013-04-11 21:35:07 -07:00
commit de Sara Golemon
commit 4fd5886617
4 arquivos alterados com 227 adições e 332 exclusões
@@ -419,11 +419,9 @@ private:
void setNoMIState() { m_needMIS = false; }
SSATmp* genMisPtr();
SSATmp* getInput(unsigned i);
SSATmp* getValue() {
// If an instruction takes an rhs, it's always input 0.
const int kValIdx = 0;
return getInput(kValIdx);
}
SSATmp* getBase();
SSATmp* getKey();
SSATmp* getValue();
SSATmp* checkInitProp(SSATmp* baseAsObj,
SSATmp* propAddr,
PropInfo propOffset,
+24 -24
Ver Arquivo
@@ -439,82 +439,82 @@ O(BaseG, D(PtrToGen), C(TCA) \
O(PropX, D(PtrToGen), C(TCA) \
C(Cls) \
S(Obj,PtrToGen) \
S(Gen) \
S(Cell) \
S(PtrToCell), E|N|Mem|Refs|Er) \
O_STK(PropDX, D(PtrToGen), C(TCA) \
C(Cls) \
S(Obj,PtrToGen) \
S(Gen) \
S(Cell) \
S(PtrToCell),VProp|E|N|Mem|Refs|Er) \
O(CGetProp, D(Cell), C(TCA) \
C(Cls) \
S(Obj,PtrToGen) \
S(Gen) \
S(Cell) \
S(PtrToCell), E|N|Mem|Refs|Er) \
O_STK(VGetProp, D(BoxedCell), C(TCA) \
C(Cls) \
S(Obj,PtrToGen) \
S(Gen) \
S(Cell) \
S(PtrToCell),VProp|E|N|Mem|Refs|Er) \
O_STK(BindProp, ND, C(TCA) \
C(Cls) \
S(Obj,PtrToGen) \
S(Gen) \
S(Cell) \
S(BoxedCell) \
S(PtrToCell),VProp|E|N|Mem|Refs|Er) \
O_STK(SetProp, DVector, C(TCA) \
C(Cls) \
S(Obj,PtrToGen) \
S(Gen) \
S(Cell) \
S(Cell), VProp|E|N|Mem|Refs|Er) \
O(UnsetProp, ND, C(TCA) \
C(Cls) \
S(Obj,PtrToGen) \
S(Gen), E|N|Mem|Refs|Er) \
S(Cell), E|N|Mem|Refs|Er) \
O_STK(SetOpProp, D(Cell), C(TCA) \
S(Obj,PtrToGen) \
S(Gen) \
S(Cell) \
S(Cell) \
S(PtrToCell),VProp|E|N|Mem|Refs|Er) \
O_STK(IncDecProp, D(Cell), C(TCA) \
C(Cls) \
S(Obj,PtrToGen) \
S(Gen) \
S(Cell) \
S(PtrToCell),VProp|E|N|Mem|Refs|Er) \
O(EmptyProp, D(Bool), C(TCA) \
C(Cls) \
S(Obj,PtrToGen) \
S(Gen), E|N|Mem|Refs|Er) \
S(Cell), E|N|Mem|Refs|Er) \
O(IssetProp, D(Bool), C(TCA) \
C(Cls) \
S(Obj,PtrToGen) \
S(Gen), E|N|Mem|Refs|Er) \
S(Cell), E|N|Mem|Refs|Er) \
O(ElemX, D(PtrToGen), C(TCA) \
S(PtrToGen) \
S(Gen) \
S(Cell) \
S(PtrToCell), E|N|Mem|Refs|Er) \
O_STK(ElemDX, D(PtrToGen), C(TCA) \
S(PtrToGen) \
S(Gen) \
S(Cell) \
S(PtrToCell),VElem|E|N|Mem|Refs|Er) \
O_STK(ElemUX, D(PtrToGen), C(TCA) \
S(PtrToGen) \
S(Gen) \
S(Cell) \
S(PtrToCell),VElem|E|N|Mem|Refs|Er) \
O(ArrayGet, D(Cell), C(TCA) \
S(Arr) \
S(Int,Str), E|N|PRc|Refs|Mem|Er) \
O(CGetElem, D(Cell), C(TCA) \
S(PtrToGen) \
S(Gen) \
S(Cell) \
S(PtrToCell), E|N|Mem|Refs|Er) \
O_STK(VGetElem, D(BoxedCell), C(TCA) \
S(PtrToGen) \
S(Gen) \
S(Cell) \
S(PtrToCell),VElem|E|N|Mem|Refs|Er) \
O_STK(BindElem, ND, C(TCA) \
S(PtrToGen) \
S(Gen) \
S(Cell) \
S(BoxedCell) \
S(PtrToCell),VElem|E|N|Mem|Refs|Er) \
O(ArraySet, D(Arr), C(TCA) \
@@ -528,22 +528,22 @@ O(ArraySetRef, ND, C(TCA) \
S(BoxedArr),E|N|PRc|CRc|Refs|Mem|K) \
O_STK(SetElem, DVector, C(TCA) \
S(PtrToGen) \
S(Gen) \
S(Cell) \
S(Cell), VElem|E|N|Mem|Refs|Er) \
O_STK(UnsetElem, ND, C(TCA) \
S(PtrToGen) \
S(Gen), VElem|E|N|Mem|Refs|Er) \
S(Cell), VElem|E|N|Mem|Refs|Er) \
O_STK(SetOpElem, D(Cell), C(TCA) \
S(PtrToGen) \
S(Gen) \
S(Cell) \
S(Cell) \
S(PtrToCell),VElem|E|N|Mem|Refs|Er) \
O_STK(IncDecElem, D(Cell), C(TCA) \
S(PtrToGen) \
S(Gen) \
S(Cell) \
S(PtrToCell),VElem|E|N|Mem|Refs|Er) \
O_STK(SetNewElem, DVector, S(PtrToGen) \
S(Gen), VElem|E|N|Mem|Refs|Er) \
S(Cell), VElem|E|N|Mem|Refs|Er) \
O_STK(BindNewElem, ND, S(PtrToGen) \
S(BoxedCell) \
S(PtrToCell),VElem|E|N|Mem|Refs|Er) \
@@ -552,11 +552,11 @@ O(ArrayIsset, D(Bool), C(TCA) \
S(Int,Str), E|N|Mem|Refs|Er) \
O(IssetElem, D(Bool), C(TCA) \
S(PtrToGen) \
S(Gen) \
S(Cell) \
S(PtrToCell), E|N|Mem|Refs|Er) \
O(EmptyElem, D(Bool), C(TCA) \
S(PtrToGen) \
S(Gen) \
S(Cell) \
S(PtrToCell), E|N|Mem|Refs|Er) \
O(IncStat, ND, C(Int) C(Int) C(Bool), E|Mem) \
O(IncStatGrouped, ND, CStr CStr C(Int), E|N|Mem) \
@@ -106,13 +106,10 @@ inline unsigned buildBitmask(T c, Args... args) {
// both, respectively.
static KeyType getKeyType(const SSATmp* key, bool nonLitStr,
bool nonLitInt) {
assert(key->getType().isKnownDataType());
auto keyType = key->getType();
assert(keyType.notBoxed());
assert(keyType.isKnownDataType() || keyType.equals(Type::Cell));
if (key->isBoxed()) {
// Variants can change types at arbitrary times, so don't try to
// pass them in registers.
return AnyKey;
}
if ((key->isConst() || nonLitStr) && key->isString()) {
return StrKey;
} else if ((key->isConst() || nonLitInt) && key->isA(Type::Int)) {
@@ -145,24 +142,6 @@ static inline TypedValue* keyPtr(TypedValue& key) {
}
}
template<KeyType kt, bool isRef>
static inline TypedValue* unbox(TypedValue* k) {
if (isRef) {
if (kt == AnyKey) {
assert(k->m_type == KindOfRef);
k = k->m_data.pref->tv();
assert(k->m_type != KindOfRef);
} else {
assert(k->m_type == keyDataType(kt) ||
(IS_STRING_TYPE(k->m_type) && IS_STRING_TYPE(keyDataType(kt))));
return reinterpret_cast<TypedValue*>(k->m_data.num);
}
} else if (kt == AnyKey) {
assert(k->m_type != KindOfRef);
}
return k;
}
} } }
#endif
+197 -279
Ver Arquivo
@@ -481,6 +481,28 @@ void HhbcTranslator::VectorTranslator::numberStackInputs() {
}
}
SSATmp* HhbcTranslator::VectorTranslator::getBase() {
assert(m_iInd == m_mii.valCount());
return getInput(m_iInd);
}
SSATmp* HhbcTranslator::VectorTranslator::getKey() {
SSATmp* key = getInput(m_iInd);
auto keyType = key->getType();
assert(keyType.isBoxed() || keyType.notBoxed());
if (keyType.isBoxed()) {
key = m_tb.gen(LdRef, Type::Cell, key);
}
return key;
}
SSATmp* HhbcTranslator::VectorTranslator::getValue() {
// If an instruction takes an rhs, it's always input 0.
assert(m_mii.valCount() == 1);
const int kValIdx = 0;
return getInput(kValIdx);
}
SSATmp* HhbcTranslator::VectorTranslator::getInput(unsigned i) {
const DynLocation& dl = *m_ni.inputs[i];
const Location& l = dl.location;
@@ -553,13 +575,13 @@ void HhbcTranslator::VectorTranslator::emitBaseLCR() {
mcodeMaybePropName(m_ni.immVecM[0])) ||
isSimpleArrayOp()) {
// In these cases we can pass the base by value, after unboxing if needed.
m_base = m_tb.gen(Unbox, failedRef, getInput(m_iInd));
m_base = m_tb.gen(Unbox, failedRef, getBase());
assert(m_base->isA(baseType.unbox()));
} else {
// Everything else is passed by reference. We don't have to worry about
// unboxing here, since all the generic helpers understand boxed bases.
if (baseType.isBoxed()) {
SSATmp* box = getInput(m_iInd);
SSATmp* box = getBase();
assert(box->isA(Type::BoxedCell));
// Guard that the inner type hasn't changed
m_tb.gen(LdRef, baseType.innerType(), failedRef, box);
@@ -663,7 +685,7 @@ void HhbcTranslator::VectorTranslator::emitBaseG() {
using namespace VectorHelpers;
static const OpFunc opFuncs[] = {baseG, baseGW, baseGD, baseGWD};
OpFunc opFunc = opFuncs[mia & MIA_base];
SSATmp* gblName = getInput(m_iInd);
SSATmp* gblName = getBase();
m_ht.spillStack();
m_base = m_tb.gen(BaseG,
m_tb.genDefConst((TCA)opFunc),
@@ -673,7 +695,7 @@ void HhbcTranslator::VectorTranslator::emitBaseG() {
void HhbcTranslator::VectorTranslator::emitBaseS() {
const int kClassIdx = m_ni.inputs.size() - 1;
SSATmp* key = getInput(m_iInd);
SSATmp* key = getKey();
SSATmp* clsRef = getInput(kClassIdx);
m_base = m_tb.gen(LdClsPropAddr,
clsRef,
@@ -725,36 +747,25 @@ void HhbcTranslator::VectorTranslator::emitProp() {
}
}
template <bool unboxKey, MInstrAttr attrs, bool isObj>
template <MInstrAttr attrs, bool isObj>
static inline TypedValue* propImpl(Class* ctx, TypedValue* base,
TypedValue keyVal, MInstrState* mis) {
TypedValue* key = unbox<AnyKey, unboxKey>(&keyVal);
return Prop<WDU(attrs), isObj>(
mis->tvScratch, mis->tvRef, ctx, base, key);
mis->tvScratch, mis->tvRef, ctx, base, &keyVal);
}
#define HELPER_TABLE(m) \
/* name unboxKey attrs isObj */ \
m(propC, false, None, false) \
m(propCD, false, Define, false) \
m(propCDO, false, Define, true) \
m(propCO, false, None, true) \
m(propCU, false, Unset, false) \
m(propCUO, false, Unset, true) \
m(propCW, false, Warn, false) \
m(propCWD, false, WarnDefine, false) \
m(propCWDO, false, WarnDefine, true) \
m(propCWO, false, Warn, true) \
m(propL, true, None, false) \
m(propLD, true, Define, false) \
m(propLDO, true, Define, true) \
m(propLO, true, None, true) \
m(propLU, true, Unset, false) \
m(propLUO, true, Unset, true) \
m(propLW, true, Warn, false) \
m(propLWD, true, WarnDefine, false) \
m(propLWDO, true, WarnDefine, true) \
m(propLWO, true, Warn, true)
#define HELPER_TABLE(m) \
/* name attrs isObj */ \
m(propC, None, false) \
m(propCD, Define, false) \
m(propCDO, Define, true) \
m(propCO, None, true) \
m(propCU, Unset, false) \
m(propCUO, Unset, true) \
m(propCW, Warn, false) \
m(propCWD, WarnDefine, false) \
m(propCWDO, WarnDefine, true) \
m(propCWO, Warn, true)
#define PROP(nm, ...) \
TypedValue* nm(Class* ctx, TypedValue* base, TypedValue key, \
@@ -776,8 +787,8 @@ void HhbcTranslator::VectorTranslator::emitPropGeneric() {
}
typedef TypedValue* (*OpFunc)(Class*, TypedValue*, TypedValue, MInstrState*);
SSATmp* key = getInput(m_iInd);
BUILD_OPTAB(key->isBoxed(), mia, m_base->isA(Type::Obj));
SSATmp* key = getKey();
BUILD_OPTAB(mia, m_base->isA(Type::Obj));
m_ht.spillStack();
if (mia & Define) {
m_base = genStk(PropDX, cns((TCA)opFunc), CTX(), m_base, key, genMisPtr());
@@ -801,7 +812,7 @@ SSATmp* HhbcTranslator::VectorTranslator::checkInitProp(
PropInfo propInfo,
bool doWarn,
bool doDefine) {
SSATmp* key = getInput(m_iInd);
SSATmp* key = getKey();
assert(key->isA(Type::StaticStr));
assert(baseAsObj->isA(Type::Obj));
assert(propAddr->getType().isPtr());
@@ -922,12 +933,11 @@ void HhbcTranslator::VectorTranslator::emitPropSpecialized(
assert(m_base->getType().isPtr());
}
template <KeyType keyType, bool unboxKey, bool warn, bool define, bool reffy,
template <KeyType keyType, bool warn, bool define, bool reffy,
bool unset>
static inline TypedValue* elemImpl(TypedValue* base, TypedValue keyVal,
MInstrState* mis) {
TypedValue* key = keyPtr<keyType>(keyVal);
key = unbox<keyType, unboxKey>(key);
if (unset) {
return ElemU<keyType>(mis->tvScratch, mis->tvRef, base, key);
} else if (define) {
@@ -938,55 +948,34 @@ static inline TypedValue* elemImpl(TypedValue* base, TypedValue keyVal,
}
}
#define HELPER_TABLE(m) \
/* name hot key unboxKey attrs */ \
m(elemC, , AnyKey, false, None) \
m(elemCD, , AnyKey, false, Define) \
m(elemCDR, , AnyKey, false, DefineReffy) \
m(elemCU, , AnyKey, false, Unset) \
m(elemCW, , AnyKey, false, Warn) \
m(elemCWD, , AnyKey, false, WarnDefine) \
m(elemCWDR, , AnyKey, false, WarnDefineReffy) \
m(elemI, , IntKey, false, None) \
m(elemID, HOT_FUNC_VM, IntKey, false, Define) \
m(elemIDR, , IntKey, false, DefineReffy) \
m(elemIU, , IntKey, false, Unset) \
m(elemIW, , IntKey, false, Warn) \
m(elemIWD, , IntKey, false, WarnDefine) \
m(elemIWDR, , IntKey, false, WarnDefineReffy) \
m(elemL, , AnyKey, true, None) \
m(elemLD, , AnyKey, true, Define) \
m(elemLDR, , AnyKey, true, DefineReffy) \
m(elemLU, , AnyKey, true, Unset) \
m(elemLW, , AnyKey, true, Warn) \
m(elemLWD, , AnyKey, true, WarnDefine) \
m(elemLWDR, , AnyKey, true, WarnDefineReffy) \
m(elemLI, , IntKey, true, None) \
m(elemLID, , IntKey, true, Define) \
m(elemLIDR, , IntKey, true, DefineReffy) \
m(elemLIU, , IntKey, true, Unset) \
m(elemLIW, , IntKey, true, Warn) \
m(elemLIWD, , IntKey, true, WarnDefine) \
m(elemLIWDR, , IntKey, true, WarnDefineReffy) \
m(elemLS, , StrKey, true, None) \
m(elemLSD, , StrKey, true, Define) \
m(elemLSDR, , StrKey, true, DefineReffy) \
m(elemLSU, , StrKey, true, Unset) \
m(elemLSW, , StrKey, true, Warn) \
m(elemLSWD, , StrKey, true, WarnDefine) \
m(elemLSWDR, , StrKey, true, WarnDefineReffy) \
m(elemS, HOT_FUNC_VM, StrKey, false, None) \
m(elemSD, HOT_FUNC_VM, StrKey, false, Define) \
m(elemSDR, , StrKey, false, DefineReffy) \
m(elemSU, , StrKey, false, Unset) \
m(elemSW, HOT_FUNC_VM, StrKey, false, Warn) \
m(elemSWD, , StrKey, false, WarnDefine) \
m(elemSWDR, , StrKey, false, WarnDefineReffy)
#define HELPER_TABLE(m) \
/* name hot key attrs */ \
m(elemC, , AnyKey, None) \
m(elemCD, , AnyKey, Define) \
m(elemCDR, , AnyKey, DefineReffy) \
m(elemCU, , AnyKey, Unset) \
m(elemCW, , AnyKey, Warn) \
m(elemCWD, , AnyKey, WarnDefine) \
m(elemCWDR, , AnyKey, WarnDefineReffy) \
m(elemI, , IntKey, None) \
m(elemID, HOT_FUNC_VM, IntKey, Define) \
m(elemIDR, , IntKey, DefineReffy) \
m(elemIU, , IntKey, Unset) \
m(elemIW, , IntKey, Warn) \
m(elemIWD, , IntKey, WarnDefine) \
m(elemIWDR, , IntKey, WarnDefineReffy) \
m(elemS, HOT_FUNC_VM, StrKey, None) \
m(elemSD, HOT_FUNC_VM, StrKey, Define) \
m(elemSDR, , StrKey, DefineReffy) \
m(elemSU, , StrKey, Unset) \
m(elemSW, HOT_FUNC_VM, StrKey, Warn) \
m(elemSWD, , StrKey, WarnDefine) \
m(elemSWDR, , StrKey, WarnDefineReffy)
#define ELEM(nm, hot, keyType, unboxKey, attrs) \
#define ELEM(nm, hot, keyType, attrs) \
hot \
TypedValue* nm(TypedValue* base, TypedValue key, MInstrState* mis) { \
return elemImpl<keyType, unboxKey, WDRU(attrs)>(base, key, mis); \
return elemImpl<keyType, WDRU(attrs)>(base, key, mis); \
}
namespace VectorHelpers {
HELPER_TABLE(ELEM)
@@ -996,7 +985,7 @@ HELPER_TABLE(ELEM)
void HhbcTranslator::VectorTranslator::emitElem() {
MemberCode mCode = m_ni.immVecM[m_mInd];
MInstrAttr mia = MInstrAttr(m_mii.getAttr(mCode) & MIA_intermediate);
SSATmp* key = getInput(m_iInd);
SSATmp* key = getKey();
const bool unset = mia & Unset;
const bool define = mia & Define;
@@ -1020,7 +1009,7 @@ void HhbcTranslator::VectorTranslator::emitElem() {
}
typedef TypedValue* (*OpFunc)(TypedValue*, TypedValue, MInstrState*);
BUILD_OPTAB_HOT(getKeyTypeIS(key), key->isBoxed(), mia);
BUILD_OPTAB_HOT(getKeyTypeIS(key), mia);
m_ht.spillStack();
if (define || unset) {
m_base = genStk(define ? ElemDX : ElemUX, cns((TCA)opFunc), m_base,
@@ -1104,12 +1093,11 @@ void HhbcTranslator::VectorTranslator::emitFinalMOp() {
}
}
template <KeyType keyType, bool unboxKey, bool isObj>
template <KeyType keyType, bool isObj>
static inline TypedValue cGetPropImpl(Class* ctx, TypedValue* base,
TypedValue keyVal, MInstrState* mis) {
TypedValue result;
TypedValue* key = keyPtr<keyType>(keyVal);
key = unbox<keyType, unboxKey>(key);
base = Prop<true, false, false, isObj, keyType>(
result, mis->tvRef, ctx, base, key);
if (base != &result) {
@@ -1122,16 +1110,12 @@ static inline TypedValue cGetPropImpl(Class* ctx, TypedValue* base,
return result;
}
#define HELPER_TABLE(m) \
/* name hot key unboxKey isObj */ \
m(cGetPropC, , AnyKey, false, false) \
m(cGetPropCO, , AnyKey, false, true) \
m(cGetPropL, , AnyKey, true, false) \
m(cGetPropLO, , AnyKey, true, true) \
m(cGetPropLS, , StrKey, true, false) \
m(cGetPropLSO, , StrKey, true, true) \
m(cGetPropS, , StrKey, false, false) \
m(cGetPropSO, HOT_FUNC_VM, StrKey, false, true)
#define HELPER_TABLE(m) \
/* name hot key isObj */ \
m(cGetPropC, , AnyKey, false) \
m(cGetPropCO, , AnyKey, true) \
m(cGetPropS, , StrKey, false) \
m(cGetPropSO, HOT_FUNC_VM, StrKey, true)
#define PROP(nm, hot, ...) \
hot \
@@ -1159,19 +1143,18 @@ void HhbcTranslator::VectorTranslator::emitCGetProp() {
}
typedef TypedValue (*OpFunc)(Class*, TypedValue*, TypedValue, MInstrState*);
SSATmp* key = getInput(m_iInd);
BUILD_OPTAB_HOT(getKeyTypeS(key), key->isBoxed(), m_base->isA(Type::Obj));
SSATmp* key = getKey();
BUILD_OPTAB_HOT(getKeyTypeS(key), m_base->isA(Type::Obj));
m_ht.spillStack();
m_result = m_tb.gen(CGetProp, cns((TCA)opFunc), CTX(),
m_base, key, genMisPtr());
}
#undef HELPER_TABLE
template <KeyType keyType, bool unboxKey, bool isObj>
template <KeyType keyType, bool isObj>
static inline TypedValue vGetPropImpl(Class* ctx, TypedValue* base,
TypedValue keyVal, MInstrState* mis) {
TypedValue* key = keyPtr<keyType>(keyVal);
key = unbox<keyType, unboxKey>(key);
base = VM::Prop<false, true, false, isObj, keyType>(
mis->tvScratch, mis->tvRef, ctx, base, key);
@@ -1188,16 +1171,12 @@ static inline TypedValue vGetPropImpl(Class* ctx, TypedValue* base,
}
}
#define HELPER_TABLE(m) \
/* name hot key unboxKey isObj */ \
m(vGetPropC, , AnyKey, false, false) \
m(vGetPropCO, , AnyKey, false, true) \
m(vGetPropL, , AnyKey, true, false) \
m(vGetPropLO, , AnyKey, true, true) \
m(vGetPropLS, , StrKey, true, false) \
m(vGetPropLSO, , StrKey, true, true) \
m(vGetPropS, , StrKey, false, false) \
m(vGetPropSO, HOT_FUNC_VM, StrKey, false, true)
#define HELPER_TABLE(m) \
/* name hot key isObj */ \
m(vGetPropC, , AnyKey, false) \
m(vGetPropCO, , AnyKey, true) \
m(vGetPropS, , StrKey, false) \
m(vGetPropSO, HOT_FUNC_VM, StrKey, true)
#define PROP(nm, hot, ...) \
hot \
@@ -1211,32 +1190,27 @@ HELPER_TABLE(PROP)
#undef PROP
void HhbcTranslator::VectorTranslator::emitVGetProp() {
SSATmp* key = getInput(m_iInd);
SSATmp* key = getKey();
typedef TypedValue (*OpFunc)(Class*, TypedValue*, TypedValue, MInstrState*);
BUILD_OPTAB_HOT(getKeyTypeS(key), key->isBoxed(), m_base->isA(Type::Obj));
BUILD_OPTAB_HOT(getKeyTypeS(key), m_base->isA(Type::Obj));
m_ht.spillStack();
m_result = genStk(VGetProp, cns((TCA)opFunc), CTX(),
m_base, key, genMisPtr());
}
#undef HELPER_TABLE
template <bool unboxKey, bool useEmpty, bool isObj>
template <bool useEmpty, bool isObj>
static inline bool issetEmptyPropImpl(Class* ctx, TypedValue* base,
TypedValue keyVal) {
TypedValue* key = unbox<AnyKey, unboxKey>(&keyVal);
return VM::IssetEmptyProp<useEmpty, isObj>(ctx, base, key);
return VM::IssetEmptyProp<useEmpty, isObj>(ctx, base, &keyVal);
}
#define HELPER_TABLE(m) \
/* name unboxKey useEmpty isObj */ \
m(issetPropC, false, false, false) \
m(issetPropCE, false, true, false) \
m(issetPropCEO, false, true, true) \
m(issetPropCO, false, false, true) \
m(issetPropL, true, false, false) \
m(issetPropLE, true, true, false) \
m(issetPropLEO, true, true, true) \
m(issetPropLO, true, false, true)
#define HELPER_TABLE(m) \
/* name useEmpty isObj */ \
m(issetPropC, false, false) \
m(issetPropCE, true, false) \
m(issetPropCEO, true, true) \
m(issetPropCO, false, true)
#define ISSET(nm, ...) \
/* This returns int64_t to ensure all 64 bits of rax are valid */ \
@@ -1249,9 +1223,9 @@ HELPER_TABLE(ISSET)
#undef ISSET
void HhbcTranslator::VectorTranslator::emitIssetEmptyProp(bool isEmpty) {
SSATmp* key = getInput(m_iInd);
SSATmp* key = getKey();
typedef uint64_t (*OpFunc)(Class*, TypedValue*, TypedValue);
BUILD_OPTAB(key->isBoxed(), isEmpty, m_base->isA(Type::Obj));
BUILD_OPTAB(isEmpty, m_base->isA(Type::Obj));
m_ht.spillStack();
m_result = m_tb.gen(isEmpty ? EmptyProp : IssetProp, cns((TCA)opFunc),
CTX(), m_base, key);
@@ -1266,20 +1240,17 @@ void HhbcTranslator::VectorTranslator::emitEmptyProp() {
emitIssetEmptyProp(true);
}
template <bool unboxKey, bool isObj>
template <bool isObj>
static inline TypedValue setPropImpl(Class* ctx, TypedValue* base,
TypedValue keyVal, Cell val) {
TypedValue* key = unbox<AnyKey, unboxKey>(&keyVal);
VM::SetProp<true, isObj>(ctx, base, key, &val);
VM::SetProp<true, isObj>(ctx, base, &keyVal, &val);
return val;
}
#define HELPER_TABLE(m) \
/* name unboxKey isObj */ \
m(setPropC, false, false) \
m(setPropCO, false, true) \
m(setPropL, true, false) \
m(setPropLO, true, true)
#define HELPER_TABLE(m) \
/* name isObj */ \
m(setPropC, false) \
m(setPropCO, true)
#define PROP(nm, ...) \
TypedValue nm(Class* ctx, TypedValue* base, TypedValue key, Cell val) { \
@@ -1311,8 +1282,8 @@ void HhbcTranslator::VectorTranslator::emitSetProp() {
// Emit the appropriate helper call.
typedef TypedValue (*OpFunc)(Class*, TypedValue*, TypedValue, Cell);
SSATmp* key = getInput(m_iInd);
BUILD_OPTAB(key->isBoxed(), m_base->isA(Type::Obj));
SSATmp* key = getKey();
BUILD_OPTAB(m_base->isA(Type::Obj));
m_ht.spillStack();
SSATmp* result = genStk(SetProp, cns((TCA)opFunc), CTX(),
m_base, key, value);
@@ -1321,24 +1292,21 @@ void HhbcTranslator::VectorTranslator::emitSetProp() {
}
#undef HELPER_TABLE
template <bool unboxKey, SetOpOp op, bool isObj>
template <SetOpOp op, bool isObj>
static inline TypedValue setOpPropImpl(TypedValue* base, TypedValue keyVal,
Cell val, MInstrState* mis) {
TypedValue* key = unbox<AnyKey, unboxKey>(&keyVal);
TypedValue* result = VM::SetOpProp<isObj>(
mis->tvScratch, mis->tvRef, mis->ctx, op, base, key, &val);
mis->tvScratch, mis->tvRef, mis->ctx, op, base, &keyVal, &val);
TypedValue ret;
tvReadCell(result, &ret);
return ret;
}
#define OPPROP_TABLE(m, nm, op) \
/* name unboxKey op isObj */ \
m(nm##op##PropC, false, op, false) \
m(nm##op##PropCO, false, op, true) \
m(nm##op##PropL, true, op, false) \
m(nm##op##PropLO, true, op, true)
#define OPPROP_TABLE(m, nm, op) \
/* name op isObj */ \
m(nm##op##PropC, op, false) \
m(nm##op##PropCO, op, true)
#define HELPER_TABLE(m, op) OPPROP_TABLE(m, setOp, SetOp##op)
#define SETOP(nm, ...) \
@@ -1355,12 +1323,12 @@ SETOP_OPS
void HhbcTranslator::VectorTranslator::emitSetOpProp() {
SetOpOp op = SetOpOp(m_ni.imm[0].u_OA);
SSATmp* key = getInput(m_iInd);
SSATmp* key = getKey();
SSATmp* value = getValue();
typedef TypedValue (*OpFunc)(TypedValue*, TypedValue,
Cell, MInstrState*);
# define SETOP_OP(op, bcOp) HELPER_TABLE(FILL_ROW, op)
BUILD_OPTAB_ARG(SETOP_OPS, key->isBoxed(), op, m_base->isA(Type::Obj));
BUILD_OPTAB_ARG(SETOP_OPS, op, m_base->isA(Type::Obj));
# undef SETOP_OP
m_tb.genStRaw(m_misBase, RawMemSlot::MisCtx, CTX());
m_ht.spillStack();
@@ -1369,14 +1337,13 @@ void HhbcTranslator::VectorTranslator::emitSetOpProp() {
}
#undef HELPER_TABLE
template <bool unboxKey, IncDecOp op, bool isObj>
template <IncDecOp op, bool isObj>
static inline TypedValue incDecPropImpl(Class* ctx, TypedValue* base,
TypedValue keyVal, MInstrState* mis) {
TypedValue* key = unbox<AnyKey, unboxKey>(&keyVal);
TypedValue result;
result.m_type = KindOfUninit;
VM::IncDecProp<true, isObj>(
mis->tvScratch, mis->tvRef, ctx, op, base, key, result);
mis->tvScratch, mis->tvRef, ctx, op, base, &keyVal, result);
assert(result.m_type != KindOfRef);
return result;
}
@@ -1397,10 +1364,10 @@ INCDEC_OPS
void HhbcTranslator::VectorTranslator::emitIncDecProp() {
IncDecOp op = IncDecOp(m_ni.imm[0].u_OA);
SSATmp* key = getInput(m_iInd);
SSATmp* key = getKey();
typedef TypedValue (*OpFunc)(Class*, TypedValue*, TypedValue, MInstrState*);
# define INCDEC_OP(op) HELPER_TABLE(FILL_ROW, op)
BUILD_OPTAB_ARG(INCDEC_OPS, key->isBoxed(), op, m_base->isA(Type::Obj));
BUILD_OPTAB_ARG(INCDEC_OPS, op, m_base->isA(Type::Obj));
# undef INCDEC_OP
m_ht.spillStack();
m_result =
@@ -1408,23 +1375,20 @@ void HhbcTranslator::VectorTranslator::emitIncDecProp() {
}
#undef HELPER_TABLE
template <bool unboxKey, bool isObj>
template <bool isObj>
static inline void bindPropImpl(Class* ctx, TypedValue* base, TypedValue keyVal,
RefData* val, MInstrState* mis) {
TypedValue* key = unbox<AnyKey, unboxKey>(&keyVal);
TypedValue* prop = VM::Prop<false, true, false, isObj>(
mis->tvScratch, mis->tvRef, ctx, base, key);
mis->tvScratch, mis->tvRef, ctx, base, &keyVal);
if (!(prop == &mis->tvScratch && prop->m_type == KindOfUninit)) {
tvBindRef(val, prop);
}
}
#define HELPER_TABLE(m) \
/* name unboxKey isObj */ \
m(bindPropC, false, false) \
m(bindPropCO, false, true) \
m(bindPropL, true, false) \
m(bindPropLO, true, true)
#define HELPER_TABLE(m) \
/* name isObj */ \
m(bindPropC, false) \
m(bindPropCO, true)
#define PROP(nm, ...) \
void nm(Class* ctx, TypedValue* base, TypedValue key, \
@@ -1437,30 +1401,27 @@ HELPER_TABLE(PROP)
#undef PROP
void HhbcTranslator::VectorTranslator::emitBindProp() {
SSATmp* key = getInput(m_iInd);
SSATmp* key = getKey();
SSATmp* box = getValue();
typedef void (*OpFunc)(Class*, TypedValue*, TypedValue*, RefData*,
MInstrState*);
BUILD_OPTAB(key->isBoxed(), m_base->isA(Type::Obj));
BUILD_OPTAB(m_base->isA(Type::Obj));
m_ht.spillStack();
genStk(BindProp, cns((TCA)opFunc), CTX(), m_base, key, box, genMisPtr());
m_result = box;
}
#undef HELPER_TABLE
template <bool unboxKey, bool isObj>
template <bool isObj>
static inline void unsetPropImpl(Class* ctx, TypedValue* base,
TypedValue keyVal) {
TypedValue* key = unbox<AnyKey, unboxKey>(&keyVal);
VM::UnsetProp<isObj>(ctx, base, key);
VM::UnsetProp<isObj>(ctx, base, &keyVal);
}
#define HELPER_TABLE(m) \
/* name unboxKey isObj */ \
m(unsetPropC, false, false) \
m(unsetPropCO, false, true) \
m(unsetPropL, true, false) \
m(unsetPropLO, true, true)
#define HELPER_TABLE(m) \
/* name isObj */ \
m(unsetPropC, false) \
m(unsetPropCO, true)
#define PROP(nm, ...) \
static void nm(Class* ctx, TypedValue* base, TypedValue key) { \
@@ -1472,7 +1433,7 @@ HELPER_TABLE(PROP)
#undef PROP
void HhbcTranslator::VectorTranslator::emitUnsetProp() {
SSATmp* key = getInput(m_iInd);
SSATmp* key = getKey();
if (m_base->getType().strip().not(Type::Obj)) {
// Noop
@@ -1480,7 +1441,7 @@ void HhbcTranslator::VectorTranslator::emitUnsetProp() {
}
typedef void (*OpFunc)(Class*, TypedValue*, TypedValue);
BUILD_OPTAB(key->isBoxed(), m_base->isA(Type::Obj));
BUILD_OPTAB(m_base->isA(Type::Obj));
m_tb.gen(UnsetProp, cns((TCA)opFunc), CTX(), m_base, key);
}
#undef HELPER_TABLE
@@ -1552,12 +1513,11 @@ void HhbcTranslator::VectorTranslator::emitArrayGet(SSATmp* key) {
}
#undef HELPER_TABLE
template <KeyType keyType, bool unboxKey>
template <KeyType keyType>
static inline TypedValue cGetElemImpl(TypedValue* base, TypedValue keyVal,
MInstrState* mis) {
TypedValue result;
TypedValue* key = keyPtr<keyType>(keyVal);
key = unbox<keyType, unboxKey>(key);
base = Elem<true, keyType>(result, mis->tvRef, base, mis->baseStrOff, key);
if (base != &result) {
// Save a copy of the result.
@@ -1569,14 +1529,11 @@ static inline TypedValue cGetElemImpl(TypedValue* base, TypedValue keyVal,
return result;
}
#define HELPER_TABLE(m) \
/* name hot key unboxKey */ \
m(cGetElemC, , AnyKey, false) \
m(cGetElemI, , IntKey, false) \
m(cGetElemL, HOT_FUNC_VM, AnyKey, true) \
m(cGetElemLI, HOT_FUNC_VM, IntKey, true) \
m(cGetElemLS, , StrKey, true) \
m(cGetElemS, HOT_FUNC_VM, StrKey, false)
#define HELPER_TABLE(m) \
/* name hot key */ \
m(cGetElemC, , AnyKey) \
m(cGetElemI, , IntKey) \
m(cGetElemS, HOT_FUNC_VM, StrKey)
#define ELEM(nm, hot, ...) \
hot \
@@ -1589,7 +1546,7 @@ HELPER_TABLE(ELEM)
#undef ELEM
void HhbcTranslator::VectorTranslator::emitCGetElem() {
SSATmp* key = getInput(m_iInd);
SSATmp* key = getKey();
if (isSimpleArrayOp()) {
emitArrayGet(key);
@@ -1597,18 +1554,17 @@ void HhbcTranslator::VectorTranslator::emitCGetElem() {
}
typedef TypedValue (*OpFunc)(TypedValue*, TypedValue, MInstrState*);
BUILD_OPTAB_HOT(getKeyTypeIS(key), key->isBoxed());
BUILD_OPTAB_HOT(getKeyTypeIS(key));
m_ht.spillStack();
m_result = m_tb.gen(CGetElem, cns((TCA)opFunc),
m_base, key, genMisPtr());
}
#undef HELPER_TABLE
template <KeyType keyType, bool unboxKey>
template <KeyType keyType>
static inline TypedValue vGetElemImpl(TypedValue* base, TypedValue keyVal,
MInstrState* mis) {
TypedValue* key = keyPtr<keyType>(keyVal);
key = unbox<keyType, unboxKey>(key);
base = VM::ElemD<false, true, keyType>(mis->tvScratch, mis->tvRef, base, key);
TypedValue result;
@@ -1625,14 +1581,11 @@ static inline TypedValue vGetElemImpl(TypedValue* base, TypedValue keyVal,
return result;
}
#define HELPER_TABLE(m) \
/* name keyType unboxKey */ \
m(vGetElemC, AnyKey, false) \
m(vGetElemI, IntKey, false) \
m(vGetElemL, AnyKey, true) \
m(vGetElemLI, IntKey, true) \
m(vGetElemLS, StrKey, true) \
m(vGetElemS, StrKey, false)
#define HELPER_TABLE(m) \
/* name keyType */ \
m(vGetElemC, AnyKey) \
m(vGetElemI, IntKey) \
m(vGetElemS, StrKey)
#define ELEM(nm, ...) \
TypedValue nm(TypedValue* base, TypedValue key, MInstrState* mis) { \
@@ -1644,19 +1597,18 @@ HELPER_TABLE(ELEM)
#undef ELEM
void HhbcTranslator::VectorTranslator::emitVGetElem() {
SSATmp* key = getInput(m_iInd);
SSATmp* key = getKey();
typedef TypedValue (*OpFunc)(TypedValue*, TypedValue, MInstrState*);
BUILD_OPTAB(getKeyTypeIS(key), key->isBoxed());
BUILD_OPTAB(getKeyTypeIS(key));
m_ht.spillStack();
m_result = genStk(VGetElem, cns((TCA)opFunc), m_base, key, genMisPtr());
}
#undef HELPER_TABLE
template <KeyType keyType, bool unboxKey, bool isEmpty>
template <KeyType keyType, bool isEmpty>
static inline bool issetEmptyElemImpl(TypedValue* base, TypedValue keyVal,
MInstrState* mis) {
TypedValue* key = keyPtr<keyType>(keyVal);
key = unbox<keyType, unboxKey>(key);
// mis == nullptr if we proved that it won't be used. mis->tvScratch and
// mis->tvRef are ok because those params are passed by
// reference. mis->baseStrOff is passed by value so we have to check mis
@@ -1665,20 +1617,14 @@ static inline bool issetEmptyElemImpl(TypedValue* base, TypedValue keyVal,
mis->tvScratch, mis->tvRef, base, mis ? mis->baseStrOff : false, key);
}
#define HELPER_TABLE(m) \
/* name hot keyType unboxKey isEmpty */ \
m(issetElemC, , AnyKey, false, false) \
m(issetElemCE, , AnyKey, false, true) \
m(issetElemI, HOT_FUNC_VM, IntKey, false, false) \
m(issetElemIE, , IntKey, false, true) \
m(issetElemL, , AnyKey, true, false) \
m(issetElemLE, , AnyKey, true, true) \
m(issetElemLI, , IntKey, true, false) \
m(issetElemLIE, , IntKey, true, true) \
m(issetElemLS, , StrKey, true, false) \
m(issetElemLSE, , StrKey, true, true) \
m(issetElemS, HOT_FUNC_VM, StrKey, false, false) \
m(issetElemSE, , StrKey, false, true)
#define HELPER_TABLE(m) \
/* name hot keyType isEmpty */ \
m(issetElemC, , AnyKey, false) \
m(issetElemCE, , AnyKey, true) \
m(issetElemI, HOT_FUNC_VM, IntKey, false) \
m(issetElemIE, , IntKey, true) \
m(issetElemS, HOT_FUNC_VM, StrKey, false) \
m(issetElemSE, , StrKey, true)
#define ISSET(nm, hot, ...) \
hot \
@@ -1691,10 +1637,10 @@ HELPER_TABLE(ISSET)
#undef ISSET
void HhbcTranslator::VectorTranslator::emitIssetEmptyElem(bool isEmpty) {
SSATmp* key = getInput(m_iInd);
SSATmp* key = getKey();
typedef uint64_t (*OpFunc)(TypedValue*, TypedValue, MInstrState*);
BUILD_OPTAB_HOT(getKeyTypeIS(key), key->isBoxed(), isEmpty);
BUILD_OPTAB_HOT(getKeyTypeIS(key), isEmpty);
m_ht.spillStack();
m_result = m_tb.gen(isEmpty ? EmptyElem : IssetElem,
cns((TCA)opFunc), m_base, key, genMisPtr());
@@ -1736,7 +1682,7 @@ HELPER_TABLE(ISSET)
#undef ISSET
void HhbcTranslator::VectorTranslator::emitArrayIsset() {
SSATmp* key = getInput(m_iInd);
SSATmp* key = getKey();
KeyType keyType;
bool checkForInt;
checkStrictlyInteger(key, keyType, checkForInt);
@@ -1852,23 +1798,19 @@ void HhbcTranslator::VectorTranslator::emitArraySet(SSATmp* key,
}
#undef HELPER_TABLE
template <KeyType keyType, bool unboxKey>
template <KeyType keyType>
static inline TypedValue setElemImpl(TypedValue* base, TypedValue keyVal,
Cell val) {
TypedValue* key = keyPtr<keyType>(keyVal);
key = unbox<keyType, unboxKey>(key);
HPHP::VM::SetElem<true, keyType>(base, key, &val);
return val;
}
#define HELPER_TABLE(m) \
/* name hot key unboxKey */ \
m(setElemC, , AnyKey, false) \
m(setElemI, , IntKey, false) \
m(setElemL, , AnyKey, true) \
m(setElemLI, , IntKey, true) \
m(setElemLS, , StrKey, true) \
m(setElemS, HOT_FUNC_VM, StrKey, false)
#define HELPER_TABLE(m) \
/* name hot key */ \
m(setElemC, , AnyKey) \
m(setElemI, , IntKey) \
m(setElemS, HOT_FUNC_VM, StrKey)
#define ELEM(nm, hot, ...) \
hot \
@@ -1882,7 +1824,7 @@ HELPER_TABLE(ELEM)
void HhbcTranslator::VectorTranslator::emitSetElem() {
SSATmp* value = getValue();
SSATmp* key = getInput(m_iInd);
SSATmp* key = getKey();
if (isSimpleArrayOp()) {
emitArraySet(key, value);
@@ -1891,7 +1833,7 @@ void HhbcTranslator::VectorTranslator::emitSetElem() {
// Emit the appropriate helper call.
typedef TypedValue (*OpFunc)(TypedValue*, TypedValue, Cell);
BUILD_OPTAB_HOT(getKeyTypeIS(key), key->isBoxed());
BUILD_OPTAB_HOT(getKeyTypeIS(key));
m_ht.spillStack();
SSATmp* result = genStk(SetElem, cns((TCA)opFunc), m_base, key, value);
VectorEffects ve(result->getInstruction());
@@ -1899,22 +1841,20 @@ void HhbcTranslator::VectorTranslator::emitSetElem() {
}
#undef HELPER_TABLE
template <bool unboxKey, SetOpOp op>
template <SetOpOp op>
static inline TypedValue setOpElemImpl(TypedValue* base, TypedValue keyVal,
Cell val, MInstrState* mis) {
TypedValue* key = unbox<AnyKey, unboxKey>(&keyVal);
TypedValue* result =
VM::SetOpElem(mis->tvScratch, mis->tvRef, op, base, key, &val);
VM::SetOpElem(mis->tvScratch, mis->tvRef, op, base, &keyVal, &val);
TypedValue ret;
tvReadCell(result, &ret);
return ret;
}
#define OPELEM_TABLE(m, nm, op) \
/* name unboxKey op */ \
m(nm##op##ElemC, false, op) \
m(nm##op##ElemL, true, op)
#define OPELEM_TABLE(m, nm, op) \
/* name op */ \
m(nm##op##ElemC, op)
#define HELPER_TABLE(m, op) OPELEM_TABLE(m, setOp, SetOp##op)
#define SETOP(nm, ...) \
@@ -1931,10 +1871,10 @@ SETOP_OPS
void HhbcTranslator::VectorTranslator::emitSetOpElem() {
SetOpOp op = SetOpOp(m_ni.imm[0].u_OA);
SSATmp* key = getInput(m_iInd);
SSATmp* key = getKey();
typedef TypedValue (*OpFunc)(TypedValue*, TypedValue, Cell, MInstrState*);
# define SETOP_OP(op, bcOp) HELPER_TABLE(FILL_ROW, op)
BUILD_OPTAB_ARG(SETOP_OPS, key->isBoxed(), op);
BUILD_OPTAB_ARG(SETOP_OPS, op);
# undef SETOP_OP
m_ht.spillStack();
m_result =
@@ -1942,13 +1882,12 @@ void HhbcTranslator::VectorTranslator::emitSetOpElem() {
}
#undef HELPER_TABLE
template <bool unboxKey, IncDecOp op>
template <IncDecOp op>
static inline TypedValue incDecElemImpl(TypedValue* base, TypedValue keyVal,
MInstrState* mis) {
TypedValue* key = unbox<AnyKey, unboxKey>(&keyVal);
TypedValue result;
VM::IncDecElem<true>(
mis->tvScratch, mis->tvRef, op, base, key, result);
mis->tvScratch, mis->tvRef, op, base, &keyVal, result);
assert(result.m_type != KindOfRef);
return result;
}
@@ -1967,67 +1906,46 @@ INCDEC_OPS
void HhbcTranslator::VectorTranslator::emitIncDecElem() {
IncDecOp op = IncDecOp(m_ni.imm[0].u_OA);
SSATmp* key = getInput(m_iInd);
SSATmp* key = getKey();
typedef TypedValue (*OpFunc)(TypedValue*, TypedValue, MInstrState*);
# define INCDEC_OP(op) HELPER_TABLE(FILL_ROW, op)
BUILD_OPTAB_ARG(INCDEC_OPS, key->isBoxed(), op);
BUILD_OPTAB_ARG(INCDEC_OPS, op);
# undef INCDEC_OP
m_ht.spillStack();
m_result = genStk(IncDecElem, cns((TCA)opFunc), m_base, key, genMisPtr());
}
#undef HELPER_TABLE
template <bool unboxKey>
static inline void bindElemImpl(TypedValue* base, TypedValue keyVal,
RefData* val, MInstrState* mis) {
TypedValue* key = unbox<AnyKey, unboxKey>(&keyVal);
base = VM::ElemD<false, true>(mis->tvScratch, mis->tvRef, base, key);
namespace VectorHelpers {
void bindElemC(TypedValue* base, TypedValue keyVal, RefData* val,
MInstrState* mis) {
base = VM::ElemD<false, true>(mis->tvScratch, mis->tvRef, base, &keyVal);
if (!(base == &mis->tvScratch && base->m_type == KindOfUninit)) {
tvBindRef(val, base);
}
}
#define HELPER_TABLE(m) \
/* name unboxKey */ \
m(bindElemC, false) \
m(bindElemL, true)
#define ELEM(nm, ...) \
void nm(TypedValue* base, TypedValue key, RefData* val, \
MInstrState* mis) { \
bindElemImpl<__VA_ARGS__>(base, key, val, mis); \
}
namespace VectorHelpers {
HELPER_TABLE(ELEM)
}
#undef ELEM
void HhbcTranslator::VectorTranslator::emitBindElem() {
SSATmp* key = getInput(m_iInd);
SSATmp* key = getKey();
SSATmp* box = getValue();
typedef void (*OpFunc)(TypedValue*, TypedValue, RefData*, MInstrState*);
BUILD_OPTAB(key->isBoxed());
m_ht.spillStack();
genStk(BindElem, cns((TCA)opFunc), m_base, key, box, genMisPtr());
genStk(BindElem, cns((TCA)VectorHelpers::bindElemC),
m_base, key, box, genMisPtr());
m_result = box;
}
#undef HELPER_TABLE
template <KeyType keyType, bool unboxKey>
template <KeyType keyType>
static inline void unsetElemImpl(TypedValue* base, TypedValue keyVal) {
TypedValue* key = keyPtr<keyType>(keyVal);
key = unbox<keyType, unboxKey>(key);
VM::UnsetElem<keyType>(base, key);
}
#define HELPER_TABLE(m) \
/* name hot keyType unboxKey */ \
m(unsetElemC, , AnyKey, false) \
m(unsetElemI, , IntKey, false) \
m(unsetElemL, , AnyKey, true) \
m(unsetElemLI, , IntKey, true) \
m(unsetElemLS, , StrKey, true) \
m(unsetElemS, HOT_FUNC_VM, StrKey, false)
#define HELPER_TABLE(m) \
/* name hot keyType */ \
m(unsetElemC, , AnyKey) \
m(unsetElemI, , IntKey) \
m(unsetElemS, HOT_FUNC_VM, StrKey)
#define ELEM(nm, hot, ...) \
hot \
@@ -2040,7 +1958,7 @@ HELPER_TABLE(ELEM)
#undef ELEM
void HhbcTranslator::VectorTranslator::emitUnsetElem() {
SSATmp* key = getInput(m_iInd);
SSATmp* key = getKey();
Type baseType = m_base->getType().strip();
if (baseType.subtypeOf(Type::Str)) {
@@ -2055,7 +1973,7 @@ void HhbcTranslator::VectorTranslator::emitUnsetElem() {
}
typedef void (*OpFunc)(TypedValue*, TypedValue);
BUILD_OPTAB_HOT(getKeyTypeIS(key), key->isBoxed());
BUILD_OPTAB_HOT(getKeyTypeIS(key));
m_ht.spillStack();
genStk(UnsetElem, cns((TCA)opFunc), m_base, key);
}