From a686bd4ca1fe63853989b2e10b6cc30816a2e9de Mon Sep 17 00:00:00 2001 From: aravind Date: Fri, 31 May 2013 12:26:29 -0700 Subject: [PATCH] Remove BPass* instructions --- hphp/compiler/analysis/emitter.cpp | 38 +++++++++++++++---- hphp/compiler/analysis/emitter.h | 1 + hphp/doc/bytecode.specification | 16 +------- hphp/runtime/vm/as.cpp | 2 + hphp/runtime/vm/bytecode.cpp | 10 ----- hphp/runtime/vm/hhbc.cpp | 2 + hphp/runtime/vm/hhbc.h | 7 ++-- .../vm/translator/hopt/irtranslator.cpp | 12 ------ hphp/runtime/vm/translator/translator-x64.h | 2 - hphp/runtime/vm/translator/translator.cpp | 2 - hphp/runtime/vm/verifier/check_func.cpp | 13 +++++-- 11 files changed, 51 insertions(+), 54 deletions(-) diff --git a/hphp/compiler/analysis/emitter.cpp b/hphp/compiler/analysis/emitter.cpp index 2c3a532a9..c628823ca 100644 --- a/hphp/compiler/analysis/emitter.cpp +++ b/hphp/compiler/analysis/emitter.cpp @@ -286,6 +286,7 @@ static int32_t countStackValues(const std::vector& 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& 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& 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, diff --git a/hphp/compiler/analysis/emitter.h b/hphp/compiler/analysis/emitter.h index 742a052de..b7ef219b6 100644 --- a/hphp/compiler/analysis/emitter.h +++ b/hphp/compiler/analysis/emitter.h @@ -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); diff --git a/hphp/doc/bytecode.specification b/hphp/doc/bytecode.specification index d14baec2a..a98da49b5 100644 --- a/hphp/doc/bytecode.specification +++ b/hphp/doc/bytecode.specification @@ -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 [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 [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 [F..F] -> [R] Optimized builtin call without an ActRec. This instruction attempts to diff --git a/hphp/runtime/vm/as.cpp b/hphp/runtime/vm/as.cpp index c6cf5942e..3eb36a884 100644 --- a/hphp/runtime/vm/as.cpp +++ b/hphp/runtime/vm/as.cpp @@ -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() { diff --git a/hphp/runtime/vm/bytecode.cpp b/hphp/runtime/vm/bytecode.cpp index 88ffb96a1..952fe0ca4 100644 --- a/hphp/runtime/vm/bytecode.cpp +++ b/hphp/runtime/vm/bytecode.cpp @@ -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); diff --git a/hphp/runtime/vm/hhbc.cpp b/hphp/runtime/vm/hhbc.cpp index 3e08b5de6..f51145370 100644 --- a/hphp/runtime/vm/hhbc.cpp +++ b/hphp/runtime/vm/hhbc.cpp @@ -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 }; diff --git a/hphp/runtime/vm/hhbc.h b/hphp/runtime/vm/hhbc.h index 0e834aaba..61956c993 100644 --- a/hphp/runtime/vm/hhbc.h +++ b/hphp/runtime/vm/hhbc.h @@ -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) \ diff --git a/hphp/runtime/vm/translator/hopt/irtranslator.cpp b/hphp/runtime/vm/translator/hopt/irtranslator.cpp index 45ba7c124..5f84be491 100644 --- a/hphp/runtime/vm/translator/hopt/irtranslator.cpp +++ b/hphp/runtime/vm/translator/hopt/irtranslator.cpp @@ -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) { diff --git a/hphp/runtime/vm/translator/translator-x64.h b/hphp/runtime/vm/translator/translator-x64.h index 6887993b4..7ef5627f2 100644 --- a/hphp/runtime/vm/translator/translator-x64.h +++ b/hphp/runtime/vm/translator/translator-x64.h @@ -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. diff --git a/hphp/runtime/vm/translator/translator.cpp b/hphp/runtime/vm/translator/translator.cpp index 7a442c464..ee0869dfc 100644 --- a/hphp/runtime/vm/translator/translator.cpp +++ b/hphp/runtime/vm/translator/translator.cpp @@ -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. diff --git a/hphp/runtime/vm/verifier/check_func.cpp b/hphp/runtime/vm/verifier/check_func.cpp index 0ea82df8c..f34ebfd81 100644 --- a/hphp/runtime/vm/verifier/check_func.cpp +++ b/hphp/runtime/vm/verifier/check_func.cpp @@ -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;