LCOV - app.info - js/src/jsscript.h

LCOV - code coverage report
| Current view: | directory - js/src - jsscript.h (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 135 | 122 | 90.4 %
| Date: | 2012-04-07 | Functions: | 70 | 64 | 91.4 %

           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                 : /*
          67                 :  * Exception handling record.
          68                 :  */
          69                 : struct JSTryNote {
          70                 :     uint8_t         kind;       /* one of JSTryNoteKind */
          71                 :     uint8_t         padding;    /* explicit padding on uint16_t boundary */
          72                 :     uint16_t        stackDepth; /* stack depth upon exception handler entry */
          73                 :     uint32_t        start;      /* start of the try statement or for-in loop
          74                 :                                    relative to script->main */
          75                 :     uint32_t        length;     /* length of the try statement or for-in loop */
          76                 : };
          77                 :
          78                 : typedef struct JSTryNoteArray {
          79                 :     JSTryNote       *vector;    /* array of indexed try notes */
          80                 :     uint32_t        length;     /* count of indexed try notes */
          81                 : } JSTryNoteArray;
          82                 :
          83                 : typedef struct JSObjectArray {
          84                 :     js::HeapPtrObject *vector;  /* array of indexed objects */
          85                 :     uint32_t        length;     /* count of indexed objects */
          86                 : } JSObjectArray;
          87                 :
          88                 : typedef struct JSConstArray {
          89                 :     js::HeapValue   *vector;    /* array of indexed constant values */
          90                 :     uint32_t        length;
          91                 : } JSConstArray;
          92                 :
          93                 : namespace js {
          94                 :
          95                 : struct GlobalSlotArray {
          96           31065 :     struct Entry {
          97                 :         uint32_t    atomIndex;  /* index into atom table */
          98                 :         uint32_t    slot;       /* global obj slot number */
          99                 :     };
         100                 :     Entry           *vector;
         101                 :     uint32_t        length;
         102                 : };
         103                 :
         104                 : struct ClosedSlotArray {
         105                 :     uint32_t        *vector;    /* array of closed slots */
         106                 :     uint32_t        length;     /* count of closed slots */
         107                 : };
         108                 :
         109                 : struct Shape;
         110                 :
         111                 : enum BindingKind { NONE, ARGUMENT, VARIABLE, CONSTANT };
         112                 :
         113                 : /*
         114                 :  * Formal parameters and local variables are stored in a shape tree
         115                 :  * path encapsulated within this class.  This class represents bindings for
         116                 :  * both function and top-level scripts (the latter is needed to track names in
         117                 :  * strict mode eval code, to give such code its own lexical environment).
         118                 :  */
         119                 : class Bindings
         120         1018770 : {
         121                 :     HeapPtr<Shape> lastBinding;
         122                 :     uint16_t nargs;
         123                 :     uint16_t nvars;
         124                 :     bool     hasDup_:1;     // true if there are duplicate argument names
         125                 :
         126                 :     inline Shape *initialShape(JSContext *cx) const;
         127                 :   public:
         128                 :     inline Bindings(JSContext *cx);
         129                 :
         130                 :     /*
         131                 :      * Transfers ownership of bindings data from bindings into this fresh
         132                 :      * Bindings instance. Once such a transfer occurs, the old bindings must
         133                 :      * not be used again.
         134                 :      */
         135                 :     inline void transfer(JSContext *cx, Bindings *bindings);
         136                 :
         137                 :     /*
         138                 :      * Clones bindings data from bindings, which must be immutable, into this
         139                 :      * fresh Bindings instance. A Bindings instance may be cloned multiple
         140                 :      * times.
         141                 :      */
         142                 :     inline void clone(JSContext *cx, Bindings *bindings);
         143                 :
         144         1099847 :     uint16_t countArgs() const { return nargs; }
         145         2302618 :     uint16_t countVars() const { return nvars; }
         146                 :
         147          834845 :     unsigned countLocalNames() const { return nargs + nvars; }
         148                 :
         149           24825 :     bool hasLocalNames() const { return countLocalNames() > 0; }
         150                 :
         151                 :     /* Ensure these bindings have a shape lineage. */
         152                 :     inline bool ensureShape(JSContext *cx);
         153                 :
         154                 :     /* Return the shape lineage generated for these bindings. */
         155                 :     inline Shape *lastShape() const;
         156                 :
         157                 :     /*
         158                 :      * Return the shape to use to create a call object for these bindings.
         159                 :      * The result is guaranteed not to have duplicate property names.
         160                 :      */
         161                 :     Shape *callObjectShape(JSContext *cx) const;
         162                 :
         163                 :     /* See Scope::extensibleParents */
         164                 :     inline bool extensibleParents();
         165                 :     bool setExtensibleParents(JSContext *cx);
         166                 :
         167                 :     bool setParent(JSContext *cx, JSObject *obj);
         168                 :
         169                 :     enum {
         170                 :         /* A script may have no more than this many arguments or variables. */
         171                 :         BINDING_COUNT_LIMIT = 0xFFFF
         172                 :     };
         173                 :
         174                 :     /*
         175                 :      * Add a local binding for the given name, of the given type, for the code
         176                 :      * being compiled.  If fun is non-null, this binding set is being created
         177                 :      * for that function, so adjust corresponding metadata in that function
         178                 :      * while adding.  Otherwise this set must correspond to a top-level script.
         179                 :      *
         180                 :      * A binding may be added twice with different kinds; the last one for a
         181                 :      * given name prevails.  (We preserve both bindings for the decompiler,
         182                 :      * which must deal with such cases.)  Pass null for name when indicating a
         183                 :      * destructuring argument.  Return true on success.
         184                 :      *
         185                 :      * The parser builds shape paths for functions, usable by Call objects at
         186                 :      * runtime, by calling an "add" method. All ARGUMENT bindings must be added
         187                 :      * before before any VARIABLE or CONSTANT bindings.
         188                 :      */
         189                 :     bool add(JSContext *cx, JSAtom *name, BindingKind kind);
         190                 :
         191                 :     /* Convenience specializations. */
         192            3771 :     bool addVariable(JSContext *cx, JSAtom *name) {
         193            3771 :         return add(cx, name, VARIABLE);
         194                 :     }
         195                 :     bool addConstant(JSContext *cx, JSAtom *name) {
         196                 :         return add(cx, name, CONSTANT);
         197                 :     }
         198          226887 :     bool addArgument(JSContext *cx, JSAtom *name, uint16_t *slotp) {
         199          226887 :         JS_ASSERT(name != NULL); /* not destructuring */
         200          226887 :         *slotp = nargs;
         201          226887 :         return add(cx, name, ARGUMENT);
         202                 :     }
         203              81 :     bool addDestructuring(JSContext *cx, uint16_t *slotp) {
         204              81 :         *slotp = nargs;
         205              81 :         return add(cx, NULL, ARGUMENT);
         206                 :     }
         207                 :
         208              18 :     void noteDup() { hasDup_ = true; }
         209          745077 :     bool hasDup() const { return hasDup_; }
         210                 :
         211                 :     /*
         212                 :      * Look up an argument or variable name, returning its kind when found or
         213                 :      * NONE when no such name exists. When indexp is not null and the name
         214                 :      * exists, *indexp will receive the index of the corresponding argument or
         215                 :      * variable.
         216                 :      */
         217                 :     BindingKind lookup(JSContext *cx, JSAtom *name, unsigned *indexp) const;
         218                 :
         219                 :     /* Convenience method to check for any binding for a name. */
         220          489783 :     bool hasBinding(JSContext *cx, JSAtom *name) const {
         221          489783 :         return lookup(cx, name, NULL) != NONE;
         222                 :     }
         223                 :
         224                 :     /*
         225                 :      * This method returns the local variable, argument, etc. names used by a
         226                 :      * script.  This function must be called only when hasLocalNames().
         227                 :      *
         228                 :      * The elements of the vector with index less than nargs correspond to the
         229                 :      * the names of arguments. An index >= nargs addresses a var binding.
         230                 :      * The name at an element will be null when the element is for an argument
         231                 :      * corresponding to a destructuring pattern.
         232                 :      */
         233                 :     bool getLocalNameArray(JSContext *cx, Vector<JSAtom *> *namesp);
         234                 :
         235                 :     /*
         236                 :      * Protect stored bindings from mutation.  Subsequent attempts to add
         237                 :      * bindings will copy the existing bindings before adding to them, allowing
         238                 :      * the original bindings to be safely shared.
         239                 :      */
         240                 :     void makeImmutable();
         241                 :
         242                 :     /*
         243                 :      * These methods provide direct access to the shape path normally
         244                 :      * encapsulated by js::Bindings. These methods may be used to make a
         245                 :      * Shape::Range for iterating over the relevant shapes from youngest to
         246                 :      * oldest (i.e., last or right-most to first or left-most in source order).
         247                 :      *
         248                 :      * Sometimes iteration order must be from oldest to youngest, however. For
         249                 :      * such cases, use js::Bindings::getLocalNameArray.
         250                 :      */
         251                 :     const js::Shape *lastArgument() const;
         252                 :     const js::Shape *lastVariable() const;
         253                 :
         254                 :     void trace(JSTracer *trc);
         255                 :
         256                 :     /* Rooter for stack allocated Bindings. */
         257          420122 :     struct StackRoot {
         258                 :         RootShape root;
         259          420122 :         StackRoot(JSContext *cx, Bindings *bindings)
         260          420122 :             : root(cx, (Shape **) &bindings->lastBinding)
         261          420122 :         {}
         262                 :     };
         263                 : };
         264                 :
         265                 : } /* namespace js */
         266                 :
         267                 : #define JS_OBJECT_ARRAY_SIZE(length)                                          \
         268                 :     (offsetof(JSObjectArray, vector) + sizeof(JSObject *) * (length))
         269                 :
         270                 : #ifdef JS_METHODJIT
         271                 : namespace JSC {
         272                 :     class ExecutablePool;
         273                 : }
         274                 :
         275                 : namespace js {
         276                 : namespace mjit {
         277                 :     struct JITScript;
         278                 :     class CallCompiler;
         279                 : }
         280                 : }
         281                 :
         282                 : #endif
         283                 :
         284                 : namespace js {
         285                 :
         286                 : namespace analyze { class ScriptAnalysis; }
         287                 :
         288                 : class ScriptCounts
         289                 : {
         290                 :     friend struct ::JSScript;
         291                 :     friend struct ScriptAndCounts;
         292                 :     /*
         293                 :      * This points to a single block that holds an array of PCCounts followed
         294                 :      * by an array of doubles.  Each element in the PCCounts array has a
         295                 :      * pointer into the array of doubles.
         296                 :      */
         297                 :     PCCounts *pcCountsVector;
         298                 :
         299                 :  public:
         300                 :
         301               0 :     ScriptCounts() : pcCountsVector(NULL) {
         302               0 :     }
         303                 :
         304                 :     inline void destroy(JSContext *cx);
         305                 :
         306               0 :     void steal(ScriptCounts &other) {
         307               0 :         *this = other;
         308               0 :         js::PodZero(&other);
         309               0 :     }
         310                 :
         311                 :     // Boolean conversion, for 'if (scriptCounts) ...'
         312     -2016551605 :     operator void*() const {
         313     -2016551605 :         return pcCountsVector;
         314                 :     }
         315                 : };
         316                 :
         317                 : class DebugScript
         318                 : {
         319                 :     friend struct ::JSScript;
         320                 :
         321                 :     /*
         322                 :      * When non-zero, compile script in single-step mode. The top bit is set and
         323                 :      * cleared by setStepMode, as used by JSD. The lower bits are a count,
         324                 :      * adjusted by changeStepModeCount, used by the Debugger object. Only
         325                 :      * when the bit is clear and the count is zero may we compile the script
         326                 :      * without single-step support.
         327                 :      */
         328                 :     uint32_t        stepMode;
         329                 :
         330                 :     /* Number of breakpoint sites at opcodes in the script. */
         331                 :     uint32_t        numSites;
         332                 :
         333                 :     /*
         334                 :      * Array with all breakpoints installed at opcodes in the script, indexed
         335                 :      * by the offset of the opcode into the script.
         336                 :      */
         337                 :     BreakpointSite  *breakpoints[1];
         338                 : };
         339                 :
         340                 : } /* namespace js */
         341                 :
         342                 : static const uint32_t JS_SCRIPT_COOKIE = 0xc00cee;
         343                 :
         344                 : struct JSScript : public js::gc::Cell
         345                 : {
         346                 :   private:
         347                 :     static const uint32_t stepFlagMask = 0x80000000U;
         348                 :     static const uint32_t stepCountMask = 0x7fffffffU;
         349                 :
         350                 :   public:
         351                 :     // This type wraps JITScript.  It has three possible states.
         352                 :     // - "Empty": no compilation has been attempted and there is no JITScript.
         353                 :     // - "Unjittable": compilation failed and there is no JITScript.
         354                 :     // - "Valid": compilation succeeded and there is a JITScript.
         355                 :     class JITScriptHandle
         356                 :     {
         357                 :         // CallCompiler must be a friend because it generates code that uses
         358                 :         // UNJITTABLE.
         359                 :         friend class js::mjit::CallCompiler;
         360                 :
         361                 :         // The exact representation:
         362                 :         // - NULL means "empty".
         363                 :         // - UNJITTABLE means "unjittable".
         364                 :         // - Any other value means "valid".
         365                 :         // UNJITTABLE = 1 so that we can check that a JITScript is valid
         366                 :         // with a single |> 1| test.  It's defined outside the class because
         367                 :         // non-integral static const fields can't be defined in the class.
         368                 :         static const js::mjit::JITScript *UNJITTABLE;   // = (JITScript *)1;
         369                 :         js::mjit::JITScript *value;
         370                 :
         371                 :       public:
         372                 :         JITScriptHandle()       { value = NULL; }
         373                 :
         374        12505470 :         bool isEmpty()          { return value == NULL; }
         375        13978427 :         bool isUnjittable()     { return value == UNJITTABLE; }
         376        47333215 :         bool isValid()          { return value  > UNJITTABLE; }
         377                 :
         378        28486721 :         js::mjit::JITScript *getValid() {
         379        28486721 :             JS_ASSERT(isValid());
         380        28486721 :             return value;
         381                 :         }
         382                 :
         383           75536 :         void setEmpty()         { value = NULL; }
         384            2131 :         void setUnjittable()    { value = const_cast<js::mjit::JITScript *>(UNJITTABLE); }
         385           75536 :         void setValid(js::mjit::JITScript *jit) {
         386           75536 :             value = jit;
         387           75536 :             JS_ASSERT(isValid());
         388           75536 :         }
         389                 :
         390                 :         static void staticAsserts();
         391                 :     };
         392                 :
         393                 :     //
         394                 :     // We order fields according to their size in order to avoid wasting space
         395                 :     // for alignment.
         396                 :     //
         397                 :
         398                 :     // Larger-than-word-sized fields.
         399                 :
         400                 :   public:
         401                 :     js::Bindings    bindings;   /* names of top-level variables in this script
         402                 :                                    (and arguments if this is a function script) */
         403                 :
         404                 :     // Word-sized fields.
         405                 :
         406                 :   public:
         407                 :     jsbytecode      *code;      /* bytecodes and their immediate operands */
         408                 :     uint8_t         *data;      /* pointer to variable-length data array (see
         409                 :                                    comment above NewScript() for details) */
         410                 :
         411                 :     const char      *filename;  /* source filename or null */
         412                 :     JSAtom          **atoms;    /* maps immediate index to literal struct */
         413                 :
         414                 :     JSPrincipals    *principals;/* principals for this script */
         415                 :     JSPrincipals    *originPrincipals; /* see jsapi.h 'originPrincipals' comment */
         416                 :
         417                 :     jschar          *sourceMap; /* source map file or null */
         418                 :
         419                 :     /*
         420                 :      * A global object for the script.
         421                 :      * - All scripts returned by JSAPI functions (JS_CompileScript,
         422                 :      *   JS_CompileUTF8File, etc.) have a non-null globalObject.
         423                 :      * - A function script has a globalObject if the function comes from a
         424                 :      *   compile-and-go script.
         425                 :      * - Temporary scripts created by obj_eval, JS_EvaluateScript, and
         426                 :      *   similar functions never have the globalObject field set; for such
         427                 :      *   scripts the global should be extracted from the JS frame that
         428                 :      *   execute scripts.
         429                 :      */
         430                 :     js::HeapPtr<js::GlobalObject, JSScript*> globalObject;
         431                 :
         432                 :     /* Execution and profiling information for JIT code in the script. */
         433                 :     js::ScriptCounts scriptCounts;
         434                 :
         435                 :     /* Persistent type information retained across GCs. */
         436                 :     js::types::TypeScript *types;
         437                 :
         438                 :   public:
         439                 : #ifdef JS_METHODJIT
         440                 :     JITScriptHandle jitHandleNormal; // extra JIT info for normal scripts
         441                 :     JITScriptHandle jitHandleCtor;   // extra JIT info for constructors
         442                 : #endif
         443                 :
         444                 :   private:
         445                 :     js::DebugScript     *debug;
         446                 :     js::HeapPtrFunction function_;
         447                 :
         448                 :     size_t          useCount;   /* Number of times the script has been called
         449                 :                                  * or has had backedges taken. Reset if the
         450                 :                                  * script's JIT code is forcibly discarded. */
         451                 : #if JS_BITS_PER_WORD == 32
         452                 :     void *padding_;
         453                 : #endif
         454                 :
         455                 :     // 32-bit fields.
         456                 :
         457                 :   public:
         458                 :     uint32_t        length;     /* length of code vector */
         459                 :
         460                 :     uint32_t        lineno;     /* base line number of script */
         461                 :
         462                 :     uint32_t        mainOffset; /* offset of main entry point from code, after
         463                 :                                    predef'ing prolog */
         464                 :
         465                 :     uint32_t        natoms;     /* length of atoms array */
         466                 :
         467                 : #ifdef DEBUG
         468                 :     // Unique identifier within the compartment for this script, used for
         469                 :     // printing analysis information.
         470                 :     uint32_t        id_;
         471                 :   private:
         472                 :     uint32_t        idpad;
         473                 :   public:
         474                 : #endif
         475                 :
         476                 :     // 16-bit fields.
         477                 :
         478                 :   private:
         479                 :     uint16_t        version;    /* JS version under which script was compiled */
         480                 :
         481                 :   public:
         482                 :     uint16_t        nfixed;     /* number of slots besides stack operands in
         483                 :                                    slot array */
         484                 :
         485                 :     uint16_t        nTypeSets;  /* number of type sets used in this script for
         486                 :                                    dynamic type monitoring */
         487                 :
         488                 :     uint16_t        nslots;     /* vars plus maximum stack depth */
         489                 :     uint16_t        staticLevel;/* static level for display maintenance */
         490                 :
         491                 :     // 8-bit fields.
         492                 :
         493                 :   public:
         494                 :     // Offsets to various array structures from the end of this script, or
         495                 :     // JSScript::INVALID_OFFSET if the array has length 0.
         496                 :     uint8_t         constsOffset;   /* offset to the array of constants */
         497                 :     uint8_t         objectsOffset;  /* offset to the array of nested function,
         498                 :                                        block, scope, xml and one-time regexps
         499                 :                                        objects */
         500                 :     uint8_t         regexpsOffset;  /* offset to the array of to-be-cloned
         501                 :                                        regexps  */
         502                 :     uint8_t         trynotesOffset; /* offset to the array of try notes */
         503                 :     uint8_t         globalsOffset;  /* offset to the array of global slots */
         504                 :     uint8_t         closedArgsOffset; /* offset to the array of closed args */
         505                 :     uint8_t         closedVarsOffset; /* offset to the array of closed vars */
         506                 :
         507                 :     // 1-bit fields.
         508                 :
         509                 :   public:
         510                 :     bool            noScriptRval:1; /* no need for result value of last
         511                 :                                        expression statement */
         512                 :     bool            savedCallerFun:1; /* can call getCallerFunction() */
         513                 :     bool            strictModeCode:1; /* code is in strict mode */
         514                 :     bool            compileAndGo:1;   /* script was compiled with TCF_COMPILE_N_GO */
         515                 :     bool            usesEval:1;       /* script uses eval() */
         516                 :     bool            warnedAboutTwoArgumentEval:1; /* have warned about use of
         517                 :                                                      obsolete eval(s, o) in
         518                 :                                                      this script */
         519                 :     bool            warnedAboutUndefinedProp:1; /* have warned about uses of
         520                 :                                                    undefined properties in this
         521                 :                                                    script */
         522                 :     bool            hasSingletons:1;  /* script has singleton objects */
         523                 :     bool            isOuterFunction:1; /* function is heavyweight, with inner functions */
         524                 :     bool            isInnerFunction:1; /* function is directly nested in a heavyweight
         525                 :                                         * outer function */
         526                 :     bool            isActiveEval:1;   /* script came from eval(), and is still active */
         527                 :     bool            isCachedEval:1;   /* script came from eval(), and is in eval cache */
         528                 :     bool            uninlineable:1;   /* script is considered uninlineable by analysis */
         529                 :     bool            reentrantOuterFunction:1; /* outer function marked reentrant */
         530                 :     bool            typesPurged:1;    /* TypeScript has been purged at some point */
         531                 : #ifdef JS_METHODJIT
         532                 :     bool            debugMode:1;      /* script was compiled in debug mode */
         533                 :     bool            failedBoundsCheck:1; /* script has had hoisted bounds checks fail */
         534                 : #endif
         535                 :     bool            callDestroyHook:1;/* need to call destroy hook */
         536                 :
         537                 :     /*
         538                 :      * An arguments object is created for a function script (when the function
         539                 :      * is first called) iff script->needsArgsObj(). There are several cases
         540                 :      * where the 'arguments' keyword is technically used but which don't really
         541                 :      * need an object (e.g., 'arguments[i]', 'f.apply(null, arguments')'). This
         542                 :      * determination is made during script analysis which occurs lazily (right
         543                 :      * before a script is run). Thus, the output of the front-end is a
         544                 :      * conservative 'mayNeedArgsObj' which leads to further analysis in
         545                 :      * analyzeBytecode and analyzeSSA. To avoid the complexity of spurious
         546                 :      * argument objects creation, we maintain the invariant that needsArgsObj()
         547                 :      * is only queried after this analysis has occurred (analyzedArgsUsage()).
         548                 :      */
         549                 :   private:
         550                 :     bool            mayNeedArgsObj_:1;
         551                 :     bool            analyzedArgsUsage_:1;
         552                 :     bool            needsArgsObj_:1;
         553                 :
         554                 :     //
         555                 :     // End of fields.  Start methods.
         556                 :     //
         557                 :
         558                 :     /*
         559                 :      * Two successively less primitive ways to make a new JSScript.  The first
         560                 :      * does *not* call a non-null cx->runtime->newScriptHook -- only the second,
         561                 :      * NewScriptFromEmitter, calls this optional debugger hook.
         562                 :      *
         563                 :      * The NewScript function can't know whether the script it creates belongs
         564                 :      * to a function, or is top-level or eval code, but the debugger wants access
         565                 :      * to the newly made script's function, if any -- so callers of NewScript
         566                 :      * are responsible for notifying the debugger after successfully creating any
         567                 :      * kind (function or other) of new JSScript.
         568                 :      */
         569                 :   public:
         570                 :     static JSScript *NewScript(JSContext *cx, uint32_t length, uint32_t nsrcnotes, uint32_t natoms,
         571                 :                                uint32_t nobjects, uint32_t nregexps,
         572                 :                                uint32_t ntrynotes, uint32_t nconsts, uint32_t nglobals,
         573                 :                                uint16_t nClosedArgs, uint16_t nClosedVars, uint32_t nTypeSets,
         574                 :                                JSVersion version);
         575                 :     static JSScript *NewScriptFromEmitter(JSContext *cx, js::BytecodeEmitter *bce);
         576                 :
         577          513260 :     bool mayNeedArgsObj() const { return mayNeedArgsObj_; }
         578        23643842 :     bool analyzedArgsUsage() const { return analyzedArgsUsage_; }
         579        23286546 :     bool needsArgsObj() const { JS_ASSERT(analyzedArgsUsage()); return needsArgsObj_; }
         580                 :     void setNeedsArgsObj(bool needsArgsObj);
         581                 :     bool applySpeculationFailed(JSContext *cx);
         582                 :
         583            7129 :     void setMayNeedArgsObj() {
         584            7129 :         mayNeedArgsObj_ = true;
         585            7129 :     }
         586                 :
         587                 :     /* Hash table chaining for JSCompartment::evalCache. */
         588          292610 :     JSScript *&evalHashLink() { return *globalObject.unsafeGetUnioned(); }
         589                 :
         590                 :     /*
         591                 :      * Original compiled function for the script, if it has a function.
         592                 :      * NULL for global and eval scripts.
         593                 :      */
         594       102611085 :     JSFunction *function() const { return function_; }
         595                 :     void setFunction(JSFunction *fun);
         596                 :
         597                 : #ifdef DEBUG
         598                 :     unsigned id();
         599                 : #else
         600                 :     unsigned id() { return 0; }
         601                 : #endif
         602                 :
         603                 :     /* Ensure the script has a TypeScript. */
         604                 :     inline bool ensureHasTypes(JSContext *cx);
         605                 :
         606                 :     /*
         607                 :      * Ensure the script has scope and bytecode analysis information.
         608                 :      * Performed when the script first runs, or first runs after a TypeScript
         609                 :      * GC purge. If scope is NULL then the script must already have types with
         610                 :      * scope information.
         611                 :      */
         612                 :     inline bool ensureRanAnalysis(JSContext *cx, JSObject *scope);
         613                 :
         614                 :     /* Ensure the script has type inference analysis information. */
         615                 :     inline bool ensureRanInference(JSContext *cx);
         616                 :
         617                 :     inline bool hasAnalysis();
         618                 :     inline void clearAnalysis();
         619                 :     inline js::analyze::ScriptAnalysis *analysis();
         620                 :
         621                 :     /*
         622                 :      * Associates this script with a specific function, constructing a new type
         623                 :      * object for the function if necessary.
         624                 :      */
         625                 :     bool typeSetFunction(JSContext *cx, JSFunction *fun, bool singleton = false);
         626                 :
         627                 :     inline bool hasGlobal() const;
         628                 :     inline bool hasClearedGlobal() const;
         629                 :
         630                 :     inline js::GlobalObject *global() const;
         631                 :     inline js::types::TypeScriptNesting *nesting() const;
         632                 :
         633                 :     inline void clearNesting();
         634                 :
         635                 :     /* Return creation time global or null. */
         636            8235 :     js::GlobalObject *getGlobalObjectOrNull() const {
         637            8235 :         return isCachedEval ? NULL : globalObject.get();
         638                 :     }
         639                 :
         640                 :   private:
         641                 :     bool makeTypes(JSContext *cx);
         642                 :     bool makeAnalysis(JSContext *cx);
         643                 :
         644                 : #ifdef JS_METHODJIT
         645                 :   private:
         646                 :     // CallCompiler must be a friend because it generates code that directly
         647                 :     // accesses jitHandleNormal/jitHandleCtor, via jitHandleOffset().
         648                 :     friend class js::mjit::CallCompiler;
         649                 :
         650            1278 :     static size_t jitHandleOffset(bool constructing) {
         651                 :         return constructing ? offsetof(JSScript, jitHandleCtor)
         652            1278 :                             : offsetof(JSScript, jitHandleNormal);
         653                 :     }
         654                 :
         655                 :   public:
         656           37764 :     bool hasJITCode()   { return jitHandleNormal.isValid() || jitHandleCtor.isValid(); }
         657                 :
         658        29864898 :     JITScriptHandle *jitHandle(bool constructing) {
         659        29864898 :         return constructing ? &jitHandleCtor : &jitHandleNormal;
         660                 :     }
         661                 :
         662        15884340 :     js::mjit::JITScript *getJIT(bool constructing) {
         663        15884340 :         JITScriptHandle *jith = jitHandle(constructing);
         664        15884340 :         return jith->isValid() ? jith->getValid() : NULL;
         665                 :     }
         666                 :
         667                 :     static void ReleaseCode(js::FreeOp *fop, JITScriptHandle *jith);
         668                 :
         669                 :     // These methods are implemented in MethodJIT.h.
         670                 :     inline void **nativeMap(bool constructing);
         671                 :     inline void *nativeCodeForPC(bool constructing, jsbytecode *pc);
         672                 :
         673           26401 :     size_t getUseCount() const  { return useCount; }
         674         4449664 :     size_t incUseCount() { return ++useCount; }
         675            2748 :     size_t *addressOfUseCount() { return &useCount; }
         676          455315 :     void resetUseCount() { useCount = 0; }
         677                 :
         678                 :     /*
         679                 :      * Size of the JITScript and all sections.  If |mallocSizeOf| is NULL, the
         680                 :      * size is computed analytically.  (This method is implemented in
         681                 :      * MethodJIT.cpp.)
         682                 :      */
         683                 :     size_t sizeOfJitScripts(JSMallocSizeOfFun mallocSizeOf);
         684                 : #endif
         685                 :
         686                 :   public:
         687               0 :     js::PCCounts getPCCounts(jsbytecode *pc) {
         688               0 :         JS_ASSERT(size_t(pc - code) < length);
         689               0 :         return scriptCounts.pcCountsVector[pc - code];
         690                 :     }
         691                 :
         692                 :     bool initScriptCounts(JSContext *cx);
         693                 :     void destroyScriptCounts(js::FreeOp *fop);
         694                 :
         695         2487622 :     jsbytecode *main() {
         696         2487622 :         return code + mainOffset;
         697                 :     }
         698                 :
         699                 :     /*
         700                 :      * computedSizeOfData() is the in-use size of all the data sections.
         701                 :      * sizeOfData() is the size of the block allocated to hold all the data sections
         702                 :      * (which can be larger than the in-use size).
         703                 :      */
         704                 :     size_t computedSizeOfData();
         705                 :     size_t sizeOfData(JSMallocSizeOfFun mallocSizeOf);
         706                 :
         707                 :     uint32_t numNotes();  /* Number of srcnote slots in the srcnotes section */
         708                 :
         709                 :     /* Script notes are allocated right after the code. */
         710        39707087 :     jssrcnote *notes() { return (jssrcnote *)(code + length); }
         711                 :
         712                 :     static const uint8_t INVALID_OFFSET = 0xFF;
         713        10713250 :     static bool isValidOffset(uint8_t offset) { return offset != INVALID_OFFSET; }
         714                 :
         715         1401394 :     JSConstArray *consts() {
         716         1401394 :         JS_ASSERT(isValidOffset(constsOffset));
         717         1401394 :         return reinterpret_cast<JSConstArray *>(data + constsOffset);
         718                 :     }
         719                 :
         720         2349936 :     JSObjectArray *objects() {
         721         2349936 :         JS_ASSERT(isValidOffset(objectsOffset));
         722         2349936 :         return reinterpret_cast<JSObjectArray *>(data + objectsOffset);
         723                 :     }
         724                 :
         725          100392 :     JSObjectArray *regexps() {
         726          100392 :         JS_ASSERT(isValidOffset(regexpsOffset));
         727          100392 :         return reinterpret_cast<JSObjectArray *>(data + regexpsOffset);
         728                 :     }
         729                 :
         730          276821 :     JSTryNoteArray *trynotes() {
         731          276821 :         JS_ASSERT(isValidOffset(trynotesOffset));
         732          276821 :         return reinterpret_cast<JSTryNoteArray *>(data + trynotesOffset);
         733                 :     }
         734                 :
         735           50672 :     js::GlobalSlotArray *globals() {
         736           50672 :         JS_ASSERT(isValidOffset(globalsOffset));
         737           50672 :         return reinterpret_cast<js::GlobalSlotArray *>(data + globalsOffset);
         738                 :     }
         739                 :
         740          245631 :     js::ClosedSlotArray *closedArgs() {
         741          245631 :         JS_ASSERT(isValidOffset(closedArgsOffset));
         742          245631 :         return reinterpret_cast<js::ClosedSlotArray *>(data + closedArgsOffset);
         743                 :     }
         744                 :
         745          598441 :     js::ClosedSlotArray *closedVars() {
         746          598441 :         JS_ASSERT(isValidOffset(closedVarsOffset));
         747          598441 :         return reinterpret_cast<js::ClosedSlotArray *>(data + closedVarsOffset);
         748                 :     }
         749                 :
         750          748766 :     uint32_t nClosedArgs() {
         751          748766 :         return isValidOffset(closedArgsOffset) ? closedArgs()->length : 0;
         752                 :     }
         753                 :
         754          585886 :     uint32_t nClosedVars() {
         755          585886 :         return isValidOffset(closedVarsOffset) ? closedVars()->length : 0;
         756                 :     }
         757                 :
         758         7566515 :     JSAtom *getAtom(size_t index) {
         759         7566515 :         JS_ASSERT(index < natoms);
         760         7566515 :         return atoms[index];
         761                 :     }
         762                 :
         763         1558423 :     js::PropertyName *getName(size_t index) {
         764         1558423 :         return getAtom(index)->asPropertyName();
         765                 :     }
         766                 :
         767         1843836 :     JSObject *getObject(size_t index) {
         768         1843836 :         JSObjectArray *arr = objects();
         769         1843836 :         JS_ASSERT(index < arr->length);
         770         1843836 :         return arr->vector[index];
         771                 :     }
         772                 :
         773          567282 :     JSVersion getVersion() const {
         774          567282 :         return JSVersion(version);
         775                 :     }
         776                 :
         777                 :     inline JSFunction *getFunction(size_t index);
         778                 :     inline JSFunction *getCallerFunction();
         779                 :
         780                 :     inline JSObject *getRegExp(size_t index);
         781                 :
         782         1392819 :     const js::Value &getConst(size_t index) {
         783         1392819 :         JSConstArray *arr = consts();
         784         1392819 :         JS_ASSERT(index < arr->length);
         785         1392819 :         return arr->vector[index];
         786                 :     }
         787                 :
         788                 :     /*
         789                 :      * The isEmpty method tells whether this script has code that computes any
         790                 :      * result (not return value, result AKA normal completion value) other than
         791                 :      * JSVAL_VOID, or any other effects.
         792                 :      */
         793                 :     inline bool isEmpty() const;
         794                 :
         795          170950 :     uint32_t getClosedArg(uint32_t index) {
         796          170950 :         js::ClosedSlotArray *arr = closedArgs();
         797          170950 :         JS_ASSERT(index < arr->length);
         798          170950 :         return arr->vector[index];
         799                 :     }
         800                 :
         801          328963 :     uint32_t getClosedVar(uint32_t index) {
         802          328963 :         js::ClosedSlotArray *arr = closedVars();
         803          328963 :         JS_ASSERT(index < arr->length);
         804          328963 :         return arr->vector[index];
         805                 :     }
         806                 :
         807                 :   private:
         808                 :     /*
         809                 :      * Recompile with or without single-stepping support, as directed
         810                 :      * by stepModeEnabled().
         811                 :      */
         812                 :     void recompileForStepMode(js::FreeOp *fop);
         813                 :
         814                 :     /* Attempt to change this->stepMode to |newValue|. */
         815                 :     bool tryNewStepMode(JSContext *cx, uint32_t newValue);
         816                 :
         817                 :     bool ensureHasDebug(JSContext *cx);
         818                 :
         819                 :   public:
         820        13346928 :     bool hasBreakpointsAt(jsbytecode *pc) { return !!getBreakpointSite(pc); }
         821        20845917 :     bool hasAnyBreakpointsOrStepMode() { return !!debug; }
         822                 :
         823        22262768 :     js::BreakpointSite *getBreakpointSite(jsbytecode *pc)
         824                 :     {
         825        22262768 :         JS_ASSERT(size_t(pc - code) < length);
         826        22262768 :         return debug ? debug->breakpoints[pc - code] : NULL;
         827                 :     }
         828                 :
         829                 :     js::BreakpointSite *getOrCreateBreakpointSite(JSContext *cx, jsbytecode *pc,
         830                 :                                                   js::GlobalObject *scriptGlobal);
         831                 :
         832                 :     void destroyBreakpointSite(js::FreeOp *fop, jsbytecode *pc);
         833                 :
         834                 :     void clearBreakpointsIn(JSContext *cx, js::Debugger *dbg, JSObject *handler);
         835                 :     void clearTraps(js::FreeOp *fop);
         836                 :
         837                 :     void markTrapClosures(JSTracer *trc);
         838                 :
         839                 :     /*
         840                 :      * Set or clear the single-step flag. If the flag is set or the count
         841                 :      * (adjusted by changeStepModeCount) is non-zero, then the script is in
         842                 :      * single-step mode. (JSD uses an on/off-style interface; Debugger uses a
         843                 :      * count-style interface.)
         844                 :      */
         845                 :     bool setStepModeFlag(JSContext *cx, bool step);
         846                 :
         847                 :     /*
         848                 :      * Increment or decrement the single-step count. If the count is non-zero or
         849                 :      * the flag (set by setStepModeFlag) is set, then the script is in
         850                 :      * single-step mode. (JSD uses an on/off-style interface; Debugger uses a
         851                 :      * count-style interface.)
         852                 :      */
         853                 :     bool changeStepModeCount(JSContext *cx, int delta);
         854                 :
         855         4143639 :     bool stepModeEnabled() { return debug && !!debug->stepMode; }
         856                 :
         857                 : #ifdef DEBUG
         858            5813 :     uint32_t stepModeCount() { return debug ? (debug->stepMode & stepCountMask) : 0; }
         859                 : #endif
         860                 :
         861                 :     void finalize(js::FreeOp *fop);
         862                 :
         863                 :     static inline void writeBarrierPre(JSScript *script);
         864                 :     static inline void writeBarrierPost(JSScript *script, void *addr);
         865                 :
         866                 :     static inline js::ThingRootKind rootKind() { return js::THING_ROOT_SCRIPT; }
         867                 :
         868          116491 :     static JSPrincipals *normalizeOriginPrincipals(JSPrincipals *principals,
         869                 :                                                    JSPrincipals *originPrincipals) {
         870          116491 :         return originPrincipals ? originPrincipals : principals;
         871                 :     }
         872                 :
         873                 :     void markChildren(JSTracer *trc);
         874                 : };
         875                 :
         876                 : /* If this fails, padding_ can be removed. */
         877                 : JS_STATIC_ASSERT(sizeof(JSScript) % js::gc::Cell::CellSize == 0);
         878                 :
         879                 : static JS_INLINE unsigned
         880        76709546 : StackDepth(JSScript *script)
         881                 : {
         882        76709546 :     return script->nslots - script->nfixed;
         883                 : }
         884                 :
         885                 : /*
         886                 :  * New-script-hook calling is factored from NewScriptFromEmitter so that it
         887                 :  * and callers of XDRScript can share this code.  In the case of callers
         888                 :  * of XDRScript, the hook should be invoked only after successful decode
         889                 :  * of any owning function (the fun parameter) or script object (null fun).
         890                 :  */
         891                 : extern JS_FRIEND_API(void)
         892                 : js_CallNewScriptHook(JSContext *cx, JSScript *script, JSFunction *fun);
         893                 :
         894                 : namespace js {
         895                 :
         896                 : extern void
         897                 : CallDestroyScriptHook(FreeOp *fop, JSScript *script);
         898                 :
         899                 : extern const char *
         900                 : SaveScriptFilename(JSContext *cx, const char *filename);
         901                 :
         902                 : extern void
         903                 : MarkScriptFilename(const char *filename);
         904                 :
         905                 : extern void
         906                 : SweepScriptFilenames(JSCompartment *comp);
         907                 :
         908                 : extern void
         909                 : FreeScriptFilenames(JSCompartment *comp);
         910                 :
         911                 : struct ScriptAndCounts
         912               0 : {
         913                 :     JSScript *script;
         914                 :     ScriptCounts scriptCounts;
         915                 :
         916               0 :     PCCounts &getPCCounts(jsbytecode *pc) const {
         917               0 :         JS_ASSERT(unsigned(pc - script->code) < script->length);
         918               0 :         return scriptCounts.pcCountsVector[pc - script->code];
         919                 :     }
         920                 : };
         921                 :
         922                 : } /* namespace js */
         923                 :
         924                 : /*
         925                 :  * To perturb as little code as possible, we introduce a js_GetSrcNote lookup
         926                 :  * cache without adding an explicit cx parameter.  Thus js_GetSrcNote becomes
         927                 :  * a macro that uses cx from its calls' lexical environments.
         928                 :  */
         929                 : #define js_GetSrcNote(script,pc) js_GetSrcNoteCached(cx, script, pc)
         930                 :
         931                 : extern jssrcnote *
         932                 : js_GetSrcNoteCached(JSContext *cx, JSScript *script, jsbytecode *pc);
         933                 :
         934                 : extern jsbytecode *
         935                 : js_LineNumberToPC(JSScript *script, unsigned lineno);
         936                 :
         937                 : extern JS_FRIEND_API(unsigned)
         938                 : js_GetScriptLineExtent(JSScript *script);
         939                 :
         940                 : namespace js {
         941                 :
         942                 : extern unsigned
         943                 : PCToLineNumber(JSScript *script, jsbytecode *pc);
         944                 :
         945                 : extern unsigned
         946                 : PCToLineNumber(unsigned startLine, jssrcnote *notes, jsbytecode *code, jsbytecode *pc);
         947                 :
         948                 : extern unsigned
         949                 : CurrentLine(JSContext *cx);
         950                 :
         951                 : /*
         952                 :  * This function returns the file and line number of the script currently
         953                 :  * executing on cx. If there is no current script executing on cx (e.g., a
         954                 :  * native called directly through JSAPI (e.g., by setTimeout)), NULL and 0 are
         955                 :  * returned as the file and line. Additionally, this function avoids the full
         956                 :  * linear scan to compute line number when the caller guarnatees that the
         957                 :  * script compilation occurs at a JSOP_EVAL.
         958                 :  */
         959                 :
         960                 : enum LineOption {
         961                 :     CALLED_FROM_JSOP_EVAL,
         962                 :     NOT_CALLED_FROM_JSOP_EVAL
         963                 : };
         964                 :
         965                 : inline void
         966                 : CurrentScriptFileLineOrigin(JSContext *cx, unsigned *linenop, LineOption = NOT_CALLED_FROM_JSOP_EVAL);
         967                 :
         968                 : extern JSScript *
         969                 : CloneScript(JSContext *cx, JSScript *script);
         970                 :
         971                 : /*
         972                 :  * NB: after a successful XDR_DECODE, XDRScript callers must do any required
         973                 :  * subsequent set-up of owning function or script object and then call
         974                 :  * js_CallNewScriptHook.
         975                 :  */
         976                 : template<XDRMode mode>
         977                 : bool
         978                 : XDRScript(XDRState<mode> *xdr, JSScript **scriptp, JSScript *parentScript);
         979                 :
         980                 : } /* namespace js */
         981                 :
         982                 : #endif /* jsscript_h___ */

Generated by: LCOV version 1.7