"Fossies" - the Fresh Open Source Software Archive

Member "UXP-2019.06.08/js/src/jsscript.h" (8 Jun 2019, 76287 Bytes) of package /linux/www/UXP-2019.06.08.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "jsscript.h": 2019.03.27_vs_2019.06.08.

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