| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476 |
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #ifndef jspubtd_h
- #define jspubtd_h
- /*
- * JS public API typedefs.
- */
- #include "mozilla/Assertions.h"
- #include "mozilla/EnumeratedArray.h"
- #include "mozilla/LinkedList.h"
- #include "mozilla/PodOperations.h"
- #include "jsprototypes.h"
- #include "jstypes.h"
- #include "js/TraceKind.h"
- #include "js/TypeDecls.h"
- #if defined(JS_GC_ZEAL) || defined(DEBUG)
- # define JSGC_HASH_TABLE_CHECKS
- #endif
- namespace JS {
- class AutoIdVector;
- class CallArgs;
- template <typename T>
- class Rooted;
- class JS_FRIEND_API(CompileOptions);
- class JS_FRIEND_API(ReadOnlyCompileOptions);
- class JS_FRIEND_API(OwningCompileOptions);
- class JS_FRIEND_API(TransitiveCompileOptions);
- class JS_PUBLIC_API(CompartmentOptions);
- struct RootingContext;
- class Value;
- struct Zone;
- namespace shadow {
- struct Runtime;
- } // namespace shadow
- } // namespace JS
- namespace js {
- class RootLists;
- } // namespace js
- /*
- * Run-time version enumeration. For compile-time version checking, please use
- * the JS_HAS_* macros in jsversion.h, or use MOZJS_MAJOR_VERSION,
- * MOZJS_MINOR_VERSION, MOZJS_PATCH_VERSION, and MOZJS_ALPHA definitions.
- */
- enum JSVersion {
- JSVERSION_ECMA_3 = 148,
- JSVERSION_1_6 = 160,
- JSVERSION_1_7 = 170,
- JSVERSION_1_8 = 180,
- JSVERSION_ECMA_5 = 185,
- JSVERSION_DEFAULT = 0,
- JSVERSION_UNKNOWN = -1,
- JSVERSION_LATEST = JSVERSION_ECMA_5
- };
- /* Result of typeof operator enumeration. */
- enum JSType {
- JSTYPE_VOID, /* undefined */
- JSTYPE_OBJECT, /* object */
- JSTYPE_FUNCTION, /* function */
- JSTYPE_STRING, /* string */
- JSTYPE_NUMBER, /* number */
- JSTYPE_BOOLEAN, /* boolean */
- JSTYPE_NULL, /* null */
- JSTYPE_SYMBOL, /* symbol */
- JSTYPE_LIMIT
- };
- /* Dense index into cached prototypes and class atoms for standard objects. */
- enum JSProtoKey {
- #define PROTOKEY_AND_INITIALIZER(name,code,init,clasp) JSProto_##name = code,
- JS_FOR_EACH_PROTOTYPE(PROTOKEY_AND_INITIALIZER)
- #undef PROTOKEY_AND_INITIALIZER
- JSProto_LIMIT
- };
- /* Struct forward declarations. */
- struct JSClass;
- struct JSCompartment;
- struct JSCrossCompartmentCall;
- class JSErrorReport;
- struct JSExceptionState;
- struct JSFunctionSpec;
- struct JSLocaleCallbacks;
- struct JSObjectMap;
- struct JSPrincipals;
- struct JSPropertyName;
- struct JSPropertySpec;
- struct JSRuntime;
- struct JSSecurityCallbacks;
- struct JSStructuredCloneCallbacks;
- struct JSStructuredCloneReader;
- struct JSStructuredCloneWriter;
- class JS_PUBLIC_API(JSTracer);
- class JSFlatString;
- typedef bool (*JSInitCallback)(void);
- template<typename T> struct JSConstScalarSpec;
- typedef JSConstScalarSpec<double> JSConstDoubleSpec;
- typedef JSConstScalarSpec<int32_t> JSConstIntegerSpec;
- /*
- * Generic trace operation that calls JS::TraceEdge on each traceable thing's
- * location reachable from data.
- */
- typedef void
- (* JSTraceDataOp)(JSTracer* trc, void* data);
- namespace js {
- namespace gc {
- class AutoTraceSession;
- class StoreBuffer;
- } // namespace gc
- // Whether the current thread is permitted access to any part of the specified
- // runtime or zone.
- JS_FRIEND_API(bool)
- CurrentThreadCanAccessRuntime(const JSRuntime* rt);
- #ifdef DEBUG
- JS_FRIEND_API(bool)
- CurrentThreadIsPerformingGC();
- #endif
- } // namespace js
- namespace JS {
- class JS_PUBLIC_API(AutoEnterCycleCollection);
- class JS_PUBLIC_API(AutoAssertOnBarrier);
- struct JS_PUBLIC_API(PropertyDescriptor);
- typedef void (*OffThreadCompileCallback)(void* token, void* callbackData);
- enum class HeapState {
- Idle, // doing nothing with the GC heap
- Tracing, // tracing the GC heap without collecting, e.g. IterateCompartments()
- MajorCollecting, // doing a GC of the major heap
- MinorCollecting, // doing a GC of the minor heap (nursery)
- CycleCollecting // in the "Unlink" phase of cycle collection
- };
- namespace shadow {
- struct Runtime
- {
- private:
- JS::HeapState heapState_;
- protected:
- void setHeapState(JS::HeapState newState) {
- MOZ_ASSERT(js::CurrentThreadCanAccessRuntime(asRuntime()));
- MOZ_ASSERT(heapState_ != newState);
- heapState_ = newState;
- }
- JS::HeapState heapState() const {
- MOZ_ASSERT(js::CurrentThreadCanAccessRuntime(asRuntime()) ||
- js::CurrentThreadIsPerformingGC());
- return heapState_;
- }
- // In some cases, invoking GC barriers (incremental or otherwise) will break
- // things. These barriers assert if this flag is set.
- bool allowGCBarriers_;
- friend class JS::AutoAssertOnBarrier;
- js::gc::StoreBuffer* gcStoreBufferPtr_;
- // The gray bits can become invalid if UnmarkGray overflows the stack. A
- // full GC will reset this bit, since it fills in all the gray bits.
- bool gcGrayBitsValid_;
- public:
- Runtime()
- : heapState_(JS::HeapState::Idle)
- , allowGCBarriers_(true)
- , gcStoreBufferPtr_(nullptr)
- , gcGrayBitsValid_(false)
- {}
- bool isHeapBusy() const { return heapState() != JS::HeapState::Idle; }
- bool isHeapTracing() const { return heapState() == JS::HeapState::Tracing; }
- bool isHeapMajorCollecting() const { return heapState() == JS::HeapState::MajorCollecting; }
- bool isHeapMinorCollecting() const { return heapState() == JS::HeapState::MinorCollecting; }
- bool isHeapCollecting() const { return isHeapMinorCollecting() || isHeapMajorCollecting(); }
- bool isCycleCollecting() const {
- return heapState() == JS::HeapState::CycleCollecting;
- }
- bool allowGCBarriers() const { return allowGCBarriers_; }
- js::gc::StoreBuffer* gcStoreBufferPtr() { return gcStoreBufferPtr_; }
- bool areGCGrayBitsValid() const { return gcGrayBitsValid_; }
- void setGCGrayBitsValid(bool valid) { gcGrayBitsValid_ = valid; }
- const JSRuntime* asRuntime() const {
- return reinterpret_cast<const JSRuntime*>(this);
- }
- static JS::shadow::Runtime* asShadowRuntime(JSRuntime* rt) {
- return reinterpret_cast<JS::shadow::Runtime*>(rt);
- }
- protected:
- void setGCStoreBufferPtr(js::gc::StoreBuffer* storeBuffer) {
- gcStoreBufferPtr_ = storeBuffer;
- }
- };
- } /* namespace shadow */
- // Decorates the Unlinking phase of CycleCollection so that accidental use
- // of barriered accessors results in assertions instead of leaks.
- class MOZ_STACK_CLASS JS_PUBLIC_API(AutoEnterCycleCollection)
- {
- #ifdef DEBUG
- JSRuntime* runtime;
- public:
- explicit AutoEnterCycleCollection(JSContext* cx);
- ~AutoEnterCycleCollection();
- #else
- public:
- explicit AutoEnterCycleCollection(JSContext* cx) {}
- ~AutoEnterCycleCollection() {}
- #endif
- };
- class JS_PUBLIC_API(AutoGCRooter)
- {
- public:
- AutoGCRooter(JSContext* cx, ptrdiff_t tag);
- AutoGCRooter(JS::RootingContext* cx, ptrdiff_t tag);
- ~AutoGCRooter() {
- MOZ_ASSERT(this == *stackTop);
- *stackTop = down;
- }
- /* Implemented in gc/RootMarking.cpp. */
- inline void trace(JSTracer* trc);
- static void traceAll(JSTracer* trc);
- static void traceAllWrappers(JSTracer* trc);
- protected:
- AutoGCRooter * const down;
- /*
- * Discriminates actual subclass of this being used. If non-negative, the
- * subclass roots an array of values of the length stored in this field.
- * If negative, meaning is indicated by the corresponding value in the enum
- * below. Any other negative value indicates some deeper problem such as
- * memory corruption.
- */
- ptrdiff_t tag_;
- enum {
- VALARRAY = -2, /* js::AutoValueArray */
- PARSER = -3, /* js::frontend::Parser */
- VALVECTOR = -10, /* js::AutoValueVector */
- IDVECTOR = -11, /* js::AutoIdVector */
- OBJVECTOR = -14, /* js::AutoObjectVector */
- IONMASM = -19, /* js::jit::MacroAssembler */
- WRAPVECTOR = -20, /* js::AutoWrapperVector */
- WRAPPER = -21, /* js::AutoWrapperRooter */
- CUSTOM = -26 /* js::CustomAutoRooter */
- };
- static ptrdiff_t GetTag(const Value& value) { return VALVECTOR; }
- static ptrdiff_t GetTag(const jsid& id) { return IDVECTOR; }
- static ptrdiff_t GetTag(JSObject* obj) { return OBJVECTOR; }
- private:
- AutoGCRooter ** const stackTop;
- /* No copy or assignment semantics. */
- AutoGCRooter(AutoGCRooter& ida) = delete;
- void operator=(AutoGCRooter& ida) = delete;
- };
- // Our instantiations of Rooted<void*> and PersistentRooted<void*> require an
- // instantiation of MapTypeToRootKind.
- template <>
- struct MapTypeToRootKind<void*> {
- static const RootKind kind = RootKind::Traceable;
- };
- } /* namespace JS */
- namespace js {
- class ExclusiveContext;
- /*
- * This list enumerates the different types of conceptual stacks we have in
- * SpiderMonkey. In reality, they all share the C stack, but we allow different
- * stack limits depending on the type of code running.
- */
- enum StackKind
- {
- StackForSystemCode, // C++, such as the GC, running on behalf of the VM.
- StackForTrustedScript, // Script running with trusted principals.
- StackForUntrustedScript, // Script running with untrusted principals.
- StackKindCount
- };
- using RootedListHeads = mozilla::EnumeratedArray<JS::RootKind, JS::RootKind::Limit,
- JS::Rooted<void*>*>;
- // Abstracts JS rooting mechanisms so they can be shared between the JSContext
- // and JSRuntime.
- class RootLists
- {
- // Stack GC roots for Rooted GC heap pointers.
- RootedListHeads stackRoots_;
- template <typename T> friend class JS::Rooted;
- // Stack GC roots for AutoFooRooter classes.
- JS::AutoGCRooter* autoGCRooters_;
- friend class JS::AutoGCRooter;
- // Heap GC roots for PersistentRooted pointers.
- mozilla::EnumeratedArray<JS::RootKind, JS::RootKind::Limit,
- mozilla::LinkedList<JS::PersistentRooted<void*>>> heapRoots_;
- template <typename T> friend class JS::PersistentRooted;
- public:
- RootLists() : autoGCRooters_(nullptr) {
- for (auto& stackRootPtr : stackRoots_)
- stackRootPtr = nullptr;
- }
- ~RootLists() {
- // The semantics of PersistentRooted containing pointers and tagged
- // pointers are somewhat different from those of PersistentRooted
- // containing a structure with a trace method. PersistentRooted
- // containing pointers are allowed to outlive the owning RootLists,
- // whereas those containing a traceable structure are not.
- //
- // The purpose of this feature is to support lazy initialization of
- // global references for the several places in Gecko that do not have
- // access to a tighter context, but that still need to refer to GC
- // pointers. For such pointers, FinishPersistentRootedChains ensures
- // that the contained references are nulled out when the owning
- // RootLists dies to prevent UAF errors.
- //
- // However, for RootKind::Traceable, we do not know the concrete type
- // of the held thing, so we simply cannot do this without accruing
- // extra overhead and complexity for all users for a case that is
- // unlikely to ever be used in practice. For this reason, the following
- // assertion disallows usage of PersistentRooted<Traceable> that
- // outlives the RootLists.
- MOZ_ASSERT(heapRoots_[JS::RootKind::Traceable].isEmpty());
- }
- void traceStackRoots(JSTracer* trc);
- void checkNoGCRooters();
- void tracePersistentRoots(JSTracer* trc);
- void finishPersistentRoots();
- };
- } // namespace js
- namespace JS {
- /*
- * JS::RootingContext is a base class of ContextFriendFields and JSContext.
- * This class can be used to let code construct a Rooted<> or PersistentRooted<>
- * instance, without giving it full access to the JSContext.
- */
- struct RootingContext
- {
- js::RootLists roots;
- #ifdef DEBUG
- // Whether the derived class is a JSContext or an ExclusiveContext.
- bool isJSContext;
- #endif
- explicit RootingContext(bool isJSContextArg)
- #ifdef DEBUG
- : isJSContext(isJSContextArg)
- #endif
- {}
- static RootingContext* get(JSContext* cx) {
- return reinterpret_cast<RootingContext*>(cx);
- }
- };
- } // namespace JS
- namespace js {
- struct ContextFriendFields : public JS::RootingContext
- {
- protected:
- /* The current compartment. */
- JSCompartment* compartment_;
- /* The current zone. */
- JS::Zone* zone_;
- public:
- /* Limit pointer for checking native stack consumption. */
- uintptr_t nativeStackLimit[js::StackKindCount];
- explicit ContextFriendFields(bool isJSContext);
- static const ContextFriendFields* get(const JSContext* cx) {
- return reinterpret_cast<const ContextFriendFields*>(cx);
- }
- static ContextFriendFields* get(JSContext* cx) {
- return reinterpret_cast<ContextFriendFields*>(cx);
- }
- friend JSCompartment* GetContextCompartment(const JSContext* cx);
- friend JS::Zone* GetContextZone(const JSContext* cx);
- template <typename T> friend class JS::Rooted;
- };
- /*
- * Inlinable accessors for JSContext.
- *
- * - These must not be available on the more restricted superclasses of
- * JSContext, so we can't simply define them on ContextFriendFields.
- *
- * - They're perfectly ordinary JSContext functionality, so ought to be
- * usable without resorting to jsfriendapi.h, and when JSContext is an
- * incomplete type.
- */
- inline JSCompartment*
- GetContextCompartment(const JSContext* cx)
- {
- return ContextFriendFields::get(cx)->compartment_;
- }
- inline JS::Zone*
- GetContextZone(const JSContext* cx)
- {
- return ContextFriendFields::get(cx)->zone_;
- }
- } /* namespace js */
- MOZ_BEGIN_EXTERN_C
- // Defined in NSPR prio.h.
- typedef struct PRFileDesc PRFileDesc;
- MOZ_END_EXTERN_C
- #endif /* jspubtd_h */
|