Bug 1226687 - Part 1: Export a GCPolicy usable by JS::Heap; r=fitzgen

--HG--
extra : rebase_source : 7ac38143297ef92265faefe6ce800b6c55dcaa64
This commit is contained in:
Terrence Cole 2015-11-20 13:53:19 -08:00
parent 64b9c0ed0b
commit 2f587b2fc3
4 changed files with 54 additions and 13 deletions

View File

@ -586,7 +586,7 @@ struct JS_PUBLIC_API(MovableCellHasher)
};
template <typename T>
struct MovableCellHasher<JS::Heap<T>>
struct JS_PUBLIC_API(MovableCellHasher<JS::Heap<T>>)
{
using Key = JS::Heap<T>;
using Lookup = T;

View File

@ -311,6 +311,12 @@ JS_CallScriptTracer(JSTracer* trc, JS::Heap<JSScript*>* scriptp, const char* nam
extern JS_PUBLIC_API(void)
JS_CallFunctionTracer(JSTracer* trc, JS::Heap<JSFunction*>* funp, const char* name);
namespace JS {
template <typename T>
extern JS_PUBLIC_API(void)
TraceEdge(JSTracer* trc, JS::Heap<T>* edgep, const char* name);
} // namespace JS
// The following JS_CallUnbarriered*Tracer functions should only be called where
// you know for sure that a heap post barrier is not required. Use with extreme
// caution!
@ -358,6 +364,11 @@ JS_GetTraceThingInfo(char* buf, size_t bufsize, JSTracer* trc,
void* thing, JS::TraceKind kind, bool includeDetails);
namespace js {
namespace gc {
template <typename T>
extern JS_PUBLIC_API(bool)
EdgeNeedsSweep(JS::Heap<T>* edgep);
} // namespace gc
// Automates static dispatch for GC interaction with TraceableContainers.
template <typename>
@ -403,6 +414,17 @@ struct DefaultGCPolicy<jsid>
template <> struct DefaultGCPolicy<uint32_t> : public IgnoreGCPolicy<uint32_t> {};
template <typename T>
struct DefaultGCPolicy<JS::Heap<T>>
{
static void trace(JSTracer* trc, JS::Heap<T>* thingp, const char* name) {
JS::TraceEdge(trc, thingp, name);
}
static bool needsSweep(JS::Heap<T>* thingp) {
return gc::EdgeNeedsSweep(thingp);
}
};
} // namespace js
#endif /* js_TracingAPI_h */

View File

@ -398,6 +398,13 @@ js::TraceEdge(JSTracer* trc, WriteBarrieredBase<T>* thingp, const char* name)
DispatchToTracer(trc, ConvertToBase(thingp->unsafeUnbarrieredForTracing()), name);
}
template <typename T>
JS_PUBLIC_API(void)
JS::TraceEdge(JSTracer* trc, JS::Heap<T>* thingp, const char* name)
{
DispatchToTracer(trc, ConvertToBase(thingp->unsafeGet()), name);
}
template <typename T>
void
js::TraceManuallyBarrieredEdge(JSTracer* trc, T* thingp, const char* name)
@ -462,6 +469,7 @@ js::TraceRootRange(JSTracer* trc, size_t len, T* vec, const char* name)
// Instantiate a copy of the Tracing templates for each derived type.
#define INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS(type) \
template void js::TraceEdge<type>(JSTracer*, WriteBarrieredBase<type>*, const char*); \
template JS_PUBLIC_API(void) JS::TraceEdge<type>(JSTracer*, JS::Heap<type>*, const char*); \
template void js::TraceManuallyBarrieredEdge<type>(JSTracer*, type*, const char*); \
template void js::TraceWeakEdge<type>(JSTracer*, WeakRef<type>*, const char*); \
template void js::TraceRoot<type>(JSTracer*, type*, const char*); \
@ -2436,13 +2444,21 @@ IsAboutToBeFinalized(ReadBarrieredBase<T>* thingp)
return IsAboutToBeFinalizedInternal(ConvertToBase(thingp->unsafeUnbarrieredForTracing()));
}
template <typename T>
JS_PUBLIC_API(bool)
EdgeNeedsSweep(JS::Heap<T>* thingp)
{
return IsAboutToBeFinalizedInternal(ConvertToBase(thingp->unsafeGet()));
}
// Instantiate a copy of the Tracing templates for each derived type.
#define INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS(type) \
template bool IsMarkedUnbarriered<type>(type*); \
template bool IsMarked<type>(WriteBarrieredBase<type>*); \
template bool IsAboutToBeFinalizedUnbarriered<type>(type*); \
template bool IsAboutToBeFinalized<type>(WriteBarrieredBase<type>*); \
template bool IsAboutToBeFinalized<type>(ReadBarrieredBase<type>*);
template bool IsAboutToBeFinalized<type>(ReadBarrieredBase<type>*); \
template JS_PUBLIC_API(bool) EdgeNeedsSweep<type>(JS::Heap<type>*);
FOR_EACH_GC_POINTER_TYPE(INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS)
#undef INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS

View File

@ -463,30 +463,33 @@ void
CheckTracedThing(JSTracer* trc, T thing);
// Define a default Policy for all pointer types. This may fail to link if this
// policy gets used on a non-GC typed pointer by accident.
// policy gets used on a non-GC typed pointer by accident. There is a separate
// default policy for Value and jsid.
template <typename T>
struct DefaultGCPolicy<T*>
{
static void trace(JSTracer* trc, T** t, const char* name) {
static void trace(JSTracer* trc, T** thingp, const char* name) {
// If linking is failing here, it likely means that you need to define
// or use a non-default GC policy for your non-gc-pointer type.
TraceManuallyBarrieredEdge(trc, t, name);
TraceManuallyBarrieredEdge(trc, thingp, name);
}
static bool needsSweep(T** t) {
return gc::IsAboutToBeFinalizedUnbarriered(t);
static bool needsSweep(T** thingp) {
// If linking is failing here, it likely means that you need to define
// or use a non-default GC policy for your non-gc-pointer type.
return gc::IsAboutToBeFinalizedUnbarriered(thingp);
}
};
// RelocatablePtr is only defined for GC pointer types, so this default policy
// should work in all cases.
template <typename T>
struct DefaultGCPolicy<RelocatablePtr<T*>>
struct DefaultGCPolicy<RelocatablePtr<T>>
{
static void trace(JSTracer* trc, RelocatablePtr<T*> t, const char* name) {
TraceEdge(trc, t, name);
static void trace(JSTracer* trc, RelocatablePtr<T>* thingp, const char* name) {
TraceEdge(trc, thingp, name);
}
static bool needsSweep(RelocatablePtr<T*>* thingp) {
static bool needsSweep(RelocatablePtr<T>* thingp) {
return gc::IsAboutToBeFinalizedUnbarriered(thingp);
}
};
@ -494,8 +497,8 @@ struct DefaultGCPolicy<RelocatablePtr<T*>>
template <typename T>
struct DefaultGCPolicy<ReadBarriered<T>>
{
static void trace(JSTracer* trc, ReadBarriered<T> t, const char* name) {
TraceEdge(trc, t, name);
static void trace(JSTracer* trc, ReadBarriered<T>* thingp, const char* name) {
TraceEdge(trc, thingp, name);
}
static bool needsSweep(ReadBarriered<T>* thingp) {
return gc::IsAboutToBeFinalized(thingp);