#ifndef vm_Runtime_h
#define vm_Runtime_h
#include "mozilla/Atomics.h"
#include "mozilla/Attributes.h"
#include "mozilla/DoublyLinkedList.h"
#include "mozilla/LinkedList.h"
#include "mozilla/Maybe.h"
#include "mozilla/MaybeOneOf.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/ThreadLocal.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/Vector.h"
#include <algorithm>
#include <setjmp.h>
#include "builtin/AtomicsObject.h"
#include "builtin/intl/SharedIntlData.h"
#include "builtin/Promise.h"
#include "frontend/BinASTRuntimeSupport.h"
#include "frontend/NameCollections.h"
#include "gc/GCRuntime.h"
#include "gc/Tracer.h"
#include "irregexp/RegExpStack.h"
#include "js/BuildId.h"
#include "js/Debug.h"
#include "js/GCVector.h"
#include "js/HashTable.h"
#ifdef DEBUG
# include "js/Proxy.h"
#endif
#include "js/Stream.h"
#include "js/Symbol.h"
#include "js/UniquePtr.h"
#include "js/Utility.h"
#include "js/Vector.h"
#include "threading/Thread.h"
#include "vm/Caches.h"
#include "vm/CodeCoverage.h"
#include "vm/CommonPropertyNames.h"
#include "vm/GeckoProfiler.h"
#include "vm/JSAtom.h"
#include "vm/JSScript.h"
#include "vm/Scope.h"
#include "vm/SharedImmutableStringsCache.h"
#include "vm/Stack.h"
#include "vm/SymbolType.h"
#include "wasm/WasmTypes.h"
namespace js {
class AutoAssertNoContentJS;
class AutoKeepAtoms;
class EnterDebuggeeNoExecute;
#ifdef JS_TRACE_LOGGING
class TraceLoggerThread;
#endif
namespace gc {
class AutoHeapSession;
}
}
struct DtoaState;
struct JSLocaleCallbacks;
#ifdef JS_SIMULATOR_ARM64
namespace vixl {
class Simulator;
}
#endif
namespace js {
extern MOZ_COLD void ReportOutOfMemory(JSContext* cx);
extern MOZ_COLD mozilla::GenericErrorResult<OOM&> ReportOutOfMemoryResult(
JSContext* cx);
extern MOZ_COLD void ReportAllocationOverflow(JSContext* maybecx);
extern MOZ_COLD void ReportOverRecursed(JSContext* cx);
class Activation;
class ActivationIterator;
namespace jit {
class JitRuntime;
class JitActivation;
struct PcScriptCache;
struct AutoFlushICache;
class CompileRuntime;
#ifdef JS_SIMULATOR_ARM64
typedef vixl::Simulator Simulator;
#elif defined(JS_SIMULATOR)
class Simulator;
#endif
}
}
namespace JS {
struct RuntimeSizes;
}
struct JSAtomState {
#define PROPERTYNAME_FIELD(idpart, id, text) js::ImmutablePropertyNamePtr id;
FOR_EACH_COMMON_PROPERTYNAME(PROPERTYNAME_FIELD)
#undef PROPERTYNAME_FIELD
#define PROPERTYNAME_FIELD(name, init, clasp) js::ImmutablePropertyNamePtr name;
JS_FOR_EACH_PROTOTYPE(PROPERTYNAME_FIELD)
#undef PROPERTYNAME_FIELD
#define PROPERTYNAME_FIELD(name) js::ImmutablePropertyNamePtr name;
JS_FOR_EACH_WELL_KNOWN_SYMBOL(PROPERTYNAME_FIELD)
#undef PROPERTYNAME_FIELD
#define PROPERTYNAME_FIELD(name) js::ImmutablePropertyNamePtr Symbol_##name;
JS_FOR_EACH_WELL_KNOWN_SYMBOL(PROPERTYNAME_FIELD)
#undef PROPERTYNAME_FIELD
js::ImmutablePropertyNamePtr* wellKnownSymbolNames() {
#define FIRST_PROPERTYNAME_FIELD(name) return &name;
JS_FOR_EACH_WELL_KNOWN_SYMBOL(FIRST_PROPERTYNAME_FIELD)
#undef FIRST_PROPERTYNAME_FIELD
}
js::ImmutablePropertyNamePtr* wellKnownSymbolDescriptions() {
#define FIRST_PROPERTYNAME_FIELD(name) return &Symbol_##name;
JS_FOR_EACH_WELL_KNOWN_SYMBOL(FIRST_PROPERTYNAME_FIELD)
#undef FIRST_PROPERTYNAME_FIELD
}
};
namespace js {
struct WellKnownSymbols {
#define DECLARE_SYMBOL(name) js::ImmutableSymbolPtr name;
JS_FOR_EACH_WELL_KNOWN_SYMBOL(DECLARE_SYMBOL)
#undef DECLARE_SYMBOL
const ImmutableSymbolPtr& get(size_t u) const {
MOZ_ASSERT(u < JS::WellKnownSymbolLimit);
const ImmutableSymbolPtr* symbols =
reinterpret_cast<const ImmutableSymbolPtr*>(this);
return symbols[u];
}
const ImmutableSymbolPtr& get(JS::SymbolCode code) const {
return get(size_t(code));
}
WellKnownSymbols() {}
WellKnownSymbols(const WellKnownSymbols&) = delete;
WellKnownSymbols& operator=(const WellKnownSymbols&) = delete;
};
#define NAME_OFFSET(name) offsetof(JSAtomState, name)
inline HandlePropertyName AtomStateOffsetToName(const JSAtomState& atomState,
size_t offset) {
return *reinterpret_cast<js::ImmutablePropertyNamePtr*>((char*)&atomState +
offset);
}
enum RuntimeLock { HelperThreadStateLock, GCLock };
inline bool CanUseExtraThreads() {
extern bool gCanUseExtraThreads;
return gCanUseExtraThreads;
}
void DisableExtraThreads();
using ScriptAndCountsVector = GCVector<ScriptAndCounts, 0, SystemAllocPolicy>;
class AutoLockScriptData;
}
struct JSRuntime : public js::MallocProvider<JSRuntime> {
private:
friend class js::Activation;
friend class js::ActivationIterator;
friend class js::jit::JitActivation;
friend class js::jit::CompileRuntime;
js::MainThreadData<js::InterpreterStack> interpreterStack_;
public:
js::InterpreterStack& interpreterStack() { return interpreterStack_.ref(); }
JSRuntime* const parentRuntime;
#ifdef DEBUG
mozilla::Atomic<size_t> childRuntimeCount;
class AutoUpdateChildRuntimeCount {
JSRuntime* parent_;
public:
explicit AutoUpdateChildRuntimeCount(JSRuntime* parent) : parent_(parent) {
if (parent_) {
parent_->childRuntimeCount++;
}
}
~AutoUpdateChildRuntimeCount() {
if (parent_) {
parent_->childRuntimeCount--;
}
}
};
AutoUpdateChildRuntimeCount updateChildRuntimeCount;
#endif
private:
#ifdef DEBUG
js::WriteOnceData<bool> initialized_;
#endif
JSContext* mainContext_;
public:
JSContext* mainContextFromAnyThread() const { return mainContext_; }
const void* addressOfMainContext() { return &mainContext_; }
inline JSContext* mainContextFromOwnThread();
mozilla::Atomic<uint64_t, mozilla::ReleaseAcquire,
mozilla::recordreplay::Behavior::DontPreserve>
profilerSampleBufferRangeStart_;
mozilla::Maybe<uint64_t> profilerSampleBufferRangeStart() {
if (beingDestroyed_ || !geckoProfiler().enabled()) {
return mozilla::Nothing();
}
uint64_t rangeStart = profilerSampleBufferRangeStart_;
return mozilla::Some(rangeStart);
}
void setProfilerSampleBufferRangeStart(uint64_t rangeStart) {
profilerSampleBufferRangeStart_ = rangeStart;
}
js::MainThreadData<JSAccumulateTelemetryDataCallback> telemetryCallback;
js::MainThreadData<JSSetUseCounterCallback> useCounterCallback;
public:
void addTelemetry(int id, uint32_t sample, const char* key = nullptr);
void setTelemetryCallback(JSRuntime* rt,
JSAccumulateTelemetryDataCallback callback);
void setUseCounter(JSObject* obj, JSUseCounter counter);
void setUseCounterCallback(JSRuntime* rt, JSSetUseCounterCallback callback);
public:
js::UnprotectedData<js::OffThreadPromiseRuntimeState> offThreadPromiseState;
js::UnprotectedData<JS::ConsumeStreamCallback> consumeStreamCallback;
js::UnprotectedData<JS::ReportStreamErrorCallback> reportStreamErrorCallback;
js::GlobalObject* getIncumbentGlobal(JSContext* cx);
bool enqueuePromiseJob(JSContext* cx, js::HandleFunction job,
js::HandleObject promise,
js::Handle<js::GlobalObject*> incumbentGlobal);
void addUnhandledRejectedPromise(JSContext* cx, js::HandleObject promise);
void removeUnhandledRejectedPromise(JSContext* cx, js::HandleObject promise);
mozilla::Atomic<bool, mozilla::SequentiallyConsistent,
mozilla::recordreplay::Behavior::DontPreserve>
hadOutOfMemory;
js::MainThreadData<bool> allowRelazificationForTesting;
js::MainThreadData<JSDestroyCompartmentCallback> destroyCompartmentCallback;
js::MainThreadData<JSSizeOfIncludingThisCompartmentCallback>
sizeOfIncludingThisCompartmentCallback;
void (*constructUbiNodeForDOMObjectCallback)(void*, JSObject*) = nullptr;
js::MainThreadData<JS::DestroyRealmCallback> destroyRealmCallback;
js::MainThreadData<JS::RealmNameCallback> realmNameCallback;
js::MainThreadData<JSExternalStringSizeofCallback>
externalStringSizeofCallback;
js::MainThreadData<mozilla::UniquePtr<js::SourceHook>> sourceHook;
js::MainThreadData<const JSSecurityCallbacks*> securityCallbacks;
js::MainThreadData<const js::DOMCallbacks*> DOMcallbacks;
js::MainThreadData<JSDestroyPrincipalsOp> destroyPrincipals;
js::MainThreadData<JSReadPrincipalsOp> readPrincipals;
js::MainThreadData<JS::WarningReporter> warningReporter;
private:
js::UnprotectedData<js::GeckoProfilerRuntime> geckoProfiler_;
public:
js::GeckoProfilerRuntime& geckoProfiler() { return geckoProfiler_.ref(); }
js::MainThreadData<mozilla::EnumeratedArray<
JS::RootKind, JS::RootKind::Limit,
mozilla::LinkedList<JS::PersistentRooted<void*>>>>
heapRoots;
void tracePersistentRoots(JSTracer* trc);
void finishPersistentRoots();
void finishRoots();
private:
js::UnprotectedData<const JSPrincipals*> trustedPrincipals_;
public:
void setTrustedPrincipals(const JSPrincipals* p) { trustedPrincipals_ = p; }
const JSPrincipals* trustedPrincipals() const { return trustedPrincipals_; }
js::MainThreadData<const JSWrapObjectCallbacks*> wrapObjectCallbacks;
js::MainThreadData<js::PreserveWrapperCallback> preserveWrapperCallback;
js::MainThreadData<js::ScriptEnvironmentPreparer*> scriptEnvironmentPreparer;
js::MainThreadData<js::CTypesActivityCallback> ctypesActivityCallback;
private:
js::WriteOnceData<const js::Class*> windowProxyClass_;
public:
const js::Class* maybeWindowProxyClass() const { return windowProxyClass_; }
void setWindowProxyClass(const js::Class* clasp) {
windowProxyClass_ = clasp;
}
private:
js::MainThreadData<mozilla::LinkedList<JS::detail::WeakCacheBase>>
weakCaches_;
public:
mozilla::LinkedList<JS::detail::WeakCacheBase>& weakCaches() {
return weakCaches_.ref();
}
void registerWeakCache(JS::detail::WeakCacheBase* cachep) {
weakCaches().insertBack(cachep);
}
template <typename T>
struct GlobalObjectWatchersLinkAccess {
static mozilla::DoublyLinkedListElement<T>& Get(T* aThis) {
return aThis->onNewGlobalObjectWatchersLink;
}
};
using WatchersList =
mozilla::DoublyLinkedList<js::Debugger,
GlobalObjectWatchersLinkAccess<js::Debugger>>;
private:
js::MainThreadData<WatchersList> onNewGlobalObjectWatchers_;
public:
WatchersList& onNewGlobalObjectWatchers() {
return onNewGlobalObjectWatchers_.ref();
}
private:
js::MainThreadData<mozilla::LinkedList<js::Debugger>> debuggerList_;
public:
mozilla::LinkedList<js::Debugger>& debuggerList() {
return debuggerList_.ref();
}
private:
js::Mutex scriptDataLock;
#ifdef DEBUG
bool activeThreadHasScriptDataAccess;
#endif
mozilla::Atomic<size_t, mozilla::SequentiallyConsistent,
mozilla::recordreplay::Behavior::DontPreserve>
numActiveHelperThreadZones;
mozilla::Atomic<JS::HeapState, mozilla::SequentiallyConsistent,
mozilla::recordreplay::Behavior::DontPreserve>
heapState_;
friend class js::AutoLockScriptData;
public:
void setUsedByHelperThread(JS::Zone* zone);
void clearUsedByHelperThread(JS::Zone* zone);
bool hasHelperThreadZones() const { return numActiveHelperThreadZones > 0; }
#ifdef DEBUG
bool currentThreadHasScriptDataAccess() const {
if (!hasHelperThreadZones()) {
return CurrentThreadCanAccessRuntime(this) &&
activeThreadHasScriptDataAccess;
}
return scriptDataLock.ownedByCurrentThread();
}
bool currentThreadHasAtomsTableAccess() const {
return CurrentThreadCanAccessRuntime(this) &&
atoms_->mainThreadHasAllLocks();
}
#endif
JS::HeapState heapState() const { return heapState_; }
js::MainThreadData<size_t> numRealms;
js::MainThreadData<const JSLocaleCallbacks*> localeCallbacks;
js::MainThreadData<js::UniqueChars> defaultLocale;
js::MainThreadOrIonCompileData<bool> profilingScripts;
js::MainThreadData<JS::PersistentRooted<js::ScriptAndCountsVector>*>
scriptAndCountsVector;
private:
js::UnprotectedData<js::coverage::LCovRuntime> lcovOutput_;
public:
js::coverage::LCovRuntime& lcovOutput() { return lcovOutput_.ref(); }
private:
js::UnprotectedData<js::jit::JitRuntime*> jitRuntime_;
js::WriteOnceData<js::NativeObject*> selfHostingGlobal_;
static js::GlobalObject* createSelfHostingGlobal(JSContext* cx);
bool getUnclonedSelfHostedValue(JSContext* cx, js::HandlePropertyName name,
js::MutableHandleValue vp);
JSFunction* getUnclonedSelfHostedFunction(JSContext* cx,
js::HandlePropertyName name);
public:
MOZ_MUST_USE bool createJitRuntime(JSContext* cx);
js::jit::JitRuntime* jitRuntime() const { return jitRuntime_.ref(); }
bool hasJitRuntime() const { return !!jitRuntime_; }
private:
mozilla::Maybe<mozilla::non_crypto::XorShift128PlusRNG> randomKeyGenerator_;
mozilla::non_crypto::XorShift128PlusRNG& randomKeyGenerator();
mozilla::Maybe<mozilla::non_crypto::XorShift128PlusRNG>
randomHashCodeGenerator_;
public:
mozilla::HashCodeScrambler randomHashCodeScrambler();
mozilla::non_crypto::XorShift128PlusRNG forkRandomKeyGenerator();
js::HashNumber randomHashCode();
bool hasInitializedSelfHosting() const { return selfHostingGlobal_; }
bool initSelfHosting(JSContext* cx);
void finishSelfHosting();
void traceSelfHostingGlobal(JSTracer* trc);
bool isSelfHostingGlobal(JSObject* global) {
return global == selfHostingGlobal_;
}
bool isSelfHostingZone(const JS::Zone* zone) const;
bool createLazySelfHostedFunctionClone(JSContext* cx,
js::HandlePropertyName selfHostedName,
js::HandleAtom name, unsigned nargs,
js::HandleObject proto,
js::NewObjectKind newKind,
js::MutableHandleFunction fun);
bool cloneSelfHostedFunctionScript(JSContext* cx,
js::Handle<js::PropertyName*> name,
js::Handle<JSFunction*> targetFun);
bool cloneSelfHostedValue(JSContext* cx, js::Handle<js::PropertyName*> name,
js::MutableHandleValue vp);
void assertSelfHostedFunctionHasCanonicalName(JSContext* cx,
js::HandlePropertyName name);
bool setDefaultLocale(const char* locale);
void resetDefaultLocale();
const char* getDefaultLocale();
js::gc::GCRuntime gc;
js::WriteOnceData<bool> gcInitialized;
bool hasZealMode(js::gc::ZealMode mode) { return gc.hasZealMode(mode); }
void lockGC() { gc.lockGC(); }
void unlockGC() { gc.unlockGC(); }
const js::Value NaNValue;
const js::Value negativeInfinityValue;
const js::Value positiveInfinityValue;
js::WriteOnceData<js::PropertyName*> emptyString;
private:
js::WriteOnceData<js::FreeOp*> defaultFreeOp_;
public:
js::FreeOp* defaultFreeOp() {
MOZ_ASSERT(defaultFreeOp_);
return defaultFreeOp_;
}
#if !EXPOSE_INTL_API
js::WriteOnceData<const char*> thousandsSeparator;
js::WriteOnceData<const char*> decimalSeparator;
js::WriteOnceData<const char*> numGrouping;
#endif
private:
mozilla::Maybe<js::SharedImmutableStringsCache> sharedImmutableStrings_;
public:
js::SharedImmutableStringsCache* maybeThisRuntimeSharedImmutableStrings() {
return sharedImmutableStrings_.isSome() ? &*sharedImmutableStrings_
: nullptr;
}
js::SharedImmutableStringsCache& sharedImmutableStrings() {
MOZ_ASSERT_IF(parentRuntime, !sharedImmutableStrings_);
MOZ_ASSERT_IF(!parentRuntime, sharedImmutableStrings_);
return parentRuntime ? parentRuntime->sharedImmutableStrings()
: *sharedImmutableStrings_;
}
private:
js::WriteOnceData<bool> beingDestroyed_;
public:
bool isBeingDestroyed() const { return beingDestroyed_; }
private:
bool allowContentJS_;
public:
bool allowContentJS() const { return allowContentJS_; }
friend class js::AutoAssertNoContentJS;
private:
js::WriteOnceData<js::AtomsTable*> atoms_;
js::MainThreadOrGCTaskData<js::SymbolRegistry> symbolRegistry_;
js::WriteOnceData<js::AtomSet*> permanentAtomsDuringInit_;
js::WriteOnceData<js::FrozenAtomSet*> permanentAtoms_;
public:
bool initializeAtoms(JSContext* cx);
void finishAtoms();
bool atomsAreFinished() const {
return !atoms_ && !permanentAtomsDuringInit_;
}
js::AtomsTable* atomsForSweeping() {
MOZ_ASSERT(JS::RuntimeHeapIsCollecting());
return atoms_;
}
js::AtomsTable& atoms() {
MOZ_ASSERT(atoms_);
return *atoms_;
}
const JS::Zone* atomsZone(const js::AutoAccessAtomsZone& access) const {
return gc.atomsZone;
}
JS::Zone* atomsZone(const js::AutoAccessAtomsZone& access) {
return gc.atomsZone;
}
JS::Zone* unsafeAtomsZone() { return gc.atomsZone; }
bool isAtomsZone(const JS::Zone* zone) const { return zone == gc.atomsZone; }
bool activeGCInAtomsZone();
js::SymbolRegistry& symbolRegistry() { return symbolRegistry_.ref(); }
js::WriteOnceData<js::StaticStrings*> staticStrings;
js::WriteOnceData<JSAtomState*> commonNames;
const js::FrozenAtomSet* permanentAtoms() const {
MOZ_ASSERT(permanentAtomsPopulated());
return permanentAtoms_.ref();
}
bool permanentAtomsPopulated() const { return permanentAtoms_; }
js::AtomSet* permanentAtomsDuringInit() const {
MOZ_ASSERT(!permanentAtoms_);
return permanentAtomsDuringInit_.ref();
}
bool initMainAtomsTables(JSContext* cx);
void tracePermanentAtoms(JSTracer* trc);
js::WriteOnceData<js::WellKnownSymbols*> wellKnownSymbols;
js::MainThreadData<js::intl::SharedIntlData> sharedIntlData;
void traceSharedIntlData(JSTracer* trc);
private:
js::ScriptDataLockData<js::ScriptDataTable> scriptDataTable_;
public:
js::ScriptDataTable& scriptDataTable(const js::AutoLockScriptData& lock) {
return scriptDataTable_.ref();
}
js::WriteOnceData<bool> jitSupportsFloatingPoint;
js::WriteOnceData<bool> jitSupportsUnalignedAccesses;
js::WriteOnceData<bool> jitSupportsSimd;
private:
static mozilla::Atomic<size_t> liveRuntimesCount;
public:
static bool hasLiveRuntimes() { return liveRuntimesCount > 0; }
explicit JSRuntime(JSRuntime* parentRuntime);
~JSRuntime();
void destroyRuntime();
bool init(JSContext* cx, uint32_t maxbytes, uint32_t maxNurseryBytes);
JSRuntime* thisFromCtor() { return this; }
public:
void updateMallocCounter(size_t nbytes);
void reportAllocationOverflow() { js::ReportAllocationOverflow(nullptr); }
JS_FRIEND_API void* onOutOfMemory(js::AllocFunction allocator,
arena_id_t arena, size_t nbytes,
void* reallocPtr = nullptr,
JSContext* maybecx = nullptr);
JS_FRIEND_API void* onOutOfMemoryCanGC(js::AllocFunction allocator,
arena_id_t arena, size_t nbytes,
void* reallocPtr = nullptr);
static const unsigned LARGE_ALLOCATION = 25 * 1024 * 1024;
void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
JS::RuntimeSizes* rtSizes);
private:
mozilla::Atomic<bool, mozilla::SequentiallyConsistent,
mozilla::recordreplay::Behavior::DontPreserve>
offthreadIonCompilationEnabled_;
mozilla::Atomic<bool, mozilla::SequentiallyConsistent,
mozilla::recordreplay::Behavior::DontPreserve>
parallelParsingEnabled_;
#ifdef DEBUG
mozilla::Atomic<uint32_t> offThreadParsesRunning_;
mozilla::Atomic<bool> offThreadParsingBlocked_;
#endif
js::MainThreadData<bool> autoWritableJitCodeActive_;
public:
void setOffthreadIonCompilationEnabled(bool value) {
offthreadIonCompilationEnabled_ = value;
}
bool canUseOffthreadIonCompilation() const {
return offthreadIonCompilationEnabled_;
}
void setParallelParsingEnabled(bool value) {
parallelParsingEnabled_ = value;
}
bool canUseParallelParsing() const { return parallelParsingEnabled_; }
#ifdef DEBUG
void incOffThreadParsesRunning() {
MOZ_ASSERT(!isOffThreadParsingBlocked());
offThreadParsesRunning_++;
}
void decOffThreadParsesRunning() {
MOZ_ASSERT(isOffThreadParseRunning());
offThreadParsesRunning_--;
}
bool isOffThreadParseRunning() const { return offThreadParsesRunning_; }
bool isOffThreadParsingBlocked() const { return offThreadParsingBlocked_; }
void setOffThreadParsingBlocked(bool blocked) {
MOZ_ASSERT(offThreadParsingBlocked_ != blocked);
MOZ_ASSERT(!isOffThreadParseRunning());
offThreadParsingBlocked_ = blocked;
}
#endif
void toggleAutoWritableJitCodeActive(bool b) {
MOZ_ASSERT(autoWritableJitCodeActive_ != b,
"AutoWritableJitCode should not be nested.");
autoWritableJitCodeActive_ = b;
}
js::MainThreadData<JS::OutOfMemoryCallback> oomCallback;
js::MainThreadData<void*> oomCallbackData;
js::MainThreadData<mozilla::MallocSizeOf> debuggerMallocSizeOf;
js::MainThreadData<mozilla::TimeStamp> lastAnimationTime;
private:
mozilla::Atomic<js::StackFormat, mozilla::ReleaseAcquire> stackFormat_;
public:
js::StackFormat stackFormat() const {
const JSRuntime* rt = this;
while (rt->parentRuntime) {
MOZ_ASSERT(rt->stackFormat_ == js::StackFormat::Default);
rt = rt->parentRuntime;
}
MOZ_ASSERT(rt->stackFormat_ != js::StackFormat::Default);
return rt->stackFormat_;
}
void setStackFormat(js::StackFormat format) {
MOZ_ASSERT(!parentRuntime);
MOZ_ASSERT(format != js::StackFormat::Default);
stackFormat_ = format;
}
friend class js::gc::AutoHeapSession;
friend class JS::AutoEnterCycleCollection;
private:
js::MainThreadData<js::RuntimeCaches> caches_;
public:
js::RuntimeCaches& caches() { return caches_.ref(); }
js::ExclusiveData<js::wasm::InstanceVector> wasmInstances;
js::MainThreadData<JS::ModuleResolveHook> moduleResolveHook;
js::MainThreadData<JS::ModuleMetadataHook> moduleMetadataHook;
mozilla::Atomic<JS::ModuleDynamicImportHook> moduleDynamicImportHook;
js::MainThreadData<JS::ScriptPrivateReferenceHook> scriptPrivateAddRefHook;
js::MainThreadData<JS::ScriptPrivateReferenceHook> scriptPrivateReleaseHook;
void addRefScriptPrivate(const JS::Value& value) {
if (!value.isUndefined() && scriptPrivateAddRefHook) {
scriptPrivateAddRefHook(value);
}
}
void releaseScriptPrivate(const JS::Value& value) {
if (!value.isUndefined() && scriptPrivateReleaseHook) {
scriptPrivateReleaseHook(value);
}
}
public:
#if defined(JS_BUILD_BINAST)
js::BinaryASTSupport& binast() { return binast_; }
private:
js::BinaryASTSupport binast_;
#endif
public:
#if defined(NIGHTLY_BUILD)
struct ErrorInterceptionSupport {
ErrorInterceptionSupport() : isExecuting(false), interceptor(nullptr) {}
bool isExecuting;
JSErrorInterceptor* interceptor;
};
ErrorInterceptionSupport errorInterception;
#endif };
namespace js {
static MOZ_ALWAYS_INLINE void MakeRangeGCSafe(Value* vec, size_t len) {
for (size_t i = 0; i < len; i++) {
vec[i].setDouble(+0.0);
}
}
static MOZ_ALWAYS_INLINE void MakeRangeGCSafe(Value* beg, Value* end) {
MakeRangeGCSafe(beg, end - beg);
}
static MOZ_ALWAYS_INLINE void MakeRangeGCSafe(jsid* beg, jsid* end) {
std::fill(beg, end, INT_TO_JSID(0));
}
static MOZ_ALWAYS_INLINE void MakeRangeGCSafe(jsid* vec, size_t len) {
MakeRangeGCSafe(vec, vec + len);
}
static MOZ_ALWAYS_INLINE void MakeRangeGCSafe(Shape** beg, Shape** end) {
std::fill(beg, end, nullptr);
}
static MOZ_ALWAYS_INLINE void MakeRangeGCSafe(Shape** vec, size_t len) {
MakeRangeGCSafe(vec, vec + len);
}
static MOZ_ALWAYS_INLINE void SetValueRangeToUndefined(Value* beg, Value* end) {
for (Value* v = beg; v != end; ++v) {
v->setUndefined();
}
}
static MOZ_ALWAYS_INLINE void SetValueRangeToUndefined(Value* vec, size_t len) {
SetValueRangeToUndefined(vec, vec + len);
}
static MOZ_ALWAYS_INLINE void SetValueRangeToNull(Value* beg, Value* end) {
for (Value* v = beg; v != end; ++v) {
v->setNull();
}
}
static MOZ_ALWAYS_INLINE void SetValueRangeToNull(Value* vec, size_t len) {
SetValueRangeToNull(vec, vec + len);
}
extern const JSSecurityCallbacks NullSecurityCallbacks;
extern mozilla::Atomic<JS::LargeAllocationFailureCallback>
OnLargeAllocationFailure;
extern mozilla::Atomic<JS::BuildIdOp> GetBuildId;
}
#endif