Kill lots of tx64

Its dead
Esse commit está contido em:
mwilliams
2013-05-23 18:59:20 -07:00
commit de Sara Golemon
commit 716a01c85e
6 arquivos alterados com 147 adições e 7297 exclusões
+2 -3
Ver Arquivo
@@ -14,10 +14,10 @@
+----------------------------------------------------------------------+
*/
#include "hphp/util/base.h"
#include "hphp/runtime/vm/translator/annotation.h"
#include "hphp/runtime/vm/translator/translator.h"
#include "hphp/runtime/vm/translator/translator-inline.h"
#include "hphp/runtime/vm/translator/annotation.h"
#include "hphp/util/base.h"
namespace HPHP {
namespace Transl {
@@ -88,7 +88,6 @@ static void recordFunc(NormalizedInstruction& i,
cr.m_type = Function;
cr.m_func = func;
s_callDB.insert(std::make_pair(sk, cr));
i.directCall = true;
}
static void recordActRecPush(NormalizedInstruction& i,
+31 -65
Ver Arquivo
@@ -191,7 +191,14 @@ TranslatorX64::irTranslateLtGtOp(const Tracelet& t,
assert(i.inputs[0]->outerType() != KindOfRef);
assert(i.inputs[1]->outerType() != KindOfRef);
HHIR_UNIMPLEMENTED_WHEN((!i.isNative()), LtGtOp);
DataType leftType = i.inputs[0]->outerType();
DataType rightType = i.inputs[1]->outerType();
bool ok = TypeConstraint::equivDataTypes(leftType, rightType) &&
(i.inputs[0]->isNull() ||
leftType == KindOfBoolean ||
i.inputs[0]->isInt());
HHIR_UNIMPLEMENTED_WHEN(!ok, LtGtOp);
switch (op) {
case OpLt : HHIR_EMIT(Lt);
case OpLte : HHIR_EMIT(Lte);
@@ -442,7 +449,8 @@ TranslatorX64::irTranslateAdd(const Tracelet& t,
const NormalizedInstruction& i) {
assert(i.inputs.size() == 2);
if (planInstrAdd_Array(i)) {
if (i.inputs[0]->valueType() == KindOfArray &&
i.inputs[1]->valueType() == KindOfArray) {
HHIR_EMIT(ArrayAdd);
return;
}
@@ -759,6 +767,12 @@ TranslatorX64::irTranslateUnsetG(const Tracelet& t,
HHIR_EMIT(UnsetG, gblName);
}
void
TranslatorX64::irTranslateUnsetN(const Tracelet& t,
const NormalizedInstruction& i) {
HHIR_EMIT(UnsetN);
}
void TranslatorX64::irTranslateCGetS(const Tracelet& t,
const NormalizedInstruction& i) {
const int kPropNameIdx = 1;
@@ -911,13 +925,6 @@ TranslatorX64::irTranslateUnsetL(const Tracelet& t,
HHIR_EMIT(UnsetL, i.inputs[0]->location.offset);
}
void
TranslatorX64::irTranslateReqLit(const Tracelet& t,
const NormalizedInstruction& i,
InclOpFlags flags) {
HHIR_UNIMPLEMENTED(ReqLit);
}
void
TranslatorX64::irTranslateReqDoc(const Tracelet& t,
const NormalizedInstruction& i) {
@@ -1037,6 +1044,18 @@ TranslatorX64::irTranslateFPushFuncD(const Tracelet& t,
HHIR_EMIT(FPushFuncD, (i.imm[0].u_IVA), (i.imm[1].u_SA));
}
void
TranslatorX64::irTranslateBPassC(const Tracelet& t,
const NormalizedInstruction& i) {
// No-op
}
void
TranslatorX64::irTranslateBPassV(const Tracelet& t,
const NormalizedInstruction& i) {
// No-op
}
void
TranslatorX64::irTranslateFPassCOp(const Tracelet& t,
const NormalizedInstruction& i) {
@@ -1537,54 +1556,8 @@ TranslatorX64::irTranslateInstrDefault(const Tracelet& t,
};
const Opcode op = i.op();
// Add to this switch the bytecodes that the IR handles but the base
// translator does not analyze and translate
switch (op) {
case OpLateBoundCls:
irTranslateLateBoundCls(t, i);
break;
case OpEmptyS:
irTranslateEmptyS(t, i);
break;
case OpEmptyG:
irTranslateEmptyG(t, i);
break;
case OpVGetS:
irTranslateVGetS(t, i);
break;
case OpIssetS:
irTranslateIssetS(t, i);
break;
case OpIssetG:
irTranslateIssetG(t, i);
break;
case OpUnsetN:
m_hhbcTrans->emitUnsetN();
break;
case OpUnsetG:
irTranslateUnsetG(t, i);
break;
case OpBindG:
irTranslateBindG(t, i);
break;
case OpIterFree:
irTranslateIterFree(t, i);
break;
case OpBPassC:
case OpBPassV:
// OpBPass* instructions are no-ops
break;
case OpFPassV:
irTranslateFPassV(t, i);
break;
case OpBindS:
irTranslateBindS(t, i);
break;
default:
// GO: if you hit this, check opNames[op] and add support for it
HHIR_UNIMPLEMENTED_OP(opNames[op]);
assert(false);
}
HHIR_UNIMPLEMENTED_OP(opNames[op]);
assert(false);
}
void
@@ -1693,14 +1666,7 @@ void TranslatorX64::irTranslateInstr(const Tracelet& t,
m_hhbcTrans->setBcOff(i.source.offset(),
i.breaksTracelet && !m_hhbcTrans->isInlining());
if (!i.grouped) {
emitVariantGuards(t, i);
const NormalizedInstruction* n = &i;
while (n->next && n->next->grouped) {
n = n->next;
emitVariantGuards(t, *n);
}
}
emitVariantGuards(t, i);
if (i.guardedThis) {
// Task #2067635: This should really generate an AssertThis
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+15 -88
Ver Arquivo
@@ -298,11 +298,6 @@ private:
PhysReg src,
int off,
PhysReg tmpReg);
void emitTvSetRegSafe(const NormalizedInstruction&, PhysReg from,
DataType fromType, PhysReg toPtr, int toOffset, PhysReg tmp1, PhysReg tmp2,
bool incRefFrom);
void emitTvSet(const NormalizedInstruction&, PhysReg from,
DataType fromType, PhysReg toPtr, int toOffset = 0, bool incRefFrom = true);
void emitThisCheck(const NormalizedInstruction& i, PhysReg reg);
void emitPushAR(const NormalizedInstruction& i, const Func* func,
@@ -557,6 +552,21 @@ private:
CASE(ArrayIdx) \
CASE(FPushCufIter) \
CASE(CIterFree) \
CASE(LateBoundCls) \
CASE(IssetS) \
CASE(IssetG) \
CASE(UnsetG) \
CASE(EmptyS) \
CASE(EmptyG) \
CASE(VGetS) \
CASE(BindS) \
CASE(BindG) \
CASE(IterFree) \
CASE(FPassV) \
CASE(UnsetN) \
CASE(BPassC) \
CASE(BPassV) \
// These are instruction-like functions which cover more than one
// opcode.
#define PSEUDOINSTRS \
@@ -571,56 +581,6 @@ private:
CASE(FPassCOp) \
CASE(CheckTypeOp)
#define PAIR(nm) \
void analyze ## nm(Tracelet& t, NormalizedInstruction& i); \
void translate ## nm(const Tracelet& t, const NormalizedInstruction& i);
#define CASE PAIR
INSTRS
PSEUDOINSTRS
#undef CASE
#undef PAIR
void branchWithFlagsSet(const Tracelet& t, const NormalizedInstruction& i,
ConditionCode cc);
void fuseBranchSync(const Tracelet& t, const NormalizedInstruction& i);
void fuseBranchAfterBool(const Tracelet& t, const NormalizedInstruction& i,
ConditionCode cc);
void fuseHalfBranchAfterBool(const Tracelet& t,
const NormalizedInstruction& i,
ConditionCode cc, bool taken);
void fuseBranchAfterStaticBool(Asm& a, const Tracelet& t,
const NormalizedInstruction& i,
bool resultIsTrue, bool doSync = true);
void emitReturnVal(Asm& a, const NormalizedInstruction& i,
PhysReg dstBase, int dstOffset,
PhysReg thisBase, int thisOffset,
PhysReg scratch);
void fuseBranchAfterHelper(const Tracelet& t,
const NormalizedInstruction& i);
void translateSetMArray(const Tracelet &t, const NormalizedInstruction& i);
void emitGetGlobal(const NormalizedInstruction& i, int nameIdx,
bool allowCreate);
void emitArrayElem(const NormalizedInstruction& i,
const DynLocation* baseInput,
PhysReg baseReg,
const DynLocation* keyIn,
const Location& outLoc);
void translateIssetMFast(const Tracelet& t,
const NormalizedInstruction& ni);
void setupActRecClsForStaticCall(const NormalizedInstruction& i,
const Func* func, const Class* cls,
size_t clsOff, bool forward);
void emitInstanceCheck(const Tracelet& t, const NormalizedInstruction& i,
const StringData* clsName,
const Class* maybeCls,
const ScratchReg& inCls,
const ScratchReg& cls,
const LazyScratchReg& result);
void emitFPushCtorDFast(const NormalizedInstruction& i, Class* cls,
int arOff);
template<typename L>
void translatorAssert(X64Assembler& a, ConditionCode cc,
const char* msg, L setup);
@@ -691,9 +651,6 @@ PSEUDOINSTRS
Asm& getAsm() { return a; }
void emitChainTo(SrcKey dest, bool isCall = false);
void syncOutputs(const Tracelet& t);
void syncOutputs(const NormalizedInstruction& i);
void syncOutputs(int stackOff);
static bool isPseudoEvent(const char* event);
void getPerfCounters(Array& ret);
@@ -713,7 +670,6 @@ private:
void poison(PhysReg dest);
public:
void analyzeInstr(Tracelet& t, NormalizedInstruction& i);
bool acquireWriteLease(bool blocking) {
return s_writeLease.acquire(blocking);
}
@@ -723,14 +679,9 @@ public:
void emitGuardChecks(Asm& a, SrcKey, const ChangeMap&,
const RefDeps&, SrcRec&);
void emitOneGuard(const Tracelet& t,
const NormalizedInstruction& i,
PhysReg reg, int disp, DataType type,
TCA &sideExit);
void irEmitResolvedDeps(const ChangeMap& resolvedDeps);
void emitVariantGuards(const Tracelet& t, const NormalizedInstruction& i);
void emitPredictionGuards(const NormalizedInstruction& i);
Debug::DebugInfo* getDebugInfo() { return &m_debugInfo; }
@@ -837,11 +788,8 @@ private:
TCA emitRetFromInterpretedGeneratorFrame();
TCA emitGearTrigger(Asm& a, SrcKey sk, TransID transId);
void emitPopRetIntoActRec(Asm& a);
void emitBox(DataType t, PhysReg rToBox);
void emitUnboxTopOfStack(const NormalizedInstruction& ni);
int32_t emitBindCall(SrcKey srcKey, const Func* funcd, int numArgs);
void emitCondJmp(SrcKey skTrue, SrcKey skFalse, ConditionCode cc);
void emitInterpOne(const Tracelet& t, const NormalizedInstruction& i);
bool handleServiceRequest(TReqInfo&, TCA& start, SrcKey& sk);
void recordGdbTranslation(SrcKey sk, const Func* f,
@@ -878,10 +826,6 @@ private:
int numArgs);
void emitIncCounter(TCA start, int cntOfs);
void analyzeReqLit(Tracelet& t, NormalizedInstruction& i,
InclOpFlags flags);
void translateReqLit(const Tracelet& t, const NormalizedInstruction& i,
InclOpFlags flags);
struct ReqLitStaticArgs {
HPHP::Eval::PhpFile* m_efile;
TCA m_pseudoMain;
@@ -897,11 +841,6 @@ private:
// Utility function shared with IR code
static uint64_t packBitVec(const vector<bool>& bits, unsigned i);
void translateBasicIterInit(const Tracelet& t,
const NormalizedInstruction& ni);
void translateBasicIterNext(const Tracelet& t,
const NormalizedInstruction& ni);
public:
/*
* enterTC is the main entry point for the translator from the
@@ -992,18 +931,6 @@ PSEUDOINSTRS
#undef CASE
#undef DECLARE_FUNC
// Helper functions not covered by macros above
void irTranslateIssetS(const Tracelet& t, const NormalizedInstruction& i);
void irTranslateIssetG(const Tracelet& t, const NormalizedInstruction& i);
void irTranslateUnsetG(const Tracelet& t, const NormalizedInstruction& i);
void irTranslateEmptyS(const Tracelet& t, const NormalizedInstruction& i);
void irTranslateEmptyG(const Tracelet& t, const NormalizedInstruction& i);
void irTranslateVGetS(const Tracelet& t, const NormalizedInstruction& i);
void irTranslateBindS(const Tracelet& t, const NormalizedInstruction& i);
void irTranslateBindG(const Tracelet& t, const NormalizedInstruction& i);
void irTranslateIterFree(const Tracelet& t, const NormalizedInstruction& i);
void irTranslateLateBoundCls(const Tracelet&, const NormalizedInstruction&i);
void irTranslateFPassV(const Tracelet& t, const NormalizedInstruction& i);
void irTranslateReqLit(const Tracelet& t,
const NormalizedInstruction& i,
InclOpFlags flags);
+1 -319
Ver Arquivo
@@ -1456,265 +1456,6 @@ int getStackDelta(const NormalizedInstruction& ni) {
return delta;
}
/*
* analyzeSecondPass --
*
* Whole-tracelet analysis pass, after we've set up the dataflow
* graph. Modifies the instruction stream, and further annotates
* individual instructions.
*/
void Translator::analyzeSecondPass(Tracelet& t) {
assert(t.m_instrStream.last);
NormalizedInstruction* next;
for (NormalizedInstruction* ni = t.m_instrStream.first; ni; ni = next) {
const Opcode op = ni->op();
next = ni->next;
if (op == OpNop) {
t.m_instrStream.remove(ni);
continue;
}
if (op == OpCGetL) {
/*
* If the local isn't more broadly useful in this tracelet, don't bother
* allocating space for it.
*/
const Location& local = ni->inputs[0]->location;
bool seen = false;
for (NormalizedInstruction* cur = ni->next; cur; cur = cur->next) {
if ((ni->m_txFlags & Native) != Native) break;
for (unsigned dli = 0; dli < cur->inputs.size(); ++dli) {
Location& loc = cur->inputs[dli]->location;
if (loc == local) {
SKTRACE(1, ni->source, "CGetL: loading input\n");
seen = true;
break;
}
}
}
ni->manuallyAllocInputs = !seen && !ni->inputs[0]->rtt.isUninit();
SKTRACE(1, ni->source, "CGetL: manuallyAllocInputs: %d\n",
ni->manuallyAllocInputs);
continue;
}
NormalizedInstruction* prev = ni->prev;
if (!prev || !(prev->m_txFlags & Supported)) continue;
const Opcode prevOp = prev->op();
if (!ni->next &&
(op == OpJmpZ || op == OpJmpNZ)) {
if (prevOp == OpNot && (ni->m_txFlags & Supported)) {
ni->invertCond = !ni->invertCond;
ni->inputs[0] = prev->inputs[0];
assert(!prev->deadLocs.size());
t.m_instrStream.remove(prev);
next = ni;
continue;
}
if (prevOp == OpGt || prevOp == OpLt ||
prevOp == OpGte || prevOp == OpLte ||
prevOp == OpEq || prevOp == OpNeq ||
prevOp == OpIssetL || prevOp == OpAKExists ||
isTypePred(prevOp) || prevOp == OpInstanceOfD ||
prev->fuseBranch) {
prev->breaksTracelet = true;
prev->changesPC = true; // Dont generate generic glue.
// Leave prev->next linked. The translator will end up needing it. The
// breaksTracelet annotation here will prevent us from really translating the
// Jmp*.
continue;
}
}
if (op == OpFPushClsMethodF && ni->directCall &&
prevOp == OpAGetC &&
prev->prev && prev->prev->op() == OpString &&
prev->prev->prev && prev->prev->prev->op() == OpString) {
/*
* We have a fully determined OpFPushClsMethodF. We dont
* need to put the class and method name strings, or the
* Class* into registers.
*/
prev->outStack = nullptr;
prev->prev->outStack = nullptr;
prev->prev->prev->outStack = nullptr;
}
if (RuntimeOption::RepoAuthoritative &&
prevOp == OpFPushCtorD &&
!prev->noCtor &&
prev->imm[0].u_IVA == 0 &&
op == OpFCall && (ni->m_txFlags & Supported) &&
ni->next && (ni->next->m_txFlags & Supported) &&
ni->next->op() == OpPopR) {
/* new obj with a ctor that takes no args */
const NamedEntityPair& np =
curUnit()->lookupNamedEntityPairId(prev->imm[1].u_SA);
const Class* cls = Unit::lookupUniqueClass(np.second);
if (cls && (cls->attrs() & AttrUnique) &&
Func::isSpecial(cls->getCtor()->name())) {
/* its the generated 86ctor, so no need to call it */
next = next->next;
t.m_instrStream.remove(ni->next);
t.m_instrStream.remove(ni);
prev->noCtor = 1;
SKTRACE(1, prev->source, "FPushCtorD: killing ctor for %s in %s\n",
np.first->data(), curFunc()->fullName()->data());
continue;
}
}
/*
* If this is a Pop instruction and the previous instruction pushed a
* single return value cell on the stack, we can roll the pop into the
* previous instruction.
*
* TODO: SetG/SetS?
*/
const bool isPop = op == OpPopC || op == OpPopV;
const bool isOptimizable = prevOp == OpSetL ||
prevOp == OpBindL ||
prevOp == OpIncDecL ||
prevOp == OpPrint ||
prevOp == OpSetM ||
prevOp == OpSetOpM ||
prevOp == OpIncDecM;
if (isPop && isOptimizable) {
// If one of these instructions already has a null outStack, we
// already hoisted a pop into it.
const bool alreadyHoisted = !prev->outStack;
if (!alreadyHoisted) {
prev->outStack = nullptr;
SKTRACE(3, ni->source, "hoisting Pop instruction in analysis\n");
for (unsigned i = 0; i < ni->deadLocs.size(); ++i) {
prev->deadLocs.push_back(ni->deadLocs[i]);
}
t.m_instrStream.remove(ni);
if ((prevOp == OpSetM || prevOp == OpSetOpM || prevOp == OpIncDecM) &&
prev->prev && prev->prev->op() == OpCGetL &&
prev->prev->inputs[0]->outerType() != KindOfUninit) {
assert(prev->prev->outStack);
prev->prev->outStack = 0;
prev->prev->manuallyAllocInputs = true;
prev->prev->ignoreInnerType = true;
prev->inputs[0] = prev->prev->inputs[0];
prev->grouped = true;
}
continue;
}
}
/*
* A Not instruction following an Is* instruction can
* be folded.
*/
if (op == OpNot) {
switch (prevOp) {
case OpAKExists:
case OpIssetL:
case OpIsNullL: case OpIsNullC:
case OpIsBoolL: case OpIsBoolC:
case OpIsIntL: case OpIsIntC:
case OpIsDoubleL: case OpIsDoubleC:
case OpIsStringL: case OpIsStringC:
case OpIsArrayL: case OpIsArrayC:
case OpIsObjectL: case OpIsObjectC:
prev->invertCond = !prev->invertCond;
prev->outStack = ni->outStack;
SKTRACE(3, ni->source, "folding Not instruction in analysis\n");
assert(!ni->deadLocs.size());
t.m_instrStream.remove(ni);
continue;
}
}
if (op == OpInstanceOfD && prevOp == OpCGetL &&
(ni->m_txFlags & Supported)) {
assert(prev->outStack);
ni->inputs[0] = prev->inputs[0];
/*
the CGetL becomes a no-op (other
than checking for UninitNull), but
we mark the InstanceOfD as grouped to
avoid breaking the tracelet between the
two.
*/
prev->ignoreInnerType = true;
prev->outStack = 0;
prev->manuallyAllocInputs = true;
ni->grouped = true;
}
if ((op == OpInstanceOfD || op == OpIsNullC) &&
(ni->m_txFlags & Supported) &&
(prevOp == OpThis || prevOp == OpBareThis)) {
prev->outStack = 0;
ni->grouped = true;
ni->manuallyAllocInputs = true;
}
/*
* TODO: #1181258 this should mostly be subsumed by the IR.
* Remove this once the IR is seen to be handling it.
*/
NormalizedInstruction* pp = nullptr;
if (prevOp == OpString &&
(ni->m_txFlags & Supported)) {
switch (op) {
case OpReqDoc:
/* Dont waste a register on the string */
prev->outStack = nullptr;
pp = prev->prev;
}
}
if (op == OpRetC && (ni->m_txFlags & Supported) &&
(prevOp == OpString ||
prevOp == OpInt ||
prevOp == OpNull ||
prevOp == OpTrue ||
prevOp == OpFalse ||
prevOp == OpDouble ||
prevOp == OpArray ||
prevOp == OpThis ||
prevOp == OpBareThis)) {
assert(!ni->outStack);
ni->grouped = true;
prev->outStack = nullptr;
pp = prev->prev;
}
if (pp && pp->op() == OpPopC &&
pp->m_txFlags == Native) {
NormalizedInstruction* ppp = prev->prev->prev;
if (ppp && (ppp->m_txFlags & Supported)) {
switch (ppp->op()) {
case OpReqDoc:
/*
We have a require+pop followed by a require or a scalar ret,
where the pop doesnt have to do any work (the pop is Native).
There is no need to inc/dec rbx between the two (since
there will be no code between them)
*/
ppp->outStack = nullptr;
ni->skipSync = true;
break;
default:
// do nothing
break;
}
}
}
}
}
static NormalizedInstruction* findInputSrc(NormalizedInstruction* ni,
DynLocation* dl) {
while (ni != nullptr) {
@@ -3065,17 +2806,6 @@ void Translator::constrainOperandType(GuardType& relxType,
}
}
void Translator::reanalizeConsumers(Tracelet& tclet, DynLocation* depDynLoc) {
for (auto& instr : tclet.m_instrs) {
for (size_t i = 0; i < instr.inputs.size(); i++) {
if (instr.inputs[i] == depDynLoc) {
analyzeInstr(tclet, instr);
}
}
}
}
/*
* This method looks at all the uses of the tracelet dependencies in the
* instruction stream and tries to relax the type associated with each location.
@@ -3125,7 +2855,6 @@ void Translator::relaxDeps(Tracelet& tclet, TraceletContext& tctxt) {
assert(relxType.getOuterType() != KindOfInvalid);
deps[loc->location]->rtt = RuntimeType(relxType.getOuterType(),
relxType.getInnerType());
reanalizeConsumers(tclet, loc);
}
}
}
@@ -3626,7 +3355,6 @@ std::unique_ptr<Tracelet> Translator::analyze(SrcKey sk,
annotate(ni);
}
analyzeInstr(t, *ni);
if (ni->op() == OpFCall) {
analyzeCallee(tas, t, ni);
}
@@ -3635,52 +3363,6 @@ std::unique_ptr<Tracelet> Translator::analyze(SrcKey sk,
tas.recordDelete(l);
}
if (debug) {
// The interpreter has lots of nice sanity assertions in debug mode
// that the translator doesn't exercise. As a cross-check on the
// translator's correctness, this is a debug-only facility for
// sending a random selection of instructions through the
// interpreter.
//
// Set stress_txInterpPct to a value between 1 and 100. If you want
// to reproduce a failing case, look for the seed in the log and set
// stress_txInterpSeed accordingly.
if (!dbgTranslateCoin) {
dbgTranslateCoin = new BiasedCoin(Trace::stress_txInterpPct,
Trace::stress_txInterpSeed);
TRACE(1, "BiasedCoin(stress_txInterpPct,stress_txInterpSeed): "
"pct %f, seed %d\n",
dbgTranslateCoin->getPercent(), dbgTranslateCoin->getSeed());
}
assert(dbgTranslateCoin);
if (dbgTranslateCoin->flip()) {
SKTRACE(3, ni->source, "stress interp\n");
ni->m_txFlags = Interp;
}
if ((ni->op()) > Trace::moduleLevel(Trace::tmp0) &&
(ni->op()) < Trace::moduleLevel(Trace::tmp1)) {
ni->m_txFlags = Interp;
}
}
Op txOpBisectLowOp = (Op)moduleLevel(Trace::txOpBisectLow),
txOpBisectHighOp = (Op)moduleLevel(Trace::txOpBisectHigh);
if (txOpBisectLowOp > OpLowInvalid &&
txOpBisectHighOp > OpLowInvalid &&
txOpBisectHighOp < OpHighInvalid) {
// If the user specified an operation bisection interval [Low, High]
// that is strictly included in (OpLowInvalid, OpHighInvalid), then
// only support the operations in that interval. Since the default
// value of moduleLevel is 0 and OpLowInvalid is also 0, this ensures
// that bisection is disabled by default.
static_assert(OpLowInvalid >= 0,
"OpLowInvalid must be nonnegative");
if (ni->op() < txOpBisectLowOp ||
ni->op() > txOpBisectHighOp)
ni->m_txFlags = Interp;
}
// Check if we need to break the tracelet.
//
// If we've gotten this far, it mostly boils down to control-flow
@@ -3696,7 +3378,7 @@ std::unique_ptr<Tracelet> Translator::analyze(SrcKey sk,
sk = SrcKey(curFunc(), sk.m_offset + ni->imm[0].u_IA);
goto head; // don't advance sk
} else if (opcodeBreaksBB(ni->op()) ||
(ni->m_txFlags == Interp && opcodeChangesPC(ni->op()))) {
(dontGuardAnyInputs(ni->op()) && opcodeChangesPC(ni->op()))) {
SKTRACE(1, sk, "BB broken\n");
sk.advance(unit);
goto breakBB;
-63
Ver Arquivo
@@ -317,27 +317,10 @@ class NormalizedInstruction {
bool fuseBranch:1;
bool preppedByRef:1; // For FPass*; indicates parameter reffiness
bool manuallyAllocInputs:1;
bool invertCond:1;
bool outputPredicted:1;
bool outputPredictionStatic:1;
bool ignoreInnerType:1;
/*
* skipSync indicates that a previous instruction that should have
* adjusted the stack (eg FCall, Req*) didnt, because it could see
* that the next one was going to immediately adjust it again
* (ie at this point, rVmSp holds the "correct" value, rather
* than the value it had at the beginning of the tracelet)
*/
bool skipSync:1;
/*
* grouped indicates that the tracelet should not be broken
* (eg by a side exit) between the preceding instruction and
* this one
*/
bool grouped:1;
/*
* guardedThis indicates that we know that ar->m_this is
* a valid $this. eg:
@@ -358,12 +341,6 @@ class NormalizedInstruction {
*/
bool noSurprise:1;
/*
noCtor is set on FPushCtorD to say that the ctor is
going to be skipped (so dont setup an actrec)
*/
bool noCtor:1;
/*
* instruction is statically known to have no effect, e.g. unboxing a Cell
*/
@@ -375,11 +352,6 @@ class NormalizedInstruction {
*/
bool interp:1;
/*
* This is an FPush* that will be directly bound to a Func*
*/
bool directCall:1;
/*
* Indicates that a RetC/RetV should generate inlined return code
* rather than calling the shared stub.
@@ -392,7 +364,6 @@ class NormalizedInstruction {
boost::dynamic_bitset<> nonRefCountedLocals;
ArgUnion constImm;
TXFlags m_txFlags;
Op op() const;
Op mInstrOp() const;
@@ -410,40 +381,17 @@ class NormalizedInstruction {
, outStack3(nullptr)
, checkedInputs(0)
, hasConstImm(false)
, invertCond(false)
, ignoreInnerType(false)
, skipSync(false)
, grouped(false)
, guardedThis(false)
, guardedCls(false)
, noSurprise(false)
, noCtor(false)
, noOp(false)
, interp(false)
, directCall(false)
, inlineReturn(false)
, m_txFlags(Interp)
{
memset(imm, 0, sizeof(imm));
}
bool isJmpNZ() const {
assert(op() == OpJmpNZ || op() == OpJmpZ);
return (op() == OpJmpNZ) != invertCond;
}
bool isSupported() const {
return (m_txFlags & Supported) == Supported;
}
bool isSimple() const {
return (m_txFlags & Simple) == Simple;
}
bool isNative() const {
return (m_txFlags & Native) == Native;
}
void markInputInferred(int i) {
if (i < 32) checkedInputs |= 1u << i;
}
@@ -452,15 +400,6 @@ class NormalizedInstruction {
return i < 32 && ((checkedInputs >> i) & 1);
}
bool wasGroupedWith(Op op) const {
return grouped && prev->op() == op;
}
template<class... OpTypes>
bool wasGroupedWith(Op op, OpTypes... ops) const {
return wasGroupedWith(op) || wasGroupedWith(ops...);
}
enum OutputUse {
OutputUsed,
OutputUnused,
@@ -845,7 +784,6 @@ private:
int& currentStackOffset,
bool& varEnvTaint);
void relaxDeps(Tracelet& tclet, TraceletContext& tctxt);
void reanalizeConsumers(Tracelet& tclet, DynLocation* depDynLoc);
DataTypeCategory getOperandConstraintCategory(NormalizedInstruction* instr,
size_t opndIdx);
GuardType getOperandConstraintType(NormalizedInstruction* instr,
@@ -905,7 +843,6 @@ public:
*/
virtual void requestInit() = 0;
virtual void requestExit() = 0;
virtual void analyzeInstr(Tracelet& t, NormalizedInstruction& i) = 0;
virtual TCA funcPrologue(Func* f, int nArgs, ActRec* ar = nullptr) = 0;
virtual TCA getCallToExit() = 0;
virtual TCA getRetFromInterpretedFrame() = 0;