Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/libraries/source/spidermonkey/include-win32-debug/jspubtd.h
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- | ||||
* vim: set ts=8 sts=4 et sw=4 tw=99: | * vim: set ts=8 sts=4 et sw=4 tw=99: | ||||
* This Source Code Form is subject to the terms of the Mozilla Public | * 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 | * 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/. */ | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||||
#ifndef jspubtd_h | #ifndef jspubtd_h | ||||
#define jspubtd_h | #define jspubtd_h | ||||
/* | /* | ||||
* JS public API typedefs. | * JS public API typedefs. | ||||
*/ | */ | ||||
#include "mozilla/Assertions.h" | #include "mozilla/Assertions.h" | ||||
#include "mozilla/EnumeratedArray.h" | |||||
#include "mozilla/LinkedList.h" | #include "mozilla/LinkedList.h" | ||||
#include "mozilla/PodOperations.h" | #include "mozilla/PodOperations.h" | ||||
#include "jsprototypes.h" | #include "jsprototypes.h" | ||||
#include "jstypes.h" | #include "jstypes.h" | ||||
#include "js/TraceKind.h" | |||||
#include "js/TypeDecls.h" | #include "js/TypeDecls.h" | ||||
#if defined(JS_GC_ZEAL) || defined(DEBUG) | #if defined(JS_GC_ZEAL) || defined(DEBUG) | ||||
# define JSGC_HASH_TABLE_CHECKS | # define JSGC_HASH_TABLE_CHECKS | ||||
#endif | #endif | ||||
namespace JS { | namespace JS { | ||||
template <typename T> | class AutoIdVector; | ||||
class AutoVectorRooter; | |||||
typedef AutoVectorRooter<jsid> AutoIdVector; | |||||
class CallArgs; | class CallArgs; | ||||
template <typename T> | template <typename T> | ||||
class Rooted; | class Rooted; | ||||
class JS_FRIEND_API(CompileOptions); | class JS_FRIEND_API(CompileOptions); | ||||
class JS_FRIEND_API(ReadOnlyCompileOptions); | class JS_FRIEND_API(ReadOnlyCompileOptions); | ||||
class JS_FRIEND_API(OwningCompileOptions); | class JS_FRIEND_API(OwningCompileOptions); | ||||
class JS_FRIEND_API(TransitiveCompileOptions); | class JS_FRIEND_API(TransitiveCompileOptions); | ||||
class JS_PUBLIC_API(CompartmentOptions); | class JS_PUBLIC_API(CompartmentOptions); | ||||
struct RootingContext; | |||||
class Value; | class Value; | ||||
struct Zone; | struct Zone; | ||||
} /* namespace JS */ | namespace shadow { | ||||
struct Runtime; | |||||
} // namespace shadow | |||||
} // namespace JS | |||||
namespace js { | namespace js { | ||||
struct ContextFriendFields; | |||||
class RootLists; | class RootLists; | ||||
} // namespace js | } // namespace js | ||||
/* | /* | ||||
* Run-time version enumeration. For compile-time version checking, please use | * Run-time version enumeration. For compile-time version checking, please use | ||||
* the JS_HAS_* macros in jsversion.h, or use MOZJS_MAJOR_VERSION, | * the JS_HAS_* macros in jsversion.h, or use MOZJS_MAJOR_VERSION, | ||||
* MOZJS_MINOR_VERSION, MOZJS_PATCH_VERSION, and MOZJS_ALPHA definitions. | * MOZJS_MINOR_VERSION, MOZJS_PATCH_VERSION, and MOZJS_ALPHA definitions. | ||||
*/ | */ | ||||
Show All 34 Lines | |||||
struct JSCompartment; | struct JSCompartment; | ||||
struct JSCrossCompartmentCall; | struct JSCrossCompartmentCall; | ||||
class JSErrorReport; | class JSErrorReport; | ||||
struct JSExceptionState; | struct JSExceptionState; | ||||
struct JSFunctionSpec; | struct JSFunctionSpec; | ||||
struct JSLocaleCallbacks; | struct JSLocaleCallbacks; | ||||
struct JSObjectMap; | struct JSObjectMap; | ||||
struct JSPrincipals; | struct JSPrincipals; | ||||
struct JSPropertyDescriptor; | |||||
struct JSPropertyName; | struct JSPropertyName; | ||||
struct JSPropertySpec; | struct JSPropertySpec; | ||||
struct JSRuntime; | struct JSRuntime; | ||||
struct JSSecurityCallbacks; | struct JSSecurityCallbacks; | ||||
struct JSStructuredCloneCallbacks; | struct JSStructuredCloneCallbacks; | ||||
struct JSStructuredCloneReader; | struct JSStructuredCloneReader; | ||||
struct JSStructuredCloneWriter; | struct JSStructuredCloneWriter; | ||||
class JS_PUBLIC_API(JSTracer); | class JS_PUBLIC_API(JSTracer); | ||||
class JSFlatString; | class JSFlatString; | ||||
typedef struct PRCallOnceType JSCallOnceType; | |||||
typedef bool (*JSInitCallback)(void); | typedef bool (*JSInitCallback)(void); | ||||
template<typename T> struct JSConstScalarSpec; | template<typename T> struct JSConstScalarSpec; | ||||
typedef JSConstScalarSpec<double> JSConstDoubleSpec; | typedef JSConstScalarSpec<double> JSConstDoubleSpec; | ||||
typedef JSConstScalarSpec<int32_t> JSConstIntegerSpec; | typedef JSConstScalarSpec<int32_t> JSConstIntegerSpec; | ||||
/* | /* | ||||
* Generic trace operation that calls JS_CallTracer on each traceable thing | * Generic trace operation that calls JS::TraceEdge on each traceable thing's | ||||
* stored in data. | * location reachable from data. | ||||
*/ | */ | ||||
typedef void | typedef void | ||||
(* JSTraceDataOp)(JSTracer* trc, void* data); | (* JSTraceDataOp)(JSTracer* trc, void* data); | ||||
namespace js { | namespace js { | ||||
void FinishGC(JSRuntime* rt); | |||||
namespace gc { | namespace gc { | ||||
class AutoTraceSession; | class AutoTraceSession; | ||||
class StoreBuffer; | class StoreBuffer; | ||||
void MarkPersistentRootedChains(JSTracer*); | |||||
void MarkPersistentRootedChainsInLists(js::RootLists&, JSTracer*); | |||||
void FinishPersistentRootedChains(js::RootLists&); | |||||
} // namespace gc | } // 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 | ||||
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); | typedef void (*OffThreadCompileCallback)(void* token, void* callbackData); | ||||
enum class HeapState { | enum class HeapState { | ||||
Idle, // doing nothing with the GC heap | Idle, // doing nothing with the GC heap | ||||
Tracing, // tracing the GC heap without collecting, e.g. IterateCompartments() | Tracing, // tracing the GC heap without collecting, e.g. IterateCompartments() | ||||
MajorCollecting, // doing a GC of the major heap | MajorCollecting, // doing a GC of the major heap | ||||
MinorCollecting // doing a GC of the minor heap (nursery) | MinorCollecting, // doing a GC of the minor heap (nursery) | ||||
CycleCollecting // in the "Unlink" phase of cycle collection | |||||
}; | }; | ||||
namespace shadow { | namespace shadow { | ||||
struct Runtime | struct Runtime | ||||
{ | { | ||||
protected: | private: | ||||
// Allow inlining of heapState checks. | |||||
friend class js::gc::AutoTraceSession; | |||||
JS::HeapState heapState_; | 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_; | 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: | public: | ||||
Runtime() | Runtime() | ||||
: heapState_(JS::HeapState::Idle) | : heapState_(JS::HeapState::Idle) | ||||
, allowGCBarriers_(true) | |||||
, gcStoreBufferPtr_(nullptr) | , gcStoreBufferPtr_(nullptr) | ||||
, gcGrayBitsValid_(false) | |||||
{} | {} | ||||
bool isHeapBusy() const { return heapState_ != JS::HeapState::Idle; } | bool isHeapBusy() const { return heapState() != JS::HeapState::Idle; } | ||||
bool isHeapMajorCollecting() const { return heapState_ == JS::HeapState::MajorCollecting; } | bool isHeapTracing() const { return heapState() == JS::HeapState::Tracing; } | ||||
bool isHeapMinorCollecting() const { return heapState_ == JS::HeapState::MinorCollecting; } | bool isHeapMajorCollecting() const { return heapState() == JS::HeapState::MajorCollecting; } | ||||
bool isHeapMinorCollecting() const { return heapState() == JS::HeapState::MinorCollecting; } | |||||
bool isHeapCollecting() const { return isHeapMinorCollecting() || isHeapMajorCollecting(); } | 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_; } | 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) { | static JS::shadow::Runtime* asShadowRuntime(JSRuntime* rt) { | ||||
return reinterpret_cast<JS::shadow::Runtime*>(rt); | return reinterpret_cast<JS::shadow::Runtime*>(rt); | ||||
} | } | ||||
protected: | protected: | ||||
void setGCStoreBufferPtr(js::gc::StoreBuffer* storeBuffer) { | void setGCStoreBufferPtr(js::gc::StoreBuffer* storeBuffer) { | ||||
gcStoreBufferPtr_ = storeBuffer; | gcStoreBufferPtr_ = storeBuffer; | ||||
} | } | ||||
}; | }; | ||||
} /* namespace shadow */ | } /* 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) | class JS_PUBLIC_API(AutoGCRooter) | ||||
{ | { | ||||
public: | public: | ||||
AutoGCRooter(JSContext* cx, ptrdiff_t tag); | AutoGCRooter(JSContext* cx, ptrdiff_t tag); | ||||
AutoGCRooter(js::ContextFriendFields* cx, ptrdiff_t tag); | AutoGCRooter(JS::RootingContext* cx, ptrdiff_t tag); | ||||
~AutoGCRooter() { | ~AutoGCRooter() { | ||||
MOZ_ASSERT(this == *stackTop); | MOZ_ASSERT(this == *stackTop); | ||||
*stackTop = down; | *stackTop = down; | ||||
} | } | ||||
/* Implemented in gc/RootMarking.cpp. */ | /* Implemented in gc/RootMarking.cpp. */ | ||||
inline void trace(JSTracer* trc); | inline void trace(JSTracer* trc); | ||||
static void traceAll(JSTracer* trc); | static void traceAll(JSTracer* trc); | ||||
static void traceAllWrappers(JSTracer* trc); | static void traceAllWrappers(JSTracer* trc); | ||||
/* T must be a context type */ | |||||
template<typename T> | |||||
static void traceAllInContext(T* cx, JSTracer* trc) { | |||||
for (AutoGCRooter* gcr = cx->roots.autoGCRooters_; gcr; gcr = gcr->down) | |||||
gcr->trace(trc); | |||||
} | |||||
protected: | protected: | ||||
AutoGCRooter * const down; | AutoGCRooter * const down; | ||||
/* | /* | ||||
* Discriminates actual subclass of this being used. If non-negative, the | * Discriminates actual subclass of this being used. If non-negative, the | ||||
* subclass roots an array of values of the length stored in this field. | * 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 | * If negative, meaning is indicated by the corresponding value in the enum | ||||
* below. Any other negative value indicates some deeper problem such as | * below. Any other negative value indicates some deeper problem such as | ||||
Show All 20 Lines | class JS_PUBLIC_API(AutoGCRooter) | ||||
private: | private: | ||||
AutoGCRooter ** const stackTop; | AutoGCRooter ** const stackTop; | ||||
/* No copy or assignment semantics. */ | /* No copy or assignment semantics. */ | ||||
AutoGCRooter(AutoGCRooter& ida) = delete; | AutoGCRooter(AutoGCRooter& ida) = delete; | ||||
void operator=(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 */ | ||||
namespace js { | namespace js { | ||||
class ExclusiveContext; | class ExclusiveContext; | ||||
/* | /* | ||||
* This list enumerates the different types of conceptual stacks we have in | * 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 | * SpiderMonkey. In reality, they all share the C stack, but we allow different | ||||
* stack limits depending on the type of code running. | * stack limits depending on the type of code running. | ||||
*/ | */ | ||||
enum StackKind | enum StackKind | ||||
{ | { | ||||
StackForSystemCode, // C++, such as the GC, running on behalf of the VM. | StackForSystemCode, // C++, such as the GC, running on behalf of the VM. | ||||
StackForTrustedScript, // Script running with trusted principals. | StackForTrustedScript, // Script running with trusted principals. | ||||
StackForUntrustedScript, // Script running with untrusted principals. | StackForUntrustedScript, // Script running with untrusted principals. | ||||
StackKindCount | StackKindCount | ||||
}; | }; | ||||
enum ThingRootKind | using RootedListHeads = mozilla::EnumeratedArray<JS::RootKind, JS::RootKind::Limit, | ||||
{ | JS::Rooted<void*>*>; | ||||
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 <typename T> | |||||
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<typename T, ThingRootKind Kind> | |||||
struct SpecificRootKind | |||||
{ | |||||
static ThingRootKind rootKind() { return Kind; } | |||||
}; | |||||
template <> struct RootKind<JSObject*> : SpecificRootKind<JSObject*, THING_ROOT_OBJECT> {}; | |||||
template <> struct RootKind<JSFlatString*> : SpecificRootKind<JSFlatString*, THING_ROOT_STRING> {}; | |||||
template <> struct RootKind<JSFunction*> : SpecificRootKind<JSFunction*, THING_ROOT_OBJECT> {}; | |||||
template <> struct RootKind<JSString*> : SpecificRootKind<JSString*, THING_ROOT_STRING> {}; | |||||
template <> struct RootKind<JS::Symbol*> : SpecificRootKind<JS::Symbol*, THING_ROOT_SYMBOL> {}; | |||||
template <> struct RootKind<JSScript*> : SpecificRootKind<JSScript*, THING_ROOT_SCRIPT> {}; | |||||
template <> struct RootKind<jsid> : SpecificRootKind<jsid, THING_ROOT_ID> {}; | |||||
template <> struct RootKind<JS::Value> : SpecificRootKind<JS::Value, THING_ROOT_VALUE> {}; | |||||
// Abstracts JS rooting mechanisms so they can be shared between the JSContext | // Abstracts JS rooting mechanisms so they can be shared between the JSContext | ||||
// and JSRuntime. | // and JSRuntime. | ||||
class RootLists | class RootLists | ||||
{ | { | ||||
// Stack GC roots for stack-allocated GC heap pointers. | // Stack GC roots for Rooted GC heap pointers. | ||||
JS::Rooted<void*>* stackRoots_[THING_ROOT_LIMIT]; | RootedListHeads stackRoots_; | ||||
template <typename T> friend class JS::Rooted; | template <typename T> friend class JS::Rooted; | ||||
// Stack GC roots for stack-allocated AutoFooRooter classes. | // Stack GC roots for AutoFooRooter classes. | ||||
JS::AutoGCRooter* autoGCRooters_; | JS::AutoGCRooter* autoGCRooters_; | ||||
friend class JS::AutoGCRooter; | 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: | public: | ||||
RootLists() : autoGCRooters_(nullptr) { | RootLists() : autoGCRooters_(nullptr) { | ||||
mozilla::PodArrayZero(stackRoots_); | for (auto& stackRootPtr : stackRoots_) | ||||
stackRootPtr = nullptr; | |||||
} | } | ||||
template <class T> | ~RootLists() { | ||||
inline JS::Rooted<T>* gcRooters() { | // The semantics of PersistentRooted containing pointers and tagged | ||||
js::ThingRootKind kind = RootKind<T>::rootKind(); | // pointers are somewhat different from those of PersistentRooted | ||||
return reinterpret_cast<JS::Rooted<T>*>(stackRoots_[kind]); | // 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 checkNoGCRooters(); | ||||
/* Allow inlining of PersistentRooted constructors and destructors. */ | void tracePersistentRoots(JSTracer* trc); | ||||
private: | void finishPersistentRoots(); | ||||
template <typename Referent> 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<JS::PersistentRooted<void*>> heapRoots_[THING_ROOT_LIMIT]; | |||||
/* Specializations of this return references to the appropriate list. */ | |||||
template<typename Referent> | |||||
inline mozilla::LinkedList<JS::PersistentRooted<Referent>>& getPersistentRootedList(); | |||||
}; | }; | ||||
template<> | } // namespace js | ||||
inline mozilla::LinkedList<JS::PersistentRootedFunction>& | |||||
RootLists::getPersistentRootedList<JSFunction*>() { | |||||
return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<JSFunction*>>&>( | |||||
heapRoots_[THING_ROOT_OBJECT]); | |||||
} | |||||
template<> | namespace JS { | ||||
inline mozilla::LinkedList<JS::PersistentRootedObject>& | |||||
RootLists::getPersistentRootedList<JSObject*>() { | |||||
return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<JSObject*>>&>( | |||||
heapRoots_[THING_ROOT_OBJECT]); | |||||
} | |||||
template<> | /* | ||||
inline mozilla::LinkedList<JS::PersistentRootedId>& | * JS::RootingContext is a base class of ContextFriendFields and JSContext. | ||||
RootLists::getPersistentRootedList<jsid>() { | * This class can be used to let code construct a Rooted<> or PersistentRooted<> | ||||
return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<jsid>>&>( | * instance, without giving it full access to the JSContext. | ||||
heapRoots_[THING_ROOT_ID]); | */ | ||||
} | struct RootingContext | ||||
{ | |||||
js::RootLists roots; | |||||
template<> | #ifdef DEBUG | ||||
inline mozilla::LinkedList<JS::PersistentRootedScript>& | // Whether the derived class is a JSContext or an ExclusiveContext. | ||||
RootLists::getPersistentRootedList<JSScript*>() { | bool isJSContext; | ||||
return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<JSScript*>>&>( | #endif | ||||
heapRoots_[THING_ROOT_SCRIPT]); | |||||
} | |||||
template<> | explicit RootingContext(bool isJSContextArg) | ||||
inline mozilla::LinkedList<JS::PersistentRootedString>& | #ifdef DEBUG | ||||
RootLists::getPersistentRootedList<JSString*>() { | : isJSContext(isJSContextArg) | ||||
return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<JSString*>>&>( | #endif | ||||
heapRoots_[THING_ROOT_STRING]); | {} | ||||
} | |||||
template<> | static RootingContext* get(JSContext* cx) { | ||||
inline mozilla::LinkedList<JS::PersistentRootedValue>& | return reinterpret_cast<RootingContext*>(cx); | ||||
RootLists::getPersistentRootedList<JS::Value>() { | |||||
return reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<JS::Value>>&>( | |||||
heapRoots_[THING_ROOT_VALUE]); | |||||
} | } | ||||
}; | |||||
} // namespace JS | |||||
namespace js { | |||||
struct ContextFriendFields | struct ContextFriendFields : public JS::RootingContext | ||||
{ | { | ||||
protected: | protected: | ||||
JSRuntime* const runtime_; | |||||
/* The current compartment. */ | /* The current compartment. */ | ||||
JSCompartment* compartment_; | JSCompartment* compartment_; | ||||
/* The current zone. */ | /* The current zone. */ | ||||
JS::Zone* zone_; | JS::Zone* zone_; | ||||
public: | public: | ||||
/* Rooting structures. */ | /* Limit pointer for checking native stack consumption. */ | ||||
RootLists roots; | uintptr_t nativeStackLimit[js::StackKindCount]; | ||||
explicit ContextFriendFields(JSRuntime* rt) | explicit ContextFriendFields(bool isJSContext); | ||||
: runtime_(rt), compartment_(nullptr), zone_(nullptr) | |||||
{} | |||||
static const ContextFriendFields* get(const JSContext* cx) { | static const ContextFriendFields* get(const JSContext* cx) { | ||||
return reinterpret_cast<const ContextFriendFields*>(cx); | return reinterpret_cast<const ContextFriendFields*>(cx); | ||||
} | } | ||||
static ContextFriendFields* get(JSContext* cx) { | static ContextFriendFields* get(JSContext* cx) { | ||||
return reinterpret_cast<ContextFriendFields*>(cx); | return reinterpret_cast<ContextFriendFields*>(cx); | ||||
} | } | ||||
friend JSRuntime* GetRuntime(const JSContext* cx); | |||||
friend JSCompartment* GetContextCompartment(const JSContext* cx); | friend JSCompartment* GetContextCompartment(const JSContext* cx); | ||||
friend JS::Zone* GetContextZone(const JSContext* cx); | friend JS::Zone* GetContextZone(const JSContext* cx); | ||||
template <typename T> friend class JS::Rooted; | template <typename T> friend class JS::Rooted; | ||||
}; | }; | ||||
/* | /* | ||||
* Inlinable accessors for JSContext. | * Inlinable accessors for JSContext. | ||||
* | * | ||||
* - These must not be available on the more restricted superclasses of | * - These must not be available on the more restricted superclasses of | ||||
* JSContext, so we can't simply define them on ContextFriendFields. | * JSContext, so we can't simply define them on ContextFriendFields. | ||||
* | * | ||||
* - They're perfectly ordinary JSContext functionality, so ought to be | * - They're perfectly ordinary JSContext functionality, so ought to be | ||||
* usable without resorting to jsfriendapi.h, and when JSContext is an | * usable without resorting to jsfriendapi.h, and when JSContext is an | ||||
* incomplete type. | * incomplete type. | ||||
*/ | */ | ||||
inline JSRuntime* | |||||
GetRuntime(const JSContext* cx) | |||||
{ | |||||
return ContextFriendFields::get(cx)->runtime_; | |||||
} | |||||
inline JSCompartment* | inline JSCompartment* | ||||
GetContextCompartment(const JSContext* cx) | GetContextCompartment(const JSContext* cx) | ||||
{ | { | ||||
return ContextFriendFields::get(cx)->compartment_; | return ContextFriendFields::get(cx)->compartment_; | ||||
} | } | ||||
inline JS::Zone* | inline JS::Zone* | ||||
GetContextZone(const JSContext* cx) | GetContextZone(const JSContext* cx) | ||||
{ | { | ||||
return ContextFriendFields::get(cx)->zone_; | return ContextFriendFields::get(cx)->zone_; | ||||
} | } | ||||
class PerThreadData; | } /* namespace js */ | ||||
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<PerThreadDataFriendFields*>(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<PerThreadDataFriendFields*>( | |||||
reinterpret_cast<char*>(rt) + RuntimeMainThreadOffset); | |||||
} | |||||
static inline const PerThreadDataFriendFields* getMainThread(const JSRuntime* rt) { | MOZ_BEGIN_EXTERN_C | ||||
// mainThread must always appear directly after |JS::shadow::Runtime|. | |||||
// Tested by a JS_STATIC_ASSERT in |jsfriendapi.cpp| | |||||
return reinterpret_cast<const PerThreadDataFriendFields*>( | |||||
reinterpret_cast<const char*>(rt) + RuntimeMainThreadOffset); | |||||
} | |||||
template <typename T> friend class JS::Rooted; | // Defined in NSPR prio.h. | ||||
}; | typedef struct PRFileDesc PRFileDesc; | ||||
} /* namespace js */ | MOZ_END_EXTERN_C | ||||
#endif /* jspubtd_h */ | #endif /* jspubtd_h */ |
Wildfire Games · Phabricator