author | Nicolas Pierron <nicolas.b.pierron@mozilla.com> |
Tue, 01 May 2012 17:40:31 -0700 | |
changeset 112441 | f39ac9c99046d00a17ae006ae3446952e38d4edb |
parent 112440 | 04590b9cde4e7904b70f98182f4ef69c5710a59d |
child 112442 | 1161f2520e9bdde60321a225084ac126f5173056 |
push id | 1708 |
push user | akeybl@mozilla.com |
push date | Mon, 19 Nov 2012 21:10:21 +0000 |
treeherder | mozilla-beta@27b14fe50103 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | dvander |
bugs | 744253 |
milestone | 15.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
|
js/src/ion/Ion.cpp | file | annotate | diff | comparison | revisions | |
js/src/ion/IonFrameIterator.h | file | annotate | diff | comparison | revisions | |
js/src/ion/IonFrames.cpp | file | annotate | diff | comparison | revisions | |
js/src/jsfun.cpp | file | annotate | diff | comparison | revisions | |
js/src/jsgc.cpp | file | annotate | diff | comparison | revisions | |
js/src/jsinfer.cpp | file | annotate | diff | comparison | revisions | |
js/src/jsobj.cpp | file | annotate | diff | comparison | revisions | |
js/src/vm/Stack.cpp | file | annotate | diff | comparison | revisions | |
js/src/vm/Stack.h | file | annotate | diff | comparison | revisions |
--- a/js/src/ion/Ion.cpp +++ b/js/src/ion/Ion.cpp @@ -1017,17 +1017,17 @@ ion::SideCannon(JSContext *cx, StackFram static void InvalidateActivation(FreeOp *fop, uint8 *ionTop, bool invalidateAll) { IonSpew(IonSpew_Invalidate, "BEGIN invalidating activation"); size_t frameno = 1; - for (IonFrameIterator it(ionTop); it.more(); ++it, ++frameno) { + for (IonFrameIterator it(ionTop); !it.done(); ++it, ++frameno) { JS_ASSERT_IF(frameno == 1, it.type() == IonFrame_Exit); #ifdef DEBUG switch (it.type()) { case IonFrame_Exit: IonSpew(IonSpew_Invalidate, "#%d exit frame @ %p", frameno, it.fp()); break; case IonFrame_JS:
--- a/js/src/ion/IonFrameIterator.h +++ b/js/src/ion/IonFrameIterator.h @@ -108,16 +108,18 @@ class IonFrameIterator bool isScripted() const { return type_ == IonFrame_JS; } bool isEntry() const { return type_ == IonFrame_Entry; } bool isFunctionFrame() const; + bool isConstructing(IonActivation *activation) const; + void *calleeToken() const; JSFunction *callee() const; JSFunction *maybeCallee() const; JSScript *script() const; // Returns the return address of the frame above this one (that is, the // return address that returns back to the current frame). uint8 *returnAddressToFp() const { @@ -130,18 +132,18 @@ class IonFrameIterator uint8 *prevFp() const; // Returns the stack space used by the current frame, in bytes. This does // not include the size of its fixed header. inline size_t frameSize() const; // Functions used to iterate on frames. When prevType is IonFrame_Entry, // the current frame is the last frame. - inline bool more() const { - return type_ != IonFrame_Entry; + inline bool done() const { + return type_ == IonFrame_Entry; } IonFrameIterator &operator++(); // Returns the IonScript associated with this JS frame. IonScript *ionScript() const; // Returns the Safepoint associated with this JS frame. Incurs a lookup // overhead. @@ -160,17 +162,17 @@ class IonActivationIterator IonActivation *activation_; public: IonActivationIterator(JSContext *cx); IonActivationIterator(JSRuntime *rt); IonActivationIterator &operator++(); - IonActivation *activation() { + IonActivation *activation() const { return activation_; } uint8 *top() const { return top_; } bool more() const; }; @@ -235,16 +237,18 @@ class InlineFrameIterator } jsbytecode *pc() const { return pc_; } SnapshotIterator snapshotIterator() const { return si_; } bool isFunctionFrame() const; + bool isConstructing(IonActivation *activation) const; + JSObject *thisObject() const; InlineFrameIterator operator++(); }; } // namespace ion } // namespace js #endif // jsion_frames_iterator_h__
--- a/js/src/ion/IonFrames.cpp +++ b/js/src/ion/IonFrames.cpp @@ -446,17 +446,17 @@ MarkIonJSFrame(JSTracer *trc, const IonF Value *v = (Value *)layout->slotRef(slot); gc::MarkValueRoot(trc, v, "ion-gc-slot"); } } static void MarkIonActivation(JSTracer *trc, uint8 *top) { - for (IonFrameIterator frames(top); frames.more(); ++frames) { + for (IonFrameIterator frames(top); !frames.done(); ++frames) { switch (frames.type()) { case IonFrame_Exit: // The exit frame gets ignored. break; case IonFrame_JS: MarkIonJSFrame(trc, frames); break; case IonFrame_Rectifier: @@ -725,8 +725,62 @@ MachineState::FromBailout(uintptr_t regs for (unsigned i = 0; i < Registers::Total; i++) machine.setRegisterLocation(Register::FromCode(i), ®s[i]); for (unsigned i = 0; i < FloatRegisters::Total; i++) machine.setRegisterLocation(FloatRegister::FromCode(i), &fpregs[i]); return machine; } +bool +InlineFrameIterator::isConstructing(IonActivation *activation) const +{ + // Skip the current frame and look at the caller's. + if (more()) { + InlineFrameIterator parent(*this); + ++parent; + + // In the case of a JS frame, look up the pc from the snapshot. + JS_ASSERT(js_CodeSpec[*parent.pc()].format & JOF_INVOKE); + + return (JSOp)*parent.pc() == JSOP_NEW; + } + + return frame_->isConstructing(activation); +} + +bool +IonFrameIterator::isConstructing(IonActivation *activation) const +{ + IonFrameIterator parent(*this); + + // Skip the current frame and look at the caller's. + do { + ++parent; + } while (!parent.done() && !parent.isScripted()); + + if (parent.isScripted()) { + // In the case of a JS frame, look up the pc from the snapshot. + InlineFrameIterator inlinedParent(&parent); + JS_ASSERT(js_CodeSpec[*inlinedParent.pc()].format & JOF_INVOKE); + + return (JSOp)*inlinedParent.pc() == JSOP_NEW; + } + + JS_ASSERT(parent.done()); + return activation->entryfp()->isConstructing(); +} + +JSObject * +InlineFrameIterator::thisObject() const +{ + // JS_ASSERT(isConstructing(...)); + SnapshotIterator s(si_); + + // scopeChain + s.skip(); + + // In strict modes, |this| may not be an object and thus may not be + // readable which can either segv in read or trigger the assertion. + Value v = s.read(); + JS_ASSERT(v.isObject()); + return &v.toObject(); +}
--- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -153,19 +153,16 @@ fun_getProperty(JSContext *cx, JSObject if (!argsobj) return false; *vp = ObjectValue(*argsobj); return true; } - StackIter prev(iter); - ++prev; - #ifdef JS_METHODJIT if (JSID_IS_ATOM(id, cx->runtime->atomState.callerAtom) && fp && fp->prev()) { /* * If the frame was called from within an inlined frame, mark the * innermost function as uninlineable to expand its frame and allow us * to recover its callee object. */ JSInlinedSite *inlined;
--- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -1114,17 +1114,17 @@ MarkRangeConservativelyAndSkipIon(JSTrac const uintptr_t *i = begin; #if JS_STACK_GROWTH_DIRECTION < 0 && defined(JS_ION) // Walk only regions in between Ion activations. Note that non-volatile // registers are spilled to the stack before the entry Ion frame, ensuring // that the conservative scanner will still see them. for (ion::IonActivationIterator ion(rt); ion.more(); ++ion) { ion::IonFrameIterator frames(ion.top()); - while (frames.more()) + while (!frames.done()) ++frames; uintptr_t *ionMin = (uintptr_t *)ion.top(); uintptr_t *ionEnd = (uintptr_t *)frames.fp(); MarkRangeConservatively(trc, i, ionMin); i = ionEnd; }
--- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -3077,21 +3077,20 @@ TypeObject::clearNewScript(JSContext *cx * script keeps track of where each property is initialized so we can walk * the stack and fix up any such objects. */ Vector<uint32_t, 32> pcOffsets(cx); for (ScriptFrameIter iter(cx); !iter.done(); ++iter) { pcOffsets.append(uint32_t(iter.pc() - iter.script()->code)); if (iter.isConstructing() && iter.callee() == newScript->fun && - iter.thisv().isObject() && - !iter.thisv().toObject().hasLazyType() && - iter.thisv().toObject().type() == this) + !iter.thisObject()->hasLazyType() && + iter.thisObject()->type() == this) { - JSObject *obj = &iter.thisv().toObject(); + JSObject *obj = iter.thisObject(); /* Whether all identified 'new' properties have been initialized. */ bool finished = false; /* If not finished, number of properties that have been added. */ uint32_t numProperties = 0; /*
--- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -6302,16 +6302,16 @@ js_DumpBacktrace(JSContext *cx) Sprinter sprinter(cx); sprinter.init(); size_t depth = 0; for (StackIter i(cx); !i.done(); ++i, ++depth) { if (i.isScript()) { const char *filename = JS_GetScriptFilename(cx, i.script()); unsigned line = JS_PCToLineNumber(cx, i.script(), i.pc()); sprinter.printf("#%d %14p %s:%d (%p @ %d)\n", - depth, i.fp(), filename, line, + depth, (i.isIon() ? 0 : i.fp()), filename, line, i.script(), i.pc() - i.script()->code); } else { sprinter.printf("#%d ???\n", depth); } } fprintf(stdout, "%s", sprinter.string()); }
--- a/js/src/vm/Stack.cpp +++ b/js/src/vm/Stack.cpp @@ -1171,20 +1171,20 @@ StackIter::settleOnNewState() popFrame(); continue; } #ifdef JS_ION if (fp_->runningInIon()) { ionFrames_ = ion::IonFrameIterator(ionActivations_.top()); - while (ionFrames_.more() && !ionFrames_.isScripted()) + while (!ionFrames_.done() && !ionFrames_.isScripted()) ++ionFrames_; - if (!ionFrames_.more()) { + if (ionFrames_.done()) { // In this case, we bailed out the last frame, so we // shouldn't really transition to Ion code. ++ionActivations_; popFrame(); continue; } state_ = ION; @@ -1268,19 +1268,17 @@ StackIter::StackIter(JSContext *cx, Save savedOption_(savedOption) #ifdef JS_ION , ionActivations_(cx), ionFrames_((uint8_t *)NULL), ionInlineFrames_(NULL) #endif { #ifdef JS_METHODJIT - CompartmentVector &v = cx->runtime->compartments; - for (size_t i = 0; i < v.length(); i++) - mjit::ExpandInlineFrames(v[i]); + mjit::ExpandInlineFrames(cx->compartment); #endif if (StackSegment *seg = cx->stack.seg_) { startOnSegment(seg); settleOnNewState(); } else { state_ = DONE; } @@ -1293,20 +1291,20 @@ StackIter::popIonFrame() // Keep fp which describes all ion frames. poisonRegs(); if (ionInlineFrames_.more()) { ++ionInlineFrames_; pc_ = ionInlineFrames_.pc(); script_ = ionInlineFrames_.script(); } else { ++ionFrames_; - while (ionFrames_.more() && !ionFrames_.isScripted()) + while (!ionFrames_.done() && !ionFrames_.isScripted()) ++ionFrames_; - if (ionFrames_.more()) { + if (!ionFrames_.done()) { ionInlineFrames_ = ion::InlineFrameIterator(&ionFrames_); pc_ = ionInlineFrames_.pc(); script_ = ionInlineFrames_.script(); } else { ++ionActivations_; popFrame(); settleOnNewState(); } @@ -1405,16 +1403,18 @@ StackIter::isNonEvalFunctionFrame() cons bool StackIter::isConstructing() const { switch (state_) { case DONE: JS_NOT_REACHED("Unexpected state"); return false; + case ION: + return ionInlineFrames_.isConstructing(ionActivations_.activation()); case SCRIPTED: case NATIVE: case IMPLICIT_NATIVE: return fp()->isConstructing(); } return false; } @@ -1451,30 +1451,31 @@ StackIter::calleev() const case NATIVE: case IMPLICIT_NATIVE: return nativeArgs().calleev(); } JS_NOT_REACHED("Unexpected state"); return Value(); } -Value -StackIter::thisv() const +JSObject * +StackIter::thisObject() const { switch (state_) { case DONE: - MOZ_NOT_REACHED("Unexpected state"); - return Value(); + break; + case ION: + return ionInlineFrames_.thisObject(); case SCRIPTED: case NATIVE: case IMPLICIT_NATIVE: - return fp()->thisValue(); + return &fp()->thisValue().toObject(); } - MOZ_NOT_REACHED("unexpected state"); - return Value(); + JS_NOT_REACHED("Unexpected state"); + return NULL; } /*****************************************************************************/ AllFramesIter::AllFramesIter(StackSpace &space) : seg_(space.seg_), fp_(seg_ ? seg_->maybefp() : NULL) {
--- a/js/src/vm/Stack.h +++ b/js/src/vm/Stack.h @@ -1833,21 +1833,17 @@ class StackIter { friend class ContextStack; JSContext *cx_; public: enum SavedOption { STOP_AT_SAVED, GO_THROUGH_SAVED }; private: SavedOption savedOption_; - enum State { DONE, SCRIPTED, NATIVE, IMPLICIT_NATIVE -#ifdef JS_ION - , ION -#endif - }; + enum State { DONE, SCRIPTED, NATIVE, IMPLICIT_NATIVE, ION }; State state_; StackFrame *fp_; CallArgsList *calls_; StackSegment *seg_; Value *sp_; @@ -1876,37 +1872,39 @@ class StackIter bool done() const { return state_ == DONE; } StackIter &operator++(); bool operator==(const StackIter &rhs) const; bool operator!=(const StackIter &rhs) const { return !(*this == rhs); } bool isScript() const { JS_ASSERT(!done()); return state_ == SCRIPTED || state_ == ION; } + bool isIon() const { JS_ASSERT(!done()); return state_ == ION; } bool isImplicitNativeCall() const { JS_ASSERT(!done()); return state_ == IMPLICIT_NATIVE; } bool isNativeCall() const { JS_ASSERT(!done()); return state_ == NATIVE || state_ == IMPLICIT_NATIVE; } bool isFunctionFrame() const; bool isEvalFrame() const; bool isNonEvalFunctionFrame() const; bool isConstructing() const; + // :TODO: Add && !isIon() in JS_ASSERT of fp() and sp(). StackFrame *fp() const { JS_ASSERT(isScript()); return fp_; } Value *sp() const { JS_ASSERT(isScript()); return sp_; } jsbytecode *pc() const { JS_ASSERT(isScript()); return pc_; } JSScript *script() const { JS_ASSERT(isScript()); return script_; } JSFunction *callee() const; Value calleev() const; - Value thisv() const; + JSObject *thisObject() const; CallArgs nativeArgs() const { JS_ASSERT(isNativeCall()); return args_; } }; /* A filtering of the StackIter to only stop at scripts. */ class ScriptFrameIter : public StackIter { void settle() {