Bug 777548 - Make non-cc-participant tracing indirect; r=smaug,billm,jst

This commit is contained in:
Terrence Cole 2013-03-28 13:37:22 -07:00
Родитель 375f75b48c
Коммит b6490325af
29 изменённых файлов: 149 добавлений и 79 удалений

Просмотреть файл

@ -419,9 +419,7 @@ TraceActiveWindowGlobal(const uint64_t& aId, nsGlobalWindow*& aWindow, void* aCl
{
if (aWindow->GetDocShell() && aWindow->IsOuterWindow()) {
TraceClosure* closure = static_cast<TraceClosure*>(aClosure);
if (JSObject* global = aWindow->FastGetGlobalJSObject()) {
JS_CallObjectTracer(closure->mTrc, global, "active window global");
}
aWindow->TraceGlobalJSObject(closure->mTrc);
#ifdef MOZ_XUL
nsIDocument* doc = aWindow->GetExtantDoc();
if (doc && doc->IsXUL()) {

Просмотреть файл

@ -1647,7 +1647,8 @@ nsContentUtils::TraceSafeJSContext(JSTracer* aTrc)
return;
}
if (JSObject* global = JS_GetGlobalObject(cx)) {
JS_CallObjectTracer(aTrc, global, "safe context");
JS_CallObjectTracer(aTrc, &global, "safe context");
MOZ_ASSERT(global == JS_GetGlobalObject(cx));
}
}

Просмотреть файл

@ -2340,10 +2340,7 @@ nsXULPrototypeElement::TraceAllScripts(JSTracer* aTrc)
if (child->mType == nsXULPrototypeNode::eType_Element) {
static_cast<nsXULPrototypeElement*>(child)->TraceAllScripts(aTrc);
} else if (child->mType == nsXULPrototypeNode::eType_Script) {
JSScript* script = static_cast<nsXULPrototypeScript*>(child)->GetScriptObject();
if (script) {
JS_CallScriptTracer(aTrc, script, "active window XUL prototype script");
}
static_cast<nsXULPrototypeScript*>(child)->TraceScriptObject(aTrc);
}
}
}

Просмотреть файл

@ -241,6 +241,13 @@ public:
return mScriptObject;
}
void TraceScriptObject(JSTracer* aTrc)
{
if (mScriptObject) {
JS_CallScriptTracer(aTrc, &mScriptObject, "active window XUL prototype script");
}
}
nsCOMPtr<nsIURI> mSrcURI;
uint32_t mLineNo;
bool mSrcLoading;

Просмотреть файл

@ -660,7 +660,7 @@ static PLDHashOperator
MarkScriptsInGC(nsIURI* aKey, CacheScriptEntry& aScriptEntry, void* aClosure)
{
JSTracer* trc = static_cast<JSTracer*>(aClosure);
JS_CallScriptTracer(trc, aScriptEntry.mScriptObject,
JS_CallScriptTracer(trc, &aScriptEntry.mScriptObject,
"nsXULPrototypeCache script");
return PL_DHASH_NEXT;
}

Просмотреть файл

@ -1823,6 +1823,14 @@ nsGlobalWindow::GetGlobalJSObject()
return FastGetGlobalJSObject();
}
void
nsGlobalWindow::TraceGlobalJSObject(JSTracer* aTrc)
{
if (mJSObject) {
JS_CallObjectTracer(aTrc, &mJSObject, "active window global");
}
}
bool
nsGlobalWindow::WouldReuseInnerWindow(nsIDocument *aNewDocument)
{

Просмотреть файл

@ -303,6 +303,7 @@ public:
{
return mJSObject;
}
void TraceGlobalJSObject(JSTracer* aTrc);
virtual nsresult EnsureScriptEnvironment();

Просмотреть файл

@ -10,6 +10,7 @@
#include "mozilla/Assertions.h"
#include "js/RootingAPI.h"
struct JSTracer;
class JSObject;
struct JSContext;
class XPCWrappedNativeScope;
@ -189,6 +190,8 @@ private:
(mWrapperPtrBits & WRAPPER_IS_DOM_BINDING);
}
void TraceJSObjectFromBits(JSTracer *aTrc, const char *aName);
/**
* If this bit is set then we're preserving the wrapper, which in effect ties
* the lifetime of the JS object stored in the cache to the lifetime of the

Просмотреть файл

@ -8,6 +8,7 @@
#include "nsWrapperCache.h"
#include "xpcpublic.h"
#include "jsapi.h"
// We want to encode 3 bits into mWrapperPtrBits, so anything we store in it
// needs to be aligned on 8 byte boundaries.
@ -56,4 +57,10 @@ nsWrapperCache::IsBlackAndDoesNotNeedTracing(nsISupports* aThis)
return false;
}
inline void
nsWrapperCache::TraceJSObjectFromBits(JSTracer* aTrc, const char* aName)
{
JS_CallMaskedObjectTracer(aTrc, &mWrapperPtrBits, kWrapperBitMask, aName);
}
#endif /* nsWrapperCache_h___ */

Просмотреть файл

@ -256,9 +256,8 @@ TraceProtoAndIfaceCache(JSTracer* trc, JSObject* obj)
return;
JSObject** protoAndIfaceArray = GetProtoAndIfaceArray(obj);
for (size_t i = 0; i < kProtoAndIfaceCacheCount; ++i) {
JSObject* proto = protoAndIfaceArray[i];
if (proto) {
JS_CallObjectTracer(trc, proto, "protoAndIfaceArray[i]");
if (protoAndIfaceArray[i]) {
JS_CallObjectTracer(trc, &protoAndIfaceArray[i], "protoAndIfaceArray[i]");
}
}
}

Просмотреть файл

@ -2172,10 +2172,11 @@ NPObjectMember_Trace(JSTracer *trc, JSObject *obj)
// Our NPIdentifier is not always interned, so we must root it explicitly.
jsid id = NPIdentifierToJSId(memberPrivate->methodName);
JS_CallIdTracer(trc, id, "NPObjectMemberPrivate.methodName");
JS_CallIdTracer(trc, &id, "NPObjectMemberPrivate.methodName");
memberPrivate->methodName = JSIdToNPIdentifier(id);
if (!JSVAL_IS_PRIMITIVE(memberPrivate->fieldValue)) {
JS_CallValueTracer(trc, memberPrivate->fieldValue,
JS_CallValueTracer(trc, &memberPrivate->fieldValue,
"NPObject Member => fieldValue");
}
@ -2183,7 +2184,7 @@ NPObjectMember_Trace(JSTracer *trc, JSObject *obj)
// NPObject, so make sure to mark the NPObject wrapper to keep the
// NPObject alive as long as this NPObjectMember is alive.
if (memberPrivate->npobjWrapper) {
JS_CallObjectTracer(trc, memberPrivate->npobjWrapper,
JS_CallObjectTracer(trc, &memberPrivate->npobjWrapper,
"NPObject Member => npobjWrapper");
}
}

Просмотреть файл

@ -39,10 +39,7 @@ NS_INTERFACE_MAP_END
void
DOMBindingBase::_trace(JSTracer* aTrc)
{
JSObject* obj = GetJSObject();
if (obj) {
JS_CallObjectTracer(aTrc, obj, "cached wrapper");
}
TraceJSObject(aTrc, "cached wrapper");
}
void

Просмотреть файл

@ -46,6 +46,13 @@ public:
JSContext*
GetJSContext() const;
void
TraceJSObject(JSTracer* aTrc, const char* aName)
{
if (GetJSObject())
TraceJSObjectFromBits(aTrc, aName);
}
#ifdef DEBUG
JSObject*
GetJSObject() const;

Просмотреть файл

@ -185,7 +185,7 @@ EventListenerManager::TraceInternal(JSTracer* aTrc) const
listenerElem;
listenerElem = listenerElem->getNext()) {
JS_CallObjectTracer(aTrc,
listenerElem->mListener,
&const_cast<ListenerData*>(listenerElem)->mListener,
"EventListenerManager listener object");
}
}

Просмотреть файл

@ -3258,10 +3258,10 @@ WorkerPrivate::TraceInternal(JSTracer* aTrc)
for (uint32_t index = 0; index < mTimeouts.Length(); index++) {
TimeoutInfo* info = mTimeouts[index];
JS_CallValueTracer(aTrc, info->mTimeoutVal,
JS_CallValueTracer(aTrc, &info->mTimeoutVal,
"WorkerPrivate timeout value");
for (uint32_t index2 = 0; index2 < info->mExtraArgVals.Length(); index2++) {
JS_CallValueTracer(aTrc, info->mExtraArgVals[index2],
JS_CallValueTracer(aTrc, &info->mExtraArgVals[index2],
"WorkerPrivate timeout extra argument value");
}
}

Просмотреть файл

@ -128,7 +128,7 @@ protected:
_trace(JSTracer* aTrc) MOZ_OVERRIDE
{
for (int32_t i = 0; i < SLOT_COUNT; i++) {
JS_CallValueTracer(aTrc, mSlots[i], "WorkerGlobalScope instance slot");
JS_CallValueTracer(aTrc, &mSlots[i], "WorkerGlobalScope instance slot");
}
mWorker->TraceInternal(aTrc);
EventTarget::_trace(aTrc);

Просмотреть файл

@ -1421,9 +1421,9 @@ void
XMLHttpRequest::_trace(JSTracer* aTrc)
{
if (mUpload) {
JS_CallObjectTracer(aTrc, mUpload->GetJSObject(), "mUpload");
mUpload->TraceJSObject(aTrc, "mUpload");
}
JS_CallValueTracer(aTrc, mStateData.mResponse, "mResponse");
JS_CallValueTracer(aTrc, &mStateData.mResponse, "mResponse");
XMLHttpRequestEventTarget::_trace(aTrc);
}

Просмотреть файл

@ -23,7 +23,7 @@ void
XMLHttpRequestUpload::_trace(JSTracer* aTrc)
{
if (mXHR) {
JS_CallObjectTracer(aTrc, mXHR->GetJSObject(), "mXHR");
mXHR->TraceJSObject(aTrc, "mXHR");
}
XMLHttpRequestEventTarget::_trace(aTrc);
}

Просмотреть файл

@ -239,6 +239,10 @@ class ObjectPtr
return *this;
}
void trace(JSTracer *trc, const char *name) {
JS_CallObjectTracer(trc, &value, name);
}
JSObject &operator*() const { return *value; }
JSObject *operator->() const { return value; }
operator JSObject *() const { return value; }

Просмотреть файл

@ -715,7 +715,7 @@ CountHeap(JSContext *cx, unsigned argc, jsval *vp)
if (startValue.isUndefined()) {
JS_TraceRuntime(&countTracer.base);
} else {
JS_CallValueTracer(&countTracer.base, startValue, "root");
JS_CallValueTracer(&countTracer.base, startValue.address(), "root");
}
counter = 0;

Просмотреть файл

@ -3326,8 +3326,10 @@ CType::Trace(JSTracer* trc, JSObject* obj)
FieldInfoHash* fields =
static_cast<FieldInfoHash*>(JSVAL_TO_PRIVATE(slot));
for (FieldInfoHash::Range r = fields->all(); !r.empty(); r.popFront()) {
JS_CallStringTracer(trc, r.front().key, "fieldName");
JS_CallObjectTracer(trc, r.front().value.mType, "fieldType");
JSString *key = r.front().key;
JS_CallStringTracer(trc, &key, "fieldName");
JS_ASSERT(key == r.front().key);
JS_CallObjectTracer(trc, &r.front().value.mType, "fieldType");
}
break;
@ -3342,10 +3344,10 @@ CType::Trace(JSTracer* trc, JSObject* obj)
JS_ASSERT(fninfo);
// Identify our objects to the tracer.
JS_CallObjectTracer(trc, fninfo->mABI, "abi");
JS_CallObjectTracer(trc, fninfo->mReturnType, "returnType");
JS_CallObjectTracer(trc, &fninfo->mABI, "abi");
JS_CallObjectTracer(trc, &fninfo->mReturnType, "returnType");
for (size_t i = 0; i < fninfo->mArgTypes.length(); ++i)
JS_CallObjectTracer(trc, fninfo->mArgTypes[i], "argType");
JS_CallObjectTracer(trc, &fninfo->mArgTypes[i], "argType");
break;
}
@ -6078,10 +6080,10 @@ CClosure::Trace(JSTracer* trc, JSObject* obj)
// Identify our objects to the tracer. (There's no need to identify
// 'closureObj', since that's us.)
JS_CallObjectTracer(trc, cinfo->typeObj, "typeObj");
JS_CallObjectTracer(trc, cinfo->jsfnObj, "jsfnObj");
JS_CallObjectTracer(trc, &cinfo->typeObj, "typeObj");
JS_CallObjectTracer(trc, &cinfo->jsfnObj, "jsfnObj");
if (cinfo->thisObj)
JS_CallObjectTracer(trc, cinfo->thisObj, "thisObj");
JS_CallObjectTracer(trc, &cinfo->thisObj, "thisObj");
}
void

Просмотреть файл

@ -2477,43 +2477,47 @@ JS_SetExtraGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data)
}
JS_PUBLIC_API(void)
JS_CallValueTracer(JSTracer *trc, Value valueArg, const char *name)
JS_CallValueTracer(JSTracer *trc, Value *valuep, const char *name)
{
Value value = valueArg;
MarkValueUnbarriered(trc, &value, name);
JS_ASSERT(value == valueArg);
MarkValueUnbarriered(trc, valuep, name);
}
JS_PUBLIC_API(void)
JS_CallIdTracer(JSTracer *trc, jsid idArg, const char *name)
JS_CallIdTracer(JSTracer *trc, jsid *idp, const char *name)
{
jsid id = idArg;
MarkIdUnbarriered(trc, &id, name);
JS_ASSERT(id == idArg);
MarkIdUnbarriered(trc, idp, name);
}
JS_PUBLIC_API(void)
JS_CallObjectTracer(JSTracer *trc, JSObject *objArg, const char *name)
JS_CallObjectTracer(JSTracer *trc, JSObject **objp, const char *name)
{
JSObject *obj = objArg;
MarkObjectUnbarriered(trc, objp, name);
}
JS_PUBLIC_API(void)
JS_CallMaskedObjectTracer(JSTracer *trc, uintptr_t *objp, uintptr_t flagMask, const char *name)
{
uintptr_t flags = *objp & flagMask;
JSObject *obj = reinterpret_cast<JSObject *>(*objp & ~flagMask);
if (!obj)
return;
JS_SET_TRACING_LOCATION(trc, (void*)objp);
MarkObjectUnbarriered(trc, &obj, name);
JS_ASSERT(obj == objArg);
*objp = uintptr_t(obj) | flags;
}
JS_PUBLIC_API(void)
JS_CallStringTracer(JSTracer *trc, JSString *strArg, const char *name)
JS_CallStringTracer(JSTracer *trc, JSString **strp, const char *name)
{
JSString *str = strArg;
MarkStringUnbarriered(trc, &str, name);
JS_ASSERT(str == strArg);
MarkStringUnbarriered(trc, strp, name);
}
JS_PUBLIC_API(void)
JS_CallScriptTracer(JSTracer *trc, JSScript *scriptArg, const char *name)
JS_CallScriptTracer(JSTracer *trc, JSScript **scriptp, const char *name)
{
JSScript *script = scriptArg;
MarkScriptUnbarriered(trc, &script, name);
JS_ASSERT(script == scriptArg);
MarkScriptUnbarriered(trc, scriptp, name);
}
JS_PUBLIC_API(void)

Просмотреть файл

@ -907,8 +907,8 @@ typedef JSBool
/*
* Function type for trace operation of the class called to enumerate all
* traceable things reachable from obj's private data structure. For each such
* thing, a trace implementation must call one of the |JS_Call<Type>Tracer|
* variants on the thing.
* thing, a trace implementation must call one of the JS_Call*Tracer variants
* on the thing.
*
* JSTraceOp implementation can assume that no other threads mutates object
* state. It must not change state of the object or corresponding native
@ -2511,24 +2511,57 @@ struct JSTracer {
# define JS_SET_TRACING_NAME(trc, name) \
JS_SET_TRACING_DETAILS(trc, NULL, name, (size_t)-1)
/*
* The JS_Call*Tracer family of functions traces the given GC thing reference.
* This performs the tracing action configured on the given JSTracer:
* typically calling the JSTracer::callback or marking the thing as live.
*
* The argument to JS_Call*Tracer is an in-out param: when the function
* returns, the garbage collector might have moved the GC thing. In this case,
* the reference passed to JS_Call*Tracer will be updated to the object's new
* location. Callers of this method are responsible for updating any state
* that is dependent on the object's address. For example, if the object's
* address is used as a key in a hashtable, then the object must be removed
* and re-inserted with the correct hash.
*/
extern JS_PUBLIC_API(void)
JS_CallValueTracer(JSTracer *trc, JS::Value value, const char *name);
JS_CallValueTracer(JSTracer *trc, JS::Value *valuep, const char *name);
extern JS_PUBLIC_API(void)
JS_CallIdTracer(JSTracer *trc, jsid id, const char *name);
JS_CallIdTracer(JSTracer *trc, jsid *idp, const char *name);
extern JS_PUBLIC_API(void)
JS_CallObjectTracer(JSTracer *trc, JSObject *obj, const char *name);
JS_CallObjectTracer(JSTracer *trc, JSObject **objp, const char *name);
extern JS_PUBLIC_API(void)
JS_CallStringTracer(JSTracer *trc, JSString *str, const char *name);
JS_CallStringTracer(JSTracer *trc, JSString **strp, const char *name);
extern JS_PUBLIC_API(void)
JS_CallScriptTracer(JSTracer *trc, JSScript *script, const char *name);
JS_CallScriptTracer(JSTracer *trc, JSScript **scriptp, const char *name);
extern JS_PUBLIC_API(void)
JS_CallGenericTracer(JSTracer *trc, void *gcthing, const char *name);
template <typename HashSetEnum>
inline void
JS_CallHashSetObjectTracer(JSTracer *trc, HashSetEnum &e, JSObject *const &key, const char *name)
{
JSObject *updated = key;
JS_SET_TRACING_LOCATION(trc, reinterpret_cast<void *>(&const_cast<JSObject *&>(key)));
JS_CallObjectTracer(trc, &updated, name);
if (updated != key)
e.rekeyFront(key, updated);
}
/*
* The JS_CallMaskedObjectTracer variant traces a JSObject* that is stored
* with flags embedded in the low bits of the word. The flagMask parameter
* expects |*objp & flagMask| to yield the flags with the pointer value
* stripped and |*objp & ~flagMask| to yield a valid GC pointer.
*/
extern JS_PUBLIC_API(void)
JS_CallMaskedObjectTracer(JSTracer *trc, uintptr_t *objp, uintptr_t flagMask, const char *name);
/*
* API for JSTraceCallback implementations.
*/

Просмотреть файл

@ -430,7 +430,7 @@ void XPCJSRuntime::TraceXPConnectRoots(JSTracer *trc)
while (JSContext *acx = JS_ContextIterator(GetJSRuntime(), &iter)) {
MOZ_ASSERT(js::HasUnrootedGlobal(acx));
if (JSObject *global = JS_GetGlobalObject(acx))
JS_CallObjectTracer(trc, global, "XPC global object");
JS_CallObjectTracer(trc, &global, "XPC global object");
}
XPCAutoLock lock(mMapLock);

Просмотреть файл

@ -65,11 +65,9 @@ XPCTraceableVariant::~XPCTraceableVariant()
void XPCTraceableVariant::TraceJS(JSTracer* trc)
{
jsval val = GetJSValPreserveColor();
MOZ_ASSERT(JSVAL_IS_TRACEABLE(val));
MOZ_ASSERT(JSVAL_IS_TRACEABLE(mJSVal));
JS_SET_TRACING_DETAILS(trc, GetTraceName, this, 0);
JS_CallValueTracer(trc, val, "XPCTraceableVariant::mJSVal");
JS_CallValueTracer(trc, &mJSVal, "XPCTraceableVariant::mJSVal");
}
// static

Просмотреть файл

@ -214,7 +214,7 @@ nsXPCWrappedJS::TraceJS(JSTracer* trc)
{
NS_ASSERTION(mRefCnt >= 2 && IsValid(), "must be strongly referenced");
JS_SET_TRACING_DETAILS(trc, GetTraceName, this, 0);
JS_CallObjectTracer(trc, GetJSObjectPreserveColor(), "nsXPCWrappedJS::mJSObj");
JS_CallObjectTracer(trc, &mJSObj, "nsXPCWrappedJS::mJSObj");
}
// static

Просмотреть файл

@ -3581,7 +3581,7 @@ void
XPCJSObjectHolder::TraceJS(JSTracer *trc)
{
JS_SET_TRACING_DETAILS(trc, GetTraceName, this, 0);
JS_CallObjectTracer(trc, mJSObj, "XPCJSObjectHolder::mJSObj");
JS_CallObjectTracer(trc, &mJSObj, "XPCJSObjectHolder::mJSObj");
}
// static

Просмотреть файл

@ -402,8 +402,8 @@ XPCWrappedNativeScope::TraceWrappedNativesInAllScopes(JSTracer* trc, XPCJSRuntim
for (XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext) {
cur->mWrappedNativeMap->Enumerate(WrappedNativeJSGCThingTracer, trc);
if (cur->mDOMExpandoSet) {
for (DOMExpandoSet::Range r = cur->mDOMExpandoSet->all(); !r.empty(); r.popFront())
JS_CallObjectTracer(trc, r.front(), "DOM expando object");
for (DOMExpandoSet::Enum e(*cur->mDOMExpandoSet); !e.empty(); e.popFront())
JS_CallHashSetObjectTracer(trc, e, e.front(), "DOM expando object");
}
}
}

Просмотреть файл

@ -1617,11 +1617,10 @@ public:
TraceWrappedNativesInAllScopes(JSTracer* trc, XPCJSRuntime* rt);
void TraceSelf(JSTracer *trc) {
JSObject *obj = GetGlobalJSObjectPreserveColor();
MOZ_ASSERT(obj);
JS_CallObjectTracer(trc, obj, "XPCWrappedNativeScope::mGlobalJSObject");
MOZ_ASSERT(mGlobalJSObject);
mGlobalJSObject.trace(trc, "XPCWrappedNativeScope::mGlobalJSObject");
if (mXBLScope)
JS_CallObjectTracer(trc, mXBLScope, "XPCWrappedNativeScope::mXBLScope");
mXBLScope.trace(trc, "XPCWrappedNativeScope::mXBLScope");
}
static void
@ -2428,7 +2427,7 @@ public:
void TraceSelf(JSTracer *trc) {
if (mJSProtoObject)
JS_CallObjectTracer(trc, mJSProtoObject, "XPCWrappedNativeProto::mJSProtoObject");
mJSProtoObject.trace(trc, "XPCWrappedNativeProto::mJSProtoObject");
}
void TraceInside(JSTracer *trc) {
@ -2826,9 +2825,7 @@ public:
GetProto()->TraceSelf(trc);
else
GetScope()->TraceSelf(trc);
JSObject* wrapper = GetWrapperPreserveColor();
if (wrapper)
JS_CallObjectTracer(trc, wrapper, "XPCWrappedNative::mWrapper");
TraceWrapper(trc);
if (mFlatJSObject && mFlatJSObject != INVALID_OBJECT &&
JS_IsGlobalObject(mFlatJSObject))
{
@ -2847,7 +2844,7 @@ public:
// normally somebody else is doing that. Be careful not to trace the
// bogus INVALID_OBJECT value we can have during init, though.
if (mFlatJSObject && mFlatJSObject != INVALID_OBJECT) {
JS_CallObjectTracer(trc, mFlatJSObject,
JS_CallObjectTracer(trc, &mFlatJSObject,
"XPCWrappedNative::mFlatJSObject");
}
}
@ -2902,6 +2899,12 @@ public:
mWrapperWord = newval;
}
void TraceWrapper(JSTracer *trc)
{
JS_CallMaskedObjectTracer(trc, reinterpret_cast<uintptr_t *>(&mWrapperWord),
(uintptr_t)FLAG_MASK, "XPCWrappedNative::mWrapper");
}
// Returns the relevant same-compartment security if applicable, or
// mFlatJSObject otherwise.
//