Remove BPass* instructions
Esse commit está contido em:
@@ -286,6 +286,7 @@ static int32_t countStackValues(const std::vector<uchar>& immVec) {
|
||||
#define COUNT_R_LMANY() 0
|
||||
#define COUNT_V_LMANY() 0
|
||||
#define COUNT_FMANY 0
|
||||
#define COUNT_CVMANY 0
|
||||
#define COUNT_CMANY 0
|
||||
|
||||
#define ONE(t) \
|
||||
@@ -338,6 +339,8 @@ static int32_t countStackValues(const std::vector<uchar>& immVec) {
|
||||
getEmitterVisitor().popEvalStackLMany()
|
||||
#define POP_FMANY \
|
||||
getEmitterVisitor().popEvalStackMany(a1, StackSym::F)
|
||||
#define POP_CVMANY \
|
||||
getEmitterVisitor().popEvalStackCVMany(a1)
|
||||
#define POP_CMANY \
|
||||
getEmitterVisitor().popEvalStackMany(a1, StackSym::C)
|
||||
|
||||
@@ -562,6 +565,7 @@ static int32_t countStackValues(const std::vector<uchar>& immVec) {
|
||||
#undef POP_FV
|
||||
#undef POP_LREST
|
||||
#undef POP_FMANY
|
||||
#undef POP_CVMANY
|
||||
#undef POP_CMANY
|
||||
#undef POP_HA_ONE
|
||||
#undef POP_HA_TWO
|
||||
@@ -1314,6 +1318,32 @@ void EmitterVisitor::popEvalStackMany(int len, char symFlavor) {
|
||||
}
|
||||
}
|
||||
|
||||
void EmitterVisitor::popEvalStackCVMany(int len) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (m_evalStack.size() == 0) {
|
||||
InvariantViolation("Emitter emitted an instruction that tries to consume "
|
||||
"a value from the stack when the stack is empty "
|
||||
"(expected symbolic flavor C or V at offset %d)",
|
||||
m_ue.bcPos());
|
||||
return;
|
||||
}
|
||||
|
||||
char sym = m_evalStack.top();
|
||||
char actual = StackSym::GetSymFlavor(sym);
|
||||
m_evalStack.pop();
|
||||
if (actual != StackSym::C && actual != StackSym::V) {
|
||||
InvariantViolation(
|
||||
"Emitter emitted an instruction that tries to consume a "
|
||||
"value from the stack when the top of the stack does not "
|
||||
"match the symbolic flavor that the instruction expects "
|
||||
"(expected symbolic flavor C or V, actual symbolic flavor \"%s\" "
|
||||
"at offset %d)",
|
||||
StackSym::ToString(actual).c_str(),
|
||||
m_ue.bcPos());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EmitterVisitor::pushEvalStack(char symFlavor) {
|
||||
// Push a value from the evaluation stack with the specified
|
||||
// symbolic flavor
|
||||
@@ -4291,15 +4321,11 @@ void EmitterVisitor::emitBuiltinCallArg(Emitter& e,
|
||||
int paramId,
|
||||
bool byRef) {
|
||||
visit(exp);
|
||||
if (checkIfStackEmpty("BPass*")) return;
|
||||
if (checkIfStackEmpty("Builtin arg*")) return;
|
||||
if (byRef) {
|
||||
emitVGet(e);
|
||||
m_metaInfo.add(m_ue.bcPos(), Unit::MetaInfo::NopOut, false, 0, 0);
|
||||
e.BPassV(paramId);
|
||||
} else {
|
||||
emitCGet(e);
|
||||
m_metaInfo.add(m_ue.bcPos(), Unit::MetaInfo::NopOut, false, 0, 0);
|
||||
e.BPassC(paramId);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -4344,8 +4370,6 @@ void EmitterVisitor::emitBuiltinDefaultArg(Emitter& e, Variant& v,
|
||||
default:
|
||||
not_reached();
|
||||
}
|
||||
m_metaInfo.add(m_ue.bcPos(), Unit::MetaInfo::NopOut, false, 0, 0);
|
||||
e.BPassC(paramId);
|
||||
}
|
||||
|
||||
void EmitterVisitor::emitFuncCallArg(Emitter& e,
|
||||
|
||||
@@ -343,6 +343,7 @@ public:
|
||||
void popSymbolicLocal(Opcode opcode, int arg = -1, int pos = -1);
|
||||
void popEvalStackLMany();
|
||||
void popEvalStackMany(int len, char symFlavor);
|
||||
void popEvalStackCVMany(int len);
|
||||
void pushEvalStack(char symFlavor);
|
||||
void peekEvalStack(char symFlavor, int depthActual);
|
||||
void pokeEvalStack(char symFlavor, int depthActual);
|
||||
|
||||
@@ -320,8 +320,8 @@ dispatcher to call the function.
|
||||
|
||||
Calls to builtin functions may be optimized to avoid pusing an entry on the FPI
|
||||
stack if it is known that the builtin function does not need access to the call
|
||||
stack. In this case, the arguments to the builtin are passed with the BPass*
|
||||
instructions, and the builtin can be invoked with the FCallBuiltin instruction.
|
||||
stack. In this case, the arguments to the builtin are pushed on stack as Cells
|
||||
and Vars, and the builtin can be invoked with the FCallBuiltin instruction.
|
||||
Unless otherwise noted, subsequent references to FCall* instructions should be
|
||||
meant to refer to non-optimized FCall instructions, i.e. all FCall instructions
|
||||
other than FCallBuiltin.
|
||||
@@ -1806,18 +1806,6 @@ FCallArray [F] -> [R]
|
||||
call the callee. When the callee returns, it will transfer the return value
|
||||
onto the caller's evaluation stack using the R flavor.
|
||||
|
||||
BPassC <param id> [C] -> [F]
|
||||
|
||||
Pass parameter to builtin call. This opcode is expected to be emitted
|
||||
only when parameter %1 is pass by value. The instruction pushes $1
|
||||
onto the stack as a cell.
|
||||
|
||||
BPassV <param id> [V] -> [F]
|
||||
|
||||
Pass parameter to builtin call. This opcode is expected to be emitted
|
||||
only when parameter %1 is pass by reference. The instruction pushes $1
|
||||
onto the stack as a var.
|
||||
|
||||
FCallBuiltin <total params> <passed params> <litstr id> [F..F] -> [R]
|
||||
|
||||
Optimized builtin call without an ActRec. This instruction attempts to
|
||||
|
||||
@@ -1023,6 +1023,7 @@ OpcodeParserMap opcode_parsers;
|
||||
#define NUM_POP_R_LMANY() (1 + vecImmStackValues)
|
||||
#define NUM_POP_C_LMANY() (1 + vecImmStackValues)
|
||||
#define NUM_POP_FMANY immIVA /* number of arguments */
|
||||
#define NUM_POP_CVMANY immIVA /* number of arguments */
|
||||
#define NUM_POP_CMANY immIVA /* number of arguments */
|
||||
|
||||
#define O(name, imm, pop, push, flags) \
|
||||
@@ -1098,6 +1099,7 @@ OPCODES
|
||||
#undef NUM_POP_R_LMANY
|
||||
#undef NUM_POP_C_LMANY
|
||||
#undef NUM_POP_FMANY
|
||||
#undef NUM_POP_CVMANY
|
||||
#undef NUM_POP_CMANY
|
||||
|
||||
void initialize_opcode_map() {
|
||||
|
||||
@@ -6030,16 +6030,6 @@ static inline ActRec* arFromInstr(TypedValue* sp, const Opcode* pc) {
|
||||
return arFromSpOffset((ActRec*)sp, instrSpToArDelta(pc));
|
||||
}
|
||||
|
||||
inline void OPTBLD_INLINE VMExecutionContext::iopBPassC(PC& pc) {
|
||||
NEXT();
|
||||
DECODE_IVA(paramId);
|
||||
}
|
||||
|
||||
inline void OPTBLD_INLINE VMExecutionContext::iopBPassV(PC& pc) {
|
||||
NEXT();
|
||||
DECODE_IVA(paramId);
|
||||
}
|
||||
|
||||
inline void OPTBLD_INLINE VMExecutionContext::iopFPassC(PC& pc) {
|
||||
#ifdef DEBUG
|
||||
ActRec* ar = arFromInstr(m_stack.top(), (Opcode*)pc);
|
||||
|
||||
@@ -366,6 +366,7 @@ int instrNumPops(const Opcode* opcode) {
|
||||
#define V_LMANY(...) -2
|
||||
#define R_LMANY(...) -2
|
||||
#define FMANY -3
|
||||
#define CVMANY -3
|
||||
#define CMANY -3
|
||||
#define O(name, imm, pop, push, flags) pop,
|
||||
OPCODES
|
||||
@@ -379,6 +380,7 @@ int instrNumPops(const Opcode* opcode) {
|
||||
#undef V_LMANY
|
||||
#undef R_LMANY
|
||||
#undef FMANY
|
||||
#undef CVMANY
|
||||
#undef CMANY
|
||||
#undef O
|
||||
};
|
||||
|
||||
@@ -74,6 +74,7 @@ enum FlavorDesc {
|
||||
AV = 3, // Classref
|
||||
RV = 4, // Return value (cell or var)
|
||||
FV = 5, // Function parameter (cell or var)
|
||||
CVV = 6, // Cell or Var argument
|
||||
};
|
||||
|
||||
enum InstrFlags {
|
||||
@@ -510,11 +511,9 @@ enum SetOpOp {
|
||||
O(FPushCufF, ONE(IVA), ONE(CV), NOV, NF) \
|
||||
O(FPushCufSafe, ONE(IVA), TWO(CV,CV), TWO(CV,CV), NF) \
|
||||
O(FPassC, ONE(IVA), ONE(CV), ONE(FV), FF) \
|
||||
O(BPassC, ONE(IVA), ONE(CV), ONE(FV), FF) \
|
||||
O(FPassCW, ONE(IVA), ONE(CV), ONE(FV), FF) \
|
||||
O(FPassCE, ONE(IVA), ONE(CV), ONE(FV), FF) \
|
||||
O(FPassV, ONE(IVA), ONE(VV), ONE(FV), FF) \
|
||||
O(BPassV, ONE(IVA), ONE(VV), ONE(FV), FF) \
|
||||
O(FPassR, ONE(IVA), ONE(RV), ONE(FV), FF) \
|
||||
O(FPassL, TWO(IVA,HA), NOV, ONE(FV), FF) \
|
||||
O(FPassN, ONE(IVA), ONE(CV), ONE(FV), FF) \
|
||||
@@ -523,7 +522,7 @@ enum SetOpOp {
|
||||
O(FPassM, TWO(IVA,MA), LMANY(), ONE(FV), FF) \
|
||||
O(FCall, ONE(IVA), FMANY, ONE(RV), CF_FF) \
|
||||
O(FCallArray, NA, ONE(FV), ONE(RV), CF_FF) \
|
||||
O(FCallBuiltin, THREE(IVA,IVA,SA),FMANY, ONE(RV), CF) \
|
||||
O(FCallBuiltin, THREE(IVA,IVA,SA),CVMANY, ONE(RV), CF) \
|
||||
O(CufSafeArray, NA, THREE(RV,CV,CV), ONE(CV), NF) \
|
||||
O(CufSafeReturn, NA, THREE(RV,CV,CV), ONE(RV), NF) \
|
||||
O(IterInit, THREE(IA,BA,HA), ONE(CV), NOV, CF) \
|
||||
@@ -567,7 +566,7 @@ enum SetOpOp {
|
||||
O(Parent, NA, NOV, ONE(AV), NF) \
|
||||
O(LateBoundCls, NA, NOV, ONE(AV), NF) \
|
||||
O(NativeImpl, NA, NOV, NOV, CF_TF) \
|
||||
O(CreateCl, TWO(IVA,SA), FMANY, ONE(CV), NF) \
|
||||
O(CreateCl, TWO(IVA,SA), CVMANY, ONE(CV), NF) \
|
||||
O(CreateCont, TWO(IVA,SA), NOV, ONE(CV), NF) \
|
||||
O(ContEnter, NA, NOV, NOV, CF) \
|
||||
O(ContExit, NA, NOV, NOV, CF) \
|
||||
|
||||
@@ -1043,18 +1043,6 @@ 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) {
|
||||
|
||||
@@ -445,8 +445,6 @@ private:
|
||||
CASE(IterFree) \
|
||||
CASE(FPassV) \
|
||||
CASE(UnsetN) \
|
||||
CASE(BPassC) \
|
||||
CASE(BPassV) \
|
||||
|
||||
// These are instruction-like functions which cover more than one
|
||||
// opcode.
|
||||
|
||||
@@ -1320,8 +1320,6 @@ static const struct {
|
||||
{ OpFPassS, {StackTop2|FuncdRef,
|
||||
Stack1, OutUnknown, -1 }},
|
||||
{ OpFPassM, {MVector|FuncdRef, Stack1, OutUnknown, 1 }},
|
||||
{ OpBPassC, {None, None, OutNull, 0 }},
|
||||
{ OpBPassV, {None, None, OutNull, 0 }},
|
||||
/*
|
||||
* FCall is special. Like the Ret* instructions, its manipulation of the
|
||||
* runtime stack are outside the boundaries of the tracelet abstraction.
|
||||
|
||||
@@ -527,7 +527,8 @@ static char stkflav(FlavorDesc f) {
|
||||
bool FuncChecker::checkSig(PC pc, int len, const FlavorDesc* args,
|
||||
const FlavorDesc* sig) {
|
||||
for (int i = 0; i < len; ++i) {
|
||||
if (args[i] != (FlavorDesc)sig[i]) {
|
||||
if (args[i] != (FlavorDesc)sig[i] &&
|
||||
!((FlavorDesc)sig[i] == CVV && (args[i] == CV || args[i] == VV))) {
|
||||
verify_error("flavor mismatch at %d, got %s expected %s\n",
|
||||
offset(pc), stkToString(len, args).c_str(),
|
||||
sigToString(len, sig).c_str());
|
||||
@@ -575,6 +576,7 @@ const FlavorDesc* FuncChecker::sig(PC pc) {
|
||||
static const FlavorDesc inputSigs[][3] = {
|
||||
#define NOV { },
|
||||
#define FMANY { },
|
||||
#define CVMANY { },
|
||||
#define CMANY { },
|
||||
#define ONE(a) { a },
|
||||
#define TWO(a,b) { b, a },
|
||||
@@ -592,6 +594,7 @@ const FlavorDesc* FuncChecker::sig(PC pc) {
|
||||
#undef R_LMANY
|
||||
#undef LMANY
|
||||
#undef FMANY
|
||||
#undef CVMANY
|
||||
#undef CMANY
|
||||
#undef FOUR
|
||||
#undef THREE
|
||||
@@ -619,12 +622,16 @@ const FlavorDesc* FuncChecker::sig(PC pc) {
|
||||
return vectorSig(pc, RV);
|
||||
case OpFCall: // ONE(IVA), FMANY, ONE(RV)
|
||||
case OpFCallArray:// NA, ONE(FV), ONE(RV)
|
||||
case OpFCallBuiltin: //TWO(IVA, SA) FMANY, ONE(RV)
|
||||
case OpCreateCl: // TWO(IVA,SA), FMANY, ONE(CV)
|
||||
for (int i = 0, n = instrNumPops(pc); i < n; ++i) {
|
||||
m_tmp_sig[i] = FV;
|
||||
}
|
||||
return m_tmp_sig;
|
||||
case OpFCallBuiltin: //TWO(IVA, SA) CVMANY, ONE(RV)
|
||||
case OpCreateCl: // TWO(IVA,SA), CVMANY, ONE(CV)
|
||||
for (int i = 0, n = instrNumPops(pc); i < n; ++i) {
|
||||
m_tmp_sig[i] = CVV;
|
||||
}
|
||||
return m_tmp_sig;
|
||||
case OpNewTuple: // ONE(IVA), CMANY, ONE(CV)
|
||||
for (int i = 0, n = instrNumPops(pc); i < n; ++i) {
|
||||
m_tmp_sig[i] = CV;
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário