Bug 996983 - Part 2: JIT-related changes. (r=jandem)
authorShu-yu Guo <shu@rfrn.org>
Wed, 30 Apr 2014 21:12:17 -0700
changeset 181130 3de709d633552254112ce6b923dfb48b7b40ff99
parent 181129 b7b2591a326de45ebfb70f354c55833e10391ca8
child 181131 ed3ea6cb5afeb1ec05fa2dd9ba41aa1acd4e9fdc
push id26693
push useremorley@mozilla.com
push dateThu, 01 May 2014 14:50:08 +0000
treeherderautoland@51bc58066ac9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs996983
milestone32.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 996983 - Part 2: JIT-related changes. (r=jandem)
js/src/jit/IonFrames.cpp
js/src/jit/JitFrameIterator-inl.h
js/src/jit/JitFrameIterator.h
js/src/jit/RematerializedFrame.cpp
js/src/jit/RematerializedFrame.h
js/src/vm/Debugger.cpp
js/src/vm/ForkJoin.cpp
js/src/vm/Stack.cpp
js/src/vm/Stack.h
--- a/js/src/jit/IonFrames.cpp
+++ b/js/src/jit/IonFrames.cpp
@@ -70,35 +70,35 @@ ReadFrameInt32Slot(IonJSFrameLayout *fp,
 }
 
 static inline bool
 ReadFrameBooleanSlot(IonJSFrameLayout *fp, int32_t slot)
 {
     return *(bool *)((char *)fp + OffsetOfFrameSlot(slot));
 }
 
-JitFrameIterator::JitFrameIterator(JSContext *cx)
-  : current_(cx->mainThread().ionTop),
+JitFrameIterator::JitFrameIterator(ThreadSafeContext *cx)
+  : current_(cx->perThreadData->ionTop),
     type_(JitFrame_Exit),
     returnAddressToFp_(nullptr),
     frameSize_(0),
     cachedSafepointIndex_(nullptr),
     activation_(nullptr),
-    mode_(SequentialExecution)
+    mode_(cx->isForkJoinContext() ? ParallelExecution : SequentialExecution)
 {
 }
 
 JitFrameIterator::JitFrameIterator(const ActivationIterator &activations)
     : current_(activations.jitTop()),
       type_(JitFrame_Exit),
       returnAddressToFp_(nullptr),
       frameSize_(0),
       cachedSafepointIndex_(nullptr),
       activation_(activations->asJit()),
-      mode_(SequentialExecution)
+      mode_(activation_->cx()->isForkJoinContext() ? ParallelExecution : SequentialExecution)
 {
 }
 
 JitFrameIterator::JitFrameIterator(IonJSFrameLayout *fp, ExecutionMode mode)
   : current_((uint8_t *)fp),
     type_(JitFrame_IonJS),
     returnAddressToFp_(fp->returnAddress()),
     frameSize_(fp->prevFrameLocalSize()),
--- a/js/src/jit/JitFrameIterator-inl.h
+++ b/js/src/jit/JitFrameIterator-inl.h
@@ -14,18 +14,18 @@
 #include "jit/Bailouts.h"
 #include "jit/BaselineFrame.h"
 
 namespace js {
 namespace jit {
 
 template <AllowGC allowGC>
 inline
-InlineFrameIteratorMaybeGC<allowGC>::InlineFrameIteratorMaybeGC(
-                                                JSContext *cx, const IonBailoutIterator *iter)
+InlineFrameIteratorMaybeGC<allowGC>::InlineFrameIteratorMaybeGC(ThreadSafeContext *cx,
+                                                                const IonBailoutIterator *iter)
   : frame_(iter),
     framesRead_(0),
     frameCount_(UINT32_MAX),
     callee_(cx),
     script_(cx)
 {
     if (iter) {
         start_ = SnapshotIterator(*iter);
--- a/js/src/jit/JitFrameIterator.h
+++ b/js/src/jit/JitFrameIterator.h
@@ -102,17 +102,17 @@ class JitFrameIterator
         type_(JitFrame_Exit),
         returnAddressToFp_(nullptr),
         frameSize_(0),
         cachedSafepointIndex_(nullptr),
         activation_(nullptr),
         mode_(mode)
     { }
 
-    explicit JitFrameIterator(JSContext *cx);
+    explicit JitFrameIterator(ThreadSafeContext *cx);
     explicit JitFrameIterator(const ActivationIterator &activations);
     explicit JitFrameIterator(IonJSFrameLayout *fp, ExecutionMode mode);
 
     // Current frame information.
     FrameType type() const {
         return type_;
     }
     uint8_t *fp() const {
@@ -487,33 +487,33 @@ class InlineFrameIteratorMaybeGC
 
         // Ion does not handle scripts that are not compile-and-go.
         MOZ_ASSERT(!script()->isForEval());
         MOZ_ASSERT(script()->compileAndGo());
         return &script()->global();
     }
 
   public:
-    InlineFrameIteratorMaybeGC(JSContext *cx, const JitFrameIterator *iter)
+    InlineFrameIteratorMaybeGC(ThreadSafeContext *cx, const JitFrameIterator *iter)
       : callee_(cx),
         script_(cx)
     {
         resetOn(iter);
     }
 
     InlineFrameIteratorMaybeGC(JSRuntime *rt, const JitFrameIterator *iter)
       : callee_(rt),
         script_(rt)
     {
         resetOn(iter);
     }
 
-    InlineFrameIteratorMaybeGC(JSContext *cx, const IonBailoutIterator *iter);
+    InlineFrameIteratorMaybeGC(ThreadSafeContext *cx, const IonBailoutIterator *iter);
 
-    InlineFrameIteratorMaybeGC(JSContext *cx, const InlineFrameIteratorMaybeGC *iter)
+    InlineFrameIteratorMaybeGC(ThreadSafeContext *cx, const InlineFrameIteratorMaybeGC *iter)
       : frame_(iter ? iter->frame_ : nullptr),
         framesRead_(0),
         frameCount_(iter ? iter->frameCount_ : UINT32_MAX),
         callee_(cx),
         script_(cx)
     {
         if (frame_) {
             start_ = SnapshotIterator(*frame_);
@@ -543,17 +543,17 @@ class InlineFrameIteratorMaybeGC
         // js_fun_call or js_fun_apply.
         if (more())
             return numActualArgs_;
 
         return frame_->numActualArgs();
     }
 
     template <class ArgOp, class LocalOp>
-    void readFrameArgsAndLocals(JSContext *cx, ArgOp &argOp, LocalOp &localOp,
+    void readFrameArgsAndLocals(ThreadSafeContext *cx, ArgOp &argOp, LocalOp &localOp,
                                 JSObject **scopeChain, Value *rval,
                                 ArgumentsObject **argsObj, Value *thisv,
                                 ReadFrameArgsBehavior behavior) const
     {
         SnapshotIterator s(si_);
 
         // Read frame slots common to both function and global frames.
         Value scopeChainValue;
@@ -612,17 +612,19 @@ class InlineFrameIteratorMaybeGC
 
         // At this point we've read all the formals in s, and can read the
         // locals.
         for (unsigned i = 0; i < script()->nfixed(); i++)
             localOp(s.read());
     }
 
     template <class Op>
-    void unaliasedForEachActual(JSContext *cx, Op op, ReadFrameArgsBehavior behavior) const {
+    void unaliasedForEachActual(ThreadSafeContext *cx, Op op,
+                                ReadFrameArgsBehavior behavior) const
+    {
         Nop nop;
         readFrameArgsAndLocals(cx, op, nop, nullptr, nullptr, nullptr, nullptr, behavior);
     }
 
     JSScript *script() const {
         return script_;
     }
     jsbytecode *pc() const {
--- a/js/src/jit/RematerializedFrame.cpp
+++ b/js/src/jit/RematerializedFrame.cpp
@@ -23,30 +23,31 @@ struct CopyValueToRematerializedFrame
       : slots(slots)
     { }
 
     void operator()(const Value &v) {
         *slots++ = v;
     }
 };
 
-RematerializedFrame::RematerializedFrame(JSContext *cx, uint8_t *top, InlineFrameIterator &iter)
+RematerializedFrame::RematerializedFrame(ThreadSafeContext *cx, uint8_t *top,
+                                         InlineFrameIterator &iter)
   : prevUpToDate_(false),
     top_(top),
     frameNo_(iter.frameNo()),
     numActualArgs_(iter.numActualArgs()),
     script_(iter.script())
 {
     CopyValueToRematerializedFrame op(slots_);
     iter.readFrameArgsAndLocals(cx, op, op, &scopeChain_, &returnValue_,
                                 &argsObj_, &thisValue_, ReadFrame_Actuals);
 }
 
 /* static */ RematerializedFrame *
-RematerializedFrame::New(JSContext *cx, uint8_t *top, InlineFrameIterator &iter)
+RematerializedFrame::New(ThreadSafeContext *cx, uint8_t *top, InlineFrameIterator &iter)
 {
     unsigned numFormals = iter.isFunctionFrame() ? iter.callee()->nargs() : 0;
     size_t numBytes = sizeof(RematerializedFrame) +
         (Max(numFormals, iter.numActualArgs()) +
          iter.script()->nfixed()) * sizeof(Value) -
         sizeof(Value); // 1 Value included in sizeof(RematerializedFrame)
 
     void *buf = cx->calloc_(numBytes);
--- a/js/src/jit/RematerializedFrame.h
+++ b/js/src/jit/RematerializedFrame.h
@@ -36,20 +36,21 @@ class RematerializedFrame
     JSScript *script_;
     JSObject *scopeChain_;
     ArgumentsObject *argsObj_;
 
     Value returnValue_;
     Value thisValue_;
     Value slots_[1];
 
-    RematerializedFrame(JSContext *cx, uint8_t *top, InlineFrameIterator &iter);
+    RematerializedFrame(ThreadSafeContext *cx, uint8_t *top, InlineFrameIterator &iter);
 
   public:
-    static RematerializedFrame *New(JSContext *cx, uint8_t *top, InlineFrameIterator &iter);
+    static RematerializedFrame *New(ThreadSafeContext *cx, uint8_t *top,
+                                    InlineFrameIterator &iter);
 
     bool prevUpToDate() const {
         return prevUpToDate_;
     }
     void setPrevUpToDate() {
         prevUpToDate_ = true;
     }
 
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -2108,17 +2108,17 @@ Debugger::getNewestFrame(JSContext *cx, 
 {
     THIS_DEBUGGER(cx, argc, vp, "getNewestFrame", args, dbg);
 
     /* Since there may be multiple contexts, use AllFramesIter. */
     for (AllFramesIter i(cx); !i.done(); ++i) {
         if (dbg->observesFrame(i)) {
             // Ensure that Ion frames are rematerialized. Only rematerialized
             // Ion frames may be used as AbstractFramePtrs.
-            if (i.isIon() && !i.ensureHasRematerializedFrame())
+            if (i.isIon() && !i.ensureHasRematerializedFrame(cx))
                 return false;
             AbstractFramePtr frame = i.abstractFramePtr();
             ScriptFrameIter iter(i.activation()->cx(), ScriptFrameIter::GO_THROUGH_SAVED);
             while (!iter.hasUsableAbstractFramePtr() || iter.abstractFramePtr() != frame)
                 ++iter;
             return dbg->getScriptFrame(cx, iter, args.rval());
         }
     }
@@ -4113,17 +4113,17 @@ UpdateFrameIterPc(FrameIter &iter)
         // because when returning to debuggee code, we would have bailed out
         // to baseline.
         //
         // We walk the stack to assert that it doesn't need updating.
         jit::RematerializedFrame *frame = iter.abstractFramePtr().asRematerializedFrame();
         jit::IonJSFrameLayout *jsFrame = (jit::IonJSFrameLayout *)frame->top();
         jit::JitActivation *activation = iter.activation()->asJit();
 
-        ActivationIterator activationIter(activation->cx()->runtime());
+        ActivationIterator activationIter(activation->cx()->perThreadData);
         while (activationIter.activation() != activation)
             ++activationIter;
 
         jit::JitFrameIterator jitIter(activationIter);
         while (!jitIter.isIonJS() || jitIter.jsFrame() != jsFrame)
             ++jitIter;
 
         jit::InlineFrameIterator ionInlineIter(activation->cx(), &jitIter);
@@ -4365,17 +4365,17 @@ DebuggerFrame_getThis(JSContext *cx, uns
 static bool
 DebuggerFrame_getOlder(JSContext *cx, unsigned argc, Value *vp)
 {
     THIS_FRAME_ITER(cx, argc, vp, "get this", args, thisobj, _, iter);
     Debugger *dbg = Debugger::fromChildJSObject(thisobj);
 
     for (++iter; !iter.done(); ++iter) {
         if (dbg->observesFrame(iter)) {
-            if (iter.isIon() && !iter.ensureHasRematerializedFrame())
+            if (iter.isIon() && !iter.ensureHasRematerializedFrame(cx))
                 return false;
             return dbg->getScriptFrame(cx, iter, args.rval());
         }
     }
     args.rval().setNull();
     return true;
 }
 
--- a/js/src/vm/ForkJoin.cpp
+++ b/js/src/vm/ForkJoin.cpp
@@ -482,17 +482,17 @@ ForkJoinActivation::ForkJoinActivation(J
     cx->runtime()->gcHelperThread.waitBackgroundSweepEnd();
 
     JS_ASSERT(!cx->runtime()->needsBarrier());
     JS_ASSERT(!cx->zone()->needsBarrier());
 }
 
 ForkJoinActivation::~ForkJoinActivation()
 {
-    cx_->mainThread().ionTop = prevIonTop_;
+    cx_->perThreadData->ionTop = prevIonTop_;
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // js::ForkJoin() and ForkJoinOperation class
 //
 // These are the top-level objects that manage the parallel execution.
 // They handle parallel compilation (if necessary), triggering
 // parallel execution, and recovering from bailouts.
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -670,17 +670,17 @@ FrameIter::FrameIter(ThreadSafeContext *
 {
     settleOnActivation();
 }
 
 FrameIter::FrameIter(ThreadSafeContext *cx, ContextOption contextOption,
                      SavedOption savedOption)
   : data_(cx, savedOption, contextOption, nullptr)
 #ifdef JS_ION
-  , ionInlineFrames_(cx, (js::jit::IonFrameIterator*) nullptr)
+  , ionInlineFrames_(cx, (js::jit::JitFrameIterator*) nullptr)
 #endif
 {
     settleOnActivation();
 }
 
 FrameIter::FrameIter(JSContext *cx, ContextOption contextOption,
                      SavedOption savedOption, JSPrincipals *principals)
   : data_(cx, savedOption, contextOption, principals)
@@ -1076,21 +1076,21 @@ FrameIter::isConstructing() const
 #endif
       case INTERP:
         return interpFrame()->isConstructing();
     }
     MOZ_ASSUME_UNREACHABLE("Unexpected state");
 }
 
 bool
-FrameIter::ensureHasRematerializedFrame()
+FrameIter::ensureHasRematerializedFrame(ThreadSafeContext *cx)
 {
 #ifdef JS_ION
     MOZ_ASSERT(isIon());
-    return !!activation()->asJit()->getRematerializedFrame(activation()->cx(), data_.jitFrames_);
+    return !!activation()->asJit()->getRematerializedFrame(cx, data_.jitFrames_);
 #else
     return true;
 #endif
 }
 
 bool
 FrameIter::hasUsableAbstractFramePtr() const
 {
@@ -1520,38 +1520,39 @@ js::CheckLocalUnaliased(MaybeCheckAliasi
 }
 #endif
 
 jit::JitActivation::JitActivation(JSContext *cx, bool firstFrameIsConstructing, bool active)
   : Activation(cx, Jit),
     firstFrameIsConstructing_(firstFrameIsConstructing),
     active_(active)
 #ifdef JS_ION
-  , rematerializedFrames_(cx)
+  , rematerializedFrames_(nullptr)
 #endif
 {
     if (active) {
         prevIonTop_ = cx->mainThread().ionTop;
         prevJitJSContext_ = cx->mainThread().jitJSContext;
         cx->mainThread().jitJSContext = cx;
     } else {
         prevIonTop_ = nullptr;
         prevJitJSContext_ = nullptr;
     }
 }
 
 jit::JitActivation::~JitActivation()
 {
     if (active_) {
-        cx_->mainThread().ionTop = prevIonTop_;
-        cx_->mainThread().jitJSContext = prevJitJSContext_;
+        cx_->perThreadData->ionTop = prevIonTop_;
+        cx_->perThreadData->jitJSContext = prevJitJSContext_;
     }
 
 #ifdef JS_ION
     clearRematerializedFrames();
+    js_delete(rematerializedFrames_);
 #endif
 }
 
 // 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)
@@ -1583,58 +1584,65 @@ jit::JitActivation::freeRematerializedFr
         js_free(f);
     }
     frames.clear();
 }
 
 void
 jit::JitActivation::removeRematerializedFrame(uint8_t *top)
 {
-    if (!rematerializedFrames_.initialized())
+    if (!rematerializedFrames_)
         return;
 
-    if (RematerializedFrameTable::Ptr p = rematerializedFrames_.lookup(top)) {
+    if (RematerializedFrameTable::Ptr p = rematerializedFrames_->lookup(top)) {
         freeRematerializedFramesInVector(p->value());
-        rematerializedFrames_.remove(p);
+        rematerializedFrames_->remove(p);
     }
 }
 
 void
 jit::JitActivation::clearRematerializedFrames()
 {
-    if (!rematerializedFrames_.initialized())
+    if (!rematerializedFrames_)
         return;
 
-    for (RematerializedFrameTable::Enum e(rematerializedFrames_); !e.empty(); e.popFront()) {
+    for (RematerializedFrameTable::Enum e(*rematerializedFrames_); !e.empty(); e.popFront()) {
         freeRematerializedFramesInVector(e.front().value());
         e.removeFront();
     }
 }
 
 jit::RematerializedFrame *
-jit::JitActivation::getRematerializedFrame(JSContext *cx, JitFrameIterator &iter,
+jit::JitActivation::getRematerializedFrame(ThreadSafeContext *cx, JitFrameIterator &iter,
                                            size_t inlineDepth)
 {
+    // Only allow rematerializing from the same thread.
+    MOZ_ASSERT(cx->perThreadData == cx_->perThreadData);
     MOZ_ASSERT(iter.activation() == this);
     MOZ_ASSERT(iter.isIonJS());
 
-    if (!rematerializedFrames_.initialized() && !rematerializedFrames_.init())
-        return nullptr;
+    if (!rematerializedFrames_) {
+        rematerializedFrames_ = cx->new_<RematerializedFrameTable>(cx);
+        if (!rematerializedFrames_ || !rematerializedFrames_->init()) {
+            rematerializedFrames_ = nullptr;
+            return nullptr;
+        }
+    }
 
     // The unit of rematerialization is an uninlined frame and its inlined
     // frames. Since inlined frames do not exist outside of snapshots, it is
     // impossible to synchronize their rematerialized copies to preserve
     // identity. Therefore, we always rematerialize an uninlined frame and all
     // its inlined frames at once.
 
     uint8_t *top = iter.fp();
-    RematerializedFrameTable::AddPtr p = rematerializedFrames_.lookupForAdd(top);
+    RematerializedFrameTable::AddPtr p = rematerializedFrames_->lookupForAdd(top);
     if (!p) {
         RematerializedFrameVector empty(cx);
-        if (!rematerializedFrames_.add(p, top, Move(empty)))
+        if (!rematerializedFrames_->add(p, top, Move(empty)))
             return nullptr;
 
         InlineFrameIterator inlineIter(cx, &iter);
         if (!p->value().resize(inlineIter.frameCount()))
             return nullptr;
 
         while (true) {
             size_t frameNo = inlineIter.frameNo();
@@ -1649,29 +1657,29 @@ jit::JitActivation::getRematerializedFra
     }
 
     return p->value()[inlineDepth];
 }
 
 jit::RematerializedFrame *
 jit::JitActivation::lookupRematerializedFrame(uint8_t *top, size_t inlineDepth)
 {
-    if (!rematerializedFrames_.initialized())
+    if (!rematerializedFrames_)
         return nullptr;
-    if (RematerializedFrameTable::Ptr p = rematerializedFrames_.lookup(top))
+    if (RematerializedFrameTable::Ptr p = rematerializedFrames_->lookup(top))
         return inlineDepth < p->value().length() ? p->value()[inlineDepth] : nullptr;
     return nullptr;
 }
 
 void
 jit::JitActivation::markRematerializedFrames(JSTracer *trc)
 {
-    if (!rematerializedFrames_.initialized())
+    if (!rematerializedFrames_)
         return;
-    for (RematerializedFrameTable::Enum e(rematerializedFrames_); !e.empty(); e.popFront()) {
+    for (RematerializedFrameTable::Enum e(*rematerializedFrames_); !e.empty(); e.popFront()) {
         RematerializedFrameVector &frames = e.front().value();
         for (size_t i = 0; i < frames.length(); i++)
             frames[i]->mark(trc);
     }
 }
 
 #endif // JS_ION
 
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -1167,18 +1167,16 @@ class Activation
     }
     JSCompartment *compartment() const {
         return compartment_;
     }
     Activation *prev() const {
         return prev_;
     }
 
-    inline JSCompartment *compartment() const;
-
     bool isInterpreter() const {
         return kind_ == Interpreter;
     }
     bool isJit() const {
         return kind_ == Jit;
     }
     bool isForkJoin() const {
         return kind_ == ForkJoin;
@@ -1337,17 +1335,17 @@ class JitActivation : public Activation
 #ifdef JS_ION
     // Rematerialized Ion frames which has info copied out of snapshots. Maps
     // frame pointers (i.e. ionTop) to a vector of rematerializations of all
     // inline frames associated with that frame.
     //
     // This table is lazily initialized by calling getRematerializedFrame.
     typedef Vector<RematerializedFrame *, 1> RematerializedFrameVector;
     typedef HashMap<uint8_t *, RematerializedFrameVector> RematerializedFrameTable;
-    RematerializedFrameTable rematerializedFrames_;
+    RematerializedFrameTable *rematerializedFrames_;
 
     void freeRematerializedFramesInVector(RematerializedFrameVector &frames);
     void clearRematerializedFrames();
 #endif
 
 #ifdef CHECK_OSIPOINT_REGISTERS
   protected:
     // Used to verify that live registers don't change between a VM call and
@@ -1396,17 +1394,17 @@ class JitActivation : public Activation
 
 #ifdef JS_ION
     // Look up a rematerialized frame keyed by the fp, rematerializing the
     // frame if one doesn't already exist. A frame can only be rematerialized
     // if an IonFrameIterator pointing to the nearest uninlined frame can be
     // provided, as values need to be read out of snapshots.
     //
     // The inlineDepth must be within bounds of the frame pointed to by iter.
-    RematerializedFrame *getRematerializedFrame(JSContext *cx, JitFrameIterator &iter,
+    RematerializedFrame *getRematerializedFrame(ThreadSafeContext *cx, JitFrameIterator &iter,
                                                 size_t inlineDepth = 0);
 
     // Look up a rematerialized frame by the fp. If inlineDepth is out of
     // bounds of what has been rematerialized, nullptr is returned.
     RematerializedFrame *lookupRematerializedFrame(uint8_t *top, size_t inlineDepth = 0);
 
     bool hasRematerializedFrame(uint8_t *top, size_t inlineDepth = 0) {
         return !!lookupRematerializedFrame(top, inlineDepth);
@@ -1429,16 +1427,22 @@ class JitActivationIterator : public Act
 
   public:
     explicit JitActivationIterator(JSRuntime *rt)
       : ActivationIterator(rt)
     {
         settle();
     }
 
+    explicit JitActivationIterator(PerThreadData *perThreadData)
+      : ActivationIterator(perThreadData)
+    {
+        settle();
+    }
+
     JitActivationIterator &operator++() {
         ActivationIterator::operator++();
         settle();
         return *this;
     }
 
     // Returns the bottom and top addresses of the current JitActivation.
     void jitStackRange(uintptr_t *&min, uintptr_t *&end);
@@ -1675,17 +1679,17 @@ class FrameIter
     }
 
     // These are only valid for the top frame.
     size_t      numFrameSlots() const;
     Value       frameSlotValue(size_t index) const;
 
     // Ensures that we have rematerialized the top frame and its associated
     // inline frames. Can only be called when isIon().
-    bool ensureHasRematerializedFrame();
+    bool ensureHasRematerializedFrame(ThreadSafeContext *cx);
 
     // True when isInterp() or isBaseline(). True when isIon() if it
     // has a rematerialized frame. False otherwise false otherwise.
     bool hasUsableAbstractFramePtr() const;
 
     // -----------------------------------------------------------
     // The following functions can only be called when isInterp(),
     // isBaseline(), or isIon(). Further, abstractFramePtr() can