Bug 1583172 part 2 - Add baselineFrameNumValueSlots method to JSJitFrameIter and use it in a few places. r=tcampbell
☠☠ backed out by 3954181d6538 ☠ ☠
authorJan de Mooij <jdemooij@mozilla.com>
Tue, 01 Oct 2019 13:55:44 +0000
changeset 495894 e94031916ebf60d2b2e69217daf7e122aa69bf56
parent 495893 92dca2ee7dd353141a7f659b4b7b12ed1bb7b76d
child 495895 71e47d3ce0f391c16c5faad8535d3977e3d5da26
push id114140
push userdvarga@mozilla.com
push dateWed, 02 Oct 2019 18:04:51 +0000
treeherdermozilla-inbound@32eb0ea893f3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstcampbell
bugs1583172
milestone71.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 1583172 part 2 - Add baselineFrameNumValueSlots method to JSJitFrameIter and use it in a few places. r=tcampbell This just forwards to BaselineFrame for now but that will change. Differential Revision: https://phabricator.services.mozilla.com/D46912
js/src/jit/BaselineFrame.cpp
js/src/jit/JSJitFrameIter-inl.h
js/src/jit/JSJitFrameIter.cpp
js/src/jit/JSJitFrameIter.h
js/src/jit/JitFrames.cpp
js/src/vm/Stack.cpp
--- a/js/src/jit/BaselineFrame.cpp
+++ b/js/src/jit/BaselineFrame.cpp
@@ -61,30 +61,33 @@ void BaselineFrame::trace(JSTracer* trc,
 
   // Trace locals and stack values.
   JSScript* script = this->script();
   size_t nfixed = script->nfixed();
   jsbytecode* pc;
   frameIterator.baselineScriptAndPc(nullptr, &pc);
   size_t nlivefixed = script->calculateLiveFixed(pc);
 
-  // NB: It is possible that numValueSlots() could be zero, even if nfixed is
-  // nonzero.  This is the case if the function has an early stack check.
-  if (numValueSlots() == 0) {
+  uint32_t numValueSlots = frameIterator.baselineFrameNumValueSlots();
+
+  // NB: It is possible that numValueSlots could be zero, even if nfixed is
+  // nonzero.  This is the case when we're initializing the environment chain or
+  // failed the prologue stack check.
+  if (numValueSlots == 0) {
     return;
   }
 
-  MOZ_ASSERT(nfixed <= numValueSlots());
+  MOZ_ASSERT(nfixed <= numValueSlots);
 
   if (nfixed == nlivefixed) {
     // All locals are live.
-    TraceLocals(this, trc, 0, numValueSlots());
+    TraceLocals(this, trc, 0, numValueSlots);
   } else {
     // Trace operand stack.
-    TraceLocals(this, trc, nfixed, numValueSlots());
+    TraceLocals(this, trc, nfixed, numValueSlots);
 
     // Clear dead block-scoped locals.
     while (nfixed > nlivefixed) {
       unaliasedLocal(--nfixed).setUndefined();
     }
 
     // Trace live locals.
     TraceLocals(this, trc, 0, nlivefixed);
--- a/js/src/jit/JSJitFrameIter-inl.h
+++ b/js/src/jit/JSJitFrameIter-inl.h
@@ -46,16 +46,21 @@ inline JSScript* JSJitProfilingFrameIter
 }
 
 inline BaselineFrame* JSJitFrameIter::baselineFrame() const {
   MOZ_ASSERT(isBaselineJS());
   return (BaselineFrame*)(fp() - BaselineFrame::FramePointerOffset -
                           BaselineFrame::Size());
 }
 
+inline uint32_t JSJitFrameIter::baselineFrameNumValueSlots() const {
+  MOZ_ASSERT(isBaselineJS());
+  return baselineFrame()->numValueSlots();
+}
+
 template <typename T>
 bool JSJitFrameIter::isExitFrameLayout() const {
   if (!isExitFrame()) {
     return false;
   }
   return exitFrame()->is<T>();
 }
 
--- a/js/src/jit/JSJitFrameIter.cpp
+++ b/js/src/jit/JSJitFrameIter.cpp
@@ -297,22 +297,20 @@ void JSJitFrameIter::dumpBaseline() cons
   baselineScriptAndPc(script.address(), &pc);
 
   fprintf(stderr, "  script = %p, pc = %p (offset %u)\n", (void*)script, pc,
           uint32_t(script->pcToOffset(pc)));
   fprintf(stderr, "  current op: %s\n", CodeName[*pc]);
 
   fprintf(stderr, "  actual args: %d\n", numActualArgs());
 
-  BaselineFrame* frame = baselineFrame();
-
-  for (unsigned i = 0; i < frame->numValueSlots(); i++) {
+  for (unsigned i = 0; i < baselineFrameNumValueSlots(); i++) {
     fprintf(stderr, "  slot %u: ", i);
 #if defined(DEBUG) || defined(JS_JITSPEW)
-    Value* v = frame->valueSlot(i);
+    Value* v = baselineFrame()->valueSlot(i);
     DumpValue(*v);
 #else
     fprintf(stderr, "?\n");
 #endif
   }
 }
 
 void JSJitFrameIter::dump() const {
--- a/js/src/jit/JSJitFrameIter.h
+++ b/js/src/jit/JSJitFrameIter.h
@@ -24,17 +24,17 @@ namespace jit {
 typedef void* CalleeToken;
 
 enum class FrameType {
   // A JS frame is analogous to a js::InterpreterFrame, representing one
   // scripted function activation. IonJS frames are used by the optimizing
   // compiler.
   IonJS,
 
-  // JS frame used by the baseline JIT.
+  // JS frame used by the Baseline Interpreter and Baseline JIT.
   BaselineJS,
 
   // Frame pushed by Baseline stubs that make non-tail calls, so that the
   // return address -> ICEntry mapping works.
   BaselineStub,
 
   // The entry frame is the initial prologue block transitioning from the VM
   // into the Ion world.
@@ -251,16 +251,20 @@ class JSJitFrameIter {
       op(argv[i]);
     }
   }
 
   void dump() const;
 
   inline BaselineFrame* baselineFrame() const;
 
+  // Returns the number of local and expression stack Values for the current
+  // Baseline frame.
+  inline uint32_t baselineFrameNumValueSlots() const;
+
   // This function isn't used, but we keep it here (debug-only) because it is
   // helpful when chasing issues with the jitcode map.
 #ifdef DEBUG
   bool verifyReturnAddressUsingNativeToBytecodeMap();
 #else
   bool verifyReturnAddressUsingNativeToBytecodeMap() { return true; }
 #endif
 };
--- a/js/src/jit/JitFrames.cpp
+++ b/js/src/jit/JitFrames.cpp
@@ -286,39 +286,43 @@ static void SettleOnTryNote(JSContext* c
   BaselineFrameAndStackPointersFromTryNote(tn, frame, &rfe->framePointer,
                                            &rfe->stackPointer);
 
   // Compute the pc.
   *pc = script->offsetToPC(tn->start + tn->length);
 }
 
 class BaselineTryNoteFilter {
-  BaselineFrame* frame_;
+  const JSJitFrameIter& frame_;
 
  public:
-  explicit BaselineTryNoteFilter(BaselineFrame* frame) : frame_(frame) {}
+  explicit BaselineTryNoteFilter(const JSJitFrameIter& frame) : frame_(frame) {}
   bool operator()(const JSTryNote* note) {
-    MOZ_ASSERT(frame_->numValueSlots() >= frame_->script()->nfixed());
-    uint32_t currDepth = frame_->numValueSlots() - frame_->script()->nfixed();
+    BaselineFrame* frame = frame_.baselineFrame();
+
+    uint32_t numValueSlots = frame_.baselineFrameNumValueSlots();
+    MOZ_ASSERT(numValueSlots >= frame->script()->nfixed());
+
+    uint32_t currDepth = numValueSlots - frame->script()->nfixed();
     return note->stackDepth <= currDepth;
   }
 };
 
 class TryNoteIterBaseline : public TryNoteIter<BaselineTryNoteFilter> {
  public:
-  TryNoteIterBaseline(JSContext* cx, BaselineFrame* frame, jsbytecode* pc)
-      : TryNoteIter(cx, frame->script(), pc, BaselineTryNoteFilter(frame)) {}
+  TryNoteIterBaseline(JSContext* cx, const JSJitFrameIter& frame,
+                      jsbytecode* pc)
+      : TryNoteIter(cx, frame.script(), pc, BaselineTryNoteFilter(frame)) {}
 };
 
 // Close all live iterators on a BaselineFrame due to exception unwinding. The
 // pc parameter is updated to where the envs have been unwound to.
 static void CloseLiveIteratorsBaselineForUncatchableException(
     JSContext* cx, const JSJitFrameIter& frame, jsbytecode* pc) {
-  for (TryNoteIterBaseline tni(cx, frame.baselineFrame(), pc); !tni.done();
-       ++tni) {
+  for (TryNoteIterBaseline tni(cx, frame, pc); !tni.done(); ++tni) {
     const JSTryNote* tn = *tni;
     switch (tn->kind) {
       case JSTRY_FOR_IN: {
         uint8_t* framePointer;
         uint8_t* stackPointer;
         BaselineFrameAndStackPointersFromTryNote(tn, frame, &framePointer,
                                                  &stackPointer);
         Value iterValue(*(Value*)stackPointer);
@@ -336,18 +340,17 @@ static void CloseLiveIteratorsBaselineFo
 static bool ProcessTryNotesBaseline(JSContext* cx, const JSJitFrameIter& frame,
                                     EnvironmentIter& ei,
                                     ResumeFromException* rfe, jsbytecode** pc) {
   MOZ_ASSERT(frame.baselineFrame()->runningInInterpreter(),
              "Caller must ensure frame is an interpreter frame");
 
   RootedScript script(cx, frame.baselineFrame()->script());
 
-  for (TryNoteIterBaseline tni(cx, frame.baselineFrame(), *pc); !tni.done();
-       ++tni) {
+  for (TryNoteIterBaseline tni(cx, frame, *pc); !tni.done(); ++tni) {
     const JSTryNote* tn = *tni;
 
     MOZ_ASSERT(cx->isExceptionPending());
     switch (tn->kind) {
       case JSTRY_CATCH: {
         // If we're closing a legacy generator, we have to skip catch
         // blocks.
         if (cx->isClosingGenerator()) {
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -1391,18 +1391,18 @@ size_t FrameIter::numFrameSlots() const 
   switch (data_.state_) {
     case DONE:
       break;
     case JIT: {
       if (isIonScripted()) {
         return ionInlineFrames_.snapshotIterator().numAllocations() -
                ionInlineFrames_.script()->nfixed();
       }
-      jit::BaselineFrame* frame = jsJitFrame().baselineFrame();
-      return frame->numValueSlots() - jsJitFrame().script()->nfixed();
+      uint32_t numValueSlots = jsJitFrame().baselineFrameNumValueSlots();
+      return numValueSlots - jsJitFrame().script()->nfixed();
     }
     case INTERP:
       MOZ_ASSERT(data_.interpFrames_.sp() >= interpFrame()->base());
       return data_.interpFrames_.sp() - interpFrame()->base();
   }
   MOZ_CRASH("Unexpected state");
 }