Bug 1070962 - Part 1: Register IonBailoutIterator on the JitActivation. r=jandem, a=abillings
authorNicolas B. Pierron <nicolas.b.pierron@mozilla.com>
Mon, 13 Oct 2014 17:33:58 +0200
changeset 234742 ccdd0dbcd0fc7782f146cbb50069b953f7dad075
parent 234741 153fe1da3d43d0a3b9a28915b71e88c23dd181f2
child 234743 ca143046f0c0e347f012441c570bfb0e38b610e8
push id611
push userraliiev@mozilla.com
push dateMon, 05 Jan 2015 23:23:16 +0000
treeherdermozilla-release@345cd3b9c445 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem, abillings
bugs1070962
milestone35.0a2
Bug 1070962 - Part 1: Register IonBailoutIterator on the JitActivation. r=jandem, a=abillings
js/src/jit/Bailouts.cpp
js/src/jit/ParallelFunctions.cpp
js/src/vm/Stack.cpp
js/src/vm/Stack.h
--- a/js/src/jit/Bailouts.cpp
+++ b/js/src/jit/Bailouts.cpp
@@ -82,16 +82,17 @@ jit::Bailout(BailoutStack *sp, BaselineB
                IsInRange(FAKE_JIT_TOP_FOR_BAILOUT + sizeof(IonCommonFrameLayout), 0, 0x1000),
                "Fake jitTop pointer should be within the first page.");
     cx->mainThread().jitTop = FAKE_JIT_TOP_FOR_BAILOUT;
     gc::AutoSuppressGC suppress(cx);
 
     JitActivationIterator jitActivations(cx->runtime());
     IonBailoutIterator iter(jitActivations, sp);
     JitActivation *activation = jitActivations->asJit();
+    JitActivation::RegisterBailoutIterator registerIterator(*activation, &iter);
 
     TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
     TraceLogTimestamp(logger, TraceLogger::Bailout);
 
     JitSpew(JitSpew_IonBailouts, "Took bailout! Snapshot offset: %d", iter.snapshotOffset());
 
     MOZ_ASSERT(IsBaselineEnabled(cx));
 
@@ -135,16 +136,17 @@ jit::InvalidationBailout(InvalidationBai
 
     // We don't have an exit frame.
     cx->mainThread().jitTop = FAKE_JIT_TOP_FOR_BAILOUT;
     gc::AutoSuppressGC suppress(cx);
 
     JitActivationIterator jitActivations(cx->runtime());
     IonBailoutIterator iter(jitActivations, sp);
     JitActivation *activation = jitActivations->asJit();
+    JitActivation::RegisterBailoutIterator registerIterator(*activation, &iter);
 
     TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
     TraceLogTimestamp(logger, TraceLogger::Invalidation);
 
     JitSpew(JitSpew_IonBailouts, "Took invalidation bailout! Snapshot offset: %d", iter.snapshotOffset());
 
     // Note: the frame size must be computed before we return from this function.
     *frameSizeOut = iter.topFrameSize();
@@ -223,16 +225,17 @@ jit::ExceptionHandlerBailout(JSContext *
     MOZ_ASSERT_IF(!excInfo.propagatingIonExceptionForDebugMode(), cx->isExceptionPending());
 
     cx->mainThread().jitTop = FAKE_JIT_TOP_FOR_BAILOUT;
     gc::AutoSuppressGC suppress(cx);
 
     JitActivationIterator jitActivations(cx->runtime());
     IonBailoutIterator iter(jitActivations, frame.frame());
     JitActivation *activation = jitActivations->asJit();
+    JitActivation::RegisterBailoutIterator registerIterator(*activation, &iter);
 
     BaselineBailoutInfo *bailoutInfo = nullptr;
     uint32_t retval = BailoutIonToBaseline(cx, activation, iter, true, &bailoutInfo, &excInfo);
 
     if (retval == BAILOUT_RETURN_OK) {
         MOZ_ASSERT(bailoutInfo);
 
         // Overwrite the kind so HandleException after the bailout returns
--- a/js/src/jit/ParallelFunctions.cpp
+++ b/js/src/jit/ParallelFunctions.cpp
@@ -541,16 +541,17 @@ jit::BailoutPar(BailoutStack *sp, uint8_
     MOZ_ASSERT(IsInRange(FAKE_JIT_TOP_FOR_BAILOUT, 0, 0x1000) &&
                IsInRange(FAKE_JIT_TOP_FOR_BAILOUT + sizeof(IonCommonFrameLayout), 0, 0x1000),
                "Fake jitTop pointer should be within the first page.");
     cx->perThreadData->jitTop = FAKE_JIT_TOP_FOR_BAILOUT;
 
     JitActivationIterator jitActivations(cx->perThreadData);
     IonBailoutIterator frameIter(jitActivations, sp);
     SnapshotIterator snapIter(frameIter);
+    JitActivation::RegisterBailoutIterator registerIterator(*jitActivations->asJit(), &frameIter);
 
     cx->bailoutRecord->setIonBailoutKind(snapIter.bailoutKind());
     cx->bailoutRecord->rematerializeFrames(cx, frameIter);
 
     MOZ_ASSERT(frameIter.done());
     *entryFramePointer = frameIter.fp();
 }
 
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -1399,52 +1399,73 @@ js::CheckLocalUnaliased(MaybeCheckAliasi
     }
 }
 #endif
 
 jit::JitActivation::JitActivation(JSContext *cx, bool active)
   : Activation(cx, Jit),
     active_(active),
     rematerializedFrames_(nullptr),
-    ionRecovery_(cx)
+    ionRecovery_(cx),
+    ionBailoutIterator_(nullptr)
 {
     if (active) {
         prevJitTop_ = cx->mainThread().jitTop;
         prevJitJSContext_ = cx->mainThread().jitJSContext;
         cx->mainThread().jitJSContext = cx;
     } else {
         prevJitTop_ = nullptr;
         prevJitJSContext_ = nullptr;
     }
 }
 
 jit::JitActivation::JitActivation(ForkJoinContext *cx)
   : Activation(cx, Jit),
     active_(true),
     rematerializedFrames_(nullptr),
-    ionRecovery_(cx)
+    ionRecovery_(cx),
+    ionBailoutIterator_(nullptr)
 {
     prevJitTop_ = cx->perThreadData->jitTop;
     prevJitJSContext_ = cx->perThreadData->jitJSContext;
     cx->perThreadData->jitJSContext = nullptr;
 }
 
 jit::JitActivation::~JitActivation()
 {
     if (active_) {
         cx_->perThreadData->jitTop = prevJitTop_;
         cx_->perThreadData->jitJSContext = prevJitJSContext_;
     }
 
-    clearRematerializedFrames();
     // All reocvered value are taken from activation during the bailout.
     MOZ_ASSERT(ionRecovery_.empty());
+
+    // The Ion Bailout Iterator should have unregistered itself from the
+    // JitActivations.
+    MOZ_ASSERT(!ionBailoutIterator_);
+
+    clearRematerializedFrames();
     js_delete(rematerializedFrames_);
 }
 
+jit::JitActivation::RegisterBailoutIterator::RegisterBailoutIterator(JitActivation &activation,
+                                                                     IonBailoutIterator *iter)
+  : activation_(activation)
+{
+    MOZ_ASSERT(!activation_.ionBailoutIterator_);
+    activation_.ionBailoutIterator_ = iter;
+}
+
+jit::JitActivation::RegisterBailoutIterator::~RegisterBailoutIterator()
+{
+    MOZ_ASSERT(activation_.ionBailoutIterator_);
+    activation_.ionBailoutIterator_ = nullptr;
+}
+
 // setActive() is inlined in GenerateFFIIonExit() with explicit masm instructions so
 // changes to the logic here need to be reflected in GenerateFFIIonExit() in the enable
 // and disable activation instruction sequences.
 void
 jit::JitActivation::setActive(JSContext *cx, bool active)
 {
     // Only allowed to deactivate/activate if activation is top.
     // (Not tested and will probably fail in other situations.)
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -1322,16 +1322,21 @@ class JitActivation : public Activation
     //
     // RInstructionResults are appended into this vector when Snapshot values
     // have to be read, or when the evaluation has to run before some mutating
     // code.  Each RInstructionResults belongs to one frame which has to bailout
     // as soon as we get back to it.
     typedef Vector<RInstructionResults, 1> IonRecoveryMap;
     IonRecoveryMap ionRecovery_;
 
+    // If we are bailing out from Ion, then this field should be a non-null
+    // pointer which references the IonBailoutIterator used to walk the inner
+    // frames.
+    IonBailoutIterator  *ionBailoutIterator_;
+
     void clearRematerializedFrames();
 
 #ifdef CHECK_OSIPOINT_REGISTERS
   protected:
     // Used to verify that live registers don't change between a VM call and
     // the OsiPoint that follows it. Protected to silence Clang warning.
     uint32_t checkRegs_;
     RegisterDump regs_;
@@ -1410,16 +1415,25 @@ class JitActivation : public Activation
     RInstructionResults *maybeIonFrameRecovery(IonJSFrameLayout *fp);
 
     // If an Ion frame recovery exists for the |fp| frame exists on the
     // activation, then move its content to the |results| argument, and remove
     // it from the activation.
     void maybeTakeIonFrameRecovery(IonJSFrameLayout *fp, RInstructionResults *results);
 
     void markIonRecovery(JSTracer *trc);
+
+    class RegisterBailoutIterator
+    {
+        JitActivation &activation_;
+
+      public:
+        RegisterBailoutIterator(JitActivation &activation, IonBailoutIterator *iter);
+        ~RegisterBailoutIterator();
+    };
 };
 
 // A filtering of the ActivationIterator to only stop at JitActivations.
 class JitActivationIterator : public ActivationIterator
 {
     void settle() {
         while (!done() && !activation_->isJit())
             ActivationIterator::operator++();