From 884ff2d2181983418bc476ed4fd96d7795aae053 Mon Sep 17 00:00:00 2001 From: smith Date: Tue, 26 Feb 2013 11:48:17 -0800 Subject: [PATCH] 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. --- hphp/doc/ir.specification | 14 ++++--------- hphp/runtime/vm/translator/hopt/codegen.cpp | 21 +++++++++---------- hphp/runtime/vm/translator/hopt/codegen.h | 6 +++--- hphp/runtime/vm/translator/hopt/ir.cpp | 7 ++----- hphp/runtime/vm/translator/hopt/ir.h | 17 +++++++++++---- hphp/runtime/vm/translator/hopt/jumpsopts.cpp | 9 ++++---- 6 files changed, 36 insertions(+), 38 deletions(-) diff --git a/hphp/doc/ir.specification b/hphp/doc/ir.specification index 9a64c6ff7..c5c51cea6 100644 --- a/hphp/doc/ir.specification +++ b/hphp/doc/ir.specification @@ -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 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 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. diff --git a/hphp/runtime/vm/translator/hopt/codegen.cpp b/hphp/runtime/vm/translator/hopt/codegen.cpp index bb1915883..28967e956 100644 --- a/hphp/runtime/vm/translator/hopt/codegen.cpp +++ b/hphp/runtime/vm/translator/hopt/codegen.cpp @@ -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()) { // Unconditional trace exit - toSmash = inst->getSrc(4); + toSmash = inst->getExtra()->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()) { + toSmash = inst->getExtra()->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(); diff --git a/hphp/runtime/vm/translator/hopt/codegen.h b/hphp/runtime/vm/translator/hopt/codegen.h index bd683aec9..0f60b580e 100644 --- a/hphp/runtime/vm/translator/hopt/codegen.h +++ b/hphp/runtime/vm/translator/hopt/codegen.h @@ -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; diff --git a/hphp/runtime/vm/translator/hopt/ir.cpp b/hphp/runtime/vm/translator/hopt/ir.cpp index 28ce43c73..c60353d73 100644 --- a/hphp/runtime/vm/translator/hopt/ir.cpp +++ b/hphp/runtime/vm/translator/hopt/ir.cpp @@ -973,11 +973,8 @@ TCA SSATmp::getValTCA() const { return m_inst->getExtra()->as(); } -void SSATmp::setTCA(TCA tca) { - getInstruction()->setTCA(tca); -} -TCA SSATmp::getTCA() const { - return getInstruction()->getTCA(); +std::string ExitData::show() const { + return folly::to(toSmash->getIId()); } std::string SSATmp::toString() const { diff --git a/hphp/runtime/vm/translator/hopt/ir.h b/hphp/runtime/vm/translator/hopt/ir.h index e4944c13e..6ab39c31f 100644 --- a/hphp/runtime/vm/translator/hopt/ir.h +++ b/hphp/runtime/vm/translator/hopt/ir.h @@ -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 { diff --git a/hphp/runtime/vm/translator/hopt/jumpsopts.cpp b/hphp/runtime/vm/translator/hopt/jumpsopts.cpp index c26c80986..cf6e9b7af 100644 --- a/hphp/runtime/vm/translator/hopt/jumpsopts.cpp +++ b/hphp/runtime/vm/translator/hopt/jumpsopts.cpp @@ -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); } } }