Merge m-i to m-c, a=merge

This commit is contained in:
Phil Ringnalda 2015-04-18 16:36:32 -07:00
commit 842c8df579
220 changed files with 9186 additions and 2015 deletions

View File

@ -13,8 +13,8 @@
"unpack": "True"
},
{
"size": 166506,
"digest": "f3c214fd571f21d64937584645212f8d7c2d12c9016be613bd2bc9cecd80b3d52a741423cc1ca69bd85fb924c3d0572c85a1734d12db1616df37abcc397e9252",
"size": 167175,
"digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
"algorithm": "sha512",
"filename": "sccache.tar.bz2"
},

View File

@ -13,8 +13,8 @@
"unpack": "True"
},
{
"size": 166506,
"digest": "f3c214fd571f21d64937584645212f8d7c2d12c9016be613bd2bc9cecd80b3d52a741423cc1ca69bd85fb924c3d0572c85a1734d12db1616df37abcc397e9252",
"size": 167175,
"digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
"algorithm": "sha512",
"filename": "sccache.tar.bz2"
},

View File

@ -15,8 +15,8 @@
"filename": "clang.tar.bz2"
},
{
"size": 166506,
"digest": "f3c214fd571f21d64937584645212f8d7c2d12c9016be613bd2bc9cecd80b3d52a741423cc1ca69bd85fb924c3d0572c85a1734d12db1616df37abcc397e9252",
"size": 167175,
"digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
"algorithm": "sha512",
"filename": "sccache.tar.bz2"
},

View File

@ -12,8 +12,8 @@
"filename": "gcc.tar.xz"
},
{
"size": 166506,
"digest": "f3c214fd571f21d64937584645212f8d7c2d12c9016be613bd2bc9cecd80b3d52a741423cc1ca69bd85fb924c3d0572c85a1734d12db1616df37abcc397e9252",
"size": 167175,
"digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
"algorithm": "sha512",
"filename": "sccache.tar.bz2"
},

View File

@ -15,8 +15,8 @@
"filename": "clang.tar.bz2"
},
{
"size": 166506,
"digest": "f3c214fd571f21d64937584645212f8d7c2d12c9016be613bd2bc9cecd80b3d52a741423cc1ca69bd85fb924c3d0572c85a1734d12db1616df37abcc397e9252",
"size": 167175,
"digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
"algorithm": "sha512",
"filename": "sccache.tar.bz2"
},

View File

@ -12,8 +12,8 @@
"filename": "setup.sh"
},
{
"size": 166506,
"digest": "f3c214fd571f21d64937584645212f8d7c2d12c9016be613bd2bc9cecd80b3d52a741423cc1ca69bd85fb924c3d0572c85a1734d12db1616df37abcc397e9252",
"size": 167175,
"digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
"algorithm": "sha512",
"filename": "sccache.tar.bz2"
},

View File

@ -1890,3 +1890,8 @@ pref("readinglist.server", "https://readinglist.services.mozilla.com/v1");
// Don't limit how many nodes we care about on desktop:
pref("reader.parse-node-limit", 0);
// Enable Service workers for desktop on non-release builds
#ifdef NIGHTLY_BUILD
pref("dom.serviceWorkers.enabled", true);
#endif

View File

@ -12,8 +12,8 @@
"filename": "gcc.tar.xz"
},
{
"size": 166506,
"digest": "f3c214fd571f21d64937584645212f8d7c2d12c9016be613bd2bc9cecd80b3d52a741423cc1ca69bd85fb924c3d0572c85a1734d12db1616df37abcc397e9252",
"size": 167175,
"digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
"algorithm": "sha512",
"filename": "sccache.tar.bz2"
}

View File

@ -12,8 +12,8 @@
"filename": "gcc.tar.xz"
},
{
"size": 166506,
"digest": "f3c214fd571f21d64937584645212f8d7c2d12c9016be613bd2bc9cecd80b3d52a741423cc1ca69bd85fb924c3d0572c85a1734d12db1616df37abcc397e9252",
"size": 167175,
"digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
"algorithm": "sha512",
"filename": "sccache.tar.bz2"
}

View File

@ -15,8 +15,8 @@
"filename": "clang.tar.bz2"
},
{
"size": 166506,
"digest": "f3c214fd571f21d64937584645212f8d7c2d12c9016be613bd2bc9cecd80b3d52a741423cc1ca69bd85fb924c3d0572c85a1734d12db1616df37abcc397e9252",
"size": 167175,
"digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
"algorithm": "sha512",
"filename": "sccache.tar.bz2"
}

View File

@ -15,8 +15,8 @@
"filename": "clang.tar.bz2"
},
{
"size": 166506,
"digest": "f3c214fd571f21d64937584645212f8d7c2d12c9016be613bd2bc9cecd80b3d52a741423cc1ca69bd85fb924c3d0572c85a1734d12db1616df37abcc397e9252",
"size": 167175,
"digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
"algorithm": "sha512",
"filename": "sccache.tar.bz2"
}

View File

@ -12,8 +12,8 @@
"filename": "setup.sh"
},
{
"size": 166506,
"digest": "f3c214fd571f21d64937584645212f8d7c2d12c9016be613bd2bc9cecd80b3d52a741423cc1ca69bd85fb924c3d0572c85a1734d12db1616df37abcc397e9252",
"size": 167175,
"digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
"algorithm": "sha512",
"filename": "sccache.tar.bz2"
}

View File

@ -12,8 +12,8 @@
"filename": "setup.sh"
},
{
"size": 166506,
"digest": "f3c214fd571f21d64937584645212f8d7c2d12c9016be613bd2bc9cecd80b3d52a741423cc1ca69bd85fb924c3d0572c85a1734d12db1616df37abcc397e9252",
"size": 167175,
"digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
"algorithm": "sha512",
"filename": "sccache.tar.bz2"
}

View File

@ -13915,7 +13915,7 @@ nsDocShell::GetURLSearchParams()
}
void
nsDocShell::NotifyJSRunToCompletionStart()
nsDocShell::NotifyJSRunToCompletionStart(const char *aReason)
{
bool timelineOn = nsIDocShell::GetRecordProfileTimelineMarkers();

View File

@ -54,7 +54,7 @@ interface nsITabParent;
typedef unsigned long nsLoadFlags;
[scriptable, builtinclass, uuid(68ba7610-e33d-47ce-8fa2-af07af2422bc)]
[scriptable, builtinclass, uuid(bf78de98-9e88-498d-bc19-0e138f683939)]
interface nsIDocShell : nsIDocShellTreeItem
{
/**
@ -1039,7 +1039,7 @@ interface nsIDocShell : nsIDocShellTreeItem
* that execution has stopped. This only occurs when the Timeline devtool
* is collecting information.
*/
[noscript,notxpcom,nostdcall] void notifyJSRunToCompletionStart();
[noscript,notxpcom,nostdcall] void notifyJSRunToCompletionStart(in string aReason);
[noscript,notxpcom,nostdcall] void notifyJSRunToCompletionStop();
/**

View File

@ -759,7 +759,10 @@ MainProcessRunnable::ReadMetadata()
nsresult rv =
qm->EnsureOriginIsInitialized(mPersistence, mGroup, mOrigin, mIsApp,
getter_AddRefs(mDirectory));
NS_ENSURE_SUCCESS(rv, rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
mResult = JS::AsmJSCache_StorageInitFailure;
return rv;
}
rv = mDirectory->Append(NS_LITERAL_STRING(ASMJSCACHE_DIRECTORY_NAME));
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -522,6 +522,7 @@ AutoJSAPI::StealException(JS::MutableHandle<JS::Value> aVal)
}
AutoEntryScript::AutoEntryScript(nsIGlobalObject* aGlobalObject,
const char *aReason,
bool aIsMainThread,
JSContext* aCx)
: AutoJSAPI(aGlobalObject, aIsMainThread,
@ -546,7 +547,7 @@ AutoEntryScript::AutoEntryScript(nsIGlobalObject* aGlobalObject,
}
if (mDocShellForJSRunToCompletion) {
mDocShellForJSRunToCompletion->NotifyJSRunToCompletionStart();
mDocShellForJSRunToCompletion->NotifyJSRunToCompletionStart(aReason);
}
}

View File

@ -318,11 +318,16 @@ private:
/*
* A class that represents a new script entry point.
*
* |aReason| should be a statically-allocated C string naming the reason we're
* invoking JavaScript code: "setTimeout", "event", and so on. The devtools use
* these strings to label JS execution in timeline and profiling displays.
*/
class MOZ_STACK_CLASS AutoEntryScript : public AutoJSAPI,
protected ScriptSettingsStackEntry {
public:
explicit AutoEntryScript(nsIGlobalObject* aGlobalObject,
AutoEntryScript(nsIGlobalObject* aGlobalObject,
const char *aReason,
bool aIsMainThread = NS_IsMainThread(),
// Note: aCx is mandatory off-main-thread.
JSContext* aCx = nullptr);

View File

@ -20,6 +20,9 @@
0x45f27d10, 0x987b, 0x11d2, \
{0xbd, 0x40, 0x00, 0x10, 0x5a, 0xa4, 0x5e, 0x89} }
#define SERVICEWORKERPERIODICUPDATER_CONTRACTID \
"@mozilla.org/service-worker-periodic-updater;1"
//The dom cannot provide the crypto or pkcs11 classes that
//were used in older days, so if someone wants to provide
//the service they must implement an object and give it

View File

@ -1063,7 +1063,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
// JSContext* cx = aes.cx();
nsIGlobalObject* nativeGlobal =
xpc::NativeGlobal(js::GetGlobalForObjectCrossCompartment(wrappedJS->GetJSObject()));
AutoEntryScript aes(nativeGlobal);
AutoEntryScript aes(nativeGlobal, "message manager handler");
aes.TakeOwnershipOfErrorReporting();
JSContext* cx = aes.cx();
JS::Rooted<JSObject*> object(cx, wrappedJS->GetJSObject());
@ -1567,7 +1567,8 @@ nsMessageManagerScriptExecutor::LoadScriptInternal(const nsAString& aURL,
JS::Rooted<JSObject*> global(rt, mGlobal->GetJSObject());
if (global) {
AutoEntryScript aes(xpc::NativeGlobal(global));
AutoEntryScript aes(xpc::NativeGlobal(global),
"message manager script load");
aes.TakeOwnershipOfErrorReporting();
JSContext* cx = aes.cx();
if (script) {

View File

@ -2703,7 +2703,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
if (createdInnerWindow) {
// AutoEntryScript required to invoke debugger hook, which is a
// Gecko-specific concept at present.
AutoEntryScript aes(newInnerWindow);
AutoEntryScript aes(newInnerWindow, "nsGlobalWindow report new global");
JS::Rooted<JSObject*> global(aes.cx(), newInnerWindow->GetWrapper());
JS_FireOnNewGlobalObject(aes.cx(), global);
}
@ -12323,6 +12323,13 @@ nsGlobalWindow::RunTimeoutHandler(nsTimeout* aTimeout,
sNestingLevel = timeout->mNestingLevel;
}
const char *reason;
if (timeout->mIsInterval) {
reason = "setInterval handler";
} else {
reason = "setTimeout handler";
}
nsCOMPtr<nsIScriptTimeoutHandler> handler(timeout->mScriptHandler);
nsRefPtr<Function> callback = handler->GetCallback();
if (!callback) {
@ -12335,8 +12342,8 @@ nsGlobalWindow::RunTimeoutHandler(nsTimeout* aTimeout,
handler->GetLocation(&filename, &lineNo);
// New script entry point required, due to the "Create a script" sub-step of
// http://www.whatwg.org/specs/web-apps/current-work/#timer-initialization-steps
AutoEntryScript entryScript(this, true, aScx->GetNativeContext());
// http://www.whatwg.org/specs/web-apps/current-work/#timer-initialisation-steps
AutoEntryScript entryScript(this, reason, true, aScx->GetNativeContext());
JS::CompileOptions options(entryScript.cx());
options.setFileAndLine(filename, lineNo)
.setVersion(JSVERSION_DEFAULT);
@ -12348,7 +12355,7 @@ nsGlobalWindow::RunTimeoutHandler(nsTimeout* aTimeout,
nsCOMPtr<nsISupports> me(static_cast<nsIDOMWindow *>(this));
ErrorResult ignored;
JS::Rooted<JS::Value> ignoredVal(CycleCollectedJSRuntime::Get()->Runtime());
callback->Call(me, handler->GetArgs(), &ignoredVal, ignored);
callback->Call(me, handler->GetArgs(), &ignoredVal, ignored, reason);
}
// We ignore any failures from calling EvaluateString() on the context or

View File

@ -1122,7 +1122,8 @@ nsScriptLoader::EvaluateScript(nsScriptLoadRequest* aRequest,
// New script entry point required, due to the "Create a script" sub-step of
// http://www.whatwg.org/specs/web-apps/current-work/#execute-the-script-block
AutoEntryScript entryScript(globalObject, true, context->GetNativeContext());
AutoEntryScript entryScript(globalObject, "<script> element", true,
context->GetNativeContext());
JS::Rooted<JSObject*> global(entryScript.cx(),
globalObject->GetGlobalJSObject());

View File

@ -61,8 +61,11 @@ nsTraversal::TestNode(nsINode* aNode, mozilla::ErrorResult& aResult)
if (mFilter.HasWebIDLCallback()) {
AutoRestore<bool> inAcceptNode(mInAcceptNode);
mInAcceptNode = true;
// No need to pass in an execution reason, since the generated default,
// "NodeFilter.acceptNode", is pretty much exactly what we'd say anyway.
return mFilter.GetWebIDLCallback()->
AcceptNode(*aNode, aResult, CallbackObject::eRethrowExceptions);
AcceptNode(*aNode, aResult, nullptr,
CallbackObject::eRethrowExceptions);
}
nsCOMPtr<nsIDOMNode> domNode = do_QueryInterface(aNode);

View File

@ -3191,7 +3191,7 @@ WrappedJSToDictionary(nsISupports* aObject, T& aDictionary)
// we need this AutoEntryScript here because the spec requires us to execute
// getters when parsing a dictionary
AutoEntryScript aes(global);
AutoEntryScript aes(global, "WebIDL dictionary creation");
aes.TakeOwnershipOfErrorReporting();
JS::Rooted<JS::Value> v(aes.cx(), JS::ObjectValue(*obj));

View File

@ -52,6 +52,7 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_END
CallbackObject::CallSetup::CallSetup(CallbackObject* aCallback,
ErrorResult& aRv,
const char* aExecutionReason,
ExceptionHandling aExceptionHandling,
JSCompartment* aCompartment,
bool aIsJSImplementedWebIDL)
@ -127,7 +128,8 @@ CallbackObject::CallSetup::CallSetup(CallbackObject* aCallback,
return;
}
mAutoEntryScript.emplace(globalObject, mIsMainThread, cx);
mAutoEntryScript.emplace(globalObject, aExecutionReason,
mIsMainThread, cx);
mAutoEntryScript->SetWebIDLCallerPrincipal(webIDLCallerPrincipal);
nsIGlobalObject* incumbent = aCallback->IncumbentGlobalOrNull();
if (incumbent) {

View File

@ -177,6 +177,7 @@ protected:
// they will only be rethrown if that compartment's principal subsumes the
// principal of our (unwrapped) callback.
CallSetup(CallbackObject* aCallback, ErrorResult& aRv,
const char* aExecutionReason,
ExceptionHandling aExceptionHandling,
JSCompartment* aCompartment = nullptr,
bool aIsJSImplementedWebIDL = false);

View File

@ -4763,7 +4763,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
extraConditionForNull=extraConditionForNull)
elif (not type.hasNullableType and defaultValue and
isinstance(defaultValue, IDLNullValue)):
assert type.hasDictionaryType
assert type.hasDictionaryType()
assert defaultValue.type.isDictionary()
if not isOwningUnion and typeNeedsRooting(defaultValue.type):
ctorArgs = "cx"
@ -13759,9 +13759,9 @@ class CGCallback(CGClass):
self.baseName = baseName
self._deps = idlObject.getDeps()
self.idlObject = idlObject
name = idlObject.identifier.name
self.name = idlObject.identifier.name
if isJSImplementedDescriptor(descriptorProvider):
name = jsImplName(name)
self.name = jsImplName(self.name)
# For our public methods that needThisHandling we want most of the
# same args and the same return type as what CallbackMember
# generates. So we want to take advantage of all its
@ -13776,11 +13776,11 @@ class CGCallback(CGClass):
realMethods.extend(self.getMethodImpls(method))
realMethods.append(
ClassMethod("operator==", "bool",
[Argument("const %s&" % name, "aOther")],
[Argument("const %s&" % self.name, "aOther")],
inline=True, bodyInHeader=True,
const=True,
body=("return %s::operator==(aOther);\n" % baseName)))
CGClass.__init__(self, name,
CGClass.__init__(self, self.name,
bases=[ClassBase(baseName)],
constructors=self.getConstructors(),
methods=realMethods+getters+setters)
@ -13818,8 +13818,10 @@ class CGCallback(CGClass):
argnamesWithThis = ["s.GetContext()", "thisValJS"] + argnames
argnamesWithoutThis = ["s.GetContext()", "JS::UndefinedHandleValue"] + argnames
# Now that we've recorded the argnames for our call to our private
# method, insert our optional argument for deciding whether the
# CallSetup should re-throw exceptions on aRv.
# method, insert our optional arguments for the execution reason and for
# deciding whether the CallSetup should re-throw exceptions on aRv.
args.append(Argument("const char*", "aExecutionReason",
"nullptr"))
args.append(Argument("ExceptionHandling", "aExceptionHandling",
"eReportExceptions"))
# And the argument for communicating when exceptions should really be
@ -13835,13 +13837,17 @@ class CGCallback(CGClass):
setupCall = fill(
"""
CallSetup s(this, aRv, aExceptionHandling, aCompartment);
if (!aExecutionReason) {
aExecutionReason = "${executionReason}";
}
CallSetup s(this, aRv, aExecutionReason, aExceptionHandling, aCompartment);
if (!s.GetContext()) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return${errorReturn};
}
""",
errorReturn=errorReturn)
errorReturn=errorReturn,
executionReason=method.getPrettyName())
bodyWithThis = fill(
"""
@ -14145,6 +14151,8 @@ class CallbackMember(CGNativeMember):
# Since we don't need this handling, we're the actual method that
# will be called, so we need an aRethrowExceptions argument.
if not self.rethrowContentException:
args.append(Argument("const char*", "aExecutionReason",
"nullptr"))
args.append(Argument("ExceptionHandling", "aExceptionHandling",
"eReportExceptions"))
args.append(Argument("JSCompartment*", "aCompartment", "nullptr"))
@ -14162,10 +14170,10 @@ class CallbackMember(CGNativeMember):
if self.rethrowContentException:
# getArgs doesn't add the aExceptionHandling argument but does add
# aCompartment for us.
callSetup += ", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ "
callSetup += ', "%s", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ ' % self.getPrettyName()
callSetup += toStringBool(isJSImplementedDescriptor(self.descriptorProvider))
else:
callSetup += ", aExceptionHandling, aCompartment"
callSetup += ', "%s", aExceptionHandling, aCompartment' % self.getPrettyName()
callSetup += ");\n"
return fill(
"""

View File

@ -1471,6 +1471,14 @@ class IDLDictionary(IDLObjectWithScope):
def isDictionary(self):
return True;
def canBeEmpty(self):
"""
Returns true if this dictionary can be empty (that is, it has no
required members and neither do any of its ancestors).
"""
return (all(member.optional for member in self.members) and
(not self.parent or self.parent.canBeEmpty()))
def finish(self, scope):
if self._finished:
return
@ -2133,7 +2141,7 @@ class IDLUnionType(IDLType):
IDLType.__init__(self, location, "")
self.memberTypes = memberTypes
self.hasNullableType = False
self.hasDictionaryType = False
self._dictionaryType = None
self.flatMemberTypes = None
self.builtin = False
@ -2189,10 +2197,10 @@ class IDLUnionType(IDLType):
if self.hasNullableType:
raise WebIDLError("Can't have more than one nullable types in a union",
[nullableType.location, self.flatMemberTypes[i].location])
if self.hasDictionaryType:
if self.hasDictionaryType():
raise WebIDLError("Can't have a nullable type and a "
"dictionary type in a union",
[dictionaryType.location,
[self._dictionaryType.location,
self.flatMemberTypes[i].location])
self.hasNullableType = True
nullableType = self.flatMemberTypes[i]
@ -2204,8 +2212,7 @@ class IDLUnionType(IDLType):
"dictionary type in a union",
[nullableType.location,
self.flatMemberTypes[i].location])
self.hasDictionaryType = True
dictionaryType = self.flatMemberTypes[i]
self._dictionaryType = self.flatMemberTypes[i]
elif self.flatMemberTypes[i].isUnion():
self.flatMemberTypes[i:i + 1] = self.flatMemberTypes[i].memberTypes
continue
@ -2244,6 +2251,13 @@ class IDLUnionType(IDLType):
return False
return True
def hasDictionaryType(self):
return self._dictionaryType is not None
def hasPossiblyEmptyDictionaryType(self):
return (self._dictionaryType is not None and
self._dictionaryType.inner.canBeEmpty())
def _getDependentObjects(self):
return set(self.memberTypes)
@ -3036,14 +3050,14 @@ class IDLNullValue(IDLObject):
def coerceToType(self, type, location):
if (not isinstance(type, IDLNullableType) and
not (type.isUnion() and type.hasNullableType) and
not (type.isUnion() and type.hasDictionaryType) and
not (type.isUnion() and type.hasDictionaryType()) and
not type.isDictionary() and
not type.isAny()):
raise WebIDLError("Cannot coerce null value to type %s." % type,
[location])
nullValue = IDLNullValue(self.location)
if type.isUnion() and not type.nullable() and type.hasDictionaryType:
if type.isUnion() and not type.nullable() and type.hasDictionaryType():
# We're actually a default value for the union's dictionary member.
# Use its type.
for t in type.flatMemberTypes:
@ -3608,7 +3622,7 @@ class IDLArgument(IDLObjectWithIdentifier):
self.type = type
if ((self.type.isDictionary() or
self.type.isUnion() and self.type.unroll().hasDictionaryType) and
self.type.isUnion() and self.type.unroll().hasDictionaryType()) and
self.optional and not self.defaultValue and not self.variadic):
# Default optional non-variadic dictionaries to null,
# for simplicity, so the codegen doesn't have to special-case this.
@ -3930,45 +3944,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
def finish(self, scope):
IDLInterfaceMember.finish(self, scope)
overloadWithPromiseReturnType = None
overloadWithoutPromiseReturnType = None
for overload in self._overloads:
variadicArgument = None
arguments = overload.arguments
for (idx, argument) in enumerate(arguments):
if not argument.isComplete():
argument.complete(scope)
assert argument.type.isComplete()
if (argument.type.isDictionary() or
(argument.type.isUnion() and
argument.type.unroll().hasDictionaryType)):
# Dictionaries and unions containing dictionaries at the
# end of the list or followed by optional arguments must be
# optional.
if (not argument.optional and
all(arg.optional for arg in arguments[idx+1:])):
raise WebIDLError("Dictionary argument or union "
"argument containing a dictionary "
"not followed by a required argument "
"must be optional",
[argument.location])
# An argument cannot be a Nullable Dictionary
if argument.type.nullable():
raise WebIDLError("An argument cannot be a nullable "
"dictionary or nullable union "
"containing a dictionary",
[argument.location])
# Only the last argument can be variadic
if variadicArgument:
raise WebIDLError("Variadic argument is not last argument",
[variadicArgument.location])
if argument.variadic:
variadicArgument = argument
returnType = overload.returnType
if not returnType.isComplete():
returnType = returnType.complete(scope)
@ -3977,22 +3953,10 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
assert not isinstance(returnType.name, IDLUnresolvedIdentifier)
overload.returnType = returnType
if returnType.isPromise():
overloadWithPromiseReturnType = overload
else:
overloadWithoutPromiseReturnType = overload
# Make sure either all our overloads return Promises or none do
if overloadWithPromiseReturnType and overloadWithoutPromiseReturnType:
raise WebIDLError("We have overloads with both Promise and "
"non-Promise return types",
[overloadWithPromiseReturnType.location,
overloadWithoutPromiseReturnType.location])
if overloadWithPromiseReturnType and self._legacycaller:
raise WebIDLError("May not have a Promise return type for a "
"legacycaller.",
[overloadWithPromiseReturnType.location])
for argument in overload.arguments:
if not argument.isComplete():
argument.complete(scope)
assert argument.type.isComplete()
# Now compute various information that will be used by the
# WebIDL overload resolution algorithm.
@ -4022,12 +3986,67 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
distinguishingIndex),
[self.location, overload.location])
overloadWithPromiseReturnType = None
overloadWithoutPromiseReturnType = None
for overload in self._overloads:
if not overload.returnType.unroll().isExposedInAllOf(self.exposureSet):
returnType = overload.returnType
if not returnType.unroll().isExposedInAllOf(self.exposureSet):
raise WebIDLError("Overload returns a type that is not exposed "
"everywhere where the method is exposed",
[overload.location])
variadicArgument = None
arguments = overload.arguments
for (idx, argument) in enumerate(arguments):
assert argument.type.isComplete()
if ((argument.type.isDictionary() and
argument.type.inner.canBeEmpty())or
(argument.type.isUnion() and
argument.type.unroll().hasPossiblyEmptyDictionaryType())):
# Optional dictionaries and unions containing optional
# dictionaries at the end of the list or followed by
# optional arguments must be optional.
if (not argument.optional and
all(arg.optional for arg in arguments[idx+1:])):
raise WebIDLError("Dictionary argument or union "
"argument containing a dictionary "
"not followed by a required argument "
"must be optional",
[argument.location])
# An argument cannot be a Nullable Dictionary
if argument.type.nullable():
raise WebIDLError("An argument cannot be a nullable "
"dictionary or nullable union "
"containing a dictionary",
[argument.location])
# Only the last argument can be variadic
if variadicArgument:
raise WebIDLError("Variadic argument is not last argument",
[variadicArgument.location])
if argument.variadic:
variadicArgument = argument
if returnType.isPromise():
overloadWithPromiseReturnType = overload
else:
overloadWithoutPromiseReturnType = overload
# Make sure either all our overloads return Promises or none do
if overloadWithPromiseReturnType and overloadWithoutPromiseReturnType:
raise WebIDLError("We have overloads with both Promise and "
"non-Promise return types",
[overloadWithPromiseReturnType.location,
overloadWithoutPromiseReturnType.location])
if overloadWithPromiseReturnType and self._legacycaller:
raise WebIDLError("May not have a Promise return type for a "
"legacycaller.",
[overloadWithPromiseReturnType.location])
def overloadsForArgCount(self, argc):
return [overload for overload in self._overloads if
len(overload.arguments) == argc or

View File

@ -712,6 +712,7 @@ public:
// Dictionary tests
void PassDictionary(JSContext*, const Dict&);
void PassDictionary2(JSContext*, const Dict&);
void GetReadonlyDictionary(JSContext*, Dict&);
void GetReadonlyNullableDictionary(JSContext*, Nullable<Dict>&);
void GetWritableDictionary(JSContext*, Dict&);

View File

@ -685,6 +685,7 @@ interface TestInterface {
attribute byte otherAttributeRenamedFrom;
void passDictionary(optional Dict x);
void passDictionary2(Dict x);
[Cached, Pure]
readonly attribute Dict readonlyDictionary;
[Cached, Pure]

View File

@ -549,6 +549,7 @@ interface TestExampleInterface {
attribute byte otherAttributeRenamedFrom;
void passDictionary(optional Dict x);
void passDictionary2(Dict x);
[Cached, Pure]
readonly attribute Dict readonlyDictionary;
[Cached, Pure]

View File

@ -562,6 +562,7 @@ interface TestJSImplInterface {
attribute byte otherAttributeRenamedFrom;
void passDictionary(optional Dict x);
void passDictionary2(Dict x);
[Cached, Pure]
readonly attribute Dict readonlyDictionary;
[Cached, Pure]

View File

@ -241,7 +241,7 @@ nsGeolocationSettings::HandleGeolocationPerOriginSettingsChange(const JS::Value&
// because the spec requires calling getters when enumerating the key of a
// dictionary
AutoEntryScript aes(global);
AutoEntryScript aes(global, "geolocation.app_settings enumeration");
aes.TakeOwnershipOfErrorReporting();
JSContext *cx = aes.cx();
JS::AutoIdArray ids(cx, JS_Enumerate(cx, obj));
@ -317,7 +317,7 @@ nsGeolocationSettings::HandleGeolocationAlwaysPreciseChange(const JS::Value& aVa
NS_ENSURE_TRUE_VOID(global && global->GetGlobalJSObject());
// the spec requires calling getters when accessing array by index
AutoEntryScript aes(global);
AutoEntryScript aes(global, "geolocation.always_precise indexing");
aes.TakeOwnershipOfErrorReporting();
JSContext *cx = aes.cx();

View File

@ -33,7 +33,7 @@ interface nsIServiceWorkerInfo : nsISupports
readonly attribute DOMString waitingCacheName;
};
[scriptable, builtinclass, uuid(3cd3acce-8c80-4fcc-9265-067ebe8cab92)]
[scriptable, builtinclass, uuid(c05b3b45-7f39-458c-8097-afafc7d69b01)]
interface nsIServiceWorkerManager : nsISupports
{
/**
@ -124,6 +124,8 @@ interface nsIServiceWorkerManager : nsISupports
void sendPushEvent(in ACString scope, in DOMString data);
void sendPushSubscriptionChangedEvent(in ACString scope);
void updateAllRegistrations();
};
%{ C++

View File

@ -78,6 +78,7 @@
#include "nsIMutable.h"
#include "nsIObserverService.h"
#include "nsIScriptSecurityManager.h"
#include "nsIServiceWorkerManager.h"
#include "nsScreenManagerProxy.h"
#include "nsMemoryInfoDumper.h"
#include "nsServiceManagerUtils.h"
@ -1239,6 +1240,16 @@ ContentChild::RecvBidiKeyboardNotify(const bool& aIsLangRTL)
return true;
}
bool
ContentChild::RecvUpdateServiceWorkerRegistrations()
{
nsCOMPtr<nsIServiceWorkerManager> swm = mozilla::services::GetServiceWorkerManager();
if (swm) {
swm->UpdateAllRegistrations();
}
return true;
}
static CancelableTask* sFirstIdleTask;
static void FirstIdle(void)

View File

@ -301,6 +301,8 @@ public:
virtual bool RecvBidiKeyboardNotify(const bool& isLangRTL) override;
virtual bool RecvUpdateServiceWorkerRegistrations() override;
virtual bool RecvNotifyVisited(const URIParams& aURI) override;
// auto remove when alertfinished is received.
nsresult AddRemoteAlertObserver(const nsString& aData, nsIObserver* aObserver);

View File

@ -465,6 +465,8 @@ child:
*/
async BidiKeyboardNotify(bool isLangRTL);
async UpdateServiceWorkerRegistrations();
async DataStoreNotify(uint32_t aAppId, nsString aName,
nsString aManifestURL);

View File

@ -249,7 +249,7 @@ nsresult nsJSThunk::EvaluateScript(nsIChannel *aChannel,
// New script entry point required, due to the "Create a script" step of
// http://www.whatwg.org/specs/web-apps/current-work/#javascript-protocol
AutoEntryScript entryScript(innerGlobal, true,
AutoEntryScript entryScript(innerGlobal, "javascript: URI", true,
scriptContext->GetNativeContext());
JSContext* cx = entryScript.cx();
JS::Rooted<JSObject*> globalJSObject(cx, innerGlobal->GetGlobalJSObject());

View File

@ -8,8 +8,14 @@
#include "MediaTaskQueue.h"
#include "nsThreadUtils.h"
#include "TaskDispatcher.h"
#include "nsIAppShell.h"
#include "nsWidgetsCID.h"
#include "nsServiceManagerUtils.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/Maybe.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/unused.h"
@ -18,13 +24,26 @@ namespace mozilla {
StaticRefPtr<AbstractThread> sMainThread;
ThreadLocal<AbstractThread*> AbstractThread::sCurrentThreadTLS;
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
class XPCOMThreadWrapper : public AbstractThread
{
public:
explicit XPCOMThreadWrapper(nsIThread* aTarget)
: AbstractThread(/* aRequireTailDispatch = */ false)
explicit XPCOMThreadWrapper(nsIThread* aTarget, bool aRequireTailDispatch)
: AbstractThread(aRequireTailDispatch)
, mTarget(aTarget)
{}
{
// Our current mechanism of implementing tail dispatch is appshell-specific.
// This is because a very similar mechanism already exists on the main
// thread, and we want to avoid making event dispatch on the main thread
// more complicated than it already is.
//
// If you need to use tail dispatch on other XPCOM threads, you'll need to
// implement an nsIThreadObserver to fire the tail dispatcher at the
// appropriate times.
MOZ_ASSERT_IF(aRequireTailDispatch,
NS_IsMainThread() && NS_GetCurrentThread() == aTarget);
}
virtual void Dispatch(already_AddRefed<nsIRunnable> aRunnable,
DispatchFailureHandling aFailureHandling = AssertDispatchSuccess,
@ -45,14 +64,30 @@ public:
virtual bool IsCurrentThreadIn() override
{
bool in = NS_GetCurrentThread() == mTarget;
MOZ_ASSERT_IF(in, GetCurrent() == this);
MOZ_ASSERT(in == (GetCurrent() == this));
return in;
}
virtual TaskDispatcher& TailDispatcher() override { MOZ_CRASH("Not implemented!"); }
void FireTailDispatcher() { MOZ_ASSERT(mTailDispatcher.isSome()); mTailDispatcher.reset(); }
virtual TaskDispatcher& TailDispatcher() override
{
MOZ_ASSERT(this == sMainThread); // See the comment in the constructor.
MOZ_ASSERT(IsCurrentThreadIn());
if (!mTailDispatcher.isSome()) {
mTailDispatcher.emplace(/* aIsTailDispatcher = */ true);
nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &XPCOMThreadWrapper::FireTailDispatcher);
nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
appShell->RunInStableState(event);
}
return mTailDispatcher.ref();
}
private:
nsRefPtr<nsIThread> mTarget;
Maybe<AutoTaskDispatcher> mTailDispatcher;
};
AbstractThread*
@ -70,7 +105,7 @@ AbstractThread::InitStatics()
nsCOMPtr<nsIThread> mainThread;
NS_GetMainThread(getter_AddRefs(mainThread));
MOZ_DIAGNOSTIC_ASSERT(mainThread);
sMainThread = new XPCOMThreadWrapper(mainThread.get());
sMainThread = new XPCOMThreadWrapper(mainThread.get(), /* aRequireTailDispatch = */ true);
ClearOnShutdown(&sMainThread);
if (!sCurrentThreadTLS.init()) {

View File

@ -106,8 +106,16 @@ private:
void
MediaTaskQueue::SyncDispatch(TemporaryRef<nsIRunnable> aRunnable) {
NS_WARNING("MediaTaskQueue::SyncDispatch is dangerous and deprecated. Stop using this!");
RefPtr<MediaTaskQueueSyncRunnable> task(new MediaTaskQueueSyncRunnable(aRunnable));
Dispatch(task);
nsRefPtr<MediaTaskQueueSyncRunnable> task(new MediaTaskQueueSyncRunnable(aRunnable));
// Tail dispatchers don't interact nicely with sync dispatch. We require that
// nothing is already in the tail dispatcher, and then sidestep it for this
// task.
MOZ_ASSERT_IF(AbstractThread::GetCurrent(),
!AbstractThread::GetCurrent()->TailDispatcher().HasTasksFor(this));
nsRefPtr<MediaTaskQueueSyncRunnable> taskRef = task;
Dispatch(taskRef.forget(), AssertDispatchSuccess, TailDispatch);
task->WaitUntilDone();
}
@ -121,6 +129,11 @@ MediaTaskQueue::AwaitIdle()
void
MediaTaskQueue::AwaitIdleLocked()
{
// Make the there are no tasks for this queue waiting in the caller's tail
// dispatcher.
MOZ_ASSERT_IF(AbstractThread::GetCurrent(),
!AbstractThread::GetCurrent()->TailDispatcher().HasTasksFor(this));
mQueueMonitor.AssertCurrentThreadOwns();
MOZ_ASSERT(mIsRunning || mTasks.empty());
while (mIsRunning) {
@ -131,6 +144,11 @@ MediaTaskQueue::AwaitIdleLocked()
void
MediaTaskQueue::AwaitShutdownAndIdle()
{
// Make the there are no tasks for this queue waiting in the caller's tail
// dispatcher.
MOZ_ASSERT_IF(AbstractThread::GetCurrent(),
!AbstractThread::GetCurrent()->TailDispatcher().HasTasksFor(this));
MonitorAutoLock mon(mQueueMonitor);
while (!mIsShutdown) {
mQueueMonitor.Wait();
@ -176,6 +194,11 @@ FlushableMediaTaskQueue::FlushAndDispatch(TemporaryRef<nsIRunnable> aRunnable)
void
FlushableMediaTaskQueue::FlushLocked()
{
// Make the there are no tasks for this queue waiting in the caller's tail
// dispatcher.
MOZ_ASSERT_IF(AbstractThread::GetCurrent(),
!AbstractThread::GetCurrent()->TailDispatcher().HasTasksFor(this));
mQueueMonitor.AssertCurrentThreadOwns();
MOZ_ASSERT(mIsFlushing);
@ -197,7 +220,7 @@ bool
MediaTaskQueue::IsCurrentThreadIn()
{
bool in = NS_GetCurrentThread() == mRunningThread;
MOZ_ASSERT_IF(in, GetCurrent() == this);
MOZ_ASSERT(in == (GetCurrent() == this));
return in;
}

View File

@ -20,7 +20,6 @@ const PC_ICE_CONTRACT = "@mozilla.org/dom/rtcicecandidate;1";
const PC_SESSION_CONTRACT = "@mozilla.org/dom/rtcsessiondescription;1";
const PC_MANAGER_CONTRACT = "@mozilla.org/dom/peerconnectionmanager;1";
const PC_STATS_CONTRACT = "@mozilla.org/dom/rtcstatsreport;1";
const PC_IDENTITY_CONTRACT = "@mozilla.org/dom/rtcidentityassertion;1";
const PC_STATIC_CONTRACT = "@mozilla.org/dom/peerconnectionstatic;1";
const PC_SENDER_CONTRACT = "@mozilla.org/dom/rtpsender;1";
const PC_RECEIVER_CONTRACT = "@mozilla.org/dom/rtpreceiver;1";
@ -31,7 +30,6 @@ const PC_ICE_CID = Components.ID("{02b9970c-433d-4cc2-923d-f7028ac66073}");
const PC_SESSION_CID = Components.ID("{1775081b-b62d-4954-8ffe-a067bbf508a7}");
const PC_MANAGER_CID = Components.ID("{7293e901-2be3-4c02-b4bd-cbef6fc24f78}");
const PC_STATS_CID = Components.ID("{7fe6e18b-0da3-4056-bf3b-440ef3809e06}");
const PC_IDENTITY_CID = Components.ID("{1abc7499-3c54-43e0-bd60-686e2703f072}");
const PC_STATIC_CID = Components.ID("{0fb47c47-a205-4583-a9fc-cbadf8c95880}");
const PC_SENDER_CID = Components.ID("{4fff5d46-d827-4cd4-a970-8fd53977440e}");
const PC_RECEIVER_CID = Components.ID("{d974b814-8fde-411c-8c45-b86791b81030}");
@ -272,22 +270,6 @@ RTCStatsReport.prototype = {
get mozPcid() { return this._pcid; }
};
function RTCIdentityAssertion() {}
RTCIdentityAssertion.prototype = {
classDescription: "RTCIdentityAssertion",
classID: PC_IDENTITY_CID,
contractID: PC_IDENTITY_CONTRACT,
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
Ci.nsIDOMGlobalPropertyInitializer]),
init: function(win) { this._win = win; },
__init: function(idp, name) {
this.idp = idp;
this.name = name;
}
};
function RTCPeerConnection() {
this._senders = [];
this._receivers = [];
@ -717,9 +699,10 @@ RTCPeerConnection.prototype = {
if (msg) {
// Set new identity and generate an event.
this._impl.peerIdentity = msg.identity;
let assertion = new this._win.RTCIdentityAssertion(
this._remoteIdp.provider, msg.identity);
this._resolvePeerIdentity(assertion);
this._resolvePeerIdentity(Cu.cloneInto({
idp: this._remoteIdp.provider,
name: msg.identity
}, this._win));
}
})
.catch(e => {
@ -1343,6 +1326,5 @@ this.NSGetFactory = XPCOMUtils.generateNSGetFactory(
RTCRtpReceiver,
RTCRtpSender,
RTCStatsReport,
RTCIdentityAssertion,
PeerConnectionObserver]
);

View File

@ -4,7 +4,6 @@ component {02b9970c-433d-4cc2-923d-f7028ac66073} PeerConnection.js
component {1775081b-b62d-4954-8ffe-a067bbf508a7} PeerConnection.js
component {7293e901-2be3-4c02-b4bd-cbef6fc24f78} PeerConnection.js
component {7fe6e18b-0da3-4056-bf3b-440ef3809e06} PeerConnection.js
component {1abc7499-3c54-43e0-bd60-686e2703f072} PeerConnection.js
component {0fb47c47-a205-4583-a9fc-cbadf8c95880} PeerConnection.js
component {4fff5d46-d827-4cd4-a970-8fd53977440e} PeerConnection.js
component {d974b814-8fde-411c-8c45-b86791b81030} PeerConnection.js
@ -15,7 +14,6 @@ contract @mozilla.org/dom/rtcicecandidate;1 {02b9970c-433d-4cc2-923d-f7028ac6607
contract @mozilla.org/dom/rtcsessiondescription;1 {1775081b-b62d-4954-8ffe-a067bbf508a7}
contract @mozilla.org/dom/peerconnectionmanager;1 {7293e901-2be3-4c02-b4bd-cbef6fc24f78}
contract @mozilla.org/dom/rtcstatsreport;1 {7fe6e18b-0da3-4056-bf3b-440ef3809e06}
contract @mozilla.org/dom/rtcidentityassertion;1 {1abc7499-3c54-43e0-bd60-686e2703f072}
contract @mozilla.org/dom/peerconnectionstatic;1 {0fb47c47-a205-4583-a9fc-cbadf8c95880}
contract @mozilla.org/dom/rtpsender;1 {4fff5d46-d827-4cd4-a970-8fd53977440e}
contract @mozilla.org/dom/rtpreceiver;1 {d974b814-8fde-411c-8c45-b86791b81030}

View File

@ -44,13 +44,15 @@ public:
virtual void AddTask(AbstractThread* aThread,
already_AddRefed<nsIRunnable> aRunnable,
AbstractThread::DispatchFailureHandling aFailureHandling = AbstractThread::AssertDispatchSuccess) = 0;
virtual bool HasTasksFor(AbstractThread* aThread) = 0;
};
/*
* AutoTaskDispatcher is a stack-scoped TaskDispatcher implementation that fires
* its queued tasks when it is popped off the stack.
*/
class MOZ_STACK_CLASS AutoTaskDispatcher : public TaskDispatcher
class AutoTaskDispatcher : public TaskDispatcher
{
public:
explicit AutoTaskDispatcher(bool aIsTailDispatcher = false) : mIsTailDispatcher(aIsTailDispatcher) {}
@ -88,6 +90,8 @@ public:
}
}
bool HasTasksFor(AbstractThread* aThread) override { return !!GetTaskGroup(aThread); }
private:
struct PerThreadTaskGroup
@ -131,16 +135,27 @@ private:
PerThreadTaskGroup& EnsureTaskGroup(AbstractThread* aThread)
{
for (size_t i = 0; i < mTaskGroups.Length(); ++i) {
if (mTaskGroups[i]->mThread == aThread) {
return *mTaskGroups[i];
}
PerThreadTaskGroup* existing = GetTaskGroup(aThread);
if (existing) {
return *existing;
}
mTaskGroups.AppendElement(new PerThreadTaskGroup(aThread));
return *mTaskGroups.LastElement();
}
PerThreadTaskGroup* GetTaskGroup(AbstractThread* aThread)
{
for (size_t i = 0; i < mTaskGroups.Length(); ++i) {
if (mTaskGroups[i]->mThread == aThread) {
return mTaskGroups[i].get();
}
}
// Not found.
return nullptr;
}
// Task groups, organized by thread.
nsTArray<UniquePtr<PerThreadTaskGroup>> mTaskGroups;

View File

@ -58,7 +58,11 @@ private:
{
{
nsRefPtr<MediaTaskQueue> queue = reader->GetTaskQueue();
queue->Dispatch(NS_NewRunnableMethod(reader, &MP4Reader::Shutdown));
nsCOMPtr<nsIRunnable> task = NS_NewRunnableMethod(reader, &MP4Reader::Shutdown);
// Hackily bypass the tail dispatcher so that we can AwaitShutdownAndIdle.
// In production code we'd use BeginShutdown + promises.
queue->Dispatch(task.forget(), AbstractThread::AssertDispatchSuccess,
AbstractThread::TailDispatch);
queue->AwaitShutdownAndIdle();
}
decoder = nullptr;

View File

@ -21,9 +21,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=604067
/** Test for Bug 604067 **/
function documentVideo() {
return document.body.getElementsByTagName("iframe")[0]
.contentDocument.body.getElementsByTagName("video")[0];
}
function check() {
var v = document.body.getElementsByTagName("iframe")[0]
.contentDocument.body.getElementsByTagName("video")[0];
var v = documentVideo();
// Debug info for Bug 608634
ok(true, "iframe src=" + document.body.getElementsByTagName("iframe")[0].src);
@ -47,7 +51,15 @@ if (!t) {
var f = document.createElement("iframe");
f.src = t.name;
f.addEventListener("load", function() { SimpleTest.executeSoon(check); }, false);
f.addEventListener("load", function() {
if (documentVideo().error) {
info("Error occured by the time we got |load| - checking directly.");
check();
} else {
todo(false, "Error hasn't occurred yet - adding |error| event listener. This shouldn't happen, see bug 608634.");
documentVideo().addEventListener("error", check);
}
}, false);
document.body.appendChild(f);
}

View File

@ -773,7 +773,7 @@ doInvoke(NPObject *npobj, NPIdentifier method, const NPVariant *args,
// We're about to run script via JS_CallFunctionValue, so we need an
// AutoEntryScript. NPAPI plugins are Gecko-specific and not in any spec.
dom::AutoEntryScript aes(globalObject);
dom::AutoEntryScript aes(globalObject, "NPAPI doInvoke");
JSContext *cx = aes.cx();
if (!npobj || !result) {
@ -901,7 +901,7 @@ nsJSObjWrapper::NP_GetProperty(NPObject *npobj, NPIdentifier id,
// We're about to run script via JS_CallFunctionValue, so we need an
// AutoEntryScript. NPAPI plugins are Gecko-specific and not in any spec.
dom::AutoEntryScript aes(globalObject);
dom::AutoEntryScript aes(globalObject, "NPAPI get");
JSContext *cx = aes.cx();
if (!npobj) {
@ -935,7 +935,7 @@ nsJSObjWrapper::NP_SetProperty(NPObject *npobj, NPIdentifier npid,
// We're about to run script via JS_CallFunctionValue, so we need an
// AutoEntryScript. NPAPI plugins are Gecko-specific and not in any spec.
dom::AutoEntryScript aes(globalObject);
dom::AutoEntryScript aes(globalObject, "NPAPI set");
JSContext *cx = aes.cx();
if (!npobj) {

View File

@ -1498,7 +1498,7 @@ _evaluate(NPP npp, NPObject* npobj, NPString *script, NPVariant *result)
return false;
}
dom::AutoEntryScript aes(win);
dom::AutoEntryScript aes(win, "NPAPI NPN_evaluate");
JSContext* cx = aes.cx();
JS::Rooted<JSObject*> obj(cx, nsNPObjWrapper::GetNewOrUsed(npp, cx, npobj));

View File

@ -225,7 +225,7 @@ protected:
JS::Rooted<JSObject*> rootedThenable(cx, mThenable);
mThen->Call(rootedThenable, resolveFunc, rejectFunc, rv,
CallbackObject::eRethrowExceptions,
"promise thenable", CallbackObject::eRethrowExceptions,
mPromise->Compartment());
rv.WouldReportJSException();
@ -630,8 +630,8 @@ Promise::CallInitFunction(const GlobalObject& aGlobal,
return;
}
aInit.Call(resolveFunc, rejectFunc, aRv, CallbackObject::eRethrowExceptions,
Compartment());
aInit.Call(resolveFunc, rejectFunc, aRv, "promise initializer",
CallbackObject::eRethrowExceptions, Compartment());
aRv.WouldReportJSException();
if (aRv.IsJSException()) {

View File

@ -205,7 +205,8 @@ WrapperPromiseCallback::Call(JSContext* aCx,
// PromiseReactionTask step 6
JS::Rooted<JS::Value> retValue(aCx);
mCallback->Call(value, &retValue, rv, CallbackObject::eRethrowExceptions,
mCallback->Call(value, &retValue, rv, "promise callback",
CallbackObject::eRethrowExceptions,
mNextPromise->Compartment());
rv.WouldReportJSException();

View File

@ -4,13 +4,10 @@
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* The origin of this IDL file is
* http://www.w3.org/TR/2013/WD-webrtc-20130910/#idl-def-RTCIdentityAssertion
* http://w3c.github.io/webrtc-pc/#idl-def-RTCIdentityAssertion
*/
[Pref="media.peerconnection.identity.enabled",
JSImplementation="@mozilla.org/dom/rtcidentityassertion;1",
Constructor(DOMString idp, DOMString name)]
interface RTCIdentityAssertion {
attribute DOMString idp;
attribute DOMString name;
dictionary RTCIdentityAssertion {
DOMString idp;
DOMString name;
};

View File

@ -34,6 +34,7 @@
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/PBackgroundChild.h"
#include "mozilla/ipc/PBackgroundSharedTypes.h"
#include "mozilla/unused.h"
#include "nsContentUtils.h"
#include "nsGlobalWindow.h"
@ -3110,6 +3111,28 @@ ServiceWorkerManager::GetAllRegistrations(nsIArray** aResult)
return NS_OK;
}
static PLDHashOperator
UpdateEachRegistration(const nsACString& aKey,
ServiceWorkerRegistrationInfo* aInfo,
void* aUserArg) {
auto This = static_cast<ServiceWorkerManager*>(aUserArg);
MOZ_ASSERT(!aInfo->mScope.IsEmpty());
nsresult res = This->Update(NS_ConvertUTF8toUTF16(aInfo->mScope));
unused << NS_WARN_IF(NS_FAILED(res));
return PL_DHASH_NEXT;
}
NS_IMETHODIMP
ServiceWorkerManager::UpdateAllRegistrations()
{
AssertIsOnMainThread();
mServiceWorkerRegistrationInfos.EnumerateRead(UpdateEachRegistration, this);
return NS_OK;
}
void
ServiceWorkerInfo::AppendWorker(ServiceWorker* aWorker)
{

View File

@ -0,0 +1,79 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ServiceWorkerPeriodicUpdater.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/unused.h"
#include "mozilla/Services.h"
#include "mozilla/Preferences.h"
#include "mozilla/dom/ContentParent.h"
#include "nsIServiceWorkerManager.h"
#define OBSERVER_TOPIC_IDLE_DAILY "idle-daily"
namespace mozilla {
namespace dom {
namespace workers {
NS_IMPL_ISUPPORTS(ServiceWorkerPeriodicUpdater, nsIObserver)
StaticRefPtr<ServiceWorkerPeriodicUpdater>
ServiceWorkerPeriodicUpdater::sInstance;
bool
ServiceWorkerPeriodicUpdater::sPeriodicUpdatesEnabled = true;
already_AddRefed<ServiceWorkerPeriodicUpdater>
ServiceWorkerPeriodicUpdater::GetSingleton()
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
if (!sInstance) {
sInstance = new ServiceWorkerPeriodicUpdater();
ClearOnShutdown(&sInstance);
}
nsRefPtr<ServiceWorkerPeriodicUpdater> copy(sInstance.get());
return copy.forget();
}
ServiceWorkerPeriodicUpdater::ServiceWorkerPeriodicUpdater()
{
Preferences::AddBoolVarCache(&sPeriodicUpdatesEnabled,
"dom.serviceWorkers.periodic-updates.enabled",
true);
}
ServiceWorkerPeriodicUpdater::~ServiceWorkerPeriodicUpdater()
{
}
NS_IMETHODIMP
ServiceWorkerPeriodicUpdater::Observe(nsISupports* aSubject,
const char* aTopic,
const char16_t* aData)
{
if (strcmp(aTopic, OBSERVER_TOPIC_IDLE_DAILY) == 0 &&
sPeriodicUpdatesEnabled) {
// First, update all registrations in the parent process.
nsCOMPtr<nsIServiceWorkerManager> swm =
mozilla::services::GetServiceWorkerManager();
if (swm) {
swm->UpdateAllRegistrations();
}
// Now, tell all child processes to update their registrations as well.
nsTArray<ContentParent*> children;
ContentParent::GetAll(children);
for (uint32_t i = 0; i < children.Length(); i++) {
unused << children[i]->SendUpdateServiceWorkerRegistrations();
}
}
return NS_OK;
}
} // namespace workers
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,46 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_ServiceWorkerPeriodicUpdater_h
#define mozilla_ServiceWorkerPeriodicUpdater_h
#include "nsCOMPtr.h"
#include "nsIObserver.h"
#include "mozilla/StaticPtr.h"
namespace mozilla {
namespace dom {
namespace workers {
/**
* This XPCOM component is main-process only, which means that it will never
* get instantiated in child processes. When we receive the idle-daily
* notification in this component, we iterate over all PContent children, and
* send each one a message that will trigger a call to
* nsIServiceWorkerManager::UpdateAllRegistrations() in all child processes.
*/
class ServiceWorkerPeriodicUpdater final : public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
static already_AddRefed<ServiceWorkerPeriodicUpdater> GetSingleton();
private:
ServiceWorkerPeriodicUpdater();
~ServiceWorkerPeriodicUpdater();
static StaticRefPtr<ServiceWorkerPeriodicUpdater> sInstance;
static bool sPeriodicUpdatesEnabled;
};
} // namespace workers
} // namespace dom
} // namespace mozilla
#endif

View File

@ -297,7 +297,7 @@ WorkerRunnable::Run()
MOZ_ASSERT(IsCanceled(), "Subclass Cancel() didn't set IsCanceled()!");
return NS_OK;
}
}
// Track down the appropriate global to use for the AutoJSAPI/AutoEntryScript.
nsCOMPtr<nsIGlobalObject> globalObject;
@ -332,8 +332,9 @@ WorkerRunnable::Run()
Maybe<mozilla::dom::AutoEntryScript> aes;
JSContext* cx;
if (globalObject) {
aes.emplace(globalObject, isMainThread, isMainThread ? nullptr :
GetCurrentThreadJSContext());
aes.emplace(globalObject, "Worker runnable",
isMainThread,
isMainThread ? nullptr : GetCurrentThreadJSContext());
cx = aes->cx();
} else {
jsapi.Init();
@ -352,7 +353,8 @@ WorkerRunnable::Run()
// In the case of CompileScriptRunnnable, WorkerRun above can cause us to
// lazily create a global, so we construct aes here before calling PostRun.
if (targetIsWorkerThread && !aes && DefaultGlobalObject()) {
aes.emplace(DefaultGlobalObject(), false, GetCurrentThreadJSContext());
aes.emplace(DefaultGlobalObject(), "worker runnable",
false, GetCurrentThreadJSContext());
cx = aes->cx();
}

View File

@ -18,6 +18,7 @@ EXPORTS.mozilla.dom += [
EXPORTS.mozilla.dom.workers += [
'ServiceWorkerManager.h',
'ServiceWorkerPeriodicUpdater.h',
'WorkerDebuggerManager.h',
'Workers.h',
]
@ -68,6 +69,7 @@ UNIFIED_SOURCES += [
'ServiceWorkerContainer.cpp',
'ServiceWorkerEvents.cpp',
'ServiceWorkerManager.cpp',
'ServiceWorkerPeriodicUpdater.cpp',
'ServiceWorkerRegistrar.cpp',
'ServiceWorkerRegistration.cpp',
'ServiceWorkerScriptCache.cpp',

View File

@ -46,6 +46,19 @@ fetchXHR('synthesized-headers.txt', function(xhr) {
finish();
});
fetch('synthesized-redirect-real-file.txt', function(xhr) {
dump("Got status AARRGH " + xhr.status + " " + xhr.responseText + "\n");
my_ok(xhr.status == 200, "load should be successful");
my_ok(xhr.responseText == "This is a real file.\n", "Redirect to real file should complete.");
finish();
});
fetch('synthesized-redirect-synthesized.txt', function(xhr) {
my_ok(xhr.status == 200, "load should be successful");
my_ok(xhr.responseText == "synthesized response body", "load should have synthesized response");
finish();
});
fetchXHR('ignored.txt', function(xhr) {
my_ok(xhr.status == 404, "load should be uninterrupted");
finish();

View File

@ -0,0 +1 @@
This is a real file.

View File

@ -27,6 +27,18 @@ onfetch = function(ev) {
ev.respondWith(new Response("test-respondwith-response response body", {}));
}
else if (ev.request.url.contains("synthesized-redirect-real-file.txt")) {
ev.respondWith(Promise.resolve(
Response.redirect("fetch/real-file.txt")
));
}
else if (ev.request.url.contains("synthesized-redirect-synthesized.txt")) {
ev.respondWith(Promise.resolve(
Response.redirect("synthesized.txt")
));
}
else if (ev.request.url.contains("ignored.txt")) {
}

View File

@ -27,6 +27,7 @@ support-files =
fetch/fetch_worker_script.js
fetch/fetch_tests.js
fetch/deliver-gzip.sjs
fetch/real-file.txt
fetch/context/index.html
fetch/context/register.html
fetch/context/unregister.html
@ -68,11 +69,15 @@ support-files =
bug1151916_worker.js
bug1151916_driver.html
empty.js
periodic.sjs
periodic/frame.html
periodic/register.html
periodic/unregister.html
[test_unregister.html]
[test_installation_simple.html]
[test_fetch_event.html]
skip-if = true # Bug 1136780
skip-if = os != "linux" # Bug 1136780
[test_https_fetch.html]
[test_https_fetch_cloned_response.html]
[test_match_all.html]
@ -97,3 +102,5 @@ skip-if = true # Bug 1136780
[test_client_focus.html]
[test_bug1151916.html]
[test_empty_serviceworker.html]
[test_periodic_update.html]
skip-if = true # bug 1151974

View File

@ -0,0 +1,18 @@
function handleRequest(request, response) {
if (!getState('periodiccounter')) {
setState('periodiccounter', '1');
} else {
// Make sure that we pass a string value to setState!
setState('periodiccounter', "" + (parseInt(getState('periodiccounter')) + 1));
}
response.setHeader("Content-Type", "application/javascript", false);
response.write(getScript());
}
function getScript() {
return "onfetch = function(e) {" +
"if (e.request.url.indexOf('get-sw-version') > -1) {" +
"e.respondWith(new Response('" + getState('periodiccounter') + "'));" +
"}" +
"};";
}

View File

@ -0,0 +1,8 @@
<!DOCTYPE html>
<script>
fetch("get-sw-version").then(function(r) {
return r.text();
}).then(function(body) {
parent.callback(body);
});
</script>

View File

@ -0,0 +1,21 @@
<!DOCTYPE html>
<script>
var isDone = false;
function done() {
if (!isDone) {
parent.callback();
isDone = true;
}
}
navigator.serviceWorker.register("../periodic.sjs", {scope: "."})
.then(function(registration) {
if (registration.installing) {
registration.installing.onstatechange = function(e) {
done();
};
} else {
done();
}
});
</script>

View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<script>
navigator.serviceWorker.getRegistration(".").then(function(registration) {
registration.unregister().then(function(success) {
if (success) {
parent.callback();
} else {
dump("Unregister failed\n");
}
});
});
</script>

View File

@ -0,0 +1,98 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1112469 - Test the periodic update of service workers</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script class="testbody" type="text/javascript">
var oldSWVersion, newSWVersion;
function start() {
const Cc = SpecialPowers.Cc;
const Ci = SpecialPowers.Ci;
function testVersion(sw) {
// Verify that the service worker has been correctly updated.
testFrame("periodic/frame.html").then(function(body) {
newSWVersion = parseInt(body);
todo_is(newSWVersion, "2", "Expected correct new version");
ok(newSWVersion > oldSWVersion,
"The SW should be successfully updated, old: " + oldSWVersion +
", new: " + newSWVersion);
unregisterSW().then(function() {
SimpleTest.finish();
});
});
}
registerSW().then(function() {
return testFrame("periodic/frame.html").then(function(body) {
oldSWVersion = parseInt(body);
todo_is(oldSWVersion, "1", "Expected correct old version");
});
}).then(function() {
return navigator.serviceWorker.getRegistration("periodic/foo");
}).then(function(reg) {
reg.onupdatefound = function() {
reg.onupdatefound = null;
var sw = reg.installing;
sw.onstatechange = function() {
sw.onstatechange = null;
ok(!reg.waiting && reg.active, "New worker must get activated immediately");
testVersion(reg.active);
};
};
}).then(function() {
SpecialPowers.startPeriodicServiceWorkerUpdates();
});
}
function testFrame(src) {
return new Promise(function(resolve, reject) {
var iframe = document.createElement("iframe");
iframe.src = src;
window.callback = function(result) {
iframe.src = "about:blank";
document.body.removeChild(iframe);
iframe = null;
SpecialPowers.exactGC(window, function() {
resolve(result);
});
};
document.body.appendChild(iframe);
});
}
function registerSW() {
return testFrame("periodic/register.html");
}
function unregisterSW() {
return testFrame("periodic/unregister.html");
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
["dom.serviceWorkers.periodic-updates.enabled", true],
]}, function() {
start();
});
</script>
</pre>
</body>
</html>

View File

@ -402,7 +402,7 @@ nsXBLProtoImplField::InstallField(JS::Handle<JSObject*> aBoundNode,
// We are going to run script via EvaluateString, so we need a script entry
// point, but as this is XBL related it does not appear in the HTML spec.
AutoEntryScript entryScript(globalObject, true);
AutoEntryScript entryScript(globalObject, "XBL <field> initialization", true);
JSContext* cx = entryScript.cx();
NS_ASSERTION(!::JS_IsExceptionPending(cx),

View File

@ -294,7 +294,7 @@ nsXBLProtoImplAnonymousMethod::Execute(nsIContent* aBoundElement, JSAddonId* aAd
// We are going to run script via JS::Call, so we need a script entry point,
// but as this is XBL related it does not appear in the HTML spec.
dom::AutoEntryScript aes(global);
dom::AutoEntryScript aes(global, "XBL <constructor>/<destructor> invocation");
aes.TakeOwnershipOfErrorReporting();
JSContext* cx = aes.cx();

View File

@ -3563,7 +3563,7 @@ XULDocument::ExecuteScript(nsXULPrototypeScript *aScript)
// Execute the precompiled script with the given version.
// We're about to run script via JS::CloneAndExecuteScript, so we need an
// AutoEntryScript. This is Gecko specific and not in any spec.
AutoEntryScript aes(mScriptGlobalObject);
AutoEntryScript aes(mScriptGlobalObject, "precompiled XUL <script> element");
aes.TakeOwnershipOfErrorReporting();
JSContext* cx = aes.cx();
JS::Rooted<JSObject*> baseGlobal(cx, JS::CurrentGlobalOrNull(cx));

View File

@ -1385,7 +1385,7 @@ nsXULTemplateBuilder::InitHTMLTemplateRoot()
// We are going to run script via JS_SetProperty, so we need a script entry
// point, but as this is XUL related it does not appear in the HTML spec.
AutoEntryScript entryScript(innerWin, true);
AutoEntryScript entryScript(innerWin, "nsXULTemplateBuilder creation", true);
JSContext* jscontext = entryScript.cx();
JS::Rooted<JS::Value> v(jscontext);

View File

@ -96,6 +96,14 @@ public:
return mContext;
}
EGLSurface GetEGLSurface() {
return mSurface;
}
EGLDisplay GetEGLDisplay() {
return EGL_DISPLAY();
}
bool BindTex2DOffscreen(GLContext *aOffscreen);
void UnbindTex2DOffscreen(GLContext *aOffscreen);
void BindOffscreenFramebuffer();

View File

@ -230,17 +230,6 @@ GLContextEGL::GLContextEGL(
#ifdef DEBUG
printf_stderr("Initializing context %p surface %p on display %p\n", mContext, mSurface, EGL_DISPLAY());
#endif
#if defined(MOZ_WIDGET_GONK)
if (!mIsOffscreen) {
mHwc = HwcComposer2D::GetInstance();
MOZ_ASSERT(!mHwc->Initialized());
if (mHwc->Init(EGL_DISPLAY(), mSurface, this)) {
NS_WARNING("HWComposer initialization failed!");
mHwc = nullptr;
}
}
#endif
}
GLContextEGL::~GLContextEGL()
@ -466,16 +455,13 @@ GLContextEGL::SwapBuffers()
? mSurfaceOverride
: mSurface;
if (surface) {
#ifdef MOZ_WIDGET_GONK
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION < 17
if (!mIsOffscreen) {
if (mHwc) {
return mHwc->Render(EGL_DISPLAY(), surface);
} else {
return GetGonkDisplay()->SwapBuffers(EGL_DISPLAY(), surface);
}
} else
// eglSwapBuffers() is called by hwcomposer.
return true;
}
#endif
return sEGLLibrary.fSwapBuffers(EGL_DISPLAY(), surface);
return sEGLLibrary.fSwapBuffers(EGL_DISPLAY(), surface);
} else {
return false;
}

View File

@ -661,16 +661,12 @@ LayerManagerComposite::Render()
/** Our more efficient but less powerful alter ego, if one is available. */
nsRefPtr<Composer2D> composer2D;
composer2D = mCompositor->GetWidget()->GetComposer2D();
// We can't use composert2D if we have layer effects, so only get it
// when we don't have any effects.
if (!haveLayerEffects) {
composer2D = mCompositor->GetWidget()->GetComposer2D();
}
if (!mTarget &&
// We can't use composert2D if we have layer effects
if (!mTarget && !haveLayerEffects &&
gfxPrefs::Composer2DCompositionEnabled() &&
composer2D && composer2D->TryRender(mRoot, mGeometryChanged))
composer2D && composer2D->HasHwc() && composer2D->TryRenderWithHwc(mRoot, mGeometryChanged))
{
LayerScope::SetHWComposed();
if (mFPS) {
@ -684,7 +680,7 @@ LayerManagerComposite::Render()
mInvalidRegion.SetEmpty();
mLastFrameMissedHWC = false;
return;
} else if (!mTarget) {
} else if (!mTarget && !haveLayerEffects) {
mLastFrameMissedHWC = !!composer2D;
}
@ -775,6 +771,10 @@ LayerManagerComposite::Render()
mCompositor->SetFBAcquireFence(mRoot);
}
if (composer2D) {
composer2D->Render();
}
mCompositor->GetWidget()->PostRender(this);
RecordFrame();

View File

@ -52,7 +52,19 @@ public:
* Currently, when TryRender() returns true, the entire framebuffer
* must have been rendered.
*/
virtual bool TryRender(Layer* aRoot, bool aGeometryChanged) = 0;
virtual bool TryRenderWithHwc(Layer* aRoot, bool aGeometryChanged) = 0;
/**
* Return true if Composer2D does composition. Return false if Composer2D
* failed the composition.
*/
virtual bool Render() = 0;
/**
* Return true if Composer2D has a fast composition hardware.
* Return false if Composer2D does not have a fast composition hardware.
*/
virtual bool HasHwc() = 0;
};
} // namespace layers

View File

@ -131,13 +131,19 @@ CompositorOGL::CreateContext()
caps, requireCompatProfile);
}
if (!context)
if (!context) {
context = gl::GLContextProvider::CreateForWindow(mWidget);
}
if (!context) {
NS_WARNING("Failed to create CompositorOGL context");
}
#ifdef MOZ_WIDGET_GONK
mWidget->SetNativeData(NS_NATIVE_OPENGL_CONTEXT,
reinterpret_cast<uintptr_t>(context.get()));
#endif
return context.forget();
}

View File

@ -72,7 +72,8 @@ TestShellCommandParent::RunCallback(const nsString& aResponse)
// We're about to run script via JS_CallFunctionValue, so we need an
// AutoEntryScript. This is just for testing and not in any spec.
dom::AutoEntryScript aes(
xpc::NativeGlobal(js::GetGlobalForObjectCrossCompartment(&mCallback.toObject())));
xpc::NativeGlobal(js::GetGlobalForObjectCrossCompartment(&mCallback.toObject())),
"TestShellCommand");
JSContext* cx = aes.cx();
JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));

View File

@ -281,7 +281,8 @@ WrapperAnswer::RecvGet(const ObjectId& objId, const ObjectVariant& receiverVar,
const JSIDVariant& idVar, ReturnStatus* rs, JSVariant* result)
{
// We may run scripted getters.
AutoEntryScript aes(xpc::NativeGlobal(scopeForTargetObjects()));
AutoEntryScript aes(xpc::NativeGlobal(scopeForTargetObjects()),
"Cross-Process Object Wrapper 'get'");
aes.TakeOwnershipOfErrorReporting();
JSContext* cx = aes.cx();
@ -318,7 +319,8 @@ WrapperAnswer::RecvSet(const ObjectId& objId, const JSIDVariant& idVar, const JS
const JSVariant& receiverVar, ReturnStatus* rs)
{
// We may run scripted setters.
AutoEntryScript aes(xpc::NativeGlobal(scopeForTargetObjects()));
AutoEntryScript aes(xpc::NativeGlobal(scopeForTargetObjects()),
"Cross-Process Object Wrapper 'set'");
aes.TakeOwnershipOfErrorReporting();
JSContext* cx = aes.cx();
@ -379,7 +381,8 @@ WrapperAnswer::RecvCallOrConstruct(const ObjectId& objId,
JSVariant* result,
nsTArray<JSParam>* outparams)
{
AutoEntryScript aes(xpc::NativeGlobal(scopeForTargetObjects()));
AutoEntryScript aes(xpc::NativeGlobal(scopeForTargetObjects()),
"Cross-Process Object Wrapper call/construct");
aes.TakeOwnershipOfErrorReporting();
JSContext* cx = aes.cx();

View File

@ -80,11 +80,6 @@ GCTraceKindToAscii(JSGCTraceKind kind);
typedef void
(* JSTraceCallback)(JS::CallbackTracer* trc, void** thingp, JSGCTraceKind kind);
// Callback that JSTraceOp implementation can provide to return a string
// describing the reference traced with JS_CallTracer.
typedef void
(* JSTraceNamePrinter)(JSTracer* trc, char* buf, size_t bufsize);
enum WeakMapTraceKind {
DoNotTraceWeakMaps = 0,
TraceWeakMapValues = 1,
@ -94,80 +89,12 @@ enum WeakMapTraceKind {
class JS_PUBLIC_API(JSTracer)
{
public:
// Set debugging information about a reference to a traceable thing to prepare
// for the following call to JS_CallTracer.
//
// When printer is null, arg must be const char * or char * C string naming
// the reference and index must be either (size_t)-1 indicating that the name
// alone describes the reference or it must be an index into some array vector
// that stores the reference.
//
// When printer callback is not null, the arg and index arguments are
// available to the callback as debugPrintArg_ and debugPrintIndex_ fields
// of JSTracer.
//
// The storage for name or callback's arguments needs to live only until
// the following call to JS_CallTracer returns.
void setTracingDetails(JSTraceNamePrinter printer, const void* arg, size_t index) {
debugPrinter_ = printer;
debugPrintArg_ = arg;
debugPrintIndex_ = index;
}
void setTracingIndex(const char* name, size_t index) {
setTracingDetails(nullptr, (void*)name, index);
}
void setTracingName(const char* name) {
setTracingDetails(nullptr, (void*)name, InvalidIndex);
}
// Remove the currently set tracing details.
void clearTracingDetails() {
debugPrinter_ = nullptr;
debugPrintArg_ = nullptr;
}
const static size_t InvalidIndex = size_t(-1);
// Return true if tracing details are currently set.
bool hasTracingDetails() const;
// Get the string set with the most recent call to setTracingName or return
// fallback if a name printer function has been installed.
const char* tracingName(const char* fallback) const;
// Build a description of this edge in the heap graph. This call may invoke
// the debug printer, which may inspect arbitrary areas of the heap.
const char* getTracingEdgeName(char* buffer, size_t bufferSize);
// Access the currently active tracing details.
JSTraceNamePrinter debugPrinter() const;
const void* debugPrintArg() const;
size_t debugPrintIndex() const;
// Return the runtime set on the tracer.
JSRuntime* runtime() const { return runtime_; }
// Return the weak map tracing behavior set on this tracer.
WeakMapTraceKind eagerlyTraceWeakMaps() const { return eagerlyTraceWeakMaps_; }
#ifdef JS_GC_ZEAL
// Sets the "real" location for a marked reference, when passing the address
// directly is not feasable. This address is used for matching against the
// store buffer when verifying the correctness of the entrees there.
//
// This is currently complicated by our need to nest calls for Values
// stored as keys in hash tables.
void setTracingLocation(void* location);
void unsetTracingLocation();
void** tracingLocation(void** thingp);
#else
void setTracingLocation(void* location) {}
void unsetTracingLocation() {}
void** tracingLocation(void** thingp) { return nullptr; }
#endif
// An intermediate state on the road from C to C++ style dispatch.
enum TracerKindTag {
MarkingTracer,
@ -184,23 +111,24 @@ class JS_PUBLIC_API(JSTracer)
private:
JSRuntime* runtime_;
TracerKindTag tag;
JSTraceNamePrinter debugPrinter_;
const void* debugPrintArg_;
size_t debugPrintIndex_;
WeakMapTraceKind eagerlyTraceWeakMaps_;
#ifdef JS_GC_ZEAL
void* realLocation_;
#endif
};
namespace JS {
class AutoTracingName;
class AutoTracingIndex;
class AutoTracingCallback;
class AutoOriginalTraceLocation;
class JS_PUBLIC_API(CallbackTracer) : public JSTracer
{
public:
CallbackTracer(JSRuntime* rt, JSTraceCallback traceCallback,
WeakMapTraceKind weakTraceKind = TraceWeakMapValues)
: JSTracer(rt, JSTracer::CallbackTracer, weakTraceKind), callback(traceCallback)
: JSTracer(rt, JSTracer::CallbackTracer, weakTraceKind), callback(traceCallback),
contextName_(nullptr), contextIndex_(InvalidIndex), contextFunctor_(nullptr),
contextRealLocation_(nullptr)
{}
// Update the trace callback.
@ -216,10 +144,173 @@ class JS_PUBLIC_API(CallbackTracer) : public JSTracer
callback(this, thing, kind);
}
// Access to the tracing context:
// When tracing with a JS::CallbackTracer, we invoke the callback with the
// edge location and the type of target. This is useful for operating on
// the edge in the abstract or on the target thing, satisfying most common
// use cases. However, some tracers need additional detail about the
// specific edge that is being traced in order to be useful. Unfortunately,
// the raw pointer to the edge that we provide is not enough information to
// infer much of anything useful about that edge.
//
// In order to better support use cases that care in particular about edges
// -- as opposed to the target thing -- tracing implementations are
// responsible for providing extra context information about each edge they
// trace, as it is traced. This contains, at a minimum, an edge name and,
// when tracing an array, the index. Further specialization can be achived
// (with some complexity), by associating a functor with the tracer so
// that, when requested, the user can generate totally custom edge
// descriptions.
// Returns the current edge's name. It is only valid to call this when
// inside the trace callback, however, the edge name will always be set.
const char* contextName() const { MOZ_ASSERT(contextName_); return contextName_; }
// Returns the current edge's index, if marked as part of an array of edges.
// This must be called only inside the trace callback. When not tracing an
// array, the value will be InvalidIndex.
const static size_t InvalidIndex = size_t(-1);
size_t contextIndex() const { return contextIndex_; }
// Build a description of this edge in the heap graph. This call may invoke
// the context functor, if set, which may inspect arbitrary areas of the
// heap. On the other hand, the description provided by this method may be
// substantially more accurate and useful than those provided by only the
// contextName and contextIndex.
const char* getTracingEdgeName(char* buffer, size_t bufferSize);
// The trace implementation may associate a callback with one or more edges
// using AutoTracingDetails. This functor is called by getTracingEdgeName
// and is responsible for providing a textual representation of the
// currently being traced edge. The callback has access to the full heap,
// including the currently set tracing context.
class ContextFunctor {
public:
virtual void operator()(CallbackTracer* trc, char* buf, size_t bufsize) = 0;
};
// Return the original heap tracing location if the raw thingp reference
// has been moved. This is generally only useful for heap analyses that
// need to build an accurate model of the heap, and thus is only accurate
// when built with JS_GC_ZEAL.
void*const* tracingLocation(void** thingp) {
return contextRealLocation_ ? contextRealLocation_ : thingp;
}
private:
// Exposed publicly for several callers that need to check if the tracer
// calling them is of the right type.
JSTraceCallback callback;
friend class AutoTracingName;
const char* contextName_;
friend class AutoTracingIndex;
size_t contextIndex_;
friend class AutoTracingDetails;
ContextFunctor* contextFunctor_;
friend class AutoOriginalTraceLocation;
void*const* contextRealLocation_;
};
// Set the name portion of the tracer's context for the current edge.
class AutoTracingName
{
CallbackTracer* trc_;
const char *prior_;
public:
AutoTracingName(CallbackTracer* trc, const char* name) : trc_(trc), prior_(trc->contextName_) {
MOZ_ASSERT(name);
trc->contextName_ = name;
}
~AutoTracingName() {
MOZ_ASSERT(trc_->contextName_);
trc_->contextName_ = prior_;
}
};
// Set the index portion of the tracer's context for the current range.
class AutoTracingIndex
{
CallbackTracer* trc_;
public:
explicit AutoTracingIndex(JSTracer* trc, size_t initial = 0) : trc_(nullptr) {
if (trc->isCallbackTracer()) {
trc_ = trc->asCallbackTracer();
MOZ_ASSERT(trc_->contextIndex_ == CallbackTracer::InvalidIndex);
trc_->contextIndex_ = initial;
}
}
~AutoTracingIndex() {
if (trc_) {
MOZ_ASSERT(trc_->contextIndex_ != CallbackTracer::InvalidIndex);
trc_->contextIndex_ = CallbackTracer::InvalidIndex;
}
}
void operator++() {
if (trc_) {
MOZ_ASSERT(trc_->contextIndex_ != CallbackTracer::InvalidIndex);
++trc_->contextIndex_;
}
}
};
// Set a context callback for the trace callback to use, if it needs a detailed
// edge description.
class AutoTracingDetails
{
CallbackTracer* trc_;
public:
AutoTracingDetails(JSTracer* trc, CallbackTracer::ContextFunctor& func) : trc_(nullptr) {
if (trc->isCallbackTracer()) {
trc_ = trc->asCallbackTracer();
MOZ_ASSERT(trc_->contextFunctor_ == nullptr);
trc_->contextFunctor_ = &func;
}
}
~AutoTracingDetails() {
if (trc_) {
MOZ_ASSERT(trc_->contextFunctor_);
trc_->contextFunctor_ = nullptr;
}
}
};
// Some dynamic analyses depend on knowing the edge source location as it
// exists in the object graph. When marking some types of things, e.g. Value
// edges, it is necessary to copy into a temporary on the stack. This class
// records the original location if we need to copy the tracee, so that the
// relevant analyses can continue to operate correctly.
class AutoOriginalTraceLocation
{
#ifdef JS_GC_ZEAL
CallbackTracer *trc_;
public:
template <typename T>
AutoOriginalTraceLocation(JSTracer* trc, T*const* realLocation) : trc_(nullptr) {
if (trc->isCallbackTracer() && trc->asCallbackTracer()->contextRealLocation_ == nullptr) {
trc_ = trc->asCallbackTracer();
trc_->contextRealLocation_ = reinterpret_cast<void*const*>(realLocation);
}
}
~AutoOriginalTraceLocation() {
if (trc_) {
MOZ_ASSERT(trc_->contextRealLocation_);
trc_->contextRealLocation_ = nullptr;
}
}
#else
public:
template <typename T>
AutoOriginalTraceLocation(JSTracer* trc, T*const* realLocation) {}
#endif
};
} // namespace JS
@ -284,7 +375,7 @@ inline void
JS_CallHashSetObjectTracer(JSTracer* trc, HashSetEnum& e, JSObject* const& key, const char* name)
{
JSObject* updated = key;
trc->setTracingLocation(reinterpret_cast<void*>(&const_cast<JSObject*&>(key)));
JS::AutoOriginalTraceLocation reloc(trc, &key);
JS_CallUnbarrieredObjectTracer(trc, &updated, name);
if (updated != key)
e.rekeyFront(updated);

View File

@ -2043,6 +2043,9 @@ class MOZ_STACK_CLASS ModuleCompiler
case JS::AsmJSCache_QuotaExceeded:
cacheString = "not enough temporary storage quota to store in cache";
break;
case JS::AsmJSCache_StorageInitFailure:
cacheString = "storage initialization failed (consider filing a bug)";
break;
case JS::AsmJSCache_Disabled_Internal:
cacheString = "caching disabled by internal configuration (consider filing a bug)";
break;

View File

@ -839,7 +839,7 @@ HashableValue
HashableValue::mark(JSTracer* trc) const
{
HashableValue hv(*this);
trc->setTracingLocation((void*)this);
JS::AutoOriginalTraceLocation reloc(trc, (void**)this);
TraceEdge(trc, &hv.value, "key");
return hv;
}

View File

@ -42,36 +42,6 @@ void * const js::NullPtr::constNullValue = nullptr;
JS_PUBLIC_DATA(void * const) JS::NullPtr::constNullValue = nullptr;
/*
* There are two mostly separate mark paths. The first is a fast path used
* internally in the GC. The second is a slow path used for root marking and
* for API consumers like the cycle collector or Class::trace implementations.
*
* The fast path uses explicit stacks. The basic marking process during a GC is
* that all roots are pushed on to a mark stack, and then each item on the
* stack is scanned (possibly pushing more stuff) until the stack is empty.
*
* PushMarkStack pushes a GC thing onto the mark stack. In some cases (shapes
* or strings) it eagerly marks the object rather than pushing it. Popping and
* scanning is done by the processMarkStackTop method. For efficiency reasons
* like tail recursion elimination that method also implements the scanning of
* objects. For other GC things it uses helper methods.
*
* Most of the marking code outside Marking.cpp uses functions like MarkObject,
* MarkString, etc. These functions check if an object is in the compartment
* currently being GCed. If it is, they call PushMarkStack. Roots are pushed
* this way as well as pointers traversed inside trace hooks (for things like
* PropertyIteratorObjects). It is always valid to call a MarkX function
* instead of PushMarkStack, although it may be slower.
*
* The MarkX functions also handle non-GC object traversal. In this case, they
* call a callback for each object visited. This is a recursive process; the
* mark stacks are not involved. These callbacks may ask for the outgoing
* pointers to be visited. Eventually, this leads to the MarkChildren functions
* being called. These functions duplicate much of the functionality of
* scanning functions, but they don't push onto an explicit stack.
*/
static inline void
PushMarkStack(GCMarker* gcmarker, JSObject* thing) {
gcmarker->traverse(thing);
@ -106,14 +76,6 @@ PushMarkStack(GCMarker* gcmarker, JSString* thing);
static inline void
PushMarkStack(GCMarker* gcmarker, JS::Symbol* thing);
namespace js {
namespace gc {
static void MarkChildren(JSTracer* trc, ObjectGroup* group);
} /* namespace gc */
} /* namespace js */
/*** Object Marking ***/
#if defined(DEBUG)
@ -272,17 +234,6 @@ CheckMarkedThing<jsid>(JSTracer* trc, jsid id)
trc->runtime()->gc.state() == NO_INCREMENTAL || \
trc->runtime()->gc.state() == MARK_ROOTS);
#define FOR_EACH_GC_LAYOUT(D) \
D(Object, JSObject) \
D(String, JSString) \
D(Symbol, JS::Symbol) \
D(Script, JSScript) \
D(Shape, js::Shape) \
D(BaseShape, js::BaseShape) \
D(JitCode, js::jit::JitCode) \
D(LazyScript, js::LazyScript) \
D(ObjectGroup, js::ObjectGroup)
// A C++ version of JSGCTraceKind
enum class TraceKind {
#define NAMES(name, _) name,
@ -368,8 +319,8 @@ ConvertToBase(T* thingp)
return reinterpret_cast<typename PtrBaseGCType<T>::type*>(thingp);
}
template <typename T> void DispatchToTracer(JSTracer* trc, T* thingp, const char* name, size_t i);
template <typename T> void DoTracing(JS::CallbackTracer* trc, T* thingp, const char* name, size_t i);
template <typename T> void DispatchToTracer(JSTracer* trc, T* thingp, const char* name);
template <typename T> void DoCallback(JS::CallbackTracer* trc, T* thingp, const char* name);
template <typename T> void DoMarking(GCMarker* gcmarker, T thing);
static bool ShouldMarkCrossCompartment(JSTracer* trc, JSObject* src, Cell* cell);
static bool ShouldMarkCrossCompartment(JSTracer* trc, JSObject* src, Value val);
@ -378,14 +329,14 @@ template <typename T>
void
js::TraceEdge(JSTracer* trc, BarrieredBase<T>* thingp, const char* name)
{
DispatchToTracer(trc, ConvertToBase(thingp->unsafeGet()), name, JSTracer::InvalidIndex);
DispatchToTracer(trc, ConvertToBase(thingp->unsafeGet()), name);
}
template <typename T>
void
js::TraceManuallyBarrieredEdge(JSTracer* trc, T* thingp, const char* name)
{
DispatchToTracer(trc, ConvertToBase(thingp), name, JSTracer::InvalidIndex);
DispatchToTracer(trc, ConvertToBase(thingp), name);
}
template <typename T>
@ -393,16 +344,18 @@ void
js::TraceRoot(JSTracer* trc, T* thingp, const char* name)
{
JS_ROOT_MARKING_ASSERT(trc);
DispatchToTracer(trc, ConvertToBase(thingp), name, JSTracer::InvalidIndex);
DispatchToTracer(trc, ConvertToBase(thingp), name);
}
template <typename T>
void
js::TraceRange(JSTracer* trc, size_t len, BarrieredBase<T>* vec, const char* name)
{
JS::AutoTracingIndex index(trc);
for (auto i : MakeRange(len)) {
if (InternalGCMethods<T>::isMarkable(vec[i].get()))
DispatchToTracer(trc, ConvertToBase(vec[i].unsafeGet()), name, i);
DispatchToTracer(trc, ConvertToBase(vec[i].unsafeGet()), name);
++index;
}
}
@ -411,9 +364,11 @@ void
js::TraceRootRange(JSTracer* trc, size_t len, T* vec, const char* name)
{
JS_ROOT_MARKING_ASSERT(trc);
JS::AutoTracingIndex index(trc);
for (auto i : MakeRange(len)) {
if (InternalGCMethods<T>::isMarkable(vec[i]))
DispatchToTracer(trc, ConvertToBase(&vec[i]), name, i);
DispatchToTracer(trc, ConvertToBase(&vec[i]), name);
++index;
}
}
@ -433,7 +388,7 @@ js::TraceManuallyBarrieredCrossCompartmentEdge(JSTracer* trc, JSObject* src, T*
const char* name)
{
if (ShouldMarkCrossCompartment(trc, src, *dst))
DispatchToTracer(trc, dst, name, -1);
DispatchToTracer(trc, dst, name);
}
template void js::TraceManuallyBarrieredCrossCompartmentEdge<JSObject*>(JSTracer*, JSObject*,
JSObject**, const char*);
@ -445,7 +400,7 @@ void
js::TraceCrossCompartmentEdge(JSTracer* trc, JSObject* src, BarrieredBase<T>* dst, const char* name)
{
if (ShouldMarkCrossCompartment(trc, src, dst->get()))
DispatchToTracer(trc, dst->unsafeGet(), name, -1);
DispatchToTracer(trc, dst->unsafeGet(), name);
}
template void js::TraceCrossCompartmentEdge<Value>(JSTracer*, JSObject*, BarrieredBase<Value>*,
const char*);
@ -455,7 +410,7 @@ template void js::TraceCrossCompartmentEdge<Value>(JSTracer*, JSObject*, Barrier
// a sufficiently smart C++ compiler may be able to devirtualize some paths.
template <typename T>
void
DispatchToTracer(JSTracer* trc, T* thingp, const char* name, size_t i)
DispatchToTracer(JSTracer* trc, T* thingp, const char* name)
{
#define IS_SAME_TYPE_OR(name, type) mozilla::IsSame<type*, T>::value ||
static_assert(
@ -468,7 +423,7 @@ DispatchToTracer(JSTracer* trc, T* thingp, const char* name, size_t i)
if (trc->isMarkingTracer())
return DoMarking(static_cast<GCMarker*>(trc), *thingp);
return DoTracing(static_cast<JS::CallbackTracer*>(trc), thingp, name, i);
return DoCallback(trc->asCallbackTracer(), thingp, name);
}
template <typename T>
@ -542,8 +497,6 @@ DoMarking<Value>(GCMarker* gcmarker, Value val)
DoMarking(gcmarker, &val.toObject());
else if (val.isSymbol())
DoMarking(gcmarker, val.toSymbol());
else
gcmarker->clearTracingDetails();
}
template <>
@ -554,110 +507,6 @@ DoMarking<jsid>(GCMarker* gcmarker, jsid id)
DoMarking(gcmarker, JSID_TO_STRING(id));
else if (JSID_IS_SYMBOL(id))
DoMarking(gcmarker, JSID_TO_SYMBOL(id));
else
gcmarker->clearTracingDetails();
}
template <typename T>
void
DoTracing(JS::CallbackTracer* trc, T* thingp, const char* name, size_t i)
{
JSGCTraceKind kind = MapTypeToTraceKind<typename mozilla::RemovePointer<T>::Type>::kind;
trc->setTracingIndex(name, i);
trc->invoke((void**)thingp, kind);
trc->unsetTracingLocation();
}
template <>
void
DoTracing<Value>(JS::CallbackTracer* trc, Value* vp, const char* name, size_t i)
{
if (vp->isObject()) {
JSObject* prior = &vp->toObject();
JSObject* obj = prior;
DoTracing(trc, &obj, name, i);
if (obj != prior)
vp->setObjectOrNull(obj);
} else if (vp->isString()) {
JSString* prior = vp->toString();
JSString* str = prior;
DoTracing(trc, &str, name, i);
if (str != prior)
vp->setString(str);
} else if (vp->isSymbol()) {
JS::Symbol* prior = vp->toSymbol();
JS::Symbol* sym = prior;
DoTracing(trc, &sym, name, i);
if (sym != prior)
vp->setSymbol(sym);
} else {
/* Unset realLocation manually if we do not call MarkInternal. */
trc->unsetTracingLocation();
}
}
template <>
void
DoTracing<jsid>(JS::CallbackTracer* trc, jsid* idp, const char* name, size_t i)
{
if (JSID_IS_STRING(*idp)) {
JSString* prior = JSID_TO_STRING(*idp);
JSString* str = prior;
DoTracing(trc, &str, name, i);
if (str != prior)
*idp = NON_INTEGER_ATOM_TO_JSID(reinterpret_cast<JSAtom*>(str));
} else if (JSID_IS_SYMBOL(*idp)) {
JS::Symbol* prior = JSID_TO_SYMBOL(*idp);
JS::Symbol* sym = prior;
DoTracing(trc, &sym, name, i);
if (sym != prior)
*idp = SYMBOL_TO_JSID(sym);
} else {
/* Unset realLocation manually if we do not call MarkInternal. */
trc->unsetTracingLocation();
}
}
template<typename T>
static void
MarkInternal(JSTracer* trc, T** thingp)
{
T* thing = *thingp;
CheckMarkedThing(trc, thing);
if (trc->isMarkingTracer()) {
/*
* We may mark a Nursery thing outside the context of the
* MinorCollectionTracer because of a pre-barrier. The pre-barrier is
* not needed in this case because we perform a minor collection before
* each incremental slice.
*/
if (IsInsideNursery(thing))
return;
/*
* Don't mark permanent atoms, as they may be associated with another
* runtime. Note that PushMarkStack() also checks this, but the tests
* and maybeAlive write below should only be done on the main thread.
*/
if (ThingIsPermanentAtomOrWellKnownSymbol(thing))
return;
/*
* Don't mark things outside a compartment if we are in a
* per-compartment GC.
*/
if (!thing->zone()->isGCMarking())
return;
PushMarkStack(AsGCMarker(trc), thing);
SetMaybeAliveFlag(thing);
} else {
trc->asCallbackTracer()->invoke((void**)thingp, MapTypeToTraceKind<T>::kind);
trc->unsetTracingLocation();
}
trc->clearTracingDetails();
}
namespace js {
@ -666,24 +515,17 @@ namespace gc {
void
MarkPermanentAtom(JSTracer* trc, JSAtom* atom, const char* name)
{
trc->setTracingName(name);
MOZ_ASSERT(atom->isPermanent());
// We have to mark permanent atoms through a special method because the
// default DoMarking implementation automatically skips them. Fortunatly,
// atoms cannot refer to other GC things, so they do not need to go through
// the mark stack and may simply be marked directly.
CheckMarkedThing(trc, atom);
if (trc->isMarkingTracer()) {
// Atoms do not refer to other GC things so don't need to go on the mark stack.
// Additionally, PushMarkStack will ignore permanent atoms.
if (trc->isMarkingTracer())
atom->markIfUnmarked();
} else {
void* thing = atom;
trc->asCallbackTracer()->invoke(&thing, JSTRACE_STRING);
MOZ_ASSERT(thing == atom);
trc->unsetTracingLocation();
}
trc->clearTracingDetails();
else
DoCallback(trc->asCallbackTracer(), reinterpret_cast<JSString**>(&atom), name);
}
void
@ -691,23 +533,17 @@ MarkWellKnownSymbol(JSTracer* trc, JS::Symbol* sym)
{
if (!sym)
return;
trc->setTracingName("wellKnownSymbols");
MOZ_ASSERT(sym->isWellKnownSymbol());
// As per permanent atoms, the normal marking path is not adequate.
CheckMarkedThing(trc, sym);
if (trc->isMarkingTracer()) {
// Permanent atoms are marked before well-known symbols.
MOZ_ASSERT(sym->description()->isMarked());
sym->markIfUnmarked();
} else {
void* thing = sym;
trc->asCallbackTracer()->invoke(&thing, JSTRACE_SYMBOL);
MOZ_ASSERT(thing == sym);
trc->unsetTracingLocation();
DoCallback(trc->asCallbackTracer(), &sym, "wellKnownSymbol");
}
trc->clearTracingDetails();
}
template <typename T>
@ -974,38 +810,6 @@ js::gc::TraceManuallyBarrieredGenericPointerEdge(JSTracer* trc, Cell** thingp, c
CallTyped(f, (*thingp)->getTraceKind(), trc, thingp, name);
}
/*** Value Marking ***/
static inline void
MarkValueInternal(JSTracer* trc, Value* v)
{
if (v->isMarkable()) {
MOZ_ASSERT(v->toGCThing());
void* thing = v->toGCThing();
trc->setTracingLocation((void*)v);
if (v->isString()) {
JSString* str = static_cast<JSString*>(thing);
MarkInternal(trc, &str);
if (str != thing)
v->setString(str);
} else if (v->isObject()) {
JSObject* obj = static_cast<JSObject*>(thing);
MarkInternal(trc, &obj);
if (obj != thing)
v->setObjectOrNull(obj);
} else {
MOZ_ASSERT(v->isSymbol());
JS::Symbol* sym = static_cast<JS::Symbol*>(thing);
MarkInternal(trc, &sym);
if (sym != thing)
v->setSymbol(sym);
}
} else {
/* Unset realLocation manually if we do not call MarkInternal. */
trc->unsetTracingLocation();
}
}
/*** Type Marking ***/
void
@ -1018,14 +822,13 @@ TypeSet::MarkTypeRoot(JSTracer* trc, TypeSet::Type* v, const char* name)
void
TypeSet::MarkTypeUnbarriered(JSTracer* trc, TypeSet::Type* v, const char* name)
{
trc->setTracingName(name);
if (v->isSingletonUnchecked()) {
JSObject* obj = v->singleton();
MarkInternal(trc, &obj);
DispatchToTracer(trc, &obj, name);
*v = TypeSet::ObjectType(obj);
} else if (v->isGroupUnchecked()) {
ObjectGroup* group = v->group();
MarkInternal(trc, &group);
DispatchToTracer(trc, &group, name);
*v = TypeSet::ObjectType(group);
}
}
@ -1035,10 +838,12 @@ TypeSet::MarkTypeUnbarriered(JSTracer* trc, TypeSet::Type* v, const char* name)
void
gc::MarkObjectSlots(JSTracer* trc, NativeObject* obj, uint32_t start, uint32_t nslots)
{
MOZ_ASSERT(obj->isNative());
JS::AutoTracingIndex index(trc, start);
for (uint32_t i = start; i < (start + nslots); ++i) {
trc->setTracingDetails(GetObjectSlotName, obj, i);
MarkValueInternal(trc, obj->getSlotRef(i).unsafeGet());
HeapSlot& slot = obj->getSlotRef(i);
if (InternalGCMethods<Value>::isMarkable(slot))
DispatchToTracer(trc, slot.unsafeGet(), "object slot");
++index;
}
}
@ -1143,7 +948,7 @@ static inline void
ScanBaseShape(GCMarker* gcmarker, BaseShape* base);
void
BaseShape::markChildren(JSTracer* trc)
BaseShape::traceChildren(JSTracer* trc)
{
if (isOwned())
TraceEdge(trc, &unowned_, "base");
@ -1413,40 +1218,40 @@ ScanObjectGroup(GCMarker* gcmarker, ObjectGroup* group)
gcmarker->traverse(fun);
}
static void
gc::MarkChildren(JSTracer* trc, ObjectGroup* group)
void
js::ObjectGroup::traceChildren(JSTracer* trc)
{
unsigned count = group->getPropertyCount();
unsigned count = getPropertyCount();
for (unsigned i = 0; i < count; i++) {
if (ObjectGroup::Property* prop = group->getProperty(i))
if (ObjectGroup::Property* prop = getProperty(i))
TraceEdge(trc, &prop->id, "group_property");
}
if (group->proto().isObject())
TraceEdge(trc, &group->protoRaw(), "group_proto");
if (proto().isObject())
TraceEdge(trc, &protoRaw(), "group_proto");
if (group->newScript())
group->newScript()->trace(trc);
if (newScript())
newScript()->trace(trc);
if (group->maybePreliminaryObjects())
group->maybePreliminaryObjects()->trace(trc);
if (maybePreliminaryObjects())
maybePreliminaryObjects()->trace(trc);
if (group->maybeUnboxedLayout())
group->unboxedLayout().trace(trc);
if (maybeUnboxedLayout())
unboxedLayout().trace(trc);
if (ObjectGroup* unboxedGroup = group->maybeOriginalUnboxedGroup()) {
if (ObjectGroup* unboxedGroup = maybeOriginalUnboxedGroup()) {
TraceManuallyBarrieredEdge(trc, &unboxedGroup, "group_original_unboxed_group");
group->setOriginalUnboxedGroup(unboxedGroup);
setOriginalUnboxedGroup(unboxedGroup);
}
if (JSObject* descr = group->maybeTypeDescr()) {
if (JSObject* descr = maybeTypeDescr()) {
TraceManuallyBarrieredEdge(trc, &descr, "group_type_descr");
group->setTypeDescr(&descr->as<TypeDescr>());
setTypeDescr(&descr->as<TypeDescr>());
}
if (JSObject* fun = group->maybeInterpretedFunction()) {
if (JSObject* fun = maybeInterpretedFunction()) {
TraceManuallyBarrieredEdge(trc, &fun, "group_function");
group->setInterpretedFunction(&fun->as<JSFunction>());
setInterpretedFunction(&fun->as<JSFunction>());
}
}
@ -1625,7 +1430,7 @@ GCMarker::processMarkStackOther(uintptr_t tag, uintptr_t addr)
else
repush(obj);
} else if (tag == JitCodeTag) {
reinterpret_cast<jit::JitCode*>(addr)->trace(this);
reinterpret_cast<jit::JitCode*>(addr)->traceChildren(this);
}
}
@ -1888,54 +1693,24 @@ GCMarker::drainMarkStack(SliceBudget& budget)
template <typename T>
void
GCMarker::markChildren(T* thing)
GCMarker::dispatchToTraceChildren(T* thing)
{
thing->markChildren(this);
thing->traceChildren(this);
}
struct TraceChildrenFunctor {
template <typename T>
void operator()(JSTracer* trc, void* thing) {
static_cast<T*>(thing)->traceChildren(trc);
}
};
void
js::TraceChildren(JSTracer* trc, void* thing, JSGCTraceKind kind)
{
switch (kind) {
case JSTRACE_OBJECT:
static_cast<JSObject*>(thing)->markChildren(trc);
break;
case JSTRACE_SCRIPT:
static_cast<JSScript*>(thing)->markChildren(trc);
break;
case JSTRACE_STRING:
static_cast<JSString*>(thing)->markChildren(trc);
break;
case JSTRACE_SYMBOL:
static_cast<JS::Symbol*>(thing)->markChildren(trc);
break;
case JSTRACE_BASE_SHAPE:
static_cast<BaseShape*>(thing)->markChildren(trc);
break;
case JSTRACE_JITCODE:
static_cast<jit::JitCode*>(thing)->trace(trc);
break;
case JSTRACE_LAZY_SCRIPT:
static_cast<LazyScript*>(thing)->markChildren(trc);
break;
case JSTRACE_SHAPE:
static_cast<Shape*>(thing)->markChildren(trc);
break;
case JSTRACE_OBJECT_GROUP:
MarkChildren(trc, (ObjectGroup*)thing);
break;
default:
MOZ_CRASH("Invalid trace kind in TraceChildren.");
}
MOZ_ASSERT(thing);
TraceChildrenFunctor f;
CallTyped(f, kind, trc, thing);
}
#ifdef DEBUG

View File

@ -77,14 +77,6 @@ IsNullTaggedPointer(void* p)
/*** Externally Typed Marking ***/
/*
* Note: this must only be called by the GC and only when we are tracing through
* MarkRoots. It is explicitly for ConservativeStackMarking and should go away
* after we transition to exact rooting.
*/
void
MarkKind(JSTracer* trc, void** thingp, JSGCTraceKind kind);
void
TraceGenericPointerRoot(JSTracer* trc, Cell** thingp, const char* name);
@ -167,7 +159,7 @@ class HashKeyRef : public BufferableRef
typename Map::Ptr p = map->lookup(key);
if (!p)
return;
trc->setTracingLocation(&*p);
JS::AutoOriginalTraceLocation reloc(trc, (void**)&*p);
TraceManuallyBarrieredEdge(trc, &key, "HashKeyRef");
map->rekeyIfMoved(prior, key);
}

View File

@ -221,8 +221,8 @@ AutoGCRooter::trace(JSTracer* trc)
AutoObjectObjectHashMap::HashMapImpl& map = static_cast<AutoObjectObjectHashMap*>(this)->map;
for (AutoObjectObjectHashMap::Enum e(map); !e.empty(); e.popFront()) {
TraceRoot(trc, &e.front().value(), "AutoObjectObjectHashMap value");
trc->setTracingLocation((void*)&e.front().key());
JSObject* key = e.front().key();
JS::AutoOriginalTraceLocation reloc(trc, &e.front().key());
TraceRoot(trc, &key, "AutoObjectObjectHashMap key");
if (key != e.front().key())
e.rekeyFront(key);
@ -583,21 +583,14 @@ struct SetMaybeAliveFunctor {
};
void
BufferGrayRootsTracer::appendGrayRoot(Cell* thing, JSGCTraceKind kind)
BufferGrayRootsTracer::appendGrayRoot(TenuredCell* thing, JSGCTraceKind kind)
{
MOZ_ASSERT(runtime()->isHeapBusy());
if (bufferingGrayRootsFailed)
return;
GrayRoot root(thing, kind);
#ifdef DEBUG
root.debugPrinter = debugPrinter();
root.debugPrintArg = debugPrintArg();
root.debugPrintIndex = debugPrintIndex();
#endif
Zone* zone = TenuredCell::fromPointer(thing)->zone();
Zone* zone = thing->zone();
if (zone->isCollecting()) {
// See the comment on SetMaybeAliveFlag to see why we only do this for
// objects and scripts. We rely on gray root buffering for this to work,
@ -605,7 +598,7 @@ BufferGrayRootsTracer::appendGrayRoot(Cell* thing, JSGCTraceKind kind)
// incremental GCs (when we do gray root buffering).
CallTyped(SetMaybeAliveFunctor(), kind, thing);
if (!zone->gcGrayRoots.append(root))
if (!zone->gcGrayRoots.append(thing))
bufferingGrayRootsFailed = true;
}
}
@ -616,13 +609,8 @@ GCRuntime::markBufferedGrayRoots(JS::Zone* zone)
MOZ_ASSERT(grayBufferState == GrayBufferState::Okay);
MOZ_ASSERT(zone->isGCMarkingGray() || zone->isGCCompacting());
for (GrayRoot* elem = zone->gcGrayRoots.begin(); elem != zone->gcGrayRoots.end(); elem++) {
#ifdef DEBUG
marker.setTracingDetails(elem->debugPrinter, elem->debugPrintArg, elem->debugPrintIndex);
#endif
TraceManuallyBarrieredGenericPointerEdge(&marker, reinterpret_cast<Cell**>(&elem->thing),
"buffered gray root");
}
for (auto cell : zone->gcGrayRoots)
TraceManuallyBarrieredGenericPointerEdge(&marker, &cell, "buffered gray root");
}
void

View File

@ -55,11 +55,11 @@ StoreBuffer::WholeCellEdges::mark(JSTracer* trc) const
JSObject* object = static_cast<JSObject*>(edge);
if (object->is<ArgumentsObject>())
ArgumentsObject::trace(trc, object);
object->markChildren(trc);
object->traceChildren(trc);
return;
}
MOZ_ASSERT(kind == JSTRACE_JITCODE);
static_cast<jit::JitCode*>(edge)->trace(trc);
static_cast<jit::JitCode*>(edge)->traceChildren(trc);
}
void

View File

@ -29,6 +29,63 @@ using namespace js;
using namespace js::gc;
using mozilla::DebugOnly;
template <typename T>
void
DoCallback(JS::CallbackTracer* trc, T* thingp, const char* name)
{
JSGCTraceKind kind = MapTypeToTraceKind<typename mozilla::RemovePointer<T>::Type>::kind;
JS::AutoTracingName ctx(trc, name);
trc->invoke((void**)thingp, kind);
}
#define INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS(name, type) \
template void DoCallback<type*>(JS::CallbackTracer*, type**, const char*);
FOR_EACH_GC_LAYOUT(INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS);
#undef INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS
template <>
void
DoCallback<Value>(JS::CallbackTracer* trc, Value* vp, const char* name)
{
if (vp->isObject()) {
JSObject* prior = &vp->toObject();
JSObject* obj = prior;
DoCallback(trc, &obj, name);
if (obj != prior)
vp->setObjectOrNull(obj);
} else if (vp->isString()) {
JSString* prior = vp->toString();
JSString* str = prior;
DoCallback(trc, &str, name);
if (str != prior)
vp->setString(str);
} else if (vp->isSymbol()) {
JS::Symbol* prior = vp->toSymbol();
JS::Symbol* sym = prior;
DoCallback(trc, &sym, name);
if (sym != prior)
vp->setSymbol(sym);
}
}
template <>
void
DoCallback<jsid>(JS::CallbackTracer* trc, jsid* idp, const char* name)
{
if (JSID_IS_STRING(*idp)) {
JSString* prior = JSID_TO_STRING(*idp);
JSString* str = prior;
DoCallback(trc, &str, name);
if (str != prior)
*idp = NON_INTEGER_ATOM_TO_JSID(reinterpret_cast<JSAtom*>(str));
} else if (JSID_IS_SYMBOL(*idp)) {
JS::Symbol* prior = JSID_TO_SYMBOL(*idp);
JS::Symbol* sym = prior;
DoCallback(trc, &sym, name);
if (sym != prior)
*idp = SYMBOL_TO_JSID(sym);
}
}
JS_PUBLIC_API(void)
JS_CallUnbarrieredValueTracer(JSTracer* trc, Value* valuep, const char* name)
{
@ -102,7 +159,7 @@ JS_CallTenuredObjectTracer(JSTracer* trc, JS::TenuredHeap<JSObject*>* objp, cons
if (!obj)
return;
trc->setTracingLocation((void*)objp);
JS::AutoOriginalTraceLocation reloc(trc, (void**)objp);
TraceManuallyBarrieredEdge(trc, &obj, name);
objp->setPtr(obj);
@ -329,61 +386,22 @@ JSTracer::JSTracer(JSRuntime* rt, TracerKindTag kindTag,
WeakMapTraceKind weakTraceKind /* = TraceWeakMapValues */)
: runtime_(rt)
, tag(kindTag)
, debugPrinter_(nullptr)
, debugPrintArg_(nullptr)
, debugPrintIndex_(size_t(-1))
, eagerlyTraceWeakMaps_(weakTraceKind)
#ifdef JS_GC_ZEAL
, realLocation_(nullptr)
#endif
{
}
bool
JSTracer::hasTracingDetails() const
{
return debugPrinter_ || debugPrintArg_;
}
const char*
JSTracer::tracingName(const char* fallback) const
JS::CallbackTracer::getTracingEdgeName(char* buffer, size_t bufferSize)
{
MOZ_ASSERT(hasTracingDetails());
return debugPrinter_ ? fallback : (const char*)debugPrintArg_;
}
const char*
JSTracer::getTracingEdgeName(char* buffer, size_t bufferSize)
{
if (debugPrinter_) {
debugPrinter_(this, buffer, bufferSize);
if (contextFunctor_) {
(*contextFunctor_)(this, buffer, bufferSize);
return buffer;
}
if (debugPrintIndex_ != size_t(-1)) {
JS_snprintf(buffer, bufferSize, "%s[%lu]",
(const char*)debugPrintArg_,
debugPrintIndex_);
if (contextIndex_ != InvalidIndex) {
JS_snprintf(buffer, bufferSize, "%s[%lu]", contextName_, contextIndex_);
return buffer;
}
return (const char*)debugPrintArg_;
}
JSTraceNamePrinter
JSTracer::debugPrinter() const
{
return debugPrinter_;
}
const void*
JSTracer::debugPrintArg() const
{
return debugPrintArg_;
}
size_t
JSTracer::debugPrintIndex() const
{
return debugPrintIndex_;
return contextName_;
}
void
@ -392,27 +410,6 @@ JS::CallbackTracer::setTraceCallback(JSTraceCallback traceCallback)
callback = traceCallback;
}
#ifdef JS_GC_ZEAL
void
JSTracer::setTracingLocation(void* location)
{
if (!realLocation_ || !location)
realLocation_ = location;
}
void
JSTracer::unsetTracingLocation()
{
realLocation_ = nullptr;
}
void**
JSTracer::tracingLocation(void** thingp)
{
return realLocation_ ? (void**)realLocation_ : thingp;
}
#endif
bool
MarkStack::init(JSGCMode gcMode)
{

View File

@ -253,11 +253,12 @@ class GCMarker : public JSTracer
template <typename T>
void markAndTraverse(T* thing) {
if (mark(thing))
markChildren(thing);
dispatchToTraceChildren(thing);
}
// We may not have concrete types yet, so this has to be out of the header.
template <typename T>
void markChildren(T* thing);
void dispatchToTraceChildren(T* thing);
// Mark the given GC thing, but do not trace its children. Return true
// if the thing became marked.
@ -304,8 +305,6 @@ class GCMarker : public JSTracer
void markAndScanString(JSObject* source, JSString* str);
void markAndScanSymbol(JSObject* source, JS::Symbol* sym);
void appendGrayRoot(void* thing, JSGCTraceKind kind);
/* The color is only applied to objects and functions. */
uint32_t color;
@ -332,7 +331,7 @@ class BufferGrayRootsTracer : public JS::CallbackTracer
// Set to false if we OOM while buffering gray roots.
bool bufferingGrayRootsFailed;
void appendGrayRoot(gc::Cell* thing, JSGCTraceKind kind);
void appendGrayRoot(gc::TenuredCell* thing, JSGCTraceKind kind);
public:
explicit BufferGrayRootsTracer(JSRuntime* rt)
@ -340,8 +339,8 @@ class BufferGrayRootsTracer : public JS::CallbackTracer
{}
static void grayTraceCallback(JS::CallbackTracer* trc, void** thingp, JSGCTraceKind kind) {
static_cast<BufferGrayRootsTracer*>(trc)->appendGrayRoot(static_cast<gc::Cell*>(*thingp),
kind);
auto tracer = static_cast<BufferGrayRootsTracer*>(trc);
tracer->appendGrayRoot(gc::TenuredCell::fromPointer(*thingp), kind);
}
bool failed() const { return bufferingGrayRootsFailed; }

View File

@ -133,7 +133,7 @@ AccumulateEdge(JS::CallbackTracer* jstrc, void** thingp, JSGCTraceKind kind)
node->edges[i].thing = *thingp;
node->edges[i].kind = kind;
node->edges[i].label = trc->tracingName("<unknown>");
node->edges[i].label = trc->contextName();
node->count++;
}
@ -312,9 +312,7 @@ AssertMarkedOrAllocated(const EdgeValue& edge)
return;
char msgbuf[1024];
const char* label = edge.label;
JS_snprintf(msgbuf, sizeof(msgbuf), "[barrier verifier] Unmarked edge: %s", label);
JS_snprintf(msgbuf, sizeof(msgbuf), "[barrier verifier] Unmarked edge: %s", edge.label);
MOZ_ReportAssertionFailure(msgbuf, __FILE__, __LINE__);
MOZ_CRASH();
}
@ -389,7 +387,7 @@ struct VerifyPostTracer : JS::CallbackTracer
int count;
/* The set of edges in the StoreBuffer at the end of verification. */
typedef HashSet<void**, PointerHasher<void**, 3>, SystemAllocPolicy> EdgeSet;
typedef HashSet<void*const*, PointerHasher<void*const*, 3>, SystemAllocPolicy> EdgeSet;
EdgeSet* edges;
VerifyPostTracer(JSRuntime* rt, JSTraceCallback callback)
@ -438,13 +436,13 @@ PostVerifierCollectStoreBufferEdges(JS::CallbackTracer* jstrc, void** thingp, JS
* only things that enter this callback are marked by the store buffer. The
* store buffer ensures that the real tracing location is set correctly.
*/
void** loc = trc->tracingLocation(thingp);
void*const* loc = trc->tracingLocation(thingp);
trc->edges->put(loc);
}
static void
AssertStoreBufferContainsEdge(VerifyPostTracer::EdgeSet* edges, void** loc, JSObject* dst)
AssertStoreBufferContainsEdge(VerifyPostTracer::EdgeSet* edges, void*const* loc, JSObject* dst)
{
if (edges->has(loc))
return;
@ -477,7 +475,7 @@ PostVerifierVisitEdge(JS::CallbackTracer* jstrc, void** thingp, JSGCTraceKind ki
* below. Since JSObject::markChildren handles this, the real trace
* location will be set correctly in these cases.
*/
void** loc = trc->tracingLocation(thingp);
void*const* loc = trc->tracingLocation(thingp);
AssertStoreBufferContainsEdge(trc->edges, loc, dst);
}

View File

@ -248,7 +248,7 @@ struct Zone : public JS::shadow::Zone,
CompartmentVector compartments;
// This compartment's gray roots.
typedef js::Vector<js::GrayRoot, 0, js::SystemAllocPolicy> GrayRootVector;
typedef js::Vector<js::gc::Cell*, 0, js::SystemAllocPolicy> GrayRootVector;
GrayRootVector gcGrayRoots;
// A set of edges from this zone to other zones.

View File

@ -639,7 +639,7 @@ JitCode::copyFrom(MacroAssembler& masm)
}
void
JitCode::trace(JSTracer* trc)
JitCode::traceChildren(JSTracer* trc)
{
// Note that we cannot mark invalidated scripts, since we've basically
// corrupted the code stream by injecting bailouts.
@ -2610,7 +2610,7 @@ InvalidateActivation(FreeOp* fop, const JitActivationIterator& activations, bool
// embedded in the JitCode. Perform one final trace of the
// JitCode for the incremental GC, as it must know about
// those edges.
ionCode->trace(zone->barrierTracer());
ionCode->traceChildren(zone->barrierTracer());
}
ionCode->setInvalidated();

View File

@ -107,7 +107,7 @@ class JitCode : public gc::TenuredCell
size_t instructionsSize() const {
return insnSize_;
}
void trace(JSTracer* trc);
void traceChildren(JSTracer* trc);
void finalize(FreeOp* fop);
void fixupAfterMovingGC() {}
void setInvalidated() {

View File

@ -5059,6 +5059,7 @@ enum AsmJSCacheResult
AsmJSCache_ModuleTooSmall,
AsmJSCache_SynchronousScript,
AsmJSCache_QuotaExceeded,
AsmJSCache_StorageInitFailure,
AsmJSCache_Disabled_Internal,
AsmJSCache_Disabled_ShellFlags,
AsmJSCache_Disabled_JitInspector,

View File

@ -86,7 +86,7 @@ js::TraceCycleDetectionSet(JSTracer* trc, js::ObjectSet& set)
{
for (js::ObjectSet::Enum e(set); !e.empty(); e.popFront()) {
JSObject* key = e.front();
trc->setTracingLocation((void*)&e.front());
JS::AutoOriginalTraceLocation reloc(trc, &e.front());
TraceRoot(trc, &key, "cycle detector table entry");
if (key != e.front())
e.rekeyFront(key);

View File

@ -23,6 +23,18 @@
#include "vm/NativeObject.h"
#define FOR_EACH_GC_LAYOUT(D) \
D(Object, JSObject) \
D(String, JSString) \
D(Symbol, JS::Symbol) \
D(Script, JSScript) \
D(AccessorShape, js::AccessorShape) \
D(Shape, js::Shape) \
D(BaseShape, js::BaseShape) \
D(JitCode, js::jit::JitCode) \
D(LazyScript, js::LazyScript) \
D(ObjectGroup, js::ObjectGroup)
namespace js {
unsigned GetCPUCount();
@ -1089,19 +1101,6 @@ struct GCChunkHasher {
typedef HashSet<js::gc::Chunk*, GCChunkHasher, SystemAllocPolicy> GCChunkSet;
struct GrayRoot {
void* thing;
JSGCTraceKind kind;
#ifdef DEBUG
JSTraceNamePrinter debugPrinter;
const void* debugPrintArg;
size_t debugPrintIndex;
#endif
GrayRoot(void* thing, JSGCTraceKind kind)
: thing(thing), kind(kind) {}
};
typedef void (*IterateChunkCallback)(JSRuntime* rt, void* data, gc::Chunk* chunk);
typedef void (*IterateZoneCallback)(JSRuntime* rt, void* data, JS::Zone* zone);
typedef void (*IterateArenaCallback)(JSRuntime* rt, void* data, gc::Arena* arena,

View File

@ -2165,8 +2165,8 @@ JSObject::swap(JSContext* cx, HandleObject a, HandleObject b)
*/
JS::Zone* zone = a->zone();
if (zone->needsIncrementalBarrier()) {
a->markChildren(zone->barrierTracer());
b->markChildren(zone->barrierTracer());
a->traceChildren(zone->barrierTracer());
b->traceChildren(zone->barrierTracer());
}
NotifyGCPostSwap(a, b, r);
@ -3490,13 +3490,21 @@ js::ToObjectSlow(JSContext* cx, JS::HandleValue val, bool reportScanStack)
return PrimitiveToObject(cx, val);
}
void
js::GetObjectSlotName(JSTracer* trc, char* buf, size_t bufsize)
class GetObjectSlotNameFunctor : public JS::CallbackTracer::ContextFunctor
{
MOZ_ASSERT(trc->debugPrinter() == GetObjectSlotName);
JSObject* obj;
JSObject* obj = (JSObject*)trc->debugPrintArg();
uint32_t slot = uint32_t(trc->debugPrintIndex());
public:
explicit GetObjectSlotNameFunctor(JSObject* ctx) : obj(ctx) {}
virtual void operator()(JS::CallbackTracer* trc, char* buf, size_t bufsize) override;
};
void
GetObjectSlotNameFunctor::operator()(JS::CallbackTracer* trc, char* buf, size_t bufsize)
{
MOZ_ASSERT(trc->contextIndex() != JS::CallbackTracer::InvalidIndex);
uint32_t slot = uint32_t(trc->contextIndex());
Shape* shape;
if (obj->isNative()) {
@ -4056,7 +4064,7 @@ template<> const char16_t JS::ubi::TracerConcrete<JSObject>::concreteTypeName[]
MOZ_UTF16("JSObject");
void
JSObject::markChildren(JSTracer* trc)
JSObject::traceChildren(JSTracer* trc)
{
TraceEdge(trc, &group_, "group");
@ -4069,7 +4077,11 @@ JSObject::markChildren(JSTracer* trc)
TraceEdge(trc, &nobj->shape_, "shape");
MarkObjectSlots(trc, nobj, 0, nobj->slotSpan());
{
GetObjectSlotNameFunctor func(nobj);
JS::AutoTracingDetails ctx(trc, func);
MarkObjectSlots(trc, nobj, 0, nobj->slotSpan());
}
do {
if (nobj->denseElementsAreCopyOnWrite()) {

View File

@ -263,7 +263,7 @@ class JSObject : public js::gc::Cell
/* GC support. */
void markChildren(JSTracer* trc);
void traceChildren(JSTracer* trc);
void fixupAfterMovingGC();
@ -1258,9 +1258,6 @@ XDRObjectLiteral(XDRState<mode>* xdr, MutableHandleObject obj);
extern JSObject*
CloneObjectLiteral(JSContext* cx, HandleObject srcObj);
extern void
GetObjectSlotName(JSTracer* trc, char* buf, size_t bufsize);
extern bool
ReportGetterOnlyAssignment(JSContext* cx, bool strict);

View File

@ -3423,7 +3423,7 @@ JSScript::hasBreakpointsAt(jsbytecode* pc)
}
void
JSScript::markChildren(JSTracer* trc)
JSScript::traceChildren(JSTracer* trc)
{
// NOTE: this JSScript may be partially initialized at this point. E.g. we
// may have created it and partially initialized it with
@ -3481,7 +3481,7 @@ JSScript::markChildren(JSTracer* trc)
}
void
LazyScript::markChildren(JSTracer* trc)
LazyScript::traceChildren(JSTracer* trc)
{
if (function_)
TraceEdge(trc, &function_, "function");

View File

@ -1717,7 +1717,7 @@ class JSScript : public js::gc::TenuredCell
static inline js::ThingRootKind rootKind() { return js::THING_ROOT_SCRIPT; }
void markChildren(JSTracer* trc);
void traceChildren(JSTracer* trc);
// A helper class to prevent relazification of the given function's script
// while it's holding on to it. This class automatically roots the script.
@ -2133,7 +2133,7 @@ class LazyScript : public gc::TenuredCell
bool hasUncompiledEnclosingScript() const;
uint32_t staticLevel(JSContext* cx) const;
void markChildren(JSTracer* trc);
void traceChildren(JSTracer* trc);
void finalize(js::FreeOp* fop);
void fixupAfterMovingGC() {}

View File

@ -416,7 +416,7 @@ class ObjectGroupCompartment::NewTableRef : public gc::BufferableRef
void mark(JSTracer* trc) {
JSObject* prior = proto;
trc->setTracingLocation(&*prior);
JS::AutoOriginalTraceLocation reloc(trc, &proto);
TraceManuallyBarrieredEdge(trc, &proto, "newObjectGroups set prototype");
if (prior == proto)
return;

View File

@ -540,6 +540,7 @@ class ObjectGroup : public gc::TenuredCell
inline void clearProperties();
void maybeSweep(AutoClearTypeInferenceStateOnOOM* oom);
void traceChildren(JSTracer *trc);
private:
#ifdef DEBUG

View File

@ -457,7 +457,7 @@ class BaseShape : public gc::TenuredCell
static inline ThingRootKind rootKind() { return THING_ROOT_BASE_SHAPE; }
void markChildren(JSTracer* trc);
void traceChildren(JSTracer* trc);
void fixupAfterMovingGC() {}
@ -965,7 +965,7 @@ class Shape : public gc::TenuredCell
static inline ThingRootKind rootKind() { return THING_ROOT_SHAPE; }
inline void markChildren(JSTracer* trc);
inline void traceChildren(JSTracer* trc);
inline Shape* search(ExclusiveContext* cx, jsid id);
inline Shape* searchLinear(jsid id);
@ -1352,7 +1352,7 @@ Shape::searchLinear(jsid id)
}
inline void
Shape::markChildren(JSTracer* trc)
Shape::traceChildren(JSTracer* trc)
{
TraceEdge(trc, &base_, "base");
TraceEdge(trc, &propidRef(), "propid");

View File

@ -466,7 +466,7 @@ class JSString : public js::gc::TenuredCell
inline JSLinearString* base() const;
void markBase(JSTracer* trc) {
void traceBase(JSTracer* trc) {
MOZ_ASSERT(hasBase());
js::TraceManuallyBarrieredEdge(trc, &d.s.u3.base, "base");
}
@ -509,7 +509,7 @@ class JSString : public js::gc::TenuredCell
bool equals(const char* s);
#endif
inline void markChildren(JSTracer* trc);
inline void traceChildren(JSTracer* trc);
static MOZ_ALWAYS_INLINE void readBarrier(JSString* thing) {
if (thing->isPermanentAtom())
@ -578,7 +578,7 @@ class JSRope : public JSString
return d.s.u3.right;
}
void markChildren(JSTracer* trc) {
void traceChildren(JSTracer* trc) {
js::TraceManuallyBarrieredEdge(trc, &d.s.u2.left, "left child");
js::TraceManuallyBarrieredEdge(trc, &d.s.u3.right, "right child");
}
@ -1273,12 +1273,12 @@ JSString::base() const
}
inline void
JSString::markChildren(JSTracer* trc)
JSString::traceChildren(JSTracer* trc)
{
if (hasBase())
markBase(trc);
traceBase(trc);
else if (isRope())
asRope().markChildren(trc);
asRope().traceChildren(trc);
}
template<>

View File

@ -56,7 +56,7 @@ class Symbol : public js::gc::TenuredCell
bool isWellKnownSymbol() const { return uint32_t(code_) < WellKnownSymbolLimit; }
static inline js::ThingRootKind rootKind() { return js::THING_ROOT_SYMBOL; }
inline void markChildren(JSTracer* trc) {
inline void traceChildren(JSTracer* trc) {
if (description_)
js::TraceManuallyBarrieredEdge(trc, &description_, "description");
}

Some files were not shown because too many files have changed in this diff Show More