LCOV - code coverage report
Current view: directory - js/src - jsinterp.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 1736 1444 83.2 %
Date: 2012-04-07 Functions: 41 40 97.6 %

       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          783158 : js::GetScopeChain(JSContext *cx, StackFrame *fp)
     140                 : {
     141          783158 :     StaticBlockObject *sharedBlock = fp->maybeBlockChain();
     142                 : 
     143          783158 :     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         2301198 :         JS_ASSERT_IF(fp->isNonEvalFunctionFrame() && fp->fun()->isHeavyweight(),
     149         2301198 :                      fp->hasCallObj());
     150          779557 :         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            3601 :     if (fp->isNonEvalFunctionFrame() && !fp->hasCallObj()) {
     162               0 :         JS_ASSERT_IF(fp->scopeChain().isClonedBlock(), fp->scopeChain().getPrivate() != fp);
     163               0 :         if (!CallObject::createForFunction(cx, fp))
     164               0 :             return NULL;
     165                 : 
     166                 :         /* We know we must clone everything on blockChain. */
     167               0 :         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            3601 :         limitClone = &fp->scopeChain();
     176            7274 :         while (limitClone->isWith())
     177              72 :             limitClone = &limitClone->asWith().enclosingScope();
     178            3601 :         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            3601 :         limitBlock = limitClone->getProto();
     199                 : 
     200                 :         /* If the innermost block has already been cloned, we are done. */
     201            3601 :         if (limitBlock == sharedBlock)
     202            1746 :             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            1855 :     ClonedBlockObject *innermostNewChild = ClonedBlockObject::create(cx, *sharedBlock, fp);
     212            1855 :     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            1855 :     ClonedBlockObject *newChild = innermostNewChild;
     220              72 :     for (;;) {
     221            1927 :         JS_ASSERT(newChild->getProto() == sharedBlock);
     222            1927 :         sharedBlock = sharedBlock->enclosingBlock();
     223                 : 
     224                 :         /* Sometimes limitBlock will be NULL, so check that first.  */
     225            1927 :         if (sharedBlock == limitBlock || !sharedBlock)
     226                 :             break;
     227                 : 
     228                 :         /* As in the call above, we don't know the real parent yet.  */
     229              72 :         ClonedBlockObject *clone = ClonedBlockObject::create(cx, *sharedBlock, fp);
     230              72 :         if (!clone)
     231               0 :             return NULL;
     232                 : 
     233              72 :         if (!newChild->setEnclosingScope(cx, *clone))
     234               0 :             return NULL;
     235              72 :         newChild = clone;
     236                 :     }
     237            1855 :     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             936 :     JS_ASSERT_IF(limitBlock &&
     246                 :                  limitBlock->isClonedBlock() &&
     247                 :                  limitClone->getPrivate() == js_FloatingFrameIfGenerator(cx, fp),
     248            2791 :                  sharedBlock);
     249                 : 
     250                 :     /* Place our newly cloned blocks at the head of the scope chain.  */
     251            1855 :     fp->setScopeChainNoCallObj(*innermostNewChild);
     252            1855 :     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           61048 : 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           61048 :     Value &thisv = call.thisv();
     320           61048 :     JS_ASSERT(!thisv.isMagic());
     321                 : 
     322                 : #ifdef DEBUG
     323           61048 :     JSFunction *fun = call.callee().isFunction() ? call.callee().toFunction() : NULL;
     324           61048 :     JS_ASSERT_IF(fun && fun->isInterpreted(), !fun->inStrictMode());
     325                 : #endif
     326                 : 
     327           61048 :     if (thisv.isNullOrUndefined()) {
     328           59998 :         JSObject *thisp = call.callee().global().thisObject(cx);
     329           59998 :         if (!thisp)
     330               0 :             return false;
     331           59998 :         call.thisv().setObject(*thisp);
     332           59998 :         return true;
     333                 :     }
     334                 : 
     335            1050 :     if (!thisv.isObject())
     336             447 :         return !!js_PrimitiveToObject(cx, &thisv);
     337                 : 
     338             603 :     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             826 : js::OnUnknownMethod(JSContext *cx, JSObject *obj, Value idval, Value *vp)
     369                 : {
     370             826 :     jsid id = ATOM_TO_JSID(cx->runtime->atomState.noSuchMethodAtom);
     371            1652 :     AutoValueRooter tvr(cx);
     372             826 :     if (!js_GetMethod(cx, obj, id, 0, tvr.addr()))
     373               0 :         return false;
     374             826 :     TypeScript::MonitorUnknown(cx, cx->fp()->script(), cx->regs().pc);
     375                 : 
     376             826 :     if (tvr.value().isPrimitive()) {
     377              97 :         *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             826 :     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         1547479 : js::RunScript(JSContext *cx, JSScript *script, StackFrame *fp)
     427                 : {
     428         1547479 :     JS_ASSERT(script);
     429         1547479 :     JS_ASSERT(fp == cx->fp());
     430         1547479 :     JS_ASSERT(fp->script() == script);
     431         1547479 :     JS_ASSERT_IF(!fp->isGeneratorFrame(), cx->regs().pc == script->code);
     432                 : #ifdef JS_METHODJIT_SPEW
     433         1547479 :     JMCheckLogging();
     434                 : #endif
     435                 : 
     436         1547479 :     JS_CHECK_RECURSION(cx, return false);
     437                 : 
     438                 :     /* FIXME: Once bug 470510 is fixed, make this an assert. */
     439         1547396 :     if (script->compileAndGo) {
     440         1539520 :         if (fp->scopeChain().global().isCleared()) {
     441               0 :             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CLEARED_SCOPE);
     442               0 :             return false;
     443                 :         }
     444                 :     }
     445                 : 
     446                 : #ifdef DEBUG
     447                 :     struct CheckStackBalance {
     448                 :         JSContext *cx;
     449                 :         StackFrame *fp;
     450                 :         JSObject *enumerators;
     451         1547396 :         CheckStackBalance(JSContext *cx)
     452         1547396 :           : cx(cx), fp(cx->fp()), enumerators(cx->enumerators)
     453         1547396 :         {}
     454         1547396 :         ~CheckStackBalance() {
     455         1547396 :             JS_ASSERT(fp == cx->fp());
     456         1547396 :             JS_ASSERT_IF(!fp->isGeneratorFrame(), enumerators == cx->enumerators);
     457         1547396 :         }
     458         3094792 :     } check(cx);
     459                 : #endif
     460                 : 
     461                 : #ifdef JS_METHODJIT
     462                 :     mjit::CompileStatus status;
     463         1547396 :     status = mjit::CanMethodJIT(cx, script, script->code, fp->isConstructing(),
     464         1547396 :                                 mjit::CompileRequest_Interpreter);
     465         1547396 :     if (status == mjit::Compile_Error)
     466               0 :         return false;
     467                 : 
     468         1547396 :     if (status == mjit::Compile_Okay)
     469         1063402 :         return mjit::JaegerStatusToSuccess(mjit::JaegerShot(cx, false));
     470                 : #endif
     471                 : 
     472          483994 :     return Interpret(cx, fp);
     473                 : }
     474                 : 
     475                 : /*
     476                 :  * Find a function reference and its 'this' value implicit first parameter
     477                 :  * under argc arguments on cx's stack, and call the function.  Push missing
     478                 :  * required arguments, allocate declared local variables, and pop everything
     479                 :  * when done.  Then push the return value.
     480                 :  */
     481                 : bool
     482         9022674 : js::InvokeKernel(JSContext *cx, CallArgs args, MaybeConstruct construct)
     483                 : {
     484         9022674 :     JS_ASSERT(args.length() <= StackSpace::ARGS_LENGTH_MAX);
     485         9022674 :     JS_ASSERT(!cx->compartment->activeAnalysis);
     486                 : 
     487                 :     /* MaybeConstruct is a subset of InitialFrameFlags */
     488         9022674 :     InitialFrameFlags initial = (InitialFrameFlags) construct;
     489                 : 
     490         9022674 :     if (args.calleev().isPrimitive()) {
     491             387 :         js_ReportIsNotFunction(cx, &args.calleev(), ToReportFlags(initial));
     492             387 :         return false;
     493                 :     }
     494                 : 
     495         9022287 :     JSObject &callee = args.callee();
     496         9022287 :     Class *clasp = callee.getClass();
     497                 : 
     498                 :     /* Invoke non-functions. */
     499         9022287 :     if (JS_UNLIKELY(clasp != &FunctionClass)) {
     500                 : #if JS_HAS_NO_SUCH_METHOD
     501           21739 :         if (JS_UNLIKELY(clasp == &js_NoSuchMethodClass))
     502             729 :             return NoSuchMethod(cx, args.length(), args.base());
     503                 : #endif
     504           21010 :         JS_ASSERT_IF(construct, !clasp->construct);
     505           21010 :         if (!clasp->call) {
     506              91 :             js_ReportIsNotFunction(cx, &args.calleev(), ToReportFlags(initial));
     507              91 :             return false;
     508                 :         }
     509           20919 :         return CallJSNative(cx, clasp->call, args);
     510                 :     }
     511                 : 
     512                 :     /* Invoke native functions. */
     513         9000548 :     JSFunction *fun = callee.toFunction();
     514         9000548 :     JS_ASSERT_IF(construct, !fun->isNativeConstructor());
     515         9000548 :     if (fun->isNative())
     516         7624791 :         return CallJSNative(cx, fun->native(), args);
     517                 : 
     518         1375757 :     TypeMonitorCall(cx, args, construct);
     519                 : 
     520                 :     /* Get pointer to new frame/slots, prepare arguments. */
     521         2751514 :     InvokeFrameGuard ifg;
     522         1375757 :     if (!cx->stack.pushInvokeFrame(cx, args, initial, &ifg))
     523              28 :         return false;
     524                 : 
     525                 :     /* Now that the new frame is rooted, maybe create a call object. */
     526         1375729 :     StackFrame *fp = ifg.fp();
     527         1375729 :     if (!fp->functionPrologue(cx))
     528               0 :         return false;
     529                 : 
     530                 :     /* Run function until JSOP_STOP, JSOP_RETURN or error. */
     531         1375729 :     JSBool ok = RunScript(cx, fun->script(), fp);
     532                 : 
     533                 :     /* Propagate the return value out. */
     534         1375729 :     args.rval() = fp->returnValue();
     535         1375729 :     JS_ASSERT_IF(ok && construct, !args.rval().isPrimitive());
     536         1375729 :     return ok;
     537                 : }
     538                 : 
     539                 : bool
     540         1488650 : js::Invoke(JSContext *cx, const Value &thisv, const Value &fval, unsigned argc, Value *argv,
     541                 :            Value *rval)
     542                 : {
     543         2977300 :     InvokeArgsGuard args;
     544         1488650 :     if (!cx->stack.pushInvokeArgs(cx, argc, &args))
     545               0 :         return false;
     546                 : 
     547         1488650 :     args.calleev() = fval;
     548         1488650 :     args.thisv() = thisv;
     549         1488650 :     PodCopy(args.array(), argv, argc);
     550                 : 
     551         1488650 :     if (args.thisv().isObject()) {
     552                 :         /*
     553                 :          * We must call the thisObject hook in case we are not called from the
     554                 :          * interpreter, where a prior bytecode has computed an appropriate
     555                 :          * |this| already.
     556                 :          */
     557         1486671 :         JSObject *thisp = args.thisv().toObject().thisObject(cx);
     558         1486671 :         if (!thisp)
     559               0 :              return false;
     560         1486671 :         args.thisv().setObject(*thisp);
     561                 :     }
     562                 : 
     563         1488650 :     if (!Invoke(cx, args))
     564           27445 :         return false;
     565                 : 
     566         1461205 :     *rval = args.rval();
     567         1461205 :     return true;
     568                 : }
     569                 : 
     570                 : bool
     571          215471 : js::InvokeConstructorKernel(JSContext *cx, const CallArgs &argsRef)
     572                 : {
     573          215471 :     JS_ASSERT(!FunctionClass.construct);
     574          215471 :     CallArgs args = argsRef;
     575                 : 
     576          215471 :     args.thisv().setMagic(JS_IS_CONSTRUCTING);
     577                 : 
     578          215471 :     if (args.calleev().isObject()) {
     579          215444 :         JSObject *callee = &args.callee();
     580          215444 :         Class *clasp = callee->getClass();
     581          215444 :         if (clasp == &FunctionClass) {
     582          215227 :             JSFunction *fun = callee->toFunction();
     583                 : 
     584          215227 :             if (fun->isNativeConstructor()) {
     585          214660 :                 Probes::calloutBegin(cx, fun);
     586          214660 :                 bool ok = CallJSNativeConstructor(cx, fun->native(), args);
     587          214660 :                 Probes::calloutEnd(cx, fun);
     588          214660 :                 return ok;
     589                 :             }
     590                 : 
     591             567 :             if (!fun->isInterpretedConstructor())
     592             252 :                 goto error;
     593                 : 
     594             315 :             if (!InvokeKernel(cx, args, CONSTRUCT))
     595              63 :                 return false;
     596                 : 
     597             252 :             JS_ASSERT(args.rval().isObject());
     598             252 :             return true;
     599                 :         }
     600             217 :         if (clasp->construct)
     601             208 :             return CallJSNativeConstructor(cx, clasp->construct, args);
     602                 :     }
     603                 : 
     604                 : error:
     605             288 :     js_ReportIsNotFunction(cx, &args.calleev(), JSV2F_CONSTRUCT);
     606             288 :     return false;
     607                 : }
     608                 : 
     609                 : bool
     610           12682 : js::InvokeConstructor(JSContext *cx, const Value &fval, unsigned argc, Value *argv, Value *rval)
     611                 : {
     612           25364 :     InvokeArgsGuard args;
     613           12682 :     if (!cx->stack.pushInvokeArgs(cx, argc, &args))
     614               0 :         return false;
     615                 : 
     616           12682 :     args.calleev() = fval;
     617           12682 :     args.thisv().setMagic(JS_THIS_POISON);
     618           12682 :     PodCopy(args.array(), argv, argc);
     619                 : 
     620           12682 :     if (!InvokeConstructor(cx, args))
     621              72 :         return false;
     622                 : 
     623           12610 :     *rval = args.rval();
     624           12610 :     return true;
     625                 : }
     626                 : 
     627                 : bool
     628          346366 : js::InvokeGetterOrSetter(JSContext *cx, JSObject *obj, const Value &fval, unsigned argc, Value *argv,
     629                 :                          Value *rval)
     630                 : {
     631                 :     /*
     632                 :      * Invoke could result in another try to get or set the same id again, see
     633                 :      * bug 355497.
     634                 :      */
     635          346366 :     JS_CHECK_RECURSION(cx, return false);
     636                 : 
     637          346361 :     return Invoke(cx, ObjectValue(*obj), fval, argc, argv, rval);
     638                 : }
     639                 : 
     640                 : bool
     641          153147 : js::ExecuteKernel(JSContext *cx, JSScript *script, JSObject &scopeChain, const Value &thisv,
     642                 :                   ExecuteType type, StackFrame *evalInFrame, Value *result)
     643                 : {
     644          153147 :     JS_ASSERT_IF(evalInFrame, type == EXECUTE_DEBUG);
     645                 : 
     646          306294 :     Root<JSScript*> scriptRoot(cx, &script);
     647                 : 
     648          153147 :     if (script->isEmpty()) {
     649             500 :         if (result)
     650             490 :             result->setUndefined();
     651             500 :         return true;
     652                 :     }
     653                 : 
     654          305294 :     ExecuteFrameGuard efg;
     655          152647 :     if (!cx->stack.pushExecuteFrame(cx, script, thisv, scopeChain, type, evalInFrame, &efg))
     656               0 :         return false;
     657                 : 
     658          152647 :     if (!script->ensureRanAnalysis(cx, &scopeChain))
     659               0 :         return false;
     660                 : 
     661                 :     /* Give strict mode eval its own fresh lexical environment. */
     662          152647 :     StackFrame *fp = efg.fp();
     663          152647 :     if (fp->isStrictEvalFrame() && !CallObject::createForStrictEval(cx, fp))
     664               0 :         return false;
     665                 : 
     666          152647 :     Probes::startExecution(cx, script);
     667                 : 
     668          152647 :     TypeScript::SetThis(cx, script, fp->thisValue());
     669                 : 
     670          152647 :     bool ok = RunScript(cx, script, fp);
     671                 : 
     672          152647 :     if (fp->isStrictEvalFrame())
     673            1908 :         js_PutCallObject(fp);
     674                 : 
     675          152647 :     Probes::stopExecution(cx, script);
     676                 : 
     677                 :     /* Propgate the return value out. */
     678          152647 :     if (result)
     679          114424 :         *result = fp->returnValue();
     680          152647 :     return ok;
     681                 : }
     682                 : 
     683                 : bool
     684           57616 : js::Execute(JSContext *cx, JSScript *script, JSObject &scopeChainArg, Value *rval)
     685                 : {
     686                 :     /* The scope chain could be anything, so innerize just in case. */
     687           57616 :     JSObject *scopeChain = &scopeChainArg;
     688           57616 :     OBJ_TO_INNER_OBJECT(cx, scopeChain);
     689           57616 :     if (!scopeChain)
     690               0 :         return false;
     691                 : 
     692                 :     /* If we were handed a non-native object, complain bitterly. */
     693           57616 :     if (!scopeChain->isNative()) {
     694               0 :         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NON_NATIVE_SCOPE);
     695               0 :         return false;
     696                 :     }
     697           57616 :     JS_ASSERT(!scopeChain->getOps()->defineProperty);
     698                 : 
     699                 :     /* The VAROBJFIX option makes varObj == globalObj in global code. */
     700           57616 :     if (!cx->hasRunOption(JSOPTION_VAROBJFIX)) {
     701           57384 :         if (!scopeChain->setVarObj(cx))
     702               0 :             return false;
     703                 :     }
     704                 : 
     705                 :     /* Use the scope chain as 'this', modulo outerization. */
     706           57616 :     JSObject *thisObj = scopeChain->thisObject(cx);
     707           57616 :     if (!thisObj)
     708               0 :         return false;
     709           57616 :     Value thisv = ObjectValue(*thisObj);
     710                 : 
     711                 :     return ExecuteKernel(cx, script, *scopeChain, thisv, EXECUTE_GLOBAL,
     712           57616 :                          NULL /* evalInFrame */, rval);
     713                 : }
     714                 : 
     715                 : JSBool
     716         1050339 : js::HasInstance(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp)
     717                 : {
     718         1050339 :     Class *clasp = obj->getClass();
     719         1050339 :     if (clasp->hasInstance)
     720         1050321 :         return clasp->hasInstance(cx, obj, v, bp);
     721              18 :     js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS,
     722              18 :                         JSDVG_SEARCH_STACK, ObjectValue(*obj), NULL);
     723              18 :     return JS_FALSE;
     724                 : }
     725                 : 
     726                 : bool
     727         4344647 : js::LooselyEqual(JSContext *cx, const Value &lval, const Value &rval, bool *result)
     728                 : {
     729                 : #if JS_HAS_XML_SUPPORT
     730         8726364 :     if (JS_UNLIKELY(lval.isObject() && lval.toObject().isXML()) ||
     731         4381717 :                     (rval.isObject() && rval.toObject().isXML())) {
     732                 :         JSBool res;
     733               9 :         if (!js_TestXMLEquality(cx, lval, rval, &res))
     734               0 :             return false;
     735               9 :         *result = !!res;
     736               9 :         return true;
     737                 :     }
     738                 : #endif
     739                 : 
     740         4344638 :     if (SameType(lval, rval)) {
     741         4142675 :         if (lval.isString()) {
     742          513953 :             JSString *l = lval.toString();
     743          513953 :             JSString *r = rval.toString();
     744          513953 :             return EqualStrings(cx, l, r, result);
     745                 :         }
     746                 : 
     747         3628722 :         if (lval.isDouble()) {
     748           40057 :             double l = lval.toDouble(), r = rval.toDouble();
     749           40057 :             *result = (l == r);
     750           40057 :             return true;
     751                 :         }
     752                 : 
     753         3588665 :         if (lval.isObject()) {
     754           34374 :             JSObject *l = &lval.toObject();
     755           34374 :             JSObject *r = &rval.toObject();
     756                 : 
     757           34374 :             if (JSEqualityOp eq = l->getClass()->ext.equality) {
     758                 :                 JSBool res;
     759              10 :                 if (!eq(cx, l, &rval, &res))
     760               0 :                     return false;
     761              10 :                 *result = !!res;
     762              10 :                 return true;
     763                 :             }
     764                 : 
     765           34364 :             *result = l == r;
     766           34364 :             return true;
     767                 :         }
     768                 : 
     769         3554291 :         *result = lval.payloadAsRawUint32() == rval.payloadAsRawUint32();
     770         3554291 :         return true;
     771                 :     }
     772                 : 
     773          201963 :     if (lval.isNullOrUndefined()) {
     774           10063 :         *result = rval.isNullOrUndefined();
     775           10063 :         return true;
     776                 :     }
     777                 : 
     778          191900 :     if (rval.isNullOrUndefined()) {
     779          174565 :         *result = false;
     780          174565 :         return true;
     781                 :     }
     782                 : 
     783           17335 :     Value lvalue = lval;
     784           17335 :     Value rvalue = rval;
     785                 : 
     786           17335 :     if (!ToPrimitive(cx, &lvalue))
     787               5 :         return false;
     788           17330 :     if (!ToPrimitive(cx, &rvalue))
     789               0 :         return false;
     790                 : 
     791           17330 :     if (lvalue.isString() && rvalue.isString()) {
     792            1377 :         JSString *l = lvalue.toString();
     793            1377 :         JSString *r = rvalue.toString();
     794            1377 :         return EqualStrings(cx, l, r, result);
     795                 :     }
     796                 : 
     797                 :     double l, r;
     798           15953 :     if (!ToNumber(cx, lvalue, &l) || !ToNumber(cx, rvalue, &r))
     799               0 :         return false;
     800           15953 :     *result = (l == r);
     801           15953 :     return true;
     802                 : }
     803                 : 
     804                 : bool
     805        10344166 : js::StrictlyEqual(JSContext *cx, const Value &lref, const Value &rref, bool *equal)
     806                 : {
     807        10344166 :     Value lval = lref, rval = rref;
     808        10344166 :     if (SameType(lval, rval)) {
     809         9135120 :         if (lval.isString())
     810         1002932 :             return EqualStrings(cx, lval.toString(), rval.toString(), equal);
     811         8132188 :         if (lval.isDouble()) {
     812         1048236 :             *equal = (lval.toDouble() == rval.toDouble());
     813         1048236 :             return true;
     814                 :         }
     815         7083952 :         if (lval.isObject()) {
     816          728835 :             *equal = lval.toObject() == rval.toObject();
     817          728835 :             return true;
     818                 :         }
     819         6355117 :         if (lval.isUndefined()) {
     820         1189250 :             *equal = true;
     821         1189250 :             return true;
     822                 :         }
     823         5165867 :         *equal = lval.payloadAsRawUint32() == rval.payloadAsRawUint32();
     824         5165867 :         return true;
     825                 :     }
     826                 : 
     827         1209046 :     if (lval.isDouble() && rval.isInt32()) {
     828            7518 :         double ld = lval.toDouble();
     829            7518 :         double rd = rval.toInt32();
     830            7518 :         *equal = (ld == rd);
     831            7518 :         return true;
     832                 :     }
     833         1201528 :     if (lval.isInt32() && rval.isDouble()) {
     834            6254 :         double ld = lval.toInt32();
     835            6254 :         double rd = rval.toDouble();
     836            6254 :         *equal = (ld == rd);
     837            6254 :         return true;
     838                 :     }
     839                 : 
     840         1195274 :     *equal = false;
     841         1195274 :     return true;
     842                 : }
     843                 : 
     844                 : static inline bool
     845        10584212 : IsNegativeZero(const Value &v)
     846                 : {
     847        10584212 :     return v.isDouble() && JSDOUBLE_IS_NEGZERO(v.toDouble());
     848                 : }
     849                 : 
     850                 : static inline bool
     851         5294060 : IsNaN(const Value &v)
     852                 : {
     853         5294060 :     return v.isDouble() && JSDOUBLE_IS_NaN(v.toDouble());
     854                 : }
     855                 : 
     856                 : bool
     857         5292106 : js::SameValue(JSContext *cx, const Value &v1, const Value &v2, bool *same)
     858                 : {
     859         5292106 :     if (IsNegativeZero(v1)) {
     860             621 :         *same = IsNegativeZero(v2);
     861             621 :         return true;
     862                 :     }
     863         5291485 :     if (IsNegativeZero(v2)) {
     864               1 :         *same = false;
     865               1 :         return true;
     866                 :     }
     867         5291484 :     if (IsNaN(v1) && IsNaN(v2)) {
     868            2576 :         *same = true;
     869            2576 :         return true;
     870                 :     }
     871         5288908 :     return StrictlyEqual(cx, v1, v2, same);
     872                 : }
     873                 : 
     874                 : JSType
     875          164799 : js::TypeOfValue(JSContext *cx, const Value &vref)
     876                 : {
     877          164799 :     Value v = vref;
     878          164799 :     if (v.isNumber())
     879           36166 :         return JSTYPE_NUMBER;
     880          128633 :     if (v.isString())
     881           98180 :         return JSTYPE_STRING;
     882           30453 :     if (v.isNull())
     883              54 :         return JSTYPE_OBJECT;
     884           30399 :     if (v.isUndefined())
     885            2085 :         return JSTYPE_VOID;
     886           28314 :     if (v.isObject())
     887           28137 :         return v.toObject().typeOf(cx);
     888             177 :     JS_ASSERT(v.isBoolean());
     889             177 :     return JSTYPE_BOOLEAN;
     890                 : }
     891                 : 
     892                 : bool
     893        12975106 : js::ValueToId(JSContext *cx, const Value &v, jsid *idp)
     894                 : {
     895                 :     int32_t i;
     896        12975106 :     if (ValueFitsInInt32(v, &i) && INT_FITS_IN_JSID(i)) {
     897          315291 :         *idp = INT_TO_JSID(i);
     898          315291 :         return true;
     899                 :     }
     900                 : 
     901                 : #if JS_HAS_XML_SUPPORT
     902        12659815 :     if (v.isObject()) {
     903              72 :         JSObject *obj = &v.toObject();
     904              72 :         if (obj->isXMLId()) {
     905              36 :             *idp = OBJECT_TO_JSID(obj);
     906              36 :             return JS_TRUE;
     907                 :         }
     908                 :     }
     909                 : #endif
     910                 : 
     911        12659779 :     return js_ValueToStringId(cx, v, idp);
     912                 : }
     913                 : 
     914                 : /*
     915                 :  * Enter the new with scope using an object at sp[-1] and associate the depth
     916                 :  * of the with block with sp + stackIndex.
     917                 :  */
     918                 : static bool
     919            1836 : EnterWith(JSContext *cx, int stackIndex)
     920                 : {
     921            1836 :     StackFrame *fp = cx->fp();
     922            1836 :     Value *sp = cx->regs().sp;
     923            1836 :     JS_ASSERT(stackIndex < 0);
     924            1836 :     JS_ASSERT(fp->base() <= sp + stackIndex);
     925                 : 
     926                 :     JSObject *obj;
     927            1836 :     if (sp[-1].isObject()) {
     928            1809 :         obj = &sp[-1].toObject();
     929                 :     } else {
     930              27 :         obj = js_ValueToNonNullObject(cx, sp[-1]);
     931              27 :         if (!obj)
     932               9 :             return JS_FALSE;
     933              18 :         sp[-1].setObject(*obj);
     934                 :     }
     935                 : 
     936            1827 :     JSObject *parent = GetScopeChain(cx, fp);
     937            1827 :     if (!parent)
     938               0 :         return JS_FALSE;
     939                 : 
     940                 :     JSObject *withobj = WithObject::create(cx, fp, *obj, *parent,
     941            1827 :                                            sp + stackIndex - fp->base());
     942            1827 :     if (!withobj)
     943               0 :         return JS_FALSE;
     944                 : 
     945            1827 :     fp->setScopeChainNoCallObj(*withobj);
     946            1827 :     return JS_TRUE;
     947                 : }
     948                 : 
     949                 : static void
     950            1827 : LeaveWith(JSContext *cx)
     951                 : {
     952            1827 :     WithObject &withobj = cx->fp()->scopeChain().asWith();
     953            1827 :     JS_ASSERT(withobj.maybeStackFrame() == js_FloatingFrameIfGenerator(cx, cx->fp()));
     954            1827 :     withobj.setStackFrame(NULL);
     955            1827 :     cx->fp()->setScopeChainNoCallObj(withobj.enclosingScope());
     956            1827 : }
     957                 : 
     958                 : bool
     959        15046374 : js::IsActiveWithOrBlock(JSContext *cx, JSObject &obj, uint32_t stackDepth)
     960                 : {
     961        30092569 :     return (obj.isWith() || obj.isBlock()) &&
     962            2395 :            obj.getPrivate() == js_FloatingFrameIfGenerator(cx, cx->fp()) &&
     963        30094964 :            obj.asNestedScope().stackDepth() >= stackDepth;
     964                 : }
     965                 : 
     966                 : /* Unwind block and scope chains to match the given depth. */
     967                 : void
     968         3291968 : js::UnwindScope(JSContext *cx, uint32_t stackDepth)
     969                 : {
     970         3291968 :     JS_ASSERT(cx->fp()->base() + stackDepth <= cx->regs().sp);
     971                 : 
     972         3291968 :     StackFrame *fp = cx->fp();
     973         3291968 :     StaticBlockObject *block = fp->maybeBlockChain();
     974         6584143 :     while (block) {
     975             360 :         if (block->stackDepth() < stackDepth)
     976             153 :             break;
     977             207 :         block = block->enclosingBlock();
     978                 :     }
     979         3291968 :     fp->setBlockChain(block);
     980                 : 
     981              90 :     for (;;) {
     982         3292058 :         JSObject &scopeChain = fp->scopeChain();
     983         3292058 :         if (!IsActiveWithOrBlock(cx, scopeChain, stackDepth))
     984                 :             break;
     985              90 :         if (scopeChain.isClonedBlock())
     986              63 :             scopeChain.asClonedBlock().put(cx);
     987                 :         else
     988              27 :             LeaveWith(cx);
     989                 :     }
     990         3291968 : }
     991                 : 
     992                 : void
     993             817 : js::UnwindForUncatchableException(JSContext *cx, const FrameRegs &regs)
     994                 : {
     995                 : 
     996                 :     /* c.f. the regular (catchable) TryNoteIter loop in Interpret. */
     997             880 :     for (TryNoteIter tni(regs); !tni.done(); ++tni) {
     998              63 :         JSTryNote *tn = *tni;
     999              63 :         if (tn->kind == JSTRY_ITER) {
    1000               0 :             Value *sp = regs.fp()->base() + tn->stackDepth;
    1001               0 :             UnwindIteratorForUncatchableException(cx, &sp[-1].toObject());
    1002                 :         }
    1003                 :     }
    1004             817 : }
    1005                 : 
    1006         2018341 : TryNoteIter::TryNoteIter(const FrameRegs &regs)
    1007                 :   : regs(regs),
    1008         2018341 :     script(regs.fp()->script()),
    1009         4036682 :     pcOffset(regs.pc - script->main())
    1010                 : {
    1011         2018341 :     if (JSScript::isValidOffset(script->trynotesOffset)) {
    1012           14664 :         tn = script->trynotes()->vector;
    1013           14664 :         tnEnd = tn + script->trynotes()->length;
    1014                 :     } else {
    1015         2003677 :         tn = tnEnd = NULL;
    1016                 :     }
    1017         2018341 :     settle();
    1018         2018341 : }
    1019                 : 
    1020                 : void
    1021            2963 : TryNoteIter::operator++()
    1022                 : {
    1023            2963 :     ++tn;
    1024            2963 :     settle();
    1025            2963 : }
    1026                 : 
    1027                 : bool
    1028         2021304 : TryNoteIter::done() const
    1029                 : {
    1030         2021304 :     return tn == tnEnd;
    1031                 : }
    1032                 : 
    1033                 : void
    1034         2021304 : TryNoteIter::settle()
    1035                 : {
    1036         2078561 :     for (; tn != tnEnd; ++tn) {
    1037                 :         /* If pc is out of range, try the next one. */
    1038           72877 :         if (pcOffset - tn->start >= tn->length)
    1039           57257 :             continue;
    1040                 : 
    1041                 :         /*
    1042                 :          * We have a note that covers the exception pc but we must check
    1043                 :          * whether the interpreter has already executed the corresponding
    1044                 :          * handler. This is possible when the executed bytecode implements
    1045                 :          * break or return from inside a for-in loop.
    1046                 :          *
    1047                 :          * In this case the emitter generates additional [enditer] and [gosub]
    1048                 :          * opcodes to close all outstanding iterators and execute the finally
    1049                 :          * blocks. If such an [enditer] throws an exception, its pc can still
    1050                 :          * be inside several nested for-in loops and try-finally statements
    1051                 :          * even if we have already closed the corresponding iterators and
    1052                 :          * invoked the finally blocks.
    1053                 :          *
    1054                 :          * To address this, we make [enditer] always decrease the stack even
    1055                 :          * when its implementation throws an exception. Thus already executed
    1056                 :          * [enditer] and [gosub] opcodes will have try notes with the stack
    1057                 :          * depth exceeding the current one and this condition is what we use to
    1058                 :          * filter them out.
    1059                 :          */
    1060           15620 :         if (tn->stackDepth <= regs.sp - regs.fp()->base())
    1061           15620 :             break;
    1062                 :     }
    1063         2021304 : }
    1064                 : 
    1065                 : /*
    1066                 :  * Increment/decrement the value 'v'. The resulting value is stored in *slot.
    1067                 :  * The result of the expression (taking into account prefix/postfix) is stored
    1068                 :  * in *expr.
    1069                 :  */
    1070                 : static bool
    1071       303998787 : DoIncDec(JSContext *cx, JSScript *script, jsbytecode *pc, const Value &v, Value *slot, Value *expr)
    1072                 : {
    1073       303998787 :     const JSCodeSpec &cs = js_CodeSpec[*pc];
    1074                 : 
    1075       303998787 :     if (v.isInt32()) {
    1076       303996900 :         int32_t i = v.toInt32();
    1077       303996900 :         if (i > JSVAL_INT_MIN && i < JSVAL_INT_MAX) {
    1078       303996880 :             int32_t sum = i + (cs.format & JOF_INC ? 1 : -1);
    1079       303996880 :             *slot = Int32Value(sum);
    1080       303996880 :             *expr = (cs.format & JOF_POST) ? Int32Value(i) : *slot;
    1081       303996880 :             return true;
    1082                 :         }
    1083                 :     }
    1084                 : 
    1085                 :     double d;
    1086            1907 :     if (!ToNumber(cx, *slot, &d))
    1087               0 :         return false;
    1088                 : 
    1089            1907 :     double sum = d + (cs.format & JOF_INC ? 1 : -1);
    1090            1907 :     *slot = NumberValue(sum);
    1091            1907 :     *expr = (cs.format & JOF_POST) ? NumberValue(d) : *slot;
    1092                 : 
    1093            1907 :     TypeScript::MonitorOverflow(cx, script, pc);
    1094            1907 :     return true;
    1095                 : }
    1096                 : 
    1097                 : #define PUSH_COPY(v)             do { *regs.sp++ = v; assertSameCompartment(cx, regs.sp[-1]); } while (0)
    1098                 : #define PUSH_COPY_SKIP_CHECK(v)  *regs.sp++ = v
    1099                 : #define PUSH_NULL()              regs.sp++->setNull()
    1100                 : #define PUSH_UNDEFINED()         regs.sp++->setUndefined()
    1101                 : #define PUSH_BOOLEAN(b)          regs.sp++->setBoolean(b)
    1102                 : #define PUSH_DOUBLE(d)           regs.sp++->setDouble(d)
    1103                 : #define PUSH_INT32(i)            regs.sp++->setInt32(i)
    1104                 : #define PUSH_STRING(s)           do { regs.sp++->setString(s); assertSameCompartment(cx, regs.sp[-1]); } while (0)
    1105                 : #define PUSH_OBJECT(obj)         do { regs.sp++->setObject(obj); assertSameCompartment(cx, regs.sp[-1]); } while (0)
    1106                 : #define PUSH_OBJECT_OR_NULL(obj) do { regs.sp++->setObjectOrNull(obj); assertSameCompartment(cx, regs.sp[-1]); } while (0)
    1107                 : #define PUSH_HOLE()              regs.sp++->setMagic(JS_ARRAY_HOLE)
    1108                 : #define POP_COPY_TO(v)           v = *--regs.sp
    1109                 : #define POP_RETURN_VALUE()       regs.fp()->setReturnValue(*--regs.sp)
    1110                 : 
    1111                 : #define VALUE_TO_BOOLEAN(cx, vp, b)                                           \
    1112                 :     JS_BEGIN_MACRO                                                            \
    1113                 :         vp = &regs.sp[-1];                                                    \
    1114                 :         if (vp->isNull()) {                                                   \
    1115                 :             b = false;                                                        \
    1116                 :         } else if (vp->isBoolean()) {                                         \
    1117                 :             b = vp->toBoolean();                                              \
    1118                 :         } else {                                                              \
    1119                 :             b = !!js_ValueToBoolean(*vp);                                     \
    1120                 :         }                                                                     \
    1121                 :     JS_END_MACRO
    1122                 : 
    1123                 : #define POP_BOOLEAN(cx, vp, b)   do { VALUE_TO_BOOLEAN(cx, vp, b); regs.sp--; } while(0)
    1124                 : 
    1125                 : #define FETCH_OBJECT(cx, n, obj)                                              \
    1126                 :     JS_BEGIN_MACRO                                                            \
    1127                 :         Value *vp_ = &regs.sp[n];                                             \
    1128                 :         obj = ToObject(cx, (vp_));                                            \
    1129                 :         if (!obj)                                                             \
    1130                 :             goto error;                                                       \
    1131                 :     JS_END_MACRO
    1132                 : 
    1133                 : /*
    1134                 :  * Threaded interpretation via computed goto appears to be well-supported by
    1135                 :  * GCC 3 and higher.  IBM's C compiler when run with the right options (e.g.,
    1136                 :  * -qlanglvl=extended) also supports threading.  Ditto the SunPro C compiler.
    1137                 :  * Currently it's broken for JS_VERSION < 160, though this isn't worth fixing.
    1138                 :  * Add your compiler support macros here.
    1139                 :  */
    1140                 : #ifndef JS_THREADED_INTERP
    1141                 : # if JS_VERSION >= 160 && (                                                   \
    1142                 :     __GNUC__ >= 3 ||                                                          \
    1143                 :     (__IBMC__ >= 700 && defined __IBM_COMPUTED_GOTO) ||                       \
    1144                 :     __SUNPRO_C >= 0x570)
    1145                 : #  define JS_THREADED_INTERP 1
    1146                 : # else
    1147                 : #  define JS_THREADED_INTERP 0
    1148                 : # endif
    1149                 : #endif
    1150                 : 
    1151                 : template<typename T>
    1152                 : class GenericInterruptEnabler : public InterpreterFrames::InterruptEnablerBase {
    1153                 :   public:
    1154          517775 :     GenericInterruptEnabler(T *variable, T value) : variable(variable), value(value) { }
    1155            1515 :     void enableInterrupts() const { *variable = value; }
    1156                 : 
    1157                 :   private:
    1158                 :     T *variable;
    1159                 :     T value;
    1160                 : };
    1161                 : 
    1162          517775 : inline InterpreterFrames::InterpreterFrames(JSContext *cx, FrameRegs *regs, 
    1163                 :                                             const InterruptEnablerBase &enabler)
    1164          517775 :   : context(cx), regs(regs), enabler(enabler)
    1165                 : {
    1166          517775 :     older = cx->runtime->interpreterFrames;
    1167          517775 :     cx->runtime->interpreterFrames = this;
    1168          517775 : }
    1169                 :  
    1170          517775 : inline InterpreterFrames::~InterpreterFrames()
    1171                 : {
    1172          517775 :     context->runtime->interpreterFrames = older;
    1173          517775 : }
    1174                 : 
    1175                 : #if defined(DEBUG) && !defined(JS_THREADSAFE)
    1176                 : void
    1177                 : js::AssertValidPropertyCacheHit(JSContext *cx,
    1178                 :                                 JSObject *start, JSObject *found,
    1179                 :                                 PropertyCacheEntry *entry)
    1180                 : {
    1181                 :     jsbytecode *pc;
    1182                 :     cx->stack.currentScript(&pc);
    1183                 : 
    1184                 :     uint64_t sample = cx->runtime->gcNumber;
    1185                 :     PropertyCacheEntry savedEntry = *entry;
    1186                 : 
    1187                 :     PropertyName *name = GetNameFromBytecode(cx, pc, JSOp(*pc), js_CodeSpec[*pc]);
    1188                 : 
    1189                 :     JSObject *obj, *pobj;
    1190                 :     JSProperty *prop;
    1191                 :     JSBool ok;
    1192                 : 
    1193                 :     if (JOF_OPMODE(*pc) == JOF_NAME)
    1194                 :         ok = FindProperty(cx, name, start, &obj, &pobj, &prop);
    1195                 :     else
    1196                 :         ok = LookupProperty(cx, start, name, &pobj, &prop);
    1197                 :     JS_ASSERT(ok);
    1198                 : 
    1199                 :     if (cx->runtime->gcNumber != sample)
    1200                 :         JS_PROPERTY_CACHE(cx).restore(&savedEntry);
    1201                 :     JS_ASSERT(prop);
    1202                 :     JS_ASSERT(pobj == found);
    1203                 : 
    1204                 :     const Shape *shape = (Shape *) prop;
    1205                 :     JS_ASSERT(entry->prop == shape);
    1206                 : }
    1207                 : #endif /* DEBUG && !JS_THREADSAFE */
    1208                 : 
    1209                 : /*
    1210                 :  * Ensure that the intrepreter switch can close call-bytecode cases in the
    1211                 :  * same way as non-call bytecodes.
    1212                 :  */
    1213                 : JS_STATIC_ASSERT(JSOP_NAME_LENGTH == JSOP_CALLNAME_LENGTH);
    1214                 : JS_STATIC_ASSERT(JSOP_GETARG_LENGTH == JSOP_CALLARG_LENGTH);
    1215                 : JS_STATIC_ASSERT(JSOP_GETLOCAL_LENGTH == JSOP_CALLLOCAL_LENGTH);
    1216                 : JS_STATIC_ASSERT(JSOP_XMLNAME_LENGTH == JSOP_CALLXMLNAME_LENGTH);
    1217                 : 
    1218                 : /*
    1219                 :  * Same for JSOP_SETNAME and JSOP_SETPROP, which differ only slightly but
    1220                 :  * remain distinct for the decompiler.
    1221                 :  */
    1222                 : JS_STATIC_ASSERT(JSOP_SETNAME_LENGTH == JSOP_SETPROP_LENGTH);
    1223                 : 
    1224                 : /* See TRY_BRANCH_AFTER_COND. */
    1225                 : JS_STATIC_ASSERT(JSOP_IFNE_LENGTH == JSOP_IFEQ_LENGTH);
    1226                 : JS_STATIC_ASSERT(JSOP_IFNE == JSOP_IFEQ + 1);
    1227                 : 
    1228                 : /* For the fastest case inder JSOP_INCNAME, etc. */
    1229                 : JS_STATIC_ASSERT(JSOP_INCNAME_LENGTH == JSOP_DECNAME_LENGTH);
    1230                 : JS_STATIC_ASSERT(JSOP_INCNAME_LENGTH == JSOP_NAMEINC_LENGTH);
    1231                 : JS_STATIC_ASSERT(JSOP_INCNAME_LENGTH == JSOP_NAMEDEC_LENGTH);
    1232                 : 
    1233                 : /*
    1234                 :  * Inline fast paths for iteration. js_IteratorMore and js_IteratorNext handle
    1235                 :  * all cases, but we inline the most frequently taken paths here.
    1236                 :  */
    1237                 : static inline bool
    1238         3273845 : IteratorMore(JSContext *cx, JSObject *iterobj, bool *cond, Value *rval)
    1239                 : {
    1240         3273845 :     if (iterobj->isIterator()) {
    1241         3260121 :         NativeIterator *ni = iterobj->getNativeIterator();
    1242         3260121 :         if (ni->isKeyIter()) {
    1243          555984 :             *cond = (ni->props_cursor < ni->props_end);
    1244          555984 :             return true;
    1245                 :         }
    1246                 :     }
    1247         2717861 :     if (!js_IteratorMore(cx, iterobj, rval))
    1248              20 :         return false;
    1249         2717841 :     *cond = rval->isTrue();
    1250         2717841 :     return true;
    1251                 : }
    1252                 : 
    1253                 : static inline bool
    1254         3221647 : IteratorNext(JSContext *cx, JSObject *iterobj, Value *rval)
    1255                 : {
    1256         3221647 :     if (iterobj->isIterator()) {
    1257         3210231 :         NativeIterator *ni = iterobj->getNativeIterator();
    1258         3210231 :         if (ni->isKeyIter()) {
    1259          542627 :             JS_ASSERT(ni->props_cursor < ni->props_end);
    1260          542627 :             rval->setString(*ni->current());
    1261          542627 :             ni->incCursor();
    1262          542627 :             return true;
    1263                 :         }
    1264                 :     }
    1265         2679020 :     return js_IteratorNext(cx, iterobj, rval);
    1266                 : }
    1267                 : 
    1268                 : /*
    1269                 :  * For bytecodes which push values and then fall through, make sure the
    1270                 :  * types of the pushed values are consistent with type inference information.
    1271                 :  */
    1272                 : static inline void
    1273      1718061810 : TypeCheckNextBytecode(JSContext *cx, JSScript *script, unsigned n, const FrameRegs &regs)
    1274                 : {
    1275                 : #ifdef DEBUG
    1276     -1714338827 :     if (cx->typeInferenceEnabled() &&
    1277       862566659 :         n == GetBytecodeLength(regs.pc)) {
    1278       859862289 :         TypeScript::CheckBytecode(cx, script, regs.pc, regs.sp);
    1279                 :     }
    1280                 : #endif
    1281      1718061810 : }
    1282                 : 
    1283                 : JS_NEVER_INLINE bool
    1284          517775 : js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode)
    1285                 : {
    1286         1035550 :     JSAutoResolveFlags rf(cx, RESOLVE_INFER);
    1287                 : 
    1288          517775 :     gc::MaybeVerifyBarriers(cx, true);
    1289                 : 
    1290          517775 :     JS_ASSERT(!cx->compartment->activeAnalysis);
    1291                 : 
    1292                 : #if JS_THREADED_INTERP
    1293                 : #define CHECK_PCCOUNT_INTERRUPTS() JS_ASSERT_IF(script->scriptCounts, jumpTable == interruptJumpTable)
    1294                 : #else
    1295                 : #define CHECK_PCCOUNT_INTERRUPTS() JS_ASSERT_IF(script->scriptCounts, switchMask == -1)
    1296                 : #endif
    1297                 : 
    1298                 :     /*
    1299                 :      * Macros for threaded interpreter loop
    1300                 :      */
    1301                 : #if JS_THREADED_INTERP
    1302                 :     static void *const normalJumpTable[] = {
    1303                 : # define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
    1304                 :         JS_EXTENSION &&L_##op,
    1305                 : # include "jsopcode.tbl"
    1306                 : # undef OPDEF
    1307                 :     };
    1308                 : 
    1309                 :     static void *const interruptJumpTable[] = {
    1310                 : # define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format)              \
    1311                 :         JS_EXTENSION &&interrupt,
    1312                 : # include "jsopcode.tbl"
    1313                 : # undef OPDEF
    1314                 :     };
    1315                 : 
    1316          517775 :     register void * const *jumpTable = normalJumpTable;
    1317                 : 
    1318                 :     typedef GenericInterruptEnabler<void * const *> InterruptEnabler;
    1319          517775 :     InterruptEnabler interruptEnabler(&jumpTable, interruptJumpTable);
    1320                 : 
    1321                 : # define DO_OP()            JS_BEGIN_MACRO                                    \
    1322                 :                                 CHECK_PCCOUNT_INTERRUPTS();                   \
    1323                 :                                 js::gc::MaybeVerifyBarriers(cx);              \
    1324                 :                                 JS_EXTENSION_(goto *jumpTable[op]);           \
    1325                 :                             JS_END_MACRO
    1326                 : # define DO_NEXT_OP(n)      JS_BEGIN_MACRO                                    \
    1327                 :                                 TypeCheckNextBytecode(cx, script, n, regs);   \
    1328                 :                                 op = (JSOp) *(regs.pc += (n));                \
    1329                 :                                 DO_OP();                                      \
    1330                 :                             JS_END_MACRO
    1331                 : 
    1332                 : # define BEGIN_CASE(OP)     L_##OP:
    1333                 : # define END_CASE(OP)       DO_NEXT_OP(OP##_LENGTH);
    1334                 : # define END_VARLEN_CASE    DO_NEXT_OP(len);
    1335                 : # define ADD_EMPTY_CASE(OP) BEGIN_CASE(OP)                                    \
    1336                 :                                 JS_ASSERT(js_CodeSpec[OP].length == 1);       \
    1337                 :                                 op = (JSOp) *++regs.pc;                       \
    1338                 :                                 DO_OP();
    1339                 : 
    1340                 : # define END_EMPTY_CASES
    1341                 : 
    1342                 : #else /* !JS_THREADED_INTERP */
    1343                 : 
    1344                 :     register int switchMask = 0;
    1345                 :     int switchOp;
    1346                 :     typedef GenericInterruptEnabler<int> InterruptEnabler;
    1347                 :     InterruptEnabler interruptEnabler(&switchMask, -1);
    1348                 : 
    1349                 : # define DO_OP()            goto do_op
    1350                 : # define DO_NEXT_OP(n)      JS_BEGIN_MACRO                                    \
    1351                 :                                 JS_ASSERT((n) == len);                        \
    1352                 :                                 goto advance_pc;                              \
    1353                 :                             JS_END_MACRO
    1354                 : 
    1355                 : # define BEGIN_CASE(OP)     case OP:
    1356                 : # define END_CASE(OP)       END_CASE_LEN(OP##_LENGTH)
    1357                 : # define END_CASE_LEN(n)    END_CASE_LENX(n)
    1358                 : # define END_CASE_LENX(n)   END_CASE_LEN##n
    1359                 : 
    1360                 : /*
    1361                 :  * To share the code for all len == 1 cases we use the specialized label with
    1362                 :  * code that falls through to advance_pc: .
    1363                 :  */
    1364                 : # define END_CASE_LEN1      goto advance_pc_by_one;
    1365                 : # define END_CASE_LEN2      len = 2; goto advance_pc;
    1366                 : # define END_CASE_LEN3      len = 3; goto advance_pc;
    1367                 : # define END_CASE_LEN4      len = 4; goto advance_pc;
    1368                 : # define END_CASE_LEN5      len = 5; goto advance_pc;
    1369                 : # define END_CASE_LEN6      len = 6; goto advance_pc;
    1370                 : # define END_CASE_LEN7      len = 7; goto advance_pc;
    1371                 : # define END_VARLEN_CASE    goto advance_pc;
    1372                 : # define ADD_EMPTY_CASE(OP) BEGIN_CASE(OP)
    1373                 : # define END_EMPTY_CASES    goto advance_pc_by_one;
    1374                 : 
    1375                 : #endif /* !JS_THREADED_INTERP */
    1376                 : 
    1377                 : #define ENABLE_INTERRUPTS() (interruptEnabler.enableInterrupts())
    1378                 : 
    1379                 : #define LOAD_ATOM(PCOFF, atom)                                                \
    1380                 :     JS_BEGIN_MACRO                                                            \
    1381                 :         JS_ASSERT((size_t)(atoms - script->atoms) <                           \
    1382                 :                   (size_t)(script->natoms - GET_UINT32_INDEX(regs.pc + PCOFF)));\
    1383                 :         atom = atoms[GET_UINT32_INDEX(regs.pc + PCOFF)];                      \
    1384                 :     JS_END_MACRO
    1385                 : 
    1386                 : #define LOAD_NAME(PCOFF, name)                                                \
    1387                 :     JS_BEGIN_MACRO                                                            \
    1388                 :         JSAtom *atom;                                                         \
    1389                 :         LOAD_ATOM((PCOFF), atom);                                             \
    1390                 :         name = atom->asPropertyName();                                        \
    1391                 :     JS_END_MACRO
    1392                 : 
    1393                 : #define LOAD_DOUBLE(PCOFF, dbl)                                               \
    1394                 :     (dbl = script->getConst(GET_UINT32_INDEX(regs.pc + (PCOFF))).toDouble())
    1395                 : 
    1396                 : #if defined(JS_METHODJIT)
    1397          517775 :     bool useMethodJIT = false;
    1398                 : #endif
    1399                 : 
    1400                 : #ifdef JS_METHODJIT
    1401                 : 
    1402                 : #define RESET_USE_METHODJIT()                                                 \
    1403                 :     JS_BEGIN_MACRO                                                            \
    1404                 :         useMethodJIT = cx->methodJitEnabled &&                                \
    1405                 :            (interpMode == JSINTERP_NORMAL ||                                  \
    1406                 :             interpMode == JSINTERP_REJOIN ||                                  \
    1407                 :             interpMode == JSINTERP_SKIP_TRAP);                                \
    1408                 :     JS_END_MACRO
    1409                 : 
    1410                 : #define CHECK_PARTIAL_METHODJIT(status)                                       \
    1411                 :     JS_BEGIN_MACRO                                                            \
    1412                 :         switch (status) {                                                     \
    1413                 :           case mjit::Jaeger_UnfinishedAtTrap:                                 \
    1414                 :             interpMode = JSINTERP_SKIP_TRAP;                                  \
    1415                 :             /* FALLTHROUGH */                                                 \
    1416                 :           case mjit::Jaeger_Unfinished:                                       \
    1417                 :             op = (JSOp) *regs.pc;                                             \
    1418                 :             RESTORE_INTERP_VARS_CHECK_EXCEPTION();                            \
    1419                 :             DO_OP();                                                          \
    1420                 :           default:;                                                           \
    1421                 :         }                                                                     \
    1422                 :     JS_END_MACRO
    1423                 : 
    1424                 : #else
    1425                 : 
    1426                 : #define RESET_USE_METHODJIT() ((void) 0)
    1427                 : 
    1428                 : #endif
    1429                 : 
    1430                 : #define RESTORE_INTERP_VARS()                                                 \
    1431                 :     JS_BEGIN_MACRO                                                            \
    1432                 :         SET_SCRIPT(regs.fp()->script());                                      \
    1433                 :         argv = regs.fp()->maybeFormalArgs();                                  \
    1434                 :         atoms = FrameAtomBase(cx, regs.fp());                                 \
    1435                 :         JS_ASSERT(&cx->regs() == &regs);                                      \
    1436                 :     JS_END_MACRO
    1437                 : 
    1438                 : #define RESTORE_INTERP_VARS_CHECK_EXCEPTION()                                 \
    1439                 :     JS_BEGIN_MACRO                                                            \
    1440                 :         RESTORE_INTERP_VARS();                                                \
    1441                 :         if (cx->isExceptionPending())                                         \
    1442                 :             goto error;                                                       \
    1443                 :         CHECK_INTERRUPT_HANDLER();                                            \
    1444                 :     JS_END_MACRO
    1445                 : 
    1446                 :     /*
    1447                 :      * Prepare to call a user-supplied branch handler, and abort the script
    1448                 :      * if it returns false.
    1449                 :      */
    1450                 : #define CHECK_BRANCH()                                                        \
    1451                 :     JS_BEGIN_MACRO                                                            \
    1452                 :         if (cx->runtime->interrupt && !js_HandleExecutionInterrupt(cx))       \
    1453                 :             goto error;                                                       \
    1454                 :     JS_END_MACRO
    1455                 : 
    1456                 : #define BRANCH(n)                                                             \
    1457                 :     JS_BEGIN_MACRO                                                            \
    1458                 :         regs.pc += (n);                                                       \
    1459                 :         op = (JSOp) *regs.pc;                                                 \
    1460                 :         if ((n) <= 0)                                                         \
    1461                 :             goto check_backedge;                                              \
    1462                 :         DO_OP();                                                              \
    1463                 :     JS_END_MACRO
    1464                 : 
    1465                 : #define SET_SCRIPT(s)                                                         \
    1466                 :     JS_BEGIN_MACRO                                                            \
    1467                 :         script = (s);                                                         \
    1468                 :         if (script->hasAnyBreakpointsOrStepMode())                            \
    1469                 :             ENABLE_INTERRUPTS();                                              \
    1470                 :         if (script->scriptCounts)                                             \
    1471                 :             ENABLE_INTERRUPTS();                                              \
    1472                 :         JS_ASSERT_IF(interpMode == JSINTERP_SKIP_TRAP,                        \
    1473                 :                      script->hasAnyBreakpointsOrStepMode());                  \
    1474                 :     JS_END_MACRO
    1475                 : 
    1476                 : #define CHECK_INTERRUPT_HANDLER()                                             \
    1477                 :     JS_BEGIN_MACRO                                                            \
    1478                 :         if (cx->runtime->debugHooks.interruptHook)                            \
    1479                 :             ENABLE_INTERRUPTS();                                              \
    1480                 :     JS_END_MACRO
    1481                 : 
    1482                 :     /* Repoint cx->regs to a local variable for faster access. */
    1483          517775 :     FrameRegs regs = cx->regs();
    1484         1035550 :     PreserveRegsGuard interpGuard(cx, regs);
    1485                 : 
    1486                 :     /*
    1487                 :      * Help Debugger find frames running scripts that it has put in
    1488                 :      * single-step mode.
    1489                 :      */
    1490         1035550 :     InterpreterFrames interpreterFrame(cx, &regs, interruptEnabler);
    1491                 : 
    1492                 :     /* Copy in hot values that change infrequently. */
    1493          517775 :     JSRuntime *const rt = cx->runtime;
    1494                 :     JSScript *script;
    1495          517775 :     SET_SCRIPT(regs.fp()->script());
    1496          517775 :     Value *argv = regs.fp()->maybeFormalArgs();
    1497          517775 :     CHECK_INTERRUPT_HANDLER();
    1498                 : 
    1499          517775 :     if (rt->profilingScripts)
    1500               0 :         ENABLE_INTERRUPTS();
    1501                 : 
    1502          517775 :     if (!entryFrame)
    1503               0 :         entryFrame = regs.fp();
    1504                 : 
    1505                 :     /*
    1506                 :      * Initialize the index segment register used by LOAD_ATOM and
    1507                 :      * GET_FULL_INDEX macros below. As a register we use a pointer based on
    1508                 :      * the atom map to turn frequently executed LOAD_ATOM into simple array
    1509                 :      * access. For less frequent object loads we have to recover the segment
    1510                 :      * from atoms pointer first.
    1511                 :      */
    1512          517775 :     JSAtom **atoms = script->atoms;
    1513                 : 
    1514                 : #if JS_HAS_GENERATORS
    1515          517775 :     if (JS_UNLIKELY(regs.fp()->isGeneratorFrame())) {
    1516           19096 :         JS_ASSERT((size_t) (regs.pc - script->code) <= script->length);
    1517           19096 :         JS_ASSERT((size_t) (regs.sp - regs.fp()->base()) <= StackDepth(script));
    1518                 : 
    1519                 :         /*
    1520                 :          * To support generator_throw and to catch ignored exceptions,
    1521                 :          * fail if cx->isExceptionPending() is true.
    1522                 :          */
    1523           19096 :         if (cx->isExceptionPending())
    1524            1470 :             goto error;
    1525                 :     }
    1526                 : #endif
    1527                 : 
    1528                 :     /* State communicated between non-local jumps: */
    1529                 :     bool interpReturnOK;
    1530                 : 
    1531                 :     /* Don't call the script prologue if executing between Method and Trace JIT. */
    1532          516305 :     if (interpMode == JSINTERP_NORMAL) {
    1533          502134 :         StackFrame *fp = regs.fp();
    1534          502134 :         JS_ASSERT_IF(!fp->isGeneratorFrame(), regs.pc == script->code);
    1535          502134 :         if (!ScriptPrologueOrGeneratorResume(cx, fp, UseNewTypeAtEntry(cx, fp)))
    1536               0 :             goto error;
    1537          502134 :         if (cx->compartment->debugMode()) {
    1538           42184 :             JSTrapStatus status = ScriptDebugPrologue(cx, fp);
    1539           42184 :             switch (status) {
    1540                 :               case JSTRAP_CONTINUE:
    1541                 :                 break;
    1542                 :               case JSTRAP_RETURN:
    1543              10 :                 interpReturnOK = true;
    1544              10 :                 goto forced_return;
    1545                 :               case JSTRAP_THROW:
    1546                 :               case JSTRAP_ERROR:
    1547             402 :                 goto error;
    1548                 :               default:
    1549               0 :                 JS_NOT_REACHED("bad ScriptDebugPrologue status");
    1550                 :             }
    1551                 :         }
    1552                 :     }
    1553                 : 
    1554                 :     /* The REJOIN mode acts like the normal mode, except the prologue is skipped. */
    1555          515893 :     if (interpMode == JSINTERP_REJOIN)
    1556           14165 :         interpMode = JSINTERP_NORMAL;
    1557                 : 
    1558          515893 :     CHECK_INTERRUPT_HANDLER();
    1559                 : 
    1560          515893 :     RESET_USE_METHODJIT();
    1561                 : 
    1562                 :     /*
    1563                 :      * It is important that "op" be initialized before calling DO_OP because
    1564                 :      * it is possible for "op" to be specially assigned during the normal
    1565                 :      * processing of an opcode while looping. We rely on DO_NEXT_OP to manage
    1566                 :      * "op" correctly in all other cases.
    1567                 :      */
    1568                 :     JSOp op;
    1569                 :     int32_t len;
    1570          515893 :     len = 0;
    1571                 : 
    1572          515893 :     DO_NEXT_OP(len);
    1573                 : 
    1574                 : #if JS_THREADED_INTERP
    1575                 :     /*
    1576                 :      * This is a loop, but it does not look like a loop. The loop-closing
    1577                 :      * jump is distributed throughout goto *jumpTable[op] inside of DO_OP.
    1578                 :      * When interrupts are enabled, jumpTable is set to interruptJumpTable
    1579                 :      * where all jumps point to the interrupt label. The latter, after
    1580                 :      * calling the interrupt handler, dispatches through normalJumpTable to
    1581                 :      * continue the normal bytecode processing.
    1582                 :      */
    1583                 : 
    1584                 : #else /* !JS_THREADED_INTERP */
    1585                 :     for (;;) {
    1586                 :       advance_pc_by_one:
    1587                 :         JS_ASSERT(js_CodeSpec[op].length == 1);
    1588                 :         len = 1;
    1589                 :       advance_pc:
    1590                 :         regs.pc += len;
    1591                 :         op = (JSOp) *regs.pc;
    1592                 : 
    1593                 :       do_op:
    1594                 :         CHECK_PCCOUNT_INTERRUPTS();
    1595                 :         js::gc::MaybeVerifyBarriers(cx);
    1596                 :         switchOp = int(op) | switchMask;
    1597                 :       do_switch:
    1598                 :         switch (switchOp) {
    1599                 : #endif
    1600                 : 
    1601                 : #if JS_THREADED_INTERP
    1602                 :   interrupt:
    1603                 : #else /* !JS_THREADED_INTERP */
    1604                 :   case -1:
    1605                 :     JS_ASSERT(switchMask == -1);
    1606                 : #endif /* !JS_THREADED_INTERP */
    1607                 :     {
    1608           18186 :         bool moreInterrupts = false;
    1609                 : 
    1610           18186 :         if (cx->runtime->profilingScripts) {
    1611               0 :             if (!script->scriptCounts)
    1612               0 :                 script->initScriptCounts(cx);
    1613               0 :             moreInterrupts = true;
    1614                 :         }
    1615                 : 
    1616           18186 :         if (script->scriptCounts) {
    1617               0 :             PCCounts counts = script->getPCCounts(regs.pc);
    1618               0 :             counts.get(PCCounts::BASE_INTERP)++;
    1619               0 :             moreInterrupts = true;
    1620                 :         }
    1621                 : 
    1622           18186 :         JSInterruptHook hook = cx->runtime->debugHooks.interruptHook;
    1623           18186 :         if (hook || script->stepModeEnabled()) {
    1624                 :             Value rval;
    1625            5514 :             JSTrapStatus status = JSTRAP_CONTINUE;
    1626            5514 :             if (hook)
    1627              17 :                 status = hook(cx, script, regs.pc, &rval, cx->runtime->debugHooks.interruptHookData);
    1628            5514 :             if (status == JSTRAP_CONTINUE && script->stepModeEnabled())
    1629            5514 :                 status = Debugger::onSingleStep(cx, &rval);
    1630            5514 :             switch (status) {
    1631                 :               case JSTRAP_ERROR:
    1632              18 :                 goto error;
    1633                 :               case JSTRAP_CONTINUE:
    1634            5478 :                 break;
    1635                 :               case JSTRAP_RETURN:
    1636               9 :                 regs.fp()->setReturnValue(rval);
    1637               9 :                 interpReturnOK = true;
    1638               9 :                 goto forced_return;
    1639                 :               case JSTRAP_THROW:
    1640               9 :                 cx->setPendingException(rval);
    1641               9 :                 goto error;
    1642                 :               default:;
    1643                 :             }
    1644            5478 :             moreInterrupts = true;
    1645                 :         }
    1646                 : 
    1647           18150 :         if (script->hasAnyBreakpointsOrStepMode())
    1648           17725 :             moreInterrupts = true;
    1649                 : 
    1650           18150 :         if (script->hasBreakpointsAt(regs.pc) && interpMode != JSINTERP_SKIP_TRAP) {
    1651                 :             Value rval;
    1652             967 :             JSTrapStatus status = Debugger::onTrap(cx, &rval);
    1653             967 :             switch (status) {
    1654                 :               case JSTRAP_ERROR:
    1655               5 :                 goto error;
    1656                 :               case JSTRAP_RETURN:
    1657              30 :                 regs.fp()->setReturnValue(rval);
    1658              30 :                 interpReturnOK = true;
    1659              30 :                 goto forced_return;
    1660                 :               case JSTRAP_THROW:
    1661               9 :                 cx->setPendingException(rval);
    1662               9 :                 goto error;
    1663                 :               default:
    1664                 :                 break;
    1665                 :             }
    1666             923 :             JS_ASSERT(status == JSTRAP_CONTINUE);
    1667             923 :             CHECK_INTERRUPT_HANDLER();
    1668             923 :             JS_ASSERT(rval.isInt32() && rval.toInt32() == op);
    1669                 :         }
    1670                 : 
    1671           18106 :         interpMode = JSINTERP_NORMAL;
    1672                 : 
    1673                 : #if JS_THREADED_INTERP
    1674           18106 :         jumpTable = moreInterrupts ? interruptJumpTable : normalJumpTable;
    1675           18106 :         JS_EXTENSION_(goto *normalJumpTable[op]);
    1676                 : #else
    1677                 :         switchMask = moreInterrupts ? -1 : 0;
    1678                 :         switchOp = int(op);
    1679                 :         goto do_switch;
    1680                 : #endif
    1681                 :     }
    1682                 : 
    1683                 : /* No-ops for ease of decompilation. */
    1684          126453 : ADD_EMPTY_CASE(JSOP_NOP)
    1685               0 : ADD_EMPTY_CASE(JSOP_UNUSED0)
    1686               0 : ADD_EMPTY_CASE(JSOP_UNUSED1)
    1687               0 : ADD_EMPTY_CASE(JSOP_UNUSED2)
    1688               0 : ADD_EMPTY_CASE(JSOP_UNUSED3)
    1689               0 : ADD_EMPTY_CASE(JSOP_UNUSED4)
    1690               0 : ADD_EMPTY_CASE(JSOP_UNUSED5)
    1691               0 : ADD_EMPTY_CASE(JSOP_UNUSED6)
    1692               0 : ADD_EMPTY_CASE(JSOP_UNUSED7)
    1693               0 : ADD_EMPTY_CASE(JSOP_UNUSED8)
    1694               0 : ADD_EMPTY_CASE(JSOP_UNUSED9)
    1695               0 : ADD_EMPTY_CASE(JSOP_UNUSED10)
    1696               0 : ADD_EMPTY_CASE(JSOP_UNUSED11)
    1697               0 : ADD_EMPTY_CASE(JSOP_UNUSED12)
    1698               0 : ADD_EMPTY_CASE(JSOP_UNUSED13)
    1699               0 : ADD_EMPTY_CASE(JSOP_UNUSED14)
    1700               0 : ADD_EMPTY_CASE(JSOP_UNUSED15)
    1701               0 : ADD_EMPTY_CASE(JSOP_UNUSED16)
    1702               0 : ADD_EMPTY_CASE(JSOP_UNUSED17)
    1703               0 : ADD_EMPTY_CASE(JSOP_UNUSED18)
    1704               0 : ADD_EMPTY_CASE(JSOP_UNUSED19)
    1705               0 : ADD_EMPTY_CASE(JSOP_UNUSED20)
    1706               0 : ADD_EMPTY_CASE(JSOP_UNUSED21)
    1707               0 : ADD_EMPTY_CASE(JSOP_UNUSED22)
    1708               0 : ADD_EMPTY_CASE(JSOP_UNUSED23)
    1709               0 : ADD_EMPTY_CASE(JSOP_UNUSED24)
    1710               0 : ADD_EMPTY_CASE(JSOP_UNUSED25)
    1711               0 : ADD_EMPTY_CASE(JSOP_UNUSED26)
    1712               0 : ADD_EMPTY_CASE(JSOP_UNUSED27)
    1713               0 : ADD_EMPTY_CASE(JSOP_UNUSED28)
    1714               0 : ADD_EMPTY_CASE(JSOP_UNUSED29)
    1715               0 : ADD_EMPTY_CASE(JSOP_UNUSED30)
    1716               0 : ADD_EMPTY_CASE(JSOP_UNUSED31)
    1717         1000379 : ADD_EMPTY_CASE(JSOP_CONDSWITCH)
    1718          311778 : ADD_EMPTY_CASE(JSOP_TRY)
    1719                 : #if JS_HAS_XML_SUPPORT
    1720             622 : ADD_EMPTY_CASE(JSOP_STARTXML)
    1721               0 : ADD_EMPTY_CASE(JSOP_STARTXMLEXPR)
    1722                 : #endif
    1723       165503459 : ADD_EMPTY_CASE(JSOP_LOOPHEAD)
    1724       167597126 : ADD_EMPTY_CASE(JSOP_LOOPENTRY)
    1725                 : END_EMPTY_CASES
    1726                 : 
    1727                 : BEGIN_CASE(JSOP_LABEL)
    1728             403 : END_CASE(JSOP_LABEL)
    1729                 : 
    1730                 : check_backedge:
    1731                 : {
    1732       165506598 :     CHECK_BRANCH();
    1733       165506598 :     if (op != JSOP_LOOPHEAD)
    1734              87 :         DO_OP();
    1735                 : 
    1736                 : #ifdef JS_METHODJIT
    1737       165506511 :     if (!useMethodJIT)
    1738       165338202 :         DO_OP();
    1739                 :     mjit::CompileStatus status =
    1740          168309 :         mjit::CanMethodJIT(cx, script, regs.pc, regs.fp()->isConstructing(),
    1741          168309 :                            mjit::CompileRequest_Interpreter);
    1742          168309 :     if (status == mjit::Compile_Error)
    1743               0 :         goto error;
    1744          168309 :     if (status == mjit::Compile_Okay) {
    1745                 :         void *ncode =
    1746           24716 :             script->nativeCodeForPC(regs.fp()->isConstructing(), regs.pc);
    1747           24716 :         JS_ASSERT(ncode);
    1748           24716 :         mjit::JaegerStatus status = mjit::JaegerShotAtSafePoint(cx, ncode, true);
    1749           24716 :         if (status == mjit::Jaeger_ThrowBeforeEnter)
    1750               0 :             goto error;
    1751           24716 :         CHECK_PARTIAL_METHODJIT(status);
    1752            4248 :         interpReturnOK = (status == mjit::Jaeger_Returned);
    1753            4248 :         if (entryFrame != regs.fp())
    1754            3542 :             goto jit_return;
    1755             706 :         regs.fp()->setFinishedInInterpreter();
    1756             706 :         goto leave_on_safe_point;
    1757                 :     }
    1758          143593 :     if (status == mjit::Compile_Abort)
    1759           10858 :         useMethodJIT = false;
    1760                 : #endif /* JS_METHODJIT */
    1761                 : 
    1762          143593 :     DO_OP();
    1763                 : }
    1764                 : 
    1765                 : /* ADD_EMPTY_CASE is not used here as JSOP_LINENO_LENGTH == 3. */
    1766                 : BEGIN_CASE(JSOP_LINENO)
    1767           21905 : END_CASE(JSOP_LINENO)
    1768                 : 
    1769                 : BEGIN_CASE(JSOP_UNDEFINED)
    1770         9902520 :     PUSH_UNDEFINED();
    1771         9902520 : END_CASE(JSOP_UNDEFINED)
    1772                 : 
    1773                 : BEGIN_CASE(JSOP_POP)
    1774       372880092 :     regs.sp--;
    1775       372880092 : END_CASE(JSOP_POP)
    1776                 : 
    1777                 : BEGIN_CASE(JSOP_POPN)
    1778                 : {
    1779            2484 :     regs.sp -= GET_UINT16(regs.pc);
    1780                 : #ifdef DEBUG
    1781            2484 :     JS_ASSERT(regs.fp()->base() <= regs.sp);
    1782            2484 :     StaticBlockObject *block = regs.fp()->maybeBlockChain();
    1783             666 :     JS_ASSERT_IF(block,
    1784                 :                  block->stackDepth() + block->slotCount()
    1785            3150 :                  <= (size_t) (regs.sp - regs.fp()->base()));
    1786            5742 :     for (JSObject *obj = &regs.fp()->scopeChain(); obj; obj = obj->enclosingScope()) {
    1787            3258 :         if (!obj->isBlock() || !obj->isWith())
    1788            3258 :             continue;
    1789               0 :         if (obj->getPrivate() != js_FloatingFrameIfGenerator(cx, regs.fp()))
    1790               0 :             break;
    1791               0 :         JS_ASSERT(regs.fp()->base() + obj->asBlock().stackDepth()
    1792                 :                   + (obj->isBlock() ? obj->asBlock().slotCount() : 1)
    1793               0 :                   <= regs.sp);
    1794                 :     }
    1795                 : #endif
    1796                 : }
    1797            2484 : END_CASE(JSOP_POPN)
    1798                 : 
    1799                 : BEGIN_CASE(JSOP_SETRVAL)
    1800                 : BEGIN_CASE(JSOP_POPV)
    1801           62482 :     POP_RETURN_VALUE();
    1802           62482 : END_CASE(JSOP_POPV)
    1803                 : 
    1804                 : BEGIN_CASE(JSOP_ENTERWITH)
    1805            1773 :     if (!EnterWith(cx, -1))
    1806               9 :         goto error;
    1807                 : 
    1808                 :     /*
    1809                 :      * We must ensure that different "with" blocks have different stack depth
    1810                 :      * associated with them. This allows the try handler search to properly
    1811                 :      * recover the scope chain. Thus we must keep the stack at least at the
    1812                 :      * current level.
    1813                 :      *
    1814                 :      * We set sp[-1] to the current "with" object to help asserting the
    1815                 :      * enter/leave balance in [leavewith].
    1816                 :      */
    1817            1764 :     regs.sp[-1].setObject(regs.fp()->scopeChain());
    1818            1764 : END_CASE(JSOP_ENTERWITH)
    1819                 : 
    1820                 : BEGIN_CASE(JSOP_LEAVEWITH)
    1821            1737 :     JS_ASSERT(regs.sp[-1].toObject() == regs.fp()->scopeChain());
    1822            1737 :     regs.sp--;
    1823            1737 :     LeaveWith(cx);
    1824            1737 : END_CASE(JSOP_LEAVEWITH)
    1825                 : 
    1826                 : BEGIN_CASE(JSOP_RETURN)
    1827         6064878 :     POP_RETURN_VALUE();
    1828                 :     /* FALL THROUGH */
    1829                 : 
    1830                 : BEGIN_CASE(JSOP_RETRVAL)    /* fp return value already set */
    1831                 : BEGIN_CASE(JSOP_STOP)
    1832                 : {
    1833                 :     /*
    1834                 :      * When the inlined frame exits with an exception or an error, ok will be
    1835                 :      * false after the inline_return label.
    1836                 :      */
    1837         8488409 :     CHECK_BRANCH();
    1838                 : 
    1839         8488409 :     interpReturnOK = true;
    1840         8488409 :     if (entryFrame != regs.fp())
    1841                 :   inline_return:
    1842                 :     {
    1843        10000754 :         JS_ASSERT(!regs.fp()->hasBlockChain());
    1844        10000754 :         JS_ASSERT(!IsActiveWithOrBlock(cx, regs.fp()->scopeChain(), 0));
    1845                 : 
    1846        10000754 :         if (cx->compartment->debugMode())
    1847          867842 :             interpReturnOK = ScriptDebugEpilogue(cx, regs.fp(), interpReturnOK);
    1848                 :  
    1849        10000754 :         interpReturnOK = ScriptEpilogue(cx, regs.fp(), interpReturnOK);
    1850                 : 
    1851                 :         /* The JIT inlines ScriptEpilogue. */
    1852                 : #ifdef JS_METHODJIT
    1853                 :   jit_return:
    1854                 : #endif
    1855                 : 
    1856                 :         /* The results of lowered call/apply frames need to be shifted. */
    1857        10093872 :         bool shiftResult = regs.fp()->loweredCallOrApply();
    1858                 : 
    1859        10093872 :         cx->stack.popInlineFrame(regs);
    1860                 : 
    1861        10093872 :         RESTORE_INTERP_VARS();
    1862                 : 
    1863               0 :         JS_ASSERT(*regs.pc == JSOP_NEW || *regs.pc == JSOP_CALL ||
    1864        10093872 :                   *regs.pc == JSOP_FUNCALL || *regs.pc == JSOP_FUNAPPLY);
    1865                 : 
    1866                 :         /* Resume execution in the calling frame. */
    1867        10093872 :         RESET_USE_METHODJIT();
    1868        10093872 :         if (JS_LIKELY(interpReturnOK)) {
    1869         8096273 :             TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
    1870                 : 
    1871         8096273 :             if (shiftResult) {
    1872              39 :                 regs.sp[-2] = regs.sp[-1];
    1873              39 :                 regs.sp--;
    1874                 :             }
    1875                 : 
    1876         8096273 :             len = JSOP_CALL_LENGTH;
    1877         8096273 :             DO_NEXT_OP(len);
    1878                 :         }
    1879                 : 
    1880                 :         /* Increment pc so that |sp - fp->slots == ReconstructStackDepth(pc)|. */
    1881         1997599 :         regs.pc += JSOP_CALL_LENGTH;
    1882         1997599 :         goto error;
    1883                 :     } else {
    1884          489369 :         JS_ASSERT(regs.sp == regs.fp()->base());
    1885                 :     }
    1886          489369 :     interpReturnOK = true;
    1887          489369 :     goto exit;
    1888                 : }
    1889                 : 
    1890                 : BEGIN_CASE(JSOP_DEFAULT)
    1891             162 :     regs.sp--;
    1892                 :     /* FALL THROUGH */
    1893                 : BEGIN_CASE(JSOP_GOTO)
    1894                 : {
    1895         5528659 :     len = GET_JUMP_OFFSET(regs.pc);
    1896         5528659 :     BRANCH(len);
    1897                 : }
    1898                 : END_CASE(JSOP_GOTO)
    1899                 : 
    1900                 : BEGIN_CASE(JSOP_IFEQ)
    1901                 : {
    1902                 :     bool cond;
    1903                 :     Value *_;
    1904         6694869 :     POP_BOOLEAN(cx, _, cond);
    1905         6694869 :     if (cond == false) {
    1906         4404471 :         len = GET_JUMP_OFFSET(regs.pc);
    1907         4404471 :         BRANCH(len);
    1908                 :     }
    1909                 : }
    1910         2290398 : END_CASE(JSOP_IFEQ)
    1911                 : 
    1912                 : BEGIN_CASE(JSOP_IFNE)
    1913                 : {
    1914                 :     bool cond;
    1915                 :     Value *_;
    1916         5100948 :     POP_BOOLEAN(cx, _, cond);
    1917         5100948 :     if (cond != false) {
    1918         4891492 :         len = GET_JUMP_OFFSET(regs.pc);
    1919         4891492 :         BRANCH(len);
    1920                 :     }
    1921                 : }
    1922          209456 : END_CASE(JSOP_IFNE)
    1923                 : 
    1924                 : BEGIN_CASE(JSOP_OR)
    1925                 : {
    1926                 :     bool cond;
    1927                 :     Value *_;
    1928          435506 :     VALUE_TO_BOOLEAN(cx, _, cond);
    1929          435506 :     if (cond == true) {
    1930          120464 :         len = GET_JUMP_OFFSET(regs.pc);
    1931          120464 :         DO_NEXT_OP(len);
    1932                 :     }
    1933                 : }
    1934          315042 : END_CASE(JSOP_OR)
    1935                 : 
    1936                 : BEGIN_CASE(JSOP_AND)
    1937                 : {
    1938                 :     bool cond;
    1939                 :     Value *_;
    1940          147178 :     VALUE_TO_BOOLEAN(cx, _, cond);
    1941          147178 :     if (cond == false) {
    1942           67206 :         len = GET_JUMP_OFFSET(regs.pc);
    1943           67206 :         DO_NEXT_OP(len);
    1944                 :     }
    1945                 : }
    1946           79972 : END_CASE(JSOP_AND)
    1947                 : 
    1948                 : /*
    1949                 :  * If the index value at sp[n] is not an int that fits in a jsval, it could
    1950                 :  * be an object (an XML QName, AttributeName, or AnyName), but only if we are
    1951                 :  * compiling with JS_HAS_XML_SUPPORT.  Otherwise convert the index value to a
    1952                 :  * string atom id.
    1953                 :  */
    1954                 : #define FETCH_ELEMENT_ID(obj, n, id)                                          \
    1955                 :     JS_BEGIN_MACRO                                                            \
    1956                 :         const Value &idval_ = regs.sp[n];                                     \
    1957                 :         int32_t i_;                                                           \
    1958                 :         if (ValueFitsInInt32(idval_, &i_) && INT_FITS_IN_JSID(i_)) {          \
    1959                 :             id = INT_TO_JSID(i_);                                             \
    1960                 :         } else {                                                              \
    1961                 :             if (!js_InternNonIntElementId(cx, obj, idval_, &id, &regs.sp[n])) \
    1962                 :                 goto error;                                                   \
    1963                 :         }                                                                     \
    1964                 :     JS_END_MACRO
    1965                 : 
    1966                 : #define TRY_BRANCH_AFTER_COND(cond,spdec)                                     \
    1967                 :     JS_BEGIN_MACRO                                                            \
    1968                 :         JS_ASSERT(js_CodeSpec[op].length == 1);                               \
    1969                 :         unsigned diff_ = (unsigned) GET_UINT8(regs.pc) - (unsigned) JSOP_IFEQ;         \
    1970                 :         if (diff_ <= 1) {                                                     \
    1971                 :             regs.sp -= spdec;                                                 \
    1972                 :             if (cond == (diff_ != 0)) {                                       \
    1973                 :                 ++regs.pc;                                                    \
    1974                 :                 len = GET_JUMP_OFFSET(regs.pc);                               \
    1975                 :                 BRANCH(len);                                                  \
    1976                 :             }                                                                 \
    1977                 :             len = 1 + JSOP_IFEQ_LENGTH;                                       \
    1978                 :             DO_NEXT_OP(len);                                                  \
    1979                 :         }                                                                     \
    1980                 :     JS_END_MACRO
    1981                 : 
    1982                 : BEGIN_CASE(JSOP_IN)
    1983                 : {
    1984          151982 :     const Value &rref = regs.sp[-1];
    1985          151982 :     if (!rref.isObject()) {
    1986              11 :         js_ReportValueError(cx, JSMSG_IN_NOT_OBJECT, -1, rref, NULL);
    1987              11 :         goto error;
    1988                 :     }
    1989          151971 :     JSObject *obj = &rref.toObject();
    1990                 :     jsid id;
    1991          151971 :     FETCH_ELEMENT_ID(obj, -2, id);
    1992                 :     JSObject *obj2;
    1993                 :     JSProperty *prop;
    1994          151971 :     if (!obj->lookupGeneric(cx, id, &obj2, &prop))
    1995               0 :         goto error;
    1996          151971 :     bool cond = prop != NULL;
    1997          151971 :     TRY_BRANCH_AFTER_COND(cond, 2);
    1998          150983 :     regs.sp--;
    1999          150983 :     regs.sp[-1].setBoolean(cond);
    2000                 : }
    2001          150983 : END_CASE(JSOP_IN)
    2002                 : 
    2003                 : BEGIN_CASE(JSOP_ITER)
    2004                 : {
    2005          164682 :     JS_ASSERT(regs.sp > regs.fp()->base());
    2006          164682 :     uint8_t flags = GET_UINT8(regs.pc);
    2007          164682 :     if (!ValueToIterator(cx, flags, &regs.sp[-1]))
    2008             150 :         goto error;
    2009          164532 :     CHECK_INTERRUPT_HANDLER();
    2010          164532 :     JS_ASSERT(!regs.sp[-1].isPrimitive());
    2011                 : }
    2012          164532 : END_CASE(JSOP_ITER)
    2013                 : 
    2014                 : BEGIN_CASE(JSOP_MOREITER)
    2015                 : {
    2016         3273845 :     JS_ASSERT(regs.sp - 1 >= regs.fp()->base());
    2017         3273845 :     JS_ASSERT(regs.sp[-1].isObject());
    2018         3273845 :     PUSH_NULL();
    2019                 :     bool cond;
    2020         3273845 :     if (!IteratorMore(cx, &regs.sp[-2].toObject(), &cond, &regs.sp[-1]))
    2021              20 :         goto error;
    2022         3273825 :     CHECK_INTERRUPT_HANDLER();
    2023         3273825 :     regs.sp[-1].setBoolean(cond);
    2024                 : }
    2025         3273825 : END_CASE(JSOP_MOREITER)
    2026                 : 
    2027                 : BEGIN_CASE(JSOP_ITERNEXT)
    2028                 : {
    2029         3221647 :     Value *itervp = regs.sp - GET_INT8(regs.pc);
    2030         3221647 :     JS_ASSERT(itervp >= regs.fp()->base());
    2031         3221647 :     JS_ASSERT(itervp->isObject());
    2032         3221647 :     PUSH_NULL();
    2033         3221647 :     if (!IteratorNext(cx, &itervp->toObject(), &regs.sp[-1]))
    2034               0 :         goto error;
    2035                 : }
    2036         3221647 : END_CASE(JSOP_ITERNEXT)
    2037                 : 
    2038                 : BEGIN_CASE(JSOP_ENDITER)
    2039                 : {
    2040          165285 :     JS_ASSERT(regs.sp - 1 >= regs.fp()->base());
    2041          165285 :     bool ok = CloseIterator(cx, &regs.sp[-1].toObject());
    2042          165285 :     regs.sp--;
    2043          165285 :     if (!ok)
    2044               0 :         goto error;
    2045                 : }
    2046          165285 : END_CASE(JSOP_ENDITER)
    2047                 : 
    2048                 : BEGIN_CASE(JSOP_DUP)
    2049                 : {
    2050         7853022 :     JS_ASSERT(regs.sp > regs.fp()->base());
    2051         7853022 :     const Value &rref = regs.sp[-1];
    2052         7853022 :     PUSH_COPY(rref);
    2053                 : }
    2054         7853022 : END_CASE(JSOP_DUP)
    2055                 : 
    2056                 : BEGIN_CASE(JSOP_DUP2)
    2057                 : {
    2058         1361954 :     JS_ASSERT(regs.sp - 2 >= regs.fp()->base());
    2059         1361954 :     const Value &lref = regs.sp[-2];
    2060         1361954 :     const Value &rref = regs.sp[-1];
    2061         1361954 :     PUSH_COPY(lref);
    2062         1361954 :     PUSH_COPY(rref);
    2063                 : }
    2064         1361954 : END_CASE(JSOP_DUP2)
    2065                 : 
    2066                 : BEGIN_CASE(JSOP_SWAP)
    2067                 : {
    2068         7035032 :     JS_ASSERT(regs.sp - 2 >= regs.fp()->base());
    2069         7035032 :     Value &lref = regs.sp[-2];
    2070         7035032 :     Value &rref = regs.sp[-1];
    2071         7035032 :     lref.swap(rref);
    2072                 : }
    2073         7035032 : END_CASE(JSOP_SWAP)
    2074                 : 
    2075                 : BEGIN_CASE(JSOP_PICK)
    2076                 : {
    2077         1237665 :     unsigned i = GET_UINT8(regs.pc);
    2078         1237665 :     JS_ASSERT(regs.sp - (i + 1) >= regs.fp()->base());
    2079         1237665 :     Value lval = regs.sp[-int(i + 1)];
    2080         1237665 :     memmove(regs.sp - (i + 1), regs.sp - i, sizeof(Value) * i);
    2081         1237665 :     regs.sp[-1] = lval;
    2082                 : }
    2083         1237665 : END_CASE(JSOP_PICK)
    2084                 : 
    2085                 : BEGIN_CASE(JSOP_SETCONST)
    2086                 : {
    2087                 :     PropertyName *name;
    2088           31053 :     LOAD_NAME(0, name);
    2089           31053 :     JSObject &obj = regs.fp()->varObj();
    2090           31053 :     const Value &ref = regs.sp[-1];
    2091           31053 :     if (!obj.defineProperty(cx, name, ref,
    2092                 :                             JS_PropertyStub, JS_StrictPropertyStub,
    2093           31053 :                             JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY)) {
    2094               0 :         goto error;
    2095                 :     }
    2096                 : }
    2097           31053 : END_CASE(JSOP_SETCONST);
    2098                 : 
    2099                 : #if JS_HAS_DESTRUCTURING
    2100                 : BEGIN_CASE(JSOP_ENUMCONSTELEM)
    2101                 : {
    2102               0 :     const Value &ref = regs.sp[-3];
    2103                 :     JSObject *obj;
    2104               0 :     FETCH_OBJECT(cx, -2, obj);
    2105                 :     jsid id;
    2106               0 :     FETCH_ELEMENT_ID(obj, -1, id);
    2107               0 :     if (!obj->defineGeneric(cx, id, ref,
    2108                 :                             JS_PropertyStub, JS_StrictPropertyStub,
    2109               0 :                             JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY)) {
    2110               0 :         goto error;
    2111                 :     }
    2112               0 :     regs.sp -= 3;
    2113                 : }
    2114               0 : END_CASE(JSOP_ENUMCONSTELEM)
    2115                 : #endif
    2116                 : 
    2117                 : BEGIN_CASE(JSOP_BINDGNAME)
    2118        11778173 :     PUSH_OBJECT(regs.fp()->scopeChain().global());
    2119        11778173 : END_CASE(JSOP_BINDGNAME)
    2120                 : 
    2121                 : BEGIN_CASE(JSOP_BINDNAME)
    2122                 : {
    2123                 :     JSObject *obj;
    2124                 :     do {
    2125                 :         /*
    2126                 :          * We can skip the property lookup for the global object. If the
    2127                 :          * property does not exist anywhere on the scope chain, JSOP_SETNAME
    2128                 :          * adds the property to the global.
    2129                 :          *
    2130                 :          * As a consequence of this optimization for the global object we run
    2131                 :          * its JSRESOLVE_ASSIGNING-tolerant resolve hooks only in JSOP_SETNAME,
    2132                 :          * after the interpreter evaluates the right- hand-side of the
    2133                 :          * assignment, and not here.
    2134                 :          *
    2135                 :          * This should be transparent to the hooks because the script, instead
    2136                 :          * of name = rhs, could have used global.name = rhs given a global
    2137                 :          * object reference, which also calls the hooks only after evaluating
    2138                 :          * the rhs. We desire such resolve hook equivalence between the two
    2139                 :          * forms.
    2140                 :          */
    2141           29387 :         obj = &regs.fp()->scopeChain();
    2142           29387 :         if (obj->isGlobal())
    2143            7238 :             break;
    2144                 : 
    2145                 :         PropertyName *name;
    2146           22149 :         LOAD_NAME(0, name);
    2147                 : 
    2148           22149 :         obj = FindIdentifierBase(cx, &regs.fp()->scopeChain(), name);
    2149           22149 :         if (!obj)
    2150               0 :             goto error;
    2151                 :     } while (0);
    2152           29387 :     PUSH_OBJECT(*obj);
    2153                 : }
    2154           29387 : END_CASE(JSOP_BINDNAME)
    2155                 : 
    2156                 : #define BITWISE_OP(OP)                                                        \
    2157                 :     JS_BEGIN_MACRO                                                            \
    2158                 :         int32_t i, j;                                                         \
    2159                 :         if (!ToInt32(cx, regs.sp[-2], &i))                                    \
    2160                 :             goto error;                                                       \
    2161                 :         if (!ToInt32(cx, regs.sp[-1], &j))                                    \
    2162                 :             goto error;                                                       \
    2163                 :         i = i OP j;                                                           \
    2164                 :         regs.sp--;                                                            \
    2165                 :         regs.sp[-1].setInt32(i);                                              \
    2166                 :     JS_END_MACRO
    2167                 : 
    2168                 : BEGIN_CASE(JSOP_BITOR)
    2169          586935 :     BITWISE_OP(|);
    2170          586929 : END_CASE(JSOP_BITOR)
    2171                 : 
    2172                 : BEGIN_CASE(JSOP_BITXOR)
    2173          603545 :     BITWISE_OP(^);
    2174          603545 : END_CASE(JSOP_BITXOR)
    2175                 : 
    2176                 : BEGIN_CASE(JSOP_BITAND)
    2177        20918186 :     BITWISE_OP(&);
    2178        20918186 : END_CASE(JSOP_BITAND)
    2179                 : 
    2180                 : #undef BITWISE_OP
    2181                 : 
    2182                 : #define EQUALITY_OP(OP)                                                       \
    2183                 :     JS_BEGIN_MACRO                                                            \
    2184                 :         Value rval = regs.sp[-1];                                             \
    2185                 :         Value lval = regs.sp[-2];                                             \
    2186                 :         bool cond;                                                            \
    2187                 :         if (!LooselyEqual(cx, lval, rval, &cond))                             \
    2188                 :             goto error;                                                       \
    2189                 :         cond = cond OP JS_TRUE;                                               \
    2190                 :         TRY_BRANCH_AFTER_COND(cond, 2);                                       \
    2191                 :         regs.sp--;                                                            \
    2192                 :         regs.sp[-1].setBoolean(cond);                                         \
    2193                 :     JS_END_MACRO
    2194                 : 
    2195                 : BEGIN_CASE(JSOP_EQ)
    2196         3855745 :     EQUALITY_OP(==);
    2197          654590 : END_CASE(JSOP_EQ)
    2198                 : 
    2199                 : BEGIN_CASE(JSOP_NE)
    2200          488826 :     EQUALITY_OP(!=);
    2201           42247 : END_CASE(JSOP_NE)
    2202                 : 
    2203                 : #undef EQUALITY_OP
    2204                 : 
    2205                 : #define STRICT_EQUALITY_OP(OP, COND)                                          \
    2206                 :     JS_BEGIN_MACRO                                                            \
    2207                 :         const Value &rref = regs.sp[-1];                                      \
    2208                 :         const Value &lref = regs.sp[-2];                                      \
    2209                 :         bool equal;                                                           \
    2210                 :         if (!StrictlyEqual(cx, lref, rref, &equal))                           \
    2211                 :             goto error;                                                       \
    2212                 :         COND = equal OP JS_TRUE;                                              \
    2213                 :         regs.sp--;                                                            \
    2214                 :     JS_END_MACRO
    2215                 : 
    2216                 : BEGIN_CASE(JSOP_STRICTEQ)
    2217                 : {
    2218                 :     bool cond;
    2219         1778962 :     STRICT_EQUALITY_OP(==, cond);
    2220         1778962 :     regs.sp[-1].setBoolean(cond);
    2221                 : }
    2222         1778962 : END_CASE(JSOP_STRICTEQ)
    2223                 : 
    2224                 : BEGIN_CASE(JSOP_STRICTNE)
    2225                 : {
    2226                 :     bool cond;
    2227          863114 :     STRICT_EQUALITY_OP(!=, cond);
    2228          863114 :     regs.sp[-1].setBoolean(cond);
    2229                 : }
    2230          863114 : END_CASE(JSOP_STRICTNE)
    2231                 : 
    2232                 : BEGIN_CASE(JSOP_CASE)
    2233                 : {
    2234                 :     bool cond;
    2235         1000977 :     STRICT_EQUALITY_OP(==, cond);
    2236         1000977 :     if (cond) {
    2237         1000245 :         regs.sp--;
    2238         1000245 :         len = GET_JUMP_OFFSET(regs.pc);
    2239         1000245 :         BRANCH(len);
    2240                 :     }
    2241                 : }
    2242             732 : END_CASE(JSOP_CASE)
    2243                 : 
    2244                 : #undef STRICT_EQUALITY_OP
    2245                 : 
    2246                 : BEGIN_CASE(JSOP_LT)
    2247                 : {
    2248                 :     bool cond;
    2249       156837398 :     const Value &lref = regs.sp[-2];
    2250       156837398 :     const Value &rref = regs.sp[-1];
    2251       156837398 :     if (!LessThanOperation(cx, lref, rref, &cond))
    2252               0 :         goto error;
    2253       156837398 :     TRY_BRANCH_AFTER_COND(cond, 2);
    2254          153859 :     regs.sp[-2].setBoolean(cond);
    2255          153859 :     regs.sp--;
    2256                 : }
    2257          153859 : END_CASE(JSOP_LT)
    2258                 : 
    2259                 : BEGIN_CASE(JSOP_LE)
    2260                 : {
    2261                 :     bool cond;
    2262         1705631 :     const Value &lref = regs.sp[-2];
    2263         1705631 :     const Value &rref = regs.sp[-1];
    2264         1705631 :     if (!LessThanOrEqualOperation(cx, lref, rref, &cond))
    2265               0 :         goto error;
    2266         1705631 :     TRY_BRANCH_AFTER_COND(cond, 2);
    2267            7978 :     regs.sp[-2].setBoolean(cond);
    2268            7978 :     regs.sp--;
    2269                 : }
    2270            7978 : END_CASE(JSOP_LE)
    2271                 : 
    2272                 : BEGIN_CASE(JSOP_GT)
    2273                 : {
    2274                 :     bool cond;
    2275         1539957 :     const Value &lref = regs.sp[-2];
    2276         1539957 :     const Value &rref = regs.sp[-1];
    2277         1539957 :     if (!GreaterThanOperation(cx, lref, rref, &cond))
    2278               7 :         goto error;
    2279         1539950 :     TRY_BRANCH_AFTER_COND(cond, 2);
    2280           52648 :     regs.sp[-2].setBoolean(cond);
    2281           52648 :     regs.sp--;
    2282                 : }
    2283           52648 : END_CASE(JSOP_GT)
    2284                 : 
    2285                 : BEGIN_CASE(JSOP_GE)
    2286                 : {
    2287                 :     bool cond;
    2288         6143501 :     const Value &lref = regs.sp[-2];
    2289         6143501 :     const Value &rref = regs.sp[-1];
    2290         6143501 :     if (!GreaterThanOrEqualOperation(cx, lref, rref, &cond))
    2291               0 :         goto error;
    2292         6143501 :     TRY_BRANCH_AFTER_COND(cond, 2);
    2293           22645 :     regs.sp[-2].setBoolean(cond);
    2294           22645 :     regs.sp--;
    2295                 : }
    2296           22645 : END_CASE(JSOP_GE)
    2297                 : 
    2298                 : #define SIGNED_SHIFT_OP(OP)                                                   \
    2299                 :     JS_BEGIN_MACRO                                                            \
    2300                 :         int32_t i, j;                                                         \
    2301                 :         if (!ToInt32(cx, regs.sp[-2], &i))                                    \
    2302                 :             goto error;                                                       \
    2303                 :         if (!ToInt32(cx, regs.sp[-1], &j))                                    \
    2304                 :             goto error;                                                       \
    2305                 :         i = i OP (j & 31);                                                    \
    2306                 :         regs.sp--;                                                            \
    2307                 :         regs.sp[-1].setInt32(i);                                              \
    2308                 :     JS_END_MACRO
    2309                 : 
    2310                 : BEGIN_CASE(JSOP_LSH)
    2311         8255527 :     SIGNED_SHIFT_OP(<<);
    2312         8255527 : END_CASE(JSOP_LSH)
    2313                 : 
    2314                 : BEGIN_CASE(JSOP_RSH)
    2315        18667328 :     SIGNED_SHIFT_OP(>>);
    2316        18667328 : END_CASE(JSOP_RSH)
    2317                 : 
    2318                 : #undef SIGNED_SHIFT_OP
    2319                 : 
    2320                 : BEGIN_CASE(JSOP_URSH)
    2321                 : {
    2322                 :     uint32_t u;
    2323          140215 :     if (!ToUint32(cx, regs.sp[-2], &u))
    2324               0 :         goto error;
    2325                 :     int32_t j;
    2326          140215 :     if (!ToInt32(cx, regs.sp[-1], &j))
    2327               0 :         goto error;
    2328                 : 
    2329          140215 :     u >>= (j & 31);
    2330                 : 
    2331          140215 :     regs.sp--;
    2332          140215 :     if (!regs.sp[-1].setNumber(uint32_t(u)))
    2333             384 :         TypeScript::MonitorOverflow(cx, script, regs.pc);
    2334                 : }
    2335          140215 : END_CASE(JSOP_URSH)
    2336                 : 
    2337                 : BEGIN_CASE(JSOP_ADD)
    2338                 : {
    2339        50410500 :     Value lval = regs.sp[-2];
    2340        50410500 :     Value rval = regs.sp[-1];
    2341        50410500 :     if (!AddOperation(cx, lval, rval, &regs.sp[-2]))
    2342              56 :         goto error;
    2343        50410444 :     regs.sp--;
    2344                 : }
    2345        50410444 : END_CASE(JSOP_ADD)
    2346                 : 
    2347                 : BEGIN_CASE(JSOP_SUB)
    2348                 : {
    2349         6564664 :     Value lval = regs.sp[-2];
    2350         6564664 :     Value rval = regs.sp[-1];
    2351         6564664 :     if (!SubOperation(cx, lval, rval, &regs.sp[-2]))
    2352               0 :         goto error;
    2353         6564664 :     regs.sp--;
    2354                 : }
    2355         6564664 : END_CASE(JSOP_SUB)
    2356                 : 
    2357                 : BEGIN_CASE(JSOP_MUL)
    2358                 : {
    2359        24958944 :     Value lval = regs.sp[-2];
    2360        24958944 :     Value rval = regs.sp[-1];
    2361        24958944 :     if (!MulOperation(cx, lval, rval, &regs.sp[-2]))
    2362               0 :         goto error;
    2363        24958944 :     regs.sp--;
    2364                 : }
    2365        24958944 : END_CASE(JSOP_MUL)
    2366                 : 
    2367                 : BEGIN_CASE(JSOP_DIV)
    2368                 : {
    2369         1388305 :     Value lval = regs.sp[-2];
    2370         1388305 :     Value rval = regs.sp[-1];
    2371         1388305 :     if (!DivOperation(cx, lval, rval, &regs.sp[-2]))
    2372               0 :         goto error;
    2373         1388305 :     regs.sp--;
    2374                 : }
    2375         1388305 : END_CASE(JSOP_DIV)
    2376                 : 
    2377                 : BEGIN_CASE(JSOP_MOD)
    2378                 : {
    2379          457306 :     Value lval = regs.sp[-2];
    2380          457306 :     Value rval = regs.sp[-1];
    2381          457306 :     if (!ModOperation(cx, lval, rval, &regs.sp[-2]))
    2382               0 :         goto error;
    2383          457306 :     regs.sp--;
    2384                 : }
    2385          457306 : END_CASE(JSOP_MOD)
    2386                 : 
    2387                 : BEGIN_CASE(JSOP_NOT)
    2388                 : {
    2389                 :     Value *_;
    2390                 :     bool cond;
    2391         2223668 :     POP_BOOLEAN(cx, _, cond);
    2392         2223668 :     PUSH_BOOLEAN(!cond);
    2393                 : }
    2394         2223668 : END_CASE(JSOP_NOT)
    2395                 : 
    2396                 : BEGIN_CASE(JSOP_BITNOT)
    2397                 : {
    2398                 :     int32_t i;
    2399          867829 :     if (!ToInt32(cx, regs.sp[-1], &i))
    2400               0 :         goto error;
    2401          867829 :     i = ~i;
    2402          867829 :     regs.sp[-1].setInt32(i);
    2403                 : }
    2404          867829 : END_CASE(JSOP_BITNOT)
    2405                 : 
    2406                 : BEGIN_CASE(JSOP_NEG)
    2407                 : {
    2408                 :     /*
    2409                 :      * When the operand is int jsval, INT32_FITS_IN_JSVAL(i) implies
    2410                 :      * INT32_FITS_IN_JSVAL(-i) unless i is 0 or INT32_MIN when the
    2411                 :      * results, -0.0 or INT32_MAX + 1, are double values.
    2412                 :      */
    2413          745377 :     Value ref = regs.sp[-1];
    2414                 :     int32_t i;
    2415          745377 :     if (ref.isInt32() && (i = ref.toInt32()) != 0 && i != INT32_MIN) {
    2416          268064 :         i = -i;
    2417          268064 :         regs.sp[-1].setInt32(i);
    2418                 :     } else {
    2419                 :         double d;
    2420          477313 :         if (!ToNumber(cx, regs.sp[-1], &d))
    2421               0 :             goto error;
    2422          477313 :         d = -d;
    2423          477313 :         if (!regs.sp[-1].setNumber(d) && !ref.isDouble())
    2424            4129 :             TypeScript::MonitorOverflow(cx, script, regs.pc);
    2425                 :     }
    2426                 : }
    2427          745377 : END_CASE(JSOP_NEG)
    2428                 : 
    2429                 : BEGIN_CASE(JSOP_POS)
    2430         4054389 :     if (!ToNumber(cx, &regs.sp[-1]))
    2431               0 :         goto error;
    2432         4054389 :     if (!regs.sp[-1].isInt32())
    2433            2528 :         TypeScript::MonitorOverflow(cx, script, regs.pc);
    2434         4054389 : END_CASE(JSOP_POS)
    2435                 : 
    2436                 : BEGIN_CASE(JSOP_DELNAME)
    2437                 : {
    2438                 :     PropertyName *name;
    2439             322 :     LOAD_NAME(0, name);
    2440                 :     JSObject *obj, *obj2;
    2441                 :     JSProperty *prop;
    2442             322 :     if (!FindProperty(cx, name, cx->stack.currentScriptedScopeChain(), &obj, &obj2, &prop))
    2443               0 :         goto error;
    2444                 : 
    2445                 :     /* Strict mode code should never contain JSOP_DELNAME opcodes. */
    2446             322 :     JS_ASSERT(!script->strictModeCode);
    2447                 : 
    2448                 :     /* ECMA says to return true if name is undefined or inherited. */
    2449             322 :     PUSH_BOOLEAN(true);
    2450             322 :     if (prop) {
    2451             239 :         if (!obj->deleteProperty(cx, name, &regs.sp[-1], false))
    2452               0 :             goto error;
    2453                 :     }
    2454                 : }
    2455             322 : END_CASE(JSOP_DELNAME)
    2456                 : 
    2457                 : BEGIN_CASE(JSOP_DELPROP)
    2458                 : {
    2459                 :     PropertyName *name;
    2460             589 :     LOAD_NAME(0, name);
    2461                 : 
    2462                 :     JSObject *obj;
    2463             589 :     FETCH_OBJECT(cx, -1, obj);
    2464                 : 
    2465                 :     Value rval;
    2466             589 :     if (!obj->deleteProperty(cx, name, &rval, script->strictModeCode))
    2467               0 :         goto error;
    2468                 : 
    2469             589 :     regs.sp[-1] = rval;
    2470                 : }
    2471             589 : END_CASE(JSOP_DELPROP)
    2472                 : 
    2473                 : BEGIN_CASE(JSOP_DELELEM)
    2474                 : {
    2475                 :     /* Fetch the left part and resolve it to a non-null object. */
    2476                 :     JSObject *obj;
    2477            1160 :     FETCH_OBJECT(cx, -2, obj);
    2478                 : 
    2479            1160 :     const Value &propval = regs.sp[-1];
    2480            1160 :     Value &rval = regs.sp[-2];
    2481                 : 
    2482            1160 :     if (!obj->deleteByValue(cx, propval, &rval, script->strictModeCode))
    2483               7 :         goto error;
    2484                 : 
    2485            1153 :     regs.sp--;
    2486                 : }
    2487            1153 : END_CASE(JSOP_DELELEM)
    2488                 : 
    2489                 : BEGIN_CASE(JSOP_TOID)
    2490                 : {
    2491                 :     /*
    2492                 :      * Increment or decrement requires use to lookup the same property twice, but we need to avoid
    2493                 :      * the oberservable stringification the second time.
    2494                 :      * There must be an object value below the id, which will not be popped
    2495                 :      * but is necessary in interning the id for XML.
    2496                 :      */
    2497           83249 :     Value objval = regs.sp[-2];
    2498           83249 :     Value idval = regs.sp[-1];
    2499           83249 :     if (!ToIdOperation(cx, objval, idval, &regs.sp[-1]))
    2500               0 :         goto error;
    2501                 : }
    2502           83249 : END_CASE(JSOP_TOID)
    2503                 : 
    2504                 : BEGIN_CASE(JSOP_TYPEOFEXPR)
    2505                 : BEGIN_CASE(JSOP_TYPEOF)
    2506                 : {
    2507           98933 :     const Value &ref = regs.sp[-1];
    2508           98933 :     JSType type = JS_TypeOfValue(cx, ref);
    2509           98933 :     regs.sp[-1].setString(rt->atomState.typeAtoms[type]);
    2510                 : }
    2511           98933 : END_CASE(JSOP_TYPEOF)
    2512                 : 
    2513                 : BEGIN_CASE(JSOP_VOID)
    2514            1222 :     regs.sp[-1].setUndefined();
    2515            1222 : END_CASE(JSOP_VOID)
    2516                 : 
    2517                 : BEGIN_CASE(JSOP_INCELEM)
    2518                 : BEGIN_CASE(JSOP_DECELEM)
    2519                 : BEGIN_CASE(JSOP_ELEMINC)
    2520                 : BEGIN_CASE(JSOP_ELEMDEC)
    2521                 :     /* No-op */
    2522           83249 : END_CASE(JSOP_INCELEM)
    2523                 : 
    2524                 : BEGIN_CASE(JSOP_INCPROP)
    2525                 : BEGIN_CASE(JSOP_DECPROP)
    2526                 : BEGIN_CASE(JSOP_PROPINC)
    2527                 : BEGIN_CASE(JSOP_PROPDEC)
    2528                 : BEGIN_CASE(JSOP_INCNAME)
    2529                 : BEGIN_CASE(JSOP_DECNAME)
    2530                 : BEGIN_CASE(JSOP_NAMEINC)
    2531                 : BEGIN_CASE(JSOP_NAMEDEC)
    2532                 : BEGIN_CASE(JSOP_INCGNAME)
    2533                 : BEGIN_CASE(JSOP_DECGNAME)
    2534                 : BEGIN_CASE(JSOP_GNAMEINC)
    2535                 : BEGIN_CASE(JSOP_GNAMEDEC)
    2536                 :     /* No-op */
    2537         3969902 : END_CASE(JSOP_INCPROP)
    2538                 : 
    2539                 : BEGIN_CASE(JSOP_DECARG)
    2540                 : BEGIN_CASE(JSOP_ARGDEC)
    2541                 : BEGIN_CASE(JSOP_INCARG)
    2542                 : BEGIN_CASE(JSOP_ARGINC)
    2543                 : {
    2544        13818630 :     Value &arg = regs.fp()->formalArg(GET_ARGNO(regs.pc));
    2545        13818630 :     if (!DoIncDec(cx, script, regs.pc, arg, &arg, &regs.sp[0]))
    2546               0 :         goto error;
    2547        13818630 :     regs.sp++;
    2548                 : }
    2549        13818630 : END_CASE(JSOP_ARGINC);
    2550                 : 
    2551                 : BEGIN_CASE(JSOP_DECLOCAL)
    2552                 : BEGIN_CASE(JSOP_LOCALDEC)
    2553                 : BEGIN_CASE(JSOP_INCLOCAL)
    2554                 : BEGIN_CASE(JSOP_LOCALINC)
    2555                 : {
    2556       290180157 :     Value &local = regs.fp()->localSlot(GET_SLOTNO(regs.pc));
    2557       290180157 :     if (!DoIncDec(cx, script, regs.pc, local, &local, &regs.sp[0]))
    2558               0 :         goto error;
    2559       290180157 :     regs.sp++;
    2560                 : }
    2561       290180157 : END_CASE(JSOP_LOCALINC)
    2562                 : 
    2563                 : BEGIN_CASE(JSOP_THIS)
    2564         7519302 :     if (!ComputeThis(cx, regs.fp()))
    2565               0 :         goto error;
    2566         7519302 :     PUSH_COPY(regs.fp()->thisValue());
    2567         7519302 : END_CASE(JSOP_THIS)
    2568                 : 
    2569                 : BEGIN_CASE(JSOP_GETPROP)
    2570                 : BEGIN_CASE(JSOP_GETXPROP)
    2571                 : BEGIN_CASE(JSOP_LENGTH)
    2572                 : BEGIN_CASE(JSOP_CALLPROP)
    2573                 : {
    2574                 :     Value rval;
    2575        64309689 :     if (!GetPropertyOperation(cx, regs.pc, regs.sp[-1], &rval))
    2576             192 :         goto error;
    2577                 : 
    2578        64309497 :     TypeScript::Monitor(cx, script, regs.pc, rval);
    2579                 : 
    2580        64309497 :     regs.sp[-1] = rval;
    2581        64309497 :     assertSameCompartment(cx, regs.sp[-1]);
    2582                 : }
    2583        64309497 : END_CASE(JSOP_GETPROP)
    2584                 : 
    2585                 : BEGIN_CASE(JSOP_SETGNAME)
    2586                 : BEGIN_CASE(JSOP_SETNAME)
    2587                 : BEGIN_CASE(JSOP_SETPROP)
    2588                 : {
    2589        16138244 :     const Value &rval = regs.sp[-1];
    2590        16138244 :     const Value &lval = regs.sp[-2];
    2591                 : 
    2592        16138244 :     if (!SetPropertyOperation(cx, regs.pc, lval, rval))
    2593             192 :         goto error;
    2594                 : 
    2595        16138052 :     regs.sp[-2] = regs.sp[-1];
    2596        16138052 :     regs.sp--;
    2597                 : }
    2598        16138052 : END_CASE(JSOP_SETPROP)
    2599                 : 
    2600                 : BEGIN_CASE(JSOP_GETELEM)
    2601                 : BEGIN_CASE(JSOP_CALLELEM)
    2602                 : {
    2603        27002084 :     Value &lref = regs.sp[-2];
    2604        27002084 :     Value &rref = regs.sp[-1];
    2605        27002084 :     if (!GetElementOperation(cx, op, lref, rref, &regs.sp[-2]))
    2606              45 :         goto error;
    2607        27002039 :     TypeScript::Monitor(cx, script, regs.pc, regs.sp[-2]);
    2608        27002039 :     regs.sp--;
    2609                 : }
    2610        27002039 : END_CASE(JSOP_GETELEM)
    2611                 : 
    2612                 : BEGIN_CASE(JSOP_SETELEM)
    2613                 : {
    2614                 :     JSObject *obj;
    2615        11318797 :     FETCH_OBJECT(cx, -3, obj);
    2616                 :     jsid id;
    2617        11318786 :     FETCH_ELEMENT_ID(obj, -2, id);
    2618        11318786 :     Value &value = regs.sp[-1];
    2619        11318786 :     if (!SetObjectElementOperation(cx, obj, id, value, script->strictModeCode))
    2620             731 :         goto error;
    2621        11318055 :     regs.sp[-3] = value;
    2622        11318055 :     regs.sp -= 2;
    2623                 : }
    2624        11318055 : END_CASE(JSOP_SETELEM)
    2625                 : 
    2626                 : BEGIN_CASE(JSOP_ENUMELEM)
    2627                 : {
    2628                 :     /* Funky: the value to set is under the [obj, id] pair. */
    2629                 :     JSObject *obj;
    2630            4496 :     FETCH_OBJECT(cx, -2, obj);
    2631                 :     jsid id;
    2632            4496 :     FETCH_ELEMENT_ID(obj, -1, id);
    2633            4496 :     Value rval = regs.sp[-3];
    2634            4496 :     if (!obj->setGeneric(cx, id, &rval, script->strictModeCode))
    2635               0 :         goto error;
    2636            4496 :     regs.sp -= 3;
    2637                 : }
    2638            4496 : END_CASE(JSOP_ENUMELEM)
    2639                 : 
    2640                 : BEGIN_CASE(JSOP_EVAL)
    2641                 : {
    2642           22161 :     CallArgs args = CallArgsFromSp(GET_ARGC(regs.pc), regs.sp);
    2643           22161 :     if (IsBuiltinEvalForScope(&regs.fp()->scopeChain(), args.calleev())) {
    2644           22140 :         if (!DirectEval(cx, args))
    2645             319 :             goto error;
    2646                 :     } else {
    2647              21 :         if (!InvokeKernel(cx, args))
    2648               0 :             goto error;
    2649                 :     }
    2650           21842 :     CHECK_INTERRUPT_HANDLER();
    2651           21842 :     regs.sp = args.spAfterCall();
    2652           21842 :     TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
    2653                 : }
    2654           21842 : END_CASE(JSOP_EVAL)
    2655                 : 
    2656                 : BEGIN_CASE(JSOP_FUNAPPLY)
    2657          194748 :     if (regs.sp[-1].isMagic(JS_OPTIMIZED_ARGUMENTS)) {
    2658          144066 :         CallArgs args = CallArgsFromSp(GET_ARGC(regs.pc), regs.sp);
    2659          144066 :         if (!IsNativeFunction(args.calleev(), js_fun_apply)) {
    2660               6 :             JS_ASSERT(args.length() == 2);
    2661               6 :             if (!script->applySpeculationFailed(cx))
    2662               0 :                 goto error;
    2663               6 :             args[1] = ObjectValue(regs.fp()->argsObj());
    2664                 :         }
    2665                 :     }
    2666                 :     /* FALL THROUGH */
    2667                 : 
    2668                 : BEGIN_CASE(JSOP_NEW)
    2669                 : BEGIN_CASE(JSOP_CALL)
    2670                 : BEGIN_CASE(JSOP_FUNCALL)
    2671                 : {
    2672        15638603 :     CallArgs args = CallArgsFromSp(GET_ARGC(regs.pc), regs.sp);
    2673        15638603 :     JS_ASSERT(args.base() >= regs.fp()->base());
    2674                 : 
    2675        15638603 :     bool construct = (*regs.pc == JSOP_NEW);
    2676                 : 
    2677                 :     JSFunction *fun;
    2678                 : 
    2679                 :     /* Don't bother trying to fast-path calls to scripted non-constructors. */
    2680        15638603 :     if (!IsFunctionObject(args.calleev(), &fun) || !fun->isInterpretedConstructor()) {
    2681         6336259 :         if (construct) {
    2682          125396 :             if (!InvokeConstructorKernel(cx, args))
    2683             567 :                 goto error;
    2684                 :         } else {
    2685         6210863 :             if (!InvokeKernel(cx, args))
    2686            9554 :                 goto error;
    2687                 :         }
    2688         6326138 :         Value *newsp = args.spAfterCall();
    2689         6326138 :         TypeScript::Monitor(cx, script, regs.pc, newsp[-1]);
    2690         6326138 :         regs.sp = newsp;
    2691         6326138 :         CHECK_INTERRUPT_HANDLER();
    2692         6326138 :         len = JSOP_CALL_LENGTH;
    2693         6326138 :         DO_NEXT_OP(len);
    2694                 :     }
    2695                 : 
    2696         9302344 :     TypeMonitorCall(cx, args, construct);
    2697                 : 
    2698         9302344 :     InitialFrameFlags initial = construct ? INITIAL_CONSTRUCT : INITIAL_NONE;
    2699                 : 
    2700         9302344 :     JSScript *newScript = fun->script();
    2701                 : 
    2702         9302344 :     if (newScript->compileAndGo && newScript->hasClearedGlobal()) {
    2703               0 :         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CLEARED_SCOPE);
    2704               0 :         goto error;
    2705                 :     }
    2706                 : 
    2707         9302344 :     if (!cx->stack.pushInlineFrame(cx, regs, args, *fun, newScript, initial))
    2708              52 :         goto error;
    2709                 : 
    2710         9302292 :     RESTORE_INTERP_VARS();
    2711                 : 
    2712         9302292 :     if (!regs.fp()->functionPrologue(cx))
    2713               0 :         goto error;
    2714                 : 
    2715         9302292 :     RESET_USE_METHODJIT();
    2716                 : 
    2717         9302292 :     bool newType = cx->typeInferenceEnabled() && UseNewType(cx, script, regs.pc);
    2718                 : 
    2719                 : #ifdef JS_METHODJIT
    2720         9302292 :     if (!newType) {
    2721                 :         /* Try to ensure methods are method JIT'd.  */
    2722                 :         mjit::CompileRequest request = (interpMode == JSINTERP_NORMAL)
    2723                 :                                        ? mjit::CompileRequest_Interpreter
    2724         9302292 :                                        : mjit::CompileRequest_JIT;
    2725                 :         mjit::CompileStatus status = mjit::CanMethodJIT(cx, script, script->code,
    2726         9302292 :                                                         construct, request);
    2727         9302292 :         if (status == mjit::Compile_Error)
    2728               0 :             goto error;
    2729         9302292 :         if (status == mjit::Compile_Okay) {
    2730          101099 :             mjit::JaegerStatus status = mjit::JaegerShot(cx, true);
    2731          101099 :             CHECK_PARTIAL_METHODJIT(status);
    2732           89576 :             interpReturnOK = mjit::JaegerStatusToSuccess(status);
    2733           89576 :             CHECK_INTERRUPT_HANDLER();
    2734           89576 :             goto jit_return;
    2735                 :         }
    2736                 :     }
    2737                 : #endif
    2738                 : 
    2739         9201193 :     if (!ScriptPrologue(cx, regs.fp(), newType))
    2740               0 :         goto error;
    2741                 : 
    2742         9201193 :     if (cx->compartment->debugMode()) {
    2743          552894 :         switch (ScriptDebugPrologue(cx, regs.fp())) {
    2744                 :           case JSTRAP_CONTINUE:
    2745                 :             break;
    2746                 :           case JSTRAP_RETURN:
    2747              15 :             interpReturnOK = true;
    2748              15 :             goto forced_return;
    2749                 :           case JSTRAP_THROW:
    2750                 :           case JSTRAP_ERROR:
    2751               5 :             goto error;
    2752                 :           default:
    2753               0 :             JS_NOT_REACHED("bad ScriptDebugPrologue status");
    2754                 :         }
    2755                 :     }
    2756                 : 
    2757         9201173 :     CHECK_INTERRUPT_HANDLER();
    2758                 : 
    2759                 :     /* Load first op and dispatch it (safe since JSOP_STOP). */
    2760         9201173 :     op = (JSOp) *regs.pc;
    2761         9201173 :     DO_OP();
    2762                 : }
    2763                 : 
    2764                 : BEGIN_CASE(JSOP_SETCALL)
    2765                 : {
    2766               9 :     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_LEFTSIDE_OF_ASS);
    2767               9 :     goto error;
    2768                 : }
    2769                 : END_CASE(JSOP_SETCALL)
    2770                 : 
    2771                 : BEGIN_CASE(JSOP_IMPLICITTHIS)
    2772                 : {
    2773                 :     PropertyName *name;
    2774           96449 :     LOAD_NAME(0, name);
    2775                 : 
    2776                 :     JSObject *obj, *obj2;
    2777                 :     JSProperty *prop;
    2778           96449 :     if (!FindPropertyHelper(cx, name, false, cx->stack.currentScriptedScopeChain(), &obj, &obj2, &prop))
    2779               0 :         goto error;
    2780                 : 
    2781                 :     Value v;
    2782           96449 :     if (!ComputeImplicitThis(cx, obj, &v))
    2783               0 :         goto error;
    2784           96449 :     PUSH_COPY(v);
    2785                 : }
    2786           96449 : END_CASE(JSOP_IMPLICITTHIS)
    2787                 : 
    2788                 : BEGIN_CASE(JSOP_GETGNAME)
    2789                 : BEGIN_CASE(JSOP_CALLGNAME)
    2790                 : BEGIN_CASE(JSOP_NAME)
    2791                 : BEGIN_CASE(JSOP_CALLNAME)
    2792                 : {
    2793                 :     Value rval;
    2794        37179564 :     if (!NameOperation(cx, regs.pc, &rval))
    2795            1353 :         goto error;
    2796                 : 
    2797        37178211 :     PUSH_COPY(rval);
    2798        37178211 :     TypeScript::Monitor(cx, script, regs.pc, rval);
    2799                 : }
    2800        37178211 : END_CASE(JSOP_NAME)
    2801                 : 
    2802                 : BEGIN_CASE(JSOP_UINT16)
    2803        15007573 :     PUSH_INT32((int32_t) GET_UINT16(regs.pc));
    2804        15007573 : END_CASE(JSOP_UINT16)
    2805                 : 
    2806                 : BEGIN_CASE(JSOP_UINT24)
    2807         2664115 :     PUSH_INT32((int32_t) GET_UINT24(regs.pc));
    2808         2664115 : END_CASE(JSOP_UINT24)
    2809                 : 
    2810                 : BEGIN_CASE(JSOP_INT8)
    2811        38767849 :     PUSH_INT32(GET_INT8(regs.pc));
    2812        38767849 : END_CASE(JSOP_INT8)
    2813                 : 
    2814                 : BEGIN_CASE(JSOP_INT32)
    2815         4615743 :     PUSH_INT32(GET_INT32(regs.pc));
    2816         4615743 : END_CASE(JSOP_INT32)
    2817                 : 
    2818                 : BEGIN_CASE(JSOP_DOUBLE)
    2819                 : {
    2820                 :     double dbl;
    2821         1376969 :     LOAD_DOUBLE(0, dbl);
    2822         1376969 :     PUSH_DOUBLE(dbl);
    2823                 : }
    2824         1376969 : END_CASE(JSOP_DOUBLE)
    2825                 : 
    2826                 : BEGIN_CASE(JSOP_STRING)
    2827                 : {
    2828                 :     JSAtom *atom;
    2829         5661363 :     LOAD_ATOM(0, atom);
    2830         5661363 :     PUSH_STRING(atom);
    2831                 : }
    2832         5661363 : END_CASE(JSOP_STRING)
    2833                 : 
    2834                 : BEGIN_CASE(JSOP_OBJECT)
    2835                 : {
    2836            3699 :     PUSH_OBJECT(*script->getObject(GET_UINT32_INDEX(regs.pc)));
    2837                 : }
    2838            3699 : END_CASE(JSOP_OBJECT)
    2839                 : 
    2840                 : BEGIN_CASE(JSOP_REGEXP)
    2841                 : {
    2842                 :     /*
    2843                 :      * Push a regexp object cloned from the regexp literal object mapped by the
    2844                 :      * bytecode at pc.
    2845                 :      */
    2846           89249 :     uint32_t index = GET_UINT32_INDEX(regs.pc);
    2847           89249 :     JSObject *proto = regs.fp()->scopeChain().global().getOrCreateRegExpPrototype(cx);
    2848           89249 :     if (!proto)
    2849               0 :         goto error;
    2850           89249 :     JSObject *obj = CloneRegExpObject(cx, script->getRegExp(index), proto);
    2851           89249 :     if (!obj)
    2852               0 :         goto error;
    2853           89249 :     PUSH_OBJECT(*obj);
    2854                 : }
    2855           89249 : END_CASE(JSOP_REGEXP)
    2856                 : 
    2857                 : BEGIN_CASE(JSOP_ZERO)
    2858        13163782 :     PUSH_INT32(0);
    2859        13163782 : END_CASE(JSOP_ZERO)
    2860                 : 
    2861                 : BEGIN_CASE(JSOP_ONE)
    2862        16313937 :     PUSH_INT32(1);
    2863        16313937 : END_CASE(JSOP_ONE)
    2864                 : 
    2865                 : BEGIN_CASE(JSOP_NULL)
    2866         2427785 :     PUSH_NULL();
    2867         2427785 : END_CASE(JSOP_NULL)
    2868                 : 
    2869                 : BEGIN_CASE(JSOP_FALSE)
    2870         1806003 :     PUSH_BOOLEAN(false);
    2871         1806003 : END_CASE(JSOP_FALSE)
    2872                 : 
    2873                 : BEGIN_CASE(JSOP_TRUE)
    2874         1786313 :     PUSH_BOOLEAN(true);
    2875         1786313 : END_CASE(JSOP_TRUE)
    2876                 : 
    2877                 : {
    2878                 : BEGIN_CASE(JSOP_TABLESWITCH)
    2879                 : {
    2880            2081 :     jsbytecode *pc2 = regs.pc;
    2881            2081 :     len = GET_JUMP_OFFSET(pc2);
    2882                 : 
    2883                 :     /*
    2884                 :      * ECMAv2+ forbids conversion of discriminant, so we will skip to the
    2885                 :      * default case if the discriminant isn't already an int jsval.  (This
    2886                 :      * opcode is emitted only for dense int-domain switches.)
    2887                 :      */
    2888            2081 :     const Value &rref = *--regs.sp;
    2889                 :     int32_t i;
    2890            2081 :     if (rref.isInt32()) {
    2891            1564 :         i = rref.toInt32();
    2892                 :     } else {
    2893                 :         double d;
    2894                 :         /* Don't use JSDOUBLE_IS_INT32; treat -0 (double) as 0. */
    2895             517 :         if (!rref.isDouble() || (d = rref.toDouble()) != (i = int32_t(rref.toDouble())))
    2896             477 :             DO_NEXT_OP(len);
    2897                 :     }
    2898                 : 
    2899            1604 :     pc2 += JUMP_OFFSET_LEN;
    2900            1604 :     int32_t low = GET_JUMP_OFFSET(pc2);
    2901            1604 :     pc2 += JUMP_OFFSET_LEN;
    2902            1604 :     int32_t high = GET_JUMP_OFFSET(pc2);
    2903                 : 
    2904            1604 :     i -= low;
    2905            1604 :     if ((uint32_t)i < (uint32_t)(high - low + 1)) {
    2906            1031 :         pc2 += JUMP_OFFSET_LEN + JUMP_OFFSET_LEN * i;
    2907            1031 :         int32_t off = (int32_t) GET_JUMP_OFFSET(pc2);
    2908            1031 :         if (off)
    2909            1021 :             len = off;
    2910                 :     }
    2911                 : }
    2912            1604 : END_VARLEN_CASE
    2913                 : }
    2914                 : 
    2915                 : {
    2916                 : BEGIN_CASE(JSOP_LOOKUPSWITCH)
    2917                 : {
    2918                 :     int32_t off;
    2919             980 :     off = JUMP_OFFSET_LEN;
    2920                 : 
    2921                 :     /*
    2922                 :      * JSOP_LOOKUPSWITCH are never used if any atom index in it would exceed
    2923                 :      * 64K limit.
    2924                 :      */
    2925             980 :     JS_ASSERT(atoms == script->atoms);
    2926             980 :     jsbytecode *pc2 = regs.pc;
    2927                 : 
    2928             980 :     Value lval = regs.sp[-1];
    2929             980 :     regs.sp--;
    2930                 : 
    2931                 :     int npairs;
    2932             980 :     if (!lval.isPrimitive())
    2933               0 :         goto end_lookup_switch;
    2934                 : 
    2935             980 :     pc2 += off;
    2936             980 :     npairs = GET_UINT16(pc2);
    2937             980 :     pc2 += UINT16_LEN;
    2938             980 :     JS_ASSERT(npairs);  /* empty switch uses JSOP_TABLESWITCH */
    2939                 : 
    2940                 :     bool match;
    2941                 : #define SEARCH_PAIRS(MATCH_CODE)                                              \
    2942                 :     for (;;) {                                                                \
    2943                 :         Value rval = script->getConst(GET_UINT32_INDEX(pc2));                 \
    2944                 :         MATCH_CODE                                                            \
    2945                 :         pc2 += UINT32_INDEX_LEN;                                              \
    2946                 :         if (match)                                                            \
    2947                 :             break;                                                            \
    2948                 :         pc2 += off;                                                           \
    2949                 :         if (--npairs == 0) {                                                  \
    2950                 :             pc2 = regs.pc;                                                    \
    2951                 :             break;                                                            \
    2952                 :         }                                                                     \
    2953                 :     }
    2954                 : 
    2955             980 :     if (lval.isString()) {
    2956             741 :         JSLinearString *str = lval.toString()->ensureLinear(cx);
    2957             741 :         if (!str)
    2958               0 :             goto error;
    2959                 :         JSLinearString *str2;
    2960            3453 :         SEARCH_PAIRS(
    2961                 :             match = (rval.isString() &&
    2962                 :                      ((str2 = &rval.toString()->asLinear()) == str ||
    2963                 :                       EqualStrings(str2, str)));
    2964                 :         )
    2965             239 :     } else if (lval.isNumber()) {
    2966              18 :         double ldbl = lval.toNumber();
    2967              54 :         SEARCH_PAIRS(
    2968                 :             match = rval.isNumber() && ldbl == rval.toNumber();
    2969                 :         )
    2970                 :     } else {
    2971             221 :         SEARCH_PAIRS(
    2972                 :             match = (lval == rval);
    2973                 :         )
    2974                 :     }
    2975                 : #undef SEARCH_PAIRS
    2976                 : 
    2977                 :   end_lookup_switch:
    2978             980 :     len = GET_JUMP_OFFSET(pc2);
    2979                 : }
    2980             980 : END_VARLEN_CASE
    2981                 : }
    2982                 : 
    2983                 : BEGIN_CASE(JSOP_ARGUMENTS)
    2984          229988 :     if (script->needsArgsObj())
    2985           28505 :         PUSH_COPY(ObjectValue(regs.fp()->argsObj()));
    2986                 :     else
    2987          201483 :         PUSH_COPY(MagicValue(JS_OPTIMIZED_ARGUMENTS));
    2988          229988 : END_CASE(JSOP_ARGUMENTS)
    2989                 : 
    2990                 : BEGIN_CASE(JSOP_GETARG)
    2991                 : BEGIN_CASE(JSOP_CALLARG)
    2992        51247084 :     PUSH_COPY(regs.fp()->formalArg(GET_ARGNO(regs.pc)));
    2993        51247084 : END_CASE(JSOP_GETARG)
    2994                 : 
    2995                 : BEGIN_CASE(JSOP_SETARG)
    2996         5106320 :     regs.fp()->formalArg(GET_ARGNO(regs.pc)) = regs.sp[-1];
    2997         5106320 : END_CASE(JSOP_SETARG)
    2998                 : 
    2999                 : BEGIN_CASE(JSOP_GETLOCAL)
    3000                 : BEGIN_CASE(JSOP_CALLLOCAL)
    3001       444562781 :     PUSH_COPY_SKIP_CHECK(regs.fp()->localSlot(GET_SLOTNO(regs.pc)));
    3002                 : 
    3003                 :     /*
    3004                 :      * Skip the same-compartment assertion if the local will be immediately
    3005                 :      * popped. We do not guarantee sync for dead locals when coming in from the
    3006                 :      * method JIT, and a GETLOCAL followed by POP is not considered to be
    3007                 :      * a use of the variable.
    3008                 :      */
    3009       444562781 :     if (regs.pc[JSOP_GETLOCAL_LENGTH] != JSOP_POP)
    3010       440454470 :         assertSameCompartment(cx, regs.sp[-1]);
    3011       444562781 : END_CASE(JSOP_GETLOCAL)
    3012                 : 
    3013                 : BEGIN_CASE(JSOP_SETLOCAL)
    3014        40921262 :     regs.fp()->localSlot(GET_SLOTNO(regs.pc)) = regs.sp[-1];
    3015        40921262 : END_CASE(JSOP_SETLOCAL)
    3016                 : 
    3017                 : BEGIN_CASE(JSOP_DEFCONST)
    3018                 : BEGIN_CASE(JSOP_DEFVAR)
    3019                 : {
    3020           32687 :     PropertyName *dn = atoms[GET_UINT32_INDEX(regs.pc)]->asPropertyName();
    3021                 : 
    3022                 :     /* ES5 10.5 step 8 (with subsequent errata). */
    3023           32687 :     unsigned attrs = JSPROP_ENUMERATE;
    3024           32687 :     if (!regs.fp()->isEvalFrame())
    3025           31658 :         attrs |= JSPROP_PERMANENT;
    3026           32687 :     if (op == JSOP_DEFCONST)
    3027           31048 :         attrs |= JSPROP_READONLY;
    3028                 : 
    3029                 :     /* Step 8b. */
    3030           32687 :     JSObject &obj = regs.fp()->varObj();
    3031                 : 
    3032           32687 :     if (!DefVarOrConstOperation(cx, obj, dn, attrs))
    3033               0 :         goto error;
    3034                 : }
    3035           32687 : END_CASE(JSOP_DEFVAR)
    3036                 : 
    3037                 : BEGIN_CASE(JSOP_DEFFUN)
    3038                 : {
    3039                 :     /*
    3040                 :      * A top-level function defined in Global or Eval code (see ECMA-262
    3041                 :      * Ed. 3), or else a SpiderMonkey extension: a named function statement in
    3042                 :      * a compound statement (not at the top statement level of global code, or
    3043                 :      * at the top level of a function body).
    3044                 :      */
    3045            2247 :     JSFunction *fun = script->getFunction(GET_UINT32_INDEX(regs.pc));
    3046            2247 :     JSObject *obj = fun;
    3047                 : 
    3048                 :     JSObject *obj2;
    3049            2247 :     if (fun->isNullClosure()) {
    3050                 :         /*
    3051                 :          * Even a null closure needs a parent for principals finding.
    3052                 :          * FIXME: bug 476950, although debugger users may also demand some kind
    3053                 :          * of scope link for debugger-assisted eval-in-frame.
    3054                 :          */
    3055            1167 :         obj2 = &regs.fp()->scopeChain();
    3056                 :     } else {
    3057            1080 :         obj2 = GetScopeChain(cx, regs.fp());
    3058            1080 :         if (!obj2)
    3059               0 :             goto error;
    3060                 :     }
    3061                 : 
    3062                 :     /*
    3063                 :      * If static link is not current scope, clone fun's object to link to the
    3064                 :      * current scope via parent. We do this to enable sharing of compiled
    3065                 :      * functions among multiple equivalent scopes, amortizing the cost of
    3066                 :      * compilation over a number of executions.  Examples include XUL scripts
    3067                 :      * and event handlers shared among Firefox or other Mozilla app chrome
    3068                 :      * windows, and user-defined JS functions precompiled and then shared among
    3069                 :      * requests in server-side JS.
    3070                 :      */
    3071            2247 :     if (obj->toFunction()->environment() != obj2) {
    3072             365 :         obj = CloneFunctionObjectIfNotSingleton(cx, fun, obj2);
    3073             365 :         if (!obj)
    3074               0 :             goto error;
    3075             365 :         JS_ASSERT_IF(script->hasGlobal(), obj->getProto() == fun->getProto());
    3076                 :     }
    3077                 : 
    3078                 :     /*
    3079                 :      * ECMA requires functions defined when entering Eval code to be
    3080                 :      * impermanent.
    3081                 :      */
    3082            2247 :     unsigned attrs = regs.fp()->isEvalFrame()
    3083                 :                   ? JSPROP_ENUMERATE
    3084            2247 :                   : JSPROP_ENUMERATE | JSPROP_PERMANENT;
    3085                 : 
    3086                 :     /*
    3087                 :      * We define the function as a property of the variable object and not the
    3088                 :      * current scope chain even for the case of function expression statements
    3089                 :      * and functions defined by eval inside let or with blocks.
    3090                 :      */
    3091            2247 :     JSObject *parent = &regs.fp()->varObj();
    3092                 : 
    3093                 :     /* ES5 10.5 (NB: with subsequent errata). */
    3094            2247 :     PropertyName *name = fun->atom->asPropertyName();
    3095            2247 :     JSProperty *prop = NULL;
    3096                 :     JSObject *pobj;
    3097            2247 :     if (!parent->lookupProperty(cx, name, &pobj, &prop))
    3098               0 :         goto error;
    3099                 : 
    3100            2247 :     Value rval = ObjectValue(*obj);
    3101                 : 
    3102                 :     do {
    3103                 :         /* Steps 5d, 5f. */
    3104            2247 :         if (!prop || pobj != parent) {
    3105            1472 :             if (!parent->defineProperty(cx, name, rval,
    3106            1472 :                                         JS_PropertyStub, JS_StrictPropertyStub, attrs))
    3107                 :             {
    3108               0 :                 goto error;
    3109                 :             }
    3110            1472 :             break;
    3111                 :         }
    3112                 : 
    3113                 :         /* Step 5e. */
    3114             775 :         JS_ASSERT(parent->isNative());
    3115             775 :         Shape *shape = reinterpret_cast<Shape *>(prop);
    3116             775 :         if (parent->isGlobal()) {
    3117             610 :             if (shape->configurable()) {
    3118             167 :                 if (!parent->defineProperty(cx, name, rval,
    3119             167 :                                             JS_PropertyStub, JS_StrictPropertyStub, attrs))
    3120                 :                 {
    3121               0 :                     goto error;
    3122                 :                 }
    3123             167 :                 break;
    3124                 :             }
    3125                 : 
    3126             443 :             if (shape->isAccessorDescriptor() || !shape->writable() || !shape->enumerable()) {
    3127              10 :                 JSAutoByteString bytes;
    3128               5 :                 if (js_AtomToPrintableString(cx, name, &bytes)) {
    3129                 :                     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
    3130               5 :                                          JSMSG_CANT_REDEFINE_PROP, bytes.ptr());
    3131                 :                 }
    3132                 :                 goto error;
    3133                 :             }
    3134                 :         }
    3135                 : 
    3136                 :         /*
    3137                 :          * Non-global properties, and global properties which we aren't simply
    3138                 :          * redefining, must be set.  First, this preserves their attributes.
    3139                 :          * Second, this will produce warnings and/or errors as necessary if the
    3140                 :          * specified Call object property is not writable (const).
    3141                 :          */
    3142                 : 
    3143                 :         /* Step 5f. */
    3144             603 :         if (!parent->setProperty(cx, name, &rval, script->strictModeCode))
    3145               0 :             goto error;
    3146                 :     } while (false);
    3147                 : }
    3148            2242 : END_CASE(JSOP_DEFFUN)
    3149                 : 
    3150                 : BEGIN_CASE(JSOP_LAMBDA)
    3151                 : {
    3152                 :     /* Load the specified function object literal. */
    3153          258584 :     JSFunction *fun = script->getFunction(GET_UINT32_INDEX(regs.pc));
    3154          258584 :     JSObject *obj = fun;
    3155                 : 
    3156                 :     /* do-while(0) so we can break instead of using a goto. */
    3157                 :     do {
    3158                 :         JSObject *parent;
    3159          258584 :         if (fun->isNullClosure()) {
    3160           86130 :             parent = &regs.fp()->scopeChain();
    3161                 :         } else {
    3162          172454 :             parent = GetScopeChain(cx, regs.fp());
    3163          172454 :             if (!parent)
    3164               0 :                 goto error;
    3165                 :         }
    3166                 : 
    3167          258584 :         obj = CloneFunctionObjectIfNotSingleton(cx, fun, parent);
    3168          258584 :         if (!obj)
    3169               0 :             goto error;
    3170                 :     } while (0);
    3171                 : 
    3172          258584 :     JS_ASSERT(obj->getProto());
    3173          258584 :     JS_ASSERT_IF(script->hasGlobal(), obj->getProto() == fun->getProto());
    3174                 : 
    3175          258584 :     PUSH_OBJECT(*obj);
    3176                 : }
    3177          258584 : END_CASE(JSOP_LAMBDA)
    3178                 : 
    3179                 : BEGIN_CASE(JSOP_CALLEE)
    3180         1297382 :     JS_ASSERT(regs.fp()->isNonEvalFunctionFrame());
    3181         1297382 :     PUSH_COPY(argv[-2]);
    3182         1297382 : END_CASE(JSOP_CALLEE)
    3183                 : 
    3184                 : BEGIN_CASE(JSOP_GETTER)
    3185                 : BEGIN_CASE(JSOP_SETTER)
    3186                 : {
    3187             297 :     JSOp op2 = JSOp(*++regs.pc);
    3188                 :     jsid id;
    3189                 :     Value rval;
    3190                 :     int i;
    3191                 :     JSObject *obj;
    3192             297 :     switch (op2) {
    3193                 :       case JSOP_SETNAME:
    3194                 :       case JSOP_SETPROP:
    3195                 :       {
    3196                 :         PropertyName *name;
    3197               0 :         LOAD_NAME(0, name);
    3198               0 :         id = ATOM_TO_JSID(name);
    3199               0 :         rval = regs.sp[-1];
    3200               0 :         i = -1;
    3201               0 :         goto gs_pop_lval;
    3202                 :       }
    3203                 :       case JSOP_SETELEM:
    3204               0 :         rval = regs.sp[-1];
    3205               0 :         id = JSID_VOID;
    3206               0 :         i = -2;
    3207                 :       gs_pop_lval:
    3208               0 :         FETCH_OBJECT(cx, i - 1, obj);
    3209               0 :         break;
    3210                 : 
    3211                 :       case JSOP_INITPROP:
    3212                 :       {
    3213             297 :         JS_ASSERT(regs.sp - regs.fp()->base() >= 2);
    3214             297 :         rval = regs.sp[-1];
    3215             297 :         i = -1;
    3216                 :         PropertyName *name;
    3217             297 :         LOAD_NAME(0, name);
    3218             297 :         id = ATOM_TO_JSID(name);
    3219             297 :         goto gs_get_lval;
    3220                 :       }
    3221                 :       default:
    3222               0 :         JS_ASSERT(op2 == JSOP_INITELEM);
    3223                 : 
    3224               0 :         JS_ASSERT(regs.sp - regs.fp()->base() >= 3);
    3225               0 :         rval = regs.sp[-1];
    3226               0 :         id = JSID_VOID;
    3227               0 :         i = -2;
    3228                 :       gs_get_lval:
    3229                 :       {
    3230             297 :         const Value &lref = regs.sp[i-1];
    3231             297 :         JS_ASSERT(lref.isObject());
    3232             297 :         obj = &lref.toObject();
    3233             297 :         break;
    3234                 :       }
    3235                 :     }
    3236                 : 
    3237                 :     /* Ensure that id has a type suitable for use with obj. */
    3238             297 :     if (JSID_IS_VOID(id))
    3239               0 :         FETCH_ELEMENT_ID(obj, i, id);
    3240                 : 
    3241             297 :     if (!js_IsCallable(rval)) {
    3242                 :         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_GETTER_OR_SETTER,
    3243               0 :                              (op == JSOP_GETTER) ? js_getter_str : js_setter_str);
    3244               0 :         goto error;
    3245                 :     }
    3246                 : 
    3247                 :     /*
    3248                 :      * Getters and setters are just like watchpoints from an access control
    3249                 :      * point of view.
    3250                 :      */
    3251                 :     Value rtmp;
    3252                 :     unsigned attrs;
    3253             297 :     if (!CheckAccess(cx, obj, id, JSACC_WATCH, &rtmp, &attrs))
    3254               0 :         goto error;
    3255                 : 
    3256                 :     PropertyOp getter;
    3257                 :     StrictPropertyOp setter;
    3258             297 :     if (op == JSOP_GETTER) {
    3259             207 :         getter = CastAsPropertyOp(&rval.toObject());
    3260             207 :         setter = JS_StrictPropertyStub;
    3261             207 :         attrs = JSPROP_GETTER;
    3262                 :     } else {
    3263              90 :         getter = JS_PropertyStub;
    3264              90 :         setter = CastAsStrictPropertyOp(&rval.toObject());
    3265              90 :         attrs = JSPROP_SETTER;
    3266                 :     }
    3267             297 :     attrs |= JSPROP_ENUMERATE | JSPROP_SHARED;
    3268                 : 
    3269             297 :     if (!obj->defineGeneric(cx, id, UndefinedValue(), getter, setter, attrs))
    3270               0 :         goto error;
    3271                 : 
    3272             297 :     regs.sp += i;
    3273             297 :     if (js_CodeSpec[op2].ndefs > js_CodeSpec[op2].nuses) {
    3274               0 :         JS_ASSERT(js_CodeSpec[op2].ndefs == js_CodeSpec[op2].nuses + 1);
    3275               0 :         regs.sp[-1] = rval;
    3276               0 :         assertSameCompartment(cx, regs.sp[-1]);
    3277                 :     }
    3278             297 :     len = js_CodeSpec[op2].length;
    3279             297 :     DO_NEXT_OP(len);
    3280                 : }
    3281                 : 
    3282                 : BEGIN_CASE(JSOP_HOLE)
    3283            4764 :     PUSH_HOLE();
    3284            4764 : END_CASE(JSOP_HOLE)
    3285                 : 
    3286                 : BEGIN_CASE(JSOP_NEWINIT)
    3287                 : {
    3288            1626 :     uint8_t i = GET_UINT8(regs.pc);
    3289            1626 :     JS_ASSERT(i == JSProto_Array || i == JSProto_Object);
    3290                 : 
    3291                 :     JSObject *obj;
    3292            1626 :     if (i == JSProto_Array) {
    3293             324 :         obj = NewDenseEmptyArray(cx);
    3294                 :     } else {
    3295            1302 :         gc::AllocKind kind = GuessObjectGCKind(0);
    3296            1302 :         obj = NewBuiltinClassInstance(cx, &ObjectClass, kind);
    3297                 :     }
    3298            1626 :     if (!obj || !SetInitializerObjectType(cx, script, regs.pc, obj))
    3299               0 :         goto error;
    3300                 : 
    3301            1626 :     PUSH_OBJECT(*obj);
    3302            1626 :     CHECK_INTERRUPT_HANDLER();
    3303                 : }
    3304            1626 : END_CASE(JSOP_NEWINIT)
    3305                 : 
    3306                 : BEGIN_CASE(JSOP_NEWARRAY)
    3307                 : {
    3308          809319 :     unsigned count = GET_UINT24(regs.pc);
    3309          809319 :     JSObject *obj = NewDenseAllocatedArray(cx, count);
    3310          809319 :     if (!obj || !SetInitializerObjectType(cx, script, regs.pc, obj))
    3311               0 :         goto error;
    3312                 : 
    3313          809319 :     PUSH_OBJECT(*obj);
    3314          809319 :     CHECK_INTERRUPT_HANDLER();
    3315                 : }
    3316          809319 : END_CASE(JSOP_NEWARRAY)
    3317                 : 
    3318                 : BEGIN_CASE(JSOP_NEWOBJECT)
    3319                 : {
    3320         1059353 :     JSObject *baseobj = script->getObject(GET_UINT32_INDEX(regs.pc));
    3321                 : 
    3322         1059353 :     JSObject *obj = CopyInitializerObject(cx, baseobj);
    3323         1059353 :     if (!obj || !SetInitializerObjectType(cx, script, regs.pc, obj))
    3324               1 :         goto error;
    3325                 : 
    3326         1059352 :     PUSH_OBJECT(*obj);
    3327         1059352 :     CHECK_INTERRUPT_HANDLER();
    3328                 : }
    3329         1059352 : END_CASE(JSOP_NEWOBJECT)
    3330                 : 
    3331                 : BEGIN_CASE(JSOP_ENDINIT)
    3332                 : {
    3333                 :     /* FIXME remove JSOP_ENDINIT bug 588522 */
    3334         1807081 :     JS_ASSERT(regs.sp - regs.fp()->base() >= 1);
    3335         1807081 :     JS_ASSERT(regs.sp[-1].isObject());
    3336                 : }
    3337         1807081 : END_CASE(JSOP_ENDINIT)
    3338                 : 
    3339                 : BEGIN_CASE(JSOP_INITPROP)
    3340                 : {
    3341                 :     /* Load the property's initial value into rval. */
    3342         2075074 :     JS_ASSERT(regs.sp - regs.fp()->base() >= 2);
    3343         2075074 :     Value rval = regs.sp[-1];
    3344                 : 
    3345                 :     /* Load the object being initialized into lval/obj. */
    3346         2075074 :     JSObject *obj = &regs.sp[-2].toObject();
    3347         2075074 :     JS_ASSERT(obj->isObject());
    3348                 : 
    3349                 :     JSAtom *atom;
    3350         2075074 :     LOAD_ATOM(0, atom);
    3351         2075074 :     jsid id = ATOM_TO_JSID(atom);
    3352                 : 
    3353         4150148 :     if (JS_UNLIKELY(atom == cx->runtime->atomState.protoAtom)
    3354              74 :         ? !js_SetPropertyHelper(cx, obj, id, 0, &rval, script->strictModeCode)
    3355                 :         : !DefineNativeProperty(cx, obj, id, rval, NULL, NULL,
    3356         2075000 :                                 JSPROP_ENUMERATE, 0, 0, 0)) {
    3357               0 :         goto error;
    3358                 :     }
    3359                 : 
    3360         2075074 :     regs.sp--;
    3361                 : }
    3362         2075074 : END_CASE(JSOP_INITPROP);
    3363                 : 
    3364                 : BEGIN_CASE(JSOP_INITELEM)
    3365                 : {
    3366                 :     /* Pop the element's value into rval. */
    3367         5794866 :     JS_ASSERT(regs.sp - regs.fp()->base() >= 3);
    3368         5794866 :     const Value &rref = regs.sp[-1];
    3369                 : 
    3370                 :     /* Find the object being initialized at top of stack. */
    3371         5794866 :     const Value &lref = regs.sp[-3];
    3372         5794866 :     JS_ASSERT(lref.isObject());
    3373         5794866 :     JSObject *obj = &lref.toObject();
    3374                 : 
    3375                 :     /* Fetch id now that we have obj. */
    3376                 :     jsid id;
    3377         5794866 :     FETCH_ELEMENT_ID(obj, -2, id);
    3378                 : 
    3379                 :     /*
    3380                 :      * If rref is a hole, do not call JSObject::defineProperty. In this case,
    3381                 :      * obj must be an array, so if the current op is the last element
    3382                 :      * initialiser, set the array length to one greater than id.
    3383                 :      */
    3384         5794866 :     if (rref.isMagic(JS_ARRAY_HOLE)) {
    3385            4764 :         JS_ASSERT(obj->isArray());
    3386            4764 :         JS_ASSERT(JSID_IS_INT(id));
    3387            4764 :         JS_ASSERT(uint32_t(JSID_TO_INT(id)) < StackSpace::ARGS_LENGTH_MAX);
    3388            5162 :         if (JSOp(regs.pc[JSOP_INITELEM_LENGTH]) == JSOP_ENDINIT &&
    3389             398 :             !js_SetLengthProperty(cx, obj, (uint32_t) (JSID_TO_INT(id) + 1))) {
    3390               0 :             goto error;
    3391                 :         }
    3392                 :     } else {
    3393         5790102 :         if (!obj->defineGeneric(cx, id, rref, NULL, NULL, JSPROP_ENUMERATE))
    3394               0 :             goto error;
    3395                 :     }
    3396         5794866 :     regs.sp -= 2;
    3397                 : }
    3398         5794866 : END_CASE(JSOP_INITELEM)
    3399                 : 
    3400                 : {
    3401                 : BEGIN_CASE(JSOP_GOSUB)
    3402              54 :     PUSH_BOOLEAN(false);
    3403              54 :     int32_t i = (regs.pc - script->code) + JSOP_GOSUB_LENGTH;
    3404              54 :     len = GET_JUMP_OFFSET(regs.pc);
    3405              54 :     PUSH_INT32(i);
    3406              54 : END_VARLEN_CASE
    3407                 : }
    3408                 : 
    3409                 : {
    3410                 : BEGIN_CASE(JSOP_RETSUB)
    3411                 :     /* Pop [exception or hole, retsub pc-index]. */
    3412                 :     Value rval, lval;
    3413            1443 :     POP_COPY_TO(rval);
    3414            1443 :     POP_COPY_TO(lval);
    3415            1443 :     JS_ASSERT(lval.isBoolean());
    3416            1443 :     if (lval.toBoolean()) {
    3417                 :         /*
    3418                 :          * Exception was pending during finally, throw it *before* we adjust
    3419                 :          * pc, because pc indexes into script->trynotes.  This turns out not to
    3420                 :          * be necessary, but it seems clearer.  And it points out a FIXME:
    3421                 :          * 350509, due to Igor Bukanov.
    3422                 :          */
    3423            1407 :         cx->setPendingException(rval);
    3424            1407 :         goto error;
    3425                 :     }
    3426              36 :     JS_ASSERT(rval.isInt32());
    3427              36 :     len = rval.toInt32();
    3428              36 :     regs.pc = script->code;
    3429              36 : END_VARLEN_CASE
    3430                 : }
    3431                 : 
    3432                 : BEGIN_CASE(JSOP_EXCEPTION)
    3433            8316 :     PUSH_COPY(cx->getPendingException());
    3434            8316 :     cx->clearPendingException();
    3435            8316 :     CHECK_BRANCH();
    3436            8316 : END_CASE(JSOP_EXCEPTION)
    3437                 : 
    3438                 : BEGIN_CASE(JSOP_FINALLY)
    3439            1479 :     CHECK_BRANCH();
    3440            1479 : END_CASE(JSOP_FINALLY)
    3441                 : 
    3442                 : BEGIN_CASE(JSOP_THROWING)
    3443                 : {
    3444               0 :     JS_ASSERT(!cx->isExceptionPending());
    3445                 :     Value v;
    3446               0 :     POP_COPY_TO(v);
    3447               0 :     cx->setPendingException(v);
    3448                 : }
    3449               0 : END_CASE(JSOP_THROWING)
    3450                 : 
    3451                 : BEGIN_CASE(JSOP_THROW)
    3452                 : {
    3453             820 :     JS_ASSERT(!cx->isExceptionPending());
    3454             820 :     CHECK_BRANCH();
    3455                 :     Value v;
    3456             820 :     POP_COPY_TO(v);
    3457             820 :     cx->setPendingException(v);
    3458                 :     /* let the code at error try to catch the exception. */
    3459             820 :     goto error;
    3460                 : }
    3461                 : 
    3462                 : BEGIN_CASE(JSOP_INSTANCEOF)
    3463                 : {
    3464         1009919 :     const Value &rref = regs.sp[-1];
    3465         1009919 :     if (rref.isPrimitive()) {
    3466               0 :         js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS, -1, rref, NULL);
    3467               0 :         goto error;
    3468                 :     }
    3469         1009919 :     JSObject *obj = &rref.toObject();
    3470         1009919 :     const Value &lref = regs.sp[-2];
    3471         1009919 :     JSBool cond = JS_FALSE;
    3472         1009919 :     if (!HasInstance(cx, obj, &lref, &cond))
    3473              19 :         goto error;
    3474         1009900 :     regs.sp--;
    3475         1009900 :     regs.sp[-1].setBoolean(cond);
    3476                 : }
    3477         1009900 : END_CASE(JSOP_INSTANCEOF)
    3478                 : 
    3479                 : BEGIN_CASE(JSOP_DEBUGGER)
    3480                 : {
    3481            4830 :     JSTrapStatus st = JSTRAP_CONTINUE;
    3482                 :     Value rval;
    3483            4830 :     if (JSDebuggerHandler handler = cx->runtime->debugHooks.debuggerHandler)
    3484              10 :         st = handler(cx, script, regs.pc, &rval, cx->runtime->debugHooks.debuggerHandlerData);
    3485            4830 :     if (st == JSTRAP_CONTINUE)
    3486            4825 :         st = Debugger::onDebuggerStatement(cx, &rval);
    3487            4830 :     switch (st) {
    3488                 :       case JSTRAP_ERROR:
    3489             118 :         goto error;
    3490                 :       case JSTRAP_CONTINUE:
    3491            4488 :         break;
    3492                 :       case JSTRAP_RETURN:
    3493             149 :         regs.fp()->setReturnValue(rval);
    3494             149 :         interpReturnOK = true;
    3495             149 :         goto forced_return;
    3496                 :       case JSTRAP_THROW:
    3497              75 :         cx->setPendingException(rval);
    3498              75 :         goto error;
    3499                 :       default:;
    3500                 :     }
    3501            4488 :     CHECK_INTERRUPT_HANDLER();
    3502                 : }
    3503            4488 : END_CASE(JSOP_DEBUGGER)
    3504                 : 
    3505                 : #if JS_HAS_XML_SUPPORT
    3506                 : BEGIN_CASE(JSOP_DEFXMLNS)
    3507                 : {
    3508               9 :     JS_ASSERT(!script->strictModeCode);
    3509                 : 
    3510               9 :     if (!js_SetDefaultXMLNamespace(cx, regs.sp[-1]))
    3511               0 :         goto error;
    3512               9 :     regs.sp--;
    3513                 : }
    3514               9 : END_CASE(JSOP_DEFXMLNS)
    3515                 : 
    3516                 : BEGIN_CASE(JSOP_ANYNAME)
    3517                 : {
    3518              18 :     JS_ASSERT(!script->strictModeCode);
    3519                 : 
    3520                 :     jsid id;
    3521              18 :     if (!js_GetAnyName(cx, &id))
    3522               0 :         goto error;
    3523              18 :     PUSH_COPY(IdToValue(id));
    3524                 : }
    3525              18 : END_CASE(JSOP_ANYNAME)
    3526                 : 
    3527                 : BEGIN_CASE(JSOP_QNAMEPART)
    3528                 : {
    3529                 :     /*
    3530                 :      * We do not JS_ASSERT(!script->strictModeCode) here because JSOP_QNAMEPART
    3531                 :      * is used for __proto__ and (in contexts where we favor JSOP_*ELEM instead
    3532                 :      * of JSOP_*PROP) obj.prop compiled as obj['prop'].
    3533                 :      */
    3534                 : 
    3535                 :     JSAtom *atom;
    3536            5585 :     LOAD_ATOM(0, atom);
    3537            5585 :     PUSH_STRING(atom);
    3538                 : }
    3539            5585 : END_CASE(JSOP_QNAMEPART)
    3540                 : 
    3541                 : BEGIN_CASE(JSOP_QNAMECONST)
    3542                 : {
    3543              45 :     JS_ASSERT(!script->strictModeCode);
    3544                 : 
    3545                 :     JSAtom *atom;
    3546              45 :     LOAD_ATOM(0, atom);
    3547              45 :     Value rval = StringValue(atom);
    3548              45 :     Value lval = regs.sp[-1];
    3549              45 :     JSObject *obj = js_ConstructXMLQNameObject(cx, lval, rval);
    3550              45 :     if (!obj)
    3551               0 :         goto error;
    3552              45 :     regs.sp[-1].setObject(*obj);
    3553                 : }
    3554              45 : END_CASE(JSOP_QNAMECONST)
    3555                 : 
    3556                 : BEGIN_CASE(JSOP_QNAME)
    3557                 : {
    3558               0 :     JS_ASSERT(!script->strictModeCode);
    3559                 : 
    3560               0 :     Value rval = regs.sp[-1];
    3561               0 :     Value lval = regs.sp[-2];
    3562               0 :     JSObject *obj = js_ConstructXMLQNameObject(cx, lval, rval);
    3563               0 :     if (!obj)
    3564               0 :         goto error;
    3565               0 :     regs.sp--;
    3566               0 :     regs.sp[-1].setObject(*obj);
    3567                 : }
    3568               0 : END_CASE(JSOP_QNAME)
    3569                 : 
    3570                 : BEGIN_CASE(JSOP_TOATTRNAME)
    3571                 : {
    3572               0 :     JS_ASSERT(!script->strictModeCode);
    3573                 : 
    3574                 :     Value rval;
    3575               0 :     rval = regs.sp[-1];
    3576               0 :     if (!js_ToAttributeName(cx, &rval))
    3577               0 :         goto error;
    3578               0 :     regs.sp[-1] = rval;
    3579                 : }
    3580               0 : END_CASE(JSOP_TOATTRNAME)
    3581                 : 
    3582                 : BEGIN_CASE(JSOP_TOATTRVAL)
    3583                 : {
    3584               0 :     JS_ASSERT(!script->strictModeCode);
    3585                 : 
    3586                 :     Value rval;
    3587               0 :     rval = regs.sp[-1];
    3588               0 :     JS_ASSERT(rval.isString());
    3589               0 :     JSString *str = js_EscapeAttributeValue(cx, rval.toString(), JS_FALSE);
    3590               0 :     if (!str)
    3591               0 :         goto error;
    3592               0 :     regs.sp[-1].setString(str);
    3593                 : }
    3594               0 : END_CASE(JSOP_TOATTRVAL)
    3595                 : 
    3596                 : BEGIN_CASE(JSOP_ADDATTRNAME)
    3597                 : BEGIN_CASE(JSOP_ADDATTRVAL)
    3598                 : {
    3599               0 :     JS_ASSERT(!script->strictModeCode);
    3600                 : 
    3601               0 :     Value rval = regs.sp[-1];
    3602               0 :     Value lval = regs.sp[-2];
    3603               0 :     JSString *str = lval.toString();
    3604               0 :     JSString *str2 = rval.toString();
    3605               0 :     str = js_AddAttributePart(cx, op == JSOP_ADDATTRNAME, str, str2);
    3606               0 :     if (!str)
    3607               0 :         goto error;
    3608               0 :     regs.sp--;
    3609               0 :     regs.sp[-1].setString(str);
    3610                 : }
    3611               0 : END_CASE(JSOP_ADDATTRNAME)
    3612                 : 
    3613                 : BEGIN_CASE(JSOP_BINDXMLNAME)
    3614                 : {
    3615              18 :     JS_ASSERT(!script->strictModeCode);
    3616                 : 
    3617                 :     Value lval;
    3618              18 :     lval = regs.sp[-1];
    3619                 :     JSObject *obj;
    3620                 :     jsid id;
    3621              18 :     if (!js_FindXMLProperty(cx, lval, &obj, &id))
    3622               0 :         goto error;
    3623              18 :     regs.sp[-1].setObjectOrNull(obj);
    3624              18 :     PUSH_COPY(IdToValue(id));
    3625                 : }
    3626              18 : END_CASE(JSOP_BINDXMLNAME)
    3627                 : 
    3628                 : BEGIN_CASE(JSOP_SETXMLNAME)
    3629                 : {
    3630              18 :     JS_ASSERT(!script->strictModeCode);
    3631                 : 
    3632              18 :     JSObject *obj = &regs.sp[-3].toObject();
    3633              18 :     Value rval = regs.sp[-1];
    3634                 :     jsid id;
    3635              18 :     FETCH_ELEMENT_ID(obj, -2, id);
    3636              18 :     if (!obj->setGeneric(cx, id, &rval, script->strictModeCode))
    3637               0 :         goto error;
    3638              18 :     rval = regs.sp[-1];
    3639              18 :     regs.sp -= 2;
    3640              18 :     regs.sp[-1] = rval;
    3641                 : }
    3642              18 : END_CASE(JSOP_SETXMLNAME)
    3643                 : 
    3644                 : BEGIN_CASE(JSOP_CALLXMLNAME)
    3645                 : BEGIN_CASE(JSOP_XMLNAME)
    3646                 : {
    3647              36 :     JS_ASSERT(!script->strictModeCode);
    3648                 : 
    3649              36 :     Value lval = regs.sp[-1];
    3650                 :     JSObject *obj;
    3651                 :     jsid id;
    3652              36 :     if (!js_FindXMLProperty(cx, lval, &obj, &id))
    3653              27 :         goto error;
    3654                 :     Value rval;
    3655               9 :     if (!obj->getGeneric(cx, id, &rval))
    3656               0 :         goto error;
    3657               9 :     regs.sp[-1] = rval;
    3658               9 :     if (op == JSOP_CALLXMLNAME) {
    3659                 :         Value v;
    3660               0 :         if (!ComputeImplicitThis(cx, obj, &v))
    3661               0 :             goto error;
    3662               0 :         PUSH_COPY(v);
    3663                 :     }
    3664                 : }
    3665               9 : END_CASE(JSOP_XMLNAME)
    3666                 : 
    3667                 : BEGIN_CASE(JSOP_DESCENDANTS)
    3668                 : BEGIN_CASE(JSOP_DELDESC)
    3669                 : {
    3670               9 :     JS_ASSERT(!script->strictModeCode);
    3671                 : 
    3672                 :     JSObject *obj;
    3673               9 :     FETCH_OBJECT(cx, -2, obj);
    3674               9 :     jsval rval = regs.sp[-1];
    3675               9 :     if (!js_GetXMLDescendants(cx, obj, rval, &rval))
    3676               0 :         goto error;
    3677                 : 
    3678               9 :     if (op == JSOP_DELDESC) {
    3679               0 :         regs.sp[-1] = rval;   /* set local root */
    3680               0 :         if (!js_DeleteXMLListElements(cx, JSVAL_TO_OBJECT(rval)))
    3681               0 :             goto error;
    3682               0 :         rval = JSVAL_TRUE;                  /* always succeed */
    3683                 :     }
    3684                 : 
    3685               9 :     regs.sp--;
    3686               9 :     regs.sp[-1] = rval;
    3687                 : }
    3688               9 : END_CASE(JSOP_DESCENDANTS)
    3689                 : 
    3690                 : BEGIN_CASE(JSOP_FILTER)
    3691                 : {
    3692              63 :     JS_ASSERT(!script->strictModeCode);
    3693                 : 
    3694                 :     /*
    3695                 :      * We push the hole value before jumping to [enditer] so we can detect the
    3696                 :      * first iteration and direct js_StepXMLListFilter to initialize filter's
    3697                 :      * state.
    3698                 :      */
    3699              63 :     PUSH_HOLE();
    3700              63 :     len = GET_JUMP_OFFSET(regs.pc);
    3701              63 :     JS_ASSERT(len > 0);
    3702                 : }
    3703              63 : END_VARLEN_CASE
    3704                 : 
    3705                 : BEGIN_CASE(JSOP_ENDFILTER)
    3706                 : {
    3707             126 :     JS_ASSERT(!script->strictModeCode);
    3708                 : 
    3709             126 :     bool cond = !regs.sp[-1].isMagic();
    3710             126 :     if (cond) {
    3711                 :         /* Exit the "with" block left from the previous iteration. */
    3712              63 :         LeaveWith(cx);
    3713                 :     }
    3714             126 :     if (!js_StepXMLListFilter(cx, cond))
    3715               9 :         goto error;
    3716             117 :     if (!regs.sp[-1].isNull()) {
    3717                 :         /*
    3718                 :          * Decrease sp after EnterWith returns as we use sp[-1] there to root
    3719                 :          * temporaries.
    3720                 :          */
    3721              63 :         JS_ASSERT(IsXML(regs.sp[-1]));
    3722              63 :         if (!EnterWith(cx, -2))
    3723               0 :             goto error;
    3724              63 :         regs.sp--;
    3725              63 :         len = GET_JUMP_OFFSET(regs.pc);
    3726              63 :         JS_ASSERT(len < 0);
    3727              63 :         BRANCH(len);
    3728                 :     }
    3729              54 :     regs.sp--;
    3730                 : }
    3731              54 : END_CASE(JSOP_ENDFILTER);
    3732                 : 
    3733                 : BEGIN_CASE(JSOP_TOXML)
    3734                 : {
    3735             595 :     JS_ASSERT(!script->strictModeCode);
    3736                 : 
    3737             595 :     Value rval = regs.sp[-1];
    3738             595 :     JSObject *obj = js_ValueToXMLObject(cx, rval);
    3739             595 :     if (!obj)
    3740               0 :         goto error;
    3741             595 :     regs.sp[-1].setObject(*obj);
    3742                 : }
    3743             595 : END_CASE(JSOP_TOXML)
    3744                 : 
    3745                 : BEGIN_CASE(JSOP_TOXMLLIST)
    3746                 : {
    3747              18 :     JS_ASSERT(!script->strictModeCode);
    3748                 : 
    3749              18 :     Value rval = regs.sp[-1];
    3750              18 :     JSObject *obj = js_ValueToXMLListObject(cx, rval);
    3751              18 :     if (!obj)
    3752               0 :         goto error;
    3753              18 :     regs.sp[-1].setObject(*obj);
    3754                 : }
    3755              18 : END_CASE(JSOP_TOXMLLIST)
    3756                 : 
    3757                 : BEGIN_CASE(JSOP_XMLTAGEXPR)
    3758                 : {
    3759               0 :     JS_ASSERT(!script->strictModeCode);
    3760                 : 
    3761               0 :     Value rval = regs.sp[-1];
    3762               0 :     JSString *str = ToString(cx, rval);
    3763               0 :     if (!str)
    3764               0 :         goto error;
    3765               0 :     regs.sp[-1].setString(str);
    3766                 : }
    3767               0 : END_CASE(JSOP_XMLTAGEXPR)
    3768                 : 
    3769                 : BEGIN_CASE(JSOP_XMLELTEXPR)
    3770                 : {
    3771               0 :     JS_ASSERT(!script->strictModeCode);
    3772                 : 
    3773               0 :     Value rval = regs.sp[-1];
    3774                 :     JSString *str;
    3775               0 :     if (IsXML(rval)) {
    3776               0 :         str = js_ValueToXMLString(cx, rval);
    3777                 :     } else {
    3778               0 :         str = ToString(cx, rval);
    3779               0 :         if (str)
    3780               0 :             str = js_EscapeElementValue(cx, str);
    3781                 :     }
    3782               0 :     if (!str)
    3783               0 :         goto error;
    3784               0 :     regs.sp[-1].setString(str);
    3785                 : }
    3786               0 : END_CASE(JSOP_XMLELTEXPR)
    3787                 : 
    3788                 : BEGIN_CASE(JSOP_XMLCDATA)
    3789                 : {
    3790               0 :     JS_ASSERT(!script->strictModeCode);
    3791                 : 
    3792               0 :     JSAtom *atom = script->getAtom(GET_UINT32_INDEX(regs.pc));
    3793               0 :     JSObject *obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_TEXT, NULL, atom);
    3794               0 :     if (!obj)
    3795               0 :         goto error;
    3796               0 :     PUSH_OBJECT(*obj);
    3797                 : }
    3798               0 : END_CASE(JSOP_XMLCDATA)
    3799                 : 
    3800                 : BEGIN_CASE(JSOP_XMLCOMMENT)
    3801                 : {
    3802               0 :     JS_ASSERT(!script->strictModeCode);
    3803                 : 
    3804               0 :     JSAtom *atom = script->getAtom(GET_UINT32_INDEX(regs.pc));
    3805               0 :     JSObject *obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_COMMENT, NULL, atom);
    3806               0 :     if (!obj)
    3807               0 :         goto error;
    3808               0 :     PUSH_OBJECT(*obj);
    3809                 : }
    3810               0 : END_CASE(JSOP_XMLCOMMENT)
    3811                 : 
    3812                 : BEGIN_CASE(JSOP_XMLPI)
    3813                 : {
    3814               0 :     JS_ASSERT(!script->strictModeCode);
    3815                 : 
    3816               0 :     JSAtom *atom = script->getAtom(GET_UINT32_INDEX(regs.pc));
    3817               0 :     Value rval = regs.sp[-1];
    3818               0 :     JSString *str2 = rval.toString();
    3819               0 :     JSObject *obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_PROCESSING_INSTRUCTION, atom, str2);
    3820               0 :     if (!obj)
    3821               0 :         goto error;
    3822               0 :     regs.sp[-1].setObject(*obj);
    3823                 : }
    3824               0 : END_CASE(JSOP_XMLPI)
    3825                 : 
    3826                 : BEGIN_CASE(JSOP_GETFUNNS)
    3827                 : {
    3828              36 :     JS_ASSERT(!script->strictModeCode);
    3829                 : 
    3830                 :     Value rval;
    3831              36 :     if (!cx->fp()->scopeChain().global().getFunctionNamespace(cx, &rval))
    3832               0 :         goto error;
    3833              36 :     PUSH_COPY(rval);
    3834                 : }
    3835              36 : END_CASE(JSOP_GETFUNNS)
    3836                 : #endif /* JS_HAS_XML_SUPPORT */
    3837                 : 
    3838                 : BEGIN_CASE(JSOP_ENTERBLOCK)
    3839                 : BEGIN_CASE(JSOP_ENTERLET0)
    3840                 : BEGIN_CASE(JSOP_ENTERLET1)
    3841                 : {
    3842           25078 :     StaticBlockObject &blockObj = script->getObject(GET_UINT32_INDEX(regs.pc))->asStaticBlock();
    3843           25078 :     JS_ASSERT(regs.fp()->maybeBlockChain() == blockObj.enclosingBlock());
    3844                 : 
    3845           25078 :     if (op == JSOP_ENTERBLOCK) {
    3846           17929 :         JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() == regs.sp);
    3847           17929 :         Value *vp = regs.sp + blockObj.slotCount();
    3848           17929 :         JS_ASSERT(regs.sp < vp);
    3849           17929 :         JS_ASSERT(vp <= regs.fp()->slots() + script->nslots);
    3850           17929 :         SetValueRangeToUndefined(regs.sp, vp);
    3851           17929 :         regs.sp = vp;
    3852            7149 :     } else if (op == JSOP_ENTERLET0) {
    3853            5074 :         JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() + blockObj.slotCount()
    3854            5074 :                   == regs.sp);
    3855            2075 :     } else if (op == JSOP_ENTERLET1) {
    3856            2075 :         JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() + blockObj.slotCount()
    3857            2075 :                   == regs.sp - 1);
    3858                 :     }
    3859                 : 
    3860                 : #ifdef DEBUG
    3861           25078 :     JS_ASSERT(regs.fp()->maybeBlockChain() == blockObj.enclosingBlock());
    3862                 : 
    3863                 :     /*
    3864                 :      * The young end of fp->scopeChain may omit blocks if we haven't closed
    3865                 :      * over them, but if there are any closure blocks on fp->scopeChain, they'd
    3866                 :      * better be (clones of) ancestors of the block we're entering now;
    3867                 :      * anything else we should have popped off fp->scopeChain when we left its
    3868                 :      * static scope.
    3869                 :      */
    3870           25078 :     JSObject *obj2 = &regs.fp()->scopeChain();
    3871           50318 :     while (obj2->isWith())
    3872             162 :         obj2 = &obj2->asWith().enclosingScope();
    3873           25948 :     if (obj2->isBlock() &&
    3874             870 :         obj2->getPrivate() == js_FloatingFrameIfGenerator(cx, regs.fp()))
    3875                 :     {
    3876             270 :         StaticBlockObject &youngestProto = obj2->asClonedBlock().staticBlock();
    3877             270 :         StaticBlockObject *parent = &blockObj;
    3878             540 :         while ((parent = parent->enclosingBlock()) != &youngestProto)
    3879               0 :             JS_ASSERT(parent);
    3880                 :     }
    3881                 : #endif
    3882                 : 
    3883           25078 :     regs.fp()->setBlockChain(&blockObj);
    3884                 : }
    3885           25078 : END_CASE(JSOP_ENTERBLOCK)
    3886                 : 
    3887                 : BEGIN_CASE(JSOP_LEAVEBLOCK)
    3888                 : BEGIN_CASE(JSOP_LEAVEFORLETIN)
    3889                 : BEGIN_CASE(JSOP_LEAVEBLOCKEXPR)
    3890                 : {
    3891           28182 :     StaticBlockObject &blockObj = regs.fp()->blockChain();
    3892           28182 :     JS_ASSERT(blockObj.stackDepth() <= StackDepth(script));
    3893                 : 
    3894                 :     /*
    3895                 :      * If we're about to leave the dynamic scope of a block that has been
    3896                 :      * cloned onto fp->scopeChain, clear its private data, move its locals from
    3897                 :      * the stack into the clone, and pop it off the chain.
    3898                 :      */
    3899           28182 :     JSObject &scope = regs.fp()->scopeChain();
    3900           28182 :     if (scope.getProto() == &blockObj)
    3901            1594 :         scope.asClonedBlock().put(cx);
    3902                 : 
    3903           28182 :     regs.fp()->setBlockChain(blockObj.enclosingBlock());
    3904                 : 
    3905           28182 :     if (op == JSOP_LEAVEBLOCK) {
    3906                 :         /* Pop the block's slots. */
    3907           25364 :         regs.sp -= GET_UINT16(regs.pc);
    3908           25364 :         JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() == regs.sp);
    3909            2818 :     } else if (op == JSOP_LEAVEBLOCKEXPR) {
    3910                 :         /* Pop the block's slots maintaining the topmost expr. */
    3911             829 :         Value *vp = &regs.sp[-1];
    3912             829 :         regs.sp -= GET_UINT16(regs.pc);
    3913             829 :         JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() == regs.sp - 1);
    3914             829 :         regs.sp[-1] = *vp;
    3915                 :     } else {
    3916                 :         /* Another op will pop; nothing to do here. */
    3917            1989 :         len = JSOP_LEAVEFORLETIN_LENGTH;
    3918            1989 :         DO_NEXT_OP(len);
    3919                 :     }
    3920                 : }
    3921           26193 : END_CASE(JSOP_LEAVEBLOCK)
    3922                 : 
    3923                 : #if JS_HAS_GENERATORS
    3924                 : BEGIN_CASE(JSOP_GENERATOR)
    3925                 : {
    3926            8222 :     JS_ASSERT(!cx->isExceptionPending());
    3927            8222 :     regs.pc += JSOP_GENERATOR_LENGTH;
    3928            8222 :     JSObject *obj = js_NewGenerator(cx);
    3929            8222 :     if (!obj)
    3930               0 :         goto error;
    3931            8222 :     regs.fp()->setReturnValue(ObjectValue(*obj));
    3932            8222 :     interpReturnOK = true;
    3933            8222 :     if (entryFrame != regs.fp())
    3934            6044 :         goto inline_return;
    3935            2178 :     goto exit;
    3936                 : }
    3937                 : 
    3938                 : BEGIN_CASE(JSOP_YIELD)
    3939           15426 :     JS_ASSERT(!cx->isExceptionPending());
    3940           15426 :     JS_ASSERT(regs.fp()->isNonEvalFunctionFrame());
    3941           15426 :     if (cx->generatorFor(regs.fp())->state == JSGEN_CLOSING) {
    3942               0 :         js_ReportValueError(cx, JSMSG_BAD_GENERATOR_YIELD,
    3943               0 :                             JSDVG_SEARCH_STACK, argv[-2], NULL);
    3944               0 :         goto error;
    3945                 :     }
    3946           15426 :     regs.fp()->setReturnValue(regs.sp[-1]);
    3947           15426 :     regs.fp()->setYielding();
    3948           15426 :     regs.pc += JSOP_YIELD_LENGTH;
    3949           15426 :     interpReturnOK = true;
    3950           15426 :     goto exit;
    3951                 : 
    3952                 : BEGIN_CASE(JSOP_ARRAYPUSH)
    3953                 : {
    3954            4680 :     uint32_t slot = GET_UINT16(regs.pc);
    3955            4680 :     JS_ASSERT(script->nfixed <= slot);
    3956            4680 :     JS_ASSERT(slot < script->nslots);
    3957            4680 :     JSObject *obj = &regs.fp()->slots()[slot].toObject();
    3958            4680 :     if (!js_NewbornArrayPush(cx, obj, regs.sp[-1]))
    3959               0 :         goto error;
    3960            4680 :     regs.sp--;
    3961                 : }
    3962            4680 : END_CASE(JSOP_ARRAYPUSH)
    3963                 : #endif /* JS_HAS_GENERATORS */
    3964                 : 
    3965                 : #if JS_THREADED_INTERP
    3966                 :   L_JSOP_BACKPATCH:
    3967                 :   L_JSOP_BACKPATCH_POP:
    3968                 : 
    3969                 : # if !JS_HAS_GENERATORS
    3970                 :   L_JSOP_GENERATOR:
    3971                 :   L_JSOP_YIELD:
    3972                 :   L_JSOP_ARRAYPUSH:
    3973                 : # endif
    3974                 : 
    3975                 : # if !JS_HAS_DESTRUCTURING
    3976                 :   L_JSOP_ENUMCONSTELEM:
    3977                 : # endif
    3978                 : 
    3979                 : # if !JS_HAS_XML_SUPPORT
    3980                 :   L_JSOP_CALLXMLNAME:
    3981                 :   L_JSOP_STARTXMLEXPR:
    3982                 :   L_JSOP_STARTXML:
    3983                 :   L_JSOP_DELDESC:
    3984                 :   L_JSOP_GETFUNNS:
    3985                 :   L_JSOP_XMLPI:
    3986                 :   L_JSOP_XMLCOMMENT:
    3987                 :   L_JSOP_XMLCDATA:
    3988                 :   L_JSOP_XMLELTEXPR:
    3989                 :   L_JSOP_XMLTAGEXPR:
    3990                 :   L_JSOP_TOXMLLIST:
    3991                 :   L_JSOP_TOXML:
    3992                 :   L_JSOP_ENDFILTER:
    3993                 :   L_JSOP_FILTER:
    3994                 :   L_JSOP_DESCENDANTS:
    3995                 :   L_JSOP_XMLNAME:
    3996                 :   L_JSOP_SETXMLNAME:
    3997                 :   L_JSOP_BINDXMLNAME:
    3998                 :   L_JSOP_ADDATTRVAL:
    3999                 :   L_JSOP_ADDATTRNAME:
    4000                 :   L_JSOP_TOATTRVAL:
    4001                 :   L_JSOP_TOATTRNAME:
    4002                 :   L_JSOP_QNAME:
    4003                 :   L_JSOP_QNAMECONST:
    4004                 :   L_JSOP_QNAMEPART:
    4005                 :   L_JSOP_ANYNAME:
    4006                 :   L_JSOP_DEFXMLNS:
    4007                 : # endif
    4008                 : 
    4009                 : #endif /* !JS_THREADED_INTERP */
    4010                 : #if !JS_THREADED_INTERP
    4011                 :           default:
    4012                 : #endif
    4013                 :           {
    4014                 :             char numBuf[12];
    4015               0 :             JS_snprintf(numBuf, sizeof numBuf, "%d", op);
    4016                 :             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
    4017               0 :                                  JSMSG_BAD_BYTECODE, numBuf);
    4018               0 :             goto error;
    4019                 :           }
    4020                 : 
    4021                 : #if !JS_THREADED_INTERP
    4022                 :         } /* switch (op) */
    4023                 :     } /* for (;;) */
    4024                 : #endif /* !JS_THREADED_INTERP */
    4025                 : 
    4026                 :   error:
    4027         2015322 :     JS_ASSERT(&cx->regs() == &regs);
    4028         2015322 :     JS_ASSERT(uint32_t(regs.pc - script->code) < script->length);
    4029                 : 
    4030                 :     /* When rejoining, we must not err before finishing Interpret's prologue. */
    4031         2015322 :     JS_ASSERT(interpMode != JSINTERP_REJOIN);
    4032                 : 
    4033         2015322 :     if (cx->isExceptionPending()) {
    4034                 :         /* Restore atoms local in case we will resume. */
    4035         2014512 :         atoms = script->atoms;
    4036                 : 
    4037                 :         /* Call debugger throw hook if set. */
    4038         2014512 :         if (cx->runtime->debugHooks.throwHook || !cx->compartment->getDebuggees().empty()) {
    4039                 :             Value rval;
    4040             718 :             JSTrapStatus st = Debugger::onExceptionUnwind(cx, &rval);
    4041             718 :             if (st == JSTRAP_CONTINUE) {
    4042             683 :                 if (JSThrowHook handler = cx->runtime->debugHooks.throwHook)
    4043              20 :                     st = handler(cx, script, regs.pc, &rval, cx->runtime->debugHooks.throwHookData);
    4044                 :             }
    4045                 : 
    4046             718 :             switch (st) {
    4047                 :               case JSTRAP_ERROR:
    4048              20 :                 cx->clearPendingException();
    4049              20 :                 goto error;
    4050                 :               case JSTRAP_RETURN:
    4051              15 :                 cx->clearPendingException();
    4052              15 :                 regs.fp()->setReturnValue(rval);
    4053              15 :                 interpReturnOK = true;
    4054              15 :                 goto forced_return;
    4055                 :               case JSTRAP_THROW:
    4056               5 :                 cx->setPendingException(rval);
    4057                 :               case JSTRAP_CONTINUE:
    4058                 :               default:;
    4059                 :             }
    4060             683 :             CHECK_INTERRUPT_HANDLER();
    4061                 :         }
    4062                 : 
    4063         2017343 :         for (TryNoteIter tni(regs); !tni.done(); ++tni) {
    4064           12615 :             JSTryNote *tn = *tni;
    4065                 : 
    4066           12615 :             UnwindScope(cx, tn->stackDepth);
    4067                 : 
    4068                 :             /*
    4069                 :              * Set pc to the first bytecode after the the try note to point
    4070                 :              * to the beginning of catch or finally or to [enditer] closing
    4071                 :              * the for-in loop.
    4072                 :              */
    4073           12615 :             regs.pc = (script)->main() + tn->start + tn->length;
    4074           12615 :             regs.sp = regs.fp()->base() + tn->stackDepth;
    4075                 : 
    4076           12615 :             switch (tn->kind) {
    4077                 :               case JSTRY_CATCH:
    4078           11076 :                   JS_ASSERT(*regs.pc == JSOP_ENTERBLOCK);
    4079                 : 
    4080                 : #if JS_HAS_GENERATORS
    4081                 :                 /* Catch cannot intercept the closing of a generator. */
    4082           11076 :                   if (JS_UNLIKELY(cx->getPendingException().isMagic(JS_GENERATOR_CLOSING)))
    4083            2760 :                     break;
    4084                 : #endif
    4085                 : 
    4086                 :                 /*
    4087                 :                  * Don't clear exceptions to save cx->exception from GC
    4088                 :                  * until it is pushed to the stack via [exception] in the
    4089                 :                  * catch block.
    4090                 :                  */
    4091            8316 :                 len = 0;
    4092            8316 :                 DO_NEXT_OP(len);
    4093                 : 
    4094                 :               case JSTRY_FINALLY:
    4095                 :                 /*
    4096                 :                  * Push (true, exception) pair for finally to indicate that
    4097                 :                  * [retsub] should rethrow the exception.
    4098                 :                  */
    4099            1425 :                 PUSH_BOOLEAN(true);
    4100            1425 :                 PUSH_COPY(cx->getPendingException());
    4101            1425 :                 cx->clearPendingException();
    4102            1425 :                 len = 0;
    4103            1425 :                 DO_NEXT_OP(len);
    4104                 : 
    4105                 :               case JSTRY_ITER: {
    4106                 :                 /* This is similar to JSOP_ENDITER in the interpreter loop. */
    4107             114 :                 JS_ASSERT(JSOp(*regs.pc) == JSOP_ENDITER);
    4108             114 :                 bool ok = UnwindIteratorForException(cx, &regs.sp[-1].toObject());
    4109             114 :                 regs.sp -= 1;
    4110             114 :                 if (!ok)
    4111               8 :                     goto error;
    4112                 :               }
    4113                 :            }
    4114                 :         }
    4115                 : 
    4116                 :         /*
    4117                 :          * Propagate the exception or error to the caller unless the exception
    4118                 :          * is an asynchronous return from a generator.
    4119                 :          */
    4120         2004728 :         interpReturnOK = false;
    4121                 : #if JS_HAS_GENERATORS
    4122         2004728 :         if (JS_UNLIKELY(cx->isExceptionPending() &&
    4123                 :                         cx->getPendingException().isMagic(JS_GENERATOR_CLOSING))) {
    4124            1452 :             cx->clearPendingException();
    4125            1452 :             interpReturnOK = true;
    4126            1452 :             regs.fp()->clearReturnValue();
    4127                 :         }
    4128                 : #endif
    4129                 :     } else {
    4130             810 :         UnwindForUncatchableException(cx, regs);
    4131             810 :         interpReturnOK = false;
    4132                 :     }
    4133                 : 
    4134                 :   forced_return:
    4135         2005766 :     UnwindScope(cx, 0);
    4136         2005766 :     regs.sp = regs.fp()->base();
    4137                 : 
    4138         2005766 :     if (entryFrame != regs.fp())
    4139         1995670 :         goto inline_return;
    4140                 : 
    4141                 :   exit:
    4142          517069 :     if (cx->compartment->debugMode())
    4143           50912 :         interpReturnOK = ScriptDebugEpilogue(cx, regs.fp(), interpReturnOK);
    4144          517069 :     interpReturnOK = ScriptEpilogueOrGeneratorYield(cx, regs.fp(), interpReturnOK);
    4145          517069 :     regs.fp()->setFinishedInInterpreter();
    4146                 : 
    4147                 :     /*
    4148                 :      * At this point we are inevitably leaving an interpreted function or a
    4149                 :      * top-level script, and returning to one of:
    4150                 :      * (a) an "out of line" call made through Invoke;
    4151                 :      * (b) a js_Execute activation;
    4152                 :      * (c) a generator (SendToGenerator, jsiter.c).
    4153                 :      *
    4154                 :      * We must not be in an inline frame. The check above ensures that for the
    4155                 :      * error case and for a normal return, the code jumps directly to parent's
    4156                 :      * frame pc.
    4157                 :      */
    4158          517069 :     JS_ASSERT(entryFrame == regs.fp());
    4159          517069 :     if (!regs.fp()->isGeneratorFrame()) {
    4160          497973 :         JS_ASSERT(!IsActiveWithOrBlock(cx, regs.fp()->scopeChain(), 0));
    4161          497973 :         JS_ASSERT(!regs.fp()->hasBlockChain());
    4162                 :     }
    4163                 : 
    4164                 : #ifdef JS_METHODJIT
    4165                 :     /*
    4166                 :      * This path is used when it's guaranteed the method can be finished
    4167                 :      * inside the JIT.
    4168                 :      */
    4169                 :   leave_on_safe_point:
    4170                 : #endif
    4171                 : 
    4172          517775 :     gc::MaybeVerifyBarriers(cx, true);
    4173          517775 :     return interpReturnOK;
    4174                 : }

Generated by: LCOV version 1.7