Skip to content

Commit

Permalink
Kill runtime options related to turning off the IR
Browse files Browse the repository at this point in the history
  • Loading branch information
swtaarrs authored and sgolemon committed May 20, 2013
1 parent e1fb60c commit f323a90
Show file tree
Hide file tree
Showing 9 changed files with 15 additions and 189 deletions.
5 changes: 1 addition & 4 deletions hphp/runtime/base/runtime_option.h
Expand Up @@ -413,9 +413,7 @@ class RuntimeOption {
F(bool, ThreadingJit, false) \
F(bool, JitTransCounters, false) \
F(bool, JitMGeneric, true) \
F(bool, JitUseIR, true) \
F(double, JitCompareHHIR, 0) \
F(bool, IRPuntDontInterp, false) \
F(bool, HHIRGenericDtorHelper, true) \
F(bool, HHIRCse, true) \
F(bool, HHIRSimplification, true) \
Expand All @@ -435,8 +433,7 @@ class RuntimeOption {
F(bool, HHIRAllocXMMRegs, true) \
F(bool, HHIRGenerateAsserts, debug) \
F(bool, HHIRDirectExit, true) \
F(bool, HHIRDisableTx64, true) \
F(uint64_t, MaxHHIRTrans, -1) \
F(uint64_t, MaxTrans, -1) \
F(bool, HHIRDeadCodeElim, true) \
/* DumpBytecode =1 dumps user php, =2 dumps systemlib & user php */ \
F(int32_t, DumpBytecode, 0) \
Expand Down
7 changes: 2 additions & 5 deletions hphp/runtime/vm/translator/abi-x64.h
Expand Up @@ -245,11 +245,8 @@ const int kNumServiceReqArgRegs =
REQ(STACK_OVERFLOW) \
\
/*
* When HHIR is in use, this requests a retranslation that does not use HHIR.
* This is only used when HHIR is turned on.
*
* Note that, when EvalJitUseIR is enabled, RETRANSLATE requests will attempt
* to use HHIR.
* This requests a retranslation that does not use HHIR, meaning it
* will be an INTERPRET service request.
*/ \
REQ(RETRANSLATE_NO_IR) \
\
Expand Down
9 changes: 1 addition & 8 deletions hphp/runtime/vm/translator/hopt/hhbctranslator.cpp
Expand Up @@ -2993,14 +2993,7 @@ void HhbcTranslator::emitInterpOneCF(int numPopped) {

void HhbcTranslator::emitInterpOneOrPunt(Type type, int numPopped,
int numExtraPushed) {
if (RuntimeOption::EvalIRPuntDontInterp) {
Op op = *(Op*)(getCurUnit()->entry() + bcOff());
const char* name = StringData::GetStaticString(
std::string("PuntDontInterp-") + opcodeToName(op))->data();
SPUNT(name);
} else {
emitInterpOne(type, numPopped, numExtraPushed);
}
emitInterpOne(type, numPopped, numExtraPushed);
}

/*
Expand Down
5 changes: 0 additions & 5 deletions hphp/runtime/vm/translator/hopt/ir.h
Expand Up @@ -76,11 +76,6 @@ class FailedIRGen : public std::exception {
throw FailedIRGen(__FILE__, __LINE__, instr); \
} while(0)
#define PUNT(instr) SPUNT(#instr)
#define PUNT_WITH_TX64(instr) do { \
if (!RuntimeOption::EvalHHIRDisableTx64) { \
PUNT(inst); \
} \
} while (false)

//////////////////////////////////////////////////////////////////////

Expand Down
7 changes: 3 additions & 4 deletions hphp/runtime/vm/translator/hopt/irtranslator.cpp
Expand Up @@ -1798,14 +1798,13 @@ TranslatorX64::irTranslateTracelet(Tracelet& t,
} catch (JIT::FailedIRGen& fcg) {
// If we haven't tried interpreting ni yet, flag it to be interpreted
// and retry
if (RuntimeOption::EvalHHIRDisableTx64 && !ni->interp &&
supportedInterpOne(ni)) {
if (!ni->interp && supportedInterpOne(ni)) {
ni->interp = true;
transResult = Retry;
break;
}
if (!RuntimeOption::EvalHHIRDisableTx64 || !ni->prev) {
// Let tx64 handle the entire tracelet.
if (!ni->prev) {
// Let the interpreter handle the entire tracelet.
throw;
}
// We've made forward progress. Proceed with the partial tracelet,
Expand Down
158 changes: 7 additions & 151 deletions hphp/runtime/vm/translator/translator-x64.cpp
Expand Up @@ -1444,15 +1444,16 @@ TranslatorX64::lookupTranslation(SrcKey sk) const {

TCA
TranslatorX64::translate(SrcKey sk, bool align, bool allowIR) {
bool useHHIR = allowIR && RuntimeOption::EvalJitUseIR;
bool useHHIR = allowIR;
INC_TPC(translate);
assert(((uintptr_t)vmsp() & (sizeof(Cell) - 1)) == 0);
assert(((uintptr_t)vmfp() & (sizeof(Cell) - 1)) == 0);

if (useHHIR) {
if (m_numHHIRTrans == RuntimeOption::EvalMaxHHIRTrans) {
if (m_numHHIRTrans == RuntimeOption::EvalMaxTrans) {
useHHIR = m_useHHIR = false;
RuntimeOption::EvalJitUseIR = false;
RuntimeOption::EvalJit = false;
ThreadInfo::s_threadInfo->m_reqInjectionData.updateJit();
} else {
m_useHHIR = true;
}
Expand All @@ -1468,7 +1469,7 @@ TranslatorX64::translate(SrcKey sk, bool align, bool allowIR) {

TCA start = a.code.frontier;
m_lastHHIRPunt.clear();
translateTracelet(sk, m_useHHIR || RuntimeOption::EvalHHIRDisableTx64);
translateTracelet(sk, true);

SKTRACE(1, sk, "translate moved head from %p to %p\n",
getTopTranslation(sk), start);
Expand Down Expand Up @@ -10878,10 +10879,6 @@ TranslatorX64::emitPredictionGuards(const NormalizedInstruction& i) {
Stats::emitInc(a, Stats::TC_TypePredHit);
}

static void failedTypePred() {
raise_error("A type prediction was incorrect");
}

void
TranslatorX64::translateInstrWork(const Tracelet& t,
const NormalizedInstruction& i) {
Expand All @@ -10904,146 +10901,7 @@ TranslatorX64::translateInstrWork(const Tracelet& t,
void
TranslatorX64::translateInstr(const Tracelet& t,
const NormalizedInstruction& i) {
/**
* translateInstr() translates an individual instruction in a tracelet,
* either by directly emitting machine code for that instruction or by
* emitting a call to the interpreter.
*
* If the instruction ends the current tracelet, we must emit machine code
* to transfer control to some target that will continue to make forward
* progress. This target may be the beginning of another tracelet, or it may
* be a translator service request. Before transferring control, a tracelet
* must ensure the following invariants hold:
* 1) The machine registers rVmFp and rVmSp are in sync with vmfp()
* and vmsp().
* 2) All "dirty" values are synced in memory. This includes the
* evaluation stack, locals, globals, statics, and any other program
* accessible locations. This also means that all refcounts must be
* up to date.
*/
assert(!m_useHHIR);
assert(!(RuntimeOption::EvalJitUseIR && RuntimeOption::EvalHHIRDisableTx64));
assert(!i.outStack || i.outStack->isStack());
assert(!i.outLocal || i.outLocal->isLocal());
const char *opNames[] = {
#define O(name, imm, push, pop, flags) \
#name,
OPCODES
#undef O
};
SpaceRecorder sr(opNames[i.op()], a);
SKTRACE(1, i.source, "translate %#lx\n", long(a.code.frontier));
const Opcode op = i.op();

TCA start = a.code.frontier;
TCA astart = astubs.code.frontier;

m_regMap.bumpEpoch();
// Allocate the input regs upfront unless instructed otherwise
// or the instruction is interpreted
if (!i.manuallyAllocInputs && i.m_txFlags) {
m_regMap.allocInputRegs(i);
}

if (debug) {
for (unsigned j = 0; j < i.inputs.size(); j++) {
if (i.inputWasInferred(j)) {
DynLocation* dl = i.inputs[j];
assert(dl->rtt.isValue() &&
!dl->rtt.isVagueValue() &&
dl->outerType() != KindOfInvalid);
PhysReg base;
int disp;
locToRegDisp(dl->location, &base, &disp);
DataType type = dl->rtt.typeCheckValue();
emitTypeCheck(a, type, base, disp);
ConditionCode cc = IS_STRING_TYPE(type) ? CC_Z : CC_NZ;
{
UnlikelyIfBlock typePredFailed(cc, a, astubs);
EMIT_CALL(astubs, failedTypePred);
recordReentrantStubCall(i);
}
}
}
}

if (!i.grouped) {
emitVariantGuards(t, i);
const NormalizedInstruction* n = &i;
while (n->next && n->next->grouped) {
n = n->next;
emitVariantGuards(t, *n);
}
}

// Allocate the input regs upfront unless instructed otherwise
// or the instruction is interpreted
if (!i.manuallyAllocInputs && i.m_txFlags) {
m_regMap.allocInputRegs(i);
}

if (i.m_txFlags == Interp || RuntimeOption::EvalThreadingJit) {
// If the problem is local to this instruction, just call out to
// the interpreter. emitInterpOne will perform end-of-tracelet duties
// if this instruction ends the tracelet.
SKTRACE(1, i.source, "Interp\n");
emitInterpOne(t, i);
} else {
// Actually translate the instruction's body.
Stats::emitIncTranslOp(a, op, RuntimeOption::EnableInstructionCounts);
translateInstrWork(t, i);
}

// Invalidate locations that are no longer live
for (unsigned k = 0; k < i.deadLocs.size(); ++k) {
const Location& l = i.deadLocs[k];
m_regMap.invalidate(l);
}

// Kill any live regs that won't be of further use in this trace.
RegSet live = m_regMap.getRegsLike(RegInfo::DIRTY) |
m_regMap.getRegsLike(RegInfo::CLEAN);
PhysReg pr;
while (live.findFirst(pr)) {
live.remove(pr);
const RegInfo* ri = m_regMap.getInfo(pr);
assert(ri->m_state == RegInfo::CLEAN || ri->m_state == RegInfo::DIRTY);
bool dirty = ri->m_state == RegInfo::DIRTY;
if (ri->m_cont.m_kind != RegContent::Loc) continue;
const Location loc = ri->m_cont.m_loc;
// These heuristics do poorly on stack slots, which are more like
// ephemeral temps.
if (loc.space != Location::Local) continue;
if (false && dirty && !t.isWrittenAfterInstr(loc, i)) {
// This seems plausible enough: the intuition is that carrying aroud
// a register we'll read, but not write, in a dirty state, has a cost
// because any control-flow diamonds will have to spill it and then
// refill it. It appears to hurt performance today, though.
m_regMap.cleanLoc(loc);
}
if (t.isLiveAfterInstr(loc, i)) continue;
SKTRACE(1, i.source, "killing %s reg %d for (%s, %d)\n",
dirty ? "dirty" : "clean", (int)pr, loc.spaceName(), loc.offset);
if (dirty) {
m_regMap.cleanLoc(loc);
}
assert(ri->m_state == RegInfo::CLEAN);
m_regMap.smashLoc(loc);
}

emitPredictionGuards(i);
recordBCInstr(op, a, start);
recordBCInstr(op + Op_count, astubs, astart);

if (i.breaksTracelet && !i.changesPC) {
// If this instruction's opcode always ends the tracelet then the
// instruction case is responsible for performing end-of-tracelet
// duties. Otherwise, we handle ending the tracelet here.
syncOutputs(t);
emitBindJmp(t.m_nextSk);
}

m_regMap.assertNoScratch();
not_reached();
}

bool
Expand Down Expand Up @@ -11218,9 +11076,7 @@ TranslatorX64::translateTracelet(SrcKey sk, bool considerHHIR/*=true*/,
// with more aggressive assumptions, or fall back to the
// interpreter.
if (considerHHIR) {
if (RuntimeOption::EvalHHIRDisableTx64) {
punt();
}
punt();
// Recur. We need to re-analyze. Since m_useHHIR is clear, we
// won't go down this path again.
return translateTracelet(sk, false);
Expand Down
4 changes: 1 addition & 3 deletions hphp/test/run
Expand Up @@ -215,9 +215,7 @@ function mode_arg($options) {
switch ($mode) {
case '':
case 'jit':
return "$jit_args -vEval.JitUseIR=0 -vEval.HHIRDisableTx64=0";
case 'hhir':
return "$jit_args -vEval.JitUseIR=1 -vEval.HHIRDisableTx64=1";
return "$jit_args";
case 'interp':
return "$repo_args -vEval.Jit=0";
default:
Expand Down
5 changes: 0 additions & 5 deletions hphp/test/test_code_run.cpp
Expand Up @@ -156,17 +156,12 @@ static bool verify_result(const char *input, const char *output, bool perfMode,

string jitarg = string("-vEval.Jit=") +
(RuntimeOption::EvalJit ? "true" : "false");
string jit_use_ir = string("-vEval.JitUseIR=") +
(RuntimeOption::EvalJitUseIR ? "true" : "false");
string jit_rename = string("-vEval.JitEnableRenameFunction=") +
(RuntimeOption::EvalJit ? "true" : "false");
const char *argv[] = {"", filearg.c_str(),
"--config=test/slow/config.hdf",
repoarg.c_str(),
jitarg.c_str(),
jit_use_ir.c_str(),
// Next arg only takes effect if JitUseIR=true also
"-vEval.HHIRDisableTx64=true",
jit_rename.c_str(),
nullptr};
Process::Exec(HHVM_PATH, argv, nullptr, actual, &err);
Expand Down
4 changes: 0 additions & 4 deletions hphp/test/test_debugger.cpp
Expand Up @@ -376,9 +376,6 @@ void TestDebugger::runServer() {
boost::lexical_cast<string>(m_debugPort);
string jitConfig = "-vEval.Jit=" +
boost::lexical_cast<string>(RuntimeOption::EvalJit);
string jitUseIRConfig = "-vEval.JitUseIR=" +
boost::lexical_cast<string>(
RuntimeOption::EvalJitUseIR);

// To emulate sandbox setup, let home to be "hphp/test", and user name to be
// "debugger_tests", so that it can find the sandbox_conf there
Expand All @@ -395,7 +392,6 @@ void TestDebugger::runServer() {
adminPortConfig.c_str(),
debugPortConfig.c_str(),
jitConfig.c_str(),
jitUseIRConfig.c_str(),
nullptr};
printf("Running server with arguments:\n");
for (unsigned i = 1; i < array_size(argv) - 1; ++i) {
Expand Down

0 comments on commit f323a90

Please sign in to comment.