Bug 1486731: wasm profiling: Don't look at FP's tagged bit in non-function call situations; r=luke

--HG--
extra : rebase_source : 7a7665b41ad3332aee4c4b7c9d9c8b8c1e677654
extra : amend_source : 06705b2fdab5e489f8c472ea41869e190042553f
This commit is contained in:
Benjamin Bouvier 2018-08-28 15:10:09 +02:00
Родитель b42fd5e8a5
Коммит f6e6cc5fcc
2 изменённых файлов: 46 добавлений и 8 удалений

Просмотреть файл

@ -0,0 +1,28 @@
var lfModule = new WebAssembly.Module(wasmTextToBinary(`
(module
(import "global" "func" (result i32))
(func (export "func_0") (result i32)
call 0 ;; calls the import, which is func #0
)
)
`));
enableGeckoProfiling();
enableSingleStepProfiling();
setJitCompilerOption("ion.warmup.trigger", 20);
Object.prototype[3] = 3;
var imports = {
global: {
func: function() {}
}
}
for (let i = 0; i < 100; ++i) {
for (dmod in imports)
for (dname in imports[dmod])
if (imports[dmod][dname] == undefined) {}
instance = new WebAssembly.Instance(lfModule, imports);
print(i, instance.exports.func_0());
}

Просмотреть файл

@ -910,6 +910,7 @@ js::wasm::StartUnwinding(const RegisterState& registers, UnwindState* unwindStat
// - in the process of tagging/untagging when calling into the JITs;
// make sure it's untagged.
// - tagged by an direct JIT call.
// - unreliable if it's not been set yet, in prologues.
DebugOnly<bool> fpWasTagged = uintptr_t(registers.fp) & ExitOrJitEntryFPTag;
Frame* const fp = (Frame*) (intptr_t(registers.fp) & ~ExitOrJitEntryFPTag);
@ -1109,7 +1110,8 @@ js::wasm::StartUnwinding(const RegisterState& registers, UnwindState* unwindStat
fixedFP = offsetFromEntry < SetJitEntryFP ? (Frame*) sp : fp;
fixedPC = nullptr;
// On the error return path, FP might be set to FailFP. Ignore these transient frames.
// On the error return path, FP might be set to FailFP. Ignore these
// transient frames.
if (intptr_t(fixedFP) == (FailFP & ~ExitOrJitEntryFPTag))
return false;
break;
@ -1156,18 +1158,26 @@ ProfilingFrameIterator::ProfilingFrameIterator(const JitActivation& activation,
if (unwoundCaller) {
callerFP_ = unwindState.fp;
callerPC_ = unwindState.pc;
// If the original FP value is tagged, then we're being called through
// a direct JIT call. We can't observe transient tagged values of FP
// (during wasm::SetExitFP) here because StartUnwinding would not have
// unwound for us in this case.
if ((uintptr_t(state.fp) & ExitOrJitEntryFPTag))
// In the case of a function call, if the original FP value is tagged,
// then we're being called through a direct JIT call (the interpreter
// and the jit entry don't set FP's low bit). We can't observe
// transient tagged values of FP (during wasm::SetExitFP) here because
// StartUnwinding would not have unwound then.
if (unwindState.codeRange &&
unwindState.codeRange->isFunction() &&
(uintptr_t(state.fp) & ExitOrJitEntryFPTag))
{
unwoundIonCallerFP_ = (uint8_t*) callerFP_;
}
} else {
callerFP_ = unwindState.fp->callerFP;
callerPC_ = unwindState.fp->returnAddress;
// See comment above.
if ((uintptr_t(callerFP_) & ExitOrJitEntryFPTag))
// See comment above. The only way to get a tagged FP here means that
// the caller is a fast JIT caller which called into a wasm function.
if ((uintptr_t(callerFP_) & ExitOrJitEntryFPTag)) {
MOZ_ASSERT(unwindState.codeRange->isFunction());
unwoundIonCallerFP_ = (uint8_t*)(uintptr_t(callerFP_) & ~ExitOrJitEntryFPTag);
}
}
if (unwindState.codeRange->isJitEntry()) {