Bug 886255 - Let activatation of inactive JitActivation behave more closely to the construction of active JitAction. r=jandem, a=bajaj
authorHannes Verschore <hv1989@gmail.com>
Wed, 03 Jul 2013 10:41:17 +0200
changeset 147868 ec74c69d417772fdec9556c48fae58c8ccdedd31
parent 147867 ce5b34dd98d44fd4deff52b78ac537e08f753bc8
child 147869 bbbcec4b886042a7964fa7f51d2ddbd467827663
push id2697
push userbbajaj@mozilla.com
push dateMon, 05 Aug 2013 18:49:53 +0000
treeherdermozilla-beta@dfec938c7b63 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem, bajaj
bugs886255
milestone24.0a2
Bug 886255 - Let activatation of inactive JitActivation behave more closely to the construction of active JitAction. r=jandem, a=bajaj
js/src/ion/AsmJS.cpp
js/src/jscntxt.h
js/src/jscntxtinlines.h
js/src/vm/Stack-inl.h
js/src/vm/Stack.cpp
js/src/vm/Stack.h
--- a/js/src/ion/AsmJS.cpp
+++ b/js/src/ion/AsmJS.cpp
@@ -5646,24 +5646,28 @@ GenerateOOLConvert(ModuleCompiler &m, Re
 
     masm.freeStack(stackDec);
 }
 
 static void
 EnableActivation(AsmJSActivation *activation)
 {
     JSContext *cx = activation->cx();
-    cx->mainThread().activation()->setActive();
+    Activation *act = cx->mainThread().activation();
+    JS_ASSERT(act->isJit());
+    act->asJit()->setActive(cx);
 }
 
 static void
 DisableActivation(AsmJSActivation *activation)
 {
     JSContext *cx = activation->cx();
-    cx->mainThread().activation()->setActive(false);
+    Activation *act = cx->mainThread().activation();
+    JS_ASSERT(act->isJit());
+    act->asJit()->setActive(cx, false);
 }
 
 static void
 GenerateFFIIonExit(ModuleCompiler &m, const ModuleCompiler::ExitDescriptor &exit,
                          unsigned exitIndex, Label *throwLabel)
 {
     MacroAssembler &masm = m.masm();
     masm.align(CodeAlignment);
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -513,16 +513,17 @@ class PerThreadData : public js::PerThre
      * running asm.js without requiring dynamic polling operations in the
      * generated code. Since triggerOperationCallback may run on a separate
      * thread than the JSRuntime's owner thread all reads/writes must be
      * synchronized (by rt->operationCallbackLock).
      */
   private:
     friend class js::Activation;
     friend class js::ActivationIterator;
+    friend class js::ion::JitActivation;
     friend class js::AsmJSActivation;
 
     /*
      * Points to the most recent activation running on the thread.
      * See Activation comment in vm/Stack.h.
      */
     js::Activation *activation_;
 
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -560,17 +560,17 @@ JSContext::setCompartment(JSCompartment 
 inline JSScript *
 JSContext::currentScript(jsbytecode **ppc,
                          MaybeAllowCrossCompartment allowCrossCompartment) const
 {
     if (ppc)
         *ppc = NULL;
 
     js::Activation *act = mainThread().activation();
-    while (act && (act->cx() != this || !act->isActive()))
+    while (act && (act->cx() != this || (act->isJit() && !act->asJit()->isActive())))
         act = act->prev();
 
     if (!act)
         return NULL;
 
     JS_ASSERT(act->cx() == this);
 
 #ifdef JS_ION
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/Stack-inl.h
@@ -817,21 +817,20 @@ inline void
 AbstractFramePtr::popWith(JSContext *cx) const
 {
     if (isStackFrame())
         asStackFrame()->popWith(cx);
     else
         JS_NOT_REACHED("Invalid frame");
 }
 
-Activation::Activation(JSContext *cx, Kind kind, bool active)
+Activation::Activation(JSContext *cx, Kind kind)
   : cx_(cx),
     compartment_(cx->compartment()),
     prev_(cx->mainThread().activation_),
-    active_(active),
     savedFrameChain_(0),
     kind_(kind)
 {
     cx->mainThread().activation_ = this;
 }
 
 Activation::~Activation()
 {
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -1297,43 +1297,56 @@ js::CheckLocalUnaliased(MaybeCheckAliasi
                 JS_ASSERT(!b->isAliased(depth - b->stackDepth()));
                 break;
             }
         }
     }
 }
 #endif
 
-void
-Activation::setActive(bool active)
+ion::JitActivation::JitActivation(JSContext *cx, bool firstFrameIsConstructing, bool active)
+  : Activation(cx, Jit),
+    firstFrameIsConstructing_(firstFrameIsConstructing),
+    active_(active)
 {
-    // Only allowed to deactivate/activate if activation is top.
-    // (Not tested and will probably fail in other situations.)
-    JS_ASSERT(cx()->mainThread().activation_ == this);
-    JS_ASSERT(active != active_);
-    active_ = active;
-
-    // Restore ionTop
-    if (!active && isJit())
-        cx()->mainThread().ionTop = asJit()->prevIonTop();
-}
-
-ion::JitActivation::JitActivation(JSContext *cx, bool firstFrameIsConstructing, bool active)
-  : Activation(cx, Jit, active),
-    prevIonTop_(cx->mainThread().ionTop),
-    prevIonJSContext_(cx->mainThread().ionJSContext),
-    firstFrameIsConstructing_(firstFrameIsConstructing)
-{
-    cx->mainThread().ionJSContext = cx;
+    if (active) {
+        prevIonTop_ = cx->mainThread().ionTop;
+        prevIonJSContext_ = cx->mainThread().ionJSContext;
+        cx->mainThread().ionJSContext = cx;
+    } else {
+        prevIonTop_ = NULL;
+        prevIonJSContext_ = NULL;
+    }
 }
 
 ion::JitActivation::~JitActivation()
 {
-    cx_->mainThread().ionTop = prevIonTop_;
-    cx_->mainThread().ionJSContext = prevIonJSContext_;
+    if (active_) {
+        cx_->mainThread().ionTop = prevIonTop_;
+        cx_->mainThread().ionJSContext = prevIonJSContext_;
+    }
+}
+
+void
+ion::JitActivation::setActive(JSContext *cx, bool active)
+{
+    // Only allowed to deactivate/activate if activation is top.
+    // (Not tested and will probably fail in other situations.)
+    JS_ASSERT(cx->mainThread().activation_ == this);
+    JS_ASSERT(active != active_);
+    active_ = active;
+
+    if (active) {
+        prevIonTop_ = cx->mainThread().ionTop;
+        prevIonJSContext_ = cx->mainThread().ionJSContext;
+        cx->mainThread().ionJSContext = cx;
+    } else {
+        cx->mainThread().ionTop = prevIonTop_;
+        cx->mainThread().ionJSContext = prevIonJSContext_;
+    }
 }
 
 InterpreterFrameIterator &
 InterpreterFrameIterator::operator++()
 {
     JS_ASSERT(!done());
     if (fp_ != activation_->entry_) {
         pc_ = fp_->prevpc();
@@ -1353,24 +1366,24 @@ ActivationIterator::ActivationIterator(J
 {
     settle();
 }
 
 ActivationIterator &
 ActivationIterator::operator++()
 {
     JS_ASSERT(activation_);
-    if (activation_->isJit())
+    if (activation_->isJit() && activation_->asJit()->isActive())
         jitTop_ = activation_->asJit()->prevIonTop();
     activation_ = activation_->prev();
     settle();
     return *this;
 }
 
 void
 ActivationIterator::settle()
 {
-    while (!done() && !activation_->isActive()) {
-        if (activation_->isJit())
+    while (!done() && activation_->isJit() && !activation_->asJit()->isActive()) {
+        if (activation_->asJit()->isActive())
             jitTop_ = activation_->asJit()->prevIonTop();
         activation_ = activation_->prev();
     }
 }
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -1145,44 +1145,39 @@ namespace ion {
 };
 
 class Activation
 {
   protected:
     JSContext *cx_;
     JSCompartment *compartment_;
     Activation *prev_;
-    bool active_;
 
     // Counter incremented by JS_SaveFrameChain on the top-most activation and
     // decremented by JS_RestoreFrameChain. If > 0, ScriptFrameIter should stop
     // iterating when it reaches this activation (if GO_THROUGH_SAVED is not
     // set).
     size_t savedFrameChain_;
 
     enum Kind { Interpreter, Jit };
     Kind kind_;
 
-    inline Activation(JSContext *cx, Kind kind_, bool active = true);
+    inline Activation(JSContext *cx, Kind kind_);
     inline ~Activation();
 
   public:
     JSContext *cx() const {
         return cx_;
     }
     JSCompartment *compartment() const {
         return compartment_;
     }
     Activation *prev() const {
         return prev_;
     }
-    bool isActive() const {
-        return active_;
-    }
-    void setActive(bool active = true);
 
     bool isInterpreter() const {
         return kind_ == Interpreter;
     }
     bool isJit() const {
         return kind_ == Jit;
     }
 
@@ -1273,21 +1268,27 @@ class ActivationIterator
 namespace ion {
 
 // A JitActivation is used for frames running in Baseline or Ion.
 class JitActivation : public Activation
 {
     uint8_t *prevIonTop_;
     JSContext *prevIonJSContext_;
     bool firstFrameIsConstructing_;
+    bool active_;
 
   public:
     JitActivation(JSContext *cx, bool firstFrameIsConstructing, bool active = true);
     ~JitActivation();
 
+    bool isActive() const {
+        return active_;
+    }
+    void setActive(JSContext *cx, bool active = true);
+
     uint8_t *prevIonTop() const {
         return prevIonTop_;
     }
     JSCompartment *compartment() const {
         return compartment_;
     }
     bool firstFrameIsConstructing() const {
         return firstFrameIsConstructing_;