LCOV - code coverage report
Current view: top level - js/src - jsscript.h (source / functions) Hit Total Coverage
Test: output.info Lines: 585 717 81.6 %
Date: 2017-07-14 16:53:18 Functions: 259 321 80.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : /* JS script descriptor. */
       8             : 
       9             : #ifndef jsscript_h
      10             : #define jsscript_h
      11             : 
      12             : #include "mozilla/Atomics.h"
      13             : #include "mozilla/Maybe.h"
      14             : #include "mozilla/MemoryReporting.h"
      15             : #include "mozilla/PodOperations.h"
      16             : #include "mozilla/Variant.h"
      17             : 
      18             : #include "jsatom.h"
      19             : #include "jsopcode.h"
      20             : #include "jstypes.h"
      21             : 
      22             : #include "frontend/NameAnalysisTypes.h"
      23             : #include "gc/Barrier.h"
      24             : #include "gc/Rooting.h"
      25             : #include "jit/IonCode.h"
      26             : #include "js/UbiNode.h"
      27             : #include "js/UniquePtr.h"
      28             : #include "vm/NativeObject.h"
      29             : #include "vm/Scope.h"
      30             : #include "vm/Shape.h"
      31             : #include "vm/SharedImmutableStringsCache.h"
      32             : 
      33             : namespace JS {
      34             : struct ScriptSourceInfo;
      35             : } // namespace JS
      36             : 
      37             : namespace js {
      38             : 
      39             : namespace jit {
      40             :     struct BaselineScript;
      41             :     struct IonScriptCounts;
      42             : } // namespace jit
      43             : 
      44             : # define ION_DISABLED_SCRIPT ((js::jit::IonScript*)0x1)
      45             : # define ION_COMPILING_SCRIPT ((js::jit::IonScript*)0x2)
      46             : # define ION_PENDING_SCRIPT ((js::jit::IonScript*)0x3)
      47             : 
      48             : # define BASELINE_DISABLED_SCRIPT ((js::jit::BaselineScript*)0x1)
      49             : 
      50             : class BreakpointSite;
      51             : class Debugger;
      52             : class LazyScript;
      53             : class ModuleObject;
      54             : class RegExpObject;
      55             : class SourceCompressionTask;
      56             : class Shape;
      57             : 
      58             : namespace frontend {
      59             :     struct BytecodeEmitter;
      60             :     class FunctionBox;
      61             :     class ModuleSharedContext;
      62             : } // namespace frontend
      63             : 
      64             : namespace detail {
      65             : 
      66             : // Do not call this directly! It is exposed for the friend declarations in
      67             : // this file.
      68             : bool
      69             : CopyScript(JSContext* cx, HandleScript src, HandleScript dst,
      70             :            MutableHandle<GCVector<Scope*>> scopes);
      71             : 
      72             : } // namespace detail
      73             : 
      74             : } // namespace js
      75             : 
      76             : /*
      77             :  * Type of try note associated with each catch or finally block, and also with
      78             :  * for-in and other kinds of loops. Non-for-in loops do not need these notes
      79             :  * for exception unwinding, but storing their boundaries here is helpful for
      80             :  * heuristics that need to know whether a given op is inside a loop.
      81             :  */
      82             : enum JSTryNoteKind {
      83             :     JSTRY_CATCH,
      84             :     JSTRY_FINALLY,
      85             :     JSTRY_FOR_IN,
      86             :     JSTRY_FOR_OF,
      87             :     JSTRY_LOOP,
      88             :     JSTRY_FOR_OF_ITERCLOSE,
      89             :     JSTRY_DESTRUCTURING_ITERCLOSE
      90             : };
      91             : 
      92             : /*
      93             :  * Exception handling record.
      94             :  */
      95             : struct JSTryNote {
      96             :     uint8_t         kind;       /* one of JSTryNoteKind */
      97             :     uint32_t        stackDepth; /* stack depth upon exception handler entry */
      98             :     uint32_t        start;      /* start of the try statement or loop
      99             :                                    relative to script->main */
     100             :     uint32_t        length;     /* length of the try statement or loop */
     101             : };
     102             : 
     103             : namespace js {
     104             : 
     105             : // A block scope has a range in bytecode: it is entered at some offset, and left
     106             : // at some later offset.  Scopes can be nested.  Given an offset, the
     107             : // ScopeNote containing that offset whose with the highest start value
     108             : // indicates the block scope.  The block scope list is sorted by increasing
     109             : // start value.
     110             : //
     111             : // It is possible to leave a scope nonlocally, for example via a "break"
     112             : // statement, so there may be short bytecode ranges in a block scope in which we
     113             : // are popping the block chain in preparation for a goto.  These exits are also
     114             : // nested with respect to outer scopes.  The scopes in these exits are indicated
     115             : // by the "index" field, just like any other block.  If a nonlocal exit pops the
     116             : // last block scope, the index will be NoScopeIndex.
     117             : //
     118             : struct ScopeNote {
     119             :     // Sentinel index for no Scope.
     120             :     static const uint32_t NoScopeIndex = UINT32_MAX;
     121             : 
     122             :     // Sentinel index for no ScopeNote.
     123             :     static const uint32_t NoScopeNoteIndex = UINT32_MAX;
     124             : 
     125             :     uint32_t        index;      // Index of Scope in the scopes array, or
     126             :                                 // NoScopeIndex if there is no block scope in
     127             :                                 // this range.
     128             :     uint32_t        start;      // Bytecode offset at which this scope starts,
     129             :                                 // from script->main().
     130             :     uint32_t        length;     // Bytecode length of scope.
     131             :     uint32_t        parent;     // Index of parent block scope in notes, or NoScopeNote.
     132             : };
     133             : 
     134             : struct ConstArray {
     135             :     js::GCPtrValue* vector;     // array of indexed constant values
     136             :     uint32_t length;
     137             : };
     138             : 
     139             : struct ObjectArray {
     140             :     js::GCPtrObject* vector;    // Array of indexed objects.
     141             :     uint32_t length;            // Count of indexed objects.
     142             : };
     143             : 
     144             : struct ScopeArray {
     145             :     js::GCPtrScope* vector;     // Array of indexed scopes.
     146             :     uint32_t        length;     // Count of indexed scopes.
     147             : };
     148             : 
     149             : struct TryNoteArray {
     150             :     JSTryNote*      vector;     // Array of indexed try notes.
     151             :     uint32_t        length;     // Count of indexed try notes.
     152             : };
     153             : 
     154             : struct ScopeNoteArray {
     155             :     ScopeNote* vector;          // Array of indexed ScopeNote records.
     156             :     uint32_t   length;          // Count of indexed try notes.
     157             : };
     158             : 
     159             : class YieldAndAwaitOffsetArray {
     160             :     friend bool
     161             :     detail::CopyScript(JSContext* cx, HandleScript src, HandleScript dst,
     162             :                        MutableHandle<GCVector<Scope*>> scopes);
     163             : 
     164             :     uint32_t*       vector_;    // Array of bytecode offsets.
     165             :     uint32_t        length_;    // Count of bytecode offsets.
     166             : 
     167             :   public:
     168         445 :     void init(uint32_t* vector, uint32_t length) {
     169         445 :         vector_ = vector;
     170         445 :         length_ = length;
     171         445 :     }
     172        1852 :     uint32_t& operator[](uint32_t index) {
     173        1852 :         MOZ_ASSERT(index < length_);
     174        1852 :         return vector_[index];
     175             :     }
     176         420 :     uint32_t length() const {
     177         420 :         return length_;
     178             :     }
     179             : };
     180             : 
     181             : class ScriptCounts
     182             : {
     183             :   public:
     184             :     typedef mozilla::Vector<PCCounts, 0, SystemAllocPolicy> PCCountsVector;
     185             : 
     186             :     inline ScriptCounts();
     187             :     inline explicit ScriptCounts(PCCountsVector&& jumpTargets);
     188             :     inline ScriptCounts(ScriptCounts&& src);
     189             :     inline ~ScriptCounts();
     190             : 
     191             :     inline ScriptCounts& operator=(ScriptCounts&& src);
     192             : 
     193             :     // Return the counter used to count the number of visits. Returns null if
     194             :     // the element is not found.
     195             :     PCCounts* maybeGetPCCounts(size_t offset);
     196             :     const PCCounts* maybeGetPCCounts(size_t offset) const;
     197             : 
     198             :     // PCCounts are stored at jump-target offsets. This function looks for the
     199             :     // previous PCCount which is in the same basic block as the current offset.
     200             :     PCCounts* getImmediatePrecedingPCCounts(size_t offset);
     201             : 
     202             :     // Return the counter used to count the number of throws. Returns null if
     203             :     // the element is not found.
     204             :     const PCCounts* maybeGetThrowCounts(size_t offset) const;
     205             : 
     206             :     // Throw counts are stored at the location of each throwing
     207             :     // instruction. This function looks for the previous throw count.
     208             :     //
     209             :     // Note: if the offset of the returned count is higher than the offset of
     210             :     // the immediate preceding PCCount, then this throw happened in the same
     211             :     // basic block.
     212             :     const PCCounts* getImmediatePrecedingThrowCounts(size_t offset) const;
     213             : 
     214             :     // Return the counter used to count the number of throws. Allocate it if
     215             :     // none exists yet. Returns null if the allocation failed.
     216             :     PCCounts* getThrowCounts(size_t offset);
     217             : 
     218             :   private:
     219             :     friend class ::JSScript;
     220             :     friend struct ScriptAndCounts;
     221             : 
     222             :     // This sorted array is used to map an offset to the number of times a
     223             :     // branch got visited.
     224             :     PCCountsVector pcCounts_;
     225             : 
     226             :     // This sorted vector is used to map an offset to the number of times an
     227             :     // instruction throw.
     228             :     PCCountsVector throwCounts_;
     229             : 
     230             :     // Information about any Ion compilations for the script.
     231             :     jit::IonScriptCounts* ionCounts_;
     232             : };
     233             : 
     234             : // Note: The key of this hash map is a weak reference to a JSScript.  We do not
     235             : // use the WeakMap implementation provided in jsweakmap.h because it would be
     236             : // collected at the beginning of the sweeping of the compartment, thus before
     237             : // the calls to the JSScript::finalize function which are used to aggregate code
     238             : // coverage results on the compartment.
     239             : typedef HashMap<JSScript*,
     240             :                 ScriptCounts*,
     241             :                 DefaultHasher<JSScript*>,
     242             :                 SystemAllocPolicy> ScriptCountsMap;
     243             : typedef HashMap<JSScript*,
     244             :                 const char*,
     245             :                 DefaultHasher<JSScript*>,
     246             :                 SystemAllocPolicy> ScriptNameMap;
     247             : 
     248             : class DebugScript
     249             : {
     250             :     friend class ::JSScript;
     251             :     friend struct ::JSCompartment;
     252             : 
     253             :     /*
     254             :      * When non-zero, compile script in single-step mode. The top bit is set and
     255             :      * cleared by setStepMode, as used by JSD. The lower bits are a count,
     256             :      * adjusted by changeStepModeCount, used by the Debugger object. Only
     257             :      * when the bit is clear and the count is zero may we compile the script
     258             :      * without single-step support.
     259             :      */
     260             :     uint32_t        stepMode;
     261             : 
     262             :     /*
     263             :      * Number of breakpoint sites at opcodes in the script. This is the number
     264             :      * of populated entries in DebugScript::breakpoints, below.
     265             :      */
     266             :     uint32_t        numSites;
     267             : 
     268             :     /*
     269             :      * Breakpoints set in our script. For speed and simplicity, this array is
     270             :      * parallel to script->code(): the BreakpointSite for the opcode at
     271             :      * script->code()[offset] is debugScript->breakpoints[offset]. Naturally,
     272             :      * this array's true length is script->length().
     273             :      */
     274             :     BreakpointSite* breakpoints[1];
     275             : };
     276             : 
     277             : typedef HashMap<JSScript*,
     278             :                 DebugScript*,
     279             :                 DefaultHasher<JSScript*>,
     280             :                 SystemAllocPolicy> DebugScriptMap;
     281             : 
     282             : class ScriptSource;
     283             : 
     284             : struct ScriptSourceChunk
     285             : {
     286             :     ScriptSource* ss;
     287             :     uint32_t chunk;
     288             : 
     289        1408 :     ScriptSourceChunk()
     290        1408 :       : ss(nullptr), chunk(0)
     291        1408 :     {}
     292           0 :     ScriptSourceChunk(ScriptSource* ss, uint32_t chunk)
     293           0 :       : ss(ss), chunk(chunk)
     294             :     {
     295           0 :         MOZ_ASSERT(valid());;
     296           0 :     }
     297           0 :     bool valid() const { return ss != nullptr; }
     298             : 
     299           0 :     bool operator==(const ScriptSourceChunk& other) const {
     300           0 :         return ss == other.ss && chunk == other.chunk;
     301             :     }
     302             : };
     303             : 
     304             : struct ScriptSourceChunkHasher
     305             : {
     306             :     using Lookup = ScriptSourceChunk;
     307             : 
     308           0 :     static HashNumber hash(const ScriptSourceChunk& ssc) {
     309           0 :         return mozilla::AddToHash(DefaultHasher<ScriptSource*>::hash(ssc.ss), ssc.chunk);
     310             :     }
     311           0 :     static bool match(const ScriptSourceChunk& c1, const ScriptSourceChunk& c2) {
     312           0 :         return c1 == c2;
     313             :     }
     314             : };
     315             : 
     316           0 : class UncompressedSourceCache
     317             : {
     318             :     typedef HashMap<ScriptSourceChunk,
     319             :                     UniqueTwoByteChars,
     320             :                     ScriptSourceChunkHasher,
     321             :                     SystemAllocPolicy> Map;
     322             : 
     323             :   public:
     324             :     // Hold an entry in the source data cache and prevent it from being purged on GC.
     325             :     class AutoHoldEntry
     326             :     {
     327             :         UncompressedSourceCache* cache_;
     328             :         ScriptSourceChunk sourceChunk_;
     329             :         UniqueTwoByteChars charsToFree_;
     330             :       public:
     331             :         explicit AutoHoldEntry();
     332             :         ~AutoHoldEntry();
     333             :         void holdChars(UniqueTwoByteChars chars);
     334             :       private:
     335             :         void holdEntry(UncompressedSourceCache* cache, const ScriptSourceChunk& sourceChunk);
     336             :         void deferDelete(UniqueTwoByteChars chars);
     337           0 :         const ScriptSourceChunk& sourceChunk() const { return sourceChunk_; }
     338             :         friend class UncompressedSourceCache;
     339             :     };
     340             : 
     341             :   private:
     342             :     UniquePtr<Map> map_;
     343             :     AutoHoldEntry* holder_;
     344             : 
     345             :   public:
     346           4 :     UncompressedSourceCache() : holder_(nullptr) {}
     347             : 
     348             :     const char16_t* lookup(const ScriptSourceChunk& ssc, AutoHoldEntry& asp);
     349             :     bool put(const ScriptSourceChunk& ssc, UniqueTwoByteChars chars, AutoHoldEntry& asp);
     350             : 
     351             :     void purge();
     352             : 
     353             :     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
     354             : 
     355             :   private:
     356             :     void holdEntry(AutoHoldEntry& holder, const ScriptSourceChunk& ssc);
     357             :     void releaseEntry(AutoHoldEntry& holder);
     358             : };
     359             : 
     360             : class ScriptSource
     361             : {
     362             :     friend class SourceCompressionTask;
     363             : 
     364             :   public:
     365             :     // Any users that wish to manipulate the char buffer of the ScriptSource
     366             :     // needs to do so via PinnedChars for GC safety. A GC may compress
     367             :     // ScriptSources. If the source were initially uncompressed, then any raw
     368             :     // pointers to the char buffer would now point to the freed, uncompressed
     369             :     // chars. This is analogous to Rooted.
     370             :     class PinnedChars
     371             :     {
     372             :         PinnedChars** stack_;
     373             :         PinnedChars* prev_;
     374             : 
     375             :         ScriptSource* source_;
     376             :         const char16_t* chars_;
     377             : 
     378             :       public:
     379             :         PinnedChars(JSContext* cx, ScriptSource* source,
     380             :                     UncompressedSourceCache::AutoHoldEntry& holder,
     381             :                     size_t begin, size_t len);
     382             : 
     383             :         ~PinnedChars();
     384             : 
     385        2820 :         const char16_t* get() const {
     386        2820 :             return chars_;
     387             :         }
     388             :     };
     389             : 
     390             :   private:
     391             :     uint32_t refs;
     392             : 
     393             :     // Note: while ScriptSources may be compressed off thread, they are only
     394             :     // modified by the active thread, and all members are always safe to access
     395             :     // on the active thread.
     396             : 
     397             :     // Indicate which field in the |data| union is active.
     398             : 
     399             :     struct Missing { };
     400             : 
     401        6814 :     struct Uncompressed
     402             :     {
     403             :         SharedImmutableTwoByteString string;
     404             : 
     405        1703 :         explicit Uncompressed(SharedImmutableTwoByteString&& str)
     406        1703 :           : string(mozilla::Move(str))
     407        1703 :         { }
     408             :     };
     409             : 
     410           0 :     struct Compressed
     411             :     {
     412             :         SharedImmutableString raw;
     413             :         size_t uncompressedLength;
     414             : 
     415           0 :         Compressed(SharedImmutableString&& raw, size_t uncompressedLength)
     416           0 :           : raw(mozilla::Move(raw))
     417           0 :           , uncompressedLength(uncompressedLength)
     418           0 :         { }
     419             :     };
     420             : 
     421             :     using SourceType = mozilla::Variant<Missing, Uncompressed, Compressed>;
     422             :     SourceType data;
     423             : 
     424             :     // If the GC attempts to call setCompressedSource with PinnedChars
     425             :     // present, the first PinnedChars (that is, bottom of the stack) will set
     426             :     // the compressed chars upon destruction.
     427             :     PinnedChars* pinnedCharsStack_;
     428             :     mozilla::Maybe<Compressed> pendingCompressed_;
     429             : 
     430             :     // The filename of this script.
     431             :     UniqueChars filename_;
     432             : 
     433             :     UniqueTwoByteChars displayURL_;
     434             :     UniqueTwoByteChars sourceMapURL_;
     435             :     bool mutedErrors_;
     436             : 
     437             :     // The start column of the source. Offsets kept for toString and the
     438             :     // function source in LazyScripts are absolute positions within a
     439             :     // ScriptSource buffer. To get their positions, they need to be offset
     440             :     // with the starting column.
     441             :     uint32_t startColumn_;
     442             : 
     443             :     // bytecode offset in caller script that generated this code.
     444             :     // This is present for eval-ed code, as well as "new Function(...)"-introduced
     445             :     // scripts.
     446             :     uint32_t introductionOffset_;
     447             : 
     448             :     // If this source is for Function constructor, the position of ")" after
     449             :     // parameter list in the source.  This is used to get function body.
     450             :     // 0 for other cases.
     451             :     uint32_t parameterListEnd_;
     452             : 
     453             :     // If this ScriptSource was generated by a code-introduction mechanism such
     454             :     // as |eval| or |new Function|, the debugger needs access to the "raw"
     455             :     // filename of the top-level script that contains the eval-ing code.  To
     456             :     // keep track of this, we must preserve the original outermost filename (of
     457             :     // the original introducer script), so that instead of a filename of
     458             :     // "foo.js line 30 > eval line 10 > Function", we can obtain the original
     459             :     // raw filename of "foo.js".
     460             :     //
     461             :     // In the case described above, this field will be non-null and will be the
     462             :     // original raw filename from above.  Otherwise this field will be null.
     463             :     UniqueChars introducerFilename_;
     464             : 
     465             :     // A string indicating how this source code was introduced into the system.
     466             :     // This accessor returns one of the following values:
     467             :     //      "eval" for code passed to |eval|.
     468             :     //      "Function" for code passed to the |Function| constructor.
     469             :     //      "Worker" for code loaded by calling the Web worker constructor&mdash;the worker's main script.
     470             :     //      "importScripts" for code by calling |importScripts| in a web worker.
     471             :     //      "handler" for code assigned to DOM elements' event handler IDL attributes.
     472             :     //      "scriptElement" for code belonging to <script> elements.
     473             :     //      undefined if the implementation doesn't know how the code was introduced.
     474             :     // This is a constant, statically allocated C string, so does not need
     475             :     // memory management.
     476             :     const char* introductionType_;
     477             : 
     478             :     // The bytecode cache encoder is used to encode only the content of function
     479             :     // which are delazified.  If this value is not nullptr, then each delazified
     480             :     // function should be recorded before their first execution.
     481             :     UniquePtr<XDRIncrementalEncoder> xdrEncoder_;
     482             : 
     483             :     // Instant at which the first parse of this source ended, or null
     484             :     // if the source hasn't been parsed yet.
     485             :     //
     486             :     // Used for statistics purposes, to determine how much time code spends
     487             :     // syntax parsed before being full parsed, to help determine whether
     488             :     // our syntax parse vs. full parse heuristics are correct.
     489             :     mozilla::TimeStamp parseEnded_;
     490             : 
     491             :     // True if we can call JSRuntime::sourceHook to load the source on
     492             :     // demand. If sourceRetrievable_ and hasSourceData() are false, it is not
     493             :     // possible to get source at all.
     494             :     bool sourceRetrievable_:1;
     495             :     bool hasIntroductionOffset_:1;
     496             : 
     497             :     const char16_t* chunkChars(JSContext* cx, UncompressedSourceCache::AutoHoldEntry& holder,
     498             :                                size_t chunk);
     499             : 
     500             :     // Return a string containing the chars starting at |begin| and ending at
     501             :     // |begin + len|.
     502             :     //
     503             :     // Warning: this is *not* GC-safe! Any chars to be handed out should use
     504             :     // PinnedChars. See comment below.
     505             :     const char16_t* chars(JSContext* cx, UncompressedSourceCache::AutoHoldEntry& asp,
     506             :                           size_t begin, size_t len);
     507             : 
     508             :     void movePendingCompressedSource();
     509             : 
     510             :   public:
     511        2088 :     explicit ScriptSource()
     512        2088 :       : refs(0),
     513        2088 :         data(SourceType(Missing())),
     514             :         pinnedCharsStack_(nullptr),
     515             :         filename_(nullptr),
     516             :         displayURL_(nullptr),
     517             :         sourceMapURL_(nullptr),
     518             :         mutedErrors_(false),
     519             :         startColumn_(0),
     520             :         introductionOffset_(0),
     521             :         parameterListEnd_(0),
     522             :         introducerFilename_(nullptr),
     523             :         introductionType_(nullptr),
     524             :         xdrEncoder_(nullptr),
     525             :         sourceRetrievable_(false),
     526        4176 :         hasIntroductionOffset_(false)
     527             :     {
     528        2087 :     }
     529             : 
     530           0 :     ~ScriptSource() {
     531           0 :         MOZ_ASSERT(refs == 0);
     532           0 :     }
     533             : 
     534        4380 :     void incref() { refs++; }
     535        2136 :     void decref() {
     536        2136 :         MOZ_ASSERT(refs != 0);
     537        2136 :         if (--refs == 0)
     538           0 :             js_delete(this);
     539        2136 :     }
     540             :     MOZ_MUST_USE bool initFromOptions(JSContext* cx,
     541             :                                       const ReadOnlyCompileOptions& options,
     542             :                                       const mozilla::Maybe<uint32_t>& parameterListEnd = mozilla::Nothing());
     543             :     MOZ_MUST_USE bool setSourceCopy(JSContext* cx, JS::SourceBufferHolder& srcBuf);
     544          64 :     void setSourceRetrievable() { sourceRetrievable_ = true; }
     545           1 :     bool sourceRetrievable() const { return sourceRetrievable_; }
     546        5396 :     bool hasSourceData() const { return !data.is<Missing>(); }
     547             :     bool hasUncompressedSource() const { return data.is<Uncompressed>(); }
     548             :     bool hasCompressedSource() const { return data.is<Compressed>(); }
     549             : 
     550        2328 :     size_t length() const {
     551             :         struct LengthMatcher
     552             :         {
     553        2328 :             size_t match(const Uncompressed& u) {
     554        2328 :                 return u.string.length();
     555             :             }
     556             : 
     557           0 :             size_t match(const Compressed& c) {
     558           0 :                 return c.uncompressedLength;
     559             :             }
     560             : 
     561           0 :             size_t match(const Missing& m) {
     562           0 :                 MOZ_CRASH("ScriptSource::length on a missing source");
     563             :                 return 0;
     564             :             }
     565             :         };
     566             : 
     567        2328 :         MOZ_ASSERT(hasSourceData());
     568        2328 :         return data.match(LengthMatcher());
     569             :     }
     570             : 
     571             :     JSFlatString* substring(JSContext* cx, size_t start, size_t stop);
     572             :     JSFlatString* substringDontDeflate(JSContext* cx, size_t start, size_t stop);
     573             : 
     574             :     MOZ_MUST_USE bool appendSubstring(JSContext* cx, js::StringBuffer& buf, size_t start, size_t stop);
     575             : 
     576           0 :     bool isFunctionBody() {
     577           0 :         return parameterListEnd_ != 0;
     578             :     }
     579             :     JSFlatString* functionBodyString(JSContext* cx);
     580             : 
     581             :     void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
     582             :                                 JS::ScriptSourceInfo* info) const;
     583             : 
     584             :     MOZ_MUST_USE bool setSource(JSContext* cx,
     585             :                                 UniqueTwoByteChars&& source,
     586             :                                 size_t length);
     587             :     void setSource(SharedImmutableTwoByteString&& string);
     588             : 
     589             :     MOZ_MUST_USE bool tryCompressOffThread(JSContext* cx);
     590             : 
     591             :     MOZ_MUST_USE bool setCompressedSource(JSContext* cx,
     592             :                                           UniqueChars&& raw,
     593             :                                           size_t rawLength,
     594             :                                           size_t sourceLength);
     595             :     void setCompressedSource(SharedImmutableString&& raw, size_t sourceLength);
     596             : 
     597             :     // XDR handling
     598             :     template <XDRMode mode>
     599             :     MOZ_MUST_USE bool performXDR(XDRState<mode>* xdr);
     600             : 
     601             :     MOZ_MUST_USE bool setFilename(JSContext* cx, const char* filename);
     602          12 :     const char* introducerFilename() const {
     603          12 :         return introducerFilename_ ? introducerFilename_.get() : filename_.get();
     604             :     }
     605           0 :     bool hasIntroductionType() const {
     606           0 :         return introductionType_;
     607             :     }
     608           0 :     const char* introductionType() const {
     609           0 :         MOZ_ASSERT(hasIntroductionType());
     610           0 :         return introductionType_;
     611             :     }
     612       22773 :     const char* filename() const {
     613       22773 :         return filename_.get();
     614             :     }
     615             : 
     616             :     // Display URLs
     617             :     MOZ_MUST_USE bool setDisplayURL(JSContext* cx, const char16_t* displayURL);
     618        2158 :     bool hasDisplayURL() const { return displayURL_ != nullptr; }
     619           0 :     const char16_t * displayURL() {
     620           0 :         MOZ_ASSERT(hasDisplayURL());
     621           0 :         return displayURL_.get();
     622             :     }
     623             : 
     624             :     // Source maps
     625             :     MOZ_MUST_USE bool setSourceMapURL(JSContext* cx, const char16_t* sourceMapURL);
     626        1434 :     bool hasSourceMapURL() const { return sourceMapURL_ != nullptr; }
     627           0 :     const char16_t * sourceMapURL() {
     628           0 :         MOZ_ASSERT(hasSourceMapURL());
     629           0 :         return sourceMapURL_.get();
     630             :     }
     631             : 
     632       15035 :     bool mutedErrors() const { return mutedErrors_; }
     633             : 
     634        1407 :     uint32_t startColumn() const { return startColumn_; }
     635             : 
     636        2088 :     bool hasIntroductionOffset() const { return hasIntroductionOffset_; }
     637           0 :     uint32_t introductionOffset() const {
     638           0 :         MOZ_ASSERT(hasIntroductionOffset());
     639           0 :         return introductionOffset_;
     640             :     }
     641        2088 :     void setIntroductionOffset(uint32_t offset) {
     642        2088 :         MOZ_ASSERT(!hasIntroductionOffset());
     643        2088 :         MOZ_ASSERT(offset <= (uint32_t)INT32_MAX);
     644        2088 :         introductionOffset_ = offset;
     645        2088 :         hasIntroductionOffset_ = true;
     646        2088 :     }
     647             : 
     648             :     // Return wether an XDR encoder is present or not.
     649        1408 :     bool hasEncoder() const { return bool(xdrEncoder_); }
     650             : 
     651             :     // Create a new XDR encoder, and encode the top-level JSScript. The result
     652             :     // of the encoding would be available in the |buffer| provided as argument,
     653             :     // as soon as |xdrFinalize| is called and all xdr function calls returned
     654             :     // successfully.
     655             :     bool xdrEncodeTopLevel(JSContext* cx, HandleScript script);
     656             : 
     657             :     // Encode a delazified JSFunction.  In case of errors, the XDR encoder is
     658             :     // freed and the |buffer| provided as argument to |xdrEncodeTopLevel| is
     659             :     // considered undefined.
     660             :     //
     661             :     // The |sourceObject| argument is the object holding the current
     662             :     // ScriptSource.
     663             :     bool xdrEncodeFunction(JSContext* cx, HandleFunction fun,
     664             :                            HandleScriptSource sourceObject);
     665             : 
     666             :     // Linearize the encoded content in the |buffer| provided as argument to
     667             :     // |xdrEncodeTopLevel|, and free the XDR encoder.  In case of errors, the
     668             :     // |buffer| is considered undefined.
     669             :     bool xdrFinalizeEncoder(JS::TranscodeBuffer& buffer);
     670             : 
     671        2046 :     const mozilla::TimeStamp parseEnded() const {
     672        2046 :         return parseEnded_;
     673             :     }
     674             :     // Inform `this` source that it has been fully parsed.
     675         269 :     void recordParseEnded() {
     676         269 :         MOZ_ASSERT(parseEnded_.IsNull());
     677         269 :         parseEnded_ = mozilla::TimeStamp::Now();
     678         269 :     }
     679             : };
     680             : 
     681             : class ScriptSourceHolder
     682             : {
     683             :     ScriptSource* ss;
     684             :   public:
     685           0 :     ScriptSourceHolder()
     686           0 :       : ss(nullptr)
     687           0 :     {}
     688        2243 :     explicit ScriptSourceHolder(ScriptSource* ss)
     689        2243 :       : ss(ss)
     690             :     {
     691        2243 :         ss->incref();
     692        2242 :     }
     693        2088 :     ~ScriptSourceHolder()
     694        2088 :     {
     695        2088 :         if (ss)
     696        2088 :             ss->decref();
     697        2088 :     }
     698           0 :     void reset(ScriptSource* newss) {
     699             :         // incref before decref just in case ss == newss.
     700           0 :         if (newss)
     701           0 :             newss->incref();
     702           0 :         if (ss)
     703           0 :             ss->decref();
     704           0 :         ss = newss;
     705           0 :     }
     706           0 :     ScriptSource* get() const {
     707           0 :         return ss;
     708             :     }
     709             : };
     710             : 
     711             : class ScriptSourceObject : public NativeObject
     712             : {
     713             :     static const ClassOps classOps_;
     714             : 
     715             :   public:
     716             :     static const Class class_;
     717             : 
     718             :     static void trace(JSTracer* trc, JSObject* obj);
     719             :     static void finalize(FreeOp* fop, JSObject* obj);
     720             :     static ScriptSourceObject* create(JSContext* cx, ScriptSource* source);
     721             : 
     722             :     // Initialize those properties of this ScriptSourceObject whose values
     723             :     // are provided by |options|, re-wrapping as necessary.
     724             :     static bool initFromOptions(JSContext* cx, HandleScriptSource source,
     725             :                                 const ReadOnlyCompileOptions& options);
     726             : 
     727       52395 :     ScriptSource* source() const {
     728       52395 :         return static_cast<ScriptSource*>(getReservedSlot(SOURCE_SLOT).toPrivate());
     729             :     }
     730           0 :     JSObject* element() const {
     731           0 :         return getReservedSlot(ELEMENT_SLOT).toObjectOrNull();
     732             :     }
     733           0 :     const Value& elementAttributeName() const {
     734           0 :         MOZ_ASSERT(!getReservedSlot(ELEMENT_PROPERTY_SLOT).isMagic());
     735           0 :         return getReservedSlot(ELEMENT_PROPERTY_SLOT);
     736             :     }
     737          22 :     JSScript* introductionScript() const {
     738          22 :         if (getReservedSlot(INTRODUCTION_SCRIPT_SLOT).isUndefined())
     739          22 :             return nullptr;
     740           0 :         void* untyped = getReservedSlot(INTRODUCTION_SCRIPT_SLOT).toPrivate();
     741           0 :         MOZ_ASSERT(untyped);
     742           0 :         return static_cast<JSScript*>(untyped);
     743             :     }
     744             : 
     745             :   private:
     746             :     static const uint32_t SOURCE_SLOT = 0;
     747             :     static const uint32_t ELEMENT_SLOT = 1;
     748             :     static const uint32_t ELEMENT_PROPERTY_SLOT = 2;
     749             :     static const uint32_t INTRODUCTION_SCRIPT_SLOT = 3;
     750             :     static const uint32_t RESERVED_SLOTS = 4;
     751             : };
     752             : 
     753             : enum GeneratorKind { NotGenerator, LegacyGenerator, StarGenerator };
     754             : enum FunctionAsyncKind { SyncFunction, AsyncFunction };
     755             : 
     756             : static inline unsigned
     757       26742 : GeneratorKindAsBits(GeneratorKind generatorKind) {
     758       26742 :     return static_cast<unsigned>(generatorKind);
     759             : }
     760             : 
     761             : static inline GeneratorKind
     762      336521 : GeneratorKindFromBits(unsigned val) {
     763      336521 :     MOZ_ASSERT(val <= StarGenerator);
     764      336521 :     return static_cast<GeneratorKind>(val);
     765             : }
     766             : 
     767             : static inline unsigned
     768        7633 : AsyncKindAsBits(FunctionAsyncKind asyncKind) {
     769        7633 :     return static_cast<unsigned>(asyncKind);
     770             : }
     771             : 
     772             : static inline FunctionAsyncKind
     773       79512 : AsyncKindFromBits(unsigned val) {
     774       79512 :     MOZ_ASSERT(val <= AsyncFunction);
     775       79512 :     return static_cast<FunctionAsyncKind>(val);
     776             : }
     777             : 
     778             : /*
     779             :  * NB: after a successful XDR_DECODE, XDRScript callers must do any required
     780             :  * subsequent set-up of owning function or script object and then call
     781             :  * CallNewScriptHook.
     782             :  */
     783             : template<XDRMode mode>
     784             : bool
     785             : XDRScript(XDRState<mode>* xdr, HandleScope enclosingScope, HandleScriptSource sourceObject,
     786             :           HandleFunction fun, MutableHandleScript scriptp);
     787             : 
     788             : template<XDRMode mode>
     789             : bool
     790             : XDRLazyScript(XDRState<mode>* xdr, HandleScope enclosingScope, HandleScriptSource sourceObject,
     791             :               HandleFunction fun, MutableHandle<LazyScript*> lazy);
     792             : 
     793             : /*
     794             :  * Code any constant value.
     795             :  */
     796             : template<XDRMode mode>
     797             : bool
     798             : XDRScriptConst(XDRState<mode>* xdr, MutableHandleValue vp);
     799             : 
     800             : /*
     801             :  * Common data that can be shared between many scripts in a single runtime.
     802             :  */
     803             : class SharedScriptData
     804             : {
     805             :     // This class is reference counted as follows: each pointer from a JSScript
     806             :     // counts as one reference plus there may be one reference from the shared
     807             :     // script data table.
     808             :     mozilla::Atomic<uint32_t> refCount_;
     809             : 
     810             :     uint32_t dataLength_;
     811             :     uint32_t natoms_;
     812             :     uint32_t codeLength_;
     813             :     uintptr_t data_[1];
     814             : 
     815             :   public:
     816             :     static SharedScriptData* new_(JSContext* cx, uint32_t codeLength,
     817             :                                   uint32_t srcnotesLength, uint32_t natoms);
     818             : 
     819       31882 :     uint32_t refCount() const {
     820       31882 :         return refCount_;
     821             :     }
     822       40121 :     void incRefCount() {
     823       40121 :         refCount_++;
     824       40122 :     }
     825        1093 :     void decRefCount() {
     826        1093 :         MOZ_ASSERT(refCount_ != 0);
     827        1093 :         refCount_--;
     828        1093 :         if (refCount_ == 0)
     829        1093 :             js_free(this);
     830        1093 :     }
     831             : 
     832       16338 :     uint32_t dataLength() const {
     833       16338 :         return dataLength_;
     834             :     }
     835     4979553 :     uint8_t* data() {
     836     4979553 :         return reinterpret_cast<uint8_t*>(data_);
     837             :     }
     838             : 
     839      175805 :     uint32_t natoms() const {
     840      175805 :         return natoms_;
     841             :     }
     842      309814 :     GCPtrAtom* atoms() {
     843      309814 :         if (!natoms_)
     844        1573 :             return nullptr;
     845      308241 :         return reinterpret_cast<GCPtrAtom*>(data());
     846             :     }
     847             : 
     848     2227657 :     uint32_t codeLength() const {
     849     2227657 :         return codeLength_;
     850             :     }
     851     4655249 :     jsbytecode* code() {
     852     4655249 :         return reinterpret_cast<jsbytecode*>(data() + natoms_ * sizeof(GCPtrAtom));
     853             :     }
     854             : 
     855             :     void traceChildren(JSTracer* trc);
     856             : 
     857             :   private:
     858             :     SharedScriptData() = delete;
     859             :     SharedScriptData(const SharedScriptData&) = delete;
     860             :     SharedScriptData& operator=(const SharedScriptData&) = delete;
     861             : };
     862             : 
     863             : struct ScriptBytecodeHasher
     864             : {
     865             :     struct Lookup
     866             :     {
     867             :         const uint8_t* data;
     868             :         uint32_t length;
     869             : 
     870       15245 :         explicit Lookup(SharedScriptData* ssd) : data(ssd->data()), length(ssd->dataLength()) {}
     871             :     };
     872       15245 :     static HashNumber hash(const Lookup& l) { return mozilla::HashBytes(l.data, l.length); }
     873        1093 :     static bool match(SharedScriptData* entry, const Lookup& lookup) {
     874        1093 :         if (entry->dataLength() != lookup.length)
     875           0 :             return false;
     876        1093 :         return mozilla::PodEqual<uint8_t>(entry->data(), lookup.data, lookup.length);
     877             :     }
     878             : };
     879             : 
     880             : typedef HashSet<SharedScriptData*,
     881             :                 ScriptBytecodeHasher,
     882             :                 SystemAllocPolicy> ScriptDataTable;
     883             : 
     884             : extern void
     885             : SweepScriptData(JSRuntime* rt, AutoLockForExclusiveAccess& lock);
     886             : 
     887             : extern void
     888             : FreeScriptData(JSRuntime* rt, AutoLockForExclusiveAccess& lock);
     889             : 
     890             : } /* namespace js */
     891             : 
     892             : class JSScript : public js::gc::TenuredCell
     893             : {
     894             :     template <js::XDRMode mode>
     895             :     friend
     896             :     bool
     897             :     js::XDRScript(js::XDRState<mode>* xdr, js::HandleScope enclosingScope,
     898             :                   js::HandleScriptSource sourceObject, js::HandleFunction fun,
     899             :                   js::MutableHandleScript scriptp);
     900             : 
     901             :     friend bool
     902             :     js::detail::CopyScript(JSContext* cx, js::HandleScript src, js::HandleScript dst,
     903             :                            js::MutableHandle<JS::GCVector<js::Scope*>> scopes);
     904             : 
     905             :   private:
     906             :     js::SharedScriptData* scriptData_;
     907             :   public:
     908             :     uint8_t*        data;      /* pointer to variable-length data array (see
     909             :                                    comment above Create() for details) */
     910             : 
     911             :     JSCompartment*  compartment_;
     912             : 
     913             :   private:
     914             :     /* Persistent type information retained across GCs. */
     915             :     js::TypeScript* types_;
     916             : 
     917             :     // This script's ScriptSourceObject, or a CCW thereof.
     918             :     //
     919             :     // (When we clone a JSScript into a new compartment, we don't clone its
     920             :     // source object. Instead, the clone refers to a wrapper.)
     921             :     js::GCPtrObject sourceObject_;
     922             : 
     923             :     /*
     924             :      * Information attached by Ion. Nexto a valid IonScript this could be
     925             :      * ION_DISABLED_SCRIPT, ION_COMPILING_SCRIPT or ION_PENDING_SCRIPT.
     926             :      * The later is a ion compilation that is ready, but hasn't been linked
     927             :      * yet.
     928             :      */
     929             :     js::jit::IonScript* ion;
     930             : 
     931             :     /* Information attached by Baseline. */
     932             :     js::jit::BaselineScript* baseline;
     933             : 
     934             :     /* Information used to re-lazify a lazily-parsed interpreted function. */
     935             :     js::LazyScript* lazyScript;
     936             : 
     937             :     /*
     938             :      * Pointer to either baseline->method()->raw() or ion->method()->raw(), or
     939             :      * nullptr if there's no Baseline or Ion script.
     940             :      */
     941             :     uint8_t* baselineOrIonRaw;
     942             :     uint8_t* baselineOrIonSkipArgCheck;
     943             : 
     944             :     // 32-bit fields.
     945             : 
     946             :     uint32_t        dataSize_;  /* size of the used part of the data array */
     947             : 
     948             :     uint32_t        lineno_;    /* base line number of script */
     949             :     uint32_t        column_;    /* base column of script, optionally set */
     950             : 
     951             :     uint32_t        mainOffset_;/* offset of main entry point from code, after
     952             :                                    predef'ing prologue */
     953             : 
     954             :     uint32_t        nfixed_;    /* fixed frame slots */
     955             :     uint32_t        nslots_;    /* slots plus maximum stack depth */
     956             : 
     957             :     uint32_t        bodyScopeIndex_; /* index into the scopes array of the body scope */
     958             : 
     959             :     // Range of characters in scriptSource which contains this script's
     960             :     // source, that is, the range used by the Parser to produce this script.
     961             :     //
     962             :     // Most scripted functions have sourceStart_ == toStringStart_ and
     963             :     // sourceEnd_ == toStringEnd_. However, for functions with extra
     964             :     // qualifiers (e.g. generators, async) and for class constructors (which
     965             :     // need to return the entire class source), their values differ.
     966             :     //
     967             :     // Each field points the following locations.
     968             :     //
     969             :     //   function * f(a, b) { return a + b; }
     970             :     //   ^          ^                        ^
     971             :     //   |          |                        |
     972             :     //   |          sourceStart_             sourceEnd_
     973             :     //   |                                   |
     974             :     //   toStringStart_                      toStringEnd_
     975             :     //
     976             :     // And, in the case of class constructors, an additional toStringEnd
     977             :     // offset is used.
     978             :     //
     979             :     //   class C { constructor() { this.field = 42; } }
     980             :     //   ^         ^                                 ^ ^
     981             :     //   |         |                                 | `---------`
     982             :     //   |         sourceStart_                      sourceEnd_  |
     983             :     //   |                                                       |
     984             :     //   toStringStart_                                          toStringEnd_
     985             :     uint32_t        sourceStart_;
     986             :     uint32_t        sourceEnd_;
     987             :     uint32_t        toStringStart_;
     988             :     uint32_t        toStringEnd_;
     989             : 
     990             : #ifdef MOZ_VTUNE
     991             :     // Unique Method ID passed to the VTune profiler, or 0 if unset.
     992             :     // Allows attribution of different jitcode to the same source script.
     993             :     uint32_t        vtuneMethodId_;
     994             :     // Extra padding to maintain JSScript as a multiple of gc::CellAlignBytes.
     995             :     uint32_t        __vtune_unused_padding_;
     996             : #endif
     997             : 
     998             :     // Number of times the script has been called or has had backedges taken.
     999             :     // When running in ion, also increased for any inlined scripts. Reset if
    1000             :     // the script's JIT code is forcibly discarded.
    1001             :     mozilla::Atomic<uint32_t, mozilla::Relaxed> warmUpCount;
    1002             : 
    1003             :     // 16-bit fields.
    1004             : 
    1005             :     uint16_t        warmUpResetCount; /* Number of times the |warmUpCount| was
    1006             :                                        * forcibly discarded. The counter is reset when
    1007             :                                        * a script is successfully jit-compiled. */
    1008             : 
    1009             :     uint16_t        version;    /* JS version under which script was compiled */
    1010             : 
    1011             :     uint16_t        funLength_; /* ES6 function length */
    1012             : 
    1013             :     uint16_t        nTypeSets_; /* number of type sets used in this script for
    1014             :                                    dynamic type monitoring */
    1015             : 
    1016             :     // Bit fields.
    1017             : 
    1018             :   public:
    1019             :     // The kinds of the optional arrays.
    1020             :     enum ArrayKind {
    1021             :         CONSTS,
    1022             :         OBJECTS,
    1023             :         TRYNOTES,
    1024             :         SCOPENOTES,
    1025             :         ARRAY_KIND_BITS
    1026             :     };
    1027             : 
    1028             :   private:
    1029             :     // The bits in this field indicate the presence/non-presence of several
    1030             :     // optional arrays in |data|.  See the comments above Create() for details.
    1031             :     uint8_t         hasArrayBits:ARRAY_KIND_BITS;
    1032             : 
    1033             :     // The GeneratorKind of the script.
    1034             :     uint8_t         generatorKindBits_:2;
    1035             : 
    1036             :     // 1-bit fields.
    1037             : 
    1038             :     // No need for result value of last expression statement.
    1039             :     bool noScriptRval_:1;
    1040             : 
    1041             :     // Code is in strict mode.
    1042             :     bool strict_:1;
    1043             : 
    1044             :     // Code has "use strict"; explicitly.
    1045             :     bool explicitUseStrict_:1;
    1046             : 
    1047             :     // True if the script has a non-syntactic scope on its dynamic scope chain.
    1048             :     // That is, there are objects about which we know nothing between the
    1049             :     // outermost syntactic scope and the global.
    1050             :     bool hasNonSyntacticScope_:1;
    1051             : 
    1052             :     // see Parser::selfHostingMode.
    1053             :     bool selfHosted_:1;
    1054             : 
    1055             :     // See FunctionContextFlags.
    1056             :     bool bindingsAccessedDynamically_:1;
    1057             :     bool funHasExtensibleScope_:1;
    1058             : 
    1059             :     // True if any formalIsAliased(i).
    1060             :     bool funHasAnyAliasedFormal_:1;
    1061             : 
    1062             :     // Have warned about uses of undefined properties in this script.
    1063             :     bool warnedAboutUndefinedProp_:1;
    1064             : 
    1065             :     // Script has singleton objects.
    1066             :     bool hasSingletons_:1;
    1067             : 
    1068             :     // Script is a lambda to treat as running once or a global or eval script
    1069             :     // that will only run once.  Which one it is can be disambiguated by
    1070             :     // checking whether function() is null.
    1071             :     bool treatAsRunOnce_:1;
    1072             : 
    1073             :     // If treatAsRunOnce, whether script has executed.
    1074             :     bool hasRunOnce_:1;
    1075             : 
    1076             :     // Script has been reused for a clone.
    1077             :     bool hasBeenCloned_:1;
    1078             : 
    1079             :     // Script came from eval(), and is still active.
    1080             :     bool isActiveEval_:1;
    1081             : 
    1082             :     // Script came from eval(), and is in eval cache.
    1083             :     bool isCachedEval_:1;
    1084             : 
    1085             :     // 'this', 'arguments' and f.apply() are used. This is likely to be a wrapper.
    1086             :     bool isLikelyConstructorWrapper_:1;
    1087             : 
    1088             :     // IonMonkey compilation hints.
    1089             :     bool failedBoundsCheck_:1; /* script has had hoisted bounds checks fail */
    1090             :     bool failedShapeGuard_:1; /* script has had hoisted shape guard fail */
    1091             :     bool hadFrequentBailouts_:1;
    1092             :     bool hadOverflowBailout_:1;
    1093             :     bool uninlineable_:1;    /* explicitly marked as uninlineable */
    1094             : 
    1095             :     // Idempotent cache has triggered invalidation.
    1096             :     bool invalidatedIdempotentCache_:1;
    1097             : 
    1098             :     // Lexical check did fail and bail out.
    1099             :     bool failedLexicalCheck_:1;
    1100             : 
    1101             :     // If the generator was created implicitly via a generator expression,
    1102             :     // isGeneratorExp will be true.
    1103             :     bool isGeneratorExp_:1;
    1104             : 
    1105             :     // Script has an entry in JSCompartment::scriptCountsMap.
    1106             :     bool hasScriptCounts_:1;
    1107             : 
    1108             :     // Script has an entry in JSCompartment::debugScriptMap.
    1109             :     bool hasDebugScript_:1;
    1110             : 
    1111             :     // Freeze constraints for stack type sets have been generated.
    1112             :     bool hasFreezeConstraints_:1;
    1113             : 
    1114             :     /* See comments below. */
    1115             :     bool argsHasVarBinding_:1;
    1116             :     bool needsArgsAnalysis_:1;
    1117             :     bool needsArgsObj_:1;
    1118             :     bool functionHasThisBinding_:1;
    1119             :     bool functionHasExtraBodyVarScope_:1;
    1120             : 
    1121             :     // Whether the arguments object for this script, if it needs one, should be
    1122             :     // mapped (alias formal parameters).
    1123             :     bool hasMappedArgsObj_:1;
    1124             : 
    1125             :     // Generation for this script's TypeScript. If out of sync with the
    1126             :     // TypeZone's generation, the TypeScript needs to be swept.
    1127             :     //
    1128             :     // This should be a uint32 but is instead a bool so that MSVC packs it
    1129             :     // correctly.
    1130             :     bool typesGeneration_:1;
    1131             : 
    1132             :     // Do not relazify this script. This is used by the relazify() testing
    1133             :     // function for scripts that are on the stack and also by the AutoDelazify
    1134             :     // RAII class. Usually we don't relazify functions in compartments with
    1135             :     // scripts on the stack, but the relazify() testing function overrides that,
    1136             :     // and sometimes we're working with a cross-compartment function and need to
    1137             :     // keep it from relazifying.
    1138             :     bool doNotRelazify_:1;
    1139             : 
    1140             :     // Script contains inner functions. Used to check if we can relazify the
    1141             :     // script.
    1142             :     bool hasInnerFunctions_:1;
    1143             : 
    1144             :     bool needsHomeObject_:1;
    1145             : 
    1146             :     bool isDerivedClassConstructor_:1;
    1147             :     bool isDefaultClassConstructor_:1;
    1148             : 
    1149             :     bool isAsync_:1;
    1150             : 
    1151             :     bool hasRest_:1;
    1152             :     bool isExprBody_:1;
    1153             : 
    1154             :     // Add padding so JSScript is gc::Cell aligned. Make padding protected
    1155             :     // instead of private to suppress -Wunused-private-field compiler warnings.
    1156             :   protected:
    1157             : #if JS_BITS_PER_WORD == 32
    1158             :     // Currently no padding is needed.
    1159             : #endif
    1160             : 
    1161             :     //
    1162             :     // End of fields.  Start methods.
    1163             :     //
    1164             : 
    1165             :   public:
    1166             :     static JSScript* Create(JSContext* cx,
    1167             :                             const JS::ReadOnlyCompileOptions& options,
    1168             :                             js::HandleObject sourceObject,
    1169             :                             uint32_t sourceStart, uint32_t sourceEnd,
    1170             :                             uint32_t toStringStart, uint32_t toStringEnd);
    1171             : 
    1172             :     void initCompartment(JSContext* cx);
    1173             : 
    1174             :     // Three ways ways to initialize a JSScript. Callers of partiallyInit()
    1175             :     // are responsible for notifying the debugger after successfully creating
    1176             :     // any kind (function or other) of new JSScript.  However, callers of
    1177             :     // fullyInitFromEmitter() do not need to do this.
    1178             :     static bool partiallyInit(JSContext* cx, JS::Handle<JSScript*> script,
    1179             :                               uint32_t nscopes, uint32_t nconsts, uint32_t nobjects,
    1180             :                               uint32_t ntrynotes, uint32_t nscopenotes, uint32_t nyieldoffsets,
    1181             :                               uint32_t nTypeSets);
    1182             : 
    1183             :   private:
    1184             :     static void initFromFunctionBox(JSContext* cx, js::HandleScript script,
    1185             :                                     js::frontend::FunctionBox* funbox);
    1186             :     static void initFromModuleContext(JSContext* cx, js::HandleScript script,
    1187             :                                       js::frontend::ModuleSharedContext* modulesc);
    1188             : 
    1189             :   public:
    1190             :     static bool fullyInitFromEmitter(JSContext* cx, js::HandleScript script,
    1191             :                                      js::frontend::BytecodeEmitter* bce);
    1192             : 
    1193             :     // Initialize the Function.prototype script.
    1194             :     static bool initFunctionPrototype(JSContext* cx, js::HandleScript script,
    1195             :                                       JS::HandleFunction functionProto);
    1196             : 
    1197             : #ifdef DEBUG
    1198             :   private:
    1199             :     // Assert that jump targets are within the code array of the script.
    1200             :     void assertValidJumpTargets() const;
    1201             : #endif
    1202             : 
    1203             :   public:
    1204             :     inline JSPrincipals* principals();
    1205             : 
    1206      126578 :     JSCompartment* compartment() const { return compartment_; }
    1207           0 :     JSCompartment* maybeCompartment() const { return compartment(); }
    1208             : 
    1209             :     void setVersion(JSVersion v) { version = v; }
    1210             : 
    1211      153996 :     js::SharedScriptData* scriptData() {
    1212      153996 :         return scriptData_;
    1213             :     }
    1214             : 
    1215             :     // Script bytecode is immutable after creation.
    1216     4655248 :     jsbytecode* code() const {
    1217     4655248 :         if (!scriptData_)
    1218           0 :             return nullptr;
    1219     4655248 :         return scriptData_->code();
    1220             :     }
    1221     2227658 :     size_t length() const {
    1222     2227658 :         MOZ_ASSERT(scriptData_);
    1223     2227658 :         return scriptData_->codeLength();
    1224             :     }
    1225             : 
    1226     1591623 :     jsbytecode* codeEnd() const { return code() + length(); }
    1227             : 
    1228          78 :     jsbytecode* lastPC() const {
    1229          78 :         jsbytecode* pc = codeEnd() - js::JSOP_RETRVAL_LENGTH;
    1230          78 :         MOZ_ASSERT(*pc == JSOP_RETRVAL);
    1231          78 :         return pc;
    1232             :     }
    1233             : 
    1234     1429754 :     bool containsPC(const jsbytecode* pc) const {
    1235     1429754 :         return pc >= code() && pc < codeEnd();
    1236             :     }
    1237             : 
    1238     1099048 :     size_t pcToOffset(const jsbytecode* pc) const {
    1239     1099048 :         MOZ_ASSERT(containsPC(pc));
    1240     1099046 :         return size_t(pc - code());
    1241             :     }
    1242             : 
    1243      267414 :     jsbytecode* offsetToPC(size_t offset) const {
    1244      267414 :         MOZ_ASSERT(offset < length());
    1245      267414 :         return code() + offset;
    1246             :     }
    1247             : 
    1248      116595 :     size_t mainOffset() const {
    1249      116595 :         return mainOffset_;
    1250             :     }
    1251             : 
    1252       32075 :     size_t lineno() const {
    1253       32075 :         return lineno_;
    1254             :     }
    1255             : 
    1256       17170 :     size_t column() const {
    1257       17170 :         return column_;
    1258             :     }
    1259             : 
    1260        1211 :     void setColumn(size_t column) { column_ = column; }
    1261             : 
    1262             :     // The fixed part of a stack frame is comprised of vars (in function and
    1263             :     // module code) and block-scoped locals (in all kinds of code).
    1264      363684 :     size_t nfixed() const {
    1265      363684 :         return nfixed_;
    1266             :     }
    1267             : 
    1268             :     // Number of fixed slots reserved for slots that are always live. Only
    1269             :     // nonzero for function or module code.
    1270         264 :     size_t numAlwaysLiveFixedSlots() const {
    1271         264 :         if (bodyScope()->is<js::FunctionScope>())
    1272         230 :             return bodyScope()->as<js::FunctionScope>().nextFrameSlot();
    1273          34 :         if (bodyScope()->is<js::ModuleScope>())
    1274           0 :             return bodyScope()->as<js::ModuleScope>().nextFrameSlot();
    1275          34 :         return 0;
    1276             :     }
    1277             : 
    1278             :     // Calculate the number of fixed slots that are live at a particular bytecode.
    1279             :     size_t calculateLiveFixed(jsbytecode* pc);
    1280             : 
    1281       52713 :     size_t nslots() const {
    1282       52713 :         return nslots_;
    1283             :     }
    1284             : 
    1285        8998 :     unsigned numArgs() const {
    1286        8998 :         if (bodyScope()->is<js::FunctionScope>())
    1287        8998 :             return bodyScope()->as<js::FunctionScope>().numPositionalFormalParameters();
    1288           0 :         return 0;
    1289             :     }
    1290             : 
    1291             :     inline js::Shape* initialEnvironmentShape() const;
    1292             : 
    1293       22908 :     bool functionHasParameterExprs() const {
    1294             :         // Only functions have parameters.
    1295       22908 :         js::Scope* scope = bodyScope();
    1296       22908 :         if (!scope->is<js::FunctionScope>())
    1297           0 :             return false;
    1298       22908 :         return scope->as<js::FunctionScope>().hasParameterExprs();
    1299             :     }
    1300             : 
    1301      117895 :     size_t nTypeSets() const {
    1302      117895 :         return nTypeSets_;
    1303             :     }
    1304             : 
    1305       13130 :     size_t funLength() const {
    1306       13130 :         return funLength_;
    1307             :     }
    1308             : 
    1309           0 :     static size_t offsetOfFunLength() {
    1310           0 :         return offsetof(JSScript, funLength_);
    1311             :     }
    1312             : 
    1313       10801 :     uint32_t sourceStart() const {
    1314       10801 :         return sourceStart_;
    1315             :     }
    1316             : 
    1317       10801 :     uint32_t sourceEnd() const {
    1318       10801 :         return sourceEnd_;
    1319             :     }
    1320             : 
    1321       10802 :     uint32_t toStringStart() const {
    1322       10802 :         return toStringStart_;
    1323             :     }
    1324             : 
    1325       10802 :     uint32_t toStringEnd() const {
    1326       10802 :         return toStringEnd_;
    1327             :     }
    1328             : 
    1329       27253 :     bool noScriptRval() const {
    1330       27253 :         return noScriptRval_;
    1331             :     }
    1332             : 
    1333       27335 :     bool strict() const {
    1334       27335 :         return strict_;
    1335             :     }
    1336             : 
    1337       12525 :     bool explicitUseStrict() const { return explicitUseStrict_; }
    1338             : 
    1339       66119 :     bool hasNonSyntacticScope() const {
    1340       66119 :         return hasNonSyntacticScope_;
    1341             :     }
    1342             : 
    1343       19663 :     bool selfHosted() const { return selfHosted_; }
    1344       12666 :     bool bindingsAccessedDynamically() const { return bindingsAccessedDynamically_; }
    1345       39969 :     bool funHasExtensibleScope() const {
    1346       39969 :         return funHasExtensibleScope_;
    1347             :     }
    1348       12654 :     bool funHasAnyAliasedFormal() const {
    1349       12654 :         return funHasAnyAliasedFormal_;
    1350             :     }
    1351             : 
    1352       12533 :     bool hasSingletons() const { return hasSingletons_; }
    1353       46047 :     bool treatAsRunOnce() const {
    1354       46047 :         return treatAsRunOnce_;
    1355             :     }
    1356          34 :     bool hasRunOnce() const { return hasRunOnce_; }
    1357        1325 :     bool hasBeenCloned() const { return hasBeenCloned_; }
    1358             : 
    1359          10 :     void setTreatAsRunOnce() { treatAsRunOnce_ = true; }
    1360          24 :     void setHasRunOnce() { hasRunOnce_ = true; }
    1361        1347 :     void setHasBeenCloned() { hasBeenCloned_ = true; }
    1362             : 
    1363      113556 :     bool isActiveEval() const { return isActiveEval_; }
    1364      111132 :     bool isCachedEval() const { return isCachedEval_; }
    1365             : 
    1366           2 :     void cacheForEval() {
    1367           2 :         MOZ_ASSERT(isActiveEval() && !isCachedEval());
    1368           2 :         isActiveEval_ = false;
    1369           2 :         isCachedEval_ = true;
    1370             :         // IsEvalCacheCandidate will make sure that there's nothing in this
    1371             :         // script that would prevent reexecution even if isRunOnce is
    1372             :         // true.  So just pretend like we never ran this script.
    1373           2 :         hasRunOnce_ = false;
    1374           2 :     }
    1375             : 
    1376           0 :     void uncacheForEval() {
    1377           0 :         MOZ_ASSERT(isCachedEval() && !isActiveEval());
    1378           0 :         isCachedEval_ = false;
    1379           0 :         isActiveEval_ = true;
    1380           0 :     }
    1381             : 
    1382           2 :     void setActiveEval() { isActiveEval_ = true; }
    1383             : 
    1384       22448 :     bool isLikelyConstructorWrapper() const {
    1385       22448 :         return isLikelyConstructorWrapper_;
    1386             :     }
    1387           0 :     void setLikelyConstructorWrapper() { isLikelyConstructorWrapper_ = true; }
    1388             : 
    1389       12758 :     bool isGeneratorExp() const { return isGeneratorExp_; }
    1390             : 
    1391         179 :     bool failedBoundsCheck() const {
    1392         179 :         return failedBoundsCheck_;
    1393             :     }
    1394         179 :     bool failedShapeGuard() const {
    1395         179 :         return failedShapeGuard_;
    1396             :     }
    1397           8 :     bool hadFrequentBailouts() const {
    1398           8 :         return hadFrequentBailouts_;
    1399             :     }
    1400         179 :     bool hadOverflowBailout() const {
    1401         179 :         return hadOverflowBailout_;
    1402             :     }
    1403          45 :     bool uninlineable() const {
    1404          45 :         return uninlineable_;
    1405             :     }
    1406          20 :     bool invalidatedIdempotentCache() const {
    1407          20 :         return invalidatedIdempotentCache_;
    1408             :     }
    1409         179 :     bool failedLexicalCheck() const {
    1410         179 :         return failedLexicalCheck_;
    1411             :     }
    1412       13054 :     bool isDefaultClassConstructor() const {
    1413       13054 :         return isDefaultClassConstructor_;
    1414             :     }
    1415             : 
    1416           0 :     void setFailedBoundsCheck() { failedBoundsCheck_ = true; }
    1417           0 :     void setFailedShapeGuard() { failedShapeGuard_ = true; }
    1418           0 :     void setHadFrequentBailouts() { hadFrequentBailouts_ = true; }
    1419           0 :     void setHadOverflowBailout() { hadOverflowBailout_ = true; }
    1420         264 :     void setUninlineable() { uninlineable_ = true; }
    1421           0 :     void setInvalidatedIdempotentCache() { invalidatedIdempotentCache_ = true; }
    1422           0 :     void setFailedLexicalCheck() { failedLexicalCheck_ = true; }
    1423           6 :     void setIsDefaultClassConstructor() { isDefaultClassConstructor_ = true; }
    1424             : 
    1425      105569 :     bool hasScriptCounts() const { return hasScriptCounts_; }
    1426             :     bool hasScriptName();
    1427             : 
    1428          31 :     bool hasFreezeConstraints() const { return hasFreezeConstraints_; }
    1429          10 :     void setHasFreezeConstraints() { hasFreezeConstraints_ = true; }
    1430             : 
    1431           0 :     bool warnedAboutUndefinedProp() const { return warnedAboutUndefinedProp_; }
    1432           0 :     void setWarnedAboutUndefinedProp() { warnedAboutUndefinedProp_ = true; }
    1433             : 
    1434             :     /* See ContextFlags::funArgumentsHasLocalBinding comment. */
    1435       24908 :     bool argumentsHasVarBinding() const {
    1436       24908 :         return argsHasVarBinding_;
    1437             :     }
    1438             :     void setArgumentsHasVarBinding();
    1439        2165 :     bool argumentsAliasesFormals() const {
    1440        2165 :         return argumentsHasVarBinding() && hasMappedArgsObj();
    1441             :     }
    1442             : 
    1443      209118 :     js::GeneratorKind generatorKind() const {
    1444      209118 :         return js::GeneratorKindFromBits(generatorKindBits_);
    1445             :     }
    1446       47831 :     bool isLegacyGenerator() const { return generatorKind() == js::LegacyGenerator; }
    1447       48460 :     bool isStarGenerator() const { return generatorKind() == js::StarGenerator; }
    1448       15058 :     void setGeneratorKind(js::GeneratorKind kind) {
    1449             :         // A script only gets its generator kind set as part of initialization,
    1450             :         // so it can only transition from not being a generator.
    1451       15058 :         MOZ_ASSERT(!isStarGenerator() && !isLegacyGenerator());
    1452       15058 :         generatorKindBits_ = GeneratorKindAsBits(kind);
    1453       15058 :     }
    1454             : 
    1455       12525 :     js::FunctionAsyncKind asyncKind() const {
    1456       12525 :         return isAsync_ ? js::AsyncFunction : js::SyncFunction;
    1457             :     }
    1458       93041 :     bool isAsync() const {
    1459       93041 :         return isAsync_;
    1460             :     }
    1461             : 
    1462        5702 :     void setAsyncKind(js::FunctionAsyncKind kind) {
    1463        5702 :         isAsync_ = kind == js::AsyncFunction;
    1464        5702 :     }
    1465             : 
    1466        4289 :     bool hasRest() const {
    1467        4289 :         return hasRest_;
    1468             :     }
    1469         110 :     void setHasRest() {
    1470         110 :         hasRest_ = true;
    1471         110 :     }
    1472             : 
    1473        2893 :     bool isExprBody() const {
    1474        2893 :         return isExprBody_;
    1475             :     }
    1476         907 :     void setIsExprBody() {
    1477         907 :         isExprBody_ = true;
    1478         907 :     }
    1479             : 
    1480             :     void setNeedsHomeObject() {
    1481             :         needsHomeObject_ = true;
    1482             :     }
    1483       39475 :     bool needsHomeObject() const {
    1484       39475 :         return needsHomeObject_;
    1485             :     }
    1486             : 
    1487       41143 :     bool isDerivedClassConstructor() const {
    1488       41143 :         return isDerivedClassConstructor_;
    1489             :     }
    1490             : 
    1491             :     /*
    1492             :      * As an optimization, even when argsHasLocalBinding, the function prologue
    1493             :      * may not need to create an arguments object. This is determined by
    1494             :      * needsArgsObj which is set by AnalyzeArgumentsUsage. When !needsArgsObj,
    1495             :      * the prologue may simply write MagicValue(JS_OPTIMIZED_ARGUMENTS) to
    1496             :      * 'arguments's slot and any uses of 'arguments' will be guaranteed to
    1497             :      * handle this magic value. To avoid spurious arguments object creation, we
    1498             :      * maintain the invariant that needsArgsObj is only called after the script
    1499             :      * has been analyzed.
    1500             :      */
    1501       53745 :     bool analyzedArgsUsage() const { return !needsArgsAnalysis_; }
    1502             :     inline bool ensureHasAnalyzedArgsUsage(JSContext* cx);
    1503       49533 :     bool needsArgsObj() const {
    1504       49533 :         MOZ_ASSERT(analyzedArgsUsage());
    1505       49533 :         return needsArgsObj_;
    1506             :     }
    1507             :     void setNeedsArgsObj(bool needsArgsObj);
    1508             :     static bool argumentsOptimizationFailed(JSContext* cx, js::HandleScript script);
    1509             : 
    1510       13630 :     bool hasMappedArgsObj() const {
    1511       13630 :         return hasMappedArgsObj_;
    1512             :     }
    1513             : 
    1514       12531 :     bool functionHasThisBinding() const {
    1515       12531 :         return functionHasThisBinding_;
    1516             :     }
    1517             : 
    1518             :     /*
    1519             :      * Arguments access (via JSOP_*ARG* opcodes) must access the canonical
    1520             :      * location for the argument. If an arguments object exists AND it's mapped
    1521             :      * ('arguments' aliases formals), then all access must go through the
    1522             :      * arguments object. Otherwise, the local slot is the canonical location for
    1523             :      * the arguments. Note: if a formal is aliased through the scope chain, then
    1524             :      * script->formalIsAliased and JSOP_*ARG* opcodes won't be emitted at all.
    1525             :      */
    1526       45105 :     bool argsObjAliasesFormals() const {
    1527       45105 :         return needsArgsObj() && hasMappedArgsObj();
    1528             :     }
    1529             : 
    1530       31598 :     uint32_t typesGeneration() const {
    1531       31598 :         return (uint32_t) typesGeneration_;
    1532             :     }
    1533             : 
    1534        5829 :     void setTypesGeneration(uint32_t generation) {
    1535        5829 :         MOZ_ASSERT(generation <= 1);
    1536        5829 :         typesGeneration_ = (bool) generation;
    1537        5829 :     }
    1538             : 
    1539       16540 :     void setDoNotRelazify(bool b) {
    1540       16540 :         doNotRelazify_ = b;
    1541       16540 :     }
    1542             : 
    1543        5405 :     void setHasInnerFunctions(bool b) {
    1544        5405 :         hasInnerFunctions_ = b;
    1545        5405 :     }
    1546             : 
    1547       12525 :     bool hasInnerFunctions() const {
    1548       12525 :         return hasInnerFunctions_;
    1549             :     }
    1550             : 
    1551         522 :     bool hasAnyIonScript() const {
    1552         522 :         return hasIonScript();
    1553             :     }
    1554             : 
    1555       91357 :     bool hasIonScript() const {
    1556      137851 :         bool res = ion && ion != ION_DISABLED_SCRIPT && ion != ION_COMPILING_SCRIPT &&
    1557      137851 :                           ion != ION_PENDING_SCRIPT;
    1558       91357 :         MOZ_ASSERT_IF(res, baseline);
    1559       91357 :         return res;
    1560             :     }
    1561       40581 :     bool canIonCompile() const {
    1562       40581 :         return ion != ION_DISABLED_SCRIPT;
    1563             :     }
    1564       39270 :     bool isIonCompilingOffThread() const {
    1565       39270 :         return ion == ION_COMPILING_SCRIPT;
    1566             :     }
    1567             : 
    1568       27860 :     js::jit::IonScript* ionScript() const {
    1569       27860 :         MOZ_ASSERT(hasIonScript());
    1570       27860 :         return ion;
    1571             :     }
    1572           8 :     js::jit::IonScript* maybeIonScript() const {
    1573           8 :         return ion;
    1574             :     }
    1575             :     js::jit::IonScript* const* addressOfIonScript() const {
    1576             :         return &ion;
    1577             :     }
    1578             :     void setIonScript(JSRuntime* maybeRuntime, js::jit::IonScript* ionScript);
    1579             : 
    1580      416027 :     bool hasBaselineScript() const {
    1581      416027 :         bool res = baseline && baseline != BASELINE_DISABLED_SCRIPT;
    1582      416027 :         MOZ_ASSERT_IF(!res, !ion || ion == ION_DISABLED_SCRIPT);
    1583      416027 :         return res;
    1584             :     }
    1585       22381 :     bool canBaselineCompile() const {
    1586       22381 :         return baseline != BASELINE_DISABLED_SCRIPT;
    1587             :     }
    1588      184396 :     js::jit::BaselineScript* baselineScript() const {
    1589      184396 :         MOZ_ASSERT(hasBaselineScript());
    1590      184396 :         return baseline;
    1591             :     }
    1592             :     inline void setBaselineScript(JSRuntime* maybeRuntime, js::jit::BaselineScript* baselineScript);
    1593             : 
    1594             :     void updateBaselineOrIonRaw(JSRuntime* maybeRuntime);
    1595             : 
    1596         673 :     static size_t offsetOfBaselineScript() {
    1597         673 :         return offsetof(JSScript, baseline);
    1598             :     }
    1599         865 :     static size_t offsetOfIonScript() {
    1600         865 :         return offsetof(JSScript, ion);
    1601             :     }
    1602          82 :     static size_t offsetOfBaselineOrIonRaw() {
    1603          82 :         return offsetof(JSScript, baselineOrIonRaw);
    1604             :     }
    1605           6 :     uint8_t* baselineOrIonRawPointer() const {
    1606           6 :         return baselineOrIonRaw;
    1607             :     }
    1608           7 :     static size_t offsetOfBaselineOrIonSkipArgCheck() {
    1609           7 :         return offsetof(JSScript, baselineOrIonSkipArgCheck);
    1610             :     }
    1611             : 
    1612        4487 :     bool isRelazifiable() const {
    1613        9498 :         return (selfHosted() || lazyScript) && !hasInnerFunctions_ && !types_ &&
    1614        1570 :                !isStarGenerator() && !isLegacyGenerator() && !isAsync() &&
    1615        1044 :                !isDefaultClassConstructor() &&
    1616        6053 :                !hasBaselineScript() && !hasAnyIonScript() &&
    1617        5009 :                !doNotRelazify_;
    1618             :     }
    1619        2143 :     void setLazyScript(js::LazyScript* lazy) {
    1620        2143 :         lazyScript = lazy;
    1621        2143 :     }
    1622        2151 :     js::LazyScript* maybeLazyScript() {
    1623        2151 :         return lazyScript;
    1624             :     }
    1625             : 
    1626             :     /*
    1627             :      * Original compiled function for the script, if it has a function.
    1628             :      * nullptr for global and eval scripts.
    1629             :      * The delazifying variant ensures that the function isn't lazy. The
    1630             :      * non-delazifying variant must only be used after earlier code has
    1631             :      * called ensureNonLazyCanonicalFunction and while the function can't
    1632             :      * have been relazified.
    1633             :      */
    1634             :     inline JSFunction* functionDelazifying() const;
    1635      538001 :     JSFunction* functionNonDelazifying() const {
    1636      538001 :         if (bodyScope()->is<js::FunctionScope>())
    1637      533331 :             return bodyScope()->as<js::FunctionScope>().canonicalFunction();
    1638        4670 :         return nullptr;
    1639             :     }
    1640             :     /*
    1641             :      * De-lazifies the canonical function. Must be called before entering code
    1642             :      * that expects the function to be non-lazy.
    1643             :      */
    1644             :     inline void ensureNonLazyCanonicalFunction();
    1645             : 
    1646       13017 :     js::ModuleObject* module() const {
    1647       13017 :         if (bodyScope()->is<js::ModuleScope>())
    1648           0 :             return bodyScope()->as<js::ModuleScope>().module();
    1649       13017 :         return nullptr;
    1650             :     }
    1651             : 
    1652             :     bool isGlobalOrEvalCode() const {
    1653             :         return bodyScope()->is<js::GlobalScope>() || bodyScope()->is<js::EvalScope>();
    1654             :     }
    1655       14067 :     bool isGlobalCode() const {
    1656       14067 :         return bodyScope()->is<js::GlobalScope>();
    1657             :     }
    1658             : 
    1659             :     // Returns true if the script may read formal arguments on the stack
    1660             :     // directly, via lazy arguments or a rest parameter.
    1661             :     bool mayReadFrameArgsDirectly();
    1662             : 
    1663             :     static JSFlatString* sourceData(JSContext* cx, JS::HandleScript script);
    1664             : 
    1665             :     MOZ_MUST_USE bool appendSourceDataForToString(JSContext* cx, js::StringBuffer& buf);
    1666             : 
    1667             :     static bool loadSource(JSContext* cx, js::ScriptSource* ss, bool* worked);
    1668             : 
    1669             :     void setSourceObject(JSObject* object);
    1670       66961 :     JSObject* sourceObject() const {
    1671       66961 :         return sourceObject_;
    1672             :     }
    1673             :     js::ScriptSourceObject& scriptSourceUnwrap() const;
    1674             :     js::ScriptSource* scriptSource() const;
    1675             :     js::ScriptSource* maybeForwardedScriptSource() const;
    1676             : 
    1677             :     void setDefaultClassConstructorSpan(JSObject* sourceObject, uint32_t start, uint32_t end);
    1678             : 
    1679       13625 :     bool mutedErrors() const { return scriptSource()->mutedErrors(); }
    1680       19698 :     const char* filename() const { return scriptSource()->filename(); }
    1681           0 :     const char* maybeForwardedFilename() const { return maybeForwardedScriptSource()->filename(); }
    1682             : 
    1683             : #ifdef MOZ_VTUNE
    1684           0 :     uint32_t vtuneMethodID() const { return vtuneMethodId_; }
    1685             : #endif
    1686             : 
    1687             :   public:
    1688             : 
    1689             :     /* Return whether this script was compiled for 'eval' */
    1690       55565 :     bool isForEval() const {
    1691       55565 :         MOZ_ASSERT_IF(isCachedEval() || isActiveEval(), bodyScope()->is<js::EvalScope>());
    1692       55565 :         return isCachedEval() || isActiveEval();
    1693             :     }
    1694             : 
    1695             :     /* Return whether this is a 'direct eval' script in a function scope. */
    1696         500 :     bool isDirectEvalInFunction() const {
    1697         500 :         if (!isForEval())
    1698         496 :             return false;
    1699           4 :         return bodyScope()->hasOnChain(js::ScopeKind::Function);
    1700             :     }
    1701             : 
    1702             :     /*
    1703             :      * Return whether this script is a top-level script.
    1704             :      *
    1705             :      * If we evaluate some code which contains a syntax error, then we might
    1706             :      * produce a JSScript which has no associated bytecode. Testing with
    1707             :      * |code()| filters out this kind of scripts.
    1708             :      *
    1709             :      * If this script has a function associated to it, then it is not the
    1710             :      * top-level of a file.
    1711             :      */
    1712           0 :     bool isTopLevel() { return code() && !functionNonDelazifying(); }
    1713             : 
    1714             :     /* Ensure the script has a TypeScript. */
    1715             :     inline bool ensureHasTypes(JSContext* cx);
    1716             : 
    1717             :     inline js::TypeScript* types();
    1718             : 
    1719             :     void maybeSweepTypes(js::AutoClearTypeInferenceStateOnOOM* oom);
    1720             : 
    1721             :     inline js::GlobalObject& global() const;
    1722             :     js::GlobalObject& uninlinedGlobal() const;
    1723             : 
    1724       46443 :     uint32_t bodyScopeIndex() const {
    1725       46443 :         return bodyScopeIndex_;
    1726             :     }
    1727             : 
    1728     1335354 :     js::Scope* bodyScope() const {
    1729     1335354 :         return getScope(bodyScopeIndex_);
    1730             :     }
    1731             : 
    1732       91343 :     js::Scope* outermostScope() const {
    1733             :         // The body scope may not be the outermost scope in the script when
    1734             :         // the decl env scope is present.
    1735       91343 :         size_t index = 0;
    1736       91343 :         return getScope(index);
    1737             :     }
    1738             : 
    1739       25972 :     bool functionHasExtraBodyVarScope() const {
    1740       25972 :         MOZ_ASSERT_IF(functionHasExtraBodyVarScope_, functionHasParameterExprs());
    1741       25972 :         return functionHasExtraBodyVarScope_;
    1742             :     }
    1743             : 
    1744          81 :     js::VarScope* functionExtraBodyVarScope() const {
    1745          81 :         MOZ_ASSERT(functionHasExtraBodyVarScope());
    1746         165 :         for (uint32_t i = 0; i < scopes()->length; i++) {
    1747         165 :             js::Scope* scope = getScope(i);
    1748         165 :             if (scope->kind() == js::ScopeKind::FunctionBodyVar)
    1749         162 :                 return &scope->as<js::VarScope>();
    1750             :         }
    1751           0 :         MOZ_CRASH("Function extra body var scope not found");
    1752             :     }
    1753             : 
    1754         179 :     bool needsBodyEnvironment() const {
    1755         402 :         for (uint32_t i = 0; i < scopes()->length; i++) {
    1756         227 :             js::Scope* scope = getScope(i);
    1757         227 :             if (ScopeKindIsInBody(scope->kind()) && scope->hasEnvironment())
    1758           4 :                 return true;
    1759             :         }
    1760         175 :         return false;
    1761             :     }
    1762             : 
    1763             :     inline js::LexicalScope* maybeNamedLambdaScope() const;
    1764             : 
    1765       52460 :     js::Scope* enclosingScope() const {
    1766       52460 :         return outermostScope()->enclosing();
    1767             :     }
    1768             : 
    1769             :   private:
    1770             :     bool makeTypes(JSContext* cx);
    1771             : 
    1772             :     bool createScriptData(JSContext* cx, uint32_t codeLength, uint32_t srcnotesLength,
    1773             :                           uint32_t natoms);
    1774             :     bool shareScriptData(JSContext* cx);
    1775             :     void freeScriptData();
    1776             :     void setScriptData(js::SharedScriptData* data);
    1777             : 
    1778             :   public:
    1779        7087 :     uint32_t getWarmUpCount() const { return warmUpCount; }
    1780       14693 :     uint32_t incWarmUpCounter(uint32_t amount = 1) { return warmUpCount += amount; }
    1781           6 :     uint32_t* addressOfWarmUpCounter() { return reinterpret_cast<uint32_t*>(&warmUpCount); }
    1782         892 :     static size_t offsetOfWarmUpCounter() { return offsetof(JSScript, warmUpCount); }
    1783       22585 :     void resetWarmUpCounter() { incWarmUpResetCounter(); warmUpCount = 0; }
    1784             : 
    1785           0 :     uint16_t getWarmUpResetCount() const { return warmUpResetCount; }
    1786       22585 :     uint16_t incWarmUpResetCounter(uint16_t amount = 1) { return warmUpResetCount += amount; }
    1787        1174 :     void resetWarmUpResetCounter() { warmUpResetCount = 0; }
    1788             : 
    1789             :   public:
    1790             :     bool initScriptCounts(JSContext* cx);
    1791             :     bool initScriptName(JSContext* cx);
    1792             :     js::ScriptCounts& getScriptCounts();
    1793             :     const char* getScriptName();
    1794             :     js::PCCounts* maybeGetPCCounts(jsbytecode* pc);
    1795             :     const js::PCCounts* maybeGetThrowCounts(jsbytecode* pc);
    1796             :     js::PCCounts* getThrowCounts(jsbytecode* pc);
    1797             :     uint64_t getHitCount(jsbytecode* pc);
    1798             :     void incHitCount(jsbytecode* pc); // Used when we bailout out of Ion.
    1799             :     void addIonCounts(js::jit::IonScriptCounts* ionCounts);
    1800             :     js::jit::IonScriptCounts* getIonCounts();
    1801             :     void releaseScriptCounts(js::ScriptCounts* counts);
    1802             :     void destroyScriptCounts(js::FreeOp* fop);
    1803             :     void destroyScriptName();
    1804             :     // The entry should be removed after using this function.
    1805             :     void takeOverScriptCountsMapEntry(js::ScriptCounts* entryValue);
    1806             : 
    1807       86541 :     jsbytecode* main() const {
    1808       86541 :         return code() + mainOffset();
    1809             :     }
    1810             : 
    1811             :     /*
    1812             :      * computedSizeOfData() is the in-use size of all the data sections.
    1813             :      * sizeOfData() is the size of the block allocated to hold all the data
    1814             :      * sections (which can be larger than the in-use size).
    1815             :      */
    1816             :     size_t computedSizeOfData() const;
    1817             :     size_t sizeOfData(mozilla::MallocSizeOf mallocSizeOf) const;
    1818             :     size_t sizeOfTypeScript(mozilla::MallocSizeOf mallocSizeOf) const;
    1819             : 
    1820             :     uint32_t numNotes();  /* Number of srcnote slots in the srcnotes section */
    1821             : 
    1822             :     /* Script notes are allocated right after the code. */
    1823        4701 :     jssrcnote* notes() { return (jssrcnote*)(code() + length()); }
    1824             : 
    1825      477539 :     bool hasArray(ArrayKind kind) const {
    1826      477539 :         return hasArrayBits & (1 << kind);
    1827             :     }
    1828       11751 :     void setHasArray(ArrayKind kind) { hasArrayBits |= (1 << kind); }
    1829        9632 :     void cloneHasArray(JSScript* script) { hasArrayBits = script->hasArrayBits; }
    1830             : 
    1831      144148 :     bool hasConsts() const       { return hasArray(CONSTS); }
    1832      142668 :     bool hasObjects() const      { return hasArray(OBJECTS); }
    1833       98528 :     bool hasTrynotes() const     { return hasArray(TRYNOTES); }
    1834       92162 :     bool hasScopeNotes() const   { return hasArray(SCOPENOTES); }
    1835       14811 :     bool hasYieldAndAwaitOffsets() const {
    1836       14811 :         return isStarGenerator() || isLegacyGenerator() || isAsync();
    1837             :     }
    1838             : 
    1839             : #define OFF(fooOff, hasFoo, t)   (fooOff() + (hasFoo() ? sizeof(t) : 0))
    1840             : 
    1841     1707961 :     size_t scopesOffset() const       { return 0; }
    1842      131318 :     size_t constsOffset() const       { return scopesOffset() + sizeof(js::ScopeArray); }
    1843      129838 :     size_t objectsOffset() const      { return OFF(constsOffset,     hasConsts,     js::ConstArray); }
    1844       74912 :     size_t trynotesOffset() const     { return OFF(objectsOffset,    hasObjects,    js::ObjectArray); }
    1845       52621 :     size_t scopeNotesOffset() const   { return OFF(trynotesOffset,   hasTrynotes,   js::TryNoteArray); }
    1846        2280 :     size_t yieldAndAwaitOffsetsOffset() const {
    1847        2280 :         return OFF(scopeNotesOffset, hasScopeNotes, js::ScopeNoteArray);
    1848             :     }
    1849             : 
    1850             : #undef OFF
    1851             : 
    1852        9632 :     size_t dataSize() const { return dataSize_; }
    1853             : 
    1854        1480 :     js::ConstArray* consts() {
    1855        1480 :         MOZ_ASSERT(hasConsts());
    1856        1480 :         return reinterpret_cast<js::ConstArray*>(data + constsOffset());
    1857             :     }
    1858             : 
    1859       54927 :     js::ObjectArray* objects() {
    1860       54927 :         MOZ_ASSERT(hasObjects());
    1861       54927 :         return reinterpret_cast<js::ObjectArray*>(data + objectsOffset());
    1862             :     }
    1863             : 
    1864     1576718 :     js::ScopeArray* scopes() const {
    1865     1576718 :         return reinterpret_cast<js::ScopeArray*>(data + scopesOffset());
    1866             :     }
    1867             : 
    1868       22249 :     js::TryNoteArray* trynotes() const {
    1869       22249 :         MOZ_ASSERT(hasTrynotes());
    1870       22249 :         return reinterpret_cast<js::TryNoteArray*>(data + trynotesOffset());
    1871             :     }
    1872             : 
    1873       50293 :     js::ScopeNoteArray* scopeNotes() {
    1874       50293 :         MOZ_ASSERT(hasScopeNotes());
    1875       50293 :         return reinterpret_cast<js::ScopeNoteArray*>(data + scopeNotesOffset());
    1876             :     }
    1877             : 
    1878        2280 :     js::YieldAndAwaitOffsetArray& yieldAndAwaitOffsets() {
    1879        2280 :         MOZ_ASSERT(hasYieldAndAwaitOffsets());
    1880        2280 :         return *reinterpret_cast<js::YieldAndAwaitOffsetArray*>(data +
    1881        2280 :                                                                 yieldAndAwaitOffsetsOffset());
    1882             :     }
    1883             : 
    1884             :     bool hasLoops();
    1885             : 
    1886      129209 :     size_t natoms() const {
    1887      129209 :         MOZ_ASSERT(scriptData_);
    1888      129209 :         return scriptData_->natoms();
    1889             :     }
    1890      252652 :     js::GCPtrAtom* atoms() const {
    1891      252652 :         MOZ_ASSERT(scriptData_);
    1892      252652 :         return scriptData_->atoms();
    1893             :     }
    1894             : 
    1895      126316 :     js::GCPtrAtom& getAtom(size_t index) const {
    1896      126316 :         MOZ_ASSERT(index < natoms());
    1897      126316 :         return atoms()[index];
    1898             :     }
    1899             : 
    1900       12755 :     js::GCPtrAtom& getAtom(jsbytecode* pc) const {
    1901       12755 :         MOZ_ASSERT(containsPC(pc) && containsPC(pc + sizeof(uint32_t)));
    1902       12755 :         return getAtom(GET_UINT32_INDEX(pc));
    1903             :     }
    1904             : 
    1905           3 :     js::PropertyName* getName(size_t index) {
    1906           3 :         return getAtom(index)->asPropertyName();
    1907             :     }
    1908             : 
    1909      111933 :     js::PropertyName* getName(jsbytecode* pc) const {
    1910      111933 :         MOZ_ASSERT(containsPC(pc) && containsPC(pc + sizeof(uint32_t)));
    1911      111933 :         return getAtom(GET_UINT32_INDEX(pc))->asPropertyName();
    1912             :     }
    1913             : 
    1914       17601 :     JSObject* getObject(size_t index) {
    1915       17601 :         js::ObjectArray* arr = objects();
    1916       17601 :         MOZ_ASSERT(index < arr->length);
    1917       17601 :         MOZ_ASSERT(arr->vector[index]->isTenured());
    1918       17601 :         return arr->vector[index];
    1919             :     }
    1920             : 
    1921        4429 :     JSObject* getObject(jsbytecode* pc) {
    1922        4429 :         MOZ_ASSERT(containsPC(pc) && containsPC(pc + sizeof(uint32_t)));
    1923        4429 :         return getObject(GET_UINT32_INDEX(pc));
    1924             :     }
    1925             : 
    1926     1449715 :     js::Scope* getScope(size_t index) const {
    1927     1449715 :         js::ScopeArray* array = scopes();
    1928     1449714 :         MOZ_ASSERT(index < array->length);
    1929     1449714 :         return array->vector[index];
    1930             :     }
    1931             : 
    1932         556 :     js::Scope* getScope(jsbytecode* pc) const {
    1933             :         // This method is used to get a scope directly using a JSOp with an
    1934             :         // index. To search through ScopeNotes to look for a Scope using pc,
    1935             :         // use lookupScope.
    1936         556 :         MOZ_ASSERT(containsPC(pc) && containsPC(pc + sizeof(uint32_t)));
    1937         556 :         MOZ_ASSERT(js::JOF_OPTYPE(JSOp(*pc)) == JOF_SCOPE,
    1938             :                    "Did you mean to use lookupScope(pc)?");
    1939         556 :         return getScope(GET_UINT32_INDEX(pc));
    1940             :     }
    1941             : 
    1942       50642 :     JSVersion getVersion() const {
    1943       50642 :         return JSVersion(version);
    1944             :     }
    1945             : 
    1946             :     inline JSFunction* getFunction(size_t index);
    1947       22275 :     JSFunction* function() const {
    1948       22275 :         if (functionNonDelazifying())
    1949       21762 :             return functionNonDelazifying();
    1950         513 :         return nullptr;
    1951             :     }
    1952             : 
    1953             :     inline js::RegExpObject* getRegExp(size_t index);
    1954             :     inline js::RegExpObject* getRegExp(jsbytecode* pc);
    1955             : 
    1956         855 :     const js::Value& getConst(size_t index) {
    1957         855 :         js::ConstArray* arr = consts();
    1958         855 :         MOZ_ASSERT(index < arr->length);
    1959         855 :         return arr->vector[index];
    1960             :     }
    1961             : 
    1962             :     // The following 3 functions find the static scope just before the
    1963             :     // execution of the instruction pointed to by pc.
    1964             : 
    1965             :     js::Scope* lookupScope(jsbytecode* pc);
    1966             : 
    1967             :     js::Scope* innermostScope(jsbytecode* pc);
    1968           0 :     js::Scope* innermostScope() { return innermostScope(main()); }
    1969             : 
    1970             :     /*
    1971             :      * The isEmpty method tells whether this script has code that computes any
    1972             :      * result (not return value, result AKA normal completion value) other than
    1973             :      * JSVAL_VOID, or any other effects.
    1974             :      */
    1975         498 :     bool isEmpty() const {
    1976         498 :         if (length() > 3)
    1977         422 :             return false;
    1978             : 
    1979          76 :         jsbytecode* pc = code();
    1980          76 :         if (noScriptRval() && JSOp(*pc) == JSOP_FALSE)
    1981           0 :             ++pc;
    1982          76 :         return JSOp(*pc) == JSOP_RETRVAL;
    1983             :     }
    1984             : 
    1985             :     bool formalIsAliased(unsigned argSlot);
    1986             :     bool formalLivesInArgumentsObject(unsigned argSlot);
    1987             : 
    1988             :   private:
    1989             :     /* Change this->stepMode to |newValue|. */
    1990             :     void setNewStepMode(js::FreeOp* fop, uint32_t newValue);
    1991             : 
    1992             :     bool ensureHasDebugScript(JSContext* cx);
    1993             :     js::DebugScript* debugScript();
    1994             :     js::DebugScript* releaseDebugScript();
    1995             :     void destroyDebugScript(js::FreeOp* fop);
    1996             : 
    1997             :   public:
    1998             :     bool hasBreakpointsAt(jsbytecode* pc);
    1999       14170 :     bool hasAnyBreakpointsOrStepMode() { return hasDebugScript_; }
    2000             : 
    2001             :     // See comment above 'debugMode' in jscompartment.h for explanation of
    2002             :     // invariants of debuggee compartments, scripts, and frames.
    2003             :     inline bool isDebuggee() const;
    2004             : 
    2005           0 :     js::BreakpointSite* getBreakpointSite(jsbytecode* pc)
    2006             :     {
    2007           0 :         return hasDebugScript_ ? debugScript()->breakpoints[pcToOffset(pc)] : nullptr;
    2008             :     }
    2009             : 
    2010             :     js::BreakpointSite* getOrCreateBreakpointSite(JSContext* cx, jsbytecode* pc);
    2011             : 
    2012             :     void destroyBreakpointSite(js::FreeOp* fop, jsbytecode* pc);
    2013             : 
    2014             :     void clearBreakpointsIn(js::FreeOp* fop, js::Debugger* dbg, JSObject* handler);
    2015             : 
    2016             :     /*
    2017             :      * Increment or decrement the single-step count. If the count is non-zero
    2018             :      * then the script is in single-step mode.
    2019             :      *
    2020             :      * Only incrementing is fallible, as it could allocate a DebugScript.
    2021             :      */
    2022             :     bool incrementStepModeCount(JSContext* cx);
    2023             :     void decrementStepModeCount(js::FreeOp* fop);
    2024             : 
    2025           0 :     bool stepModeEnabled() { return hasDebugScript_ && !!debugScript()->stepMode; }
    2026             : 
    2027             : #ifdef DEBUG
    2028           0 :     uint32_t stepModeCount() { return hasDebugScript_ ? debugScript()->stepMode : 0; }
    2029             : #endif
    2030             : 
    2031             :     void finalize(js::FreeOp* fop);
    2032             : 
    2033             :     static const JS::TraceKind TraceKind = JS::TraceKind::Script;
    2034             : 
    2035             :     void traceChildren(JSTracer* trc);
    2036             : 
    2037             :     // A helper class to prevent relazification of the given function's script
    2038             :     // while it's holding on to it.  This class automatically roots the script.
    2039             :     class AutoDelazify;
    2040             :     friend class AutoDelazify;
    2041             : 
    2042             :     class AutoDelazify
    2043             :     {
    2044             :         JS::RootedScript script_;
    2045             :         JSContext* cx_;
    2046             :         bool oldDoNotRelazify_;
    2047             :       public:
    2048       10362 :         explicit AutoDelazify(JSContext* cx, JS::HandleFunction fun = nullptr)
    2049       10362 :             : script_(cx)
    2050       10362 :             , cx_(cx)
    2051             :         {
    2052       10362 :             holdScript(fun);
    2053       10362 :         }
    2054             : 
    2055       10362 :         ~AutoDelazify()
    2056       10362 :         {
    2057       10362 :             dropScript();
    2058       10362 :         }
    2059             : 
    2060        1463 :         void operator=(JS::HandleFunction fun)
    2061             :         {
    2062        1463 :             dropScript();
    2063        1463 :             holdScript(fun);
    2064        1463 :         }
    2065             : 
    2066        7385 :         operator JS::HandleScript() const { return script_; }
    2067        8849 :         explicit operator bool() const { return script_; }
    2068             : 
    2069             :       private:
    2070             :         void holdScript(JS::HandleFunction fun);
    2071             :         void dropScript();
    2072             :     };
    2073             : };
    2074             : 
    2075             : /* If this fails, add/remove padding within JSScript. */
    2076             : static_assert(sizeof(JSScript) % js::gc::CellAlignBytes == 0,
    2077             :               "Size of JSScript must be an integral multiple of js::gc::CellAlignBytes");
    2078             : 
    2079             : namespace js {
    2080             : 
    2081             : // Information about a script which may be (or has been) lazily compiled to
    2082             : // bytecode from its source.
    2083             : class LazyScript : public gc::TenuredCell
    2084             : {
    2085             :   private:
    2086             :     // If non-nullptr, the script has been compiled and this is a forwarding
    2087             :     // pointer to the result. This is a weak pointer: after relazification, we
    2088             :     // can collect the script if there are no other pointers to it.
    2089             :     WeakRef<JSScript*> script_;
    2090             : 
    2091             :     // Original function with which the lazy script is associated.
    2092             :     GCPtrFunction function_;
    2093             : 
    2094             :     // Scope in which the script is nested.
    2095             :     GCPtrScope enclosingScope_;
    2096             : 
    2097             :     // ScriptSourceObject. We leave this set to nullptr until we generate
    2098             :     // bytecode for our immediate parent. This is never a CCW; we don't clone
    2099             :     // LazyScripts into other compartments.
    2100             :     GCPtrObject sourceObject_;
    2101             : 
    2102             :     // Heap allocated table with any free variables or inner functions.
    2103             :     void* table_;
    2104             : 
    2105             :     // Add padding so LazyScript is gc::Cell aligned. Make padding protected
    2106             :     // instead of private to suppress -Wunused-private-field compiler warnings.
    2107             :   protected:
    2108             : #if JS_BITS_PER_WORD == 32
    2109             :     uint32_t padding;
    2110             : #endif
    2111             : 
    2112             :   private:
    2113             :     static const uint32_t NumClosedOverBindingsBits = 20;
    2114             :     static const uint32_t NumInnerFunctionsBits = 20;
    2115             : 
    2116             :     struct PackedView {
    2117             :         // Assorted bits that should really be in ScriptSourceObject.
    2118             :         uint32_t version : 8;
    2119             : 
    2120             :         uint32_t shouldDeclareArguments : 1;
    2121             :         uint32_t hasThisBinding : 1;
    2122             :         uint32_t isAsync : 1;
    2123             :         uint32_t isExprBody : 1;
    2124             : 
    2125             :         uint32_t numClosedOverBindings : NumClosedOverBindingsBits;
    2126             : 
    2127             :         // -- 32bit boundary --
    2128             : 
    2129             :         uint32_t numInnerFunctions : NumInnerFunctionsBits;
    2130             : 
    2131             :         uint32_t generatorKindBits : 2;
    2132             : 
    2133             :         // N.B. These are booleans but need to be uint32_t to pack correctly on MSVC.
    2134             :         // If you add another boolean here, make sure to initialze it in
    2135             :         // LazyScript::CreateRaw().
    2136             :         uint32_t strict : 1;
    2137             :         uint32_t bindingsAccessedDynamically : 1;
    2138             :         uint32_t hasDebuggerStatement : 1;
    2139             :         uint32_t hasDirectEval : 1;
    2140             :         uint32_t isLikelyConstructorWrapper : 1;
    2141             :         uint32_t hasBeenCloned : 1;
    2142             :         uint32_t treatAsRunOnce : 1;
    2143             :         uint32_t isDerivedClassConstructor : 1;
    2144             :         uint32_t needsHomeObject : 1;
    2145             :         uint32_t hasRest : 1;
    2146             :     };
    2147             : 
    2148             :     union {
    2149             :         PackedView p_;
    2150             :         uint64_t packedFields_;
    2151             :     };
    2152             : 
    2153             :     // Source location for the script.
    2154             :     // See the comment in JSScript for the details
    2155             :     uint32_t begin_;
    2156             :     uint32_t end_;
    2157             :     uint32_t toStringStart_;
    2158             :     uint32_t toStringEnd_;
    2159             :     // Line and column of |begin_| position, that is the position where we
    2160             :     // start parsing.
    2161             :     uint32_t lineno_;
    2162             :     uint32_t column_;
    2163             : 
    2164             :     LazyScript(JSFunction* fun, void* table, uint64_t packedFields,
    2165             :                uint32_t begin, uint32_t end, uint32_t toStringStart,
    2166             :                uint32_t lineno, uint32_t column);
    2167             : 
    2168             :     // Create a LazyScript without initializing the closedOverBindings and the
    2169             :     // innerFunctions. To be GC-safe, the caller must initialize both vectors
    2170             :     // with valid atoms and functions.
    2171             :     static LazyScript* CreateRaw(JSContext* cx, HandleFunction fun,
    2172             :                                  uint64_t packedData, uint32_t begin, uint32_t end,
    2173             :                                  uint32_t toStringStart, uint32_t lineno, uint32_t column);
    2174             : 
    2175             :   public:
    2176             :     static const uint32_t NumClosedOverBindingsLimit = 1 << NumClosedOverBindingsBits;
    2177             :     static const uint32_t NumInnerFunctionsLimit = 1 << NumInnerFunctionsBits;
    2178             : 
    2179             :     // Create a LazyScript and initialize closedOverBindings and innerFunctions
    2180             :     // with the provided vectors.
    2181             :     static LazyScript* Create(JSContext* cx, HandleFunction fun,
    2182             :                               const frontend::AtomVector& closedOverBindings,
    2183             :                               Handle<GCVector<JSFunction*, 8>> innerFunctions,
    2184             :                               JSVersion version, uint32_t begin, uint32_t end,
    2185             :                               uint32_t toStringStart, uint32_t lineno, uint32_t column);
    2186             : 
    2187             :     // Create a LazyScript and initialize the closedOverBindings and the
    2188             :     // innerFunctions with dummy values to be replaced in a later initialization
    2189             :     // phase.
    2190             :     //
    2191             :     // The "script" argument to this function can be null.  If it's non-null,
    2192             :     // then this LazyScript should be associated with the given JSScript.
    2193             :     //
    2194             :     // The sourceObject and enclosingScope arguments may be null if the
    2195             :     // enclosing function is also lazy.
    2196             :     static LazyScript* Create(JSContext* cx, HandleFunction fun,
    2197             :                               HandleScript script, HandleScope enclosingScope,
    2198             :                               HandleScriptSource sourceObject,
    2199             :                               uint64_t packedData, uint32_t begin, uint32_t end,
    2200             :                               uint32_t toStringStart, uint32_t lineno, uint32_t column);
    2201             : 
    2202             :     void initRuntimeFields(uint64_t packedFields);
    2203             : 
    2204             :     static inline JSFunction* functionDelazifying(JSContext* cx, Handle<LazyScript*>);
    2205        5033 :     JSFunction* functionNonDelazifying() const {
    2206        5033 :         return function_;
    2207             :     }
    2208             : 
    2209             :     void initScript(JSScript* script);
    2210             :     void resetScript();
    2211             : 
    2212        4798 :     JSScript* maybeScript() {
    2213        4798 :         return script_;
    2214             :     }
    2215           0 :     const JSScript* maybeScriptUnbarriered() const {
    2216           0 :         return script_.unbarrieredGet();
    2217             :     }
    2218        2133 :     bool hasScript() const {
    2219        2133 :         return bool(script_);
    2220             :     }
    2221             : 
    2222        9055 :     Scope* enclosingScope() const {
    2223        9055 :         return enclosingScope_;
    2224             :     }
    2225             : 
    2226             :     ScriptSourceObject* sourceObject() const;
    2227        9095 :     ScriptSource* scriptSource() const {
    2228        9095 :         return sourceObject()->source();
    2229             :     }
    2230             :     ScriptSource* maybeForwardedScriptSource() const;
    2231        1407 :     bool mutedErrors() const {
    2232        1407 :         return scriptSource()->mutedErrors();
    2233             :     }
    2234        3435 :     JSVersion version() const {
    2235             :         JS_STATIC_ASSERT(JSVERSION_UNKNOWN == -1);
    2236        3435 :         return (p_.version == JS_BIT(8) - 1) ? JSVERSION_UNKNOWN : JSVersion(p_.version);
    2237             :     }
    2238             : 
    2239             :     void setEnclosingScopeAndSource(Scope* enclosingScope, ScriptSourceObject* sourceObject);
    2240             : 
    2241       29111 :     uint32_t numClosedOverBindings() const {
    2242       29111 :         return p_.numClosedOverBindings;
    2243             :     }
    2244       20779 :     JSAtom** closedOverBindings() {
    2245       20779 :         return (JSAtom**)table_;
    2246             :     }
    2247             : 
    2248        8703 :     uint32_t numInnerFunctions() const {
    2249        8703 :         return p_.numInnerFunctions;
    2250             :     }
    2251        6019 :     GCPtrFunction* innerFunctions() {
    2252        6019 :         return (GCPtrFunction*)&closedOverBindings()[numClosedOverBindings()];
    2253             :     }
    2254             : 
    2255        9175 :     GeneratorKind generatorKind() const { return GeneratorKindFromBits(p_.generatorKindBits); }
    2256             : 
    2257        3433 :     bool isLegacyGenerator() const { return generatorKind() == LegacyGenerator; }
    2258             : 
    2259        2023 :     bool isStarGenerator() const { return generatorKind() == StarGenerator; }
    2260             : 
    2261        2023 :     void setGeneratorKind(GeneratorKind kind) {
    2262             :         // A script only gets its generator kind set as part of initialization,
    2263             :         // so it can only transition from NotGenerator.
    2264        2023 :         MOZ_ASSERT(!isStarGenerator() && !isLegacyGenerator());
    2265             :         // Legacy generators cannot currently be lazy.
    2266        2023 :         MOZ_ASSERT(kind != LegacyGenerator);
    2267        2023 :         p_.generatorKindBits = GeneratorKindAsBits(kind);
    2268        2023 :     }
    2269             : 
    2270        1667 :     FunctionAsyncKind asyncKind() const {
    2271        1667 :         return p_.isAsync ? AsyncFunction : SyncFunction;
    2272             :     }
    2273        1680 :     bool isAsync() const {
    2274        1680 :         return p_.isAsync;
    2275             :     }
    2276             : 
    2277        2023 :     void setAsyncKind(FunctionAsyncKind kind) {
    2278        2023 :         p_.isAsync = kind == AsyncFunction;
    2279        2023 :     }
    2280             : 
    2281             :     bool hasRest() const {
    2282             :         return p_.hasRest;
    2283             :     }
    2284          11 :     void setHasRest() {
    2285          11 :         p_.hasRest = true;
    2286          11 :     }
    2287             : 
    2288         260 :     bool isExprBody() const {
    2289         260 :         return p_.isExprBody;
    2290             :     }
    2291         177 :     void setIsExprBody() {
    2292         177 :         p_.isExprBody = true;
    2293         177 :     }
    2294             : 
    2295        1412 :     bool strict() const {
    2296        1412 :         return p_.strict;
    2297             :     }
    2298        1652 :     void setStrict() {
    2299        1652 :         p_.strict = true;
    2300        1652 :     }
    2301             : 
    2302         260 :     bool bindingsAccessedDynamically() const {
    2303         260 :         return p_.bindingsAccessedDynamically;
    2304             :     }
    2305           0 :     void setBindingsAccessedDynamically() {
    2306           0 :         p_.bindingsAccessedDynamically = true;
    2307           0 :     }
    2308             : 
    2309         260 :     bool hasDebuggerStatement() const {
    2310         260 :         return p_.hasDebuggerStatement;
    2311             :     }
    2312           0 :     void setHasDebuggerStatement() {
    2313           0 :         p_.hasDebuggerStatement = true;
    2314           0 :     }
    2315             : 
    2316        1702 :     bool hasDirectEval() const {
    2317        1702 :         return p_.hasDirectEval;
    2318             :     }
    2319           0 :     void setHasDirectEval() {
    2320           0 :         p_.hasDirectEval = true;
    2321           0 :     }
    2322             : 
    2323        4037 :     bool isLikelyConstructorWrapper() const {
    2324        4037 :         return p_.isLikelyConstructorWrapper;
    2325             :     }
    2326           0 :     void setLikelyConstructorWrapper() {
    2327           0 :         p_.isLikelyConstructorWrapper = true;
    2328           0 :     }
    2329             : 
    2330        1498 :     bool hasBeenCloned() const {
    2331        1498 :         return p_.hasBeenCloned;
    2332             :     }
    2333          86 :     void setHasBeenCloned() {
    2334          86 :         p_.hasBeenCloned = true;
    2335          86 :     }
    2336             : 
    2337        1665 :     bool treatAsRunOnce() const {
    2338        1665 :         return p_.treatAsRunOnce;
    2339             :     }
    2340           0 :     void setTreatAsRunOnce() {
    2341           0 :         p_.treatAsRunOnce = true;
    2342           0 :     }
    2343             : 
    2344        1409 :     bool isDerivedClassConstructor() const {
    2345        1409 :         return p_.isDerivedClassConstructor;
    2346             :     }
    2347           4 :     void setIsDerivedClassConstructor() {
    2348           4 :         p_.isDerivedClassConstructor = true;
    2349           4 :     }
    2350             : 
    2351        1667 :     bool needsHomeObject() const {
    2352        1667 :         return p_.needsHomeObject;
    2353             :     }
    2354           0 :     void setNeedsHomeObject() {
    2355           0 :         p_.needsHomeObject = true;
    2356           0 :     }
    2357             : 
    2358        1128 :     bool shouldDeclareArguments() const {
    2359        1128 :         return p_.shouldDeclareArguments;
    2360             :     }
    2361           6 :     void setShouldDeclareArguments() {
    2362           6 :         p_.shouldDeclareArguments = true;
    2363           6 :     }
    2364             : 
    2365        1128 :     bool hasThisBinding() const {
    2366        1128 :         return p_.hasThisBinding;
    2367             :     }
    2368         924 :     void setHasThisBinding() {
    2369         924 :         p_.hasThisBinding = true;
    2370         924 :     }
    2371             : 
    2372        1407 :     const char* filename() const {
    2373        1407 :         return scriptSource()->filename();
    2374             :     }
    2375        7455 :     uint32_t begin() const {
    2376        7455 :         return begin_;
    2377             :     }
    2378        6046 :     uint32_t end() const {
    2379        6046 :         return end_;
    2380             :     }
    2381        3360 :     uint32_t toStringStart() const {
    2382        3360 :         return toStringStart_;
    2383             :     }
    2384        1953 :     uint32_t toStringEnd() const {
    2385        1953 :         return toStringEnd_;
    2386             :     }
    2387        4388 :     uint32_t lineno() const {
    2388        4388 :         return lineno_;
    2389             :     }
    2390        5849 :     uint32_t column() const {
    2391        5849 :         return column_;
    2392             :     }
    2393             : 
    2394        2143 :     void setToStringEnd(uint32_t toStringEnd) {
    2395        2143 :         MOZ_ASSERT(toStringStart_ <= toStringEnd);
    2396        2143 :         MOZ_ASSERT(toStringEnd_ >= end_);
    2397        2143 :         toStringEnd_ = toStringEnd;
    2398        2143 :     }
    2399             : 
    2400             :     bool hasUncompiledEnclosingScript() const;
    2401             : 
    2402             :     friend class GCMarker;
    2403             :     void traceChildren(JSTracer* trc);
    2404             :     void finalize(js::FreeOp* fop);
    2405             : 
    2406             :     static const JS::TraceKind TraceKind = JS::TraceKind::LazyScript;
    2407             : 
    2408           0 :     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
    2409             :     {
    2410           0 :         return mallocSizeOf(table_);
    2411             :     }
    2412             : 
    2413         546 :     uint64_t packedFields() const {
    2414         546 :         return packedFields_;
    2415             :     }
    2416             : };
    2417             : 
    2418             : /* If this fails, add/remove padding within LazyScript. */
    2419             : static_assert(sizeof(LazyScript) % js::gc::CellAlignBytes == 0,
    2420             :               "Size of LazyScript must be an integral multiple of js::gc::CellAlignBytes");
    2421             : 
    2422           0 : struct ScriptAndCounts
    2423             : {
    2424             :     /* This structure is stored and marked from the JSRuntime. */
    2425             :     JSScript* script;
    2426             :     ScriptCounts scriptCounts;
    2427             : 
    2428             :     inline explicit ScriptAndCounts(JSScript* script);
    2429             :     inline ScriptAndCounts(ScriptAndCounts&& sac);
    2430             : 
    2431           0 :     const PCCounts* maybeGetPCCounts(jsbytecode* pc) const {
    2432           0 :         return scriptCounts.maybeGetPCCounts(script->pcToOffset(pc));
    2433             :     }
    2434           0 :     const PCCounts* maybeGetThrowCounts(jsbytecode* pc) const {
    2435           0 :         return scriptCounts.maybeGetThrowCounts(script->pcToOffset(pc));
    2436             :     }
    2437             : 
    2438           0 :     jit::IonScriptCounts* getIonCounts() const {
    2439           0 :         return scriptCounts.ionCounts_;
    2440             :     }
    2441             : 
    2442           0 :     void trace(JSTracer* trc) {
    2443           0 :         TraceRoot(trc, &script, "ScriptAndCounts::script");
    2444           0 :     }
    2445             : };
    2446             : 
    2447             : struct GSNCache;
    2448             : 
    2449             : jssrcnote*
    2450             : GetSrcNote(GSNCache& cache, JSScript* script, jsbytecode* pc);
    2451             : 
    2452             : extern jssrcnote*
    2453             : GetSrcNote(JSContext* cx, JSScript* script, jsbytecode* pc);
    2454             : 
    2455             : extern jsbytecode*
    2456             : LineNumberToPC(JSScript* script, unsigned lineno);
    2457             : 
    2458             : extern JS_FRIEND_API(unsigned)
    2459             : GetScriptLineExtent(JSScript* script);
    2460             : 
    2461             : } /* namespace js */
    2462             : 
    2463             : namespace js {
    2464             : 
    2465             : extern unsigned
    2466             : PCToLineNumber(JSScript* script, jsbytecode* pc, unsigned* columnp = nullptr);
    2467             : 
    2468             : extern unsigned
    2469             : PCToLineNumber(unsigned startLine, jssrcnote* notes, jsbytecode* code, jsbytecode* pc,
    2470             :                unsigned* columnp = nullptr);
    2471             : 
    2472             : /*
    2473             :  * This function returns the file and line number of the script currently
    2474             :  * executing on cx. If there is no current script executing on cx (e.g., a
    2475             :  * native called directly through JSAPI (e.g., by setTimeout)), nullptr and 0
    2476             :  * are returned as the file and line. Additionally, this function avoids the
    2477             :  * full linear scan to compute line number when the caller guarantees that the
    2478             :  * script compilation occurs at a JSOP_EVAL/JSOP_SPREADEVAL.
    2479             :  */
    2480             : 
    2481             : enum LineOption {
    2482             :     CALLED_FROM_JSOP_EVAL,
    2483             :     NOT_CALLED_FROM_JSOP_EVAL
    2484             : };
    2485             : 
    2486             : extern void
    2487             : DescribeScriptedCallerForCompilation(JSContext* cx, MutableHandleScript maybeScript,
    2488             :                                      const char** file, unsigned* linenop,
    2489             :                                      uint32_t* pcOffset, bool* mutedErrors,
    2490             :                                      LineOption opt = NOT_CALLED_FROM_JSOP_EVAL);
    2491             : 
    2492             : JSScript*
    2493             : CloneScriptIntoFunction(JSContext* cx, HandleScope enclosingScope, HandleFunction fun,
    2494             :                         HandleScript src);
    2495             : 
    2496             : JSScript*
    2497             : CloneGlobalScript(JSContext* cx, ScopeKind scopeKind, HandleScript src);
    2498             : 
    2499             : } /* namespace js */
    2500             : 
    2501             : // JS::ubi::Nodes can point to js::LazyScripts; they're js::gc::Cell instances
    2502             : // with no associated compartment.
    2503             : namespace JS {
    2504             : namespace ubi {
    2505             : template<>
    2506             : class Concrete<js::LazyScript> : TracerConcrete<js::LazyScript> {
    2507             :   protected:
    2508           0 :     explicit Concrete(js::LazyScript *ptr) : TracerConcrete<js::LazyScript>(ptr) { }
    2509             : 
    2510             :   public:
    2511           0 :     static void construct(void *storage, js::LazyScript *ptr) { new (storage) Concrete(ptr); }
    2512             : 
    2513           0 :     CoarseType coarseType() const final { return CoarseType::Script; }
    2514             :     Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
    2515             :     const char* scriptFilename() const final;
    2516             : 
    2517           0 :     const char16_t* typeName() const override { return concreteTypeName; }
    2518             :     static const char16_t concreteTypeName[];
    2519             : };
    2520             : } // namespace ubi
    2521             : } // namespace JS
    2522             : 
    2523             : #endif /* jsscript_h */

Generated by: LCOV version 1.13