Skip to content

Commit

Permalink
Replace Vunit::roots with a single entry block
Browse files Browse the repository at this point in the history
Summary: We don't need multiple roots. All code should be reachable from a
single entry block. The only complication was bindaddr. It's now roughly
analogous to the other service request instructions in that it lives in the
code block that references it and directly emits the service request itself to
frozen.

Reviewed By: @edwinsmith

Differential Revision: D1603594
  • Loading branch information
swtaarrs authored and hhvm-bot committed Oct 13, 2014
1 parent 4183f94 commit 007f175
Show file tree
Hide file tree
Showing 11 changed files with 58 additions and 63 deletions.
2 changes: 1 addition & 1 deletion hphp/runtime/vm/jit/back-end-arm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,7 @@ void BackEnd::genCodeImpl(IRUnit& unit, AsmInfo* asmInfo) {
}
// create vregs for all relevant SSATmps
assignRegs(unit, vunit, state, linfo.blocks, this);
vunit.roots.push_back(state.labels[unit.entry()]);
vunit.entry = state.labels[unit.entry()];
vasm.main(mainCode);
vasm.cold(coldCode);
vasm.frozen(*frozenCode);
Expand Down
2 changes: 1 addition & 1 deletion hphp/runtime/vm/jit/back-end-x64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -797,7 +797,7 @@ void BackEnd::genCodeImpl(IRUnit& unit, AsmInfo* asmInfo) {
}
// create vregs for all relevant SSATmps
assignRegs(unit, vunit, state, linfo.blocks, this);
vunit.roots.push_back(state.labels[unit.entry()]);
vunit.entry = state.labels[unit.entry()];
vasm.main(mainCode);
vasm.cold(coldCode);
vasm.frozen(*frozenCode);
Expand Down
16 changes: 8 additions & 8 deletions hphp/runtime/vm/jit/code-gen-helpers-x64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ void emitEagerSyncPoint(Vout& v, const Op* pc) {
}

void emitEagerSyncPoint(Asm& as, const Op* pc) {
emitEagerSyncPoint(Vauto().main(as), pc);
emitEagerSyncPoint(Vauto(as.code()).main(), pc);
}

// emitEagerVMRegSave --
Expand Down Expand Up @@ -115,7 +115,7 @@ void emitGetGContext(Vout& v, Vreg dest) {
}

void emitGetGContext(Asm& as, PhysReg dest) {
emitGetGContext(Vauto().main(as), dest);
emitGetGContext(Vauto(as.code()).main(), dest);
}

// IfCountNotStatic --
Expand Down Expand Up @@ -156,7 +156,7 @@ void emitTransCounterInc(Vout& v) {
}

void emitTransCounterInc(Asm& a) {
emitTransCounterInc(Vauto().main(a));
emitTransCounterInc(Vauto(a.code()).main());
}

void emitIncRef(Vout& v, Vreg base) {
Expand All @@ -173,7 +173,7 @@ void emitIncRef(Vout& v, Vreg base) {
}

void emitIncRef(Asm& as, PhysReg base) {
emitIncRef(Vauto().main(as), base);
emitIncRef(Vauto(as.code()).main(), base);
}

void emitIncRefCheckNonStatic(Asm& as, PhysReg base, DataType dtype) {
Expand Down Expand Up @@ -259,11 +259,11 @@ Vreg emitLdClsCctx(Vout& v, Vreg srcReg, Vreg dstReg) {
}

void emitCall(Asm& a, TCA dest, RegSet args) {
Vauto().main(a) << call{dest, args};
Vauto(a.code()).main() << call{dest, args};
}

void emitCall(Asm& a, CppCall call, RegSet args) {
emitCall(Vauto().main(a), call, args);
emitCall(Vauto(a.code()).main(), call, args);
}

void emitCall(Vout& v, CppCall target, RegSet args) {
Expand Down Expand Up @@ -368,8 +368,8 @@ Vreg emitTestSurpriseFlags(Vout& v) {

void emitCheckSurpriseFlagsEnter(CodeBlock& mainCode, CodeBlock& coldCode,
Fixup fixup) {
Vauto vasm;
auto& v = vasm.main(mainCode);
Vauto vasm(mainCode);
auto& v = vasm.main();
auto& vc = vasm.cold(coldCode);
emitCheckSurpriseFlagsEnter(v, vc, fixup);
}
Expand Down
28 changes: 10 additions & 18 deletions hphp/runtime/vm/jit/code-gen-x64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2284,12 +2284,10 @@ void CodeGenerator::cgLdBindAddr(IRInstruction* inst) {
auto data = inst->extra<LdBindAddr>();
auto dstReg = dstLoc(0).reg();
auto& v = vmain();
auto& vf = vfrozen();

// Emit service request to smash address of SrcKey into 'addr'.
TCA* addrPtr = mcg->allocData<TCA>(sizeof(TCA), 1);
vf = vf.makeEntry();
vf << bindaddr{addrPtr, data->sk};
v << bindaddr{addrPtr, data->sk};

// Load the maybe bound address.
auto addr = intptr_t(addrPtr);
Expand All @@ -2305,7 +2303,6 @@ void CodeGenerator::cgJmpSwitchDest(IRInstruction* inst) {
SSATmp* index = inst->src(0);
auto indexReg = srcLoc(0).reg();
auto& v = vmain();
auto& vf = vfrozen();

if (!index->isConst()) {
auto idx = indexReg;
Expand All @@ -2321,13 +2318,12 @@ void CodeGenerator::cgJmpSwitchDest(IRInstruction* inst) {

TCA* table = mcg->allocData<TCA>(sizeof(TCA), data->cases);
auto t = v.makeReg();
v << leap{rip[(intptr_t)table], t};
v << jmpm{t[idx*8]};
for (int i = 0; i < data->cases; i++) {
auto sk = SrcKey(curFunc(), data->targets[i], resumed());
vf = vf.makeEntry();
vf << bindaddr{&table[i], sk};
v << bindaddr{&table[i], sk};
}
v << leap{rip[(intptr_t)table], t};
v << jmpm{t[idx*8]};
} else {
int64_t indexVal = index->intVal();
if (data->bounded) {
Expand All @@ -2349,18 +2345,16 @@ void CodeGenerator::cgLdSSwitchDestFast(IRInstruction* inst) {
auto table = mcg->allocData<SSwitchMap>(64);
new (table) SSwitchMap(data->numCases);
auto& v = vmain();
auto& vf = vfrozen();

for (int64_t i = 0; i < data->numCases; ++i) {
table->add(data->cases[i].str, nullptr);
TCA* addr = table->find(data->cases[i].str);
auto sk = SrcKey(curFunc(), data->cases[i].dest, resumed());
vf = vf.makeEntry();
vf << bindaddr{addr, sk};
v << bindaddr{addr, sk};
}
TCA* def = mcg->allocData<TCA>(sizeof(TCA), 1);
auto sk = SrcKey(curFunc(), data->defaultOff, resumed());
vf = vf.makeEntry();
vf << bindaddr{def, sk};
v << bindaddr{def, sk};
cgCallHelper(v,
CppCall::direct(sswitchHelperFast),
callDest(inst),
Expand Down Expand Up @@ -2389,16 +2383,14 @@ void CodeGenerator::cgLdSSwitchDestSlow(IRInstruction* inst) {
sizeof(const StringData*), data->numCases);
auto jmptab = mcg->allocData<TCA>(sizeof(TCA), data->numCases + 1);
auto& v = vmain();
auto& vf = vfrozen();

for (int i = 0; i < data->numCases; ++i) {
strtab[i] = data->cases[i].str;
auto sk = SrcKey(curFunc(), data->cases[i].dest, resumed());
vf = vf.makeEntry();
vf << bindaddr{&jmptab[i], sk};
v << bindaddr{&jmptab[i], sk};
}
auto sk = SrcKey(curFunc(), data->defaultOff, resumed());
vf = vf.makeEntry();
vf << bindaddr{&jmptab[data->numCases], sk};
v << bindaddr{&jmptab[data->numCases], sk};
cgCallHelper(v,
CppCall::direct(sswitchHelperSlow),
callDest(inst),
Expand Down
6 changes: 3 additions & 3 deletions hphp/runtime/vm/jit/phys-reg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ PhysRegSaverParity::PhysRegSaverParity(int parity, Vout& v,

PhysRegSaverParity::PhysRegSaverParity(int parity, X64Assembler& as,
RegSet regs)
: PhysRegSaverParity{parity, Vauto().main(as), regs} {
: PhysRegSaverParity{parity, Vauto(as.code()).main(), regs} {
m_v = nullptr;
m_as = &as;
}
Expand All @@ -73,7 +73,7 @@ PhysRegSaverParity::~PhysRegSaverParity() {
emitPops(v, m_regs);
};
if (m_as) {
finish(Vauto().main(*m_as));
finish(Vauto(m_as->code()).main());
} else {
finish(*m_v);
}
Expand All @@ -97,7 +97,7 @@ void PhysRegSaverParity::emitPops(Vout& v, RegSet regs) {
}

void PhysRegSaverParity::emitPops(X64Assembler& as, RegSet regs) {
emitPops(Vauto().main(as), regs);
emitPops(Vauto(as.code()).main(), regs);
}

int PhysRegSaverParity::rspAdjustment() const {
Expand Down
1 change: 0 additions & 1 deletion hphp/runtime/vm/jit/vasm-check.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,6 @@ bool checkCalls(Vunit& unit, jit::vector<Vlabel>& blocks) {
bool isBlockEnd(Vinstr& inst) {
switch (inst.op) {
// service request-y things
case Vinstr::bindaddr:
case Vinstr::bindjcc1:
case Vinstr::bindjmp:
case Vinstr::fallback:
Expand Down
6 changes: 2 additions & 4 deletions hphp/runtime/vm/jit/vasm-jumps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,8 @@ void optimizeJmps(Vunit& unit) {
npreds[s]++;
}
});
// give roots an extra predecessor to prevent cloning them.
for (auto b : unit.roots) {
npreds[b]++;
}
// give entry an extra predecessor to prevent cloning it
npreds[unit.entry]++;
PostorderWalker{unit}.dfs([&](Vlabel b) {
auto& block = unit.blocks[b];
auto& code = block.code;
Expand Down
6 changes: 6 additions & 0 deletions hphp/runtime/vm/jit/vasm-print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ struct FormatVisitor {
void imm(TCA addr) {
str << sep() << getNativeFunctionName(addr);
}
void imm(TCA* addr) {
str << sep() << folly::format("{}", addr);
}
void imm(Vpoint p) { str << sep() << '@' << (size_t)p; }
void imm(const CppCall& cppcall) {
switch (cppcall.kind()) {
Expand Down Expand Up @@ -102,6 +105,9 @@ struct FormatVisitor {
void imm(DestType dt) {
str << sep() << destTypeName(dt);
}
void imm(RIPRelativeRef r) {
str << sep() << folly::format("ip[{:#x}]", r.r.disp);
}

template<class R> void across(R r) { print(r); }
template<class R> void use(R r) { print(r); }
Expand Down
28 changes: 12 additions & 16 deletions hphp/runtime/vm/jit/vasm-x64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,23 +107,18 @@ bool Vunit::needsRegAlloc() const {
return false;
}

Vout& Vout::operator<<(Vinstr inst) {
Vout& Vout::operator<<(const Vinstr& inst) {
assert(!closed());
inst.origin = m_origin;
m_unit.blocks[m_block].code.push_back(inst);
auto& code = m_unit.blocks[m_block].code;
code.emplace_back(inst);
code.back().origin = m_origin;
return *this;
}

Vout Vout::makeBlock() {
return {m_meta, m_unit, m_unit.makeBlock(area()), m_origin};
}

Vout Vout::makeEntry() {
auto label = m_unit.makeBlock(area());
m_unit.roots.push_back(label); // save entry label
return {m_meta, m_unit, label, m_origin};
}

// implicit cast to label for initializing branch instructions
Vout::operator Vlabel() const {
assert(empty());
Expand Down Expand Up @@ -472,12 +467,14 @@ void Vgen::emit(copy2& i) {

void Vgen::emit(bindaddr& i) {
mcg->setJmpTransID((TCA)i.dest);
*i.dest = emitEphemeralServiceReq(a->code(),
mcg->getFreeStub(a->code(), &mcg->cgFixups()),
REQ_BIND_ADDR,
i.dest,
i.sk.toAtomicInt(),
TransFlags{}.packed);
*i.dest = emitEphemeralServiceReq(
frozen(),
mcg->getFreeStub(frozen(), &mcg->cgFixups()),
REQ_BIND_ADDR,
i.dest,
i.sk.toAtomicInt(),
TransFlags{}.packed
);
mcg->cgFixups().m_codePointers.insert(i.dest);
}

Expand Down Expand Up @@ -841,7 +838,6 @@ void Vgen::emit(loadq& i) {
Vout& Vasm::add(CodeBlock& cb, AreaIndex area) {
assert(size_t(area) == m_areas.size());
auto b = m_unit.makeBlock(area);
if (size_t(b) == 0) m_unit.roots.push_back(b);
Vout v{m_meta, m_unit, b};
m_areas.push_back(Area{v, cb, cb.frontier()});
return m_areas.back().out;
Expand Down
22 changes: 14 additions & 8 deletions hphp/runtime/vm/jit/vasm-x64.h
Original file line number Diff line number Diff line change
Expand Up @@ -820,8 +820,8 @@ struct Vunit {
bool needsRegAlloc() const;

unsigned next_vr{Vreg::V0};
Vlabel entry;
jit::vector<Vblock> blocks;
jit::vector<Vlabel> roots; // entry points
jit::hash_map<uint64_t,Vreg> cpool;
jit::vector<VregList> tuples;
jit::vector<VcallArgs> vcallArgs;
Expand All @@ -846,10 +846,9 @@ struct Vout {
bool closed() const;

Vout makeBlock(); // create a stream connected to a new empty block
Vout makeEntry(); // makeBlock() and add it to unit.roots

// instruction emitter
Vout& operator<<(Vinstr inst);
Vout& operator<<(const Vinstr& inst);

Vpoint makePoint() { return m_meta->makePoint(); }
Vmeta& meta() { return *m_meta; }
Expand Down Expand Up @@ -922,12 +921,19 @@ struct Vasm {
jit::vector<Area> m_areas; // indexed by AreaIndex
};

/*
* Vauto is a convenience helper for emitting small amounts of machine code
* using vasm. It always has a main code block; cold and frozen blocks may be
* added using the normal Vasm API after creation. When the Vauto goes out of
* scope, it will finalize and emit any code it contains.
*/
struct Vauto : Vasm {
explicit Vauto(Vmeta* meta = nullptr)
: Vasm(meta)
{}
explicit Vauto(CodeBlock& code)
: Vasm(nullptr)
{
unit().entry = Vlabel(main(code));
}
~Vauto();
RegSet params;
};

template<class F> void visit(const Vunit&, Vreg v, F f) {
Expand Down Expand Up @@ -1050,7 +1056,7 @@ struct PostorderWalker {
fn(b);
}
template<class Fn> void dfs(Fn fn) {
for (auto b : unit.roots) dfs(b, fn);
dfs(unit.entry, fn);
}
explicit PostorderWalker(const Vunit& u)
: unit(u)
Expand Down
4 changes: 1 addition & 3 deletions hphp/runtime/vm/jit/vasm-xls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1694,9 +1694,7 @@ void Vxls::print(const char* caption) {

jit::vector<Vlabel> sortBlocks(const Vunit& unit) {
BlockSorter s(unit);
for (auto it = unit.roots.end(); it != unit.roots.begin();) {
s.dfs(*--it);
}
s.dfs(unit.entry);
std::reverse(s.blocks.begin(), s.blocks.end());
// put the blocks containing "end" last; expect at most one per area.
std::stable_partition(s.blocks.begin(), s.blocks.end(), [&] (Vlabel b) {
Expand Down

0 comments on commit 007f175

Please sign in to comment.