LCOV - code coverage report
Current view: directory - js/src - jsinterp.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 1835 1549 84.4 %
Date: 2012-04-21 Functions: 43 42 97.7 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  * vim: set ts=8 sw=4 et tw=99:
       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 Mozilla Communicator client code, released
      18                 :  * March 31, 1998.
      19                 :  *
      20                 :  * The Initial Developer of the Original Code is
      21                 :  * Netscape Communications Corporation.
      22                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      23                 :  * the Initial Developer. All Rights Reserved.
      24                 :  *
      25                 :  * Contributor(s):
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      29                 :  * or 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                 : /*
      42                 :  * JavaScript bytecode interpreter.
      43                 :  */
      44                 : #include <stdio.h>
      45                 : #include <string.h>
      46                 : #include <math.h>
      47                 : #include "jstypes.h"
      48                 : #include "jsutil.h"
      49                 : #include "jsprf.h"
      50                 : #include "jsapi.h"
      51                 : #include "jsarray.h"
      52                 : #include "jsatom.h"
      53                 : #include "jsbool.h"
      54                 : #include "jscntxt.h"
      55                 : #include "jsdate.h"
      56                 : #include "jsversion.h"
      57                 : #include "jsdbgapi.h"
      58                 : #include "jsfun.h"
      59                 : #include "jsgc.h"
      60                 : #include "jsgcmark.h"
      61                 : #include "jsinterp.h"
      62                 : #include "jsiter.h"
      63                 : #include "jslock.h"
      64                 : #include "jsnum.h"
      65                 : #include "jsobj.h"
      66                 : #include "jsopcode.h"
      67                 : #include "jspropertycache.h"
      68                 : #include "jsscope.h"
      69                 : #include "jsscript.h"
      70                 : #include "jsstr.h"
      71                 : #include "jslibmath.h"
      72                 : 
      73                 : #include "frontend/BytecodeEmitter.h"
      74                 : #ifdef JS_METHODJIT
      75                 : #include "methodjit/MethodJIT.h"
      76                 : #include "methodjit/Logging.h"
      77                 : #endif
      78                 : #include "vm/Debugger.h"
      79                 : 
      80                 : #include "jsatominlines.h"
      81                 : #include "jsinferinlines.h"
      82                 : #include "jsinterpinlines.h"
      83                 : #include "jsobjinlines.h"
      84                 : #include "jsopcodeinlines.h"
      85                 : #include "jsprobes.h"
      86                 : #include "jspropertycacheinlines.h"
      87                 : #include "jsscopeinlines.h"
      88                 : #include "jsscriptinlines.h"
      89                 : #include "jstypedarrayinlines.h"
      90                 : 
      91                 : #include "vm/Stack-inl.h"
      92                 : #include "vm/String-inl.h"
      93                 : 
      94                 : #if JS_HAS_XML_SUPPORT
      95                 : #include "jsxml.h"
      96                 : #endif
      97                 : 
      98                 : #include "jsautooplen.h"
      99                 : 
     100                 : #if defined(JS_METHODJIT) && defined(JS_MONOIC)
     101                 : #include "methodjit/MonoIC.h"
     102                 : #endif
     103                 : 
     104                 : using namespace js;
     105                 : using namespace js::gc;
     106                 : using namespace js::types;
     107                 : 
     108                 : /*
     109                 :  * We can't determine in advance which local variables can live on the stack and
     110                 :  * be freed when their dynamic scope ends, and which will be closed over and
     111                 :  * need to live in the heap.  So we place variables on the stack initially, note
     112                 :  * when they are closed over, and copy those that are out to the heap when we
     113                 :  * leave their dynamic scope.
     114                 :  *
     115                 :  * The bytecode compiler produces a tree of block objects accompanying each
     116                 :  * JSScript representing those lexical blocks in the script that have let-bound
     117                 :  * variables associated with them.  These block objects are never modified, and
     118                 :  * never become part of any function's scope chain.  Their parent slots point to
     119                 :  * the innermost block that encloses them, or are NULL in the outermost blocks
     120                 :  * within a function or in eval or global code.
     121                 :  *
     122                 :  * When we are in the static scope of such a block, blockChain points to its
     123                 :  * compiler-allocated block object; otherwise, it is NULL.
     124                 :  *
     125                 :  * scopeChain is the current scope chain, including 'call' and 'block' objects
     126                 :  * for those function calls and lexical blocks whose static scope we are
     127                 :  * currently executing in, and 'with' objects for with statements; the chain is
     128                 :  * typically terminated by a global object.  However, as an optimization, the
     129                 :  * young end of the chain omits block objects we have not yet cloned.  To create
     130                 :  * a closure, we clone the missing blocks from blockChain (which is always
     131                 :  * current), place them at the head of scopeChain, and use that for the
     132                 :  * closure's scope chain.  If we never close over a lexical block, we never
     133                 :  * place a mutable clone of it on scopeChain.
     134                 :  *
     135                 :  * This lazy cloning is implemented in GetScopeChain, which is also used in
     136                 :  * some other cases --- entering 'with' blocks, for example.
     137                 :  */
     138                 : JSObject *
     139          876355 : js::GetScopeChain(JSContext *cx, StackFrame *fp)
     140                 : {
     141          876355 :     StaticBlockObject *sharedBlock = fp->maybeBlockChain();
     142                 : 
     143          876355 :     if (!sharedBlock) {
     144                 :         /*
     145                 :          * Don't force a call object for a lightweight function call, but do
     146                 :          * insist that there is a call object for a heavyweight function call.
     147                 :          */
     148         2386365 :         JS_ASSERT_IF(fp->isNonEvalFunctionFrame() && fp->fun()->isHeavyweight(),
     149         2386365 :                      fp->hasCallObj());
     150          847186 :         return &fp->scopeChain();
     151                 :     }
     152                 : 
     153                 :     /*
     154                 :      * We have one or more lexical scopes to reflect into fp->scopeChain, so
     155                 :      * make sure there's a call object at the current head of the scope chain,
     156                 :      * if this frame is a call frame.
     157                 :      *
     158                 :      * Also, identify the innermost compiler-allocated block we needn't clone.
     159                 :      */
     160                 :     JSObject *limitBlock, *limitClone;
     161           29169 :     if (fp->isNonEvalFunctionFrame() && !fp->hasCallObj()) {
     162               1 :         JS_ASSERT_IF(fp->scopeChain().isClonedBlock(), fp->scopeChain().getPrivate() != fp);
     163               1 :         if (!CallObject::createForFunction(cx, fp))
     164               0 :             return NULL;
     165                 : 
     166                 :         /* We know we must clone everything on blockChain. */
     167               1 :         limitBlock = limitClone = NULL;
     168                 :     } else {
     169                 :         /*
     170                 :          * scopeChain includes all blocks whose static scope we're within that
     171                 :          * have already been cloned.  Find the innermost such block.  Its
     172                 :          * prototype should appear on blockChain; we'll clone blockChain up
     173                 :          * to, but not including, that prototype.
     174                 :          */
     175           29168 :         limitClone = &fp->scopeChain();
     176           58408 :         while (limitClone->isWith())
     177              72 :             limitClone = &limitClone->asWith().enclosingScope();
     178           29168 :         JS_ASSERT(limitClone);
     179                 : 
     180                 :         /*
     181                 :          * It may seem like we don't know enough about limitClone to be able
     182                 :          * to just grab its prototype as we do here, but it's actually okay.
     183                 :          *
     184                 :          * If limitClone is a block object belonging to this frame, then its
     185                 :          * prototype is the innermost entry in blockChain that we have already
     186                 :          * cloned, and is thus the place to stop when we clone below.
     187                 :          *
     188                 :          * Otherwise, there are no blocks for this frame on scopeChain, and we
     189                 :          * need to clone the whole blockChain.  In this case, limitBlock can
     190                 :          * point to any object known not to be on blockChain, since we simply
     191                 :          * loop until we hit limitBlock or NULL.  If limitClone is a block, it
     192                 :          * isn't a block from this function, since blocks can't be nested
     193                 :          * within themselves on scopeChain (recursion is dynamic nesting, not
     194                 :          * static nesting).  If limitClone isn't a block, its prototype won't
     195                 :          * be a block either.  So we can just grab limitClone's prototype here
     196                 :          * regardless of its type or which frame it belongs to.
     197                 :          */
     198           29168 :         limitBlock = limitClone->getProto();
     199                 : 
     200                 :         /* If the innermost block has already been cloned, we are done. */
     201           29168 :         if (limitBlock == sharedBlock)
     202           11430 :             return &fp->scopeChain();
     203                 :     }
     204                 : 
     205                 :     /*
     206                 :      * Special-case cloning the innermost block; this doesn't have enough in
     207                 :      * common with subsequent steps to include in the loop.
     208                 :      *
     209                 :      * create() leaves the clone's enclosingScope unset. We set it below.
     210                 :      */
     211           17739 :     ClonedBlockObject *innermostNewChild = ClonedBlockObject::create(cx, *sharedBlock, fp);
     212           17739 :     if (!innermostNewChild)
     213               0 :         return NULL;
     214                 : 
     215                 :     /*
     216                 :      * Clone our way towards outer scopes until we reach the innermost
     217                 :      * enclosing function, or the innermost block we've already cloned.
     218                 :      */
     219           17739 :     ClonedBlockObject *newChild = innermostNewChild;
     220             901 :     for (;;) {
     221           18640 :         JS_ASSERT(newChild->getProto() == sharedBlock);
     222           18640 :         sharedBlock = sharedBlock->enclosingBlock();
     223                 : 
     224                 :         /* Sometimes limitBlock will be NULL, so check that first.  */
     225           18640 :         if (sharedBlock == limitBlock || !sharedBlock)
     226                 :             break;
     227                 : 
     228                 :         /* As in the call above, we don't know the real parent yet.  */
     229             901 :         ClonedBlockObject *clone = ClonedBlockObject::create(cx, *sharedBlock, fp);
     230             901 :         if (!clone)
     231               0 :             return NULL;
     232                 : 
     233             901 :         if (!newChild->setEnclosingScope(cx, *clone))
     234               0 :             return NULL;
     235             901 :         newChild = clone;
     236                 :     }
     237           17739 :     if (!newChild->setEnclosingScope(cx, fp->scopeChain()))
     238               0 :         return NULL;
     239                 : 
     240                 : 
     241                 :     /*
     242                 :      * If we found a limit block belonging to this frame, then we should have
     243                 :      * found it in blockChain.
     244                 :      */
     245            5890 :     JS_ASSERT_IF(limitBlock &&
     246                 :                  limitBlock->isClonedBlock() &&
     247                 :                  limitClone->getPrivate() == js_FloatingFrameIfGenerator(cx, fp),
     248           23629 :                  sharedBlock);
     249                 : 
     250                 :     /* Place our newly cloned blocks at the head of the scope chain.  */
     251           17739 :     fp->setScopeChainNoCallObj(*innermostNewChild);
     252           17739 :     return innermostNewChild;
     253                 : }
     254                 : 
     255                 : JSObject *
     256               0 : js::GetScopeChain(JSContext *cx)
     257                 : {
     258                 :     /*
     259                 :      * Note: we don't need to expand inline frames here, because frames are
     260                 :      * only inlined when the caller and callee share the same scope chain.
     261                 :      */
     262               0 :     StackFrame *fp = js_GetTopStackFrame(cx, FRAME_EXPAND_NONE);
     263               0 :     if (!fp) {
     264                 :         /*
     265                 :          * There is no code active on this context. In place of an actual
     266                 :          * scope chain, use the context's global object, which is set in
     267                 :          * js_InitFunctionAndObjectClasses, and which represents the default
     268                 :          * scope chain for the embedding. See also js_FindClassObject.
     269                 :          *
     270                 :          * For embeddings that use the inner and outer object hooks, the inner
     271                 :          * object represents the ultimate global object, with the outer object
     272                 :          * acting as a stand-in.
     273                 :          */
     274               0 :         JSObject *obj = cx->globalObject;
     275               0 :         if (!obj) {
     276               0 :             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INACTIVE);
     277               0 :             return NULL;
     278                 :         }
     279                 : 
     280               0 :         OBJ_TO_INNER_OBJECT(cx, obj);
     281               0 :         return obj;
     282                 :     }
     283               0 :     return GetScopeChain(cx, fp);
     284                 : }
     285                 : 
     286                 : /* Some objects (e.g., With) delegate 'this' to another object. */
     287                 : static inline JSObject *
     288                 : CallThisObjectHook(JSContext *cx, JSObject *obj, Value *argv)
     289                 : {
     290                 :     JSObject *thisp = obj->thisObject(cx);
     291                 :     if (!thisp)
     292                 :         return NULL;
     293                 :     argv[-1].setObject(*thisp);
     294                 :     return thisp;
     295                 : }
     296                 : 
     297                 : /*
     298                 :  * ECMA requires "the global object", but in embeddings such as the browser,
     299                 :  * which have multiple top-level objects (windows, frames, etc. in the DOM),
     300                 :  * we prefer fun's parent.  An example that causes this code to run:
     301                 :  *
     302                 :  *   // in window w1
     303                 :  *   function f() { return this }
     304                 :  *   function g() { return f }
     305                 :  *
     306                 :  *   // in window w2
     307                 :  *   var h = w1.g()
     308                 :  *   alert(h() == w1)
     309                 :  *
     310                 :  * The alert should display "true".
     311                 :  */
     312                 : bool
     313          361780 : js::BoxNonStrictThis(JSContext *cx, const CallReceiver &call)
     314                 : {
     315                 :     /*
     316                 :      * Check for SynthesizeFrame poisoning and fast constructors which
     317                 :      * didn't check their callee properly.
     318                 :      */
     319          361780 :     Value &thisv = call.thisv();
     320          361780 :     JS_ASSERT(!thisv.isMagic());
     321                 : 
     322                 : #ifdef DEBUG
     323          361780 :     JSFunction *fun = call.callee().isFunction() ? call.callee().toFunction() : NULL;
     324          361780 :     JS_ASSERT_IF(fun && fun->isInterpreted(), !fun->inStrictMode());
     325                 : #endif
     326                 : 
     327          361780 :     if (thisv.isNullOrUndefined()) {
     328           64884 :         JSObject *thisp = call.callee().global().thisObject(cx);
     329           64884 :         if (!thisp)
     330               0 :             return false;
     331           64884 :         call.thisv().setObject(*thisp);
     332           64884 :         return true;
     333                 :     }
     334                 : 
     335          296896 :     if (!thisv.isObject())
     336             479 :         return !!js_PrimitiveToObject(cx, &thisv);
     337                 : 
     338          296417 :     return true;
     339                 : }
     340                 : 
     341                 : #if JS_HAS_NO_SUCH_METHOD
     342                 : 
     343                 : const uint32_t JSSLOT_FOUND_FUNCTION  = 0;
     344                 : const uint32_t JSSLOT_SAVED_ID        = 1;
     345                 : 
     346                 : Class js_NoSuchMethodClass = {
     347                 :     "NoSuchMethod",
     348                 :     JSCLASS_HAS_RESERVED_SLOTS(2) | JSCLASS_IS_ANONYMOUS,
     349                 :     JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
     350                 :     JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub,
     351                 : };
     352                 : 
     353                 : /*
     354                 :  * When JSOP_CALLPROP or JSOP_CALLELEM does not find the method property of
     355                 :  * the base object, we search for the __noSuchMethod__ method in the base.
     356                 :  * If it exists, we store the method and the property's id into an object of
     357                 :  * NoSuchMethod class and store this object into the callee's stack slot.
     358                 :  * Later, Invoke will recognise such an object and transfer control to
     359                 :  * NoSuchMethod that invokes the method like:
     360                 :  *
     361                 :  *   this.__noSuchMethod__(id, args)
     362                 :  *
     363                 :  * where id is the name of the method that this invocation attempted to
     364                 :  * call by name, and args is an Array containing this invocation's actual
     365                 :  * parameters.
     366                 :  */
     367                 : bool
     368            1234 : js::OnUnknownMethod(JSContext *cx, JSObject *obj, Value idval, Value *vp)
     369                 : {
     370            1234 :     jsid id = ATOM_TO_JSID(cx->runtime->atomState.noSuchMethodAtom);
     371            2468 :     AutoValueRooter tvr(cx);
     372            1234 :     if (!js_GetMethod(cx, obj, id, JSGET_NO_METHOD_BARRIER, tvr.addr()))
     373               0 :         return false;
     374            1234 :     TypeScript::MonitorUnknown(cx, cx->fp()->script(), cx->regs().pc);
     375                 : 
     376            1234 :     if (tvr.value().isPrimitive()) {
     377             505 :         *vp = tvr.value();
     378                 :     } else {
     379                 : #if JS_HAS_XML_SUPPORT
     380                 :         /* Extract the function name from function::name qname. */
     381             729 :         if (idval.isObject()) {
     382               0 :             obj = &idval.toObject();
     383               0 :             if (js_GetLocalNameFromFunctionQName(obj, &id, cx))
     384               0 :                 idval = IdToValue(id);
     385                 :         }
     386                 : #endif
     387                 : 
     388             729 :         obj = NewObjectWithClassProto(cx, &js_NoSuchMethodClass, NULL, NULL);
     389             729 :         if (!obj)
     390               0 :             return false;
     391                 : 
     392             729 :         obj->setSlot(JSSLOT_FOUND_FUNCTION, tvr.value());
     393             729 :         obj->setSlot(JSSLOT_SAVED_ID, idval);
     394             729 :         vp->setObject(*obj);
     395                 :     }
     396            1234 :     return true;
     397                 : }
     398                 : 
     399                 : static JSBool
     400             729 : NoSuchMethod(JSContext *cx, unsigned argc, Value *vp)
     401                 : {
     402            1458 :     InvokeArgsGuard args;
     403             729 :     if (!cx->stack.pushInvokeArgs(cx, 2, &args))
     404               0 :         return JS_FALSE;
     405                 : 
     406             729 :     JS_ASSERT(vp[0].isObject());
     407             729 :     JS_ASSERT(vp[1].isObject());
     408             729 :     JSObject *obj = &vp[0].toObject();
     409             729 :     JS_ASSERT(obj->getClass() == &js_NoSuchMethodClass);
     410                 : 
     411             729 :     args.calleev() = obj->getSlot(JSSLOT_FOUND_FUNCTION);
     412             729 :     args.thisv() = vp[1];
     413             729 :     args[0] = obj->getSlot(JSSLOT_SAVED_ID);
     414             729 :     JSObject *argsobj = NewDenseCopiedArray(cx, argc, vp + 2);
     415             729 :     if (!argsobj)
     416               0 :         return JS_FALSE;
     417             729 :     args[1].setObject(*argsobj);
     418             729 :     JSBool ok = Invoke(cx, args);
     419             729 :     vp[0] = args.rval();
     420             729 :     return ok;
     421                 : }
     422                 : 
     423                 : #endif /* JS_HAS_NO_SUCH_METHOD */
     424                 : 
     425                 : bool
     426         5449222 : js::RunScript(JSContext *cx, JSScript *script, StackFrame *fp)
     427                 : {
     428         5449222 :     JS_ASSERT(script);
     429         5449222 :     JS_ASSERT(fp == cx->fp());
     430         5449222 :     JS_ASSERT(fp->script() == script);
     431                 : #ifdef JS_METHODJIT_SPEW
     432         5449222 :     JMCheckLogging();
     433                 : #endif
     434                 : 
     435                 :     /* FIXME: Once bug 470510 is fixed, make this an assert. */
     436         5449222 :     if (script->compileAndGo) {
     437         1535559 :         if (fp->scopeChain().global().isCleared()) {
     438               0 :             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CLEARED_SCOPE);
     439               0 :             return false;
     440                 :         }
     441                 :     }
     442                 : 
     443                 : #ifdef DEBUG
     444                 :     struct CheckStackBalance {
     445                 :         JSContext *cx;
     446                 :         StackFrame *fp;
     447                 :         JSObject *enumerators;
     448         5449222 :         CheckStackBalance(JSContext *cx)
     449         5449222 :           : cx(cx), fp(cx->fp()), enumerators(cx->enumerators)
     450         5449222 :         {}
     451         5449222 :         ~CheckStackBalance() {
     452         5449222 :             JS_ASSERT(fp == cx->fp());
     453         5449222 :             JS_ASSERT_IF(!fp->isGeneratorFrame(), enumerators == cx->enumerators);
     454         5449222 :         }
     455        10898444 :     } check(cx);
     456                 : #endif
     457                 : 
     458                 : #ifdef JS_METHODJIT
     459                 :     mjit::CompileStatus status;
     460         5449222 :     status = mjit::CanMethodJIT(cx, script, script->code, fp->isConstructing(),
     461         5449222 :                                 mjit::CompileRequest_Interpreter);
     462         5449222 :     if (status == mjit::Compile_Error)
     463               0 :         return false;
     464                 : 
     465         5449222 :     if (status == mjit::Compile_Okay)
     466         3565008 :         return mjit::JaegerStatusToSuccess(mjit::JaegerShot(cx, false));
     467                 : #endif
     468                 : 
     469         1884214 :     return Interpret(cx, fp);
     470                 : }
     471                 : 
     472                 : /*
     473                 :  * Find a function reference and its 'this' value implicit first parameter
     474                 :  * under argc arguments on cx's stack, and call the function.  Push missing
     475                 :  * required arguments, allocate declared local variables, and pop everything
     476                 :  * when done.  Then push the return value.
     477                 :  */
     478                 : bool
     479        20402721 : js::InvokeKernel(JSContext *cx, CallArgs args, MaybeConstruct construct)
     480                 : {
     481        20402721 :     JS_ASSERT(args.length() <= StackSpace::ARGS_LENGTH_MAX);
     482                 : 
     483        20402721 :     JS_ASSERT(!cx->compartment->activeAnalysis);
     484                 : 
     485                 :     /* MaybeConstruct is a subset of InitialFrameFlags */
     486        20402721 :     InitialFrameFlags initial = (InitialFrameFlags) construct;
     487                 : 
     488        20402721 :     if (args.calleev().isPrimitive()) {
     489             785 :         js_ReportIsNotFunction(cx, &args.calleev(), ToReportFlags(initial));
     490             785 :         return false;
     491                 :     }
     492                 : 
     493        20401936 :     JSObject &callee = args.callee();
     494        20401936 :     Class *clasp = callee.getClass();
     495                 : 
     496                 :     /* Invoke non-functions. */
     497        20401936 :     if (JS_UNLIKELY(clasp != &FunctionClass)) {
     498                 : #if JS_HAS_NO_SUCH_METHOD
     499           40396 :         if (JS_UNLIKELY(clasp == &js_NoSuchMethodClass))
     500             729 :             return NoSuchMethod(cx, args.length(), args.base());
     501                 : #endif
     502           39667 :         JS_ASSERT_IF(construct, !clasp->construct);
     503           39667 :         if (!clasp->call) {
     504              91 :             js_ReportIsNotFunction(cx, &args.calleev(), ToReportFlags(initial));
     505              91 :             return false;
     506                 :         }
     507           39576 :         return CallJSNative(cx, clasp->call, args);
     508                 :     }
     509                 : 
     510                 :     /* Invoke native functions. */
     511        20361540 :     JSFunction *fun = callee.toFunction();
     512        20361540 :     JS_ASSERT_IF(construct, !fun->isNativeConstructor());
     513        20361540 :     if (fun->isNative())
     514        15143781 :         return CallJSNative(cx, fun->u.n.native, args);
     515                 : 
     516         5217759 :     TypeMonitorCall(cx, args, construct);
     517                 : 
     518                 :     /* Get pointer to new frame/slots, prepare arguments. */
     519        10435518 :     InvokeFrameGuard ifg;
     520         5217759 :     if (!cx->stack.pushInvokeFrame(cx, args, initial, &ifg))
     521              28 :         return false;
     522                 : 
     523                 :     /* Now that the new frame is rooted, maybe create a call object. */
     524         5217731 :     StackFrame *fp = ifg.fp();
     525         5217731 :     if (!fp->functionPrologue(cx))
     526               0 :         return false;
     527                 : 
     528                 :     /* Run function until JSOP_STOP, JSOP_RETURN or error. */
     529         5217731 :     JSBool ok = RunScript(cx, fun->script(), fp);
     530                 : 
     531                 :     /* Propagate the return value out. */
     532         5217731 :     args.rval() = fp->returnValue();
     533         5217731 :     JS_ASSERT_IF(ok && construct, !args.rval().isPrimitive());
     534         5217731 :     return ok;
     535                 : }
     536                 : 
     537                 : bool
     538         5292146 : js::Invoke(JSContext *cx, const Value &thisv, const Value &fval, unsigned argc, Value *argv,
     539                 :            Value *rval)
     540                 : {
     541        10584292 :     InvokeArgsGuard args;
     542         5292146 :     if (!cx->stack.pushInvokeArgs(cx, argc, &args))
     543               0 :         return false;
     544                 : 
     545         5292146 :     args.calleev() = fval;
     546         5292146 :     args.thisv() = thisv;
     547         5292146 :     PodCopy(args.array(), argv, argc);
     548                 : 
     549         5292146 :     if (args.thisv().isObject()) {
     550                 :         /*
     551                 :          * We must call the thisObject hook in case we are not called from the
     552                 :          * interpreter, where a prior bytecode has computed an appropriate
     553                 :          * |this| already.
     554                 :          */
     555         5290157 :         JSObject *thisp = args.thisv().toObject().thisObject(cx);
     556         5290157 :         if (!thisp)
     557               0 :              return false;
     558         5290157 :         args.thisv().setObject(*thisp);
     559                 :     }
     560                 : 
     561         5292146 :     if (!Invoke(cx, args))
     562           86010 :         return false;
     563                 : 
     564         5206136 :     *rval = args.rval();
     565         5206136 :     return true;
     566                 : }
     567                 : 
     568                 : bool
     569          266450 : js::InvokeConstructorKernel(JSContext *cx, const CallArgs &argsRef)
     570                 : {
     571          266450 :     JS_ASSERT(!FunctionClass.construct);
     572          266450 :     CallArgs args = argsRef;
     573                 : 
     574          266450 :     args.thisv().setMagic(JS_IS_CONSTRUCTING);
     575                 : 
     576          266450 :     if (args.calleev().isObject()) {
     577          266423 :         JSObject *callee = &args.callee();
     578          266423 :         Class *clasp = callee->getClass();
     579          266423 :         if (clasp == &FunctionClass) {
     580          218322 :             JSFunction *fun = callee->toFunction();
     581                 : 
     582          218322 :             if (fun->isNativeConstructor()) {
     583          217755 :                 Probes::calloutBegin(cx, fun);
     584          217755 :                 bool ok = CallJSNativeConstructor(cx, fun->u.n.native, args);
     585          217755 :                 Probes::calloutEnd(cx, fun);
     586          217755 :                 return ok;
     587                 :             }
     588                 : 
     589             567 :             if (!fun->isInterpretedConstructor())
     590             252 :                 goto error;
     591                 : 
     592             315 :             if (!InvokeKernel(cx, args, CONSTRUCT))
     593              63 :                 return false;
     594                 : 
     595             252 :             JS_ASSERT(args.rval().isObject());
     596             252 :             return true;
     597                 :         }
     598           48101 :         if (clasp->construct)
     599           48092 :             return CallJSNativeConstructor(cx, clasp->construct, args);
     600                 :     }
     601                 : 
     602                 : error:
     603             288 :     js_ReportIsNotFunction(cx, &args.calleev(), JSV2F_CONSTRUCT);
     604             288 :     return false;
     605                 : }
     606                 : 
     607                 : bool
     608            7945 : js::InvokeConstructor(JSContext *cx, const Value &fval, unsigned argc, Value *argv, Value *rval)
     609                 : {
     610           15890 :     InvokeArgsGuard args;
     611            7945 :     if (!cx->stack.pushInvokeArgs(cx, argc, &args))
     612               0 :         return false;
     613                 : 
     614            7945 :     args.calleev() = fval;
     615            7945 :     args.thisv().setMagic(JS_THIS_POISON);
     616            7945 :     PodCopy(args.array(), argv, argc);
     617                 : 
     618            7945 :     if (!InvokeConstructor(cx, args))
     619              72 :         return false;
     620                 : 
     621            7873 :     *rval = args.rval();
     622            7873 :     return true;
     623                 : }
     624                 : 
     625                 : bool
     626         3436268 : js::InvokeGetterOrSetter(JSContext *cx, JSObject *obj, const Value &fval, unsigned argc, Value *argv,
     627                 :                          Value *rval)
     628                 : {
     629                 :     /*
     630                 :      * Invoke could result in another try to get or set the same id again, see
     631                 :      * bug 355497.
     632                 :      */
     633         3436268 :     JS_CHECK_RECURSION(cx, return false);
     634                 : 
     635         3436262 :     return Invoke(cx, ObjectValue(*obj), fval, argc, argv, rval);
     636                 : }
     637                 : 
     638                 : bool
     639          179670 : js::ExecuteKernel(JSContext *cx, JSScript *script, JSObject &scopeChain, const Value &thisv,
     640                 :                   ExecuteType type, StackFrame *evalInFrame, Value *result)
     641                 : {
     642          179670 :     JS_ASSERT_IF(evalInFrame, type == EXECUTE_DEBUG);
     643                 : 
     644          359340 :     Root<JSScript*> scriptRoot(cx, &script);
     645                 : 
     646          179670 :     if (script->isEmpty()) {
     647             500 :         if (result)
     648             490 :             result->setUndefined();
     649             500 :         return true;
     650                 :     }
     651                 : 
     652          358340 :     ExecuteFrameGuard efg;
     653          179170 :     if (!cx->stack.pushExecuteFrame(cx, script, thisv, scopeChain, type, evalInFrame, &efg))
     654               0 :         return false;
     655                 : 
     656          179170 :     if (!script->ensureRanAnalysis(cx, &scopeChain))
     657               0 :         return false;
     658                 : 
     659                 :     /* Give strict mode eval its own fresh lexical environment. */
     660          179170 :     StackFrame *fp = efg.fp();
     661          179170 :     if (fp->isStrictEvalFrame() && !CallObject::createForStrictEval(cx, fp))
     662               0 :         return false;
     663                 : 
     664          179170 :     Probes::startExecution(cx, script);
     665                 : 
     666          179170 :     TypeScript::SetThis(cx, script, fp->thisValue());
     667                 : 
     668          179170 :     bool ok = RunScript(cx, script, fp);
     669                 : 
     670          179170 :     if (fp->isStrictEvalFrame())
     671            1908 :         js_PutCallObject(fp);
     672                 : 
     673          179170 :     Probes::stopExecution(cx, script);
     674                 : 
     675                 :     /* Propgate the return value out. */
     676          179170 :     if (result)
     677          129739 :         *result = fp->returnValue();
     678          179170 :     return ok;
     679                 : }
     680                 : 
     681                 : bool
     682           84060 : js::Execute(JSContext *cx, JSScript *script, JSObject &scopeChainArg, Value *rval)
     683                 : {
     684                 :     /* The scope chain could be anything, so innerize just in case. */
     685           84060 :     JSObject *scopeChain = &scopeChainArg;
     686           84060 :     OBJ_TO_INNER_OBJECT(cx, scopeChain);
     687           84060 :     if (!scopeChain)
     688               0 :         return false;
     689                 : 
     690                 :     /* If we were handed a non-native object, complain bitterly. */
     691           84060 :     if (!scopeChain->isNative()) {
     692               0 :         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NON_NATIVE_SCOPE);
     693               0 :         return false;
     694                 :     }
     695           84060 :     JS_ASSERT(!scopeChain->getOps()->defineProperty);
     696                 : 
     697                 :     /* The VAROBJFIX option makes varObj == globalObj in global code. */
     698           84060 :     if (!cx->hasRunOption(JSOPTION_VAROBJFIX)) {
     699           83830 :         if (!scopeChain->setVarObj(cx))
     700               0 :             return false;
     701                 :     }
     702                 : 
     703                 :     /* Use the scope chain as 'this', modulo outerization. */
     704           84060 :     JSObject *thisObj = scopeChain->thisObject(cx);
     705           84060 :     if (!thisObj)
     706               0 :         return false;
     707           84060 :     Value thisv = ObjectValue(*thisObj);
     708                 : 
     709                 :     return ExecuteKernel(cx, script, *scopeChain, thisv, EXECUTE_GLOBAL,
     710           84060 :                          NULL /* evalInFrame */, rval);
     711                 : }
     712                 : 
     713                 : JSBool
     714         1228760 : js::HasInstance(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp)
     715                 : {
     716         1228760 :     Class *clasp = obj->getClass();
     717         1228760 :     if (clasp->hasInstance)
     718         1228742 :         return clasp->hasInstance(cx, obj, v, bp);
     719              18 :     js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS,
     720              18 :                         JSDVG_SEARCH_STACK, ObjectValue(*obj), NULL);
     721              18 :     return JS_FALSE;
     722                 : }
     723                 : 
     724                 : bool
     725         5222890 : js::LooselyEqual(JSContext *cx, const Value &lval, const Value &rval, bool *result)
     726                 : {
     727                 : #if JS_HAS_XML_SUPPORT
     728        10530629 :     if (JS_UNLIKELY(lval.isObject() && lval.toObject().isXML()) ||
     729         5307739 :                     (rval.isObject() && rval.toObject().isXML())) {
     730                 :         JSBool res;
     731               9 :         if (!js_TestXMLEquality(cx, lval, rval, &res))
     732               0 :             return false;
     733               9 :         *result = !!res;
     734               9 :         return true;
     735                 :     }
     736                 : #endif
     737                 : 
     738         5222881 :     if (SameType(lval, rval)) {
     739         4937272 :         if (lval.isString()) {
     740          930010 :             JSString *l = lval.toString();
     741          930010 :             JSString *r = rval.toString();
     742          930010 :             return EqualStrings(cx, l, r, result);
     743                 :         }
     744                 : 
     745         4007262 :         if (lval.isDouble()) {
     746           45983 :             double l = lval.toDouble(), r = rval.toDouble();
     747           45983 :             *result = (l == r);
     748           45983 :             return true;
     749                 :         }
     750                 : 
     751         3961279 :         if (lval.isObject()) {
     752           77130 :             JSObject *l = &lval.toObject();
     753           77130 :             JSObject *r = &rval.toObject();
     754                 : 
     755           77130 :             if (JSEqualityOp eq = l->getClass()->ext.equality) {
     756                 :                 JSBool res;
     757             517 :                 if (!eq(cx, l, &rval, &res))
     758               0 :                     return false;
     759             517 :                 *result = !!res;
     760             517 :                 return true;
     761                 :             }
     762                 : 
     763           76613 :             *result = l == r;
     764           76613 :             return true;
     765                 :         }
     766                 : 
     767         3884149 :         *result = lval.payloadAsRawUint32() == rval.payloadAsRawUint32();
     768         3884149 :         return true;
     769                 :     }
     770                 : 
     771          285609 :     if (lval.isNullOrUndefined()) {
     772           19831 :         *result = rval.isNullOrUndefined();
     773           19831 :         return true;
     774                 :     }
     775                 : 
     776          265778 :     if (rval.isNullOrUndefined()) {
     777          241630 :         *result = false;
     778          241630 :         return true;
     779                 :     }
     780                 : 
     781           24148 :     Value lvalue = lval;
     782           24148 :     Value rvalue = rval;
     783                 : 
     784           24148 :     if (!ToPrimitive(cx, &lvalue))
     785               5 :         return false;
     786           24143 :     if (!ToPrimitive(cx, &rvalue))
     787               0 :         return false;
     788                 : 
     789           24143 :     if (lvalue.isString() && rvalue.isString()) {
     790            4846 :         JSString *l = lvalue.toString();
     791            4846 :         JSString *r = rvalue.toString();
     792            4846 :         return EqualStrings(cx, l, r, result);
     793                 :     }
     794                 : 
     795                 :     double l, r;
     796           19297 :     if (!ToNumber(cx, lvalue, &l) || !ToNumber(cx, rvalue, &r))
     797               0 :         return false;
     798           19297 :     *result = (l == r);
     799           19297 :     return true;
     800                 : }
     801                 : 
     802                 : bool
     803        12469728 : js::StrictlyEqual(JSContext *cx, const Value &lref, const Value &rref, bool *equal)
     804                 : {
     805        12469728 :     Value lval = lref, rval = rref;
     806        12469728 :     if (SameType(lval, rval)) {
     807        11107214 :         if (lval.isString())
     808         1235225 :             return EqualStrings(cx, lval.toString(), rval.toString(), equal);
     809         9871989 :         if (lval.isDouble()) {
     810         1055916 :             *equal = (lval.toDouble() == rval.toDouble());
     811         1055916 :             return true;
     812                 :         }
     813         8816073 :         if (lval.isObject()) {
     814          720836 :             *equal = lval.toObject() == rval.toObject();
     815          720836 :             return true;
     816                 :         }
     817         8095237 :         if (lval.isUndefined()) {
     818         1204044 :             *equal = true;
     819         1204044 :             return true;
     820                 :         }
     821         6891193 :         *equal = lval.payloadAsRawUint32() == rval.payloadAsRawUint32();
     822         6891193 :         return true;
     823                 :     }
     824                 : 
     825         1362514 :     if (lval.isDouble() && rval.isInt32()) {
     826            7659 :         double ld = lval.toDouble();
     827            7659 :         double rd = rval.toInt32();
     828            7659 :         *equal = (ld == rd);
     829            7659 :         return true;
     830                 :     }
     831         1354855 :     if (lval.isInt32() && rval.isDouble()) {
     832            8825 :         double ld = lval.toInt32();
     833            8825 :         double rd = rval.toDouble();
     834            8825 :         *equal = (ld == rd);
     835            8825 :         return true;
     836                 :     }
     837                 : 
     838         1346030 :     *equal = false;
     839         1346030 :     return true;
     840                 : }
     841                 : 
     842                 : static inline bool
     843        10614194 : IsNegativeZero(const Value &v)
     844                 : {
     845        10614194 :     return v.isDouble() && JSDOUBLE_IS_NEGZERO(v.toDouble());
     846                 : }
     847                 : 
     848                 : static inline bool
     849         5309051 : IsNaN(const Value &v)
     850                 : {
     851         5309051 :     return v.isDouble() && JSDOUBLE_IS_NaN(v.toDouble());
     852                 : }
     853                 : 
     854                 : bool
     855         5307097 : js::SameValue(JSContext *cx, const Value &v1, const Value &v2, bool *same)
     856                 : {
     857         5307097 :     if (IsNegativeZero(v1)) {
     858             621 :         *same = IsNegativeZero(v2);
     859             621 :         return true;
     860                 :     }
     861         5306476 :     if (IsNegativeZero(v2)) {
     862               1 :         *same = false;
     863               1 :         return true;
     864                 :     }
     865         5306475 :     if (IsNaN(v1) && IsNaN(v2)) {
     866            2576 :         *same = true;
     867            2576 :         return true;
     868                 :     }
     869         5303899 :     return StrictlyEqual(cx, v1, v2, same);
     870                 : }
     871                 : 
     872                 : JSType
     873         7889299 : js::TypeOfValue(JSContext *cx, const Value &vref)
     874                 : {
     875         7889299 :     Value v = vref;
     876         7889299 :     if (v.isNumber())
     877           55303 :         return JSTYPE_NUMBER;
     878         7833996 :     if (v.isString())
     879          125584 :         return JSTYPE_STRING;
     880         7708412 :     if (v.isNull())
     881            4435 :         return JSTYPE_OBJECT;
     882         7703977 :     if (v.isUndefined())
     883           51846 :         return JSTYPE_VOID;
     884         7652131 :     if (v.isObject())
     885         7648217 :         return v.toObject().typeOf(cx);
     886            3914 :     JS_ASSERT(v.isBoolean());
     887            3914 :     return JSTYPE_BOOLEAN;
     888                 : }
     889                 : 
     890                 : bool
     891        18661129 : js::ValueToId(JSContext *cx, const Value &v, jsid *idp)
     892                 : {
     893                 :     int32_t i;
     894        18661129 :     if (ValueFitsInInt32(v, &i) && INT_FITS_IN_JSID(i)) {
     895         4726844 :         *idp = INT_TO_JSID(i);
     896         4726844 :         return true;
     897                 :     }
     898                 : 
     899                 : #if JS_HAS_XML_SUPPORT
     900        13934285 :     if (v.isObject()) {
     901              72 :         JSObject *obj = &v.toObject();
     902              72 :         if (obj->isXMLId()) {
     903              36 :             *idp = OBJECT_TO_JSID(obj);
     904              36 :             return JS_TRUE;
     905                 :         }
     906                 :     }
     907                 : #endif
     908                 : 
     909        13934249 :     return js_ValueToStringId(cx, v, idp);
     910                 : }
     911                 : 
     912                 : /*
     913                 :  * Enter the new with scope using an object at sp[-1] and associate the depth
     914                 :  * of the with block with sp + stackIndex.
     915                 :  */
     916                 : static bool
     917            1800 : EnterWith(JSContext *cx, int stackIndex)
     918                 : {
     919            1800 :     StackFrame *fp = cx->fp();
     920            1800 :     Value *sp = cx->regs().sp;
     921            1800 :     JS_ASSERT(stackIndex < 0);
     922            1800 :     JS_ASSERT(fp->base() <= sp + stackIndex);
     923                 : 
     924                 :     JSObject *obj;
     925            1800 :     if (sp[-1].isObject()) {
     926            1773 :         obj = &sp[-1].toObject();
     927                 :     } else {
     928              27 :         obj = js_ValueToNonNullObject(cx, sp[-1]);
     929              27 :         if (!obj)
     930               9 :             return JS_FALSE;
     931              18 :         sp[-1].setObject(*obj);
     932                 :     }
     933                 : 
     934            1791 :     JSObject *parent = GetScopeChain(cx, fp);
     935            1791 :     if (!parent)
     936               0 :         return JS_FALSE;
     937                 : 
     938                 :     JSObject *withobj = WithObject::create(cx, fp, *obj, *parent,
     939            1791 :                                            sp + stackIndex - fp->base());
     940            1791 :     if (!withobj)
     941               0 :         return JS_FALSE;
     942                 : 
     943            1791 :     fp->setScopeChainNoCallObj(*withobj);
     944            1791 :     return JS_TRUE;
     945                 : }
     946                 : 
     947                 : static void
     948            1791 : LeaveWith(JSContext *cx)
     949                 : {
     950            1791 :     WithObject &withobj = cx->fp()->scopeChain().asWith();
     951            1791 :     JS_ASSERT(withobj.maybeStackFrame() == js_FloatingFrameIfGenerator(cx, cx->fp()));
     952            1791 :     JS_ASSERT(withobj.stackDepth() >= 0);
     953            1791 :     withobj.setStackFrame(NULL);
     954            1791 :     cx->fp()->setScopeChainNoCallObj(withobj.enclosingScope());
     955            1791 : }
     956                 : 
     957                 : bool
     958        18546107 : js::IsActiveWithOrBlock(JSContext *cx, JSObject &obj, uint32_t stackDepth)
     959                 : {
     960        37092063 :     return (obj.isWith() || obj.isBlock()) &&
     961           34194 :            obj.getPrivate() == js_FloatingFrameIfGenerator(cx, cx->fp()) &&
     962        37126257 :            obj.asNestedScope().stackDepth() >= stackDepth;
     963                 : }
     964                 : 
     965                 : /* Unwind block and scope chains to match the given depth. */
     966                 : void
     967         3378582 : js::UnwindScope(JSContext *cx, uint32_t stackDepth)
     968                 : {
     969         3378582 :     JS_ASSERT(cx->fp()->base() + stackDepth <= cx->regs().sp);
     970                 : 
     971         3378582 :     StackFrame *fp = cx->fp();
     972         3378582 :     StaticBlockObject *block = fp->maybeBlockChain();
     973         6760861 :     while (block) {
     974            4550 :         if (block->stackDepth() < stackDepth)
     975             853 :             break;
     976            3697 :         block = block->enclosingBlock();
     977                 :     }
     978         3378582 :     fp->setBlockChain(block);
     979                 : 
     980             106 :     for (;;) {
     981         3378688 :         JSObject &scopeChain = fp->scopeChain();
     982         3378688 :         if (!IsActiveWithOrBlock(cx, scopeChain, stackDepth))
     983                 :             break;
     984             106 :         if (scopeChain.isClonedBlock())
     985              88 :             scopeChain.asClonedBlock().put(cx);
     986                 :         else
     987              18 :             LeaveWith(cx);
     988                 :     }
     989         3378582 : }
     990                 : 
     991                 : void
     992            2176 : js::UnwindForUncatchableException(JSContext *cx, const FrameRegs &regs)
     993                 : {
     994                 : 
     995                 :     /* c.f. the regular (catchable) TryNoteIter loop in Interpret. */
     996            2239 :     for (TryNoteIter tni(regs); !tni.done(); ++tni) {
     997              63 :         JSTryNote *tn = *tni;
     998              63 :         if (tn->kind == JSTRY_ITER) {
     999               0 :             Value *sp = regs.fp()->base() + tn->stackDepth;
    1000               0 :             UnwindIteratorForUncatchableException(cx, &sp[-1].toObject());
    1001                 :         }
    1002                 :     }
    1003            2176 : }
    1004                 : 
    1005         2104457 : TryNoteIter::TryNoteIter(const FrameRegs &regs)
    1006                 :   : regs(regs),
    1007         2104457 :     script(regs.fp()->script()),
    1008         4208914 :     pcOffset(regs.pc - script->main())
    1009                 : {
    1010         2104457 :     if (JSScript::isValidOffset(script->trynotesOffset)) {
    1011           70515 :         tn = script->trynotes()->vector;
    1012           70515 :         tnEnd = tn + script->trynotes()->length;
    1013                 :     } else {
    1014         2033942 :         tn = tnEnd = NULL;
    1015                 :     }
    1016         2104457 :     settle();
    1017         2104457 : }
    1018                 : 
    1019                 : void
    1020            2855 : TryNoteIter::operator++()
    1021                 : {
    1022            2855 :     ++tn;
    1023            2855 :     settle();
    1024            2855 : }
    1025                 : 
    1026                 : bool
    1027         2107312 : TryNoteIter::done() const
    1028                 : {
    1029         2107312 :     return tn == tnEnd;
    1030                 : }
    1031                 : 
    1032                 : void
    1033         2107312 : TryNoteIter::settle()
    1034                 : {
    1035         2217618 :     for (; tn != tnEnd; ++tn) {
    1036                 :         /* If pc is out of range, try the next one. */
    1037          147357 :         if (pcOffset - tn->start >= tn->length)
    1038          110306 :             continue;
    1039                 : 
    1040                 :         /*
    1041                 :          * We have a note that covers the exception pc but we must check
    1042                 :          * whether the interpreter has already executed the corresponding
    1043                 :          * handler. This is possible when the executed bytecode implements
    1044                 :          * break or return from inside a for-in loop.
    1045                 :          *
    1046                 :          * In this case the emitter generates additional [enditer] and [gosub]
    1047                 :          * opcodes to close all outstanding iterators and execute the finally
    1048                 :          * blocks. If such an [enditer] throws an exception, its pc can still
    1049                 :          * be inside several nested for-in loops and try-finally statements
    1050                 :          * even if we have already closed the corresponding iterators and
    1051                 :          * invoked the finally blocks.
    1052                 :          *
    1053                 :          * To address this, we make [enditer] always decrease the stack even
    1054                 :          * when its implementation throws an exception. Thus already executed
    1055                 :          * [enditer] and [gosub] opcodes will have try notes with the stack
    1056                 :          * depth exceeding the current one and this condition is what we use to
    1057                 :          * filter them out.
    1058                 :          */
    1059           37051 :         if (tn->stackDepth <= regs.sp - regs.fp()->base())
    1060           37051 :             break;
    1061                 :     }
    1062         2107312 : }
    1063                 : 
    1064                 : /*
    1065                 :  * Increment/decrement the value 'v'. The resulting value is stored in *slot.
    1066                 :  * The result of the expression (taking into account prefix/postfix) is stored
    1067                 :  * in *expr.
    1068                 :  */
    1069                 : static bool
    1070       204325659 : DoIncDec(JSContext *cx, JSScript *script, jsbytecode *pc, const Value &v, Value *slot, Value *expr)
    1071                 : {
    1072       204325659 :     const JSCodeSpec &cs = js_CodeSpec[*pc];
    1073                 : 
    1074       204325659 :     if (v.isInt32()) {
    1075       204323460 :         int32_t i = v.toInt32();
    1076       204323460 :         if (i > JSVAL_INT_MIN && i < JSVAL_INT_MAX) {
    1077       204323436 :             int32_t sum = i + (cs.format & JOF_INC ? 1 : -1);
    1078       204323436 :             *slot = Int32Value(sum);
    1079       204323436 :             *expr = (cs.format & JOF_POST) ? Int32Value(i) : *slot;
    1080       204323436 :             return true;
    1081                 :         }
    1082                 :     }
    1083                 : 
    1084                 :     double d;
    1085            2223 :     if (!ToNumber(cx, *slot, &d))
    1086               0 :         return false;
    1087                 : 
    1088            2223 :     double sum = d + (cs.format & JOF_INC ? 1 : -1);
    1089            2223 :     *slot = NumberValue(sum);
    1090            2223 :     *expr = (cs.format & JOF_POST) ? NumberValue(d) : *slot;
    1091                 : 
    1092            2223 :     TypeScript::MonitorOverflow(cx, script, pc);
    1093            2223 :     return true;
    1094                 : }
    1095                 : 
    1096                 : const Value &
    1097          765453 : js::GetUpvar(JSContext *cx, unsigned closureLevel, UpvarCookie cookie)
    1098                 : {
    1099          765453 :     JS_ASSERT(closureLevel >= cookie.level() && cookie.level() > 0);
    1100          765453 :     const unsigned targetLevel = closureLevel - cookie.level();
    1101                 : 
    1102          765453 :     StackFrame *fp = FindUpvarFrame(cx, targetLevel);
    1103          765453 :     unsigned slot = cookie.slot();
    1104                 :     const Value *vp;
    1105                 : 
    1106          765453 :     if (!fp->isFunctionFrame() || fp->isEvalFrame()) {
    1107              30 :         vp = fp->slots() + fp->numFixed();
    1108          765423 :     } else if (slot < fp->numFormalArgs()) {
    1109          411919 :         vp = fp->formalArgs();
    1110          353504 :     } else if (slot == UpvarCookie::CALLEE_SLOT) {
    1111               0 :         vp = &fp->calleev();
    1112               0 :         slot = 0;
    1113                 :     } else {
    1114          353504 :         slot -= fp->numFormalArgs();
    1115          353504 :         JS_ASSERT(slot < fp->numSlots());
    1116          353504 :         vp = fp->slots();
    1117                 :     }
    1118                 : 
    1119          765453 :     return vp[slot];
    1120                 : }
    1121                 : 
    1122                 : extern StackFrame *
    1123          765453 : js::FindUpvarFrame(JSContext *cx, unsigned targetLevel)
    1124                 : {
    1125          765453 :     StackFrame *fp = cx->fp();
    1126             889 :     while (true) {
    1127          766342 :         JS_ASSERT(fp && fp->isScriptFrame());
    1128          766342 :         if (fp->script()->staticLevel == targetLevel)
    1129                 :             break;
    1130             889 :         fp = fp->prev();
    1131                 :     }
    1132          765453 :     return fp;
    1133                 : }
    1134                 : 
    1135                 : #define PUSH_COPY(v)             do { *regs.sp++ = v; assertSameCompartment(cx, regs.sp[-1]); } while (0)
    1136                 : #define PUSH_COPY_SKIP_CHECK(v)  *regs.sp++ = v
    1137                 : #define PUSH_NULL()              regs.sp++->setNull()
    1138                 : #define PUSH_UNDEFINED()         regs.sp++->setUndefined()
    1139                 : #define PUSH_BOOLEAN(b)          regs.sp++->setBoolean(b)
    1140                 : #define PUSH_DOUBLE(d)           regs.sp++->setDouble(d)
    1141                 : #define PUSH_INT32(i)            regs.sp++->setInt32(i)
    1142                 : #define PUSH_STRING(s)           do { regs.sp++->setString(s); assertSameCompartment(cx, regs.sp[-1]); } while (0)
    1143                 : #define PUSH_OBJECT(obj)         do { regs.sp++->setObject(obj); assertSameCompartment(cx, regs.sp[-1]); } while (0)
    1144                 : #define PUSH_OBJECT_OR_NULL(obj) do { regs.sp++->setObjectOrNull(obj); assertSameCompartment(cx, regs.sp[-1]); } while (0)
    1145                 : #define PUSH_HOLE()              regs.sp++->setMagic(JS_ARRAY_HOLE)
    1146                 : #define POP_COPY_TO(v)           v = *--regs.sp
    1147                 : #define POP_RETURN_VALUE()       regs.fp()->setReturnValue(*--regs.sp)
    1148                 : 
    1149                 : #define VALUE_TO_BOOLEAN(cx, vp, b)                                           \
    1150                 :     JS_BEGIN_MACRO                                                            \
    1151                 :         vp = &regs.sp[-1];                                                    \
    1152                 :         if (vp->isNull()) {                                                   \
    1153                 :             b = false;                                                        \
    1154                 :         } else if (vp->isBoolean()) {                                         \
    1155                 :             b = vp->toBoolean();                                              \
    1156                 :         } else {                                                              \
    1157                 :             b = !!js_ValueToBoolean(*vp);                                     \
    1158                 :         }                                                                     \
    1159                 :     JS_END_MACRO
    1160                 : 
    1161                 : #define POP_BOOLEAN(cx, vp, b)   do { VALUE_TO_BOOLEAN(cx, vp, b); regs.sp--; } while(0)
    1162                 : 
    1163                 : #define FETCH_OBJECT(cx, n, obj)                                              \
    1164                 :     JS_BEGIN_MACRO                                                            \
    1165                 :         Value *vp_ = &regs.sp[n];                                             \
    1166                 :         obj = ToObject(cx, (vp_));                                            \
    1167                 :         if (!obj)                                                             \
    1168                 :             goto error;                                                       \
    1169                 :     JS_END_MACRO
    1170                 : 
    1171                 : /*
    1172                 :  * Threaded interpretation via computed goto appears to be well-supported by
    1173                 :  * GCC 3 and higher.  IBM's C compiler when run with the right options (e.g.,
    1174                 :  * -qlanglvl=extended) also supports threading.  Ditto the SunPro C compiler.
    1175                 :  * Currently it's broken for JS_VERSION < 160, though this isn't worth fixing.
    1176                 :  * Add your compiler support macros here.
    1177                 :  */
    1178                 : #ifndef JS_THREADED_INTERP
    1179                 : # if JS_VERSION >= 160 && (                                                   \
    1180                 :     __GNUC__ >= 3 ||                                                          \
    1181                 :     (__IBMC__ >= 700 && defined __IBM_COMPUTED_GOTO) ||                       \
    1182                 :     __SUNPRO_C >= 0x570)
    1183                 : #  define JS_THREADED_INTERP 1
    1184                 : # else
    1185                 : #  define JS_THREADED_INTERP 0
    1186                 : # endif
    1187                 : #endif
    1188                 : 
    1189                 : template<typename T>
    1190                 : class GenericInterruptEnabler : public InterpreterFrames::InterruptEnablerBase {
    1191                 :   public:
    1192         1997347 :     GenericInterruptEnabler(T *variable, T value) : variable(variable), value(value) { }
    1193            1534 :     void enableInterrupts() const { *variable = value; }
    1194                 : 
    1195                 :   private:
    1196                 :     T *variable;
    1197                 :     T value;
    1198                 : };
    1199                 : 
    1200         1997347 : inline InterpreterFrames::InterpreterFrames(JSContext *cx, FrameRegs *regs, 
    1201                 :                                             const InterruptEnablerBase &enabler)
    1202         1997347 :   : context(cx), regs(regs), enabler(enabler)
    1203                 : {
    1204         1997347 :     older = cx->runtime->interpreterFrames;
    1205         1997347 :     cx->runtime->interpreterFrames = this;
    1206         1997347 : }
    1207                 :  
    1208         1997347 : inline InterpreterFrames::~InterpreterFrames()
    1209                 : {
    1210         1997347 :     context->runtime->interpreterFrames = older;
    1211         1997347 : }
    1212                 : 
    1213                 : #if defined(DEBUG) && !defined(JS_THREADSAFE)
    1214                 : void
    1215                 : js::AssertValidPropertyCacheHit(JSContext *cx,
    1216                 :                                 JSObject *start, JSObject *found,
    1217                 :                                 PropertyCacheEntry *entry)
    1218                 : {
    1219                 :     jsbytecode *pc;
    1220                 :     cx->stack.currentScript(&pc);
    1221                 : 
    1222                 :     uint64_t sample = cx->runtime->gcNumber;
    1223                 :     PropertyCacheEntry savedEntry = *entry;
    1224                 : 
    1225                 :     PropertyName *name = GetNameFromBytecode(cx, pc, JSOp(*pc), js_CodeSpec[*pc]);
    1226                 : 
    1227                 :     JSObject *obj, *pobj;
    1228                 :     JSProperty *prop;
    1229                 :     JSBool ok;
    1230                 : 
    1231                 :     if (JOF_OPMODE(*pc) == JOF_NAME)
    1232                 :         ok = FindProperty(cx, name, start, &obj, &pobj, &prop);
    1233                 :     else
    1234                 :         ok = LookupProperty(cx, start, name, &pobj, &prop);
    1235                 :     JS_ASSERT(ok);
    1236                 : 
    1237                 :     if (cx->runtime->gcNumber != sample)
    1238                 :         JS_PROPERTY_CACHE(cx).restore(&savedEntry);
    1239                 :     JS_ASSERT(prop);
    1240                 :     JS_ASSERT(pobj == found);
    1241                 : 
    1242                 :     const Shape *shape = (Shape *) prop;
    1243                 :     JS_ASSERT(entry->prop == shape);
    1244                 : }
    1245                 : #endif /* DEBUG && !JS_THREADSAFE */
    1246                 : 
    1247                 : /*
    1248                 :  * Ensure that the intrepreter switch can close call-bytecode cases in the
    1249                 :  * same way as non-call bytecodes.
    1250                 :  */
    1251                 : JS_STATIC_ASSERT(JSOP_NAME_LENGTH == JSOP_CALLNAME_LENGTH);
    1252                 : JS_STATIC_ASSERT(JSOP_GETFCSLOT_LENGTH == JSOP_CALLFCSLOT_LENGTH);
    1253                 : JS_STATIC_ASSERT(JSOP_GETARG_LENGTH == JSOP_CALLARG_LENGTH);
    1254                 : JS_STATIC_ASSERT(JSOP_GETLOCAL_LENGTH == JSOP_CALLLOCAL_LENGTH);
    1255                 : JS_STATIC_ASSERT(JSOP_XMLNAME_LENGTH == JSOP_CALLXMLNAME_LENGTH);
    1256                 : 
    1257                 : /*
    1258                 :  * Same for JSOP_SETNAME and JSOP_SETPROP, which differ only slightly but
    1259                 :  * remain distinct for the decompiler. Likewise for JSOP_INIT{PROP,METHOD}.
    1260                 :  */
    1261                 : JS_STATIC_ASSERT(JSOP_SETNAME_LENGTH == JSOP_SETPROP_LENGTH);
    1262                 : JS_STATIC_ASSERT(JSOP_SETNAME_LENGTH == JSOP_SETMETHOD_LENGTH);
    1263                 : JS_STATIC_ASSERT(JSOP_INITPROP_LENGTH == JSOP_INITMETHOD_LENGTH);
    1264                 : 
    1265                 : /* See TRY_BRANCH_AFTER_COND. */
    1266                 : JS_STATIC_ASSERT(JSOP_IFNE_LENGTH == JSOP_IFEQ_LENGTH);
    1267                 : JS_STATIC_ASSERT(JSOP_IFNE == JSOP_IFEQ + 1);
    1268                 : 
    1269                 : /* For the fastest case inder JSOP_INCNAME, etc. */
    1270                 : JS_STATIC_ASSERT(JSOP_INCNAME_LENGTH == JSOP_DECNAME_LENGTH);
    1271                 : JS_STATIC_ASSERT(JSOP_INCNAME_LENGTH == JSOP_NAMEINC_LENGTH);
    1272                 : JS_STATIC_ASSERT(JSOP_INCNAME_LENGTH == JSOP_NAMEDEC_LENGTH);
    1273                 : 
    1274                 : /*
    1275                 :  * Inline fast paths for iteration. js_IteratorMore and js_IteratorNext handle
    1276                 :  * all cases, but we inline the most frequently taken paths here.
    1277                 :  */
    1278                 : static inline bool
    1279         4605547 : IteratorMore(JSContext *cx, JSObject *iterobj, bool *cond, Value *rval)
    1280                 : {
    1281         4605547 :     if (iterobj->isIterator()) {
    1282         4583325 :         NativeIterator *ni = iterobj->getNativeIterator();
    1283         4583325 :         if (ni->isKeyIter()) {
    1284          734396 :             *cond = (ni->props_cursor < ni->props_end);
    1285          734396 :             return true;
    1286                 :         }
    1287                 :     }
    1288         3871151 :     if (!js_IteratorMore(cx, iterobj, rval))
    1289              20 :         return false;
    1290         3871131 :     *cond = rval->isTrue();
    1291         3871131 :     return true;
    1292                 : }
    1293                 : 
    1294                 : static inline bool
    1295         4412591 : IteratorNext(JSContext *cx, JSObject *iterobj, Value *rval)
    1296                 : {
    1297         4412591 :     if (iterobj->isIterator()) {
    1298         4396488 :         NativeIterator *ni = iterobj->getNativeIterator();
    1299         4396488 :         if (ni->isKeyIter()) {
    1300          685234 :             JS_ASSERT(ni->props_cursor < ni->props_end);
    1301          685234 :             rval->setString(*ni->current());
    1302          685234 :             ni->incCursor();
    1303          685234 :             return true;
    1304                 :         }
    1305                 :     }
    1306         3727357 :     return js_IteratorNext(cx, iterobj, rval);
    1307                 : }
    1308                 : 
    1309                 : /*
    1310                 :  * For bytecodes which push values and then fall through, make sure the
    1311                 :  * types of the pushed values are consistent with type inference information.
    1312                 :  */
    1313                 : static inline void
    1314      1655882633 : TypeCheckNextBytecode(JSContext *cx, JSScript *script, unsigned n, const FrameRegs &regs)
    1315                 : {
    1316                 : #ifdef DEBUG
    1317     -2077069427 :     if (cx->typeInferenceEnabled() &&
    1318       562015236 :         n == GetBytecodeLength(regs.pc)) {
    1319       559323774 :         TypeScript::CheckBytecode(cx, script, regs.pc, regs.sp);
    1320                 :     }
    1321                 : #endif
    1322      1655882633 : }
    1323                 : 
    1324                 : JS_NEVER_INLINE bool
    1325         1997347 : js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode)
    1326                 : {
    1327         3994694 :     JSAutoResolveFlags rf(cx, RESOLVE_INFER);
    1328                 : 
    1329         1997347 :     gc::MaybeVerifyBarriers(cx, true);
    1330                 : 
    1331         1997347 :     JS_ASSERT(!cx->compartment->activeAnalysis);
    1332                 : 
    1333                 : #if JS_THREADED_INTERP
    1334                 : #define CHECK_PCCOUNT_INTERRUPTS() JS_ASSERT_IF(script->pcCounters, jumpTable == interruptJumpTable)
    1335                 : #else
    1336                 : #define CHECK_PCCOUNT_INTERRUPTS() JS_ASSERT_IF(script->pcCounters, switchMask == -1)
    1337                 : #endif
    1338                 : 
    1339                 :     /*
    1340                 :      * Macros for threaded interpreter loop
    1341                 :      */
    1342                 : #if JS_THREADED_INTERP
    1343                 :     static void *const normalJumpTable[] = {
    1344                 : # define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
    1345                 :         JS_EXTENSION &&L_##op,
    1346                 : # include "jsopcode.tbl"
    1347                 : # undef OPDEF
    1348                 :     };
    1349                 : 
    1350                 :     static void *const interruptJumpTable[] = {
    1351                 : # define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format)              \
    1352                 :         JS_EXTENSION &&interrupt,
    1353                 : # include "jsopcode.tbl"
    1354                 : # undef OPDEF
    1355                 :     };
    1356                 : 
    1357         1997347 :     register void * const *jumpTable = normalJumpTable;
    1358                 : 
    1359                 :     typedef GenericInterruptEnabler<void * const *> InterruptEnabler;
    1360         1997347 :     InterruptEnabler interruptEnabler(&jumpTable, interruptJumpTable);
    1361                 : 
    1362                 : # define DO_OP()            JS_BEGIN_MACRO                                    \
    1363                 :                                 CHECK_PCCOUNT_INTERRUPTS();                   \
    1364                 :                                 js::gc::MaybeVerifyBarriers(cx);              \
    1365                 :                                 JS_EXTENSION_(goto *jumpTable[op]);           \
    1366                 :                             JS_END_MACRO
    1367                 : # define DO_NEXT_OP(n)      JS_BEGIN_MACRO                                    \
    1368                 :                                 TypeCheckNextBytecode(cx, script, n, regs);   \
    1369                 :                                 op = (JSOp) *(regs.pc += (n));                \
    1370                 :                                 DO_OP();                                      \
    1371                 :                             JS_END_MACRO
    1372                 : 
    1373                 : # define BEGIN_CASE(OP)     L_##OP:
    1374                 : # define END_CASE(OP)       DO_NEXT_OP(OP##_LENGTH);
    1375                 : # define END_VARLEN_CASE    DO_NEXT_OP(len);
    1376                 : # define ADD_EMPTY_CASE(OP) BEGIN_CASE(OP)                                    \
    1377                 :                                 JS_ASSERT(js_CodeSpec[OP].length == 1);       \
    1378                 :                                 op = (JSOp) *++regs.pc;                       \
    1379                 :                                 DO_OP();
    1380                 : 
    1381                 : # define END_EMPTY_CASES
    1382                 : 
    1383                 : #else /* !JS_THREADED_INTERP */
    1384                 : 
    1385                 :     register int switchMask = 0;
    1386                 :     int switchOp;
    1387                 :     typedef GenericInterruptEnabler<int> InterruptEnabler;
    1388                 :     InterruptEnabler interruptEnabler(&switchMask, -1);
    1389                 : 
    1390                 : # define DO_OP()            goto do_op
    1391                 : # define DO_NEXT_OP(n)      JS_BEGIN_MACRO                                    \
    1392                 :                                 JS_ASSERT((n) == len);                        \
    1393                 :                                 goto advance_pc;                              \
    1394                 :                             JS_END_MACRO
    1395                 : 
    1396                 : # define BEGIN_CASE(OP)     case OP:
    1397                 : # define END_CASE(OP)       END_CASE_LEN(OP##_LENGTH)
    1398                 : # define END_CASE_LEN(n)    END_CASE_LENX(n)
    1399                 : # define END_CASE_LENX(n)   END_CASE_LEN##n
    1400                 : 
    1401                 : /*
    1402                 :  * To share the code for all len == 1 cases we use the specialized label with
    1403                 :  * code that falls through to advance_pc: .
    1404                 :  */
    1405                 : # define END_CASE_LEN1      goto advance_pc_by_one;
    1406                 : # define END_CASE_LEN2      len = 2; goto advance_pc;
    1407                 : # define END_CASE_LEN3      len = 3; goto advance_pc;
    1408                 : # define END_CASE_LEN4      len = 4; goto advance_pc;
    1409                 : # define END_CASE_LEN5      len = 5; goto advance_pc;
    1410                 : # define END_CASE_LEN6      len = 6; goto advance_pc;
    1411                 : # define END_CASE_LEN7      len = 7; goto advance_pc;
    1412                 : # define END_VARLEN_CASE    goto advance_pc;
    1413                 : # define ADD_EMPTY_CASE(OP) BEGIN_CASE(OP)
    1414                 : # define END_EMPTY_CASES    goto advance_pc_by_one;
    1415                 : 
    1416                 : #endif /* !JS_THREADED_INTERP */
    1417                 : 
    1418                 : #define ENABLE_INTERRUPTS() (interruptEnabler.enableInterrupts())
    1419                 : 
    1420                 : #define LOAD_ATOM(PCOFF, atom)                                                \
    1421                 :     JS_BEGIN_MACRO                                                            \
    1422                 :         JS_ASSERT((size_t)(atoms - script->atoms) <                           \
    1423                 :                   (size_t)(script->natoms - GET_UINT32_INDEX(regs.pc + PCOFF)));\
    1424                 :         atom = atoms[GET_UINT32_INDEX(regs.pc + PCOFF)];                      \
    1425                 :     JS_END_MACRO
    1426                 : 
    1427                 : #define LOAD_NAME(PCOFF, name)                                                \
    1428                 :     JS_BEGIN_MACRO                                                            \
    1429                 :         JSAtom *atom;                                                         \
    1430                 :         LOAD_ATOM((PCOFF), atom);                                             \
    1431                 :         name = atom->asPropertyName();                                        \
    1432                 :     JS_END_MACRO
    1433                 : 
    1434                 : #define LOAD_DOUBLE(PCOFF, dbl)                                               \
    1435                 :     (dbl = script->getConst(GET_UINT32_INDEX(regs.pc + (PCOFF))).toDouble())
    1436                 : 
    1437                 : #if defined(JS_METHODJIT)
    1438         1997347 :     bool useMethodJIT = false;
    1439                 : #endif
    1440                 : 
    1441                 : #ifdef JS_METHODJIT
    1442                 : 
    1443                 : #define RESET_USE_METHODJIT()                                                 \
    1444                 :     JS_BEGIN_MACRO                                                            \
    1445                 :         useMethodJIT = cx->methodJitEnabled &&                                \
    1446                 :            (interpMode == JSINTERP_NORMAL ||                                  \
    1447                 :             interpMode == JSINTERP_REJOIN ||                                  \
    1448                 :             interpMode == JSINTERP_SKIP_TRAP);                                \
    1449                 :     JS_END_MACRO
    1450                 : 
    1451                 : #define CHECK_PARTIAL_METHODJIT(status)                                       \
    1452                 :     JS_BEGIN_MACRO                                                            \
    1453                 :         switch (status) {                                                     \
    1454                 :           case mjit::Jaeger_UnfinishedAtTrap:                                 \
    1455                 :             interpMode = JSINTERP_SKIP_TRAP;                                  \
    1456                 :             /* FALLTHROUGH */                                                 \
    1457                 :           case mjit::Jaeger_Unfinished:                                       \
    1458                 :             op = (JSOp) *regs.pc;                                             \
    1459                 :             RESTORE_INTERP_VARS_CHECK_EXCEPTION();                            \
    1460                 :             DO_OP();                                                          \
    1461                 :           default:;                                                           \
    1462                 :         }                                                                     \
    1463                 :     JS_END_MACRO
    1464                 : 
    1465                 : #else
    1466                 : 
    1467                 : #define RESET_USE_METHODJIT() ((void) 0)
    1468                 : 
    1469                 : #endif
    1470                 : 
    1471                 : #define RESTORE_INTERP_VARS()                                                 \
    1472                 :     JS_BEGIN_MACRO                                                            \
    1473                 :         SET_SCRIPT(regs.fp()->script());                                      \
    1474                 :         argv = regs.fp()->maybeFormalArgs();                                  \
    1475                 :         atoms = FrameAtomBase(cx, regs.fp());                                 \
    1476                 :         JS_ASSERT(&cx->regs() == &regs);                                      \
    1477                 :     JS_END_MACRO
    1478                 : 
    1479                 : #define RESTORE_INTERP_VARS_CHECK_EXCEPTION()                                 \
    1480                 :     JS_BEGIN_MACRO                                                            \
    1481                 :         RESTORE_INTERP_VARS();                                                \
    1482                 :         if (cx->isExceptionPending())                                         \
    1483                 :             goto error;                                                       \
    1484                 :         CHECK_INTERRUPT_HANDLER();                                            \
    1485                 :     JS_END_MACRO
    1486                 : 
    1487                 :     /*
    1488                 :      * Prepare to call a user-supplied branch handler, and abort the script
    1489                 :      * if it returns false.
    1490                 :      */
    1491                 : #define CHECK_BRANCH()                                                        \
    1492                 :     JS_BEGIN_MACRO                                                            \
    1493                 :         if (cx->runtime->interrupt && !js_HandleExecutionInterrupt(cx))       \
    1494                 :             goto error;                                                       \
    1495                 :     JS_END_MACRO
    1496                 : 
    1497                 : #define BRANCH(n)                                                             \
    1498                 :     JS_BEGIN_MACRO                                                            \
    1499                 :         regs.pc += (n);                                                       \
    1500                 :         op = (JSOp) *regs.pc;                                                 \
    1501                 :         if ((n) <= 0)                                                         \
    1502                 :             goto check_backedge;                                              \
    1503                 :         DO_OP();                                                              \
    1504                 :     JS_END_MACRO
    1505                 : 
    1506                 : #define SET_SCRIPT(s)                                                         \
    1507                 :     JS_BEGIN_MACRO                                                            \
    1508                 :         script = (s);                                                         \
    1509                 :         if (script->hasAnyBreakpointsOrStepMode())                            \
    1510                 :             ENABLE_INTERRUPTS();                                              \
    1511                 :         if (script->pcCounters)                                               \
    1512                 :             ENABLE_INTERRUPTS();                                              \
    1513                 :         JS_ASSERT_IF(interpMode == JSINTERP_SKIP_TRAP,                        \
    1514                 :                      script->hasAnyBreakpointsOrStepMode());                  \
    1515                 :     JS_END_MACRO
    1516                 : 
    1517                 : #define CHECK_INTERRUPT_HANDLER()                                             \
    1518                 :     JS_BEGIN_MACRO                                                            \
    1519                 :         if (cx->runtime->debugHooks.interruptHook)                            \
    1520                 :             ENABLE_INTERRUPTS();                                              \
    1521                 :     JS_END_MACRO
    1522                 : 
    1523                 :     /* Repoint cx->regs to a local variable for faster access. */
    1524         1997347 :     FrameRegs regs = cx->regs();
    1525         3994694 :     PreserveRegsGuard interpGuard(cx, regs);
    1526                 : 
    1527                 :     /*
    1528                 :      * Help Debugger find frames running scripts that it has put in
    1529                 :      * single-step mode.
    1530                 :      */
    1531         3994694 :     InterpreterFrames interpreterFrame(cx, &regs, interruptEnabler);
    1532                 : 
    1533                 :     /* Copy in hot values that change infrequently. */
    1534         1997347 :     JSRuntime *const rt = cx->runtime;
    1535                 :     JSScript *script;
    1536         1997347 :     SET_SCRIPT(regs.fp()->script());
    1537         1997347 :     Value *argv = regs.fp()->maybeFormalArgs();
    1538         1997347 :     CHECK_INTERRUPT_HANDLER();
    1539                 : 
    1540         1997347 :     if (rt->profilingScripts)
    1541               0 :         ENABLE_INTERRUPTS();
    1542                 : 
    1543         1997347 :     if (!entryFrame)
    1544               0 :         entryFrame = regs.fp();
    1545                 : 
    1546                 :     /*
    1547                 :      * Initialize the index segment register used by LOAD_ATOM and
    1548                 :      * GET_FULL_INDEX macros below. As a register we use a pointer based on
    1549                 :      * the atom map to turn frequently executed LOAD_ATOM into simple array
    1550                 :      * access. For less frequent object loads we have to recover the segment
    1551                 :      * from atoms pointer first.
    1552                 :      */
    1553         1997347 :     JSAtom **atoms = script->atoms;
    1554                 : 
    1555                 : #if JS_HAS_GENERATORS
    1556         1997347 :     if (JS_UNLIKELY(regs.fp()->isGeneratorFrame())) {
    1557           52321 :         JS_ASSERT((size_t) (regs.pc - script->code) <= script->length);
    1558           52321 :         JS_ASSERT((size_t) (regs.sp - regs.fp()->base()) <= StackDepth(script));
    1559                 : 
    1560                 :         /*
    1561                 :          * To support generator_throw and to catch ignored exceptions,
    1562                 :          * fail if cx->isExceptionPending() is true.
    1563                 :          */
    1564           52321 :         if (cx->isExceptionPending())
    1565            1479 :             goto error;
    1566                 :     }
    1567                 : #endif
    1568                 : 
    1569                 :     /* State communicated between non-local jumps: */
    1570                 :     bool interpReturnOK;
    1571                 : 
    1572                 :     /* Don't call the script prologue if executing between Method and Trace JIT. */
    1573         1995868 :     if (interpMode == JSINTERP_NORMAL) {
    1574         1981439 :         StackFrame *fp = regs.fp();
    1575         1981439 :         JS_ASSERT_IF(!fp->isGeneratorFrame(), regs.pc == script->code);
    1576         1981439 :         if (!ScriptPrologueOrGeneratorResume(cx, fp, UseNewTypeAtEntry(cx, fp)))
    1577               0 :             goto error;
    1578         1981439 :         if (cx->compartment->debugMode()) {
    1579          645091 :             JSTrapStatus status = ScriptDebugPrologue(cx, fp);
    1580          645091 :             switch (status) {
    1581                 :               case JSTRAP_CONTINUE:
    1582                 :                 break;
    1583                 :               case JSTRAP_RETURN:
    1584              10 :                 interpReturnOK = true;
    1585              10 :                 goto forced_return;
    1586                 :               case JSTRAP_THROW:
    1587                 :               case JSTRAP_ERROR:
    1588             396 :                 goto error;
    1589                 :               default:
    1590               0 :                 JS_NOT_REACHED("bad ScriptDebugPrologue status");
    1591                 :             }
    1592                 :         }
    1593                 :     }
    1594                 : 
    1595                 :     /* The REJOIN mode acts like the normal mode, except the prologue is skipped. */
    1596         1995462 :     if (interpMode == JSINTERP_REJOIN)
    1597           14423 :         interpMode = JSINTERP_NORMAL;
    1598                 : 
    1599         1995462 :     CHECK_INTERRUPT_HANDLER();
    1600                 : 
    1601         1995462 :     RESET_USE_METHODJIT();
    1602                 : 
    1603                 :     /*
    1604                 :      * It is important that "op" be initialized before calling DO_OP because
    1605                 :      * it is possible for "op" to be specially assigned during the normal
    1606                 :      * processing of an opcode while looping. We rely on DO_NEXT_OP to manage
    1607                 :      * "op" correctly in all other cases.
    1608                 :      */
    1609                 :     JSOp op;
    1610                 :     int32_t len;
    1611         1995462 :     len = 0;
    1612                 : 
    1613                 :     /* Check for too deep of a native thread stack. */
    1614         1995462 :     JS_CHECK_RECURSION(cx, goto error);
    1615                 : 
    1616         1995396 :     DO_NEXT_OP(len);
    1617                 : 
    1618                 : #if JS_THREADED_INTERP
    1619                 :     /*
    1620                 :      * This is a loop, but it does not look like a loop. The loop-closing
    1621                 :      * jump is distributed throughout goto *jumpTable[op] inside of DO_OP.
    1622                 :      * When interrupts are enabled, jumpTable is set to interruptJumpTable
    1623                 :      * where all jumps point to the interrupt label. The latter, after
    1624                 :      * calling the interrupt handler, dispatches through normalJumpTable to
    1625                 :      * continue the normal bytecode processing.
    1626                 :      */
    1627                 : 
    1628                 : #else /* !JS_THREADED_INTERP */
    1629                 :     for (;;) {
    1630                 :       advance_pc_by_one:
    1631                 :         JS_ASSERT(js_CodeSpec[op].length == 1);
    1632                 :         len = 1;
    1633                 :       advance_pc:
    1634                 :         regs.pc += len;
    1635                 :         op = (JSOp) *regs.pc;
    1636                 : 
    1637                 :       do_op:
    1638                 :         CHECK_PCCOUNT_INTERRUPTS();
    1639                 :         js::gc::MaybeVerifyBarriers(cx);
    1640                 :         switchOp = int(op) | switchMask;
    1641                 :       do_switch:
    1642                 :         switch (switchOp) {
    1643                 : #endif
    1644                 : 
    1645                 : #if JS_THREADED_INTERP
    1646                 :   interrupt:
    1647                 : #else /* !JS_THREADED_INTERP */
    1648                 :   case -1:
    1649                 :     JS_ASSERT(switchMask == -1);
    1650                 : #endif /* !JS_THREADED_INTERP */
    1651                 :     {
    1652           18252 :         bool moreInterrupts = false;
    1653                 : 
    1654           18252 :         if (cx->runtime->profilingScripts) {
    1655               0 :             if (!script->pcCounters)
    1656               0 :                 script->initCounts(cx);
    1657               0 :             moreInterrupts = true;
    1658                 :         }
    1659                 : 
    1660           18252 :         if (script->pcCounters) {
    1661               0 :             OpcodeCounts counts = script->getCounts(regs.pc);
    1662               0 :             counts.get(OpcodeCounts::BASE_INTERP)++;
    1663               0 :             moreInterrupts = true;
    1664                 :         }
    1665                 : 
    1666           18252 :         JSInterruptHook hook = cx->runtime->debugHooks.interruptHook;
    1667           18252 :         if (hook || script->stepModeEnabled()) {
    1668                 :             Value rval;
    1669            5486 :             JSTrapStatus status = JSTRAP_CONTINUE;
    1670            5486 :             if (hook)
    1671              16 :                 status = hook(cx, script, regs.pc, &rval, cx->runtime->debugHooks.interruptHookData);
    1672            5486 :             if (status == JSTRAP_CONTINUE && script->stepModeEnabled())
    1673            5486 :                 status = Debugger::onSingleStep(cx, &rval);
    1674            5486 :             switch (status) {
    1675                 :               case JSTRAP_ERROR:
    1676              18 :                 goto error;
    1677                 :               case JSTRAP_CONTINUE:
    1678            5450 :                 break;
    1679                 :               case JSTRAP_RETURN:
    1680               9 :                 regs.fp()->setReturnValue(rval);
    1681               9 :                 interpReturnOK = true;
    1682               9 :                 goto forced_return;
    1683                 :               case JSTRAP_THROW:
    1684               9 :                 cx->setPendingException(rval);
    1685               9 :                 goto error;
    1686                 :               default:;
    1687                 :             }
    1688            5450 :             moreInterrupts = true;
    1689                 :         }
    1690                 : 
    1691           18216 :         if (script->hasAnyBreakpointsOrStepMode())
    1692           17780 :             moreInterrupts = true;
    1693                 : 
    1694           18216 :         if (script->hasBreakpointsAt(regs.pc) && interpMode != JSINTERP_SKIP_TRAP) {
    1695                 :             Value rval;
    1696             982 :             JSTrapStatus status = Debugger::onTrap(cx, &rval);
    1697             982 :             switch (status) {
    1698                 :               case JSTRAP_ERROR:
    1699               5 :                 goto error;
    1700                 :               case JSTRAP_RETURN:
    1701              30 :                 regs.fp()->setReturnValue(rval);
    1702              30 :                 interpReturnOK = true;
    1703              30 :                 goto forced_return;
    1704                 :               case JSTRAP_THROW:
    1705               9 :                 cx->setPendingException(rval);
    1706               9 :                 goto error;
    1707                 :               default:
    1708                 :                 break;
    1709                 :             }
    1710             938 :             JS_ASSERT(status == JSTRAP_CONTINUE);
    1711             938 :             CHECK_INTERRUPT_HANDLER();
    1712             938 :             JS_ASSERT(rval.isInt32() && rval.toInt32() == op);
    1713                 :         }
    1714                 : 
    1715           18172 :         interpMode = JSINTERP_NORMAL;
    1716                 : 
    1717                 : #if JS_THREADED_INTERP
    1718           18172 :         jumpTable = moreInterrupts ? interruptJumpTable : normalJumpTable;
    1719           18172 :         JS_EXTENSION_(goto *normalJumpTable[op]);
    1720                 : #else
    1721                 :         switchMask = moreInterrupts ? -1 : 0;
    1722                 :         switchOp = int(op);
    1723                 :         goto do_switch;
    1724                 : #endif
    1725                 :     }
    1726                 : 
    1727                 : /* No-ops for ease of decompilation. */
    1728          407106 : ADD_EMPTY_CASE(JSOP_NOP)
    1729               0 : ADD_EMPTY_CASE(JSOP_UNUSED0)
    1730               0 : ADD_EMPTY_CASE(JSOP_UNUSED1)
    1731               0 : ADD_EMPTY_CASE(JSOP_UNUSED2)
    1732               0 : ADD_EMPTY_CASE(JSOP_UNUSED3)
    1733               0 : ADD_EMPTY_CASE(JSOP_UNUSED4)
    1734               0 : ADD_EMPTY_CASE(JSOP_UNUSED5)
    1735               0 : ADD_EMPTY_CASE(JSOP_UNUSED6)
    1736               0 : ADD_EMPTY_CASE(JSOP_UNUSED7)
    1737               0 : ADD_EMPTY_CASE(JSOP_UNUSED8)
    1738               0 : ADD_EMPTY_CASE(JSOP_UNUSED9)
    1739               0 : ADD_EMPTY_CASE(JSOP_UNUSED10)
    1740               0 : ADD_EMPTY_CASE(JSOP_UNUSED11)
    1741               0 : ADD_EMPTY_CASE(JSOP_UNUSED12)
    1742               0 : ADD_EMPTY_CASE(JSOP_UNUSED13)
    1743               0 : ADD_EMPTY_CASE(JSOP_UNUSED14)
    1744               0 : ADD_EMPTY_CASE(JSOP_UNUSED15)
    1745               0 : ADD_EMPTY_CASE(JSOP_UNUSED16)
    1746               0 : ADD_EMPTY_CASE(JSOP_UNUSED17)
    1747               0 : ADD_EMPTY_CASE(JSOP_UNUSED18)
    1748               0 : ADD_EMPTY_CASE(JSOP_UNUSED19)
    1749               0 : ADD_EMPTY_CASE(JSOP_UNUSED20)
    1750               0 : ADD_EMPTY_CASE(JSOP_UNUSED21)
    1751               0 : ADD_EMPTY_CASE(JSOP_UNUSED22)
    1752               0 : ADD_EMPTY_CASE(JSOP_UNUSED23)
    1753         1024558 : ADD_EMPTY_CASE(JSOP_CONDSWITCH)
    1754          685558 : ADD_EMPTY_CASE(JSOP_TRY)
    1755                 : #if JS_HAS_XML_SUPPORT
    1756             623 : ADD_EMPTY_CASE(JSOP_STARTXML)
    1757               0 : ADD_EMPTY_CASE(JSOP_STARTXMLEXPR)
    1758                 : #endif
    1759       117595395 : ADD_EMPTY_CASE(JSOP_LOOPHEAD)
    1760       119972329 : ADD_EMPTY_CASE(JSOP_LOOPENTRY)
    1761                 : END_EMPTY_CASES
    1762                 : 
    1763                 : BEGIN_CASE(JSOP_LABEL)
    1764             427 : END_CASE(JSOP_LABEL)
    1765                 : 
    1766                 : check_backedge:
    1767                 : {
    1768       117608115 :     CHECK_BRANCH();
    1769       117608115 :     if (op != JSOP_LOOPHEAD)
    1770            1056 :         DO_OP();
    1771                 : 
    1772                 : #ifdef JS_METHODJIT
    1773       117607059 :     if (!useMethodJIT)
    1774       116911023 :         DO_OP();
    1775                 :     mjit::CompileStatus status =
    1776          696036 :         mjit::CanMethodJIT(cx, script, regs.pc, regs.fp()->isConstructing(),
    1777          696036 :                            mjit::CompileRequest_Interpreter);
    1778          696036 :     if (status == mjit::Compile_Error)
    1779               0 :         goto error;
    1780          696036 :     if (status == mjit::Compile_Okay) {
    1781                 :         void *ncode =
    1782           33590 :             script->nativeCodeForPC(regs.fp()->isConstructing(), regs.pc);
    1783           33590 :         JS_ASSERT(ncode);
    1784           33590 :         mjit::JaegerStatus status = mjit::JaegerShotAtSafePoint(cx, ncode, true);
    1785           33590 :         if (status == mjit::Jaeger_ThrowBeforeEnter)
    1786               0 :             goto error;
    1787           33590 :         CHECK_PARTIAL_METHODJIT(status);
    1788           11117 :         interpReturnOK = (status == mjit::Jaeger_Returned);
    1789           11117 :         if (entryFrame != regs.fp())
    1790           10233 :             goto jit_return;
    1791             884 :         regs.fp()->setFinishedInInterpreter();
    1792             884 :         goto leave_on_safe_point;
    1793                 :     }
    1794          662446 :     if (status == mjit::Compile_Abort)
    1795          167624 :         useMethodJIT = false;
    1796                 : #endif /* JS_METHODJIT */
    1797                 : 
    1798          662446 :     DO_OP();
    1799                 : }
    1800                 : 
    1801                 : /* ADD_EMPTY_CASE is not used here as JSOP_LINENO_LENGTH == 3. */
    1802                 : BEGIN_CASE(JSOP_LINENO)
    1803           22061 : END_CASE(JSOP_LINENO)
    1804                 : 
    1805                 : BEGIN_CASE(JSOP_UNDEFINED)
    1806        10455985 :     PUSH_UNDEFINED();
    1807        10455985 : END_CASE(JSOP_UNDEFINED)
    1808                 : 
    1809                 : BEGIN_CASE(JSOP_POP)
    1810       296333221 :     regs.sp--;
    1811       296333221 : END_CASE(JSOP_POP)
    1812                 : 
    1813                 : BEGIN_CASE(JSOP_POPN)
    1814                 : {
    1815           96783 :     regs.sp -= GET_UINT16(regs.pc);
    1816                 : #ifdef DEBUG
    1817           96783 :     JS_ASSERT(regs.fp()->base() <= regs.sp);
    1818           96783 :     StaticBlockObject *block = regs.fp()->maybeBlockChain();
    1819            7148 :     JS_ASSERT_IF(block,
    1820                 :                  block->stackDepth() + block->slotCount()
    1821          103931 :                  <= (size_t) (regs.sp - regs.fp()->base()));
    1822          202443 :     for (JSObject *obj = &regs.fp()->scopeChain(); obj; obj = obj->enclosingScope()) {
    1823          105660 :         if (!obj->isBlock() || !obj->isWith())
    1824          105660 :             continue;
    1825               0 :         if (obj->getPrivate() != js_FloatingFrameIfGenerator(cx, regs.fp()))
    1826               0 :             break;
    1827               0 :         JS_ASSERT(regs.fp()->base() + obj->asBlock().stackDepth()
    1828                 :                   + (obj->isBlock() ? obj->asBlock().slotCount() : 1)
    1829               0 :                   <= regs.sp);
    1830                 :     }
    1831                 : #endif
    1832                 : }
    1833           96783 : END_CASE(JSOP_POPN)
    1834                 : 
    1835                 : BEGIN_CASE(JSOP_SETRVAL)
    1836                 : BEGIN_CASE(JSOP_POPV)
    1837          767278 :     POP_RETURN_VALUE();
    1838          767278 : END_CASE(JSOP_POPV)
    1839                 : 
    1840                 : BEGIN_CASE(JSOP_ENTERWITH)
    1841            1737 :     if (!EnterWith(cx, -1))
    1842               9 :         goto error;
    1843                 : 
    1844                 :     /*
    1845                 :      * We must ensure that different "with" blocks have different stack depth
    1846                 :      * associated with them. This allows the try handler search to properly
    1847                 :      * recover the scope chain. Thus we must keep the stack at least at the
    1848                 :      * current level.
    1849                 :      *
    1850                 :      * We set sp[-1] to the current "with" object to help asserting the
    1851                 :      * enter/leave balance in [leavewith].
    1852                 :      */
    1853            1728 :     regs.sp[-1].setObject(regs.fp()->scopeChain());
    1854            1728 : END_CASE(JSOP_ENTERWITH)
    1855                 : 
    1856                 : BEGIN_CASE(JSOP_LEAVEWITH)
    1857            1710 :     JS_ASSERT(regs.sp[-1].toObject() == regs.fp()->scopeChain());
    1858            1710 :     regs.sp--;
    1859            1710 :     LeaveWith(cx);
    1860            1710 : END_CASE(JSOP_LEAVEWITH)
    1861                 : 
    1862                 : BEGIN_CASE(JSOP_RETURN)
    1863         7675969 :     POP_RETURN_VALUE();
    1864                 :     /* FALL THROUGH */
    1865                 : 
    1866                 : BEGIN_CASE(JSOP_RETRVAL)    /* fp return value already set */
    1867                 : BEGIN_CASE(JSOP_STOP)
    1868                 : {
    1869                 :     /*
    1870                 :      * When the inlined frame exits with an exception or an error, ok will be
    1871                 :      * false after the inline_return label.
    1872                 :      */
    1873        11836896 :     CHECK_BRANCH();
    1874                 : 
    1875        11836896 :     interpReturnOK = true;
    1876        11836896 :     if (entryFrame != regs.fp())
    1877                 :   inline_return:
    1878                 :     {
    1879        11967662 :         JS_ASSERT(!regs.fp()->hasBlockChain());
    1880        11967662 :         JS_ASSERT(!IsActiveWithOrBlock(cx, regs.fp()->scopeChain(), 0));
    1881                 : 
    1882        11967662 :         if (cx->compartment->debugMode())
    1883         1676209 :             interpReturnOK = ScriptDebugEpilogue(cx, regs.fp(), interpReturnOK);
    1884                 :  
    1885        11967662 :         interpReturnOK = ScriptEpilogue(cx, regs.fp(), interpReturnOK);
    1886                 : 
    1887                 :         /* The JIT inlines ScriptEpilogue. */
    1888                 : #ifdef JS_METHODJIT
    1889                 :   jit_return:
    1890                 : #endif
    1891                 : 
    1892                 :         /* The results of lowered call/apply frames need to be shifted. */
    1893        12685530 :         bool shiftResult = regs.fp()->loweredCallOrApply();
    1894                 : 
    1895        12685530 :         cx->stack.popInlineFrame(regs);
    1896                 : 
    1897        12685530 :         RESTORE_INTERP_VARS();
    1898                 : 
    1899               0 :         JS_ASSERT(*regs.pc == JSOP_NEW || *regs.pc == JSOP_CALL ||
    1900        12685530 :                   *regs.pc == JSOP_FUNCALL || *regs.pc == JSOP_FUNAPPLY);
    1901                 : 
    1902                 :         /* Resume execution in the calling frame. */
    1903        12685530 :         RESET_USE_METHODJIT();
    1904        12685530 :         if (JS_LIKELY(interpReturnOK)) {
    1905        10679348 :             TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
    1906                 : 
    1907        10679348 :             if (shiftResult) {
    1908             161 :                 regs.sp[-2] = regs.sp[-1];
    1909             161 :                 regs.sp--;
    1910                 :             }
    1911                 : 
    1912        10679348 :             len = JSOP_CALL_LENGTH;
    1913        10679348 :             DO_NEXT_OP(len);
    1914                 :         }
    1915                 : 
    1916                 :         /* Increment pc so that |sp - fp->slots == ReconstructStackDepth(pc)|. */
    1917         2006182 :         regs.pc += JSOP_CALL_LENGTH;
    1918         2006182 :         goto error;
    1919                 :     } else {
    1920         1883390 :         JS_ASSERT(regs.sp == regs.fp()->base());
    1921                 :     }
    1922         1883390 :     interpReturnOK = true;
    1923         1883390 :     goto exit;
    1924                 : }
    1925                 : 
    1926                 : BEGIN_CASE(JSOP_DEFAULT)
    1927             751 :     regs.sp--;
    1928                 :     /* FALL THROUGH */
    1929                 : BEGIN_CASE(JSOP_GOTO)
    1930                 : {
    1931         6603743 :     len = GET_JUMP_OFFSET(regs.pc);
    1932         6603743 :     BRANCH(len);
    1933                 : }
    1934                 : END_CASE(JSOP_GOTO)
    1935                 : 
    1936                 : BEGIN_CASE(JSOP_IFEQ)
    1937                 : {
    1938                 :     bool cond;
    1939                 :     Value *_;
    1940         9296953 :     POP_BOOLEAN(cx, _, cond);
    1941         9296953 :     if (cond == false) {
    1942         6162076 :         len = GET_JUMP_OFFSET(regs.pc);
    1943         6162076 :         BRANCH(len);
    1944                 :     }
    1945                 : }
    1946         3134877 : END_CASE(JSOP_IFEQ)
    1947                 : 
    1948                 : BEGIN_CASE(JSOP_IFNE)
    1949                 : {
    1950                 :     bool cond;
    1951                 :     Value *_;
    1952         6948165 :     POP_BOOLEAN(cx, _, cond);
    1953         6948165 :     if (cond != false) {
    1954         6557908 :         len = GET_JUMP_OFFSET(regs.pc);
    1955         6557908 :         BRANCH(len);
    1956                 :     }
    1957                 : }
    1958          390257 : END_CASE(JSOP_IFNE)
    1959                 : 
    1960                 : BEGIN_CASE(JSOP_OR)
    1961                 : {
    1962                 :     bool cond;
    1963                 :     Value *_;
    1964         1228170 :     VALUE_TO_BOOLEAN(cx, _, cond);
    1965         1228170 :     if (cond == true) {
    1966          193779 :         len = GET_JUMP_OFFSET(regs.pc);
    1967          193779 :         DO_NEXT_OP(len);
    1968                 :     }
    1969                 : }
    1970         1034391 : END_CASE(JSOP_OR)
    1971                 : 
    1972                 : BEGIN_CASE(JSOP_AND)
    1973                 : {
    1974                 :     bool cond;
    1975                 :     Value *_;
    1976          664255 :     VALUE_TO_BOOLEAN(cx, _, cond);
    1977          664255 :     if (cond == false) {
    1978          270599 :         len = GET_JUMP_OFFSET(regs.pc);
    1979          270599 :         DO_NEXT_OP(len);
    1980                 :     }
    1981                 : }
    1982          393656 : END_CASE(JSOP_AND)
    1983                 : 
    1984                 : /*
    1985                 :  * If the index value at sp[n] is not an int that fits in a jsval, it could
    1986                 :  * be an object (an XML QName, AttributeName, or AnyName), but only if we are
    1987                 :  * compiling with JS_HAS_XML_SUPPORT.  Otherwise convert the index value to a
    1988                 :  * string atom id.
    1989                 :  */
    1990                 : #define FETCH_ELEMENT_ID(obj, n, id)                                          \
    1991                 :     JS_BEGIN_MACRO                                                            \
    1992                 :         const Value &idval_ = regs.sp[n];                                     \
    1993                 :         int32_t i_;                                                           \
    1994                 :         if (ValueFitsInInt32(idval_, &i_) && INT_FITS_IN_JSID(i_)) {          \
    1995                 :             id = INT_TO_JSID(i_);                                             \
    1996                 :         } else {                                                              \
    1997                 :             if (!js_InternNonIntElementId(cx, obj, idval_, &id, &regs.sp[n])) \
    1998                 :                 goto error;                                                   \
    1999                 :         }                                                                     \
    2000                 :     JS_END_MACRO
    2001                 : 
    2002                 : #define TRY_BRANCH_AFTER_COND(cond,spdec)                                     \
    2003                 :     JS_BEGIN_MACRO                                                            \
    2004                 :         JS_ASSERT(js_CodeSpec[op].length == 1);                               \
    2005                 :         unsigned diff_ = (unsigned) GET_UINT8(regs.pc) - (unsigned) JSOP_IFEQ;         \
    2006                 :         if (diff_ <= 1) {                                                     \
    2007                 :             regs.sp -= spdec;                                                 \
    2008                 :             if (cond == (diff_ != 0)) {                                       \
    2009                 :                 ++regs.pc;                                                    \
    2010                 :                 len = GET_JUMP_OFFSET(regs.pc);                               \
    2011                 :                 BRANCH(len);                                                  \
    2012                 :             }                                                                 \
    2013                 :             len = 1 + JSOP_IFEQ_LENGTH;                                       \
    2014                 :             DO_NEXT_OP(len);                                                  \
    2015                 :         }                                                                     \
    2016                 :     JS_END_MACRO
    2017                 : 
    2018                 : BEGIN_CASE(JSOP_IN)
    2019                 : {
    2020          430322 :     const Value &rref = regs.sp[-1];
    2021          430322 :     if (!rref.isObject()) {
    2022              11 :         js_ReportValueError(cx, JSMSG_IN_NOT_OBJECT, -1, rref, NULL);
    2023              11 :         goto error;
    2024                 :     }
    2025          430311 :     JSObject *obj = &rref.toObject();
    2026                 :     jsid id;
    2027          430311 :     FETCH_ELEMENT_ID(obj, -2, id);
    2028                 :     JSObject *obj2;
    2029                 :     JSProperty *prop;
    2030          430311 :     if (!obj->lookupGeneric(cx, id, &obj2, &prop))
    2031               0 :         goto error;
    2032          430311 :     bool cond = prop != NULL;
    2033          430311 :     TRY_BRANCH_AFTER_COND(cond, 2);
    2034          213016 :     regs.sp--;
    2035          213016 :     regs.sp[-1].setBoolean(cond);
    2036                 : }
    2037          213016 : END_CASE(JSOP_IN)
    2038                 : 
    2039                 : BEGIN_CASE(JSOP_ITER)
    2040                 : {
    2041          327916 :     JS_ASSERT(regs.sp > regs.fp()->base());
    2042          327916 :     uint8_t flags = GET_UINT8(regs.pc);
    2043          327916 :     if (!ValueToIterator(cx, flags, &regs.sp[-1]))
    2044             150 :         goto error;
    2045          327766 :     CHECK_INTERRUPT_HANDLER();
    2046          327766 :     JS_ASSERT(!regs.sp[-1].isPrimitive());
    2047                 : }
    2048          327766 : END_CASE(JSOP_ITER)
    2049                 : 
    2050                 : BEGIN_CASE(JSOP_MOREITER)
    2051                 : {
    2052         4605547 :     JS_ASSERT(regs.sp - 1 >= regs.fp()->base());
    2053         4605547 :     JS_ASSERT(regs.sp[-1].isObject());
    2054         4605547 :     PUSH_NULL();
    2055                 :     bool cond;
    2056         4605547 :     if (!IteratorMore(cx, &regs.sp[-2].toObject(), &cond, &regs.sp[-1]))
    2057              20 :         goto error;
    2058         4605527 :     CHECK_INTERRUPT_HANDLER();
    2059         4605527 :     regs.sp[-1].setBoolean(cond);
    2060                 : }
    2061         4605527 : END_CASE(JSOP_MOREITER)
    2062                 : 
    2063                 : BEGIN_CASE(JSOP_ITERNEXT)
    2064                 : {
    2065         4412591 :     Value *itervp = regs.sp - GET_INT8(regs.pc);
    2066         4412591 :     JS_ASSERT(itervp >= regs.fp()->base());
    2067         4412591 :     JS_ASSERT(itervp->isObject());
    2068         4412591 :     PUSH_NULL();
    2069         4412591 :     if (!IteratorNext(cx, &itervp->toObject(), &regs.sp[-1]))
    2070               0 :         goto error;
    2071                 : }
    2072         4412591 : END_CASE(JSOP_ITERNEXT)
    2073                 : 
    2074                 : BEGIN_CASE(JSOP_ENDITER)
    2075                 : {
    2076          328303 :     JS_ASSERT(regs.sp - 1 >= regs.fp()->base());
    2077          328303 :     bool ok = CloseIterator(cx, &regs.sp[-1].toObject());
    2078          328303 :     regs.sp--;
    2079          328303 :     if (!ok)
    2080               0 :         goto error;
    2081                 : }
    2082          328303 : END_CASE(JSOP_ENDITER)
    2083                 : 
    2084                 : BEGIN_CASE(JSOP_DUP)
    2085                 : {
    2086        20737177 :     JS_ASSERT(regs.sp > regs.fp()->base());
    2087        20737177 :     const Value &rref = regs.sp[-1];
    2088        20737177 :     PUSH_COPY(rref);
    2089                 : }
    2090        20737177 : END_CASE(JSOP_DUP)
    2091                 : 
    2092                 : BEGIN_CASE(JSOP_DUP2)
    2093                 : {
    2094         7847273 :     JS_ASSERT(regs.sp - 2 >= regs.fp()->base());
    2095         7847273 :     const Value &lref = regs.sp[-2];
    2096         7847273 :     const Value &rref = regs.sp[-1];
    2097         7847273 :     PUSH_COPY(lref);
    2098         7847273 :     PUSH_COPY(rref);
    2099                 : }
    2100         7847273 : END_CASE(JSOP_DUP2)
    2101                 : 
    2102                 : BEGIN_CASE(JSOP_SWAP)
    2103                 : {
    2104        13149938 :     JS_ASSERT(regs.sp - 2 >= regs.fp()->base());
    2105        13149938 :     Value &lref = regs.sp[-2];
    2106        13149938 :     Value &rref = regs.sp[-1];
    2107        13149938 :     lref.swap(rref);
    2108                 : }
    2109        13149938 : END_CASE(JSOP_SWAP)
    2110                 : 
    2111                 : BEGIN_CASE(JSOP_PICK)
    2112                 : {
    2113        20717506 :     unsigned i = GET_UINT8(regs.pc);
    2114        20717506 :     JS_ASSERT(regs.sp - (i + 1) >= regs.fp()->base());
    2115        20717506 :     Value lval = regs.sp[-int(i + 1)];
    2116        20717506 :     memmove(regs.sp - (i + 1), regs.sp - i, sizeof(Value) * i);
    2117        20717506 :     regs.sp[-1] = lval;
    2118                 : }
    2119        20717506 : END_CASE(JSOP_PICK)
    2120                 : 
    2121                 : BEGIN_CASE(JSOP_SETCONST)
    2122                 : {
    2123                 :     PropertyName *name;
    2124          166662 :     LOAD_NAME(0, name);
    2125          166662 :     JSObject &obj = regs.fp()->varObj();
    2126          166662 :     const Value &ref = regs.sp[-1];
    2127          166662 :     if (!obj.defineProperty(cx, name, ref,
    2128                 :                             JS_PropertyStub, JS_StrictPropertyStub,
    2129          166662 :                             JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY)) {
    2130               0 :         goto error;
    2131                 :     }
    2132                 : }
    2133          166662 : END_CASE(JSOP_SETCONST);
    2134                 : 
    2135                 : #if JS_HAS_DESTRUCTURING
    2136                 : BEGIN_CASE(JSOP_ENUMCONSTELEM)
    2137                 : {
    2138               4 :     const Value &ref = regs.sp[-3];
    2139                 :     JSObject *obj;
    2140               4 :     FETCH_OBJECT(cx, -2, obj);
    2141                 :     jsid id;
    2142               4 :     FETCH_ELEMENT_ID(obj, -1, id);
    2143               4 :     if (!obj->defineGeneric(cx, id, ref,
    2144                 :                             JS_PropertyStub, JS_StrictPropertyStub,
    2145               4 :                             JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY)) {
    2146               0 :         goto error;
    2147                 :     }
    2148               4 :     regs.sp -= 3;
    2149                 : }
    2150               4 : END_CASE(JSOP_ENUMCONSTELEM)
    2151                 : #endif
    2152                 : 
    2153                 : BEGIN_CASE(JSOP_BINDGNAME)
    2154        11706634 :     PUSH_OBJECT(regs.fp()->scopeChain().global());
    2155        11706634 : END_CASE(JSOP_BINDGNAME)
    2156                 : 
    2157                 : BEGIN_CASE(JSOP_BINDNAME)
    2158                 : {
    2159                 :     JSObject *obj;
    2160                 :     do {
    2161                 :         /*
    2162                 :          * We can skip the property lookup for the global object. If the
    2163                 :          * property does not exist anywhere on the scope chain, JSOP_SETNAME
    2164                 :          * adds the property to the global.
    2165                 :          *
    2166                 :          * As a consequence of this optimization for the global object we run
    2167                 :          * its JSRESOLVE_ASSIGNING-tolerant resolve hooks only in JSOP_SETNAME,
    2168                 :          * after the interpreter evaluates the right- hand-side of the
    2169                 :          * assignment, and not here.
    2170                 :          *
    2171                 :          * This should be transparent to the hooks because the script, instead
    2172                 :          * of name = rhs, could have used global.name = rhs given a global
    2173                 :          * object reference, which also calls the hooks only after evaluating
    2174                 :          * the rhs. We desire such resolve hook equivalence between the two
    2175                 :          * forms.
    2176                 :          */
    2177          237796 :         obj = &regs.fp()->scopeChain();
    2178          237796 :         if (obj->isGlobal())
    2179          182895 :             break;
    2180                 : 
    2181                 :         PropertyName *name;
    2182           54901 :         LOAD_NAME(0, name);
    2183                 : 
    2184           54901 :         obj = FindIdentifierBase(cx, &regs.fp()->scopeChain(), name);
    2185           54901 :         if (!obj)
    2186               0 :             goto error;
    2187                 :     } while (0);
    2188          237796 :     PUSH_OBJECT(*obj);
    2189                 : }
    2190          237796 : END_CASE(JSOP_BINDNAME)
    2191                 : 
    2192                 : #define BITWISE_OP(OP)                                                        \
    2193                 :     JS_BEGIN_MACRO                                                            \
    2194                 :         int32_t i, j;                                                         \
    2195                 :         if (!ToInt32(cx, regs.sp[-2], &i))                                    \
    2196                 :             goto error;                                                       \
    2197                 :         if (!ToInt32(cx, regs.sp[-1], &j))                                    \
    2198                 :             goto error;                                                       \
    2199                 :         i = i OP j;                                                           \
    2200                 :         regs.sp--;                                                            \
    2201                 :         regs.sp[-1].setInt32(i);                                              \
    2202                 :     JS_END_MACRO
    2203                 : 
    2204                 : BEGIN_CASE(JSOP_BITOR)
    2205          622252 :     BITWISE_OP(|);
    2206          622246 : END_CASE(JSOP_BITOR)
    2207                 : 
    2208                 : BEGIN_CASE(JSOP_BITXOR)
    2209          629123 :     BITWISE_OP(^);
    2210          629123 : END_CASE(JSOP_BITXOR)
    2211                 : 
    2212                 : BEGIN_CASE(JSOP_BITAND)
    2213        20947079 :     BITWISE_OP(&);
    2214        20947079 : END_CASE(JSOP_BITAND)
    2215                 : 
    2216                 : #undef BITWISE_OP
    2217                 : 
    2218                 : #define EQUALITY_OP(OP)                                                       \
    2219                 :     JS_BEGIN_MACRO                                                            \
    2220                 :         Value rval = regs.sp[-1];                                             \
    2221                 :         Value lval = regs.sp[-2];                                             \
    2222                 :         bool cond;                                                            \
    2223                 :         if (!LooselyEqual(cx, lval, rval, &cond))                             \
    2224                 :             goto error;                                                       \
    2225                 :         cond = cond OP JS_TRUE;                                               \
    2226                 :         TRY_BRANCH_AFTER_COND(cond, 2);                                       \
    2227                 :         regs.sp--;                                                            \
    2228                 :         regs.sp[-1].setBoolean(cond);                                         \
    2229                 :     JS_END_MACRO
    2230                 : 
    2231                 : BEGIN_CASE(JSOP_EQ)
    2232         4483852 :     EQUALITY_OP(==);
    2233          834215 : END_CASE(JSOP_EQ)
    2234                 : 
    2235                 : BEGIN_CASE(JSOP_NE)
    2236          738962 :     EQUALITY_OP(!=);
    2237          151485 : END_CASE(JSOP_NE)
    2238                 : 
    2239                 : #undef EQUALITY_OP
    2240                 : 
    2241                 : #define STRICT_EQUALITY_OP(OP, COND)                                          \
    2242                 :     JS_BEGIN_MACRO                                                            \
    2243                 :         const Value &rref = regs.sp[-1];                                      \
    2244                 :         const Value &lref = regs.sp[-2];                                      \
    2245                 :         bool equal;                                                           \
    2246                 :         if (!StrictlyEqual(cx, lref, rref, &equal))                           \
    2247                 :             goto error;                                                       \
    2248                 :         COND = equal OP JS_TRUE;                                              \
    2249                 :         regs.sp--;                                                            \
    2250                 :     JS_END_MACRO
    2251                 : 
    2252                 : BEGIN_CASE(JSOP_STRICTEQ)
    2253                 : {
    2254                 :     bool cond;
    2255         2020037 :     STRICT_EQUALITY_OP(==, cond);
    2256         2020037 :     regs.sp[-1].setBoolean(cond);
    2257                 : }
    2258         2020037 : END_CASE(JSOP_STRICTEQ)
    2259                 : 
    2260                 : BEGIN_CASE(JSOP_STRICTNE)
    2261                 : {
    2262                 :     bool cond;
    2263          907485 :     STRICT_EQUALITY_OP(!=, cond);
    2264          907485 :     regs.sp[-1].setBoolean(cond);
    2265                 : }
    2266          907485 : END_CASE(JSOP_STRICTNE)
    2267                 : 
    2268                 : BEGIN_CASE(JSOP_CASE)
    2269                 : {
    2270                 :     bool cond;
    2271         1049756 :     STRICT_EQUALITY_OP(==, cond);
    2272         1049756 :     if (cond) {
    2273         1023835 :         regs.sp--;
    2274         1023835 :         len = GET_JUMP_OFFSET(regs.pc);
    2275         1023835 :         BRANCH(len);
    2276                 :     }
    2277                 : }
    2278           25921 : END_CASE(JSOP_CASE)
    2279                 : 
    2280                 : #undef STRICT_EQUALITY_OP
    2281                 : 
    2282                 : BEGIN_CASE(JSOP_LT)
    2283                 : {
    2284                 :     bool cond;
    2285       107445857 :     const Value &lref = regs.sp[-2];
    2286       107445857 :     const Value &rref = regs.sp[-1];
    2287       107445857 :     if (!LessThanOperation(cx, lref, rref, &cond))
    2288               0 :         goto error;
    2289       107445857 :     TRY_BRANCH_AFTER_COND(cond, 2);
    2290          202991 :     regs.sp[-2].setBoolean(cond);
    2291          202991 :     regs.sp--;
    2292                 : }
    2293          202991 : END_CASE(JSOP_LT)
    2294                 : 
    2295                 : BEGIN_CASE(JSOP_LE)
    2296                 : {
    2297                 :     bool cond;
    2298         1755239 :     const Value &lref = regs.sp[-2];
    2299         1755239 :     const Value &rref = regs.sp[-1];
    2300         1755239 :     if (!LessThanOrEqualOperation(cx, lref, rref, &cond))
    2301               0 :         goto error;
    2302         1755239 :     TRY_BRANCH_AFTER_COND(cond, 2);
    2303           56529 :     regs.sp[-2].setBoolean(cond);
    2304           56529 :     regs.sp--;
    2305                 : }
    2306           56529 : END_CASE(JSOP_LE)
    2307                 : 
    2308                 : BEGIN_CASE(JSOP_GT)
    2309                 : {
    2310                 :     bool cond;
    2311         1718769 :     const Value &lref = regs.sp[-2];
    2312         1718769 :     const Value &rref = regs.sp[-1];
    2313         1718769 :     if (!GreaterThanOperation(cx, lref, rref, &cond))
    2314               7 :         goto error;
    2315         1718762 :     TRY_BRANCH_AFTER_COND(cond, 2);
    2316          100389 :     regs.sp[-2].setBoolean(cond);
    2317          100389 :     regs.sp--;
    2318                 : }
    2319          100389 : END_CASE(JSOP_GT)
    2320                 : 
    2321                 : BEGIN_CASE(JSOP_GE)
    2322                 : {
    2323                 :     bool cond;
    2324         6230031 :     const Value &lref = regs.sp[-2];
    2325         6230031 :     const Value &rref = regs.sp[-1];
    2326         6230031 :     if (!GreaterThanOrEqualOperation(cx, lref, rref, &cond))
    2327               0 :         goto error;
    2328         6230031 :     TRY_BRANCH_AFTER_COND(cond, 2);
    2329           82035 :     regs.sp[-2].setBoolean(cond);
    2330           82035 :     regs.sp--;
    2331                 : }
    2332           82035 : END_CASE(JSOP_GE)
    2333                 : 
    2334                 : #define SIGNED_SHIFT_OP(OP)                                                   \
    2335                 :     JS_BEGIN_MACRO                                                            \
    2336                 :         int32_t i, j;                                                         \
    2337                 :         if (!ToInt32(cx, regs.sp[-2], &i))                                    \
    2338                 :             goto error;                                                       \
    2339                 :         if (!ToInt32(cx, regs.sp[-1], &j))                                    \
    2340                 :             goto error;                                                       \
    2341                 :         i = i OP (j & 31);                                                    \
    2342                 :         regs.sp--;                                                            \
    2343                 :         regs.sp[-1].setInt32(i);                                              \
    2344                 :     JS_END_MACRO
    2345                 : 
    2346                 : BEGIN_CASE(JSOP_LSH)
    2347         8257786 :     SIGNED_SHIFT_OP(<<);
    2348         8257786 : END_CASE(JSOP_LSH)
    2349                 : 
    2350                 : BEGIN_CASE(JSOP_RSH)
    2351        18669800 :     SIGNED_SHIFT_OP(>>);
    2352        18669800 : END_CASE(JSOP_RSH)
    2353                 : 
    2354                 : #undef SIGNED_SHIFT_OP
    2355                 : 
    2356                 : BEGIN_CASE(JSOP_URSH)
    2357                 : {
    2358                 :     uint32_t u;
    2359          140311 :     if (!ToUint32(cx, regs.sp[-2], &u))
    2360               0 :         goto error;
    2361                 :     int32_t j;
    2362          140311 :     if (!ToInt32(cx, regs.sp[-1], &j))
    2363               0 :         goto error;
    2364                 : 
    2365          140311 :     u >>= (j & 31);
    2366                 : 
    2367          140311 :     regs.sp--;
    2368          140311 :     if (!regs.sp[-1].setNumber(uint32_t(u)))
    2369             392 :         TypeScript::MonitorOverflow(cx, script, regs.pc);
    2370                 : }
    2371          140311 : END_CASE(JSOP_URSH)
    2372                 : 
    2373                 : BEGIN_CASE(JSOP_ADD)
    2374                 : {
    2375        58738652 :     Value lval = regs.sp[-2];
    2376        58738652 :     Value rval = regs.sp[-1];
    2377        58738652 :     if (!AddOperation(cx, lval, rval, &regs.sp[-2]))
    2378              40 :         goto error;
    2379        58738612 :     regs.sp--;
    2380                 : }
    2381        58738612 : END_CASE(JSOP_ADD)
    2382                 : 
    2383                 : BEGIN_CASE(JSOP_SUB)
    2384                 : {
    2385         6625315 :     Value lval = regs.sp[-2];
    2386         6625315 :     Value rval = regs.sp[-1];
    2387         6625315 :     if (!SubOperation(cx, lval, rval, &regs.sp[-2]))
    2388               0 :         goto error;
    2389         6625315 :     regs.sp--;
    2390                 : }
    2391         6625315 : END_CASE(JSOP_SUB)
    2392                 : 
    2393                 : BEGIN_CASE(JSOP_MUL)
    2394                 : {
    2395        24962242 :     Value lval = regs.sp[-2];
    2396        24962242 :     Value rval = regs.sp[-1];
    2397        24962242 :     if (!MulOperation(cx, lval, rval, &regs.sp[-2]))
    2398               0 :         goto error;
    2399        24962242 :     regs.sp--;
    2400                 : }
    2401        24962242 : END_CASE(JSOP_MUL)
    2402                 : 
    2403                 : BEGIN_CASE(JSOP_DIV)
    2404                 : {
    2405         1396387 :     Value lval = regs.sp[-2];
    2406         1396387 :     Value rval = regs.sp[-1];
    2407         1396387 :     if (!DivOperation(cx, lval, rval, &regs.sp[-2]))
    2408               0 :         goto error;
    2409         1396387 :     regs.sp--;
    2410                 : }
    2411         1396387 : END_CASE(JSOP_DIV)
    2412                 : 
    2413                 : BEGIN_CASE(JSOP_MOD)
    2414                 : {
    2415          461332 :     Value lval = regs.sp[-2];
    2416          461332 :     Value rval = regs.sp[-1];
    2417          461332 :     if (!ModOperation(cx, lval, rval, &regs.sp[-2]))
    2418               0 :         goto error;
    2419          461332 :     regs.sp--;
    2420                 : }
    2421          461332 : END_CASE(JSOP_MOD)
    2422                 : 
    2423                 : BEGIN_CASE(JSOP_NOT)
    2424                 : {
    2425                 :     Value *_;
    2426                 :     bool cond;
    2427         3974094 :     POP_BOOLEAN(cx, _, cond);
    2428         3974094 :     PUSH_BOOLEAN(!cond);
    2429                 : }
    2430         3974094 : END_CASE(JSOP_NOT)
    2431                 : 
    2432                 : BEGIN_CASE(JSOP_BITNOT)
    2433                 : {
    2434                 :     int32_t i;
    2435          867860 :     if (!ToInt32(cx, regs.sp[-1], &i))
    2436               0 :         goto error;
    2437          867860 :     i = ~i;
    2438          867860 :     regs.sp[-1].setInt32(i);
    2439                 : }
    2440          867860 : END_CASE(JSOP_BITNOT)
    2441                 : 
    2442                 : BEGIN_CASE(JSOP_NEG)
    2443                 : {
    2444                 :     /*
    2445                 :      * When the operand is int jsval, INT32_FITS_IN_JSVAL(i) implies
    2446                 :      * INT32_FITS_IN_JSVAL(-i) unless i is 0 or INT32_MIN when the
    2447                 :      * results, -0.0 or INT32_MAX + 1, are double values.
    2448                 :      */
    2449          745802 :     Value ref = regs.sp[-1];
    2450                 :     int32_t i;
    2451          745802 :     if (ref.isInt32() && (i = ref.toInt32()) != 0 && i != INT32_MIN) {
    2452          268205 :         i = -i;
    2453          268205 :         regs.sp[-1].setInt32(i);
    2454                 :     } else {
    2455                 :         double d;
    2456          477597 :         if (!ToNumber(cx, regs.sp[-1], &d))
    2457               0 :             goto error;
    2458          477597 :         d = -d;
    2459          477597 :         if (!regs.sp[-1].setNumber(d) && !ref.isDouble())
    2460            4139 :             TypeScript::MonitorOverflow(cx, script, regs.pc);
    2461                 :     }
    2462                 : }
    2463          745802 : END_CASE(JSOP_NEG)
    2464                 : 
    2465                 : BEGIN_CASE(JSOP_POS)
    2466        10616611 :     if (!ToNumber(cx, &regs.sp[-1]))
    2467               0 :         goto error;
    2468        10616611 :     if (!regs.sp[-1].isInt32())
    2469            2572 :         TypeScript::MonitorOverflow(cx, script, regs.pc);
    2470        10616611 : END_CASE(JSOP_POS)
    2471                 : 
    2472                 : BEGIN_CASE(JSOP_DELNAME)
    2473                 : {
    2474                 :     PropertyName *name;
    2475             326 :     LOAD_NAME(0, name);
    2476                 :     JSObject *obj, *obj2;
    2477                 :     JSProperty *prop;
    2478             326 :     if (!FindProperty(cx, name, cx->stack.currentScriptedScopeChain(), &obj, &obj2, &prop))
    2479               0 :         goto error;
    2480                 : 
    2481                 :     /* Strict mode code should never contain JSOP_DELNAME opcodes. */
    2482             326 :     JS_ASSERT(!script->strictModeCode);
    2483                 : 
    2484                 :     /* ECMA says to return true if name is undefined or inherited. */
    2485             326 :     PUSH_BOOLEAN(true);
    2486             326 :     if (prop) {
    2487             243 :         if (!obj->deleteProperty(cx, name, &regs.sp[-1], false))
    2488               0 :             goto error;
    2489                 :     }
    2490                 : }
    2491             326 : END_CASE(JSOP_DELNAME)
    2492                 : 
    2493                 : BEGIN_CASE(JSOP_DELPROP)
    2494                 : {
    2495                 :     PropertyName *name;
    2496           26649 :     LOAD_NAME(0, name);
    2497                 : 
    2498                 :     JSObject *obj;
    2499           26649 :     FETCH_OBJECT(cx, -1, obj);
    2500                 : 
    2501                 :     Value rval;
    2502           26649 :     if (!obj->deleteProperty(cx, name, &rval, script->strictModeCode))
    2503               0 :         goto error;
    2504                 : 
    2505           26649 :     regs.sp[-1] = rval;
    2506                 : }
    2507           26649 : END_CASE(JSOP_DELPROP)
    2508                 : 
    2509                 : BEGIN_CASE(JSOP_DELELEM)
    2510                 : {
    2511                 :     /* Fetch the left part and resolve it to a non-null object. */
    2512                 :     JSObject *obj;
    2513           25028 :     FETCH_OBJECT(cx, -2, obj);
    2514                 : 
    2515           25028 :     const Value &propval = regs.sp[-1];
    2516           25028 :     Value &rval = regs.sp[-2];
    2517                 : 
    2518           25028 :     if (!obj->deleteByValue(cx, propval, &rval, script->strictModeCode))
    2519               7 :         goto error;
    2520                 : 
    2521           25021 :     regs.sp--;
    2522                 : }
    2523           25021 : END_CASE(JSOP_DELELEM)
    2524                 : 
    2525                 : BEGIN_CASE(JSOP_TOID)
    2526                 : {
    2527                 :     /*
    2528                 :      * Increment or decrement requires use to lookup the same property twice, but we need to avoid
    2529                 :      * the oberservable stringification the second time.
    2530                 :      * There must be an object value below the id, which will not be popped
    2531                 :      * but is necessary in interning the id for XML.
    2532                 :      */
    2533         6566938 :     Value objval = regs.sp[-2];
    2534         6566938 :     Value idval = regs.sp[-1];
    2535         6566938 :     if (!ToIdOperation(cx, objval, idval, &regs.sp[-1]))
    2536               0 :         goto error;
    2537                 : }
    2538         6566938 : END_CASE(JSOP_TOID)
    2539                 : 
    2540                 : BEGIN_CASE(JSOP_TYPEOFEXPR)
    2541                 : BEGIN_CASE(JSOP_TYPEOF)
    2542                 : {
    2543          209435 :     const Value &ref = regs.sp[-1];
    2544          209435 :     JSType type = JS_TypeOfValue(cx, ref);
    2545          209435 :     regs.sp[-1].setString(rt->atomState.typeAtoms[type]);
    2546                 : }
    2547          209435 : END_CASE(JSOP_TYPEOF)
    2548                 : 
    2549                 : BEGIN_CASE(JSOP_VOID)
    2550            1222 :     regs.sp[-1].setUndefined();
    2551            1222 : END_CASE(JSOP_VOID)
    2552                 : 
    2553                 : BEGIN_CASE(JSOP_INCELEM)
    2554                 : BEGIN_CASE(JSOP_DECELEM)
    2555                 : BEGIN_CASE(JSOP_ELEMINC)
    2556                 : BEGIN_CASE(JSOP_ELEMDEC)
    2557                 :     /* No-op */
    2558         6566938 : END_CASE(JSOP_INCELEM)
    2559                 : 
    2560                 : BEGIN_CASE(JSOP_INCPROP)
    2561                 : BEGIN_CASE(JSOP_DECPROP)
    2562                 : BEGIN_CASE(JSOP_PROPINC)
    2563                 : BEGIN_CASE(JSOP_PROPDEC)
    2564                 : BEGIN_CASE(JSOP_INCNAME)
    2565                 : BEGIN_CASE(JSOP_DECNAME)
    2566                 : BEGIN_CASE(JSOP_NAMEINC)
    2567                 : BEGIN_CASE(JSOP_NAMEDEC)
    2568                 : BEGIN_CASE(JSOP_INCGNAME)
    2569                 : BEGIN_CASE(JSOP_DECGNAME)
    2570                 : BEGIN_CASE(JSOP_GNAMEINC)
    2571                 : BEGIN_CASE(JSOP_GNAMEDEC)
    2572                 :     /* No-op */
    2573         4045610 : END_CASE(JSOP_INCPROP)
    2574                 : 
    2575                 : BEGIN_CASE(JSOP_DECARG)
    2576                 : BEGIN_CASE(JSOP_ARGDEC)
    2577                 : BEGIN_CASE(JSOP_INCARG)
    2578                 : BEGIN_CASE(JSOP_ARGINC)
    2579                 : {
    2580        13820265 :     Value &arg = regs.fp()->formalArg(GET_ARGNO(regs.pc));
    2581        13820265 :     if (!DoIncDec(cx, script, regs.pc, arg, &arg, &regs.sp[0]))
    2582               0 :         goto error;
    2583        13820265 :     regs.sp++;
    2584                 : }
    2585        13820265 : END_CASE(JSOP_ARGINC);
    2586                 : 
    2587                 : BEGIN_CASE(JSOP_DECLOCAL)
    2588                 : BEGIN_CASE(JSOP_LOCALDEC)
    2589                 : BEGIN_CASE(JSOP_INCLOCAL)
    2590                 : BEGIN_CASE(JSOP_LOCALINC)
    2591                 : {
    2592       190505394 :     Value &local = regs.fp()->localSlot(GET_SLOTNO(regs.pc));
    2593       190505394 :     if (!DoIncDec(cx, script, regs.pc, local, &local, &regs.sp[0]))
    2594               0 :         goto error;
    2595       190505394 :     regs.sp++;
    2596                 : }
    2597       190505394 : END_CASE(JSOP_LOCALINC)
    2598                 : 
    2599                 : BEGIN_CASE(JSOP_THIS)
    2600        11839328 :     if (!ComputeThis(cx, regs.fp()))
    2601               0 :         goto error;
    2602        11839328 :     PUSH_COPY(regs.fp()->thisValue());
    2603        11839328 : END_CASE(JSOP_THIS)
    2604                 : 
    2605                 : BEGIN_CASE(JSOP_GETPROP)
    2606                 : BEGIN_CASE(JSOP_GETXPROP)
    2607                 : BEGIN_CASE(JSOP_LENGTH)
    2608                 : BEGIN_CASE(JSOP_CALLPROP)
    2609                 : {
    2610                 :     Value rval;
    2611        85086067 :     if (!GetPropertyOperation(cx, regs.pc, regs.sp[-1], &rval))
    2612             742 :         goto error;
    2613                 : 
    2614        85085325 :     TypeScript::Monitor(cx, script, regs.pc, rval);
    2615                 : 
    2616        85085325 :     regs.sp[-1] = rval;
    2617        85085325 :     assertSameCompartment(cx, regs.sp[-1]);
    2618                 : }
    2619        85085325 : END_CASE(JSOP_GETPROP)
    2620                 : 
    2621                 : BEGIN_CASE(JSOP_SETGNAME)
    2622                 : BEGIN_CASE(JSOP_SETNAME)
    2623                 : BEGIN_CASE(JSOP_SETPROP)
    2624                 : BEGIN_CASE(JSOP_SETMETHOD)
    2625                 : {
    2626        17443787 :     const Value &rval = regs.sp[-1];
    2627        17443787 :     const Value &lval = regs.sp[-2];
    2628                 : 
    2629        17443787 :     if (!SetPropertyOperation(cx, regs.pc, lval, rval))
    2630             378 :         goto error;
    2631                 : 
    2632        17443409 :     regs.sp[-2] = regs.sp[-1];
    2633        17443409 :     regs.sp--;
    2634                 : }
    2635        17443409 : END_CASE(JSOP_SETPROP)
    2636                 : 
    2637                 : BEGIN_CASE(JSOP_GETELEM)
    2638                 : BEGIN_CASE(JSOP_CALLELEM)
    2639                 : {
    2640        34951384 :     Value &lref = regs.sp[-2];
    2641        34951384 :     Value &rref = regs.sp[-1];
    2642        34951384 :     if (!GetElementOperation(cx, op, lref, rref, &regs.sp[-2]))
    2643             369 :         goto error;
    2644        34951015 :     TypeScript::Monitor(cx, script, regs.pc, regs.sp[-2]);
    2645        34951015 :     regs.sp--;
    2646                 : }
    2647        34951015 : END_CASE(JSOP_GETELEM)
    2648                 : 
    2649                 : BEGIN_CASE(JSOP_SETELEM)
    2650                 : {
    2651                 :     JSObject *obj;
    2652        19832765 :     FETCH_OBJECT(cx, -3, obj);
    2653                 :     jsid id;
    2654        19832754 :     FETCH_ELEMENT_ID(obj, -2, id);
    2655        19832754 :     Value &value = regs.sp[-1];
    2656        19832754 :     if (!SetObjectElementOperation(cx, obj, id, value, script->strictModeCode))
    2657             464 :         goto error;
    2658        19832290 :     regs.sp[-3] = value;
    2659        19832290 :     regs.sp -= 2;
    2660                 : }
    2661        19832290 : END_CASE(JSOP_SETELEM)
    2662                 : 
    2663                 : BEGIN_CASE(JSOP_ENUMELEM)
    2664                 : {
    2665                 :     /* Funky: the value to set is under the [obj, id] pair. */
    2666                 :     JSObject *obj;
    2667            6120 :     FETCH_OBJECT(cx, -2, obj);
    2668                 :     jsid id;
    2669            6120 :     FETCH_ELEMENT_ID(obj, -1, id);
    2670            6120 :     Value rval = regs.sp[-3];
    2671            6120 :     if (!obj->setGeneric(cx, id, &rval, script->strictModeCode))
    2672               0 :         goto error;
    2673            6120 :     regs.sp -= 3;
    2674                 : }
    2675            6120 : END_CASE(JSOP_ENUMELEM)
    2676                 : 
    2677                 : BEGIN_CASE(JSOP_EVAL)
    2678                 : {
    2679           22319 :     CallArgs args = CallArgsFromSp(GET_ARGC(regs.pc), regs.sp);
    2680           22319 :     if (IsBuiltinEvalForScope(&regs.fp()->scopeChain(), args.calleev())) {
    2681           22298 :         if (!DirectEval(cx, args))
    2682             319 :             goto error;
    2683                 :     } else {
    2684              21 :         if (!InvokeKernel(cx, args))
    2685               0 :             goto error;
    2686                 :     }
    2687           22000 :     CHECK_INTERRUPT_HANDLER();
    2688           22000 :     regs.sp = args.spAfterCall();
    2689           22000 :     TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
    2690                 : }
    2691           22000 : END_CASE(JSOP_EVAL)
    2692                 : 
    2693                 : BEGIN_CASE(JSOP_NEW)
    2694                 : BEGIN_CASE(JSOP_CALL)
    2695                 : BEGIN_CASE(JSOP_FUNCALL)
    2696                 : BEGIN_CASE(JSOP_FUNAPPLY)
    2697                 : {
    2698        23197157 :     CallArgs args = CallArgsFromSp(GET_ARGC(regs.pc), regs.sp);
    2699        23197157 :     JS_ASSERT(args.base() >= regs.fp()->base());
    2700                 : 
    2701        23197157 :     bool construct = (*regs.pc == JSOP_NEW);
    2702                 : 
    2703                 :     JSFunction *fun;
    2704                 : 
    2705                 :     /* Don't bother trying to fast-path calls to scripted non-constructors. */
    2706        23197157 :     if (!IsFunctionObject(args.calleev(), &fun) || !fun->isInterpretedConstructor()) {
    2707        11303879 :         if (construct) {
    2708          174611 :             if (!InvokeConstructorKernel(cx, args))
    2709             575 :                 goto error;
    2710                 :         } else {
    2711        11129268 :             if (!InvokeKernel(cx, args))
    2712           29401 :                 goto error;
    2713                 :         }
    2714        11273903 :         Value *newsp = args.spAfterCall();
    2715        11273903 :         TypeScript::Monitor(cx, script, regs.pc, newsp[-1]);
    2716        11273903 :         regs.sp = newsp;
    2717        11273903 :         CHECK_INTERRUPT_HANDLER();
    2718        11273903 :         len = JSOP_CALL_LENGTH;
    2719        11273903 :         DO_NEXT_OP(len);
    2720                 :     }
    2721                 : 
    2722        11893278 :     TypeMonitorCall(cx, args, construct);
    2723                 : 
    2724        11893278 :     InitialFrameFlags initial = construct ? INITIAL_CONSTRUCT : INITIAL_NONE;
    2725                 : 
    2726        11893278 :     JSScript *newScript = fun->script();
    2727                 : 
    2728        11893278 :     if (newScript->compileAndGo && newScript->hasClearedGlobal()) {
    2729               0 :         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CLEARED_SCOPE);
    2730               0 :         goto error;
    2731                 :     }
    2732                 : 
    2733        11893278 :     if (!cx->stack.pushInlineFrame(cx, regs, args, *fun, newScript, initial))
    2734              52 :         goto error;
    2735                 : 
    2736        11893226 :     RESTORE_INTERP_VARS();
    2737                 : 
    2738        11893226 :     if (!regs.fp()->functionPrologue(cx))
    2739               0 :         goto error;
    2740                 : 
    2741        11893226 :     RESET_USE_METHODJIT();
    2742                 : 
    2743        11893226 :     bool newType = cx->typeInferenceEnabled() && UseNewType(cx, script, regs.pc);
    2744                 : 
    2745                 : #ifdef JS_METHODJIT
    2746        11893226 :     if (!newType) {
    2747                 :         /* Try to ensure methods are method JIT'd.  */
    2748                 :         mjit::CompileRequest request = (interpMode == JSINTERP_NORMAL)
    2749                 :                                        ? mjit::CompileRequest_Interpreter
    2750        11893226 :                                        : mjit::CompileRequest_JIT;
    2751                 :         mjit::CompileStatus status = mjit::CanMethodJIT(cx, script, script->code,
    2752        11893226 :                                                         construct, request);
    2753        11893226 :         if (status == mjit::Compile_Error)
    2754               0 :             goto error;
    2755        11893226 :         if (status == mjit::Compile_Okay) {
    2756          719821 :             mjit::JaegerStatus status = mjit::JaegerShot(cx, true);
    2757          719821 :             CHECK_PARTIAL_METHODJIT(status);
    2758          707635 :             interpReturnOK = mjit::JaegerStatusToSuccess(status);
    2759          707635 :             CHECK_INTERRUPT_HANDLER();
    2760          707635 :             goto jit_return;
    2761                 :         }
    2762                 :     }
    2763                 : #endif
    2764                 : 
    2765        11173405 :     if (!ScriptPrologue(cx, regs.fp(), newType))
    2766               0 :         goto error;
    2767                 : 
    2768        11173405 :     if (cx->compartment->debugMode()) {
    2769         1364827 :         switch (ScriptDebugPrologue(cx, regs.fp())) {
    2770                 :           case JSTRAP_CONTINUE:
    2771                 :             break;
    2772                 :           case JSTRAP_RETURN:
    2773              15 :             interpReturnOK = true;
    2774              15 :             goto forced_return;
    2775                 :           case JSTRAP_THROW:
    2776                 :           case JSTRAP_ERROR:
    2777               5 :             goto error;
    2778                 :           default:
    2779               0 :             JS_NOT_REACHED("bad ScriptDebugPrologue status");
    2780                 :         }
    2781                 :     }
    2782                 : 
    2783        11173385 :     CHECK_INTERRUPT_HANDLER();
    2784                 : 
    2785                 :     /* Load first op and dispatch it (safe since JSOP_STOP). */
    2786        11173385 :     op = (JSOp) *regs.pc;
    2787        11173385 :     DO_OP();
    2788                 : }
    2789                 : 
    2790                 : BEGIN_CASE(JSOP_SETCALL)
    2791                 : {
    2792               0 :     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_LEFTSIDE_OF_ASS);
    2793               0 :     goto error;
    2794                 : }
    2795                 : END_CASE(JSOP_SETCALL)
    2796                 : 
    2797                 : BEGIN_CASE(JSOP_IMPLICITTHIS)
    2798                 : {
    2799                 :     PropertyName *name;
    2800         1276090 :     LOAD_NAME(0, name);
    2801                 : 
    2802                 :     JSObject *obj, *obj2;
    2803                 :     JSProperty *prop;
    2804         1276090 :     if (!FindPropertyHelper(cx, name, false, cx->stack.currentScriptedScopeChain(), &obj, &obj2, &prop))
    2805               0 :         goto error;
    2806                 : 
    2807                 :     Value v;
    2808         1276090 :     if (!ComputeImplicitThis(cx, obj, &v))
    2809               0 :         goto error;
    2810         1276090 :     PUSH_COPY(v);
    2811                 : }
    2812         1276090 : END_CASE(JSOP_IMPLICITTHIS)
    2813                 : 
    2814                 : BEGIN_CASE(JSOP_GETGNAME)
    2815                 : BEGIN_CASE(JSOP_CALLGNAME)
    2816                 : BEGIN_CASE(JSOP_NAME)
    2817                 : BEGIN_CASE(JSOP_CALLNAME)
    2818                 : {
    2819                 :     Value rval;
    2820        51242318 :     if (!NameOperation(cx, regs.pc, &rval))
    2821            1310 :         goto error;
    2822                 : 
    2823        51241008 :     PUSH_COPY(rval);
    2824        51241008 :     TypeScript::Monitor(cx, script, regs.pc, rval);
    2825                 : }
    2826        51241008 : END_CASE(JSOP_NAME)
    2827                 : 
    2828                 : BEGIN_CASE(JSOP_UINT16)
    2829        26974890 :     PUSH_INT32((int32_t) GET_UINT16(regs.pc));
    2830        26974890 : END_CASE(JSOP_UINT16)
    2831                 : 
    2832                 : BEGIN_CASE(JSOP_UINT24)
    2833         2691323 :     PUSH_INT32((int32_t) GET_UINT24(regs.pc));
    2834         2691323 : END_CASE(JSOP_UINT24)
    2835                 : 
    2836                 : BEGIN_CASE(JSOP_INT8)
    2837        40716628 :     PUSH_INT32(GET_INT8(regs.pc));
    2838        40716628 : END_CASE(JSOP_INT8)
    2839                 : 
    2840                 : BEGIN_CASE(JSOP_INT32)
    2841         4617766 :     PUSH_INT32(GET_INT32(regs.pc));
    2842         4617766 : END_CASE(JSOP_INT32)
    2843                 : 
    2844                 : BEGIN_CASE(JSOP_DOUBLE)
    2845                 : {
    2846                 :     double dbl;
    2847         1378549 :     LOAD_DOUBLE(0, dbl);
    2848         1378549 :     PUSH_DOUBLE(dbl);
    2849                 : }
    2850         1378549 : END_CASE(JSOP_DOUBLE)
    2851                 : 
    2852                 : BEGIN_CASE(JSOP_STRING)
    2853                 : {
    2854                 :     JSAtom *atom;
    2855        13669591 :     LOAD_ATOM(0, atom);
    2856        13669591 :     PUSH_STRING(atom);
    2857                 : }
    2858        13669591 : END_CASE(JSOP_STRING)
    2859                 : 
    2860                 : BEGIN_CASE(JSOP_OBJECT)
    2861                 : {
    2862            6083 :     PUSH_OBJECT(*script->getObject(GET_UINT32_INDEX(regs.pc)));
    2863                 : }
    2864            6083 : END_CASE(JSOP_OBJECT)
    2865                 : 
    2866                 : BEGIN_CASE(JSOP_REGEXP)
    2867                 : {
    2868                 :     /*
    2869                 :      * Push a regexp object cloned from the regexp literal object mapped by the
    2870                 :      * bytecode at pc.
    2871                 :      */
    2872          191874 :     uint32_t index = GET_UINT32_INDEX(regs.pc);
    2873          191874 :     JSObject *proto = regs.fp()->scopeChain().global().getOrCreateRegExpPrototype(cx);
    2874          191874 :     if (!proto)
    2875               0 :         goto error;
    2876          191874 :     JSObject *obj = CloneRegExpObject(cx, script->getRegExp(index), proto);
    2877          191874 :     if (!obj)
    2878               0 :         goto error;
    2879          191874 :     PUSH_OBJECT(*obj);
    2880                 : }
    2881          191874 : END_CASE(JSOP_REGEXP)
    2882                 : 
    2883                 : BEGIN_CASE(JSOP_ZERO)
    2884        15893426 :     PUSH_INT32(0);
    2885        15893426 : END_CASE(JSOP_ZERO)
    2886                 : 
    2887                 : BEGIN_CASE(JSOP_ONE)
    2888        23285598 :     PUSH_INT32(1);
    2889        23285598 : END_CASE(JSOP_ONE)
    2890                 : 
    2891                 : BEGIN_CASE(JSOP_NULL)
    2892         2984618 :     PUSH_NULL();
    2893         2984618 : END_CASE(JSOP_NULL)
    2894                 : 
    2895                 : BEGIN_CASE(JSOP_FALSE)
    2896         2090201 :     PUSH_BOOLEAN(false);
    2897         2090201 : END_CASE(JSOP_FALSE)
    2898                 : 
    2899                 : BEGIN_CASE(JSOP_TRUE)
    2900         2154343 :     PUSH_BOOLEAN(true);
    2901         2154343 : END_CASE(JSOP_TRUE)
    2902                 : 
    2903                 : {
    2904                 : BEGIN_CASE(JSOP_TABLESWITCH)
    2905                 : {
    2906            2662 :     jsbytecode *pc2 = regs.pc;
    2907            2662 :     len = GET_JUMP_OFFSET(pc2);
    2908                 : 
    2909                 :     /*
    2910                 :      * ECMAv2+ forbids conversion of discriminant, so we will skip to the
    2911                 :      * default case if the discriminant isn't already an int jsval.  (This
    2912                 :      * opcode is emitted only for dense int-domain switches.)
    2913                 :      */
    2914            2662 :     const Value &rref = *--regs.sp;
    2915                 :     int32_t i;
    2916            2662 :     if (rref.isInt32()) {
    2917            2137 :         i = rref.toInt32();
    2918                 :     } else {
    2919                 :         double d;
    2920                 :         /* Don't use JSDOUBLE_IS_INT32; treat -0 (double) as 0. */
    2921             525 :         if (!rref.isDouble() || (d = rref.toDouble()) != (i = int32_t(rref.toDouble())))
    2922             481 :             DO_NEXT_OP(len);
    2923                 :     }
    2924                 : 
    2925            2181 :     pc2 += JUMP_OFFSET_LEN;
    2926            2181 :     int32_t low = GET_JUMP_OFFSET(pc2);
    2927            2181 :     pc2 += JUMP_OFFSET_LEN;
    2928            2181 :     int32_t high = GET_JUMP_OFFSET(pc2);
    2929                 : 
    2930            2181 :     i -= low;
    2931            2181 :     if ((uint32_t)i < (uint32_t)(high - low + 1)) {
    2932            1578 :         pc2 += JUMP_OFFSET_LEN + JUMP_OFFSET_LEN * i;
    2933            1578 :         int32_t off = (int32_t) GET_JUMP_OFFSET(pc2);
    2934            1578 :         if (off)
    2935            1568 :             len = off;
    2936                 :     }
    2937                 : }
    2938            2181 : END_VARLEN_CASE
    2939                 : }
    2940                 : 
    2941                 : {
    2942                 : BEGIN_CASE(JSOP_LOOKUPSWITCH)
    2943                 : {
    2944                 :     int32_t off;
    2945           26944 :     off = JUMP_OFFSET_LEN;
    2946                 : 
    2947                 :     /*
    2948                 :      * JSOP_LOOKUPSWITCH are never used if any atom index in it would exceed
    2949                 :      * 64K limit.
    2950                 :      */
    2951           26944 :     JS_ASSERT(atoms == script->atoms);
    2952           26944 :     jsbytecode *pc2 = regs.pc;
    2953                 : 
    2954           26944 :     Value lval = regs.sp[-1];
    2955           26944 :     regs.sp--;
    2956                 : 
    2957                 :     int npairs;
    2958           26944 :     if (!lval.isPrimitive())
    2959               0 :         goto end_lookup_switch;
    2960                 : 
    2961           26944 :     pc2 += off;
    2962           26944 :     npairs = GET_UINT16(pc2);
    2963           26944 :     pc2 += UINT16_LEN;
    2964           26944 :     JS_ASSERT(npairs);  /* empty switch uses JSOP_TABLESWITCH */
    2965                 : 
    2966                 :     bool match;
    2967                 : #define SEARCH_PAIRS(MATCH_CODE)                                              \
    2968                 :     for (;;) {                                                                \
    2969                 :         Value rval = script->getConst(GET_UINT32_INDEX(pc2));                 \
    2970                 :         MATCH_CODE                                                            \
    2971                 :         pc2 += UINT32_INDEX_LEN;                                              \
    2972                 :         if (match)                                                            \
    2973                 :             break;                                                            \
    2974                 :         pc2 += off;                                                           \
    2975                 :         if (--npairs == 0) {                                                  \
    2976                 :             pc2 = regs.pc;                                                    \
    2977                 :             break;                                                            \
    2978                 :         }                                                                     \
    2979                 :     }
    2980                 : 
    2981           26944 :     if (lval.isString()) {
    2982           26387 :         JSLinearString *str = lval.toString()->ensureLinear(cx);
    2983           26387 :         if (!str)
    2984               0 :             goto error;
    2985                 :         JSLinearString *str2;
    2986           92993 :         SEARCH_PAIRS(
    2987                 :             match = (rval.isString() &&
    2988                 :                      ((str2 = &rval.toString()->asLinear()) == str ||
    2989                 :                       EqualStrings(str2, str)));
    2990                 :         )
    2991             557 :     } else if (lval.isNumber()) {
    2992             225 :         double ldbl = lval.toNumber();
    2993             574 :         SEARCH_PAIRS(
    2994                 :             match = rval.isNumber() && ldbl == rval.toNumber();
    2995                 :         )
    2996                 :     } else {
    2997             664 :         SEARCH_PAIRS(
    2998                 :             match = (lval == rval);
    2999                 :         )
    3000                 :     }
    3001                 : #undef SEARCH_PAIRS
    3002                 : 
    3003                 :   end_lookup_switch:
    3004           26944 :     len = GET_JUMP_OFFSET(pc2);
    3005                 : }
    3006           26944 : END_VARLEN_CASE
    3007                 : }
    3008                 : 
    3009                 : BEGIN_CASE(JSOP_ARGUMENTS)
    3010                 : {
    3011                 :     Value rval;
    3012          267512 :     if (cx->typeInferenceEnabled() && !script->strictModeCode) {
    3013          117221 :         if (!script->ensureRanInference(cx))
    3014               0 :             goto error;
    3015          117221 :         if (script->createdArgs) {
    3016           90295 :             ArgumentsObject *arguments = js_GetArgsObject(cx, regs.fp());
    3017           90295 :             if (!arguments)
    3018               0 :                 goto error;
    3019           90295 :             rval = ObjectValue(*arguments);
    3020                 :         } else {
    3021           26926 :             rval = MagicValue(JS_LAZY_ARGUMENTS);
    3022                 :         }
    3023                 :     } else {
    3024          150291 :         ArgumentsObject *arguments = js_GetArgsObject(cx, regs.fp());
    3025          150291 :         if (!arguments)
    3026               0 :             goto error;
    3027          150291 :         rval = ObjectValue(*arguments);
    3028                 :     }
    3029          267512 :     PUSH_COPY(rval);
    3030                 : }
    3031          267512 : END_CASE(JSOP_ARGUMENTS)
    3032                 : 
    3033                 : BEGIN_CASE(JSOP_GETARG)
    3034                 : BEGIN_CASE(JSOP_CALLARG)
    3035        57642932 :     PUSH_COPY(regs.fp()->formalArg(GET_ARGNO(regs.pc)));
    3036        57642932 : END_CASE(JSOP_GETARG)
    3037                 : 
    3038                 : BEGIN_CASE(JSOP_SETARG)
    3039         5233396 :     regs.fp()->formalArg(GET_ARGNO(regs.pc)) = regs.sp[-1];
    3040         5233396 : END_CASE(JSOP_SETARG)
    3041                 : 
    3042                 : BEGIN_CASE(JSOP_GETLOCAL)
    3043                 : BEGIN_CASE(JSOP_CALLLOCAL)
    3044       352925145 :     PUSH_COPY_SKIP_CHECK(regs.fp()->localSlot(GET_SLOTNO(regs.pc)));
    3045                 : 
    3046                 :     /*
    3047                 :      * Skip the same-compartment assertion if the local will be immediately
    3048                 :      * popped. We do not guarantee sync for dead locals when coming in from the
    3049                 :      * method JIT, and a GETLOCAL followed by POP is not considered to be
    3050                 :      * a use of the variable.
    3051                 :      */
    3052       352925145 :     if (regs.pc[JSOP_GETLOCAL_LENGTH] != JSOP_POP)
    3053       348733569 :         assertSameCompartment(cx, regs.sp[-1]);
    3054       352925145 : END_CASE(JSOP_GETLOCAL)
    3055                 : 
    3056                 : BEGIN_CASE(JSOP_SETLOCAL)
    3057        44240905 :     regs.fp()->localSlot(GET_SLOTNO(regs.pc)) = regs.sp[-1];
    3058        44240905 : END_CASE(JSOP_SETLOCAL)
    3059                 : 
    3060                 : BEGIN_CASE(JSOP_GETFCSLOT)
    3061                 : BEGIN_CASE(JSOP_CALLFCSLOT)
    3062                 : {
    3063          718370 :     JS_ASSERT(regs.fp()->isNonEvalFunctionFrame());
    3064          718370 :     unsigned index = GET_UINT16(regs.pc);
    3065          718370 :     JSObject *obj = &argv[-2].toObject();
    3066                 : 
    3067          718370 :     PUSH_COPY(obj->toFunction()->getFlatClosureUpvar(index));
    3068          718370 :     TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
    3069                 : }
    3070          718370 : END_CASE(JSOP_GETFCSLOT)
    3071                 : 
    3072                 : BEGIN_CASE(JSOP_DEFCONST)
    3073                 : BEGIN_CASE(JSOP_DEFVAR)
    3074                 : {
    3075          285723 :     PropertyName *dn = atoms[GET_UINT32_INDEX(regs.pc)]->asPropertyName();
    3076                 : 
    3077                 :     /* ES5 10.5 step 8 (with subsequent errata). */
    3078          285723 :     unsigned attrs = JSPROP_ENUMERATE;
    3079          285723 :     if (!regs.fp()->isEvalFrame())
    3080          284637 :         attrs |= JSPROP_PERMANENT;
    3081          285723 :     if (op == JSOP_DEFCONST)
    3082          166661 :         attrs |= JSPROP_READONLY;
    3083                 : 
    3084                 :     /* Step 8b. */
    3085          285723 :     JSObject &obj = regs.fp()->varObj();
    3086                 : 
    3087          285723 :     if (!DefVarOrConstOperation(cx, obj, dn, attrs))
    3088               0 :         goto error;
    3089                 : }
    3090          285723 : END_CASE(JSOP_DEFVAR)
    3091                 : 
    3092                 : BEGIN_CASE(JSOP_DEFFUN)
    3093                 : {
    3094                 :     /*
    3095                 :      * A top-level function defined in Global or Eval code (see ECMA-262
    3096                 :      * Ed. 3), or else a SpiderMonkey extension: a named function statement in
    3097                 :      * a compound statement (not at the top statement level of global code, or
    3098                 :      * at the top level of a function body).
    3099                 :      */
    3100          184370 :     JSFunction *fun = script->getFunction(GET_UINT32_INDEX(regs.pc));
    3101          184370 :     JSObject *obj = fun;
    3102                 : 
    3103                 :     JSObject *obj2;
    3104          184370 :     if (fun->isNullClosure()) {
    3105                 :         /*
    3106                 :          * Even a null closure needs a parent for principals finding.
    3107                 :          * FIXME: bug 476950, although debugger users may also demand some kind
    3108                 :          * of scope link for debugger-assisted eval-in-frame.
    3109                 :          */
    3110          172017 :         obj2 = &regs.fp()->scopeChain();
    3111                 :     } else {
    3112           12353 :         JS_ASSERT(!fun->isFlatClosure());
    3113                 : 
    3114           12353 :         obj2 = GetScopeChain(cx, regs.fp());
    3115           12353 :         if (!obj2)
    3116               0 :             goto error;
    3117                 :     }
    3118                 : 
    3119                 :     /*
    3120                 :      * If static link is not current scope, clone fun's object to link to the
    3121                 :      * current scope via parent. We do this to enable sharing of compiled
    3122                 :      * functions among multiple equivalent scopes, amortizing the cost of
    3123                 :      * compilation over a number of executions.  Examples include XUL scripts
    3124                 :      * and event handlers shared among Firefox or other Mozilla app chrome
    3125                 :      * windows, and user-defined JS functions precompiled and then shared among
    3126                 :      * requests in server-side JS.
    3127                 :      */
    3128          184370 :     if (obj->toFunction()->environment() != obj2) {
    3129          182528 :         obj = CloneFunctionObjectIfNotSingleton(cx, fun, obj2);
    3130          182528 :         if (!obj)
    3131               0 :             goto error;
    3132          182528 :         JS_ASSERT_IF(script->hasGlobal(), obj->getProto() == fun->getProto());
    3133                 :     }
    3134                 : 
    3135                 :     /*
    3136                 :      * ECMA requires functions defined when entering Eval code to be
    3137                 :      * impermanent.
    3138                 :      */
    3139          184370 :     unsigned attrs = regs.fp()->isEvalFrame()
    3140                 :                   ? JSPROP_ENUMERATE
    3141          184370 :                   : JSPROP_ENUMERATE | JSPROP_PERMANENT;
    3142                 : 
    3143                 :     /*
    3144                 :      * We define the function as a property of the variable object and not the
    3145                 :      * current scope chain even for the case of function expression statements
    3146                 :      * and functions defined by eval inside let or with blocks.
    3147                 :      */
    3148          184370 :     JSObject *parent = &regs.fp()->varObj();
    3149                 : 
    3150                 :     /* ES5 10.5 (NB: with subsequent errata). */
    3151          184370 :     PropertyName *name = fun->atom->asPropertyName();
    3152          184370 :     JSProperty *prop = NULL;
    3153                 :     JSObject *pobj;
    3154          184370 :     if (!parent->lookupProperty(cx, name, &pobj, &prop))
    3155               0 :         goto error;
    3156                 : 
    3157          184370 :     Value rval = ObjectValue(*obj);
    3158                 : 
    3159                 :     do {
    3160                 :         /* Steps 5d, 5f. */
    3161          184370 :         if (!prop || pobj != parent) {
    3162          183360 :             if (!parent->defineProperty(cx, name, rval,
    3163          183360 :                                         JS_PropertyStub, JS_StrictPropertyStub, attrs))
    3164                 :             {
    3165               0 :                 goto error;
    3166                 :             }
    3167          183360 :             break;
    3168                 :         }
    3169                 : 
    3170                 :         /* Step 5e. */
    3171            1010 :         JS_ASSERT(parent->isNative());
    3172            1010 :         Shape *shape = reinterpret_cast<Shape *>(prop);
    3173            1010 :         if (parent->isGlobal()) {
    3174             720 :             if (shape->configurable()) {
    3175             201 :                 if (!parent->defineProperty(cx, name, rval,
    3176             201 :                                             JS_PropertyStub, JS_StrictPropertyStub, attrs))
    3177                 :                 {
    3178               0 :                     goto error;
    3179                 :                 }
    3180             201 :                 break;
    3181                 :             }
    3182                 : 
    3183             519 :             if (shape->isAccessorDescriptor() || !shape->writable() || !shape->enumerable()) {
    3184              10 :                 JSAutoByteString bytes;
    3185               5 :                 if (js_AtomToPrintableString(cx, name, &bytes)) {
    3186                 :                     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
    3187               5 :                                          JSMSG_CANT_REDEFINE_PROP, bytes.ptr());
    3188                 :                 }
    3189                 :                 goto error;
    3190                 :             }
    3191                 :         }
    3192                 : 
    3193                 :         /*
    3194                 :          * Non-global properties, and global properties which we aren't simply
    3195                 :          * redefining, must be set.  First, this preserves their attributes.
    3196                 :          * Second, this will produce warnings and/or errors as necessary if the
    3197                 :          * specified Call object property is not writable (const).
    3198                 :          */
    3199                 : 
    3200                 :         /* Step 5f. */
    3201             804 :         if (!parent->setProperty(cx, name, &rval, script->strictModeCode))
    3202               0 :             goto error;
    3203                 :     } while (false);
    3204                 : }
    3205          184365 : END_CASE(JSOP_DEFFUN)
    3206                 : 
    3207                 : BEGIN_CASE(JSOP_DEFLOCALFUN)
    3208                 : {
    3209                 :     /*
    3210                 :      * Define a local function (i.e., one nested at the top level of another
    3211                 :      * function), parented by the current scope chain, stored in a local
    3212                 :      * variable slot that the compiler allocated.  This is an optimization over
    3213                 :      * JSOP_DEFFUN that avoids requiring a call object for the outer function's
    3214                 :      * activation.
    3215                 :      */
    3216          124457 :     JSFunction *fun = script->getFunction(GET_UINT32_INDEX(regs.pc + SLOTNO_LEN));
    3217          124457 :     JS_ASSERT(fun->isInterpreted());
    3218          124457 :     JS_ASSERT(!fun->isFlatClosure());
    3219                 : 
    3220                 :     JSObject *parent;
    3221          124457 :     if (fun->isNullClosure()) {
    3222           21849 :         parent = &regs.fp()->scopeChain();
    3223                 :     } else {
    3224          102608 :         parent = GetScopeChain(cx, regs.fp());
    3225          102608 :         if (!parent)
    3226               0 :             goto error;
    3227                 :     }
    3228          124457 :     JSObject *obj = CloneFunctionObjectIfNotSingleton(cx, fun, parent);
    3229          124457 :     if (!obj)
    3230               0 :         goto error;
    3231                 : 
    3232          124457 :     JS_ASSERT_IF(script->hasGlobal(), obj->getProto() == fun->getProto());
    3233                 : 
    3234          124457 :     regs.fp()->varSlot(GET_SLOTNO(regs.pc)) = ObjectValue(*obj);
    3235                 : }
    3236          124457 : END_CASE(JSOP_DEFLOCALFUN)
    3237                 : 
    3238                 : BEGIN_CASE(JSOP_DEFLOCALFUN_FC)
    3239                 : {
    3240            8017 :     JSFunction *fun = script->getFunction(GET_UINT32_INDEX(regs.pc + SLOTNO_LEN));
    3241                 : 
    3242            8017 :     JSObject *obj = js_NewFlatClosure(cx, fun);
    3243            8017 :     if (!obj)
    3244               0 :         goto error;
    3245                 : 
    3246            8017 :     regs.fp()->varSlot(GET_SLOTNO(regs.pc)) = ObjectValue(*obj);
    3247                 : }
    3248            8017 : END_CASE(JSOP_DEFLOCALFUN_FC)
    3249                 : 
    3250                 : BEGIN_CASE(JSOP_LAMBDA)
    3251                 : {
    3252                 :     /* Load the specified function object literal. */
    3253         1028290 :     JSFunction *fun = script->getFunction(GET_UINT32_INDEX(regs.pc));
    3254         1028290 :     JSObject *obj = fun;
    3255                 : 
    3256                 :     /* do-while(0) so we can break instead of using a goto. */
    3257                 :     do {
    3258                 :         JSObject *parent;
    3259         1028290 :         if (fun->isNullClosure()) {
    3260          646687 :             parent = &regs.fp()->scopeChain();
    3261                 : 
    3262          646687 :             if (fun->joinable()) {
    3263           82826 :                 jsbytecode *pc2 = regs.pc + JSOP_LAMBDA_LENGTH;
    3264           82826 :                 JSOp op2 = JSOp(*pc2);
    3265                 : 
    3266                 :                 /*
    3267                 :                  * Optimize var obj = {method: function () { ... }, ...},
    3268                 :                  * this.method = function () { ... }; and other significant
    3269                 :                  * single-use-of-null-closure bytecode sequences.
    3270                 :                  */
    3271           82826 :                 if (op2 == JSOP_INITMETHOD) {
    3272                 : #ifdef DEBUG
    3273            5356 :                     const Value &lref = regs.sp[-1];
    3274            5356 :                     JS_ASSERT(lref.isObject());
    3275            5356 :                     JSObject *obj2 = &lref.toObject();
    3276            5356 :                     JS_ASSERT(obj2->isObject());
    3277                 : #endif
    3278            5356 :                     JS_ASSERT(fun->methodAtom() ==
    3279            5356 :                               script->getAtom(GET_UINT32_INDEX(regs.pc + JSOP_LAMBDA_LENGTH)));
    3280            5356 :                     break;
    3281                 :                 }
    3282                 : 
    3283           77470 :                 if (op2 == JSOP_SETMETHOD) {
    3284                 : #ifdef DEBUG
    3285            5940 :                     op2 = JSOp(pc2[JSOP_SETMETHOD_LENGTH]);
    3286            5940 :                     JS_ASSERT(op2 == JSOP_POP || op2 == JSOP_POPV);
    3287                 : #endif
    3288            5940 :                     const Value &lref = regs.sp[-1];
    3289            5940 :                     if (lref.isObject() && lref.toObject().canHaveMethodBarrier()) {
    3290            2727 :                         JS_ASSERT(fun->methodAtom() ==
    3291            2727 :                                   script->getAtom(GET_UINT32_INDEX(regs.pc + JSOP_LAMBDA_LENGTH)));
    3292            2727 :                         break;
    3293                 :                     }
    3294           71530 :                 } else if (op2 == JSOP_CALL) {
    3295                 :                     /*
    3296                 :                      * Array.prototype.sort and String.prototype.replace are
    3297                 :                      * optimized as if they are special form. We know that they
    3298                 :                      * won't leak the joined function object in obj, therefore
    3299                 :                      * we don't need to clone that compiler-created function
    3300                 :                      * object for identity/mutation reasons.
    3301                 :                      */
    3302            5052 :                     int iargc = GET_ARGC(pc2);
    3303                 : 
    3304                 :                     /*
    3305                 :                      * Note that we have not yet pushed obj as the final argument,
    3306                 :                      * so regs.sp[1 - (iargc + 2)], and not regs.sp[-(iargc + 2)],
    3307                 :                      * is the callee for this JSOP_CALL.
    3308                 :                      */
    3309            5052 :                     const Value &cref = regs.sp[1 - (iargc + 2)];
    3310                 :                     JSFunction *fun;
    3311                 : 
    3312            5052 :                     if (IsFunctionObject(cref, &fun)) {
    3313            5030 :                         if (Native native = fun->maybeNative()) {
    3314            3039 :                             if ((iargc == 1 && native == array_sort) ||
    3315                 :                                 (iargc == 2 && native == str_replace)) {
    3316             595 :                                 break;
    3317                 :                             }
    3318                 :                         }
    3319                 :                     }
    3320           66478 :                 } else if (op2 == JSOP_NULL) {
    3321               0 :                     pc2 += JSOP_NULL_LENGTH;
    3322               0 :                     op2 = JSOp(*pc2);
    3323                 : 
    3324               0 :                     if (op2 == JSOP_CALL && GET_ARGC(pc2) == 0)
    3325               0 :                         break;
    3326                 :                 }
    3327                 :             }
    3328                 :         } else {
    3329          381603 :             parent = GetScopeChain(cx, regs.fp());
    3330          381603 :             if (!parent)
    3331               0 :                 goto error;
    3332                 :         }
    3333                 : 
    3334         1019612 :         obj = CloneFunctionObjectIfNotSingleton(cx, fun, parent);
    3335         1019612 :         if (!obj)
    3336               0 :             goto error;
    3337                 :     } while (0);
    3338                 : 
    3339         1028290 :     JS_ASSERT(obj->getProto());
    3340         1028290 :     JS_ASSERT_IF(script->hasGlobal(), obj->getProto() == fun->getProto());
    3341                 : 
    3342         1028290 :     PUSH_OBJECT(*obj);
    3343                 : }
    3344         1028290 : END_CASE(JSOP_LAMBDA)
    3345                 : 
    3346                 : BEGIN_CASE(JSOP_LAMBDA_FC)
    3347                 : {
    3348          312692 :     JSFunction *fun = script->getFunction(GET_UINT32_INDEX(regs.pc));
    3349                 : 
    3350          312692 :     JSObject *obj = js_NewFlatClosure(cx, fun);
    3351          312692 :     if (!obj)
    3352               0 :         goto error;
    3353          312692 :     JS_ASSERT_IF(script->hasGlobal(), obj->getProto() == fun->getProto());
    3354                 : 
    3355          312692 :     PUSH_OBJECT(*obj);
    3356                 : }
    3357          312692 : END_CASE(JSOP_LAMBDA_FC)
    3358                 : 
    3359                 : BEGIN_CASE(JSOP_CALLEE)
    3360         1307054 :     JS_ASSERT(regs.fp()->isNonEvalFunctionFrame());
    3361         1307054 :     PUSH_COPY(argv[-2]);
    3362         1307054 : END_CASE(JSOP_CALLEE)
    3363                 : 
    3364                 : BEGIN_CASE(JSOP_GETTER)
    3365                 : BEGIN_CASE(JSOP_SETTER)
    3366                 : {
    3367           73594 :     JSOp op2 = JSOp(*++regs.pc);
    3368                 :     jsid id;
    3369                 :     Value rval;
    3370                 :     int i;
    3371                 :     JSObject *obj;
    3372           73594 :     switch (op2) {
    3373                 :       case JSOP_SETNAME:
    3374                 :       case JSOP_SETPROP:
    3375                 :       {
    3376                 :         PropertyName *name;
    3377               0 :         LOAD_NAME(0, name);
    3378               0 :         id = ATOM_TO_JSID(name);
    3379               0 :         rval = regs.sp[-1];
    3380               0 :         i = -1;
    3381               0 :         goto gs_pop_lval;
    3382                 :       }
    3383                 :       case JSOP_SETELEM:
    3384               0 :         rval = regs.sp[-1];
    3385               0 :         id = JSID_VOID;
    3386               0 :         i = -2;
    3387                 :       gs_pop_lval:
    3388               0 :         FETCH_OBJECT(cx, i - 1, obj);
    3389               0 :         break;
    3390                 : 
    3391                 :       case JSOP_INITPROP:
    3392                 :       {
    3393           73594 :         JS_ASSERT(regs.sp - regs.fp()->base() >= 2);
    3394           73594 :         rval = regs.sp[-1];
    3395           73594 :         i = -1;
    3396                 :         PropertyName *name;
    3397           73594 :         LOAD_NAME(0, name);
    3398           73594 :         id = ATOM_TO_JSID(name);
    3399           73594 :         goto gs_get_lval;
    3400                 :       }
    3401                 :       default:
    3402               0 :         JS_ASSERT(op2 == JSOP_INITELEM);
    3403                 : 
    3404               0 :         JS_ASSERT(regs.sp - regs.fp()->base() >= 3);
    3405               0 :         rval = regs.sp[-1];
    3406               0 :         id = JSID_VOID;
    3407               0 :         i = -2;
    3408                 :       gs_get_lval:
    3409                 :       {
    3410           73594 :         const Value &lref = regs.sp[i-1];
    3411           73594 :         JS_ASSERT(lref.isObject());
    3412           73594 :         obj = &lref.toObject();
    3413           73594 :         break;
    3414                 :       }
    3415                 :     }
    3416                 : 
    3417                 :     /* Ensure that id has a type suitable for use with obj. */
    3418           73594 :     if (JSID_IS_VOID(id))
    3419               0 :         FETCH_ELEMENT_ID(obj, i, id);
    3420                 : 
    3421           73594 :     if (!js_IsCallable(rval)) {
    3422                 :         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_GETTER_OR_SETTER,
    3423               0 :                              (op == JSOP_GETTER) ? js_getter_str : js_setter_str);
    3424               0 :         goto error;
    3425                 :     }
    3426                 : 
    3427                 :     /*
    3428                 :      * Getters and setters are just like watchpoints from an access control
    3429                 :      * point of view.
    3430                 :      */
    3431                 :     Value rtmp;
    3432                 :     unsigned attrs;
    3433           73594 :     if (!CheckAccess(cx, obj, id, JSACC_WATCH, &rtmp, &attrs))
    3434               0 :         goto error;
    3435                 : 
    3436                 :     PropertyOp getter;
    3437                 :     StrictPropertyOp setter;
    3438           73594 :     if (op == JSOP_GETTER) {
    3439           60028 :         getter = CastAsPropertyOp(&rval.toObject());
    3440           60028 :         setter = JS_StrictPropertyStub;
    3441           60028 :         attrs = JSPROP_GETTER;
    3442                 :     } else {
    3443           13566 :         getter = JS_PropertyStub;
    3444           13566 :         setter = CastAsStrictPropertyOp(&rval.toObject());
    3445           13566 :         attrs = JSPROP_SETTER;
    3446                 :     }
    3447           73594 :     attrs |= JSPROP_ENUMERATE | JSPROP_SHARED;
    3448                 : 
    3449           73594 :     if (!obj->defineGeneric(cx, id, UndefinedValue(), getter, setter, attrs))
    3450               0 :         goto error;
    3451                 : 
    3452           73594 :     regs.sp += i;
    3453           73594 :     if (js_CodeSpec[op2].ndefs > js_CodeSpec[op2].nuses) {
    3454               0 :         JS_ASSERT(js_CodeSpec[op2].ndefs == js_CodeSpec[op2].nuses + 1);
    3455               0 :         regs.sp[-1] = rval;
    3456               0 :         assertSameCompartment(cx, regs.sp[-1]);
    3457                 :     }
    3458           73594 :     len = js_CodeSpec[op2].length;
    3459           73594 :     DO_NEXT_OP(len);
    3460                 : }
    3461                 : 
    3462                 : BEGIN_CASE(JSOP_HOLE)
    3463            4767 :     PUSH_HOLE();
    3464            4767 : END_CASE(JSOP_HOLE)
    3465                 : 
    3466                 : BEGIN_CASE(JSOP_NEWINIT)
    3467                 : {
    3468          303229 :     uint8_t i = GET_UINT8(regs.pc);
    3469          303229 :     JS_ASSERT(i == JSProto_Array || i == JSProto_Object);
    3470                 : 
    3471                 :     JSObject *obj;
    3472          303229 :     if (i == JSProto_Array) {
    3473           57856 :         obj = NewDenseEmptyArray(cx);
    3474                 :     } else {
    3475          245373 :         gc::AllocKind kind = GuessObjectGCKind(0);
    3476          245373 :         obj = NewBuiltinClassInstance(cx, &ObjectClass, kind);
    3477                 :     }
    3478          303229 :     if (!obj)
    3479               0 :         goto error;
    3480                 : 
    3481          303229 :     TypeObject *type = TypeScript::InitObject(cx, script, regs.pc, (JSProtoKey) i);
    3482          303229 :     if (!type)
    3483               0 :         goto error;
    3484          303229 :     obj->setType(type);
    3485                 : 
    3486          303229 :     PUSH_OBJECT(*obj);
    3487          303229 :     CHECK_INTERRUPT_HANDLER();
    3488                 : }
    3489          303229 : END_CASE(JSOP_NEWINIT)
    3490                 : 
    3491                 : BEGIN_CASE(JSOP_NEWARRAY)
    3492                 : {
    3493         1088178 :     unsigned count = GET_UINT24(regs.pc);
    3494         1088178 :     JSObject *obj = NewDenseAllocatedArray(cx, count);
    3495         1088178 :     if (!obj)
    3496               0 :         goto error;
    3497                 : 
    3498         1088178 :     TypeObject *type = TypeScript::InitObject(cx, script, regs.pc, JSProto_Array);
    3499         1088178 :     if (!type)
    3500               0 :         goto error;
    3501         1088178 :     obj->setType(type);
    3502                 : 
    3503         1088178 :     PUSH_OBJECT(*obj);
    3504         1088178 :     CHECK_INTERRUPT_HANDLER();
    3505                 : }
    3506         1088178 : END_CASE(JSOP_NEWARRAY)
    3507                 : 
    3508                 : BEGIN_CASE(JSOP_NEWOBJECT)
    3509                 : {
    3510         1054016 :     JSObject *baseobj = script->getObject(GET_UINT32_INDEX(regs.pc));
    3511                 : 
    3512         1054016 :     TypeObject *type = TypeScript::InitObject(cx, script, regs.pc, JSProto_Object);
    3513         1054016 :     if (!type)
    3514               0 :         goto error;
    3515                 : 
    3516         1054016 :     JSObject *obj = CopyInitializerObject(cx, baseobj, type);
    3517         1054016 :     if (!obj)
    3518               1 :         goto error;
    3519                 : 
    3520         1054015 :     PUSH_OBJECT(*obj);
    3521         1054015 :     CHECK_INTERRUPT_HANDLER();
    3522                 : }
    3523         1054015 : END_CASE(JSOP_NEWOBJECT)
    3524                 : 
    3525                 : BEGIN_CASE(JSOP_ENDINIT)
    3526                 : {
    3527                 :     /* FIXME remove JSOP_ENDINIT bug 588522 */
    3528         2382188 :     JS_ASSERT(regs.sp - regs.fp()->base() >= 1);
    3529         2382188 :     JS_ASSERT(regs.sp[-1].isObject());
    3530                 : }
    3531         2382188 : END_CASE(JSOP_ENDINIT)
    3532                 : 
    3533                 : BEGIN_CASE(JSOP_INITPROP)
    3534                 : BEGIN_CASE(JSOP_INITMETHOD)
    3535                 : {
    3536                 :     /* Load the property's initial value into rval. */
    3537         2989315 :     JS_ASSERT(regs.sp - regs.fp()->base() >= 2);
    3538         2989315 :     Value rval = regs.sp[-1];
    3539                 : 
    3540                 :     /* Load the object being initialized into lval/obj. */
    3541         2989315 :     JSObject *obj = &regs.sp[-2].toObject();
    3542         2989315 :     JS_ASSERT(obj->isObject());
    3543                 : 
    3544                 :     JSAtom *atom;
    3545         2989315 :     LOAD_ATOM(0, atom);
    3546         2989315 :     jsid id = ATOM_TO_JSID(atom);
    3547                 : 
    3548         2989315 :     unsigned defineHow = (op == JSOP_INITMETHOD) ? DNP_SET_METHOD : 0;
    3549         5978630 :     if (JS_UNLIKELY(atom == cx->runtime->atomState.protoAtom)
    3550            9716 :         ? !js_SetPropertyHelper(cx, obj, id, defineHow, &rval, script->strictModeCode)
    3551                 :         : !DefineNativeProperty(cx, obj, id, rval, NULL, NULL,
    3552         2979599 :                                 JSPROP_ENUMERATE, 0, 0, defineHow)) {
    3553               0 :         goto error;
    3554                 :     }
    3555                 : 
    3556         2989315 :     regs.sp--;
    3557                 : }
    3558         2989315 : END_CASE(JSOP_INITPROP);
    3559                 : 
    3560                 : BEGIN_CASE(JSOP_INITELEM)
    3561                 : {
    3562                 :     /* Pop the element's value into rval. */
    3563        11320186 :     JS_ASSERT(regs.sp - regs.fp()->base() >= 3);
    3564        11320186 :     const Value &rref = regs.sp[-1];
    3565                 : 
    3566                 :     /* Find the object being initialized at top of stack. */
    3567        11320186 :     const Value &lref = regs.sp[-3];
    3568        11320186 :     JS_ASSERT(lref.isObject());
    3569        11320186 :     JSObject *obj = &lref.toObject();
    3570                 : 
    3571                 :     /* Fetch id now that we have obj. */
    3572                 :     jsid id;
    3573        11320186 :     FETCH_ELEMENT_ID(obj, -2, id);
    3574                 : 
    3575                 :     /*
    3576                 :      * If rref is a hole, do not call JSObject::defineProperty. In this case,
    3577                 :      * obj must be an array, so if the current op is the last element
    3578                 :      * initialiser, set the array length to one greater than id.
    3579                 :      */
    3580        11320186 :     if (rref.isMagic(JS_ARRAY_HOLE)) {
    3581            4767 :         JS_ASSERT(obj->isArray());
    3582            4767 :         JS_ASSERT(JSID_IS_INT(id));
    3583            4767 :         JS_ASSERT(uint32_t(JSID_TO_INT(id)) < StackSpace::ARGS_LENGTH_MAX);
    3584            5165 :         if (JSOp(regs.pc[JSOP_INITELEM_LENGTH]) == JSOP_ENDINIT &&
    3585             398 :             !js_SetLengthProperty(cx, obj, (uint32_t) (JSID_TO_INT(id) + 1))) {
    3586               0 :             goto error;
    3587                 :         }
    3588                 :     } else {
    3589        11315419 :         if (!obj->defineGeneric(cx, id, rref, NULL, NULL, JSPROP_ENUMERATE))
    3590               0 :             goto error;
    3591                 :     }
    3592        11320186 :     regs.sp -= 2;
    3593                 : }
    3594        11320186 : END_CASE(JSOP_INITELEM)
    3595                 : 
    3596                 : {
    3597                 : BEGIN_CASE(JSOP_GOSUB)
    3598           43471 :     PUSH_BOOLEAN(false);
    3599           43471 :     int32_t i = (regs.pc - script->code) + JSOP_GOSUB_LENGTH;
    3600           43471 :     len = GET_JUMP_OFFSET(regs.pc);
    3601           43471 :     PUSH_INT32(i);
    3602           43471 : END_VARLEN_CASE
    3603                 : }
    3604                 : 
    3605                 : {
    3606                 : BEGIN_CASE(JSOP_RETSUB)
    3607                 :     /* Pop [exception or hole, retsub pc-index]. */
    3608                 :     Value rval, lval;
    3609           45222 :     POP_COPY_TO(rval);
    3610           45222 :     POP_COPY_TO(lval);
    3611           45222 :     JS_ASSERT(lval.isBoolean());
    3612           45222 :     if (lval.toBoolean()) {
    3613                 :         /*
    3614                 :          * Exception was pending during finally, throw it *before* we adjust
    3615                 :          * pc, because pc indexes into script->trynotes.  This turns out not to
    3616                 :          * be necessary, but it seems clearer.  And it points out a FIXME:
    3617                 :          * 350509, due to Igor Bukanov.
    3618                 :          */
    3619            1770 :         cx->setPendingException(rval);
    3620            1770 :         goto error;
    3621                 :     }
    3622           43452 :     JS_ASSERT(rval.isInt32());
    3623           43452 :     len = rval.toInt32();
    3624           43452 :     regs.pc = script->code;
    3625           43452 : END_VARLEN_CASE
    3626                 : }
    3627                 : 
    3628                 : BEGIN_CASE(JSOP_EXCEPTION)
    3629           27622 :     PUSH_COPY(cx->getPendingException());
    3630           27622 :     cx->clearPendingException();
    3631           27622 :     CHECK_BRANCH();
    3632           27622 : END_CASE(JSOP_EXCEPTION)
    3633                 : 
    3634                 : BEGIN_CASE(JSOP_FINALLY)
    3635           45259 :     CHECK_BRANCH();
    3636           45259 : END_CASE(JSOP_FINALLY)
    3637                 : 
    3638                 : BEGIN_CASE(JSOP_THROWING)
    3639                 : {
    3640              54 :     JS_ASSERT(!cx->isExceptionPending());
    3641                 :     Value v;
    3642              54 :     POP_COPY_TO(v);
    3643              54 :     cx->setPendingException(v);
    3644                 : }
    3645              54 : END_CASE(JSOP_THROWING)
    3646                 : 
    3647                 : BEGIN_CASE(JSOP_THROW)
    3648                 : {
    3649           55422 :     JS_ASSERT(!cx->isExceptionPending());
    3650           55422 :     CHECK_BRANCH();
    3651                 :     Value v;
    3652           55422 :     POP_COPY_TO(v);
    3653           55422 :     cx->setPendingException(v);
    3654                 :     /* let the code at error try to catch the exception. */
    3655           55422 :     goto error;
    3656                 : }
    3657                 : BEGIN_CASE(JSOP_SETLOCALPOP)
    3658                 :     /*
    3659                 :      * The stack must have a block with at least one local slot below the
    3660                 :      * exception object.
    3661                 :      */
    3662          274677 :     JS_ASSERT((size_t) (regs.sp - regs.fp()->base()) >= 2);
    3663          274677 :     POP_COPY_TO(regs.fp()->localSlot(GET_UINT16(regs.pc)));
    3664          274677 : END_CASE(JSOP_SETLOCALPOP)
    3665                 : 
    3666                 : BEGIN_CASE(JSOP_INSTANCEOF)
    3667                 : {
    3668         1137081 :     const Value &rref = regs.sp[-1];
    3669         1137081 :     if (rref.isPrimitive()) {
    3670               0 :         js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS, -1, rref, NULL);
    3671               0 :         goto error;
    3672                 :     }
    3673         1137081 :     JSObject *obj = &rref.toObject();
    3674         1137081 :     const Value &lref = regs.sp[-2];
    3675         1137081 :     JSBool cond = JS_FALSE;
    3676         1137081 :     if (!HasInstance(cx, obj, &lref, &cond))
    3677              19 :         goto error;
    3678         1137062 :     regs.sp--;
    3679         1137062 :     regs.sp[-1].setBoolean(cond);
    3680                 : }
    3681         1137062 : END_CASE(JSOP_INSTANCEOF)
    3682                 : 
    3683                 : BEGIN_CASE(JSOP_DEBUGGER)
    3684                 : {
    3685            4874 :     JSTrapStatus st = JSTRAP_CONTINUE;
    3686                 :     Value rval;
    3687            4874 :     if (JSDebuggerHandler handler = cx->runtime->debugHooks.debuggerHandler)
    3688              59 :         st = handler(cx, script, regs.pc, &rval, cx->runtime->debugHooks.debuggerHandlerData);
    3689            4874 :     if (st == JSTRAP_CONTINUE)
    3690            4869 :         st = Debugger::onDebuggerStatement(cx, &rval);
    3691            4874 :     switch (st) {
    3692                 :       case JSTRAP_ERROR:
    3693             118 :         goto error;
    3694                 :       case JSTRAP_CONTINUE:
    3695            4532 :         break;
    3696                 :       case JSTRAP_RETURN:
    3697             149 :         regs.fp()->setReturnValue(rval);
    3698             149 :         interpReturnOK = true;
    3699             149 :         goto forced_return;
    3700                 :       case JSTRAP_THROW:
    3701              75 :         cx->setPendingException(rval);
    3702              75 :         goto error;
    3703                 :       default:;
    3704                 :     }
    3705            4532 :     CHECK_INTERRUPT_HANDLER();
    3706                 : }
    3707            4532 : END_CASE(JSOP_DEBUGGER)
    3708                 : 
    3709                 : #if JS_HAS_XML_SUPPORT
    3710                 : BEGIN_CASE(JSOP_DEFXMLNS)
    3711                 : {
    3712               9 :     JS_ASSERT(!script->strictModeCode);
    3713                 : 
    3714               9 :     if (!js_SetDefaultXMLNamespace(cx, regs.sp[-1]))
    3715               0 :         goto error;
    3716               9 :     regs.sp--;
    3717                 : }
    3718               9 : END_CASE(JSOP_DEFXMLNS)
    3719                 : 
    3720                 : BEGIN_CASE(JSOP_ANYNAME)
    3721                 : {
    3722              18 :     JS_ASSERT(!script->strictModeCode);
    3723                 : 
    3724                 :     jsid id;
    3725              18 :     if (!js_GetAnyName(cx, &id))
    3726               0 :         goto error;
    3727              18 :     PUSH_COPY(IdToValue(id));
    3728                 : }
    3729              18 : END_CASE(JSOP_ANYNAME)
    3730                 : 
    3731                 : BEGIN_CASE(JSOP_QNAMEPART)
    3732                 : {
    3733                 :     /*
    3734                 :      * We do not JS_ASSERT(!script->strictModeCode) here because JSOP_QNAMEPART
    3735                 :      * is used for __proto__ and (in contexts where we favor JSOP_*ELEM instead
    3736                 :      * of JSOP_*PROP) obj.prop compiled as obj['prop'].
    3737                 :      */
    3738                 : 
    3739                 :     JSAtom *atom;
    3740            7359 :     LOAD_ATOM(0, atom);
    3741            7359 :     PUSH_STRING(atom);
    3742                 : }
    3743            7359 : END_CASE(JSOP_QNAMEPART)
    3744                 : 
    3745                 : BEGIN_CASE(JSOP_QNAMECONST)
    3746                 : {
    3747              45 :     JS_ASSERT(!script->strictModeCode);
    3748                 : 
    3749                 :     JSAtom *atom;
    3750              45 :     LOAD_ATOM(0, atom);
    3751              45 :     Value rval = StringValue(atom);
    3752              45 :     Value lval = regs.sp[-1];
    3753              45 :     JSObject *obj = js_ConstructXMLQNameObject(cx, lval, rval);
    3754              45 :     if (!obj)
    3755               0 :         goto error;
    3756              45 :     regs.sp[-1].setObject(*obj);
    3757                 : }
    3758              45 : END_CASE(JSOP_QNAMECONST)
    3759                 : 
    3760                 : BEGIN_CASE(JSOP_QNAME)
    3761                 : {
    3762               0 :     JS_ASSERT(!script->strictModeCode);
    3763                 : 
    3764               0 :     Value rval = regs.sp[-1];
    3765               0 :     Value lval = regs.sp[-2];
    3766               0 :     JSObject *obj = js_ConstructXMLQNameObject(cx, lval, rval);
    3767               0 :     if (!obj)
    3768               0 :         goto error;
    3769               0 :     regs.sp--;
    3770               0 :     regs.sp[-1].setObject(*obj);
    3771                 : }
    3772               0 : END_CASE(JSOP_QNAME)
    3773                 : 
    3774                 : BEGIN_CASE(JSOP_TOATTRNAME)
    3775                 : {
    3776               0 :     JS_ASSERT(!script->strictModeCode);
    3777                 : 
    3778                 :     Value rval;
    3779               0 :     rval = regs.sp[-1];
    3780               0 :     if (!js_ToAttributeName(cx, &rval))
    3781               0 :         goto error;
    3782               0 :     regs.sp[-1] = rval;
    3783                 : }
    3784               0 : END_CASE(JSOP_TOATTRNAME)
    3785                 : 
    3786                 : BEGIN_CASE(JSOP_TOATTRVAL)
    3787                 : {
    3788               0 :     JS_ASSERT(!script->strictModeCode);
    3789                 : 
    3790                 :     Value rval;
    3791               0 :     rval = regs.sp[-1];
    3792               0 :     JS_ASSERT(rval.isString());
    3793               0 :     JSString *str = js_EscapeAttributeValue(cx, rval.toString(), JS_FALSE);
    3794               0 :     if (!str)
    3795               0 :         goto error;
    3796               0 :     regs.sp[-1].setString(str);
    3797                 : }
    3798               0 : END_CASE(JSOP_TOATTRVAL)
    3799                 : 
    3800                 : BEGIN_CASE(JSOP_ADDATTRNAME)
    3801                 : BEGIN_CASE(JSOP_ADDATTRVAL)
    3802                 : {
    3803               0 :     JS_ASSERT(!script->strictModeCode);
    3804                 : 
    3805               0 :     Value rval = regs.sp[-1];
    3806               0 :     Value lval = regs.sp[-2];
    3807               0 :     JSString *str = lval.toString();
    3808               0 :     JSString *str2 = rval.toString();
    3809               0 :     str = js_AddAttributePart(cx, op == JSOP_ADDATTRNAME, str, str2);
    3810               0 :     if (!str)
    3811               0 :         goto error;
    3812               0 :     regs.sp--;
    3813               0 :     regs.sp[-1].setString(str);
    3814                 : }
    3815               0 : END_CASE(JSOP_ADDATTRNAME)
    3816                 : 
    3817                 : BEGIN_CASE(JSOP_BINDXMLNAME)
    3818                 : {
    3819              18 :     JS_ASSERT(!script->strictModeCode);
    3820                 : 
    3821                 :     Value lval;
    3822              18 :     lval = regs.sp[-1];
    3823                 :     JSObject *obj;
    3824                 :     jsid id;
    3825              18 :     if (!js_FindXMLProperty(cx, lval, &obj, &id))
    3826               0 :         goto error;
    3827              18 :     regs.sp[-1].setObjectOrNull(obj);
    3828              18 :     PUSH_COPY(IdToValue(id));
    3829                 : }
    3830              18 : END_CASE(JSOP_BINDXMLNAME)
    3831                 : 
    3832                 : BEGIN_CASE(JSOP_SETXMLNAME)
    3833                 : {
    3834              18 :     JS_ASSERT(!script->strictModeCode);
    3835                 : 
    3836              18 :     JSObject *obj = &regs.sp[-3].toObject();
    3837              18 :     Value rval = regs.sp[-1];
    3838                 :     jsid id;
    3839              18 :     FETCH_ELEMENT_ID(obj, -2, id);
    3840              18 :     if (!obj->setGeneric(cx, id, &rval, script->strictModeCode))
    3841               0 :         goto error;
    3842              18 :     rval = regs.sp[-1];
    3843              18 :     regs.sp -= 2;
    3844              18 :     regs.sp[-1] = rval;
    3845                 : }
    3846              18 : END_CASE(JSOP_SETXMLNAME)
    3847                 : 
    3848                 : BEGIN_CASE(JSOP_CALLXMLNAME)
    3849                 : BEGIN_CASE(JSOP_XMLNAME)
    3850                 : {
    3851              36 :     JS_ASSERT(!script->strictModeCode);
    3852                 : 
    3853              36 :     Value lval = regs.sp[-1];
    3854                 :     JSObject *obj;
    3855                 :     jsid id;
    3856              36 :     if (!js_FindXMLProperty(cx, lval, &obj, &id))
    3857              27 :         goto error;
    3858                 :     Value rval;
    3859               9 :     if (!obj->getGeneric(cx, id, &rval))
    3860               0 :         goto error;
    3861               9 :     regs.sp[-1] = rval;
    3862               9 :     if (op == JSOP_CALLXMLNAME) {
    3863                 :         Value v;
    3864               0 :         if (!ComputeImplicitThis(cx, obj, &v))
    3865               0 :             goto error;
    3866               0 :         PUSH_COPY(v);
    3867                 :     }
    3868                 : }
    3869               9 : END_CASE(JSOP_XMLNAME)
    3870                 : 
    3871                 : BEGIN_CASE(JSOP_DESCENDANTS)
    3872                 : BEGIN_CASE(JSOP_DELDESC)
    3873                 : {
    3874               9 :     JS_ASSERT(!script->strictModeCode);
    3875                 : 
    3876                 :     JSObject *obj;
    3877               9 :     FETCH_OBJECT(cx, -2, obj);
    3878               9 :     jsval rval = regs.sp[-1];
    3879               9 :     if (!js_GetXMLDescendants(cx, obj, rval, &rval))
    3880               0 :         goto error;
    3881                 : 
    3882               9 :     if (op == JSOP_DELDESC) {
    3883               0 :         regs.sp[-1] = rval;   /* set local root */
    3884               0 :         if (!js_DeleteXMLListElements(cx, JSVAL_TO_OBJECT(rval)))
    3885               0 :             goto error;
    3886               0 :         rval = JSVAL_TRUE;                  /* always succeed */
    3887                 :     }
    3888                 : 
    3889               9 :     regs.sp--;
    3890               9 :     regs.sp[-1] = rval;
    3891                 : }
    3892               9 : END_CASE(JSOP_DESCENDANTS)
    3893                 : 
    3894                 : BEGIN_CASE(JSOP_FILTER)
    3895                 : {
    3896              63 :     JS_ASSERT(!script->strictModeCode);
    3897                 : 
    3898                 :     /*
    3899                 :      * We push the hole value before jumping to [enditer] so we can detect the
    3900                 :      * first iteration and direct js_StepXMLListFilter to initialize filter's
    3901                 :      * state.
    3902                 :      */
    3903              63 :     PUSH_HOLE();
    3904              63 :     len = GET_JUMP_OFFSET(regs.pc);
    3905              63 :     JS_ASSERT(len > 0);
    3906                 : }
    3907              63 : END_VARLEN_CASE
    3908                 : 
    3909                 : BEGIN_CASE(JSOP_ENDFILTER)
    3910                 : {
    3911             126 :     JS_ASSERT(!script->strictModeCode);
    3912                 : 
    3913             126 :     bool cond = !regs.sp[-1].isMagic();
    3914             126 :     if (cond) {
    3915                 :         /* Exit the "with" block left from the previous iteration. */
    3916              63 :         LeaveWith(cx);
    3917                 :     }
    3918             126 :     if (!js_StepXMLListFilter(cx, cond))
    3919               9 :         goto error;
    3920             117 :     if (!regs.sp[-1].isNull()) {
    3921                 :         /*
    3922                 :          * Decrease sp after EnterWith returns as we use sp[-1] there to root
    3923                 :          * temporaries.
    3924                 :          */
    3925              63 :         JS_ASSERT(IsXML(regs.sp[-1]));
    3926              63 :         if (!EnterWith(cx, -2))
    3927               0 :             goto error;
    3928              63 :         regs.sp--;
    3929              63 :         len = GET_JUMP_OFFSET(regs.pc);
    3930              63 :         JS_ASSERT(len < 0);
    3931              63 :         BRANCH(len);
    3932                 :     }
    3933              54 :     regs.sp--;
    3934                 : }
    3935              54 : END_CASE(JSOP_ENDFILTER);
    3936                 : 
    3937                 : BEGIN_CASE(JSOP_TOXML)
    3938                 : {
    3939             596 :     JS_ASSERT(!script->strictModeCode);
    3940                 : 
    3941             596 :     Value rval = regs.sp[-1];
    3942             596 :     JSObject *obj = js_ValueToXMLObject(cx, rval);
    3943             596 :     if (!obj)
    3944               0 :         goto error;
    3945             596 :     regs.sp[-1].setObject(*obj);
    3946                 : }
    3947             596 : END_CASE(JSOP_TOXML)
    3948                 : 
    3949                 : BEGIN_CASE(JSOP_TOXMLLIST)
    3950                 : {
    3951              18 :     JS_ASSERT(!script->strictModeCode);
    3952                 : 
    3953              18 :     Value rval = regs.sp[-1];
    3954              18 :     JSObject *obj = js_ValueToXMLListObject(cx, rval);
    3955              18 :     if (!obj)
    3956               0 :         goto error;
    3957              18 :     regs.sp[-1].setObject(*obj);
    3958                 : }
    3959              18 : END_CASE(JSOP_TOXMLLIST)
    3960                 : 
    3961                 : BEGIN_CASE(JSOP_XMLTAGEXPR)
    3962                 : {
    3963               0 :     JS_ASSERT(!script->strictModeCode);
    3964                 : 
    3965               0 :     Value rval = regs.sp[-1];
    3966               0 :     JSString *str = ToString(cx, rval);
    3967               0 :     if (!str)
    3968               0 :         goto error;
    3969               0 :     regs.sp[-1].setString(str);
    3970                 : }
    3971               0 : END_CASE(JSOP_XMLTAGEXPR)
    3972                 : 
    3973                 : BEGIN_CASE(JSOP_XMLELTEXPR)
    3974                 : {
    3975               0 :     JS_ASSERT(!script->strictModeCode);
    3976                 : 
    3977               0 :     Value rval = regs.sp[-1];
    3978                 :     JSString *str;
    3979               0 :     if (IsXML(rval)) {
    3980               0 :         str = js_ValueToXMLString(cx, rval);
    3981                 :     } else {
    3982               0 :         str = ToString(cx, rval);
    3983               0 :         if (str)
    3984               0 :             str = js_EscapeElementValue(cx, str);
    3985                 :     }
    3986               0 :     if (!str)
    3987               0 :         goto error;
    3988               0 :     regs.sp[-1].setString(str);
    3989                 : }
    3990               0 : END_CASE(JSOP_XMLELTEXPR)
    3991                 : 
    3992                 : BEGIN_CASE(JSOP_XMLCDATA)
    3993                 : {
    3994               0 :     JS_ASSERT(!script->strictModeCode);
    3995                 : 
    3996               0 :     JSAtom *atom = script->getAtom(GET_UINT32_INDEX(regs.pc));
    3997               0 :     JSObject *obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_TEXT, NULL, atom);
    3998               0 :     if (!obj)
    3999               0 :         goto error;
    4000               0 :     PUSH_OBJECT(*obj);
    4001                 : }
    4002               0 : END_CASE(JSOP_XMLCDATA)
    4003                 : 
    4004                 : BEGIN_CASE(JSOP_XMLCOMMENT)
    4005                 : {
    4006               0 :     JS_ASSERT(!script->strictModeCode);
    4007                 : 
    4008               0 :     JSAtom *atom = script->getAtom(GET_UINT32_INDEX(regs.pc));
    4009               0 :     JSObject *obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_COMMENT, NULL, atom);
    4010               0 :     if (!obj)
    4011               0 :         goto error;
    4012               0 :     PUSH_OBJECT(*obj);
    4013                 : }
    4014               0 : END_CASE(JSOP_XMLCOMMENT)
    4015                 : 
    4016                 : BEGIN_CASE(JSOP_XMLPI)
    4017                 : {
    4018               0 :     JS_ASSERT(!script->strictModeCode);
    4019                 : 
    4020               0 :     JSAtom *atom = script->getAtom(GET_UINT32_INDEX(regs.pc));
    4021               0 :     Value rval = regs.sp[-1];
    4022               0 :     JSString *str2 = rval.toString();
    4023               0 :     JSObject *obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_PROCESSING_INSTRUCTION, atom, str2);
    4024               0 :     if (!obj)
    4025               0 :         goto error;
    4026               0 :     regs.sp[-1].setObject(*obj);
    4027                 : }
    4028               0 : END_CASE(JSOP_XMLPI)
    4029                 : 
    4030                 : BEGIN_CASE(JSOP_GETFUNNS)
    4031                 : {
    4032              36 :     JS_ASSERT(!script->strictModeCode);
    4033                 : 
    4034                 :     Value rval;
    4035              36 :     if (!cx->fp()->scopeChain().global().getFunctionNamespace(cx, &rval))
    4036               0 :         goto error;
    4037              36 :     PUSH_COPY(rval);
    4038                 : }
    4039              36 : END_CASE(JSOP_GETFUNNS)
    4040                 : #endif /* JS_HAS_XML_SUPPORT */
    4041                 : 
    4042                 : BEGIN_CASE(JSOP_ENTERBLOCK)
    4043                 : BEGIN_CASE(JSOP_ENTERLET0)
    4044                 : BEGIN_CASE(JSOP_ENTERLET1)
    4045                 : {
    4046          522229 :     StaticBlockObject &blockObj = script->getObject(GET_UINT32_INDEX(regs.pc))->asStaticBlock();
    4047          522229 :     JS_ASSERT(regs.fp()->maybeBlockChain() == blockObj.enclosingBlock());
    4048                 : 
    4049          522229 :     if (op == JSOP_ENTERBLOCK) {
    4050          367402 :         JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() == regs.sp);
    4051          367402 :         Value *vp = regs.sp + blockObj.slotCount();
    4052          367402 :         JS_ASSERT(regs.sp < vp);
    4053          367402 :         JS_ASSERT(vp <= regs.fp()->slots() + script->nslots);
    4054          367402 :         SetValueRangeToUndefined(regs.sp, vp);
    4055          367402 :         regs.sp = vp;
    4056          154827 :     } else if (op == JSOP_ENTERLET0) {
    4057           47771 :         JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() + blockObj.slotCount()
    4058           47771 :                   == regs.sp);
    4059          107056 :     } else if (op == JSOP_ENTERLET1) {
    4060          107056 :         JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() + blockObj.slotCount()
    4061          107056 :                   == regs.sp - 1);
    4062                 :     }
    4063                 : 
    4064                 : #ifdef DEBUG
    4065          522229 :     JS_ASSERT(regs.fp()->maybeBlockChain() == blockObj.enclosingBlock());
    4066                 : 
    4067                 :     /*
    4068                 :      * The young end of fp->scopeChain may omit blocks if we haven't closed
    4069                 :      * over them, but if there are any closure blocks on fp->scopeChain, they'd
    4070                 :      * better be (clones of) ancestors of the block we're entering now;
    4071                 :      * anything else we should have popped off fp->scopeChain when we left its
    4072                 :      * static scope.
    4073                 :      */
    4074          522229 :     JSObject *obj2 = &regs.fp()->scopeChain();
    4075         1044620 :     while (obj2->isWith())
    4076             162 :         obj2 = &obj2->asWith().enclosingScope();
    4077          531457 :     if (obj2->isBlock() &&
    4078            9228 :         obj2->getPrivate() == js_FloatingFrameIfGenerator(cx, regs.fp()))
    4079                 :     {
    4080            7959 :         StaticBlockObject &youngestProto = obj2->asClonedBlock().staticBlock();
    4081            7959 :         StaticBlockObject *parent = &blockObj;
    4082           17203 :         while ((parent = parent->enclosingBlock()) != &youngestProto)
    4083            1285 :             JS_ASSERT(parent);
    4084                 :     }
    4085                 : #endif
    4086                 : 
    4087          522229 :     regs.fp()->setBlockChain(&blockObj);
    4088                 : }
    4089          522229 : END_CASE(JSOP_ENTERBLOCK)
    4090                 : 
    4091                 : BEGIN_CASE(JSOP_LEAVEBLOCK)
    4092                 : BEGIN_CASE(JSOP_LEAVEFORLETIN)
    4093                 : BEGIN_CASE(JSOP_LEAVEBLOCKEXPR)
    4094                 : {
    4095          522666 :     StaticBlockObject &blockObj = regs.fp()->blockChain();
    4096          522666 :     JS_ASSERT(blockObj.stackDepth() <= StackDepth(script));
    4097                 : 
    4098                 :     /*
    4099                 :      * If we're about to leave the dynamic scope of a block that has been
    4100                 :      * cloned onto fp->scopeChain, clear its private data, move its locals from
    4101                 :      * the stack into the clone, and pop it off the chain.
    4102                 :      */
    4103          522666 :     JSObject &scope = regs.fp()->scopeChain();
    4104          522666 :     if (scope.getProto() == &blockObj)
    4105           17206 :         scope.asClonedBlock().put(cx);
    4106                 : 
    4107          522666 :     regs.fp()->setBlockChain(blockObj.enclosingBlock());
    4108                 : 
    4109          522666 :     if (op == JSOP_LEAVEBLOCK) {
    4110                 :         /* Pop the block's slots. */
    4111          425996 :         regs.sp -= GET_UINT16(regs.pc);
    4112          425996 :         JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() == regs.sp);
    4113           96670 :     } else if (op == JSOP_LEAVEBLOCKEXPR) {
    4114                 :         /* Pop the block's slots maintaining the topmost expr. */
    4115             930 :         Value *vp = &regs.sp[-1];
    4116             930 :         regs.sp -= GET_UINT16(regs.pc);
    4117             930 :         JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() == regs.sp - 1);
    4118             930 :         regs.sp[-1] = *vp;
    4119                 :     } else {
    4120                 :         /* Another op will pop; nothing to do here. */
    4121           95740 :         len = JSOP_LEAVEFORLETIN_LENGTH;
    4122           95740 :         DO_NEXT_OP(len);
    4123                 :     }
    4124                 : }
    4125          426926 : END_CASE(JSOP_LEAVEBLOCK)
    4126                 : 
    4127                 : #if JS_HAS_GENERATORS
    4128                 : BEGIN_CASE(JSOP_GENERATOR)
    4129                 : {
    4130           12235 :     JS_ASSERT(!cx->isExceptionPending());
    4131           12235 :     regs.pc += JSOP_GENERATOR_LENGTH;
    4132           12235 :     JSObject *obj = js_NewGenerator(cx);
    4133           12235 :     if (!obj)
    4134               0 :         goto error;
    4135           12235 :     JS_ASSERT(!regs.fp()->hasCallObj() && !regs.fp()->hasArgsObj());
    4136           12235 :     regs.fp()->setReturnValue(ObjectValue(*obj));
    4137           12235 :     interpReturnOK = true;
    4138           12235 :     if (entryFrame != regs.fp())
    4139            9940 :         goto inline_return;
    4140            2295 :     goto exit;
    4141                 : }
    4142                 : 
    4143                 : BEGIN_CASE(JSOP_YIELD)
    4144           44646 :     JS_ASSERT(!cx->isExceptionPending());
    4145           44646 :     JS_ASSERT(regs.fp()->isNonEvalFunctionFrame());
    4146           44646 :     if (cx->generatorFor(regs.fp())->state == JSGEN_CLOSING) {
    4147               0 :         js_ReportValueError(cx, JSMSG_BAD_GENERATOR_YIELD,
    4148               0 :                             JSDVG_SEARCH_STACK, argv[-2], NULL);
    4149               0 :         goto error;
    4150                 :     }
    4151           44646 :     regs.fp()->setReturnValue(regs.sp[-1]);
    4152           44646 :     regs.fp()->setYielding();
    4153           44646 :     regs.pc += JSOP_YIELD_LENGTH;
    4154           44646 :     interpReturnOK = true;
    4155           44646 :     goto exit;
    4156                 : 
    4157                 : BEGIN_CASE(JSOP_ARRAYPUSH)
    4158                 : {
    4159          940721 :     uint32_t slot = GET_UINT16(regs.pc);
    4160          940721 :     JS_ASSERT(script->nfixed <= slot);
    4161          940721 :     JS_ASSERT(slot < script->nslots);
    4162          940721 :     JSObject *obj = &regs.fp()->slots()[slot].toObject();
    4163          940721 :     if (!js_NewbornArrayPush(cx, obj, regs.sp[-1]))
    4164               0 :         goto error;
    4165          940721 :     regs.sp--;
    4166                 : }
    4167          940721 : END_CASE(JSOP_ARRAYPUSH)
    4168                 : #endif /* JS_HAS_GENERATORS */
    4169                 : 
    4170                 : #if JS_THREADED_INTERP
    4171                 :   L_JSOP_BACKPATCH:
    4172                 :   L_JSOP_BACKPATCH_POP:
    4173                 : 
    4174                 : # if !JS_HAS_GENERATORS
    4175                 :   L_JSOP_GENERATOR:
    4176                 :   L_JSOP_YIELD:
    4177                 :   L_JSOP_ARRAYPUSH:
    4178                 : # endif
    4179                 : 
    4180                 : # if !JS_HAS_DESTRUCTURING
    4181                 :   L_JSOP_ENUMCONSTELEM:
    4182                 : # endif
    4183                 : 
    4184                 : # if !JS_HAS_XML_SUPPORT
    4185                 :   L_JSOP_CALLXMLNAME:
    4186                 :   L_JSOP_STARTXMLEXPR:
    4187                 :   L_JSOP_STARTXML:
    4188                 :   L_JSOP_DELDESC:
    4189                 :   L_JSOP_GETFUNNS:
    4190                 :   L_JSOP_XMLPI:
    4191                 :   L_JSOP_XMLCOMMENT:
    4192                 :   L_JSOP_XMLCDATA:
    4193                 :   L_JSOP_XMLELTEXPR:
    4194                 :   L_JSOP_XMLTAGEXPR:
    4195                 :   L_JSOP_TOXMLLIST:
    4196                 :   L_JSOP_TOXML:
    4197                 :   L_JSOP_ENDFILTER:
    4198                 :   L_JSOP_FILTER:
    4199                 :   L_JSOP_DESCENDANTS:
    4200                 :   L_JSOP_XMLNAME:
    4201                 :   L_JSOP_SETXMLNAME:
    4202                 :   L_JSOP_BINDXMLNAME:
    4203                 :   L_JSOP_ADDATTRVAL:
    4204                 :   L_JSOP_ADDATTRNAME:
    4205                 :   L_JSOP_TOATTRVAL:
    4206                 :   L_JSOP_TOATTRNAME:
    4207                 :   L_JSOP_QNAME:
    4208                 :   L_JSOP_QNAMECONST:
    4209                 :   L_JSOP_QNAMEPART:
    4210                 :   L_JSOP_ANYNAME:
    4211                 :   L_JSOP_DEFXMLNS:
    4212                 : # endif
    4213                 : 
    4214                 : #endif /* !JS_THREADED_INTERP */
    4215                 : #if !JS_THREADED_INTERP
    4216                 :           default:
    4217                 : #endif
    4218                 :           {
    4219                 :             char numBuf[12];
    4220               0 :             JS_snprintf(numBuf, sizeof numBuf, "%d", op);
    4221                 :             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
    4222               0 :                                  JSMSG_BAD_BYTECODE, numBuf);
    4223               0 :             goto error;
    4224                 :           }
    4225                 : 
    4226                 : #if !JS_THREADED_INTERP
    4227                 :         } /* switch (op) */
    4228                 :     } /* for (;;) */
    4229                 : #endif /* !JS_THREADED_INTERP */
    4230                 : 
    4231                 :   error:
    4232         2099517 :     JS_ASSERT(&cx->regs() == &regs);
    4233         2099517 :     JS_ASSERT(uint32_t(regs.pc - script->code) < script->length);
    4234                 : 
    4235         2099517 :     if (cx->isExceptionPending()) {
    4236                 :         /* Restore atoms local in case we will resume. */
    4237         2097348 :         atoms = script->atoms;
    4238                 : 
    4239                 :         /* Call debugger throw hook if set. */
    4240         2097348 :         if (cx->runtime->debugHooks.throwHook || !cx->compartment->getDebuggees().empty()) {
    4241                 :             Value rval;
    4242           29473 :             JSTrapStatus st = Debugger::onExceptionUnwind(cx, &rval);
    4243           29473 :             if (st == JSTRAP_CONTINUE) {
    4244           29438 :                 if (JSThrowHook handler = cx->runtime->debugHooks.throwHook)
    4245           28774 :                     st = handler(cx, script, regs.pc, &rval, cx->runtime->debugHooks.throwHookData);
    4246                 :             }
    4247                 : 
    4248           29473 :             switch (st) {
    4249                 :               case JSTRAP_ERROR:
    4250              20 :                 cx->clearPendingException();
    4251              20 :                 goto error;
    4252                 :               case JSTRAP_RETURN:
    4253              15 :                 cx->clearPendingException();
    4254              15 :                 regs.fp()->setReturnValue(rval);
    4255              15 :                 interpReturnOK = true;
    4256              15 :                 goto forced_return;
    4257                 :               case JSTRAP_THROW:
    4258               5 :                 cx->setPendingException(rval);
    4259                 :               case JSTRAP_CONTINUE:
    4260                 :               default:;
    4261                 :             }
    4262           29438 :             CHECK_INTERRUPT_HANDLER();
    4263                 :         }
    4264                 : 
    4265         2100078 :         for (TryNoteIter tni(regs); !tni.done(); ++tni) {
    4266           32127 :             JSTryNote *tn = *tni;
    4267                 : 
    4268           32127 :             UnwindScope(cx, tn->stackDepth);
    4269                 : 
    4270                 :             /*
    4271                 :              * Set pc to the first bytecode after the the try note to point
    4272                 :              * to the beginning of catch or finally or to [enditer] closing
    4273                 :              * the for-in loop.
    4274                 :              */
    4275           32127 :             regs.pc = (script)->main() + tn->start + tn->length;
    4276           32127 :             regs.sp = regs.fp()->base() + tn->stackDepth;
    4277                 : 
    4278           32127 :             switch (tn->kind) {
    4279                 :               case JSTRY_CATCH:
    4280           30228 :                   JS_ASSERT(*regs.pc == JSOP_ENTERBLOCK);
    4281                 : 
    4282                 : #if JS_HAS_GENERATORS
    4283                 :                 /* Catch cannot intercept the closing of a generator. */
    4284           30228 :                   if (JS_UNLIKELY(cx->getPendingException().isMagic(JS_GENERATOR_CLOSING)))
    4285            2660 :                     break;
    4286                 : #endif
    4287                 : 
    4288                 :                 /*
    4289                 :                  * Don't clear exceptions to save cx->exception from GC
    4290                 :                  * until it is pushed to the stack via [exception] in the
    4291                 :                  * catch block.
    4292                 :                  */
    4293           27568 :                 len = 0;
    4294           27568 :                 DO_NEXT_OP(len);
    4295                 : 
    4296                 :               case JSTRY_FINALLY:
    4297                 :                 /*
    4298                 :                  * Push (true, exception) pair for finally to indicate that
    4299                 :                  * [retsub] should rethrow the exception.
    4300                 :                  */
    4301            1788 :                 PUSH_BOOLEAN(true);
    4302            1788 :                 PUSH_COPY(cx->getPendingException());
    4303            1788 :                 cx->clearPendingException();
    4304            1788 :                 len = 0;
    4305            1788 :                 DO_NEXT_OP(len);
    4306                 : 
    4307                 :               case JSTRY_ITER: {
    4308                 :                 /* This is similar to JSOP_ENDITER in the interpreter loop. */
    4309             111 :                 JS_ASSERT(JSOp(*regs.pc) == JSOP_ENDITER);
    4310             111 :                 bool ok = UnwindIteratorForException(cx, &regs.sp[-1].toObject());
    4311             111 :                 regs.sp -= 1;
    4312             111 :                 if (!ok)
    4313               6 :                     goto error;
    4314                 :               }
    4315                 :            }
    4316                 :         }
    4317                 : 
    4318                 :         /*
    4319                 :          * Propagate the exception or error to the caller unless the exception
    4320                 :          * is an asynchronous return from a generator.
    4321                 :          */
    4322         2067951 :         interpReturnOK = false;
    4323                 : #if JS_HAS_GENERATORS
    4324         2067951 :         if (JS_UNLIKELY(cx->isExceptionPending() &&
    4325                 :                         cx->getPendingException().isMagic(JS_GENERATOR_CLOSING))) {
    4326            1461 :             cx->clearPendingException();
    4327            1461 :             interpReturnOK = true;
    4328            1461 :             regs.fp()->clearReturnValue();
    4329                 :         }
    4330                 : #endif
    4331                 :     } else {
    4332            2169 :         UnwindForUncatchableException(cx, regs);
    4333            2169 :         interpReturnOK = false;
    4334                 :     }
    4335                 : 
    4336                 :   forced_return:
    4337         2070348 :     UnwindScope(cx, 0);
    4338         2070348 :     regs.sp = regs.fp()->base();
    4339                 : 
    4340         2070348 :     if (entryFrame != regs.fp())
    4341         2004216 :         goto inline_return;
    4342                 : 
    4343                 :   exit:
    4344         1996463 :     if (cx->compartment->debugMode())
    4345          653749 :         interpReturnOK = ScriptDebugEpilogue(cx, regs.fp(), interpReturnOK);
    4346         1996463 :     interpReturnOK = ScriptEpilogueOrGeneratorYield(cx, regs.fp(), interpReturnOK);
    4347         1996463 :     regs.fp()->setFinishedInInterpreter();
    4348                 : 
    4349                 :     /*
    4350                 :      * At this point we are inevitably leaving an interpreted function or a
    4351                 :      * top-level script, and returning to one of:
    4352                 :      * (a) an "out of line" call made through Invoke;
    4353                 :      * (b) a js_Execute activation;
    4354                 :      * (c) a generator (SendToGenerator, jsiter.c).
    4355                 :      *
    4356                 :      * We must not be in an inline frame. The check above ensures that for the
    4357                 :      * error case and for a normal return, the code jumps directly to parent's
    4358                 :      * frame pc.
    4359                 :      */
    4360         1996463 :     JS_ASSERT(entryFrame == regs.fp());
    4361         1996463 :     if (!regs.fp()->isGeneratorFrame()) {
    4362         1944142 :         JS_ASSERT(!IsActiveWithOrBlock(cx, regs.fp()->scopeChain(), 0));
    4363         1944142 :         JS_ASSERT(!regs.fp()->hasBlockChain());
    4364                 :     }
    4365                 : 
    4366                 : #ifdef JS_METHODJIT
    4367                 :     /*
    4368                 :      * This path is used when it's guaranteed the method can be finished
    4369                 :      * inside the JIT.
    4370                 :      */
    4371                 :   leave_on_safe_point:
    4372                 : #endif
    4373                 : 
    4374         1997347 :     gc::MaybeVerifyBarriers(cx, true);
    4375         1997347 :     return interpReturnOK;
    4376                 : }

Generated by: LCOV version 1.7