diff --git a/hphp/runtime/base/execution_context.h b/hphp/runtime/base/execution_context.h index cca704d01..a3ff8df33 100644 --- a/hphp/runtime/base/execution_context.h +++ b/hphp/runtime/base/execution_context.h @@ -487,6 +487,8 @@ private: Offset offset, Cell* c1); bool initIteratorM(PC& pc, PC& origPc, Iter* it, Offset offset, Var* v1); + void jmpSurpriseCheck(Offset o); + template void jmpOpImpl(PC& pc); #define O(name, imm, pusph, pop, flags) \ void iop##name(PC& pc); OPCODES diff --git a/hphp/runtime/base/stats.h b/hphp/runtime/base/stats.h index 28bb6e085..6ad906503 100644 --- a/hphp/runtime/base/stats.h +++ b/hphp/runtime/base/stats.h @@ -218,7 +218,7 @@ inline void inc(StatCounter stat, int n = 1) { } inline StatCounter opcodeToStatCounter(Op opc) { - assert(static_cast(OpLowInvalid) == 0); + assert(static_cast(OpLowInvalid) == 0); return StatCounter(Instr_InterpBBLowInvalid + STATS_PER_OPCODE * uint8_t(opc)); } diff --git a/hphp/runtime/vm/bytecode.cpp b/hphp/runtime/vm/bytecode.cpp index 0b4c646f5..c4eb56784 100644 --- a/hphp/runtime/vm/bytecode.cpp +++ b/hphp/runtime/vm/bytecode.cpp @@ -2019,7 +2019,7 @@ Array VMExecutionContext::debugBacktrace(bool skip /* = false */, ArrayInit frame(7); auto const curUnit = fp->m_func->unit(); - auto const curOp = *reinterpret_cast(curUnit->at(pc)); + auto const curOp = toOp(*curUnit->at(pc)); auto const isReturning = curOp == OpRetC || curOp == OpRetV; // Builtins and generators don't have a file and line number @@ -3992,58 +3992,58 @@ inline void OPTBLD_INLINE VMExecutionContext::iopFatal(PC& pc) { } } -#define JMP_SURPRISE_CHECK() \ - if (offset < 0 && UNLIKELY(Transl::TargetCache::loadConditionFlags())) { \ - SYNC(); \ - EventHook::CheckSurprise(); \ +inline void OPTBLD_INLINE VMExecutionContext::jmpSurpriseCheck(Offset offset) { + if (offset < 0 && UNLIKELY(Transl::TargetCache::loadConditionFlags())) { + EventHook::CheckSurprise(); } +} inline void OPTBLD_INLINE VMExecutionContext::iopJmp(PC& pc) { NEXT(); DECODE_JMP(Offset, offset); - JMP_SURPRISE_CHECK(); + jmpSurpriseCheck(offset); + pc += offset - 1; } -#define JMPOP(OP, VOP) do { \ - Cell* c1 = m_stack.topC(); \ - if (c1->m_type == KindOfInt64 || c1->m_type == KindOfBoolean) { \ - int64_t n = c1->m_data.num; \ - if (n OP 0) { \ - NEXT(); \ - DECODE_JMP(Offset, offset); \ - JMP_SURPRISE_CHECK(); \ - pc += offset - 1; \ - m_stack.popX(); \ - } else { \ - pc += 1 + sizeof(Offset); \ - m_stack.popX(); \ - } \ - } else { \ - if (VOP(tvCellAsCVarRef(c1))) { \ - NEXT(); \ - DECODE_JMP(Offset, offset); \ - JMP_SURPRISE_CHECK(); \ - pc += offset - 1; \ - m_stack.popC(); \ - } else { \ - pc += 1 + sizeof(Offset); \ - m_stack.popC(); \ - } \ - } \ -} while (0) +template +inline void OPTBLD_INLINE VMExecutionContext::jmpOpImpl(PC& pc) { + static_assert(op == OpJmpZ || op == OpJmpNZ, + "jmpOpImpl should only be used by JmpZ and JmpNZ"); + NEXT(); + DECODE_JMP(Offset, offset); + jmpSurpriseCheck(offset); + + Cell* c1 = m_stack.topC(); + if (c1->m_type == KindOfInt64 || c1->m_type == KindOfBoolean) { + int64_t n = c1->m_data.num; + if (op == OpJmpZ ? n == 0 : n != 0) { + pc += offset - 1; + m_stack.popX(); + } else { + pc += sizeof(Offset); + m_stack.popX(); + } + } else { + auto const condition = toBoolean(tvCellAsCVarRef(c1)); + if (op == OpJmpZ ? !condition : condition) { + pc += offset - 1; + m_stack.popC(); + } else { + pc += sizeof(Offset); + m_stack.popC(); + } + } +} inline void OPTBLD_INLINE VMExecutionContext::iopJmpZ(PC& pc) { - JMPOP(==, !toBoolean); + jmpOpImpl(pc); } inline void OPTBLD_INLINE VMExecutionContext::iopJmpNZ(PC& pc) { - JMPOP(!=, toBoolean); + jmpOpImpl(pc); } -#undef JMPOP -#undef JMP_SURPRISE_CHECK - enum class SwitchMatch { NORMAL, // value was converted to an int: match normally NONZERO, // can't be converted to an int: match first nonzero case diff --git a/hphp/test/quick/setprofile_throw.php.disable b/hphp/test/quick/setprofile_throw.php similarity index 100% rename from hphp/test/quick/setprofile_throw.php.disable rename to hphp/test/quick/setprofile_throw.php