Bug 1062869 part 5 - Add MaybeReadFallback class to record the fallback method. r=shu
authorNicolas B. Pierron <nicolas.b.pierron@mozilla.com>
Tue, 23 Sep 2014 19:42:34 +0200
changeset 206721 ac58d3ca34572d479883735680b30cc143da8c53
parent 206720 92264943548c01ca34202b4154a45f5bc2ed8fa3
child 206722 91eb93886eb1498a8eb2ecc376f3144757c6364a
push id49490
push usernpierron@mozilla.com
push dateTue, 23 Sep 2014 17:43:07 +0000
treeherdermozilla-inbound@7b268a7dc60b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersshu
bugs1062869
milestone35.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 1062869 part 5 - Add MaybeReadFallback class to record the fallback method. r=shu
js/src/jit/IonFrames.cpp
js/src/jit/JitFrameIterator.h
js/src/jit/RematerializedFrame.cpp
js/src/vm/Stack-inl.h
--- a/js/src/jit/IonFrames.cpp
+++ b/js/src/jit/IonFrames.cpp
@@ -2206,37 +2206,38 @@ InlineFrameIterator::dump() const
     fprintf(stderr, "  script = %p, pc = %p\n", (void*) script(), pc());
     fprintf(stderr, "  current op: %s\n", js_CodeName[*pc()]);
 
     if (!more()) {
         numActualArgs();
     }
 
     SnapshotIterator si = snapshotIterator();
+    MaybeReadFallback fallback(UndefinedValue());
     fprintf(stderr, "  slots: %u\n", si.numAllocations() - 1);
     for (unsigned i = 0; i < si.numAllocations() - 1; i++) {
         if (isFunction) {
             if (i == 0)
                 fprintf(stderr, "  scope chain: ");
             else if (i == 1)
                 fprintf(stderr, "  this: ");
             else if (i - 2 < callee()->nargs())
                 fprintf(stderr, "  formal (arg %d): ", i - 2);
             else {
                 if (i - 2 == callee()->nargs() && numActualArgs() > callee()->nargs()) {
                     DumpOp d(callee()->nargs());
-                    unaliasedForEachActual(GetJSContextFromJitCode(), d, ReadFrame_Overflown);
+                    unaliasedForEachActual(GetJSContextFromJitCode(), d, ReadFrame_Overflown, fallback);
                 }
 
                 fprintf(stderr, "  slot %d: ", int(i - 2 - callee()->nargs()));
             }
         } else
             fprintf(stderr, "  slot %u: ", i);
 #ifdef DEBUG
-        js_DumpValue(si.maybeRead());
+        js_DumpValue(si.maybeRead(fallback));
 #else
         fprintf(stderr, "?\n");
 #endif
     }
 
     fputc('\n', stderr);
 }
 
--- a/js/src/jit/JitFrameIterator.h
+++ b/js/src/jit/JitFrameIterator.h
@@ -289,16 +289,43 @@ class RInstructionResults
 
     IonJSFrameLayout *frame() const;
 
     RelocatableValue& operator[](size_t index);
 
     void trace(JSTracer *trc);
 };
 
+struct MaybeReadFallback
+{
+    JSContext *maybeCx;
+    JitActivation *activation;
+    JitFrameIterator *frame;
+    const Value unreadablePlaceholder;
+
+    MaybeReadFallback(const Value &placeholder = UndefinedValue())
+      : maybeCx(nullptr),
+        activation(nullptr),
+        frame(nullptr),
+        unreadablePlaceholder(placeholder)
+    {
+    }
+
+    MaybeReadFallback(JSContext *cx, JitActivation *activation, JitFrameIterator *frame)
+      : maybeCx(cx),
+        activation(activation),
+        frame(frame),
+        unreadablePlaceholder(UndefinedValue())
+    {
+    }
+
+    bool canRecoverResults() { return maybeCx; }
+};
+
+
 class RResumePoint;
 
 // Reads frame information in snapshot-encoding order (that is, outermost frame
 // to innermost frame).
 class SnapshotIterator
 {
     SnapshotReader snapshot_;
     RecoverReader recover_;
@@ -420,23 +447,25 @@ class SnapshotIterator
                      IonJSFrameLayout *fp, const MachineState &machine);
     explicit SnapshotIterator(const JitFrameIterator &iter);
     explicit SnapshotIterator(const IonBailoutIterator &iter);
     SnapshotIterator();
 
     Value read() {
         return allocationValue(readAllocation());
     }
-    Value maybeRead(const Value &placeholder = UndefinedValue(), bool silentFailure = false) {
+
+    Value maybeRead(MaybeReadFallback &fallback) {
         RValueAllocation a = readAllocation();
         if (allocationReadable(a))
             return allocationValue(a);
-        if (!silentFailure)
+
+        if (fallback.canRecoverResults())
             warnUnreadableAllocation();
-        return placeholder;
+        return fallback.unreadablePlaceholder;
     }
 
     void readCommonFrameSlots(Value *scopeChain, Value *rval) {
         if (scopeChain)
             *scopeChain = read();
         else
             skip();
 
@@ -444,18 +473,17 @@ class SnapshotIterator
             *rval = read();
         else
             skip();
     }
 
     template <class Op>
     void readFunctionFrameArgs(Op &op, ArgumentsObject **argsObj, Value *thisv,
                                unsigned start, unsigned end, JSScript *script,
-                               const Value &unreadablePlaceholder = UndefinedValue(),
-                               bool silentFailure = false)
+                               MaybeReadFallback &fallback)
     {
         // Assumes that the common frame arguments have already been read.
         if (script->argumentsHasVarBinding()) {
             if (argsObj) {
                 Value v = read();
                 if (v.isObject())
                     *argsObj = &v.toObject().as<ArgumentsObject>();
             } else {
@@ -473,28 +501,29 @@ class SnapshotIterator
             i = start;
 
         for (; i < start; i++)
             skip();
         for (; i < end; i++) {
             // We are not always able to read values from the snapshots, some values
             // such as non-gc things may still be live in registers and cause an
             // error while reading the machine state.
-            Value v = maybeRead(unreadablePlaceholder, silentFailure);
+            Value v = maybeRead(fallback);
             op(v);
         }
     }
 
     Value maybeReadAllocByIndex(size_t index) {
         while (index--) {
             JS_ASSERT(moreAllocations());
             skip();
         }
 
-        Value s = maybeRead(/* placeholder = */ UndefinedValue(), true);
+        MaybeReadFallback fallback(UndefinedValue());
+        Value s = maybeRead(fallback);
 
         while (moreAllocations())
             skip();
 
         return s;
     }
 
 #ifdef TRACK_SNAPSHOTS
@@ -561,18 +590,17 @@ class InlineFrameIterator
         return frame_->numActualArgs();
     }
 
     template <class ArgOp, class LocalOp>
     void readFrameArgsAndLocals(ThreadSafeContext *cx, ArgOp &argOp, LocalOp &localOp,
                                 JSObject **scopeChain, Value *rval,
                                 ArgumentsObject **argsObj, Value *thisv,
                                 ReadFrameArgsBehavior behavior,
-                                const Value &unreadablePlaceholder = UndefinedValue(),
-                                bool silentFailure = false) const
+                                MaybeReadFallback &fallback) const
     {
         SnapshotIterator s(si_);
 
         // Read frame slots common to both function and global frames.
         Value scopeChainValue;
         s.readCommonFrameSlots(&scopeChainValue, rval);
 
         if (scopeChain)
@@ -581,20 +609,18 @@ class InlineFrameIterator
         // Read arguments, which only function frames have.
         if (isFunctionFrame()) {
             unsigned nactual = numActualArgs();
             unsigned nformal = callee()->nargs();
 
             // Get the non overflown arguments, which are taken from the inlined
             // frame, because it will have the updated value when JSOP_SETARG is
             // done.
-            if (behavior != ReadFrame_Overflown) {
-                s.readFunctionFrameArgs(argOp, argsObj, thisv, 0, nformal, script(),
-                                        unreadablePlaceholder, silentFailure);
-            }
+            if (behavior != ReadFrame_Overflown)
+                s.readFunctionFrameArgs(argOp, argsObj, thisv, 0, nformal, script(), fallback);
 
             if (behavior != ReadFrame_Formals) {
                 if (more()) {
                     // There is still a parent frame of this inlined frame.  All
                     // arguments (also the overflown) are the last pushed values
                     // in the parent frame.  To get the overflown arguments, we
                     // need to take them from there.
 
@@ -613,17 +639,17 @@ class InlineFrameIterator
                     unsigned skip = parent_s.numAllocations() - nactual - 3 - argsObjAdj;
                     for (unsigned j = 0; j < skip; j++)
                         parent_s.skip();
 
                     // Get the overflown arguments
                     parent_s.readCommonFrameSlots(nullptr, nullptr);
                     parent_s.readFunctionFrameArgs(argOp, nullptr, nullptr,
                                                    nformal, nactual, it.script(),
-                                                   unreadablePlaceholder, silentFailure);
+                                                   fallback);
                 } else {
                     // There is no parent frame to this inlined frame, we can read
                     // from the frame's Value vector directly.
                     Value *argv = frame_->actualArgs();
                     for (unsigned i = nformal; i < nactual; i++)
                         argOp(argv[i]);
                 }
             }
@@ -632,26 +658,27 @@ class InlineFrameIterator
         // At this point we've read all the formals in s, and can read the
         // locals.
         for (unsigned i = 0; i < script()->nfixed(); i++) {
             // We have to use maybeRead here, some of these might be recover
             // instructions, and currently InlineFrameIter does not support
             // recovering slots.
             //
             // FIXME bug 1029963.
-            localOp(s.maybeRead(unreadablePlaceholder, silentFailure));
+            localOp(s.maybeRead(fallback));
         }
     }
 
     template <class Op>
     void unaliasedForEachActual(ThreadSafeContext *cx, Op op,
-                                ReadFrameArgsBehavior behavior) const
+                                ReadFrameArgsBehavior behavior,
+                                MaybeReadFallback &fallback) const
     {
         Nop nop;
-        readFrameArgsAndLocals(cx, op, nop, nullptr, nullptr, nullptr, nullptr, behavior);
+        readFrameArgsAndLocals(cx, op, nop, nullptr, nullptr, nullptr, nullptr, behavior, fallback);
     }
 
     JSScript *script() const {
         return script_;
     }
     jsbytecode *pc() const {
         return pc_;
     }
--- a/js/src/jit/RematerializedFrame.cpp
+++ b/js/src/jit/RematerializedFrame.cpp
@@ -33,19 +33,20 @@ RematerializedFrame::RematerializedFrame
   : prevUpToDate_(false),
     top_(top),
     pc_(iter.pc()),
     frameNo_(iter.frameNo()),
     numActualArgs_(numActualArgs),
     script_(iter.script())
 {
     CopyValueToRematerializedFrame op(slots_);
+    MaybeReadFallback fallback(MagicValue(JS_OPTIMIZED_OUT));
     iter.readFrameArgsAndLocals(cx, op, op, &scopeChain_, &returnValue_,
                                 &argsObj_, &thisValue_, ReadFrame_Actuals,
-                                MagicValue(JS_OPTIMIZED_OUT), /* silentFailure = */ true);
+                                fallback);
 }
 
 /* static */ RematerializedFrame *
 RematerializedFrame::New(ThreadSafeContext *cx, uint8_t *top, InlineFrameIterator &iter)
 {
     unsigned numFormals = iter.isFunctionFrame() ? iter.callee()->nargs() : 0;
     unsigned numActualArgs = Max(numFormals, iter.numActualArgs());
     size_t numBytes = sizeof(RematerializedFrame) +
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/Stack-inl.h
@@ -344,17 +344,18 @@ FrameIter::unaliasedForEachActual(JSCont
       case DONE:
       case ASMJS:
         break;
       case INTERP:
         interpFrame()->unaliasedForEachActual(op);
         return;
       case JIT:
         if (data_.jitFrames_.isIonJS()) {
-            ionInlineFrames_.unaliasedForEachActual(cx, op, jit::ReadFrame_Actuals);
+            jit::MaybeReadFallback recover(cx, activation()->asJit(), &data_.jitFrames_);
+            ionInlineFrames_.unaliasedForEachActual(cx, op, jit::ReadFrame_Actuals, recover);
         } else {
             JS_ASSERT(data_.jitFrames_.isBaselineJS());
             data_.jitFrames_.unaliasedForEachActual(op, jit::ReadFrame_Actuals);
         }
         return;
     }
     MOZ_CRASH("Unexpected state");
 }