LCOV - app.info - js/src/jsinterp.cpp

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