#ifndef gc_Policy_h
#define gc_Policy_h
#include "mozilla/TypeTraits.h"
#include "gc/Barrier.h"
#include "gc/Marking.h"
#include "js/GCPolicyAPI.h"
namespace js {
template <typename T>
struct InternalGCPointerPolicy : public JS::GCPointerPolicy<T> {
using Type = typename mozilla::RemovePointer<T>::Type;
#define IS_BASE_OF_OR(_1, BaseType, _2) \
mozilla::IsBaseOf<BaseType, Type>::value ||
static_assert(
JS_FOR_EACH_TRACEKIND(IS_BASE_OF_OR) false,
"InternalGCPointerPolicy must only be used for GC thing pointers");
#undef IS_BASE_OF_OR
static void preBarrier(T v) {
if (v) {
Type::writeBarrierPre(v);
}
}
static void postBarrier(T* vp, T prev, T next) {
if (*vp) {
Type::writeBarrierPost(vp, prev, next);
}
}
static void readBarrier(T v) {
if (v) {
Type::readBarrier(v);
}
}
static void trace(JSTracer* trc, T* vp, const char* name) {
if (*vp) {
TraceManuallyBarrieredEdge(trc, vp, name);
}
}
};
}
namespace JS {
template <typename T>
struct GCPolicy<T*> : public js::InternalGCPointerPolicy<T*> {};
template <typename T>
struct GCPolicy<T* const> : public js::InternalGCPointerPolicy<T* const> {};
template <typename T>
struct GCPolicy<js::HeapPtr<T>> {
static void trace(JSTracer* trc, js::HeapPtr<T>* thingp, const char* name) {
js::TraceEdge(trc, thingp, name);
}
static bool needsSweep(js::HeapPtr<T>* thingp) {
return js::gc::IsAboutToBeFinalized(thingp);
}
};
template <typename T>
struct GCPolicy<js::ReadBarriered<T>> {
static void trace(JSTracer* trc, js::ReadBarriered<T>* thingp,
const char* name) {
js::TraceEdge(trc, thingp, name);
}
static bool needsSweep(js::ReadBarriered<T>* thingp) {
return js::gc::IsAboutToBeFinalized(thingp);
}
};
}
#endif