/* -*- 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/LinkedList.h" #include "mozilla/PodOperations.h" #include "jsprototypes.h" #include "jstypes.h" #include "js/TypeDecls.h" #if defined(JS_GC_ZEAL) || defined(DEBUG) # define JSGC_HASH_TABLE_CHECKS #endif namespace JS { template class AutoVectorRooter; typedef AutoVectorRooter AutoIdVector; class CallArgs; template 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); class Value; struct Zone; } /* namespace JS */ namespace js { struct ContextFriendFields; 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 JSPropertyDescriptor; struct JSPropertyName; struct JSPropertySpec; struct JSRuntime; struct JSSecurityCallbacks; struct JSStructuredCloneCallbacks; struct JSStructuredCloneReader; struct JSStructuredCloneWriter; class JS_PUBLIC_API(JSTracer); class JSFlatString; typedef struct PRCallOnceType JSCallOnceType; typedef bool (*JSInitCallback)(void); template struct JSConstScalarSpec; typedef JSConstScalarSpec JSConstDoubleSpec; typedef JSConstScalarSpec JSConstIntegerSpec; /* * Generic trace operation that calls JS_CallTracer on each traceable thing * stored in data. */ typedef void (* JSTraceDataOp)(JSTracer* trc, void* data); namespace js { void FinishGC(JSRuntime* rt); namespace gc { class AutoTraceSession; class StoreBuffer; void MarkPersistentRootedChains(JSTracer*); void MarkPersistentRootedChainsInLists(js::RootLists&, JSTracer*); void FinishPersistentRootedChains(js::RootLists&); } // namespace gc } // namespace js namespace JS { 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) }; namespace shadow { struct Runtime { protected: // Allow inlining of heapState checks. friend class js::gc::AutoTraceSession; JS::HeapState heapState_; js::gc::StoreBuffer* gcStoreBufferPtr_; public: Runtime() : heapState_(JS::HeapState::Idle) , gcStoreBufferPtr_(nullptr) {} bool isHeapBusy() const { return heapState_ != JS::HeapState::Idle; } js::gc::StoreBuffer* gcStoreBufferPtr() { return gcStoreBufferPtr_; } static JS::shadow::Runtime* asShadowRuntime(JSRuntime* rt) { return reinterpret_cast(rt); } protected: void setGCStoreBufferPtr(js::gc::StoreBuffer* storeBuffer) { gcStoreBufferPtr_ = storeBuffer; } }; } /* namespace shadow */ class JS_PUBLIC_API(AutoGCRooter) { public: AutoGCRooter(JSContext* cx, ptrdiff_t tag); AutoGCRooter(js::ContextFriendFields* 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); /* T must be a context type */ template static void traceAllInContext(T* cx, JSTracer* trc) { for (AutoGCRooter* gcr = cx->roots.autoGCRooters_; gcr; gcr = gcr->down) gcr->trace(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; }; } /* 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 }; enum ThingRootKind { THING_ROOT_OBJECT, THING_ROOT_SHAPE, THING_ROOT_BASE_SHAPE, THING_ROOT_OBJECT_GROUP, THING_ROOT_STRING, THING_ROOT_SYMBOL, THING_ROOT_JIT_CODE, THING_ROOT_SCRIPT, THING_ROOT_LAZY_SCRIPT, THING_ROOT_ID, THING_ROOT_VALUE, THING_ROOT_TRACEABLE, THING_ROOT_LIMIT }; template struct RootKind; /* * Specifically mark the ThingRootKind of externally visible types, so that * JSAPI users may use JSRooted... types without having the class definition * available. */ template struct SpecificRootKind { static ThingRootKind rootKind() { return Kind; } }; template <> struct RootKind : SpecificRootKind {}; template <> struct RootKind : SpecificRootKind {}; template <> struct RootKind : SpecificRootKind {}; template <> struct RootKind : SpecificRootKind {}; template <> struct RootKind : SpecificRootKind {}; template <> struct RootKind : SpecificRootKind {}; template <> struct RootKind : SpecificRootKind {}; template <> struct RootKind : SpecificRootKind {}; // Abstracts JS rooting mechanisms so they can be shared between the JSContext // and JSRuntime. class RootLists { // Stack GC roots for stack-allocated GC heap pointers. JS::Rooted* stackRoots_[THING_ROOT_LIMIT]; template friend class JS::Rooted; // Stack GC roots for stack-allocated AutoFooRooter classes. JS::AutoGCRooter* autoGCRooters_; friend class JS::AutoGCRooter; public: RootLists() : autoGCRooters_(nullptr) { mozilla::PodArrayZero(stackRoots_); } template inline JS::Rooted* gcRooters() { js::ThingRootKind kind = RootKind::rootKind(); return reinterpret_cast*>(stackRoots_[kind]); } void checkNoGCRooters(); /* Allow inlining of PersistentRooted constructors and destructors. */ private: template friend class JS::PersistentRooted; friend void js::gc::MarkPersistentRootedChains(JSTracer*); friend void js::gc::MarkPersistentRootedChainsInLists(RootLists&, JSTracer*); friend void js::gc::FinishPersistentRootedChains(RootLists&); mozilla::LinkedList> heapRoots_[THING_ROOT_LIMIT]; /* Specializations of this return references to the appropriate list. */ template inline mozilla::LinkedList>& getPersistentRootedList(); }; template<> inline mozilla::LinkedList& RootLists::getPersistentRootedList() { return reinterpret_cast>&>( heapRoots_[THING_ROOT_OBJECT]); } template<> inline mozilla::LinkedList& RootLists::getPersistentRootedList() { return reinterpret_cast>&>( heapRoots_[THING_ROOT_OBJECT]); } template<> inline mozilla::LinkedList& RootLists::getPersistentRootedList() { return reinterpret_cast>&>( heapRoots_[THING_ROOT_ID]); } template<> inline mozilla::LinkedList& RootLists::getPersistentRootedList() { return reinterpret_cast>&>( heapRoots_[THING_ROOT_SCRIPT]); } template<> inline mozilla::LinkedList& RootLists::getPersistentRootedList() { return reinterpret_cast>&>( heapRoots_[THING_ROOT_STRING]); } template<> inline mozilla::LinkedList& RootLists::getPersistentRootedList() { return reinterpret_cast>&>( heapRoots_[THING_ROOT_VALUE]); } struct ContextFriendFields { protected: JSRuntime* const runtime_; /* The current compartment. */ JSCompartment* compartment_; /* The current zone. */ JS::Zone* zone_; public: /* Rooting structures. */ RootLists roots; explicit ContextFriendFields(JSRuntime* rt) : runtime_(rt), compartment_(nullptr), zone_(nullptr) {} static const ContextFriendFields* get(const JSContext* cx) { return reinterpret_cast(cx); } static ContextFriendFields* get(JSContext* cx) { return reinterpret_cast(cx); } friend JSRuntime* GetRuntime(const JSContext* cx); friend JSCompartment* GetContextCompartment(const JSContext* cx); friend JS::Zone* GetContextZone(const JSContext* cx); template 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 JSRuntime* GetRuntime(const JSContext* cx) { return ContextFriendFields::get(cx)->runtime_; } inline JSCompartment* GetContextCompartment(const JSContext* cx) { return ContextFriendFields::get(cx)->compartment_; } inline JS::Zone* GetContextZone(const JSContext* cx) { return ContextFriendFields::get(cx)->zone_; } class PerThreadData; struct PerThreadDataFriendFields { private: // Note: this type only exists to permit us to derive the offset of // the perThread data within the real JSRuntime* type in a portable // way. struct RuntimeDummy : JS::shadow::Runtime { struct PerThreadDummy { void* field1; uintptr_t field2; #ifdef JS_DEBUG uint64_t field3; #endif } mainThread; }; public: /* Rooting structures. */ RootLists roots; PerThreadDataFriendFields(); /* Limit pointer for checking native stack consumption. */ uintptr_t nativeStackLimit[js::StackKindCount]; static const size_t RuntimeMainThreadOffset = offsetof(RuntimeDummy, mainThread); static inline PerThreadDataFriendFields* get(js::PerThreadData* pt) { return reinterpret_cast(pt); } static inline PerThreadDataFriendFields* getMainThread(JSRuntime* rt) { // mainThread must always appear directly after |JS::shadow::Runtime|. // Tested by a JS_STATIC_ASSERT in |jsfriendapi.cpp| return reinterpret_cast( reinterpret_cast(rt) + RuntimeMainThreadOffset); } static inline const PerThreadDataFriendFields* getMainThread(const JSRuntime* rt) { // mainThread must always appear directly after |JS::shadow::Runtime|. // Tested by a JS_STATIC_ASSERT in |jsfriendapi.cpp| return reinterpret_cast( reinterpret_cast(rt) + RuntimeMainThreadOffset); } template friend class JS::Rooted; }; } /* namespace js */ #endif /* jspubtd_h */