author | Shu-yu Guo <shu@rfrn.org> |
Fri, 20 Jun 2014 18:39:13 -0700 | |
changeset 189914 | feaac6c10dc6dd76e908bdc9185cc8849bbb8595 |
parent 189913 | b3ebf7675c7bd1d85ed1b7290e1d2c3ae28a0490 |
child 189915 | cd7125c3338572cbb59534ed03243a8a87fbc92c |
push id | 26999 |
push user | ryanvm@gmail.com |
push date | Mon, 23 Jun 2014 14:42:40 +0000 |
treeherder | mozilla-central@4a7f4ed3f08b [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jandem |
bugs | 1019304 |
milestone | 33.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/RematerializedFrame.cpp +++ b/js/src/jit/RematerializedFrame.cpp @@ -24,42 +24,76 @@ struct CopyValueToRematerializedFrame { } void operator()(const Value &v) { *slots++ = v; } }; RematerializedFrame::RematerializedFrame(ThreadSafeContext *cx, uint8_t *top, - InlineFrameIterator &iter) + unsigned numActualArgs, InlineFrameIterator &iter) : prevUpToDate_(false), top_(top), + pc_(iter.pc()), frameNo_(iter.frameNo()), - numActualArgs_(iter.numActualArgs()), + numActualArgs_(numActualArgs), script_(iter.script()) { CopyValueToRematerializedFrame op(slots_); iter.readFrameArgsAndLocals(cx, op, op, &scopeChain_, &returnValue_, &argsObj_, &thisValue_, ReadFrame_Actuals); } /* 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) + - (Max(numFormals, iter.numActualArgs()) + - iter.script()->nfixed()) * sizeof(Value) - + (numActualArgs + iter.script()->nfixed()) * sizeof(Value) - sizeof(Value); // 1 Value included in sizeof(RematerializedFrame) void *buf = cx->calloc_(numBytes); if (!buf) return nullptr; - return new (buf) RematerializedFrame(cx, top, iter); + return new (buf) RematerializedFrame(cx, top, numActualArgs, iter); +} + +/* static */ bool +RematerializedFrame::RematerializeInlineFrames(ThreadSafeContext *cx, uint8_t *top, + InlineFrameIterator &iter, + Vector<RematerializedFrame *> &frames) +{ + if (!frames.resize(iter.frameCount())) + return false; + + while (true) { + size_t frameNo = iter.frameNo(); + frames[frameNo] = RematerializedFrame::New(cx, top, iter); + if (!frames[frameNo]) + return false; + + if (!iter.more()) + break; + ++iter; + } + + return true; +} + +/* static */ void +RematerializedFrame::FreeInVector(Vector<RematerializedFrame *> &frames) +{ + for (size_t i = 0; i < frames.length(); i++) { + RematerializedFrame *f = frames[i]; + f->RematerializedFrame::~RematerializedFrame(); + js_free(f); + } + frames.clear(); } CallObject & RematerializedFrame::callObj() const { JS_ASSERT(hasCallObj()); JSObject *scope = scopeChain(); @@ -77,45 +111,46 @@ RematerializedFrame::mark(JSTracer *trc) gc::MarkValueRoot(trc, &thisValue_, "remat ion frame this"); gc::MarkValueRootRange(trc, slots_, slots_ + numActualArgs_ + script_->nfixed(), "remat ion frame stack"); } void RematerializedFrame::dump() { - fprintf(stderr, " Rematerialized Optimized Frame%s\n", inlined() ? " (inlined)" : ""); + fprintf(stderr, " Rematerialized Ion Frame%s\n", inlined() ? " (inlined)" : ""); if (isFunctionFrame()) { fprintf(stderr, " callee fun: "); #ifdef DEBUG - js_DumpObject(callee()); + js_DumpValue(ObjectValue(*callee())); #else fprintf(stderr, "?\n"); #endif } else { fprintf(stderr, " global frame, no callee\n"); } - fprintf(stderr, " file %s line %u\n", - script()->filename(), (unsigned) script()->lineno()); + fprintf(stderr, " file %s line %u offset %zu\n", + script()->filename(), (unsigned) script()->lineno(), + script()->pcToOffset(pc())); fprintf(stderr, " script = %p\n", (void*) script()); if (isFunctionFrame()) { fprintf(stderr, " scope chain: "); #ifdef DEBUG - js_DumpObject(scopeChain()); + js_DumpValue(ObjectValue(*scopeChain())); #else fprintf(stderr, "?\n"); #endif if (hasArgsObj()) { fprintf(stderr, " args obj: "); #ifdef DEBUG - js_DumpObject(&argsObj()); + js_DumpValue(ObjectValue(argsObj())); #else fprintf(stderr, "?\n"); #endif } fprintf(stderr, " this: "); #ifdef DEBUG js_DumpValue(thisValue());
--- a/js/src/jit/RematerializedFrame.h +++ b/js/src/jit/RematerializedFrame.h @@ -25,43 +25,60 @@ namespace jit { class RematerializedFrame { // See DebugScopes::updateLiveScopes. bool prevUpToDate_; // The fp of the top frame associated with this possibly inlined frame. uint8_t *top_; + // The bytecode at the time of rematerialization. + jsbytecode *pc_; + size_t frameNo_; unsigned numActualArgs_; JSScript *script_; JSObject *scopeChain_; ArgumentsObject *argsObj_; Value returnValue_; Value thisValue_; Value slots_[1]; - RematerializedFrame(ThreadSafeContext *cx, uint8_t *top, InlineFrameIterator &iter); + RematerializedFrame(ThreadSafeContext *cx, uint8_t *top, unsigned numActualArgs, + InlineFrameIterator &iter); public: static RematerializedFrame *New(ThreadSafeContext *cx, uint8_t *top, InlineFrameIterator &iter); + // Rematerialize all remaining frames pointed to by |iter| into |frames| + // in older-to-younger order, e.g., frames[0] is the oldest frame. + static bool RematerializeInlineFrames(ThreadSafeContext *cx, uint8_t *top, + InlineFrameIterator &iter, + Vector<RematerializedFrame *> &frames); + + // Free a vector of RematerializedFrames; takes care to call the + // destructor. Also clears the vector. + static void FreeInVector(Vector<RematerializedFrame *> &frames); + bool prevUpToDate() const { return prevUpToDate_; } void setPrevUpToDate() { prevUpToDate_ = true; } uint8_t *top() const { return top_; } + jsbytecode *pc() const { + return pc_; + } size_t frameNo() const { return frameNo_; } bool inlined() const { return frameNo_ > 0; } JSObject *scopeChain() const {
--- a/js/src/vm/Stack.cpp +++ b/js/src/vm/Stack.cpp @@ -1582,99 +1582,85 @@ jit::JitActivation::setActive(JSContext cx->mainThread().jitTop = prevJitTop_; cx->mainThread().jitJSContext = prevJitJSContext_; } } #ifdef JS_ION void -jit::JitActivation::freeRematerializedFramesInVector(RematerializedFrameVector &frames) -{ - for (size_t i = 0; i < frames.length(); i++) { - RematerializedFrame *f = frames[i]; - f->RematerializedFrame::~RematerializedFrame(); - js_free(f); - } - frames.clear(); -} - -void jit::JitActivation::removeRematerializedFrame(uint8_t *top) { if (!rematerializedFrames_) return; if (RematerializedFrameTable::Ptr p = rematerializedFrames_->lookup(top)) { - freeRematerializedFramesInVector(p->value()); + RematerializedFrame::FreeInVector(p->value()); rematerializedFrames_->remove(p); } } void jit::JitActivation::clearRematerializedFrames() { if (!rematerializedFrames_) return; for (RematerializedFrameTable::Enum e(*rematerializedFrames_); !e.empty(); e.popFront()) { - freeRematerializedFramesInVector(e.front().value()); + RematerializedFrame::FreeInVector(e.front().value()); e.removeFront(); } } +template <class T> jit::RematerializedFrame * -jit::JitActivation::getRematerializedFrame(ThreadSafeContext *cx, JitFrameIterator &iter, - size_t inlineDepth) +jit::JitActivation::getRematerializedFrame(ThreadSafeContext *cx, const T &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_) { 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); if (!p) { RematerializedFrameVector empty(cx); if (!rematerializedFrames_->add(p, top, Move(empty))) 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. InlineFrameIterator inlineIter(cx, &iter); - if (!p->value().resize(inlineIter.frameCount())) + if (!RematerializedFrame::RematerializeInlineFrames(cx, top, inlineIter, p->value())) return nullptr; - - while (true) { - size_t frameNo = inlineIter.frameNo(); - p->value()[frameNo] = RematerializedFrame::New(cx, top, inlineIter); - if (!p->value()[frameNo]) - return nullptr; - - if (!inlineIter.more()) - break; - ++inlineIter; - } } return p->value()[inlineDepth]; } +template jit::RematerializedFrame * +jit::JitActivation::getRematerializedFrame<jit::JitFrameIterator>(ThreadSafeContext *cx, + const jit::JitFrameIterator &iter, + size_t inlineDepth); +template jit::RematerializedFrame * +jit::JitActivation::getRematerializedFrame<jit::IonBailoutIterator>(ThreadSafeContext *cx, + const jit::IonBailoutIterator &iter, + size_t inlineDepth); + jit::RematerializedFrame * jit::JitActivation::lookupRematerializedFrame(uint8_t *top, size_t inlineDepth) { if (!rematerializedFrames_) return nullptr; if (RematerializedFrameTable::Ptr p = rematerializedFrames_->lookup(top)) return inlineDepth < p->value().length() ? p->value()[inlineDepth] : nullptr; return nullptr;
--- a/js/src/vm/Stack.h +++ b/js/src/vm/Stack.h @@ -1333,21 +1333,20 @@ class JitActivation : public Activation bool active_; #ifdef JS_ION // Rematerialized Ion frames which has info copied out of snapshots. Maps // frame pointers (i.e. jitTop) 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 Vector<RematerializedFrame *> RematerializedFrameVector; typedef HashMap<uint8_t *, RematerializedFrameVector> RematerializedFrameTable; 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 // the OsiPoint that follows it. Protected to silence Clang warning. uint32_t checkRegs_; @@ -1394,18 +1393,21 @@ class JitActivation : public Activation #endif #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. // + // T is either JitFrameIterator or IonBailoutIterator. + // // The inlineDepth must be within bounds of the frame pointed to by iter. - RematerializedFrame *getRematerializedFrame(ThreadSafeContext *cx, JitFrameIterator &iter, + template <class T> + RematerializedFrame *getRematerializedFrame(ThreadSafeContext *cx, const T &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);