summaryrefslogtreecommitdiffstats
path: root/js/src/jspubtd.h
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jspubtd.h')
-rw-r--r--js/src/jspubtd.h476
1 files changed, 476 insertions, 0 deletions
diff --git a/js/src/jspubtd.h b/js/src/jspubtd.h
new file mode 100644
index 000000000..309b9d746
--- /dev/null
+++ b/js/src/jspubtd.h
@@ -0,0 +1,476 @@
+/* -*- 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 */