From 3f829f3edee5436c24c5cbe742d768877ddabbe3 Mon Sep 17 00:00:00 2001 From: bsimmers Date: Mon, 18 Mar 2013 16:12:23 -0700 Subject: [PATCH] Print relative offsets in Eval.JitCompareHHIR This diff adds a relativeOffsets option to Disasm, which will print code addresses as relative offsets from the beginning of the tracelet instead of absolute addresses. This format makes it much easier to compare the relative sizes of the instructions selected by the two jits. I also changed the runtime option to be a double instead of a bool, which is used as the cutoff ratio for which tracelets to print. Setting it to 1 will print tracelets where the ir made larger code than tx64, setting it to 2 will print tracelets where the ir's code is at least twice as big as tx64's, etc... --- hphp/runtime/base/runtime_option.h | 2 +- hphp/runtime/vm/bytecode.cpp | 4 +++ hphp/runtime/vm/translator/hopt/ir.cpp | 3 +- hphp/runtime/vm/translator/translator-x64.cpp | 9 ++--- hphp/util/disasm.cpp | 34 ++++++++++++++----- hphp/util/disasm.h | 30 ++++++++++++++-- 6 files changed, 64 insertions(+), 18 deletions(-) diff --git a/hphp/runtime/base/runtime_option.h b/hphp/runtime/base/runtime_option.h index cece553dd..750ce1cd8 100644 --- a/hphp/runtime/base/runtime_option.h +++ b/hphp/runtime/base/runtime_option.h @@ -409,7 +409,7 @@ public: F(bool, JitTransCounters, false) \ F(bool, JitMGeneric, true) \ F(bool, JitUseIR, false) \ - F(bool, JitCompareHHIR, false) \ + F(double, JitCompareHHIR, 0) \ F(bool, IRPuntDontInterp, false) \ F(bool, HHIRGenericDtorHelper, true) \ F(bool, HHIRCse, true) \ diff --git a/hphp/runtime/vm/bytecode.cpp b/hphp/runtime/vm/bytecode.cpp index cb4db2e07..e0062ba69 100644 --- a/hphp/runtime/vm/bytecode.cpp +++ b/hphp/runtime/vm/bytecode.cpp @@ -1910,6 +1910,10 @@ static int exception_handler() { } catch (Exception &e) { pushFault(Fault::CppException, e.clone()); longJmpType = g_vmContext->hhvmPrepareThrow(); + } catch (std::exception& e) { + pushFault(Fault::CppException, + new Exception("unexpected %s: %s", typeid(e).name(), e.what())); + longJmpType = g_vmContext->hhvmPrepareThrow(); } catch (...) { pushFault(Fault::CppException, new Exception("unknown exception")); diff --git a/hphp/runtime/vm/translator/hopt/ir.cpp b/hphp/runtime/vm/translator/hopt/ir.cpp index 489cc0c0f..afe723d5b 100644 --- a/hphp/runtime/vm/translator/hopt/ir.cpp +++ b/hphp/runtime/vm/translator/hopt/ir.cpp @@ -1067,7 +1067,8 @@ void Trace::print() const { void Trace::print(std::ostream& os, const AsmInfo* asmInfo) const { static const int kIndent = 4; - Disasm disasm(kIndent + 4, RuntimeOption::EvalDumpIR > 5); + Disasm disasm(Disasm::Options().indent(kIndent + 4) + .printEncoding(RuntimeOption::EvalDumpIR > 5)); // Print unlikely blocks at the end BlockList blocks, unlikely; diff --git a/hphp/runtime/vm/translator/translator-x64.cpp b/hphp/runtime/vm/translator/translator-x64.cpp index 2aeeaf70b..f8a14afc5 100644 --- a/hphp/runtime/vm/translator/translator-x64.cpp +++ b/hphp/runtime/vm/translator/translator-x64.cpp @@ -11475,7 +11475,7 @@ TranslatorX64::translateTracelet(SrcKey sk, bool considerHHIR/*=true*/, if (transKind == TransNormalIR && RuntimeOption::EvalJitCompareHHIR) { m_useHHIR = false; - Disasm disasm; + Disasm disasm(Disasm::Options().relativeOffset(true)); TCA irEnd = a.code.frontier; TCA irStubsEnd = astubs.code.frontier; TCA tx64Start = a.code.frontier; @@ -11484,15 +11484,16 @@ TranslatorX64::translateTracelet(SrcKey sk, bool considerHHIR/*=true*/, size_t irSize = irEnd - start; size_t tx64Size = tx64End - tx64Start; - if (irSize > tx64Size) { + 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 = {}% ", - 100 * irSize / tx64Size)); + int(100 * ratio))); t.print(out); out << '\n'; # define IRCOL "{:<90}" -# define TXCOL "{:<55}" +# define TXCOL "{:<50}" out << folly::format(TXCOL " " TXCOL "\n", folly::format("Translation from tx64 ({} bytes)", tx64Size), diff --git a/hphp/util/disasm.cpp b/hphp/util/disasm.cpp index 8ba0662aa..5dd5c5dcc 100644 --- a/hphp/util/disasm.cpp +++ b/hphp/util/disasm.cpp @@ -123,9 +123,8 @@ static int addressToSymbol(xed_uint64_t address, } #endif /* HAVE_LIBXED */ -Disasm::Disasm(int indentLevel /* = 0 */, bool printEncoding /* = false */) - : m_indent(indentLevel) - , m_printEncoding(printEncoding) +Disasm::Disasm(const Disasm::Options& opts) + : m_opts(opts) { #ifdef HAVE_LIBXED xed_state_init(&m_xedState, XED_MACHINE_MODE_LONG_64, @@ -153,6 +152,7 @@ void Disasm::disasm(std::ostream& out, uint8_t* codeStartAddr, char codeStr[MAX_INSTR_ASM_LEN]; xed_uint8_t *frontier; xed_decoded_inst_t xedd; + uint64_t codeBase = uint64_t(codeStartAddr); uint64_t ip; // Decode and print each instruction @@ -168,14 +168,30 @@ void Disasm::disasm(std::ostream& out, uint8_t* codeStartAddr, MAX_INSTR_ASM_LEN, ip, nullptr)) { error("disasm error: xed_format_context failed"); } + uint32_t instrLen = xed_decoded_inst_get_length(&xedd); - for (int i = 0; i < m_indent; ++i) { + // If it's a jump, we're printing relative offsets, and the dest + // is within the range we're printing, add the dest as a relative + // offset. + std::string jmpComment; + auto const cat = xed_decoded_inst_get_category(&xedd); + if (cat == XED_CATEGORY_COND_BR || cat == XED_CATEGORY_UNCOND_BR) { + if (m_opts.m_relativeOffset) { + auto disp = uint64_t(frontier + instrLen + + xed_decoded_inst_get_branch_displacement(&xedd) - + codeBase); + if (disp < uint64_t(codeEndAddr - codeStartAddr)) { + jmpComment = folly::format(" # {:#x}", disp).str(); + } + } + } + + for (int i = 0; i < m_opts.m_indentLevel; ++i) { out << ' '; } - out << folly::format("{:#10x}: ", ip); - - uint32_t instrLen = xed_decoded_inst_get_length(&xedd); - if (m_printEncoding) { + const char* fmt = m_opts.m_relativeOffset ? "{:3x}: " : "{:#10x}: "; + out << folly::format(fmt, ip - (m_opts.m_relativeOffset ? codeBase : 0)); + if (m_opts.m_printEncoding) { // print encoding, like in objdump unsigned posi = 0; for (; posi < instrLen; ++posi) { @@ -185,7 +201,7 @@ void Disasm::disasm(std::ostream& out, uint8_t* codeStartAddr, out << " "; } } - out << codeStr << std::endl; + out << codeStr << jmpComment << std::endl; frontier += instrLen; ip += instrLen; } diff --git a/hphp/util/disasm.h b/hphp/util/disasm.h index b52be4bf6..e3bbcac1d 100644 --- a/hphp/util/disasm.h +++ b/hphp/util/disasm.h @@ -30,10 +30,35 @@ namespace HPHP { class Disasm : private boost::noncopyable { public: + struct Options { + Options() + : m_indentLevel(0) + , m_printEncoding(false) + , m_relativeOffset(false) + {} + + Options& indent(int i) { + m_indentLevel = i; + return *this; + } + Options& printEncoding(bool pe) { + m_printEncoding = pe; + return *this; + } + Options& relativeOffset(bool re) { + m_relativeOffset = re; + return *this; + } + + int m_indentLevel; + bool m_printEncoding; + bool m_relativeOffset; + }; + /* Create a Disasm object. indentLevel spaces will be put at the beginning of * each line of disassembly. If printEncoding is true, the raw hex bytes of * the instructions will also be in the output. */ - explicit Disasm(int indentLevel = 0, bool printEncoding = false); + explicit Disasm(const Options& opts = Options()); /* Disassemble instructions. start should be the first byte of the region to * disassemble and end should be the first byte past the region to @@ -44,8 +69,7 @@ class Disasm : private boost::noncopyable { #ifdef HAVE_LIBXED xed_state_t m_xedState; #endif // HAVE_LIBXED - const int m_indent; - const bool m_printEncoding; + const Options m_opts; }; } // namespace HPHP