LCOV - code coverage report
Current view: directory - js/src - jsscript.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 1041 886 85.1 %
Date: 2012-06-02 Functions: 49 46 93.9 %

       1                 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  * vim: set ts=8 sw=4 et tw=78:
       3                 :  *
       4                 :  * ***** BEGIN LICENSE BLOCK *****
       5                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       6                 :  *
       7                 :  * The contents of this file are subject to the Mozilla Public License Version
       8                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       9                 :  * the License. You may obtain a copy of the License at
      10                 :  * http://www.mozilla.org/MPL/
      11                 :  *
      12                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      13                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      14                 :  * for the specific language governing rights and limitations under the
      15                 :  * License.
      16                 :  *
      17                 :  * The Original Code is Mozilla Communicator client code, released
      18                 :  * March 31, 1998.
      19                 :  *
      20                 :  * The Initial Developer of the Original Code is
      21                 :  * Netscape Communications Corporation.
      22                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      23                 :  * the Initial Developer. All Rights Reserved.
      24                 :  *
      25                 :  * Contributor(s):
      26                 :  *   Nick Fitzgerald <nfitzgerald@mozilla.com>
      27                 :  *
      28                 :  * Alternatively, the contents of this file may be used under the terms of
      29                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      30                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      31                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      32                 :  * of those above. If you wish to allow use of your version of this file only
      33                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      34                 :  * use your version of this file under the terms of the MPL, indicate your
      35                 :  * decision by deleting the provisions above and replace them with the notice
      36                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      37                 :  * the provisions above, a recipient may use your version of this file under
      38                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      39                 :  *
      40                 :  * ***** END LICENSE BLOCK ***** */
      41                 : 
      42                 : /*
      43                 :  * JS script operations.
      44                 :  */
      45                 : 
      46                 : #include <string.h>
      47                 : #include "jstypes.h"
      48                 : #include "jsutil.h"
      49                 : #include "jscrashreport.h"
      50                 : #include "jsprf.h"
      51                 : #include "jsapi.h"
      52                 : #include "jsatom.h"
      53                 : #include "jscntxt.h"
      54                 : #include "jsversion.h"
      55                 : #include "jsdbgapi.h"
      56                 : #include "jsfun.h"
      57                 : #include "jsgc.h"
      58                 : #include "jsgcmark.h"
      59                 : #include "jsinterp.h"
      60                 : #include "jslock.h"
      61                 : #include "jsnum.h"
      62                 : #include "jsopcode.h"
      63                 : #include "jsscope.h"
      64                 : #include "jsscript.h"
      65                 : #if JS_HAS_XDR
      66                 : #include "jsxdrapi.h"
      67                 : #endif
      68                 : 
      69                 : #include "frontend/BytecodeEmitter.h"
      70                 : #include "frontend/Parser.h"
      71                 : #include "js/MemoryMetrics.h"
      72                 : #include "methodjit/MethodJIT.h"
      73                 : #include "methodjit/Retcon.h"
      74                 : #include "vm/Debugger.h"
      75                 : 
      76                 : #include "jsinferinlines.h"
      77                 : #include "jsinterpinlines.h"
      78                 : #include "jsobjinlines.h"
      79                 : #include "jsscriptinlines.h"
      80                 : 
      81                 : using namespace js;
      82                 : using namespace js::gc;
      83                 : using namespace js::frontend;
      84                 : 
      85                 : namespace js {
      86                 : 
      87                 : BindingKind
      88        11472851 : Bindings::lookup(JSContext *cx, JSAtom *name, unsigned *indexp) const
      89                 : {
      90        11472851 :     if (!lastBinding)
      91           93720 :         return NONE;
      92                 : 
      93                 :     Shape **spp;
      94        11379131 :     Shape *shape = Shape::search(cx, lastBinding, ATOM_TO_JSID(name), &spp);
      95        11379131 :     if (!shape)
      96        11302284 :         return NONE;
      97                 : 
      98           76847 :     if (indexp)
      99           76837 :         *indexp = shape->shortid();
     100                 : 
     101           76847 :     if (shape->getter() == CallObject::getArgOp)
     102            1870 :         return ARGUMENT;
     103           74977 :     if (shape->getter() == CallObject::getUpvarOp)
     104               0 :         return UPVAR;
     105                 : 
     106           74977 :     return shape->writable() ? VARIABLE : CONSTANT;
     107                 : }
     108                 : 
     109                 : bool
     110         2573514 : Bindings::add(JSContext *cx, JSAtom *name, BindingKind kind)
     111                 : {
     112         2573514 :     if (!ensureShape(cx))
     113               0 :         return false;
     114                 : 
     115                 :     /*
     116                 :      * We still follow 10.2.3 of ES3 and make argument and variable properties
     117                 :      * of the Call objects enumerable. ES5 reformulated all of its Clause 10 to
     118                 :      * avoid objects as activations, something we should do too.
     119                 :      */
     120         2573514 :     unsigned attrs = JSPROP_ENUMERATE | JSPROP_PERMANENT;
     121                 : 
     122                 :     uint16_t *indexp;
     123                 :     PropertyOp getter;
     124                 :     StrictPropertyOp setter;
     125         2573514 :     uint32_t slot = CallObject::RESERVED_SLOTS;
     126                 : 
     127         2573514 :     if (kind == ARGUMENT) {
     128         1419274 :         JS_ASSERT(nvars == 0);
     129         1419274 :         JS_ASSERT(nupvars == 0);
     130         1419274 :         indexp = &nargs;
     131         1419274 :         getter = CallObject::getArgOp;
     132         1419274 :         setter = CallObject::setArgOp;
     133         1419274 :         slot += nargs;
     134         1154240 :     } else if (kind == UPVAR) {
     135          148046 :         indexp = &nupvars;
     136          148046 :         getter = CallObject::getUpvarOp;
     137          148046 :         setter = CallObject::setUpvarOp;
     138          148046 :         slot = lastBinding->maybeSlot();
     139          148046 :         attrs |= JSPROP_SHARED;
     140                 :     } else {
     141         1006194 :         JS_ASSERT(kind == VARIABLE || kind == CONSTANT);
     142         1006194 :         JS_ASSERT(nupvars == 0);
     143                 : 
     144         1006194 :         indexp = &nvars;
     145         1006194 :         getter = CallObject::getVarOp;
     146         1006194 :         setter = CallObject::setVarOp;
     147         1006194 :         if (kind == CONSTANT)
     148           18686 :             attrs |= JSPROP_READONLY;
     149         1006194 :         slot += nargs + nvars;
     150                 :     }
     151                 : 
     152         2573514 :     if (*indexp == BINDING_COUNT_LIMIT) {
     153                 :         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
     154                 :                              (kind == ARGUMENT)
     155                 :                              ? JSMSG_TOO_MANY_FUN_ARGS
     156               0 :                              : JSMSG_TOO_MANY_LOCALS);
     157               0 :         return false;
     158                 :     }
     159                 : 
     160                 :     jsid id;
     161         2573514 :     if (!name) {
     162            1556 :         JS_ASSERT(kind == ARGUMENT); /* destructuring */
     163            1556 :         id = INT_TO_JSID(nargs);
     164                 :     } else {
     165         2571958 :         id = ATOM_TO_JSID(name);
     166                 :     }
     167                 : 
     168         2573514 :     StackBaseShape base(&CallClass, NULL, BaseShape::VAROBJ);
     169         2573514 :     base.updateGetterSetter(attrs, getter, setter);
     170                 : 
     171         2573514 :     UnownedBaseShape *nbase = BaseShape::getUnowned(cx, base);
     172         2573514 :     if (!nbase)
     173               0 :         return NULL;
     174                 : 
     175         2573514 :     StackShape child(nbase, id, slot, 0, attrs, Shape::HAS_SHORTID, *indexp);
     176                 : 
     177                 :     /* Shapes in bindings cannot be dictionaries. */
     178         2573514 :     Shape *shape = lastBinding->getChildBinding(cx, child);
     179         2573514 :     if (!shape)
     180               0 :         return false;
     181                 : 
     182         2573514 :     lastBinding = shape;
     183         2573514 :     ++*indexp;
     184         2573514 :     return true;
     185                 : }
     186                 : 
     187                 : Shape *
     188          703452 : Bindings::callObjectShape(JSContext *cx) const
     189                 : {
     190          703452 :     if (!hasDup())
     191          703443 :         return lastShape();
     192                 : 
     193                 :     /*
     194                 :      * Build a vector of non-duplicate properties in order from last added
     195                 :      * to first (i.e., the order we normally have iterate over Shapes). Choose
     196                 :      * the last added property in each set of dups.
     197                 :      */
     198              18 :     Vector<const Shape *> shapes(cx);
     199              18 :     HashSet<jsid> seen(cx);
     200               9 :     if (!seen.init())
     201               0 :         return NULL;
     202                 : 
     203              27 :     for (Shape::Range r = lastShape()->all(); !r.empty(); r.popFront()) {
     204              18 :         const Shape &s = r.front();
     205              18 :         HashSet<jsid>::AddPtr p = seen.lookupForAdd(s.propid());
     206              18 :         if (!p) {
     207               9 :             if (!seen.add(p, s.propid()))
     208               0 :                 return NULL;
     209               9 :             if (!shapes.append(&s))
     210               0 :                 return NULL;
     211                 :         }
     212                 :     }
     213                 : 
     214                 :     /*
     215                 :      * Now build the Shape without duplicate properties.
     216                 :      */
     217              18 :     RootedVarShape shape(cx);
     218               9 :     shape = initialShape(cx);
     219              18 :     for (int i = shapes.length() - 1; i >= 0; --i) {
     220               9 :         shape = shape->getChildBinding(cx, shapes[i]);
     221               9 :         if (!shape)
     222               0 :             return NULL;
     223                 :     }
     224                 : 
     225               9 :     return shape;
     226                 : }
     227                 : 
     228                 : bool
     229          380632 : Bindings::getLocalNameArray(JSContext *cx, Vector<JSAtom *> *namesp)
     230                 : {
     231          380632 :     JS_ASSERT(lastBinding);
     232          380632 :     JS_ASSERT(hasLocalNames());
     233                 : 
     234          380632 :     Vector<JSAtom *> &names = *namesp;
     235          380632 :     JS_ASSERT(names.empty());
     236                 : 
     237          380632 :     unsigned n = countLocalNames();
     238          380632 :     if (!names.growByUninitialized(n))
     239               0 :         return false;
     240                 : 
     241                 : #ifdef DEBUG
     242          380632 :     JSAtom * const POISON = reinterpret_cast<JSAtom *>(0xdeadbeef);
     243         1356381 :     for (unsigned i = 0; i < n; i++)
     244          975749 :         names[i] = POISON;
     245                 : #endif
     246                 : 
     247         1356381 :     for (Shape::Range r = lastBinding->all(); !r.empty(); r.popFront()) {
     248          975749 :         const Shape &shape = r.front();
     249          975749 :         unsigned index = uint16_t(shape.shortid());
     250                 : 
     251          975749 :         if (shape.getter() == CallObject::getArgOp) {
     252          510362 :             JS_ASSERT(index < nargs);
     253          465387 :         } else if (shape.getter() == CallObject::getUpvarOp) {
     254           69693 :             JS_ASSERT(index < nupvars);
     255           69693 :             index += nargs + nvars;
     256                 :         } else {
     257          395694 :             JS_ASSERT(index < nvars);
     258          395694 :             index += nargs;
     259                 :         }
     260                 : 
     261          975749 :         if (JSID_IS_ATOM(shape.propid())) {
     262          975272 :             names[index] = JSID_TO_ATOM(shape.propid());
     263                 :         } else {
     264             477 :             JS_ASSERT(JSID_IS_INT(shape.propid()));
     265             477 :             JS_ASSERT(shape.getter() == CallObject::getArgOp);
     266             477 :             names[index] = NULL;
     267                 :         }
     268                 :     }
     269                 : 
     270                 : #ifdef DEBUG
     271         1356381 :     for (unsigned i = 0; i < n; i++)
     272          975749 :         JS_ASSERT(names[i] != POISON);
     273                 : #endif
     274                 : 
     275          380632 :     return true;
     276                 : }
     277                 : 
     278                 : const Shape *
     279               0 : Bindings::lastArgument() const
     280                 : {
     281               0 :     JS_ASSERT(lastBinding);
     282                 : 
     283               0 :     const js::Shape *shape = lastVariable();
     284               0 :     if (nvars > 0) {
     285               0 :         while (shape->previous() && shape->getter() != CallObject::getArgOp)
     286               0 :             shape = shape->previous();
     287                 :     }
     288               0 :     return shape;
     289                 : }
     290                 : 
     291                 : const Shape *
     292          420026 : Bindings::lastVariable() const
     293                 : {
     294          420026 :     JS_ASSERT(lastBinding);
     295                 : 
     296          420026 :     const js::Shape *shape = lastUpvar();
     297          420026 :     if (nupvars > 0) {
     298               0 :         while (shape->getter() == CallObject::getUpvarOp)
     299               0 :             shape = shape->previous();
     300                 :     }
     301          420026 :     return shape;
     302                 : }
     303                 : 
     304                 : const Shape *
     305          420026 : Bindings::lastUpvar() const
     306                 : {
     307          420026 :     JS_ASSERT(lastBinding);
     308          420026 :     return lastBinding;
     309                 : }
     310                 : 
     311                 : void
     312         1286213 : Bindings::makeImmutable()
     313                 : {
     314         1286213 :     JS_ASSERT(lastBinding);
     315         1286213 :     JS_ASSERT(!lastBinding->inDictionary());
     316         1286213 : }
     317                 : 
     318                 : void
     319         6825145 : Bindings::trace(JSTracer *trc)
     320                 : {
     321         6825145 :     if (lastBinding)
     322         6632047 :         MarkShape(trc, &lastBinding, "shape");
     323         6825145 : }
     324                 : 
     325                 : #if JS_HAS_XDR
     326                 : 
     327                 : static bool
     328           27254 : XDRScriptConst(JSXDRState *xdr, HeapValue *vp)
     329                 : {
     330                 :     /*
     331                 :      * A script constant can be an arbitrary primitive value as they are used
     332                 :      * to implement JSOP_LOOKUPSWITCH. But they cannot be objects, see
     333                 :      * bug 407186.
     334                 :      */
     335                 :     enum ConstTag {
     336                 :         SCRIPT_INT     = 0,
     337                 :         SCRIPT_DOUBLE  = 1,
     338                 :         SCRIPT_STRING  = 2,
     339                 :         SCRIPT_TRUE    = 3,
     340                 :         SCRIPT_FALSE   = 4,
     341                 :         SCRIPT_NULL    = 5,
     342                 :         SCRIPT_VOID    = 6
     343                 :     };
     344                 : 
     345                 :     uint32_t tag;
     346           27254 :     if (xdr->mode == JSXDR_ENCODE) {
     347           25428 :         if (vp->isInt32()) {
     348             533 :             tag = SCRIPT_INT;
     349           24895 :         } else if (vp->isDouble()) {
     350             975 :             tag = SCRIPT_DOUBLE;
     351           23920 :         } else if (vp->isString()) {
     352           23920 :             tag = SCRIPT_STRING;
     353               0 :         } else if (vp->isTrue()) {
     354               0 :             tag = SCRIPT_TRUE;
     355               0 :         } else if (vp->isFalse()) {
     356               0 :             tag = SCRIPT_FALSE;
     357               0 :         } else if (vp->isNull()) {
     358               0 :             tag = SCRIPT_NULL;
     359                 :         } else {
     360               0 :             JS_ASSERT(vp->isUndefined());
     361               0 :             tag = SCRIPT_VOID;
     362                 :         }
     363                 :     }
     364                 : 
     365           27254 :     if (!JS_XDRUint32(xdr, &tag))
     366               0 :         return false;
     367                 : 
     368           27254 :     switch (tag) {
     369                 :       case SCRIPT_INT: {
     370                 :         uint32_t i;
     371             533 :         if (xdr->mode == JSXDR_ENCODE)
     372             533 :             i = uint32_t(vp->toInt32());
     373             533 :         if (!JS_XDRUint32(xdr, &i))
     374               0 :             return JS_FALSE;
     375             533 :         if (xdr->mode == JSXDR_DECODE)
     376               0 :             vp->init(Int32Value(int32_t(i)));
     377             533 :         break;
     378                 :       }
     379                 :       case SCRIPT_DOUBLE: {
     380                 :         double d;
     381             975 :         if (xdr->mode == JSXDR_ENCODE)
     382             975 :             d = vp->toDouble();
     383             975 :         if (!JS_XDRDouble(xdr, &d))
     384               0 :             return false;
     385             975 :         if (xdr->mode == JSXDR_DECODE)
     386               0 :             vp->init(DoubleValue(d));
     387             975 :         break;
     388                 :       }
     389                 :       case SCRIPT_STRING: {
     390                 :         JSString *str;
     391           25746 :         if (xdr->mode == JSXDR_ENCODE)
     392           23920 :             str = vp->toString();
     393           25746 :         if (!JS_XDRString(xdr, &str))
     394               0 :             return false;
     395           25746 :         if (xdr->mode == JSXDR_DECODE)
     396            1826 :             vp->init(StringValue(str));
     397           25746 :         break;
     398                 :       }
     399                 :       case SCRIPT_TRUE:
     400               0 :         if (xdr->mode == JSXDR_DECODE)
     401               0 :             vp->init(BooleanValue(true));
     402               0 :         break;
     403                 :       case SCRIPT_FALSE:
     404               0 :         if (xdr->mode == JSXDR_DECODE)
     405               0 :             vp->init(BooleanValue(false));
     406               0 :         break;
     407                 :       case SCRIPT_NULL:
     408               0 :         if (xdr->mode == JSXDR_DECODE)
     409               0 :             vp->init(NullValue());
     410               0 :         break;
     411                 :       case SCRIPT_VOID:
     412               0 :         if (xdr->mode == JSXDR_DECODE)
     413               0 :             vp->init(UndefinedValue());
     414               0 :         break;
     415                 :     }
     416           27254 :     return true;
     417                 : }
     418                 : 
     419                 : static const char *
     420                 : SaveScriptFilename(JSContext *cx, const char *filename);
     421                 : 
     422                 : JSBool
     423          636231 : XDRScript(JSXDRState *xdr, JSScript **scriptp)
     424                 : {
     425                 :     enum ScriptBits {
     426                 :         NoScriptRval,
     427                 :         SavedCallerFun,
     428                 :         StrictModeCode,
     429                 :         UsesEval,
     430                 :         UsesArguments,
     431                 :         OwnFilename,
     432                 :         SharedFilename
     433                 :     };
     434                 : 
     435                 :     uint32_t length, lineno, nslots;
     436                 :     uint32_t natoms, nsrcnotes, ntrynotes, nobjects, nregexps, nconsts, i;
     437                 :     uint32_t prologLength, version, encodedClosedCount;
     438          636231 :     uint16_t nClosedArgs = 0, nClosedVars = 0;
     439          636231 :     uint32_t nTypeSets = 0;
     440          636231 :     uint32_t scriptBits = 0;
     441                 : 
     442          636231 :     JSContext *cx = xdr->cx;
     443                 :     JSScript *script;
     444          636231 :     nsrcnotes = ntrynotes = natoms = nobjects = nregexps = nconsts = 0;
     445          636231 :     jssrcnote *notes = NULL;
     446                 : 
     447                 :     /* XDR arguments, local vars, and upvars. */
     448                 :     uint16_t nargs, nvars, nupvars;
     449                 : #if defined(DEBUG) || defined(__GNUC__) /* quell GCC overwarning */
     450          636231 :     script = NULL;
     451          636231 :     nargs = nvars = nupvars = Bindings::BINDING_COUNT_LIMIT;
     452                 : #endif
     453                 :     uint32_t argsVars, paddingUpvars;
     454          636231 :     if (xdr->mode == JSXDR_ENCODE) {
     455          459139 :         script = *scriptp;
     456                 : 
     457                 :         /* Should not XDR scripts optimized for a single global object. */
     458          459139 :         JS_ASSERT(!JSScript::isValidOffset(script->globalsOffset));
     459                 : 
     460          459139 :         nargs = script->bindings.countArgs();
     461          459139 :         nvars = script->bindings.countVars();
     462          459139 :         nupvars = script->bindings.countUpvars();
     463          459139 :         argsVars = (nargs << 16) | nvars;
     464          459139 :         paddingUpvars = nupvars;
     465                 :     }
     466          636231 :     if (!JS_XDRUint32(xdr, &argsVars) || !JS_XDRUint32(xdr, &paddingUpvars))
     467               0 :         return false;
     468          636231 :     if (xdr->mode == JSXDR_DECODE) {
     469          177092 :         nargs = argsVars >> 16;
     470          177092 :         nvars = argsVars & 0xFFFF;
     471          177092 :         JS_ASSERT((paddingUpvars >> 16) == 0);
     472          177092 :         nupvars = paddingUpvars & 0xFFFF;
     473                 :     }
     474          636231 :     JS_ASSERT(nargs != Bindings::BINDING_COUNT_LIMIT);
     475          636231 :     JS_ASSERT(nvars != Bindings::BINDING_COUNT_LIMIT);
     476          636231 :     JS_ASSERT(nupvars != Bindings::BINDING_COUNT_LIMIT);
     477                 : 
     478         1272462 :     Bindings bindings(cx);
     479          636231 :     uint32_t nameCount = nargs + nvars + nupvars;
     480          636231 :     if (nameCount > 0) {
     481         1045084 :         LifoAllocScope las(&cx->tempLifoAlloc());
     482                 : 
     483                 :         /*
     484                 :          * To xdr the names we prefix the names with a bitmap descriptor and
     485                 :          * then xdr the names as strings. For argument names (indexes below
     486                 :          * nargs) the corresponding bit in the bitmap is unset when the name
     487                 :          * is null. Such null names are not encoded or decoded. For variable
     488                 :          * names (indexes starting from nargs) bitmap's bit is set when the
     489                 :          * name is declared as const, not as ordinary var.
     490                 :          * */
     491          522542 :         unsigned bitmapLength = JS_HOWMANY(nameCount, JS_BITS_PER_UINT32);
     492          522542 :         uint32_t *bitmap = cx->tempLifoAlloc().newArray<uint32_t>(bitmapLength);
     493          522542 :         if (!bitmap) {
     494               0 :             js_ReportOutOfMemory(cx);
     495               0 :             return false;
     496                 :         }
     497                 : 
     498         1045084 :         Vector<JSAtom *> names(cx);
     499          522542 :         if (xdr->mode == JSXDR_ENCODE) {
     500          366634 :             if (!script->bindings.getLocalNameArray(cx, &names))
     501               0 :                 return false;
     502          366634 :             PodZero(bitmap, bitmapLength);
     503         1321935 :             for (unsigned i = 0; i < nameCount; i++) {
     504          955301 :                 if (i < nargs && names[i])
     505          495286 :                     bitmap[i >> JS_BITS_PER_UINT32_LOG2] |= JS_BIT(i & (JS_BITS_PER_UINT32 - 1));
     506                 :             }
     507                 :         }
     508         1045084 :         for (unsigned i = 0; i < bitmapLength; ++i) {
     509          522542 :             if (!JS_XDRUint32(xdr, &bitmap[i]))
     510               0 :                 return false;
     511                 :         }
     512                 : 
     513         1873584 :         for (unsigned i = 0; i < nameCount; i++) {
     514         2056035 :             if (i < nargs &&
     515          704993 :                 !(bitmap[i >> JS_BITS_PER_UINT32_LOG2] & JS_BIT(i & (JS_BITS_PER_UINT32 - 1))))
     516                 :             {
     517             432 :                 if (xdr->mode == JSXDR_DECODE) {
     518                 :                     uint16_t dummy;
     519               0 :                     if (!bindings.addDestructuring(cx, &dummy))
     520               0 :                         return false;
     521                 :                 } else {
     522             432 :                     JS_ASSERT(!names[i]);
     523                 :                 }
     524             432 :                 continue;
     525                 :             }
     526                 : 
     527                 :             JSAtom *name;
     528         1350610 :             if (xdr->mode == JSXDR_ENCODE)
     529          954869 :                 name = names[i];
     530         1350610 :             if (!js_XDRAtom(xdr, &name))
     531               0 :                 return false;
     532         1350610 :             if (xdr->mode == JSXDR_DECODE) {
     533                 :                 BindingKind kind = (i < nargs)
     534                 :                                    ? ARGUMENT
     535                 :                                    : (i < unsigned(nargs + nvars))
     536          151124 :                                    ? (bitmap[i >> JS_BITS_PER_UINT32_LOG2] &
     537                 :                                       JS_BIT(i & (JS_BITS_PER_UINT32 - 1))
     538                 :                                       ? CONSTANT
     539                 :                                       : VARIABLE)
     540          546865 :                                    : UPVAR;
     541          395741 :                 if (!bindings.add(cx, name, kind))
     542               0 :                     return false;
     543                 :             }
     544                 :         }
     545                 :     }
     546                 : 
     547          636231 :     if (xdr->mode == JSXDR_DECODE) {
     548          177092 :         if (!bindings.ensureShape(cx))
     549               0 :             return false;
     550          177092 :         bindings.makeImmutable();
     551                 :     }
     552                 : 
     553          636231 :     if (xdr->mode == JSXDR_ENCODE)
     554          459139 :         length = script->length;
     555          636231 :     if (!JS_XDRUint32(xdr, &length))
     556               0 :         return JS_FALSE;
     557                 : 
     558          636231 :     if (xdr->mode == JSXDR_ENCODE) {
     559          459139 :         prologLength = script->mainOffset;
     560          459139 :         JS_ASSERT(script->getVersion() != JSVERSION_UNKNOWN);
     561          459139 :         version = (uint32_t)script->getVersion() | (script->nfixed << 16);
     562          459139 :         lineno = (uint32_t)script->lineno;
     563          459139 :         nslots = (uint32_t)script->nslots;
     564          459139 :         nslots = (uint32_t)((script->staticLevel << 16) | script->nslots);
     565          459139 :         natoms = script->natoms;
     566                 : 
     567          459139 :         notes = script->notes();
     568          459139 :         nsrcnotes = script->numNotes();
     569                 : 
     570          459139 :         if (JSScript::isValidOffset(script->objectsOffset))
     571          186140 :             nobjects = script->objects()->length;
     572          459139 :         if (JSScript::isValidOffset(script->upvarsOffset))
     573           53645 :             JS_ASSERT(script->bindings.countUpvars() == script->upvars()->length);
     574          459139 :         if (JSScript::isValidOffset(script->regexpsOffset))
     575            6530 :             nregexps = script->regexps()->length;
     576          459139 :         if (JSScript::isValidOffset(script->trynotesOffset))
     577           90592 :             ntrynotes = script->trynotes()->length;
     578          459139 :         if (JSScript::isValidOffset(script->constOffset))
     579            5435 :             nconsts = script->consts()->length;
     580                 : 
     581          459139 :         nClosedArgs = script->nClosedArgs;
     582          459139 :         nClosedVars = script->nClosedVars;
     583          459139 :         encodedClosedCount = (nClosedArgs << 16) | nClosedVars;
     584                 : 
     585          459139 :         nTypeSets = script->nTypeSets;
     586                 : 
     587          459139 :         if (script->noScriptRval)
     588            7244 :             scriptBits |= (1 << NoScriptRval);
     589          459139 :         if (script->savedCallerFun)
     590               0 :             scriptBits |= (1 << SavedCallerFun);
     591          459139 :         if (script->strictModeCode)
     592          275992 :             scriptBits |= (1 << StrictModeCode);
     593          459139 :         if (script->usesEval)
     594            1532 :             scriptBits |= (1 << UsesEval);
     595          459139 :         if (script->usesArguments)
     596            1779 :             scriptBits |= (1 << UsesArguments);
     597          459139 :         if (script->filename) {
     598                 :             scriptBits |= (script->filename != xdr->sharedFilename)
     599                 :                           ? (1 << OwnFilename)
     600          459139 :                           : (1 << SharedFilename);
     601                 :         }
     602                 : 
     603          459139 :         JS_ASSERT(!script->compileAndGo);
     604          459139 :         JS_ASSERT(!script->hasSingletons);
     605                 :     }
     606                 : 
     607          636231 :     if (!JS_XDRUint32(xdr, &prologLength))
     608               0 :         return JS_FALSE;
     609          636231 :     if (!JS_XDRUint32(xdr, &version))
     610               0 :         return JS_FALSE;
     611                 : 
     612                 :     /*
     613                 :      * To fuse allocations, we need srcnote, atom, objects, regexp, and trynote
     614                 :      * counts early.
     615                 :      */
     616          636231 :     if (!JS_XDRUint32(xdr, &natoms))
     617               0 :         return JS_FALSE;
     618          636231 :     if (!JS_XDRUint32(xdr, &nsrcnotes))
     619               0 :         return JS_FALSE;
     620          636231 :     if (!JS_XDRUint32(xdr, &ntrynotes))
     621               0 :         return JS_FALSE;
     622          636231 :     if (!JS_XDRUint32(xdr, &nobjects))
     623               0 :         return JS_FALSE;
     624          636231 :     if (!JS_XDRUint32(xdr, &nregexps))
     625               0 :         return JS_FALSE;
     626          636231 :     if (!JS_XDRUint32(xdr, &nconsts))
     627               0 :         return JS_FALSE;
     628          636231 :     if (!JS_XDRUint32(xdr, &encodedClosedCount))
     629               0 :         return JS_FALSE;
     630          636231 :     if (!JS_XDRUint32(xdr, &nTypeSets))
     631               0 :         return JS_FALSE;
     632          636231 :     if (!JS_XDRUint32(xdr, &scriptBits))
     633               0 :         return JS_FALSE;
     634                 : 
     635          636231 :     if (xdr->mode == JSXDR_DECODE) {
     636          177092 :         nClosedArgs = encodedClosedCount >> 16;
     637          177092 :         nClosedVars = encodedClosedCount & 0xFFFF;
     638                 : 
     639                 :         /* Note: version is packed into the 32b space with another 16b value. */
     640          177092 :         JSVersion version_ = JSVersion(version & JS_BITMASK(16));
     641          177092 :         JS_ASSERT((version_ & VersionFlags::FULL_MASK) == unsigned(version_));
     642                 :         script = JSScript::NewScript(cx, length, nsrcnotes, natoms, nobjects, nupvars,
     643                 :                                      nregexps, ntrynotes, nconsts, 0, nClosedArgs,
     644          177092 :                                      nClosedVars, nTypeSets, version_);
     645          177092 :         if (!script)
     646               0 :             return JS_FALSE;
     647                 : 
     648          177092 :         script->bindings.transfer(cx, &bindings);
     649          177092 :         JS_ASSERT(!script->mainOffset);
     650          177092 :         script->mainOffset = prologLength;
     651          177092 :         script->nfixed = uint16_t(version >> 16);
     652                 : 
     653                 :         /* If we know nsrcnotes, we allocated space for notes in script. */
     654          177092 :         notes = script->notes();
     655          177092 :         *scriptp = script;
     656                 : 
     657          177092 :         if (scriptBits & (1 << NoScriptRval))
     658             541 :             script->noScriptRval = true;
     659          177092 :         if (scriptBits & (1 << SavedCallerFun))
     660               0 :             script->savedCallerFun = true;
     661          177092 :         if (scriptBits & (1 << StrictModeCode))
     662          172371 :             script->strictModeCode = true;
     663          177092 :         if (scriptBits & (1 << UsesEval))
     664             506 :             script->usesEval = true;
     665          177092 :         if (scriptBits & (1 << UsesArguments))
     666             506 :             script->usesArguments = true;
     667                 :     }
     668                 : 
     669          636231 :     if (!JS_XDRBytes(xdr, (char *)script->code, length * sizeof(jsbytecode)))
     670               0 :         return false;
     671                 : 
     672         1908693 :     if (!JS_XDRBytes(xdr, (char *)notes, nsrcnotes * sizeof(jssrcnote)) ||
     673          636231 :         !JS_XDRUint32(xdr, &lineno) ||
     674          636231 :         !JS_XDRUint32(xdr, &nslots)) {
     675               0 :         return false;
     676                 :     }
     677                 : 
     678          636231 :     if (scriptBits & (1 << OwnFilename)) {
     679                 :         char *filename;
     680          636231 :         if (xdr->mode == JSXDR_ENCODE)
     681          459139 :             filename = const_cast<char *>(script->filename);
     682          636231 :         if (!JS_XDRCString(xdr, &filename))
     683               0 :             return false;
     684          636231 :         if (xdr->mode == JSXDR_DECODE) {
     685          177092 :             script->filename = SaveScriptFilename(xdr->cx, filename);
     686          177092 :             Foreground::free_(filename);
     687          177092 :             if (!script->filename)
     688               0 :                 return false;
     689          177092 :             if (!xdr->sharedFilename)
     690            2942 :                 xdr->sharedFilename = script->filename;
     691                 :         }
     692               0 :     } else if (scriptBits & (1 << SharedFilename)) {
     693               0 :         JS_ASSERT(xdr->sharedFilename);
     694               0 :         if (xdr->mode == JSXDR_DECODE)
     695               0 :             script->filename = xdr->sharedFilename;
     696                 :     }
     697                 : 
     698          636231 :     if (xdr->mode == JSXDR_DECODE) {
     699          177092 :         JS_ASSERT(!script->principals);
     700          177092 :         JS_ASSERT(!script->originPrincipals);
     701                 : 
     702                 :         /* The origin principals must be normalized at this point. */ 
     703          177092 :         JS_ASSERT_IF(script->principals, script->originPrincipals);
     704          177092 :         if (xdr->principals) {
     705          174703 :             script->principals = xdr->principals;
     706          174703 :             JS_HoldPrincipals(xdr->principals);
     707                 :         }
     708          177092 :         if (xdr->originPrincipals) {
     709          174708 :             script->originPrincipals = xdr->originPrincipals;
     710          174708 :             JS_HoldPrincipals(xdr->originPrincipals);
     711                 :         }
     712                 :     }
     713                 : 
     714          636231 :     if (xdr->mode == JSXDR_DECODE) {
     715          177092 :         script->lineno = (unsigned)lineno;
     716          177092 :         script->nslots = uint16_t(nslots);
     717          177092 :         script->staticLevel = uint16_t(nslots >> 16);
     718                 :     }
     719                 : 
     720         9892487 :     for (i = 0; i != natoms; ++i) {
     721         9256256 :         if (!js_XDRAtom(xdr, &script->atoms[i]))
     722               0 :             return false;
     723                 :     }
     724                 : 
     725                 :     /*
     726                 :      * Here looping from 0-to-length to xdr objects is essential. It ensures
     727                 :      * that block objects from the script->objects array will be written and
     728                 :      * restored in the outer-to-inner order. js_XDRBlockObject relies on this
     729                 :      * to restore the parent chain.
     730                 :      */
     731         1619620 :     for (i = 0; i != nobjects; ++i) {
     732          983389 :         HeapPtr<JSObject> *objp = &script->objects()->vector[i];
     733                 :         uint32_t isBlock;
     734          983389 :         if (xdr->mode == JSXDR_ENCODE) {
     735          695699 :             JSObject *obj = *objp;
     736          695699 :             JS_ASSERT(obj->isFunction() || obj->isStaticBlock());
     737          695699 :             isBlock = obj->isBlock() ? 1 : 0;
     738                 :         }
     739          983389 :         if (!JS_XDRUint32(xdr, &isBlock))
     740               0 :             return false;
     741          983389 :         if (isBlock == 0) {
     742          623614 :             JSObject *tmp = *objp;
     743          623614 :             if (!XDRFunctionObject(xdr, &tmp))
     744               0 :                 return false;
     745          623614 :             *objp = tmp;
     746                 :         } else {
     747          359775 :             JS_ASSERT(isBlock == 1);
     748          359775 :             StaticBlockObject *tmp = static_cast<StaticBlockObject *>(objp->get());
     749          359775 :             if (!XDRStaticBlockObject(xdr, script, &tmp))
     750               0 :                 return false;
     751          359775 :             *objp = tmp;
     752                 :         }
     753                 :     }
     754          741043 :     for (i = 0; i != nupvars; ++i) {
     755          104812 :         if (!JS_XDRUint32(xdr, reinterpret_cast<uint32_t *>(&script->upvars()->vector[i])))
     756               0 :             return false;
     757                 :     }
     758          654759 :     for (i = 0; i != nregexps; ++i) {
     759           18528 :         if (!XDRScriptRegExpObject(xdr, &script->regexps()->vector[i]))
     760               0 :             return false;
     761                 :     }
     762          738728 :     for (i = 0; i != nClosedArgs; ++i) {
     763          102497 :         if (!JS_XDRUint32(xdr, &script->closedSlots[i]))
     764               0 :             return false;
     765                 :     }
     766          722351 :     for (i = 0; i != nClosedVars; ++i) {
     767           86120 :         if (!JS_XDRUint32(xdr, &script->closedSlots[nClosedArgs + i]))
     768               0 :             return false;
     769                 :     }
     770                 : 
     771          636231 :     if (ntrynotes != 0) {
     772                 :         /*
     773                 :          * We combine tn->kind and tn->stackDepth when serializing as XDR is not
     774                 :          * efficient when serializing small integer types.
     775                 :          */
     776                 :         JSTryNote *tn, *tnfirst;
     777                 :         uint32_t kindAndDepth;
     778                 :         JS_STATIC_ASSERT(sizeof(tn->kind) == sizeof(uint8_t));
     779                 :         JS_STATIC_ASSERT(sizeof(tn->stackDepth) == sizeof(uint16_t));
     780                 : 
     781          130334 :         tnfirst = script->trynotes()->vector;
     782          130334 :         JS_ASSERT(script->trynotes()->length == ntrynotes);
     783          130334 :         tn = tnfirst + ntrynotes;
     784          213625 :         do {
     785          213625 :             --tn;
     786          213625 :             if (xdr->mode == JSXDR_ENCODE) {
     787                 :                 kindAndDepth = (uint32_t(tn->kind) << 16)
     788          145713 :                                | uint32_t(tn->stackDepth);
     789                 :             }
     790          640875 :             if (!JS_XDRUint32(xdr, &kindAndDepth) ||
     791          213625 :                 !JS_XDRUint32(xdr, &tn->start) ||
     792          213625 :                 !JS_XDRUint32(xdr, &tn->length)) {
     793               0 :                 return false;
     794                 :             }
     795          213625 :             if (xdr->mode == JSXDR_DECODE) {
     796           67912 :                 tn->kind = uint8_t(kindAndDepth >> 16);
     797           67912 :                 tn->stackDepth = uint16_t(kindAndDepth);
     798                 :             }
     799                 :         } while (tn != tnfirst);
     800                 :     }
     801                 : 
     802          636231 :     if (nconsts) {
     803            5985 :         HeapValue *vector = script->consts()->vector;
     804           33239 :         for (i = 0; i != nconsts; ++i) {
     805           27254 :             if (!XDRScriptConst(xdr, &vector[i]))
     806               0 :                 return false;
     807                 :         }
     808                 :     }
     809                 : 
     810          636231 :     if (xdr->mode == JSXDR_DECODE) {
     811          177092 :         if (cx->hasRunOption(JSOPTION_PCCOUNT))
     812               0 :             (void) script->initCounts(cx);
     813          177092 :         *scriptp = script;
     814                 :     }
     815                 : 
     816          636231 :     return true;
     817                 : }
     818                 : 
     819                 : #endif /* JS_HAS_XDR */
     820                 : 
     821                 : } /* namespace js */
     822                 : 
     823                 : bool
     824               0 : JSScript::initCounts(JSContext *cx)
     825                 : {
     826               0 :     JS_ASSERT(!pcCounters);
     827                 : 
     828               0 :     size_t count = 0;
     829                 : 
     830                 :     jsbytecode *pc, *next;
     831               0 :     for (pc = code; pc < code + length; pc = next) {
     832               0 :         count += OpcodeCounts::numCounts(JSOp(*pc));
     833               0 :         next = pc + GetBytecodeLength(pc);
     834                 :     }
     835                 : 
     836               0 :     size_t bytes = (length * sizeof(OpcodeCounts)) + (count * sizeof(double));
     837               0 :     char *cursor = (char *) cx->calloc_(bytes);
     838               0 :     if (!cursor)
     839               0 :         return false;
     840                 : 
     841               0 :     DebugOnly<char *> base = cursor;
     842                 : 
     843               0 :     pcCounters.counts = (OpcodeCounts *) cursor;
     844               0 :     cursor += length * sizeof(OpcodeCounts);
     845                 : 
     846               0 :     for (pc = code; pc < code + length; pc = next) {
     847               0 :         pcCounters.counts[pc - code].counts = (double *) cursor;
     848               0 :         size_t capacity = OpcodeCounts::numCounts(JSOp(*pc));
     849                 : #ifdef DEBUG
     850               0 :         pcCounters.counts[pc - code].capacity = capacity;
     851                 : #endif
     852               0 :         cursor += capacity * sizeof(double);
     853               0 :         next = pc + GetBytecodeLength(pc);
     854                 :     }
     855                 : 
     856               0 :     JS_ASSERT(size_t(cursor - base) == bytes);
     857                 : 
     858                 :     /* Enable interrupts in any interpreter frames running on this script. */
     859                 :     InterpreterFrames *frames;
     860               0 :     for (frames = cx->runtime->interpreterFrames; frames; frames = frames->older)
     861               0 :         frames->enableInterruptsIfRunning(this);
     862                 : 
     863               0 :     return true;
     864                 : }
     865                 : 
     866                 : void
     867         1324353 : JSScript::destroyCounts(JSContext *cx)
     868                 : {
     869         1324353 :     if (pcCounters) {
     870               0 :         cx->free_(pcCounters.counts);
     871               0 :         pcCounters.counts = NULL;
     872                 :     }
     873         1324353 : }
     874                 : 
     875                 : namespace js {
     876                 : 
     877                 : /*
     878                 :  * Shared script filename management.
     879                 :  */
     880                 : 
     881                 : static const char *
     882         1286209 : SaveScriptFilename(JSContext *cx, const char *filename)
     883                 : {
     884         1286209 :     JSCompartment *comp = cx->compartment;
     885                 : 
     886         1286209 :     ScriptFilenameTable::AddPtr p = comp->scriptFilenameTable.lookupForAdd(filename);
     887         1286209 :     if (!p) {
     888           78536 :         size_t size = offsetof(ScriptFilenameEntry, filename) + strlen(filename) + 1;
     889           78536 :         ScriptFilenameEntry *entry = (ScriptFilenameEntry *) cx->malloc_(size);
     890           78536 :         if (!entry)
     891               0 :             return NULL;
     892           78536 :         entry->marked = false;
     893           78536 :         strcpy(entry->filename, filename);
     894                 : 
     895           78536 :         if (!comp->scriptFilenameTable.add(p, entry)) {
     896               0 :             Foreground::free_(entry);
     897               0 :             JS_ReportOutOfMemory(cx);
     898               0 :             return NULL;
     899                 :         }
     900                 :     }
     901                 : 
     902         1286209 :     ScriptFilenameEntry *sfe = *p;
     903                 : #ifdef JSGC_INCREMENTAL
     904                 :     /*
     905                 :      * During the IGC we need to ensure that filename is marked whenever it is
     906                 :      * accessed even if the name was already in the table. At this point old
     907                 :      * scripts or exceptions pointing to the filename may no longer be
     908                 :      * reachable.
     909                 :      */
     910         1286209 :     if (comp->needsBarrier() && !sfe->marked)
     911              55 :         sfe->marked = true;
     912                 : #endif
     913                 : 
     914         1286209 :     return sfe->filename;
     915                 : }
     916                 : 
     917                 : } /* namespace js */
     918                 : 
     919                 : /*
     920                 :  * Back up from a saved filename by its offset within its hash table entry.
     921                 :  */
     922                 : #define FILENAME_TO_SFE(fn) \
     923                 :     ((ScriptFilenameEntry *) ((fn) - offsetof(ScriptFilenameEntry, filename)))
     924                 : 
     925                 : void
     926         6567533 : js_MarkScriptFilename(const char *filename)
     927                 : {
     928         6567533 :     ScriptFilenameEntry *sfe = FILENAME_TO_SFE(filename);
     929         6567533 :     sfe->marked = true;
     930         6567533 : }
     931                 : 
     932                 : void
     933          122478 : js_SweepScriptFilenames(JSCompartment *comp)
     934                 : {
     935          122478 :     ScriptFilenameTable &table = comp->scriptFilenameTable;
     936          388368 :     for (ScriptFilenameTable::Enum e(table); !e.empty(); e.popFront()) {
     937          265890 :         ScriptFilenameEntry *entry = e.front();
     938          265890 :         if (entry->marked) {
     939          187351 :             entry->marked = false;
     940           78539 :         } else if (!comp->rt->gcKeepAtoms) {
     941           78461 :             Foreground::free_(entry);
     942           78461 :             e.removeFront();
     943                 :         }
     944                 :     }
     945          122478 : }
     946                 : 
     947                 : /*
     948                 :  * JSScript data structures memory alignment:
     949                 :  *
     950                 :  * JSScript
     951                 :  * JSObjectArray    script objects' descriptor if JSScript.objectsOffset != 0,
     952                 :  *                    use script->objects() to access it.
     953                 :  * JSObjectArray    script regexps' descriptor if JSScript.regexpsOffset != 0,
     954                 :  *                    use script->regexps() to access it.
     955                 :  * JSTryNoteArray   script try notes' descriptor if JSScript.tryNotesOffset
     956                 :  *                    != 0, use script->trynotes() to access it.
     957                 :  * JSAtom *a[]      array of JSScript.natoms atoms pointed by
     958                 :  *                    JSScript.atoms if any.
     959                 :  * JSObject *o[]    array of script->objects()->length objects if any
     960                 :  *                    pointed by script->objects()->vector.
     961                 :  * JSObject *r[]    array of script->regexps()->length regexps if any
     962                 :  *                    pointed by script->regexps()->vector.
     963                 :  * JSTryNote t[]    array of script->trynotes()->length try notes if any
     964                 :  *                    pointed by script->trynotes()->vector.
     965                 :  * jsbytecode b[]   script bytecode pointed by JSScript.code.
     966                 :  * jssrcnote  s[]   script source notes, use script->notes() to access it
     967                 :  *
     968                 :  * The alignment avoids gaps between entries as alignment requirement for each
     969                 :  * subsequent structure or array is the same or divides the alignment
     970                 :  * requirement for the previous one.
     971                 :  *
     972                 :  * The followings asserts checks that assuming that the alignment requirement
     973                 :  * for JSObjectArray and JSTryNoteArray are sizeof(void *) and for JSTryNote
     974                 :  * it is sizeof(uint32_t) as the structure consists of 3 uint32_t fields.
     975                 :  */
     976                 : JS_STATIC_ASSERT(sizeof(JSScript) % sizeof(void *) == 0);
     977                 : JS_STATIC_ASSERT(sizeof(JSObjectArray) % sizeof(void *) == 0);
     978                 : JS_STATIC_ASSERT(sizeof(JSTryNoteArray) == sizeof(JSObjectArray));
     979                 : JS_STATIC_ASSERT(sizeof(JSAtom *) == sizeof(JSObject *));
     980                 : JS_STATIC_ASSERT(sizeof(JSObject *) % sizeof(uint32_t) == 0);
     981                 : JS_STATIC_ASSERT(sizeof(JSTryNote) == 3 * sizeof(uint32_t));
     982                 : JS_STATIC_ASSERT(sizeof(uint32_t) % sizeof(jsbytecode) == 0);
     983                 : JS_STATIC_ASSERT(sizeof(jsbytecode) % sizeof(jssrcnote) == 0);
     984                 : 
     985                 : /*
     986                 :  * Check that uint8_t offsets is enough to reach any optional array allocated
     987                 :  * after JSScript. For that we check that the maximum possible offset for
     988                 :  * JSConstArray, that last optional array, still fits 1 byte and do not
     989                 :  * coincide with INVALID_OFFSET.
     990                 :  */
     991                 : JS_STATIC_ASSERT(sizeof(JSObjectArray) +
     992                 :                  sizeof(JSUpvarArray) +
     993                 :                  sizeof(JSObjectArray) +
     994                 :                  sizeof(JSTryNoteArray) +
     995                 :                  sizeof(js::GlobalSlotArray)
     996                 :                  < JSScript::INVALID_OFFSET);
     997                 : JS_STATIC_ASSERT(JSScript::INVALID_OFFSET <= 255);
     998                 : 
     999                 : JSScript *
    1000         1324850 : JSScript::NewScript(JSContext *cx, uint32_t length, uint32_t nsrcnotes, uint32_t natoms,
    1001                 :                     uint32_t nobjects, uint32_t nupvars, uint32_t nregexps,
    1002                 :                     uint32_t ntrynotes, uint32_t nconsts, uint32_t nglobals,
    1003                 :                     uint16_t nClosedArgs, uint16_t nClosedVars, uint32_t nTypeSets, JSVersion version)
    1004                 : {
    1005         1324850 :     size_t size = sizeof(JSAtom *) * natoms;
    1006         1324850 :     if (nobjects != 0)
    1007          470954 :         size += sizeof(JSObjectArray) + nobjects * sizeof(JSObject *);
    1008         1324850 :     if (nupvars != 0)
    1009          112447 :         size += sizeof(JSUpvarArray) + nupvars * sizeof(uint32_t);
    1010         1324850 :     if (nregexps != 0)
    1011           18673 :         size += sizeof(JSObjectArray) + nregexps * sizeof(JSObject *);
    1012         1324850 :     if (ntrynotes != 0)
    1013          181686 :         size += sizeof(JSTryNoteArray) + ntrynotes * sizeof(JSTryNote);
    1014         1324850 :     if (nglobals != 0)
    1015           12799 :         size += sizeof(GlobalSlotArray) + nglobals * sizeof(GlobalSlotArray::Entry);
    1016         1324850 :     uint32_t totalClosed = nClosedArgs + nClosedVars;
    1017         1324850 :     if (totalClosed != 0)
    1018          149939 :         size += totalClosed * sizeof(uint32_t);
    1019                 : 
    1020                 :     /*
    1021                 :      * To esnure jsval alignment for the const array we place it immediately
    1022                 :      * after JSSomethingArray structs as their sizes all divide sizeof(jsval).
    1023                 :      * This works as long as the data itself is allocated with proper
    1024                 :      * alignment which we ensure below.
    1025                 :      */
    1026                 :     JS_STATIC_ASSERT(sizeof(JSObjectArray) % sizeof(jsval) == 0);
    1027                 :     JS_STATIC_ASSERT(sizeof(JSUpvarArray) % sizeof(jsval) == 0);
    1028                 :     JS_STATIC_ASSERT(sizeof(JSTryNoteArray) % sizeof(jsval) == 0);
    1029                 :     JS_STATIC_ASSERT(sizeof(GlobalSlotArray) % sizeof(jsval) == 0);
    1030                 :     JS_STATIC_ASSERT(sizeof(JSConstArray) % sizeof(jsval) == 0);
    1031         1324850 :     if (nconsts != 0)
    1032           13348 :         size += sizeof(JSConstArray) + nconsts * sizeof(Value);
    1033                 : 
    1034         1324850 :     size += length * sizeof(jsbytecode) + nsrcnotes * sizeof(jssrcnote);
    1035                 : 
    1036         1324850 :     uint8_t *data = NULL;
    1037                 : #if JS_SCRIPT_INLINE_DATA_LIMIT
    1038                 :     if (size <= JS_SCRIPT_INLINE_DATA_LIMIT) {
    1039                 :         /*
    1040                 :          * Check that if inlineData is big enough to store const values, we
    1041                 :          * can do that without any special alignment requirements given that
    1042                 :          * the script as a GC thing is always aligned on Cell::CellSize.
    1043                 :          */
    1044                 :         JS_STATIC_ASSERT(Cell::CellSize % sizeof(Value) == 0);
    1045                 :         JS_STATIC_ASSERT(JS_SCRIPT_INLINE_DATA_LIMIT < sizeof(Value) ||
    1046                 :                          offsetof(JSScript, inlineData) % sizeof(Value) == 0);
    1047                 :     } else
    1048                 : #endif
    1049                 :     {
    1050                 :         /*
    1051                 :          * We assume that calloc aligns on sizeof(Value) if the size we ask to
    1052                 :          * allocate divides sizeof(Value).
    1053                 :          */
    1054                 :         JS_STATIC_ASSERT(sizeof(Value) == sizeof(double));
    1055         1324850 :         data = static_cast<uint8_t *>(cx->calloc_(JS_ROUNDUP(size, sizeof(Value))));
    1056         1324850 :         if (!data)
    1057               0 :             return NULL;
    1058                 :     }
    1059                 : 
    1060         1324850 :     JSScript *script = js_NewGCScript(cx);
    1061         1324850 :     if (!script) {
    1062               0 :         Foreground::free_(data);
    1063               0 :         return NULL;
    1064                 :     }
    1065                 : 
    1066         1324850 :     PodZero(script);
    1067                 : #ifdef JS_CRASH_DIAGNOSTICS
    1068         1324850 :     script->cookie1[0] = script->cookie2[0] = JS_SCRIPT_COOKIE;
    1069                 : #endif
    1070                 : #if JS_SCRIPT_INLINE_DATA_LIMIT
    1071                 :     if (!data)
    1072                 :         data = script->inlineData;
    1073                 : #endif
    1074         1324850 :     script->data  = data;
    1075         1324850 :     script->length = length;
    1076         1324850 :     script->version = version;
    1077         1324850 :     new (&script->bindings) Bindings(cx);
    1078                 : 
    1079         1324850 :     uint8_t *cursor = data;
    1080         1324850 :     if (nobjects != 0) {
    1081          470954 :         script->objectsOffset = uint8_t(cursor - data);
    1082          470954 :         cursor += sizeof(JSObjectArray);
    1083                 :     } else {
    1084          853896 :         script->objectsOffset = JSScript::INVALID_OFFSET;
    1085                 :     }
    1086         1324850 :     if (nupvars != 0) {
    1087          112447 :         script->upvarsOffset = uint8_t(cursor - data);
    1088          112447 :         cursor += sizeof(JSUpvarArray);
    1089                 :     } else {
    1090         1212403 :         script->upvarsOffset = JSScript::INVALID_OFFSET;
    1091                 :     }
    1092         1324850 :     if (nregexps != 0) {
    1093           18673 :         script->regexpsOffset = uint8_t(cursor - data);
    1094           18673 :         cursor += sizeof(JSObjectArray);
    1095                 :     } else {
    1096         1306177 :         script->regexpsOffset = JSScript::INVALID_OFFSET;
    1097                 :     }
    1098         1324850 :     if (ntrynotes != 0) {
    1099          181686 :         script->trynotesOffset = uint8_t(cursor - data);
    1100          181686 :         cursor += sizeof(JSTryNoteArray);
    1101                 :     } else {
    1102         1143164 :         script->trynotesOffset = JSScript::INVALID_OFFSET;
    1103                 :     }
    1104         1324850 :     if (nglobals != 0) {
    1105           12799 :         script->globalsOffset = uint8_t(cursor - data);
    1106           12799 :         cursor += sizeof(GlobalSlotArray);
    1107                 :     } else {
    1108         1312051 :         script->globalsOffset = JSScript::INVALID_OFFSET;
    1109                 :     }
    1110         1324850 :     JS_ASSERT(cursor - data < 0xFF);
    1111         1324850 :     if (nconsts != 0) {
    1112           13348 :         script->constOffset = uint8_t(cursor - data);
    1113           13348 :         cursor += sizeof(JSConstArray);
    1114                 :     } else {
    1115         1311502 :         script->constOffset = JSScript::INVALID_OFFSET;
    1116                 :     }
    1117                 : 
    1118                 :     JS_STATIC_ASSERT(sizeof(JSObjectArray) +
    1119                 :                      sizeof(JSUpvarArray) +
    1120                 :                      sizeof(JSObjectArray) +
    1121                 :                      sizeof(JSTryNoteArray) +
    1122                 :                      sizeof(GlobalSlotArray) < 0xFF);
    1123                 : 
    1124                 : 
    1125         1324850 :     if (nconsts != 0) {
    1126           13348 :         JS_ASSERT(reinterpret_cast<uintptr_t>(cursor) % sizeof(jsval) == 0);
    1127           13348 :         script->consts()->length = nconsts;
    1128           13348 :         script->consts()->vector = (HeapValue *)cursor;
    1129           13348 :         cursor += nconsts * sizeof(script->consts()->vector[0]);
    1130                 :     }
    1131                 : 
    1132         1324850 :     if (natoms != 0) {
    1133         1178782 :         script->natoms = natoms;
    1134         1178782 :         script->atoms = reinterpret_cast<JSAtom **>(cursor);
    1135         1178782 :         cursor += natoms * sizeof(script->atoms[0]);
    1136                 :     }
    1137                 : 
    1138         1324850 :     if (nobjects != 0) {
    1139          470954 :         script->objects()->length = nobjects;
    1140          470954 :         script->objects()->vector = (HeapPtr<JSObject> *)cursor;
    1141          470954 :         cursor += nobjects * sizeof(script->objects()->vector[0]);
    1142                 :     }
    1143                 : 
    1144         1324850 :     if (nregexps != 0) {
    1145           18673 :         script->regexps()->length = nregexps;
    1146           18673 :         script->regexps()->vector = (HeapPtr<JSObject> *)cursor;
    1147           18673 :         cursor += nregexps * sizeof(script->regexps()->vector[0]);
    1148                 :     }
    1149                 : 
    1150         1324850 :     if (ntrynotes != 0) {
    1151          181686 :         script->trynotes()->length = ntrynotes;
    1152          181686 :         script->trynotes()->vector = reinterpret_cast<JSTryNote *>(cursor);
    1153          181686 :         size_t vectorSize = ntrynotes * sizeof(script->trynotes()->vector[0]);
    1154                 : #ifdef DEBUG
    1155          181686 :         memset(cursor, 0, vectorSize);
    1156                 : #endif
    1157          181686 :         cursor += vectorSize;
    1158                 :     }
    1159                 : 
    1160         1324850 :     if (nglobals != 0) {
    1161           12799 :         script->globals()->length = nglobals;
    1162           12799 :         script->globals()->vector = reinterpret_cast<GlobalSlotArray::Entry *>(cursor);
    1163           12799 :         cursor += nglobals * sizeof(script->globals()->vector[0]);
    1164                 :     }
    1165                 : 
    1166         1324850 :     if (totalClosed != 0) {
    1167          149939 :         script->nClosedArgs = nClosedArgs;
    1168          149939 :         script->nClosedVars = nClosedVars;
    1169          149939 :         script->closedSlots = reinterpret_cast<uint32_t *>(cursor);
    1170          149939 :         cursor += totalClosed * sizeof(uint32_t);
    1171                 :     }
    1172                 : 
    1173         1324850 :     JS_ASSERT(nTypeSets <= UINT16_MAX);
    1174         1324850 :     script->nTypeSets = uint16_t(nTypeSets);
    1175                 : 
    1176                 :     /*
    1177                 :      * NB: We allocate the vector of uint32_t upvar cookies after all vectors of
    1178                 :      * pointers, to avoid misalignment on 64-bit platforms. See bug 514645.
    1179                 :      */
    1180         1324850 :     if (nupvars != 0) {
    1181          112447 :         script->upvars()->length = nupvars;
    1182          112447 :         script->upvars()->vector = reinterpret_cast<UpvarCookie *>(cursor);
    1183          112447 :         cursor += nupvars * sizeof(script->upvars()->vector[0]);
    1184                 :     }
    1185                 : 
    1186         1324850 :     script->code = (jsbytecode *)cursor;
    1187         1324850 :     JS_ASSERT(cursor + length * sizeof(jsbytecode) + nsrcnotes * sizeof(jssrcnote) == data + size);
    1188                 : 
    1189                 : #ifdef DEBUG
    1190         1324850 :     script->id_ = 0;
    1191                 : #endif
    1192                 : 
    1193         1324850 :     JS_ASSERT(script->getVersion() == version);
    1194         1324850 :     return script;
    1195                 : }
    1196                 : 
    1197                 : JSScript *
    1198         1109121 : JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce)
    1199                 : {
    1200                 :     uint32_t mainLength, prologLength, nfixed;
    1201                 :     JSScript *script;
    1202                 :     const char *filename;
    1203                 :     JSFunction *fun;
    1204                 : 
    1205                 :     /* The counts of indexed things must be checked during code generation. */
    1206         1109121 :     JS_ASSERT(bce->atomIndices->count() <= INDEX_LIMIT);
    1207         1109121 :     JS_ASSERT(bce->objectList.length <= INDEX_LIMIT);
    1208         1109121 :     JS_ASSERT(bce->regexpList.length <= INDEX_LIMIT);
    1209                 : 
    1210         1109121 :     mainLength = bce->offset();
    1211         1109121 :     prologLength = bce->prologOffset();
    1212                 : 
    1213         1109121 :     if (!bce->bindings.ensureShape(cx))
    1214               0 :         return NULL;
    1215                 : 
    1216         1109121 :     uint32_t nsrcnotes = uint32_t(bce->countFinalSourceNotes());
    1217         1109121 :     uint16_t nClosedArgs = uint16_t(bce->closedArgs.length());
    1218         1109121 :     JS_ASSERT(nClosedArgs == bce->closedArgs.length());
    1219         1109121 :     uint16_t nClosedVars = uint16_t(bce->closedVars.length());
    1220         1109121 :     JS_ASSERT(nClosedVars == bce->closedVars.length());
    1221         1109121 :     size_t upvarIndexCount = bce->upvarIndices.hasMap() ? bce->upvarIndices->count() : 0;
    1222                 :     script = NewScript(cx, prologLength + mainLength, nsrcnotes,
    1223                 :                        bce->atomIndices->count(), bce->objectList.length,
    1224                 :                        upvarIndexCount, bce->regexpList.length,
    1225                 :                        bce->ntrynotes, bce->constList.length(),
    1226                 :                        bce->globalUses.length(), nClosedArgs, nClosedVars,
    1227         1109121 :                        bce->typesetCount, bce->version());
    1228         1109121 :     if (!script)
    1229               0 :         return NULL;
    1230                 : 
    1231         1109121 :     bce->bindings.makeImmutable();
    1232                 : 
    1233         1109121 :     JS_ASSERT(script->mainOffset == 0);
    1234         1109121 :     script->mainOffset = prologLength;
    1235         1109121 :     PodCopy<jsbytecode>(script->code, bce->prologBase(), prologLength);
    1236         1109121 :     PodCopy<jsbytecode>(script->main(), bce->base(), mainLength);
    1237         1109121 :     nfixed = bce->inFunction() ? bce->bindings.countVars() : 0;
    1238         1109121 :     JS_ASSERT(nfixed < SLOTNO_LIMIT);
    1239         1109121 :     script->nfixed = uint16_t(nfixed);
    1240         1109121 :     js_InitAtomMap(cx, bce->atomIndices.getMap(), script->atoms);
    1241                 : 
    1242         1109121 :     filename = bce->parser->tokenStream.getFilename();
    1243         1109121 :     if (filename) {
    1244         1109117 :         script->filename = SaveScriptFilename(cx, filename);
    1245         1109117 :         if (!script->filename)
    1246               0 :             return NULL;
    1247                 :     }
    1248         1109121 :     script->lineno = bce->firstLine;
    1249         1109121 :     if (script->nfixed + bce->maxStackDepth >= JS_BIT(16)) {
    1250                 :         ReportCompileErrorNumber(cx, bce->tokenStream(), NULL, JSREPORT_ERROR, JSMSG_NEED_DIET,
    1251               0 :                                  "script");
    1252               0 :         return NULL;
    1253                 :     }
    1254         1109121 :     script->nslots = script->nfixed + bce->maxStackDepth;
    1255         1109121 :     script->staticLevel = uint16_t(bce->staticLevel);
    1256         1109121 :     script->principals = bce->parser->principals;
    1257                 : 
    1258         1109121 :     if (script->principals)
    1259          890705 :         JS_HoldPrincipals(script->principals);
    1260                 : 
    1261                 :     /* Establish invariant: principals implies originPrincipals. */
    1262         1109121 :     script->originPrincipals = bce->parser->originPrincipals;
    1263         1109121 :     if (!script->originPrincipals)
    1264         1108591 :         script->originPrincipals = script->principals;
    1265         1109121 :     if (script->originPrincipals)
    1266          890711 :         JS_HoldPrincipals(script->originPrincipals);
    1267                 : 
    1268         1109121 :     script->sourceMap = (jschar *) bce->parser->tokenStream.releaseSourceMap();
    1269                 : 
    1270         1109121 :     if (!FinishTakingSrcNotes(cx, bce, script->notes()))
    1271               0 :         return NULL;
    1272         1109121 :     if (bce->ntrynotes != 0)
    1273          141944 :         FinishTakingTryNotes(bce, script->trynotes());
    1274         1109121 :     if (bce->objectList.length != 0)
    1275          386133 :         bce->objectList.finish(script->objects());
    1276         1109121 :     if (bce->regexpList.length != 0)
    1277           16561 :         bce->regexpList.finish(script->regexps());
    1278         1109121 :     if (bce->constList.length() != 0)
    1279           12798 :         bce->constList.finish(script->consts());
    1280         1109121 :     if (bce->flags & TCF_NO_SCRIPT_RVAL)
    1281           48924 :         script->noScriptRval = true;
    1282         1109121 :     if (bce->flags & TCF_STRICT_MODE_CODE)
    1283          364963 :         script->strictModeCode = true;
    1284         1109121 :     if (bce->flags & TCF_COMPILE_N_GO) {
    1285          219176 :         script->compileAndGo = true;
    1286          219176 :         const StackFrame *fp = bce->parser->callerFrame;
    1287          219176 :         if (fp && fp->isFunctionFrame())
    1288           30760 :             script->savedCallerFun = true;
    1289                 :     }
    1290         1109121 :     if (bce->callsEval())
    1291            8074 :         script->usesEval = true;
    1292         1109121 :     if (bce->flags & TCF_FUN_USES_ARGUMENTS)
    1293           11913 :         script->usesArguments = true;
    1294         1109121 :     if (bce->flags & TCF_HAS_SINGLETONS)
    1295           30620 :         script->hasSingletons = true;
    1296                 : 
    1297         1109121 :     if (bce->hasUpvarIndices()) {
    1298           83617 :         JS_ASSERT(bce->upvarIndices->count() <= bce->upvarMap.length());
    1299           83617 :         PodCopy<UpvarCookie>(script->upvars()->vector, bce->upvarMap.begin(),
    1300          167234 :                              bce->upvarIndices->count());
    1301           83617 :         bce->upvarIndices->clear();
    1302           83617 :         bce->upvarMap.clear();
    1303                 :     }
    1304                 : 
    1305         1109121 :     if (bce->globalUses.length()) {
    1306           12799 :         PodCopy<GlobalSlotArray::Entry>(script->globals()->vector, &bce->globalUses[0],
    1307           25598 :                                         bce->globalUses.length());
    1308                 :     }
    1309                 : 
    1310         1109121 :     if (script->nClosedArgs)
    1311           83956 :         PodCopy<uint32_t>(script->closedSlots, &bce->closedArgs[0], script->nClosedArgs);
    1312         1109121 :     if (script->nClosedVars) {
    1313           59105 :         PodCopy<uint32_t>(&script->closedSlots[script->nClosedArgs], &bce->closedVars[0],
    1314          118210 :                           script->nClosedVars);
    1315                 :     }
    1316                 : 
    1317         1109121 :     script->bindings.transfer(cx, &bce->bindings);
    1318                 : 
    1319         1109121 :     fun = NULL;
    1320         1109121 :     if (bce->inFunction()) {
    1321                 :         /*
    1322                 :          * We initialize fun->script() to be the script constructed above
    1323                 :          * so that the debugger has a valid fun->script().
    1324                 :          */
    1325          988449 :         fun = bce->fun();
    1326          988449 :         JS_ASSERT(fun->isInterpreted());
    1327          988449 :         JS_ASSERT(!fun->script());
    1328                 : #ifdef DEBUG
    1329          988449 :         if (JSScript::isValidOffset(script->upvarsOffset))
    1330           83617 :             JS_ASSERT(script->upvars()->length == script->bindings.countUpvars());
    1331                 :         else
    1332          904832 :             JS_ASSERT(script->bindings.countUpvars() == 0);
    1333                 : #endif
    1334          988449 :         if (bce->flags & TCF_FUN_HEAVYWEIGHT)
    1335           70146 :             fun->flags |= JSFUN_HEAVYWEIGHT;
    1336                 : 
    1337                 :         /*
    1338                 :          * Mark functions which will only be executed once as singletons.
    1339                 :          * Skip this for flat closures, which must be copied on executing.
    1340                 :          */
    1341                 :         bool singleton =
    1342          988449 :             cx->typeInferenceEnabled() &&
    1343                 :             bce->parent &&
    1344           64157 :             bce->parent->compiling() &&
    1345           64157 :             bce->parent->asBytecodeEmitter()->checkSingletonContext() &&
    1346         1116763 :             !fun->isFlatClosure();
    1347                 : 
    1348          988449 :         if (!script->typeSetFunction(cx, fun, singleton))
    1349               0 :             return NULL;
    1350                 : 
    1351          988449 :         fun->setScript(script);
    1352          988449 :         script->globalObject = fun->getParent() ? &fun->getParent()->global() : NULL;
    1353                 :     } else {
    1354                 :         /*
    1355                 :          * Initialize script->object, if necessary, so that the debugger has a
    1356                 :          * valid holder object.
    1357                 :          */
    1358          120672 :         if (bce->flags & TCF_NEED_SCRIPT_GLOBAL)
    1359           86584 :             script->globalObject = GetCurrentGlobal(cx);
    1360                 :     }
    1361                 : 
    1362                 :     /* Tell the debugger about this compiled script. */
    1363         1109121 :     js_CallNewScriptHook(cx, script, fun);
    1364         1109121 :     if (!bce->parent) {
    1365          130777 :         GlobalObject *compileAndGoGlobal = NULL;
    1366          130777 :         if (script->compileAndGo) {
    1367          104023 :             compileAndGoGlobal = script->globalObject;
    1368          104023 :             if (!compileAndGoGlobal)
    1369           34088 :                 compileAndGoGlobal = &bce->scopeChain()->global();
    1370                 :         }
    1371          130777 :         Debugger::onNewScript(cx, script, compileAndGoGlobal);
    1372                 :     }
    1373                 : 
    1374         1109121 :     if (cx->hasRunOption(JSOPTION_PCCOUNT))
    1375               0 :         (void) script->initCounts(cx);
    1376                 : 
    1377         1109121 :     return script;
    1378                 : }
    1379                 : 
    1380                 : size_t
    1381         1324353 : JSScript::computedSizeOfData()
    1382                 : {
    1383                 : #if JS_SCRIPT_INLINE_DATA_LIMIT
    1384                 :     if (data == inlineData)
    1385                 :         return 0;
    1386                 : #endif
    1387                 : 
    1388         1324353 :     uint8_t *dataEnd = code + length * sizeof(jsbytecode) + numNotes() * sizeof(jssrcnote);
    1389         1324353 :     JS_ASSERT(dataEnd >= data);
    1390         1324353 :     return dataEnd - data;
    1391                 : }
    1392                 : 
    1393                 : size_t
    1394            3818 : JSScript::sizeOfData(JSMallocSizeOfFun mallocSizeOf)
    1395                 : {
    1396                 : #if JS_SCRIPT_INLINE_DATA_LIMIT
    1397                 :     if (data == inlineData)
    1398                 :         return 0;
    1399                 : #endif
    1400                 : 
    1401            3818 :     return mallocSizeOf(data);
    1402                 : }
    1403                 : 
    1404                 : /*
    1405                 :  * Nb: srcnotes are variable-length.  This function computes the number of
    1406                 :  * srcnote *slots*, which may be greater than the number of srcnotes.
    1407                 :  */
    1408                 : uint32_t
    1409         1783492 : JSScript::numNotes()
    1410                 : {
    1411                 :     jssrcnote *sn;
    1412         1783492 :     jssrcnote *notes_ = notes();
    1413        83317355 :     for (sn = notes_; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn))
    1414        81533863 :         continue;
    1415         1783492 :     return sn - notes_ + 1;    /* +1 for the terminator */
    1416                 : }
    1417                 : 
    1418                 : JS_FRIEND_API(void)
    1419         1383636 : js_CallNewScriptHook(JSContext *cx, JSScript *script, JSFunction *fun)
    1420                 : {
    1421         1383636 :     JS_ASSERT(!script->callDestroyHook);
    1422         1383636 :     if (JSNewScriptHook hook = cx->runtime->debugHooks.newScriptHook) {
    1423          420786 :         AutoKeepAtoms keep(cx->runtime);
    1424                 :         hook(cx, script->filename, script->lineno, script, fun,
    1425          210393 :              cx->runtime->debugHooks.newScriptHookData);
    1426                 :     }
    1427         1383636 :     script->callDestroyHook = true;
    1428         1383636 : }
    1429                 : 
    1430                 : void
    1431         1417227 : js_CallDestroyScriptHook(JSContext *cx, JSScript *script)
    1432                 : {
    1433         1417227 :     if (!script->callDestroyHook)
    1434           34088 :         return;
    1435                 : 
    1436         1383139 :     if (JSDestroyScriptHook hook = cx->runtime->debugHooks.destroyScriptHook)
    1437           71086 :         hook(cx, script, cx->runtime->debugHooks.destroyScriptHookData);
    1438         1383139 :     script->callDestroyHook = false;
    1439         1383139 :     JS_ClearScriptTraps(cx, script);
    1440                 : }
    1441                 : 
    1442                 : #ifdef JS_CRASH_DIAGNOSTICS
    1443                 : 
    1444                 : void
    1445         8149498 : JSScript::CheckScript(JSScript *prev)
    1446                 : {
    1447         8149498 :     if (cookie1[0] != JS_SCRIPT_COOKIE || cookie2[0] != JS_SCRIPT_COOKIE) {
    1448               0 :         crash::StackBuffer<sizeof(JSScript), 0x87> buf1(this);
    1449               0 :         crash::StackBuffer<sizeof(JSScript), 0x88> buf2(prev);
    1450               0 :         JS_OPT_ASSERT(false);
    1451                 :     }
    1452         8149498 : }
    1453                 : 
    1454                 : #endif /* JS_CRASH_DIAGNOSTICS */
    1455                 : 
    1456                 : void
    1457         1324353 : JSScript::finalize(JSContext *cx, bool background)
    1458                 : {
    1459         1324353 :     CheckScript(NULL);
    1460                 : 
    1461         1324353 :     js_CallDestroyScriptHook(cx, this);
    1462                 : 
    1463         1324353 :     JS_ASSERT_IF(principals, originPrincipals);
    1464         1324353 :     if (principals)
    1465         1064927 :         JS_DropPrincipals(cx->runtime, principals);
    1466         1324353 :     if (originPrincipals)
    1467         1064938 :         JS_DropPrincipals(cx->runtime, originPrincipals);
    1468                 : 
    1469         1324353 :     if (types)
    1470          470660 :         types->destroy();
    1471                 : 
    1472                 : #ifdef JS_METHODJIT
    1473         1324353 :     mjit::ReleaseScriptCode(cx, this);
    1474                 : #endif
    1475                 : 
    1476         1324353 :     destroyCounts(cx);
    1477                 : 
    1478         1324353 :     if (sourceMap)
    1479               1 :         cx->free_(sourceMap);
    1480                 : 
    1481         1324353 :     if (debug) {
    1482               1 :         jsbytecode *end = code + length;
    1483              67 :         for (jsbytecode *pc = code; pc < end; pc++) {
    1484              66 :             if (BreakpointSite *site = getBreakpointSite(pc)) {
    1485                 :                 /* Breakpoints are swept before finalization. */
    1486               0 :                 JS_ASSERT(site->firstBreakpoint() == NULL);
    1487               0 :                 site->clearTrap(cx, NULL, NULL);
    1488               0 :                 JS_ASSERT(getBreakpointSite(pc) == NULL);
    1489                 :             }
    1490                 :         }
    1491               1 :         cx->free_(debug);
    1492                 :     }
    1493                 : 
    1494                 : #if JS_SCRIPT_INLINE_DATA_LIMIT
    1495                 :     if (data != inlineData)
    1496                 : #endif
    1497                 :     {
    1498         1324353 :         JS_POISON(data, 0xdb, computedSizeOfData());
    1499         1324353 :         cx->free_(data);
    1500                 :     }
    1501         1324353 : }
    1502                 : 
    1503                 : namespace js {
    1504                 : 
    1505                 : static const uint32_t GSN_CACHE_THRESHOLD = 100;
    1506                 : static const uint32_t GSN_CACHE_MAP_INIT_SIZE = 20;
    1507                 : 
    1508                 : void
    1509           52591 : GSNCache::purge()
    1510                 : {
    1511           52591 :     code = NULL;
    1512           52591 :     if (map.initialized())
    1513            4813 :         map.finish();
    1514           52591 : }
    1515                 : 
    1516                 : } /* namespace js */
    1517                 : 
    1518                 : jssrcnote *
    1519        35139329 : js_GetSrcNoteCached(JSContext *cx, JSScript *script, jsbytecode *pc)
    1520                 : {
    1521        35139329 :     size_t target = pc - script->code;
    1522        35139329 :     if (target >= size_t(script->length))
    1523               0 :         return NULL;
    1524                 : 
    1525        35139329 :     GSNCache *cache = GetGSNCache(cx);
    1526        35139329 :     if (cache->code == script->code) {
    1527         6768717 :         JS_ASSERT(cache->map.initialized());
    1528         6768717 :         GSNCache::Map::Ptr p = cache->map.lookup(pc);
    1529         6768717 :         return p ? p->value : NULL;
    1530                 :     }
    1531                 : 
    1532        28370612 :     size_t offset = 0;
    1533                 :     jssrcnote *result;
    1534       163120524 :     for (jssrcnote *sn = script->notes(); ; sn = SN_NEXT(sn)) {
    1535       163120524 :         if (SN_IS_TERMINATOR(sn)) {
    1536        26468047 :             result = NULL;
    1537        26468047 :             break;
    1538                 :         }
    1539       136652477 :         offset += SN_DELTA(sn);
    1540       136652477 :         if (offset == target && SN_IS_GETTABLE(sn)) {
    1541         1902565 :             result = sn;
    1542         1902565 :             break;
    1543                 :         }
    1544                 :     }
    1545                 : 
    1546        28370612 :     if (cache->code != script->code && script->length >= GSN_CACHE_THRESHOLD) {
    1547           27005 :         unsigned nsrcnotes = 0;
    1548         3765236 :         for (jssrcnote *sn = script->notes(); !SN_IS_TERMINATOR(sn);
    1549         3738231 :              sn = SN_NEXT(sn)) {
    1550         3738231 :             if (SN_IS_GETTABLE(sn))
    1551         1537312 :                 ++nsrcnotes;
    1552                 :         }
    1553           27005 :         if (cache->code) {
    1554           22192 :             JS_ASSERT(cache->map.initialized());
    1555           22192 :             cache->map.finish();
    1556           22192 :             cache->code = NULL;
    1557                 :         }
    1558           27005 :         if (cache->map.init(nsrcnotes)) {
    1559           27005 :             pc = script->code;
    1560         3765236 :             for (jssrcnote *sn = script->notes(); !SN_IS_TERMINATOR(sn);
    1561         3738231 :                  sn = SN_NEXT(sn)) {
    1562         3738231 :                 pc += SN_DELTA(sn);
    1563         3738231 :                 if (SN_IS_GETTABLE(sn))
    1564         1537312 :                     JS_ALWAYS_TRUE(cache->map.put(pc, sn));
    1565                 :             }
    1566           27005 :             cache->code = script->code;
    1567                 :         }
    1568                 :     }
    1569                 : 
    1570        28370612 :     return result;
    1571                 : }
    1572                 : 
    1573                 : unsigned
    1574         6564562 : js::PCToLineNumber(unsigned startLine, jssrcnote *notes, jsbytecode *code, jsbytecode *pc)
    1575                 : {
    1576         6564562 :     unsigned lineno = startLine;
    1577                 : 
    1578                 :     /*
    1579                 :      * Walk through source notes accumulating their deltas, keeping track of
    1580                 :      * line-number notes, until we pass the note for pc's offset within
    1581                 :      * script->code.
    1582                 :      */
    1583         6564562 :     ptrdiff_t offset = 0;
    1584         6564562 :     ptrdiff_t target = pc - code;
    1585       136098171 :     for (jssrcnote *sn = notes; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {
    1586       133035066 :         offset += SN_DELTA(sn);
    1587       133035066 :         SrcNoteType type = (SrcNoteType) SN_TYPE(sn);
    1588       133035066 :         if (type == SRC_SETLINE) {
    1589         4604761 :             if (offset <= target)
    1590         4388558 :                 lineno = (unsigned) js_GetSrcNoteOffset(sn, 0);
    1591       128430305 :         } else if (type == SRC_NEWLINE) {
    1592        41037060 :             if (offset <= target)
    1593        40494405 :                 lineno++;
    1594                 :         }
    1595       133035066 :         if (offset > target)
    1596         3501457 :             break;
    1597                 :     }
    1598                 : 
    1599         6564562 :     return lineno;
    1600                 : }
    1601                 : 
    1602                 : unsigned
    1603         6564562 : js::PCToLineNumber(JSScript *script, jsbytecode *pc)
    1604                 : {
    1605                 :     /* Cope with StackFrame.pc value prior to entering js_Interpret. */
    1606         6564562 :     if (!pc)
    1607               0 :         return 0;
    1608                 : 
    1609         6564562 :     return PCToLineNumber(script->lineno, script->notes(), script->code, pc);
    1610                 : }
    1611                 : 
    1612                 : /* The line number limit is the same as the jssrcnote offset limit. */
    1613                 : #define SN_LINE_LIMIT   (SN_3BYTE_OFFSET_FLAG << 16)
    1614                 : 
    1615                 : jsbytecode *
    1616              18 : js_LineNumberToPC(JSScript *script, unsigned target)
    1617                 : {
    1618              18 :     ptrdiff_t offset = 0;
    1619              18 :     ptrdiff_t best = -1;
    1620              18 :     unsigned lineno = script->lineno;
    1621              18 :     unsigned bestdiff = SN_LINE_LIMIT;
    1622             150 :     for (jssrcnote *sn = script->notes(); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {
    1623                 :         /*
    1624                 :          * Exact-match only if offset is not in the prolog; otherwise use
    1625                 :          * nearest greater-or-equal line number match.
    1626                 :          */
    1627             135 :         if (lineno == target && offset >= ptrdiff_t(script->mainOffset))
    1628               3 :             goto out;
    1629             132 :         if (lineno >= target) {
    1630              65 :             unsigned diff = lineno - target;
    1631              65 :             if (diff < bestdiff) {
    1632               7 :                 bestdiff = diff;
    1633               7 :                 best = offset;
    1634                 :             }
    1635                 :         }
    1636             132 :         offset += SN_DELTA(sn);
    1637             132 :         SrcNoteType type = (SrcNoteType) SN_TYPE(sn);
    1638             132 :         if (type == SRC_SETLINE) {
    1639              15 :             lineno = (unsigned) js_GetSrcNoteOffset(sn, 0);
    1640             117 :         } else if (type == SRC_NEWLINE) {
    1641              45 :             lineno++;
    1642                 :         }
    1643                 :     }
    1644              15 :     if (best >= 0)
    1645               6 :         offset = best;
    1646                 : out:
    1647              18 :     return script->code + offset;
    1648                 : }
    1649                 : 
    1650                 : JS_FRIEND_API(unsigned)
    1651            1061 : js_GetScriptLineExtent(JSScript *script)
    1652                 : {
    1653            1061 :     unsigned lineno = script->lineno;
    1654            1061 :     unsigned maxLineNo = 0;
    1655            1061 :     bool counting = true;
    1656            1728 :     for (jssrcnote *sn = script->notes(); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {
    1657             667 :         SrcNoteType type = (SrcNoteType) SN_TYPE(sn);
    1658             667 :         if (type == SRC_SETLINE) {
    1659              92 :             if (maxLineNo < lineno)
    1660              50 :                 maxLineNo = lineno;
    1661              92 :             lineno = (unsigned) js_GetSrcNoteOffset(sn, 0);
    1662              92 :             counting = true;
    1663              92 :             if (maxLineNo < lineno)
    1664              71 :                 maxLineNo = lineno;
    1665                 :             else
    1666              21 :                 counting = false;
    1667             575 :         } else if (type == SRC_NEWLINE) {
    1668             117 :             if (counting)
    1669              92 :                 lineno++;
    1670                 :         }
    1671                 :     }
    1672                 : 
    1673            1061 :     if (maxLineNo > lineno)
    1674               4 :         lineno = maxLineNo;
    1675                 : 
    1676            1061 :     return 1 + lineno - script->lineno;
    1677                 : }
    1678                 : 
    1679                 : namespace js {
    1680                 : 
    1681                 : unsigned
    1682          610651 : CurrentLine(JSContext *cx)
    1683                 : {
    1684          610651 :     return PCToLineNumber(cx->fp()->script(), cx->regs().pc);
    1685                 : }
    1686                 : 
    1687                 : void
    1688           24243 : CurrentScriptFileLineOriginSlow(JSContext *cx, const char **file, unsigned *linenop,
    1689                 :                                 JSPrincipals **origin)
    1690                 : {
    1691           24243 :     FrameRegsIter iter(cx);
    1692           48486 :     while (!iter.done() && !iter.fp()->isScriptFrame())
    1693               0 :         ++iter;
    1694                 : 
    1695           24243 :     if (iter.done()) {
    1696               4 :         *file = NULL;
    1697               4 :         *linenop = 0;
    1698               4 :         *origin = NULL;
    1699               4 :         return;
    1700                 :     }
    1701                 : 
    1702           24239 :     JSScript *script = iter.fp()->script();
    1703           24239 :     *file = script->filename;
    1704           24239 :     *linenop = PCToLineNumber(iter.fp()->script(), iter.pc());
    1705           24239 :     *origin = script->originPrincipals;
    1706                 : }
    1707                 : 
    1708                 : class AutoJSXDRState {
    1709                 :   public:
    1710            4558 :     AutoJSXDRState(JSXDRState *x
    1711                 :                    JS_GUARD_OBJECT_NOTIFIER_PARAM)
    1712            4558 :         : xdr(x)
    1713                 :     {
    1714            4558 :         JS_GUARD_OBJECT_NOTIFIER_INIT;
    1715            4558 :     }
    1716            4558 :     ~AutoJSXDRState()
    1717            4558 :     {
    1718            4558 :         JS_XDRDestroy(xdr);
    1719            4558 :     }
    1720                 : 
    1721           15953 :     operator JSXDRState*() const
    1722                 :     {
    1723           15953 :         return xdr;
    1724                 :     }
    1725                 : 
    1726            4558 :     JSXDRState* operator->() const
    1727                 :     {
    1728            4558 :         return xdr;
    1729                 :     }
    1730                 : 
    1731                 :   private:
    1732                 :     JSXDRState *const xdr;
    1733                 :     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
    1734                 : };
    1735                 : 
    1736                 : JSScript *
    1737            2279 : CloneScript(JSContext *cx, JSScript *script)
    1738                 : {
    1739            2279 :     JS_ASSERT(cx->compartment != script->compartment());
    1740                 : 
    1741                 :     /* Serialize script. */
    1742            4558 :     AutoJSXDRState w(JS_XDRNewMem(cx, JSXDR_ENCODE));
    1743            2279 :     if (!w)
    1744               0 :         return NULL;
    1745                 : 
    1746            2279 :     if (!XDRScript(w, &script))
    1747               0 :         return NULL;
    1748                 : 
    1749                 :     uint32_t nbytes;
    1750            2279 :     void *p = JS_XDRMemGetData(w, &nbytes);
    1751            2279 :     if (!p)
    1752               0 :         return NULL;
    1753                 : 
    1754                 :     /* De-serialize script. */
    1755            4558 :     AutoJSXDRState r(JS_XDRNewMem(cx, JSXDR_DECODE));
    1756            2279 :     if (!r)
    1757               0 :         return NULL;
    1758                 : 
    1759                 :     /*
    1760                 :      * Hand p off from w to r.  Don't want them to share the data mem, lest
    1761                 :      * they both try to free it in JS_XDRDestroy.
    1762                 :      */
    1763            2279 :     JS_XDRMemSetData(r, p, nbytes);
    1764            2279 :     JS_XDRMemSetData(w, NULL, 0);
    1765                 : 
    1766            2279 :     r->principals = cx->compartment->principals;
    1767            2279 :     r->originPrincipals = JSScript::normalizeOriginPrincipals(cx->compartment->principals,
    1768            2279 :                                                               script->originPrincipals);
    1769            2279 :     JSScript *newScript = NULL;
    1770            2279 :     if (!XDRScript(r, &newScript))
    1771               0 :         return NULL;
    1772                 : 
    1773            2279 :     return newScript;
    1774                 : }
    1775                 : 
    1776                 : }  /* namespace js */
    1777                 : 
    1778                 : void
    1779               0 : JSScript::copyClosedSlotsTo(JSScript *other)
    1780                 : {
    1781               0 :     js_memcpy(other->closedSlots, closedSlots, nClosedArgs + nClosedVars);
    1782               0 : }
    1783                 : 
    1784                 : bool
    1785            2595 : JSScript::ensureHasDebug(JSContext *cx)
    1786                 : {
    1787            2595 :     if (debug)
    1788            1246 :         return true;
    1789                 : 
    1790            1349 :     size_t nbytes = offsetof(DebugScript, breakpoints) + length * sizeof(BreakpointSite*);
    1791            1349 :     debug = (DebugScript *) cx->calloc_(nbytes);
    1792            1349 :     if (!debug)
    1793               0 :         return false;
    1794                 : 
    1795                 :     /*
    1796                 :      * Ensure that any Interpret() instances running on this script have
    1797                 :      * interrupts enabled. The interrupts must stay enabled until the
    1798                 :      * debug state is destroyed.
    1799                 :      */
    1800                 :     InterpreterFrames *frames;
    1801            3956 :     for (frames = cx->runtime->interpreterFrames; frames; frames = frames->older)
    1802            2607 :         frames->enableInterruptsIfRunning(this);
    1803                 : 
    1804            1349 :     return true;
    1805                 : }
    1806                 : 
    1807                 : bool
    1808             883 : JSScript::recompileForStepMode(JSContext *cx)
    1809                 : {
    1810                 : #ifdef JS_METHODJIT
    1811             883 :     if (jitNormal || jitCtor) {
    1812             202 :         mjit::Recompiler::clearStackReferences(cx, this);
    1813             202 :         mjit::ReleaseScriptCode(cx, this);
    1814                 :     }
    1815                 : #endif
    1816             883 :     return true;
    1817                 : }
    1818                 : 
    1819                 : bool
    1820             937 : JSScript::tryNewStepMode(JSContext *cx, uint32_t newValue)
    1821                 : {
    1822             937 :     JS_ASSERT(debug);
    1823                 : 
    1824             937 :     uint32_t prior = debug->stepMode;
    1825             937 :     debug->stepMode = newValue;
    1826                 : 
    1827             937 :     if (!prior != !newValue) {
    1828                 :         /* Step mode has been enabled or disabled. Alert the methodjit. */
    1829             883 :         if (!recompileForStepMode(cx)) {
    1830               0 :             debug->stepMode = prior;
    1831               0 :             return false;
    1832                 :         }
    1833                 : 
    1834             883 :         if (!stepModeEnabled() && !debug->numSites) {
    1835             432 :             cx->free_(debug);
    1836             432 :             debug = NULL;
    1837                 :         }
    1838                 :     }
    1839                 : 
    1840             937 :     return true;
    1841                 : }
    1842                 : 
    1843                 : bool
    1844               1 : JSScript::setStepModeFlag(JSContext *cx, bool step)
    1845                 : {
    1846               1 :     if (!ensureHasDebug(cx))
    1847               0 :         return false;
    1848                 : 
    1849               1 :     return tryNewStepMode(cx, (debug->stepMode & stepCountMask) | (step ? stepFlagMask : 0));
    1850                 : }
    1851                 : 
    1852                 : bool
    1853             936 : JSScript::changeStepModeCount(JSContext *cx, int delta)
    1854                 : {
    1855             936 :     if (!ensureHasDebug(cx))
    1856               0 :         return false;
    1857                 : 
    1858             936 :     assertSameCompartment(cx, this);
    1859             936 :     JS_ASSERT_IF(delta > 0, cx->compartment->debugMode());
    1860                 : 
    1861             936 :     uint32_t count = debug->stepMode & stepCountMask;
    1862             936 :     JS_ASSERT(((count + delta) & stepCountMask) == count + delta);
    1863                 :     return tryNewStepMode(cx,
    1864                 :                           (debug->stepMode & stepFlagMask) |
    1865             936 :                           ((count + delta) & stepCountMask));
    1866                 : }
    1867                 : 
    1868                 : BreakpointSite *
    1869            1658 : JSScript::getOrCreateBreakpointSite(JSContext *cx, jsbytecode *pc,
    1870                 :                                     GlobalObject *scriptGlobal)
    1871                 : {
    1872            1658 :     JS_ASSERT(size_t(pc - code) < length);
    1873                 : 
    1874            1658 :     if (!ensureHasDebug(cx))
    1875               0 :         return NULL;
    1876                 : 
    1877            1658 :     BreakpointSite *&site = debug->breakpoints[pc - code];
    1878                 : 
    1879            1658 :     if (!site) {
    1880            1190 :         site = cx->runtime->new_<BreakpointSite>(this, pc);
    1881            1190 :         if (!site) {
    1882               0 :             js_ReportOutOfMemory(cx);
    1883               0 :             return NULL;
    1884                 :         }
    1885            1190 :         debug->numSites++;
    1886                 :     }
    1887                 : 
    1888            1658 :     if (site->scriptGlobal)
    1889             279 :         JS_ASSERT_IF(scriptGlobal, site->scriptGlobal == scriptGlobal);
    1890                 :     else
    1891            1379 :         site->scriptGlobal = scriptGlobal;
    1892                 : 
    1893            1658 :     return site;
    1894                 : }
    1895                 : 
    1896                 : void
    1897            1190 : JSScript::destroyBreakpointSite(JSRuntime *rt, jsbytecode *pc)
    1898                 : {
    1899            1190 :     JS_ASSERT(unsigned(pc - code) < length);
    1900                 : 
    1901            1190 :     BreakpointSite *&site = debug->breakpoints[pc - code];
    1902            1190 :     JS_ASSERT(site);
    1903                 : 
    1904            1190 :     rt->delete_(site);
    1905            1190 :     site = NULL;
    1906                 : 
    1907            1190 :     if (--debug->numSites == 0 && !stepModeEnabled()) {
    1908             916 :         rt->free_(debug);
    1909             916 :         debug = NULL;
    1910                 :     }
    1911            1190 : }
    1912                 : 
    1913                 : void
    1914            8814 : JSScript::clearBreakpointsIn(JSContext *cx, js::Debugger *dbg, JSObject *handler)
    1915                 : {
    1916            8814 :     if (!hasAnyBreakpointsOrStepMode())
    1917            8337 :         return;
    1918                 : 
    1919             477 :     jsbytecode *end = code + length;
    1920         8886126 :     for (jsbytecode *pc = code; pc < end; pc++) {
    1921         8885649 :         BreakpointSite *site = getBreakpointSite(pc);
    1922         8885649 :         if (site) {
    1923                 :             Breakpoint *nextbp;
    1924            1707 :             for (Breakpoint *bp = site->firstBreakpoint(); bp; bp = nextbp) {
    1925            1047 :                 nextbp = bp->nextInSite();
    1926            1047 :                 if ((!dbg || bp->debugger == dbg) && (!handler || bp->getHandler() == handler))
    1927             768 :                     bp->destroy(cx);
    1928                 :             }
    1929                 :         }
    1930                 :     }
    1931                 : }
    1932                 : 
    1933                 : void
    1934         1741574 : JSScript::clearTraps(JSContext *cx)
    1935                 : {
    1936         1741574 :     if (!hasAnyBreakpointsOrStepMode())
    1937         1741052 :         return;
    1938                 : 
    1939             522 :     jsbytecode *end = code + length;
    1940           18081 :     for (jsbytecode *pc = code; pc < end; pc++) {
    1941           17559 :         BreakpointSite *site = getBreakpointSite(pc);
    1942           17559 :         if (site)
    1943             638 :             site->clearTrap(cx);
    1944                 :     }
    1945                 : }
    1946                 : 
    1947                 : void
    1948         6825145 : JSScript::markChildren(JSTracer *trc)
    1949                 : {
    1950         6825145 :     CheckScript(NULL);
    1951                 : 
    1952             470 :     JS_ASSERT_IF(trc->runtime->gcCheckCompartment,
    1953         6825615 :                  compartment() == trc->runtime->gcCheckCompartment);
    1954                 : 
    1955        69116789 :     for (uint32_t i = 0; i < natoms; ++i) {
    1956        62291644 :         if (atoms[i])
    1957        62291644 :             MarkStringUnbarriered(trc, &atoms[i], "atom");
    1958                 :     }
    1959                 : 
    1960         6825145 :     if (JSScript::isValidOffset(objectsOffset)) {
    1961         2173737 :         JSObjectArray *objarray = objects();
    1962         2173737 :         MarkObjectRange(trc, objarray->length, objarray->vector, "objects");
    1963                 :     }
    1964                 : 
    1965         6825145 :     if (JSScript::isValidOffset(regexpsOffset)) {
    1966           87260 :         JSObjectArray *objarray = regexps();
    1967           87260 :         MarkObjectRange(trc, objarray->length, objarray->vector, "objects");
    1968                 :     }
    1969                 : 
    1970         6825145 :     if (JSScript::isValidOffset(constOffset)) {
    1971           86824 :         JSConstArray *constarray = consts();
    1972           86824 :         MarkValueRange(trc, constarray->length, constarray->vector, "consts");
    1973                 :     }
    1974                 : 
    1975         6825145 :     if (function())
    1976         6778093 :         MarkObject(trc, &function_, "function");
    1977                 : 
    1978         6825145 :     if (!isCachedEval && globalObject)
    1979          100743 :         MarkObject(trc, &globalObject, "object");
    1980                 : 
    1981         6825145 :     if (IS_GC_MARKING_TRACER(trc) && filename)
    1982         6564228 :         js_MarkScriptFilename(filename);
    1983                 : 
    1984         6825145 :     bindings.trace(trc);
    1985                 : 
    1986         6825145 :     if (types)
    1987         1954054 :         types->trace(trc);
    1988                 : 
    1989         6825145 :     if (hasAnyBreakpointsOrStepMode()) {
    1990           24457 :         for (unsigned i = 0; i < length; i++) {
    1991           23811 :             BreakpointSite *site = debug->breakpoints[i];
    1992           23811 :             if (site && site->trapHandler)
    1993             641 :                 MarkValue(trc, &site->trapClosure, "trap closure");
    1994                 :         }
    1995                 :     }
    1996         6825145 : }

Generated by: LCOV version 1.7