LCOV - app.info - js/src/vm/Stack-inl.h

LCOV - code coverage report
| Current view: | directory - js/src/vm - Stack-inl.h (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 315 | 299 | 94.9 %
| Date: | 2012-04-07 | Functions: | 36 | 36 | 100.0 %

           1                 : /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
           2                 :  * vim: set ts=4 sw=4 et tw=79 ft=cpp:
           3                 :  *
           4                 :  * ***** BEGIN LICENSE BLOCK *****
           5                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           6                 :  *
           7                 :  * The contents of this file are subject to the Mozilla Public License Version
           8                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           9                 :  * the License. You may obtain a copy of the License at
          10                 :  * http://www.mozilla.org/MPL/
          11                 :  *
          12                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          13                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          14                 :  * for the specific language governing rights and limitations under the
          15                 :  * License.
          16                 :  *
          17                 :  * The Original Code is SpiderMonkey JavaScript engine.
          18                 :  *
          19                 :  * The Initial Developer of the Original Code is
          20                 :  * Mozilla Corporation.
          21                 :  * Portions created by the Initial Developer are Copyright (C) 2009
          22                 :  * the Initial Developer. All Rights Reserved.
          23                 :  *
          24                 :  * Contributor(s):
          25                 :  *   Luke Wagner <luke@mozilla.com>
          26                 :  *
          27                 :  * Alternatively, the contents of this file may be used under the terms of
          28                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          29                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          31                 :  * of those above. If you wish to allow use of your version of this file only
          32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          33                 :  * use your version of this file under the terms of the MPL, indicate your
          34                 :  * decision by deleting the provisions above and replace them with the notice
          35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          36                 :  * the provisions above, a recipient may use your version of this file under
          37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          38                 :  *
          39                 :  * ***** END LICENSE BLOCK ***** */
          40                 :
          41                 : #ifndef Stack_inl_h__
          42                 : #define Stack_inl_h__
          43                 :
          44                 : #include "jscntxt.h"
          45                 : #include "jscompartment.h"
          46                 :
          47                 : #include "methodjit/MethodJIT.h"
          48                 : #include "vm/Stack.h"
          49                 :
          50                 : #include "jsscriptinlines.h"
          51                 :
          52                 : #include "ArgumentsObject-inl.h"
          53                 : #include "ScopeObject-inl.h"
          54                 :
          55                 :
          56                 : namespace js {
          57                 :
          58                 : /*
          59                 :  * We cache name lookup results only for the global object or for native
          60                 :  * non-global objects without prototype or with prototype that never mutates,
          61                 :  * see bug 462734 and bug 487039.
          62                 :  */
          63                 : static inline bool
          64          683963 : IsCacheableNonGlobalScope(JSObject *obj)
          65                 : {
          66          683963 :     bool cacheable = (obj->isCall() || obj->isBlock() || obj->isDeclEnv());
          67                 :
          68          683963 :     JS_ASSERT_IF(cacheable, !obj->getOps()->lookupProperty);
          69          683963 :     return cacheable;
          70                 : }
          71                 :
          72                 : inline JSObject &
          73      1030221999 : StackFrame::scopeChain() const
          74                 : {
          75      1030221999 :     JS_ASSERT_IF(!(flags_ & HAS_SCOPECHAIN), isFunctionFrame());
          76      1030221999 :     if (!(flags_ & HAS_SCOPECHAIN)) {
          77         2981792 :         scopeChain_ = callee().toFunction()->environment();
          78         2981792 :         flags_ |= HAS_SCOPECHAIN;
          79                 :     }
          80      1030221999 :     return *scopeChain_;
          81                 : }
          82                 :
          83                 : inline JSObject &
          84          142185 : StackFrame::varObj()
          85                 : {
          86          142185 :     JSObject *obj = &scopeChain();
          87          285090 :     while (!obj->isVarObj())
          88             720 :         obj = obj->enclosingScope();
          89          142185 :     return *obj;
          90                 : }
          91                 :
          92                 : inline JSCompartment *
          93                 : StackFrame::compartment() const
          94                 : {
          95                 :     JS_ASSERT_IF(isScriptFrame(), scopeChain().compartment() == script()->compartment());
          96                 :     return scopeChain().compartment();
          97                 : }
          98                 :
          99                 : inline void
         100        22102279 : StackFrame::initPrev(JSContext *cx)
         101                 : {
         102        22102279 :     JS_ASSERT(flags_ & HAS_PREVPC);
         103        22102279 :     if (FrameRegs *regs = cx->maybeRegs()) {
         104        22083255 :         prev_ = regs->fp();
         105        22083255 :         prevpc_ = regs->pc;
         106        22083255 :         prevInline_ = regs->inlined();
         107        66187111 :         JS_ASSERT_IF(!prev_->isDummyFrame(),
         108        66187111 :                      uint32_t(prevpc_ - prev_->script()->code) < prev_->script()->length);
         109                 :     } else {
         110           19024 :         prev_ = NULL;
         111                 : #ifdef DEBUG
         112           19024 :         prevpc_ = (jsbytecode *)0xbadc;
         113           19024 :         prevInline_ = (JSInlinedSite *)0xbadc;
         114                 : #endif
         115                 :     }
         116        22102279 : }
         117                 :
         118                 : inline void
         119           19103 : StackFrame::resetGeneratorPrev(JSContext *cx)
         120                 : {
         121           19103 :     flags_ |= HAS_PREVPC;
         122           19103 :     initPrev(cx);
         123           19103 : }
         124                 :
         125                 : inline void
         126             140 : StackFrame::initInlineFrame(JSFunction *fun, StackFrame *prevfp, jsbytecode *prevpc)
         127                 : {
         128                 :     /*
         129                 :      * Note: no need to ensure the scopeChain is instantiated for inline
         130                 :      * frames. Functions which use the scope chain are never inlined.
         131                 :      */
         132             140 :     flags_ = StackFrame::FUNCTION;
         133             140 :     exec.fun = fun;
         134             140 :     resetInlinePrev(prevfp, prevpc);
         135             140 : }
         136                 :
         137                 : inline void
         138             195 : StackFrame::resetInlinePrev(StackFrame *prevfp, jsbytecode *prevpc)
         139                 : {
         140             195 :     JS_ASSERT_IF(flags_ & StackFrame::HAS_PREVPC, prevInline_);
         141             195 :     flags_ |= StackFrame::HAS_PREVPC;
         142             195 :     prev_ = prevfp;
         143             195 :     prevpc_ = prevpc;
         144             195 :     prevInline_ = NULL;
         145             195 : }
         146                 :
         147                 : inline void
         148        21873172 : StackFrame::initCallFrame(JSContext *cx, JSFunction &callee,
         149                 :                           JSScript *script, uint32_t nactual, StackFrame::Flags flagsArg)
         150                 : {
         151               0 :     JS_ASSERT((flagsArg & ~(CONSTRUCTING |
         152                 :                             LOWERED_CALL_APPLY |
         153                 :                             OVERFLOW_ARGS |
         154        21873172 :                             UNDERFLOW_ARGS)) == 0);
         155        21873172 :     JS_ASSERT(script == callee.script());
         156                 :
         157                 :     /* Initialize stack frame members. */
         158        21873172 :     flags_ = FUNCTION | HAS_PREVPC | HAS_SCOPECHAIN | HAS_BLOCKCHAIN | flagsArg;
         159        21873172 :     exec.fun = &callee;
         160        21873172 :     u.nactual = nactual;
         161        21873172 :     scopeChain_ = callee.environment();
         162        21873172 :     ncode_ = NULL;
         163        21873172 :     initPrev(cx);
         164        21873172 :     blockChain_= NULL;
         165        21873172 :     JS_ASSERT(!hasBlockChain());
         166        21873172 :     JS_ASSERT(!hasHookData());
         167        21873172 :     JS_ASSERT(annotation() == NULL);
         168        21873172 :     JS_ASSERT(!hasCallObj());
         169                 :
         170        21873172 :     SetValueRangeToUndefined(slots(), script->nfixed);
         171        21873172 : }
         172                 :
         173                 : /*
         174                 :  * Reinitialize the StackFrame fields that have been initialized up to the
         175                 :  * point of FixupArity in the function prologue.
         176                 :  */
         177                 : inline void
         178          935048 : StackFrame::initFixupFrame(StackFrame *prev, StackFrame::Flags flags, void *ncode, unsigned nactual)
         179                 : {
         180               0 :     JS_ASSERT((flags & ~(CONSTRUCTING |
         181                 :                          LOWERED_CALL_APPLY |
         182                 :                          FUNCTION |
         183                 :                          OVERFLOW_ARGS |
         184          935048 :                          UNDERFLOW_ARGS)) == 0);
         185                 :
         186          935048 :     flags_ = FUNCTION | flags;
         187          935048 :     prev_ = prev;
         188          935048 :     ncode_ = ncode;
         189          935048 :     u.nactual = nactual;
         190          935048 : }
         191                 :
         192                 : inline Value &
         193          210579 : StackFrame::canonicalActualArg(unsigned i) const
         194                 : {
         195          210579 :     if (i < numFormalArgs())
         196           11580 :         return formalArg(i);
         197          198999 :     JS_ASSERT(i < numActualArgs());
         198          198999 :     return actualArgs()[i];
         199                 : }
         200                 :
         201                 : template <class Op>
         202                 : inline bool
         203         6551417 : StackFrame::forEachCanonicalActualArg(Op op, unsigned start /* = 0 */, unsigned count /* = unsigned(-1) */)
         204                 : {
         205         6764264 :     unsigned nformal = fun()->nargs;
         206         6764264 :     JS_ASSERT(start <= nformal);
         207                 :
         208         6764264 :     Value *formals = formalArgsEnd() - nformal;
         209         6764264 :     unsigned nactual = numActualArgs();
         210         6764264 :     if (count == unsigned(-1))
         211         6551417 :         count = nactual - start;
         212                 :
         213         6764264 :     unsigned end = start + count;
         214         6764264 :     JS_ASSERT(end >= start);
         215         6764264 :     JS_ASSERT(end <= nactual);
         216                 :
         217         6764264 :     if (end <= nformal) {
         218         4881697 :         Value *p = formals + start;
         219         5933435 :         for (; start < end; ++p, ++start) {
         220         1051738 :             if (!op(start, p))
         221               0 :                 return false;
         222                 :         }
         223                 :     } else {
         224         2165774 :         for (Value *p = formals + start; start < nformal; ++p, ++start) {
         225          283207 :             if (!op(start, p))
         226               0 :                 return false;
         227                 :         }
         228         1882567 :         JS_ASSERT(start >= nformal);
         229         1882567 :         Value *actuals = formals - (nactual + 2) + start;
         230         8988466 :         for (Value *p = actuals; start < end; ++p, ++start) {
         231         7105899 :             if (!op(start, p))
         232               0 :                 return false;
         233                 :         }
         234                 :     }
         235         6764264 :     return true;
         236                 : }
         237                 :
         238                 : template <class Op>
         239                 : inline bool
         240                 : StackFrame::forEachFormalArg(Op op)
         241                 : {
         242                 :     Value *formals = formalArgsEnd() - fun()->nargs;
         243                 :     Value *formalsEnd = formalArgsEnd();
         244                 :     unsigned i = 0;
         245                 :     for (Value *p = formals; p != formalsEnd; ++p, ++i) {
         246                 :         if (!op(i, p))
         247                 :             return false;
         248                 :     }
         249                 :     return true;
         250                 : }
         251                 :
         252                 : struct CopyTo
         253                 : {
         254                 :     Value *dst;
         255          425289 :     CopyTo(Value *dst) : dst(dst) {}
         256         1040540 :     bool operator()(unsigned, Value *src) {
         257         1040540 :         *dst++ = *src;
         258         1040540 :         return true;
         259                 :     }
         260                 : };
         261                 :
         262                 : inline unsigned
         263        18616370 : StackFrame::numActualArgs() const
         264                 : {
         265                 :     /*
         266                 :      * u.nactual is always coherent, except for method JIT frames where the
         267                 :      * callee does not access its arguments and the number of actual arguments
         268                 :      * matches the number of formal arguments. The JIT requires that all frames
         269                 :      * which do not have an arguments object and use their arguments have a
         270                 :      * coherent u.nactual (even though the below code may not use it), as
         271                 :      * JIT code may access the field directly.
         272                 :      */
         273        18616370 :     JS_ASSERT(hasArgs());
         274        18616370 :     if (JS_UNLIKELY(flags_ & (OVERFLOW_ARGS | UNDERFLOW_ARGS)))
         275         4181585 :         return u.nactual;
         276        14434785 :     return numFormalArgs();
         277                 : }
         278                 :
         279                 : inline Value *
         280        11653680 : StackFrame::actualArgs() const
         281                 : {
         282        11653680 :     JS_ASSERT(hasArgs());
         283        11653680 :     Value *argv = formalArgs();
         284        11653680 :     if (JS_UNLIKELY(flags_ & OVERFLOW_ARGS))
         285         1523941 :         return argv - (2 + u.nactual);
         286        10129739 :     return argv;
         287                 : }
         288                 :
         289                 : inline Value *
         290         5767206 : StackFrame::actualArgsEnd() const
         291                 : {
         292         5767206 :     JS_ASSERT(hasArgs());
         293         5767206 :     if (JS_UNLIKELY(flags_ & OVERFLOW_ARGS))
         294         1078934 :         return formalArgs() - 2;
         295         4688272 :     return formalArgs() + numActualArgs();
         296                 : }
         297                 :
         298                 : inline void
         299          217422 : StackFrame::setScopeChainNoCallObj(JSObject &obj)
         300                 : {
         301                 : #ifdef DEBUG
         302          217422 :     JS_ASSERT(&obj != NULL);
         303          217422 :     if (&obj != sInvalidScopeChain) {
         304          217422 :         if (hasCallObj()) {
         305            4250 :             JSObject *pobj = &obj;
         306            8599 :             while (pobj && pobj->getPrivate() != this)
         307              99 :                 pobj = pobj->enclosingScope();
         308            4250 :             JS_ASSERT(pobj);
         309                 :         } else {
         310          215062 :             for (JSObject *pobj = &obj; pobj->isScope(); pobj = pobj->enclosingScope())
         311            1890 :                 JS_ASSERT_IF(pobj->isCall(), pobj->getPrivate() != this);
         312                 :         }
         313                 :     }
         314                 : #endif
         315          217422 :     scopeChain_ = &obj;
         316          217422 :     flags_ |= HAS_SCOPECHAIN;
         317          217422 : }
         318                 :
         319                 : inline void
         320          745077 : StackFrame::setScopeChainWithOwnCallObj(CallObject &obj)
         321                 : {
         322          745077 :     JS_ASSERT(&obj != NULL);
         323          745077 :     JS_ASSERT(!hasCallObj() && obj.maybeStackFrame() == this);
         324          745077 :     scopeChain_ = &obj;
         325          745077 :     flags_ |= HAS_SCOPECHAIN | HAS_CALL_OBJ;
         326          745077 : }
         327                 :
         328                 : inline CallObject &
         329         1159593 : StackFrame::callObj() const
         330                 : {
         331         1159593 :     JS_ASSERT_IF(isNonEvalFunctionFrame() || isStrictEvalFrame(), hasCallObj());
         332                 :
         333         1159593 :     JSObject *pobj = &scopeChain();
         334         2319303 :     while (JS_UNLIKELY(!pobj->isCall()))
         335             117 :         pobj = pobj->enclosingScope();
         336         1159593 :     return pobj->asCall();
         337                 : }
         338                 :
         339                 : inline bool
         340        15365746 : StackFrame::maintainNestingState() const
         341                 : {
         342                 :     /*
         343                 :      * Whether to invoke the nesting epilogue/prologue to maintain active
         344                 :      * frame counts and check for reentrant outer functions.
         345                 :      */
         346        15365746 :     return isNonEvalFunctionFrame() && !isGeneratorFrame() && script()->nesting();
         347                 : }
         348                 :
         349                 : inline bool
         350        22242544 : StackFrame::functionPrologue(JSContext *cx)
         351                 : {
         352        22242544 :     JS_ASSERT(isNonEvalFunctionFrame());
         353        22242544 :     JS_ASSERT(!isGeneratorFrame());
         354                 :
         355        22242544 :     JSFunction *fun = this->fun();
         356        22242544 :     JSScript *script = fun->script();
         357                 :
         358        22242544 :     if (script->needsArgsObj() && !ArgumentsObject::create(cx, this))
         359               0 :         return false;
         360                 :
         361        22242544 :     if (fun->isHeavyweight()) {
         362          742143 :         if (!CallObject::createForFunction(cx, this))
         363               0 :             return false;
         364                 :     } else {
         365                 :         /* Force instantiation of the scope chain, for JIT frames. */
         366        21500401 :         scopeChain();
         367                 :     }
         368                 :
         369        22242544 :     if (script->nesting()) {
         370          796707 :         JS_ASSERT(maintainNestingState());
         371          796707 :         types::NestingPrologue(cx, this);
         372                 :     }
         373                 :
         374        22242544 :     return true;
         375                 : }
         376                 :
         377                 : inline void
         378        13451255 : StackFrame::functionEpilogue()
         379                 : {
         380        13451255 :     JS_ASSERT(isNonEvalFunctionFrame());
         381                 :
         382        13451255 :     if (flags_ & (HAS_ARGS_OBJ | HAS_CALL_OBJ)) {
         383         1073348 :         if (hasCallObj())
         384          742692 :             js_PutCallObject(this);
         385         1073348 :         if (hasArgsObj())
         386          361711 :             js_PutArgsObject(this);
         387                 :     }
         388                 :
         389        13451255 :     if (maintainNestingState())
         390          681430 :         types::NestingEpilogue(this);
         391        13451255 : }
         392                 :
         393                 : inline void
         394         1117784 : StackFrame::updateEpilogueFlags()
         395                 : {
         396         1117784 :     if (flags_ & (HAS_ARGS_OBJ | HAS_CALL_OBJ)) {
         397           14321 :         if (hasArgsObj() && !argsObj().maybeStackFrame())
         398            8516 :             flags_ &= ~HAS_ARGS_OBJ;
         399           14321 :         if (hasCallObj() && !callObj().maybeStackFrame()) {
         400                 :             /*
         401                 :              * For function frames, the call object may or may not have have an
         402                 :              * enclosing DeclEnv object, so we use the callee's parent, since
         403                 :              * it was the initial scope chain. For global (strict) eval frames,
         404                 :              * there is no callee, but the call object's parent is the initial
         405                 :              * scope chain.
         406                 :              */
         407            5943 :             scopeChain_ = isFunctionFrame()
         408            5943 :                           ? callee().toFunction()->environment()
         409           11886 :                           : &scopeChain_->asScope().enclosingScope();
         410            5943 :             flags_ &= ~HAS_CALL_OBJ;
         411                 :         }
         412                 :     }
         413                 :
         414                 :     /*
         415                 :      * For outer/inner function frames, undo the active frame balancing so that
         416                 :      * when we redo it in the epilogue we get the right final value. The other
         417                 :      * nesting epilogue changes (update active args/vars) are idempotent.
         418                 :      */
         419         1117784 :     if (maintainNestingState())
         420          153241 :         script()->nesting()->activeFrames++;
         421         1117784 : }
         422                 :
         423                 : /*****************************************************************************/
         424                 :
         425                 : STATIC_POSTCONDITION(!return || ubound(from) >= nvals)
         426                 : JS_ALWAYS_INLINE bool
         427        26521929 : StackSpace::ensureSpace(JSContext *cx, MaybeReportError report, Value *from, ptrdiff_t nvals,
         428                 :                         JSCompartment *dest) const
         429                 : {
         430        26521929 :     assertInvariants();
         431        26521929 :     JS_ASSERT(from >= firstUnused());
         432                 : #ifdef XP_WIN
         433                 :     JS_ASSERT(from <= commitEnd_);
         434                 : #endif
         435        26521929 :     if (JS_UNLIKELY(conservativeEnd_ - from < nvals))
         436             231 :         return ensureSpaceSlow(cx, report, from, nvals, dest);
         437        26521698 :     return true;
         438                 : }
         439                 :
         440                 : inline Value *
         441         1189214 : StackSpace::getStackLimit(JSContext *cx, MaybeReportError report)
         442                 : {
         443         1189214 :     FrameRegs &regs = cx->regs();
         444         1189214 :     unsigned nvals = regs.fp()->numSlots() + STACK_JIT_EXTRA;
         445         1189214 :     return ensureSpace(cx, report, regs.sp, nvals)
         446                 :            ? conservativeEnd_
         447         1189214 :            : NULL;
         448                 : }
         449                 :
         450                 : /*****************************************************************************/
         451                 :
         452                 : JS_ALWAYS_INLINE StackFrame *
         453        22808333 : ContextStack::getCallFrame(JSContext *cx, MaybeReportError report, const CallArgs &args,
         454                 :                            JSFunction *fun, JSScript *script, StackFrame::Flags *flags) const
         455                 : {
         456        22808333 :     JS_ASSERT(fun->script() == script);
         457        22808333 :     unsigned nformal = fun->nargs;
         458                 :
         459        22808333 :     Value *firstUnused = args.end();
         460        22808333 :     JS_ASSERT(firstUnused == space().firstUnused());
         461                 :
         462                 :     /* Include extra space to satisfy the method-jit stackLimit invariant. */
         463        22808333 :     unsigned nvals = VALUES_PER_STACK_FRAME + script->nslots + StackSpace::STACK_JIT_EXTRA;
         464                 :
         465                 :     /* Maintain layout invariant: &formalArgs[0] == ((Value *)fp) - nformal. */
         466                 :
         467        22808333 :     if (args.length() == nformal) {
         468        20353103 :         if (!space().ensureSpace(cx, report, firstUnused, nvals))
         469              71 :             return NULL;
         470        20353032 :         return reinterpret_cast<StackFrame *>(firstUnused);
         471                 :     }
         472                 :
         473         2455230 :     if (args.length() < nformal) {
         474           62791 :         *flags = StackFrame::Flags(*flags | StackFrame::UNDERFLOW_ARGS);
         475           62791 :         unsigned nmissing = nformal - args.length();
         476           62791 :         if (!space().ensureSpace(cx, report, firstUnused, nmissing + nvals))
         477               1 :             return NULL;
         478           62790 :         SetValueRangeToUndefined(firstUnused, nmissing);
         479           62790 :         return reinterpret_cast<StackFrame *>(firstUnused + nmissing);
         480                 :     }
         481                 :
         482         2392439 :     *flags = StackFrame::Flags(*flags | StackFrame::OVERFLOW_ARGS);
         483         2392439 :     unsigned ncopy = 2 + nformal;
         484         2392439 :     if (!space().ensureSpace(cx, report, firstUnused, ncopy + nvals))
         485              41 :         return NULL;
         486         2392398 :     Value *dst = firstUnused;
         487         2392398 :     Value *src = args.base();
         488         2392398 :     PodCopy(dst, src, ncopy);
         489         2392398 :     return reinterpret_cast<StackFrame *>(firstUnused + ncopy);
         490                 : }
         491                 :
         492                 : JS_ALWAYS_INLINE bool
         493        20497516 : ContextStack::pushInlineFrame(JSContext *cx, FrameRegs &regs, const CallArgs &args,
         494                 :                               JSFunction &callee, JSScript *script,
         495                 :                               InitialFrameFlags initial)
         496                 : {
         497        20497516 :     JS_ASSERT(onTop());
         498        20497516 :     JS_ASSERT(regs.sp == args.end());
         499                 :     /* Cannot assert callee == args.callee() since this is called from LeaveTree. */
         500        20497516 :     JS_ASSERT(script == callee.script());
         501                 :
         502        20497516 :     StackFrame::Flags flags = ToFrameFlags(initial);
         503        20497516 :     StackFrame *fp = getCallFrame(cx, REPORT_ERROR, args, &callee, script, &flags);
         504        20497516 :     if (!fp)
         505              73 :         return false;
         506                 :
         507                 :     /* Initialize frame, locals, regs. */
         508        20497443 :     fp->initCallFrame(cx, callee, script, args.length(), flags);
         509                 :
         510                 :     /*
         511                 :      * N.B. regs may differ from the active registers, if the parent is about
         512                 :      * to repoint the active registers to regs. See UncachedInlineCall.
         513                 :      */
         514        20497443 :     regs.prepareToRun(*fp, script);
         515        20497443 :     return true;
         516                 : }
         517                 :
         518                 : JS_ALWAYS_INLINE bool
         519        11195172 : ContextStack::pushInlineFrame(JSContext *cx, FrameRegs &regs, const CallArgs &args,
         520                 :                               JSFunction &callee, JSScript *script,
         521                 :                               InitialFrameFlags initial, Value **stackLimit)
         522                 : {
         523        11195172 :     if (!pushInlineFrame(cx, regs, args, callee, script, initial))
         524              21 :         return false;
         525        11195151 :     *stackLimit = space().conservativeEnd_;
         526        11195151 :     return true;
         527                 : }
         528                 :
         529                 : JS_ALWAYS_INLINE StackFrame *
         530          935060 : ContextStack::getFixupFrame(JSContext *cx, MaybeReportError report,
         531                 :                             const CallArgs &args, JSFunction *fun, JSScript *script,
         532                 :                             void *ncode, InitialFrameFlags initial, Value **stackLimit)
         533                 : {
         534          935060 :     JS_ASSERT(onTop());
         535          935060 :     JS_ASSERT(fun->script() == args.callee().toFunction()->script());
         536          935060 :     JS_ASSERT(fun->script() == script);
         537                 :
         538          935060 :     StackFrame::Flags flags = ToFrameFlags(initial);
         539          935060 :     StackFrame *fp = getCallFrame(cx, report, args, fun, script, &flags);
         540          935060 :     if (!fp)
         541              12 :         return NULL;
         542                 :
         543                 :     /* Do not init late prologue or regs; this is done by jit code. */
         544          935048 :     fp->initFixupFrame(cx->fp(), flags, ncode, args.length());
         545                 :
         546          935048 :     *stackLimit = space().conservativeEnd_;
         547          935048 :     return fp;
         548                 : }
         549                 :
         550                 : JS_ALWAYS_INLINE void
         551        11369071 : ContextStack::popInlineFrame(FrameRegs &regs)
         552                 : {
         553        11369071 :     JS_ASSERT(onTop());
         554        11369071 :     JS_ASSERT(&regs == &seg_->regs());
         555                 :
         556        11369071 :     StackFrame *fp = regs.fp();
         557        11369071 :     fp->functionEpilogue();
         558                 :
         559        11369071 :     Value *newsp = fp->actualArgs() - 1;
         560        11369071 :     JS_ASSERT(newsp >= fp->prev()->base());
         561                 :
         562        11369071 :     newsp[-1] = fp->returnValue();
         563        11369071 :     regs.popFrame(newsp);
         564        11369071 : }
         565                 :
         566                 : inline void
         567              16 : ContextStack::popFrameAfterOverflow()
         568                 : {
         569                 :     /* Restore the regs to what they were on entry to JSOP_CALL. */
         570              16 :     FrameRegs &regs = seg_->regs();
         571              16 :     StackFrame *fp = regs.fp();
         572              16 :     regs.popFrame(fp->actualArgsEnd());
         573              16 : }
         574                 :
         575                 : inline JSScript *
         576        10828314 : ContextStack::currentScript(jsbytecode **ppc) const
         577                 : {
         578        10828314 :     if (ppc)
         579         3703622 :         *ppc = NULL;
         580                 :
         581        10828314 :     FrameRegs *regs = maybeRegs();
         582        10828314 :     StackFrame *fp = regs ? regs->fp() : NULL;
         583        21672645 :     while (fp && fp->isDummyFrame())
         584           16017 :         fp = fp->prev();
         585        10828314 :     if (!fp)
         586               2 :         return NULL;
         587                 :
         588                 : #ifdef JS_METHODJIT
         589        10828312 :     mjit::CallSite *inlined = regs->inlined();
         590        10828312 :     if (inlined) {
         591            2863 :         mjit::JITChunk *chunk = fp->jit()->chunk(regs->pc);
         592            2863 :         JS_ASSERT(inlined->inlineIndex < chunk->nInlineFrames);
         593            2863 :         mjit::InlineFrame *frame = &chunk->inlineFrames()[inlined->inlineIndex];
         594            2863 :         JSScript *script = frame->fun->script();
         595            2863 :         if (script->compartment() != cx_->compartment)
         596               0 :             return NULL;
         597            2863 :         if (ppc)
         598             237 :             *ppc = script->code + inlined->pcOffset;
         599            2863 :         return script;
         600                 :     }
         601                 : #endif
         602                 :
         603        10825449 :     JSScript *script = fp->script();
         604        10825449 :     if (script->compartment() != cx_->compartment)
         605           16017 :         return NULL;
         606                 :
         607        10809432 :     if (ppc)
         608         3687375 :         *ppc = fp->pcQuadratic(*this);
         609        10809432 :     return script;
         610                 : }
         611                 :
         612                 : inline JSScript *
         613         5034879 : ContextStack::currentScriptWithDiagnostics(jsbytecode **ppc) const
         614                 : {
         615         5034879 :     if (ppc)
         616               0 :         *ppc = NULL;
         617                 :
         618         5034879 :     FrameRegs *regs = maybeRegs();
         619         5034879 :     StackFrame *fp = regs ? regs->fp() : NULL;
         620        10069758 :     while (fp && fp->isDummyFrame())
         621               0 :         fp = fp->prev();
         622         5034879 :     if (!fp)
         623               0 :         *(int *) 0x10 = 0;
         624                 :
         625                 : #ifdef JS_METHODJIT
         626         5034879 :     mjit::CallSite *inlined = regs->inlined();
         627         5034879 :     if (inlined) {
         628            1367 :         mjit::JITChunk *chunk = fp->jit()->chunk(regs->pc);
         629            1367 :         JS_ASSERT(inlined->inlineIndex < chunk->nInlineFrames);
         630            1367 :         mjit::InlineFrame *frame = &chunk->inlineFrames()[inlined->inlineIndex];
         631            1367 :         JSScript *script = frame->fun->script();
         632            1367 :         if (script->compartment() != cx_->compartment)
         633               0 :             *(int *) 0x20 = 0;
         634            1367 :         if (ppc)
         635               0 :             *ppc = script->code + inlined->pcOffset;
         636            1367 :         return script;
         637                 :     }
         638                 : #endif
         639                 :
         640         5033512 :     JSScript *script = fp->script();
         641         5033512 :     if (script->compartment() != cx_->compartment)
         642               0 :         *(int *) 0x30 = 0;
         643                 :
         644         5033512 :     if (ppc)
         645               0 :         *ppc = fp->pcQuadratic(*this);
         646         5033512 :     if (!script)
         647               0 :         *(int *) 0x40 = 0;
         648         5033512 :     return script;
         649                 : }
         650                 :
         651                 : inline JSObject *
         652        37458477 : ContextStack::currentScriptedScopeChain() const
         653                 : {
         654        37458477 :     return &fp()->scopeChain();
         655                 : }
         656                 :
         657                 : } /* namespace js */
         658                 : #endif /* Stack_inl_h__ */

Generated by: LCOV version 1.7