зеркало из https://github.com/mozilla/gecko-dev.git
Bug 888338 - 1 - Add TenuredHeap<T> class r=terrence r=bz
This commit is contained in:
Родитель
f0b09dd716
Коммит
e526358777
|
@ -1650,6 +1650,7 @@ nsContentUtils::TraceSafeJSContext(JSTracer* aTrc)
|
|||
return;
|
||||
}
|
||||
if (JSObject* global = js::GetDefaultGlobalForContext(cx)) {
|
||||
JS::AssertGCThingMustBeTenured(global);
|
||||
JS_CallObjectTracer(aTrc, &global, "safe context");
|
||||
MOZ_ASSERT(global == js::GetDefaultGlobalForContext(cx));
|
||||
}
|
||||
|
|
|
@ -1027,7 +1027,6 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
|
|||
mTimeoutInsertionPoint(nullptr),
|
||||
mTimeoutPublicIdCounter(1),
|
||||
mTimeoutFiringDepth(0),
|
||||
mJSObject(nullptr),
|
||||
mTimeoutsSuspendDepth(0),
|
||||
mFocusMethod(0),
|
||||
mSerial(0),
|
||||
|
@ -1865,7 +1864,7 @@ void
|
|||
nsGlobalWindow::TraceGlobalJSObject(JSTracer* aTrc)
|
||||
{
|
||||
if (mJSObject) {
|
||||
JS_CallObjectTracer(aTrc, &mJSObject, "active window global");
|
||||
JS_CallTenuredObjectTracer(aTrc, &mJSObject, "active window global");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2117,14 +2116,13 @@ CreateNativeGlobalForInner(JSContext* aCx,
|
|||
nsGlobalWindow* aNewInner,
|
||||
nsIURI* aURI,
|
||||
nsIPrincipal* aPrincipal,
|
||||
JSObject** aNativeGlobal,
|
||||
JS::TenuredHeap<JSObject*>& aNativeGlobal,
|
||||
nsIXPConnectJSObjectHolder** aHolder)
|
||||
{
|
||||
MOZ_ASSERT(aCx);
|
||||
MOZ_ASSERT(aNewInner);
|
||||
MOZ_ASSERT(aNewInner->IsInnerWindow());
|
||||
MOZ_ASSERT(aPrincipal);
|
||||
MOZ_ASSERT(aNativeGlobal);
|
||||
MOZ_ASSERT(aHolder);
|
||||
|
||||
nsGlobalWindow *top = NULL;
|
||||
|
@ -2154,13 +2152,13 @@ CreateNativeGlobalForInner(JSContext* aCx,
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
MOZ_ASSERT(jsholder);
|
||||
*aNativeGlobal = jsholder->GetJSObject();
|
||||
aNativeGlobal = jsholder->GetJSObject();
|
||||
jsholder.forget(aHolder);
|
||||
|
||||
// Set the location information for the new global, so that tools like
|
||||
// about:memory may use that information
|
||||
MOZ_ASSERT(*aNativeGlobal);
|
||||
xpc::SetLocationForGlobal(*aNativeGlobal, aURI);
|
||||
MOZ_ASSERT(aNativeGlobal.getPtr());
|
||||
xpc::SetLocationForGlobal(aNativeGlobal, aURI);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -2353,7 +2351,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
|||
rv = CreateNativeGlobalForInner(cx, newInnerWindow,
|
||||
aDocument->GetDocumentURI(),
|
||||
aDocument->NodePrincipal(),
|
||||
&newInnerWindow->mJSObject,
|
||||
newInnerWindow->mJSObject,
|
||||
getter_AddRefs(mInnerWindowHolder));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) && newInnerWindow->mJSObject && mInnerWindowHolder,
|
||||
"Failed to get script global and holder");
|
||||
|
@ -3153,7 +3151,7 @@ nsGlobalWindow::PoisonOuterWindowProxy(JSObject *aObject)
|
|||
{
|
||||
MOZ_ASSERT(IsOuterWindow());
|
||||
if (aObject == mJSObject) {
|
||||
mJSObject = reinterpret_cast<JSObject*>(0x1);
|
||||
mJSObject.setToCrashOnTouch();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1225,7 +1225,9 @@ protected:
|
|||
|
||||
// These member variables are used on both inner and the outer windows.
|
||||
nsCOMPtr<nsIPrincipal> mDocumentPrincipal;
|
||||
JSObject* mJSObject;
|
||||
|
||||
// The JS global object. Global objects are always allocated tenured.
|
||||
JS::TenuredHeap<JSObject*> mJSObject;
|
||||
|
||||
typedef nsCOMArray<nsIDOMStorageEvent> nsDOMStorageEventArray;
|
||||
nsDOMStorageEventArray mPendingStorageEvents;
|
||||
|
|
|
@ -169,21 +169,19 @@ struct JS_PUBLIC_API(NullPtr)
|
|||
};
|
||||
|
||||
/*
|
||||
* An encapsulated pointer class for heap based GC thing pointers.
|
||||
* The Heap<T> class is a C/C++ heap-stored reference to a JS GC thing. All
|
||||
* members of heap classes that refer to GC thing should use Heap<T> (or
|
||||
* possibly TenuredHeap<T>, described below).
|
||||
*
|
||||
* This implements post-barriers for GC thing pointers stored on the heap. It is
|
||||
* designed to be used for all heap-based GC thing pointers outside the JS
|
||||
* engine.
|
||||
* Heap<T> wraps the complex mechanisms required to ensure GC safety for the
|
||||
* contained reference into a C++ class that behaves similarly to a normal
|
||||
* pointer.
|
||||
*
|
||||
* The template parameter T must be a JS GC thing pointer, masked pointer or
|
||||
* possible pointer, such as a JS::Value or jsid.
|
||||
* GC references stored on the C/C++ stack must use Rooted/Handle/MutableHandle
|
||||
* instead.
|
||||
*
|
||||
* The class must be used to declare data members of heap classes only.
|
||||
* Stack-based GC thing pointers should used Rooted<T>.
|
||||
*
|
||||
* Write barriers are implemented by overloading the assingment operator.
|
||||
* Assiging to a Heap<T> triggers the appropriate calls into the GC to notify it
|
||||
* of the change.
|
||||
* Requirements for type T:
|
||||
* - Must be one of: Value, jsid, JSObject*, JSString*, JSScript*
|
||||
*/
|
||||
template <typename T>
|
||||
class Heap : public js::HeapBase<T>
|
||||
|
@ -257,6 +255,117 @@ class Heap : public js::HeapBase<T>
|
|||
T ptr;
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* For generational GC, assert that an object is in the tenured generation as
|
||||
* opposed to being in the nursery.
|
||||
*/
|
||||
extern JS_FRIEND_API(void)
|
||||
AssertGCThingMustBeTenured(JSObject* obj);
|
||||
#else
|
||||
inline void
|
||||
AssertGCThingMustBeTenured(JSObject *obj) {}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The TenuredHeap<T> class is similar to the Heap<T> class above in that it
|
||||
* encapsulates the GC concerns of an on-heap reference to a JS object. However,
|
||||
* it has two important differences:
|
||||
*
|
||||
* 1) Pointers which are statically known to only reference "tenured" objects
|
||||
* can avoid the extra overhead of SpiderMonkey's write barriers.
|
||||
*
|
||||
* 2) Objects in the "tenured" heap have stronger alignment restrictions than
|
||||
* those in the "nursery", so it is possible to store flags in the lower
|
||||
* bits of pointers known to be tenured. TenuredHeap wraps a normal tagged
|
||||
* pointer with a nice API for accessing the flag bits and adds various
|
||||
* assertions to ensure that it is not mis-used.
|
||||
*
|
||||
* GC things are said to be "tenured" when they are located in the long-lived
|
||||
* heap: e.g. they have gained tenure as an object by surviving past at least
|
||||
* one GC. For performance, SpiderMonkey allocates some things which are known
|
||||
* to normally be long lived directly into the tenured generation; for example,
|
||||
* global objects. Additionally, SpiderMonkey does not visit individual objects
|
||||
* when deleting non-tenured objects, so object with finalizers are also always
|
||||
* tenured; for instance, this includes most DOM objects.
|
||||
*
|
||||
* The considerations to keep in mind when using a TenuredHeap<T> vs a normal
|
||||
* Heap<T> are:
|
||||
*
|
||||
* - It is invalid for a TenuredHeap<T> to refer to a non-tenured thing.
|
||||
* - It is however valid for a Heap<T> to refer to a tenured thing.
|
||||
* - It is not possible to store flag bits in a Heap<T>.
|
||||
*/
|
||||
template <typename T>
|
||||
class TenuredHeap : public js::HeapBase<T>
|
||||
{
|
||||
public:
|
||||
TenuredHeap() : bits(0) {
|
||||
MOZ_STATIC_ASSERT(sizeof(T) == sizeof(TenuredHeap<T>),
|
||||
"TenuredHeap<T> must be binary compatible with T.");
|
||||
}
|
||||
explicit TenuredHeap(T p) : bits(0) { setPtr(p); }
|
||||
explicit TenuredHeap(const TenuredHeap<T> &p) : bits(0) { setPtr(p.ptr); }
|
||||
|
||||
bool operator==(const TenuredHeap<T> &other) { return bits == other.bits; }
|
||||
bool operator!=(const TenuredHeap<T> &other) { return bits != other.bits; }
|
||||
|
||||
void setPtr(T newPtr) {
|
||||
JS_ASSERT((reinterpret_cast<uintptr_t>(newPtr) & flagsMask) == 0);
|
||||
JS_ASSERT(!js::GCMethods<T>::poisoned(newPtr));
|
||||
if (newPtr)
|
||||
AssertGCThingMustBeTenured(newPtr);
|
||||
bits = (bits & flagsMask) | reinterpret_cast<uintptr_t>(newPtr);
|
||||
}
|
||||
|
||||
void setFlags(uintptr_t flagsToSet) {
|
||||
JS_ASSERT((flagsToSet & ~flagsMask) == 0);
|
||||
bits |= flagsToSet;
|
||||
}
|
||||
|
||||
void unsetFlags(uintptr_t flagsToUnset) {
|
||||
JS_ASSERT((flagsToUnset & ~flagsMask) == 0);
|
||||
bits &= ~flagsToUnset;
|
||||
}
|
||||
|
||||
bool hasFlag(uintptr_t flag) const {
|
||||
JS_ASSERT((flag & ~flagsMask) == 0);
|
||||
return (bits & flag) != 0;
|
||||
}
|
||||
|
||||
T getPtr() const { return reinterpret_cast<T>(bits & ~flagsMask); }
|
||||
uintptr_t getFlags() const { return bits & flagsMask; }
|
||||
|
||||
operator T() const { return getPtr(); }
|
||||
T operator->() const { return getPtr(); }
|
||||
|
||||
TenuredHeap<T> &operator=(T p) {
|
||||
setPtr(p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the pointer to a value which will cause a crash if it is
|
||||
* dereferenced.
|
||||
*/
|
||||
void setToCrashOnTouch() {
|
||||
bits = (bits & flagsMask) | crashOnTouchPointer;
|
||||
}
|
||||
|
||||
bool isSetToCrashOnTouch() {
|
||||
return (bits & ~flagsMask) == crashOnTouchPointer;
|
||||
}
|
||||
|
||||
private:
|
||||
enum {
|
||||
maskBits = 3,
|
||||
flagsMask = (1 << maskBits) - 1,
|
||||
crashOnTouchPointer = 1 << maskBits
|
||||
};
|
||||
|
||||
uintptr_t bits;
|
||||
};
|
||||
|
||||
/*
|
||||
* Reference to a T that has been rooted elsewhere. This is most useful
|
||||
* as a parameter type, which guarantees that the T lvalue is properly
|
||||
|
|
|
@ -2362,17 +2362,16 @@ JS_CallObjectTracer(JSTracer *trc, JSObject **objp, const char *name)
|
|||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_CallMaskedObjectTracer(JSTracer *trc, uintptr_t *objp, uintptr_t flagMask, const char *name)
|
||||
JS_CallTenuredObjectTracer(JSTracer *trc, JS::TenuredHeap<JSObject *> *objp, const char *name)
|
||||
{
|
||||
uintptr_t flags = *objp & flagMask;
|
||||
JSObject *obj = reinterpret_cast<JSObject *>(*objp & ~flagMask);
|
||||
JSObject *obj = objp->getPtr();
|
||||
if (!obj)
|
||||
return;
|
||||
|
||||
JS_SET_TRACING_LOCATION(trc, (void*)objp);
|
||||
MarkObjectUnbarriered(trc, &obj, name);
|
||||
|
||||
*objp = uintptr_t(obj) | flags;
|
||||
objp->setPtr(obj);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
|
|
|
@ -2586,13 +2586,11 @@ JS_CallHashSetObjectTracer(JSTracer *trc, HashSetEnum &e, JSObject *const &key,
|
|||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* Trace an object that is known to always be tenured. No post barriers are
|
||||
* required in this case.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_CallMaskedObjectTracer(JSTracer *trc, uintptr_t *objp, uintptr_t flagMask, const char *name);
|
||||
JS_CallTenuredObjectTracer(JSTracer *trc, JS::TenuredHeap<JSObject *> *objp, const char *name);
|
||||
|
||||
/*
|
||||
* API for JSTraceCallback implementations.
|
||||
|
|
|
@ -5107,4 +5107,11 @@ AutoDisableProxyCheck::AutoDisableProxyCheck(JSRuntime *rt
|
|||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
count++;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
JS::AssertGCThingMustBeTenured(JSObject *obj)
|
||||
{
|
||||
JS_ASSERT((!IsNurseryAllocable(obj->tenuredGetAllocKind()) || obj->getClass()->finalize) &&
|
||||
obj->isTenured());
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -151,7 +151,7 @@ template <> struct MapTypeToTraceKind<JSLinearString> { const static JSGCTrace
|
|||
template <> struct MapTypeToTraceKind<PropertyName> { const static JSGCTraceKind kind = JSTRACE_STRING; };
|
||||
template <> struct MapTypeToTraceKind<ion::IonCode> { const static JSGCTraceKind kind = JSTRACE_IONCODE; };
|
||||
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
#if defined(JSGC_GENERATIONAL) || defined(DEBUG)
|
||||
static inline bool
|
||||
IsNurseryAllocable(AllocKind kind)
|
||||
{
|
||||
|
|
|
@ -367,6 +367,7 @@ XPCWrappedNative::WrapNewGlobal(xpcObjectHelper &nativeHelper,
|
|||
|
||||
// Set the JS object to the global we already created.
|
||||
wrapper->mFlatJSObject = global;
|
||||
wrapper->mFlatJSObject.setFlags(FLAT_JS_OBJECT_VALID);
|
||||
|
||||
// Set the private to the XPCWrappedNative.
|
||||
JS_SetPrivate(global, wrapper);
|
||||
|
@ -757,11 +758,10 @@ XPCWrappedNative::XPCWrappedNative(already_AddRefed<nsISupports> aIdentity,
|
|||
XPCWrappedNativeProto* aProto)
|
||||
: mMaybeProto(aProto),
|
||||
mSet(aProto->GetSet()),
|
||||
mFlatJSObject(INVALID_OBJECT), // non-null to pass IsValid() test
|
||||
mScriptableInfo(nullptr),
|
||||
mWrapperWord(0)
|
||||
mScriptableInfo(nullptr)
|
||||
{
|
||||
mIdentity = aIdentity.get();
|
||||
mFlatJSObject.setFlags(FLAT_JS_OBJECT_VALID);
|
||||
|
||||
NS_ASSERTION(mMaybeProto, "bad ctor param");
|
||||
NS_ASSERTION(mSet, "bad ctor param");
|
||||
|
@ -776,11 +776,10 @@ XPCWrappedNative::XPCWrappedNative(already_AddRefed<nsISupports> aIdentity,
|
|||
|
||||
: mMaybeScope(TagScope(aScope)),
|
||||
mSet(aSet),
|
||||
mFlatJSObject(INVALID_OBJECT), // non-null to pass IsValid() test
|
||||
mScriptableInfo(nullptr),
|
||||
mWrapperWord(0)
|
||||
mScriptableInfo(nullptr)
|
||||
{
|
||||
mIdentity = aIdentity.get();
|
||||
mFlatJSObject.setFlags(FLAT_JS_OBJECT_VALID);
|
||||
|
||||
NS_ASSERTION(aScope, "bad ctor param");
|
||||
NS_ASSERTION(aSet, "bad ctor param");
|
||||
|
@ -795,8 +794,6 @@ XPCWrappedNative::~XPCWrappedNative()
|
|||
Destroy();
|
||||
}
|
||||
|
||||
static const intptr_t WRAPPER_WORD_POISON = 0xa8a8a8a8;
|
||||
|
||||
void
|
||||
XPCWrappedNative::Destroy()
|
||||
{
|
||||
|
@ -835,14 +832,14 @@ XPCWrappedNative::Destroy()
|
|||
* The only time GetRuntime() will be NULL is if Destroy is called a second
|
||||
* time on a wrapped native. Since we already unregistered the pointer the
|
||||
* first time, there's no need to unregister again. Unregistration is safe
|
||||
* the first time because mWrapperWord isn't used afterwards.
|
||||
* the first time because mWrapper isn't used afterwards.
|
||||
*/
|
||||
if (XPCJSRuntime *rt = GetRuntime()) {
|
||||
if (IsIncrementalBarrierNeeded(rt->Runtime()))
|
||||
IncrementalObjectBarrier(GetWrapperPreserveColor());
|
||||
mWrapperWord = WRAPPER_WORD_POISON;
|
||||
mWrapper.setToCrashOnTouch();
|
||||
} else {
|
||||
MOZ_ASSERT(mWrapperWord == WRAPPER_WORD_POISON);
|
||||
MOZ_ASSERT(mWrapper.isSetToCrashOnTouch());
|
||||
}
|
||||
|
||||
mMaybeScope = nullptr;
|
||||
|
@ -1033,9 +1030,12 @@ XPCWrappedNative::Init(HandleObject parent,
|
|||
}
|
||||
|
||||
mFlatJSObject = JS_NewObject(cx, jsclazz, protoJSObject, parent);
|
||||
if (!mFlatJSObject)
|
||||
if (!mFlatJSObject) {
|
||||
mFlatJSObject.unsetFlags(FLAT_JS_OBJECT_VALID);
|
||||
return false;
|
||||
}
|
||||
|
||||
mFlatJSObject.setFlags(FLAT_JS_OBJECT_VALID);
|
||||
JS_SetPrivate(mFlatJSObject, this);
|
||||
|
||||
return FinishInit();
|
||||
|
@ -1179,8 +1179,8 @@ XPCWrappedNative::FlatJSObjectFinalized()
|
|||
if (cache)
|
||||
cache->ClearWrapper();
|
||||
|
||||
// This makes IsValid return false from now on...
|
||||
mFlatJSObject = nullptr;
|
||||
mFlatJSObject.unsetFlags(FLAT_JS_OBJECT_VALID);
|
||||
|
||||
NS_ASSERTION(mIdentity, "bad pointer!");
|
||||
#ifdef XP_WIN
|
||||
|
@ -1227,7 +1227,8 @@ XPCWrappedNative::SystemIsBeingShutDown()
|
|||
|
||||
// short circuit future finalization
|
||||
JS_SetPrivate(mFlatJSObject, nullptr);
|
||||
mFlatJSObject = nullptr; // This makes 'IsValid()' return false.
|
||||
mFlatJSObject = nullptr;
|
||||
mFlatJSObject.unsetFlags(FLAT_JS_OBJECT_VALID);
|
||||
|
||||
XPCWrappedNativeProto* proto = GetProto();
|
||||
|
||||
|
@ -1472,7 +1473,10 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCWrappedNativeScope* aOldScope,
|
|||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(flat);
|
||||
wrapper->mFlatJSObject = flat;
|
||||
wrapper->mFlatJSObject.setFlags(FLAT_JS_OBJECT_VALID);
|
||||
|
||||
if (cache) {
|
||||
bool preserving = cache->PreservingWrapper();
|
||||
cache->SetPreservingWrapper(false);
|
||||
|
@ -2934,7 +2938,7 @@ NS_IMETHODIMP XPCWrappedNative::DebugDump(int16_t depth)
|
|||
else
|
||||
XPC_LOG_ALWAYS(("mSet @ %x", mSet));
|
||||
|
||||
XPC_LOG_ALWAYS(("mFlatJSObject of %x", mFlatJSObject));
|
||||
XPC_LOG_ALWAYS(("mFlatJSObject of %x", mFlatJSObject.getPtr()));
|
||||
XPC_LOG_ALWAYS(("mIdentity of %x", mIdentity));
|
||||
XPC_LOG_ALWAYS(("mScriptableInfo @ %x", mScriptableInfo));
|
||||
|
||||
|
|
|
@ -1385,6 +1385,8 @@ public:
|
|||
js::SystemAllocPolicy> DOMExpandoSet;
|
||||
|
||||
bool RegisterDOMExpandoObject(JSObject *expando) {
|
||||
// Expandos are proxy objects, and proxies are always tenured.
|
||||
JS::AssertGCThingMustBeTenured(expando);
|
||||
if (!mDOMExpandoSet) {
|
||||
mDOMExpandoSet = new DOMExpandoSet();
|
||||
mDOMExpandoSet->init(8);
|
||||
|
@ -2259,7 +2261,7 @@ public:
|
|||
nsIPrincipal* GetObjectPrincipal() const;
|
||||
|
||||
JSBool
|
||||
IsValid() const {return nullptr != mFlatJSObject;}
|
||||
IsValid() const { return mFlatJSObject.hasFlag(FLAT_JS_OBJECT_VALID); }
|
||||
|
||||
#define XPC_SCOPE_WORD(s) (intptr_t(s))
|
||||
#define XPC_SCOPE_MASK (intptr_t(0x3))
|
||||
|
@ -2309,8 +2311,7 @@ public:
|
|||
*/
|
||||
JSObject*
|
||||
GetFlatJSObject() const
|
||||
{if (mFlatJSObject != INVALID_OBJECT)
|
||||
xpc_UnmarkGrayObject(mFlatJSObject);
|
||||
{xpc_UnmarkGrayObject(mFlatJSObject);
|
||||
return mFlatJSObject;}
|
||||
|
||||
/**
|
||||
|
@ -2443,8 +2444,7 @@ public:
|
|||
else
|
||||
GetScope()->TraceSelf(trc);
|
||||
TraceWrapper(trc);
|
||||
if (mFlatJSObject && mFlatJSObject != INVALID_OBJECT &&
|
||||
JS_IsGlobalObject(mFlatJSObject))
|
||||
if (mFlatJSObject && JS_IsGlobalObject(mFlatJSObject))
|
||||
{
|
||||
TraceXPCGlobal(trc, mFlatJSObject);
|
||||
}
|
||||
|
@ -2460,9 +2460,9 @@ public:
|
|||
// This is the only time we should be tracing our mFlatJSObject,
|
||||
// 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,
|
||||
"XPCWrappedNative::mFlatJSObject");
|
||||
if (mFlatJSObject) {
|
||||
JS_CallTenuredObjectTracer(trc, &mFlatJSObject,
|
||||
"XPCWrappedNative::mFlatJSObject");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2490,13 +2490,12 @@ public:
|
|||
|
||||
JSBool HasExternalReference() const {return mRefCnt > 1;}
|
||||
|
||||
JSBool NeedsSOW() { return !!(mWrapperWord & NEEDS_SOW); }
|
||||
void SetNeedsSOW() { mWrapperWord |= NEEDS_SOW; }
|
||||
JSBool NeedsCOW() { return !!(mWrapperWord & NEEDS_COW); }
|
||||
void SetNeedsCOW() { mWrapperWord |= NEEDS_COW; }
|
||||
JSBool NeedsSOW() { return mWrapper.hasFlag(WRAPPER_NEEDS_SOW); }
|
||||
void SetNeedsSOW() { mWrapper.setFlags(WRAPPER_NEEDS_SOW); }
|
||||
JSBool NeedsCOW() { return mWrapper.hasFlag(WRAPPER_NEEDS_COW); }
|
||||
void SetNeedsCOW() { mWrapper.setFlags(WRAPPER_NEEDS_COW); }
|
||||
|
||||
JSObject* GetWrapperPreserveColor() const
|
||||
{return (JSObject*)(mWrapperWord & (size_t)~(size_t)FLAG_MASK);}
|
||||
JSObject* GetWrapperPreserveColor() const { return mWrapper.getPtr(); }
|
||||
|
||||
JSObject* GetWrapper()
|
||||
{
|
||||
|
@ -2511,20 +2510,18 @@ public:
|
|||
void SetWrapper(JSObject *obj)
|
||||
{
|
||||
JS::IncrementalObjectBarrier(GetWrapperPreserveColor());
|
||||
intptr_t newval = intptr_t(obj) | (mWrapperWord & FLAG_MASK);
|
||||
mWrapperWord = newval;
|
||||
mWrapper.setPtr(obj);
|
||||
}
|
||||
|
||||
void TraceWrapper(JSTracer *trc)
|
||||
{
|
||||
JS_CallMaskedObjectTracer(trc, reinterpret_cast<uintptr_t *>(&mWrapperWord),
|
||||
(uintptr_t)FLAG_MASK, "XPCWrappedNative::mWrapper");
|
||||
JS_CallTenuredObjectTracer(trc, &mWrapper, "XPCWrappedNative::mWrapper");
|
||||
}
|
||||
|
||||
// Returns the relevant same-compartment security if applicable, or
|
||||
// mFlatJSObject otherwise.
|
||||
//
|
||||
// This takes care of checking mWrapperWord to see if we already have such
|
||||
// This takes care of checking mWrapper to see if we already have such
|
||||
// a wrapper.
|
||||
JSObject *GetSameCompartmentSecurityWrapper(JSContext *cx);
|
||||
|
||||
|
@ -2550,9 +2547,12 @@ protected:
|
|||
|
||||
private:
|
||||
enum {
|
||||
NEEDS_SOW = JS_BIT(0),
|
||||
NEEDS_COW = JS_BIT(1),
|
||||
FLAG_MASK = JS_BITMASK(3)
|
||||
// Flags bits for mWrapper:
|
||||
WRAPPER_NEEDS_SOW = JS_BIT(0),
|
||||
WRAPPER_NEEDS_COW = JS_BIT(1),
|
||||
|
||||
// Flags bits for mFlatJSObject:
|
||||
FLAT_JS_OBJECT_VALID = JS_BIT(0)
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -2581,10 +2581,10 @@ private:
|
|||
XPCWrappedNativeProto* mMaybeProto;
|
||||
};
|
||||
XPCNativeSet* mSet;
|
||||
JSObject* mFlatJSObject;
|
||||
JS::TenuredHeap<JSObject*> mFlatJSObject;
|
||||
XPCNativeScriptableInfo* mScriptableInfo;
|
||||
XPCWrappedNativeTearOffChunk mFirstChunk;
|
||||
intptr_t mWrapperWord;
|
||||
JS::TenuredHeap<JSObject*> mWrapper;
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
|
|
|
@ -563,6 +563,7 @@ CycleCollectedJSRuntime::MaybeTraceGlobals(JSTracer* aTracer) const
|
|||
}
|
||||
|
||||
if (JSObject* global = js::GetDefaultGlobalForContext(acx)) {
|
||||
JS::AssertGCThingMustBeTenured(global);
|
||||
JS_CallObjectTracer(aTracer, &global, "Global Object");
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче