Trace -> IRTrace
For converting Transl -> JIT. We either do this or convert all the other `Trace` calls to `HPHP::Trace` which seemed worse. This also niecly mirrors `IRInstruction`.
Esse commit está contido em:
@@ -56,11 +56,11 @@ struct Block : boost::noncopyable {
|
||||
return &*it;
|
||||
}
|
||||
|
||||
uint32_t id() const { return m_id; }
|
||||
Trace* trace() const { return m_trace; }
|
||||
void setTrace(Trace* t) { m_trace = t; }
|
||||
Hint hint() const { return m_hint; }
|
||||
void setHint(Hint hint) { m_hint = hint; }
|
||||
uint32_t id() const { return m_id; }
|
||||
IRTrace* trace() const { return m_trace; }
|
||||
void setTrace(IRTrace* t) { m_trace = t; }
|
||||
Hint hint() const { return m_hint; }
|
||||
void setHint(Hint hint) { m_hint = hint; }
|
||||
|
||||
void addEdge(IRInstruction* jmp);
|
||||
void removeEdge(IRInstruction* jmp);
|
||||
@@ -233,7 +233,7 @@ struct Block : boost::noncopyable {
|
||||
|
||||
private:
|
||||
InstructionList m_instrs; // instructions in this block
|
||||
Trace* m_trace; // owner of this block.
|
||||
IRTrace* m_trace; // owner of this block.
|
||||
const Func* m_func; // which func are we in
|
||||
Edge m_next; // fall-through path; null if back()->isTerminal().
|
||||
const unsigned m_id; // factory-assigned unique id of this block
|
||||
|
||||
@@ -73,7 +73,7 @@ void postorderWalk(Visitor visitor, unsigned num_blocks, Block* head) {
|
||||
*
|
||||
* Post: isRPOSorted(return value)
|
||||
*/
|
||||
BlockList rpoSortCfg(Trace*, const IRFactory&);
|
||||
BlockList rpoSortCfg(IRTrace*, const IRFactory&);
|
||||
|
||||
/*
|
||||
* Return an iterator into an rpo-sorted BlockList for a given Block.
|
||||
@@ -122,7 +122,7 @@ bool dominates(const Block* b1, const Block* b2, const IdomVector& idoms);
|
||||
* Return true if trace has internal control flow (IE it has a branch
|
||||
* to itself somewhere.
|
||||
*/
|
||||
bool hasInternalFlow(Trace*);
|
||||
bool hasInternalFlow(IRTrace*);
|
||||
|
||||
/*
|
||||
* Visit basic blocks in a preorder traversal over the dominator tree.
|
||||
@@ -144,9 +144,9 @@ void forPreorderDoms(Block* block, const DomChildren& children,
|
||||
* Visit the main trace followed by exit traces.
|
||||
*/
|
||||
template <class Body>
|
||||
void forEachTrace(Trace* main, Body body) {
|
||||
void forEachTrace(IRTrace* main, Body body) {
|
||||
body(main);
|
||||
for (Trace* exit : main->exitTraces()) {
|
||||
for (IRTrace* exit : main->exitTraces()) {
|
||||
body(exit);
|
||||
}
|
||||
}
|
||||
@@ -155,11 +155,11 @@ void forEachTrace(Trace* main, Body body) {
|
||||
* Visit the blocks in the main trace followed by exit trace blocks.
|
||||
*/
|
||||
template <class Body>
|
||||
void forEachTraceBlock(Trace* main, Body body) {
|
||||
void forEachTraceBlock(IRTrace* main, Body body) {
|
||||
for (Block* block : main->blocks()) {
|
||||
body(block);
|
||||
}
|
||||
for (Trace* exit : main->exitTraces()) {
|
||||
for (IRTrace* exit : main->exitTraces()) {
|
||||
for (Block* block : exit->blocks()) {
|
||||
body(block);
|
||||
}
|
||||
@@ -179,7 +179,7 @@ void forEachInst(const BlockList& blocks, Body body) {
|
||||
}
|
||||
|
||||
template <class Body>
|
||||
void forEachInst(Trace* trace, Body body) {
|
||||
void forEachInst(IRTrace* trace, Body body) {
|
||||
forEachInst(trace->blocks(), body);
|
||||
}
|
||||
|
||||
@@ -187,8 +187,8 @@ void forEachInst(Trace* trace, Body body) {
|
||||
* Visit each instruction in the main trace, then the exit traces
|
||||
*/
|
||||
template <class Body>
|
||||
void forEachTraceInst(Trace* main, Body body) {
|
||||
forEachTrace(main, [=](Trace* t) {
|
||||
void forEachTraceInst(IRTrace* main, Body body) {
|
||||
forEachTrace(main, [=](IRTrace* t) {
|
||||
forEachInst(t, body);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ bool checkBlock(Block* b) {
|
||||
* Check that every catch trace has at most one incoming branch and a single
|
||||
* block.
|
||||
*/
|
||||
bool checkCatchTraces(Trace* trace, const IRFactory& irFactory) {
|
||||
bool checkCatchTraces(IRTrace* trace, const IRFactory& irFactory) {
|
||||
forEachTraceBlock(trace, [&](Block* b) {
|
||||
auto trace = b->trace();
|
||||
if (trace->isCatch()) {
|
||||
@@ -174,7 +174,7 @@ const Edge* nextEdge(Block* b) {
|
||||
* 5. Each predecessor of a reachable block must be reachable (deleted
|
||||
* blocks must not have out-edges to reachable blocks).
|
||||
*/
|
||||
bool checkCfg(Trace* trace, const IRFactory& factory) {
|
||||
bool checkCfg(IRTrace* trace, const IRFactory& factory) {
|
||||
forEachTraceBlock(trace, checkBlock);
|
||||
|
||||
// Check valid successor/predecessor edges.
|
||||
@@ -227,7 +227,7 @@ bool checkCfg(Trace* trace, const IRFactory& factory) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool checkTmpsSpanningCalls(Trace* trace, const IRFactory& irFactory) {
|
||||
bool checkTmpsSpanningCalls(IRTrace* trace, const IRFactory& irFactory) {
|
||||
auto const blocks = rpoSortCfg(trace, irFactory);
|
||||
auto const children = findDomChildren(blocks);
|
||||
|
||||
@@ -275,7 +275,7 @@ bool checkTmpsSpanningCalls(Trace* trace, const IRFactory& irFactory) {
|
||||
return isValid;
|
||||
}
|
||||
|
||||
bool checkRegisters(Trace* trace, const IRFactory& factory,
|
||||
bool checkRegisters(IRTrace* trace, const IRFactory& factory,
|
||||
const RegAllocInfo& regs) {
|
||||
assert(checkCfg(trace, factory));
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
namespace HPHP {
|
||||
namespace JIT {
|
||||
|
||||
class Trace;
|
||||
class IRTrace;
|
||||
class IRFactory;
|
||||
struct RegAllocInfo;
|
||||
|
||||
@@ -28,7 +28,7 @@ struct RegAllocInfo;
|
||||
* Ensure valid SSA properties; each SSATmp must be defined exactly once,
|
||||
* only used in positions dominated by the definition.
|
||||
*/
|
||||
bool checkCfg(Trace*, const IRFactory&);
|
||||
bool checkCfg(IRTrace*, const IRFactory&);
|
||||
|
||||
/*
|
||||
* We can't have SSATmps spanning php-level calls, except for frame
|
||||
@@ -37,13 +37,13 @@ bool checkCfg(Trace*, const IRFactory&);
|
||||
* We have no callee-saved registers in php, and there'd be nowhere to
|
||||
* spill these because all translations share the spill space.
|
||||
*/
|
||||
bool checkTmpsSpanningCalls(Trace*, const IRFactory&);
|
||||
bool checkTmpsSpanningCalls(IRTrace*, const IRFactory&);
|
||||
|
||||
/*
|
||||
* Check register and spill slot assignments; registers and spill slots must
|
||||
* contain the correct SSATmp value at every point of use.
|
||||
*/
|
||||
bool checkRegisters(Trace*, const IRFactory&, const RegAllocInfo&);
|
||||
bool checkRegisters(IRTrace*, const IRFactory&, const RegAllocInfo&);
|
||||
|
||||
}}
|
||||
|
||||
|
||||
@@ -5383,7 +5383,7 @@ LiveRegs computeLiveRegs(const IRFactory* factory, const RegAllocInfo& regs,
|
||||
return live_regs;
|
||||
}
|
||||
|
||||
void genCodeForTrace(Trace* trace,
|
||||
void genCodeForTrace(IRTrace* trace,
|
||||
CodeGenerator::Asm& as,
|
||||
CodeGenerator::Asm& astubs,
|
||||
IRFactory* irFactory,
|
||||
|
||||
@@ -122,7 +122,7 @@ struct CodegenState {
|
||||
|
||||
// If non-null, represents the catch trace for the current
|
||||
// instruction, to be registered with the unwinder.
|
||||
Trace* catchTrace;
|
||||
IRTrace* catchTrace;
|
||||
};
|
||||
|
||||
constexpr Reg64 rCgGP (reg::r11);
|
||||
@@ -132,8 +132,8 @@ constexpr RegXMM rCgXMM1(reg::xmm1);
|
||||
struct CodeGenerator {
|
||||
typedef Transl::X64Assembler Asm;
|
||||
|
||||
CodeGenerator(Trace* trace, Asm& as, Asm& astubs, Transl::TranslatorX64* tx64,
|
||||
CodegenState& state)
|
||||
CodeGenerator(IRTrace* trace, Asm& as, Asm& astubs,
|
||||
Transl::TranslatorX64* tx64, CodegenState& state)
|
||||
: m_as(as)
|
||||
, m_astubs(astubs)
|
||||
, m_tx64(tx64)
|
||||
@@ -386,7 +386,7 @@ private:
|
||||
const RegAllocInfo& m_regs;
|
||||
Reg64 m_rScratch; // currently selected GP scratch reg
|
||||
IRInstruction* m_curInst; // current instruction being generated
|
||||
Trace* m_curTrace;
|
||||
IRTrace* m_curTrace;
|
||||
uint32_t m_curBcOff; // offset of bytecode instr that produced
|
||||
// m_curInst
|
||||
};
|
||||
@@ -565,7 +565,7 @@ const Func* loadClassCtor(Class* cls);
|
||||
|
||||
Instance* createClHelper(Class*, int, ActRec*, TypedValue*);
|
||||
|
||||
void genCodeForTrace(Trace* trace,
|
||||
void genCodeForTrace(IRTrace* trace,
|
||||
CodeGenerator::Asm& a,
|
||||
CodeGenerator::Asm& astubs,
|
||||
IRFactory* irFactory,
|
||||
|
||||
@@ -116,7 +116,7 @@ typedef StateVector<SSATmp, SSASet> SSACache;
|
||||
typedef StateVector<SSATmp, uint32_t> UseCounts;
|
||||
typedef std::list<const IRInstruction*> WorkList;
|
||||
|
||||
void removeDeadInstructions(Trace* trace, const DceState& state) {
|
||||
void removeDeadInstructions(IRTrace* trace, const DceState& state) {
|
||||
auto &blocks = trace->blocks();
|
||||
for (auto it = blocks.begin(), end = blocks.end(); it != end;) {
|
||||
auto cur = it; ++it;
|
||||
@@ -148,7 +148,7 @@ bool isUnguardedLoad(IRInstruction* inst) {
|
||||
|
||||
// removeUnreachable erases unreachable blocks from trace, and returns
|
||||
// a sorted list of the remaining blocks.
|
||||
BlockList removeUnreachable(Trace* trace, IRFactory* factory) {
|
||||
BlockList removeUnreachable(IRTrace* trace, IRFactory* factory) {
|
||||
FTRACE(5, "RemoveUnreachable:vvvvvvvvvvvvvvvvvvvv\n");
|
||||
SCOPE_EXIT { FTRACE(5, "RemoveUnreachable:^^^^^^^^^^^^^^^^^^^^\n"); };
|
||||
|
||||
@@ -184,7 +184,7 @@ BlockList removeUnreachable(Trace* trace, IRFactory* factory) {
|
||||
}
|
||||
});
|
||||
}
|
||||
forEachTrace(trace, [&](Trace* t) {
|
||||
forEachTrace(trace, [&](IRTrace* t) {
|
||||
for (auto bit = t->begin(); bit != t->end();) {
|
||||
if (reachable[*bit]) {
|
||||
++bit;
|
||||
@@ -239,7 +239,7 @@ initInstructions(const BlockList& blocks, DceState& state) {
|
||||
// cannot be eliminated.
|
||||
// 3) Eliminates IncRef-DecRef pairs who value is used only by the DecRef and
|
||||
// whose type does not run a destructor with side effects.
|
||||
void optimizeRefCount(Trace* trace, DceState& state, UseCounts& uses) {
|
||||
void optimizeRefCount(IRTrace* trace, DceState& state, UseCounts& uses) {
|
||||
WorkList decrefs;
|
||||
forEachInst(trace, [&](IRInstruction* inst) {
|
||||
if (inst->op() == IncRef && !state[inst].countConsumedAny()) {
|
||||
@@ -247,7 +247,7 @@ void optimizeRefCount(Trace* trace, DceState& state, UseCounts& uses) {
|
||||
// consumesReferences flag but doesn't.
|
||||
auto& s = state[inst];
|
||||
always_assert_log(s.decRefNZed(), [&]{
|
||||
Trace* mainTrace = trace->isMain() ? trace : trace->main();
|
||||
IRTrace* mainTrace = trace->isMain() ? trace : trace->main();
|
||||
return folly::format("\n{} has state {} in trace:\n{}{}\n",
|
||||
inst->toString(), s.toString(), mainTrace->toString(),
|
||||
trace == mainTrace ? "" : trace->toString()).str();
|
||||
@@ -307,16 +307,16 @@ void optimizeRefCount(Trace* trace, DceState& state, UseCounts& uses) {
|
||||
* * replace each use of the original incref's result with the new
|
||||
* incref's result.
|
||||
*/
|
||||
void sinkIncRefs(Trace* trace, IRFactory* irFactory, DceState& state) {
|
||||
void sinkIncRefs(IRTrace* trace, IRFactory* irFactory, DceState& state) {
|
||||
assert(trace->isMain());
|
||||
|
||||
auto copyPropTrace = [] (Trace* trace) {
|
||||
auto copyPropTrace = [] (IRTrace* trace) {
|
||||
forEachInst(trace, copyProp);
|
||||
};
|
||||
|
||||
WorkList toSink;
|
||||
|
||||
auto processExit = [&] (Trace* exit) {
|
||||
auto processExit = [&] (IRTrace* exit) {
|
||||
// Sink REFCOUNT_CONSUMED_OFF_TRACE IncRefs before the first non-label
|
||||
// instruction, and create a mapping between the original tmps to the sunk
|
||||
// tmps so that we can later replace the original ones with the sunk ones.
|
||||
@@ -376,7 +376,7 @@ void sinkIncRefs(Trace* trace, IRFactory* irFactory, DceState& state) {
|
||||
if (Block* target = inst->taken()) {
|
||||
if (!pushedTo[target->id()]) {
|
||||
pushedTo[target->id()] = 1;
|
||||
Trace* exit = target->trace();
|
||||
IRTrace* exit = target->trace();
|
||||
if (exit != trace) processExit(exit);
|
||||
}
|
||||
}
|
||||
@@ -392,7 +392,7 @@ void sinkIncRefs(Trace* trace, IRFactory* irFactory, DceState& state) {
|
||||
* of a DefInlineFP. In this case we can kill both, which may allow
|
||||
* removing a SpillFrame as well.
|
||||
*/
|
||||
void optimizeActRecs(Trace* trace, DceState& state, IRFactory* factory,
|
||||
void optimizeActRecs(IRTrace* trace, DceState& state, IRFactory* factory,
|
||||
UseCounts& uses) {
|
||||
FTRACE(5, "AR:vvvvvvvvvvvvvvvvvvvvv\n");
|
||||
SCOPE_EXIT { FTRACE(5, "AR:^^^^^^^^^^^^^^^^^^^^^\n"); };
|
||||
@@ -577,9 +577,9 @@ void consumeIncRef(const IRInstruction* consumer, const SSATmp* src,
|
||||
|
||||
// Publicly exported functions:
|
||||
|
||||
void eliminateDeadCode(Trace* trace, IRFactory* irFactory) {
|
||||
void eliminateDeadCode(IRTrace* trace, IRFactory* irFactory) {
|
||||
auto removeEmptyExitTraces = [&] {
|
||||
trace->exitTraces().remove_if([](Trace* exit) {
|
||||
trace->exitTraces().remove_if([](IRTrace* exit) {
|
||||
return exit->blocks().empty();
|
||||
});
|
||||
};
|
||||
@@ -621,7 +621,7 @@ void eliminateDeadCode(Trace* trace, IRFactory* irFactory) {
|
||||
}
|
||||
|
||||
// Optimize IncRefs and DecRefs.
|
||||
forEachTrace(trace, [&](Trace* t) { optimizeRefCount(t, state, uses); });
|
||||
forEachTrace(trace, [&](IRTrace* t) { optimizeRefCount(t, state, uses); });
|
||||
|
||||
if (RuntimeOption::EvalHHIREnableSinking) {
|
||||
// Sink IncRefs consumed off trace.
|
||||
@@ -634,7 +634,7 @@ void eliminateDeadCode(Trace* trace, IRFactory* irFactory) {
|
||||
|
||||
// now remove instructions whose id == DEAD
|
||||
removeDeadInstructions(trace, state);
|
||||
for (Trace* exit : trace->exitTraces()) {
|
||||
for (IRTrace* exit : trace->exitTraces()) {
|
||||
removeDeadInstructions(exit, state);
|
||||
}
|
||||
|
||||
|
||||
@@ -630,13 +630,13 @@ void HhbcTranslator::emitInitThisLoc(int32_t id) {
|
||||
}
|
||||
|
||||
void HhbcTranslator::emitCGetL(int32_t id) {
|
||||
Trace* exitTrace = getExitTrace();
|
||||
IRTrace* exitTrace = getExitTrace();
|
||||
pushIncRef(ldLocInnerWarn(id, exitTrace));
|
||||
}
|
||||
|
||||
void HhbcTranslator::emitCGetL2(int32_t id) {
|
||||
Trace* exitTrace = getExitTrace();
|
||||
Trace* catchTrace = getCatchTrace();
|
||||
IRTrace* exitTrace = getExitTrace();
|
||||
IRTrace* catchTrace = getCatchTrace();
|
||||
SSATmp* oldTop = pop(Type::Gen);
|
||||
pushIncRef(ldLocInnerWarn(id, exitTrace, catchTrace));
|
||||
push(oldTop);
|
||||
@@ -688,7 +688,7 @@ void HhbcTranslator::emitSetL(int32_t id) {
|
||||
}
|
||||
|
||||
void HhbcTranslator::emitIncDecL(bool pre, bool inc, uint32_t id) {
|
||||
Trace* exitTrace = getExitTrace();
|
||||
IRTrace* exitTrace = getExitTrace();
|
||||
auto const src = ldLocInner(id, exitTrace);
|
||||
|
||||
// Inc/Dec of a bool is a no-op.
|
||||
@@ -714,7 +714,7 @@ SSATmp* HhbcTranslator::emitIncDec(bool pre, bool inc, SSATmp* src) {
|
||||
void HhbcTranslator::emitIncDecMem(bool pre,
|
||||
bool inc,
|
||||
SSATmp* propAddr,
|
||||
Trace* exitTrace) {
|
||||
IRTrace* exitTrace) {
|
||||
// Handle only integer inc/dec for now
|
||||
SSATmp* src = gen(LdMem, Type::Int, exitTrace, propAddr, cns(0));
|
||||
// do the add and store back
|
||||
@@ -1371,7 +1371,7 @@ SSATmp* HhbcTranslator::emitLdGblAddrDef(const StringData* gblName) {
|
||||
|
||||
void HhbcTranslator::emitIncDecS(bool pre, bool inc) {
|
||||
if (!checkSupportedClsProp(nullptr, Type::Cell, 0)) return;
|
||||
Trace* exit = getExitSlowTrace();
|
||||
IRTrace* exit = getExitSlowTrace();
|
||||
emitIncDecMem(pre, inc, emitLdClsPropAddr(nullptr), exit);
|
||||
}
|
||||
|
||||
@@ -1426,7 +1426,7 @@ void HhbcTranslator::emitIsTypeC(Type t) {
|
||||
}
|
||||
|
||||
void HhbcTranslator::emitIsTypeL(Type t, int id) {
|
||||
Trace* exitTrace = getExitTrace();
|
||||
IRTrace* exitTrace = getExitTrace();
|
||||
push(gen(IsType, t, ldLocInnerWarn(id, exitTrace)));
|
||||
}
|
||||
|
||||
@@ -1496,7 +1496,7 @@ void HhbcTranslator::emitJmpNZ(Offset taken) {
|
||||
}
|
||||
|
||||
void HhbcTranslator::emitCmp(Opcode opc) {
|
||||
Trace* catchTrace = nullptr;
|
||||
IRTrace* catchTrace = nullptr;
|
||||
if (cmpOpTypesMayReenter(opc, topC(0)->type(), topC(1)->type())) {
|
||||
catchTrace = getCatchTrace();
|
||||
}
|
||||
@@ -1516,7 +1516,7 @@ void HhbcTranslator::emitClsCnsD(int32_t cnsNameId, int32_t clsNameId) {
|
||||
// chaining to another Tracelet so forward progress still happens.
|
||||
auto const sideExit = makeSideExit(
|
||||
nextBcOff(),
|
||||
[&] (Trace* t) {
|
||||
[&] (IRTrace* t) {
|
||||
return genFor(t, LookupClsCns, Type::Cell, clsCnsName);
|
||||
}
|
||||
);
|
||||
@@ -1677,7 +1677,7 @@ void HhbcTranslator::emitFPushCtorCommon(SSATmp* cls,
|
||||
SSATmp* obj,
|
||||
const Func* func,
|
||||
int32_t numParams,
|
||||
Trace* catchTrace) {
|
||||
IRTrace* catchTrace) {
|
||||
push(obj);
|
||||
SSATmp* fn = nullptr;
|
||||
if (func) {
|
||||
@@ -1691,7 +1691,7 @@ void HhbcTranslator::emitFPushCtorCommon(SSATmp* cls,
|
||||
}
|
||||
|
||||
void HhbcTranslator::emitFPushCtor(int32_t numParams) {
|
||||
Trace* catchTrace = getCatchTrace();
|
||||
IRTrace* catchTrace = getCatchTrace();
|
||||
SSATmp* cls = popA();
|
||||
SSATmp* obj = gen(IncRef, gen(AllocObj, cls));
|
||||
emitFPushCtorCommon(cls, obj, nullptr, numParams, catchTrace);
|
||||
@@ -1706,8 +1706,8 @@ void HhbcTranslator::emitFPushCtorD(int32_t numParams, int32_t classNameStrId) {
|
||||
const StringData* className = lookupStringId(classNameStrId);
|
||||
// The code generated for the catch trace depends on the environment at the
|
||||
// call so we can't share them between instructions.
|
||||
Trace* catchTrace1 = getCatchTrace();
|
||||
Trace* catchTrace2 = getCatchTrace();
|
||||
IRTrace* catchTrace1 = getCatchTrace();
|
||||
IRTrace* catchTrace2 = getCatchTrace();
|
||||
|
||||
const Class* cls = Unit::lookupUniqueClass(className);
|
||||
bool uniqueCls = classIsUnique(cls);
|
||||
@@ -1784,7 +1784,7 @@ void HhbcTranslator::emitFPushFuncD(int32_t numParams, int32_t funcId) {
|
||||
|
||||
const bool immutable = func->isNameBindingImmutable(curUnit());
|
||||
|
||||
Trace* catchTrace = nullptr;
|
||||
IRTrace* catchTrace = nullptr;
|
||||
if (!immutable) {
|
||||
catchTrace = getCatchTrace(); // LdFuncCached can throw
|
||||
}
|
||||
@@ -1950,7 +1950,7 @@ void HhbcTranslator::emitFPushClsMethodD(int32_t numParams,
|
||||
func && magicCall ? methodName : nullptr);
|
||||
} else {
|
||||
// lookup static method & class in the target cache
|
||||
Trace* exitTrace = getExitSlowTrace();
|
||||
IRTrace* exitTrace = getExitSlowTrace();
|
||||
SSATmp* funcClassTmp =
|
||||
gen(LdClsMethodCache,
|
||||
exitTrace,
|
||||
@@ -2283,7 +2283,7 @@ void HhbcTranslator::emitSwitch(const ImmVector& iv,
|
||||
switchVal, ssabase, ssatargets);
|
||||
} else if (type.subtypeOf(Type::Obj)) {
|
||||
// switchObjHelper can throw exceptions and reenter the VM
|
||||
Trace* catchTrace = nullptr;
|
||||
IRTrace* catchTrace = nullptr;
|
||||
if (type.subtypeOf(Type::Obj)) {
|
||||
catchTrace = getCatchTrace();
|
||||
}
|
||||
@@ -2335,7 +2335,7 @@ void HhbcTranslator::emitSSwitch(const ImmVector& iv) {
|
||||
}
|
||||
);
|
||||
|
||||
Trace* catchTrace = nullptr;
|
||||
IRTrace* catchTrace = nullptr;
|
||||
// The slow path can throw exceptions and reenter the VM.
|
||||
if (!fastPath) catchTrace = getCatchTrace();
|
||||
|
||||
@@ -2405,7 +2405,7 @@ void HhbcTranslator::guardTypeStack(uint32_t stackIndex, Type type) {
|
||||
}
|
||||
|
||||
void HhbcTranslator::checkTypeTopOfStack(Type type, Offset nextByteCode) {
|
||||
Trace* exitTrace = getExitTrace(nextByteCode);
|
||||
IRTrace* exitTrace = getExitTrace(nextByteCode);
|
||||
SSATmp* tmp = m_evalStack.top();
|
||||
if (!tmp) {
|
||||
FTRACE(1, "checkTypeTopOfStack: no tmp: {}\n", type.toString());
|
||||
@@ -2681,7 +2681,7 @@ void HhbcTranslator::emitCastBool() {
|
||||
}
|
||||
|
||||
void HhbcTranslator::emitCastDouble() {
|
||||
Trace* catchTrace = getCatchTrace();
|
||||
IRTrace* catchTrace = getCatchTrace();
|
||||
SSATmp* src = popC();
|
||||
Type fromType = src->type();
|
||||
if (fromType.isDbl()) {
|
||||
@@ -2705,7 +2705,7 @@ void HhbcTranslator::emitCastDouble() {
|
||||
}
|
||||
|
||||
void HhbcTranslator::emitCastInt() {
|
||||
Trace* catchTrace = getCatchTrace();
|
||||
IRTrace* catchTrace = getCatchTrace();
|
||||
SSATmp* src = popC();
|
||||
Type fromType = src->type();
|
||||
if (fromType.isInt()) {
|
||||
@@ -2740,7 +2740,7 @@ void HhbcTranslator::emitCastObject() {
|
||||
}
|
||||
|
||||
void HhbcTranslator::emitCastString() {
|
||||
Trace* catchTrace = getCatchTrace();
|
||||
IRTrace* catchTrace = getCatchTrace();
|
||||
SSATmp* src = popC();
|
||||
Type fromType = src->type();
|
||||
if (fromType.isString()) {
|
||||
@@ -2955,7 +2955,7 @@ void HhbcTranslator::emitCGet(const StringData* name,
|
||||
EmitLdAddrFun emitLdAddr) {
|
||||
resultType = getResultType(resultType, isInferedType);
|
||||
if (!(this->*checkSupported)(name, resultType, 0)) return;
|
||||
Trace* exit = (isInferedType || resultType.equals(Type::Cell))
|
||||
IRTrace* exit = (isInferedType || resultType.equals(Type::Cell))
|
||||
? nullptr : getExitSlowTrace();
|
||||
SSATmp* ptr = (this->*emitLdAddr)(name,
|
||||
exitOnFailure
|
||||
@@ -3147,24 +3147,24 @@ std::vector<SSATmp*> HhbcTranslator::peekSpillValues() const {
|
||||
return ret;
|
||||
}
|
||||
|
||||
Trace* HhbcTranslator::getExitTrace(Offset targetBcOff /* = -1 */) {
|
||||
IRTrace* HhbcTranslator::getExitTrace(Offset targetBcOff /* = -1 */) {
|
||||
auto spillValues = peekSpillValues();
|
||||
return getExitTrace(targetBcOff, spillValues);
|
||||
}
|
||||
|
||||
Trace* HhbcTranslator::getExitTrace(Offset targetBcOff,
|
||||
IRTrace* HhbcTranslator::getExitTrace(Offset targetBcOff,
|
||||
std::vector<SSATmp*>& spillValues) {
|
||||
if (targetBcOff == -1) targetBcOff = bcOff();
|
||||
return getExitTraceImpl(targetBcOff, ExitFlag::None, spillValues,
|
||||
CustomExit{});
|
||||
}
|
||||
|
||||
Trace* HhbcTranslator::getExitTraceWarn(Offset targetBcOff,
|
||||
IRTrace* HhbcTranslator::getExitTraceWarn(Offset targetBcOff,
|
||||
std::vector<SSATmp*>& spillValues,
|
||||
const StringData* warning) {
|
||||
assert(targetBcOff != -1);
|
||||
return getExitTraceImpl(targetBcOff, ExitFlag::None, spillValues,
|
||||
[&](Trace* t) -> SSATmp* {
|
||||
[&](IRTrace* t) -> SSATmp* {
|
||||
genFor(t, RaiseWarning, cns(warning));
|
||||
return nullptr;
|
||||
}
|
||||
@@ -3172,7 +3172,7 @@ Trace* HhbcTranslator::getExitTraceWarn(Offset targetBcOff,
|
||||
}
|
||||
|
||||
template<class ExitLambda>
|
||||
Trace* HhbcTranslator::makeSideExit(Offset targetBcOff, ExitLambda exit) {
|
||||
IRTrace* HhbcTranslator::makeSideExit(Offset targetBcOff, ExitLambda exit) {
|
||||
auto spillValues = peekSpillValues();
|
||||
return getExitTraceImpl(targetBcOff,
|
||||
ExitFlag::DelayedMarker,
|
||||
@@ -3180,13 +3180,13 @@ Trace* HhbcTranslator::makeSideExit(Offset targetBcOff, ExitLambda exit) {
|
||||
exit);
|
||||
}
|
||||
|
||||
Trace* HhbcTranslator::getExitSlowTrace() {
|
||||
IRTrace* HhbcTranslator::getExitSlowTrace() {
|
||||
auto spillValues = peekSpillValues();
|
||||
return getExitTraceImpl(bcOff(), ExitFlag::NoIR, spillValues,
|
||||
CustomExit{});
|
||||
}
|
||||
|
||||
Trace* HhbcTranslator::getExitTraceImpl(Offset targetBcOff,
|
||||
IRTrace* HhbcTranslator::getExitTraceImpl(Offset targetBcOff,
|
||||
ExitFlag flag,
|
||||
std::vector<SSATmp*>& stackValues,
|
||||
const CustomExit& customFn) {
|
||||
@@ -3264,7 +3264,7 @@ Trace* HhbcTranslator::getExitTraceImpl(Offset targetBcOff,
|
||||
* instruction as its taken field, code will be generated and the trace will be
|
||||
* registered with the unwinder automatically.
|
||||
*/
|
||||
Trace* HhbcTranslator::getCatchTrace() {
|
||||
IRTrace* HhbcTranslator::getCatchTrace() {
|
||||
auto exit = m_tb->makeExitTrace(bcOff());
|
||||
assert(exit->blocks().size() == 1);
|
||||
|
||||
@@ -3277,7 +3277,7 @@ Trace* HhbcTranslator::getCatchTrace() {
|
||||
return exit;
|
||||
}
|
||||
|
||||
SSATmp* HhbcTranslator::emitSpillStack(Trace* t, SSATmp* sp,
|
||||
SSATmp* HhbcTranslator::emitSpillStack(IRTrace* t, SSATmp* sp,
|
||||
const std::vector<SSATmp*>& spillVals) {
|
||||
std::vector<SSATmp*> ssaArgs{ sp, cns(int64_t(m_stackDeficit)) };
|
||||
ssaArgs.insert(ssaArgs.end(), spillVals.begin(), spillVals.end());
|
||||
@@ -3341,7 +3341,7 @@ SSATmp* HhbcTranslator::ldLocAddr(uint32_t locId) {
|
||||
* the tracked type for this local. This check may be optimized away
|
||||
* if we can determine that the inner type must match the tracked type.
|
||||
*/
|
||||
SSATmp* HhbcTranslator::ldLocInner(uint32_t locId, Trace* exitTrace) {
|
||||
SSATmp* HhbcTranslator::ldLocInner(uint32_t locId, IRTrace* exitTrace) {
|
||||
auto loc = ldLoc(locId);
|
||||
assert((loc->type().isBoxed() || loc->type().notBoxed()) &&
|
||||
"Currently we don't handle traces where locals are maybeBoxed");
|
||||
@@ -3356,8 +3356,8 @@ SSATmp* HhbcTranslator::ldLocInner(uint32_t locId, Trace* exitTrace) {
|
||||
* caller requires the catch trace to be generated at a point earlier than when
|
||||
* it calls this function.
|
||||
*/
|
||||
SSATmp* HhbcTranslator::ldLocInnerWarn(uint32_t id, Trace* target,
|
||||
Trace* catchTrace /* = nullptr */) {
|
||||
SSATmp* HhbcTranslator::ldLocInnerWarn(uint32_t id, IRTrace* target,
|
||||
IRTrace* catchTrace /* = nullptr */) {
|
||||
if (!catchTrace) catchTrace = getCatchTrace();
|
||||
auto const locVal = ldLocInner(id, target);
|
||||
|
||||
@@ -3379,7 +3379,7 @@ SSATmp* HhbcTranslator::ldLocInnerWarn(uint32_t id, Trace* target,
|
||||
* Pre: exitTrace != nullptr if the local may be boxed
|
||||
*/
|
||||
SSATmp* HhbcTranslator::stLocImpl(uint32_t id,
|
||||
Trace* exitTrace,
|
||||
IRTrace* exitTrace,
|
||||
SSATmp* newVal,
|
||||
bool doRefCount) {
|
||||
assert(!newVal->type().maybeBoxed());
|
||||
@@ -3412,12 +3412,12 @@ SSATmp* HhbcTranslator::stLocImpl(uint32_t id,
|
||||
return ret;
|
||||
}
|
||||
|
||||
SSATmp* HhbcTranslator::stLoc(uint32_t id, Trace* exit, SSATmp* newVal) {
|
||||
SSATmp* HhbcTranslator::stLoc(uint32_t id, IRTrace* exit, SSATmp* newVal) {
|
||||
const bool doRefCount = true;
|
||||
return stLocImpl(id, exit, newVal, doRefCount);
|
||||
}
|
||||
|
||||
SSATmp* HhbcTranslator::stLocNRC(uint32_t id, Trace* exit, SSATmp* newVal) {
|
||||
SSATmp* HhbcTranslator::stLocNRC(uint32_t id, IRTrace* exit, SSATmp* newVal) {
|
||||
const bool doRefCount = false;
|
||||
return stLocImpl(id, exit, newVal, doRefCount);
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ struct HhbcTranslator {
|
||||
const Func* func);
|
||||
|
||||
// Accessors.
|
||||
Trace* trace() const { return m_tb->trace(); }
|
||||
IRTrace* trace() const { return m_tb->trace(); }
|
||||
TraceBuilder* traceBuilder() const { return m_tb.get(); }
|
||||
|
||||
// In between each emit* call, irtranslator indicates the new
|
||||
@@ -262,7 +262,7 @@ struct HhbcTranslator {
|
||||
SSATmp* obj,
|
||||
const Func* func,
|
||||
int32_t numParams,
|
||||
Trace* catchTrace);
|
||||
IRTrace* catchTrace);
|
||||
void emitCreateCl(int32_t numParams, int32_t classNameStrId);
|
||||
void emitFCallArray(const Offset pcOffset, const Offset after);
|
||||
void emitFCall(uint32_t numParams,
|
||||
@@ -457,7 +457,7 @@ private:
|
||||
* if appropriate.
|
||||
*/
|
||||
template<typename... Srcs>
|
||||
SSATmp* genStk(Opcode op, Trace* taken, Srcs... srcs);
|
||||
SSATmp* genStk(Opcode op, IRTrace* taken, Srcs... srcs);
|
||||
|
||||
/* Various predicates about the current instruction */
|
||||
bool isSimpleArrayOp();
|
||||
@@ -514,7 +514,7 @@ private:
|
||||
* unexpected type, in which case they'll throw an InvalidSetMException. To
|
||||
* handle this, emitMPost adds code to the catch trace to fish the correct
|
||||
* value out of the exception and side exit. */
|
||||
Trace* m_failedSetTrace;
|
||||
IRTrace* m_failedSetTrace;
|
||||
};
|
||||
|
||||
private: // tracebuilder forwarding utilities
|
||||
@@ -529,7 +529,7 @@ private: // tracebuilder forwarding utilities
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
SSATmp* genFor(Trace* trace, Args&&... args) {
|
||||
SSATmp* genFor(IRTrace* trace, Args&&... args) {
|
||||
return m_tb->genFor(trace, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
@@ -560,7 +560,7 @@ private:
|
||||
void emitEmpty(const StringData* name,
|
||||
CheckSupportedFun checkSupported,
|
||||
EmitLdAddrFun emitLdAddr);
|
||||
void emitIncDecMem(bool pre, bool inc, SSATmp* ptr, Trace* exitTrace);
|
||||
void emitIncDecMem(bool pre, bool inc, SSATmp* ptr, IRTrace* exitTrace);
|
||||
bool checkSupportedClsProp(const StringData* propName,
|
||||
Type resultType,
|
||||
int stkIndex);
|
||||
@@ -595,10 +595,10 @@ private:
|
||||
void emitMarker();
|
||||
|
||||
private: // Exit trace creation routines.
|
||||
Trace* getExitTrace(Offset targetBcOff = -1);
|
||||
Trace* getExitTrace(Offset targetBcOff,
|
||||
IRTrace* getExitTrace(Offset targetBcOff = -1);
|
||||
IRTrace* getExitTrace(Offset targetBcOff,
|
||||
std::vector<SSATmp*>& spillValues);
|
||||
Trace* getExitTraceWarn(Offset targetBcOff,
|
||||
IRTrace* getExitTraceWarn(Offset targetBcOff,
|
||||
std::vector<SSATmp*>& spillValues,
|
||||
const StringData* warning);
|
||||
|
||||
@@ -609,7 +609,7 @@ private: // Exit trace creation routines.
|
||||
* The exit trace will spill things with a Marker for the current bytecode.
|
||||
*
|
||||
* Then it will do an ExceptionBarrier, followed by whatever is done
|
||||
* by the CustomExit(Trace*) function. The custom exit may add
|
||||
* by the CustomExit(IRTrace*) function. The custom exit may add
|
||||
* instructions to the exit trace, and optionally may return an
|
||||
* additional SSATmp* to spill on the stack. If there is no
|
||||
* additional SSATmp*, it should return nullptr.
|
||||
@@ -618,21 +618,21 @@ private: // Exit trace creation routines.
|
||||
* using gen/push/spillStack/etc.
|
||||
*/
|
||||
template<class ExitLambda>
|
||||
Trace* makeSideExit(Offset targetBcOff, ExitLambda exit);
|
||||
IRTrace* makeSideExit(Offset targetBcOff, ExitLambda exit);
|
||||
|
||||
/*
|
||||
* Generates an exit trace which will continue execution without HHIR.
|
||||
* This should be used in situations that HHIR cannot handle -- ideally
|
||||
* only in slow paths.
|
||||
*/
|
||||
Trace* getExitSlowTrace();
|
||||
Trace* getCatchTrace();
|
||||
IRTrace* getExitSlowTrace();
|
||||
IRTrace* getCatchTrace();
|
||||
|
||||
/*
|
||||
* Implementation for the above. Takes spillValues, target offset,
|
||||
* and a flag for whether to make a no-IR exit.
|
||||
*
|
||||
* Also takes a CustomExit(Trace*) function that may perform more
|
||||
* Also takes a CustomExit(IRTrace*) function that may perform more
|
||||
* operations and optionally return a single additional SSATmp*
|
||||
* (otherwise nullptr) to spill on the stack before exiting.
|
||||
*/
|
||||
@@ -644,8 +644,8 @@ private: // Exit trace creation routines.
|
||||
// instead of one for targetBcOff.
|
||||
DelayedMarker,
|
||||
};
|
||||
typedef std::function<SSATmp* (Trace*)> CustomExit;
|
||||
Trace* getExitTraceImpl(Offset targetBcOff,
|
||||
typedef std::function<SSATmp* (IRTrace*)> CustomExit;
|
||||
IRTrace* getExitTraceImpl(Offset targetBcOff,
|
||||
ExitFlag noIRExit,
|
||||
std::vector<SSATmp*>& spillValues,
|
||||
const CustomExit&);
|
||||
@@ -703,7 +703,7 @@ private:
|
||||
SSATmp* topC(uint32_t i = 0) { return top(Type::Cell, i); }
|
||||
SSATmp* topV(uint32_t i = 0) { return top(Type::BoxedCell, i); }
|
||||
std::vector<SSATmp*> peekSpillValues() const;
|
||||
SSATmp* emitSpillStack(Trace* t, SSATmp* sp,
|
||||
SSATmp* emitSpillStack(IRTrace* t, SSATmp* sp,
|
||||
const std::vector<SSATmp*>& spillVals);
|
||||
SSATmp* spillStack();
|
||||
void exceptionBarrier();
|
||||
@@ -718,12 +718,12 @@ private:
|
||||
*/
|
||||
SSATmp* ldLoc(uint32_t id);
|
||||
SSATmp* ldLocAddr(uint32_t id);
|
||||
SSATmp* ldLocInner(uint32_t id, Trace* exitTrace);
|
||||
SSATmp* ldLocInnerWarn(uint32_t id, Trace* target,
|
||||
Trace* catchTrace = nullptr);
|
||||
SSATmp* stLoc(uint32_t id, Trace* exitTrace, SSATmp* newVal);
|
||||
SSATmp* stLocNRC(uint32_t id, Trace* exitTrace, SSATmp* newVal);
|
||||
SSATmp* stLocImpl(uint32_t id, Trace*, SSATmp* newVal, bool doRefCount);
|
||||
SSATmp* ldLocInner(uint32_t id, IRTrace* exitTrace);
|
||||
SSATmp* ldLocInnerWarn(uint32_t id, IRTrace* target,
|
||||
IRTrace* catchTrace = nullptr);
|
||||
SSATmp* stLoc(uint32_t id, IRTrace* exitTrace, SSATmp* newVal);
|
||||
SSATmp* stLocNRC(uint32_t id, IRTrace* exitTrace, SSATmp* newVal);
|
||||
SSATmp* stLocImpl(uint32_t id, IRTrace*, SSATmp* newVal, bool doRefCount);
|
||||
|
||||
private:
|
||||
// Tracks information about the current bytecode offset and which
|
||||
|
||||
@@ -325,7 +325,7 @@ Opcode getStackModifyingOpcode(Opcode opc) {
|
||||
return opc;
|
||||
}
|
||||
|
||||
Trace* IRInstruction::trace() const {
|
||||
IRTrace* IRInstruction::trace() const {
|
||||
return block()->trace();
|
||||
}
|
||||
|
||||
@@ -1029,7 +1029,7 @@ std::string SSATmp::toString() const {
|
||||
return out.str();
|
||||
}
|
||||
|
||||
std::string Trace::toString() const {
|
||||
std::string IRTrace::toString() const {
|
||||
std::ostringstream out;
|
||||
print(out, this, nullptr);
|
||||
return out.str();
|
||||
@@ -1053,7 +1053,7 @@ bool isConvIntOrPtrToBool(IRInstruction* instr) {
|
||||
}
|
||||
}
|
||||
|
||||
BlockList rpoSortCfg(Trace* trace, const IRFactory& factory) {
|
||||
BlockList rpoSortCfg(IRTrace* trace, const IRFactory& factory) {
|
||||
assert(trace->isMain());
|
||||
BlockList blocks;
|
||||
blocks.reserve(factory.numBlocks());
|
||||
@@ -1151,7 +1151,7 @@ DomChildren findDomChildren(const BlockList& blocks) {
|
||||
return children;
|
||||
}
|
||||
|
||||
bool hasInternalFlow(Trace* trace) {
|
||||
bool hasInternalFlow(IRTrace* trace) {
|
||||
for (Block* block : trace->blocks()) {
|
||||
if (Block* taken = block->taken()) {
|
||||
if (taken->trace() == trace) return true;
|
||||
|
||||
@@ -62,7 +62,7 @@ using HPHP::Transl::ConditionCode;
|
||||
struct IRInstruction;
|
||||
struct SSATmp;
|
||||
struct Block;
|
||||
struct Trace;
|
||||
struct IRTrace;
|
||||
|
||||
class FailedIRGen : public std::exception {
|
||||
public:
|
||||
@@ -834,7 +834,7 @@ class RawMemSlot {
|
||||
};
|
||||
|
||||
class SSATmp;
|
||||
class Trace;
|
||||
class IRTrace;
|
||||
class CodeGenerator;
|
||||
struct AsmInfo;
|
||||
class IRFactory;
|
||||
@@ -932,7 +932,7 @@ typedef folly::Range<TCA> TcaRange;
|
||||
/**
|
||||
* Run all optimization passes on this trace
|
||||
*/
|
||||
void optimizeTrace(Trace*, IRFactory* irFactory);
|
||||
void optimizeTrace(IRTrace*, IRFactory* irFactory);
|
||||
|
||||
/*
|
||||
* Counts the number of cells a SpillStack will logically push. (Not
|
||||
|
||||
@@ -102,7 +102,7 @@ private:
|
||||
inst->setTaken(target);
|
||||
}
|
||||
|
||||
void setter(IRInstruction* inst, Trace* trace) {
|
||||
void setter(IRInstruction* inst, IRTrace* trace) {
|
||||
inst->setTaken(trace ? trace->front() : nullptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -223,7 +223,7 @@ struct IRInstruction {
|
||||
* inserting it in any blocks.
|
||||
*/
|
||||
bool isTransient() const { return m_id == kTransient; }
|
||||
Trace* trace() const;
|
||||
IRTrace* trace() const;
|
||||
|
||||
/*
|
||||
* block() and setBlock() keep track of the block that contains this
|
||||
|
||||
@@ -1845,7 +1845,7 @@ void TranslatorX64::hhirTraceEnd() {
|
||||
void TranslatorX64::hhirTraceCodeGen(vector<TransBCMapping>* bcMap) {
|
||||
using namespace JIT;
|
||||
|
||||
HPHP::JIT::Trace* trace = m_hhbcTrans->trace();
|
||||
HPHP::JIT::IRTrace* trace = m_hhbcTrans->trace();
|
||||
auto finishPass = [&](const char* msg, int level,
|
||||
const RegAllocInfo* regs = nullptr,
|
||||
const LifetimeInfo* lifetime = nullptr) {
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace {
|
||||
// If main trace ends with an unconditional jump, and the target is not
|
||||
// reached by any other branch, then copy the target of the jump to the
|
||||
// end of the trace
|
||||
void elimUnconditionalJump(Trace* trace, IRFactory* irFactory) {
|
||||
void elimUnconditionalJump(IRTrace* trace, IRFactory* irFactory) {
|
||||
boost::dynamic_bitset<> isJoin(irFactory->numBlocks());
|
||||
boost::dynamic_bitset<> havePred(irFactory->numBlocks());
|
||||
for (Block* block : trace->blocks()) {
|
||||
@@ -58,7 +58,7 @@ void elimUnconditionalJump(Trace* trace, IRFactory* irFactory) {
|
||||
}
|
||||
}
|
||||
|
||||
Block* findMainExitBlock(Trace* trace, IRFactory* irFactory) {
|
||||
Block* findMainExitBlock(IRTrace* trace, IRFactory* irFactory) {
|
||||
assert(trace->isMain());
|
||||
auto const back = trace->back();
|
||||
|
||||
@@ -136,7 +136,7 @@ bool jccCanBeDirectExit(Opcode opc) {
|
||||
* This leads to more efficient code because the service request stubs
|
||||
* will patch jumps in the main trace instead of off-trace.
|
||||
*/
|
||||
void optimizeCondTraceExit(Trace* trace, IRFactory* irFactory) {
|
||||
void optimizeCondTraceExit(IRTrace* trace, IRFactory* irFactory) {
|
||||
FTRACE(5, "CondExit:vvvvvvvvvvvvvvvvvvvvv\n");
|
||||
SCOPE_EXIT { FTRACE(5, "CondExit:^^^^^^^^^^^^^^^^^^^^^\n"); };
|
||||
|
||||
@@ -177,7 +177,7 @@ void optimizeCondTraceExit(Trace* trace, IRFactory* irFactory) {
|
||||
* branch to "normal exits". We can optimize these into the
|
||||
* SideExitGuard* instructions that can be patched in place.
|
||||
*/
|
||||
void optimizeSideExits(Trace* trace, IRFactory* irFactory) {
|
||||
void optimizeSideExits(IRTrace* trace, IRFactory* irFactory) {
|
||||
FTRACE(5, "SideExit:vvvvvvvvvvvvvvvvvvvvv\n");
|
||||
SCOPE_EXIT { FTRACE(5, "SideExit:^^^^^^^^^^^^^^^^^^^^^\n"); };
|
||||
|
||||
@@ -220,7 +220,7 @@ void optimizeSideExits(Trace* trace, IRFactory* irFactory) {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
void optimizeJumps(Trace* trace, IRFactory* irFactory) {
|
||||
void optimizeJumps(IRTrace* trace, IRFactory* irFactory) {
|
||||
elimUnconditionalJump(trace, irFactory);
|
||||
|
||||
if (RuntimeOption::EvalHHIRDirectExit) {
|
||||
|
||||
@@ -58,7 +58,7 @@ smart::vector<Block*> rpoForCodegen(const IRFactory& factory, Block* head) {
|
||||
* so this just selects an appropriate reverse post order on the
|
||||
* blocks, and partitions the unlikely ones to astubs.
|
||||
*/
|
||||
LayoutInfo layoutBlocks(Trace* trace, const IRFactory& irFactory) {
|
||||
LayoutInfo layoutBlocks(IRTrace* trace, const IRFactory& irFactory) {
|
||||
LayoutInfo ret;
|
||||
ret.blocks = rpoForCodegen(irFactory, trace->blocks().front());
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ struct LayoutInfo {
|
||||
* goal is to minimize branching and put related blocks close to each
|
||||
* other.
|
||||
*/
|
||||
LayoutInfo layoutBlocks(Trace*, const IRFactory&);
|
||||
LayoutInfo layoutBlocks(IRTrace*, const IRFactory&);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ struct LinearScan : private boost::noncopyable {
|
||||
static const int NumRegs = kNumRegs;
|
||||
|
||||
explicit LinearScan(IRFactory*);
|
||||
RegAllocInfo allocRegs(Trace*, LifetimeInfo*);
|
||||
RegAllocInfo allocRegs(IRTrace*, LifetimeInfo*);
|
||||
|
||||
private:
|
||||
class RegState {
|
||||
@@ -141,8 +141,8 @@ private:
|
||||
return m_irFactory->cns(val);
|
||||
}
|
||||
void initFreeList();
|
||||
void coalesce(Trace* trace);
|
||||
void genSpillStats(Trace* trace, int numSpillLocs);
|
||||
void coalesce(IRTrace* trace);
|
||||
void genSpillStats(IRTrace* trace, int numSpillLocs);
|
||||
void allocRegsOneTrace(BlockList::iterator& blockIt,
|
||||
ExitTraceMap& etm);
|
||||
void allocRegsToTrace();
|
||||
@@ -153,7 +153,7 @@ private:
|
||||
void rematerialize();
|
||||
void rematerializeAux();
|
||||
void removeUnusedSpills();
|
||||
void collectInfo(BlockList::iterator it, Trace* trace);
|
||||
void collectInfo(BlockList::iterator it, IRTrace* trace);
|
||||
RegNumber getJmpPreColor(SSATmp* tmp, uint32_t regIndx, bool isReload);
|
||||
void computePreColoringHint();
|
||||
void findFullXMMCandidates();
|
||||
@@ -714,7 +714,7 @@ uint32_t LinearScan::assignSpillLoc() {
|
||||
return maxSpillLoc;
|
||||
}
|
||||
|
||||
void LinearScan::collectInfo(BlockList::iterator it, Trace* trace) {
|
||||
void LinearScan::collectInfo(BlockList::iterator it, IRTrace* trace) {
|
||||
m_natives.clear();
|
||||
m_jmps.reset();
|
||||
m_uses.reset();
|
||||
@@ -954,7 +954,7 @@ void LinearScan::initFreeList() {
|
||||
}
|
||||
}
|
||||
|
||||
void LinearScan::coalesce(Trace* trace) {
|
||||
void LinearScan::coalesce(IRTrace* trace) {
|
||||
forEachTraceInst(trace, [](IRInstruction* inst) {
|
||||
for (uint32_t i = 0; i < inst->numSrcs(); ++i) {
|
||||
SSATmp* src = inst->src(i);
|
||||
@@ -990,7 +990,7 @@ void LinearScan::numberInstructions(const BlockList& blocks) {
|
||||
}
|
||||
}
|
||||
|
||||
void LinearScan::genSpillStats(Trace* trace, int numSpillLocs) {
|
||||
void LinearScan::genSpillStats(IRTrace* trace, int numSpillLocs) {
|
||||
if (!moduleEnabled(HPHP::Trace::statgroups, 1)) return;
|
||||
static bool enabled = getenv("HHVM_STATS_SPILLS");
|
||||
if (!enabled) return;
|
||||
@@ -1079,7 +1079,7 @@ void LinearScan::findFullXMMCandidates() {
|
||||
m_fullXMMCandidates -= notCandidates;
|
||||
}
|
||||
|
||||
RegAllocInfo LinearScan::allocRegs(Trace* trace, LifetimeInfo* lifetime) {
|
||||
RegAllocInfo LinearScan::allocRegs(IRTrace* trace, LifetimeInfo* lifetime) {
|
||||
if (RuntimeOption::EvalHHIREnableCoalescing) {
|
||||
// <coalesce> doesn't need instruction numbering.
|
||||
coalesce(trace);
|
||||
@@ -1653,7 +1653,7 @@ void LinearScan::PreColoringHint::add(SSATmp* tmp, uint32_t index, int argNum) {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
RegAllocInfo allocRegsForTrace(Trace* trace, IRFactory* irFactory,
|
||||
RegAllocInfo allocRegsForTrace(IRTrace* trace, IRFactory* irFactory,
|
||||
LifetimeInfo* lifetime) {
|
||||
return LinearScan(irFactory).allocRegs(trace, lifetime);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
namespace HPHP { namespace JIT {
|
||||
|
||||
class Trace;
|
||||
class IRTrace;
|
||||
class IRFactory;
|
||||
|
||||
// This value must be consistent with the number of pre-allocated
|
||||
@@ -206,7 +206,7 @@ inline std::ostream& operator<<(std::ostream& os, SpillInfo si) {
|
||||
* The main entry point for register allocation. Called prior to code
|
||||
* generation.
|
||||
*/
|
||||
RegAllocInfo allocRegsForTrace(Trace*, IRFactory*, LifetimeInfo* = nullptr);
|
||||
RegAllocInfo allocRegsForTrace(IRTrace*, IRFactory*, LifetimeInfo* = nullptr);
|
||||
|
||||
// Native stack layout:
|
||||
// | |
|
||||
|
||||
@@ -77,7 +77,7 @@ static void insertSpillStackAsserts(IRInstruction& inst, IRFactory* factory) {
|
||||
* Insert asserts at various points in the IR.
|
||||
* TODO: t2137231 Insert DbgAssertPtr at points that use or produces a GenPtr
|
||||
*/
|
||||
static void insertAsserts(Trace* trace, IRFactory* factory) {
|
||||
static void insertAsserts(IRTrace* trace, IRFactory* factory) {
|
||||
forEachTraceBlock(trace, [=](Block* block) {
|
||||
for (auto it = block->begin(), end = block->end(); it != end; ) {
|
||||
IRInstruction& inst = *it;
|
||||
@@ -101,7 +101,7 @@ static void insertAsserts(Trace* trace, IRFactory* factory) {
|
||||
});
|
||||
}
|
||||
|
||||
void optimizeTrace(Trace* trace, TraceBuilder* traceBuilder) {
|
||||
void optimizeTrace(IRTrace* trace, TraceBuilder* traceBuilder) {
|
||||
IRFactory* irFactory = traceBuilder->factory();
|
||||
|
||||
auto finishPass = [&](const char* msg) {
|
||||
@@ -111,7 +111,7 @@ void optimizeTrace(Trace* trace, TraceBuilder* traceBuilder) {
|
||||
if (debug) forEachTraceInst(trace, assertOperandTypes);
|
||||
};
|
||||
|
||||
auto doPass = [&](void (*fn)(Trace*, IRFactory*),
|
||||
auto doPass = [&](void (*fn)(IRTrace*, IRFactory*),
|
||||
const char* msg) {
|
||||
fn(trace, irFactory);
|
||||
finishPass(msg);
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace HPHP { namespace JIT {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
class Trace;
|
||||
class IRTrace;
|
||||
class TraceBuilder;
|
||||
class IRFactory;
|
||||
class IRInstruction;
|
||||
@@ -30,15 +30,15 @@ class IRInstruction;
|
||||
/*
|
||||
* The main optimization passes, in the order they run.
|
||||
*/
|
||||
void optimizeMemoryAccesses(Trace*, IRFactory*);
|
||||
void optimizePredictions(Trace*, IRFactory*);
|
||||
void eliminateDeadCode(Trace*, IRFactory*);
|
||||
void optimizeJumps(Trace*, IRFactory*);
|
||||
void optimizeMemoryAccesses(IRTrace*, IRFactory*);
|
||||
void optimizePredictions(IRTrace*, IRFactory*);
|
||||
void eliminateDeadCode(IRTrace*, IRFactory*);
|
||||
void optimizeJumps(IRTrace*, IRFactory*);
|
||||
|
||||
/*
|
||||
* Run all the optimization passes.
|
||||
*/
|
||||
void optimizeTrace(Trace*, TraceBuilder*);
|
||||
void optimizeTrace(IRTrace*, TraceBuilder*);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ bool instructionsAreSinkable(InputIterator first, InputIterator last) {
|
||||
* Optimizations that try to hoist CheckType instructions so that we
|
||||
* can specialize code earlier and avoid generic operations.
|
||||
*/
|
||||
void optimizePredictions(Trace* const trace, IRFactory* const irFactory) {
|
||||
void optimizePredictions(IRTrace* const trace, IRFactory* const irFactory) {
|
||||
FTRACE(5, "PredOpts:vvvvvvvvvvvvvvvvvvvvv\n");
|
||||
SCOPE_EXIT { FTRACE(5, "PredOpts:^^^^^^^^^^^^^^^^^^^^^\n"); };
|
||||
|
||||
|
||||
@@ -263,13 +263,13 @@ void print(const SSATmp* tmp) {
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
void print(const Trace* trace) {
|
||||
void print(const IRTrace* trace) {
|
||||
print(std::cout, trace);
|
||||
}
|
||||
|
||||
// Print unlikely blocks at the end in normal generation. If we have
|
||||
// asmInfo, order the blocks based on how they were layed out.
|
||||
static smart::vector<Block*> blocks(const Trace* trace,
|
||||
static smart::vector<Block*> blocks(const IRTrace* trace,
|
||||
const AsmInfo* asmInfo) {
|
||||
smart::vector<Block*> blocks;
|
||||
|
||||
@@ -282,7 +282,7 @@ static smart::vector<Block*> blocks(const Trace* trace,
|
||||
blocks.push_back(block);
|
||||
}
|
||||
}
|
||||
for (Trace* e : trace->exitTraces()) {
|
||||
for (IRTrace* e : trace->exitTraces()) {
|
||||
unlikely.insert(unlikely.end(),
|
||||
e->blocks().begin(),
|
||||
e->blocks().end());
|
||||
@@ -292,7 +292,7 @@ static smart::vector<Block*> blocks(const Trace* trace,
|
||||
}
|
||||
|
||||
blocks.assign(trace->blocks().begin(), trace->blocks().end());
|
||||
for (Trace* e : trace->exitTraces()) {
|
||||
for (IRTrace* e : trace->exitTraces()) {
|
||||
blocks.insert(blocks.end(), e->blocks().begin(), e->blocks().end());
|
||||
}
|
||||
std::sort(
|
||||
@@ -306,7 +306,7 @@ static smart::vector<Block*> blocks(const Trace* trace,
|
||||
return blocks;
|
||||
}
|
||||
|
||||
void print(std::ostream& os, const Trace* trace, const RegAllocInfo* regs,
|
||||
void print(std::ostream& os, const IRTrace* trace, const RegAllocInfo* regs,
|
||||
const LifetimeInfo* lifetime, const AsmInfo* asmInfo) {
|
||||
static const int kIndent = 4;
|
||||
Disasm disasm(Disasm::Options().indent(kIndent + 4)
|
||||
@@ -413,7 +413,7 @@ void print(std::ostream& os, const Trace* trace, const RegAllocInfo* regs,
|
||||
}
|
||||
}
|
||||
|
||||
void dumpTraceImpl(const Trace* trace,
|
||||
void dumpTraceImpl(const IRTrace* trace,
|
||||
std::ostream& out,
|
||||
const RegAllocInfo* regs,
|
||||
const LifetimeInfo* lifetime,
|
||||
@@ -423,7 +423,7 @@ void dumpTraceImpl(const Trace* trace,
|
||||
|
||||
// Suggested captions: "before jiffy removal", "after goat saturation",
|
||||
// etc.
|
||||
void dumpTrace(int level, const Trace* trace, const char* caption,
|
||||
void dumpTrace(int level, const IRTrace* trace, const char* caption,
|
||||
const RegAllocInfo* regs, const LifetimeInfo* lifetime,
|
||||
AsmInfo* ai) {
|
||||
if (dumpIREnabled(level)) {
|
||||
|
||||
@@ -28,7 +28,7 @@ struct IRInstruction;
|
||||
class SSATmp;
|
||||
struct Block;
|
||||
struct AsmInfo;
|
||||
class Trace;
|
||||
class IRTrace;
|
||||
struct LifetimeInfo;
|
||||
|
||||
// IRInstruction
|
||||
@@ -47,11 +47,11 @@ void print(std::ostream& ostream, const SSATmp*,
|
||||
void print(const SSATmp*);
|
||||
|
||||
// Trace
|
||||
void print(std::ostream& ostream, const Trace*,
|
||||
void print(std::ostream& ostream, const IRTrace*,
|
||||
const RegAllocInfo* regs = nullptr,
|
||||
const LifetimeInfo* lifetime = nullptr,
|
||||
const AsmInfo* asmInfo = nullptr);
|
||||
void print(const Trace*);
|
||||
void print(const IRTrace*);
|
||||
|
||||
/*
|
||||
* Some utilities related to dumping. Rather than file-by-file control, we
|
||||
@@ -67,9 +67,9 @@ static const int kRegAllocLevel = 3;
|
||||
static const int kOptLevel = 4;
|
||||
static const int kExtraLevel = 6;
|
||||
|
||||
void dumpTraceImpl(const Trace* trace, std::ostream& out,
|
||||
void dumpTraceImpl(const IRTrace* trace, std::ostream& out,
|
||||
const RegAllocInfo*, const LifetimeInfo*, const AsmInfo*);
|
||||
void dumpTrace(int level, const Trace* trace, const char* caption,
|
||||
void dumpTrace(int level, const IRTrace* trace, const char* caption,
|
||||
const RegAllocInfo* regs = nullptr,
|
||||
const LifetimeInfo* lifetime = nullptr,
|
||||
AsmInfo* ai = nullptr);
|
||||
|
||||
@@ -23,24 +23,24 @@
|
||||
namespace HPHP { namespace JIT {
|
||||
|
||||
/*
|
||||
* A Trace is a single-entry, multi-exit, sequence of blocks. Typically
|
||||
* An IRTrace is a single-entry, multi-exit, sequence of blocks. Typically
|
||||
* each block falls through to the next block but this is not guaranteed;
|
||||
* traces may contain internal forward-only control flow.
|
||||
*/
|
||||
struct Trace : private boost::noncopyable {
|
||||
struct IRTrace : private boost::noncopyable {
|
||||
typedef std::list<Block*>::const_iterator const_iterator;
|
||||
typedef std::list<Block*>::iterator iterator;
|
||||
|
||||
explicit Trace(Block* first, uint32_t bcOff)
|
||||
explicit IRTrace(Block* first, uint32_t bcOff)
|
||||
: m_bcOff(bcOff)
|
||||
, m_main(nullptr)
|
||||
{
|
||||
push_back(first);
|
||||
}
|
||||
|
||||
~Trace() {
|
||||
~IRTrace() {
|
||||
std::for_each(m_exitTraces.begin(), m_exitTraces.end(),
|
||||
boost::checked_deleter<Trace>());
|
||||
boost::checked_deleter<IRTrace>());
|
||||
}
|
||||
|
||||
std::list<Block*>& blocks() { return m_blocks; }
|
||||
@@ -89,7 +89,7 @@ struct Trace : private boost::noncopyable {
|
||||
void setData(uint32_t d) { m_data = d; }
|
||||
|
||||
uint32_t bcOff() const { return m_bcOff; }
|
||||
Trace* addExitTrace(Trace* exit) {
|
||||
IRTrace* addExitTrace(IRTrace* exit) {
|
||||
m_exitTraces.push_back(exit);
|
||||
exit->setMain(this);
|
||||
return exit;
|
||||
@@ -104,16 +104,16 @@ struct Trace : private boost::noncopyable {
|
||||
|
||||
return (--it)->op() == BeginCatch;
|
||||
}
|
||||
void setMain(Trace* t) {
|
||||
void setMain(IRTrace* t) {
|
||||
assert(m_main == nullptr);
|
||||
m_main = t;
|
||||
}
|
||||
Trace* main() {
|
||||
IRTrace* main() {
|
||||
return m_main;
|
||||
}
|
||||
|
||||
typedef std::list<Trace*> ExitList;
|
||||
typedef std::list<Trace*>::iterator ExitIterator;
|
||||
typedef std::list<IRTrace*> ExitList;
|
||||
typedef std::list<IRTrace*>::iterator ExitIterator;
|
||||
|
||||
ExitList& exitTraces() { return m_exitTraces; }
|
||||
const ExitList& exitTraces() const { return m_exitTraces; }
|
||||
@@ -126,7 +126,7 @@ private:
|
||||
uint32_t m_data;
|
||||
std::list<Block*> m_blocks; // Blocks in main trace starting with entry block
|
||||
ExitList m_exitTraces; // traces to which this trace exits
|
||||
Trace* m_main; // ptr to parent trace if this is an exit trace
|
||||
IRTrace* m_main; // ptr to parent trace if this is an exit trace
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -98,7 +98,7 @@ struct TraceBuilder {
|
||||
void setEnableCse(bool val) { m_enableCse = val; }
|
||||
void setEnableSimplification(bool val) { m_enableSimplification = val; }
|
||||
|
||||
Trace* trace() const { return m_trace.get(); }
|
||||
IRTrace* trace() const { return m_trace.get(); }
|
||||
IRFactory* factory() { return &m_irFactory; }
|
||||
int32_t spOffset() { return m_spOffset; }
|
||||
SSATmp* sp() const { return m_spValue; }
|
||||
@@ -141,7 +141,7 @@ struct TraceBuilder {
|
||||
* TODO(#2404447): run simplifier?
|
||||
*/
|
||||
template<class... Args>
|
||||
SSATmp* genFor(Trace* t, Args&&... args) {
|
||||
SSATmp* genFor(IRTrace* t, Args&&... args) {
|
||||
auto instr = m_irFactory.gen(std::forward<Args>(args)...);
|
||||
t->back()->push_back(instr);
|
||||
return instr->dst();
|
||||
@@ -257,7 +257,7 @@ struct TraceBuilder {
|
||||
* a cold path, which always exits the tracelet without control flow
|
||||
* rejoining the main line.
|
||||
*/
|
||||
Trace* makeExitTrace(uint32_t bcOff) {
|
||||
IRTrace* makeExitTrace(uint32_t bcOff) {
|
||||
return m_trace->addExitTrace(makeTrace(m_curFunc->getValFunc(),
|
||||
bcOff));
|
||||
}
|
||||
@@ -341,8 +341,8 @@ private:
|
||||
void clearTrackedState();
|
||||
void dropLocalRefsInnerTypes();
|
||||
|
||||
Trace* makeTrace(const Func* func, uint32_t bcOff) {
|
||||
return new Trace(m_irFactory.defBlock(func), bcOff);
|
||||
IRTrace* makeTrace(const Func* func, uint32_t bcOff) {
|
||||
return new IRTrace(m_irFactory.defBlock(func), bcOff);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -356,7 +356,7 @@ private:
|
||||
IRFactory& m_irFactory;
|
||||
Simplifier m_simplifier;
|
||||
|
||||
boost::scoped_ptr<Trace> const m_trace; // generated trace
|
||||
boost::scoped_ptr<IRTrace> const m_trace; // generated trace
|
||||
|
||||
// Flags that enable optimizations
|
||||
bool m_enableCse;
|
||||
|
||||
@@ -266,7 +266,7 @@ HhbcTranslator::VectorTranslator::VectorTranslator(
|
||||
}
|
||||
|
||||
template<typename... Srcs>
|
||||
SSATmp* HhbcTranslator::VectorTranslator::genStk(Opcode opc, Trace* taken,
|
||||
SSATmp* HhbcTranslator::VectorTranslator::genStk(Opcode opc, IRTrace* taken,
|
||||
Srcs... srcs) {
|
||||
assert(opcodeHasFlags(opc, HasStackVersion));
|
||||
assert(!opcodeHasFlags(opc, ModifiesStack));
|
||||
@@ -565,7 +565,7 @@ void HhbcTranslator::VectorTranslator::emitBaseLCR() {
|
||||
// the MInstrState. These particular stores are harmless though, and the
|
||||
// worst outcome here is that we'll end up doing the stores twice, once for
|
||||
// this instruction and once at the beginning of the retranslation.
|
||||
Trace* failedRef = baseType.isBoxed() ? m_ht.getExitTrace() : nullptr;
|
||||
IRTrace* failedRef = baseType.isBoxed() ? m_ht.getExitTrace() : nullptr;
|
||||
if ((baseType.subtypeOfAny(Type::Obj, Type::BoxedObj) &&
|
||||
mcodeMaybePropName(m_ni.immVecM[0])) ||
|
||||
isSimpleArrayOp()) {
|
||||
@@ -2155,7 +2155,7 @@ void HhbcTranslator::VectorTranslator::emitSideExits(SSATmp* catchSp,
|
||||
assert(toSpill[0] == m_result);
|
||||
SSATmp* str = m_irf.gen(AssertNonNull, m_strTestResult)->dst();
|
||||
toSpill[0] = str;
|
||||
Trace* exit = m_ht.getExitTrace(nextOff, toSpill);
|
||||
IRTrace* exit = m_ht.getExitTrace(nextOff, toSpill);
|
||||
exit->front()->prepend(str->inst());
|
||||
exit->front()->prepend(m_irf.gen(DecRef, m_result));
|
||||
exit->front()->prepend(
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário