Move gen{Guard,Assert}Loc logic to updateTrackedEffects/preOptimize

GuardLoc drops into preOptimize.  genAssertLoc did two things
based on a bool---one of which needed logic in preOptimize, and the
other which implied something for updateTrackedEffects (and was
handled in hhbctranslator).  Also removes genLdAssertedLoc---it's not
an instruction; I considered an emitLdAssertedLoc but since this is
only used in a few places (less than a LdIncRefLoc would be) it seemed
fine to just flatten.
Esse commit está contido em:
Jordan DeLong
2013-04-24 21:30:23 -07:00
commit de Sara Golemon
commit 0f752932cf
6 arquivos alterados com 74 adições e 62 exclusões
+5
Ver Arquivo
@@ -343,6 +343,11 @@ AssertLoc<T,localId> S0:FramePtr
GuardLoc except it doesn't imply a runtime check and cannot cause
control flow.
OverrideLoc<T,localId> S0:StkPtr
Overrides tracked information about the type of a local in frame S0.
This is used to fix tracked state after InterpOne instructions.
D:StkPtr = GuardStk<T> S0:StkPtr S1:ConstInt -> L
Check that the type of the cell on the stack pointed to by S0 at
@@ -303,6 +303,7 @@ NOOP_OPCODE(DefFP)
NOOP_OPCODE(DefSP)
NOOP_OPCODE(Marker)
NOOP_OPCODE(AssertLoc)
NOOP_OPCODE(OverrideLoc)
NOOP_OPCODE(AssertStk)
NOOP_OPCODE(Nop)
NOOP_OPCODE(DefLabel)
+22 -17
Ver Arquivo
@@ -889,7 +889,13 @@ void HhbcTranslator::emitCreateCont(bool getArgs,
SSATmp* locals = gen(LdContLocalsPtr, cont);
for (int i = 0; i < origLocals; ++i) {
SSATmp* loc = gen(IncRef, m_tb->genLdAssertedLoc(i, Type::Gen));
// We must generate an AssertLoc because we don't have tracelet
// guards on the object type in these outer generator functions.
gen(AssertLoc, Type::Gen, LocalId(i), m_tb->getFp());
auto const loc = gen(
IncRef,
m_tb->genLdLoc(i)
);
gen(
StMem,
locals,
@@ -960,13 +966,15 @@ void HhbcTranslator::emitContExit() {
void HhbcTranslator::emitUnpackCont() {
gen(LinkContVarEnv, m_tb->getFp());
SSATmp* cont = m_tb->genLdAssertedLoc(0, Type::Obj);
gen(AssertLoc, Type::Obj, LocalId(0), m_tb->getFp());
auto const cont = m_tb->genLdLoc(0);
push(gen(LdRaw, Type::Int, cont, cns(RawMemSlot::ContLabel)));
}
void HhbcTranslator::emitPackCont(int64_t labelId) {
gen(UnlinkContVarEnv, m_tb->getFp());
SSATmp* cont = m_tb->genLdAssertedLoc(0, Type::Obj);
gen(AssertLoc, Type::Obj, LocalId(0), m_tb->getFp());
auto const cont = m_tb->genLdLoc(0);
m_tb->genSetPropCell(cont, CONTOFF(m_value), popC());
gen(
StRaw, cont, cns(RawMemSlot::ContLabel), cns(labelId)
@@ -974,7 +982,8 @@ void HhbcTranslator::emitPackCont(int64_t labelId) {
}
void HhbcTranslator::emitContReceive() {
SSATmp* cont = m_tb->genLdAssertedLoc(0, Type::Obj);
gen(AssertLoc, Type::Obj, LocalId(0), m_tb->getFp());
auto const cont = m_tb->genLdLoc(0);
gen(ContRaiseCheck, getExitSlowTrace(), cont);
auto const valOffset = cns(CONTOFF(m_received));
push(gen(LdProp, Type::Cell, cont, valOffset));
@@ -982,7 +991,8 @@ void HhbcTranslator::emitContReceive() {
}
void HhbcTranslator::emitContRetC() {
SSATmp* cont = m_tb->genLdAssertedLoc(0, Type::Obj);
gen(AssertLoc, Type::Obj, LocalId(0), m_tb->getFp());
auto const cont = m_tb->genLdLoc(0);
gen(ExitWhenSurprised, getExitSlowTrace());
gen(
StRaw, cont, cns(RawMemSlot::ContDone), cns(true)
@@ -1006,8 +1016,8 @@ void HhbcTranslator::emitContSendImpl(bool raise) {
gen(ContStartedCheck, getExitSlowTrace(), cont);
gen(ContPreNext, getExitSlowTrace(), cont);
SSATmp* value = m_tb->genLdAssertedLoc(0, Type::Cell);
value = gen(IncRef, value);
gen(AssertLoc, Type::Cell, LocalId(0), m_tb->getFp());
auto const value = gen(IncRef, m_tb->genLdLoc(0));
m_tb->genSetPropCell(cont, CONTOFF(m_received), value);
if (raise) {
gen(
@@ -2105,20 +2115,15 @@ void HhbcTranslator::guardTypeLocal(uint32_t locId, Type type) {
}
void HhbcTranslator::checkTypeLocal(uint32_t locId, Type type) {
m_tb->genGuardLoc(locId, type, getExitTrace());
gen(GuardLoc, type, getExitTrace(), LocalId(locId), m_tb->getFp());
}
void HhbcTranslator::assertTypeLocal(uint32_t localIndex, Type type) {
m_tb->genAssertLoc(localIndex, type, false);
void HhbcTranslator::assertTypeLocal(uint32_t locId, Type type) {
gen(AssertLoc, type, LocalId(locId), m_tb->getFp());
}
void HhbcTranslator::overrideTypeLocal(uint32_t localIndex, Type type) {
// if changing the inner type of a boxed local, also drop the
// information about inner types for any other boxed local
if (type.isBoxed()) {
m_tb->dropLocalRefsInnerTypes();
}
m_tb->genAssertLoc(localIndex, type, true);
void HhbcTranslator::overrideTypeLocal(uint32_t locId, Type type) {
gen(OverrideLoc, type, LocalId(locId), m_tb->getFp());
}
Trace* HhbcTranslator::guardTypeStack(uint32_t stackIndex,
+2
Ver Arquivo
@@ -172,6 +172,7 @@ O(CastStk, D(StkPtr), S(StkPtr) C(Int), Mem|N|Er) \
O(AssertStk, D(StkPtr), S(StkPtr) C(Int), E) \
O(GuardRefs, ND, SUnk, E) \
O(AssertLoc, ND, S(FramePtr), E) \
O(OverrideLoc, ND, S(FramePtr), E) \
O(OpAdd, DArith, SNum SNum, C) \
O(OpSub, DArith, SNum SNum, C) \
O(OpAnd, D(Int), SNumInt SNumInt, C) \
@@ -812,6 +813,7 @@ X(Marker, MarkerData);
X(RaiseUninitLoc, LocalId);
X(GuardLoc, LocalId);
X(AssertLoc, LocalId);
X(OverrideLoc, LocalId);
X(LdLocAddr, LocalId);
X(DecRefLoc, LocalId);
X(LdLoc, LocalId);
+42 -35
Ver Arquivo
@@ -263,41 +263,6 @@ SSATmp* TraceBuilder::genCmp(Opcode opc, SSATmp* src1, SSATmp* src2) {
return gen(opc, src1, src2);
}
void TraceBuilder::genGuardLoc(uint32_t id, Type type, Trace* exitTrace) {
SSATmp* prevValue = getLocalValue(id);
if (prevValue) {
gen(GuardType, type, exitTrace, prevValue);
return;
}
Type prevType = getLocalType(id);
if (prevType == Type::None) {
gen(GuardLoc, type, getFirstBlock(exitTrace), LocalId(id), m_fpValue);
} else {
// It doesn't make sense to be guarding on something that's deemed to fail
assert(prevType == type);
}
}
/**
* Generates an AssertLoc instruction for the given local 'id' and 'type'.
* If the 'override' flag is not set, then 'type' must be a subtype of the
* previous tracked type for this local.
*/
void TraceBuilder::genAssertLoc(uint32_t id, Type type,
bool overrideType /* =false */) {
Type prevType = overrideType ? Type::None : getLocalType(id);
if (prevType == Type::None || type.strictSubtypeOf(prevType)) {
gen(AssertLoc, type, LocalId(id), m_fpValue);
} else {
assert(prevType == type || prevType.strictSubtypeOf(type));
}
}
SSATmp* TraceBuilder::genLdAssertedLoc(uint32_t id, Type type) {
genAssertLoc(id, type);
return genLdLoc(id);
}
SSATmp* TraceBuilder::genBoxLoc(uint32_t id) {
SSATmp* prevValue = genLdLoc(id);
Type prevType = prevValue->type();
@@ -867,6 +832,13 @@ void TraceBuilder::updateTrackedState(IRInstruction* inst) {
setLocalValue(inst->getExtra<LdLoc>()->locId, inst->getDst());
break;
case OverrideLoc:
// If changing the inner type of a boxed local, also drop the
// information about inner types for any other boxed locals.
if (inst->getTypeParam().isBoxed()) {
dropLocalRefsInnerTypes();
}
// fallthrough
case AssertLoc:
case GuardLoc:
setLocalType(inst->getExtra<LocalId>()->locId,
@@ -1162,6 +1134,39 @@ SSATmp* TraceBuilder::cseLookup(IRInstruction* inst) {
//////////////////////////////////////////////////////////////////////
SSATmp* TraceBuilder::preOptimizeGuardLoc(IRInstruction* inst) {
auto const locId = inst->getExtra<GuardLoc>()->locId;
if (auto const prevValue = getLocalValue(locId)) {
return gen(
GuardType, inst->getTypeParam(), inst->getTaken(), prevValue
);
}
auto const prevType = getLocalType(locId);
if (prevType != Type::None) {
// It doesn't make sense to be guarding on something that's deemed
// to fail.
assert(prevType == inst->getTypeParam());
inst->convertToNop();
}
return nullptr;
}
SSATmp* TraceBuilder::preOptimizeAssertLoc(IRInstruction* inst) {
auto const locId = inst->getExtra<AssertLoc>()->locId;
auto const prevType = getLocalType(locId);
auto const typeParam = inst->getTypeParam();
if (prevType != Type::None && !typeParam.strictSubtypeOf(prevType)) {
assert(prevType.subtypeOf(typeParam));
inst->convertToNop();
}
return nullptr;
}
SSATmp* TraceBuilder::preOptimizeLdThis(IRInstruction* inst) {
if (isThisAvailable()) inst->setTaken(nullptr);
return nullptr;
@@ -1198,6 +1203,8 @@ SSATmp* TraceBuilder::preOptimizeDecRef(IRInstruction* inst) {
SSATmp* TraceBuilder::preOptimize(IRInstruction* inst) {
#define X(op) case op: return preOptimize##op(inst)
switch (inst->op()) {
X(GuardLoc);
X(AssertLoc);
X(LdThis);
X(LdCtx);
X(DecRef);
+2 -10
Ver Arquivo
@@ -100,12 +100,6 @@ public:
*/
SSATmp* genLdLocAsCell(uint32_t id, Trace* exitTrace);
/*
* Asserts that local 'id' has type 'type' and loads it into the
* returned SSATmp.
*/
SSATmp* genLdAssertedLoc(uint32_t id, Type type);
SSATmp* genStLoc(uint32_t id,
SSATmp* src,
bool doRefCount,
@@ -116,11 +110,7 @@ public:
SSATmp* genBoxLoc(uint32_t id);
void genBindLoc(uint32_t id, SSATmp* ref, bool doRefCount = true);
void genGuardLoc(uint32_t id, Type type, Trace* exitTrace);
void genAssertStk(uint32_t id, Type type);
void genAssertLoc(uint32_t id,
Type type,
bool override = false); // ignores conflict w/ prev type
// TODO(#2058865): we should have a real not opcode
SSATmp* genNot(SSATmp* src);
@@ -309,6 +299,8 @@ public:
}
private:
SSATmp* preOptimizeGuardLoc(IRInstruction*);
SSATmp* preOptimizeAssertLoc(IRInstruction*);
SSATmp* preOptimizeLdThis(IRInstruction*);
SSATmp* preOptimizeLdCtx(IRInstruction*);
SSATmp* preOptimizeDecRef(IRInstruction*);