Bumping gaia.json for 1 gaia revision(s) a=gaia-bump
[gecko.git] / js / src / jsscript.h
blob06ae8f345d498b3b7bb97418c0f7f6288dc80c5a
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sts=4 et sw=4 tw=99:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /* JS script descriptor. */
9 #ifndef jsscript_h
10 #define jsscript_h
12 #include "mozilla/MemoryReporting.h"
13 #include "mozilla/PodOperations.h"
14 #include "mozilla/UniquePtr.h"
16 #include "jsatom.h"
17 #include "jslock.h"
18 #include "jsopcode.h"
19 #include "jstypes.h"
21 #include "gc/Barrier.h"
22 #include "gc/Rooting.h"
23 #include "jit/IonCode.h"
24 #include "js/UbiNode.h"
25 #include "vm/NativeObject.h"
26 #include "vm/Shape.h"
28 namespace JS {
29 struct ScriptSourceInfo;
32 namespace js {
34 namespace jit {
35 struct BaselineScript;
36 struct IonScriptCounts;
39 # define ION_DISABLED_SCRIPT ((js::jit::IonScript*)0x1)
40 # define ION_COMPILING_SCRIPT ((js::jit::IonScript*)0x2)
42 # define BASELINE_DISABLED_SCRIPT ((js::jit::BaselineScript*)0x1)
44 class BreakpointSite;
45 class BindingIter;
46 class LazyScript;
47 class RegExpObject;
48 struct SourceCompressionTask;
49 class Shape;
50 class WatchpointMap;
51 class NestedScopeObject;
53 namespace frontend {
54 struct BytecodeEmitter;
55 class UpvarCookie;
61 * Type of try note associated with each catch or finally block, and also with
62 * for-in and other kinds of loops. Non-for-in loops do not need these notes
63 * for exception unwinding, but storing their boundaries here is helpful for
64 * heuristics that need to know whether a given op is inside a loop.
66 enum JSTryNoteKind {
67 JSTRY_CATCH,
68 JSTRY_FINALLY,
69 JSTRY_FOR_IN,
70 JSTRY_FOR_OF,
71 JSTRY_LOOP
75 * Exception handling record.
77 struct JSTryNote {
78 uint8_t kind; /* one of JSTryNoteKind */
79 uint32_t stackDepth; /* stack depth upon exception handler entry */
80 uint32_t start; /* start of the try statement or loop
81 relative to script->main */
82 uint32_t length; /* length of the try statement or loop */
85 namespace js {
87 // A block scope has a range in bytecode: it is entered at some offset, and left
88 // at some later offset. Scopes can be nested. Given an offset, the
89 // BlockScopeNote containing that offset whose with the highest start value
90 // indicates the block scope. The block scope list is sorted by increasing
91 // start value.
93 // It is possible to leave a scope nonlocally, for example via a "break"
94 // statement, so there may be short bytecode ranges in a block scope in which we
95 // are popping the block chain in preparation for a goto. These exits are also
96 // nested with respect to outer scopes. The scopes in these exits are indicated
97 // by the "index" field, just like any other block. If a nonlocal exit pops the
98 // last block scope, the index will be NoBlockScopeIndex.
100 struct BlockScopeNote {
101 static const uint32_t NoBlockScopeIndex = UINT32_MAX;
103 uint32_t index; // Index of NestedScopeObject in the object
104 // array, or NoBlockScopeIndex if there is no
105 // block scope in this range.
106 uint32_t start; // Bytecode offset at which this scope starts,
107 // from script->main().
108 uint32_t length; // Bytecode length of scope.
109 uint32_t parent; // Index of parent block scope in notes, or UINT32_MAX.
112 struct ConstArray {
113 js::HeapValue* vector; /* array of indexed constant values */
114 uint32_t length;
117 struct ObjectArray {
118 js::HeapPtrNativeObject* vector; // Array of indexed objects.
119 uint32_t length; // Count of indexed objects.
122 struct TryNoteArray {
123 JSTryNote* vector; // Array of indexed try notes.
124 uint32_t length; // Count of indexed try notes.
127 struct BlockScopeArray {
128 BlockScopeNote* vector; // Array of indexed BlockScopeNote records.
129 uint32_t length; // Count of indexed try notes.
132 class YieldOffsetArray {
133 uint32_t* vector_; // Array of bytecode offsets.
134 uint32_t length_; // Count of bytecode offsets.
136 public:
137 void init(uint32_t* vector, uint32_t length) {
138 vector_ = vector;
139 length_ = length;
141 uint32_t& operator[](uint32_t index) {
142 MOZ_ASSERT(index < length_);
143 return vector_[index];
145 uint32_t length() const {
146 return length_;
150 class Binding
152 // One JSScript stores one Binding per formal/variable so we use a
153 // packed-word representation.
154 uintptr_t bits_;
156 static const uintptr_t KIND_MASK = 0x3;
157 static const uintptr_t ALIASED_BIT = 0x4;
158 static const uintptr_t NAME_MASK = ~(KIND_MASK | ALIASED_BIT);
160 public:
161 // A "binding" is a formal parameter, 'var' (also a stand in for
162 // body-level 'let' declarations), or 'const' declaration. A function's
163 // lexical scope is composed of these three kinds of bindings.
164 enum Kind { ARGUMENT, VARIABLE, CONSTANT };
166 explicit Binding() : bits_(0) {}
168 Binding(PropertyName* name, Kind kind, bool aliased) {
169 JS_STATIC_ASSERT(CONSTANT <= KIND_MASK);
170 MOZ_ASSERT((uintptr_t(name) & ~NAME_MASK) == 0);
171 MOZ_ASSERT((uintptr_t(kind) & ~KIND_MASK) == 0);
172 bits_ = uintptr_t(name) | uintptr_t(kind) | (aliased ? ALIASED_BIT : 0);
175 PropertyName* name() const {
176 return (PropertyName*)(bits_ & NAME_MASK);
179 Kind kind() const {
180 return Kind(bits_ & KIND_MASK);
183 bool aliased() const {
184 return bool(bits_ & ALIASED_BIT);
188 JS_STATIC_ASSERT(sizeof(Binding) == sizeof(uintptr_t));
190 class Bindings;
191 typedef InternalHandle<Bindings*> InternalBindingsHandle;
194 * Formal parameters and local variables are stored in a shape tree
195 * path encapsulated within this class. This class represents bindings for
196 * both function and top-level scripts (the latter is needed to track names in
197 * strict mode eval code, to give such code its own lexical environment).
199 class Bindings
201 friend class BindingIter;
202 friend class AliasedFormalIter;
204 RelocatablePtrShape callObjShape_;
205 uintptr_t bindingArrayAndFlag_;
206 uint16_t numArgs_;
207 uint16_t numBlockScoped_;
208 uint16_t numBodyLevelLexicals_;
209 uint16_t aliasedBodyLevelLexicalBegin_;
210 uint16_t numUnaliasedBodyLevelLexicals_;
211 uint32_t numVars_;
212 uint32_t numUnaliasedVars_;
214 #if JS_BITS_PER_WORD == 32
215 // Bindings is allocated inline inside JSScript, which needs to be
216 // gc::Cell aligned.
217 uint32_t padding_;
218 #endif
221 * During parsing, bindings are allocated out of a temporary LifoAlloc.
222 * After parsing, a JSScript object is created and the bindings are
223 * permanently transferred to it. On error paths, the JSScript object may
224 * end up with bindings that still point to the (new released) LifoAlloc
225 * memory. To avoid tracing these bindings during GC, we keep track of
226 * whether the bindings are temporary or permanent in the low bit of
227 * bindingArrayAndFlag_.
229 static const uintptr_t TEMPORARY_STORAGE_BIT = 0x1;
230 bool bindingArrayUsingTemporaryStorage() const {
231 return bindingArrayAndFlag_ & TEMPORARY_STORAGE_BIT;
234 public:
236 Binding* bindingArray() const {
237 return reinterpret_cast<Binding*>(bindingArrayAndFlag_ & ~TEMPORARY_STORAGE_BIT);
240 inline Bindings();
243 * Initialize a Bindings with a pointer into temporary storage.
244 * bindingArray must have length numArgs + numVars +
245 * numBodyLevelLexicals. Before the temporary storage is release,
246 * switchToScriptStorage must be called, providing a pointer into the
247 * Binding array stored in script->data.
249 static bool initWithTemporaryStorage(ExclusiveContext* cx, InternalBindingsHandle self,
250 uint32_t numArgs, uint32_t numVars,
251 uint32_t numBodyLevelLexicals, uint32_t numBlockScoped,
252 uint32_t numUnaliasedVars, uint32_t numUnaliasedBodyLevelLexicals,
253 Binding* bindingArray);
255 // CompileScript parses and compiles one statement at a time, but the result
256 // is one Script object. There will be no vars or bindings, because those
257 // go on the global, but there may be block-scoped locals, and the number of
258 // block-scoped locals may increase as we parse more expressions. This
259 // helper updates the number of block scoped variables in a script as it is
260 // being parsed.
261 void updateNumBlockScoped(unsigned numBlockScoped) {
262 MOZ_ASSERT(!callObjShape_);
263 MOZ_ASSERT(numVars_ == 0);
264 MOZ_ASSERT(numBlockScoped < LOCALNO_LIMIT);
265 MOZ_ASSERT(numBlockScoped >= numBlockScoped_);
266 numBlockScoped_ = numBlockScoped;
269 void setAllLocalsAliased() {
270 numBlockScoped_ = 0;
273 uint8_t* switchToScriptStorage(Binding* newStorage);
276 * Clone srcScript's bindings (as part of js::CloneScript). dstScriptData
277 * is the pointer to what will eventually be dstScript->data.
279 static bool clone(JSContext* cx, InternalBindingsHandle self, uint8_t* dstScriptData,
280 HandleScript srcScript);
282 uint32_t numArgs() const { return numArgs_; }
283 uint32_t numVars() const { return numVars_; }
284 uint32_t numBodyLevelLexicals() const { return numBodyLevelLexicals_; }
285 uint32_t numBlockScoped() const { return numBlockScoped_; }
286 uint32_t numBodyLevelLocals() const { return numVars_ + numBodyLevelLexicals_; }
287 uint32_t numUnaliasedBodyLevelLocals() const { return numUnaliasedVars_ + numUnaliasedBodyLevelLexicals_; }
288 uint32_t numAliasedBodyLevelLocals() const { return numBodyLevelLocals() - numUnaliasedBodyLevelLocals(); }
289 uint32_t numLocals() const { return numVars() + numBodyLevelLexicals() + numBlockScoped(); }
290 uint32_t numFixedLocals() const { return numUnaliasedVars() + numUnaliasedBodyLevelLexicals() + numBlockScoped(); }
291 uint32_t lexicalBegin() const { return numArgs() + numVars(); }
292 uint32_t aliasedBodyLevelLexicalBegin() const { return aliasedBodyLevelLexicalBegin_; }
294 uint32_t numUnaliasedVars() const { return numUnaliasedVars_; }
295 uint32_t numUnaliasedBodyLevelLexicals() const { return numUnaliasedBodyLevelLexicals_; }
297 // Return the size of the bindingArray.
298 uint32_t count() const { return numArgs() + numVars() + numBodyLevelLexicals(); }
300 /* Return the initial shape of call objects created for this scope. */
301 Shape* callObjShape() const { return callObjShape_; }
303 /* Convenience method to get the var index of 'arguments'. */
304 static BindingIter argumentsBinding(ExclusiveContext* cx, InternalBindingsHandle);
306 /* Return whether the binding at bindingIndex is aliased. */
307 bool bindingIsAliased(uint32_t bindingIndex);
309 /* Return whether this scope has any aliased bindings. */
310 bool hasAnyAliasedBindings() const {
311 if (!callObjShape_)
312 return false;
314 return !callObjShape_->isEmptyShape();
317 static js::ThingRootKind rootKind() { return js::THING_ROOT_BINDINGS; }
318 void trace(JSTracer* trc);
321 template <>
322 struct GCMethods<Bindings> {
323 static Bindings initial();
324 static bool poisoned(const Bindings& bindings) {
325 return IsPoisonedPtr(bindings.callObjShape());
329 class ScriptCounts
331 friend class ::JSScript;
332 friend struct ScriptAndCounts;
335 * This points to a single block that holds an array of PCCounts followed
336 * by an array of doubles. Each element in the PCCounts array has a
337 * pointer into the array of doubles.
339 PCCounts* pcCountsVector;
341 /* Information about any Ion compilations for the script. */
342 jit::IonScriptCounts* ionCounts;
344 public:
345 ScriptCounts() : pcCountsVector(nullptr), ionCounts(nullptr) { }
347 inline void destroy(FreeOp* fop);
349 void set(js::ScriptCounts counts) {
350 pcCountsVector = counts.pcCountsVector;
351 ionCounts = counts.ionCounts;
355 typedef HashMap<JSScript*,
356 ScriptCounts,
357 DefaultHasher<JSScript*>,
358 SystemAllocPolicy> ScriptCountsMap;
360 class DebugScript
362 friend class ::JSScript;
365 * When non-zero, compile script in single-step mode. The top bit is set and
366 * cleared by setStepMode, as used by JSD. The lower bits are a count,
367 * adjusted by changeStepModeCount, used by the Debugger object. Only
368 * when the bit is clear and the count is zero may we compile the script
369 * without single-step support.
371 uint32_t stepMode;
374 * Number of breakpoint sites at opcodes in the script. This is the number
375 * of populated entries in DebugScript::breakpoints, below.
377 uint32_t numSites;
380 * Breakpoints set in our script. For speed and simplicity, this array is
381 * parallel to script->code(): the BreakpointSite for the opcode at
382 * script->code()[offset] is debugScript->breakpoints[offset]. Naturally,
383 * this array's true length is script->length().
385 BreakpointSite* breakpoints[1];
388 typedef HashMap<JSScript*,
389 DebugScript*,
390 DefaultHasher<JSScript*>,
391 SystemAllocPolicy> DebugScriptMap;
393 class ScriptSource;
395 class UncompressedSourceCache
397 typedef HashMap<ScriptSource*,
398 const char16_t*,
399 DefaultHasher<ScriptSource*>,
400 SystemAllocPolicy> Map;
402 public:
403 // Hold an entry in the source data cache and prevent it from being purged on GC.
404 class AutoHoldEntry
406 UncompressedSourceCache* cache_;
407 ScriptSource* source_;
408 const char16_t* charsToFree_;
409 public:
410 explicit AutoHoldEntry();
411 ~AutoHoldEntry();
412 private:
413 void holdEntry(UncompressedSourceCache* cache, ScriptSource* source);
414 void deferDelete(const char16_t* chars);
415 ScriptSource* source() const { return source_; }
416 friend class UncompressedSourceCache;
419 private:
420 Map* map_;
421 AutoHoldEntry* holder_;
423 public:
424 UncompressedSourceCache() : map_(nullptr), holder_(nullptr) {}
426 const char16_t* lookup(ScriptSource* ss, AutoHoldEntry& asp);
427 bool put(ScriptSource* ss, const char16_t* chars, AutoHoldEntry& asp);
429 void purge();
431 size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
433 private:
434 void holdEntry(AutoHoldEntry& holder, ScriptSource* ss);
435 void releaseEntry(AutoHoldEntry& holder);
438 class ScriptSource
440 friend struct SourceCompressionTask;
442 uint32_t refs;
444 // Note: while ScriptSources may be compressed off thread, they are only
445 // modified by the main thread, and all members are always safe to access
446 // on the main thread.
448 // Indicate which field in the |data| union is active.
449 enum {
450 DataMissing,
451 DataUncompressed,
452 DataCompressed,
453 DataParent
454 } dataType;
456 union {
457 struct {
458 const char16_t* chars;
459 bool ownsChars;
460 } uncompressed;
462 struct {
463 void* raw;
464 size_t nbytes;
465 HashNumber hash;
466 } compressed;
468 ScriptSource* parent;
469 } data;
471 uint32_t length_;
473 // The filename of this script.
474 mozilla::UniquePtr<char[], JS::FreePolicy> filename_;
476 mozilla::UniquePtr<char16_t[], JS::FreePolicy> displayURL_;
477 mozilla::UniquePtr<char16_t[], JS::FreePolicy> sourceMapURL_;
478 bool mutedErrors_;
480 // bytecode offset in caller script that generated this code.
481 // This is present for eval-ed code, as well as "new Function(...)"-introduced
482 // scripts.
483 uint32_t introductionOffset_;
485 // If this ScriptSource was generated by a code-introduction mechanism such
486 // as |eval| or |new Function|, the debugger needs access to the "raw"
487 // filename of the top-level script that contains the eval-ing code. To
488 // keep track of this, we must preserve the original outermost filename (of
489 // the original introducer script), so that instead of a filename of
490 // "foo.js line 30 > eval line 10 > Function", we can obtain the original
491 // raw filename of "foo.js".
493 // In the case described above, this field will be non-null and will be the
494 // original raw filename from above. Otherwise this field will be null.
495 mozilla::UniquePtr<char[], JS::FreePolicy> introducerFilename_;
497 // A string indicating how this source code was introduced into the system.
498 // This accessor returns one of the following values:
499 // "eval" for code passed to |eval|.
500 // "Function" for code passed to the |Function| constructor.
501 // "Worker" for code loaded by calling the Web worker constructor&mdash;the worker's main script.
502 // "importScripts" for code by calling |importScripts| in a web worker.
503 // "handler" for code assigned to DOM elements' event handler IDL attributes.
504 // "scriptElement" for code belonging to <script> elements.
505 // undefined if the implementation doesn't know how the code was introduced.
506 // This is a constant, statically allocated C string, so does not need
507 // memory management.
508 const char* introductionType_;
510 // True if we can call JSRuntime::sourceHook to load the source on
511 // demand. If sourceRetrievable_ and hasSourceData() are false, it is not
512 // possible to get source at all.
513 bool sourceRetrievable_:1;
514 bool argumentsNotIncluded_:1;
515 bool hasIntroductionOffset_:1;
517 // Whether this is in the runtime's set of compressed ScriptSources.
518 bool inCompressedSourceSet:1;
520 public:
521 explicit ScriptSource()
522 : refs(0),
523 dataType(DataMissing),
524 length_(0),
525 filename_(nullptr),
526 displayURL_(nullptr),
527 sourceMapURL_(nullptr),
528 mutedErrors_(false),
529 introductionOffset_(0),
530 introducerFilename_(nullptr),
531 introductionType_(nullptr),
532 sourceRetrievable_(false),
533 argumentsNotIncluded_(false),
534 hasIntroductionOffset_(false),
535 inCompressedSourceSet(false)
538 ~ScriptSource();
539 void incref() { refs++; }
540 void decref() {
541 MOZ_ASSERT(refs != 0);
542 if (--refs == 0)
543 js_delete(this);
545 bool initFromOptions(ExclusiveContext* cx, const ReadOnlyCompileOptions& options);
546 bool setSourceCopy(ExclusiveContext* cx,
547 JS::SourceBufferHolder& srcBuf,
548 bool argumentsNotIncluded,
549 SourceCompressionTask* tok);
550 void setSourceRetrievable() { sourceRetrievable_ = true; }
551 bool sourceRetrievable() const { return sourceRetrievable_; }
552 bool hasSourceData() const { return dataType != DataMissing; }
553 bool hasCompressedSource() const { return dataType == DataCompressed; }
554 size_t length() const {
555 MOZ_ASSERT(hasSourceData());
556 return length_;
558 bool argumentsNotIncluded() const {
559 MOZ_ASSERT(hasSourceData());
560 return argumentsNotIncluded_;
562 const char16_t* chars(JSContext* cx, UncompressedSourceCache::AutoHoldEntry& asp);
563 JSFlatString* substring(JSContext* cx, uint32_t start, uint32_t stop);
564 JSFlatString* substringDontDeflate(JSContext* cx, uint32_t start, uint32_t stop);
565 void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
566 JS::ScriptSourceInfo* info) const;
568 const char16_t* uncompressedChars() const {
569 MOZ_ASSERT(dataType == DataUncompressed);
570 return data.uncompressed.chars;
573 bool ownsUncompressedChars() const {
574 MOZ_ASSERT(dataType == DataUncompressed);
575 return data.uncompressed.ownsChars;
578 void* compressedData() const {
579 MOZ_ASSERT(dataType == DataCompressed);
580 return data.compressed.raw;
583 size_t compressedBytes() const {
584 MOZ_ASSERT(dataType == DataCompressed);
585 return data.compressed.nbytes;
588 HashNumber compressedHash() const {
589 MOZ_ASSERT(dataType == DataCompressed);
590 return data.compressed.hash;
593 ScriptSource* parent() const {
594 MOZ_ASSERT(dataType == DataParent);
595 return data.parent;
598 void setSource(const char16_t* chars, size_t length, bool ownsChars = true);
599 void setCompressedSource(JSRuntime* maybert, void* raw, size_t nbytes, HashNumber hash);
600 void updateCompressedSourceSet(JSRuntime* rt);
601 bool ensureOwnsSource(ExclusiveContext* cx);
603 // XDR handling
604 template <XDRMode mode>
605 bool performXDR(XDRState<mode>* xdr);
607 bool setFilename(ExclusiveContext* cx, const char* filename);
608 const char* introducerFilename() const {
609 return introducerFilename_ ? introducerFilename_.get() : filename_.get();
611 bool hasIntroductionType() const {
612 return introductionType_;
614 const char* introductionType() const {
615 MOZ_ASSERT(hasIntroductionType());
616 return introductionType_;
618 const char* filename() const {
619 return filename_.get();
622 // Display URLs
623 bool setDisplayURL(ExclusiveContext* cx, const char16_t* displayURL);
624 bool hasDisplayURL() const { return displayURL_ != nullptr; }
625 const char16_t * displayURL() {
626 MOZ_ASSERT(hasDisplayURL());
627 return displayURL_.get();
630 // Source maps
631 bool setSourceMapURL(ExclusiveContext* cx, const char16_t* sourceMapURL);
632 bool hasSourceMapURL() const { return sourceMapURL_ != nullptr; }
633 const char16_t * sourceMapURL() {
634 MOZ_ASSERT(hasSourceMapURL());
635 return sourceMapURL_.get();
638 bool mutedErrors() const { return mutedErrors_; }
640 bool hasIntroductionOffset() const { return hasIntroductionOffset_; }
641 uint32_t introductionOffset() const {
642 MOZ_ASSERT(hasIntroductionOffset());
643 return introductionOffset_;
645 void setIntroductionOffset(uint32_t offset) {
646 MOZ_ASSERT(!hasIntroductionOffset());
647 MOZ_ASSERT(offset <= (uint32_t)INT32_MAX);
648 introductionOffset_ = offset;
649 hasIntroductionOffset_ = true;
652 private:
653 size_t computedSizeOfData() const;
656 class ScriptSourceHolder
658 ScriptSource* ss;
659 public:
660 explicit ScriptSourceHolder(ScriptSource* ss)
661 : ss(ss)
663 ss->incref();
665 ~ScriptSourceHolder()
667 ss->decref();
671 struct CompressedSourceHasher
673 typedef ScriptSource* Lookup;
675 static HashNumber computeHash(const void* data, size_t nbytes) {
676 return mozilla::HashBytes(data, nbytes);
679 static HashNumber hash(const ScriptSource* ss) {
680 return ss->compressedHash();
683 static bool match(const ScriptSource* a, const ScriptSource* b) {
684 return a->compressedBytes() == b->compressedBytes() &&
685 a->compressedHash() == b->compressedHash() &&
686 !memcmp(a->compressedData(), b->compressedData(), a->compressedBytes());
690 typedef HashSet<ScriptSource*, CompressedSourceHasher, SystemAllocPolicy> CompressedSourceSet;
692 class ScriptSourceObject : public NativeObject
694 public:
695 static const Class class_;
697 static void trace(JSTracer* trc, JSObject* obj);
698 static void finalize(FreeOp* fop, JSObject* obj);
699 static ScriptSourceObject* create(ExclusiveContext* cx, ScriptSource* source);
701 // Initialize those properties of this ScriptSourceObject whose values
702 // are provided by |options|, re-wrapping as necessary.
703 static bool initFromOptions(JSContext* cx, HandleScriptSource source,
704 const ReadOnlyCompileOptions& options);
706 ScriptSource* source() const {
707 return static_cast<ScriptSource*>(getReservedSlot(SOURCE_SLOT).toPrivate());
709 JSObject* element() const {
710 return getReservedSlot(ELEMENT_SLOT).toObjectOrNull();
712 const Value& elementAttributeName() const {
713 MOZ_ASSERT(!getReservedSlot(ELEMENT_PROPERTY_SLOT).isMagic());
714 return getReservedSlot(ELEMENT_PROPERTY_SLOT);
716 JSScript* introductionScript() const {
717 if (getReservedSlot(INTRODUCTION_SCRIPT_SLOT).isUndefined())
718 return nullptr;
719 void* untyped = getReservedSlot(INTRODUCTION_SCRIPT_SLOT).toPrivate();
720 MOZ_ASSERT(untyped);
721 return static_cast<JSScript*>(untyped);
724 private:
725 static const uint32_t SOURCE_SLOT = 0;
726 static const uint32_t ELEMENT_SLOT = 1;
727 static const uint32_t ELEMENT_PROPERTY_SLOT = 2;
728 static const uint32_t INTRODUCTION_SCRIPT_SLOT = 3;
729 static const uint32_t RESERVED_SLOTS = 4;
732 enum GeneratorKind { NotGenerator, LegacyGenerator, StarGenerator };
734 static inline unsigned
735 GeneratorKindAsBits(GeneratorKind generatorKind) {
736 return static_cast<unsigned>(generatorKind);
739 static inline GeneratorKind
740 GeneratorKindFromBits(unsigned val) {
741 MOZ_ASSERT(val <= StarGenerator);
742 return static_cast<GeneratorKind>(val);
746 * NB: after a successful XDR_DECODE, XDRScript callers must do any required
747 * subsequent set-up of owning function or script object and then call
748 * js_CallNewScriptHook.
750 template<XDRMode mode>
751 bool
752 XDRScript(XDRState<mode>* xdr, HandleObject enclosingScope, HandleScript enclosingScript,
753 HandleFunction fun, MutableHandleScript scriptp);
755 JSScript*
756 CloneScript(JSContext* cx, HandleObject enclosingScope, HandleFunction fun, HandleScript script,
757 NewObjectKind newKind = GenericObject);
759 template<XDRMode mode>
760 bool
761 XDRLazyScript(XDRState<mode>* xdr, HandleObject enclosingScope, HandleScript enclosingScript,
762 HandleFunction fun, MutableHandle<LazyScript*> lazy);
765 * Code any constant value.
767 template<XDRMode mode>
768 bool
769 XDRScriptConst(XDRState<mode>* xdr, MutableHandleValue vp);
771 } /* namespace js */
773 class JSScript : public js::gc::TenuredCell
775 template <js::XDRMode mode>
776 friend
777 bool
778 js::XDRScript(js::XDRState<mode>* xdr, js::HandleObject enclosingScope, js::HandleScript enclosingScript,
779 js::HandleFunction fun, js::MutableHandleScript scriptp);
781 friend JSScript*
782 js::CloneScript(JSContext* cx, js::HandleObject enclosingScope, js::HandleFunction fun, js::HandleScript src,
783 js::NewObjectKind newKind);
785 public:
787 // We order fields according to their size in order to avoid wasting space
788 // for alignment.
791 // Larger-than-word-sized fields.
793 public:
794 js::Bindings bindings; /* names of top-level variables in this script
795 (and arguments if this is a function script) */
797 bool hasAnyAliasedBindings() const {
798 return bindings.hasAnyAliasedBindings();
801 js::Binding* bindingArray() const {
802 return bindings.bindingArray();
805 unsigned numArgs() const {
806 return bindings.numArgs();
809 js::Shape* callObjShape() const {
810 return bindings.callObjShape();
813 // Word-sized fields.
815 private:
816 jsbytecode* code_; /* bytecodes and their immediate operands */
817 public:
818 uint8_t* data; /* pointer to variable-length data array (see
819 comment above Create() for details) */
821 js::HeapPtrAtom* atoms; /* maps immediate index to literal struct */
823 JSCompartment* compartment_;
825 private:
826 /* Persistent type information retained across GCs. */
827 js::types::TypeScript* types_;
829 // This script's ScriptSourceObject, or a CCW thereof.
831 // (When we clone a JSScript into a new compartment, we don't clone its
832 // source object. Instead, the clone refers to a wrapper.)
833 js::HeapPtrObject sourceObject_;
835 js::HeapPtrFunction function_;
837 // For callsite clones, which cannot have enclosing scopes, the original
838 // function; otherwise the enclosing scope
839 js::HeapPtrObject enclosingScopeOrOriginalFunction_;
841 /* Information attached by Baseline/Ion for sequential mode execution. */
842 js::jit::IonScript* ion;
843 js::jit::BaselineScript* baseline;
845 /* Information attached by Ion for parallel mode execution */
846 js::jit::IonScript* parallelIon;
848 /* Information used to re-lazify a lazily-parsed interpreted function. */
849 js::LazyScript* lazyScript;
852 * Pointer to either baseline->method()->raw() or ion->method()->raw(), or
853 * nullptr if there's no Baseline or Ion script.
855 uint8_t* baselineOrIonRaw;
856 uint8_t* baselineOrIonSkipArgCheck;
858 // 32-bit fields.
860 uint32_t length_; /* length of code vector */
861 uint32_t dataSize_; /* size of the used part of the data array */
863 uint32_t lineno_; /* base line number of script */
864 uint32_t column_; /* base column of script, optionally set */
866 uint32_t mainOffset_;/* offset of main entry point from code, after
867 predef'ing prolog */
869 uint32_t natoms_; /* length of atoms array */
870 uint32_t nslots_; /* vars plus maximum stack depth */
872 /* Range of characters in scriptSource which contains this script's source. */
873 uint32_t sourceStart_;
874 uint32_t sourceEnd_;
876 uint32_t warmUpCount; /* Number of times the script has been called
877 * or has had backedges taken. When running in
878 * ion, also increased for any inlined scripts.
879 * Reset if the script's JIT code is forcibly
880 * discarded. */
882 #ifdef DEBUG
883 // Unique identifier within the compartment for this script, used for
884 // printing analysis information.
885 uint32_t id_;
886 uint32_t idpad;
887 #endif
889 // 16-bit fields.
891 uint16_t version; /* JS version under which script was compiled */
893 uint16_t funLength_; /* ES6 function length */
895 uint16_t nTypeSets_; /* number of type sets used in this script for
896 dynamic type monitoring */
898 uint16_t staticLevel_;/* static level for display maintenance */
900 // Bit fields.
902 public:
903 // The kinds of the optional arrays.
904 enum ArrayKind {
905 CONSTS,
906 OBJECTS,
907 REGEXPS,
908 TRYNOTES,
909 BLOCK_SCOPES,
910 ARRAY_KIND_BITS
913 private:
914 // The bits in this field indicate the presence/non-presence of several
915 // optional arrays in |data|. See the comments above Create() for details.
916 uint8_t hasArrayBits:ARRAY_KIND_BITS;
918 // The GeneratorKind of the script.
919 uint8_t generatorKindBits_:2;
921 // 1-bit fields.
923 // No need for result value of last expression statement.
924 bool noScriptRval_:1;
926 // Can call getCallerFunction().
927 bool savedCallerFun_:1;
929 // Code is in strict mode.
930 bool strict_:1;
932 // Code has "use strict"; explicitly.
933 bool explicitUseStrict_:1;
935 // See Parser::compileAndGo.
936 bool compileAndGo_:1;
938 // see Parser::selfHostingMode.
939 bool selfHosted_:1;
941 // See FunctionContextFlags.
942 bool bindingsAccessedDynamically_:1;
943 bool funHasExtensibleScope_:1;
944 bool funNeedsDeclEnvObject_:1;
946 // True if any formalIsAliased(i).
947 bool funHasAnyAliasedFormal_:1;
949 // Have warned about uses of undefined properties in this script.
950 bool warnedAboutUndefinedProp_:1;
952 // Script has singleton objects.
953 bool hasSingletons_:1;
955 // Script is a lambda to treat as running once.
956 bool treatAsRunOnce_:1;
958 // If treatAsRunOnce, whether script has executed.
959 bool hasRunOnce_:1;
961 // Script has been reused for a clone.
962 bool hasBeenCloned_:1;
964 // Script came from eval(), and is still active.
965 bool isActiveEval_:1;
967 // Script came from eval(), and is in eval cache.
968 bool isCachedEval_:1;
970 // Set for functions defined at the top level within an 'eval' script.
971 bool directlyInsideEval_:1;
973 // 'this', 'arguments' and f.apply() are used. This is likely to be a wrapper.
974 bool usesArgumentsApplyAndThis_:1;
976 /* script is attempted to be cloned anew at each callsite. This is
977 temporarily needed for ParallelArray selfhosted code until type
978 information can be made context sensitive. See discussion in
979 bug 826148. */
980 bool shouldCloneAtCallsite_:1;
981 bool isCallsiteClone_:1; /* is a callsite clone; has a link to the original function */
982 bool shouldInline_:1; /* hint to inline when possible */
984 // IonMonkey compilation hints.
985 bool failedBoundsCheck_:1; /* script has had hoisted bounds checks fail */
986 bool failedShapeGuard_:1; /* script has had hoisted shape guard fail */
987 bool hadFrequentBailouts_:1;
988 bool uninlineable_:1; /* explicitly marked as uninlineable */
990 // Idempotent cache has triggered invalidation.
991 bool invalidatedIdempotentCache_:1;
993 // If the generator was created implicitly via a generator expression,
994 // isGeneratorExp will be true.
995 bool isGeneratorExp_:1;
997 // Script has an entry in JSCompartment::scriptCountsMap.
998 bool hasScriptCounts_:1;
1000 // Script has an entry in JSCompartment::debugScriptMap.
1001 bool hasDebugScript_:1;
1003 // Freeze constraints for stack type sets have been generated.
1004 bool hasFreezeConstraints_:1;
1006 /* See comments below. */
1007 bool argsHasVarBinding_:1;
1008 bool needsArgsAnalysis_:1;
1009 bool needsArgsObj_:1;
1011 // Generation for this script's TypeScript. If out of sync with the
1012 // TypeZone's generation, the TypeScript needs to be swept.
1014 // This should be a uint32 but is instead a bool so that MSVC packs it
1015 // correctly.
1016 bool typesGeneration_:1;
1019 // End of fields. Start methods.
1022 public:
1023 static JSScript* Create(js::ExclusiveContext* cx,
1024 js::HandleObject enclosingScope, bool savedCallerFun,
1025 const JS::ReadOnlyCompileOptions& options, unsigned staticLevel,
1026 js::HandleObject sourceObject, uint32_t sourceStart,
1027 uint32_t sourceEnd);
1029 void initCompartment(js::ExclusiveContext* cx);
1031 // Three ways ways to initialize a JSScript. Callers of partiallyInit()
1032 // and fullyInitTrivial() are responsible for notifying the debugger after
1033 // successfully creating any kind (function or other) of new JSScript.
1034 // However, callers of fullyInitFromEmitter() do not need to do this.
1035 static bool partiallyInit(js::ExclusiveContext* cx, JS::Handle<JSScript*> script,
1036 uint32_t nconsts, uint32_t nobjects, uint32_t nregexps,
1037 uint32_t ntrynotes, uint32_t nblockscopes, uint32_t nyieldoffsets,
1038 uint32_t nTypeSets);
1039 static bool fullyInitFromEmitter(js::ExclusiveContext* cx, JS::Handle<JSScript*> script,
1040 js::frontend::BytecodeEmitter* bce);
1041 // Initialize a no-op script.
1042 static bool fullyInitTrivial(js::ExclusiveContext* cx, JS::Handle<JSScript*> script);
1044 inline JSPrincipals* principals();
1046 JSCompartment* compartment() const { return compartment_; }
1048 void setVersion(JSVersion v) { version = v; }
1050 // Script bytecode is immutable after creation.
1051 jsbytecode* code() const {
1052 return code_;
1054 size_t length() const {
1055 return length_;
1058 void setCode(jsbytecode* code) { code_ = code; }
1059 void setLength(size_t length) { length_ = length; }
1061 jsbytecode* codeEnd() const { return code() + length(); }
1063 bool containsPC(const jsbytecode* pc) const {
1064 return pc >= code() && pc < codeEnd();
1067 size_t pcToOffset(const jsbytecode* pc) const {
1068 MOZ_ASSERT(containsPC(pc));
1069 return size_t(pc - code());
1072 jsbytecode* offsetToPC(size_t offset) const {
1073 MOZ_ASSERT(offset < length());
1074 return code() + offset;
1077 size_t mainOffset() const {
1078 return mainOffset_;
1081 size_t lineno() const {
1082 return lineno_;
1085 size_t column() const {
1086 return column_;
1089 void setColumn(size_t column) { column_ = column; }
1091 // The fixed part of a stack frame is comprised of vars (in function code)
1092 // and block-scoped locals (in all kinds of code).
1093 size_t nfixed() const {
1094 return function_ ? bindings.numFixedLocals() : bindings.numBlockScoped();
1097 // Number of fixed slots reserved for vars. Only nonzero for function
1098 // code.
1099 size_t nfixedvars() const {
1100 return function_ ? bindings.numUnaliasedVars() : 0;
1103 // Number of fixed slots reserved for body-level lexicals and vars. This
1104 // value minus nfixedvars() is the number of body-level lexicals. Only
1105 // nonzero for function code.
1106 size_t nbodyfixed() const {
1107 return function_ ? bindings.numUnaliasedBodyLevelLocals() : 0;
1110 // Aliases for clarity when dealing with lexical slots.
1111 size_t fixedLexicalBegin() const {
1112 return nfixedvars();
1115 size_t fixedLexicalEnd() const {
1116 return nfixed();
1119 size_t nslots() const {
1120 return nslots_;
1123 size_t staticLevel() const {
1124 return staticLevel_;
1127 size_t nTypeSets() const {
1128 return nTypeSets_;
1131 size_t funLength() const {
1132 return funLength_;
1135 size_t sourceStart() const {
1136 return sourceStart_;
1139 size_t sourceEnd() const {
1140 return sourceEnd_;
1143 bool noScriptRval() const {
1144 return noScriptRval_;
1147 bool savedCallerFun() const { return savedCallerFun_; }
1149 bool strict() const {
1150 return strict_;
1153 bool explicitUseStrict() const { return explicitUseStrict_; }
1155 bool compileAndGo() const {
1156 return compileAndGo_;
1159 bool selfHosted() const { return selfHosted_; }
1160 bool bindingsAccessedDynamically() const { return bindingsAccessedDynamically_; }
1161 bool funHasExtensibleScope() const {
1162 return funHasExtensibleScope_;
1164 bool funNeedsDeclEnvObject() const {
1165 return funNeedsDeclEnvObject_;
1167 bool funHasAnyAliasedFormal() const {
1168 return funHasAnyAliasedFormal_;
1171 bool hasSingletons() const { return hasSingletons_; }
1172 bool treatAsRunOnce() const {
1173 return treatAsRunOnce_;
1175 bool hasRunOnce() const { return hasRunOnce_; }
1176 bool hasBeenCloned() const { return hasBeenCloned_; }
1178 void setTreatAsRunOnce() { treatAsRunOnce_ = true; }
1179 void setHasRunOnce() { hasRunOnce_ = true; }
1180 void setHasBeenCloned() { hasBeenCloned_ = true; }
1182 bool isActiveEval() const { return isActiveEval_; }
1183 bool isCachedEval() const { return isCachedEval_; }
1184 bool directlyInsideEval() const { return directlyInsideEval_; }
1186 void cacheForEval() {
1187 MOZ_ASSERT(isActiveEval() && !isCachedEval());
1188 isActiveEval_ = false;
1189 isCachedEval_ = true;
1192 void uncacheForEval() {
1193 MOZ_ASSERT(isCachedEval() && !isActiveEval());
1194 isCachedEval_ = false;
1195 isActiveEval_ = true;
1198 void setActiveEval() { isActiveEval_ = true; }
1199 void setDirectlyInsideEval() { directlyInsideEval_ = true; }
1201 bool usesArgumentsApplyAndThis() const {
1202 return usesArgumentsApplyAndThis_;
1204 void setUsesArgumentsApplyAndThis() { usesArgumentsApplyAndThis_ = true; }
1206 bool shouldCloneAtCallsite() const {
1207 return shouldCloneAtCallsite_;
1209 bool shouldInline() const {
1210 return shouldInline_;
1213 void setShouldCloneAtCallsite() { shouldCloneAtCallsite_ = true; }
1214 void setShouldInline() { shouldInline_ = true; }
1216 bool isCallsiteClone() const {
1217 return isCallsiteClone_;
1219 bool isGeneratorExp() const { return isGeneratorExp_; }
1221 bool failedBoundsCheck() const {
1222 return failedBoundsCheck_;
1224 bool failedShapeGuard() const {
1225 return failedShapeGuard_;
1227 bool hadFrequentBailouts() const {
1228 return hadFrequentBailouts_;
1230 bool uninlineable() const {
1231 return uninlineable_;
1233 bool invalidatedIdempotentCache() const {
1234 return invalidatedIdempotentCache_;
1237 void setFailedBoundsCheck() { failedBoundsCheck_ = true; }
1238 void setFailedShapeGuard() { failedShapeGuard_ = true; }
1239 void setHadFrequentBailouts() { hadFrequentBailouts_ = true; }
1240 void setUninlineable() { uninlineable_ = true; }
1241 void setInvalidatedIdempotentCache() { invalidatedIdempotentCache_ = true; }
1243 bool hasScriptCounts() const { return hasScriptCounts_; }
1245 bool hasFreezeConstraints() const { return hasFreezeConstraints_; }
1246 void setHasFreezeConstraints() { hasFreezeConstraints_ = true; }
1248 bool warnedAboutUndefinedProp() const { return warnedAboutUndefinedProp_; }
1249 void setWarnedAboutUndefinedProp() { warnedAboutUndefinedProp_ = true; }
1251 /* See ContextFlags::funArgumentsHasLocalBinding comment. */
1252 bool argumentsHasVarBinding() const {
1253 return argsHasVarBinding_;
1255 jsbytecode* argumentsBytecode() const { MOZ_ASSERT(code()[0] == JSOP_ARGUMENTS); return code(); }
1256 void setArgumentsHasVarBinding();
1257 bool argumentsAliasesFormals() const {
1258 return argumentsHasVarBinding() && !strict();
1261 js::GeneratorKind generatorKind() const {
1262 return js::GeneratorKindFromBits(generatorKindBits_);
1264 bool isGenerator() const { return generatorKind() != js::NotGenerator; }
1265 bool isLegacyGenerator() const { return generatorKind() == js::LegacyGenerator; }
1266 bool isStarGenerator() const { return generatorKind() == js::StarGenerator; }
1267 void setGeneratorKind(js::GeneratorKind kind) {
1268 // A script only gets its generator kind set as part of initialization,
1269 // so it can only transition from not being a generator.
1270 MOZ_ASSERT(!isGenerator());
1271 generatorKindBits_ = GeneratorKindAsBits(kind);
1275 * As an optimization, even when argsHasLocalBinding, the function prologue
1276 * may not need to create an arguments object. This is determined by
1277 * needsArgsObj which is set by AnalyzeArgumentsUsage. When !needsArgsObj,
1278 * the prologue may simply write MagicValue(JS_OPTIMIZED_ARGUMENTS) to
1279 * 'arguments's slot and any uses of 'arguments' will be guaranteed to
1280 * handle this magic value. To avoid spurious arguments object creation, we
1281 * maintain the invariant that needsArgsObj is only called after the script
1282 * has been analyzed.
1284 bool analyzedArgsUsage() const { return !needsArgsAnalysis_; }
1285 inline bool ensureHasAnalyzedArgsUsage(JSContext* cx);
1286 bool needsArgsObj() const {
1287 MOZ_ASSERT(analyzedArgsUsage());
1288 return needsArgsObj_;
1290 void setNeedsArgsObj(bool needsArgsObj);
1291 static bool argumentsOptimizationFailed(JSContext* cx, js::HandleScript script);
1294 * Arguments access (via JSOP_*ARG* opcodes) must access the canonical
1295 * location for the argument. If an arguments object exists AND this is a
1296 * non-strict function (where 'arguments' aliases formals), then all access
1297 * must go through the arguments object. Otherwise, the local slot is the
1298 * canonical location for the arguments. Note: if a formal is aliased
1299 * through the scope chain, then script->formalIsAliased and JSOP_*ARG*
1300 * opcodes won't be emitted at all.
1302 bool argsObjAliasesFormals() const {
1303 return needsArgsObj() && !strict();
1306 uint32_t typesGeneration() const {
1307 return (uint32_t) typesGeneration_;
1310 void setTypesGeneration(uint32_t generation) {
1311 MOZ_ASSERT(generation <= 1);
1312 typesGeneration_ = (bool) generation;
1315 bool hasAnyIonScript() const {
1316 return hasIonScript() || hasParallelIonScript();
1319 bool hasIonScript() const {
1320 bool res = ion && ion != ION_DISABLED_SCRIPT && ion != ION_COMPILING_SCRIPT;
1321 MOZ_ASSERT_IF(res, baseline);
1322 return res;
1324 bool canIonCompile() const {
1325 return ion != ION_DISABLED_SCRIPT;
1328 bool isIonCompilingOffThread() const {
1329 return ion == ION_COMPILING_SCRIPT;
1332 js::jit::IonScript* ionScript() const {
1333 MOZ_ASSERT(hasIonScript());
1334 return ion;
1336 js::jit::IonScript* maybeIonScript() const {
1337 return ion;
1339 js::jit::IonScript* const* addressOfIonScript() const {
1340 return &ion;
1342 void setIonScript(JSContext* maybecx, js::jit::IonScript* ionScript) {
1343 if (hasIonScript())
1344 js::jit::IonScript::writeBarrierPre(zone(), ion);
1345 ion = ionScript;
1346 MOZ_ASSERT_IF(hasIonScript(), hasBaselineScript());
1347 updateBaselineOrIonRaw(maybecx);
1350 bool hasBaselineScript() const {
1351 bool res = baseline && baseline != BASELINE_DISABLED_SCRIPT;
1352 MOZ_ASSERT_IF(!res, !ion || ion == ION_DISABLED_SCRIPT);
1353 return res;
1355 bool canBaselineCompile() const {
1356 return baseline != BASELINE_DISABLED_SCRIPT;
1358 js::jit::BaselineScript* baselineScript() const {
1359 MOZ_ASSERT(hasBaselineScript());
1360 return baseline;
1362 inline void setBaselineScript(JSContext* maybecx, js::jit::BaselineScript* baselineScript);
1364 void updateBaselineOrIonRaw(JSContext* maybecx);
1366 void setPendingIonBuilder(JSContext* maybecx, js::jit::IonBuilder* builder) {
1367 MOZ_ASSERT(!builder || !ion->pendingBuilder());
1368 ion->setPendingBuilderPrivate(builder);
1369 updateBaselineOrIonRaw(maybecx);
1371 js::jit::IonBuilder* pendingIonBuilder() {
1372 MOZ_ASSERT(hasIonScript());
1373 return ion->pendingBuilder();
1376 bool hasParallelIonScript() const {
1377 return parallelIon && parallelIon != ION_DISABLED_SCRIPT && parallelIon != ION_COMPILING_SCRIPT;
1380 bool canParallelIonCompile() const {
1381 return parallelIon != ION_DISABLED_SCRIPT;
1384 bool isParallelIonCompilingOffThread() const {
1385 return parallelIon == ION_COMPILING_SCRIPT;
1388 js::jit::IonScript* parallelIonScript() const {
1389 MOZ_ASSERT(hasParallelIonScript());
1390 return parallelIon;
1392 js::jit::IonScript* maybeParallelIonScript() const {
1393 return parallelIon;
1395 void setParallelIonScript(js::jit::IonScript* ionScript) {
1396 if (hasParallelIonScript())
1397 js::jit::IonScript::writeBarrierPre(zone(), parallelIon);
1398 parallelIon = ionScript;
1401 static size_t offsetOfBaselineScript() {
1402 return offsetof(JSScript, baseline);
1404 static size_t offsetOfIonScript() {
1405 return offsetof(JSScript, ion);
1407 static size_t offsetOfParallelIonScript() {
1408 return offsetof(JSScript, parallelIon);
1410 static size_t offsetOfBaselineOrIonRaw() {
1411 return offsetof(JSScript, baselineOrIonRaw);
1413 uint8_t* baselineOrIonRawPointer() const {
1414 return baselineOrIonRaw;
1416 static size_t offsetOfBaselineOrIonSkipArgCheck() {
1417 return offsetof(JSScript, baselineOrIonSkipArgCheck);
1420 bool isRelazifiable() const {
1421 return (selfHosted() || lazyScript) && !types_ &&
1422 !isGenerator() && !hasBaselineScript() && !hasAnyIonScript();
1424 void setLazyScript(js::LazyScript* lazy) {
1425 lazyScript = lazy;
1427 js::LazyScript* maybeLazyScript() {
1428 return lazyScript;
1432 * Original compiled function for the script, if it has a function.
1433 * nullptr for global and eval scripts.
1434 * The delazifying variant ensures that the function isn't lazy. The
1435 * non-delazifying variant must only be used after earlier code has
1436 * called ensureNonLazyCanonicalFunction and while the function can't
1437 * have been relazified.
1439 inline JSFunction* functionDelazifying() const;
1440 JSFunction* functionNonDelazifying() const {
1441 return function_;
1443 inline void setFunction(JSFunction* fun);
1445 * De-lazifies the canonical function. Must be called before entering code
1446 * that expects the function to be non-lazy.
1448 inline void ensureNonLazyCanonicalFunction(JSContext* cx);
1451 * Donor provided itself to callsite clone; null if this is non-clone.
1453 JSFunction* donorFunction() const;
1454 void setIsCallsiteClone(JSObject* fun);
1456 JSFlatString* sourceData(JSContext* cx);
1458 static bool loadSource(JSContext* cx, js::ScriptSource* ss, bool* worked);
1460 void setSourceObject(JSObject* object);
1461 JSObject* sourceObject() const {
1462 return sourceObject_;
1464 js::ScriptSourceObject& scriptSourceUnwrap() const;
1465 js::ScriptSource* scriptSource() const;
1466 js::ScriptSource* maybeForwardedScriptSource() const;
1467 bool mutedErrors() const { return scriptSource()->mutedErrors(); }
1468 const char* filename() const { return scriptSource()->filename(); }
1469 const char* maybeForwardedFilename() const { return maybeForwardedScriptSource()->filename(); }
1471 public:
1473 /* Return whether this script was compiled for 'eval' */
1474 bool isForEval() { return isCachedEval() || isActiveEval(); }
1476 #ifdef DEBUG
1477 unsigned id();
1478 #else
1479 unsigned id() { return 0; }
1480 #endif
1482 /* Ensure the script has a TypeScript. */
1483 inline bool ensureHasTypes(JSContext* cx);
1485 inline js::types::TypeScript* types();
1487 void maybeSweepTypes(js::types::AutoClearTypeInferenceStateOnOOM* oom);
1489 inline js::GlobalObject& global() const;
1490 js::GlobalObject& uninlinedGlobal() const;
1492 /* See StaticScopeIter comment. */
1493 JSObject* enclosingStaticScope() const {
1494 if (isCallsiteClone())
1495 return nullptr;
1496 return enclosingScopeOrOriginalFunction_;
1499 private:
1500 bool makeTypes(JSContext* cx);
1502 public:
1503 uint32_t getWarmUpCount() const {
1504 return warmUpCount;
1506 uint32_t incWarmUpCounter(uint32_t amount = 1) { return warmUpCount += amount; }
1507 uint32_t* addressOfWarmUpCounter() { return &warmUpCount; }
1508 static size_t offsetOfWarmUpCounter() { return offsetof(JSScript, warmUpCount); }
1509 void resetWarmUpCounter() { warmUpCount = 0; }
1511 public:
1512 bool initScriptCounts(JSContext* cx);
1513 js::PCCounts getPCCounts(jsbytecode* pc);
1514 void addIonCounts(js::jit::IonScriptCounts* ionCounts);
1515 js::jit::IonScriptCounts* getIonCounts();
1516 js::ScriptCounts releaseScriptCounts();
1517 void destroyScriptCounts(js::FreeOp* fop);
1519 jsbytecode* main() {
1520 return code() + mainOffset();
1524 * computedSizeOfData() is the in-use size of all the data sections.
1525 * sizeOfData() is the size of the block allocated to hold all the data
1526 * sections (which can be larger than the in-use size).
1528 size_t computedSizeOfData() const;
1529 size_t sizeOfData(mozilla::MallocSizeOf mallocSizeOf) const;
1530 size_t sizeOfTypeScript(mozilla::MallocSizeOf mallocSizeOf) const;
1532 uint32_t numNotes(); /* Number of srcnote slots in the srcnotes section */
1534 /* Script notes are allocated right after the code. */
1535 jssrcnote* notes() { return (jssrcnote*)(code() + length()); }
1537 bool hasArray(ArrayKind kind) {
1538 return hasArrayBits & (1 << kind);
1540 void setHasArray(ArrayKind kind) { hasArrayBits |= (1 << kind); }
1541 void cloneHasArray(JSScript* script) { hasArrayBits = script->hasArrayBits; }
1543 bool hasConsts() { return hasArray(CONSTS); }
1544 bool hasObjects() { return hasArray(OBJECTS); }
1545 bool hasRegexps() { return hasArray(REGEXPS); }
1546 bool hasTrynotes() { return hasArray(TRYNOTES); }
1547 bool hasBlockScopes() { return hasArray(BLOCK_SCOPES); }
1548 bool hasYieldOffsets() { return isGenerator(); }
1550 #define OFF(fooOff, hasFoo, t) (fooOff() + (hasFoo() ? sizeof(t) : 0))
1552 size_t constsOffset() { return 0; }
1553 size_t objectsOffset() { return OFF(constsOffset, hasConsts, js::ConstArray); }
1554 size_t regexpsOffset() { return OFF(objectsOffset, hasObjects, js::ObjectArray); }
1555 size_t trynotesOffset() { return OFF(regexpsOffset, hasRegexps, js::ObjectArray); }
1556 size_t blockScopesOffset() { return OFF(trynotesOffset, hasTrynotes, js::TryNoteArray); }
1557 size_t yieldOffsetsOffset() { return OFF(blockScopesOffset, hasBlockScopes, js::BlockScopeArray); }
1559 size_t dataSize() const { return dataSize_; }
1561 js::ConstArray* consts() {
1562 MOZ_ASSERT(hasConsts());
1563 return reinterpret_cast<js::ConstArray*>(data + constsOffset());
1566 js::ObjectArray* objects() {
1567 MOZ_ASSERT(hasObjects());
1568 return reinterpret_cast<js::ObjectArray*>(data + objectsOffset());
1571 js::ObjectArray* regexps() {
1572 MOZ_ASSERT(hasRegexps());
1573 return reinterpret_cast<js::ObjectArray*>(data + regexpsOffset());
1576 js::TryNoteArray* trynotes() {
1577 MOZ_ASSERT(hasTrynotes());
1578 return reinterpret_cast<js::TryNoteArray*>(data + trynotesOffset());
1581 js::BlockScopeArray* blockScopes() {
1582 MOZ_ASSERT(hasBlockScopes());
1583 return reinterpret_cast<js::BlockScopeArray*>(data + blockScopesOffset());
1586 js::YieldOffsetArray& yieldOffsets() {
1587 MOZ_ASSERT(hasYieldOffsets());
1588 return *reinterpret_cast<js::YieldOffsetArray*>(data + yieldOffsetsOffset());
1591 bool hasLoops();
1593 size_t natoms() const { return natoms_; }
1595 js::HeapPtrAtom& getAtom(size_t index) const {
1596 MOZ_ASSERT(index < natoms());
1597 return atoms[index];
1600 js::HeapPtrAtom& getAtom(jsbytecode* pc) const {
1601 MOZ_ASSERT(containsPC(pc) && containsPC(pc + sizeof(uint32_t)));
1602 return getAtom(GET_UINT32_INDEX(pc));
1605 js::PropertyName* getName(size_t index) {
1606 return getAtom(index)->asPropertyName();
1609 js::PropertyName* getName(jsbytecode* pc) const {
1610 MOZ_ASSERT(containsPC(pc) && containsPC(pc + sizeof(uint32_t)));
1611 return getAtom(GET_UINT32_INDEX(pc))->asPropertyName();
1614 js::NativeObject* getObject(size_t index) {
1615 js::ObjectArray* arr = objects();
1616 MOZ_ASSERT(index < arr->length);
1617 return arr->vector[index];
1620 size_t innerObjectsStart() {
1621 // The first object contains the caller if savedCallerFun is used.
1622 return savedCallerFun() ? 1 : 0;
1625 js::NativeObject* getObject(jsbytecode* pc) {
1626 MOZ_ASSERT(containsPC(pc) && containsPC(pc + sizeof(uint32_t)));
1627 return getObject(GET_UINT32_INDEX(pc));
1630 JSVersion getVersion() const {
1631 return JSVersion(version);
1634 inline JSFunction* getFunction(size_t index);
1635 inline JSFunction* getCallerFunction();
1636 inline JSFunction* functionOrCallerFunction();
1638 inline js::RegExpObject* getRegExp(size_t index);
1639 inline js::RegExpObject* getRegExp(jsbytecode* pc);
1641 const js::Value& getConst(size_t index) {
1642 js::ConstArray* arr = consts();
1643 MOZ_ASSERT(index < arr->length);
1644 return arr->vector[index];
1647 js::NestedScopeObject* getStaticScope(jsbytecode* pc);
1650 * The isEmpty method tells whether this script has code that computes any
1651 * result (not return value, result AKA normal completion value) other than
1652 * JSVAL_VOID, or any other effects.
1654 bool isEmpty() const {
1655 if (length() > 3)
1656 return false;
1658 jsbytecode* pc = code();
1659 if (noScriptRval() && JSOp(*pc) == JSOP_FALSE)
1660 ++pc;
1661 return JSOp(*pc) == JSOP_RETRVAL;
1664 bool bindingIsAliased(const js::BindingIter& bi);
1665 bool formalIsAliased(unsigned argSlot);
1666 bool formalLivesInArgumentsObject(unsigned argSlot);
1668 // Frontend-only.
1669 bool cookieIsAliased(const js::frontend::UpvarCookie& cookie);
1671 private:
1672 /* Change this->stepMode to |newValue|. */
1673 void setNewStepMode(js::FreeOp* fop, uint32_t newValue);
1675 bool ensureHasDebugScript(JSContext* cx);
1676 js::DebugScript* debugScript();
1677 js::DebugScript* releaseDebugScript();
1678 void destroyDebugScript(js::FreeOp* fop);
1680 public:
1681 bool hasBreakpointsAt(jsbytecode* pc);
1682 bool hasAnyBreakpointsOrStepMode() { return hasDebugScript_; }
1684 // See comment above 'debugMode' in jscompartment.h for explanation of
1685 // invariants of debuggee compartments, scripts, and frames.
1686 inline bool isDebuggee() const;
1688 js::BreakpointSite* getBreakpointSite(jsbytecode* pc)
1690 return hasDebugScript_ ? debugScript()->breakpoints[pcToOffset(pc)] : nullptr;
1693 js::BreakpointSite* getOrCreateBreakpointSite(JSContext* cx, jsbytecode* pc);
1695 void destroyBreakpointSite(js::FreeOp* fop, jsbytecode* pc);
1697 void clearBreakpointsIn(js::FreeOp* fop, js::Debugger* dbg, JSObject* handler);
1700 * Increment or decrement the single-step count. If the count is non-zero
1701 * then the script is in single-step mode.
1703 * Only incrementing is fallible, as it could allocate a DebugScript.
1705 bool incrementStepModeCount(JSContext* cx);
1706 void decrementStepModeCount(js::FreeOp* fop);
1708 bool stepModeEnabled() { return hasDebugScript_ && !!debugScript()->stepMode; }
1710 #ifdef DEBUG
1711 uint32_t stepModeCount() { return hasDebugScript_ ? debugScript()->stepMode : 0; }
1712 #endif
1714 void finalize(js::FreeOp* fop);
1715 void fixupAfterMovingGC() {}
1717 static inline js::ThingRootKind rootKind() { return js::THING_ROOT_SCRIPT; }
1719 void markChildren(JSTracer* trc);
1722 /* If this fails, add/remove padding within JSScript. */
1723 static_assert(sizeof(JSScript) % js::gc::CellSize == 0,
1724 "Size of JSScript must be an integral multiple of js::gc::CellSize");
1726 namespace js {
1729 * Iterator over a script's bindings (formals and variables).
1730 * The order of iteration is:
1731 * - first, formal arguments, from index 0 to numArgs
1732 * - next, variables, from index 0 to numLocals
1734 class BindingIter
1736 const InternalBindingsHandle bindings_;
1737 uint32_t i_;
1738 uint32_t unaliasedLocal_;
1740 friend class ::JSScript;
1741 friend class Bindings;
1743 public:
1744 explicit BindingIter(const InternalBindingsHandle& bindings)
1745 : bindings_(bindings), i_(0), unaliasedLocal_(0) {}
1746 explicit BindingIter(const HandleScript& script)
1747 : bindings_(script, &script->bindings), i_(0), unaliasedLocal_(0) {}
1749 bool done() const { return i_ == bindings_->count(); }
1750 operator bool() const { return !done(); }
1751 BindingIter& operator++() { (*this)++; return *this; }
1753 void operator++(int) {
1754 MOZ_ASSERT(!done());
1755 const Binding& binding = **this;
1756 if (binding.kind() != Binding::ARGUMENT && !binding.aliased())
1757 unaliasedLocal_++;
1758 i_++;
1761 // Stack slots are assigned to arguments (aliased and unaliased) and
1762 // unaliased locals. frameIndex() returns the slot index. It's invalid to
1763 // call this method when the iterator is stopped on an aliased local, as it
1764 // has no stack slot.
1765 uint32_t frameIndex() const {
1766 MOZ_ASSERT(!done());
1767 if (i_ < bindings_->numArgs())
1768 return i_;
1769 MOZ_ASSERT(!(*this)->aliased());
1770 return unaliasedLocal_;
1773 // If the current binding is an argument, argIndex() returns its index.
1774 // It returns the same value as frameIndex(), as slots are allocated for
1775 // both unaliased and aliased arguments.
1776 uint32_t argIndex() const {
1777 MOZ_ASSERT(!done());
1778 MOZ_ASSERT(i_ < bindings_->numArgs());
1779 return i_;
1781 uint32_t argOrLocalIndex() const {
1782 MOZ_ASSERT(!done());
1783 return i_ < bindings_->numArgs() ? i_ : i_ - bindings_->numArgs();
1785 uint32_t localIndex() const {
1786 MOZ_ASSERT(!done());
1787 MOZ_ASSERT(i_ >= bindings_->numArgs());
1788 return i_ - bindings_->numArgs();
1790 bool isBodyLevelLexical() const {
1791 MOZ_ASSERT(!done());
1792 const Binding& binding = **this;
1793 return binding.kind() != Binding::ARGUMENT;
1796 const Binding& operator*() const { MOZ_ASSERT(!done()); return bindings_->bindingArray()[i_]; }
1797 const Binding* operator->() const { MOZ_ASSERT(!done()); return &bindings_->bindingArray()[i_]; }
1801 * Iterator over the aliased formal bindings in ascending index order. This can
1802 * be veiwed as a filtering of BindingIter with predicate
1803 * bi->aliased() && bi->kind() == Binding::ARGUMENT
1805 class AliasedFormalIter
1807 const Binding* begin_, *p_, *end_;
1808 unsigned slot_;
1810 void settle() {
1811 while (p_ != end_ && !p_->aliased())
1812 p_++;
1815 public:
1816 explicit inline AliasedFormalIter(JSScript* script);
1818 bool done() const { return p_ == end_; }
1819 operator bool() const { return !done(); }
1820 void operator++(int) { MOZ_ASSERT(!done()); p_++; slot_++; settle(); }
1822 const Binding& operator*() const { MOZ_ASSERT(!done()); return *p_; }
1823 const Binding* operator->() const { MOZ_ASSERT(!done()); return p_; }
1824 unsigned frameIndex() const { MOZ_ASSERT(!done()); return p_ - begin_; }
1825 unsigned scopeSlot() const { MOZ_ASSERT(!done()); return slot_; }
1828 // Information about a script which may be (or has been) lazily compiled to
1829 // bytecode from its source.
1830 class LazyScript : public gc::TenuredCell
1832 public:
1833 class FreeVariable
1835 // Free variable names are possible tagged JSAtom* s.
1836 uintptr_t bits_;
1838 static const uintptr_t HOISTED_USE_BIT = 0x1;
1839 static const uintptr_t MASK = ~HOISTED_USE_BIT;
1841 public:
1842 explicit FreeVariable()
1843 : bits_(0)
1846 explicit FreeVariable(JSAtom* name)
1847 : bits_(uintptr_t(name))
1849 // We rely on not requiring any write barriers so we can tag the
1850 // pointer. This code needs to change if we start allocating
1851 // JSAtoms inside the nursery.
1852 MOZ_ASSERT(!IsInsideNursery(name));
1855 JSAtom* atom() const { return (JSAtom*)(bits_ & MASK); }
1856 void setIsHoistedUse() { bits_ |= HOISTED_USE_BIT; }
1857 bool isHoistedUse() const { return bool(bits_ & HOISTED_USE_BIT); }
1860 private:
1861 // If non-nullptr, the script has been compiled and this is a forwarding
1862 // pointer to the result.
1863 HeapPtrScript script_;
1865 // Original function with which the lazy script is associated.
1866 HeapPtrFunction function_;
1868 // Function or block chain in which the script is nested, or nullptr.
1869 HeapPtrObject enclosingScope_;
1871 // ScriptSourceObject, or nullptr if the script in which this is nested
1872 // has not been compiled yet. This is never a CCW; we don't clone
1873 // LazyScripts into other compartments.
1874 HeapPtrObject sourceObject_;
1876 // Heap allocated table with any free variables or inner functions.
1877 void* table_;
1879 // Add padding so LazyScript is gc::Cell aligned. Make padding protected
1880 // instead of private to suppress -Wunused-private-field compiler warnings.
1881 protected:
1882 #if JS_BITS_PER_WORD == 32
1883 uint32_t padding;
1884 #endif
1885 private:
1887 struct PackedView {
1888 // Assorted bits that should really be in ScriptSourceObject.
1889 uint32_t version : 8;
1891 uint32_t numFreeVariables : 24;
1892 uint32_t numInnerFunctions : 23;
1894 uint32_t generatorKindBits : 2;
1896 // N.B. These are booleans but need to be uint32_t to pack correctly on MSVC.
1897 uint32_t strict : 1;
1898 uint32_t bindingsAccessedDynamically : 1;
1899 uint32_t hasDebuggerStatement : 1;
1900 uint32_t directlyInsideEval : 1;
1901 uint32_t usesArgumentsApplyAndThis : 1;
1902 uint32_t hasBeenCloned : 1;
1903 uint32_t treatAsRunOnce : 1;
1906 union {
1907 PackedView p_;
1908 uint64_t packedFields_;
1911 // Source location for the script.
1912 uint32_t begin_;
1913 uint32_t end_;
1914 uint32_t lineno_;
1915 uint32_t column_;
1917 LazyScript(JSFunction* fun, void* table, uint64_t packedFields,
1918 uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column);
1920 // Create a LazyScript without initializing the freeVariables and the
1921 // innerFunctions. To be GC-safe, the caller must initialize both vectors
1922 // with valid atoms and functions.
1923 static LazyScript* CreateRaw(ExclusiveContext* cx, HandleFunction fun,
1924 uint64_t packedData, uint32_t begin, uint32_t end,
1925 uint32_t lineno, uint32_t column);
1927 public:
1928 // Create a LazyScript without initializing the freeVariables and the
1929 // innerFunctions. To be GC-safe, the caller must initialize both vectors
1930 // with valid atoms and functions.
1931 static LazyScript* CreateRaw(ExclusiveContext* cx, HandleFunction fun,
1932 uint32_t numFreeVariables, uint32_t numInnerFunctions,
1933 JSVersion version, uint32_t begin, uint32_t end,
1934 uint32_t lineno, uint32_t column);
1936 // Create a LazyScript and initialize the freeVariables and the
1937 // innerFunctions with dummy values to be replaced in a later initialization
1938 // phase.
1939 static LazyScript* Create(ExclusiveContext* cx, HandleFunction fun,
1940 uint64_t packedData, uint32_t begin, uint32_t end,
1941 uint32_t lineno, uint32_t column);
1943 void initRuntimeFields(uint64_t packedFields);
1945 inline JSFunction* functionDelazifying(JSContext* cx) const;
1946 JSFunction* functionNonDelazifying() const {
1947 return function_;
1950 void initScript(JSScript* script);
1951 void resetScript();
1952 JSScript* maybeScript() {
1953 return script_;
1956 JSObject* enclosingScope() const {
1957 return enclosingScope_;
1959 ScriptSourceObject* sourceObject() const;
1960 ScriptSource* scriptSource() const {
1961 return sourceObject()->source();
1963 bool mutedErrors() const {
1964 return scriptSource()->mutedErrors();
1966 JSVersion version() const {
1967 JS_STATIC_ASSERT(JSVERSION_UNKNOWN == -1);
1968 return (p_.version == JS_BIT(8) - 1) ? JSVERSION_UNKNOWN : JSVersion(p_.version);
1971 void setParent(JSObject* enclosingScope, ScriptSourceObject* sourceObject);
1973 uint32_t numFreeVariables() const {
1974 return p_.numFreeVariables;
1976 FreeVariable* freeVariables() {
1977 return (FreeVariable*)table_;
1980 uint32_t numInnerFunctions() const {
1981 return p_.numInnerFunctions;
1983 HeapPtrFunction* innerFunctions() {
1984 return (HeapPtrFunction*)&freeVariables()[numFreeVariables()];
1987 GeneratorKind generatorKind() const { return GeneratorKindFromBits(p_.generatorKindBits); }
1989 bool isGenerator() const { return generatorKind() != NotGenerator; }
1991 bool isLegacyGenerator() const { return generatorKind() == LegacyGenerator; }
1993 bool isStarGenerator() const { return generatorKind() == StarGenerator; }
1995 void setGeneratorKind(GeneratorKind kind) {
1996 // A script only gets its generator kind set as part of initialization,
1997 // so it can only transition from NotGenerator.
1998 MOZ_ASSERT(!isGenerator());
1999 // Legacy generators cannot currently be lazy.
2000 MOZ_ASSERT(kind != LegacyGenerator);
2001 p_.generatorKindBits = GeneratorKindAsBits(kind);
2004 bool strict() const {
2005 return p_.strict;
2007 void setStrict() {
2008 p_.strict = true;
2011 bool bindingsAccessedDynamically() const {
2012 return p_.bindingsAccessedDynamically;
2014 void setBindingsAccessedDynamically() {
2015 p_.bindingsAccessedDynamically = true;
2018 bool hasDebuggerStatement() const {
2019 return p_.hasDebuggerStatement;
2021 void setHasDebuggerStatement() {
2022 p_.hasDebuggerStatement = true;
2025 bool directlyInsideEval() const {
2026 return p_.directlyInsideEval;
2028 void setDirectlyInsideEval() {
2029 p_.directlyInsideEval = true;
2032 bool usesArgumentsApplyAndThis() const {
2033 return p_.usesArgumentsApplyAndThis;
2035 void setUsesArgumentsApplyAndThis() {
2036 p_.usesArgumentsApplyAndThis = true;
2039 bool hasBeenCloned() const {
2040 return p_.hasBeenCloned;
2042 void setHasBeenCloned() {
2043 p_.hasBeenCloned = true;
2046 bool treatAsRunOnce() const {
2047 return p_.treatAsRunOnce;
2049 void setTreatAsRunOnce() {
2050 p_.treatAsRunOnce = true;
2053 ScriptSource* source() const {
2054 return sourceObject()->source();
2056 uint32_t begin() const {
2057 return begin_;
2059 uint32_t end() const {
2060 return end_;
2062 uint32_t lineno() const {
2063 return lineno_;
2065 uint32_t column() const {
2066 return column_;
2069 bool hasUncompiledEnclosingScript() const;
2070 uint32_t staticLevel(JSContext* cx) const;
2072 void markChildren(JSTracer* trc);
2073 void finalize(js::FreeOp* fop);
2074 void fixupAfterMovingGC() {}
2076 static inline js::ThingRootKind rootKind() { return js::THING_ROOT_LAZY_SCRIPT; }
2078 size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
2080 return mallocSizeOf(table_);
2083 uint64_t packedFields() const {
2084 return packedFields_;
2088 /* If this fails, add/remove padding within LazyScript. */
2089 JS_STATIC_ASSERT(sizeof(LazyScript) % js::gc::CellSize == 0);
2091 struct SharedScriptData
2093 uint32_t length;
2094 uint32_t natoms;
2095 bool marked;
2096 jsbytecode data[1];
2098 static SharedScriptData* new_(ExclusiveContext* cx, uint32_t codeLength,
2099 uint32_t srcnotesLength, uint32_t natoms);
2101 HeapPtrAtom* atoms() {
2102 if (!natoms)
2103 return nullptr;
2104 return reinterpret_cast<HeapPtrAtom*>(data + length - sizeof(JSAtom*) * natoms);
2107 static SharedScriptData* fromBytecode(const jsbytecode* bytecode) {
2108 return (SharedScriptData*)(bytecode - offsetof(SharedScriptData, data));
2111 private:
2112 SharedScriptData() = delete;
2113 SharedScriptData(const SharedScriptData&) = delete;
2116 struct ScriptBytecodeHasher
2118 struct Lookup
2120 jsbytecode* code;
2121 uint32_t length;
2123 explicit Lookup(SharedScriptData* ssd) : code(ssd->data), length(ssd->length) {}
2125 static HashNumber hash(const Lookup& l) { return mozilla::HashBytes(l.code, l.length); }
2126 static bool match(SharedScriptData* entry, const Lookup& lookup) {
2127 if (entry->length != lookup.length)
2128 return false;
2129 return mozilla::PodEqual<jsbytecode>(entry->data, lookup.code, lookup.length);
2133 typedef HashSet<SharedScriptData*,
2134 ScriptBytecodeHasher,
2135 SystemAllocPolicy> ScriptDataTable;
2137 extern void
2138 UnmarkScriptData(JSRuntime* rt);
2140 extern void
2141 SweepScriptData(JSRuntime* rt);
2143 extern void
2144 FreeScriptData(JSRuntime* rt);
2146 struct ScriptAndCounts
2148 /* This structure is stored and marked from the JSRuntime. */
2149 JSScript* script;
2150 ScriptCounts scriptCounts;
2152 PCCounts& getPCCounts(jsbytecode* pc) const {
2153 return scriptCounts.pcCountsVector[script->pcToOffset(pc)];
2156 jit::IonScriptCounts* getIonCounts() const {
2157 return scriptCounts.ionCounts;
2161 struct GSNCache;
2163 jssrcnote*
2164 GetSrcNote(GSNCache& cache, JSScript* script, jsbytecode* pc);
2166 } /* namespace js */
2168 extern jssrcnote*
2169 js_GetSrcNote(JSContext* cx, JSScript* script, jsbytecode* pc);
2171 extern jsbytecode*
2172 js_LineNumberToPC(JSScript* script, unsigned lineno);
2174 extern JS_FRIEND_API(unsigned)
2175 js_GetScriptLineExtent(JSScript* script);
2177 namespace js {
2179 extern unsigned
2180 PCToLineNumber(JSScript* script, jsbytecode* pc, unsigned* columnp = nullptr);
2182 extern unsigned
2183 PCToLineNumber(unsigned startLine, jssrcnote* notes, jsbytecode* code, jsbytecode* pc,
2184 unsigned* columnp = nullptr);
2187 * This function returns the file and line number of the script currently
2188 * executing on cx. If there is no current script executing on cx (e.g., a
2189 * native called directly through JSAPI (e.g., by setTimeout)), nullptr and 0
2190 * are returned as the file and line. Additionally, this function avoids the
2191 * full linear scan to compute line number when the caller guarantees that the
2192 * script compilation occurs at a JSOP_EVAL/JSOP_SPREADEVAL.
2195 enum LineOption {
2196 CALLED_FROM_JSOP_EVAL,
2197 NOT_CALLED_FROM_JSOP_EVAL
2200 extern void
2201 DescribeScriptedCallerForCompilation(JSContext* cx, MutableHandleScript maybeScript,
2202 const char** file, unsigned* linenop,
2203 uint32_t* pcOffset, bool* mutedErrors,
2204 LineOption opt = NOT_CALLED_FROM_JSOP_EVAL);
2206 bool
2207 CloneFunctionScript(JSContext* cx, HandleFunction original, HandleFunction clone,
2208 NewObjectKind newKind = GenericObject);
2210 } /* namespace js */
2212 // JS::ubi::Nodes can point to js::LazyScripts; they're js::gc::Cell instances
2213 // with no associated compartment.
2214 namespace JS {
2215 namespace ubi {
2216 template<> struct Concrete<js::LazyScript> : TracerConcrete<js::LazyScript> { };
2220 #endif /* jsscript_h */