author | Shu-yu Guo <shu@rfrn.org> |
Wed, 30 Apr 2014 21:12:17 -0700 | |
changeset 181130 | 3de709d633552254112ce6b923dfb48b7b40ff99 |
parent 181129 | b7b2591a326de45ebfb70f354c55833e10391ca8 |
child 181131 | ed3ea6cb5afeb1ec05fa2dd9ba41aa1acd4e9fdc |
push id | 26693 |
push user | emorley@mozilla.com |
push date | Thu, 01 May 2014 14:50:08 +0000 |
treeherder | autoland@51bc58066ac9 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jandem |
bugs | 996983 |
milestone | 32.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
|
--- 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