Bug 1188197 - Allow PersistentRooted to store DynamicTraceable; r=sfink

This commit is contained in:
Terrence Cole 2015-07-24 15:09:28 -07:00
parent 5b850bd74e
commit 0d78b57012
4 changed files with 68 additions and 3 deletions

View File

@ -997,6 +997,10 @@ template<typename T>
class PersistentRooted : public js::PersistentRootedBase<T>,
private mozilla::LinkedListElement<PersistentRooted<T>>
{
static_assert(!mozilla::IsConvertible<T, StaticTraceable*>::value &&
!mozilla::IsConvertible<T, DynamicTraceable*>::value,
"Rooted takes pointer or Traceable types but not Traceable* type");
typedef mozilla::LinkedListElement<PersistentRooted<T>> ListBase;
friend class mozilla::LinkedList<PersistentRooted>;
@ -1016,7 +1020,8 @@ class PersistentRooted : public js::PersistentRootedBase<T>,
kind == js::THING_ROOT_SCRIPT ||
kind == js::THING_ROOT_STRING ||
kind == js::THING_ROOT_ID ||
kind == js::THING_ROOT_VALUE);
kind == js::THING_ROOT_VALUE ||
kind == js::THING_ROOT_DYNAMIC_TRACEABLE);
}
public:

View File

@ -304,13 +304,14 @@ struct PersistentRootedMarker
{
typedef PersistentRooted<T> Element;
typedef mozilla::LinkedList<Element> List;
typedef void (*MarkFunc)(JSTracer* trc, T* ref, const char* name);
using TraceFunc = void (*)(JSTracer* trc, T* ref, const char* name);
template <TraceFunction<T> TraceFn = TraceNullableRoot>
static void
markChain(JSTracer* trc, List& list, const char* name)
{
for (Element* r = list.getFirst(); r; r = r->getNext())
TraceNullableRoot(trc, r->address(), name);
TraceFn(trc, r->address(), name);
}
};
@ -331,6 +332,11 @@ js::gc::MarkPersistentRootedChainsInLists(RootLists& roots, JSTracer* trc)
"PersistentRooted<jsid>");
PersistentRootedMarker<Value>::markChain(trc, roots.getPersistentRootedList<Value>(),
"PersistentRooted<Value>");
PersistentRootedMarker<ConcreteTraceable>::markChain<MarkDynamicTraceable>(trc,
reinterpret_cast<mozilla::LinkedList<JS::PersistentRooted<ConcreteTraceable>>&>(
roots.heapRoots_[THING_ROOT_DYNAMIC_TRACEABLE]),
"PersistentRooted<Value>");
}
void

View File

@ -123,6 +123,15 @@ struct RootedBase<DynamicContainer> {
RelocatablePtrObject& obj() { return static_cast<Rooted<DynamicContainer>*>(this)->get().obj; }
RelocatablePtrString& str() { return static_cast<Rooted<DynamicContainer>*>(this)->get().str; }
};
template <>
struct PersistentRootedBase<DynamicContainer> {
RelocatablePtrObject& obj() {
return static_cast<PersistentRooted<DynamicContainer>*>(this)->get().obj;
}
RelocatablePtrString& str() {
return static_cast<PersistentRooted<DynamicContainer>*>(this)->get().str;
}
};
} // namespace js
BEGIN_TEST(testGCRootedDynamicStructInternalStackStorage)
@ -153,6 +162,40 @@ BEGIN_TEST(testGCRootedDynamicStructInternalStackStorageAugmented)
JS::RootedObject obj(cx, container.obj());
JS::RootedValue val(cx, StringValue(container.str()));
CHECK(JS_SetProperty(cx, obj, "foo", val));
obj = nullptr;
val = UndefinedValue();
{
JS::RootedString actual(cx);
bool same;
// Automatic move from stack to heap.
JS::PersistentRooted<DynamicContainer> heap(cx, container);
// clear prior rooting.
container.obj() = nullptr;
container.str() = nullptr;
obj = heap.obj();
CHECK(JS_GetProperty(cx, obj, "foo", &val));
actual = val.toString();
CHECK(JS_StringEqualsAscii(cx, actual, "Hello", &same));
CHECK(same);
obj = nullptr;
actual = nullptr;
JS_GC(cx->runtime());
JS_GC(cx->runtime());
obj = heap.obj();
CHECK(JS_GetProperty(cx, obj, "foo", &val));
actual = val.toString();
CHECK(JS_StringEqualsAscii(cx, actual, "Hello", &same));
CHECK(same);
obj = nullptr;
actual = nullptr;
}
return true;
}
END_TEST(testGCRootedDynamicStructInternalStackStorageAugmented)
@ -232,6 +275,16 @@ BEGIN_TEST(testGCHandleHashMap)
CHECK(CheckMyHashMap(cx, map));
// Unfortunately, the type of get() needs to be non-const ref, so
// we need to explicitly Move the storage.
JS::PersistentRooted<MyHashMap> heapMap(cx, mozilla::Move(map.get()));
CHECK(CheckMyHashMap(cx, heapMap));
JS_GC(rt);
JS_GC(rt);
CHECK(CheckMyHashMap(cx, heapMap));
return true;
}
END_TEST(testGCHandleHashMap)

View File

@ -1371,6 +1371,7 @@ js::gc::FinishPersistentRootedChains(RootLists& roots)
FinishPersistentRootedChain(roots.getPersistentRootedList<JSString*>());
FinishPersistentRootedChain(roots.getPersistentRootedList<jsid>());
FinishPersistentRootedChain(roots.getPersistentRootedList<Value>());
FinishPersistentRootedChain(roots.heapRoots_[THING_ROOT_DYNAMIC_TRACEABLE]);
}
void