LCOV - app.info - js/src/methodjit/StubCalls.cpp

LCOV - code coverage report
| Current view: | directory - js/src/methodjit - StubCalls.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 837 | 687 | 82.1 %
| Date: | 2012-04-07 | Functions: | 94 | 87 | 92.6 %

           1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
           2                 :  * vim: set ts=4 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 SpiderMonkey JavaScript 1.9 code, released
          18                 :  * May 28, 2008.
          19                 :  *
          20                 :  * The Initial Developer of the Original Code is
          21                 :  *   Brendan Eich <brendan@mozilla.org>
          22                 :  *
          23                 :  * Contributor(s):
          24                 :  *   David Anderson <danderson@mozilla.com>
          25                 :  *   David Mandelin <dmandelin@mozilla.com>
          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                 : #include "jscntxt.h"
          42                 : #include "jsscope.h"
          43                 : #include "jsobj.h"
          44                 : #include "jslibmath.h"
          45                 : #include "jsiter.h"
          46                 : #include "jsgcmark.h"
          47                 : #include "jsnum.h"
          48                 : #include "jsxml.h"
          49                 : #include "jsbool.h"
          50                 : #include "assembler/assembler/MacroAssemblerCodeRef.h"
          51                 : #include "jstypes.h"
          52                 : #include "vm/Debugger.h"
          53                 : #include "vm/String.h"
          54                 : #include "methodjit/Compiler.h"
          55                 : #include "methodjit/StubCalls.h"
          56                 : #include "methodjit/Retcon.h"
          57                 :
          58                 : #include "jsinterpinlines.h"
          59                 : #include "jsscopeinlines.h"
          60                 : #include "jsscriptinlines.h"
          61                 : #include "jsnuminlines.h"
          62                 : #include "jsobjinlines.h"
          63                 : #include "jscntxtinlines.h"
          64                 : #include "jsatominlines.h"
          65                 : #include "StubCalls-inl.h"
          66                 : #include "jsfuninlines.h"
          67                 : #include "jstypedarray.h"
          68                 :
          69                 : #include "vm/RegExpObject-inl.h"
          70                 : #include "vm/String-inl.h"
          71                 :
          72                 : #ifdef XP_WIN
          73                 : # include "jswin.h"
          74                 : #endif
          75                 :
          76                 : #include "jsautooplen.h"
          77                 :
          78                 : using namespace js;
          79                 : using namespace js::mjit;
          80                 : using namespace js::types;
          81                 : using namespace JSC;
          82                 :
          83                 : void JS_FASTCALL
          84            1180 : stubs::BindName(VMFrame &f, PropertyName *name)
          85                 : {
          86            1180 :     JSObject *obj = FindIdentifierBase(f.cx, &f.fp()->scopeChain(), name);
          87            1180 :     if (!obj)
          88               0 :         THROW();
          89            1180 :     f.regs.sp[0].setObject(*obj);
          90                 : }
          91                 :
          92                 : JSObject * JS_FASTCALL
          93               0 : stubs::BindGlobalName(VMFrame &f)
          94                 : {
          95               0 :     return &f.fp()->scopeChain().global();
          96                 : }
          97                 :
          98                 : template<JSBool strict>
          99                 : void JS_FASTCALL
         100           76307 : stubs::SetName(VMFrame &f, PropertyName *name)
         101                 : {
         102           76307 :     JSContext *cx = f.cx;
         103           76307 :     const Value &rval = f.regs.sp[-1];
         104           76307 :     const Value &lval = f.regs.sp[-2];
         105                 :
         106           76307 :     if (!SetPropertyOperation(cx, f.pc(), lval, rval))
         107              70 :         THROW();
         108                 :
         109           76237 :     f.regs.sp[-2] = f.regs.sp[-1];
         110                 : }
         111                 :
         112                 : template void JS_FASTCALL stubs::SetName<true>(VMFrame &f, PropertyName *origName);
         113                 : template void JS_FASTCALL stubs::SetName<false>(VMFrame &f, PropertyName *origName);
         114                 :
         115                 : template<JSBool strict>
         116                 : void JS_FASTCALL
         117           47724 : stubs::SetGlobalName(VMFrame &f, PropertyName *name)
         118                 : {
         119           47724 :     SetName<strict>(f, name);
         120           47724 : }
         121                 :
         122                 : template void JS_FASTCALL stubs::SetGlobalName<true>(VMFrame &f, PropertyName *name);
         123                 : template void JS_FASTCALL stubs::SetGlobalName<false>(VMFrame &f, PropertyName *name);
         124                 :
         125                 : void JS_FASTCALL
         126          157575 : stubs::Name(VMFrame &f)
         127                 : {
         128                 :     Value rval;
         129          157575 :     if (!NameOperation(f.cx, f.pc(), &rval))
         130            3298 :         THROW();
         131          154277 :     f.regs.sp[0] = rval;
         132                 : }
         133                 :
         134                 : void JS_FASTCALL
         135          825969 : stubs::GetElem(VMFrame &f)
         136                 : {
         137          825969 :     Value &lref = f.regs.sp[-2];
         138          825969 :     Value &rref = f.regs.sp[-1];
         139          825969 :     Value &rval = f.regs.sp[-2];
         140                 :
         141          825969 :     if (!GetElementOperation(f.cx, JSOp(*f.pc()), lref, rref, &rval))
         142              45 :         THROW();
         143                 : }
         144                 :
         145                 : template<JSBool strict>
         146                 : void JS_FASTCALL
         147         1842887 : stubs::SetElem(VMFrame &f)
         148                 : {
         149         1842887 :     JSContext *cx = f.cx;
         150         1842887 :     FrameRegs &regs = f.regs;
         151                 :
         152         1842887 :     Value &objval = regs.sp[-3];
         153         1842887 :     Value &idval  = regs.sp[-2];
         154         1842887 :     Value rval    = regs.sp[-1];
         155                 :
         156                 :     JSObject *obj;
         157                 :     jsid id;
         158                 :
         159         1842887 :     obj = ValueToObject(cx, objval);
         160         1842887 :     if (!obj)
         161               7 :         THROW();
         162                 :
         163         1842880 :     if (!FetchElementId(f.cx, obj, idval, id, &regs.sp[-2]))
         164               0 :         THROW();
         165                 :
         166         1842880 :     TypeScript::MonitorAssign(cx, obj, id);
         167                 :
         168                 :     do {
         169         1842880 :         if (obj->isDenseArray() && JSID_IS_INT(id)) {
         170         1026676 :             uint32_t length = obj->getDenseArrayInitializedLength();
         171         1026676 :             int32_t i = JSID_TO_INT(id);
         172         1026676 :             if ((uint32_t)i < length) {
         173           19458 :                 if (obj->getDenseArrayElement(i).isMagic(JS_ARRAY_HOLE)) {
         174           19410 :                     if (js_PrototypeHasIndexedProperties(cx, obj))
         175               0 :                         break;
         176           19410 :                     if ((uint32_t)i >= obj->getArrayLength())
         177               0 :                         obj->setArrayLength(cx, i + 1);
         178                 :                 }
         179           19458 :                 obj->setDenseArrayElementWithType(cx, i, rval);
         180           19458 :                 goto end_setelem;
         181                 :             } else {
         182         1007218 :                 if (f.script()->hasAnalysis())
         183         1007218 :                     f.script()->analysis()->getCode(f.pc()).arrayWriteHole = true;
         184                 :             }
         185                 :         }
         186                 :     } while (0);
         187         1823422 :     if (!obj->setGeneric(cx, id, &rval, strict))
         188            2905 :         THROW();
         189                 :   end_setelem:
         190                 :     /* :FIXME: Moving the assigned object into the lowest stack slot
         191                 :      * is a temporary hack. What we actually want is an implementation
         192                 :      * of popAfterSet() that allows popping more than one value;
         193                 :      * this logic can then be handled in Compiler.cpp. */
         194         1839975 :     regs.sp[-3] = regs.sp[-1];
         195                 : }
         196                 :
         197                 : template void JS_FASTCALL stubs::SetElem<true>(VMFrame &f);
         198                 : template void JS_FASTCALL stubs::SetElem<false>(VMFrame &f);
         199                 :
         200                 : void JS_FASTCALL
         201            1126 : stubs::ToId(VMFrame &f)
         202                 : {
         203            1126 :     Value &objval = f.regs.sp[-2];
         204            1126 :     Value &idval  = f.regs.sp[-1];
         205                 :
         206            1126 :     JSObject *obj = ValueToObject(f.cx, objval);
         207            1126 :     if (!obj)
         208               0 :         THROW();
         209                 :
         210                 :     jsid id;
         211            1126 :     if (!FetchElementId(f.cx, obj, idval, id, &idval))
         212               0 :         THROW();
         213                 :
         214            1126 :     if (!idval.isInt32())
         215            1126 :         TypeScript::MonitorUnknown(f.cx, f.script(), f.pc());
         216                 : }
         217                 :
         218                 : void JS_FASTCALL
         219            1024 : stubs::ImplicitThis(VMFrame &f, PropertyName *name)
         220                 : {
         221                 :     JSObject *obj, *obj2;
         222                 :     JSProperty *prop;
         223            1024 :     if (!FindPropertyHelper(f.cx, name, false, f.cx->stack.currentScriptedScopeChain(), &obj, &obj2, &prop))
         224               0 :         THROW();
         225                 :
         226            1024 :     if (!ComputeImplicitThis(f.cx, obj, &f.regs.sp[0]))
         227               0 :         THROW();
         228                 : }
         229                 :
         230                 : void JS_FASTCALL
         231          407742 : stubs::BitOr(VMFrame &f)
         232                 : {
         233                 :     int32_t i, j;
         234                 :
         235          407742 :     if (!ToInt32(f.cx, f.regs.sp[-2], &i) || !ToInt32(f.cx, f.regs.sp[-1], &j))
         236              21 :         THROW();
         237                 :
         238          407721 :     i = i | j;
         239          407721 :     f.regs.sp[-2].setInt32(i);
         240                 : }
         241                 :
         242                 : void JS_FASTCALL
         243           20783 : stubs::BitXor(VMFrame &f)
         244                 : {
         245                 :     int32_t i, j;
         246                 :
         247           20783 :     if (!ToInt32(f.cx, f.regs.sp[-2], &i) || !ToInt32(f.cx, f.regs.sp[-1], &j))
         248               0 :         THROW();
         249                 :
         250           20783 :     i = i ^ j;
         251           20783 :     f.regs.sp[-2].setInt32(i);
         252                 : }
         253                 :
         254                 : void JS_FASTCALL
         255           64504 : stubs::BitAnd(VMFrame &f)
         256                 : {
         257                 :     int32_t i, j;
         258                 :
         259           64504 :     if (!ToInt32(f.cx, f.regs.sp[-2], &i) || !ToInt32(f.cx, f.regs.sp[-1], &j))
         260               0 :         THROW();
         261                 :
         262           64504 :     i = i & j;
         263           64504 :     f.regs.sp[-2].setInt32(i);
         264                 : }
         265                 :
         266                 : void JS_FASTCALL
         267               2 : stubs::BitNot(VMFrame &f)
         268                 : {
         269                 :     int32_t i;
         270                 :
         271               2 :     if (!ToInt32(f.cx, f.regs.sp[-1], &i))
         272               0 :         THROW();
         273               2 :     i = ~i;
         274               2 :     f.regs.sp[-1].setInt32(i);
         275                 : }
         276                 :
         277                 : void JS_FASTCALL
         278             453 : stubs::Lsh(VMFrame &f)
         279                 : {
         280                 :     int32_t i, j;
         281             453 :     if (!ToInt32(f.cx, f.regs.sp[-2], &i))
         282               0 :         THROW();
         283             453 :     if (!ToInt32(f.cx, f.regs.sp[-1], &j))
         284               0 :         THROW();
         285             453 :     i = i << (j & 31);
         286             453 :     f.regs.sp[-2].setInt32(i);
         287                 : }
         288                 :
         289                 : void JS_FASTCALL
         290             509 : stubs::Rsh(VMFrame &f)
         291                 : {
         292                 :     int32_t i, j;
         293             509 :     if (!ToInt32(f.cx, f.regs.sp[-2], &i))
         294               0 :         THROW();
         295             509 :     if (!ToInt32(f.cx, f.regs.sp[-1], &j))
         296               0 :         THROW();
         297             509 :     i = i >> (j & 31);
         298             509 :     f.regs.sp[-2].setInt32(i);
         299                 : }
         300                 :
         301                 : void JS_FASTCALL
         302             388 : stubs::Ursh(VMFrame &f)
         303                 : {
         304                 :     uint32_t u;
         305             388 :     if (!ToUint32(f.cx, f.regs.sp[-2], &u))
         306               0 :         THROW();
         307                 :     int32_t j;
         308             388 :     if (!ToInt32(f.cx, f.regs.sp[-1], &j))
         309               0 :         THROW();
         310                 :
         311             388 :     u >>= (j & 31);
         312                 :
         313             388 :         if (!f.regs.sp[-2].setNumber(uint32_t(u)))
         314             255 :         TypeScript::MonitorOverflow(f.cx, f.script(), f.pc());
         315                 : }
         316                 :
         317                 : template<JSBool strict>
         318                 : void JS_FASTCALL
         319            1739 : stubs::DefFun(VMFrame &f, JSFunction *fun)
         320                 : {
         321                 :     JSObject *obj2;
         322                 :
         323            1739 :     JSContext *cx = f.cx;
         324            1739 :     StackFrame *fp = f.fp();
         325                 :
         326                 :     /*
         327                 :      * A top-level function defined in Global or Eval code (see ECMA-262
         328                 :      * Ed. 3), or else a SpiderMonkey extension: a named function statement in
         329                 :      * a compound statement (not at the top statement level of global code, or
         330                 :      * at the top level of a function body).
         331                 :      */
         332            1739 :     JSObject *obj = fun;
         333                 :
         334            1739 :     if (fun->isNullClosure()) {
         335                 :         /*
         336                 :          * Even a null closure needs a parent for principals finding.
         337                 :          * FIXME: bug 476950, although debugger users may also demand some kind
         338                 :          * of scope link for debugger-assisted eval-in-frame.
         339                 :          */
         340             865 :         obj2 = &fp->scopeChain();
         341                 :     } else {
         342             874 :         obj2 = GetScopeChain(cx, fp);
         343             874 :         if (!obj2)
         344               0 :             THROW();
         345                 :     }
         346                 :
         347                 :     /*
         348                 :      * If static link is not current scope, clone fun's object to link to the
         349                 :      * current scope via parent. We do this to enable sharing of compiled
         350                 :      * functions among multiple equivalent scopes, amortizing the cost of
         351                 :      * compilation over a number of executions.  Examples include XUL scripts
         352                 :      * and event handlers shared among Firefox or other Mozilla app chrome
         353                 :      * windows, and user-defined JS functions precompiled and then shared among
         354                 :      * requests in server-side JS.
         355                 :      */
         356            1739 :     if (obj->toFunction()->environment() != obj2) {
         357             306 :         obj = CloneFunctionObjectIfNotSingleton(cx, fun, obj2);
         358             306 :         if (!obj)
         359               0 :             THROW();
         360             306 :         JS_ASSERT_IF(f.script()->compileAndGo, obj->global() == fun->global());
         361                 :     }
         362                 :
         363                 :     /*
         364                 :      * ECMA requires functions defined when entering Eval code to be
         365                 :      * impermanent.
         366                 :      */
         367                 :     unsigned attrs = fp->isEvalFrame()
         368                 :                   ? JSPROP_ENUMERATE
         369            1739 :                   : JSPROP_ENUMERATE | JSPROP_PERMANENT;
         370                 :
         371                 :     /*
         372                 :      * We define the function as a property of the variable object and not the
         373                 :      * current scope chain even for the case of function expression statements
         374                 :      * and functions defined by eval inside let or with blocks.
         375                 :      */
         376            1739 :     JSObject *parent = &fp->varObj();
         377                 :
         378                 :     /* ES5 10.5 (NB: with subsequent errata). */
         379            1739 :     PropertyName *name = fun->atom->asPropertyName();
         380            1739 :     JSProperty *prop = NULL;
         381                 :     JSObject *pobj;
         382            1739 :     if (!parent->lookupProperty(cx, name, &pobj, &prop))
         383               0 :         THROW();
         384                 :
         385            1739 :     Value rval = ObjectValue(*obj);
         386                 :
         387                 :     do {
         388                 :         /* Steps 5d, 5f. */
         389            1739 :         if (!prop || pobj != parent) {
         390            1114 :             if (!parent->defineProperty(cx, name, rval,
         391                 :                                         JS_PropertyStub, JS_StrictPropertyStub, attrs))
         392                 :             {
         393               0 :                 THROW();
         394                 :             }
         395            1114 :             break;
         396                 :         }
         397                 :
         398                 :         /* Step 5e. */
         399             625 :         JS_ASSERT(parent->isNative());
         400             625 :         Shape *shape = reinterpret_cast<Shape *>(prop);
         401             625 :         if (parent->isGlobal()) {
         402             475 :             if (shape->configurable()) {
         403             130 :                 if (!parent->defineProperty(cx, name, rval,
         404                 :                                             JS_PropertyStub, JS_StrictPropertyStub, attrs))
         405                 :                 {
         406               0 :                     THROW();
         407                 :                 }
         408             130 :                 break;
         409                 :             }
         410                 :
         411             345 :             if (shape->isAccessorDescriptor() || !shape->writable() || !shape->enumerable()) {
         412               8 :                 JSAutoByteString bytes;
         413               4 :                 if (js_AtomToPrintableString(cx, name, &bytes)) {
         414               4 :                     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
         415                 :                                          JSMSG_CANT_REDEFINE_PROP, bytes.ptr());
         416                 :                 }
         417               4 :                 THROW();
         418                 :             }
         419                 :         }
         420                 :
         421                 :         /*
         422                 :          * Non-global properties, and global properties which we aren't simply
         423                 :          * redefining, must be set.  First, this preserves their attributes.
         424                 :          * Second, this will produce warnings and/or errors as necessary if the
         425                 :          * specified Call object property is not writable (const).
         426                 :          */
         427                 :
         428                 :         /* Step 5f. */
         429             491 :         if (!parent->setProperty(cx, name, &rval, strict))
         430               0 :             THROW();
         431                 :     } while (false);
         432                 : }
         433                 :
         434                 : template void JS_FASTCALL stubs::DefFun<true>(VMFrame &f, JSFunction *fun);
         435                 : template void JS_FASTCALL stubs::DefFun<false>(VMFrame &f, JSFunction *fun);
         436                 :
         437                 : #define RELATIONAL(OP)                                                        \
         438                 :     JS_BEGIN_MACRO                                                            \
         439                 :         JSContext *cx = f.cx;                                                 \
         440                 :         FrameRegs &regs = f.regs;                                             \
         441                 :         Value &rval = regs.sp[-1];                                            \
         442                 :         Value &lval = regs.sp[-2];                                            \
         443                 :         bool cond;                                                            \
         444                 :         if (!ToPrimitive(cx, JSTYPE_NUMBER, &lval))                           \
         445                 :             THROWV(JS_FALSE);                                                 \
         446                 :         if (!ToPrimitive(cx, JSTYPE_NUMBER, &rval))                           \
         447                 :             THROWV(JS_FALSE);                                                 \
         448                 :         if (lval.isString() && rval.isString()) {                             \
         449                 :             JSString *l = lval.toString(), *r = rval.toString();              \
         450                 :             int32_t cmp;                                                      \
         451                 :             if (!CompareStrings(cx, l, r, &cmp))                              \
         452                 :                 THROWV(JS_FALSE);                                             \
         453                 :             cond = cmp OP 0;                                                  \
         454                 :         } else {                                                              \
         455                 :             double l, r;                                                      \
         456                 :             if (!ToNumber(cx, lval, &l) || !ToNumber(cx, rval, &r))           \
         457                 :                 THROWV(JS_FALSE);                                             \
         458                 :             cond = (l OP r);                                                  \
         459                 :         }                                                                     \
         460                 :         regs.sp[-2].setBoolean(cond);                                         \
         461                 :         return cond;                                                          \
         462                 :     JS_END_MACRO
         463                 :
         464                 : JSBool JS_FASTCALL
         465          402239 : stubs::LessThan(VMFrame &f)
         466                 : {
         467          402239 :     RELATIONAL(<);
         468                 : }
         469                 :
         470                 : JSBool JS_FASTCALL
         471           17849 : stubs::LessEqual(VMFrame &f)
         472                 : {
         473           17849 :     RELATIONAL(<=);
         474                 : }
         475                 :
         476                 : JSBool JS_FASTCALL
         477          154450 : stubs::GreaterThan(VMFrame &f)
         478                 : {
         479          154450 :     RELATIONAL(>);
         480                 : }
         481                 :
         482                 : JSBool JS_FASTCALL
         483           17849 : stubs::GreaterEqual(VMFrame &f)
         484                 : {
         485           17849 :     RELATIONAL(>=);
         486                 : }
         487                 :
         488                 : JSBool JS_FASTCALL
         489         3927492 : stubs::ValueToBoolean(VMFrame &f)
         490                 : {
         491         3927492 :     return js_ValueToBoolean(f.regs.sp[-1]);
         492                 : }
         493                 :
         494                 : void JS_FASTCALL
         495          117304 : stubs::Not(VMFrame &f)
         496                 : {
         497          117304 :     JSBool b = !js_ValueToBoolean(f.regs.sp[-1]);
         498          117304 :     f.regs.sp[-1].setBoolean(b);
         499          117304 : }
         500                 :
         501                 : template <bool EQ>
         502                 : static inline bool
         503          380895 : StubEqualityOp(VMFrame &f)
         504                 : {
         505          380895 :     JSContext *cx = f.cx;
         506          380895 :     FrameRegs &regs = f.regs;
         507                 :
         508          380895 :     Value rval = regs.sp[-1];
         509          380895 :     Value lval = regs.sp[-2];
         510                 :
         511                 :     bool cond;
         512                 :
         513                 :     /* The string==string case is easily the hottest;  try it first. */
         514          380895 :     if (lval.isString() && rval.isString()) {
         515          111211 :         JSString *l = lval.toString();
         516          111211 :         JSString *r = rval.toString();
         517                 :         bool equal;
         518          111211 :         if (!EqualStrings(cx, l, r, &equal))
         519               0 :             return false;
         520          111211 :         cond = equal == EQ;
         521                 :     } else
         522                 : #if JS_HAS_XML_SUPPORT
         523          269684 :     if ((lval.isObject() && lval.toObject().isXML()) ||
         524                 :         (rval.isObject() && rval.toObject().isXML()))
         525                 :     {
         526                 :         JSBool equal;
         527               0 :         if (!js_TestXMLEquality(cx, lval, rval, &equal))
         528               0 :             return false;
         529               0 :         cond = !!equal == EQ;
         530                 :     } else
         531                 : #endif
         532                 :
         533          269684 :     if (SameType(lval, rval)) {
         534          195312 :         JS_ASSERT(!lval.isString());    /* this case is handled above */
         535          195312 :         if (lval.isDouble()) {
         536          123658 :             double l = lval.toDouble();
         537          123658 :             double r = rval.toDouble();
         538                 :             if (EQ)
         539          115481 :                 cond = (l == r);
         540                 :             else
         541            8177 :                 cond = (l != r);
         542           71654 :         } else if (lval.isObject()) {
         543           31564 :             JSObject *l = &lval.toObject(), *r = &rval.toObject();
         544           31564 :             if (JSEqualityOp eq = l->getClass()->ext.equality) {
         545                 :                 JSBool equal;
         546               0 :                 if (!eq(cx, l, &rval, &equal))
         547               0 :                     return false;
         548               0 :                 cond = !!equal == EQ;
         549                 :             } else {
         550           31564 :                 cond = (l == r) == EQ;
         551                 :             }
         552           40090 :         } else if (lval.isNullOrUndefined()) {
         553           32936 :             cond = EQ;
         554                 :         } else {
         555            7154 :             cond = (lval.payloadAsRawUint32() == rval.payloadAsRawUint32()) == EQ;
         556                 :         }
         557                 :     } else {
         558           74372 :         if (lval.isNullOrUndefined()) {
         559           15034 :             cond = rval.isNullOrUndefined() == EQ;
         560           59338 :         } else if (rval.isNullOrUndefined()) {
         561           13139 :             cond = !EQ;
         562                 :         } else {
         563           46199 :             if (!ToPrimitive(cx, &lval))
         564               4 :                 return false;
         565           46195 :             if (!ToPrimitive(cx, &rval))
         566               0 :                 return false;
         567                 :
         568                 :             /*
         569                 :              * The string==string case is repeated because ToPrimitive can
         570                 :              * convert lval/rval to strings.
         571                 :              */
         572           46195 :             if (lval.isString() && rval.isString()) {
         573            2632 :                 JSString *l = lval.toString();
         574            2632 :                 JSString *r = rval.toString();
         575                 :                 bool equal;
         576            2632 :                 if (!EqualStrings(cx, l, r, &equal))
         577               0 :                     return false;
         578            2632 :                 cond = equal == EQ;
         579                 :             } else {
         580                 :                 double l, r;
         581           43563 :                 if (!ToNumber(cx, lval, &l) || !ToNumber(cx, rval, &r))
         582               0 :                     return false;
         583                 :
         584                 :                 if (EQ)
         585           27989 :                     cond = (l == r);
         586                 :                 else
         587           15574 :                     cond = (l != r);
         588                 :             }
         589                 :         }
         590                 :     }
         591                 :
         592          380891 :     regs.sp[-2].setBoolean(cond);
         593          380891 :     return true;
         594                 : }
         595                 :
         596                 : JSBool JS_FASTCALL
         597          260674 : stubs::Equal(VMFrame &f)
         598                 : {
         599          260674 :     if (!StubEqualityOp<true>(f))
         600               4 :         THROWV(JS_FALSE);
         601          260670 :     return f.regs.sp[-2].toBoolean();
         602                 : }
         603                 :
         604                 : JSBool JS_FASTCALL
         605          120221 : stubs::NotEqual(VMFrame &f)
         606                 : {
         607          120221 :     if (!StubEqualityOp<false>(f))
         608               0 :         THROWV(JS_FALSE);
         609          120221 :     return f.regs.sp[-2].toBoolean();
         610                 : }
         611                 :
         612                 : void JS_FASTCALL
         613        15707038 : stubs::Add(VMFrame &f)
         614                 : {
         615        15707038 :     JSContext *cx = f.cx;
         616        15707038 :     FrameRegs &regs = f.regs;
         617        15707038 :     Value rval = regs.sp[-1];
         618        15707038 :     Value lval = regs.sp[-2];
         619                 :
         620                 :     /* The string + string case is easily the hottest;  try it first. */
         621        15707038 :     bool lIsString = lval.isString();
         622        15707038 :     bool rIsString = rval.isString();
         623                 :     JSString *lstr, *rstr;
         624        15707038 :     if (lIsString && rIsString) {
         625        12739443 :         lstr = lval.toString();
         626        12739443 :         rstr = rval.toString();
         627        12739443 :         goto string_concat;
         628                 :
         629                 :     } else
         630                 : #if JS_HAS_XML_SUPPORT
         631         2967595 :     if (lval.isObject() && lval.toObject().isXML() &&
         632               0 :         rval.isObject() && rval.toObject().isXML()) {
         633               0 :         if (!js_ConcatenateXML(cx, &lval.toObject(), &rval.toObject(), &rval))
         634               0 :             THROW();
         635               0 :         regs.sp[-2] = rval;
         636               0 :         regs.sp--;
         637               0 :         TypeScript::MonitorUnknown(cx, f.script(), f.pc());
         638                 :     } else
         639                 : #endif
         640                 :     {
         641         2967595 :         bool lIsObject = lval.isObject(), rIsObject = rval.isObject();
         642         2967595 :         if (!ToPrimitive(f.cx, &lval))
         643              16 :             THROW();
         644         2967579 :         if (!ToPrimitive(f.cx, &rval))
         645              13 :             THROW();
         646         2967566 :         if ((lIsString = lval.isString()) || (rIsString = rval.isString())) {
         647         2687059 :             if (lIsString) {
         648         2184360 :                 lstr = lval.toString();
         649                 :             } else {
         650          502699 :                 lstr = ToString(cx, lval);
         651          502699 :                 if (!lstr)
         652               0 :                     THROW();
         653          502699 :                 regs.sp[-2].setString(lstr);
         654                 :             }
         655         2687059 :             if (rIsString) {
         656          504101 :                 rstr = rval.toString();
         657                 :             } else {
         658         2182958 :                 rstr = ToString(cx, rval);
         659         2182958 :                 if (!rstr)
         660               0 :                     THROW();
         661         2182958 :                 regs.sp[-1].setString(rstr);
         662                 :             }
         663         2687059 :             if (lIsObject || rIsObject)
         664          391309 :                 TypeScript::MonitorString(cx, f.script(), f.pc());
         665         2687059 :             goto string_concat;
         666                 :
         667                 :         } else {
         668                 :             double l, r;
         669          280507 :             if (!ToNumber(cx, lval, &l) || !ToNumber(cx, rval, &r))
         670               0 :                 THROW();
         671          280507 :             l += r;
         672          837970 :             if (!regs.sp[-2].setNumber(l) &&
         673          557463 :                 (lIsObject || rIsObject || (!lval.isDouble() && !rval.isDouble()))) {
         674          278020 :                 TypeScript::MonitorOverflow(cx, f.script(), f.pc());
         675                 :             }
         676                 :         }
         677                 :     }
         678          280507 :     return;
         679                 :
         680                 :   string_concat:
         681        15426502 :     JSString *str = js_ConcatStrings(cx, lstr, rstr);
         682        15426502 :     if (!str)
         683               5 :         THROW();
         684        15426497 :     regs.sp[-2].setString(str);
         685        15426497 :     regs.sp--;
         686                 : }
         687                 :
         688                 :
         689                 : void JS_FASTCALL
         690             163 : stubs::Sub(VMFrame &f)
         691                 : {
         692             163 :     JSContext *cx = f.cx;
         693             163 :     FrameRegs &regs = f.regs;
         694                 :     double d1, d2;
         695             163 :     if (!ToNumber(cx, regs.sp[-2], &d1) || !ToNumber(cx, regs.sp[-1], &d2))
         696               0 :         THROW();
         697             163 :     double d = d1 - d2;
         698             163 :     if (!regs.sp[-2].setNumber(d))
         699             109 :         TypeScript::MonitorOverflow(cx, f.script(), f.pc());
         700                 : }
         701                 :
         702                 : void JS_FASTCALL
         703           78337 : stubs::Mul(VMFrame &f)
         704                 : {
         705           78337 :     JSContext *cx = f.cx;
         706           78337 :     FrameRegs &regs = f.regs;
         707                 :     double d1, d2;
         708           78337 :     if (!ToNumber(cx, regs.sp[-2], &d1) || !ToNumber(cx, regs.sp[-1], &d2))
         709               0 :         THROW();
         710           78337 :     double d = d1 * d2;
         711           78337 :     if (!regs.sp[-2].setNumber(d))
         712           78199 :         TypeScript::MonitorOverflow(cx, f.script(), f.pc());
         713                 : }
         714                 :
         715                 : void JS_FASTCALL
         716             730 : stubs::Div(VMFrame &f)
         717                 : {
         718             730 :     JSContext *cx = f.cx;
         719             730 :     JSRuntime *rt = cx->runtime;
         720             730 :     FrameRegs &regs = f.regs;
         721                 :
         722                 :     double d1, d2;
         723             730 :     if (!ToNumber(cx, regs.sp[-2], &d1) || !ToNumber(cx, regs.sp[-1], &d2))
         724               0 :         THROW();
         725             730 :     if (d2 == 0) {
         726                 :         const Value *vp;
         727                 : #ifdef XP_WIN
         728                 :         /* XXX MSVC miscompiles such that (NaN == 0) */
         729                 :         if (JSDOUBLE_IS_NaN(d2))
         730                 :             vp = &rt->NaNValue;
         731                 :         else
         732                 : #endif
         733               2 :         if (d1 == 0 || JSDOUBLE_IS_NaN(d1))
         734               2 :             vp = &rt->NaNValue;
         735               0 :         else if (JSDOUBLE_IS_NEG(d1) != JSDOUBLE_IS_NEG(d2))
         736               0 :             vp = &rt->negativeInfinityValue;
         737                 :         else
         738               0 :             vp = &rt->positiveInfinityValue;
         739               2 :         regs.sp[-2] = *vp;
         740               2 :         TypeScript::MonitorOverflow(cx, f.script(), f.pc());
         741                 :     } else {
         742             728 :         d1 /= d2;
         743             728 :         if (!regs.sp[-2].setNumber(d1))
         744              22 :             TypeScript::MonitorOverflow(cx, f.script(), f.pc());
         745                 :     }
         746                 : }
         747                 :
         748                 : void JS_FASTCALL
         749           30492 : stubs::Mod(VMFrame &f)
         750                 : {
         751           30492 :     JSContext *cx = f.cx;
         752           30492 :     FrameRegs &regs = f.regs;
         753                 :
         754           30492 :     Value &lref = regs.sp[-2];
         755           30492 :     Value &rref = regs.sp[-1];
         756                 :     int32_t l, r;
         757           30492 :     if (lref.isInt32() && rref.isInt32() &&
         758                 :         (l = lref.toInt32()) >= 0 && (r = rref.toInt32()) > 0) {
         759               0 :         int32_t mod = l % r;
         760               0 :         regs.sp[-2].setInt32(mod);
         761                 :     } else {
         762                 :         double d1, d2;
         763           30492 :         if (!ToNumber(cx, regs.sp[-2], &d1) || !ToNumber(cx, regs.sp[-1], &d2))
         764               0 :             THROW();
         765           30492 :         if (d2 == 0) {
         766              97 :             regs.sp[-2].setDouble(js_NaN);
         767                 :         } else {
         768           30395 :             d1 = js_fmod(d1, d2);
         769           30395 :             regs.sp[-2].setDouble(d1);
         770                 :         }
         771           30492 :         TypeScript::MonitorOverflow(cx, f.script(), f.pc());
         772                 :     }
         773                 : }
         774                 :
         775                 : void JS_FASTCALL
         776            3382 : stubs::DebuggerStatement(VMFrame &f, jsbytecode *pc)
         777                 : {
         778            3382 :     JSDebuggerHandler handler = f.cx->runtime->debugHooks.debuggerHandler;
         779            3382 :     if (handler || !f.cx->compartment->getDebuggees().empty()) {
         780            3352 :         JSTrapStatus st = JSTRAP_CONTINUE;
         781                 :         Value rval;
         782            3352 :         if (handler)
         783               8 :             st = handler(f.cx, f.script(), pc, &rval, f.cx->runtime->debugHooks.debuggerHandlerData);
         784            3352 :         if (st == JSTRAP_CONTINUE)
         785            3348 :             st = Debugger::onDebuggerStatement(f.cx, &rval);
         786                 :
         787            3352 :         switch (st) {
         788                 :           case JSTRAP_THROW:
         789              60 :             f.cx->setPendingException(rval);
         790              60 :             THROW();
         791                 :
         792                 :           case JSTRAP_RETURN:
         793             112 :             f.cx->clearPendingException();
         794             112 :             f.cx->fp()->setReturnValue(rval);
         795             112 :             *f.returnAddressLocation() = f.cx->jaegerCompartment()->forceReturnFromFastCall();
         796             112 :             break;
         797                 :
         798                 :           case JSTRAP_ERROR:
         799              80 :             f.cx->clearPendingException();
         800              80 :             THROW();
         801                 :
         802                 :           default:
         803            3100 :             break;
         804                 :         }
         805                 :     }
         806                 : }
         807                 :
         808                 : void JS_FASTCALL
         809             354 : stubs::Interrupt(VMFrame &f, jsbytecode *pc)
         810                 : {
         811             354 :     gc::MaybeVerifyBarriers(f.cx);
         812                 :
         813             354 :     if (!js_HandleExecutionInterrupt(f.cx))
         814               0 :         THROW();
         815                 : }
         816                 :
         817                 : void JS_FASTCALL
         818              93 : stubs::RecompileForInline(VMFrame &f)
         819                 : {
         820              93 :     ExpandInlineFrames(f.cx->compartment);
         821                 :     Recompiler::clearStackReferencesAndChunk(f.cx->runtime->defaultFreeOp(), f.script(), f.jit(),
         822              93 :                                              f.chunkIndex(), /* resetUses = */ false);
         823              93 : }
         824                 :
         825                 : void JS_FASTCALL
         826             594 : stubs::Trap(VMFrame &f, uint32_t trapTypes)
         827                 : {
         828                 :     Value rval;
         829                 :
         830                 :     /*
         831                 :      * Trap may be called for a single-step interrupt trap and/or a
         832                 :      * regular trap. Try the single-step first, and if it lets control
         833                 :      * flow through or does not exist, do the regular trap.
         834                 :      */
         835             594 :     JSTrapStatus result = JSTRAP_CONTINUE;
         836             594 :     if (trapTypes & JSTRAP_SINGLESTEP) {
         837                 :         /*
         838                 :          * single step mode may be paused without recompiling by
         839                 :          * setting the interruptHook to NULL.
         840                 :          */
         841             299 :         JSInterruptHook hook = f.cx->runtime->debugHooks.interruptHook;
         842             299 :         if (hook)
         843               0 :             result = hook(f.cx, f.script(), f.pc(), &rval, f.cx->runtime->debugHooks.interruptHookData);
         844                 :
         845             299 :         if (result == JSTRAP_CONTINUE)
         846             299 :             result = Debugger::onSingleStep(f.cx, &rval);
         847                 :     }
         848                 :
         849             594 :     if (result == JSTRAP_CONTINUE && (trapTypes & JSTRAP_TRAP))
         850             295 :         result = Debugger::onTrap(f.cx, &rval);
         851                 :
         852             594 :     switch (result) {
         853                 :       case JSTRAP_THROW:
         854               0 :         f.cx->setPendingException(rval);
         855               0 :         THROW();
         856                 :
         857                 :       case JSTRAP_RETURN:
         858              24 :         f.cx->clearPendingException();
         859              24 :         f.cx->fp()->setReturnValue(rval);
         860              24 :         *f.returnAddressLocation() = f.cx->jaegerCompartment()->forceReturnFromFastCall();
         861              24 :         break;
         862                 :
         863                 :       case JSTRAP_ERROR:
         864               4 :         f.cx->clearPendingException();
         865               4 :         THROW();
         866                 :
         867                 :       default:
         868             566 :         break;
         869                 :     }
         870                 : }
         871                 :
         872                 : void JS_FASTCALL
         873           40573 : stubs::This(VMFrame &f)
         874                 : {
         875                 :     /*
         876                 :      * We can't yet inline scripts which need to compute their 'this' object
         877                 :      * from a primitive; the frame we are computing 'this' for does not exist yet.
         878                 :      */
         879           40573 :     if (f.regs.inlined()) {
         880               0 :         f.script()->uninlineable = true;
         881               0 :         MarkTypeObjectFlags(f.cx, &f.fp()->callee(), OBJECT_FLAG_UNINLINEABLE);
         882                 :     }
         883                 :
         884           40573 :     if (!ComputeThis(f.cx, f.fp()))
         885               0 :         THROW();
         886           40573 :     f.regs.sp[-1] = f.fp()->thisValue();
         887                 : }
         888                 :
         889                 : void JS_FASTCALL
         890            1905 : stubs::Neg(VMFrame &f)
         891                 : {
         892                 :     double d;
         893            1905 :     if (!ToNumber(f.cx, f.regs.sp[-1], &d))
         894               0 :         THROW();
         895            1905 :     d = -d;
         896            1905 :     if (!f.regs.sp[-1].setNumber(d))
         897            1845 :         TypeScript::MonitorOverflow(f.cx, f.script(), f.pc());
         898                 : }
         899                 :
         900                 : void JS_FASTCALL
         901         1210617 : stubs::NewInitArray(VMFrame &f, uint32_t count)
         902                 : {
         903         1210617 :     JSObject *obj = NewDenseAllocatedArray(f.cx, count);
         904         1210617 :     if (!obj)
         905               0 :         THROW();
         906                 :
         907         1210617 :     TypeObject *type = (TypeObject *) f.scratch;
         908         1210617 :     if (type) {
         909         1210421 :         obj->setType(type);
         910                 :     } else {
         911             196 :         if (!SetInitializerObjectType(f.cx, f.script(), f.pc(), obj))
         912               0 :             THROW();
         913                 :     }
         914                 :
         915         1210617 :     f.regs.sp[0].setObject(*obj);
         916                 : }
         917                 :
         918                 : void JS_FASTCALL
         919         1552128 : stubs::NewInitObject(VMFrame &f, JSObject *baseobj)
         920                 : {
         921         1552128 :     JSContext *cx = f.cx;
         922         1552128 :     TypeObject *type = (TypeObject *) f.scratch;
         923                 :
         924                 :     JSObject *obj;
         925                 :
         926         1552128 :     if (baseobj) {
         927         1551601 :         obj = CopyInitializerObject(cx, baseobj);
         928                 :     } else {
         929             527 :         gc::AllocKind kind = GuessObjectGCKind(0);
         930             527 :         obj = NewBuiltinClassInstance(cx, &ObjectClass, kind);
         931                 :     }
         932                 :
         933         1552128 :     if (!obj)
         934               0 :         THROW();
         935                 :
         936         1552128 :     if (type) {
         937         1551724 :         obj->setType(type);
         938                 :     } else {
         939             404 :         if (!SetInitializerObjectType(cx, f.script(), f.pc(), obj))
         940               0 :             THROW();
         941                 :     }
         942                 :
         943         1552128 :     f.regs.sp[0].setObject(*obj);
         944                 : }
         945                 :
         946                 : void JS_FASTCALL
         947             638 : stubs::InitElem(VMFrame &f, uint32_t last)
         948                 : {
         949             638 :     JSContext *cx = f.cx;
         950             638 :     FrameRegs &regs = f.regs;
         951                 :
         952                 :     /* Pop the element's value into rval. */
         953             638 :     JS_ASSERT(regs.sp - f.fp()->base() >= 3);
         954             638 :     const Value &rref = regs.sp[-1];
         955                 :
         956                 :     /* Find the object being initialized at top of stack. */
         957             638 :     const Value &lref = regs.sp[-3];
         958             638 :     JS_ASSERT(lref.isObject());
         959             638 :     JSObject *obj = &lref.toObject();
         960                 :
         961                 :     /* Fetch id now that we have obj. */
         962                 :     jsid id;
         963             638 :     const Value &idval = regs.sp[-2];
         964             638 :     if (!FetchElementId(f.cx, obj, idval, id, &regs.sp[-2]))
         965               0 :         THROW();
         966                 :
         967                 :     /*
         968                 :      * If rref is a hole, do not call JSObject::defineProperty. In this case,
         969                 :      * obj must be an array, so if the current op is the last element
         970                 :      * initialiser, set the array length to one greater than id.
         971                 :      */
         972             638 :     if (rref.isMagic(JS_ARRAY_HOLE)) {
         973               0 :         JS_ASSERT(obj->isArray());
         974               0 :         JS_ASSERT(JSID_IS_INT(id));
         975               0 :         JS_ASSERT(uint32_t(JSID_TO_INT(id)) < StackSpace::ARGS_LENGTH_MAX);
         976               0 :         if (last && !js_SetLengthProperty(cx, obj, (uint32_t) (JSID_TO_INT(id) + 1)))
         977               0 :             THROW();
         978                 :     } else {
         979             638 :         if (!obj->defineGeneric(cx, id, rref, NULL, NULL, JSPROP_ENUMERATE))
         980               0 :             THROW();
         981                 :     }
         982                 : }
         983                 :
         984                 : void JS_FASTCALL
         985          107872 : stubs::RegExp(VMFrame &f, JSObject *regex)
         986                 : {
         987                 :     /*
         988                 :      * Push a regexp object cloned from the regexp literal object mapped by the
         989                 :      * bytecode at pc.
         990                 :      */
         991          107872 :     JSObject *proto = f.fp()->scopeChain().global().getOrCreateRegExpPrototype(f.cx);
         992          107872 :     if (!proto)
         993               0 :         THROW();
         994          107872 :     JS_ASSERT(proto);
         995          107872 :     JSObject *obj = CloneRegExpObject(f.cx, regex, proto);
         996          107872 :     if (!obj)
         997               0 :         THROW();
         998          107872 :     f.regs.sp[0].setObject(*obj);
         999                 : }
        1000                 :
        1001                 : JSObject * JS_FASTCALL
        1002          733251 : stubs::Lambda(VMFrame &f, JSFunction *fun)
        1003                 : {
        1004                 :     JSObject *parent;
        1005          733251 :     if (fun->isNullClosure()) {
        1006          214137 :         parent = &f.fp()->scopeChain();
        1007                 :     } else {
        1008          519114 :         parent = GetScopeChain(f.cx, f.fp());
        1009          519114 :         if (!parent)
        1010               0 :             THROWV(NULL);
        1011                 :     }
        1012                 :
        1013          733251 :     JSObject *obj = CloneFunctionObjectIfNotSingleton(f.cx, fun, parent);
        1014          733251 :     if (!obj)
        1015               0 :         THROWV(NULL);
        1016                 :
        1017          733251 :     JS_ASSERT_IF(f.script()->compileAndGo, obj->global() == fun->global());
        1018          733251 :     return obj;
        1019                 : }
        1020                 :
        1021                 : void JS_FASTCALL
        1022          430799 : stubs::GetProp(VMFrame &f, PropertyName *name)
        1023                 : {
        1024          430799 :     JSContext *cx = f.cx;
        1025          430799 :     FrameRegs &regs = f.regs;
        1026                 :
        1027                 :     Value rval;
        1028          430799 :     if (!GetPropertyOperation(cx, f.pc(), f.regs.sp[-1], &rval))
        1029              19 :         THROW();
        1030                 :
        1031          430780 :     regs.sp[-1] = rval;
        1032                 : }
        1033                 :
        1034                 : void JS_FASTCALL
        1035               0 : stubs::GetPropNoCache(VMFrame &f, PropertyName *name)
        1036                 : {
        1037               0 :     JSContext *cx = f.cx;
        1038               0 :     FrameRegs &regs = f.regs;
        1039                 :
        1040               0 :     const Value &lval = f.regs.sp[-1];
        1041                 :
        1042                 :     // Uncached lookups are only used for .prototype accesses at the start of constructors.
        1043               0 :     JS_ASSERT(lval.isObject());
        1044               0 :     JS_ASSERT(name == cx->runtime->atomState.classPrototypeAtom);
        1045                 :
        1046               0 :     JSObject *obj = &lval.toObject();
        1047                 :
        1048                 :     Value rval;
        1049               0 :     if (!obj->getProperty(cx, name, &rval))
        1050               0 :         THROW();
        1051                 :
        1052               0 :     regs.sp[-1] = rval;
        1053                 : }
        1054                 :
        1055                 : void JS_FASTCALL
        1056          301557 : stubs::Iter(VMFrame &f, uint32_t flags)
        1057                 : {
        1058          301557 :     if (!ValueToIterator(f.cx, flags, &f.regs.sp[-1]))
        1059              57 :         THROW();
        1060          301500 :     JS_ASSERT(!f.regs.sp[-1].isPrimitive());
        1061                 : }
        1062                 :
        1063                 : static void
        1064            1541 : InitPropOrMethod(VMFrame &f, PropertyName *name, JSOp op)
        1065                 : {
        1066            1541 :     JSContext *cx = f.cx;
        1067            1541 :     FrameRegs &regs = f.regs;
        1068                 :
        1069                 :     /* Load the property's initial value into rval. */
        1070            1541 :     JS_ASSERT(regs.sp - f.fp()->base() >= 2);
        1071                 :     Value rval;
        1072            1541 :     rval = regs.sp[-1];
        1073                 :
        1074                 :     /* Load the object being initialized into lval/obj. */
        1075            1541 :     JSObject *obj = &regs.sp[-2].toObject();
        1076            1541 :     JS_ASSERT(obj->isNative());
        1077                 :
        1078                 :     /* Get the immediate property name into id. */
        1079            1541 :     jsid id = ATOM_TO_JSID(name);
        1080                 :
        1081            3082 :     if (JS_UNLIKELY(name == cx->runtime->atomState.protoAtom)
        1082              61 :         ? !js_SetPropertyHelper(cx, obj, id, 0, &rval, false)
        1083                 :         : !DefineNativeProperty(cx, obj, id, rval, NULL, NULL,
        1084            1480 :                                 JSPROP_ENUMERATE, 0, 0, 0)) {
        1085               0 :         THROW();
        1086                 :     }
        1087                 : }
        1088                 :
        1089                 : void JS_FASTCALL
        1090            1541 : stubs::InitProp(VMFrame &f, PropertyName *name)
        1091                 : {
        1092            1541 :     InitPropOrMethod(f, name, JSOP_INITPROP);
        1093            1541 : }
        1094                 :
        1095                 : void JS_FASTCALL
        1096         9307099 : stubs::IterNext(VMFrame &f, int32_t offset)
        1097                 : {
        1098         9307099 :     JS_ASSERT(f.regs.sp - offset >= f.fp()->base());
        1099         9307099 :     JS_ASSERT(f.regs.sp[-offset].isObject());
        1100                 :
        1101         9307099 :     JSObject *iterobj = &f.regs.sp[-offset].toObject();
        1102         9307099 :     f.regs.sp[0].setNull();
        1103         9307099 :     f.regs.sp++;
        1104         9307099 :     if (!js_IteratorNext(f.cx, iterobj, &f.regs.sp[-1]))
        1105               0 :         THROW();
        1106                 : }
        1107                 :
        1108                 : JSBool JS_FASTCALL
        1109         9420833 : stubs::IterMore(VMFrame &f)
        1110                 : {
        1111         9420833 :     JS_ASSERT(f.regs.sp - 1 >= f.fp()->base());
        1112         9420833 :     JS_ASSERT(f.regs.sp[-1].isObject());
        1113                 :
        1114                 :     Value v;
        1115         9420833 :     JSObject *iterobj = &f.regs.sp[-1].toObject();
        1116         9420833 :     if (!js_IteratorMore(f.cx, iterobj, &v))
        1117              14 :         THROWV(JS_FALSE);
        1118                 :
        1119         9420819 :     return v.toBoolean();
        1120                 : }
        1121                 :
        1122                 : void JS_FASTCALL
        1123             917 : stubs::EndIter(VMFrame &f)
        1124                 : {
        1125             917 :     JS_ASSERT(f.regs.sp - 1 >= f.fp()->base());
        1126             917 :     if (!CloseIterator(f.cx, &f.regs.sp[-1].toObject()))
        1127               0 :         THROW();
        1128                 : }
        1129                 :
        1130                 : JSString * JS_FASTCALL
        1131           65632 : stubs::TypeOf(VMFrame &f)
        1132                 : {
        1133           65632 :     const Value &ref = f.regs.sp[-1];
        1134           65632 :     JSType type = JS_TypeOfValue(f.cx, ref);
        1135           65632 :     return f.cx->runtime->atomState.typeAtoms[type];
        1136                 : }
        1137                 :
        1138                 : void JS_FASTCALL
        1139          701110 : stubs::StrictEq(VMFrame &f)
        1140                 : {
        1141          701110 :     const Value &rhs = f.regs.sp[-1];
        1142          701110 :     const Value &lhs = f.regs.sp[-2];
        1143                 :     bool equal;
        1144          701110 :     if (!StrictlyEqual(f.cx, lhs, rhs, &equal))
        1145               0 :         THROW();
        1146          701110 :     f.regs.sp--;
        1147          701110 :     f.regs.sp[-1].setBoolean(equal == JS_TRUE);
        1148                 : }
        1149                 :
        1150                 : void JS_FASTCALL
        1151          236164 : stubs::StrictNe(VMFrame &f)
        1152                 : {
        1153          236164 :     const Value &rhs = f.regs.sp[-1];
        1154          236164 :     const Value &lhs = f.regs.sp[-2];
        1155                 :     bool equal;
        1156          236164 :     if (!StrictlyEqual(f.cx, lhs, rhs, &equal))
        1157               0 :         THROW();
        1158          236164 :     f.regs.sp--;
        1159          236164 :     f.regs.sp[-1].setBoolean(equal != JS_TRUE);
        1160                 : }
        1161                 :
        1162                 : void JS_FASTCALL
        1163             501 : stubs::Throw(VMFrame &f)
        1164                 : {
        1165             501 :     JSContext *cx = f.cx;
        1166                 :
        1167             501 :     JS_ASSERT(!cx->isExceptionPending());
        1168             501 :     cx->setPendingException(f.regs.sp[-1]);
        1169             501 :     THROW();
        1170                 : }
        1171                 :
        1172                 : void JS_FASTCALL
        1173          302545 : stubs::Arguments(VMFrame &f)
        1174                 : {
        1175          302545 :     if (!f.fp()->hasArgsObj()) {
        1176                 :         /*
        1177                 :          * This case occurs when checkCallApplySpeculation detects that
        1178                 :          * 'f.apply' is not actually js_fun_apply. In this case, we need to
        1179                 :          * report the mis-speculation which will bail
        1180                 :          */
        1181               1 :         if (!f.fp()->script()->applySpeculationFailed(f.cx))
        1182               0 :             THROW();
        1183                 :     }
        1184          302545 :     f.regs.sp[0] = ObjectValue(f.fp()->argsObj());
        1185                 : }
        1186                 :
        1187                 : JSBool JS_FASTCALL
        1188           40420 : stubs::InstanceOf(VMFrame &f)
        1189                 : {
        1190           40420 :     JSContext *cx = f.cx;
        1191           40420 :     FrameRegs &regs = f.regs;
        1192                 :
        1193           40420 :     const Value &rref = regs.sp[-1];
        1194           40420 :     if (rref.isPrimitive()) {
        1195                 :         js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS,
        1196               0 :                             -1, rref, NULL);
        1197               0 :         THROWV(JS_FALSE);
        1198                 :     }
        1199           40420 :     JSObject *obj = &rref.toObject();
        1200           40420 :     const Value &lref = regs.sp[-2];
        1201           40420 :     JSBool cond = JS_FALSE;
        1202           40420 :     if (!HasInstance(cx, obj, &lref, &cond))
        1203               6 :         THROWV(JS_FALSE);
        1204           40414 :     f.regs.sp[-2].setBoolean(cond);
        1205           40414 :     return cond;
        1206                 : }
        1207                 :
        1208                 : void JS_FASTCALL
        1209               2 : stubs::FastInstanceOf(VMFrame &f)
        1210                 : {
        1211               2 :     const Value &lref = f.regs.sp[-1];
        1212                 :
        1213               2 :     if (lref.isPrimitive()) {
        1214                 :         /*
        1215                 :          * Throw a runtime error if instanceof is called on a function that
        1216                 :          * has a non-object as its .prototype value.
        1217                 :          */
        1218               2 :         js_ReportValueError(f.cx, JSMSG_BAD_PROTOTYPE, -1, f.regs.sp[-2], NULL);
        1219               2 :         THROW();
        1220                 :     }
        1221                 :
        1222               0 :     f.regs.sp[-3].setBoolean(js_IsDelegate(f.cx, &lref.toObject(), f.regs.sp[-3]));
        1223                 : }
        1224                 :
        1225                 : void JS_FASTCALL
        1226           32163 : stubs::EnterBlock(VMFrame &f, JSObject *obj)
        1227                 : {
        1228           32163 :     FrameRegs &regs = f.regs;
        1229           32163 :     StackFrame *fp = f.fp();
        1230           32163 :     StaticBlockObject &blockObj = obj->asStaticBlock();
        1231                 :
        1232           32163 :     JS_ASSERT(!f.regs.inlined());
        1233                 :
        1234           32163 :     if (*regs.pc == JSOP_ENTERBLOCK) {
        1235           29096 :         JS_ASSERT(fp->base() + blockObj.stackDepth() == regs.sp);
        1236           29096 :         Value *vp = regs.sp + blockObj.slotCount();
        1237           29096 :         JS_ASSERT(regs.sp < vp);
        1238           29096 :         JS_ASSERT(vp <= fp->slots() + fp->script()->nslots);
        1239           29096 :         SetValueRangeToUndefined(regs.sp, vp);
        1240           29096 :         regs.sp = vp;
        1241                 :     }
        1242                 :
        1243                 : #ifdef DEBUG
        1244           32163 :     JSContext *cx = f.cx;
        1245           32163 :     JS_ASSERT(fp->maybeBlockChain() == blockObj.enclosingBlock());
        1246                 :
        1247                 :     /*
        1248                 :      * The young end of fp->scopeChain() may omit blocks if we haven't closed
        1249                 :      * over them, but if there are any closure blocks on fp->scopeChain(), they'd
        1250                 :      * better be (clones of) ancestors of the block we're entering now;
        1251                 :      * anything else we should have popped off fp->scopeChain() when we left its
        1252                 :      * static scope.
        1253                 :      */
        1254           32163 :     JSObject *obj2 = &fp->scopeChain();
        1255           64326 :     while (obj2->isWith())
        1256               0 :         obj2 = &obj2->asWith().enclosingScope();
        1257           32589 :     if (obj2->isBlock() &&
        1258             426 :         obj2->getPrivate() == js_FloatingFrameIfGenerator(cx, fp)) {
        1259               0 :         JSObject &youngestProto = obj2->asClonedBlock().staticBlock();
        1260               0 :         StaticBlockObject *parent = &blockObj;
        1261               0 :         while ((parent = parent->enclosingBlock()) != &youngestProto)
        1262               0 :             JS_ASSERT(parent);
        1263                 :     }
        1264                 : #endif
        1265                 :
        1266           32163 :     fp->setBlockChain(&blockObj);
        1267           32163 : }
        1268                 :
        1269                 : void JS_FASTCALL
        1270           31730 : stubs::LeaveBlock(VMFrame &f)
        1271                 : {
        1272           31730 :     JSContext *cx = f.cx;
        1273           31730 :     StackFrame *fp = f.fp();
        1274                 :
        1275           31730 :     StaticBlockObject &blockObj = fp->blockChain();
        1276           31730 :     JS_ASSERT(blockObj.stackDepth() <= StackDepth(fp->script()));
        1277                 :
        1278                 :     /*
        1279                 :      * If we're about to leave the dynamic scope of a block that has been
        1280                 :      * cloned onto fp->scopeChain(), clear its private data, move its locals from
        1281                 :      * the stack into the clone, and pop it off the chain.
        1282                 :      */
        1283           31730 :     JSObject &obj = fp->scopeChain();
        1284           31730 :     if (obj.getProto() == &blockObj)
        1285             252 :         obj.asClonedBlock().put(cx);
        1286                 :
        1287           31730 :     fp->setBlockChain(blockObj.enclosingBlock());
        1288           31730 : }
        1289                 :
        1290                 : inline void *
        1291            2119 : FindNativeCode(VMFrame &f, jsbytecode *target)
        1292                 : {
        1293            2119 :     void* native = f.fp()->script()->nativeCodeForPC(f.fp()->isConstructing(), target);
        1294            2119 :     if (native)
        1295            2119 :         return native;
        1296                 :
        1297               0 :     uint32_t sourceOffset = f.pc() - f.script()->code;
        1298               0 :     uint32_t targetOffset = target - f.script()->code;
        1299                 :
        1300               0 :     CrossChunkEdge *edges = f.jit()->edges();
        1301               0 :     for (size_t i = 0; i < f.jit()->nedges; i++) {
        1302               0 :         const CrossChunkEdge &edge = edges[i];
        1303               0 :         if (edge.source == sourceOffset && edge.target == targetOffset)
        1304               0 :             return edge.shimLabel;
        1305                 :     }
        1306                 :
        1307               0 :     JS_NOT_REACHED("Missing edge");
        1308                 :     return NULL;
        1309                 : }
        1310                 :
        1311                 : void * JS_FASTCALL
        1312            1441 : stubs::LookupSwitch(VMFrame &f, jsbytecode *pc)
        1313                 : {
        1314            1441 :     jsbytecode *jpc = pc;
        1315            1441 :     JSScript *script = f.fp()->script();
        1316                 :
        1317                 :     /* This is correct because the compiler adjusts the stack beforehand. */
        1318            1441 :     Value lval = f.regs.sp[-1];
        1319                 :
        1320            1441 :     if (!lval.isPrimitive())
        1321               0 :         return FindNativeCode(f, pc + GET_JUMP_OFFSET(pc));
        1322                 :
        1323            1441 :     JS_ASSERT(pc[0] == JSOP_LOOKUPSWITCH);
        1324                 :
        1325            1441 :     pc += JUMP_OFFSET_LEN;
        1326            1441 :     uint32_t npairs = GET_UINT16(pc);
        1327            1441 :     pc += UINT16_LEN;
        1328                 :
        1329            1441 :     JS_ASSERT(npairs);
        1330                 :
        1331            1441 :     if (lval.isString()) {
        1332            1086 :         JSLinearString *str = lval.toString()->ensureLinear(f.cx);
        1333            1086 :         if (!str)
        1334               0 :             THROWV(NULL);
        1335            4475 :         for (uint32_t i = 1; i <= npairs; i++) {
        1336            4305 :             Value rval = script->getConst(GET_UINT32_INDEX(pc));
        1337            4305 :             pc += UINT32_INDEX_LEN;
        1338            4305 :             if (rval.isString()) {
        1339            4305 :                 JSLinearString *rhs = &rval.toString()->asLinear();
        1340            4305 :                 if (rhs == str || EqualStrings(str, rhs))
        1341             916 :                     return FindNativeCode(f, jpc + GET_JUMP_OFFSET(pc));
        1342                 :             }
        1343            3389 :             pc += JUMP_OFFSET_LEN;
        1344                 :         }
        1345             355 :     } else if (lval.isNumber()) {
        1346               0 :         double d = lval.toNumber();
        1347               0 :         for (uint32_t i = 1; i <= npairs; i++) {
        1348               0 :             Value rval = script->getConst(GET_UINT32_INDEX(pc));
        1349               0 :             pc += UINT32_INDEX_LEN;
        1350               0 :             if (rval.isNumber() && d == rval.toNumber())
        1351               0 :                 return FindNativeCode(f, jpc + GET_JUMP_OFFSET(pc));
        1352               0 :             pc += JUMP_OFFSET_LEN;
        1353                 :         }
        1354                 :     } else {
        1355             710 :         for (uint32_t i = 1; i <= npairs; i++) {
        1356             355 :             Value rval = script->getConst(GET_UINT32_INDEX(pc));
        1357             355 :             pc += UINT32_INDEX_LEN;
        1358             355 :             if (lval == rval)
        1359               0 :                 return FindNativeCode(f, jpc + GET_JUMP_OFFSET(pc));
        1360             355 :             pc += JUMP_OFFSET_LEN;
        1361                 :         }
        1362                 :     }
        1363                 :
        1364             525 :     return FindNativeCode(f, jpc + GET_JUMP_OFFSET(jpc));
        1365                 : }
        1366                 :
        1367                 : void * JS_FASTCALL
        1368             678 : stubs::TableSwitch(VMFrame &f, jsbytecode *origPc)
        1369                 : {
        1370             678 :     jsbytecode * const originalPC = origPc;
        1371                 :
        1372            1356 :     DebugOnly<JSOp> op = JSOp(*originalPC);
        1373             678 :     JS_ASSERT(op == JSOP_TABLESWITCH);
        1374                 :
        1375             678 :     uint32_t jumpOffset = GET_JUMP_OFFSET(originalPC);
        1376             678 :     jsbytecode *pc = originalPC + JUMP_OFFSET_LEN;
        1377                 :
        1378                 :     /* Note: compiler adjusts the stack beforehand. */
        1379             678 :     Value rval = f.regs.sp[-1];
        1380                 :
        1381                 :     int32_t tableIdx;
        1382             678 :     if (rval.isInt32()) {
        1383               0 :         tableIdx = rval.toInt32();
        1384             678 :     } else if (rval.isDouble()) {
        1385             199 :         double d = rval.toDouble();
        1386             199 :         if (d == 0) {
        1387                 :             /* Treat -0 (double) as 0. */
        1388              93 :             tableIdx = 0;
        1389             106 :         } else if (!JSDOUBLE_IS_INT32(d, &tableIdx)) {
        1390              88 :             goto finally;
        1391                 :         }
        1392                 :     } else {
        1393             479 :         goto finally;
        1394                 :     }
        1395                 :
        1396                 :     {
        1397             111 :         int32_t low = GET_JUMP_OFFSET(pc);
        1398             111 :         pc += JUMP_OFFSET_LEN;
        1399             111 :         int32_t high = GET_JUMP_OFFSET(pc);
        1400             111 :         pc += JUMP_OFFSET_LEN;
        1401                 :
        1402             111 :         tableIdx -= low;
        1403             111 :         if ((uint32_t) tableIdx < (uint32_t)(high - low + 1)) {
        1404              69 :             pc += JUMP_OFFSET_LEN * tableIdx;
        1405              69 :             if (uint32_t candidateOffset = GET_JUMP_OFFSET(pc))
        1406              69 :                 jumpOffset = candidateOffset;
        1407                 :         }
        1408                 :     }
        1409                 :
        1410                 : finally:
        1411                 :     /* Provide the native address. */
        1412             678 :     return FindNativeCode(f, originalPC + jumpOffset);
        1413                 : }
        1414                 :
        1415                 : void JS_FASTCALL
        1416            1105 : stubs::Pos(VMFrame &f)
        1417                 : {
        1418            1105 :     if (!ToNumber(f.cx, &f.regs.sp[-1]))
        1419               0 :         THROW();
        1420            1105 :     if (!f.regs.sp[-1].isInt32())
        1421             436 :         TypeScript::MonitorOverflow(f.cx, f.script(), f.pc());
        1422                 : }
        1423                 :
        1424                 : void JS_FASTCALL
        1425             137 : stubs::DelName(VMFrame &f, PropertyName *name)
        1426                 : {
        1427                 :     JSObject *obj, *obj2;
        1428                 :     JSProperty *prop;
        1429             137 :     if (!FindProperty(f.cx, name, f.cx->stack.currentScriptedScopeChain(), &obj, &obj2, &prop))
        1430               0 :         THROW();
        1431                 :
        1432                 :     /* Strict mode code should never contain JSOP_DELNAME opcodes. */
        1433             137 :     JS_ASSERT(!f.script()->strictModeCode);
        1434                 :
        1435                 :     /* ECMA says to return true if name is undefined or inherited. */
        1436             137 :     f.regs.sp++;
        1437             137 :     f.regs.sp[-1] = BooleanValue(true);
        1438             137 :     if (prop) {
        1439              85 :         if (!obj->deleteProperty(f.cx, name, &f.regs.sp[-1], false))
        1440               0 :             THROW();
        1441                 :     }
        1442                 : }
        1443                 :
        1444                 : template<JSBool strict>
        1445                 : void JS_FASTCALL
        1446             266 : stubs::DelProp(VMFrame &f, PropertyName *name)
        1447                 : {
        1448             266 :     JSContext *cx = f.cx;
        1449                 :
        1450             266 :     JSObject *obj = ValueToObject(cx, f.regs.sp[-1]);
        1451             266 :     if (!obj)
        1452               0 :         THROW();
        1453                 :
        1454                 :     Value rval;
        1455             266 :     if (!obj->deleteProperty(cx, name, &rval, strict))
        1456               0 :         THROW();
        1457                 :
        1458             266 :     f.regs.sp[-1] = rval;
        1459                 : }
        1460                 :
        1461                 : template void JS_FASTCALL stubs::DelProp<true>(VMFrame &f, PropertyName *name);
        1462                 : template void JS_FASTCALL stubs::DelProp<false>(VMFrame &f, PropertyName *name);
        1463                 :
        1464                 : template<JSBool strict>
        1465                 : void JS_FASTCALL
        1466            1351 : stubs::DelElem(VMFrame &f)
        1467                 : {
        1468            1351 :     JSContext *cx = f.cx;
        1469                 :
        1470            1351 :     JSObject *obj = ValueToObject(cx, f.regs.sp[-2]);
        1471            1351 :     if (!obj)
        1472               0 :         THROW();
        1473                 :
        1474            1351 :     const Value &propval = f.regs.sp[-1];
        1475            1351 :     Value &rval = f.regs.sp[-2];
        1476                 :
        1477            1351 :     if (!obj->deleteByValue(cx, propval, &rval, strict))
        1478               2 :         THROW();
        1479                 : }
        1480                 :
        1481                 : void JS_FASTCALL
        1482           26250 : stubs::DefVarOrConst(VMFrame &f, PropertyName *dn)
        1483                 : {
        1484           26250 :     unsigned attrs = JSPROP_ENUMERATE;
        1485           26250 :     if (!f.fp()->isEvalFrame())
        1486           25488 :         attrs |= JSPROP_PERMANENT;
        1487           26250 :     if (JSOp(*f.regs.pc) == JSOP_DEFCONST)
        1488           25076 :         attrs |= JSPROP_READONLY;
        1489                 :
        1490           26250 :     JSObject &obj = f.fp()->varObj();
        1491                 :
        1492           26250 :     if (!DefVarOrConstOperation(f.cx, obj, dn, attrs))
        1493               0 :         THROW();
        1494                 : }
        1495                 :
        1496                 : void JS_FASTCALL
        1497           25062 : stubs::SetConst(VMFrame &f, PropertyName *name)
        1498                 : {
        1499           25062 :     JSContext *cx = f.cx;
        1500                 :
        1501           25062 :     JSObject *obj = &f.fp()->varObj();
        1502           25062 :     const Value &ref = f.regs.sp[-1];
        1503                 :
        1504           25062 :     if (!obj->defineProperty(cx, name, ref, JS_PropertyStub, JS_StrictPropertyStub,
        1505           25062 :                              JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY))
        1506                 :     {
        1507               0 :         THROW();
        1508                 :     }
        1509                 : }
        1510                 :
        1511                 : JSBool JS_FASTCALL
        1512          383951 : stubs::In(VMFrame &f)
        1513                 : {
        1514          383951 :     JSContext *cx = f.cx;
        1515                 :
        1516          383951 :     const Value &rref = f.regs.sp[-1];
        1517          383951 :     if (!rref.isObject()) {
        1518               7 :         js_ReportValueError(cx, JSMSG_IN_NOT_OBJECT, -1, rref, NULL);
        1519               7 :         THROWV(JS_FALSE);
        1520                 :     }
        1521                 :
        1522          383944 :     JSObject *obj = &rref.toObject();
        1523                 :     jsid id;
        1524          383944 :     if (!FetchElementId(f.cx, obj, f.regs.sp[-2], id, &f.regs.sp[-2]))
        1525               0 :         THROWV(JS_FALSE);
        1526                 :
        1527                 :     JSObject *obj2;
        1528                 :     JSProperty *prop;
        1529          383944 :     if (!obj->lookupGeneric(cx, id, &obj2, &prop))
        1530               0 :         THROWV(JS_FALSE);
        1531                 :
        1532          383944 :     return !!prop;
        1533                 : }
        1534                 :
        1535                 : template void JS_FASTCALL stubs::DelElem<true>(VMFrame &f);
        1536                 : template void JS_FASTCALL stubs::DelElem<false>(VMFrame &f);
        1537                 :
        1538                 : void JS_FASTCALL
        1539           14673 : stubs::TypeBarrierHelper(VMFrame &f, uint32_t which)
        1540                 : {
        1541           14673 :     JS_ASSERT(which == 0 || which == 1);
        1542                 :
        1543                 :     /* The actual pushed value is at sp[0], fix up the stack. See finishBarrier. */
        1544           14673 :     Value &result = f.regs.sp[-1 - (int)which];
        1545           14673 :     result = f.regs.sp[0];
        1546                 :
        1547                 :     /*
        1548                 :      * Break type barriers at this bytecode if we have added many objects to
        1549                 :      * the target already. This isn't needed if inference results for the
        1550                 :      * script have been destroyed, as we will reanalyze and prune type barriers
        1551                 :      * as they are regenerated.
        1552                 :      */
        1553           14673 :     if (f.script()->hasAnalysis() && f.script()->analysis()->ranInference()) {
        1554           29346 :         AutoEnterTypeInference enter(f.cx);
        1555           14673 :         f.script()->analysis()->breakTypeBarriers(f.cx, f.pc() - f.script()->code, false);
        1556                 :     }
        1557                 :
        1558           14673 :     TypeScript::Monitor(f.cx, f.script(), f.pc(), result);
        1559           14673 : }
        1560                 :
        1561                 : void JS_FASTCALL
        1562           13298 : stubs::StubTypeHelper(VMFrame &f, int32_t which)
        1563                 : {
        1564           13298 :     const Value &result = f.regs.sp[which];
        1565                 :
        1566           13298 :     if (f.script()->hasAnalysis() && f.script()->analysis()->ranInference()) {
        1567           26596 :         AutoEnterTypeInference enter(f.cx);
        1568           13298 :         f.script()->analysis()->breakTypeBarriers(f.cx, f.pc() - f.script()->code, false);
        1569                 :     }
        1570                 :
        1571           13298 :     TypeScript::Monitor(f.cx, f.script(), f.pc(), result);
        1572           13298 : }
        1573                 :
        1574                 : /*
        1575                 :  * Variant of TypeBarrierHelper for checking types after making a native call.
        1576                 :  * The stack is already correct, and no fixup should be performed.
        1577                 :  */
        1578                 : void JS_FASTCALL
        1579             287 : stubs::TypeBarrierReturn(VMFrame &f, Value *vp)
        1580                 : {
        1581             287 :     TypeScript::Monitor(f.cx, f.script(), f.pc(), vp[0]);
        1582             287 : }
        1583                 :
        1584                 : void JS_FASTCALL
        1585             100 : stubs::NegZeroHelper(VMFrame &f)
        1586                 : {
        1587             100 :     f.regs.sp[-1].setDouble(-0.0);
        1588             100 :     TypeScript::MonitorOverflow(f.cx, f.script(), f.pc());
        1589             100 : }
        1590                 :
        1591                 : void JS_FASTCALL
        1592             916 : stubs::CheckArgumentTypes(VMFrame &f)
        1593                 : {
        1594             916 :     StackFrame *fp = f.fp();
        1595             916 :     JSFunction *fun = fp->fun();
        1596             916 :     JSScript *script = fun->script();
        1597             916 :     RecompilationMonitor monitor(f.cx);
        1598                 :
        1599                 :     {
        1600                 :         /* Postpone recompilations until all args have been updated. */
        1601            1832 :         types::AutoEnterTypeInference enter(f.cx);
        1602                 :
        1603             916 :         if (!f.fp()->isConstructing())
        1604             898 :             TypeScript::SetThis(f.cx, script, fp->thisValue());
        1605            2337 :         for (unsigned i = 0; i < fun->nargs; i++)
        1606            1421 :             TypeScript::SetArgument(f.cx, script, i, fp->formalArg(i));
        1607                 :     }
        1608                 :
        1609             916 :     if (monitor.recompiled())
        1610              23 :         return;
        1611                 :
        1612                 : #ifdef JS_MONOIC
        1613             893 :     ic::GenerateArgumentCheckStub(f);
        1614                 : #endif
        1615                 : }
        1616                 :
        1617                 : #ifdef DEBUG
        1618                 : void JS_FASTCALL
        1619        14134094 : stubs::AssertArgumentTypes(VMFrame &f)
        1620                 : {
        1621        14134094 :     StackFrame *fp = f.fp();
        1622        14134094 :     JSFunction *fun = fp->fun();
        1623        14134094 :     JSScript *script = fun->script();
        1624                 :
        1625                 :     /*
        1626                 :      * Don't check the type of 'this' for constructor frames, the 'this' value
        1627                 :      * has not been constructed yet.
        1628                 :      */
        1629        14134094 :     if (!fp->isConstructing()) {
        1630        12397874 :         Type type = GetValueType(f.cx, fp->thisValue());
        1631        12397874 :         if (!TypeScript::ThisTypes(script)->hasType(type))
        1632               0 :             TypeFailure(f.cx, "Missing type for this: %s", TypeString(type));
        1633                 :     }
        1634                 :
        1635        38256008 :     for (unsigned i = 0; i < fun->nargs; i++) {
        1636        24121914 :         Type type = GetValueType(f.cx, fp->formalArg(i));
        1637        24121914 :         if (!TypeScript::ArgTypes(script, i)->hasType(type))
        1638               0 :             TypeFailure(f.cx, "Missing type for arg %d: %s", i, TypeString(type));
        1639                 :     }
        1640        14134094 : }
        1641                 : #endif
        1642                 :
        1643                 : /*
        1644                 :  * These two are never actually called, they just give us a place to rejoin if
        1645                 :  * there is an invariant failure when initially entering a loop.
        1646                 :  */
        1647               0 : void JS_FASTCALL stubs::MissedBoundsCheckEntry(VMFrame &f) {}
        1648               0 : void JS_FASTCALL stubs::MissedBoundsCheckHead(VMFrame &f) {}
        1649                 :
        1650                 : void * JS_FASTCALL
        1651              66 : stubs::InvariantFailure(VMFrame &f, void *rval)
        1652                 : {
        1653                 :     /*
        1654                 :      * Patch this call to the return site of the call triggering the invariant
        1655                 :      * failure (or a MissedBoundsCheck* function if the failure occurred on
        1656                 :      * initial loop entry), and trigger a recompilation which will then
        1657                 :      * redirect to the rejoin point for that call. We want to make things look
        1658                 :      * to the recompiler like we are still inside that call, and that after
        1659                 :      * recompilation we will return to the call's rejoin point.
        1660                 :      */
        1661              66 :     void *repatchCode = f.scratch;
        1662              66 :     JS_ASSERT(repatchCode);
        1663              66 :     void **frameAddr = f.returnAddressLocation();
        1664              66 :     *frameAddr = repatchCode;
        1665                 :
        1666                 :     /* Recompile the outermost script, and don't hoist any bounds checks. */
        1667              66 :     JSScript *script = f.fp()->script();
        1668              66 :     JS_ASSERT(!script->failedBoundsCheck);
        1669              66 :     script->failedBoundsCheck = true;
        1670                 :
        1671              66 :     ExpandInlineFrames(f.cx->compartment);
        1672                 :
        1673              66 :     mjit::Recompiler::clearStackReferences(f.cx->runtime->defaultFreeOp(), script);
        1674              66 :     mjit::ReleaseScriptCode(f.cx->runtime->defaultFreeOp(), script);
        1675                 :
        1676                 :     /* Return the same value (if any) as the call triggering the invariant failure. */
        1677              66 :     return rval;
        1678                 : }
        1679                 :
        1680                 : void JS_FASTCALL
        1681               0 : stubs::Exception(VMFrame &f)
        1682                 : {
        1683                 :     // Check the interrupt flag to allow interrupting deeply nested exception
        1684                 :     // handling.
        1685               0 :     if (f.cx->runtime->interrupt && !js_HandleExecutionInterrupt(f.cx))
        1686               0 :         THROW();
        1687                 :
        1688               0 :     f.regs.sp[0] = f.cx->getPendingException();
        1689               0 :     f.cx->clearPendingException();
        1690                 : }
        1691                 :
        1692                 : void JS_FASTCALL
        1693          369352 : stubs::FunctionFramePrologue(VMFrame &f)
        1694                 : {
        1695          369352 :     if (!f.fp()->functionPrologue(f.cx))
        1696               0 :         THROW();
        1697                 : }
        1698                 :
        1699                 : void JS_FASTCALL
        1700          687190 : stubs::FunctionFrameEpilogue(VMFrame &f)
        1701                 : {
        1702          687190 :     f.fp()->functionEpilogue();
        1703          687190 : }
        1704                 :
        1705                 : void JS_FASTCALL
        1706             202 : stubs::AnyFrameEpilogue(VMFrame &f)
        1707                 : {
        1708                 :     /*
        1709                 :      * On the normal execution path, emitReturn calls ScriptDebugEpilogue
        1710                 :      * and inlines ScriptEpilogue. This function implements forced early
        1711                 :      * returns, so it must have the same effect.
        1712                 :      */
        1713             202 :     bool ok = true;
        1714             202 :     if (f.cx->compartment->debugMode())
        1715             202 :         ok = js::ScriptDebugEpilogue(f.cx, f.fp(), ok);
        1716             202 :     ok = ScriptEpilogue(f.cx, f.fp(), ok);
        1717             202 :     if (!ok)
        1718               0 :         THROW();
        1719             202 :     if (f.fp()->isNonEvalFunctionFrame())
        1720             162 :         f.fp()->functionEpilogue();
        1721                 : }
        1722                 :
        1723                 : template <bool Clamped>
        1724                 : int32_t JS_FASTCALL
        1725             489 : stubs::ConvertToTypedInt(JSContext *cx, Value *vp)
        1726                 : {
        1727             489 :     JS_ASSERT(!vp->isInt32());
        1728                 :
        1729             489 :     if (vp->isDouble()) {
        1730                 :         if (Clamped)
        1731              93 :             return js_TypedArray_uint8_clamp_double(vp->toDouble());
        1732             276 :         return js_DoubleToECMAInt32(vp->toDouble());
        1733                 :     }
        1734                 :
        1735             120 :     if (vp->isNull() || vp->isObject() || vp->isUndefined())
        1736             120 :         return 0;
        1737                 :
        1738               0 :     if (vp->isBoolean())
        1739               0 :         return vp->toBoolean() ? 1 : 0;
        1740                 :
        1741               0 :     JS_ASSERT(vp->isString());
        1742                 :
        1743               0 :     int32_t i32 = 0;
        1744                 : #ifdef DEBUG
        1745                 :     bool success =
        1746                 : #endif
        1747               0 :         StringToNumberType<int32_t>(cx, vp->toString(), &i32);
        1748               0 :     JS_ASSERT(success);
        1749                 :
        1750               0 :     return i32;
        1751                 : }
        1752                 :
        1753                 : template int32_t JS_FASTCALL stubs::ConvertToTypedInt<true>(JSContext *, Value *);
        1754                 : template int32_t JS_FASTCALL stubs::ConvertToTypedInt<false>(JSContext *, Value *);
        1755                 :
        1756                 : void JS_FASTCALL
        1757              56 : stubs::ConvertToTypedFloat(JSContext *cx, Value *vp)
        1758                 : {
        1759              56 :     JS_ASSERT(!vp->isDouble() && !vp->isInt32());
        1760                 :
        1761              56 :     if (vp->isNull()) {
        1762               0 :         vp->setDouble(0);
        1763              56 :     } else if (vp->isObject() || vp->isUndefined()) {
        1764              28 :         vp->setDouble(js_NaN);
        1765              28 :     } else if (vp->isBoolean()) {
        1766               0 :         vp->setDouble(vp->toBoolean() ? 1 : 0);
        1767                 :     } else {
        1768              28 :         JS_ASSERT(vp->isString());
        1769              28 :         double d = 0;
        1770                 : #ifdef DEBUG
        1771                 :         bool success =
        1772                 : #endif
        1773              28 :             StringToNumberType<double>(cx, vp->toString(), &d);
        1774              28 :         JS_ASSERT(success);
        1775              28 :         vp->setDouble(d);
        1776                 :     }
        1777              56 : }
        1778                 :
        1779                 : void JS_FASTCALL
        1780              48 : stubs::WriteBarrier(VMFrame &f, Value *addr)
        1781                 : {
        1782              48 :     gc::MarkValueUnbarriered(f.cx->compartment->barrierTracer(), addr, "write barrier");
        1783              48 : }
        1784                 :
        1785                 : void JS_FASTCALL
        1786               2 : stubs::GCThingWriteBarrier(VMFrame &f, Value *addr)
        1787                 : {
        1788               2 :     gc::Cell *cell = (gc::Cell *)addr->toGCThing();
        1789               2 :     if (cell && !cell->isMarked())
        1790               2 :         gc::MarkValueUnbarriered(f.cx->compartment->barrierTracer(), addr, "write barrier");
        1791               2 : }

Generated by: LCOV version 1.7