Add TranslArgs and delete a bunch of tx64 code
I want to add a new argument to translateTracelet. Rather than plumbing it through the many functions in the translation stack, let's use an options struct. Dealing with the many bools we had flying around controlling hhir was complicating things, so I removed m_useHHIR and collapsed them all into an "interp" bool in TranslArgs. I removed any code that was clearly unreachable from these changes.
Esse commit está contido em:
@@ -117,7 +117,6 @@ TranslatorX64::irCheckType(X64Assembler& a,
|
||||
const Location& l,
|
||||
const RuntimeType& rtt,
|
||||
SrcRec& fail) {
|
||||
assert(m_useHHIR);
|
||||
// We can get invalid inputs as a side effect of reading invalid
|
||||
// items out of BBs we truncate; they don't need guards.
|
||||
if (rtt.isVagueValue()) return;
|
||||
@@ -1573,8 +1572,6 @@ static bool isPop(Opcode opc) {
|
||||
|
||||
void
|
||||
TranslatorX64::irPassPredictedAndInferredTypes(const NormalizedInstruction& i) {
|
||||
assert(m_useHHIR);
|
||||
|
||||
if (!i.outStack || i.breaksTracelet) return;
|
||||
|
||||
NormalizedInstruction::OutputUse u = i.getOutputUsage(i.outStack);
|
||||
@@ -1648,7 +1645,6 @@ void TranslatorX64::irInterpretInstr(const NormalizedInstruction& i) {
|
||||
|
||||
void TranslatorX64::irTranslateInstr(const Tracelet& t,
|
||||
const NormalizedInstruction& i) {
|
||||
assert(m_useHHIR);
|
||||
assert(!i.outStack || i.outStack->isStack());
|
||||
assert(!i.outLocal || i.outLocal->isLocal());
|
||||
FTRACE(1, "translating: {}\n", opcodeToName(i.op()));
|
||||
@@ -1692,7 +1688,6 @@ void TranslatorX64::irTranslateInstr(const Tracelet& t,
|
||||
|
||||
void TranslatorX64::irAssertType(const Location& l,
|
||||
const RuntimeType& rtt) {
|
||||
assert(m_useHHIR);
|
||||
if (rtt.isVagueValue()) return;
|
||||
|
||||
switch (l.space) {
|
||||
@@ -1755,8 +1750,6 @@ TranslatorX64::irTranslateTracelet(Tracelet& t,
|
||||
const TCA stubStart,
|
||||
vector<TransBCMapping>* bcMap) {
|
||||
auto transResult = Failure;
|
||||
assert(m_useHHIR);
|
||||
|
||||
const SrcKey &sk = t.m_sk;
|
||||
SrcRec& srcRec = *getSrcRec(sk);
|
||||
assert(srcRec.inProgressTailJumps().size() == 0);
|
||||
@@ -1895,7 +1888,6 @@ TranslatorX64::irTranslateTracelet(Tracelet& t,
|
||||
assert(0);
|
||||
}
|
||||
|
||||
m_useHHIR = transResult != Failure;
|
||||
if (transResult != Success) {
|
||||
// The whole translation failed; give up on this BB. Since it is not
|
||||
// linked into srcDB yet, it is guaranteed not to be reachable.
|
||||
@@ -1914,7 +1906,6 @@ TranslatorX64::irTranslateTracelet(Tracelet& t,
|
||||
void TranslatorX64::hhirTraceStart(Offset bcStartOffset,
|
||||
Offset nextTraceletOffset) {
|
||||
assert(!m_irFactory);
|
||||
assert(m_useHHIR);
|
||||
|
||||
Cell* fp = vmfp();
|
||||
if (curFunc()->isGenerator()) {
|
||||
@@ -1925,14 +1916,12 @@ void TranslatorX64::hhirTraceStart(Offset bcStartOffset,
|
||||
" HHIR during translation ",
|
||||
color(ANSI_COLOR_END));
|
||||
|
||||
m_useHHIR = true;
|
||||
m_irFactory.reset(new JIT::IRFactory());
|
||||
m_hhbcTrans.reset(new JIT::HhbcTranslator(
|
||||
*m_irFactory, bcStartOffset, nextTraceletOffset, fp - vmsp(), curFunc()));
|
||||
}
|
||||
|
||||
void TranslatorX64::hhirTraceEnd() {
|
||||
assert(m_useHHIR);
|
||||
m_hhbcTrans->end();
|
||||
FTRACE(1, "{}{:-^40}{}\n",
|
||||
color(ANSI_COLOR_BLACK, ANSI_BGCOLOR_GREEN),
|
||||
@@ -1942,7 +1931,6 @@ void TranslatorX64::hhirTraceEnd() {
|
||||
|
||||
void TranslatorX64::hhirTraceCodeGen(vector<TransBCMapping>* bcMap) {
|
||||
using namespace JIT;
|
||||
assert(m_useHHIR);
|
||||
|
||||
HPHP::JIT::Trace* trace = m_hhbcTrans->getTrace();
|
||||
auto finishPass = [&](const char* msg, int level,
|
||||
|
||||
@@ -1249,17 +1249,17 @@ asm_label(a, release);
|
||||
}
|
||||
|
||||
|
||||
TCA TranslatorX64::retranslate(SrcKey sk, bool align, bool allowIR) {
|
||||
if (isDebuggerAttachedProcess() && isSrcKeyInBL(curUnit(), sk)) {
|
||||
TCA TranslatorX64::retranslate(const TranslArgs& args) {
|
||||
if (isDebuggerAttachedProcess() && isSrcKeyInBL(curUnit(), args.m_sk)) {
|
||||
// We are about to translate something known to be blacklisted by
|
||||
// debugger, exit early
|
||||
SKTRACE(1, sk, "retranslate abort due to debugger\n");
|
||||
SKTRACE(1, args.m_sk, "retranslate abort due to debugger\n");
|
||||
return nullptr;
|
||||
}
|
||||
LeaseHolder writer(s_writeLease);
|
||||
if (!writer) return nullptr;
|
||||
SKTRACE(1, sk, "retranslate\n");
|
||||
return translate(sk, align, allowIR);
|
||||
SKTRACE(1, args.m_sk, "retranslate\n");
|
||||
return translate(args);
|
||||
}
|
||||
|
||||
// Only use comes from HHIR's cgExitTrace() case TraceExitType::SlowNoProgress
|
||||
@@ -1282,7 +1282,7 @@ TCA TranslatorX64::retranslateAndPatchNoIR(SrcKey sk,
|
||||
// interpretation of this BB.
|
||||
return nullptr;
|
||||
}
|
||||
TCA start = translate(sk, align, false);
|
||||
TCA start = translate(TranslArgs(sk, align).interp(true));
|
||||
if (start != nullptr) {
|
||||
smashJmp(getAsmFor(toSmash), toSmash, start);
|
||||
}
|
||||
@@ -1347,10 +1347,11 @@ reqName(int req) {
|
||||
* a translation.
|
||||
*/
|
||||
TCA
|
||||
TranslatorX64::getTranslation(SrcKey sk, bool align,
|
||||
bool forceNoHHIR /* = false */) {
|
||||
TranslatorX64::getTranslation(const TranslArgs& args) {
|
||||
auto sk = args.m_sk;
|
||||
curFunc()->validate();
|
||||
SKTRACE(2, sk, "getTranslation: curUnit %s funcId %" PRIx64 " offset %d\n",
|
||||
SKTRACE(2, sk,
|
||||
"getTranslation: curUnit %s funcId %" PRIx64 " offset %d\n",
|
||||
curUnit()->filepath()->data(),
|
||||
sk.getFuncId(),
|
||||
sk.offset());
|
||||
@@ -1368,7 +1369,7 @@ TranslatorX64::getTranslation(SrcKey sk, bool align,
|
||||
return tca;
|
||||
}
|
||||
}
|
||||
return createTranslation(sk, align, forceNoHHIR);
|
||||
return createTranslation(args);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -1380,8 +1381,7 @@ TranslatorX64::numTranslations(SrcKey sk) const {
|
||||
}
|
||||
|
||||
TCA
|
||||
TranslatorX64::createTranslation(SrcKey sk, bool align,
|
||||
bool forceNoHHIR /* = false */) {
|
||||
TranslatorX64::createTranslation(const TranslArgs& args) {
|
||||
/*
|
||||
* Try to become the writer. We delay this until we *know* we will have
|
||||
* a need to create new translations, instead of just trying to win the
|
||||
@@ -1389,8 +1389,9 @@ TranslatorX64::createTranslation(SrcKey sk, bool align,
|
||||
* any new translation.
|
||||
*/
|
||||
auto retransl = [&] {
|
||||
return retranslate(sk, align, !forceNoHHIR);
|
||||
return retranslate(args);
|
||||
};
|
||||
auto sk = args.m_sk;
|
||||
LeaseHolder writer(s_writeLease);
|
||||
if (!writer) return nullptr;
|
||||
if (SrcRec* sr = m_srcDB.find(sk)) {
|
||||
@@ -1443,36 +1444,30 @@ TranslatorX64::lookupTranslation(SrcKey sk) const {
|
||||
}
|
||||
|
||||
TCA
|
||||
TranslatorX64::translate(SrcKey sk, bool align, bool allowIR) {
|
||||
bool useHHIR = allowIR;
|
||||
TranslatorX64::translate(const TranslArgs& args) {
|
||||
INC_TPC(translate);
|
||||
assert(((uintptr_t)vmsp() & (sizeof(Cell) - 1)) == 0);
|
||||
assert(((uintptr_t)vmfp() & (sizeof(Cell) - 1)) == 0);
|
||||
|
||||
if (useHHIR) {
|
||||
if (!args.m_interp) {
|
||||
if (m_numHHIRTrans == RuntimeOption::EvalMaxTrans) {
|
||||
useHHIR = m_useHHIR = false;
|
||||
RuntimeOption::EvalJit = false;
|
||||
ThreadInfo::s_threadInfo->m_reqInjectionData.updateJit();
|
||||
} else {
|
||||
m_useHHIR = true;
|
||||
}
|
||||
} else {
|
||||
assert(m_useHHIR == false);
|
||||
}
|
||||
|
||||
AHotSelector ahs(this, curFunc()->attrs() & AttrHot);
|
||||
|
||||
if (align) {
|
||||
if (args.m_align) {
|
||||
moveToAlign(a, kNonFallthroughAlign);
|
||||
}
|
||||
|
||||
TCA start = a.code.frontier;
|
||||
m_lastHHIRPunt.clear();
|
||||
translateTracelet(sk, true);
|
||||
translateTracelet(args);
|
||||
|
||||
SKTRACE(1, sk, "translate moved head from %p to %p\n",
|
||||
getTopTranslation(sk), start);
|
||||
SKTRACE(1, args.m_sk, "translate moved head from %p to %p\n",
|
||||
getTopTranslation(args.m_sk), start);
|
||||
return start;
|
||||
}
|
||||
|
||||
@@ -1756,7 +1751,7 @@ TranslatorX64::getCallArrayProlog(Func* func) {
|
||||
}
|
||||
} else {
|
||||
SrcKey sk(func, func->base());
|
||||
tca = tx64->getTranslation(sk, false);
|
||||
tca = tx64->getTranslation(TranslArgs(sk, false));
|
||||
}
|
||||
|
||||
return tca;
|
||||
@@ -2000,7 +1995,7 @@ TranslatorX64::funcPrologue(Func* func, int nPassed, ActRec* ar) {
|
||||
}
|
||||
interp_set_regs(ar, (Cell*)ar - func->numSlotsInFrame(), entry);
|
||||
SrcKey funcBody(func, entry);
|
||||
TCA tca = getTranslation(funcBody, false);
|
||||
TCA tca = getTranslation(TranslArgs(funcBody, false));
|
||||
tl_regState = REGSTATE_DIRTY;
|
||||
if (tca) {
|
||||
// racy, but ok...
|
||||
@@ -2416,7 +2411,9 @@ TranslatorX64::emitCondJmp(SrcKey skTaken, SrcKey skNotTaken,
|
||||
TCA
|
||||
TranslatorX64::bindJmp(TCA toSmash, SrcKey destSk,
|
||||
ServiceRequest req, bool& smashed) {
|
||||
TCA tDest = getTranslation(destSk, false, req == REQ_BIND_JMP_NO_IR);
|
||||
TCA tDest = getTranslation(
|
||||
TranslArgs(destSk, false).interp(req == REQ_BIND_JMP_NO_IR)
|
||||
.src(toSmash));
|
||||
if (!tDest) return nullptr;
|
||||
LeaseHolder writer(s_writeLease);
|
||||
if (!writer) return tDest;
|
||||
@@ -2488,7 +2485,7 @@ TranslatorX64::bindJmpccFirst(TCA toSmash,
|
||||
!m_srcDB.find(dest);
|
||||
|
||||
TCA tDest;
|
||||
tDest = getTranslation(dest, !fallThru /* align */);
|
||||
tDest = getTranslation(TranslArgs(dest, !fallThru).src(toSmash));
|
||||
if (!tDest) {
|
||||
return 0;
|
||||
}
|
||||
@@ -2520,7 +2517,7 @@ TranslatorX64::bindJmpccSecond(TCA toSmash, const Offset off,
|
||||
ConditionCode cc, bool& smashed) {
|
||||
const Func* f = curFunc();
|
||||
SrcKey dest(f, off);
|
||||
TCA branch = getTranslation(dest, true);
|
||||
TCA branch = getTranslation(TranslArgs(dest, true).src(toSmash));
|
||||
LeaseHolder writer(s_writeLease, NO_ACQUIRE);
|
||||
if (branch && writer.acquire()) {
|
||||
smashed = true;
|
||||
@@ -2653,27 +2650,7 @@ TranslatorX64::checkType(X64Assembler& a,
|
||||
// items out of BBs we truncate; they don't need guards.
|
||||
if (rtt.isVagueValue() || l.isThis()) return;
|
||||
|
||||
if (m_useHHIR) {
|
||||
irCheckType(a, l, rtt, fail);
|
||||
return;
|
||||
}
|
||||
|
||||
PhysReg base;
|
||||
int disp = 0;
|
||||
SpaceRecorder sr("_CheckType", a);
|
||||
|
||||
TRACE(1, Trace::prettyNode("Precond", DynLocation(l, rtt)) + "\n");
|
||||
|
||||
locToRegDisp(l, &base, &disp);
|
||||
TRACE(2, "TypeCheck: %d(%%r%d)\n", int(disp), int(base));
|
||||
// Negative offsets from RSP are not yet allocated; they had
|
||||
// better not be inputs to the tracelet.
|
||||
assert(l.space != Location::Stack || disp >= 0);
|
||||
if (Trace::moduleEnabled(Trace::stats, 2)) {
|
||||
Stats::emitInc(a, Stats::TraceletGuard_branch);
|
||||
}
|
||||
assert(!rtt.isIter());
|
||||
emitTypeCheck(a, rtt.typeCheckValue(), base, disp, &fail);
|
||||
irCheckType(a, l, rtt, fail);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2770,80 +2747,9 @@ TranslatorX64::checkRefs(X64Assembler& a,
|
||||
// with too many arguments to have passed their checks.
|
||||
int entryArDelta = it->first;
|
||||
|
||||
if (m_useHHIR) {
|
||||
m_hhbcTrans->guardRefs(entryArDelta,
|
||||
it->second.m_mask,
|
||||
it->second.m_vals);
|
||||
continue;
|
||||
}
|
||||
|
||||
int32_t funcOff = cellsToBytes(entryArDelta) + AROFF(m_func);
|
||||
a. load_reg64_disp_reg64(rVmSp, funcOff, r(rFunc)); // rFunc <- Func*
|
||||
a. load_reg64_disp_reg32(r(rFunc), Func::numParamsOff(),
|
||||
r(rNumParams));
|
||||
a. load_reg64_disp_reg64(r(rFunc), Func::refBitVecOff(),
|
||||
r(rBits)); // rBits <- m_refBitVec
|
||||
|
||||
for (unsigned i = 0; i < it->second.m_mask.size(); i += 64) {
|
||||
assert(i < it->second.m_vals.size());
|
||||
uint64_t mask = packBitVec(it->second.m_mask, i);
|
||||
if (mask == 0) {
|
||||
continue;
|
||||
}
|
||||
uint64_t value = packBitVec(it->second.m_vals, i);
|
||||
|
||||
emitImmReg(a, mask, r(rMask));
|
||||
emitImmReg(a, value, r(rExpectedBits));
|
||||
|
||||
/*
|
||||
* Before trying to load this block off the bit vector, make
|
||||
* sure it actually exists. It's ok to index past numArgs
|
||||
* within one of these words, because the remaining bits will be
|
||||
* set to zero (or one in the case of the variadic by ref
|
||||
* builtins).
|
||||
*/
|
||||
if (Trace::moduleEnabled(Trace::stats, 2)) {
|
||||
Stats::emitInc(a, Stats::TraceletGuard_branch);
|
||||
}
|
||||
a. cmp_imm32_reg32(i + 1, r(rNumParams));
|
||||
{
|
||||
IfElseBlock<CC_L> ifFewEnoughArgs(a);
|
||||
|
||||
// Load the appropriate qword off of the top actRec's func*.
|
||||
SKTRACE(2, sk, "reffiness mask %" PRIx64 " value %" PRIx64 ", ar @%d\n",
|
||||
mask, value, entryArDelta);
|
||||
a. load_reg64_disp_reg64(r(rBits), sizeof(uint64_t) * (i / 64),
|
||||
r(rBitsValue)); // rBitsValue <- rBits[i / 64]
|
||||
a. and_reg64_reg64(r(rMask), r(rBitsValue)); // rBitsValue &= rMask
|
||||
a. cmp_reg64_reg64(r(rBitsValue), r(rExpectedBits));
|
||||
emitFallbackJmp(fail);
|
||||
|
||||
ifFewEnoughArgs.Else();
|
||||
|
||||
static_assert(AttrVariadicByRef == (1 << 15),
|
||||
"AttrVariadicByRef assumed to be 1 << 15 in translator");
|
||||
uint8_t mask = (1u << (15 % CHAR_BIT));
|
||||
int offset = Func::attrsOff() + 15 / CHAR_BIT;
|
||||
a. testb((int8_t)mask, r(rFunc)[offset]);
|
||||
{
|
||||
IfElseBlock<CC_NZ> ifNotWeirdBuiltin(a);
|
||||
|
||||
// Other than these builtins, we need to have all by value
|
||||
// args in this case.
|
||||
prepareForTestAndSmash(a, kTestRegRegLen, kAlignJccImmediate);
|
||||
a. test_reg64_reg64(r(rExpectedBits), r(rExpectedBits));
|
||||
emitFallbackJmp(fail);
|
||||
|
||||
ifNotWeirdBuiltin.Else();
|
||||
|
||||
// If it is one of the weird builtins that has reffiness for
|
||||
// additional args, we have to make sure our expectation is
|
||||
// that these additional args are by ref.
|
||||
a. cmp_imm32_reg64((signed int)(-1ull & mask), r(rExpectedBits));
|
||||
emitFallbackJmp(fail);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_hhbcTrans->guardRefs(entryArDelta,
|
||||
it->second.m_mask,
|
||||
it->second.m_vals);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2988,7 +2894,7 @@ TranslatorX64::enterTC(TCA start, void* data) {
|
||||
info.requestNum = -1;
|
||||
info.saved_rStashedAr = 0;
|
||||
sk = *(SrcKey*)data;
|
||||
start = getTranslation(sk, true);
|
||||
start = getTranslation(TranslArgs(sk, true));
|
||||
}
|
||||
for (;;) {
|
||||
assert(sizeof(Cell) == 16);
|
||||
@@ -3006,7 +2912,7 @@ TranslatorX64::enterTC(TCA start, void* data) {
|
||||
PC newPc = g_vmContext->getPC();
|
||||
if (!newPc) { g_vmContext->m_fp = 0; return; }
|
||||
sk = SrcKey(curFunc(), newPc);
|
||||
start = getTranslation(sk, true);
|
||||
start = getTranslation(TranslArgs(sk, true));
|
||||
}
|
||||
assert(start == (TCA)HPHP::Transl::funcBodyHelperThunk ||
|
||||
isValidCodeAddress(start) ||
|
||||
@@ -3163,7 +3069,7 @@ bool TranslatorX64::handleServiceRequest(TReqInfo& info,
|
||||
case REQ_BIND_REQUIRE: {
|
||||
ReqLitStaticArgs* rlsa = (ReqLitStaticArgs*)args[0];
|
||||
sk = SrcKey((Func*)args[1], (Offset)args[2]);
|
||||
start = getTranslation(sk, true);
|
||||
start = getTranslation(TranslArgs(sk, true));
|
||||
if (start) {
|
||||
LeaseHolder writer(s_writeLease);
|
||||
if (writer) {
|
||||
@@ -3184,7 +3090,7 @@ bool TranslatorX64::handleServiceRequest(TReqInfo& info,
|
||||
case REQ_RETRANSLATE: {
|
||||
INC_TPC(retranslate);
|
||||
sk = SrcKey(curFunc(), (Offset)args[0]);
|
||||
start = retranslate(sk, true, true);
|
||||
start = retranslate(TranslArgs(sk, true));
|
||||
SKTRACE(2, sk, "retranslated @%p\n", start);
|
||||
} break;
|
||||
|
||||
@@ -3212,7 +3118,7 @@ bool TranslatorX64::handleServiceRequest(TReqInfo& info,
|
||||
SrcKey newSk(curFunc(), newPc);
|
||||
SKTRACE(5, newSk, "interp: exit\n");
|
||||
sk = newSk;
|
||||
start = getTranslation(newSk, true);
|
||||
start = getTranslation(TranslArgs(newSk, true));
|
||||
} break;
|
||||
|
||||
case REQ_POST_INTERP_RET: {
|
||||
@@ -3226,7 +3132,7 @@ bool TranslatorX64::handleServiceRequest(TReqInfo& info,
|
||||
vmpc() = destUnit->at(caller->m_func->base() + ar->m_soff);
|
||||
SrcKey dest(caller->m_func, vmpc());
|
||||
sk = dest;
|
||||
start = getTranslation(dest, true);
|
||||
start = getTranslation(TranslArgs(dest, true));
|
||||
TRACE(3, "REQ_POST_INTERP_RET: from %s to %s\n",
|
||||
ar->m_func->fullName()->data(),
|
||||
caller->m_func->fullName()->data());
|
||||
@@ -3235,7 +3141,7 @@ bool TranslatorX64::handleServiceRequest(TReqInfo& info,
|
||||
case REQ_RESUME: {
|
||||
SrcKey dest(curFunc(), vmpc());
|
||||
sk = dest;
|
||||
start = getTranslation(dest, true);
|
||||
start = getTranslation(TranslArgs(dest, true));
|
||||
} break;
|
||||
|
||||
case REQ_STACK_OVERFLOW: {
|
||||
@@ -10769,7 +10675,6 @@ TranslatorX64::emitVariantGuards(const Tracelet& t,
|
||||
const NormalizedInstruction& i) {
|
||||
bool pseudoMain = Translator::liveFrameIsPseudoMain();
|
||||
bool isFirstInstr = (&i == t.m_instrStream.first);
|
||||
TCA sideExit = nullptr;
|
||||
const NormalizedInstruction *base = &i;
|
||||
while (base->grouped) {
|
||||
base = base->prev;
|
||||
@@ -10795,27 +10700,14 @@ TranslatorX64::emitVariantGuards(const Tracelet& t,
|
||||
// checked it and have executed no possibly-aliasing instructions in
|
||||
// the meanwhile.
|
||||
if (modifiableLocal) {
|
||||
if (m_useHHIR) {
|
||||
RuntimeType& rtt = input->rtt;
|
||||
JIT::Type type = JIT::Type::fromRuntimeType(rtt);
|
||||
if (isFirstInstr) {
|
||||
m_hhbcTrans->guardTypeLocal(input->location.offset, type);
|
||||
} else {
|
||||
m_hhbcTrans->checkTypeLocal(input->location.offset, type);
|
||||
}
|
||||
RuntimeType& rtt = input->rtt;
|
||||
JIT::Type type = JIT::Type::fromRuntimeType(rtt);
|
||||
if (isFirstInstr) {
|
||||
m_hhbcTrans->guardTypeLocal(input->location.offset, type);
|
||||
} else {
|
||||
PhysReg reg;
|
||||
int disp;
|
||||
locToRegDisp(input->location, ®, &disp);
|
||||
emitOneGuard(t, *base, reg, disp,
|
||||
input->rtt.outerType(), sideExit);
|
||||
m_hhbcTrans->checkTypeLocal(input->location.offset, type);
|
||||
}
|
||||
}
|
||||
if (isRef && !m_useHHIR) {
|
||||
m_regMap.allocInputReg(i, in);
|
||||
emitOneGuard(t, *base, getReg(input->location), RefData::tvOffset(),
|
||||
input->rtt.innerType(), sideExit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11001,8 +10893,8 @@ void dumpTranslationInfo(const Tracelet& t, TCA postGuards) {
|
||||
}
|
||||
|
||||
void
|
||||
TranslatorX64::translateTracelet(SrcKey sk, bool considerHHIR/*=true*/,
|
||||
bool dryRun /*= false */) {
|
||||
TranslatorX64::translateTracelet(const TranslArgs& args) {
|
||||
auto sk = args.m_sk;
|
||||
std::unique_ptr<Tracelet> tp = analyze(sk);
|
||||
Tracelet& t = *tp;
|
||||
m_curTrace = &t;
|
||||
@@ -11018,10 +10910,9 @@ TranslatorX64::translateTracelet(SrcKey sk, bool considerHHIR/*=true*/,
|
||||
uint8_t counterLen = 0;
|
||||
SrcRec& srcRec = *getSrcRec(sk);
|
||||
vector<TransBCMapping> bcMapping;
|
||||
TransKind transKind = TransNormal;
|
||||
TransKind transKind = TransInterp;
|
||||
|
||||
|
||||
if (m_useHHIR) {
|
||||
if (!args.m_interp) {
|
||||
TranslateTraceletResult result;
|
||||
do {
|
||||
hhirTraceStart(sk.offset(), t.m_nextSk.offset());
|
||||
@@ -11032,99 +10923,43 @@ TranslatorX64::translateTracelet(SrcKey sk, bool considerHHIR/*=true*/,
|
||||
assert(astubs.code.frontier == stubStart);
|
||||
}
|
||||
} while (result == Retry);
|
||||
m_useHHIR = false;
|
||||
|
||||
if (result == Success) {
|
||||
m_irAUsage += (a.code.frontier - start);
|
||||
m_irAstubsUsage += (astubs.code.frontier - stubStart);
|
||||
transKind = TransNormalIR;
|
||||
}
|
||||
}
|
||||
if (transKind == TransNormal) { // Regular old tx64.
|
||||
|
||||
if (transKind == TransInterp) {
|
||||
assert(m_pendingFixups.size() == 0);
|
||||
assert(srcRec.inProgressTailJumps().size() == 0);
|
||||
assert(!m_useHHIR);
|
||||
bcMapping.clear();
|
||||
transKind = TransNormal;
|
||||
try {
|
||||
if (t.m_analysisFailed || checkTranslationLimit(t.m_sk, srcRec)) {
|
||||
punt();
|
||||
}
|
||||
// If we failed to IR-translate the tracelet, either reanalyze
|
||||
// with more aggressive assumptions, or fall back to the
|
||||
// interpreter.
|
||||
if (considerHHIR) {
|
||||
punt();
|
||||
// Recur. We need to re-analyze. Since m_useHHIR is clear, we
|
||||
// won't go down this path again.
|
||||
return translateTracelet(sk, false);
|
||||
}
|
||||
|
||||
emitGuardChecks(a, t.m_sk, t.m_dependencies, t.m_refDeps, srcRec);
|
||||
dumpTranslationInfo(t, a.code.frontier);
|
||||
|
||||
// after guards, add a counter for the translation if requested
|
||||
if (RuntimeOption::EvalJitTransCounters) {
|
||||
emitTransCounterInc(a);
|
||||
}
|
||||
|
||||
// emit a counter for the hhir punt that got us here, if any
|
||||
if (Trace::moduleEnabled(Trace::punt, 1) && !m_lastHHIRPunt.empty()) {
|
||||
emitRecordPunt(a, m_lastHHIRPunt);
|
||||
}
|
||||
|
||||
emitRB(a, RBTypeTraceletBody, t.m_sk);
|
||||
Stats::emitInc(a, Stats::Instr_TC, t.m_numOpcodes);
|
||||
recordBCInstr(OpTraceletGuard, a, start);
|
||||
|
||||
// Translate each instruction in the tracelet
|
||||
for (auto ni = t.m_instrStream.first; ni; ni = ni->next) {
|
||||
if (isTransDBEnabled()) {
|
||||
bcMapping.push_back((TransBCMapping){ni->offset(),
|
||||
a.code.frontier,
|
||||
astubs.code.frontier});
|
||||
}
|
||||
|
||||
m_curNI = ni;
|
||||
Nuller<NormalizedInstruction> niNuller(&m_curNI);
|
||||
translateInstr(t, *ni);
|
||||
assert(ni->source.offset() >= curFunc()->base());
|
||||
// We sometimes leave the tail of a truncated tracelet in place to aid
|
||||
// analysis, but breaksTracelet is authoritative.
|
||||
if (ni->breaksTracelet) break;
|
||||
}
|
||||
} catch (TranslationFailedExc& tfe) {
|
||||
// The whole translation failed; give up on this BB. Since it is not
|
||||
// linked into srcDB yet, it is guaranteed not to be reachable.
|
||||
m_regMap.reset();
|
||||
// Permanent reset; nothing is reachable yet.
|
||||
a.code.frontier = start;
|
||||
astubs.code.frontier = stubStart;
|
||||
bcMapping.clear();
|
||||
// Discard any pending fixups.
|
||||
m_pendingFixups.clear();
|
||||
srcRec.clearInProgressTailJumps();
|
||||
TRACE(1,
|
||||
"emitting %d-instr interp request for failed translation @%s:%d\n",
|
||||
int(t.m_numOpcodes), tfe.m_file, tfe.m_line);
|
||||
// Add a counter for the translation if requested
|
||||
if (RuntimeOption::EvalJitTransCounters) {
|
||||
emitTransCounterInc(a);
|
||||
}
|
||||
a. jmp(emitServiceReq(REQ_INTERPRET, 2ull, uint64_t(t.m_sk.offset()),
|
||||
uint64_t(t.m_numOpcodes)));
|
||||
// Fall through.
|
||||
// The whole translation failed; give up on this BB. Since it is not
|
||||
// linked into srcDB yet, it is guaranteed not to be reachable.
|
||||
m_regMap.reset();
|
||||
// Permanent reset; nothing is reachable yet.
|
||||
a.code.frontier = start;
|
||||
astubs.code.frontier = stubStart;
|
||||
bcMapping.clear();
|
||||
// Discard any pending fixups.
|
||||
m_pendingFixups.clear();
|
||||
srcRec.clearInProgressTailJumps();
|
||||
TRACE(1,
|
||||
"emitting %d-instr interp request for failed translation\n",
|
||||
int(t.m_numOpcodes));
|
||||
// Add a counter for the translation if requested
|
||||
if (RuntimeOption::EvalJitTransCounters) {
|
||||
emitTransCounterInc(a);
|
||||
}
|
||||
a. jmp(emitServiceReq(REQ_INTERPRET, 2ull, uint64_t(t.m_sk.offset()),
|
||||
uint64_t(t.m_numOpcodes)));
|
||||
// Fall through.
|
||||
}
|
||||
|
||||
m_regMap.reset();
|
||||
|
||||
if (dryRun) {
|
||||
m_pendingFixups.clear();
|
||||
bcMapping.clear();
|
||||
srcRec.clearInProgressTailJumps();
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint i = 0; i < m_pendingFixups.size(); i++) {
|
||||
TCA tca = m_pendingFixups[i].m_tca;
|
||||
assert(isValidCodeAddress(tca));
|
||||
@@ -11152,63 +10987,6 @@ TranslatorX64::translateTracelet(SrcKey sk, bool considerHHIR/*=true*/,
|
||||
if (Trace::moduleEnabledRelease(Trace::tcspace, 1)) {
|
||||
Trace::traceRelease(getUsage().c_str());
|
||||
}
|
||||
|
||||
|
||||
if (transKind == TransNormalIR && RuntimeOption::EvalJitCompareHHIR) {
|
||||
m_useHHIR = false;
|
||||
Disasm disasm(Disasm::Options().relativeOffset(true));
|
||||
TCA irEnd = a.code.frontier;
|
||||
TCA irStubsEnd = astubs.code.frontier;
|
||||
TCA tx64Start = a.code.frontier;
|
||||
translateTracelet(sk, false, true);
|
||||
TCA tx64End = a.code.frontier;
|
||||
size_t irSize = irEnd - start;
|
||||
size_t tx64Size = tx64End - tx64Start;
|
||||
|
||||
double ratio = (double)irSize / tx64Size;
|
||||
if (ratio > RuntimeOption::EvalJitCompareHHIR) {
|
||||
std::ostringstream irOut, tx64Out, out;
|
||||
out << folly::format("{:-^140}\n",
|
||||
folly::format(" New translation - hhir/tx64 = {}% ",
|
||||
int(100 * ratio)));
|
||||
t.print(out);
|
||||
out << '\n';
|
||||
# define IRCOL "{:<90}"
|
||||
# define TXCOL "{:<50}"
|
||||
out << folly::format(TXCOL " " TXCOL "\n",
|
||||
folly::format("Translation from tx64 ({} bytes)",
|
||||
tx64Size),
|
||||
folly::format("Translation from hhir ({} bytes)",
|
||||
irSize));
|
||||
|
||||
disasm.disasm(irOut, start, irEnd);
|
||||
disasm.disasm(tx64Out, tx64Start, tx64End);
|
||||
std::string irAsm = irOut.str(), tx64Str = tx64Out.str();
|
||||
std::istringstream irAsmIn(irAsm), irPrettyIn(m_lastHHIRDump),
|
||||
tx64In(tx64Str);
|
||||
std::string irAsmLine, irPrettyLine, tx64Line;
|
||||
|
||||
// || without short-circuiting
|
||||
auto or = [](bool a, bool b) { return a || b; };
|
||||
while (or(std::getline(irAsmIn, irAsmLine),
|
||||
or(std::getline(irPrettyIn, irPrettyLine),
|
||||
std::getline(tx64In, tx64Line)))) {
|
||||
out << folly::format(" " TXCOL TXCOL IRCOL "\n",
|
||||
tx64Line, irAsmLine, irPrettyLine);
|
||||
irAsmLine.clear();
|
||||
irPrettyLine.clear();
|
||||
tx64Line.clear();
|
||||
}
|
||||
# undef IRCOL
|
||||
# undef TXCOL
|
||||
out << '\n';
|
||||
|
||||
Trace::traceRelease("%s", out.str().c_str());
|
||||
}
|
||||
|
||||
a.code.frontier = irEnd;
|
||||
astubs.code.frontier = irStubsEnd;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -739,8 +739,6 @@ private:
|
||||
void irTranslateInstrDefault(const Tracelet& t,
|
||||
const NormalizedInstruction& i);
|
||||
bool checkTranslationLimit(SrcKey, const SrcRec&) const;
|
||||
void translateTracelet(SrcKey sk, bool considerHHIR=true,
|
||||
bool dryRun = false);
|
||||
enum TranslateTraceletResult {
|
||||
Failure,
|
||||
Retry,
|
||||
@@ -786,11 +784,13 @@ private:
|
||||
smash(a, src, dest, true);
|
||||
}
|
||||
|
||||
TCA getTranslation(SrcKey sk, bool align, bool forceNoHHIR = false);
|
||||
TCA createTranslation(SrcKey sk, bool align, bool forceNoHHIR = false);
|
||||
TCA getTranslation(const TranslArgs& args);
|
||||
TCA createTranslation(const TranslArgs& args);
|
||||
TCA retranslate(const TranslArgs& args);
|
||||
TCA translate(const TranslArgs& args);
|
||||
void translateTracelet(const TranslArgs& args);
|
||||
|
||||
TCA lookupTranslation(SrcKey sk) const;
|
||||
TCA translate(SrcKey sk, bool align, bool useHHIR);
|
||||
TCA retranslate(SrcKey sk, bool align, bool useHHIR);
|
||||
TCA retranslateOpt(TransID transId, bool align);
|
||||
TCA retranslateAndPatchNoIR(SrcKey sk,
|
||||
bool align,
|
||||
|
||||
@@ -1816,7 +1816,7 @@ bool Translator::applyInputMetaData(Unit::MetaHandle& metaHand,
|
||||
"newType = %d\n", arg, DataType(info.m_data));
|
||||
InputInfo& ii = inputInfos[arg];
|
||||
ii.dontGuard = true;
|
||||
DynLocation* dl = tas.recordRead(ii, m_useHHIR, (DataType)info.m_data);
|
||||
DynLocation* dl = tas.recordRead(ii, true, (DataType)info.m_data);
|
||||
if (dl->rtt.outerType() != info.m_data &&
|
||||
(!dl->isString() || info.m_data != KindOfString)) {
|
||||
if (dl->rtt.outerType() != KindOfInvalid) {
|
||||
@@ -1872,7 +1872,7 @@ bool Translator::applyInputMetaData(Unit::MetaHandle& metaHand,
|
||||
assert((unsigned)arg < inputInfos.size());
|
||||
InputInfo& ii = inputInfos[arg];
|
||||
ii.dontGuard = true;
|
||||
DynLocation* dl = tas.recordRead(ii, m_useHHIR, KindOfString);
|
||||
DynLocation* dl = tas.recordRead(ii, true, KindOfString);
|
||||
assert(!dl->rtt.isString() || !dl->rtt.valueString() ||
|
||||
dl->rtt.valueString() == sd);
|
||||
SKTRACE(1, ni->source, "MetaInfo on input %d; old type = %s\n",
|
||||
@@ -1884,7 +1884,7 @@ bool Translator::applyInputMetaData(Unit::MetaHandle& metaHand,
|
||||
case Unit::MetaInfo::Class: {
|
||||
assert((unsigned)arg < inputInfos.size());
|
||||
InputInfo& ii = inputInfos[arg];
|
||||
DynLocation* dl = tas.recordRead(ii, m_useHHIR);
|
||||
DynLocation* dl = tas.recordRead(ii, true);
|
||||
if (dl->rtt.valueType() != KindOfObject) {
|
||||
continue;
|
||||
}
|
||||
@@ -2955,7 +2955,7 @@ Translator::getOperandConstraintCategory(NormalizedInstruction* instr,
|
||||
assert(opndIdx < 2);
|
||||
if (opndIdx == 0) { // stack value
|
||||
auto stackValUsage = instr->getOutputUsage(instr->outStack, true);
|
||||
if ((instr->outStack && (!m_useHHIR || stackValUsage == kOutputUsed)) ||
|
||||
if ((instr->outStack && stackValUsage == kOutputUsed) ||
|
||||
(instr->getOutputUsage(instr->outLocal) == kOutputUsed)) {
|
||||
return DataTypeSpecific;
|
||||
}
|
||||
@@ -3160,7 +3160,6 @@ extern bool shouldIRInline(const Func* curFunc,
|
||||
void Translator::analyzeCallee(TraceletContext& tas,
|
||||
Tracelet& parent,
|
||||
NormalizedInstruction* fcall) {
|
||||
always_assert(m_useHHIR);
|
||||
if (!shouldAnalyzeCallee(fcall)) return;
|
||||
|
||||
auto const numArgs = fcall->imm[0].u_IVA;
|
||||
@@ -3318,7 +3317,7 @@ void Translator::analyzeCallee(TraceletContext& tas,
|
||||
*/
|
||||
restoreFrame();
|
||||
for (auto& loc : callerArgLocs) {
|
||||
fcall->inputs.push_back(tas.recordRead(InputInfo(loc), m_useHHIR));
|
||||
fcall->inputs.push_back(tas.recordRead(InputInfo(loc), true));
|
||||
}
|
||||
|
||||
FTRACE(1, "analyzeCallee: inline candidate\n");
|
||||
@@ -3427,10 +3426,8 @@ std::unique_ptr<Tracelet> Translator::analyze(SrcKey sk,
|
||||
getInputs(t, ni, stackFrameOffset, inputInfos, tas);
|
||||
bool noOp = applyInputMetaData(metaHand, ni, tas, inputInfos);
|
||||
if (noOp) {
|
||||
if (m_useHHIR) {
|
||||
t.m_instrStream.append(ni);
|
||||
++t.m_numOpcodes;
|
||||
}
|
||||
t.m_instrStream.append(ni);
|
||||
++t.m_numOpcodes;
|
||||
stackFrameOffset = oldStackFrameOffset;
|
||||
continue;
|
||||
}
|
||||
@@ -3453,7 +3450,7 @@ std::unique_ptr<Tracelet> Translator::analyze(SrcKey sk,
|
||||
for (unsigned int i = 0; i < inputInfos.size(); i++) {
|
||||
SKTRACE(2, sk, "typing input %d\n", i);
|
||||
const InputInfo& ii = inputInfos[i];
|
||||
DynLocation* dl = tas.recordRead(ii, m_useHHIR);
|
||||
DynLocation* dl = tas.recordRead(ii, true);
|
||||
const RuntimeType& rtt = dl->rtt;
|
||||
// Some instructions are able to handle an input with an unknown type
|
||||
if (!ii.dontBreak && !ii.dontGuard) {
|
||||
@@ -3582,7 +3579,7 @@ std::unique_ptr<Tracelet> Translator::analyze(SrcKey sk,
|
||||
}
|
||||
|
||||
analyzeInstr(t, *ni);
|
||||
if (m_useHHIR && ni->op() == OpFCall) {
|
||||
if (ni->op() == OpFCall) {
|
||||
analyzeCallee(tas, t, ni);
|
||||
}
|
||||
|
||||
@@ -3696,12 +3693,6 @@ breakBB:
|
||||
}
|
||||
}
|
||||
|
||||
// Peephole optimizations may leave the bytecode stream in a state that is
|
||||
// inconsistent and troubles HHIR emission, so don't do it if HHIR is in use
|
||||
if (!m_useHHIR) {
|
||||
analyzeSecondPass(t);
|
||||
}
|
||||
|
||||
relaxDeps(t, tas);
|
||||
|
||||
// Mark the last instruction appropriately
|
||||
@@ -3725,7 +3716,6 @@ breakBB:
|
||||
|
||||
Translator::Translator()
|
||||
: m_resumeHelper(nullptr)
|
||||
, m_useHHIR(false)
|
||||
, m_createdTime(Timer::GetCurrentTimeMicros())
|
||||
, m_analysisDepth(0)
|
||||
{
|
||||
|
||||
@@ -703,7 +703,7 @@ struct Tracelet : private boost::noncopyable {
|
||||
};
|
||||
|
||||
enum TransKind {
|
||||
TransNormal = 0,
|
||||
TransInterp = 0,
|
||||
TransNormalIR = 1,
|
||||
TransAnchor = 2,
|
||||
TransProlog = 3,
|
||||
@@ -781,6 +781,37 @@ struct TransRec {
|
||||
string print(uint64_t profCount) const;
|
||||
};
|
||||
|
||||
struct TranslArgs {
|
||||
TranslArgs(const SrcKey& sk, bool align)
|
||||
: m_sk(sk)
|
||||
, m_src(nullptr)
|
||||
, m_align(align)
|
||||
, m_interp(false)
|
||||
{}
|
||||
|
||||
TranslArgs& sk(const SrcKey& sk) {
|
||||
m_sk = sk;
|
||||
return *this;
|
||||
}
|
||||
TranslArgs& src(TCA src) {
|
||||
m_src = src;
|
||||
return *this;
|
||||
}
|
||||
TranslArgs& align(bool align) {
|
||||
m_align = align;
|
||||
return *this;
|
||||
}
|
||||
TranslArgs& interp(bool interp) {
|
||||
m_interp = interp;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SrcKey m_sk;
|
||||
TCA m_src;
|
||||
bool m_align;
|
||||
bool m_interp;
|
||||
};
|
||||
|
||||
/*
|
||||
* Translator annotates a tracelet with input/output locations/types.
|
||||
*/
|
||||
@@ -851,8 +882,6 @@ protected:
|
||||
vector<TransRec> m_translations;
|
||||
vector<uint64_t*> m_transCounters;
|
||||
|
||||
bool m_useHHIR; // Is HHIR in effect for current trace?
|
||||
|
||||
int64_t m_createdTime;
|
||||
|
||||
static Lease s_writeLease;
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário