js/src/jsscript.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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/. */
     7 /* JS script descriptor. */
     9 #ifndef jsscript_h
    10 #define jsscript_h
    12 #include "mozilla/MemoryReporting.h"
    13 #include "mozilla/PodOperations.h"
    15 #include "jsatom.h"
    16 #ifdef JS_THREADSAFE
    17 #include "jslock.h"
    18 #endif
    19 #include "jsobj.h"
    20 #include "jsopcode.h"
    21 #include "jstypes.h"
    23 #include "gc/Barrier.h"
    24 #include "gc/Rooting.h"
    25 #include "jit/IonCode.h"
    26 #include "vm/Shape.h"
    28 namespace JS {
    29 struct ScriptSourceInfo;
    30 }
    32 namespace js {
    34 namespace jit {
    35     struct BaselineScript;
    36     struct IonScriptCounts;
    37 }
    39 # define ION_DISABLED_SCRIPT ((js::jit::IonScript *)0x1)
    40 # define ION_COMPILING_SCRIPT ((js::jit::IonScript *)0x2)
    42 # define BASELINE_DISABLED_SCRIPT ((js::jit::BaselineScript *)0x1)
    44 class BreakpointSite;
    45 class BindingIter;
    46 class LazyScript;
    47 class RegExpObject;
    48 struct SourceCompressionTask;
    49 class Shape;
    50 class WatchpointMap;
    51 class NestedScopeObject;
    53 namespace frontend {
    54     class BytecodeEmitter;
    55 }
    57 }
    59 /*
    60  * Type of try note associated with each catch or finally block, and also with
    61  * for-in and other kinds of loops. Non-for-in loops do not need these notes
    62  * for exception unwinding, but storing their boundaries here is helpful for
    63  * heuristics that need to know whether a given op is inside a loop.
    64  */
    65 typedef enum JSTryNoteKind {
    66     JSTRY_CATCH,
    67     JSTRY_FINALLY,
    68     JSTRY_ITER,
    69     JSTRY_LOOP
    70 } JSTryNoteKind;
    72 /*
    73  * Exception handling record.
    74  */
    75 struct JSTryNote {
    76     uint8_t         kind;       /* one of JSTryNoteKind */
    77     uint32_t        stackDepth; /* stack depth upon exception handler entry */
    78     uint32_t        start;      /* start of the try statement or loop
    79                                    relative to script->main */
    80     uint32_t        length;     /* length of the try statement or loop */
    81 };
    83 namespace js {
    85 // A block scope has a range in bytecode: it is entered at some offset, and left
    86 // at some later offset.  Scopes can be nested.  Given an offset, the
    87 // BlockScopeNote containing that offset whose with the highest start value
    88 // indicates the block scope.  The block scope list is sorted by increasing
    89 // start value.
    90 //
    91 // It is possible to leave a scope nonlocally, for example via a "break"
    92 // statement, so there may be short bytecode ranges in a block scope in which we
    93 // are popping the block chain in preparation for a goto.  These exits are also
    94 // nested with respect to outer scopes.  The scopes in these exits are indicated
    95 // by the "index" field, just like any other block.  If a nonlocal exit pops the
    96 // last block scope, the index will be NoBlockScopeIndex.
    97 //
    98 struct BlockScopeNote {
    99     static const uint32_t NoBlockScopeIndex = UINT32_MAX;
   101     uint32_t        index;      // Index of NestedScopeObject in the object
   102                                 // array, or NoBlockScopeIndex if there is no
   103                                 // block scope in this range.
   104     uint32_t        start;      // Bytecode offset at which this scope starts,
   105                                 // from script->main().
   106     uint32_t        length;     // Bytecode length of scope.
   107     uint32_t        parent;     // Index of parent block scope in notes, or UINT32_MAX.
   108 };
   110 struct ConstArray {
   111     js::HeapValue   *vector;    /* array of indexed constant values */
   112     uint32_t        length;
   113 };
   115 struct ObjectArray {
   116     js::HeapPtrObject *vector;  // Array of indexed objects.
   117     uint32_t        length;     // Count of indexed objects.
   118 };
   120 struct TryNoteArray {
   121     JSTryNote       *vector;    // Array of indexed try notes.
   122     uint32_t        length;     // Count of indexed try notes.
   123 };
   125 struct BlockScopeArray {
   126     BlockScopeNote *vector;     // Array of indexed BlockScopeNote records.
   127     uint32_t        length;     // Count of indexed try notes.
   128 };
   130 class Binding
   131 {
   132     // One JSScript stores one Binding per formal/variable so we use a
   133     // packed-word representation.
   134     uintptr_t bits_;
   136     static const uintptr_t KIND_MASK = 0x3;
   137     static const uintptr_t ALIASED_BIT = 0x4;
   138     static const uintptr_t NAME_MASK = ~(KIND_MASK | ALIASED_BIT);
   140   public:
   141     // A "binding" is a formal, 'var', or 'const' declaration. A function's
   142     // lexical scope is composed of these three kinds of bindings.
   143     enum Kind { ARGUMENT, VARIABLE, CONSTANT };
   145     explicit Binding() : bits_(0) {}
   147     Binding(PropertyName *name, Kind kind, bool aliased) {
   148         JS_STATIC_ASSERT(CONSTANT <= KIND_MASK);
   149         JS_ASSERT((uintptr_t(name) & ~NAME_MASK) == 0);
   150         JS_ASSERT((uintptr_t(kind) & ~KIND_MASK) == 0);
   151         bits_ = uintptr_t(name) | uintptr_t(kind) | (aliased ? ALIASED_BIT : 0);
   152     }
   154     PropertyName *name() const {
   155         return (PropertyName *)(bits_ & NAME_MASK);
   156     }
   158     Kind kind() const {
   159         return Kind(bits_ & KIND_MASK);
   160     }
   162     bool aliased() const {
   163         return bool(bits_ & ALIASED_BIT);
   164     }
   165 };
   167 JS_STATIC_ASSERT(sizeof(Binding) == sizeof(uintptr_t));
   169 class Bindings;
   170 typedef InternalHandle<Bindings *> InternalBindingsHandle;
   172 /*
   173  * Formal parameters and local variables are stored in a shape tree
   174  * path encapsulated within this class.  This class represents bindings for
   175  * both function and top-level scripts (the latter is needed to track names in
   176  * strict mode eval code, to give such code its own lexical environment).
   177  */
   178 class Bindings
   179 {
   180     friend class BindingIter;
   181     friend class AliasedFormalIter;
   183     HeapPtr<Shape> callObjShape_;
   184     uintptr_t bindingArrayAndFlag_;
   185     uint16_t numArgs_;
   186     uint16_t numBlockScoped_;
   187     uint32_t numVars_;
   189     /*
   190      * During parsing, bindings are allocated out of a temporary LifoAlloc.
   191      * After parsing, a JSScript object is created and the bindings are
   192      * permanently transferred to it. On error paths, the JSScript object may
   193      * end up with bindings that still point to the (new released) LifoAlloc
   194      * memory. To avoid tracing these bindings during GC, we keep track of
   195      * whether the bindings are temporary or permanent in the low bit of
   196      * bindingArrayAndFlag_.
   197      */
   198     static const uintptr_t TEMPORARY_STORAGE_BIT = 0x1;
   199     bool bindingArrayUsingTemporaryStorage() const {
   200         return bindingArrayAndFlag_ & TEMPORARY_STORAGE_BIT;
   201     }
   203   public:
   205     Binding *bindingArray() const {
   206         return reinterpret_cast<Binding *>(bindingArrayAndFlag_ & ~TEMPORARY_STORAGE_BIT);
   207     }
   209     inline Bindings();
   211     /*
   212      * Initialize a Bindings with a pointer into temporary storage.
   213      * bindingArray must have length numArgs+numVars. Before the temporary
   214      * storage is release, switchToScriptStorage must be called, providing a
   215      * pointer into the Binding array stored in script->data.
   216      */
   217     static bool initWithTemporaryStorage(ExclusiveContext *cx, InternalBindingsHandle self,
   218                                          unsigned numArgs, uint32_t numVars,
   219                                          Binding *bindingArray, unsigned numBlockScoped);
   221     // CompileScript parses and compiles one statement at a time, but the result
   222     // is one Script object.  There will be no vars or bindings, because those
   223     // go on the global, but there may be block-scoped locals, and the number of
   224     // block-scoped locals may increase as we parse more expressions.  This
   225     // helper updates the number of block scoped variables in a script as it is
   226     // being parsed.
   227     void updateNumBlockScoped(unsigned numBlockScoped) {
   228         JS_ASSERT(!callObjShape_);
   229         JS_ASSERT(numVars_ == 0);
   230         JS_ASSERT(numBlockScoped < LOCALNO_LIMIT);
   231         JS_ASSERT(numBlockScoped >= numBlockScoped_);
   232         numBlockScoped_ = numBlockScoped;
   233     }
   235     uint8_t *switchToScriptStorage(Binding *newStorage);
   237     /*
   238      * Clone srcScript's bindings (as part of js::CloneScript). dstScriptData
   239      * is the pointer to what will eventually be dstScript->data.
   240      */
   241     static bool clone(JSContext *cx, InternalBindingsHandle self, uint8_t *dstScriptData,
   242                       HandleScript srcScript);
   244     unsigned numArgs() const { return numArgs_; }
   245     uint32_t numVars() const { return numVars_; }
   246     unsigned numBlockScoped() const { return numBlockScoped_; }
   247     uint32_t numLocals() const { return numVars() + numBlockScoped(); }
   249     // Return the size of the bindingArray.
   250     uint32_t count() const { return numArgs() + numVars(); }
   252     /* Return the initial shape of call objects created for this scope. */
   253     Shape *callObjShape() const { return callObjShape_; }
   255     /* Convenience method to get the var index of 'arguments'. */
   256     static uint32_t argumentsVarIndex(ExclusiveContext *cx, InternalBindingsHandle);
   258     /* Return whether the binding at bindingIndex is aliased. */
   259     bool bindingIsAliased(uint32_t bindingIndex);
   261     /* Return whether this scope has any aliased bindings. */
   262     bool hasAnyAliasedBindings() const {
   263         if (!callObjShape_)
   264             return false;
   266         return !callObjShape_->isEmptyShape();
   267     }
   269     void trace(JSTracer *trc);
   270 };
   272 template <>
   273 struct GCMethods<Bindings> {
   274     static Bindings initial();
   275     static ThingRootKind kind() { return THING_ROOT_BINDINGS; }
   276     static bool poisoned(const Bindings &bindings) {
   277         return IsPoisonedPtr(static_cast<Shape *>(bindings.callObjShape()));
   278     }
   279 };
   281 class ScriptCounts
   282 {
   283     friend class ::JSScript;
   284     friend struct ScriptAndCounts;
   286     /*
   287      * This points to a single block that holds an array of PCCounts followed
   288      * by an array of doubles.  Each element in the PCCounts array has a
   289      * pointer into the array of doubles.
   290      */
   291     PCCounts *pcCountsVector;
   293     /* Information about any Ion compilations for the script. */
   294     jit::IonScriptCounts *ionCounts;
   296  public:
   297     ScriptCounts() : pcCountsVector(nullptr), ionCounts(nullptr) { }
   299     inline void destroy(FreeOp *fop);
   301     void set(js::ScriptCounts counts) {
   302         pcCountsVector = counts.pcCountsVector;
   303         ionCounts = counts.ionCounts;
   304     }
   305 };
   307 typedef HashMap<JSScript *,
   308                 ScriptCounts,
   309                 DefaultHasher<JSScript *>,
   310                 SystemAllocPolicy> ScriptCountsMap;
   312 class DebugScript
   313 {
   314     friend class ::JSScript;
   316     /*
   317      * When non-zero, compile script in single-step mode. The top bit is set and
   318      * cleared by setStepMode, as used by JSD. The lower bits are a count,
   319      * adjusted by changeStepModeCount, used by the Debugger object. Only
   320      * when the bit is clear and the count is zero may we compile the script
   321      * without single-step support.
   322      */
   323     uint32_t        stepMode;
   325     /* Number of breakpoint sites at opcodes in the script. */
   326     uint32_t        numSites;
   328     /*
   329      * Array with all breakpoints installed at opcodes in the script, indexed
   330      * by the offset of the opcode into the script.
   331      */
   332     BreakpointSite  *breakpoints[1];
   333 };
   335 typedef HashMap<JSScript *,
   336                 DebugScript *,
   337                 DefaultHasher<JSScript *>,
   338                 SystemAllocPolicy> DebugScriptMap;
   340 class ScriptSource;
   342 class SourceDataCache
   343 {
   344     typedef HashMap<ScriptSource *,
   345                     const jschar *,
   346                     DefaultHasher<ScriptSource *>,
   347                     SystemAllocPolicy> Map;
   349   public:
   350     // Hold an entry in the source data cache and prevent it from being purged on GC.
   351     class AutoHoldEntry
   352     {
   353         SourceDataCache *cache_;
   354         ScriptSource *source_;
   355         const jschar *charsToFree_;
   356       public:
   357         explicit AutoHoldEntry();
   358         ~AutoHoldEntry();
   359       private:
   360         void holdEntry(SourceDataCache *cache, ScriptSource *source);
   361         void deferDelete(const jschar *chars);
   362         ScriptSource *source() const { return source_; }
   363         friend class SourceDataCache;
   364     };
   366   private:
   367     Map *map_;
   368     AutoHoldEntry *holder_;
   370   public:
   371     SourceDataCache() : map_(nullptr), holder_(nullptr) {}
   373     const jschar *lookup(ScriptSource *ss, AutoHoldEntry &asp);
   374     bool put(ScriptSource *ss, const jschar *chars, AutoHoldEntry &asp);
   376     void purge();
   378     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
   380   private:
   381     void holdEntry(AutoHoldEntry &holder, ScriptSource *ss);
   382     void releaseEntry(AutoHoldEntry &holder);
   383 };
   385 class ScriptSource
   386 {
   387     friend class SourceCompressionTask;
   389     // A note on concurrency:
   390     //
   391     // The source may be compressed by a worker thread during parsing. (See
   392     // SourceCompressionTask.) When compression is running in the background,
   393     // ready() returns false. The compression thread touches the |data| union
   394     // and |compressedLength_|. Therefore, it is not safe to read these members
   395     // unless ready() is true. With that said, users of the public ScriptSource
   396     // API should be fine.
   398     union {
   399         // Before setSourceCopy or setSource are successfully called, this union
   400         // has a nullptr pointer. When the script source is ready,
   401         // compressedLength_ != 0 implies compressed holds the compressed data;
   402         // otherwise, source holds the uncompressed source. There is a special
   403         // pointer |emptySource| for source code for length 0.
   404         //
   405         // The only function allowed to malloc, realloc, or free the pointers in
   406         // this union is adjustDataSize(). Don't do it elsewhere.
   407         jschar *source;
   408         unsigned char *compressed;
   409     } data;
   410     uint32_t refs;
   411     uint32_t length_;
   412     uint32_t compressedLength_;
   413     char *filename_;
   414     jschar *displayURL_;
   415     jschar *sourceMapURL_;
   416     JSPrincipals *originPrincipals_;
   418     // bytecode offset in caller script that generated this code.
   419     // This is present for eval-ed code, as well as "new Function(...)"-introduced
   420     // scripts.
   421     uint32_t introductionOffset_;
   423     // If this ScriptSource was generated by a code-introduction mechanism such as |eval|
   424     // or |new Function|, the debugger needs access to the "raw" filename of the top-level
   425     // script that contains the eval-ing code.  To keep track of this, we must preserve
   426     // the original outermost filename (of the original introducer script), so that instead
   427     // of a filename of "foo.js line 30 > eval line 10 > Function", we can obtain the
   428     // original raw filename of "foo.js".
   429     char *introducerFilename_;
   431     // A string indicating how this source code was introduced into the system.
   432     // This accessor returns one of the following values:
   433     //      "eval" for code passed to |eval|.
   434     //      "Function" for code passed to the |Function| constructor.
   435     //      "Worker" for code loaded by calling the Web worker constructor&mdash;the worker's main script.
   436     //      "importScripts" for code by calling |importScripts| in a web worker.
   437     //      "handler" for code assigned to DOM elements' event handler IDL attributes.
   438     //      "scriptElement" for code belonging to <script> elements.
   439     //      undefined if the implementation doesn't know how the code was introduced.
   440     // This is a constant, statically allocated C string, so does not need
   441     // memory management.
   442     const char *introductionType_;
   444     // True if we can call JSRuntime::sourceHook to load the source on
   445     // demand. If sourceRetrievable_ and hasSourceData() are false, it is not
   446     // possible to get source at all.
   447     bool sourceRetrievable_:1;
   448     bool argumentsNotIncluded_:1;
   449     bool ready_:1;
   450     bool hasIntroductionOffset_:1;
   452   public:
   453     explicit ScriptSource()
   454       : refs(0),
   455         length_(0),
   456         compressedLength_(0),
   457         filename_(nullptr),
   458         displayURL_(nullptr),
   459         sourceMapURL_(nullptr),
   460         originPrincipals_(nullptr),
   461         introductionOffset_(0),
   462         introducerFilename_(nullptr),
   463         introductionType_(nullptr),
   464         sourceRetrievable_(false),
   465         argumentsNotIncluded_(false),
   466         ready_(true),
   467         hasIntroductionOffset_(false)
   468     {
   469         data.source = nullptr;
   470     }
   471     void incref() { refs++; }
   472     void decref() {
   473         JS_ASSERT(refs != 0);
   474         if (--refs == 0)
   475             destroy();
   476     }
   477     bool initFromOptions(ExclusiveContext *cx, const ReadOnlyCompileOptions &options);
   478     bool setSourceCopy(ExclusiveContext *cx,
   479                        JS::SourceBufferHolder &srcBuf,
   480                        bool argumentsNotIncluded,
   481                        SourceCompressionTask *tok);
   482     void setSource(const jschar *src, size_t length);
   483     bool ready() const { return ready_; }
   484     void setSourceRetrievable() { sourceRetrievable_ = true; }
   485     bool sourceRetrievable() const { return sourceRetrievable_; }
   486     bool hasSourceData() const { return !ready() || !!data.source; }
   487     uint32_t length() const {
   488         JS_ASSERT(hasSourceData());
   489         return length_;
   490     }
   491     bool argumentsNotIncluded() const {
   492         JS_ASSERT(hasSourceData());
   493         return argumentsNotIncluded_;
   494     }
   495     const jschar *chars(JSContext *cx, SourceDataCache::AutoHoldEntry &asp);
   496     JSFlatString *substring(JSContext *cx, uint32_t start, uint32_t stop);
   497     void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
   498                                 JS::ScriptSourceInfo *info) const;
   500     // XDR handling
   501     template <XDRMode mode>
   502     bool performXDR(XDRState<mode> *xdr);
   504     bool setFilename(ExclusiveContext *cx, const char *filename);
   505     const char *introducerFilename() const {
   506         return introducerFilename_;
   507     }
   508     bool hasIntroductionType() const {
   509         return introductionType_;
   510     }
   511     const char *introductionType() const {
   512         JS_ASSERT(hasIntroductionType());
   513         return introductionType_;
   514     }
   515     const char *filename() const {
   516         return filename_;
   517     }
   519     // Display URLs
   520     bool setDisplayURL(ExclusiveContext *cx, const jschar *displayURL);
   521     const jschar *displayURL();
   522     bool hasDisplayURL() const { return displayURL_ != nullptr; }
   524     // Source maps
   525     bool setSourceMapURL(ExclusiveContext *cx, const jschar *sourceMapURL);
   526     const jschar *sourceMapURL();
   527     bool hasSourceMapURL() const { return sourceMapURL_ != nullptr; }
   529     JSPrincipals *originPrincipals() const { return originPrincipals_; }
   531     bool hasIntroductionOffset() const { return hasIntroductionOffset_; }
   532     uint32_t introductionOffset() const {
   533         JS_ASSERT(hasIntroductionOffset());
   534         return introductionOffset_;
   535     }
   536     void setIntroductionOffset(uint32_t offset) {
   537         JS_ASSERT(!hasIntroductionOffset());
   538         JS_ASSERT(offset <= (uint32_t)INT32_MAX);
   539         introductionOffset_ = offset;
   540         hasIntroductionOffset_ = true;
   541     }
   543   private:
   544     void destroy();
   545     bool compressed() const { return compressedLength_ != 0; }
   546     size_t computedSizeOfData() const {
   547         return compressed() ? compressedLength_ : sizeof(jschar) * length_;
   548     }
   549     bool adjustDataSize(size_t nbytes);
   550     const jschar *getOffThreadCompressionChars(ExclusiveContext *cx);
   551 };
   553 class ScriptSourceHolder
   554 {
   555     ScriptSource *ss;
   556   public:
   557     explicit ScriptSourceHolder(ScriptSource *ss)
   558       : ss(ss)
   559     {
   560         ss->incref();
   561     }
   562     ~ScriptSourceHolder()
   563     {
   564         ss->decref();
   565     }
   566 };
   568 class ScriptSourceObject : public JSObject
   569 {
   570   public:
   571     static const Class class_;
   573     static void trace(JSTracer *trc, JSObject *obj);
   574     static void finalize(FreeOp *fop, JSObject *obj);
   575     static ScriptSourceObject *create(ExclusiveContext *cx, ScriptSource *source,
   576                                       const ReadOnlyCompileOptions &options);
   578     ScriptSource *source() {
   579         return static_cast<ScriptSource *>(getReservedSlot(SOURCE_SLOT).toPrivate());
   580     }
   582     void setSource(ScriptSource *source);
   584     JSObject *element() const;
   585     void initElement(HandleObject element);
   586     const Value &elementAttributeName() const;
   588     JSScript *introductionScript() const {
   589         void *untyped = getReservedSlot(INTRODUCTION_SCRIPT_SLOT).toPrivate();
   590         return static_cast<JSScript *>(untyped);
   591     }
   592     void initIntroductionScript(JSScript *script);
   594   private:
   595     static const uint32_t SOURCE_SLOT = 0;
   596     static const uint32_t ELEMENT_SLOT = 1;
   597     static const uint32_t ELEMENT_PROPERTY_SLOT = 2;
   598     static const uint32_t INTRODUCTION_SCRIPT_SLOT = 3;
   599     static const uint32_t RESERVED_SLOTS = 4;
   600 };
   602 enum GeneratorKind { NotGenerator, LegacyGenerator, StarGenerator };
   604 static inline unsigned
   605 GeneratorKindAsBits(GeneratorKind generatorKind) {
   606     return static_cast<unsigned>(generatorKind);
   607 }
   609 static inline GeneratorKind
   610 GeneratorKindFromBits(unsigned val) {
   611     JS_ASSERT(val <= StarGenerator);
   612     return static_cast<GeneratorKind>(val);
   613 }
   615 /*
   616  * NB: after a successful XDR_DECODE, XDRScript callers must do any required
   617  * subsequent set-up of owning function or script object and then call
   618  * js_CallNewScriptHook.
   619  */
   620 template<XDRMode mode>
   621 bool
   622 XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enclosingScript,
   623           HandleFunction fun, MutableHandleScript scriptp);
   625 JSScript *
   626 CloneScript(JSContext *cx, HandleObject enclosingScope, HandleFunction fun, HandleScript script,
   627             NewObjectKind newKind = GenericObject);
   629 template<XDRMode mode>
   630 bool
   631 XDRLazyScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enclosingScript,
   632               HandleFunction fun, MutableHandle<LazyScript *> lazy);
   634 /*
   635  * Code any constant value.
   636  */
   637 template<XDRMode mode>
   638 bool
   639 XDRScriptConst(XDRState<mode> *xdr, MutableHandleValue vp);
   641 } /* namespace js */
   643 class JSScript : public js::gc::BarrieredCell<JSScript>
   644 {
   645     static const uint32_t stepFlagMask = 0x80000000U;
   646     static const uint32_t stepCountMask = 0x7fffffffU;
   648     template <js::XDRMode mode>
   649     friend
   650     bool
   651     js::XDRScript(js::XDRState<mode> *xdr, js::HandleObject enclosingScope, js::HandleScript enclosingScript,
   652                   js::HandleFunction fun, js::MutableHandleScript scriptp);
   654     friend JSScript *
   655     js::CloneScript(JSContext *cx, js::HandleObject enclosingScope, js::HandleFunction fun, js::HandleScript src,
   656                     js::NewObjectKind newKind);
   658   public:
   659     //
   660     // We order fields according to their size in order to avoid wasting space
   661     // for alignment.
   662     //
   664     // Larger-than-word-sized fields.
   666   public:
   667     js::Bindings    bindings;   /* names of top-level variables in this script
   668                                    (and arguments if this is a function script) */
   670     bool hasAnyAliasedBindings() const {
   671         return bindings.hasAnyAliasedBindings();
   672     }
   674     js::Binding *bindingArray() const {
   675         return bindings.bindingArray();
   676     }
   678     unsigned numArgs() const {
   679         return bindings.numArgs();
   680     }
   682     js::Shape *callObjShape() const {
   683         return bindings.callObjShape();
   684     }
   686     // Word-sized fields.
   688   private:
   689     jsbytecode      *code_;     /* bytecodes and their immediate operands */
   690   public:
   691     uint8_t         *data;      /* pointer to variable-length data array (see
   692                                    comment above Create() for details) */
   694     js::HeapPtrAtom *atoms;     /* maps immediate index to literal struct */
   696     JSCompartment   *compartment_;
   698     /* Persistent type information retained across GCs. */
   699     js::types::TypeScript *types;
   701   private:
   702     // This script's ScriptSourceObject, or a CCW thereof.
   703     //
   704     // (When we clone a JSScript into a new compartment, we don't clone its
   705     // source object. Instead, the clone refers to a wrapper.)
   706     js::HeapPtrObject sourceObject_;
   708     js::HeapPtrFunction function_;
   710     // For callsite clones, which cannot have enclosing scopes, the original
   711     // function; otherwise the enclosing scope
   712     js::HeapPtrObject   enclosingScopeOrOriginalFunction_;
   714     /* Information attached by Baseline/Ion for sequential mode execution. */
   715     js::jit::IonScript *ion;
   716     js::jit::BaselineScript *baseline;
   718     /* Information attached by Ion for parallel mode execution */
   719     js::jit::IonScript *parallelIon;
   721     /* Information used to re-lazify a lazily-parsed interpreted function. */
   722     js::LazyScript *lazyScript;
   724     /*
   725      * Pointer to either baseline->method()->raw() or ion->method()->raw(), or
   726      * nullptr if there's no Baseline or Ion script.
   727      */
   728     uint8_t *baselineOrIonRaw;
   729     uint8_t *baselineOrIonSkipArgCheck;
   731     // 32-bit fields.
   733     uint32_t        length_;    /* length of code vector */
   734     uint32_t        dataSize_;  /* size of the used part of the data array */
   736     uint32_t        lineno_;    /* base line number of script */
   737     uint32_t        column_;    /* base column of script, optionally set */
   739     uint32_t        mainOffset_;/* offset of main entry point from code, after
   740                                    predef'ing prolog */
   742     uint32_t        natoms_;    /* length of atoms array */
   743     uint32_t        nslots_;    /* vars plus maximum stack depth */
   745     /* Range of characters in scriptSource which contains this script's source. */
   746     uint32_t        sourceStart_;
   747     uint32_t        sourceEnd_;
   749     uint32_t        useCount;   /* Number of times the script has been called
   750                                  * or has had backedges taken. When running in
   751                                  * ion, also increased for any inlined scripts.
   752                                  * Reset if the script's JIT code is forcibly
   753                                  * discarded. */
   755 #ifdef DEBUG
   756     // Unique identifier within the compartment for this script, used for
   757     // printing analysis information.
   758     uint32_t        id_;
   759     uint32_t        idpad;
   760 #endif
   762     // 16-bit fields.
   764     uint16_t        version;    /* JS version under which script was compiled */
   766     uint16_t        funLength_; /* ES6 function length */
   768     uint16_t        nTypeSets_; /* number of type sets used in this script for
   769                                    dynamic type monitoring */
   771     uint16_t        staticLevel_;/* static level for display maintenance */
   773     // Bit fields.
   775   public:
   776     // The kinds of the optional arrays.
   777     enum ArrayKind {
   778         CONSTS,
   779         OBJECTS,
   780         REGEXPS,
   781         TRYNOTES,
   782         BLOCK_SCOPES,
   783         ARRAY_KIND_BITS
   784     };
   786   private:
   787     // The bits in this field indicate the presence/non-presence of several
   788     // optional arrays in |data|.  See the comments above Create() for details.
   789     uint8_t         hasArrayBits:ARRAY_KIND_BITS;
   791     // The GeneratorKind of the script.
   792     uint8_t         generatorKindBits_:2;
   794     // 1-bit fields.
   796     // No need for result value of last expression statement.
   797     bool noScriptRval_:1;
   799     // Can call getCallerFunction().
   800     bool savedCallerFun_:1;
   802     // Code is in strict mode.
   803     bool strict_:1;
   805     // Code has "use strict"; explicitly.
   806     bool explicitUseStrict_:1;
   808     // See Parser::compileAndGo.
   809     bool compileAndGo_:1;
   811     // see Parser::selfHostingMode.
   812     bool selfHosted_:1;
   814     // See FunctionContextFlags.
   815     bool bindingsAccessedDynamically_:1;
   816     bool funHasExtensibleScope_:1;
   817     bool funNeedsDeclEnvObject_:1;
   819     // True if any formalIsAliased(i).
   820     bool funHasAnyAliasedFormal_:1;
   822     // Have warned about uses of undefined properties in this script.
   823     bool warnedAboutUndefinedProp_:1;
   825     // Script has singleton objects.
   826     bool hasSingletons_:1;
   828     // Script is a lambda to treat as running once.
   829     bool treatAsRunOnce_:1;
   831     // If treatAsRunOnce, whether script has executed.
   832     bool hasRunOnce_:1;
   834     // Script has been reused for a clone.
   835     bool hasBeenCloned_:1;
   837     // Script has been inlined at least once, and can't be relazified.
   838     bool hasBeenInlined_:1;
   840     // Script came from eval(), and is still active.
   841     bool isActiveEval_:1;
   843     // Script came from eval(), and is in eval cache.
   844     bool isCachedEval_:1;
   846     // Set for functions defined at the top level within an 'eval' script.
   847     bool directlyInsideEval_:1;
   849     // Both 'arguments' and f.apply() are used. This is likely to be a wrapper.
   850     bool usesArgumentsAndApply_:1;
   852     /* script is attempted to be cloned anew at each callsite. This is
   853        temporarily needed for ParallelArray selfhosted code until type
   854        information can be made context sensitive. See discussion in
   855        bug 826148. */
   856     bool shouldCloneAtCallsite_:1;
   857     bool isCallsiteClone_:1; /* is a callsite clone; has a link to the original function */
   858     bool shouldInline_:1;    /* hint to inline when possible */
   860     // IonMonkey compilation hints.
   861     bool failedBoundsCheck_:1; /* script has had hoisted bounds checks fail */
   862     bool failedShapeGuard_:1; /* script has had hoisted shape guard fail */
   863     bool hadFrequentBailouts_:1;
   864     bool uninlineable_:1;    /* explicitly marked as uninlineable */
   866     // Idempotent cache has triggered invalidation.
   867     bool invalidatedIdempotentCache_:1;
   869     // If the generator was created implicitly via a generator expression,
   870     // isGeneratorExp will be true.
   871     bool isGeneratorExp_:1;
   873     // Script has an entry in JSCompartment::scriptCountsMap.
   874     bool hasScriptCounts_:1;
   876     // Script has an entry in JSCompartment::debugScriptMap.
   877     bool hasDebugScript_:1;
   879     // Freeze constraints for stack type sets have been generated.
   880     bool hasFreezeConstraints_:1;
   882     /* See comments below. */
   883     bool argsHasVarBinding_:1;
   884     bool needsArgsAnalysis_:1;
   885     bool needsArgsObj_:1;
   887     //
   888     // End of fields.  Start methods.
   889     //
   891   public:
   892     static JSScript *Create(js::ExclusiveContext *cx,
   893                             js::HandleObject enclosingScope, bool savedCallerFun,
   894                             const JS::ReadOnlyCompileOptions &options, unsigned staticLevel,
   895                             js::HandleObject sourceObject, uint32_t sourceStart,
   896                             uint32_t sourceEnd);
   898     void initCompartment(js::ExclusiveContext *cx);
   900     // Three ways ways to initialize a JSScript. Callers of partiallyInit()
   901     // and fullyInitTrivial() are responsible for notifying the debugger after
   902     // successfully creating any kind (function or other) of new JSScript.
   903     // However, callers of fullyInitFromEmitter() do not need to do this.
   904     static bool partiallyInit(js::ExclusiveContext *cx, JS::Handle<JSScript*> script,
   905                               uint32_t nconsts, uint32_t nobjects, uint32_t nregexps,
   906                               uint32_t ntrynotes, uint32_t nblockscopes,
   907                               uint32_t nTypeSets);
   908     static bool fullyInitFromEmitter(js::ExclusiveContext *cx, JS::Handle<JSScript*> script,
   909                                      js::frontend::BytecodeEmitter *bce);
   910     // Initialize a no-op script.
   911     static bool fullyInitTrivial(js::ExclusiveContext *cx, JS::Handle<JSScript*> script);
   913     inline JSPrincipals *principals();
   915     JSCompartment *compartment() const { return compartment_; }
   917     void setVersion(JSVersion v) { version = v; }
   919     // Script bytecode is immutable after creation.
   920     jsbytecode *code() const {
   921         return code_;
   922     }
   923     size_t length() const {
   924         return length_;
   925     }
   927     void setCode(jsbytecode *code) { code_ = code; }
   928     void setLength(size_t length) { length_ = length; }
   930     jsbytecode *codeEnd() const { return code() + length(); }
   932     bool containsPC(const jsbytecode *pc) const {
   933         return pc >= code() && pc < codeEnd();
   934     }
   936     size_t pcToOffset(const jsbytecode *pc) const {
   937         JS_ASSERT(containsPC(pc));
   938         return size_t(pc - code());
   939     }
   941     jsbytecode *offsetToPC(size_t offset) const {
   942         JS_ASSERT(offset < length());
   943         return code() + offset;
   944     }
   946     size_t mainOffset() const {
   947         return mainOffset_;
   948     }
   950     size_t lineno() const {
   951         return lineno_;
   952     }
   954     size_t column() const {
   955         return column_;
   956     }
   958     void setColumn(size_t column) { column_ = column; }
   960     // The fixed part of a stack frame is comprised of vars (in function code)
   961     // and block-scoped locals (in all kinds of code).
   962     size_t nfixed() const {
   963         return function_ ? bindings.numLocals() : bindings.numBlockScoped();
   964     }
   966     // Number of fixed slots reserved for vars.  Only nonzero for function code.
   967     size_t nfixedvars() const {
   968         return function_ ? bindings.numVars() : 0;
   969     }
   971     size_t nslots() const {
   972         return nslots_;
   973     }
   975     size_t staticLevel() const {
   976         return staticLevel_;
   977     }
   979     size_t nTypeSets() const {
   980         return nTypeSets_;
   981     }
   983     size_t funLength() const {
   984         return funLength_;
   985     }
   987     size_t sourceStart() const {
   988         return sourceStart_;
   989     }
   991     size_t sourceEnd() const {
   992         return sourceEnd_;
   993     }
   995     bool noScriptRval() const {
   996         return noScriptRval_;
   997     }
   999     bool savedCallerFun() const { return savedCallerFun_; }
  1001     bool strict() const {
  1002         return strict_;
  1005     bool explicitUseStrict() const { return explicitUseStrict_; }
  1007     bool compileAndGo() const {
  1008         return compileAndGo_;
  1011     bool selfHosted() const { return selfHosted_; }
  1012     bool bindingsAccessedDynamically() const { return bindingsAccessedDynamically_; }
  1013     bool funHasExtensibleScope() const {
  1014         return funHasExtensibleScope_;
  1016     bool funNeedsDeclEnvObject() const {
  1017         return funNeedsDeclEnvObject_;
  1019     bool funHasAnyAliasedFormal() const {
  1020         return funHasAnyAliasedFormal_;
  1023     bool hasSingletons() const { return hasSingletons_; }
  1024     bool treatAsRunOnce() const {
  1025         return treatAsRunOnce_;
  1027     bool hasRunOnce() const { return hasRunOnce_; }
  1028     bool hasBeenCloned() const { return hasBeenCloned_; }
  1029     bool hasBeenInlined() const { return hasBeenInlined_; }
  1031     void setTreatAsRunOnce() { treatAsRunOnce_ = true; }
  1032     void setHasRunOnce() { hasRunOnce_ = true; }
  1033     void setHasBeenCloned() { hasBeenCloned_ = true; }
  1034     void setHasBeenInlined() { hasBeenInlined_ = true; }
  1036     bool isActiveEval() const { return isActiveEval_; }
  1037     bool isCachedEval() const { return isCachedEval_; }
  1038     bool directlyInsideEval() const { return directlyInsideEval_; }
  1040     void cacheForEval() {
  1041         JS_ASSERT(isActiveEval() && !isCachedEval());
  1042         isActiveEval_ = false;
  1043         isCachedEval_ = true;
  1046     void uncacheForEval() {
  1047         JS_ASSERT(isCachedEval() && !isActiveEval());
  1048         isCachedEval_ = false;
  1049         isActiveEval_ = true;
  1052     void setActiveEval() { isActiveEval_ = true; }
  1053     void setDirectlyInsideEval() { directlyInsideEval_ = true; }
  1055     bool usesArgumentsAndApply() const {
  1056         return usesArgumentsAndApply_;
  1058     void setUsesArgumentsAndApply() { usesArgumentsAndApply_ = true; }
  1060     bool shouldCloneAtCallsite() const {
  1061         return shouldCloneAtCallsite_;
  1063     bool shouldInline() const {
  1064         return shouldInline_;
  1067     void setShouldCloneAtCallsite() { shouldCloneAtCallsite_ = true; }
  1068     void setShouldInline() { shouldInline_ = true; }
  1070     bool isCallsiteClone() const {
  1071         return isCallsiteClone_;
  1073     bool isGeneratorExp() const { return isGeneratorExp_; }
  1075     bool failedBoundsCheck() const {
  1076         return failedBoundsCheck_;
  1078     bool failedShapeGuard() const {
  1079         return failedShapeGuard_;
  1081     bool hadFrequentBailouts() const {
  1082         return hadFrequentBailouts_;
  1084     bool uninlineable() const {
  1085         return uninlineable_;
  1087     bool invalidatedIdempotentCache() const {
  1088         return invalidatedIdempotentCache_;
  1091     void setFailedBoundsCheck() { failedBoundsCheck_ = true; }
  1092     void setFailedShapeGuard() { failedShapeGuard_ = true; }
  1093     void setHadFrequentBailouts() { hadFrequentBailouts_ = true; }
  1094     void setUninlineable() { uninlineable_ = true; }
  1095     void setInvalidatedIdempotentCache() { invalidatedIdempotentCache_ = true; }
  1097     bool hasScriptCounts() const { return hasScriptCounts_; }
  1099     bool hasFreezeConstraints() const { return hasFreezeConstraints_; }
  1100     void setHasFreezeConstraints() { hasFreezeConstraints_ = true; }
  1101     void clearHasFreezeConstraints() { hasFreezeConstraints_ = false; }
  1103     bool warnedAboutUndefinedProp() const { return warnedAboutUndefinedProp_; }
  1104     void setWarnedAboutUndefinedProp() { warnedAboutUndefinedProp_ = true; }
  1106     /* See ContextFlags::funArgumentsHasLocalBinding comment. */
  1107     bool argumentsHasVarBinding() const {
  1108         return argsHasVarBinding_;
  1110     jsbytecode *argumentsBytecode() const { JS_ASSERT(code()[0] == JSOP_ARGUMENTS); return code(); }
  1111     void setArgumentsHasVarBinding();
  1112     bool argumentsAliasesFormals() const {
  1113         return argumentsHasVarBinding() && !strict();
  1116     js::GeneratorKind generatorKind() const {
  1117         return js::GeneratorKindFromBits(generatorKindBits_);
  1119     bool isGenerator() const { return generatorKind() != js::NotGenerator; }
  1120     bool isLegacyGenerator() const { return generatorKind() == js::LegacyGenerator; }
  1121     bool isStarGenerator() const { return generatorKind() == js::StarGenerator; }
  1122     void setGeneratorKind(js::GeneratorKind kind) {
  1123         // A script only gets its generator kind set as part of initialization,
  1124         // so it can only transition from not being a generator.
  1125         JS_ASSERT(!isGenerator());
  1126         generatorKindBits_ = GeneratorKindAsBits(kind);
  1129     /*
  1130      * As an optimization, even when argsHasLocalBinding, the function prologue
  1131      * may not need to create an arguments object. This is determined by
  1132      * needsArgsObj which is set by AnalyzeArgumentsUsage before running
  1133      * the script the first time. When !needsArgsObj, the prologue may simply
  1134      * write MagicValue(JS_OPTIMIZED_ARGUMENTS) to 'arguments's slot and any
  1135      * uses of 'arguments' will be guaranteed to handle this magic value.
  1136      * So avoid spurious arguments object creation, we maintain the invariant
  1137      * that needsArgsObj is only called after the script has been analyzed.
  1138      */
  1139     bool analyzedArgsUsage() const { return !needsArgsAnalysis_; }
  1140     inline bool ensureHasAnalyzedArgsUsage(JSContext *cx);
  1141     bool needsArgsObj() const {
  1142         JS_ASSERT(analyzedArgsUsage());
  1143         return needsArgsObj_;
  1145     void setNeedsArgsObj(bool needsArgsObj);
  1146     static bool argumentsOptimizationFailed(JSContext *cx, js::HandleScript script);
  1148     /*
  1149      * Arguments access (via JSOP_*ARG* opcodes) must access the canonical
  1150      * location for the argument. If an arguments object exists AND this is a
  1151      * non-strict function (where 'arguments' aliases formals), then all access
  1152      * must go through the arguments object. Otherwise, the local slot is the
  1153      * canonical location for the arguments. Note: if a formal is aliased
  1154      * through the scope chain, then script->formalIsAliased and JSOP_*ARG*
  1155      * opcodes won't be emitted at all.
  1156      */
  1157     bool argsObjAliasesFormals() const {
  1158         return needsArgsObj() && !strict();
  1161     bool hasAnyIonScript() const {
  1162         return hasIonScript() || hasParallelIonScript();
  1165     bool hasIonScript() const {
  1166         bool res = ion && ion != ION_DISABLED_SCRIPT && ion != ION_COMPILING_SCRIPT;
  1167         MOZ_ASSERT_IF(res, baseline);
  1168         return res;
  1170     bool canIonCompile() const {
  1171         return ion != ION_DISABLED_SCRIPT;
  1174     bool isIonCompilingOffThread() const {
  1175         return ion == ION_COMPILING_SCRIPT;
  1178     js::jit::IonScript *ionScript() const {
  1179         JS_ASSERT(hasIonScript());
  1180         return ion;
  1182     js::jit::IonScript *maybeIonScript() const {
  1183         return ion;
  1185     js::jit::IonScript *const *addressOfIonScript() const {
  1186         return &ion;
  1188     void setIonScript(js::jit::IonScript *ionScript) {
  1189         if (hasIonScript())
  1190             js::jit::IonScript::writeBarrierPre(tenuredZone(), ion);
  1191         ion = ionScript;
  1192         MOZ_ASSERT_IF(hasIonScript(), hasBaselineScript());
  1193         updateBaselineOrIonRaw();
  1196     bool hasBaselineScript() const {
  1197         bool res = baseline && baseline != BASELINE_DISABLED_SCRIPT;
  1198         MOZ_ASSERT_IF(!res, !ion || ion == ION_DISABLED_SCRIPT);
  1199         return res;
  1201     bool canBaselineCompile() const {
  1202         return baseline != BASELINE_DISABLED_SCRIPT;
  1204     js::jit::BaselineScript *baselineScript() const {
  1205         JS_ASSERT(hasBaselineScript());
  1206         return baseline;
  1208     inline void setBaselineScript(JSContext *maybecx, js::jit::BaselineScript *baselineScript);
  1210     void updateBaselineOrIonRaw();
  1212     bool hasParallelIonScript() const {
  1213         return parallelIon && parallelIon != ION_DISABLED_SCRIPT && parallelIon != ION_COMPILING_SCRIPT;
  1216     bool canParallelIonCompile() const {
  1217         return parallelIon != ION_DISABLED_SCRIPT;
  1220     bool isParallelIonCompilingOffThread() const {
  1221         return parallelIon == ION_COMPILING_SCRIPT;
  1224     js::jit::IonScript *parallelIonScript() const {
  1225         JS_ASSERT(hasParallelIonScript());
  1226         return parallelIon;
  1228     js::jit::IonScript *maybeParallelIonScript() const {
  1229         return parallelIon;
  1231     void setParallelIonScript(js::jit::IonScript *ionScript) {
  1232         if (hasParallelIonScript())
  1233             js::jit::IonScript::writeBarrierPre(tenuredZone(), parallelIon);
  1234         parallelIon = ionScript;
  1237     static size_t offsetOfBaselineScript() {
  1238         return offsetof(JSScript, baseline);
  1240     static size_t offsetOfIonScript() {
  1241         return offsetof(JSScript, ion);
  1243     static size_t offsetOfParallelIonScript() {
  1244         return offsetof(JSScript, parallelIon);
  1246     static size_t offsetOfBaselineOrIonRaw() {
  1247         return offsetof(JSScript, baselineOrIonRaw);
  1249     static size_t offsetOfBaselineOrIonSkipArgCheck() {
  1250         return offsetof(JSScript, baselineOrIonSkipArgCheck);
  1253     bool isRelazifiable() const {
  1254         return (selfHosted() || lazyScript) &&
  1255                !isGenerator() && !hasBaselineScript() && !hasAnyIonScript() && !hasBeenInlined();
  1257     void setLazyScript(js::LazyScript *lazy) {
  1258         lazyScript = lazy;
  1260     js::LazyScript *maybeLazyScript() {
  1261         return lazyScript;
  1264     /*
  1265      * Original compiled function for the script, if it has a function.
  1266      * nullptr for global and eval scripts.
  1267      * The delazifying variant ensures that the function isn't lazy. The
  1268      * non-delazifying variant must only be used after earlier code has
  1269      * called ensureNonLazyCanonicalFunction and while the function can't
  1270      * have been relazified.
  1271      */
  1272     inline JSFunction *functionDelazifying() const;
  1273     JSFunction *functionNonDelazifying() const {
  1274         return function_;
  1276     inline void setFunction(JSFunction *fun);
  1277     /*
  1278      * De-lazifies the canonical function. Must be called before entering code
  1279      * that expects the function to be non-lazy.
  1280      */
  1281     inline void ensureNonLazyCanonicalFunction(JSContext *cx);
  1283     /*
  1284      * Donor provided itself to callsite clone; null if this is non-clone.
  1285      */
  1286     JSFunction *donorFunction() const;
  1287     void setIsCallsiteClone(JSObject *fun);
  1289     JSFlatString *sourceData(JSContext *cx);
  1291     static bool loadSource(JSContext *cx, js::ScriptSource *ss, bool *worked);
  1293     void setSourceObject(JSObject *object);
  1294     JSObject *sourceObject() const {
  1295         return sourceObject_;
  1297     js::ScriptSourceObject &scriptSourceUnwrap() const;
  1298     js::ScriptSource *scriptSource() const;
  1299     JSPrincipals *originPrincipals() const { return scriptSource()->originPrincipals(); }
  1300     const char *filename() const { return scriptSource()->filename(); }
  1302   public:
  1304     /* Return whether this script was compiled for 'eval' */
  1305     bool isForEval() { return isCachedEval() || isActiveEval(); }
  1307 #ifdef DEBUG
  1308     unsigned id();
  1309 #else
  1310     unsigned id() { return 0; }
  1311 #endif
  1313     /* Ensure the script has a TypeScript. */
  1314     inline bool ensureHasTypes(JSContext *cx);
  1316     inline js::GlobalObject &global() const;
  1317     js::GlobalObject &uninlinedGlobal() const;
  1319     /* See StaticScopeIter comment. */
  1320     JSObject *enclosingStaticScope() const {
  1321         if (isCallsiteClone())
  1322             return nullptr;
  1323         return enclosingScopeOrOriginalFunction_;
  1326   private:
  1327     bool makeTypes(JSContext *cx);
  1329   public:
  1330     uint32_t getUseCount() const {
  1331         return useCount;
  1333     uint32_t incUseCount(uint32_t amount = 1) { return useCount += amount; }
  1334     uint32_t *addressOfUseCount() { return &useCount; }
  1335     static size_t offsetOfUseCount() { return offsetof(JSScript, useCount); }
  1336     void resetUseCount() { useCount = 0; }
  1338   public:
  1339     bool initScriptCounts(JSContext *cx);
  1340     js::PCCounts getPCCounts(jsbytecode *pc);
  1341     void addIonCounts(js::jit::IonScriptCounts *ionCounts);
  1342     js::jit::IonScriptCounts *getIonCounts();
  1343     js::ScriptCounts releaseScriptCounts();
  1344     void destroyScriptCounts(js::FreeOp *fop);
  1346     jsbytecode *main() {
  1347         return code() + mainOffset();
  1350     /*
  1351      * computedSizeOfData() is the in-use size of all the data sections.
  1352      * sizeOfData() is the size of the block allocated to hold all the data
  1353      * sections (which can be larger than the in-use size).
  1354      */
  1355     size_t computedSizeOfData() const;
  1356     size_t sizeOfData(mozilla::MallocSizeOf mallocSizeOf) const;
  1357     size_t sizeOfTypeScript(mozilla::MallocSizeOf mallocSizeOf) const;
  1359     uint32_t numNotes();  /* Number of srcnote slots in the srcnotes section */
  1361     /* Script notes are allocated right after the code. */
  1362     jssrcnote *notes() { return (jssrcnote *)(code() + length()); }
  1364     bool hasArray(ArrayKind kind) {
  1365         return hasArrayBits & (1 << kind);
  1367     void setHasArray(ArrayKind kind) { hasArrayBits |= (1 << kind); }
  1368     void cloneHasArray(JSScript *script) { hasArrayBits = script->hasArrayBits; }
  1370     bool hasConsts()        { return hasArray(CONSTS);      }
  1371     bool hasObjects()       { return hasArray(OBJECTS);     }
  1372     bool hasRegexps()       { return hasArray(REGEXPS);     }
  1373     bool hasTrynotes()      { return hasArray(TRYNOTES);    }
  1374     bool hasBlockScopes()   { return hasArray(BLOCK_SCOPES); }
  1376     #define OFF(fooOff, hasFoo, t)   (fooOff() + (hasFoo() ? sizeof(t) : 0))
  1378     size_t constsOffset()     { return 0; }
  1379     size_t objectsOffset()    { return OFF(constsOffset,     hasConsts,     js::ConstArray);      }
  1380     size_t regexpsOffset()    { return OFF(objectsOffset,    hasObjects,    js::ObjectArray);     }
  1381     size_t trynotesOffset()   { return OFF(regexpsOffset,    hasRegexps,    js::ObjectArray);     }
  1382     size_t blockScopesOffset(){ return OFF(trynotesOffset,   hasTrynotes,   js::TryNoteArray);    }
  1384     size_t dataSize() const { return dataSize_; }
  1386     js::ConstArray *consts() {
  1387         JS_ASSERT(hasConsts());
  1388         return reinterpret_cast<js::ConstArray *>(data + constsOffset());
  1391     js::ObjectArray *objects() {
  1392         JS_ASSERT(hasObjects());
  1393         return reinterpret_cast<js::ObjectArray *>(data + objectsOffset());
  1396     js::ObjectArray *regexps() {
  1397         JS_ASSERT(hasRegexps());
  1398         return reinterpret_cast<js::ObjectArray *>(data + regexpsOffset());
  1401     js::TryNoteArray *trynotes() {
  1402         JS_ASSERT(hasTrynotes());
  1403         return reinterpret_cast<js::TryNoteArray *>(data + trynotesOffset());
  1406     js::BlockScopeArray *blockScopes() {
  1407         JS_ASSERT(hasBlockScopes());
  1408         return reinterpret_cast<js::BlockScopeArray *>(data + blockScopesOffset());
  1411     bool hasLoops();
  1413     size_t natoms() const { return natoms_; }
  1415     js::HeapPtrAtom &getAtom(size_t index) const {
  1416         JS_ASSERT(index < natoms());
  1417         return atoms[index];
  1420     js::HeapPtrAtom &getAtom(jsbytecode *pc) const {
  1421         JS_ASSERT(containsPC(pc) && containsPC(pc + sizeof(uint32_t)));
  1422         return getAtom(GET_UINT32_INDEX(pc));
  1425     js::PropertyName *getName(size_t index) {
  1426         return getAtom(index)->asPropertyName();
  1429     js::PropertyName *getName(jsbytecode *pc) const {
  1430         JS_ASSERT(containsPC(pc) && containsPC(pc + sizeof(uint32_t)));
  1431         return getAtom(GET_UINT32_INDEX(pc))->asPropertyName();
  1434     JSObject *getObject(size_t index) {
  1435         js::ObjectArray *arr = objects();
  1436         JS_ASSERT(index < arr->length);
  1437         return arr->vector[index];
  1440     size_t innerObjectsStart() {
  1441         // The first object contains the caller if savedCallerFun is used.
  1442         return savedCallerFun() ? 1 : 0;
  1445     JSObject *getObject(jsbytecode *pc) {
  1446         JS_ASSERT(containsPC(pc) && containsPC(pc + sizeof(uint32_t)));
  1447         return getObject(GET_UINT32_INDEX(pc));
  1450     JSVersion getVersion() const {
  1451         return JSVersion(version);
  1454     inline JSFunction *getFunction(size_t index);
  1455     inline JSFunction *getCallerFunction();
  1456     inline JSFunction *functionOrCallerFunction();
  1458     inline js::RegExpObject *getRegExp(size_t index);
  1459     inline js::RegExpObject *getRegExp(jsbytecode *pc);
  1461     const js::Value &getConst(size_t index) {
  1462         js::ConstArray *arr = consts();
  1463         JS_ASSERT(index < arr->length);
  1464         return arr->vector[index];
  1467     js::NestedScopeObject *getStaticScope(jsbytecode *pc);
  1469     /*
  1470      * The isEmpty method tells whether this script has code that computes any
  1471      * result (not return value, result AKA normal completion value) other than
  1472      * JSVAL_VOID, or any other effects.
  1473      */
  1474     bool isEmpty() const {
  1475         if (length() > 3)
  1476             return false;
  1478         jsbytecode *pc = code();
  1479         if (noScriptRval() && JSOp(*pc) == JSOP_FALSE)
  1480             ++pc;
  1481         return JSOp(*pc) == JSOP_RETRVAL;
  1484     bool varIsAliased(uint32_t varSlot);
  1485     bool formalIsAliased(unsigned argSlot);
  1486     bool formalLivesInArgumentsObject(unsigned argSlot);
  1488   private:
  1489     /* Change this->stepMode to |newValue|. */
  1490     void setNewStepMode(js::FreeOp *fop, uint32_t newValue);
  1492     bool ensureHasDebugScript(JSContext *cx);
  1493     js::DebugScript *debugScript();
  1494     js::DebugScript *releaseDebugScript();
  1495     void destroyDebugScript(js::FreeOp *fop);
  1497   public:
  1498     bool hasBreakpointsAt(jsbytecode *pc);
  1499     bool hasAnyBreakpointsOrStepMode() { return hasDebugScript_; }
  1501     js::BreakpointSite *getBreakpointSite(jsbytecode *pc)
  1503         return hasDebugScript_ ? debugScript()->breakpoints[pcToOffset(pc)] : nullptr;
  1506     js::BreakpointSite *getOrCreateBreakpointSite(JSContext *cx, jsbytecode *pc);
  1508     void destroyBreakpointSite(js::FreeOp *fop, jsbytecode *pc);
  1510     void clearBreakpointsIn(js::FreeOp *fop, js::Debugger *dbg, JSObject *handler);
  1511     void clearTraps(js::FreeOp *fop);
  1513     void markTrapClosures(JSTracer *trc);
  1515     /*
  1516      * Set or clear the single-step flag. If the flag is set or the count
  1517      * (adjusted by changeStepModeCount) is non-zero, then the script is in
  1518      * single-step mode. (JSD uses an on/off-style interface; Debugger uses a
  1519      * count-style interface.)
  1520      */
  1521     bool setStepModeFlag(JSContext *cx, bool step);
  1523     /*
  1524      * Increment or decrement the single-step count. If the count is non-zero or
  1525      * the flag (set by setStepModeFlag) is set, then the script is in
  1526      * single-step mode. (JSD uses an on/off-style interface; Debugger uses a
  1527      * count-style interface.)
  1529      * Only incrementing is fallible, as it could allocate a DebugScript.
  1530      */
  1531     bool incrementStepModeCount(JSContext *cx);
  1532     void decrementStepModeCount(js::FreeOp *fop);
  1534     bool stepModeEnabled() { return hasDebugScript_ && !!debugScript()->stepMode; }
  1536 #ifdef DEBUG
  1537     uint32_t stepModeCount() { return hasDebugScript_ ? (debugScript()->stepMode & stepCountMask) : 0; }
  1538 #endif
  1540     void finalize(js::FreeOp *fop);
  1542     static inline js::ThingRootKind rootKind() { return js::THING_ROOT_SCRIPT; }
  1544     void markChildren(JSTracer *trc);
  1545 };
  1547 /* If this fails, add/remove padding within JSScript. */
  1548 static_assert(sizeof(JSScript) % js::gc::CellSize == 0,
  1549               "Size of JSScript must be an integral multiple of js::gc::CellSize");
  1551 namespace js {
  1553 /*
  1554  * Iterator over a script's bindings (formals and variables).
  1555  * The order of iteration is:
  1556  *  - first, formal arguments, from index 0 to numArgs
  1557  *  - next, variables, from index 0 to numLocals
  1558  */
  1559 class BindingIter
  1561     const InternalBindingsHandle bindings_;
  1562     uint32_t i_;
  1564     friend class Bindings;
  1566   public:
  1567     explicit BindingIter(const InternalBindingsHandle &bindings) : bindings_(bindings), i_(0) {}
  1568     explicit BindingIter(const HandleScript &script) : bindings_(script, &script->bindings), i_(0) {}
  1570     bool done() const { return i_ == bindings_->count(); }
  1571     operator bool() const { return !done(); }
  1572     void operator++(int) { JS_ASSERT(!done()); i_++; }
  1573     BindingIter &operator++() { (*this)++; return *this; }
  1575     uint32_t frameIndex() const {
  1576         JS_ASSERT(!done());
  1577         return i_ < bindings_->numArgs() ? i_ : i_ - bindings_->numArgs();
  1580     const Binding &operator*() const { JS_ASSERT(!done()); return bindings_->bindingArray()[i_]; }
  1581     const Binding *operator->() const { JS_ASSERT(!done()); return &bindings_->bindingArray()[i_]; }
  1582 };
  1584 /*
  1585  * This helper function fills the given BindingVector with the sequential
  1586  * values of BindingIter.
  1587  */
  1589 typedef Vector<Binding, 32> BindingVector;
  1591 extern bool
  1592 FillBindingVector(HandleScript fromScript, BindingVector *vec);
  1594 /*
  1595  * Iterator over the aliased formal bindings in ascending index order. This can
  1596  * be veiwed as a filtering of BindingIter with predicate
  1597  *   bi->aliased() && bi->kind() == Binding::ARGUMENT
  1598  */
  1599 class AliasedFormalIter
  1601     const Binding *begin_, *p_, *end_;
  1602     unsigned slot_;
  1604     void settle() {
  1605         while (p_ != end_ && !p_->aliased())
  1606             p_++;
  1609   public:
  1610     explicit inline AliasedFormalIter(JSScript *script);
  1612     bool done() const { return p_ == end_; }
  1613     operator bool() const { return !done(); }
  1614     void operator++(int) { JS_ASSERT(!done()); p_++; slot_++; settle(); }
  1616     const Binding &operator*() const { JS_ASSERT(!done()); return *p_; }
  1617     const Binding *operator->() const { JS_ASSERT(!done()); return p_; }
  1618     unsigned frameIndex() const { JS_ASSERT(!done()); return p_ - begin_; }
  1619     unsigned scopeSlot() const { JS_ASSERT(!done()); return slot_; }
  1620 };
  1622 // Information about a script which may be (or has been) lazily compiled to
  1623 // bytecode from its source.
  1624 class LazyScript : public gc::BarrieredCell<LazyScript>
  1626     // If non-nullptr, the script has been compiled and this is a forwarding
  1627     // pointer to the result.
  1628     HeapPtrScript script_;
  1630     // Original function with which the lazy script is associated.
  1631     HeapPtrFunction function_;
  1633     // Function or block chain in which the script is nested, or nullptr.
  1634     HeapPtrObject enclosingScope_;
  1636     // ScriptSourceObject, or nullptr if the script in which this is nested
  1637     // has not been compiled yet. This is never a CCW; we don't clone
  1638     // LazyScripts into other compartments.
  1639     HeapPtrObject sourceObject_;
  1641     // Heap allocated table with any free variables or inner functions.
  1642     void *table_;
  1644 #if JS_BITS_PER_WORD == 32
  1645     uint32_t padding;
  1646 #endif
  1648     struct PackedView {
  1649         // Assorted bits that should really be in ScriptSourceObject.
  1650         uint32_t version : 8;
  1652         uint32_t numFreeVariables : 24;
  1653         uint32_t numInnerFunctions : 23;
  1655         uint32_t generatorKindBits : 2;
  1657         // N.B. These are booleans but need to be uint32_t to pack correctly on MSVC.
  1658         uint32_t strict : 1;
  1659         uint32_t bindingsAccessedDynamically : 1;
  1660         uint32_t hasDebuggerStatement : 1;
  1661         uint32_t directlyInsideEval : 1;
  1662         uint32_t usesArgumentsAndApply : 1;
  1663         uint32_t hasBeenCloned : 1;
  1664         uint32_t treatAsRunOnce : 1;
  1665     };
  1667     union {
  1668         PackedView p_;
  1669         uint64_t packedFields_;
  1670     };
  1672     // Source location for the script.
  1673     uint32_t begin_;
  1674     uint32_t end_;
  1675     uint32_t lineno_;
  1676     uint32_t column_;
  1678     LazyScript(JSFunction *fun, void *table, uint64_t packedFields,
  1679                uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column);
  1681     // Create a LazyScript without initializing the freeVariables and the
  1682     // innerFunctions. To be GC-safe, the caller must initialize both vectors
  1683     // with valid atoms and functions.
  1684     static LazyScript *CreateRaw(ExclusiveContext *cx, HandleFunction fun,
  1685                                  uint64_t packedData, uint32_t begin, uint32_t end,
  1686                                  uint32_t lineno, uint32_t column);
  1688   public:
  1689     // Create a LazyScript without initializing the freeVariables and the
  1690     // innerFunctions. To be GC-safe, the caller must initialize both vectors
  1691     // with valid atoms and functions.
  1692     static LazyScript *CreateRaw(ExclusiveContext *cx, HandleFunction fun,
  1693                                  uint32_t numFreeVariables, uint32_t numInnerFunctions,
  1694                                  JSVersion version, uint32_t begin, uint32_t end,
  1695                                  uint32_t lineno, uint32_t column);
  1697     // Create a LazyScript and initialize the freeVariables and the
  1698     // innerFunctions with dummy values to be replaced in a later initialization
  1699     // phase.
  1700     static LazyScript *Create(ExclusiveContext *cx, HandleFunction fun,
  1701                               uint64_t packedData, uint32_t begin, uint32_t end,
  1702                               uint32_t lineno, uint32_t column);
  1704     void initRuntimeFields(uint64_t packedFields);
  1706     inline JSFunction *functionDelazifying(JSContext *cx) const;
  1707     JSFunction *functionNonDelazifying() const {
  1708         return function_;
  1711     void initScript(JSScript *script);
  1712     void resetScript();
  1713     JSScript *maybeScript() {
  1714         return script_;
  1717     JSObject *enclosingScope() const {
  1718         return enclosingScope_;
  1720     ScriptSourceObject *sourceObject() const;
  1721     ScriptSource *scriptSource() const {
  1722         return sourceObject()->source();
  1724     JSPrincipals *originPrincipals() const {
  1725         return scriptSource()->originPrincipals();
  1727     JSVersion version() const {
  1728         JS_STATIC_ASSERT(JSVERSION_UNKNOWN == -1);
  1729         return (p_.version == JS_BIT(8) - 1) ? JSVERSION_UNKNOWN : JSVersion(p_.version);
  1732     void setParent(JSObject *enclosingScope, ScriptSourceObject *sourceObject);
  1734     uint32_t numFreeVariables() const {
  1735         return p_.numFreeVariables;
  1737     HeapPtrAtom *freeVariables() {
  1738         return (HeapPtrAtom *)table_;
  1741     uint32_t numInnerFunctions() const {
  1742         return p_.numInnerFunctions;
  1744     HeapPtrFunction *innerFunctions() {
  1745         return (HeapPtrFunction *)&freeVariables()[numFreeVariables()];
  1748     GeneratorKind generatorKind() const { return GeneratorKindFromBits(p_.generatorKindBits); }
  1750     bool isGenerator() const { return generatorKind() != NotGenerator; }
  1752     bool isLegacyGenerator() const { return generatorKind() == LegacyGenerator; }
  1754     bool isStarGenerator() const { return generatorKind() == StarGenerator; }
  1756     void setGeneratorKind(GeneratorKind kind) {
  1757         // A script only gets its generator kind set as part of initialization,
  1758         // so it can only transition from NotGenerator.
  1759         JS_ASSERT(!isGenerator());
  1760         // Legacy generators cannot currently be lazy.
  1761         JS_ASSERT(kind != LegacyGenerator);
  1762         p_.generatorKindBits = GeneratorKindAsBits(kind);
  1765     bool strict() const {
  1766         return p_.strict;
  1768     void setStrict() {
  1769         p_.strict = true;
  1772     bool bindingsAccessedDynamically() const {
  1773         return p_.bindingsAccessedDynamically;
  1775     void setBindingsAccessedDynamically() {
  1776         p_.bindingsAccessedDynamically = true;
  1779     bool hasDebuggerStatement() const {
  1780         return p_.hasDebuggerStatement;
  1782     void setHasDebuggerStatement() {
  1783         p_.hasDebuggerStatement = true;
  1786     bool directlyInsideEval() const {
  1787         return p_.directlyInsideEval;
  1789     void setDirectlyInsideEval() {
  1790         p_.directlyInsideEval = true;
  1793     bool usesArgumentsAndApply() const {
  1794         return p_.usesArgumentsAndApply;
  1796     void setUsesArgumentsAndApply() {
  1797         p_.usesArgumentsAndApply = true;
  1800     bool hasBeenCloned() const {
  1801         return p_.hasBeenCloned;
  1803     void setHasBeenCloned() {
  1804         p_.hasBeenCloned = true;
  1807     bool treatAsRunOnce() const {
  1808         return p_.treatAsRunOnce;
  1810     void setTreatAsRunOnce() {
  1811         p_.treatAsRunOnce = true;
  1814     ScriptSource *source() const {
  1815         return sourceObject()->source();
  1817     uint32_t begin() const {
  1818         return begin_;
  1820     uint32_t end() const {
  1821         return end_;
  1823     uint32_t lineno() const {
  1824         return lineno_;
  1826     uint32_t column() const {
  1827         return column_;
  1830     bool hasUncompiledEnclosingScript() const;
  1831     uint32_t staticLevel(JSContext *cx) const;
  1833     void markChildren(JSTracer *trc);
  1834     void finalize(js::FreeOp *fop);
  1836     static inline js::ThingRootKind rootKind() { return js::THING_ROOT_LAZY_SCRIPT; }
  1838     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
  1840         return mallocSizeOf(table_);
  1843     uint64_t packedFields() const {
  1844         return packedFields_;
  1846 };
  1848 /* If this fails, add/remove padding within LazyScript. */
  1849 JS_STATIC_ASSERT(sizeof(LazyScript) % js::gc::CellSize == 0);
  1851 /*
  1852  * New-script-hook calling is factored from JSScript::fullyInitFromEmitter() so
  1853  * that it and callers of XDRScript() can share this code.  In the case of
  1854  * callers of XDRScript(), the hook should be invoked only after successful
  1855  * decode of any owning function (the fun parameter) or script object (null
  1856  * fun).
  1857  */
  1858 extern void
  1859 CallNewScriptHook(JSContext *cx, JS::HandleScript script, JS::HandleFunction fun);
  1861 extern void
  1862 CallDestroyScriptHook(FreeOp *fop, JSScript *script);
  1864 struct SharedScriptData
  1866     uint32_t length;
  1867     uint32_t natoms;
  1868     bool marked;
  1869     jsbytecode data[1];
  1871     static SharedScriptData *new_(ExclusiveContext *cx, uint32_t codeLength,
  1872                                   uint32_t srcnotesLength, uint32_t natoms);
  1874     HeapPtrAtom *atoms() {
  1875         if (!natoms)
  1876             return nullptr;
  1877         return reinterpret_cast<HeapPtrAtom *>(data + length - sizeof(JSAtom *) * natoms);
  1880     static SharedScriptData *fromBytecode(const jsbytecode *bytecode) {
  1881         return (SharedScriptData *)(bytecode - offsetof(SharedScriptData, data));
  1884   private:
  1885     SharedScriptData() MOZ_DELETE;
  1886     SharedScriptData(const SharedScriptData&) MOZ_DELETE;
  1887 };
  1889 struct ScriptBytecodeHasher
  1891     struct Lookup
  1893         jsbytecode          *code;
  1894         uint32_t            length;
  1896         Lookup(SharedScriptData *ssd) : code(ssd->data), length(ssd->length) {}
  1897     };
  1898     static HashNumber hash(const Lookup &l) { return mozilla::HashBytes(l.code, l.length); }
  1899     static bool match(SharedScriptData *entry, const Lookup &lookup) {
  1900         if (entry->length != lookup.length)
  1901             return false;
  1902         return mozilla::PodEqual<jsbytecode>(entry->data, lookup.code, lookup.length);
  1904 };
  1906 typedef HashSet<SharedScriptData*,
  1907                 ScriptBytecodeHasher,
  1908                 SystemAllocPolicy> ScriptDataTable;
  1910 extern void
  1911 UnmarkScriptData(JSRuntime *rt);
  1913 extern void
  1914 SweepScriptData(JSRuntime *rt);
  1916 extern void
  1917 FreeScriptData(JSRuntime *rt);
  1919 struct ScriptAndCounts
  1921     /* This structure is stored and marked from the JSRuntime. */
  1922     JSScript *script;
  1923     ScriptCounts scriptCounts;
  1925     PCCounts &getPCCounts(jsbytecode *pc) const {
  1926         return scriptCounts.pcCountsVector[script->pcToOffset(pc)];
  1929     jit::IonScriptCounts *getIonCounts() const {
  1930         return scriptCounts.ionCounts;
  1932 };
  1934 struct GSNCache;
  1936 jssrcnote *
  1937 GetSrcNote(GSNCache &cache, JSScript *script, jsbytecode *pc);
  1939 } /* namespace js */
  1941 extern jssrcnote *
  1942 js_GetSrcNote(JSContext *cx, JSScript *script, jsbytecode *pc);
  1944 extern jsbytecode *
  1945 js_LineNumberToPC(JSScript *script, unsigned lineno);
  1947 extern JS_FRIEND_API(unsigned)
  1948 js_GetScriptLineExtent(JSScript *script);
  1950 namespace js {
  1952 extern unsigned
  1953 PCToLineNumber(JSScript *script, jsbytecode *pc, unsigned *columnp = nullptr);
  1955 extern unsigned
  1956 PCToLineNumber(unsigned startLine, jssrcnote *notes, jsbytecode *code, jsbytecode *pc,
  1957                unsigned *columnp = nullptr);
  1959 /*
  1960  * This function returns the file and line number of the script currently
  1961  * executing on cx. If there is no current script executing on cx (e.g., a
  1962  * native called directly through JSAPI (e.g., by setTimeout)), nullptr and 0
  1963  * are returned as the file and line. Additionally, this function avoids the
  1964  * full linear scan to compute line number when the caller guarantees that the
  1965  * script compilation occurs at a JSOP_EVAL/JSOP_SPREADEVAL.
  1966  */
  1968 enum LineOption {
  1969     CALLED_FROM_JSOP_EVAL,
  1970     NOT_CALLED_FROM_JSOP_EVAL
  1971 };
  1973 extern void
  1974 DescribeScriptedCallerForCompilation(JSContext *cx, MutableHandleScript maybeScript,
  1975                                      const char **file, unsigned *linenop,
  1976                                      uint32_t *pcOffset, JSPrincipals **origin,
  1977                                      LineOption opt = NOT_CALLED_FROM_JSOP_EVAL);
  1979 bool
  1980 CloneFunctionScript(JSContext *cx, HandleFunction original, HandleFunction clone,
  1981                     NewObjectKind newKind = GenericObject);
  1983 /*
  1984  * JSAPI clients are allowed to leave CompileOptions.originPrincipals nullptr in
  1985  * which case the JS engine sets options.originPrincipals = origin.principals.
  1986  * This normalization step must occur before the originPrincipals get stored in
  1987  * the JSScript/ScriptSource.
  1988  */
  1990 static inline JSPrincipals *
  1991 NormalizeOriginPrincipals(JSPrincipals *principals, JSPrincipals *originPrincipals)
  1993     return originPrincipals ? originPrincipals : principals;
  1996 } /* namespace js */
  1998 #endif /* jsscript_h */

mercurial