Bug 1107639 - Remove public Add/RemoveRoot API r=terrence

This commit is contained in:
Jon Coppeard 2015-01-23 10:23:58 +00:00
parent 56abdc7b9a
commit fbac697693
6 changed files with 21 additions and 330 deletions

View File

@ -272,6 +272,11 @@ class ChainedIter
T operator->() const { return get(); }
};
typedef js::HashMap<Value *,
const char *,
js::DefaultHasher<Value *>,
js::SystemAllocPolicy> RootedValueMap;
class GCRuntime
{
public:
@ -284,8 +289,8 @@ class GCRuntime
inline bool upcomingZealousGC();
inline bool needZealousGC();
template <typename T> bool addRoot(T *rp, const char *name, JSGCRootType rootType);
void removeRoot(void *rp);
bool addRoot(Value *vp, const char *name);
void removeRoot(Value *vp);
void setMarkStackLimit(size_t limit);
void setParameter(JSGCParamKey key, uint32_t value);
@ -665,7 +670,7 @@ class GCRuntime
// so as to reduce the cost of operations on the available lists.
ChunkPool fullChunks_;
js::RootedValueMap rootsHash;
RootedValueMap rootsHash;
size_t maxMallocBytes;

View File

@ -445,21 +445,7 @@ js::gc::GCRuntime::markRuntime(JSTracer *trc,
for (RootRange r = rootsHash.all(); !r.empty(); r.popFront()) {
const RootEntry &entry = r.front();
const char *name = entry.value().name ? entry.value().name : "root";
JSGCRootType type = entry.value().type;
void *key = entry.key();
if (type == JS_GC_ROOT_VALUE_PTR) {
MarkValueRoot(trc, reinterpret_cast<Value *>(key), name);
} else if (*reinterpret_cast<void **>(key)){
if (type == JS_GC_ROOT_STRING_PTR)
MarkStringRoot(trc, reinterpret_cast<JSString **>(key), name);
else if (type == JS_GC_ROOT_OBJECT_PTR)
MarkObjectRoot(trc, reinterpret_cast<JSObject **>(key), name);
else if (type == JS_GC_ROOT_SCRIPT_PTR)
MarkScriptRoot(trc, reinterpret_cast<JSScript **>(key), name);
else
MOZ_CRASH("unexpected js::RootInfo::type value");
}
MarkValueRoot(trc, entry.key(), entry.value());
}
MarkPersistentRootedChains(trc);

View File

@ -1500,130 +1500,6 @@ JS_strdup(JSRuntime *rt, const char *s)
#undef JS_AddRoot
JS_PUBLIC_API(bool)
JS::AddValueRoot(JSContext *cx, JS::Heap<JS::Value> *vp)
{
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
return AddValueRoot(cx, vp->unsafeGet(), nullptr);
}
JS_PUBLIC_API(bool)
JS::AddStringRoot(JSContext *cx, JS::Heap<JSString *> *rp)
{
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
return AddStringRoot(cx, rp->unsafeGet(), nullptr);
}
JS_PUBLIC_API(bool)
JS::AddObjectRoot(JSContext *cx, JS::Heap<JSObject *> *rp)
{
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
return AddObjectRoot(cx, rp->unsafeGet(), nullptr);
}
JS_PUBLIC_API(bool)
JS::AddNamedValueRoot(JSContext *cx, JS::Heap<JS::Value> *vp, const char *name)
{
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
return AddValueRoot(cx, vp->unsafeGet(), name);
}
JS_PUBLIC_API(bool)
JS::AddNamedValueRootRT(JSRuntime *rt, JS::Heap<JS::Value> *vp, const char *name)
{
return AddValueRootRT(rt, vp->unsafeGet(), name);
}
JS_PUBLIC_API(bool)
JS::AddNamedStringRoot(JSContext *cx, JS::Heap<JSString *> *rp, const char *name)
{
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
return AddStringRoot(cx, rp->unsafeGet(), name);
}
JS_PUBLIC_API(bool)
JS::AddNamedObjectRoot(JSContext *cx, JS::Heap<JSObject *> *rp, const char *name)
{
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
return AddObjectRoot(cx, rp->unsafeGet(), name);
}
JS_PUBLIC_API(bool)
JS::AddNamedScriptRoot(JSContext *cx, JS::Heap<JSScript *> *rp, const char *name)
{
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
return AddScriptRoot(cx, rp->unsafeGet(), name);
}
/* We allow unrooting from finalizers within the GC */
JS_PUBLIC_API(void)
JS::RemoveValueRoot(JSContext *cx, JS::Heap<JS::Value> *vp)
{
CHECK_REQUEST(cx);
RemoveRoot(cx->runtime(), (void *)vp);
*vp = UndefinedValue();
}
JS_PUBLIC_API(void)
JS::RemoveStringRoot(JSContext *cx, JS::Heap<JSString *> *rp)
{
CHECK_REQUEST(cx);
RemoveRoot(cx->runtime(), (void *)rp);
*rp = nullptr;
}
JS_PUBLIC_API(void)
JS::RemoveObjectRoot(JSContext *cx, JS::Heap<JSObject *> *rp)
{
CHECK_REQUEST(cx);
RemoveRoot(cx->runtime(), (void *)rp);
*rp = nullptr;
}
JS_PUBLIC_API(void)
JS::RemoveScriptRoot(JSContext *cx, JS::Heap<JSScript *> *rp)
{
CHECK_REQUEST(cx);
RemoveRoot(cx->runtime(), (void *)rp);
*rp = nullptr;
}
JS_PUBLIC_API(void)
JS::RemoveValueRootRT(JSRuntime *rt, JS::Heap<JS::Value> *vp)
{
RemoveRoot(rt, (void *)vp);
*vp = UndefinedValue();
}
JS_PUBLIC_API(void)
JS::RemoveStringRootRT(JSRuntime *rt, JS::Heap<JSString *> *rp)
{
RemoveRoot(rt, (void *)rp);
*rp = nullptr;
}
JS_PUBLIC_API(void)
JS::RemoveObjectRootRT(JSRuntime *rt, JS::Heap<JSObject *> *rp)
{
RemoveRoot(rt, (void *)rp);
*rp = nullptr;
}
JS_PUBLIC_API(void)
JS::RemoveScriptRootRT(JSRuntime *rt, JS::Heap<JSScript *> *rp)
{
RemoveRoot(rt, (void *)rp);
*rp = nullptr;
}
JS_PUBLIC_API(bool)
JS_AddExtraGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data)
{

View File

@ -1996,83 +1996,6 @@ JS_strdup(JSContext *cx, const char *s);
extern JS_PUBLIC_API(char *)
JS_strdup(JSRuntime *rt, const char *s);
namespace JS {
/*
* A GC root is a pointer to a jsval, JSObject * or JSString * that itself
* points into the GC heap. JS_AddValueRoot takes a pointer to a jsval and
* JS_AddGCThingRoot takes a pointer to a JSObject * or JString *.
*
* Note that, since JS_Add*Root stores the address of a variable (of type
* jsval, JSString *, or JSObject *), that variable must live until
* JS_Remove*Root is called to remove that variable. For example, after:
*
* void some_function() {
* jsval v;
* JS_AddNamedValueRoot(cx, &v, "name");
*
* the caller must perform
*
* JS_RemoveValueRoot(cx, &v);
*
* before some_function() returns.
*
* Also, use JS_AddNamed*Root(cx, &structPtr->memberObj, "structPtr->memberObj")
* in preference to JS_Add*Root(cx, &structPtr->memberObj), in order to identify
* roots by their source callsites. This way, you can find the callsite while
* debugging if you should fail to do JS_Remove*Root(cx, &structPtr->memberObj)
* before freeing structPtr's memory.
*/
extern JS_PUBLIC_API(bool)
AddValueRoot(JSContext *cx, JS::Heap<JS::Value> *vp);
extern JS_PUBLIC_API(bool)
AddStringRoot(JSContext *cx, JS::Heap<JSString *> *rp);
extern JS_PUBLIC_API(bool)
AddObjectRoot(JSContext *cx, JS::Heap<JSObject *> *rp);
extern JS_PUBLIC_API(bool)
AddNamedValueRoot(JSContext *cx, JS::Heap<JS::Value> *vp, const char *name);
extern JS_PUBLIC_API(bool)
AddNamedValueRootRT(JSRuntime *rt, JS::Heap<JS::Value> *vp, const char *name);
extern JS_PUBLIC_API(bool)
AddNamedStringRoot(JSContext *cx, JS::Heap<JSString *> *rp, const char *name);
extern JS_PUBLIC_API(bool)
AddNamedObjectRoot(JSContext *cx, JS::Heap<JSObject *> *rp, const char *name);
extern JS_PUBLIC_API(bool)
AddNamedScriptRoot(JSContext *cx, JS::Heap<JSScript *> *rp, const char *name);
extern JS_PUBLIC_API(void)
RemoveValueRoot(JSContext *cx, JS::Heap<JS::Value> *vp);
extern JS_PUBLIC_API(void)
RemoveStringRoot(JSContext *cx, JS::Heap<JSString *> *rp);
extern JS_PUBLIC_API(void)
RemoveObjectRoot(JSContext *cx, JS::Heap<JSObject *> *rp);
extern JS_PUBLIC_API(void)
RemoveScriptRoot(JSContext *cx, JS::Heap<JSScript *> *rp);
extern JS_PUBLIC_API(void)
RemoveValueRootRT(JSRuntime *rt, JS::Heap<JS::Value> *vp);
extern JS_PUBLIC_API(void)
RemoveStringRootRT(JSRuntime *rt, JS::Heap<JSString *> *rp);
extern JS_PUBLIC_API(void)
RemoveObjectRootRT(JSRuntime *rt, JS::Heap<JSObject *> *rp);
extern JS_PUBLIC_API(void)
RemoveScriptRootRT(JSRuntime *rt, JS::Heap<JSScript *> *rp);
} /* namespace JS */
/*
* Register externally maintained GC roots.
*

View File

@ -1495,10 +1495,6 @@ GCRuntime::setMarkStackLimit(size_t limit)
marker.setMaxCapacity(limit);
}
template <typename T> struct BarrierOwner {};
template <typename T> struct BarrierOwner<T *> { typedef T result; };
template <> struct BarrierOwner<Value> { typedef HeapValue result; };
bool
GCRuntime::addBlackRootsTracer(JSTraceDataOp traceOp, void *data)
{
@ -1596,9 +1592,8 @@ GCRuntime::setSliceCallback(JS::GCSliceCallback callback) {
return stats.setSliceCallback(callback);
}
template <typename T>
bool
GCRuntime::addRoot(T *rp, const char *name, JSGCRootType rootType)
GCRuntime::addRoot(Value *vp, const char *name)
{
/*
* Sometimes Firefox will hold weak references to objects and then convert
@ -1607,87 +1602,33 @@ GCRuntime::addRoot(T *rp, const char *name, JSGCRootType rootType)
* cases.
*/
if (isIncrementalGCInProgress())
BarrierOwner<T>::result::writeBarrierPre(*rp);
HeapValue::writeBarrierPre(*vp);
return rootsHash.put((void *)rp, RootInfo(name, rootType));
return rootsHash.put(vp, name);
}
void
GCRuntime::removeRoot(void *rp)
GCRuntime::removeRoot(Value *vp)
{
rootsHash.remove(rp);
rootsHash.remove(vp);
poke();
}
template <typename T>
static bool
AddRoot(JSRuntime *rt, T *rp, const char *name, JSGCRootType rootType)
{
return rt->gc.addRoot(rp, name, rootType);
}
template <typename T>
static bool
AddRoot(JSContext *cx, T *rp, const char *name, JSGCRootType rootType)
{
bool ok = cx->runtime()->gc.addRoot(rp, name, rootType);
if (!ok)
JS_ReportOutOfMemory(cx);
return ok;
}
bool
js::AddValueRoot(JSContext *cx, Value *vp, const char *name)
{
return AddRoot(cx, vp, name, JS_GC_ROOT_VALUE_PTR);
}
extern bool
js::AddValueRootRT(JSRuntime *rt, js::Value *vp, const char *name)
{
return AddRoot(rt, vp, name, JS_GC_ROOT_VALUE_PTR);
}
extern bool
js::AddStringRoot(JSContext *cx, JSString **rp, const char *name)
{
return AddRoot(cx, rp, name, JS_GC_ROOT_STRING_PTR);
}
extern bool
js::AddObjectRoot(JSContext *cx, JSObject **rp, const char *name)
{
return AddRoot(cx, rp, name, JS_GC_ROOT_OBJECT_PTR);
}
extern bool
js::AddObjectRoot(JSRuntime *rt, JSObject **rp, const char *name)
{
return AddRoot(rt, rp, name, JS_GC_ROOT_OBJECT_PTR);
}
extern bool
js::AddScriptRoot(JSContext *cx, JSScript **rp, const char *name)
{
return AddRoot(cx, rp, name, JS_GC_ROOT_SCRIPT_PTR);
}
extern JS_FRIEND_API(bool)
js::AddRawValueRoot(JSContext *cx, Value *vp, const char *name)
{
return AddRoot(cx, vp, name, JS_GC_ROOT_VALUE_PTR);
MOZ_ASSERT(vp);
MOZ_ASSERT(name);
bool ok = cx->runtime()->gc.addRoot(vp, name);
if (!ok)
JS_ReportOutOfMemory(cx);
return ok;
}
extern JS_FRIEND_API(void)
js::RemoveRawValueRoot(JSContext *cx, Value *vp)
{
RemoveRoot(cx->runtime(), vp);
}
void
js::RemoveRoot(JSRuntime *rt, void *rp)
{
rt->gc.removeRoot(rp);
cx->runtime()->gc.removeRoot(vp);
}
void

View File

@ -832,46 +832,6 @@ const size_t MAX_EMPTY_CHUNK_AGE = 4;
} /* namespace gc */
typedef enum JSGCRootType {
JS_GC_ROOT_VALUE_PTR,
JS_GC_ROOT_STRING_PTR,
JS_GC_ROOT_OBJECT_PTR,
JS_GC_ROOT_SCRIPT_PTR
} JSGCRootType;
struct RootInfo {
RootInfo() {}
RootInfo(const char *name, JSGCRootType type) : name(name), type(type) {}
const char *name;
JSGCRootType type;
};
typedef js::HashMap<void *,
RootInfo,
js::DefaultHasher<void *>,
js::SystemAllocPolicy> RootedValueMap;
extern bool
AddValueRoot(JSContext *cx, js::Value *vp, const char *name);
extern bool
AddValueRootRT(JSRuntime *rt, js::Value *vp, const char *name);
extern bool
AddStringRoot(JSContext *cx, JSString **rp, const char *name);
extern bool
AddObjectRoot(JSContext *cx, JSObject **rp, const char *name);
extern bool
AddObjectRoot(JSRuntime *rt, JSObject **rp, const char *name);
extern bool
AddScriptRoot(JSContext *cx, JSScript **rp, const char *name);
extern void
RemoveRoot(JSRuntime *rt, void *rp);
} /* namespace js */
extern bool