Merge mozilla-central and inbound

This commit is contained in:
Ed Morley 2013-07-23 14:01:42 +01:00
Родитель 3bcb2143f6 e87b89e60f
Коммит ae11c63344
50 изменённых файлов: 474 добавлений и 250 удалений

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

@ -52,6 +52,11 @@
#else #else
/> />
#endif #endif
<menuitem id="menu_keyboardShortcuts"
oncommand="openHelpLink('keyboard-shortcuts')"
onclick="checkForMiddleClick(this, event);"
label="&helpKeyboardShortcuts.label;"
accesskey="&helpKeyboardShortcuts.accesskey;"/>
#ifdef MOZ_SERVICES_HEALTHREPORT #ifdef MOZ_SERVICES_HEALTHREPORT
<menuitem id="healthReport" <menuitem id="healthReport"
label="&healthReport.label;" label="&healthReport.label;"

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

@ -371,6 +371,10 @@
label="&appMenuGettingStarted.label;" label="&appMenuGettingStarted.label;"
oncommand="gBrowser.loadOneTab('https://www.mozilla.org/firefox/central/', {inBackground: false});" oncommand="gBrowser.loadOneTab('https://www.mozilla.org/firefox/central/', {inBackground: false});"
onclick="checkForMiddleClick(this, event);"/> onclick="checkForMiddleClick(this, event);"/>
<menuitem id="appmenu_keyboardShortcuts"
label="&helpKeyboardShortcuts.label;"
oncommand="openHelpLink('keyboard-shortcuts')"
onclick="checkForMiddleClick(this, event);"/>
#ifdef MOZ_SERVICES_HEALTHREPORT #ifdef MOZ_SERVICES_HEALTHREPORT
<menuitem id="appmenu_healthReport" <menuitem id="appmenu_healthReport"
label="&healthReport.label;" label="&healthReport.label;"

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

@ -488,14 +488,6 @@
onpopupshowing="gSyncUI.updateUI();" onpopupshowing="gSyncUI.updateUI();"
#endif #endif
> >
<menuitem id="menu_search"
class="show-only-for-keyboard"
label="&search.label;"
accesskey="&search.accesskey;"
key="key_search"
command="Tools:Search"/>
<menuseparator id="browserToolsSeparator"
class="show-only-for-keyboard"/>
<menuitem id="menu_openDownloads" <menuitem id="menu_openDownloads"
label="&downloads.label;" label="&downloads.label;"
accesskey="&downloads.accesskey;" accesskey="&downloads.accesskey;"

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

@ -19,6 +19,10 @@
<!ENTITY productHelp.label "&brandShortName; Help"> <!ENTITY productHelp.label "&brandShortName; Help">
<!ENTITY productHelp.accesskey "H"> <!ENTITY productHelp.accesskey "H">
<!ENTITY helpMac.commandkey "?"> <!ENTITY helpMac.commandkey "?">
<!ENTITY helpKeyboardShortcuts.label "Keyboard Shortcuts">
<!ENTITY helpKeyboardShortcuts.accesskey "K">
<!ENTITY helpSafeMode.label "Restart with Add-ons Disabled…"> <!ENTITY helpSafeMode.label "Restart with Add-ons Disabled…">
<!ENTITY helpSafeMode.accesskey "R"> <!ENTITY helpSafeMode.accesskey "R">

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

@ -194,8 +194,7 @@ These should match what Safari and other Apple applications use on OS X Lion. --
<!ENTITY keywordfield.label "Add a Keyword for this Search…"> <!ENTITY keywordfield.label "Add a Keyword for this Search…">
<!ENTITY keywordfield.accesskey "K"> <!ENTITY keywordfield.accesskey "K">
<!ENTITY search.label "Web Search">
<!ENTITY search.accesskey "S">
<!ENTITY downloads.label "Downloads"> <!ENTITY downloads.label "Downloads">
<!ENTITY downloads.tooltip "Display the progress of ongoing downloads"> <!ENTITY downloads.tooltip "Display the progress of ongoing downloads">
<!ENTITY downloads.accesskey "D"> <!ENTITY downloads.accesskey "D">

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

@ -240,6 +240,9 @@ endif
ifdef MODULE_NAME ifdef MODULE_NAME
$(error MODULE_NAME is $(MODULE_NAME) but MODULE_NAME and LIBXUL_LIBRARY are not compatible) $(error MODULE_NAME is $(MODULE_NAME) but MODULE_NAME and LIBXUL_LIBRARY are not compatible)
endif endif
ifdef FORCE_STATIC_LIB
$(error Makefile sets FORCE_STATIC_LIB which was already implied by LIBXUL_LIBRARY)
endif
FORCE_STATIC_LIB=1 FORCE_STATIC_LIB=1
ifneq ($(SHORT_LIBNAME),) ifneq ($(SHORT_LIBNAME),)
$(error SHORT_LIBNAME is $(SHORT_LIBNAME) but SHORT_LIBNAME is not compatable with LIBXUL_LIBRARY) $(error SHORT_LIBNAME is $(SHORT_LIBNAME) but SHORT_LIBNAME is not compatable with LIBXUL_LIBRARY)

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

@ -1650,6 +1650,7 @@ nsContentUtils::TraceSafeJSContext(JSTracer* aTrc)
return; return;
} }
if (JSObject* global = js::GetDefaultGlobalForContext(cx)) { if (JSObject* global = js::GetDefaultGlobalForContext(cx)) {
JS::AssertGCThingMustBeTenured(global);
JS_CallObjectTracer(aTrc, &global, "safe context"); JS_CallObjectTracer(aTrc, &global, "safe context");
MOZ_ASSERT(global == js::GetDefaultGlobalForContext(cx)); MOZ_ASSERT(global == js::GetDefaultGlobalForContext(cx));
} }

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

@ -237,6 +237,8 @@ nsresult
nsXBLProtoImplMethod::Read(nsIScriptContext* aContext, nsXBLProtoImplMethod::Read(nsIScriptContext* aContext,
nsIObjectInputStream* aStream) nsIObjectInputStream* aStream)
{ {
MOZ_ASSERT(!IsCompiled() && !GetUncompiledMethod());
JS::Rooted<JSObject*> methodObject(aContext->GetNativeContext()); JS::Rooted<JSObject*> methodObject(aContext->GetNativeContext());
nsresult rv = XBL_DeserializeFunction(aContext, aStream, &methodObject); nsresult rv = XBL_DeserializeFunction(aContext, aStream, &methodObject);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
@ -261,7 +263,12 @@ nsXBLProtoImplMethod::Write(nsIScriptContext* aContext,
rv = aStream->WriteWStringZ(mName); rv = aStream->WriteWStringZ(mName);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
return XBL_SerializeFunction(aContext, aStream, mMethod.AsHeapObject()); // Calling fromMarkedLocation() is safe because mMethod is traced by the
// Trace() method above, and because its value is never changed after it has
// been set to a compiled method.
JS::Handle<JSObject*> method =
JS::Handle<JSObject*>::fromMarkedLocation(mMethod.AsHeapObject().address());
return XBL_SerializeFunction(aContext, aStream, method);
} }
return NS_OK; return NS_OK;
@ -271,7 +278,7 @@ nsresult
nsXBLProtoImplAnonymousMethod::Execute(nsIContent* aBoundElement) nsXBLProtoImplAnonymousMethod::Execute(nsIContent* aBoundElement)
{ {
NS_PRECONDITION(IsCompiled(), "Can't execute uncompiled method"); NS_PRECONDITION(IsCompiled(), "Can't execute uncompiled method");
if (!GetCompiledMethod()) { if (!GetCompiledMethod()) {
// Nothing to do here // Nothing to do here
return NS_OK; return NS_OK;
@ -364,7 +371,12 @@ nsXBLProtoImplAnonymousMethod::Write(nsIScriptContext* aContext,
nsresult rv = aStream->Write8(aType); nsresult rv = aStream->Write8(aType);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
rv = XBL_SerializeFunction(aContext, aStream, mMethod.AsHeapObject()); // Calling fromMarkedLocation() is safe because mMethod is traced by the
// Trace() method above, and because its value is never changed after it has
// been set to a compiled method.
JS::Handle<JSObject*> method =
JS::Handle<JSObject*>::fromMarkedLocation(mMethod.AsHeapObject().address());
rv = XBL_SerializeFunction(aContext, aStream, method);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }

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

@ -357,13 +357,22 @@ nsXBLProtoImplProperty::Write(nsIScriptContext* aContext,
rv = aStream->WriteWStringZ(mName); rv = aStream->WriteWStringZ(mName);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
// The calls to fromMarkedLocation() below are safe because mSetter and
// mGetter are traced by the Trace() method above, and because their values
// are never changed after they have been set to a compiled function.
MOZ_ASSERT_IF(mJSAttributes & (JSPROP_GETTER | JSPROP_SETTER), mIsCompiled);
if (mJSAttributes & JSPROP_GETTER) { if (mJSAttributes & JSPROP_GETTER) {
rv = XBL_SerializeFunction(aContext, aStream, mGetter.AsHeapObject()); JS::Handle<JSObject*> function =
JS::Handle<JSObject*>::fromMarkedLocation(mGetter.AsHeapObject().address());
rv = XBL_SerializeFunction(aContext, aStream, function);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
if (mJSAttributes & JSPROP_SETTER) { if (mJSAttributes & JSPROP_SETTER) {
rv = XBL_SerializeFunction(aContext, aStream, mSetter.AsHeapObject()); JS::Handle<JSObject*> function =
JS::Handle<JSObject*>::fromMarkedLocation(mSetter.AsHeapObject().address());
rv = XBL_SerializeFunction(aContext, aStream, function);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }

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

@ -2380,8 +2380,15 @@ nsXULPrototypeScript::Serialize(nsIObjectOutputStream* aStream,
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
rv = aStream->Write32(mLangVersion); rv = aStream->Write32(mLangVersion);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
// And delegate the writing to the nsIScriptContext
rv = context->Serialize(aStream, mScriptObject); // And delegate the writing to the nsIScriptContext.
//
// Calling fromMarkedLocation() is safe because we trace mScriptObject in
// TraceScriptObject() and because its value is never changed after it has
// been set.
JS::Handle<JSScript*> script =
JS::Handle<JSScript*>::fromMarkedLocation(mScriptObject.address());
rv = context->Serialize(aStream, script);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
return NS_OK; return NS_OK;
@ -2406,8 +2413,7 @@ nsXULPrototypeScript::SerializeOutOfLine(nsIObjectOutputStream* aStream,
"writing to the cache file, but the XUL cache is off?"); "writing to the cache file, but the XUL cache is off?");
bool exists; bool exists;
cache->HasData(mSrcURI, &exists); cache->HasData(mSrcURI, &exists);
/* return will be NS_OK from GetAsciiSpec. /* return will be NS_OK from GetAsciiSpec.
* that makes no sense. * that makes no sense.
* nor does returning NS_OK from HasMuxedDocument. * nor does returning NS_OK from HasMuxedDocument.

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

@ -243,7 +243,10 @@ public:
// &mScriptObject pointer can't go stale. // &mScriptObject pointer can't go stale.
JS::Handle<JSScript*> GetScriptObject() JS::Handle<JSScript*> GetScriptObject()
{ {
return JS::Handle<JSScript*>(mScriptObject); // Calling fromMarkedLocation() is safe because we trace mScriptObject in
// TraceScriptObject() and because its value is never changed after it has
// been set.
return JS::Handle<JSScript*>::fromMarkedLocation(mScriptObject.address());
} }
void TraceScriptObject(JSTracer* aTrc) void TraceScriptObject(JSTracer* aTrc)

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

@ -197,11 +197,7 @@ nsXULPrototypeCache::PutStyleSheet(nsCSSStyleSheet* aStyleSheet)
JSScript* JSScript*
nsXULPrototypeCache::GetScript(nsIURI* aURI) nsXULPrototypeCache::GetScript(nsIURI* aURI)
{ {
JSScript* script; return mScriptTable.Get(aURI);
if (!mScriptTable.Get(aURI, &script)) {
return nullptr;
}
return script;
} }
nsresult nsresult
@ -209,8 +205,7 @@ nsXULPrototypeCache::PutScript(nsIURI* aURI,
JS::Handle<JSScript*> aScriptObject) JS::Handle<JSScript*> aScriptObject)
{ {
#ifdef DEBUG #ifdef DEBUG
JSScript* existingScript; if (JSScript* existingScript = mScriptTable.Get(aURI)) {
if (mScriptTable.Get(aURI, &existingScript)) {
nsAutoCString scriptName; nsAutoCString scriptName;
aURI->GetSpec(scriptName); aURI->GetSpec(scriptName);
nsAutoCString message("Loaded script "); nsAutoCString message("Loaded script ");
@ -656,10 +651,10 @@ nsXULPrototypeCache::MarkInCCGeneration(uint32_t aGeneration)
} }
static PLDHashOperator static PLDHashOperator
MarkScriptsInGC(nsIURI* aKey, JSScript*& aScript, void* aClosure) MarkScriptsInGC(nsIURI* aKey, JS::Heap<JSScript*>& aScript, void* aClosure)
{ {
JSTracer* trc = static_cast<JSTracer*>(aClosure); JSTracer* trc = static_cast<JSTracer*>(aClosure);
JS_CallScriptTracer(trc, &aScript, "nsXULPrototypeCache script"); JS_CallHeapScriptTracer(trc, &aScript, "nsXULPrototypeCache script");
return PL_DHASH_NEXT; return PL_DHASH_NEXT;
} }

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

@ -9,7 +9,7 @@
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsIObserver.h" #include "nsIObserver.h"
#include "nsXBLDocumentInfo.h" #include "nsXBLDocumentInfo.h"
#include "nsDataHashtable.h" #include "nsJSThingHashtable.h"
#include "nsInterfaceHashtable.h" #include "nsInterfaceHashtable.h"
#include "nsRefPtrHashtable.h" #include "nsRefPtrHashtable.h"
#include "nsURIHashKey.h" #include "nsURIHashKey.h"
@ -123,14 +123,14 @@ protected:
void FlushSkinFiles(); void FlushSkinFiles();
nsRefPtrHashtable<nsURIHashKey,nsXULPrototypeDocument> mPrototypeTable; // owns the prototypes nsRefPtrHashtable<nsURIHashKey,nsXULPrototypeDocument> mPrototypeTable; // owns the prototypes
nsRefPtrHashtable<nsURIHashKey,nsCSSStyleSheet> mStyleSheetTable; nsRefPtrHashtable<nsURIHashKey,nsCSSStyleSheet> mStyleSheetTable;
nsDataHashtable<nsURIHashKey, JSScript*> mScriptTable; nsJSThingHashtable<nsURIHashKey, JSScript*> mScriptTable;
nsRefPtrHashtable<nsURIHashKey,nsXBLDocumentInfo> mXBLDocTable; nsRefPtrHashtable<nsURIHashKey,nsXBLDocumentInfo> mXBLDocTable;
nsTHashtable<nsURIHashKey> mCacheURITable; nsTHashtable<nsURIHashKey> mCacheURITable;
nsInterfaceHashtable<nsURIHashKey, nsIStorageStream> mOutputStreamTable; nsInterfaceHashtable<nsURIHashKey, nsIStorageStream> mOutputStreamTable;
nsInterfaceHashtable<nsURIHashKey, nsIObjectInputStream> mInputStreamTable; nsInterfaceHashtable<nsURIHashKey, nsIObjectInputStream> mInputStreamTable;
// Bootstrap caching service // Bootstrap caching service

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

@ -89,13 +89,8 @@ uint32_t nsXULPrototypeDocument::gRefCnt;
void void
nsXULPDGlobalObject_finalize(JSFreeOp *fop, JSObject *obj) nsXULPDGlobalObject_finalize(JSFreeOp *fop, JSObject *obj)
{ {
nsISupports *nativeThis = (nsISupports*)JS_GetPrivate(obj); nsXULPDGlobalObject* nativeThis = static_cast<nsXULPDGlobalObject*>(JS_GetPrivate(obj));
nativeThis->OnFinalize(obj);
nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(nativeThis));
if (sgo) {
sgo->OnFinalize(obj);
}
// The addref was part of JSObject construction // The addref was part of JSObject construction
NS_RELEASE(nativeThis); NS_RELEASE(nativeThis);

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

@ -1027,7 +1027,6 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
mTimeoutInsertionPoint(nullptr), mTimeoutInsertionPoint(nullptr),
mTimeoutPublicIdCounter(1), mTimeoutPublicIdCounter(1),
mTimeoutFiringDepth(0), mTimeoutFiringDepth(0),
mJSObject(nullptr),
mTimeoutsSuspendDepth(0), mTimeoutsSuspendDepth(0),
mFocusMethod(0), mFocusMethod(0),
mSerial(0), mSerial(0),
@ -1865,7 +1864,7 @@ void
nsGlobalWindow::TraceGlobalJSObject(JSTracer* aTrc) nsGlobalWindow::TraceGlobalJSObject(JSTracer* aTrc)
{ {
if (mJSObject) { 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, nsGlobalWindow* aNewInner,
nsIURI* aURI, nsIURI* aURI,
nsIPrincipal* aPrincipal, nsIPrincipal* aPrincipal,
JSObject** aNativeGlobal, JS::TenuredHeap<JSObject*>& aNativeGlobal,
nsIXPConnectJSObjectHolder** aHolder) nsIXPConnectJSObjectHolder** aHolder)
{ {
MOZ_ASSERT(aCx); MOZ_ASSERT(aCx);
MOZ_ASSERT(aNewInner); MOZ_ASSERT(aNewInner);
MOZ_ASSERT(aNewInner->IsInnerWindow()); MOZ_ASSERT(aNewInner->IsInnerWindow());
MOZ_ASSERT(aPrincipal); MOZ_ASSERT(aPrincipal);
MOZ_ASSERT(aNativeGlobal);
MOZ_ASSERT(aHolder); MOZ_ASSERT(aHolder);
nsGlobalWindow *top = NULL; nsGlobalWindow *top = NULL;
@ -2154,13 +2152,13 @@ CreateNativeGlobalForInner(JSContext* aCx,
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
MOZ_ASSERT(jsholder); MOZ_ASSERT(jsholder);
*aNativeGlobal = jsholder->GetJSObject(); aNativeGlobal = jsholder->GetJSObject();
jsholder.forget(aHolder); jsholder.forget(aHolder);
// Set the location information for the new global, so that tools like // Set the location information for the new global, so that tools like
// about:memory may use that information // about:memory may use that information
MOZ_ASSERT(*aNativeGlobal); MOZ_ASSERT(aNativeGlobal.getPtr());
xpc::SetLocationForGlobal(*aNativeGlobal, aURI); xpc::SetLocationForGlobal(aNativeGlobal, aURI);
return NS_OK; return NS_OK;
} }
@ -2353,7 +2351,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
rv = CreateNativeGlobalForInner(cx, newInnerWindow, rv = CreateNativeGlobalForInner(cx, newInnerWindow,
aDocument->GetDocumentURI(), aDocument->GetDocumentURI(),
aDocument->NodePrincipal(), aDocument->NodePrincipal(),
&newInnerWindow->mJSObject, newInnerWindow->mJSObject,
getter_AddRefs(mInnerWindowHolder)); getter_AddRefs(mInnerWindowHolder));
NS_ASSERTION(NS_SUCCEEDED(rv) && newInnerWindow->mJSObject && mInnerWindowHolder, NS_ASSERTION(NS_SUCCEEDED(rv) && newInnerWindow->mJSObject && mInnerWindowHolder,
"Failed to get script global and holder"); "Failed to get script global and holder");
@ -3153,7 +3151,7 @@ nsGlobalWindow::PoisonOuterWindowProxy(JSObject *aObject)
{ {
MOZ_ASSERT(IsOuterWindow()); MOZ_ASSERT(IsOuterWindow());
if (aObject == mJSObject) { 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. // These member variables are used on both inner and the outer windows.
nsCOMPtr<nsIPrincipal> mDocumentPrincipal; nsCOMPtr<nsIPrincipal> mDocumentPrincipal;
JSObject* mJSObject;
// The JS global object. Global objects are always allocated tenured.
JS::TenuredHeap<JSObject*> mJSObject;
typedef nsCOMArray<nsIDOMStorageEvent> nsDOMStorageEventArray; typedef nsCOMArray<nsIDOMStorageEvent> nsDOMStorageEventArray;
nsDOMStorageEventArray mPendingStorageEvents; nsDOMStorageEventArray mPendingStorageEvents;

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

@ -553,11 +553,11 @@ CreateInterfacePrototypeObject(JSContext* cx, JS::Handle<JSObject*> global,
void void
CreateInterfaceObjects(JSContext* cx, JS::Handle<JSObject*> global, CreateInterfaceObjects(JSContext* cx, JS::Handle<JSObject*> global,
JS::Handle<JSObject*> protoProto, JS::Handle<JSObject*> protoProto,
JSClass* protoClass, JSObject** protoCache, JSClass* protoClass, JS::Heap<JSObject*>* protoCache,
JS::Handle<JSObject*> constructorProto, JS::Handle<JSObject*> constructorProto,
JSClass* constructorClass, const JSNativeHolder* constructor, JSClass* constructorClass, const JSNativeHolder* constructor,
unsigned ctorNargs, const NamedConstructor* namedConstructors, unsigned ctorNargs, const NamedConstructor* namedConstructors,
JSObject** constructorCache, const DOMClass* domClass, JS::Heap<JSObject*>* constructorCache, const DOMClass* domClass,
const NativeProperties* properties, const NativeProperties* properties,
const NativeProperties* chromeOnlyProperties, const NativeProperties* chromeOnlyProperties,
const char* name) const char* name)
@ -990,7 +990,7 @@ ResolvePrototypeOrConstructor(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::Rooted<JSObject*> global(cx, js::GetGlobalForObjectCrossCompartment(obj)); JS::Rooted<JSObject*> global(cx, js::GetGlobalForObjectCrossCompartment(obj));
{ {
JSAutoCompartment ac(cx, global); JSAutoCompartment ac(cx, global);
JSObject** protoAndIfaceArray = GetProtoAndIfaceArray(global); JS::Heap<JSObject*>* protoAndIfaceArray = GetProtoAndIfaceArray(global);
JSObject* protoOrIface = protoAndIfaceArray[protoAndIfaceArrayIndex]; JSObject* protoOrIface = protoAndIfaceArray[protoAndIfaceArrayIndex];
if (!protoOrIface) { if (!protoOrIface) {
return false; return false;

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

@ -277,8 +277,7 @@ AllocateProtoAndIfaceCache(JSObject* obj)
MOZ_ASSERT(js::GetObjectClass(obj)->flags & JSCLASS_DOM_GLOBAL); MOZ_ASSERT(js::GetObjectClass(obj)->flags & JSCLASS_DOM_GLOBAL);
MOZ_ASSERT(js::GetReservedSlot(obj, DOM_PROTOTYPE_SLOT).isUndefined()); MOZ_ASSERT(js::GetReservedSlot(obj, DOM_PROTOTYPE_SLOT).isUndefined());
// Important: The () at the end ensure zero-initialization JS::Heap<JSObject*>* protoAndIfaceArray = new JS::Heap<JSObject*>[kProtoAndIfaceCacheCount];
JSObject** protoAndIfaceArray = new JSObject*[kProtoAndIfaceCacheCount]();
js::SetReservedSlot(obj, DOM_PROTOTYPE_SLOT, js::SetReservedSlot(obj, DOM_PROTOTYPE_SLOT,
JS::PrivateValue(protoAndIfaceArray)); JS::PrivateValue(protoAndIfaceArray));
@ -291,10 +290,10 @@ TraceProtoAndIfaceCache(JSTracer* trc, JSObject* obj)
if (!HasProtoAndIfaceArray(obj)) if (!HasProtoAndIfaceArray(obj))
return; return;
JSObject** protoAndIfaceArray = GetProtoAndIfaceArray(obj); JS::Heap<JSObject*>* protoAndIfaceArray = GetProtoAndIfaceArray(obj);
for (size_t i = 0; i < kProtoAndIfaceCacheCount; ++i) { for (size_t i = 0; i < kProtoAndIfaceCacheCount; ++i) {
if (protoAndIfaceArray[i]) { if (protoAndIfaceArray[i]) {
JS_CallObjectTracer(trc, &protoAndIfaceArray[i], "protoAndIfaceArray[i]"); JS_CallHeapObjectTracer(trc, &protoAndIfaceArray[i], "protoAndIfaceArray[i]");
} }
} }
} }
@ -304,7 +303,7 @@ DestroyProtoAndIfaceCache(JSObject* obj)
{ {
MOZ_ASSERT(js::GetObjectClass(obj)->flags & JSCLASS_DOM_GLOBAL); MOZ_ASSERT(js::GetObjectClass(obj)->flags & JSCLASS_DOM_GLOBAL);
JSObject** protoAndIfaceArray = GetProtoAndIfaceArray(obj); JS::Heap<JSObject*>* protoAndIfaceArray = GetProtoAndIfaceArray(obj);
delete [] protoAndIfaceArray; delete [] protoAndIfaceArray;
} }
@ -371,11 +370,11 @@ struct NamedConstructor
void void
CreateInterfaceObjects(JSContext* cx, JS::Handle<JSObject*> global, CreateInterfaceObjects(JSContext* cx, JS::Handle<JSObject*> global,
JS::Handle<JSObject*> protoProto, JS::Handle<JSObject*> protoProto,
JSClass* protoClass, JSObject** protoCache, JSClass* protoClass, JS::Heap<JSObject*>* protoCache,
JS::Handle<JSObject*> interfaceProto, JS::Handle<JSObject*> interfaceProto,
JSClass* constructorClass, const JSNativeHolder* constructor, JSClass* constructorClass, const JSNativeHolder* constructor,
unsigned ctorNargs, const NamedConstructor* namedConstructors, unsigned ctorNargs, const NamedConstructor* namedConstructors,
JSObject** constructorCache, const DOMClass* domClass, JS::Heap<JSObject*>* constructorCache, const DOMClass* domClass,
const NativeProperties* regularProperties, const NativeProperties* regularProperties,
const NativeProperties* chromeOnlyProperties, const NativeProperties* chromeOnlyProperties,
const char* name); const char* name);
@ -2048,7 +2047,7 @@ ReportLenientThisUnwrappingFailure(JSContext* cx, JS::Handle<JSObject*> obj);
inline JSObject* inline JSObject*
GetUnforgeableHolder(JSObject* aGlobal, prototypes::ID aId) GetUnforgeableHolder(JSObject* aGlobal, prototypes::ID aId)
{ {
JSObject** protoAndIfaceArray = GetProtoAndIfaceArray(aGlobal); JS::Heap<JSObject*>* protoAndIfaceArray = GetProtoAndIfaceArray(aGlobal);
JSObject* interfaceProto = protoAndIfaceArray[aId]; JSObject* interfaceProto = protoAndIfaceArray[aId];
return &js::GetReservedSlot(interfaceProto, return &js::GetReservedSlot(interfaceProto,
DOM_INTERFACE_PROTO_SLOTS_BASE).toObject(); DOM_INTERFACE_PROTO_SLOTS_BASE).toObject();

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

@ -71,12 +71,12 @@ public:
* This should only be called if you are certain that the return value won't * This should only be called if you are certain that the return value won't
* be passed into a JS API function and that it won't be stored without being * be passed into a JS API function and that it won't be stored without being
* rooted (or otherwise signaling the stored value to the CC). * rooted (or otherwise signaling the stored value to the CC).
*
* This can return a handle because we trace our mCallback.
*/ */
JS::Handle<JSObject*> CallbackPreserveColor() const JS::Handle<JSObject*> CallbackPreserveColor() const
{ {
return mCallback; // Calling fromMarkedLocation() is safe because we trace our mCallback, and
// because the value of mCallback cannot change after if has been set.
return JS::Handle<JSObject*>::fromMarkedLocation(mCallback.address());
} }
enum ExceptionHandling { enum ExceptionHandling {
@ -93,6 +93,7 @@ protected:
private: private:
inline void Init(JSObject* aCallback) inline void Init(JSObject* aCallback)
{ {
MOZ_ASSERT(aCallback && !mCallback);
// Set mCallback before we hold, on the off chance that a GC could somehow // Set mCallback before we hold, on the off chance that a GC could somehow
// happen in there... (which would be pretty odd, granted). // happen in there... (which would be pretty odd, granted).
mCallback = aCallback; mCallback = aCallback;

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

@ -1684,7 +1684,7 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
def __init__(self, descriptor, properties): def __init__(self, descriptor, properties):
args = [Argument('JSContext*', 'aCx'), args = [Argument('JSContext*', 'aCx'),
Argument('JS::Handle<JSObject*>', 'aGlobal'), Argument('JS::Handle<JSObject*>', 'aGlobal'),
Argument('JSObject**', 'protoAndIfaceArray')] Argument('JS::Heap<JSObject*>*', 'protoAndIfaceArray')]
CGAbstractMethod.__init__(self, descriptor, 'CreateInterfaceObjects', 'void', args) CGAbstractMethod.__init__(self, descriptor, 'CreateInterfaceObjects', 'void', args)
self.properties = properties self.properties = properties
def definition_body(self): def definition_body(self):
@ -1887,13 +1887,19 @@ class CGGetPerInterfaceObject(CGAbstractMethod):
return JS::NullPtr(); return JS::NullPtr();
} }
/* Check to see whether the interface objects are already installed */ /* Check to see whether the interface objects are already installed */
JSObject** protoAndIfaceArray = GetProtoAndIfaceArray(aGlobal); JS::Heap<JSObject*>* protoAndIfaceArray = GetProtoAndIfaceArray(aGlobal);
if (!protoAndIfaceArray[%s]) { if (!protoAndIfaceArray[%s]) {
CreateInterfaceObjects(aCx, aGlobal, protoAndIfaceArray); CreateInterfaceObjects(aCx, aGlobal, protoAndIfaceArray);
} }
/* The object might _still_ be null, but that's OK */ /*
return JS::Handle<JSObject*>::fromMarkedLocation(&protoAndIfaceArray[%s]);""" % * The object might _still_ be null, but that's OK.
*
* Calling fromMarkedLocation() is safe because protoAndIfaceArray is
* traced by TraceProtoAndIfaceCache() and its contents are never
* changed after they have been set.
*/
return JS::Handle<JSObject*>::fromMarkedLocation(protoAndIfaceArray[%s].address());""" %
(self.id, self.id)) (self.id, self.id))
class CGGetProtoObjectMethod(CGGetPerInterfaceObject): class CGGetProtoObjectMethod(CGGetPerInterfaceObject):
@ -9842,7 +9848,7 @@ class CallbackOperationBase(CallbackMethod):
# This relies on getCallableDecl declaring a boolean # This relies on getCallableDecl declaring a boolean
# isCallable in the case when we're a single-operation # isCallable in the case when we're a single-operation
# interface. # interface.
return "isCallable ? aThisObj : mCallback" return "isCallable ? aThisObj.get() : mCallback"
def getCallableDecl(self): def getCallableDecl(self):
replacements = { replacements = {

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

@ -260,11 +260,11 @@ HasProtoAndIfaceArray(JSObject* global)
return !js::GetReservedSlot(global, DOM_PROTOTYPE_SLOT).isUndefined(); return !js::GetReservedSlot(global, DOM_PROTOTYPE_SLOT).isUndefined();
} }
inline JSObject** inline JS::Heap<JSObject*>*
GetProtoAndIfaceArray(JSObject* global) GetProtoAndIfaceArray(JSObject* global)
{ {
MOZ_ASSERT(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL); MOZ_ASSERT(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL);
return static_cast<JSObject**>( return static_cast<JS::Heap<JSObject*>*>(
js::GetReservedSlot(global, DOM_PROTOTYPE_SLOT).toPrivate()); js::GetReservedSlot(global, DOM_PROTOTYPE_SLOT).toPrivate());
} }

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

@ -164,9 +164,9 @@ JSClass sNPObjectJSWrapperClass =
}; };
typedef struct NPObjectMemberPrivate { typedef struct NPObjectMemberPrivate {
JSObject *npobjWrapper; JS::Heap<JSObject *> npobjWrapper;
JS::Value fieldValue; JS::Heap<JS::Value> fieldValue;
NPIdentifier methodName; JS::Heap<jsid> methodName;
NPP npp; NPP npp;
} NPObjectMemberPrivate; } NPObjectMemberPrivate;
@ -2017,7 +2017,7 @@ CreateNPObjectMember(NPP npp, JSContext *cx, JSObject *obj, NPObject* npobj,
memberPrivate->npobjWrapper = obj; memberPrivate->npobjWrapper = obj;
memberPrivate->fieldValue = fieldValue; memberPrivate->fieldValue = fieldValue;
memberPrivate->methodName = identifier; memberPrivate->methodName = id;
memberPrivate->npp = npp; memberPrivate->npp = npp;
::JS_RemoveValueRoot(cx, vp); ::JS_RemoveValueRoot(cx, vp);
@ -2124,7 +2124,7 @@ NPObjectMember_Call(JSContext *cx, unsigned argc, JS::Value *vp)
NPVariant npv; NPVariant npv;
JSBool ok; JSBool ok;
ok = npobj->_class->invoke(npobj, memberPrivate->methodName, ok = npobj->_class->invoke(npobj, JSIdToNPIdentifier(memberPrivate->methodName),
npargs, argc, &npv); npargs, argc, &npv);
// Release arguments. // Release arguments.
@ -2162,20 +2162,18 @@ NPObjectMember_Trace(JSTracer *trc, JSObject *obj)
return; return;
// Our NPIdentifier is not always interned, so we must root it explicitly. // Our NPIdentifier is not always interned, so we must root it explicitly.
jsid id = NPIdentifierToJSId(memberPrivate->methodName); JS_CallHeapIdTracer(trc, &memberPrivate->methodName, "NPObjectMemberPrivate.methodName");
JS_CallIdTracer(trc, &id, "NPObjectMemberPrivate.methodName");
memberPrivate->methodName = JSIdToNPIdentifier(id);
if (!JSVAL_IS_PRIMITIVE(memberPrivate->fieldValue)) { if (!JSVAL_IS_PRIMITIVE(memberPrivate->fieldValue)) {
JS_CallValueTracer(trc, &memberPrivate->fieldValue, JS_CallHeapValueTracer(trc, &memberPrivate->fieldValue,
"NPObject Member => fieldValue"); "NPObject Member => fieldValue");
} }
// There's no strong reference from our private data to the // There's no strong reference from our private data to the
// NPObject, so make sure to mark the NPObject wrapper to keep the // NPObject, so make sure to mark the NPObject wrapper to keep the
// NPObject alive as long as this NPObjectMember is alive. // NPObject alive as long as this NPObjectMember is alive.
if (memberPrivate->npobjWrapper) { if (memberPrivate->npobjWrapper) {
JS_CallObjectTracer(trc, &memberPrivate->npobjWrapper, JS_CallHeapObjectTracer(trc, &memberPrivate->npobjWrapper,
"NPObject Member => npobjWrapper"); "NPObject Member => npobjWrapper");
} }
} }

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

@ -60,7 +60,7 @@ private:
struct ListenerData : LinkedListElement<ListenerData> struct ListenerData : LinkedListElement<ListenerData>
{ {
JSObject* mListener; JS::Heap<JSObject*> mListener;
EventListenerManager::Phase mPhase; EventListenerManager::Phase mPhase;
bool mWantsUntrusted; bool mWantsUntrusted;
@ -184,9 +184,9 @@ EventListenerManager::TraceInternal(JSTracer* aTrc) const
for (const ListenerData* listenerElem = collection->mListeners.getFirst(); for (const ListenerData* listenerElem = collection->mListeners.getFirst();
listenerElem; listenerElem;
listenerElem = listenerElem->getNext()) { listenerElem = listenerElem->getNext()) {
JS_CallObjectTracer(aTrc, JS_CallHeapObjectTracer(aTrc,
&const_cast<ListenerData*>(listenerElem)->mListener, &const_cast<ListenerData*>(listenerElem)->mListener,
"EventListenerManager listener object"); "EventListenerManager listener object");
} }
} }
} }

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

@ -1763,8 +1763,8 @@ struct WorkerPrivate::TimeoutInfo
return mTargetTime < aOther.mTargetTime; return mTargetTime < aOther.mTargetTime;
} }
JS::Value mTimeoutVal; JS::Heap<JS::Value> mTimeoutVal;
nsTArray<jsval> mExtraArgVals; nsTArray<JS::Heap<JS::Value> > mExtraArgVals;
mozilla::TimeStamp mTargetTime; mozilla::TimeStamp mTargetTime;
mozilla::TimeDuration mInterval; mozilla::TimeDuration mInterval;
nsCString mFilename; nsCString mFilename;
@ -3398,11 +3398,11 @@ WorkerPrivate::TraceInternal(JSTracer* aTrc)
for (uint32_t index = 0; index < mTimeouts.Length(); index++) { for (uint32_t index = 0; index < mTimeouts.Length(); index++) {
TimeoutInfo* info = mTimeouts[index]; TimeoutInfo* info = mTimeouts[index];
JS_CallValueTracer(aTrc, &info->mTimeoutVal, JS_CallHeapValueTracer(aTrc, &info->mTimeoutVal,
"WorkerPrivate timeout value"); "WorkerPrivate timeout value");
for (uint32_t index2 = 0; index2 < info->mExtraArgVals.Length(); index2++) { for (uint32_t index2 = 0; index2 < info->mExtraArgVals.Length(); index2++) {
JS_CallValueTracer(aTrc, &info->mExtraArgVals[index2], JS_CallHeapValueTracer(aTrc, &info->mExtraArgVals[index2],
"WorkerPrivate timeout extra argument value"); "WorkerPrivate timeout extra argument value");
} }
} }
} }
@ -3952,7 +3952,7 @@ WorkerPrivate::SetTimeout(JSContext* aCx, unsigned aArgc, jsval* aVp,
newInfo->mInterval = TimeDuration::FromMilliseconds(intervalMS); newInfo->mInterval = TimeDuration::FromMilliseconds(intervalMS);
if (aArgc > 2 && newInfo->mTimeoutVal.isObject()) { if (aArgc > 2 && newInfo->mTimeoutVal.isObject()) {
nsTArray<jsval> extraArgVals(aArgc - 2); nsTArray<JS::Heap<JS::Value> > extraArgVals(aArgc - 2);
for (unsigned index = 2; index < aArgc; index++) { for (unsigned index = 2; index < aArgc; index++) {
extraArgVals.AppendElement(argv[index]); extraArgVals.AppendElement(argv[index]);
} }
@ -4104,9 +4104,14 @@ WorkerPrivate::RunExpiredTimeouts(JSContext* aCx)
} }
else { else {
JS::Rooted<JS::Value> rval(aCx); JS::Rooted<JS::Value> rval(aCx);
/*
* unsafeGet() is needed below because the argument is a not a const
* pointer, even though values are not modified.
*/
if (!JS_CallFunctionValue(aCx, global, info->mTimeoutVal, if (!JS_CallFunctionValue(aCx, global, info->mTimeoutVal,
info->mExtraArgVals.Length(), info->mExtraArgVals.Length(),
info->mExtraArgVals.Elements(), rval.address()) && info->mExtraArgVals.Elements()->unsafeGet(),
rval.address()) &&
!JS_ReportPendingException(aCx)) { !JS_ReportPendingException(aCx)) {
retval = false; retval = false;
break; break;

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

@ -77,7 +77,7 @@ class WorkerGlobalScope : public workers::EventTarget
}; };
// Must be traced! // Must be traced!
jsval mSlots[SLOT_COUNT]; JS::Heap<JS::Value> mSlots[SLOT_COUNT];
enum enum
{ {
@ -128,7 +128,7 @@ protected:
_trace(JSTracer* aTrc) MOZ_OVERRIDE _trace(JSTracer* aTrc) MOZ_OVERRIDE
{ {
for (int32_t i = 0; i < SLOT_COUNT; i++) { for (int32_t i = 0; i < SLOT_COUNT; i++) {
JS_CallValueTracer(aTrc, &mSlots[i], "WorkerGlobalScope instance slot"); JS_CallHeapValueTracer(aTrc, &mSlots[i], "WorkerGlobalScope instance slot");
} }
mWorker->TraceInternal(aTrc); mWorker->TraceInternal(aTrc);
EventTarget::_trace(aTrc); EventTarget::_trace(aTrc);

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

@ -520,7 +520,7 @@ class EventRunnable : public MainThreadProxyRunnable
nsString mResponseType; nsString mResponseType;
JSAutoStructuredCloneBuffer mResponseBuffer; JSAutoStructuredCloneBuffer mResponseBuffer;
nsTArray<nsCOMPtr<nsISupports> > mClonedObjects; nsTArray<nsCOMPtr<nsISupports> > mClonedObjects;
jsval mResponse; JS::Heap<JS::Value> mResponse;
nsString mResponseText; nsString mResponseText;
nsCString mStatusText; nsCString mStatusText;
uint64_t mLoaded; uint64_t mLoaded;
@ -607,6 +607,28 @@ public:
return true; return true;
} }
class StateDataAutoRooter : private JS::CustomAutoRooter
{
public:
explicit StateDataAutoRooter(JSContext* aCx, XMLHttpRequest::StateData* aData
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: CustomAutoRooter(aCx), mStateData(aData), mSkip(aCx, mStateData)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
private:
virtual void trace(JSTracer* aTrc)
{
JS_CallHeapValueTracer(aTrc, &mStateData->mResponse,
"XMLHttpRequest::StateData::mResponse");
}
XMLHttpRequest::StateData* mStateData;
js::SkipRoot mSkip;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
bool bool
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
{ {
@ -665,8 +687,7 @@ public:
} }
XMLHttpRequest::StateData state; XMLHttpRequest::StateData state;
// XXXbz there is no AutoValueRooter anymore? StateDataAutoRooter rooter(aCx, &state);
JS::AutoArrayRooter rooter(aCx, 1, &state.mResponse);
state.mResponseTextResult = mResponseTextResult; state.mResponseTextResult = mResponseTextResult;
state.mResponseText = mResponseText; state.mResponseText = mResponseText;
@ -1423,9 +1444,9 @@ void
XMLHttpRequest::_trace(JSTracer* aTrc) XMLHttpRequest::_trace(JSTracer* aTrc)
{ {
if (mUpload) { if (mUpload) {
mUpload->TraceJSObject(aTrc, "mUpload"); mUpload->TraceJSObject(aTrc, "XMLHttpRequest::mUpload");
} }
JS_CallValueTracer(aTrc, &mStateData.mResponse, "mResponse"); JS_CallHeapValueTracer(aTrc, &mStateData.mResponse, "XMLHttpRequest::mResponse");
XMLHttpRequestEventTarget::_trace(aTrc); XMLHttpRequestEventTarget::_trace(aTrc);
} }
@ -1510,13 +1531,19 @@ XMLHttpRequest::MaybePin(ErrorResult& aRv)
JSContext* cx = GetJSContext(); JSContext* cx = GetJSContext();
if (!JS_AddNamedObjectRoot(cx, &mJSObject, "XMLHttpRequest mJSObject")) { /*
* It's safe to use unsafeGet() here: the unsafeness comes from the
* possibility of updating the value of mJSObject without triggering the post
* barriers. However if the value will always be marked, post barriers are
* unnecessary.
*/
if (!JS_AddNamedObjectRoot(cx, mJSObject.unsafeGet(), "XMLHttpRequest::mJSObjectRooted")) {
aRv.Throw(NS_ERROR_FAILURE); aRv.Throw(NS_ERROR_FAILURE);
return; return;
} }
if (!mWorkerPrivate->AddFeature(cx, this)) { if (!mWorkerPrivate->AddFeature(cx, this)) {
JS_RemoveObjectRoot(cx, &mJSObject); JS_RemoveObjectRoot(cx, mJSObject.unsafeGet());
aRv.Throw(NS_ERROR_FAILURE); aRv.Throw(NS_ERROR_FAILURE);
return; return;
} }
@ -1635,7 +1662,8 @@ XMLHttpRequest::Unpin()
JSContext* cx = GetJSContext(); JSContext* cx = GetJSContext();
JS_RemoveObjectRoot(cx, &mJSObject); /* See the comment in MaybePin() for why this is safe. */
JS_RemoveObjectRoot(cx, mJSObject.unsafeGet());
mWorkerPrivate->RemoveFeature(cx, this); mWorkerPrivate->RemoveFeature(cx, this);

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

@ -31,7 +31,7 @@ public:
uint32_t mStatus; uint32_t mStatus;
nsCString mStatusText; nsCString mStatusText;
uint16_t mReadyState; uint16_t mReadyState;
jsval mResponse; JS::Heap<JS::Value> mResponse;
nsresult mResponseTextResult; nsresult mResponseTextResult;
nsresult mStatusResult; nsresult mStatusResult;
nsresult mResponseResult; nsresult mResponseResult;
@ -44,7 +44,7 @@ public:
}; };
private: private:
JSObject* mJSObject; JS::Heap<JSObject*> mJSObject;
XMLHttpRequestUpload* mUpload; XMLHttpRequestUpload* mUpload;
WorkerPrivate* mWorkerPrivate; WorkerPrivate* mWorkerPrivate;
nsRefPtr<Proxy> mProxy; nsRefPtr<Proxy> mProxy;

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

@ -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 * Heap<T> wraps the complex mechanisms required to ensure GC safety for the
* designed to be used for all heap-based GC thing pointers outside the JS * contained reference into a C++ class that behaves similarly to a normal
* engine. * pointer.
* *
* The template parameter T must be a JS GC thing pointer, masked pointer or * GC references stored on the C/C++ stack must use Rooted/Handle/MutableHandle
* possible pointer, such as a JS::Value or jsid. * instead.
* *
* The class must be used to declare data members of heap classes only. * Requirements for type T:
* Stack-based GC thing pointers should used Rooted<T>. * - Must be one of: Value, jsid, JSObject*, JSString*, JSScript*
*
* 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.
*/ */
template <typename T> template <typename T>
class Heap : public js::HeapBase<T> class Heap : public js::HeapBase<T>
@ -257,6 +255,117 @@ class Heap : public js::HeapBase<T>
T ptr; 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 * 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 * as a parameter type, which guarantees that the T lvalue is properly
@ -299,16 +408,20 @@ class MOZ_NONHEAP_CLASS Handle : public js::HandleBase<T>
ptr = handle.address(); ptr = handle.address();
} }
Handle(const Heap<T> &heapPtr) {
ptr = heapPtr.address();
}
/* /*
* This may be called only if the location of the T is guaranteed * Take care when calling this method!
* to be marked (for some reason other than being a Rooted),
* e.g., if it is guaranteed to be reachable from an implicit root.
* *
* Create a Handle from a raw location of a T. * This creates a Handle from the raw location of a T.
*
* It should be called only if the following conditions hold:
*
* 1) the location of the T is guaranteed to be marked (for some reason
* other than being a Rooted), e.g., if it is guaranteed to be reachable
* from an implicit root.
*
* 2) the contents of the location are immutable, or at least cannot change
* for the lifetime of the handle, as its users may not expect its value
* to change underneath them.
*/ */
static Handle fromMarkedLocation(const T *p) { static Handle fromMarkedLocation(const T *p) {
Handle h; Handle h;

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

@ -240,6 +240,9 @@ endif
ifdef MODULE_NAME ifdef MODULE_NAME
$(error MODULE_NAME is $(MODULE_NAME) but MODULE_NAME and LIBXUL_LIBRARY are not compatible) $(error MODULE_NAME is $(MODULE_NAME) but MODULE_NAME and LIBXUL_LIBRARY are not compatible)
endif endif
ifdef FORCE_STATIC_LIB
$(error Makefile sets FORCE_STATIC_LIB which was already implied by LIBXUL_LIBRARY)
endif
FORCE_STATIC_LIB=1 FORCE_STATIC_LIB=1
ifneq ($(SHORT_LIBNAME),) ifneq ($(SHORT_LIBNAME),)
$(error SHORT_LIBNAME is $(SHORT_LIBNAME) but SHORT_LIBNAME is not compatable with LIBXUL_LIBRARY) $(error SHORT_LIBNAME is $(SHORT_LIBNAME) but SHORT_LIBNAME is not compatable with LIBXUL_LIBRARY)

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

@ -3325,11 +3325,12 @@ CType::Trace(JSTracer* trc, JSObject* obj)
FieldInfoHash* fields = FieldInfoHash* fields =
static_cast<FieldInfoHash*>(JSVAL_TO_PRIVATE(slot)); static_cast<FieldInfoHash*>(JSVAL_TO_PRIVATE(slot));
for (FieldInfoHash::Range r = fields->all(); !r.empty(); r.popFront()) { for (FieldInfoHash::Enum e(*fields); !e.empty(); e.popFront()) {
JSString *key = r.front().key; JSString *key = e.front().key;
JS_CallStringTracer(trc, &key, "fieldName"); JS_CallStringTracer(trc, &key, "fieldName");
JS_ASSERT(key == r.front().key); if (key != e.front().key)
JS_CallObjectTracer(trc, &r.front().value.mType, "fieldType"); e.rekeyFront(JS_ASSERT_STRING_IS_FLAT(key));
JS_CallHeapObjectTracer(trc, &e.front().value.mType, "fieldType");
} }
break; break;
@ -3344,10 +3345,10 @@ CType::Trace(JSTracer* trc, JSObject* obj)
JS_ASSERT(fninfo); JS_ASSERT(fninfo);
// Identify our objects to the tracer. // Identify our objects to the tracer.
JS_CallObjectTracer(trc, &fninfo->mABI, "abi"); JS_CallHeapObjectTracer(trc, &fninfo->mABI, "abi");
JS_CallObjectTracer(trc, &fninfo->mReturnType, "returnType"); JS_CallHeapObjectTracer(trc, &fninfo->mReturnType, "returnType");
for (size_t i = 0; i < fninfo->mArgTypes.length(); ++i) for (size_t i = 0; i < fninfo->mArgTypes.length(); ++i)
JS_CallObjectTracer(trc, &fninfo->mArgTypes[i], "argType"); JS_CallHeapObjectTracer(trc, &fninfo->mArgTypes[i], "argType");
break; break;
} }
@ -4733,6 +4734,16 @@ StructType::Create(JSContext* cx, unsigned argc, jsval* vp)
return JS_TRUE; return JS_TRUE;
} }
static void
PostBarrierCallback(JSTracer *trc, void *k, void *d)
{
JSString *prior = static_cast<JSString*>(k);
FieldInfoHash *table = static_cast<FieldInfoHash*>(d);
JSString *key = prior;
JS_CallStringTracer(trc, &key, "CType fieldName");
table->rekey(JS_ASSERT_STRING_IS_FLAT(prior), JS_ASSERT_STRING_IS_FLAT(key));
}
JSBool JSBool
StructType::DefineInternal(JSContext* cx, JSObject* typeObj_, JSObject* fieldsObj_) StructType::DefineInternal(JSContext* cx, JSObject* typeObj_, JSObject* fieldsObj_)
{ {
@ -4823,6 +4834,7 @@ StructType::DefineInternal(JSContext* cx, JSObject* typeObj_, JSObject* fieldsOb
info.mIndex = i; info.mIndex = i;
info.mOffset = fieldOffset; info.mOffset = fieldOffset;
ASSERT_OK(fields->add(entryPtr, name, info)); ASSERT_OK(fields->add(entryPtr, name, info));
JS_StoreStringPostBarrierCallback(cx, PostBarrierCallback, name, fields.get());
structSize = fieldOffset + fieldSize; structSize = fieldOffset + fieldSize;
@ -6082,10 +6094,10 @@ CClosure::Trace(JSTracer* trc, JSObject* obj)
// Identify our objects to the tracer. (There's no need to identify // Identify our objects to the tracer. (There's no need to identify
// 'closureObj', since that's us.) // 'closureObj', since that's us.)
JS_CallObjectTracer(trc, &cinfo->typeObj, "typeObj"); JS_CallHeapObjectTracer(trc, &cinfo->typeObj, "typeObj");
JS_CallObjectTracer(trc, &cinfo->jsfnObj, "jsfnObj"); JS_CallHeapObjectTracer(trc, &cinfo->jsfnObj, "jsfnObj");
if (cinfo->thisObj) if (cinfo->thisObj)
JS_CallObjectTracer(trc, &cinfo->thisObj, "thisObj"); JS_CallHeapObjectTracer(trc, &cinfo->thisObj, "thisObj");
} }
void void

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

@ -211,9 +211,9 @@ enum TypeCode {
// as the key to the hash entry. // as the key to the hash entry.
struct FieldInfo struct FieldInfo
{ {
JSObject* mType; // CType of the field JS::Heap<JSObject*> mType; // CType of the field
size_t mIndex; // index of the field in the struct (first is 0) size_t mIndex; // index of the field in the struct (first is 0)
size_t mOffset; // offset of the field in the struct, in bytes size_t mOffset; // offset of the field in the struct, in bytes
}; };
// Hash policy for FieldInfos. // Hash policy for FieldInfos.
@ -255,14 +255,14 @@ struct FunctionInfo
// Calling convention of the function. Convert to ffi_abi using GetABI // Calling convention of the function. Convert to ffi_abi using GetABI
// and OBJECT_TO_JSVAL. Stored as a JSObject* for ease of tracing. // and OBJECT_TO_JSVAL. Stored as a JSObject* for ease of tracing.
JSObject* mABI; JS::Heap<JSObject*> mABI;
// The CType of the value returned by the function. // The CType of the value returned by the function.
JSObject* mReturnType; JS::Heap<JSObject*> mReturnType;
// A fixed array of known parameter types, excluding any variadic // A fixed array of known parameter types, excluding any variadic
// parameters (if mIsVariadic). // parameters (if mIsVariadic).
Array<JSObject*> mArgTypes; Array<JS::Heap<JSObject*> > mArgTypes;
// A variable array of ffi_type*s corresponding to both known parameter // A variable array of ffi_type*s corresponding to both known parameter
// types and dynamic (variadic) parameter types. Longer than mArgTypes // types and dynamic (variadic) parameter types. Longer than mArgTypes
@ -277,15 +277,15 @@ struct FunctionInfo
// Parameters necessary for invoking a JS function from a C closure. // Parameters necessary for invoking a JS function from a C closure.
struct ClosureInfo struct ClosureInfo
{ {
JSContext* cx; // JSContext to use JSContext* cx; // JSContext to use
JSRuntime* rt; // Used in the destructor, where cx might have already JSRuntime* rt; // Used in the destructor, where cx might have already
// been GCed. // been GCed.
JSObject* closureObj; // CClosure object JS::Heap<JSObject*> closureObj; // CClosure object
JSObject* typeObj; // FunctionType describing the C function JS::Heap<JSObject*> typeObj; // FunctionType describing the C function
JSObject* thisObj; // 'this' object to use for the JS function call JS::Heap<JSObject*> thisObj; // 'this' object to use for the JS function call
JSObject* jsfnObj; // JS function JS::Heap<JSObject*> jsfnObj; // JS function
void* errResult; // Result that will be returned if the closure throws void* errResult; // Result that will be returned if the closure throws
ffi_closure* closure; // The C closure itself ffi_closure* closure; // The C closure itself
// Anything conditionally freed in the destructor should be initialized to // Anything conditionally freed in the destructor should be initialized to
// NULL here. // NULL here.

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

@ -771,7 +771,7 @@ js::gc::MarkRuntime(JSTracer *trc, bool useSavedRoots)
/* During GC, we don't mark gray roots at this stage. */ /* During GC, we don't mark gray roots at this stage. */
if (JSTraceDataOp op = rt->gcGrayRootTracer.op) { if (JSTraceDataOp op = rt->gcGrayRootTracer.op) {
if (!IS_GC_MARKING_TRACER(trc)) if (!IS_GC_MARKING_TRACER(trc) && !trc->runtime->isHeapMinorCollecting())
(*op)(trc, rt->gcGrayRootTracer.data); (*op)(trc, rt->gcGrayRootTracer.data);
} }
} }

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

@ -356,17 +356,18 @@ class StoreBuffer
class CallbackRef : public BufferableRef class CallbackRef : public BufferableRef
{ {
public: public:
typedef void (*MarkCallback)(JSTracer *trc, void *key); typedef void (*MarkCallback)(JSTracer *trc, void *key, void *data);
CallbackRef(MarkCallback cb, void *k) : callback(cb), key(k) {} CallbackRef(MarkCallback cb, void *k, void *d) : callback(cb), key(k), data(d) {}
virtual void mark(JSTracer *trc) { virtual void mark(JSTracer *trc) {
callback(trc, key); callback(trc, key, data);
} }
private: private:
MarkCallback callback; MarkCallback callback;
void *key; void *key;
void *data;
}; };
MonoTypeBuffer<ValueEdge> bufferVal; MonoTypeBuffer<ValueEdge> bufferVal;
@ -451,8 +452,9 @@ class StoreBuffer
} }
/* Insert or update a callback entry. */ /* Insert or update a callback entry. */
void putCallback(CallbackRef::MarkCallback callback, void *key) { void putCallback(CallbackRef::MarkCallback callback, Cell *key, void *data) {
bufferGeneric.put(CallbackRef(callback, key)); if (!key->isTenured())
bufferGeneric.put(CallbackRef(callback, key, data));
} }
/* Mark the source of all edges in the store buffer. */ /* Mark the source of all edges in the store buffer. */

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

@ -2362,17 +2362,16 @@ JS_CallObjectTracer(JSTracer *trc, JSObject **objp, const char *name)
} }
JS_PUBLIC_API(void) 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 = objp->getPtr();
JSObject *obj = reinterpret_cast<JSObject *>(*objp & ~flagMask);
if (!obj) if (!obj)
return; return;
JS_SET_TRACING_LOCATION(trc, (void*)objp); JS_SET_TRACING_LOCATION(trc, (void*)objp);
MarkObjectUnbarriered(trc, &obj, name); MarkObjectUnbarriered(trc, &obj, name);
*objp = uintptr_t(obj) | flags; objp->setPtr(obj);
} }
JS_PUBLIC_API(void) 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 * Trace an object that is known to always be tenured. No post barriers are
* with flags embedded in the low bits of the word. The flagMask parameter * required in this case.
* 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) 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. * API for JSTraceCallback implementations.

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

@ -1121,8 +1121,18 @@ js::IsInRequest(JSContext *cx)
#ifdef JSGC_GENERATIONAL #ifdef JSGC_GENERATIONAL
JS_FRIEND_API(void) JS_FRIEND_API(void)
JS_StorePostBarrierCallback(JSContext* cx, void (*callback)(JSTracer *trc, void *key), void *key) JS_StoreObjectPostBarrierCallback(JSContext* cx,
void (*callback)(JSTracer *trc, void *key, void *data),
JSObject *key, void *data)
{ {
cx->runtime()->gcStoreBuffer.putCallback(callback, key); cx->runtime()->gcStoreBuffer.putCallback(callback, key, data);
}
extern JS_FRIEND_API(void)
JS_StoreStringPostBarrierCallback(JSContext* cx,
void (*callback)(JSTracer *trc, void *key, void *data),
JSString *key, void *data)
{
cx->runtime()->gcStoreBuffer.putCallback(callback, key, data);
} }
#endif /* JSGC_GENERATIONAL */ #endif /* JSGC_GENERATIONAL */

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

@ -1794,10 +1794,24 @@ js_ReportIsNotFunction(JSContext *cx, const JS::Value& v);
#ifdef JSGC_GENERATIONAL #ifdef JSGC_GENERATIONAL
extern JS_FRIEND_API(void) extern JS_FRIEND_API(void)
JS_StorePostBarrierCallback(JSContext* cx, void (*callback)(JSTracer *trc, void *key), void *key); JS_StoreObjectPostBarrierCallback(JSContext* cx,
void (*callback)(JSTracer *trc, void *key, void *data),
JSObject *key, void *data);
extern JS_FRIEND_API(void)
JS_StoreStringPostBarrierCallback(JSContext* cx,
void (*callback)(JSTracer *trc, void *key, void *data),
JSString *key, void *data);
#else #else
inline void inline void
JS_StorePostBarrierCallback(JSContext* cx, void (*callback)(JSTracer *trc, void *key), void *key) {} JS_StoreObjectPostBarrierCallback(JSContext* cx,
void (*callback)(JSTracer *trc, void *key, void *data),
JSObject *key, void *data) {}
inline void
JS_StoreStringPostBarrierCallback(JSContext* cx,
void (*callback)(JSTracer *trc, void *key, void *data),
JSString *key, void *data) {}
#endif /* JSGC_GENERATIONAL */ #endif /* JSGC_GENERATIONAL */
#endif /* jsfriendapi_h */ #endif /* jsfriendapi_h */

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

@ -5107,4 +5107,11 @@ AutoDisableProxyCheck::AutoDisableProxyCheck(JSRuntime *rt
MOZ_GUARD_OBJECT_NOTIFIER_INIT; MOZ_GUARD_OBJECT_NOTIFIER_INIT;
count++; count++;
} }
JS_FRIEND_API(void)
JS::AssertGCThingMustBeTenured(JSObject *obj)
{
JS_ASSERT((!IsNurseryAllocable(obj->tenuredGetAllocKind()) || obj->getClass()->finalize) &&
obj->isTenured());
}
#endif #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<PropertyName> { const static JSGCTraceKind kind = JSTRACE_STRING; };
template <> struct MapTypeToTraceKind<ion::IonCode> { const static JSGCTraceKind kind = JSTRACE_IONCODE; }; template <> struct MapTypeToTraceKind<ion::IonCode> { const static JSGCTraceKind kind = JSTRACE_IONCODE; };
#ifdef JSGC_GENERATIONAL #if defined(JSGC_GENERATIONAL) || defined(DEBUG)
static inline bool static inline bool
IsNurseryAllocable(AllocKind kind) IsNurseryAllocable(AllocKind kind)
{ {

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

@ -855,8 +855,9 @@ XPCConvert::NativeInterface2JSObject(jsval* d,
// with objects that don't provide necessary QIs (such as objects under // with objects that don't provide necessary QIs (such as objects under
// the new DOM bindings). We expect the other side of the CPOW to have // the new DOM bindings). We expect the other side of the CPOW to have
// the appropriate wrappers in place. // the appropriate wrappers in place.
if (JSObject *cpow = UnwrapNativeCPOW(aHelper.Object())) { RootedObject cpow(cx, UnwrapNativeCPOW(aHelper.Object()));
if (!JS_WrapObject(cx, &cpow)) if (cpow) {
if (!JS_WrapObject(cx, cpow.address()))
return false; return false;
*d = OBJECT_TO_JSVAL(cpow); *d = OBJECT_TO_JSVAL(cpow);
return true; return true;
@ -1113,13 +1114,12 @@ private:
// static // static
nsresult nsresult
XPCConvert::JSValToXPCException(jsval sArg, XPCConvert::JSValToXPCException(MutableHandleValue s,
const char* ifaceName, const char* ifaceName,
const char* methodName, const char* methodName,
nsIException** exceptn) nsIException** exceptn)
{ {
AutoJSContext cx; AutoJSContext cx;
RootedValue s(cx, sArg);
AutoExceptionRestorer aer(cx, s); AutoExceptionRestorer aer(cx, s);
if (!JSVAL_IS_PRIMITIVE(s)) { if (!JSVAL_IS_PRIMITIVE(s)) {
@ -1575,7 +1575,7 @@ XPCConvert::JSTypedArray2Native(void** d,
// static // static
JSBool JSBool
XPCConvert::JSArray2Native(void** d, JS::Value s, XPCConvert::JSArray2Native(void** d, HandleValue s,
uint32_t count, const nsXPTType& type, uint32_t count, const nsXPTType& type,
const nsID* iid, nsresult* pErr) const nsID* iid, nsresult* pErr)
{ {
@ -1759,7 +1759,7 @@ XPCConvert::NativeStringWithSize2JS(jsval* d, const void* s,
// static // static
JSBool JSBool
XPCConvert::JSStringWithSize2Native(void* d, jsval s, XPCConvert::JSStringWithSize2Native(void* d, HandleValue s,
uint32_t count, const nsXPTType& type, uint32_t count, const nsXPTType& type,
nsresult* pErr) nsresult* pErr)
{ {

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

@ -54,7 +54,7 @@ public:
return p->value; return p->value;
if (!mTable.add(p, obj, wrapper)) if (!mTable.add(p, obj, wrapper))
return nullptr; return nullptr;
JS_StorePostBarrierCallback(cx, KeyMarkCallback, obj); JS_StoreObjectPostBarrierCallback(cx, KeyMarkCallback, obj, this);
return wrapper; return wrapper;
} }
@ -87,12 +87,11 @@ private:
* This function is called during minor GCs for each key in the HashMap that * This function is called during minor GCs for each key in the HashMap that
* has been moved. * has been moved.
*/ */
static void KeyMarkCallback(JSTracer *trc, void *k) { static void KeyMarkCallback(JSTracer *trc, void *k, void *d) {
JSObject *key = static_cast<JSObject*>(k); JSObject *key = static_cast<JSObject*>(k);
JSObject2WrappedJSMap* self = static_cast<JSObject2WrappedJSMap*>(d);
JSObject *prior = key; JSObject *prior = key;
JS_CallObjectTracer(trc, &key, "XPCJSRuntime::mWrappedJSMap key"); JS_CallObjectTracer(trc, &key, "XPCJSRuntime::mWrappedJSMap key");
XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance();
JSObject2WrappedJSMap* self = rt->GetWrappedJSMap();
self->mTable.rekey(prior, key); self->mTable.rekey(prior, key);
} }
@ -650,7 +649,7 @@ public:
if (!mTable.add(p, key, value)) if (!mTable.add(p, key, value))
return nullptr; return nullptr;
MOZ_ASSERT(xpc::GetObjectScope(key)->mWaiverWrapperMap == this); MOZ_ASSERT(xpc::GetObjectScope(key)->mWaiverWrapperMap == this);
JS_StorePostBarrierCallback(cx, KeyMarkCallback, key); JS_StoreObjectPostBarrierCallback(cx, KeyMarkCallback, key, this);
return value; return value;
} }
@ -697,11 +696,11 @@ private:
* This function is called during minor GCs for each key in the HashMap that * This function is called during minor GCs for each key in the HashMap that
* has been moved. * has been moved.
*/ */
static void KeyMarkCallback(JSTracer *trc, void *k) { static void KeyMarkCallback(JSTracer *trc, void *k, void *d) {
JSObject *key = static_cast<JSObject*>(k); JSObject *key = static_cast<JSObject*>(k);
JSObject2JSObjectMap *self = static_cast<JSObject2JSObjectMap *>(d);
JSObject *prior = key; JSObject *prior = key;
JS_CallObjectTracer(trc, &key, "XPCWrappedNativeScope::mWaiverWrapperMap key"); JS_CallObjectTracer(trc, &key, "XPCWrappedNativeScope::mWaiverWrapperMap key");
JSObject2JSObjectMap *self = xpc::GetObjectScope(key)->mWaiverWrapperMap;
self->mTable.rekey(prior, key); self->mTable.rekey(prior, key);
} }

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

@ -69,7 +69,7 @@ void XPCTraceableVariant::TraceJS(JSTracer* trc)
{ {
MOZ_ASSERT(JSVAL_IS_TRACEABLE(mJSVal)); MOZ_ASSERT(JSVAL_IS_TRACEABLE(mJSVal));
JS_SET_TRACING_DETAILS(trc, GetTraceName, this, 0); JS_SET_TRACING_DETAILS(trc, GetTraceName, this, 0);
JS_CallValueTracer(trc, &mJSVal, "XPCTraceableVariant::mJSVal"); JS_CallHeapValueTracer(trc, &mJSVal, "XPCTraceableVariant::mJSVal");
} }
// static // static

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

@ -275,7 +275,7 @@ CheckMainThreadOnly(nsXPCWrappedJS *aWrapper)
// static // static
nsresult nsresult
nsXPCWrappedJS::GetNewOrUsed(JSObject* aJSObj, nsXPCWrappedJS::GetNewOrUsed(JS::HandleObject jsObj,
REFNSIID aIID, REFNSIID aIID,
nsISupports* aOuter, nsISupports* aOuter,
nsXPCWrappedJS** wrapperResult) nsXPCWrappedJS** wrapperResult)
@ -285,7 +285,6 @@ nsXPCWrappedJS::GetNewOrUsed(JSObject* aJSObj,
MOZ_CRASH(); MOZ_CRASH();
AutoJSContext cx; AutoJSContext cx;
JS::RootedObject jsObj(cx, aJSObj);
JSObject2WrappedJSMap* map; JSObject2WrappedJSMap* map;
nsXPCWrappedJS* root = nullptr; nsXPCWrappedJS* root = nullptr;
nsXPCWrappedJS* wrapper = nullptr; nsXPCWrappedJS* wrapper = nullptr;

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

@ -960,13 +960,13 @@ nsXPCWrappedJSClass::CheckForException(XPCCallContext & ccx,
// to run on this JSContext // to run on this JSContext
nsresult pending_result = xpcc->GetPendingResult(); nsresult pending_result = xpcc->GetPendingResult();
jsval js_exception; RootedValue js_exception(cx);
JSBool is_js_exception = JS_GetPendingException(cx, &js_exception); JSBool is_js_exception = JS_GetPendingException(cx, js_exception.address());
/* JS might throw an expection whether the reporter was called or not */ /* JS might throw an expection whether the reporter was called or not */
if (is_js_exception) { if (is_js_exception) {
if (!xpc_exception) if (!xpc_exception)
XPCConvert::JSValToXPCException(js_exception, anInterfaceName, XPCConvert::JSValToXPCException(&js_exception, anInterfaceName,
aPropertyName, aPropertyName,
getter_AddRefs(xpc_exception)); getter_AddRefs(xpc_exception));

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

@ -367,6 +367,7 @@ XPCWrappedNative::WrapNewGlobal(xpcObjectHelper &nativeHelper,
// Set the JS object to the global we already created. // Set the JS object to the global we already created.
wrapper->mFlatJSObject = global; wrapper->mFlatJSObject = global;
wrapper->mFlatJSObject.setFlags(FLAT_JS_OBJECT_VALID);
// Set the private to the XPCWrappedNative. // Set the private to the XPCWrappedNative.
JS_SetPrivate(global, wrapper); JS_SetPrivate(global, wrapper);
@ -757,11 +758,10 @@ XPCWrappedNative::XPCWrappedNative(already_AddRefed<nsISupports> aIdentity,
XPCWrappedNativeProto* aProto) XPCWrappedNativeProto* aProto)
: mMaybeProto(aProto), : mMaybeProto(aProto),
mSet(aProto->GetSet()), mSet(aProto->GetSet()),
mFlatJSObject(INVALID_OBJECT), // non-null to pass IsValid() test mScriptableInfo(nullptr)
mScriptableInfo(nullptr),
mWrapperWord(0)
{ {
mIdentity = aIdentity.get(); mIdentity = aIdentity.get();
mFlatJSObject.setFlags(FLAT_JS_OBJECT_VALID);
NS_ASSERTION(mMaybeProto, "bad ctor param"); NS_ASSERTION(mMaybeProto, "bad ctor param");
NS_ASSERTION(mSet, "bad ctor param"); NS_ASSERTION(mSet, "bad ctor param");
@ -776,11 +776,10 @@ XPCWrappedNative::XPCWrappedNative(already_AddRefed<nsISupports> aIdentity,
: mMaybeScope(TagScope(aScope)), : mMaybeScope(TagScope(aScope)),
mSet(aSet), mSet(aSet),
mFlatJSObject(INVALID_OBJECT), // non-null to pass IsValid() test mScriptableInfo(nullptr)
mScriptableInfo(nullptr),
mWrapperWord(0)
{ {
mIdentity = aIdentity.get(); mIdentity = aIdentity.get();
mFlatJSObject.setFlags(FLAT_JS_OBJECT_VALID);
NS_ASSERTION(aScope, "bad ctor param"); NS_ASSERTION(aScope, "bad ctor param");
NS_ASSERTION(aSet, "bad ctor param"); NS_ASSERTION(aSet, "bad ctor param");
@ -795,8 +794,6 @@ XPCWrappedNative::~XPCWrappedNative()
Destroy(); Destroy();
} }
static const intptr_t WRAPPER_WORD_POISON = 0xa8a8a8a8;
void void
XPCWrappedNative::Destroy() XPCWrappedNative::Destroy()
{ {
@ -835,14 +832,14 @@ XPCWrappedNative::Destroy()
* The only time GetRuntime() will be NULL is if Destroy is called a second * 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 * time on a wrapped native. Since we already unregistered the pointer the
* first time, there's no need to unregister again. Unregistration is safe * 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 (XPCJSRuntime *rt = GetRuntime()) {
if (IsIncrementalBarrierNeeded(rt->Runtime())) if (IsIncrementalBarrierNeeded(rt->Runtime()))
IncrementalObjectBarrier(GetWrapperPreserveColor()); IncrementalObjectBarrier(GetWrapperPreserveColor());
mWrapperWord = WRAPPER_WORD_POISON; mWrapper.setToCrashOnTouch();
} else { } else {
MOZ_ASSERT(mWrapperWord == WRAPPER_WORD_POISON); MOZ_ASSERT(mWrapper.isSetToCrashOnTouch());
} }
mMaybeScope = nullptr; mMaybeScope = nullptr;
@ -1033,9 +1030,12 @@ XPCWrappedNative::Init(HandleObject parent,
} }
mFlatJSObject = JS_NewObject(cx, jsclazz, protoJSObject, parent); mFlatJSObject = JS_NewObject(cx, jsclazz, protoJSObject, parent);
if (!mFlatJSObject) if (!mFlatJSObject) {
mFlatJSObject.unsetFlags(FLAT_JS_OBJECT_VALID);
return false; return false;
}
mFlatJSObject.setFlags(FLAT_JS_OBJECT_VALID);
JS_SetPrivate(mFlatJSObject, this); JS_SetPrivate(mFlatJSObject, this);
return FinishInit(); return FinishInit();
@ -1179,8 +1179,8 @@ XPCWrappedNative::FlatJSObjectFinalized()
if (cache) if (cache)
cache->ClearWrapper(); cache->ClearWrapper();
// This makes IsValid return false from now on...
mFlatJSObject = nullptr; mFlatJSObject = nullptr;
mFlatJSObject.unsetFlags(FLAT_JS_OBJECT_VALID);
NS_ASSERTION(mIdentity, "bad pointer!"); NS_ASSERTION(mIdentity, "bad pointer!");
#ifdef XP_WIN #ifdef XP_WIN
@ -1227,7 +1227,8 @@ XPCWrappedNative::SystemIsBeingShutDown()
// short circuit future finalization // short circuit future finalization
JS_SetPrivate(mFlatJSObject, nullptr); JS_SetPrivate(mFlatJSObject, nullptr);
mFlatJSObject = nullptr; // This makes 'IsValid()' return false. mFlatJSObject = nullptr;
mFlatJSObject.unsetFlags(FLAT_JS_OBJECT_VALID);
XPCWrappedNativeProto* proto = GetProto(); XPCWrappedNativeProto* proto = GetProto();
@ -1472,7 +1473,10 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCWrappedNativeScope* aOldScope,
MOZ_CRASH(); MOZ_CRASH();
} }
MOZ_ASSERT(flat);
wrapper->mFlatJSObject = flat; wrapper->mFlatJSObject = flat;
wrapper->mFlatJSObject.setFlags(FLAT_JS_OBJECT_VALID);
if (cache) { if (cache) {
bool preserving = cache->PreservingWrapper(); bool preserving = cache->PreservingWrapper();
cache->SetPreservingWrapper(false); cache->SetPreservingWrapper(false);
@ -2934,7 +2938,7 @@ NS_IMETHODIMP XPCWrappedNative::DebugDump(int16_t depth)
else else
XPC_LOG_ALWAYS(("mSet @ %x", mSet)); 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(("mIdentity of %x", mIdentity));
XPC_LOG_ALWAYS(("mScriptableInfo @ %x", mScriptableInfo)); XPC_LOG_ALWAYS(("mScriptableInfo @ %x", mScriptableInfo));
@ -3399,7 +3403,7 @@ void
XPCJSObjectHolder::TraceJS(JSTracer *trc) XPCJSObjectHolder::TraceJS(JSTracer *trc)
{ {
JS_SET_TRACING_DETAILS(trc, GetTraceName, this, 0); JS_SET_TRACING_DETAILS(trc, GetTraceName, this, 0);
JS_CallObjectTracer(trc, &mJSObj, "XPCJSObjectHolder::mJSObj"); JS_CallHeapObjectTracer(trc, &mJSObj, "XPCJSObjectHolder::mJSObj");
} }
// static // static

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

@ -65,7 +65,7 @@ XrayWrapperConstructor(JSContext *cx, unsigned argc, jsval *vp)
} }
// static // static
bool bool
AttachNewConstructorObject(JSContext *aCx, JSObject *aGlobalObject) AttachNewConstructorObject(JSContext *aCx, JS::HandleObject aGlobalObject)
{ {
// Pushing a JSContext calls ActivateDebugger which calls this function, so // Pushing a JSContext calls ActivateDebugger which calls this function, so
// we can't use an AutoJSContext here until JSD is gone. // we can't use an AutoJSContext here until JSD is gone.

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

@ -23,7 +23,7 @@ namespace XPCNativeWrapper {
(_wn)->GetScriptableInfo()->GetFlags()._flag()) (_wn)->GetScriptableInfo()->GetFlags()._flag())
bool bool
AttachNewConstructorObject(JSContext *aCx, JSObject *aGlobalObject); AttachNewConstructorObject(JSContext *aCx, JS::HandleObject aGlobalObject);
} // namespace XPCNativeWrapper } // namespace XPCNativeWrapper

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

@ -595,9 +595,9 @@ nsXPConnect::WrapNative(JSContext * aJSContext,
NS_ASSERTION(aCOMObj, "bad param"); NS_ASSERTION(aCOMObj, "bad param");
RootedObject aScope(aJSContext, aScopeArg); RootedObject aScope(aJSContext, aScopeArg);
jsval v; RootedValue v(aJSContext);
return NativeInterface2JSObject(aScope, aCOMObj, nullptr, &aIID, return NativeInterface2JSObject(aScope, aCOMObj, nullptr, &aIID,
false, &v, aHolder); false, v.address(), aHolder);
} }
/* void wrapNativeToJSVal (in JSContextPtr aJSContext, in JSObjectPtr aScope, in nsISupports aCOMObj, in nsIIDPtr aIID, out jsval aVal, out nsIXPConnectJSObjectHolder aHolder); */ /* void wrapNativeToJSVal (in JSContextPtr aJSContext, in JSObjectPtr aScope, in nsISupports aCOMObj, in nsIIDPtr aIID, out jsval aVal, out nsIXPConnectJSObjectHolder aHolder); */
@ -1389,8 +1389,8 @@ Base64Encode(JSContext *cx, JS::Value val, JS::Value *out)
MOZ_ASSERT(cx); MOZ_ASSERT(cx);
MOZ_ASSERT(out); MOZ_ASSERT(out);
JS::Value root = val; JS::RootedValue root(cx, val);
xpc_qsACString encodedString(cx, root, &root, xpc_qsACString::eNull, xpc_qsACString encodedString(cx, root, root.address(), xpc_qsACString::eNull,
xpc_qsACString::eStringify); xpc_qsACString::eStringify);
if (!encodedString.IsValid()) if (!encodedString.IsValid())
return false; return false;
@ -1415,8 +1415,8 @@ Base64Decode(JSContext *cx, JS::Value val, JS::Value *out)
MOZ_ASSERT(cx); MOZ_ASSERT(cx);
MOZ_ASSERT(out); MOZ_ASSERT(out);
JS::Value root = val; JS::RootedValue root(cx, val);
xpc_qsACString encodedString(cx, root, &root, xpc_qsACString::eNull, xpc_qsACString encodedString(cx, root, root.address(), xpc_qsACString::eNull,
xpc_qsACString::eNull); xpc_qsACString::eNull);
if (!encodedString.IsValid()) if (!encodedString.IsValid())
return false; return false;

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

@ -1385,6 +1385,8 @@ public:
js::SystemAllocPolicy> DOMExpandoSet; js::SystemAllocPolicy> DOMExpandoSet;
bool RegisterDOMExpandoObject(JSObject *expando) { bool RegisterDOMExpandoObject(JSObject *expando) {
// Expandos are proxy objects, and proxies are always tenured.
JS::AssertGCThingMustBeTenured(expando);
if (!mDOMExpandoSet) { if (!mDOMExpandoSet) {
mDOMExpandoSet = new DOMExpandoSet(); mDOMExpandoSet = new DOMExpandoSet();
mDOMExpandoSet->init(8); mDOMExpandoSet->init(8);
@ -2259,7 +2261,7 @@ public:
nsIPrincipal* GetObjectPrincipal() const; nsIPrincipal* GetObjectPrincipal() const;
JSBool 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_WORD(s) (intptr_t(s))
#define XPC_SCOPE_MASK (intptr_t(0x3)) #define XPC_SCOPE_MASK (intptr_t(0x3))
@ -2309,8 +2311,7 @@ public:
*/ */
JSObject* JSObject*
GetFlatJSObject() const GetFlatJSObject() const
{if (mFlatJSObject != INVALID_OBJECT) {xpc_UnmarkGrayObject(mFlatJSObject);
xpc_UnmarkGrayObject(mFlatJSObject);
return mFlatJSObject;} return mFlatJSObject;}
/** /**
@ -2443,8 +2444,7 @@ public:
else else
GetScope()->TraceSelf(trc); GetScope()->TraceSelf(trc);
TraceWrapper(trc); TraceWrapper(trc);
if (mFlatJSObject && mFlatJSObject != INVALID_OBJECT && if (mFlatJSObject && JS_IsGlobalObject(mFlatJSObject))
JS_IsGlobalObject(mFlatJSObject))
{ {
TraceXPCGlobal(trc, mFlatJSObject); TraceXPCGlobal(trc, mFlatJSObject);
} }
@ -2460,9 +2460,9 @@ public:
// This is the only time we should be tracing our mFlatJSObject, // This is the only time we should be tracing our mFlatJSObject,
// normally somebody else is doing that. Be careful not to trace the // normally somebody else is doing that. Be careful not to trace the
// bogus INVALID_OBJECT value we can have during init, though. // bogus INVALID_OBJECT value we can have during init, though.
if (mFlatJSObject && mFlatJSObject != INVALID_OBJECT) { if (mFlatJSObject) {
JS_CallObjectTracer(trc, &mFlatJSObject, JS_CallTenuredObjectTracer(trc, &mFlatJSObject,
"XPCWrappedNative::mFlatJSObject"); "XPCWrappedNative::mFlatJSObject");
} }
} }
@ -2490,13 +2490,12 @@ public:
JSBool HasExternalReference() const {return mRefCnt > 1;} JSBool HasExternalReference() const {return mRefCnt > 1;}
JSBool NeedsSOW() { return !!(mWrapperWord & NEEDS_SOW); } JSBool NeedsSOW() { return mWrapper.hasFlag(WRAPPER_NEEDS_SOW); }
void SetNeedsSOW() { mWrapperWord |= NEEDS_SOW; } void SetNeedsSOW() { mWrapper.setFlags(WRAPPER_NEEDS_SOW); }
JSBool NeedsCOW() { return !!(mWrapperWord & NEEDS_COW); } JSBool NeedsCOW() { return mWrapper.hasFlag(WRAPPER_NEEDS_COW); }
void SetNeedsCOW() { mWrapperWord |= NEEDS_COW; } void SetNeedsCOW() { mWrapper.setFlags(WRAPPER_NEEDS_COW); }
JSObject* GetWrapperPreserveColor() const JSObject* GetWrapperPreserveColor() const { return mWrapper.getPtr(); }
{return (JSObject*)(mWrapperWord & (size_t)~(size_t)FLAG_MASK);}
JSObject* GetWrapper() JSObject* GetWrapper()
{ {
@ -2511,20 +2510,18 @@ public:
void SetWrapper(JSObject *obj) void SetWrapper(JSObject *obj)
{ {
JS::IncrementalObjectBarrier(GetWrapperPreserveColor()); JS::IncrementalObjectBarrier(GetWrapperPreserveColor());
intptr_t newval = intptr_t(obj) | (mWrapperWord & FLAG_MASK); mWrapper.setPtr(obj);
mWrapperWord = newval;
} }
void TraceWrapper(JSTracer *trc) void TraceWrapper(JSTracer *trc)
{ {
JS_CallMaskedObjectTracer(trc, reinterpret_cast<uintptr_t *>(&mWrapperWord), JS_CallTenuredObjectTracer(trc, &mWrapper, "XPCWrappedNative::mWrapper");
(uintptr_t)FLAG_MASK, "XPCWrappedNative::mWrapper");
} }
// Returns the relevant same-compartment security if applicable, or // Returns the relevant same-compartment security if applicable, or
// mFlatJSObject otherwise. // 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. // a wrapper.
JSObject *GetSameCompartmentSecurityWrapper(JSContext *cx); JSObject *GetSameCompartmentSecurityWrapper(JSContext *cx);
@ -2550,9 +2547,12 @@ protected:
private: private:
enum { enum {
NEEDS_SOW = JS_BIT(0), // Flags bits for mWrapper:
NEEDS_COW = JS_BIT(1), WRAPPER_NEEDS_SOW = JS_BIT(0),
FLAG_MASK = JS_BITMASK(3) WRAPPER_NEEDS_COW = JS_BIT(1),
// Flags bits for mFlatJSObject:
FLAT_JS_OBJECT_VALID = JS_BIT(0)
}; };
private: private:
@ -2581,10 +2581,10 @@ private:
XPCWrappedNativeProto* mMaybeProto; XPCWrappedNativeProto* mMaybeProto;
}; };
XPCNativeSet* mSet; XPCNativeSet* mSet;
JSObject* mFlatJSObject; JS::TenuredHeap<JSObject*> mFlatJSObject;
XPCNativeScriptableInfo* mScriptableInfo; XPCNativeScriptableInfo* mScriptableInfo;
XPCWrappedNativeTearOffChunk mFirstChunk; XPCWrappedNativeTearOffChunk mFirstChunk;
intptr_t mWrapperWord; JS::TenuredHeap<JSObject*> mWrapper;
}; };
/*************************************************************************** /***************************************************************************
@ -2735,7 +2735,7 @@ public:
*/ */
static nsresult static nsresult
GetNewOrUsed(JSObject* aJSObj, GetNewOrUsed(JS::HandleObject aJSObj,
REFNSIID aIID, REFNSIID aIID,
nsISupports* aOuter, nsISupports* aOuter,
nsXPCWrappedJS** wrapper); nsXPCWrappedJS** wrapper);
@ -2829,7 +2829,7 @@ private:
XPCJSObjectHolder(JSObject* obj); XPCJSObjectHolder(JSObject* obj);
XPCJSObjectHolder(); // not implemented XPCJSObjectHolder(); // not implemented
JSObject* mJSObj; JS::Heap<JSObject*> mJSObj;
}; };
/*************************************************************************** /***************************************************************************
@ -2864,7 +2864,6 @@ public:
/** /**
* Convert a native object into a jsval. * Convert a native object into a jsval.
* *
* @param ccx the context for the whole procedure
* @param d [out] the resulting jsval * @param d [out] the resulting jsval
* @param s the native object we're working with * @param s the native object we're working with
* @param type the type of object that s is * @param type the type of object that s is
@ -2886,7 +2885,6 @@ public:
/** /**
* Convert a native nsISupports into a JSObject. * Convert a native nsISupports into a JSObject.
* *
* @param ccx the context for the whole procedure
* @param dest [out] the resulting JSObject * @param dest [out] the resulting JSObject
* @param src the native object we're working with * @param src the native object we're working with
* @param iid the interface of src that we want (may be null) * @param iid the interface of src that we want (may be null)
@ -2931,7 +2929,7 @@ public:
const nsXPTType& type, const nsID* iid, const nsXPTType& type, const nsID* iid,
uint32_t count, nsresult* pErr); uint32_t count, nsresult* pErr);
static JSBool JSArray2Native(void** d, jsval s, static JSBool JSArray2Native(void** d, JS::HandleValue s,
uint32_t count, const nsXPTType& type, uint32_t count, const nsXPTType& type,
const nsID* iid, nsresult* pErr); const nsID* iid, nsresult* pErr);
@ -2946,11 +2944,11 @@ public:
uint32_t count, uint32_t count,
nsresult* pErr); nsresult* pErr);
static JSBool JSStringWithSize2Native(void* d, jsval s, static JSBool JSStringWithSize2Native(void* d, JS::HandleValue s,
uint32_t count, const nsXPTType& type, uint32_t count, const nsXPTType& type,
nsresult* pErr); nsresult* pErr);
static nsresult JSValToXPCException(jsval s, static nsresult JSValToXPCException(JS::MutableHandleValue s,
const char* ifaceName, const char* ifaceName,
const char* methodName, const char* methodName,
nsIException** exception); nsIException** exception);
@ -3640,7 +3638,7 @@ protected:
protected: protected:
nsDiscriminatedUnion mData; nsDiscriminatedUnion mData;
jsval mJSVal; JS::Heap<JS::Value> mJSVal;
bool mReturnRawObject : 1; bool mReturnRawObject : 1;
uint32_t mCCGeneration : 31; uint32_t mCCGeneration : 31;
}; };

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

@ -563,6 +563,7 @@ CycleCollectedJSRuntime::MaybeTraceGlobals(JSTracer* aTracer) const
} }
if (JSObject* global = js::GetDefaultGlobalForContext(acx)) { if (JSObject* global = js::GetDefaultGlobalForContext(acx)) {
JS::AssertGCThingMustBeTenured(global);
JS_CallObjectTracer(aTracer, &global, "Global Object"); JS_CallObjectTracer(aTracer, &global, "Global Object");
} }
} }