diff --git a/hphp/runtime/vm/translator/hopt/hhbctranslator.h b/hphp/runtime/vm/translator/hopt/hhbctranslator.h index 5237aad89..3c11d212b 100644 --- a/hphp/runtime/vm/translator/hopt/hhbctranslator.h +++ b/hphp/runtime/vm/translator/hopt/hhbctranslator.h @@ -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, diff --git a/hphp/runtime/vm/translator/hopt/ir.h b/hphp/runtime/vm/translator/hopt/ir.h index 00baa0d23..30bc71932 100644 --- a/hphp/runtime/vm/translator/hopt/ir.h +++ b/hphp/runtime/vm/translator/hopt/ir.h @@ -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) \ diff --git a/hphp/runtime/vm/translator/hopt/vectortranslator-internal.h b/hphp/runtime/vm/translator/hopt/vectortranslator-internal.h index 9fdb1838e..a4b3fa4f2 100644 --- a/hphp/runtime/vm/translator/hopt/vectortranslator-internal.h +++ b/hphp/runtime/vm/translator/hopt/vectortranslator-internal.h @@ -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 -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(k->m_data.num); - } - } else if (kt == AnyKey) { - assert(k->m_type != KindOfRef); - } - return k; -} - } } } #endif diff --git a/hphp/runtime/vm/translator/hopt/vectortranslator.cpp b/hphp/runtime/vm/translator/hopt/vectortranslator.cpp index e9f060dd0..82b9dbaca 100644 --- a/hphp/runtime/vm/translator/hopt/vectortranslator.cpp +++ b/hphp/runtime/vm/translator/hopt/vectortranslator.cpp @@ -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 +template static inline TypedValue* propImpl(Class* ctx, TypedValue* base, TypedValue keyVal, MInstrState* mis) { - TypedValue* key = unbox(&keyVal); return Prop( - 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 static inline TypedValue* elemImpl(TypedValue* base, TypedValue keyVal, MInstrState* mis) { TypedValue* key = keyPtr(keyVal); - key = unbox(key); if (unset) { return ElemU(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(base, key, mis); \ + return elemImpl(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 +template static inline TypedValue cGetPropImpl(Class* ctx, TypedValue* base, TypedValue keyVal, MInstrState* mis) { TypedValue result; TypedValue* key = keyPtr(keyVal); - key = unbox(key); base = Prop( 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 +template static inline TypedValue vGetPropImpl(Class* ctx, TypedValue* base, TypedValue keyVal, MInstrState* mis) { TypedValue* key = keyPtr(keyVal); - key = unbox(key); base = VM::Prop( 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 +template static inline bool issetEmptyPropImpl(Class* ctx, TypedValue* base, TypedValue keyVal) { - TypedValue* key = unbox(&keyVal); - return VM::IssetEmptyProp(ctx, base, key); + return VM::IssetEmptyProp(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 +template static inline TypedValue setPropImpl(Class* ctx, TypedValue* base, TypedValue keyVal, Cell val) { - TypedValue* key = unbox(&keyVal); - VM::SetProp(ctx, base, key, &val); + VM::SetProp(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 +template static inline TypedValue setOpPropImpl(TypedValue* base, TypedValue keyVal, Cell val, MInstrState* mis) { - TypedValue* key = unbox(&keyVal); TypedValue* result = VM::SetOpProp( - 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 +template static inline TypedValue incDecPropImpl(Class* ctx, TypedValue* base, TypedValue keyVal, MInstrState* mis) { - TypedValue* key = unbox(&keyVal); TypedValue result; result.m_type = KindOfUninit; VM::IncDecProp( - 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 +template static inline void bindPropImpl(Class* ctx, TypedValue* base, TypedValue keyVal, RefData* val, MInstrState* mis) { - TypedValue* key = unbox(&keyVal); TypedValue* prop = VM::Prop( - 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 +template static inline void unsetPropImpl(Class* ctx, TypedValue* base, TypedValue keyVal) { - TypedValue* key = unbox(&keyVal); - VM::UnsetProp(ctx, base, key); + VM::UnsetProp(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 +template static inline TypedValue cGetElemImpl(TypedValue* base, TypedValue keyVal, MInstrState* mis) { TypedValue result; TypedValue* key = keyPtr(keyVal); - key = unbox(key); base = Elem(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 +template static inline TypedValue vGetElemImpl(TypedValue* base, TypedValue keyVal, MInstrState* mis) { TypedValue* key = keyPtr(keyVal); - key = unbox(key); base = VM::ElemD(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 +template static inline bool issetEmptyElemImpl(TypedValue* base, TypedValue keyVal, MInstrState* mis) { TypedValue* key = keyPtr(keyVal); - key = unbox(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 +template static inline TypedValue setElemImpl(TypedValue* base, TypedValue keyVal, Cell val) { TypedValue* key = keyPtr(keyVal); - key = unbox(key); HPHP::VM::SetElem(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 +template static inline TypedValue setOpElemImpl(TypedValue* base, TypedValue keyVal, Cell val, MInstrState* mis) { - TypedValue* key = unbox(&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 +template static inline TypedValue incDecElemImpl(TypedValue* base, TypedValue keyVal, MInstrState* mis) { - TypedValue* key = unbox(&keyVal); TypedValue result; VM::IncDecElem( - 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 -static inline void bindElemImpl(TypedValue* base, TypedValue keyVal, - RefData* val, MInstrState* mis) { - TypedValue* key = unbox(&keyVal); - base = VM::ElemD(mis->tvScratch, mis->tvRef, base, key); +namespace VectorHelpers { +void bindElemC(TypedValue* base, TypedValue keyVal, RefData* val, + MInstrState* mis) { + base = VM::ElemD(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 +template static inline void unsetElemImpl(TypedValue* base, TypedValue keyVal) { TypedValue* key = keyPtr(keyVal); - key = unbox(key); VM::UnsetElem(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); }