LCOV - code coverage report
Current view: directory - js/src - jsscript.h (source / functions) Found Hit Coverage
Test: app.info Lines: 118 104 88.1 %
Date: 2012-06-02 Functions: 67 60 89.6 %

       1                 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  * vim: set ts=4 sw=4 et tw=79 ft=cpp:
       3                 :  *
       4                 :  * ***** BEGIN LICENSE BLOCK *****
       5                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       6                 :  *
       7                 :  * The contents of this file are subject to the Mozilla Public License Version
       8                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       9                 :  * the License. You may obtain a copy of the License at
      10                 :  * http://www.mozilla.org/MPL/
      11                 :  *
      12                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      13                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      14                 :  * for the specific language governing rights and limitations under the
      15                 :  * License.
      16                 :  *
      17                 :  * The Original Code is Mozilla Communicator client code, released
      18                 :  * March 31, 1998.
      19                 :  *
      20                 :  * The Initial Developer of the Original Code is
      21                 :  * Netscape Communications Corporation.
      22                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      23                 :  * the Initial Developer. All Rights Reserved.
      24                 :  *
      25                 :  * Contributor(s):
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      29                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : 
      41                 : #ifndef jsscript_h___
      42                 : #define jsscript_h___
      43                 : /*
      44                 :  * JS script descriptor.
      45                 :  */
      46                 : #include "jsatom.h"
      47                 : #include "jsprvtd.h"
      48                 : #include "jsdbgapi.h"
      49                 : #include "jsclist.h"
      50                 : #include "jsinfer.h"
      51                 : #include "jsopcode.h"
      52                 : #include "jsscope.h"
      53                 : 
      54                 : #include "gc/Barrier.h"
      55                 : 
      56                 : /*
      57                 :  * Type of try note associated with each catch or finally block, and also with
      58                 :  * for-in loops.
      59                 :  */
      60                 : typedef enum JSTryNoteKind {
      61                 :     JSTRY_CATCH,
      62                 :     JSTRY_FINALLY,
      63                 :     JSTRY_ITER
      64                 : } JSTryNoteKind;
      65                 : 
      66                 : namespace js {
      67                 : 
      68                 : /*
      69                 :  * Indicates a location in the stack that an upvar value can be retrieved from
      70                 :  * as a two tuple of (level, slot).
      71                 :  *
      72                 :  * Some existing client code uses the level value as a delta, or level "skip"
      73                 :  * quantity. We could probably document that through use of more types at some
      74                 :  * point in the future.
      75                 :  *
      76                 :  * Existing XDR code wants this to be backed by a 32b integer for serialization,
      77                 :  * so we oblige.
      78                 :  *
      79                 :  * TODO: consider giving more bits to the slot value and takings ome from the level.
      80                 :  */
      81                 : class UpvarCookie
      82          205910 : {
      83                 :     uint32_t value;
      84                 : 
      85                 :     static const uint32_t FREE_VALUE = 0xfffffffful;
      86                 : 
      87                 :     void checkInvariants() {
      88                 :         JS_STATIC_ASSERT(sizeof(UpvarCookie) == sizeof(uint32_t));
      89                 :         JS_STATIC_ASSERT(UPVAR_LEVEL_LIMIT < FREE_LEVEL);
      90                 :     }
      91                 : 
      92                 :   public:
      93                 :     /*
      94                 :      * All levels above-and-including FREE_LEVEL are reserved so that
      95                 :      * FREE_VALUE can be used as a special value.
      96                 :      */
      97                 :     static const uint16_t FREE_LEVEL = 0x3fff;
      98                 : 
      99                 :     /*
     100                 :      * If a function has a higher static level than this limit, we will not
     101                 :      * optimize it using UPVAR opcodes.
     102                 :      */
     103                 :     static const uint16_t UPVAR_LEVEL_LIMIT = 16;
     104                 :     static const uint16_t CALLEE_SLOT = 0xffff;
     105         1101840 :     static bool isLevelReserved(uint16_t level) { return level >= FREE_LEVEL; }
     106                 : 
     107       118801165 :     bool isFree() const { return value == FREE_VALUE; }
     108          520988 :     uint32_t asInteger() const { return value; }
     109                 :     /* isFree check should be performed before using these accessors. */
     110        11144255 :     uint16_t level() const { JS_ASSERT(!isFree()); return uint16_t(value >> 16); }
     111        21786603 :     uint16_t slot() const { JS_ASSERT(!isFree()); return uint16_t(value); }
     112                 : 
     113                 :     void set(const UpvarCookie &other) { set(other.level(), other.slot()); }
     114        30966458 :     void set(uint16_t newLevel, uint16_t newSlot) { value = (uint32_t(newLevel) << 16) | newSlot; }
     115        21609523 :     void makeFree() { set(0xffff, 0xffff); JS_ASSERT(isFree()); }
     116               0 :     void fromInteger(uint32_t u32) { value = u32; }
     117                 : };
     118                 : 
     119                 : }
     120                 : 
     121                 : /*
     122                 :  * Exception handling record.
     123                 :  */
     124                 : struct JSTryNote {
     125                 :     uint8_t         kind;       /* one of JSTryNoteKind */
     126                 :     uint8_t         padding;    /* explicit padding on uint16_t boundary */
     127                 :     uint16_t        stackDepth; /* stack depth upon exception handler entry */
     128                 :     uint32_t        start;      /* start of the try statement or for-in loop
     129                 :                                    relative to script->main */
     130                 :     uint32_t        length;     /* length of the try statement or for-in loop */
     131                 : };
     132                 : 
     133                 : typedef struct JSTryNoteArray {
     134                 :     JSTryNote       *vector;    /* array of indexed try notes */
     135                 :     uint32_t        length;     /* count of indexed try notes */
     136                 : } JSTryNoteArray;
     137                 : 
     138                 : typedef struct JSObjectArray {
     139                 :     js::HeapPtrObject *vector;  /* array of indexed objects */
     140                 :     uint32_t        length;     /* count of indexed objects */
     141                 : } JSObjectArray;
     142                 : 
     143                 : typedef struct JSUpvarArray {
     144                 :     js::UpvarCookie *vector;    /* array of indexed upvar cookies */
     145                 :     uint32_t        length;     /* count of indexed upvar cookies */
     146                 : } JSUpvarArray;
     147                 : 
     148                 : typedef struct JSConstArray {
     149                 :     js::HeapValue   *vector;    /* array of indexed constant values */
     150                 :     uint32_t        length;
     151                 : } JSConstArray;
     152                 : 
     153                 : namespace js {
     154                 : 
     155                 : struct GlobalSlotArray {
     156           31216 :     struct Entry {
     157                 :         uint32_t    atomIndex;  /* index into atom table */
     158                 :         uint32_t    slot;       /* global obj slot number */
     159                 :     };
     160                 :     Entry           *vector;
     161                 :     uint32_t        length;
     162                 : };
     163                 : 
     164                 : struct Shape;
     165                 : 
     166                 : enum BindingKind { NONE, ARGUMENT, VARIABLE, CONSTANT, UPVAR };
     167                 : 
     168                 : /*
     169                 :  * Formal parameters, local variables, and upvars are stored in a shape tree
     170                 :  * path encapsulated within this class.  This class represents bindings for
     171                 :  * both function and top-level scripts (the latter is needed to track names in
     172                 :  * strict mode eval code, to give such code its own lexical environment).
     173                 :  */
     174         5995995 : class Bindings {
     175                 :     HeapPtr<Shape> lastBinding;
     176                 :     uint16_t nargs;
     177                 :     uint16_t nvars;
     178                 :     uint16_t nupvars;
     179                 :     bool     hasDup_:1;     // true if there are duplicate argument names
     180                 : 
     181                 :     inline Shape *initialShape(JSContext *cx) const;
     182                 :   public:
     183                 :     inline Bindings(JSContext *cx);
     184                 : 
     185                 :     /*
     186                 :      * Transfers ownership of bindings data from bindings into this fresh
     187                 :      * Bindings instance. Once such a transfer occurs, the old bindings must
     188                 :      * not be used again.
     189                 :      */
     190                 :     inline void transfer(JSContext *cx, Bindings *bindings);
     191                 : 
     192                 :     /*
     193                 :      * Clones bindings data from bindings, which must be immutable, into this
     194                 :      * fresh Bindings instance. A Bindings instance may be cloned multiple
     195                 :      * times.
     196                 :      */
     197                 :     inline void clone(JSContext *cx, Bindings *bindings);
     198                 : 
     199         3438604 :     uint16_t countArgs() const { return nargs; }
     200         5619172 :     uint16_t countVars() const { return nvars; }
     201         6982580 :     uint16_t countUpvars() const { return nupvars; }
     202                 : 
     203          701226 :     unsigned countArgsAndVars() const { return nargs + nvars; }
     204                 : 
     205          825776 :     unsigned countLocalNames() const { return nargs + nvars + nupvars; }
     206                 : 
     207         1144699 :     bool hasUpvars() const { return nupvars > 0; }
     208          391256 :     bool hasLocalNames() const { return countLocalNames() > 0; }
     209                 : 
     210                 :     /* Ensure these bindings have a shape lineage. */
     211                 :     inline bool ensureShape(JSContext *cx);
     212                 : 
     213                 :     /* Return the shape lineage generated for these bindings. */
     214                 :     inline Shape *lastShape() const;
     215                 : 
     216                 :     /*
     217                 :      * Return the shape to use to create a call object for these bindings.
     218                 :      * The result is guaranteed not to have duplicate property names.
     219                 :      */
     220                 :     Shape *callObjectShape(JSContext *cx) const;
     221                 : 
     222                 :     /* See Scope::extensibleParents */
     223                 :     inline bool extensibleParents();
     224                 :     bool setExtensibleParents(JSContext *cx);
     225                 : 
     226                 :     bool setParent(JSContext *cx, JSObject *obj);
     227                 : 
     228                 :     enum {
     229                 :         /*
     230                 :          * A script may have no more than this many arguments, variables, or
     231                 :          * upvars.
     232                 :          */
     233                 :         BINDING_COUNT_LIMIT = 0xFFFF
     234                 :     };
     235                 : 
     236                 :     /*
     237                 :      * Add a local binding for the given name, of the given type, for the code
     238                 :      * being compiled.  If fun is non-null, this binding set is being created
     239                 :      * for that function, so adjust corresponding metadata in that function
     240                 :      * while adding.  Otherwise this set must correspond to a top-level script.
     241                 :      *
     242                 :      * A binding may be added twice with different kinds; the last one for a
     243                 :      * given name prevails.  (We preserve both bindings for the decompiler,
     244                 :      * which must deal with such cases.)  Pass null for name when indicating a
     245                 :      * destructuring argument.  Return true on success.
     246                 :      *
     247                 :      * The parser builds shape paths for functions, usable by Call objects at
     248                 :      * runtime, by calling an "add" method. All ARGUMENT bindings must be added
     249                 :      * before before any VARIABLE or CONSTANT bindings, which themselves must
     250                 :      * be added before all UPVAR bindings.
     251                 :      */
     252                 :     bool add(JSContext *cx, JSAtom *name, BindingKind kind);
     253                 : 
     254                 :     /* Convenience specializations. */
     255           41008 :     bool addVariable(JSContext *cx, JSAtom *name) {
     256           41008 :         return add(cx, name, VARIABLE);
     257                 :     }
     258                 :     bool addConstant(JSContext *cx, JSAtom *name) {
     259                 :         return add(cx, name, CONSTANT);
     260                 :     }
     261          112704 :     bool addUpvar(JSContext *cx, JSAtom *name) {
     262          112704 :         return add(cx, name, UPVAR);
     263                 :     }
     264         1208443 :     bool addArgument(JSContext *cx, JSAtom *name, uint16_t *slotp) {
     265         1208443 :         JS_ASSERT(name != NULL); /* not destructuring */
     266         1208443 :         *slotp = nargs;
     267         1208443 :         return add(cx, name, ARGUMENT);
     268                 :     }
     269            1556 :     bool addDestructuring(JSContext *cx, uint16_t *slotp) {
     270            1556 :         *slotp = nargs;
     271            1556 :         return add(cx, NULL, ARGUMENT);
     272                 :     }
     273                 : 
     274              18 :     void noteDup() { hasDup_ = true; }
     275          703452 :     bool hasDup() const { return hasDup_; }
     276                 : 
     277                 :     /*
     278                 :      * Look up an argument or variable name, returning its kind when found or
     279                 :      * NONE when no such name exists. When indexp is not null and the name
     280                 :      * exists, *indexp will receive the index of the corresponding argument or
     281                 :      * variable.
     282                 :      */
     283                 :     BindingKind lookup(JSContext *cx, JSAtom *name, unsigned *indexp) const;
     284                 : 
     285                 :     /* Convenience method to check for any binding for a name. */
     286         1588831 :     bool hasBinding(JSContext *cx, JSAtom *name) const {
     287         1588831 :         return lookup(cx, name, NULL) != NONE;
     288                 :     }
     289                 : 
     290                 :     /*
     291                 :      * This method returns the local variable, argument, etc. names used by a
     292                 :      * script.  This function must be called only when hasLocalNames().
     293                 :      *
     294                 :      * The elements of the vector with index less than nargs correspond to the
     295                 :      * the names of arguments. An index >= nargs addresses a var binding.
     296                 :      * The name at an element will be null when the element is for an argument
     297                 :      * corresponding to a destructuring pattern.
     298                 :      */
     299                 :     bool getLocalNameArray(JSContext *cx, Vector<JSAtom *> *namesp);
     300                 : 
     301                 :     /*
     302                 :      * Protect stored bindings from mutation.  Subsequent attempts to add
     303                 :      * bindings will copy the existing bindings before adding to them, allowing
     304                 :      * the original bindings to be safely shared.
     305                 :      */
     306                 :     void makeImmutable();
     307                 : 
     308                 :     /*
     309                 :      * These methods provide direct access to the shape path normally
     310                 :      * encapsulated by js::Bindings. These methods may be used to make a
     311                 :      * Shape::Range for iterating over the relevant shapes from youngest to
     312                 :      * oldest (i.e., last or right-most to first or left-most in source order).
     313                 :      *
     314                 :      * Sometimes iteration order must be from oldest to youngest, however. For
     315                 :      * such cases, use js::Bindings::getLocalNameArray.
     316                 :      */
     317                 :     const js::Shape *lastArgument() const;
     318                 :     const js::Shape *lastVariable() const;
     319                 :     const js::Shape *lastUpvar() const;
     320                 : 
     321                 :     void trace(JSTracer *trc);
     322                 : 
     323                 :     /* Rooter for stack allocated Bindings. */
     324         2093498 :     struct StackRoot {
     325                 :         RootShape root;
     326         2093498 :         StackRoot(JSContext *cx, Bindings *bindings)
     327         2093498 :             : root(cx, (Shape **) &bindings->lastBinding)
     328         2093498 :         {}
     329                 :     };
     330                 : };
     331                 : 
     332                 : } /* namespace js */
     333                 : 
     334                 : #define JS_OBJECT_ARRAY_SIZE(length)                                          \
     335                 :     (offsetof(JSObjectArray, vector) + sizeof(JSObject *) * (length))
     336                 : 
     337                 : #ifdef JS_METHODJIT
     338                 : namespace JSC {
     339                 :     class ExecutablePool;
     340                 : }
     341                 : 
     342                 : #define JS_UNJITTABLE_SCRIPT (reinterpret_cast<void*>(1))
     343                 : 
     344                 : namespace js { namespace mjit { struct JITScript; } }
     345                 : #endif
     346                 : 
     347                 : namespace js {
     348                 : 
     349                 : namespace analyze { class ScriptAnalysis; }
     350                 : 
     351                 : class ScriptOpcodeCounts
     352                 : {
     353                 :     friend struct ::JSScript;
     354                 :     friend struct ScriptOpcodeCountsPair;
     355                 :     OpcodeCounts *counts;
     356                 : 
     357                 :  public:
     358                 : 
     359               0 :     ScriptOpcodeCounts() : counts(NULL) {
     360               0 :     }
     361                 : 
     362                 :     inline void destroy(JSContext *cx);
     363                 : 
     364               0 :     void steal(ScriptOpcodeCounts &other) {
     365               0 :         *this = other;
     366               0 :         js::PodZero(&other);
     367               0 :     }
     368                 : 
     369                 :     // Boolean conversion, for 'if (counters) ...'
     370     -1737678852 :     operator void*() const {
     371     -1737678852 :         return counts;
     372                 :     }
     373                 : };
     374                 : 
     375                 : class DebugScript
     376                 : {
     377                 :     friend struct ::JSScript;
     378                 : 
     379                 :     /*
     380                 :      * When non-zero, compile script in single-step mode. The top bit is set and
     381                 :      * cleared by setStepMode, as used by JSD. The lower bits are a count,
     382                 :      * adjusted by changeStepModeCount, used by the Debugger object. Only
     383                 :      * when the bit is clear and the count is zero may we compile the script
     384                 :      * without single-step support.
     385                 :      */
     386                 :     uint32_t        stepMode;
     387                 : 
     388                 :     /* Number of breakpoint sites at opcodes in the script. */
     389                 :     uint32_t        numSites;
     390                 : 
     391                 :     /*
     392                 :      * Array with all breakpoints installed at opcodes in the script, indexed
     393                 :      * by the offset of the opcode into the script.
     394                 :      */
     395                 :     BreakpointSite  *breakpoints[1];
     396                 : };
     397                 : 
     398                 : } /* namespace js */
     399                 : 
     400                 : static const uint32_t JS_SCRIPT_COOKIE = 0xc00cee;
     401                 : 
     402                 : struct JSScript : public js::gc::Cell {
     403                 :     /*
     404                 :      * Two successively less primitive ways to make a new JSScript.  The first
     405                 :      * does *not* call a non-null cx->runtime->newScriptHook -- only the second,
     406                 :      * NewScriptFromEmitter, calls this optional debugger hook.
     407                 :      *
     408                 :      * The NewScript function can't know whether the script it creates belongs
     409                 :      * to a function, or is top-level or eval code, but the debugger wants access
     410                 :      * to the newly made script's function, if any -- so callers of NewScript
     411                 :      * are responsible for notifying the debugger after successfully creating any
     412                 :      * kind (function or other) of new JSScript.
     413                 :      */
     414                 :     static JSScript *NewScript(JSContext *cx, uint32_t length, uint32_t nsrcnotes, uint32_t natoms,
     415                 :                                uint32_t nobjects, uint32_t nupvars, uint32_t nregexps,
     416                 :                                uint32_t ntrynotes, uint32_t nconsts, uint32_t nglobals,
     417                 :                                uint16_t nClosedArgs, uint16_t nClosedVars, uint32_t nTypeSets,
     418                 :                                JSVersion version);
     419                 : 
     420                 :     static JSScript *NewScriptFromEmitter(JSContext *cx, js::BytecodeEmitter *bce);
     421                 : 
     422                 : #ifdef JS_CRASH_DIAGNOSTICS
     423                 :     /*
     424                 :      * Make sure that the cookie size does not affect the GC alignment
     425                 :      * requirements.
     426                 :      */
     427                 :     uint32_t        cookie1[Cell::CellSize / sizeof(uint32_t)];
     428                 : #endif
     429                 :     jsbytecode      *code;      /* bytecodes and their immediate operands */
     430                 :     uint8_t         *data;      /* pointer to variable-length data array */
     431                 : 
     432                 :     uint32_t        length;     /* length of code vector */
     433                 :   private:
     434                 :     uint16_t        version;    /* JS version under which script was compiled */
     435                 : 
     436                 :   public:
     437                 :     uint16_t        nfixed;     /* number of slots besides stack operands in
     438                 :                                    slot array */
     439                 :     /*
     440                 :      * Offsets to various array structures from the end of this script, or
     441                 :      * JSScript::INVALID_OFFSET if the array has length 0.
     442                 :      */
     443                 :     uint8_t         objectsOffset;  /* offset to the array of nested function,
     444                 :                                        block, scope, xml and one-time regexps
     445                 :                                        objects */
     446                 :     uint8_t         upvarsOffset;   /* offset of the array of display ("up")
     447                 :                                        closure vars */
     448                 :     uint8_t         regexpsOffset;  /* offset to the array of to-be-cloned
     449                 :                                        regexps  */
     450                 :     uint8_t         trynotesOffset; /* offset to the array of try notes */
     451                 :     uint8_t         globalsOffset;  /* offset to the array of global slots */
     452                 :     uint8_t         constOffset;    /* offset to the array of constants */
     453                 : 
     454                 :     uint16_t        nTypeSets;      /* number of type sets used in this script for
     455                 :                                        dynamic type monitoring */
     456                 : 
     457                 :     uint32_t        lineno;     /* base line number of script */
     458                 : 
     459                 :     uint32_t        mainOffset; /* offset of main entry point from code, after
     460                 :                                    predef'ing prolog */
     461                 :     bool            noScriptRval:1; /* no need for result value of last
     462                 :                                        expression statement */
     463                 :     bool            savedCallerFun:1; /* can call getCallerFunction() */
     464                 :     bool            strictModeCode:1; /* code is in strict mode */
     465                 :     bool            compileAndGo:1;   /* script was compiled with TCF_COMPILE_N_GO */
     466                 :     bool            usesEval:1;       /* script uses eval() */
     467                 :     bool            usesArguments:1;  /* script uses arguments */
     468                 :     bool            warnedAboutTwoArgumentEval:1; /* have warned about use of
     469                 :                                                      obsolete eval(s, o) in
     470                 :                                                      this script */
     471                 :     bool            warnedAboutUndefinedProp:1; /* have warned about uses of
     472                 :                                                    undefined properties in this
     473                 :                                                    script */
     474                 :     bool            hasSingletons:1;  /* script has singleton objects */
     475                 :     bool            isOuterFunction:1; /* function is heavyweight, with inner functions */
     476                 :     bool            isInnerFunction:1; /* function is directly nested in a heavyweight
     477                 :                                         * outer function */
     478                 :     bool            isActiveEval:1;   /* script came from eval(), and is still active */
     479                 :     bool            isCachedEval:1;   /* script came from eval(), and is in eval cache */
     480                 :     bool            usedLazyArgs:1;   /* script has used lazy arguments at some point */
     481                 :     bool            createdArgs:1;    /* script has had arguments objects created */
     482                 :     bool            uninlineable:1;   /* script is considered uninlineable by analysis */
     483                 :     bool            reentrantOuterFunction:1; /* outer function marked reentrant */
     484                 :     bool            typesPurged:1;    /* TypeScript has been purged at some point */
     485                 : #ifdef JS_METHODJIT
     486                 :     bool            debugMode:1;      /* script was compiled in debug mode */
     487                 :     bool            failedBoundsCheck:1; /* script has had hoisted bounds checks fail */
     488                 : #endif
     489                 :     bool            callDestroyHook:1;/* need to call destroy hook */
     490                 : 
     491                 :     uint32_t        natoms;     /* length of atoms array */
     492                 :     uint16_t        nslots;     /* vars plus maximum stack depth */
     493                 :     uint16_t        staticLevel;/* static level for display maintenance */
     494                 : 
     495                 :     uint16_t        nClosedArgs; /* number of args which are closed over. */
     496                 :     uint16_t        nClosedVars; /* number of vars which are closed over. */
     497                 : 
     498                 :     /*
     499                 :      * To ensure sizeof(JSScript) % gc::Cell::CellSize  == 0 on we must pad
     500                 :      * the script with 4 bytes. We use them to store tiny scripts like empty
     501                 :      * scripts.
     502                 :      */
     503                 : #if JS_BITS_PER_WORD == 64
     504                 : #define JS_SCRIPT_INLINE_DATA_LIMIT 4
     505                 :     uint8_t         inlineData[JS_SCRIPT_INLINE_DATA_LIMIT];
     506                 : #endif
     507                 : 
     508                 :     const char      *filename;  /* source filename or null */
     509                 :     JSAtom          **atoms;    /* maps immediate index to literal struct */
     510                 :   private:
     511                 :     size_t          useCount;  /* Number of times the script has been called
     512                 :                                  * or has had backedges taken. Reset if the
     513                 :                                  * script's JIT code is forcibly discarded. */
     514                 :   public:
     515                 :     js::Bindings    bindings;   /* names of top-level variables in this script
     516                 :                                    (and arguments if this is a function script) */
     517                 :     JSPrincipals    *principals;/* principals for this script */
     518                 :     JSPrincipals    *originPrincipals; /* see jsapi.h 'originPrincipals' comment */
     519                 :     jschar          *sourceMap; /* source map file or null */
     520                 : 
     521                 :     /*
     522                 :      * A global object for the script.
     523                 :      * - All scripts returned by JSAPI functions (JS_CompileScript,
     524                 :      *   JS_CompileUTF8File, etc.) have a non-null globalObject.
     525                 :      * - A function script has a globalObject if the function comes from a
     526                 :      *   compile-and-go script.
     527                 :      * - Temporary scripts created by obj_eval, JS_EvaluateScript, and
     528                 :      *   similar functions never have the globalObject field set; for such
     529                 :      *   scripts the global should be extracted from the JS frame that
     530                 :      *   execute scripts.
     531                 :      */
     532                 :     js::HeapPtr<js::GlobalObject, JSScript*> globalObject;
     533                 : 
     534                 :     /* Hash table chaining for JSCompartment::evalCache. */
     535          293618 :     JSScript        *&evalHashLink() { return *globalObject.unsafeGetUnioned(); }
     536                 : 
     537                 :     uint32_t        *closedSlots; /* vector of closed slots; args first, then vars. */
     538                 : 
     539                 :     /* Execution and profiling information for JIT code in the script. */
     540                 :     js::ScriptOpcodeCounts pcCounters;
     541                 : 
     542                 :   private:
     543                 :     js::DebugScript     *debug;
     544                 :     js::HeapPtrFunction function_;
     545                 :   public:
     546                 : 
     547                 :     /*
     548                 :      * Original compiled function for the script, if it has a function.
     549                 :      * NULL for global and eval scripts.
     550                 :      */
     551       133909610 :     JSFunction *function() const { return function_; }
     552                 :     void setFunction(JSFunction *fun);
     553                 : 
     554                 : #ifdef JS_CRASH_DIAGNOSTICS
     555                 :     /* All diagnostic fields must be multiples of Cell::CellSize. */
     556                 :     uint32_t        cookie2[Cell::CellSize / sizeof(uint32_t)];
     557                 : 
     558                 :     void CheckScript(JSScript *prev);
     559                 : #else
     560                 :     void CheckScript(JSScript *prev) {}
     561                 : #endif /* !JS_CRASH_DIAGNOSTICS */
     562                 : 
     563                 : #ifdef DEBUG
     564                 :     /*
     565                 :      * Unique identifier within the compartment for this script, used for
     566                 :      * printing analysis information.
     567                 :      */
     568                 :     uint32_t id_;
     569                 :     uint32_t idpad;
     570                 :     unsigned id();
     571                 : #else
     572                 :     unsigned id() { return 0; }
     573                 : #endif
     574                 : 
     575                 :     /* Persistent type information retained across GCs. */
     576                 :     js::types::TypeScript *types;
     577                 : 
     578                 : #if JS_BITS_PER_WORD == 32
     579                 :   private:
     580                 :     void *padding_;
     581                 :   public:
     582                 : #endif
     583                 : 
     584                 :     /* Ensure the script has a TypeScript. */
     585                 :     inline bool ensureHasTypes(JSContext *cx);
     586                 : 
     587                 :     /*
     588                 :      * Ensure the script has scope and bytecode analysis information.
     589                 :      * Performed when the script first runs, or first runs after a TypeScript
     590                 :      * GC purge. If scope is NULL then the script must already have types with
     591                 :      * scope information.
     592                 :      */
     593                 :     inline bool ensureRanAnalysis(JSContext *cx, JSObject *scope);
     594                 : 
     595                 :     /* Ensure the script has type inference analysis information. */
     596                 :     inline bool ensureRanInference(JSContext *cx);
     597                 : 
     598                 :     inline bool hasAnalysis();
     599                 :     inline void clearAnalysis();
     600                 :     inline js::analyze::ScriptAnalysis *analysis();
     601                 : 
     602                 :     /*
     603                 :      * Associates this script with a specific function, constructing a new type
     604                 :      * object for the function if necessary.
     605                 :      */
     606                 :     bool typeSetFunction(JSContext *cx, JSFunction *fun, bool singleton = false);
     607                 : 
     608                 :     inline bool hasGlobal() const;
     609                 :     inline bool hasClearedGlobal() const;
     610                 : 
     611                 :     inline js::GlobalObject *global() const;
     612                 :     inline js::types::TypeScriptNesting *nesting() const;
     613                 : 
     614                 :     inline void clearNesting();
     615                 : 
     616                 :     /* Return creation time global or null. */
     617            1686 :     js::GlobalObject *getGlobalObjectOrNull() const {
     618            1686 :         return isCachedEval ? NULL : globalObject.get();
     619                 :     }
     620                 : 
     621                 :   private:
     622                 :     bool makeTypes(JSContext *cx);
     623                 :     bool makeAnalysis(JSContext *cx);
     624                 :   public:
     625                 : 
     626                 : #ifdef JS_METHODJIT
     627                 :     // Fast-cached pointers to make calls faster. These are also used to
     628                 :     // quickly test whether there is JIT code; a NULL value means no
     629                 :     // compilation has been attempted. A JS_UNJITTABLE_SCRIPT value means
     630                 :     // compilation failed. Any value is the arity-check entry point.
     631                 :     void *jitArityCheckNormal;
     632                 :     void *jitArityCheckCtor;
     633                 : 
     634                 :     js::mjit::JITScript *jitNormal;   /* Extra JIT info for normal scripts */
     635                 :     js::mjit::JITScript *jitCtor;     /* Extra JIT info for constructors */
     636                 : #endif
     637                 : 
     638                 : #ifdef JS_METHODJIT
     639           48092 :     bool hasJITCode() {
     640           48092 :         return jitNormal || jitCtor;
     641                 :     }
     642                 : 
     643                 :     // These methods are implemented in MethodJIT.h.
     644                 :     inline void **nativeMap(bool constructing);
     645                 :     inline void *nativeCodeForPC(bool constructing, jsbytecode *pc);
     646                 : 
     647        39677746 :     js::mjit::JITScript *getJIT(bool constructing) {
     648        39677746 :         return constructing ? jitCtor : jitNormal;
     649                 :     }
     650                 : 
     651           26302 :     size_t getUseCount() const  { return useCount; }
     652         9938535 :     size_t incUseCount() { return ++useCount; }
     653            2737 :     size_t *addressOfUseCount() { return &useCount; }
     654         8108534 :     void resetUseCount() { useCount = 0; }
     655                 : 
     656                 :     /*
     657                 :      * Size of the JITScript and all sections.  If |mallocSizeOf| is NULL, the
     658                 :      * size is computed analytically.  (This method is implemented in
     659                 :      * MethodJIT.cpp.)
     660                 :      */
     661                 :     size_t sizeOfJitScripts(JSMallocSizeOfFun mallocSizeOf);
     662                 : 
     663                 : #endif
     664                 : 
     665                 :     /* Counter accessors. */
     666               0 :     js::OpcodeCounts getCounts(jsbytecode *pc) {
     667               0 :         JS_ASSERT(size_t(pc - code) < length);
     668               0 :         return pcCounters.counts[pc - code];
     669                 :     }
     670                 : 
     671                 :     bool initCounts(JSContext *cx);
     672                 :     void destroyCounts(JSContext *cx);
     673                 : 
     674         3470627 :     jsbytecode *main() {
     675         3470627 :         return code + mainOffset;
     676                 :     }
     677                 : 
     678                 :     /*
     679                 :      * computedSizeOfData() is the in-use size of all the data sections.
     680                 :      * sizeOfData() is the size of the block allocated to hold all the data sections
     681                 :      * (which can be larger than the in-use size).
     682                 :      */
     683                 :     size_t computedSizeOfData();
     684                 :     size_t sizeOfData(JSMallocSizeOfFun mallocSizeOf);
     685                 : 
     686                 :     uint32_t numNotes();  /* Number of srcnote slots in the srcnotes section */
     687                 : 
     688                 :     /* Script notes are allocated right after the code. */
     689        38652984 :     jssrcnote *notes() { return (jssrcnote *)(code + length); }
     690                 : 
     691                 :     static const uint8_t INVALID_OFFSET = 0xFF;
     692        48493575 :     static bool isValidOffset(uint8_t offset) { return offset != INVALID_OFFSET; }
     693                 : 
     694         9753379 :     JSObjectArray *objects() {
     695         9753379 :         JS_ASSERT(isValidOffset(objectsOffset));
     696         9753379 :         return reinterpret_cast<JSObjectArray *>(data + objectsOffset);
     697                 :     }
     698                 : 
     699         3141733 :     JSUpvarArray *upvars() {
     700         3141733 :         JS_ASSERT(isValidOffset(upvarsOffset));
     701         3141733 :         return reinterpret_cast<JSUpvarArray *>(data + upvarsOffset);
     702                 :     }
     703                 : 
     704          387713 :     JSObjectArray *regexps() {
     705          387713 :         JS_ASSERT(isValidOffset(regexpsOffset));
     706          387713 :         return reinterpret_cast<JSObjectArray *>(data + regexpsOffset);
     707                 :     }
     708                 : 
     709         1631955 :     JSTryNoteArray *trynotes() {
     710         1631955 :         JS_ASSERT(isValidOffset(trynotesOffset));
     711         1631955 :         return reinterpret_cast<JSTryNoteArray *>(data + trynotesOffset);
     712                 :     }
     713                 : 
     714           51196 :     js::GlobalSlotArray *globals() {
     715           51196 :         JS_ASSERT(isValidOffset(globalsOffset));
     716           51196 :         return reinterpret_cast<js::GlobalSlotArray *>(data + globalsOffset);
     717                 :     }
     718                 : 
     719         1653197 :     JSConstArray *consts() {
     720         1653197 :         JS_ASSERT(isValidOffset(constOffset));
     721         1653197 :         return reinterpret_cast<JSConstArray *>(data + constOffset);
     722                 :     }
     723                 : 
     724        35770964 :     JSAtom *getAtom(size_t index) {
     725        35770964 :         JS_ASSERT(index < natoms);
     726        35770964 :         return atoms[index];
     727                 :     }
     728                 : 
     729         2238353 :     js::PropertyName *getName(size_t index) {
     730         2238353 :         return getAtom(index)->asPropertyName();
     731                 :     }
     732                 : 
     733         4314897 :     JSObject *getObject(size_t index) {
     734         4314897 :         JSObjectArray *arr = objects();
     735         4314897 :         JS_ASSERT(index < arr->length);
     736         4314897 :         return arr->vector[index];
     737                 :     }
     738                 : 
     739         6435474 :     JSVersion getVersion() const {
     740         6435474 :         return JSVersion(version);
     741                 :     }
     742                 : 
     743                 :     inline JSFunction *getFunction(size_t index);
     744                 :     inline JSFunction *getCallerFunction();
     745                 : 
     746                 :     inline JSObject *getRegExp(size_t index);
     747                 : 
     748         1515459 :     const js::Value &getConst(size_t index) {
     749         1515459 :         JSConstArray *arr = consts();
     750         1515459 :         JS_ASSERT(index < arr->length);
     751         1515459 :         return arr->vector[index];
     752                 :     }
     753                 : 
     754                 :     /*
     755                 :      * The isEmpty method tells whether this script has code that computes any
     756                 :      * result (not return value, result AKA normal completion value) other than
     757                 :      * JSVAL_VOID, or any other effects.
     758                 :      */
     759                 :     inline bool isEmpty() const;
     760                 : 
     761          491553 :     uint32_t getClosedArg(uint32_t index) {
     762          491553 :         JS_ASSERT(index < nClosedArgs);
     763          491553 :         return closedSlots[index];
     764                 :     }
     765                 : 
     766          288961 :     uint32_t getClosedVar(uint32_t index) {
     767          288961 :         JS_ASSERT(index < nClosedVars);
     768          288961 :         return closedSlots[nClosedArgs + index];
     769                 :     }
     770                 : 
     771                 :     void copyClosedSlotsTo(JSScript *other);
     772                 : 
     773                 :   private:
     774                 :     static const uint32_t stepFlagMask = 0x80000000U;
     775                 :     static const uint32_t stepCountMask = 0x7fffffffU;
     776                 : 
     777                 :     /*
     778                 :      * Attempt to recompile with or without single-stepping support, as directed
     779                 :      * by stepModeEnabled().
     780                 :      */
     781                 :     bool recompileForStepMode(JSContext *cx);
     782                 : 
     783                 :     /* Attempt to change this->stepMode to |newValue|. */
     784                 :     bool tryNewStepMode(JSContext *cx, uint32_t newValue);
     785                 : 
     786                 :     bool ensureHasDebug(JSContext *cx);
     787                 : 
     788                 :   public:
     789       143689538 :     bool hasBreakpointsAt(jsbytecode *pc) { return !!getBreakpointSite(pc); }
     790        35516783 :     bool hasAnyBreakpointsOrStepMode() { return !!debug; }
     791                 : 
     792       152606042 :     js::BreakpointSite *getBreakpointSite(jsbytecode *pc)
     793                 :     {
     794       152606042 :         JS_ASSERT(size_t(pc - code) < length);
     795       152606042 :         return debug ? debug->breakpoints[pc - code] : NULL;
     796                 :     }
     797                 : 
     798                 :     js::BreakpointSite *getOrCreateBreakpointSite(JSContext *cx, jsbytecode *pc,
     799                 :                                                   js::GlobalObject *scriptGlobal);
     800                 : 
     801                 :     void destroyBreakpointSite(JSRuntime *rt, jsbytecode *pc);
     802                 : 
     803                 :     void clearBreakpointsIn(JSContext *cx, js::Debugger *dbg, JSObject *handler);
     804                 :     void clearTraps(JSContext *cx);
     805                 : 
     806                 :     void markTrapClosures(JSTracer *trc);
     807                 : 
     808                 :     /*
     809                 :      * Set or clear the single-step flag. If the flag is set or the count
     810                 :      * (adjusted by changeStepModeCount) is non-zero, then the script is in
     811                 :      * single-step mode. (JSD uses an on/off-style interface; Debugger uses a
     812                 :      * count-style interface.)
     813                 :      */
     814                 :     bool setStepModeFlag(JSContext *cx, bool step);
     815                 : 
     816                 :     /*
     817                 :      * Increment or decrement the single-step count. If the count is non-zero or
     818                 :      * the flag (set by setStepModeFlag) is set, then the script is in
     819                 :      * single-step mode. (JSD uses an on/off-style interface; Debugger uses a
     820                 :      * count-style interface.)
     821                 :      */
     822                 :     bool changeStepModeCount(JSContext *cx, int delta);
     823                 : 
     824         8846094 :     bool stepModeEnabled() { return debug && !!debug->stepMode; }
     825                 : 
     826                 : #ifdef DEBUG
     827            5785 :     uint32_t stepModeCount() { return debug ? (debug->stepMode & stepCountMask) : 0; }
     828                 : #endif
     829                 : 
     830                 :     void finalize(JSContext *cx, bool background);
     831                 : 
     832                 :     static inline void writeBarrierPre(JSScript *script);
     833                 :     static inline void writeBarrierPost(JSScript *script, void *addr);
     834                 : 
     835                 :     static inline js::ThingRootKind rootKind() { return js::THING_ROOT_SCRIPT; }
     836                 : 
     837          141277 :     static JSPrincipals *normalizeOriginPrincipals(JSPrincipals *principals,
     838                 :                                                    JSPrincipals *originPrincipals) {
     839          141277 :         return originPrincipals ? originPrincipals : principals;
     840                 :     }
     841                 : 
     842                 :     void markChildren(JSTracer *trc);
     843                 : };
     844                 : 
     845                 : /* If this fails, padding_ can be removed. */
     846                 : JS_STATIC_ASSERT(sizeof(JSScript) % js::gc::Cell::CellSize == 0);
     847                 : 
     848                 : static JS_INLINE unsigned
     849        71057769 : StackDepth(JSScript *script)
     850                 : {
     851        71057769 :     return script->nslots - script->nfixed;
     852                 : }
     853                 : 
     854                 : extern void
     855                 : js_MarkScriptFilename(const char *filename);
     856                 : 
     857                 : extern void
     858                 : js_SweepScriptFilenames(JSCompartment *comp);
     859                 : 
     860                 : /*
     861                 :  * New-script-hook calling is factored from NewScriptFromEmitter so that it
     862                 :  * and callers of XDRScript can share this code.  In the case of callers
     863                 :  * of XDRScript, the hook should be invoked only after successful decode
     864                 :  * of any owning function (the fun parameter) or script object (null fun).
     865                 :  */
     866                 : extern JS_FRIEND_API(void)
     867                 : js_CallNewScriptHook(JSContext *cx, JSScript *script, JSFunction *fun);
     868                 : 
     869                 : extern void
     870                 : js_CallDestroyScriptHook(JSContext *cx, JSScript *script);
     871                 : 
     872                 : namespace js {
     873                 : 
     874                 : struct ScriptOpcodeCountsPair
     875               0 : {
     876                 :     JSScript *script;
     877                 :     ScriptOpcodeCounts counters;
     878                 : 
     879               0 :     OpcodeCounts &getCounts(jsbytecode *pc) const {
     880               0 :         JS_ASSERT(unsigned(pc - script->code) < script->length);
     881               0 :         return counters.counts[pc - script->code];
     882                 :     }
     883                 : };
     884                 : 
     885                 : #ifdef JS_CRASH_DIAGNOSTICS
     886                 : 
     887                 : void
     888                 : CheckScript(JSScript *script, JSScript *prev);
     889                 : 
     890                 : #else
     891                 : 
     892                 : inline void
     893                 : CheckScript(JSScript *script, JSScript *prev)
     894                 : {
     895                 : }
     896                 : 
     897                 : #endif /* !JS_CRASH_DIAGNOSTICS */
     898                 : 
     899                 : } /* namespace js */
     900                 : 
     901                 : /*
     902                 :  * To perturb as little code as possible, we introduce a js_GetSrcNote lookup
     903                 :  * cache without adding an explicit cx parameter.  Thus js_GetSrcNote becomes
     904                 :  * a macro that uses cx from its calls' lexical environments.
     905                 :  */
     906                 : #define js_GetSrcNote(script,pc) js_GetSrcNoteCached(cx, script, pc)
     907                 : 
     908                 : extern jssrcnote *
     909                 : js_GetSrcNoteCached(JSContext *cx, JSScript *script, jsbytecode *pc);
     910                 : 
     911                 : extern jsbytecode *
     912                 : js_LineNumberToPC(JSScript *script, unsigned lineno);
     913                 : 
     914                 : extern JS_FRIEND_API(unsigned)
     915                 : js_GetScriptLineExtent(JSScript *script);
     916                 : 
     917                 : namespace js {
     918                 : 
     919                 : extern unsigned
     920                 : PCToLineNumber(JSScript *script, jsbytecode *pc);
     921                 : 
     922                 : extern unsigned
     923                 : PCToLineNumber(unsigned startLine, jssrcnote *notes, jsbytecode *code, jsbytecode *pc);
     924                 : 
     925                 : extern unsigned
     926                 : CurrentLine(JSContext *cx);
     927                 : 
     928                 : /*
     929                 :  * This function returns the file and line number of the script currently
     930                 :  * executing on cx. If there is no current script executing on cx (e.g., a
     931                 :  * native called directly through JSAPI (e.g., by setTimeout)), NULL and 0 are
     932                 :  * returned as the file and line. Additionally, this function avoids the full
     933                 :  * linear scan to compute line number when the caller guarnatees that the
     934                 :  * script compilation occurs at a JSOP_EVAL.
     935                 :  */
     936                 : 
     937                 : enum LineOption {
     938                 :     CALLED_FROM_JSOP_EVAL,
     939                 :     NOT_CALLED_FROM_JSOP_EVAL
     940                 : };
     941                 : 
     942                 : inline void
     943                 : CurrentScriptFileLineOrigin(JSContext *cx, unsigned *linenop, LineOption = NOT_CALLED_FROM_JSOP_EVAL);
     944                 : 
     945                 : extern JSScript *
     946                 : CloneScript(JSContext *cx, JSScript *script);
     947                 : 
     948                 : /*
     949                 :  * NB: after a successful JSXDR_DECODE, XDRScript callers must do any
     950                 :  * required subsequent set-up of owning function or script object and then call
     951                 :  * js_CallNewScriptHook.
     952                 :  */
     953                 : extern JSBool
     954                 : XDRScript(JSXDRState *xdr, JSScript **scriptp);
     955                 : 
     956                 : }
     957                 : 
     958                 : #endif /* jsscript_h___ */

Generated by: LCOV version 1.7