mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central and inbound
This commit is contained in:
commit
791e8139a6
@ -52,6 +52,11 @@
|
||||
#else
|
||||
/>
|
||||
#endif
|
||||
<menuitem id="menu_keyboardShortcuts"
|
||||
oncommand="openHelpLink('keyboard-shortcuts')"
|
||||
onclick="checkForMiddleClick(this, event);"
|
||||
label="&helpKeyboardShortcuts.label;"
|
||||
accesskey="&helpKeyboardShortcuts.accesskey;"/>
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
<menuitem id="healthReport"
|
||||
label="&healthReport.label;"
|
||||
|
@ -371,6 +371,10 @@
|
||||
label="&appMenuGettingStarted.label;"
|
||||
oncommand="gBrowser.loadOneTab('https://www.mozilla.org/firefox/central/', {inBackground: false});"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuitem id="appmenu_keyboardShortcuts"
|
||||
label="&helpKeyboardShortcuts.label;"
|
||||
oncommand="openHelpLink('keyboard-shortcuts')"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
<menuitem id="appmenu_healthReport"
|
||||
label="&healthReport.label;"
|
||||
|
@ -488,14 +488,6 @@
|
||||
onpopupshowing="gSyncUI.updateUI();"
|
||||
#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"
|
||||
label="&downloads.label;"
|
||||
accesskey="&downloads.accesskey;"
|
||||
|
@ -19,6 +19,10 @@
|
||||
<!ENTITY productHelp.label "&brandShortName; Help">
|
||||
<!ENTITY productHelp.accesskey "H">
|
||||
<!ENTITY helpMac.commandkey "?">
|
||||
|
||||
<!ENTITY helpKeyboardShortcuts.label "Keyboard Shortcuts">
|
||||
<!ENTITY helpKeyboardShortcuts.accesskey "K">
|
||||
|
||||
<!ENTITY helpSafeMode.label "Restart with Add-ons Disabled…">
|
||||
<!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.accesskey "K">
|
||||
<!ENTITY search.label "Web Search">
|
||||
<!ENTITY search.accesskey "S">
|
||||
|
||||
<!ENTITY downloads.label "Downloads">
|
||||
<!ENTITY downloads.tooltip "Display the progress of ongoing downloads">
|
||||
<!ENTITY downloads.accesskey "D">
|
||||
|
@ -240,6 +240,9 @@ endif
|
||||
ifdef MODULE_NAME
|
||||
$(error MODULE_NAME is $(MODULE_NAME) but MODULE_NAME and LIBXUL_LIBRARY are not compatible)
|
||||
endif
|
||||
ifdef FORCE_STATIC_LIB
|
||||
$(error Makefile sets FORCE_STATIC_LIB which was already implied by LIBXUL_LIBRARY)
|
||||
endif
|
||||
FORCE_STATIC_LIB=1
|
||||
ifneq ($(SHORT_LIBNAME),)
|
||||
$(error SHORT_LIBNAME is $(SHORT_LIBNAME) but SHORT_LIBNAME is not compatable with LIBXUL_LIBRARY)
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -237,6 +237,8 @@ nsresult
|
||||
nsXBLProtoImplMethod::Read(nsIScriptContext* aContext,
|
||||
nsIObjectInputStream* aStream)
|
||||
{
|
||||
MOZ_ASSERT(!IsCompiled() && !GetUncompiledMethod());
|
||||
|
||||
JS::Rooted<JSObject*> methodObject(aContext->GetNativeContext());
|
||||
nsresult rv = XBL_DeserializeFunction(aContext, aStream, &methodObject);
|
||||
if (NS_FAILED(rv)) {
|
||||
@ -261,7 +263,12 @@ nsXBLProtoImplMethod::Write(nsIScriptContext* aContext,
|
||||
rv = aStream->WriteWStringZ(mName);
|
||||
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;
|
||||
@ -271,7 +278,7 @@ nsresult
|
||||
nsXBLProtoImplAnonymousMethod::Execute(nsIContent* aBoundElement)
|
||||
{
|
||||
NS_PRECONDITION(IsCompiled(), "Can't execute uncompiled method");
|
||||
|
||||
|
||||
if (!GetCompiledMethod()) {
|
||||
// Nothing to do here
|
||||
return NS_OK;
|
||||
@ -364,7 +371,12 @@ nsXBLProtoImplAnonymousMethod::Write(nsIScriptContext* aContext,
|
||||
nsresult rv = aStream->Write8(aType);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -357,13 +357,22 @@ nsXBLProtoImplProperty::Write(nsIScriptContext* aContext,
|
||||
rv = aStream->WriteWStringZ(mName);
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -2380,8 +2380,15 @@ nsXULPrototypeScript::Serialize(nsIObjectOutputStream* aStream,
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = aStream->Write32(mLangVersion);
|
||||
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;
|
||||
|
||||
return NS_OK;
|
||||
@ -2406,8 +2413,7 @@ nsXULPrototypeScript::SerializeOutOfLine(nsIObjectOutputStream* aStream,
|
||||
"writing to the cache file, but the XUL cache is off?");
|
||||
bool exists;
|
||||
cache->HasData(mSrcURI, &exists);
|
||||
|
||||
|
||||
|
||||
/* return will be NS_OK from GetAsciiSpec.
|
||||
* that makes no sense.
|
||||
* nor does returning NS_OK from HasMuxedDocument.
|
||||
|
@ -243,7 +243,10 @@ public:
|
||||
// &mScriptObject pointer can't go stale.
|
||||
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)
|
||||
|
@ -197,11 +197,7 @@ nsXULPrototypeCache::PutStyleSheet(nsCSSStyleSheet* aStyleSheet)
|
||||
JSScript*
|
||||
nsXULPrototypeCache::GetScript(nsIURI* aURI)
|
||||
{
|
||||
JSScript* script;
|
||||
if (!mScriptTable.Get(aURI, &script)) {
|
||||
return nullptr;
|
||||
}
|
||||
return script;
|
||||
return mScriptTable.Get(aURI);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -209,8 +205,7 @@ nsXULPrototypeCache::PutScript(nsIURI* aURI,
|
||||
JS::Handle<JSScript*> aScriptObject)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
JSScript* existingScript;
|
||||
if (mScriptTable.Get(aURI, &existingScript)) {
|
||||
if (JSScript* existingScript = mScriptTable.Get(aURI)) {
|
||||
nsAutoCString scriptName;
|
||||
aURI->GetSpec(scriptName);
|
||||
nsAutoCString message("Loaded script ");
|
||||
@ -656,10 +651,10 @@ nsXULPrototypeCache::MarkInCCGeneration(uint32_t aGeneration)
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
MarkScriptsInGC(nsIURI* aKey, JSScript*& aScript, void* aClosure)
|
||||
MarkScriptsInGC(nsIURI* aKey, JS::Heap<JSScript*>& aScript, void* aClosure)
|
||||
{
|
||||
JSTracer* trc = static_cast<JSTracer*>(aClosure);
|
||||
JS_CallScriptTracer(trc, &aScript, "nsXULPrototypeCache script");
|
||||
JS_CallHeapScriptTracer(trc, &aScript, "nsXULPrototypeCache script");
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsXBLDocumentInfo.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsJSThingHashtable.h"
|
||||
#include "nsInterfaceHashtable.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsURIHashKey.h"
|
||||
@ -123,14 +123,14 @@ protected:
|
||||
|
||||
void FlushSkinFiles();
|
||||
|
||||
nsRefPtrHashtable<nsURIHashKey,nsXULPrototypeDocument> mPrototypeTable; // owns the prototypes
|
||||
nsRefPtrHashtable<nsURIHashKey,nsCSSStyleSheet> mStyleSheetTable;
|
||||
nsDataHashtable<nsURIHashKey, JSScript*> mScriptTable;
|
||||
nsRefPtrHashtable<nsURIHashKey,nsXBLDocumentInfo> mXBLDocTable;
|
||||
nsRefPtrHashtable<nsURIHashKey,nsXULPrototypeDocument> mPrototypeTable; // owns the prototypes
|
||||
nsRefPtrHashtable<nsURIHashKey,nsCSSStyleSheet> mStyleSheetTable;
|
||||
nsJSThingHashtable<nsURIHashKey, JSScript*> mScriptTable;
|
||||
nsRefPtrHashtable<nsURIHashKey,nsXBLDocumentInfo> mXBLDocTable;
|
||||
|
||||
nsTHashtable<nsURIHashKey> mCacheURITable;
|
||||
nsTHashtable<nsURIHashKey> mCacheURITable;
|
||||
|
||||
nsInterfaceHashtable<nsURIHashKey, nsIStorageStream> mOutputStreamTable;
|
||||
nsInterfaceHashtable<nsURIHashKey, nsIStorageStream> mOutputStreamTable;
|
||||
nsInterfaceHashtable<nsURIHashKey, nsIObjectInputStream> mInputStreamTable;
|
||||
|
||||
// Bootstrap caching service
|
||||
|
@ -89,13 +89,8 @@ uint32_t nsXULPrototypeDocument::gRefCnt;
|
||||
void
|
||||
nsXULPDGlobalObject_finalize(JSFreeOp *fop, JSObject *obj)
|
||||
{
|
||||
nsISupports *nativeThis = (nsISupports*)JS_GetPrivate(obj);
|
||||
|
||||
nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(nativeThis));
|
||||
|
||||
if (sgo) {
|
||||
sgo->OnFinalize(obj);
|
||||
}
|
||||
nsXULPDGlobalObject* nativeThis = static_cast<nsXULPDGlobalObject*>(JS_GetPrivate(obj));
|
||||
nativeThis->OnFinalize(obj);
|
||||
|
||||
// The addref was part of JSObject construction
|
||||
NS_RELEASE(nativeThis);
|
||||
|
@ -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;
|
||||
|
@ -553,11 +553,11 @@ CreateInterfacePrototypeObject(JSContext* cx, JS::Handle<JSObject*> global,
|
||||
void
|
||||
CreateInterfaceObjects(JSContext* cx, JS::Handle<JSObject*> global,
|
||||
JS::Handle<JSObject*> protoProto,
|
||||
JSClass* protoClass, JSObject** protoCache,
|
||||
JSClass* protoClass, JS::Heap<JSObject*>* protoCache,
|
||||
JS::Handle<JSObject*> constructorProto,
|
||||
JSClass* constructorClass, const JSNativeHolder* constructor,
|
||||
unsigned ctorNargs, const NamedConstructor* namedConstructors,
|
||||
JSObject** constructorCache, const DOMClass* domClass,
|
||||
JS::Heap<JSObject*>* constructorCache, const DOMClass* domClass,
|
||||
const NativeProperties* properties,
|
||||
const NativeProperties* chromeOnlyProperties,
|
||||
const char* name)
|
||||
@ -990,7 +990,7 @@ ResolvePrototypeOrConstructor(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||
JS::Rooted<JSObject*> global(cx, js::GetGlobalForObjectCrossCompartment(obj));
|
||||
{
|
||||
JSAutoCompartment ac(cx, global);
|
||||
JSObject** protoAndIfaceArray = GetProtoAndIfaceArray(global);
|
||||
JS::Heap<JSObject*>* protoAndIfaceArray = GetProtoAndIfaceArray(global);
|
||||
JSObject* protoOrIface = protoAndIfaceArray[protoAndIfaceArrayIndex];
|
||||
if (!protoOrIface) {
|
||||
return false;
|
||||
|
@ -277,8 +277,7 @@ AllocateProtoAndIfaceCache(JSObject* obj)
|
||||
MOZ_ASSERT(js::GetObjectClass(obj)->flags & JSCLASS_DOM_GLOBAL);
|
||||
MOZ_ASSERT(js::GetReservedSlot(obj, DOM_PROTOTYPE_SLOT).isUndefined());
|
||||
|
||||
// Important: The () at the end ensure zero-initialization
|
||||
JSObject** protoAndIfaceArray = new JSObject*[kProtoAndIfaceCacheCount]();
|
||||
JS::Heap<JSObject*>* protoAndIfaceArray = new JS::Heap<JSObject*>[kProtoAndIfaceCacheCount];
|
||||
|
||||
js::SetReservedSlot(obj, DOM_PROTOTYPE_SLOT,
|
||||
JS::PrivateValue(protoAndIfaceArray));
|
||||
@ -291,10 +290,10 @@ TraceProtoAndIfaceCache(JSTracer* trc, JSObject* obj)
|
||||
|
||||
if (!HasProtoAndIfaceArray(obj))
|
||||
return;
|
||||
JSObject** protoAndIfaceArray = GetProtoAndIfaceArray(obj);
|
||||
JS::Heap<JSObject*>* protoAndIfaceArray = GetProtoAndIfaceArray(obj);
|
||||
for (size_t i = 0; i < kProtoAndIfaceCacheCount; ++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);
|
||||
|
||||
JSObject** protoAndIfaceArray = GetProtoAndIfaceArray(obj);
|
||||
JS::Heap<JSObject*>* protoAndIfaceArray = GetProtoAndIfaceArray(obj);
|
||||
|
||||
delete [] protoAndIfaceArray;
|
||||
}
|
||||
@ -371,11 +370,11 @@ struct NamedConstructor
|
||||
void
|
||||
CreateInterfaceObjects(JSContext* cx, JS::Handle<JSObject*> global,
|
||||
JS::Handle<JSObject*> protoProto,
|
||||
JSClass* protoClass, JSObject** protoCache,
|
||||
JSClass* protoClass, JS::Heap<JSObject*>* protoCache,
|
||||
JS::Handle<JSObject*> interfaceProto,
|
||||
JSClass* constructorClass, const JSNativeHolder* constructor,
|
||||
unsigned ctorNargs, const NamedConstructor* namedConstructors,
|
||||
JSObject** constructorCache, const DOMClass* domClass,
|
||||
JS::Heap<JSObject*>* constructorCache, const DOMClass* domClass,
|
||||
const NativeProperties* regularProperties,
|
||||
const NativeProperties* chromeOnlyProperties,
|
||||
const char* name);
|
||||
@ -2048,7 +2047,7 @@ ReportLenientThisUnwrappingFailure(JSContext* cx, JS::Handle<JSObject*> obj);
|
||||
inline JSObject*
|
||||
GetUnforgeableHolder(JSObject* aGlobal, prototypes::ID aId)
|
||||
{
|
||||
JSObject** protoAndIfaceArray = GetProtoAndIfaceArray(aGlobal);
|
||||
JS::Heap<JSObject*>* protoAndIfaceArray = GetProtoAndIfaceArray(aGlobal);
|
||||
JSObject* interfaceProto = protoAndIfaceArray[aId];
|
||||
return &js::GetReservedSlot(interfaceProto,
|
||||
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
|
||||
* 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).
|
||||
*
|
||||
* This can return a handle because we trace our mCallback.
|
||||
*/
|
||||
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 {
|
||||
@ -93,6 +93,7 @@ protected:
|
||||
private:
|
||||
inline void Init(JSObject* aCallback)
|
||||
{
|
||||
MOZ_ASSERT(aCallback && !mCallback);
|
||||
// Set mCallback before we hold, on the off chance that a GC could somehow
|
||||
// happen in there... (which would be pretty odd, granted).
|
||||
mCallback = aCallback;
|
||||
|
@ -1684,7 +1684,7 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
||||
def __init__(self, descriptor, properties):
|
||||
args = [Argument('JSContext*', 'aCx'),
|
||||
Argument('JS::Handle<JSObject*>', 'aGlobal'),
|
||||
Argument('JSObject**', 'protoAndIfaceArray')]
|
||||
Argument('JS::Heap<JSObject*>*', 'protoAndIfaceArray')]
|
||||
CGAbstractMethod.__init__(self, descriptor, 'CreateInterfaceObjects', 'void', args)
|
||||
self.properties = properties
|
||||
def definition_body(self):
|
||||
@ -1887,13 +1887,19 @@ class CGGetPerInterfaceObject(CGAbstractMethod):
|
||||
return JS::NullPtr();
|
||||
}
|
||||
/* Check to see whether the interface objects are already installed */
|
||||
JSObject** protoAndIfaceArray = GetProtoAndIfaceArray(aGlobal);
|
||||
JS::Heap<JSObject*>* protoAndIfaceArray = GetProtoAndIfaceArray(aGlobal);
|
||||
if (!protoAndIfaceArray[%s]) {
|
||||
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))
|
||||
|
||||
class CGGetProtoObjectMethod(CGGetPerInterfaceObject):
|
||||
@ -9842,7 +9848,7 @@ class CallbackOperationBase(CallbackMethod):
|
||||
# This relies on getCallableDecl declaring a boolean
|
||||
# isCallable in the case when we're a single-operation
|
||||
# interface.
|
||||
return "isCallable ? aThisObj : mCallback"
|
||||
return "isCallable ? aThisObj.get() : mCallback"
|
||||
|
||||
def getCallableDecl(self):
|
||||
replacements = {
|
||||
|
@ -260,11 +260,11 @@ HasProtoAndIfaceArray(JSObject* global)
|
||||
return !js::GetReservedSlot(global, DOM_PROTOTYPE_SLOT).isUndefined();
|
||||
}
|
||||
|
||||
inline JSObject**
|
||||
inline JS::Heap<JSObject*>*
|
||||
GetProtoAndIfaceArray(JSObject* 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());
|
||||
}
|
||||
|
||||
|
@ -164,9 +164,9 @@ JSClass sNPObjectJSWrapperClass =
|
||||
};
|
||||
|
||||
typedef struct NPObjectMemberPrivate {
|
||||
JSObject *npobjWrapper;
|
||||
JS::Value fieldValue;
|
||||
NPIdentifier methodName;
|
||||
JS::Heap<JSObject *> npobjWrapper;
|
||||
JS::Heap<JS::Value> fieldValue;
|
||||
JS::Heap<jsid> methodName;
|
||||
NPP npp;
|
||||
} NPObjectMemberPrivate;
|
||||
|
||||
@ -2017,7 +2017,7 @@ CreateNPObjectMember(NPP npp, JSContext *cx, JSObject *obj, NPObject* npobj,
|
||||
memberPrivate->npobjWrapper = obj;
|
||||
|
||||
memberPrivate->fieldValue = fieldValue;
|
||||
memberPrivate->methodName = identifier;
|
||||
memberPrivate->methodName = id;
|
||||
memberPrivate->npp = npp;
|
||||
|
||||
::JS_RemoveValueRoot(cx, vp);
|
||||
@ -2124,7 +2124,7 @@ NPObjectMember_Call(JSContext *cx, unsigned argc, JS::Value *vp)
|
||||
|
||||
NPVariant npv;
|
||||
JSBool ok;
|
||||
ok = npobj->_class->invoke(npobj, memberPrivate->methodName,
|
||||
ok = npobj->_class->invoke(npobj, JSIdToNPIdentifier(memberPrivate->methodName),
|
||||
npargs, argc, &npv);
|
||||
|
||||
// Release arguments.
|
||||
@ -2162,20 +2162,18 @@ NPObjectMember_Trace(JSTracer *trc, JSObject *obj)
|
||||
return;
|
||||
|
||||
// Our NPIdentifier is not always interned, so we must root it explicitly.
|
||||
jsid id = NPIdentifierToJSId(memberPrivate->methodName);
|
||||
JS_CallIdTracer(trc, &id, "NPObjectMemberPrivate.methodName");
|
||||
memberPrivate->methodName = JSIdToNPIdentifier(id);
|
||||
JS_CallHeapIdTracer(trc, &memberPrivate->methodName, "NPObjectMemberPrivate.methodName");
|
||||
|
||||
if (!JSVAL_IS_PRIMITIVE(memberPrivate->fieldValue)) {
|
||||
JS_CallValueTracer(trc, &memberPrivate->fieldValue,
|
||||
"NPObject Member => fieldValue");
|
||||
JS_CallHeapValueTracer(trc, &memberPrivate->fieldValue,
|
||||
"NPObject Member => fieldValue");
|
||||
}
|
||||
|
||||
// There's no strong reference from our private data to the
|
||||
// NPObject, so make sure to mark the NPObject wrapper to keep the
|
||||
// NPObject alive as long as this NPObjectMember is alive.
|
||||
if (memberPrivate->npobjWrapper) {
|
||||
JS_CallObjectTracer(trc, &memberPrivate->npobjWrapper,
|
||||
"NPObject Member => npobjWrapper");
|
||||
JS_CallHeapObjectTracer(trc, &memberPrivate->npobjWrapper,
|
||||
"NPObject Member => npobjWrapper");
|
||||
}
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ private:
|
||||
|
||||
struct ListenerData : LinkedListElement<ListenerData>
|
||||
{
|
||||
JSObject* mListener;
|
||||
JS::Heap<JSObject*> mListener;
|
||||
EventListenerManager::Phase mPhase;
|
||||
bool mWantsUntrusted;
|
||||
|
||||
@ -184,9 +184,9 @@ EventListenerManager::TraceInternal(JSTracer* aTrc) const
|
||||
for (const ListenerData* listenerElem = collection->mListeners.getFirst();
|
||||
listenerElem;
|
||||
listenerElem = listenerElem->getNext()) {
|
||||
JS_CallObjectTracer(aTrc,
|
||||
&const_cast<ListenerData*>(listenerElem)->mListener,
|
||||
"EventListenerManager listener object");
|
||||
JS_CallHeapObjectTracer(aTrc,
|
||||
&const_cast<ListenerData*>(listenerElem)->mListener,
|
||||
"EventListenerManager listener object");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1763,8 +1763,8 @@ struct WorkerPrivate::TimeoutInfo
|
||||
return mTargetTime < aOther.mTargetTime;
|
||||
}
|
||||
|
||||
JS::Value mTimeoutVal;
|
||||
nsTArray<jsval> mExtraArgVals;
|
||||
JS::Heap<JS::Value> mTimeoutVal;
|
||||
nsTArray<JS::Heap<JS::Value> > mExtraArgVals;
|
||||
mozilla::TimeStamp mTargetTime;
|
||||
mozilla::TimeDuration mInterval;
|
||||
nsCString mFilename;
|
||||
@ -3398,11 +3398,11 @@ WorkerPrivate::TraceInternal(JSTracer* aTrc)
|
||||
|
||||
for (uint32_t index = 0; index < mTimeouts.Length(); index++) {
|
||||
TimeoutInfo* info = mTimeouts[index];
|
||||
JS_CallValueTracer(aTrc, &info->mTimeoutVal,
|
||||
"WorkerPrivate timeout value");
|
||||
JS_CallHeapValueTracer(aTrc, &info->mTimeoutVal,
|
||||
"WorkerPrivate timeout value");
|
||||
for (uint32_t index2 = 0; index2 < info->mExtraArgVals.Length(); index2++) {
|
||||
JS_CallValueTracer(aTrc, &info->mExtraArgVals[index2],
|
||||
"WorkerPrivate timeout extra argument value");
|
||||
JS_CallHeapValueTracer(aTrc, &info->mExtraArgVals[index2],
|
||||
"WorkerPrivate timeout extra argument value");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3952,7 +3952,7 @@ WorkerPrivate::SetTimeout(JSContext* aCx, unsigned aArgc, jsval* aVp,
|
||||
newInfo->mInterval = TimeDuration::FromMilliseconds(intervalMS);
|
||||
|
||||
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++) {
|
||||
extraArgVals.AppendElement(argv[index]);
|
||||
}
|
||||
@ -4104,9 +4104,14 @@ WorkerPrivate::RunExpiredTimeouts(JSContext* aCx)
|
||||
}
|
||||
else {
|
||||
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,
|
||||
info->mExtraArgVals.Length(),
|
||||
info->mExtraArgVals.Elements(), rval.address()) &&
|
||||
info->mExtraArgVals.Elements()->unsafeGet(),
|
||||
rval.address()) &&
|
||||
!JS_ReportPendingException(aCx)) {
|
||||
retval = false;
|
||||
break;
|
||||
|
@ -77,7 +77,7 @@ class WorkerGlobalScope : public workers::EventTarget
|
||||
};
|
||||
|
||||
// Must be traced!
|
||||
jsval mSlots[SLOT_COUNT];
|
||||
JS::Heap<JS::Value> mSlots[SLOT_COUNT];
|
||||
|
||||
enum
|
||||
{
|
||||
@ -128,7 +128,7 @@ protected:
|
||||
_trace(JSTracer* aTrc) MOZ_OVERRIDE
|
||||
{
|
||||
for (int32_t i = 0; i < SLOT_COUNT; i++) {
|
||||
JS_CallValueTracer(aTrc, &mSlots[i], "WorkerGlobalScope instance slot");
|
||||
JS_CallHeapValueTracer(aTrc, &mSlots[i], "WorkerGlobalScope instance slot");
|
||||
}
|
||||
mWorker->TraceInternal(aTrc);
|
||||
EventTarget::_trace(aTrc);
|
||||
|
@ -520,7 +520,7 @@ class EventRunnable : public MainThreadProxyRunnable
|
||||
nsString mResponseType;
|
||||
JSAutoStructuredCloneBuffer mResponseBuffer;
|
||||
nsTArray<nsCOMPtr<nsISupports> > mClonedObjects;
|
||||
jsval mResponse;
|
||||
JS::Heap<JS::Value> mResponse;
|
||||
nsString mResponseText;
|
||||
nsCString mStatusText;
|
||||
uint64_t mLoaded;
|
||||
@ -607,6 +607,28 @@ public:
|
||||
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
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
||||
{
|
||||
@ -665,8 +687,7 @@ public:
|
||||
}
|
||||
|
||||
XMLHttpRequest::StateData state;
|
||||
// XXXbz there is no AutoValueRooter anymore?
|
||||
JS::AutoArrayRooter rooter(aCx, 1, &state.mResponse);
|
||||
StateDataAutoRooter rooter(aCx, &state);
|
||||
|
||||
state.mResponseTextResult = mResponseTextResult;
|
||||
state.mResponseText = mResponseText;
|
||||
@ -1423,9 +1444,9 @@ void
|
||||
XMLHttpRequest::_trace(JSTracer* aTrc)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1510,13 +1531,19 @@ XMLHttpRequest::MaybePin(ErrorResult& aRv)
|
||||
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mWorkerPrivate->AddFeature(cx, this)) {
|
||||
JS_RemoveObjectRoot(cx, &mJSObject);
|
||||
JS_RemoveObjectRoot(cx, mJSObject.unsafeGet());
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
@ -1635,7 +1662,8 @@ XMLHttpRequest::Unpin()
|
||||
|
||||
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);
|
||||
|
||||
|
@ -31,7 +31,7 @@ public:
|
||||
uint32_t mStatus;
|
||||
nsCString mStatusText;
|
||||
uint16_t mReadyState;
|
||||
jsval mResponse;
|
||||
JS::Heap<JS::Value> mResponse;
|
||||
nsresult mResponseTextResult;
|
||||
nsresult mStatusResult;
|
||||
nsresult mResponseResult;
|
||||
@ -44,7 +44,7 @@ public:
|
||||
};
|
||||
|
||||
private:
|
||||
JSObject* mJSObject;
|
||||
JS::Heap<JSObject*> mJSObject;
|
||||
XMLHttpRequestUpload* mUpload;
|
||||
WorkerPrivate* mWorkerPrivate;
|
||||
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
|
||||
* 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
|
||||
@ -299,16 +408,20 @@ class MOZ_NONHEAP_CLASS Handle : public js::HandleBase<T>
|
||||
ptr = handle.address();
|
||||
}
|
||||
|
||||
Handle(const Heap<T> &heapPtr) {
|
||||
ptr = heapPtr.address();
|
||||
}
|
||||
|
||||
/*
|
||||
* This may be called only if 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.
|
||||
* Take care when calling this method!
|
||||
*
|
||||
* 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) {
|
||||
Handle h;
|
||||
|
@ -240,6 +240,9 @@ endif
|
||||
ifdef MODULE_NAME
|
||||
$(error MODULE_NAME is $(MODULE_NAME) but MODULE_NAME and LIBXUL_LIBRARY are not compatible)
|
||||
endif
|
||||
ifdef FORCE_STATIC_LIB
|
||||
$(error Makefile sets FORCE_STATIC_LIB which was already implied by LIBXUL_LIBRARY)
|
||||
endif
|
||||
FORCE_STATIC_LIB=1
|
||||
ifneq ($(SHORT_LIBNAME),)
|
||||
$(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 =
|
||||
static_cast<FieldInfoHash*>(JSVAL_TO_PRIVATE(slot));
|
||||
for (FieldInfoHash::Range r = fields->all(); !r.empty(); r.popFront()) {
|
||||
JSString *key = r.front().key;
|
||||
for (FieldInfoHash::Enum e(*fields); !e.empty(); e.popFront()) {
|
||||
JSString *key = e.front().key;
|
||||
JS_CallStringTracer(trc, &key, "fieldName");
|
||||
JS_ASSERT(key == r.front().key);
|
||||
JS_CallObjectTracer(trc, &r.front().value.mType, "fieldType");
|
||||
if (key != e.front().key)
|
||||
e.rekeyFront(JS_ASSERT_STRING_IS_FLAT(key));
|
||||
JS_CallHeapObjectTracer(trc, &e.front().value.mType, "fieldType");
|
||||
}
|
||||
|
||||
break;
|
||||
@ -3344,10 +3345,10 @@ CType::Trace(JSTracer* trc, JSObject* obj)
|
||||
JS_ASSERT(fninfo);
|
||||
|
||||
// Identify our objects to the tracer.
|
||||
JS_CallObjectTracer(trc, &fninfo->mABI, "abi");
|
||||
JS_CallObjectTracer(trc, &fninfo->mReturnType, "returnType");
|
||||
JS_CallHeapObjectTracer(trc, &fninfo->mABI, "abi");
|
||||
JS_CallHeapObjectTracer(trc, &fninfo->mReturnType, "returnType");
|
||||
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;
|
||||
}
|
||||
@ -4733,6 +4734,16 @@ StructType::Create(JSContext* cx, unsigned argc, jsval* vp)
|
||||
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
|
||||
StructType::DefineInternal(JSContext* cx, JSObject* typeObj_, JSObject* fieldsObj_)
|
||||
{
|
||||
@ -4823,6 +4834,7 @@ StructType::DefineInternal(JSContext* cx, JSObject* typeObj_, JSObject* fieldsOb
|
||||
info.mIndex = i;
|
||||
info.mOffset = fieldOffset;
|
||||
ASSERT_OK(fields->add(entryPtr, name, info));
|
||||
JS_StoreStringPostBarrierCallback(cx, PostBarrierCallback, name, fields.get());
|
||||
|
||||
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
|
||||
// 'closureObj', since that's us.)
|
||||
JS_CallObjectTracer(trc, &cinfo->typeObj, "typeObj");
|
||||
JS_CallObjectTracer(trc, &cinfo->jsfnObj, "jsfnObj");
|
||||
JS_CallHeapObjectTracer(trc, &cinfo->typeObj, "typeObj");
|
||||
JS_CallHeapObjectTracer(trc, &cinfo->jsfnObj, "jsfnObj");
|
||||
if (cinfo->thisObj)
|
||||
JS_CallObjectTracer(trc, &cinfo->thisObj, "thisObj");
|
||||
JS_CallHeapObjectTracer(trc, &cinfo->thisObj, "thisObj");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -211,9 +211,9 @@ enum TypeCode {
|
||||
// as the key to the hash entry.
|
||||
struct FieldInfo
|
||||
{
|
||||
JSObject* mType; // CType of the field
|
||||
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
|
||||
JS::Heap<JSObject*> mType; // CType of the field
|
||||
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
|
||||
};
|
||||
|
||||
// Hash policy for FieldInfos.
|
||||
@ -255,14 +255,14 @@ struct FunctionInfo
|
||||
|
||||
// Calling convention of the function. Convert to ffi_abi using GetABI
|
||||
// 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.
|
||||
JSObject* mReturnType;
|
||||
JS::Heap<JSObject*> mReturnType;
|
||||
|
||||
// A fixed array of known parameter types, excluding any variadic
|
||||
// parameters (if mIsVariadic).
|
||||
Array<JSObject*> mArgTypes;
|
||||
Array<JS::Heap<JSObject*> > mArgTypes;
|
||||
|
||||
// A variable array of ffi_type*s corresponding to both known parameter
|
||||
// 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.
|
||||
struct ClosureInfo
|
||||
{
|
||||
JSContext* cx; // JSContext to use
|
||||
JSRuntime* rt; // Used in the destructor, where cx might have already
|
||||
// been GCed.
|
||||
JSObject* closureObj; // CClosure object
|
||||
JSObject* typeObj; // FunctionType describing the C function
|
||||
JSObject* thisObj; // 'this' object to use for the JS function call
|
||||
JSObject* jsfnObj; // JS function
|
||||
void* errResult; // Result that will be returned if the closure throws
|
||||
ffi_closure* closure; // The C closure itself
|
||||
JSContext* cx; // JSContext to use
|
||||
JSRuntime* rt; // Used in the destructor, where cx might have already
|
||||
// been GCed.
|
||||
JS::Heap<JSObject*> closureObj; // CClosure object
|
||||
JS::Heap<JSObject*> typeObj; // FunctionType describing the C function
|
||||
JS::Heap<JSObject*> thisObj; // 'this' object to use for the JS function call
|
||||
JS::Heap<JSObject*> jsfnObj; // JS function
|
||||
void* errResult; // Result that will be returned if the closure throws
|
||||
ffi_closure* closure; // The C closure itself
|
||||
|
||||
// Anything conditionally freed in the destructor should be initialized to
|
||||
// NULL here.
|
||||
|
@ -771,7 +771,7 @@ js::gc::MarkRuntime(JSTracer *trc, bool useSavedRoots)
|
||||
|
||||
/* During GC, we don't mark gray roots at this stage. */
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -356,17 +356,18 @@ class StoreBuffer
|
||||
class CallbackRef : public BufferableRef
|
||||
{
|
||||
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) {
|
||||
callback(trc, key);
|
||||
callback(trc, key, data);
|
||||
}
|
||||
|
||||
private:
|
||||
MarkCallback callback;
|
||||
void *key;
|
||||
void *data;
|
||||
};
|
||||
|
||||
MonoTypeBuffer<ValueEdge> bufferVal;
|
||||
@ -451,8 +452,9 @@ class StoreBuffer
|
||||
}
|
||||
|
||||
/* Insert or update a callback entry. */
|
||||
void putCallback(CallbackRef::MarkCallback callback, void *key) {
|
||||
bufferGeneric.put(CallbackRef(callback, key));
|
||||
void putCallback(CallbackRef::MarkCallback callback, Cell *key, void *data) {
|
||||
if (!key->isTenured())
|
||||
bufferGeneric.put(CallbackRef(callback, key, data));
|
||||
}
|
||||
|
||||
/* 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_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.
|
||||
|
@ -1121,8 +1121,18 @@ js::IsInRequest(JSContext *cx)
|
||||
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
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 */
|
||||
|
@ -1794,10 +1794,24 @@ js_ReportIsNotFunction(JSContext *cx, const JS::Value& v);
|
||||
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
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
|
||||
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 /* jsfriendapi_h */
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -855,8 +855,9 @@ XPCConvert::NativeInterface2JSObject(jsval* d,
|
||||
// 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 appropriate wrappers in place.
|
||||
if (JSObject *cpow = UnwrapNativeCPOW(aHelper.Object())) {
|
||||
if (!JS_WrapObject(cx, &cpow))
|
||||
RootedObject cpow(cx, UnwrapNativeCPOW(aHelper.Object()));
|
||||
if (cpow) {
|
||||
if (!JS_WrapObject(cx, cpow.address()))
|
||||
return false;
|
||||
*d = OBJECT_TO_JSVAL(cpow);
|
||||
return true;
|
||||
@ -1113,13 +1114,12 @@ private:
|
||||
|
||||
// static
|
||||
nsresult
|
||||
XPCConvert::JSValToXPCException(jsval sArg,
|
||||
XPCConvert::JSValToXPCException(MutableHandleValue s,
|
||||
const char* ifaceName,
|
||||
const char* methodName,
|
||||
nsIException** exceptn)
|
||||
{
|
||||
AutoJSContext cx;
|
||||
RootedValue s(cx, sArg);
|
||||
AutoExceptionRestorer aer(cx, s);
|
||||
|
||||
if (!JSVAL_IS_PRIMITIVE(s)) {
|
||||
@ -1575,7 +1575,7 @@ XPCConvert::JSTypedArray2Native(void** d,
|
||||
|
||||
// static
|
||||
JSBool
|
||||
XPCConvert::JSArray2Native(void** d, JS::Value s,
|
||||
XPCConvert::JSArray2Native(void** d, HandleValue s,
|
||||
uint32_t count, const nsXPTType& type,
|
||||
const nsID* iid, nsresult* pErr)
|
||||
{
|
||||
@ -1759,7 +1759,7 @@ XPCConvert::NativeStringWithSize2JS(jsval* d, const void* s,
|
||||
|
||||
// static
|
||||
JSBool
|
||||
XPCConvert::JSStringWithSize2Native(void* d, jsval s,
|
||||
XPCConvert::JSStringWithSize2Native(void* d, HandleValue s,
|
||||
uint32_t count, const nsXPTType& type,
|
||||
nsresult* pErr)
|
||||
{
|
||||
|
@ -54,7 +54,7 @@ public:
|
||||
return p->value;
|
||||
if (!mTable.add(p, obj, wrapper))
|
||||
return nullptr;
|
||||
JS_StorePostBarrierCallback(cx, KeyMarkCallback, obj);
|
||||
JS_StoreObjectPostBarrierCallback(cx, KeyMarkCallback, obj, this);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
@ -87,12 +87,11 @@ private:
|
||||
* This function is called during minor GCs for each key in the HashMap that
|
||||
* 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);
|
||||
JSObject2WrappedJSMap* self = static_cast<JSObject2WrappedJSMap*>(d);
|
||||
JSObject *prior = key;
|
||||
JS_CallObjectTracer(trc, &key, "XPCJSRuntime::mWrappedJSMap key");
|
||||
XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance();
|
||||
JSObject2WrappedJSMap* self = rt->GetWrappedJSMap();
|
||||
self->mTable.rekey(prior, key);
|
||||
}
|
||||
|
||||
@ -650,7 +649,7 @@ public:
|
||||
if (!mTable.add(p, key, value))
|
||||
return nullptr;
|
||||
MOZ_ASSERT(xpc::GetObjectScope(key)->mWaiverWrapperMap == this);
|
||||
JS_StorePostBarrierCallback(cx, KeyMarkCallback, key);
|
||||
JS_StoreObjectPostBarrierCallback(cx, KeyMarkCallback, key, this);
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -697,11 +696,11 @@ private:
|
||||
* This function is called during minor GCs for each key in the HashMap that
|
||||
* 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);
|
||||
JSObject2JSObjectMap *self = static_cast<JSObject2JSObjectMap *>(d);
|
||||
JSObject *prior = key;
|
||||
JS_CallObjectTracer(trc, &key, "XPCWrappedNativeScope::mWaiverWrapperMap key");
|
||||
JSObject2JSObjectMap *self = xpc::GetObjectScope(key)->mWaiverWrapperMap;
|
||||
self->mTable.rekey(prior, key);
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ void XPCTraceableVariant::TraceJS(JSTracer* trc)
|
||||
{
|
||||
MOZ_ASSERT(JSVAL_IS_TRACEABLE(mJSVal));
|
||||
JS_SET_TRACING_DETAILS(trc, GetTraceName, this, 0);
|
||||
JS_CallValueTracer(trc, &mJSVal, "XPCTraceableVariant::mJSVal");
|
||||
JS_CallHeapValueTracer(trc, &mJSVal, "XPCTraceableVariant::mJSVal");
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -275,7 +275,7 @@ CheckMainThreadOnly(nsXPCWrappedJS *aWrapper)
|
||||
|
||||
// static
|
||||
nsresult
|
||||
nsXPCWrappedJS::GetNewOrUsed(JSObject* aJSObj,
|
||||
nsXPCWrappedJS::GetNewOrUsed(JS::HandleObject jsObj,
|
||||
REFNSIID aIID,
|
||||
nsISupports* aOuter,
|
||||
nsXPCWrappedJS** wrapperResult)
|
||||
@ -285,7 +285,6 @@ nsXPCWrappedJS::GetNewOrUsed(JSObject* aJSObj,
|
||||
MOZ_CRASH();
|
||||
|
||||
AutoJSContext cx;
|
||||
JS::RootedObject jsObj(cx, aJSObj);
|
||||
JSObject2WrappedJSMap* map;
|
||||
nsXPCWrappedJS* root = nullptr;
|
||||
nsXPCWrappedJS* wrapper = nullptr;
|
||||
|
@ -960,13 +960,13 @@ nsXPCWrappedJSClass::CheckForException(XPCCallContext & ccx,
|
||||
// to run on this JSContext
|
||||
nsresult pending_result = xpcc->GetPendingResult();
|
||||
|
||||
jsval js_exception;
|
||||
JSBool is_js_exception = JS_GetPendingException(cx, &js_exception);
|
||||
RootedValue js_exception(cx);
|
||||
JSBool is_js_exception = JS_GetPendingException(cx, js_exception.address());
|
||||
|
||||
/* JS might throw an expection whether the reporter was called or not */
|
||||
if (is_js_exception) {
|
||||
if (!xpc_exception)
|
||||
XPCConvert::JSValToXPCException(js_exception, anInterfaceName,
|
||||
XPCConvert::JSValToXPCException(&js_exception, anInterfaceName,
|
||||
aPropertyName,
|
||||
getter_AddRefs(xpc_exception));
|
||||
|
||||
|
@ -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));
|
||||
|
||||
@ -3399,7 +3403,7 @@ void
|
||||
XPCJSObjectHolder::TraceJS(JSTracer *trc)
|
||||
{
|
||||
JS_SET_TRACING_DETAILS(trc, GetTraceName, this, 0);
|
||||
JS_CallObjectTracer(trc, &mJSObj, "XPCJSObjectHolder::mJSObj");
|
||||
JS_CallHeapObjectTracer(trc, &mJSObj, "XPCJSObjectHolder::mJSObj");
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -65,7 +65,7 @@ XrayWrapperConstructor(JSContext *cx, unsigned argc, jsval *vp)
|
||||
}
|
||||
// static
|
||||
bool
|
||||
AttachNewConstructorObject(JSContext *aCx, JSObject *aGlobalObject)
|
||||
AttachNewConstructorObject(JSContext *aCx, JS::HandleObject aGlobalObject)
|
||||
{
|
||||
// Pushing a JSContext calls ActivateDebugger which calls this function, so
|
||||
// we can't use an AutoJSContext here until JSD is gone.
|
||||
|
@ -23,7 +23,7 @@ namespace XPCNativeWrapper {
|
||||
(_wn)->GetScriptableInfo()->GetFlags()._flag())
|
||||
|
||||
bool
|
||||
AttachNewConstructorObject(JSContext *aCx, JSObject *aGlobalObject);
|
||||
AttachNewConstructorObject(JSContext *aCx, JS::HandleObject aGlobalObject);
|
||||
|
||||
} // namespace XPCNativeWrapper
|
||||
|
||||
|
@ -595,9 +595,9 @@ nsXPConnect::WrapNative(JSContext * aJSContext,
|
||||
NS_ASSERTION(aCOMObj, "bad param");
|
||||
|
||||
RootedObject aScope(aJSContext, aScopeArg);
|
||||
jsval v;
|
||||
RootedValue v(aJSContext);
|
||||
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); */
|
||||
@ -1389,8 +1389,8 @@ Base64Encode(JSContext *cx, JS::Value val, JS::Value *out)
|
||||
MOZ_ASSERT(cx);
|
||||
MOZ_ASSERT(out);
|
||||
|
||||
JS::Value root = val;
|
||||
xpc_qsACString encodedString(cx, root, &root, xpc_qsACString::eNull,
|
||||
JS::RootedValue root(cx, val);
|
||||
xpc_qsACString encodedString(cx, root, root.address(), xpc_qsACString::eNull,
|
||||
xpc_qsACString::eStringify);
|
||||
if (!encodedString.IsValid())
|
||||
return false;
|
||||
@ -1415,8 +1415,8 @@ Base64Decode(JSContext *cx, JS::Value val, JS::Value *out)
|
||||
MOZ_ASSERT(cx);
|
||||
MOZ_ASSERT(out);
|
||||
|
||||
JS::Value root = val;
|
||||
xpc_qsACString encodedString(cx, root, &root, xpc_qsACString::eNull,
|
||||
JS::RootedValue root(cx, val);
|
||||
xpc_qsACString encodedString(cx, root, root.address(), xpc_qsACString::eNull,
|
||||
xpc_qsACString::eNull);
|
||||
if (!encodedString.IsValid())
|
||||
return false;
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
@ -2735,7 +2735,7 @@ public:
|
||||
*/
|
||||
|
||||
static nsresult
|
||||
GetNewOrUsed(JSObject* aJSObj,
|
||||
GetNewOrUsed(JS::HandleObject aJSObj,
|
||||
REFNSIID aIID,
|
||||
nsISupports* aOuter,
|
||||
nsXPCWrappedJS** wrapper);
|
||||
@ -2829,7 +2829,7 @@ private:
|
||||
XPCJSObjectHolder(JSObject* obj);
|
||||
XPCJSObjectHolder(); // not implemented
|
||||
|
||||
JSObject* mJSObj;
|
||||
JS::Heap<JSObject*> mJSObj;
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
@ -2864,7 +2864,6 @@ public:
|
||||
/**
|
||||
* Convert a native object into a jsval.
|
||||
*
|
||||
* @param ccx the context for the whole procedure
|
||||
* @param d [out] the resulting jsval
|
||||
* @param s the native object we're working with
|
||||
* @param type the type of object that s is
|
||||
@ -2886,7 +2885,6 @@ public:
|
||||
/**
|
||||
* Convert a native nsISupports into a JSObject.
|
||||
*
|
||||
* @param ccx the context for the whole procedure
|
||||
* @param dest [out] the resulting JSObject
|
||||
* @param src the native object we're working with
|
||||
* @param iid the interface of src that we want (may be null)
|
||||
@ -2931,7 +2929,7 @@ public:
|
||||
const nsXPTType& type, const nsID* iid,
|
||||
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,
|
||||
const nsID* iid, nsresult* pErr);
|
||||
|
||||
@ -2946,11 +2944,11 @@ public:
|
||||
uint32_t count,
|
||||
nsresult* pErr);
|
||||
|
||||
static JSBool JSStringWithSize2Native(void* d, jsval s,
|
||||
static JSBool JSStringWithSize2Native(void* d, JS::HandleValue s,
|
||||
uint32_t count, const nsXPTType& type,
|
||||
nsresult* pErr);
|
||||
|
||||
static nsresult JSValToXPCException(jsval s,
|
||||
static nsresult JSValToXPCException(JS::MutableHandleValue s,
|
||||
const char* ifaceName,
|
||||
const char* methodName,
|
||||
nsIException** exception);
|
||||
@ -3640,7 +3638,7 @@ protected:
|
||||
|
||||
protected:
|
||||
nsDiscriminatedUnion mData;
|
||||
jsval mJSVal;
|
||||
JS::Heap<JS::Value> mJSVal;
|
||||
bool mReturnRawObject : 1;
|
||||
uint32_t mCCGeneration : 31;
|
||||
};
|
||||
|
@ -563,6 +563,7 @@ CycleCollectedJSRuntime::MaybeTraceGlobals(JSTracer* aTracer) const
|
||||
}
|
||||
|
||||
if (JSObject* global = js::GetDefaultGlobalForContext(acx)) {
|
||||
JS::AssertGCThingMustBeTenured(global);
|
||||
JS_CallObjectTracer(aTracer, &global, "Global Object");
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user