/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 * vim: set ts=8 sts=4 et sw=4 tw=99:
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/* JS script descriptor. */

#ifndef jsscript_h
#define jsscript_h

#include "mozilla/Atomics.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/PodOperations.h"
#include "mozilla/UniquePtr.h"

#include "jsatom.h"
#include "jslock.h"
#include "jsopcode.h"
#include "jstypes.h"

#include "gc/Barrier.h"
#include "gc/Rooting.h"
#include "jit/IonCode.h"
#include "js/UbiNode.h"
#include "vm/NativeObject.h"
#include "vm/Shape.h"

namespace JS {
struct ScriptSourceInfo;
} // namespace JS

namespace js {

namespace jit {
    struct BaselineScript;
    struct IonScriptCounts;
} // namespace jit

# define ION_DISABLED_SCRIPT ((js::jit::IonScript*)0x1)
# define ION_COMPILING_SCRIPT ((js::jit::IonScript*)0x2)
# define ION_PENDING_SCRIPT ((js::jit::IonScript*)0x3)

# define BASELINE_DISABLED_SCRIPT ((js::jit::BaselineScript*)0x1)

class BreakpointSite;
class BindingIter;
class Debugger;
class LazyScript;
class ModuleObject;
class NestedScopeObject;
class RegExpObject;
struct SourceCompressionTask;
class Shape;

namespace frontend {
    struct BytecodeEmitter;
    class UpvarCookie;
    class FunctionBox;
    class ModuleBox;
} // namespace frontend

namespace detail {

// Do not call this directly! It is exposed for the friend declarations in
// this file.
bool
CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScript src, HandleScript dst);

} // namespace detail

} // namespace js

/*
 * Type of try note associated with each catch or finally block, and also with
 * for-in and other kinds of loops. Non-for-in loops do not need these notes
 * for exception unwinding, but storing their boundaries here is helpful for
 * heuristics that need to know whether a given op is inside a loop.
 */
enum JSTryNoteKind {
    JSTRY_CATCH,
    JSTRY_FINALLY,
    JSTRY_FOR_IN,
    JSTRY_FOR_OF,
    JSTRY_LOOP
};

/*
 * Exception handling record.
 */
struct JSTryNote {
    uint8_t         kind;       /* one of JSTryNoteKind */
    uint32_t        stackDepth; /* stack depth upon exception handler entry */
    uint32_t        start;      /* start of the try statement or loop
                                   relative to script->main */
    uint32_t        length;     /* length of the try statement or loop */
};

namespace js {

// A block scope has a range in bytecode: it is entered at some offset, and left
// at some later offset.  Scopes can be nested.  Given an offset, the
// BlockScopeNote containing that offset whose with the highest start value
// indicates the block scope.  The block scope list is sorted by increasing
// start value.
//
// It is possible to leave a scope nonlocally, for example via a "break"
// statement, so there may be short bytecode ranges in a block scope in which we
// are popping the block chain in preparation for a goto.  These exits are also
// nested with respect to outer scopes.  The scopes in these exits are indicated
// by the "index" field, just like any other block.  If a nonlocal exit pops the
// last block scope, the index will be NoBlockScopeIndex.
//
struct BlockScopeNote {
    static const uint32_t NoBlockScopeIndex = UINT32_MAX;

    uint32_t        index;      // Index of NestedScopeObject in the object
                                // array, or NoBlockScopeIndex if there is no
                                // block scope in this range.
    uint32_t        start;      // Bytecode offset at which this scope starts,
                                // from script->main().
    uint32_t        length;     // Bytecode length of scope.
    uint32_t        parent;     // Index of parent block scope in notes, or UINT32_MAX.
};

struct ConstArray {
    js::HeapValue*  vector;    /* array of indexed constant values */
    uint32_t        length;
};

struct ObjectArray {
    js::HeapPtrObject* vector;  // Array of indexed objects.
    uint32_t        length;     // Count of indexed objects.
};

struct TryNoteArray {
    JSTryNote*      vector;    // Array of indexed try notes.
    uint32_t        length;     // Count of indexed try notes.
};

struct BlockScopeArray {
    BlockScopeNote* vector;     // Array of indexed BlockScopeNote records.
    uint32_t        length;     // Count of indexed try notes.
};

class YieldOffsetArray {
    friend bool
    detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScript src,
                       HandleScript dst);

    uint32_t*       vector_;   // Array of bytecode offsets.
    uint32_t        length_;    // Count of bytecode offsets.

  public:
    void init(uint32_t* vector, uint32_t length) {
        vector_ = vector;
        length_ = length;
    }
    uint32_t& operator[](uint32_t index) {
        MOZ_ASSERT(index < length_);
        return vector_[index];
    }
    uint32_t length() const {
        return length_;
    }
};

class Binding : public JS::Traceable
{
    // One JSScript stores one Binding per formal/variable so we use a
    // packed-word representation.
    uintptr_t bits_;

    static const uintptr_t KIND_MASK = 0x3;
    static const uintptr_t ALIASED_BIT = 0x4;
    static const uintptr_t NAME_MASK = ~(KIND_MASK | ALIASED_BIT);

  public:
    // A "binding" is a formal parameter, 'var' (also a stand in for
    // body-level 'let' declarations), or 'const' declaration. A function's
    // lexical scope is composed of these three kinds of bindings.
    enum Kind { ARGUMENT, VARIABLE, CONSTANT };

    explicit Binding() : bits_(0) {}

    Binding(PropertyName* name, Kind kind, bool aliased) {
        JS_STATIC_ASSERT(CONSTANT <= KIND_MASK);
        MOZ_ASSERT((uintptr_t(name) & ~NAME_MASK) == 0);
        MOZ_ASSERT((uintptr_t(kind) & ~KIND_MASK) == 0);
        bits_ = uintptr_t(name) | uintptr_t(kind) | (aliased ? ALIASED_BIT : 0);
    }

    PropertyName* name() const {
        return (PropertyName*)(bits_ & NAME_MASK);
    }

    Kind kind() const {
        return Kind(bits_ & KIND_MASK);
    }

    bool aliased() const {
        return bool(bits_ & ALIASED_BIT);
    }

    static void trace(Binding* self, JSTracer* trc) { self->trace(trc); }
    void trace(JSTracer* trc);
};

JS_STATIC_ASSERT(sizeof(Binding) == sizeof(uintptr_t));

/*
 * Formal parameters and local variables are stored in a shape tree
 * path encapsulated within this class.  This class represents bindings for
 * both function and top-level scripts (the latter is needed to track names in
 * strict mode eval code, to give such code its own lexical environment).
 */
class Bindings : public JS::Traceable
{
    friend class BindingIter;
    friend class AliasedFormalIter;
    template <typename Outer> friend class BindingsOperations;
    template <typename Outer> friend class MutableBindingsOperations;

    RelocatablePtrShape callObjShape_;
    uintptr_t bindingArrayAndFlag_;
    uint16_t numArgs_;
    uint16_t numBlockScoped_;
    uint16_t numBodyLevelLexicals_;
    uint16_t numUnaliasedBodyLevelLexicals_;
    uint32_t aliasedBodyLevelLexicalBegin_;
    uint32_t numVars_;
    uint32_t numUnaliasedVars_;

#if JS_BITS_PER_WORD == 32
    // Bindings is allocated inline inside JSScript, which needs to be
    // gc::Cell aligned.
    uint32_t padding_;
#endif

    /*
     * During parsing, bindings are allocated out of a temporary LifoAlloc.
     * After parsing, a JSScript object is created and the bindings are
     * permanently transferred to it. On error paths, the JSScript object may
     * end up with bindings that still point to the (new released) LifoAlloc
     * memory. To avoid tracing these bindings during GC, we keep track of
     * whether the bindings are temporary or permanent in the low bit of
     * bindingArrayAndFlag_.
     */
    static const uintptr_t TEMPORARY_STORAGE_BIT = 0x1;
    bool bindingArrayUsingTemporaryStorage() const {
        return bindingArrayAndFlag_ & TEMPORARY_STORAGE_BIT;
    }

  public:

    Binding* bindingArray() const {
        return reinterpret_cast<Binding*>(bindingArrayAndFlag_ & ~TEMPORARY_STORAGE_BIT);
    }

    Bindings()
      : callObjShape_(nullptr), bindingArrayAndFlag_(TEMPORARY_STORAGE_BIT),
        numArgs_(0), numBlockScoped_(0),
        numBodyLevelLexicals_(0), numUnaliasedBodyLevelLexicals_(0),
        numVars_(0), numUnaliasedVars_(0)
    {}

    /*
     * Initialize a Bindings with a pointer into temporary storage.
     * bindingArray must have length numArgs + numVars +
     * numBodyLevelLexicals. Before the temporary storage is release,
     * switchToScriptStorage must be called, providing a pointer into the
     * Binding array stored in script->data.
     */
    static bool initWithTemporaryStorage(ExclusiveContext* cx, MutableHandle<Bindings> self,
                                         uint32_t numArgs,
                                         uint32_t numVars,
                                         uint32_t numBodyLevelLexicals,
                                         uint32_t numBlockScoped,
                                         uint32_t numUnaliasedVars,
                                         uint32_t numUnaliasedBodyLevelLexicals,
                                         const Binding* bindingArray,
                                         bool isModule = false);

    // Initialize a trivial Bindings with no slots and an empty callObjShape.
    bool initTrivial(ExclusiveContext* cx);

    // CompileScript parses and compiles one statement at a time, but the result
    // is one Script object.  There will be no vars or bindings, because those
    // go on the global, but there may be block-scoped locals, and the number of
    // block-scoped locals may increase as we parse more expressions.  This
    // helper updates the number of block scoped variables in a script as it is
    // being parsed.
    void updateNumBlockScoped(unsigned numBlockScoped) {
        MOZ_ASSERT(!callObjShape_);
        MOZ_ASSERT(numVars_ == 0);
        MOZ_ASSERT(numBlockScoped < LOCALNO_LIMIT);
        MOZ_ASSERT(numBlockScoped >= numBlockScoped_);
        numBlockScoped_ = numBlockScoped;
    }

    void setAllLocalsAliased() {
        numBlockScoped_ = 0;
    }

    uint8_t* switchToScriptStorage(Binding* newStorage);

    /*
     * Clone srcScript's bindings (as part of js::CloneScript). dstScriptData
     * is the pointer to what will eventually be dstScript->data.
     */
    static bool clone(JSContext* cx, MutableHandle<Bindings> self, uint8_t* dstScriptData,
                      HandleScript srcScript);

    uint32_t numArgs() const { return numArgs_; }
    uint32_t numVars() const { return numVars_; }
    uint32_t numBodyLevelLexicals() const { return numBodyLevelLexicals_; }
    uint32_t numBlockScoped() const { return numBlockScoped_; }
    uint32_t numBodyLevelLocals() const { return numVars_ + numBodyLevelLexicals_; }
    uint32_t numUnaliasedBodyLevelLocals() const { return numUnaliasedVars_ + numUnaliasedBodyLevelLexicals_; }
    uint32_t numAliasedBodyLevelLocals() const { return numBodyLevelLocals() - numUnaliasedBodyLevelLocals(); }
    uint32_t numLocals() const { return numVars() + numBodyLevelLexicals() + numBlockScoped(); }
    uint32_t numFixedLocals() const { return numUnaliasedVars() + numUnaliasedBodyLevelLexicals() + numBlockScoped(); }
    uint32_t lexicalBegin() const { return numArgs() + numVars(); }
    uint32_t aliasedBodyLevelLexicalBegin() const { return aliasedBodyLevelLexicalBegin_; }

    uint32_t numUnaliasedVars() const { return numUnaliasedVars_; }
    uint32_t numUnaliasedBodyLevelLexicals() const { return numUnaliasedBodyLevelLexicals_; }

    // Return the size of the bindingArray.
    uint32_t count() const { return numArgs() + numVars() + numBodyLevelLexicals(); }

    /* Return the initial shape of call objects created for this scope. */
    Shape* callObjShape() const { return callObjShape_; }

    /* Convenience method to get the var index of 'arguments' or 'this'. */
    static BindingIter argumentsBinding(ExclusiveContext* cx, HandleScript script);
    static BindingIter thisBinding(ExclusiveContext* cx, HandleScript script);

    /* Return whether the binding at bindingIndex is aliased. */
    bool bindingIsAliased(uint32_t bindingIndex);

    /* Return whether this scope has any aliased bindings. */
    bool hasAnyAliasedBindings() const {
        if (!callObjShape_)
            return false;

        return !callObjShape_->isEmptyShape();
    }

    Binding* begin() const { return bindingArray(); }
    Binding* end() const { return bindingArray() + count(); }

    static void trace(Bindings* self, JSTracer* trc) { self->trace(trc); }
    void trace(JSTracer* trc);
};

// If this fails, add/remove padding within Bindings.
static_assert(sizeof(Bindings) % js::gc::CellSize == 0,
              "Size of Bindings must be an integral multiple of js::gc::CellSize");

template <class Outer>
class BindingsOperations
{
    const Bindings& bindings() const { return static_cast<const Outer*>(this)->get(); }

  public:
    // Direct data access to the underlying bindings.
    const RelocatablePtrShape& callObjShape() const {
        return bindings().callObjShape_;
    }
    uint16_t numArgs() const {
        return bindings().numArgs_;
    }
    uint16_t numBlockScoped() const {
        return bindings().numBlockScoped_;
    }
    uint16_t numBodyLevelLexicals() const {
        return bindings().numBodyLevelLexicals_;
    }
    uint16_t aliasedBodyLevelLexicalBegin() const {
        return bindings().aliasedBodyLevelLexicalBegin_;
    }
    uint16_t numUnaliasedBodyLevelLexicals() const {
        return bindings().numUnaliasedBodyLevelLexicals_;
    }
    uint32_t numVars() const {
        return bindings().numVars_;
    }
    uint32_t numUnaliasedVars() const {
        return bindings().numUnaliasedVars_;
    }

    // Binding array access.
    bool bindingArrayUsingTemporaryStorage() const {
        return bindings().bindingArrayUsingTemporaryStorage();
    }
    const Binding* bindingArray() const {
        return bindings().bindingArray();
    }
    uint32_t count() const {
        return bindings().count();
    }

    // Helpers.
    uint32_t numBodyLevelLocals() const {
        return numVars() + numBodyLevelLexicals();
    }
    uint32_t numUnaliasedBodyLevelLocals() const {
        return numUnaliasedVars() + numUnaliasedBodyLevelLexicals();
    }
    uint32_t numAliasedBodyLevelLocals() const {
        return numBodyLevelLocals() - numUnaliasedBodyLevelLocals();
    }
    uint32_t numLocals() const {
        return numVars() + numBodyLevelLexicals() + numBlockScoped();
    }
    uint32_t numFixedLocals() const {
        return numUnaliasedVars() + numUnaliasedBodyLevelLexicals() + numBlockScoped();
    }
    uint32_t lexicalBegin() const {
        return numArgs() + numVars();
    }
};

template <class Outer>
class MutableBindingsOperations : public BindingsOperations<Outer>
{
    Bindings& bindings() { return static_cast<Outer*>(this)->get(); }

  public:
    void setCallObjShape(HandleShape shape) { bindings().callObjShape_ = shape; }
    void setBindingArray(const Binding* bindingArray, uintptr_t temporaryBit) {
        bindings().bindingArrayAndFlag_ = uintptr_t(bindingArray) | temporaryBit;
    }
    void setNumArgs(uint16_t num) { bindings().numArgs_ = num; }
    void setNumVars(uint32_t num) { bindings().numVars_ = num; }
    void setNumBodyLevelLexicals(uint16_t num) { bindings().numBodyLevelLexicals_ = num; }
    void setNumBlockScoped(uint16_t num) { bindings().numBlockScoped_ = num; }
    void setNumUnaliasedVars(uint32_t num) { bindings().numUnaliasedVars_ = num; }
    void setNumUnaliasedBodyLevelLexicals(uint16_t num) {
        bindings().numUnaliasedBodyLevelLexicals_ = num;
    }
    void setAliasedBodyLevelLexicalBegin(uint32_t offset) {
        bindings().aliasedBodyLevelLexicalBegin_ = offset;
    }
    uint8_t* switchToScriptStorage(Binding* permanentStorage) {
        return bindings().switchToScriptStorage(permanentStorage);
    }
};

template <>
class HandleBase<Bindings> : public BindingsOperations<JS::Handle<Bindings>>
{};

template <>
class MutableHandleBase<Bindings>
  : public MutableBindingsOperations<JS::MutableHandle<Bindings>>
{};

class ScriptCounts
{
  public:
    typedef mozilla::Vector<PCCounts, 0, SystemAllocPolicy> PCCountsVector;

    inline ScriptCounts();
    inline explicit ScriptCounts(PCCountsVector&& jumpTargets);
    inline ScriptCounts(ScriptCounts&& src);
    inline ~ScriptCounts();

    inline ScriptCounts& operator=(ScriptCounts&& src);

    // Return the counter used to count the number of visits. Returns null if
    // the element is not found.
    PCCounts* maybeGetPCCounts(size_t offset);
    const PCCounts* maybeGetPCCounts(size_t offset) const;

    // PCCounts are stored at jump-target offsets. This function looks for the
    // previous PCCount which is in the same basic block as the current offset.
    PCCounts* getImmediatePrecedingPCCounts(size_t offset);

    // Return the counter used to count the number of throws. Returns null if
    // the element is not found.
    const PCCounts* maybeGetThrowCounts(size_t offset) const;

    // Throw counts are stored at the location of each throwing
    // instruction. This function looks for the previous throw count.
    //
    // Note: if the offset of the returned count is higher than the offset of
    // the immediate preceding PCCount, then this throw happened in the same
    // basic block.
    const PCCounts* getImmediatePrecedingThrowCounts(size_t offset) const;

    // Return the counter used to count the number of throws. Allocate it if
    // none exists yet. Returns null if the allocation failed.
    PCCounts* getThrowCounts(size_t offset);

  private:
    friend class ::JSScript;
    friend struct ScriptAndCounts;

    // This sorted array is used to map an offset to the number of times a
    // branch got visited.
    PCCountsVector pcCounts_;

    // This sorted vector is used to map an offset to the number of times an
    // instruction throw.
    PCCountsVector throwCounts_;

    // Information about any Ion compilations for the script.
    jit::IonScriptCounts* ionCounts_;
};

// Note: The key of this hash map is a weak reference to a JSScript.  We do not
// use the WeakMap implementation provided in jsweakmap.h because it would be
// collected at the beginning of the sweeping of the compartment, thus before
// the calls to the JSScript::finalize function which are used to aggregate code
// coverage results on the compartment.
typedef HashMap<JSScript*,
                ScriptCounts,
                DefaultHasher<JSScript*>,
                SystemAllocPolicy> ScriptCountsMap;

class DebugScript
{
    friend class ::JSScript;

    /*
     * When non-zero, compile script in single-step mode. The top bit is set and
     * cleared by setStepMode, as used by JSD. The lower bits are a count,
     * adjusted by changeStepModeCount, used by the Debugger object. Only
     * when the bit is clear and the count is zero may we compile the script
     * without single-step support.
     */
    uint32_t        stepMode;

    /*
     * Number of breakpoint sites at opcodes in the script. This is the number
     * of populated entries in DebugScript::breakpoints, below.
     */
    uint32_t        numSites;

    /*
     * Breakpoints set in our script. For speed and simplicity, this array is
     * parallel to script->code(): the BreakpointSite for the opcode at
     * script->code()[offset] is debugScript->breakpoints[offset]. Naturally,
     * this array's true length is script->length().
     */
    BreakpointSite* breakpoints[1];
};

typedef HashMap<JSScript*,
                DebugScript*,
                DefaultHasher<JSScript*>,
                SystemAllocPolicy> DebugScriptMap;

class ScriptSource;

class UncompressedSourceCache
{
    typedef HashMap<ScriptSource*,
                    const char16_t*,
                    DefaultHasher<ScriptSource*>,
                    SystemAllocPolicy> Map;

  public:
    // Hold an entry in the source data cache and prevent it from being purged on GC.
    class AutoHoldEntry
    {
        UncompressedSourceCache* cache_;
        ScriptSource* source_;
        const char16_t* charsToFree_;
      public:
        explicit AutoHoldEntry();
        ~AutoHoldEntry();
      private:
        void holdEntry(UncompressedSourceCache* cache, ScriptSource* source);
        void deferDelete(const char16_t* chars);
        ScriptSource* source() const { return source_; }
        friend class UncompressedSourceCache;
    };

  private:
    Map* map_;
    AutoHoldEntry* holder_;

  public:
    UncompressedSourceCache() : map_(nullptr), holder_(nullptr) {}

    const char16_t* lookup(ScriptSource* ss, AutoHoldEntry& asp);
    bool put(ScriptSource* ss, const char16_t* chars, AutoHoldEntry& asp);

    void purge();

    size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);

  private:
    void holdEntry(AutoHoldEntry& holder, ScriptSource* ss);
    void releaseEntry(AutoHoldEntry& holder);
};

class ScriptSource
{
    friend struct SourceCompressionTask;

    uint32_t refs;

    // Note: while ScriptSources may be compressed off thread, they are only
    // modified by the main thread, and all members are always safe to access
    // on the main thread.

    // Indicate which field in the |data| union is active.
    enum {
        DataMissing,
        DataUncompressed,
        DataCompressed,
        DataParent
    } dataType;

    union {
        struct {
            const char16_t* chars;
            bool ownsChars;
        } uncompressed;

        struct {
            void* raw;
            size_t nbytes;
            HashNumber hash;
        } compressed;

        ScriptSource* parent;
    } data;

    uint32_t length_;

    // The filename of this script.
    mozilla::UniquePtr<char[], JS::FreePolicy> filename_;

    mozilla::UniquePtr<char16_t[], JS::FreePolicy> displayURL_;
    mozilla::UniquePtr<char16_t[], JS::FreePolicy> sourceMapURL_;
    bool mutedErrors_;

    // bytecode offset in caller script that generated this code.
    // This is present for eval-ed code, as well as "new Function(...)"-introduced
    // scripts.
    uint32_t introductionOffset_;

    // If this ScriptSource was generated by a code-introduction mechanism such
    // as |eval| or |new Function|, the debugger needs access to the "raw"
    // filename of the top-level script that contains the eval-ing code.  To
    // keep track of this, we must preserve the original outermost filename (of
    // the original introducer script), so that instead of a filename of
    // "foo.js line 30 > eval line 10 > Function", we can obtain the original
    // raw filename of "foo.js".
    //
    // In the case described above, this field will be non-null and will be the
    // original raw filename from above.  Otherwise this field will be null.
    mozilla::UniquePtr<char[], JS::FreePolicy> introducerFilename_;

    // A string indicating how this source code was introduced into the system.
    // This accessor returns one of the following values:
    //      "eval" for code passed to |eval|.
    //      "Function" for code passed to the |Function| constructor.
    //      "Worker" for code loaded by calling the Web worker constructor&mdash;the worker's main script.
    //      "importScripts" for code by calling |importScripts| in a web worker.
    //      "handler" for code assigned to DOM elements' event handler IDL attributes.
    //      "scriptElement" for code belonging to <script> elements.
    //      undefined if the implementation doesn't know how the code was introduced.
    // This is a constant, statically allocated C string, so does not need
    // memory management.
    const char* introductionType_;

    // True if we can call JSRuntime::sourceHook to load the source on
    // demand. If sourceRetrievable_ and hasSourceData() are false, it is not
    // possible to get source at all.
    bool sourceRetrievable_:1;
    bool argumentsNotIncluded_:1;
    bool hasIntroductionOffset_:1;

    // Whether this is in the runtime's set of compressed ScriptSources.
    bool inCompressedSourceSet:1;

  public:
    explicit ScriptSource()
      : refs(0),
        dataType(DataMissing),
        length_(0),
        filename_(nullptr),
        displayURL_(nullptr),
        sourceMapURL_(nullptr),
        mutedErrors_(false),
        introductionOffset_(0),
        introducerFilename_(nullptr),
        introductionType_(nullptr),
        sourceRetrievable_(false),
        argumentsNotIncluded_(false),
        hasIntroductionOffset_(false),
        inCompressedSourceSet(false)
    {
    }
    ~ScriptSource();
    void incref() { refs++; }
    void decref() {
        MOZ_ASSERT(refs != 0);
        if (--refs == 0)
            js_delete(this);
    }
    bool initFromOptions(ExclusiveContext* cx, const ReadOnlyCompileOptions& options);
    bool setSourceCopy(ExclusiveContext* cx,
                       JS::SourceBufferHolder& srcBuf,
                       bool argumentsNotIncluded,
                       SourceCompressionTask* tok);
    void setSourceRetrievable() { sourceRetrievable_ = true; }
    bool sourceRetrievable() const { return sourceRetrievable_; }
    bool hasSourceData() const { return dataType != DataMissing; }
    bool hasCompressedSource() const { return dataType == DataCompressed; }
    size_t length() const {
        MOZ_ASSERT(hasSourceData());
        return length_;
    }
    bool argumentsNotIncluded() const {
        MOZ_ASSERT(hasSourceData());
        return argumentsNotIncluded_;
    }
    const char16_t* chars(JSContext* cx, UncompressedSourceCache::AutoHoldEntry& asp);
    JSFlatString* substring(JSContext* cx, uint32_t start, uint32_t stop);
    JSFlatString* substringDontDeflate(JSContext* cx, uint32_t start, uint32_t stop);
    void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
                                JS::ScriptSourceInfo* info) const;

    const char16_t* uncompressedChars() const {
        MOZ_ASSERT(dataType == DataUncompressed);
        return data.uncompressed.chars;
    }

    bool ownsUncompressedChars() const {
        MOZ_ASSERT(dataType == DataUncompressed);
        return data.uncompressed.ownsChars;
    }

    void* compressedData() const {
        MOZ_ASSERT(dataType == DataCompressed);
        return data.compressed.raw;
    }

    size_t compressedBytes() const {
        MOZ_ASSERT(dataType == DataCompressed);
        return data.compressed.nbytes;
    }

    HashNumber compressedHash() const {
        MOZ_ASSERT(dataType == DataCompressed);
        return data.compressed.hash;
    }

    ScriptSource* parent() const {
        MOZ_ASSERT(dataType == DataParent);
        return data.parent;
    }

    void setSource(const char16_t* chars, size_t length, bool ownsChars = true);
    void setCompressedSource(JSRuntime* maybert, void* raw, size_t nbytes, HashNumber hash);
    void updateCompressedSourceSet(JSRuntime* rt);
    bool ensureOwnsSource(ExclusiveContext* cx);

    // XDR handling
    template <XDRMode mode>
    bool performXDR(XDRState<mode>* xdr);

    bool setFilename(ExclusiveContext* cx, const char* filename);
    const char* introducerFilename() const {
        return introducerFilename_ ? introducerFilename_.get() : filename_.get();
    }
    bool hasIntroductionType() const {
        return introductionType_;
    }
    const char* introductionType() const {
        MOZ_ASSERT(hasIntroductionType());
        return introductionType_;
    }
    const char* filename() const {
        return filename_.get();
    }

    // Display URLs
    bool setDisplayURL(ExclusiveContext* cx, const char16_t* displayURL);
    bool hasDisplayURL() const { return displayURL_ != nullptr; }
    const char16_t * displayURL() {
        MOZ_ASSERT(hasDisplayURL());
        return displayURL_.get();
    }

    // Source maps
    bool setSourceMapURL(ExclusiveContext* cx, const char16_t* sourceMapURL);
    bool hasSourceMapURL() const { return sourceMapURL_ != nullptr; }
    const char16_t * sourceMapURL() {
        MOZ_ASSERT(hasSourceMapURL());
        return sourceMapURL_.get();
    }

    bool mutedErrors() const { return mutedErrors_; }

    bool hasIntroductionOffset() const { return hasIntroductionOffset_; }
    uint32_t introductionOffset() const {
        MOZ_ASSERT(hasIntroductionOffset());
        return introductionOffset_;
    }
    void setIntroductionOffset(uint32_t offset) {
        MOZ_ASSERT(!hasIntroductionOffset());
        MOZ_ASSERT(offset <= (uint32_t)INT32_MAX);
        introductionOffset_ = offset;
        hasIntroductionOffset_ = true;
    }

  private:
    size_t computedSizeOfData() const;
};

class ScriptSourceHolder
{
    ScriptSource* ss;
  public:
    explicit ScriptSourceHolder(ScriptSource* ss)
      : ss(ss)
    {
        ss->incref();
    }
    ~ScriptSourceHolder()
    {
        ss->decref();
    }
};

struct CompressedSourceHasher
{
    typedef ScriptSource* Lookup;

    static HashNumber computeHash(const void* data, size_t nbytes) {
        return mozilla::HashBytes(data, nbytes);
    }

    static HashNumber hash(const ScriptSource* ss) {
        return ss->compressedHash();
    }

    static bool match(const ScriptSource* a, const ScriptSource* b) {
        return a->compressedBytes() == b->compressedBytes() &&
               a->compressedHash() == b->compressedHash() &&
               !memcmp(a->compressedData(), b->compressedData(), a->compressedBytes());
    }
};

typedef HashSet<ScriptSource*, CompressedSourceHasher, SystemAllocPolicy> CompressedSourceSet;

class ScriptSourceObject : public NativeObject
{
  public:
    static const Class class_;

    static void trace(JSTracer* trc, JSObject* obj);
    static void finalize(FreeOp* fop, JSObject* obj);
    static ScriptSourceObject* create(ExclusiveContext* cx, ScriptSource* source);

    // Initialize those properties of this ScriptSourceObject whose values
    // are provided by |options|, re-wrapping as necessary.
    static bool initFromOptions(JSContext* cx, HandleScriptSource source,
                                const ReadOnlyCompileOptions& options);

    ScriptSource* source() const {
        return static_cast<ScriptSource*>(getReservedSlot(SOURCE_SLOT).toPrivate());
    }
    JSObject* element() const {
        return getReservedSlot(ELEMENT_SLOT).toObjectOrNull();
    }
    const Value& elementAttributeName() const {
        MOZ_ASSERT(!getReservedSlot(ELEMENT_PROPERTY_SLOT).isMagic());
        return getReservedSlot(ELEMENT_PROPERTY_SLOT);
    }
    JSScript* introductionScript() const {
        if (getReservedSlot(INTRODUCTION_SCRIPT_SLOT).isUndefined())
            return nullptr;
        void* untyped = getReservedSlot(INTRODUCTION_SCRIPT_SLOT).toPrivate();
        MOZ_ASSERT(untyped);
        return static_cast<JSScript*>(untyped);
    }

  private:
    static const uint32_t SOURCE_SLOT = 0;
    static const uint32_t ELEMENT_SLOT = 1;
    static const uint32_t ELEMENT_PROPERTY_SLOT = 2;
    static const uint32_t INTRODUCTION_SCRIPT_SLOT = 3;
    static const uint32_t RESERVED_SLOTS = 4;
};

enum GeneratorKind { NotGenerator, LegacyGenerator, StarGenerator };

static inline unsigned
GeneratorKindAsBits(GeneratorKind generatorKind) {
    return static_cast<unsigned>(generatorKind);
}

static inline GeneratorKind
GeneratorKindFromBits(unsigned val) {
    MOZ_ASSERT(val <= StarGenerator);
    return static_cast<GeneratorKind>(val);
}

/*
 * NB: after a successful XDR_DECODE, XDRScript callers must do any required
 * subsequent set-up of owning function or script object and then call
 * CallNewScriptHook.
 */
template<XDRMode mode>
bool
XDRScript(XDRState<mode>* xdr, HandleObject enclosingScope, HandleScript enclosingScript,
          HandleFunction fun, MutableHandleScript scriptp);

template<XDRMode mode>
bool
XDRLazyScript(XDRState<mode>* xdr, HandleObject enclosingScope, HandleScript enclosingScript,
              HandleFunction fun, MutableHandle<LazyScript*> lazy);

/*
 * Code any constant value.
 */
template<XDRMode mode>
bool
XDRScriptConst(XDRState<mode>* xdr, MutableHandleValue vp);

} /* namespace js */

class JSScript : public js::gc::TenuredCell
{
    template <js::XDRMode mode>
    friend
    bool
    js::XDRScript(js::XDRState<mode>* xdr, js::HandleObject enclosingScope,
                  js::HandleScript enclosingScript,
                  js::HandleFunction fun, js::MutableHandleScript scriptp);

    friend bool
    js::detail::CopyScript(JSContext* cx, js::HandleObject scriptStaticScope, js::HandleScript src,
                           js::HandleScript dst);

  public:
    //
    // We order fields according to their size in order to avoid wasting space
    // for alignment.
    //

    // Larger-than-word-sized fields.

  public:
    js::Bindings    bindings;   /* names of top-level variables in this script
                                   (and arguments if this is a function script) */

    bool hasAnyAliasedBindings() const {
        return bindings.hasAnyAliasedBindings();
    }

    js::Binding* bindingArray() const {
        return bindings.bindingArray();
    }

    unsigned numArgs() const {
        return bindings.numArgs();
    }

    js::Shape* callObjShape() const {
        return bindings.callObjShape();
    }

    // Word-sized fields.

  private:
    jsbytecode*     code_;     /* bytecodes and their immediate operands */
  public:
    uint8_t*        data;      /* pointer to variable-length data array (see
                                   comment above Create() for details) */

    js::HeapPtrAtom* atoms;     /* maps immediate index to literal struct */

    JSCompartment*  compartment_;

  private:
    /* Persistent type information retained across GCs. */
    js::TypeScript* types_;

    // This script's ScriptSourceObject, or a CCW thereof.
    //
    // (When we clone a JSScript into a new compartment, we don't clone its
    // source object. Instead, the clone refers to a wrapper.)
    js::HeapPtrObject sourceObject_;

    js::HeapPtrFunction function_;
    js::HeapPtr<js::ModuleObject*> module_;
    js::HeapPtrObject   enclosingStaticScope_;

    /*
     * Information attached by Ion. Nexto a valid IonScript this could be
     * ION_DISABLED_SCRIPT, ION_COMPILING_SCRIPT or ION_PENDING_SCRIPT.
     * The later is a ion compilation that is ready, but hasn't been linked
     * yet.
     */
    js::jit::IonScript* ion;

    /* Information attached by Baseline. */
    js::jit::BaselineScript* baseline;

    /* Information used to re-lazify a lazily-parsed interpreted function. */
    js::LazyScript* lazyScript;

    /*
     * Pointer to either baseline->method()->raw() or ion->method()->raw(), or
     * nullptr if there's no Baseline or Ion script.
     */
    uint8_t* baselineOrIonRaw;
    uint8_t* baselineOrIonSkipArgCheck;

    // 32-bit fields.

    uint32_t        length_;    /* length of code vector */
    uint32_t        dataSize_;  /* size of the used part of the data array */

    uint32_t        lineno_;    /* base line number of script */
    uint32_t        column_;    /* base column of script, optionally set */

    uint32_t        mainOffset_;/* offset of main entry point from code, after
                                   predef'ing prologue */

    uint32_t        natoms_;    /* length of atoms array */
    uint32_t        nslots_;    /* vars plus maximum stack depth */

    /* Range of characters in scriptSource which contains this script's source. */
    uint32_t        sourceStart_;
    uint32_t        sourceEnd_;

    uint32_t        warmUpCount; /* Number of times the script has been called
                                  * or has had backedges taken. When running in
                                  * ion, also increased for any inlined scripts.
                                  * Reset if the script's JIT code is forcibly
                                  * discarded. */

    // 16-bit fields.

    uint16_t        warmUpResetCount; /* Number of times the |warmUpCount| was
                                 * forcibly discarded. The counter is reset when
                                 * a script is successfully jit-compiled. */

    uint16_t        version;    /* JS version under which script was compiled */

    uint16_t        funLength_; /* ES6 function length */

    uint16_t        nTypeSets_; /* number of type sets used in this script for
                                   dynamic type monitoring */

    // Bit fields.

  public:
    // The kinds of the optional arrays.
    enum ArrayKind {
        CONSTS,
        OBJECTS,
        REGEXPS,
        TRYNOTES,
        BLOCK_SCOPES,
        ARRAY_KIND_BITS
    };

  private:
    // The bits in this field indicate the presence/non-presence of several
    // optional arrays in |data|.  See the comments above Create() for details.
    uint8_t         hasArrayBits:ARRAY_KIND_BITS;

    // The GeneratorKind of the script.
    uint8_t         generatorKindBits_:2;

    // 1-bit fields.

    // No need for result value of last expression statement.
    bool noScriptRval_:1;

    // Can call getCallerFunction().
    bool savedCallerFun_:1;

    // Code is in strict mode.
    bool strict_:1;

    // Code has "use strict"; explicitly.
    bool explicitUseStrict_:1;

    // True if the script has a non-syntactic scope on its dynamic scope chain.
    // That is, there are objects about which we know nothing between the
    // outermost syntactic scope and the global.
    bool hasNonSyntacticScope_:1;

    // see Parser::selfHostingMode.
    bool selfHosted_:1;

    // See FunctionContextFlags.
    bool bindingsAccessedDynamically_:1;
    bool funHasExtensibleScope_:1;
    bool funNeedsDeclEnvObject_:1;

    // True if any formalIsAliased(i).
    bool funHasAnyAliasedFormal_:1;

    // Have warned about uses of undefined properties in this script.
    bool warnedAboutUndefinedProp_:1;

    // Script has singleton objects.
    bool hasSingletons_:1;

    // Script is a lambda to treat as running once or a global or eval script
    // that will only run once.  Which one it is can be disambiguated by
    // checking whether function_ is null.
    bool treatAsRunOnce_:1;

    // If treatAsRunOnce, whether script has executed.
    bool hasRunOnce_:1;

    // Script has been reused for a clone.
    bool hasBeenCloned_:1;

    // Script came from eval(), and is still active.
    bool isActiveEval_:1;

    // Script came from eval(), and is in eval cache.
    bool isCachedEval_:1;

    // 'this', 'arguments' and f.apply() are used. This is likely to be a wrapper.
    bool isLikelyConstructorWrapper_:1;

    // IonMonkey compilation hints.
    bool failedBoundsCheck_:1; /* script has had hoisted bounds checks fail */
    bool failedShapeGuard_:1; /* script has had hoisted shape guard fail */
    bool hadFrequentBailouts_:1;
    bool uninlineable_:1;    /* explicitly marked as uninlineable */

    // Idempotent cache has triggered invalidation.
    bool invalidatedIdempotentCache_:1;

    // Lexical check did fail and bail out.
    bool failedLexicalCheck_:1;

    // If the generator was created implicitly via a generator expression,
    // isGeneratorExp will be true.
    bool isGeneratorExp_:1;

    // Script has an entry in JSCompartment::scriptCountsMap.
    bool hasScriptCounts_:1;

    // Script has an entry in JSCompartment::debugScriptMap.
    bool hasDebugScript_:1;

    // Freeze constraints for stack type sets have been generated.
    bool hasFreezeConstraints_:1;

    /* See comments below. */
    bool argsHasVarBinding_:1;
    bool needsArgsAnalysis_:1;
    bool needsArgsObj_:1;
    bool functionHasThisBinding_:1;

    // Whether the arguments object for this script, if it needs one, should be
    // mapped (alias formal parameters).
    bool hasMappedArgsObj_:1;

    // Generation for this script's TypeScript. If out of sync with the
    // TypeZone's generation, the TypeScript needs to be swept.
    //
    // This should be a uint32 but is instead a bool so that MSVC packs it
    // correctly.
    bool typesGeneration_:1;

    // Do not relazify this script. This is used by the relazify() testing
    // function for scripts that are on the stack and also by the AutoDelazify
    // RAII class. Usually we don't relazify functions in compartments with
    // scripts on the stack, but the relazify() testing function overrides that,
    // and sometimes we're working with a cross-compartment function and need to
    // keep it from relazifying.
    bool doNotRelazify_:1;

    // Script contains inner functions. Used to check if we can relazify the
    // script.
    bool hasInnerFunctions_:1;

    bool needsHomeObject_:1;

    bool isDerivedClassConstructor_:1;

    // Add padding so JSScript is gc::Cell aligned. Make padding protected
    // instead of private to suppress -Wunused-private-field compiler warnings.
  protected:
#if JS_BITS_PER_WORD == 32
    // No padding currently required.
#endif

    //
    // End of fields.  Start methods.
    //

  public:
    static JSScript* Create(js::ExclusiveContext* cx,
                            js::HandleObject enclosingScope, bool savedCallerFun,
                            const JS::ReadOnlyCompileOptions& options,
                            js::HandleObject sourceObject, uint32_t sourceStart,
                            uint32_t sourceEnd);

    void initCompartment(js::ExclusiveContext* cx);

    // Three ways ways to initialize a JSScript. Callers of partiallyInit()
    // and fullyInitTrivial() are responsible for notifying the debugger after
    // successfully creating any kind (function or other) of new JSScript.
    // However, callers of fullyInitFromEmitter() do not need to do this.
    static bool partiallyInit(js::ExclusiveContext* cx, JS::Handle<JSScript*> script,
                              uint32_t nconsts, uint32_t nobjects, uint32_t nregexps,
                              uint32_t ntrynotes, uint32_t nblockscopes, uint32_t nyieldoffsets,
                              uint32_t nTypeSets);
    static bool fullyInitFromEmitter(js::ExclusiveContext* cx, JS::Handle<JSScript*> script,
                                     js::frontend::BytecodeEmitter* bce);
    static void linkToFunctionFromEmitter(js::ExclusiveContext* cx, JS::Handle<JSScript*> script,
                                          js::frontend::FunctionBox* funbox);
    static void linkToModuleFromEmitter(js::ExclusiveContext* cx, JS::Handle<JSScript*> script,
                                        js::frontend::ModuleBox* funbox);
    // Initialize a no-op script.
    static bool fullyInitTrivial(js::ExclusiveContext* cx, JS::Handle<JSScript*> script);

    inline JSPrincipals* principals();

    JSCompartment* compartment() const { return compartment_; }
    JSCompartment* maybeCompartment() const { return compartment(); }

    void setVersion(JSVersion v) { version = v; }

    // Script bytecode is immutable after creation.
    jsbytecode* code() const {
        return code_;
    }
    size_t length() const {
        return length_;
    }

    void setCode(jsbytecode* code) { code_ = code; }
    void setLength(size_t length) { length_ = length; }

    jsbytecode* codeEnd() const { return code() + length(); }

    jsbytecode* lastPC() const {
        jsbytecode* pc = codeEnd() - js::JSOP_RETRVAL_LENGTH;
        MOZ_ASSERT(*pc == JSOP_RETRVAL);
        return pc;
    }

    bool containsPC(const jsbytecode* pc) const {
        return pc >= code() && pc < codeEnd();
    }

    size_t pcToOffset(const jsbytecode* pc) const {
        MOZ_ASSERT(containsPC(pc));
        return size_t(pc - code());
    }

    jsbytecode* offsetToPC(size_t offset) const {
        MOZ_ASSERT(offset < length());
        return code() + offset;
    }

    size_t mainOffset() const {
        return mainOffset_;
    }

    size_t lineno() const {
        return lineno_;
    }

    size_t column() const {
        return column_;
    }

    void setColumn(size_t column) { column_ = column; }

    // The fixed part of a stack frame is comprised of vars (in function code)
    // and block-scoped locals (in all kinds of code).
    size_t nfixed() const {
        return function_ ? bindings.numFixedLocals() : bindings.numBlockScoped();
    }

    // Number of fixed slots reserved for vars.  Only nonzero for function
    // code.
    size_t nfixedvars() const {
        return function_ ? bindings.numUnaliasedVars() : 0;
    }

    // Number of fixed slots reserved for body-level lexicals and vars. This
    // value minus nfixedvars() is the number of body-level lexicals. Only
    // nonzero for function code.
    size_t nbodyfixed() const {
        return function_ ? bindings.numUnaliasedBodyLevelLocals() : 0;
    }

    // Calculate the number of fixed slots that are live at a particular bytecode.
    size_t calculateLiveFixed(jsbytecode* pc);

    // Aliases for clarity when dealing with lexical slots.
    size_t fixedLexicalBegin() const {
        return nfixedvars();
    }

    size_t fixedLexicalEnd() const {
        return nfixed();
    }

    size_t nslots() const {
        return nslots_;
    }

    size_t nTypeSets() const {
        return nTypeSets_;
    }

    size_t funLength() const {
        return funLength_;
    }

    size_t sourceStart() const {
        return sourceStart_;
    }

    size_t sourceEnd() const {
        return sourceEnd_;
    }

    bool noScriptRval() const {
        return noScriptRval_;
    }

    bool savedCallerFun() const { return savedCallerFun_; }

    bool strict() const {
        return strict_;
    }

    bool explicitUseStrict() const { return explicitUseStrict_; }

    bool hasNonSyntacticScope() const {
        return hasNonSyntacticScope_;
    }

    bool selfHosted() const { return selfHosted_; }
    bool bindingsAccessedDynamically() const { return bindingsAccessedDynamically_; }
    bool funHasExtensibleScope() const {
        return funHasExtensibleScope_;
    }
    bool funNeedsDeclEnvObject() const {
        return funNeedsDeclEnvObject_;
    }
    bool funHasAnyAliasedFormal() const {
        return funHasAnyAliasedFormal_;
    }

    bool hasSingletons() const { return hasSingletons_; }
    bool treatAsRunOnce() const {
        return treatAsRunOnce_;
    }
    bool hasRunOnce() const { return hasRunOnce_; }
    bool hasBeenCloned() const { return hasBeenCloned_; }

    void setTreatAsRunOnce() { treatAsRunOnce_ = true; }
    void setHasRunOnce() { hasRunOnce_ = true; }
    void setHasBeenCloned() { hasBeenCloned_ = true; }

    bool isActiveEval() const { return isActiveEval_; }
    bool isCachedEval() const { return isCachedEval_; }

    void cacheForEval() {
        MOZ_ASSERT(isActiveEval() && !isCachedEval());
        isActiveEval_ = false;
        isCachedEval_ = true;
        // IsEvalCacheCandidate will make sure that there's nothing in this
        // script that would prevent reexecution even if isRunOnce is
        // true.  So just pretend like we never ran this script.
        hasRunOnce_ = false;
    }

    void uncacheForEval() {
        MOZ_ASSERT(isCachedEval() && !isActiveEval());
        isCachedEval_ = false;
        isActiveEval_ = true;
    }

    void setActiveEval() { isActiveEval_ = true; }

    bool isLikelyConstructorWrapper() const {
        return isLikelyConstructorWrapper_;
    }
    void setLikelyConstructorWrapper() { isLikelyConstructorWrapper_ = true; }

    bool isGeneratorExp() const { return isGeneratorExp_; }

    bool failedBoundsCheck() const {
        return failedBoundsCheck_;
    }
    bool failedShapeGuard() const {
        return failedShapeGuard_;
    }
    bool hadFrequentBailouts() const {
        return hadFrequentBailouts_;
    }
    bool uninlineable() const {
        return uninlineable_;
    }
    bool invalidatedIdempotentCache() const {
        return invalidatedIdempotentCache_;
    }
    bool failedLexicalCheck() const {
        return failedLexicalCheck_;
    }

    void setFailedBoundsCheck() { failedBoundsCheck_ = true; }
    void setFailedShapeGuard() { failedShapeGuard_ = true; }
    void setHadFrequentBailouts() { hadFrequentBailouts_ = true; }
    void setUninlineable() { uninlineable_ = true; }
    void setInvalidatedIdempotentCache() { invalidatedIdempotentCache_ = true; }
    void setFailedLexicalCheck() { failedLexicalCheck_ = true; }

    bool hasScriptCounts() const { return hasScriptCounts_; }

    bool hasFreezeConstraints() const { return hasFreezeConstraints_; }
    void setHasFreezeConstraints() { hasFreezeConstraints_ = true; }

    bool warnedAboutUndefinedProp() const { return warnedAboutUndefinedProp_; }
    void setWarnedAboutUndefinedProp() { warnedAboutUndefinedProp_ = true; }

    /* See ContextFlags::funArgumentsHasLocalBinding comment. */
    bool argumentsHasVarBinding() const {
        return argsHasVarBinding_;
    }
    jsbytecode* argumentsBytecode() const { MOZ_ASSERT(code()[0] == JSOP_ARGUMENTS); return code(); }
    void setArgumentsHasVarBinding();
    bool argumentsAliasesFormals() const {
        return argumentsHasVarBinding() && hasMappedArgsObj();
    }

    js::GeneratorKind generatorKind() const {
        return js::GeneratorKindFromBits(generatorKindBits_);
    }
    bool isGenerator() const { return generatorKind() != js::NotGenerator; }
    bool isLegacyGenerator() const { return generatorKind() == js::LegacyGenerator; }
    bool isStarGenerator() const { return generatorKind() == js::StarGenerator; }
    void setGeneratorKind(js::GeneratorKind kind) {
        // A script only gets its generator kind set as part of initialization,
        // so it can only transition from not being a generator.
        MOZ_ASSERT(!isGenerator());
        generatorKindBits_ = GeneratorKindAsBits(kind);
    }

    void setNeedsHomeObject() {
        needsHomeObject_ = true;
    }
    bool needsHomeObject() const {
        return needsHomeObject_;
    }

    bool isDerivedClassConstructor() const {
        return isDerivedClassConstructor_;
    }

    /*
     * As an optimization, even when argsHasLocalBinding, the function prologue
     * may not need to create an arguments object. This is determined by
     * needsArgsObj which is set by AnalyzeArgumentsUsage. When !needsArgsObj,
     * the prologue may simply write MagicValue(JS_OPTIMIZED_ARGUMENTS) to
     * 'arguments's slot and any uses of 'arguments' will be guaranteed to
     * handle this magic value. To avoid spurious arguments object creation, we
     * maintain the invariant that needsArgsObj is only called after the script
     * has been analyzed.
     */
    bool analyzedArgsUsage() const { return !needsArgsAnalysis_; }
    inline bool ensureHasAnalyzedArgsUsage(JSContext* cx);
    bool needsArgsObj() const {
        MOZ_ASSERT(analyzedArgsUsage());
        return needsArgsObj_;
    }
    void setNeedsArgsObj(bool needsArgsObj);
    static bool argumentsOptimizationFailed(JSContext* cx, js::HandleScript script);

    bool hasMappedArgsObj() const {
        return hasMappedArgsObj_;
    }

    bool functionHasThisBinding() const {
        return functionHasThisBinding_;
    }

    /*
     * Arguments access (via JSOP_*ARG* opcodes) must access the canonical
     * location for the argument. If an arguments object exists AND it's mapped
     * ('arguments' aliases formals), then all access must go through the
     * arguments object. Otherwise, the local slot is the canonical location for
     * the arguments. Note: if a formal is aliased through the scope chain, then
     * script->formalIsAliased and JSOP_*ARG* opcodes won't be emitted at all.
     */
    bool argsObjAliasesFormals() const {
        return needsArgsObj() && hasMappedArgsObj();
    }

    uint32_t typesGeneration() const {
        return (uint32_t) typesGeneration_;
    }

    void setTypesGeneration(uint32_t generation) {
        MOZ_ASSERT(generation <= 1);
        typesGeneration_ = (bool) generation;
    }

    void setDoNotRelazify(bool b) {
        doNotRelazify_ = b;
    }

    void setHasInnerFunctions(bool b) {
        hasInnerFunctions_ = b;
    }

    bool hasInnerFunctions() const {
        return hasInnerFunctions_;
    }

    bool hasAnyIonScript() const {
        return hasIonScript();
    }

    bool hasIonScript() const {
        bool res = ion && ion != ION_DISABLED_SCRIPT && ion != ION_COMPILING_SCRIPT &&
                          ion != ION_PENDING_SCRIPT;
        MOZ_ASSERT_IF(res, baseline);
        return res;
    }
    bool canIonCompile() const {
        return ion != ION_DISABLED_SCRIPT;
    }
    bool isIonCompilingOffThread() const {
        return ion == ION_COMPILING_SCRIPT;
    }

    js::jit::IonScript* ionScript() const {
        MOZ_ASSERT(hasIonScript());
        return ion;
    }
    js::jit::IonScript* maybeIonScript() const {
        return ion;
    }
    js::jit::IonScript* const* addressOfIonScript() const {
        return &ion;
    }
    void setIonScript(JSContext* maybecx, js::jit::IonScript* ionScript);

    bool hasBaselineScript() const {
        bool res = baseline && baseline != BASELINE_DISABLED_SCRIPT;
        MOZ_ASSERT_IF(!res, !ion || ion == ION_DISABLED_SCRIPT);
        return res;
    }
    bool canBaselineCompile() const {
        return baseline != BASELINE_DISABLED_SCRIPT;
    }
    js::jit::BaselineScript* baselineScript() const {
        MOZ_ASSERT(hasBaselineScript());
        return baseline;
    }
    inline void setBaselineScript(JSContext* maybecx, js::jit::BaselineScript* baselineScript);

    void updateBaselineOrIonRaw(JSContext* maybecx);

    static size_t offsetOfBaselineScript() {
        return offsetof(JSScript, baseline);
    }
    static size_t offsetOfIonScript() {
        return offsetof(JSScript, ion);
    }
    static size_t offsetOfBaselineOrIonRaw() {
        return offsetof(JSScript, baselineOrIonRaw);
    }
    uint8_t* baselineOrIonRawPointer() const {
        return baselineOrIonRaw;
    }
    static size_t offsetOfBaselineOrIonSkipArgCheck() {
        return offsetof(JSScript, baselineOrIonSkipArgCheck);
    }

    bool isRelazifiable() const {
        return (selfHosted() || lazyScript) && !hasInnerFunctions_ && !types_ &&
               !isGenerator() && !hasBaselineScript() && !hasAnyIonScript() &&
               !hasScriptCounts() && !doNotRelazify_;
    }
    void setLazyScript(js::LazyScript* lazy) {
        lazyScript = lazy;
    }
    js::LazyScript* maybeLazyScript() {
        return lazyScript;
    }

    /*
     * Original compiled function for the script, if it has a function.
     * nullptr for global and eval scripts.
     * The delazifying variant ensures that the function isn't lazy. The
     * non-delazifying variant must only be used after earlier code has
     * called ensureNonLazyCanonicalFunction and while the function can't
     * have been relazified.
     */
    inline JSFunction* functionDelazifying() const;
    JSFunction* functionNonDelazifying() const {
        return function_;
    }
    inline void setFunction(JSFunction* fun);
    /*
     * De-lazifies the canonical function. Must be called before entering code
     * that expects the function to be non-lazy.
     */
    inline void ensureNonLazyCanonicalFunction(JSContext* cx);

    js::ModuleObject* module() const {
        return module_;
    }
    inline void setModule(js::ModuleObject* module);

    // Returns true if the script may read formal arguments on the stack
    // directly, via lazy arguments or a rest parameter.
    bool mayReadFrameArgsDirectly();

    JSFlatString* sourceData(JSContext* cx);

    static bool loadSource(JSContext* cx, js::ScriptSource* ss, bool* worked);

    void setSourceObject(JSObject* object);
    JSObject* sourceObject() const {
        return sourceObject_;
    }
    js::ScriptSourceObject& scriptSourceUnwrap() const;
    js::ScriptSource* scriptSource() const;
    js::ScriptSource* maybeForwardedScriptSource() const;
    bool mutedErrors() const { return scriptSource()->mutedErrors(); }
    const char* filename() const { return scriptSource()->filename(); }
    const char* maybeForwardedFilename() const { return maybeForwardedScriptSource()->filename(); }

  public:

    /* Return whether this script was compiled for 'eval' */
    bool isForEval() { return isCachedEval() || isActiveEval(); }

    /*
     * Return whether this script is a top-level script.
     *
     * If we evaluate some code which contains a syntax error, then we might
     * produce a JSScript which has no associated bytecode. Testing with
     * |code()| filters out this kind of scripts.
     *
     * If this script has a function associated to it, then it is not the
     * top-level of a file.
     */
    bool isTopLevel() { return code() && !functionNonDelazifying(); }

    /* Ensure the script has a TypeScript. */
    inline bool ensureHasTypes(JSContext* cx);

    inline js::TypeScript* types();

    void maybeSweepTypes(js::AutoClearTypeInferenceStateOnOOM* oom);

    inline js::GlobalObject& global() const;
    js::GlobalObject& uninlinedGlobal() const;

    /* See StaticScopeIter comment. */
    JSObject* enclosingStaticScope() const {
        return enclosingStaticScope_;
    }

    // Switch the script over from the off-thread compartment's static
    // global lexical scope to the main thread compartment's.
    void fixEnclosingStaticGlobalLexicalScope();

  private:
    bool makeTypes(JSContext* cx);

  public:
    uint32_t getWarmUpCount() const { return warmUpCount; }
    uint32_t incWarmUpCounter(uint32_t amount = 1) { return warmUpCount += amount; }
    uint32_t* addressOfWarmUpCounter() { return &warmUpCount; }
    static size_t offsetOfWarmUpCounter() { return offsetof(JSScript, warmUpCount); }
    void resetWarmUpCounter() { incWarmUpResetCounter(); warmUpCount = 0; }

    uint16_t getWarmUpResetCount() const { return warmUpResetCount; }
    uint16_t incWarmUpResetCounter(uint16_t amount = 1) { return warmUpResetCount += amount; }
    void resetWarmUpResetCounter() { warmUpResetCount = 0; }

  public:
    bool initScriptCounts(JSContext* cx);
    js::ScriptCounts& getScriptCounts();
    js::PCCounts* maybeGetPCCounts(jsbytecode* pc);
    const js::PCCounts* maybeGetThrowCounts(jsbytecode* pc);
    js::PCCounts* getThrowCounts(jsbytecode* pc);
    uint64_t getHitCount(jsbytecode* pc);
    void incHitCount(jsbytecode* pc); // Used when we bailout out of Ion.
    void addIonCounts(js::jit::IonScriptCounts* ionCounts);
    js::jit::IonScriptCounts* getIonCounts();
    void releaseScriptCounts(js::ScriptCounts* counts);
    void destroyScriptCounts(js::FreeOp* fop);
    // The entry should be removed after using this function.
    void takeOverScriptCountsMapEntry(js::ScriptCounts* entryValue);

    jsbytecode* main() {
        return code() + mainOffset();
    }

    /*
     * computedSizeOfData() is the in-use size of all the data sections.
     * sizeOfData() is the size of the block allocated to hold all the data
     * sections (which can be larger than the in-use size).
     */
    size_t computedSizeOfData() const;
    size_t sizeOfData(mozilla::MallocSizeOf mallocSizeOf) const;
    size_t sizeOfTypeScript(mozilla::MallocSizeOf mallocSizeOf) const;

    uint32_t numNotes();  /* Number of srcnote slots in the srcnotes section */

    /* Script notes are allocated right after the code. */
    jssrcnote* notes() { return (jssrcnote*)(code() + length()); }

    bool hasArray(ArrayKind kind) {
        return hasArrayBits & (1 << kind);
    }
    void setHasArray(ArrayKind kind) { hasArrayBits |= (1 << kind); }
    void cloneHasArray(JSScript* script) { hasArrayBits = script->hasArrayBits; }

    bool hasConsts()        { return hasArray(CONSTS);      }
    bool hasObjects()       { return hasArray(OBJECTS);     }
    bool hasRegexps()       { return hasArray(REGEXPS);     }
    bool hasTrynotes()      { return hasArray(TRYNOTES);    }
    bool hasBlockScopes()   { return hasArray(BLOCK_SCOPES); }
    bool hasYieldOffsets()  { return isGenerator(); }

    #define OFF(fooOff, hasFoo, t)   (fooOff() + (hasFoo() ? sizeof(t) : 0))

    size_t constsOffset()       { return 0; }
    size_t objectsOffset()      { return OFF(constsOffset,      hasConsts,      js::ConstArray);      }
    size_t regexpsOffset()      { return OFF(objectsOffset,     hasObjects,     js::ObjectArray);     }
    size_t trynotesOffset()     { return OFF(regexpsOffset,     hasRegexps,     js::ObjectArray);     }
    size_t blockScopesOffset()  { return OFF(trynotesOffset,    hasTrynotes,    js::TryNoteArray);    }
    size_t yieldOffsetsOffset() { return OFF(blockScopesOffset, hasBlockScopes, js::BlockScopeArray); }

    size_t dataSize() const { return dataSize_; }

    js::ConstArray* consts() {
        MOZ_ASSERT(hasConsts());
        return reinterpret_cast<js::ConstArray*>(data + constsOffset());
    }

    js::ObjectArray* objects() {
        MOZ_ASSERT(hasObjects());
        return reinterpret_cast<js::ObjectArray*>(data + objectsOffset());
    }

    js::ObjectArray* regexps() {
        MOZ_ASSERT(hasRegexps());
        return reinterpret_cast<js::ObjectArray*>(data + regexpsOffset());
    }

    js::TryNoteArray* trynotes() {
        MOZ_ASSERT(hasTrynotes());
        return reinterpret_cast<js::TryNoteArray*>(data + trynotesOffset());
    }

    js::BlockScopeArray* blockScopes() {
        MOZ_ASSERT(hasBlockScopes());
        return reinterpret_cast<js::BlockScopeArray*>(data + blockScopesOffset());
    }

    js::YieldOffsetArray& yieldOffsets() {
        MOZ_ASSERT(hasYieldOffsets());
        return *reinterpret_cast<js::YieldOffsetArray*>(data + yieldOffsetsOffset());
    }

    bool hasLoops();

    size_t natoms() const { return natoms_; }

    js::HeapPtrAtom& getAtom(size_t index) const {
        MOZ_ASSERT(index < natoms());
        return atoms[index];
    }

    js::HeapPtrAtom& getAtom(jsbytecode* pc) const {
        MOZ_ASSERT(containsPC(pc) && containsPC(pc + sizeof(uint32_t)));
        return getAtom(GET_UINT32_INDEX(pc));
    }

    js::PropertyName* getName(size_t index) {
        return getAtom(index)->asPropertyName();
    }

    js::PropertyName* getName(jsbytecode* pc) const {
        MOZ_ASSERT(containsPC(pc) && containsPC(pc + sizeof(uint32_t)));
        return getAtom(GET_UINT32_INDEX(pc))->asPropertyName();
    }

    JSObject* getObject(size_t index) {
        js::ObjectArray* arr = objects();
        MOZ_ASSERT(index < arr->length);
        MOZ_ASSERT(arr->vector[index]->isTenured());
        return arr->vector[index];
    }

    size_t innerObjectsStart() {
        // The first object contains the caller if savedCallerFun is used.
        return savedCallerFun() ? 1 : 0;
    }

    JSObject* getObject(jsbytecode* pc) {
        MOZ_ASSERT(containsPC(pc) && containsPC(pc + sizeof(uint32_t)));
        return getObject(GET_UINT32_INDEX(pc));
    }

    JSVersion getVersion() const {
        return JSVersion(version);
    }

    inline JSFunction* getFunction(size_t index);
    inline JSFunction* getCallerFunction();
    inline JSFunction* functionOrCallerFunction();

    inline js::RegExpObject* getRegExp(size_t index);
    inline js::RegExpObject* getRegExp(jsbytecode* pc);

    const js::Value& getConst(size_t index) {
        js::ConstArray* arr = consts();
        MOZ_ASSERT(index < arr->length);
        return arr->vector[index];
    }

    // The following 4 functions find the static scope just before the
    // execution of the instruction pointed to by pc.

    js::NestedScopeObject* getStaticBlockScope(jsbytecode* pc);

    // Returns the innermost static scope at pc if it falls within the extent
    // of the script. Returns nullptr otherwise.
    JSObject* innermostStaticScopeInScript(jsbytecode* pc);

    // As innermostStaticScopeInScript, but returns the enclosing static scope
    // if the innermost static scope falls without the extent of the script.
    JSObject* innermostStaticScope(jsbytecode* pc);

    JSObject* innermostStaticScope() { return innermostStaticScope(main()); }

    /*
     * The isEmpty method tells whether this script has code that computes any
     * result (not return value, result AKA normal completion value) other than
     * JSVAL_VOID, or any other effects.
     */
    bool isEmpty() const {
        if (length() > 3)
            return false;

        jsbytecode* pc = code();
        if (noScriptRval() && JSOp(*pc) == JSOP_FALSE)
            ++pc;
        return JSOp(*pc) == JSOP_RETRVAL;
    }

    bool bindingIsAliased(const js::BindingIter& bi);
    bool formalIsAliased(unsigned argSlot);
    bool formalLivesInArgumentsObject(unsigned argSlot);
    bool localIsAliased(unsigned localSlot);

  private:
    /* Change this->stepMode to |newValue|. */
    void setNewStepMode(js::FreeOp* fop, uint32_t newValue);

    bool ensureHasDebugScript(JSContext* cx);
    js::DebugScript* debugScript();
    js::DebugScript* releaseDebugScript();
    void destroyDebugScript(js::FreeOp* fop);

  public:
    bool hasBreakpointsAt(jsbytecode* pc);
    bool hasAnyBreakpointsOrStepMode() { return hasDebugScript_; }

    // See comment above 'debugMode' in jscompartment.h for explanation of
    // invariants of debuggee compartments, scripts, and frames.
    inline bool isDebuggee() const;

    js::BreakpointSite* getBreakpointSite(jsbytecode* pc)
    {
        return hasDebugScript_ ? debugScript()->breakpoints[pcToOffset(pc)] : nullptr;
    }

    js::BreakpointSite* getOrCreateBreakpointSite(JSContext* cx, jsbytecode* pc);

    void destroyBreakpointSite(js::FreeOp* fop, jsbytecode* pc);

    void clearBreakpointsIn(js::FreeOp* fop, js::Debugger* dbg, JSObject* handler);

    /*
     * Increment or decrement the single-step count. If the count is non-zero
     * then the script is in single-step mode.
     *
     * Only incrementing is fallible, as it could allocate a DebugScript.
     */
    bool incrementStepModeCount(JSContext* cx);
    void decrementStepModeCount(js::FreeOp* fop);

    bool stepModeEnabled() { return hasDebugScript_ && !!debugScript()->stepMode; }

#ifdef DEBUG
    uint32_t stepModeCount() { return hasDebugScript_ ? debugScript()->stepMode : 0; }
#endif

    void finalize(js::FreeOp* fop);
    void fixupAfterMovingGC() {}

    static inline js::ThingRootKind rootKind() { return js::THING_ROOT_SCRIPT; }

    void traceChildren(JSTracer* trc);

    // A helper class to prevent relazification of the given function's script
    // while it's holding on to it.  This class automatically roots the script.
    class AutoDelazify;
    friend class AutoDelazify;

    class AutoDelazify
    {
        JS::RootedScript script_;
        JSContext* cx_;
        bool oldDoNotRelazify_;
      public:
        explicit AutoDelazify(JSContext* cx, JS::HandleFunction fun = nullptr)
            : script_(cx)
            , cx_(cx)
        {
            holdScript(fun);
        }

        ~AutoDelazify()
        {
            dropScript();
        }

        void operator=(JS::HandleFunction fun)
        {
            dropScript();
            holdScript(fun);
        }

        operator JS::HandleScript() const { return script_; }
        explicit operator bool() const { return script_; }

      private:
        void holdScript(JS::HandleFunction fun);
        void dropScript();
    };
};

/* If this fails, add/remove padding within JSScript. */
static_assert(sizeof(JSScript) % js::gc::CellSize == 0,
              "Size of JSScript must be an integral multiple of js::gc::CellSize");

namespace js {

/*
 * Iterator over a script's bindings (formals and variables).
 * The order of iteration is:
 *  - first, formal arguments, from index 0 to numArgs
 *  - next, variables, from index 0 to numLocals
 */
class BindingIter
{
    Handle<Bindings> bindings_;
    uint32_t i_;
    uint32_t unaliasedLocal_;

    friend class ::JSScript;
    friend class Bindings;

  public:
    explicit BindingIter(Handle<Bindings> bindings)
      : bindings_(bindings), i_(0), unaliasedLocal_(0)
    {}

    explicit BindingIter(const HandleScript& script)
      : bindings_(Handle<Bindings>::fromMarkedLocation(&script->bindings)),
        i_(0), unaliasedLocal_(0)
    {}

    bool done() const { return i_ == bindings_.count(); }
    explicit operator bool() const { return !done(); }
    BindingIter& operator++() { (*this)++; return *this; }

    void operator++(int) {
        MOZ_ASSERT(!done());
        const Binding& binding = **this;
        if (binding.kind() != Binding::ARGUMENT && !binding.aliased())
            unaliasedLocal_++;
        i_++;
    }

    // Stack slots are assigned to arguments (aliased and unaliased) and
    // unaliased locals. frameIndex() returns the slot index. It's invalid to
    // call this method when the iterator is stopped on an aliased local, as it
    // has no stack slot.
    uint32_t frameIndex() const {
        MOZ_ASSERT(!done());
        if (i_ < bindings_.numArgs())
            return i_;
        MOZ_ASSERT(!(*this)->aliased());
        return unaliasedLocal_;
    }

    // If the current binding is an argument, argIndex() returns its index.
    // It returns the same value as frameIndex(), as slots are allocated for
    // both unaliased and aliased arguments.
    uint32_t argIndex() const {
        MOZ_ASSERT(!done());
        MOZ_ASSERT(i_ < bindings_.numArgs());
        return i_;
    }
    uint32_t argOrLocalIndex() const {
        MOZ_ASSERT(!done());
        return i_ < bindings_.numArgs() ? i_ : i_ - bindings_.numArgs();
    }
    uint32_t localIndex() const {
        MOZ_ASSERT(!done());
        MOZ_ASSERT(i_ >= bindings_.numArgs());
        return i_ - bindings_.numArgs();
    }
    bool isBodyLevelLexical() const {
        MOZ_ASSERT(!done());
        const Binding& binding = **this;
        return binding.kind() != Binding::ARGUMENT;
    }

    const Binding& operator*() const { MOZ_ASSERT(!done()); return bindings_.bindingArray()[i_]; }
    const Binding* operator->() const { MOZ_ASSERT(!done()); return &bindings_.bindingArray()[i_]; }
};

/*
 * Iterator over the aliased formal bindings in ascending index order. This can
 * be veiwed as a filtering of BindingIter with predicate
 *   bi->aliased() && bi->kind() == Binding::ARGUMENT
 */
class AliasedFormalIter
{
    const Binding* begin_;
    const Binding* p_;
    const Binding* end_;
    unsigned slot_;

    void settle() {
        while (p_ != end_ && !p_->aliased())
            p_++;
    }

  public:
    explicit inline AliasedFormalIter(JSScript* script);

    bool done() const { return p_ == end_; }
    explicit operator bool() const { return !done(); }
    void operator++(int) { MOZ_ASSERT(!done()); p_++; slot_++; settle(); }

    const Binding& operator*() const { MOZ_ASSERT(!done()); return *p_; }
    const Binding* operator->() const { MOZ_ASSERT(!done()); return p_; }
    unsigned frameIndex() const { MOZ_ASSERT(!done()); return p_ - begin_; }
    unsigned scopeSlot() const { MOZ_ASSERT(!done()); return slot_; }
};

// Information about a script which may be (or has been) lazily compiled to
// bytecode from its source.
class LazyScript : public gc::TenuredCell
{
  public:
    class FreeVariable
    {
        // Variable name is stored as a tagged JSAtom pointer.
        uintptr_t bits_;

        static const uintptr_t HOISTED_USE_BIT = 0x1;
        static const uintptr_t MASK = ~HOISTED_USE_BIT;

      public:
        explicit FreeVariable()
          : bits_(0)
        { }

        explicit FreeVariable(JSAtom* name)
          : bits_(uintptr_t(name))
        {
            // We rely on not requiring any write barriers so we can tag the
            // pointer. This code needs to change if we start allocating
            // JSAtoms inside the nursery.
            MOZ_ASSERT(!IsInsideNursery(name));
        }

        JSAtom* atom() const { return (JSAtom*)(bits_ & MASK); }
        void setIsHoistedUse() { bits_ |= HOISTED_USE_BIT; }
        bool isHoistedUse() const { return bool(bits_ & HOISTED_USE_BIT); }
    };

  private:
    // If non-nullptr, the script has been compiled and this is a forwarding
    // pointer to the result. This is a weak pointer: after relazification, we
    // can collect the script if there are no other pointers to it.
    WeakRef<JSScript*> script_;

    // Original function with which the lazy script is associated.
    HeapPtrFunction function_;

    // Function or block chain in which the script is nested, or nullptr.
    HeapPtrObject enclosingScope_;

    // ScriptSourceObject, or nullptr if the script in which this is nested
    // has not been compiled yet. This is never a CCW; we don't clone
    // LazyScripts into other compartments.
    HeapPtrObject sourceObject_;

    // Heap allocated table with any free variables or inner functions.
    void* table_;

    // Add padding so LazyScript is gc::Cell aligned. Make padding protected
    // instead of private to suppress -Wunused-private-field compiler warnings.
  protected:
#if JS_BITS_PER_WORD == 32
    uint32_t padding;
#endif
  private:

    struct PackedView {
        // Assorted bits that should really be in ScriptSourceObject.
        uint32_t version : 8;

        uint32_t numFreeVariables : 24;
        uint32_t numInnerFunctions : 20;

        uint32_t generatorKindBits : 2;

        // N.B. These are booleans but need to be uint32_t to pack correctly on MSVC.
        // If you add another boolean here, make sure to initialze it in
        // LazyScript::CreateRaw().
        uint32_t strict : 1;
        uint32_t bindingsAccessedDynamically : 1;
        uint32_t hasDebuggerStatement : 1;
        uint32_t hasDirectEval : 1;
        uint32_t isLikelyConstructorWrapper : 1;
        uint32_t hasBeenCloned : 1;
        uint32_t treatAsRunOnce : 1;
        uint32_t isDerivedClassConstructor : 1;
        uint32_t needsHomeObject : 1;
    };

    union {
        PackedView p_;
        uint64_t packedFields_;
    };

    // Source location for the script.
    uint32_t begin_;
    uint32_t end_;
    uint32_t lineno_;
    uint32_t column_;

    LazyScript(JSFunction* fun, void* table, uint64_t packedFields,
               uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column);

    // Create a LazyScript without initializing the freeVariables and the
    // innerFunctions. To be GC-safe, the caller must initialize both vectors
    // with valid atoms and functions.
    static LazyScript* CreateRaw(ExclusiveContext* cx, HandleFunction fun,
                                 uint64_t packedData, uint32_t begin, uint32_t end,
                                 uint32_t lineno, uint32_t column);

  public:
    // Create a LazyScript without initializing the freeVariables and the
    // innerFunctions. To be GC-safe, the caller must initialize both vectors
    // with valid atoms and functions.
    static LazyScript* CreateRaw(ExclusiveContext* cx, HandleFunction fun,
                                 uint32_t numFreeVariables, uint32_t numInnerFunctions,
                                 JSVersion version, uint32_t begin, uint32_t end,
                                 uint32_t lineno, uint32_t column);

    // Create a LazyScript and initialize the freeVariables and the
    // innerFunctions with dummy values to be replaced in a later initialization
    // phase.
    //
    // The "script" argument to this function can be null.  If it's non-null,
    // then this LazyScript should be associated with the given JSScript.
    //
    // The sourceObjectScript argument must be non-null and is the script that
    // should be used to get the sourceObject_ of this lazyScript.
    static LazyScript* Create(ExclusiveContext* cx, HandleFunction fun,
                              HandleScript script, HandleObject enclosingScope,
                              HandleScript sourceObjectScript,
                              uint64_t packedData, uint32_t begin, uint32_t end,
                              uint32_t lineno, uint32_t column);

    void initRuntimeFields(uint64_t packedFields);

    inline JSFunction* functionDelazifying(JSContext* cx) const;
    JSFunction* functionNonDelazifying() const {
        return function_;
    }

    void initScript(JSScript* script);
    void resetScript();

    JSScript* maybeScript() {
        return script_;
    }
    const JSScript* maybeScriptUnbarriered() const {
        return script_.unbarrieredGet();
    }
    bool hasScript() const {
        return bool(script_);
    }

    JSObject* enclosingScope() const {
        return enclosingScope_;
    }

    // Switch the script over from the off-thread compartment's static
    // global lexical scope to the main thread compartment's.
    void fixEnclosingStaticGlobalLexicalScope();

    ScriptSourceObject* sourceObject() const;
    ScriptSource* scriptSource() const {
        return sourceObject()->source();
    }
    ScriptSource* maybeForwardedScriptSource() const;
    bool mutedErrors() const {
        return scriptSource()->mutedErrors();
    }
    JSVersion version() const {
        JS_STATIC_ASSERT(JSVERSION_UNKNOWN == -1);
        return (p_.version == JS_BIT(8) - 1) ? JSVERSION_UNKNOWN : JSVersion(p_.version);
    }

    void setParent(JSObject* enclosingScope, ScriptSourceObject* sourceObject);

    uint32_t numFreeVariables() const {
        return p_.numFreeVariables;
    }
    FreeVariable* freeVariables() {
        return (FreeVariable*)table_;
    }

    uint32_t numInnerFunctions() const {
        return p_.numInnerFunctions;
    }
    HeapPtrFunction* innerFunctions() {
        return (HeapPtrFunction*)&freeVariables()[numFreeVariables()];
    }

    GeneratorKind generatorKind() const { return GeneratorKindFromBits(p_.generatorKindBits); }

    bool isGenerator() const { return generatorKind() != NotGenerator; }

    bool isLegacyGenerator() const { return generatorKind() == LegacyGenerator; }

    bool isStarGenerator() const { return generatorKind() == StarGenerator; }

    void setGeneratorKind(GeneratorKind kind) {
        // A script only gets its generator kind set as part of initialization,
        // so it can only transition from NotGenerator.
        MOZ_ASSERT(!isGenerator());
        // Legacy generators cannot currently be lazy.
        MOZ_ASSERT(kind != LegacyGenerator);
        p_.generatorKindBits = GeneratorKindAsBits(kind);
    }

    bool strict() const {
        return p_.strict;
    }
    void setStrict() {
        p_.strict = true;
    }

    bool bindingsAccessedDynamically() const {
        return p_.bindingsAccessedDynamically;
    }
    void setBindingsAccessedDynamically() {
        p_.bindingsAccessedDynamically = true;
    }

    bool hasDebuggerStatement() const {
        return p_.hasDebuggerStatement;
    }
    void setHasDebuggerStatement() {
        p_.hasDebuggerStatement = true;
    }

    bool hasDirectEval() const {
        return p_.hasDirectEval;
    }
    void setHasDirectEval() {
        p_.hasDirectEval = true;
    }

    bool isLikelyConstructorWrapper() const {
        return p_.isLikelyConstructorWrapper;
    }
    void setLikelyConstructorWrapper() {
        p_.isLikelyConstructorWrapper = true;
    }

    bool hasBeenCloned() const {
        return p_.hasBeenCloned;
    }
    void setHasBeenCloned() {
        p_.hasBeenCloned = true;
    }

    bool treatAsRunOnce() const {
        return p_.treatAsRunOnce;
    }
    void setTreatAsRunOnce() {
        p_.treatAsRunOnce = true;
    }

    bool isDerivedClassConstructor() const {
        return p_.isDerivedClassConstructor;
    }
    void setIsDerivedClassConstructor() {
        p_.isDerivedClassConstructor = true;
    }

    bool needsHomeObject() const {
        return p_.needsHomeObject;
    }
    void setNeedsHomeObject() {
        p_.needsHomeObject = true;
    }

    const char* filename() const {
        return scriptSource()->filename();
    }
    uint32_t begin() const {
        return begin_;
    }
    uint32_t end() const {
        return end_;
    }
    uint32_t lineno() const {
        return lineno_;
    }
    uint32_t column() const {
        return column_;
    }

    bool hasUncompiledEnclosingScript() const;

    friend class GCMarker;
    void traceChildren(JSTracer* trc);
    void finalize(js::FreeOp* fop);
    void fixupAfterMovingGC() {}

    static inline js::ThingRootKind rootKind() { return js::THING_ROOT_LAZY_SCRIPT; }

    size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
    {
        return mallocSizeOf(table_);
    }

    uint64_t packedFields() const {
        return packedFields_;
    }
};

/* If this fails, add/remove padding within LazyScript. */
JS_STATIC_ASSERT(sizeof(LazyScript) % js::gc::CellSize == 0);

struct SharedScriptData
{
    uint32_t length;
    uint32_t natoms;
    mozilla::Atomic<bool, mozilla::ReleaseAcquire> marked;
    jsbytecode data[1];

    static SharedScriptData* new_(ExclusiveContext* cx, uint32_t codeLength,
                                  uint32_t srcnotesLength, uint32_t natoms);

    HeapPtrAtom* atoms() {
        if (!natoms)
            return nullptr;
        return reinterpret_cast<HeapPtrAtom*>(data + length - sizeof(JSAtom*) * natoms);
    }

    static SharedScriptData* fromBytecode(const jsbytecode* bytecode) {
        return (SharedScriptData*)(bytecode - offsetof(SharedScriptData, data));
    }

  private:
    SharedScriptData() = delete;
    SharedScriptData(const SharedScriptData&) = delete;
};

struct ScriptBytecodeHasher
{
    struct Lookup
    {
        jsbytecode*         code;
        uint32_t            length;

        explicit Lookup(SharedScriptData* ssd) : code(ssd->data), length(ssd->length) {}
    };
    static HashNumber hash(const Lookup& l) { return mozilla::HashBytes(l.code, l.length); }
    static bool match(SharedScriptData* entry, const Lookup& lookup) {
        if (entry->length != lookup.length)
            return false;
        return mozilla::PodEqual<jsbytecode>(entry->data, lookup.code, lookup.length);
    }
};

typedef HashSet<SharedScriptData*,
                ScriptBytecodeHasher,
                SystemAllocPolicy> ScriptDataTable;

extern void
UnmarkScriptData(JSRuntime* rt);

extern void
SweepScriptData(JSRuntime* rt);

extern void
FreeScriptData(JSRuntime* rt);

struct ScriptAndCounts
{
    /* This structure is stored and marked from the JSRuntime. */
    JSScript* script;
    ScriptCounts scriptCounts;

    inline explicit ScriptAndCounts(JSScript* script);
    inline ScriptAndCounts(ScriptAndCounts&& sac);

    const PCCounts* maybeGetPCCounts(jsbytecode* pc) const {
        return scriptCounts.maybeGetPCCounts(script->pcToOffset(pc));
    }
    const PCCounts* maybeGetThrowCounts(jsbytecode* pc) const {
        return scriptCounts.maybeGetThrowCounts(script->pcToOffset(pc));
    }

    jit::IonScriptCounts* getIonCounts() const {
        return scriptCounts.ionCounts_;
    }

    void trace(JSTracer* trc) {
        TraceRoot(trc, &script, "ScriptAndCounts::script");
    }
};

struct GSNCache;

jssrcnote*
GetSrcNote(GSNCache& cache, JSScript* script, jsbytecode* pc);

extern jssrcnote*
GetSrcNote(JSContext* cx, JSScript* script, jsbytecode* pc);

extern jsbytecode*
LineNumberToPC(JSScript* script, unsigned lineno);

extern JS_FRIEND_API(unsigned)
GetScriptLineExtent(JSScript* script);

} /* namespace js */

namespace js {

extern unsigned
PCToLineNumber(JSScript* script, jsbytecode* pc, unsigned* columnp = nullptr);

extern unsigned
PCToLineNumber(unsigned startLine, jssrcnote* notes, jsbytecode* code, jsbytecode* pc,
               unsigned* columnp = nullptr);

/*
 * This function returns the file and line number of the script currently
 * executing on cx. If there is no current script executing on cx (e.g., a
 * native called directly through JSAPI (e.g., by setTimeout)), nullptr and 0
 * are returned as the file and line. Additionally, this function avoids the
 * full linear scan to compute line number when the caller guarantees that the
 * script compilation occurs at a JSOP_EVAL/JSOP_SPREADEVAL.
 */

enum LineOption {
    CALLED_FROM_JSOP_EVAL,
    NOT_CALLED_FROM_JSOP_EVAL
};

extern void
DescribeScriptedCallerForCompilation(JSContext* cx, MutableHandleScript maybeScript,
                                     const char** file, unsigned* linenop,
                                     uint32_t* pcOffset, bool* mutedErrors,
                                     LineOption opt = NOT_CALLED_FROM_JSOP_EVAL);

JSScript*
CloneScriptIntoFunction(JSContext* cx, HandleObject enclosingScope, HandleFunction fun,
                        HandleScript src);

JSScript*
CloneGlobalScript(JSContext* cx, Handle<ScopeObject*> enclosingScope, HandleScript src);

} /* namespace js */

// JS::ubi::Nodes can point to js::LazyScripts; they're js::gc::Cell instances
// with no associated compartment.
namespace JS {
namespace ubi {
template<>
struct Concrete<js::LazyScript> : TracerConcrete<js::LazyScript> {
    CoarseType coarseType() const final { return CoarseType::Script; }
    Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
    const char* scriptFilename() const final;

  protected:
    explicit Concrete(js::LazyScript *ptr) : TracerConcrete<js::LazyScript>(ptr) { }

  public:
    static void construct(void *storage, js::LazyScript *ptr) { new (storage) Concrete(ptr); }
};
} // namespace ubi
} // namespace JS

#endif /* jsscript_h */
