Bug 1679736 - Prohibit Rooted<void*> r=jonco

Differential Revision: https://phabricator.services.mozilla.com/D98230
This commit is contained in:
Steve Fink 2020-12-03 23:05:29 +00:00
parent 984958944e
commit faadaa5160
5 changed files with 46 additions and 30 deletions

View File

@ -925,15 +925,22 @@ enum class AutoGCRooterKind : uint8_t {
Limit
};
// Our instantiations of Rooted<void*> and PersistentRooted<void*> require an
// instantiation of MapTypeToRootKind.
namespace detail {
// Dummy type to store root list entry pointers as. This code does not just use
// the actual type, because then eg JSObject* and JSFunction* would be assumed
// to never alias but they do (they are stored in the same list). Also, do not
// use `void*` so that `Rooted<void*>` is a compile error.
struct RootListEntry;
} // namespace detail
template <>
struct MapTypeToRootKind<void*> {
struct MapTypeToRootKind<detail::RootListEntry*> {
static const RootKind kind = RootKind::Traceable;
};
using RootedListHeads =
mozilla::EnumeratedArray<RootKind, RootKind::Limit, Rooted<void*>*>;
mozilla::EnumeratedArray<RootKind, RootKind::Limit,
Rooted<detail::RootListEntry*>*>;
using AutoRooterListHeads =
mozilla::EnumeratedArray<AutoGCRooterKind, AutoGCRooterKind::Limit,
@ -1073,7 +1080,7 @@ class MOZ_RAII Rooted : public js::RootedBase<T, Rooted<T>> {
inline void registerWithRootLists(RootedListHeads& roots) {
this->stack = &roots[JS::MapTypeToRootKind<T>::kind];
this->prev = *stack;
*stack = reinterpret_cast<Rooted<void*>*>(this);
*stack = reinterpret_cast<Rooted<detail::RootListEntry*>*>(this);
}
inline RootedListHeads& rootLists(RootingContext* cx) {
@ -1123,7 +1130,8 @@ class MOZ_RAII Rooted : public js::RootedBase<T, Rooted<T>> {
}
~Rooted() {
MOZ_ASSERT(*stack == reinterpret_cast<Rooted<void*>*>(this));
MOZ_ASSERT(*stack ==
reinterpret_cast<Rooted<detail::RootListEntry*>*>(this));
*stack = prev;
}
@ -1155,12 +1163,12 @@ class MOZ_RAII Rooted : public js::RootedBase<T, Rooted<T>> {
private:
/*
* These need to be templated on void* to avoid aliasing issues between, for
* example, Rooted<JSObject> and Rooted<JSFunction>, which use the same
* stack head pointer for different classes.
* These need to be templated on RootListEntry* to avoid aliasing issues
* between, for example, Rooted<JSObject*> and Rooted<JSFunction*>, which use
* the same stack head pointer for different classes.
*/
Rooted<void*>** stack;
Rooted<void*>* prev;
Rooted<detail::RootListEntry*>** stack;
Rooted<detail::RootListEntry*>* prev;
Ptr ptr;
@ -1289,11 +1297,13 @@ inline MutableHandle<T>::MutableHandle(PersistentRooted<T>* root) {
ptr = root->address();
}
JS_PUBLIC_API void AddPersistentRoot(RootingContext* cx, RootKind kind,
PersistentRooted<void*>* root);
JS_PUBLIC_API void AddPersistentRoot(
RootingContext* cx, RootKind kind,
PersistentRooted<detail::RootListEntry*>* root);
JS_PUBLIC_API void AddPersistentRoot(JSRuntime* rt, RootKind kind,
PersistentRooted<void*>* root);
JS_PUBLIC_API void AddPersistentRoot(
JSRuntime* rt, RootKind kind,
PersistentRooted<detail::RootListEntry*>* root);
/**
* A copyable, assignable global GC root type with arbitrary lifetime, an
@ -1342,15 +1352,17 @@ class PersistentRooted
void registerWithRootLists(RootingContext* cx) {
MOZ_ASSERT(!initialized());
JS::RootKind kind = JS::MapTypeToRootKind<T>::kind;
AddPersistentRoot(cx, kind,
reinterpret_cast<JS::PersistentRooted<void*>*>(this));
AddPersistentRoot(
cx, kind,
reinterpret_cast<JS::PersistentRooted<detail::RootListEntry*>*>(this));
}
void registerWithRootLists(JSRuntime* rt) {
MOZ_ASSERT(!initialized());
JS::RootKind kind = JS::MapTypeToRootKind<T>::kind;
AddPersistentRoot(rt, kind,
reinterpret_cast<JS::PersistentRooted<void*>*>(this));
AddPersistentRoot(
rt, kind,
reinterpret_cast<JS::PersistentRooted<detail::RootListEntry*>*>(this));
}
public:

View File

@ -215,6 +215,7 @@ const WHITELIST_TYPES: &'static [&'static str] = &[
"JS::Compartment",
"JS::Latin1Char",
"JS::detail::RootedPtr",
"JS::detail::RootListEntry",
"JS::MutableHandle",
"JS::MutableHandleObject",
"JS::MutableHandleValue",

View File

@ -366,7 +366,7 @@ impl<T> JS::Rooted<T> {
unsafe fn get_root_stack(
cx: *mut JSContext,
) -> *mut *mut JS::Rooted<*mut ::std::os::raw::c_void>
) -> *mut *mut JS::Rooted<*mut JS::detail::RootListEntry>
where
T: RootKind,
{

View File

@ -75,9 +75,9 @@ inline void JS::PersistentRooted<T>::trace(JSTracer* trc, const char* name) {
}
template <typename T>
static inline void TraceExactStackRootList(JSTracer* trc,
JS::Rooted<void*>* listHead,
const char* name) {
static inline void TraceExactStackRootList(
JSTracer* trc, JS::Rooted<JS::detail::RootListEntry*>* listHead,
const char* name) {
auto* typedList = reinterpret_cast<JS::Rooted<T>*>(listHead);
for (JS::Rooted<T>* root = typedList; root; root = root->previous()) {
root->trace(trc, name);
@ -112,7 +112,8 @@ static void TraceExactStackRoots(JSContext* cx, JSTracer* trc) {
template <typename T>
static inline void TracePersistentRootedList(
JSTracer* trc, LinkedList<PersistentRooted<void*>>& list,
JSTracer* trc,
LinkedList<PersistentRooted<JS::detail::RootListEntry*>>& list,
const char* name) {
auto& typedList = reinterpret_cast<LinkedList<PersistentRooted<T>>&>(list);
for (PersistentRooted<T>* root : typedList) {
@ -144,7 +145,7 @@ static void TracePersistentRooted(JSRuntime* rt, JSTracer* trc) {
template <typename T>
static void FinishPersistentRootedChain(
LinkedList<PersistentRooted<void*>>& listArg) {
LinkedList<PersistentRooted<JS::detail::RootListEntry*>>& listArg) {
auto& list = reinterpret_cast<LinkedList<PersistentRooted<T>>&>(listArg);
while (!list.isEmpty()) {
list.getFirst()->reset();
@ -634,13 +635,15 @@ void GCRuntime::resetBufferedGrayRoots() {
}
}
JS_PUBLIC_API void JS::AddPersistentRoot(JS::RootingContext* cx, RootKind kind,
PersistentRooted<void*>* root) {
JS_PUBLIC_API void JS::AddPersistentRoot(
JS::RootingContext* cx, RootKind kind,
PersistentRooted<JS::detail::RootListEntry*>* root) {
static_cast<JSContext*>(cx)->runtime()->heapRoots.ref()[kind].insertBack(
root);
}
JS_PUBLIC_API void JS::AddPersistentRoot(JSRuntime* rt, RootKind kind,
PersistentRooted<void*>* root) {
JS_PUBLIC_API void JS::AddPersistentRoot(
JSRuntime* rt, RootKind kind,
PersistentRooted<JS::detail::RootListEntry*>* root) {
rt->heapRoots.ref()[kind].insertBack(root);
}

View File

@ -394,7 +394,7 @@ struct JSRuntime {
// Heap GC roots for PersistentRooted pointers.
js::MainThreadData<mozilla::EnumeratedArray<
JS::RootKind, JS::RootKind::Limit,
mozilla::LinkedList<JS::PersistentRooted<void*>>>>
mozilla::LinkedList<JS::PersistentRooted<JS::detail::RootListEntry*>>>>
heapRoots;
void tracePersistentRoots(JSTracer* trc);