michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: set ts=8 sts=4 et sw=4 tw=99: michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef vm_Stack_inl_h michael@0: #define vm_Stack_inl_h michael@0: michael@0: #include "vm/Stack.h" michael@0: michael@0: #include "mozilla/PodOperations.h" michael@0: michael@0: #include "jscntxt.h" michael@0: michael@0: #include "jit/BaselineFrame.h" michael@0: #include "jit/RematerializedFrame.h" michael@0: #include "vm/ScopeObject.h" michael@0: michael@0: #include "jsobjinlines.h" michael@0: michael@0: #include "jit/BaselineFrame-inl.h" michael@0: michael@0: namespace js { michael@0: michael@0: /* michael@0: * We cache name lookup results only for the global object or for native michael@0: * non-global objects without prototype or with prototype that never mutates, michael@0: * see bug 462734 and bug 487039. michael@0: */ michael@0: static inline bool michael@0: IsCacheableNonGlobalScope(JSObject *obj) michael@0: { michael@0: bool cacheable = (obj->is() || obj->is() || obj->is()); michael@0: michael@0: JS_ASSERT_IF(cacheable, !obj->getOps()->lookupProperty); michael@0: return cacheable; michael@0: } michael@0: michael@0: inline HandleObject michael@0: InterpreterFrame::scopeChain() const michael@0: { michael@0: JS_ASSERT_IF(!(flags_ & HAS_SCOPECHAIN), isFunctionFrame()); michael@0: if (!(flags_ & HAS_SCOPECHAIN)) { michael@0: scopeChain_ = callee().environment(); michael@0: flags_ |= HAS_SCOPECHAIN; michael@0: } michael@0: return HandleObject::fromMarkedLocation(&scopeChain_); michael@0: } michael@0: michael@0: inline GlobalObject & michael@0: InterpreterFrame::global() const michael@0: { michael@0: return scopeChain()->global(); michael@0: } michael@0: michael@0: inline JSObject & michael@0: InterpreterFrame::varObj() michael@0: { michael@0: JSObject *obj = scopeChain(); michael@0: while (!obj->isVarObj()) michael@0: obj = obj->enclosingScope(); michael@0: return *obj; michael@0: } michael@0: michael@0: inline JSCompartment * michael@0: InterpreterFrame::compartment() const michael@0: { michael@0: JS_ASSERT(scopeChain()->compartment() == script()->compartment()); michael@0: return scopeChain()->compartment(); michael@0: } michael@0: michael@0: inline void michael@0: InterpreterFrame::initCallFrame(JSContext *cx, InterpreterFrame *prev, jsbytecode *prevpc, michael@0: Value *prevsp, JSFunction &callee, JSScript *script, Value *argv, michael@0: uint32_t nactual, InterpreterFrame::Flags flagsArg) michael@0: { michael@0: JS_ASSERT((flagsArg & ~CONSTRUCTING) == 0); michael@0: JS_ASSERT(callee.nonLazyScript() == script); michael@0: michael@0: /* Initialize stack frame members. */ michael@0: flags_ = FUNCTION | HAS_SCOPECHAIN | flagsArg; michael@0: argv_ = argv; michael@0: exec.fun = &callee; michael@0: u.nactual = nactual; michael@0: scopeChain_ = callee.environment(); michael@0: prev_ = prev; michael@0: prevpc_ = prevpc; michael@0: prevsp_ = prevsp; michael@0: JS_ASSERT(!hasHookData()); michael@0: michael@0: initVarsToUndefined(); michael@0: } michael@0: michael@0: inline void michael@0: InterpreterFrame::initVarsToUndefined() michael@0: { michael@0: SetValueRangeToUndefined(slots(), script()->nfixed()); michael@0: } michael@0: michael@0: inline Value & michael@0: InterpreterFrame::unaliasedVar(uint32_t i, MaybeCheckAliasing checkAliasing) michael@0: { michael@0: JS_ASSERT_IF(checkAliasing, !script()->varIsAliased(i)); michael@0: JS_ASSERT(i < script()->nfixedvars()); michael@0: return slots()[i]; michael@0: } michael@0: michael@0: inline Value & michael@0: InterpreterFrame::unaliasedLocal(uint32_t i, MaybeCheckAliasing checkAliasing) michael@0: { michael@0: JS_ASSERT(i < script()->nfixed()); michael@0: #ifdef DEBUG michael@0: CheckLocalUnaliased(checkAliasing, script(), i); michael@0: #endif michael@0: return slots()[i]; michael@0: } michael@0: michael@0: inline Value & michael@0: InterpreterFrame::unaliasedFormal(unsigned i, MaybeCheckAliasing checkAliasing) michael@0: { michael@0: JS_ASSERT(i < numFormalArgs()); michael@0: JS_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals()); michael@0: JS_ASSERT_IF(checkAliasing, !script()->formalIsAliased(i)); michael@0: return argv()[i]; michael@0: } michael@0: michael@0: inline Value & michael@0: InterpreterFrame::unaliasedActual(unsigned i, MaybeCheckAliasing checkAliasing) michael@0: { michael@0: JS_ASSERT(i < numActualArgs()); michael@0: JS_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals()); michael@0: JS_ASSERT_IF(checkAliasing && i < numFormalArgs(), !script()->formalIsAliased(i)); michael@0: return argv()[i]; michael@0: } michael@0: michael@0: template michael@0: inline void michael@0: InterpreterFrame::unaliasedForEachActual(Op op) michael@0: { michael@0: // Don't assert !script()->funHasAnyAliasedFormal() since this function is michael@0: // called from ArgumentsObject::createUnexpected() which can access aliased michael@0: // slots. michael@0: michael@0: const Value *argsEnd = argv() + numActualArgs(); michael@0: for (const Value *p = argv(); p < argsEnd; ++p) michael@0: op(*p); michael@0: } michael@0: michael@0: struct CopyTo michael@0: { michael@0: Value *dst; michael@0: CopyTo(Value *dst) : dst(dst) {} michael@0: void operator()(const Value &src) { *dst++ = src; } michael@0: }; michael@0: michael@0: struct CopyToHeap michael@0: { michael@0: HeapValue *dst; michael@0: CopyToHeap(HeapValue *dst) : dst(dst) {} michael@0: void operator()(const Value &src) { dst->init(src); ++dst; } michael@0: }; michael@0: michael@0: inline ArgumentsObject & michael@0: InterpreterFrame::argsObj() const michael@0: { michael@0: JS_ASSERT(script()->needsArgsObj()); michael@0: JS_ASSERT(flags_ & HAS_ARGS_OBJ); michael@0: return *argsObj_; michael@0: } michael@0: michael@0: inline void michael@0: InterpreterFrame::initArgsObj(ArgumentsObject &argsobj) michael@0: { michael@0: JS_ASSERT(script()->needsArgsObj()); michael@0: flags_ |= HAS_ARGS_OBJ; michael@0: argsObj_ = &argsobj; michael@0: } michael@0: michael@0: inline ScopeObject & michael@0: InterpreterFrame::aliasedVarScope(ScopeCoordinate sc) const michael@0: { michael@0: JSObject *scope = &scopeChain()->as(); michael@0: for (unsigned i = sc.hops(); i; i--) michael@0: scope = &scope->as().enclosingScope(); michael@0: return scope->as(); michael@0: } michael@0: michael@0: inline void michael@0: InterpreterFrame::pushOnScopeChain(ScopeObject &scope) michael@0: { michael@0: JS_ASSERT(*scopeChain() == scope.enclosingScope() || michael@0: *scopeChain() == scope.as().enclosingScope().as().enclosingScope()); michael@0: scopeChain_ = &scope; michael@0: flags_ |= HAS_SCOPECHAIN; michael@0: } michael@0: michael@0: inline void michael@0: InterpreterFrame::popOffScopeChain() michael@0: { michael@0: JS_ASSERT(flags_ & HAS_SCOPECHAIN); michael@0: scopeChain_ = &scopeChain_->as().enclosingScope(); michael@0: } michael@0: michael@0: bool michael@0: InterpreterFrame::hasCallObj() const michael@0: { michael@0: JS_ASSERT(isStrictEvalFrame() || fun()->isHeavyweight()); michael@0: return flags_ & HAS_CALL_OBJ; michael@0: } michael@0: michael@0: inline CallObject & michael@0: InterpreterFrame::callObj() const michael@0: { michael@0: JS_ASSERT(fun()->isHeavyweight()); michael@0: michael@0: JSObject *pobj = scopeChain(); michael@0: while (MOZ_UNLIKELY(!pobj->is())) michael@0: pobj = pobj->enclosingScope(); michael@0: return pobj->as(); michael@0: } michael@0: michael@0: /*****************************************************************************/ michael@0: michael@0: inline void michael@0: InterpreterStack::purge(JSRuntime *rt) michael@0: { michael@0: rt->freeLifoAlloc.transferUnusedFrom(&allocator_); michael@0: } michael@0: michael@0: uint8_t * michael@0: InterpreterStack::allocateFrame(JSContext *cx, size_t size) michael@0: { michael@0: size_t maxFrames; michael@0: if (cx->compartment()->principals == cx->runtime()->trustedPrincipals()) michael@0: maxFrames = MAX_FRAMES_TRUSTED; michael@0: else michael@0: maxFrames = MAX_FRAMES; michael@0: michael@0: if (MOZ_UNLIKELY(frameCount_ >= maxFrames)) { michael@0: js_ReportOverRecursed(cx); michael@0: return nullptr; michael@0: } michael@0: michael@0: uint8_t *buffer = reinterpret_cast(allocator_.alloc(size)); michael@0: if (!buffer) michael@0: return nullptr; michael@0: michael@0: frameCount_++; michael@0: return buffer; michael@0: } michael@0: michael@0: MOZ_ALWAYS_INLINE InterpreterFrame * michael@0: InterpreterStack::getCallFrame(JSContext *cx, const CallArgs &args, HandleScript script, michael@0: InterpreterFrame::Flags *flags, Value **pargv) michael@0: { michael@0: JSFunction *fun = &args.callee().as(); michael@0: michael@0: JS_ASSERT(fun->nonLazyScript() == script); michael@0: unsigned nformal = fun->nargs(); michael@0: unsigned nvals = script->nslots(); michael@0: michael@0: if (args.length() >= nformal) { michael@0: *pargv = args.array(); michael@0: uint8_t *buffer = allocateFrame(cx, sizeof(InterpreterFrame) + nvals * sizeof(Value)); michael@0: return reinterpret_cast(buffer); michael@0: } michael@0: michael@0: // Pad any missing arguments with |undefined|. michael@0: JS_ASSERT(args.length() < nformal); michael@0: michael@0: nvals += nformal + 2; // Include callee, |this|. michael@0: uint8_t *buffer = allocateFrame(cx, sizeof(InterpreterFrame) + nvals * sizeof(Value)); michael@0: if (!buffer) michael@0: return nullptr; michael@0: michael@0: Value *argv = reinterpret_cast(buffer); michael@0: unsigned nmissing = nformal - args.length(); michael@0: michael@0: mozilla::PodCopy(argv, args.base(), 2 + args.length()); michael@0: SetValueRangeToUndefined(argv + 2 + args.length(), nmissing); michael@0: michael@0: *pargv = argv + 2; michael@0: return reinterpret_cast(argv + 2 + nformal); michael@0: } michael@0: michael@0: MOZ_ALWAYS_INLINE bool michael@0: InterpreterStack::pushInlineFrame(JSContext *cx, InterpreterRegs ®s, const CallArgs &args, michael@0: HandleScript script, InitialFrameFlags initial) michael@0: { michael@0: RootedFunction callee(cx, &args.callee().as()); michael@0: JS_ASSERT(regs.sp == args.end()); michael@0: JS_ASSERT(callee->nonLazyScript() == script); michael@0: michael@0: script->ensureNonLazyCanonicalFunction(cx); michael@0: michael@0: InterpreterFrame *prev = regs.fp(); michael@0: jsbytecode *prevpc = regs.pc; michael@0: Value *prevsp = regs.sp; michael@0: JS_ASSERT(prev); michael@0: michael@0: LifoAlloc::Mark mark = allocator_.mark(); michael@0: michael@0: InterpreterFrame::Flags flags = ToFrameFlags(initial); michael@0: Value *argv; michael@0: InterpreterFrame *fp = getCallFrame(cx, args, script, &flags, &argv); michael@0: if (!fp) michael@0: return false; michael@0: michael@0: fp->mark_ = mark; michael@0: michael@0: /* Initialize frame, locals, regs. */ michael@0: fp->initCallFrame(cx, prev, prevpc, prevsp, *callee, script, argv, args.length(), flags); michael@0: michael@0: regs.prepareToRun(*fp, script); michael@0: return true; michael@0: } michael@0: michael@0: MOZ_ALWAYS_INLINE void michael@0: InterpreterStack::popInlineFrame(InterpreterRegs ®s) michael@0: { michael@0: InterpreterFrame *fp = regs.fp(); michael@0: regs.popInlineFrame(); michael@0: regs.sp[-1] = fp->returnValue(); michael@0: releaseFrame(fp); michael@0: JS_ASSERT(regs.fp()); michael@0: } michael@0: michael@0: template michael@0: inline void michael@0: FrameIter::unaliasedForEachActual(JSContext *cx, Op op) michael@0: { michael@0: switch (data_.state_) { michael@0: case DONE: michael@0: case ASMJS: michael@0: break; michael@0: case INTERP: michael@0: interpFrame()->unaliasedForEachActual(op); michael@0: return; michael@0: case JIT: michael@0: #ifdef JS_ION michael@0: if (data_.jitFrames_.isIonJS()) { michael@0: ionInlineFrames_.unaliasedForEachActual(cx, op, jit::ReadFrame_Actuals); michael@0: } else { michael@0: JS_ASSERT(data_.jitFrames_.isBaselineJS()); michael@0: data_.jitFrames_.unaliasedForEachActual(op, jit::ReadFrame_Actuals); michael@0: } michael@0: return; michael@0: #else michael@0: break; michael@0: #endif michael@0: } michael@0: MOZ_ASSUME_UNREACHABLE("Unexpected state"); michael@0: } michael@0: michael@0: inline void * michael@0: AbstractFramePtr::maybeHookData() const michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->maybeHookData(); michael@0: #ifdef JS_ION michael@0: return asBaselineFrame()->maybeHookData(); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: michael@0: inline void michael@0: AbstractFramePtr::setHookData(void *data) const michael@0: { michael@0: if (isInterpreterFrame()) { michael@0: asInterpreterFrame()->setHookData(data); michael@0: return; michael@0: } michael@0: #ifdef JS_ION michael@0: asBaselineFrame()->setHookData(data); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: michael@0: inline HandleValue michael@0: AbstractFramePtr::returnValue() const michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->returnValue(); michael@0: #ifdef JS_ION michael@0: return asBaselineFrame()->returnValue(); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: michael@0: inline void michael@0: AbstractFramePtr::setReturnValue(const Value &rval) const michael@0: { michael@0: if (isInterpreterFrame()) { michael@0: asInterpreterFrame()->setReturnValue(rval); michael@0: return; michael@0: } michael@0: #ifdef JS_ION michael@0: asBaselineFrame()->setReturnValue(rval); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: michael@0: inline JSObject * michael@0: AbstractFramePtr::scopeChain() const michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->scopeChain(); michael@0: #ifdef JS_ION michael@0: if (isBaselineFrame()) michael@0: return asBaselineFrame()->scopeChain(); michael@0: return asRematerializedFrame()->scopeChain(); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: michael@0: inline void michael@0: AbstractFramePtr::pushOnScopeChain(ScopeObject &scope) michael@0: { michael@0: if (isInterpreterFrame()) { michael@0: asInterpreterFrame()->pushOnScopeChain(scope); michael@0: return; michael@0: } michael@0: #ifdef JS_ION michael@0: asBaselineFrame()->pushOnScopeChain(scope); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: michael@0: inline CallObject & michael@0: AbstractFramePtr::callObj() const michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->callObj(); michael@0: #ifdef JS_ION michael@0: if (isBaselineFrame()) michael@0: return asBaselineFrame()->callObj(); michael@0: return asRematerializedFrame()->callObj(); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: michael@0: inline bool michael@0: AbstractFramePtr::initFunctionScopeObjects(JSContext *cx) michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->initFunctionScopeObjects(cx); michael@0: #ifdef JS_ION michael@0: return asBaselineFrame()->initFunctionScopeObjects(cx); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: michael@0: inline JSCompartment * michael@0: AbstractFramePtr::compartment() const michael@0: { michael@0: return scopeChain()->compartment(); michael@0: } michael@0: michael@0: inline unsigned michael@0: AbstractFramePtr::numActualArgs() const michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->numActualArgs(); michael@0: #ifdef JS_ION michael@0: if (isBaselineFrame()) michael@0: return asBaselineFrame()->numActualArgs(); michael@0: return asRematerializedFrame()->numActualArgs(); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: inline unsigned michael@0: AbstractFramePtr::numFormalArgs() const michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->numFormalArgs(); michael@0: #ifdef JS_ION michael@0: if (isBaselineFrame()) michael@0: return asBaselineFrame()->numFormalArgs(); michael@0: return asRematerializedFrame()->numActualArgs(); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: michael@0: inline Value & michael@0: AbstractFramePtr::unaliasedVar(uint32_t i, MaybeCheckAliasing checkAliasing) michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->unaliasedVar(i, checkAliasing); michael@0: #ifdef JS_ION michael@0: if (isBaselineFrame()) michael@0: return asBaselineFrame()->unaliasedVar(i, checkAliasing); michael@0: return asRematerializedFrame()->unaliasedVar(i, checkAliasing); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: michael@0: inline Value & michael@0: AbstractFramePtr::unaliasedLocal(uint32_t i, MaybeCheckAliasing checkAliasing) michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->unaliasedLocal(i, checkAliasing); michael@0: #ifdef JS_ION michael@0: if (isBaselineFrame()) michael@0: return asBaselineFrame()->unaliasedLocal(i, checkAliasing); michael@0: return asRematerializedFrame()->unaliasedLocal(i, checkAliasing); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: michael@0: inline Value & michael@0: AbstractFramePtr::unaliasedFormal(unsigned i, MaybeCheckAliasing checkAliasing) michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->unaliasedFormal(i, checkAliasing); michael@0: #ifdef JS_ION michael@0: if (isBaselineFrame()) michael@0: return asBaselineFrame()->unaliasedFormal(i, checkAliasing); michael@0: return asRematerializedFrame()->unaliasedFormal(i, checkAliasing); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: michael@0: inline Value & michael@0: AbstractFramePtr::unaliasedActual(unsigned i, MaybeCheckAliasing checkAliasing) michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->unaliasedActual(i, checkAliasing); michael@0: #ifdef JS_ION michael@0: if (isBaselineFrame()) michael@0: return asBaselineFrame()->unaliasedActual(i, checkAliasing); michael@0: return asRematerializedFrame()->unaliasedActual(i, checkAliasing); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: michael@0: inline bool michael@0: AbstractFramePtr::hasCallObj() const michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->hasCallObj(); michael@0: #ifdef JS_ION michael@0: if (isBaselineFrame()) michael@0: return asBaselineFrame()->hasCallObj(); michael@0: return asRematerializedFrame()->hasCallObj(); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: inline bool michael@0: AbstractFramePtr::useNewType() const michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->useNewType(); michael@0: return false; michael@0: } michael@0: inline bool michael@0: AbstractFramePtr::isGeneratorFrame() const michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->isGeneratorFrame(); michael@0: return false; michael@0: } michael@0: inline bool michael@0: AbstractFramePtr::isYielding() const michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->isYielding(); michael@0: return false; michael@0: } michael@0: inline bool michael@0: AbstractFramePtr::isFunctionFrame() const michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->isFunctionFrame(); michael@0: #ifdef JS_ION michael@0: if (isBaselineFrame()) michael@0: return asBaselineFrame()->isFunctionFrame(); michael@0: return asRematerializedFrame()->isFunctionFrame(); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: inline bool michael@0: AbstractFramePtr::isGlobalFrame() const michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->isGlobalFrame(); michael@0: #ifdef JS_ION michael@0: if (isBaselineFrame()) michael@0: return asBaselineFrame()->isGlobalFrame(); michael@0: return asRematerializedFrame()->isGlobalFrame(); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: inline bool michael@0: AbstractFramePtr::isEvalFrame() const michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->isEvalFrame(); michael@0: #ifdef JS_ION michael@0: if (isBaselineFrame()) michael@0: return asBaselineFrame()->isEvalFrame(); michael@0: MOZ_ASSERT(isRematerializedFrame()); michael@0: return false; michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: inline bool michael@0: AbstractFramePtr::isFramePushedByExecute() const michael@0: { michael@0: return isGlobalFrame() || isEvalFrame(); michael@0: } michael@0: inline bool michael@0: AbstractFramePtr::isDebuggerFrame() const michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->isDebuggerFrame(); michael@0: #ifdef JS_ION michael@0: if (isBaselineFrame()) michael@0: return asBaselineFrame()->isDebuggerFrame(); michael@0: MOZ_ASSERT(isRematerializedFrame()); michael@0: return false; michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: inline bool michael@0: AbstractFramePtr::hasArgs() const { michael@0: return isNonEvalFunctionFrame(); michael@0: } michael@0: inline JSScript * michael@0: AbstractFramePtr::script() const michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->script(); michael@0: #ifdef JS_ION michael@0: if (isBaselineFrame()) michael@0: return asBaselineFrame()->script(); michael@0: return asRematerializedFrame()->script(); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: inline JSFunction * michael@0: AbstractFramePtr::fun() const michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->fun(); michael@0: #ifdef JS_ION michael@0: if (isBaselineFrame()) michael@0: return asBaselineFrame()->fun(); michael@0: return asRematerializedFrame()->fun(); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: inline JSFunction * michael@0: AbstractFramePtr::maybeFun() const michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->maybeFun(); michael@0: #ifdef JS_ION michael@0: if (isBaselineFrame()) michael@0: return asBaselineFrame()->maybeFun(); michael@0: return asRematerializedFrame()->maybeFun(); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: inline JSFunction * michael@0: AbstractFramePtr::callee() const michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return &asInterpreterFrame()->callee(); michael@0: #ifdef JS_ION michael@0: if (isBaselineFrame()) michael@0: return asBaselineFrame()->callee(); michael@0: return asRematerializedFrame()->callee(); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: inline Value michael@0: AbstractFramePtr::calleev() const michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->calleev(); michael@0: #ifdef JS_ION michael@0: if (isBaselineFrame()) michael@0: return asBaselineFrame()->calleev(); michael@0: return asRematerializedFrame()->calleev(); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: inline bool michael@0: AbstractFramePtr::isNonEvalFunctionFrame() const michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->isNonEvalFunctionFrame(); michael@0: #ifdef JS_ION michael@0: if (isBaselineFrame()) michael@0: return asBaselineFrame()->isNonEvalFunctionFrame(); michael@0: return asRematerializedFrame()->isNonEvalFunctionFrame(); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: inline bool michael@0: AbstractFramePtr::isNonStrictDirectEvalFrame() const michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->isNonStrictDirectEvalFrame(); michael@0: #ifdef JS_ION michael@0: if (isBaselineFrame()) michael@0: return asBaselineFrame()->isNonStrictDirectEvalFrame(); michael@0: MOZ_ASSERT(isRematerializedFrame()); michael@0: return false; michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: inline bool michael@0: AbstractFramePtr::isStrictEvalFrame() const michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->isStrictEvalFrame(); michael@0: #ifdef JS_ION michael@0: if (isBaselineFrame()) michael@0: return asBaselineFrame()->isStrictEvalFrame(); michael@0: MOZ_ASSERT(isRematerializedFrame()); michael@0: return false; michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: michael@0: inline Value * michael@0: AbstractFramePtr::argv() const michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->argv(); michael@0: #ifdef JS_ION michael@0: if (isBaselineFrame()) michael@0: return asBaselineFrame()->argv(); michael@0: return asRematerializedFrame()->argv(); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: michael@0: inline bool michael@0: AbstractFramePtr::hasArgsObj() const michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->hasArgsObj(); michael@0: #ifdef JS_ION michael@0: if (isBaselineFrame()) michael@0: return asBaselineFrame()->hasArgsObj(); michael@0: return asRematerializedFrame()->hasArgsObj(); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: inline ArgumentsObject & michael@0: AbstractFramePtr::argsObj() const michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->argsObj(); michael@0: #ifdef JS_ION michael@0: if (isBaselineFrame()) michael@0: return asBaselineFrame()->argsObj(); michael@0: return asRematerializedFrame()->argsObj(); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: inline void michael@0: AbstractFramePtr::initArgsObj(ArgumentsObject &argsobj) const michael@0: { michael@0: if (isInterpreterFrame()) { michael@0: asInterpreterFrame()->initArgsObj(argsobj); michael@0: return; michael@0: } michael@0: #ifdef JS_ION michael@0: asBaselineFrame()->initArgsObj(argsobj); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: inline bool michael@0: AbstractFramePtr::copyRawFrameSlots(AutoValueVector *vec) const michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->copyRawFrameSlots(vec); michael@0: #ifdef JS_ION michael@0: return asBaselineFrame()->copyRawFrameSlots(vec); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: michael@0: inline bool michael@0: AbstractFramePtr::prevUpToDate() const michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->prevUpToDate(); michael@0: #ifdef JS_ION michael@0: if (isBaselineFrame()) michael@0: return asBaselineFrame()->prevUpToDate(); michael@0: return asRematerializedFrame()->prevUpToDate(); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: inline void michael@0: AbstractFramePtr::setPrevUpToDate() const michael@0: { michael@0: if (isInterpreterFrame()) { michael@0: asInterpreterFrame()->setPrevUpToDate(); michael@0: return; michael@0: } michael@0: #ifdef JS_ION michael@0: if (isBaselineFrame()) { michael@0: asBaselineFrame()->setPrevUpToDate(); michael@0: return; michael@0: } michael@0: asRematerializedFrame()->setPrevUpToDate(); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: michael@0: inline Value & michael@0: AbstractFramePtr::thisValue() const michael@0: { michael@0: if (isInterpreterFrame()) michael@0: return asInterpreterFrame()->thisValue(); michael@0: #ifdef JS_ION michael@0: if (isBaselineFrame()) michael@0: return asBaselineFrame()->thisValue(); michael@0: return asRematerializedFrame()->thisValue(); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: michael@0: inline void michael@0: AbstractFramePtr::popBlock(JSContext *cx) const michael@0: { michael@0: if (isInterpreterFrame()) { michael@0: asInterpreterFrame()->popBlock(cx); michael@0: return; michael@0: } michael@0: #ifdef JS_ION michael@0: asBaselineFrame()->popBlock(cx); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: michael@0: inline void michael@0: AbstractFramePtr::popWith(JSContext *cx) const michael@0: { michael@0: if (isInterpreterFrame()) { michael@0: asInterpreterFrame()->popWith(cx); michael@0: return; michael@0: } michael@0: #ifdef JS_ION michael@0: asBaselineFrame()->popWith(cx); michael@0: #else michael@0: MOZ_ASSUME_UNREACHABLE("Invalid frame"); michael@0: #endif michael@0: } michael@0: michael@0: Activation::Activation(JSContext *cx, Kind kind) michael@0: : cx_(cx), michael@0: compartment_(cx->compartment()), michael@0: prev_(cx->mainThread().activation_), michael@0: savedFrameChain_(0), michael@0: hideScriptedCallerCount_(0), michael@0: kind_(kind) michael@0: { michael@0: cx->mainThread().activation_ = this; michael@0: } michael@0: michael@0: Activation::~Activation() michael@0: { michael@0: JS_ASSERT(cx_->mainThread().activation_ == this); michael@0: JS_ASSERT(hideScriptedCallerCount_ == 0); michael@0: cx_->mainThread().activation_ = prev_; michael@0: } michael@0: michael@0: InterpreterActivation::InterpreterActivation(RunState &state, JSContext *cx, michael@0: InterpreterFrame *entryFrame) michael@0: : Activation(cx, Interpreter), michael@0: state_(state), michael@0: entryFrame_(entryFrame), michael@0: opMask_(0) michael@0: #ifdef DEBUG michael@0: , oldFrameCount_(cx_->runtime()->interpreterStack().frameCount_) michael@0: #endif michael@0: { michael@0: if (!state.isGenerator()) { michael@0: regs_.prepareToRun(*entryFrame, state.script()); michael@0: JS_ASSERT(regs_.pc == state.script()->code()); michael@0: } else { michael@0: regs_ = state.asGenerator()->gen()->regs; michael@0: } michael@0: michael@0: JS_ASSERT_IF(entryFrame_->isEvalFrame(), state_.script()->isActiveEval()); michael@0: } michael@0: michael@0: InterpreterActivation::~InterpreterActivation() michael@0: { michael@0: // Pop all inline frames. michael@0: while (regs_.fp() != entryFrame_) michael@0: popInlineFrame(regs_.fp()); michael@0: michael@0: JS_ASSERT(oldFrameCount_ == cx_->runtime()->interpreterStack().frameCount_); michael@0: JS_ASSERT_IF(oldFrameCount_ == 0, cx_->runtime()->interpreterStack().allocator_.used() == 0); michael@0: michael@0: if (state_.isGenerator()) { michael@0: JSGenerator *gen = state_.asGenerator()->gen(); michael@0: gen->fp->unsetPushedSPSFrame(); michael@0: gen->regs = regs_; michael@0: return; michael@0: } michael@0: michael@0: if (entryFrame_) michael@0: cx_->runtime()->interpreterStack().releaseFrame(entryFrame_); michael@0: } michael@0: michael@0: inline bool michael@0: InterpreterActivation::pushInlineFrame(const CallArgs &args, HandleScript script, michael@0: InitialFrameFlags initial) michael@0: { michael@0: if (!cx_->runtime()->interpreterStack().pushInlineFrame(cx_, regs_, args, script, initial)) michael@0: return false; michael@0: JS_ASSERT(regs_.fp()->script()->compartment() == compartment_); michael@0: return true; michael@0: } michael@0: michael@0: inline void michael@0: InterpreterActivation::popInlineFrame(InterpreterFrame *frame) michael@0: { michael@0: (void)frame; // Quell compiler warning. michael@0: JS_ASSERT(regs_.fp() == frame); michael@0: JS_ASSERT(regs_.fp() != entryFrame_); michael@0: michael@0: cx_->runtime()->interpreterStack().popInlineFrame(regs_); michael@0: } michael@0: michael@0: } /* namespace js */ michael@0: michael@0: #endif /* vm_Stack_inl_h */