Remove many of the genFoo functions from tracebuilder

Removes most of the wrappers in favor of gen(). Does two
cases that actually had logic by adding a new "preOptimize" pass where
TraceBuilder can use tracked state to modify instructions before they
go to the simplifier.
Esse commit está contido em:
Jordan DeLong
2013-04-24 10:18:50 -07:00
commit de Sara Golemon
commit 858731971a
7 arquivos alterados com 279 adições e 620 exclusões
+191 -132
Ver Arquivo
@@ -362,7 +362,7 @@ void HhbcTranslator::emitThis() {
emitInterpOne(Type::Obj, 0); // will throw a fatal
return;
}
pushIncRef(m_tb->genLdThis(getExitSlowTrace()));
pushIncRef(m_tb->gen(LdThis, getExitSlowTrace(), m_tb->getFp()));
}
void HhbcTranslator::emitCheckThis() {
@@ -370,7 +370,7 @@ void HhbcTranslator::emitCheckThis() {
emitInterpOne(Type::None, 0); // will throw a fatal
return;
}
m_tb->genLdThis(getExitSlowTrace());
m_tb->gen(LdThis, getExitSlowTrace(), m_tb->getFp());
}
void HhbcTranslator::emitBareThis(int notice) {
@@ -384,7 +384,7 @@ void HhbcTranslator::emitBareThis(int notice) {
emitInterpOne(Type::InitNull, 0); // will raise notice and push null
return;
}
pushIncRef(m_tb->genLdThis(getExitSlowTrace()));
pushIncRef(m_tb->gen(LdThis, getExitSlowTrace(), m_tb->getFp()));
}
void HhbcTranslator::emitArray(int arrayId) {
@@ -397,7 +397,7 @@ void HhbcTranslator::emitNewArray(int capacity) {
ArrayData* ad = HphpArray::GetStaticEmptyArray();
push(m_tb->genDefConst(ad));
} else {
push(m_tb->genNewArray(capacity));
push(m_tb->gen(NewArray, cns(capacity)));
}
}
@@ -409,7 +409,7 @@ void HhbcTranslator::emitNewTuple(int numArgs) {
// its values directly as SSA operands.
SSATmp* sp = spillStack();
for (int i = 0; i < numArgs; i++) popC();
push(m_tb->genNewTuple(numArgs, sp));
push(m_tb->gen(NewTuple, cns(numArgs), sp));
}
void HhbcTranslator::emitArrayAdd() {
@@ -522,14 +522,14 @@ void HhbcTranslator::emitCns(uint32_t id) {
void HhbcTranslator::emitDefCns(uint32_t id) {
StringData* name = lookupStringId(id);
SSATmp* val = popC();
push(m_tb->genDefCns(name, val));
push(m_tb->gen(DefCns, cns(name), val));
}
void HhbcTranslator::emitConcat() {
SSATmp* tr = popC();
SSATmp* tl = popC();
// the concat helpers decref their args, so don't decref pop'ed values
push(m_tb->genConcat(tl, tr));
push(m_tb->gen(Concat, tl, tr));
}
void HhbcTranslator::emitDefCls(int cid, Offset after) {
@@ -547,7 +547,8 @@ void HhbcTranslator::emitLateBoundCls() {
emitInterpOne(Type::Cls, 0);
return;
}
push(m_tb->gen(LdClsCtx, m_tb->genLdCtx(getCurFunc())));
auto const ctx = m_tb->gen(LdCtx, m_tb->getFp(), cns(getCurFunc()));
push(m_tb->gen(LdClsCtx, ctx));
}
void HhbcTranslator::emitSelf() {
@@ -596,17 +597,13 @@ void HhbcTranslator::emitFalse() {
push(m_tb->genDefConst(false));
}
void HhbcTranslator::emitUninitLoc(uint32_t id) {
m_tb->genInitLoc(id, m_tb->genDefUninit());
}
void HhbcTranslator::emitInitThisLoc(int32_t id) {
if (!getCurClass()) {
// Do nothing if this is null
return;
}
SSATmp* tmpThis = m_tb->genLdThis(getExitSlowTrace());
m_tb->genInitLoc(id, m_tb->genIncRef(tmpThis));
SSATmp* tmpThis = m_tb->gen(LdThis, getExitSlowTrace(), m_tb->getFp());
m_tb->gen(StLoc, LocalId(id), m_tb->getFp(), m_tb->gen(IncRef, tmpThis));
}
void HhbcTranslator::emitCGetL(int32_t id) {
@@ -693,11 +690,11 @@ void HhbcTranslator::emitIncDecMem(bool pre,
SSATmp* propAddr,
Trace* exitTrace) {
// Handle only integer inc/dec for now
SSATmp* src = m_tb->genLdMem(propAddr, Type::Int, exitTrace);
SSATmp* src = m_tb->gen(LdMem, Type::Int, exitTrace, propAddr, cns(0));
// do the add and store back
SSATmp* res = emitIncDec(pre, inc, src);
// don't gen a dec ref or type store
m_tb->genStMem(propAddr, res, false);
m_tb->gen(StMemNT, propAddr, cns(0), res);
}
static bool isSupportedBinaryArith(Opcode opc,
@@ -724,7 +721,7 @@ void HhbcTranslator::emitSetOpL(Opcode subOpc, uint32_t id) {
// also incref their results, which will be consumed by the stloc. We
// need an extra incref for the push onto the stack.
SSATmp* val = popC();
SSATmp* result = m_tb->genConcat(loc, val);
SSATmp* result = m_tb->gen(Concat, loc, val);
pushIncRef(m_tb->genStLoc(id, result, false, true, exitTrace));
} else if (isSupportedBinaryArith(subOpc,
loc->type(),
@@ -803,7 +800,14 @@ void HhbcTranslator::emitIterInit(uint32_t iterId,
int offset,
uint32_t valLocalId) {
emitIterInitCommon(offset, [=] (SSATmp* src) {
return m_tb->genIterInit(src, iterId, valLocalId);
return m_tb->gen(
IterInit,
Type::Bool,
src,
m_tb->getFp(),
cns(iterId),
cns(valLocalId)
);
});
}
@@ -812,14 +816,28 @@ void HhbcTranslator::emitIterInitK(uint32_t iterId,
uint32_t valLocalId,
uint32_t keyLocalId) {
emitIterInitCommon(offset, [=] (SSATmp* src) {
return m_tb->genIterInitK(src, iterId, valLocalId, keyLocalId);
return m_tb->gen(
IterInitK,
Type::Bool,
src,
m_tb->getFp(),
cns(iterId),
cns(valLocalId),
cns(keyLocalId)
);
});
}
void HhbcTranslator::emitIterNext(uint32_t iterId,
int offset,
uint32_t valLocalId) {
SSATmp* res = m_tb->genIterNext(iterId, valLocalId);
SSATmp* res = m_tb->gen(
IterNext,
Type::Bool,
m_tb->getFp(),
cns(iterId),
cns(valLocalId)
);
emitJmpCondHelper(offset, false, res);
}
@@ -827,12 +845,19 @@ void HhbcTranslator::emitIterNextK(uint32_t iterId,
int offset,
uint32_t valLocalId,
uint32_t keyLocalId) {
SSATmp* res = m_tb->genIterNextK(iterId, valLocalId, keyLocalId);
SSATmp* res = m_tb->gen(
IterNextK,
Type::Bool,
m_tb->getFp(),
cns(iterId),
cns(valLocalId),
cns(keyLocalId)
);
emitJmpCondHelper(offset, false, res);
}
void HhbcTranslator::emitIterFree(uint32_t iterId) {
m_tb->genIterFree(iterId);
m_tb->gen(IterFree, m_tb->getFp(), cns(iterId));
}
void HhbcTranslator::emitCreateCont(bool getArgs,
@@ -870,9 +895,13 @@ void HhbcTranslator::emitCreateCont(bool getArgs,
SSATmp* locals = m_tb->gen(LdContLocalsPtr, cont);
for (int i = 0; i < origLocals; ++i) {
SSATmp* loc = m_tb->genIncRef(m_tb->genLdAssertedLoc(i, Type::Gen));
m_tb->genStMem(locals, cellsToBytes(genLocals - params[i] - 1), loc,
true);
SSATmp* loc = m_tb->gen(IncRef, m_tb->genLdAssertedLoc(i, Type::Gen));
m_tb->gen(
StMem,
locals,
cns(cellsToBytes(genLocals - params[i] - 1)),
loc
);
}
if (fillThis) {
assert(thisId != kInvalidId);
@@ -891,11 +920,15 @@ void HhbcTranslator::emitContEnter(int32_t returnBcOffset) {
spillStack();
assert(getCurClass());
SSATmp* cont = m_tb->genLdThis(nullptr);
SSATmp* contAR = m_tb->genLdRaw(cont, RawMemSlot::ContARPtr, Type::FramePtr);
SSATmp* cont = m_tb->gen(LdThis, m_tb->getFp());
SSATmp* contAR = m_tb->gen(
LdRaw, Type::FramePtr, cont, cns(RawMemSlot::ContARPtr)
);
SSATmp* func = m_tb->genLdARFuncPtr(contAR, m_tb->genDefConst<int64_t>(0));
SSATmp* funcBody = m_tb->genLdRaw(func, RawMemSlot::ContEntry, Type::TCA);
SSATmp* func = m_tb->gen(LdARFuncPtr, contAR, cns(0));
SSATmp* funcBody = m_tb->gen(
LdRaw, Type::TCA, func, cns(RawMemSlot::ContEntry)
);
m_tb->gen(
ContEnter,
@@ -908,7 +941,7 @@ void HhbcTranslator::emitContEnter(int32_t returnBcOffset) {
}
void HhbcTranslator::emitContExitImpl() {
SSATmp* retAddr = m_tb->genLdRetAddr();
SSATmp* retAddr = m_tb->gen(LdRetAddr, m_tb->getFp());
// Despite the name, this doesn't actually free the AR; it updates the
// hardware fp and returns the old one
SSATmp* fp = m_tb->gen(FreeActRec, m_tb->getFp());
@@ -922,41 +955,44 @@ void HhbcTranslator::emitContExitImpl() {
sp = m_tb->getSp();
}
m_tb->genRetCtrl(sp, fp, retAddr);
m_tb->gen(RetCtrl, sp, fp, retAddr);
m_hasExit = true;
}
void HhbcTranslator::emitContExit() {
m_tb->genExitWhenSurprised(getExitSlowTrace());
m_tb->gen(ExitWhenSurprised, getExitSlowTrace());
emitContExitImpl();
}
void HhbcTranslator::emitUnpackCont() {
m_tb->genLinkContVarEnv();
m_tb->gen(LinkContVarEnv, m_tb->getFp());
SSATmp* cont = m_tb->genLdAssertedLoc(0, Type::Obj);
push(m_tb->genLdRaw(cont, RawMemSlot::ContLabel, Type::Int));
push(m_tb->gen(LdRaw, Type::Int, cont, cns(RawMemSlot::ContLabel)));
}
void HhbcTranslator::emitPackCont(int64_t labelId) {
m_tb->genUnlinkContVarEnv();
m_tb->gen(UnlinkContVarEnv, m_tb->getFp());
SSATmp* cont = m_tb->genLdAssertedLoc(0, Type::Obj);
m_tb->genSetPropCell(cont, CONTOFF(m_value), popC());
m_tb->genStRaw(cont, RawMemSlot::ContLabel,
m_tb->genDefConst(labelId));
m_tb->gen(
StRaw, cont, cns(RawMemSlot::ContLabel), cns(labelId)
);
}
void HhbcTranslator::emitContReceive() {
SSATmp* cont = m_tb->genLdAssertedLoc(0, Type::Obj);
m_tb->genContRaiseCheck(cont, getExitSlowTrace());
SSATmp* valOffset = m_tb->genDefConst<int64_t>(CONTOFF(m_received));
push(m_tb->genLdProp(cont, valOffset, Type::Cell, nullptr));
m_tb->genStProp(cont, valOffset, m_tb->genDefUninit(), true);
m_tb->gen(ContRaiseCheck, getExitSlowTrace(), cont);
auto const valOffset = cns(CONTOFF(m_received));
push(m_tb->gen(LdProp, Type::Cell, cont, valOffset));
m_tb->gen(StProp, cont, valOffset, m_tb->genDefUninit());
}
void HhbcTranslator::emitContRetC() {
SSATmp* cont = m_tb->genLdAssertedLoc(0, Type::Obj);
m_tb->genExitWhenSurprised(getExitSlowTrace());
m_tb->genStRaw(cont, RawMemSlot::ContDone, m_tb->genDefConst(true));
m_tb->gen(ExitWhenSurprised, getExitSlowTrace());
m_tb->gen(
StRaw, cont, cns(RawMemSlot::ContDone), cns(true)
);
m_tb->genSetPropCell(cont, CONTOFF(m_value), popC());
// transfer control
@@ -965,23 +1001,24 @@ void HhbcTranslator::emitContRetC() {
void HhbcTranslator::emitContNext() {
assert(getCurClass());
SSATmp* cont = m_tb->genLdThis(nullptr);
m_tb->genContPreNext(cont, getExitSlowTrace());
SSATmp* cont = m_tb->gen(LdThis, m_tb->getFp());
m_tb->gen(ContPreNext, getExitSlowTrace(), cont);
m_tb->genSetPropCell(cont, CONTOFF(m_received), m_tb->genDefInitNull());
}
void HhbcTranslator::emitContSendImpl(bool raise) {
assert(getCurClass());
SSATmp* cont = m_tb->genLdThis(nullptr);
m_tb->genContStartedCheck(cont, getExitSlowTrace());
m_tb->genContPreNext(cont, getExitSlowTrace());
SSATmp* cont = m_tb->gen(LdThis, m_tb->getFp());
m_tb->gen(ContStartedCheck, getExitSlowTrace(), cont);
m_tb->gen(ContPreNext, getExitSlowTrace(), cont);
SSATmp* value = m_tb->genLdAssertedLoc(0, Type::Cell);
value = m_tb->genIncRef(value);
value = m_tb->gen(IncRef, value);
m_tb->genSetPropCell(cont, CONTOFF(m_received), value);
if (raise) {
m_tb->genStRaw(cont, RawMemSlot::ContShouldThrow,
m_tb->genDefConst(true));
m_tb->gen(
StRaw, cont, cns(RawMemSlot::ContShouldThrow), cns(true)
);
}
}
@@ -995,25 +1032,29 @@ void HhbcTranslator::emitContRaise() {
void HhbcTranslator::emitContValid() {
assert(getCurClass());
SSATmp* cont = m_tb->genLdThis(nullptr);
SSATmp* done = m_tb->genLdRaw(cont, RawMemSlot::ContDone, Type::Bool);
SSATmp* cont = m_tb->gen(LdThis, m_tb->getFp());
SSATmp* done = m_tb->gen(
LdRaw, Type::Bool, cont, cns(RawMemSlot::ContDone)
);
push(m_tb->genNot(done));
}
void HhbcTranslator::emitContCurrent() {
assert(getCurClass());
SSATmp* cont = m_tb->genLdThis(nullptr);
m_tb->genContStartedCheck(cont, getExitSlowTrace());
SSATmp* cont = m_tb->gen(LdThis, m_tb->getFp());
m_tb->gen(ContStartedCheck, getExitSlowTrace(), cont);
SSATmp* offset = m_tb->genDefConst<int64_t>(CONTOFF(m_value));
SSATmp* value = m_tb->genLdProp(cont, offset, Type::Cell, nullptr);
value = m_tb->genIncRef(value);
SSATmp* value = m_tb->gen(LdProp, Type::Cell, cont, offset);
value = m_tb->gen(IncRef, value);
push(value);
}
void HhbcTranslator::emitContStopped() {
assert(getCurClass());
SSATmp* cont = m_tb->genLdThis(nullptr);
m_tb->genStRaw(cont, RawMemSlot::ContRunning, m_tb->genDefConst(false));
SSATmp* cont = m_tb->gen(LdThis, m_tb->getFp());
m_tb->gen(
StRaw, cont, cns(RawMemSlot::ContRunning), cns(false)
);
}
void HhbcTranslator::emitContHandle() {
@@ -1029,7 +1070,7 @@ void HhbcTranslator::emitStrlen() {
// static string; fold its strlen operation
push(m_tb->genDefConst<int64_t>(input->getValStr()->size()));
} else {
push(m_tb->genLdRaw(input, RawMemSlot::StrLen, Type::Int));
push(m_tb->gen(LdRaw, Type::Int, input, cns(RawMemSlot::StrLen)));
m_tb->genDecRef(input);
}
} else if (inType.isNull()) {
@@ -1045,7 +1086,7 @@ void HhbcTranslator::emitStrlen() {
void HhbcTranslator::emitIncStat(int32_t counter, int32_t value, bool force) {
if (Stats::enabled() || force) {
m_tb->genIncStat(counter, value, force);
m_tb->gen(IncStat, cns(counter), cns(value), cns(force));
}
}
@@ -1227,10 +1268,10 @@ void HhbcTranslator::emitJmp(int32_t offset,
// If surprise flags are set, exit trace and handle surprise
bool backward = (offset - (int32_t)bcOff()) < 0;
if (backward && !noSurprise) {
m_tb->genExitWhenSurprised(getExitSlowTrace());
m_tb->gen(ExitWhenSurprised, getExitSlowTrace());
}
if (!breakTracelet) return;
m_tb->genJmp(getExitTrace(offset));
m_tb->gen(Jmp_, getExitTrace(offset));
}
SSATmp* HhbcTranslator::emitJmpCondHelper(int32_t offset,
@@ -1246,7 +1287,7 @@ SSATmp* HhbcTranslator::emitJmpCondHelper(int32_t offset,
}
SSATmp* boolSrc = m_tb->genConvToBool(src);
m_tb->genDecRef(src);
return m_tb->genJmpCond(boolSrc, target, negate);
return m_tb->gen(negate ? JmpZero : JmpNZero, target, boolSrc);
}
void HhbcTranslator::emitJmpZ(int32_t offset) {
@@ -1388,11 +1429,11 @@ void HhbcTranslator::emitFPushCufOp(VM::Op op, Class* cls, StringData* invName,
}
void HhbcTranslator::emitNativeImpl() {
m_tb->genNativeImpl();
SSATmp* sp = m_tb->genRetAdjustStack();
SSATmp* retAddr = m_tb->genLdRetAddr();
m_tb->gen(NativeImpl, cns(getCurFunc()), m_tb->getFp());
SSATmp* sp = m_tb->gen(RetAdjustStack, m_tb->getFp());
SSATmp* retAddr = m_tb->gen(LdRetAddr, m_tb->getFp());
SSATmp* fp = m_tb->gen(FreeActRec, m_tb->getFp());
m_tb->genRetCtrl(sp, fp, retAddr);
m_tb->gen(RetCtrl, sp, fp, retAddr);
// Flag that this trace has a Ret instruction so no ExitTrace is needed
m_hasExit = true;
@@ -1448,7 +1489,7 @@ void HhbcTranslator::emitFPushActRec(SSATmp* func,
void HhbcTranslator::emitFPushCtor(int32_t numParams) {
SSATmp* cls = popA();
exceptionBarrier();
m_tb->genNewObj(numParams, cls);
m_tb->gen(NewObj, cls, cns(numParams), m_tb->getSp(), m_tb->getFp());
m_fpiStack.emplace(nullptr, 0);
}
@@ -1468,12 +1509,14 @@ void HhbcTranslator::emitFPushCtorD(int32_t numParams, int32_t classNameStrId) {
// tracelet. Luckily that is always the case: since this
// optimization only applies when numParams==0, there will be
// nothing between the FPushCtorD and the FCall.
m_tb->genNewObjNoCtorCached(className);
m_tb->gen(NewObjNoCtorCached, cns(className), m_tb->getSp());
push(m_tb->genDefNull());
return;
}
}
m_tb->genNewObjCached(numParams, className);
m_tb->gen(
NewObjCached, cns(numParams), cns(className), m_tb->getSp(), m_tb->getFp()
);
}
/*
@@ -1576,7 +1619,9 @@ void HhbcTranslator::emitFPushObjMethodD(int32_t numParams,
*/
if (!(func->attrs() & AttrPrivate)) {
SSATmp* clsTmp = m_tb->gen(LdObjClass, obj);
SSATmp* funcTmp = m_tb->genLdClsMethod(clsTmp, func->methodSlot());
SSATmp* funcTmp = m_tb->gen(
LdClsMethod, clsTmp, cns(func->methodSlot())
);
if (res == MethodLookup::MethodFoundNoThis) {
m_tb->genDecRef(obj);
objOrCls = clsTmp;
@@ -1638,7 +1683,7 @@ SSATmp* HhbcTranslator::getClsMethodCtx(const Func* callee, const Class* cls) {
// might not be a static call and $this is available, so we know it's
// definitely not static
assert(getCurClass());
return m_tb->genIncRef(m_tb->genLdThis(nullptr));
return m_tb->gen(IncRef, m_tb->gen(LdThis, m_tb->getFp()));
} else {
// might be a non-static call. we have to inspect the func at runtime
PUNT(getClsMethodCtx-MightNotBeStatic);
@@ -1669,10 +1714,11 @@ void HhbcTranslator::emitFPushClsMethodD(int32_t numParams,
// lookup static method & class in the target cache
Trace* exitTrace = getExitSlowTrace();
SSATmp* funcClassTmp =
m_tb->genLdClsMethodCache(m_tb->genDefConst(className),
m_tb->genDefConst(methodName),
m_tb->genDefConst(np.second),
exitTrace);
m_tb->gen(LdClsMethodCache,
exitTrace,
cns(className),
cns(methodName),
cns(np.second));
emitFPushActRec(funcClassTmp,
m_tb->genDefInitNull(),
numParams,
@@ -1695,7 +1741,7 @@ void HhbcTranslator::emitFPushClsMethodF(int32_t numParams,
bool magicCall = false;
const Func* func = lookupImmutableMethod(cls, methName, magicCall,
true /* staticLookup */);
SSATmp* curCtxTmp = m_tb->genLdCtx(getCurFunc());
SSATmp* curCtxTmp = m_tb->gen(LdCtx, m_tb->getFp(), cns(getCurFunc()));
if (func) {
SSATmp* funcTmp = m_tb->genDefConst(func);
SSATmp* newCtxTmp = m_tb->gen(GetCtxFwdCall, curCtxTmp, funcTmp);
@@ -1722,18 +1768,16 @@ void HhbcTranslator::emitFCallArray() {
void HhbcTranslator::emitFCall(uint32_t numParams,
Offset returnBcOffset,
const Func* callee) {
// pop the incoming parameters to the call
SSATmp* params[numParams];
SSATmp* params[numParams + 3];
std::memset(params, 0, sizeof params);
for (uint32_t i = 0; i < numParams; i++) {
params[numParams - i - 1] = popF();
params[numParams + 3 - i - 1] = popF();
}
auto actRec = spillStack();
auto func = callee ? cns(callee) : m_tb->genDefNull();
m_tb->genCall(actRec,
returnBcOffset,
func,
numParams,
params);
params[0] = spillStack();
params[1] = cns(returnBcOffset);
params[2] = callee ? cns(callee) : m_tb->genDefNull();
SSATmp** decayedPtr = params;
m_tb->gen(Call, std::make_pair(numParams + 3, decayedPtr));
if (!m_fpiStack.empty()) {
m_fpiStack.pop();
@@ -1889,32 +1933,34 @@ void HhbcTranslator::emitRet(Type type, bool freeInline) {
const Func* curFunc = getCurFunc();
bool mayUseVV = (curFunc->attrs() & AttrMayUseVV);
m_tb->genExitWhenSurprised(getExitSlowTrace());
m_tb->gen(ExitWhenSurprised, getExitSlowTrace());
if (mayUseVV) {
// Note: this has to be the first thing, because we cannot bail after
// we start decRefing locs because then there'll be no corresponding
// bytecode boundaries until the end of RetC
m_tb->genReleaseVVOrExit(getExitSlowTrace());
m_tb->gen(ReleaseVVOrExit, getExitSlowTrace(), m_tb->getFp());
}
SSATmp* retVal = pop(type);
SSATmp* sp;
if (freeInline) {
SSATmp* useRet = emitDecRefLocalsInline(retVal);
m_tb->genRetVal(useRet);
sp = m_tb->genRetAdjustStack();
m_tb->gen(RetVal, m_tb->getFp(), useRet);
sp = m_tb->gen(RetAdjustStack, m_tb->getFp());
} else {
if (mayHaveThis(curFunc)) {
m_tb->genDecRefThis();
}
sp = m_tb->genGenericRetDecRefs(retVal, curFunc->numLocals());
m_tb->genRetVal(retVal);
sp = m_tb->gen(
GenericRetDecRefs, m_tb->getFp(), retVal, cns(curFunc->numLocals())
);
m_tb->gen(RetVal, m_tb->getFp(), retVal);
}
// Free ActRec, and return control to caller.
SSATmp* retAddr = m_tb->genLdRetAddr();
SSATmp* retAddr = m_tb->gen(LdRetAddr, m_tb->getFp());
SSATmp* fp = m_tb->gen(FreeActRec, m_tb->getFp());
m_tb->genRetCtrl(sp, fp, retAddr);
m_tb->gen(RetCtrl, sp, fp, retAddr);
// Flag that this trace has a Ret instruction, so that no ExitTrace is needed
m_hasExit = true;
@@ -1942,12 +1988,12 @@ void HhbcTranslator::emitSwitch(const ImmVector& iv,
}
if (type.subtypeOf(Type::Null)) {
m_tb->genJmp(getExitTrace(zeroOff));
m_tb->gen(Jmp_, getExitTrace(zeroOff));
return;
} else if (type.subtypeOf(Type::Bool)) {
Offset nonZeroOff = bcOff() + iv.vec32()[iv.size() - 2];
m_tb->genJmpCond(switchVal, getExitTrace(nonZeroOff), false);
m_tb->genJmp(getExitTrace(zeroOff));
m_tb->gen(JmpNZero, getExitTrace(nonZeroOff), switchVal);
m_tb->gen(Jmp_, getExitTrace(zeroOff));
return;
} else if (type.subtypeOf(Type::Int)) {
// No special treatment needed
@@ -1973,7 +2019,7 @@ void HhbcTranslator::emitSwitch(const ImmVector& iv,
switchVal, ssabase, ssatargets);
} else if (type.subtypeOf(Type::Arr)) {
m_tb->genDecRef(switchVal);
m_tb->genJmp(getExitTrace(defaultOff));
m_tb->gen(Jmp_, getExitTrace(defaultOff));
return;
} else {
PUNT(Switch-UnknownType);
@@ -2092,7 +2138,7 @@ Trace* HhbcTranslator::guardTypeStack(uint32_t stackIndex,
if (nextTrace == nullptr) {
nextTrace = getGuardExit();
}
m_tb->genGuardStk(stackIndex, type, nextTrace);
m_tb->gen(GuardStk, type, nextTrace, m_tb->getSp(), cns(stackIndex));
m_typeGuards.push_back(TypeGuard(TypeGuard::Stack, stackIndex, type));
return nextTrace;
@@ -2104,13 +2150,13 @@ void HhbcTranslator::checkTypeTopOfStack(Type type,
SSATmp* tmp = m_evalStack.top();
if (!tmp) {
FTRACE(1, "checkTypeTopOfStack: no tmp: {}\n", type.toString());
m_tb->genGuardStk(0, type, exitTrace);
m_tb->gen(GuardStk, type, exitTrace, m_tb->getSp(), cns(0));
push(pop(type));
} else {
FTRACE(1, "checkTypeTopOfStack: generating GuardType for {}\n",
type.toString());
m_evalStack.pop();
tmp = m_tb->genGuardType(tmp, type, exitTrace);
tmp = m_tb->gen(GuardType, type, exitTrace, tmp);
push(tmp);
}
}
@@ -2154,12 +2200,13 @@ Trace* HhbcTranslator::guardRefs(int64_t entryArDelta,
}
int32_t actRecOff = cellsToBytes(entryArDelta);
SSATmp* funcPtr = m_tb->genLdARFuncPtr(m_tb->getSp(),
m_tb->genDefConst<int64_t>(actRecOff));
SSATmp* nParams = m_tb->genLdRaw(funcPtr, RawMemSlot::FuncNumParams,
Type::Int);
SSATmp* bitsPtr = m_tb->genLdRaw(funcPtr, RawMemSlot::FuncRefBitVec,
Type::Int);
SSATmp* funcPtr = m_tb->gen(LdARFuncPtr, m_tb->getSp(), cns(actRecOff));
SSATmp* nParams = m_tb->gen(
LdRaw, Type::Int, funcPtr, cns(RawMemSlot::FuncNumParams)
);
SSATmp* bitsPtr = m_tb->gen(
LdRaw, Type::Int, funcPtr, cns(RawMemSlot::FuncRefBitVec)
);
for (unsigned i = 0; i < mask.size(); i += 64) {
assert(i < vals.size());
@@ -2168,15 +2215,18 @@ Trace* HhbcTranslator::guardRefs(int64_t entryArDelta,
if (mask64 == 0) {
continue;
}
uint64_t vals64 = TranslatorX64::packBitVec(vals, i);
SSATmp* mask64Tmp = m_tb->genLdConst<int64_t>(mask64);
SSATmp* vals64Tmp = m_tb->genLdConst<int64_t>(vals64);
SSATmp* firstBitNum = m_tb->genDefConst<int64_t>(i);
m_tb->genGuardRefs(funcPtr, nParams, bitsPtr, firstBitNum,
mask64Tmp, vals64Tmp, exitTrace);
m_tb->gen(
GuardRefs,
exitTrace,
funcPtr,
nParams,
bitsPtr,
cns(i),
m_tb->genLdConst(mask64),
m_tb->genLdConst(vals64)
);
}
return exitTrace;
@@ -2505,14 +2555,10 @@ void HhbcTranslator::emitAGetL(int id, const StringData* clsName) {
}
}
SSATmp* HhbcTranslator::unboxPtr(SSATmp* ptr) {
return m_tb->genUnboxPtr(ptr);
}
void HhbcTranslator::emitBindMem(SSATmp* ptr, SSATmp* src) {
SSATmp* prevValue = m_tb->genLdMem(ptr, ptr->type().deref(), NULL);
SSATmp* prevValue = m_tb->gen(LdMem, ptr->type().deref(), ptr, cns(0));
pushIncRef(src);
m_tb->genStMem(ptr, src, true);
m_tb->gen(StMem, ptr, cns(0), src);
if (isRefCounted(src) && src->type().canRunDtor()) {
Block* exitBlock = getExitTrace(getNextSrcKey().offset())->front();
Block::iterator markerInst = exitBlock->skipLabel();
@@ -2533,7 +2579,7 @@ void HhbcTranslator::emitBind(const StringData* name,
}
void HhbcTranslator::emitSetMem(SSATmp* ptr, SSATmp* src) {
emitBindMem(unboxPtr(ptr), src);
emitBindMem(m_tb->gen(UnboxPtr, ptr), src);
}
template<class CheckSupportedFun, class EmitLdAddrFun>
@@ -2546,7 +2592,9 @@ void HhbcTranslator::emitSet(const StringData* name,
}
void HhbcTranslator::emitVGetMem(SSATmp* ptr) {
pushIncRef(m_tb->genLdMem(m_tb->gen(BoxPtr, ptr), Type::BoxedCell, NULL));
pushIncRef(
m_tb->gen(LdMem, Type::BoxedCell, m_tb->gen(BoxPtr, ptr), cns(0))
);
}
template<class CheckSupportedFun, class EmitLdAddrFun>
@@ -2569,7 +2617,7 @@ void HhbcTranslator::emitIsset(const StringData* name,
},
[&] { // Next: property or global is defined
return m_tb->gen(IsNTypeMem, Type::Null,
m_tb->genUnboxPtr(ptr));
m_tb->gen(UnboxPtr, ptr));
},
[&] { // Taken
return m_tb->genDefConst(false);
@@ -2579,7 +2627,7 @@ void HhbcTranslator::emitIsset(const StringData* name,
}
void HhbcTranslator::emitEmptyMem(SSATmp* ptr) {
SSATmp* ld = m_tb->genLdMem(unboxPtr(ptr), Type::Cell, nullptr);
SSATmp* ld = m_tb->gen(LdMem, Type::Cell, m_tb->gen(UnboxPtr, ptr), cns(0));
push(m_tb->genNot(m_tb->genConvToBool(ld)));
}
@@ -2594,8 +2642,12 @@ void HhbcTranslator::emitEmpty(const StringData* name,
ptr = (this->*emitLdAddr)(name, taken);
},
[&] { // Next: property or global is defined
SSATmp* ld = m_tb->genLdMem(unboxPtr(ptr), Type::Cell,
nullptr);
SSATmp* ld = m_tb->gen(
LdMem,
Type::Cell,
m_tb->gen(UnboxPtr, ptr),
cns(0)
);
return m_tb->genNot(m_tb->genConvToBool(ld));
},
[&] { // Taken
@@ -2666,8 +2718,8 @@ void HhbcTranslator::emitCGet(const StringData* name,
exitOnFailure
? m_tb->getFirstBlock(getExitSlowTrace())
: nullptr);
if (!isInferedType) ptr = unboxPtr(ptr);
pushIncRef(m_tb->genLdMem(ptr, resultType, exit));
if (!isInferedType) ptr = m_tb->gen(UnboxPtr, ptr);
pushIncRef(m_tb->gen(LdMem, resultType, exit, ptr, cns(0)));
}
void HhbcTranslator::emitCGetG(const StringData* gblName,
@@ -2825,7 +2877,14 @@ void HhbcTranslator::emitInterpOne(Type type, int numPopped,
discard(numPopped);
assert(numPopped == m_stackDeficit);
int numPushed = (type == Type::None ? 0 : 1) + numExtraPushed;
m_tb->genInterpOne(bcOff(), numPopped - numPushed, type);
m_tb->gen(
InterpOne,
type,
m_tb->getFp(),
m_tb->getSp(),
cns(bcOff()),
cns(numPopped - numPushed)
);
m_stackDeficit = 0;
}
@@ -2961,7 +3020,7 @@ SSATmp* HhbcTranslator::emitLdLocWarn(uint32_t id,
if (locVal->type().subtypeOf(Type::Uninit)) {
exceptionBarrier();
m_tb->genRaiseUninitLoc(id);
m_tb->gen(RaiseUninitLoc, cns(getCurFunc()->localVarName(id)));
return m_tb->genDefInitNull();
}
@@ -138,7 +138,6 @@ struct HhbcTranslator {
void setBcOffNextTrace(Offset bcOff) { m_bcOffNextTrace = bcOff; }
uint32_t getBcOffNextTrace() { return m_bcOffNextTrace; }
void emitUninitLoc(uint32_t id);
void emitPrint();
void emitThis();
void emitCheckThis();
@@ -523,7 +522,6 @@ private:
SSATmp* getStrName(const StringData* propName = nullptr);
SSATmp* emitLdGblAddrDef(const StringData* gblName = nullptr);
SSATmp* emitLdGblAddr(const StringData* gblName, Block* block);
SSATmp* unboxPtr(SSATmp* ptr);
void emitUnboxRAux();
void emitAGet(SSATmp* src, const StringData* clsName);
void emitRetFromInlined(Type type);
@@ -575,7 +573,7 @@ private:
* Eval stack helpers
*/
SSATmp* push(SSATmp* tmp);
SSATmp* pushIncRef(SSATmp* tmp) { return push(m_tb->genIncRef(tmp)); }
SSATmp* pushIncRef(SSATmp* tmp) { return push(m_tb->gen(IncRef, tmp)); }
SSATmp* pop(Type type);
void popDecRef(Type type);
void discard(unsigned n);
+3 -2
Ver Arquivo
@@ -1497,10 +1497,11 @@ static_assert(sizeof(Type) <= sizeof(uint64_t),
* ConstData.
*/
// The only interesting case is int/bool disambiguation.
// The only interesting case is int/bool disambiguation. Enums are
// treated as ints.
template<class T>
typename std::enable_if<
std::is_integral<T>::value,
std::is_integral<T>::value || std::is_enum<T>::value,
Type
>::type typeForConst(T) {
return std::is_same<T,bool>::value ? Type::Bool : Type::Int;
+1 -1
Ver Arquivo
@@ -1316,7 +1316,7 @@ SSATmp* Simplifier::simplifyUnbox(IRInstruction* inst) {
if (srcType.isBoxed()) {
srcType = srcType.innerType();
assert(type.equals(srcType));
return m_tb->genLdRef(src, type, inst->getTaken()->getTrace());
return m_tb->gen(LdRef, type, inst->getTaken()->getTrace(), src);
}
return nullptr;
}
+46 -368
Ver Arquivo
@@ -70,91 +70,12 @@ TraceBuilder::~TraceBuilder() {
for (State* state : m_snapshots) delete state;
}
SSATmp* TraceBuilder::genDefCns(const StringData* cnsName, SSATmp* val) {
return gen(DefCns, genDefConst<const StringData*>(cnsName), val);
}
SSATmp* TraceBuilder::genConcat(SSATmp* tl, SSATmp* tr) {
return gen(Concat, tl, tr);
}
SSATmp* TraceBuilder::genLdThis(Trace* exitTrace) {
if (isThisAvailable()) {
return gen(LdThis, m_fpValue);
} else {
return gen(LdThis, getFirstBlock(exitTrace), m_fpValue);
}
}
SSATmp* TraceBuilder::genLdCtx(const Func* func) {
if (isThisAvailable()) {
return genLdThis(nullptr);
}
return gen(LdCtx, m_fpValue, genDefConst(func));
}
SSATmp* TraceBuilder::genLdProp(SSATmp* obj,
SSATmp* prop,
Type type,
Trace* exit) {
assert(obj->type() == Type::Obj);
assert(prop->type() == Type::Int);
assert(prop->isConst());
return gen(LdProp, type, getFirstBlock(exit), obj, prop);
}
void TraceBuilder::genStProp(SSATmp* obj,
SSATmp* prop,
SSATmp* src,
bool genStoreType) {
Opcode opc = genStoreType ? StProp : StPropNT;
gen(opc, obj, prop, src);
}
void TraceBuilder::genStMem(SSATmp* addr,
SSATmp* src,
bool genStoreType) {
genStMem(addr, 0, src, genStoreType);
}
void TraceBuilder::genStMem(SSATmp* addr,
int64_t offset,
SSATmp* src,
bool genStoreType) {
Opcode opc = genStoreType ? StMem : StMemNT;
gen(opc, addr, genDefConst(offset), src);
}
void TraceBuilder::genSetPropCell(SSATmp* base, int64_t offset, SSATmp* value) {
SSATmp* oldVal = genLdProp(base, genDefConst(offset), Type::Cell, nullptr);
genStProp(base, genDefConst(offset), value, true);
SSATmp* oldVal = gen(LdProp, Type::Cell, base, genDefConst(offset));
gen(StProp, base, genDefConst(offset), value);
genDecRef(oldVal);
}
SSATmp* TraceBuilder::genLdMem(SSATmp* addr,
int64_t offset,
Type type,
Trace* target) {
return gen(LdMem, type, getFirstBlock(target), addr,
genDefConst(offset));
}
SSATmp* TraceBuilder::genLdMem(SSATmp* addr,
Type type,
Trace* target) {
return genLdMem(addr, 0, type, target);
}
SSATmp* TraceBuilder::genLdRef(SSATmp* ref, Type type, Trace* exit) {
assert(type.notBoxed());
assert(ref->type().isBoxed());
return gen(LdRef, type, getFirstBlock(exit), ref);
}
SSATmp* TraceBuilder::genUnboxPtr(SSATmp* ptr) {
return gen(UnboxPtr, ptr);
}
/**
* Checks if the given SSATmp, or any of its aliases, is available in
* any VM location, including locals and the This pointer.
@@ -210,10 +131,6 @@ void TraceBuilder::genDecRef(SSATmp* tmp) {
gen(DecRef, tmp);
}
void TraceBuilder::genDecRefMem(SSATmp* base, int64_t offset, Type type) {
gen(DecRefMem, type, base, genDefConst(offset));
}
/*
* Code generation support for side exits.
* There are 3 types of side exits as defined by the ExitType enum:
@@ -263,20 +180,6 @@ Trace* TraceBuilder::getExitSlowTrace(uint32_t bcOff,
}
SSATmp* TraceBuilder::genLdRetAddr() {
return gen(LdRetAddr, m_fpValue);
}
SSATmp* TraceBuilder::genLdRaw(SSATmp* base, RawMemSlot::Kind kind,
Type type) {
return gen(LdRaw, type, base, genDefConst(int64_t(kind)));
}
void TraceBuilder::genStRaw(SSATmp* base, RawMemSlot::Kind kind,
SSATmp* value) {
gen(StRaw, base, genDefConst(int64_t(kind)), value);
}
void TraceBuilder::genTraceEnd(uint32_t nextPc,
TraceExitType::ExitType exitType /* = Normal */) {
gen(getExitOpcode(TraceExitType::Normal),
@@ -417,37 +320,10 @@ SSATmp* TraceBuilder::genCmp(Opcode opc, SSATmp* src1, SSATmp* src2) {
return gen(opc, src1, src2);
}
SSATmp* TraceBuilder::genJmp(Trace* targetTrace) {
assert(targetTrace);
return gen(Jmp_, getFirstBlock(targetTrace));
}
SSATmp* TraceBuilder::genJmpCond(SSATmp* boolSrc, Trace* target, bool negate) {
assert(target);
assert(boolSrc->type() == Type::Bool);
return gen(negate ? JmpZero : JmpNZero, getFirstBlock(target), boolSrc);
}
void TraceBuilder::genJmp(Block* target, SSATmp* src) {
gen(Jmp_, target, EdgeData(), src);
}
void TraceBuilder::genExitWhenSurprised(Trace* targetTrace) {
gen(ExitWhenSurprised, getFirstBlock(targetTrace));
}
void TraceBuilder::genExitOnVarEnv(Trace* targetTrace) {
gen(ExitOnVarEnv, getFirstBlock(targetTrace), m_fpValue);
}
void TraceBuilder::genReleaseVVOrExit(Trace* exit) {
gen(ReleaseVVOrExit, getFirstBlock(exit), m_fpValue);
}
void TraceBuilder::genGuardLoc(uint32_t id, Type type, Trace* exitTrace) {
SSATmp* prevValue = getLocalValue(id);
if (prevValue) {
genGuardType(prevValue, type, exitTrace);
gen(GuardType, type, exitTrace, prevValue);
return;
}
Type prevType = getLocalType(id);
@@ -479,55 +355,6 @@ SSATmp* TraceBuilder::genLdAssertedLoc(uint32_t id, Type type) {
return genLdLoc(id);
}
void TraceBuilder::genGuardStk(uint32_t id, Type type, Trace* exitTrace) {
gen(GuardStk, type, getFirstBlock(exitTrace), m_spValue,
genDefConst<int64_t>(id));
}
SSATmp* TraceBuilder::genGuardType(SSATmp* src,
Type type,
Trace* target) {
assert(target);
return gen(GuardType, type, getFirstBlock(target), src);
}
void TraceBuilder::genGuardRefs(SSATmp* funcPtr,
SSATmp* nParams,
SSATmp* bitsPtr,
SSATmp* firstBitNum,
SSATmp* mask64,
SSATmp* vals64,
Trace* exit) {
gen(GuardRefs,
getFirstBlock(exit),
funcPtr,
nParams,
bitsPtr,
firstBitNum,
mask64,
vals64);
}
SSATmp* TraceBuilder::genLdARFuncPtr(SSATmp* baseAddr, SSATmp* offset) {
return gen(LdARFuncPtr, baseAddr, offset);
}
SSATmp* TraceBuilder::genLdPropAddr(SSATmp* obj, SSATmp* prop) {
return gen(LdPropAddr, obj, prop);
}
SSATmp* TraceBuilder::genLdClsMethod(SSATmp* cls, uint32_t methodSlot) {
return gen(LdClsMethod, cls, genDefConst<int64_t>(methodSlot));
}
SSATmp* TraceBuilder::genLdClsMethodCache(SSATmp* className,
SSATmp* methodName,
SSATmp* baseClass,
Trace* exit) {
return gen(LdClsMethodCache, getFirstBlock(exit), className, methodName,
baseClass);
}
SSATmp* TraceBuilder::genBoxLoc(uint32_t id) {
SSATmp* prevValue = genLdLoc(id);
Type prevType = prevValue->type();
@@ -544,19 +371,10 @@ SSATmp* TraceBuilder::genBoxLoc(uint32_t id) {
prevValue = genDefInitNull();
}
SSATmp* newValue = gen(Box, prevValue);
genStLocAux(id, newValue, true);
gen(StLoc, LocalId(id), m_fpValue, newValue);
return newValue;
}
void TraceBuilder::genRaiseUninitLoc(uint32_t id) {
gen(RaiseUninitLoc,
genDefConst(m_curFunc->getValFunc()->localVarName(id)));
}
SSATmp* TraceBuilder::genLdAddr(SSATmp* base, int64_t offset) {
return gen(LdAddr, base, genDefConst<int64_t>(offset));
}
/**
* Returns an SSATmp containing the current value of the given local.
* This generates a LdLoc instruction if needed.
@@ -589,27 +407,13 @@ SSATmp* TraceBuilder::genLdLocAsCell(uint32_t id, Trace* exitTrace) {
return tmp;
}
// Unbox tmp into a cell via a LdRef
return genLdRef(tmp, type.innerType(), exitTrace);
return gen(LdRef, type.innerType(), exitTrace, tmp);
}
SSATmp* TraceBuilder::genLdLocAddr(uint32_t id) {
return gen(LdLocAddr, getLocalType(id).ptr(), LocalId(id), getFp());
}
void TraceBuilder::genStLocAux(uint32_t id, SSATmp* newValue, bool storeType) {
gen(storeType ? StLoc : StLocNT,
LocalId(id),
m_fpValue,
newValue);
}
/*
* Initializes a local to the provided state.
*/
void TraceBuilder::genInitLoc(uint32_t id, SSATmp* t0) {
genStLocAux(id, t0, true);
}
void TraceBuilder::genDecRefLoc(int id) {
Type type = getLocalType(id);
@@ -628,7 +432,7 @@ void TraceBuilder::genDecRefLoc(int id) {
}
if (val) {
if (setNull) {
genStLocAux(id, genDefUninit(), true);
gen(StLoc, LocalId(id), m_fpValue, genDefUninit());
}
genDecRef(val);
return;
@@ -677,7 +481,7 @@ void TraceBuilder::genBindLoc(uint32_t id,
// no need to store type with local value
genStoreType = false;
}
genStLocAux(id, newValue, genStoreType);
gen(genStoreType ? StLoc : StLocNT, LocalId(id), m_fpValue, newValue);
if (trackedType.maybeCounted() && doRefCount) {
genDecRef(prevValue);
}
@@ -705,7 +509,7 @@ SSATmp* TraceBuilder::genStLoc(uint32_t id,
Type trackedType = getLocalType(id);
assert(trackedType != Type::None); // tracelet guards guarantee a type
if (trackedType.notBoxed()) {
SSATmp* retVal = doRefCount ? genIncRef(newValue) : newValue;
SSATmp* retVal = doRefCount ? gen(IncRef, newValue) : newValue;
genBindLoc(id, newValue, doRefCount);
return retVal;
}
@@ -729,40 +533,12 @@ SSATmp* TraceBuilder::genStLoc(uint32_t id,
SSATmp* retVal = newValue;
if (doRefCount) {
retVal = genIncRef(newValue);
retVal = gen(IncRef, newValue);
genDecRef(prevValue);
}
return retVal;
}
SSATmp* TraceBuilder::genNewObj(int32_t numParams, SSATmp* cls) {
return gen(NewObj, cls, genDefConst<int64_t>(numParams), m_spValue, m_fpValue);
}
SSATmp* TraceBuilder::genNewObjCached(int32_t numParams,
const StringData* className) {
return gen(NewObjCached,
genDefConst<int64_t>(numParams),
genDefConst<const StringData*>(className),
m_spValue,
m_fpValue);
}
SSATmp* TraceBuilder::genNewObjNoCtorCached(const StringData* className) {
return gen(NewObjNoCtorCached,
genDefConst<const StringData*>(className),
m_spValue);
}
SSATmp* TraceBuilder::genNewArray(int32_t capacity) {
return gen(NewArray, genDefConst<int64_t>(capacity));
}
SSATmp* TraceBuilder::genNewTuple(int32_t numArgs, SSATmp* sp) {
assert(numArgs >= 0);
return gen(NewTuple, genDefConst<int64_t>(numArgs), sp);
}
/*
* Track down a value that was previously spilled onto the stack
* The spansCall parameter tracks whether the returned value's
@@ -953,35 +729,6 @@ SSATmp* TraceBuilder::genLdStackAddr(SSATmp* sp, int64_t index) {
return gen(LdStackAddr, type.ptr(), sp, genDefConst(index));
}
void TraceBuilder::genNativeImpl() {
gen(NativeImpl, m_curFunc, m_fpValue);
}
SSATmp* TraceBuilder::genInterpOne(uint32_t pcOff,
int32_t stackAdjustment,
Type resultType) {
return gen(InterpOne,
resultType,
m_fpValue,
m_spValue,
genDefConst<int64_t>(pcOff),
genDefConst<int64_t>(stackAdjustment));
}
SSATmp* TraceBuilder::genCall(SSATmp* actRec,
uint32_t returnBcOffset,
SSATmp* func,
uint32_t numParams,
SSATmp** params) {
SSATmp* srcs[numParams + 3];
srcs[0] = actRec;
srcs[1] = genDefConst<int64_t>(returnBcOffset);
srcs[2] = func;
std::copy(params, params + numParams, srcs + 3);
SSATmp** decayedPtr = srcs;
return gen(Call, std::make_pair(numParams + 3, decayedPtr));
}
SSATmp* TraceBuilder::genCallBuiltin(SSATmp* func,
Type type,
uint32_t numArgs,
@@ -993,18 +740,6 @@ SSATmp* TraceBuilder::genCallBuiltin(SSATmp* func,
return gen(CallBuiltin, type, std::make_pair(numArgs + 1, decayedPtr));
}
void TraceBuilder::genRetVal(SSATmp* val) {
gen(RetVal, m_fpValue, val);
}
SSATmp* TraceBuilder::genRetAdjustStack() {
return gen(RetAdjustStack, m_fpValue);
}
void TraceBuilder::genRetCtrl(SSATmp* sp, SSATmp* fp, SSATmp* retVal) {
gen(RetCtrl, sp, fp, retVal);
}
void TraceBuilder::genDecRefStack(Type type, uint32_t stackOff) {
bool spansCall = false;
Type knownType = Type::None;
@@ -1024,7 +759,7 @@ void TraceBuilder::genDecRefStack(Type type, uint32_t stackOff) {
void TraceBuilder::genDecRefThis() {
if (isThisAvailable()) {
auto const thiss = genLdThis(nullptr);
auto const thiss = gen(LdThis, m_fpValue);
auto const thisInst = thiss->inst();
if (thisInst->op() == IncRef &&
@@ -1042,22 +777,6 @@ void TraceBuilder::genDecRefThis() {
gen(DecRefThis, m_fpValue);
}
SSATmp* TraceBuilder::genGenericRetDecRefs(SSATmp* retVal, int numLocals) {
return gen(GenericRetDecRefs, m_fpValue, retVal,
genDefConst<int64_t>(numLocals));
}
void TraceBuilder::genIncStat(int32_t counter, int32_t value, bool force) {
gen(IncStat,
genDefConst<int64_t>(counter),
genDefConst<int64_t>(value),
genDefConst<bool>(force));
}
SSATmp* TraceBuilder::genIncRef(SSATmp* src) {
return gen(IncRef, src);
}
SSATmp* TraceBuilder::genSpillStack(uint32_t stackAdjustment,
uint32_t numOpnds,
SSATmp** spillOpnds) {
@@ -1092,83 +811,6 @@ SSATmp* TraceBuilder::genLdStack(int32_t stackOff, Type type) {
return tmp;
}
void TraceBuilder::genUnlinkContVarEnv() {
gen(UnlinkContVarEnv, m_fpValue);
}
void TraceBuilder::genLinkContVarEnv() {
gen(LinkContVarEnv, m_fpValue);
}
Trace* TraceBuilder::genContRaiseCheck(SSATmp* cont, Trace* target) {
assert(target);
gen(ContRaiseCheck, getFirstBlock(target), cont);
return target;
}
Trace* TraceBuilder::genContPreNext(SSATmp* cont, Trace* target) {
assert(target);
gen(ContPreNext, getFirstBlock(target), cont);
return target;
}
Trace* TraceBuilder::genContStartedCheck(SSATmp* cont, Trace* target) {
assert(target);
gen(ContStartedCheck, getFirstBlock(target), cont);
return target;
}
SSATmp* TraceBuilder::genIterNext(uint32_t iterId, uint32_t localId) {
// IterNext fpReg, iterId, localId
return gen(IterNext,
Type::Bool,
m_fpValue,
genDefConst<int64_t>(iterId),
genDefConst<int64_t>(localId));
}
SSATmp* TraceBuilder::genIterNextK(uint32_t iterId,
uint32_t valLocalId,
uint32_t keyLocalId) {
// IterNextK fpReg, iterId, valLocalId, keyLocalId
return gen(IterNextK,
Type::Bool,
m_fpValue,
genDefConst<int64_t>(iterId),
genDefConst<int64_t>(valLocalId),
genDefConst<int64_t>(keyLocalId));
}
SSATmp* TraceBuilder::genIterInit(SSATmp* src,
uint32_t iterId,
uint32_t valLocalId) {
// IterInit src, fpReg, iterId, valLocalId
return gen(IterInit,
Type::Bool,
src,
m_fpValue,
genDefConst<int64_t>(iterId),
genDefConst<int64_t>(valLocalId));
}
SSATmp* TraceBuilder::genIterInitK(SSATmp* src,
uint32_t iterId,
uint32_t valLocalId,
uint32_t keyLocalId) {
// IterInitK src, fpReg, iterId, valLocalId, keyLocalId
return gen(IterInitK,
Type::Bool,
src,
m_fpValue,
genDefConst<int64_t>(iterId),
genDefConst<int64_t>(valLocalId),
genDefConst<int64_t>(keyLocalId));
}
SSATmp* TraceBuilder::genIterFree(uint32_t iterId) {
return gen(IterFree, m_fpValue, genDefConst<int64_t>(iterId));
}
void TraceBuilder::updateTrackedState(IRInstruction* inst) {
Opcode opc = inst->op();
// Update tracked state of local values/types, stack/frame pointer, CSE, etc.
@@ -1575,6 +1217,32 @@ SSATmp* TraceBuilder::cseLookup(IRInstruction* inst) {
return getCSEHashTable(inst)->lookup(inst);
}
//////////////////////////////////////////////////////////////////////
SSATmp* TraceBuilder::preOptimizeLdThis(IRInstruction* inst) {
if (isThisAvailable()) inst->setTaken(nullptr);
return nullptr;
}
SSATmp* TraceBuilder::preOptimizeLdCtx(IRInstruction* inst) {
if (isThisAvailable()) return gen(LdThis, m_fpValue);
return nullptr;
}
SSATmp* TraceBuilder::preOptimize(IRInstruction* inst) {
#define X(op) case op: return preOptimize##op(inst)
switch (inst->op()) {
X(LdThis);
X(LdCtx);
default:
break;
}
#undef X
return nullptr;
}
//////////////////////////////////////////////////////////////////////
SSATmp* TraceBuilder::optimizeWork(IRInstruction* inst) {
static DEBUG_ONLY __thread int instNest = 0;
if (debug) ++instNest;
@@ -1583,6 +1251,16 @@ SSATmp* TraceBuilder::optimizeWork(IRInstruction* inst) {
FTRACE(1, "{}{}\n", indent(), inst->toString());
// First pass of tracebuilder optimizations try to replace an
// instruction based on tracked state before we do anything else.
// May mutate the IRInstruction in place (and return nullptr) or
// return an SSATmp*.
if (SSATmp* preOpt = preOptimize(inst)) {
FTRACE(1, " {}preOptimize returned: {}\n",
indent(), preOpt->inst()->toString());
return preOpt;
}
// copy propagation on inst source operands
copyProp(inst);
+15 -93
Ver Arquivo
@@ -86,18 +86,8 @@ public:
return instr;
}
SSATmp* genDefCns(const StringData* cnsName, SSATmp* val);
SSATmp* genConcat(SSATmp* tl, SSATmp* tr);
SSATmp* genLdThis(Trace* trace);
SSATmp* genLdCtx(const Func* func);
SSATmp* genLdRetAddr();
SSATmp* genLdRaw(SSATmp* base, RawMemSlot::Kind kind, Type type);
void genStRaw(SSATmp* base, RawMemSlot::Kind kind, SSATmp* value);
SSATmp* genLdLoc(uint32_t id);
SSATmp* genLdLocAddr(uint32_t id);
void genRaiseUninitLoc(uint32_t id);
/*
* Returns an SSATmp containing the (inner) value of the given local.
@@ -121,47 +111,20 @@ public:
bool doRefCount,
bool genStoreType,
Trace* exit);
SSATmp* genLdMem(SSATmp* addr, Type type, Trace* target);
SSATmp* genLdMem(SSATmp* addr, int64_t offset,
Type type, Trace* target);
void genStMem(SSATmp* addr, SSATmp* src, bool genStoreType);
void genStMem(SSATmp* addr, int64_t offset, SSATmp* src, bool stType);
SSATmp* genLdProp(SSATmp* obj, SSATmp* prop, Type type, Trace* exit);
void genStProp(SSATmp* obj, SSATmp* prop, SSATmp* src, bool genStoreType);
void genSetPropCell(SSATmp* base, int64_t offset, SSATmp* value);
SSATmp* genBoxLoc(uint32_t id);
void genBindLoc(uint32_t id, SSATmp* ref, bool doRefCount = true);
void genInitLoc(uint32_t id, SSATmp* t);
void genCheckClsCnsDefined(SSATmp* cns, Trace* exitTrace);
SSATmp* genLdCurFuncPtr();
SSATmp* genLdARFuncPtr(SSATmp* baseAddr, SSATmp* offset);
SSATmp* genLdFuncCls(SSATmp* func);
SSATmp* genNewObjNoCtorCached(const StringData* className);
SSATmp* genNewObjCached(int32_t numParams, const StringData* clsName);
SSATmp* genNewObj(int32_t numParams, SSATmp* cls);
SSATmp* genNewArray(int32_t capacity);
SSATmp* genNewTuple(int32_t numArgs, SSATmp* sp);
void genGuardLoc(uint32_t id, Type type, Trace* exitTrace);
void genGuardStk(uint32_t id, Type type, Trace* exitTrace);
void genAssertStk(uint32_t id, Type type);
SSATmp* genGuardType(SSATmp* src, Type type, Trace* nextTrace);
void genGuardRefs(SSATmp* funcPtr,
SSATmp* nParams,
SSATmp* bitsPtr,
SSATmp* firstBitNum,
SSATmp* mask64,
SSATmp* vals64,
Trace* exitTrace);
void genAssertLoc(uint32_t id,
Type type,
bool override = false); // ignores conflict w/ prev type
SSATmp* genUnboxPtr(SSATmp* ptr);
SSATmp* genLdRef(SSATmp* ref, Type type, Trace* exit);
SSATmp* genAdd(SSATmp* src1, SSATmp* src2);
SSATmp* genLdAddr(SSATmp* base, int64_t offset);
SSATmp* genSub(SSATmp* src1, SSATmp* src2);
SSATmp* genMul(SSATmp* src1, SSATmp* src2);
@@ -176,42 +139,16 @@ public:
SSATmp* genPtrToInitNull();
SSATmp* genPtrToUninit();
SSATmp* genDefNone();
SSATmp* genJmp(Trace* target);
SSATmp* genJmpCond(SSATmp* src, Trace* target, bool negate);
void genJmp(Block* target, SSATmp* src);
void genExitWhenSurprised(Trace* target);
void genExitOnVarEnv(Trace* target);
void genCheckInit(SSATmp* src, Trace* target) {
gen(CheckInit, getFirstBlock(target), src);
}
SSATmp* genCmp(Opcode opc, SSATmp* src1, SSATmp* src2);
SSATmp* genCastStk(uint32_t id, Type type);
SSATmp* genConvToBool(SSATmp* src);
SSATmp* genLdPropAddr(SSATmp* obj, SSATmp* prop);
SSATmp* genLdClsMethod(SSATmp* cls, uint32_t methodSlot);
SSATmp* genLdClsMethodCache(SSATmp* className,
SSATmp* methodName,
SSATmp* baseClass,
Trace* slowPathExit);
SSATmp* genCall(SSATmp* actRec,
uint32_t returnBcOffset,
SSATmp* func,
uint32_t numParams,
SSATmp** params);
SSATmp* genCallBuiltin(SSATmp* func, Type type,
uint32_t numArgs, SSATmp** args);
void genReleaseVVOrExit(Trace* exit);
SSATmp* genGenericRetDecRefs(SSATmp* retVal, int numLocals);
void genRetVal(SSATmp* val);
SSATmp* genRetAdjustStack();
void genRetCtrl(SSATmp* sp, SSATmp* fp, SSATmp* retAddr);
void genDecRef(SSATmp* tmp);
void genDecRefMem(SSATmp* base, int64_t offset, Type type);
void genDecRefStack(Type type, uint32_t stackOff);
void genDecRefLoc(int id);
void genDecRefThis();
void genIncStat(int32_t counter, int32_t value, bool force = false);
SSATmp* genIncRef(SSATmp* src);
SSATmp* genSpillStack(uint32_t stackAdjustment,
uint32_t numOpnds,
SSATmp** opnds);
@@ -221,25 +158,6 @@ public:
return genLdStackAddr(m_spValue, offset);
}
void genNativeImpl();
void genUnlinkContVarEnv();
void genLinkContVarEnv();
Trace* genContRaiseCheck(SSATmp* cont, Trace* target);
Trace* genContPreNext(SSATmp* cont, Trace* target);
Trace* genContStartedCheck(SSATmp* cont, Trace* target);
SSATmp* genIterInit(SSATmp* src, uint32_t iterId, uint32_t valLocalId);
SSATmp* genIterInitK(SSATmp* src,
uint32_t iterId,
uint32_t valLocalId,
uint32_t keyLocalId);
SSATmp* genIterNext(uint32_t iterId, uint32_t valLocalId);
SSATmp* genIterNextK(uint32_t iterId, uint32_t valLocalId, uint32_t keyLocalId);
SSATmp* genIterFree(uint32_t iterId);
SSATmp* genInterpOne(uint32_t pcOff, int32_t stackAdjustment,
Type resultType);
Trace* getExitSlowTrace(uint32_t bcOff,
int32_t stackDeficit,
uint32_t numOpnds,
@@ -283,6 +201,10 @@ public:
return gen(DefConst, type, ConstData(val));
}
SSATmp* genDefConst(Type t) {
return gen(DefConst, t, ConstData(0));
}
template<typename T>
SSATmp* genLdConst(T val) {
return gen(LdConst, typeForConst(val), ConstData(val));
@@ -334,10 +256,10 @@ public:
DisableCseGuard guard(*this);
branch(taken_block);
SSATmp* v1 = next();
genJmp(done_block, v1);
gen(Jmp_, done_block, EdgeData(), v1);
appendBlock(taken_block);
SSATmp* v2 = taken();
genJmp(done_block, v2);
gen(Jmp_, done_block, EdgeData(), v2);
appendBlock(done_block);
SSATmp* result = done_block->getLabel()->getDst(0);
result->setType(Type::unionOf(v1->type(), v2->type()));
@@ -395,13 +317,19 @@ public:
appendBlock(done_block);
}
private:
SSATmp* preOptimizeLdThis(IRInstruction*);
SSATmp* preOptimizeLdCtx(IRInstruction*);
SSATmp* preOptimize(IRInstruction* inst);
SSATmp* optimizeWork(IRInstruction* inst);
SSATmp* optimizeInst(IRInstruction* inst);
private:
static void appendInstruction(IRInstruction* inst, Block* block);
void appendInstruction(IRInstruction* inst);
void appendBlock(Block* block);
enum CloneInstMode { kCloneInst, kUseInst };
SSATmp* optimizeWork(IRInstruction* inst);
SSATmp* optimizeInst(IRInstruction* inst);
SSATmp* cseLookup(IRInstruction* inst);
void cseInsert(IRInstruction* inst);
void cseKill(SSATmp* src);
@@ -421,7 +349,6 @@ private:
Trace* makeTrace(const Func* func, uint32_t bcOff) {
return new Trace(m_irFactory.defBlock(func), bcOff);
}
void genStLocAux(uint32_t id, SSATmp* t0, bool genStoreType);
// Saved state information associated with the start of a block, or
// for the caller of an inlined function.
@@ -514,11 +441,6 @@ private:
std::vector<std::unique_ptr<State>> m_inlineSavedStates;
};
template<>
inline SSATmp* TraceBuilder::genDefConst(Type t) {
return gen(DefConst, t, ConstData(0));
}
}}}
#endif
@@ -305,7 +305,7 @@ void HhbcTranslator::VectorTranslator::emit() {
// a null pointer if it's not needed.
SSATmp* HhbcTranslator::VectorTranslator::genMisPtr() {
if (m_needMIS) {
return m_tb.genLdAddr(m_misBase, kReservedRSPSpillSpace);
return m_tb.gen(LdAddr, m_misBase, cns(kReservedRSPSpillSpace));
} else {
return m_tb.gen(DefConst, Type::PtrToCell, ConstData(nullptr));
}
@@ -400,8 +400,8 @@ void HhbcTranslator::VectorTranslator::emitMPre() {
SSATmp* uninit = m_tb.genDefUninit();
if (nLogicalRatchets() > 0) {
m_tb.genStMem(m_misBase, HHIR_MISOFF(tvRef), uninit, true);
m_tb.genStMem(m_misBase, HHIR_MISOFF(tvRef2), uninit, true);
m_tb.gen(StMem, m_misBase, cns(HHIR_MISOFF(tvRef)), uninit);
m_tb.gen(StMem, m_misBase, cns(HHIR_MISOFF(tvRef2)), uninit);
}
}
@@ -541,7 +541,7 @@ SSATmp* HhbcTranslator::VectorTranslator::getInput(unsigned i) {
return cns(l.offset);
case Location::This:
return m_tb.genLdThis(nullptr);
return m_tb.gen(LdThis, m_tb.getFp());
default: not_reached();
}
@@ -630,7 +630,7 @@ bool HhbcTranslator::VectorTranslator::isSingleMember() {
}
void HhbcTranslator::VectorTranslator::emitBaseH() {
m_base = m_tb.genLdThis(nullptr);
m_base = m_tb.gen(LdThis, m_tb.getFp());
}
void HhbcTranslator::VectorTranslator::emitBaseN() {
@@ -884,7 +884,7 @@ void HhbcTranslator::VectorTranslator::emitPropSpecialized(const MInstrAttr mia,
* check against null here in the intermediate cases.
*/
if (m_base->isA(Type::Obj)) {
SSATmp* propAddr = m_tb.genLdPropAddr(m_base, cns(propInfo.offset));
SSATmp* propAddr = m_tb.gen(LdPropAddr, m_base, cns(propInfo.offset));
m_base = checkInitProp(m_base, propAddr, propInfo, doWarn, doDefine);
} else {
SSATmp* baseAsObj = nullptr;
@@ -896,8 +896,8 @@ void HhbcTranslator::VectorTranslator::emitPropSpecialized(const MInstrAttr mia,
[&] { // Next: Base is an object. Load property address and
// check for uninit
return checkInitProp(baseAsObj,
m_tb.genLdPropAddr(baseAsObj,
cns(propInfo.offset)),
m_tb.gen(LdPropAddr, baseAsObj,
cns(propInfo.offset)),
propInfo,
doWarn,
doDefine);
@@ -1043,19 +1043,20 @@ void HhbcTranslator::VectorTranslator::emitRatchetRefs() {
[&] { // Next: tvRef isn't Uninit. Ratchet the refs
// Clean up tvRef2 before overwriting it.
if (ratchetInd() > 0) {
m_tb.genDecRefMem(m_misBase, HHIR_MISOFF(tvRef2), Type::Gen);
m_tb.gen(DecRefMem, Type::Gen, m_misBase, cns(HHIR_MISOFF(tvRef2)));
}
// Copy tvRef to tvRef2. Use mmx at some point
SSATmp* tvRef = m_tb.genLdMem(m_misBase, HHIR_MISOFF(tvRef), Type::Gen,
nullptr);
m_tb.genStMem(m_misBase, HHIR_MISOFF(tvRef2), tvRef, true);
SSATmp* tvRef = m_tb.gen(
LdMem, Type::Gen, m_misBase, cns(HHIR_MISOFF(tvRef))
);
m_tb.gen(StMem, m_misBase, cns(HHIR_MISOFF(tvRef2)), tvRef);
// Reset tvRef.
m_tb.genStMem(m_misBase, HHIR_MISOFF(tvRef), m_tb.genDefUninit(), true);
m_tb.gen(StMem, m_misBase, cns(HHIR_MISOFF(tvRef)), m_tb.genDefUninit());
// Adjust base pointer.
assert(m_base->type().isPtr());
return m_tb.genLdAddr(m_misBase, HHIR_MISOFF(tvRef2));
return m_tb.gen(LdAddr, m_misBase, cns(HHIR_MISOFF(tvRef2)));
},
[&] { // Taken: tvRef is Uninit. Do nothing.
return m_base;
@@ -1143,9 +1144,9 @@ void HhbcTranslator::VectorTranslator::emitCGetProp() {
m_mii, m_mInd, m_iInd);
if (propInfo.offset != -1) {
emitPropSpecialized(MIA_warn, propInfo);
SSATmp* cellPtr = m_tb.genUnboxPtr(m_base);
SSATmp* cellPtr = m_tb.gen(UnboxPtr, m_base);
SSATmp* propVal = m_tb.gen(LdMem, Type::Cell, cellPtr, cns(0));
m_result = m_tb.genIncRef(propVal);
m_result = m_tb.gen(IncRef, propVal);
return;
}
@@ -1277,10 +1278,10 @@ void HhbcTranslator::VectorTranslator::emitSetProp() {
m_mii, m_mInd, m_iInd);
if (propInfo.offset != -1) {
emitPropSpecialized(MIA_define, propInfo);
SSATmp* cellPtr = m_tb.genUnboxPtr(m_base);
SSATmp* cellPtr = m_tb.gen(UnboxPtr, m_base);
SSATmp* oldVal = m_tb.gen(LdMem, Type::Cell, cellPtr, cns(0));
// The object owns a reference now
SSATmp* increffed = m_tb.genIncRef(value);
SSATmp* increffed = m_tb.gen(IncRef, value);
m_tb.gen(StMem, cellPtr, cns(0), value);
m_tb.genDecRef(oldVal);
m_result = increffed;
@@ -1337,7 +1338,7 @@ void HhbcTranslator::VectorTranslator::emitSetOpProp() {
# define SETOP_OP(op, bcOp) HELPER_TABLE(FILL_ROW, op)
BUILD_OPTAB_ARG(SETOP_OPS, op, m_base->isA(Type::Obj));
# undef SETOP_OP
m_tb.genStRaw(m_misBase, RawMemSlot::MisCtx, CTX());
m_tb.gen(StRaw, m_misBase, cns(RawMemSlot::MisCtx), CTX());
m_ht.exceptionBarrier();
m_result =
genStk(SetOpProp, cns((TCA)opFunc), m_base, key, value, genMisPtr());
@@ -2057,10 +2058,10 @@ void HhbcTranslator::VectorTranslator::emitMPost() {
// Clean up tvRef(2)
if (nLogicalRatchets() > 1) {
m_tb.genDecRefMem(m_misBase, HHIR_MISOFF(tvRef2), Type::Gen);
m_tb.gen(DecRefMem, Type::Gen, m_misBase, cns(HHIR_MISOFF(tvRef2)));
}
if (nLogicalRatchets() > 0) {
m_tb.genDecRefMem(m_misBase, HHIR_MISOFF(tvRef), Type::Gen);
m_tb.gen(DecRefMem, Type::Gen, m_misBase, cns(HHIR_MISOFF(tvRef)));
}
}