From d3795dc945481048a9f88fba066e69ed9ca6fc96 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Thu, 5 Jun 2014 14:39:11 -0400 Subject: [PATCH] Backed out changeset 846ee7c7debf (bug 1020690) for bustage. CLOSED TREE --- js/public/RootingAPI.h | 72 +++++++++++++++++++++------ js/src/NamespaceImports.h | 2 - js/src/gc/RootMarking.cpp | 100 ++++++++++++++++---------------------- js/src/jsapi.h | 39 --------------- js/src/jscntxt.cpp | 13 ++--- js/src/jsinfer.h | 2 - js/src/jspubtd.h | 23 +-------- js/src/jsscript.h | 1 - js/src/vm/Shape.h | 2 + 9 files changed, 106 insertions(+), 148 deletions(-) diff --git a/js/public/RootingAPI.h b/js/public/RootingAPI.h index cd95a5e400b..7038f83b34a 100644 --- a/js/public/RootingAPI.h +++ b/js/public/RootingAPI.h @@ -634,16 +634,10 @@ class InternalHandle }; /* - * By default, things should use the inheritance hierarchy to find their + * By default, pointers should use the inheritance hierarchy to find their * ThingRootKind. Some pointer types are explicitly set in jspubtd.h so that * Rooted may be used without the class definition being available. */ -template -struct RootKind -{ - static ThingRootKind rootKind() { return T::rootKind(); } -}; - template struct RootKind { @@ -798,7 +792,7 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase #endif #ifdef JSGC_TRACK_EXACT_ROOTS - Rooted *previous() { return reinterpret_cast*>(prev); } + Rooted *previous() { return prev; } #endif /* @@ -833,12 +827,7 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase private: #ifdef JSGC_TRACK_EXACT_ROOTS - /* - * These need to be templated on void* to avoid aliasing issues between, for - * example, Rooted and Rooted, which use the same - * stack head pointer for different classes. - */ - Rooted **stack, *prev; + Rooted **stack, *prev; #endif /* @@ -874,6 +863,61 @@ class RootedBase JS::Handle as() const; }; + +/* + * RootedGeneric allows a class to instantiate its own Rooted type by + * including the following two methods: + * + * static inline js::ThingRootKind rootKind() { return js::THING_ROOT_CUSTOM; } + * void trace(JSTracer *trc); + * + * The trace() method must trace all of the class's fields. + * + * Implementation: + * + * RootedGeneric works by placing a pointer to its 'rooter' field into the + * usual list of rooters when it is instantiated. When marking, it backs up + * from this pointer to find a vtable containing a type-appropriate trace() + * method. + */ +template +class JS_PUBLIC_API(RootedGeneric) +{ + public: + JS::Rooted rooter; + + explicit RootedGeneric(js::ContextFriendFields *cx) + : rooter(cx) + { + } + + RootedGeneric(js::ContextFriendFields *cx, const GCType &initial) + : rooter(cx, initial) + { + } + + virtual inline void trace(JSTracer *trc); + + operator const GCType&() const { return rooter.get(); } + GCType operator->() const { return rooter.get(); } +}; + +template +inline void RootedGeneric::trace(JSTracer *trc) +{ + rooter->trace(trc); +} + +// We will instantiate RootedGeneric in RootMarking.cpp, and MSVC will +// notice that void*s have no trace() method defined on them and complain (even +// though it's never called.) MSVC's complaint is not unreasonable, so +// specialize for void*. +template <> +inline void RootedGeneric::trace(JSTracer *trc) +{ + MOZ_ASSUME_UNREACHABLE("RootedGeneric::trace()"); +} + /* Interface substitute for Rooted which does not root the variable's memory. */ template class FakeRooted : public RootedBase diff --git a/js/src/NamespaceImports.h b/js/src/NamespaceImports.h index 77abedb4017..c14909ab3b1 100644 --- a/js/src/NamespaceImports.h +++ b/js/src/NamespaceImports.h @@ -36,7 +36,6 @@ class JS_PUBLIC_API(AutoGCRooter); template class AutoVectorRooter; template class AutoHashMapRooter; template class AutoHashSetRooter; -template class RootedGeneric; class MOZ_STACK_CLASS SourceBufferHolder; @@ -84,7 +83,6 @@ using JS::AutoGCRooter; using JS::AutoHashMapRooter; using JS::AutoHashSetRooter; using JS::AutoVectorRooter; -using JS::RootedGeneric; using JS::CallArgs; using JS::CallNonGenericMethod; diff --git a/js/src/gc/RootMarking.cpp b/js/src/gc/RootMarking.cpp index 3229f170fdb..49aca07a429 100644 --- a/js/src/gc/RootMarking.cpp +++ b/js/src/gc/RootMarking.cpp @@ -40,77 +40,59 @@ typedef RootedValueMap::Entry RootEntry; typedef RootedValueMap::Enum RootEnum; #ifdef JSGC_USE_EXACT_ROOTING -static void -MarkBindingsRoot(JSTracer *trc, Bindings *bindings, const char *name) -{ - bindings->trace(trc); -} - -static void -MarkPropertyDescriptorRoot(JSTracer *trc, JSPropertyDescriptor *pd, const char *name) -{ - pd->trace(trc); -} - -template -static inline bool -IgnoreExactRoot(T *thingp) -{ - return false; -} - -template -inline bool -IgnoreExactRoot(T **thingp) -{ - return IsNullTaggedPointer(*thingp); -} - -template <> -inline bool -IgnoreExactRoot(JSObject **thingp) -{ - return IsNullTaggedPointer(*thingp) || *thingp == TaggedProto::LazyProto; -} - -template static inline void -MarkExactStackRootList(JSTracer *trc, Source *s, const char *name) +MarkExactStackRoot(JSTracer *trc, Rooted *rooter, ThingRootKind kind) { - Rooted *rooter = s->template gcRooters(); - while (rooter) { - T *addr = rooter->address(); - if (!IgnoreExactRoot(addr)) - MarkFunc(trc, addr, name); - rooter = rooter->previous(); + void **addr = (void **)rooter->address(); + if (IsNullTaggedPointer(*addr)) + return; + + if (kind == THING_ROOT_OBJECT && *addr == TaggedProto::LazyProto) + return; + + switch (kind) { + case THING_ROOT_OBJECT: MarkObjectRoot(trc, (JSObject **)addr, "exact-object"); break; + case THING_ROOT_STRING: MarkStringRoot(trc, (JSString **)addr, "exact-string"); break; + case THING_ROOT_SCRIPT: MarkScriptRoot(trc, (JSScript **)addr, "exact-script"); break; + case THING_ROOT_LAZY_SCRIPT: MarkLazyScriptRoot(trc, (LazyScript **)addr, "exact-lazy-script"); break; + case THING_ROOT_SHAPE: MarkShapeRoot(trc, (Shape **)addr, "exact-shape"); break; + case THING_ROOT_BASE_SHAPE: MarkBaseShapeRoot(trc, (BaseShape **)addr, "exact-baseshape"); break; + case THING_ROOT_TYPE: MarkTypeRoot(trc, (types::Type *)addr, "exact-type"); break; + case THING_ROOT_TYPE_OBJECT: MarkTypeObjectRoot(trc, (types::TypeObject **)addr, "exact-typeobject"); break; + case THING_ROOT_JIT_CODE: MarkJitCodeRoot(trc, (jit::JitCode **)addr, "exact-jitcode"); break; + case THING_ROOT_VALUE: MarkValueRoot(trc, (Value *)addr, "exact-value"); break; + case THING_ROOT_ID: MarkIdRoot(trc, (jsid *)addr, "exact-id"); break; + case THING_ROOT_BINDINGS: ((Bindings *)addr)->trace(trc); break; + case THING_ROOT_PROPERTY_DESCRIPTOR: ((JSPropertyDescriptor *)addr)->trace(trc); break; + case THING_ROOT_CUSTOM: { + // 'rooter' is a member within a class containing a vtable. Back up + // to the vtable and call trace() through it. + const size_t rooterOffset = offsetof(RootedGeneric, rooter); + reinterpret_cast< RootedGeneric* >(uintptr_t(rooter) - rooterOffset)->trace(trc); + break; + } + default: MOZ_ASSUME_UNREACHABLE("Invalid THING_ROOT kind"); break; } } -template static inline void -MarkExactStackRootsForType(JSTracer *trc, const char *name = nullptr) +MarkExactStackRootList(JSTracer *trc, Rooted *rooter, ThingRootKind kind) { - for (ContextIter cx(trc->runtime()); !cx.done(); cx.next()) - MarkExactStackRootList(trc, cx.get(), name); - MarkExactStackRootList(trc, &trc->runtime()->mainThread, name); + while (rooter) { + MarkExactStackRoot(trc, rooter, kind); + rooter = rooter->previous(); + } } static void MarkExactStackRoots(JSTracer *trc) { - MarkExactStackRootsForType(trc, "exact-object"); - MarkExactStackRootsForType(trc, "exact-shape"); - MarkExactStackRootsForType(trc, "exact-baseshape"); - MarkExactStackRootsForType(trc, "exact-typeobject"); - MarkExactStackRootsForType(trc, "exact-string"); - MarkExactStackRootsForType(trc, "exact-jitcode"); - MarkExactStackRootsForType(trc, "exact-script"); - MarkExactStackRootsForType(trc, "exact-lazy-script"); - MarkExactStackRootsForType(trc, "exact-id"); - MarkExactStackRootsForType(trc, "exact-value"); - MarkExactStackRootsForType(trc, "exact-type"); - MarkExactStackRootsForType(trc); - MarkExactStackRootsForType(trc); + for (unsigned i = 0; i < THING_ROOT_LIMIT; i++) { + for (ContextIter cx(trc->runtime()); !cx.done(); cx.next()) + MarkExactStackRootList(trc, cx->thingGCRooters[i], ThingRootKind(i)); + + MarkExactStackRootList(trc, trc->runtime()->mainThread.thingGCRooters[i], ThingRootKind(i)); + } } #endif /* JSGC_USE_EXACT_ROOTING */ diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 21ffe5f5b24..150e118e73f 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -591,43 +591,6 @@ class JS_PUBLIC_API(CustomAutoRooter) : private AutoGCRooter MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER }; -/* - * RootedGeneric allows a class to instantiate its own Rooted type by - * including the method: - * - * void trace(JSTracer *trc); - * - * The trace() method must trace all of the class's fields. - */ -template -class RootedGeneric : private CustomAutoRooter -{ - public: - template - explicit RootedGeneric(CX *cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) - : CustomAutoRooter(cx) - { - MOZ_GUARD_OBJECT_NOTIFIER_INIT; - } - - template - explicit RootedGeneric(CX *cx, const T& initial MOZ_GUARD_OBJECT_NOTIFIER_PARAM) - : CustomAutoRooter(cx), value(initial) - { - MOZ_GUARD_OBJECT_NOTIFIER_INIT; - } - - operator const T&() const { return value; } - T operator->() const { return value; } - - private: - virtual void trace(JSTracer *trc) { value->trace(trc); } - - T value; - - MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER -}; - /* A handle to an array of rooted values. */ class HandleValueArray { @@ -2915,8 +2878,6 @@ struct JSPropertyDescriptor { {} void trace(JSTracer *trc); - - static js::ThingRootKind rootKind() { return js::THING_ROOT_PROPERTY_DESCRIPTOR; } }; namespace JS { diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index 6a18183862b..70f6f67a6cc 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -231,7 +231,10 @@ js::DestroyContext(JSContext *cx, DestroyContextMode mode) MOZ_CRASH(); #endif - cx->checkNoGCRooters(); +#if defined(JSGC_USE_EXACT_ROOTING) && defined(DEBUG) + for (int i = 0; i < THING_ROOT_LIMIT; ++i) + JS_ASSERT(cx->thingGCRooters[i] == nullptr); +#endif if (mode != DCM_NEW_FAILED) { if (JSContextCallback cxCallback = rt->cxCallback) { @@ -262,14 +265,6 @@ js::DestroyContext(JSContext *cx, DestroyContextMode mode) js_delete_poison(cx); } -void -ContextFriendFields::checkNoGCRooters() { -#if defined(JSGC_USE_EXACT_ROOTING) && defined(DEBUG) - for (int i = 0; i < THING_ROOT_LIMIT; ++i) - JS_ASSERT(thingGCRooters[i] == nullptr); -#endif -} - bool AutoResolving::alreadyStartedSlow() const { diff --git a/js/src/jsinfer.h b/js/src/jsinfer.h index 60b6a545341..78cb8f47e59 100644 --- a/js/src/jsinfer.h +++ b/js/src/jsinfer.h @@ -309,8 +309,6 @@ class Type static inline Type ObjectType(JSObject *obj); static inline Type ObjectType(TypeObject *obj); static inline Type ObjectType(TypeObjectKey *obj); - - static js::ThingRootKind rootKind() { return js::THING_ROOT_TYPE; } }; /* Get the type of a jsval, or zero for an unknown special value. */ diff --git a/js/src/jspubtd.h b/js/src/jspubtd.h index c7d633974e4..4950a9e7c35 100644 --- a/js/src/jspubtd.h +++ b/js/src/jspubtd.h @@ -279,6 +279,7 @@ enum ThingRootKind THING_ROOT_TYPE, THING_ROOT_BINDINGS, THING_ROOT_PROPERTY_DESCRIPTOR, + THING_ROOT_CUSTOM, THING_ROOT_LIMIT }; @@ -346,31 +347,19 @@ struct ContextFriendFields } #ifdef JSGC_TRACK_EXACT_ROOTS - 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]); - } - #endif - 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); - template friend class JS::Rooted; }; /* @@ -425,19 +414,11 @@ struct PerThreadDataFriendFields PerThreadDataFriendFields(); #ifdef JSGC_TRACK_EXACT_ROOTS - 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]); - } #endif /* Limit pointer for checking native stack consumption. */ @@ -462,8 +443,6 @@ struct PerThreadDataFriendFields return reinterpret_cast( reinterpret_cast(rt) + RuntimeMainThreadOffset); } - - template friend class JS::Rooted; }; } /* namespace js */ diff --git a/js/src/jsscript.h b/js/src/jsscript.h index 929085153c9..4a12cdfc395 100644 --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -266,7 +266,6 @@ class Bindings return !callObjShape_->isEmptyShape(); } - static js::ThingRootKind rootKind() { return js::THING_ROOT_BINDINGS; } void trace(JSTracer *trc); }; diff --git a/js/src/vm/Shape.h b/js/src/vm/Shape.h index 152371185b4..b2f56c306da 100644 --- a/js/src/vm/Shape.h +++ b/js/src/vm/Shape.h @@ -853,6 +853,7 @@ struct StackBaseShape static inline bool match(UnownedBaseShape *key, const StackBaseShape *lookup); // For RootedGeneric + static inline js::ThingRootKind rootKind() { return js::THING_ROOT_CUSTOM; } void trace(JSTracer *trc); }; @@ -1504,6 +1505,7 @@ struct StackShape } // For RootedGeneric + static inline js::ThingRootKind rootKind() { return js::THING_ROOT_CUSTOM; } void trace(JSTracer *trc); };