Bug 1403438 - Add profiler-lul on mips64-linux. r=sewardj

--HG--
extra : rebase_source : 9f507b59a77785d60a0944baf4dad27ec7d2e1c7
This commit is contained in:
qiaopengcheng 2017-09-28 02:04:00 -04:00
parent bd8a2fdfb5
commit be9033b5a9
9 changed files with 174 additions and 2 deletions

View File

@ -107,7 +107,7 @@
#endif
// Linux builds use LUL, which uses DWARF info to unwind stacks.
#if defined(GP_PLAT_amd64_linux) || defined(GP_PLAT_x86_linux)
#if defined(GP_PLAT_amd64_linux) || defined(GP_PLAT_x86_linux) || defined(GP_PLAT_mips64_linux)
# define HAVE_NATIVE_UNWIND
# define USE_LUL_STACKWALK
# include "lul/LulMain.h"

View File

@ -1856,6 +1856,21 @@ unsigned int DwarfCFIToModule::RegisterNames::ARM() {
return 13 * 8;
}
unsigned int DwarfCFIToModule::RegisterNames::MIPS() {
/*
8 "$zero", "$at", "$v0", "$v1", "$a0", "$a1", "$a2", "$a3",
8 "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7",
8 "$s0", "$s1", "$s2", "$s3", "$s4", "$s5", "$s6", "$s7",
8 "$t8", "$t9", "$k0", "$k1", "$gp", "$sp", "$fp", "$ra",
9 "$lo", "$hi", "$pc", "$f0", "$f1", "$f2", "$f3", "$f4", "$f5",
8 "$f6", "$f7", "$f8", "$f9", "$f10", "$f11", "$f12", "$f13",
7 "$f14", "$f15", "$f16", "$f17", "$f18", "$f19", "$f20",
7 "$f21", "$f22", "$f23", "$f24", "$f25", "$f26", "$f27",
6 "$f28", "$f29", "$f30", "$f31", "$fcsr", "$fir"
*/
return 8 + 8 + 8 + 8 + 9 + 8 + 7 + 7 + 6;
}
// See prototype for comments.
int32_t parseDwarfExpr(Summariser* summ, const ByteReader* reader,
string expr, bool debug,

View File

@ -1210,6 +1210,9 @@ class DwarfCFIToModule: public CallFrameInfo::Handler {
// ARM.
static unsigned int ARM();
// MIPS.
static unsigned int MIPS();
};
// Create a handler for the dwarf2reader::CallFrameInfo parser that

View File

@ -329,6 +329,79 @@ Summariser::Rule(uintptr_t aAddress, int aNewReg,
mCurrRules.mXbpExpr = LExpr(NODEREF, DW_REG_INTEL_XBP, 0);
}
#elif defined(GP_ARCH_mips64)
// ---------------- mips ---------------- //
//
// Now, can we add the rule to our summary? This depends on whether
// the registers and the overall expression are representable. This
// is the heart of the summarisation process.
switch (aNewReg) {
case DW_REG_CFA:
// This is a rule that defines the CFA. The only forms we can
// represent are: = SP+offset or = FP+offset.
if (how != NODEREF) {
reason1 = "rule for DW_REG_CFA: invalid |how|";
goto cant_summarise;
}
if (oldReg != DW_REG_MIPS_SP && oldReg != DW_REG_MIPS_FP) {
reason1 = "rule for DW_REG_CFA: invalid |oldReg|";
goto cant_summarise;
}
mCurrRules.mCfaExpr = LExpr(how, oldReg, offset);
break;
case DW_REG_MIPS_SP: case DW_REG_MIPS_FP: case DW_REG_MIPS_PC: {
// This is a new rule for SP, FP or PC (the return address).
switch (how) {
case NODEREF: case DEREF:
// Check the old register is one we're tracking.
if (!registerIsTracked((DW_REG_NUMBER)oldReg) &&
oldReg != DW_REG_CFA) {
reason1 = "rule for SP/FP/PC: uses untracked reg";
goto cant_summarise;
}
break;
case PFXEXPR: {
// Check that the prefix expression only mentions tracked registers.
const vector<PfxInstr>* pfxInstrs = mSecMap->GetPfxInstrs();
reason2 = checkPfxExpr(pfxInstrs, offset);
if (reason2) {
reason1 = "rule for SP/FP/PC: ";
goto cant_summarise;
}
break;
}
default:
goto cant_summarise;
}
LExpr expr = LExpr(how, oldReg, offset);
switch (aNewReg) {
case DW_REG_MIPS_FP: mCurrRules.mFPexpr = expr; break;
case DW_REG_MIPS_SP: mCurrRules.mSPexpr = expr; break;
case DW_REG_MIPS_PC: mCurrRules.mPCexpr = expr; break;
default: MOZ_CRASH("impossible value for aNewReg");
}
break;
}
default:
// Leave |reason1| and |reason2| unset here, for the reasons
// explained in the analogous point in the ARM case just above.
goto cant_summarise;
}
// On MIPS, it seems the old SP value before the call is always the
// same as the CFA. Therefore, in the absence of any other way to
// recover the SP, specify that the CFA should be copied.
if (mCurrRules.mSPexpr.mHow == UNKNOWN) {
mCurrRules.mSPexpr = LExpr(NODEREF, DW_REG_CFA, 0);
}
// Also, gcc says "Undef" for FP when it is unchanged.
if (mCurrRules.mFPexpr.mHow == UNKNOWN) {
mCurrRules.mFPexpr = LExpr(NODEREF, DW_REG_MIPS_FP, 0);
}
#else
# error "Unsupported arch"

View File

@ -164,6 +164,9 @@ bool DwarfCFIRegisterNames(const typename ElfClass::Ehdr* elf_header,
case EM_X86_64:
*num_dw_regnames = DwarfCFIToModule::RegisterNames::X86_64();
return true;
case EM_MIPS:
*num_dw_regnames = DwarfCFIToModule::RegisterNames::MIPS();
return true;
default:
MOZ_ASSERT(0);
return false;

View File

@ -73,6 +73,10 @@ NameOf_DW_REG(int16_t aReg)
case DW_REG_ARM_R13: return "r13";
case DW_REG_ARM_R14: return "r14";
case DW_REG_ARM_R15: return "r15";
#elif defined(GP_ARCH_mips64)
case DW_REG_MIPS_SP: return "sp";
case DW_REG_MIPS_FP: return "fp";
case DW_REG_MIPS_PC: return "pc";
#else
# error "Unsupported arch"
#endif
@ -132,6 +136,10 @@ RuleSet::Print(void(*aLog)(const char*)) const
res += mR12expr.ShowRule(" R12");
res += mR13expr.ShowRule(" R13");
res += mR14expr.ShowRule(" R14");
#elif defined(GP_ARCH_mips64)
res += mPCexpr.ShowRule(" PC");
res += mSPexpr.ShowRule(" SP");
res += mFPexpr.ShowRule(" FP");
#else
# error "Unsupported arch"
#endif
@ -153,6 +161,10 @@ RuleSet::ExprForRegno(DW_REG_NUMBER aRegno) {
case DW_REG_ARM_R12: return &mR12expr;
case DW_REG_ARM_R11: return &mR11expr;
case DW_REG_ARM_R7: return &mR7expr;
#elif defined(GP_ARCH_mips64)
case DW_REG_MIPS_SP: return &mSPexpr;
case DW_REG_MIPS_FP: return &mFPexpr;
case DW_REG_MIPS_PC: return &mPCexpr;
# else
# error "Unknown arch"
# endif
@ -902,6 +914,10 @@ TaggedUWord EvaluateReg(int16_t aReg, const UnwindRegs* aOldRegs,
case DW_REG_ARM_R13: return aOldRegs->r13;
case DW_REG_ARM_R14: return aOldRegs->r14;
case DW_REG_ARM_R15: return aOldRegs->r15;
#elif defined(GP_ARCH_mips64)
case DW_REG_MIPS_SP: return aOldRegs->sp;
case DW_REG_MIPS_FP: return aOldRegs->fp;
case DW_REG_MIPS_PC: return aOldRegs->pc;
#else
# error "Unsupported arch"
#endif
@ -1094,6 +1110,10 @@ void UseRuleSet(/*MOD*/UnwindRegs* aRegs,
aRegs->r13 = TaggedUWord();
aRegs->r14 = TaggedUWord();
aRegs->r15 = TaggedUWord();
#elif defined(GP_ARCH_mips64)
aRegs->sp = TaggedUWord();
aRegs->fp = TaggedUWord();
aRegs->pc = TaggedUWord();
#else
# error "Unsupported arch"
#endif
@ -1131,6 +1151,13 @@ void UseRuleSet(/*MOD*/UnwindRegs* aRegs,
= aRS->mR14expr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
aRegs->r15
= aRS->mR15expr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
#elif defined(GP_ARCH_mips64)
aRegs->sp
= aRS->mSPexpr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
aRegs->fp
= aRS->mFPexpr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
aRegs->pc
= aRS->mPCexpr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
#else
# error "Unsupported arch"
#endif
@ -1183,6 +1210,14 @@ LUL::Unwind(/*OUT*/uintptr_t* aFramePCs,
(int)regs.r14.Valid(), (unsigned long long int)regs.r14.Value());
buf[sizeof(buf)-1] = 0;
mLog(buf);
#elif defined(GP_ARCH_mips64)
SprintfLiteral(buf,
"LoopTop: pc %d/%llx sp %d/%llx fp %d/%llx\n",
(int)regs.pc.Valid(), (unsigned long long int)regs.pc.Value(),
(int)regs.sp.Valid(), (unsigned long long int)regs.sp.Value(),
(int)regs.fp.Valid(), (unsigned long long int)regs.fp.Value());
buf[sizeof(buf)-1] = 0;
mLog(buf);
#else
# error "Unsupported arch"
#endif
@ -1194,6 +1229,9 @@ LUL::Unwind(/*OUT*/uintptr_t* aFramePCs,
#elif defined(GP_ARCH_arm)
TaggedUWord ia = (*aFramesUsed == 0 ? regs.r15 : regs.r14);
TaggedUWord sp = regs.r13;
#elif defined(GP_ARCH_mips64)
TaggedUWord ia = regs.pc;
TaggedUWord sp = regs.sp;
#else
# error "Unsupported arch"
#endif
@ -1410,6 +1448,15 @@ LUL::Unwind(/*OUT*/uintptr_t* aFramePCs,
static const int LUL_UNIT_TEST_STACK_SIZE = 16384;
#if defined(GP_ARCH_mips64)
static __attribute__((noinline))
unsigned long __getpc(void) {
unsigned long rtaddr;
__asm__ volatile ("move %0, $31" : "=r"(rtaddr));
return rtaddr;
}
#endif
// This function is innermost in the test call sequence. It uses LUL
// to unwind, and compares the result with the sequence specified in
// the director string. These need to agree in order for the test to
@ -1480,6 +1527,22 @@ bool GetAndCheckStackTrace(LUL* aLUL, const char* dstring)
startRegs.r7 = TaggedUWord(block[5]);
const uintptr_t REDZONE_SIZE = 0;
uintptr_t start = block[1] - REDZONE_SIZE;
#elif defined(GP_ARCH_mips64)
volatile uintptr_t block[3];
MOZ_ASSERT(sizeof(block) == 24);
__asm__ __volatile__(
"sd $29, 8(%0) \n"
"sd $30, 16(%0) \n"
:
:"r"(block)
:"memory"
);
block[0] = __getpc();
startRegs.pc = TaggedUWord(block[0]);
startRegs.sp = TaggedUWord(block[1]);
startRegs.fp = TaggedUWord(block[2]);
const uintptr_t REDZONE_SIZE = 0;
uintptr_t start = block[1] - REDZONE_SIZE;
#else
# error "Unsupported platform"
#endif

View File

@ -152,6 +152,10 @@ struct UnwindRegs {
TaggedUWord xbp;
TaggedUWord xsp;
TaggedUWord xip;
#elif defined(GP_ARCH_mips64)
TaggedUWord sp;
TaggedUWord fp;
TaggedUWord pc;
#else
# error "Unknown plat"
#endif

View File

@ -53,6 +53,10 @@ enum DW_REG_NUMBER {
DW_REG_INTEL_XBP = 5,
DW_REG_INTEL_XSP = 4,
DW_REG_INTEL_XIP = 8,
#elif defined(GP_ARCH_mips64)
DW_REG_MIPS_SP = 29,
DW_REG_MIPS_FP = 30,
DW_REG_MIPS_PC = 34,
#else
# error "Unknown arch"
#endif
@ -275,6 +279,10 @@ public:
LExpr mR12expr;
LExpr mR11expr;
LExpr mR7expr;
#elif defined(GP_ARCH_mips64)
LExpr mPCexpr;
LExpr mFPexpr;
LExpr mSPexpr;
#else
# error "Unknown arch"
#endif
@ -291,6 +299,9 @@ static inline bool registerIsTracked(DW_REG_NUMBER reg) {
case DW_REG_ARM_R7: case DW_REG_ARM_R11: case DW_REG_ARM_R12:
case DW_REG_ARM_R13: case DW_REG_ARM_R14: case DW_REG_ARM_R15:
return true;
#elif defined(GP_ARCH_mips64)
case DW_REG_MIPS_FP: case DW_REG_MIPS_SP: case DW_REG_MIPS_PC:
return true;
# else
# error "Unknown arch"
# endif

View File

@ -47,7 +47,7 @@ if CONFIG['MOZ_GECKO_PROFILER']:
]
if CONFIG['OS_TARGET'] in ('Android', 'Linux'):
if CONFIG['CPU_ARCH'] in ('arm', 'x86', 'x86_64'):
if CONFIG['CPU_ARCH'] in ('arm', 'x86', 'x86_64', 'mips64'):
UNIFIED_SOURCES += [
'lul/AutoObjectMapper.cpp',
'lul/LulCommon.cpp',