Use IRExtraData to link ExitTrace[cc] with smashable jumps

Use a new ExitData subclass of IRExtraData to link ExitTrace[Cc]
with the Jmp or Jcc that ends the trace, so the Jmp/Jcc can be
smashed later.  SSATmps should represent runtime values, whereas
these instr->instr pointers are for internal compiler use.
Esse commit está contido em:
smith
2013-02-26 11:48:17 -08:00
commit de Sara Golemon
commit 884ff2d218
6 arquivos alterados com 36 adições e 38 exclusões
+4 -10
Ver Arquivo
@@ -868,20 +868,14 @@ D:StkPtr = SpillStack S0:StkP S1:ConstInt, S2...
11. Trace exits
ExitTrace S0:ConstFunc S1:ConstInt S2:StkPtr S3:StkPtr
[S4:TCA]
ExitTrace<toSmash> S0:ConstFunc S1:ConstInt S2:StkPtr S3:StkPtr
Unconditional exit to bytecode offset S1 in function S0. S2 and
S3 are the VM stack and frame pointers, respectively. If given,
S4 is the address of a jmp instruction to patch later.
toSmash points to a jump or branch instruction to patch later.
[Implementation note. S4 refers to a branch instruction, but the
type is really None. We access the branch instruction to find
the TCA to use, at compile time. In effect, S4 is simply a
compile-time pointer to the IRInstruction to patch].
ExitTraceCc S0:ConstFunc S1:ConstInt S2:StkPtr S3:StkPtr
S4:ConstInt [S5:TCA]
ExitTraceCc<toSmash> S0:ConstFunc S1:ConstInt S2:StkPtr S3:StkPtr
S4:ConstInt
Exit conditionally to bytecode offset S1 or S4 in function S0.
S4 is bytecode address to exit to if the condition is false.
+10 -11
Ver Arquivo
@@ -393,7 +393,7 @@ Address CodeGenerator::emitFwdJmp(Block* target) {
}
// Patch with service request EMIT_BIND_JMP
Address CodeGenerator::emitSmashableFwdJmp(Block* target, SSATmp* toSmash) {
Address CodeGenerator::emitSmashableFwdJmp(Block* target, IRInstruction* toSmash) {
Address start = m_as.code.frontier;
if (toSmash) {
m_tx64->prepareForSmash(m_as, TranslatorX64::kJmpLen);
@@ -408,7 +408,7 @@ Address CodeGenerator::emitSmashableFwdJmp(Block* target, SSATmp* toSmash) {
// Patch with service request REQ_BIND_JMPCC_FIRST/SECOND
Address CodeGenerator::emitSmashableFwdJccAtEnd(ConditionCode cc, Block* target,
SSATmp* toSmash) {
IRInstruction* toSmash) {
Address start = m_as.code.frontier;
if (toSmash) {
m_tx64->prepareForSmash(m_as, TranslatorX64::kJmpLen +
@@ -425,14 +425,13 @@ Address CodeGenerator::emitSmashableFwdJccAtEnd(ConditionCode cc, Block* target,
void CodeGenerator::emitJccDirectExit(IRInstruction* inst,
ConditionCode cc) {
if (cc == CC_None) return;
SSATmp* toSmash = inst->getTCA() == kIRDirectJccJmpActive
? inst->getDst() : nullptr;
auto* toSmash = inst->getTCA() == kIRDirectJccJmpActive ? inst : nullptr;
emitSmashableFwdJccAtEnd(cc, inst->getTaken(), toSmash);
}
// Patch with service request REQ_BIND_JCC
Address CodeGenerator::emitSmashableFwdJcc(ConditionCode cc, Block* target,
SSATmp* toSmash) {
IRInstruction* toSmash) {
Address start = m_as.code.frontier;
assert(toSmash);
@@ -2250,20 +2249,20 @@ void CodeGenerator::cgExitTrace(IRInstruction* inst) {
SSATmp* sp = inst->getSrc(2);
SSATmp* fp = inst->getSrc(3);
SSATmp* notTakenPC = nullptr;
SSATmp* toSmash = nullptr;
IRInstruction* toSmash = nullptr;
assert(pc->isConst() && inst->getNumSrcs() <= 6);
TraceExitType::ExitType exitType = getExitType(inst->getOpcode());
if (exitType == TraceExitType::Normal && inst->getNumSrcs() == 5) {
if (exitType == TraceExitType::Normal && inst->getExtra<ExitTrace>()) {
// Unconditional trace exit
toSmash = inst->getSrc(4);
toSmash = inst->getExtra<ExitTrace>()->toSmash;
assert(toSmash);
} else if (exitType == TraceExitType::NormalCc) {
// Exit at trace end which is the target of a conditional branch
notTakenPC = inst->getSrc(4);
assert(notTakenPC->isConst());
if (inst->getNumSrcs() == 6) {
toSmash = inst->getSrc(5);
if (inst->getExtra<ExitTraceCc>()) {
toSmash = inst->getExtra<ExitTraceCc>()->toSmash;
assert(toSmash);
}
}
@@ -2288,7 +2287,7 @@ void CodeGenerator::cgExitTrace(IRInstruction* inst) {
break;
}
// Patch the original jcc;jmp, don't emit another
IRInstruction* jcc = toSmash->getInstruction();
IRInstruction* jcc = toSmash;
Opcode opc = jcc->getOpcode();
ConditionCode cc = queryJmpToCC(opc);
uint64_t taken = pc->getValInt();
+3 -3
Ver Arquivo
@@ -268,12 +268,12 @@ private:
Address emitFwdJcc(Asm& a, ConditionCode cc, Block* target);
Address emitFwdJmp(Asm& as, Block* target);
Address emitFwdJmp(Block* target);
Address emitSmashableFwdJmp(Block* target, SSATmp* toSmash);
Address emitSmashableFwdJmp(Block* target, IRInstruction* toSmash);
Address emitSmashableFwdJccAtEnd(ConditionCode cc, Block* target,
SSATmp* toSmash);
IRInstruction* toSmash);
void emitJccDirectExit(IRInstruction*, ConditionCode);
Address emitSmashableFwdJcc(ConditionCode cc, Block* target,
SSATmp* toSmash);
IRInstruction* toSmash);
void emitGuardOrFwdJcc(IRInstruction* inst, ConditionCode cc);
void emitContVarEnvHelperCall(SSATmp* fp, TCA helper);
const Func* getCurFunc() const;
+2 -5
Ver Arquivo
@@ -973,11 +973,8 @@ TCA SSATmp::getValTCA() const {
return m_inst->getExtra<ConstData>()->as<TCA>();
}
void SSATmp::setTCA(TCA tca) {
getInstruction()->setTCA(tca);
}
TCA SSATmp::getTCA() const {
return getInstruction()->getTCA();
std::string ExitData::show() const {
return folly::to<std::string>(toSmash->getIId());
}
std::string SSATmp::toString() const {
+13 -4
Ver Arquivo
@@ -558,6 +558,17 @@ struct EdgeData : IRExtraData {
EdgeData* next; // next edge to same target
};
/*
* ExitData contains the address of a jmp instruction we can smash later
* if we start a new tracelet at this exit point.
*/
struct ExitData : IRExtraData {
explicit ExitData(IRInstruction* toSmash) : toSmash(toSmash) {}
IRInstruction* toSmash;
std::string show() const;
};
//////////////////////////////////////////////////////////////////////
#define X(op, data) \
@@ -581,6 +592,8 @@ X(StLocNT, LocalId);
X(DefConst, ConstData);
X(LdConst, ConstData);
X(Jmp_, EdgeData);
X(ExitTrace, ExitData);
X(ExitTraceCc, ExitData);
#undef X
@@ -1632,10 +1645,6 @@ public:
bool printLastUse = false) const;
void print() const;
// Used for Jcc to Jmp elimination
void setTCA(TCA tca);
TCA getTCA() const;
// XXX: false for Null, etc. Would rather it returns whether we
// have a compile-time constant value.
bool isConst() const {
+4 -5
Ver Arquivo
@@ -111,7 +111,6 @@ static void hoistConditionalJumps(Trace* trace, IRFactory* irFactory) {
}
}
if (exitInst) {
SSATmp* dst = jccInst.getDst();
Block* targetBlock = jccInst.getTaken();
auto targetInstIter = targetBlock->skipLabel();
@@ -131,11 +130,11 @@ static void hoistConditionalJumps(Trace* trace, IRFactory* irFactory) {
if (exitCcInst) {
// Found both exits, link them to Jcc for codegen
assert(dst);
exitCcInst->appendSrc(irFactory->arena(), dst);
exitInst->appendSrc(irFactory->arena(), dst);
ExitData* exitData = new (irFactory->arena()) ExitData(&jccInst);
exitCcInst->setExtra(exitData);
exitInst->setExtra(exitData);
// Set flag so Jcc and exits know this is active
dst->setTCA(kIRDirectJccJmpActive);
jccInst.setTCA(kIRDirectJccJmpActive);
}
}
}