LCOV - code coverage report
Current view: directory - js/src/vm - Stack-inl.h (source / functions) Found Hit Coverage
Test: app.info Lines: 296 286 96.6 %
Date: 2012-06-02 Functions: 38 37 97.4 %

       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         2597599 : IsCacheableNonGlobalScope(JSObject *obj)
      65                 : {
      66         2597599 :     bool cacheable = (obj->isCall() || obj->isBlock() || obj->isDeclEnv());
      67                 : 
      68         2597599 :     JS_ASSERT_IF(cacheable, !obj->getOps()->lookupProperty);
      69         2597599 :     return cacheable;
      70                 : }
      71                 : 
      72                 : inline JSObject &
      73      1080834795 : StackFrame::scopeChain() const
      74                 : {
      75      1080834795 :     JS_ASSERT_IF(!(flags_ & HAS_SCOPECHAIN), isFunctionFrame());
      76      1080834795 :     if (!(flags_ & HAS_SCOPECHAIN)) {
      77         3840676 :         scopeChain_ = callee().toFunction()->environment();
      78         3840676 :         flags_ |= HAS_SCOPECHAIN;
      79                 :     }
      80      1080834795 :     return *scopeChain_;
      81                 : }
      82                 : 
      83                 : inline JSObject &
      84          697741 : StackFrame::varObj()
      85                 : {
      86          697741 :     JSObject *obj = &scopeChain();
      87         1396348 :     while (!obj->isVarObj())
      88             866 :         obj = obj->enclosingScope();
      89          697741 :     return *obj;
      90                 : }
      91                 : 
      92                 : inline JSCompartment *
      93         4374042 : StackFrame::compartment() const
      94                 : {
      95         4374042 :     JS_ASSERT_IF(isScriptFrame(), scopeChain().compartment() == script()->compartment());
      96         4374042 :     return scopeChain().compartment();
      97                 : }
      98                 : 
      99                 : inline void
     100        29269195 : StackFrame::initPrev(JSContext *cx)
     101                 : {
     102        29269195 :     JS_ASSERT(flags_ & HAS_PREVPC);
     103        29269195 :     if (FrameRegs *regs = cx->maybeRegs()) {
     104        29041382 :         prev_ = regs->fp();
     105        29041382 :         prevpc_ = regs->pc;
     106        29041382 :         prevInline_ = regs->inlined();
     107        87054930 :         JS_ASSERT_IF(!prev_->isDummyFrame(),
     108        87054930 :                      uint32_t(prevpc_ - prev_->script()->code) < prev_->script()->length);
     109                 :     } else {
     110          227813 :         prev_ = NULL;
     111                 : #ifdef DEBUG
     112          227813 :         prevpc_ = (jsbytecode *)0xbadc;
     113          227813 :         prevInline_ = (JSInlinedSite *)0xbadc;
     114                 : #endif
     115                 :     }
     116        29269195 : }
     117                 : 
     118                 : inline void
     119           30834 : StackFrame::resetGeneratorPrev(JSContext *cx)
     120                 : {
     121           30834 :     flags_ |= HAS_PREVPC;
     122           30834 :     initPrev(cx);
     123           30834 : }
     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        28978615 : 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        28978615 :                             UNDERFLOW_ARGS)) == 0);
     155        28978615 :     JS_ASSERT(script == callee.script());
     156                 : 
     157                 :     /* Initialize stack frame members. */
     158        28978615 :     flags_ = FUNCTION | HAS_PREVPC | HAS_SCOPECHAIN | HAS_BLOCKCHAIN | flagsArg;
     159        28978615 :     exec.fun = &callee;
     160        28978615 :     u.nactual = nactual;
     161        28978615 :     scopeChain_ = callee.environment();
     162        28978615 :     ncode_ = NULL;
     163        28978615 :     initPrev(cx);
     164        28978615 :     blockChain_= NULL;
     165        28978615 :     JS_ASSERT(!hasBlockChain());
     166        28978615 :     JS_ASSERT(!hasHookData());
     167        28978615 :     JS_ASSERT(annotation() == NULL);
     168        28978615 :     JS_ASSERT(!hasCallObj());
     169                 : 
     170        28978615 :     SetValueRangeToUndefined(slots(), script->nfixed);
     171        28978615 : }
     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         1022182 : 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         1022182 :                          UNDERFLOW_ARGS)) == 0);
     185                 : 
     186         1022182 :     flags_ = FUNCTION | flags;
     187         1022182 :     prev_ = prev;
     188         1022182 :     ncode_ = ncode;
     189         1022182 :     u.nactual = nactual;
     190         1022182 : }
     191                 : 
     192                 : inline void
     193               0 : StackFrame::overwriteCallee(JSObject &newCallee)
     194                 : {
     195               0 :     JS_ASSERT(callee().toFunction()->script() == newCallee.toFunction()->script());
     196               0 :     mutableCalleev().setObject(newCallee);
     197               0 : }
     198                 : 
     199                 : inline Value &
     200           76805 : StackFrame::canonicalActualArg(unsigned i) const
     201                 : {
     202           76805 :     if (i < numFormalArgs())
     203           12468 :         return formalArg(i);
     204           64337 :     JS_ASSERT(i < numActualArgs());
     205           64337 :     return actualArgs()[i];
     206                 : }
     207                 : 
     208                 : template <class Op>
     209                 : inline bool
     210         5264114 : StackFrame::forEachCanonicalActualArg(Op op, unsigned start /* = 0 */, unsigned count /* = unsigned(-1) */)
     211                 : {
     212         5624074 :     unsigned nformal = fun()->nargs;
     213         5624074 :     JS_ASSERT(start <= nformal);
     214                 : 
     215         5624074 :     Value *formals = formalArgsEnd() - nformal;
     216         5624074 :     unsigned nactual = numActualArgs();
     217         5624074 :     if (count == unsigned(-1))
     218         5264114 :         count = nactual - start;
     219                 : 
     220         5624074 :     unsigned end = start + count;
     221         5624074 :     JS_ASSERT(end >= start);
     222         5624074 :     JS_ASSERT(end <= nactual);
     223                 : 
     224         5624074 :     if (end <= nformal) {
     225         3490782 :         Value *p = formals + start;
     226         4486237 :         for (; start < end; ++p, ++start) {
     227          995455 :             if (!op(start, p))
     228               0 :                 return false;
     229                 :         }
     230                 :     } else {
     231         2480881 :         for (Value *p = formals + start; start < nformal; ++p, ++start) {
     232          347589 :             if (!op(start, p))
     233               0 :                 return false;
     234                 :         }
     235         2133292 :         JS_ASSERT(start >= nformal);
     236         2133292 :         Value *actuals = formals - (nactual + 2) + start;
     237         9856543 :         for (Value *p = actuals; start < end; ++p, ++start) {
     238         7723269 :             if (!op(start, p))
     239              18 :                 return false;
     240                 :         }
     241                 :     }
     242         5624056 :     return true;
     243                 : }
     244                 : 
     245                 : template <class Op>
     246                 : inline bool
     247                 : StackFrame::forEachFormalArg(Op op)
     248                 : {
     249                 :     Value *formals = formalArgsEnd() - fun()->nargs;
     250                 :     Value *formalsEnd = formalArgsEnd();
     251                 :     unsigned i = 0;
     252                 :     for (Value *p = formals; p != formalsEnd; ++p, ++i) {
     253                 :         if (!op(i, p))
     254                 :             return false;
     255                 :     }
     256                 :     return true;
     257                 : }
     258                 : 
     259                 : struct CopyTo
     260                 : {
     261                 :     Value *dst;
     262          282240 :     CopyTo(Value *dst) : dst(dst) {}
     263          689882 :     bool operator()(unsigned, Value *src) {
     264          689882 :         *dst++ = *src;
     265          689882 :         return true;
     266                 :     }
     267                 : };
     268                 : 
     269                 : inline unsigned
     270        15275202 : StackFrame::numActualArgs() const
     271                 : {
     272                 :     /*
     273                 :      * u.nactual is always coherent, except for method JIT frames where the
     274                 :      * callee does not access its arguments and the number of actual arguments
     275                 :      * matches the number of formal arguments. The JIT requires that all frames
     276                 :      * which do not have an arguments object and use their arguments have a
     277                 :      * coherent u.nactual (even though the below code may not use it), as
     278                 :      * JIT code may access the field directly.
     279                 :      */
     280        15275202 :     JS_ASSERT(hasArgs());
     281        15275202 :     if (JS_UNLIKELY(flags_ & (OVERFLOW_ARGS | UNDERFLOW_ARGS)))
     282         4958540 :         return u.nactual;
     283        10316662 :     return numFormalArgs();
     284                 : }
     285                 : 
     286                 : inline Value *
     287        14230701 : StackFrame::actualArgs() const
     288                 : {
     289        14230701 :     JS_ASSERT(hasArgs());
     290        14230701 :     Value *argv = formalArgs();
     291        14230701 :     if (JS_UNLIKELY(flags_ & OVERFLOW_ARGS))
     292         1417567 :         return argv - (2 + u.nactual);
     293        12813134 :     return argv;
     294                 : }
     295                 : 
     296                 : inline Value *
     297         4363392 : StackFrame::actualArgsEnd() const
     298                 : {
     299         4363392 :     JS_ASSERT(hasArgs());
     300         4363392 :     if (JS_UNLIKELY(flags_ & OVERFLOW_ARGS))
     301         1083038 :         return formalArgs() - 2;
     302         3280354 :     return formalArgs() + numActualArgs();
     303                 : }
     304                 : 
     305                 : inline void
     306          620157 : StackFrame::setArgsObj(ArgumentsObject &obj)
     307                 : {
     308          620157 :     JS_ASSERT_IF(hasArgsObj(), &obj == argsObj_);
     309          620157 :     JS_ASSERT_IF(!hasArgsObj(), numActualArgs() == obj.initialLength());
     310          620157 :     argsObj_ = &obj;
     311          620157 :     flags_ |= HAS_ARGS_OBJ;
     312          620157 : }
     313                 : 
     314                 : inline void
     315          299685 : StackFrame::setScopeChainNoCallObj(JSObject &obj)
     316                 : {
     317                 : #ifdef DEBUG
     318          299685 :     JS_ASSERT(&obj != NULL);
     319          299685 :     if (&obj != sInvalidScopeChain) {
     320          299685 :         if (hasCallObj()) {
     321           36581 :             JSObject *pobj = &obj;
     322           74201 :             while (pobj && pobj->getPrivate() != this)
     323            1039 :                 pobj = pobj->enclosingScope();
     324           36581 :             JS_ASSERT(pobj);
     325                 :         } else {
     326          265089 :             for (JSObject *pobj = &obj; pobj->isScope(); pobj = pobj->enclosingScope())
     327            1985 :                 JS_ASSERT_IF(pobj->isCall(), pobj->getPrivate() != this);
     328                 :         }
     329                 :     }
     330                 : #endif
     331          299685 :     scopeChain_ = &obj;
     332          299685 :     flags_ |= HAS_SCOPECHAIN;
     333          299685 : }
     334                 : 
     335                 : inline void
     336          703452 : StackFrame::setScopeChainWithOwnCallObj(CallObject &obj)
     337                 : {
     338          703452 :     JS_ASSERT(&obj != NULL);
     339          703452 :     JS_ASSERT(!hasCallObj() && obj.maybeStackFrame() == this);
     340          703452 :     scopeChain_ = &obj;
     341          703452 :     flags_ |= HAS_SCOPECHAIN | HAS_CALL_OBJ;
     342          703452 : }
     343                 : 
     344                 : inline CallObject &
     345          950931 : StackFrame::callObj() const
     346                 : {
     347          950931 :     JS_ASSERT_IF(isNonEvalFunctionFrame() || isStrictEvalFrame(), hasCallObj());
     348                 : 
     349          950931 :     JSObject *pobj = &scopeChain();
     350         1904071 :     while (JS_UNLIKELY(!pobj->isCall()))
     351            2209 :         pobj = pobj->enclosingScope();
     352          950931 :     return pobj->asCall();
     353                 : }
     354                 : 
     355                 : inline bool
     356        24387586 : StackFrame::maintainNestingState() const
     357                 : {
     358                 :     /*
     359                 :      * Whether to invoke the nesting epilogue/prologue to maintain active
     360                 :      * frame counts and check for reentrant outer functions.
     361                 :      */
     362        24387586 :     return isNonEvalFunctionFrame() && !isGeneratorFrame() && script()->nesting();
     363                 : }
     364                 : 
     365                 : inline bool
     366        29167371 : StackFrame::functionPrologue(JSContext *cx)
     367                 : {
     368        29167371 :     JS_ASSERT(isNonEvalFunctionFrame());
     369                 : 
     370        29167371 :     JSFunction *fun = this->fun();
     371                 : 
     372        29167371 :     if (fun->isHeavyweight()) {
     373          700285 :         if (!CallObject::createForFunction(cx, this))
     374               0 :             return false;
     375                 :     } else {
     376                 :         /* Force instantiation of the scope chain, for JIT frames. */
     377        28467086 :         scopeChain();
     378                 :     }
     379                 : 
     380        29167371 :     if (script()->nesting()) {
     381          415918 :         JS_ASSERT(maintainNestingState());
     382          415918 :         types::NestingPrologue(cx, this);
     383                 :     }
     384                 : 
     385        29167371 :     return true;
     386                 : }
     387                 : 
     388                 : inline void
     389        19816248 : StackFrame::functionEpilogue()
     390                 : {
     391        19816248 :     JS_ASSERT(isNonEvalFunctionFrame());
     392                 : 
     393        19816248 :     if (flags_ & (HAS_ARGS_OBJ | HAS_CALL_OBJ)) {
     394                 :         /* NB: there is an ordering dependency here. */
     395         1311441 :         if (hasCallObj())
     396          701040 :             js_PutCallObject(this);
     397          610401 :         else if (hasArgsObj())
     398          610401 :             js_PutArgsObject(this);
     399                 :     }
     400                 : 
     401        19816248 :     if (maintainNestingState())
     402          320368 :         types::NestingEpilogue(this);
     403        19816248 : }
     404                 : 
     405                 : inline void
     406         4155420 : StackFrame::updateEpilogueFlags()
     407                 : {
     408         4155420 :     if (flags_ & (HAS_ARGS_OBJ | HAS_CALL_OBJ)) {
     409           31254 :         if (hasArgsObj() && !argsObj().maybeStackFrame())
     410           15633 :             flags_ &= ~HAS_ARGS_OBJ;
     411           31254 :         if (hasCallObj() && !callObj().maybeStackFrame()) {
     412                 :             /*
     413                 :              * For function frames, the call object may or may not have have an
     414                 :              * enclosing DeclEnv object, so we use the callee's parent, since
     415                 :              * it was the initial scope chain. For global (strict) eval frames,
     416                 :              * there is no callee, but the call object's parent is the initial
     417                 :              * scope chain.
     418                 :              */
     419           12928 :             scopeChain_ = isFunctionFrame()
     420           12928 :                           ? callee().toFunction()->environment()
     421           25856 :                           : &scopeChain_->asScope().enclosingScope();
     422           12928 :             flags_ &= ~HAS_CALL_OBJ;
     423                 :         }
     424                 :     }
     425                 : 
     426                 :     /*
     427                 :      * For outer/inner function frames, undo the active frame balancing so that
     428                 :      * when we redo it in the epilogue we get the right final value. The other
     429                 :      * nesting epilogue changes (update active args/vars) are idempotent.
     430                 :      */
     431         4155420 :     if (maintainNestingState())
     432           15528 :         script()->nesting()->activeFrames++;
     433         4155420 : }
     434                 : 
     435                 : /*****************************************************************************/
     436                 : 
     437                 : STATIC_POSTCONDITION(!return || ubound(from) >= nvals)
     438                 : JS_ALWAYS_INLINE bool
     439        41021978 : StackSpace::ensureSpace(JSContext *cx, MaybeReportError report, Value *from, ptrdiff_t nvals,
     440                 :                         JSCompartment *dest) const
     441                 : {
     442        41021978 :     assertInvariants();
     443        41021978 :     JS_ASSERT(from >= firstUnused());
     444                 : #ifdef XP_WIN
     445                 :     JS_ASSERT(from <= commitEnd_);
     446                 : #endif
     447        41021978 :     if (JS_UNLIKELY(conservativeEnd_ - from < nvals))
     448             231 :         return ensureSpaceSlow(cx, report, from, nvals, dest);
     449        41021747 :     return true;
     450                 : }
     451                 : 
     452                 : inline Value *
     453         4229385 : StackSpace::getStackLimit(JSContext *cx, MaybeReportError report)
     454                 : {
     455         4229385 :     FrameRegs &regs = cx->regs();
     456         4229385 :     unsigned nvals = regs.fp()->numSlots() + STACK_JIT_EXTRA;
     457         4229385 :     return ensureSpace(cx, report, regs.sp, nvals)
     458                 :            ? conservativeEnd_
     459         4229385 :            : NULL;
     460                 : }
     461                 : 
     462                 : /*****************************************************************************/
     463                 : 
     464                 : JS_ALWAYS_INLINE StackFrame *
     465        30000910 : ContextStack::getCallFrame(JSContext *cx, MaybeReportError report, const CallArgs &args,
     466                 :                            JSFunction *fun, JSScript *script, StackFrame::Flags *flags) const
     467                 : {
     468        30000910 :     JS_ASSERT(fun->script() == script);
     469        30000910 :     unsigned nformal = fun->nargs;
     470                 : 
     471        30000910 :     Value *firstUnused = args.end();
     472        30000910 :     JS_ASSERT(firstUnused == space().firstUnused());
     473                 : 
     474                 :     /* Include extra space to satisfy the method-jit stackLimit invariant. */
     475        30000910 :     unsigned nvals = VALUES_PER_STACK_FRAME + script->nslots + StackSpace::STACK_JIT_EXTRA;
     476                 : 
     477                 :     /* Maintain layout invariant: &formalArgs[0] == ((Value *)fp) - nformal. */
     478                 : 
     479        30000910 :     if (args.length() == nformal) {
     480        24692683 :         if (!space().ensureSpace(cx, report, firstUnused, nvals))
     481              71 :             return NULL;
     482        24692612 :         return reinterpret_cast<StackFrame *>(firstUnused);
     483                 :     }
     484                 : 
     485         5308227 :     if (args.length() < nformal) {
     486          423392 :         *flags = StackFrame::Flags(*flags | StackFrame::UNDERFLOW_ARGS);
     487          423392 :         unsigned nmissing = nformal - args.length();
     488          423392 :         if (!space().ensureSpace(cx, report, firstUnused, nmissing + nvals))
     489               1 :             return NULL;
     490          423391 :         SetValueRangeToUndefined(firstUnused, nmissing);
     491          423391 :         return reinterpret_cast<StackFrame *>(firstUnused + nmissing);
     492                 :     }
     493                 : 
     494         4884835 :     *flags = StackFrame::Flags(*flags | StackFrame::OVERFLOW_ARGS);
     495         4884835 :     unsigned ncopy = 2 + nformal;
     496         4884835 :     if (!space().ensureSpace(cx, report, firstUnused, ncopy + nvals))
     497              41 :         return NULL;
     498         4884794 :     Value *dst = firstUnused;
     499         4884794 :     Value *src = args.base();
     500         4884794 :     PodCopy(dst, src, ncopy);
     501         4884794 :     return reinterpret_cast<StackFrame *>(firstUnused + ncopy);
     502                 : }
     503                 : 
     504                 : JS_ALWAYS_INLINE bool
     505        23760453 : ContextStack::pushInlineFrame(JSContext *cx, FrameRegs &regs, const CallArgs &args,
     506                 :                               JSFunction &callee, JSScript *script,
     507                 :                               InitialFrameFlags initial)
     508                 : {
     509        23760453 :     JS_ASSERT(onTop());
     510        23760453 :     JS_ASSERT(regs.sp == args.end());
     511                 :     /* Cannot assert callee == args.callee() since this is called from LeaveTree. */
     512        23760453 :     JS_ASSERT(script == callee.script());
     513                 : 
     514        23760453 :     StackFrame::Flags flags = ToFrameFlags(initial);
     515        23760453 :     StackFrame *fp = getCallFrame(cx, REPORT_ERROR, args, &callee, script, &flags);
     516        23760453 :     if (!fp)
     517              73 :         return false;
     518                 : 
     519                 :     /* Initialize frame, locals, regs. */
     520        23760380 :     fp->initCallFrame(cx, callee, script, args.length(), flags);
     521                 : 
     522                 :     /*
     523                 :      * N.B. regs may differ from the active registers, if the parent is about
     524                 :      * to repoint the active registers to regs. See UncachedInlineCall.
     525                 :      */
     526        23760380 :     regs.prepareToRun(*fp, script);
     527        23760380 :     return true;
     528                 : }
     529                 : 
     530                 : JS_ALWAYS_INLINE bool
     531        11875216 : ContextStack::pushInlineFrame(JSContext *cx, FrameRegs &regs, const CallArgs &args,
     532                 :                               JSFunction &callee, JSScript *script,
     533                 :                               InitialFrameFlags initial, Value **stackLimit)
     534                 : {
     535        11875216 :     if (!pushInlineFrame(cx, regs, args, callee, script, initial))
     536              21 :         return false;
     537        11875195 :     *stackLimit = space().conservativeEnd_;
     538        11875195 :     return true;
     539                 : }
     540                 : 
     541                 : JS_ALWAYS_INLINE StackFrame *
     542         1022194 : ContextStack::getFixupFrame(JSContext *cx, MaybeReportError report,
     543                 :                             const CallArgs &args, JSFunction *fun, JSScript *script,
     544                 :                             void *ncode, InitialFrameFlags initial, Value **stackLimit)
     545                 : {
     546         1022194 :     JS_ASSERT(onTop());
     547         1022194 :     JS_ASSERT(fun->script() == args.callee().toFunction()->script());
     548         1022194 :     JS_ASSERT(fun->script() == script);
     549                 : 
     550         1022194 :     StackFrame::Flags flags = ToFrameFlags(initial);
     551         1022194 :     StackFrame *fp = getCallFrame(cx, report, args, fun, script, &flags);
     552         1022194 :     if (!fp)
     553              12 :         return NULL;
     554                 : 
     555                 :     /* Do not init late prologue or regs; this is done by jit code. */
     556         1022182 :     fp->initFixupFrame(cx->fp(), flags, ncode, args.length());
     557                 : 
     558         1022182 :     *stackLimit = space().conservativeEnd_;
     559         1022182 :     return fp;
     560                 : }
     561                 : 
     562                 : JS_ALWAYS_INLINE void
     563        14031757 : ContextStack::popInlineFrame(FrameRegs &regs)
     564                 : {
     565        14031757 :     JS_ASSERT(onTop());
     566        14031757 :     JS_ASSERT(&regs == &seg_->regs());
     567                 : 
     568        14031757 :     StackFrame *fp = regs.fp();
     569        14031757 :     fp->functionEpilogue();
     570                 : 
     571        14031757 :     Value *newsp = fp->actualArgs() - 1;
     572        14031757 :     JS_ASSERT(newsp >= fp->prev()->base());
     573                 : 
     574        14031757 :     newsp[-1] = fp->returnValue();
     575        14031757 :     regs.popFrame(newsp);
     576        14031757 : }
     577                 : 
     578                 : inline void
     579              16 : ContextStack::popFrameAfterOverflow()
     580                 : {
     581                 :     /* Restore the regs to what they were on entry to JSOP_CALL. */
     582              16 :     FrameRegs &regs = seg_->regs();
     583              16 :     StackFrame *fp = regs.fp();
     584              16 :     regs.popFrame(fp->actualArgsEnd());
     585              16 : }
     586                 : 
     587                 : inline JSScript *
     588        80878136 : ContextStack::currentScript(jsbytecode **ppc) const
     589                 : {
     590        80878136 :     if (ppc)
     591        27316264 :         *ppc = NULL;
     592                 : 
     593        80878136 :     FrameRegs *regs = maybeRegs();
     594        80878136 :     StackFrame *fp = regs ? regs->fp() : NULL;
     595       161765129 :     while (fp && fp->isDummyFrame())
     596            8857 :         fp = fp->prev();
     597        80878136 :     if (!fp)
     598            2007 :         return NULL;
     599                 : 
     600                 : #ifdef JS_METHODJIT
     601        80876129 :     mjit::CallSite *inlined = regs->inlined();
     602        80876129 :     if (inlined) {
     603            4313 :         mjit::JITChunk *chunk = fp->jit()->chunk(regs->pc);
     604            4313 :         JS_ASSERT(inlined->inlineIndex < chunk->nInlineFrames);
     605            4313 :         mjit::InlineFrame *frame = &chunk->inlineFrames()[inlined->inlineIndex];
     606            4313 :         JSScript *script = frame->fun->script();
     607            4313 :         if (script->compartment() != cx_->compartment)
     608               0 :             return NULL;
     609            4313 :         if (ppc)
     610             266 :             *ppc = script->code + inlined->pcOffset;
     611            4313 :         return script;
     612                 :     }
     613                 : #endif
     614                 : 
     615        80871816 :     JSScript *script = fp->script();
     616        80871816 :     if (script->compartment() != cx_->compartment)
     617            8857 :         return NULL;
     618                 : 
     619        80862959 :     if (ppc)
     620        27305143 :         *ppc = fp->pcQuadratic(*this);
     621        80862959 :     return script;
     622                 : }
     623                 : 
     624                 : inline JSObject *
     625        55901318 : ContextStack::currentScriptedScopeChain() const
     626                 : {
     627        55901318 :     return &fp()->scopeChain();
     628                 : }
     629                 : 
     630                 : } /* namespace js */
     631                 : #endif /* Stack_inl_h__ */

Generated by: LCOV version 1.7