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