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