LCOV - code coverage report
Current view: directory - js/src - jsinterp.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 1807 1525 84.4 %
Date: 2012-06-02 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          876394 : js::GetScopeChain(JSContext *cx, StackFrame *fp)
     140                 : {
     141          876394 :     StaticBlockObject *sharedBlock = fp->maybeBlockChain();
     142                 : 
     143          876394 :     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         2386458 :         JS_ASSERT_IF(fp->isNonEvalFunctionFrame() && fp->fun()->isHeavyweight(),
     149         2386458 :                      fp->hasCallObj());
     150          847227 :         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           29167 :     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           29166 :         limitClone = &fp->scopeChain();
     176           58404 :         while (limitClone->isWith())
     177              72 :             limitClone = &limitClone->asWith().enclosingScope();
     178           29166 :         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           29166 :         limitBlock = limitClone->getProto();
     199                 : 
     200                 :         /* If the innermost block has already been cloned, we are done. */
     201           29166 :         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           17737 :     ClonedBlockObject *innermostNewChild = ClonedBlockObject::create(cx, *sharedBlock, fp);
     212           17737 :     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           17737 :     ClonedBlockObject *newChild = innermostNewChild;
     220             901 :     for (;;) {
     221           18638 :         JS_ASSERT(newChild->getProto() == sharedBlock);
     222           18638 :         sharedBlock = sharedBlock->enclosingBlock();
     223                 : 
     224                 :         /* Sometimes limitBlock will be NULL, so check that first.  */
     225           18638 :         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           17737 :     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           23627 :                  sharedBlock);
     249                 : 
     250                 :     /* Place our newly cloned blocks at the head of the scope chain.  */
     251           17737 :     fp->setScopeChainNoCallObj(*innermostNewChild);
     252           17737 :     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          361902 : 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          361902 :     Value &thisv = call.thisv();
     320          361902 :     JS_ASSERT(!thisv.isMagic());
     321                 : 
     322                 : #ifdef DEBUG
     323          361902 :     JSFunction *fun = call.callee().isFunction() ? call.callee().toFunction() : NULL;
     324          361902 :     JS_ASSERT_IF(fun && fun->isInterpreted(), !fun->inStrictMode());
     325                 : #endif
     326                 : 
     327          361902 :     if (thisv.isNullOrUndefined()) {
     328           64909 :         JSObject *thisp = call.callee().global().thisObject(cx);
     329           64909 :         if (!thisp)
     330               0 :             return false;
     331           64909 :         call.thisv().setObject(*thisp);
     332           64909 :         return true;
     333                 :     }
     334                 : 
     335          296993 :     if (!thisv.isObject())
     336             479 :         return !!js_PrimitiveToObject(cx, &thisv);
     337                 : 
     338          296514 :     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            1227 : js::OnUnknownMethod(JSContext *cx, JSObject *obj, Value idval, Value *vp)
     369                 : {
     370            1227 :     jsid id = ATOM_TO_JSID(cx->runtime->atomState.noSuchMethodAtom);
     371            2454 :     AutoValueRooter tvr(cx);
     372            1227 :     if (!js_GetMethod(cx, obj, id, JSGET_NO_METHOD_BARRIER, tvr.addr()))
     373               0 :         return false;
     374            1227 :     TypeScript::MonitorUnknown(cx, cx->fp()->script(), cx->regs().pc);
     375                 : 
     376            1227 :     if (tvr.value().isPrimitive()) {
     377             498 :         *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            1227 :     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         5428662 : js::RunScript(JSContext *cx, JSScript *script, StackFrame *fp)
     427                 : {
     428         5428662 :     JS_ASSERT(script);
     429         5428662 :     JS_ASSERT(fp == cx->fp());
     430         5428662 :     JS_ASSERT(fp->script() == script);
     431                 : #ifdef JS_METHODJIT_SPEW
     432         5428662 :     JMCheckLogging();
     433                 : #endif
     434                 : 
     435                 :     /* FIXME: Once bug 470510 is fixed, make this an assert. */
     436         5428662 :     if (script->compileAndGo) {
     437         1536069 :         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         5428662 :         CheckStackBalance(JSContext *cx)
     449         5428662 :           : cx(cx), fp(cx->fp()), enumerators(cx->enumerators)
     450         5428662 :         {}
     451         5428662 :         ~CheckStackBalance() {
     452         5428662 :             JS_ASSERT(fp == cx->fp());
     453         5428662 :             JS_ASSERT_IF(!fp->isGeneratorFrame(), enumerators == cx->enumerators);
     454         5428662 :         }
     455        10857324 :     } check(cx);
     456                 : #endif
     457                 : 
     458                 : #ifdef JS_METHODJIT
     459                 :     mjit::CompileStatus status;
     460         5428662 :     status = mjit::CanMethodJIT(cx, script, script->code, fp->isConstructing(),
     461         5428662 :                                 mjit::CompileRequest_Interpreter);
     462         5428662 :     if (status == mjit::Compile_Error)
     463               0 :         return false;
     464                 : 
     465         5428662 :     if (status == mjit::Compile_Okay)
     466         3563828 :         return mjit::JaegerStatusToSuccess(mjit::JaegerShot(cx, false));
     467                 : #endif
     468                 : 
     469         1864834 :     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        20074332 : js::InvokeKernel(JSContext *cx, CallArgs args, MaybeConstruct construct)
     480                 : {
     481        20074332 :     JS_ASSERT(args.length() <= StackSpace::ARGS_LENGTH_MAX);
     482                 : 
     483        20074332 :     JS_ASSERT(!cx->compartment->activeAnalysis);
     484                 : 
     485                 :     /* MaybeConstruct is a subset of InitialFrameFlags */
     486        20074332 :     InitialFrameFlags initial = (InitialFrameFlags) construct;
     487                 : 
     488        20074332 :     if (args.calleev().isPrimitive()) {
     489             786 :         js_ReportIsNotFunction(cx, &args.calleev(), ToReportFlags(initial));
     490             786 :         return false;
     491                 :     }
     492                 : 
     493        20073546 :     JSObject &callee = args.callee();
     494        20073546 :     Class *clasp = callee.getClass();
     495                 : 
     496                 :     /* Invoke non-functions. */
     497        20073546 :     if (JS_UNLIKELY(clasp != &FunctionClass)) {
     498                 : #if JS_HAS_NO_SUCH_METHOD
     499           40431 :         if (JS_UNLIKELY(clasp == &js_NoSuchMethodClass))
     500             729 :             return NoSuchMethod(cx, args.length(), args.base());
     501                 : #endif
     502           39702 :         JS_ASSERT_IF(construct, !clasp->construct);
     503           39702 :         if (!clasp->call) {
     504              91 :             js_ReportIsNotFunction(cx, &args.calleev(), ToReportFlags(initial));
     505              91 :             return false;
     506                 :         }
     507           39611 :         return CallJSNative(cx, clasp->call, args);
     508                 :     }
     509                 : 
     510                 :     /* Invoke native functions. */
     511        20033115 :     JSFunction *fun = callee.toFunction();
     512        20033115 :     JS_ASSERT_IF(construct, !fun->isNativeConstructor());
     513        20033115 :     if (fun->isNative())
     514        14814852 :         return CallJSNative(cx, fun->u.n.native, args);
     515                 : 
     516         5218263 :     TypeMonitorCall(cx, args, construct);
     517                 : 
     518                 :     /* Get pointer to new frame/slots, prepare arguments. */
     519        10436526 :     InvokeFrameGuard ifg;
     520         5218263 :     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         5218235 :     StackFrame *fp = ifg.fp();
     525         5218235 :     if (!fp->functionPrologue(cx))
     526               0 :         return false;
     527                 : 
     528                 :     /* Run function until JSOP_STOP, JSOP_RETURN or error. */
     529         5218235 :     JSBool ok = RunScript(cx, fun->script(), fp);
     530                 : 
     531                 :     /* Propagate the return value out. */
     532         5218235 :     args.rval() = fp->returnValue();
     533         5218235 :     JS_ASSERT_IF(ok && construct, !args.rval().isPrimitive());
     534         5218235 :     return ok;
     535                 : }
     536                 : 
     537                 : bool
     538         5223509 : js::Invoke(JSContext *cx, const Value &thisv, const Value &fval, unsigned argc, Value *argv,
     539                 :            Value *rval)
     540                 : {
     541        10447018 :     InvokeArgsGuard args;
     542         5223509 :     if (!cx->stack.pushInvokeArgs(cx, argc, &args))
     543               0 :         return false;
     544                 : 
     545         5223509 :     args.calleev() = fval;
     546         5223509 :     args.thisv() = thisv;
     547         5223509 :     PodCopy(args.array(), argv, argc);
     548                 : 
     549         5223509 :     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         5221520 :         JSObject *thisp = args.thisv().toObject().thisObject(cx);
     556         5221520 :         if (!thisp)
     557               0 :              return false;
     558         5221520 :         args.thisv().setObject(*thisp);
     559                 :     }
     560                 : 
     561         5223509 :     if (!Invoke(cx, args))
     562           89664 :         return false;
     563                 : 
     564         5133845 :     *rval = args.rval();
     565         5133845 :     return true;
     566                 : }
     567                 : 
     568                 : bool
     569          266525 : js::InvokeConstructorKernel(JSContext *cx, const CallArgs &argsRef)
     570                 : {
     571          266525 :     JS_ASSERT(!FunctionClass.construct);
     572          266525 :     CallArgs args = argsRef;
     573                 : 
     574          266525 :     args.thisv().setMagic(JS_IS_CONSTRUCTING);
     575                 : 
     576          266525 :     if (args.calleev().isObject()) {
     577          266498 :         JSObject *callee = &args.callee();
     578          266498 :         Class *clasp = callee->getClass();
     579          266498 :         if (clasp == &FunctionClass) {
     580          218571 :             JSFunction *fun = callee->toFunction();
     581                 : 
     582          218571 :             if (fun->isNativeConstructor()) {
     583          218004 :                 Probes::calloutBegin(cx, fun);
     584          218004 :                 bool ok = CallJSNativeConstructor(cx, fun->u.n.native, args);
     585          218004 :                 Probes::calloutEnd(cx, fun);
     586          218004 :                 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           47927 :         if (clasp->construct)
     599           47918 :             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            8017 : js::InvokeConstructor(JSContext *cx, const Value &fval, unsigned argc, Value *argv, Value *rval)
     609                 : {
     610           16034 :     InvokeArgsGuard args;
     611            8017 :     if (!cx->stack.pushInvokeArgs(cx, argc, &args))
     612               0 :         return false;
     613                 : 
     614            8017 :     args.calleev() = fval;
     615            8017 :     args.thisv().setMagic(JS_THIS_POISON);
     616            8017 :     PodCopy(args.array(), argv, argc);
     617                 : 
     618            8017 :     if (!InvokeConstructor(cx, args))
     619              72 :         return false;
     620                 : 
     621            7945 :     *rval = args.rval();
     622            7945 :     return true;
     623                 : }
     624                 : 
     625                 : bool
     626         3365844 : 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         3365844 :     JS_CHECK_RECURSION(cx, return false);
     634                 : 
     635         3365838 :     return Invoke(cx, ObjectValue(*obj), fval, argc, argv, rval);
     636                 : }
     637                 : 
     638                 : bool
     639          180093 : js::ExecuteKernel(JSContext *cx, JSScript *script, JSObject &scopeChain, const Value &thisv,
     640                 :                   ExecuteType type, StackFrame *evalInFrame, Value *result)
     641                 : {
     642          180093 :     JS_ASSERT_IF(evalInFrame, type == EXECUTE_DEBUG);
     643                 : 
     644          360186 :     Root<JSScript*> scriptRoot(cx, &script);
     645                 : 
     646          180093 :     if (script->isEmpty()) {
     647             500 :         if (result)
     648             490 :             result->setUndefined();
     649             500 :         return true;
     650                 :     }
     651                 : 
     652          359186 :     ExecuteFrameGuard efg;
     653          179593 :     if (!cx->stack.pushExecuteFrame(cx, script, thisv, scopeChain, type, evalInFrame, &efg))
     654               0 :         return false;
     655                 : 
     656          179593 :     if (!script->ensureRanAnalysis(cx, &scopeChain))
     657               0 :         return false;
     658                 : 
     659                 :     /* Give strict mode eval its own fresh lexical environment. */
     660          179593 :     StackFrame *fp = efg.fp();
     661          179593 :     if (fp->isStrictEvalFrame() && !CallObject::createForStrictEval(cx, fp))
     662               0 :         return false;
     663                 : 
     664          179593 :     Probes::startExecution(cx, script);
     665                 : 
     666          179593 :     TypeScript::SetThis(cx, script, fp->thisValue());
     667                 : 
     668          179593 :     bool ok = RunScript(cx, script, fp);
     669                 : 
     670          179593 :     if (fp->isStrictEvalFrame())
     671            1908 :         js_PutCallObject(fp);
     672                 : 
     673          179593 :     Probes::stopExecution(cx, script);
     674                 : 
     675                 :     /* Propgate the return value out. */
     676          179593 :     if (result)
     677          130137 :         *result = fp->returnValue();
     678          179593 :     return ok;
     679                 : }
     680                 : 
     681                 : bool
     682           84280 : js::Execute(JSContext *cx, JSScript *script, JSObject &scopeChainArg, Value *rval)
     683                 : {
     684                 :     /* The scope chain could be anything, so innerize just in case. */
     685           84280 :     JSObject *scopeChain = &scopeChainArg;
     686           84280 :     OBJ_TO_INNER_OBJECT(cx, scopeChain);
     687           84280 :     if (!scopeChain)
     688               0 :         return false;
     689                 : 
     690                 :     /* If we were handed a non-native object, complain bitterly. */
     691           84280 :     if (!scopeChain->isNative()) {
     692               0 :         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NON_NATIVE_SCOPE);
     693               0 :         return false;
     694                 :     }
     695           84280 :     JS_ASSERT(!scopeChain->getOps()->defineProperty);
     696                 : 
     697                 :     /* The VAROBJFIX option makes varObj == globalObj in global code. */
     698           84280 :     if (!cx->hasRunOption(JSOPTION_VAROBJFIX)) {
     699           84050 :         if (!scopeChain->setVarObj(cx))
     700               0 :             return false;
     701                 :     }
     702                 : 
     703                 :     /* Use the scope chain as 'this', modulo outerization. */
     704           84280 :     JSObject *thisObj = scopeChain->thisObject(cx);
     705           84280 :     if (!thisObj)
     706               0 :         return false;
     707           84280 :     Value thisv = ObjectValue(*thisObj);
     708                 : 
     709                 :     return ExecuteKernel(cx, script, *scopeChain, thisv, EXECUTE_GLOBAL,
     710           84280 :                          NULL /* evalInFrame */, rval);
     711                 : }
     712                 : 
     713                 : JSBool
     714         1228738 : js::HasInstance(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp)
     715                 : {
     716         1228738 :     Class *clasp = obj->getClass();
     717         1228738 :     if (clasp->hasInstance)
     718         1228720 :         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         5265784 : js::LooselyEqual(JSContext *cx, const Value &lval, const Value &rval, bool *result)
     726                 : {
     727                 : #if JS_HAS_XML_SUPPORT
     728        10619061 :     if (JS_UNLIKELY(lval.isObject() && lval.toObject().isXML()) ||
     729         5353277 :                     (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         5265775 :     if (SameType(lval, rval)) {
     739         4975314 :         if (lval.isString()) {
     740          961545 :             JSString *l = lval.toString();
     741          961545 :             JSString *r = rval.toString();
     742          961545 :             return EqualStrings(cx, l, r, result);
     743                 :         }
     744                 : 
     745         4013769 :         if (lval.isDouble()) {
     746           45988 :             double l = lval.toDouble(), r = rval.toDouble();
     747           45988 :             *result = (l == r);
     748           45988 :             return true;
     749                 :         }
     750                 : 
     751         3967781 :         if (lval.isObject()) {
     752           79129 :             JSObject *l = &lval.toObject();
     753           79129 :             JSObject *r = &rval.toObject();
     754                 : 
     755           79129 :             if (JSEqualityOp eq = l->getClass()->ext.equality) {
     756                 :                 JSBool res;
     757            1441 :                 if (!eq(cx, l, &rval, &res))
     758               0 :                     return false;
     759            1441 :                 *result = !!res;
     760            1441 :                 return true;
     761                 :             }
     762                 : 
     763           77688 :             *result = l == r;
     764           77688 :             return true;
     765                 :         }
     766                 : 
     767         3888652 :         *result = lval.payloadAsRawUint32() == rval.payloadAsRawUint32();
     768         3888652 :         return true;
     769                 :     }
     770                 : 
     771          290461 :     if (lval.isNullOrUndefined()) {
     772           22549 :         *result = rval.isNullOrUndefined();
     773           22549 :         return true;
     774                 :     }
     775                 : 
     776          267912 :     if (rval.isNullOrUndefined()) {
     777          243576 :         *result = false;
     778          243576 :         return true;
     779                 :     }
     780                 : 
     781           24336 :     Value lvalue = lval;
     782           24336 :     Value rvalue = rval;
     783                 : 
     784           24336 :     if (!ToPrimitive(cx, &lvalue))
     785               5 :         return false;
     786           24331 :     if (!ToPrimitive(cx, &rvalue))
     787               0 :         return false;
     788                 : 
     789           24331 :     if (lvalue.isString() && rvalue.isString()) {
     790            5032 :         JSString *l = lvalue.toString();
     791            5032 :         JSString *r = rvalue.toString();
     792            5032 :         return EqualStrings(cx, l, r, result);
     793                 :     }
     794                 : 
     795                 :     double l, r;
     796           19299 :     if (!ToNumber(cx, lvalue, &l) || !ToNumber(cx, rvalue, &r))
     797               0 :         return false;
     798           19299 :     *result = (l == r);
     799           19299 :     return true;
     800                 : }
     801                 : 
     802                 : bool
     803        12458319 : js::StrictlyEqual(JSContext *cx, const Value &lref, const Value &rref, bool *equal)
     804                 : {
     805        12458319 :     Value lval = lref, rval = rref;
     806        12458319 :     if (SameType(lval, rval)) {
     807        11095830 :         if (lval.isString())
     808         1234982 :             return EqualStrings(cx, lval.toString(), rval.toString(), equal);
     809         9860848 :         if (lval.isDouble()) {
     810         1055900 :             *equal = (lval.toDouble() == rval.toDouble());
     811         1055900 :             return true;
     812                 :         }
     813         8804948 :         if (lval.isObject()) {
     814          720818 :             *equal = lval.toObject() == rval.toObject();
     815          720818 :             return true;
     816                 :         }
     817         8084130 :         if (lval.isUndefined()) {
     818         1203851 :             *equal = true;
     819         1203851 :             return true;
     820                 :         }
     821         6880279 :         *equal = lval.payloadAsRawUint32() == rval.payloadAsRawUint32();
     822         6880279 :         return true;
     823                 :     }
     824                 : 
     825         1362489 :     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         1354830 :     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         1346005 :     *equal = false;
     839         1346005 :     return true;
     840                 : }
     841                 : 
     842                 : static inline bool
     843        10613692 : IsNegativeZero(const Value &v)
     844                 : {
     845        10613692 :     return v.isDouble() && JSDOUBLE_IS_NEGZERO(v.toDouble());
     846                 : }
     847                 : 
     848                 : static inline bool
     849         5308800 : IsNaN(const Value &v)
     850                 : {
     851         5308800 :     return v.isDouble() && JSDOUBLE_IS_NaN(v.toDouble());
     852                 : }
     853                 : 
     854                 : bool
     855         5306846 : js::SameValue(JSContext *cx, const Value &v1, const Value &v2, bool *same)
     856                 : {
     857         5306846 :     if (IsNegativeZero(v1)) {
     858             621 :         *same = IsNegativeZero(v2);
     859             621 :         return true;
     860                 :     }
     861         5306225 :     if (IsNegativeZero(v2)) {
     862               1 :         *same = false;
     863               1 :         return true;
     864                 :     }
     865         5306224 :     if (IsNaN(v1) && IsNaN(v2)) {
     866            2576 :         *same = true;
     867            2576 :         return true;
     868                 :     }
     869         5303648 :     return StrictlyEqual(cx, v1, v2, same);
     870                 : }
     871                 : 
     872                 : JSType
     873         7243639 : js::TypeOfValue(JSContext *cx, const Value &vref)
     874                 : {
     875         7243639 :     Value v = vref;
     876         7243639 :     if (v.isNumber())
     877           40851 :         return JSTYPE_NUMBER;
     878         7202788 :     if (v.isString())
     879          152464 :         return JSTYPE_STRING;
     880         7050324 :     if (v.isNull())
     881            4434 :         return JSTYPE_OBJECT;
     882         7045890 :     if (v.isUndefined())
     883           51901 :         return JSTYPE_VOID;
     884         6993989 :     if (v.isObject())
     885         6990067 :         return v.toObject().typeOf(cx);
     886            3922 :     JS_ASSERT(v.isBoolean());
     887            3922 :     return JSTYPE_BOOLEAN;
     888                 : }
     889                 : 
     890                 : bool
     891        18682600 : js::ValueToId(JSContext *cx, const Value &v, jsid *idp)
     892                 : {
     893                 :     int32_t i;
     894        18682600 :     if (ValueFitsInInt32(v, &i) && INT_FITS_IN_JSID(i)) {
     895         4738850 :         *idp = INT_TO_JSID(i);
     896         4738850 :         return true;
     897                 :     }
     898                 : 
     899                 : #if JS_HAS_XML_SUPPORT
     900        13943750 :     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        13943714 :     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        18651217 : js::IsActiveWithOrBlock(JSContext *cx, JSObject &obj, uint32_t stackDepth)
     959                 : {
     960        37302283 :     return (obj.isWith() || obj.isBlock()) &&
     961           34192 :            obj.getPrivate() == js_FloatingFrameIfGenerator(cx, cx->fp()) &&
     962        37336475 :            obj.asNestedScope().stackDepth() >= stackDepth;
     963                 : }
     964                 : 
     965                 : /* Unwind block and scope chains to match the given depth. */
     966                 : void
     967         3401865 : js::UnwindScope(JSContext *cx, uint32_t stackDepth)
     968                 : {
     969         3401865 :     JS_ASSERT(cx->fp()->base() + stackDepth <= cx->regs().sp);
     970                 : 
     971         3401865 :     StackFrame *fp = cx->fp();
     972         3401865 :     StaticBlockObject *block = fp->maybeBlockChain();
     973         6807433 :     while (block) {
     974            4551 :         if (block->stackDepth() < stackDepth)
     975             848 :             break;
     976            3703 :         block = block->enclosingBlock();
     977                 :     }
     978         3401865 :     fp->setBlockChain(block);
     979                 : 
     980             108 :     for (;;) {
     981         3401973 :         JSObject &scopeChain = fp->scopeChain();
     982         3401973 :         if (!IsActiveWithOrBlock(cx, scopeChain, stackDepth))
     983                 :             break;
     984             108 :         if (scopeChain.isClonedBlock())
     985              90 :             scopeChain.asClonedBlock().put(cx);
     986                 :         else
     987              18 :             LeaveWith(cx);
     988                 :     }
     989         3401865 : }
     990                 : 
     991                 : void
     992            2198 : js::UnwindForUncatchableException(JSContext *cx, const FrameRegs &regs)
     993                 : {
     994                 : 
     995                 :     /* c.f. the regular (catchable) TryNoteIter loop in Interpret. */
     996            2261 :     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            2198 : }
    1004                 : 
    1005         2127709 : TryNoteIter::TryNoteIter(const FrameRegs &regs)
    1006                 :   : regs(regs),
    1007         2127709 :     script(regs.fp()->script()),
    1008         4255418 :     pcOffset(regs.pc - script->main())
    1009                 : {
    1010         2127709 :     if (JSScript::isValidOffset(script->trynotesOffset)) {
    1011           93461 :         tn = script->trynotes()->vector;
    1012           93461 :         tnEnd = tn + script->trynotes()->length;
    1013                 :     } else {
    1014         2034248 :         tn = tnEnd = NULL;
    1015                 :     }
    1016         2127709 :     settle();
    1017         2127709 : }
    1018                 : 
    1019                 : void
    1020            2906 : TryNoteIter::operator++()
    1021                 : {
    1022            2906 :     ++tn;
    1023            2906 :     settle();
    1024            2906 : }
    1025                 : 
    1026                 : bool
    1027         2130615 : TryNoteIter::done() const
    1028                 : {
    1029         2130615 :     return tn == tnEnd;
    1030                 : }
    1031                 : 
    1032                 : void
    1033         2130615 : TryNoteIter::settle()
    1034                 : {
    1035         2244558 :     for (; tn != tnEnd; ++tn) {
    1036                 :         /* If pc is out of range, try the next one. */
    1037          170354 :         if (pcOffset - tn->start >= tn->length)
    1038          113943 :             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           56411 :         if (tn->stackDepth <= regs.sp - regs.fp()->base())
    1060           56411 :             break;
    1061                 :     }
    1062         2130615 : }
    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       304364363 : DoIncDec(JSContext *cx, JSScript *script, jsbytecode *pc, const Value &v, Value *slot, Value *expr)
    1071                 : {
    1072       304364363 :     const JSCodeSpec &cs = js_CodeSpec[*pc];
    1073                 : 
    1074       304364363 :     if (v.isInt32()) {
    1075       304362164 :         int32_t i = v.toInt32();
    1076       304362164 :         if (i > JSVAL_INT_MIN && i < JSVAL_INT_MAX) {
    1077       304362140 :             int32_t sum = i + (cs.format & JOF_INC ? 1 : -1);
    1078       304362140 :             *slot = Int32Value(sum);
    1079       304362140 :             *expr = (cs.format & JOF_POST) ? Int32Value(i) : *slot;
    1080       304362140 :             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          743992 : js::GetUpvar(JSContext *cx, unsigned closureLevel, UpvarCookie cookie)
    1098                 : {
    1099          743992 :     JS_ASSERT(closureLevel >= cookie.level() && cookie.level() > 0);
    1100          743992 :     const unsigned targetLevel = closureLevel - cookie.level();
    1101                 : 
    1102          743992 :     StackFrame *fp = FindUpvarFrame(cx, targetLevel);
    1103          743992 :     unsigned slot = cookie.slot();
    1104                 :     const Value *vp;
    1105                 : 
    1106          743992 :     if (!fp->isFunctionFrame() || fp->isEvalFrame()) {
    1107              30 :         vp = fp->slots() + fp->numFixed();
    1108          743962 :     } else if (slot < fp->numFormalArgs()) {
    1109          390557 :         vp = fp->formalArgs();
    1110          353405 :     } else if (slot == UpvarCookie::CALLEE_SLOT) {
    1111               0 :         vp = &fp->calleev();
    1112               0 :         slot = 0;
    1113                 :     } else {
    1114          353405 :         slot -= fp->numFormalArgs();
    1115          353405 :         JS_ASSERT(slot < fp->numSlots());
    1116          353405 :         vp = fp->slots();
    1117                 :     }
    1118                 : 
    1119          743992 :     return vp[slot];
    1120                 : }
    1121                 : 
    1122                 : extern StackFrame *
    1123          743992 : js::FindUpvarFrame(JSContext *cx, unsigned targetLevel)
    1124                 : {
    1125          743992 :     StackFrame *fp = cx->fp();
    1126             889 :     while (true) {
    1127          744881 :         JS_ASSERT(fp && fp->isScriptFrame());
    1128          744881 :         if (fp->script()->staticLevel == targetLevel)
    1129                 :             break;
    1130             889 :         fp = fp->prev();
    1131                 :     }
    1132          743992 :     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         1977915 :     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         1977915 : inline InterpreterFrames::InterpreterFrames(JSContext *cx, FrameRegs *regs, 
    1201                 :                                             const InterruptEnablerBase &enabler)
    1202         1977915 :   : context(cx), regs(regs), enabler(enabler)
    1203                 : {
    1204         1977915 :     older = cx->runtime->interpreterFrames;
    1205         1977915 :     cx->runtime->interpreterFrames = this;
    1206         1977915 : }
    1207                 :  
    1208         1977915 : inline InterpreterFrames::~InterpreterFrames()
    1209                 : {
    1210         1977915 :     context->runtime->interpreterFrames = older;
    1211         1977915 : }
    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         4620085 : IteratorMore(JSContext *cx, JSObject *iterobj, bool *cond, Value *rval)
    1280                 : {
    1281         4620085 :     if (iterobj->isIterator()) {
    1282         4597869 :         NativeIterator *ni = iterobj->getNativeIterator();
    1283         4597869 :         if (ni->isKeyIter()) {
    1284          736816 :             *cond = (ni->props_cursor < ni->props_end);
    1285          736816 :             return true;
    1286                 :         }
    1287                 :     }
    1288         3883269 :     if (!js_IteratorMore(cx, iterobj, rval))
    1289              20 :         return false;
    1290         3883249 :     *cond = rval->isTrue();
    1291         3883249 :     return true;
    1292                 : }
    1293                 : 
    1294                 : static inline bool
    1295         4422919 : IteratorNext(JSContext *cx, JSObject *iterobj, Value *rval)
    1296                 : {
    1297         4422919 :     if (iterobj->isIterator()) {
    1298         4406813 :         NativeIterator *ni = iterobj->getNativeIterator();
    1299         4406813 :         if (ni->isKeyIter()) {
    1300          687043 :             JS_ASSERT(ni->props_cursor < ni->props_end);
    1301          687043 :             rval->setString(*ni->current());
    1302          687043 :             ni->incCursor();
    1303          687043 :             return true;
    1304                 :         }
    1305                 :     }
    1306         3735876 :     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      1961045842 : TypeCheckNextBytecode(JSContext *cx, JSScript *script, unsigned n, const FrameRegs &regs)
    1315                 : {
    1316                 : #ifdef DEBUG
    1317     -1471779413 :     if (cx->typeInferenceEnabled() &&
    1318       862142041 :         n == GetBytecodeLength(regs.pc)) {
    1319       859440498 :         TypeScript::CheckBytecode(cx, script, regs.pc, regs.sp);
    1320                 :     }
    1321                 : #endif
    1322      1961045842 : }
    1323                 : 
    1324                 : JS_NEVER_INLINE bool
    1325         1977915 : js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode)
    1326                 : {
    1327         3955830 :     JSAutoResolveFlags rf(cx, RESOLVE_INFER);
    1328                 : 
    1329         1977915 :     gc::MaybeVerifyBarriers(cx, true);
    1330                 : 
    1331         1977915 :     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         1977915 :     register void * const *jumpTable = normalJumpTable;
    1358                 : 
    1359                 :     typedef GenericInterruptEnabler<void * const *> InterruptEnabler;
    1360         1977915 :     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         1977915 :     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         1977915 :     FrameRegs regs = cx->regs();
    1525         3955830 :     PreserveRegsGuard interpGuard(cx, regs);
    1526                 : 
    1527                 :     /*
    1528                 :      * Help Debugger find frames running scripts that it has put in
    1529                 :      * single-step mode.
    1530                 :      */
    1531         3955830 :     InterpreterFrames interpreterFrame(cx, &regs, interruptEnabler);
    1532                 : 
    1533                 :     /* Copy in hot values that change infrequently. */
    1534         1977915 :     JSRuntime *const rt = cx->runtime;
    1535                 :     JSScript *script;
    1536         1977915 :     SET_SCRIPT(regs.fp()->script());
    1537         1977915 :     Value *argv = regs.fp()->maybeFormalArgs();
    1538         1977915 :     CHECK_INTERRUPT_HANDLER();
    1539                 : 
    1540         1977915 :     if (rt->profilingScripts)
    1541               0 :         ENABLE_INTERRUPTS();
    1542                 : 
    1543         1977915 :     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         1977915 :     JSAtom **atoms = script->atoms;
    1554                 : 
    1555                 : #if JS_HAS_GENERATORS
    1556         1977915 :     if (JS_UNLIKELY(regs.fp()->isGeneratorFrame())) {
    1557           30834 :         JS_ASSERT((size_t) (regs.pc - script->code) <= script->length);
    1558           30834 :         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           30834 :         if (cx->isExceptionPending())
    1565            1505 :             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         1976410 :     if (interpMode == JSINTERP_NORMAL) {
    1574         1961998 :         StackFrame *fp = regs.fp();
    1575         1961998 :         JS_ASSERT_IF(!fp->isGeneratorFrame(), regs.pc == script->code);
    1576         1961998 :         if (!ScriptPrologueOrGeneratorResume(cx, fp, UseNewTypeAtEntry(cx, fp)))
    1577               0 :             goto error;
    1578         1961998 :         if (cx->compartment->debugMode()) {
    1579          601784 :             JSTrapStatus status = ScriptDebugPrologue(cx, fp);
    1580          601784 :             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             399 :                 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         1976001 :     if (interpMode == JSINTERP_REJOIN)
    1597           14406 :         interpMode = JSINTERP_NORMAL;
    1598                 : 
    1599         1976001 :     CHECK_INTERRUPT_HANDLER();
    1600                 : 
    1601         1976001 :     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         1976001 :     len = 0;
    1612                 : 
    1613                 :     /* Check for too deep of a native thread stack. */
    1614         1976001 :     JS_CHECK_RECURSION(cx, goto error);
    1615                 : 
    1616         1975938 :     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          408268 : 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         1024482 : ADD_EMPTY_CASE(JSOP_CONDSWITCH)
    1754          687993 : 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       167272799 : ADD_EMPTY_CASE(JSOP_LOOPHEAD)
    1760       169671524 : 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       167285352 :     CHECK_BRANCH();
    1769       167285352 :     if (op != JSOP_LOOPHEAD)
    1770            1056 :         DO_OP();
    1771                 : 
    1772                 : #ifdef JS_METHODJIT
    1773       167284296 :     if (!useMethodJIT)
    1774       166611205 :         DO_OP();
    1775                 :     mjit::CompileStatus status =
    1776          673091 :         mjit::CanMethodJIT(cx, script, regs.pc, regs.fp()->isConstructing(),
    1777          673091 :                            mjit::CompileRequest_Interpreter);
    1778          673091 :     if (status == mjit::Compile_Error)
    1779               0 :         goto error;
    1780          673091 :     if (status == mjit::Compile_Okay) {
    1781                 :         void *ncode =
    1782           33494 :             script->nativeCodeForPC(regs.fp()->isConstructing(), regs.pc);
    1783           33494 :         JS_ASSERT(ncode);
    1784           33494 :         mjit::JaegerStatus status = mjit::JaegerShotAtSafePoint(cx, ncode, true);
    1785           33494 :         if (status == mjit::Jaeger_ThrowBeforeEnter)
    1786               0 :             goto error;
    1787           33494 :         CHECK_PARTIAL_METHODJIT(status);
    1788           11060 :         interpReturnOK = (status == mjit::Jaeger_Returned);
    1789           11060 :         if (entryFrame != regs.fp())
    1790           10179 :             goto jit_return;
    1791             881 :         regs.fp()->setFinishedInInterpreter();
    1792             881 :         goto leave_on_safe_point;
    1793                 :     }
    1794          639597 :     if (status == mjit::Compile_Abort)
    1795          146051 :         useMethodJIT = false;
    1796                 : #endif /* JS_METHODJIT */
    1797                 : 
    1798          639597 :     DO_OP();
    1799                 : }
    1800                 : 
    1801                 : /* ADD_EMPTY_CASE is not used here as JSOP_LINENO_LENGTH == 3. */
    1802                 : BEGIN_CASE(JSOP_LINENO)
    1803           22271 : END_CASE(JSOP_LINENO)
    1804                 : 
    1805                 : BEGIN_CASE(JSOP_UNDEFINED)
    1806        10433067 :     PUSH_UNDEFINED();
    1807        10433067 : END_CASE(JSOP_UNDEFINED)
    1808                 : 
    1809                 : BEGIN_CASE(JSOP_POP)
    1810       397013325 :     regs.sp--;
    1811       397013325 : END_CASE(JSOP_POP)
    1812                 : 
    1813                 : BEGIN_CASE(JSOP_POPN)
    1814                 : {
    1815          101981 :     regs.sp -= GET_UINT16(regs.pc);
    1816                 : #ifdef DEBUG
    1817          101981 :     JS_ASSERT(regs.fp()->base() <= regs.sp);
    1818          101981 :     StaticBlockObject *block = regs.fp()->maybeBlockChain();
    1819            7156 :     JS_ASSERT_IF(block,
    1820                 :                  block->stackDepth() + block->slotCount()
    1821          109137 :                  <= (size_t) (regs.sp - regs.fp()->base()));
    1822          212836 :     for (JSObject *obj = &regs.fp()->scopeChain(); obj; obj = obj->enclosingScope()) {
    1823          110855 :         if (!obj->isBlock() || !obj->isWith())
    1824          110855 :             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          101981 : END_CASE(JSOP_POPN)
    1834                 : 
    1835                 : BEGIN_CASE(JSOP_SETRVAL)
    1836                 : BEGIN_CASE(JSOP_POPV)
    1837          782909 :     POP_RETURN_VALUE();
    1838          782909 : 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         7736017 :     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        11914778 :     CHECK_BRANCH();
    1874                 : 
    1875        11914778 :     interpReturnOK = true;
    1876        11914778 :     if (entryFrame != regs.fp())
    1877                 :   inline_return:
    1878                 :     {
    1879        12047429 :         JS_ASSERT(!regs.fp()->hasBlockChain());
    1880        12047429 :         JS_ASSERT(!IsActiveWithOrBlock(cx, regs.fp()->scopeChain(), 0));
    1881                 : 
    1882        12047429 :         if (cx->compartment->debugMode())
    1883         1672977 :             interpReturnOK = ScriptDebugEpilogue(cx, regs.fp(), interpReturnOK);
    1884                 :  
    1885        12047429 :         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        12677473 :         bool shiftResult = regs.fp()->loweredCallOrApply();
    1894                 : 
    1895        12677473 :         cx->stack.popInlineFrame(regs);
    1896                 : 
    1897        12677473 :         RESTORE_INTERP_VARS();
    1898                 : 
    1899               0 :         JS_ASSERT(*regs.pc == JSOP_NEW || *regs.pc == JSOP_CALL ||
    1900        12677473 :                   *regs.pc == JSOP_FUNCALL || *regs.pc == JSOP_FUNAPPLY);
    1901                 : 
    1902                 :         /* Resume execution in the calling frame. */
    1903        12677473 :         RESET_USE_METHODJIT();
    1904        12677473 :         if (JS_LIKELY(interpReturnOK)) {
    1905        10671147 :             TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
    1906                 : 
    1907        10671147 :             if (shiftResult) {
    1908             161 :                 regs.sp[-2] = regs.sp[-1];
    1909             161 :                 regs.sp--;
    1910                 :             }
    1911                 : 
    1912        10671147 :             len = JSOP_CALL_LENGTH;
    1913        10671147 :             DO_NEXT_OP(len);
    1914                 :         }
    1915                 : 
    1916                 :         /* Increment pc so that |sp - fp->slots == ReconstructStackDepth(pc)|. */
    1917         2006326 :         regs.pc += JSOP_CALL_LENGTH;
    1918         2006326 :         goto error;
    1919                 :     } else {
    1920         1881645 :         JS_ASSERT(regs.sp == regs.fp()->base());
    1921                 :     }
    1922         1881645 :     interpReturnOK = true;
    1923         1881645 :     goto exit;
    1924                 : }
    1925                 : 
    1926                 : BEGIN_CASE(JSOP_DEFAULT)
    1927             751 :     regs.sp--;
    1928                 :     /* FALL THROUGH */
    1929                 : BEGIN_CASE(JSOP_GOTO)
    1930                 : {
    1931         6631369 :     len = GET_JUMP_OFFSET(regs.pc);
    1932         6631369 :     BRANCH(len);
    1933                 : }
    1934                 : END_CASE(JSOP_GOTO)
    1935                 : 
    1936                 : BEGIN_CASE(JSOP_IFEQ)
    1937                 : {
    1938                 :     bool cond;
    1939                 :     Value *_;
    1940         9050044 :     POP_BOOLEAN(cx, _, cond);
    1941         9050044 :     if (cond == false) {
    1942         5895429 :         len = GET_JUMP_OFFSET(regs.pc);
    1943         5895429 :         BRANCH(len);
    1944                 :     }
    1945                 : }
    1946         3154615 : END_CASE(JSOP_IFEQ)
    1947                 : 
    1948                 : BEGIN_CASE(JSOP_IFNE)
    1949                 : {
    1950                 :     bool cond;
    1951                 :     Value *_;
    1952         6617179 :     POP_BOOLEAN(cx, _, cond);
    1953         6617179 :     if (cond != false) {
    1954         6222831 :         len = GET_JUMP_OFFSET(regs.pc);
    1955         6222831 :         BRANCH(len);
    1956                 :     }
    1957                 : }
    1958          394348 : END_CASE(JSOP_IFNE)
    1959                 : 
    1960                 : BEGIN_CASE(JSOP_OR)
    1961                 : {
    1962                 :     bool cond;
    1963                 :     Value *_;
    1964          898787 :     VALUE_TO_BOOLEAN(cx, _, cond);
    1965          898787 :     if (cond == true) {
    1966          165228 :         len = GET_JUMP_OFFSET(regs.pc);
    1967          165228 :         DO_NEXT_OP(len);
    1968                 :     }
    1969                 : }
    1970          733559 : END_CASE(JSOP_OR)
    1971                 : 
    1972                 : BEGIN_CASE(JSOP_AND)
    1973                 : {
    1974                 :     bool cond;
    1975                 :     Value *_;
    1976          711448 :     VALUE_TO_BOOLEAN(cx, _, cond);
    1977          711448 :     if (cond == false) {
    1978          292061 :         len = GET_JUMP_OFFSET(regs.pc);
    1979          292061 :         DO_NEXT_OP(len);
    1980                 :     }
    1981                 : }
    1982          419387 : 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          433423 :     const Value &rref = regs.sp[-1];
    2021          433423 :     if (!rref.isObject()) {
    2022              11 :         js_ReportValueError(cx, JSMSG_IN_NOT_OBJECT, -1, rref, NULL);
    2023              11 :         goto error;
    2024                 :     }
    2025          433412 :     JSObject *obj = &rref.toObject();
    2026                 :     jsid id;
    2027          433412 :     FETCH_ELEMENT_ID(obj, -2, id);
    2028                 :     JSObject *obj2;
    2029                 :     JSProperty *prop;
    2030          433412 :     if (!obj->lookupGeneric(cx, id, &obj2, &prop))
    2031               0 :         goto error;
    2032          433412 :     bool cond = prop != NULL;
    2033          433412 :     TRY_BRANCH_AFTER_COND(cond, 2);
    2034          212866 :     regs.sp--;
    2035          212866 :     regs.sp[-1].setBoolean(cond);
    2036                 : }
    2037          212866 : END_CASE(JSOP_IN)
    2038                 : 
    2039                 : BEGIN_CASE(JSOP_ITER)
    2040                 : {
    2041          333544 :     JS_ASSERT(regs.sp > regs.fp()->base());
    2042          333544 :     uint8_t flags = GET_UINT8(regs.pc);
    2043          333544 :     if (!ValueToIterator(cx, flags, &regs.sp[-1]))
    2044             150 :         goto error;
    2045          333394 :     CHECK_INTERRUPT_HANDLER();
    2046          333394 :     JS_ASSERT(!regs.sp[-1].isPrimitive());
    2047                 : }
    2048          333394 : END_CASE(JSOP_ITER)
    2049                 : 
    2050                 : BEGIN_CASE(JSOP_MOREITER)
    2051                 : {
    2052         4620085 :     JS_ASSERT(regs.sp - 1 >= regs.fp()->base());
    2053         4620085 :     JS_ASSERT(regs.sp[-1].isObject());
    2054         4620085 :     PUSH_NULL();
    2055                 :     bool cond;
    2056         4620085 :     if (!IteratorMore(cx, &regs.sp[-2].toObject(), &cond, &regs.sp[-1]))
    2057              20 :         goto error;
    2058         4620065 :     CHECK_INTERRUPT_HANDLER();
    2059         4620065 :     regs.sp[-1].setBoolean(cond);
    2060                 : }
    2061         4620065 : END_CASE(JSOP_MOREITER)
    2062                 : 
    2063                 : BEGIN_CASE(JSOP_ITERNEXT)
    2064                 : {
    2065         4422919 :     Value *itervp = regs.sp - GET_INT8(regs.pc);
    2066         4422919 :     JS_ASSERT(itervp >= regs.fp()->base());
    2067         4422919 :     JS_ASSERT(itervp->isObject());
    2068         4422919 :     PUSH_NULL();
    2069         4422919 :     if (!IteratorNext(cx, &itervp->toObject(), &regs.sp[-1]))
    2070               0 :         goto error;
    2071                 : }
    2072         4422919 : END_CASE(JSOP_ITERNEXT)
    2073                 : 
    2074                 : BEGIN_CASE(JSOP_ENDITER)
    2075                 : {
    2076          333967 :     JS_ASSERT(regs.sp - 1 >= regs.fp()->base());
    2077          333967 :     bool ok = CloseIterator(cx, &regs.sp[-1].toObject());
    2078          333967 :     regs.sp--;
    2079          333967 :     if (!ok)
    2080               0 :         goto error;
    2081                 : }
    2082          333967 : END_CASE(JSOP_ENDITER)
    2083                 : 
    2084                 : BEGIN_CASE(JSOP_DUP)
    2085                 : {
    2086        20885863 :     JS_ASSERT(regs.sp > regs.fp()->base());
    2087        20885863 :     const Value &rref = regs.sp[-1];
    2088        20885863 :     PUSH_COPY(rref);
    2089                 : }
    2090        20885863 : END_CASE(JSOP_DUP)
    2091                 : 
    2092                 : BEGIN_CASE(JSOP_DUP2)
    2093                 : {
    2094         8227967 :     JS_ASSERT(regs.sp - 2 >= regs.fp()->base());
    2095         8227967 :     const Value &lref = regs.sp[-2];
    2096         8227967 :     const Value &rref = regs.sp[-1];
    2097         8227967 :     PUSH_COPY(lref);
    2098         8227967 :     PUSH_COPY(rref);
    2099                 : }
    2100         8227967 : END_CASE(JSOP_DUP2)
    2101                 : 
    2102                 : BEGIN_CASE(JSOP_SWAP)
    2103                 : {
    2104        12900246 :     JS_ASSERT(regs.sp - 2 >= regs.fp()->base());
    2105        12900246 :     Value &lref = regs.sp[-2];
    2106        12900246 :     Value &rref = regs.sp[-1];
    2107        12900246 :     lref.swap(rref);
    2108                 : }
    2109        12900246 : END_CASE(JSOP_SWAP)
    2110                 : 
    2111                 : BEGIN_CASE(JSOP_PICK)
    2112                 : {
    2113        21859667 :     unsigned i = GET_UINT8(regs.pc);
    2114        21859667 :     JS_ASSERT(regs.sp - (i + 1) >= regs.fp()->base());
    2115        21859667 :     Value lval = regs.sp[-int(i + 1)];
    2116        21859667 :     memmove(regs.sp - (i + 1), regs.sp - i, sizeof(Value) * i);
    2117        21859667 :     regs.sp[-1] = lval;
    2118                 : }
    2119        21859667 : END_CASE(JSOP_PICK)
    2120                 : 
    2121                 : BEGIN_CASE(JSOP_SETCONST)
    2122                 : {
    2123                 :     PropertyName *name;
    2124          166854 :     LOAD_NAME(0, name);
    2125          166854 :     JSObject &obj = regs.fp()->varObj();
    2126          166854 :     const Value &ref = regs.sp[-1];
    2127          166854 :     if (!obj.defineProperty(cx, name, ref,
    2128                 :                             JS_PropertyStub, JS_StrictPropertyStub,
    2129          166854 :                             JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY)) {
    2130               0 :         goto error;
    2131                 :     }
    2132                 : }
    2133          166854 : 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        11706579 :     PUSH_OBJECT(regs.fp()->scopeChain().global());
    2155        11706579 : 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          244505 :         obj = &regs.fp()->scopeChain();
    2178          244505 :         if (obj->isGlobal())
    2179          189158 :             break;
    2180                 : 
    2181                 :         PropertyName *name;
    2182           55347 :         LOAD_NAME(0, name);
    2183                 : 
    2184           55347 :         obj = FindIdentifierBase(cx, &regs.fp()->scopeChain(), name);
    2185           55347 :         if (!obj)
    2186               0 :             goto error;
    2187                 :     } while (0);
    2188          244505 :     PUSH_OBJECT(*obj);
    2189                 : }
    2190          244505 : 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          622276 :     BITWISE_OP(|);
    2206          622270 : END_CASE(JSOP_BITOR)
    2207                 : 
    2208                 : BEGIN_CASE(JSOP_BITXOR)
    2209          628981 :     BITWISE_OP(^);
    2210          628981 : END_CASE(JSOP_BITXOR)
    2211                 : 
    2212                 : BEGIN_CASE(JSOP_BITAND)
    2213        20947006 :     BITWISE_OP(&);
    2214        20947006 : 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         4523994 :     EQUALITY_OP(==);
    2233          869848 : END_CASE(JSOP_EQ)
    2234                 : 
    2235                 : BEGIN_CASE(JSOP_NE)
    2236          741713 :     EQUALITY_OP(!=);
    2237          152669 : 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         2019108 :     STRICT_EQUALITY_OP(==, cond);
    2256         2019108 :     regs.sp[-1].setBoolean(cond);
    2257                 : }
    2258         2019108 : END_CASE(JSOP_STRICTEQ)
    2259                 : 
    2260                 : BEGIN_CASE(JSOP_STRICTNE)
    2261                 : {
    2262                 :     bool cond;
    2263          907937 :     STRICT_EQUALITY_OP(!=, cond);
    2264          907937 :     regs.sp[-1].setBoolean(cond);
    2265                 : }
    2266          907937 : END_CASE(JSOP_STRICTNE)
    2267                 : 
    2268                 : BEGIN_CASE(JSOP_CASE)
    2269                 : {
    2270                 :     bool cond;
    2271         1049610 :     STRICT_EQUALITY_OP(==, cond);
    2272         1049610 :     if (cond) {
    2273         1023759 :         regs.sp--;
    2274         1023759 :         len = GET_JUMP_OFFSET(regs.pc);
    2275         1023759 :         BRANCH(len);
    2276                 :     }
    2277                 : }
    2278           25851 : END_CASE(JSOP_CASE)
    2279                 : 
    2280                 : #undef STRICT_EQUALITY_OP
    2281                 : 
    2282                 : BEGIN_CASE(JSOP_LT)
    2283                 : {
    2284                 :     bool cond;
    2285       157465842 :     const Value &lref = regs.sp[-2];
    2286       157465842 :     const Value &rref = regs.sp[-1];
    2287       157465842 :     if (!LessThanOperation(cx, lref, rref, &cond))
    2288               0 :         goto error;
    2289       157465842 :     TRY_BRANCH_AFTER_COND(cond, 2);
    2290          202835 :     regs.sp[-2].setBoolean(cond);
    2291          202835 :     regs.sp--;
    2292                 : }
    2293          202835 : END_CASE(JSOP_LT)
    2294                 : 
    2295                 : BEGIN_CASE(JSOP_LE)
    2296                 : {
    2297                 :     bool cond;
    2298         1765038 :     const Value &lref = regs.sp[-2];
    2299         1765038 :     const Value &rref = regs.sp[-1];
    2300         1765038 :     if (!LessThanOrEqualOperation(cx, lref, rref, &cond))
    2301               0 :         goto error;
    2302         1765038 :     TRY_BRANCH_AFTER_COND(cond, 2);
    2303           56322 :     regs.sp[-2].setBoolean(cond);
    2304           56322 :     regs.sp--;
    2305                 : }
    2306           56322 : END_CASE(JSOP_LE)
    2307                 : 
    2308                 : BEGIN_CASE(JSOP_GT)
    2309                 : {
    2310                 :     bool cond;
    2311         1724099 :     const Value &lref = regs.sp[-2];
    2312         1724099 :     const Value &rref = regs.sp[-1];
    2313         1724099 :     if (!GreaterThanOperation(cx, lref, rref, &cond))
    2314               7 :         goto error;
    2315         1724092 :     TRY_BRANCH_AFTER_COND(cond, 2);
    2316          101780 :     regs.sp[-2].setBoolean(cond);
    2317          101780 :     regs.sp--;
    2318                 : }
    2319          101780 : END_CASE(JSOP_GT)
    2320                 : 
    2321                 : BEGIN_CASE(JSOP_GE)
    2322                 : {
    2323                 :     bool cond;
    2324         6230173 :     const Value &lref = regs.sp[-2];
    2325         6230173 :     const Value &rref = regs.sp[-1];
    2326         6230173 :     if (!GreaterThanOrEqualOperation(cx, lref, rref, &cond))
    2327               0 :         goto error;
    2328         6230173 :     TRY_BRANCH_AFTER_COND(cond, 2);
    2329           82206 :     regs.sp[-2].setBoolean(cond);
    2330           82206 :     regs.sp--;
    2331                 : }
    2332           82206 : 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        18669801 :     SIGNED_SHIFT_OP(>>);
    2352        18669801 : 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             388 :         TypeScript::MonitorOverflow(cx, script, regs.pc);
    2370                 : }
    2371          140311 : END_CASE(JSOP_URSH)
    2372                 : 
    2373                 : BEGIN_CASE(JSOP_ADD)
    2374                 : {
    2375        59135463 :     Value lval = regs.sp[-2];
    2376        59135463 :     Value rval = regs.sp[-1];
    2377        59135463 :     if (!AddOperation(cx, lval, rval, &regs.sp[-2]))
    2378              40 :         goto error;
    2379        59135423 :     regs.sp--;
    2380                 : }
    2381        59135423 : END_CASE(JSOP_ADD)
    2382                 : 
    2383                 : BEGIN_CASE(JSOP_SUB)
    2384                 : {
    2385         6633500 :     Value lval = regs.sp[-2];
    2386         6633500 :     Value rval = regs.sp[-1];
    2387         6633500 :     if (!SubOperation(cx, lval, rval, &regs.sp[-2]))
    2388               0 :         goto error;
    2389         6633500 :     regs.sp--;
    2390                 : }
    2391         6633500 : END_CASE(JSOP_SUB)
    2392                 : 
    2393                 : BEGIN_CASE(JSOP_MUL)
    2394                 : {
    2395        24972227 :     Value lval = regs.sp[-2];
    2396        24972227 :     Value rval = regs.sp[-1];
    2397        24972227 :     if (!MulOperation(cx, lval, rval, &regs.sp[-2]))
    2398               0 :         goto error;
    2399        24972227 :     regs.sp--;
    2400                 : }
    2401        24972227 : END_CASE(JSOP_MUL)
    2402                 : 
    2403                 : BEGIN_CASE(JSOP_DIV)
    2404                 : {
    2405         1396383 :     Value lval = regs.sp[-2];
    2406         1396383 :     Value rval = regs.sp[-1];
    2407         1396383 :     if (!DivOperation(cx, lval, rval, &regs.sp[-2]))
    2408               0 :         goto error;
    2409         1396383 :     regs.sp--;
    2410                 : }
    2411         1396383 : END_CASE(JSOP_DIV)
    2412                 : 
    2413                 : BEGIN_CASE(JSOP_MOD)
    2414                 : {
    2415          461322 :     Value lval = regs.sp[-2];
    2416          461322 :     Value rval = regs.sp[-1];
    2417          461322 :     if (!ModOperation(cx, lval, rval, &regs.sp[-2]))
    2418               0 :         goto error;
    2419          461322 :     regs.sp--;
    2420                 : }
    2421          461322 : END_CASE(JSOP_MOD)
    2422                 : 
    2423                 : BEGIN_CASE(JSOP_NOT)
    2424                 : {
    2425                 :     Value *_;
    2426                 :     bool cond;
    2427         3320629 :     POP_BOOLEAN(cx, _, cond);
    2428         3320629 :     PUSH_BOOLEAN(!cond);
    2429                 : }
    2430         3320629 : 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        11004739 :     if (!ToNumber(cx, &regs.sp[-1]))
    2467               0 :         goto error;
    2468        11004739 :     if (!regs.sp[-1].isInt32())
    2469            2573 :         TypeScript::MonitorOverflow(cx, script, regs.pc);
    2470        11004739 : 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           26674 :     LOAD_NAME(0, name);
    2497                 : 
    2498                 :     JSObject *obj;
    2499           26674 :     FETCH_OBJECT(cx, -1, obj);
    2500                 : 
    2501                 :     Value rval;
    2502           26674 :     if (!obj->deleteProperty(cx, name, &rval, script->strictModeCode))
    2503               0 :         goto error;
    2504                 : 
    2505           26674 :     regs.sp[-1] = rval;
    2506                 : }
    2507           26674 : 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           25151 :     FETCH_OBJECT(cx, -2, obj);
    2514                 : 
    2515           25151 :     const Value &propval = regs.sp[-1];
    2516           25151 :     Value &rval = regs.sp[-2];
    2517                 : 
    2518           25151 :     if (!obj->deleteByValue(cx, propval, &rval, script->strictModeCode))
    2519               7 :         goto error;
    2520                 : 
    2521           25144 :     regs.sp--;
    2522                 : }
    2523           25144 : 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         6947632 :     Value objval = regs.sp[-2];
    2534         6947632 :     Value idval = regs.sp[-1];
    2535         6947632 :     if (!ToIdOperation(cx, objval, idval, &regs.sp[-1]))
    2536               0 :         goto error;
    2537                 : }
    2538         6947632 : END_CASE(JSOP_TOID)
    2539                 : 
    2540                 : BEGIN_CASE(JSOP_TYPEOFEXPR)
    2541                 : BEGIN_CASE(JSOP_TYPEOF)
    2542                 : {
    2543          233980 :     const Value &ref = regs.sp[-1];
    2544          233980 :     JSType type = JS_TypeOfValue(cx, ref);
    2545          233980 :     regs.sp[-1].setString(rt->atomState.typeAtoms[type]);
    2546                 : }
    2547          233980 : 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         6947632 : 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         4053058 : 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       290544098 :     Value &local = regs.fp()->localSlot(GET_SLOTNO(regs.pc));
    2593       290544098 :     if (!DoIncDec(cx, script, regs.pc, local, &local, &regs.sp[0]))
    2594               0 :         goto error;
    2595       290544098 :     regs.sp++;
    2596                 : }
    2597       290544098 : END_CASE(JSOP_LOCALINC)
    2598                 : 
    2599                 : BEGIN_CASE(JSOP_THIS)
    2600        12027110 :     if (!ComputeThis(cx, regs.fp()))
    2601               0 :         goto error;
    2602        12027110 :     PUSH_COPY(regs.fp()->thisValue());
    2603        12027110 : 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        85388868 :     if (!GetPropertyOperation(cx, regs.pc, regs.sp[-1], &rval))
    2612             725 :         goto error;
    2613                 : 
    2614        85388143 :     TypeScript::Monitor(cx, script, regs.pc, rval);
    2615                 : 
    2616        85388143 :     regs.sp[-1] = rval;
    2617        85388143 :     assertSameCompartment(cx, regs.sp[-1]);
    2618                 : }
    2619        85388143 : 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        17558796 :     const Value &rval = regs.sp[-1];
    2627        17558796 :     const Value &lval = regs.sp[-2];
    2628                 : 
    2629        17558796 :     if (!SetPropertyOperation(cx, regs.pc, lval, rval))
    2630             378 :         goto error;
    2631                 : 
    2632        17558418 :     regs.sp[-2] = regs.sp[-1];
    2633        17558418 :     regs.sp--;
    2634                 : }
    2635        17558418 : END_CASE(JSOP_SETPROP)
    2636                 : 
    2637                 : BEGIN_CASE(JSOP_GETELEM)
    2638                 : BEGIN_CASE(JSOP_CALLELEM)
    2639                 : {
    2640        35403349 :     Value &lref = regs.sp[-2];
    2641        35403349 :     Value &rref = regs.sp[-1];
    2642        35403349 :     if (!GetElementOperation(cx, op, lref, rref, &regs.sp[-2]))
    2643             371 :         goto error;
    2644        35402978 :     TypeScript::Monitor(cx, script, regs.pc, regs.sp[-2]);
    2645        35402978 :     regs.sp--;
    2646                 : }
    2647        35402978 : END_CASE(JSOP_GETELEM)
    2648                 : 
    2649                 : BEGIN_CASE(JSOP_SETELEM)
    2650                 : {
    2651                 :     JSObject *obj;
    2652        20220102 :     FETCH_OBJECT(cx, -3, obj);
    2653                 :     jsid id;
    2654        20220091 :     FETCH_ELEMENT_ID(obj, -2, id);
    2655        20220091 :     Value &value = regs.sp[-1];
    2656        20220091 :     if (!SetObjectElementOperation(cx, obj, id, value, script->strictModeCode))
    2657             471 :         goto error;
    2658        20219620 :     regs.sp[-3] = value;
    2659        20219620 :     regs.sp -= 2;
    2660                 : }
    2661        20219620 : 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            6167 :     FETCH_OBJECT(cx, -2, obj);
    2668                 :     jsid id;
    2669            6167 :     FETCH_ELEMENT_ID(obj, -1, id);
    2670            6167 :     Value rval = regs.sp[-3];
    2671            6167 :     if (!obj->setGeneric(cx, id, &rval, script->strictModeCode))
    2672               0 :         goto error;
    2673            6167 :     regs.sp -= 3;
    2674                 : }
    2675            6167 : END_CASE(JSOP_ENUMELEM)
    2676                 : 
    2677                 : BEGIN_CASE(JSOP_EVAL)
    2678                 : {
    2679           22529 :     CallArgs args = CallArgsFromSp(GET_ARGC(regs.pc), regs.sp);
    2680           22529 :     if (IsBuiltinEvalForScope(&regs.fp()->scopeChain(), args.calleev())) {
    2681           22508 :         if (!DirectEval(cx, args))
    2682             319 :             goto error;
    2683                 :     } else {
    2684              21 :         if (!InvokeKernel(cx, args))
    2685               0 :             goto error;
    2686                 :     }
    2687           22210 :     CHECK_INTERRUPT_HANDLER();
    2688           22210 :     regs.sp = args.spAfterCall();
    2689           22210 :     TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
    2690                 : }
    2691           22210 : 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        22930517 :     CallArgs args = CallArgsFromSp(GET_ARGC(regs.pc), regs.sp);
    2699        22930517 :     JS_ASSERT(args.base() >= regs.fp()->base());
    2700                 : 
    2701        22930517 :     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        22930517 :     if (!IsFunctionObject(args.calleev(), &fun) || !fun->isInterpretedConstructor()) {
    2707        11045280 :         if (construct) {
    2708          174653 :             if (!InvokeConstructorKernel(cx, args))
    2709             575 :                 goto error;
    2710                 :         } else {
    2711        10870627 :             if (!InvokeKernel(cx, args))
    2712           48749 :                 goto error;
    2713                 :         }
    2714        10995956 :         Value *newsp = args.spAfterCall();
    2715        10995956 :         TypeScript::Monitor(cx, script, regs.pc, newsp[-1]);
    2716        10995956 :         regs.sp = newsp;
    2717        10995956 :         CHECK_INTERRUPT_HANDLER();
    2718        10995956 :         len = JSOP_CALL_LENGTH;
    2719        10995956 :         DO_NEXT_OP(len);
    2720                 :     }
    2721                 : 
    2722        11885237 :     TypeMonitorCall(cx, args, construct);
    2723                 : 
    2724        11885237 :     InitialFrameFlags initial = construct ? INITIAL_CONSTRUCT : INITIAL_NONE;
    2725                 : 
    2726        11885237 :     JSScript *newScript = fun->script();
    2727                 : 
    2728        11885237 :     if (newScript->compileAndGo && newScript->hasClearedGlobal()) {
    2729               0 :         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CLEARED_SCOPE);
    2730               0 :         goto error;
    2731                 :     }
    2732                 : 
    2733        11885237 :     if (!cx->stack.pushInlineFrame(cx, regs, args, *fun, newScript, initial))
    2734              52 :         goto error;
    2735                 : 
    2736        11885185 :     RESTORE_INTERP_VARS();
    2737                 : 
    2738        11885185 :     if (!regs.fp()->functionPrologue(cx))
    2739               0 :         goto error;
    2740                 : 
    2741        11885185 :     RESET_USE_METHODJIT();
    2742                 : 
    2743        11885185 :     bool newType = cx->typeInferenceEnabled() && UseNewType(cx, script, regs.pc);
    2744                 : 
    2745                 : #ifdef JS_METHODJIT
    2746        11885185 :     if (!newType) {
    2747                 :         /* Try to ensure methods are method JIT'd.  */
    2748                 :         mjit::CompileRequest request = (interpMode == JSINTERP_NORMAL)
    2749                 :                                        ? mjit::CompileRequest_Interpreter
    2750        11885185 :                                        : mjit::CompileRequest_JIT;
    2751                 :         mjit::CompileStatus status = mjit::CanMethodJIT(cx, script, script->code,
    2752        11885185 :                                                         construct, request);
    2753        11885185 :         if (status == mjit::Compile_Error)
    2754               0 :             goto error;
    2755        11885185 :         if (status == mjit::Compile_Okay) {
    2756          632092 :             mjit::JaegerStatus status = mjit::JaegerShot(cx, true);
    2757          632092 :             CHECK_PARTIAL_METHODJIT(status);
    2758          619865 :             interpReturnOK = mjit::JaegerStatusToSuccess(status);
    2759          619865 :             CHECK_INTERRUPT_HANDLER();
    2760          619865 :             goto jit_return;
    2761                 :         }
    2762                 :     }
    2763                 : #endif
    2764                 : 
    2765        11253093 :     if (!ScriptPrologue(cx, regs.fp(), newType))
    2766               0 :         goto error;
    2767                 : 
    2768        11253093 :     if (cx->compartment->debugMode()) {
    2769         1361549 :         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        11253073 :     CHECK_INTERRUPT_HANDLER();
    2784                 : 
    2785                 :     /* Load first op and dispatch it (safe since JSOP_STOP). */
    2786        11253073 :     op = (JSOp) *regs.pc;
    2787        11253073 :     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         1267469 :     LOAD_NAME(0, name);
    2801                 : 
    2802                 :     JSObject *obj, *obj2;
    2803                 :     JSProperty *prop;
    2804         1267469 :     if (!FindPropertyHelper(cx, name, false, cx->stack.currentScriptedScopeChain(), &obj, &obj2, &prop))
    2805               0 :         goto error;
    2806                 : 
    2807                 :     Value v;
    2808         1267469 :     if (!ComputeImplicitThis(cx, obj, &v))
    2809               0 :         goto error;
    2810         1267469 :     PUSH_COPY(v);
    2811                 : }
    2812         1267469 : 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        51720447 :     if (!NameOperation(cx, regs.pc, &rval))
    2821            1314 :         goto error;
    2822                 : 
    2823        51719133 :     PUSH_COPY(rval);
    2824        51719133 :     TypeScript::Monitor(cx, script, regs.pc, rval);
    2825                 : }
    2826        51719133 : END_CASE(JSOP_NAME)
    2827                 : 
    2828                 : BEGIN_CASE(JSOP_UINT16)
    2829        27296074 :     PUSH_INT32((int32_t) GET_UINT16(regs.pc));
    2830        27296074 : END_CASE(JSOP_UINT16)
    2831                 : 
    2832                 : BEGIN_CASE(JSOP_UINT24)
    2833         2691200 :     PUSH_INT32((int32_t) GET_UINT24(regs.pc));
    2834         2691200 : END_CASE(JSOP_UINT24)
    2835                 : 
    2836                 : BEGIN_CASE(JSOP_INT8)
    2837        40770252 :     PUSH_INT32(GET_INT8(regs.pc));
    2838        40770252 : END_CASE(JSOP_INT8)
    2839                 : 
    2840                 : BEGIN_CASE(JSOP_INT32)
    2841         4617769 :     PUSH_INT32(GET_INT32(regs.pc));
    2842         4617769 : END_CASE(JSOP_INT32)
    2843                 : 
    2844                 : BEGIN_CASE(JSOP_DOUBLE)
    2845                 : {
    2846                 :     double dbl;
    2847         1378550 :     LOAD_DOUBLE(0, dbl);
    2848         1378550 :     PUSH_DOUBLE(dbl);
    2849                 : }
    2850         1378550 : END_CASE(JSOP_DOUBLE)
    2851                 : 
    2852                 : BEGIN_CASE(JSOP_STRING)
    2853                 : {
    2854                 :     JSAtom *atom;
    2855        13762571 :     LOAD_ATOM(0, atom);
    2856        13762571 :     PUSH_STRING(atom);
    2857                 : }
    2858        13762571 : END_CASE(JSOP_STRING)
    2859                 : 
    2860                 : BEGIN_CASE(JSOP_OBJECT)
    2861                 : {
    2862            6105 :     PUSH_OBJECT(*script->getObject(GET_UINT32_INDEX(regs.pc)));
    2863                 : }
    2864            6105 : 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          203727 :     uint32_t index = GET_UINT32_INDEX(regs.pc);
    2873          203727 :     JSObject *proto = regs.fp()->scopeChain().global().getOrCreateRegExpPrototype(cx);
    2874          203727 :     if (!proto)
    2875               0 :         goto error;
    2876          203727 :     JSObject *obj = CloneRegExpObject(cx, script->getRegExp(index), proto);
    2877          203727 :     if (!obj)
    2878               0 :         goto error;
    2879          203727 :     PUSH_OBJECT(*obj);
    2880                 : }
    2881          203727 : END_CASE(JSOP_REGEXP)
    2882                 : 
    2883                 : BEGIN_CASE(JSOP_ZERO)
    2884        15927047 :     PUSH_INT32(0);
    2885        15927047 : END_CASE(JSOP_ZERO)
    2886                 : 
    2887                 : BEGIN_CASE(JSOP_ONE)
    2888        23694457 :     PUSH_INT32(1);
    2889        23694457 : END_CASE(JSOP_ONE)
    2890                 : 
    2891                 : BEGIN_CASE(JSOP_NULL)
    2892         3024210 :     PUSH_NULL();
    2893         3024210 : END_CASE(JSOP_NULL)
    2894                 : 
    2895                 : BEGIN_CASE(JSOP_FALSE)
    2896         2099463 :     PUSH_BOOLEAN(false);
    2897         2099463 : END_CASE(JSOP_FALSE)
    2898                 : 
    2899                 : BEGIN_CASE(JSOP_TRUE)
    2900         2163384 :     PUSH_BOOLEAN(true);
    2901         2163384 : 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            1579 :         pc2 += JUMP_OFFSET_LEN + JUMP_OFFSET_LEN * i;
    2933            1579 :         int32_t off = (int32_t) GET_JUMP_OFFSET(pc2);
    2934            1579 :         if (off)
    2935            1569 :             len = off;
    2936                 :     }
    2937                 : }
    2938            2181 : END_VARLEN_CASE
    2939                 : }
    2940                 : 
    2941                 : {
    2942                 : BEGIN_CASE(JSOP_LOOKUPSWITCH)
    2943                 : {
    2944                 :     int32_t off;
    2945           26932 :     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           26932 :     JS_ASSERT(atoms == script->atoms);
    2952           26932 :     jsbytecode *pc2 = regs.pc;
    2953                 : 
    2954           26932 :     Value lval = regs.sp[-1];
    2955           26932 :     regs.sp--;
    2956                 : 
    2957                 :     int npairs;
    2958           26932 :     if (!lval.isPrimitive())
    2959               0 :         goto end_lookup_switch;
    2960                 : 
    2961           26932 :     pc2 += off;
    2962           26932 :     npairs = GET_UINT16(pc2);
    2963           26932 :     pc2 += UINT16_LEN;
    2964           26932 :     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           26932 :     if (lval.isString()) {
    2982           26376 :         JSLinearString *str = lval.toString()->ensureLinear(cx);
    2983           26376 :         if (!str)
    2984               0 :             goto error;
    2985                 :         JSLinearString *str2;
    2986           92875 :         SEARCH_PAIRS(
    2987                 :             match = (rval.isString() &&
    2988                 :                      ((str2 = &rval.toString()->asLinear()) == str ||
    2989                 :                       EqualStrings(str2, str)));
    2990                 :         )
    2991             556 :     } 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             655 :         SEARCH_PAIRS(
    2998                 :             match = (lval == rval);
    2999                 :         )
    3000                 :     }
    3001                 : #undef SEARCH_PAIRS
    3002                 : 
    3003                 :   end_lookup_switch:
    3004           26932 :     len = GET_JUMP_OFFSET(pc2);
    3005                 : }
    3006           26932 : END_VARLEN_CASE
    3007                 : }
    3008                 : 
    3009                 : BEGIN_CASE(JSOP_ARGUMENTS)
    3010                 : {
    3011                 :     Value rval;
    3012          267499 :     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          150278 :         ArgumentsObject *arguments = js_GetArgsObject(cx, regs.fp());
    3025          150278 :         if (!arguments)
    3026               0 :             goto error;
    3027          150278 :         rval = ObjectValue(*arguments);
    3028                 :     }
    3029          267499 :     PUSH_COPY(rval);
    3030                 : }
    3031          267499 : END_CASE(JSOP_ARGUMENTS)
    3032                 : 
    3033                 : BEGIN_CASE(JSOP_GETARG)
    3034                 : BEGIN_CASE(JSOP_CALLARG)
    3035        57892163 :     PUSH_COPY(regs.fp()->formalArg(GET_ARGNO(regs.pc)));
    3036        57892163 : END_CASE(JSOP_GETARG)
    3037                 : 
    3038                 : BEGIN_CASE(JSOP_SETARG)
    3039         5244700 :     regs.fp()->formalArg(GET_ARGNO(regs.pc)) = regs.sp[-1];
    3040         5244700 : END_CASE(JSOP_SETARG)
    3041                 : 
    3042                 : BEGIN_CASE(JSOP_GETLOCAL)
    3043                 : BEGIN_CASE(JSOP_CALLLOCAL)
    3044       452151302 :     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       452151302 :     if (regs.pc[JSOP_GETLOCAL_LENGTH] != JSOP_POP)
    3053       447953188 :         assertSameCompartment(cx, regs.sp[-1]);
    3054       452151302 : END_CASE(JSOP_GETLOCAL)
    3055                 : 
    3056                 : BEGIN_CASE(JSOP_SETLOCAL)
    3057        44349352 :     regs.fp()->localSlot(GET_SLOTNO(regs.pc)) = regs.sp[-1];
    3058        44349352 : END_CASE(JSOP_SETLOCAL)
    3059                 : 
    3060                 : BEGIN_CASE(JSOP_GETFCSLOT)
    3061                 : BEGIN_CASE(JSOP_CALLFCSLOT)
    3062                 : {
    3063          702753 :     JS_ASSERT(regs.fp()->isNonEvalFunctionFrame());
    3064          702753 :     unsigned index = GET_UINT16(regs.pc);
    3065          702753 :     JSObject *obj = &argv[-2].toObject();
    3066                 : 
    3067          702753 :     PUSH_COPY(obj->toFunction()->getFlatClosureUpvar(index));
    3068          702753 :     TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
    3069                 : }
    3070          702753 : END_CASE(JSOP_GETFCSLOT)
    3071                 : 
    3072                 : BEGIN_CASE(JSOP_DEFCONST)
    3073                 : BEGIN_CASE(JSOP_DEFVAR)
    3074                 : {
    3075          286242 :     PropertyName *dn = atoms[GET_UINT32_INDEX(regs.pc)]->asPropertyName();
    3076                 : 
    3077                 :     /* ES5 10.5 step 8 (with subsequent errata). */
    3078          286242 :     unsigned attrs = JSPROP_ENUMERATE;
    3079          286242 :     if (!regs.fp()->isEvalFrame())
    3080          285105 :         attrs |= JSPROP_PERMANENT;
    3081          286242 :     if (op == JSOP_DEFCONST)
    3082          166855 :         attrs |= JSPROP_READONLY;
    3083                 : 
    3084                 :     /* Step 8b. */
    3085          286242 :     JSObject &obj = regs.fp()->varObj();
    3086                 : 
    3087          286242 :     if (!DefVarOrConstOperation(cx, obj, dn, attrs))
    3088               0 :         goto error;
    3089                 : }
    3090          286242 : 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          185300 :     JSFunction *fun = script->getFunction(GET_UINT32_INDEX(regs.pc));
    3101          185300 :     JSObject *obj = fun;
    3102                 : 
    3103                 :     JSObject *obj2;
    3104          185300 :     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          172941 :         obj2 = &regs.fp()->scopeChain();
    3111                 :     } else {
    3112           12359 :         JS_ASSERT(!fun->isFlatClosure());
    3113                 : 
    3114           12359 :         obj2 = GetScopeChain(cx, regs.fp());
    3115           12359 :         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          185300 :     if (obj->toFunction()->environment() != obj2) {
    3129          183458 :         obj = CloneFunctionObjectIfNotSingleton(cx, fun, obj2);
    3130          183458 :         if (!obj)
    3131               0 :             goto error;
    3132          183458 :         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          185300 :     unsigned attrs = regs.fp()->isEvalFrame()
    3140                 :                   ? JSPROP_ENUMERATE
    3141          185300 :                   : 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          185300 :     JSObject *parent = &regs.fp()->varObj();
    3149                 : 
    3150                 :     /* ES5 10.5 (NB: with subsequent errata). */
    3151          185300 :     PropertyName *name = fun->atom->asPropertyName();
    3152          185300 :     JSProperty *prop = NULL;
    3153                 :     JSObject *pobj;
    3154          185300 :     if (!parent->lookupProperty(cx, name, &pobj, &prop))
    3155               0 :         goto error;
    3156                 : 
    3157          185300 :     Value rval = ObjectValue(*obj);
    3158                 : 
    3159                 :     do {
    3160                 :         /* Steps 5d, 5f. */
    3161          185300 :         if (!prop || pobj != parent) {
    3162          184289 :             if (!parent->defineProperty(cx, name, rval,
    3163          184289 :                                         JS_PropertyStub, JS_StrictPropertyStub, attrs))
    3164                 :             {
    3165               0 :                 goto error;
    3166                 :             }
    3167          184289 :             break;
    3168                 :         }
    3169                 : 
    3170                 :         /* Step 5e. */
    3171            1011 :         JS_ASSERT(parent->isNative());
    3172            1011 :         Shape *shape = reinterpret_cast<Shape *>(prop);
    3173            1011 :         if (parent->isGlobal()) {
    3174             721 :             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             520 :             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             805 :         if (!parent->setProperty(cx, name, &rval, script->strictModeCode))
    3202               0 :             goto error;
    3203                 :     } while (false);
    3204                 : }
    3205          185295 : 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          124491 :     JSFunction *fun = script->getFunction(GET_UINT32_INDEX(regs.pc + SLOTNO_LEN));
    3217          124491 :     JS_ASSERT(fun->isInterpreted());
    3218          124491 :     JS_ASSERT(!fun->isFlatClosure());
    3219                 : 
    3220                 :     JSObject *parent;
    3221          124491 :     if (fun->isNullClosure()) {
    3222           21898 :         parent = &regs.fp()->scopeChain();
    3223                 :     } else {
    3224          102593 :         parent = GetScopeChain(cx, regs.fp());
    3225          102593 :         if (!parent)
    3226               0 :             goto error;
    3227                 :     }
    3228          124491 :     JSObject *obj = CloneFunctionObjectIfNotSingleton(cx, fun, parent);
    3229          124491 :     if (!obj)
    3230               0 :         goto error;
    3231                 : 
    3232          124491 :     JS_ASSERT_IF(script->hasGlobal(), obj->getProto() == fun->getProto());
    3233                 : 
    3234          124491 :     regs.fp()->varSlot(GET_SLOTNO(regs.pc)) = ObjectValue(*obj);
    3235                 : }
    3236          124491 : END_CASE(JSOP_DEFLOCALFUN)
    3237                 : 
    3238                 : BEGIN_CASE(JSOP_DEFLOCALFUN_FC)
    3239                 : {
    3240            8009 :     JSFunction *fun = script->getFunction(GET_UINT32_INDEX(regs.pc + SLOTNO_LEN));
    3241                 : 
    3242            8009 :     JSObject *obj = js_NewFlatClosure(cx, fun);
    3243            8009 :     if (!obj)
    3244               0 :         goto error;
    3245                 : 
    3246            8009 :     regs.fp()->varSlot(GET_SLOTNO(regs.pc)) = ObjectValue(*obj);
    3247                 : }
    3248            8009 : END_CASE(JSOP_DEFLOCALFUN_FC)
    3249                 : 
    3250                 : BEGIN_CASE(JSOP_LAMBDA)
    3251                 : {
    3252                 :     /* Load the specified function object literal. */
    3253         1007161 :     JSFunction *fun = script->getFunction(GET_UINT32_INDEX(regs.pc));
    3254         1007161 :     JSObject *obj = fun;
    3255                 : 
    3256                 :     /* do-while(0) so we can break instead of using a goto. */
    3257                 :     do {
    3258                 :         JSObject *parent;
    3259         1007161 :         if (fun->isNullClosure()) {
    3260          625721 :             parent = &regs.fp()->scopeChain();
    3261                 :         } else {
    3262          381440 :             parent = GetScopeChain(cx, regs.fp());
    3263          381440 :             if (!parent)
    3264               0 :                 goto error;
    3265                 :         }
    3266                 : 
    3267         1007161 :         obj = CloneFunctionObjectIfNotSingleton(cx, fun, parent);
    3268         1007161 :         if (!obj)
    3269               0 :             goto error;
    3270                 :     } while (0);
    3271                 : 
    3272         1007161 :     JS_ASSERT(obj->getProto());
    3273         1007161 :     JS_ASSERT_IF(script->hasGlobal(), obj->getProto() == fun->getProto());
    3274                 : 
    3275         1007161 :     PUSH_OBJECT(*obj);
    3276                 : }
    3277         1007161 : END_CASE(JSOP_LAMBDA)
    3278                 : 
    3279                 : BEGIN_CASE(JSOP_LAMBDA_FC)
    3280                 : {
    3281          312716 :     JSFunction *fun = script->getFunction(GET_UINT32_INDEX(regs.pc));
    3282                 : 
    3283          312716 :     JSObject *obj = js_NewFlatClosure(cx, fun);
    3284          312716 :     if (!obj)
    3285               0 :         goto error;
    3286          312716 :     JS_ASSERT_IF(script->hasGlobal(), obj->getProto() == fun->getProto());
    3287                 : 
    3288          312716 :     PUSH_OBJECT(*obj);
    3289                 : }
    3290          312716 : END_CASE(JSOP_LAMBDA_FC)
    3291                 : 
    3292                 : BEGIN_CASE(JSOP_CALLEE)
    3293         1307123 :     JS_ASSERT(regs.fp()->isNonEvalFunctionFrame());
    3294         1307123 :     PUSH_COPY(argv[-2]);
    3295         1307123 : END_CASE(JSOP_CALLEE)
    3296                 : 
    3297                 : BEGIN_CASE(JSOP_GETTER)
    3298                 : BEGIN_CASE(JSOP_SETTER)
    3299                 : {
    3300           73705 :     JSOp op2 = JSOp(*++regs.pc);
    3301                 :     jsid id;
    3302                 :     Value rval;
    3303                 :     int i;
    3304                 :     JSObject *obj;
    3305           73705 :     switch (op2) {
    3306                 :       case JSOP_SETNAME:
    3307                 :       case JSOP_SETPROP:
    3308                 :       {
    3309                 :         PropertyName *name;
    3310               0 :         LOAD_NAME(0, name);
    3311               0 :         id = ATOM_TO_JSID(name);
    3312               0 :         rval = regs.sp[-1];
    3313               0 :         i = -1;
    3314               0 :         goto gs_pop_lval;
    3315                 :       }
    3316                 :       case JSOP_SETELEM:
    3317               0 :         rval = regs.sp[-1];
    3318               0 :         id = JSID_VOID;
    3319               0 :         i = -2;
    3320                 :       gs_pop_lval:
    3321               0 :         FETCH_OBJECT(cx, i - 1, obj);
    3322               0 :         break;
    3323                 : 
    3324                 :       case JSOP_INITPROP:
    3325                 :       {
    3326           73705 :         JS_ASSERT(regs.sp - regs.fp()->base() >= 2);
    3327           73705 :         rval = regs.sp[-1];
    3328           73705 :         i = -1;
    3329                 :         PropertyName *name;
    3330           73705 :         LOAD_NAME(0, name);
    3331           73705 :         id = ATOM_TO_JSID(name);
    3332           73705 :         goto gs_get_lval;
    3333                 :       }
    3334                 :       default:
    3335               0 :         JS_ASSERT(op2 == JSOP_INITELEM);
    3336                 : 
    3337               0 :         JS_ASSERT(regs.sp - regs.fp()->base() >= 3);
    3338               0 :         rval = regs.sp[-1];
    3339               0 :         id = JSID_VOID;
    3340               0 :         i = -2;
    3341                 :       gs_get_lval:
    3342                 :       {
    3343           73705 :         const Value &lref = regs.sp[i-1];
    3344           73705 :         JS_ASSERT(lref.isObject());
    3345           73705 :         obj = &lref.toObject();
    3346           73705 :         break;
    3347                 :       }
    3348                 :     }
    3349                 : 
    3350                 :     /* Ensure that id has a type suitable for use with obj. */
    3351           73705 :     if (JSID_IS_VOID(id))
    3352               0 :         FETCH_ELEMENT_ID(obj, i, id);
    3353                 : 
    3354           73705 :     if (!js_IsCallable(rval)) {
    3355                 :         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_GETTER_OR_SETTER,
    3356               0 :                              (op == JSOP_GETTER) ? js_getter_str : js_setter_str);
    3357               0 :         goto error;
    3358                 :     }
    3359                 : 
    3360                 :     /*
    3361                 :      * Getters and setters are just like watchpoints from an access control
    3362                 :      * point of view.
    3363                 :      */
    3364                 :     Value rtmp;
    3365                 :     unsigned attrs;
    3366           73705 :     if (!CheckAccess(cx, obj, id, JSACC_WATCH, &rtmp, &attrs))
    3367               0 :         goto error;
    3368                 : 
    3369                 :     PropertyOp getter;
    3370                 :     StrictPropertyOp setter;
    3371           73705 :     if (op == JSOP_GETTER) {
    3372           60133 :         getter = CastAsPropertyOp(&rval.toObject());
    3373           60133 :         setter = JS_StrictPropertyStub;
    3374           60133 :         attrs = JSPROP_GETTER;
    3375                 :     } else {
    3376           13572 :         getter = JS_PropertyStub;
    3377           13572 :         setter = CastAsStrictPropertyOp(&rval.toObject());
    3378           13572 :         attrs = JSPROP_SETTER;
    3379                 :     }
    3380           73705 :     attrs |= JSPROP_ENUMERATE | JSPROP_SHARED;
    3381                 : 
    3382           73705 :     if (!obj->defineGeneric(cx, id, UndefinedValue(), getter, setter, attrs))
    3383               0 :         goto error;
    3384                 : 
    3385           73705 :     regs.sp += i;
    3386           73705 :     if (js_CodeSpec[op2].ndefs > js_CodeSpec[op2].nuses) {
    3387               0 :         JS_ASSERT(js_CodeSpec[op2].ndefs == js_CodeSpec[op2].nuses + 1);
    3388               0 :         regs.sp[-1] = rval;
    3389               0 :         assertSameCompartment(cx, regs.sp[-1]);
    3390                 :     }
    3391           73705 :     len = js_CodeSpec[op2].length;
    3392           73705 :     DO_NEXT_OP(len);
    3393                 : }
    3394                 : 
    3395                 : BEGIN_CASE(JSOP_HOLE)
    3396            4772 :     PUSH_HOLE();
    3397            4772 : END_CASE(JSOP_HOLE)
    3398                 : 
    3399                 : BEGIN_CASE(JSOP_NEWINIT)
    3400                 : {
    3401          302491 :     uint8_t i = GET_UINT8(regs.pc);
    3402          302491 :     JS_ASSERT(i == JSProto_Array || i == JSProto_Object);
    3403                 : 
    3404                 :     JSObject *obj;
    3405          302491 :     if (i == JSProto_Array) {
    3406           57861 :         obj = NewDenseEmptyArray(cx);
    3407                 :     } else {
    3408          244630 :         gc::AllocKind kind = GuessObjectGCKind(0);
    3409          244630 :         obj = NewBuiltinClassInstance(cx, &ObjectClass, kind);
    3410                 :     }
    3411          302491 :     if (!obj)
    3412               0 :         goto error;
    3413                 : 
    3414          302491 :     TypeObject *type = TypeScript::InitObject(cx, script, regs.pc, (JSProtoKey) i);
    3415          302491 :     if (!type)
    3416               0 :         goto error;
    3417          302491 :     obj->setType(type);
    3418                 : 
    3419          302491 :     PUSH_OBJECT(*obj);
    3420          302491 :     TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
    3421                 : 
    3422          302491 :     CHECK_INTERRUPT_HANDLER();
    3423                 : }
    3424          302491 : END_CASE(JSOP_NEWINIT)
    3425                 : 
    3426                 : BEGIN_CASE(JSOP_NEWARRAY)
    3427                 : {
    3428         1090952 :     unsigned count = GET_UINT24(regs.pc);
    3429         1090952 :     JSObject *obj = NewDenseAllocatedArray(cx, count);
    3430         1090952 :     if (!obj)
    3431               0 :         goto error;
    3432                 : 
    3433         1090952 :     TypeObject *type = TypeScript::InitObject(cx, script, regs.pc, JSProto_Array);
    3434         1090952 :     if (!type)
    3435               0 :         goto error;
    3436         1090952 :     obj->setType(type);
    3437                 : 
    3438         1090952 :     PUSH_OBJECT(*obj);
    3439         1090952 :     TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
    3440                 : 
    3441         1090952 :     CHECK_INTERRUPT_HANDLER();
    3442                 : }
    3443         1090952 : END_CASE(JSOP_NEWARRAY)
    3444                 : 
    3445                 : BEGIN_CASE(JSOP_NEWOBJECT)
    3446                 : {
    3447         1058456 :     JSObject *baseobj = script->getObject(GET_UINT32_INDEX(regs.pc));
    3448                 : 
    3449         1058456 :     TypeObject *type = TypeScript::InitObject(cx, script, regs.pc, JSProto_Object);
    3450         1058456 :     if (!type)
    3451               0 :         goto error;
    3452                 : 
    3453         1058456 :     JSObject *obj = CopyInitializerObject(cx, baseobj, type);
    3454         1058456 :     if (!obj)
    3455               1 :         goto error;
    3456                 : 
    3457         1058455 :     PUSH_OBJECT(*obj);
    3458         1058455 :     TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
    3459                 : 
    3460         1058455 :     CHECK_INTERRUPT_HANDLER();
    3461                 : }
    3462         1058455 : END_CASE(JSOP_NEWOBJECT)
    3463                 : 
    3464                 : BEGIN_CASE(JSOP_ENDINIT)
    3465                 : {
    3466                 :     /* FIXME remove JSOP_ENDINIT bug 588522 */
    3467         2388664 :     JS_ASSERT(regs.sp - regs.fp()->base() >= 1);
    3468         2388664 :     JS_ASSERT(regs.sp[-1].isObject());
    3469                 : }
    3470         2388664 : END_CASE(JSOP_ENDINIT)
    3471                 : 
    3472                 : BEGIN_CASE(JSOP_INITPROP)
    3473                 : BEGIN_CASE(JSOP_INITMETHOD)
    3474                 : {
    3475                 :     /* Load the property's initial value into rval. */
    3476         2999106 :     JS_ASSERT(regs.sp - regs.fp()->base() >= 2);
    3477         2999106 :     Value rval = regs.sp[-1];
    3478                 : 
    3479                 :     /* Load the object being initialized into lval/obj. */
    3480         2999106 :     JSObject *obj = &regs.sp[-2].toObject();
    3481         2999106 :     JS_ASSERT(obj->isObject());
    3482                 : 
    3483                 :     JSAtom *atom;
    3484         2999106 :     LOAD_ATOM(0, atom);
    3485         2999106 :     jsid id = ATOM_TO_JSID(atom);
    3486                 : 
    3487         2999106 :     unsigned defineHow = (op == JSOP_INITMETHOD) ? DNP_SET_METHOD : 0;
    3488         5998212 :     if (JS_UNLIKELY(atom == cx->runtime->atomState.protoAtom)
    3489            9716 :         ? !js_SetPropertyHelper(cx, obj, id, defineHow, &rval, script->strictModeCode)
    3490                 :         : !DefineNativeProperty(cx, obj, id, rval, NULL, NULL,
    3491         2989390 :                                 JSPROP_ENUMERATE, 0, 0, defineHow)) {
    3492               0 :         goto error;
    3493                 :     }
    3494                 : 
    3495         2999106 :     regs.sp--;
    3496                 : }
    3497         2999106 : END_CASE(JSOP_INITPROP);
    3498                 : 
    3499                 : BEGIN_CASE(JSOP_INITELEM)
    3500                 : {
    3501                 :     /* Pop the element's value into rval. */
    3502        11336664 :     JS_ASSERT(regs.sp - regs.fp()->base() >= 3);
    3503        11336664 :     const Value &rref = regs.sp[-1];
    3504                 : 
    3505                 :     /* Find the object being initialized at top of stack. */
    3506        11336664 :     const Value &lref = regs.sp[-3];
    3507        11336664 :     JS_ASSERT(lref.isObject());
    3508        11336664 :     JSObject *obj = &lref.toObject();
    3509                 : 
    3510                 :     /* Fetch id now that we have obj. */
    3511                 :     jsid id;
    3512        11336664 :     FETCH_ELEMENT_ID(obj, -2, id);
    3513                 : 
    3514                 :     /*
    3515                 :      * If rref is a hole, do not call JSObject::defineProperty. In this case,
    3516                 :      * obj must be an array, so if the current op is the last element
    3517                 :      * initialiser, set the array length to one greater than id.
    3518                 :      */
    3519        11336664 :     if (rref.isMagic(JS_ARRAY_HOLE)) {
    3520            4772 :         JS_ASSERT(obj->isArray());
    3521            4772 :         JS_ASSERT(JSID_IS_INT(id));
    3522            4772 :         JS_ASSERT(uint32_t(JSID_TO_INT(id)) < StackSpace::ARGS_LENGTH_MAX);
    3523            5175 :         if (JSOp(regs.pc[JSOP_INITELEM_LENGTH]) == JSOP_ENDINIT &&
    3524             403 :             !js_SetLengthProperty(cx, obj, (uint32_t) (JSID_TO_INT(id) + 1))) {
    3525               0 :             goto error;
    3526                 :         }
    3527                 :     } else {
    3528        11331892 :         if (!obj->defineGeneric(cx, id, rref, NULL, NULL, JSPROP_ENUMERATE))
    3529               0 :             goto error;
    3530                 :     }
    3531        11336664 :     regs.sp -= 2;
    3532                 : }
    3533        11336664 : END_CASE(JSOP_INITELEM)
    3534                 : 
    3535                 : {
    3536                 : BEGIN_CASE(JSOP_GOSUB)
    3537           22516 :     PUSH_BOOLEAN(false);
    3538           22516 :     int32_t i = (regs.pc - script->code) + JSOP_GOSUB_LENGTH;
    3539           22516 :     len = GET_JUMP_OFFSET(regs.pc);
    3540           22516 :     PUSH_INT32(i);
    3541           22516 : END_VARLEN_CASE
    3542                 : }
    3543                 : 
    3544                 : {
    3545                 : BEGIN_CASE(JSOP_RETSUB)
    3546                 :     /* Pop [exception or hole, retsub pc-index]. */
    3547                 :     Value rval, lval;
    3548           24292 :     POP_COPY_TO(rval);
    3549           24292 :     POP_COPY_TO(lval);
    3550           24292 :     JS_ASSERT(lval.isBoolean());
    3551           24292 :     if (lval.toBoolean()) {
    3552                 :         /*
    3553                 :          * Exception was pending during finally, throw it *before* we adjust
    3554                 :          * pc, because pc indexes into script->trynotes.  This turns out not to
    3555                 :          * be necessary, but it seems clearer.  And it points out a FIXME:
    3556                 :          * 350509, due to Igor Bukanov.
    3557                 :          */
    3558            1795 :         cx->setPendingException(rval);
    3559            1795 :         goto error;
    3560                 :     }
    3561           22497 :     JS_ASSERT(rval.isInt32());
    3562           22497 :     len = rval.toInt32();
    3563           22497 :     regs.pc = script->code;
    3564           22497 : END_VARLEN_CASE
    3565                 : }
    3566                 : 
    3567                 : BEGIN_CASE(JSOP_EXCEPTION)
    3568           46902 :     PUSH_COPY(cx->getPendingException());
    3569           46902 :     cx->clearPendingException();
    3570           46902 :     CHECK_BRANCH();
    3571           46902 : END_CASE(JSOP_EXCEPTION)
    3572                 : 
    3573                 : BEGIN_CASE(JSOP_FINALLY)
    3574           24329 :     CHECK_BRANCH();
    3575           24329 : END_CASE(JSOP_FINALLY)
    3576                 : 
    3577                 : BEGIN_CASE(JSOP_THROWING)
    3578                 : {
    3579              54 :     JS_ASSERT(!cx->isExceptionPending());
    3580                 :     Value v;
    3581              54 :     POP_COPY_TO(v);
    3582              54 :     cx->setPendingException(v);
    3583                 : }
    3584              54 : END_CASE(JSOP_THROWING)
    3585                 : 
    3586                 : BEGIN_CASE(JSOP_THROW)
    3587                 : {
    3588           59131 :     JS_ASSERT(!cx->isExceptionPending());
    3589           59131 :     CHECK_BRANCH();
    3590                 :     Value v;
    3591           59131 :     POP_COPY_TO(v);
    3592           59131 :     cx->setPendingException(v);
    3593                 :     /* let the code at error try to catch the exception. */
    3594           59131 :     goto error;
    3595                 : }
    3596                 : BEGIN_CASE(JSOP_SETLOCALPOP)
    3597                 :     /*
    3598                 :      * The stack must have a block with at least one local slot below the
    3599                 :      * exception object.
    3600                 :      */
    3601          294207 :     JS_ASSERT((size_t) (regs.sp - regs.fp()->base()) >= 2);
    3602          294207 :     POP_COPY_TO(regs.fp()->localSlot(GET_UINT16(regs.pc)));
    3603          294207 : END_CASE(JSOP_SETLOCALPOP)
    3604                 : 
    3605                 : BEGIN_CASE(JSOP_INSTANCEOF)
    3606                 : {
    3607         1137037 :     const Value &rref = regs.sp[-1];
    3608         1137037 :     if (rref.isPrimitive()) {
    3609               0 :         js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS, -1, rref, NULL);
    3610               0 :         goto error;
    3611                 :     }
    3612         1137037 :     JSObject *obj = &rref.toObject();
    3613         1137037 :     const Value &lref = regs.sp[-2];
    3614         1137037 :     JSBool cond = JS_FALSE;
    3615         1137037 :     if (!HasInstance(cx, obj, &lref, &cond))
    3616              19 :         goto error;
    3617         1137018 :     regs.sp--;
    3618         1137018 :     regs.sp[-1].setBoolean(cond);
    3619                 : }
    3620         1137018 : END_CASE(JSOP_INSTANCEOF)
    3621                 : 
    3622                 : BEGIN_CASE(JSOP_DEBUGGER)
    3623                 : {
    3624            4874 :     JSTrapStatus st = JSTRAP_CONTINUE;
    3625                 :     Value rval;
    3626            4874 :     if (JSDebuggerHandler handler = cx->runtime->debugHooks.debuggerHandler)
    3627              59 :         st = handler(cx, script, regs.pc, &rval, cx->runtime->debugHooks.debuggerHandlerData);
    3628            4874 :     if (st == JSTRAP_CONTINUE)
    3629            4869 :         st = Debugger::onDebuggerStatement(cx, &rval);
    3630            4874 :     switch (st) {
    3631                 :       case JSTRAP_ERROR:
    3632             118 :         goto error;
    3633                 :       case JSTRAP_CONTINUE:
    3634            4532 :         break;
    3635                 :       case JSTRAP_RETURN:
    3636             149 :         regs.fp()->setReturnValue(rval);
    3637             149 :         interpReturnOK = true;
    3638             149 :         goto forced_return;
    3639                 :       case JSTRAP_THROW:
    3640              75 :         cx->setPendingException(rval);
    3641              75 :         goto error;
    3642                 :       default:;
    3643                 :     }
    3644            4532 :     CHECK_INTERRUPT_HANDLER();
    3645                 : }
    3646            4532 : END_CASE(JSOP_DEBUGGER)
    3647                 : 
    3648                 : #if JS_HAS_XML_SUPPORT
    3649                 : BEGIN_CASE(JSOP_DEFXMLNS)
    3650                 : {
    3651               9 :     JS_ASSERT(!script->strictModeCode);
    3652                 : 
    3653               9 :     if (!js_SetDefaultXMLNamespace(cx, regs.sp[-1]))
    3654               0 :         goto error;
    3655               9 :     regs.sp--;
    3656                 : }
    3657               9 : END_CASE(JSOP_DEFXMLNS)
    3658                 : 
    3659                 : BEGIN_CASE(JSOP_ANYNAME)
    3660                 : {
    3661              18 :     JS_ASSERT(!script->strictModeCode);
    3662                 : 
    3663                 :     jsid id;
    3664              18 :     if (!js_GetAnyName(cx, &id))
    3665               0 :         goto error;
    3666              18 :     PUSH_COPY(IdToValue(id));
    3667                 : }
    3668              18 : END_CASE(JSOP_ANYNAME)
    3669                 : 
    3670                 : BEGIN_CASE(JSOP_QNAMEPART)
    3671                 : {
    3672                 :     /*
    3673                 :      * We do not JS_ASSERT(!script->strictModeCode) here because JSOP_QNAMEPART
    3674                 :      * is used for __proto__ and (in contexts where we favor JSOP_*ELEM instead
    3675                 :      * of JSOP_*PROP) obj.prop compiled as obj['prop'].
    3676                 :      */
    3677                 : 
    3678                 :     JSAtom *atom;
    3679            7406 :     LOAD_ATOM(0, atom);
    3680            7406 :     PUSH_STRING(atom);
    3681                 : }
    3682            7406 : END_CASE(JSOP_QNAMEPART)
    3683                 : 
    3684                 : BEGIN_CASE(JSOP_QNAMECONST)
    3685                 : {
    3686              45 :     JS_ASSERT(!script->strictModeCode);
    3687                 : 
    3688                 :     JSAtom *atom;
    3689              45 :     LOAD_ATOM(0, atom);
    3690              45 :     Value rval = StringValue(atom);
    3691              45 :     Value lval = regs.sp[-1];
    3692              45 :     JSObject *obj = js_ConstructXMLQNameObject(cx, lval, rval);
    3693              45 :     if (!obj)
    3694               0 :         goto error;
    3695              45 :     regs.sp[-1].setObject(*obj);
    3696                 : }
    3697              45 : END_CASE(JSOP_QNAMECONST)
    3698                 : 
    3699                 : BEGIN_CASE(JSOP_QNAME)
    3700                 : {
    3701               0 :     JS_ASSERT(!script->strictModeCode);
    3702                 : 
    3703               0 :     Value rval = regs.sp[-1];
    3704               0 :     Value lval = regs.sp[-2];
    3705               0 :     JSObject *obj = js_ConstructXMLQNameObject(cx, lval, rval);
    3706               0 :     if (!obj)
    3707               0 :         goto error;
    3708               0 :     regs.sp--;
    3709               0 :     regs.sp[-1].setObject(*obj);
    3710                 : }
    3711               0 : END_CASE(JSOP_QNAME)
    3712                 : 
    3713                 : BEGIN_CASE(JSOP_TOATTRNAME)
    3714                 : {
    3715               0 :     JS_ASSERT(!script->strictModeCode);
    3716                 : 
    3717                 :     Value rval;
    3718               0 :     rval = regs.sp[-1];
    3719               0 :     if (!js_ToAttributeName(cx, &rval))
    3720               0 :         goto error;
    3721               0 :     regs.sp[-1] = rval;
    3722                 : }
    3723               0 : END_CASE(JSOP_TOATTRNAME)
    3724                 : 
    3725                 : BEGIN_CASE(JSOP_TOATTRVAL)
    3726                 : {
    3727               0 :     JS_ASSERT(!script->strictModeCode);
    3728                 : 
    3729                 :     Value rval;
    3730               0 :     rval = regs.sp[-1];
    3731               0 :     JS_ASSERT(rval.isString());
    3732               0 :     JSString *str = js_EscapeAttributeValue(cx, rval.toString(), JS_FALSE);
    3733               0 :     if (!str)
    3734               0 :         goto error;
    3735               0 :     regs.sp[-1].setString(str);
    3736                 : }
    3737               0 : END_CASE(JSOP_TOATTRVAL)
    3738                 : 
    3739                 : BEGIN_CASE(JSOP_ADDATTRNAME)
    3740                 : BEGIN_CASE(JSOP_ADDATTRVAL)
    3741                 : {
    3742               0 :     JS_ASSERT(!script->strictModeCode);
    3743                 : 
    3744               0 :     Value rval = regs.sp[-1];
    3745               0 :     Value lval = regs.sp[-2];
    3746               0 :     JSString *str = lval.toString();
    3747               0 :     JSString *str2 = rval.toString();
    3748               0 :     str = js_AddAttributePart(cx, op == JSOP_ADDATTRNAME, str, str2);
    3749               0 :     if (!str)
    3750               0 :         goto error;
    3751               0 :     regs.sp--;
    3752               0 :     regs.sp[-1].setString(str);
    3753                 : }
    3754               0 : END_CASE(JSOP_ADDATTRNAME)
    3755                 : 
    3756                 : BEGIN_CASE(JSOP_BINDXMLNAME)
    3757                 : {
    3758              18 :     JS_ASSERT(!script->strictModeCode);
    3759                 : 
    3760                 :     Value lval;
    3761              18 :     lval = regs.sp[-1];
    3762                 :     JSObject *obj;
    3763                 :     jsid id;
    3764              18 :     if (!js_FindXMLProperty(cx, lval, &obj, &id))
    3765               0 :         goto error;
    3766              18 :     regs.sp[-1].setObjectOrNull(obj);
    3767              18 :     PUSH_COPY(IdToValue(id));
    3768                 : }
    3769              18 : END_CASE(JSOP_BINDXMLNAME)
    3770                 : 
    3771                 : BEGIN_CASE(JSOP_SETXMLNAME)
    3772                 : {
    3773              18 :     JS_ASSERT(!script->strictModeCode);
    3774                 : 
    3775              18 :     JSObject *obj = &regs.sp[-3].toObject();
    3776              18 :     Value rval = regs.sp[-1];
    3777                 :     jsid id;
    3778              18 :     FETCH_ELEMENT_ID(obj, -2, id);
    3779              18 :     if (!obj->setGeneric(cx, id, &rval, script->strictModeCode))
    3780               0 :         goto error;
    3781              18 :     rval = regs.sp[-1];
    3782              18 :     regs.sp -= 2;
    3783              18 :     regs.sp[-1] = rval;
    3784                 : }
    3785              18 : END_CASE(JSOP_SETXMLNAME)
    3786                 : 
    3787                 : BEGIN_CASE(JSOP_CALLXMLNAME)
    3788                 : BEGIN_CASE(JSOP_XMLNAME)
    3789                 : {
    3790              36 :     JS_ASSERT(!script->strictModeCode);
    3791                 : 
    3792              36 :     Value lval = regs.sp[-1];
    3793                 :     JSObject *obj;
    3794                 :     jsid id;
    3795              36 :     if (!js_FindXMLProperty(cx, lval, &obj, &id))
    3796              27 :         goto error;
    3797                 :     Value rval;
    3798               9 :     if (!obj->getGeneric(cx, id, &rval))
    3799               0 :         goto error;
    3800               9 :     regs.sp[-1] = rval;
    3801               9 :     if (op == JSOP_CALLXMLNAME) {
    3802                 :         Value v;
    3803               0 :         if (!ComputeImplicitThis(cx, obj, &v))
    3804               0 :             goto error;
    3805               0 :         PUSH_COPY(v);
    3806                 :     }
    3807                 : }
    3808               9 : END_CASE(JSOP_XMLNAME)
    3809                 : 
    3810                 : BEGIN_CASE(JSOP_DESCENDANTS)
    3811                 : BEGIN_CASE(JSOP_DELDESC)
    3812                 : {
    3813               9 :     JS_ASSERT(!script->strictModeCode);
    3814                 : 
    3815                 :     JSObject *obj;
    3816               9 :     FETCH_OBJECT(cx, -2, obj);
    3817               9 :     jsval rval = regs.sp[-1];
    3818               9 :     if (!js_GetXMLDescendants(cx, obj, rval, &rval))
    3819               0 :         goto error;
    3820                 : 
    3821               9 :     if (op == JSOP_DELDESC) {
    3822               0 :         regs.sp[-1] = rval;   /* set local root */
    3823               0 :         if (!js_DeleteXMLListElements(cx, JSVAL_TO_OBJECT(rval)))
    3824               0 :             goto error;
    3825               0 :         rval = JSVAL_TRUE;                  /* always succeed */
    3826                 :     }
    3827                 : 
    3828               9 :     regs.sp--;
    3829               9 :     regs.sp[-1] = rval;
    3830                 : }
    3831               9 : END_CASE(JSOP_DESCENDANTS)
    3832                 : 
    3833                 : BEGIN_CASE(JSOP_FILTER)
    3834                 : {
    3835              63 :     JS_ASSERT(!script->strictModeCode);
    3836                 : 
    3837                 :     /*
    3838                 :      * We push the hole value before jumping to [enditer] so we can detect the
    3839                 :      * first iteration and direct js_StepXMLListFilter to initialize filter's
    3840                 :      * state.
    3841                 :      */
    3842              63 :     PUSH_HOLE();
    3843              63 :     len = GET_JUMP_OFFSET(regs.pc);
    3844              63 :     JS_ASSERT(len > 0);
    3845                 : }
    3846              63 : END_VARLEN_CASE
    3847                 : 
    3848                 : BEGIN_CASE(JSOP_ENDFILTER)
    3849                 : {
    3850             126 :     JS_ASSERT(!script->strictModeCode);
    3851                 : 
    3852             126 :     bool cond = !regs.sp[-1].isMagic();
    3853             126 :     if (cond) {
    3854                 :         /* Exit the "with" block left from the previous iteration. */
    3855              63 :         LeaveWith(cx);
    3856                 :     }
    3857             126 :     if (!js_StepXMLListFilter(cx, cond))
    3858               9 :         goto error;
    3859             117 :     if (!regs.sp[-1].isNull()) {
    3860                 :         /*
    3861                 :          * Decrease sp after EnterWith returns as we use sp[-1] there to root
    3862                 :          * temporaries.
    3863                 :          */
    3864              63 :         JS_ASSERT(IsXML(regs.sp[-1]));
    3865              63 :         if (!EnterWith(cx, -2))
    3866               0 :             goto error;
    3867              63 :         regs.sp--;
    3868              63 :         len = GET_JUMP_OFFSET(regs.pc);
    3869              63 :         JS_ASSERT(len < 0);
    3870              63 :         BRANCH(len);
    3871                 :     }
    3872              54 :     regs.sp--;
    3873                 : }
    3874              54 : END_CASE(JSOP_ENDFILTER);
    3875                 : 
    3876                 : BEGIN_CASE(JSOP_TOXML)
    3877                 : {
    3878             596 :     JS_ASSERT(!script->strictModeCode);
    3879                 : 
    3880             596 :     Value rval = regs.sp[-1];
    3881             596 :     JSObject *obj = js_ValueToXMLObject(cx, rval);
    3882             596 :     if (!obj)
    3883               0 :         goto error;
    3884             596 :     regs.sp[-1].setObject(*obj);
    3885                 : }
    3886             596 : END_CASE(JSOP_TOXML)
    3887                 : 
    3888                 : BEGIN_CASE(JSOP_TOXMLLIST)
    3889                 : {
    3890              18 :     JS_ASSERT(!script->strictModeCode);
    3891                 : 
    3892              18 :     Value rval = regs.sp[-1];
    3893              18 :     JSObject *obj = js_ValueToXMLListObject(cx, rval);
    3894              18 :     if (!obj)
    3895               0 :         goto error;
    3896              18 :     regs.sp[-1].setObject(*obj);
    3897                 : }
    3898              18 : END_CASE(JSOP_TOXMLLIST)
    3899                 : 
    3900                 : BEGIN_CASE(JSOP_XMLTAGEXPR)
    3901                 : {
    3902               0 :     JS_ASSERT(!script->strictModeCode);
    3903                 : 
    3904               0 :     Value rval = regs.sp[-1];
    3905               0 :     JSString *str = ToString(cx, rval);
    3906               0 :     if (!str)
    3907               0 :         goto error;
    3908               0 :     regs.sp[-1].setString(str);
    3909                 : }
    3910               0 : END_CASE(JSOP_XMLTAGEXPR)
    3911                 : 
    3912                 : BEGIN_CASE(JSOP_XMLELTEXPR)
    3913                 : {
    3914               0 :     JS_ASSERT(!script->strictModeCode);
    3915                 : 
    3916               0 :     Value rval = regs.sp[-1];
    3917                 :     JSString *str;
    3918               0 :     if (IsXML(rval)) {
    3919               0 :         str = js_ValueToXMLString(cx, rval);
    3920                 :     } else {
    3921               0 :         str = ToString(cx, rval);
    3922               0 :         if (str)
    3923               0 :             str = js_EscapeElementValue(cx, str);
    3924                 :     }
    3925               0 :     if (!str)
    3926               0 :         goto error;
    3927               0 :     regs.sp[-1].setString(str);
    3928                 : }
    3929               0 : END_CASE(JSOP_XMLELTEXPR)
    3930                 : 
    3931                 : BEGIN_CASE(JSOP_XMLCDATA)
    3932                 : {
    3933               0 :     JS_ASSERT(!script->strictModeCode);
    3934                 : 
    3935               0 :     JSAtom *atom = script->getAtom(GET_UINT32_INDEX(regs.pc));
    3936               0 :     JSObject *obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_TEXT, NULL, atom);
    3937               0 :     if (!obj)
    3938               0 :         goto error;
    3939               0 :     PUSH_OBJECT(*obj);
    3940                 : }
    3941               0 : END_CASE(JSOP_XMLCDATA)
    3942                 : 
    3943                 : BEGIN_CASE(JSOP_XMLCOMMENT)
    3944                 : {
    3945               0 :     JS_ASSERT(!script->strictModeCode);
    3946                 : 
    3947               0 :     JSAtom *atom = script->getAtom(GET_UINT32_INDEX(regs.pc));
    3948               0 :     JSObject *obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_COMMENT, NULL, atom);
    3949               0 :     if (!obj)
    3950               0 :         goto error;
    3951               0 :     PUSH_OBJECT(*obj);
    3952                 : }
    3953               0 : END_CASE(JSOP_XMLCOMMENT)
    3954                 : 
    3955                 : BEGIN_CASE(JSOP_XMLPI)
    3956                 : {
    3957               0 :     JS_ASSERT(!script->strictModeCode);
    3958                 : 
    3959               0 :     JSAtom *atom = script->getAtom(GET_UINT32_INDEX(regs.pc));
    3960               0 :     Value rval = regs.sp[-1];
    3961               0 :     JSString *str2 = rval.toString();
    3962               0 :     JSObject *obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_PROCESSING_INSTRUCTION, atom, str2);
    3963               0 :     if (!obj)
    3964               0 :         goto error;
    3965               0 :     regs.sp[-1].setObject(*obj);
    3966                 : }
    3967               0 : END_CASE(JSOP_XMLPI)
    3968                 : 
    3969                 : BEGIN_CASE(JSOP_GETFUNNS)
    3970                 : {
    3971              36 :     JS_ASSERT(!script->strictModeCode);
    3972                 : 
    3973                 :     Value rval;
    3974              36 :     if (!cx->fp()->scopeChain().global().getFunctionNamespace(cx, &rval))
    3975               0 :         goto error;
    3976              36 :     PUSH_COPY(rval);
    3977                 : }
    3978              36 : END_CASE(JSOP_GETFUNNS)
    3979                 : #endif /* JS_HAS_XML_SUPPORT */
    3980                 : 
    3981                 : BEGIN_CASE(JSOP_ENTERBLOCK)
    3982                 : BEGIN_CASE(JSOP_ENTERLET0)
    3983                 : BEGIN_CASE(JSOP_ENTERLET1)
    3984                 : {
    3985          546775 :     StaticBlockObject &blockObj = script->getObject(GET_UINT32_INDEX(regs.pc))->asStaticBlock();
    3986          546775 :     JS_ASSERT(regs.fp()->maybeBlockChain() == blockObj.enclosingBlock());
    3987                 : 
    3988          546775 :     if (op == JSOP_ENTERBLOCK) {
    3989          386667 :         JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() == regs.sp);
    3990          386667 :         Value *vp = regs.sp + blockObj.slotCount();
    3991          386667 :         JS_ASSERT(regs.sp < vp);
    3992          386667 :         JS_ASSERT(vp <= regs.fp()->slots() + script->nslots);
    3993          386667 :         SetValueRangeToUndefined(regs.sp, vp);
    3994          386667 :         regs.sp = vp;
    3995          160108 :     } else if (op == JSOP_ENTERLET0) {
    3996           47851 :         JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() + blockObj.slotCount()
    3997           47851 :                   == regs.sp);
    3998          112257 :     } else if (op == JSOP_ENTERLET1) {
    3999          112257 :         JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() + blockObj.slotCount()
    4000          112257 :                   == regs.sp - 1);
    4001                 :     }
    4002                 : 
    4003                 : #ifdef DEBUG
    4004          546775 :     JS_ASSERT(regs.fp()->maybeBlockChain() == blockObj.enclosingBlock());
    4005                 : 
    4006                 :     /*
    4007                 :      * The young end of fp->scopeChain may omit blocks if we haven't closed
    4008                 :      * over them, but if there are any closure blocks on fp->scopeChain, they'd
    4009                 :      * better be (clones of) ancestors of the block we're entering now;
    4010                 :      * anything else we should have popped off fp->scopeChain when we left its
    4011                 :      * static scope.
    4012                 :      */
    4013          546775 :     JSObject *obj2 = &regs.fp()->scopeChain();
    4014         1093712 :     while (obj2->isWith())
    4015             162 :         obj2 = &obj2->asWith().enclosingScope();
    4016          556001 :     if (obj2->isBlock() &&
    4017            9226 :         obj2->getPrivate() == js_FloatingFrameIfGenerator(cx, regs.fp()))
    4018                 :     {
    4019            7959 :         StaticBlockObject &youngestProto = obj2->asClonedBlock().staticBlock();
    4020            7959 :         StaticBlockObject *parent = &blockObj;
    4021           17203 :         while ((parent = parent->enclosingBlock()) != &youngestProto)
    4022            1285 :             JS_ASSERT(parent);
    4023                 :     }
    4024                 : #endif
    4025                 : 
    4026          546775 :     regs.fp()->setBlockChain(&blockObj);
    4027                 : }
    4028          546775 : END_CASE(JSOP_ENTERBLOCK)
    4029                 : 
    4030                 : BEGIN_CASE(JSOP_LEAVEBLOCK)
    4031                 : BEGIN_CASE(JSOP_LEAVEFORLETIN)
    4032                 : BEGIN_CASE(JSOP_LEAVEBLOCKEXPR)
    4033                 : {
    4034          547207 :     StaticBlockObject &blockObj = regs.fp()->blockChain();
    4035          547207 :     JS_ASSERT(blockObj.stackDepth() <= StackDepth(script));
    4036                 : 
    4037                 :     /*
    4038                 :      * If we're about to leave the dynamic scope of a block that has been
    4039                 :      * cloned onto fp->scopeChain, clear its private data, move its locals from
    4040                 :      * the stack into the clone, and pop it off the chain.
    4041                 :      */
    4042          547207 :     JSObject &scope = regs.fp()->scopeChain();
    4043          547207 :     if (scope.getProto() == &blockObj)
    4044           17202 :         scope.asClonedBlock().put(cx);
    4045                 : 
    4046          547207 :     regs.fp()->setBlockChain(blockObj.enclosingBlock());
    4047                 : 
    4048          547207 :     if (op == JSOP_LEAVEBLOCK) {
    4049                 :         /* Pop the block's slots. */
    4050          445339 :         regs.sp -= GET_UINT16(regs.pc);
    4051          445339 :         JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() == regs.sp);
    4052          101868 :     } else if (op == JSOP_LEAVEBLOCKEXPR) {
    4053                 :         /* Pop the block's slots maintaining the topmost expr. */
    4054             930 :         Value *vp = &regs.sp[-1];
    4055             930 :         regs.sp -= GET_UINT16(regs.pc);
    4056             930 :         JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() == regs.sp - 1);
    4057             930 :         regs.sp[-1] = *vp;
    4058                 :     } else {
    4059                 :         /* Another op will pop; nothing to do here. */
    4060          100938 :         len = JSOP_LEAVEFORLETIN_LENGTH;
    4061          100938 :         DO_NEXT_OP(len);
    4062                 :     }
    4063                 : }
    4064          446269 : END_CASE(JSOP_LEAVEBLOCK)
    4065                 : 
    4066                 : #if JS_HAS_GENERATORS
    4067                 : BEGIN_CASE(JSOP_GENERATOR)
    4068                 : {
    4069           12263 :     JS_ASSERT(!cx->isExceptionPending());
    4070           12263 :     regs.pc += JSOP_GENERATOR_LENGTH;
    4071           12263 :     JSObject *obj = js_NewGenerator(cx);
    4072           12263 :     if (!obj)
    4073               0 :         goto error;
    4074           12263 :     JS_ASSERT(!regs.fp()->hasCallObj() && !regs.fp()->hasArgsObj());
    4075           12263 :     regs.fp()->setReturnValue(ObjectValue(*obj));
    4076           12263 :     interpReturnOK = true;
    4077           12263 :     if (entryFrame != regs.fp())
    4078            9939 :         goto inline_return;
    4079            2324 :     goto exit;
    4080                 : }
    4081                 : 
    4082                 : BEGIN_CASE(JSOP_YIELD)
    4083           23131 :     JS_ASSERT(!cx->isExceptionPending());
    4084           23131 :     JS_ASSERT(regs.fp()->isNonEvalFunctionFrame());
    4085           23131 :     if (cx->generatorFor(regs.fp())->state == JSGEN_CLOSING) {
    4086               0 :         js_ReportValueError(cx, JSMSG_BAD_GENERATOR_YIELD,
    4087               0 :                             JSDVG_SEARCH_STACK, argv[-2], NULL);
    4088               0 :         goto error;
    4089                 :     }
    4090           23131 :     regs.fp()->setReturnValue(regs.sp[-1]);
    4091           23131 :     regs.fp()->setYielding();
    4092           23131 :     regs.pc += JSOP_YIELD_LENGTH;
    4093           23131 :     interpReturnOK = true;
    4094           23131 :     goto exit;
    4095                 : 
    4096                 : BEGIN_CASE(JSOP_ARRAYPUSH)
    4097                 : {
    4098          940755 :     uint32_t slot = GET_UINT16(regs.pc);
    4099          940755 :     JS_ASSERT(script->nfixed <= slot);
    4100          940755 :     JS_ASSERT(slot < script->nslots);
    4101          940755 :     JSObject *obj = &regs.fp()->slots()[slot].toObject();
    4102          940755 :     if (!js_NewbornArrayPush(cx, obj, regs.sp[-1]))
    4103               0 :         goto error;
    4104          940755 :     regs.sp--;
    4105                 : }
    4106          940755 : END_CASE(JSOP_ARRAYPUSH)
    4107                 : #endif /* JS_HAS_GENERATORS */
    4108                 : 
    4109                 : #if JS_THREADED_INTERP
    4110                 :   L_JSOP_BACKPATCH:
    4111                 :   L_JSOP_BACKPATCH_POP:
    4112                 : 
    4113                 : # if !JS_HAS_GENERATORS
    4114                 :   L_JSOP_GENERATOR:
    4115                 :   L_JSOP_YIELD:
    4116                 :   L_JSOP_ARRAYPUSH:
    4117                 : # endif
    4118                 : 
    4119                 : # if !JS_HAS_DESTRUCTURING
    4120                 :   L_JSOP_ENUMCONSTELEM:
    4121                 : # endif
    4122                 : 
    4123                 : # if !JS_HAS_XML_SUPPORT
    4124                 :   L_JSOP_CALLXMLNAME:
    4125                 :   L_JSOP_STARTXMLEXPR:
    4126                 :   L_JSOP_STARTXML:
    4127                 :   L_JSOP_DELDESC:
    4128                 :   L_JSOP_GETFUNNS:
    4129                 :   L_JSOP_XMLPI:
    4130                 :   L_JSOP_XMLCOMMENT:
    4131                 :   L_JSOP_XMLCDATA:
    4132                 :   L_JSOP_XMLELTEXPR:
    4133                 :   L_JSOP_XMLTAGEXPR:
    4134                 :   L_JSOP_TOXMLLIST:
    4135                 :   L_JSOP_TOXML:
    4136                 :   L_JSOP_ENDFILTER:
    4137                 :   L_JSOP_FILTER:
    4138                 :   L_JSOP_DESCENDANTS:
    4139                 :   L_JSOP_XMLNAME:
    4140                 :   L_JSOP_SETXMLNAME:
    4141                 :   L_JSOP_BINDXMLNAME:
    4142                 :   L_JSOP_ADDATTRVAL:
    4143                 :   L_JSOP_ADDATTRNAME:
    4144                 :   L_JSOP_TOATTRVAL:
    4145                 :   L_JSOP_TOATTRNAME:
    4146                 :   L_JSOP_QNAME:
    4147                 :   L_JSOP_QNAMECONST:
    4148                 :   L_JSOP_QNAMEPART:
    4149                 :   L_JSOP_ANYNAME:
    4150                 :   L_JSOP_DEFXMLNS:
    4151                 : # endif
    4152                 : 
    4153                 : #endif /* !JS_THREADED_INTERP */
    4154                 : #if !JS_THREADED_INTERP
    4155                 :           default:
    4156                 : #endif
    4157                 :           {
    4158                 :             char numBuf[12];
    4159               0 :             JS_snprintf(numBuf, sizeof numBuf, "%d", op);
    4160                 :             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
    4161               0 :                                  JSMSG_BAD_BYTECODE, numBuf);
    4162               0 :             goto error;
    4163                 :           }
    4164                 : 
    4165                 : #if !JS_THREADED_INTERP
    4166                 :         } /* switch (op) */
    4167                 :     } /* for (;;) */
    4168                 : #endif /* !JS_THREADED_INTERP */
    4169                 : 
    4170                 :   error:
    4171         2122765 :     JS_ASSERT(&cx->regs() == &regs);
    4172         2122765 :     JS_ASSERT(uint32_t(regs.pc - script->code) < script->length);
    4173                 : 
    4174         2122765 :     if (cx->isExceptionPending()) {
    4175                 :         /* Restore atoms local in case we will resume. */
    4176         2120574 :         atoms = script->atoms;
    4177                 : 
    4178                 :         /* Call debugger throw hook if set. */
    4179         2120574 :         if (cx->runtime->debugHooks.throwHook || !cx->compartment->getDebuggees().empty()) {
    4180                 :             Value rval;
    4181           29457 :             JSTrapStatus st = Debugger::onExceptionUnwind(cx, &rval);
    4182           29457 :             if (st == JSTRAP_CONTINUE) {
    4183           29422 :                 if (JSThrowHook handler = cx->runtime->debugHooks.throwHook)
    4184           28758 :                     st = handler(cx, script, regs.pc, &rval, cx->runtime->debugHooks.throwHookData);
    4185                 :             }
    4186                 : 
    4187           29457 :             switch (st) {
    4188                 :               case JSTRAP_ERROR:
    4189              20 :                 cx->clearPendingException();
    4190              20 :                 goto error;
    4191                 :               case JSTRAP_RETURN:
    4192              15 :                 cx->clearPendingException();
    4193              15 :                 regs.fp()->setReturnValue(rval);
    4194              15 :                 interpReturnOK = true;
    4195              15 :                 goto forced_return;
    4196                 :               case JSTRAP_THROW:
    4197               5 :                 cx->setPendingException(rval);
    4198                 :               case JSTRAP_CONTINUE:
    4199                 :               default:;
    4200                 :             }
    4201           29422 :             CHECK_INTERRUPT_HANDLER();
    4202                 :         }
    4203                 : 
    4204         2123354 :         for (TryNoteIter tni(regs); !tni.done(); ++tni) {
    4205           51482 :             JSTryNote *tn = *tni;
    4206                 : 
    4207           51482 :             UnwindScope(cx, tn->stackDepth);
    4208                 : 
    4209                 :             /*
    4210                 :              * Set pc to the first bytecode after the the try note to point
    4211                 :              * to the beginning of catch or finally or to [enditer] closing
    4212                 :              * the for-in loop.
    4213                 :              */
    4214           51482 :             regs.pc = (script)->main() + tn->start + tn->length;
    4215           51482 :             regs.sp = regs.fp()->base() + tn->stackDepth;
    4216                 : 
    4217           51482 :             switch (tn->kind) {
    4218                 :               case JSTRY_CATCH:
    4219           49558 :                   JS_ASSERT(*regs.pc == JSOP_ENTERBLOCK);
    4220                 : 
    4221                 : #if JS_HAS_GENERATORS
    4222                 :                 /* Catch cannot intercept the closing of a generator. */
    4223           49558 :                   if (JS_UNLIKELY(cx->getPendingException().isMagic(JS_GENERATOR_CLOSING)))
    4224            2710 :                     break;
    4225                 : #endif
    4226                 : 
    4227                 :                 /*
    4228                 :                  * Don't clear exceptions to save cx->exception from GC
    4229                 :                  * until it is pushed to the stack via [exception] in the
    4230                 :                  * catch block.
    4231                 :                  */
    4232           46848 :                 len = 0;
    4233           46848 :                 DO_NEXT_OP(len);
    4234                 : 
    4235                 :               case JSTRY_FINALLY:
    4236                 :                 /*
    4237                 :                  * Push (true, exception) pair for finally to indicate that
    4238                 :                  * [retsub] should rethrow the exception.
    4239                 :                  */
    4240            1813 :                 PUSH_BOOLEAN(true);
    4241            1813 :                 PUSH_COPY(cx->getPendingException());
    4242            1813 :                 cx->clearPendingException();
    4243            1813 :                 len = 0;
    4244            1813 :                 DO_NEXT_OP(len);
    4245                 : 
    4246                 :               case JSTRY_ITER: {
    4247                 :                 /* This is similar to JSOP_ENDITER in the interpreter loop. */
    4248             111 :                 JS_ASSERT(JSOp(*regs.pc) == JSOP_ENDITER);
    4249             111 :                 bool ok = UnwindIteratorForException(cx, &regs.sp[-1].toObject());
    4250             111 :                 regs.sp -= 1;
    4251             111 :                 if (!ok)
    4252               6 :                     goto error;
    4253                 :               }
    4254                 :            }
    4255                 :         }
    4256                 : 
    4257                 :         /*
    4258                 :          * Propagate the exception or error to the caller unless the exception
    4259                 :          * is an asynchronous return from a generator.
    4260                 :          */
    4261         2071872 :         interpReturnOK = false;
    4262                 : #if JS_HAS_GENERATORS
    4263         2071872 :         if (JS_UNLIKELY(cx->isExceptionPending() &&
    4264                 :                         cx->getPendingException().isMagic(JS_GENERATOR_CLOSING))) {
    4265            1487 :             cx->clearPendingException();
    4266            1487 :             interpReturnOK = true;
    4267            1487 :             regs.fp()->clearReturnValue();
    4268                 :         }
    4269                 : #endif
    4270                 :     } else {
    4271            2191 :         UnwindForUncatchableException(cx, regs);
    4272            2191 :         interpReturnOK = false;
    4273                 :     }
    4274                 : 
    4275                 :   forced_return:
    4276         2074291 :     UnwindScope(cx, 0);
    4277         2074291 :     regs.sp = regs.fp()->base();
    4278                 : 
    4279         2074291 :     if (entryFrame != regs.fp())
    4280         2004357 :         goto inline_return;
    4281                 : 
    4282                 :   exit:
    4283         1977034 :     if (cx->compartment->debugMode())
    4284          610449 :         interpReturnOK = ScriptDebugEpilogue(cx, regs.fp(), interpReturnOK);
    4285         1977034 :     interpReturnOK = ScriptEpilogueOrGeneratorYield(cx, regs.fp(), interpReturnOK);
    4286         1977034 :     regs.fp()->setFinishedInInterpreter();
    4287                 : 
    4288                 :     /*
    4289                 :      * At this point we are inevitably leaving an interpreted function or a
    4290                 :      * top-level script, and returning to one of:
    4291                 :      * (a) an "out of line" call made through Invoke;
    4292                 :      * (b) a js_Execute activation;
    4293                 :      * (c) a generator (SendToGenerator, jsiter.c).
    4294                 :      *
    4295                 :      * We must not be in an inline frame. The check above ensures that for the
    4296                 :      * error case and for a normal return, the code jumps directly to parent's
    4297                 :      * frame pc.
    4298                 :      */
    4299         1977034 :     JS_ASSERT(entryFrame == regs.fp());
    4300         1977034 :     if (!regs.fp()->isGeneratorFrame()) {
    4301         1946200 :         JS_ASSERT(!IsActiveWithOrBlock(cx, regs.fp()->scopeChain(), 0));
    4302         1946200 :         JS_ASSERT(!regs.fp()->hasBlockChain());
    4303                 :     }
    4304                 : 
    4305                 : #ifdef JS_METHODJIT
    4306                 :     /*
    4307                 :      * This path is used when it's guaranteed the method can be finished
    4308                 :      * inside the JIT.
    4309                 :      */
    4310                 :   leave_on_safe_point:
    4311                 : #endif
    4312                 : 
    4313         1977915 :     gc::MaybeVerifyBarriers(cx, true);
    4314         1977915 :     return interpReturnOK;
    4315                 : }

Generated by: LCOV version 1.7