diff --git a/js/public/RootingAPI.h b/js/public/RootingAPI.h index ae9cb0c50396..867876b5eea4 100644 --- a/js/public/RootingAPI.h +++ b/js/public/RootingAPI.h @@ -642,7 +642,7 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase template void init(CX* cx) { js::ThingRootKind kind = js::RootKind::rootKind(); - this->stack = &cx->thingGCRooters[kind]; + this->stack = &cx->roots.stackRoots_[kind]; this->prev = *stack; *stack = reinterpret_cast*>(this); } diff --git a/js/src/gc/RootMarking.cpp b/js/src/gc/RootMarking.cpp index 96bec3a60f44..d6ddb25eaad8 100644 --- a/js/src/gc/RootMarking.cpp +++ b/js/src/gc/RootMarking.cpp @@ -81,7 +81,7 @@ template * rooter = s->template gcRooters(); + Rooted* rooter = s->roots.template gcRooters(); while (rooter) { T* addr = rooter->address(); if (!IgnoreExactRoot(addr)) @@ -282,7 +282,7 @@ AutoGCRooter::traceAll(JSTracer* trc) AutoGCRooter::traceAllWrappers(JSTracer* trc) { for (ContextIter cx(trc->runtime()); !cx.done(); cx.next()) { - for (AutoGCRooter* gcr = cx->autoGCRooters; gcr; gcr = gcr->down) { + for (AutoGCRooter* gcr = cx->roots.autoGCRooters_; gcr; gcr = gcr->down) { if (gcr->tag_ == WRAPVECTOR || gcr->tag_ == WRAPPER) gcr->trace(trc); } diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 6355ece45cc2..7ff44e961472 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -6126,18 +6126,18 @@ JS_CallOnce(JSCallOnceType* once, JSInitCallback func) } AutoGCRooter::AutoGCRooter(JSContext* cx, ptrdiff_t tag) - : down(ContextFriendFields::get(cx)->autoGCRooters), + : down(ContextFriendFields::get(cx)->roots.autoGCRooters_), tag_(tag), - stackTop(&ContextFriendFields::get(cx)->autoGCRooters) + stackTop(&ContextFriendFields::get(cx)->roots.autoGCRooters_) { MOZ_ASSERT(this != *stackTop); *stackTop = this; } AutoGCRooter::AutoGCRooter(ContextFriendFields* cx, ptrdiff_t tag) - : down(cx->autoGCRooters), + : down(cx->roots.autoGCRooters_), tag_(tag), - stackTop(&cx->autoGCRooters) + stackTop(&cx->roots.autoGCRooters_) { MOZ_ASSERT(this != *stackTop); *stackTop = this; diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index 7279e6a3e809..cd06286eadd1 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -156,7 +156,7 @@ js::DestroyContext(JSContext* cx, DestroyContextMode mode) if (cx->outstandingRequests != 0) MOZ_CRASH(); - cx->checkNoGCRooters(); + cx->roots.checkNoGCRooters(); if (mode != DCM_NEW_FAILED) { if (JSContextCallback cxCallback = rt->cxCallback) { @@ -188,10 +188,10 @@ js::DestroyContext(JSContext* cx, DestroyContextMode mode) } void -ContextFriendFields::checkNoGCRooters() { +RootLists::checkNoGCRooters() { #ifdef DEBUG for (int i = 0; i < THING_ROOT_LIMIT; ++i) - MOZ_ASSERT(thingGCRooters[i] == nullptr); + MOZ_ASSERT(stackRoots_[i] == nullptr); #endif } diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp index 0464f7288702..ffc636f3f976 100644 --- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -50,7 +50,6 @@ PerThreadDataFriendFields::PerThreadDataFriendFields() for (int i=0; i static void traceAllInContext(T* cx, JSTracer* trc) { - for (AutoGCRooter* gcr = cx->autoGCRooters; gcr; gcr = gcr->down) + for (AutoGCRooter* gcr = cx->roots.autoGCRooters_; gcr; gcr = gcr->down) gcr->trace(trc); } @@ -355,6 +355,32 @@ template <> struct RootKind : SpecificRootKind 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(); +}; + struct ContextFriendFields { protected: @@ -367,11 +393,12 @@ struct ContextFriendFields JS::Zone* zone_; public: + /* Rooting structures. */ + RootLists roots; + explicit ContextFriendFields(JSRuntime* rt) - : runtime_(rt), compartment_(nullptr), zone_(nullptr), autoGCRooters(nullptr) - { - mozilla::PodArrayZero(thingGCRooters); - } + : runtime_(rt), compartment_(nullptr), zone_(nullptr) + {} static const ContextFriendFields* get(const JSContext* cx) { return reinterpret_cast(cx); @@ -381,25 +408,6 @@ struct ContextFriendFields return reinterpret_cast(cx); } - private: - /* - * Stack allocated GC roots for stack GC heap pointers, which may be - * overwritten if moved during a GC. - */ - JS::Rooted* thingGCRooters[THING_ROOT_LIMIT]; - - public: - template - inline JS::Rooted* gcRooters() { - js::ThingRootKind kind = RootKind::rootKind(); - return reinterpret_cast*>(thingGCRooters[kind]); - } - - void checkNoGCRooters(); - - /* Stack of thread-stack-allocated GC roots. */ - JS::AutoGCRooter* autoGCRooters; - friend JSRuntime* GetRuntime(const JSContext* cx); friend JSCompartment* GetContextCompartment(const JSContext* cx); friend JS::Zone* GetContextZone(const JSContext* cx); @@ -454,23 +462,11 @@ struct PerThreadDataFriendFields }; public: + /* Rooting structures. */ + RootLists roots; PerThreadDataFriendFields(); - private: - /* - * Stack allocated GC roots for stack GC heap pointers, which may be - * overwritten if moved during a GC. - */ - JS::Rooted* thingGCRooters[THING_ROOT_LIMIT]; - - public: - template - inline JS::Rooted* gcRooters() { - js::ThingRootKind kind = RootKind::rootKind(); - return reinterpret_cast*>(thingGCRooters[kind]); - } - /* Limit pointer for checking native stack consumption. */ uintptr_t nativeStackLimit[js::StackKindCount];