Bug 1422043: Don't use LookupCode for the interpreter entry in wasm profiling iteration; r=luke
authorBenjamin Bouvier <benj@benj.me>
Thu, 15 Feb 2018 19:26:34 +0100
changeset 404138 a274eb9c8f1f980668fb53a60e10df2b3cbb718e
parent 404137 b0db89ec8e9700b63779372d473c91900e6beb17
child 404139 0be0607b050e9eeaff114166618b0e486dcaa79b
push id99939
push userbbouvier@mozilla.com
push dateFri, 16 Feb 2018 10:00:41 +0000
treeherdermozilla-inbound@a274eb9c8f1f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1422043
milestone60.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1422043: Don't use LookupCode for the interpreter entry in wasm profiling iteration; r=luke MozReview-Commit-ID: 5Jb0rio2gMi
js/src/wasm/WasmFrameIter.cpp
js/src/wasm/WasmFrameIter.h
--- a/js/src/wasm/WasmFrameIter.cpp
+++ b/js/src/wasm/WasmFrameIter.cpp
@@ -727,16 +727,18 @@ ProfilingFrameIterator::initFromExitFP(c
     //  - for Math and other builtin calls as well as interrupts, we note the
     //    absence of an exit reason and inject a fake "builtin" frame; and
     //  - for async interrupts, we just accept that we'll lose the innermost
     //    frame.
     switch (codeRange_->kind()) {
       case CodeRange::InterpEntry:
         callerPC_ = nullptr;
         callerFP_ = nullptr;
+        codeRange_ = nullptr;
+        exitReason_ = ExitReason(ExitReason::Fixed::FakeInterpEntry);
         break;
       case CodeRange::JitEntry:
         callerPC_ = nullptr;
         callerFP_ = nullptr;
         unwoundIonCallerFP_ = (uint8_t*) fp->callerFP;
         break;
       case CodeRange::Function:
         fp = fp->callerFP;
@@ -997,29 +999,35 @@ ProfilingFrameIterator::ProfilingFrameIt
     } else {
         callerFP_ = unwindState.fp->callerFP;
         callerPC_ = unwindState.fp->returnAddress;
     }
 
     if (unwindState.codeRange->isJitEntry())
         unwoundIonCallerFP_ = (uint8_t*) callerFP_;
 
+    if (unwindState.codeRange->isInterpEntry()) {
+        unwindState.codeRange = nullptr;
+        exitReason_ = ExitReason(ExitReason::Fixed::FakeInterpEntry);
+    }
+
     code_ = unwindState.code;
     codeRange_ = unwindState.codeRange;
     stackAddress_ = state.sp;
     MOZ_ASSERT(!done());
 }
 
 void
 ProfilingFrameIterator::operator++()
 {
     if (!exitReason_.isNone()) {
-        MOZ_ASSERT(codeRange_);
+        DebugOnly<ExitReason> prevExitReason = exitReason_;
         exitReason_ = ExitReason::None();
-        MOZ_ASSERT(!done());
+        MOZ_ASSERT(!codeRange_ == prevExitReason.value.isInterpEntry());
+        MOZ_ASSERT(done() == prevExitReason.value.isInterpEntry());
         return;
     }
 
     if (unwoundIonCallerFP_) {
         MOZ_ASSERT(codeRange_->isJitEntry());
         callerPC_ = nullptr;
         callerFP_ = nullptr;
         codeRange_ = nullptr;
@@ -1030,18 +1038,20 @@ ProfilingFrameIterator::operator++()
     if (!callerPC_) {
         MOZ_ASSERT(!callerFP_);
         codeRange_ = nullptr;
         MOZ_ASSERT(done());
         return;
     }
 
     if (!callerFP_) {
-        MOZ_ALWAYS_TRUE(LookupCode(callerPC_, &codeRange_) == code_);
+        MOZ_ASSERT(LookupCode(callerPC_, &codeRange_) == code_);
         MOZ_ASSERT(codeRange_->kind() == CodeRange::InterpEntry);
+        exitReason_ = ExitReason(ExitReason::Fixed::FakeInterpEntry);
+        codeRange_ = nullptr;
         callerPC_ = nullptr;
         MOZ_ASSERT(!done());
         return;
     }
 
     code_ = LookupCode(callerPC_, &codeRange_);
     MOZ_ASSERT(codeRange_);
 
@@ -1220,21 +1230,23 @@ ProfilingFrameIterator::label() const
       case ExitReason::Fixed::ImportInterp:
         return importInterpDescription;
       case ExitReason::Fixed::BuiltinNative:
         return builtinNativeDescription;
       case ExitReason::Fixed::Trap:
         return trapDescription;
       case ExitReason::Fixed::DebugTrap:
         return debugTrapDescription;
+      case ExitReason::Fixed::FakeInterpEntry:
+        return "slow entry trampoline (in wasm)";
     }
 
     switch (codeRange_->kind()) {
       case CodeRange::Function:          return code_->profilingLabel(codeRange_->funcIndex());
-      case CodeRange::InterpEntry:       return "slow entry trampoline (in wasm)";
+      case CodeRange::InterpEntry:       MOZ_CRASH("should be an ExitReason");
       case CodeRange::JitEntry:          return "fast entry trampoline (in wasm)";
       case CodeRange::ImportJitExit:     return importJitDescription;
       case CodeRange::BuiltinThunk:      return builtinNativeDescription;
       case CodeRange::ImportInterpExit:  return importInterpDescription;
       case CodeRange::TrapExit:          return trapDescription;
       case CodeRange::OldTrapExit:       return trapDescription;
       case CodeRange::DebugTrap:         return debugTrapDescription;
       case CodeRange::OutOfBoundsExit:   return "out-of-bounds stub (in wasm)";
--- a/js/src/wasm/WasmFrameIter.h
+++ b/js/src/wasm/WasmFrameIter.h
@@ -103,22 +103,23 @@ class ExitReason
 {
     uint32_t payload_;
 
     ExitReason() {}
 
   public:
     enum class Fixed : uint32_t
     {
-        None,          // default state, the pc is in wasm code
-        ImportJit,     // fast-path call directly into JIT code
-        ImportInterp,  // slow-path call into C++ Invoke()
-        BuiltinNative, // fast-path call directly into native C++ code
-        Trap,          // call to trap handler
-        DebugTrap      // call to debug trap handler
+        None,            // default state, the pc is in wasm code
+        FakeInterpEntry, // slow-path entry call from C++ WasmCall()
+        ImportJit,       // fast-path call directly into JIT code
+        ImportInterp,    // slow-path call into C++ Invoke()
+        BuiltinNative,   // fast-path call directly into native C++ code
+        Trap,            // call to trap handler
+        DebugTrap        // call to debug trap handler
     };
 
     MOZ_IMPLICIT ExitReason(Fixed exitReason)
       : payload_(0x0 | (uint32_t(exitReason) << 1))
     {
         MOZ_ASSERT(isFixed());
         MOZ_ASSERT_IF(isNone(), payload_ == 0);
     }
@@ -136,16 +137,17 @@ class ExitReason
         return reason;
     }
 
     static ExitReason None() { return ExitReason(ExitReason::Fixed::None); }
 
     bool isFixed() const { return (payload_ & 0x1) == 0; }
     bool isNone() const { return isFixed() && fixed() == Fixed::None; }
     bool isNative() const { return !isFixed() || fixed() == Fixed::BuiltinNative; }
+    bool isInterpEntry() const { return isFixed() && fixed() == Fixed::FakeInterpEntry; }
 
     uint32_t encode() const {
         return payload_;
     }
     Fixed fixed() const {
         MOZ_ASSERT(isFixed());
         return Fixed(payload_ >> 1);
     }
@@ -181,17 +183,17 @@ class ProfilingFrameIterator
     ProfilingFrameIterator(const jit::JitActivation& activation, const Frame* fp);
 
     // Start unwinding at the innermost activation given the register state when
     // the thread was suspended.
     ProfilingFrameIterator(const jit::JitActivation& activation,
                            const JS::ProfilingFrameIterator::RegisterState& state);
 
     void operator++();
-    bool done() const { return !codeRange_; }
+    bool done() const { return !codeRange_ && exitReason_.isNone(); }
 
     void* stackAddress() const { MOZ_ASSERT(!done()); return stackAddress_; }
     uint8_t* unwoundIonCallerFP() const { MOZ_ASSERT(done()); return unwoundIonCallerFP_; }
     const char* label() const;
 };
 
 // Prologue/epilogue code generation