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