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