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:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário