diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/debian/changelog thunderbird-trunk-37.0~a1~hg20150108r17327.222808/debian/changelog --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/debian/changelog 2015-01-07 22:54:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/debian/changelog 2015-01-09 14:11:29.000000000 +0000 @@ -1,10 +1,10 @@ -thunderbird-trunk (37.0~a1~hg20150107r17323.222415-0ubuntu1~umd1~trusty) trusty; urgency=medium +thunderbird-trunk (37.0~a1~hg20150108r17327.222808-0ubuntu1~umd1~trusty) trusty; urgency=medium * Refresh patches - update debian/patches/unity-menubar.patch - update debian/patches/dont-include-hyphenation-patterns.patch - -- Chris Coulson Wed, 07 Jan 2015 22:08:37 +0000 + -- Chris Coulson Fri, 09 Jan 2015 12:13:28 +0000 thunderbird-trunk (36.0~a1~hg20141126r17147.217518-0ubuntu1) utopic; urgency=medium diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/l10n/changesets thunderbird-trunk-37.0~a1~hg20150108r17327.222808/l10n/changesets --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/l10n/changesets 2015-01-07 22:17:38.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/l10n/changesets 2015-01-09 12:42:43.000000000 +0000 @@ -24,7 +24,7 @@ hu 794:b45f6b60407e id 512:b520186368ec is 297:33af74865c25 -it 3576:b2e5691e68ae +it 3580:2ada31bf14a7 ja 633:608df4a0c172 ja-JP-mac 634:aba6f4f0ee5e ka 56:2ee9bc162267 @@ -34,9 +34,9 @@ nl 3800:8bd8b62c2435 nn-NO 636:2032d95af2a7 pa-IN 589:b51530b15a00 -pl 5018:9c57564a4b23 +pl 5023:aa68b815eead pt-BR 664:723658175bdd -pt-PT 2056:22b468633bda +pt-PT 2057:0cb37830d909 rm 388:945a12b3635b ro 414:9a349bbcf451 ru 2260:b1944c9224ca diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/l10n/pt-PT/mail/chrome/messenger/messengercompose/composeMsgs.properties thunderbird-trunk-37.0~a1~hg20150108r17327.222808/l10n/pt-PT/mail/chrome/messenger/messengercompose/composeMsgs.properties --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/l10n/pt-PT/mail/chrome/messenger/messengercompose/composeMsgs.properties 2015-01-07 22:17:11.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/l10n/pt-PT/mail/chrome/messenger/messengercompose/composeMsgs.properties 2015-01-09 12:41:20.000000000 +0000 @@ -295,7 +295,7 @@ ## Attachment Reminder ## LOCALIZATION NOTE (mail.compose.attachment_reminder_keywords): comma separated ## words that that should trigger an attachment reminder. -mail.compose.attachment_reminder_keywords=.doc,.pdf,.xls,.ppt,.rtf,.pps,anexo,anexar,anexado,cv, +mail.compose.attachment_reminder_keywords=.doc,.pdf,.xls,.ppt,.rtf,.pps,anexo,anexar,anexado,cv addAttachmentButton=Adicionar anexo addAttachmentButton.accesskey=A diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mail/installer/package-manifest.in thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mail/installer/package-manifest.in --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mail/installer/package-manifest.in 2015-01-07 22:14:56.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mail/installer/package-manifest.in 2015-01-09 12:34:50.000000000 +0000 @@ -436,6 +436,7 @@ ; layout @RESPATH@/components/content_events.xpt +@RESPATH@/components/content_geckomediaplugins.xpt @RESPATH@/components/content_html.xpt @RESPATH@/components/content_xslt.xpt @RESPATH@/components/html5.xpt diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mailnews/base/public/nsIMsgFolder.idl thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mailnews/base/public/nsIMsgFolder.idl --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mailnews/base/public/nsIMsgFolder.idl 2015-01-07 22:14:56.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mailnews/base/public/nsIMsgFolder.idl 2015-01-09 12:34:49.000000000 +0000 @@ -30,7 +30,7 @@ // enumerated type for determining if a message has been replied to, forwarded, etc. typedef long nsMsgDispositionState; -[scriptable, uuid(9ce446f3-398c-4462-a4c6-0ce562d5bd30)] +[scriptable, uuid(8EC4D122-1082-4fa2-B97C-4AE852B254D2)] interface nsIMsgFolder : nsISupports { const nsMsgBiffState nsMsgBiffState_NewMail = 0; // User has new mail waiting. @@ -547,7 +547,6 @@ */ nsIInputStream getMsgInputStream(in nsIMsgDBHdr aHdr, out boolean aReusable); - readonly attribute nsIInputStream offlineStoreInputStream; void DownloadMessagesForOffline(in nsIArray messages, in nsIMsgWindow window); nsIMsgFolder getChildWithURI(in ACString uri, in boolean deep, diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mailnews/base/public/nsIMsgPluggableStore.idl thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mailnews/base/public/nsIMsgPluggableStore.idl --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mailnews/base/public/nsIMsgPluggableStore.idl 2015-01-07 22:14:56.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mailnews/base/public/nsIMsgPluggableStore.idl 2015-01-09 12:34:49.000000000 +0000 @@ -17,7 +17,7 @@ interface nsIMsgDatabase; interface nsITransaction; -[scriptable, uuid(eccf0046-99db-4b08-8e14-29fa254f59c6)] +[scriptable, uuid(2a861ed8-b4c2-4443-8c20-5e8a217a6310)] /** * Pluggable message store interface. Each incoming server can have a different @@ -321,4 +321,12 @@ */ void changeKeywords(in nsIArray aHdrArray, in ACString aKeywords, in boolean aAdd); + + /** + * Identifies a specific type of store. Please use this only for legacy + * bug fixes, and not as a method to change behavior! + * + * Typical values: "mbox", "maildir" + */ + readonly attribute ACString storeType; }; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mailnews/base/util/nsMsgDBFolder.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mailnews/base/util/nsMsgDBFolder.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mailnews/base/util/nsMsgDBFolder.cpp 2015-01-07 22:14:56.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mailnews/base/util/nsMsgDBFolder.cpp 2015-01-09 12:34:50.000000000 +0000 @@ -751,14 +751,6 @@ return msgStore->GetSummaryFile(this, aSummaryFile); } -NS_IMETHODIMP nsMsgDBFolder::GetOfflineStoreInputStream(nsIInputStream **stream) -{ - nsCOMPtr localStore; - nsresult rv = GetFilePath(getter_AddRefs(localStore)); - NS_ENSURE_SUCCESS(rv, rv); - return NS_NewLocalFileInputStream(stream, localStore); -} - bool nsMsgDBFolder::VerifyOfflineMessage(nsIMsgDBHdr *msgHdr, nsIInputStream *fileStream) { nsCOMPtr seekableStream = do_QueryInterface(fileStream); @@ -1791,13 +1783,6 @@ } else m_offlineHeader->SetLineCount(m_numOfflineMsgLines); -#ifdef _DEBUG - nsCOMPtr inputStream; - GetOfflineStoreInputStream(getter_AddRefs(inputStream)); - if (inputStream) - NS_ASSERTION(VerifyOfflineMessage(m_offlineHeader, inputStream), - "offline message doesn't start with From "); -#endif } if (msgStore) msgStore->FinishNewMessage(m_tempMessageStream, m_offlineHeader); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mailnews/db/msgdb/src/nsMsgThread.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mailnews/db/msgdb/src/nsMsgThread.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mailnews/db/msgdb/src/nsMsgThread.cpp 2015-01-07 22:14:56.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mailnews/db/msgdb/src/nsMsgThread.cpp 2015-01-09 12:34:51.000000000 +0000 @@ -56,8 +56,8 @@ bool found = m_mdbDB->m_threads.RemoveElement(this); NS_ASSERTION(found, "removing thread not in threads array"); } - else - NS_ERROR("null db in thread"); + else // This can happen if db is forced closed + NS_WARNING("null db in thread"); Clear(); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mailnews/imap/src/nsImapMailFolder.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mailnews/imap/src/nsImapMailFolder.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mailnews/imap/src/nsImapMailFolder.cpp 2015-01-07 22:14:57.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mailnews/imap/src/nsImapMailFolder.cpp 2015-01-09 12:34:52.000000000 +0000 @@ -6982,12 +6982,21 @@ { // Some offline stores may contain a bug where the storeToken is set but // the messageOffset is zero. Detect cases like this, and use storeToken - // to set the missing messageOffset. Note that offline stores at least for - // now do not fully support pluggable stores, so this assumes mbox. - nsCString storeToken; - origHdr->GetStringProperty("storeToken", getter_Copies(storeToken)); - if (!storeToken.IsEmpty()) - messageOffset = ParseUint64Str(storeToken.get()); + // to set the missing messageOffset. Note this assumes mbox. + nsCOMPtr offlineStore; + (void) GetMsgStore(getter_AddRefs(offlineStore)); + if (offlineStore) + { + nsAutoCString type; + offlineStore->GetStoreType(type); + if (type.EqualsLiteral("mbox")) + { + nsCString storeToken; + origHdr->GetStringProperty("storeToken", getter_Copies(storeToken)); + if (!storeToken.IsEmpty()) + messageOffset = ParseUint64Str(storeToken.get()); + } + } } origHdr->GetOfflineMessageSize(&messageSize); if (!messageSize) @@ -7134,7 +7143,8 @@ // on the UI thread but we should check if the offline store is locked. bool isLocked; GetLocked(&isLocked); - nsCOMPtr inputStream; + nsCOMPtr inputStream; + bool reusable = false; nsCOMPtr outputStream; nsTArray addedKeys; nsTArray srcKeyArray; @@ -7144,7 +7154,6 @@ nsOfflineImapOperationType deleteOpType = nsIMsgOfflineImapOperation::kDeletedMsg; if (!deleteToTrash) deleteOpType = nsIMsgOfflineImapOperation::kMsgMarkedDeleted; - srcFolder->GetOfflineStoreInputStream(getter_AddRefs(inputStream)); nsCString messageIds; rv = BuildIdsAndKeyArray(messages, messageIds, srcKeyArray); // put fake message in destination db, delete source if move @@ -7253,6 +7262,9 @@ destMsgHdrs->AppendElement(newMailHdr, false); srcFolder->HasMsgOffline(originalKey, &hasMsgOffline); newMailHdr->SetUint32Property("pseudoHdr", 1); + if (!reusable) + (void)srcFolder->GetMsgInputStream(newMailHdr, &reusable, + getter_AddRefs(inputStream)); if (inputStream && hasMsgOffline && !isLocked) { @@ -8286,7 +8298,6 @@ if (msgKey == nsMsgKey_None) mDatabase->GetNextFakeOfflineMsgKey(&msgKey); - nsCOMPtr messages(do_CreateInstance(NS_ARRAY_CONTRACTID)); nsCOMPtr op; rv = mDatabase->GetOfflineOpForKey(msgKey, true, getter_AddRefs(op)); @@ -8322,7 +8333,6 @@ // Tell the parser to use the offset that will be in the dest stream, not the // temp file. - nsCString storeToken; uint64_t offset; fakeHdr->GetMessageOffset(&offset); // This will fail for > 4GB mbox folders, see bug 793865 @@ -8360,16 +8370,24 @@ msgParser->FinishHeader(); uint32_t resultFlags; - fakeHdr->SetMessageOffset(curOfflineStorePos); - char storeToken[100]; - PR_snprintf(storeToken, sizeof(storeToken), "%lld", curOfflineStorePos); - fakeHdr->SetStringProperty("storeToken", storeToken); fakeHdr->OrFlags(nsMsgMessageFlags::Offline | nsMsgMessageFlags::Read, &resultFlags); fakeHdr->SetOfflineMessageSize(fileSize); fakeHdr->SetUint32Property("pseudoHdr", 1); mDatabase->AddNewHdrToDB(fakeHdr, true /* notify */); SetFlag(nsMsgFolderFlags::OfflineEvents); + + // Call FinishNewMessage before setting pending attributes, as in + // maildir it copies from tmp to cur and may change the storeToken + // to get a unique filename. + nsCOMPtr msgStore; + GetMsgStore(getter_AddRefs(msgStore)); + if (msgStore) + msgStore->FinishNewMessage(offlineStore, fakeHdr); + + nsCOMPtr messages(do_CreateInstance(NS_ARRAY_CONTRACTID, &rv)); + NS_ENSURE_SUCCESS(rv, rv); messages->AppendElement(fakeHdr, false); + SetPendingAttributes(messages, false); // Gloda needs this notification to index the fake message. nsCOMPtr @@ -8379,10 +8397,6 @@ inputStream->Close(); inputStream = nullptr; delete inputStreamBuffer; - nsCOMPtr msgStore; - GetMsgStore(getter_AddRefs(msgStore)); - if (msgStore) - msgStore->FinishNewMessage(offlineStore, fakeHdr); } offlineStore->Close(); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mailnews/imap/src/nsImapOfflineSync.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mailnews/imap/src/nsImapOfflineSync.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mailnews/imap/src/nsImapOfflineSync.cpp 2015-01-07 22:14:57.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mailnews/imap/src/nsImapOfflineSync.cpp 2015-01-09 12:34:52.000000000 +0000 @@ -402,7 +402,9 @@ if (NS_SUCCEEDED(rv) && destFolder) { nsCOMPtr offlineStoreInputStream; - rv = destFolder->GetOfflineStoreInputStream(getter_AddRefs(offlineStoreInputStream)); + bool reusable; + rv = destFolder->GetMsgInputStream( + mailHdr, &reusable, getter_AddRefs(offlineStoreInputStream)); if (NS_SUCCEEDED(rv) && offlineStoreInputStream) { nsCOMPtr seekStream = do_QueryInterface(offlineStoreInputStream); @@ -415,7 +417,7 @@ // now, copy the dest folder offline store msg to the temp file int32_t inputBufferSize = 10240; char *inputBuffer = nullptr; - + while (!inputBuffer && (inputBufferSize >= 512)) { inputBuffer = (char *) PR_Malloc(inputBufferSize); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mailnews/local/src/nsLocalMailFolder.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mailnews/local/src/nsLocalMailFolder.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mailnews/local/src/nsLocalMailFolder.cpp 2015-01-07 22:14:57.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mailnews/local/src/nsLocalMailFolder.cpp 2015-01-09 12:34:52.000000000 +0000 @@ -2004,6 +2004,11 @@ NS_ENSURE_SUCCESS(rv, rv); } nsCOMPtr seekableStream = do_QueryInterface(mCopyState->m_fileStream, &rv); + + // XXX ToDo: When copying multiple messages from a non-offline-enabled IMAP + // server, this fails. (The copy succeeds because the file stream is created + // subsequently in StartMessage) We should not be warning on an expected error. + // Perhaps there are unexpected consequences of returning early? NS_ENSURE_SUCCESS(rv, rv); seekableStream->Seek(nsISeekableStream::NS_SEEK_END, 0); @@ -2197,18 +2202,19 @@ if (!aCopySucceeded || mCopyState->m_writeFailed) { - if (mCopyState->m_curDstKey != nsMsgKey_None) - mCopyState->m_msgStore->DiscardNewMessage(mCopyState->m_fileStream, - mCopyState->m_newHdr); - if (mCopyState->m_fileStream) + { + if (mCopyState->m_curDstKey != nsMsgKey_None) + mCopyState->m_msgStore->DiscardNewMessage(mCopyState->m_fileStream, + mCopyState->m_newHdr); mCopyState->m_fileStream->Close(); + } if (!mCopyState->m_isMove) { - // passing true because the messages that have been successfully - // copied have their corresponding hdrs in place. The message that has - // failed has been truncated so the msf file and berkeley mailbox + // passing true because the messages that have been successfully + // copied have their corresponding hdrs in place. The message that has + // failed has been truncated so the msf file and berkeley mailbox // are in sync. (void) OnCopyCompleted(mCopyState->m_srcSupport, true); // enable the dest folder @@ -2221,7 +2227,6 @@ nsRefPtr localUndoTxn = mCopyState->m_undoMsgTxn; - nsCOMPtr seekableStream; NS_ASSERTION(mCopyState->m_leftOver == 0, "whoops, something wrong with previous copy"); mCopyState->m_leftOver = 0; // reset to 0. // need to reset this in case we're move/copying multiple msgs. @@ -2229,9 +2234,19 @@ // flush the copied message. We need a close at the end to get the // file size and time updated correctly. - if (mCopyState->m_fileStream) + // + // These filestream closes are handled inconsistently in the code. In some + // cases, this is done in EndMessage, while in others it is done here in + // EndCopy. When we do the close in EndMessage, we'll set + // mCopyState->m_fileStream to null since it is no longer needed, and detect + // here the null stream so we know that we don't have to close it here. + // + // Similarly, m_parseMsgState->GetNewMsgHdr() returns a null hdr if the hdr + // has already been processed by EndMessage so it is not doubly added here. + + nsCOMPtr seekableStream(do_QueryInterface(mCopyState->m_fileStream)); + if (seekableStream) { - seekableStream = do_QueryInterface(mCopyState->m_fileStream); if (mCopyState->m_dummyEnvelopeNeeded) { uint32_t bytesWritten; @@ -2240,30 +2255,14 @@ if (mCopyState->m_parseMsgState) mCopyState->m_parseMsgState->ParseAFolderLine(CRLF, MSG_LINEBREAK_LEN); } - // flush the copied message. We need a close at the end to get the - // file size and time updated correctly. - seekableStream = do_QueryInterface(mCopyState->m_fileStream); - if (mCopyState->m_dummyEnvelopeNeeded) - { - uint32_t bytesWritten; - seekableStream->Seek(nsISeekableStream::NS_SEEK_END, 0); - mCopyState->m_fileStream->Write(MSG_LINEBREAK, MSG_LINEBREAK_LEN, - &bytesWritten); - if (mCopyState->m_parseMsgState) - mCopyState->m_parseMsgState->ParseAFolderLine(CRLF, MSG_LINEBREAK_LEN); - } - // flush the copied message. We need a close at the end to get the - // file size and time updated correctly. rv = mCopyState->m_msgStore->FinishNewMessage(mCopyState->m_fileStream, - mCopyState->m_newHdr); + mCopyState->m_newHdr); if (NS_SUCCEEDED(rv) && mCopyState->m_newHdr) mCopyState->m_newHdr->GetMessageKey(&mCopyState->m_curDstKey); if (multipleCopiesFinished) mCopyState->m_fileStream->Close(); else mCopyState->m_fileStream->Flush(); - mCopyState->m_msgStore->FinishNewMessage(mCopyState->m_fileStream, - mCopyState->m_newHdr); } //Copy the header to the new database if (mCopyState->m_message) @@ -2580,6 +2579,11 @@ if (mCopyState->m_parseMsgState) mCopyState->m_parseMsgState->ParseAFolderLine(CRLF, MSG_LINEBREAK_LEN); + rv = mCopyState->m_msgStore->FinishNewMessage(mCopyState->m_fileStream, + mCopyState->m_newHdr); + mCopyState->m_fileStream->Close(); + mCopyState->m_fileStream = nullptr; // all done with the file stream + // CopyFileMessage() and CopyMessages() from servers other than mailbox if (mCopyState->m_parseMsgState) { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mailnews/local/src/nsMsgBrkMBoxStore.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mailnews/local/src/nsMsgBrkMBoxStore.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mailnews/local/src/nsMsgBrkMBoxStore.cpp 2015-01-07 22:14:57.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mailnews/local/src/nsMsgBrkMBoxStore.cpp 2015-01-09 12:34:52.000000000 +0000 @@ -1005,6 +1005,12 @@ return NS_OK; } +NS_IMETHODIMP nsMsgBrkMBoxStore::GetStoreType(nsACString& aType) +{ + aType.AssignLiteral("mbox"); + return NS_OK; +} + // Iterates over the files in the "path" directory, and adds subfolders to // parent for each mailbox file found. nsresult diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mailnews/local/src/nsMsgMaildirStore.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mailnews/local/src/nsMsgMaildirStore.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mailnews/local/src/nsMsgMaildirStore.cpp 2015-01-07 22:14:57.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mailnews/local/src/nsMsgMaildirStore.cpp 2015-01-09 12:34:52.000000000 +0000 @@ -977,21 +977,56 @@ NS_ENSURE_ARG_POINTER(aDstFolder); NS_ENSURE_ARG_POINTER(aCopyDone); NS_ENSURE_ARG_POINTER(aUndoAction); - uint32_t messageCount; - nsresult rv = aHdrArray->GetLength(&messageCount); - NS_ENSURE_SUCCESS(rv, rv); + + *aCopyDone = false; + nsCOMPtr srcFolder; + nsresult rv; + nsCOMPtr msgHdr = do_QueryElementAt(aHdrArray, 0, &rv); + NS_ENSURE_SUCCESS(rv, rv); + rv = msgHdr->GetFolder(getter_AddRefs(srcFolder)); + NS_ENSURE_SUCCESS(rv, rv); + + // Both source and destination folders must use maildir type store. + nsCOMPtr srcStore; + nsAutoCString srcType; + srcFolder->GetMsgStore(getter_AddRefs(srcStore)); + if (srcStore) + srcStore->GetStoreType(srcType); + nsCOMPtr dstStore; + nsAutoCString dstType; + aDstFolder->GetMsgStore(getter_AddRefs(dstStore)); + if (dstStore) + dstStore->GetStoreType(dstType); + if (!srcType.EqualsLiteral("maildir") || !dstType.EqualsLiteral("maildir")) + return NS_OK; + + // Both source and destination must be local folders. In theory we could + // do efficient copies of the offline store of IMAP, but this is not + // supported yet. For that, we need to deal with both correct handling + // of deletes from the src server, and msgKey = UIDL in the dst folder. + nsCOMPtr destLocalFolder(do_QueryInterface(aDstFolder)); + if (!destLocalFolder) + return NS_OK; + nsCOMPtr srcLocalFolder(do_QueryInterface(srcFolder)); + if (!srcLocalFolder) + return NS_OK; + + // We should be able to use a file move for an efficient copy. + nsCOMPtr destFolderPath; nsCOMPtr destDB; - nsCOMPtr srcDB; aDstFolder->GetMsgDatabase(getter_AddRefs(destDB)); - aDstFolder->GetFilePath(getter_AddRefs(destFolderPath)); + rv = aDstFolder->GetFilePath(getter_AddRefs(destFolderPath)); + NS_ENSURE_SUCCESS(rv, rv); destFolderPath->Append(NS_LITERAL_STRING("cur")); - nsCOMPtr msgHdr = do_QueryElementAt(aHdrArray, 0, &rv); - NS_ENSURE_SUCCESS(rv, rv); - rv = msgHdr->GetFolder(getter_AddRefs(srcFolder)); + nsCOMPtr srcFolderPath; + rv = srcFolder->GetFilePath(getter_AddRefs(srcFolderPath)); NS_ENSURE_SUCCESS(rv, rv); + srcFolderPath->Append(NS_LITERAL_STRING("cur")); + + nsCOMPtr srcDB; srcFolder->GetMsgDatabase(getter_AddRefs(srcDB)); nsRefPtr msgTxn = new nsLocalMoveCopyMsgTxn; NS_ENSURE_TRUE(msgTxn, NS_ERROR_OUT_OF_MEMORY); @@ -1003,34 +1038,40 @@ msgTxn->SetTransactionType(nsIMessenger::eCopyMsg); } + if (aListener) + aListener->OnStartCopy(); + nsCOMPtr dstHdrs(do_CreateInstance(NS_ARRAY_CONTRACTID, &rv)); NS_ENSURE_SUCCESS(rv, rv); + uint32_t messageCount; + rv = aHdrArray->GetLength(&messageCount); + NS_ENSURE_SUCCESS(rv, rv); + for (uint32_t i = 0; i < messageCount; i++) { - nsCOMPtr msgHdr = do_QueryElementAt(aHdrArray, i, &rv); + nsCOMPtr srcHdr = do_QueryElementAt(aHdrArray, i, &rv); if (NS_FAILED(rv)) + { + PR_LOG(MailDirLog, PR_LOG_ALWAYS, + ("srcHdr null\n")); continue; + } nsMsgKey srcKey; - msgHdr->GetMessageKey(&srcKey); + srcHdr->GetMessageKey(&srcKey); msgTxn->AddSrcKey(srcKey); - msgHdr->GetFolder(getter_AddRefs(srcFolder)); - nsCOMPtr path; - rv = srcFolder->GetFilePath(getter_AddRefs(path)); - NS_ENSURE_SUCCESS(rv, rv); nsAutoCString fileName; msgHdr->GetStringProperty("storeToken", getter_Copies(fileName)); if (fileName.IsEmpty()) - return NS_ERROR_FAILURE; - - if (fileName.IsEmpty()) { PR_LOG(MailDirLog, PR_LOG_ALWAYS, ("GetMsgInputStream - empty storeToken!!\n")); return NS_ERROR_FAILURE; } - path->Append(NS_LITERAL_STRING("cur")); - path->AppendNative(fileName); + nsCOMPtr srcFile; + rv = srcFolderPath->Clone(getter_AddRefs(srcFile)); + NS_ENSURE_SUCCESS(rv, rv); + srcFile->AppendNative(fileName); nsCOMPtr destFile; destFolderPath->Clone(getter_AddRefs(destFile)); @@ -1044,26 +1085,33 @@ destFile->GetNativeLeafName(fileName); } if (aIsMove) - path->MoveToNative(destFolderPath, fileName); + rv = srcFile->MoveToNative(destFolderPath, fileName); else - path->CopyToNative(destFolderPath, fileName); + rv = srcFile->CopyToNative(destFolderPath, fileName); + NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr destHdr; if (destDB) { - rv = destDB->CopyHdrFromExistingHdr(nsMsgKey_None, msgHdr, true, getter_AddRefs(destHdr)); + rv = destDB->CopyHdrFromExistingHdr(nsMsgKey_None, srcHdr, true, getter_AddRefs(destHdr)); NS_ENSURE_SUCCESS(rv, rv); destHdr->SetStringProperty("storeToken", fileName.get()); dstHdrs->AppendElement(destHdr, false); nsMsgKey dstKey; destHdr->GetMessageKey(&dstKey); msgTxn->AddDstKey(dstKey); + if (aListener) + aListener->SetMessageKey(dstKey); } } nsCOMPtr notifier(do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID)); if (notifier) notifier->NotifyMsgsMoveCopyCompleted(aIsMove, aHdrArray, aDstFolder, dstHdrs); + + // For now, we only support local dest folders, and for those we are done and + // can delete the messages. Perhaps this should be moved into the folder + // when we try to support other folder types. if (aIsMove) { for (uint32_t i = 0; i < messageCount; ++i) @@ -1072,11 +1120,11 @@ rv = srcDB->DeleteHeader(msgDBHdr, nullptr, false, true); } } + *aCopyDone = true; nsCOMPtr srcSupports(do_QueryInterface(srcFolder)); - nsCOMPtr localDest(do_QueryInterface(aDstFolder)); - if (localDest) - localDest->OnCopyCompleted(srcSupports, true); + if (destLocalFolder) + destLocalFolder->OnCopyCompleted(srcSupports, true); if (aListener) aListener->OnStopCopy(NS_OK); msgTxn.forget(aUndoAction); @@ -1359,6 +1407,12 @@ return NS_OK; } +NS_IMETHODIMP nsMsgMaildirStore::GetStoreType(nsACString& aType) +{ + aType.AssignLiteral("maildir"); + return NS_OK; +} + /** * Finds the directory associated with this folder. That is if the path is * c:\Inbox, it will return c:\Inbox.sbd if it succeeds. Path is strictly diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/addon-sdk/source/python-lib/cuddlefish/runner.py thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/addon-sdk/source/python-lib/cuddlefish/runner.py --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/addon-sdk/source/python-lib/cuddlefish/runner.py 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/addon-sdk/source/python-lib/cuddlefish/runner.py 2015-01-09 12:36:25.000000000 +0000 @@ -492,7 +492,6 @@ env['MOZ_DISABLE_NONLOCAL_CONNECTIONS'] = '1' env['MOZ_NO_REMOTE'] = '1' env['XPCOM_DEBUG_BREAK'] = 'stack' - env['NS_TRACE_MALLOC_DISABLE_STACKS'] = '1' env.update(extra_environment) if norun: cmdargs.append("-no-remote") diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/b2g/config/dolphin/sources.xml thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/b2g/config/dolphin/sources.xml --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/b2g/config/dolphin/sources.xml 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/b2g/config/dolphin/sources.xml 2015-01-09 12:36:27.000000000 +0000 @@ -15,15 +15,15 @@ - + - + - + @@ -129,7 +129,7 @@ - + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/b2g/config/emulator/sources.xml thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/b2g/config/emulator/sources.xml --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/b2g/config/emulator/sources.xml 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/b2g/config/emulator/sources.xml 2015-01-09 12:36:27.000000000 +0000 @@ -19,16 +19,16 @@ - - + + - + - + @@ -102,6 +102,7 @@ + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/b2g/config/emulator-ics/sources.xml thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/b2g/config/emulator-ics/sources.xml --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/b2g/config/emulator-ics/sources.xml 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/b2g/config/emulator-ics/sources.xml 2015-01-09 12:36:27.000000000 +0000 @@ -19,16 +19,16 @@ - - + + - + - + @@ -102,6 +102,7 @@ + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/b2g/config/emulator-jb/sources.xml thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/b2g/config/emulator-jb/sources.xml --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/b2g/config/emulator-jb/sources.xml 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/b2g/config/emulator-jb/sources.xml 2015-01-09 12:36:27.000000000 +0000 @@ -17,10 +17,10 @@ - - + + - + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/b2g/config/emulator-kk/sources.xml thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/b2g/config/emulator-kk/sources.xml --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/b2g/config/emulator-kk/sources.xml 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/b2g/config/emulator-kk/sources.xml 2015-01-09 12:36:27.000000000 +0000 @@ -15,15 +15,15 @@ - + - + - + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/b2g/config/flame/sources.xml thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/b2g/config/flame/sources.xml --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/b2g/config/flame/sources.xml 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/b2g/config/flame/sources.xml 2015-01-09 12:36:27.000000000 +0000 @@ -17,10 +17,10 @@ - - + + - + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/b2g/config/flame-kk/releng-flame-kk.tt thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/b2g/config/flame-kk/releng-flame-kk.tt --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/b2g/config/flame-kk/releng-flame-kk.tt 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/b2g/config/flame-kk/releng-flame-kk.tt 2015-01-09 12:36:27.000000000 +0000 @@ -1,9 +1,9 @@ [ { -"size": 120750384, -"digest": "0e0a0b0dcca020e3283ce8deb33d0eed48fab16ef2fd919120bd7b5abba00713210be17f466d11bf77cca3c9e3b663805be61774476cc669f0a75736d901edfd", +"size": 135359412, +"digest": "45e677c9606cc4eec44ef4761df47ff431df1ffad17a5c6d21ce700a1c47f79e87a4aa9f30ae47ff060bd64f5b775d995780d88211f9a759ffa0d076beb4816b", "algorithm": "sha512", "filename": "backup-flame.tar.xz", -"comment": "v188-1" +"comment": "v18D" } ] diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/b2g/config/flame-kk/sources.xml thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/b2g/config/flame-kk/sources.xml --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/b2g/config/flame-kk/sources.xml 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/b2g/config/flame-kk/sources.xml 2015-01-09 12:36:27.000000000 +0000 @@ -15,15 +15,15 @@ - + - + - + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/b2g/config/gaia.json thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/b2g/config/gaia.json --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/b2g/config/gaia.json 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/b2g/config/gaia.json 2015-01-09 12:36:27.000000000 +0000 @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "6505a7b6b4c727a9b561c1220b4ecf726248c5c5", + "revision": "85bbbd703dba85b58c5b9d5902bc784c9f763c1d", "repo_path": "integration/gaia-central" } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/b2g/config/hamachi/sources.xml thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/b2g/config/hamachi/sources.xml --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/b2g/config/hamachi/sources.xml 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/b2g/config/hamachi/sources.xml 2015-01-09 12:36:27.000000000 +0000 @@ -17,11 +17,11 @@ - - + + - + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/b2g/config/helix/sources.xml thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/b2g/config/helix/sources.xml --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/b2g/config/helix/sources.xml 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/b2g/config/helix/sources.xml 2015-01-09 12:36:27.000000000 +0000 @@ -15,8 +15,8 @@ - - + + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/b2g/config/nexus-4/sources.xml thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/b2g/config/nexus-4/sources.xml --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/b2g/config/nexus-4/sources.xml 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/b2g/config/nexus-4/sources.xml 2015-01-09 12:36:27.000000000 +0000 @@ -17,10 +17,10 @@ - - + + - + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/b2g/config/wasabi/sources.xml thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/b2g/config/wasabi/sources.xml --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/b2g/config/wasabi/sources.xml 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/b2g/config/wasabi/sources.xml 2015-01-09 12:36:27.000000000 +0000 @@ -17,12 +17,12 @@ - - + + - + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/b2g/confvars.sh thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/b2g/confvars.sh --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/b2g/confvars.sh 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/b2g/confvars.sh 2015-01-09 12:36:27.000000000 +0000 @@ -59,6 +59,11 @@ if test "$OS_TARGET" = "Android"; then MOZ_NUWA_PROCESS=1 MOZ_B2G_LOADER=1 +# Warnings-as-errors cannot be enabled on gcc <= 4.4 due to bug 915555. +if test "$GCC_MAJOR_VERSION" -gt 4 -o \ + "$GCC_MAJOR_VERSION" -eq 4 -a "$GCC_MINOR_VERSION" -gt 4; then +MOZ_ENABLE_WARNINGS_AS_ERRORS=1 +fi fi MOZ_JSDOWNLOADS=1 diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/app/profile/firefox.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/app/profile/firefox.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/app/profile/firefox.js 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/app/profile/firefox.js 2015-01-09 12:36:27.000000000 +0000 @@ -862,7 +862,7 @@ #endif // Toggles between the two Preferences implementations, pop-up window and in-content -#ifndef RELEASE_BUILD +#ifdef EARLY_BETA_OR_EARLIER pref("browser.preferences.inContent", true); pref("browser.preferences.instantApply", true); #else @@ -1644,6 +1644,7 @@ pref("loop.enabled", true); pref("loop.server", "https://loop.services.mozilla.com/v0"); pref("loop.seenToS", "unseen"); +pref("loop.showPartnerLogo", true); pref("loop.gettingStarted.seen", false); pref("loop.gettingStarted.url", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/hello/start/"); pref("loop.gettingStarted.resumeOnFirstJoin", false); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/base/content/browser-fxaccounts.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/base/content/browser-fxaccounts.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/base/content/browser-fxaccounts.js 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/base/content/browser-fxaccounts.js 2015-01-09 12:36:27.000000000 +0000 @@ -266,11 +266,6 @@ Weave.Notifications.removeAll(this.SYNC_MIGRATION_NOTIFICATION_TITLE); return; } - if (gBrowser.currentURI.spec.split("?")[0] == "about:accounts") { - // If the current tab is about:accounts, assume the user just completed a - // migration step and don't bother them with a redundant notification. - return; - } let note = null; switch (this._migrationInfo.state) { case this.fxaMigrator.STATE_USER_FXA: { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/base/content/browser.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/base/content/browser.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/base/content/browser.js 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/base/content/browser.js 2015-01-09 12:36:27.000000000 +0000 @@ -1738,7 +1738,7 @@ saveDocument(gBrowser.selectedBrowser.contentDocumentAsCPOW); break; case "SendMail": - MailIntegration.sendLinkForWindow(window.content); + MailIntegration.sendLinkForBrowser(gBrowser.selectedBrowser); break; default: return; @@ -2643,11 +2643,6 @@ let transportSecurityInfo = serhelper.deserializeObject(securityInfo); transportSecurityInfo.QueryInterface(Ci.nsITransportSecurityInfo) - if (transportSecurityInfo.failedCertChain == null) { - Cu.reportError("transportSecurityInfo didn't have a failedCertChain for a failedChannel"); - return; - } - showReportStatus("activity"); /* @@ -2677,11 +2672,14 @@ // Convert the nsIX509CertList into a format that can be parsed into // JSON let asciiCertChain = []; - let certs = transportSecurityInfo.failedCertChain.getEnumerator(); - while (certs.hasMoreElements()) { - let cert = certs.getNext(); - cert.QueryInterface(Ci.nsIX509Cert); - asciiCertChain.push(btoa(getDERString(cert))); + + if (transportSecurityInfo.failedCertChain) { + let certs = transportSecurityInfo.failedCertChain.getEnumerator(); + while (certs.hasMoreElements()) { + let cert = certs.getNext(); + cert.QueryInterface(Ci.nsIX509Cert); + asciiCertChain.push(btoa(getDERString(cert))); + } } let report = { @@ -6526,9 +6524,8 @@ } var MailIntegration = { - sendLinkForWindow: function (aWindow) { - this.sendMessage(aWindow.location.href, - aWindow.document.title); + sendLinkForBrowser: function (aBrowser) { + this.sendMessage(aBrowser.currentURI.spec, aBrowser.contentTitle); }, sendMessage: function (aBody, aSubject) { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/base/content/browser-sets.inc thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/base/content/browser-sets.inc --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/base/content/browser-sets.inc 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/base/content/browser-sets.inc 2015-01-09 12:36:27.000000000 +0000 @@ -25,7 +25,7 @@ + oncommand="MailIntegration.sendLinkForBrowser(gBrowser.selectedBrowser);"/> diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/base/content/test/general/browser_bug846489_content.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/base/content/test/general/browser_bug846489_content.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/base/content/test/general/browser_bug846489_content.js 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/base/content/test/general/browser_bug846489_content.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -addMessageListener("Browser:SSLErrorReportStatus", function(message) { - sendSyncMessage("ssler-test:SSLErrorReportStatus", {reportStatus:message.data.reportStatus}); -}); - -addMessageListener("ssler-test:SetAutoPref", function(message) { - let checkbox = content.document.getElementById("automaticallyReportInFuture"); - - // we use "click" because otherwise the 'changed' event will not fire - if (checkbox.checked != message.data.value) { - checkbox.click(); - } - - sendSyncMessage("ssler-test:AutoPrefUpdated", {}); -}); - -addMessageListener("ssler-test:SendBtnClick", function(message) { - if (message.data && message.data.forceUI) { - content.dispatchEvent(new content.CustomEvent("AboutNetErrorOptions", - { - detail: "{\"enabled\": true, \"automatic\": false}" - })); - } - let btn = content.document.getElementById("reportCertificateError"); - btn.click(); -}); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/base/content/test/general/browser_bug846489.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/base/content/test/general/browser_bug846489.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/base/content/test/general/browser_bug846489.js 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/base/content/test/general/browser_bug846489.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,327 +0,0 @@ -var badPin = "https://include-subdomains.pinning.example.com"; -var enabledPref = false; -var automaticPref = false; -var urlPref = "security.ssl.errorReporting.url"; -var enforcement_level = 1; - -function loadFrameScript() { - let mm = Cc["@mozilla.org/globalmessagemanager;1"] - .getService(Ci.nsIMessageListenerManager); - const ROOT = getRootDirectory(gTestPath); - mm.loadFrameScript(ROOT+"browser_bug846489_content.js", true); -} - -add_task(function*(){ - waitForExplicitFinish(); - loadFrameScript(); - SimpleTest.requestCompleteLog(); - yield testSendReportDisabled(); - yield testSendReportManual(); - yield testSendReportAuto(); - yield testSendReportError(); - yield testSetAutomatic(); -}); - -// creates a promise of the message in an error page -function createNetworkErrorMessagePromise(aBrowser) { - return new Promise(function(resolve, reject) { - // Error pages do not fire "load" events, so use a progressListener. - var originalDocumentURI = aBrowser.contentDocument.documentURI; - - var progressListener = { - onLocationChange: function(aWebProgress, aRequest, aLocation, aFlags) { - // Make sure nothing other than an error page is loaded. - if (!(aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE)) { - reject("location change was not to an error page"); - } - }, - - onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) { - let doc = aBrowser.contentDocument; - - if (doc.getElementById("reportCertificateError")) { - // Wait until the documentURI changes (from about:blank) this should - // be the error page URI. - var documentURI = doc.documentURI; - if (documentURI == originalDocumentURI) { - return; - } - - aWebProgress.removeProgressListener(progressListener, - Ci.nsIWebProgress.NOTIFY_LOCATION | - Ci.nsIWebProgress.NOTIFY_STATE_REQUEST); - var matchArray = /about:neterror\?.*&d=([^&]*)/.exec(documentURI); - if (!matchArray) { - reject("no network error message found in URI") - return; - } - - var errorMsg = matchArray[1]; - resolve(decodeURIComponent(errorMsg)); - } - }, - - QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener, - Ci.nsISupportsWeakReference]) - }; - - aBrowser.addProgressListener(progressListener, - Ci.nsIWebProgress.NOTIFY_LOCATION | - Ci.nsIWebProgress.NOTIFY_STATE_REQUEST); - }); -} - -// check we can set the 'automatically send' pref -let testSetAutomatic = Task.async(function*() { - setup(); - let tab = gBrowser.addTab(badPin, {skipAnimation: true}); - let browser = tab.linkedBrowser; - let mm = browser.messageManager; - - gBrowser.selectedTab = tab; - - // ensure we have the correct error message from about:neterror - let netError = createNetworkErrorMessagePromise(browser); - yield netError; - - // ensure that setting automatic when unset works - let prefEnabled = new Promise(function(resolve, reject){ - mm.addMessageListener("ssler-test:AutoPrefUpdated", function() { - if (Services.prefs.getBoolPref("security.ssl.errorReporting.automatic")) { - resolve(); - } else { - reject(); - } - }); - }); - - mm.sendAsyncMessage("ssler-test:SetAutoPref",{value:true}); - - yield prefEnabled; - - // ensure un-setting automatic, when set, works - let prefDisabled = new Promise(function(resolve, reject){ - mm.addMessageListener("ssler-test:AutoPrefUpdated", function () { - if (!Services.prefs.getBoolPref("security.ssl.errorReporting.automatic")) { - resolve(); - } else { - reject(); - } - }); - }); - - mm.sendAsyncMessage("ssler-test:SetAutoPref",{value:false}); - - yield prefDisabled; - - gBrowser.removeTab(tab); - cleanup(); -}); - -// test that manual report sending (with button clicks) works -let testSendReportManual = Task.async(function*() { - setup(); - Services.prefs.setBoolPref("security.ssl.errorReporting.enabled", true); - Services.prefs.setCharPref("security.ssl.errorReporting.url", "https://example.com/browser/browser/base/content/test/general/pinning_reports.sjs?succeed"); - - let tab = gBrowser.addTab(badPin, {skipAnimation: true}); - let browser = tab.linkedBrowser; - let mm = browser.messageManager; - - gBrowser.selectedTab = tab; - - // ensure we have the correct error message from about:neterror - let netError = createNetworkErrorMessagePromise(browser); - yield netError; - netError.then(function(val){ - is(val.startsWith("An error occurred during a connection to include-subdomains.pinning.example.com"), true ,"ensure the correct error message came from about:neterror"); - }); - - // Check the report starts on click - let btn = browser.contentDocument.getElementById("reportCertificateError"); - - // check the content script sends the message to report - let reportWillStart = new Promise(function(resolve, reject){ - mm.addMessageListener("Browser:SendSSLErrorReport", function() { - resolve(); - }); - }); - - let deferredReportActivity = Promise.defer() - let deferredReportSucceeds = Promise.defer(); - - // ensure we see the correct statuses in the correct order... - mm.addMessageListener("ssler-test:SSLErrorReportStatus", function(message) { - switch(message.data.reportStatus) { - case "activity": - deferredReportActivity.resolve(message.data.reportStatus); - break; - case "complete": - deferredReportSucceeds.resolve(message.data.reportStatus); - break; - case "error": - deferredReportSucceeds.reject(); - deferredReportActivity.reject(); - break; - } - }); - - // ... once the button is clicked, that is - mm.sendAsyncMessage("ssler-test:SendBtnClick",{}); - - yield reportWillStart; - - yield deferredReportActivity.promise; - yield deferredReportSucceeds.promise; - - gBrowser.removeTab(tab); - cleanup(); -}); - -// test that automatic sending works -let testSendReportAuto = Task.async(function*() { - setup(); - Services.prefs.setBoolPref("security.ssl.errorReporting.enabled", true); - Services.prefs.setBoolPref("security.ssl.errorReporting.automatic", true); - Services.prefs.setCharPref("security.ssl.errorReporting.url", "https://example.com/browser/browser/base/content/test/general/pinning_reports.sjs?succeed"); - - let tab = gBrowser.addTab(badPin, {skipAnimation: true}); - let browser = tab.linkedBrowser; - let mm = browser.messageManager; - - gBrowser.selectedTab = tab; - - let reportWillStart = Promise.defer(); - mm.addMessageListener("Browser:SendSSLErrorReport", function() { - reportWillStart.resolve(); - }); - - let deferredReportActivity = Promise.defer(); - let deferredReportSucceeds = Promise.defer(); - - mm.addMessageListener("ssler-test:SSLErrorReportStatus", function(message) { - switch(message.data.reportStatus) { - case "activity": - deferredReportActivity.resolve(message.data.reportStatus); - break; - case "complete": - deferredReportSucceeds.resolve(message.data.reportStatus); - break; - case "error": - deferredReportSucceeds.reject(); - deferredReportActivity.reject(); - break; - } - }); - - // Ensure the error page loads - let netError = createNetworkErrorMessagePromise(browser); - yield netError; - - // Ensure the reporting steps all occur with no interaction - yield reportWillStart; - yield deferredReportActivity.promise; - yield deferredReportSucceeds.promise; - - gBrowser.removeTab(tab); - cleanup(); -}); - -// test that an error is shown if there's a problem with the report server -let testSendReportError = Task.async(function*() { - setup(); - Services.prefs.setBoolPref("security.ssl.errorReporting.enabled", true); - Services.prefs.setBoolPref("security.ssl.errorReporting.automatic", true); - Services.prefs.setCharPref("security.ssl.errorReporting.url", "https://example.com/browser/browser/base/content/test/general/pinning_reports.sjs?error"); - - let tab = gBrowser.addTab(badPin, {skipAnimation: true}); - let browser = tab.linkedBrowser; - let mm = browser.messageManager; - - gBrowser.selectedTab = tab; - - // check the report send starts.... - let reportWillStart = new Promise(function(resolve, reject){ - mm.addMessageListener("Browser:SendSSLErrorReport", function() { - resolve(); - }); - }); - - let netError = createNetworkErrorMessagePromise(browser); - yield netError; - yield reportWillStart; - - // and that errors are seen - let reportErrors = new Promise(function(resolve, reject) { - mm.addMessageListener("ssler-test:SSLErrorReportStatus", function(message) { - switch(message.data.reportStatus) { - case "complete": - reject(message.data.reportStatus); - break; - case "error": - resolve(message.data.reportStatus); - break; - } - }); - }); - - yield reportErrors; - - gBrowser.removeTab(tab); - cleanup(); -}); - -let testSendReportDisabled = Task.async(function*() { - setup(); - Services.prefs.setBoolPref("security.ssl.errorReporting.enabled", false); - Services.prefs.setCharPref("security.ssl.errorReporting.url", "https://offdomain.com"); - - let tab = gBrowser.addTab(badPin, {skipAnimation: true}); - let browser = tab.linkedBrowser; - let mm = browser.messageManager; - - gBrowser.selectedTab = tab; - - // Ensure we have an error page - let netError = createNetworkErrorMessagePromise(browser); - yield netError; - - let reportErrors = new Promise(function(resolve, reject) { - mm.addMessageListener("ssler-test:SSLErrorReportStatus", function(message) { - switch(message.data.reportStatus) { - case "complete": - reject(message.data.reportStatus); - break; - case "error": - resolve(message.data.reportStatus); - break; - } - }); - }); - - // click the button - mm.sendAsyncMessage("ssler-test:SendBtnClick",{forceUI:true}); - - // check we get an error - yield reportErrors; - - gBrowser.removeTab(tab); - cleanup(); -}); - -function setup() { - // ensure the relevant prefs are set - enabledPref = Services.prefs.getBoolPref("security.ssl.errorReporting.enabled"); - automaticPref = Services.prefs.getBoolPref("security.ssl.errorReporting.automatic"); - urlPref = Services.prefs.getCharPref("security.ssl.errorReporting.url"); - - enforcement_level = Services.prefs.getIntPref("security.cert_pinning.enforcement_level"); - Services.prefs.setIntPref("security.cert_pinning.enforcement_level", 2); -} - -function cleanup() { - // reset prefs for other tests in the run - Services.prefs.setBoolPref("security.ssl.errorReporting.enabled", enabledPref); - Services.prefs.setBoolPref("security.ssl.errorReporting.automatic", automaticPref); - Services.prefs.setCharPref("security.ssl.errorReporting.url", urlPref); -} diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/base/content/test/general/browser.ini thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/base/content/test/general/browser.ini --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/base/content/test/general/browser.ini 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/base/content/test/general/browser.ini 2015-01-09 12:36:28.000000000 +0000 @@ -10,10 +10,10 @@ browser_bug479408_sample.html browser_bug678392-1.html browser_bug678392-2.html - browser_bug846489_content.js browser_bug970746.xhtml browser_fxa_oauth.html browser_registerProtocolHandler_notification.html + browser_ssl_error_reports_content.js browser_star_hsts.sjs browser_tab_dragdrop2_frame1.xul browser_web_channel.html @@ -153,7 +153,6 @@ [browser_bug419612.js] skip-if = e10s # Bug 1056146 - zoom tests use FullZoomHelper and break in e10s [browser_bug422590.js] -[browser_bug846489.js] [browser_bug423833.js] skip-if = true # bug 428712 [browser_bug424101.js] @@ -399,6 +398,7 @@ searchSuggestionUI.html searchSuggestionUI.js [browser_selectTabAtIndex.js] +[browser_ssl_error_reports.js] [browser_star_hsts.js] [browser_subframe_favicons_not_used.js] [browser_tabDrop.js] diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/base/content/test/general/browser_ssl_error_reports_content.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/base/content/test/general/browser_ssl_error_reports_content.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/base/content/test/general/browser_ssl_error_reports_content.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/base/content/test/general/browser_ssl_error_reports_content.js 2015-01-09 12:36:28.000000000 +0000 @@ -0,0 +1,25 @@ +addMessageListener("Browser:SSLErrorReportStatus", function(message) { + sendSyncMessage("ssler-test:SSLErrorReportStatus", {reportStatus:message.data.reportStatus}); +}); + +addMessageListener("ssler-test:SetAutoPref", function(message) { + let checkbox = content.document.getElementById("automaticallyReportInFuture"); + + // we use "click" because otherwise the 'changed' event will not fire + if (checkbox.checked != message.data.value) { + checkbox.click(); + } + + sendSyncMessage("ssler-test:AutoPrefUpdated", {}); +}); + +addMessageListener("ssler-test:SendBtnClick", function(message) { + if (message.data && message.data.forceUI) { + content.dispatchEvent(new content.CustomEvent("AboutNetErrorOptions", + { + detail: "{\"enabled\": true, \"automatic\": false}" + })); + } + let btn = content.document.getElementById("reportCertificateError"); + btn.click(); +}); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/base/content/test/general/browser_ssl_error_reports.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/base/content/test/general/browser_ssl_error_reports.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/base/content/test/general/browser_ssl_error_reports.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/base/content/test/general/browser_ssl_error_reports.js 2015-01-09 12:36:28.000000000 +0000 @@ -0,0 +1,331 @@ +let badChainURL = "https://badchain.include-subdomains.pinning.example.com"; +let noCertURL = "https://fail-handshake.example.com"; +let enabledPref = false; +let automaticPref = false; +let urlPref = "security.ssl.errorReporting.url"; +let enforcement_level = 1; + +function loadFrameScript() { + let mm = Cc["@mozilla.org/globalmessagemanager;1"] + .getService(Ci.nsIMessageListenerManager); + const ROOT = getRootDirectory(gTestPath); + mm.loadFrameScript(ROOT + "browser_ssl_error_reports_content.js", true); +} + +add_task(function*(){ + waitForExplicitFinish(); + loadFrameScript(); + SimpleTest.requestCompleteLog(); + yield testSendReportDisabled(); + yield testSendReportManual(badChainURL, "succeed"); + yield testSendReportManual(noCertURL, "nocert"); + yield testSendReportAuto(); + yield testSendReportError(); + yield testSetAutomatic(); +}); + +// creates a promise of the message in an error page +function createNetworkErrorMessagePromise(aBrowser) { + return new Promise(function(resolve, reject) { + // Error pages do not fire "load" events, so use a progressListener. + let originalDocumentURI = aBrowser.contentDocument.documentURI; + + let progressListener = { + onLocationChange: function(aWebProgress, aRequest, aLocation, aFlags) { + // Make sure nothing other than an error page is loaded. + if (!(aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE)) { + reject("location change was not to an error page"); + } + }, + + onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) { + let doc = aBrowser.contentDocument; + + if (doc.getElementById("reportCertificateError")) { + // Wait until the documentURI changes (from about:blank) this should + // be the error page URI. + let documentURI = doc.documentURI; + if (documentURI == originalDocumentURI) { + return; + } + + aWebProgress.removeProgressListener(progressListener, + Ci.nsIWebProgress.NOTIFY_LOCATION | + Ci.nsIWebProgress.NOTIFY_STATE_REQUEST); + let matchArray = /about:neterror\?.*&d=([^&]*)/.exec(documentURI); + if (!matchArray) { + reject("no network error message found in URI") + return; + } + + let errorMsg = matchArray[1]; + resolve(decodeURIComponent(errorMsg)); + } + }, + + QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener, + Ci.nsISupportsWeakReference]) + }; + + aBrowser.addProgressListener(progressListener, + Ci.nsIWebProgress.NOTIFY_LOCATION | + Ci.nsIWebProgress.NOTIFY_STATE_REQUEST); + }); +} + +// check we can set the 'automatically send' pref +let testSetAutomatic = Task.async(function*() { + setup(); + let tab = gBrowser.addTab(badChainURL, {skipAnimation: true}); + let browser = tab.linkedBrowser; + let mm = browser.messageManager; + + gBrowser.selectedTab = tab; + + // ensure we have the correct error message from about:neterror + let netError = createNetworkErrorMessagePromise(browser); + yield netError; + + // ensure that setting automatic when unset works + let prefEnabled = new Promise(function(resolve, reject){ + mm.addMessageListener("ssler-test:AutoPrefUpdated", function() { + if (Services.prefs.getBoolPref("security.ssl.errorReporting.automatic")) { + resolve(); + } else { + reject(); + } + }); + }); + + mm.sendAsyncMessage("ssler-test:SetAutoPref",{value:true}); + + yield prefEnabled; + + // ensure un-setting automatic, when set, works + let prefDisabled = new Promise(function(resolve, reject){ + mm.addMessageListener("ssler-test:AutoPrefUpdated", function () { + if (!Services.prefs.getBoolPref("security.ssl.errorReporting.automatic")) { + resolve(); + } else { + reject(); + } + }); + }); + + mm.sendAsyncMessage("ssler-test:SetAutoPref",{value:false}); + + yield prefDisabled; + + gBrowser.removeTab(tab); + cleanup(); +}); + +// test that manual report sending (with button clicks) works +let testSendReportManual = Task.async(function*(testURL, suffix) { + setup(); + Services.prefs.setBoolPref("security.ssl.errorReporting.enabled", true); + Services.prefs.setCharPref("security.ssl.errorReporting.url", + "https://example.com/browser/browser/base/content/test/general/pinning_reports.sjs?" + suffix); + + let tab = gBrowser.addTab(testURL, {skipAnimation: true}); + let browser = tab.linkedBrowser; + let mm = browser.messageManager; + + gBrowser.selectedTab = tab; + + // ensure we have the correct error message from about:neterror + let netError = createNetworkErrorMessagePromise(browser); + yield netError; + netError.then(function(val){ + is(val.startsWith("An error occurred during a connection to"), true, + "ensure the correct error message came from about:neterror"); + }); + + // Check the report starts on click + let btn = browser.contentDocument.getElementById("reportCertificateError"); + + // check the content script sends the message to report + let reportWillStart = new Promise(function(resolve, reject){ + mm.addMessageListener("Browser:SendSSLErrorReport", function() { + resolve(); + }); + }); + + let deferredReportActivity = Promise.defer() + let deferredReportSucceeds = Promise.defer(); + + // ensure we see the correct statuses in the correct order... + mm.addMessageListener("ssler-test:SSLErrorReportStatus", function(message) { + switch(message.data.reportStatus) { + case "activity": + deferredReportActivity.resolve(message.data.reportStatus); + break; + case "complete": + deferredReportSucceeds.resolve(message.data.reportStatus); + break; + case "error": + deferredReportSucceeds.reject(); + deferredReportActivity.reject(); + break; + } + }); + + // ... once the button is clicked, that is + mm.sendAsyncMessage("ssler-test:SendBtnClick",{}); + + yield reportWillStart; + + yield deferredReportActivity.promise; + yield deferredReportSucceeds.promise; + + gBrowser.removeTab(tab); + cleanup(); +}); + +// test that automatic sending works +let testSendReportAuto = Task.async(function*() { + setup(); + Services.prefs.setBoolPref("security.ssl.errorReporting.enabled", true); + Services.prefs.setBoolPref("security.ssl.errorReporting.automatic", true); + Services.prefs.setCharPref("security.ssl.errorReporting.url", "https://example.com/browser/browser/base/content/test/general/pinning_reports.sjs?succeed"); + + let tab = gBrowser.addTab(badChainURL, {skipAnimation: true}); + let browser = tab.linkedBrowser; + let mm = browser.messageManager; + + gBrowser.selectedTab = tab; + + let reportWillStart = Promise.defer(); + mm.addMessageListener("Browser:SendSSLErrorReport", function() { + reportWillStart.resolve(); + }); + + let deferredReportActivity = Promise.defer(); + let deferredReportSucceeds = Promise.defer(); + + mm.addMessageListener("ssler-test:SSLErrorReportStatus", function(message) { + switch(message.data.reportStatus) { + case "activity": + deferredReportActivity.resolve(message.data.reportStatus); + break; + case "complete": + deferredReportSucceeds.resolve(message.data.reportStatus); + break; + case "error": + deferredReportSucceeds.reject(); + deferredReportActivity.reject(); + break; + } + }); + + // Ensure the error page loads + let netError = createNetworkErrorMessagePromise(browser); + yield netError; + + // Ensure the reporting steps all occur with no interaction + yield reportWillStart; + yield deferredReportActivity.promise; + yield deferredReportSucceeds.promise; + + gBrowser.removeTab(tab); + cleanup(); +}); + +// test that an error is shown if there's a problem with the report server +let testSendReportError = Task.async(function*() { + setup(); + Services.prefs.setBoolPref("security.ssl.errorReporting.enabled", true); + Services.prefs.setBoolPref("security.ssl.errorReporting.automatic", true); + Services.prefs.setCharPref("security.ssl.errorReporting.url", "https://example.com/browser/browser/base/content/test/general/pinning_reports.sjs?error"); + + let tab = gBrowser.addTab(badChainURL, {skipAnimation: true}); + let browser = tab.linkedBrowser; + let mm = browser.messageManager; + + gBrowser.selectedTab = tab; + + // check the report send starts.... + let reportWillStart = new Promise(function(resolve, reject){ + mm.addMessageListener("Browser:SendSSLErrorReport", function() { + resolve(); + }); + }); + + let netError = createNetworkErrorMessagePromise(browser); + yield netError; + yield reportWillStart; + + // and that errors are seen + let reportErrors = new Promise(function(resolve, reject) { + mm.addMessageListener("ssler-test:SSLErrorReportStatus", function(message) { + switch(message.data.reportStatus) { + case "complete": + reject(message.data.reportStatus); + break; + case "error": + resolve(message.data.reportStatus); + break; + } + }); + }); + + yield reportErrors; + + gBrowser.removeTab(tab); + cleanup(); +}); + +let testSendReportDisabled = Task.async(function*() { + setup(); + Services.prefs.setBoolPref("security.ssl.errorReporting.enabled", false); + Services.prefs.setCharPref("security.ssl.errorReporting.url", "https://offdomain.com"); + + let tab = gBrowser.addTab(badChainURL, {skipAnimation: true}); + let browser = tab.linkedBrowser; + let mm = browser.messageManager; + + gBrowser.selectedTab = tab; + + // Ensure we have an error page + let netError = createNetworkErrorMessagePromise(browser); + yield netError; + + let reportErrors = new Promise(function(resolve, reject) { + mm.addMessageListener("ssler-test:SSLErrorReportStatus", function(message) { + switch(message.data.reportStatus) { + case "complete": + reject(message.data.reportStatus); + break; + case "error": + resolve(message.data.reportStatus); + break; + } + }); + }); + + // click the button + mm.sendAsyncMessage("ssler-test:SendBtnClick",{forceUI:true}); + + // check we get an error + yield reportErrors; + + gBrowser.removeTab(tab); + cleanup(); +}); + +function setup() { + // ensure the relevant prefs are set + enabledPref = Services.prefs.getBoolPref("security.ssl.errorReporting.enabled"); + automaticPref = Services.prefs.getBoolPref("security.ssl.errorReporting.automatic"); + urlPref = Services.prefs.getCharPref("security.ssl.errorReporting.url"); + + enforcement_level = Services.prefs.getIntPref("security.cert_pinning.enforcement_level"); + Services.prefs.setIntPref("security.cert_pinning.enforcement_level", 2); +} + +function cleanup() { + // reset prefs for other tests in the run + Services.prefs.setBoolPref("security.ssl.errorReporting.enabled", enabledPref); + Services.prefs.setBoolPref("security.ssl.errorReporting.automatic", automaticPref); + Services.prefs.setCharPref("security.ssl.errorReporting.url", urlPref); +} diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/base/content/test/general/pinning_reports.sjs thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/base/content/test/general/pinning_reports.sjs --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/base/content/test/general/pinning_reports.sjs 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/base/content/test/general/pinning_reports.sjs 2015-01-09 12:36:28.000000000 +0000 @@ -3,39 +3,67 @@ "MIIC2jCCAcKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAmMSQwIgYDVQQDExtBbHRlcm5hdGUgVHJ1c3RlZCBBdXRob3JpdHkwHhcNMTQwOTI1MjEyMTU0WhcNMjQwOTI1MjEyMTU0WjAmMSQwIgYDVQQDExtBbHRlcm5hdGUgVHJ1c3RlZCBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBT+BwAhO52IWgSIdZZifU9LHOs3IR/+8DCC0WP5d/OuyKlZ6Rqd0tsd3i7durhQyjHSbLf2lJStcnFjcVEbEnNI76RuvlN8xLLn5eV+2Ayr4cZYKztudwRmw+DV/iYAiMSy0hs7m3ssfX7qpoi1aNRjUanwU0VTCPQhF1bEKAC2du+C5Z8e92zN5t87w7bYr7lt+m8197XliXEu+0s9RgnGwGaZ296BIRz6NOoJYTa43n06LU1I1+Z4d6lPdzUFrSR0GBaMhUSurUBtOin3yWiMhg1VHX/KwqGc4als5GyCVXy8HGrA/0zQPOhetxrlhEVAdK/xBt7CZvByj1Rcc7AgMBAAGjEzARMA8GA1UdEwQIMAYBAf8CAQAwDQYJKoZIhvcNAQELBQADggEBAJq/hogSRqzPWTwX4wTn/DVSNdWwFLv53qep9YrSMJ8ZsfbfK9Es4VP4dBLRQAVMJ0Z5mW1I6d/n0KayTanuUBvemYdxPi/qQNSs8UJcllqdhqWzmzAg6a0LxrMnEeKzPBPD6q8PwQ7tYP+B4sBN9tnnsnyPgti9ZiNZn5FwXZliHXseQ7FE9/SqHlLw5LXW3YtKjuti6RmuV6fq3j+D4oeC5vb1mKgIyoTqGN6ze57v8RHi+pQ8Q+kmoUn/L3Z2YmFe4SKN/4WoyXr8TdejpThGOCGCAd3565s5gOx5QfSQX11P8NZKO8hcN0tme3VzmGpHK0Z/6MTmdpNaTwQ6odk=" ]; -function handleRequest(request, response) -{ - if (request.queryString === "succeed") { - // read the report from the client - let inputStream = Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance(Components.interfaces.nsIScriptableInputStream); - inputStream.init(request.bodyInputStream, 0x01, 0004, 0); - - let body = ""; - if (inputStream) { - while (inputStream.available()) { - body = body + inputStream.read(inputStream.available()); - } +function parseReport(request) { + // read the report from the request + let inputStream = Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance(Components.interfaces.nsIScriptableInputStream); + inputStream.init(request.bodyInputStream, 0x01, 0004, 0); + + let body = ""; + if (inputStream) { + while (inputStream.available()) { + body = body + inputStream.read(inputStream.available()); } - // parse the report - let report = JSON.parse(body); - let certChain = report.failedCertChain; - - // ensure the cert chain is what we expect - for (idx in certChain) { - if (certChain[idx] !== EXPECTED_CHAIN[idx]) { - // if the chain differs, send an error response to cause test - // failure + } + // parse the report + return JSON.parse(body); +} + +function handleRequest(request, response) { + let report = {}; + let certChain = []; + + switch (request.queryString) { + case "succeed": + report = parseReport(request); + certChain = report.failedCertChain; + + // ensure the cert chain is what we expect + for (idx in certChain) { + if (certChain[idx] !== EXPECTED_CHAIN[idx]) { + // if the chain differs, send an error response to cause test + // failure + response.setStatusLine("1.1", 500, "Server error"); + response.write("The report contained an unexpected chain"); + return; + } + } + + // if all is as expected, send the 201 the client expects + response.setStatusLine("1.1", 201, "Created"); + response.write("OK"); + break; + case "nocert": + report = parseReport(request); + certChain = report.failedCertChain; + + if (certChain && certChain.length > 0) { + // We're not expecting a chain; if there is one, send an error response.setStatusLine("1.1", 500, "Server error"); response.write("The report contained an unexpected chain"); return; } - } - // if all is as expected, send the 201 the client expects - response.setStatusLine("1.1", 201, "Created"); - response.write("OK"); - } else if (request.queryString === "error") { - response.setStatusLine("1.1", 500, "Server error"); - response.write("server error"); + // if all is as expected, send the 201 the client expects + response.setStatusLine("1.1", 201, "Created"); + response.write("OK"); + break; + case "error": + response.setStatusLine("1.1", 500, "Server error"); + response.write("server error"); + break; + default: + response.setStatusLine("1.1", 500, "Server error"); + response.write("succeed, nocert or error expected"); + break; } } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/components/customizableui/CustomizableWidgets.jsm thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/components/customizableui/CustomizableWidgets.jsm --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/components/customizableui/CustomizableWidgets.jsm 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/components/customizableui/CustomizableWidgets.jsm 2015-01-09 12:36:29.000000000 +0000 @@ -920,7 +920,7 @@ tooltiptext: "email-link-button.tooltiptext3", onCommand: function(aEvent) { let win = aEvent.view; - win.MailIntegration.sendLinkForWindow(win.content); + win.MailIntegration.sendLinkForBrowser(win.gBrowser.selectedBrowser) } }, { id: "loop-button", diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/components/loop/content/js/panel.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/components/loop/content/js/panel.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/components/loop/content/js/panel.js 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/components/loop/content/js/panel.js 2015-01-09 12:36:30.000000000 +0000 @@ -201,13 +201,29 @@ return { seenToS: getPref("seenToS"), - gettingStartedSeen: getPref("gettingStarted.seen") + gettingStartedSeen: getPref("gettingStarted.seen"), + showPartnerLogo: getPref("showPartnerLogo") }; }, + renderPartnerLogo: function() { + if (!this.state.showPartnerLogo) { + return null; + } + + var locale = mozL10n.getLanguage(); + navigator.mozLoop.setLoopPref('showPartnerLogo', false); + return ( + React.createElement("p", {id: "powered-by", className: "powered-by"}, + mozL10n.get("powered_by_beforeLogo"), + React.createElement("img", {id: "powered-by-logo", className: locale}), + mozL10n.get("powered_by_afterLogo") + ) + ); + }, + render: function() { if (!this.state.gettingStartedSeen || this.state.seenToS == "unseen") { - var locale = mozL10n.getLanguage(); var terms_of_use_url = navigator.mozLoop.getLoopPref('legal.ToS_url'); var privacy_notice_url = navigator.mozLoop.getLoopPref('legal.privacy_url'); var tosHTML = mozL10n.get("legal_text_and_links3", { @@ -224,11 +240,7 @@ ), }); return React.createElement("div", {id: "powered-by-wrapper"}, - React.createElement("p", {id: "powered-by"}, - mozL10n.get("powered_by_beforeLogo"), - React.createElement("img", {id: "powered-by-logo", className: locale}), - mozL10n.get("powered_by_afterLogo") - ), + this.renderPartnerLogo(), React.createElement("p", {className: "terms-service", dangerouslySetInnerHTML: {__html: tosHTML}}) ); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/components/loop/content/js/panel.jsx thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/components/loop/content/js/panel.jsx --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/components/loop/content/js/panel.jsx 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/components/loop/content/js/panel.jsx 2015-01-09 12:36:30.000000000 +0000 @@ -201,13 +201,29 @@ return { seenToS: getPref("seenToS"), - gettingStartedSeen: getPref("gettingStarted.seen") + gettingStartedSeen: getPref("gettingStarted.seen"), + showPartnerLogo: getPref("showPartnerLogo") }; }, + renderPartnerLogo: function() { + if (!this.state.showPartnerLogo) { + return null; + } + + var locale = mozL10n.getLanguage(); + navigator.mozLoop.setLoopPref('showPartnerLogo', false); + return ( +

+ {mozL10n.get("powered_by_beforeLogo")} + + {mozL10n.get("powered_by_afterLogo")} +

+ ); + }, + render: function() { if (!this.state.gettingStartedSeen || this.state.seenToS == "unseen") { - var locale = mozL10n.getLanguage(); var terms_of_use_url = navigator.mozLoop.getLoopPref('legal.ToS_url'); var privacy_notice_url = navigator.mozLoop.getLoopPref('legal.privacy_url'); var tosHTML = mozL10n.get("legal_text_and_links3", { @@ -224,11 +240,7 @@ ), }); return
-

- {mozL10n.get("powered_by_beforeLogo")} - - {mozL10n.get("powered_by_afterLogo")} -

+ {this.renderPartnerLogo()}

; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/components/loop/content/shared/js/activeRoomStore.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/components/loop/content/shared/js/activeRoomStore.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/components/loop/content/shared/js/activeRoomStore.js 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/components/loop/content/shared/js/activeRoomStore.js 2015-01-09 12:36:30.000000000 +0000 @@ -203,6 +203,11 @@ * @param {sharedActions.SetupRoomInfo} actionData */ setupRoomInfo: function(actionData) { + if (this._onUpdateListener) { + console.error("Room info already set up!"); + return; + } + this.setStoreState({ roomName: actionData.roomName, roomOwner: actionData.roomOwner, @@ -211,10 +216,11 @@ roomUrl: actionData.roomUrl }); - this._mozLoop.rooms.on("update:" + actionData.roomToken, - this._handleRoomUpdate.bind(this)); - this._mozLoop.rooms.on("delete:" + actionData.roomToken, - this._handleRoomDelete.bind(this)); + this._onUpdateListener = this._handleRoomUpdate.bind(this); + this._onDeleteListener = this._handleRoomDelete.bind(this); + + this._mozLoop.rooms.on("update:" + actionData.roomToken, this._onUpdateListener); + this._mozLoop.rooms.on("delete:" + actionData.roomToken, this._onDeleteListener); }, /** @@ -390,10 +396,16 @@ windowUnload: function() { this._leaveRoom(ROOM_STATES.CLOSING); + if (!this._onUpdateListener) { + return; + } + // If we're closing the window, we can stop listening to updates. var roomToken = this.getStoreState().roomToken; - this._mozLoop.rooms.off("update:" + roomToken); - this._mozLoop.rooms.off("delete:" + roomToken); + this._mozLoop.rooms.off("update:" + roomToken, this._onUpdateListener); + this._mozLoop.rooms.off("delete:" + roomToken, this._onDeleteListener); + delete this._onUpdateListener; + delete this._onDeleteListener; }, /** diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/components/loop/content/shared/js/feedbackViews.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/components/loop/content/shared/js/feedbackViews.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/components/loop/content/shared/js/feedbackViews.js 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/components/loop/content/shared/js/feedbackViews.js 2015-01-09 12:36:30.000000000 +0000 @@ -76,7 +76,7 @@ video_quality: l10n.get("feedback_category_video_quality"), disconnected : l10n.get("feedback_category_was_disconnected"), confusing: l10n.get("feedback_category_confusing"), - other: l10n.get("feedback_category_other") + other: l10n.get("feedback_category_other2") }; }, @@ -119,8 +119,7 @@ handleCategoryChange: function(event) { var category = event.target.value; this.setState({ - category: category, - description: category == "other" ? "" : this._getCategories()[category] + category: category }); if (category == "other") { this.refs.description.getDOMNode().focus(); @@ -131,10 +130,6 @@ this.setState({description: event.target.value}); }, - handleDescriptionFieldFocus: function(event) { - this.setState({category: "other", description: ""}); - }, - handleFormSubmit: function(event) { event.preventDefault(); // XXX this feels ugly, we really want a feedbackActions object here. @@ -146,8 +141,6 @@ }, render: function() { - var descriptionDisplayValue = this.state.category === "other" ? - this.state.description : ""; return ( React.createElement(FeedbackLayout, {title: l10n.get("feedback_what_makes_you_sad"), reset: this.props.reset}, @@ -157,8 +150,7 @@ React.createElement("input", {type: "text", ref: "description", name: "description", className: "feedback-description", onChange: this.handleDescriptionFieldChange, - onFocus: this.handleDescriptionFieldFocus, - value: descriptionDisplayValue, + value: this.state.description, placeholder: l10n.get("feedback_custom_category_text_placeholder")}) ), diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/components/loop/content/shared/js/feedbackViews.jsx thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/components/loop/content/shared/js/feedbackViews.jsx --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/components/loop/content/shared/js/feedbackViews.jsx 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/components/loop/content/shared/js/feedbackViews.jsx 2015-01-09 12:36:30.000000000 +0000 @@ -76,7 +76,7 @@ video_quality: l10n.get("feedback_category_video_quality"), disconnected : l10n.get("feedback_category_was_disconnected"), confusing: l10n.get("feedback_category_confusing"), - other: l10n.get("feedback_category_other") + other: l10n.get("feedback_category_other2") }; }, @@ -119,8 +119,7 @@ handleCategoryChange: function(event) { var category = event.target.value; this.setState({ - category: category, - description: category == "other" ? "" : this._getCategories()[category] + category: category }); if (category == "other") { this.refs.description.getDOMNode().focus(); @@ -131,10 +130,6 @@ this.setState({description: event.target.value}); }, - handleDescriptionFieldFocus: function(event) { - this.setState({category: "other", description: ""}); - }, - handleFormSubmit: function(event) { event.preventDefault(); // XXX this feels ugly, we really want a feedbackActions object here. @@ -146,8 +141,6 @@ }, render: function() { - var descriptionDisplayValue = this.state.category === "other" ? - this.state.description : ""; return ( @@ -157,8 +150,7 @@

diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/components/loop/MozLoopAPI.jsm thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/components/loop/MozLoopAPI.jsm --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/components/loop/MozLoopAPI.jsm 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/components/loop/MozLoopAPI.jsm 2015-01-09 12:36:30.000000000 +0000 @@ -43,13 +43,23 @@ * We can work around this by copying the properties we care about onto a regular * object. * - * @param {Error} error Error object to copy - * @param {nsIDOMWindow} targetWindow The content window to attach the API + * @param {Error|nsIException} error Error object to copy + * @param {nsIDOMWindow} targetWindow The content window to clone into */ const cloneErrorObject = function(error, targetWindow) { let obj = new targetWindow.Error(); - for (let prop of Object.getOwnPropertyNames(error)) { + let props = Object.getOwnPropertyNames(error); + // nsIException properties are not enumerable, so we'll try to copy the most + // common and useful ones. + if (!props.length) { + props.push("message", "filename", "lineNumber", "columnNumber", "stack"); + } + for (let prop of props) { let value = error[prop]; + // for nsIException objects, the property may not be defined. + if (typeof value == "undefined") { + continue; + } if (typeof value != "string" && typeof value != "number") { value = String(value); } @@ -78,6 +88,11 @@ return value; } + // HAWK request errors contain an nsIException object inside `value`. + if (("error" in value) && (value.error instanceof Ci.nsIException)) { + value = value.error; + } + // Strip Function properties, since they can not be cloned across boundaries // like this. for (let prop of Object.getOwnPropertyNames(value)) { @@ -87,7 +102,7 @@ } // Inspect for an error this way, because the Error object is special. - if (value.constructor.name == "Error") { + if (value.constructor.name == "Error" || value instanceof Ci.nsIException) { return cloneErrorObject(value, targetWindow); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/components/loop/standalone/content/l10n/en-US/loop.properties thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/components/loop/standalone/content/l10n/en-US/loop.properties --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/components/loop/standalone/content/l10n/en-US/loop.properties 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/components/loop/standalone/content/l10n/en-US/loop.properties 2015-01-09 12:36:30.000000000 +0000 @@ -74,7 +74,7 @@ feedback_category_video_quality=Video quality feedback_category_was_disconnected=Was disconnected feedback_category_confusing=Confusing -feedback_category_other=Other: +feedback_category_other2=Other feedback_custom_category_text_placeholder=What went wrong? feedback_submit_button=Submit feedback_back_button=Back diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/components/loop/standalone/content/libs/l10n-gaia-02ca67948fe8.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/components/loop/standalone/content/libs/l10n-gaia-02ca67948fe8.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/components/loop/standalone/content/libs/l10n-gaia-02ca67948fe8.js 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/components/loop/standalone/content/libs/l10n-gaia-02ca67948fe8.js 2015-01-09 12:36:31.000000000 +0000 @@ -1241,11 +1241,19 @@ // Getting ready function negotiate(available, requested, defaultLocale) { - if (available.indexOf(requested[0]) === -1 || - requested[0] === defaultLocale) { + var supportedLocale; + for (var i = 0; i < requested.length; ++i) { + var locale = requested[i]; + if (available.indexOf(locale) !== -1) { + supportedLocale = locale; + break; + } + } + if (!supportedLocale || + supportedLocale === defaultLocale) { return [defaultLocale]; } else { - return [requested[0], defaultLocale]; + return [supportedLocale, defaultLocale]; } } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/components/loop/test/desktop-local/panel_test.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/components/loop/test/desktop-local/panel_test.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/components/loop/test/desktop-local/panel_test.js 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/components/loop/test/desktop-local/panel_test.js 2015-01-09 12:36:31.000000000 +0000 @@ -1052,5 +1052,21 @@ TestUtils.findRenderedDOMComponentWithClass(view, "terms-service"); }); + it("should render the telefonica logo after the first time use", + function() { + navigator.mozLoop.getLoopPref = function(key) { + return { + "gettingStarted.seen": false, + "seenToS": "unseen", + "showPartnerLogo": false + }[key]; + }; + + var view = TestUtils.renderIntoDocument( + React.createElement(loop.panel.ToSView)); + + expect(view.getDOMNode().querySelector(".powered-by")).eql(null); + }); + }); }); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/components/loop/test/shared/feedbackViews_test.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/components/loop/test/shared/feedbackViews_test.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/components/loop/test/shared/feedbackViews_test.js 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/components/loop/test/shared/feedbackViews_test.js 2015-01-09 12:36:31.000000000 +0000 @@ -133,16 +133,6 @@ expect(comp.getDOMNode().querySelector("form button").disabled).eql(false); }); - it("should empty the description field when a predefined category is " + - "chosen", - function() { - clickSadFace(comp); - - fillSadFeedbackForm(comp, "confusing"); - - expect(comp.getDOMNode().querySelector(".feedback-description").value).eql(""); - }); - it("should enable the form submit button once a predefined category is " + "chosen", function() { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/components/preferences/cookies.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/components/preferences/cookies.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/components/preferences/cookies.js 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/components/preferences/cookies.js 2015-01-09 12:36:31.000000000 +0000 @@ -555,7 +555,8 @@ let buttonLabel = this._bundle.getString("removeSelectedCookies"); let removeSelectedCookies = document.getElementById("removeSelectedCookies"); - removeSelectedCookies.label = PluralForm.get(selectedCookieCount, buttonLabel); + removeSelectedCookies.label = PluralForm.get(selectedCookieCount, buttonLabel) + .replace("#1", selectedCookieCount); removeSelectedCookies.disabled = !(seln.count > 0); }, diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/devtools/debugger/test/browser_dbg_pretty-print-07.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/devtools/debugger/test/browser_dbg_pretty-print-07.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/devtools/debugger/test/browser_dbg_pretty-print-07.js 2015-01-07 22:15:21.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/devtools/debugger/test/browser_dbg_pretty-print-07.js 2015-01-09 12:36:33.000000000 +0000 @@ -35,8 +35,9 @@ } function testPrettyPrinted({ error, source }) { - ok(!error); - ok(source.contains("\n ")); + ok(!error, "Should not get an error while pretty-printing"); + ok(source.contains("\n "), + "Source should be pretty-printed"); disablePrettyPrint(); } @@ -45,8 +46,9 @@ } function testUgly({ error, source }) { - ok(!error); - ok(!source.contains("\n ")); + ok(!error, "Should not get an error while disabling pretty-printing"); + ok(!source.contains("\n "), + "Source should not be pretty after disabling pretty-printing"); closeDebuggerAndFinish(gPanel); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/devtools/debugger/test/code_math_bogus_map.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/devtools/debugger/test/code_math_bogus_map.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/devtools/debugger/test/code_math_bogus_map.js 2015-01-07 22:15:21.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/devtools/debugger/test/code_math_bogus_map.js 2015-01-09 12:36:34.000000000 +0000 @@ -1,4 +1,4 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ function stopMe(){throw Error("boom");}try{stopMe();var a=1;a=a*2;}catch(e){}; - +//# sourceMappingURL=bogus.map diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/devtools/scratchpad/test/browser_scratchpad_pprint_error_goto_line.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/devtools/scratchpad/test/browser_scratchpad_pprint_error_goto_line.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/devtools/scratchpad/test/browser_scratchpad_pprint_error_goto_line.js 2015-01-07 22:15:21.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/devtools/scratchpad/test/browser_scratchpad_pprint_error_goto_line.js 2015-01-09 12:36:35.000000000 +0000 @@ -15,28 +15,38 @@ openScratchpad(runTests); }, true); - content.location = "data:text/html;charset=utf8,test Scratchpad pretty print error goto line."; + content.location = "data:text/html;charset=utf8," + + "test Scratchpad pretty print error goto line."; } function testJumpToPrettyPrintError(sp, error, remark) { info("will test jumpToLine after prettyPrint error" + remark); - // CodeMirror lines and columns are 0-based, Scratchpad UI and error - // stack are 1-based. - is(/Invalid regexp flag \(3:10\)/.test(error), true, "prettyPrint expects error in editor text:\n" + error); - const errorLine = 3, errorColumn = 10; - const editorDoc = sp.editor.container.contentDocument; - sp.editor.jumpToLine(); - const lineInput = editorDoc.querySelector("input"); - const errorLocation = lineInput.value; - const [ inputLine, inputColumn ] = errorLocation.split(":"); - is(inputLine, errorLine, "jumpToLine input field is set from editor selection (line)"); - is(inputColumn, errorColumn, "jumpToLine input field is set from editor selection (column)"); - EventUtils.synthesizeKey("VK_RETURN", { }, editorDoc.defaultView); - // CodeMirror lines and columns are 0-based, Scratchpad UI and error - // stack are 1-based. - const cursor = sp.editor.getCursor(); - is(inputLine, cursor.line + 1, "jumpToLine goto error location (line)"); - is(inputColumn, cursor.ch + 1, "jumpToLine goto error location (column)"); + + // CodeMirror lines and columns are 0-based, Scratchpad UI and error + // stack are 1-based. + is(/Invalid regular expression flag \(3:10\)/.test(error), true, + "prettyPrint expects error in editor text:\n" + error); + + sp.editor.jumpToLine(); + + const editorDoc = sp.editor.container.contentDocument; + const lineInput = editorDoc.querySelector("input"); + const errorLocation = lineInput.value; + const [ inputLine, inputColumn ] = errorLocation.split(":"); + const errorLine = 3, errorColumn = 10; + + is(inputLine, errorLine, + "jumpToLine input field is set from editor selection (line)"); + is(inputColumn, errorColumn, + "jumpToLine input field is set from editor selection (column)"); + + EventUtils.synthesizeKey("VK_RETURN", { }, editorDoc.defaultView); + + // CodeMirror lines and columns are 0-based, Scratchpad UI and error + // stack are 1-based. + const cursor = sp.editor.getCursor(); + is(inputLine, cursor.line + 1, "jumpToLine goto error location (line)"); + is(inputColumn, cursor.ch + 1, "jumpToLine goto error location (column)"); } function runTests(sw, sp) @@ -49,12 +59,14 @@ "// line 5", "" ].join("\n")); + sp.prettyPrint().then(aFulfill => { ok(false, "Expecting Invalid regexp flag (3:10)"); finish(); }, error => { testJumpToPrettyPrintError(sp, error, " (Bug 1005471, first time)"); }); + sp.prettyPrint().then(aFulfill => { ok(false, "Expecting Invalid regexp flag (3:10)"); finish(); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/devtools/webaudioeditor/test/browser_audionode-actor-get-automation-data-02.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/devtools/webaudioeditor/test/browser_audionode-actor-get-automation-data-02.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/devtools/webaudioeditor/test/browser_audionode-actor-get-automation-data-02.js 2015-01-07 22:15:21.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/devtools/webaudioeditor/test/browser_audionode-actor-get-automation-data-02.js 2015-01-09 12:36:36.000000000 +0000 @@ -13,26 +13,30 @@ get3(front, "create-node") ]); - let t0 = 0, t1 = 0.1, t2 = 0.2, t3 = 0.3, t4 = 0.4, t5 = 0.6, t6 = 0.7, t7 = 1; - yield oscNode.addAutomationEvent("frequency", "setValueAtTime", [0.2, t0]); - yield oscNode.addAutomationEvent("frequency", "setValueAtTime", [0.3, t1]); - yield oscNode.addAutomationEvent("frequency", "setValueAtTime", [0.4, t2]); - yield oscNode.addAutomationEvent("frequency", "linearRampToValueAtTime", [1, t3]); - yield oscNode.addAutomationEvent("frequency", "linearRampToValueAtTime", [0.15, t4]); - yield oscNode.addAutomationEvent("frequency", "exponentialRampToValueAtTime", [0.75, t5]); - yield oscNode.addAutomationEvent("frequency", "exponentialRampToValueAtTime", [0.05, t6]); + yield oscNode.addAutomationEvent("frequency", "setValueAtTime", [300, 0.1]); + yield oscNode.addAutomationEvent("frequency", "linearRampToValueAtTime", [500, 0.4]); + yield oscNode.addAutomationEvent("frequency", "exponentialRampToValueAtTime", [200, 0.6]); // End with a setTargetAtTime event, as the target approaches infinity, which will // give us more points to render than the default 2000 - yield oscNode.addAutomationEvent("frequency", "setTargetAtTime", [1, t7, 0.5]); + yield oscNode.addAutomationEvent("frequency", "setTargetAtTime", [1000, 2, 0.5]); - let { events, values } = yield oscNode.getAutomationData("frequency"); + var { events, values } = yield oscNode.getAutomationData("frequency"); - is(events.length, 8, "8 recorded events returned."); - is(values.length, 4000, "6000 value points returned when ending with exponentiall approaching automator."); + is(events.length, 4, "4 recorded events returned."); + is(values.length, 4000, "4000 value points returned when ending with exponentiall approaching automator."); - checkAutomationValue(values, 1, 0.05); - checkAutomationValue(values, 2, 0.87); - checkAutomationValue(values, 3, 0.98); + checkAutomationValue(values, 2.01, 215.055) + checkAutomationValue(values, 2.1, 345.930); + checkAutomationValue(values, 3, 891.601); + checkAutomationValue(values, 5, 998.01); + + // Refetch the automation data to ensure it recalculates correctly (bug 1118071) + var { events, values } = yield oscNode.getAutomationData("frequency"); + + checkAutomationValue(values, 2.01, 215.055) + checkAutomationValue(values, 2.1, 345.930); + checkAutomationValue(values, 3, 891.601); + checkAutomationValue(values, 5, 998.01); yield removeTab(target.tab); }); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/devtools/webconsole/test/browser_webconsole_bug_599725_response_headers.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/devtools/webconsole/test/browser_webconsole_bug_599725_response_headers.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/devtools/webconsole/test/browser_webconsole_bug_599725_response_headers.js 2015-01-07 22:15:21.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/devtools/webconsole/test/browser_webconsole_bug_599725_response_headers.js 2015-01-09 12:36:36.000000000 +0000 @@ -16,12 +16,6 @@ { let deferred = promise.defer(); - loads++; - ok(aRequest, "page load was logged"); - if (loads != 2) { - return; - } - let headers = null; function readHeader(aName) @@ -64,6 +58,11 @@ function waitForRequest() { let deferred = promise.defer(); HUDService.lastFinishedRequest.callback = (req, console) => { + loads++; + ok(req, "page load was logged"); + if (loads != 2) { + return; + } performTest(req, console).then(deferred.resolve); }; return deferred.promise; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/installer/Makefile.in thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/installer/Makefile.in --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/installer/Makefile.in 2015-01-07 22:15:21.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/installer/Makefile.in 2015-01-09 12:36:37.000000000 +0000 @@ -147,6 +147,14 @@ ifdef CLANG_CL DEFINES += -DCLANG_CL endif +ifeq (x86,$(CPU_ARCH)) +ifdef _MSC_VER +ifndef CLANG_CL +DEFINES += -DWOW_HELPER +endif +endif +endif + libs:: $(MAKE) -C $(DEPTH)/browser/locales langpack diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/installer/package-manifest.in thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/installer/package-manifest.in --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/installer/package-manifest.in 2015-01-07 22:15:21.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/installer/package-manifest.in 2015-01-09 12:36:37.000000000 +0000 @@ -783,6 +783,9 @@ #if defined(MOZ_SANDBOX) #if defined(XP_WIN) @BINPATH@/@DLL_PREFIX@sandboxbroker@DLL_SUFFIX@ +#if defined(WOW_HELPER) +@BINPATH@/wow_helper.exe +#endif #endif #endif @@ -895,13 +898,14 @@ @RESPATH@/components/nsTerminatorTelemetry.js @RESPATH@/components/terminator.manifest -#ifdef MOZ_ASAN -#ifdef CLANG_CXX +#if defined(CLANG_CXX) +#if defined(MOZ_ASAN) || defined(MOZ_TSAN) @BINPATH@/llvm-symbolizer #endif -#ifdef CLANG_CL -@BINPATH@/clang_rt.asan_dynamic-i386.dll #endif + +#if defined(MOZ_ASAN) && defined(CLANG_CL) +@BINPATH@/clang_rt.asan_dynamic-i386.dll #endif diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/locales/en-US/chrome/browser/loop/loop.properties thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/locales/en-US/chrome/browser/loop/loop.properties --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/locales/en-US/chrome/browser/loop/loop.properties 2015-01-07 22:15:22.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/locales/en-US/chrome/browser/loop/loop.properties 2015-01-09 12:36:37.000000000 +0000 @@ -271,7 +271,7 @@ feedback_category_video_quality=Video quality feedback_category_was_disconnected=Was disconnected feedback_category_confusing=Confusing -feedback_category_other=Other: +feedback_category_other2=Other feedback_custom_category_text_placeholder=What went wrong? feedback_submit_button=Submit feedback_back_button=Back diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/locales/en-US/chrome/browser/preferences/cookies.dtd thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/locales/en-US/chrome/browser/preferences/cookies.dtd --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/locales/en-US/chrome/browser/preferences/cookies.dtd 2015-01-07 22:15:22.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/locales/en-US/chrome/browser/preferences/cookies.dtd 2015-01-09 12:36:37.000000000 +0000 @@ -7,6 +7,10 @@ + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/locales/en-US/chrome/browser/preferences/preferences.properties thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/locales/en-US/chrome/browser/preferences/preferences.properties --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/locales/en-US/chrome/browser/preferences/preferences.properties 2015-01-07 22:15:22.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/locales/en-US/chrome/browser/preferences/preferences.properties 2015-01-09 12:36:37.000000000 +0000 @@ -95,6 +95,10 @@ # LOCALIZATION NOTE (removeSelectedCookies): # Semicolon-separated list of plural forms. See: # http://developer.mozilla.org/en/docs/Localization_and_Plurals +# If you need to display the number of selected elements in your language, +# you can use #1 in your localization as a placeholder for the number. +# For example this is the English string with numbers: +# removeSelectedCookied=Remove #1 Selected;Remove #1 Selected removeSelectedCookies=Remove Selected;Remove Selected #### Offline apps diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/themes/osx/customizableui/panelUIOverlay.css thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/themes/osx/customizableui/panelUIOverlay.css --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/themes/osx/customizableui/panelUIOverlay.css 2015-01-07 22:15:22.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/themes/osx/customizableui/panelUIOverlay.css 2015-01-09 12:36:39.000000000 +0000 @@ -177,3 +177,7 @@ width: 32px; height: 32px; } + +toolbarpaletteitem[place="palette"] > .toolbarbutton-1 > .toolbarbutton-menubutton-button { + padding: 3px 1px; +} \ No newline at end of file diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/themes/shared/incontentprefs/preferences.inc.css thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/themes/shared/incontentprefs/preferences.inc.css --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/browser/themes/shared/incontentprefs/preferences.inc.css 2015-01-07 22:15:22.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/browser/themes/shared/incontentprefs/preferences.inc.css 2015-01-09 12:36:39.000000000 +0000 @@ -194,6 +194,10 @@ padding-bottom: 0; /* no padding needed in inContent prefs */ } +#tabsElement { + -moz-margin-end: 4px; /* add the 4px end-margin of other elements */ +} + #encryptionPanel { margin-top: 15px; } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/build/autoconf/toolchain.m4 thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/build/autoconf/toolchain.m4 --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/build/autoconf/toolchain.m4 2015-01-07 22:15:22.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/build/autoconf/toolchain.m4 2015-01-09 12:36:40.000000000 +0000 @@ -15,7 +15,7 @@ #if defined(__clang__) COMPILER clang-cl _MSC_VER #else -COMPILER msvc _MSC_VER +COMPILER msvc _MSC_FULL_VER #endif #elif defined(__clang__) COMPILER clang __clang_major__.__clang_minor__.__clang_patchlevel__ @@ -55,6 +55,13 @@ if test "`echo | $LD -v 2>&1 | grep -c GNU`" != "0"; then GNU_LD=1 fi + +if test "$compiler" = "msvc"; then + MSVC_VERSION_FULL="$CXX_VERSION" + CC_VERSION=`echo ${CC_VERSION} | cut -c 1-4` + CXX_VERSION=`echo ${CXX_VERSION} | cut -c 1-4` +fi + INTEL_CC= INTEL_CXX= if test "$compiler" = "icc"; then @@ -78,9 +85,10 @@ # getting the right version here manually. CC_VERSION=1800 CXX_VERSION=1800 - # Build on clang-cl with MSVC 2013 with fallback emulation. - CFLAGS="$CFLAGS -fmsc-version=1800 -fallback" - CXXFLAGS="$CXXFLAGS -fmsc-version=1800 -fallback" + MSVC_VERSION_FULL=180030723 + # Build on clang-cl with MSVC 2013 Update 3 with fallback emulation. + CFLAGS="$CFLAGS -fms-compatibility-version=18.00.30723 -fallback" + CXXFLAGS="$CXXFLAGS -fms-compatibility-version=18.00.30723 -fallback" fi if test "$GNU_CC"; then diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/build/autoconf/winsdk.m4 thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/build/autoconf/winsdk.m4 --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/build/autoconf/winsdk.m4 2015-01-07 22:15:22.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/build/autoconf/winsdk.m4 2015-01-09 12:36:40.000000000 +0000 @@ -6,32 +6,17 @@ dnl Windows Server 2008 and newer SDKs have WinSDKVer.h, get the version dnl from there AC_DEFUN([MOZ_FIND_WINSDK_VERSION], [ - MOZ_CHECK_HEADERS([winsdkver.h]) - if test "$ac_cv_header_winsdkver_h" = "yes"; then - dnl Get the highest _WIN32_WINNT and NTDDI versions supported - dnl Take the higher of the two - dnl This is done because the Windows 7 beta SDK reports its - dnl NTDDI_MAXVER to be 0x06000100 instead of 0x06010000, as it should - AC_CACHE_CHECK(for highest Windows version supported by this SDK, - ac_cv_winsdk_maxver, - [cat > conftest.h < conftest.h < -#include -#if (NTDDI_VERSION_FROM_WIN32_WINNT(_WIN32_WINNT_MAXVER) > NTDDI_MAXVER) -#define WINSDK_MAXVER NTDDI_VERSION_FROM_WIN32_WINNT(_WIN32_WINNT_MAXVER) -#else -#define WINSDK_MAXVER NTDDI_MAXVER -#endif - -WINSDK_MAXVER +WINVER_MAXVER EOF ac_cv_winsdk_maxver=`$CPP conftest.h 2>/dev/null | tail -n1` rm -f conftest.h ]) - MOZ_WINSDK_MAXVER=${ac_cv_winsdk_maxver} - else - dnl Any SDK which doesn't have WinSDKVer.h is too old. - AC_MSG_ERROR([Your SDK does not have WinSDKVer.h. It is probably too old. Please upgrade to a newer SDK or try running the Windows SDK Configuration Tool and selecting a newer SDK. See https://developer.mozilla.org/En/Windows_SDK_versions for more details on fixing this.]) - fi + dnl WinSDKVer.h returns the version number in 4-digit format while many + dnl consumers expect 8. Therefore, pad the result with an extra 4 zeroes. + MOZ_WINSDK_MAXVER=${ac_cv_winsdk_maxver}0000 ]) diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/build/automation.py.in thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/build/automation.py.in --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/build/automation.py.in 2015-01-07 22:15:22.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/build/automation.py.in 2015-01-09 12:36:40.000000000 +0000 @@ -504,7 +504,6 @@ env['GNOME_DISABLE_CRASH_DIALOG'] = '1' env['XRE_NO_WINDOWS_CRASH_DIALOG'] = '1' - env['NS_TRACE_MALLOC_DISABLE_STACKS'] = '1' # Set WebRTC logging in case it is not set yet env.setdefault('NSPR_LOG_MODULES', 'signaling:5,mtransport:5,datachannel:5,jsep:5,MediaPipelineFactory:5') diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/build/automationutils.py thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/build/automationutils.py --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/build/automationutils.py 2015-01-07 22:15:22.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/build/automationutils.py 2015-01-09 12:36:40.000000000 +0000 @@ -330,7 +330,6 @@ # crashreporter env['GNOME_DISABLE_CRASH_DIALOG'] = '1' env['XRE_NO_WINDOWS_CRASH_DIALOG'] = '1' - env['NS_TRACE_MALLOC_DISABLE_STACKS'] = '1' if crashreporter and not debugger: env['MOZ_CRASHREPORTER_NO_REPORT'] = '1' diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/build/pgo/server-locations.txt thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/build/pgo/server-locations.txt --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/build/pgo/server-locations.txt 2015-01-07 22:15:23.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/build/pgo/server-locations.txt 2015-01-09 12:36:41.000000000 +0000 @@ -20,7 +20,8 @@ # number is the default for the protocol. # # Unrecognized options are ignored. Recognized options are "primary" and -# "privileged", "nocert", "cert=some_cert_nickname", "redir=hostname". +# "privileged", "nocert", "cert=some_cert_nickname", "redir=hostname" and +# "failHandshake". # # "primary" denotes a location which is the canonical location of # the server; this location is the one assumed for requests which don't @@ -32,6 +33,9 @@ # "nocert" makes sense only for https:// hosts and means there is not # any certificate automatically generated for this host. # +# "failHandshake" causes the tls handshake to fail (by sending a client hello to +# the client). +# # "cert=nickname" tells the pgo server to use a particular certificate # for this host. The certificate is referenced by its nickname that must # not contain any spaces. The certificate key files (PKCS12 modules) @@ -227,7 +231,8 @@ https://bad.include-subdomains.pinning-dynamic.example.com:443 privileged,cert=dynamicPinningBad # Host for static pin tests -https://include-subdomains.pinning.example.com:443 privileged,cert=staticPinningBad +https://badchain.include-subdomains.pinning.example.com:443 privileged,cert=staticPinningBad +https://fail-handshake.example.com:443 privileged,failHandshake # Hosts for sha1 console warning tests https://sha1ee.example.com:443 privileged,cert=sha1_end_entity diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/build/stlport/fix-warnings-as-errors.patch thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/build/stlport/fix-warnings-as-errors.patch --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/build/stlport/fix-warnings-as-errors.patch 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/build/stlport/fix-warnings-as-errors.patch 2015-01-09 12:36:41.000000000 +0000 @@ -0,0 +1,70 @@ +# HG changeset patch +# Parent f89b28ea7c7b7fcb54c34e74fcb047626300bfba +# User Dave Hylands +Bug 1073003 - Fix warnings in stlport causing errors in emulator build. + +diff --git a/build/stlport/stlport/stl/_istream.c b/build/stlport/stlport/stl/_istream.c +--- a/build/stlport/stlport/stl/_istream.c ++++ b/build/stlport/stlport/stl/_istream.c +@@ -1140,17 +1140,16 @@ basic_istream<_CharT, _Traits>::ignore(s + template + basic_istream<_CharT, _Traits>& + basic_istream<_CharT, _Traits>::ignore(streamsize __n, int_type __delim) { + sentry __sentry(*this, _No_Skip_WS()); + this->_M_gcount = 0; + + if (__sentry) { + basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); +- typedef _STLP_PRIV _Constant_unary_fun _Const_bool; + typedef _STLP_PRIV _Constant_binary_fun + _Const_streamsize; + const streamsize __maxss = (numeric_limits::max)(); + + if (__n == (numeric_limits::max)()) { + if (__buf->gptr() != __buf->egptr()) + _M_gcount = _M_ignore_buffered(this, __buf, + __maxss, _Const_streamsize(__maxss), +diff --git a/build/stlport/stlport/stl/_slist.c b/build/stlport/stlport/stl/_slist.c +--- a/build/stlport/stlport/stl/_slist.c ++++ b/build/stlport/stlport/stl/_slist.c +@@ -143,17 +143,16 @@ void _Slist_unique(slist<_Tp, _Alloc>& _ + } + } + } + + template + void _Slist_merge(slist<_Tp, _Alloc>& __that, slist<_Tp, _Alloc>& __x, + _StrictWeakOrdering __comp) { + typedef _Slist_node<_Tp> _Node; +- typedef _STLP_PRIV _Slist_node_base _Node_base; + if (__that.get_allocator() == __x.get_allocator()) { + typename slist<_Tp, _Alloc>::iterator __ite(__that.before_begin()); + while (__ite._M_node->_M_next && !__x.empty()) { + if (__comp(__x.front(), __STATIC_CAST(_Node*, __ite._M_node->_M_next)->_M_data)) { + _STLP_VERBOSE_ASSERT(!__comp(__STATIC_CAST(_Node*, __ite._M_node->_M_next)->_M_data, __x.front()), + _StlMsg_INVALID_STRICT_WEAK_PREDICATE) + __that.splice_after(__ite, __x, __x.before_begin()); + } +diff --git a/build/stlport/stlport/stl/config/features.h b/build/stlport/stlport/stl/config/features.h +--- a/build/stlport/stlport/stl/config/features.h ++++ b/build/stlport/stlport/stl/config/features.h +@@ -303,17 +303,18 @@ + # undef _STLP_NO_DEFAULT_NON_TYPE_PARAM + # define _STLP_NO_DEFAULT_NON_TYPE_PARAM 1 + #endif + + #if !defined (_STLP_STATIC_ASSERT) + /* Some compiler support 0 size array so we use negative size array to generate + * a compilation time error. + */ +-# define _STLP_STATIC_ASSERT(expr) typedef char __static_assert[expr ? 1 : -1]; ++//# define _STLP_STATIC_ASSERT(expr) typedef char __static_assert[expr ? 1 : -1]; ++# define _STLP_STATIC_ASSERT(expr) static_assert(expr, "static_assert failed"); + #endif + + /* apple mpw exception handling bug */ + #ifndef _STLP_MPWFIX_TRY + # define _STLP_MPWFIX_TRY + #endif + #ifndef _STLP_MPWFIX_CATCH + # define _STLP_MPWFIX_CATCH diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/build/stlport/moz.build thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/build/stlport/moz.build --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/build/stlport/moz.build 2015-01-07 22:15:23.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/build/stlport/moz.build 2015-01-09 12:36:41.000000000 +0000 @@ -9,9 +9,6 @@ # name for the Library for convenience in moz.build. STATIC_LIBRARY_NAME = 'stlport_static' -if not CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': - OS_LIBS += ['-static-libstdc++'] - FORCE_STATIC_LIB = True SOURCES += [ diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/build/stlport/README.mozilla thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/build/stlport/README.mozilla --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/build/stlport/README.mozilla 2015-01-07 22:15:23.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/build/stlport/README.mozilla 2015-01-09 12:36:41.000000000 +0000 @@ -7,3 +7,6 @@ The following patches are applied on top: - android-mozilla-config.patch: Adjusts Android-specific configuration to the mozilla codebase use of the STL. + +- fix-warnings-as-errors.patch: Fixes warnings which were causing the + B2G emulator-ICS build to fail (related to bug 1073003). diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/build/stlport/stlport/stl/config/features.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/build/stlport/stlport/stl/config/features.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/build/stlport/stlport/stl/config/features.h 2015-01-07 22:15:23.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/build/stlport/stlport/stl/config/features.h 2015-01-09 12:36:41.000000000 +0000 @@ -308,7 +308,8 @@ /* Some compiler support 0 size array so we use negative size array to generate * a compilation time error. */ -# define _STLP_STATIC_ASSERT(expr) typedef char __static_assert[expr ? 1 : -1]; +//# define _STLP_STATIC_ASSERT(expr) typedef char __static_assert[expr ? 1 : -1]; +# define _STLP_STATIC_ASSERT(expr) static_assert(expr, "static_assert failed"); #endif /* apple mpw exception handling bug */ diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/build/stlport/stlport/stl/_istream.c thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/build/stlport/stlport/stl/_istream.c --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/build/stlport/stlport/stl/_istream.c 2015-01-07 22:15:23.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/build/stlport/stlport/stl/_istream.c 2015-01-09 12:36:41.000000000 +0000 @@ -1145,7 +1145,6 @@ if (__sentry) { basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); - typedef _STLP_PRIV _Constant_unary_fun _Const_bool; typedef _STLP_PRIV _Constant_binary_fun _Const_streamsize; const streamsize __maxss = (numeric_limits::max)(); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/build/stlport/stlport/stl/_slist.c thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/build/stlport/stlport/stl/_slist.c --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/build/stlport/stlport/stl/_slist.c 2015-01-07 22:15:23.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/build/stlport/stlport/stl/_slist.c 2015-01-09 12:36:41.000000000 +0000 @@ -148,7 +148,6 @@ void _Slist_merge(slist<_Tp, _Alloc>& __that, slist<_Tp, _Alloc>& __x, _StrictWeakOrdering __comp) { typedef _Slist_node<_Tp> _Node; - typedef _STLP_PRIV _Slist_node_base _Node_base; if (__that.get_allocator() == __x.get_allocator()) { typename slist<_Tp, _Alloc>::iterator __ite(__that.before_begin()); while (__ite._M_node->_M_next && !__x.empty()) { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/CLOBBER thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/CLOBBER --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/CLOBBER 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/CLOBBER 2015-01-09 12:36:23.000000000 +0000 @@ -22,4 +22,4 @@ # changes to stick? As of bug 928195, this shouldn't be necessary! Please # don't change CLOBBER for WebIDL changes any more. -Bug 1066383 - Clobber needed due to build system not reliably picking up an IDL removal. +Bug 1056337 - Change default compiler for B2G ICS builds. diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/config/config.mk thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/config/config.mk --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/config/config.mk 2015-01-07 22:15:23.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/config/config.mk 2015-01-09 12:36:41.000000000 +0000 @@ -228,17 +228,17 @@ endif # -# Handle trace-malloc and DMD in optimized builds. +# Handle DMD in optimized builds. # No opt to give sane callstacks. # -ifneq (,$(NS_TRACE_MALLOC)$(MOZ_DMD)) +ifdef MOZ_DMD MOZ_OPTIMIZE_FLAGS=-Zi -Od -UDEBUG -DNDEBUG ifdef HAVE_64BIT_BUILD OS_LDFLAGS = -DEBUG -OPT:REF,ICF else OS_LDFLAGS = -DEBUG -OPT:REF endif -endif # NS_TRACE_MALLOC || MOZ_DMD +endif # MOZ_DMD endif # MOZ_DEBUG @@ -421,20 +421,20 @@ #//------------------------------------------------------------------------ ifdef USE_STATIC_LIBS RTL_FLAGS=-MT # Statically linked multithreaded RTL -ifneq (,$(MOZ_DEBUG)$(NS_TRACE_MALLOC)) +ifdef MOZ_DEBUG ifndef MOZ_NO_DEBUG_RTL RTL_FLAGS=-MTd # Statically linked multithreaded MSVC4.0 debug RTL endif -endif # MOZ_DEBUG || NS_TRACE_MALLOC +endif # MOZ_DEBUG else # !USE_STATIC_LIBS RTL_FLAGS=-MD # Dynamically linked, multithreaded RTL -ifneq (,$(MOZ_DEBUG)$(NS_TRACE_MALLOC)) +ifdef MOZ_DEBUG ifndef MOZ_NO_DEBUG_RTL RTL_FLAGS=-MDd # Dynamically linked, multithreaded MSVC4.0 debug RTL endif -endif # MOZ_DEBUG || NS_TRACE_MALLOC +endif # MOZ_DEBUG endif # USE_STATIC_LIBS endif # WINNT && !GNU_CC diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/configure.in thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/configure.in --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/configure.in 2015-01-07 22:15:23.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/configure.in 2015-01-09 12:36:42.000000000 +0000 @@ -415,30 +415,27 @@ MOZ_METRO=) if test -n "$MOZ_METRO"; then AC_DEFINE(MOZ_METRO) - # Target the Windows 8 Kit - WINSDK_TARGETVER=602 - WINVER=502 # toolkit/library/makefile.in needs these, see nsDllMain. CRTDLLVERSION=110 CRTEXPDLLVERSION=1-1-0 -else - # Target the Windows 7 SDK by default - WINSDK_TARGETVER=601 - WINVER=502 fi AC_SUBST(CRTDLLVERSION) AC_SUBST(CRTEXPDLLVERSION) +# Target the Windows 8.1 SDK by default +WINSDK_TARGETVER=603 +WINVER=502 + MOZ_ARG_WITH_STRING(windows-version, [ --with-windows-version=WINSDK_TARGETVER - Windows SDK version to target. Lowest version - currently allowed is 601 (Win7), highest is 602 (Win8)], + Windows SDK version to target. Win8.1 (603) is + currently the minimum supported version.], WINSDK_TARGETVER=$withval) -# Currently only two sdk versions allowed, 601 and 602 +# Currently only version 603 is allowed case "$WINSDK_TARGETVER" in -601|602) +603) MOZ_WINSDK_TARGETVER=0${WINSDK_TARGETVER}0000 ;; @@ -474,8 +471,9 @@ changequote([,]) # Determine compiler version - _CC_MAJOR_VERSION=`echo ${CC_VERSION} | cut -c 1-2` - _CC_MINOR_VERSION=`echo ${CC_VERSION} | cut -c 3-4` + _CC_MAJOR_VERSION=`echo ${MSVC_VERSION_FULL} | cut -c 1-2` + _CC_MINOR_VERSION=`echo ${MSVC_VERSION_FULL} | cut -c 3-4` + _CC_BUILD_VERSION=`echo ${MSVC_VERSION_FULL} | cut -c 5-` _MSC_VER=${CC_VERSION} _CXX_MAJOR_VERSION=`echo ${CXX_VERSION} | cut -c 1-2` @@ -487,13 +485,15 @@ AC_DEFINE(_CRT_SECURE_NO_WARNINGS) AC_DEFINE(_CRT_NONSTDC_NO_WARNINGS) - if test "$_CC_MAJOR_VERSION" = "18"; then + if test "$_CC_MAJOR_VERSION" = "18" -a "$_CC_BUILD_VERSION" -ge "30723"; then _CC_SUITE=12 MSVS_VERSION=2013 MSVC_C_RUNTIME_DLL=msvcr120.dll MSVC_CXX_RUNTIME_DLL=msvcp120.dll else - AC_MSG_ERROR([This version ($CC_VERSION) of the MSVC compiler is unsupported. See https://developer.mozilla.org/en/Windows_Build_Prerequisites.]) + AC_MSG_ERROR([This version (${_CC_MAJOR_VERSION}.${_CC_MINOR_VERSION}.${_CC_BUILD_VERSION}) of the MSVC compiler is unsupported. +You must install Visual C++ 2013 Update 3 or newer in order to build. +See https://developer.mozilla.org/en/Windows_Build_Prerequisites.]) fi AC_SUBST(MSVS_VERSION) AC_SUBST(MSVC_C_RUNTIME_DLL) @@ -685,7 +685,7 @@ # causing problems with local implementations with the same name. AC_DEFINE(STRSAFE_NO_DEPRECATE) - MOZ_WINSDK_MAXVER=0x06020000 + MOZ_WINSDK_MAXVER=0x06030000 fi # !GNU_CC AC_DEFINE_UNQUOTED(WINVER,0x$WINVER) @@ -5880,10 +5880,6 @@ MOZ_D3DCOMPILER_VISTA_DLL=d3dcompiler_47.dll AC_MSG_RESULT([Found D3D compiler in Windows SDK 8.1.]) ;; - 0x0602*) - MOZ_D3DCOMPILER_VISTA_DLL=d3dcompiler_46.dll - AC_MSG_RESULT([Found D3D compiler in Windows SDK 8.0.]) - ;; esac if test -n "$MOZ_D3DCOMPILER_VISTA_DLL"; then @@ -6032,15 +6028,6 @@ MOZ_GAMEPAD_BACKEND=cocoa ;; WINNT) - case "$MOZ_WINSDK_MAXVER" in - # We support building with the Windows 7 SDK otherwise, but - # Gamepad support requires the Windows 8 SDK for some HID headers. - 0x0601*) - AC_MSG_ERROR([The Windows 8 SDK or newer is required to build Gamepad support. Please install a newer Windows SDK or reconfigure with --disable-gamepad to disable gamepad support.]) - ;; - *) - ;; - esac MOZ_GAMEPAD_BACKEND=windows ;; Linux) @@ -7063,21 +7050,6 @@ fi dnl ======================================================== -dnl = Enable trace malloc -dnl ======================================================== -NS_TRACE_MALLOC=${MOZ_TRACE_MALLOC} -MOZ_ARG_ENABLE_BOOL(trace-malloc, -[ --enable-trace-malloc Enable malloc tracing; also disables DMD and jemalloc], - NS_TRACE_MALLOC=1, - NS_TRACE_MALLOC= ) -if test "$NS_TRACE_MALLOC"; then - # Please, Mr. Linker Man, don't take away our symbol names - MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS= - AC_DEFINE(NS_TRACE_MALLOC) -fi -AC_SUBST(NS_TRACE_MALLOC) - -dnl ======================================================== dnl = Enable DMD dnl ======================================================== @@ -7086,11 +7058,6 @@ MOZ_DMD=1, MOZ_DMD= ) -dnl The two options are conflicting. Fails the configure to alert the user. -if test "$NS_TRACE_MALLOC" -a "$MOZ_DMD"; then - AC_MSG_ERROR([--enable-trace-malloc and --enable-dmd are conflicting options]) -fi - if test "$MOZ_DMD"; then AC_DEFINE(MOZ_DMD) @@ -7112,10 +7079,6 @@ MOZ_MEMORY=1, MOZ_MEMORY=) -if test "$NS_TRACE_MALLOC"; then - MOZ_MEMORY= -fi - case "${OS_TARGET}" in Android|WINNT|Darwin) MOZ_GLUE_IN_PROGRAM= @@ -7138,11 +7101,6 @@ MOZ_REPLACE_MALLOC=1, MOZ_REPLACE_MALLOC= ) -dnl The two options are conflicting. Fails the configure to alert the user. -if test "$NS_TRACE_MALLOC" -a "$MOZ_REPLACE_MALLOC"; then - AC_MSG_ERROR([--enable-trace-malloc and --enable-replace-malloc are conflicting options]) -fi - if test -n "$MOZ_REPLACE_MALLOC" -a -z "$MOZ_MEMORY"; then dnl We don't want to enable jemalloc unconditionally because it may be a dnl deliberate choice not to enable it (bug 702250, for instance) @@ -7617,9 +7575,9 @@ AC_LANG_RESTORE fi -# Demangle only for debug or trace-malloc or DMD builds +# Demangle only for debug or DMD builds MOZ_DEMANGLE_SYMBOLS= -if test "$HAVE_DEMANGLE" && test "$MOZ_DEBUG" -o "$NS_TRACE_MALLOC" -o "$MOZ_DMD"; then +if test "$HAVE_DEMANGLE" && test "$MOZ_DEBUG" -o "$MOZ_DMD"; then MOZ_DEMANGLE_SYMBOLS=1 AC_DEFINE(MOZ_DEMANGLE_SYMBOLS) fi @@ -7977,13 +7935,6 @@ dnl Graphics checks. dnl ======================================================== -if test "${OS_TARGET}" = "WINNT"; then - if $PERL -e "exit($MOZ_WINSDK_MAXVER < 0x06020000)"; then - MOZ_ENABLE_DIRECT2D1_1=1 - AC_SUBST(MOZ_ENABLE_DIRECT2D1_1) - fi -fi - if test "${OS_TARGET}" = "WINNT" -o \ "${OS_ARCH}" = "Darwin" -o \ "${MOZ_WIDGET_TOOLKIT}" = "android" -o \ @@ -8158,17 +8109,12 @@ QUARTZ_FONT_FEATURE="#define CAIRO_HAS_QUARTZ_FONT 1" ;; windows) - WIN32_SURFACE_FEATURE="#define CAIRO_HAS_WIN32_SURFACE 1" + WIN32_D2D_SURFACE_FEATURE="#define CAIRO_HAS_D2D_SURFACE 1" + WIN32_DWRITE_FONT_FEATURE="#define CAIRO_HAS_DWRITE_FONT 1" WIN32_FONT_FEATURE="#define CAIRO_HAS_WIN32_FONT 1" - if test "$MOZ_WINSDK_TARGETVER" -ge "06010000"; then - WIN32_DWRITE_FONT_FEATURE="#define CAIRO_HAS_DWRITE_FONT 1" - WIN32_D2D_SURFACE_FEATURE="#define CAIRO_HAS_D2D_SURFACE 1" - MOZ_ENABLE_D2D_SURFACE=1 - MOZ_ENABLE_DWRITE_FONT=1 - else - WIN32_DWRITE_FONT_FEATURE= - WIN32_D2D_SURFACE_FEATURE= - fi + WIN32_SURFACE_FEATURE="#define CAIRO_HAS_WIN32_SURFACE 1" + MOZ_ENABLE_D2D_SURFACE=1 + MOZ_ENABLE_DWRITE_FONT=1 MOZ_CHECK_HEADER(d3d9.h, MOZ_ENABLE_D3D9_LAYER=1) @@ -8451,7 +8397,7 @@ fi dnl ======================================================== -if test "$MOZ_DEBUG" -o "$NS_TRACE_MALLOC" -o "$MOZ_DMD"; then +if test "$MOZ_DEBUG" -o "$MOZ_DMD"; then MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS= fi @@ -9024,7 +8970,8 @@ # B2G: bug 866301 if test "$MOZ_WIDGET_TOOLKIT" = "android" || - test "$MOZ_BUILD_APP" = "b2g"; then + test "$MOZ_BUILD_APP" = "b2g" || + test "$MOZ_BUILD_APP" = "b2g/dev"; then _INTL_API=no else _INTL_API=yes diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/docshell/base/LoadInfo.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/docshell/base/LoadInfo.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/docshell/base/LoadInfo.cpp 2015-01-07 22:15:23.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/docshell/base/LoadInfo.cpp 2015-01-09 12:36:43.000000000 +0000 @@ -28,6 +28,8 @@ , mSecurityFlags(aSecurityFlags) , mContentPolicyType(aContentPolicyType) , mBaseURI(aBaseURI) + , mInnerWindowID(aLoadingContext ? + aLoadingContext->OwnerDoc()->InnerWindowID() : 0) { MOZ_ASSERT(mLoadingPrincipal); MOZ_ASSERT(mTriggeringPrincipal); @@ -43,6 +45,21 @@ } } +LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, + nsIPrincipal* aTriggeringPrincipal, + nsSecurityFlags aSecurityFlags, + nsContentPolicyType aContentPolicyType, + uint32_t aInnerWindowID) + : mLoadingPrincipal(aLoadingPrincipal) + , mTriggeringPrincipal(aTriggeringPrincipal) + , mSecurityFlags(aSecurityFlags) + , mContentPolicyType(aContentPolicyType) + , mInnerWindowID(aInnerWindowID) +{ + MOZ_ASSERT(mLoadingPrincipal); + MOZ_ASSERT(mTriggeringPrincipal); +} + LoadInfo::~LoadInfo() { } @@ -135,4 +152,11 @@ return mBaseURI; } +NS_IMETHODIMP +LoadInfo::GetInnerWindowID(uint32_t* outInnerWindowID) +{ + *outInnerWindowID = mInnerWindowID; + return NS_OK; +} + } // namespace mozilla diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/docshell/base/LoadInfo.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/docshell/base/LoadInfo.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/docshell/base/LoadInfo.h 2015-01-07 22:15:23.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/docshell/base/LoadInfo.h 2015-01-09 12:36:43.000000000 +0000 @@ -17,6 +17,11 @@ namespace mozilla { +namespace net { +class HttpChannelParent; +class FTPChannelParent; +} + /** * Class that provides an nsILoadInfo implementation. */ @@ -35,6 +40,18 @@ nsIURI* aBaseURI = nullptr); private: + // private constructor that is only allowed to be called from within + // HttpChannelParent and FTPChannelParent declared as friends undeneath. + // In e10s we can not serialize nsINode, hence we store the innerWindowID. + LoadInfo(nsIPrincipal* aLoadingPrincipal, + nsIPrincipal* aTriggeringPrincipal, + nsSecurityFlags aSecurityFlags, + nsContentPolicyType aContentPolicyType, + uint32_t aInnerWindowID); + + friend class net::HttpChannelParent; + friend class net::FTPChannelParent; + ~LoadInfo(); nsCOMPtr mLoadingPrincipal; @@ -43,6 +60,7 @@ nsSecurityFlags mSecurityFlags; nsContentPolicyType mContentPolicyType; nsCOMPtr mBaseURI; + uint32_t mInnerWindowID; }; } // namespace mozilla diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/docshell/base/nsILoadInfo.idl thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/docshell/base/nsILoadInfo.idl --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/docshell/base/nsILoadInfo.idl 2015-01-07 22:15:23.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/docshell/base/nsILoadInfo.idl 2015-01-09 12:36:43.000000000 +0000 @@ -180,4 +180,24 @@ */ [noscript, notxpcom, nostdcall, binaryname(BaseURI)] nsIURI binaryBaseURI(); + + /** + * The innerWindowId of the loadingDocument, used to identify + * the loadingDocument in e10s where the loadingDocument is + * not available. + * + * Warning: If the loadingDocument is null, then the + * innerWindowId is 0. + */ + readonly attribute unsigned long innerWindowID; + +%{ C++ + inline uint32_t GetInnerWindowID() + { + uint32_t result; + mozilla::DebugOnly rv = GetInnerWindowID(&result); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + return result; + } +%} }; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/alarm/AlarmHalService.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/alarm/AlarmHalService.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/alarm/AlarmHalService.h 2015-01-07 22:15:23.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/alarm/AlarmHalService.h 2015-01-09 12:36:43.000000000 +0000 @@ -34,10 +34,10 @@ static already_AddRefed GetInstance(); // Implementing hal::AlarmObserver - void Notify(const void_t& aVoid); + void Notify(const void_t& aVoid) MOZ_OVERRIDE; // Implementing hal::SystemTimezoneChangeObserver - void Notify(const hal::SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo); + void Notify(const hal::SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo) MOZ_OVERRIDE; private: virtual ~AlarmHalService(); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/base/nsContentList.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/base/nsContentList.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/base/nsContentList.cpp 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/base/nsContentList.cpp 2015-01-09 12:36:44.000000000 +0000 @@ -230,9 +230,7 @@ // A PL_DHASH_ADD is equivalent to a PL_DHASH_LOOKUP for cases // when the entry is already in the hashtable. entry = static_cast - (PL_DHashTableOperate(&gContentListHashTable, - &hashKey, - PL_DHASH_ADD)); + (PL_DHashTableAdd(&gContentListHashTable, &hashKey)); if (entry) list = entry->mContentList; } @@ -346,9 +344,8 @@ // A PL_DHASH_ADD is equivalent to a PL_DHASH_LOOKUP for cases // when the entry is already in the hashtable. entry = static_cast - (PL_DHashTableOperate(&gFuncStringContentListHashTable, - &hashKey, - PL_DHASH_ADD)); + (PL_DHashTableAdd(&gFuncStringContentListHashTable, + &hashKey)); if (entry) { list = entry->mContentList; #ifdef DEBUG @@ -989,9 +986,7 @@ if (!gContentListHashTable.ops) return; - PL_DHashTableOperate(&gContentListHashTable, - &key, - PL_DHASH_REMOVE); + PL_DHashTableRemove(&gContentListHashTable, &key); if (gContentListHashTable.EntryCount() == 0) { PL_DHashTableFinish(&gContentListHashTable); @@ -1032,9 +1027,7 @@ } nsFuncStringCacheKey key(mRootNode, mFunc, mString); - PL_DHashTableOperate(&gFuncStringContentListHashTable, - &key, - PL_DHASH_REMOVE); + PL_DHashTableRemove(&gFuncStringContentListHashTable, &key); if (gFuncStringContentListHashTable.EntryCount() == 0) { PL_DHashTableFinish(&gFuncStringContentListHashTable); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/base/nsContentUtils.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/base/nsContentUtils.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/base/nsContentUtils.cpp 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/base/nsContentUtils.cpp 2015-01-09 12:36:44.000000000 +0000 @@ -3954,8 +3954,7 @@ EventListenerManagerMapEntry *entry = static_cast - (PL_DHashTableOperate(&sEventListenerManagersHash, aNode, - PL_DHASH_LOOKUP)); + (PL_DHashTableLookup(&sEventListenerManagersHash, aNode)); if (PL_DHASH_ENTRY_IS_BUSY(entry)) { CycleCollectionNoteChild(cb, entry->mListenerManager.get(), "[via hash] mListenerManager"); @@ -3974,8 +3973,7 @@ EventListenerManagerMapEntry *entry = static_cast - (PL_DHashTableOperate(&sEventListenerManagersHash, aNode, - PL_DHASH_ADD)); + (PL_DHashTableAdd(&sEventListenerManagersHash, aNode)); if (!entry) { return nullptr; @@ -4006,8 +4004,7 @@ EventListenerManagerMapEntry *entry = static_cast - (PL_DHashTableOperate(&sEventListenerManagersHash, aNode, - PL_DHASH_LOOKUP)); + (PL_DHashTableLookup(&sEventListenerManagersHash, aNode)); if (PL_DHASH_ENTRY_IS_BUSY(entry)) { return entry->mListenerManager; } @@ -4022,8 +4019,7 @@ if (sEventListenerManagersHash.ops) { EventListenerManagerMapEntry *entry = static_cast - (PL_DHashTableOperate(&sEventListenerManagersHash, aNode, - PL_DHASH_LOOKUP)); + (PL_DHashTableLookup(&sEventListenerManagersHash, aNode)); if (PL_DHASH_ENTRY_IS_BUSY(entry)) { nsRefPtr listenerManager; listenerManager.swap(entry->mListenerManager); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/base/nsDocument.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/base/nsDocument.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/base/nsDocument.cpp 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/base/nsDocument.cpp 2015-01-09 12:36:44.000000000 +0000 @@ -3282,6 +3282,15 @@ return undoManager.forget(); } +bool +nsDocument::IsWebAnimationsEnabled(JSContext* /*unused*/, JSObject* /*unused*/) +{ + MOZ_ASSERT(NS_IsMainThread()); + + return nsContentUtils::IsCallerChrome() || + Preferences::GetBool("dom.animations-api.core.enabled"); +} + AnimationTimeline* nsDocument::Timeline() { @@ -3951,8 +3960,7 @@ if (mSubDocuments) { SubDocMapEntry *entry = static_cast - (PL_DHashTableOperate(mSubDocuments, aElement, - PL_DHASH_LOOKUP)); + (PL_DHashTableLookup(mSubDocuments, aElement)); if (PL_DHASH_ENTRY_IS_BUSY(entry)) { PL_DHashTableRawRemove(mSubDocuments, entry); @@ -3984,8 +3992,7 @@ // Add a mapping to the hash table SubDocMapEntry *entry = static_cast - (PL_DHashTableOperate(mSubDocuments, aElement, - PL_DHASH_ADD)); + (PL_DHashTableAdd(mSubDocuments, aElement)); if (!entry) { return NS_ERROR_OUT_OF_MEMORY; @@ -4013,8 +4020,7 @@ if (mSubDocuments && aContent->IsElement()) { SubDocMapEntry *entry = static_cast - (PL_DHashTableOperate(mSubDocuments, aContent->AsElement(), - PL_DHASH_LOOKUP)); + (PL_DHashTableLookup(mSubDocuments, aContent->AsElement())); if (PL_DHASH_ENTRY_IS_BUSY(entry)) { return entry->mSubDocument; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/base/nsDocument.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/base/nsDocument.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/base/nsDocument.h 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/base/nsDocument.h 2015-01-09 12:36:44.000000000 +0000 @@ -782,6 +782,7 @@ virtual already_AddRefed GetUndoManager() MOZ_OVERRIDE; + static bool IsWebAnimationsEnabled(JSContext* aCx, JSObject* aObject); virtual mozilla::dom::AnimationTimeline* Timeline() MOZ_OVERRIDE; virtual nsresult SetSubDocumentFor(Element* aContent, diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/base/nsDOMWindowUtils.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/base/nsDOMWindowUtils.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/base/nsDOMWindowUtils.cpp 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/base/nsDOMWindowUtils.cpp 2015-01-09 12:36:44.000000000 +0000 @@ -511,6 +511,27 @@ } NS_IMETHODIMP +nsDOMWindowUtils::SetResolutionAndScaleTo(float aXResolution, float aYResolution) +{ + if (!nsContentUtils::IsCallerChrome()) { + return NS_ERROR_DOM_SECURITY_ERR; + } + + nsIPresShell* presShell = GetPresShell(); + if (!presShell) { + return NS_ERROR_FAILURE; + } + + nsIScrollableFrame* sf = presShell->GetRootScrollFrameAsScrollable(); + if (sf) { + sf->SetResolutionAndScaleTo(gfxSize(aXResolution, aYResolution)); + presShell->SetResolutionAndScaleTo(aXResolution, aYResolution); + } + + return NS_OK; +} + +NS_IMETHODIMP nsDOMWindowUtils::GetResolution(float* aXResolution, float* aYResolution) { MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome()); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/base/nsIContentPolicy.idl thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/base/nsIContentPolicy.idl --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/base/nsIContentPolicy.idl 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/base/nsIContentPolicy.idl 2015-01-09 12:36:45.000000000 +0000 @@ -33,7 +33,13 @@ const nsContentPolicyType TYPE_INVALID = 0; /** - * Gecko/Firefox developers: Do not use TYPE_OTHER under any circumstances. + * Gecko/Firefox developers: Avoid using TYPE_OTHER. Especially for + * requests that are coming from webpages. Or requests in general which + * you expect that security checks will be done on. + * Always use a more specific type if one is available. And do not hesitate + * to add more types as appropriate. + * But if you are fairly sure that no one would care about your more specific + * type, then it's ok to use TYPE_OTHER. * * Extension developers: Whenever it is reasonable, use one of the existing * content types. If none of the existing content types are right for diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/base/nsIXMLHttpRequest.idl thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/base/nsIXMLHttpRequest.idl --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/base/nsIXMLHttpRequest.idl 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/base/nsIXMLHttpRequest.idl 2015-01-09 12:36:45.000000000 +0000 @@ -8,6 +8,7 @@ interface nsIChannel; interface nsIDOMDocument; interface nsIDOMEventListener; +interface nsILoadGroup; interface nsIPrincipal; interface nsIScriptContext; interface nsIURI; @@ -67,7 +68,7 @@ * you're aware of all the security implications. And then think twice about * it. */ -[scriptable, uuid(2e91e088-e9fa-4ba4-9887-2a0b7cf27a3e)] +[scriptable, uuid(704e91dc-a3f6-4e4d-9f5f-4bb85159aeb7)] interface nsIXMLHttpRequest : nsISupports { /** @@ -295,11 +296,15 @@ * document. * @param baseURI The base URI to use when resolving relative URIs. May be * null. + * @param loadGroup An optional load group to use when performing the request. + * This will be used even if the global has a window with a + * load group. */ [noscript] void init(in nsIPrincipal principal, in nsIScriptContext scriptContext, in nsIGlobalObject globalObject, - in nsIURI baseURI); + in nsIURI baseURI, + [optional] in nsILoadGroup loadGroup); /** * Upload process can be tracked by adding event listener to |upload|. diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/base/nsJSEnvironment.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/base/nsJSEnvironment.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/base/nsJSEnvironment.cpp 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/base/nsJSEnvironment.cpp 2015-01-09 12:36:45.000000000 +0000 @@ -185,7 +185,6 @@ static uint32_t sPreviousSuspectedCount = 0; static uint32_t sCleanupsSinceLastGC = UINT32_MAX; static bool sNeedsFullCC = false; -static bool sNeedsFullGC = false; static bool sNeedsGCAfterCC = false; static bool sIncrementalCC = false; static bool sDidPaintAfterPreviousICCSlice = false; @@ -1087,177 +1086,6 @@ return NS_OK; } -#ifdef NS_TRACE_MALLOC - -#include // XXX assume Linux if NS_TRACE_MALLOC -#include -#ifdef XP_UNIX -#include -#endif -#ifdef XP_WIN32 -#include -#endif -#include "nsTraceMalloc.h" - -static bool -CheckUniversalXPConnectForTraceMalloc(JSContext *cx) -{ - if (nsContentUtils::IsCallerChrome()) - return true; - JS_ReportError(cx, "trace-malloc functions require UniversalXPConnect"); - return false; -} - -static bool -TraceMallocDisable(JSContext *cx, unsigned argc, JS::Value *vp) -{ - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); - - if (!CheckUniversalXPConnectForTraceMalloc(cx)) - return false; - - NS_TraceMallocDisable(); - args.rval().setUndefined(); - return true; -} - -static bool -TraceMallocEnable(JSContext *cx, unsigned argc, JS::Value *vp) -{ - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); - - if (!CheckUniversalXPConnectForTraceMalloc(cx)) - return false; - - NS_TraceMallocEnable(); - args.rval().setUndefined(); - return true; -} - -static bool -TraceMallocOpenLogFile(JSContext *cx, unsigned argc, JS::Value *vp) -{ - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); - - if (!CheckUniversalXPConnectForTraceMalloc(cx)) - return false; - - int fd; - if (argc == 0) { - fd = -1; - } else { - JSString *str = JS::ToString(cx, args[0]); - if (!str) - return false; - JSAutoByteString filename(cx, str); - if (!filename) - return false; - fd = open(filename.ptr(), O_CREAT | O_WRONLY | O_TRUNC, 0644); - if (fd < 0) { - JS_ReportError(cx, "can't open %s: %s", filename.ptr(), strerror(errno)); - return false; - } - } - args.rval().setInt32(fd); - return true; -} - -static bool -TraceMallocChangeLogFD(JSContext *cx, unsigned argc, JS::Value *vp) -{ - JS::CallArgs args = CallArgsFromVp(argc, vp); - - if (!CheckUniversalXPConnectForTraceMalloc(cx)) - return false; - - int32_t fd, oldfd; - if (args.length() == 0) { - oldfd = -1; - } else { - if (!JS::ToInt32(cx, args[0], &fd)) - return false; - oldfd = NS_TraceMallocChangeLogFD(fd); - if (oldfd == -2) { - JS_ReportOutOfMemory(cx); - return false; - } - } - args.rval().setInt32(oldfd); - return true; -} - -static bool -TraceMallocCloseLogFD(JSContext *cx, unsigned argc, JS::Value *vp) -{ - JS::CallArgs args = CallArgsFromVp(argc, vp); - - if (!CheckUniversalXPConnectForTraceMalloc(cx)) - return false; - - int32_t fd; - if (args.length() == 0) { - args.rval().setUndefined(); - return true; - } - if (!JS::ToInt32(cx, args[0], &fd)) - return false; - NS_TraceMallocCloseLogFD((int) fd); - args.rval().setInt32(fd); - return true; -} - -static bool -TraceMallocLogTimestamp(JSContext *cx, unsigned argc, JS::Value *vp) -{ - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); - if (!CheckUniversalXPConnectForTraceMalloc(cx)) - return false; - - JSString *str = JS::ToString(cx, args.get(0)); - if (!str) - return false; - JSAutoByteString caption(cx, str); - if (!caption) - return false; - NS_TraceMallocLogTimestamp(caption.ptr()); - args.rval().setUndefined(); - return true; -} - -static bool -TraceMallocDumpAllocations(JSContext *cx, unsigned argc, JS::Value *vp) -{ - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); - if (!CheckUniversalXPConnectForTraceMalloc(cx)) - return false; - - JSString *str = JS::ToString(cx, args.get(0)); - if (!str) - return false; - JSAutoByteString pathname(cx, str); - if (!pathname) - return false; - if (NS_TraceMallocDumpAllocations(pathname.ptr()) < 0) { - JS_ReportError(cx, "can't dump to %s: %s", pathname.ptr(), strerror(errno)); - return false; - } - args.rval().setUndefined(); - return true; -} - -static const JSFunctionSpec TraceMallocFunctions[] = { - JS_FS("TraceMallocDisable", TraceMallocDisable, 0, 0), - JS_FS("TraceMallocEnable", TraceMallocEnable, 0, 0), - JS_FS("TraceMallocOpenLogFile", TraceMallocOpenLogFile, 1, 0), - JS_FS("TraceMallocChangeLogFD", TraceMallocChangeLogFD, 1, 0), - JS_FS("TraceMallocCloseLogFD", TraceMallocCloseLogFD, 1, 0), - JS_FS("TraceMallocLogTimestamp", TraceMallocLogTimestamp, 1, 0), - JS_FS("TraceMallocDumpAllocations", TraceMallocDumpAllocations, 1, 0), - JS_FS_END -}; - -#endif /* NS_TRACE_MALLOC */ - #ifdef MOZ_JPROF #include @@ -1374,13 +1202,6 @@ // Attempt to initialize profiling functions ::JS_DefineProfilingFunctions(cx, aGlobalObj); -#ifdef NS_TRACE_MALLOC - if (nsContentUtils::IsCallerChrome()) { - // Attempt to initialize TraceMalloc functions - ::JS_DefineFunctions(cx, aGlobalObj, TraceMallocFunctions); - } -#endif - #ifdef MOZ_JPROF // Attempt to initialize JProf functions ::JS_DefineFunctions(cx, aGlobalObj, JProfFunctions); @@ -1459,24 +1280,17 @@ if (sCCLockedOut && aIncremental == IncrementalGC) { // We're in the middle of incremental GC. Do another slice. JS::PrepareForIncrementalGC(sRuntime); - JS::IncrementalGC(sRuntime, aReason, aSliceMillis); + JS::IncrementalGCSlice(sRuntime, aReason, aSliceMillis); return; } - if (sNeedsFullGC || aReason != JS::gcreason::CC_WAITING) { - sNeedsFullGC = false; - JS::PrepareForFullGC(sRuntime); - } else { - CycleCollectedJSRuntime::Get()->PrepareWaitingZonesForGC(); - } - + JS::PrepareForFullGC(sRuntime); if (aIncremental == IncrementalGC) { MOZ_ASSERT(aShrinking == NonShrinkingGC); - JS::IncrementalGC(sRuntime, aReason, aSliceMillis); - } else if (aShrinking == ShrinkingGC) { - JS::ShrinkingGC(sRuntime, aReason); + JS::StartIncrementalGC(sRuntime, GC_NORMAL, aReason, aSliceMillis); } else { - JS::GCForReason(sRuntime, aReason); + JSGCInvocationKind gckind = aShrinking == ShrinkingGC ? GC_SHRINK : GC_NORMAL; + JS::GCForReason(sRuntime, gckind, aReason); } } @@ -2156,8 +1970,6 @@ void nsJSContext::PokeGC(JS::gcreason::Reason aReason, int aDelay) { - sNeedsFullGC = sNeedsFullGC || aReason != JS::gcreason::CC_WAITING; - if (sGCTimer || sInterSliceGCTimer || sShuttingDown) { // There's already a timer for GC'ing, just return return; @@ -2479,7 +2291,6 @@ sLikelyShortLivingObjectsNeedingGC = 0; sPostGCEventsToConsole = false; sNeedsFullCC = false; - sNeedsFullGC = false; sNeedsGCAfterCC = false; gNameSpaceManager = nullptr; sRuntimeService = nullptr; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/base/nsPropertyTable.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/base/nsPropertyTable.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/base/nsPropertyTable.cpp 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/base/nsPropertyTable.cpp 2015-01-09 12:36:45.000000000 +0000 @@ -95,8 +95,7 @@ for (PropertyList* prop = mPropertyList; prop; prop = prop->mNext) { if (prop->mTransfer) { PropertyListMapEntry *entry = static_cast - (PL_DHashTableOperate(&prop->mObjectValueMap, aObject, - PL_DHASH_LOOKUP)); + (PL_DHashTableLookup(&prop->mObjectValueMap, aObject)); if (PL_DHASH_ENTRY_IS_BUSY(entry)) { rv = aOtherTable->SetProperty(aObject, prop->mName, entry->value, prop->mDtorFunc, @@ -126,7 +125,7 @@ PropertyList* prop; for (prop = mPropertyList; prop; prop = prop->mNext) { PropertyListMapEntry *entry = static_cast - (PL_DHashTableOperate(&prop->mObjectValueMap, aObject, PL_DHASH_LOOKUP)); + (PL_DHashTableLookup(&prop->mObjectValueMap, aObject)); if (PL_DHASH_ENTRY_IS_BUSY(entry)) { aCallback(const_cast(aObject.get()), prop->mName, entry->value, aData); @@ -174,8 +173,7 @@ PropertyList* propertyList = GetPropertyListFor(aPropertyName); if (propertyList) { PropertyListMapEntry *entry = static_cast - (PL_DHashTableOperate(&propertyList->mObjectValueMap, aObject, - PL_DHASH_LOOKUP)); + (PL_DHashTableLookup(&propertyList->mObjectValueMap, aObject)); if (PL_DHASH_ENTRY_IS_BUSY(entry)) { propValue = entry->value; if (aRemove) { @@ -230,7 +228,7 @@ // value is destroyed nsresult result = NS_OK; PropertyListMapEntry *entry = static_cast - (PL_DHashTableOperate(&propertyList->mObjectValueMap, aObject, PL_DHASH_ADD)); + (PL_DHashTableAdd(&propertyList->mObjectValueMap, aObject)); if (!entry) return NS_ERROR_OUT_OF_MEMORY; // A nullptr entry->key is the sign that the entry has just been allocated @@ -329,7 +327,7 @@ nsPropertyTable::PropertyList::DeletePropertyFor(nsPropertyOwner aObject) { PropertyListMapEntry *entry = static_cast - (PL_DHashTableOperate(&mObjectValueMap, aObject, PL_DHASH_LOOKUP)); + (PL_DHashTableLookup(&mObjectValueMap, aObject)); if (!PL_DHASH_ENTRY_IS_BUSY(entry)) return false; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/base/nsScriptNameSpaceManager.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/base/nsScriptNameSpaceManager.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/base/nsScriptNameSpaceManager.cpp 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/base/nsScriptNameSpaceManager.cpp 2015-01-09 12:36:45.000000000 +0000 @@ -144,7 +144,7 @@ { GlobalNameMapEntry *entry = static_cast - (PL_DHashTableOperate(aTable, aKey, PL_DHASH_ADD)); + (PL_DHashTableAdd(aTable, aKey)); if (!entry) { return nullptr; @@ -161,7 +161,7 @@ nsScriptNameSpaceManager::RemoveFromHash(PLDHashTable *aTable, const nsAString *aKey) { - PL_DHashTableOperate(aTable, aKey, PL_DHASH_REMOVE); + PL_DHashTableRemove(aTable, aKey); } nsGlobalNameStruct* @@ -172,9 +172,8 @@ if (!aStruct->mAlias->mProto) { GlobalNameMapEntry *proto = static_cast - (PL_DHashTableOperate(&mGlobalNames, - &aStruct->mAlias->mProtoName, - PL_DHASH_LOOKUP)); + (PL_DHashTableLookup(&mGlobalNames, + &aStruct->mAlias->mProtoName)); if (PL_DHASH_ENTRY_IS_BUSY(proto)) { aStruct->mAlias->mProto = &proto->mGlobalName; @@ -389,8 +388,7 @@ { GlobalNameMapEntry *entry = static_cast - (PL_DHashTableOperate(&mGlobalNames, &aName, - PL_DHASH_LOOKUP)); + (PL_DHashTableLookup(&mGlobalNames, &aName)); if (PL_DHASH_ENTRY_IS_BUSY(entry)) { if (aClassName) { @@ -410,8 +408,7 @@ { GlobalNameMapEntry *entry = static_cast - (PL_DHashTableOperate(&mNavigatorNames, &aName, - PL_DHASH_LOOKUP)); + (PL_DHashTableLookup(&mNavigatorNames, &aName)); if (!PL_DHASH_ENTRY_IS_BUSY(entry)) { return nullptr; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/base/nsXMLHttpRequest.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/base/nsXMLHttpRequest.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/base/nsXMLHttpRequest.cpp 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/base/nsXMLHttpRequest.cpp 2015-01-09 12:36:45.000000000 +0000 @@ -361,10 +361,11 @@ nsXMLHttpRequest::Init(nsIPrincipal* aPrincipal, nsIScriptContext* aScriptContext, nsIGlobalObject* aGlobalObject, - nsIURI* aBaseURI) + nsIURI* aBaseURI, + nsILoadGroup* aLoadGroup) { NS_ENSURE_ARG_POINTER(aPrincipal); - + if (nsCOMPtr win = do_QueryInterface(aGlobalObject)) { if (win->IsOuterWindow()) { // Must be bound to inner window, innerize if necessary. @@ -374,7 +375,7 @@ } } - Construct(aPrincipal, aGlobalObject, aBaseURI); + Construct(aPrincipal, aGlobalObject, aBaseURI, aLoadGroup); return NS_OK; } @@ -1436,6 +1437,11 @@ return nullptr; } + if (mLoadGroup) { + nsCOMPtr ref = mLoadGroup; + return ref.forget(); + } + nsresult rv = NS_ERROR_FAILURE; nsIScriptContext* sc = const_cast(this)->GetContextForEventHandlers(&rv); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/base/nsXMLHttpRequest.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/base/nsXMLHttpRequest.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/base/nsXMLHttpRequest.h 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/base/nsXMLHttpRequest.h 2015-01-09 12:36:45.000000000 +0000 @@ -244,7 +244,8 @@ void Construct(nsIPrincipal* aPrincipal, nsIGlobalObject* aGlobalObject, - nsIURI* aBaseURI = nullptr) + nsIURI* aBaseURI = nullptr, + nsILoadGroup* aLoadGroup = nullptr) { MOZ_ASSERT(aPrincipal); MOZ_ASSERT_IF(nsCOMPtr win = do_QueryInterface( @@ -252,6 +253,7 @@ mPrincipal = aPrincipal; BindToOwner(aGlobalObject); mBaseURI = aBaseURI; + mLoadGroup = aLoadGroup; } void InitParameters(bool aAnon, bool aSystem); @@ -717,6 +719,7 @@ nsIRequestObserver* mRequestObserver; nsCOMPtr mBaseURI; + nsCOMPtr mLoadGroup; uint32_t mState; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/base/test/TestGetURL.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/base/test/TestGetURL.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/base/test/TestGetURL.cpp 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/base/test/TestGetURL.cpp 2015-01-09 12:36:45.000000000 +0000 @@ -42,7 +42,7 @@ rv = secman->GetSystemPrincipal(getter_AddRefs(systemPrincipal)); TEST_ENSURE_SUCCESS(rv, "Couldn't get system principal!"); - rv = xhr->Init(systemPrincipal, nullptr, nullptr, nullptr); + rv = xhr->Init(systemPrincipal, nullptr, nullptr, nullptr, nullptr); TEST_ENSURE_SUCCESS(rv, "Couldn't initialize the XHR!"); rv = xhr->Open(getString, aURL, false, empty, empty); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/base/test/TestNativeXMLHttpRequest.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/base/test/TestNativeXMLHttpRequest.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/base/test/TestNativeXMLHttpRequest.cpp 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/base/test/TestNativeXMLHttpRequest.cpp 2015-01-09 12:36:45.000000000 +0000 @@ -52,7 +52,7 @@ rv = secman->GetSystemPrincipal(getter_AddRefs(systemPrincipal)); TEST_ENSURE_SUCCESS(rv, "Couldn't get system principal!"); - rv = xhr->Init(systemPrincipal, nullptr, nullptr, nullptr); + rv = xhr->Init(systemPrincipal, nullptr, nullptr, nullptr, nullptr); TEST_ENSURE_SUCCESS(rv, "Couldn't initialize the XHR!"); rv = xhr->Open(getString, testURL, false, empty, empty); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/battery/BatteryManager.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/battery/BatteryManager.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/battery/BatteryManager.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/battery/BatteryManager.h 2015-01-09 12:36:46.000000000 +0000 @@ -33,7 +33,7 @@ void Shutdown(); // For IObserver. - void Notify(const hal::BatteryInformation& aBatteryInfo); + void Notify(const hal::BatteryInformation& aBatteryInfo) MOZ_OVERRIDE; /** * WebIDL Interface diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bindings/BindingUtils.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bindings/BindingUtils.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bindings/BindingUtils.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bindings/BindingUtils.cpp 2015-01-09 12:36:46.000000000 +0000 @@ -2068,8 +2068,8 @@ } bool -GetWindowForJSImplementedObject(JSContext* cx, JS::Handle obj, - nsPIDOMWindow** window) +GetContentGlobalForJSImplementedObject(JSContext* cx, JS::Handle obj, + nsIGlobalObject** globalObj) { // Be very careful to not get tricked here. MOZ_ASSERT(NS_IsMainThread()); @@ -2095,37 +2095,36 @@ return false; } - // It's OK if we have null here: that just means the content-side - // object really wasn't associated with any window. - nsCOMPtr win(do_QueryInterface(global.GetAsSupports())); - win.forget(window); + DebugOnly rv = CallQueryInterface(global.GetAsSupports(), globalObj); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + MOZ_ASSERT(*globalObj); return true; } -already_AddRefed +already_AddRefed ConstructJSImplementation(JSContext* aCx, const char* aContractId, const GlobalObject& aGlobal, JS::MutableHandle aObject, ErrorResult& aRv) { - // Get the window to use as a parent and for initialization. - nsCOMPtr window = do_QueryInterface(aGlobal.GetAsSupports()); - if (!window) { + // Get the global object to use as a parent and for initialization. + nsCOMPtr global = do_QueryInterface(aGlobal.GetAsSupports()); + if (!global) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } - ConstructJSImplementation(aCx, aContractId, window, aObject, aRv); + ConstructJSImplementation(aCx, aContractId, global, aObject, aRv); if (aRv.Failed()) { return nullptr; } - return window.forget(); + return global.forget(); } void ConstructJSImplementation(JSContext* aCx, const char* aContractId, - nsPIDOMWindow* aWindow, + nsIGlobalObject* aGlobal, JS::MutableHandle aObject, ErrorResult& aRv) { @@ -2145,12 +2144,14 @@ aRv.Throw(rv); return; } - // Initialize the object, if it implements nsIDOMGlobalPropertyInitializer. + // Initialize the object, if it implements nsIDOMGlobalPropertyInitializer + // and our global is a window. nsCOMPtr gpi = do_QueryInterface(implISupports); + nsCOMPtr window = do_QueryInterface(aGlobal); if (gpi) { JS::Rooted initReturn(aCx); - rv = gpi->Init(aWindow, &initReturn); + rv = gpi->Init(window, &initReturn); if (NS_FAILED(rv)) { aRv.Throw(rv); return; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bindings/BindingUtils.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bindings/BindingUtils.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bindings/BindingUtils.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bindings/BindingUtils.h 2015-01-09 12:36:46.000000000 +0000 @@ -2651,19 +2651,19 @@ } // Given a JSObject* that represents the chrome side of a JS-implemented WebIDL -// interface, get the nsPIDOMWindow corresponding to the content side, if any. +// interface, get the nsIGlobalObject corresponding to the content side, if any. // A false return means an exception was thrown. bool -GetWindowForJSImplementedObject(JSContext* cx, JS::Handle obj, - nsPIDOMWindow** window); +GetContentGlobalForJSImplementedObject(JSContext* cx, JS::Handle obj, + nsIGlobalObject** global); void ConstructJSImplementation(JSContext* aCx, const char* aContractId, - nsPIDOMWindow* aWindow, + nsIGlobalObject* aGlobal, JS::MutableHandle aObject, ErrorResult& aRv); -already_AddRefed +already_AddRefed ConstructJSImplementation(JSContext* aCx, const char* aContractId, const GlobalObject& aGlobal, JS::MutableHandle aObject, diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bindings/Codegen.py thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bindings/Codegen.py --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bindings/Codegen.py 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bindings/Codegen.py 2015-01-09 12:36:47.000000000 +0000 @@ -3710,12 +3710,12 @@ // XXXbz Wish we could check for a JS-implemented object // that already has a content reflection... if (!IsDOMObject(js::UncheckedUnwrap(${source}))) { - nsCOMPtr ourWindow; - if (!GetWindowForJSImplementedObject(cx, Callback(), getter_AddRefs(ourWindow))) { + nsCOMPtr contentGlobal; + if (!GetContentGlobalForJSImplementedObject(cx, Callback(), getter_AddRefs(contentGlobal))) { $*{exceptionCode} } JS::Rooted jsImplSourceObj(cx, ${source}); - ${target} = new ${type}(jsImplSourceObj, ourWindow); + ${target} = new ${type}(jsImplSourceObj, contentGlobal); } else { $*{codeOnFailure} } @@ -12291,7 +12291,7 @@ jsImplemented = config.getDescriptors(webIDLFile=webIDLFile, isJSImplemented=True) bindingDeclareHeaders["nsWeakReference.h"] = jsImplemented - bindingHeaders["nsPIDOMWindow.h"] = jsImplemented + bindingHeaders["nsIGlobalObject.h"] = jsImplemented bindingHeaders["AtomList.h"] = hasNonEmptyDictionaries or jsImplemented or callbackDescriptors def addHeaderBasedOnTypes(header, typeChecker): @@ -13300,7 +13300,6 @@ initCall = fill( """ // Wrap the object before calling __Init so that __DOM_IMPL__ is available. - nsCOMPtr globalHolder = do_QueryInterface(window); JS::Rooted scopeObj(cx, globalHolder->GetGlobalJSObject()); MOZ_ASSERT(js::IsObjectInContextCompartment(scopeObj, cx)); JS::Rooted wrappedVal(cx); @@ -13326,13 +13325,13 @@ return fill( """ JS::Rooted jsImplObj(cx); - nsCOMPtr window = + nsCOMPtr globalHolder = ConstructJSImplementation(cx, "${contractId}", global, &jsImplObj, aRv); if (aRv.Failed()) { return nullptr; } // Build the C++ implementation. - nsRefPtr<${implClass}> impl = new ${implClass}(jsImplObj, window); + nsRefPtr<${implClass}> impl = new ${implClass}(jsImplObj, globalHolder); $*{initCall} return impl.forget(); """, @@ -13516,7 +13515,7 @@ constructor = ClassConstructor( [Argument("JS::Handle", "aJSImplObject"), - Argument("nsPIDOMWindow*", "aParent")], + Argument("nsIGlobalObject*", "aParent")], visibility="public", baseConstructors=baseConstructors) @@ -13587,12 +13586,10 @@ if (global.Failed()) { return false; } - nsCOMPtr window = do_QueryInterface(global.GetAsSupports()); - if (!window) { - return ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "Argument 1 of ${ifaceName}._create", "Window"); - } + nsCOMPtr globalHolder = do_QueryInterface(global.GetAsSupports()); + MOZ_ASSERT(globalHolder); JS::Rooted arg(cx, &args[1].toObject()); - nsRefPtr<${implName}> impl = new ${implName}(arg, window); + nsRefPtr<${implName}> impl = new ${implName}(arg, globalHolder); MOZ_ASSERT(js::IsObjectInContextCompartment(arg, cx)); return GetOrCreateDOMReflector(cx, impl, args.rval()); """, diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bindings/test/TestCImplementedInterface.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bindings/test/TestCImplementedInterface.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bindings/test/TestCImplementedInterface.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bindings/test/TestCImplementedInterface.h 2015-01-09 12:36:47.000000000 +0000 @@ -18,7 +18,7 @@ { public: TestCImplementedInterface(JS::Handle aJSImpl, - nsPIDOMWindow* aParent) + nsIGlobalObject* aParent) : TestJSImplInterface(aJSImpl, aParent) {} }; @@ -27,7 +27,7 @@ public nsWrapperCache { public: - explicit TestCImplementedInterface2(nsPIDOMWindow* aParent) + explicit TestCImplementedInterface2(nsIGlobalObject* aParent) {} NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TestCImplementedInterface2) diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonAvrcpInterface.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonAvrcpInterface.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonAvrcpInterface.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonAvrcpInterface.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -0,0 +1,1056 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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 "BluetoothDaemonAvrcpInterface.h" +#include "BluetoothDaemonSetupInterface.h" +#include "mozilla/unused.h" + +BEGIN_BLUETOOTH_NAMESPACE + +// +// AVRCP module +// + +BluetoothAvrcpNotificationHandler* + BluetoothDaemonAvrcpModule::sNotificationHandler; + +void +BluetoothDaemonAvrcpModule::SetNotificationHandler( + BluetoothAvrcpNotificationHandler* aNotificationHandler) +{ + sNotificationHandler = aNotificationHandler; +} + +nsresult +BluetoothDaemonAvrcpModule::Send(BluetoothDaemonPDU* aPDU, + BluetoothAvrcpResultHandler* aRes) +{ + if (aRes) { + aRes->AddRef(); // Keep reference for response + } + return Send(aPDU, static_cast(aRes)); +} + +void +BluetoothDaemonAvrcpModule::HandleSvc(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, void* aUserData) +{ + static void (BluetoothDaemonAvrcpModule::* const HandleOp[])( + const BluetoothDaemonPDUHeader&, BluetoothDaemonPDU&, void*) = { + INIT_ARRAY_AT(0, &BluetoothDaemonAvrcpModule::HandleRsp), + INIT_ARRAY_AT(1, &BluetoothDaemonAvrcpModule::HandleNtf), + }; + + MOZ_ASSERT(!NS_IsMainThread()); + + unsigned int isNtf = !!(aHeader.mOpcode & 0x80); + + (this->*(HandleOp[isNtf]))(aHeader, aPDU, aUserData); +} + +// Commands +// + +nsresult +BluetoothDaemonAvrcpModule::GetPlayStatusRspCmd( + ControlPlayStatus aPlayStatus, uint32_t aSongLen, uint32_t aSongPos, + BluetoothAvrcpResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_GET_PLAY_STATUS_RSP, + 1 + // Play status + 4 + // Duration + 4)); // Position + + nsresult rv = PackPDU(aPlayStatus, aSongLen, aSongPos, *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonAvrcpModule::ListPlayerAppAttrRspCmd( + int aNumAttr, const BluetoothAvrcpPlayerAttribute* aPAttrs, + BluetoothAvrcpResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_LIST_PLAYER_APP_ATTR_RSP, + 1 + // # Attributes + aNumAttr)); // Player attributes + + nsresult rv = PackPDU( + PackConversion(aNumAttr), + PackArray(aPAttrs, aNumAttr), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonAvrcpModule::ListPlayerAppValueRspCmd( + int aNumVal, uint8_t* aPVals, BluetoothAvrcpResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_LIST_PLAYER_APP_VALUE_RSP, + 1 + // # Values + aNumVal)); // Player values + + nsresult rv = PackPDU(PackConversion(aNumVal), + PackArray(aPVals, aNumVal), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonAvrcpModule::GetPlayerAppValueRspCmd( + uint8_t aNumAttrs, const uint8_t* aIds, const uint8_t* aValues, + BluetoothAvrcpResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_GET_PLAYER_APP_VALUE_RSP, + 1 + // # Pairs + 2 * aNumAttrs)); // Attribute-value pairs + nsresult rv = PackPDU( + aNumAttrs, + BluetoothAvrcpAttributeValuePairs(aIds, aValues, aNumAttrs), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonAvrcpModule::GetPlayerAppAttrTextRspCmd( + int aNumAttr, const uint8_t* aIds, const char** aTexts, + BluetoothAvrcpResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_GET_PLAYER_APP_ATTR_TEXT_RSP, + 0)); // Dynamically allocated + nsresult rv = PackPDU( + PackConversion(aNumAttr), + BluetoothAvrcpAttributeTextPairs(aIds, aTexts, aNumAttr), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonAvrcpModule::GetPlayerAppValueTextRspCmd( + int aNumVal, const uint8_t* aIds, const char** aTexts, + BluetoothAvrcpResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_GET_PLAYER_APP_VALUE_TEXT_RSP, + 0)); // Dynamically allocated + nsresult rv = PackPDU( + PackConversion(aNumVal), + BluetoothAvrcpAttributeTextPairs(aIds, aTexts, aNumVal), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonAvrcpModule::GetElementAttrRspCmd( + uint8_t aNumAttr, const BluetoothAvrcpElementAttribute* aAttr, + BluetoothAvrcpResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_GET_ELEMENT_ATTR_RSP, + 0)); // Dynamically allocated + nsresult rv = PackPDU( + aNumAttr, + PackArray(aAttr, aNumAttr), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonAvrcpModule::SetPlayerAppValueRspCmd( + BluetoothAvrcpStatus aRspStatus, BluetoothAvrcpResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_SET_PLAYER_APP_VALUE_RSP, + 1)); // Status code + + nsresult rv = PackPDU(aRspStatus, *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonAvrcpModule::RegisterNotificationRspCmd( + BluetoothAvrcpEvent aEvent, BluetoothAvrcpNotification aType, + const BluetoothAvrcpNotificationParam& aParam, + BluetoothAvrcpResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_REGISTER_NOTIFICATION_RSP, + 1 + // Event + 1 + // Type + 1 + // Data length + 256)); // Maximum data length + + nsresult rv = PackPDU(aEvent, aType, + BluetoothAvrcpEventParamPair(aEvent, aParam), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonAvrcpModule::SetVolumeCmd(uint8_t aVolume, + BluetoothAvrcpResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_SET_VOLUME, + 1)); // Volume + + nsresult rv = PackPDU(aVolume, *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +// Responses +// + +void +BluetoothDaemonAvrcpModule::ErrorRsp( + const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes) +{ + ErrorRunnable::Dispatch( + aRes, &BluetoothAvrcpResultHandler::OnError, UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonAvrcpModule::GetPlayStatusRspRsp( + const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothAvrcpResultHandler::GetPlayStatusRsp, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonAvrcpModule::ListPlayerAppAttrRspRsp( + const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothAvrcpResultHandler::ListPlayerAppAttrRsp, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonAvrcpModule::ListPlayerAppValueRspRsp( + const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothAvrcpResultHandler::ListPlayerAppValueRsp, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonAvrcpModule::GetPlayerAppValueRspRsp( + const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothAvrcpResultHandler::GetPlayerAppValueRsp, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonAvrcpModule::GetPlayerAppAttrTextRspRsp( + const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothAvrcpResultHandler::GetPlayerAppAttrTextRsp, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonAvrcpModule::GetPlayerAppValueTextRspRsp( + const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothAvrcpResultHandler::GetPlayerAppValueTextRsp, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonAvrcpModule::GetElementAttrRspRsp( + const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothAvrcpResultHandler::GetElementAttrRsp, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonAvrcpModule::SetPlayerAppValueRspRsp( + const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothAvrcpResultHandler::SetPlayerAppValueRsp, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonAvrcpModule::RegisterNotificationRspRsp( + const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothAvrcpResultHandler::RegisterNotificationRsp, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonAvrcpModule::SetVolumeRsp( + const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothAvrcpResultHandler::SetVolume, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonAvrcpModule::HandleRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + void* aUserData) +{ + static void (BluetoothDaemonAvrcpModule::* const HandleRsp[])( + const BluetoothDaemonPDUHeader&, + BluetoothDaemonPDU&, + BluetoothAvrcpResultHandler*) = { + INIT_ARRAY_AT(OPCODE_ERROR, + &BluetoothDaemonAvrcpModule::ErrorRsp), + INIT_ARRAY_AT(OPCODE_GET_PLAY_STATUS_RSP, + &BluetoothDaemonAvrcpModule::GetPlayStatusRspRsp), + INIT_ARRAY_AT(OPCODE_LIST_PLAYER_APP_ATTR_RSP, + &BluetoothDaemonAvrcpModule::ListPlayerAppAttrRspRsp), + INIT_ARRAY_AT(OPCODE_LIST_PLAYER_APP_VALUE_RSP, + &BluetoothDaemonAvrcpModule::ListPlayerAppValueRspRsp), + INIT_ARRAY_AT(OPCODE_GET_PLAYER_APP_VALUE_RSP, + &BluetoothDaemonAvrcpModule::GetPlayerAppValueRspRsp), + INIT_ARRAY_AT(OPCODE_GET_PLAYER_APP_ATTR_TEXT_RSP, + &BluetoothDaemonAvrcpModule::GetPlayerAppAttrTextRspRsp), + INIT_ARRAY_AT(OPCODE_GET_PLAYER_APP_VALUE_TEXT_RSP, + &BluetoothDaemonAvrcpModule::GetPlayerAppValueTextRspRsp), + INIT_ARRAY_AT(OPCODE_GET_ELEMENT_ATTR_RSP, + &BluetoothDaemonAvrcpModule::GetElementAttrRspRsp), + INIT_ARRAY_AT(OPCODE_SET_PLAYER_APP_VALUE_RSP, + &BluetoothDaemonAvrcpModule::SetPlayerAppValueRspRsp), + INIT_ARRAY_AT(OPCODE_REGISTER_NOTIFICATION_RSP, + &BluetoothDaemonAvrcpModule::RegisterNotificationRspRsp), + INIT_ARRAY_AT(OPCODE_SET_VOLUME, + &BluetoothDaemonAvrcpModule::SetVolumeRsp) + }; + + MOZ_ASSERT(!NS_IsMainThread()); // I/O thread + + if (NS_WARN_IF(!(aHeader.mOpcode < MOZ_ARRAY_LENGTH(HandleRsp))) || + NS_WARN_IF(!HandleRsp[aHeader.mOpcode])) { + return; + } + + nsRefPtr res = + already_AddRefed( + static_cast(aUserData)); + + if (!res) { + return; // Return early if no result handler has been set for response + } + + (this->*(HandleRsp[aHeader.mOpcode]))(aHeader, aPDU, res); +} + +// Notifications +// + +// Returns the current notification handler to a notification runnable +class BluetoothDaemonAvrcpModule::NotificationHandlerWrapper MOZ_FINAL +{ +public: + typedef BluetoothAvrcpNotificationHandler ObjectType; + + static ObjectType* GetInstance() + { + MOZ_ASSERT(NS_IsMainThread()); + + return sNotificationHandler; + } +}; + +// Init operator class for RemoteFeatureNotification +class BluetoothDaemonAvrcpModule::RemoteFeatureInitOp MOZ_FINAL + : private PDUInitOp +{ +public: + RemoteFeatureInitOp(BluetoothDaemonPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (nsString& aArg1, unsigned long& aArg2) const + { + BluetoothDaemonPDU& pdu = GetPDU(); + + /* Read address */ + nsresult rv = UnpackPDU( + pdu, UnpackConversion(aArg1)); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read feature */ + rv = UnpackPDU( + pdu, + UnpackConversion(aArg2)); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonAvrcpModule::RemoteFeatureNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + RemoteFeatureNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::RemoteFeatureNotification, + RemoteFeatureInitOp(aPDU)); +} + +void +BluetoothDaemonAvrcpModule::GetPlayStatusNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + GetPlayStatusNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::GetPlayStatusNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonAvrcpModule::ListPlayerAppAttrNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + ListPlayerAppAttrNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::ListPlayerAppAttrNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonAvrcpModule::ListPlayerAppValuesNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + ListPlayerAppValuesNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::ListPlayerAppValuesNotification, + UnpackPDUInitOp(aPDU)); +} + +// Init operator class for GetPlayerAppValueNotification +class BluetoothDaemonAvrcpModule::GetPlayerAppValueInitOp MOZ_FINAL + : private PDUInitOp +{ +public: + GetPlayerAppValueInitOp(BluetoothDaemonPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (uint8_t& aArg1, + nsAutoArrayPtr& aArg2) const + { + BluetoothDaemonPDU& pdu = GetPDU(); + + /* Read number of attributes */ + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read attributes */ + rv = UnpackPDU( + pdu, UnpackArray(aArg2, aArg1)); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonAvrcpModule::GetPlayerAppValueNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + GetPlayerAppValueNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::GetPlayerAppValueNotification, + GetPlayerAppValueInitOp(aPDU)); +} + +// Init operator class for GetPlayerAppAttrsTextNotification +class BluetoothDaemonAvrcpModule::GetPlayerAppAttrsTextInitOp MOZ_FINAL + : private PDUInitOp +{ +public: + GetPlayerAppAttrsTextInitOp(BluetoothDaemonPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (uint8_t& aArg1, + nsAutoArrayPtr& aArg2) const + { + BluetoothDaemonPDU& pdu = GetPDU(); + + /* Read number of attributes */ + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read attributes */ + rv = UnpackPDU( + pdu, UnpackArray(aArg2, aArg1)); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonAvrcpModule::GetPlayerAppAttrsTextNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + GetPlayerAppAttrsTextNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::GetPlayerAppAttrsTextNotification, + GetPlayerAppAttrsTextInitOp(aPDU)); +} + +// Init operator class for GetPlayerAppValuesTextNotification +class BluetoothDaemonAvrcpModule::GetPlayerAppValuesTextInitOp MOZ_FINAL + : private PDUInitOp +{ +public: + GetPlayerAppValuesTextInitOp(BluetoothDaemonPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (uint8_t& aArg1, uint8_t& aArg2, + nsAutoArrayPtr& aArg3) const + { + BluetoothDaemonPDU& pdu = GetPDU(); + + /* Read attribute */ + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read number of values */ + rv = UnpackPDU(pdu, aArg2); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read values */ + rv = UnpackPDU(pdu, UnpackArray(aArg3, aArg2)); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonAvrcpModule::GetPlayerAppValuesTextNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + GetPlayerAppValuesTextNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::GetPlayerAppValuesTextNotification, + GetPlayerAppValuesTextInitOp(aPDU)); +} + +void +BluetoothDaemonAvrcpModule::SetPlayerAppValueNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + SetPlayerAppValueNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::SetPlayerAppValueNotification, + UnpackPDUInitOp(aPDU)); +} + +// Init operator class for GetElementAttrNotification +class BluetoothDaemonAvrcpModule::GetElementAttrInitOp MOZ_FINAL + : private PDUInitOp +{ +public: + GetElementAttrInitOp(BluetoothDaemonPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (uint8_t& aArg1, + nsAutoArrayPtr& aArg2) const + { + BluetoothDaemonPDU& pdu = GetPDU(); + + /* Read number of attributes */ + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read attributes */ + rv = UnpackPDU( + pdu, UnpackArray(aArg2, aArg1)); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonAvrcpModule::GetElementAttrNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + GetElementAttrNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::GetElementAttrNotification, + GetElementAttrInitOp(aPDU)); +} + +void +BluetoothDaemonAvrcpModule::RegisterNotificationNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + RegisterNotificationNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::RegisterNotificationNotification, + UnpackPDUInitOp(aPDU)); +} + +#if ANDROID_VERSION >= 19 +void +BluetoothDaemonAvrcpModule::VolumeChangeNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + VolumeChangeNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::VolumeChangeNotification, + UnpackPDUInitOp(aPDU)); +} + +// Init operator class for PassthroughCmdNotification +class BluetoothDaemonAvrcpModule::PassthroughCmdInitOp MOZ_FINAL + : private PDUInitOp +{ +public: + PassthroughCmdInitOp(BluetoothDaemonPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (int& aArg1, int& aArg2) const + { + BluetoothDaemonPDU& pdu = GetPDU(); + + nsresult rv = UnpackPDU(pdu, UnpackConversion(aArg1)); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, UnpackConversion(aArg2)); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonAvrcpModule::PassthroughCmdNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + PassthroughCmdNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::PassthroughCmdNotification, + PassthroughCmdInitOp(aPDU)); +} +#endif + +void +BluetoothDaemonAvrcpModule::HandleNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + void* aUserData) +{ + static void (BluetoothDaemonAvrcpModule::* const HandleNtf[])( + const BluetoothDaemonPDUHeader&, BluetoothDaemonPDU&) = { +#if ANDROID_VERSION >= 19 + INIT_ARRAY_AT(0, &BluetoothDaemonAvrcpModule::RemoteFeatureNtf), + INIT_ARRAY_AT(1, &BluetoothDaemonAvrcpModule::GetPlayStatusNtf), + INIT_ARRAY_AT(2, &BluetoothDaemonAvrcpModule::ListPlayerAppAttrNtf), + INIT_ARRAY_AT(3, &BluetoothDaemonAvrcpModule::ListPlayerAppValuesNtf), + INIT_ARRAY_AT(4, &BluetoothDaemonAvrcpModule::GetPlayerAppValueNtf), + INIT_ARRAY_AT(5, &BluetoothDaemonAvrcpModule::GetPlayerAppAttrsTextNtf), + INIT_ARRAY_AT(6, &BluetoothDaemonAvrcpModule::GetPlayerAppValuesTextNtf), + INIT_ARRAY_AT(7, &BluetoothDaemonAvrcpModule::SetPlayerAppValueNtf), + INIT_ARRAY_AT(8, &BluetoothDaemonAvrcpModule::GetElementAttrNtf), + INIT_ARRAY_AT(9, &BluetoothDaemonAvrcpModule::RegisterNotificationNtf), + INIT_ARRAY_AT(10, &BluetoothDaemonAvrcpModule::VolumeChangeNtf), + INIT_ARRAY_AT(11, &BluetoothDaemonAvrcpModule::PassthroughCmdNtf) +#else + INIT_ARRAY_AT(0, &BluetoothDaemonAvrcpModule::GetPlayStatusNtf), + INIT_ARRAY_AT(1, &BluetoothDaemonAvrcpModule::ListPlayerAppAttrNtf), + INIT_ARRAY_AT(2, &BluetoothDaemonAvrcpModule::ListPlayerAppValuesNtf), + INIT_ARRAY_AT(3, &BluetoothDaemonAvrcpModule::GetPlayerAppValueNtf), + INIT_ARRAY_AT(4, &BluetoothDaemonAvrcpModule::GetPlayerAppAttrsTextNtf), + INIT_ARRAY_AT(5, &BluetoothDaemonAvrcpModule::GetPlayerAppValuesTextNtf), + INIT_ARRAY_AT(6, &BluetoothDaemonAvrcpModule::SetPlayerAppValueNtf), + INIT_ARRAY_AT(7, &BluetoothDaemonAvrcpModule::GetElementAttrNtf), + INIT_ARRAY_AT(8, &BluetoothDaemonAvrcpModule::RegisterNotificationNtf) +#endif + }; + + MOZ_ASSERT(!NS_IsMainThread()); + + uint8_t index = aHeader.mOpcode - 0x81; + + if (NS_WARN_IF(!(index < MOZ_ARRAY_LENGTH(HandleNtf))) || + NS_WARN_IF(!HandleNtf[index])) { + return; + } + + (this->*(HandleNtf[index]))(aHeader, aPDU); +} + +// +// AVRCP interface +// + +BluetoothDaemonAvrcpInterface::BluetoothDaemonAvrcpInterface( + BluetoothDaemonAvrcpModule* aModule) + : mModule(aModule) +{ } + +BluetoothDaemonAvrcpInterface::~BluetoothDaemonAvrcpInterface() +{ } + +class BluetoothDaemonAvrcpInterface::InitResultHandler MOZ_FINAL + : public BluetoothSetupResultHandler +{ +public: + InitResultHandler(BluetoothAvrcpResultHandler* aRes) + : mRes(aRes) + { + MOZ_ASSERT(mRes); + } + + void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + + mRes->OnError(aStatus); + } + + void RegisterModule() MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + + mRes->Init(); + } + +private: + nsRefPtr mRes; +}; + +void +BluetoothDaemonAvrcpInterface::Init( + BluetoothAvrcpNotificationHandler* aNotificationHandler, + BluetoothAvrcpResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + // Set notification handler _before_ registering the module. It could + // happen that we receive notifications, before the result handler runs. + mModule->SetNotificationHandler(aNotificationHandler); + + InitResultHandler* res; + + if (aRes) { + res = new InitResultHandler(aRes); + } else { + // We don't need a result handler if the caller is not interested. + res = nullptr; + } + + nsresult rv = mModule->RegisterModule( + BluetoothDaemonAvrcpModule::SERVICE_ID, 0x00, res); + + if (NS_FAILED(rv) && aRes) { + DispatchError(aRes, STATUS_FAIL); + } +} + +class BluetoothDaemonAvrcpInterface::CleanupResultHandler MOZ_FINAL + : public BluetoothSetupResultHandler +{ +public: + CleanupResultHandler(BluetoothDaemonAvrcpModule* aModule, + BluetoothAvrcpResultHandler* aRes) + : mModule(aModule) + , mRes(aRes) + { + MOZ_ASSERT(mModule); + } + + void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + + if (mRes) { + mRes->OnError(aStatus); + } + } + + void UnregisterModule() MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + + // Clear notification handler _after_ module has been + // unregistered. While unregistering the module, we might + // still receive notifications. + mModule->SetNotificationHandler(nullptr); + + if (mRes) { + mRes->Cleanup(); + } + } + +private: + BluetoothDaemonAvrcpModule* mModule; + nsRefPtr mRes; +}; + +void +BluetoothDaemonAvrcpInterface::Cleanup( + BluetoothAvrcpResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->UnregisterModule(BluetoothDaemonAvrcpModule::SERVICE_ID, + new CleanupResultHandler(mModule, aRes)); +} + +void +BluetoothDaemonAvrcpInterface::GetPlayStatusRsp( + ControlPlayStatus aPlayStatus, uint32_t aSongLen, uint32_t aSongPos, + BluetoothAvrcpResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->GetPlayStatusRspCmd(aPlayStatus, aSongLen, aSongPos, aRes); +} + +void +BluetoothDaemonAvrcpInterface::ListPlayerAppAttrRsp( + int aNumAttr, const BluetoothAvrcpPlayerAttribute* aPAttrs, + BluetoothAvrcpResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->ListPlayerAppAttrRspCmd(aNumAttr, aPAttrs, aRes); +} + +void +BluetoothDaemonAvrcpInterface::ListPlayerAppValueRsp( + int aNumVal, uint8_t* aPVals, BluetoothAvrcpResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->ListPlayerAppValueRspCmd(aNumVal, aPVals, aRes); +} + +void +BluetoothDaemonAvrcpInterface::GetPlayerAppValueRsp( + uint8_t aNumAttrs, const uint8_t* aIds, const uint8_t* aValues, + BluetoothAvrcpResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->GetPlayerAppValueRspCmd(aNumAttrs, aIds, aValues, aRes); +} + +void +BluetoothDaemonAvrcpInterface::GetPlayerAppAttrTextRsp( + int aNumAttr, const uint8_t* aIds, const char** aTexts, + BluetoothAvrcpResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->GetPlayerAppAttrTextRspCmd(aNumAttr, aIds, aTexts, aRes); +} + +void +BluetoothDaemonAvrcpInterface::GetPlayerAppValueTextRsp( + int aNumVal, const uint8_t* aIds, const char** aTexts, + BluetoothAvrcpResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->GetPlayerAppValueTextRspCmd(aNumVal, aIds, aTexts, aRes); +} + +void +BluetoothDaemonAvrcpInterface::GetElementAttrRsp( + uint8_t aNumAttr, const BluetoothAvrcpElementAttribute* aAttr, + BluetoothAvrcpResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->GetElementAttrRspCmd(aNumAttr, aAttr, aRes); +} + +void +BluetoothDaemonAvrcpInterface::SetPlayerAppValueRsp( + BluetoothAvrcpStatus aRspStatus, BluetoothAvrcpResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->SetPlayerAppValueRspCmd(aRspStatus, aRes); +} + +void +BluetoothDaemonAvrcpInterface::RegisterNotificationRsp( + BluetoothAvrcpEvent aEvent, + BluetoothAvrcpNotification aType, + const BluetoothAvrcpNotificationParam& aParam, + BluetoothAvrcpResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->RegisterNotificationRspCmd(aEvent, aType, aParam, aRes); +} + +void +BluetoothDaemonAvrcpInterface::SetVolume( + uint8_t aVolume, BluetoothAvrcpResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->SetVolumeCmd(aVolume, aRes); +} + +void +BluetoothDaemonAvrcpInterface::DispatchError( + BluetoothAvrcpResultHandler* aRes, BluetoothStatus aStatus) +{ + BluetoothResultRunnable1::Dispatch( + aRes, &BluetoothAvrcpResultHandler::OnError, + ConstantInitOp1(aStatus)); +} + +END_BLUETOOTH_NAMESPACE diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonAvrcpInterface.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonAvrcpInterface.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonAvrcpInterface.h 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonAvrcpInterface.h 2015-01-09 12:36:47.000000000 +0000 @@ -0,0 +1,352 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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_dom_bluetooth_bluetoothdaemonavrcpinterface_h +#define mozilla_dom_bluetooth_bluetoothdaemonavrcpinterface_h + +#include "BluetoothDaemonHelpers.h" +#include "BluetoothInterface.h" +#include "BluetoothInterfaceHelpers.h" + +BEGIN_BLUETOOTH_NAMESPACE + +class BluetoothSetupResultHandler; + +class BluetoothDaemonAvrcpModule +{ +public: + enum { + SERVICE_ID = 0x08 + }; + + enum { + OPCODE_ERROR = 0x00, + OPCODE_GET_PLAY_STATUS_RSP = 0x01, + OPCODE_LIST_PLAYER_APP_ATTR_RSP = 0x02, + OPCODE_LIST_PLAYER_APP_VALUE_RSP = 0x03, + OPCODE_GET_PLAYER_APP_VALUE_RSP = 0x04, + OPCODE_GET_PLAYER_APP_ATTR_TEXT_RSP = 0x05, + OPCODE_GET_PLAYER_APP_VALUE_TEXT_RSP = 0x06, + OPCODE_GET_ELEMENT_ATTR_RSP = 0x07, + OPCODE_SET_PLAYER_APP_VALUE_RSP = 0x08, + OPCODE_REGISTER_NOTIFICATION_RSP = 0x09, + OPCODE_SET_VOLUME = 0x0a, +#if ANDROID_VERSION >= 19 + OPCODE_REMOTE_FEATURES_NTF = 0x81, + OPCODE_GET_PLAY_STATUS_NTF = 0x82, + OPCODE_LIST_PLAYER_APP_ATTR_NTF = 0x83, + OPCODE_LIST_PLAYER_APP_VALUES_NTF = 0x84, + OPCODE_GET_PLAYER_APP_VALUE_NTF = 0x85, + OPCODE_GET_PLAYER_APP_ATTRS_TEXT_NTF = 0x86, + OPCODE_GET_PLAYER_APP_VALUES_TEXT_NTF = 0x87, + OPCODE_SET_PLAYER_APP_VALUE_NTF = 0x88, + OPCODE_GET_ELEMENT_ATTR_NTF = 0x89, + OPCODE_REGISTER_NOTIFICATION_NTF = 0x8a, + OPCODE_VOLUME_CHANGE_NTF = 0x8b, + OPCODE_PASSTHROUGH_CMD_NTF = 0x8c +#else /* defined by BlueZ 5.14 */ + OPCODE_GET_PLAY_STATUS_NTF = 0x81, + OPCODE_LIST_PLAYER_APP_ATTR_NTF = 0x82, + OPCODE_LIST_PLAYER_APP_VALUES_NTF = 0x83, + OPCODE_GET_PLAYER_APP_VALUE_NTF = 0x84, + OPCODE_GET_PLAYER_APP_ATTRS_TEXT_NTF = 0x85, + OPCODE_GET_PLAYER_APP_VALUES_TEXT_NTF = 0x86, + OPCODE_SET_PLAYER_APP_VALUE_NTF = 0x87, + OPCODE_GET_ELEMENT_ATTR_NTF = 0x88, + OPCODE_REGISTER_NOTIFICATION_NTF = 0x89 +#endif + }; + + virtual nsresult Send(BluetoothDaemonPDU* aPDU, void* aUserData) = 0; + + virtual nsresult RegisterModule(uint8_t aId, uint8_t aMode, + BluetoothSetupResultHandler* aRes) = 0; + + virtual nsresult UnregisterModule(uint8_t aId, + BluetoothSetupResultHandler* aRes) = 0; + + void SetNotificationHandler( + BluetoothAvrcpNotificationHandler* aNotificationHandler); + + // + // Commands + // + + nsresult GetPlayStatusRspCmd( + ControlPlayStatus aPlayStatus, uint32_t aSongLen, uint32_t aSongPos, + BluetoothAvrcpResultHandler* aRes); + + nsresult ListPlayerAppAttrRspCmd( + int aNumAttr, const BluetoothAvrcpPlayerAttribute* aPAttrs, + BluetoothAvrcpResultHandler* aRes); + + nsresult ListPlayerAppValueRspCmd( + int aNumVal, uint8_t* aPVals, BluetoothAvrcpResultHandler* aRes); + + nsresult GetPlayerAppValueRspCmd( + uint8_t aNumAttrs, const uint8_t* aIds, const uint8_t* aValues, + BluetoothAvrcpResultHandler* aRes); + + nsresult GetPlayerAppAttrTextRspCmd( + int aNumAttr, const uint8_t* aIds, const char** aTexts, + BluetoothAvrcpResultHandler* aRes); + + nsresult GetPlayerAppValueTextRspCmd( + int aNumVal, const uint8_t* aIds, const char** aTexts, + BluetoothAvrcpResultHandler* aRes); + + nsresult GetElementAttrRspCmd( + uint8_t aNumAttr, const BluetoothAvrcpElementAttribute* aAttr, + BluetoothAvrcpResultHandler* aRes); + + nsresult SetPlayerAppValueRspCmd( + BluetoothAvrcpStatus aRspStatus, BluetoothAvrcpResultHandler* aRes); + + nsresult RegisterNotificationRspCmd( + BluetoothAvrcpEvent aEvent, BluetoothAvrcpNotification aType, + const BluetoothAvrcpNotificationParam& aParam, + BluetoothAvrcpResultHandler* aRes); + + nsresult SetVolumeCmd(uint8_t aVolume, BluetoothAvrcpResultHandler* aRes); + +protected: + nsresult Send(BluetoothDaemonPDU* aPDU, + BluetoothAvrcpResultHandler* aRes); + + void HandleSvc(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, void* aUserData); + + // + // Responses + // + + typedef BluetoothResultRunnable0 + ResultRunnable; + + typedef BluetoothResultRunnable1 + ErrorRunnable; + + void ErrorRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothAvrcpResultHandler* aRes); + + void GetPlayStatusRspRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothAvrcpResultHandler* aRes); + + void ListPlayerAppAttrRspRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothAvrcpResultHandler* aRes); + + void ListPlayerAppValueRspRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothAvrcpResultHandler* aRes); + + void GetPlayerAppValueRspRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothAvrcpResultHandler* aRes); + + void GetPlayerAppAttrTextRspRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothAvrcpResultHandler* aRes); + + void GetPlayerAppValueTextRspRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothAvrcpResultHandler* aRes); + + void GetElementAttrRspRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothAvrcpResultHandler* aRes); + + void SetPlayerAppValueRspRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothAvrcpResultHandler* aRes); + + void RegisterNotificationRspRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothAvrcpResultHandler* aRes); + + void SetVolumeRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothAvrcpResultHandler* aRes); + + void HandleRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + void* aUserData); + + // + // Notifications + // + + class NotificationHandlerWrapper; + + typedef BluetoothNotificationRunnable2 + RemoteFeatureNotification; + + typedef BluetoothNotificationRunnable0 + GetPlayStatusNotification; + + typedef BluetoothNotificationRunnable0 + ListPlayerAppAttrNotification; + + typedef BluetoothNotificationRunnable1 + ListPlayerAppValuesNotification; + + typedef BluetoothNotificationRunnable2, + uint8_t, const BluetoothAvrcpPlayerAttribute*> + GetPlayerAppValueNotification; + + typedef BluetoothNotificationRunnable2, + uint8_t, const BluetoothAvrcpPlayerAttribute*> + GetPlayerAppAttrsTextNotification; + + typedef BluetoothNotificationRunnable3, uint8_t, + uint8_t, const uint8_t*> + GetPlayerAppValuesTextNotification; + + typedef BluetoothNotificationRunnable1 + SetPlayerAppValueNotification; + + typedef BluetoothNotificationRunnable2, + uint8_t, const BluetoothAvrcpMediaAttribute*> + GetElementAttrNotification; + + typedef BluetoothNotificationRunnable2 + RegisterNotificationNotification; + + typedef BluetoothNotificationRunnable2 + VolumeChangeNotification; + + typedef BluetoothNotificationRunnable2 + PassthroughCmdNotification; + + class GetElementAttrInitOp; + class GetPlayerAppAttrsTextInitOp; + class GetPlayerAppValueInitOp; + class GetPlayerAppValuesTextInitOp; + class PassthroughCmdInitOp; + class RemoteFeatureInitOp; + + void RemoteFeatureNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void GetPlayStatusNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void ListPlayerAppAttrNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void ListPlayerAppValuesNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void GetPlayerAppValueNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void GetPlayerAppAttrsTextNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void GetPlayerAppValuesTextNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void SetPlayerAppValueNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void GetElementAttrNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void RegisterNotificationNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void VolumeChangeNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void PassthroughCmdNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void HandleNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + void* aUserData); + + static BluetoothAvrcpNotificationHandler* sNotificationHandler; +}; + +class BluetoothDaemonAvrcpInterface MOZ_FINAL + : public BluetoothAvrcpInterface +{ + class CleanupResultHandler; + class InitResultHandler; + +public: + BluetoothDaemonAvrcpInterface(BluetoothDaemonAvrcpModule* aModule); + ~BluetoothDaemonAvrcpInterface(); + + void Init(BluetoothAvrcpNotificationHandler* aNotificationHandler, + BluetoothAvrcpResultHandler* aRes) MOZ_OVERRIDE; + + void Cleanup(BluetoothAvrcpResultHandler* aRes) MOZ_OVERRIDE; + + void GetPlayStatusRsp(ControlPlayStatus aPlayStatus, + uint32_t aSongLen, uint32_t aSongPos, + BluetoothAvrcpResultHandler* aRes) MOZ_OVERRIDE; + + void ListPlayerAppAttrRsp(int aNumAttr, + const BluetoothAvrcpPlayerAttribute* aPAttrs, + BluetoothAvrcpResultHandler* aRes) MOZ_OVERRIDE; + + void ListPlayerAppValueRsp(int aNumVal, uint8_t* aPVals, + BluetoothAvrcpResultHandler* aRes) MOZ_OVERRIDE; + + void GetPlayerAppValueRsp(uint8_t aNumAttrs, const uint8_t* aIds, + const uint8_t* aValues, + BluetoothAvrcpResultHandler* aRes) MOZ_OVERRIDE; + + void GetPlayerAppAttrTextRsp(int aNumAttr, const uint8_t* aIds, + const char** aTexts, + BluetoothAvrcpResultHandler* aRes) MOZ_OVERRIDE; + + void GetPlayerAppValueTextRsp(int aNumVal, const uint8_t* aIds, + const char** aTexts, + BluetoothAvrcpResultHandler* aRes) MOZ_OVERRIDE; + + void GetElementAttrRsp(uint8_t aNumAttr, + const BluetoothAvrcpElementAttribute* aAttr, + BluetoothAvrcpResultHandler* aRes) MOZ_OVERRIDE; + + void SetPlayerAppValueRsp(BluetoothAvrcpStatus aRspStatus, + BluetoothAvrcpResultHandler* aRes) MOZ_OVERRIDE; + + void RegisterNotificationRsp(BluetoothAvrcpEvent aEvent, + BluetoothAvrcpNotification aType, + const BluetoothAvrcpNotificationParam& aParam, + BluetoothAvrcpResultHandler* aRes) MOZ_OVERRIDE; + + void SetVolume(uint8_t aVolume, + BluetoothAvrcpResultHandler* aRes) MOZ_OVERRIDE; + +private: + void DispatchError(BluetoothAvrcpResultHandler* aRes, + BluetoothStatus aStatus); + + BluetoothDaemonAvrcpModule* mModule; +}; + +END_BLUETOOTH_NAMESPACE + +#endif diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -70,6 +70,39 @@ } nsresult +Convert(int32_t aIn, BluetoothDeviceType& aOut) +{ + static const BluetoothDeviceType sDeviceType[] = { + CONVERT(0x00, static_cast(0)), // invalid, required by gcc + CONVERT(0x01, DEVICE_TYPE_BREDR), + CONVERT(0x02, DEVICE_TYPE_BLE), + CONVERT(0x03, DEVICE_TYPE_DUAL) + }; + if (NS_WARN_IF(!aIn) || + NS_WARN_IF(static_cast(aIn) >= MOZ_ARRAY_LENGTH(sDeviceType))) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sDeviceType[aIn]; + return NS_OK; +} + +nsresult +Convert(int32_t aIn, BluetoothScanMode& aOut) +{ + static const BluetoothScanMode sScanMode[] = { + CONVERT(0x00, SCAN_MODE_NONE), + CONVERT(0x01, SCAN_MODE_CONNECTABLE), + CONVERT(0x02, SCAN_MODE_CONNECTABLE_DISCOVERABLE) + }; + if (NS_WARN_IF(aIn < 0) || + NS_WARN_IF(static_cast(aIn) >= MOZ_ARRAY_LENGTH(sScanMode))) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sScanMode[aIn]; + return NS_OK; +} + +nsresult Convert(uint8_t aIn, bool& aOut) { static const bool sBool[] = { @@ -98,6 +131,13 @@ } nsresult +Convert(uint8_t aIn, unsigned long& aOut) +{ + aOut = static_cast(aIn); + return NS_OK; +} + +nsresult Convert(uint8_t aIn, BluetoothA2dpAudioState& aOut) { static const BluetoothA2dpAudioState sAudioState[] = { @@ -143,6 +183,93 @@ } nsresult +Convert(uint8_t aIn, BluetoothAvrcpEvent& aOut) +{ + static const BluetoothAvrcpEvent sAvrcpEvent[] = { + CONVERT(0x00, static_cast(0)), + CONVERT(0x01, AVRCP_EVENT_PLAY_STATUS_CHANGED), + CONVERT(0x02, AVRCP_EVENT_TRACK_CHANGE), + CONVERT(0x03, AVRCP_EVENT_TRACK_REACHED_END), + CONVERT(0x04, AVRCP_EVENT_TRACK_REACHED_START), + CONVERT(0x05, AVRCP_EVENT_PLAY_POS_CHANGED), + CONVERT(0x06, static_cast(0)), + CONVERT(0x07, static_cast(0)), + CONVERT(0x08, AVRCP_EVENT_APP_SETTINGS_CHANGED) + }; + if (NS_WARN_IF(!aIn) || + NS_WARN_IF(aIn == 0x06) || + NS_WARN_IF(aIn == 0x07) || + NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sAvrcpEvent))) { + aOut = static_cast(0); // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sAvrcpEvent[aIn]; + return NS_OK; +} + +nsresult +Convert(uint8_t aIn, BluetoothAvrcpMediaAttribute& aOut) +{ + static const BluetoothAvrcpMediaAttribute sAvrcpMediaAttribute[] = { + CONVERT(0x00, static_cast(0)), + CONVERT(0x01, AVRCP_MEDIA_ATTRIBUTE_TITLE), + CONVERT(0x02, AVRCP_MEDIA_ATTRIBUTE_ARTIST), + CONVERT(0x03, AVRCP_MEDIA_ATTRIBUTE_ALBUM), + CONVERT(0x04, AVRCP_MEDIA_ATTRIBUTE_TRACK_NUM), + CONVERT(0x05, AVRCP_MEDIA_ATTRIBUTE_NUM_TRACKS), + CONVERT(0x06, AVRCP_MEDIA_ATTRIBUTE_GENRE), + CONVERT(0x07, AVRCP_MEDIA_ATTRIBUTE_PLAYING_TIME) + }; + if (NS_WARN_IF(!aIn) || + NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sAvrcpMediaAttribute))) { + // silences compiler warning + aOut = static_cast(0); + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sAvrcpMediaAttribute[aIn]; + return NS_OK; +} + +nsresult +Convert(uint8_t aIn, BluetoothAvrcpPlayerAttribute& aOut) +{ + static const BluetoothAvrcpPlayerAttribute sAvrcpPlayerAttribute[] = { + CONVERT(0x00, static_cast(0)), + CONVERT(0x01, AVRCP_PLAYER_ATTRIBUTE_EQUALIZER), + CONVERT(0x02, AVRCP_PLAYER_ATTRIBUTE_REPEAT), + CONVERT(0x03, AVRCP_PLAYER_ATTRIBUTE_SHUFFLE), + CONVERT(0x04, AVRCP_PLAYER_ATTRIBUTE_SCAN) + }; + if (NS_WARN_IF(!aIn) || + NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sAvrcpPlayerAttribute))) { + // silences compiler warning + aOut = static_cast(0); + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sAvrcpPlayerAttribute[aIn]; + return NS_OK; +} + +nsresult +Convert(uint8_t aIn, BluetoothAvrcpRemoteFeature& aOut) +{ + static const BluetoothAvrcpRemoteFeature sAvrcpRemoteFeature[] = { + CONVERT(0x00, AVRCP_REMOTE_FEATURE_NONE), + CONVERT(0x01, AVRCP_REMOTE_FEATURE_METADATA), + CONVERT(0x02, AVRCP_REMOTE_FEATURE_ABSOLUTE_VOLUME), + CONVERT(0x03, AVRCP_REMOTE_FEATURE_BROWSE) + }; + if (NS_WARN_IF(!aIn) || + NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sAvrcpRemoteFeature))) { + // silences compiler warning + aOut = static_cast(0); + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sAvrcpRemoteFeature[aIn]; + return NS_OK; +} + +nsresult Convert(uint8_t aIn, BluetoothBondState& aOut) { static const BluetoothBondState sBondState[] = { @@ -249,23 +376,6 @@ } nsresult -Convert(int32_t aIn, BluetoothDeviceType& aOut) -{ - static const BluetoothDeviceType sDeviceType[] = { - CONVERT(0x00, static_cast(0)), // invalid, required by gcc - CONVERT(0x01, DEVICE_TYPE_BREDR), - CONVERT(0x02, DEVICE_TYPE_BLE), - CONVERT(0x03, DEVICE_TYPE_DUAL) - }; - if (NS_WARN_IF(!aIn) || - NS_WARN_IF(static_cast(aIn) >= MOZ_ARRAY_LENGTH(sDeviceType))) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sDeviceType[aIn]; - return NS_OK; -} - -nsresult Convert(uint8_t aIn, BluetoothPropertyType& aOut) { static const BluetoothPropertyType sPropertyType[] = { @@ -318,22 +428,6 @@ } nsresult -Convert(int32_t aIn, BluetoothScanMode& aOut) -{ - static const BluetoothScanMode sScanMode[] = { - CONVERT(0x00, SCAN_MODE_NONE), - CONVERT(0x01, SCAN_MODE_CONNECTABLE), - CONVERT(0x02, SCAN_MODE_CONNECTABLE_DISCOVERABLE) - }; - if (NS_WARN_IF(aIn < 0) || - NS_WARN_IF(static_cast(aIn) >= MOZ_ARRAY_LENGTH(sScanMode))) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sScanMode[aIn]; - return NS_OK; -} - -nsresult Convert(uint8_t aIn, BluetoothSspPairingVariant& aOut) { static const BluetoothSspPairingVariant sSspPairingVariant[] = { @@ -380,6 +474,18 @@ } nsresult +Convert(uint32_t aIn, uint8_t& aOut) +{ + if (NS_WARN_IF(aIn < std::numeric_limits::min()) || + NS_WARN_IF(aIn > std::numeric_limits::max())) { + aOut = 0; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = static_cast(aIn); + return NS_OK; +} + +nsresult Convert(size_t aIn, uint16_t& aOut) { if (NS_WARN_IF(aIn >= (1ul << 16))) { @@ -522,6 +628,50 @@ } nsresult +Convert(BluetoothAvrcpEvent aIn, uint8_t& aOut) +{ + static const uint8_t sValue[] = { + CONVERT(AVRCP_EVENT_PLAY_STATUS_CHANGED, 0x01), + CONVERT(AVRCP_EVENT_TRACK_CHANGE, 0x02), + CONVERT(AVRCP_EVENT_TRACK_REACHED_END, 0x03), + CONVERT(AVRCP_EVENT_TRACK_REACHED_START, 0x04), + CONVERT(AVRCP_EVENT_PLAY_POS_CHANGED, 0x05), + CONVERT(AVRCP_EVENT_APP_SETTINGS_CHANGED, 0x08) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sValue))) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sValue[aIn]; + return NS_OK; +} + +nsresult +Convert(BluetoothAvrcpNotification aIn, uint8_t& aOut) +{ + static const bool sValue[] = { + CONVERT(AVRCP_NTF_INTERIM, 0x00), + CONVERT(AVRCP_NTF_CHANGED, 0x01) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sValue))) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sValue[aIn]; + return NS_OK; +} + +nsresult +Convert(BluetoothAvrcpRemoteFeature aIn, unsigned long& aOut) +{ + if (NS_WARN_IF(aIn < std::numeric_limits::min()) || + NS_WARN_IF(aIn > std::numeric_limits::max())) { + aOut = 0; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = static_cast(aIn); + return NS_OK; +} + +nsresult Convert(BluetoothHandsfreeAtResponse aIn, uint8_t& aOut) { static const uint8_t sAtResponse[] = { @@ -748,6 +898,30 @@ return NS_OK; } +nsresult +Convert(ControlPlayStatus aIn, uint8_t& aOut) +{ + static const uint8_t sValue[] = { + CONVERT(PLAYSTATUS_STOPPED, 0x00), + CONVERT(PLAYSTATUS_PLAYING, 0x01), + CONVERT(PLAYSTATUS_PAUSED, 0x02), + CONVERT(PLAYSTATUS_FWD_SEEK, 0x03), + CONVERT(PLAYSTATUS_REV_SEEK, 0x04) + }; + if (aIn == PLAYSTATUS_ERROR) { + /* This case is handled separately to not populate + * |sValue| with empty entries. */ + aOut = 0xff; + return NS_OK; + } + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sValue))) { + aOut = 0; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sValue[aIn]; + return NS_OK; +} + /* |ConvertArray| is a helper for converting arrays. Pass an * instance of this structure as the first argument to |Convert| * to convert an array. The output type has to support the array @@ -799,6 +973,142 @@ } nsresult +PackPDU(const BluetoothAvrcpAttributeTextPairs& aIn, + BluetoothDaemonPDU& aPDU) +{ + size_t i; + + for (i = 0; i < aIn.mLength; ++i) { + nsresult rv = PackPDU(aIn.mAttr[i], aPDU); + if (NS_FAILED(rv)) { + return rv; + } + + uint8_t len; + const uint8_t* str; + + if (aIn.mText[i]) { + str = reinterpret_cast(aIn.mText[i]); + len = strlen(aIn.mText[i]) + 1; + } else { + /* write \0 character for NULL strings */ + str = reinterpret_cast("\0"); + len = 1; + } + + rv = PackPDU(len, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + rv = PackPDU(PackArray(str, len), aPDU); + if (NS_FAILED(rv)) { + return rv; + } + } + return NS_OK; +} + +nsresult +PackPDU(const BluetoothAvrcpAttributeValuePairs& aIn, + BluetoothDaemonPDU& aPDU) +{ + size_t i; + + for (i = 0; i < aIn.mLength; ++i) { + nsresult rv = PackPDU(aIn.mAttr[i], aPDU); + if (NS_FAILED(rv)) { + return rv; + } + rv = PackPDU(aIn.mValue[i], aPDU); + if (NS_FAILED(rv)) { + return rv; + } + } + return NS_OK; +} + +nsresult +PackPDU(const BluetoothAvrcpElementAttribute& aIn, BluetoothDaemonPDU& aPDU) +{ + nsresult rv = PackPDU(PackConversion(aIn.mId), aPDU); + if (NS_FAILED(rv)) { + return rv; + } + + const NS_ConvertUTF16toUTF8 cstr(aIn.mValue); + + if (NS_WARN_IF(cstr.Length() == PR_UINT32_MAX)) { + return NS_ERROR_ILLEGAL_VALUE; /* integer overflow detected */ + } + + PRUint32 clen = cstr.Length() + 1; /* include \0 character */ + + rv = PackPDU(PackConversion(clen), aPDU); + if (NS_FAILED(rv)) { + return rv; + } + + return PackPDU( + PackArray(reinterpret_cast(cstr.get()), clen), + aPDU); +} + +nsresult +PackPDU(BluetoothAvrcpEvent aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU(PackConversion(aIn), aPDU); +} + +nsresult +PackPDU(const BluetoothAvrcpEventParamPair& aIn, BluetoothDaemonPDU& aPDU) +{ + nsresult rv; + + switch (aIn.mEvent) { + case AVRCP_EVENT_PLAY_STATUS_CHANGED: + rv = PackPDU(aIn.mParam.mPlayStatus, aPDU); + break; + case AVRCP_EVENT_TRACK_CHANGE: + rv = PackPDU(PackArray(aIn.mParam.mTrack, + MOZ_ARRAY_LENGTH(aIn.mParam.mTrack)), + aPDU); + break; + case AVRCP_EVENT_TRACK_REACHED_END: + /* fall through */ + case AVRCP_EVENT_TRACK_REACHED_START: + /* no data to pack */ + rv = NS_OK; + break; + case AVRCP_EVENT_PLAY_POS_CHANGED: + rv = PackPDU(aIn.mParam.mSongPos, aPDU); + break; + case AVRCP_EVENT_APP_SETTINGS_CHANGED: + /* pack number of attribute-value pairs */ + rv = PackPDU(aIn.mParam.mNumAttr, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + /* pack attribute-value pairs */ + rv = PackPDU(BluetoothAvrcpAttributeValuePairs(aIn.mParam.mIds, + aIn.mParam.mValues, + aIn.mParam.mNumAttr), + aPDU); + break; + default: + rv = NS_ERROR_ILLEGAL_VALUE; + break; + } + return rv; +} + +nsresult +PackPDU(BluetoothAvrcpNotification aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU( + PackConversion(aIn), aPDU); +} + +nsresult PackPDU(const BluetoothConfigurationParameter& aIn, BluetoothDaemonPDU& aPDU) { return PackPDU(aIn.mType, aIn.mLength, @@ -949,6 +1259,12 @@ return PackPDU(PackConversion(aIn), aPDU); } +nsresult +PackPDU(ControlPlayStatus aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU(PackConversion(aIn), aPDU); +} + // // Unpacking // @@ -986,6 +1302,56 @@ } nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAvrcpEvent& aOut) +{ + return UnpackPDU( + aPDU, UnpackConversion(aOut)); +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAvrcpMediaAttribute& aOut) +{ + return UnpackPDU( + aPDU, UnpackConversion(aOut)); +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAvrcpPlayerAttribute& aOut) +{ + return UnpackPDU( + aPDU, UnpackConversion(aOut)); +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAvrcpPlayerSettings& aOut) +{ + /* Read number of attribute-value pairs */ + nsresult rv = UnpackPDU(aPDU, aOut.mNumAttr); + if (NS_FAILED(rv)) { + return rv; + } + /* Read attribute-value pairs */ + for (uint8_t i = 0; i < aOut.mNumAttr; ++i) { + nsresult rv = UnpackPDU(aPDU, aOut.mIds[i]); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(aPDU, aOut.mValues[i]); + if (NS_FAILED(rv)) { + return rv; + } + } + return NS_OK; +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAvrcpRemoteFeature& aOut) +{ + return UnpackPDU( + aPDU, UnpackConversion(aOut)); +} + +nsresult UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothBondState& aOut) { return UnpackPDU(aPDU, UnpackConversion(aOut)); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.h 2015-01-09 12:36:47.000000000 +0000 @@ -50,6 +50,45 @@ uint8_t mAddr[6]; }; +struct BluetoothAvrcpAttributeTextPairs { + BluetoothAvrcpAttributeTextPairs(const uint8_t* aAttr, + const char** aText, + size_t aLength) + : mAttr(aAttr) + , mText(aText) + , mLength(aLength) + { } + + const uint8_t* mAttr; + const char** mText; + size_t mLength; +}; + +struct BluetoothAvrcpAttributeValuePairs { + BluetoothAvrcpAttributeValuePairs(const uint8_t* aAttr, + const uint8_t* aValue, + size_t aLength) + : mAttr(aAttr) + , mValue(aValue) + , mLength(aLength) + { } + + const uint8_t* mAttr; + const uint8_t* mValue; + size_t mLength; +}; + +struct BluetoothAvrcpEventParamPair { + BluetoothAvrcpEventParamPair(BluetoothAvrcpEvent aEvent, + const BluetoothAvrcpNotificationParam& aParam) + : mEvent(aEvent) + , mParam(aParam) + { } + + BluetoothAvrcpEvent mEvent; + const BluetoothAvrcpNotificationParam& mParam; +}; + struct BluetoothConfigurationParameter { uint8_t mType; uint16_t mLength; @@ -110,6 +149,12 @@ Convert(int aIn, int16_t& aOut); nsresult +Convert(int32_t aIn, BluetoothDeviceType& aOut); + +nsresult +Convert(int32_t aIn, BluetoothScanMode& aOut); + +nsresult Convert(uint8_t aIn, bool& aOut); nsresult @@ -119,6 +164,9 @@ Convert(uint8_t aIn, int& aOut); nsresult +Convert(uint8_t aIn, unsigned long& aOut); + +nsresult Convert(uint8_t aIn, BluetoothA2dpAudioState& aOut); nsresult @@ -128,6 +176,18 @@ Convert(uint8_t aIn, BluetoothAclState& aOut); nsresult +Convert(uint8_t aIn, BluetoothAvrcpEvent& aOut); + +nsresult +Convert(uint8_t aIn, BluetoothAvrcpMediaAttribute& aOut); + +nsresult +Convert(uint8_t aIn, BluetoothAvrcpPlayerAttribute& aOut); + +nsresult +Convert(uint8_t aIn, BluetoothAvrcpRemoteFeature& aOut); + +nsresult Convert(uint8_t aIn, BluetoothHandsfreeAudioState& aOut); nsresult @@ -167,6 +227,9 @@ Convert(uint32_t aIn, int& aOut); nsresult +Convert(uint32_t aIn, uint8_t& aOut); + +nsresult Convert(size_t aIn, uint16_t& aOut); nsresult @@ -191,6 +254,15 @@ Convert(const BluetoothAddress& aIn, nsAString& aOut); nsresult +Convert(BluetoothAvrcpEvent aIn, uint8_t& aOut); + +nsresult +Convert(BluetoothAvrcpNotification aIn, uint8_t& aOut); + +nsresult +Convert(BluetoothAvrcpRemoteFeature aIn, unsigned long& aOut); + +nsresult Convert(BluetoothHandsfreeAtResponse aIn, uint8_t& aOut); nsresult @@ -235,6 +307,9 @@ nsresult Convert(BluetoothSspPairingVariant aIn, nsAString& aOut); +nsresult +Convert(ControlPlayStatus aIn, uint8_t& aOut); + // // Packing // @@ -270,6 +345,26 @@ PackPDU(const BluetoothAddress& aIn, BluetoothDaemonPDU& aPDU); nsresult +PackPDU(const BluetoothAvrcpAttributeTextPairs& aIn, + BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(const BluetoothAvrcpAttributeValuePairs& aIn, + BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(const BluetoothAvrcpElementAttribute& aIn, BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(BluetoothAvrcpEvent aIn, BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(const BluetoothAvrcpEventParamPair& aIn, BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(BluetoothAvrcpNotification aIn, BluetoothDaemonPDU& aPDU); + +nsresult PackPDU(const BluetoothConfigurationParameter& aIn, BluetoothDaemonPDU& aPDU); nsresult @@ -323,6 +418,9 @@ nsresult PackPDU(BluetoothScanMode aIn, BluetoothDaemonPDU& aPDU); +nsresult +PackPDU(ControlPlayStatus aIn, BluetoothDaemonPDU& aPDU); + /* |PackConversion| is a helper for packing converted values. Pass * an instance of this structure to |PackPDU| to convert a value from * the input type to the output type and and write it to the PDU. @@ -576,6 +674,21 @@ } nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAvrcpEvent& aOut); + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAvrcpMediaAttribute& aOut); + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAvrcpPlayerAttribute& aOut); + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAvrcpPlayerSettings& aOut); + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAvrcpRemoteFeature& aOut); + +nsresult UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothBondState& aOut); inline nsresult diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -6,6 +6,7 @@ #include "BluetoothDaemonInterface.h" #include "BluetoothDaemonA2dpInterface.h" +#include "BluetoothDaemonAvrcpInterface.h" #include "BluetoothDaemonHandsfreeInterface.h" #include "BluetoothDaemonHelpers.h" #include "BluetoothDaemonSetupInterface.h" @@ -1356,6 +1357,54 @@ // Protocol handling // +// |BluetoothDaemonProtocol| is the central class for communicating +// with the Bluetooth daemon. It maintains both socket connections +// to the external daemon and implements the complete HAL protocol +// by inheriting from base-class modules. +// +// Each |BluetoothDaemon*Module| class implements an individual +// module of the HAL protocol. Each class contains the abstract +// methods +// +// - |Send|, +// - |RegisterModule|, and +// - |UnregisterModule|. +// +// Module classes use |Send| to send out command PDUs. The socket +// in |BluetoothDaemonProtocol| is required for sending. The abstract +// method hides all these internal details from the modules. +// +// |RegisterModule| is required during module initialization, when +// modules must register themselves at the daemon. The register command +// is not part of the module itself, but contained in the Setup module +// (id of 0x00). The abstract method |RegisterModule| allows modules to +// call into the Setup module for generating the register command. +// +// |UnregisterModule| works like |RegisterModule|, but for cleanups. +// +// |BluetoothDaemonProtocol| also handles PDU receiving. It implements +// the method |Handle| from |BluetoothDaemonPDUConsumer|. The socket +// connections of type |BluetoothDaemonConnection| invoke this method +// to forward received PDUs for processing by higher layers. The +// implementation of |Handle| checks the service id of the PDU and +// forwards it to the correct module class using the module's method +// |HandleSvc|. Further PDU processing is module-dependent. +// +// To summarize the interface between |BluetoothDaemonProtocol| and +// modules; the former implements the abstract methods +// +// - |Send|, +// - |RegisterModule|, and +// - |UnregisterModule|, +// +// which allow modules to send out data. Each module implements the +// method +// +// - |HandleSvc|, +// +// which is called by |BluetoothDaemonProtcol| to hand over received +// PDUs into a module. +// class BluetoothDaemonProtocol MOZ_FINAL : public BluetoothDaemonPDUConsumer , public BluetoothDaemonSetupModule @@ -1363,6 +1412,7 @@ , public BluetoothDaemonSocketModule , public BluetoothDaemonHandsfreeModule , public BluetoothDaemonA2dpModule + , public BluetoothDaemonAvrcpModule { public: BluetoothDaemonProtocol(BluetoothDaemonConnection* aConnection); @@ -1398,6 +1448,8 @@ BluetoothDaemonPDU& aPDU, void* aUserData); void HandleA2dpSvc(const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, void* aUserData); + void HandleAvrcpSvc(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, void* aUserData); BluetoothDaemonConnection* mConnection; nsTArray mUserDataQ; @@ -1475,6 +1527,14 @@ } void +BluetoothDaemonProtocol::HandleAvrcpSvc( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + void* aUserData) +{ + BluetoothDaemonAvrcpModule::HandleSvc(aHeader, aPDU, aUserData); +} + +void BluetoothDaemonProtocol::Handle(BluetoothDaemonPDU& aPDU) { static void (BluetoothDaemonProtocol::* const HandleSvc[])( @@ -1487,7 +1547,10 @@ INIT_ARRAY_AT(BluetoothDaemonHandsfreeModule::SERVICE_ID, &BluetoothDaemonProtocol::HandleHandsfreeSvc), INIT_ARRAY_AT(BluetoothDaemonA2dpModule::SERVICE_ID, - &BluetoothDaemonProtocol::HandleA2dpSvc) + &BluetoothDaemonProtocol::HandleA2dpSvc), + INIT_ARRAY_AT(0x07, nullptr), // Health + INIT_ARRAY_AT(BluetoothDaemonAvrcpModule::SERVICE_ID, + &BluetoothDaemonProtocol::HandleAvrcpSvc) }; BluetoothDaemonPDUHeader header; @@ -2079,7 +2142,13 @@ BluetoothAvrcpInterface* BluetoothDaemonInterface::GetBluetoothAvrcpInterface() { - return nullptr; + if (mAvrcpInterface) { + return mAvrcpInterface; + } + + mAvrcpInterface = new BluetoothDaemonAvrcpInterface(mProtocol); + + return mAvrcpInterface; } END_BLUETOOTH_NAMESPACE diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonInterface.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonInterface.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonInterface.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bluetooth/bluedroid/BluetoothDaemonInterface.h 2015-01-09 12:36:47.000000000 +0000 @@ -13,6 +13,7 @@ class BluetoothDaemonChannel; class BluetoothDaemonA2dpInterface; +class BluetoothDaemonAvrcpInterface; class BluetoothDaemonHandsfreeInterface; class BluetoothDaemonProtocol; class BluetoothDaemonSocketInterface; @@ -129,6 +130,7 @@ nsAutoPtr mSocketInterface; nsAutoPtr mHandsfreeInterface; nsAutoPtr mA2dpInterface; + nsAutoPtr mAvrcpInterface; }; END_BLUETOOTH_NAMESPACE diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bluetooth/BluetoothRilListener.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bluetooth/BluetoothRilListener.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bluetooth/BluetoothRilListener.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bluetooth/BluetoothRilListener.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -10,6 +10,7 @@ #include "nsIIccProvider.h" #include "nsIMobileConnectionInfo.h" #include "nsIMobileConnectionService.h" +#include "nsITelephonyCallInfo.h" #include "nsITelephonyService.h" #include "nsRadioInterfaceLayer.h" // For NS_RILCONTENTHELPER_CONTRACTID. #include "nsServiceManagerUtils.h" @@ -186,48 +187,42 @@ */ NS_IMPL_ISUPPORTS(TelephonyListener, nsITelephonyListener) -NS_IMETHODIMP -TelephonyListener::CallStateChanged(uint32_t aServiceId, - uint32_t aCallIndex, - uint16_t aCallState, - const nsAString& aNumber, - uint16_t aNumberPresentation, - const nsAString& aName, - uint16_t aNamePresentation, - bool aIsOutgoing, - bool aIsEmergency, - bool aIsConference, - bool aIsSwitchable, - bool aIsMergeable) +/** + * @param aSend A boolean indicates whether we need to notify headset or not + */ +nsresult +TelephonyListener::HandleCallInfo(nsITelephonyCallInfo* aInfo, bool aSend) { BluetoothHfpManager* hfp = BluetoothHfpManager::Get(); NS_ENSURE_TRUE(hfp, NS_ERROR_FAILURE); - hfp->HandleCallStateChanged(aCallIndex, aCallState, EmptyString(), aNumber, - aIsOutgoing, aIsConference, true); + uint32_t callIndex; + uint16_t callState; + nsAutoString number; + bool isOutgoing; + bool isConference; + + aInfo->GetCallIndex(&callIndex); + aInfo->GetCallState(&callState); + aInfo->GetNumber(number); + aInfo->GetIsOutgoing(&isOutgoing); + aInfo->GetIsConference(&isConference); + + hfp->HandleCallStateChanged(callIndex, callState, EmptyString(), number, + isOutgoing, isConference, aSend); return NS_OK; } NS_IMETHODIMP -TelephonyListener::EnumerateCallState(uint32_t aServiceId, - uint32_t aCallIndex, - uint16_t aCallState, - const nsAString_internal& aNumber, - uint16_t aNumberPresentation, - const nsAString& aName, - uint16_t aNamePresentation, - bool aIsOutgoing, - bool aIsEmergency, - bool aIsConference, - bool aIsSwitchable, - bool aIsMergeable) +TelephonyListener::CallStateChanged(nsITelephonyCallInfo* aInfo) { - BluetoothHfpManager* hfp = BluetoothHfpManager::Get(); - NS_ENSURE_TRUE(hfp, NS_ERROR_FAILURE); + return HandleCallInfo(aInfo, true); +} - hfp->HandleCallStateChanged(aCallIndex, aCallState, EmptyString(), aNumber, - aIsOutgoing, aIsConference, false); - return NS_OK; +NS_IMETHODIMP +TelephonyListener::EnumerateCallState(nsITelephonyCallInfo* aInfo) +{ + return HandleCallInfo(aInfo, false); } NS_IMETHODIMP diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bluetooth/BluetoothRilListener.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bluetooth/BluetoothRilListener.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bluetooth/BluetoothRilListener.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bluetooth/BluetoothRilListener.h 2015-01-09 12:36:47.000000000 +0000 @@ -13,6 +13,7 @@ #include "nsIIccProvider.h" #include "nsIMobileConnectionService.h" +#include "nsITelephonyCallInfo.h" #include "nsITelephonyService.h" BEGIN_BLUETOOTH_NAMESPACE @@ -61,6 +62,9 @@ virtual ~TelephonyListener() { } bool Listen(bool aStart); + +private: + nsresult HandleCallInfo(nsITelephonyCallInfo* aInfo, bool aSend); }; class BluetoothRilListener diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bluetooth/ipc/BluetoothMessageUtils.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bluetooth/ipc/BluetoothMessageUtils.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bluetooth/ipc/BluetoothMessageUtils.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bluetooth/ipc/BluetoothMessageUtils.h 2015-01-09 12:36:47.000000000 +0000 @@ -22,4 +22,4 @@ } // namespace IPC -#endif // mozilla_dom_bluetooth_ipc_bluetoothchild_h__ +#endif // mozilla_dom_bluetooth_ipc_bluetoothmessageutils_h__ diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bluetooth/moz.build thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bluetooth/moz.build --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bluetooth/moz.build 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bluetooth/moz.build 2015-01-09 12:36:47.000000000 +0000 @@ -49,6 +49,7 @@ 'bluedroid/BluetoothA2dpManager.cpp', 'bluedroid/BluetoothAvrcpHALInterface.cpp', 'bluedroid/BluetoothDaemonA2dpInterface.cpp', + 'bluedroid/BluetoothDaemonAvrcpInterface.cpp', 'bluedroid/BluetoothDaemonHandsfreeInterface.cpp', 'bluedroid/BluetoothDaemonHelpers.cpp', 'bluedroid/BluetoothDaemonInterface.cpp', diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bluetooth2/BluetoothRilListener.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bluetooth2/BluetoothRilListener.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bluetooth2/BluetoothRilListener.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bluetooth2/BluetoothRilListener.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -186,48 +186,42 @@ */ NS_IMPL_ISUPPORTS(TelephonyListener, nsITelephonyListener) -NS_IMETHODIMP -TelephonyListener::CallStateChanged(uint32_t aServiceId, - uint32_t aCallIndex, - uint16_t aCallState, - const nsAString& aNumber, - uint16_t aNumberPresentation, - const nsAString& aName, - uint16_t aNamePresentation, - bool aIsOutgoing, - bool aIsEmergency, - bool aIsConference, - bool aIsSwitchable, - bool aIsMergeable) +/** + * @param aSend A boolean indicates whether we need to notify headset or not + */ +nsresult +TelephonyListener::HandleCallInfo(nsITelephonyCallInfo* aInfo, bool aSend) { BluetoothHfpManager* hfp = BluetoothHfpManager::Get(); NS_ENSURE_TRUE(hfp, NS_ERROR_FAILURE); - hfp->HandleCallStateChanged(aCallIndex, aCallState, EmptyString(), aNumber, - aIsOutgoing, aIsConference, true); + uint32_t callIndex; + uint16_t callState; + nsAutoString number; + bool isOutgoing; + bool isConference; + + aInfo->GetCallIndex(&callIndex); + aInfo->GetCallState(&callState); + aInfo->GetNumber(number); + aInfo->GetIsOutgoing(&isOutgoing); + aInfo->GetIsConference(&isConference); + + hfp->HandleCallStateChanged(callIndex, callState, EmptyString(), number, + isOutgoing, isConference, aSend); return NS_OK; } NS_IMETHODIMP -TelephonyListener::EnumerateCallState(uint32_t aServiceId, - uint32_t aCallIndex, - uint16_t aCallState, - const nsAString_internal& aNumber, - uint16_t aNumberPresentation, - const nsAString& aName, - uint16_t aNamePresentation, - bool aIsOutgoing, - bool aIsEmergency, - bool aIsConference, - bool aIsSwitchable, - bool aIsMergeable) +TelephonyListener::CallStateChanged(nsITelephonyCallInfo* aInfo) { - BluetoothHfpManager* hfp = BluetoothHfpManager::Get(); - NS_ENSURE_TRUE(hfp, NS_ERROR_FAILURE); + return HandleCallInfo(aInfo, true); +} - hfp->HandleCallStateChanged(aCallIndex, aCallState, EmptyString(), aNumber, - aIsOutgoing, aIsConference, false); - return NS_OK; +NS_IMETHODIMP +TelephonyListener::EnumerateCallState(nsITelephonyCallInfo* aInfo) +{ + return HandleCallInfo(aInfo, false); } NS_IMETHODIMP diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bluetooth2/BluetoothRilListener.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bluetooth2/BluetoothRilListener.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bluetooth2/BluetoothRilListener.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bluetooth2/BluetoothRilListener.h 2015-01-09 12:36:47.000000000 +0000 @@ -61,6 +61,9 @@ virtual ~TelephonyListener() { } bool Listen(bool aStart); + +private: + nsresult HandleCallInfo(nsITelephonyCallInfo* aInfo, bool aSend); }; class BluetoothRilListener diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bluetooth2/ipc/BluetoothMessageUtils.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bluetooth2/ipc/BluetoothMessageUtils.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/bluetooth2/ipc/BluetoothMessageUtils.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/bluetooth2/ipc/BluetoothMessageUtils.h 2015-01-09 12:36:47.000000000 +0000 @@ -30,4 +30,4 @@ } // namespace IPC -#endif // mozilla_dom_bluetooth_ipc_bluetoothchild_h__ +#endif // mozilla_dom_bluetooth_ipc_bluetoothmessageutils_h__ diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/browser-element/BrowserElementChildPreload.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/browser-element/BrowserElementChildPreload.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/browser-element/BrowserElementChildPreload.js 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/browser-element/BrowserElementChildPreload.js 2015-01-09 12:36:47.000000000 +0000 @@ -94,7 +94,7 @@ this._isContentWindowCreated = false; this._pendingSetInputMethodActive = []; - this._forceDispatchSelectionStateChanged = false; + this._selectionStateChangedTarget = null; this._init(); }; @@ -594,13 +594,18 @@ _selectionStateChangedHandler: function(e) { e.stopPropagation(); + + if (!this._isContentWindowCreated) { + return; + } + let boundingClientRect = e.boundingClientRect; let isCollapsed = (e.selectedText.length == 0); let isMouseUp = (e.states.indexOf('mouseup') == 0); let canPaste = this._isCommandEnabled("paste"); - if (!this._forceDispatchSelectionStateChanged) { + if (this._selectionStateChangedTarget != e.target) { // SelectionStateChanged events with the following states are not // necessary to trigger the text dialog, bypass these events // by default. @@ -613,25 +618,28 @@ } // The collapsed SelectionStateChanged event is unnecessary to dispatch, - // bypass this event by default. But there is one exception to support - // the shortcut mode which can paste previous copied content easily + // bypass this event by default, but here comes some exceptional cases if (isCollapsed) { if (isMouseUp && canPaste) { - //Dispatch this selection change event to support shortcut mode + // Always dispatch to support shortcut mode which can paste previous + // copied content easily + } else if (e.states.indexOf('blur') == 0) { + // Always dispatch to notify the blur for the focus content } else { return; } } } - // If we select something and selection range is visible, we set the - // forceDispatchSelectionStateChanged flag as true to dispatch the - // next SelectionStateChange event so that the parent side can - // hide the text dialog. + // If we select something and selection range is visible, we cache current + // event's target to selectionStateChangedTarget. + // And dispatch the next SelectionStateChagne event if target is matched, so + // that the parent side can hide the text dialog. + // We clear selectionStateChangedTarget if selection carets are invisible. if (e.visible && !isCollapsed) { - this._forceDispatchSelectionStateChanged = true; + this._selectionStateChangedTarget = e.target; } else { - this._forceDispatchSelectionStateChanged = false; + this._selectionStateChangedTarget = null; } let zoomFactor = content.screen.width / content.innerWidth; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/browser-element/mochitest/browserElement_CopyPaste.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/browser-element/mochitest/browserElement_CopyPaste.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/browser-element/mochitest/browserElement_CopyPaste.js 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/browser-element/mochitest/browserElement_CopyPaste.js 2015-01-09 12:36:47.000000000 +0000 @@ -181,12 +181,15 @@ // Skip mozbrowser test if we're at child process. if (!isChildProcess()) { iframeOuter.addEventListener("mozbrowserselectionstatechanged", function selectchangeforselectall(e) { - iframeOuter.removeEventListener("mozbrowserselectionstatechanged", selectchangeforselectall, true); - ok(true, "got mozbrowserselectionstatechanged event." + stateMeaning); - ok(e.detail, "event.detail is not null." + stateMeaning); - ok(e.detail.width != 0, "event.detail.width is not zero" + stateMeaning); - ok(e.detail.height != 0, "event.detail.height is not zero" + stateMeaning); - SimpleTest.executeSoon(function() { testCopy1(e); }); + if (e.detail.states.indexOf('selectall') == 0) { + iframeOuter.removeEventListener("mozbrowserselectionstatechanged", selectchangeforselectall, true); + ok(true, "got mozbrowserselectionstatechanged event." + stateMeaning); + ok(e.detail, "event.detail is not null." + stateMeaning); + ok(e.detail.width != 0, "event.detail.width is not zero" + stateMeaning); + ok(e.detail.height != 0, "event.detail.height is not zero" + stateMeaning); + ok(e.detail.states, "event.detail.state " + e.detail.states); + SimpleTest.executeSoon(function() { testCopy1(e); }); + } }, true); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/browser-element/mochitest/browserElement_SelectionStateBlur.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/browser-element/mochitest/browserElement_SelectionStateBlur.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/browser-element/mochitest/browserElement_SelectionStateBlur.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/browser-element/mochitest/browserElement_SelectionStateBlur.js 2015-01-09 12:36:47.000000000 +0000 @@ -0,0 +1,57 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Bug 1111433: Send out the SelectionStateChanged event with Blur state + +"use strict"; + +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.setSelectionChangeEnabledPref(true); +browserElementTestHelpers.addPermission(); + +var mm; +var iframe; + +var changefocus = function () { + var elt = content.document.getElementById("text"); + if (elt) { + elt.focus(); + elt.select(); + elt.blur(); + } +} + +function runTest() { + iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + document.body.appendChild(iframe); + + mm = SpecialPowers.getBrowserFrameMessageManager(iframe); + + iframe.src = "data:text/html," + + ""+ + ""; + + var loadtime = 0; + iframe.addEventListener("mozbrowserloadend", function onloadend(e) { + loadtime++; + if (loadtime === 2) { + iframe.removeEventListener("mozbrowserloadend", onloadend); + SimpleTest.executeSoon(function() { testBlur(e); }); + } + }); +} + +function testBlur(e) { + iframe.addEventListener("mozbrowserselectionstatechanged", function selectionstatechanged(e) { + iframe.removeEventListener("mozbrowserselectionstatechanged", selectionstatechanged, true); + ok(e.detail.states.indexOf('blur') == 0, "received state " + e.detail.states); + SimpleTest.finish(); + }, true); + + iframe.focus(); + mm.loadFrameScript('data:,(' + changefocus.toString() + ')();', false); +} + +addEventListener('testready', runTest); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/browser-element/mochitest/mochitest.ini thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/browser-element/mochitest/mochitest.ini --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/browser-element/mochitest/mochitest.ini 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/browser-element/mochitest/mochitest.ini 2015-01-09 12:36:47.000000000 +0000 @@ -53,6 +53,7 @@ browserElement_ScrollEvent.js browserElement_SecurityChange.js browserElement_SendEvent.js + browserElement_SelectionStateBlur.js browserElement_SetInputMethodActive.js browserElement_SetVisible.js browserElement_SetVisibleFrames.js @@ -184,6 +185,8 @@ [test_browserElement_inproc_ScrollEvent.html] [test_browserElement_inproc_SecurityChange.html] skip-if = toolkit == 'android' || (toolkit == 'gonk' && !debug) # android(TIMED_OUT, bug 766586) androidx86(TIMED_OUT, bug 766586) +[test_browserElement_inproc_SelectionStateBlur.html] +skip-if = (toolkit == 'gonk') # Disabled on b2g due to bug 1097419 [test_browserElement_inproc_SendEvent.html] # The setInputMethodActive() tests will timed out on Android [test_browserElement_inproc_SetInputMethodActive.html] diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/browser-element/mochitest/mochitest-oop.ini thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/browser-element/mochitest/mochitest-oop.ini --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/browser-element/mochitest/mochitest-oop.ini 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/browser-element/mochitest/mochitest-oop.ini 2015-01-09 12:36:47.000000000 +0000 @@ -70,6 +70,8 @@ [test_browserElement_oop_ScrollEvent.html] [test_browserElement_oop_SecurityChange.html] skip-if = toolkit == 'android' || (toolkit == 'gonk' && !debug) #TIMED_OUT, bug 766586 +[test_browserElement_oop_SelectionStateBlur.html] +skip-if = (toolkit == 'gonk') # Disabled on b2g due to bug 1097419 [test_browserElement_oop_SendEvent.html] [test_browserElement_oop_SetInputMethodActive.html] skip-if = (os == "android") diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/browser-element/mochitest/test_browserElement_inproc_SelectionStateBlur.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/browser-element/mochitest/test_browserElement_inproc_SelectionStateBlur.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/browser-element/mochitest/test_browserElement_inproc_SelectionStateBlur.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/browser-element/mochitest/test_browserElement_inproc_SelectionStateBlur.html 2015-01-09 12:36:47.000000000 +0000 @@ -0,0 +1,18 @@ + + + + + Test for Bug 1111433 + + + + + +Mozilla Bug 1111433 + + + + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/browser-element/mochitest/test_browserElement_oop_SelectionStateBlur.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/browser-element/mochitest/test_browserElement_oop_SelectionStateBlur.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/browser-element/mochitest/test_browserElement_oop_SelectionStateBlur.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/browser-element/mochitest/test_browserElement_oop_SelectionStateBlur.html 2015-01-09 12:36:47.000000000 +0000 @@ -0,0 +1,18 @@ + + + + + Test for Bug 1111433 + + + + + +Mozilla Bug 1111433 + + + + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/camera/FallbackCameraControl.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/camera/FallbackCameraControl.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/camera/FallbackCameraControl.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/camera/FallbackCameraControl.cpp 2015-01-09 12:36:48.000000000 +0000 @@ -54,18 +54,18 @@ protected: ~FallbackCameraControl(); - virtual nsresult StartPreviewImpl() { return NS_ERROR_NOT_INITIALIZED; } - virtual nsresult StopPreviewImpl() { return NS_ERROR_NOT_INITIALIZED; } - virtual nsresult AutoFocusImpl() { return NS_ERROR_NOT_INITIALIZED; } - virtual nsresult StartFaceDetectionImpl() { return NS_ERROR_NOT_INITIALIZED; } - virtual nsresult StopFaceDetectionImpl() { return NS_ERROR_NOT_INITIALIZED; } - virtual nsresult TakePictureImpl() { return NS_ERROR_NOT_INITIALIZED; } + virtual nsresult StartPreviewImpl() MOZ_OVERRIDE { return NS_ERROR_NOT_INITIALIZED; } + virtual nsresult StopPreviewImpl() MOZ_OVERRIDE { return NS_ERROR_NOT_INITIALIZED; } + virtual nsresult AutoFocusImpl() MOZ_OVERRIDE { return NS_ERROR_NOT_INITIALIZED; } + virtual nsresult StartFaceDetectionImpl() MOZ_OVERRIDE { return NS_ERROR_NOT_INITIALIZED; } + virtual nsresult StopFaceDetectionImpl() MOZ_OVERRIDE { return NS_ERROR_NOT_INITIALIZED; } + virtual nsresult TakePictureImpl() MOZ_OVERRIDE { return NS_ERROR_NOT_INITIALIZED; } virtual nsresult StartRecordingImpl(DeviceStorageFileDescriptor* aFileDescriptor, const StartRecordingOptions* aOptions = nullptr) MOZ_OVERRIDE { return NS_ERROR_NOT_INITIALIZED; } - virtual nsresult StopRecordingImpl() { return NS_ERROR_NOT_INITIALIZED; } - virtual nsresult PushParametersImpl() { return NS_ERROR_NOT_INITIALIZED; } - virtual nsresult PullParametersImpl() { return NS_ERROR_NOT_INITIALIZED; } + virtual nsresult StopRecordingImpl() MOZ_OVERRIDE { return NS_ERROR_NOT_INITIALIZED; } + virtual nsresult PushParametersImpl() MOZ_OVERRIDE { return NS_ERROR_NOT_INITIALIZED; } + virtual nsresult PullParametersImpl() MOZ_OVERRIDE { return NS_ERROR_NOT_INITIALIZED; } private: FallbackCameraControl(const FallbackCameraControl&) MOZ_DELETE; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/canvas/CanvasImageCache.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/canvas/CanvasImageCache.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/canvas/CanvasImageCache.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/canvas/CanvasImageCache.cpp 2015-01-09 12:36:48.000000000 +0000 @@ -162,7 +162,7 @@ NS_IMETHODIMP Observe(nsISupports* aSubject, const char* aTopic, - const char16_t* aSomeData) + const char16_t* aSomeData) MOZ_OVERRIDE { if (!mImageCache || strcmp(aTopic, "memory-pressure")) { return NS_OK; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/canvas/CanvasRenderingContext2D.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/canvas/CanvasRenderingContext2D.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/canvas/CanvasRenderingContext2D.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/canvas/CanvasRenderingContext2D.cpp 2015-01-09 12:36:48.000000000 +0000 @@ -164,7 +164,7 @@ NS_DECL_ISUPPORTS NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport, - nsISupports* aData, bool aAnonymize) + nsISupports* aData, bool aAnonymize) MOZ_OVERRIDE { return MOZ_COLLECT_REPORT( "canvas-2d-pixels", KIND_OTHER, UNITS_BYTES, diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/canvas/CanvasRenderingContext2D.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/canvas/CanvasRenderingContext2D.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/canvas/CanvasRenderingContext2D.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/canvas/CanvasRenderingContext2D.h 2015-01-09 12:36:48.000000000 +0000 @@ -584,15 +584,15 @@ friend class CanvasRenderingContext2DUserData; - virtual void GetImageBuffer(uint8_t** aImageBuffer, int32_t* aFormat); + virtual void GetImageBuffer(uint8_t** aImageBuffer, int32_t* aFormat) MOZ_OVERRIDE; // Given a point, return hit region ID if it exists - nsString GetHitRegion(const mozilla::gfx::Point& aPoint); + nsString GetHitRegion(const mozilla::gfx::Point& aPoint) MOZ_OVERRIDE; // return true and fills in the bound rect if element has a hit region. - bool GetHitRegionRect(Element* aElement, nsRect& aRect); + bool GetHitRegionRect(Element* aElement, nsRect& aRect) MOZ_OVERRIDE; protected: nsresult GetImageDataArray(JSContext* aCx, int32_t aX, int32_t aY, diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/canvas/test/webgl-conformance/generate-wrappers-and-manifest.py thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/canvas/test/webgl-conformance/generate-wrappers-and-manifest.py --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/canvas/test/webgl-conformance/generate-wrappers-and-manifest.py 2015-01-07 22:15:26.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/canvas/test/webgl-conformance/generate-wrappers-and-manifest.py 2015-01-09 12:36:49.000000000 +0000 @@ -31,6 +31,7 @@ ACCEPTABLE_ERRATA_KEYS = set([ 'skip-if', + 'fail-if', ]) GENERATED_HEADER = ''' diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/canvas/test/webgl-conformance/mochitest-errata.ini thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/canvas/test/webgl-conformance/mochitest-errata.ini --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/canvas/test/webgl-conformance/mochitest-errata.ini 2015-01-07 22:15:26.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/canvas/test/webgl-conformance/mochitest-errata.ini 2015-01-09 12:36:49.000000000 +0000 @@ -78,6 +78,12 @@ skip-if = (os == 'b2g') ######################################################################## +# Linux +[_wrappers/test_conformance__extensions__oes-texture-float.html] +# Failures after enabling color_buffer_[half_]float. +fail-if = (os == 'linux') + +######################################################################## # Mac [_wrappers/test_conformance__canvas__drawingbuffer-static-canvas-test.html] # Intermittent crash on OSX. diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/canvas/test/_webgl-conformance.ini thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/canvas/test/_webgl-conformance.ini --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/canvas/test/_webgl-conformance.ini 2015-01-07 22:15:26.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/canvas/test/_webgl-conformance.ini 2015-01-09 12:36:48.000000000 +0000 @@ -499,7 +499,6 @@ [webgl-conformance/_wrappers/test_conformance__buffers__index-validation-with-resized-buffer.html] [webgl-conformance/_wrappers/test_conformance__buffers__index-validation.html] [webgl-conformance/_wrappers/test_conformance__canvas__buffer-offscreen-test.html] -skip-if = os == 'android' # Bug 1102402 - It fails intermittently and causes a lot of retried jobs [webgl-conformance/_wrappers/test_conformance__canvas__buffer-preserve-test.html] [webgl-conformance/_wrappers/test_conformance__canvas__canvas-test.html] [webgl-conformance/_wrappers/test_conformance__canvas__canvas-zero-size.html] @@ -520,6 +519,7 @@ [webgl-conformance/_wrappers/test_conformance__extensions__oes-standard-derivatives.html] [webgl-conformance/_wrappers/test_conformance__extensions__ext-texture-filter-anisotropic.html] [webgl-conformance/_wrappers/test_conformance__extensions__oes-texture-float.html] +fail-if = (os == 'linux') [webgl-conformance/_wrappers/test_conformance__extensions__oes-vertex-array-object.html] [webgl-conformance/_wrappers/test_conformance__extensions__webgl-debug-renderer-info.html] [webgl-conformance/_wrappers/test_conformance__extensions__webgl-debug-shaders.html] @@ -768,7 +768,7 @@ [webgl-conformance/_wrappers/test_conformance__textures__texture-formats-test.html] [webgl-conformance/_wrappers/test_conformance__textures__texture-mips.html] [webgl-conformance/_wrappers/test_conformance__textures__texture-npot-video.html] -skip-if = os == 'win' || buildapp == 'mulet' # Mulet - bug 1089453 (crashes in libLLVM-3.0.so) +skip-if = os == 'win' [webgl-conformance/_wrappers/test_conformance__textures__texture-npot.html] [webgl-conformance/_wrappers/test_conformance__textures__texture-size.html] skip-if = os == 'android' diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/canvas/WebGLContextExtensions.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/canvas/WebGLContextExtensions.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/canvas/WebGLContextExtensions.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/canvas/WebGLContextExtensions.cpp 2015-01-09 12:36:48.000000000 +0000 @@ -33,8 +33,8 @@ WEBGL_EXTENSION_IDENTIFIER(EXT_blend_minmax) WEBGL_EXTENSION_IDENTIFIER(EXT_color_buffer_half_float) WEBGL_EXTENSION_IDENTIFIER(EXT_frag_depth) - WEBGL_EXTENSION_IDENTIFIER(EXT_sRGB) WEBGL_EXTENSION_IDENTIFIER(EXT_shader_texture_lod) + WEBGL_EXTENSION_IDENTIFIER(EXT_sRGB) WEBGL_EXTENSION_IDENTIFIER(EXT_texture_filter_anisotropic) WEBGL_EXTENSION_IDENTIFIER(OES_element_index_uint) WEBGL_EXTENSION_IDENTIFIER(OES_standard_derivatives) @@ -95,24 +95,37 @@ return IsExtensionSupported(ext); } -bool WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const +bool +WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const { if (mDisableExtensions) return false; + // In alphabetical order switch (ext) { - case WebGLExtensionID::OES_vertex_array_object: - case WebGLExtensionID::WEBGL_lose_context: - // Always supported. - return true; + // ANGLE_ + case WebGLExtensionID::ANGLE_instanced_arrays: + return WebGLExtensionInstancedArrays::IsSupported(this); + // EXT_ case WebGLExtensionID::EXT_blend_minmax: return WebGLExtensionBlendMinMax::IsSupported(this); + case WebGLExtensionID::EXT_color_buffer_half_float: + return WebGLExtensionColorBufferHalfFloat::IsSupported(this); + case WebGLExtensionID::EXT_frag_depth: + return WebGLExtensionFragDepth::IsSupported(this); + case WebGLExtensionID::EXT_shader_texture_lod: + return gl->IsExtensionSupported(gl::GLContext::EXT_shader_texture_lod); + case WebGLExtensionID::EXT_sRGB: + return WebGLExtensionSRGB::IsSupported(this); + case WebGLExtensionID::EXT_texture_filter_anisotropic: + return gl->IsExtensionSupported(gl::GLContext::EXT_texture_filter_anisotropic); + + // OES_ case WebGLExtensionID::OES_element_index_uint: return gl->IsSupported(gl::GLFeature::element_index_uint); case WebGLExtensionID::OES_standard_derivatives: return gl->IsSupported(gl::GLFeature::standard_derivatives); - case WebGLExtensionID::OES_texture_float: return gl->IsSupported(gl::GLFeature::texture_float); case WebGLExtensionID::OES_texture_float_linear: @@ -126,22 +139,25 @@ case WebGLExtensionID::OES_texture_half_float_linear: return gl->IsSupported(gl::GLFeature::texture_half_float_linear); - case WebGLExtensionID::EXT_texture_filter_anisotropic: - return gl->IsExtensionSupported(gl::GLContext::EXT_texture_filter_anisotropic); - case WebGLExtensionID::WEBGL_compressed_texture_s3tc: - if (gl->IsExtensionSupported(gl::GLContext::EXT_texture_compression_s3tc)) - return true; - - return gl->IsExtensionSupported(gl::GLContext::EXT_texture_compression_dxt1) && - gl->IsExtensionSupported(gl::GLContext::ANGLE_texture_compression_dxt3) && - gl->IsExtensionSupported(gl::GLContext::ANGLE_texture_compression_dxt5); + case WebGLExtensionID::OES_vertex_array_object: + return true; + // WEBGL_ + case WebGLExtensionID::WEBGL_color_buffer_float: + return WebGLExtensionColorBufferFloat::IsSupported(this); case WebGLExtensionID::WEBGL_compressed_texture_atc: return gl->IsExtensionSupported(gl::GLContext::AMD_compressed_ATC_texture); case WebGLExtensionID::WEBGL_compressed_texture_etc1: return gl->IsExtensionSupported(gl::GLContext::OES_compressed_ETC1_RGB8_texture); case WebGLExtensionID::WEBGL_compressed_texture_pvrtc: return gl->IsExtensionSupported(gl::GLContext::IMG_texture_compression_pvrtc); + case WebGLExtensionID::WEBGL_compressed_texture_s3tc: + if (gl->IsExtensionSupported(gl::GLContext::EXT_texture_compression_s3tc)) + return true; + + return gl->IsExtensionSupported(gl::GLContext::EXT_texture_compression_dxt1) && + gl->IsExtensionSupported(gl::GLContext::ANGLE_texture_compression_dxt3) && + gl->IsExtensionSupported(gl::GLContext::ANGLE_texture_compression_dxt5); case WebGLExtensionID::WEBGL_depth_texture: // WEBGL_depth_texture supports DEPTH_STENCIL textures if (!gl->IsSupported(gl::GLFeature::packed_depth_stencil)) @@ -149,17 +165,11 @@ return gl->IsSupported(gl::GLFeature::depth_texture) || gl->IsExtensionSupported(gl::GLContext::ANGLE_depth_texture); - - case WebGLExtensionID::ANGLE_instanced_arrays: - return WebGLExtensionInstancedArrays::IsSupported(this); - case WebGLExtensionID::EXT_sRGB: - return WebGLExtensionSRGB::IsSupported(this); case WebGLExtensionID::WEBGL_draw_buffers: return WebGLExtensionDrawBuffers::IsSupported(this); - case WebGLExtensionID::EXT_frag_depth: - return WebGLExtensionFragDepth::IsSupported(this); - case WebGLExtensionID::EXT_shader_texture_lod: - return gl->IsExtensionSupported(gl::GLContext::EXT_shader_texture_lod); + case WebGLExtensionID::WEBGL_lose_context: + // We always support this extension. + return true; default: // For warnings-as-errors. @@ -169,15 +179,13 @@ if (Preferences::GetBool("webgl.enable-draft-extensions", false) || IsWebGL2()) { + /* None for now. switch (ext) { - case WebGLExtensionID::EXT_color_buffer_half_float: - return WebGLExtensionColorBufferHalfFloat::IsSupported(this); - case WebGLExtensionID::WEBGL_color_buffer_float: - return WebGLExtensionColorBufferFloat::IsSupported(this); default: // For warnings-as-errors. break; } + */ } return false; @@ -292,38 +300,37 @@ WebGLExtensionBase* obj = nullptr; switch (ext) { - case WebGLExtensionID::OES_element_index_uint: - obj = new WebGLExtensionElementIndexUint(this); - break; - case WebGLExtensionID::OES_standard_derivatives: - obj = new WebGLExtensionStandardDerivatives(this); - break; - case WebGLExtensionID::EXT_texture_filter_anisotropic: - obj = new WebGLExtensionTextureFilterAnisotropic(this); + // ANGLE_ + case WebGLExtensionID::ANGLE_instanced_arrays: + obj = new WebGLExtensionInstancedArrays(this); break; - case WebGLExtensionID::WEBGL_lose_context: - obj = new WebGLExtensionLoseContext(this); + + // EXT_ + case WebGLExtensionID::EXT_blend_minmax: + obj = new WebGLExtensionBlendMinMax(this); break; - case WebGLExtensionID::WEBGL_compressed_texture_s3tc: - obj = new WebGLExtensionCompressedTextureS3TC(this); + case WebGLExtensionID::EXT_color_buffer_half_float: + obj = new WebGLExtensionColorBufferHalfFloat(this); break; - case WebGLExtensionID::WEBGL_compressed_texture_atc: - obj = new WebGLExtensionCompressedTextureATC(this); + case WebGLExtensionID::EXT_frag_depth: + obj = new WebGLExtensionFragDepth(this); break; - case WebGLExtensionID::WEBGL_compressed_texture_etc1: - obj = new WebGLExtensionCompressedTextureETC1(this); + case WebGLExtensionID::EXT_shader_texture_lod: + obj = new WebGLExtensionShaderTextureLod(this); break; - case WebGLExtensionID::WEBGL_compressed_texture_pvrtc: - obj = new WebGLExtensionCompressedTexturePVRTC(this); + case WebGLExtensionID::EXT_sRGB: + obj = new WebGLExtensionSRGB(this); break; - case WebGLExtensionID::WEBGL_debug_renderer_info: - obj = new WebGLExtensionDebugRendererInfo(this); + case WebGLExtensionID::EXT_texture_filter_anisotropic: + obj = new WebGLExtensionTextureFilterAnisotropic(this); break; - case WebGLExtensionID::WEBGL_debug_shaders: - obj = new WebGLExtensionDebugShaders(this); + + // OES_ + case WebGLExtensionID::OES_element_index_uint: + obj = new WebGLExtensionElementIndexUint(this); break; - case WebGLExtensionID::WEBGL_depth_texture: - obj = new WebGLExtensionDepthTexture(this); + case WebGLExtensionID::OES_standard_derivatives: + obj = new WebGLExtensionStandardDerivatives(this); break; case WebGLExtensionID::OES_texture_float: obj = new WebGLExtensionTextureFloat(this); @@ -337,36 +344,44 @@ case WebGLExtensionID::OES_texture_half_float_linear: obj = new WebGLExtensionTextureHalfFloatLinear(this); break; + case WebGLExtensionID::OES_vertex_array_object: + obj = new WebGLExtensionVertexArray(this); + break; + + // WEBGL_ case WebGLExtensionID::WEBGL_color_buffer_float: obj = new WebGLExtensionColorBufferFloat(this); break; - case WebGLExtensionID::EXT_color_buffer_half_float: - obj = new WebGLExtensionColorBufferHalfFloat(this); + case WebGLExtensionID::WEBGL_compressed_texture_atc: + obj = new WebGLExtensionCompressedTextureATC(this); break; - case WebGLExtensionID::WEBGL_draw_buffers: - obj = new WebGLExtensionDrawBuffers(this); + case WebGLExtensionID::WEBGL_compressed_texture_etc1: + obj = new WebGLExtensionCompressedTextureETC1(this); break; - case WebGLExtensionID::OES_vertex_array_object: - obj = new WebGLExtensionVertexArray(this); + case WebGLExtensionID::WEBGL_compressed_texture_pvrtc: + obj = new WebGLExtensionCompressedTexturePVRTC(this); break; - case WebGLExtensionID::ANGLE_instanced_arrays: - obj = new WebGLExtensionInstancedArrays(this); + case WebGLExtensionID::WEBGL_compressed_texture_s3tc: + obj = new WebGLExtensionCompressedTextureS3TC(this); break; - case WebGLExtensionID::EXT_sRGB: - obj = new WebGLExtensionSRGB(this); + case WebGLExtensionID::WEBGL_debug_renderer_info: + obj = new WebGLExtensionDebugRendererInfo(this); break; - case WebGLExtensionID::EXT_frag_depth: - obj = new WebGLExtensionFragDepth(this); + case WebGLExtensionID::WEBGL_debug_shaders: + obj = new WebGLExtensionDebugShaders(this); break; - case WebGLExtensionID::EXT_blend_minmax: - obj = new WebGLExtensionBlendMinMax(this); + case WebGLExtensionID::WEBGL_depth_texture: + obj = new WebGLExtensionDepthTexture(this); break; - case WebGLExtensionID::EXT_shader_texture_lod: - obj = new WebGLExtensionShaderTextureLod(this); + case WebGLExtensionID::WEBGL_draw_buffers: + obj = new WebGLExtensionDrawBuffers(this); + break; + case WebGLExtensionID::WEBGL_lose_context: + obj = new WebGLExtensionLoseContext(this); break; + default: MOZ_ASSERT(false, "should not get there."); - break; } mExtensions[ext] = obj; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/canvas/WebGLContext.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/canvas/WebGLContext.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/canvas/WebGLContext.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/canvas/WebGLContext.h 2015-01-09 12:36:48.000000000 +0000 @@ -192,7 +192,7 @@ NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(WebGLContext, nsIDOMWebGLRenderingContext) - virtual JSObject* WrapObject(JSContext* cx) = 0; + virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE = 0; NS_DECL_NSIDOMWEBGLRENDERINGCONTEXT diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/cellbroadcast/ipc/CellBroadcastParent.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/cellbroadcast/ipc/CellBroadcastParent.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/cellbroadcast/ipc/CellBroadcastParent.h 2015-01-07 22:15:26.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/cellbroadcast/ipc/CellBroadcastParent.h 2015-01-09 12:36:49.000000000 +0000 @@ -28,11 +28,11 @@ // MOZ_FINAL suppresses -Werror,-Wdelete-non-virtual-dtor ~CellBroadcastParent() {}; - virtual void ActorDestroy(ActorDestroyReason aWhy); + virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; }; } // namespace cellbroadcast } // namespace dom } // namespace mozilla -#endif // mozilla_dom_cellbroadcast_CellBroadcastParent_h \ No newline at end of file +#endif // mozilla_dom_cellbroadcast_CellBroadcastParent_h diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/crypto/CryptoKey.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/crypto/CryptoKey.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/crypto/CryptoKey.h 2015-01-07 22:15:26.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/crypto/CryptoKey.h 2015-01-09 12:36:50.000000000 +0000 @@ -139,7 +139,7 @@ SECKEYPublicKey* GetPublicKey() const; // For nsNSSShutDownObject - virtual void virtualDestroyNSSReference(); + virtual void virtualDestroyNSSReference() MOZ_OVERRIDE; void destructorSafeDestroyNSSReference(); // Serialization and deserialization convenience methods diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/crypto/WebCryptoTask.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/crypto/WebCryptoTask.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/crypto/WebCryptoTask.cpp 2015-01-07 22:15:26.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/crypto/WebCryptoTask.cpp 2015-01-09 12:36:50.000000000 +0000 @@ -2104,12 +2104,14 @@ return NS_OK; } - virtual void Resolve() { + virtual void Resolve() MOZ_OVERRIDE + { mKey->SetSymKey(mKeyData); mResultPromise->MaybeResolve(mKey); } - virtual void Cleanup() { + virtual void Cleanup() MOZ_OVERRIDE + { mKey = nullptr; } }; @@ -2744,7 +2746,8 @@ return NS_OK; } - virtual void Resolve() MOZ_OVERRIDE { + virtual void Resolve() MOZ_OVERRIDE + { mTask->SetData(mResult); mTask->DispatchWithPromise(mResultPromise); mResolved = true; @@ -2777,7 +2780,8 @@ nsRefPtr mTask; bool mResolved; - virtual void Resolve() MOZ_OVERRIDE { + virtual void Resolve() MOZ_OVERRIDE + { mTask->SetKeyData(KeyEncryptTask::mResult); mTask->DispatchWithPromise(KeyEncryptTask::mResultPromise); mResolved = true; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/datastore/DataStoreService.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/datastore/DataStoreService.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/datastore/DataStoreService.cpp 2015-01-07 22:15:26.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/datastore/DataStoreService.cpp 2015-01-09 12:36:50.000000000 +0000 @@ -1005,9 +1005,12 @@ return; } + nsCOMPtr global = do_QueryInterface(aWindow); + MOZ_ASSERT(global); + JSAutoCompartment ac(cx, dataStoreJS); nsRefPtr dataStoreObj = new DataStoreImpl(dataStoreJS, - aWindow); + global); nsRefPtr exposedStore = new DataStore(aWindow); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/devicestorage/nsDeviceStorage.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/devicestorage/nsDeviceStorage.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/devicestorage/nsDeviceStorage.cpp 2015-01-07 22:15:26.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/devicestorage/nsDeviceStorage.cpp 2015-01-09 12:36:50.000000000 +0000 @@ -2202,21 +2202,21 @@ } NS_IMETHODIMP -nsDOMDeviceStorageCursor::GetPrincipal(nsIPrincipal * *aRequestingPrincipal) +nsDOMDeviceStorageCursor::GetPrincipal(nsIPrincipal** aRequestingPrincipal) { NS_IF_ADDREF(*aRequestingPrincipal = mPrincipal); return NS_OK; } NS_IMETHODIMP -nsDOMDeviceStorageCursor::GetWindow(nsIDOMWindow * *aRequestingWindow) +nsDOMDeviceStorageCursor::GetWindow(nsIDOMWindow** aRequestingWindow) { NS_IF_ADDREF(*aRequestingWindow = GetOwner()); return NS_OK; } NS_IMETHODIMP -nsDOMDeviceStorageCursor::GetElement(nsIDOMElement * *aRequestingElement) +nsDOMDeviceStorageCursor::GetElement(nsIDOMElement** aRequestingElement) { *aRequestingElement = nullptr; return NS_OK; @@ -2900,7 +2900,7 @@ NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(DeviceStorageRequest, nsIContentPermissionRequest) - NS_IMETHOD Run() + NS_IMETHOD Run() MOZ_OVERRIDE { MOZ_ASSERT(NS_IsMainThread()); @@ -2912,7 +2912,7 @@ return nsContentPermissionUtils::AskPermission(this, mWindow); } - NS_IMETHODIMP GetTypes(nsIArray** aTypes) + NS_IMETHODIMP GetTypes(nsIArray** aTypes) MOZ_OVERRIDE { nsCString type; nsresult rv = @@ -2932,25 +2932,25 @@ return nsContentPermissionUtils::CreatePermissionArray(type, access, emptyOptions, aTypes); } - NS_IMETHOD GetPrincipal(nsIPrincipal * *aRequestingPrincipal) + NS_IMETHOD GetPrincipal(nsIPrincipal * *aRequestingPrincipal) MOZ_OVERRIDE { NS_IF_ADDREF(*aRequestingPrincipal = mPrincipal); return NS_OK; } - NS_IMETHOD GetWindow(nsIDOMWindow * *aRequestingWindow) + NS_IMETHOD GetWindow(nsIDOMWindow * *aRequestingWindow) MOZ_OVERRIDE { NS_IF_ADDREF(*aRequestingWindow = mWindow); return NS_OK; } - NS_IMETHOD GetElement(nsIDOMElement * *aRequestingElement) + NS_IMETHOD GetElement(nsIDOMElement * *aRequestingElement) MOZ_OVERRIDE { *aRequestingElement = nullptr; return NS_OK; } - NS_IMETHOD Cancel() + NS_IMETHOD Cancel() MOZ_OVERRIDE { nsCOMPtr event = new PostErrorEvent(mRequest.forget(), @@ -2958,7 +2958,7 @@ return NS_DispatchToMainThread(event); } - NS_IMETHOD Allow(JS::HandleValue aChoices) + NS_IMETHOD Allow(JS::HandleValue aChoices) MOZ_OVERRIDE { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aChoices.isUndefined()); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/events/DataTransfer.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/events/DataTransfer.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/events/DataTransfer.h 2015-01-07 22:15:26.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/events/DataTransfer.h 2015-01-09 12:36:50.000000000 +0000 @@ -104,7 +104,7 @@ DataTransfer(nsISupports* aParent, uint32_t aEventType, bool aIsExternal, int32_t aClipboardType); - virtual JSObject* WrapObject(JSContext* aCx); + virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE; nsISupports* GetParentObject() { return mParent; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/events/DOMEventTargetHelper.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/events/DOMEventTargetHelper.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/events/DOMEventTargetHelper.h 2015-01-07 22:15:26.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/events/DOMEventTargetHelper.h 2015-01-09 12:36:50.000000000 +0000 @@ -271,11 +271,11 @@ using _class::RemoveEventListener; \ NS_FORWARD_NSIDOMEVENTTARGET(_class::) \ virtual mozilla::EventListenerManager* \ - GetOrCreateListenerManager() { \ + GetOrCreateListenerManager() MOZ_OVERRIDE { \ return _class::GetOrCreateListenerManager(); \ } \ virtual mozilla::EventListenerManager* \ - GetExistingListenerManager() const { \ + GetExistingListenerManager() const MOZ_OVERRIDE { \ return _class::GetExistingListenerManager(); \ } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/events/Event.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/events/Event.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/events/Event.h 2015-01-07 22:15:26.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/events/Event.h 2015-01-09 12:36:50.000000000 +0000 @@ -292,28 +292,28 @@ NS_FORWARD_NSIDOMEVENT(Event::) #define NS_FORWARD_NSIDOMEVENT_NO_SERIALIZATION_NO_DUPLICATION(_to) \ - NS_IMETHOD GetType(nsAString& aType){ return _to GetType(aType); } \ - NS_IMETHOD GetTarget(nsIDOMEventTarget * *aTarget) { return _to GetTarget(aTarget); } \ - NS_IMETHOD GetCurrentTarget(nsIDOMEventTarget * *aCurrentTarget) { return _to GetCurrentTarget(aCurrentTarget); } \ - NS_IMETHOD GetEventPhase(uint16_t *aEventPhase) { return _to GetEventPhase(aEventPhase); } \ - NS_IMETHOD GetBubbles(bool *aBubbles) { return _to GetBubbles(aBubbles); } \ - NS_IMETHOD GetCancelable(bool *aCancelable) { return _to GetCancelable(aCancelable); } \ - NS_IMETHOD GetTimeStamp(DOMTimeStamp *aTimeStamp) { return _to GetTimeStamp(aTimeStamp); } \ - NS_IMETHOD StopPropagation(void) { return _to StopPropagation(); } \ - NS_IMETHOD PreventDefault(void) { return _to PreventDefault(); } \ - NS_IMETHOD InitEvent(const nsAString & eventTypeArg, bool canBubbleArg, bool cancelableArg) { return _to InitEvent(eventTypeArg, canBubbleArg, cancelableArg); } \ - NS_IMETHOD GetDefaultPrevented(bool *aDefaultPrevented) { return _to GetDefaultPrevented(aDefaultPrevented); } \ - NS_IMETHOD StopImmediatePropagation(void) { return _to StopImmediatePropagation(); } \ - NS_IMETHOD GetOriginalTarget(nsIDOMEventTarget** aOriginalTarget) { return _to GetOriginalTarget(aOriginalTarget); } \ - NS_IMETHOD GetExplicitOriginalTarget(nsIDOMEventTarget** aExplicitOriginalTarget) { return _to GetExplicitOriginalTarget(aExplicitOriginalTarget); } \ - NS_IMETHOD GetPreventDefault(bool* aRetval) { return _to GetPreventDefault(aRetval); } \ - NS_IMETHOD GetIsTrusted(bool* aIsTrusted) { return _to GetIsTrusted(aIsTrusted); } \ - NS_IMETHOD SetTarget(nsIDOMEventTarget *aTarget) { return _to SetTarget(aTarget); } \ - NS_IMETHOD_(bool) IsDispatchStopped(void) { return _to IsDispatchStopped(); } \ - NS_IMETHOD_(WidgetEvent*) GetInternalNSEvent(void) { return _to GetInternalNSEvent(); } \ - NS_IMETHOD_(void) SetTrusted(bool aTrusted) { _to SetTrusted(aTrusted); } \ - NS_IMETHOD_(void) SetOwner(EventTarget* aOwner) { _to SetOwner(aOwner); } \ - NS_IMETHOD_(Event*) InternalDOMEvent() { return _to InternalDOMEvent(); } + NS_IMETHOD GetType(nsAString& aType) MOZ_OVERRIDE { return _to GetType(aType); } \ + NS_IMETHOD GetTarget(nsIDOMEventTarget** aTarget) MOZ_OVERRIDE { return _to GetTarget(aTarget); } \ + NS_IMETHOD GetCurrentTarget(nsIDOMEventTarget** aCurrentTarget) MOZ_OVERRIDE { return _to GetCurrentTarget(aCurrentTarget); } \ + NS_IMETHOD GetEventPhase(uint16_t* aEventPhase) MOZ_OVERRIDE { return _to GetEventPhase(aEventPhase); } \ + NS_IMETHOD GetBubbles(bool* aBubbles) MOZ_OVERRIDE { return _to GetBubbles(aBubbles); } \ + NS_IMETHOD GetCancelable(bool* aCancelable) MOZ_OVERRIDE { return _to GetCancelable(aCancelable); } \ + NS_IMETHOD GetTimeStamp(DOMTimeStamp* aTimeStamp) MOZ_OVERRIDE { return _to GetTimeStamp(aTimeStamp); } \ + NS_IMETHOD StopPropagation(void) MOZ_OVERRIDE { return _to StopPropagation(); } \ + NS_IMETHOD PreventDefault(void) MOZ_OVERRIDE { return _to PreventDefault(); } \ + NS_IMETHOD InitEvent(const nsAString& eventTypeArg, bool canBubbleArg, bool cancelableArg) MOZ_OVERRIDE { return _to InitEvent(eventTypeArg, canBubbleArg, cancelableArg); } \ + NS_IMETHOD GetDefaultPrevented(bool* aDefaultPrevented) MOZ_OVERRIDE { return _to GetDefaultPrevented(aDefaultPrevented); } \ + NS_IMETHOD StopImmediatePropagation(void) MOZ_OVERRIDE { return _to StopImmediatePropagation(); } \ + NS_IMETHOD GetOriginalTarget(nsIDOMEventTarget** aOriginalTarget) MOZ_OVERRIDE { return _to GetOriginalTarget(aOriginalTarget); } \ + NS_IMETHOD GetExplicitOriginalTarget(nsIDOMEventTarget** aExplicitOriginalTarget) MOZ_OVERRIDE { return _to GetExplicitOriginalTarget(aExplicitOriginalTarget); } \ + NS_IMETHOD GetPreventDefault(bool* aRetval) MOZ_OVERRIDE { return _to GetPreventDefault(aRetval); } \ + NS_IMETHOD GetIsTrusted(bool* aIsTrusted) MOZ_OVERRIDE { return _to GetIsTrusted(aIsTrusted); } \ + NS_IMETHOD SetTarget(nsIDOMEventTarget* aTarget) MOZ_OVERRIDE { return _to SetTarget(aTarget); } \ + NS_IMETHOD_(bool) IsDispatchStopped(void) MOZ_OVERRIDE { return _to IsDispatchStopped(); } \ + NS_IMETHOD_(WidgetEvent*) GetInternalNSEvent(void) MOZ_OVERRIDE { return _to GetInternalNSEvent(); } \ + NS_IMETHOD_(void) SetTrusted(bool aTrusted) MOZ_OVERRIDE { _to SetTrusted(aTrusted); } \ + NS_IMETHOD_(void) SetOwner(EventTarget* aOwner) MOZ_OVERRIDE { _to SetOwner(aOwner); } \ + NS_IMETHOD_(Event*) InternalDOMEvent() MOZ_OVERRIDE { return _to InternalDOMEvent(); } #define NS_FORWARD_TO_EVENT_NO_SERIALIZATION_NO_DUPLICATION \ NS_FORWARD_NSIDOMEVENT_NO_SERIALIZATION_NO_DUPLICATION(Event::) diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/events/ScrollAreaEvent.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/events/ScrollAreaEvent.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/events/ScrollAreaEvent.h 2015-01-07 22:15:26.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/events/ScrollAreaEvent.h 2015-01-09 12:36:51.000000000 +0000 @@ -31,7 +31,7 @@ NS_FORWARD_NSIDOMUIEVENT(UIEvent::) NS_FORWARD_TO_EVENT_NO_SERIALIZATION_NO_DUPLICATION - NS_IMETHOD DuplicatePrivateData() + NS_IMETHOD DuplicatePrivateData() MOZ_OVERRIDE { return Event::DuplicatePrivateData(); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/events/UIEvent.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/events/UIEvent.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/events/UIEvent.h 2015-01-07 22:15:26.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/events/UIEvent.h 2015-01-09 12:36:51.000000000 +0000 @@ -177,17 +177,18 @@ #define NS_FORWARD_TO_UIEVENT \ NS_FORWARD_NSIDOMUIEVENT(UIEvent::) \ NS_FORWARD_TO_EVENT_NO_SERIALIZATION_NO_DUPLICATION \ - NS_IMETHOD DuplicatePrivateData() \ + NS_IMETHOD DuplicatePrivateData() MOZ_OVERRIDE \ { \ return UIEvent::DuplicatePrivateData(); \ } \ NS_IMETHOD_(void) Serialize(IPC::Message* aMsg, \ bool aSerializeInterfaceType) \ + MOZ_OVERRIDE \ { \ UIEvent::Serialize(aMsg, aSerializeInterfaceType); \ } \ NS_IMETHOD_(bool) Deserialize(const IPC::Message* aMsg, \ - void** aIter) \ + void** aIter) MOZ_OVERRIDE \ { \ return UIEvent::Deserialize(aMsg, aIter); \ } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/fmradio/FMRadioService.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/fmradio/FMRadioService.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/fmradio/FMRadioService.cpp 2015-01-07 22:15:26.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/fmradio/FMRadioService.cpp 2015-01-09 12:36:51.000000000 +0000 @@ -20,6 +20,7 @@ #include "nsJSUtils.h" #include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/SettingChangeNotificationBinding.h" +#include "mozilla/DebugOnly.h" #define TUNE_THREAD_TIMEOUT_MS 5000 @@ -780,7 +781,7 @@ { mRDSGroupMask = aRDSGroupMask; if (IsFMRadioOn() && mRDSEnabled) { - bool enabled = hal::EnableRDS(mRDSGroupMask | DOM_PARSED_RDS_GROUPS); + DebugOnly enabled = hal::EnableRDS(mRDSGroupMask | DOM_PARSED_RDS_GROUPS); MOZ_ASSERT(enabled); } } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/geolocation/nsGeolocation.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/geolocation/nsGeolocation.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/geolocation/nsGeolocation.cpp 2015-01-07 22:15:26.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/geolocation/nsGeolocation.cpp 2015-01-09 12:36:51.000000000 +0000 @@ -133,7 +133,7 @@ MOZ_COUNT_CTOR(GeolocationSettingsCallback); } - NS_IMETHOD Handle(const nsAString& aName, JS::Handle aResult) + NS_IMETHOD Handle(const nsAString& aName, JS::Handle aResult) MOZ_OVERRIDE { MOZ_ASSERT(NS_IsMainThread()); @@ -159,7 +159,7 @@ return NS_OK; } - NS_IMETHOD HandleError(const nsAString& aName) + NS_IMETHOD HandleError(const nsAString& aName) MOZ_OVERRIDE { if (aName.EqualsASCII(GEO_SETTINGS_ENABLED)) { GPSLOG("Unable to get value for '" GEO_SETTINGS_ENABLED "'"); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/icc/Assertions.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/icc/Assertions.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/icc/Assertions.cpp 2015-01-07 22:15:27.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/icc/Assertions.cpp 2015-01-09 12:36:53.000000000 +0000 @@ -63,19 +63,23 @@ ASSERT_ICC_LOCK_TYPE_EQUALITY(Puk, CARD_LOCK_TYPE_PUK); ASSERT_ICC_LOCK_TYPE_EQUALITY(Puk2, CARD_LOCK_TYPE_PUK2); ASSERT_ICC_LOCK_TYPE_EQUALITY(Nck, CARD_LOCK_TYPE_NCK); +ASSERT_ICC_LOCK_TYPE_EQUALITY(Nsck, CARD_LOCK_TYPE_NSCK); ASSERT_ICC_LOCK_TYPE_EQUALITY(Nck1, CARD_LOCK_TYPE_NCK1); ASSERT_ICC_LOCK_TYPE_EQUALITY(Nck2, CARD_LOCK_TYPE_NCK2); ASSERT_ICC_LOCK_TYPE_EQUALITY(Hnck, CARD_LOCK_TYPE_HNCK); ASSERT_ICC_LOCK_TYPE_EQUALITY(Cck, CARD_LOCK_TYPE_CCK); ASSERT_ICC_LOCK_TYPE_EQUALITY(Spck, CARD_LOCK_TYPE_SPCK); +ASSERT_ICC_LOCK_TYPE_EQUALITY(Pck, CARD_LOCK_TYPE_PCK); ASSERT_ICC_LOCK_TYPE_EQUALITY(Rcck, CARD_LOCK_TYPE_RCCK); ASSERT_ICC_LOCK_TYPE_EQUALITY(Rspck, CARD_LOCK_TYPE_RSPCK); ASSERT_ICC_LOCK_TYPE_EQUALITY(NckPuk, CARD_LOCK_TYPE_NCK_PUK); +ASSERT_ICC_LOCK_TYPE_EQUALITY(NsckPuk, CARD_LOCK_TYPE_NSCK_PUK); ASSERT_ICC_LOCK_TYPE_EQUALITY(Nck1Puk, CARD_LOCK_TYPE_NCK1_PUK); ASSERT_ICC_LOCK_TYPE_EQUALITY(Nck2Puk, CARD_LOCK_TYPE_NCK2_PUK); ASSERT_ICC_LOCK_TYPE_EQUALITY(HnckPuk, CARD_LOCK_TYPE_HNCK_PUK); ASSERT_ICC_LOCK_TYPE_EQUALITY(CckPuk, CARD_LOCK_TYPE_CCK_PUK); ASSERT_ICC_LOCK_TYPE_EQUALITY(SpckPuk, CARD_LOCK_TYPE_SPCK_PUK); +ASSERT_ICC_LOCK_TYPE_EQUALITY(PckPuk, CARD_LOCK_TYPE_PCK_PUK); ASSERT_ICC_LOCK_TYPE_EQUALITY(RcckPuk, CARD_LOCK_TYPE_RCCK_PUK); ASSERT_ICC_LOCK_TYPE_EQUALITY(RspckPuk, CARD_LOCK_TYPE_RSPCK_PUK); ASSERT_ICC_LOCK_TYPE_EQUALITY(Fdn, CARD_LOCK_TYPE_FDN); @@ -106,6 +110,16 @@ #undef ASSERT_ICC_MVNO_TYPE_EQUALITY +/** + * Enum IccService + */ +#define ASSERT_ICC_SERVICE_EQUALITY(webidlState, xpidlState) \ + ASSERT_EQUALITY(IccService, webidlState, xpidlState) + +ASSERT_ICC_SERVICE_EQUALITY(Fdn, CARD_SERVICE_FDN); + +#undef ASSERT_ICC_SERVICE_EQUALITY + #undef ASSERT_EQUALITY } // namespace icc diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/icc/Icc.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/icc/Icc.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/icc/Icc.cpp 2015-01-07 22:15:27.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/icc/Icc.cpp 2015-01-09 12:36:53.000000000 +0000 @@ -7,6 +7,7 @@ #include "mozilla/dom/DOMRequest.h" #include "mozilla/dom/IccInfo.h" #include "mozilla/dom/MozStkCommandEvent.h" +#include "mozilla/dom/Promise.h" #include "mozilla/dom/ScriptSettings.h" #include "nsIIccInfo.h" #include "nsIIccProvider.h" @@ -34,9 +35,9 @@ case IccLockType::RcckPuk: case IccLockType::RspckPuk: return true; + default: + return false; } - - return false; } } // anonymous namespace @@ -404,5 +405,26 @@ return request.forget().downcast(); } +already_AddRefed +Icc::GetServiceState(IccService aService, ErrorResult& aRv) +{ + if (!mProvider) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + nsCOMPtr supports; + nsresult rv = mProvider->GetServiceState(mClientId, GetOwner(), + static_cast(aService), + getter_AddRefs(supports)); + if (NS_FAILED(rv)) { + aRv.Throw(rv); + return nullptr; + } + + nsCOMPtr promise = do_QueryInterface(supports); + return promise.forget(); +} + } // namespace dom } // namespace mozilla diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/icc/Icc.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/icc/Icc.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/icc/Icc.h 2015-01-07 22:15:27.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/icc/Icc.h 2015-01-09 12:36:53.000000000 +0000 @@ -16,6 +16,7 @@ class DOMRequest; class OwningMozIccInfoOrMozGsmIccInfoOrMozCdmaIccInfo; +class Promise; class Icc MOZ_FINAL : public DOMEventTargetHelper { @@ -101,6 +102,9 @@ MatchMvno(IccMvnoType aMvnoType, const nsAString& aMatchData, ErrorResult& aRv); + already_AddRefed + GetServiceState(IccService aService, ErrorResult& aRv); + IMPL_EVENT_HANDLER(iccinfochange) IMPL_EVENT_HANDLER(cardstatechange) IMPL_EVENT_HANDLER(stkcommand) diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/icc/interfaces/nsIIccProvider.idl thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/icc/interfaces/nsIIccProvider.idl --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/icc/interfaces/nsIIccProvider.idl 2015-01-07 22:15:27.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/icc/interfaces/nsIIccProvider.idl 2015-01-09 12:36:53.000000000 +0000 @@ -58,7 +58,7 @@ /** * XPCOM component (in the content process) that provides the ICC information. */ -[scriptable, uuid(bf985ee1-14c9-43c6-a471-8ab52fb24b0d)] +[scriptable, uuid(a203cd2e-2280-4d8e-a687-42b745d322c1)] interface nsIIccProvider : nsISupports { // MUST match enum IccCardState in MozIcc.webidl! @@ -101,22 +101,26 @@ const unsigned long CARD_LOCK_TYPE_PUK = 2; const unsigned long CARD_LOCK_TYPE_PUK2 = 3; const unsigned long CARD_LOCK_TYPE_NCK = 4; - const unsigned long CARD_LOCK_TYPE_NCK1 = 5; - const unsigned long CARD_LOCK_TYPE_NCK2 = 6; - const unsigned long CARD_LOCK_TYPE_HNCK = 7; - const unsigned long CARD_LOCK_TYPE_CCK = 8; - const unsigned long CARD_LOCK_TYPE_SPCK = 9; - const unsigned long CARD_LOCK_TYPE_RCCK = 10; - const unsigned long CARD_LOCK_TYPE_RSPCK = 11; - const unsigned long CARD_LOCK_TYPE_NCK_PUK = 12; - const unsigned long CARD_LOCK_TYPE_NCK1_PUK = 13; - const unsigned long CARD_LOCK_TYPE_NCK2_PUK = 14; - const unsigned long CARD_LOCK_TYPE_HNCK_PUK = 15; - const unsigned long CARD_LOCK_TYPE_CCK_PUK = 16; - const unsigned long CARD_LOCK_TYPE_SPCK_PUK = 17; - const unsigned long CARD_LOCK_TYPE_RCCK_PUK = 18; - const unsigned long CARD_LOCK_TYPE_RSPCK_PUK = 19; - const unsigned long CARD_LOCK_TYPE_FDN = 20; + const unsigned long CARD_LOCK_TYPE_NSCK = 5; + const unsigned long CARD_LOCK_TYPE_NCK1 = 6; + const unsigned long CARD_LOCK_TYPE_NCK2 = 7; + const unsigned long CARD_LOCK_TYPE_HNCK = 8; + const unsigned long CARD_LOCK_TYPE_CCK = 9; + const unsigned long CARD_LOCK_TYPE_SPCK = 10; + const unsigned long CARD_LOCK_TYPE_PCK = 11; + const unsigned long CARD_LOCK_TYPE_RCCK = 12; + const unsigned long CARD_LOCK_TYPE_RSPCK = 13; + const unsigned long CARD_LOCK_TYPE_NCK_PUK = 14; + const unsigned long CARD_LOCK_TYPE_NSCK_PUK = 15; + const unsigned long CARD_LOCK_TYPE_NCK1_PUK = 16; + const unsigned long CARD_LOCK_TYPE_NCK2_PUK = 17; + const unsigned long CARD_LOCK_TYPE_HNCK_PUK = 18; + const unsigned long CARD_LOCK_TYPE_CCK_PUK = 19; + const unsigned long CARD_LOCK_TYPE_SPCK_PUK = 20; + const unsigned long CARD_LOCK_TYPE_PCK_PUK = 21; + const unsigned long CARD_LOCK_TYPE_RCCK_PUK = 22; + const unsigned long CARD_LOCK_TYPE_RSPCK_PUK = 23; + const unsigned long CARD_LOCK_TYPE_FDN = 24; // MUST match with enum IccContactType in MozIcc.webidl const unsigned long CARD_CONTACT_TYPE_ADN = 0; @@ -128,6 +132,9 @@ const unsigned long CARD_MVNO_TYPE_SPN = 1; const unsigned long CARD_MVNO_TYPE_GID = 2; + // MUST match with enum IccService in MozIcc.webidl + const unsigned long CARD_SERVICE_FDN = 0; + /** * Called when a content process registers receiving unsolicited messages from * RadioInterfaceLayer in the chrome process. Only a content process that has @@ -239,4 +246,8 @@ in nsIDOMWindow window, in unsigned long mvnoType, in DOMString mvnoData); + + nsISupports getServiceState(in unsigned long clientId, + in nsIDOMWindow window, + in unsigned long service); }; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/icc/tests/marionette/manifest.ini thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/icc/tests/marionette/manifest.ini --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/icc/tests/marionette/manifest.ini 2015-01-07 22:15:27.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/icc/tests/marionette/manifest.ini 2015-01-09 12:36:53.000000000 +0000 @@ -31,3 +31,4 @@ [test_icc_access_invalid_object.js] [test_icc_detected_undetected_event.js] [test_icc_match_mvno.js] +[test_icc_service_state.js] diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/icc/tests/marionette/test_icc_service_state.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/icc/tests/marionette/test_icc_service_state.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/icc/tests/marionette/test_icc_service_state.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/icc/tests/marionette/test_icc_service_state.js 2015-01-09 12:36:53.000000000 +0000 @@ -0,0 +1,28 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +MARIONETTE_TIMEOUT = 60000; +MARIONETTE_HEAD_JS = "head.js"; + +function testUnsupportedService() { + try { + icc.getServiceState("unsupported-service"); + ok(false, "should get exception"); + } catch (aException) { + ok(true, "got exception: " + aException); + } +} + +// Start tests +startTestCommon(function() { + let icc = getMozIcc(); + + // Check fdn service state + return icc.getServiceState("fdn") + .then((aResult) => { + is(aResult, true, "check fdn service state"); + }) + + // Test unsupported service + .then(() => testUnsupportedService()); +}); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/indexedDB/ActorsParent.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/indexedDB/ActorsParent.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/indexedDB/ActorsParent.cpp 2015-01-07 22:15:27.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/indexedDB/ActorsParent.cpp 2015-01-09 12:36:53.000000000 +0000 @@ -5210,7 +5210,7 @@ void NoteBackgroundThread(nsIEventTarget* aBackgroundThread); - NS_INLINE_DECL_REFCOUNTING(QuotaClient) + NS_INLINE_DECL_REFCOUNTING(QuotaClient, MOZ_OVERRIDE) virtual mozilla::dom::quota::Client::Type GetType() MOZ_OVERRIDE; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/interfaces/base/nsIDOMWindowUtils.idl thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/interfaces/base/nsIDOMWindowUtils.idl --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/interfaces/base/nsIDOMWindowUtils.idl 2015-01-07 22:15:27.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/interfaces/base/nsIDOMWindowUtils.idl 2015-01-09 12:36:54.000000000 +0000 @@ -51,7 +51,7 @@ interface nsIJSRAIIHelper; interface nsIContentPermissionRequest; -[scriptable, uuid(9621eb05-b498-4e87-a012-95d817987624)] +[scriptable, uuid(4922a706-a17e-48e0-ab6f-9fe1bbe4e5f7)] interface nsIDOMWindowUtils : nsISupports { /** @@ -199,24 +199,16 @@ /** * Get/set the resolution at which rescalable web content is drawn. - * Currently this is only (some) thebes content. * * Setting a new resolution does *not* trigger reflow. This API is * entirely separate from textZoom and fullZoom; a resolution scale * can be applied together with both textZoom and fullZoom. * - * The effect of is API for gfx code to allocate more or fewer + * The effect of this API is for gfx code to allocate more or fewer * pixels for rescalable content by a factor of |resolution| in - * either or both dimensions. setResolution() together with - * setDisplayport() can be used to implement a non-reflowing - * scale-zoom in concert with another entity that can draw with a - * scale. For example, to scale a content |window| inside a - * by a factor of 2.0 - * - * window.setDisplayport(x, y, oldW / 2.0, oldH / 2.0); - * window.setResolution(2.0, 2.0); - * // elsewhere - * browser.setViewportScale(2.0, 2.0); + * either or both dimensions. The scale at which the content is + * displayed does not change; if that is desired, use + * setResolutionAndScaleTo() instead. * * The caller of this method must have chrome privileges. */ @@ -225,6 +217,19 @@ void getResolution(out float aXResolution, out float aYResolution); /** + * Similar to setResolution(), but also scales the content by the + * amount of the resolution, so that it is displayed at a + * correspondingly larger or smaller size, without the need for + * the caller to set an additional transform. + * + * This can be used to implement a non-reflowing scale-zoom, e.g. + * for pinch-zoom on mobile platforms. + * + * The caller of this method must have chrome privileges. + */ + void setResolutionAndScaleTo(in float aXResolution, in float aYResolution); + + /** * Whether the resolution has been set by the user. * This gives a way to check whether the provided resolution is the default * value or restored from a previous session. diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/ipc/TabChild.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/ipc/TabChild.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/ipc/TabChild.cpp 2015-01-07 22:15:27.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/ipc/TabChild.cpp 2015-01-09 12:36:55.000000000 +0000 @@ -435,7 +435,7 @@ // This is the root layer, so the cumulative resolution is the same // as the resolution. metrics.mPresShellResolution = metrics.GetCumulativeResolution().scale; - utils->SetResolution(metrics.mPresShellResolution, metrics.mPresShellResolution); + utils->SetResolutionAndScaleTo(metrics.mPresShellResolution, metrics.mPresShellResolution); CSSSize scrollPort = metrics.CalculateCompositedSizeInCssPixels(); utils->SetScrollPositionClampingScrollPortSize(scrollPort.width, scrollPort.height); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/AbstractMediaDecoder.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/AbstractMediaDecoder.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/AbstractMediaDecoder.h 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/AbstractMediaDecoder.h 2015-01-09 12:36:55.000000000 +0000 @@ -65,6 +65,9 @@ // Can be called on any thread. virtual void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded) = 0; + // For decoders with a notion of timestamp offset, returns the value in microseconds. + virtual int64_t GetTimestampOffset() const { return 0; } + // Return the duration of the media in microseconds. virtual int64_t GetMediaDuration() = 0; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/encoder/OmxTrackEncoder.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/encoder/OmxTrackEncoder.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/encoder/OmxTrackEncoder.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/encoder/OmxTrackEncoder.cpp 2015-01-09 12:36:56.000000000 +0000 @@ -26,6 +26,13 @@ #define ENCODER_CONFIG_FRAME_RATE 30 // fps #define GET_ENCODED_VIDEO_FRAME_TIMEOUT 100000 // microseconds +OmxVideoTrackEncoder::OmxVideoTrackEncoder() + : VideoTrackEncoder() +{} + +OmxVideoTrackEncoder::~OmxVideoTrackEncoder() +{} + nsresult OmxVideoTrackEncoder::Init(int aWidth, int aHeight, int aDisplayWidth, int aDisplayHeight, TrackRate aTrackRate) @@ -162,6 +169,13 @@ return NS_OK; } +OmxAudioTrackEncoder::OmxAudioTrackEncoder() + : AudioTrackEncoder() +{} + +OmxAudioTrackEncoder::~OmxAudioTrackEncoder() +{} + nsresult OmxAudioTrackEncoder::AppendEncodedFrames(EncodedFrameContainer& aContainer) { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/encoder/OmxTrackEncoder.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/encoder/OmxTrackEncoder.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/encoder/OmxTrackEncoder.h 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/encoder/OmxTrackEncoder.h 2015-01-09 12:36:56.000000000 +0000 @@ -26,9 +26,8 @@ class OmxVideoTrackEncoder: public VideoTrackEncoder { public: - OmxVideoTrackEncoder() - : VideoTrackEncoder() - {} + OmxVideoTrackEncoder(); + ~OmxVideoTrackEncoder(); already_AddRefed GetMetadata() MOZ_OVERRIDE; @@ -46,9 +45,8 @@ class OmxAudioTrackEncoder : public AudioTrackEncoder { public: - OmxAudioTrackEncoder() - : AudioTrackEncoder() - {} + OmxAudioTrackEncoder(); + ~OmxAudioTrackEncoder(); already_AddRefed GetMetadata() = 0; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/fmp4/android/AndroidDecoderModule.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/fmp4/android/AndroidDecoderModule.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/fmp4/android/AndroidDecoderModule.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/fmp4/android/AndroidDecoderModule.cpp 2015-01-09 12:36:56.000000000 +0000 @@ -138,7 +138,7 @@ data.mSync = eglSync; data.mOwns = true; data.mSize = gfx::IntSize(mConfig.display_width, mConfig.display_height); - data.mOriginPos = gl::OriginPos::TopLeft; + data.mOriginPos = gl::OriginPos::BottomLeft; layers::EGLImageImage* typedImg = static_cast(img.get()); typedImg->SetData(data); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/fmp4/gonk/GonkMediaDataDecoder.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/fmp4/gonk/GonkMediaDataDecoder.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/fmp4/gonk/GonkMediaDataDecoder.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/fmp4/gonk/GonkMediaDataDecoder.cpp 2015-01-09 12:36:56.000000000 +0000 @@ -11,7 +11,7 @@ #include "prlog.h" #include -#define GMDD_LOG(...) __android_log_print(ANDROID_LOG_DEBUG, "GonkMediaDataDecoder(blake)", __VA_ARGS__) +#define GMDD_LOG(...) __android_log_print(ANDROID_LOG_DEBUG, "GonkMediaDataDecoder", __VA_ARGS__) #ifdef PR_LOGGING PRLogModuleInfo* GetDemuxerLog(); @@ -89,8 +89,9 @@ GonkMediaDataDecoder::ProcessOutput() { nsRefPtr output; - nsresult rv; - while (true && !mDrainComplete) { + nsresult rv = NS_ERROR_ABORT; + + while (!mDrainComplete) { rv = mManager->Output(mLastStreamOffset, output); if (rv == NS_OK) { mCallback->Output(output); @@ -121,6 +122,7 @@ mDrainComplete = true; return; } + GMDD_LOG("Callback error!"); mCallback->Error(); } } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/fmp4/MP4Reader.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/fmp4/MP4Reader.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/fmp4/MP4Reader.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/fmp4/MP4Reader.cpp 2015-01-09 12:36:56.000000000 +0000 @@ -157,7 +157,7 @@ { MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread."); PlatformDecoderModule::Init(); - mDemuxer = new MP4Demuxer(new MP4Stream(mDecoder->GetResource(), &mDemuxerMonitor), &mDemuxerMonitor); + mDemuxer = new MP4Demuxer(new MP4Stream(mDecoder->GetResource(), &mDemuxerMonitor), GetDecoder()->GetTimestampOffset(), &mDemuxerMonitor); InitLayersBackendType(); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/gtest/MockMediaResource.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/gtest/MockMediaResource.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/gtest/MockMediaResource.h 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/gtest/MockMediaResource.h 2015-01-09 12:36:56.000000000 +0000 @@ -38,7 +38,7 @@ return NS_OK; } virtual nsresult ReadAt(int64_t aOffset, char* aBuffer, uint32_t aCount, - uint32_t* aBytes); + uint32_t* aBytes) MOZ_OVERRIDE; virtual nsresult Seek(int32_t aWhence, int64_t aOffset) MOZ_OVERRIDE { return NS_OK; @@ -57,7 +57,7 @@ virtual bool IsSuspendedByCache() MOZ_OVERRIDE { return false; } virtual bool IsSuspended() MOZ_OVERRIDE { return false; } virtual nsresult ReadFromCache(char* aBuffer, int64_t aOffset, - uint32_t aCount) + uint32_t aCount) MOZ_OVERRIDE { return NS_OK; } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/gtest/TestMP4Demuxer.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/gtest/TestMP4Demuxer.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/gtest/TestMP4Demuxer.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/gtest/TestMP4Demuxer.cpp 2015-01-09 12:36:56.000000000 +0000 @@ -24,7 +24,7 @@ explicit MP4DemuxerBinding(const char* aFileName = "dash_dashinit.mp4") : resource(new MockMediaResource(aFileName)) , mMonitor("TestMP4Demuxer monitor") - , demuxer(new MP4Demuxer(new MP4Stream(resource, &mMonitor), &mMonitor)) + , demuxer(new MP4Demuxer(new MP4Stream(resource, &mMonitor), 0, &mMonitor)) { EXPECT_EQ(NS_OK, resource->Open(nullptr)); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/ContainerParser.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/ContainerParser.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/ContainerParser.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/ContainerParser.cpp 2015-01-09 12:36:56.000000000 +0000 @@ -237,8 +237,8 @@ return false; } - return aData[4] == 'm' && aData[5] == 'o' && aData[6] == 'o' && - aData[7] == 'f'; + return (aData[4] == 'm' && aData[5] == 'o' && aData[6] == 'o' && aData[7] == 'f') || + (aData[4] == 's' && aData[5] == 't' && aData[6] == 'y' && aData[7] == 'p'); } bool ParseStartAndEndTimestamps(const uint8_t* aData, uint32_t aLength, @@ -249,7 +249,11 @@ bool initSegment = IsInitSegmentPresent(aData, aLength); if (initSegment) { mStream = new mp4_demuxer::BufferStream(); - mParser = new mp4_demuxer::MoofParser(mStream, 0, &mMonitor); + // We use a timestampOffset of 0 for ContainerParser, and require + // consumers of ParseStartAndEndTimestamps to add their timestamp offset + // manually. This allows the ContainerParser to be shared across different + // timestampOffsets. + mParser = new mp4_demuxer::MoofParser(mStream, 0, 0, &mMonitor); } else if (!mStream || !mParser) { return false; } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/MediaSource.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/MediaSource.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/MediaSource.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/MediaSource.cpp 2015-01-09 12:36:56.000000000 +0000 @@ -19,10 +19,14 @@ #include "mozilla/dom/TimeRanges.h" #include "mozilla/mozalloc.h" #include "nsContentTypeParser.h" +#include "nsContentUtils.h" #include "nsDebug.h" #include "nsError.h" +#include "nsIEffectiveTLDService.h" #include "nsIRunnable.h" #include "nsIScriptObjectPrincipal.h" +#include "nsIURI.h" +#include "nsNetCID.h" #include "nsPIDOMWindow.h" #include "nsString.h" #include "nsThreadUtils.h" @@ -306,6 +310,49 @@ return NS_SUCCEEDED(rv); } +/* static */ bool +MediaSource::Enabled(JSContext* cx, JSObject* aGlobal) +{ + MOZ_ASSERT(NS_IsMainThread()); + + // Don't use aGlobal across Preferences stuff, which the static + // analysis thinks can GC. + JS::Rooted global(cx, aGlobal); + + bool enabled = Preferences::GetBool("media.mediasource.enabled"); + if (!enabled) { + return false; + } + + // Check whether it's enabled everywhere or just YouTube. + bool restrict = Preferences::GetBool("media.mediasource.youtubeonly", false); + if (!restrict) { + return true; + } + + // We want to restrict to YouTube only. We define that as the + // origin being https://*.youtube.com. + nsIPrincipal* principal = nsContentUtils::ObjectPrincipal(global); + nsCOMPtr uri; + if (NS_FAILED(principal->GetURI(getter_AddRefs(uri))) || !uri) { + return false; + } + + bool isHttps = false; + if (NS_FAILED(uri->SchemeIs("https", &isHttps)) || !isHttps) { + return false; + } + + nsCOMPtr tldServ = + do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID); + NS_ENSURE_TRUE(tldServ, false); + + nsAutoCString eTLDplusOne; + return + NS_SUCCEEDED(tldServ->GetBaseDomain(uri, 0, eTLDplusOne)) && + eTLDplusOne.EqualsLiteral("youtube.com"); +} + bool MediaSource::Attach(MediaSourceDecoder* aDecoder) { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/MediaSourceDecoder.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/MediaSourceDecoder.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/MediaSourceDecoder.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/MediaSourceDecoder.cpp 2015-01-09 12:36:56.000000000 +0000 @@ -129,10 +129,10 @@ } already_AddRefed -MediaSourceDecoder::CreateSubDecoder(const nsACString& aType) +MediaSourceDecoder::CreateSubDecoder(const nsACString& aType, int64_t aTimestampOffset) { MOZ_ASSERT(mReader); - return mReader->CreateSubDecoder(aType); + return mReader->CreateSubDecoder(aType, aTimestampOffset); } void diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/MediaSourceDecoder.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/MediaSourceDecoder.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/MediaSourceDecoder.h 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/MediaSourceDecoder.h 2015-01-09 12:36:56.000000000 +0000 @@ -46,7 +46,8 @@ void AttachMediaSource(dom::MediaSource* aMediaSource); void DetachMediaSource(); - already_AddRefed CreateSubDecoder(const nsACString& aType); + already_AddRefed CreateSubDecoder(const nsACString& aType, + int64_t aTimestampOffset /* microseconds */); void AddTrackBuffer(TrackBuffer* aTrackBuffer); void RemoveTrackBuffer(TrackBuffer* aTrackBuffer); void OnTrackBufferConfigured(TrackBuffer* aTrackBuffer, const MediaInfo& aInfo); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/MediaSource.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/MediaSource.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/MediaSource.h 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/MediaSource.h 2015-01-09 12:36:56.000000000 +0000 @@ -60,6 +60,8 @@ void EndOfStream(const Optional& aError, ErrorResult& aRv); static bool IsTypeSupported(const GlobalObject&, const nsAString& aType); + + static bool Enabled(JSContext* cx, JSObject* aGlobal); /** End WebIDL Methods. */ NS_DECL_ISUPPORTS_INHERITED diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/MediaSourceReader.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/MediaSourceReader.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/MediaSourceReader.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/MediaSourceReader.cpp 2015-01-09 12:36:56.000000000 +0000 @@ -457,14 +457,14 @@ } already_AddRefed -MediaSourceReader::CreateSubDecoder(const nsACString& aType) +MediaSourceReader::CreateSubDecoder(const nsACString& aType, int64_t aTimestampOffset) { if (IsShutdown()) { return nullptr; } MOZ_ASSERT(GetTaskQueue()); nsRefPtr decoder = - new SourceBufferDecoder(new SourceBufferResource(aType), mDecoder); + new SourceBufferDecoder(new SourceBufferResource(aType), mDecoder, aTimestampOffset); nsRefPtr reader(CreateReaderForType(aType, decoder)); if (!reader) { return nullptr; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/MediaSourceReader.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/MediaSourceReader.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/MediaSourceReader.h 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/MediaSourceReader.h 2015-01-09 12:36:56.000000000 +0000 @@ -99,7 +99,8 @@ // Acquires the decoder monitor, and is thus callable on any thread. nsresult GetBuffered(dom::TimeRanges* aBuffered) MOZ_OVERRIDE; - already_AddRefed CreateSubDecoder(const nsACString& aType); + already_AddRefed CreateSubDecoder(const nsACString& aType, + int64_t aTimestampOffset /* microseconds */); void AddTrackBuffer(TrackBuffer* aTrackBuffer); void RemoveTrackBuffer(TrackBuffer* aTrackBuffer); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/SourceBuffer.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/SourceBuffer.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/SourceBuffer.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/SourceBuffer.cpp 2015-01-09 12:36:56.000000000 +0000 @@ -335,7 +335,9 @@ } StartUpdating(); - if (!mTrackBuffer->AppendData(aData, aLength)) { + MOZ_ASSERT(mAppendMode == SourceBufferAppendMode::Segments, + "We don't handle timestampOffset for sequence mode yet"); + if (!mTrackBuffer->AppendData(aData, aLength, mTimestampOffset * USECS_PER_S)) { Optional decodeError(MediaSourceEndOfStreamError::Decode); ErrorResult dummy; mMediaSource->EndOfStream(decodeError, dummy); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/SourceBufferDecoder.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/SourceBufferDecoder.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/SourceBufferDecoder.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/SourceBufferDecoder.cpp 2015-01-09 12:36:56.000000000 +0000 @@ -33,10 +33,12 @@ NS_IMPL_ISUPPORTS0(SourceBufferDecoder) SourceBufferDecoder::SourceBufferDecoder(MediaResource* aResource, - AbstractMediaDecoder* aParentDecoder) + AbstractMediaDecoder* aParentDecoder, + int64_t aTimestampOffset) : mResource(aResource) , mParentDecoder(aParentDecoder) , mReader(nullptr) + , mTimestampOffset(aTimestampOffset) , mMediaDuration(-1) { MOZ_ASSERT(NS_IsMainThread()); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/SourceBufferDecoder.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/SourceBufferDecoder.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/SourceBufferDecoder.h 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/SourceBufferDecoder.h 2015-01-09 12:36:56.000000000 +0000 @@ -32,7 +32,8 @@ public: // This class holds a weak pointer to MediaResource. It's the responsibility // of the caller to manage the memory of the MediaResource object. - SourceBufferDecoder(MediaResource* aResource, AbstractMediaDecoder* aParentDecoder); + SourceBufferDecoder(MediaResource* aResource, AbstractMediaDecoder* aParentDecoder, + int64_t aTimestampOffset /* microseconds */); NS_DECL_THREADSAFE_ISUPPORTS @@ -41,6 +42,7 @@ virtual bool IsTransportSeekable() MOZ_FINAL MOZ_OVERRIDE; virtual bool OnDecodeThread() const MOZ_FINAL MOZ_OVERRIDE; virtual bool OnStateMachineThread() const MOZ_FINAL MOZ_OVERRIDE; + virtual int64_t GetTimestampOffset() const MOZ_FINAL MOZ_OVERRIDE { return mTimestampOffset; } virtual int64_t GetMediaDuration() MOZ_FINAL MOZ_OVERRIDE; virtual layers::ImageContainer* GetImageContainer() MOZ_FINAL MOZ_OVERRIDE; virtual MediaDecoderOwner* GetOwner() MOZ_FINAL MOZ_OVERRIDE; @@ -129,6 +131,7 @@ AbstractMediaDecoder* mParentDecoder; nsRefPtr mReader; + int64_t mTimestampOffset; int64_t mMediaDuration; #ifdef MOZ_EME diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/test/crashtests/1005366.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/test/crashtests/1005366.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/test/crashtests/1005366.html 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/test/crashtests/1005366.html 2015-01-09 12:36:56.000000000 +0000 @@ -6,6 +6,7 @@ /* user_pref("media.mediasource.enabled", true); +user_pref("media.mediasource.youtubeonly", false); */ function boom() diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/test/crashtests/1059035.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/test/crashtests/1059035.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/test/crashtests/1059035.html 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/test/crashtests/1059035.html 2015-01-09 12:36:56.000000000 +0000 @@ -5,6 +5,7 @@ /* user_pref("media.mediasource.enabled", true); +user_pref("media.mediasource.youtubeonly", false); */ function boom() diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/test/crashtests/crashtests.list thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/test/crashtests/crashtests.list --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/test/crashtests/crashtests.list 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/test/crashtests/crashtests.list 2015-01-09 12:36:56.000000000 +0000 @@ -1,4 +1,4 @@ -test-pref(media.mediasource.enabled,true) load 926665.html -test-pref(media.mediasource.enabled,true) load 931388.html -test-pref(media.mediasource.enabled,true) load 1005366.html -test-pref(media.mediasource.enabled,true) load 1059035.html +test-pref(media.mediasource.enabled,true) test-pref(media.mediasource.youtubeonly,false) load 926665.html +test-pref(media.mediasource.enabled,true) test-pref(media.mediasource.youtubeonly,false) load 931388.html +test-pref(media.mediasource.enabled,true) test-pref(media.mediasource.youtubeonly,false) load 1005366.html +test-pref(media.mediasource.enabled,true) test-pref(media.mediasource.youtubeonly,false) load 1059035.html diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/test/mediasource.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/test/mediasource.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/test/mediasource.js 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/test/mediasource.js 2015-01-09 12:36:56.000000000 +0000 @@ -17,7 +17,10 @@ } addLoadEvent(function () { - SpecialPowers.pushPrefEnv({"set": [[ "media.mediasource.enabled", true ]]}, + SpecialPowers.pushPrefEnv({"set": [ + [ "media.mediasource.enabled", true ], + [ "media.mediasource.youtubeonly", false ], + ]}, bootstrapTest); }); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/test/test_MediaSource_disabled.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/test/test_MediaSource_disabled.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/test/test_MediaSource_disabled.html 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/test/test_MediaSource_disabled.html 2015-01-09 12:36:56.000000000 +0000 @@ -19,7 +19,12 @@ SimpleTest.finish(); } -SpecialPowers.pushPrefEnv({"set": [["media.mediasource.enabled", false]]}, +SpecialPowers.pushPrefEnv({"set": + [ + ["media.mediasource.enabled", false], + ["media.mediasource.youtubeonly", false], + ] + }, test); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/TrackBuffer.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/TrackBuffer.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/TrackBuffer.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/TrackBuffer.cpp 2015-01-09 12:36:56.000000000 +0000 @@ -39,6 +39,7 @@ : mParentDecoder(aParentDecoder) , mType(aType) , mLastStartTimestamp(0) + , mLastTimestampOffset(0) , mShutdown(false) { MOZ_COUNT_CTOR(TrackBuffer); @@ -85,9 +86,9 @@ } } - bool NewDecoder() + bool NewDecoder(int64_t aTimestampOffset) { - nsRefPtr decoder = mOwner->NewDecoder(); + nsRefPtr decoder = mOwner->NewDecoder(aTimestampOffset); if (!decoder) { return false; } @@ -138,14 +139,14 @@ } bool -TrackBuffer::AppendData(const uint8_t* aData, uint32_t aLength) +TrackBuffer::AppendData(const uint8_t* aData, uint32_t aLength, int64_t aTimestampOffset) { MOZ_ASSERT(NS_IsMainThread()); DecodersToInitialize decoders(this); // TODO: Run more of the buffer append algorithm asynchronously. if (mParser->IsInitSegmentPresent(aData, aLength)) { MSE_DEBUG("TrackBuffer(%p)::AppendData: New initialization segment.", this); - if (!decoders.NewDecoder()) { + if (!decoders.NewDecoder(aTimestampOffset)) { return false; } } else if (!mParser->HasInitData()) { @@ -155,16 +156,19 @@ int64_t start, end; if (mParser->ParseStartAndEndTimestamps(aData, aLength, start, end)) { + start += aTimestampOffset; + end += aTimestampOffset; if (mParser->IsMediaSegmentPresent(aData, aLength) && mLastEndTimestamp && (!mParser->TimestampsFuzzyEqual(start, mLastEndTimestamp.value()) || + mLastTimestampOffset != aTimestampOffset || mDecoderPerSegment)) { MSE_DEBUG("TrackBuffer(%p)::AppendData: Data last=[%lld, %lld] overlaps [%lld, %lld]", this, mLastStartTimestamp, mLastEndTimestamp.value(), start, end); // This data is earlier in the timeline than data we have already // processed, so we must create a new decoder to handle the decoding. - if (!decoders.NewDecoder()) { + if (!decoders.NewDecoder(aTimestampOffset)) { return false; } MSE_DEBUG("TrackBuffer(%p)::AppendData: Decoder marked as initialized.", this); @@ -331,14 +335,14 @@ } already_AddRefed -TrackBuffer::NewDecoder() +TrackBuffer::NewDecoder(int64_t aTimestampOffset) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mParentDecoder); DiscardDecoder(); - nsRefPtr decoder = mParentDecoder->CreateSubDecoder(mType); + nsRefPtr decoder = mParentDecoder->CreateSubDecoder(mType, aTimestampOffset); if (!decoder) { return nullptr; } @@ -348,6 +352,7 @@ mLastStartTimestamp = 0; mLastEndTimestamp.reset(); + mLastTimestampOffset = aTimestampOffset; decoder->SetTaskQueue(mTaskQueue); return decoder.forget(); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/TrackBuffer.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/TrackBuffer.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/mediasource/TrackBuffer.h 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/mediasource/TrackBuffer.h 2015-01-09 12:36:56.000000000 +0000 @@ -39,7 +39,7 @@ // Append data to the current decoder. Also responsible for calling // NotifyDataArrived on the decoder to keep buffered range computation up // to date. Returns false if the append failed. - bool AppendData(const uint8_t* aData, uint32_t aLength); + bool AppendData(const uint8_t* aData, uint32_t aLength, int64_t aTimestampOffset /* microseconds */); bool EvictData(uint32_t aThreshold); void EvictBefore(double aTime); @@ -92,7 +92,7 @@ // for initialization. // The decoder is not considered initialized until it is added to // mInitializedDecoders. - already_AddRefed NewDecoder(); + already_AddRefed NewDecoder(int64_t aTimestampOffset /* microseconds */); // Helper for AppendData, ensures NotifyDataArrived is called whenever // data is appended to the current decoder's SourceBufferResource. @@ -156,6 +156,9 @@ int64_t mLastStartTimestamp; Maybe mLastEndTimestamp; + // The timestamp offset used by our current decoder, in microseconds. + int64_t mLastTimestampOffset; + // Set when the first decoder used by this TrackBuffer is initialized. // Protected by mParentDecoder's monitor. MediaInfo mInfo; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/omx/AudioOffloadPlayer.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/omx/AudioOffloadPlayer.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/omx/AudioOffloadPlayer.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/omx/AudioOffloadPlayer.cpp 2015-01-09 12:36:57.000000000 +0000 @@ -55,18 +55,18 @@ static const uint64_t OFFLOAD_PAUSE_MAX_MSECS = 60000ll; AudioOffloadPlayer::AudioOffloadPlayer(MediaOmxCommonDecoder* aObserver) : - mObserver(aObserver), - mInputBuffer(nullptr), - mSampleRate(0), + mStarted(false), + mPlaying(false), mSeeking(false), - mSeekDuringPause(false), mReachedEOS(false), - mSeekTimeUs(0), + mSeekDuringPause(false), + mIsElementVisible(true), + mSampleRate(0), mStartPosUs(0), + mSeekTimeUs(0), mPositionTimeMediaUs(-1), - mStarted(false), - mPlaying(false), - mIsElementVisible(true) + mInputBuffer(nullptr), + mObserver(aObserver) { MOZ_ASSERT(NS_IsMainThread()); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/omx/AudioOutput.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/omx/AudioOutput.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/omx/AudioOutput.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/omx/AudioOutput.cpp 2015-01-09 12:36:57.000000000 +0000 @@ -33,11 +33,11 @@ using namespace android; AudioOutput::AudioOutput(int aSessionId, int aUid) : - mCallback(nullptr), mCallbackCookie(nullptr), + mCallback(nullptr), mCallbackData(nullptr), - mSessionId(aSessionId), - mUid(aUid) + mUid(aUid), + mSessionId(aSessionId) { #ifdef PR_LOGGING if (!gAudioOffloadPlayerLog) { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/omx/AudioOutput.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/omx/AudioOutput.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/omx/AudioOutput.h 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/omx/AudioOutput.h 2015-01-09 12:36:57.000000000 +0000 @@ -26,8 +26,6 @@ #include "AudioSink.h" -#define LOG_TAG "AudioOffloadPlayer" - namespace mozilla { /** diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/omx/MediaCodecProxy.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/omx/MediaCodecProxy.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/omx/MediaCodecProxy.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/omx/MediaCodecProxy.cpp 2015-01-09 12:36:57.000000000 +0000 @@ -12,9 +12,8 @@ #include #include "stagefright/MediaErrors.h" -#define LOG_TAG "MediaCodecProxy" #include -#define ALOG(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) +#define MCP_LOG(...) __android_log_print(ANDROID_LOG_DEBUG, "MediaCodecProxy", __VA_ARGS__) #define TIMEOUT_DEQUEUE_INPUTBUFFER_MS 1000000ll namespace android { @@ -183,7 +182,7 @@ // Release MediaCodec if (mCodec != nullptr) { - status_t err = mCodec->stop(); + mCodec->stop(); mCodec->release(); mCodec = nullptr; } @@ -494,17 +493,16 @@ bool MediaCodecProxy::Prepare() { - status_t err; if (start() != OK) { - ALOG("Couldn't start MediaCodec"); + MCP_LOG("Couldn't start MediaCodec"); return false; } if (getInputBuffers(&mInputBuffers) != OK) { - ALOG("Couldn't get input buffers from MediaCodec"); + MCP_LOG("Couldn't get input buffers from MediaCodec"); return false; } if (getOutputBuffers(&mOutputBuffers) != OK) { - ALOG("Couldn't get output buffers from MediaCodec"); + MCP_LOG("Couldn't get output buffers from MediaCodec"); return false; } @@ -514,13 +512,13 @@ bool MediaCodecProxy::UpdateOutputBuffers() { if (mCodec == nullptr) { - ALOG("MediaCodec has not been inited from input!"); + MCP_LOG("MediaCodec has not been inited from input!"); return false; } status_t err = getOutputBuffers(&mOutputBuffers); if (err != OK){ - ALOG("Couldn't update output buffers from MediaCodec"); + MCP_LOG("Couldn't update output buffers from MediaCodec"); return false; } return true; @@ -530,14 +528,14 @@ int64_t aTimestampUsecs, uint64_t aflags) { if (mCodec == nullptr) { - ALOG("MediaCodec has not been inited from input!"); + MCP_LOG("MediaCodec has not been inited from input!"); return NO_INIT; } size_t index; status_t err = dequeueInputBuffer(&index, TIMEOUT_DEQUEUE_INPUTBUFFER_MS); if (err != OK) { - ALOG("dequeueInputBuffer returned %d", err); + MCP_LOG("dequeueInputBuffer returned %d", err); return err; } @@ -554,7 +552,7 @@ } if (err != OK) { - ALOG("queueInputBuffer returned %d", err); + MCP_LOG("queueInputBuffer returned %d", err); return err; } return err; @@ -563,7 +561,7 @@ status_t MediaCodecProxy::Output(MediaBuffer** aBuffer, int64_t aTimeoutUs) { if (mCodec == nullptr) { - ALOG("MediaCodec has not been inited from output!"); + MCP_LOG("MediaCodec has not been inited from output!"); return NO_INIT; } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/omx/MediaOmxReader.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/omx/MediaOmxReader.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/omx/MediaOmxReader.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/omx/MediaOmxReader.cpp 2015-01-09 12:36:57.000000000 +0000 @@ -138,15 +138,15 @@ MediaOmxReader::MediaOmxReader(AbstractMediaDecoder *aDecoder) : MediaOmxCommonReader(aDecoder) , mMutex("MediaOmxReader.Data") - , mMP3FrameParser(-1) , mHasVideo(false) , mHasAudio(false) , mVideoSeekTimeUs(-1) , mAudioSeekTimeUs(-1) + , mLastParserDuration(-1) , mSkipCount(0) , mUseParserDuration(false) - , mLastParserDuration(-1) , mIsShutdown(false) + , mMP3FrameParser(-1) , mIsWaitingResources(false) { #ifdef PR_LOGGING diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/omx/mediaresourcemanager/MediaResourceManagerService.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/omx/mediaresourcemanager/MediaResourceManagerService.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/omx/mediaresourcemanager/MediaResourceManagerService.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/omx/mediaresourcemanager/MediaResourceManagerService.cpp 2015-01-09 12:36:57.000000000 +0000 @@ -148,7 +148,7 @@ return; } - const sp& req = mResources.nextRequest(type); + sp req = mResources.nextRequest(type); mResources.aquireResource(req, type, found); // Notify resource assignment to the client. sp client = interface_cast(req); @@ -292,7 +292,7 @@ return queue.size(); } -const sp& MediaResourceManagerService::ResourceTable::nextRequest(ResourceType type) +sp MediaResourceManagerService::ResourceTable::nextRequest(ResourceType type) { ssize_t found = mMap.indexOfKey(type); if (found == NAME_NOT_FOUND) { @@ -333,7 +333,7 @@ status_t MediaResourceManagerService::ResourceTable::forgetClient(const sp& client) { // Traverse all resources. - for (int i = 0; i < mMap.size(); i++) { + for (size_t i = 0; i < mMap.size(); i++) { forgetClient(client, mMap.keyAt(i)); } return OK; @@ -358,7 +358,7 @@ // Revoke ownership for given client. Slots& slots = resources.mSlots; - for (int i = 0; i < slots.size(); i++) { + for (size_t i = 0; i < slots.size(); i++) { ResourceSlot& slot = slots.editItemAt(i); if (client.get() == slot.mClient.get()) { slot.mClient = nullptr; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/omx/mediaresourcemanager/MediaResourceManagerService.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/omx/mediaresourcemanager/MediaResourceManagerService.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/omx/mediaresourcemanager/MediaResourceManagerService.h 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/omx/mediaresourcemanager/MediaResourceManagerService.h 2015-01-09 12:36:57.000000000 +0000 @@ -99,7 +99,7 @@ // Request operations. bool hasRequest(ResourceType type); uint32_t countRequests(ResourceType type); - const sp& nextRequest(ResourceType type); + sp nextRequest(ResourceType type); status_t enqueueRequest(const sp& client, ResourceType type); status_t dequeueRequest(ResourceType type); status_t forgetClient(const sp& client, ResourceType type); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/omx/mediaresourcemanager/moz.build thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/omx/mediaresourcemanager/moz.build --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/omx/mediaresourcemanager/moz.build 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/omx/mediaresourcemanager/moz.build 2015-01-09 12:36:57.000000000 +0000 @@ -24,6 +24,13 @@ include('/ipc/chromium/chromium-config.mozbuild') +# Suppress some GCC/clang warnings being treated as errors: +# - about multi-character constants which are used in codec-related code +if CONFIG['GNU_CC'] or CONFIG['CLANG_CL']: + CXXFLAGS += [ + '-Wno-error=multichar' + ] + CXXFLAGS += [ '-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [ 'frameworks/base/include', diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/omx/moz.build thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/omx/moz.build --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/omx/moz.build 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/omx/moz.build 2015-01-09 12:36:57.000000000 +0000 @@ -79,6 +79,16 @@ include('/ipc/chromium/chromium-config.mozbuild') +# Suppress some GCC/clang warnings being treated as errors: +# - about attributes on forward declarations for types that are already +# defined, which complains about an important MOZ_EXPORT for android::AString +# - about multi-character constants which are used in codec-related code +if CONFIG['GNU_CC'] or CONFIG['CLANG_CL']: + CXXFLAGS += [ + '-Wno-error=attributes', + '-Wno-error=multichar' + ] + FINAL_LIBRARY = 'xul' LOCAL_INCLUDES += [ '/dom/base', diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/omx/OMXCodecDescriptorUtil.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/omx/OMXCodecDescriptorUtil.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/omx/OMXCodecDescriptorUtil.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/omx/OMXCodecDescriptorUtil.cpp 2015-01-09 12:36:57.000000000 +0000 @@ -84,8 +84,8 @@ { // 2 bytes length value. uint8_t size[] = { - (mSize & 0xFF00) >> 8, // MSB. - mSize & 0x00FF, // LSB. + uint8_t((mSize & 0xFF00) >> 8), // MSB. + uint8_t(mSize & 0x00FF), // LSB. }; aOutputBuf->AppendElements(size, sizeof(size)); @@ -189,7 +189,6 @@ return ERROR_MALFORMED; } - status_t result = OK; if (aFormat == OMXVideoEncoder::BlobFormat::AVC_NAL) { // SPS + PPS. aOutputBuf->AppendElements(sps->data(), sps->size()); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/omx/OMXCodecProxy.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/omx/OMXCodecProxy.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/omx/OMXCodecProxy.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/omx/OMXCodecProxy.cpp 2015-01-09 12:36:57.000000000 +0000 @@ -55,11 +55,11 @@ const sp &nativeWindow) : mOMX(omx), mSrcMeta(meta), - mIsEncoder(createEncoder), - mSource(source), mComponentName(nullptr), + mIsEncoder(createEncoder), mFlags(flags), mNativeWindow(nativeWindow), + mSource(source), mState(MediaResourceManagerClient::CLIENT_STATE_WAIT_FOR_RESOURCE) { } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/omx/OMXCodecWrapper.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/omx/OMXCodecWrapper.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/omx/OMXCodecWrapper.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/omx/OMXCodecWrapper.cpp 2015-01-09 12:36:57.000000000 +0000 @@ -287,11 +287,11 @@ size_t vPixStride = horiSubsample * (1 + aSource->mCrSkip); size_t lineStride = uvSize.height / uvHeight * aSource->mCbCrStride; - for (int i = 0; i < uvHeight; i++) { + for (size_t i = 0; i < uvHeight; i++) { // 1st pixel per line. uint8_t* uSrc = u; uint8_t* vSrc = v; - for (int j = 0; j < uvWidth; j++) { + for (size_t j = 0; j < uvWidth; j++) { *aDestination++ = *uSrc; *aDestination++ = *vSrc; // Pick next source pixel. @@ -495,10 +495,10 @@ } // Replace start code with data length. uint8_t length[] = { - (aSize >> 24) & 0xFF, - (aSize >> 16) & 0xFF, - (aSize >> 8) & 0xFF, - aSize & 0xFF, + uint8_t((aSize >> 24) & 0xFF), + uint8_t((aSize >> 16) & 0xFF), + uint8_t((aSize >> 8) & 0xFF), + uint8_t(aSize & 0xFF), }; aOutputBuf->AppendElements(length, sizeof(length)); aOutputBuf->AppendElements(aData + sizeof(length), aSize); @@ -592,8 +592,8 @@ , mInputFlags(aInputFlags) , mIndex(0) , mData(nullptr) - , mOffset(0) , mCapicity(0) + , mOffset(0) {} ~InputBufferHelper() @@ -908,14 +908,14 @@ // Decoder config descriptor const uint8_t decConfig[] = { 0x04, // Decoder config descriptor tag. - 15 + csdSize, // Size: following bytes + csd size. + uint8_t(15 + csdSize), // Size: following bytes + csd size. 0x40, // Object type: MPEG-4 audio. 0x15, // Stream type: audio, reserved: 1. 0x00, 0x03, 0x00, // Buffer size: 768 (kAACFrameSize). 0x00, 0x01, 0x77, 0x00, // Max bitrate: 96000 (kAACBitrate). 0x00, 0x01, 0x77, 0x00, // Avg bitrate: 96000 (kAACBitrate). 0x05, // Decoder specific descriptor tag. - csdSize, // Data size. + uint8_t(csdSize), // Data size. }; // SL config descriptor. const uint8_t slConfig[] = { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/omx/OmxDecoder.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/omx/OmxDecoder.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/omx/OmxDecoder.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/omx/OmxDecoder.cpp 2015-01-09 12:36:57.000000000 +0000 @@ -33,10 +33,10 @@ #include "OMXCodecProxy.h" #include "OmxDecoder.h" -#define LOG_TAG "OmxDecoder" #include -#define ALOG(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) +#define OD_LOG(...) __android_log_print(ANDROID_LOG_DEBUG, "OmxDecoder", __VA_ARGS__) +#undef LOG #ifdef PR_LOGGING PRLogModuleInfo *gOmxDecoderLog; #define LOG(type, msg...) PR_LOG(gOmxDecoderLog, type, (msg)) @@ -65,13 +65,13 @@ mAudioChannels(-1), mAudioSampleRate(-1), mDurationUs(-1), + mVideoLastFrameTime(-1), mVideoBuffer(nullptr), mAudioBuffer(nullptr), mIsVideoSeeking(false), mAudioMetadataRead(false), mAudioPaused(false), - mVideoPaused(false), - mVideoLastFrameTime(-1) + mVideoPaused(false) { mLooper = new ALooper; mLooper->setName("OmxDecoder"); @@ -119,7 +119,6 @@ } #endif - const char* extractorMime; sp meta = extractor->getMetaData(); ssize_t audioTrackIndex = -1; @@ -177,7 +176,6 @@ } if (mAudioTrack.get()) { durationUs = -1; - const char* audioMime; sp meta = mAudioTrack->getFormat(); if ((durationUs == -1) && meta->findInt64(kKeyDuration, &durationUs)) { @@ -604,7 +602,7 @@ } continue; } else if (err != OK) { - ALOG("Unexpected error when seeking to %lld", aTimeUs); + OD_LOG("Unexpected error when seeking to %lld", aTimeUs); break; } // For some codecs, the length of first decoded frame after seek is 0. diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/test/test_eme_canvas_blocked.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/test/test_eme_canvas_blocked.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/test/test_eme_canvas_blocked.html 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/test/test_eme_canvas_blocked.html 2015-01-09 12:36:57.000000000 +0000 @@ -49,6 +49,7 @@ var prefs = [ [ "media.mediasource.enabled", true ], + [ "media.mediasource.youtubeonly", false ], [ "media.mediasource.mp4.enabled", true ], ]; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/test/test_eme_playback.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/test/test_eme_playback.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/test/test_eme_playback.html 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/test/test_eme_playback.html 2015-01-09 12:36:57.000000000 +0000 @@ -92,6 +92,7 @@ var prefs = [ [ "media.mediasource.enabled", true ], + [ "media.mediasource.youtubeonly", false ], [ "media.mediasource.mp4.enabled", true ], ]; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/test/test_eme_requestKeySystemAccess.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/test/test_eme_requestKeySystemAccess.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/test/test_eme_requestKeySystemAccess.html 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/test/test_eme_requestKeySystemAccess.html 2015-01-09 12:36:57.000000000 +0000 @@ -274,6 +274,7 @@ var prefs = [ [ "media.mediasource.enabled", true ], + [ "media.mediasource.youtubeonly", false ], [ "media.mediasource.mp4.enabled", true ], ]; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/test/test_eme_stream_capture_blocked.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/test/test_eme_stream_capture_blocked.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/test/test_eme_stream_capture_blocked.html 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/test/test_eme_stream_capture_blocked.html 2015-01-09 12:36:57.000000000 +0000 @@ -81,6 +81,7 @@ var prefs = [ [ "media.mediasource.enabled", true ], + [ "media.mediasource.youtubeonly", false ], [ "media.mediasource.mp4.enabled", true ], ]; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/test/test_VideoPlaybackQuality_disabled.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/test/test_VideoPlaybackQuality_disabled.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/test/test_VideoPlaybackQuality_disabled.html 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/test/test_VideoPlaybackQuality_disabled.html 2015-01-09 12:36:57.000000000 +0000 @@ -25,7 +25,12 @@ } addLoadEvent(function() { - SpecialPowers.pushPrefEnv({"set": [["media.mediasource.enabled", false]]}, test); + SpecialPowers.pushPrefEnv({"set": + [ + ["media.mediasource.enabled", false], + ["media.mediasource.youtubeonly", false], + ] + }, test); }); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/test/test_VideoPlaybackQuality.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/test/test_VideoPlaybackQuality.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/test/test_VideoPlaybackQuality.html 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/test/test_VideoPlaybackQuality.html 2015-01-09 12:36:57.000000000 +0000 @@ -51,7 +51,12 @@ } addLoadEvent(function() { - SpecialPowers.pushPrefEnv({"set": [["media.mediasource.enabled", true]]}, test); + SpecialPowers.pushPrefEnv({"set": + [ + ["media.mediasource.enabled", true], + ["media.mediasource.youtubeonly", false], + ] + }, test); }); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/webaudio/blink/PeriodicWave.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/webaudio/blink/PeriodicWave.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/webaudio/blink/PeriodicWave.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/webaudio/blink/PeriodicWave.cpp 2015-01-09 12:36:58.000000000 +0000 @@ -291,8 +291,12 @@ case OscillatorType::Triangle: // Triangle-shaped waveform going from its maximum value to // its minimum value then back to the maximum value. - a = (4 - 4 * cos(0.5 * omega)) / (n * n * piFloat * piFloat); - b = 0; + a = 0; + if (n & 1) { + b = 2 * (2 / (n * piFloat) * 2 / (n * piFloat)) * ((((n - 1) >> 1) & 1) ? -1 : 1); + } else { + b = 0; + } break; default: NS_NOTREACHED("invalid oscillator type"); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/webaudio/OscillatorNode.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/webaudio/OscillatorNode.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/webaudio/OscillatorNode.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/webaudio/OscillatorNode.cpp 2015-01-09 12:36:58.000000000 +0000 @@ -23,40 +23,6 @@ NS_IMPL_ADDREF_INHERITED(OscillatorNode, AudioNode) NS_IMPL_RELEASE_INHERITED(OscillatorNode, AudioNode) -static const float sLeakTriangle = 0.995f; -static const float sLeak = 0.999f; - -class DCBlocker -{ -public: - // These are sane defauts when the initial mPhase is zero - explicit DCBlocker(float aLastInput = 0.0f, - float aLastOutput = 0.0f, - float aPole = 0.995) - :mLastInput(aLastInput), - mLastOutput(aLastOutput), - mPole(aPole) - { - MOZ_ASSERT(aPole > 0); - } - - inline float Process(float aInput) - { - float out; - - out = mLastOutput * mPole + aInput - mLastInput; - mLastOutput = out; - mLastInput = aInput; - - return out; - } -private: - float mLastInput; - float mLastOutput; - float mPole; -}; - - class OscillatorNodeEngine : public AudioNodeEngine { public: @@ -71,12 +37,6 @@ , mDetune(0.f) , mType(OscillatorType::Sine) , mPhase(0.) - // mSquare, mTriangle, and mSaw are not used for default type "sine". - // They are initialized if and when switching to the OscillatorTypes that - // use them. - // mFinalFrequency, mNumberOfHarmonics, mSignalPeriod, mAmplitudeAtZero, - // mPhaseIncrement, and mPhaseWrap are initialized in - // UpdateParametersIfNeeded() when mRecomputeParameters is set. , mRecomputeParameters(true) , mCustomLength(0) { @@ -132,41 +92,27 @@ case TYPE: // Set the new type. mType = static_cast(aParam); - if (mType != OscillatorType::Custom) { + if (mType == OscillatorType::Sine) { // Forget any previous custom data. mCustomLength = 0; mCustom = nullptr; mPeriodicWave = nullptr; mRecomputeParameters = true; } - // Update BLIT integrators with the new initial conditions. switch (mType) { case OscillatorType::Sine: mPhase = 0.0; break; case OscillatorType::Square: - mPhase = 0.0; - // Initial integration condition is -0.5, because our - // square has 50% duty cycle. - mSquare = -0.5; + mPeriodicWave = WebCore::PeriodicWave::createSquare(mSource->SampleRate()); break; case OscillatorType::Triangle: - // Initial mPhase and related integration condition so the - // triangle is in the middle of the first upward slope. - // XXX actually do the maths and put the right number here. - mPhase = (float)(M_PI / 2); - mSquare = 0.5; - mTriangle = 0.0; + mPeriodicWave = WebCore::PeriodicWave::createTriangle(mSource->SampleRate()); break; case OscillatorType::Sawtooth: - // Initial mPhase so the oscillator starts at the - // middle of the ramp, per spec. - mPhase = (float)(M_PI / 2); - // mSaw = 0 when mPhase = pi/2. - mSaw = 0.0; + mPeriodicWave = WebCore::PeriodicWave::createSawtooth(mSource->SampleRate()); break; case OscillatorType::Custom: - // Custom waveforms don't use BLIT. break; default: NS_ERROR("Bad OscillatorNodeEngine type parameter."); @@ -195,31 +141,28 @@ void IncrementPhase() { + const float twoPiFloat = float(2 * M_PI); mPhase += mPhaseIncrement; - if (mPhase > mPhaseWrap) { - mPhase -= mPhaseWrap; + if (mPhase > twoPiFloat) { + mPhase -= twoPiFloat; + } else if (mPhase < -twoPiFloat) { + mPhase += twoPiFloat; } } - // Square and triangle are using a bipolar band-limited impulse train, saw is - // using a normal band-limited impulse train. - bool UsesBipolarBLIT() { - return mType == OscillatorType::Square || mType == OscillatorType::Triangle; - } - void UpdateParametersIfNeeded(StreamTime ticks, size_t count) { double frequency, detune; - bool simpleFrequency = mFrequency.HasSimpleValue(); - bool simpleDetune = mDetune.HasSimpleValue(); - // Shortcut if frequency-related AudioParam are not automated, and we // already have computed the frequency information and related parameters. - if (simpleFrequency && simpleDetune && !mRecomputeParameters) { + if (!ParametersMayNeedUpdate()) { return; } + bool simpleFrequency = mFrequency.HasSimpleValue(); + bool simpleDetune = mDetune.HasSimpleValue(); + if (simpleFrequency) { frequency = mFrequency.GetValue(); } else { @@ -232,21 +175,10 @@ } mFinalFrequency = frequency * pow(2., detune / 1200.); + float signalPeriod = mSource->SampleRate() / mFinalFrequency; mRecomputeParameters = false; - // When using bipolar BLIT, we divide the signal period by two, because we - // are using two BLIT out of phase. - mSignalPeriod = UsesBipolarBLIT() ? 0.5 * mSource->SampleRate() / mFinalFrequency - : mSource->SampleRate() / mFinalFrequency; - // Wrap the phase accordingly: - mPhaseWrap = UsesBipolarBLIT() || mType == OscillatorType::Sine ? 2 * M_PI - : M_PI; - // Even number of harmonics for bipolar blit, odd otherwise. - mNumberOfHarmonics = UsesBipolarBLIT() ? 2 * floor(0.5 * mSignalPeriod) - : 2 * floor(0.5 * mSignalPeriod) + 1; - mPhaseIncrement = mType == OscillatorType::Sine ? 2 * M_PI / mSignalPeriod - : M_PI / mSignalPeriod; - mAmplitudeAtZero = mNumberOfHarmonics / mSignalPeriod; + mPhaseIncrement = 2 * M_PI / signalPeriod; } void FillBounds(float* output, StreamTime ticks, @@ -271,39 +203,6 @@ } } - float BipolarBLIT() - { - float blit; - float denom = sin(mPhase); - - if (fabs(denom) < std::numeric_limits::epsilon()) { - if (mPhase < 0.1f || mPhase > 2 * M_PI - 0.1f) { - blit = mAmplitudeAtZero; - } else { - blit = -mAmplitudeAtZero; - } - } else { - blit = sin(mNumberOfHarmonics * mPhase); - blit /= mSignalPeriod * denom; - } - return blit; - } - - float UnipolarBLIT() - { - float blit; - float denom = sin(mPhase); - - if (fabs(denom) <= std::numeric_limits::epsilon()) { - blit = mAmplitudeAtZero; - } else { - blit = sin(mNumberOfHarmonics * mPhase); - blit /= mSignalPeriod * denom; - } - - return blit; - } - void ComputeSine(float * aOutput, StreamTime ticks, uint32_t aStart, uint32_t aEnd) { for (uint32_t i = aStart; i < aEnd; ++i) { @@ -315,54 +214,11 @@ } } - void ComputeSquare(float * aOutput, StreamTime ticks, uint32_t aStart, uint32_t aEnd) - { - for (uint32_t i = aStart; i < aEnd; ++i) { - UpdateParametersIfNeeded(ticks, i); - // Integration to get us a square. It turns out we can have a - // pure integrator here. - mSquare = mSquare * sLeak + BipolarBLIT(); - aOutput[i] = mSquare; - // maybe we want to apply a gain, the wg has not decided yet - aOutput[i] *= 1.5; - IncrementPhase(); - } - } - - void ComputeSawtooth(float * aOutput, StreamTime ticks, uint32_t aStart, uint32_t aEnd) + bool ParametersMayNeedUpdate() { - float dcoffset; - for (uint32_t i = aStart; i < aEnd; ++i) { - UpdateParametersIfNeeded(ticks, i); - // DC offset so the Saw does not ramp up to infinity when integrating. - dcoffset = mFinalFrequency / mSource->SampleRate(); - // Integrate and offset so we get mAmplitudeAtZero sawtooth. We have a - // very low frequency component somewhere here, but I'm not sure where. - mSaw = mSaw * sLeak + (UnipolarBLIT() - dcoffset); - // reverse the saw so we are spec compliant - aOutput[i] = -mSaw * 1.5; - - IncrementPhase(); - } - } - - void ComputeTriangle(float * aOutput, StreamTime ticks, uint32_t aStart, uint32_t aEnd) - { - for (uint32_t i = aStart; i < aEnd; ++i) { - UpdateParametersIfNeeded(ticks, i); - // Integrate to get a square - mSquare += BipolarBLIT(); - // Leaky integrate to get a triangle. We get too much dc offset if we don't - // leaky integrate here. - // C6 = k0 / period - // (period is samplingrate / frequency, k0 = (PI/2)/(2*PI)) = 0.25 - float C6 = 0.25 / (mSource->SampleRate() / mFinalFrequency); - mTriangle = mTriangle * sLeakTriangle + mSquare + C6; - // DC Block, and scale back to [-1.0; 1.0] - aOutput[i] = mDCBlocker.Process(mTriangle) / (mSignalPeriod/2) * 1.5; - - IncrementPhase(); - } + return !mDetune.HasSimpleValue() || + !mFrequency.HasSimpleValue() || + mRecomputeParameters; } void ComputeCustom(float* aOutput, @@ -382,15 +238,24 @@ float tableInterpolationFactor; // Phase increment at frequency of 1 Hz. // mPhase runs [0,periodicWaveSize) here instead of [0,2*M_PI). - float basePhaseIncrement = - static_cast(periodicWaveSize) / mSource->SampleRate(); + float basePhaseIncrement = mPeriodicWave->rateScale(); + + UpdateParametersIfNeeded(ticks, aStart); + + bool parametersMayNeedUpdate = ParametersMayNeedUpdate(); + mPeriodicWave->waveDataForFundamentalFrequency(mFinalFrequency, + lowerWaveData, + higherWaveData, + tableInterpolationFactor); for (uint32_t i = aStart; i < aEnd; ++i) { - UpdateParametersIfNeeded(ticks, i); - mPeriodicWave->waveDataForFundamentalFrequency(mFinalFrequency, - lowerWaveData, - higherWaveData, - tableInterpolationFactor); + if (parametersMayNeedUpdate) { + mPeriodicWave->waveDataForFundamentalFrequency(mFinalFrequency, + lowerWaveData, + higherWaveData, + tableInterpolationFactor); + UpdateParametersIfNeeded(ticks, i); + } // Bilinear interpolation between adjacent samples in each table. float floorPhase = floorf(mPhase); uint32_t j1 = floorPhase; @@ -457,14 +322,8 @@ ComputeSine(output, ticks, start, end); break; case OscillatorType::Square: - ComputeSquare(output, ticks, start, end); - break; case OscillatorType::Triangle: - ComputeTriangle(output, ticks, start, end); - break; case OscillatorType::Sawtooth: - ComputeSawtooth(output, ticks, start, end); - break; case OscillatorType::Custom: ComputeCustom(output, ticks, start, end); break; @@ -500,7 +359,6 @@ return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); } - DCBlocker mDCBlocker; AudioNodeStream* mSource; AudioNodeStream* mDestination; StreamTime mStart; @@ -510,14 +368,7 @@ OscillatorType mType; float mPhase; float mFinalFrequency; - uint32_t mNumberOfHarmonics; - float mSignalPeriod; - float mAmplitudeAtZero; float mPhaseIncrement; - float mSquare; - float mTriangle; - float mSaw; - float mPhaseWrap; bool mRecomputeParameters; nsRefPtr mCustom; uint32_t mCustomLength; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/webaudio/test/mochitest.ini thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/webaudio/test/mochitest.ini --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/webaudio/test/mochitest.ini 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/webaudio/test/mochitest.ini 2015-01-09 12:36:58.000000000 +0000 @@ -126,6 +126,8 @@ [test_offlineDestinationChannelCountMore.html] [test_oscillatorNode.html] [test_oscillatorNode2.html] +[test_oscillatorNodeNegativeFrequency.html] +skip-if = (toolkit == 'gonk') || (toolkit == 'android') [test_oscillatorNodePassThrough.html] [test_oscillatorNodeStart.html] [test_oscillatorTypeChange.html] diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/webaudio/test/test_oscillatorNodeNegativeFrequency.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/webaudio/test/test_oscillatorNodeNegativeFrequency.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/webaudio/test/test_oscillatorNodeNegativeFrequency.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/webaudio/test/test_oscillatorNodeNegativeFrequency.html 2015-01-09 12:36:58.000000000 +0000 @@ -0,0 +1,50 @@ + + + + Test the OscillatorNode when the frequency is negative + + + + + +
+
+
+ + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/webrtc/GonkCameraImage.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/webrtc/GonkCameraImage.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/webrtc/GonkCameraImage.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/webrtc/GonkCameraImage.cpp 2015-01-09 12:36:59.000000000 +0000 @@ -26,7 +26,7 @@ } nsresult -GonkCameraImage::GetBuffer(android::MediaBuffer** aBuffer) +GonkCameraImage::GetMediaBuffer(android::MediaBuffer** aBuffer) { ReentrantMonitorAutoEnter mon(mMonitor); @@ -50,7 +50,7 @@ } nsresult -GonkCameraImage::SetBuffer(android::MediaBuffer* aBuffer) +GonkCameraImage::SetMediaBuffer(android::MediaBuffer* aBuffer) { ReentrantMonitorAutoEnter mon(mMonitor); MOZ_ASSERT(!mMediaBuffer); @@ -63,7 +63,7 @@ } nsresult -GonkCameraImage::ClearBuffer() +GonkCameraImage::ClearMediaBuffer() { ReentrantMonitorAutoEnter mon(mMonitor); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/webrtc/GonkCameraImage.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/webrtc/GonkCameraImage.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/webrtc/GonkCameraImage.h 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/webrtc/GonkCameraImage.h 2015-01-09 12:36:59.000000000 +0000 @@ -24,8 +24,8 @@ * shared memory based on android binder (IMemory), the actual format in IMemory * is platform dependent. * This instance is created in MediaEngine when the preview image arrives. - * The MediaBuffer is attached to the current created GonkCameraImage via SetBuffer(). - * After sending this image to MediaStreamGraph by AppendToTrack(), ClearBuffer() + * The MediaBuffer is attached to the current created GonkCameraImage via SetMediaBuffer(). + * After sending this image to MediaStreamGraph by AppendToTrack(), ClearMediaBuffer() * must be called to clear MediaBuffer to avoid MediaBuffer be kept in MSG thread. * The reason to keep MediaBuffer be accessed from MSG thread is MediaBuffer is * limited resource and it could cause frame rate jitter if MediaBuffer stay too @@ -37,8 +37,8 @@ * Third is the MSG thread via NotifyPull, the image should have preview image * only in NotifyPull. * - * Note: SetBuffer() and GetBuffer() should be called from the same thread. It - * is forbidden to call GetBuffer() from other threads. + * Note: SetMediaBuffer() and GetMediaBuffer() should be called from the same + * thread. It is forbidden to call GetMediaBuffer() from other threads. */ class GonkCameraImage : public layers::GrallocImage { @@ -47,15 +47,15 @@ // The returned aBuffer has called aBuffer->add_ref() already, so it is caller's // duty to release aBuffer. It should be called from the same thread which - // called SetBuffer(). - nsresult GetBuffer(android::MediaBuffer** aBuffer); + // called SetMediaBuffer(). + nsresult GetMediaBuffer(android::MediaBuffer** aBuffer); - // Set MediaBuffer to image. It is caller's responsibility to call ClearBuffer() + // Set MediaBuffer to image. It is caller's responsibility to call ClearMediaBuffer() // after the MediaBuffer is sent via MediaStreamGraph. - nsresult SetBuffer(android::MediaBuffer* aBuffer); + nsresult SetMediaBuffer(android::MediaBuffer* aBuffer); - // It should be called from the same thread which called SetBuffer(). - nsresult ClearBuffer(); + // It should be called from the same thread which called SetMediaBuffer(). + nsresult ClearMediaBuffer(); bool HasMediaBuffer(); @@ -65,7 +65,7 @@ // mMonitor protects mMediaBuffer and mThread. ReentrantMonitor mMonitor; android::MediaBuffer* mMediaBuffer; - // Check if current thread is the same one which called SetBuffer(). + // Check if current thread is the same one which called SetMediaBuffer(). // It doesn't need to hold reference count. DebugOnly mThread; }; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/webrtc/MediaEngineGonkVideoSource.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/webrtc/MediaEngineGonkVideoSource.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/webrtc/MediaEngineGonkVideoSource.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/webrtc/MediaEngineGonkVideoSource.cpp 2015-01-09 12:36:59.000000000 +0000 @@ -3,6 +3,7 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "MediaEngineGonkVideoSource.h" +#undef LOG_TAG #define LOG_TAG "MediaEngineGonkVideoSource" #include @@ -23,6 +24,7 @@ using namespace mozilla::gfx; using namespace android; +#undef LOG #ifdef PR_LOGGING extern PRLogModuleInfo* GetMediaManagerLog(); #define LOG(msg) PR_LOG(GetMediaManagerLog(), PR_LOG_DEBUG, msg) @@ -800,7 +802,7 @@ // MediaEngineGonkVideoSource expects that GrallocImage is GonkCameraImage. // See Bug 938034. GonkCameraImage* cameraImage = static_cast(mImage.get()); - cameraImage->SetBuffer(aBuffer); + cameraImage->SetMediaBuffer(aBuffer); } else { LOG(("mImage is non-GrallocImage")); } @@ -821,7 +823,7 @@ GonkCameraImage* cameraImage = static_cast(mImage.get()); // Clear MediaBuffer immediately, it prevents MediaBuffer is kept in // MediaStreamGraph thread. - cameraImage->ClearBuffer(); + cameraImage->ClearMediaBuffer(); } } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/webrtc/MediaEngineGonkVideoSource.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/webrtc/MediaEngineGonkVideoSource.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/webrtc/MediaEngineGonkVideoSource.h 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/webrtc/MediaEngineGonkVideoSource.h 2015-01-09 12:36:59.000000000 +0000 @@ -97,7 +97,7 @@ // It adds aBuffer to current preview image and sends this image to MediaStreamDirectListener // via AppendToTrack(). Due to MediaBuffer is limited resource, it will clear - // image's MediaBuffer by calling GonkCameraImage::ClearBuffer() before leaving + // image's MediaBuffer by calling GonkCameraImage::ClearMediaBuffer() before leaving // this function. nsresult OnNewMediaBufferFrame(android::MediaBuffer* aBuffer); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/webrtc/MediaEngineTabVideoSource.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/webrtc/MediaEngineTabVideoSource.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/webrtc/MediaEngineTabVideoSource.h 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/webrtc/MediaEngineTabVideoSource.h 2015-01-09 12:36:59.000000000 +0000 @@ -18,27 +18,27 @@ NS_DECL_NSITIMERCALLBACK MediaEngineTabVideoSource(); - virtual void GetName(nsAString_internal&); - virtual void GetUUID(nsAString_internal&); + virtual void GetName(nsAString_internal&) MOZ_OVERRIDE; + virtual void GetUUID(nsAString_internal&) MOZ_OVERRIDE; virtual nsresult Allocate(const VideoTrackConstraintsN &, - const mozilla::MediaEnginePrefs&); - virtual nsresult Deallocate(); - virtual nsresult Start(mozilla::SourceMediaStream*, mozilla::TrackID); - virtual void SetDirectListeners(bool aHasDirectListeners) {}; + const mozilla::MediaEnginePrefs&) MOZ_OVERRIDE; + virtual nsresult Deallocate() MOZ_OVERRIDE; + virtual nsresult Start(mozilla::SourceMediaStream*, mozilla::TrackID) MOZ_OVERRIDE; + virtual void SetDirectListeners(bool aHasDirectListeners) MOZ_OVERRIDE {}; virtual void NotifyPull(mozilla::MediaStreamGraph*, mozilla::SourceMediaStream*, mozilla::TrackID, mozilla::StreamTime) MOZ_OVERRIDE; - virtual nsresult Stop(mozilla::SourceMediaStream*, mozilla::TrackID); - virtual nsresult Config(bool, uint32_t, bool, uint32_t, bool, uint32_t, int32_t); - virtual bool IsFake(); - virtual const MediaSourceType GetMediaSource() { + virtual nsresult Stop(mozilla::SourceMediaStream*, mozilla::TrackID) MOZ_OVERRIDE; + virtual nsresult Config(bool, uint32_t, bool, uint32_t, bool, uint32_t, int32_t) MOZ_OVERRIDE; + virtual bool IsFake() MOZ_OVERRIDE; + virtual const MediaSourceType GetMediaSource() MOZ_OVERRIDE { return MediaSourceType::Browser; } virtual bool SatisfiesConstraintSets( - const nsTArray& aConstraintSets) + const nsTArray& aConstraintSets) MOZ_OVERRIDE { return true; } - virtual nsresult TakePhoto(PhotoCallback* aCallback) + virtual nsresult TakePhoto(PhotoCallback* aCallback) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/webrtc/moz.build thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/webrtc/moz.build --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/webrtc/moz.build 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/webrtc/moz.build 2015-01-09 12:36:59.000000000 +0000 @@ -60,6 +60,15 @@ include('/ipc/chromium/chromium-config.mozbuild') +# Suppress some GCC/clang warnings being treated as errors: +# - about attributes on forward declarations for types that are already +# defined, which complains about important MOZ_EXPORT attributes for +# android API types +if CONFIG['GNU_CC'] or CONFIG['CLANG_CL']: + CXXFLAGS += [ + '-Wno-error=attributes' + ] + FINAL_LIBRARY = 'xul' if CONFIG['OS_ARCH'] == 'WINNT': DEFINES['NOMINMAX'] = True diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/webspeech/synth/ipc/SpeechSynthesisChild.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/webspeech/synth/ipc/SpeechSynthesisChild.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/webspeech/synth/ipc/SpeechSynthesisChild.h 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/webspeech/synth/ipc/SpeechSynthesisChild.h 2015-01-09 12:36:59.000000000 +0000 @@ -82,11 +82,11 @@ NS_IMETHOD SendAudioNative(int16_t* aData, uint32_t aDataLen) MOZ_OVERRIDE; - virtual void Pause(); + virtual void Pause() MOZ_OVERRIDE; - virtual void Resume(); + virtual void Resume() MOZ_OVERRIDE; - virtual void Cancel(); + virtual void Cancel() MOZ_OVERRIDE; private: SpeechSynthesisRequestChild* mActor; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/webspeech/synth/nsSpeechTask.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/webspeech/synth/nsSpeechTask.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/media/webspeech/synth/nsSpeechTask.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/media/webspeech/synth/nsSpeechTask.cpp 2015-01-09 12:36:59.000000000 +0000 @@ -68,7 +68,7 @@ } } - virtual void NotifyBlockingChanged(MediaStreamGraph* aGraph, Blocking aBlocked) + virtual void NotifyBlockingChanged(MediaStreamGraph* aGraph, Blocking aBlocked) MOZ_OVERRIDE { if (aBlocked == MediaStreamListener::UNBLOCKED && !mStarted) { mStarted = true; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/mobileconnection/DOMMMIError.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/mobileconnection/DOMMMIError.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/mobileconnection/DOMMMIError.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/mobileconnection/DOMMMIError.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* 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 "mozilla/dom/DOMMMIError.h" -#include "mozilla/dom/DOMMMIErrorBinding.h" - -using namespace mozilla::dom; - -NS_IMPL_CYCLE_COLLECTION_CLASS(DOMMMIError) - -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(DOMMMIError, DOMError) -NS_IMPL_CYCLE_COLLECTION_UNLINK_END - -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(DOMMMIError, DOMError) -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DOMMMIError) -NS_INTERFACE_MAP_END_INHERITING(DOMError) - -NS_IMPL_ADDREF_INHERITED(DOMMMIError, DOMError) -NS_IMPL_RELEASE_INHERITED(DOMMMIError, DOMError) - -DOMMMIError::DOMMMIError(nsPIDOMWindow* aWindow, const nsAString& aName, - const nsAString& aMessage, const nsAString& aServiceCode, - const Nullable& aInfo) - : DOMError(aWindow, aName, aMessage) - , mServiceCode(aServiceCode) - , mInfo(aInfo) -{ -} - -JSObject* -DOMMMIError::WrapObject(JSContext* aCx) -{ - return DOMMMIErrorBinding::Wrap(aCx, this); -} diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/mobileconnection/DOMMMIError.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/mobileconnection/DOMMMIError.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/mobileconnection/DOMMMIError.h 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/mobileconnection/DOMMMIError.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* 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_dom_MmiError_h -#define mozilla_dom_MmiError_h - -#include "mozilla/dom/DOMError.h" - -namespace mozilla { -namespace dom { - -class DOMMMIError MOZ_FINAL : public DOMError -{ -public: - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DOMMMIError, DOMError) - - DOMMMIError(nsPIDOMWindow* aWindow, const nsAString& aName, - const nsAString& aMessage, const nsAString& aServiceCode, - const Nullable& aInfo); - - virtual JSObject* - WrapObject(JSContext* aCx) MOZ_OVERRIDE; - - // WebIDL interface - - void - GetServiceCode(nsString& aServiceCode) const - { - aServiceCode = mServiceCode; - } - - Nullable - GetAdditionalInformation() const - { - return mInfo; - } - -private: - ~DOMMMIError() {} - -private: - nsString mServiceCode; - Nullable mInfo; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_MmiError_h diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/mobileconnection/ipc/MobileConnectionParent.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/mobileconnection/ipc/MobileConnectionParent.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/mobileconnection/ipc/MobileConnectionParent.h 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/mobileconnection/ipc/MobileConnectionParent.h 2015-01-09 12:36:59.000000000 +0000 @@ -36,7 +36,7 @@ } virtual void - ActorDestroy(ActorDestroyReason why); + ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; virtual bool RecvPMobileConnectionRequestConstructor(PMobileConnectionRequestParent* aActor, @@ -152,7 +152,7 @@ } virtual void - ActorDestroy(ActorDestroyReason why); + ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; nsresult SendReply(const MobileConnectionReply& aReply); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/mobileconnection/moz.build thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/mobileconnection/moz.build --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/mobileconnection/moz.build 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/mobileconnection/moz.build 2015-01-09 12:36:59.000000000 +0000 @@ -7,7 +7,6 @@ MOCHITEST_MANIFESTS += ['tests/mochitest/mochitest.ini'] EXPORTS.mozilla.dom += [ - 'DOMMMIError.h', 'MobileCellInfo.h', 'MobileConnection.h', 'MobileConnectionArray.h', @@ -34,7 +33,6 @@ UNIFIED_SOURCES += [ 'Assertions.cpp', - 'DOMMMIError.cpp', 'ipc/MobileConnectionChild.cpp', 'ipc/MobileConnectionIPCService.cpp', 'ipc/MobileConnectionParent.cpp', diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/mobilemessage/ipc/SmsParent.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/mobilemessage/ipc/SmsParent.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/mobilemessage/ipc/SmsParent.h 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/mobilemessage/ipc/SmsParent.h 2015-01-09 12:36:59.000000000 +0000 @@ -44,7 +44,7 @@ } virtual void - ActorDestroy(ActorDestroyReason why); + ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; virtual bool RecvPSmsRequestConstructor(PSmsRequestParent* aActor, diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/network/Connection.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/network/Connection.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/network/Connection.h 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/network/Connection.h 2015-01-09 12:36:59.000000000 +0000 @@ -37,7 +37,7 @@ void Shutdown(); // For IObserver - void Notify(const hal::NetworkInformation& aNetworkInfo); + void Notify(const hal::NetworkInformation& aNetworkInfo) MOZ_OVERRIDE; // WebIDL diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/network/TCPSocketParent.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/network/TCPSocketParent.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/network/TCPSocketParent.h 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/network/TCPSocketParent.h 2015-01-09 12:36:59.000000000 +0000 @@ -52,7 +52,7 @@ TCPSocketParent() {} virtual bool RecvOpen(const nsString& aHost, const uint16_t& aPort, - const bool& useSSL, const nsString& aBinaryType); + const bool& useSSL, const nsString& aBinaryType) MOZ_OVERRIDE; virtual bool RecvStartTLS() MOZ_OVERRIDE; virtual bool RecvSuspend() MOZ_OVERRIDE; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/notification/DesktopNotification.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/notification/DesktopNotification.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/notification/DesktopNotification.h 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/notification/DesktopNotification.h 2015-01-09 12:36:59.000000000 +0000 @@ -150,9 +150,9 @@ void Disconnect() { mNotification = nullptr; } NS_IMETHODIMP - Observe(nsISupports *aSubject, - const char *aTopic, - const char16_t *aData) + Observe(nsISupports* aSubject, + const char* aTopic, + const char16_t* aData) MOZ_OVERRIDE { // forward to parent diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/notification/Notification.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/notification/Notification.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/notification/Notification.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/notification/Notification.cpp 2015-01-09 12:36:59.000000000 +0000 @@ -64,7 +64,7 @@ const nsAString& aIcon, const nsAString& aData, const nsAString& aBehavior, - JSContext* aCx) + JSContext* aCx) MOZ_OVERRIDE { MOZ_ASSERT(!aID.IsEmpty()); @@ -99,7 +99,7 @@ return NS_OK; } - NS_IMETHOD Done(JSContext* aCx) + NS_IMETHOD Done(JSContext* aCx) MOZ_OVERRIDE { JSAutoCompartment ac(aCx, mGlobal); JS::Rooted result(aCx, JS::ObjectValue(*mNotifications)); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/plugins/base/nsJSNPRuntime.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/plugins/base/nsJSNPRuntime.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/plugins/base/nsJSNPRuntime.cpp 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/plugins/base/nsJSNPRuntime.cpp 2015-01-09 12:36:59.000000000 +0000 @@ -1750,7 +1750,7 @@ NPObject *npobj = (NPObject *)::JS_GetPrivate(obj); if (npobj) { if (sNPObjWrappers.ops) { - PL_DHashTableOperate(&sNPObjWrappers, npobj, PL_DHASH_REMOVE); + PL_DHashTableRemove(&sNPObjWrappers, npobj); } } @@ -1779,7 +1779,7 @@ JS::AutoSuppressGCAnalysis nogc; NPObjWrapperHashEntry *entry = static_cast - (PL_DHashTableOperate(&sNPObjWrappers, npobj, PL_DHASH_LOOKUP)); + (PL_DHashTableLookup(&sNPObjWrappers, npobj)); MOZ_ASSERT(PL_DHASH_ENTRY_IS_BUSY(entry) && entry->mJSObj); MOZ_ASSERT(entry->mJSObj == old); entry->mJSObj = obj; @@ -1832,7 +1832,7 @@ } NPObjWrapperHashEntry *entry = static_cast - (PL_DHashTableOperate(&sNPObjWrappers, npobj, PL_DHASH_LOOKUP)); + (PL_DHashTableLookup(&sNPObjWrappers, npobj)); if (PL_DHASH_ENTRY_IS_BUSY(entry) && entry->mJSObj) { // Found a live NPObject wrapper, null out its JSObjects' private @@ -1883,7 +1883,7 @@ } NPObjWrapperHashEntry *entry = static_cast - (PL_DHashTableOperate(&sNPObjWrappers, npobj, PL_DHASH_ADD)); + (PL_DHashTableAdd(&sNPObjWrappers, npobj)); if (!entry) { // Out of memory @@ -1917,7 +1917,7 @@ // the table (see bug 445229). This is guaranteed to succeed. entry = static_cast - (PL_DHashTableOperate(&sNPObjWrappers, npobj, PL_DHASH_LOOKUP)); + (PL_DHashTableLookup(&sNPObjWrappers, npobj)); NS_ASSERTION(entry && PL_DHASH_ENTRY_IS_BUSY(entry), "Hashtable didn't find what we just added?"); } @@ -2049,7 +2049,7 @@ } NPObjWrapperHashEntry *entry = static_cast - (PL_DHashTableOperate(&sNPObjWrappers, npobj, PL_DHASH_ADD)); + (PL_DHashTableAdd(&sNPObjWrappers, npobj)); if (PL_DHASH_ENTRY_IS_FREE(entry)) { return nullptr; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/plugins/base/nsPluginStreamListenerPeer.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/plugins/base/nsPluginStreamListenerPeer.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/plugins/base/nsPluginStreamListenerPeer.cpp 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/plugins/base/nsPluginStreamListenerPeer.cpp 2015-01-09 12:36:59.000000000 +0000 @@ -1260,14 +1260,14 @@ NS_DECL_ISUPPORTS - NS_IMETHODIMP OnRedirectVerifyCallback(nsresult result) + NS_IMETHODIMP OnRedirectVerifyCallback(nsresult aResult) MOZ_OVERRIDE { - if (NS_SUCCEEDED(result)) { + if (NS_SUCCEEDED(aResult)) { nsCOMPtr listener = do_QueryReferent(mWeakListener); if (listener) static_cast(listener.get())->ReplaceRequest(mOldChannel, mNewChannel); } - return mParent->OnRedirectVerifyCallback(result); + return mParent->OnRedirectVerifyCallback(aResult); } private: diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/plugins/base/PluginPRLibrary.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/plugins/base/PluginPRLibrary.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/plugins/base/PluginPRLibrary.h 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/plugins/base/PluginPRLibrary.h 2015-01-09 12:36:59.000000000 +0000 @@ -45,9 +45,9 @@ // unref here?? } - virtual void SetPlugin(nsNPAPIPlugin*) { } + virtual void SetPlugin(nsNPAPIPlugin*) MOZ_OVERRIDE { } - virtual bool HasRequiredFunctions() { + virtual bool HasRequiredFunctions() MOZ_OVERRIDE { mNP_Initialize = (NP_InitializeFunc) PR_FindFunctionSymbol(mLibrary, "NP_Initialize"); if (!mNP_Initialize) @@ -82,39 +82,39 @@ } #if defined(XP_UNIX) && !defined(XP_MACOSX) && !defined(MOZ_WIDGET_GONK) - virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, - NPPluginFuncs* pFuncs, NPError* error); + virtual nsresult NP_Initialize(NPNetscapeFuncs* aNetscapeFuncs, + NPPluginFuncs* aFuncs, NPError* aError) MOZ_OVERRIDE; #else - virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, - NPError* error); + virtual nsresult NP_Initialize(NPNetscapeFuncs* aNetscapeFuncs, + NPError* aError) MOZ_OVERRIDE; #endif - virtual nsresult NP_Shutdown(NPError* error); - virtual nsresult NP_GetMIMEDescription(const char** mimeDesc); + virtual nsresult NP_Shutdown(NPError* aError) MOZ_OVERRIDE; + virtual nsresult NP_GetMIMEDescription(const char** aMimeDesc) MOZ_OVERRIDE; - virtual nsresult NP_GetValue(void *future, NPPVariable aVariable, - void *aValue, NPError* error); + virtual nsresult NP_GetValue(void* aFuture, NPPVariable aVariable, + void* aValue, NPError* aError) MOZ_OVERRIDE; #if defined(XP_WIN) || defined(XP_MACOSX) - virtual nsresult NP_GetEntryPoints(NPPluginFuncs* pFuncs, NPError* error); + virtual nsresult NP_GetEntryPoints(NPPluginFuncs* aFuncs, NPError* aError) MOZ_OVERRIDE; #endif - virtual nsresult NPP_New(NPMIMEType pluginType, NPP instance, - uint16_t mode, int16_t argc, char* argn[], - char* argv[], NPSavedData* saved, - NPError* error); + virtual nsresult NPP_New(NPMIMEType aPluginType, NPP aInstance, + uint16_t aMode, int16_t aArgc, char* aArgn[], + char* aArgv[], NPSavedData* aSaved, + NPError* aError) MOZ_OVERRIDE; - virtual nsresult NPP_ClearSiteData(const char* site, uint64_t flags, - uint64_t maxAge); - virtual nsresult NPP_GetSitesWithData(InfallibleTArray& result); + virtual nsresult NPP_ClearSiteData(const char* aSite, uint64_t aFlags, + uint64_t aMaxAge) MOZ_OVERRIDE; + virtual nsresult NPP_GetSitesWithData(InfallibleTArray& aResult) MOZ_OVERRIDE; - virtual nsresult AsyncSetWindow(NPP instance, NPWindow* window); - virtual nsresult GetImageContainer(NPP instance, mozilla::layers::ImageContainer** aContainer); - virtual nsresult GetImageSize(NPP instance, nsIntSize* aSize); + virtual nsresult AsyncSetWindow(NPP aInstance, NPWindow* aWindow) MOZ_OVERRIDE; + virtual nsresult GetImageContainer(NPP aInstance, mozilla::layers::ImageContainer** aContainer) MOZ_OVERRIDE; + virtual nsresult GetImageSize(NPP aInstance, nsIntSize* aSize) MOZ_OVERRIDE; virtual bool IsOOP() MOZ_OVERRIDE { return false; } #if defined(XP_MACOSX) - virtual nsresult IsRemoteDrawingCoreAnimation(NPP instance, bool *aDrawing); - virtual nsresult ContentsScaleFactorChanged(NPP instance, double aContentsScaleFactor); + virtual nsresult IsRemoteDrawingCoreAnimation(NPP aInstance, bool* aDrawing) MOZ_OVERRIDE; + virtual nsresult ContentsScaleFactorChanged(NPP aInstance, double aContentsScaleFactor) MOZ_OVERRIDE; #endif virtual nsresult SetBackgroundUnknown(NPP instance) MOZ_OVERRIDE; virtual nsresult BeginUpdateBackground(NPP instance, diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/plugins/ipc/BrowserStreamParent.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/plugins/ipc/BrowserStreamParent.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/plugins/ipc/BrowserStreamParent.cpp 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/plugins/ipc/BrowserStreamParent.cpp 2015-01-09 12:36:59.000000000 +0000 @@ -13,7 +13,7 @@ // How much data are we willing to send across the wire // in one chunk? -static const int32_t kSendDataChunk = 0x4000; +static const int32_t kSendDataChunk = 0xffff; namespace mozilla { namespace plugins { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/plugins/ipc/PluginInstanceChild.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/plugins/ipc/PluginInstanceChild.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/plugins/ipc/PluginInstanceChild.h 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/plugins/ipc/PluginInstanceChild.h 2015-01-09 12:36:59.000000000 +0000 @@ -144,9 +144,9 @@ RecvPPluginScriptableObjectConstructor(PPluginScriptableObjectChild* aActor) MOZ_OVERRIDE; virtual bool - RecvPBrowserStreamConstructor(PBrowserStreamChild* aActor, const nsCString& url, - const uint32_t& length, const uint32_t& lastmodified, - PStreamNotifyChild* notifyData, const nsCString& headers); + RecvPBrowserStreamConstructor(PBrowserStreamChild* aActor, const nsCString& aURL, + const uint32_t& aLength, const uint32_t& aLastmodified, + PStreamNotifyChild* aNotifyData, const nsCString& aHeaders) MOZ_OVERRIDE; virtual bool AnswerNPP_NewStream( @@ -545,7 +545,7 @@ void Destroy(); - void ActorDestroy(ActorDestroyReason why); + void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; // Set as true when SetupLayer called // and go with different path in InvalidateRect function diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/plugins/ipc/PluginInstanceParent.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/plugins/ipc/PluginInstanceParent.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/plugins/ipc/PluginInstanceParent.h 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/plugins/ipc/PluginInstanceParent.h 2015-01-09 12:36:59.000000000 +0000 @@ -279,9 +279,9 @@ const nsIntRect& aRect); void DidComposite() { unused << SendNPP_DidComposite(); } - virtual PluginAsyncSurrogate* GetAsyncSurrogate(); + virtual PluginAsyncSurrogate* GetAsyncSurrogate() MOZ_OVERRIDE; - virtual PluginInstanceParent* GetInstance() { return this; } + virtual PluginInstanceParent* GetInstance() MOZ_OVERRIDE { return this; } static PluginInstanceParent* Cast(NPP instance, PluginAsyncSurrogate** aSurrogate = nullptr); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/plugins/ipc/PluginModuleParent.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/plugins/ipc/PluginModuleParent.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/plugins/ipc/PluginModuleParent.h 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/plugins/ipc/PluginModuleParent.h 2015-01-09 12:36:59.000000000 +0000 @@ -114,7 +114,7 @@ return !IsOnCxxStack(); } - void ProcessRemoteNativeEventsInInterruptCall(); + void ProcessRemoteNativeEventsInInterruptCall() MOZ_OVERRIDE; virtual bool WaitForIPCConnection() { return true; } @@ -214,10 +214,10 @@ static void NPP_URLRedirectNotify(NPP instance, const char* url, int32_t status, void* notifyData); - virtual bool HasRequiredFunctions(); - virtual nsresult AsyncSetWindow(NPP instance, NPWindow* window); - virtual nsresult GetImageContainer(NPP instance, mozilla::layers::ImageContainer** aContainer); - virtual nsresult GetImageSize(NPP instance, nsIntSize* aSize); + virtual bool HasRequiredFunctions() MOZ_OVERRIDE; + virtual nsresult AsyncSetWindow(NPP aInstance, NPWindow* aWindow) MOZ_OVERRIDE; + virtual nsresult GetImageContainer(NPP aInstance, mozilla::layers::ImageContainer** aContainer) MOZ_OVERRIDE; + virtual nsresult GetImageSize(NPP aInstance, nsIntSize* aSize) MOZ_OVERRIDE; virtual bool IsOOP() MOZ_OVERRIDE { return true; } virtual nsresult SetBackgroundUnknown(NPP instance) MOZ_OVERRIDE; virtual nsresult BeginUpdateBackground(NPP instance, @@ -230,27 +230,27 @@ #if defined(XP_UNIX) && !defined(XP_MACOSX) && !defined(MOZ_WIDGET_GONK) virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, NPError* error); #else - virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error); + virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error) MOZ_OVERRIDE; #endif - virtual nsresult NP_Shutdown(NPError* error); + virtual nsresult NP_Shutdown(NPError* error) MOZ_OVERRIDE; - virtual nsresult NP_GetMIMEDescription(const char** mimeDesc); + virtual nsresult NP_GetMIMEDescription(const char** mimeDesc) MOZ_OVERRIDE; virtual nsresult NP_GetValue(void *future, NPPVariable aVariable, - void *aValue, NPError* error); + void *aValue, NPError* error) MOZ_OVERRIDE; #if defined(XP_WIN) || defined(XP_MACOSX) - virtual nsresult NP_GetEntryPoints(NPPluginFuncs* pFuncs, NPError* error); + virtual nsresult NP_GetEntryPoints(NPPluginFuncs* pFuncs, NPError* error) MOZ_OVERRIDE; #endif virtual nsresult NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* saved, - NPError* error); + NPError* error) MOZ_OVERRIDE; virtual nsresult NPP_ClearSiteData(const char* site, uint64_t flags, - uint64_t maxAge); - virtual nsresult NPP_GetSitesWithData(InfallibleTArray& result); + uint64_t maxAge) MOZ_OVERRIDE; + virtual nsresult NPP_GetSitesWithData(InfallibleTArray& result) MOZ_OVERRIDE; #if defined(XP_MACOSX) - virtual nsresult IsRemoteDrawingCoreAnimation(NPP instance, bool *aDrawing); - virtual nsresult ContentsScaleFactorChanged(NPP instance, double aContentsScaleFactor); + virtual nsresult IsRemoteDrawingCoreAnimation(NPP instance, bool *aDrawing) MOZ_OVERRIDE; + virtual nsresult ContentsScaleFactorChanged(NPP instance, double aContentsScaleFactor) MOZ_OVERRIDE; #endif void InitAsyncSurrogates(); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/power/PowerManagerService.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/power/PowerManagerService.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/power/PowerManagerService.h 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/power/PowerManagerService.h 2015-01-09 12:37:00.000000000 +0000 @@ -35,7 +35,7 @@ void Init(); // Implement WakeLockObserver - void Notify(const hal::WakeLockInformation& aWakeLockInfo); + void Notify(const hal::WakeLockInformation& aWakeLockInfo) MOZ_OVERRIDE; /** * Acquire a wake lock on behalf of a given process (aContentParent). diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/promise/Promise.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/promise/Promise.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/promise/Promise.cpp 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/promise/Promise.cpp 2015-01-09 12:37:00.000000000 +0000 @@ -273,6 +273,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Promise) NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY NS_INTERFACE_MAP_ENTRY(nsISupports) + NS_INTERFACE_MAP_ENTRY(Promise) NS_INTERFACE_MAP_END Promise::Promise(nsIGlobalObject* aGlobal) @@ -788,13 +789,13 @@ } void - ResolvedCallback(JSContext* aCx, JS::Handle aValue) + ResolvedCallback(JSContext* aCx, JS::Handle aValue) MOZ_OVERRIDE { mCountdownHolder->SetValue(mIndex, aValue); } void - RejectedCallback(JSContext* aCx, JS::Handle aValue) + RejectedCallback(JSContext* aCx, JS::Handle aValue) MOZ_OVERRIDE { // Should never be attached to Promise as a reject handler. MOZ_ASSERT(false, "AllResolveHandler should never be attached to a Promise's reject handler!"); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/promise/Promise.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/promise/Promise.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/promise/Promise.h 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/promise/Promise.h 2015-01-09 12:37:00.000000000 +0000 @@ -52,6 +52,10 @@ Notify(JSContext* aCx, workers::Status aStatus) MOZ_OVERRIDE; }; +#define NS_PROMISE_IID \ + { 0x1b8d6215, 0x3e67, 0x43ba, \ + { 0x8a, 0xf9, 0x31, 0x5e, 0x8f, 0xce, 0x75, 0x65 } } + class Promise : public nsISupports, public nsWrapperCache, public SupportsWeakPtr @@ -68,6 +72,7 @@ friend class WrapperPromiseCallback; public: + NS_DECLARE_STATIC_IID_ACCESSOR(NS_PROMISE_IID) NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Promise) MOZ_DECLARE_REFCOUNTED_TYPENAME(Promise) @@ -332,6 +337,8 @@ TimeStamp mSettlementTimestamp; }; +NS_DEFINE_STATIC_IID_ACCESSOR(Promise, NS_PROMISE_IID) + } // namespace dom } // namespace mozilla diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/promise/PromiseWorkerProxy.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/promise/PromiseWorkerProxy.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/promise/PromiseWorkerProxy.h 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/promise/PromiseWorkerProxy.h 2015-01-09 12:37:00.000000000 +0000 @@ -62,7 +62,7 @@ friend class PromiseWorkerProxyRunnable; // This overrides the non-threadsafe refcounting in PromiseNativeHandler. - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PromiseWorkerProxy) + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PromiseWorkerProxy, MOZ_OVERRIDE) public: static already_AddRefed diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/quota/QuotaManager.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/quota/QuotaManager.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/quota/QuotaManager.cpp 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/quota/QuotaManager.cpp 2015-01-09 12:37:00.000000000 +0000 @@ -225,7 +225,7 @@ { } NS_IMETHOD - Run(); + Run() MOZ_OVERRIDE; void AdvanceState() @@ -299,7 +299,7 @@ nsIUsageCallback* aCallback); NS_IMETHOD - Run(); + Run() MOZ_OVERRIDE; void AdvanceState() @@ -369,7 +369,7 @@ { } NS_IMETHOD - Run(); + Run() MOZ_OVERRIDE; void AdvanceState() diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/smil/nsSMILFloatType.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/smil/nsSMILFloatType.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/smil/nsSMILFloatType.h 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/smil/nsSMILFloatType.h 2015-01-09 12:37:01.000000000 +0000 @@ -23,11 +23,11 @@ protected: // nsISMILType Methods // ------------------- - virtual void Init(nsSMILValue& aValue) const MOZ_OVERRIDE; - virtual void Destroy(nsSMILValue&) const; + virtual void Init(nsSMILValue& aValue) const MOZ_OVERRIDE; + virtual void Destroy(nsSMILValue& aValue) const MOZ_OVERRIDE; virtual nsresult Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const MOZ_OVERRIDE; - virtual bool IsEqual(const nsSMILValue& aLeft, - const nsSMILValue& aRight) const MOZ_OVERRIDE; + virtual bool IsEqual(const nsSMILValue& aLeft, + const nsSMILValue& aRight) const MOZ_OVERRIDE; virtual nsresult Add(nsSMILValue& aDest, const nsSMILValue& aValueToAdd, uint32_t aCount) const MOZ_OVERRIDE; virtual nsresult ComputeDistance(const nsSMILValue& aFrom, diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/smil/SMILBoolType.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/smil/SMILBoolType.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/smil/SMILBoolType.h 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/smil/SMILBoolType.h 2015-01-09 12:37:00.000000000 +0000 @@ -24,13 +24,13 @@ protected: // nsISMILType Methods // ------------------- - virtual void Init(nsSMILValue& aValue) const MOZ_OVERRIDE; - virtual void Destroy(nsSMILValue&) const; + virtual void Init(nsSMILValue& aValue) const MOZ_OVERRIDE; + virtual void Destroy(nsSMILValue& aValue) const MOZ_OVERRIDE; virtual nsresult Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const MOZ_OVERRIDE; virtual nsresult Add(nsSMILValue& aDest, const nsSMILValue& aValueToAdd, uint32_t aCount) const MOZ_OVERRIDE; virtual bool IsEqual(const nsSMILValue& aLeft, - const nsSMILValue& aRight) const MOZ_OVERRIDE; + const nsSMILValue& aRight) const MOZ_OVERRIDE; virtual nsresult ComputeDistance(const nsSMILValue& aFrom, const nsSMILValue& aTo, double& aDistance) const MOZ_OVERRIDE; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/smil/SMILEnumType.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/smil/SMILEnumType.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/smil/SMILEnumType.h 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/smil/SMILEnumType.h 2015-01-09 12:37:00.000000000 +0000 @@ -25,11 +25,11 @@ protected: // nsISMILType Methods // ------------------- - virtual void Init(nsSMILValue& aValue) const MOZ_OVERRIDE; - virtual void Destroy(nsSMILValue&) const; + virtual void Init(nsSMILValue& aValue) const MOZ_OVERRIDE; + virtual void Destroy(nsSMILValue& aValue) const MOZ_OVERRIDE; virtual nsresult Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const MOZ_OVERRIDE; - virtual bool IsEqual(const nsSMILValue& aLeft, - const nsSMILValue& aRight) const MOZ_OVERRIDE; + virtual bool IsEqual(const nsSMILValue& aLeft, + const nsSMILValue& aRight) const MOZ_OVERRIDE; virtual nsresult Add(nsSMILValue& aDest, const nsSMILValue& aValueToAdd, uint32_t aCount) const MOZ_OVERRIDE; virtual nsresult ComputeDistance(const nsSMILValue& aFrom, diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/smil/SMILIntegerType.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/smil/SMILIntegerType.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/smil/SMILIntegerType.h 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/smil/SMILIntegerType.h 2015-01-09 12:37:00.000000000 +0000 @@ -14,11 +14,11 @@ class SMILIntegerType : public nsISMILType { public: - virtual void Init(nsSMILValue& aValue) const MOZ_OVERRIDE; - virtual void Destroy(nsSMILValue&) const; + virtual void Init(nsSMILValue& aValue) const MOZ_OVERRIDE; + virtual void Destroy(nsSMILValue& aValue) const MOZ_OVERRIDE; virtual nsresult Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const MOZ_OVERRIDE; - virtual bool IsEqual(const nsSMILValue& aLeft, - const nsSMILValue& aRight) const MOZ_OVERRIDE; + virtual bool IsEqual(const nsSMILValue& aLeft, + const nsSMILValue& aRight) const MOZ_OVERRIDE; virtual nsresult Add(nsSMILValue& aDest, const nsSMILValue& aValueToAdd, uint32_t aCount) const MOZ_OVERRIDE; virtual nsresult ComputeDistance(const nsSMILValue& aFrom, diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/smil/SMILStringType.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/smil/SMILStringType.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/smil/SMILStringType.h 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/smil/SMILStringType.h 2015-01-09 12:37:00.000000000 +0000 @@ -25,11 +25,11 @@ protected: // nsISMILType Methods // ------------------- - virtual void Init(nsSMILValue& aValue) const MOZ_OVERRIDE; - virtual void Destroy(nsSMILValue&) const; + virtual void Init(nsSMILValue& aValue) const MOZ_OVERRIDE; + virtual void Destroy(nsSMILValue& aValue) const MOZ_OVERRIDE; virtual nsresult Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const MOZ_OVERRIDE; - virtual bool IsEqual(const nsSMILValue& aLeft, - const nsSMILValue& aRight) const MOZ_OVERRIDE; + virtual bool IsEqual(const nsSMILValue& aLeft, + const nsSMILValue& aRight) const MOZ_OVERRIDE; virtual nsresult Add(nsSMILValue& aDest, const nsSMILValue& aValueToAdd, uint32_t aCount) const MOZ_OVERRIDE; virtual nsresult ComputeDistance(const nsSMILValue& aFrom, diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/storage/DOMStorageCache.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/storage/DOMStorageCache.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/storage/DOMStorageCache.cpp 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/storage/DOMStorageCache.cpp 2015-01-09 12:37:01.000000000 +0000 @@ -247,7 +247,7 @@ NS_DECL_ISUPPORTS NS_IMETHODIMP - Notify(nsITimer* aTimer) + Notify(nsITimer* aTimer) MOZ_OVERRIDE { mCache = nullptr; return NS_OK; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/storage/DOMStorageIPC.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/storage/DOMStorageIPC.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/storage/DOMStorageIPC.h 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/storage/DOMStorageIPC.h 2015-01-09 12:37:01.000000000 +0000 @@ -174,27 +174,27 @@ private: // IPC virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; - bool RecvAsyncPreload(const nsCString& aScope, const bool& aPriority); + bool RecvAsyncPreload(const nsCString& aScope, const bool& aPriority) MOZ_OVERRIDE; bool RecvPreload(const nsCString& aScope, const uint32_t& aAlreadyLoadedCount, InfallibleTArray* aKeys, InfallibleTArray* aValues, - nsresult* aRv); - bool RecvAsyncGetUsage(const nsCString& aScope); - bool RecvAsyncAddItem(const nsCString& aScope, const nsString& aKey, const nsString& aValue); - bool RecvAsyncUpdateItem(const nsCString& aScope, const nsString& aKey, const nsString& aValue); - bool RecvAsyncRemoveItem(const nsCString& aScope, const nsString& aKey); - bool RecvAsyncClear(const nsCString& aScope); - bool RecvAsyncFlush(); + nsresult* aRv) MOZ_OVERRIDE; + bool RecvAsyncGetUsage(const nsCString& aScope) MOZ_OVERRIDE; + bool RecvAsyncAddItem(const nsCString& aScope, const nsString& aKey, const nsString& aValue) MOZ_OVERRIDE; + bool RecvAsyncUpdateItem(const nsCString& aScope, const nsString& aKey, const nsString& aValue) MOZ_OVERRIDE; + bool RecvAsyncRemoveItem(const nsCString& aScope, const nsString& aKey) MOZ_OVERRIDE; + bool RecvAsyncClear(const nsCString& aScope) MOZ_OVERRIDE; + bool RecvAsyncFlush() MOZ_OVERRIDE; // DOMStorageObserverSink - virtual nsresult Observe(const char* aTopic, const nsACString& aScopePrefix); + virtual nsresult Observe(const char* aTopic, const nsACString& aScopePrefix) MOZ_OVERRIDE; private: CacheParentBridge* NewCache(const nsACString& aScope); ThreadSafeAutoRefCnt mRefCnt; NS_DECL_OWNINGTHREAD - - // True when IPC channel is open and Send*() methods are OK to use. + + // True when IPC channel is open and Send*() methods are OK to use. bool mIPCOpen; }; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/storage/DOMStorageManager.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/storage/DOMStorageManager.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/storage/DOMStorageManager.h 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/storage/DOMStorageManager.h 2015-01-09 12:37:01.000000000 +0000 @@ -46,7 +46,7 @@ private: // DOMStorageObserverSink, handler to various chrome clearing notification - virtual nsresult Observe(const char* aTopic, const nsACString& aScopePrefix); + virtual nsresult Observe(const char* aTopic, const nsACString& aScopePrefix) MOZ_OVERRIDE; // Since nsTHashtable doesn't like multiple inheritance, we have to aggregate // DOMStorageCache into the entry. diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/svg/nsSVGBoolean.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/svg/nsSVGBoolean.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/svg/nsSVGBoolean.cpp 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/svg/nsSVGBoolean.cpp 2015-01-09 12:37:01.000000000 +0000 @@ -56,7 +56,7 @@ nsresult nsSVGBoolean::SetBaseValueAtom(const nsIAtom* aValue, nsSVGElement *aSVGElement) { - bool val; + bool val = false; nsresult rv = GetValueFromAtom(aValue, &val); if (NS_FAILED(rv)) { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/svg/nsSVGPathGeometryElement.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/svg/nsSVGPathGeometryElement.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/svg/nsSVGPathGeometryElement.cpp 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/svg/nsSVGPathGeometryElement.cpp 2015-01-09 12:37:01.000000000 +0000 @@ -87,7 +87,9 @@ // chrome). The benefit is that we avoid causing a CPU memory cache miss by // looking at the global variable that the pref's stored in. if (cacheable && mCachedPath) { - return mCachedPath; + if (aDrawTarget.GetBackendType() == mCachedPath->GetBackendType()) { + return mCachedPath; + } } RefPtr builder = aDrawTarget.CreatePathBuilder(aFillRule); RefPtr path = BuildPath(builder); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/system/gonk/AudioManager.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/system/gonk/AudioManager.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/system/gonk/AudioManager.cpp 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/system/gonk/AudioManager.cpp 2015-01-09 12:37:01.000000000 +0000 @@ -51,6 +51,7 @@ using namespace mozilla; using namespace mozilla::dom::bluetooth; +#undef LOG #define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "AudioManager" , ## args) #define HEADPHONES_STATUS_HEADSET MOZ_UTF16("headset") diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/system/gonk/RadioInterfaceLayer.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/system/gonk/RadioInterfaceLayer.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/system/gonk/RadioInterfaceLayer.js 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/system/gonk/RadioInterfaceLayer.js 2015-01-09 12:37:01.000000000 +0000 @@ -101,7 +101,8 @@ "RIL:ReadIccContacts", "RIL:UpdateIccContact", "RIL:RegisterIccMsg", - "RIL:MatchMvno" + "RIL:MatchMvno", + "RIL:GetServiceState" ]; // set to true in ril_consts.js to see debug messages @@ -1836,6 +1837,9 @@ case "RIL:MatchMvno": this.matchMvno(msg.target, msg.json.data); break; + case "RIL:GetServiceState": + this.workerMessenger.sendWithIPCMessage(msg, "getIccServiceState"); + break; } return null; }, diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/system/gonk/ril_consts.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/system/gonk/ril_consts.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/system/gonk/ril_consts.js 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/system/gonk/ril_consts.js 2015-01-09 12:37:01.000000000 +0000 @@ -668,6 +668,8 @@ this.ICC_SEL_CODE_PH_SP_PUK = "PH-SP PUK"; this.ICC_SEL_CODE_PH_CORP_PIN = "PH-CORP PIN"; this.ICC_SEL_CODE_PH_CORP_PUK = "PH-CORP PUK"; +// TODO: Bug 1116072: identify the mapping between RIL_PERSOSUBSTATE_SIM_SIM @ +// ril.h and TS 27.007, clause 8.65 for GECKO_CARDLOCK_PCK. this.ICC_USIM_TYPE1_TAG = 0xa8; this.ICC_USIM_TYPE2_TAG = 0xa9; @@ -2611,22 +2613,26 @@ this.GECKO_CARDLOCK_PUK = 2; this.GECKO_CARDLOCK_PUK2 = 3; this.GECKO_CARDLOCK_NCK = 4; -this.GECKO_CARDLOCK_NCK1 = 5; -this.GECKO_CARDLOCK_NCK2 = 6; -this.GECKO_CARDLOCK_HNCK = 7; -this.GECKO_CARDLOCK_CCK = 8; -this.GECKO_CARDLOCK_SPCK = 9; -this.GECKO_CARDLOCK_RCCK = 10; -this.GECKO_CARDLOCK_RSPCK = 11; -this.GECKO_CARDLOCK_NCK_PUK = 12; -this.GECKO_CARDLOCK_NCK1_PUK = 13; -this.GECKO_CARDLOCK_NCK2_PUK = 14; -this.GECKO_CARDLOCK_HNCK_PUK = 15; -this.GECKO_CARDLOCK_CCK_PUK = 16; -this.GECKO_CARDLOCK_SPCK_PUK = 17; -this.GECKO_CARDLOCK_RCCK_PUK = 18; -this.GECKO_CARDLOCK_RSPCK_PUK = 19; -this.GECKO_CARDLOCK_FDN = 20; +this.GECKO_CARDLOCK_NSCK = 5; +this.GECKO_CARDLOCK_NCK1 = 6; +this.GECKO_CARDLOCK_NCK2 = 7; +this.GECKO_CARDLOCK_HNCK = 8; +this.GECKO_CARDLOCK_CCK = 9; +this.GECKO_CARDLOCK_SPCK = 10; +this.GECKO_CARDLOCK_PCK = 11; +this.GECKO_CARDLOCK_RCCK = 12; +this.GECKO_CARDLOCK_RSPCK = 13; +this.GECKO_CARDLOCK_NCK_PUK = 14; +this.GECKO_CARDLOCK_NSCK_PUK = 15; +this.GECKO_CARDLOCK_NCK1_PUK = 16; +this.GECKO_CARDLOCK_NCK2_PUK = 17; +this.GECKO_CARDLOCK_HNCK_PUK = 18; +this.GECKO_CARDLOCK_CCK_PUK = 19; +this.GECKO_CARDLOCK_SPCK_PUK = 20; +this.GECKO_CARDLOCK_PCK_PUK = 21; +this.GECKO_CARDLOCK_RCCK_PUK = 22; +this.GECKO_CARDLOCK_RSPCK_PUK = 23; +this.GECKO_CARDLOCK_FDN = 24; this.GECKO_CARDLOCK_TO_FACILITY = {}; GECKO_CARDLOCK_TO_FACILITY[GECKO_CARDLOCK_PIN] = ICC_CB_FACILITY_SIM; @@ -2638,8 +2644,11 @@ GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_PUK] = ICC_SEL_CODE_SIM_PUK; GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_PUK2] = ICC_SEL_CODE_SIM_PUK2; GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_NCK] = ICC_SEL_CODE_PH_NET_PIN; +GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_NSCK] = ICC_SEL_CODE_PH_NETSUB_PIN; GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_CCK] = ICC_SEL_CODE_PH_CORP_PIN; GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_SPCK] = ICC_SEL_CODE_PH_SP_PIN; +// TODO: Bug 1116072: identify the mapping between RIL_PERSOSUBSTATE_SIM_SIM @ +// ril.h and TS 27.007, clause 8.65 for GECKO_CARDLOCK_PCK. // See nsIIccProvider::CARD_CONTACT_TYPE_* this.GECKO_CARDCONTACT_TYPE_ADN = 0; @@ -2651,6 +2660,9 @@ this.GECKO_CARDMVNO_TYPE_SPN = 1; this.GECKO_CARDMVNO_TYPE_GID = 2; +// See nsIIccProvider::CARD_MVNO_TYPE_* +this.GECKO_CARDSERVICE_FDN = 0; + // See ril.h RIL_PersoSubstate this.PERSONSUBSTATE = {}; PERSONSUBSTATE[CARD_PERSOSUBSTATE_UNKNOWN] = GECKO_CARDSTATE_UNKNOWN; @@ -2679,24 +2691,6 @@ PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK] = GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED; PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_RUIM_PUK] = GECKO_CARDSTATE_RUIM_PUK_REQUIRED; -this.GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK = {}; -GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_NCK] = CARD_PERSOSUBSTATE_SIM_NETWORK; -GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_NCK1] = CARD_PERSOSUBSTATE_RUIM_NETWORK1; -GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_NCK2] = CARD_PERSOSUBSTATE_RUIM_NETWORK2; -GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_HNCK] = CARD_PERSOSUBSTATE_RUIM_HRPD; -GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_CCK] = CARD_PERSOSUBSTATE_SIM_CORPORATE; -GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_SPCK] = CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER; -GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_RCCK] = CARD_PERSOSUBSTATE_RUIM_CORPORATE; -GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_RSPCK] = CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER; -GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_NCK_PUK] = CARD_PERSOSUBSTATE_SIM_NETWORK_PUK; -GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_NCK1_PUK] = CARD_PERSOSUBSTATE_RUIM_NETWORK1_PUK; -GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_NCK2_PUK] = CARD_PERSOSUBSTATE_RUIM_NETWORK2_PUK; -GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_HNCK_PUK] = CARD_PERSOSUBSTATE_RUIM_HRPD_PUK; -GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_CCK_PUK] = CARD_PERSOSUBSTATE_SIM_CORPORATE_PUK; -GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_SPCK_PUK] = CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK; -GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_RCCK_PUK] = CARD_PERSOSUBSTATE_RUIM_CORPORATE_PUK; -GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[GECKO_CARDLOCK_RSPCK_PUK] = CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK; - // See nsIMobileConnection::NETWORK_SELECTION_MODE_* this.GECKO_NETWORK_SELECTION_UNKNOWN = -1; this.GECKO_NETWORK_SELECTION_AUTOMATIC = 0; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/system/gonk/RILContentHelper.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/system/gonk/RILContentHelper.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/system/gonk/RILContentHelper.js 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/system/gonk/RILContentHelper.js 2015-01-09 12:37:01.000000000 +0000 @@ -55,7 +55,8 @@ "RIL:IccExchangeAPDU", "RIL:ReadIccContacts", "RIL:UpdateIccContact", - "RIL:MatchMvno" + "RIL:MatchMvno", + "RIL:GetServiceState" ]; XPCOMUtils.defineLazyServiceGetter(this, "cpmm", @@ -536,6 +537,27 @@ return request; }, + getServiceState: function(clientId, window, service) { + if (window == null) { + throw Components.Exception("Can't get window object", + Cr.NS_ERROR_UNEXPECTED); + } + + return new window.Promise((resolve, reject) => { + let requestId = + this.getPromiseResolverId({resolve: resolve, reject: reject}); + this._windowsMap[requestId] = window; + + cpmm.sendAsyncMessage("RIL:GetServiceState", { + clientId: clientId, + data: { + requestId: requestId, + service: service + } + }); + }); + }, + _iccListeners: null, registerListener: function(listenerType, clientId, listener) { @@ -772,6 +794,9 @@ case "RIL:MatchMvno": this.handleSimpleRequest(data.requestId, data.errorMsg, data.result); break; + case "RIL:GetServiceState": + this.handleGetServiceState(data); + break; } }, @@ -874,6 +899,20 @@ this.fireRequestSuccess(message.requestId, contact); }, + handleGetServiceState: function(message) { + let requestId = message.requestId; + let requestWindow = this._windowsMap[requestId]; + delete this._windowsMap[requestId]; + + let resolver = this.takePromiseResolver(requestId); + if (message.errorMsg) { + resolver.reject(new requestWindow.DOMError(message.errorMsg)); + return; + } + + resolver.resolve(message.result); + }, + _deliverEvent: function(clientId, listenerType, name, args) { if (!this[listenerType]) { return; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/system/gonk/ril_worker.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/system/gonk/ril_worker.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/system/gonk/ril_worker.js 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/system/gonk/ril_worker.js 2015-01-09 12:37:01.000000000 +0000 @@ -616,23 +616,25 @@ this.enterICCPUK2(options); break; case GECKO_CARDLOCK_NCK: + case GECKO_CARDLOCK_NSCK: case GECKO_CARDLOCK_NCK1: case GECKO_CARDLOCK_NCK2: case GECKO_CARDLOCK_HNCK: case GECKO_CARDLOCK_CCK: case GECKO_CARDLOCK_SPCK: + case GECKO_CARDLOCK_PCK: case GECKO_CARDLOCK_RCCK: case GECKO_CARDLOCK_RSPCK: case GECKO_CARDLOCK_NCK_PUK: + case GECKO_CARDLOCK_NSCK_PUK: case GECKO_CARDLOCK_NCK1_PUK: case GECKO_CARDLOCK_NCK2_PUK: case GECKO_CARDLOCK_HNCK_PUK: case GECKO_CARDLOCK_CCK_PUK: case GECKO_CARDLOCK_SPCK_PUK: + case GECKO_CARDLOCK_PCK_PUK: case GECKO_CARDLOCK_RCCK_PUK: // Fall through. case GECKO_CARDLOCK_RSPCK_PUK: - options.personlization = - GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[options.lockType]; this.enterDepersonalization(options); break; default: @@ -690,7 +692,7 @@ enterDepersonalization: function(options) { let Buf = this.context.Buf; Buf.newParcel(REQUEST_ENTER_NETWORK_DEPERSONALIZATION_CODE, options); - Buf.writeInt32(options.personlization); + Buf.writeInt32(1); Buf.writeString(options.password); Buf.sendParcel(); }, @@ -863,8 +865,11 @@ case GECKO_CARDLOCK_PUK: case GECKO_CARDLOCK_PUK2: case GECKO_CARDLOCK_NCK: + case GECKO_CARDLOCK_NSCK: case GECKO_CARDLOCK_CCK: // Fall through. case GECKO_CARDLOCK_SPCK: + // TODO: Bug 1116072: identify the mapping between RIL_PERSOSUBSTATE_SIM_SIM + // @ ril.h and TS 27.007, clause 8.65 for GECKO_CARDLOCK_SPCK. options.selCode = GECKO_CARDLOCK_TO_SEL_CODE[options.lockType]; break; default: @@ -1504,6 +1509,22 @@ }, /** + * Get UICC service state + */ + getIccServiceState: function(options) { + switch (options.service) { + case GECKO_CARDSERVICE_FDN: + let ICCUtilsHelper = this.context.ICCUtilsHelper; + options.result = ICCUtilsHelper.isICCServiceAvailable("FDN"); + break; + default: + options.errorMsg = GECKO_ERROR_REQUEST_NOT_SUPPORTED; + break; + } + this.sendChromeMessage(options); + }, + + /** * Enable/Disable UICC subscription */ setUiccSubscription: function(options) { @@ -2244,7 +2265,7 @@ */ startTone: function(options) { let Buf = this.context.Buf; - Buf.newParcel(REQUEST_DTMF_START); + Buf.newParcel(REQUEST_DTMF_START, options); Buf.writeString(options.dtmfChar); Buf.sendParcel(); }, @@ -4110,7 +4131,7 @@ _addVoiceCall: function(newCall) { newCall.number = this._formatInternationalNumber(newCall.number, newCall.toa); - newCall.isOutgoing = !(newCall.state == CALL_STATE_INCOMING); + newCall.isOutgoing = !newCall.isMT; newCall.isConference = false; this.currentCalls[newCall.callIndex] = newCall; @@ -6187,7 +6208,13 @@ } this.sendChromeMessage(options); }; -RilObject.prototype[REQUEST_DTMF_START] = null; +RilObject.prototype[REQUEST_DTMF_START] = function REQUEST_DTMF_START(length, options) { + options.success = (options.rilRequestError === 0); + if (!options.success) { + options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError]; + } + this.sendChromeMessage(options); +}; RilObject.prototype[REQUEST_DTMF_STOP] = null; RilObject.prototype[REQUEST_BASEBAND_VERSION] = function REQUEST_BASEBAND_VERSION(length, options) { if (options.rilRequestError) { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/system/gonk/tests/test_ril_worker_icc_CardLock.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/system/gonk/tests/test_ril_worker_icc_CardLock.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/system/gonk/tests/test_ril_worker_icc_CardLock.js 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/system/gonk/tests/test_ril_worker_icc_CardLock.js 2015-01-09 12:37:01.000000000 +0000 @@ -270,7 +270,7 @@ let ril = context.RIL; let buf = context.Buf; - function do_test(aLock, aPassword) { + function do_test(aPassword) { buf.sendParcel = function fakeSendParcel() { // Request Type. do_check_eq(this.readInt32(), REQUEST_ENTER_NETWORK_DEPERSONALIZATION_CODE); @@ -279,32 +279,18 @@ this.readInt32(); // Data - do_check_eq(this.readInt32(), GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[aLock]); - do_check_eq(this.readString(), aPassword); + let parcel = this.readStringList(); + do_check_eq(parcel.length, 1); + do_check_eq(parcel[0], aPassword); }; ril.iccUnlockCardLock({ - lockType: aLock, + lockType: GECKO_CARDLOCK_NCK, password: aPassword }); } - do_test(GECKO_CARDLOCK_NCK, "12345678"); - do_test(GECKO_CARDLOCK_NCK1, "12345678"); - do_test(GECKO_CARDLOCK_NCK2, "12345678"); - do_test(GECKO_CARDLOCK_HNCK, "12345678"); - do_test(GECKO_CARDLOCK_CCK, "12345678"); - do_test(GECKO_CARDLOCK_SPCK, "12345678"); - do_test(GECKO_CARDLOCK_RCCK, "12345678"); - do_test(GECKO_CARDLOCK_RSPCK, "12345678"); - do_test(GECKO_CARDLOCK_NCK_PUK, "12345678"); - do_test(GECKO_CARDLOCK_NCK1_PUK, "12345678"); - do_test(GECKO_CARDLOCK_NCK2_PUK, "12345678"); - do_test(GECKO_CARDLOCK_HNCK_PUK, "12345678"); - do_test(GECKO_CARDLOCK_CCK_PUK, "12345678"); - do_test(GECKO_CARDLOCK_SPCK_PUK, "12345678"); - do_test(GECKO_CARDLOCK_RCCK_PUK, "12345678"); - do_test(GECKO_CARDLOCK_RSPCK_PUK, "12345678"); + do_test("12345678"); run_next_test(); }); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/system/gonk/VolumeManager.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/system/gonk/VolumeManager.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/system/gonk/VolumeManager.cpp 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/system/gonk/VolumeManager.cpp 2015-01-09 12:37:01.000000000 +0000 @@ -180,7 +180,6 @@ return; } while(fgets(line, sizeof(line), fp)) { - const char *delim = " \t\n"; n++; if (line[0] == '#') diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/system/nsDeviceSensors.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/system/nsDeviceSensors.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/system/nsDeviceSensors.h 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/system/nsDeviceSensors.h 2015-01-09 12:37:02.000000000 +0000 @@ -33,7 +33,7 @@ nsDeviceSensors(); - void Notify(const mozilla::hal::SensorData& aSensorData); + void Notify(const mozilla::hal::SensorData& aSensorData) MOZ_OVERRIDE; private: virtual ~nsDeviceSensors(); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/gonk/TelephonyService.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/gonk/TelephonyService.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/gonk/TelephonyService.js 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/gonk/TelephonyService.js 2015-01-09 12:37:02.000000000 +0000 @@ -20,10 +20,13 @@ const GONK_TELEPHONYSERVICE_CONTRACTID = "@mozilla.org/telephony/gonktelephonyservice;1"; + const GONK_TELEPHONYSERVICE_CID = Components.ID("{67d26434-d063-4d28-9f48-5b3189788155}"); const MOBILECALLFORWARDINGOPTIONS_CID = Components.ID("{79b5988b-9436-48d8-a652-88fa033f146c}"); +const TELEPHONYCALLINFO_CID = + Components.ID("{d9e8b358-a02c-4cf3-9fc7-816c2e8d46e4}"); const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown"; @@ -47,6 +50,8 @@ const DEFAULT_EMERGENCY_NUMBERS = ["112", "911"]; +const TONES_GAP_DURATION = 70; + // MMI match groups const MMI_MATCH_GROUP_FULL_MMI = 1; const MMI_MATCH_GROUP_PROCEDURE = 2; @@ -112,6 +117,45 @@ serviceClass: Ci.nsIMobileConnection.ICC_SERVICE_CLASS_NONE }; +function TelephonyCallInfo(aCall) { + this.clientId = aCall.clientId; + this.callIndex = aCall.callIndex; + this.callState = aCall.state; + this.number = aCall.number; + this.numberPresentation = aCall.numberPresentation; + this.name = aCall.name; + this.namePresentation = aCall.namePresentation; + this.isOutgoing = aCall.isOutgoing; + this.isEmergency = aCall.isEmergency; + this.isConference = aCall.isConference; + this.isSwitchable = aCall.isSwitchable; + this.isMergeable = aCall.isMergeable; +} +TelephonyCallInfo.prototype = { + QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyCallInfo]), + classID: TELEPHONYCALLINFO_CID, + classInfo: XPCOMUtils.generateCI({ + classID: TELEPHONYCALLINFO_CID, + classDescription: "TelephonyCallInfo", + interfaces: [Ci.nsITelephonyCallInfo] + }), + + // nsITelephonyCallInfo + + clientId: 0, + callIndex: 0, + callState: nsITelephonyService.CALL_STATE_UNKNOWN, + number: "", + numberPresentation: nsITelephonyService.CALL_PRESENTATION_ALLOWED, + name: "", + namePresentation: nsITelephonyService.CALL_PRESENTATION_ALLOWED, + isOutgoing: true, + isEmergency: false, + isConference: false, + isSwitchable: true, + isMergeable: true +}; + function TelephonyService() { this._numClients = gRadioInterfaceLayer.numRadioInterfaces; this._listeners = []; @@ -381,12 +425,8 @@ } for (let i = 0, indexes = Object.keys(calls); i < indexes.length; ++i) { let call = calls[indexes[i]]; - aListener.enumerateCallState(call.clientId, call.callIndex, - call.state, call.number, - call.numberPresentation, call.name, - call.namePresentation, call.isOutgoing, - call.isEmergency, call.isConference, - call.isSwitchable, call.isMergeable); + let callInfo = new TelephonyCallInfo(call); + aListener.enumerateCallState(callInfo); } } aListener.enumerateCallStateComplete(); @@ -897,6 +937,36 @@ } }, + sendTones: function(aClientId, aDtmfChars, aPauseDuration, aToneDuration, + aCallback) { + let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + let tones = aDtmfChars; + let playTone = (tone) => { + this._sendToRilWorker(aClientId, "startTone", { dtmfChar: tone }, response => { + if (!response.success) { + aCallback.notifyError(response.errorMsg); + return; + } + + timer.initWithCallback(() => { + this.stopTone(); + timer.initWithCallback(() => { + if (tones.length === 1) { + aCallback.notifySuccess(); + } else { + tones = tones.substr(1); + playTone(tones[0]); + } + }, TONES_GAP_DURATION, Ci.nsITimer.TYPE_ONE_SHOT); + }, aToneDuration, Ci.nsITimer.TYPE_ONE_SHOT); + }); + }; + + timer.initWithCallback(() => { + playTone(tones[0]); + }, aPauseDuration, Ci.nsITimer.TYPE_ONE_SHOT); + }, + startTone: function(aClientId, aDtmfChar) { this._sendToRilWorker(aClientId, "startTone", { dtmfChar: aDtmfChar }); }, @@ -1066,6 +1136,16 @@ }); }, + cancelUSSD: function(aClientId, aCallback) { + this._sendToRilWorker(aClientId, "cancelUSSD", {}, response => { + if (!response.success) { + aCallback.notifyError(response.errorMsg); + } else { + aCallback.notifySuccess(); + } + }); + }, + get microphoneMuted() { return gAudioService.microphoneMuted; }, @@ -1147,18 +1227,8 @@ if (!aCall.failCause || aCall.failCause === RIL.GECKO_CALL_ERROR_NORMAL_CALL_CLEARING) { - this._notifyAllListeners("callStateChanged", [aClientId, - aCall.callIndex, - aCall.state, - aCall.number, - aCall.numberPresentation, - aCall.name, - aCall.namePresentation, - aCall.isOutgoing, - aCall.isEmergency, - aCall.isConference, - aCall.isSwitchable, - aCall.isMergeable]); + let callInfo = new TelephonyCallInfo(aCall); + this._notifyAllListeners("callStateChanged", [callInfo]); } else { this._notifyAllListeners("notifyError", [aClientId, aCall.callIndex, aCall.failCause]); @@ -1234,18 +1304,8 @@ this._cachedDialRequest = null; } - this._notifyAllListeners("callStateChanged", [aClientId, - call.callIndex, - call.state, - call.number, - call.numberPresentation, - call.name, - call.namePresentation, - call.isOutgoing, - call.isEmergency, - call.isConference, - call.isSwitchable, - call.isMergeable]); + let callInfo = new TelephonyCallInfo(call); + this._notifyAllListeners("callStateChanged", [callInfo]); }, notifyCdmaCallWaiting: function(aClientId, aCall) { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/ipc/PTelephony.ipdl thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/ipc/PTelephony.ipdl --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/ipc/PTelephony.ipdl 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/ipc/PTelephony.ipdl 2015-01-09 12:37:02.000000000 +0000 @@ -8,6 +8,8 @@ include protocol PTelephonyRequest; include TelephonyTypes; +using nsTelephonyCallInfo from "mozilla/dom/telephony/TelephonyIPCSerializer.h"; + namespace mozilla { namespace dom { namespace telephony { @@ -24,12 +26,17 @@ bool isEmergency; }; -struct USSDRequest +struct SendUSSDRequest { uint32_t clientId; nsString ussd; }; +struct CancelUSSDRequest +{ + uint32_t clientId; +}; + struct HangUpConferenceRequest { uint32_t clientId; @@ -65,17 +72,27 @@ uint32_t callIndex; }; +struct SendTonesRequest +{ + uint32_t clientId; + nsString dtmfChars; + uint32_t pauseDuration; + uint32_t toneDuration; +}; + union IPCTelephonyRequest { EnumerateCallsRequest; DialRequest; - USSDRequest; + SendUSSDRequest; + CancelUSSDRequest; HangUpConferenceRequest; AnswerCallRequest; HangUpCallRequest; RejectCallRequest; HoldCallRequest; ResumeCallRequest; + SendTonesRequest; }; sync protocol PTelephony { @@ -85,7 +102,7 @@ child: NotifyCallError(uint32_t aClientId, int32_t aCallIndex, nsString aError); - NotifyCallStateChanged(uint32_t aClientId, IPCCallStateData aData); + NotifyCallStateChanged(nsTelephonyCallInfo aInfo); NotifyCdmaCallWaiting(uint32_t aClientId, IPCCdmaWaitingCallData aData); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/ipc/PTelephonyRequest.ipdl thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/ipc/PTelephonyRequest.ipdl --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/ipc/PTelephonyRequest.ipdl 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/ipc/PTelephonyRequest.ipdl 2015-01-09 12:37:02.000000000 +0000 @@ -7,6 +7,8 @@ include protocol PTelephony; include TelephonyTypes; +using nsTelephonyCallInfo from "mozilla/dom/telephony/TelephonyIPCSerializer.h"; + namespace mozilla { namespace dom { namespace telephony { @@ -64,7 +66,7 @@ manager PTelephony; child: - NotifyEnumerateCallState(uint32_t aClientId, IPCCallStateData aData); + NotifyEnumerateCallState(nsTelephonyCallInfo aInfo); NotifyDialMMI(nsString aServiceCode); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/ipc/TelephonyChild.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/ipc/TelephonyChild.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/ipc/TelephonyChild.cpp 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/ipc/TelephonyChild.cpp 2015-01-09 12:37:02.000000000 +0000 @@ -58,23 +58,16 @@ } bool -TelephonyChild::RecvNotifyCallStateChanged(const uint32_t& aClientId, - const IPCCallStateData& aData) +TelephonyChild::RecvNotifyCallStateChanged(nsITelephonyCallInfo* const& aInfo) { + // Use dont_AddRef here because this instances has already been AddRef-ed in + // TelephonyIPCSerializer.h + nsCOMPtr info = dont_AddRef(aInfo); + MOZ_ASSERT(mService); - mService->CallStateChanged(aClientId, - aData.callIndex(), - aData.callState(), - aData.number(), - aData.numberPresentation(), - aData.name(), - aData.namePresentation(), - aData.isOutGoing(), - aData.isEmergency(), - aData.isConference(), - aData.isSwitchable(), - aData.isMergeable()); + mService->CallStateChanged(aInfo); + return true; } @@ -165,23 +158,16 @@ } bool -TelephonyRequestChild::RecvNotifyEnumerateCallState(const uint32_t& aClientId, - const IPCCallStateData& aData) +TelephonyRequestChild::RecvNotifyEnumerateCallState(nsITelephonyCallInfo* const& aInfo) { + // Use dont_AddRef here because this instances has already been AddRef-ed in + // TelephonyIPCSerializer.h + nsCOMPtr info = dont_AddRef(aInfo); + MOZ_ASSERT(mListener); - mListener->EnumerateCallState(aClientId, - aData.callIndex(), - aData.callState(), - aData.number(), - aData.numberPresentation(), - aData.name(), - aData.namePresentation(), - aData.isOutGoing(), - aData.isEmergency(), - aData.isConference(), - aData.isSwitchable(), - aData.isMergeable()); + mListener->EnumerateCallState(aInfo); + return true; } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/ipc/TelephonyChild.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/ipc/TelephonyChild.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/ipc/TelephonyChild.h 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/ipc/TelephonyChild.h 2015-01-09 12:37:02.000000000 +0000 @@ -6,9 +6,10 @@ #ifndef mozilla_dom_telephony_TelephonyChild_h #define mozilla_dom_telephony_TelephonyChild_h -#include "mozilla/dom/telephony/TelephonyCommon.h" #include "mozilla/dom/telephony/PTelephonyChild.h" #include "mozilla/dom/telephony/PTelephonyRequestChild.h" +#include "mozilla/dom/telephony/TelephonyCommon.h" +#include "nsITelephonyCallInfo.h" #include "nsITelephonyService.h" BEGIN_TELEPHONY_NAMESPACE @@ -37,8 +38,7 @@ const nsString& aError) MOZ_OVERRIDE; virtual bool - RecvNotifyCallStateChanged(const uint32_t& aClientId, - const IPCCallStateData& aData) MOZ_OVERRIDE; + RecvNotifyCallStateChanged(nsITelephonyCallInfo* const& aInfo) MOZ_OVERRIDE; virtual bool RecvNotifyCdmaCallWaiting(const uint32_t& aClientId, @@ -76,8 +76,7 @@ Recv__delete__(const IPCTelephonyResponse& aResponse) MOZ_OVERRIDE; virtual bool - RecvNotifyEnumerateCallState(const uint32_t& aClientId, - const IPCCallStateData& aData) MOZ_OVERRIDE; + RecvNotifyEnumerateCallState(nsITelephonyCallInfo* const& aInfo) MOZ_OVERRIDE; virtual bool RecvNotifyDialMMI(const nsString& aServiceCode) MOZ_OVERRIDE; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/ipc/TelephonyIPCSerializer.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/ipc/TelephonyIPCSerializer.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/ipc/TelephonyIPCSerializer.h 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/ipc/TelephonyIPCSerializer.h 2015-01-09 12:37:02.000000000 +0000 @@ -0,0 +1,132 @@ +/* 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_dom_telephony_TelephonyIPCSerializer_h +#define mozilla_dom_telephony_TelephonyIPCSerializer_h + +#include "ipc/IPCMessageUtils.h" +#include "mozilla/dom/telephony/TelephonyCallInfo.h" +#include "nsITelephonyCallInfo.h" + +using mozilla::AutoJSContext; +using mozilla::dom::telephony::TelephonyCallInfo; + +typedef nsITelephonyCallInfo* nsTelephonyCallInfo; + +namespace IPC { + +/** + * nsITelephonyCallInfo Serialize/De-serialize. + */ +template <> +struct ParamTraits +{ + typedef nsITelephonyCallInfo* paramType; + + static void Write(Message* aMsg, const paramType& aParam) { + bool isNull = !aParam; + WriteParam(aMsg, isNull); + // If it is a null object, then we are done. + if (isNull) { + return; + } + + uint32_t clientId; + uint32_t callIndex; + uint16_t callState; + nsString number; + uint16_t numberPresentation; + nsString name; + uint16_t namePresentation; + bool isOutgoing; + bool isEmergency; + bool isConference; + bool isSwitchable; + bool isMergeable; + + aParam->GetClientId(&clientId); + aParam->GetCallIndex(&callIndex); + aParam->GetCallState(&callState); + aParam->GetNumber(number); + aParam->GetNumberPresentation(&numberPresentation); + aParam->GetName(name); + aParam->GetNamePresentation(&namePresentation); + aParam->GetIsOutgoing(&isOutgoing); + aParam->GetIsEmergency(&isEmergency); + aParam->GetIsConference(&isConference); + aParam->GetIsSwitchable(&isSwitchable); + aParam->GetIsMergeable(&isMergeable); + + WriteParam(aMsg, clientId); + WriteParam(aMsg, callIndex); + WriteParam(aMsg, callState); + WriteParam(aMsg, number); + WriteParam(aMsg, numberPresentation); + WriteParam(aMsg, name); + WriteParam(aMsg, namePresentation); + WriteParam(aMsg, isOutgoing); + WriteParam(aMsg, isEmergency); + WriteParam(aMsg, isConference); + WriteParam(aMsg, isSwitchable); + WriteParam(aMsg, isMergeable); + } + + static bool Read(const Message* aMsg, void** aIter, paramType* aResult) + { + // Check if is the null pointer we have transfered. + bool isNull; + if (!ReadParam(aMsg, aIter, &isNull)) { + return false; + } + + if (isNull) { + *aResult = nullptr; + return true; + } + + uint32_t clientId; + uint32_t callIndex; + uint16_t callState; + nsString number; + uint16_t numberPresentation; + nsString name; + uint16_t namePresentation; + bool isOutgoing; + bool isEmergency; + bool isConference; + bool isSwitchable; + bool isMergeable; + + // It's not important to us where it fails, but rather if it fails + if (!(ReadParam(aMsg, aIter, &clientId) && + ReadParam(aMsg, aIter, &callIndex) && + ReadParam(aMsg, aIter, &callState) && + ReadParam(aMsg, aIter, &number) && + ReadParam(aMsg, aIter, &numberPresentation) && + ReadParam(aMsg, aIter, &name) && + ReadParam(aMsg, aIter, &namePresentation) && + ReadParam(aMsg, aIter, &isOutgoing) && + ReadParam(aMsg, aIter, &isEmergency) && + ReadParam(aMsg, aIter, &isConference) && + ReadParam(aMsg, aIter, &isSwitchable) && + ReadParam(aMsg, aIter, &isMergeable))) { + return false; + } + + nsCOMPtr info = + new TelephonyCallInfo(clientId, callIndex, callState, number, + numberPresentation, name, namePresentation, + isOutgoing, isEmergency, isConference, + isSwitchable, isMergeable); + + info.forget(aResult); + + return true; + } +}; + + +} // namespace IPC + +#endif // mozilla_dom_telephony_TelephonyIPCSerializer_h diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/ipc/TelephonyIPCService.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/ipc/TelephonyIPCService.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/ipc/TelephonyIPCService.cpp 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/ipc/TelephonyIPCService.cpp 2015-01-09 12:37:02.000000000 +0000 @@ -9,6 +9,8 @@ #include "mozilla/dom/telephony/TelephonyChild.h" #include "mozilla/Preferences.h" +#include "nsITelephonyCallInfo.h" + USING_TELEPHONY_NAMESPACE using namespace mozilla::dom; @@ -286,6 +288,15 @@ } NS_IMETHODIMP +TelephonyIPCService::SendTones(uint32_t aClientId, const nsAString& aDtmfChars, + uint32_t aPauseDuration, uint32_t aToneDuration, + nsITelephonyCallback *aCallback) +{ + return SendRequest(nullptr, aCallback, SendTonesRequest(aClientId, + nsString(aDtmfChars), aPauseDuration, aToneDuration)); +} + +NS_IMETHODIMP TelephonyIPCService::StartTone(uint32_t aClientId, const nsAString& aDtmfChar) { if (!mPTelephonyChild) { @@ -314,7 +325,14 @@ nsITelephonyCallback *aCallback) { return SendRequest(nullptr, aCallback, - USSDRequest(aClientId, nsString(aUssd))); + SendUSSDRequest(aClientId, nsString(aUssd))); +} + +NS_IMETHODIMP +TelephonyIPCService::CancelUSSD(uint32_t aClientId, + nsITelephonyCallback *aCallback) +{ + return SendRequest(nullptr, aCallback, CancelUSSDRequest(aClientId)); } NS_IMETHODIMP @@ -368,24 +386,10 @@ // nsITelephonyListener NS_IMETHODIMP -TelephonyIPCService::CallStateChanged(uint32_t aClientId, - uint32_t aCallIndex, - uint16_t aCallState, - const nsAString& aNumber, - uint16_t aNumberPresentation, - const nsAString& aName, - uint16_t aNamePresentation, - bool aIsOutgoing, - bool aIsEmergency, - bool aIsConference, - bool aIsSwitchable, - bool aIsMergeable) +TelephonyIPCService::CallStateChanged(nsITelephonyCallInfo* aInfo) { for (uint32_t i = 0; i < mListeners.Length(); i++) { - mListeners[i]->CallStateChanged(aClientId, aCallIndex, aCallState, aNumber, - aNumberPresentation, aName, aNamePresentation, - aIsOutgoing, aIsEmergency, aIsConference, - aIsSwitchable, aIsMergeable); + mListeners[i]->CallStateChanged(aInfo); } return NS_OK; } @@ -406,18 +410,7 @@ } NS_IMETHODIMP -TelephonyIPCService::EnumerateCallState(uint32_t aClientId, - uint32_t aCallIndex, - uint16_t aCallState, - const nsAString& aNumber, - uint16_t aNumberPresentation, - const nsAString& aName, - uint16_t aNamePresentation, - bool aIsOutgoing, - bool aIsEmergency, - bool aIsConference, - bool aIsSwitchable, - bool aIsMergeable) +TelephonyIPCService::EnumerateCallState(nsITelephonyCallInfo* aInfo) { MOZ_CRASH("Not a EnumerateCalls request!"); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/ipc/TelephonyParent.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/ipc/TelephonyParent.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/ipc/TelephonyParent.cpp 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/ipc/TelephonyParent.cpp 2015-01-09 12:37:02.000000000 +0000 @@ -60,12 +60,18 @@ return true; } - case IPCTelephonyRequest::TUSSDRequest: { - const USSDRequest& request = aRequest.get_USSDRequest(); + case IPCTelephonyRequest::TSendUSSDRequest: { + const SendUSSDRequest& request = aRequest.get_SendUSSDRequest(); service->SendUSSD(request.clientId(), request.ussd(), actor); return true; } + case IPCTelephonyRequest::TCancelUSSDRequest: { + const CancelUSSDRequest& request = aRequest.get_CancelUSSDRequest(); + service->CancelUSSD(request.clientId(), actor); + return true; + } + case IPCTelephonyRequest::THangUpConferenceRequest: { const HangUpConferenceRequest& request = aRequest.get_HangUpConferenceRequest(); service->HangUpConference(request.clientId(), actor); @@ -102,6 +108,16 @@ return true; } + case IPCTelephonyRequest::TSendTonesRequest: { + const SendTonesRequest& request = aRequest.get_SendTonesRequest(); + service->SendTones(request.clientId(), + request.dtmfChars(), + request.pauseDuration(), + request.toneDuration(), + actor); + return true; + } + default: MOZ_CRASH("Unknown type!"); } @@ -278,26 +294,11 @@ // nsITelephonyListener NS_IMETHODIMP -TelephonyParent::CallStateChanged(uint32_t aClientId, - uint32_t aCallIndex, - uint16_t aCallState, - const nsAString& aNumber, - uint16_t aNumberPresentation, - const nsAString& aName, - uint16_t aNamePresentation, - bool aIsOutgoing, - bool aIsEmergency, - bool aIsConference, - bool aIsSwitchable, - bool aIsMergeable) +TelephonyParent::CallStateChanged(nsITelephonyCallInfo* aInfo) { NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE); - IPCCallStateData data(aCallIndex, aCallState, nsString(aNumber), - aNumberPresentation, nsString(aName), aNamePresentation, - aIsOutgoing, aIsEmergency, aIsConference, - aIsSwitchable, aIsMergeable); - return SendNotifyCallStateChanged(aClientId, data) ? NS_OK : NS_ERROR_FAILURE; + return SendNotifyCallStateChanged(aInfo) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP @@ -316,18 +317,7 @@ } NS_IMETHODIMP -TelephonyParent::EnumerateCallState(uint32_t aClientId, - uint32_t aCallIndex, - uint16_t aCallState, - const nsAString& aNumber, - uint16_t aNumberPresentation, - const nsAString& aName, - uint16_t aNamePresentation, - bool aIsOutgoing, - bool aIsEmergency, - bool aIsConference, - bool aIsSwitchable, - bool aIsMergeable) +TelephonyParent::EnumerateCallState(nsITelephonyCallInfo* aInfo) { MOZ_CRASH("Not a EnumerateCalls request!"); } @@ -412,18 +402,7 @@ // nsITelephonyListener NS_IMETHODIMP -TelephonyRequestParent::CallStateChanged(uint32_t aClientId, - uint32_t aCallIndex, - uint16_t aCallState, - const nsAString& aNumber, - uint16_t aNumberPresentation, - const nsAString& aName, - uint16_t aNamePresentation, - bool aIsOutgoing, - bool aIsEmergency, - bool aIsConference, - bool aIsSwitchable, - bool aIsMergeable) +TelephonyRequestParent::CallStateChanged(nsITelephonyCallInfo* aInfo) { MOZ_CRASH("Not a TelephonyParent!"); } @@ -443,27 +422,11 @@ } NS_IMETHODIMP -TelephonyRequestParent::EnumerateCallState(uint32_t aClientId, - uint32_t aCallIndex, - uint16_t aCallState, - const nsAString& aNumber, - uint16_t aNumberPresentation, - const nsAString& aName, - uint16_t aNamePresentation, - bool aIsOutgoing, - bool aIsEmergency, - bool aIsConference, - bool aIsSwitchable, - bool aIsMergeable) +TelephonyRequestParent::EnumerateCallState(nsITelephonyCallInfo* aInfo) { NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE); - IPCCallStateData data(aCallIndex, aCallState, nsString(aNumber), - aNumberPresentation, nsString(aName), aNamePresentation, - aIsOutgoing, aIsEmergency, aIsConference, - aIsSwitchable, aIsMergeable); - return SendNotifyEnumerateCallState(aClientId, data) ? NS_OK - : NS_ERROR_FAILURE; + return SendNotifyEnumerateCallState(aInfo) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/ipc/TelephonyParent.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/ipc/TelephonyParent.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/ipc/TelephonyParent.h 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/ipc/TelephonyParent.h 2015-01-09 12:37:02.000000000 +0000 @@ -26,7 +26,7 @@ virtual ~TelephonyParent() {} virtual void - ActorDestroy(ActorDestroyReason why); + ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; virtual bool RecvPTelephonyRequestConstructor(PTelephonyRequestParent* aActor, const IPCTelephonyRequest& aRequest) MOZ_OVERRIDE; @@ -98,7 +98,7 @@ virtual ~TelephonyRequestParent() {} virtual void - ActorDestroy(ActorDestroyReason why); + ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; nsresult SendResponse(const IPCTelephonyResponse& aResponse); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/ipc/TelephonyTypes.ipdlh thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/ipc/TelephonyTypes.ipdlh --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/ipc/TelephonyTypes.ipdlh 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/ipc/TelephonyTypes.ipdlh 2015-01-09 12:37:02.000000000 +0000 @@ -11,21 +11,6 @@ namespace dom { namespace telephony { -struct IPCCallStateData -{ - uint32_t callIndex; - uint16_t callState; - nsString number; - uint16_t numberPresentation; - nsString name; - uint16_t namePresentation; - bool isOutGoing; - bool isEmergency; - bool isConference; - bool isSwitchable; - bool isMergeable; -}; - struct IPCCdmaWaitingCallData { nsString number; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/moz.build thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/moz.build --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/moz.build 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/moz.build 2015-01-09 12:37:02.000000000 +0000 @@ -5,6 +5,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. XPIDL_SOURCES += [ + 'nsITelephonyCallInfo.idl', 'nsITelephonyService.idl', ] @@ -22,8 +23,10 @@ EXPORTS.mozilla.dom.telephony += [ 'ipc/TelephonyChild.h', + 'ipc/TelephonyIPCSerializer.h', 'ipc/TelephonyParent.h', 'TelephonyCallback.h', + 'TelephonyCallInfo.h', 'TelephonyCommon.h', 'TelephonyDialCallback.h', ] @@ -39,6 +42,7 @@ 'TelephonyCallback.cpp', 'TelephonyCallGroup.cpp', 'TelephonyCallId.cpp', + 'TelephonyCallInfo.cpp', 'TelephonyDialCallback.cpp', 'USSDSession.cpp', ] diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/nsIGonkTelephonyService.idl thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/nsIGonkTelephonyService.idl --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/nsIGonkTelephonyService.idl 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/nsIGonkTelephonyService.idl 2015-01-09 12:37:02.000000000 +0000 @@ -10,7 +10,7 @@ "@mozilla.org/telephony/gonktelephonyservice;1" %} -[scriptable, uuid(aec05f05-0ca5-470b-8230-cdee0209eafd)] +[scriptable, uuid(a334105b-a329-49b0-9aa8-0900dec71eb8)] interface nsIGonkTelephonyService : nsITelephonyService { void notifyAudioStateChanged(in unsigned long clientId, in short state); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/nsITelephonyCallInfo.idl thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/nsITelephonyCallInfo.idl --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/nsITelephonyCallInfo.idl 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/nsITelephonyCallInfo.idl 2015-01-09 12:37:02.000000000 +0000 @@ -0,0 +1,73 @@ +/* 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 "nsISupports.idl" + +[scriptable, uuid(3ea2d155-8ea2-42be-85d7-bd8ede8afc40)] +interface nsITelephonyCallInfo : nsISupports +{ + /** + * Indicate the RIL client, 0 ~ (number of client - 1). + */ + readonly attribute unsigned long clientId; + + /** + * Call identifier assigned by the RIL. + */ + readonly attribute unsigned long callIndex; + + /** + * One of the nsITelephonyService::CALL_STATE_* values. + */ + readonly attribute unsigned short callState; + + /** + * Number of the other party. + */ + readonly attribute DOMString number; + + /** + * Presentation of the call number. + * One of the nsITelephonyService::CALL_PRESENTATION_* values. + */ + readonly attribute unsigned short numberPresentation; + + /** + * Name of the other party. + */ + readonly attribute DOMString name; + + /** + * Presentation of the call name. + * One of the nsITelephonyService::CALL_PRESENTATION_* values. + */ + readonly attribute unsigned short namePresentation; + + /** + * Indicates whether this call is outgoing or incoming. + */ + readonly attribute boolean isOutgoing; + + /** + * Indicates whether this call is an emergency call. + */ + readonly attribute boolean isEmergency; + + /** + * Indicates whether this call is a conference call. + */ + readonly attribute boolean isConference; + + /** + * Indicates whether this call can be switched between states of + * nsITelephonyService::CALL_STATE_CONNECTED and + * nsITelephonyService::CALL_STATE_HELD. + */ + readonly attribute boolean isSwitchable; + + /** + * Indicates whether this call be be added into a conference. + */ + readonly attribute boolean isMergeable; +}; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/nsITelephonyService.idl thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/nsITelephonyService.idl --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/nsITelephonyService.idl 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/nsITelephonyService.idl 2015-01-09 12:37:02.000000000 +0000 @@ -5,54 +5,28 @@ #include "nsISupports.idl" interface nsIMobileCallForwardingOptions; +interface nsITelephonyCallInfo; -[scriptable, uuid(464d4cf8-454a-4cdb-9329-bfe7ede97103)] +[scriptable, uuid(3cdc0b98-0c5f-489d-9190-083d137f40da)] interface nsITelephonyListener : nsISupports { /** + * Called when enumeration asked by nsITelephonyService::enumerateCalls + * is completed. + */ + void enumerateCallStateComplete(); + + /** + * Called when nsITelephonyService is asked to enumerate the current + * telephony call state (nsITelephonyService::enumerateCalls). This is + * called once per call that is currently managed by the RIL. + */ + void enumerateCallState(in nsITelephonyCallInfo info); + + /** * Notified when a telephony call changes state. - * - * @param clientId - Indicate the RIL client, 0 ~ (number of client - 1). - * @param callIndex - * Call identifier assigned by the RIL. - * @param callState - * One of the nsITelephonyService::CALL_STATE_* values. - * @param number - * Number of the other party. - * @param numberPresentation - * Presentation of the call number. - * One of the nsITelephonyProvider::CALL_PRESENTATION_* values. - * @param name - * Name of the other party. - * @param namePresentation - * Presentation of the call name. - * One of the nsITelephonyProvider::CALL_PRESENTATION_* values. - * @param isOutgoing - * Indicates whether this call is outgoing or incoming. - * @param isEmergency - * Indicates whether this call is an emergency call. - * @param isConference - * Indicates whether this call is a conference call. - * @param isSwitchable - * Indicates whether this call can be switched between states of - * nsITelephonyService::CALL_STATE_CONNECTED and - * nsITelephonyService::CALL_STATE_HELD. - * @param isMergeable - * Indicates whether this call be be added into a conference. - */ - void callStateChanged(in unsigned long clientId, - in unsigned long callIndex, - in unsigned short callState, - in AString number, - in unsigned short numberPresentation, - in AString name, - in unsigned short namePresentation, - in boolean isOutgoing, - in boolean isEmergency, - in boolean isConference, - in boolean isSwitchable, - in boolean isMergeable); + */ + void callStateChanged(in nsITelephonyCallInfo info); /** * Called when participants of a conference call have been updated, and the @@ -66,57 +40,6 @@ void conferenceCallStateChanged(in unsigned short callState); /** - * Called when enumeration asked by nsITelephonyService::enumerateCalls - * is completed. - */ - void enumerateCallStateComplete(); - - /** - * Called when nsITelephonyService is asked to enumerate the current - * telephony call state (nsITelephonyService::enumerateCalls). This is - * called once per call that is currently managed by the RIL. - * - * @param clientId - Indicate the RIL client, 0 ~ (number of client - 1). - * @param callIndex - * Call identifier assigned by the RIL. - * @param callState - * One of the nsITelephonyService::CALL_STATE_* values. - * @param number - * Number of the other party. - * @param numberPresentation - * Presentation of the call number. - * One of the nsITelephonyProvider::CALL_PRESENTATION_* values. - * @param name - * Name of the other party. - * @param namePresentation - * Presentation of the call name. - * One of the nsITelephonyProvider::CALL_PRESENTATION_* values. - * @param isOutgoing - * Indicates whether this call is outgoing or incoming. - * @param isConference - * Indicates whether this call is a conference call. - * @param isSwitchable - * Indicates whether this call can be switched between states of - * nsITelephonyService::CALL_STATE_CONNECTED and - * nsITelephonyService::CALL_STATE_HELD. - * @param isMergeable - * Indicates whether this call be be added into a conference. - */ - void enumerateCallState(in unsigned long clientId, - in unsigned long callIndex, - in unsigned short callState, - in AString number, - in unsigned short numberPresentation, - in AString name, - in unsigned short namePresentation, - in boolean isOutgoing, - in boolean isEmergency, - in boolean isConference, - in boolean isSwitchable, - in boolean isMergeable); - - /** * Notify when RIL receives supplementary service notification. * * @param clientId @@ -251,7 +174,7 @@ * XPCOM component (in the content process) that provides the telephony * information. */ -[scriptable, uuid(fd797bcc-54e2-4e4a-9ec7-3b72862d0d78)] +[scriptable, uuid(a91fa6be-0acc-4d36-99f1-3e3a88e83ae9)] interface nsITelephonyService : nsISupports { const unsigned short CALL_STATE_UNKNOWN = 0; @@ -296,6 +219,10 @@ void dial(in unsigned long clientId, in DOMString number, in boolean isEmergency, in nsITelephonyDialCallback callback); + void sendTones(in unsigned long clientId, in DOMString dtmfChars, + in unsigned long pauseDuration, in unsigned long toneDuration, + in nsITelephonyCallback callback); + void startTone(in unsigned long clientId, in DOMString dtmfChar); void stopTone(in unsigned long clientId); @@ -332,6 +259,14 @@ void sendUSSD(in unsigned long clientId, in DOMString ussd, in nsITelephonyCallback callback); + /** + * Cancel an existing USSD session. + * + * If successful, callback.notifySuccess() will be called. + * Otherwise, callback.notifyError() will be called. + */ + void cancelUSSD(in unsigned long cliendId, in nsITelephonyCallback callback); + attribute bool microphoneMuted; attribute bool speakerEnabled; }; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/TelephonyCallInfo.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/TelephonyCallInfo.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/TelephonyCallInfo.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/TelephonyCallInfo.cpp 2015-01-09 12:37:02.000000000 +0000 @@ -0,0 +1,126 @@ +/* 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 "mozilla/dom/telephony/TelephonyCallInfo.h" + +namespace mozilla { +namespace dom { +namespace telephony { + +NS_IMPL_ISUPPORTS(TelephonyCallInfo, nsITelephonyCallInfo) + +TelephonyCallInfo::TelephonyCallInfo(uint32_t aClientId, + uint32_t aCallIndex, + uint16_t aCallState, + const nsAString& aNumber, + uint16_t aNumberPresentation, + const nsAString& aName, + uint16_t aNamePresentation, + bool aIsOutgoing, + bool aIsEmergency, + bool aIsConference, + bool aIsSwitchable, + bool aIsMergeable) + : mClientId(aClientId), + mCallIndex(aCallIndex), + mCallState(aCallState), + mNumber(aNumber), + mNumberPresentation(aNumberPresentation), + mName(aName), + mNamePresentation(aNamePresentation), + mIsOutgoing(aIsOutgoing), + mIsEmergency(aIsEmergency), + mIsConference(aIsConference), + mIsSwitchable(aIsSwitchable), + mIsMergeable(aIsMergeable) +{ +} + +NS_IMETHODIMP +TelephonyCallInfo::GetClientId(uint32_t* aClientId) +{ + *aClientId = mClientId; + return NS_OK; +} + +NS_IMETHODIMP +TelephonyCallInfo::GetCallIndex(uint32_t* aCallIndex) +{ + *aCallIndex = mCallIndex; + return NS_OK; +} + +NS_IMETHODIMP +TelephonyCallInfo::GetCallState(uint16_t* aCallState) +{ + *aCallState = mCallState; + return NS_OK; +} + +NS_IMETHODIMP +TelephonyCallInfo::GetNumber(nsAString& aNumber) +{ + aNumber = mNumber; + return NS_OK; +} + +NS_IMETHODIMP +TelephonyCallInfo::GetNumberPresentation(uint16_t* aNumberPresentation) +{ + *aNumberPresentation = mNumberPresentation; + return NS_OK; +} + +NS_IMETHODIMP +TelephonyCallInfo::GetName(nsAString& aName) +{ + aName = mName; + return NS_OK; +} + +NS_IMETHODIMP +TelephonyCallInfo::GetNamePresentation(uint16_t* aNamePresentation) +{ + *aNamePresentation = mNamePresentation; + return NS_OK; +} + +NS_IMETHODIMP +TelephonyCallInfo::GetIsOutgoing(bool* aIsOutgoing) +{ + *aIsOutgoing = mIsOutgoing; + return NS_OK; +} + +NS_IMETHODIMP +TelephonyCallInfo::GetIsEmergency(bool* aIsEmergency) +{ + *aIsEmergency = mIsEmergency; + return NS_OK; +} + +NS_IMETHODIMP +TelephonyCallInfo::GetIsConference(bool* aIsConference) +{ + *aIsConference = mIsConference; + return NS_OK; +} + +NS_IMETHODIMP +TelephonyCallInfo::GetIsSwitchable(bool* aIsSwitchable) +{ + *aIsSwitchable = mIsSwitchable; + return NS_OK; +} + +NS_IMETHODIMP +TelephonyCallInfo::GetIsMergeable(bool* aIsMergeable) +{ + *aIsMergeable = mIsMergeable; + return NS_OK; +} + +} // namespace telephony +} // namespace dom +} // namespace mozilla diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/TelephonyCallInfo.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/TelephonyCallInfo.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/TelephonyCallInfo.h 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/TelephonyCallInfo.h 2015-01-09 12:37:02.000000000 +0000 @@ -0,0 +1,53 @@ +/* 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_dom_TelephonyCallInfo_h +#define mozilla_dom_TelephonyCallInfo_h + +#include "nsITelephonyCallInfo.h" +#include "nsString.h" +#include "mozilla/Attributes.h" + +namespace mozilla { +namespace dom { +namespace telephony { + +class TelephonyCallInfo MOZ_FINAL : public nsITelephonyCallInfo +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSITELEPHONYCALLINFO + + TelephonyCallInfo(uint32_t aClientId, uint32_t aCallIndex, + uint16_t aCallState, const nsAString& aNumber, + uint16_t aNumberPresentation, const nsAString& aName, + uint16_t aNamePresentation, bool aIsOutgoing, + bool aIsEmergency, bool aIsConference, + bool aIsSwitchable, bool aIsMergeable); + +private: + // Don't try to use the default constructor. + TelephonyCallInfo() {} + + ~TelephonyCallInfo() {} + + uint32_t mClientId; + uint32_t mCallIndex; + uint16_t mCallState; + nsString mNumber; + uint16_t mNumberPresentation; + nsString mName; + uint16_t mNamePresentation; + bool mIsOutgoing; + bool mIsEmergency; + bool mIsConference; + bool mIsSwitchable; + bool mIsMergeable; +}; + +} // namespace telephony +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_TelephonyCallInfo_h diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/Telephony.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/Telephony.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/Telephony.cpp 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/Telephony.cpp 2015-01-09 12:37:02.000000000 +0000 @@ -236,6 +236,22 @@ } already_AddRefed +Telephony::CreateCallId(nsITelephonyCallInfo *aInfo) +{ + nsAutoString number; + nsAutoString name; + uint16_t numberPresentation; + uint16_t namePresentation; + + aInfo->GetNumber(number); + aInfo->GetName(name); + aInfo->GetNumberPresentation(&numberPresentation); + aInfo->GetNamePresentation(&namePresentation); + + return CreateCallId(number, numberPresentation, name, namePresentation); +} + +already_AddRefed Telephony::CreateCallId(const nsAString& aNumber, uint16_t aNumberPresentation, const nsAString& aName, uint16_t aNamePresentation) { @@ -310,6 +326,81 @@ return call.forget(); } +nsresult +Telephony::HandleCallInfo(nsITelephonyCallInfo* aInfo) +{ + uint32_t serviceId; + uint32_t callIndex; + uint16_t callState; + bool isEmergency; + bool isConference; + bool isSwitchable; + bool isMergeable; + + aInfo->GetClientId(&serviceId); + aInfo->GetCallIndex(&callIndex); + aInfo->GetCallState(&callState); + aInfo->GetIsEmergency(&isEmergency); + aInfo->GetIsConference(&isConference); + aInfo->GetIsSwitchable(&isSwitchable); + aInfo->GetIsMergeable(&isMergeable); + + nsRefPtr call = GetCallFromEverywhere(serviceId, callIndex); + + if (!call) { + nsRefPtr id = CreateCallId(aInfo); + call = CreateCall(id, serviceId, callIndex, callState, isEmergency, + isConference, isSwitchable, isMergeable); + + if (call && callState == nsITelephonyService::CALL_STATE_INCOMING) { + nsresult rv = DispatchCallEvent(NS_LITERAL_STRING("incoming"), call); + NS_ENSURE_SUCCESS(rv, rv); + } + } else { + call->UpdateEmergency(isEmergency); + call->UpdateSwitchable(isSwitchable); + call->UpdateMergeable(isMergeable); + + nsAutoString number; + aInfo->GetNumber(number); + nsRefPtr id = call->Id(); + id->UpdateNumber(number); + + // State changed. + if (call->CallState() != callState) { + if (callState == nsITelephonyService::CALL_STATE_DISCONNECTED) { + call->ChangeStateInternal(callState, true); + return NS_OK; + } + + // We don't fire the statechange event on a call in conference here. + // Instead, the event will be fired later in + // TelephonyCallGroup::ChangeState(). Thus the sequence of firing the + // statechange events is guaranteed: first on TelephonyCallGroup then on + // individual TelephonyCall objects. + bool fireEvent = !isConference; + call->ChangeStateInternal(callState, fireEvent); + } + + // Group changed. + nsRefPtr group = call->GetGroup(); + + if (!group && isConference) { + // Add to conference. + NS_ASSERTION(mCalls.Contains(call), "Should in mCalls"); + mGroup->AddCall(call); + RemoveCall(call); + } else if (group && !isConference) { + // Remove from conference. + NS_ASSERTION(mGroup->CallsArray().Contains(call), "Should in mGroup"); + mGroup->RemoveCall(call); + AddCall(call); + } + } + + return NS_OK; +} + NS_IMPL_CYCLE_COLLECTION_CLASS(Telephony) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(Telephony, @@ -360,6 +451,45 @@ return promise.forget(); } +already_AddRefed +Telephony::SendTones(const nsAString& aDTMFChars, + uint32_t aPauseDuration, + uint32_t aToneDuration, + const Optional& aServiceId, + ErrorResult& aRv) +{ + uint32_t serviceId = ProvidedOrDefaultServiceId(aServiceId); + + nsCOMPtr global = do_QueryInterface(GetOwner()); + if (!global) { + return nullptr; + } + + nsRefPtr promise = Promise::Create(global, aRv); + if (aRv.Failed()) { + return nullptr; + } + + if (aDTMFChars.IsEmpty()) { + NS_WARNING("Empty tone string will be ignored"); + promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR); + return promise.forget(); + } + + if (!IsValidServiceId(serviceId)) { + aRv.Throw(NS_ERROR_INVALID_ARG); + promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR); + return promise.forget(); + } + + nsCOMPtr callback = + new TelephonyCallback(promise); + + aRv = mService->SendTones(serviceId, aDTMFChars, aPauseDuration, + aToneDuration, callback); + return promise.forget(); +} + void Telephony::StartTone(const nsAString& aDTMFChar, const Optional& aServiceId, @@ -469,67 +599,15 @@ // nsITelephonyListener NS_IMETHODIMP -Telephony::CallStateChanged(uint32_t aServiceId, uint32_t aCallIndex, - uint16_t aCallState, const nsAString& aNumber, - uint16_t aNumberPresentation, const nsAString& aName, - uint16_t aNamePresentation, bool aIsOutgoing, - bool aIsEmergency, bool aIsConference, - bool aIsSwitchable, bool aIsMergeable) -{ - nsRefPtr modifiedCall - = GetCallFromEverywhere(aServiceId, aCallIndex); - - if (modifiedCall) { - modifiedCall->UpdateEmergency(aIsEmergency); - modifiedCall->UpdateSwitchable(aIsSwitchable); - modifiedCall->UpdateMergeable(aIsMergeable); - nsRefPtr id = modifiedCall->Id(); - id->UpdateNumber(aNumber); - - if (modifiedCall->CallState() != aCallState) { - if (aCallState == nsITelephonyService::CALL_STATE_DISCONNECTED) { - modifiedCall->ChangeStateInternal(aCallState, true); - return NS_OK; - } - - // We don't fire the statechange event on a call in conference here. - // Instead, the event will be fired later in - // TelephonyCallGroup::ChangeState(). Thus the sequence of firing the - // statechange events is guaranteed: first on TelephonyCallGroup then on - // individual TelephonyCall objects. - bool fireEvent = !aIsConference; - modifiedCall->ChangeStateInternal(aCallState, fireEvent); - } - - nsRefPtr group = modifiedCall->GetGroup(); - - if (!group && aIsConference) { - // Add to conference. - NS_ASSERTION(mCalls.Contains(modifiedCall), "Should in mCalls"); - mGroup->AddCall(modifiedCall); - RemoveCall(modifiedCall); - } else if (group && !aIsConference) { - // Remove from conference. - NS_ASSERTION(mGroup->CallsArray().Contains(modifiedCall), "Should in mGroup"); - mGroup->RemoveCall(modifiedCall); - AddCall(modifiedCall); - } - - return NS_OK; - } - - nsRefPtr id = CreateCallId(aNumber, aNumberPresentation, - aName, aNamePresentation); - nsRefPtr call = - CreateCall(id, aServiceId, aCallIndex, aCallState, - aIsEmergency, aIsConference, aIsSwitchable, aIsMergeable); - - if (call && aCallState == nsITelephonyService::CALL_STATE_INCOMING) { - nsresult rv = DispatchCallEvent(NS_LITERAL_STRING("incoming"), call); - NS_ENSURE_SUCCESS(rv, rv); - } +Telephony::CallStateChanged(nsITelephonyCallInfo* aInfo) +{ + return HandleCallInfo(aInfo); +} - return NS_OK; +NS_IMETHODIMP +Telephony::EnumerateCallState(nsITelephonyCallInfo* aInfo) +{ + return HandleCallInfo(aInfo); } NS_IMETHODIMP @@ -567,33 +645,6 @@ return NS_OK; } -NS_IMETHODIMP -Telephony::EnumerateCallState(uint32_t aServiceId, uint32_t aCallIndex, - uint16_t aCallState, const nsAString& aNumber, - uint16_t aNumberPresentation, const nsAString& aName, - uint16_t aNamePresentation, bool aIsOutgoing, - bool aIsEmergency, bool aIsConference, - bool aIsSwitchable, bool aIsMergeable) -{ - // We request calls enumeration in constructor, and the asynchronous result - // will be sent back through the callback function EnumerateCallState(). - // However, it is likely to have call state changes, i.e. CallStateChanged() - // being called, before the enumeration result comes back. We'd make sure - // we don't somehow add duplicates due to the race condition. - nsRefPtr call = GetCallFromEverywhere(aServiceId, aCallIndex); - if (call) { - return NS_OK; - } - - // Didn't know anything about this call before now. - nsRefPtr id = CreateCallId(aNumber, aNumberPresentation, - aName, aNamePresentation); - call = CreateCall(id, aServiceId, aCallIndex, aCallState, - aIsEmergency, aIsConference, aIsSwitchable, aIsMergeable); - - return NS_OK; -} - NS_IMETHODIMP Telephony::SupplementaryServiceNotification(uint32_t aServiceId, int32_t aCallIndex, diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/Telephony.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/Telephony.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/Telephony.h 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/Telephony.h 2015-01-09 12:37:02.000000000 +0000 @@ -11,6 +11,7 @@ #include "mozilla/dom/Promise.h" #include "mozilla/dom/telephony/TelephonyCommon.h" +#include "nsITelephonyCallInfo.h" #include "nsITelephonyService.h" // Need to include TelephonyCall.h because we have inline methods that @@ -79,6 +80,13 @@ DialEmergency(const nsAString& aNumber, const Optional& aServiceId, ErrorResult& aRv); + already_AddRefed + SendTones(const nsAString& aDTMFChars, + uint32_t aPauseDuration, + uint32_t aToneDuration, + const Optional& aServiceId, + ErrorResult& aRv); + void StartTone(const nsAString& aDTMFChar, const Optional& aServiceId, ErrorResult& aRv); @@ -176,6 +184,9 @@ ErrorResult& aRv); already_AddRefed + CreateCallId(nsITelephonyCallInfo *aInfo); + + already_AddRefed CreateCallId(const nsAString& aNumber, uint16_t aNumberPresentation = nsITelephonyService::CALL_PRESENTATION_ALLOWED, const nsAString& aName = EmptyString(), @@ -201,6 +212,9 @@ already_AddRefed GetCallFromEverywhere(uint32_t aServiceId, uint32_t aCallIndex); + + nsresult + HandleCallInfo(nsITelephonyCallInfo* aInfo); }; } // namespace dom diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/USSDSession.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/USSDSession.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/USSDSession.cpp 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/USSDSession.cpp 2015-01-09 12:37:02.000000000 +0000 @@ -45,6 +45,28 @@ return USSDSessionBinding::Wrap(aCx, this); } +already_AddRefed +USSDSession::CreatePromise(ErrorResult& aRv) +{ + if (!mService) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + nsCOMPtr global = do_QueryInterface(mWindow); + if (!global) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + nsRefPtr promise = Promise::Create(global, aRv); + if (aRv.Failed()) { + return nullptr; + } + + return promise.forget(); +} + // WebIDL already_AddRefed @@ -71,24 +93,32 @@ already_AddRefed USSDSession::Send(const nsAString& aUssd, ErrorResult& aRv) { - if (!mService) { - aRv.Throw(NS_ERROR_FAILURE); + nsRefPtr promise = CreatePromise(aRv); + if (!promise) { return nullptr; } - nsCOMPtr global = do_QueryInterface(mWindow); - if (!global) { - return nullptr; + nsCOMPtr callback = new TelephonyCallback(promise); + + nsresult rv = mService->SendUSSD(mServiceId, aUssd, callback); + if (NS_FAILED(rv)) { + promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR); } - nsRefPtr promise = Promise::Create(global, aRv); - if (aRv.Failed()) { + return promise.forget(); +} + +already_AddRefed +USSDSession::Cancel(ErrorResult& aRv) +{ + nsRefPtr promise = CreatePromise(aRv); + if (!promise) { return nullptr; } nsCOMPtr callback = new TelephonyCallback(promise); - nsresult rv = mService->SendUSSD(mServiceId, aUssd, callback); + nsresult rv = mService->CancelUSSD(mServiceId, callback); if (NS_FAILED(rv)) { promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/USSDSession.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/USSDSession.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/telephony/USSDSession.h 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/telephony/USSDSession.h 2015-01-09 12:37:02.000000000 +0000 @@ -47,9 +47,15 @@ already_AddRefed Send(const nsAString& aUssd, ErrorResult& aRv); + already_AddRefed + Cancel(ErrorResult& aRv); + private: ~USSDSession(); + already_AddRefed + CreatePromise(ErrorResult& aRv); + nsCOMPtr mWindow; nsCOMPtr mService; uint32_t mServiceId; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/tests/mochitest/general/test_interfaces.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/tests/mochitest/general/test_interfaces.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/tests/mochitest/general/test_interfaces.html 2015-01-07 22:15:31.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/tests/mochitest/general/test_interfaces.html 2015-01-09 12:37:07.000000000 +0000 @@ -364,8 +364,6 @@ // IMPORTANT: Do not change this list without review from a DOM peer! "DOMMatrixReadOnly", // IMPORTANT: Do not change this list without review from a DOM peer! - {name: "DOMMMIError", b2g: true, pref: "dom.mobileconnection.enabled"}, -// IMPORTANT: Do not change this list without review from a DOM peer! {name: "DOMMobileMessageError", b2g: true, pref: "dom.sms.enabled"}, // IMPORTANT: Do not change this list without review from a DOM peer! "DOMParser", diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/time/TimeManager.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/time/TimeManager.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/time/TimeManager.h 2015-01-07 22:15:31.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/time/TimeManager.h 2015-01-09 12:37:07.000000000 +0000 @@ -42,7 +42,7 @@ { return mWindow; } - JSObject* WrapObject(JSContext* aCx); + virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE; void Set(Date& aDate); void Set(double aTime); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/tv/FakeTVService.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/tv/FakeTVService.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/tv/FakeTVService.cpp 2015-01-07 22:15:31.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/tv/FakeTVService.cpp 2015-01-09 12:37:07.000000000 +0000 @@ -196,7 +196,7 @@ {} NS_IMETHODIMP - Notify(nsITimer* aTimer) + Notify(nsITimer* aTimer) MOZ_OVERRIDE { // Notify mock EIT broadcasting. nsITVProgramData** programDataList = @@ -242,7 +242,7 @@ {} NS_IMETHODIMP - Notify(nsITimer* aTimer) + Notify(nsITimer* aTimer) MOZ_OVERRIDE { return mSourceListener->NotifyChannelScanComplete(mTunerId, mSourceType); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/Animatable.webidl thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/Animatable.webidl --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/Animatable.webidl 2015-01-07 22:15:31.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/Animatable.webidl 2015-01-09 12:37:07.000000000 +0000 @@ -12,6 +12,6 @@ [NoInterfaceObject] interface Animatable { - [Pref="dom.animations-api.core.enabled"] + [Func="nsDocument::IsWebAnimationsEnabled"] sequence getAnimationPlayers(); }; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/AnimationEffect.webidl thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/AnimationEffect.webidl --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/AnimationEffect.webidl 2015-01-07 22:15:31.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/AnimationEffect.webidl 2015-01-09 12:37:07.000000000 +0000 @@ -10,7 +10,7 @@ * liability, trademark and document use rules apply. */ -[Pref="dom.animations-api.core.enabled"] +[Func="nsDocument::IsWebAnimationsEnabled"] interface AnimationEffect { readonly attribute DOMString name; }; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/AnimationPlayer.webidl thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/AnimationPlayer.webidl --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/AnimationPlayer.webidl 2015-01-07 22:15:31.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/AnimationPlayer.webidl 2015-01-09 12:37:07.000000000 +0000 @@ -12,7 +12,7 @@ enum AnimationPlayState { "idle", "pending", "running", "paused", "finished" }; -[Pref="dom.animations-api.core.enabled"] +[Func="nsDocument::IsWebAnimationsEnabled"] interface AnimationPlayer { // Bug 1049975 // attribute AnimationNode? source; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/AnimationTimeline.webidl thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/AnimationTimeline.webidl --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/AnimationTimeline.webidl 2015-01-07 22:15:31.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/AnimationTimeline.webidl 2015-01-09 12:37:07.000000000 +0000 @@ -10,7 +10,7 @@ * liability, trademark and document use rules apply. */ -[Pref="dom.animations-api.core.enabled"] +[Func="nsDocument::IsWebAnimationsEnabled"] interface AnimationTimeline { [BinaryName="currentTimeAsDouble"] readonly attribute double? currentTime; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/Animation.webidl thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/Animation.webidl --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/Animation.webidl 2015-01-07 22:15:31.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/Animation.webidl 2015-01-09 12:37:07.000000000 +0000 @@ -10,7 +10,7 @@ * liability, trademark and document use rules apply. */ -[Pref="dom.animations-api.core.enabled"] +[Func="nsDocument::IsWebAnimationsEnabled"] interface Animation { // FIXME: |effect| should have type (AnimationEffect or EffectCallback)? // but we haven't implemented EffectCallback yet. diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/Document.webidl thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/Document.webidl --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/Document.webidl 2015-01-07 22:15:31.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/Document.webidl 2015-01-09 12:37:07.000000000 +0000 @@ -287,7 +287,7 @@ // http://dev.w3.org/fxtf/web-animations/#extensions-to-the-document-interface partial interface Document { - [Pref="dom.animations-api.core.enabled"] + [Func="nsDocument::IsWebAnimationsEnabled"] readonly attribute AnimationTimeline timeline; }; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/DOMMMIError.webidl thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/DOMMMIError.webidl --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/DOMMMIError.webidl 2015-01-07 22:15:31.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/DOMMMIError.webidl 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. - */ - -[Pref="dom.mobileconnection.enabled"] -interface DOMMMIError : DOMError { - [Constant] - readonly attribute DOMString serviceCode; - - [Constant] - readonly attribute short? additionalInformation; -}; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/HTMLVideoElement.webidl thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/HTMLVideoElement.webidl --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/HTMLVideoElement.webidl 2015-01-07 22:15:31.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/HTMLVideoElement.webidl 2015-01-09 12:37:08.000000000 +0000 @@ -48,6 +48,6 @@ // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#idl-def-HTMLVideoElement partial interface HTMLVideoElement { - [Pref="media.mediasource.enabled", NewObject] + [Func="mozilla::dom::MediaSource::Enabled", NewObject] VideoPlaybackQuality getVideoPlaybackQuality(); }; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/MediaSource.webidl thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/MediaSource.webidl --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/MediaSource.webidl 2015-01-07 22:15:31.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/MediaSource.webidl 2015-01-09 12:37:08.000000000 +0000 @@ -21,7 +21,7 @@ "decode" }; -[Constructor, Pref="media.mediasource.enabled"] +[Constructor, Func="mozilla::dom::MediaSource::Enabled"] interface MediaSource : EventTarget { readonly attribute SourceBufferList sourceBuffers; readonly attribute SourceBufferList activeSourceBuffers; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/moz.build thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/moz.build --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/moz.build 2015-01-07 22:15:31.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/moz.build 2015-01-09 12:37:08.000000000 +0000 @@ -106,7 +106,6 @@ 'DOMException.webidl', 'DOMImplementation.webidl', 'DOMMatrix.webidl', - 'DOMMMIError.webidl', 'DOMMobileMessageError.webidl', 'DOMParser.webidl', 'DOMPoint.webidl', diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/MozIcc.webidl thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/MozIcc.webidl --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/MozIcc.webidl 2015-01-07 22:15:31.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/MozIcc.webidl 2015-01-09 12:37:08.000000000 +0000 @@ -57,19 +57,23 @@ "puk", "puk2", "nck", // Network depersonalization -- network control key (NCK). + "nsck", // Network subset depersonalization -- network subset control key (NSCK). "nck1", // Network type 1 depersonalization -- network type 1 control key (NCK1). "nck2", // Network type 2 depersonalization -- network type 2 control key (NCK2). "hnck", // HRPD network depersonalization -- HRPD network control key (HNCK). "cck", // Corporate depersonalization -- corporate control key (CCK). "spck", // Service provider depersonalization -- service provider control key (SPCK). + "pck", // SIM depersonalization -- personalization control key (PCK). "rcck", // RUIM corporate depersonalization -- RUIM corporate control key (RCCK). "rspck", // RUIM service provider depersonalization -- RUIM service provider control key (RSPCK). "nckPuk", // Network PUK depersonalization -- network control key (NCK). + "nsckPuk", // Network subset PUK depersonalization -- network subset control key (NSCK). "nck1Puk", // Network type 1 PUK depersonalization -- network type 1 control key (NCK1). "nck2Puk", // Network type 2 PUK depersonalization -- Network type 2 control key (NCK2). "hnckPuk", // HRPD network PUK depersonalization -- HRPD network control key (HNCK). "cckPuk", // Corporate PUK depersonalization -- corporate control key (CCK). "spckPuk", // Service provider PUK depersonalization -- service provider control key (SPCK). + "pckPuk", // SIM PUK depersonalization -- personalization control key (PCK). "rcckPuk", // RUIM corporate PUK depersonalization -- RUIM corporate control key (RCCK). "rspckPuk", // RUIM service provider PUK depersonalization -- service provider control key (SPCK). "fdn" @@ -89,17 +93,22 @@ "gid" }; +enum IccService +{ + "fdn" +}; + dictionary IccUnlockCardLockOptions { required IccLockType lockType; DOMString? pin = null; // Necessary for lock types: "pin", "pin2", "nck", - // "nck1", "nck2", "hnck", "cck", "spck", "rcck", - // "rspck". + // "nsck", "nck1", "nck2", "hnck", "cck", "spck", + // "pck", "rcck", "rspck". DOMString? puk = null; // Necessary for lock types: "puk", "puk2", "nckPuk", - // "nck1Puk", "nck2Puk", "hnckPuk", "cckPuk", - // "spckPuk", "rcckPuk", "rspckPuk". + // "nsckPuk", "nck1Puk", "nck2Puk", "hnckPuk", "cckPuk", + // "spckPuk", "pckPuk", "rcckPuk", "rspckPuk". DOMString? newPin = null; // Necessary for lock types: "puk", "puk2". }; @@ -331,4 +340,17 @@ */ [Throws] DOMRequest matchMvno(IccMvnoType mvnoType, DOMString matchData); + + /** + * Retrieve the the availability of an icc service. + * + * @param service + * Identifies the service type. + * + * @return a Promise + * If succeeds, the promise is resolved with boolean indicating the + * availability of the service. Otherwise, rejected with a DOMError. + */ + [NewObject, Throws] + Promise getServiceState(IccService service); }; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/SourceBufferList.webidl thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/SourceBufferList.webidl --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/SourceBufferList.webidl 2015-01-07 22:15:31.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/SourceBufferList.webidl 2015-01-09 12:37:08.000000000 +0000 @@ -10,7 +10,7 @@ * liability, trademark and document use rules apply. */ -[Pref="media.mediasource.enabled"] +[Func="mozilla::dom::MediaSource::Enabled"] interface SourceBufferList : EventTarget { readonly attribute unsigned long length; getter SourceBuffer (unsigned long index); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/SourceBuffer.webidl thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/SourceBuffer.webidl --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/SourceBuffer.webidl 2015-01-07 22:15:31.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/SourceBuffer.webidl 2015-01-09 12:37:08.000000000 +0000 @@ -15,7 +15,7 @@ "sequence" }; -[Pref="media.mediasource.enabled"] +[Func="mozilla::dom::MediaSource::Enabled"] interface SourceBuffer : EventTarget { [SetterThrows] attribute SourceBufferAppendMode mode; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/Telephony.webidl thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/Telephony.webidl --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/Telephony.webidl 2015-01-07 22:15:31.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/Telephony.webidl 2015-01-09 12:37:08.000000000 +0000 @@ -28,6 +28,21 @@ [Throws] Promise dialEmergency(DOMString number, optional unsigned long serviceId); +/** + * Send a series of DTMF tones. + * + * @param tones + * DTMF chars. + * @param pauseDuraton (ms) [optional] + * Time to wait before sending tones. Default value is 3000 ms. + * @param toneDuration (ms) [optional] + * Duration of each tone. Default value is 70 ms. + * @param serviceId [optional] + * Default value is as user setting dom.telephony.defaultServiceId. + */ + [Throws] + Promise sendTones(DOMString tones, optional unsigned long pauseDuration = 3000, optional unsigned long toneDuration = 70, optional unsigned long serviceId); + [Throws] void startTone(DOMString tone, optional unsigned long serviceId); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/USSDSession.webidl thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/USSDSession.webidl --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/USSDSession.webidl 2015-01-07 22:15:31.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/USSDSession.webidl 2015-01-09 12:37:08.000000000 +0000 @@ -9,6 +9,9 @@ AvailableIn="CertifiedApps", Constructor(unsigned long serviceId)] interface USSDSession { - [Throws] + [NewObject, Throws] Promise send(DOMString ussd); + + [NewObject, Throws] + Promise cancel(); }; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/VideoPlaybackQuality.webidl thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/VideoPlaybackQuality.webidl --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/webidl/VideoPlaybackQuality.webidl 2015-01-07 22:15:31.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/webidl/VideoPlaybackQuality.webidl 2015-01-09 12:37:08.000000000 +0000 @@ -10,7 +10,7 @@ * liability, trademark and document use rules apply. */ -[Pref="media.mediasource.enabled"] +[Func="mozilla::dom::MediaSource::Enabled"] interface VideoPlaybackQuality { readonly attribute DOMHighResTimeStamp creationTime; readonly attribute unsigned long totalVideoFrames; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/workers/WorkerPrivate.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/workers/WorkerPrivate.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/workers/WorkerPrivate.cpp 2015-01-07 22:15:31.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/workers/WorkerPrivate.cpp 2015-01-09 12:37:09.000000000 +0000 @@ -6020,14 +6020,14 @@ JS::PrepareForFullGC(rt); if (aShrinking) { - JS::ShrinkingGC(rt, JS::gcreason::DOM_WORKER); + JS::GCForReason(rt, GC_SHRINK, JS::gcreason::DOM_WORKER); if (!aCollectChildren) { LOG(("Worker %p collected idle garbage\n", this)); } } else { - JS::GCForReason(rt, JS::gcreason::DOM_WORKER); + JS::GCForReason(rt, GC_NORMAL, JS::gcreason::DOM_WORKER); LOG(("Worker %p collected garbage\n", this)); } } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/workers/XMLHttpRequest.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/workers/XMLHttpRequest.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/workers/XMLHttpRequest.cpp 2015-01-07 22:15:31.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/workers/XMLHttpRequest.cpp 2015-01-09 12:37:09.000000000 +0000 @@ -919,7 +919,8 @@ nsCOMPtr global = do_QueryInterface(ownerWindow); if (NS_FAILED(mXHR->Init(mWorkerPrivate->GetPrincipal(), mWorkerPrivate->GetScriptContext(), - global, mWorkerPrivate->GetBaseURI()))) { + global, mWorkerPrivate->GetBaseURI(), + mWorkerPrivate->GetLoadGroup()))) { mXHR = nullptr; return false; } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xbl/XBLChildrenElement.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xbl/XBLChildrenElement.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xbl/XBLChildrenElement.cpp 2015-01-07 22:15:31.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xbl/XBLChildrenElement.cpp 2015-01-09 12:37:09.000000000 +0000 @@ -26,18 +26,6 @@ NS_IMPL_ELEMENT_CLONE(XBLChildrenElement) -nsIAtom* -XBLChildrenElement::GetIDAttributeName() const -{ - return nullptr; -} - -nsIAtom* -XBLChildrenElement::DoGetID() const -{ - return nullptr; -} - nsresult XBLChildrenElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, bool aNotify) diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xbl/XBLChildrenElement.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xbl/XBLChildrenElement.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xbl/XBLChildrenElement.h 2015-01-07 22:15:31.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xbl/XBLChildrenElement.h 2015-01-09 12:37:09.000000000 +0000 @@ -35,21 +35,17 @@ NS_DECL_ISUPPORTS_INHERITED // nsINode interface methods - virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const; + virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const MOZ_OVERRIDE; - virtual nsXPCClassInfo* GetClassInfo() { return nullptr; } - - virtual nsIDOMNode* AsDOMNode() { return this; } + virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE { return this; } // nsIContent interface methods - virtual nsIAtom *GetIDAttributeName() const; - virtual nsIAtom* DoGetID() const; virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, - bool aNotify); + bool aNotify) MOZ_OVERRIDE; virtual bool ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute, const nsAString& aValue, - nsAttrValue& aResult); + nsAttrValue& aResult) MOZ_OVERRIDE; void AppendInsertedChild(nsIContent* aChild) { @@ -176,9 +172,9 @@ NS_DECL_NSIDOMNODELIST // nsINodeList interface - virtual int32_t IndexOf(nsIContent* aContent); - virtual nsINode* GetParentObject() { return mParent; } - virtual nsIContent* Item(uint32_t aIndex); + virtual int32_t IndexOf(nsIContent* aContent) MOZ_OVERRIDE; + virtual nsINode* GetParentObject() MOZ_OVERRIDE { return mParent; } + virtual nsIContent* Item(uint32_t aIndex) MOZ_OVERRIDE; virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xml/CDATASection.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xml/CDATASection.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xml/CDATASection.h 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xml/CDATASection.h 2015-01-09 12:37:09.000000000 +0000 @@ -57,7 +57,7 @@ // Empty interface // nsINode - virtual bool IsNodeOfType(uint32_t aFlags) const; + virtual bool IsNodeOfType(uint32_t aFlags) const MOZ_OVERRIDE; virtual nsGenericDOMDataNode* CloneDataNode(mozilla::dom::NodeInfo *aNodeInfo, bool aCloneText) const MOZ_OVERRIDE; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xml/nsXMLFragmentContentSink.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xml/nsXMLFragmentContentSink.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xml/nsXMLFragmentContentSink.cpp 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xml/nsXMLFragmentContentSink.cpp 2015-01-09 12:37:09.000000000 +0000 @@ -45,51 +45,51 @@ nsXMLContentSink) // nsIExpatSink - NS_IMETHOD HandleDoctypeDecl(const nsAString & aSubset, - const nsAString & aName, - const nsAString & aSystemId, - const nsAString & aPublicId, - nsISupports* aCatalogData); - NS_IMETHOD HandleProcessingInstruction(const char16_t *aTarget, - const char16_t *aData); - NS_IMETHOD HandleXMLDeclaration(const char16_t *aVersion, - const char16_t *aEncoding, - int32_t aStandalone); - NS_IMETHOD ReportError(const char16_t* aErrorText, + NS_IMETHOD HandleDoctypeDecl(const nsAString& aSubset, + const nsAString& aName, + const nsAString& aSystemId, + const nsAString& aPublicId, + nsISupports* aCatalogData) MOZ_OVERRIDE; + NS_IMETHOD HandleProcessingInstruction(const char16_t* aTarget, + const char16_t* aData) MOZ_OVERRIDE; + NS_IMETHOD HandleXMLDeclaration(const char16_t* aVersion, + const char16_t* aEncoding, + int32_t aStandalone) MOZ_OVERRIDE; + NS_IMETHOD ReportError(const char16_t* aErrorText, const char16_t* aSourceText, - nsIScriptError *aError, - bool *_retval); + nsIScriptError* aError, + bool* aRetval) MOZ_OVERRIDE; // nsIContentSink - NS_IMETHOD WillBuildModel(nsDTDMode aDTDMode); - NS_IMETHOD DidBuildModel(bool aTerminated); - NS_IMETHOD SetDocumentCharset(nsACString& aCharset); - virtual nsISupports *GetTarget(); + NS_IMETHOD WillBuildModel(nsDTDMode aDTDMode) MOZ_OVERRIDE; + NS_IMETHOD DidBuildModel(bool aTerminated) MOZ_OVERRIDE; + NS_IMETHOD SetDocumentCharset(nsACString& aCharset) MOZ_OVERRIDE; + virtual nsISupports* GetTarget() MOZ_OVERRIDE; NS_IMETHOD DidProcessATokenImpl(); // nsIXMLContentSink // nsIFragmentContentSink - NS_IMETHOD FinishFragmentParsing(nsIDOMDocumentFragment** aFragment); - NS_IMETHOD SetTargetDocument(nsIDocument* aDocument); - NS_IMETHOD WillBuildContent(); - NS_IMETHOD DidBuildContent(); - NS_IMETHOD IgnoreFirstContainer(); - NS_IMETHOD SetPreventScriptExecution(bool aPreventScriptExecution); + NS_IMETHOD FinishFragmentParsing(nsIDOMDocumentFragment** aFragment) MOZ_OVERRIDE; + NS_IMETHOD SetTargetDocument(nsIDocument* aDocument) MOZ_OVERRIDE; + NS_IMETHOD WillBuildContent() MOZ_OVERRIDE; + NS_IMETHOD DidBuildContent() MOZ_OVERRIDE; + NS_IMETHOD IgnoreFirstContainer() MOZ_OVERRIDE; + NS_IMETHOD SetPreventScriptExecution(bool aPreventScriptExecution) MOZ_OVERRIDE; protected: virtual ~nsXMLFragmentContentSink(); - virtual bool SetDocElement(int32_t aNameSpaceID, - nsIAtom *aTagName, - nsIContent *aContent); + virtual bool SetDocElement(int32_t aNameSpaceID, + nsIAtom* aTagName, + nsIContent* aContent) MOZ_OVERRIDE; virtual nsresult CreateElement(const char16_t** aAtts, uint32_t aAttsCount, mozilla::dom::NodeInfo* aNodeInfo, uint32_t aLineNumber, nsIContent** aResult, bool* aAppendContent, - mozilla::dom::FromParser aFromParser); - virtual nsresult CloseElement(nsIContent* aContent); + mozilla::dom::FromParser aFromParser) MOZ_OVERRIDE; + virtual nsresult CloseElement(nsIContent* aContent) MOZ_OVERRIDE; - virtual void MaybeStartLayout(bool aIgnorePendingSheets); + virtual void MaybeStartLayout(bool aIgnorePendingSheets) MOZ_OVERRIDE; // nsContentSink overrides virtual nsresult ProcessStyleLink(nsIContent* aElement, @@ -97,7 +97,7 @@ bool aAlternate, const nsSubstring& aTitle, const nsSubstring& aType, - const nsSubstring& aMedia); + const nsSubstring& aMedia) MOZ_OVERRIDE; nsresult LoadXSLStyleSheet(nsIURI* aUrl); void StartLayout(); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xml/ProcessingInstruction.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xml/ProcessingInstruction.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xml/ProcessingInstruction.h 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xml/ProcessingInstruction.h 2015-01-09 12:37:09.000000000 +0000 @@ -35,7 +35,7 @@ NS_DECL_NSIDOMPROCESSINGINSTRUCTION // nsINode - virtual bool IsNodeOfType(uint32_t aFlags) const; + virtual bool IsNodeOfType(uint32_t aFlags) const MOZ_OVERRIDE; virtual nsGenericDOMDataNode* CloneDataNode(mozilla::dom::NodeInfo *aNodeInfo, bool aCloneText) const MOZ_OVERRIDE; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xslt/xpath/txExpr.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xslt/xpath/txExpr.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xslt/xpath/txExpr.h 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xslt/xpath/txExpr.h 2015-01-09 12:37:09.000000000 +0000 @@ -139,29 +139,28 @@ #ifdef TX_TO_STRING #define TX_DECL_TOSTRING \ - void toString(nsAString& aDest); + void toString(nsAString& aDest) MOZ_OVERRIDE; #define TX_DECL_GETNAMEATOM \ - nsresult getNameAtom(nsIAtom** aAtom); + nsresult getNameAtom(nsIAtom** aAtom) MOZ_OVERRIDE; #else #define TX_DECL_TOSTRING #define TX_DECL_GETNAMEATOM #endif #define TX_DECL_EXPR_BASE \ - nsresult evaluate(txIEvalContext* aContext, txAExprResult** aResult); \ - ResultType getReturnType(); \ - bool isSensitiveTo(ContextSensitivity aContexts); + nsresult evaluate(txIEvalContext* aContext, txAExprResult** aResult) MOZ_OVERRIDE; \ + ResultType getReturnType() MOZ_OVERRIDE; \ + bool isSensitiveTo(ContextSensitivity aContexts) MOZ_OVERRIDE; #define TX_DECL_EXPR \ TX_DECL_EXPR_BASE \ TX_DECL_TOSTRING \ - Expr* getSubExprAt(uint32_t aPos); \ - void setSubExprAt(uint32_t aPos, Expr* aExpr); + Expr* getSubExprAt(uint32_t aPos) MOZ_OVERRIDE; \ + void setSubExprAt(uint32_t aPos, Expr* aExpr) MOZ_OVERRIDE; #define TX_DECL_OPTIMIZABLE_EXPR \ TX_DECL_EXPR \ - ExprType getType(); - + ExprType getType() MOZ_OVERRIDE; #define TX_DECL_FUNCTION \ TX_DECL_GETNAMEATOM \ @@ -426,9 +425,9 @@ #define TX_DECL_NODE_TEST \ TX_DECL_TOSTRING \ - bool matches(const txXPathNode& aNode, txIMatchContext* aContext); \ - double getDefaultPriority(); \ - bool isSensitiveTo(Expr::ContextSensitivity aContext); + bool matches(const txXPathNode& aNode, txIMatchContext* aContext) MOZ_OVERRIDE; \ + double getDefaultPriority() MOZ_OVERRIDE; \ + bool isSensitiveTo(Expr::ContextSensitivity aContext) MOZ_OVERRIDE; /* * This class represents a NameTest as defined by the XPath spec diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xslt/xpath/txXPathObjectAdaptor.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xslt/xpath/txXPathObjectAdaptor.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xslt/xpath/txXPathObjectAdaptor.h 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xslt/xpath/txXPathObjectAdaptor.h 2015-01-09 12:37:09.000000000 +0000 @@ -27,7 +27,7 @@ NS_DECL_ISUPPORTS - NS_IMETHODIMP_(txAExprResult*) GetResult() + NS_IMETHODIMP_(txAExprResult*) GetResult() MOZ_OVERRIDE { return mValue; } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xslt/xpath/XPathResult.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xslt/xpath/XPathResult.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xslt/xpath/XPathResult.h 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xslt/xpath/XPathResult.h 2015-01-09 12:37:09.000000000 +0000 @@ -77,7 +77,7 @@ return static_cast(static_cast(aSupports)); } - virtual JSObject* WrapObject(JSContext* aCx); + virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE; nsINode* GetParentObject() const { return mParent; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp 2015-01-09 12:37:09.000000000 +0000 @@ -79,14 +79,14 @@ NS_DECL_NSIINTERFACEREQUESTOR // nsIContentSink - NS_IMETHOD WillParse(void) { return NS_OK; } - NS_IMETHOD DidBuildModel(bool aTerminated); - NS_IMETHOD WillInterrupt(void) { return NS_OK; } - NS_IMETHOD WillResume(void) { return NS_OK; } - NS_IMETHOD SetParser(nsParserBase* aParser) { return NS_OK; } - virtual void FlushPendingNotifications(mozFlushType aType) { } - NS_IMETHOD SetDocumentCharset(nsACString& aCharset) { return NS_OK; } - virtual nsISupports *GetTarget() { return nullptr; } + NS_IMETHOD WillParse(void) MOZ_OVERRIDE { return NS_OK; } + NS_IMETHOD DidBuildModel(bool aTerminated) MOZ_OVERRIDE; + NS_IMETHOD WillInterrupt(void) MOZ_OVERRIDE { return NS_OK; } + NS_IMETHOD WillResume(void) MOZ_OVERRIDE { return NS_OK; } + NS_IMETHOD SetParser(nsParserBase* aParser) MOZ_OVERRIDE { return NS_OK; } + virtual void FlushPendingNotifications(mozFlushType aType) MOZ_OVERRIDE { } + NS_IMETHOD SetDocumentCharset(nsACString& aCharset) MOZ_OVERRIDE { return NS_OK; } + virtual nsISupports *GetTarget() MOZ_OVERRIDE { return nullptr; } private: nsRefPtr mCompiler; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xslt/xslt/txXSLTPatterns.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xslt/xslt/txXSLTPatterns.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xslt/xslt/txXSLTPatterns.h 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xslt/xslt/txXSLTPatterns.h 2015-01-09 12:37:09.000000000 +0000 @@ -88,19 +88,19 @@ }; #define TX_DECL_PATTERN_BASE \ - bool matches(const txXPathNode& aNode, txIMatchContext* aContext); \ - double getDefaultPriority(); \ - virtual Expr* getSubExprAt(uint32_t aPos); \ - virtual void setSubExprAt(uint32_t aPos, Expr* aExpr); \ - virtual txPattern* getSubPatternAt(uint32_t aPos); \ - virtual void setSubPatternAt(uint32_t aPos, txPattern* aPattern) + bool matches(const txXPathNode& aNode, txIMatchContext* aContext) MOZ_OVERRIDE; \ + double getDefaultPriority() MOZ_OVERRIDE; \ + virtual Expr* getSubExprAt(uint32_t aPos) MOZ_OVERRIDE; \ + virtual void setSubExprAt(uint32_t aPos, Expr* aExpr) MOZ_OVERRIDE; \ + virtual txPattern* getSubPatternAt(uint32_t aPos) MOZ_OVERRIDE; \ + virtual void setSubPatternAt(uint32_t aPos, txPattern* aPattern) MOZ_OVERRIDE #ifndef TX_TO_STRING #define TX_DECL_PATTERN TX_DECL_PATTERN_BASE #else #define TX_DECL_PATTERN \ TX_DECL_PATTERN_BASE; \ - void toString(nsAString& aDest) + void toString(nsAString& aDest) MOZ_OVERRIDE #endif #define TX_IMPL_PATTERN_STUBS_NO_SUB_EXPR(_class) \ diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xul/nsXULElement.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xul/nsXULElement.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xul/nsXULElement.cpp 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xul/nsXULElement.cpp 2015-01-09 12:37:09.000000000 +0000 @@ -138,7 +138,7 @@ { } - NS_IMETHOD GetStyle(nsIDOMCSSStyleDeclaration** aStyle) + NS_IMETHOD GetStyle(nsIDOMCSSStyleDeclaration** aStyle) MOZ_OVERRIDE { nsXULElement* element = static_cast(mElement.get()); NS_ADDREF(*aStyle = element->Style()); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xul/templates/nsContentSupportMap.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xul/templates/nsContentSupportMap.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xul/templates/nsContentSupportMap.cpp 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xul/templates/nsContentSupportMap.cpp 2015-01-09 12:37:10.000000000 +0000 @@ -27,7 +27,7 @@ nsIContent* child = aElement; do { - PL_DHashTableOperate(&mMap, child, PL_DHASH_REMOVE); + PL_DHashTableRemove(&mMap, child); child = child->GetNextNode(aElement); } while(child); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xul/templates/nsContentSupportMap.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xul/templates/nsContentSupportMap.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xul/templates/nsContentSupportMap.h 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xul/templates/nsContentSupportMap.h 2015-01-09 12:37:10.000000000 +0000 @@ -28,7 +28,7 @@ if (!mMap.ops) return NS_ERROR_NOT_INITIALIZED; - PLDHashEntryHdr* hdr = PL_DHashTableOperate(&mMap, aElement, PL_DHASH_ADD); + PLDHashEntryHdr* hdr = PL_DHashTableAdd(&mMap, aElement); if (!hdr) return NS_ERROR_OUT_OF_MEMORY; @@ -42,7 +42,7 @@ if (!mMap.ops) return false; - PLDHashEntryHdr* hdr = PL_DHashTableOperate(&mMap, aElement, PL_DHASH_LOOKUP); + PLDHashEntryHdr* hdr = PL_DHashTableLookup(&mMap, aElement); if (PL_DHASH_ENTRY_IS_FREE(hdr)) return false; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xul/templates/nsTemplateMap.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xul/templates/nsTemplateMap.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xul/templates/nsTemplateMap.h 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xul/templates/nsTemplateMap.h 2015-01-09 12:37:11.000000000 +0000 @@ -36,11 +36,11 @@ void Put(nsIContent* aContent, nsIContent* aTemplate) { - NS_ASSERTION(PL_DHASH_ENTRY_IS_FREE(PL_DHashTableOperate(&mTable, aContent, PL_DHASH_LOOKUP)), + NS_ASSERTION(PL_DHASH_ENTRY_IS_FREE(PL_DHashTableLookup(&mTable, aContent)), "aContent already in map"); Entry* entry = - reinterpret_cast(PL_DHashTableOperate(&mTable, aContent, PL_DHASH_ADD)); + reinterpret_cast(PL_DHashTableAdd(&mTable, aContent)); if (entry) { entry->mContent = aContent; @@ -50,7 +50,7 @@ void Remove(nsIContent* aContent) { - PL_DHashTableOperate(&mTable, aContent, PL_DHASH_REMOVE); + PL_DHashTableRemove(&mTable, aContent); for (nsIContent* child = aContent->GetFirstChild(); child; @@ -63,7 +63,7 @@ void GetTemplateFor(nsIContent* aContent, nsIContent** aResult) { Entry* entry = - reinterpret_cast(PL_DHashTableOperate(&mTable, aContent, PL_DHASH_LOOKUP)); + reinterpret_cast(PL_DHashTableLookup(&mTable, aContent)); if (PL_DHASH_ENTRY_IS_BUSY(&entry->mHdr)) NS_IF_ADDREF(*aResult = entry->mTemplate); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xul/templates/nsXULContentBuilder.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xul/templates/nsXULContentBuilder.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xul/templates/nsXULContentBuilder.cpp 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xul/templates/nsXULContentBuilder.cpp 2015-01-09 12:37:11.000000000 +0000 @@ -72,14 +72,14 @@ { public: // nsIXULTemplateBuilder interface - NS_IMETHOD CreateContents(nsIContent* aElement, bool aForceCreation); + NS_IMETHOD CreateContents(nsIContent* aElement, bool aForceCreation) MOZ_OVERRIDE; NS_IMETHOD HasGeneratedContent(nsIRDFResource* aResource, nsIAtom* aTag, - bool* aGenerated); + bool* aGenerated) MOZ_OVERRIDE; NS_IMETHOD GetResultForContent(nsIDOMElement* aContent, - nsIXULTemplateResult** aResult); + nsIXULTemplateResult** aResult) MOZ_OVERRIDE; // nsIMutationObserver interface NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED @@ -91,12 +91,12 @@ nsXULContentBuilder(); - void Traverse(nsCycleCollectionTraversalCallback &cb) const + void Traverse(nsCycleCollectionTraversalCallback& aCb) const MOZ_OVERRIDE { - mSortState.Traverse(cb); + mSortState.Traverse(aCb); } - virtual void Uninit(bool aIsFinal); + virtual void Uninit(bool aIsFinal) MOZ_OVERRIDE; // Implementation methods nsresult @@ -269,7 +269,7 @@ bool aNotify); virtual nsresult - RebuildAll(); + RebuildAll() MOZ_OVERRIDE; // GetInsertionLocations, ReplaceMatch and SynchronizeResult are inherited // from nsXULTemplateBuilder @@ -281,7 +281,7 @@ */ virtual bool GetInsertionLocations(nsIXULTemplateResult* aOldResult, - nsCOMArray** aLocations); + nsCOMArray** aLocations) MOZ_OVERRIDE; /** * Remove the content associated with aOldResult which no longer matches, @@ -291,7 +291,7 @@ ReplaceMatch(nsIXULTemplateResult* aOldResult, nsTemplateMatch* aNewMatch, nsTemplateRule* aNewMatchRule, - void *aContext); + void *aContext) MOZ_OVERRIDE; /** * Synchronize a result bindings with the generated content for that @@ -299,7 +299,7 @@ * ResultBindingChanged method. */ virtual nsresult - SynchronizeResult(nsIXULTemplateResult* aResult); + SynchronizeResult(nsIXULTemplateResult* aResult) MOZ_OVERRIDE; /** * Compare a result to a content node. If the generated content for the diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xul/templates/nsXULTemplateQueryProcessorXML.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xul/templates/nsXULTemplateQueryProcessorXML.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xul/templates/nsXULTemplateQueryProcessorXML.cpp 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xul/templates/nsXULTemplateQueryProcessorXML.cpp 2015-01-09 12:37:11.000000000 +0000 @@ -173,7 +173,7 @@ rv = req->Init(docPrincipal, context, scriptObject ? scriptObject : doc->GetScopeObject(), - nullptr); + nullptr, nullptr); NS_ENSURE_SUCCESS(rv, rv); rv = req->Open(NS_LITERAL_CSTRING("GET"), uriStr, true, diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xul/templates/nsXULTreeBuilder.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xul/templates/nsXULTreeBuilder.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xul/templates/nsXULTreeBuilder.cpp 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xul/templates/nsXULTreeBuilder.cpp 2015-01-09 12:37:11.000000000 +0000 @@ -55,7 +55,7 @@ // nsITreeView NS_DECL_NSITREEVIEW // nsINativeTreeView: Untrusted code can use us - NS_IMETHOD EnsureNative() { return NS_OK; } + NS_IMETHOD EnsureNative() MOZ_OVERRIDE { return NS_OK; } // nsIMutationObserver NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED @@ -72,7 +72,7 @@ /** * Uninitialize the template builder */ - virtual void Uninit(bool aIsFinal); + virtual void Uninit(bool aIsFinal) MOZ_OVERRIDE; /** * Get sort variables from the active @@ -81,7 +81,7 @@ EnsureSortVariables(); virtual nsresult - RebuildAll(); + RebuildAll() MOZ_OVERRIDE; /** * Given a row, use the row's match to figure out the appropriate @@ -169,7 +169,7 @@ NS_IMETHOD HasGeneratedContent(nsIRDFResource* aResource, nsIAtom* aTag, - bool* aGenerated); + bool* aGenerated) MOZ_OVERRIDE; // GetInsertionLocations, ReplaceMatch and SynchronizeResult are inherited // from nsXULTemplateBuilder @@ -180,7 +180,7 @@ */ bool GetInsertionLocations(nsIXULTemplateResult* aResult, - nsCOMArray** aLocations); + nsCOMArray** aLocations) MOZ_OVERRIDE; /** * Implement result replacement @@ -189,13 +189,13 @@ ReplaceMatch(nsIXULTemplateResult* aOldResult, nsTemplateMatch* aNewMatch, nsTemplateRule* aNewMatchRule, - void *aContext); + void* aContext) MOZ_OVERRIDE; /** * Implement match synchronization */ virtual nsresult - SynchronizeResult(nsIXULTemplateResult* aResult); + SynchronizeResult(nsIXULTemplateResult* aResult) MOZ_OVERRIDE; /** * The tree's box object, used to communicate with the front-end. diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xul/XULDocument.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xul/XULDocument.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/dom/xul/XULDocument.cpp 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/dom/xul/XULDocument.cpp 2015-01-09 12:37:09.000000000 +0000 @@ -782,14 +782,12 @@ BroadcasterMapEntry* entry = static_cast - (PL_DHashTableOperate(mBroadcasterMap, &aBroadcaster, - PL_DHASH_LOOKUP)); + (PL_DHashTableLookup(mBroadcasterMap, &aBroadcaster)); if (PL_DHASH_ENTRY_IS_FREE(entry)) { entry = static_cast - (PL_DHashTableOperate(mBroadcasterMap, &aBroadcaster, - PL_DHASH_ADD)); + (PL_DHashTableAdd(mBroadcasterMap, &aBroadcaster)); if (! entry) { aRv.Throw(NS_ERROR_OUT_OF_MEMORY); @@ -850,8 +848,7 @@ BroadcasterMapEntry* entry = static_cast - (PL_DHashTableOperate(mBroadcasterMap, &aBroadcaster, - PL_DHASH_LOOKUP)); + (PL_DHashTableLookup(mBroadcasterMap, &aBroadcaster)); if (PL_DHASH_ENTRY_IS_BUSY(entry)) { nsCOMPtr attr = do_GetAtom(aAttr); @@ -866,8 +863,7 @@ delete bl; if (entry->mListeners.Count() == 0) - PL_DHashTableOperate(mBroadcasterMap, &aBroadcaster, - PL_DHASH_REMOVE); + PL_DHashTableRemove(mBroadcasterMap, &aBroadcaster); break; } @@ -974,8 +970,7 @@ CanBroadcast(aNameSpaceID, aAttribute)) { BroadcasterMapEntry* entry = static_cast - (PL_DHashTableOperate(mBroadcasterMap, aElement, - PL_DHASH_LOOKUP)); + (PL_DHashTableLookup(mBroadcasterMap, aElement)); if (PL_DHASH_ENTRY_IS_BUSY(entry)) { // We've got listeners: push the value. @@ -4171,7 +4166,7 @@ return rv; BroadcasterMapEntry* entry = static_cast - (PL_DHashTableOperate(mBroadcasterMap, aNode->AsElement(), PL_DHASH_LOOKUP)); + (PL_DHashTableLookup(mBroadcasterMap, aNode->AsElement())); if (!PL_DHASH_ENTRY_IS_BUSY(entry)) return rv; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/editor/composer/nsComposerCommands.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/editor/composer/nsComposerCommands.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/editor/composer/nsComposerCommands.h 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/editor/composer/nsComposerCommands.h 2015-01-09 12:37:12.000000000 +0000 @@ -38,8 +38,8 @@ NS_DECL_ISUPPORTS // nsIControllerCommand. Declared longhand so we can make them pure virtual - NS_IMETHOD IsCommandEnabled(const char * aCommandName, nsISupports *aCommandRefCon, bool *_retval) = 0; - NS_IMETHOD DoCommand(const char * aCommandName, nsISupports *aCommandRefCon) = 0; + NS_IMETHOD IsCommandEnabled(const char * aCommandName, nsISupports *aCommandRefCon, bool *_retval) MOZ_OVERRIDE = 0; + NS_IMETHOD DoCommand(const char * aCommandName, nsISupports *aCommandRefCon) MOZ_OVERRIDE = 0; }; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/editor/composer/nsComposerCommandsUpdater.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/editor/composer/nsComposerCommandsUpdater.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/editor/composer/nsComposerCommandsUpdater.h 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/editor/composer/nsComposerCommandsUpdater.h 2015-01-09 12:37:12.000000000 +0000 @@ -47,21 +47,21 @@ /** nsITransactionListener interfaces */ - NS_IMETHOD WillDo(nsITransactionManager *aManager, nsITransaction *aTransaction, bool *aInterrupt); - NS_IMETHOD DidDo(nsITransactionManager *aManager, nsITransaction *aTransaction, nsresult aDoResult); - NS_IMETHOD WillUndo(nsITransactionManager *aManager, nsITransaction *aTransaction, bool *aInterrupt); - NS_IMETHOD DidUndo(nsITransactionManager *aManager, nsITransaction *aTransaction, nsresult aUndoResult); - NS_IMETHOD WillRedo(nsITransactionManager *aManager, nsITransaction *aTransaction, bool *aInterrupt); - NS_IMETHOD DidRedo(nsITransactionManager *aManager, nsITransaction *aTransaction, nsresult aRedoResult); - NS_IMETHOD WillBeginBatch(nsITransactionManager *aManager, bool *aInterrupt); - NS_IMETHOD DidBeginBatch(nsITransactionManager *aManager, nsresult aResult); - NS_IMETHOD WillEndBatch(nsITransactionManager *aManager, bool *aInterrupt); - NS_IMETHOD DidEndBatch(nsITransactionManager *aManager, nsresult aResult); + NS_IMETHOD WillDo(nsITransactionManager *aManager, nsITransaction *aTransaction, bool *aInterrupt) MOZ_OVERRIDE; + NS_IMETHOD DidDo(nsITransactionManager *aManager, nsITransaction *aTransaction, nsresult aDoResult) MOZ_OVERRIDE; + NS_IMETHOD WillUndo(nsITransactionManager *aManager, nsITransaction *aTransaction, bool *aInterrupt) MOZ_OVERRIDE; + NS_IMETHOD DidUndo(nsITransactionManager *aManager, nsITransaction *aTransaction, nsresult aUndoResult) MOZ_OVERRIDE; + NS_IMETHOD WillRedo(nsITransactionManager *aManager, nsITransaction *aTransaction, bool *aInterrupt) MOZ_OVERRIDE; + NS_IMETHOD DidRedo(nsITransactionManager *aManager, nsITransaction *aTransaction, nsresult aRedoResult) MOZ_OVERRIDE; + NS_IMETHOD WillBeginBatch(nsITransactionManager *aManager, bool *aInterrupt) MOZ_OVERRIDE; + NS_IMETHOD DidBeginBatch(nsITransactionManager *aManager, nsresult aResult) MOZ_OVERRIDE; + NS_IMETHOD WillEndBatch(nsITransactionManager *aManager, bool *aInterrupt) MOZ_OVERRIDE; + NS_IMETHOD DidEndBatch(nsITransactionManager *aManager, nsresult aResult) MOZ_OVERRIDE; NS_IMETHOD WillMerge(nsITransactionManager *aManager, nsITransaction *aTopTransaction, - nsITransaction *aTransactionToMerge, bool *aInterrupt); + nsITransaction *aTransactionToMerge, bool *aInterrupt) MOZ_OVERRIDE; NS_IMETHOD DidMerge(nsITransactionManager *aManager, nsITransaction *aTopTransaction, nsITransaction *aTransactionToMerge, - bool aDidMerge, nsresult aMergeResult); + bool aDidMerge, nsresult aMergeResult) MOZ_OVERRIDE; nsresult Init(nsIDOMWindow* aDOMWindow); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/editor/composer/nsEditorSpellCheck.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/editor/composer/nsEditorSpellCheck.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/editor/composer/nsEditorSpellCheck.cpp 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/editor/composer/nsEditorSpellCheck.cpp 2015-01-09 12:37:12.000000000 +0000 @@ -138,7 +138,7 @@ NS_IMETHOD Fetch(nsIEditor* aEditor); - NS_IMETHOD HandleResult(nsIContentPref* aPref) + NS_IMETHOD HandleResult(nsIContentPref* aPref) MOZ_OVERRIDE { nsCOMPtr value; nsresult rv = aPref->GetValue(getter_AddRefs(value)); @@ -147,13 +147,13 @@ return NS_OK; } - NS_IMETHOD HandleCompletion(uint16_t reason) + NS_IMETHOD HandleCompletion(uint16_t reason) MOZ_OVERRIDE { mSpellCheck->DictionaryFetched(this); return NS_OK; } - NS_IMETHOD HandleError(nsresult error) + NS_IMETHOD HandleError(nsresult error) MOZ_OVERRIDE { return NS_OK; } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/embedding/components/commandhandler/nsCommandParams.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/embedding/components/commandhandler/nsCommandParams.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/embedding/components/commandhandler/nsCommandParams.cpp 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/embedding/components/commandhandler/nsCommandParams.cpp 2015-01-09 12:37:13.000000000 +0000 @@ -214,7 +214,7 @@ { // PL_DHASH_REMOVE doesn't tell us if the entry was really removed, so we // return NS_OK unconditionally. - (void)PL_DHashTableOperate(&mValuesHash, (void *)aName, PL_DHASH_REMOVE); + (void)PL_DHashTableRemove(&mValuesHash, (void *)aName); return NS_OK; } @@ -222,8 +222,7 @@ nsCommandParams::GetNamedEntry(const char* aName) { HashEntry *foundEntry = - (HashEntry *)PL_DHashTableOperate(&mValuesHash, (void *)aName, - PL_DHASH_LOOKUP); + (HashEntry *)PL_DHashTableLookup(&mValuesHash, (void *)aName); if (PL_DHASH_ENTRY_IS_BUSY(foundEntry)) { return foundEntry; } @@ -234,15 +233,13 @@ nsCommandParams::GetOrMakeEntry(const char* aName, uint8_t entryType) { HashEntry *foundEntry = - (HashEntry *)PL_DHashTableOperate(&mValuesHash, (void *)aName, - PL_DHASH_LOOKUP); + (HashEntry *)PL_DHashTableLookup(&mValuesHash, (void *)aName); if (PL_DHASH_ENTRY_IS_BUSY(foundEntry)) { // reuse existing entry foundEntry->Reset(entryType); return foundEntry; } - foundEntry = (HashEntry *)PL_DHashTableOperate(&mValuesHash, (void *)aName, - PL_DHASH_ADD); + foundEntry = (HashEntry *)PL_DHashTableAdd(&mValuesHash, (void *)aName); if (!foundEntry) { return nullptr; } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/extensions/spellcheck/hunspell/src/mozHunspell.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/extensions/spellcheck/hunspell/src/mozHunspell.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/extensions/spellcheck/hunspell/src/mozHunspell.h 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/extensions/spellcheck/hunspell/src/mozHunspell.h 2015-01-09 12:37:13.000000000 +0000 @@ -102,7 +102,7 @@ nsresult ConvertCharset(const char16_t* aStr, char ** aDst); NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport, - nsISupports* aData, bool aAnonymize) + nsISupports* aData, bool aAnonymize) MOZ_OVERRIDE { return MOZ_COLLECT_REPORT( "explicit/spell-check", KIND_HEAP, UNITS_BYTES, HunspellAllocator::MemoryAllocated(), diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/extensions/spellcheck/src/mozInlineSpellChecker.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/extensions/spellcheck/src/mozInlineSpellChecker.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/extensions/spellcheck/src/mozInlineSpellChecker.cpp 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/extensions/spellcheck/src/mozInlineSpellChecker.cpp 2015-01-09 12:37:14.000000000 +0000 @@ -500,7 +500,7 @@ explicit InitEditorSpellCheckCallback(mozInlineSpellChecker* aSpellChecker) : mSpellChecker(aSpellChecker) {} - NS_IMETHOD EditorSpellCheckDone() + NS_IMETHOD EditorSpellCheckDone() MOZ_OVERRIDE { return mSpellChecker ? mSpellChecker->EditorSpellCheckInited() : NS_OK; } @@ -1950,7 +1950,7 @@ uint32_t aDisabledAsyncToken) : mSpellChecker(aSpellChecker), mDisabledAsyncToken(aDisabledAsyncToken) {} - NS_IMETHOD EditorSpellCheckDone() + NS_IMETHOD EditorSpellCheckDone() MOZ_OVERRIDE { // Ignore this callback if SetEnableRealTimeSpell(false) was called after // the UpdateCurrentDictionary call that triggered it. diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/extensions/spellcheck/src/mozSpellChecker.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/extensions/spellcheck/src/mozSpellChecker.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/extensions/spellcheck/src/mozSpellChecker.h 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/extensions/spellcheck/src/mozSpellChecker.h 2015-01-09 12:37:14.000000000 +0000 @@ -35,20 +35,20 @@ nsresult Init(); // nsISpellChecker - NS_IMETHOD SetDocument(nsITextServicesDocument *aDoc, bool aFromStartofDoc); - NS_IMETHOD NextMisspelledWord(nsAString &aWord, nsTArray *aSuggestions); - NS_IMETHOD CheckWord(const nsAString &aWord, bool *aIsMisspelled, nsTArray *aSuggestions); - NS_IMETHOD Replace(const nsAString &aOldWord, const nsAString &aNewWord, bool aAllOccurrences); - NS_IMETHOD IgnoreAll(const nsAString &aWord); + NS_IMETHOD SetDocument(nsITextServicesDocument *aDoc, bool aFromStartofDoc) MOZ_OVERRIDE; + NS_IMETHOD NextMisspelledWord(nsAString &aWord, nsTArray *aSuggestions) MOZ_OVERRIDE; + NS_IMETHOD CheckWord(const nsAString &aWord, bool *aIsMisspelled, nsTArray *aSuggestions) MOZ_OVERRIDE; + NS_IMETHOD Replace(const nsAString &aOldWord, const nsAString &aNewWord, bool aAllOccurrences) MOZ_OVERRIDE; + NS_IMETHOD IgnoreAll(const nsAString &aWord) MOZ_OVERRIDE; - NS_IMETHOD AddWordToPersonalDictionary(const nsAString &aWord); - NS_IMETHOD RemoveWordFromPersonalDictionary(const nsAString &aWord); - NS_IMETHOD GetPersonalDictionary(nsTArray *aWordList); + NS_IMETHOD AddWordToPersonalDictionary(const nsAString &aWord) MOZ_OVERRIDE; + NS_IMETHOD RemoveWordFromPersonalDictionary(const nsAString &aWord) MOZ_OVERRIDE; + NS_IMETHOD GetPersonalDictionary(nsTArray *aWordList) MOZ_OVERRIDE; - NS_IMETHOD GetDictionaryList(nsTArray *aDictionaryList); - NS_IMETHOD GetCurrentDictionary(nsAString &aDictionary); - NS_IMETHOD SetCurrentDictionary(const nsAString &aDictionary); - NS_IMETHOD CheckCurrentDictionary(); + NS_IMETHOD GetDictionaryList(nsTArray *aDictionaryList) MOZ_OVERRIDE; + NS_IMETHOD GetCurrentDictionary(nsAString &aDictionary) MOZ_OVERRIDE; + NS_IMETHOD SetCurrentDictionary(const nsAString &aDictionary) MOZ_OVERRIDE; + NS_IMETHOD CheckCurrentDictionary() MOZ_OVERRIDE; void DeleteRemoteEngine() { mEngine = nullptr; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/2D.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/2D.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/2D.h 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/2D.h 2015-01-09 12:37:14.000000000 +0000 @@ -1181,6 +1181,8 @@ */ static TemporaryRef CreateTiledDrawTarget(const TileSet& aTileSet); + static bool DoesBackendSupportDataDrawtarget(BackendType aType); + #ifdef XP_MACOSX static TemporaryRef CreateDrawTargetForCairoCGContext(CGContextRef cg, const IntSize& aSize); static TemporaryRef @@ -1196,14 +1198,12 @@ static void SetDirect3D10Device(ID3D10Device1 *aDevice); static ID3D10Device1 *GetDirect3D10Device(); -#ifdef USE_D2D1_1 static TemporaryRef CreateDrawTargetForD3D11Texture(ID3D11Texture2D *aTexture, SurfaceFormat aFormat); static void SetDirect3D11Device(ID3D11Device *aDevice); static ID3D11Device *GetDirect3D11Device(); static ID2D1Device *GetD2D1Device(); static bool SupportsD2D1(); -#endif static TemporaryRef CreateDWriteGlyphRenderingOptions(IDWriteRenderingParams *aParams); @@ -1213,11 +1213,9 @@ static void D2DCleanup(); private: + static ID2D1Device *mD2D1Device; static ID3D10Device1 *mD3D10Device; -#ifdef USE_D2D1_1 static ID3D11Device *mD3D11Device; - static ID2D1Device *mD2D1Device; -#endif #endif static DrawEventRecorder *mRecorder; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/DataSourceSurfaceWrapper.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/DataSourceSurfaceWrapper.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/DataSourceSurfaceWrapper.h 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/DataSourceSurfaceWrapper.h 2015-01-09 12:37:14.000000000 +0000 @@ -16,7 +16,7 @@ class DataSourceSurfaceWrapper : public DataSourceSurface { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceWrapper) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceWrapper, MOZ_OVERRIDE) explicit DataSourceSurfaceWrapper(DataSourceSurface *aSurface) : mSurface(aSurface) {} diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/DrawTargetCairo.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/DrawTargetCairo.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/DrawTargetCairo.h 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/DrawTargetCairo.h 2015-01-09 12:37:14.000000000 +0000 @@ -52,116 +52,116 @@ class DrawTargetCairo : public DrawTarget { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetCairo) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetCairo, MOZ_OVERRIDE) friend class BorrowedCairoContext; DrawTargetCairo(); virtual ~DrawTargetCairo(); virtual DrawTargetType GetType() const MOZ_OVERRIDE; - virtual BackendType GetBackendType() const { return BackendType::CAIRO; } - virtual TemporaryRef Snapshot(); - virtual IntSize GetSize(); + virtual BackendType GetBackendType() const MOZ_OVERRIDE { return BackendType::CAIRO; } + virtual TemporaryRef Snapshot() MOZ_OVERRIDE; + virtual IntSize GetSize() MOZ_OVERRIDE; - virtual void SetPermitSubpixelAA(bool aPermitSubpixelAA); + virtual void SetPermitSubpixelAA(bool aPermitSubpixelAA) MOZ_OVERRIDE; virtual bool LockBits(uint8_t** aData, IntSize* aSize, - int32_t* aStride, SurfaceFormat* aFormat); - virtual void ReleaseBits(uint8_t* aData); + int32_t* aStride, SurfaceFormat* aFormat) MOZ_OVERRIDE; + virtual void ReleaseBits(uint8_t* aData) MOZ_OVERRIDE; - virtual void Flush(); + virtual void Flush() MOZ_OVERRIDE; virtual void DrawSurface(SourceSurface *aSurface, const Rect &aDest, const Rect &aSource, const DrawSurfaceOptions &aSurfOptions = DrawSurfaceOptions(), - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void DrawFilter(FilterNode *aNode, const Rect &aSourceRect, const Point &aDestPoint, - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void DrawSurfaceWithShadow(SourceSurface *aSurface, const Point &aDest, const Color &aColor, const Point &aOffset, Float aSigma, - CompositionOp aOperator); + CompositionOp aOperator) MOZ_OVERRIDE; - virtual void ClearRect(const Rect &aRect); + virtual void ClearRect(const Rect &aRect) MOZ_OVERRIDE; virtual void CopySurface(SourceSurface *aSurface, const IntRect &aSourceRect, - const IntPoint &aDestination); + const IntPoint &aDestination) MOZ_OVERRIDE; virtual void CopyRect(const IntRect &aSourceRect, - const IntPoint &aDestination); + const IntPoint &aDestination) MOZ_OVERRIDE; virtual void FillRect(const Rect &aRect, const Pattern &aPattern, - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void StrokeRect(const Rect &aRect, const Pattern &aPattern, const StrokeOptions &aStrokeOptions = StrokeOptions(), - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void StrokeLine(const Point &aStart, const Point &aEnd, const Pattern &aPattern, const StrokeOptions &aStrokeOptions = StrokeOptions(), - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void Stroke(const Path *aPath, const Pattern &aPattern, const StrokeOptions &aStrokeOptions = StrokeOptions(), - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void Fill(const Path *aPath, const Pattern &aPattern, - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void FillGlyphs(ScaledFont *aFont, const GlyphBuffer &aBuffer, const Pattern &aPattern, const DrawOptions &aOptions, - const GlyphRenderingOptions *aRenderingOptions = nullptr); + const GlyphRenderingOptions *aRenderingOptions = nullptr) MOZ_OVERRIDE; virtual void Mask(const Pattern &aSource, const Pattern &aMask, - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void MaskSurface(const Pattern &aSource, SourceSurface *aMask, Point aOffset, - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; - virtual void PushClip(const Path *aPath); - virtual void PushClipRect(const Rect &aRect); - virtual void PopClip(); + virtual void PushClip(const Path *aPath) MOZ_OVERRIDE; + virtual void PushClipRect(const Rect &aRect) MOZ_OVERRIDE; + virtual void PopClip() MOZ_OVERRIDE; - virtual TemporaryRef CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const; + virtual TemporaryRef CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const MOZ_OVERRIDE; virtual TemporaryRef CreateSourceSurfaceFromData(unsigned char *aData, const IntSize &aSize, int32_t aStride, - SurfaceFormat aFormat) const; - virtual TemporaryRef OptimizeSourceSurface(SourceSurface *aSurface) const; + SurfaceFormat aFormat) const MOZ_OVERRIDE; + virtual TemporaryRef OptimizeSourceSurface(SourceSurface *aSurface) const MOZ_OVERRIDE; virtual TemporaryRef - CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const; + CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const MOZ_OVERRIDE; virtual TemporaryRef - CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const; + CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const MOZ_OVERRIDE; virtual TemporaryRef CreateShadowDrawTarget(const IntSize &aSize, SurfaceFormat aFormat, - float aSigma) const; + float aSigma) const MOZ_OVERRIDE; virtual TemporaryRef CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, - ExtendMode aExtendMode = ExtendMode::CLAMP) const; + ExtendMode aExtendMode = ExtendMode::CLAMP) const MOZ_OVERRIDE; - virtual TemporaryRef CreateFilter(FilterType aType); + virtual TemporaryRef CreateFilter(FilterType aType) MOZ_OVERRIDE; - virtual void *GetNativeSurface(NativeSurfaceType aType); + virtual void *GetNativeSurface(NativeSurfaceType aType) MOZ_OVERRIDE; bool Init(cairo_surface_t* aSurface, const IntSize& aSize, SurfaceFormat* aFormat = nullptr); bool Init(const IntSize& aSize, SurfaceFormat aFormat); bool Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat); - virtual void SetTransform(const Matrix& aTransform); + virtual void SetTransform(const Matrix& aTransform) MOZ_OVERRIDE; // Call to set up aContext for drawing (with the current transform, etc). // Pass the path you're going to be using if you have one. diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/DrawTargetCG.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/DrawTargetCG.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/DrawTargetCG.h 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/DrawTargetCG.h 2015-01-09 12:37:14.000000000 +0000 @@ -94,7 +94,7 @@ class GlyphRenderingOptionsCG : public GlyphRenderingOptions { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GlyphRenderingOptionsCG) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GlyphRenderingOptionsCG, MOZ_OVERRIDE) explicit GlyphRenderingOptionsCG(const Color &aFontSmoothingBackgroundColor) : mFontSmoothingBackgroundColor(aFontSmoothingBackgroundColor) @@ -111,33 +111,33 @@ class DrawTargetCG : public DrawTarget { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetCG) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetCG, MOZ_OVERRIDE) friend class BorrowedCGContext; friend class SourceSurfaceCGBitmapContext; DrawTargetCG(); virtual ~DrawTargetCG(); virtual DrawTargetType GetType() const MOZ_OVERRIDE; - virtual BackendType GetBackendType() const; - virtual TemporaryRef Snapshot(); + virtual BackendType GetBackendType() const MOZ_OVERRIDE; + virtual TemporaryRef Snapshot() MOZ_OVERRIDE; virtual void DrawSurface(SourceSurface *aSurface, const Rect &aDest, const Rect &aSource, const DrawSurfaceOptions &aSurfOptions = DrawSurfaceOptions(), - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void DrawFilter(FilterNode *aNode, const Rect &aSourceRect, const Point &aDestPoint, - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void MaskSurface(const Pattern &aSource, SourceSurface *aMask, Point aOffset, - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void FillRect(const Rect &aRect, const Pattern &aPattern, - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; //XXX: why do we take a reference to SurfaceFormat? @@ -146,40 +146,40 @@ bool Init(CGContextRef cgContext, const IntSize &aSize); // Flush if using IOSurface context - virtual void Flush(); + virtual void Flush() MOZ_OVERRIDE; - virtual void DrawSurfaceWithShadow(SourceSurface *, const Point &, const Color &, const Point &, Float, CompositionOp); - virtual void ClearRect(const Rect &); - virtual void CopySurface(SourceSurface *, const IntRect&, const IntPoint&); - virtual void StrokeRect(const Rect &, const Pattern &, const StrokeOptions&, const DrawOptions&); - virtual void StrokeLine(const Point &, const Point &, const Pattern &, const StrokeOptions &, const DrawOptions &); - virtual void Stroke(const Path *, const Pattern &, const StrokeOptions &, const DrawOptions &); - virtual void Fill(const Path *, const Pattern &, const DrawOptions &); - virtual void FillGlyphs(ScaledFont *, const GlyphBuffer&, const Pattern &, const DrawOptions &, const GlyphRenderingOptions *); + virtual void DrawSurfaceWithShadow(SourceSurface *, const Point &, const Color &, const Point &, Float, CompositionOp) MOZ_OVERRIDE; + virtual void ClearRect(const Rect &) MOZ_OVERRIDE; + virtual void CopySurface(SourceSurface *, const IntRect&, const IntPoint&) MOZ_OVERRIDE; + virtual void StrokeRect(const Rect &, const Pattern &, const StrokeOptions&, const DrawOptions&) MOZ_OVERRIDE; + virtual void StrokeLine(const Point &, const Point &, const Pattern &, const StrokeOptions &, const DrawOptions &) MOZ_OVERRIDE; + virtual void Stroke(const Path *, const Pattern &, const StrokeOptions &, const DrawOptions &) MOZ_OVERRIDE; + virtual void Fill(const Path *, const Pattern &, const DrawOptions &) MOZ_OVERRIDE; + virtual void FillGlyphs(ScaledFont *, const GlyphBuffer&, const Pattern &, const DrawOptions &, const GlyphRenderingOptions *) MOZ_OVERRIDE; virtual void Mask(const Pattern &aSource, const Pattern &aMask, - const DrawOptions &aOptions = DrawOptions()); - virtual void PushClip(const Path *); - virtual void PushClipRect(const Rect &aRect); - virtual void PopClip(); - virtual TemporaryRef CreateSourceSurfaceFromNativeSurface(const NativeSurface&) const { return nullptr;} - virtual TemporaryRef CreateSimilarDrawTarget(const IntSize &, SurfaceFormat) const; - virtual TemporaryRef CreatePathBuilder(FillRule) const; + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; + virtual void PushClip(const Path *) MOZ_OVERRIDE; + virtual void PushClipRect(const Rect &aRect) MOZ_OVERRIDE; + virtual void PopClip() MOZ_OVERRIDE; + virtual TemporaryRef CreateSourceSurfaceFromNativeSurface(const NativeSurface&) const MOZ_OVERRIDE { return nullptr;} + virtual TemporaryRef CreateSimilarDrawTarget(const IntSize &, SurfaceFormat) const MOZ_OVERRIDE; + virtual TemporaryRef CreatePathBuilder(FillRule) const MOZ_OVERRIDE; virtual TemporaryRef CreateGradientStops(GradientStop *, uint32_t, - ExtendMode aExtendMode = ExtendMode::CLAMP) const; - virtual TemporaryRef CreateFilter(FilterType aType); + ExtendMode aExtendMode = ExtendMode::CLAMP) const MOZ_OVERRIDE; + virtual TemporaryRef CreateFilter(FilterType aType) MOZ_OVERRIDE; - virtual void *GetNativeSurface(NativeSurfaceType); + virtual void *GetNativeSurface(NativeSurfaceType) MOZ_OVERRIDE; - virtual IntSize GetSize() { return mSize; } + virtual IntSize GetSize() MOZ_OVERRIDE { return mSize; } /* This is for creating good compatible surfaces */ virtual TemporaryRef CreateSourceSurfaceFromData(unsigned char *aData, const IntSize &aSize, int32_t aStride, - SurfaceFormat aFormat) const; - virtual TemporaryRef OptimizeSourceSurface(SourceSurface *aSurface) const; + SurfaceFormat aFormat) const MOZ_OVERRIDE; + virtual TemporaryRef OptimizeSourceSurface(SourceSurface *aSurface) const MOZ_OVERRIDE; CGContextRef GetCGContext() { return mCg; } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/DrawTargetD2D1.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/DrawTargetD2D1.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/DrawTargetD2D1.cpp 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/DrawTargetD2D1.cpp 2015-01-09 12:37:14.000000000 +0000 @@ -411,7 +411,7 @@ const StrokeOptions &aStrokeOptions, const DrawOptions &aOptions) { - if (aPath->GetBackendType() != BackendType::DIRECT2D) { + if (aPath->GetBackendType() != BackendType::DIRECT2D1_1) { gfxDebug() << *this << ": Ignoring drawing call for incompatible path."; return; } @@ -434,7 +434,7 @@ const Pattern &aPattern, const DrawOptions &aOptions) { - if (aPath->GetBackendType() != BackendType::DIRECT2D) { + if (aPath->GetBackendType() != BackendType::DIRECT2D1_1) { gfxDebug() << *this << ": Ignoring drawing call for incompatible path."; return; } @@ -560,7 +560,7 @@ void DrawTargetD2D1::PushClip(const Path *aPath) { - if (aPath->GetBackendType() != BackendType::DIRECT2D) { + if (aPath->GetBackendType() != BackendType::DIRECT2D1_1) { gfxDebug() << *this << ": Ignoring clipping call for incompatible path."; return; } @@ -694,7 +694,7 @@ sink->SetFillMode(D2D1_FILL_MODE_WINDING); } - return new PathBuilderD2D(sink, path, aFillRule); + return new PathBuilderD2D(sink, path, aFillRule, BackendType::DIRECT2D1_1); } TemporaryRef diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/DrawTargetD2D.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/DrawTargetD2D.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/DrawTargetD2D.cpp 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/DrawTargetD2D.cpp 2015-01-09 12:37:14.000000000 +0000 @@ -6,9 +6,7 @@ #include #include "DrawTargetD2D.h" #include "SourceSurfaceD2D.h" -#ifdef USE_D2D1_1 #include "SourceSurfaceD2D1.h" -#endif #include "SourceSurfaceD2DTarget.h" #include "ShadersD2D.h" #include "PathD2D.h" @@ -21,9 +19,7 @@ #include "mozilla/Constants.h" #include "FilterNodeSoftware.h" -#ifdef USE_D2D1_1 #include "FilterNodeD2D1.h" -#endif #include @@ -323,7 +319,6 @@ return bitmap; } -#ifdef USE_D2D1_1 TemporaryRef DrawTargetD2D::GetImageForSurface(SourceSurface *aSurface) { @@ -334,7 +329,6 @@ return image; } -#endif void DrawTargetD2D::DrawSurface(SourceSurface *aSurface, @@ -369,7 +363,6 @@ const Point &aDestPoint, const DrawOptions &aOptions) { -#ifdef USE_D2D1_1 RefPtr dc; HRESULT hr; @@ -395,7 +388,6 @@ return; } } -#endif if (aNode->GetBackendType() != FILTER_BACKEND_SOFTWARE) { gfxWarning() << "Invalid filter backend passed to DrawTargetD2D!"; @@ -1282,7 +1274,7 @@ sink->SetFillMode(D2D1_FILL_MODE_WINDING); } - return new PathBuilderD2D(sink, path, aFillRule); + return new PathBuilderD2D(sink, path, aFillRule, BackendType::DIRECT2D); } TemporaryRef @@ -1314,14 +1306,12 @@ TemporaryRef DrawTargetD2D::CreateFilter(FilterType aType) { -#ifdef USE_D2D1_1 RefPtr dc; HRESULT hr = mRT->QueryInterface((ID2D1DeviceContext**)byRef(dc)); if (SUCCEEDED(hr)) { return FilterNodeD2D1::Create(dc, aType); } -#endif return FilterNodeSoftware::Create(aType); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/DrawTargetD2D.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/DrawTargetD2D.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/DrawTargetD2D.h 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/DrawTargetD2D.h 2015-01-09 12:37:14.000000000 +0000 @@ -142,9 +142,7 @@ TemporaryRef GetCachedLayer(); void PopCachedLayer(ID2D1RenderTarget *aRT); -#ifdef USE_D2D1_1 TemporaryRef GetImageForSurface(SourceSurface *aSurface); -#endif static ID2D1Factory *factory(); static void CleanupD2D(); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/DrawTargetDual.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/DrawTargetDual.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/DrawTargetDual.h 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/DrawTargetDual.h 2015-01-09 12:37:14.000000000 +0000 @@ -18,9 +18,9 @@ namespace gfx { #define FORWARD_FUNCTION(funcName) \ - virtual void funcName() { mA->funcName(); mB->funcName(); } + virtual void funcName() MOZ_OVERRIDE { mA->funcName(); mB->funcName(); } #define FORWARD_FUNCTION1(funcName, var1Type, var1Name) \ - virtual void funcName(var1Type var1Name) { mA->funcName(var1Name); mB->funcName(var1Name); } + virtual void funcName(var1Type var1Name) MOZ_OVERRIDE { mA->funcName(var1Name); mB->funcName(var1Name); } /* This is a special type of DrawTarget. It duplicates all drawing calls * accross two drawtargets. An exception to this is when a snapshot of another @@ -35,7 +35,7 @@ class DrawTargetDual : public DrawTarget { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetDual) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetDual, MOZ_OVERRIDE) DrawTargetDual(DrawTarget *aA, DrawTarget *aB) : mA(aA) , mB(aB) @@ -44,9 +44,9 @@ } virtual DrawTargetType GetType() const MOZ_OVERRIDE { return mA->GetType(); } - virtual BackendType GetBackendType() const { return mA->GetBackendType(); } - virtual TemporaryRef Snapshot() { return new SourceSurfaceDual(mA, mB); } - virtual IntSize GetSize() { return mA->GetSize(); } + virtual BackendType GetBackendType() const MOZ_OVERRIDE { return mA->GetBackendType(); } + virtual TemporaryRef Snapshot() MOZ_OVERRIDE { return new SourceSurfaceDual(mA, mB); } + virtual IntSize GetSize() MOZ_OVERRIDE { return mA->GetSize(); } FORWARD_FUNCTION(Flush) FORWARD_FUNCTION1(PushClip, const Path *, aPath) @@ -54,19 +54,19 @@ FORWARD_FUNCTION(PopClip) FORWARD_FUNCTION1(ClearRect, const Rect &, aRect) - virtual void SetTransform(const Matrix &aTransform) { + virtual void SetTransform(const Matrix &aTransform) MOZ_OVERRIDE { mTransform = aTransform; mA->SetTransform(aTransform); mB->SetTransform(aTransform); } virtual void DrawSurface(SourceSurface *aSurface, const Rect &aDest, const Rect & aSource, - const DrawSurfaceOptions &aSurfOptions, const DrawOptions &aOptions); + const DrawSurfaceOptions &aSurfOptions, const DrawOptions &aOptions) MOZ_OVERRIDE; virtual void DrawFilter(FilterNode *aNode, const Rect &aSourceRect, const Point &aDestPoint, - const DrawOptions &aOptions = DrawOptions()) + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE { mA->DrawFilter(aNode, aSourceRect, aDestPoint, aOptions); mB->DrawFilter(aNode, aSourceRect, aDestPoint, aOptions); @@ -75,58 +75,58 @@ virtual void MaskSurface(const Pattern &aSource, SourceSurface *aMask, Point aOffset, - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void DrawSurfaceWithShadow(SourceSurface *aSurface, const Point &aDest, const Color &aColor, const Point &aOffset, - Float aSigma, CompositionOp aOp); + Float aSigma, CompositionOp aOp) MOZ_OVERRIDE; virtual void CopySurface(SourceSurface *aSurface, const IntRect &aSourceRect, - const IntPoint &aDestination); + const IntPoint &aDestination) MOZ_OVERRIDE; - virtual void FillRect(const Rect &aRect, const Pattern &aPattern, const DrawOptions &aOptions); + virtual void FillRect(const Rect &aRect, const Pattern &aPattern, const DrawOptions &aOptions) MOZ_OVERRIDE; virtual void StrokeRect(const Rect &aRect, const Pattern &aPattern, - const StrokeOptions &aStrokeOptions, const DrawOptions &aOptions); + const StrokeOptions &aStrokeOptions, const DrawOptions &aOptions) MOZ_OVERRIDE; virtual void StrokeLine(const Point &aStart, const Point &aEnd, const Pattern &aPattern, - const StrokeOptions &aStrokeOptions, const DrawOptions &aOptions); + const StrokeOptions &aStrokeOptions, const DrawOptions &aOptions) MOZ_OVERRIDE; virtual void Stroke(const Path *aPath, const Pattern &aPattern, - const StrokeOptions &aStrokeOptions, const DrawOptions &aOptions); + const StrokeOptions &aStrokeOptions, const DrawOptions &aOptions) MOZ_OVERRIDE; - virtual void Fill(const Path *aPath, const Pattern &aPattern, const DrawOptions &aOptions); + virtual void Fill(const Path *aPath, const Pattern &aPattern, const DrawOptions &aOptions) MOZ_OVERRIDE; virtual void FillGlyphs(ScaledFont *aScaledFont, const GlyphBuffer &aBuffer, const Pattern &aPattern, const DrawOptions &aOptions, - const GlyphRenderingOptions *aRenderingOptions); + const GlyphRenderingOptions *aRenderingOptions) MOZ_OVERRIDE; - virtual void Mask(const Pattern &aSource, const Pattern &aMask, const DrawOptions &aOptions); + virtual void Mask(const Pattern &aSource, const Pattern &aMask, const DrawOptions &aOptions) MOZ_OVERRIDE; virtual TemporaryRef CreateSourceSurfaceFromData(unsigned char *aData, const IntSize &aSize, int32_t aStride, - SurfaceFormat aFormat) const + SurfaceFormat aFormat) const MOZ_OVERRIDE { return mA->CreateSourceSurfaceFromData(aData, aSize, aStride, aFormat); } - virtual TemporaryRef OptimizeSourceSurface(SourceSurface *aSurface) const + virtual TemporaryRef OptimizeSourceSurface(SourceSurface *aSurface) const MOZ_OVERRIDE { return mA->OptimizeSourceSurface(aSurface); } virtual TemporaryRef - CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const + CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const MOZ_OVERRIDE { return mA->CreateSourceSurfaceFromNativeSurface(aSurface); } virtual TemporaryRef - CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const; + CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const MOZ_OVERRIDE; - virtual TemporaryRef CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const + virtual TemporaryRef CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const MOZ_OVERRIDE { return mA->CreatePathBuilder(aFillRule); } @@ -134,22 +134,22 @@ virtual TemporaryRef CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, - ExtendMode aExtendMode = ExtendMode::CLAMP) const + ExtendMode aExtendMode = ExtendMode::CLAMP) const MOZ_OVERRIDE { return mA->CreateGradientStops(aStops, aNumStops, aExtendMode); } - virtual TemporaryRef CreateFilter(FilterType aType) + virtual TemporaryRef CreateFilter(FilterType aType) MOZ_OVERRIDE { return mA->CreateFilter(aType); } - virtual void *GetNativeSurface(NativeSurfaceType aType) + virtual void *GetNativeSurface(NativeSurfaceType aType) MOZ_OVERRIDE { return nullptr; } - virtual bool IsDualDrawTarget() const + virtual bool IsDualDrawTarget() const MOZ_OVERRIDE { return true; } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/DrawTargetRecording.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/DrawTargetRecording.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/DrawTargetRecording.cpp 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/DrawTargetRecording.cpp 2015-01-09 12:37:15.000000000 +0000 @@ -80,7 +80,7 @@ class FilterNodeRecording : public FilterNode { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeRecording) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeRecording, MOZ_OVERRIDE) using FilterNode::SetAttribute; FilterNodeRecording(FilterNode *aFinalFilterNode, DrawEventRecorderPrivate *aRecorder) @@ -93,12 +93,12 @@ mRecorder->RecordEvent(RecordedFilterNodeDestruction(this)); } - virtual void SetInput(uint32_t aIndex, SourceSurface *aSurface) + virtual void SetInput(uint32_t aIndex, SourceSurface *aSurface) MOZ_OVERRIDE { mRecorder->RecordEvent(RecordedFilterNodeSetInput(this, aIndex, aSurface)); mFinalFilterNode->SetInput(aIndex, GetSourceSurface(aSurface)); } - virtual void SetInput(uint32_t aIndex, FilterNode *aFilter) + virtual void SetInput(uint32_t aIndex, FilterNode *aFilter) MOZ_OVERRIDE { FilterNode *finalNode = aFilter; if (aFilter->GetBackendType() != FILTER_BACKEND_RECORDING) { @@ -113,7 +113,7 @@ #define FORWARD_SET_ATTRIBUTE(type, argtype) \ - virtual void SetAttribute(uint32_t aIndex, type aValue) { \ + virtual void SetAttribute(uint32_t aIndex, type aValue) MOZ_OVERRIDE { \ mRecorder->RecordEvent(RecordedFilterNodeSetAttribute(this, aIndex, aValue, RecordedFilterNodeSetAttribute::ARGTYPE_##argtype)); \ mFinalFilterNode->SetAttribute(aIndex, aValue); \ } @@ -133,7 +133,7 @@ #undef FORWARD_SET_ATTRIBUTE - virtual void SetAttribute(uint32_t aIndex, const Float* aFloat, uint32_t aSize) { + virtual void SetAttribute(uint32_t aIndex, const Float* aFloat, uint32_t aSize) MOZ_OVERRIDE { mRecorder->RecordEvent(RecordedFilterNodeSetAttribute(this, aIndex, aFloat, aSize)); mFinalFilterNode->SetAttribute(aIndex, aFloat, aSize); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/DrawTargetRecording.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/DrawTargetRecording.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/DrawTargetRecording.h 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/DrawTargetRecording.h 2015-01-09 12:37:15.000000000 +0000 @@ -15,22 +15,22 @@ class DrawTargetRecording : public DrawTarget { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetRecording) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetRecording, MOZ_OVERRIDE) DrawTargetRecording(DrawEventRecorder *aRecorder, DrawTarget *aDT, bool aHasData = false); ~DrawTargetRecording(); virtual DrawTargetType GetType() const MOZ_OVERRIDE { return mFinalDT->GetType(); } - virtual BackendType GetBackendType() const { return mFinalDT->GetBackendType(); } + virtual BackendType GetBackendType() const MOZ_OVERRIDE { return mFinalDT->GetBackendType(); } - virtual TemporaryRef Snapshot(); + virtual TemporaryRef Snapshot() MOZ_OVERRIDE; - virtual IntSize GetSize() { return mFinalDT->GetSize(); } + virtual IntSize GetSize() MOZ_OVERRIDE { return mFinalDT->GetSize(); } /* Ensure that the DrawTarget backend has flushed all drawing operations to * this draw target. This must be called before using the backing surface of * this draw target outside of GFX 2D code. */ - virtual void Flush() { mFinalDT->Flush(); } + virtual void Flush() MOZ_OVERRIDE { mFinalDT->Flush(); } /* * Draw a surface to the draw target. Possibly doing partial drawing or @@ -47,12 +47,12 @@ const Rect &aDest, const Rect &aSource, const DrawSurfaceOptions &aSurfOptions = DrawSurfaceOptions(), - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void DrawFilter(FilterNode *aNode, const Rect &aSourceRect, const Point &aDestPoint, - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; /* * Blend a surface to the draw target with a shadow. The shadow is drawn as a @@ -73,7 +73,7 @@ const Color &aColor, const Point &aOffset, Float aSigma, - CompositionOp aOperator); + CompositionOp aOperator) MOZ_OVERRIDE; /* * Clear a rectangle on the draw target to transparent black. This will @@ -81,7 +81,7 @@ * * aRect Rectangle to clear */ - virtual void ClearRect(const Rect &aRect); + virtual void ClearRect(const Rect &aRect) MOZ_OVERRIDE; /* * This is essentially a 'memcpy' between two surfaces. It moves a pixel @@ -94,7 +94,7 @@ */ virtual void CopySurface(SourceSurface *aSurface, const IntRect &aSourceRect, - const IntPoint &aDestination); + const IntPoint &aDestination) MOZ_OVERRIDE; /* * Fill a rectangle on the DrawTarget with a certain source pattern. @@ -105,7 +105,7 @@ */ virtual void FillRect(const Rect &aRect, const Pattern &aPattern, - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; /* * Stroke a rectangle on the DrawTarget with a certain source pattern. @@ -117,7 +117,7 @@ virtual void StrokeRect(const Rect &aRect, const Pattern &aPattern, const StrokeOptions &aStrokeOptions = StrokeOptions(), - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; /* * Stroke a line on the DrawTarget with a certain source pattern. @@ -131,7 +131,7 @@ const Point &aEnd, const Pattern &aPattern, const StrokeOptions &aStrokeOptions = StrokeOptions(), - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; /* * Stroke a path on the draw target with a certain source pattern. @@ -144,7 +144,7 @@ virtual void Stroke(const Path *aPath, const Pattern &aPattern, const StrokeOptions &aStrokeOptions = StrokeOptions(), - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; /* * Fill a path on the draw target with a certain source pattern. @@ -155,7 +155,7 @@ */ virtual void Fill(const Path *aPath, const Pattern &aPattern, - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; /* * Fill a series of clyphs on the draw target with a certain source pattern. @@ -164,7 +164,7 @@ const GlyphBuffer &aBuffer, const Pattern &aPattern, const DrawOptions &aOptions = DrawOptions(), - const GlyphRenderingOptions *aRenderingOptions = nullptr); + const GlyphRenderingOptions *aRenderingOptions = nullptr) MOZ_OVERRIDE; /* * This takes a source pattern and a mask, and composites the source pattern @@ -177,19 +177,19 @@ */ virtual void Mask(const Pattern &aSource, const Pattern &aMask, - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void MaskSurface(const Pattern &aSource, SourceSurface *aMask, Point aOffset, - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; /* * Push a clip to the DrawTarget. * * aPath The path to clip to */ - virtual void PushClip(const Path *aPath); + virtual void PushClip(const Path *aPath) MOZ_OVERRIDE; /* * Push an axis-aligned rectangular clip to the DrawTarget. This rectangle @@ -197,12 +197,12 @@ * * aRect The rect to clip to */ - virtual void PushClipRect(const Rect &aRect); + virtual void PushClipRect(const Rect &aRect) MOZ_OVERRIDE; /* Pop a clip from the DrawTarget. A pop without a corresponding push will * be ignored. */ - virtual void PopClip(); + virtual void PopClip() MOZ_OVERRIDE; /* * Create a SourceSurface optimized for use with this DrawTarget from @@ -213,14 +213,14 @@ virtual TemporaryRef CreateSourceSurfaceFromData(unsigned char *aData, const IntSize &aSize, int32_t aStride, - SurfaceFormat aFormat) const; + SurfaceFormat aFormat) const MOZ_OVERRIDE; /* * Create a SourceSurface optimized for use with this DrawTarget from * an arbitrary other SourceSurface. This may return aSourceSurface or some * other existing surface. */ - virtual TemporaryRef OptimizeSourceSurface(SourceSurface *aSurface) const; + virtual TemporaryRef OptimizeSourceSurface(SourceSurface *aSurface) const MOZ_OVERRIDE; /* * Create a SourceSurface for a type of NativeSurface. This may fail if the @@ -228,13 +228,13 @@ * in. */ virtual TemporaryRef - CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const; + CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const MOZ_OVERRIDE; /* * Create a DrawTarget whose snapshot is optimized for use with this DrawTarget. */ virtual TemporaryRef - CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const; + CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const MOZ_OVERRIDE; /* * Create a path builder with the specified fillmode. @@ -243,7 +243,7 @@ * ID2D1SimplifiedGeometrySink requires the fill mode * to be set before calling BeginFigure(). */ - virtual TemporaryRef CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const; + virtual TemporaryRef CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const MOZ_OVERRIDE; /* * Create a GradientStops object that holds information about a set of @@ -258,20 +258,20 @@ virtual TemporaryRef CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, - ExtendMode aExtendMode = ExtendMode::CLAMP) const; + ExtendMode aExtendMode = ExtendMode::CLAMP) const MOZ_OVERRIDE; - virtual TemporaryRef CreateFilter(FilterType aType); + virtual TemporaryRef CreateFilter(FilterType aType) MOZ_OVERRIDE; /* * Set a transform on the surface, this transform is applied at drawing time * to both the mask and source of the operation. */ - virtual void SetTransform(const Matrix &aTransform); + virtual void SetTransform(const Matrix &aTransform) MOZ_OVERRIDE; /* Tries to get a native surface for a DrawTarget, this may fail if the * draw target cannot convert to this surface type. */ - virtual void *GetNativeSurface(NativeSurfaceType aType) { return mFinalDT->GetNativeSurface(aType); } + virtual void *GetNativeSurface(NativeSurfaceType aType) MOZ_OVERRIDE { return mFinalDT->GetNativeSurface(aType); } private: Path *GetPathForPathRecording(const Path *aPath) const; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/DrawTargetSkia.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/DrawTargetSkia.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/DrawTargetSkia.h 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/DrawTargetSkia.h 2015-01-09 12:37:15.000000000 +0000 @@ -28,82 +28,82 @@ class DrawTargetSkia : public DrawTarget { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetSkia) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetSkia, MOZ_OVERRIDE) DrawTargetSkia(); virtual ~DrawTargetSkia(); virtual DrawTargetType GetType() const MOZ_OVERRIDE; - virtual BackendType GetBackendType() const { return BackendType::SKIA; } - virtual TemporaryRef Snapshot(); - virtual IntSize GetSize() { return mSize; } - virtual void Flush(); + virtual BackendType GetBackendType() const MOZ_OVERRIDE { return BackendType::SKIA; } + virtual TemporaryRef Snapshot() MOZ_OVERRIDE; + virtual IntSize GetSize() MOZ_OVERRIDE { return mSize; } + virtual void Flush() MOZ_OVERRIDE; virtual void DrawSurface(SourceSurface *aSurface, const Rect &aDest, const Rect &aSource, const DrawSurfaceOptions &aSurfOptions = DrawSurfaceOptions(), - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void DrawFilter(FilterNode *aNode, const Rect &aSourceRect, const Point &aDestPoint, - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void DrawSurfaceWithShadow(SourceSurface *aSurface, const Point &aDest, const Color &aColor, const Point &aOffset, Float aSigma, - CompositionOp aOperator); - virtual void ClearRect(const Rect &aRect); + CompositionOp aOperator) MOZ_OVERRIDE; + virtual void ClearRect(const Rect &aRect) MOZ_OVERRIDE; virtual void CopySurface(SourceSurface *aSurface, const IntRect &aSourceRect, - const IntPoint &aDestination); + const IntPoint &aDestination) MOZ_OVERRIDE; virtual void FillRect(const Rect &aRect, const Pattern &aPattern, - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void StrokeRect(const Rect &aRect, const Pattern &aPattern, const StrokeOptions &aStrokeOptions = StrokeOptions(), - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void StrokeLine(const Point &aStart, const Point &aEnd, const Pattern &aPattern, const StrokeOptions &aStrokeOptions = StrokeOptions(), - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void Stroke(const Path *aPath, const Pattern &aPattern, const StrokeOptions &aStrokeOptions = StrokeOptions(), - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void Fill(const Path *aPath, const Pattern &aPattern, - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void FillGlyphs(ScaledFont *aFont, const GlyphBuffer &aBuffer, const Pattern &aPattern, const DrawOptions &aOptions = DrawOptions(), - const GlyphRenderingOptions *aRenderingOptions = nullptr); + const GlyphRenderingOptions *aRenderingOptions = nullptr) MOZ_OVERRIDE; virtual void Mask(const Pattern &aSource, const Pattern &aMask, - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void MaskSurface(const Pattern &aSource, SourceSurface *aMask, Point aOffset, - const DrawOptions &aOptions = DrawOptions()); - virtual void PushClip(const Path *aPath); - virtual void PushClipRect(const Rect& aRect); - virtual void PopClip(); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; + virtual void PushClip(const Path *aPath) MOZ_OVERRIDE; + virtual void PushClipRect(const Rect& aRect) MOZ_OVERRIDE; + virtual void PopClip() MOZ_OVERRIDE; virtual TemporaryRef CreateSourceSurfaceFromData(unsigned char *aData, const IntSize &aSize, int32_t aStride, - SurfaceFormat aFormat) const; - virtual TemporaryRef OptimizeSourceSurface(SourceSurface *aSurface) const; + SurfaceFormat aFormat) const MOZ_OVERRIDE; + virtual TemporaryRef OptimizeSourceSurface(SourceSurface *aSurface) const MOZ_OVERRIDE; virtual TemporaryRef - CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const; + CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const MOZ_OVERRIDE; virtual TemporaryRef - CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const; - virtual TemporaryRef CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const; - virtual TemporaryRef CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode = ExtendMode::CLAMP) const; - virtual TemporaryRef CreateFilter(FilterType aType); - virtual void SetTransform(const Matrix &aTransform); - virtual void *GetNativeSurface(NativeSurfaceType aType); + CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const MOZ_OVERRIDE; + virtual TemporaryRef CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const MOZ_OVERRIDE; + virtual TemporaryRef CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode = ExtendMode::CLAMP) const MOZ_OVERRIDE; + virtual TemporaryRef CreateFilter(FilterType aType) MOZ_OVERRIDE; + virtual void SetTransform(const Matrix &aTransform) MOZ_OVERRIDE; + virtual void *GetNativeSurface(NativeSurfaceType aType) MOZ_OVERRIDE; bool Init(const IntSize &aSize, SurfaceFormat aFormat); void Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/DrawTargetTiled.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/DrawTargetTiled.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/DrawTargetTiled.h 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/DrawTargetTiled.h 2015-01-09 12:37:15.000000000 +0000 @@ -35,101 +35,101 @@ bool Init(const TileSet& mTiles); - virtual bool IsTiledDrawTarget() const { return true; } + virtual bool IsTiledDrawTarget() const MOZ_OVERRIDE { return true; } virtual DrawTargetType GetType() const MOZ_OVERRIDE { return mTiles[0].mDrawTarget->GetType(); } - virtual BackendType GetBackendType() const { return mTiles[0].mDrawTarget->GetBackendType(); } - virtual TemporaryRef Snapshot(); - virtual IntSize GetSize() { + virtual BackendType GetBackendType() const MOZ_OVERRIDE { return mTiles[0].mDrawTarget->GetBackendType(); } + virtual TemporaryRef Snapshot() MOZ_OVERRIDE; + virtual IntSize GetSize() MOZ_OVERRIDE { MOZ_ASSERT(mRect.width > 0 && mRect.height > 0); return IntSize(mRect.XMost(), mRect.YMost()); } - virtual void Flush(); + virtual void Flush() MOZ_OVERRIDE; virtual void DrawSurface(SourceSurface *aSurface, const Rect &aDest, const Rect &aSource, const DrawSurfaceOptions &aSurfOptions, - const DrawOptions &aOptions); + const DrawOptions &aOptions) MOZ_OVERRIDE; virtual void DrawFilter(FilterNode *aNode, const Rect &aSourceRect, const Point &aDestPoint, - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void DrawSurfaceWithShadow(SourceSurface *aSurface, const Point &aDest, const Color &aColor, const Point &aOffset, Float aSigma, - CompositionOp aOperator) { /* Not implemented */ MOZ_CRASH(); } + CompositionOp aOperator) MOZ_OVERRIDE { /* Not implemented */ MOZ_CRASH(); } - virtual void ClearRect(const Rect &aRect); + virtual void ClearRect(const Rect &aRect) MOZ_OVERRIDE; virtual void MaskSurface(const Pattern &aSource, SourceSurface *aMask, Point aOffset, - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void CopySurface(SourceSurface *aSurface, const IntRect &aSourceRect, - const IntPoint &aDestination); + const IntPoint &aDestination) MOZ_OVERRIDE; virtual void FillRect(const Rect &aRect, const Pattern &aPattern, - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void StrokeRect(const Rect &aRect, const Pattern &aPattern, const StrokeOptions &aStrokeOptions = StrokeOptions(), - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void StrokeLine(const Point &aStart, const Point &aEnd, const Pattern &aPattern, const StrokeOptions &aStrokeOptions = StrokeOptions(), - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void Stroke(const Path *aPath, const Pattern &aPattern, const StrokeOptions &aStrokeOptions = StrokeOptions(), - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void Fill(const Path *aPath, const Pattern &aPattern, - const DrawOptions &aOptions = DrawOptions()); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; virtual void FillGlyphs(ScaledFont *aFont, const GlyphBuffer &aBuffer, const Pattern &aPattern, const DrawOptions &aOptions = DrawOptions(), - const GlyphRenderingOptions *aRenderingOptions = nullptr); + const GlyphRenderingOptions *aRenderingOptions = nullptr) MOZ_OVERRIDE; virtual void Mask(const Pattern &aSource, const Pattern &aMask, - const DrawOptions &aOptions = DrawOptions()); - virtual void PushClip(const Path *aPath); - virtual void PushClipRect(const Rect &aRect); - virtual void PopClip(); + const DrawOptions &aOptions = DrawOptions()) MOZ_OVERRIDE; + virtual void PushClip(const Path *aPath) MOZ_OVERRIDE; + virtual void PushClipRect(const Rect &aRect) MOZ_OVERRIDE; + virtual void PopClip() MOZ_OVERRIDE; - virtual void SetTransform(const Matrix &aTransform); + virtual void SetTransform(const Matrix &aTransform) MOZ_OVERRIDE; virtual TemporaryRef CreateSourceSurfaceFromData(unsigned char *aData, const IntSize &aSize, int32_t aStride, - SurfaceFormat aFormat) const + SurfaceFormat aFormat) const MOZ_OVERRIDE { return mTiles[0].mDrawTarget->CreateSourceSurfaceFromData(aData, aSize, aStride, aFormat); } - virtual TemporaryRef OptimizeSourceSurface(SourceSurface *aSurface) const + virtual TemporaryRef OptimizeSourceSurface(SourceSurface *aSurface) const MOZ_OVERRIDE { return mTiles[0].mDrawTarget->OptimizeSourceSurface(aSurface); } virtual TemporaryRef - CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const + CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const MOZ_OVERRIDE { return mTiles[0].mDrawTarget->CreateSourceSurfaceFromNativeSurface(aSurface); } virtual TemporaryRef - CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const + CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const MOZ_OVERRIDE { return mTiles[0].mDrawTarget->CreateSimilarDrawTarget(aSize, aFormat); } - virtual TemporaryRef CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const + virtual TemporaryRef CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const MOZ_OVERRIDE { return mTiles[0].mDrawTarget->CreatePathBuilder(aFillRule); } @@ -137,11 +137,11 @@ virtual TemporaryRef CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, - ExtendMode aExtendMode = ExtendMode::CLAMP) const + ExtendMode aExtendMode = ExtendMode::CLAMP) const MOZ_OVERRIDE { return mTiles[0].mDrawTarget->CreateGradientStops(aStops, aNumStops, aExtendMode); } - virtual TemporaryRef CreateFilter(FilterType aType) + virtual TemporaryRef CreateFilter(FilterType aType) MOZ_OVERRIDE { return mTiles[0].mDrawTarget->CreateFilter(aType); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/Factory.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/Factory.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/Factory.cpp 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/Factory.cpp 2015-01-09 12:37:15.000000000 +0000 @@ -34,9 +34,7 @@ #ifdef WIN32 #include "DrawTargetD2D.h" -#ifdef USE_D2D1_1 #include "DrawTargetD2D1.h" -#endif #include "ScaledFontDWrite.h" #include #include "HelpersD2D.h" @@ -184,11 +182,9 @@ #ifdef WIN32 ID3D10Device1 *Factory::mD3D10Device; -#ifdef USE_D2D1_1 ID3D11Device *Factory::mD3D11Device; ID2D1Device *Factory::mD2D1Device; #endif -#endif DrawEventRecorder *Factory::mRecorder; @@ -294,7 +290,6 @@ } break; } -#ifdef USE_D2D1_1 case BackendType::DIRECT2D1_1: { RefPtr newTarget; @@ -304,7 +299,6 @@ } break; } -#endif #elif defined XP_MACOSX case BackendType::COREGRAPHICS: case BackendType::COREGRAPHICS_ACCELERATED: @@ -436,6 +430,25 @@ return dt.forget(); } +bool +Factory::DoesBackendSupportDataDrawtarget(BackendType aType) +{ + switch (aType) { + case BackendType::DIRECT2D: + case BackendType::DIRECT2D1_1: + case BackendType::RECORDING: + case BackendType::NONE: + case BackendType::COREGRAPHICS_ACCELERATED: + return false; + case BackendType::CAIRO: + case BackendType::COREGRAPHICS: + case BackendType::SKIA: + return true; + } + + return false; +} + TemporaryRef Factory::CreateScaledFontForNativeFont(const NativeFont &aNativeFont, Float aSize) { @@ -602,7 +615,6 @@ return mD3D10Device; } -#ifdef USE_D2D1_1 TemporaryRef Factory::CreateDrawTargetForD3D11Texture(ID3D11Texture2D *aTexture, SurfaceFormat aFormat) { @@ -637,6 +649,10 @@ mD2D1Device = nullptr; } + if (!aDevice) { + return; + } + RefPtr factory = D2DFactory1(); RefPtr device; @@ -661,7 +677,6 @@ { return !!D2DFactory1(); } -#endif TemporaryRef Factory::CreateDWriteGlyphRenderingOptions(IDWriteRenderingParams *aParams) @@ -684,13 +699,11 @@ void Factory::D2DCleanup() { -#ifdef USE_D2D1_1 if (mD2D1Device) { mD2D1Device->Release(); mD2D1Device = nullptr; } DrawTargetD2D1::CleanupD2D(); -#endif DrawTargetD2D::CleanupD2D(); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/FilterNodeSoftware.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/FilterNodeSoftware.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/FilterNodeSoftware.h 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/FilterNodeSoftware.h 2015-01-09 12:37:15.000000000 +0000 @@ -38,7 +38,7 @@ public FilterInvalidationListener { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeSoftware) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeSoftware, MOZ_OVERRIDE) virtual ~FilterNodeSoftware(); // Factory method, intended to be called from DrawTarget*::CreateFilter. @@ -58,7 +58,7 @@ virtual void RemoveInvalidationListener(FilterInvalidationListener* aListener); // FilterInvalidationListener implementation - virtual void FilterInvalidated(FilterNodeSoftware* aFilter); + virtual void FilterInvalidated(FilterNodeSoftware* aFilter) MOZ_OVERRIDE; protected: @@ -218,7 +218,7 @@ class FilterNodeTransformSoftware : public FilterNodeSoftware { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeTransformSoftware) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeTransformSoftware, MOZ_OVERRIDE) FilterNodeTransformSoftware(); virtual const char* GetName() MOZ_OVERRIDE { return "Transform"; } using FilterNodeSoftware::SetAttribute; @@ -240,7 +240,7 @@ class FilterNodeBlendSoftware : public FilterNodeSoftware { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeBlendSoftware) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeBlendSoftware, MOZ_OVERRIDE) FilterNodeBlendSoftware(); virtual const char* GetName() MOZ_OVERRIDE { return "Blend"; } using FilterNodeSoftware::SetAttribute; @@ -259,7 +259,7 @@ class FilterNodeMorphologySoftware : public FilterNodeSoftware { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeMorphologySoftware) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeMorphologySoftware, MOZ_OVERRIDE) FilterNodeMorphologySoftware(); virtual const char* GetName() MOZ_OVERRIDE { return "Morphology"; } using FilterNodeSoftware::SetAttribute; @@ -280,7 +280,7 @@ class FilterNodeColorMatrixSoftware : public FilterNodeSoftware { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeColorMatrixSoftware) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeColorMatrixSoftware, MOZ_OVERRIDE) virtual const char* GetName() MOZ_OVERRIDE { return "ColorMatrix"; } using FilterNodeSoftware::SetAttribute; virtual void SetAttribute(uint32_t aIndex, const Matrix5x4 &aMatrix) MOZ_OVERRIDE; @@ -300,7 +300,7 @@ class FilterNodeFloodSoftware : public FilterNodeSoftware { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeFloodSoftware) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeFloodSoftware, MOZ_OVERRIDE) virtual const char* GetName() MOZ_OVERRIDE { return "Flood"; } using FilterNodeSoftware::SetAttribute; virtual void SetAttribute(uint32_t aIndex, const Color &aColor) MOZ_OVERRIDE; @@ -317,7 +317,7 @@ class FilterNodeTileSoftware : public FilterNodeSoftware { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeTileSoftware) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeTileSoftware, MOZ_OVERRIDE) virtual const char* GetName() MOZ_OVERRIDE { return "Tile"; } using FilterNodeSoftware::SetAttribute; virtual void SetAttribute(uint32_t aIndex, const IntRect &aSourceRect) MOZ_OVERRIDE; @@ -338,7 +338,7 @@ class FilterNodeComponentTransferSoftware : public FilterNodeSoftware { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeComponentTransferSoftware) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeComponentTransferSoftware, MOZ_OVERRIDE) FilterNodeComponentTransferSoftware(); using FilterNodeSoftware::SetAttribute; @@ -362,7 +362,7 @@ class FilterNodeTableTransferSoftware : public FilterNodeComponentTransferSoftware { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeTableTransferSoftware) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeTableTransferSoftware, MOZ_OVERRIDE) virtual const char* GetName() MOZ_OVERRIDE { return "TableTransfer"; } using FilterNodeComponentTransferSoftware::SetAttribute; virtual void SetAttribute(uint32_t aIndex, const Float* aFloat, uint32_t aSize) MOZ_OVERRIDE; @@ -382,7 +382,7 @@ class FilterNodeDiscreteTransferSoftware : public FilterNodeComponentTransferSoftware { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeDiscreteTransferSoftware) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeDiscreteTransferSoftware, MOZ_OVERRIDE) virtual const char* GetName() MOZ_OVERRIDE { return "DiscreteTransfer"; } using FilterNodeComponentTransferSoftware::SetAttribute; virtual void SetAttribute(uint32_t aIndex, const Float* aFloat, uint32_t aSize) MOZ_OVERRIDE; @@ -402,7 +402,7 @@ class FilterNodeLinearTransferSoftware : public FilterNodeComponentTransferSoftware { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeLinearTransformSoftware) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeLinearTransformSoftware, MOZ_OVERRIDE) FilterNodeLinearTransferSoftware(); virtual const char* GetName() MOZ_OVERRIDE { return "LinearTransfer"; } using FilterNodeComponentTransferSoftware::SetAttribute; @@ -427,7 +427,7 @@ class FilterNodeGammaTransferSoftware : public FilterNodeComponentTransferSoftware { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeGammaTransferSoftware) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeGammaTransferSoftware, MOZ_OVERRIDE) FilterNodeGammaTransferSoftware(); virtual const char* GetName() MOZ_OVERRIDE { return "GammaTransfer"; } using FilterNodeComponentTransferSoftware::SetAttribute; @@ -456,7 +456,7 @@ class FilterNodeConvolveMatrixSoftware : public FilterNodeSoftware { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeConvolveMatrixSoftware) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeConvolveMatrixSoftware, MOZ_OVERRIDE) FilterNodeConvolveMatrixSoftware(); virtual const char* GetName() MOZ_OVERRIDE { return "ConvolveMatrix"; } using FilterNodeSoftware::SetAttribute; @@ -498,7 +498,7 @@ class FilterNodeDisplacementMapSoftware : public FilterNodeSoftware { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeDisplacementMapSoftware) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeDisplacementMapSoftware, MOZ_OVERRIDE) FilterNodeDisplacementMapSoftware(); virtual const char* GetName() MOZ_OVERRIDE { return "DisplacementMap"; } using FilterNodeSoftware::SetAttribute; @@ -522,7 +522,7 @@ class FilterNodeTurbulenceSoftware : public FilterNodeSoftware { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeTurbulenceSoftware) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeTurbulenceSoftware, MOZ_OVERRIDE) FilterNodeTurbulenceSoftware(); virtual const char* GetName() MOZ_OVERRIDE { return "Turbulence"; } using FilterNodeSoftware::SetAttribute; @@ -548,7 +548,7 @@ class FilterNodeArithmeticCombineSoftware : public FilterNodeSoftware { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeArithmeticCombineSoftware) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeArithmeticCombineSoftware, MOZ_OVERRIDE) FilterNodeArithmeticCombineSoftware(); virtual const char* GetName() MOZ_OVERRIDE { return "ArithmeticCombine"; } using FilterNodeSoftware::SetAttribute; @@ -570,7 +570,7 @@ class FilterNodeCompositeSoftware : public FilterNodeSoftware { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeCompositeSoftware) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeCompositeSoftware, MOZ_OVERRIDE) FilterNodeCompositeSoftware(); virtual const char* GetName() MOZ_OVERRIDE { return "Composite"; } using FilterNodeSoftware::SetAttribute; @@ -591,7 +591,7 @@ class FilterNodeBlurXYSoftware : public FilterNodeSoftware { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeBlurXYSoftware) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeBlurXYSoftware, MOZ_OVERRIDE) protected: virtual TemporaryRef Render(const IntRect& aRect) MOZ_OVERRIDE; virtual IntRect GetOutputRectInRect(const IntRect& aRect) MOZ_OVERRIDE; @@ -606,7 +606,7 @@ class FilterNodeGaussianBlurSoftware : public FilterNodeBlurXYSoftware { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeGaussianBlurSoftware) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeGaussianBlurSoftware, MOZ_OVERRIDE) FilterNodeGaussianBlurSoftware(); virtual const char* GetName() MOZ_OVERRIDE { return "GaussianBlur"; } using FilterNodeSoftware::SetAttribute; @@ -622,7 +622,7 @@ class FilterNodeDirectionalBlurSoftware : public FilterNodeBlurXYSoftware { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeDirectionalBlurSoftware) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeDirectionalBlurSoftware, MOZ_OVERRIDE) FilterNodeDirectionalBlurSoftware(); virtual const char* GetName() MOZ_OVERRIDE { return "DirectionalBlur"; } using FilterNodeSoftware::SetAttribute; @@ -640,7 +640,7 @@ class FilterNodeCropSoftware : public FilterNodeSoftware { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeCropSoftware) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeCropSoftware, MOZ_OVERRIDE) virtual const char* GetName() MOZ_OVERRIDE { return "Crop"; } using FilterNodeSoftware::SetAttribute; virtual void SetAttribute(uint32_t aIndex, const Rect &aSourceRect) MOZ_OVERRIDE; @@ -658,7 +658,7 @@ class FilterNodePremultiplySoftware : public FilterNodeSoftware { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodePremultiplySoftware) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodePremultiplySoftware, MOZ_OVERRIDE) virtual const char* GetName() MOZ_OVERRIDE { return "Premultiply"; } protected: virtual TemporaryRef Render(const IntRect& aRect) MOZ_OVERRIDE; @@ -670,7 +670,7 @@ class FilterNodeUnpremultiplySoftware : public FilterNodeSoftware { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeUnpremultiplySoftware) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeUnpremultiplySoftware, MOZ_OVERRIDE) virtual const char* GetName() MOZ_OVERRIDE { return "Unpremultiply"; } protected: virtual TemporaryRef Render(const IntRect& aRect) MOZ_OVERRIDE; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/HelpersD2D.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/HelpersD2D.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/HelpersD2D.h 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/HelpersD2D.h 2015-01-09 12:37:15.000000000 +0000 @@ -6,11 +6,7 @@ #ifndef MOZILLA_GFX_HELPERSD2D_H_ #define MOZILLA_GFX_HELPERSD2D_H_ -#ifndef USE_D2D1_1 -#include "moz-d2d1-1.h" -#else #include -#endif #include @@ -30,9 +26,7 @@ ID2D1Factory* D2DFactory(); -#ifdef USE_D2D1_1 ID2D1Factory1* D2DFactory1(); -#endif static inline D2D1_POINT_2F D2DPoint(const Point &aPoint) { @@ -77,7 +71,6 @@ } } -#ifdef USE_D2D1_1 static inline D2D1_INTERPOLATION_MODE D2DInterpolationMode(const Filter &aFilter) { switch (aFilter) { @@ -102,8 +95,6 @@ return D2D1::Vector3F(aPoint.x, aPoint.y, aPoint.z); } -#endif - static inline D2D1_ANTIALIAS_MODE D2DAAMode(AntialiasMode aMode) { switch (aMode) { @@ -193,7 +184,6 @@ return D2D1::PixelFormat(DXGIFormat(aFormat), D2DAlphaModeForFormat(aFormat)); } -#ifdef USE_D2D1_1 static inline bool D2DSupportsCompositeMode(CompositionOp aOp) { switch(aOp) { @@ -281,7 +271,6 @@ return D2D1_BLEND_MODE_MULTIPLY; } } -#endif static inline bool IsPatternSupportedByD2D(const Pattern &aPattern) { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/moz.build thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/moz.build --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/moz.build 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/moz.build 2015-01-09 12:37:15.000000000 +0000 @@ -52,22 +52,17 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': SOURCES += [ 'DrawTargetD2D.cpp', + 'DrawTargetD2D1.cpp', + 'FilterNodeD2D1.cpp', 'PathD2D.cpp', + 'RadialGradientEffectD2D1.cpp', 'ScaledFontDWrite.cpp', 'ScaledFontWin.cpp', 'SourceSurfaceD2D.cpp', + 'SourceSurfaceD2D1.cpp', 'SourceSurfaceD2DTarget.cpp', ] DEFINES['WIN32'] = True - # For Direct2D 1.1 we require WINSDK_MAXVER 0x06020000 or higher. - if CONFIG['MOZ_ENABLE_DIRECT2D1_1']: - SOURCES += [ - 'DrawTargetD2D1.cpp', - 'FilterNodeD2D1.cpp', - 'RadialGradientEffectD2D1.cpp', - 'SourceSurfaceD2D1.cpp' - ] - DEFINES['USE_D2D1_1'] = True if CONFIG['MOZ_ENABLE_SKIA']: UNIFIED_SOURCES += [ diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/PathD2D.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/PathD2D.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/PathD2D.cpp 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/PathD2D.cpp 2015-01-09 12:37:15.000000000 +0000 @@ -303,7 +303,7 @@ return nullptr; } - return new PathD2D(mGeometry, mFigureActive, mCurrentPoint, mFillRule); + return new PathD2D(mGeometry, mFigureActive, mCurrentPoint, mFillRule, mBackendType); } TemporaryRef @@ -345,7 +345,7 @@ sink); } - RefPtr pathBuilder = new PathBuilderD2D(sink, path, aFillRule); + RefPtr pathBuilder = new PathBuilderD2D(sink, path, aFillRule, mBackendType); pathBuilder->mCurrentPoint = aTransform * mEndPoint; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/PathD2D.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/PathD2D.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/PathD2D.h 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/PathD2D.h 2015-01-09 12:37:15.000000000 +0000 @@ -19,11 +19,12 @@ { public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathBuilderD2D) - PathBuilderD2D(ID2D1GeometrySink *aSink, ID2D1PathGeometry *aGeom, FillRule aFillRule) + PathBuilderD2D(ID2D1GeometrySink *aSink, ID2D1PathGeometry *aGeom, FillRule aFillRule, BackendType aBackendType) : mSink(aSink) , mGeometry(aGeom) , mFigureActive(false) , mFillRule(aFillRule) + , mBackendType(aBackendType) { } virtual ~PathBuilderD2D(); @@ -42,7 +43,7 @@ virtual TemporaryRef Finish(); - virtual BackendType GetBackendType() const { return BackendType::DIRECT2D; } + virtual BackendType GetBackendType() const { return mBackendType; } ID2D1GeometrySink *GetSink() { return mSink; } @@ -58,6 +59,7 @@ Point mCurrentPoint; Point mBeginPoint; FillRule mFillRule; + BackendType mBackendType; }; class PathD2D : public Path @@ -65,14 +67,15 @@ public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathD2D) PathD2D(ID2D1PathGeometry *aGeometry, bool aEndedActive, - const Point &aEndPoint, FillRule aFillRule) + const Point &aEndPoint, FillRule aFillRule, BackendType aBackendType) : mGeometry(aGeometry) , mEndedActive(aEndedActive) , mEndPoint(aEndPoint) , mFillRule(aFillRule) + , mBackendType(aBackendType) {} - virtual BackendType GetBackendType() const { return BackendType::DIRECT2D; } + virtual BackendType GetBackendType() const { return mBackendType; } virtual TemporaryRef CopyToBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const; virtual TemporaryRef TransformedCopyToBuilder(const Matrix &aTransform, @@ -103,6 +106,7 @@ bool mEndedActive; Point mEndPoint; FillRule mFillRule; + BackendType mBackendType; }; } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/SourceSurfaceD2D1.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/SourceSurfaceD2D1.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/2d/SourceSurfaceD2D1.cpp 2015-01-07 22:15:32.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/2d/SourceSurfaceD2D1.cpp 2015-01-09 12:37:15.000000000 +0000 @@ -108,7 +108,13 @@ props.pixelFormat = D2DPixelFormat(mFormat); props.colorContext = nullptr; props.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET; - mDC->CreateBitmap(D2DIntSize(mSize), nullptr, 0, props, (ID2D1Bitmap1**)byRef(mRealizedBitmap)); + HRESULT hr = mDC->CreateBitmap(D2DIntSize(mSize), nullptr, 0, props, (ID2D1Bitmap1**)byRef(mRealizedBitmap)); + + if (FAILED(hr)) { + gfxCriticalError() << "Failed to create bitmap to make DrawTarget copy. Size: " << mSize << " Code: " << hexa(hr); + MarkIndependent(); + return; + } D2D1_POINT_2U point = D2D1::Point2U(0, 0); D2D1_RECT_U rect = D2D1::RectU(0, 0, mSize.width, mSize.height); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/gl/GfxTexturesReporter.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/gl/GfxTexturesReporter.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/gl/GfxTexturesReporter.h 2015-01-07 22:15:33.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/gl/GfxTexturesReporter.h 2015-01-09 12:37:17.000000000 +0000 @@ -49,7 +49,7 @@ } NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport, - nsISupports* aData, bool aAnonymize) + nsISupports* aData, bool aAnonymize) MOZ_OVERRIDE { MOZ_COLLECT_REPORT("gfx-tiles-waste", KIND_OTHER, UNITS_BYTES, sTileWasteAmount, diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/gl/GLContextCGL.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/gl/GLContextCGL.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/gl/GLContextCGL.h 2015-01-07 22:15:33.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/gl/GLContextCGL.h 2015-01-09 12:37:17.000000000 +0000 @@ -27,7 +27,7 @@ NSOpenGLContext *mContext; public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextCGL) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextCGL, MOZ_OVERRIDE) GLContextCGL(const SurfaceCaps& caps, GLContext *shareContext, NSOpenGLContext *context, diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/gl/GLContextEGL.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/gl/GLContextEGL.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/gl/GLContextEGL.h 2015-01-07 22:15:33.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/gl/GLContextEGL.h 2015-01-09 12:37:17.000000000 +0000 @@ -29,7 +29,7 @@ EGLSurface surface); public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextEGL) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextEGL, MOZ_OVERRIDE) GLContextEGL(const SurfaceCaps& caps, GLContext* shareContext, bool isOffscreen, diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/apz/src/APZCTreeManager.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/apz/src/APZCTreeManager.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/apz/src/APZCTreeManager.cpp 2015-01-07 22:15:33.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/apz/src/APZCTreeManager.cpp 2015-01-09 12:37:17.000000000 +0000 @@ -6,6 +6,7 @@ #include "APZCTreeManager.h" #include "AsyncPanZoomController.h" #include "Compositor.h" // for Compositor +#include "HitTestingTreeNode.h" // for HitTestingTreeNode #include "InputBlockState.h" // for InputBlockState #include "InputData.h" // for InputData, etc #include "Layers.h" // for Layer, etc @@ -27,8 +28,14 @@ #include "OverscrollHandoffState.h" // for OverscrollHandoffState #include "LayersLogging.h" // for Stringify -#define APZCTM_LOG(...) -// #define APZCTM_LOG(...) printf_stderr("APZCTM: " __VA_ARGS__) +#define ENABLE_APZCTM_LOGGING 0 +// #define ENABLE_APZCTM_LOGGING 1 + +#if ENABLE_APZCTM_LOGGING +# define APZCTM_LOG(...) printf_stderr("APZCTM: " __VA_ARGS__) +#else +# define APZCTM_LOG(...) +#endif namespace mozilla { namespace layers { @@ -57,9 +64,16 @@ const APZPaintLogHelper mPaintLogger; // State that is updated as we perform the tree build - nsTArray< nsRefPtr > mApzcsToDestroy; + + // A list of nodes that need to be destroyed at the end of the tree building. + // This is initialized with all nodes in the old tree, and nodes are removed + // from it as we reuse them in the new tree. + nsTArray> mNodesToDestroy; + + // This map is populated as we place APZCs into the new tree. Its purpose is + // to facilitate re-using the same APZC for different layers that scroll + // together (and thus have the same ScrollableLayerGuid). std::map mApzcMap; - nsTArray mEventRegions; }; /*static*/ const ScreenMargin @@ -126,23 +140,23 @@ mInputQueue->SetAllowedTouchBehavior(aInputBlockId, aValues); } -/* Flatten the tree of APZC instances into the given nsTArray */ +/* Flatten the tree of nodes into the given nsTArray */ static void -Collect(AsyncPanZoomController* aApzc, nsTArray< nsRefPtr >* aCollection) +Collect(HitTestingTreeNode* aNode, nsTArray>* aCollection) { - if (aApzc) { - aCollection->AppendElement(aApzc); - Collect(aApzc->GetLastChild(), aCollection); - Collect(aApzc->GetPrevSibling(), aCollection); + if (aNode) { + aCollection->AppendElement(aNode); + Collect(aNode->GetLastChild(), aCollection); + Collect(aNode->GetPrevSibling(), aCollection); } } void -APZCTreeManager::UpdatePanZoomControllerTree(CompositorParent* aCompositor, - Layer* aRoot, - bool aIsFirstPaint, - uint64_t aOriginatingLayersId, - uint32_t aPaintSequenceNumber) +APZCTreeManager::UpdateHitTestingTree(CompositorParent* aCompositor, + Layer* aRoot, + bool aIsFirstPaint, + uint64_t aOriginatingLayersId, + uint32_t aPaintSequenceNumber) { if (AsyncPanZoomController::GetThreadAssertionsEnabled()) { Compositor::AssertOnCompositorThread(); @@ -175,36 +189,53 @@ // we are sure that the layer was removed and not just transplanted elsewhere. Doing that // as part of a recursive tree walk is hard and so maintaining a list and removing // APZCs that are still alive is much simpler. - Collect(mRootApzc, &state.mApzcsToDestroy); - mRootApzc = nullptr; + Collect(mRootNode, &state.mNodesToDestroy); + mRootNode = nullptr; if (aRoot) { mApzcTreeLog << "[start]\n"; LayerMetricsWrapper root(aRoot); - UpdatePanZoomControllerTree(state, root, - // aCompositor is null in gtest scenarios - aCompositor ? aCompositor->RootLayerTreeId() : 0, - Matrix4x4(), nullptr, nullptr, nsIntRegion()); + UpdateHitTestingTree(state, root, + // aCompositor is null in gtest scenarios + aCompositor ? aCompositor->RootLayerTreeId() : 0, + Matrix4x4(), nullptr, nullptr); mApzcTreeLog << "[end]\n"; } - MOZ_ASSERT(state.mEventRegions.Length() == 0); - for (size_t i = 0; i < state.mApzcsToDestroy.Length(); i++) { - APZCTM_LOG("Destroying APZC at %p\n", state.mApzcsToDestroy[i].get()); - state.mApzcsToDestroy[i]->Destroy(); - } + for (size_t i = 0; i < state.mNodesToDestroy.Length(); i++) { + APZCTM_LOG("Destroying node at %p with APZC %p\n", + state.mNodesToDestroy[i].get(), + state.mNodesToDestroy[i]->GetApzc()); + state.mNodesToDestroy[i]->Destroy(); + } + +#if ENABLE_APZCTM_LOGGING + // Make the hit-test tree line up with the layer dump + printf_stderr("APZCTreeManager (%p)\n", this); + mRootNode->Dump(" "); +#endif } +// Compute the clip region to be used for a layer with an APZC. This function +// is only called for layers which actually have scrollable metrics and an APZC. static nsIntRegion -ComputeTouchSensitiveRegion(GeckoContentController* aController, - const FrameMetrics& aMetrics, - const nsIntRegion& aObscured) +ComputeClipRegion(GeckoContentController* aController, + const LayerMetricsWrapper& aLayer) { - // Use the composition bounds as the hit test region. + nsIntRegion clipRegion; + if (aLayer.GetClipRect()) { + clipRegion = nsIntRegion(*aLayer.GetClipRect()); + } else { + // if there is no clip on this layer (which should only happen for the + // root scrollable layer in a process) fall back to using the comp + // bounds which should be equivalent. + clipRegion = nsIntRegion(ParentLayerIntRect::ToUntyped( + RoundedToInt(aLayer.Metrics().mCompositionBounds))); + } + // Optionally, the GeckoContentController can provide a touch-sensitive // region that constrains all frames associated with the controller. // In this case we intersect the composition bounds with that region. - ParentLayerRect visible(aMetrics.mCompositionBounds); CSSRect touchSensitiveRegion; if (aController->GetTouchSensitiveRegion(&touchSensitiveRegion)) { // Here we assume 'touchSensitiveRegion' is in the CSS pixels of the @@ -214,19 +245,19 @@ // this approximation may not be accurate in the presence of a css-driven // resolution. LayoutDeviceToParentLayerScale parentCumulativeResolution = - aMetrics.GetCumulativeResolution() - / ParentLayerToLayerScale(aMetrics.mPresShellResolution); - visible = visible.Intersect(touchSensitiveRegion - * aMetrics.GetDevPixelsPerCSSPixel() - * parentCumulativeResolution); + aLayer.Metrics().GetCumulativeResolution() + / ParentLayerToLayerScale(aLayer.Metrics().mPresShellResolution); + // Not sure what rounding option is the most correct here, but if we ever + // figure it out we can change this. For now I'm rounding in to minimize + // the chances of getting a complex region. + nsIntRect extraClip = ParentLayerIntRect::ToUntyped(RoundedIn( + touchSensitiveRegion + * aLayer.Metrics().GetDevPixelsPerCSSPixel() + * parentCumulativeResolution)); + clipRegion.AndWith(extraClip); } - // Not sure what rounding option is the most correct here, but if we ever - // figure it out we can change this. For now I'm rounding in to minimize - // the chances of getting a complex region. - nsIntRegion unobscured; - unobscured.Sub(ParentLayerIntRect::ToUntyped(RoundedIn(visible)), aObscured); - return unobscured; + return clipRegion; } void @@ -241,26 +272,79 @@ << metrics.GetContentDescription().get(); } -AsyncPanZoomController* -APZCTreeManager::PrepareAPZCForLayer(const LayerMetricsWrapper& aLayer, +void +APZCTreeManager::AttachNodeToTree(HitTestingTreeNode* aNode, + HitTestingTreeNode* aParent, + HitTestingTreeNode* aNextSibling) +{ + if (aNextSibling) { + aNextSibling->SetPrevSibling(aNode); + } else if (aParent) { + aParent->SetLastChild(aNode); + } else { + MOZ_ASSERT(!mRootNode); + mRootNode = aNode; + aNode->MakeRoot(); + } +} + +static EventRegions +GetEventRegions(const LayerMetricsWrapper& aLayer) +{ + if (gfxPrefs::LayoutEventRegionsEnabled()) { + return aLayer.GetEventRegions(); + } + return EventRegions(aLayer.GetVisibleRegion()); +} + +already_AddRefed +APZCTreeManager::RecycleOrCreateNode(TreeBuildingState& aState, + AsyncPanZoomController* aApzc) +{ + // Find a node without an APZC and return it. Note that unless the layer tree + // actually changes, this loop should generally do an early-return on the + // first iteration, so it should be cheap in the common case. + for (size_t i = 0; i < aState.mNodesToDestroy.Length(); i++) { + nsRefPtr node = aState.mNodesToDestroy[i]; + if (!node->IsPrimaryHolder()) { + aState.mNodesToDestroy.RemoveElement(node); + node->RecycleWith(aApzc); + return node.forget(); + } + } + nsRefPtr node = new HitTestingTreeNode(aApzc, false); + return node.forget(); +} + +HitTestingTreeNode* +APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer, const FrameMetrics& aMetrics, uint64_t aLayersId, const gfx::Matrix4x4& aAncestorTransform, - const nsIntRegion& aObscured, - AsyncPanZoomController* aParent, - AsyncPanZoomController* aNextSibling, + HitTestingTreeNode* aParent, + HitTestingTreeNode* aNextSibling, TreeBuildingState& aState) { + bool needsApzc = true; if (!aMetrics.IsScrollable()) { - return nullptr; + needsApzc = false; } if (gfxPrefs::LayoutEventRegionsEnabled() && aLayer.IsScrollInfoLayer()) { - return nullptr; + needsApzc = false; } const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(aLayersId); if (!(state && state->mController.get())) { - return nullptr; + needsApzc = false; + } + + nsRefPtr node = nullptr; + if (!needsApzc) { + node = RecycleOrCreateNode(aState, nullptr); + AttachNodeToTree(node, aParent, aNextSibling); + node->SetHitTestData(GetEventRegions(aLayer), aLayer.GetTransform(), + aLayer.GetClipRect() ? Some(nsIntRegion(*aLayer.GetClipRect())) : Nothing()); + return node; } AsyncPanZoomController* apzc = nullptr; @@ -294,25 +378,36 @@ apzc = nullptr; } - // If the layer doesn't have an APZC already, try to find one of our - // pre-existing ones that matches. In particular, if we find an APZC whose - // ScrollableLayerGuid is the same, then we know what happened is that the - // layout of the page changed causing the layer tree to be rebuilt, but the - // underlying content for which the APZC was originally created is still - // there. So it makes sense to pick up that APZC instance again and use it here. - if (apzc == nullptr) { - for (size_t i = 0; i < aState.mApzcsToDestroy.Length(); i++) { - if (aState.mApzcsToDestroy.ElementAt(i)->Matches(guid)) { - apzc = aState.mApzcsToDestroy.ElementAt(i); - break; + // See if we can find an APZC from the previous tree that matches the + // ScrollableLayerGuid from this layer. If there is one, then we know that + // the layout of the page changed causing the layer tree to be rebuilt, but + // the underlying content for the APZC is still there somewhere. Therefore, + // we want to find the APZC instance and continue using it here. + // + // We particularly want to find the primary-holder node from the previous + // tree that matches, because we don't want that node to get destroyed. If + // it does get destroyed, then the APZC will get destroyed along with it by + // definition, but we want to keep that APZC around in the new tree. + // We leave non-primary-holder nodes in the destroy list because we don't + // care about those nodes getting destroyed. + for (size_t i = 0; i < aState.mNodesToDestroy.Length(); i++) { + nsRefPtr n = aState.mNodesToDestroy[i]; + if (n->IsPrimaryHolder() && n->GetApzc() && n->GetApzc()->Matches(guid)) { + node = n; + if (apzc != nullptr) { + // If there is an APZC already then it should match the one from the + // old primary-holder node + MOZ_ASSERT(apzc == node->GetApzc()); } + apzc = node->GetApzc(); + break; } } - // The APZC we get off the layer may have been destroyed previously if the layer was inactive - // or omitted from the layer tree for whatever reason from a layers update. If it later comes - // back it will have a reference to a destroyed APZC and so we need to throw that out and make - // a new one. + // The APZC we get off the layer may have been destroyed previously if the + // layer was inactive or omitted from the layer tree for whatever reason + // from a layers update. If it later comes back it will have a reference to + // a destroyed APZC and so we need to throw that out and make a new one. bool newApzc = (apzc == nullptr || apzc->IsDestroyed()); if (newApzc) { apzc = MakeAPZCInstance(aLayersId, state->mController); @@ -320,41 +415,37 @@ if (state->mCrossProcessParent != nullptr) { apzc->ShareFrameMetricsAcrossProcesses(); } + MOZ_ASSERT(node == nullptr); + node = new HitTestingTreeNode(apzc, true); } else { - // If there was already an APZC for the layer clear the tree pointers - // so that it doesn't continue pointing to APZCs that should no longer + // If we are re-using a node for this layer clear the tree pointers + // so that it doesn't continue pointing to nodes that might no longer // be in the tree. These pointers will get reset properly as we continue - // building the tree. Also remove it from the set of APZCs that are going + // building the tree. Also remove it from the set of nodes that are going // to be destroyed, because it's going to remain active. - aState.mApzcsToDestroy.RemoveElement(apzc); - apzc->SetPrevSibling(nullptr); - apzc->SetLastChild(nullptr); + aState.mNodesToDestroy.RemoveElement(node); + node->SetPrevSibling(nullptr); + node->SetLastChild(nullptr); } + APZCTM_LOG("Using APZC %p for layer %p with identifiers %" PRId64 " %" PRId64 "\n", apzc, aLayer.GetLayer(), aLayersId, aMetrics.GetScrollId()); apzc->NotifyLayersUpdated(aMetrics, aState.mIsFirstPaint && (aLayersId == aState.mOriginatingLayersId)); - nsIntRegion unobscured; - if (!gfxPrefs::LayoutEventRegionsEnabled()) { - unobscured = ComputeTouchSensitiveRegion(state->mController, aMetrics, aObscured); - } - apzc->SetLayerHitTestData(EventRegions(unobscured), aAncestorTransform); - APZCTM_LOG("Setting region %s as visible region for APZC %p\n", - Stringify(unobscured).c_str(), apzc); + // Since this is the first time we are encountering an APZC with this guid, + // the node holding it must be the primary holder. It may be newly-created + // or not, depending on whether it went through the newApzc branch above. + MOZ_ASSERT(node->IsPrimaryHolder() && node->GetApzc() && node->GetApzc()->Matches(guid)); + + nsIntRegion clipRegion = ComputeClipRegion(state->mController, aLayer); + node->SetHitTestData(GetEventRegions(aLayer), aLayer.GetTransform(), Some(clipRegion)); + apzc->SetAncestorTransform(aAncestorTransform); PrintAPZCInfo(aLayer, apzc); // Bind the APZC instance into the tree of APZCs - if (aNextSibling) { - aNextSibling->SetPrevSibling(apzc); - } else if (aParent) { - aParent->SetLastChild(apzc); - } else { - MOZ_ASSERT(!mRootApzc); - mRootApzc = apzc; - apzc->MakeRoot(); - } + AttachNodeToTree(node, aParent, aNextSibling); // For testing, log the parent scroll id of every APZC that has a // parent. This allows test code to reconstruct the APZC tree. @@ -385,49 +476,46 @@ } } + // Add a guid -> APZC mapping for the newly created APZC. insertResult.first->second = apzc; } else { // We already built an APZC earlier in this tree walk, but we have another layer // now that will also be using that APZC. The hit-test region on the APZC needs // to be updated to deal with the new layer's hit region. - // FIXME: Combining this hit test region to the existing hit test region has a bit - // of a problem, because it assumes the z-index of this new region is the same as - // the z-index of the old region (from the previous layer with the same scrollid) - // when in fact that may not be the case. - // Consider the case where we have three layers: A, B, and C. A is at the top in - // z-order and C is at the bottom. A and C share a scrollid and scroll together; but - // B has a different scrollid and scrolls independently. Depending on how B moves - // and the async transform on it, a larger/smaller area of C may be unobscured. - // However, when we combine the hit regions of A and C here we are ignoring the async - // async transform and so we basically assume the same amount of C is always visible - // on top of B. Fixing this doesn't appear to be very easy so I'm leaving it for - // now in the hopes that we won't run into this problem a lot. - if (!gfxPrefs::LayoutEventRegionsEnabled()) { - nsIntRegion unobscured = ComputeTouchSensitiveRegion(state->mController, aMetrics, aObscured); - apzc->AddHitTestRegions(EventRegions(unobscured)); - APZCTM_LOG("Adding region %s to visible region of APZC %p\n", Stringify(unobscured).c_str(), apzc); - } + + node = RecycleOrCreateNode(aState, apzc); + AttachNodeToTree(node, aParent, aNextSibling); + + // Even though different layers associated with a given APZC may be at + // different levels in the layer tree (e.g. one being an uncle of another), + // we require from Layout that the CSS transforms up to their common + // ancestor be the same. + MOZ_ASSERT(aAncestorTransform == apzc->GetAncestorTransform()); + + nsIntRegion clipRegion = ComputeClipRegion(state->mController, aLayer); + node->SetHitTestData(GetEventRegions(aLayer), aLayer.GetTransform(), Some(clipRegion)); } - return apzc; + return node; } -AsyncPanZoomController* -APZCTreeManager::UpdatePanZoomControllerTree(TreeBuildingState& aState, - const LayerMetricsWrapper& aLayer, - uint64_t aLayersId, - const gfx::Matrix4x4& aAncestorTransform, - AsyncPanZoomController* aParent, - AsyncPanZoomController* aNextSibling, - const nsIntRegion& aObscured) +HitTestingTreeNode* +APZCTreeManager::UpdateHitTestingTree(TreeBuildingState& aState, + const LayerMetricsWrapper& aLayer, + uint64_t aLayersId, + const gfx::Matrix4x4& aAncestorTransform, + HitTestingTreeNode* aParent, + HitTestingTreeNode* aNextSibling) { mTreeLock.AssertCurrentThreadOwns(); mApzcTreeLog << aLayer.Name() << '\t'; - AsyncPanZoomController* apzc = PrepareAPZCForLayer(aLayer, + HitTestingTreeNode* node = PrepareNodeForLayer(aLayer, aLayer.Metrics(), aLayersId, aAncestorTransform, - aObscured, aParent, aNextSibling, aState); + aParent, aNextSibling, aState); + MOZ_ASSERT(node); + AsyncPanZoomController* apzc = node->GetApzc(); aLayer.SetApzc(apzc); mApzcTreeLog << '\n'; @@ -445,149 +533,20 @@ ancestorTransform = ancestorTransform * aAncestorTransform; } - uint64_t childLayersId = (aLayer.AsRefLayer() ? aLayer.AsRefLayer()->GetReferentId() : aLayersId); - - nsIntRegion obscured; - if (aLayersId == childLayersId) { - // If the child layer is in the same process, transform - // aObscured from aLayer's ParentLayerPixels to aLayer's LayerPixels, - // which are the children layers' ParentLayerPixels. - // If we cross a process boundary, we assume that we can start with - // an empty obscured region because nothing in the parent process will - // obscure the child process. This may be false. However, not doing this - // definitely runs into a problematic case where the B2G notification - // bar and the keyboard get merged into a single layer that obscures - // all child processes, even though visually they do not. We'd probably - // have to check for mask layers and so on in order to properly handle - // that case. - obscured = aObscured; - obscured.Transform(To3DMatrix(transform).Inverse()); - } - - // If there's no APZC at this level, any APZCs for our child layers will - // have our siblings as their siblings, and our parent as their parent. - AsyncPanZoomController* next = aNextSibling; - if (apzc) { - // Otherwise, use this APZC as the parent going downwards, and start off - // with its first child as the next sibling - aParent = apzc; - next = apzc->GetFirstChild(); - } - - // In our recursive downward traversal, track event regions for layers once - // we encounter an APZC. Push a new empty region on the mEventRegions stack - // which will accumulate the hit area of descendants of aLayer. In general, - // the mEventRegions stack is used to accumulate event regions from descendant - // layers because the event regions for a layer don't include those of its - // children. - if (gfxPrefs::LayoutEventRegionsEnabled() && (apzc || aState.mEventRegions.Length() > 0)) { - aState.mEventRegions.AppendElement(EventRegions()); - } + // Note that |node| at this point will not have any children, otherwise we + // we would have to set next to node->GetFirstChild(). + MOZ_ASSERT(!node->GetFirstChild()); + aParent = node; + HitTestingTreeNode* next = nullptr; + uint64_t childLayersId = (aLayer.AsRefLayer() ? aLayer.AsRefLayer()->GetReferentId() : aLayersId); for (LayerMetricsWrapper child = aLayer.GetLastChild(); child; child = child.GetPrevSibling()) { gfx::TreeAutoIndent indent(mApzcTreeLog); - next = UpdatePanZoomControllerTree(aState, child, childLayersId, - ancestorTransform, aParent, next, - obscured); - - // Each layer obscures its previous siblings, so we augment the obscured - // region as we loop backwards through the children. - nsIntRegion childRegion; - if (gfxPrefs::LayoutEventRegionsEnabled()) { - childRegion = child.GetEventRegions().mHitRegion; - } else { - childRegion = child.GetVisibleRegion(); - } - childRegion.Transform(gfx::To3DMatrix(child.GetTransform())); - if (child.GetClipRect()) { - childRegion.AndWith(*child.GetClipRect()); - } - - obscured.OrWith(childRegion); - } - - if (gfxPrefs::LayoutEventRegionsEnabled() && aState.mEventRegions.Length() > 0) { - // At this point in the code, aState.mEventRegions.LastElement() contains - // the accumulated regions of the non-APZC descendants of |aLayer|. This - // happened in the loop above while we iterated through the descendants of - // |aLayer|. Note that it only includes the non-APZC descendants, because - // if a layer has an APZC, we simply store the regions from that subtree on - // that APZC and don't propagate them upwards in the tree. Because of the - // way we do hit-testing (where the deepest matching APZC is used) it should - // still be ok if we did propagate those regions upwards and included them - // in all the ancestor APZCs. - // - // Also at this point in the code the |obscured| region includes the hit - // regions of children of |aLayer| as well as the hit regions of |aLayer|'s - // younger uncles (i.e. the next-sibling chain of |aLayer|'s parent). - // When we compute the unobscured regions below, we subtract off the - // |obscured| region, but it would also be ok to do this before the above - // loop. At that point |obscured| would only have the uncles' hit regions - // and not the children. The reason this is ok is again because of the way - // we do hit-testing (where the deepest APZC is used) it doesn't matter if - // we count the children as obscuring the parent or not. - - EventRegions unobscured; - unobscured.Sub(aLayer.GetEventRegions(), obscured); - APZCTM_LOG("Picking up unobscured hit region %s from layer %p\n", Stringify(unobscured).c_str(), aLayer.GetLayer()); - - // Take the hit region of the |aLayer|'s subtree (which has already been - // transformed into the coordinate space of |aLayer|) and... - EventRegions subtreeEventRegions = aState.mEventRegions.LastElement(); - aState.mEventRegions.RemoveElementAt(aState.mEventRegions.Length() - 1); - // ... combine it with the hit region for this layer, and then ... - subtreeEventRegions.OrWith(unobscured); - // ... transform it up to the parent layer's coordinate space. - subtreeEventRegions.Transform(To3DMatrix(aLayer.GetTransform())); - if (aLayer.GetClipRect()) { - subtreeEventRegions.AndWith(*aLayer.GetClipRect()); - } - - APZCTM_LOG("After processing layer %p the subtree hit region is %s\n", aLayer.GetLayer(), Stringify(subtreeEventRegions).c_str()); - - // If we have an APZC at this level, intersect the subtree hit region with - // the touch-sensitive region and add it to the APZ's hit test regions. - if (apzc) { - APZCTM_LOG("Adding region %s to visible region of APZC %p\n", Stringify(subtreeEventRegions).c_str(), apzc); - const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(aLayersId); - MOZ_ASSERT(state); - MOZ_ASSERT(state->mController.get()); - CSSRect touchSensitiveRegion; - if (state->mController->GetTouchSensitiveRegion(&touchSensitiveRegion)) { - // Here we assume 'touchSensitiveRegion' is in the CSS pixels of the - // parent frame. To convert it to ParentLayer pixels, we therefore need - // the cumulative resolution of the parent frame. We approximate this as - // the quotient of our cumulative resolution and our pres shell - // resolution; this approximation may not be accurate in the presence of - // a css-driven resolution. - LayoutDeviceToParentLayerScale parentCumulativeResolution = - aLayer.Metrics().GetCumulativeResolution() - / ParentLayerToLayerScale(aLayer.Metrics().mPresShellResolution); - subtreeEventRegions.AndWith(ParentLayerIntRect::ToUntyped( - RoundedIn(touchSensitiveRegion - * aLayer.Metrics().GetDevPixelsPerCSSPixel() - * parentCumulativeResolution))); - } - apzc->AddHitTestRegions(subtreeEventRegions); - } else { - // If we don't have an APZC at this level, carry the subtree hit region - // up to the parent. - MOZ_ASSERT(aState.mEventRegions.Length() > 0); - aState.mEventRegions.LastElement().OrWith(subtreeEventRegions); - } + next = UpdateHitTestingTree(aState, child, childLayersId, + ancestorTransform, aParent, next); } - // Return the APZC that should be the sibling of other APZCs as we continue - // moving towards the first child at this depth in the layer tree. - // If this layer doesn't have an APZC, we promote any APZCs in the subtree - // upwards. Otherwise we fall back to the aNextSibling that was passed in. - if (apzc) { - return apzc; - } - if (next) { - return next; - } - return aNextSibling; + return node; } nsEventStatus @@ -628,7 +587,7 @@ apzc->GetGuid(aOutTargetGuid); Matrix4x4 transformToGecko = transformToApzc * GetApzcToGeckoTransform(apzc); wheelInput.mOrigin = - TransformTo(transformToGecko, wheelInput.mLocalOrigin); + TransformTo(transformToGecko, wheelInput.mOrigin); } break; } case PANGESTURE_INPUT: { @@ -723,9 +682,7 @@ // the event we send to gecko because we don't know the layer to untransform with // respect to. MonitorAutoLock lock(mTreeLock); - for (AsyncPanZoomController* apzc = mRootApzc; apzc; apzc = apzc->GetPrevSibling()) { - FlushRepaintsRecursively(apzc); - } + FlushRepaintsRecursively(mRootNode); } apzc = GetTargetAPZC(aEvent.mTouches[0].mScreenPoint, aOutHitResult); @@ -1007,8 +964,8 @@ target = GetTargetAPZC(aTargets[0]); } for (size_t i = 1; i < aTargets.Length(); i++) { - nsRefPtr apzc2 = GetTargetAPZC(aTargets[i]); - target = GetMultitouchTarget(target, apzc2); + nsRefPtr apzc = GetTargetAPZC(aTargets[i]); + target = GetMultitouchTarget(target, apzc); } mInputQueue->SetConfirmedTargetApzc(aInputBlockId, target); } @@ -1016,46 +973,55 @@ void APZCTreeManager::SetTargetAPZC(uint64_t aInputBlockId, const ScrollableLayerGuid& aTarget) { - nsRefPtr target = GetTargetAPZC(aTarget); - mInputQueue->SetConfirmedTargetApzc(aInputBlockId, target); + nsRefPtr apzc = GetTargetAPZC(aTarget); + mInputQueue->SetConfirmedTargetApzc(aInputBlockId, apzc); } void APZCTreeManager::UpdateZoomConstraints(const ScrollableLayerGuid& aGuid, const ZoomConstraints& aConstraints) { - nsRefPtr apzc = GetTargetAPZC(aGuid); + nsRefPtr node = GetTargetNode(aGuid, nullptr); + MOZ_ASSERT(!node || node->GetApzc()); // any node returned must have an APZC + // For a given layers id, non-root APZCs inherit the zoom constraints // of their root. - if (apzc && apzc->IsRootForLayersId()) { + if (node && node->GetApzc()->IsRootForLayersId()) { MonitorAutoLock lock(mTreeLock); - UpdateZoomConstraintsRecursively(apzc.get(), aConstraints); + UpdateZoomConstraintsRecursively(node.get(), aConstraints); } } void -APZCTreeManager::UpdateZoomConstraintsRecursively(AsyncPanZoomController* aApzc, +APZCTreeManager::UpdateZoomConstraintsRecursively(HitTestingTreeNode* aNode, const ZoomConstraints& aConstraints) { mTreeLock.AssertCurrentThreadOwns(); - aApzc->UpdateZoomConstraints(aConstraints); - for (AsyncPanZoomController* child = aApzc->GetLastChild(); child; child = child->GetPrevSibling()) { + if (aNode->IsPrimaryHolder()) { + MOZ_ASSERT(aNode->GetApzc()); + aNode->GetApzc()->UpdateZoomConstraints(aConstraints); + } + for (HitTestingTreeNode* child = aNode->GetLastChild(); child; child = child->GetPrevSibling()) { // We can have subtrees with their own layers id - leave those alone. - if (!child->IsRootForLayersId()) { - UpdateZoomConstraintsRecursively(child, aConstraints); + if (child->GetApzc() && child->GetApzc()->IsRootForLayersId()) { + continue; } + UpdateZoomConstraintsRecursively(child, aConstraints); } } void -APZCTreeManager::FlushRepaintsRecursively(AsyncPanZoomController* aApzc) +APZCTreeManager::FlushRepaintsRecursively(HitTestingTreeNode* aNode) { mTreeLock.AssertCurrentThreadOwns(); - aApzc->FlushRepaintForNewInputBlock(); - for (AsyncPanZoomController* child = aApzc->GetLastChild(); child; child = child->GetPrevSibling()) { - FlushRepaintsRecursively(child); + for (HitTestingTreeNode* node = aNode; node; node = node->GetPrevSibling()) { + if (node->IsPrimaryHolder()) { + MOZ_ASSERT(node->GetApzc()); + node->GetApzc()->FlushRepaintForNewInputBlock(); + } + FlushRepaintsRecursively(node->GetLastChild()); } } @@ -1076,12 +1042,19 @@ // This can be done as part of a tree walk but it's easier to // just re-use the Collect method that we need in other places. // If this is too slow feel free to change it to a recursive walk. - nsTArray< nsRefPtr > apzcsToDestroy; - Collect(mRootApzc, &apzcsToDestroy); - for (size_t i = 0; i < apzcsToDestroy.Length(); i++) { - apzcsToDestroy[i]->Destroy(); + nsTArray> nodesToDestroy; + Collect(mRootNode, &nodesToDestroy); + for (size_t i = 0; i < nodesToDestroy.Length(); i++) { + nodesToDestroy[i]->Destroy(); } - mRootApzc = nullptr; + mRootNode = nullptr; +} + +nsRefPtr +APZCTreeManager::GetRootNode() const +{ + MonitorAutoLock lock(mTreeLock); + return mRootNode; } /** @@ -1220,17 +1193,21 @@ } already_AddRefed -APZCTreeManager::GetTargetAPZC(const ScrollableLayerGuid& aGuid) +APZCTreeManager::GetTargetAPZC(const ScrollableLayerGuid& aGuid, + GuidComparator aComparator) +{ + nsRefPtr node = GetTargetNode(aGuid, aComparator); + MOZ_ASSERT(!node || node->GetApzc()); // any node returned must have an APZC + nsRefPtr apzc = node ? node->GetApzc() : nullptr; + return apzc.forget(); +} + +already_AddRefed +APZCTreeManager::GetTargetNode(const ScrollableLayerGuid& aGuid, + GuidComparator aComparator) { MonitorAutoLock lock(mTreeLock); - nsRefPtr target; - // The root may have siblings, check those too - for (AsyncPanZoomController* apzc = mRootApzc; apzc; apzc = apzc->GetPrevSibling()) { - target = FindTargetAPZC(apzc, aGuid); - if (target) { - break; - } - } + nsRefPtr target = FindTargetNode(mRootNode, aGuid, aComparator); return target.forget(); } @@ -1238,17 +1215,11 @@ APZCTreeManager::GetTargetAPZC(const ScreenPoint& aPoint, HitTestResult* aOutHitResult) { MonitorAutoLock lock(mTreeLock); - nsRefPtr target; - // The root may have siblings, so check those too HitTestResult hitResult = NoApzcHit; - for (AsyncPanZoomController* apzc = mRootApzc; apzc; apzc = apzc->GetPrevSibling()) { - target = GetAPZCAtPoint(apzc, aPoint.ToUnknownPoint(), &hitResult); - // If we hit an overscrolled APZC, 'target' will be nullptr but it's still - // a hit so we don't search further siblings. - if (target || (hitResult == OverscrolledApzc)) { - break; - } - } + ParentLayerPoint point = ViewAs(aPoint, + PixelCastJustification::ScreenIsParentLayerForRoot); + nsRefPtr target = GetAPZCAtPoint(mRootNode, point, &hitResult); + // If we are in an overscrolled APZC, we should be returning nullptr. MOZ_ASSERT(!(target && (hitResult == OverscrolledApzc))); if (aOutHitResult) { @@ -1257,6 +1228,13 @@ return target.forget(); } +static bool +GuidComparatorIgnoringPresShell(const ScrollableLayerGuid& aOne, const ScrollableLayerGuid& aTwo) +{ + return aOne.mLayersId == aTwo.mLayersId + && aOne.mScrollId == aTwo.mScrollId; +} + nsRefPtr APZCTreeManager::BuildOverscrollHandoffChain(const nsRefPtr& aInitialTarget) { @@ -1308,7 +1286,9 @@ } } if (!scrollParent) { - scrollParent = FindTargetAPZC(parent, apzc->GetScrollHandoffParentId()); + ScrollableLayerGuid guid(parent->GetGuid().mLayersId, 0, apzc->GetScrollHandoffParentId()); + nsRefPtr scrollParentPtr = GetTargetAPZC(guid, &GuidComparatorIgnoringPresShell); + scrollParent = scrollParentPtr.get(); } apzc = scrollParent; } @@ -1326,122 +1306,129 @@ return result; } -/* Find the apzc in the subtree rooted at aApzc that has the same layers id as - aApzc, and that has the given scroll id. Generally this function should be called - with aApzc being the root of its layers id subtree. */ -AsyncPanZoomController* -APZCTreeManager::FindTargetAPZC(AsyncPanZoomController* aApzc, FrameMetrics::ViewID aScrollId) -{ - mTreeLock.AssertCurrentThreadOwns(); - - if (aApzc->GetGuid().mScrollId == aScrollId) { - return aApzc; - } - for (AsyncPanZoomController* child = aApzc->GetLastChild(); child; child = child->GetPrevSibling()) { - if (child->GetGuid().mLayersId != aApzc->GetGuid().mLayersId) { - continue; - } - AsyncPanZoomController* match = FindTargetAPZC(child, aScrollId); - if (match) { - return match; - } - } - - return nullptr; -} - -AsyncPanZoomController* -APZCTreeManager::FindTargetAPZC(AsyncPanZoomController* aApzc, const ScrollableLayerGuid& aGuid) +HitTestingTreeNode* +APZCTreeManager::FindTargetNode(HitTestingTreeNode* aNode, + const ScrollableLayerGuid& aGuid, + GuidComparator aComparator) { mTreeLock.AssertCurrentThreadOwns(); // This walks the tree in depth-first, reverse order, so that it encounters // APZCs front-to-back on the screen. - for (AsyncPanZoomController* child = aApzc->GetLastChild(); child; child = child->GetPrevSibling()) { - AsyncPanZoomController* match = FindTargetAPZC(child, aGuid); + for (HitTestingTreeNode* node = aNode; node; node = node->GetPrevSibling()) { + HitTestingTreeNode* match = FindTargetNode(node->GetLastChild(), aGuid, aComparator); if (match) { return match; } - } - if (aApzc->Matches(aGuid)) { - return aApzc; + bool matches = false; + if (node->GetApzc()) { + if (aComparator) { + matches = aComparator(aGuid, node->GetApzc()->GetGuid()); + } else { + matches = node->GetApzc()->Matches(aGuid); + } + } + if (matches) { + return node; + } } return nullptr; } AsyncPanZoomController* -APZCTreeManager::GetAPZCAtPoint(AsyncPanZoomController* aApzc, - const Point& aHitTestPoint, +APZCTreeManager::GetAPZCAtPoint(HitTestingTreeNode* aNode, + const ParentLayerPoint& aHitTestPoint, HitTestResult* aOutHitResult) { mTreeLock.AssertCurrentThreadOwns(); - // The comments below assume there is a chain of layers L..R with L and P having APZC instances as - // explained in the comment above GetScreenToApzcTransform. This function will recurse with aApzc at L and P, and the - // comments explain what values are stored in the variables at these two levels. All the comments - // use standard matrix notation where the leftmost matrix in a multiplication is applied first. - - // ancestorUntransform takes points from aApzc's parent APZC's CSS-transformed layer coordinates - // to aApzc's parent layer's layer coordinates. - // It is PC.Inverse() * OC.Inverse() * NC.Inverse() * MC.Inverse() at recursion level for L, - // and RC.Inverse() * QC.Inverse() at recursion level for P. - Matrix4x4 ancestorUntransform = aApzc->GetAncestorTransform().Inverse(); - - // Hit testing for this layer takes place in our parent layer coordinates, - // since the composition bounds (used to initialize the visible rect against - // which we hit test are in those coordinates). - Point4D hitTestPointForThisLayer = ancestorUntransform.ProjectPoint(aHitTestPoint); - APZCTM_LOG("Untransformed %f %f to transient coordinates %f %f for hit-testing APZC %p\n", - aHitTestPoint.x, aHitTestPoint.y, - hitTestPointForThisLayer.x, hitTestPointForThisLayer.y, aApzc); - - // childUntransform takes points from aApzc's parent APZC's CSS-transformed layer coordinates - // to aApzc's CSS-transformed layer coordinates. - // It is PC.Inverse() * OC.Inverse() * NC.Inverse() * MC.Inverse() * LA.Inverse() at L - // and RC.Inverse() * QC.Inverse() * PA.Inverse() at P. - Matrix4x4 childUntransform = ancestorUntransform * Matrix4x4(aApzc->GetCurrentAsyncTransform()).Inverse(); - Point4D hitTestPointForChildLayers = childUntransform.ProjectPoint(aHitTestPoint); - APZCTM_LOG("Untransformed %f %f to layer coordinates %f %f for APZC %p\n", - aHitTestPoint.x, aHitTestPoint.y, - hitTestPointForChildLayers.x, hitTestPointForChildLayers.y, aApzc); - - AsyncPanZoomController* result = nullptr; // This walks the tree in depth-first, reverse order, so that it encounters // APZCs front-to-back on the screen. - if (hitTestPointForChildLayers.HasPositiveWCoord()) { - for (AsyncPanZoomController* child = aApzc->GetLastChild(); child; child = child->GetPrevSibling()) { - AsyncPanZoomController* match = GetAPZCAtPoint(child, hitTestPointForChildLayers.As2DPoint(), aOutHitResult); + for (HitTestingTreeNode* node = aNode; node; node = node->GetPrevSibling()) { + AsyncPanZoomController* apzc = node->GetApzc(); + + if (node->IsOutsideClip(aHitTestPoint)) { + // If the point being tested is outside the clip region for this node + // then we don't need to test against this node or any of its children. + // Just skip it and move on. + APZCTM_LOG("Point %f %f outside clip for node %p\n", + aHitTestPoint.x, aHitTestPoint.y, node); + continue; + } + + AsyncPanZoomController* result = nullptr; + + // First check the subtree rooted at this node, because deeper nodes + // are more "in front". + Maybe hitTestPointForChildLayers = node->Untransform(aHitTestPoint); + if (hitTestPointForChildLayers) { + ParentLayerPoint childPoint = ViewAs(hitTestPointForChildLayers.ref(), + PixelCastJustification::MovingDownToChildren); + result = GetAPZCAtPoint(node->GetLastChild(), childPoint, aOutHitResult); if (*aOutHitResult == OverscrolledApzc) { // We matched an overscrolled APZC, abort. return nullptr; } - if (match) { - result = match; - break; - } } - } - if (!result && hitTestPointForThisLayer.HasPositiveWCoord()) { - ParentLayerPoint point = ParentLayerPoint::FromUnknownPoint(hitTestPointForThisLayer.As2DPoint()); - if (aApzc->HitRegionContains(point)) { - APZCTM_LOG("Successfully matched untransformed point %f %f to visible region for APZC %p\n", - hitTestPointForThisLayer.x, hitTestPointForThisLayer.y, aApzc); - result = aApzc; - // If event regions are disabled, *aOutHitResult will be ApzcHitRegion - *aOutHitResult = (aApzc->DispatchToContentRegionContains(point) ? ApzcContentRegion : ApzcHitRegion); + + // If we didn't match anything in the subtree, check |node|. + if (!result) { + APZCTM_LOG("Testing ParentLayer point %s (Layer %s) against node %p\n", + Stringify(aHitTestPoint).c_str(), + hitTestPointForChildLayers ? Stringify(hitTestPointForChildLayers.ref()).c_str() : "nil", + node); + HitTestResult hitResult = node->HitTest(aHitTestPoint); + if (hitResult != HitTestResult::NoApzcHit) { + result = node->GetNearestContainingApzc(); + APZCTM_LOG("Successfully matched APZC %p via node %p (hit result %d)\n", + result, node, hitResult); + MOZ_ASSERT(hitResult == ApzcHitRegion || hitResult == ApzcContentRegion); + // If event regions are disabled, *aOutHitResult will be ApzcHitRegion + *aOutHitResult = hitResult; + } } - } - // If we are overscrolled, and the point matches us or one of our children, - // the result is inside an overscrolled APZC, inform our caller of this - // (callers typically ignore events targeted at overscrolled APZCs). - if (result && aApzc->IsOverscrolled()) { - *aOutHitResult = OverscrolledApzc; - result = nullptr; + // If we are overscrolled, and the point matches us or one of our children, + // the result is inside an overscrolled APZC, inform our caller of this + // (callers typically ignore events targeted at overscrolled APZCs). + if (result && apzc && apzc->IsOverscrolled()) { + APZCTM_LOG("Result is inside overscrolled APZC %p\n", apzc); + *aOutHitResult = OverscrolledApzc; + return nullptr; + } + + if (result) { + if (!gfxPrefs::LayoutEventRegionsEnabled()) { + // When event-regions are disabled, we treat scrollinfo layers as + // regular scrollable layers. Unfortunately, their "hit region" (which + // we create from the composition bounds) is their full area, and they + // sit on top of their non-scrollinfo siblings. This means they will get + // a HitTestingTreeNode with a hit region that will aggressively match + // any input events that might be directed to sub-APZCs of their non- + // scrollinfo siblings. Therefore, we need to keep looping through to + // see if there are any other non-scrollinfo siblings that have children + // that match this input. If so, they should take priority. With event- + // regions enabled we use the actual regions from the layer, which are + // empty, and so this is unnecessary. + AsyncPanZoomController* prevSiblingApzc = nullptr; + for (HitTestingTreeNode* n = node->GetPrevSibling(); n; n = n->GetPrevSibling()) { + if (n->GetApzc()) { + prevSiblingApzc = n->GetApzc(); + break; + } + } + if (result == prevSiblingApzc) { + APZCTM_LOG("Continuing search past probable scrollinfo info layer\n"); + continue; + } + } + + return result; + } } - return result; + return nullptr; } /* The methods GetScreenToApzcTransform() and GetApzcToGeckoTransform() return diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/apz/src/APZCTreeManager.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/apz/src/APZCTreeManager.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/apz/src/APZCTreeManager.h 2015-01-07 22:15:33.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/apz/src/APZCTreeManager.h 2015-01-09 12:37:17.000000000 +0000 @@ -21,6 +21,7 @@ #include "mozilla/Vector.h" // for mozilla::Vector #include "nsTArrayForwardDeclare.h" // for nsTArray, nsTArray_Impl, etc #include "mozilla/gfx/Logging.h" // for gfx::TreeLog +#include "mozilla/layers/APZUtils.h" // for HitTestResult class nsIntRegion; @@ -48,6 +49,7 @@ class LayerMetricsWrapper; class InputQueue; class GeckoContentController; +class HitTestingTreeNode; /** * ****************** NOTE ON LOCK ORDERING IN APZ ************************** @@ -72,10 +74,11 @@ * This class generally lives on the compositor thread, although some functions * may be called from other threads as noted; thread safety is ensured internally. * - * The bulk of the work of this class happens as part of the UpdatePanZoomControllerTree + * The bulk of the work of this class happens as part of the UpdateHitTestingTree * function, which is when a layer tree update is received by the compositor. - * This function walks through the layer tree and creates a tree of APZC instances - * to match the scrollable container layers. APZC instances may be preserved across + * This function walks through the layer tree and creates a tree of + * HitTestingTreeNode instances to match the layer tree and for use in + * hit-testing on the controller thread. APZC instances may be preserved across * calls to this function if the corresponding layers are still present in the layer * tree. * @@ -95,9 +98,9 @@ typedef mozilla::layers::AllowedTouchBehavior AllowedTouchBehavior; typedef uint32_t TouchBehaviorFlags; - // Helper struct to hold some state while we build the APZ tree. The + // Helper struct to hold some state while we build the hit-testing tree. The // sole purpose of this struct is to shorten the argument list to - // UpdatePanZoomControllerTree. All the state that we don't need to + // UpdateHitTestingTree. All the state that we don't need to // push on the stack during recursion and pop on unwind is stored here. struct TreeBuildingState; @@ -105,9 +108,9 @@ APZCTreeManager(); /** - * Rebuild the APZC tree based on the layer update that just came up. Preserve - * APZC instances where possible, but retire those whose layers are no longer - * in the layer tree. + * Rebuild the hit-testing tree based on the layer update that just came up. + * Preserve nodes and APZC instances where possible, but retire those whose + * layers are no longer in the layer tree. * * This must be called on the compositor thread as it walks the layer tree. * @@ -125,11 +128,11 @@ * process' layer subtree has its own sequence * numbers. */ - void UpdatePanZoomControllerTree(CompositorParent* aCompositor, - Layer* aRoot, - bool aIsFirstPaint, - uint64_t aOriginatingLayersId, - uint32_t aPaintSequenceNumber); + void UpdateHitTestingTree(CompositorParent* aCompositor, + Layer* aRoot, + bool aIsFirstPaint, + uint64_t aOriginatingLayersId, + uint32_t aPaintSequenceNumber); /** * General handler for incoming input events. Manipulates the frame metrics @@ -398,24 +401,27 @@ about it going away. These are public for testing code and generally should not be used by other production code. */ - enum HitTestResult { - NoApzcHit, - ApzcHitRegion, - ApzcContentRegion, - OverscrolledApzc, - }; - - already_AddRefed GetTargetAPZC(const ScrollableLayerGuid& aGuid); + nsRefPtr GetRootNode() const; already_AddRefed GetTargetAPZC(const ScreenPoint& aPoint, HitTestResult* aOutHitResult); gfx::Matrix4x4 GetScreenToApzcTransform(const AsyncPanZoomController *aApzc) const; gfx::Matrix4x4 GetApzcToGeckoTransform(const AsyncPanZoomController *aApzc) const; private: + typedef bool (*GuidComparator)(const ScrollableLayerGuid&, const ScrollableLayerGuid&); + /* Helpers */ - AsyncPanZoomController* FindTargetAPZC(AsyncPanZoomController* aApzc, FrameMetrics::ViewID aScrollId); - AsyncPanZoomController* FindTargetAPZC(AsyncPanZoomController* aApzc, const ScrollableLayerGuid& aGuid); - AsyncPanZoomController* GetAPZCAtPoint(AsyncPanZoomController* aApzc, - const gfx::Point& aHitTestPoint, + void AttachNodeToTree(HitTestingTreeNode* aNode, + HitTestingTreeNode* aParent, + HitTestingTreeNode* aNextSibling); + already_AddRefed GetTargetAPZC(const ScrollableLayerGuid& aGuid, + GuidComparator aComparator = nullptr); + already_AddRefed GetTargetNode(const ScrollableLayerGuid& aGuid, + GuidComparator aComparator); + HitTestingTreeNode* FindTargetNode(HitTestingTreeNode* aNode, + const ScrollableLayerGuid& aGuid, + GuidComparator aComparator); + AsyncPanZoomController* GetAPZCAtPoint(HitTestingTreeNode* aNode, + const ParentLayerPoint& aHitTestPoint, HitTestResult* aOutHitResult); already_AddRefed GetMultitouchTarget(AsyncPanZoomController* aApzc1, AsyncPanZoomController* aApzc2) const; already_AddRefed CommonAncestor(AsyncPanZoomController* aApzc1, AsyncPanZoomController* aApzc2) const; @@ -431,35 +437,47 @@ nsEventStatus ProcessEvent(WidgetInputEvent& inputEvent, ScrollableLayerGuid* aOutTargetGuid, uint64_t* aOutInputBlockId); - void UpdateZoomConstraintsRecursively(AsyncPanZoomController* aApzc, + void UpdateZoomConstraintsRecursively(HitTestingTreeNode* aNode, const ZoomConstraints& aConstraints); - void FlushRepaintsRecursively(AsyncPanZoomController* aApzc); + void FlushRepaintsRecursively(HitTestingTreeNode* aNode); - AsyncPanZoomController* PrepareAPZCForLayer(const LayerMetricsWrapper& aLayer, - const FrameMetrics& aMetrics, - uint64_t aLayersId, - const gfx::Matrix4x4& aAncestorTransform, - const nsIntRegion& aObscured, - AsyncPanZoomController* aParent, - AsyncPanZoomController* aNextSibling, - TreeBuildingState& aState); - - /** - * Recursive helper function to build the APZC tree. The tree of APZC instances has - * the same shape as the layer tree, but excludes all the layers that are not scrollable. - * Note that this means APZCs corresponding to layers at different depths in the tree - * may end up becoming siblings. It also means that the "root" APZC may have siblings. - * This function walks the layer tree backwards through siblings and constructs the APZC - * tree also as a last-child-prev-sibling tree because that simplifies the hit detection - * code. - */ - AsyncPanZoomController* UpdatePanZoomControllerTree(TreeBuildingState& aState, - const LayerMetricsWrapper& aLayer, - uint64_t aLayersId, - const gfx::Matrix4x4& aAncestorTransform, - AsyncPanZoomController* aParent, - AsyncPanZoomController* aNextSibling, - const nsIntRegion& aObscured); + already_AddRefed RecycleOrCreateNode(TreeBuildingState& aState, + AsyncPanZoomController* aApzc); + HitTestingTreeNode* PrepareNodeForLayer(const LayerMetricsWrapper& aLayer, + const FrameMetrics& aMetrics, + uint64_t aLayersId, + const gfx::Matrix4x4& aAncestorTransform, + HitTestingTreeNode* aParent, + HitTestingTreeNode* aNextSibling, + TreeBuildingState& aState); + + /** + * Recursive helper function to build the hit-testing tree. See documentation + * in HitTestingTreeNode.h for more details on the shape of the tree. + * This function walks the layer tree backwards through siblings and + * constructs the hit-testing tree also as a last-child-prev-sibling tree + * because that simplifies the hit detection code. + * + * @param aState The current tree building state. + * @param aLayer The (layer, metrics) pair which is the current position in + * the recursive walk of the layer tree. This call builds a + * hit-testing subtree corresponding to the layer subtree rooted + * at aLayer. + * @param aLayersId The layers id of the layer in aLayer. + * @param aAncestorTransform The accumulated CSS transforms of all the + * layers from aLayer up (via the parent chain) + * to the next APZC-bearing layer. + * @param aParent The parent of any node built at this level. + * @param aNextSibling The next sibling of any node built at this level. + * @return The HitTestingTreeNode created at this level. This will always + * be non-null. + */ + HitTestingTreeNode* UpdateHitTestingTree(TreeBuildingState& aState, + const LayerMetricsWrapper& aLayer, + uint64_t aLayersId, + const gfx::Matrix4x4& aAncestorTransform, + HitTestingTreeNode* aParent, + HitTestingTreeNode* aNextSibling); void PrintAPZCInfo(const LayerMetricsWrapper& aLayer, const AsyncPanZoomController* apzc); @@ -471,15 +489,15 @@ nsRefPtr mInputQueue; private: - /* Whenever walking or mutating the tree rooted at mRootApzc, mTreeLock must be held. + /* Whenever walking or mutating the tree rooted at mRootNode, mTreeLock must be held. * This lock does not need to be held while manipulating a single APZC instance in * isolation (that is, if its tree pointers are not being accessed or mutated). The - * lock also needs to be held when accessing the mRootApzc instance variable, as that + * lock also needs to be held when accessing the mRootNode instance variable, as that * is considered part of the APZC tree management state. * Finally, the lock needs to be held when accessing mOverscrollHandoffChain. * IMPORTANT: See the note about lock ordering at the top of this file. */ mutable mozilla::Monitor mTreeLock; - nsRefPtr mRootApzc; + nsRefPtr mRootNode; /* This tracks the APZC that should receive all inputs for the current input event block. * This allows touch points to move outside the thing they started on, but still have the * touch events delivered to the same initial APZC. This will only ever be touched on the diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/apz/src/APZUtils.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/apz/src/APZUtils.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/apz/src/APZUtils.h 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/apz/src/APZUtils.h 2015-01-09 12:37:17.000000000 +0000 @@ -0,0 +1,23 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et tw=80 : */ +/* 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_layers_APZUtils_h +#define mozilla_layers_APZUtils_h + +namespace mozilla { +namespace layers { + +enum HitTestResult { + NoApzcHit, + ApzcHitRegion, + ApzcContentRegion, + OverscrolledApzc, +}; + +} +} + +#endif // mozilla_layers_APZUtils_h diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/apz/src/AsyncPanZoomController.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/apz/src/AsyncPanZoomController.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/apz/src/AsyncPanZoomController.cpp 2015-01-07 22:15:33.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/apz/src/AsyncPanZoomController.cpp 2015-01-09 12:37:17.000000000 +0000 @@ -916,7 +916,9 @@ } } -AsyncPanZoomController::~AsyncPanZoomController() { +AsyncPanZoomController::~AsyncPanZoomController() +{ + MOZ_ASSERT(IsDestroyed()); } PCompositorParent* @@ -963,8 +965,6 @@ mGeckoContentController = nullptr; mGestureEventListener = nullptr; } - mPrevSibling = nullptr; - mLastChild = nullptr; mParent = nullptr; mTreeManager = nullptr; @@ -2639,19 +2639,10 @@ } } - LayerToParentLayerScale scale(mFrameMetrics.mPresShellResolution // non-transient portion - * mFrameMetrics.GetAsyncZoom().scale); // transient portion ParentLayerPoint translation = (currentScrollOffset - lastPaintScrollOffset) * mFrameMetrics.GetZoom(); - return ViewTransform(scale, -translation); -} - -Matrix4x4 AsyncPanZoomController::GetNontransientAsyncTransform() const { - ReentrantMonitorAutoEnter lock(mMonitor); - return Matrix4x4::Scaling(mLastContentPaintMetrics.mPresShellResolution, - mLastContentPaintMetrics.mPresShellResolution, - 1.0f); + return ViewTransform(mFrameMetrics.GetAsyncZoom(), -translation); } Matrix4x4 AsyncPanZoomController::GetTransformToLastDispatchedPaint() const { @@ -2660,16 +2651,7 @@ LayerPoint scrollChange = (mLastContentPaintMetrics.GetScrollOffset() - mLastDispatchedPaintMetrics.GetScrollOffset()) * mLastContentPaintMetrics.GetDevPixelsPerCSSPixel() - * mLastContentPaintMetrics.GetCumulativeResolution() - // This transform ("LD" in the terminology of the comment above - // GetScreenToApzcTransform() in APZCTreeManager.h) is applied in a - // coordinate space that includes the APZC's CSS transform ("LC"). - // This CSS transform is the identity unless this APZC sets a pres-shell - // resolution, in which case the transform has a post-scale that cancels - // out the pres-shell resolution. We simulate applying the "LC" transform - // by dividing by the pres-shell resolution. This will go away once - // bug 1076192 is fixed. - / mLastContentPaintMetrics.mPresShellResolution; + * mLastContentPaintMetrics.GetCumulativeResolution(); float zoomChange = mLastContentPaintMetrics.GetZoom().scale / mLastDispatchedPaintMetrics.GetZoom().scale; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/apz/src/AsyncPanZoomController.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/apz/src/AsyncPanZoomController.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/apz/src/AsyncPanZoomController.h 2015-01-07 22:15:33.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/apz/src/AsyncPanZoomController.h 2015-01-09 12:37:17.000000000 +0000 @@ -218,13 +218,6 @@ ViewTransform GetCurrentAsyncTransform() const; /** - * Returns the part of the async transform that will remain once Gecko does a - * repaint at the desired metrics. That is, in the steady state: - * Matrix4x4(GetCurrentAsyncTransform()) === GetNontransientAsyncTransform() - */ - Matrix4x4 GetNontransientAsyncTransform() const; - - /** * Returns the transform to take something from the coordinate space of the * last thing we know gecko painted, to the coordinate space of the last thing * we asked gecko to paint. In cases where that last request has not yet been @@ -852,41 +845,17 @@ void StartSmoothScroll(); /* =================================================================== - * The functions and members in this section are used to build a tree - * structure out of APZC instances. This tree can only be walked or - * manipulated while holding the lock in the associated APZCTreeManager - * instance. + * The functions and members in this section are used to make ancestor chains + * out of APZC instances. These chains can only be walked or manipulated + * while holding the lock in the associated APZCTreeManager instance. */ public: - void SetLastChild(AsyncPanZoomController* child) { - mLastChild = child; - if (child) { - child->mParent = this; - } - } - - void SetPrevSibling(AsyncPanZoomController* sibling) { - mPrevSibling = sibling; - if (sibling) { - sibling->mParent = mParent; - } - } - - // Make this APZC the root of the APZC tree. Clears the parent pointer. - void MakeRoot() { - mParent = nullptr; + void SetParent(AsyncPanZoomController* aParent) { + mParent = aParent; } - AsyncPanZoomController* GetLastChild() const { return mLastChild; } - AsyncPanZoomController* GetPrevSibling() const { return mPrevSibling; } - AsyncPanZoomController* GetParent() const { return mParent; } - - AsyncPanZoomController* GetFirstChild() const { - AsyncPanZoomController* child = GetLastChild(); - while (child && child->GetPrevSibling()) { - child = child->GetPrevSibling(); - } - return child; + AsyncPanZoomController* GetParent() const { + return mParent; } /* Returns true if there is no APZC higher in the tree with the same @@ -904,8 +873,6 @@ // pointer out in Destroy() will prevent accessing deleted memory. Atomic mTreeManager; - nsRefPtr mLastChild; - nsRefPtr mPrevSibling; nsRefPtr mParent; @@ -1003,39 +970,19 @@ * hit-testing to see which APZC instance should handle touch events. */ public: - void SetLayerHitTestData(const EventRegions& aRegions, const Matrix4x4& aTransformToLayer) { - mEventRegions = aRegions; + void SetAncestorTransform(const Matrix4x4& aTransformToLayer) { mAncestorTransform = aTransformToLayer; } - void AddHitTestRegions(const EventRegions& aRegions) { - mEventRegions.OrWith(aRegions); - } - Matrix4x4 GetAncestorTransform() const { return mAncestorTransform; } - bool HitRegionContains(const ParentLayerPoint& aPoint) const { - ParentLayerIntPoint point = RoundedToInt(aPoint); - return mEventRegions.mHitRegion.Contains(point.x, point.y); - } - - bool DispatchToContentRegionContains(const ParentLayerPoint& aPoint) const { - ParentLayerIntPoint point = RoundedToInt(aPoint); - return mEventRegions.mDispatchToContentHitRegion.Contains(point.x, point.y); - } - bool IsOverscrolled() const { return mX.IsOverscrolled() || mY.IsOverscrolled(); } private: - /* This is the union of the hit regions of the layers that this APZC - * corresponds to, in the local screen pixels of those layers. (This is the - * same coordinate system in which this APZC receives events in - * ReceiveInputEvent()). */ - EventRegions mEventRegions; /* This is the cumulative CSS transform for all the layers from (and including) * the parent APZC down to (but excluding) this one. */ Matrix4x4 mAncestorTransform; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/apz/src/HitTestingTreeNode.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/apz/src/HitTestingTreeNode.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/apz/src/HitTestingTreeNode.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/apz/src/HitTestingTreeNode.cpp 2015-01-09 12:37:17.000000000 +0000 @@ -0,0 +1,246 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et tw=80 : */ +/* 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 "HitTestingTreeNode.h" + +#include "AsyncPanZoomController.h" // for AsyncPanZoomController +#include "LayersLogging.h" // for Stringify +#include "mozilla/gfx/Point.h" // for Point4D +#include "mozilla/layers/AsyncCompositionManager.h" // for ViewTransform::operator Matrix4x4() +#include "nsPrintfCString.h" // for nsPrintfCString +#include "UnitTransforms.h" // for ViewAs + +namespace mozilla { +namespace layers { + +HitTestingTreeNode::HitTestingTreeNode(AsyncPanZoomController* aApzc, + bool aIsPrimaryHolder) + : mApzc(aApzc) + , mIsPrimaryApzcHolder(aIsPrimaryHolder) +{ + if (mIsPrimaryApzcHolder) { + MOZ_ASSERT(mApzc); + } +} + +void +HitTestingTreeNode::RecycleWith(AsyncPanZoomController* aApzc) +{ + MOZ_ASSERT(!mIsPrimaryApzcHolder); + Destroy(); // clear out tree pointers + mApzc = aApzc; + // The caller is expected to call SetHitTestData to repopulate the hit-test + // fields. +} + +HitTestingTreeNode::~HitTestingTreeNode() +{ +} + +void +HitTestingTreeNode::Destroy() +{ + AsyncPanZoomController::AssertOnCompositorThread(); + + mPrevSibling = nullptr; + mLastChild = nullptr; + mParent = nullptr; + + if (mApzc) { + if (mIsPrimaryApzcHolder) { + mApzc->Destroy(); + } + mApzc = nullptr; + } +} + +void +HitTestingTreeNode::SetLastChild(HitTestingTreeNode* aChild) +{ + mLastChild = aChild; + if (aChild) { + aChild->mParent = this; + + if (aChild->GetApzc()) { + AsyncPanZoomController* parent = GetNearestContainingApzc(); + // We assume that HitTestingTreeNodes with an ancestor/descendant + // relationship cannot both point to the same APZC instance. This + // assertion only covers a subset of cases in which that might occur, + // but it's better than nothing. + MOZ_ASSERT(aChild->GetApzc() != parent); + aChild->SetApzcParent(parent); + } + } +} + +void +HitTestingTreeNode::SetPrevSibling(HitTestingTreeNode* aSibling) +{ + mPrevSibling = aSibling; + if (aSibling) { + aSibling->mParent = mParent; + + if (aSibling->GetApzc()) { + AsyncPanZoomController* parent = mParent ? mParent->GetNearestContainingApzc() : nullptr; + aSibling->SetApzcParent(parent); + } + } +} + +void +HitTestingTreeNode::MakeRoot() +{ + mParent = nullptr; + + if (GetApzc()) { + SetApzcParent(nullptr); + } +} + +HitTestingTreeNode* +HitTestingTreeNode::GetFirstChild() const +{ + HitTestingTreeNode* child = GetLastChild(); + while (child && child->GetPrevSibling()) { + child = child->GetPrevSibling(); + } + return child; +} + +HitTestingTreeNode* +HitTestingTreeNode::GetLastChild() const +{ + return mLastChild; +} + +HitTestingTreeNode* +HitTestingTreeNode::GetPrevSibling() const +{ + return mPrevSibling; +} + +HitTestingTreeNode* +HitTestingTreeNode::GetParent() const +{ + return mParent; +} + +AsyncPanZoomController* +HitTestingTreeNode::GetApzc() const +{ + return mApzc; +} + +AsyncPanZoomController* +HitTestingTreeNode::GetNearestContainingApzc() const +{ + for (const HitTestingTreeNode* n = this; n; n = n->GetParent()) { + if (n->GetApzc()) { + return n->GetApzc(); + } + } + return nullptr; +} + +bool +HitTestingTreeNode::IsPrimaryHolder() const +{ + return mIsPrimaryApzcHolder; +} + +void +HitTestingTreeNode::SetHitTestData(const EventRegions& aRegions, + const gfx::Matrix4x4& aTransform, + const Maybe& aClipRegion) +{ + mEventRegions = aRegions; + mTransform = aTransform; + mClipRegion = aClipRegion; +} + +bool +HitTestingTreeNode::IsOutsideClip(const ParentLayerPoint& aPoint) const +{ + // test against clip rect in ParentLayer coordinate space + return (mClipRegion.isSome() && !mClipRegion->Contains(aPoint.x, aPoint.y)); +} + +Maybe +HitTestingTreeNode::Untransform(const ParentLayerPoint& aPoint) const +{ + // convert into Layer coordinate space + gfx::Matrix4x4 localTransform = mTransform; + if (mApzc) { + localTransform = localTransform * gfx::Matrix4x4(mApzc->GetCurrentAsyncTransform()); + } + gfx::Point4D point = localTransform.Inverse().ProjectPoint(aPoint.ToUnknownPoint()); + return point.HasPositiveWCoord() + ? Some(ViewAs(point.As2DPoint())) + : Nothing(); +} + +HitTestResult +HitTestingTreeNode::HitTest(const ParentLayerPoint& aPoint) const +{ + // This should only ever get called if the point is inside the clip region + // for this node. + MOZ_ASSERT(!IsOutsideClip(aPoint)); + + // When event regions are disabled and we have an APZC on this node, we are + // actually storing the touch-sensitive section of the composition bounds in + // the clip region, and we don't need to check against the mEventRegions. + // If there's no APZC, then we do need to check against the mEventRegions + // (which contains the layer's visible region) for obscuration purposes. + if (!gfxPrefs::LayoutEventRegionsEnabled() && GetApzc()) { + return HitTestResult::ApzcHitRegion; + } + + // convert into Layer coordinate space + Maybe pointInLayerPixels = Untransform(aPoint); + if (!pointInLayerPixels) { + return HitTestResult::NoApzcHit; + } + LayerIntPoint point = RoundedToInt(pointInLayerPixels.ref()); + + // test against event regions in Layer coordinate space + if (!mEventRegions.mHitRegion.Contains(point.x, point.y)) { + return HitTestResult::NoApzcHit; + } + if (mEventRegions.mDispatchToContentHitRegion.Contains(point.x, point.y)) { + return HitTestResult::ApzcContentRegion; + } + return HitTestResult::ApzcHitRegion; +} + +void +HitTestingTreeNode::Dump(const char* aPrefix) const +{ + if (mPrevSibling) { + mPrevSibling->Dump(aPrefix); + } + printf_stderr("%sHitTestingTreeNode (%p) APZC (%p) g=(%s) r=(%s) t=(%s) c=(%s)\n", + aPrefix, this, mApzc.get(), mApzc ? Stringify(mApzc->GetGuid()).c_str() : "", + Stringify(mEventRegions).c_str(), Stringify(mTransform).c_str(), + mClipRegion ? Stringify(mClipRegion.ref()).c_str() : "none"); + if (mLastChild) { + mLastChild->Dump(nsPrintfCString("%s ", aPrefix).get()); + } +} + +void +HitTestingTreeNode::SetApzcParent(AsyncPanZoomController* aParent) +{ + // precondition: GetApzc() is non-null + MOZ_ASSERT(GetApzc() != nullptr); + if (IsPrimaryHolder()) { + GetApzc()->SetParent(aParent); + } else { + MOZ_ASSERT(GetApzc()->GetParent() == aParent); + } +} + +} // namespace layers +} // namespace mozilla diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/apz/src/HitTestingTreeNode.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/apz/src/HitTestingTreeNode.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/apz/src/HitTestingTreeNode.h 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/apz/src/HitTestingTreeNode.h 2015-01-09 12:37:17.000000000 +0000 @@ -0,0 +1,130 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et tw=80 : */ +/* 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_layers_HitTestingTreeNode_h +#define mozilla_layers_HitTestingTreeNode_h + +#include "APZUtils.h" // for HitTestResult +#include "FrameMetrics.h" // for ScrollableLayerGuid +#include "mozilla/gfx/Matrix.h" // for Matrix4x4 +#include "mozilla/layers/LayersTypes.h" // for EventRegions +#include "mozilla/Maybe.h" // for Maybe +#include "nsRefPtr.h" // for nsRefPtr + +namespace mozilla { +namespace layers { + +class AsyncPanZoomController; + +/** + * This class represents a node in a tree that is used by the APZCTreeManager + * to do hit testing. The tree is roughly a copy of the layer tree, but will + * contain multiple nodes in cases where the layer has multiple FrameMetrics. + * In other words, the structure of this tree should be identical to the + * LayerMetrics tree (see documentation in LayerMetricsWrapper.h). + * + * Not all HitTestingTreeNode instances will have an APZC associated with them; + * only HitTestingTreeNodes that correspond to layers with scrollable metrics + * have APZCs. + * Multiple HitTestingTreeNode instances may share the same underlying APZC + * instance if the layers they represent share the same scrollable metrics (i.e. + * are part of the same animated geometry root). If this happens, exactly one of + * the HitTestingTreeNode instances will be designated as the "primary holder" + * of the APZC. When this primary holder is destroyed, it will destroy the APZC + * along with it; in contrast, destroying non-primary-holder nodes will not + * destroy the APZC. + * Code should not make assumptions about which of the nodes will be the + * primary holder, only that that there will be exactly one for each APZC in + * the tree. + * + * The reason this tree exists at all is so that we can do hit-testing on the + * thread that we receive input on (referred to the as the controller thread in + * APZ terminology), which may be different from the compositor thread. + * Accessing the compositor layer tree can only be done on the compositor + * thread, and so it is simpler to make a copy of the hit-testing related + * properties into a separate tree. + */ +class HitTestingTreeNode { + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(HitTestingTreeNode); + +private: + ~HitTestingTreeNode(); +public: + HitTestingTreeNode(AsyncPanZoomController* aApzc, bool aIsPrimaryHolder); + void RecycleWith(AsyncPanZoomController* aApzc); + void Destroy(); + + /* Tree construction methods */ + + void SetLastChild(HitTestingTreeNode* aChild); + void SetPrevSibling(HitTestingTreeNode* aSibling); + void MakeRoot(); + + /* Tree walking methods. GetFirstChild is O(n) in the number of children. The + * other tree walking methods are all O(1). */ + + HitTestingTreeNode* GetFirstChild() const; + HitTestingTreeNode* GetLastChild() const; + HitTestingTreeNode* GetPrevSibling() const; + HitTestingTreeNode* GetParent() const; + + /* APZC related methods */ + + AsyncPanZoomController* GetApzc() const; + AsyncPanZoomController* GetNearestContainingApzc() const; + bool IsPrimaryHolder() const; + + /* Hit test related methods */ + + void SetHitTestData(const EventRegions& aRegions, + const gfx::Matrix4x4& aTransform, + const Maybe& aClipRegion); + bool IsOutsideClip(const ParentLayerPoint& aPoint) const; + /* Convert aPoint into the LayerPixel space for the layer corresponding to + * this node. */ + Maybe Untransform(const ParentLayerPoint& aPoint) const; + /* Assuming aPoint is inside the clip region for this node, check which of the + * event region spaces it falls inside. */ + HitTestResult HitTest(const ParentLayerPoint& aPoint) const; + + /* Debug helpers */ + void Dump(const char* aPrefix = "") const; + +private: + void SetApzcParent(AsyncPanZoomController* aApzc); + + nsRefPtr mLastChild; + nsRefPtr mPrevSibling; + nsRefPtr mParent; + + nsRefPtr mApzc; + bool mIsPrimaryApzcHolder; + + /* Let {L,M} be the {layer, scrollable metrics} pair that this node + * corresponds to in the layer tree. mEventRegions contains the event regions + * from L, in the case where event-regions are enabled. If event-regions are + * disabled, it will contain the visible region of L, which we use as an + * approximation to the hit region for the purposes of obscuring other layers. + * This value is in L's LayerPixels. + */ + EventRegions mEventRegions; + + /* This is the transform from layer L. This does NOT include any async + * transforms. */ + gfx::Matrix4x4 mTransform; + + /* This is clip rect for L that we wish to use for hit-testing purposes. Note + * that this may not be exactly the same as the clip rect on layer L because + * of the touch-sensitive region provided by the GeckoContentController, or + * because we may use the composition bounds of the layer if the clip is not + * present. This value is in L's ParentLayerPixels. */ + Maybe mClipRegion; +}; + +} +} + +#endif // mozilla_layers_HitTestingTreeNode_h diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/apz/util/APZCCallbackHelper.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/apz/util/APZCCallbackHelper.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/apz/util/APZCCallbackHelper.cpp 2015-01-07 22:15:33.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/apz/util/APZCCallbackHelper.cpp 2015-01-09 12:37:17.000000000 +0000 @@ -145,7 +145,7 @@ // last paint. float presShellResolution = aMetrics.mPresShellResolution * aMetrics.GetAsyncZoom().scale; - aUtils->SetResolution(presShellResolution, presShellResolution); + aUtils->SetResolutionAndScaleTo(presShellResolution, presShellResolution); // Finally, we set the displayport. nsCOMPtr content = nsLayoutUtils::FindContentFor(aMetrics.GetScrollId()); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/client/ClientTiledPaintedLayer.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/client/ClientTiledPaintedLayer.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/client/ClientTiledPaintedLayer.cpp 2015-01-07 22:15:33.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/client/ClientTiledPaintedLayer.cpp 2015-01-09 12:37:17.000000000 +0000 @@ -72,8 +72,8 @@ ancestorParent ? iter != ancestorParent : iter.IsValid(); iter = iter.GetParent()) { transform = transform * iter.GetTransform(); - // If the layer has a non-transient async transform then we need to apply it here - // because it will get applied by the APZ in the compositor as well + // If the layer has a pres shell resolution, the compositor will apply + // a scale to scale to this transform. Apply it here too. const FrameMetrics& metrics = iter.Metrics(); transform.PostScale(metrics.mPresShellResolution, metrics.mPresShellResolution, 1.f); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/client/TiledContentClient.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/client/TiledContentClient.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/client/TiledContentClient.cpp 2015-01-07 22:15:33.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/client/TiledContentClient.cpp 2015-01-09 12:37:17.000000000 +0000 @@ -27,7 +27,7 @@ #include "nsSize.h" // for nsIntSize #include "gfxReusableSharedImageSurfaceWrapper.h" #include "nsExpirationTracker.h" // for nsExpirationTracker -#include "nsMathUtils.h" // for NS_roundf +#include "nsMathUtils.h" // for NS_lroundf #include "gfx2DGlue.h" #include "LayersLogging.h" #include "UnitTransforms.h" // for TransformTo @@ -151,11 +151,9 @@ // but with aContentMetrics used in place of mLastContentPaintMetrics, because they // should be equivalent, modulo race conditions while transactions are inflight. - LayerToParentLayerScale scale(aCompositorMetrics.mPresShellResolution - * aCompositorMetrics.GetAsyncZoom().scale); ParentLayerPoint translation = (aCompositorMetrics.GetScrollOffset() - aContentMetrics.GetScrollOffset()) * aCompositorMetrics.GetZoom(); - return ViewTransform(scale, -translation); + return ViewTransform(aCompositorMetrics.GetAsyncZoom(), -translation); } bool @@ -1191,7 +1189,7 @@ // Mark the newly updated area as invalid in the front buffer aTile.mInvalidFront.Or(aTile.mInvalidFront, - nsIntRect(NS_roundf(drawRect.x), NS_roundf(drawRect.y), + nsIntRect(NS_lroundf(drawRect.x), NS_lroundf(drawRect.y), drawRect.width, drawRect.height)); if (mode == SurfaceMode::SURFACE_COMPONENT_ALPHA) { @@ -1237,11 +1235,11 @@ dirtyRect->height); drawRect.Scale(mResolution); - gfx::IntRect copyRect(NS_roundf((dirtyRect->x - mSinglePaintBufferOffset.x) * mResolution), - NS_roundf((dirtyRect->y - mSinglePaintBufferOffset.y) * mResolution), + gfx::IntRect copyRect(NS_lroundf((dirtyRect->x - mSinglePaintBufferOffset.x) * mResolution), + NS_lroundf((dirtyRect->y - mSinglePaintBufferOffset.y) * mResolution), drawRect.width, drawRect.height); - gfx::IntPoint copyTarget(NS_roundf(drawRect.x), NS_roundf(drawRect.y)); + gfx::IntPoint copyTarget(NS_lroundf(drawRect.x), NS_lroundf(drawRect.y)); drawTarget->CopySurface(source, copyRect, copyTarget); // Mark the newly updated area as invalid in the front buffer @@ -1284,8 +1282,8 @@ nsIntRect(aTileOrigin.x, aTileOrigin.y, GetScaledTileSize().width, GetScaledTileSize().height); // Intersect this area with the portion that's invalid. - tileRegion = tileRegion.Sub(tileRegion, GetValidRegion()); - tileRegion = tileRegion.Sub(tileRegion, aDirtyRegion); // Has now been validated + tileRegion.SubOut(GetValidRegion()); + tileRegion.SubOut(aDirtyRegion); // Has now been validated backBuffer->SetWaste(tileRegion.Area() * mResolution * mResolution); backBuffer->Unlock(); @@ -1318,8 +1316,7 @@ * (which was generated in GetTransformToAncestorsParentLayer), and * modifies it with the ViewTransform from the compositor side so that * it reflects what the compositor is actually rendering. This operation - * basically replaces the nontransient async transform that was injected - * in GetTransformToAncestorsParentLayer with the complete async transform. + * basically adds in the layer's async transform. * This function then returns the scroll ancestor's composition bounds, * transformed into the painted layer's LayerPixel coordinates, accounting * for the compositor state. @@ -1329,22 +1326,8 @@ const Matrix4x4& aTransformToCompBounds, const ViewTransform& aAPZTransform) { - Matrix4x4 nonTransientAPZUntransform = Matrix4x4::Scaling( - aScrollAncestor.Metrics().mPresShellResolution, - aScrollAncestor.Metrics().mPresShellResolution, - 1.f); - nonTransientAPZUntransform.Invert(); - - // Take off the last "term" of aTransformToCompBounds, which - // is the APZ's nontransient async transform. Replace it with - // the APZ's async transform (this includes the nontransient - // component as well). - Matrix4x4 transform = aTransformToCompBounds - * nonTransientAPZUntransform - * Matrix4x4(aAPZTransform); - transform.Invert(); - - return TransformTo(transform, + Matrix4x4 transform = aTransformToCompBounds * Matrix4x4(aAPZTransform); + return TransformTo(transform.Inverse(), aScrollAncestor.Metrics().mCompositionBounds); } @@ -1506,6 +1489,11 @@ while (true) { aRegionToPaint.And(aInvalidRegion, tileBounds); if (!aRegionToPaint.IsEmpty()) { + if (mResolution != 1) { + // Paint the entire tile for low-res. This is aimed to fixing low-res resampling + // and to avoid doing costly region accurate painting for a small area. + aRegionToPaint = tileBounds; + } break; } if (Abs(scrollDiffY) >= Abs(scrollDiffX)) { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/composite/AsyncCompositionManager.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/composite/AsyncCompositionManager.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/composite/AsyncCompositionManager.cpp 2015-01-07 22:15:33.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/composite/AsyncCompositionManager.cpp 2015-01-09 12:37:17.000000000 +0000 @@ -695,17 +695,15 @@ AsyncPanZoomController* apzc = aContent.GetApzc(); Matrix4x4 asyncTransform = apzc->GetCurrentAsyncTransform(); - Matrix4x4 nontransientTransform = apzc->GetNontransientAsyncTransform(); - Matrix4x4 transientTransform = nontransientTransform.Inverse() * asyncTransform; - // |transientTransform| represents the amount by which we have scrolled and + // |asyncTransform| represents the amount by which we have scrolled and // zoomed since the last paint. Because the scrollbar was sized and positioned based - // on the painted content, we need to adjust it based on transientTransform so that + // on the painted content, we need to adjust it based on asyncTransform so that // it reflects what the user is actually seeing now. // - The scroll thumb needs to be scaled in the direction of scrolling by the inverse - // of the transientTransform scale (representing the zoom). This is because zooming + // of the asyncTransform scale (representing the zoom). This is because zooming // in decreases the fraction of the whole scrollable rect that is in view. - // - It needs to be translated in opposite direction of the transientTransform + // - It needs to be translated in opposite direction of the asyncTransform // translation (representing the scroll). This is because scrolling down, which // translates the layer content up, should result in moving the scroll thumb down. // The amount of the translation to the scroll thumb should be such that the ratio @@ -719,41 +717,57 @@ // scrollbar gets painted at the same resolution as the content. Since the // coordinate space we apply this transform in includes the resolution, we // need to adjust for it as well here. Note that in another - // aScrollbarIsDescendant hunk below we unapply the entire async - // transform, which includes the nontransientasync transform and would - // normally account for the resolution. + // aScrollbarIsDescendant hunk below we apply a resolution-cancelling + // transform which ensures the scroll thumb isn't actually rendered + // at a larger scale. scale *= metrics.mPresShellResolution; } - scrollbarTransform.PostScale(1.f, 1.f / transientTransform._22, 1.f); - scrollbarTransform.PostTranslate(0, -transientTransform._42 * scale, 0); + scrollbarTransform.PostScale(1.f, 1.f / asyncTransform._22, 1.f); + scrollbarTransform.PostTranslate(0, -asyncTransform._42 * scale, 0); } if (aScrollbar->GetScrollbarDirection() == Layer::HORIZONTAL) { float scale = metrics.CalculateCompositedSizeInCssPixels().width / metrics.GetScrollableRect().width; if (aScrollbarIsDescendant) { scale *= metrics.mPresShellResolution; } - scrollbarTransform.PostScale(1.f / transientTransform._11, 1.f, 1.f); - scrollbarTransform.PostTranslate(-transientTransform._41 * scale, 0, 0); + scrollbarTransform.PostScale(1.f / asyncTransform._11, 1.f, 1.f); + scrollbarTransform.PostTranslate(-asyncTransform._41 * scale, 0, 0); } Matrix4x4 transform = scrollbarTransform * aScrollbar->GetTransform(); if (aScrollbarIsDescendant) { - // If the scrollbar layer is a child of the content it is a scrollbar for, then we - // need to do an extra untransform to cancel out the async transform on - // the content. This is needed because layout positions and sizes the - // scrollbar on the assumption that there is no async transform, and without - // this code the scrollbar will end up in the wrong place. + // If the scrollbar layer is a child of the content it is a scrollbar for, + // then we need to make a couple of adjustments to the scrollbar's transform. // - // Since the async transform is applied on top of the content's regular - // transform, we need to make sure to unapply the async transform in the - // same coordinate space. This requires applying the content transform and - // then unapplying it after unapplying the async transform. + // - First, the content's resolution applies to the scrollbar as well. + // Since we don't actually want the scroll thumb's size to vary with + // the zoom (other than its length reflecting the fraction of the + // scrollable length that's in view, which is taken care of above), + // we apply a transform to cancel out this resolution. + // + // - Second, if there is any async transform (including an overscroll + // transform) on the content, this needs to be cancelled out because + // layout positions and sizes the scrollbar on the assumption that there + // is no async transform, and without this adjustment the scrollbar will + // end up in the wrong place. + // + // Note that since the async transform is applied on top of the content's + // regular transform, we need to make sure to unapply the async transform + // in the same coordinate space. This requires applying the content + // transform and then unapplying it after unapplying the async transform. + Matrix4x4 resolutionCancellingTransform = + Matrix4x4::Scaling(metrics.mPresShellResolution, + metrics.mPresShellResolution, + 1.0f).Inverse(); Matrix4x4 asyncUntransform = (asyncTransform * apzc->GetOverscrollTransform()).Inverse(); Matrix4x4 contentTransform = aContent.GetTransform(); Matrix4x4 contentUntransform = contentTransform.Inverse(); - Matrix4x4 compensation = contentTransform * asyncUntransform * contentUntransform; + Matrix4x4 compensation = resolutionCancellingTransform + * contentTransform + * asyncUntransform + * contentUntransform; transform = transform * compensation; // We also need to make a corresponding change on the clip rect of all the @@ -894,10 +908,8 @@ } LayerToParentLayerScale asyncZoom = userZoom / metrics.LayersPixelsPerCSSPixel(); - LayerToParentLayerScale scale(metrics.mPresShellResolution - * asyncZoom.scale); ParentLayerPoint translation = userScroll - geckoScroll; - Matrix4x4 treeTransform = ViewTransform(scale, -translation); + Matrix4x4 treeTransform = ViewTransform(asyncZoom, -translation); SetShadowTransform(aLayer, oldTransform * treeTransform); NS_ASSERTION(!aLayer->AsLayerComposite()->GetShadowTransformSetByAnimation(), diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/composite/ContainerLayerComposite.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/composite/ContainerLayerComposite.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/composite/ContainerLayerComposite.h 2015-01-07 22:15:33.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/composite/ContainerLayerComposite.h 2015-01-09 12:37:17.000000000 +0000 @@ -92,6 +92,24 @@ // container layers don't use a compositable CompositableHost* GetCompositableHost() MOZ_OVERRIDE { return nullptr; } + // If the layer is marked as scale-to-resolution, add a post-scale + // to the layer's transform equal to the pres shell resolution we're + // scaling to. This cancels out the post scale of '1 / resolution' + // added by Layout. TODO: It would be nice to get rid of both of these + // post-scales. + virtual float GetPostXScale() const MOZ_OVERRIDE { + if (mScaleToResolution) { + return mPostXScale * mPresShellResolution; + } + return mPostXScale; + } + virtual float GetPostYScale() const MOZ_OVERRIDE { + if (mScaleToResolution) { + return mPostYScale * mPresShellResolution; + } + return mPostYScale; + } + virtual const char* Name() const MOZ_OVERRIDE { return "ContainerLayerComposite"; } UniquePtr mPrepared; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/d3d11/CompositorD3D11.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/d3d11/CompositorD3D11.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/d3d11/CompositorD3D11.cpp 2015-01-07 22:15:33.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/d3d11/CompositorD3D11.cpp 2015-01-09 12:37:17.000000000 +0000 @@ -1045,7 +1045,7 @@ // this is important because resizing our buffers when mimised will fail and // cause a crash when we're restored. NS_ASSERTION(mHwnd, "Couldn't find an HWND when initialising?"); - if (::IsIconic(mHwnd)) { + if (::IsIconic(mHwnd) || gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) { *aRenderBoundsOut = Rect(); return; } @@ -1180,7 +1180,7 @@ mSize = rect.Size(); } -void +bool CompositorD3D11::VerifyBufferSize() { DXGI_SWAP_CHAIN_DESC swapDesc; @@ -1188,13 +1188,13 @@ hr = mSwapChain->GetDesc(&swapDesc); if (Failed(hr)) { - return; + return false; } if ((swapDesc.BufferDesc.Width == mSize.width && swapDesc.BufferDesc.Height == mSize.height) || mSize.width <= 0 || mSize.height <= 0) { - return; + return true; } if (mDefaultRT) { @@ -1211,14 +1211,14 @@ hr = mSwapChain->ResizeBuffers(2, mSize.width, mSize.height, DXGI_FORMAT_B8G8R8A8_UNORM, 0); - HandleError(hr); mDisableSequenceForNextFrame = true; } else { hr = mSwapChain->ResizeBuffers(1, mSize.width, mSize.height, DXGI_FORMAT_B8G8R8A8_UNORM, 0); - HandleError(hr); } + + return Succeeded(hr); } void @@ -1422,7 +1422,7 @@ } // XXX - It would be nice to use gfxCriticalError, but it needs to // be made to work off the main thread first. - MOZ_ASSERT(aSeverity != DebugAssert); + //MOZ_ASSERT(aSeverity != DebugAssert); if (aSeverity == Critical) { MOZ_CRASH("Unrecoverable D3D11 error"); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/d3d11/CompositorD3D11.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/d3d11/CompositorD3D11.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/d3d11/CompositorD3D11.h 2015-01-07 22:15:33.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/d3d11/CompositorD3D11.h 2015-01-09 12:37:17.000000000 +0000 @@ -159,7 +159,7 @@ // ensure mSize is up to date with respect to mWidget void EnsureSize(); - void VerifyBufferSize(); + bool VerifyBufferSize(); void UpdateRenderTarget(); bool CreateShaders(); bool UpdateConstantBuffers(); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/d3d11/TextureD3D11.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/d3d11/TextureD3D11.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/d3d11/TextureD3D11.cpp 2015-01-07 22:15:33.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/d3d11/TextureD3D11.cpp 2015-01-09 12:37:17.000000000 +0000 @@ -347,11 +347,9 @@ } // This may return a null DrawTarget -#if USE_D2D1_1 if (mTexture) { mDrawTarget = Factory::CreateDrawTargetForD3D11Texture(mTexture, mFormat); } else -#endif { MOZ_ASSERT(mTexture10); mDrawTarget = Factory::CreateDrawTargetForD3D10Texture(mTexture10, mFormat); @@ -370,7 +368,6 @@ return false; } -#ifdef USE_D2D1_1 ID3D11Device* d3d11device = gfxWindowsPlatform::GetPlatform()->GetD3D11ContentDevice(); if (gfxPrefs::Direct2DUse1_1() && d3d11device) { @@ -383,7 +380,6 @@ hr = d3d11device->CreateTexture2D(&newDesc, nullptr, byRef(mTexture)); } else -#endif { ID3D10Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device(); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/GLImages.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/GLImages.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/GLImages.cpp 2015-01-07 22:15:33.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/GLImages.cpp 2015-01-09 12:37:17.000000000 +0000 @@ -61,7 +61,7 @@ GLBlitHelper helper(sSnapshotContext); - helper.BlitImageToFramebuffer(this, size, fb.FB(), false); + helper.BlitImageToFramebuffer(this, size, fb.FB(), true); ScopedBindFramebuffer bind(sSnapshotContext, fb.FB()); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/ImageContainer.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/ImageContainer.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/ImageContainer.cpp 2015-01-07 22:15:33.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/ImageContainer.cpp 2015-01-09 12:37:17.000000000 +0000 @@ -20,7 +20,7 @@ #ifdef MOZ_WIDGET_GONK #include "GrallocImages.h" #endif -#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_CAMERA) +#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_CAMERA) && defined(MOZ_WEBRTC) #include "GonkCameraImage.h" #endif #include "gfx2DGlue.h" @@ -64,7 +64,7 @@ return img.forget(); } #endif -#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_CAMERA) +#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_CAMERA) && defined(MOZ_WEBRTC) if (aFormat == ImageFormat::GONK_CAMERA_IMAGE) { img = new GonkCameraImage(); return img.forget(); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/ipc/CompositorParent.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/ipc/CompositorParent.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/ipc/CompositorParent.cpp 2015-01-07 22:15:33.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/ipc/CompositorParent.cpp 2015-01-09 12:37:17.000000000 +0000 @@ -733,7 +733,7 @@ mLayerManager && mLayerManager->GetRoot()) { AutoResolveRefLayers resolve(mCompositionManager); - mApzcTreeManager->UpdatePanZoomControllerTree(this, mLayerManager->GetRoot(), + mApzcTreeManager->UpdateHitTestingTree(this, mLayerManager->GetRoot(), aIsFirstPaint, aId, aPaintSequenceNumber); mLayerManager->NotifyShadowTreeTransaction(); @@ -1006,7 +1006,7 @@ if (mApzcTreeManager && !aIsRepeatTransaction) { AutoResolveRefLayers resolve(mCompositionManager); - mApzcTreeManager->UpdatePanZoomControllerTree(this, root, aIsFirstPaint, + mApzcTreeManager->UpdateHitTestingTree(this, root, aIsFirstPaint, mRootLayerTreeID, aPaintSequenceNumber); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/ipc/LayersMessages.ipdlh thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/ipc/LayersMessages.ipdlh --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/ipc/LayersMessages.ipdlh 2015-01-07 22:15:33.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/ipc/LayersMessages.ipdlh 2015-01-09 12:37:17.000000000 +0000 @@ -232,6 +232,8 @@ float preYScale; float inheritedXScale; float inheritedYScale; + float presShellResolution; + bool scaleToResolution; // This is a bare pointer; LayerTransactionParent::RecvUpdate prevents this // from being used when !IsSameProcess(), but we should make this truly // cross process at some point by passing the HMDConfig diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/ipc/LayerTransactionParent.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/ipc/LayerTransactionParent.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/ipc/LayerTransactionParent.cpp 2015-01-07 22:15:33.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/ipc/LayerTransactionParent.cpp 2015-01-09 12:37:17.000000000 +0000 @@ -382,6 +382,8 @@ specific.get_ContainerLayerAttributes(); containerLayer->SetPreScale(attrs.preXScale(), attrs.preYScale()); containerLayer->SetInheritedScale(attrs.inheritedXScale(), attrs.inheritedYScale()); + containerLayer->SetScaleToResolution(attrs.scaleToResolution(), + attrs.presShellResolution()); if (attrs.hmdInfo()) { if (!IsSameProcess()) { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/Layers.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/Layers.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/Layers.cpp 2015-01-07 22:15:33.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/Layers.cpp 2015-01-09 12:37:17.000000000 +0000 @@ -737,7 +737,7 @@ Layer::GetTransform() const { Matrix4x4 transform = mTransform; - transform.PostScale(mPostXScale, mPostYScale, 1.0f); + transform.PostScale(GetPostXScale(), GetPostYScale(), 1.0f); if (const ContainerLayer* c = AsContainerLayer()) { transform.PreScale(c->GetPreXScale(), c->GetPreYScale(), 1.0f); } @@ -753,7 +753,7 @@ else transform = mTransform; - transform.PostScale(mPostXScale, mPostYScale, 1.0f); + transform.PostScale(GetPostXScale(), GetPostYScale(), 1.0f); if (ContainerLayer* c = AsContainerLayer()) { transform.PreScale(c->GetPreXScale(), c->GetPreYScale(), 1.0f); } @@ -858,6 +858,8 @@ mPreYScale(1.0f), mInheritedXScale(1.0f), mInheritedYScale(1.0f), + mPresShellResolution(1.0f), + mScaleToResolution(false), mUseIntermediateSurface(false), mSupportsComponentAlphaChildren(false), mMayHaveReadbackChild(false), @@ -1017,6 +1019,7 @@ { aAttrs = ContainerLayerAttributes(mPreXScale, mPreYScale, mInheritedXScale, mInheritedYScale, + mPresShellResolution, mScaleToResolution, reinterpret_cast(mHMDInfo.get())); } @@ -1681,6 +1684,9 @@ if (1.0 != mPreXScale || 1.0 != mPreYScale) { aStream << nsPrintfCString(" [preScale=%g, %g]", mPreXScale, mPreYScale).get(); } + if (mScaleToResolution) { + aStream << nsPrintfCString(" [presShellResolution=%g]", mPresShellResolution).get(); + } if (mHMDInfo) { aStream << nsPrintfCString(" [hmd=%p]", mHMDInfo.get()).get(); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/Layers.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/Layers.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/Layers.h 2015-01-07 22:15:33.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/Layers.h 2015-01-09 12:37:17.000000000 +0000 @@ -1226,8 +1226,9 @@ virtual Layer* GetLastChild() const { return nullptr; } const gfx::Matrix4x4 GetTransform() const; const gfx::Matrix4x4& GetBaseTransform() const { return mTransform; } - float GetPostXScale() const { return mPostXScale; } - float GetPostYScale() const { return mPostYScale; } + // Note: these are virtual because ContainerLayerComposite overrides them. + virtual float GetPostXScale() const { return mPostXScale; } + virtual float GetPostYScale() const { return mPostYScale; } bool GetIsFixedPosition() { return mIsFixedPosition; } bool GetIsStickyPosition() { return mStickyPositionData; } LayerPoint GetFixedPositionAnchor() { return mAnchor; } @@ -1855,6 +1856,18 @@ Mutated(); } + void SetScaleToResolution(bool aScaleToResolution, float aResolution) + { + if (mScaleToResolution == aScaleToResolution && mPresShellResolution == aResolution) { + return; + } + + MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) ScaleToResolution", this)); + mScaleToResolution = aScaleToResolution; + mPresShellResolution = aResolution; + Mutated(); + } + virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs) MOZ_OVERRIDE; void SortChildrenBy3DZOrder(nsTArray& aArray); @@ -1870,6 +1883,8 @@ float GetPreYScale() const { return mPreYScale; } float GetInheritedXScale() const { return mInheritedXScale; } float GetInheritedYScale() const { return mInheritedYScale; } + float GetPresShellResolution() const { return mPresShellResolution; } + bool ScaleToResolution() const { return mScaleToResolution; } MOZ_LAYER_DECL_NAME("ContainerLayer", TYPE_CONTAINER) @@ -1968,6 +1983,11 @@ // be part of mTransform. float mInheritedXScale; float mInheritedYScale; + // For layers corresponding to an nsDisplayResolution, the resolution of the + // associated pres shell; for other layers, 1.0. + float mPresShellResolution; + // Whether the compositor should scale to mPresShellResolution. + bool mScaleToResolution; bool mUseIntermediateSurface; bool mSupportsComponentAlphaChildren; bool mMayHaveReadbackChild; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/moz.build thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/moz.build --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/moz.build 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/moz.build 2015-01-09 12:37:17.000000000 +0000 @@ -98,8 +98,6 @@ 'd3d11/CompositorD3D11.cpp', 'd3d11/ReadbackManagerD3D11.cpp', ] - if CONFIG['MOZ_ENABLE_DIRECT2D1_1']: - DEFINES['USE_D2D1_1'] = True EXPORTS.gfxipc += [ 'ipc/ShadowLayerUtils.h', @@ -110,6 +108,7 @@ # exporting things from apz/src is temporary until we extract a # proper interface for the code there 'apz/src/APZCTreeManager.h', + 'apz/src/APZUtils.h', 'apz/testutil/APZTestData.h', 'apz/util/ActiveElementManager.h', 'apz/util/APZCCallbackHelper.h', @@ -239,6 +238,7 @@ 'apz/src/AsyncPanZoomController.cpp', 'apz/src/Axis.cpp', 'apz/src/GestureEventListener.cpp', + 'apz/src/HitTestingTreeNode.cpp', 'apz/src/InputBlockState.cpp', 'apz/src/InputQueue.cpp', 'apz/src/OverscrollHandoffState.cpp', diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/opengl/GrallocTextureHost.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/opengl/GrallocTextureHost.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/layers/opengl/GrallocTextureHost.cpp 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/layers/opengl/GrallocTextureHost.cpp 2015-01-09 12:37:17.000000000 +0000 @@ -231,7 +231,7 @@ GrallocTextureHostOGL::GetAsSurface() { android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get(); uint8_t* grallocData; - int32_t rv = graphicBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast(&grallocData)); + graphicBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast(&grallocData)); RefPtr grallocTempSurf = gfx::Factory::CreateWrappingDataSourceSurface(grallocData, graphicBuffer->getStride() * android::bytesPerPixel(graphicBuffer->getPixelFormat()), diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/skia/trunk/include/effects/SkLayerRasterizer.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/skia/trunk/include/effects/SkLayerRasterizer.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/skia/trunk/include/effects/SkLayerRasterizer.h 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/skia/trunk/include/effects/SkLayerRasterizer.h 2015-01-09 12:36:24.000000000 +0000 @@ -75,7 +75,7 @@ // override from SkRasterizer virtual bool onRasterize(const SkPath& path, const SkMatrix& matrix, const SkIRect* clipBounds, - SkMask* mask, SkMask::CreateMode mode) const; + SkMask* mask, SkMask::CreateMode mode) const SK_OVERRIDE; private: const SkDeque* const fLayers; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/skia/trunk/include/gpu/SkGpuDevice.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/skia/trunk/include/gpu/SkGpuDevice.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/skia/trunk/include/gpu/SkGpuDevice.h 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/skia/trunk/include/gpu/SkGpuDevice.h 2015-01-09 12:36:24.000000000 +0000 @@ -97,7 +97,7 @@ const SkPaint& paint, SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE; virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap, - int x, int y, const SkPaint& paint); + int x, int y, const SkPaint& paint) SK_OVERRIDE; virtual void drawText(const SkDraw&, const void* text, size_t len, SkScalar x, SkScalar y, const SkPaint&) SK_OVERRIDE; virtual void drawPosText(const SkDraw&, const void* text, size_t len, diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/tests/gtest/TestAsyncPanZoomController.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/tests/gtest/TestAsyncPanZoomController.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/tests/gtest/TestAsyncPanZoomController.cpp 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/tests/gtest/TestAsyncPanZoomController.cpp 2015-01-09 12:36:27.000000000 +0000 @@ -14,6 +14,7 @@ #include "mozilla/layers/LayerMetricsWrapper.h" #include "mozilla/UniquePtr.h" #include "apz/src/AsyncPanZoomController.h" +#include "apz/src/HitTestingTreeNode.h" #include "base/task.h" #include "Layers.h" #include "TestLayers.h" @@ -841,40 +842,42 @@ apzc->SetFrameMetrics(metrics); apzc->NotifyLayersUpdated(metrics, true); apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ViewTransform(LayerToParentLayerScale(2), ParentLayerPoint()), viewTransformOut); + EXPECT_EQ(ViewTransform(LayerToParentLayerScale(1), ParentLayerPoint()), viewTransformOut); EXPECT_EQ(ParentLayerPoint(60, 60), pointOut); childApzc->SetFrameMetrics(childMetrics); childApzc->NotifyLayersUpdated(childMetrics, true); childApzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ViewTransform(LayerToParentLayerScale(2), ParentLayerPoint()), viewTransformOut); + EXPECT_EQ(ViewTransform(LayerToParentLayerScale(1), ParentLayerPoint()), viewTransformOut); EXPECT_EQ(ParentLayerPoint(60, 60), pointOut); // do an async scroll by 5 pixels and check the transform metrics.ScrollBy(CSSPoint(5, 0)); apzc->SetFrameMetrics(metrics); apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ViewTransform(LayerToParentLayerScale(2), ParentLayerPoint(-30, 0)), viewTransformOut); + EXPECT_EQ(ViewTransform(LayerToParentLayerScale(1), ParentLayerPoint(-30, 0)), viewTransformOut); EXPECT_EQ(ParentLayerPoint(90, 60), pointOut); childMetrics.ScrollBy(CSSPoint(5, 0)); childApzc->SetFrameMetrics(childMetrics); childApzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ViewTransform(LayerToParentLayerScale(2), ParentLayerPoint(-30, 0)), viewTransformOut); + EXPECT_EQ(ViewTransform(LayerToParentLayerScale(1), ParentLayerPoint(-30, 0)), viewTransformOut); EXPECT_EQ(ParentLayerPoint(90, 60), pointOut); // do an async zoom of 1.5x and check the transform metrics.ZoomBy(1.5f); apzc->SetFrameMetrics(metrics); apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ViewTransform(LayerToParentLayerScale(3), ParentLayerPoint(-45, 0)), viewTransformOut); + EXPECT_EQ(ViewTransform(LayerToParentLayerScale(1.5), ParentLayerPoint(-45, 0)), viewTransformOut); EXPECT_EQ(ParentLayerPoint(135, 90), pointOut); childMetrics.ZoomBy(1.5f); childApzc->SetFrameMetrics(childMetrics); childApzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ViewTransform(LayerToParentLayerScale(3), ParentLayerPoint(-45, 0)), viewTransformOut); + EXPECT_EQ(ViewTransform(LayerToParentLayerScale(1.5), ParentLayerPoint(-45, 0)), viewTransformOut); EXPECT_EQ(ParentLayerPoint(135, 90), pointOut); + + childApzc->Destroy(); } class APZCPanningTester : public APZCBasicTester { @@ -1685,6 +1688,7 @@ metrics.SetScrollableRect(aScrollableRect); metrics.SetScrollOffset(CSSPoint(0, 0)); aLayer->SetFrameMetrics(metrics); + aLayer->SetClipRect(&layerBound); if (!aScrollableRect.IsEqualEdges(CSSRect(-1, -1, -1, -1))) { // The purpose of this is to roughly mimic what layout would do in the // case of a scrollable frame with the event regions and clip. This lets @@ -1693,7 +1697,6 @@ nsIntRect scrollRect = LayerIntRect::ToUntyped(RoundedToInt(aScrollableRect * metrics.LayersPixelsPerCSSPixel())); er.mHitRegion = nsIntRegion(nsIntRect(layerBound.TopLeft(), scrollRect.Size())); aLayer->SetEventRegions(er); - aLayer->SetClipRect(&layerBound); } } @@ -1832,7 +1835,7 @@ // Now we have a root APZC that will match the page SetScrollableFrameMetrics(root, FrameMetrics::START_SCROLL_ID); - manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, paintSequenceNumber++); + manager->UpdateHitTestingTree(nullptr, root, false, 0, paintSequenceNumber++); hit = GetTargetAPZC(ScreenPoint(15, 15)); EXPECT_EQ(ApzcOf(root), hit.get()); // expect hit point at LayerIntPoint(15, 15) @@ -1841,7 +1844,7 @@ // Now we have a sub APZC with a better fit SetScrollableFrameMetrics(layers[3], FrameMetrics::START_SCROLL_ID + 1); - manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, paintSequenceNumber++); + manager->UpdateHitTestingTree(nullptr, root, false, 0, paintSequenceNumber++); EXPECT_NE(ApzcOf(root), ApzcOf(layers[3])); hit = GetTargetAPZC(ScreenPoint(25, 25)); EXPECT_EQ(ApzcOf(layers[3]), hit.get()); @@ -1856,7 +1859,7 @@ // Now test hit testing when we have two scrollable layers SetScrollableFrameMetrics(layers[4], FrameMetrics::START_SCROLL_ID + 2); - manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, paintSequenceNumber++); + manager->UpdateHitTestingTree(nullptr, root, false, 0, paintSequenceNumber++); hit = GetTargetAPZC(ScreenPoint(15, 15)); EXPECT_EQ(ApzcOf(layers[4]), hit.get()); // expect hit point at LayerIntPoint(15, 15) @@ -1886,7 +1889,7 @@ CreateHitTesting2LayerTree(); ScopedLayerTreeRegistration registration(0, root, mcc); - manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, 0); + manager->UpdateHitTestingTree(nullptr, root, false, 0, 0); // At this point, the following holds (all coordinates in screen pixels): // layers[0] has content from (0,0)-(200,200), clipped by composition bounds (0,0)-(100,100) @@ -2002,7 +2005,7 @@ // both layers have the same scrollId SetScrollableFrameMetrics(layers[1], FrameMetrics::START_SCROLL_ID); SetScrollableFrameMetrics(layers[2], FrameMetrics::START_SCROLL_ID); - manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, 0); + manager->UpdateHitTestingTree(nullptr, root, false, 0, 0); TestAsyncPanZoomController* nullAPZC = nullptr; // so they should have the same APZC @@ -2013,13 +2016,13 @@ // Change the scrollId of layers[1], and verify the APZC changes SetScrollableFrameMetrics(layers[1], FrameMetrics::START_SCROLL_ID + 1); - manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, 0); + manager->UpdateHitTestingTree(nullptr, root, false, 0, 0); EXPECT_NE(ApzcOf(layers[1]), ApzcOf(layers[2])); // Change the scrollId of layers[2] to match that of layers[1], ensure we get the same // APZC for both again SetScrollableFrameMetrics(layers[2], FrameMetrics::START_SCROLL_ID + 1); - manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, 0); + manager->UpdateHitTestingTree(nullptr, root, false, 0, 0); EXPECT_EQ(ApzcOf(layers[1]), ApzcOf(layers[2])); } @@ -2027,23 +2030,44 @@ CreatePotentiallyLeakingTree(); ScopedLayerTreeRegistration registration(0, root, mcc); - manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, 0); - EXPECT_EQ(ApzcOf(layers[2]), ApzcOf(layers[0])->GetLastChild()); - EXPECT_EQ(ApzcOf(layers[2]), ApzcOf(layers[0])->GetFirstChild()); + manager->UpdateHitTestingTree(nullptr, root, false, 0, 0); + nsRefPtr root = manager->GetRootNode(); + nsRefPtr node2 = root->GetFirstChild()->GetFirstChild(); + nsRefPtr node5 = root->GetLastChild()->GetLastChild(); + + EXPECT_EQ(ApzcOf(layers[2]), node5->GetApzc()); + EXPECT_EQ(ApzcOf(layers[2]), node2->GetApzc()); EXPECT_EQ(ApzcOf(layers[0]), ApzcOf(layers[2])->GetParent()); EXPECT_EQ(ApzcOf(layers[2]), ApzcOf(layers[5])); - EXPECT_EQ(ApzcOf(layers[3]), ApzcOf(layers[2])->GetFirstChild()); - EXPECT_EQ(ApzcOf(layers[6]), ApzcOf(layers[2])->GetLastChild()); - EXPECT_EQ(ApzcOf(layers[3]), ApzcOf(layers[6])->GetPrevSibling()); + EXPECT_EQ(node2->GetFirstChild(), node2->GetLastChild()); + EXPECT_EQ(ApzcOf(layers[3]), node2->GetLastChild()->GetApzc()); + EXPECT_EQ(node5->GetFirstChild(), node5->GetLastChild()); + EXPECT_EQ(ApzcOf(layers[6]), node5->GetLastChild()->GetApzc()); EXPECT_EQ(ApzcOf(layers[2]), ApzcOf(layers[3])->GetParent()); - EXPECT_EQ(ApzcOf(layers[2]), ApzcOf(layers[6])->GetParent()); + EXPECT_EQ(ApzcOf(layers[5]), ApzcOf(layers[6])->GetParent()); } TEST_F(APZHitTestingTester, ComplexMultiLayerTree) { CreateComplexMultiLayerTree(); ScopedLayerTreeRegistration registration(0, root, mcc); - manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, 0); + manager->UpdateHitTestingTree(nullptr, root, false, 0, 0); + + /* The layer tree looks like this: + + 0 + |----|--+--|----| + 1 2 4 5 + | /|\ + 3 6 8 9 + | + 7 + + Layers 1,2 have the same APZC + Layers 4,6,8 have the same APZC + Layer 7 has an APZC + Layer 9 has an APZC + */ TestAsyncPanZoomController* nullAPZC = nullptr; // Ensure all the scrollable layers have an APZC @@ -2068,8 +2092,7 @@ EXPECT_NE(ApzcOf(layers[4]), ApzcOf(layers[7])); EXPECT_NE(ApzcOf(layers[4]), ApzcOf(layers[9])); EXPECT_NE(ApzcOf(layers[7]), ApzcOf(layers[9])); - - // Ensure the shape of the APZC tree is as expected + // Ensure the APZC parent chains are set up correctly TestAsyncPanZoomController* layers1_2 = ApzcOf(layers[1]); TestAsyncPanZoomController* layers4_6_8 = ApzcOf(layers[4]); TestAsyncPanZoomController* layer7 = ApzcOf(layers[7]); @@ -2078,10 +2101,27 @@ EXPECT_EQ(nullptr, layers4_6_8->GetParent()); EXPECT_EQ(layers4_6_8, layer7->GetParent()); EXPECT_EQ(nullptr, layer9->GetParent()); - EXPECT_EQ(nullptr, layers1_2->GetPrevSibling()); - EXPECT_EQ(layers1_2, layers4_6_8->GetPrevSibling()); - EXPECT_EQ(nullptr, layer7->GetPrevSibling()); - EXPECT_EQ(layers4_6_8, layer9->GetPrevSibling()); + // Ensure the hit-testing tree looks like the layer tree + nsRefPtr root = manager->GetRootNode(); + nsRefPtr node5 = root->GetLastChild(); + nsRefPtr node4 = node5->GetPrevSibling(); + nsRefPtr node2 = node4->GetPrevSibling(); + nsRefPtr node1 = node2->GetPrevSibling(); + nsRefPtr node3 = node2->GetLastChild(); + nsRefPtr node9 = node5->GetLastChild(); + nsRefPtr node8 = node9->GetPrevSibling(); + nsRefPtr node6 = node8->GetPrevSibling(); + nsRefPtr node7 = node6->GetLastChild(); + EXPECT_EQ(nullptr, node1->GetPrevSibling()); + EXPECT_EQ(nullptr, node3->GetPrevSibling()); + EXPECT_EQ(nullptr, node6->GetPrevSibling()); + EXPECT_EQ(nullptr, node7->GetPrevSibling()); + EXPECT_EQ(nullptr, node1->GetLastChild()); + EXPECT_EQ(nullptr, node3->GetLastChild()); + EXPECT_EQ(nullptr, node4->GetLastChild()); + EXPECT_EQ(nullptr, node7->GetLastChild()); + EXPECT_EQ(nullptr, node8->GetLastChild()); + EXPECT_EQ(nullptr, node9->GetLastChild()); nsRefPtr hit = GetTargetAPZC(ScreenPoint(25, 25)); EXPECT_EQ(ApzcOf(layers[1]), hit.get()); @@ -2099,7 +2139,7 @@ CreateSimpleScrollingLayer(); ScopedLayerTreeRegistration registration(0, root, mcc); - manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, 0); + manager->UpdateHitTestingTree(nullptr, root, false, 0, 0); TestAsyncPanZoomController* apzcroot = ApzcOf(root); // At this point, the following holds (all coordinates in screen pixels): @@ -2177,7 +2217,7 @@ SetScrollableFrameMetrics(layers[1], FrameMetrics::START_SCROLL_ID + 1, CSSRect(0, 0, 100, 100)); SetScrollHandoff(layers[1], root); registration = MakeUnique(0, root, mcc); - manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, 0); + manager->UpdateHitTestingTree(nullptr, root, false, 0, 0); rootApzc = ApzcOf(root); } @@ -2197,7 +2237,7 @@ // No ScopedLayerTreeRegistration as that just needs to be done once per test // and this is the second layer tree for a particular test. MOZ_ASSERT(registration); - manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, 0); + manager->UpdateHitTestingTree(nullptr, root, false, 0, 0); rootApzc = ApzcOf(root); } @@ -2218,7 +2258,7 @@ SetScrollHandoff(layers[2], layers[1]); SetScrollHandoff(layers[4], layers[3]); registration = MakeUnique(0, root, mcc); - manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, 0); + manager->UpdateHitTestingTree(nullptr, root, false, 0, 0); } void CreateScrollgrabLayerTree() { @@ -2232,7 +2272,7 @@ SetScrollableFrameMetrics(layers[1], FrameMetrics::START_SCROLL_ID + 1, CSSRect(0, 0, 100, 200)); SetScrollHandoff(layers[1], root); registration = MakeUnique(0, root, mcc); - manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, 0); + manager->UpdateHitTestingTree(nullptr, root, false, 0, 0); rootApzc = ApzcOf(root); rootApzc->GetFrameMetrics().SetHasScrollgrab(true); } @@ -2426,7 +2466,12 @@ void CreateEventRegionsLayerTree1() { const char* layerTreeSyntax = "c(tt)"; - root = CreateLayerTree(layerTreeSyntax, nullptr, nullptr, lm, layers); + nsIntRegion layerVisibleRegions[] = { + nsIntRegion(nsIntRect(0, 0, 200, 200)), // root + nsIntRegion(nsIntRect(0, 0, 100, 200)), // left half + nsIntRegion(nsIntRect(0, 100, 200, 100)), // bottom half + }; + root = CreateLayerTree(layerTreeSyntax, layerVisibleRegions, nullptr, lm, layers); SetScrollableFrameMetrics(root, FrameMetrics::START_SCROLL_ID); SetScrollableFrameMetrics(layers[1], FrameMetrics::START_SCROLL_ID + 1); SetScrollableFrameMetrics(layers[2], FrameMetrics::START_SCROLL_ID + 2); @@ -2448,13 +2493,17 @@ layers[2]->SetEventRegions(regions); registration = MakeUnique(0, root, mcc); - manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, 0); + manager->UpdateHitTestingTree(nullptr, root, false, 0, 0); rootApzc = ApzcOf(root); } void CreateEventRegionsLayerTree2() { const char* layerTreeSyntax = "c(t)"; - root = CreateLayerTree(layerTreeSyntax, nullptr, nullptr, lm, layers); + nsIntRegion layerVisibleRegions[] = { + nsIntRegion(nsIntRect(0, 0, 100, 500)), + nsIntRegion(nsIntRect(0, 150, 100, 100)), + }; + root = CreateLayerTree(layerTreeSyntax, layerVisibleRegions, nullptr, lm, layers); SetScrollableFrameMetrics(root, FrameMetrics::START_SCROLL_ID); // Set up the event regions so that the child thebes layer is positioned far @@ -2465,7 +2514,41 @@ layers[1]->SetEventRegions(regions); registration = MakeUnique(0, root, mcc); - manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, 0); + manager->UpdateHitTestingTree(nullptr, root, false, 0, 0); + rootApzc = ApzcOf(root); + } + + void CreateObscuringLayerTree() { + const char* layerTreeSyntax = "c(c(t)t)"; + // LayerID 0 1 2 3 + // 0 is the root. + // 1 is a parent scrollable layer. + // 2 is a child scrollable layer. + // 3 is the Obscurer, who ruins everything. + nsIntRegion layerVisibleRegions[] = { + // x coordinates are uninteresting + nsIntRegion(nsIntRect(0, 0, 200, 200)), // [0, 200] + nsIntRegion(nsIntRect(0, 0, 200, 200)), // [0, 200] + nsIntRegion(nsIntRect(0, 100, 200, 50)), // [100, 150] + nsIntRegion(nsIntRect(0, 100, 200, 100)) // [100, 200] + }; + root = CreateLayerTree(layerTreeSyntax, layerVisibleRegions, nullptr, lm, layers); + + SetScrollableFrameMetrics(root, FrameMetrics::START_SCROLL_ID, CSSRect(0, 0, 200, 200)); + SetScrollableFrameMetrics(layers[1], FrameMetrics::START_SCROLL_ID + 1, CSSRect(0, 0, 200, 300)); + SetScrollableFrameMetrics(layers[2], FrameMetrics::START_SCROLL_ID + 2, CSSRect(0, 0, 200, 100)); + SetScrollHandoff(layers[2], layers[1]); + SetScrollHandoff(layers[1], root); + + EventRegions regions(nsIntRegion(nsIntRect(0, 0, 200, 200))); + root->SetEventRegions(regions); + regions.mHitRegion = nsIntRegion(nsIntRect(0, 0, 200, 300)); + layers[1]->SetEventRegions(regions); + regions.mHitRegion = nsIntRegion(nsIntRect(0, 100, 200, 100)); + layers[2]->SetEventRegions(regions); + + registration = MakeUnique(0, root, mcc); + manager->UpdateHitTestingTree(nullptr, root, false, 0, 0); rootApzc = ApzcOf(root); } }; @@ -2540,6 +2623,26 @@ mcc->RunThroughDelayedTasks(); // this runs the tap event } +TEST_F(APZEventRegionsTester, Obscuration) { + SCOPED_GFX_PREF(LayoutEventRegionsEnabled, bool, true); + + CreateObscuringLayerTree(); + ScopedLayerTreeRegistration registration(0, root, mcc); + + manager->UpdateHitTestingTree(nullptr, root, false, 0, 0); + + TestAsyncPanZoomController* parent = ApzcOf(layers[1]); + TestAsyncPanZoomController* child = ApzcOf(layers[2]); + + int time = 0; + ApzcPanNoFling(parent, time, 75, 25); + + HitTestResult result; + nsRefPtr hit = manager->GetTargetAPZC(ScreenPoint(50, 75), &result); + EXPECT_EQ(child, hit.get()); + EXPECT_EQ(HitTestResult::ApzcHitRegion, result); +} + class TaskRunMetrics { public: TaskRunMetrics() diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxASurface.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxASurface.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxASurface.cpp 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxASurface.cpp 2015-01-09 12:36:27.000000000 +0000 @@ -588,7 +588,7 @@ NS_DECL_ISUPPORTS NS_IMETHOD CollectReports(nsIMemoryReporterCallback *aCb, - nsISupports *aClosure, bool aAnonymize) + nsISupports *aClosure, bool aAnonymize) MOZ_OVERRIDE { const size_t len = ArrayLength(sSurfaceMemoryReporterAttrs); for (size_t i = 0; i < len; i++) { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxContext.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxContext.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxContext.cpp 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxContext.cpp 2015-01-09 12:36:27.000000000 +0000 @@ -27,7 +27,7 @@ #include "mozilla/gfx/DrawTargetTiled.h" #include -#if CAIRO_HAS_DWRITE_FONT +#if XP_WIN #include "gfxWindowsPlatform.h" #endif @@ -1309,7 +1309,11 @@ newDT = mDT->CreateSimilarDrawTarget(IntSize(64, 64), format); if (!newDT) { - if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) { + if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset() +#ifdef XP_WIN + && !(mDT->GetBackendType() == BackendType::DIRECT2D1_1 && !gfxWindowsPlatform::GetPlatform()->GetD3D11ContentDevice()) +#endif + ) { // If even this fails.. we're most likely just out of memory! NS_ABORT_OOM(BytesPerPixel(format) * 64 * 64); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxDWriteFontList.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxDWriteFontList.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxDWriteFontList.cpp 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxDWriteFontList.cpp 2015-01-09 12:36:27.000000000 +0000 @@ -96,14 +96,8 @@ return S_OK; } -// These strings are only defined in Win SDK 8+, so use #ifdef for now -#if MOZ_WINSDK_TARGETVER > 0x08000000 #define FULLNAME_ID DWRITE_INFORMATIONAL_STRING_FULL_NAME #define PSNAME_ID DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME -#else -#define FULLNAME_ID DWRITE_INFORMATIONAL_STRING_ID(DWRITE_INFORMATIONAL_STRING_SAMPLE_TEXT + 1) -#define PSNAME_ID DWRITE_INFORMATIONAL_STRING_ID(DWRITE_INFORMATIONAL_STRING_SAMPLE_TEXT + 2) -#endif // for use in reading postscript or fullname static HRESULT diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxFont.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxFont.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxFont.cpp 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxFont.cpp 2015-01-09 12:36:27.000000000 +0000 @@ -2490,7 +2490,8 @@ NS_WARN_IF_FALSE(ok, "shaper failed, expect scrambled or missing text"); - PostShapingFixup(aContext, aText, aOffset, aLength, aShapedText); + PostShapingFixup(aContext, aText, aOffset, aLength, aVertical, + aShapedText); return ok; } @@ -2500,13 +2501,18 @@ const char16_t *aText, uint32_t aOffset, uint32_t aLength, + bool aVertical, gfxShapedText *aShapedText) { if (IsSyntheticBold()) { - float synBoldOffset = - GetSyntheticBoldOffset() * CalcXScale(aContext); - aShapedText->AdjustAdvancesForSyntheticBold(synBoldOffset, - aOffset, aLength); + const Metrics& metrics = + GetMetrics(aVertical ? eVertical : eHorizontal); + if (metrics.maxAdvance > metrics.aveCharWidth) { + float synBoldOffset = + GetSyntheticBoldOffset() * CalcXScale(aContext); + aShapedText->AdjustAdvancesForSyntheticBold(synBoldOffset, + aOffset, aLength); + } } } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxFont.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxFont.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxFont.h 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxFont.h 2015-01-09 12:36:27.000000000 +0000 @@ -1881,6 +1881,7 @@ const char16_t *aText, uint32_t aOffset, // position within aShapedText uint32_t aLength, + bool aVertical, gfxShapedText *aShapedText); // Shape text directly into a range within a textrun, without using the diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxFontInfoLoader.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxFontInfoLoader.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxFontInfoLoader.cpp 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxFontInfoLoader.cpp 2015-01-09 12:36:27.000000000 +0000 @@ -35,7 +35,7 @@ mFontInfo(aFontInfo) {} - NS_IMETHOD Run(); + NS_IMETHOD Run() MOZ_OVERRIDE; nsRefPtr mFontInfo; }; @@ -51,7 +51,7 @@ mCompleteEvent = new FontInfoLoadCompleteEvent(aFontInfo); } - NS_IMETHOD Run(); + NS_IMETHOD Run() MOZ_OVERRIDE; nsRefPtr mFontInfo; nsRefPtr mCompleteEvent; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxFT2FontList.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxFT2FontList.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxFT2FontList.cpp 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxFT2FontList.cpp 2015-01-09 12:36:27.000000000 +0000 @@ -692,7 +692,7 @@ FNCMapEntry* mapEntry = static_cast - (PL_DHashTableOperate(&mMap, filename.get(), PL_DHASH_ADD)); + (PL_DHashTableAdd(&mMap, filename.get())); if (mapEntry) { mapEntry->mFilename.Assign(filename); mapEntry->mTimestamp = timestamp; @@ -719,7 +719,7 @@ return; } PLDHashEntryHdr *hdr = - PL_DHashTableOperate(&mMap, aFileName.get(), PL_DHASH_LOOKUP); + PL_DHashTableLookup(&mMap, aFileName.get()); if (!hdr) { return; } @@ -744,7 +744,7 @@ } FNCMapEntry* entry = static_cast - (PL_DHashTableOperate(&mMap, aFileName.get(), PL_DHASH_ADD)); + (PL_DHashTableAdd(&mMap, aFileName.get())); if (entry) { entry->mFilename.Assign(aFileName); entry->mTimestamp = aTimestamp; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxFT2Fonts.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxFT2Fonts.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxFT2Fonts.cpp 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxFT2Fonts.cpp 2015-01-09 12:36:27.000000000 +0000 @@ -55,7 +55,8 @@ aVertical, aShapedText)) { // harfbuzz must have failed(?!), just render raw glyphs AddRange(aText, aOffset, aLength, aShapedText); - PostShapingFixup(aContext, aText, aOffset, aLength, aShapedText); + PostShapingFixup(aContext, aText, aOffset, aLength, aVertical, + aShapedText); } return true; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxImageSurface.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxImageSurface.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxImageSurface.h 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxImageSurface.h 2015-01-09 12:36:27.000000000 +0000 @@ -76,7 +76,7 @@ // ImageSurface methods gfxImageFormat Format() const { return mFormat; } - virtual const gfxIntSize GetSize() const { return mSize; } + virtual const gfxIntSize GetSize() const MOZ_OVERRIDE { return mSize; } int32_t Width() const { return mSize.width; } int32_t Height() const { return mSize.height; } @@ -121,7 +121,7 @@ */ already_AddRefed GetSubimage(const gfxRect& aRect); - virtual already_AddRefed GetAsImageSurface(); + virtual already_AddRefed GetAsImageSurface() MOZ_OVERRIDE; /** See gfxASurface.h. */ static long ComputeStride(const gfxIntSize&, gfxImageFormat); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxMacFont.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxMacFont.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxMacFont.cpp 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxMacFont.cpp 2015-01-09 12:36:27.000000000 +0000 @@ -143,7 +143,8 @@ } if (mCoreTextShaper->ShapeText(aContext, aText, aOffset, aLength, aScript, aVertical, aShapedText)) { - PostShapingFixup(aContext, aText, aOffset, aLength, aShapedText); + PostShapingFixup(aContext, aText, aOffset, aLength, aVertical, + aShapedText); return true; } } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxMacFont.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxMacFont.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxMacFont.h 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxMacFont.h 2015-01-09 12:36:27.000000000 +0000 @@ -55,9 +55,9 @@ GetGlyphRenderingOptions(const TextRunDrawParams* aRunParams = nullptr) MOZ_OVERRIDE; virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf, - FontCacheSizes* aSizes) const; + FontCacheSizes* aSizes) const MOZ_OVERRIDE; virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, - FontCacheSizes* aSizes) const; + FontCacheSizes* aSizes) const MOZ_OVERRIDE; virtual FontType GetType() const MOZ_OVERRIDE { return FONT_TYPE_MAC; } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxMacPlatformFontList.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxMacPlatformFontList.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxMacPlatformFontList.h 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxMacPlatformFontList.h 2015-01-09 12:36:27.000000000 +0000 @@ -46,18 +46,18 @@ virtual hb_blob_t *GetFontTable(uint32_t aTag) MOZ_OVERRIDE; virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, - FontListSizes* aSizes) const; + FontListSizes* aSizes) const MOZ_OVERRIDE; - nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr); + nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr) MOZ_OVERRIDE; bool RequiresAATLayout() const { return mRequiresAAT; } bool IsCFF(); protected: - virtual gfxFont* CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold); + virtual gfxFont* CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold) MOZ_OVERRIDE; - virtual bool HasFontTable(uint32_t aTableTag); + virtual bool HasFontTable(uint32_t aTableTag) MOZ_OVERRIDE; static void DestroyBlobFunc(void* aUserData); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxPlatform.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxPlatform.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxPlatform.cpp 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxPlatform.cpp 2015-01-09 12:36:27.000000000 +0000 @@ -702,7 +702,7 @@ // cairo_debug_* function unconditionally. // // because cairo can assert and thus crash on shutdown, don't do this in release builds -#if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING) || defined(NS_TRACE_MALLOC) || defined(MOZ_VALGRIND) +#if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING) || defined(MOZ_VALGRIND) #ifdef USE_SKIA // must do Skia cleanup before Cairo cleanup, because Skia may be referencing // Cairo objects e.g. through SkCairoFTTypeface @@ -1182,16 +1182,16 @@ { NS_ASSERTION(mContentBackend != BackendType::NONE, "No backend."); - RefPtr dt = Factory::CreateDrawTargetForData(mContentBackend, + BackendType backendType = mContentBackend; + + if (!Factory::DoesBackendSupportDataDrawtarget(mContentBackend)) { + backendType = BackendType::CAIRO; + } + + RefPtr dt = Factory::CreateDrawTargetForData(backendType, aData, aSize, aStride, aFormat); - if (!dt) { - // Factory::CreateDrawTargetForData does not support mContentBackend; retry - // with BackendType::CAIRO: - dt = Factory::CreateDrawTargetForData(BackendType::CAIRO, - aData, aSize, - aStride, aFormat); - } + return dt.forget(); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxPlatformMac.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxPlatformMac.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxPlatformMac.h 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxPlatformMac.h 2015-01-09 12:36:27.000000000 +0000 @@ -30,39 +30,39 @@ gfxContentType contentType) MOZ_OVERRIDE; mozilla::TemporaryRef - GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont); + GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont) MOZ_OVERRIDE; - nsresult GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName); + nsresult GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName) MOZ_OVERRIDE; gfxFontGroup* CreateFontGroup(const mozilla::FontFamilyList& aFontFamilyList, const gfxFontStyle *aStyle, - gfxUserFontSet *aUserFontSet); + gfxUserFontSet *aUserFontSet) MOZ_OVERRIDE; virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName, uint16_t aWeight, int16_t aStretch, - bool aItalic); + bool aItalic) MOZ_OVERRIDE; - virtual gfxPlatformFontList* CreatePlatformFontList(); + virtual gfxPlatformFontList* CreatePlatformFontList() MOZ_OVERRIDE; virtual gfxFontEntry* MakePlatformFont(const nsAString& aFontName, uint16_t aWeight, int16_t aStretch, bool aItalic, const uint8_t* aFontData, - uint32_t aLength); + uint32_t aLength) MOZ_OVERRIDE; - bool IsFontFormatSupported(nsIURI *aFontURI, uint32_t aFormatFlags); + bool IsFontFormatSupported(nsIURI *aFontURI, uint32_t aFormatFlags) MOZ_OVERRIDE; nsresult GetFontList(nsIAtom *aLangGroup, const nsACString& aGenericFamily, - nsTArray& aListOfFonts); - nsresult UpdateFontList(); + nsTArray& aListOfFonts) MOZ_OVERRIDE; + nsresult UpdateFontList() MOZ_OVERRIDE; virtual void GetCommonFallbackFonts(uint32_t aCh, uint32_t aNextCh, int32_t aRunScript, - nsTArray& aFontList); + nsTArray& aFontList) MOZ_OVERRIDE; virtual bool CanRenderContentToDataSurface() const MOZ_OVERRIDE { return true; @@ -77,7 +77,7 @@ uint32_t GetAntiAliasingThreshold() { return mFontAntiAliasingThreshold; } private: - virtual void GetPlatformCMSOutputProfile(void* &mem, size_t &size); + virtual void GetPlatformCMSOutputProfile(void* &mem, size_t &size) MOZ_OVERRIDE; // read in the pref value for the lower threshold on font anti-aliasing static uint32_t ReadAntiAliasingThreshold(); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxPrefs.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxPrefs.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxPrefs.h 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxPrefs.h 2015-01-09 12:36:27.000000000 +0000 @@ -245,7 +245,6 @@ DECL_GFX_PREF(Once, "image.mem.surfacecache.min_expiration_ms", ImageMemSurfaceCacheMinExpirationMS, uint32_t, 60*1000); DECL_GFX_PREF(Once, "image.mem.surfacecache.size_factor", ImageMemSurfaceCacheSizeFactor, uint32_t, 64); DECL_GFX_PREF(Live, "image.mozsamplesize.enabled", ImageMozSampleSizeEnabled, bool, false); - DECL_GFX_PREF(Live, "image.multithreaded_decoding.enabled", ImageMTDecodingEnabled, bool, true); DECL_GFX_PREF(Live, "image.multithreaded_decoding.limit", ImageMTDecodingLimit, int32_t, -1); DECL_GFX_PREF(Once, "layers.acceleration.disabled", LayersAccelerationDisabled, bool, false); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxReusableImageSurfaceWrapper.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxReusableImageSurfaceWrapper.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxReusableImageSurfaceWrapper.h 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxReusableImageSurfaceWrapper.h 2015-01-09 12:36:27.000000000 +0000 @@ -26,7 +26,7 @@ void ReadLock() MOZ_OVERRIDE; void ReadUnlock() MOZ_OVERRIDE; - Type GetType() + Type GetType() MOZ_OVERRIDE { return TYPE_IMAGE; } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxReusableSharedImageSurfaceWrapper.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxReusableSharedImageSurfaceWrapper.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxReusableSharedImageSurfaceWrapper.h 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxReusableSharedImageSurfaceWrapper.h 2015-01-09 12:36:27.000000000 +0000 @@ -37,7 +37,7 @@ void ReadLock() MOZ_OVERRIDE; void ReadUnlock() MOZ_OVERRIDE; - Type GetType() + Type GetType() MOZ_OVERRIDE { return TYPE_SHARED_IMAGE; } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxVR.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxVR.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxVR.cpp 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxVR.cpp 2015-01-09 12:36:27.000000000 +0000 @@ -195,35 +195,35 @@ NS_DECL_ISUPPORTS - NS_IMETHOD GetRect(int32_t *l, int32_t *t, int32_t *w, int32_t *h) { + NS_IMETHOD GetRect(int32_t *l, int32_t *t, int32_t *w, int32_t *h) MOZ_OVERRIDE { *l = mScreenRect.x; *t = mScreenRect.y; *w = mScreenRect.width; *h = mScreenRect.height; return NS_OK; } - NS_IMETHOD GetAvailRect(int32_t *l, int32_t *t, int32_t *w, int32_t *h) { + NS_IMETHOD GetAvailRect(int32_t *l, int32_t *t, int32_t *w, int32_t *h) MOZ_OVERRIDE { return GetRect(l, t, w, h); } - NS_IMETHOD GetRectDisplayPix(int32_t *l, int32_t *t, int32_t *w, int32_t *h) { + NS_IMETHOD GetRectDisplayPix(int32_t *l, int32_t *t, int32_t *w, int32_t *h) MOZ_OVERRIDE { return GetRect(l, t, w, h); } - NS_IMETHOD GetAvailRectDisplayPix(int32_t *l, int32_t *t, int32_t *w, int32_t *h) { + NS_IMETHOD GetAvailRectDisplayPix(int32_t *l, int32_t *t, int32_t *w, int32_t *h) MOZ_OVERRIDE { return GetAvailRect(l, t, w, h); } - NS_IMETHOD GetId(uint32_t* aId) { *aId = (uint32_t)-1; return NS_OK; } - NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth) { *aPixelDepth = 24; return NS_OK; } - NS_IMETHOD GetColorDepth(int32_t* aColorDepth) { *aColorDepth = 24; return NS_OK; } + NS_IMETHOD GetId(uint32_t* aId) MOZ_OVERRIDE { *aId = (uint32_t)-1; return NS_OK; } + NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth) MOZ_OVERRIDE { *aPixelDepth = 24; return NS_OK; } + NS_IMETHOD GetColorDepth(int32_t* aColorDepth) MOZ_OVERRIDE { *aColorDepth = 24; return NS_OK; } - NS_IMETHOD LockMinimumBrightness(uint32_t aBrightness) { return NS_ERROR_NOT_AVAILABLE; } - NS_IMETHOD UnlockMinimumBrightness(uint32_t aBrightness) { return NS_ERROR_NOT_AVAILABLE; } - NS_IMETHOD GetRotation(uint32_t* aRotation) { + NS_IMETHOD LockMinimumBrightness(uint32_t aBrightness) MOZ_OVERRIDE { return NS_ERROR_NOT_AVAILABLE; } + NS_IMETHOD UnlockMinimumBrightness(uint32_t aBrightness) MOZ_OVERRIDE { return NS_ERROR_NOT_AVAILABLE; } + NS_IMETHOD GetRotation(uint32_t* aRotation) MOZ_OVERRIDE { *aRotation = nsIScreen::ROTATION_0_DEG; return NS_OK; } - NS_IMETHOD SetRotation(uint32_t aRotation) { return NS_ERROR_NOT_AVAILABLE; } - NS_IMETHOD GetContentsScaleFactor(double* aContentsScaleFactor) { + NS_IMETHOD SetRotation(uint32_t aRotation) MOZ_OVERRIDE { return NS_ERROR_NOT_AVAILABLE; } + NS_IMETHOD GetContentsScaleFactor(double* aContentsScaleFactor) MOZ_OVERRIDE { *aContentsScaleFactor = 1.0; return NS_OK; } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxWindowsPlatform.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxWindowsPlatform.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/gfxWindowsPlatform.cpp 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/gfxWindowsPlatform.cpp 2015-01-09 12:36:27.000000000 +0000 @@ -23,6 +23,7 @@ #include "nsIFile.h" #include "plbase64.h" #include "nsIXULRuntime.h" +#include "imgLoader.h" #include "nsIGfxInfo.h" #include "GfxDriverInfo.h" @@ -384,6 +385,17 @@ /* Pick the default render mode for * desktop. */ + if (DidRenderingDeviceReset()) { + mD3D11DeviceInitialized = false; + mD3D11Device = nullptr; + mD3D11ContentDevice = nullptr; + mAdapter = nullptr; + + imgLoader::Singleton()->ClearCache(true); + imgLoader::Singleton()->ClearCache(false); + Factory::SetDirect3D11Device(nullptr); + } + mRenderMode = RENDER_GDI; bool isVistaOrHigher = IsVistaOrLater(); @@ -485,18 +497,14 @@ if (mRenderMode == RENDER_DIRECT2D) { canvasMask |= BackendTypeBit(BackendType::DIRECT2D); contentMask |= BackendTypeBit(BackendType::DIRECT2D); -#ifdef USE_D2D1_1 if (gfxPrefs::Direct2DUse1_1() && Factory::SupportsD2D1() && GetD3D11ContentDevice()) { contentMask |= BackendTypeBit(BackendType::DIRECT2D1_1); canvasMask |= BackendTypeBit(BackendType::DIRECT2D1_1); defaultBackend = BackendType::DIRECT2D1_1; } else { -#endif defaultBackend = BackendType::DIRECT2D; -#ifdef USE_D2D1_1 } -#endif } else { canvasMask |= BackendTypeBit(BackendType::SKIA); } @@ -619,14 +627,12 @@ mozilla::gfx::Factory::SetDirect3D10Device(cairo_d2d_device_get_device(mD2DDevice)); } -#ifdef USE_D2D1_1 ScopedGfxFeatureReporter reporter1_1("D2D1.1"); if (Factory::SupportsD2D1()) { reporter1_1.SetSuccessful(); } #endif -#endif } gfxPlatformFontList* @@ -1041,7 +1047,22 @@ bool gfxWindowsPlatform::DidRenderingDeviceReset() { - return GetD3D10Device() && GetD3D10Device()->GetDeviceRemovedReason() != S_OK; + if (mD3D11Device) { + if (mD3D11Device->GetDeviceRemovedReason() != S_OK) { + return true; + } + } + if (mD3D11ContentDevice) { + if (mD3D11ContentDevice->GetDeviceRemovedReason() != S_OK) { + return true; + } + } + if (GetD3D10Device()) { + if (GetD3D10Device()->GetDeviceRemovedReason() != S_OK) { + return true; + } + } + return false; } gfxFontFamily * @@ -1825,7 +1846,6 @@ mD3D11Device->SetExceptionMode(0); -#ifdef USE_D2D1_1 // We create our device for D2D content drawing here. Normally we don't use // D2D content drawing when using WARP. However when WARP is forced by // default we will let Direct2D use WARP as well. @@ -1851,7 +1871,6 @@ Factory::SetDirect3D11Device(mD3D11ContentDevice); } -#endif // We leak these everywhere and we need them our entire runtime anyway, let's // leak it here as well. diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/moz.build thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/moz.build --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/moz.build 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/moz.build 2015-01-09 12:36:27.000000000 +0000 @@ -188,8 +188,6 @@ 'gfxDWriteCommon.cpp', 'gfxDWriteFonts.cpp', ] - if CONFIG['MOZ_ENABLE_DIRECT2D1_1']: - DEFINES['USE_D2D1_1'] = True # Are we targeting x86 or x64? If so, build gfxAlphaRecoverySSE2.cpp. if CONFIG['INTEL_ARCHITECTURE']: diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/VsyncSource.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/VsyncSource.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/gfx/thebes/VsyncSource.cpp 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/gfx/thebes/VsyncSource.cpp 2015-01-09 12:36:27.000000000 +0000 @@ -7,6 +7,7 @@ #include "gfxPlatform.h" #include "mozilla/TimeStamp.h" #include "mozilla/VsyncDispatcher.h" +#include "MainThreadUtils.h" using namespace mozilla; using namespace mozilla::gfx; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/hal/gonk/GonkHal.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/hal/gonk/GonkHal.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/hal/gonk/GonkHal.cpp 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/hal/gonk/GonkHal.cpp 2015-01-09 12:36:27.000000000 +0000 @@ -48,6 +48,7 @@ #include "HalLog.h" #include "mozilla/ArrayUtils.h" #include "mozilla/dom/battery/Constants.h" +#include "mozilla/DebugOnly.h" #include "mozilla/FileUtils.h" #include "mozilla/Monitor.h" #include "mozilla/RefPtr.h" @@ -529,7 +530,7 @@ static bool GetCurrentBatteryCharging(int* aCharging) { - static const int BATTERY_NOT_CHARGING = 0; + static const DebugOnly BATTERY_NOT_CHARGING = 0; static const int BATTERY_CHARGING_USB = 1; static const int BATTERY_CHARGING_AC = 2; @@ -1313,8 +1314,8 @@ nsAutoCString adjParams; nsAutoCString minfreeParams; - int32_t lowerBoundOfNextOomScoreAdj = OOM_SCORE_ADJ_MIN - 1; - int32_t lowerBoundOfNextKillUnderKB = 0; + DebugOnly lowerBoundOfNextOomScoreAdj = OOM_SCORE_ADJ_MIN - 1; + DebugOnly lowerBoundOfNextKillUnderKB = 0; int32_t countOfLowmemorykillerParametersSets = 0; long page_size = sysconf(_SC_PAGESIZE); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/decoders/nsBMPDecoder.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/decoders/nsBMPDecoder.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/decoders/nsBMPDecoder.cpp 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/decoders/nsBMPDecoder.cpp 2015-01-09 12:36:28.000000000 +0000 @@ -39,17 +39,22 @@ #define PIXEL_OFFSET(row, col) (LINE(row) * mBIH.width + col) nsBMPDecoder::nsBMPDecoder(RasterImage& aImage) - : Decoder(aImage) -{ - mColors = nullptr; - mRow = nullptr; - mCurPos = mPos = mNumColors = mRowBytes = 0; - mOldLine = mCurLine = 1; // Otherwise decoder will never start - mState = eRLEStateInitial; - mStateData = 0; - mLOH = WIN_V3_HEADER_LENGTH; - mUseAlphaData = mHaveAlphaData = false; -} + : Decoder(aImage) + , mPos(0) + , mLOH(WIN_V3_HEADER_LENGTH) + , mNumColors(0) + , mColors(nullptr) + , mRow(nullptr) + , mRowBytes(0) + , mCurLine(1) // Otherwise decoder will never start. + , mOldLine(1) + , mCurPos(0) + , mState(eRLEStateInitial) + , mStateData(0) + , mProcessedHeader(false) + , mUseAlphaData(false) + , mHaveAlphaData(false) +{ } nsBMPDecoder::~nsBMPDecoder() { @@ -144,9 +149,9 @@ PostInvalidation(r); if (mUseAlphaData) { - PostFrameStop(FrameBlender::kFrameHasAlpha); + PostFrameStop(Opacity::SOME_TRANSPARENCY); } else { - PostFrameStop(FrameBlender::kFrameOpaque); + PostFrameStop(Opacity::OPAQUE); } PostDecodeDone(); } @@ -194,8 +199,7 @@ } void -nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount, - DecodeStrategy) +nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount) { NS_ABORT_IF_FALSE(!HasError(), "Shouldn't call WriteInternal after error!"); @@ -327,10 +331,12 @@ // data. In the latter case aCount should be 0. MOZ_ASSERT(mPos >= mLOH || aCount == 0); - // HasSize is called to ensure that if at this point mPos == mLOH but - // we have no data left to process, the next time WriteInternal is called + // mProcessedHeader is checked to ensure that if at this point mPos == mLOH + // but we have no data left to process, the next time WriteInternal is called // we won't enter this condition again. - if (mPos == mLOH && !HasSize()) { + if (mPos == mLOH && !mProcessedHeader) { + mProcessedHeader = true; + ProcessInfoHeader(); PR_LOG(GetBMPLog(), PR_LOG_DEBUG, ("BMP is %lix%lix%lu. compression=%lu\n", diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/decoders/nsBMPDecoder.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/decoders/nsBMPDecoder.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/decoders/nsBMPDecoder.h 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/decoders/nsBMPDecoder.h 2015-01-09 12:36:28.000000000 +0000 @@ -50,8 +50,8 @@ // for 32BPP bitmaps. Only use after the bitmap has been processed. bool HasAlphaData() const; - virtual void WriteInternal(const char* aBuffer, uint32_t aCount, - DecodeStrategy aStrategy) MOZ_OVERRIDE; + virtual void WriteInternal(const char* aBuffer, + uint32_t aCount) MOZ_OVERRIDE; virtual void FinishInternal() MOZ_OVERRIDE; private: @@ -94,6 +94,9 @@ /// data to native data as necessary void ProcessInfoHeader(); + /// True if we've already processed the BMP header. + bool mProcessedHeader; + // Stores whether the image data may store alpha data, or if // the alpha data is unspecified and filled with a padding byte of 0. // When a 32BPP bitmap is stored in an ICO or CUR file, its 4th byte diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/decoders/nsGIFDecoder2.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/decoders/nsGIFDecoder2.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/decoders/nsGIFDecoder2.cpp 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/decoders/nsGIFDecoder2.cpp 2015-01-09 12:36:28.000000000 +0000 @@ -199,12 +199,6 @@ NeedNewFrame(mGIFStruct.images_decoded, mGIFStruct.x_offset, mGIFStruct.y_offset, mGIFStruct.width, mGIFStruct.height, format); - } else { - // Our preallocated frame matches up, with the possible exception - // of alpha. - if (format == gfx::SurfaceFormat::B8G8R8X8) { - currentFrame->SetHasNoAlpha(); - } } } @@ -216,7 +210,7 @@ void nsGIFDecoder2::EndImageFrame() { - FrameBlender::FrameAlpha alpha = FrameBlender::kFrameHasAlpha; + Opacity opacity = Opacity::SOME_TRANSPARENCY; // First flush all pending image data if (!mGIFStruct.images_decoded) { @@ -233,9 +227,13 @@ mGIFStruct.screen_height - realFrameHeight); PostInvalidation(r); } - // This transparency check is only valid for first frame - if (mGIFStruct.is_transparent && !mSawTransparency) { - alpha = FrameBlender::kFrameOpaque; + + // The first frame was preallocated with alpha; if it wasn't transparent, we + // should fix that. We can also mark it opaque unconditionally if we didn't + // actually see any transparent pixels - this test is only valid for the + // first frame. + if (!mGIFStruct.is_transparent || !mSawTransparency) { + opacity = Opacity::OPAQUE; } } mCurrentRow = mLastFlushedRow = -1; @@ -259,8 +257,8 @@ mGIFStruct.images_decoded++; // Tell the superclass we finished a frame - PostFrameStop(alpha, - FrameBlender::FrameDisposalMethod(mGIFStruct.disposal_method), + PostFrameStop(opacity, + DisposalMethod(mGIFStruct.disposal_method), mGIFStruct.delay_time); // Reset the transparent pixel @@ -569,8 +567,7 @@ } void -nsGIFDecoder2::WriteInternal(const char* aBuffer, uint32_t aCount, - DecodeStrategy) +nsGIFDecoder2::WriteInternal(const char* aBuffer, uint32_t aCount) { NS_ABORT_IF_FALSE(!HasError(), "Shouldn't call WriteInternal after error!"); @@ -830,10 +827,9 @@ } { - int32_t method = - FrameBlender::FrameDisposalMethod(mGIFStruct.disposal_method); - if (method == FrameBlender::kDisposeClearAll || - method == FrameBlender::kDisposeClear) { + DisposalMethod method = DisposalMethod(mGIFStruct.disposal_method); + if (method == DisposalMethod::CLEAR_ALL || + method == DisposalMethod::CLEAR) { // We may have to display the background under this image during // animation playback, so we regard it as transparent. PostHasTransparency(); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/decoders/nsGIFDecoder2.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/decoders/nsGIFDecoder2.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/decoders/nsGIFDecoder2.h 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/decoders/nsGIFDecoder2.h 2015-01-09 12:36:28.000000000 +0000 @@ -26,8 +26,7 @@ explicit nsGIFDecoder2(RasterImage& aImage); ~nsGIFDecoder2(); - virtual void WriteInternal(const char* aBuffer, uint32_t aCount, - DecodeStrategy aStrategy) MOZ_OVERRIDE; + virtual void WriteInternal(const char* aBuffer, uint32_t aCount) MOZ_OVERRIDE; virtual void FinishInternal() MOZ_OVERRIDE; virtual Telemetry::ID SpeedHistogram() MOZ_OVERRIDE; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/decoders/nsICODecoder.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/decoders/nsICODecoder.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/decoders/nsICODecoder.cpp 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/decoders/nsICODecoder.cpp 2015-01-09 12:36:28.000000000 +0000 @@ -214,14 +214,13 @@ } void -nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount, - DecodeStrategy aStrategy) +nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount) { NS_ABORT_IF_FALSE(!HasError(), "Shouldn't call WriteInternal after error!"); if (!aCount) { if (mContainedDecoder) { - WriteToContainedDecoder(aBuffer, aCount, aStrategy); + WriteToContainedDecoder(aBuffer, aCount); } return; } @@ -346,7 +345,7 @@ mContainedDecoder->InitSharedDecoder(mImageData, mImageDataLength, mColormap, mColormapSize, Move(mRefForContainedDecoder)); - if (!WriteToContainedDecoder(mSignature, PNGSIGNATURESIZE, aStrategy)) { + if (!WriteToContainedDecoder(mSignature, PNGSIGNATURESIZE)) { return; } } @@ -354,7 +353,7 @@ // If we have a PNG, let the PNG decoder do all of the rest of the work if (mIsPNG && mContainedDecoder && mPos >= mImageOffset + PNGSIGNATURESIZE) { - if (!WriteToContainedDecoder(aBuffer, aCount, aStrategy)) { + if (!WriteToContainedDecoder(aBuffer, aCount)) { return; } @@ -433,8 +432,7 @@ PostDataError(); return; } - if (!WriteToContainedDecoder((const char*)bfhBuffer, sizeof(bfhBuffer), - aStrategy)) { + if (!WriteToContainedDecoder((const char*)bfhBuffer, sizeof(bfhBuffer))) { return; } @@ -455,7 +453,7 @@ } // Write out the BMP's bitmap info header - if (!WriteToContainedDecoder(mBIHraw, sizeof(mBIHraw), aStrategy)) { + if (!WriteToContainedDecoder(mBIHraw, sizeof(mBIHraw))) { return; } @@ -505,7 +503,7 @@ toFeed = aCount; } - if (!WriteToContainedDecoder(aBuffer, toFeed, aStrategy)) { + if (!WriteToContainedDecoder(aBuffer, toFeed)) { return; } @@ -594,10 +592,9 @@ } bool -nsICODecoder::WriteToContainedDecoder(const char* aBuffer, uint32_t aCount, - DecodeStrategy aStrategy) +nsICODecoder::WriteToContainedDecoder(const char* aBuffer, uint32_t aCount) { - mContainedDecoder->Write(aBuffer, aCount, aStrategy); + mContainedDecoder->Write(aBuffer, aCount); mProgress |= mContainedDecoder->TakeProgress(); mInvalidRect.Union(mContainedDecoder->TakeInvalidRect()); if (mContainedDecoder->HasDataError()) { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/decoders/nsICODecoder.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/decoders/nsICODecoder.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/decoders/nsICODecoder.h 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/decoders/nsICODecoder.h 2015-01-09 12:36:28.000000000 +0000 @@ -38,17 +38,17 @@ return mDirEntry.mHeight == 0 ? 256 : mDirEntry.mHeight; } - virtual void WriteInternal(const char* aBuffer, uint32_t aCount, - DecodeStrategy aStrategy) MOZ_OVERRIDE; + virtual void WriteInternal(const char* aBuffer, uint32_t aCount) MOZ_OVERRIDE; virtual void FinishInternal() MOZ_OVERRIDE; - virtual bool NeedsNewFrame() const MOZ_OVERRIDE; virtual nsresult AllocateFrame() MOZ_OVERRIDE; +protected: + virtual bool NeedsNewFrame() const MOZ_OVERRIDE; + private: // Writes to the contained decoder and sets the appropriate errors // Returns true if there are no errors. - bool WriteToContainedDecoder(const char* aBuffer, uint32_t aCount, - DecodeStrategy aStrategy); + bool WriteToContainedDecoder(const char* aBuffer, uint32_t aCount); // Processes a single dir entry of the icon resource void ProcessDirEntry(IconDirEntry& aTarget); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/decoders/nsIconDecoder.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/decoders/nsIconDecoder.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/decoders/nsIconDecoder.cpp 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/decoders/nsIconDecoder.cpp 2015-01-09 12:36:28.000000000 +0000 @@ -29,8 +29,7 @@ { } void -nsIconDecoder::WriteInternal(const char* aBuffer, uint32_t aCount, - DecodeStrategy) +nsIconDecoder::WriteInternal(const char* aBuffer, uint32_t aCount) { NS_ABORT_IF_FALSE(!HasError(), "Shouldn't call WriteInternal after error!"); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/decoders/nsIconDecoder.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/decoders/nsIconDecoder.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/decoders/nsIconDecoder.h 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/decoders/nsIconDecoder.h 2015-01-09 12:36:28.000000000 +0000 @@ -41,8 +41,7 @@ explicit nsIconDecoder(RasterImage& aImage); virtual ~nsIconDecoder(); - virtual void WriteInternal(const char* aBuffer, uint32_t aCount, - DecodeStrategy aStrategy) MOZ_OVERRIDE; + virtual void WriteInternal(const char* aBuffer, uint32_t aCount) MOZ_OVERRIDE; uint8_t mWidth; uint8_t mHeight; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/decoders/nsJPEGDecoder.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/decoders/nsJPEGDecoder.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/decoders/nsJPEGDecoder.cpp 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/decoders/nsJPEGDecoder.cpp 2015-01-09 12:36:28.000000000 +0000 @@ -190,8 +190,7 @@ } void -nsJPEGDecoder::WriteInternal(const char* aBuffer, uint32_t aCount, - DecodeStrategy) +nsJPEGDecoder::WriteInternal(const char* aBuffer, uint32_t aCount) { mSegment = (const JOCTET*)aBuffer; mSegmentLen = aCount; @@ -580,7 +579,7 @@ void nsJPEGDecoder::NotifyDone() { - PostFrameStop(FrameBlender::kFrameOpaque); + PostFrameStop(Opacity::OPAQUE); PostDecodeDone(); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/decoders/nsJPEGDecoder.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/decoders/nsJPEGDecoder.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/decoders/nsJPEGDecoder.h 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/decoders/nsJPEGDecoder.h 2015-01-09 12:36:28.000000000 +0000 @@ -56,8 +56,7 @@ virtual ~nsJPEGDecoder(); virtual void InitInternal() MOZ_OVERRIDE; - virtual void WriteInternal(const char* aBuffer, uint32_t aCount, - DecodeStrategy aStrategy) MOZ_OVERRIDE; + virtual void WriteInternal(const char* aBuffer, uint32_t aCount) MOZ_OVERRIDE; virtual void FinishInternal() MOZ_OVERRIDE; virtual Telemetry::ID SpeedHistogram() MOZ_OVERRIDE; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/decoders/nsPNGDecoder.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/decoders/nsPNGDecoder.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/decoders/nsPNGDecoder.cpp 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/decoders/nsPNGDecoder.cpp 2015-01-09 12:36:28.000000000 +0000 @@ -54,15 +54,15 @@ #define BYTES_NEEDED_FOR_DIMENSIONS (HEIGHT_OFFSET + 4) nsPNGDecoder::AnimFrameInfo::AnimFrameInfo() - : mDispose(FrameBlender::kDisposeKeep) - , mBlend(FrameBlender::kBlendOver) + : mDispose(DisposalMethod::KEEP) + , mBlend(BlendMethod::OVER) , mTimeout(0) { } #ifdef PNG_APNG_SUPPORTED nsPNGDecoder::AnimFrameInfo::AnimFrameInfo(png_structp aPNG, png_infop aInfo) - : mDispose(FrameBlender::kDisposeKeep) - , mBlend(FrameBlender::kBlendOver) + : mDispose(DisposalMethod::KEEP) + , mBlend(BlendMethod::OVER) , mTimeout(0) { png_uint_16 delay_num, delay_den; @@ -88,17 +88,17 @@ } if (dispose_op == PNG_DISPOSE_OP_PREVIOUS) { - mDispose = FrameBlender::kDisposeRestorePrevious; + mDispose = DisposalMethod::RESTORE_PREVIOUS; } else if (dispose_op == PNG_DISPOSE_OP_BACKGROUND) { - mDispose = FrameBlender::kDisposeClear; + mDispose = DisposalMethod::CLEAR; } else { - mDispose = FrameBlender::kDisposeKeep; + mDispose = DisposalMethod::KEEP; } if (blend_op == PNG_BLEND_OP_SOURCE) { - mBlend = FrameBlender::kBlendSource; + mBlend = BlendMethod::SOURCE; } else { - mBlend = FrameBlender::kBlendOver; + mBlend = BlendMethod::OVER; } } #endif @@ -165,11 +165,6 @@ NeedNewFrame(mNumFrames, x_offset, y_offset, width, height, format); } else if (mNumFrames != 0) { NeedNewFrame(mNumFrames, x_offset, y_offset, width, height, format); - } else { - // Our preallocated frame matches up, with the possible exception of alpha. - if (format == gfx::SurfaceFormat::B8G8R8X8) { - currentFrame->SetHasNoAlpha(); - } } mFrameRect = neededRect; @@ -185,7 +180,7 @@ if (png_get_valid(mPNG, mInfo, PNG_INFO_acTL)) { mAnimInfo = AnimFrameInfo(mPNG, mInfo); - if (mAnimInfo.mDispose == FrameBlender::kDisposeClear) { + if (mAnimInfo.mDispose == DisposalMethod::CLEAR) { // We may have to display the background under this image during // animation playback, so we regard it as transparent. PostHasTransparency(); @@ -204,11 +199,9 @@ mNumFrames++; - FrameBlender::FrameAlpha alpha; - if (mFrameHasNoAlpha) { - alpha = FrameBlender::kFrameOpaque; - } else { - alpha = FrameBlender::kFrameHasAlpha; + Opacity opacity = Opacity::SOME_TRANSPARENCY; + if (format == gfx::SurfaceFormat::B8G8R8X8 || mFrameHasNoAlpha) { + opacity = Opacity::OPAQUE; } #ifdef PNG_APNG_SUPPORTED @@ -220,7 +213,7 @@ } #endif - PostFrameStop(alpha, mAnimInfo.mDispose, mAnimInfo.mTimeout, + PostFrameStop(opacity, mAnimInfo.mDispose, mAnimInfo.mTimeout, mAnimInfo.mBlend); } @@ -320,8 +313,7 @@ } void -nsPNGDecoder::WriteInternal(const char* aBuffer, uint32_t aCount, - DecodeStrategy) +nsPNGDecoder::WriteInternal(const char* aBuffer, uint32_t aCount) { NS_ABORT_IF_FALSE(!HasError(), "Shouldn't call WriteInternal after error!"); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/decoders/nsPNGDecoder.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/decoders/nsPNGDecoder.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/decoders/nsPNGDecoder.h 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/decoders/nsPNGDecoder.h 2015-01-09 12:36:28.000000000 +0000 @@ -28,8 +28,7 @@ virtual ~nsPNGDecoder(); virtual void InitInternal() MOZ_OVERRIDE; - virtual void WriteInternal(const char* aBuffer, uint32_t aCount, - DecodeStrategy aStrategy) MOZ_OVERRIDE; + virtual void WriteInternal(const char* aBuffer, uint32_t aCount) MOZ_OVERRIDE; virtual Telemetry::ID SpeedHistogram() MOZ_OVERRIDE; void CreateFrame(png_uint_32 x_offset, png_uint_32 y_offset, @@ -98,8 +97,8 @@ AnimFrameInfo(png_structp aPNG, png_infop aInfo); #endif - FrameBlender::FrameDisposalMethod mDispose; - FrameBlender::FrameBlendMethod mBlend; + DisposalMethod mDispose; + BlendMethod mBlend; int32_t mTimeout; }; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/ClippedImage.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/ClippedImage.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/ClippedImage.cpp 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/ClippedImage.cpp 2015-01-09 12:36:28.000000000 +0000 @@ -165,16 +165,6 @@ NS_IMPL_ISUPPORTS_INHERITED0(ClippedImage, ImageWrapper) -nsIntRect -ClippedImage::FrameRect(uint32_t aWhichFrame) -{ - if (!ShouldClip()) { - return InnerImage()->FrameRect(aWhichFrame); - } - - return nsIntRect(0, 0, mClip.width, mClip.height); -} - NS_IMETHODIMP ClippedImage::GetWidth(int32_t* aWidth) { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/ClippedImage.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/ClippedImage.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/ClippedImage.h 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/ClippedImage.h 2015-01-09 12:36:28.000000000 +0000 @@ -31,8 +31,6 @@ public: NS_DECL_ISUPPORTS_INHERITED - virtual nsIntRect FrameRect(uint32_t aWhichFrame) MOZ_OVERRIDE; - NS_IMETHOD GetWidth(int32_t* aWidth) MOZ_OVERRIDE; NS_IMETHOD GetHeight(int32_t* aHeight) MOZ_OVERRIDE; NS_IMETHOD GetIntrinsicSize(nsSize* aSize) MOZ_OVERRIDE; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/DecodePool.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/DecodePool.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/DecodePool.cpp 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/DecodePool.cpp 2015-01-09 12:36:28.000000000 +0000 @@ -12,6 +12,7 @@ #include "nsCOMPtr.h" #include "nsIObserverService.h" #include "nsIThreadPool.h" +#include "nsProxyRelease.h" #include "nsXPCOMCIDInternal.h" #include "prsystem.h" @@ -65,49 +66,6 @@ nsRefPtr mImage; }; -class FrameNeededWorker : public nsRunnable -{ -public: - /** - * Called when an off-main-thread decoder needs a new frame to be allocated on - * the main thread. - * - * After allocating the new frame, the worker will call RequestDecode to - * continue decoding. - */ - static void Dispatch(RasterImage* aImage) - { - nsCOMPtr worker = new FrameNeededWorker(aImage); - NS_DispatchToMainThread(worker); - } - - NS_IMETHOD Run() MOZ_OVERRIDE - { - ReentrantMonitorAutoEnter lock(mImage->mDecodingMonitor); - nsresult rv = NS_OK; - - // If we got a synchronous decode in the mean time, we don't need to do - // anything. - if (mImage->mDecoder && mImage->mDecoder->NeedsNewFrame()) { - rv = mImage->mDecoder->AllocateFrame(); - } - - if (NS_SUCCEEDED(rv) && mImage->mDecoder) { - // By definition, we're not done decoding, so enqueue us for more decoding. - DecodePool::Singleton()->RequestDecode(mImage); - } - - return NS_OK; - } - -private: - explicit FrameNeededWorker(RasterImage* aImage) - : mImage(aImage) - { } - - nsRefPtr mImage; -}; - class DecodeWorker : public nsRunnable { public: @@ -117,6 +75,8 @@ NS_IMETHOD Run() MOZ_OVERRIDE { + MOZ_ASSERT(!NS_IsMainThread()); + ReentrantMonitorAutoEnter lock(mImage->mDecodingMonitor); // If we were interrupted, we shouldn't do any work. @@ -131,41 +91,25 @@ return NS_OK; } - // If we're a decode job that's been enqueued since a previous decode that - // still needs a new frame, we can't do anything. Wait until the - // FrameNeededWorker enqueues another frame. - if (mImage->mDecoder->NeedsNewFrame()) { - return NS_OK; - } - mImage->mDecodeStatus = DecodeStatus::ACTIVE; size_t oldByteCount = mImage->mDecoder->BytesDecoded(); - // Multithreaded decoding can be disabled. If we've done so, we don't want - // to monopolize the main thread, and will allow a timeout. - DecodeUntil type = NS_IsMainThread() ? DecodeUntil::TIME - : DecodeUntil::DONE_BYTES; - size_t maxBytes = mImage->mSourceData.Length() - mImage->mDecoder->BytesDecoded(); - DecodePool::Singleton()->DecodeSomeOfImage(mImage, DecodeStrategy::ASYNC, - type, maxBytes); + DecodePool::Singleton()->DecodeSomeOfImage(mImage, DecodeUntil::DONE_BYTES, + maxBytes); size_t bytesDecoded = mImage->mDecoder->BytesDecoded() - oldByteCount; mImage->mDecodeStatus = DecodeStatus::WORK_DONE; - if (mImage->mDecoder && mImage->mDecoder->NeedsNewFrame()) { - // The decoder needs a new frame. Enqueue an event to get it; that event - // will enqueue another decode request when it's done. - FrameNeededWorker::Dispatch(mImage); - } else if (mImage->mDecoder && - !mImage->mError && - !mImage->mPendingError && - !mImage->IsDecodeFinished() && - bytesDecoded < maxBytes && - bytesDecoded > 0) { + if (mImage->mDecoder && + !mImage->mError && + !mImage->mPendingError && + !mImage->IsDecodeFinished() && + bytesDecoded < maxBytes && + bytesDecoded > 0) { // We aren't finished decoding, and we have more data, so add this request // to the back of the list. DecodePool::Singleton()->RequestDecode(mImage); @@ -180,17 +124,15 @@ protected: virtual ~DecodeWorker() { - if (gfxPrefs::ImageMTDecodingEnabled()) { - // Dispatch mImage to main thread to prevent mImage from being destructed by decode thread. - nsCOMPtr mainThread = do_GetMainThread(); - NS_WARN_IF_FALSE(mainThread, "Couldn't get the main thread!"); - if (mainThread) { - // Handle ambiguous nsISupports inheritance - RasterImage* rawImg = nullptr; - mImage.swap(rawImg); - DebugOnly rv = NS_ProxyRelease(mainThread, NS_ISUPPORTS_CAST(ImageResource*, rawImg)); - MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed to proxy release to main thread"); - } + // Dispatch mImage to main thread to prevent mImage from being destructed by decode thread. + nsCOMPtr mainThread = do_GetMainThread(); + NS_WARN_IF_FALSE(mainThread, "Couldn't get the main thread!"); + if (mainThread) { + // Handle ambiguous nsISupports inheritance + RasterImage* rawImg = nullptr; + mImage.swap(rawImg); + DebugOnly rv = NS_ProxyRelease(mainThread, NS_ISUPPORTS_CAST(ImageResource*, rawImg)); + MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed to proxy release to main thread"); } } @@ -262,32 +204,31 @@ DecodePool::DecodePool() : mThreadPoolMutex("Thread Pool") { - if (gfxPrefs::ImageMTDecodingEnabled()) { - mThreadPool = do_CreateInstance(NS_THREADPOOL_CONTRACTID); - if (mThreadPool) { - mThreadPool->SetName(NS_LITERAL_CSTRING("ImageDecoder")); - int32_t prefLimit = gfxPrefs::ImageMTDecodingLimit(); - uint32_t limit; - if (prefLimit <= 0) { - limit = max(PR_GetNumberOfProcessors(), 2) - 1; - } else { - limit = static_cast(prefLimit); - } + mThreadPool = do_CreateInstance(NS_THREADPOOL_CONTRACTID); + MOZ_RELEASE_ASSERT(mThreadPool, + "Should succeed in creating image decoding thread pool"); + + mThreadPool->SetName(NS_LITERAL_CSTRING("ImageDecoder")); + int32_t prefLimit = gfxPrefs::ImageMTDecodingLimit(); + uint32_t limit; + if (prefLimit <= 0) { + limit = max(PR_GetNumberOfProcessors(), 2) - 1; + } else { + limit = static_cast(prefLimit); + } - mThreadPool->SetThreadLimit(limit); - mThreadPool->SetIdleThreadLimit(limit); + mThreadPool->SetThreadLimit(limit); + mThreadPool->SetIdleThreadLimit(limit); #ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess()) { - mThreadPool->SetListener(new RIDThreadPoolListener()); - } + if (IsNuwaProcess()) { + mThreadPool->SetListener(new RIDThreadPoolListener()); + } #endif - nsCOMPtr obsSvc = services::GetObserverService(); - if (obsSvc) { - obsSvc->AddObserver(this, "xpcom-shutdown-threads", false); - } - } + nsCOMPtr obsSvc = services::GetObserverService(); + if (obsSvc) { + obsSvc->AddObserver(this, "xpcom-shutdown-threads", false); } } @@ -322,30 +263,26 @@ MOZ_ASSERT(aImage->mDecoder); aImage->mDecodingMonitor.AssertCurrentThreadIn(); - // If we're currently waiting on a new frame for this image, we can't do any - // decoding. - if (!aImage->mDecoder->NeedsNewFrame()) { - if (aImage->mDecodeStatus == DecodeStatus::PENDING || - aImage->mDecodeStatus == DecodeStatus::ACTIVE) { - // The image is already in our list of images to decode, or currently being - // decoded, so we don't have to do anything else. - return; - } - - aImage->mDecodeStatus = DecodeStatus::PENDING; - nsCOMPtr worker = new DecodeWorker(aImage); + if (aImage->mDecodeStatus == DecodeStatus::PENDING || + aImage->mDecodeStatus == DecodeStatus::ACTIVE) { + // The image is already in our list of images to decode, or currently being + // decoded, so we don't have to do anything else. + return; + } - MutexAutoLock threadPoolLock(mThreadPoolMutex); - if (!gfxPrefs::ImageMTDecodingEnabled() || !mThreadPool) { - NS_DispatchToMainThread(worker); - } else { - mThreadPool->Dispatch(worker, nsIEventTarget::DISPATCH_NORMAL); - } + aImage->mDecodeStatus = DecodeStatus::PENDING; + nsCOMPtr worker = new DecodeWorker(aImage); + + // Dispatch to the thread pool if it exists. If it doesn't, we're currently + // shutting down, so it's OK to just drop the job on the floor. + MutexAutoLock threadPoolLock(mThreadPoolMutex); + if (mThreadPool) { + mThreadPool->Dispatch(worker, nsIEventTarget::DISPATCH_NORMAL); } } void -DecodePool::DecodeABitOf(RasterImage* aImage, DecodeStrategy aStrategy) +DecodePool::DecodeABitOf(RasterImage* aImage) { MOZ_ASSERT(NS_IsMainThread()); aImage->mDecodingMonitor.AssertCurrentThreadIn(); @@ -355,23 +292,17 @@ aImage->FinishedSomeDecoding(); } - DecodeSomeOfImage(aImage, aStrategy); + DecodeSomeOfImage(aImage); aImage->FinishedSomeDecoding(); - // If the decoder needs a new frame, enqueue an event to get it; that event - // will enqueue another decode request when it's done. - if (aImage->mDecoder && aImage->mDecoder->NeedsNewFrame()) { - FrameNeededWorker::Dispatch(aImage); - } else { - // If we aren't yet finished decoding and we have more data in hand, add - // this request to the back of the priority list. - if (aImage->mDecoder && - !aImage->mError && - !aImage->IsDecodeFinished() && - aImage->mSourceData.Length() > aImage->mDecoder->BytesDecoded()) { - RequestDecode(aImage); - } + // If we aren't yet finished decoding and we have more data in hand, add + // this request to the back of the priority list. + if (aImage->mDecoder && + !aImage->mError && + !aImage->IsDecodeFinished() && + aImage->mSourceData.Length() > aImage->mDecoder->BytesDecoded()) { + RequestDecode(aImage); } } @@ -400,28 +331,16 @@ } } - // We use DecodeStrategy::ASYNC here because we just want to get the size - // information here and defer the rest of the work. - nsresult rv = - DecodeSomeOfImage(aImage, DecodeStrategy::ASYNC, DecodeUntil::SIZE); + nsresult rv = DecodeSomeOfImage(aImage, DecodeUntil::SIZE); if (NS_FAILED(rv)) { return rv; } - // If the decoder needs a new frame, enqueue an event to get it; that event - // will enqueue another decode request when it's done. - if (aImage->mDecoder && aImage->mDecoder->NeedsNewFrame()) { - FrameNeededWorker::Dispatch(aImage); - } else { - rv = aImage->FinishedSomeDecoding(); - } - - return rv; + return aImage->FinishedSomeDecoding(); } nsresult DecodePool::DecodeSomeOfImage(RasterImage* aImage, - DecodeStrategy aStrategy, DecodeUntil aDecodeUntil /* = DecodeUntil::TIME */, uint32_t bytesToDecode /* = 0 */) { @@ -446,15 +365,6 @@ return NS_OK; } - if (aImage->mDecoder->NeedsNewFrame()) { - if (aStrategy == DecodeStrategy::SYNC) { - MOZ_ASSERT(NS_IsMainThread()); - aImage->mDecoder->AllocateFrame(); - } else { - return NS_OK; - } - } - nsRefPtr decoderKungFuDeathGrip = aImage->mDecoder; uint32_t maxBytes; @@ -481,16 +391,12 @@ // * the decode completes, // * we're an DecodeUntil::SIZE decode and we get the size, or // * we run out of time. - // We also try to decode at least one "chunk" if we've allocated a new frame, - // even if we have no more data to send to the decoder. - while ((aImage->mSourceData.Length() > aImage->mDecoder->BytesDecoded() && - bytesToDecode > 0 && - !aImage->IsDecodeFinished() && - !(aDecodeUntil == DecodeUntil::SIZE && aImage->mHasSize) && - !aImage->mDecoder->NeedsNewFrame()) || - aImage->mDecoder->NeedsToFlushData()) { + while (aImage->mSourceData.Length() > aImage->mDecoder->BytesDecoded() && + bytesToDecode > 0 && + !aImage->IsDecodeFinished() && + !(aDecodeUntil == DecodeUntil::SIZE && aImage->mHasSize)) { uint32_t chunkSize = min(bytesToDecode, maxBytes); - nsresult rv = aImage->DecodeSomeData(chunkSize, aStrategy); + nsresult rv = aImage->DecodeSomeData(chunkSize); if (NS_FAILED(rv)) { aImage->DoError(); return rv; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/DecodePool.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/DecodePool.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/DecodePool.h 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/DecodePool.h 2015-01-09 12:36:28.000000000 +0000 @@ -25,22 +25,6 @@ class Decoder; class RasterImage; -MOZ_BEGIN_ENUM_CLASS(DecodeStrategy, uint8_t) - // DecodeStrategy::SYNC requests a synchronous decode, which will continue - // decoding frames as long as it has more source data. It returns to the - // caller only once decoding is complete (or until it needs more source data - // before continuing). Because DecodeStrategy::SYNC can involve allocating new - // imgFrames, it can only be run on the main thread. - SYNC, - - // DecodeStrategy::ASYNC requests an asynchronous decode, which will continue - // decoding until it either finishes a frame or runs out of source data. - // Because DecodeStrategy::ASYNC does not allocate new imgFrames, it can be - // safely run off the main thread. (And hence workers in the decode pool - // always use it.) - ASYNC -MOZ_END_ENUM_CLASS(DecodeStrategy) - MOZ_BEGIN_ENUM_CLASS(DecodeStatus, uint8_t) INACTIVE, PENDING, @@ -92,7 +76,7 @@ * Decode aImage for a short amount of time, and post the remainder to the * queue. */ - void DecodeABitOf(RasterImage* aImage, DecodeStrategy aStrategy); + void DecodeABitOf(RasterImage* aImage); /** * Ask the DecodePool to stop decoding this image. Internally, we also @@ -128,7 +112,6 @@ * DONE_BYTES, decode until all bytesToDecode bytes are decoded. */ nsresult DecodeSomeOfImage(RasterImage* aImage, - DecodeStrategy aStrategy, DecodeUntil aDecodeUntil = DecodeUntil::TIME, uint32_t bytesToDecode = 0); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/Decoder.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/Decoder.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/Decoder.cpp 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/Decoder.cpp 2015-01-09 12:36:28.000000000 +0000 @@ -5,12 +5,18 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "Decoder.h" + +#include "mozilla/gfx/2D.h" +#include "imgIContainer.h" #include "nsIConsoleService.h" #include "nsIScriptError.h" #include "GeckoProfiler.h" #include "nsServiceManagerUtils.h" #include "nsComponentManagerUtils.h" +using mozilla::gfx::IntSize; +using mozilla::gfx::SurfaceFormat; + namespace mozilla { namespace image { @@ -82,6 +88,7 @@ // We have all the frame data, so we've started the frame. if (!IsSizeDecode()) { + mFrameCount++; PostFrameStart(); } @@ -91,13 +98,11 @@ } void -Decoder::Write(const char* aBuffer, uint32_t aCount, DecodeStrategy aStrategy) +Decoder::Write(const char* aBuffer, uint32_t aCount) { PROFILER_LABEL("ImageDecoder", "Write", js::ProfileEntry::Category::GRAPHICS); - MOZ_ASSERT(NS_IsMainThread() || aStrategy == DecodeStrategy::ASYNC); - // We're strict about decoder errors MOZ_ASSERT(!HasDecoderError(), "Not allowed to make more decoder calls after error!"); @@ -124,22 +129,26 @@ return; } - // Pass the data along to the implementation - WriteInternal(aBuffer, aCount, aStrategy); - - // If we're a synchronous decoder and we need a new frame to proceed, let's - // create one and call it again. - if (aStrategy == DecodeStrategy::SYNC) { - while (NeedsNewFrame() && !HasDataError()) { - nsresult rv = AllocateFrame(); - - if (NS_SUCCEEDED(rv)) { - // Use the data we saved when we asked for a new frame. - WriteInternal(nullptr, 0, aStrategy); - } - - mNeedsToFlushData = false; + MOZ_ASSERT(!NeedsNewFrame() || HasDataError(), + "Should not need a new frame before writing anything"); + MOZ_ASSERT(!NeedsToFlushData() || HasDataError(), + "Should not need to flush data before writing anything"); + + // Pass the data along to the implementation. + WriteInternal(aBuffer, aCount); + + // If we need a new frame to proceed, let's create one and call it again. + while (NeedsNewFrame() && !HasDataError()) { + MOZ_ASSERT(!IsSizeDecode(), "Shouldn't need new frame for size decode"); + + nsresult rv = AllocateFrame(); + + if (NS_SUCCEEDED(rv)) { + // Use the data we saved when we asked for a new frame. + WriteInternal(nullptr, 0); } + + mNeedsToFlushData = false; } // Finish telemetry. @@ -230,21 +239,20 @@ Decoder::AllocateFrame() { MOZ_ASSERT(mNeedsNewFrame); - MOZ_ASSERT(NS_IsMainThread()); - mCurrentFrame = mImage.EnsureFrame(mNewFrameData.mFrameNum, - mNewFrameData.mFrameRect, - mDecodeFlags, - mNewFrameData.mFormat, - mNewFrameData.mPaletteDepth, - mCurrentFrame.get()); + mCurrentFrame = EnsureFrame(mNewFrameData.mFrameNum, + mNewFrameData.mFrameRect, + mDecodeFlags, + mNewFrameData.mFormat, + mNewFrameData.mPaletteDepth, + mCurrentFrame.get()); if (mCurrentFrame) { // Gather the raw pointers the decoders will use. mCurrentFrame->GetImageData(&mImageData, &mImageDataLength); mCurrentFrame->GetPaletteData(&mColormap, &mColormapSize); - if (mNewFrameData.mFrameNum == mFrameCount) { + if (mNewFrameData.mFrameNum + 1 == mFrameCount) { PostFrameStart(); } } else { @@ -264,6 +272,139 @@ return mCurrentFrame ? NS_OK : NS_ERROR_FAILURE; } +RawAccessFrameRef +Decoder::EnsureFrame(uint32_t aFrameNum, + const nsIntRect& aFrameRect, + uint32_t aDecodeFlags, + SurfaceFormat aFormat, + uint8_t aPaletteDepth, + imgFrame* aPreviousFrame) +{ + if (mDataError || NS_FAILED(mFailCode)) { + return RawAccessFrameRef(); + } + + MOZ_ASSERT(aFrameNum <= mFrameCount, "Invalid frame index!"); + if (aFrameNum > mFrameCount) { + return RawAccessFrameRef(); + } + + // Adding a frame that doesn't already exist. This is the normal case. + if (aFrameNum == mFrameCount) { + return InternalAddFrame(aFrameNum, aFrameRect, aDecodeFlags, aFormat, + aPaletteDepth, aPreviousFrame); + } + + // We're replacing a frame. It must be the first frame; there's no reason to + // ever replace any other frame, since the first frame is the only one we + // speculatively allocate without knowing what the decoder really needs. + // XXX(seth): I'm not convinced there's any reason to support this at all. We + // should figure out how to avoid triggering this and rip it out. + MOZ_ASSERT(aFrameNum == 0, "Replacing a frame other than the first?"); + MOZ_ASSERT(mFrameCount == 1, "Should have only one frame"); + MOZ_ASSERT(aPreviousFrame, "Need the previous frame to replace"); + if (aFrameNum != 0 || !aPreviousFrame || mFrameCount != 1) { + return RawAccessFrameRef(); + } + + MOZ_ASSERT(!aPreviousFrame->GetRect().IsEqualEdges(aFrameRect) || + aPreviousFrame->GetFormat() != aFormat || + aPreviousFrame->GetPaletteDepth() != aPaletteDepth, + "Replacing first frame with the same kind of frame?"); + + // Remove the old frame from the SurfaceCache. + IntSize prevFrameSize = aPreviousFrame->GetImageSize(); + SurfaceCache::RemoveSurface(ImageKey(&mImage), + RasterSurfaceKey(prevFrameSize, aDecodeFlags, 0)); + mFrameCount = 0; + mInFrame = false; + + // Add the new frame as usual. + return InternalAddFrame(aFrameNum, aFrameRect, aDecodeFlags, aFormat, + aPaletteDepth, nullptr); +} + +RawAccessFrameRef +Decoder::InternalAddFrame(uint32_t aFrameNum, + const nsIntRect& aFrameRect, + uint32_t aDecodeFlags, + SurfaceFormat aFormat, + uint8_t aPaletteDepth, + imgFrame* aPreviousFrame) +{ + MOZ_ASSERT(aFrameNum <= mFrameCount, "Invalid frame index!"); + if (aFrameNum > mFrameCount) { + return RawAccessFrameRef(); + } + + MOZ_ASSERT(mImageMetadata.HasSize()); + nsIntSize imageSize(mImageMetadata.GetWidth(), mImageMetadata.GetHeight()); + if (imageSize.width <= 0 || imageSize.height <= 0 || + aFrameRect.width <= 0 || aFrameRect.height <= 0) { + NS_WARNING("Trying to add frame with zero or negative size"); + return RawAccessFrameRef(); + } + + if (!SurfaceCache::CanHold(imageSize.ToIntSize())) { + NS_WARNING("Trying to add frame that's too large for the SurfaceCache"); + return RawAccessFrameRef(); + } + + nsRefPtr frame = new imgFrame(); + bool nonPremult = + aDecodeFlags & imgIContainer::FLAG_DECODE_NO_PREMULTIPLY_ALPHA; + if (NS_FAILED(frame->InitForDecoder(imageSize, aFrameRect, aFormat, + aPaletteDepth, nonPremult))) { + NS_WARNING("imgFrame::Init should succeed"); + return RawAccessFrameRef(); + } + + RawAccessFrameRef ref = frame->RawAccessRef(); + if (!ref) { + return RawAccessFrameRef(); + } + + bool succeeded = + SurfaceCache::Insert(frame, ImageKey(&mImage), + RasterSurfaceKey(imageSize.ToIntSize(), + aDecodeFlags, + aFrameNum), + Lifetime::Persistent); + if (!succeeded) { + return RawAccessFrameRef(); + } + + nsIntRect refreshArea; + + if (aFrameNum == 1) { + MOZ_ASSERT(aPreviousFrame, "Must provide a previous frame when animated"); + aPreviousFrame->SetRawAccessOnly(); + + // If we dispose of the first frame by clearing it, then the first frame's + // refresh area is all of itself. + // RESTORE_PREVIOUS is invalid (assumed to be DISPOSE_CLEAR). + AnimationData previousFrameData = aPreviousFrame->GetAnimationData(); + if (previousFrameData.mDisposalMethod == DisposalMethod::CLEAR || + previousFrameData.mDisposalMethod == DisposalMethod::CLEAR_ALL || + previousFrameData.mDisposalMethod == DisposalMethod::RESTORE_PREVIOUS) { + refreshArea = previousFrameData.mRect; + } + } + + if (aFrameNum > 0) { + ref->SetRawAccessOnly(); + + // Some GIFs are huge but only have a small area that they animate. We only + // need to refresh that small area when frame 0 comes around again. + refreshArea.UnionRect(refreshArea, frame->GetRect()); + } + + mFrameCount++; + mImage.OnAddedFrame(mFrameCount, refreshArea); + + return ref; +} + void Decoder::SetSizeOnImage() { @@ -280,7 +421,7 @@ */ void Decoder::InitInternal() { } -void Decoder::WriteInternal(const char* aBuffer, uint32_t aCount, DecodeStrategy aStrategy) { } +void Decoder::WriteInternal(const char* aBuffer, uint32_t aCount) { } void Decoder::FinishInternal() { } /* @@ -316,7 +457,6 @@ NS_ABORT_IF_FALSE(!mInFrame, "Starting new frame but not done with old one!"); // Update our state to reflect the new frame - mFrameCount++; mInFrame = true; // If we just became animated, record that fact. @@ -324,19 +464,13 @@ mIsAnimated = true; mProgress |= FLAG_IS_ANIMATED; } - - // Decoder implementations should only call this method if they successfully - // appended the frame to the image. So mFrameCount should always match that - // reported by the Image. - MOZ_ASSERT(mFrameCount == mImage.GetNumFrames(), - "Decoder frame count doesn't match image's!"); } void -Decoder::PostFrameStop(FrameBlender::FrameAlpha aFrameAlpha /* = FrameBlender::kFrameHasAlpha */, - FrameBlender::FrameDisposalMethod aDisposalMethod /* = FrameBlender::kDisposeKeep */, +Decoder::PostFrameStop(Opacity aFrameOpacity /* = Opacity::TRANSPARENT */, + DisposalMethod aDisposalMethod /* = DisposalMethod::KEEP */, int32_t aTimeout /* = 0 */, - FrameBlender::FrameBlendMethod aBlendMethod /* = FrameBlender::kBlendOver */) + BlendMethod aBlendMethod /* = BlendMethod::OVER */) { // We should be mid-frame MOZ_ASSERT(!IsSizeDecode(), "Stopping frame during a size decode"); @@ -346,14 +480,7 @@ // Update our state mInFrame = false; - if (aFrameAlpha == FrameBlender::kFrameOpaque) { - mCurrentFrame->SetHasNoAlpha(); - } - - mCurrentFrame->SetFrameDisposalMethod(aDisposalMethod); - mCurrentFrame->SetRawTimeout(aTimeout); - mCurrentFrame->SetBlendMethod(aBlendMethod); - mCurrentFrame->ImageUpdated(mCurrentFrame->GetRect()); + mCurrentFrame->Finish(aFrameOpacity, aDisposalMethod, aTimeout, aBlendMethod); mProgress |= FLAG_FRAME_COMPLETE | FLAG_ONLOAD_UNBLOCKED; } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/Decoder.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/Decoder.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/Decoder.h 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/Decoder.h 2015-01-09 12:36:28.000000000 +0000 @@ -6,6 +6,7 @@ #ifndef MOZILLA_IMAGELIB_DECODER_H_ #define MOZILLA_IMAGELIB_DECODER_H_ +#include "FrameAnimator.h" #include "RasterImage.h" #include "mozilla/RefPtr.h" #include "DecodePool.h" @@ -55,7 +56,7 @@ * * Notifications Sent: TODO */ - void Write(const char* aBuffer, uint32_t aCount, DecodeStrategy aStrategy); + void Write(const char* aBuffer, uint32_t aCount); /** * Informs the decoder that all the data has been written. @@ -158,6 +159,11 @@ bool HasSize() const { return mImageMetadata.HasSize(); } void SetSizeOnImage(); + void SetSize(const nsIntSize& aSize, const Orientation& aOrientation) + { + PostSize(aSize.width, aSize.height, aOrientation); + } + // Use HistogramCount as an invalid Histogram ID virtual Telemetry::ID SpeedHistogram() { return Telemetry::HistogramCount; } @@ -174,13 +180,8 @@ uint32_t width, uint32_t height, gfx::SurfaceFormat format, uint8_t palette_depth = 0); - virtual bool NeedsNewFrame() const { return mNeedsNewFrame; } - // Returns true if we may have stored data that we need to flush now that we - // have a new frame to decode into. Callers can use Write() to actually - // flush the data; see the documentation for that method. - bool NeedsToFlushData() const { return mNeedsToFlushData; } // Try to allocate a frame as described in mNewFrameData and return the // status code from that attempt. Clears mNewFrameData. @@ -206,8 +207,7 @@ * only these methods. */ virtual void InitInternal(); - virtual void WriteInternal(const char* aBuffer, uint32_t aCount, - DecodeStrategy aStrategy); + virtual void WriteInternal(const char* aBuffer, uint32_t aCount); virtual void FinishInternal(); /* @@ -226,7 +226,7 @@ // that affect content, so it's necessarily pessimistic - if there's a // possibility that the image has transparency, for example because its header // specifies that it has an alpha channel, we fire PostHasTransparency - // immediately. PostFrameStop's aFrameAlpha argument, on the other hand, is + // immediately. PostFrameStop's aFrameOpacity argument, on the other hand, is // only used internally to ImageLib. Because PostFrameStop isn't delivered // until the entire frame has been decoded, decoders may take into account the // actual contents of the frame and give a more accurate result. @@ -241,10 +241,10 @@ // Specify whether this frame is opaque as an optimization. // For animated images, specify the disposal, blend method and timeout for // this frame. - void PostFrameStop(FrameBlender::FrameAlpha aFrameAlpha = FrameBlender::kFrameHasAlpha, - FrameBlender::FrameDisposalMethod aDisposalMethod = FrameBlender::kDisposeKeep, + void PostFrameStop(Opacity aFrameOpacity = Opacity::SOME_TRANSPARENCY, + DisposalMethod aDisposalMethod = DisposalMethod::KEEP, int32_t aTimeout = 0, - FrameBlender::FrameBlendMethod aBlendMethod = FrameBlender::kBlendOver); + BlendMethod aBlendMethod = BlendMethod::OVER); // Called by the decoders when they have a region to invalidate. We may not // actually pass these invalidations on right away. @@ -264,6 +264,32 @@ void PostDataError(); void PostDecoderError(nsresult aFailCode); + // Returns true if we may have stored data that we need to flush now that we + // have a new frame to decode into. Callers can use Write() to actually + // flush the data; see the documentation for that method. + bool NeedsToFlushData() const { return mNeedsToFlushData; } + + /** + * Ensures that a given frame number exists with the given parameters, and + * returns a RawAccessFrameRef for that frame. + * It is not possible to create sparse frame arrays; you can only append + * frames to the current frame array, or if there is only one frame in the + * array, replace that frame. + * If a non-paletted frame is desired, pass 0 for aPaletteDepth. + */ + RawAccessFrameRef EnsureFrame(uint32_t aFrameNum, + const nsIntRect& aFrameRect, + uint32_t aDecodeFlags, + gfx::SurfaceFormat aFormat, + uint8_t aPaletteDepth, + imgFrame* aPreviousFrame); + + RawAccessFrameRef InternalAddFrame(uint32_t aFrameNum, + const nsIntRect& aFrameRect, + uint32_t aDecodeFlags, + gfx::SurfaceFormat aFormat, + uint8_t aPaletteDepth, + imgFrame* aPreviousFrame); /* * Member variables. * diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/DynamicImage.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/DynamicImage.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/DynamicImage.cpp 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/DynamicImage.cpp 2015-01-09 12:36:28.000000000 +0000 @@ -36,13 +36,6 @@ return nullptr; } -nsIntRect -DynamicImage::FrameRect(uint32_t aWhichFrame) -{ - gfxIntSize size(mDrawable->Size()); - return nsIntRect(0, 0, size.width, size.height); -} - size_t DynamicImage::SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const { @@ -91,12 +84,6 @@ { return NS_OK; } - -nsresult -DynamicImage::OnNewSourceData() -{ - return NS_OK; -} void DynamicImage::OnSurfaceDiscarded() diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/DynamicImage.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/DynamicImage.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/DynamicImage.h 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/DynamicImage.h 2015-01-09 12:36:28.000000000 +0000 @@ -34,7 +34,6 @@ virtual nsresult Init(const char* aMimeType, uint32_t aFlags) MOZ_OVERRIDE; virtual already_AddRefed GetProgressTracker() MOZ_OVERRIDE; - virtual nsIntRect FrameRect(uint32_t aWhichFrame) MOZ_OVERRIDE; virtual size_t SizeOfSourceWithComputedFallback( MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE; virtual size_t SizeOfDecoded(gfxMemoryLocation aLocation, @@ -55,7 +54,6 @@ nsISupports* aContext, nsresult aStatus, bool aLastPart) MOZ_OVERRIDE; - virtual nsresult OnNewSourceData() MOZ_OVERRIDE; virtual void OnSurfaceDiscarded() MOZ_OVERRIDE; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/FrameAnimator.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/FrameAnimator.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/FrameAnimator.cpp 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/FrameAnimator.cpp 2015-01-09 12:36:28.000000000 +0000 @@ -4,21 +4,20 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "FrameAnimator.h" -#include "FrameBlender.h" +#include "mozilla/MemoryReporting.h" +#include "mozilla/Move.h" #include "imgIContainer.h" +#include "MainThreadUtils.h" +#include "RasterImage.h" + +#include "pixman.h" namespace mozilla { -namespace image { -FrameAnimator::FrameAnimator(FrameBlender& aFrameBlender, - uint16_t aAnimationMode) - : mCurrentAnimationFrameIndex(0) - , mLoopCounter(-1) - , mFrameBlender(aFrameBlender) - , mAnimationMode(aAnimationMode) - , mDoneDecoding(false) -{ } +using namespace gfx; + +namespace image { int32_t FrameAnimator::GetSingleLoopTime() const @@ -34,8 +33,8 @@ } uint32_t looptime = 0; - for (uint32_t i = 0; i < mFrameBlender.GetNumFrames(); ++i) { - int32_t timeout = mFrameBlender.GetTimeoutForFrame(i); + for (uint32_t i = 0; i < mImage->GetNumFrames(); ++i) { + int32_t timeout = GetTimeoutForFrame(i); if (timeout >= 0) { looptime += static_cast(timeout); } else { @@ -54,7 +53,7 @@ { TimeStamp currentFrameTime = mCurrentAnimationFrameTime; int32_t timeout = - mFrameBlender.GetTimeoutForFrame(mCurrentAnimationFrameIndex); + GetTimeoutForFrame(mCurrentAnimationFrameIndex); if (timeout < 0) { // We need to return a sentinel value in this case, because our logic @@ -85,7 +84,7 @@ int32_t timeout = 0; RefreshResult ret; - nsRefPtr nextFrame = mFrameBlender.RawGetFrame(nextFrameIndex); + RawAccessFrameRef nextFrame = GetRawFrame(nextFrameIndex); // If we're done decoding, we know we've got everything we're going to get. // If we aren't, we only display fully-downloaded frames; everything else @@ -100,25 +99,25 @@ // If we're done decoding the next frame, go ahead and display it now and // reinit with the next frame's delay time. - if (mFrameBlender.GetNumFrames() == nextFrameIndex) { + if (mImage->GetNumFrames() == nextFrameIndex) { // End of an animation loop... // If we are not looping forever, initialize the loop counter - if (mLoopCounter < 0 && mFrameBlender.GetLoopCount() >= 0) { - mLoopCounter = mFrameBlender.GetLoopCount(); + if (mLoopRemainingCount < 0 && LoopCount() >= 0) { + mLoopRemainingCount = LoopCount(); } // If animation mode is "loop once", or we're at end of loop counter, - // it's time to stop animating + // it's time to stop animating. if (mAnimationMode == imgIContainer::kLoopOnceAnimMode || - mLoopCounter == 0) { + mLoopRemainingCount == 0) { ret.animationFinished = true; } nextFrameIndex = 0; - if (mLoopCounter > 0) { - mLoopCounter--; + if (mLoopRemainingCount > 0) { + mLoopRemainingCount--; } // If we're done, exit early. @@ -127,7 +126,7 @@ } } - timeout = mFrameBlender.GetTimeoutForFrame(nextFrameIndex); + timeout = GetTimeoutForFrame(nextFrameIndex); // Bad data if (timeout < 0) { @@ -140,10 +139,10 @@ } else { // Change frame if (nextFrameIndex != currentFrameIndex + 1) { - nextFrame = mFrameBlender.RawGetFrame(nextFrameIndex); + nextFrame = GetRawFrame(nextFrameIndex); } - if (!mFrameBlender.DoBlend(&ret.dirtyRect, currentFrameIndex, + if (!DoBlend(&ret.dirtyRect, currentFrameIndex, nextFrameIndex)) { // something went wrong, move on to next NS_WARNING("FrameAnimator::AdvanceFrame(): Compositing of frame failed"); @@ -218,6 +217,7 @@ FrameAnimator::ResetAnimation() { mCurrentAnimationFrameIndex = 0; + mLastCompositedFrameIndex = -1; } void @@ -247,12 +247,6 @@ } void -FrameAnimator::SetFirstFrameRefreshArea(const nsIntRect& aRect) -{ - mFirstFrameRefreshArea = aRect; -} - -void FrameAnimator::UnionFirstFrameRefreshArea(const nsIntRect& aRect) { mFirstFrameRefreshArea.UnionRect(mFirstFrameRefreshArea, aRect); @@ -270,5 +264,506 @@ return mFirstFrameRefreshArea; } +DrawableFrameRef +FrameAnimator::GetCompositedFrame(uint32_t aFrameNum) +{ + MOZ_ASSERT(aFrameNum != 0, "First frame is never composited"); + + // If we have a composited version of this frame, return that. + if (mLastCompositedFrameIndex == int32_t(aFrameNum)) { + return mCompositingFrame->DrawableRef(); + } + + // Otherwise return the raw frame. DoBlend is required to ensure that we only + // hit this case if the frame is not paletted and doesn't require compositing. + DrawableFrameRef ref = + SurfaceCache::Lookup(ImageKey(mImage), + RasterSurfaceKey(mSize, + 0, // Default decode flags. + aFrameNum)); + MOZ_ASSERT(!ref || !ref->GetIsPaletted(), "About to return a paletted frame"); + return ref; +} + +int32_t +FrameAnimator::GetTimeoutForFrame(uint32_t aFrameNum) const +{ + RawAccessFrameRef frame = GetRawFrame(aFrameNum); + AnimationData data = frame->GetAnimationData(); + + // Ensure a minimal time between updates so we don't throttle the UI thread. + // consider 0 == unspecified and make it fast but not too fast. Unless we + // have a single loop GIF. See bug 890743, bug 125137, bug 139677, and bug + // 207059. The behavior of recent IE and Opera versions seems to be: + // IE 6/Win: + // 10 - 50ms go 100ms + // >50ms go correct speed + // Opera 7 final/Win: + // 10ms goes 100ms + // >10ms go correct speed + // It seems that there are broken tools out there that set a 0ms or 10ms + // timeout when they really want a "default" one. So munge values in that + // range. + if (data.mRawTimeout >= 0 && data.mRawTimeout <= 10 && mLoopCount != 0) { + return 100; + } + + return data.mRawTimeout; +} + +size_t +FrameAnimator::SizeOfCompositingFrames(gfxMemoryLocation aLocation, + MallocSizeOf aMallocSizeOf) const +{ + size_t n = 0; + + if (mCompositingFrame) { + n += mCompositingFrame->SizeOfExcludingThis(aLocation, aMallocSizeOf); + } + if (mCompositingPrevFrame) { + n += mCompositingPrevFrame->SizeOfExcludingThis(aLocation, aMallocSizeOf); + } + + return n; +} + +RawAccessFrameRef +FrameAnimator::GetRawFrame(uint32_t aFrameNum) const +{ + DrawableFrameRef ref = + SurfaceCache::Lookup(ImageKey(mImage), + RasterSurfaceKey(mSize, + 0, // Default decode flags. + aFrameNum)); + return ref ? ref->RawAccessRef() + : RawAccessFrameRef(); +} + +//****************************************************************************** +// DoBlend gets called when the timer for animation get fired and we have to +// update the composited frame of the animation. +bool +FrameAnimator::DoBlend(nsIntRect* aDirtyRect, + uint32_t aPrevFrameIndex, + uint32_t aNextFrameIndex) +{ + RawAccessFrameRef prevFrame = GetRawFrame(aPrevFrameIndex); + RawAccessFrameRef nextFrame = GetRawFrame(aNextFrameIndex); + + MOZ_ASSERT(prevFrame && nextFrame, "Should have frames here"); + + AnimationData prevFrameData = prevFrame->GetAnimationData(); + if (prevFrameData.mDisposalMethod == DisposalMethod::RESTORE_PREVIOUS && + !mCompositingPrevFrame) { + prevFrameData.mDisposalMethod = DisposalMethod::CLEAR; + } + + bool isFullPrevFrame = prevFrameData.mRect.x == 0 && + prevFrameData.mRect.y == 0 && + prevFrameData.mRect.width == mSize.width && + prevFrameData.mRect.height == mSize.height; + + // Optimization: DisposeClearAll if the previous frame is the same size as + // container and it's clearing itself + if (isFullPrevFrame && + (prevFrameData.mDisposalMethod == DisposalMethod::CLEAR)) { + prevFrameData.mDisposalMethod = DisposalMethod::CLEAR_ALL; + } + + AnimationData nextFrameData = nextFrame->GetAnimationData(); + bool isFullNextFrame = nextFrameData.mRect.x == 0 && + nextFrameData.mRect.y == 0 && + nextFrameData.mRect.width == mSize.width && + nextFrameData.mRect.height == mSize.height; + + if (!nextFrame->GetIsPaletted()) { + // Optimization: Skip compositing if the previous frame wants to clear the + // whole image + if (prevFrameData.mDisposalMethod == DisposalMethod::CLEAR_ALL) { + aDirtyRect->SetRect(0, 0, mSize.width, mSize.height); + return true; + } + + // Optimization: Skip compositing if this frame is the same size as the + // container and it's fully drawing over prev frame (no alpha) + if (isFullNextFrame && + (nextFrameData.mDisposalMethod != DisposalMethod::RESTORE_PREVIOUS) && + !nextFrameData.mHasAlpha) { + aDirtyRect->SetRect(0, 0, mSize.width, mSize.height); + return true; + } + } + + // Calculate area that needs updating + switch (prevFrameData.mDisposalMethod) { + default: + case DisposalMethod::NOT_SPECIFIED: + case DisposalMethod::KEEP: + *aDirtyRect = nextFrameData.mRect; + break; + + case DisposalMethod::CLEAR_ALL: + // Whole image container is cleared + aDirtyRect->SetRect(0, 0, mSize.width, mSize.height); + break; + + case DisposalMethod::CLEAR: + // Calc area that needs to be redrawn (the combination of previous and + // this frame) + // XXX - This could be done with multiple framechanged calls + // Having prevFrame way at the top of the image, and nextFrame + // way at the bottom, and both frames being small, we'd be + // telling framechanged to refresh the whole image when only two + // small areas are needed. + aDirtyRect->UnionRect(nextFrameData.mRect, prevFrameData.mRect); + break; + + case DisposalMethod::RESTORE_PREVIOUS: + aDirtyRect->SetRect(0, 0, mSize.width, mSize.height); + break; + } + + // Optimization: + // Skip compositing if the last composited frame is this frame + // (Only one composited frame was made for this animation. Example: + // Only Frame 3 of a 10 frame image required us to build a composite frame + // On the second loop, we do not need to rebuild the frame + // since it's still sitting in compositingFrame) + if (mLastCompositedFrameIndex == int32_t(aNextFrameIndex)) { + return true; + } + + bool needToBlankComposite = false; + + // Create the Compositing Frame + if (!mCompositingFrame) { + nsRefPtr newFrame = new imgFrame; + nsresult rv = newFrame->InitForDecoder(ThebesIntSize(mSize), + SurfaceFormat::B8G8R8A8); + if (NS_FAILED(rv)) { + mCompositingFrame.reset(); + return false; + } + mCompositingFrame = newFrame->RawAccessRef(); + needToBlankComposite = true; + } else if (int32_t(aNextFrameIndex) != mLastCompositedFrameIndex+1) { + + // If we are not drawing on top of last composited frame, + // then we are building a new composite frame, so let's clear it first. + needToBlankComposite = true; + } + + AnimationData compositingFrameData = mCompositingFrame->GetAnimationData(); + + // More optimizations possible when next frame is not transparent + // But if the next frame has DisposalMethod::RESTORE_PREVIOUS, + // this "no disposal" optimization is not possible, + // because the frame in "after disposal operation" state + // needs to be stored in compositingFrame, so it can be + // copied into compositingPrevFrame later. + bool doDisposal = true; + if (!nextFrameData.mHasAlpha && + nextFrameData.mDisposalMethod != DisposalMethod::RESTORE_PREVIOUS) { + if (isFullNextFrame) { + // Optimization: No need to dispose prev.frame when + // next frame is full frame and not transparent. + doDisposal = false; + // No need to blank the composite frame + needToBlankComposite = false; + } else { + if ((prevFrameData.mRect.x >= nextFrameData.mRect.x) && + (prevFrameData.mRect.y >= nextFrameData.mRect.y) && + (prevFrameData.mRect.x + prevFrameData.mRect.width <= + nextFrameData.mRect.x + nextFrameData.mRect.width) && + (prevFrameData.mRect.y + prevFrameData.mRect.height <= + nextFrameData.mRect.y + nextFrameData.mRect.height)) { + // Optimization: No need to dispose prev.frame when + // next frame fully overlaps previous frame. + doDisposal = false; + } + } + } + + if (doDisposal) { + // Dispose of previous: clear, restore, or keep (copy) + switch (prevFrameData.mDisposalMethod) { + case DisposalMethod::CLEAR: + if (needToBlankComposite) { + // If we just created the composite, it could have anything in its + // buffer. Clear whole frame + ClearFrame(compositingFrameData.mRawData, + compositingFrameData.mRect); + } else { + // Only blank out previous frame area (both color & Mask/Alpha) + ClearFrame(compositingFrameData.mRawData, + compositingFrameData.mRect, + prevFrameData.mRect); + } + break; + + case DisposalMethod::CLEAR_ALL: + ClearFrame(compositingFrameData.mRawData, + compositingFrameData.mRect); + break; + + case DisposalMethod::RESTORE_PREVIOUS: + // It would be better to copy only the area changed back to + // compositingFrame. + if (mCompositingPrevFrame) { + AnimationData compositingPrevFrameData = + mCompositingPrevFrame->GetAnimationData(); + + CopyFrameImage(compositingPrevFrameData.mRawData, + compositingPrevFrameData.mRect, + compositingFrameData.mRawData, + compositingFrameData.mRect); + + // destroy only if we don't need it for this frame's disposal + if (nextFrameData.mDisposalMethod != + DisposalMethod::RESTORE_PREVIOUS) { + mCompositingPrevFrame.reset(); + } + } else { + ClearFrame(compositingFrameData.mRawData, + compositingFrameData.mRect); + } + break; + + default: + // Copy previous frame into compositingFrame before we put the new + // frame on top + // Assumes that the previous frame represents a full frame (it could be + // smaller in size than the container, as long as the frame before it + // erased itself) + // Note: Frame 1 never gets into DoBlend(), so (aNextFrameIndex - 1) + // will always be a valid frame number. + if (mLastCompositedFrameIndex != int32_t(aNextFrameIndex - 1)) { + if (isFullPrevFrame && !prevFrame->GetIsPaletted()) { + // Just copy the bits + CopyFrameImage(prevFrameData.mRawData, + prevFrameData.mRect, + compositingFrameData.mRawData, + compositingFrameData.mRect); + } else { + if (needToBlankComposite) { + // Only blank composite when prev is transparent or not full. + if (prevFrameData.mHasAlpha || !isFullPrevFrame) { + ClearFrame(compositingFrameData.mRawData, + compositingFrameData.mRect); + } + } + DrawFrameTo(prevFrameData.mRawData, prevFrameData.mRect, + prevFrameData.mPaletteDataLength, + prevFrameData.mHasAlpha, + compositingFrameData.mRawData, + compositingFrameData.mRect, + prevFrameData.mBlendMethod); + } + } + } + } else if (needToBlankComposite) { + // If we just created the composite, it could have anything in its + // buffers. Clear them + ClearFrame(compositingFrameData.mRawData, + compositingFrameData.mRect); + } + + // Check if the frame we are composing wants the previous image restored after + // it is done. Don't store it (again) if last frame wanted its image restored + // too + if ((nextFrameData.mDisposalMethod == DisposalMethod::RESTORE_PREVIOUS) && + (prevFrameData.mDisposalMethod != DisposalMethod::RESTORE_PREVIOUS)) { + // We are storing the whole image. + // It would be better if we just stored the area that nextFrame is going to + // overwrite. + if (!mCompositingPrevFrame) { + nsRefPtr newFrame = new imgFrame; + nsresult rv = newFrame->InitForDecoder(ThebesIntSize(mSize), + SurfaceFormat::B8G8R8A8); + if (NS_FAILED(rv)) { + mCompositingPrevFrame.reset(); + return false; + } + + mCompositingPrevFrame = newFrame->RawAccessRef(); + } + + AnimationData compositingPrevFrameData = + mCompositingPrevFrame->GetAnimationData(); + + CopyFrameImage(compositingFrameData.mRawData, + compositingFrameData.mRect, + compositingPrevFrameData.mRawData, + compositingPrevFrameData.mRect); + } + + // blit next frame into it's correct spot + DrawFrameTo(nextFrameData.mRawData, nextFrameData.mRect, + nextFrameData.mPaletteDataLength, + nextFrameData.mHasAlpha, + compositingFrameData.mRawData, + compositingFrameData.mRect, + nextFrameData.mBlendMethod); + + // Tell the image that it is fully 'downloaded'. + nsresult rv = + mCompositingFrame->ImageUpdated(compositingFrameData.mRect); + if (NS_FAILED(rv)) { + return false; + } + + mLastCompositedFrameIndex = int32_t(aNextFrameIndex); + + return true; +} + +//****************************************************************************** +// Fill aFrame with black. Does also clears the mask. +void +FrameAnimator::ClearFrame(uint8_t* aFrameData, const nsIntRect& aFrameRect) +{ + if (!aFrameData) { + return; + } + + memset(aFrameData, 0, aFrameRect.width * aFrameRect.height * 4); +} + +//****************************************************************************** +void +FrameAnimator::ClearFrame(uint8_t* aFrameData, const nsIntRect& aFrameRect, + const nsIntRect& aRectToClear) +{ + if (!aFrameData || aFrameRect.width <= 0 || aFrameRect.height <= 0 || + aRectToClear.width <= 0 || aRectToClear.height <= 0) { + return; + } + + nsIntRect toClear = aFrameRect.Intersect(aRectToClear); + if (toClear.IsEmpty()) { + return; + } + + uint32_t bytesPerRow = aFrameRect.width * 4; + for (int row = toClear.y; row < toClear.y + toClear.height; ++row) { + memset(aFrameData + toClear.x * 4 + row * bytesPerRow, 0, + toClear.width * 4); + } +} + +//****************************************************************************** +// Whether we succeed or fail will not cause a crash, and there's not much +// we can do about a failure, so there we don't return a nsresult +bool +FrameAnimator::CopyFrameImage(const uint8_t* aDataSrc, const nsIntRect& aRectSrc, + uint8_t* aDataDest, const nsIntRect& aRectDest) +{ + uint32_t dataLengthSrc = aRectSrc.width * aRectSrc.height * 4; + uint32_t dataLengthDest = aRectDest.width * aRectDest.height * 4; + + if (!aDataDest || !aDataSrc || dataLengthSrc != dataLengthDest) { + return false; + } + + memcpy(aDataDest, aDataSrc, dataLengthDest); + + return true; +} + +nsresult +FrameAnimator::DrawFrameTo(const uint8_t* aSrcData, const nsIntRect& aSrcRect, + uint32_t aSrcPaletteLength, bool aSrcHasAlpha, + uint8_t* aDstPixels, const nsIntRect& aDstRect, + BlendMethod aBlendMethod) +{ + NS_ENSURE_ARG_POINTER(aSrcData); + NS_ENSURE_ARG_POINTER(aDstPixels); + + // According to both AGIF and APNG specs, offsets are unsigned + if (aSrcRect.x < 0 || aSrcRect.y < 0) { + NS_WARNING("FrameAnimator::DrawFrameTo: negative offsets not allowed"); + return NS_ERROR_FAILURE; + } + // Outside the destination frame, skip it + if ((aSrcRect.x > aDstRect.width) || (aSrcRect.y > aDstRect.height)) { + return NS_OK; + } + + if (aSrcPaletteLength) { + // Larger than the destination frame, clip it + int32_t width = std::min(aSrcRect.width, aDstRect.width - aSrcRect.x); + int32_t height = std::min(aSrcRect.height, aDstRect.height - aSrcRect.y); + + // The clipped image must now fully fit within destination image frame + NS_ASSERTION((aSrcRect.x >= 0) && (aSrcRect.y >= 0) && + (aSrcRect.x + width <= aDstRect.width) && + (aSrcRect.y + height <= aDstRect.height), + "FrameAnimator::DrawFrameTo: Invalid aSrcRect"); + + // clipped image size may be smaller than source, but not larger + NS_ASSERTION((width <= aSrcRect.width) && (height <= aSrcRect.height), + "FrameAnimator::DrawFrameTo: source must be smaller than dest"); + + // Get pointers to image data + const uint8_t* srcPixels = aSrcData + aSrcPaletteLength; + uint32_t* dstPixels = reinterpret_cast(aDstPixels); + const uint32_t* colormap = reinterpret_cast(aSrcData); + + // Skip to the right offset + dstPixels += aSrcRect.x + (aSrcRect.y * aDstRect.width); + if (!aSrcHasAlpha) { + for (int32_t r = height; r > 0; --r) { + for (int32_t c = 0; c < width; c++) { + dstPixels[c] = colormap[srcPixels[c]]; + } + // Go to the next row in the source resp. destination image + srcPixels += aSrcRect.width; + dstPixels += aDstRect.width; + } + } else { + for (int32_t r = height; r > 0; --r) { + for (int32_t c = 0; c < width; c++) { + const uint32_t color = colormap[srcPixels[c]]; + if (color) { + dstPixels[c] = color; + } + } + // Go to the next row in the source resp. destination image + srcPixels += aSrcRect.width; + dstPixels += aDstRect.width; + } + } + } else { + pixman_image_t* src = + pixman_image_create_bits( + aSrcHasAlpha ? PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8, + aSrcRect.width, aSrcRect.height, + reinterpret_cast(const_cast(aSrcData)), + aSrcRect.width * 4); + pixman_image_t* dst = + pixman_image_create_bits(PIXMAN_a8r8g8b8, + aDstRect.width, + aDstRect.height, + reinterpret_cast(aDstPixels), + aDstRect.width * 4); + + auto op = aBlendMethod == BlendMethod::SOURCE ? PIXMAN_OP_SRC + : PIXMAN_OP_OVER; + pixman_image_composite32(op, + src, + nullptr, + dst, + 0, 0, + 0, 0, + aSrcRect.x, aSrcRect.y, + aSrcRect.width, aSrcRect.height); + + pixman_image_unref(src); + pixman_image_unref(dst); + } + + return NS_OK; +} + } // namespace image } // namespace mozilla diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/FrameAnimator.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/FrameAnimator.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/FrameAnimator.h 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/FrameAnimator.h 2015-01-09 12:36:28.000000000 +0000 @@ -7,18 +7,35 @@ #ifndef mozilla_image_src_FrameAnimator_h #define mozilla_image_src_FrameAnimator_h +#include "mozilla/MemoryReporting.h" #include "mozilla/TimeStamp.h" +#include "gfx2DGlue.h" +#include "gfxTypes.h" +#include "imgFrame.h" +#include "nsCOMPtr.h" #include "nsRect.h" +#include "SurfaceCache.h" namespace mozilla { namespace image { -class FrameBlender; +class RasterImage; class FrameAnimator { public: - FrameAnimator(FrameBlender& aBlender, uint16_t aAnimationMode); + FrameAnimator(RasterImage* aImage, + gfx::IntSize aSize, + uint16_t aAnimationMode) + : mImage(aImage) + , mSize(aSize) + , mCurrentAnimationFrameIndex(0) + , mLoopRemainingCount(-1) + , mLastCompositedFrameIndex(-1) + , mLoopCount(-1) + , mAnimationMode(aAnimationMode) + , mDoneDecoding(false) + { } /** * Return value from RequestRefresh. Tells callers what happened in that call @@ -83,11 +100,6 @@ void SetAnimationMode(uint16_t aAnimationMode); /** - * Set the area to refresh when we loop around to the first frame. - */ - void SetFirstFrameRefreshArea(const nsIntRect& aRect); - - /** * Union the area to refresh when we loop around to the first frame with this * rect. */ @@ -114,6 +126,30 @@ */ nsIntRect GetFirstFrameRefreshArea() const; + /** + * If we have a composited frame for @aFrameNum, returns it. Otherwise, returns + * an empty DrawableFrameRef. It is an error to call this method with + * aFrameNum == 0, because the first frame is never composited. + */ + DrawableFrameRef GetCompositedFrame(uint32_t aFrameNum); + + /* + * Returns the frame's adjusted timeout. If the animation loops and the + * timeout falls in between a certain range then the timeout is adjusted so + * that it's never 0. If the animation does not loop then no adjustments are + * made. + */ + int32_t GetTimeoutForFrame(uint32_t aFrameNum) const; + + /* + * Set number of times to loop the image. + * @note -1 means loop forever. + */ + void SetLoopCount(int32_t aLoopCount) { mLoopCount = aLoopCount; } + int32_t LoopCount() const { return mLoopCount; } + + size_t SizeOfCompositingFrames(gfxMemoryLocation aLocation, + MallocSizeOf aMallocSizeOf) const; private: // methods /** * Gets the length of a single loop of this image, in milliseconds. @@ -145,7 +181,78 @@ */ TimeStamp GetCurrentImgFrameEndTime() const; + bool DoBlend(nsIntRect* aDirtyRect, uint32_t aPrevFrameIndex, + uint32_t aNextFrameIndex); + + /** + * Get the @aIndex-th frame in the frame index, ignoring results of blending. + */ + RawAccessFrameRef GetRawFrame(uint32_t aFrameNum) const; + + /** Clears an area of with transparent black. + * + * @param aFrameData Target Frame data + * @param aFrameRect The rectangle of the data pointed ot by aFrameData + * + * @note Does also clears the transparency mask + */ + static void ClearFrame(uint8_t* aFrameData, const nsIntRect& aFrameRect); + + //! @overload + static void ClearFrame(uint8_t* aFrameData, const nsIntRect& aFrameRect, + const nsIntRect& aRectToClear); + + //! Copy one frame's image and mask into another + static bool CopyFrameImage(const uint8_t* aDataSrc, const nsIntRect& aRectSrc, + uint8_t* aDataDest, const nsIntRect& aRectDest); + + /** + * Draws one frame's image to into another, at the position specified by + * aSrcRect. + * + * @aSrcData the raw data of the current frame being drawn + * @aSrcRect the size of the source frame, and the position of that frame in + * the composition frame + * @aSrcPaletteLength the length (in bytes) of the palette at the beginning + * of the source data (0 if image is not paletted) + * @aSrcHasAlpha whether the source data represents an image with alpha + * @aDstPixels the raw data of the composition frame where the current frame + * is drawn into (32-bit ARGB) + * @aDstRect the size of the composition frame + * @aBlendMethod the blend method for how to blend src on the composition + * frame. + */ + static nsresult DrawFrameTo(const uint8_t* aSrcData, + const nsIntRect& aSrcRect, + uint32_t aSrcPaletteLength, bool aSrcHasAlpha, + uint8_t* aDstPixels, const nsIntRect& aDstRect, + BlendMethod aBlendMethod); + private: // data + //! A weak pointer to our owning image. + RasterImage* mImage; + + //! The intrinsic size of the image. + gfx::IntSize mSize; + + /** For managing blending of frames + * + * Some animations will use the compositingFrame to composite images + * and just hand this back to the caller when it is time to draw the frame. + * NOTE: When clearing compositingFrame, remember to set + * lastCompositedFrameIndex to -1. Code assume that if + * lastCompositedFrameIndex >= 0 then compositingFrame exists. + */ + RawAccessFrameRef mCompositingFrame; + + /** the previous composited frame, for DISPOSE_RESTORE_PREVIOUS + * + * The Previous Frame (all frames composited up to the current) needs to be + * stored in cases where the image specifies it wants the last frame back + * when it's done with the current frame. + */ + RawAccessFrameRef mCompositingPrevFrame; + //! Area of the first frame that needs to be redrawn on subsequent loops. nsIntRect mFirstFrameRefreshArea; @@ -156,10 +263,13 @@ uint32_t mCurrentAnimationFrameIndex; //! number of loops remaining before animation stops (-1 no stop) - int32_t mLoopCounter; + int32_t mLoopRemainingCount; + + //! Track the last composited frame for Optimizations (See DoComposite code) + int32_t mLastCompositedFrameIndex; - //! All the frames of the image, shared with our owner - FrameBlender& mFrameBlender; + //! The total number of loops for the image. + int32_t mLoopCount; //! The animation mode of this image. Constants defined in imgIContainer. uint16_t mAnimationMode; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/FrameBlender.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/FrameBlender.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/FrameBlender.cpp 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/FrameBlender.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,597 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * 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 "FrameBlender.h" - -#include "mozilla/MemoryReporting.h" -#include "mozilla/Move.h" -#include "MainThreadUtils.h" - -#include "pixman.h" - -namespace mozilla { - -using namespace gfx; - -namespace image { - -FrameBlender::FrameBlender() - : mAnim(nullptr) - , mLoopCount(-1) -{ -} - -FrameBlender::~FrameBlender() -{ - delete mAnim; -} - -already_AddRefed -FrameBlender::GetFrame(uint32_t aFrameNum) -{ - if (mAnim && mAnim->lastCompositedFrameIndex == int32_t(aFrameNum)) { - nsRefPtr frame = mAnim->compositingFrame.get(); - return frame.forget(); - } - return RawGetFrame(aFrameNum); -} - -already_AddRefed -FrameBlender::RawGetFrame(uint32_t aFrameNum) -{ - if (!mAnim) { - NS_ASSERTION(aFrameNum == 0, - "Don't ask for a frame > 0 if we're not animated!"); - aFrameNum = 0; - } - if (aFrameNum >= mFrames.Length()) { - return nullptr; - } - nsRefPtr frame = mFrames[aFrameNum].get(); - return frame.forget(); -} - -uint32_t -FrameBlender::GetNumFrames() const -{ - return mFrames.Length(); -} - -int32_t -FrameBlender::GetTimeoutForFrame(uint32_t aFrameNum) -{ - nsRefPtr frame = RawGetFrame(aFrameNum); - const int32_t timeout = frame->GetRawTimeout(); - - // Ensure a minimal time between updates so we don't throttle the UI thread. - // consider 0 == unspecified and make it fast but not too fast. Unless we - // have a single loop GIF. See bug 890743, bug 125137, bug 139677, and bug - // 207059. The behavior of recent IE and Opera versions seems to be: - // IE 6/Win: - // 10 - 50ms go 100ms - // >50ms go correct speed - // Opera 7 final/Win: - // 10ms goes 100ms - // >10ms go correct speed - // It seems that there are broken tools out there that set a 0ms or 10ms - // timeout when they really want a "default" one. So munge values in that - // range. - if (timeout >= 0 && timeout <= 10 && mLoopCount != 0) { - return 100; - } - - return timeout; -} - -void -FrameBlender::SetLoopCount(int32_t aLoopCount) -{ - mLoopCount = aLoopCount; -} - -int32_t -FrameBlender::GetLoopCount() const -{ - return mLoopCount; -} - -void -FrameBlender::RemoveFrame(uint32_t aFrameNum) -{ - MOZ_ASSERT(aFrameNum < GetNumFrames(), "Deleting invalid frame!"); - mFrames.RemoveElementAt(aFrameNum); -} - -void -FrameBlender::ClearFrames() -{ - mFrames.Clear(); - mFrames.Compact(); -} - -void -FrameBlender::InsertFrame(uint32_t aFrameNum, RawAccessFrameRef&& aRef) -{ - MOZ_ASSERT(aRef, "Need a reference to a frame"); - MOZ_ASSERT(aFrameNum <= GetNumFrames(), "Inserting invalid frame"); - - mFrames.InsertElementAt(aFrameNum, Move(aRef)); - if (GetNumFrames() == 2) { - MOZ_ASSERT(!mAnim, "Shouldn't have an animation context yet"); - mAnim = new Anim(); - } - - MOZ_ASSERT(GetNumFrames() < 2 || mAnim, - "If we're animated we should have an animation context now"); -} - -//****************************************************************************** -// DoBlend gets called when the timer for animation get fired and we have to -// update the composited frame of the animation. -bool -FrameBlender::DoBlend(nsIntRect* aDirtyRect, - uint32_t aPrevFrameIndex, - uint32_t aNextFrameIndex) -{ - nsRefPtr prevFrame = RawGetFrame(aPrevFrameIndex); - nsRefPtr nextFrame = RawGetFrame(aNextFrameIndex); - - MOZ_ASSERT(prevFrame && nextFrame, "Should have frames here"); - - int32_t prevFrameDisposalMethod = prevFrame->GetFrameDisposalMethod(); - if (prevFrameDisposalMethod == FrameBlender::kDisposeRestorePrevious && - !mAnim->compositingPrevFrame) { - prevFrameDisposalMethod = FrameBlender::kDisposeClear; - } - - nsIntRect prevFrameRect = prevFrame->GetRect(); - bool isFullPrevFrame = (prevFrameRect.x == 0 && prevFrameRect.y == 0 && - prevFrameRect.width == mSize.width && - prevFrameRect.height == mSize.height); - - // Optimization: DisposeClearAll if the previous frame is the same size as - // container and it's clearing itself - if (isFullPrevFrame && - (prevFrameDisposalMethod == FrameBlender::kDisposeClear)) { - prevFrameDisposalMethod = FrameBlender::kDisposeClearAll; - } - - int32_t nextFrameDisposalMethod = nextFrame->GetFrameDisposalMethod(); - nsIntRect nextFrameRect = nextFrame->GetRect(); - bool isFullNextFrame = (nextFrameRect.x == 0 && nextFrameRect.y == 0 && - nextFrameRect.width == mSize.width && - nextFrameRect.height == mSize.height); - - if (!nextFrame->GetIsPaletted()) { - // Optimization: Skip compositing if the previous frame wants to clear the - // whole image - if (prevFrameDisposalMethod == FrameBlender::kDisposeClearAll) { - aDirtyRect->SetRect(0, 0, mSize.width, mSize.height); - return true; - } - - // Optimization: Skip compositing if this frame is the same size as the - // container and it's fully drawing over prev frame (no alpha) - if (isFullNextFrame && - (nextFrameDisposalMethod != FrameBlender::kDisposeRestorePrevious) && - !nextFrame->GetHasAlpha()) { - aDirtyRect->SetRect(0, 0, mSize.width, mSize.height); - return true; - } - } - - // Calculate area that needs updating - switch (prevFrameDisposalMethod) { - default: - case FrameBlender::kDisposeNotSpecified: - case FrameBlender::kDisposeKeep: - *aDirtyRect = nextFrameRect; - break; - - case FrameBlender::kDisposeClearAll: - // Whole image container is cleared - aDirtyRect->SetRect(0, 0, mSize.width, mSize.height); - break; - - case FrameBlender::kDisposeClear: - // Calc area that needs to be redrawn (the combination of previous and - // this frame) - // XXX - This could be done with multiple framechanged calls - // Having prevFrame way at the top of the image, and nextFrame - // way at the bottom, and both frames being small, we'd be - // telling framechanged to refresh the whole image when only two - // small areas are needed. - aDirtyRect->UnionRect(nextFrameRect, prevFrameRect); - break; - - case FrameBlender::kDisposeRestorePrevious: - aDirtyRect->SetRect(0, 0, mSize.width, mSize.height); - break; - } - - // Optimization: - // Skip compositing if the last composited frame is this frame - // (Only one composited frame was made for this animation. Example: - // Only Frame 3 of a 10 frame image required us to build a composite frame - // On the second loop, we do not need to rebuild the frame - // since it's still sitting in compositingFrame) - if (mAnim->lastCompositedFrameIndex == int32_t(aNextFrameIndex)) { - return true; - } - - bool needToBlankComposite = false; - - // Create the Compositing Frame - if (!mAnim->compositingFrame) { - nsRefPtr newFrame = new imgFrame; - nsresult rv = newFrame->InitForDecoder(mSize, SurfaceFormat::B8G8R8A8); - if (NS_FAILED(rv)) { - mAnim->compositingFrame.reset(); - return false; - } - mAnim->compositingFrame = newFrame->RawAccessRef(); - needToBlankComposite = true; - } else if (int32_t(aNextFrameIndex) != mAnim->lastCompositedFrameIndex+1) { - - // If we are not drawing on top of last composited frame, - // then we are building a new composite frame, so let's clear it first. - needToBlankComposite = true; - } - - // More optimizations possible when next frame is not transparent - // But if the next frame has FrameBlender::kDisposeRestorePrevious, - // this "no disposal" optimization is not possible, - // because the frame in "after disposal operation" state - // needs to be stored in compositingFrame, so it can be - // copied into compositingPrevFrame later. - bool doDisposal = true; - if (!nextFrame->GetHasAlpha() && - nextFrameDisposalMethod != FrameBlender::kDisposeRestorePrevious) { - if (isFullNextFrame) { - // Optimization: No need to dispose prev.frame when - // next frame is full frame and not transparent. - doDisposal = false; - // No need to blank the composite frame - needToBlankComposite = false; - } else { - if ((prevFrameRect.x >= nextFrameRect.x) && - (prevFrameRect.y >= nextFrameRect.y) && - (prevFrameRect.x + prevFrameRect.width <= - nextFrameRect.x + nextFrameRect.width) && - (prevFrameRect.y + prevFrameRect.height <= - nextFrameRect.y + nextFrameRect.height)) { - // Optimization: No need to dispose prev.frame when - // next frame fully overlaps previous frame. - doDisposal = false; - } - } - } - - if (doDisposal) { - // Dispose of previous: clear, restore, or keep (copy) - switch (prevFrameDisposalMethod) { - case FrameBlender::kDisposeClear: - if (needToBlankComposite) { - // If we just created the composite, it could have anything in its - // buffer. Clear whole frame - ClearFrame(mAnim->compositingFrame->GetRawData(), - mAnim->compositingFrame->GetRect()); - } else { - // Only blank out previous frame area (both color & Mask/Alpha) - ClearFrame(mAnim->compositingFrame->GetRawData(), - mAnim->compositingFrame->GetRect(), - prevFrameRect); - } - break; - - case FrameBlender::kDisposeClearAll: - ClearFrame(mAnim->compositingFrame->GetRawData(), - mAnim->compositingFrame->GetRect()); - break; - - case FrameBlender::kDisposeRestorePrevious: - // It would be better to copy only the area changed back to - // compositingFrame. - if (mAnim->compositingPrevFrame) { - CopyFrameImage(mAnim->compositingPrevFrame->GetRawData(), - mAnim->compositingPrevFrame->GetRect(), - mAnim->compositingFrame->GetRawData(), - mAnim->compositingFrame->GetRect()); - - // destroy only if we don't need it for this frame's disposal - if (nextFrameDisposalMethod != - FrameBlender::kDisposeRestorePrevious) { - mAnim->compositingPrevFrame.reset(); - } - } else { - ClearFrame(mAnim->compositingFrame->GetRawData(), - mAnim->compositingFrame->GetRect()); - } - break; - - default: - // Copy previous frame into compositingFrame before we put the new - // frame on top - // Assumes that the previous frame represents a full frame (it could be - // smaller in size than the container, as long as the frame before it - // erased itself) - // Note: Frame 1 never gets into DoBlend(), so (aNextFrameIndex - 1) - // will always be a valid frame number. - if (mAnim->lastCompositedFrameIndex != int32_t(aNextFrameIndex - 1)) { - if (isFullPrevFrame && !prevFrame->GetIsPaletted()) { - // Just copy the bits - CopyFrameImage(prevFrame->GetRawData(), - prevFrame->GetRect(), - mAnim->compositingFrame->GetRawData(), - mAnim->compositingFrame->GetRect()); - } else { - if (needToBlankComposite) { - // Only blank composite when prev is transparent or not full. - if (prevFrame->GetHasAlpha() || !isFullPrevFrame) { - ClearFrame(mAnim->compositingFrame->GetRawData(), - mAnim->compositingFrame->GetRect()); - } - } - DrawFrameTo(prevFrame->GetRawData(), prevFrameRect, - prevFrame->PaletteDataLength(), - prevFrame->GetHasAlpha(), - mAnim->compositingFrame->GetRawData(), - mAnim->compositingFrame->GetRect(), - FrameBlendMethod(prevFrame->GetBlendMethod())); - } - } - } - } else if (needToBlankComposite) { - // If we just created the composite, it could have anything in its - // buffers. Clear them - ClearFrame(mAnim->compositingFrame->GetRawData(), - mAnim->compositingFrame->GetRect()); - } - - // Check if the frame we are composing wants the previous image restored after - // it is done. Don't store it (again) if last frame wanted its image restored - // too - if ((nextFrameDisposalMethod == FrameBlender::kDisposeRestorePrevious) && - (prevFrameDisposalMethod != FrameBlender::kDisposeRestorePrevious)) { - // We are storing the whole image. - // It would be better if we just stored the area that nextFrame is going to - // overwrite. - if (!mAnim->compositingPrevFrame) { - nsRefPtr newFrame = new imgFrame; - nsresult rv = newFrame->InitForDecoder(mSize, SurfaceFormat::B8G8R8A8); - if (NS_FAILED(rv)) { - mAnim->compositingPrevFrame.reset(); - return false; - } - - mAnim->compositingPrevFrame = newFrame->RawAccessRef(); - } - - CopyFrameImage(mAnim->compositingFrame->GetRawData(), - mAnim->compositingFrame->GetRect(), - mAnim->compositingPrevFrame->GetRawData(), - mAnim->compositingPrevFrame->GetRect()); - } - - // blit next frame into it's correct spot - DrawFrameTo(nextFrame->GetRawData(), nextFrameRect, - nextFrame->PaletteDataLength(), - nextFrame->GetHasAlpha(), - mAnim->compositingFrame->GetRawData(), - mAnim->compositingFrame->GetRect(), - FrameBlendMethod(nextFrame->GetBlendMethod())); - - // Set timeout of CompositeFrame to timeout of frame we just composed - // Bug 177948 - int32_t timeout = nextFrame->GetRawTimeout(); - mAnim->compositingFrame->SetRawTimeout(timeout); - - // Tell the image that it is fully 'downloaded'. - nsresult rv = - mAnim->compositingFrame->ImageUpdated(mAnim->compositingFrame->GetRect()); - if (NS_FAILED(rv)) { - return false; - } - - mAnim->lastCompositedFrameIndex = int32_t(aNextFrameIndex); - - return true; -} - -//****************************************************************************** -// Fill aFrame with black. Does also clears the mask. -void -FrameBlender::ClearFrame(uint8_t* aFrameData, const nsIntRect& aFrameRect) -{ - if (!aFrameData) { - return; - } - - memset(aFrameData, 0, aFrameRect.width * aFrameRect.height * 4); -} - -//****************************************************************************** -void -FrameBlender::ClearFrame(uint8_t* aFrameData, const nsIntRect& aFrameRect, - const nsIntRect& aRectToClear) -{ - if (!aFrameData || aFrameRect.width <= 0 || aFrameRect.height <= 0 || - aRectToClear.width <= 0 || aRectToClear.height <= 0) { - return; - } - - nsIntRect toClear = aFrameRect.Intersect(aRectToClear); - if (toClear.IsEmpty()) { - return; - } - - uint32_t bytesPerRow = aFrameRect.width * 4; - for (int row = toClear.y; row < toClear.y + toClear.height; ++row) { - memset(aFrameData + toClear.x * 4 + row * bytesPerRow, 0, - toClear.width * 4); - } -} - -//****************************************************************************** -// Whether we succeed or fail will not cause a crash, and there's not much -// we can do about a failure, so there we don't return a nsresult -bool -FrameBlender::CopyFrameImage(const uint8_t* aDataSrc, const nsIntRect& aRectSrc, - uint8_t* aDataDest, const nsIntRect& aRectDest) -{ - uint32_t dataLengthSrc = aRectSrc.width * aRectSrc.height * 4; - uint32_t dataLengthDest = aRectDest.width * aRectDest.height * 4; - - if (!aDataDest || !aDataSrc || dataLengthSrc != dataLengthDest) { - return false; - } - - memcpy(aDataDest, aDataSrc, dataLengthDest); - - return true; -} - -nsresult -FrameBlender::DrawFrameTo(const uint8_t* aSrcData, const nsIntRect& aSrcRect, - uint32_t aSrcPaletteLength, bool aSrcHasAlpha, - uint8_t* aDstPixels, const nsIntRect& aDstRect, - FrameBlender::FrameBlendMethod aBlendMethod) -{ - NS_ENSURE_ARG_POINTER(aSrcData); - NS_ENSURE_ARG_POINTER(aDstPixels); - - // According to both AGIF and APNG specs, offsets are unsigned - if (aSrcRect.x < 0 || aSrcRect.y < 0) { - NS_WARNING("FrameBlender::DrawFrameTo: negative offsets not allowed"); - return NS_ERROR_FAILURE; - } - // Outside the destination frame, skip it - if ((aSrcRect.x > aDstRect.width) || (aSrcRect.y > aDstRect.height)) { - return NS_OK; - } - - if (aSrcPaletteLength) { - // Larger than the destination frame, clip it - int32_t width = std::min(aSrcRect.width, aDstRect.width - aSrcRect.x); - int32_t height = std::min(aSrcRect.height, aDstRect.height - aSrcRect.y); - - // The clipped image must now fully fit within destination image frame - NS_ASSERTION((aSrcRect.x >= 0) && (aSrcRect.y >= 0) && - (aSrcRect.x + width <= aDstRect.width) && - (aSrcRect.y + height <= aDstRect.height), - "FrameBlender::DrawFrameTo: Invalid aSrcRect"); - - // clipped image size may be smaller than source, but not larger - NS_ASSERTION((width <= aSrcRect.width) && (height <= aSrcRect.height), - "FrameBlender::DrawFrameTo: source must be smaller than dest"); - - // Get pointers to image data - const uint8_t* srcPixels = aSrcData + aSrcPaletteLength; - uint32_t* dstPixels = reinterpret_cast(aDstPixels); - const uint32_t* colormap = reinterpret_cast(aSrcData); - - // Skip to the right offset - dstPixels += aSrcRect.x + (aSrcRect.y * aDstRect.width); - if (!aSrcHasAlpha) { - for (int32_t r = height; r > 0; --r) { - for (int32_t c = 0; c < width; c++) { - dstPixels[c] = colormap[srcPixels[c]]; - } - // Go to the next row in the source resp. destination image - srcPixels += aSrcRect.width; - dstPixels += aDstRect.width; - } - } else { - for (int32_t r = height; r > 0; --r) { - for (int32_t c = 0; c < width; c++) { - const uint32_t color = colormap[srcPixels[c]]; - if (color) { - dstPixels[c] = color; - } - } - // Go to the next row in the source resp. destination image - srcPixels += aSrcRect.width; - dstPixels += aDstRect.width; - } - } - } else { - pixman_image_t* src = - pixman_image_create_bits( - aSrcHasAlpha ? PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8, - aSrcRect.width, aSrcRect.height, - reinterpret_cast(const_cast(aSrcData)), - aSrcRect.width * 4); - pixman_image_t* dst = - pixman_image_create_bits(PIXMAN_a8r8g8b8, - aDstRect.width, - aDstRect.height, - reinterpret_cast(aDstPixels), - aDstRect.width * 4); - - auto op = aBlendMethod == FrameBlender::kBlendSource ? PIXMAN_OP_SRC - : PIXMAN_OP_OVER; - pixman_image_composite32(op, - src, - nullptr, - dst, - 0, 0, - 0, 0, - aSrcRect.x, aSrcRect.y, - aSrcRect.width, aSrcRect.height); - - pixman_image_unref(src); - pixman_image_unref(dst); - } - - return NS_OK; -} - -void -FrameBlender::Discard() -{ - MOZ_ASSERT(NS_IsMainThread()); - - // As soon as an image becomes animated, it becomes non-discardable and any - // timers are cancelled. - NS_ABORT_IF_FALSE(!mAnim, "Asked to discard for animated image!"); - - // Delete all the decoded frames, then clear the array. - ClearFrames(); -} - -size_t -FrameBlender::SizeOfDecoded(gfxMemoryLocation aLocation, - MallocSizeOf aMallocSizeOf) const -{ - size_t n = 0; - - for (uint32_t i = 0; i < mFrames.Length(); ++i) { - n += mFrames[i]->SizeOfExcludingThis(aLocation, aMallocSizeOf); - } - - if (mAnim) { - if (mAnim->compositingFrame) { - n += mAnim->compositingFrame - ->SizeOfExcludingThis(aLocation, aMallocSizeOf); - } - if (mAnim->compositingPrevFrame) { - n += mAnim->compositingPrevFrame - ->SizeOfExcludingThis(aLocation, aMallocSizeOf); - } - } - - return n; -} - -void -FrameBlender::ResetAnimation() -{ - if (mAnim) { - mAnim->lastCompositedFrameIndex = -1; - } -} - -} // namespace image -} // namespace mozilla diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/FrameBlender.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/FrameBlender.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/FrameBlender.h 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/FrameBlender.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,187 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * 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_imagelib_FrameBlender_h_ -#define mozilla_imagelib_FrameBlender_h_ - -#include "mozilla/MemoryReporting.h" -#include "gfxTypes.h" -#include "imgFrame.h" -#include "nsCOMPtr.h" - -namespace mozilla { -namespace image { - -/** - * FrameBlender stores and gives access to imgFrames. It also knows how to - * blend frames from previous to next, looping if necessary. - * - * All logic about when and whether to blend are external to FrameBlender. - */ -class FrameBlender -{ -public: - - /** - * Create a new FrameBlender with a given frame sequence. - * - * If aSequenceToUse is not specified, it will be allocated automatically. - */ - FrameBlender(); - ~FrameBlender(); - - bool DoBlend(nsIntRect* aDirtyRect, uint32_t aPrevFrameIndex, - uint32_t aNextFrameIndex); - - /** - * Get the @aIndex-th frame, including (if applicable) any results of - * blending. - */ - already_AddRefed GetFrame(uint32_t aIndex); - - /** - * Get the @aIndex-th frame in the frame index, ignoring results of blending. - */ - already_AddRefed RawGetFrame(uint32_t aIndex); - - void InsertFrame(uint32_t aFrameNum, RawAccessFrameRef&& aRef); - void RemoveFrame(uint32_t aFrameNum); - void ClearFrames(); - - /* The total number of frames in this image. */ - uint32_t GetNumFrames() const; - - /* - * Returns the frame's adjusted timeout. If the animation loops and the - * timeout falls in between a certain range then the timeout is adjusted so - * that it's never 0. If the animation does not loop then no adjustments are - * made. - */ - int32_t GetTimeoutForFrame(uint32_t aFrameNum); - - /* - * Set number of times to loop the image. - * @note -1 means loop forever. - */ - void SetLoopCount(int32_t aLoopCount); - int32_t GetLoopCount() const; - - void Discard(); - - void SetSize(nsIntSize aSize) { mSize = aSize; } - - size_t SizeOfDecoded(gfxMemoryLocation aLocation, - MallocSizeOf aMallocSizeOf) const; - - void ResetAnimation(); - - // "Blend" method indicates how the current image is combined with the - // previous image. - enum FrameBlendMethod { - // All color components of the frame, including alpha, overwrite the current - // contents of the frame's output buffer region - kBlendSource = 0, - - // The frame should be composited onto the output buffer based on its alpha, - // using a simple OVER operation - kBlendOver - }; - - enum FrameDisposalMethod { - kDisposeClearAll = -1, // Clear the whole image, revealing - // what was there before the gif displayed - kDisposeNotSpecified, // Leave frame, let new frame draw on top - kDisposeKeep, // Leave frame, let new frame draw on top - kDisposeClear, // Clear the frame's area, revealing bg - kDisposeRestorePrevious // Restore the previous (composited) frame - }; - - // A hint as to whether an individual frame is entirely opaque, or requires - // alpha blending. - enum FrameAlpha { - kFrameHasAlpha, - kFrameOpaque - }; - -private: - - struct Anim - { - //! Track the last composited frame for Optimizations (See DoComposite code) - int32_t lastCompositedFrameIndex; - - /** For managing blending of frames - * - * Some animations will use the compositingFrame to composite images - * and just hand this back to the caller when it is time to draw the frame. - * NOTE: When clearing compositingFrame, remember to set - * lastCompositedFrameIndex to -1. Code assume that if - * lastCompositedFrameIndex >= 0 then compositingFrame exists. - */ - RawAccessFrameRef compositingFrame; - - /** the previous composited frame, for DISPOSE_RESTORE_PREVIOUS - * - * The Previous Frame (all frames composited up to the current) needs to be - * stored in cases where the image specifies it wants the last frame back - * when it's done with the current frame. - */ - RawAccessFrameRef compositingPrevFrame; - - Anim() : lastCompositedFrameIndex(-1) { } - }; - - /** Clears an area of with transparent black. - * - * @param aFrameData Target Frame data - * @param aFrameRect The rectangle of the data pointed ot by aFrameData - * - * @note Does also clears the transparency mask - */ - static void ClearFrame(uint8_t* aFrameData, const nsIntRect& aFrameRect); - - //! @overload - static void ClearFrame(uint8_t* aFrameData, const nsIntRect& aFrameRect, - const nsIntRect& aRectToClear); - - //! Copy one frame's image and mask into another - static bool CopyFrameImage(const uint8_t* aDataSrc, const nsIntRect& aRectSrc, - uint8_t* aDataDest, const nsIntRect& aRectDest); - - /** - * Draws one frame's image to into another, at the position specified by - * aSrcRect. - * - * @aSrcData the raw data of the current frame being drawn - * @aSrcRect the size of the source frame, and the position of that frame in - * the composition frame - * @aSrcPaletteLength the length (in bytes) of the palette at the beginning - * of the source data (0 if image is not paletted) - * @aSrcHasAlpha whether the source data represents an image with alpha - * @aDstPixels the raw data of the composition frame where the current frame - * is drawn into (32-bit ARGB) - * @aDstRect the size of the composition frame - * @aBlendMethod the blend method for how to blend src on the composition - * frame. - */ - static nsresult DrawFrameTo(const uint8_t* aSrcData, - const nsIntRect& aSrcRect, - uint32_t aSrcPaletteLength, bool aSrcHasAlpha, - uint8_t* aDstPixels, const nsIntRect& aDstRect, - FrameBlendMethod aBlendMethod); - -private: // data - //! All the frames of the image - nsTArray mFrames; - nsIntSize mSize; - Anim* mAnim; - int32_t mLoopCount; -}; - -} // namespace image -} // namespace mozilla - -#endif /* mozilla_imagelib_FrameBlender_h_ */ diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/FrozenImage.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/FrozenImage.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/FrozenImage.cpp 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/FrozenImage.cpp 2015-01-09 12:36:28.000000000 +0000 @@ -13,12 +13,6 @@ NS_IMPL_ISUPPORTS_INHERITED0(FrozenImage, ImageWrapper) -nsIntRect -FrozenImage::FrameRect(uint32_t /* aWhichFrame - ignored */) -{ - return InnerImage()->FrameRect(FRAME_FIRST); -} - void FrozenImage::IncrementAnimationConsumers() { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/FrozenImage.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/FrozenImage.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/FrozenImage.h 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/FrozenImage.h 2015-01-09 12:36:28.000000000 +0000 @@ -31,7 +31,6 @@ public: NS_DECL_ISUPPORTS_INHERITED - virtual nsIntRect FrameRect(uint32_t aWhichFrame) MOZ_OVERRIDE; virtual void IncrementAnimationConsumers() MOZ_OVERRIDE; virtual void DecrementAnimationConsumers() MOZ_OVERRIDE; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/ImageFactory.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/ImageFactory.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/ImageFactory.cpp 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/ImageFactory.cpp 2015-01-09 12:36:28.000000000 +0000 @@ -71,7 +71,7 @@ imageFlags |= Image::INIT_FLAG_DECODE_ON_DRAW; } if (isMultiPart) { - imageFlags |= Image::INIT_FLAG_MULTIPART; + imageFlags |= Image::INIT_FLAG_TRANSIENT; } return imageFlags; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/Image.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/Image.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/Image.h 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/Image.h 2015-01-09 12:36:28.000000000 +0000 @@ -7,6 +7,7 @@ #define MOZILLA_IMAGELIB_IMAGE_H_ #include "mozilla/MemoryReporting.h" +#include "mozilla/TimeStamp.h" #include "gfx2DGlue.h" // for gfxMemoryLocation #include "imgIContainer.h" #include "ProgressTracker.h" @@ -46,14 +47,16 @@ * INIT_FLAG_DECODE_ON_DRAW: The container should decode on draw rather than * decoding on load. * - * INIT_FLAG_MULTIPART: The container will be used to display a stream of - * images in a multipart channel. If this flag is set, INIT_FLAG_DISCARDABLE - * and INIT_FLAG_DECODE_ON_DRAW must not be set. + * INIT_FLAG_TRANSIENT: The container is likely to exist for only a short time + * before being destroyed. (For example, containers for + * multipart/x-mixed-replace image parts fall into this category.) If this + * flag is set, INIT_FLAG_DISCARDABLE and INIT_FLAG_DECODE_ON_DRAW must not be + * set. */ static const uint32_t INIT_FLAG_NONE = 0x0; static const uint32_t INIT_FLAG_DISCARDABLE = 0x1; static const uint32_t INIT_FLAG_DECODE_ON_DRAW = 0x2; - static const uint32_t INIT_FLAG_MULTIPART = 0x4; + static const uint32_t INIT_FLAG_TRANSIENT = 0x4; /** * Creates a new image container. @@ -68,11 +71,6 @@ virtual void SetProgressTracker(ProgressTracker* aProgressTracker) {} /** - * The rectangle defining the location and size of the given frame. - */ - virtual nsIntRect FrameRect(uint32_t aWhichFrame) = 0; - - /** * The size, in bytes, occupied by the compressed source data of the image. * If MallocSizeOf does not work on this platform, uses a fallback approach to * ensure that something reasonable is always returned. @@ -123,12 +121,6 @@ bool aLastPart) = 0; /** - * Called for multipart images to allow for any necessary reinitialization - * when there's a new part to add. - */ - virtual nsresult OnNewSourceData() = 0; - - /** * Called when the SurfaceCache discards a persistent surface belonging to * this image. */ diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/ImageMetadata.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/ImageMetadata.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/ImageMetadata.h 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/ImageMetadata.h 2015-01-09 12:36:28.000000000 +0000 @@ -42,8 +42,10 @@ void SetSize(int32_t width, int32_t height, Orientation orientation) { - mSize.emplace(nsIntSize(width, height)); - mOrientation.emplace(orientation); + if (!HasSize()) { + mSize.emplace(nsIntSize(width, height)); + mOrientation.emplace(orientation); + } } bool HasSize() const { return mSize.isSome(); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/ImageWrapper.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/ImageWrapper.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/ImageWrapper.cpp 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/ImageWrapper.cpp 2015-01-09 12:36:28.000000000 +0000 @@ -33,12 +33,6 @@ return mInnerImage->GetProgressTracker(); } -nsIntRect -ImageWrapper::FrameRect(uint32_t aWhichFrame) -{ - return mInnerImage->FrameRect(aWhichFrame); -} - size_t ImageWrapper::SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const { @@ -97,12 +91,6 @@ aLastPart); } -nsresult -ImageWrapper::OnNewSourceData() -{ - return mInnerImage->OnNewSourceData(); -} - void ImageWrapper::OnSurfaceDiscarded() { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/ImageWrapper.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/ImageWrapper.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/ImageWrapper.h 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/ImageWrapper.h 2015-01-09 12:36:28.000000000 +0000 @@ -25,7 +25,6 @@ virtual nsresult Init(const char* aMimeType, uint32_t aFlags) MOZ_OVERRIDE; virtual already_AddRefed GetProgressTracker() MOZ_OVERRIDE; - virtual nsIntRect FrameRect(uint32_t aWhichFrame) MOZ_OVERRIDE; virtual size_t SizeOfSourceWithComputedFallback( MallocSizeOf aMallocSizeOf) const @@ -49,7 +48,6 @@ nsISupports* aContext, nsresult aStatus, bool aLastPart) MOZ_OVERRIDE; - virtual nsresult OnNewSourceData() MOZ_OVERRIDE; virtual void OnSurfaceDiscarded() MOZ_OVERRIDE; @@ -65,7 +63,7 @@ explicit ImageWrapper(Image* aInnerImage) : mInnerImage(aInnerImage) { - NS_ABORT_IF_FALSE(aInnerImage, "Cannot wrap a null image"); + MOZ_ASSERT(aInnerImage, "Need an image to wrap"); } virtual ~ImageWrapper() { } @@ -73,7 +71,13 @@ /** * Returns a weak reference to the inner image wrapped by this ImageWrapper. */ - Image* InnerImage() { return mInnerImage.get(); } + Image* InnerImage() const { return mInnerImage.get(); } + + void SetInnerImage(Image* aInnerImage) + { + MOZ_ASSERT(aInnerImage, "Need an image to wrap"); + mInnerImage = aInnerImage; + } private: nsRefPtr mInnerImage; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/imgFrame.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/imgFrame.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/imgFrame.cpp 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/imgFrame.cpp 2015-01-09 12:36:28.000000000 +0000 @@ -22,6 +22,7 @@ #include "MainThreadUtils.h" #include "mozilla/MemoryReporting.h" #include "nsMargin.h" +#include "nsThreadUtils.h" #include "mozilla/CheckedInt.h" #include "mozilla/gfx/Tools.h" @@ -128,19 +129,20 @@ } -imgFrame::imgFrame() : - mDecoded(0, 0, 0, 0), - mDecodedMutex("imgFrame::mDecoded"), - mPalettedImageData(nullptr), - mTimeout(100), - mDisposalMethod(0), /* imgIContainer::kDisposeNotSpecified */ - mLockCount(0), - mBlendMethod(1), /* imgIContainer::kBlendOver */ - mSinglePixel(false), - mCompositingFailed(false), - mHasNoAlpha(false), - mNonPremult(false), - mOptimizable(false) +imgFrame::imgFrame() + : mMutex("imgFrame") + , mDecoded(0, 0, 0, 0) + , mLockCount(0) + , mTimeout(100) + , mDisposalMethod(DisposalMethod::NOT_SPECIFIED) + , mBlendMethod(BlendMethod::OVER) + , mHasNoAlpha(false) + , mPalettedImageData(nullptr) + , mPaletteDepth(0) + , mNonPremult(false) + , mSinglePixel(false) + , mCompositingFailed(false) + , mOptimizable(false) { static bool hasCheckedOptimize = false; if (!hasCheckedOptimize) { @@ -161,7 +163,8 @@ imgFrame::InitForDecoder(const nsIntSize& aImageSize, const nsIntRect& aRect, SurfaceFormat aFormat, - uint8_t aPaletteDepth /* = 0 */) + uint8_t aPaletteDepth /* = 0 */, + bool aNonPremult /* = false */) { // Assert for properties that should be verified by decoders, // warn for properties related to bad content. @@ -176,6 +179,7 @@ mFormat = aFormat; mPaletteDepth = aPaletteDepth; + mNonPremult = aNonPremult; if (aPaletteDepth != 0) { // We're creating for a paletted image. @@ -185,8 +189,11 @@ return NS_ERROR_FAILURE; } - // Use the fallible allocator here - mPalettedImageData = (uint8_t*)moz_malloc(PaletteDataLength() + GetImageDataLength()); + // Use the fallible allocator here. Paletted images always use 1 byte per + // pixel, so calculating the amount of memory we need is straightforward. + mPalettedImageData = + static_cast(moz_malloc(PaletteDataLength() + + (mSize.width * mSize.height))); if (!mPalettedImageData) NS_WARNING("moz_malloc for paletted image data should succeed"); NS_ENSURE_TRUE(mPalettedImageData, NS_ERROR_OUT_OF_MEMORY); @@ -300,6 +307,7 @@ nsresult imgFrame::Optimize() { MOZ_ASSERT(NS_IsMainThread()); + mMutex.AssertCurrentThreadOwns(); MOZ_ASSERT(mLockCount == 1, "Should only optimize when holding the lock exclusively"); @@ -359,7 +367,8 @@ SurfaceFormat optFormat = gfxPlatform::GetPlatform()->Optimal2DFormatForContent(gfxContentType::COLOR); - if (!GetHasAlpha() && optFormat == SurfaceFormat::R5G6B5) { + if (mFormat != SurfaceFormat::B8G8R8A8 && + optFormat == SurfaceFormat::R5G6B5) { RefPtr buf = AllocateBufferForImage(mSize, optFormat); if (!buf) @@ -425,6 +434,16 @@ return RawAccessFrameRef(this); } +void +imgFrame::SetRawAccessOnly() +{ + AssertImageDataLocked(); + + // Lock our data and throw away the key. + LockImageData(); +} + + imgFrame::SurfaceWithFormat imgFrame::SurfaceForDrawing(bool aDoPadding, bool aDoPartialDecode, @@ -435,6 +454,9 @@ ImageRegion& aRegion, SourceSurface* aSurface) { + MOZ_ASSERT(NS_IsMainThread()); + mMutex.AssertCurrentThreadOwns(); + IntSize size(int32_t(aImageRect.Width()), int32_t(aImageRect.Height())); if (!aDoPadding && !aDoPartialDecode) { NS_ASSERTION(!mSinglePixel, "This should already have been handled"); @@ -487,19 +509,22 @@ PROFILER_LABEL("imgFrame", "Draw", js::ProfileEntry::Category::GRAPHICS); + MOZ_ASSERT(NS_IsMainThread()); NS_ASSERTION(!aRegion.Rect().IsEmpty(), "Drawing empty region!"); NS_ASSERTION(!aRegion.IsRestricted() || !aRegion.Rect().Intersect(aRegion.Restriction()).IsEmpty(), "We must be allowed to sample *some* source pixels!"); NS_ASSERTION(!mPalettedImageData, "Directly drawing a paletted image!"); + MutexAutoLock lock(mMutex); + nsIntMargin padding(mOffset.y, mImageSize.width - (mOffset.x + mSize.width), mImageSize.height - (mOffset.y + mSize.height), mOffset.x); bool doPadding = padding != nsIntMargin(0,0,0,0); - bool doPartialDecode = !ImageComplete(); + bool doPartialDecode = !ImageCompleteInternal(); if (mSinglePixel && !doPadding && !doPartialDecode) { if (mSinglePixelColor.a == 0.0) { @@ -513,7 +538,7 @@ return true; } - RefPtr surf = GetSurface(); + RefPtr surf = GetSurfaceInternal(); if (!surf && !mSinglePixel) { return false; } @@ -541,10 +566,17 @@ return true; } -// This can be called from any thread, but not simultaneously. -nsresult imgFrame::ImageUpdated(const nsIntRect &aUpdateRect) +nsresult +imgFrame::ImageUpdated(const nsIntRect& aUpdateRect) { - MutexAutoLock lock(mDecodedMutex); + MutexAutoLock lock(mMutex); + return ImageUpdatedInternal(aUpdateRect); +} + +nsresult +imgFrame::ImageUpdatedInternal(const nsIntRect& aUpdateRect) +{ + mMutex.AssertCurrentThreadOwns(); mDecoded.UnionRect(mDecoded, aUpdateRect); @@ -556,6 +588,23 @@ return NS_OK; } +void +imgFrame::Finish(Opacity aFrameOpacity, DisposalMethod aDisposalMethod, + int32_t aRawTimeout, BlendMethod aBlendMethod) +{ + MutexAutoLock lock(mMutex); + MOZ_ASSERT(mLockCount > 0, "Image data should be locked"); + + if (aFrameOpacity == Opacity::OPAQUE) { + mHasNoAlpha = true; + } + + mDisposalMethod = aDisposalMethod; + mTimeout = aRawTimeout; + mBlendMethod = aBlendMethod; + ImageUpdatedInternal(GetRect()); +} + nsIntRect imgFrame::GetRect() const { return nsIntRect(mOffset, nsIntSize(mSize.width, mSize.height)); @@ -564,6 +613,8 @@ int32_t imgFrame::GetStride() const { + mMutex.AssertCurrentThreadOwns(); + if (mImageSurface) { return mImageSurface->Stride(); } @@ -573,11 +624,14 @@ SurfaceFormat imgFrame::GetFormat() const { + MutexAutoLock lock(mMutex); return mFormat; } uint32_t imgFrame::GetImageBytesPerRow() const { + mMutex.AssertCurrentThreadOwns(); + if (mVBuf) return mSize.width * BytesPerPixel(mFormat); @@ -592,18 +646,31 @@ return GetImageBytesPerRow() * mSize.height; } -void imgFrame::GetImageData(uint8_t **aData, uint32_t *length) const +void +imgFrame::GetImageData(uint8_t** aData, uint32_t* aLength) const { - NS_ABORT_IF_FALSE(mLockCount != 0, "Can't GetImageData unless frame is locked"); + MutexAutoLock lock(mMutex); + GetImageDataInternal(aData, aLength); +} - if (mImageSurface) +void +imgFrame::GetImageDataInternal(uint8_t** aData, uint32_t* aLength) const +{ + mMutex.AssertCurrentThreadOwns(); + MOZ_ASSERT(mLockCount > 0, "Image data should be locked"); + + if (mImageSurface) { *aData = mVBufPtr; - else if (mPalettedImageData) + MOZ_ASSERT(*aData, "mImageSurface is non-null, but mVBufPtr is null in GetImageData"); + } else if (mPalettedImageData) { *aData = mPalettedImageData + PaletteDataLength(); - else + MOZ_ASSERT(*aData, "mPalettedImageData is non-null, but result is null in GetImageData"); + } else { + MOZ_ASSERT(false, "Have neither mImageSurface nor mPalettedImageData in GetImageData"); *aData = nullptr; + } - *length = GetImageDataLength(); + *aLength = GetImageDataLength(); } uint8_t* imgFrame::GetImageData() const @@ -619,14 +686,9 @@ return mPalettedImageData != nullptr; } -bool imgFrame::GetHasAlpha() const -{ - return mFormat == SurfaceFormat::B8G8R8A8; -} - void imgFrame::GetPaletteData(uint32_t **aPalette, uint32_t *length) const { - NS_ABORT_IF_FALSE(mLockCount != 0, "Can't GetPaletteData unless frame is locked"); + AssertImageDataLocked(); if (!mPalettedImageData) { *aPalette = nullptr; @@ -645,21 +707,12 @@ return data; } -uint8_t* -imgFrame::GetRawData() const -{ - MOZ_ASSERT(mLockCount, "Should be locked to call GetRawData()"); - if (mPalettedImageData) { - return mPalettedImageData; - } - return GetImageData(); -} - -nsresult imgFrame::LockImageData() +nsresult +imgFrame::LockImageData() { - MOZ_ASSERT(NS_IsMainThread()); + MutexAutoLock lock(mMutex); - NS_ABORT_IF_FALSE(mLockCount >= 0, "Unbalanced locks and unlocks"); + MOZ_ASSERT(mLockCount >= 0, "Unbalanced locks and unlocks"); if (mLockCount < 0) { return NS_ERROR_FAILURE; } @@ -671,9 +724,26 @@ return NS_OK; } + // If we're the first lock, but have an image surface, we're OK. + if (mImageSurface) { + mVBufPtr = mVBuf; + return NS_OK; + } + // Paletted images don't have surfaces, so there's nothing to do. - if (mPalettedImageData) + if (mPalettedImageData) { return NS_OK; + } + + return Deoptimize(); +} + +nsresult +imgFrame::Deoptimize() +{ + MOZ_ASSERT(NS_IsMainThread()); + mMutex.AssertCurrentThreadOwns(); + MOZ_ASSERT(!mImageSurface); if (!mImageSurface) { if (mVBuf) { @@ -737,9 +807,34 @@ return NS_OK; } -nsresult imgFrame::UnlockImageData() +void +imgFrame::AssertImageDataLocked() const { - MOZ_ASSERT(NS_IsMainThread()); +#ifdef DEBUG + MutexAutoLock lock(mMutex); + MOZ_ASSERT(mLockCount > 0, "Image data should be locked"); +#endif +} + +class UnlockImageDataRunnable : public nsRunnable +{ +public: + explicit UnlockImageDataRunnable(imgFrame* aTarget) + : mTarget(aTarget) + { + MOZ_ASSERT(mTarget); + } + + NS_IMETHOD Run() { return mTarget->UnlockImageData(); } + +private: + nsRefPtr mTarget; +}; + +nsresult +imgFrame::UnlockImageData() +{ + MutexAutoLock lock(mMutex); MOZ_ASSERT(mLockCount > 0, "Unlocking an unlocked image!"); if (mLockCount <= 0) { @@ -750,6 +845,13 @@ // surface anymore. (But we don't need to do anything for paletted images, // which don't have surfaces.) if (mLockCount == 1 && !mPalettedImageData) { + // We can't safely optimize off-main-thread, so create a runnable to do it. + if (!NS_IsMainThread()) { + nsCOMPtr runnable = new UnlockImageDataRunnable(this); + NS_DispatchToMainThread(runnable); + return NS_OK; + } + // If we're using a surface format with alpha but the image has no alpha, // change the format. This doesn't change the underlying data at all, but // allows DrawTargets to avoid blending when drawing known opaque images. @@ -774,13 +876,37 @@ void imgFrame::SetOptimizable() { - MOZ_ASSERT(mLockCount, "Expected to be locked when SetOptimizable is called"); + MOZ_ASSERT(NS_IsMainThread()); + AssertImageDataLocked(); mOptimizable = true; } +Color +imgFrame::SinglePixelColor() const +{ + MOZ_ASSERT(NS_IsMainThread()); + return mSinglePixelColor; +} + +bool +imgFrame::IsSinglePixel() const +{ + MOZ_ASSERT(NS_IsMainThread()); + return mSinglePixel; +} + TemporaryRef imgFrame::GetSurface() { + MutexAutoLock lock(mMutex); + return GetSurfaceInternal(); +} + +TemporaryRef +imgFrame::GetSurfaceInternal() +{ + mMutex.AssertCurrentThreadOwns(); + if (mOptSurface) { if (mOptSurface->IsValid()) return mOptSurface; @@ -804,9 +930,11 @@ TemporaryRef imgFrame::GetDrawTarget() { - MOZ_ASSERT(mLockCount >= 1, "Should lock before requesting a DrawTarget"); + MutexAutoLock lock(mMutex); - uint8_t* data = GetImageData(); + uint8_t* data; + uint32_t length; + GetImageDataInternal(&data, &length); if (!data) { return nullptr; } @@ -816,65 +944,64 @@ CreateDrawTargetForData(data, mSize, stride, mFormat); } -int32_t imgFrame::GetRawTimeout() const +AnimationData +imgFrame::GetAnimationData() const { - return mTimeout; -} + MutexAutoLock lock(mMutex); + MOZ_ASSERT(mLockCount > 0, "Image data should be locked"); -void imgFrame::SetRawTimeout(int32_t aTimeout) -{ - mTimeout = aTimeout; -} - -int32_t imgFrame::GetFrameDisposalMethod() const -{ - return mDisposalMethod; -} + uint8_t* data; + if (mPalettedImageData) { + data = mPalettedImageData; + } else { + uint32_t length; + GetImageDataInternal(&data, &length); + } -void imgFrame::SetFrameDisposalMethod(int32_t aFrameDisposalMethod) -{ - mDisposalMethod = aFrameDisposalMethod; -} + bool hasAlpha = mFormat == SurfaceFormat::B8G8R8A8; -int32_t imgFrame::GetBlendMethod() const -{ - return mBlendMethod; + return AnimationData(data, PaletteDataLength(), mTimeout, GetRect(), + mBlendMethod, mDisposalMethod, hasAlpha); } -void imgFrame::SetBlendMethod(int32_t aBlendMethod) +ScalingData +imgFrame::GetScalingData() const { - mBlendMethod = (int8_t)aBlendMethod; -} + MutexAutoLock lock(mMutex); + MOZ_ASSERT(mLockCount > 0, "Image data should be locked"); + MOZ_ASSERT(!GetIsPaletted(), "GetScalingData can't handle paletted images"); -// This can be called from any thread. -bool imgFrame::ImageComplete() const -{ - MutexAutoLock lock(mDecodedMutex); + uint8_t* data; + uint32_t length; + GetImageDataInternal(&data, &length); - return mDecoded.IsEqualInterior(nsIntRect(mOffset.x, mOffset.y, - mSize.width, mSize.height)); + return ScalingData(data, mSize, GetImageBytesPerRow(), mFormat); } -// A hint from the image decoders that this image has no alpha, even -// though we're decoding it as B8G8R8A8. -void imgFrame::SetHasNoAlpha() +bool +imgFrame::ImageComplete() const { - MOZ_ASSERT(mLockCount, "Expected to be locked when SetHasNoAlpha is called"); - mHasNoAlpha = true; + MutexAutoLock lock(mMutex); + return ImageCompleteInternal(); } -void imgFrame::SetAsNonPremult(bool aIsNonPremult) +bool +imgFrame::ImageCompleteInternal() const { - mNonPremult = aIsNonPremult; + mMutex.AssertCurrentThreadOwns(); + return mDecoded.IsEqualInterior(nsIntRect(mOffset.x, mOffset.y, + mSize.width, mSize.height)); } bool imgFrame::GetCompositingFailed() const { + MOZ_ASSERT(NS_IsMainThread()); return mCompositingFailed; } void imgFrame::SetCompositingFailed(bool val) { + MOZ_ASSERT(NS_IsMainThread()); mCompositingFailed = val; } @@ -882,6 +1009,8 @@ imgFrame::SizeOfExcludingThis(gfxMemoryLocation aLocation, MallocSizeOf aMallocSizeOf) const { + MutexAutoLock lock(mMutex); + // aMallocSizeOf is only used if aLocation==gfxMemoryLocation::IN_PROCESS_HEAP. It // should be nullptr otherwise. NS_ABORT_IF_FALSE( diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/imgFrame.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/imgFrame.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/imgFrame.h 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/imgFrame.h 2015-01-09 12:36:28.000000000 +0000 @@ -10,9 +10,11 @@ #include "mozilla/MemoryReporting.h" #include "mozilla/Move.h" #include "mozilla/Mutex.h" +#include "mozilla/TypedEnum.h" #include "mozilla/VolatileBuffer.h" #include "gfxDrawable.h" #include "imgIContainer.h" +#include "MainThreadUtils.h" namespace mozilla { namespace image { @@ -21,6 +23,88 @@ class DrawableFrameRef; class RawAccessFrameRef; +MOZ_BEGIN_ENUM_CLASS(BlendMethod, int8_t) + // All color components of the frame, including alpha, overwrite the current + // contents of the frame's output buffer region. + SOURCE, + + // The frame should be composited onto the output buffer based on its alpha, + // using a simple OVER operation. + OVER +MOZ_END_ENUM_CLASS(BlendMethod) + +MOZ_BEGIN_ENUM_CLASS(DisposalMethod, int8_t) + CLEAR_ALL = -1, // Clear the whole image, revealing what's underneath. + NOT_SPECIFIED, // Leave the frame and let the new frame draw on top. + KEEP, // Leave the frame and let the new frame draw on top. + CLEAR, // Clear the frame's area, revealing what's underneath. + RESTORE_PREVIOUS // Restore the previous (composited) frame. +MOZ_END_ENUM_CLASS(DisposalMethod) + +MOZ_BEGIN_ENUM_CLASS(Opacity, uint8_t) + OPAQUE, + SOME_TRANSPARENCY +MOZ_END_ENUM_CLASS(Opacity) + + +/** + * AnimationData contains all of the information necessary for using an imgFrame + * as part of an animation. + * + * It includes pointers to the raw image data of the underlying imgFrame, but + * does not own that data. A RawAccessFrameRef for the underlying imgFrame must + * outlive the AnimationData for it to remain valid. + */ +struct AnimationData +{ + AnimationData(uint8_t* aRawData, uint32_t aPaletteDataLength, + int32_t aRawTimeout, const nsIntRect& aRect, + BlendMethod aBlendMethod, DisposalMethod aDisposalMethod, + bool aHasAlpha) + : mRawData(aRawData) + , mPaletteDataLength(aPaletteDataLength) + , mRawTimeout(aRawTimeout) + , mRect(aRect) + , mBlendMethod(aBlendMethod) + , mDisposalMethod(aDisposalMethod) + , mHasAlpha(aHasAlpha) + { } + + uint8_t* mRawData; + uint32_t mPaletteDataLength; + int32_t mRawTimeout; + nsIntRect mRect; + BlendMethod mBlendMethod; + DisposalMethod mDisposalMethod; + bool mHasAlpha; +}; + +/** + * ScalingData contains all of the information necessary for performing + * high-quality (CPU-based) scaling an imgFrame. + * + * It includes pointers to the raw image data of the underlying imgFrame, but + * does not own that data. A RawAccessFrameRef for the underlying imgFrame must + * outlive the ScalingData for it to remain valid. + */ +struct ScalingData +{ + ScalingData(uint8_t* aRawData, + gfx::IntSize aSize, + uint32_t aBytesPerRow, + gfx::SurfaceFormat aFormat) + : mRawData(aRawData) + , mSize(aSize) + , mBytesPerRow(aBytesPerRow) + , mFormat(aFormat) + { } + + uint8_t* mRawData; + gfx::IntSize mSize; + uint32_t mBytesPerRow; + gfx::SurfaceFormat mFormat; +}; + class imgFrame { typedef gfx::Color Color; @@ -47,7 +131,8 @@ nsresult InitForDecoder(const nsIntSize& aImageSize, const nsIntRect& aRect, SurfaceFormat aFormat, - uint8_t aPaletteDepth = 0); + uint8_t aPaletteDepth = 0, + bool aNonPremult = false); nsresult InitForDecoder(const nsIntSize& aSize, SurfaceFormat aFormat, @@ -77,71 +162,78 @@ DrawableFrameRef DrawableRef(); RawAccessFrameRef RawAccessRef(); + /** + * Make this imgFrame permanently available for raw access. + * + * This is irrevocable, and should be avoided whenever possible, since it + * prevents this imgFrame from being optimized and makes it impossible for its + * volatile buffer to be freed. + * + * It is an error to call this without already holding a RawAccessFrameRef to + * this imgFrame. + */ + void SetRawAccessOnly(); + bool Draw(gfxContext* aContext, const ImageRegion& aRegion, GraphicsFilter aFilter, uint32_t aImageFlags); nsresult ImageUpdated(const nsIntRect &aUpdateRect); + /** + * Mark this imgFrame as completely decoded, and set final options. + * + * @param aFrameOpacity Whether this imgFrame is opaque. + * @param aDisposalMethod For animation frames, how this imgFrame is cleared + * from the compositing frame before the next frame is + * displayed. + * @param aRawTimeout For animation frames, the timeout in milliseconds + * before the next frame is displayed. This timeout is + * not necessarily the timeout that will actually be + * used; see FrameAnimator::GetTimeoutForFrame. + * @param aBlendMethod For animation frames, a blending method to be used + * when compositing this frame. + */ + void Finish(Opacity aFrameOpacity, DisposalMethod aDisposalMethod, + int32_t aRawTimeout, BlendMethod aBlendMethod); + IntSize GetImageSize() { return mImageSize; } nsIntRect GetRect() const; IntSize GetSize() const { return mSize; } bool NeedsPadding() const { return mOffset != nsIntPoint(0, 0); } - int32_t GetStride() const; - SurfaceFormat GetFormat() const; - uint32_t GetImageBytesPerRow() const; - uint32_t GetImageDataLength() const; - bool GetIsPaletted() const; - bool GetHasAlpha() const; void GetImageData(uint8_t **aData, uint32_t *length) const; uint8_t* GetImageData() const; + + bool GetIsPaletted() const; void GetPaletteData(uint32_t **aPalette, uint32_t *length) const; uint32_t* GetPaletteData() const; - uint8_t* GetRawData() const; + uint8_t GetPaletteDepth() const { return mPaletteDepth; } - int32_t GetRawTimeout() const; - void SetRawTimeout(int32_t aTimeout); + /** + * Get the SurfaceFormat for this imgFrame. + * + * This should only be used for assertions. + */ + SurfaceFormat GetFormat() const; - int32_t GetFrameDisposalMethod() const; - void SetFrameDisposalMethod(int32_t aFrameDisposalMethod); - int32_t GetBlendMethod() const; - void SetBlendMethod(int32_t aBlendMethod); - bool ImageComplete() const; + AnimationData GetAnimationData() const; + ScalingData GetScalingData() const; - void SetHasNoAlpha(); - void SetAsNonPremult(bool aIsNonPremult); + bool ImageComplete() const; bool GetCompositingFailed() const; void SetCompositingFailed(bool val); void SetOptimizable(); + Color SinglePixelColor() const; + bool IsSinglePixel() const; + TemporaryRef GetSurface(); TemporaryRef GetDrawTarget(); - Color - SinglePixelColor() - { - return mSinglePixelColor; - } - - bool IsSinglePixel() - { - return mSinglePixel; - } - - TemporaryRef CachedSurface(); - size_t SizeOfExcludingThis(gfxMemoryLocation aLocation, MallocSizeOf aMallocSizeOf) const; - uint8_t GetPaletteDepth() const { return mPaletteDepth; } - uint32_t PaletteDataLength() const { - if (!mPaletteDepth) - return 0; - - return ((1 << mPaletteDepth) * sizeof(uint32_t)); - } - private: // methods ~imgFrame(); @@ -149,6 +241,23 @@ nsresult LockImageData(); nsresult UnlockImageData(); nsresult Optimize(); + nsresult Deoptimize(); + + void AssertImageDataLocked() const; + + bool ImageCompleteInternal() const; + nsresult ImageUpdatedInternal(const nsIntRect& aUpdateRect); + void GetImageDataInternal(uint8_t **aData, uint32_t *length) const; + uint32_t GetImageBytesPerRow() const; + uint32_t GetImageDataLength() const; + int32_t GetStride() const; + TemporaryRef GetSurfaceInternal(); + + uint32_t PaletteDataLength() const + { + return mPaletteDepth ? (1 << mPaletteDepth) * sizeof(uint32_t) + : 0; + } struct SurfaceWithFormat { nsRefPtr mDrawable; @@ -169,46 +278,65 @@ SourceSurface* aSurface); private: // data + friend class DrawableFrameRef; + friend class RawAccessFrameRef; + friend class UnlockImageDataRunnable; + + ////////////////////////////////////////////////////////////////////////////// + // Thread-safe mutable data, protected by mMutex. + ////////////////////////////////////////////////////////////////////////////// + + mutable Mutex mMutex; + RefPtr mImageSurface; RefPtr mOptSurface; + RefPtr mVBuf; + VolatileBufferPtr mVBufPtr; + + nsIntRect mDecoded; + + //! Number of RawAccessFrameRefs currently alive for this imgFrame. + int32_t mLockCount; + + //! Raw timeout for this frame. (See FrameAnimator::GetTimeoutForFrame.) + int32_t mTimeout; // -1 means display forever. + + DisposalMethod mDisposalMethod; + BlendMethod mBlendMethod; + SurfaceFormat mFormat; + + bool mHasNoAlpha; + + + ////////////////////////////////////////////////////////////////////////////// + // Effectively const data, only mutated in the Init methods. + ////////////////////////////////////////////////////////////////////////////// + IntSize mImageSize; IntSize mSize; nsIntPoint mOffset; - nsIntRect mDecoded; - - mutable Mutex mDecodedMutex; - // The palette and image data for images that are paletted, since Cairo // doesn't support these images. // The paletted data comes first, then the image data itself. // Total length is PaletteDataLength() + GetImageDataLength(). uint8_t* mPalettedImageData; + uint8_t mPaletteDepth; - // Note that the data stored in gfx::Color is *non-alpha-premultiplied*. - Color mSinglePixelColor; + bool mNonPremult; - int32_t mTimeout; // -1 means display forever - int32_t mDisposalMethod; - /** Indicates how many readers currently have locked this frame */ - int32_t mLockCount; + ////////////////////////////////////////////////////////////////////////////// + // Main-thread-only mutable data. + ////////////////////////////////////////////////////////////////////////////// - RefPtr mVBuf; - VolatileBufferPtr mVBufPtr; + // Note that the data stored in gfx::Color is *non-alpha-premultiplied*. + Color mSinglePixelColor; - SurfaceFormat mFormat; - uint8_t mPaletteDepth; - int8_t mBlendMethod; bool mSinglePixel; bool mCompositingFailed; - bool mHasNoAlpha; - bool mNonPremult; bool mOptimizable; - - friend class DrawableFrameRef; - friend class RawAccessFrameRef; }; /** diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/imgRequest.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/imgRequest.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/imgRequest.cpp 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/imgRequest.cpp 2015-01-09 12:36:28.000000000 +0000 @@ -12,6 +12,7 @@ #include "ProgressTracker.h" #include "ImageFactory.h" #include "Image.h" +#include "MultipartImage.h" #include "RasterImage.h" #include "nsIChannel.h" @@ -62,7 +63,7 @@ imgRequest::imgRequest(imgLoader* aLoader) : mLoader(aLoader) - , mProgressTracker(new ProgressTracker(nullptr)) + , mProgressTracker(new ProgressTracker()) , mValidator(nullptr) , mInnerWindowId(0) , mCORSMode(imgIRequest::CORS_NONE) @@ -72,7 +73,7 @@ , mIsMultiPartChannel(false) , mGotData(false) , mIsInCache(false) - , mResniffMimeType(false) + , mNewPartPending(false) { } imgRequest::~imgRequest() @@ -142,7 +143,7 @@ already_AddRefed imgRequest::GetProgressTracker() { - if (mImage && mGotData) { + if (mImage) { NS_ABORT_IF_FALSE(!mProgressTracker, "Should have given mProgressTracker to mImage"); return mImage->GetProgressTracker(); @@ -180,14 +181,14 @@ // If we're empty before adding, we have to tell the loader we now have // proxies. nsRefPtr progressTracker = GetProgressTracker(); - if (progressTracker->ConsumerCount() == 0) { + if (progressTracker->ObserverCount() == 0) { NS_ABORT_IF_FALSE(mURI, "Trying to SetHasProxies without key uri."); if (mLoader) { mLoader->SetHasProxies(this); } } - progressTracker->AddConsumer(proxy); + progressTracker->AddObserver(proxy); } nsresult imgRequest::RemoveProxy(imgRequestProxy *proxy, nsresult aStatus) @@ -204,10 +205,10 @@ // before Cancel() returns, leaving the image in a different state then the // one it was in at this point. nsRefPtr progressTracker = GetProgressTracker(); - if (!progressTracker->RemoveConsumer(proxy, aStatus)) + if (!progressTracker->RemoveObserver(proxy)) return NS_OK; - if (progressTracker->ConsumerCount() == 0) { + if (progressTracker->ObserverCount() == 0) { // If we have no observers, there's nothing holding us alive. If we haven't // been cancelled and thus removed from the cache, tell the image loader so // we can be evicted from the cache. @@ -417,7 +418,7 @@ bool imgRequest::HasConsumers() { nsRefPtr progressTracker = GetProgressTracker(); - return progressTracker && progressTracker->ConsumerCount() > 0; + return progressTracker && progressTracker->ObserverCount() > 0; } int32_t imgRequest::Priority() const @@ -439,7 +440,7 @@ // of content such as link clicks, CSS, and JS. // nsRefPtr progressTracker = GetProgressTracker(); - if (!progressTracker->FirstConsumerIs(proxy)) + if (!progressTracker->FirstObserverIs(proxy)) return; nsCOMPtr p = do_QueryInterface(mChannel); @@ -633,12 +634,13 @@ { LOG_SCOPE(GetImgLog(), "imgRequest::OnStartRequest"); - // Figure out if we're multipart + mNewPartPending = true; + + // Figure out if we're multipart. nsCOMPtr mpchan(do_QueryInterface(aRequest)); nsRefPtr progressTracker = GetProgressTracker(); if (mpchan) { mIsMultiPartChannel = true; - progressTracker->SetIsMultipart(); } else { NS_ABORT_IF_FALSE(!mIsMultiPartChannel, "Something went wrong"); } @@ -647,19 +649,6 @@ NS_ABORT_IF_FALSE(mIsMultiPartChannel || !mImage, "Already have an image for non-multipart request"); - // If we're multipart and about to load another image, signal so we can - // detect the mime type in OnDataAvailable. - if (mIsMultiPartChannel && mImage) { - mResniffMimeType = true; - - // Tell the image to reinitialize itself. We have to do this in - // OnStartRequest so that its state machine is always in a consistent - // state. - // Note that if our MIME type changes, mImage will be replaced with a - // new object. - mImage->OnNewSourceData(); - } - /* * If mRequest is null here, then we need to set it so that we'll be able to * cancel it if our Cancel() method is called. Note that this can only @@ -675,10 +664,6 @@ mRequest = chan; } - // Note: refreshing progressTracker in case OnNewSourceData changed it. - progressTracker = GetProgressTracker(); - progressTracker->ResetForNewRequest(); - nsCOMPtr channel(do_QueryInterface(aRequest)); if (channel) channel->GetSecurityInfo(getter_AddRefs(mSecurityInfo)); @@ -701,7 +686,7 @@ mApplicationCache = GetApplicationCache(aRequest); // Shouldn't we be dead already if this gets hit? Probably multipart/x-mixed-replace... - if (progressTracker->ConsumerCount() == 0) { + if (progressTracker->ObserverCount() == 0) { this->Cancel(NS_IMAGELIB_ERROR_FAILURE); } @@ -838,16 +823,12 @@ NS_ASSERTION(aRequest, "imgRequest::OnDataAvailable -- no request!"); nsresult rv; + mGotData = true; - if (!mGotData || mResniffMimeType) { - LOG_SCOPE(GetImgLog(), "imgRequest::OnDataAvailable |First time through... finding mimetype|"); + if (mNewPartPending) { + LOG_SCOPE(GetImgLog(), "imgRequest::OnDataAvailable |New part; finding MIME type|"); - mGotData = true; - - // Store and reset this for the invariant that it's always false after - // calls to OnDataAvailable (see bug 907575) - bool resniffMimeType = mResniffMimeType; - mResniffMimeType = false; + mNewPartPending = false; mimetype_closure closure; nsAutoCString newType; @@ -881,65 +862,66 @@ LOG_MSG(GetImgLog(), "imgRequest::OnDataAvailable", "Got content type from the channel"); } - // If we're a regular image and this is the first call to OnDataAvailable, - // this will always be true. If we've resniffed our MIME type (i.e. we're a - // multipart/x-mixed-replace image), we have to be able to switch our image - // type and decoder. - // We always reinitialize for SVGs, because they have no way of - // reinitializing themselves. - if (mContentType != newType || newType.EqualsLiteral(IMAGE_SVG_XML)) { - mContentType = newType; - - // If we've resniffed our MIME type and it changed, we need to create a - // new status tracker to give to the image, because we don't have one of - // our own any more. - if (resniffMimeType) { - MOZ_ASSERT(mIsMultiPartChannel, "Resniffing a non-multipart image"); - - // Initialize a new status tracker. - nsRefPtr freshTracker = new ProgressTracker(nullptr); - freshTracker->SetIsMultipart(); - - // Replace the old status tracker with it. - nsRefPtr oldProgressTracker = GetProgressTracker(); - freshTracker->AdoptConsumers(oldProgressTracker); - mProgressTracker = freshTracker.forget(); + mContentType = newType; + SetProperties(chan); + bool firstPart = !mImage; + + LOG_MSG_WITH_PARAM(GetImgLog(), "imgRequest::OnDataAvailable", "content type", mContentType.get()); + + // XXX If server lied about mimetype and it's SVG, we may need to copy + // the data and dispatch back to the main thread, AND tell the channel to + // dispatch there in the future. + + // Create the new image and give it ownership of our ProgressTracker. + if (mIsMultiPartChannel) { + // Create the ProgressTracker and image for this part. + nsRefPtr progressTracker = new ProgressTracker(); + nsRefPtr image = + ImageFactory::CreateImage(aRequest, progressTracker, mContentType, + mURI, /* aIsMultipart = */ true, + static_cast(mInnerWindowId)); + + if (!mImage) { + // First part for a multipart channel. Create the MultipartImage wrapper. + MOZ_ASSERT(mProgressTracker, "Shouldn't have given away tracker yet"); + mImage = new MultipartImage(image, mProgressTracker); + mProgressTracker = nullptr; + } else { + // Transition to the new part. + static_cast(mImage.get())->BeginTransitionToPart(image); } + } else { + MOZ_ASSERT(!mImage, "New part for non-multipart channel?"); + MOZ_ASSERT(mProgressTracker, "Shouldn't have given away tracker yet"); - SetProperties(chan); - - LOG_MSG_WITH_PARAM(GetImgLog(), "imgRequest::OnDataAvailable", "content type", mContentType.get()); - - // XXX If server lied about mimetype and it's SVG, we may need to copy - // the data and dispatch back to the main thread, AND tell the channel to - // dispatch there in the future. - - // Now we can create a new image to hold the data. If we don't have a decoder - // for this mimetype we'll find out about it here. - mImage = ImageFactory::CreateImage(aRequest, mProgressTracker, mContentType, - mURI, mIsMultiPartChannel, - static_cast(mInnerWindowId)); - - // Release our copy of the status tracker since the image owns it now. + // Create an image using our progress tracker. + mImage = + ImageFactory::CreateImage(aRequest, mProgressTracker, mContentType, + mURI, /* aIsMultipart = */ false, + static_cast(mInnerWindowId)); mProgressTracker = nullptr; + } + if (firstPart) { // Notify listeners that we have an image. nsRefPtr progressTracker = GetProgressTracker(); progressTracker->OnImageAvailable(); + MOZ_ASSERT(progressTracker->HasImage()); + } - if (mImage->HasError() && !mIsMultiPartChannel) { // Probably bad mimetype - // We allow multipart images to fail to initialize without cancelling the - // load because subsequent images might be fine; thus only single part - // images end up here. - this->Cancel(NS_IMAGELIB_ERROR_FAILURE); - return NS_BINDING_ABORTED; - } + if (mImage->HasError() && !mIsMultiPartChannel) { // Probably bad mimetype + // We allow multipart images to fail to initialize without cancelling the + // load because subsequent images might be fine; thus only single part + // images end up here. + this->Cancel(NS_IMAGELIB_ERROR_FAILURE); + return NS_BINDING_ABORTED; + } - NS_ABORT_IF_FALSE(progressTracker->HasImage(), "Status tracker should have an image!"); - NS_ABORT_IF_FALSE(mImage, "imgRequest should have an image!"); + MOZ_ASSERT(!mProgressTracker, "Should've given tracker to image"); + MOZ_ASSERT(mImage, "Should have image"); - if (mDecodeRequested) - mImage->StartDecoding(); + if (mDecodeRequested) { + mImage->StartDecoding(); } } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/imgRequest.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/imgRequest.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/imgRequest.h 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/imgRequest.h 2015-01-09 12:36:28.000000000 +0000 @@ -272,7 +272,7 @@ bool mGotData : 1; bool mIsInCache : 1; bool mBlockingOnload : 1; - bool mResniffMimeType : 1; + bool mNewPartPending : 1; }; #endif diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/imgRequestProxy.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/imgRequestProxy.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/imgRequestProxy.cpp 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/imgRequestProxy.cpp 2015-01-09 12:36:28.000000000 +0000 @@ -734,98 +734,52 @@ } } -void imgRequestProxy::OnSizeAvailable() +static const char* +NotificationTypeToString(int32_t aType) { - LOG_FUNC(GetImgLog(), "imgRequestProxy::OnStartContainer"); - - if (mListener && !mCanceled) { - // Hold a ref to the listener while we call it, just in case. - nsCOMPtr kungFuDeathGrip(mListener); - mListener->Notify(this, imgINotificationObserver::SIZE_AVAILABLE, nullptr); - } -} - -void imgRequestProxy::OnFrameUpdate(const nsIntRect * rect) -{ - LOG_FUNC(GetImgLog(), "imgRequestProxy::OnFrameUpdate"); - - if (mListener && !mCanceled) { - // Hold a ref to the listener while we call it, just in case. - nsCOMPtr kungFuDeathGrip(mListener); - mListener->Notify(this, imgINotificationObserver::FRAME_UPDATE, rect); - } -} - -void imgRequestProxy::OnFrameComplete() -{ - LOG_FUNC(GetImgLog(), "imgRequestProxy::OnFrameComplete"); - - if (mListener && !mCanceled) { - // Hold a ref to the listener while we call it, just in case. - nsCOMPtr kungFuDeathGrip(mListener); - mListener->Notify(this, imgINotificationObserver::FRAME_COMPLETE, nullptr); - } -} - -void imgRequestProxy::OnDecodeComplete() -{ - LOG_FUNC(GetImgLog(), "imgRequestProxy::OnDecodeComplete"); - - if (mListener && !mCanceled) { - // Hold a ref to the listener while we call it, just in case. - nsCOMPtr kungFuDeathGrip(mListener); - mListener->Notify(this, imgINotificationObserver::DECODE_COMPLETE, nullptr); + switch(aType) + { + case imgINotificationObserver::SIZE_AVAILABLE: return "SIZE_AVAILABLE"; + case imgINotificationObserver::FRAME_UPDATE: return "FRAME_UPDATE"; + case imgINotificationObserver::FRAME_COMPLETE: return "FRAME_COMPLETE"; + case imgINotificationObserver::LOAD_COMPLETE: return "LOAD_COMPLETE"; + case imgINotificationObserver::DECODE_COMPLETE: return "DECODE_COMPLETE"; + case imgINotificationObserver::DISCARD: return "DISCARD"; + case imgINotificationObserver::UNLOCKED_DRAW: return "UNLOCKED_DRAW"; + case imgINotificationObserver::IS_ANIMATED: return "IS_ANIMATED"; + case imgINotificationObserver::HAS_TRANSPARENCY: return "HAS_TRANSPARENCY"; + default: + NS_NOTREACHED("Notification list should be exhaustive"); + return "(unknown notification)"; } } -void imgRequestProxy::OnDiscard() +void +imgRequestProxy::Notify(int32_t aType, const nsIntRect* aRect) { - LOG_FUNC(GetImgLog(), "imgRequestProxy::OnDiscard"); + MOZ_ASSERT(aType != imgINotificationObserver::LOAD_COMPLETE, + "Should call OnLoadComplete"); - if (mListener && !mCanceled) { - // Hold a ref to the listener while we call it, just in case. - nsCOMPtr kungFuDeathGrip(mListener); - mListener->Notify(this, imgINotificationObserver::DISCARD, nullptr); - } -} - -void imgRequestProxy::OnUnlockedDraw() -{ - LOG_FUNC(GetImgLog(), "imgRequestProxy::OnUnlockedDraw"); + LOG_FUNC_WITH_PARAM(GetImgLog(), "imgRequestProxy::Notify", "type", + NotificationTypeToString(aType)); - if (mListener && !mCanceled) { - // Hold a ref to the listener while we call it, just in case. - nsCOMPtr kungFuDeathGrip(mListener); - mListener->Notify(this, imgINotificationObserver::UNLOCKED_DRAW, nullptr); + if (!mListener || mCanceled) { + return; } -} -void imgRequestProxy::OnImageHasTransparency() -{ - LOG_FUNC(GetImgLog(), "imgRequestProxy::OnImageHasTransparency"); - if (mListener && !mCanceled) { - // Hold a ref to the listener while we call it, just in case. - nsCOMPtr kungFuDeathGrip(mListener); - mListener->Notify(this, imgINotificationObserver::HAS_TRANSPARENCY, nullptr); - } -} + // Make sure the listener stays alive while we notify. + nsCOMPtr listener(mListener); -void imgRequestProxy::OnImageIsAnimated() -{ - LOG_FUNC(GetImgLog(), "imgRequestProxy::OnImageIsAnimated"); - if (mListener && !mCanceled) { - // Hold a ref to the listener while we call it, just in case. - nsCOMPtr kungFuDeathGrip(mListener); - mListener->Notify(this, imgINotificationObserver::IS_ANIMATED, nullptr); - } + mListener->Notify(this, aType, aRect); } -void imgRequestProxy::OnLoadComplete(bool aLastPart) +void +imgRequestProxy::OnLoadComplete(bool aLastPart) { #ifdef PR_LOGGING nsAutoCString name; GetName(name); - LOG_FUNC_WITH_PARAM(GetImgLog(), "imgRequestProxy::OnStopRequest", "name", name.get()); + LOG_FUNC_WITH_PARAM(GetImgLog(), "imgRequestProxy::OnLoadComplete", "name", name.get()); #endif // There's all sorts of stuff here that could kill us (the OnStopRequest call // on the listener, the removal from the loadgroup, the release of the @@ -863,7 +817,8 @@ } } -void imgRequestProxy::BlockOnload() +void +imgRequestProxy::BlockOnload() { #ifdef PR_LOGGING nsAutoCString name; @@ -877,7 +832,8 @@ } } -void imgRequestProxy::UnblockOnload() +void +imgRequestProxy::UnblockOnload() { #ifdef PR_LOGGING nsAutoCString name; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/imgRequestProxy.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/imgRequestProxy.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/imgRequestProxy.h 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/imgRequestProxy.h 2015-01-09 12:36:28.000000000 +0000 @@ -7,7 +7,6 @@ #ifndef imgRequestProxy_h__ #define imgRequestProxy_h__ -#include "mozilla/WeakPtr.h" #include "imgIRequest.h" #include "nsISecurityInfoProvider.h" @@ -20,6 +19,7 @@ #include "mozilla/TimeStamp.h" #include "imgRequest.h" +#include "IProgressObserver.h" #define NS_IMGREQUESTPROXY_CID \ { /* 20557898-1dd2-11b2-8f65-9c462ee2bc95 */ \ @@ -44,10 +44,10 @@ } // namespace mozilla class imgRequestProxy : public imgIRequest, + public mozilla::image::IProgressObserver, public nsISupportsPriority, public nsISecurityInfoProvider, - public nsITimedChannel, - public mozilla::SupportsWeakPtr + public nsITimedChannel { protected: virtual ~imgRequestProxy(); @@ -95,20 +95,30 @@ // asynchronously-called function. void SyncNotifyListener(); + // imgINotificationObserver methods: + virtual void Notify(int32_t aType, + const nsIntRect* aRect = nullptr) MOZ_OVERRIDE; + virtual void OnLoadComplete(bool aLastPart) MOZ_OVERRIDE; + + // imgIOnloadBlocker methods: + virtual void BlockOnload() MOZ_OVERRIDE; + virtual void UnblockOnload() MOZ_OVERRIDE; + + // Other, internal-only methods: + virtual void SetHasImage() MOZ_OVERRIDE; + virtual void OnStartDecode() MOZ_OVERRIDE; + // Whether we want notifications from ProgressTracker to be deferred until // an event it has scheduled has been fired. - bool NotificationsDeferred() const + virtual bool NotificationsDeferred() const MOZ_OVERRIDE { return mDeferNotifications; } - void SetNotificationsDeferred(bool aDeferNotifications) + virtual void SetNotificationsDeferred(bool aDeferNotifications) MOZ_OVERRIDE { mDeferNotifications = aDeferNotifications; } - // XXXbholley - This eventually gets folded into the new notification API. - void SetHasImage(); - // Removes all animation consumers that were created with // IncrementAnimationConsumers. This is necessary since we need // to do it before the proxy itself is destroyed. See @@ -145,27 +155,6 @@ nsresult mStatus; }; - // The following notification functions are protected to ensure that (friend - // class) ProgressTracker is the only class allowed to send us - // notifications. - - void OnStartDecode(); - void OnSizeAvailable(); - void OnFrameUpdate(const nsIntRect* aRect); - void OnFrameComplete(); - void OnDecodeComplete(); - void OnDiscard(); - void OnUnlockedDraw(); - void OnImageHasTransparency(); - void OnImageIsAnimated(); - - /* non-virtual sort-of-nsIRequestObserver methods */ - void OnLoadComplete(bool aLastPart); - - /* non-virtual imgIOnloadBlocker methods */ - void BlockOnload(); - void UnblockOnload(); - /* Finish up canceling ourselves */ void DoCancel(nsresult status); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/IProgressObserver.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/IProgressObserver.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/IProgressObserver.h 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/IProgressObserver.h 2015-01-09 12:36:28.000000000 +0000 @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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_IMAGELIB_PROGRESSOBSERVER_H_ +#define MOZILLA_IMAGELIB_PROGRESSOBSERVER_H_ + +#include "mozilla/WeakPtr.h" +#include "nsISupports.h" +#include "nsRect.h" + +namespace mozilla { +namespace image { + +/** + * An interface for observing changes to image state, as reported by + * ProgressTracker. + * + * This is the ImageLib-internal version of imgINotificationObserver, + * essentially, with implementation details that code outside of ImageLib + * shouldn't see. + * + * XXX(seth): It's preferable to avoid adding anything to this interface if + * possible. In the long term, it would be ideal to get to a place where we can + * just use the imgINotificationObserver interface internally as well. + */ +class IProgressObserver : public SupportsWeakPtr +{ +public: + MOZ_DECLARE_REFCOUNTED_TYPENAME(IProgressObserver) + + // Subclasses may or may not be XPCOM classes, so we just require that they + // implement AddRef and Release. + NS_IMETHOD_(MozExternalRefCountType) AddRef(void) = 0; + NS_IMETHOD_(MozExternalRefCountType) Release(void) = 0; + + // imgINotificationObserver methods: + virtual void Notify(int32_t aType, const nsIntRect* aRect = nullptr) = 0; + virtual void OnLoadComplete(bool aLastPart) = 0; + + // imgIOnloadBlocker methods: + virtual void BlockOnload() = 0; + virtual void UnblockOnload() = 0; + + // Other, internal-only methods: + virtual void SetHasImage() = 0; + virtual void OnStartDecode() = 0; + virtual bool NotificationsDeferred() const = 0; + virtual void SetNotificationsDeferred(bool aDeferNotifications) = 0; + +protected: + virtual ~IProgressObserver() { } +}; + +} // namespace image +} // namespace mozilla + +#endif // MOZILLA_IMAGELIB_PROGRESSOBSERVER_H_ diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/moz.build thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/moz.build --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/moz.build 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/moz.build 2015-01-09 12:36:28.000000000 +0000 @@ -10,8 +10,9 @@ 'imgLoader.h', 'imgRequest.h', 'imgRequestProxy.h', + 'IProgressObserver.h', 'Orientation.h', - 'SurfaceCache.h' + 'SurfaceCache.h', ] UNIFIED_SOURCES += [ @@ -20,7 +21,6 @@ 'Decoder.cpp', 'DynamicImage.cpp', 'FrameAnimator.cpp', - 'FrameBlender.cpp', 'FrozenImage.cpp', 'Image.cpp', 'ImageFactory.cpp', @@ -29,6 +29,7 @@ 'ImageWrapper.cpp', 'imgFrame.cpp', 'imgTools.cpp', + 'MultipartImage.cpp', 'OrientedImage.cpp', 'ScriptedNotificationObserver.cpp', 'ShutdownTracker.cpp', diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/MultipartImage.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/MultipartImage.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/MultipartImage.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/MultipartImage.cpp 2015-01-09 12:36:28.000000000 +0000 @@ -0,0 +1,299 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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 "MultipartImage.h" + +#include "imgINotificationObserver.h" + +namespace mozilla { +namespace image { + +/////////////////////////////////////////////////////////////////////////////// +// Helpers +/////////////////////////////////////////////////////////////////////////////// + +class NextPartObserver : public IProgressObserver +{ +public: + MOZ_DECLARE_REFCOUNTED_TYPENAME(NextPartObserver) + NS_INLINE_DECL_REFCOUNTING(NextPartObserver) + + explicit NextPartObserver(MultipartImage* aOwner) + : mOwner(aOwner) + { + MOZ_ASSERT(mOwner); + } + + void BeginObserving(Image* aImage) + { + MOZ_ASSERT(aImage); + mImage = aImage; + + nsRefPtr tracker = mImage->GetProgressTracker(); + tracker->AddObserver(this); + } + + void FinishObservingWithoutNotifying() + { + FinishObserving(/* aNotify = */ false); + } + + virtual void Notify(int32_t aType, + const nsIntRect* aRect = nullptr) MOZ_OVERRIDE + { + if (!mImage) { + // We've already finished observing the last image we were given. + return; + } + + if (aType == imgINotificationObserver::FRAME_COMPLETE) { + FinishObserving(/* aNotify = */ true); + } + } + + virtual void OnLoadComplete(bool aLastPart) MOZ_OVERRIDE + { + if (!mImage) { + // We've already finished observing the last image we were given. + return; + } + + // If there's already an error, we may never get a FRAME_COMPLETE + // notification, so go ahead and notify our owner right away. + nsRefPtr tracker = mImage->GetProgressTracker(); + if (tracker->GetProgress() & FLAG_HAS_ERROR) { + FinishObserving(/* aNotify = */ true); + } + } + + // Other notifications are ignored. + virtual void BlockOnload() MOZ_OVERRIDE { } + virtual void UnblockOnload() MOZ_OVERRIDE { } + virtual void SetHasImage() MOZ_OVERRIDE { } + virtual void OnStartDecode() MOZ_OVERRIDE { } + virtual bool NotificationsDeferred() const MOZ_OVERRIDE { return false; } + virtual void SetNotificationsDeferred(bool) MOZ_OVERRIDE { } + +private: + virtual ~NextPartObserver() { } + + void FinishObserving(bool aNotify) + { + MOZ_ASSERT(mImage); + + nsRefPtr tracker = mImage->GetProgressTracker(); + tracker->RemoveObserver(this); + mImage = nullptr; + + if (aNotify) { + mOwner->FinishTransition(); + } + } + + MultipartImage* mOwner; + nsRefPtr mImage; +}; + + +/////////////////////////////////////////////////////////////////////////////// +// Implementation +/////////////////////////////////////////////////////////////////////////////// + +MultipartImage::MultipartImage(Image* aImage, ProgressTracker* aTracker) + : ImageWrapper(aImage) + , mDeferNotifications(false) +{ + MOZ_ASSERT(aTracker); + mProgressTrackerInit = new ProgressTrackerInit(this, aTracker); + mNextPartObserver = new NextPartObserver(this); + + // Start observing the first part. + nsRefPtr firstPartTracker = + InnerImage()->GetProgressTracker(); + firstPartTracker->AddObserver(this); + InnerImage()->RequestDecode(); + InnerImage()->IncrementAnimationConsumers(); +} + +MultipartImage::~MultipartImage() { } + +NS_IMPL_QUERY_INTERFACE_INHERITED0(MultipartImage, ImageWrapper) +NS_IMPL_ADDREF(MultipartImage) +NS_IMPL_RELEASE(MultipartImage) + +void +MultipartImage::BeginTransitionToPart(Image* aNextPart) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(aNextPart); + + if (mNextPart) { + NS_WARNING("Decoder not keeping up with multipart image"); + mNextPartObserver->FinishObservingWithoutNotifying(); + } + + mNextPart = aNextPart; + + // Start observing the next part; we'll complete the transition when + // NextPartObserver calls FinishTransition. + mNextPartObserver->BeginObserving(mNextPart); + mNextPart->RequestDecode(); + mNextPart->IncrementAnimationConsumers(); +} + +void MultipartImage::FinishTransition() +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(mNextPart, "Should have a next part here"); + + // Stop observing the current part. + { + nsRefPtr currentPartTracker = + InnerImage()->GetProgressTracker(); + currentPartTracker->RemoveObserver(this); + } + + // Make the next part become the current part. + mTracker->ResetForNewRequest(); + SetInnerImage(mNextPart); + mNextPart = nullptr; + nsRefPtr newCurrentPartTracker = + InnerImage()->GetProgressTracker(); + newCurrentPartTracker->AddObserver(this); + + // Finally, send all the notifications for the new current part and send a + // FRAME_UPDATE notification so that observers know to redraw. + mTracker->SyncNotifyProgress(newCurrentPartTracker->GetProgress(), + nsIntRect::GetMaxSizedIntRect()); +} + +already_AddRefed +MultipartImage::Unwrap() +{ + // Although we wrap another image, we don't allow callers to unwrap as. As far + // as external code is concerned, MultipartImage is atomic. + nsCOMPtr image = this; + return image.forget(); +} + +already_AddRefed +MultipartImage::GetProgressTracker() +{ + MOZ_ASSERT(mTracker); + nsRefPtr tracker = mTracker; + return tracker.forget(); +} + +void +MultipartImage::SetProgressTracker(ProgressTracker* aTracker) +{ + MOZ_ASSERT(aTracker); + MOZ_ASSERT(!mTracker); + mTracker = aTracker; +} + +nsresult +MultipartImage::OnImageDataAvailable(nsIRequest* aRequest, + nsISupports* aContext, + nsIInputStream* aInStr, + uint64_t aSourceOffset, + uint32_t aCount) +{ + // Note that this method is special in that we forward it to the next part if + // one exists, and *not* the current part. + + // We may trigger notifications that will free mNextPart, so keep it alive. + nsRefPtr nextPart = mNextPart; + if (nextPart) { + return nextPart->OnImageDataAvailable(aRequest, aContext, aInStr, + aSourceOffset, aCount); + } + + return InnerImage()->OnImageDataAvailable(aRequest, aContext, aInStr, + aSourceOffset, aCount); +} + +nsresult +MultipartImage::OnImageDataComplete(nsIRequest* aRequest, + nsISupports* aContext, + nsresult aStatus, + bool aLastPart) +{ + // Note that this method is special in that we forward it to the next part if + // one exists, and *not* the current part. + + // We may trigger notifications that will free mNextPart, so keep it alive. + nsRefPtr nextPart = mNextPart; + if (nextPart) { + return nextPart->OnImageDataComplete(aRequest, aContext, aStatus, + aLastPart); + } + + return InnerImage()->OnImageDataComplete(aRequest, aContext, aStatus, + aLastPart); +} + +void +MultipartImage::Notify(int32_t aType, const nsIntRect* aRect /* = nullptr*/) +{ + if (aType == imgINotificationObserver::SIZE_AVAILABLE) { + mTracker->SyncNotifyProgress(FLAG_SIZE_AVAILABLE); + } else if (aType == imgINotificationObserver::FRAME_UPDATE) { + mTracker->SyncNotifyProgress(NoProgress, *aRect); + } else if (aType == imgINotificationObserver::FRAME_COMPLETE) { + mTracker->SyncNotifyProgress(FLAG_FRAME_COMPLETE); + } else if (aType == imgINotificationObserver::LOAD_COMPLETE) { + mTracker->SyncNotifyProgress(FLAG_LOAD_COMPLETE); + } else if (aType == imgINotificationObserver::DECODE_COMPLETE) { + mTracker->SyncNotifyProgress(FLAG_DECODE_COMPLETE); + } else if (aType == imgINotificationObserver::DISCARD) { + mTracker->OnDiscard(); + } else if (aType == imgINotificationObserver::UNLOCKED_DRAW) { + mTracker->OnUnlockedDraw(); + } else if (aType == imgINotificationObserver::IS_ANIMATED) { + mTracker->SyncNotifyProgress(FLAG_IS_ANIMATED); + } else if (aType == imgINotificationObserver::HAS_TRANSPARENCY) { + mTracker->SyncNotifyProgress(FLAG_HAS_TRANSPARENCY); + } else { + NS_NOTREACHED("Notification list should be exhaustive"); + } +} + +void +MultipartImage::OnLoadComplete(bool aLastPart) +{ + Progress progress = FLAG_LOAD_COMPLETE; + if (aLastPart) { + progress |= FLAG_LAST_PART_COMPLETE; + } + mTracker->SyncNotifyProgress(progress); +} + +void +MultipartImage::SetHasImage() +{ + mTracker->OnImageAvailable(); +} + +void +MultipartImage::OnStartDecode() +{ + mTracker->SyncNotifyProgress(FLAG_DECODE_STARTED); +} + +bool +MultipartImage::NotificationsDeferred() const +{ + return mDeferNotifications; +} + +void +MultipartImage::SetNotificationsDeferred(bool aDeferNotifications) +{ + mDeferNotifications = aDeferNotifications; +} + +} // namespace image +} // namespace mozilla diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/MultipartImage.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/MultipartImage.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/MultipartImage.h 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/MultipartImage.h 2015-01-09 12:36:28.000000000 +0000 @@ -0,0 +1,90 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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_IMAGELIB_MULTIPARTIMAGE_H_ +#define MOZILLA_IMAGELIB_MULTIPARTIMAGE_H_ + +#include "ImageWrapper.h" +#include "IProgressObserver.h" +#include "ProgressTracker.h" + +namespace mozilla { +namespace image { + +class NextPartObserver; + +/** + * An Image wrapper that implements support for multipart/x-mixed-replace + * images. + */ +class MultipartImage + : public ImageWrapper + , public IProgressObserver +{ +public: + MOZ_DECLARE_REFCOUNTED_TYPENAME(MultipartImage) + NS_DECL_ISUPPORTS + + MultipartImage(Image* aImage, ProgressTracker* aTracker); + + void BeginTransitionToPart(Image* aNextPart); + + // Overridden ImageWrapper methods: + virtual already_AddRefed Unwrap() MOZ_OVERRIDE; + virtual already_AddRefed GetProgressTracker() MOZ_OVERRIDE; + virtual void SetProgressTracker(ProgressTracker* aTracker) MOZ_OVERRIDE; + virtual nsresult OnImageDataAvailable(nsIRequest* aRequest, + nsISupports* aContext, + nsIInputStream* aInStr, + uint64_t aSourceOffset, + uint32_t aCount) MOZ_OVERRIDE; + virtual nsresult OnImageDataComplete(nsIRequest* aRequest, + nsISupports* aContext, + nsresult aStatus, + bool aLastPart) MOZ_OVERRIDE; + + // We don't support locking or track animation consumers for individual parts, + // so we override these methods to do nothing. + NS_IMETHOD LockImage() MOZ_OVERRIDE { return NS_OK; } + NS_IMETHOD UnlockImage() MOZ_OVERRIDE { return NS_OK; } + virtual void IncrementAnimationConsumers() MOZ_OVERRIDE { } + virtual void DecrementAnimationConsumers() MOZ_OVERRIDE { } +#ifdef DEBUG + virtual uint32_t GetAnimationConsumers() MOZ_OVERRIDE { return 1; } +#endif + + // Overridden IProgressObserver methods: + virtual void Notify(int32_t aType, + const nsIntRect* aRect = nullptr) MOZ_OVERRIDE; + virtual void OnLoadComplete(bool aLastPart) MOZ_OVERRIDE; + virtual void SetHasImage() MOZ_OVERRIDE; + virtual void OnStartDecode() MOZ_OVERRIDE; + virtual bool NotificationsDeferred() const MOZ_OVERRIDE; + virtual void SetNotificationsDeferred(bool aDeferNotifications) MOZ_OVERRIDE; + + // We don't allow multipart images to block onload, so we override these + // methods to do nothing. + virtual void BlockOnload() MOZ_OVERRIDE { } + virtual void UnblockOnload() MOZ_OVERRIDE { } + +protected: + virtual ~MultipartImage(); + +private: + friend class NextPartObserver; + + void FinishTransition(); + + nsRefPtr mTracker; + nsAutoPtr mProgressTrackerInit; + nsRefPtr mNextPartObserver; + nsRefPtr mNextPart; + bool mDeferNotifications : 1; +}; + +} // namespace image +} // namespace mozilla + +#endif // MOZILLA_IMAGELIB_MULTIPARTIMAGE_H_ diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/OrientedImage.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/OrientedImage.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/OrientedImage.cpp 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/OrientedImage.cpp 2015-01-09 12:36:28.000000000 +0000 @@ -26,29 +26,6 @@ NS_IMPL_ISUPPORTS_INHERITED0(OrientedImage, ImageWrapper) -nsIntRect -OrientedImage::FrameRect(uint32_t aWhichFrame) -{ - nsresult rv; - - // Retrieve the frame rect of the inner image. - nsIntRect innerRect = InnerImage()->FrameRect(aWhichFrame); - if (mOrientation.IsIdentity()) { - return innerRect; - } - - // Get the underlying image's dimensions. - nsIntSize size; - rv = InnerImage()->GetWidth(&size.width); - NS_ENSURE_SUCCESS(rv, innerRect); - rv = InnerImage()->GetHeight(&size.height); - NS_ENSURE_SUCCESS(rv, innerRect); - - // Transform the frame rect. - gfxRect finalRect = OrientationMatrix(size).TransformBounds(innerRect); - return nsIntRect(finalRect.x, finalRect.y, finalRect.width, finalRect.height); -} - NS_IMETHODIMP OrientedImage::GetWidth(int32_t* aWidth) { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/OrientedImage.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/OrientedImage.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/OrientedImage.h 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/OrientedImage.h 2015-01-09 12:36:28.000000000 +0000 @@ -28,8 +28,6 @@ public: NS_DECL_ISUPPORTS_INHERITED - virtual nsIntRect FrameRect(uint32_t aWhichFrame) MOZ_OVERRIDE; - NS_IMETHOD GetWidth(int32_t* aWidth) MOZ_OVERRIDE; NS_IMETHOD GetHeight(int32_t* aHeight) MOZ_OVERRIDE; NS_IMETHOD GetIntrinsicSize(nsSize* aSize) MOZ_OVERRIDE; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/ProgressTracker.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/ProgressTracker.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/ProgressTracker.cpp 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/ProgressTracker.cpp 2015-01-09 12:36:28.000000000 +0000 @@ -8,7 +8,8 @@ #include "ProgressTracker.h" #include "imgIContainer.h" -#include "imgRequestProxy.h" +#include "imgINotificationObserver.h" +#include "imgIRequest.h" #include "Image.h" #include "nsNetUtil.h" #include "nsIObserverService.h" @@ -28,10 +29,10 @@ if (aTracker) { mTracker = aTracker; - mTracker->SetImage(aImage); } else { - mTracker = new ProgressTracker(aImage); + mTracker = new ProgressTracker(); } + mTracker->SetImage(aImage); aImage->SetProgressTracker(mTracker); MOZ_ASSERT(mTracker); } @@ -62,17 +63,11 @@ // No preconditions. } if (aProgress & FLAG_ONLOAD_BLOCKED) { - if (aProgress & FLAG_IS_MULTIPART) { - MOZ_ASSERT(aProgress & FLAG_ONLOAD_UNBLOCKED); - } else { - MOZ_ASSERT(aProgress & FLAG_DECODE_STARTED); - } + MOZ_ASSERT(aProgress & FLAG_DECODE_STARTED); } if (aProgress & FLAG_ONLOAD_UNBLOCKED) { MOZ_ASSERT(aProgress & FLAG_ONLOAD_BLOCKED); - MOZ_ASSERT(aProgress & (FLAG_FRAME_COMPLETE | - FLAG_IS_MULTIPART | - FLAG_HAS_ERROR)); + MOZ_ASSERT(aProgress & (FLAG_FRAME_COMPLETE | FLAG_HAS_ERROR)); } if (aProgress & FLAG_IS_ANIMATED) { MOZ_ASSERT(aProgress & FLAG_DECODE_STARTED); @@ -81,9 +76,6 @@ if (aProgress & FLAG_HAS_TRANSPARENCY) { MOZ_ASSERT(aProgress & FLAG_SIZE_AVAILABLE); } - if (aProgress & FLAG_IS_MULTIPART) { - // No preconditions. - } if (aProgress & FLAG_LAST_PART_COMPLETE) { MOZ_ASSERT(aProgress & FLAG_LOAD_COMPLETE); } @@ -107,22 +99,6 @@ mImage = nullptr; } -void -ProgressTracker::SetIsMultipart() -{ - if (mProgress & FLAG_IS_MULTIPART) { - return; - } - - MOZ_ASSERT(!(mProgress & FLAG_ONLOAD_BLOCKED), - "Blocked onload before we knew we were multipart?"); - - // Set the MULTIPART flag and ensure that we never block onload. - mProgress |= FLAG_IS_MULTIPART | FLAG_ONLOAD_BLOCKED | FLAG_ONLOAD_UNBLOCKED; - - CheckProgressConsistency(mProgress); -} - bool ProgressTracker::IsLoading() const { @@ -171,49 +147,50 @@ { public: AsyncNotifyRunnable(ProgressTracker* aTracker, - imgRequestProxy* aRequestProxy) + IProgressObserver* aObserver) : mTracker(aTracker) { MOZ_ASSERT(NS_IsMainThread(), "Should be created on the main thread"); MOZ_ASSERT(aTracker, "aTracker should not be null"); - MOZ_ASSERT(aRequestProxy, "aRequestProxy should not be null"); - mProxies.AppendElement(aRequestProxy); + MOZ_ASSERT(aObserver, "aObserver should not be null"); + mObservers.AppendElement(aObserver); } NS_IMETHOD Run() { MOZ_ASSERT(NS_IsMainThread(), "Should be running on the main thread"); MOZ_ASSERT(mTracker, "mTracker should not be null"); - for (uint32_t i = 0; i < mProxies.Length(); ++i) { - mProxies[i]->SetNotificationsDeferred(false); - mTracker->SyncNotify(mProxies[i]); + for (uint32_t i = 0; i < mObservers.Length(); ++i) { + mObservers[i]->SetNotificationsDeferred(false); + mTracker->SyncNotify(mObservers[i]); } mTracker->mRunnable = nullptr; return NS_OK; } - void AddProxy(imgRequestProxy* aRequestProxy) + void AddObserver(IProgressObserver* aObserver) { - mProxies.AppendElement(aRequestProxy); + mObservers.AppendElement(aObserver); } - void RemoveProxy(imgRequestProxy* aRequestProxy) + void RemoveObserver(IProgressObserver* aObserver) { - mProxies.RemoveElement(aRequestProxy); + mObservers.RemoveElement(aObserver); } private: friend class ProgressTracker; nsRefPtr mTracker; - nsTArray> mProxies; + nsTArray> mObservers; }; void -ProgressTracker::Notify(imgRequestProxy* proxy) +ProgressTracker::Notify(IProgressObserver* aObserver) { - MOZ_ASSERT(NS_IsMainThread(), "imgRequestProxy is not threadsafe"); + MOZ_ASSERT(NS_IsMainThread()); + #ifdef PR_LOGGING if (mImage && mImage->GetURI()) { nsRefPtr uri(mImage->GetURI()); @@ -227,18 +204,18 @@ } #endif - proxy->SetNotificationsDeferred(true); + aObserver->SetNotificationsDeferred(true); - // If we have an existing runnable that we can use, we just append this proxy - // to its list of proxies to be notified. This ensures we don't unnecessarily - // delay onload. + // If we have an existing runnable that we can use, we just append this + // observer to its list of observers to be notified. This ensures we don't + // unnecessarily delay onload. AsyncNotifyRunnable* runnable = static_cast(mRunnable.get()); if (runnable) { - runnable->AddProxy(proxy); + runnable->AddObserver(aObserver); } else { - mRunnable = new AsyncNotifyRunnable(this, proxy); + mRunnable = new AsyncNotifyRunnable(this, aObserver); NS_DispatchToCurrentThread(mRunnable); } } @@ -249,28 +226,28 @@ { public: AsyncNotifyCurrentStateRunnable(ProgressTracker* aProgressTracker, - imgRequestProxy* aProxy) + IProgressObserver* aObserver) : mProgressTracker(aProgressTracker) - , mProxy(aProxy) + , mObserver(aObserver) { MOZ_ASSERT(NS_IsMainThread(), "Should be created on the main thread"); MOZ_ASSERT(mProgressTracker, "mProgressTracker should not be null"); - MOZ_ASSERT(mProxy, "mProxy should not be null"); + MOZ_ASSERT(mObserver, "mObserver should not be null"); mImage = mProgressTracker->GetImage(); } NS_IMETHOD Run() { MOZ_ASSERT(NS_IsMainThread(), "Should be running on the main thread"); - mProxy->SetNotificationsDeferred(false); + mObserver->SetNotificationsDeferred(false); - mProgressTracker->SyncNotify(mProxy); + mProgressTracker->SyncNotify(mObserver); return NS_OK; } private: nsRefPtr mProgressTracker; - nsRefPtr mProxy; + nsRefPtr mObserver; // We have to hold on to a reference to the tracker's image, just in case // it goes away while we're in the event queue. @@ -278,53 +255,56 @@ }; void -ProgressTracker::NotifyCurrentState(imgRequestProxy* proxy) +ProgressTracker::NotifyCurrentState(IProgressObserver* aObserver) { - MOZ_ASSERT(NS_IsMainThread(), "imgRequestProxy is not threadsafe"); + MOZ_ASSERT(NS_IsMainThread()); + #ifdef PR_LOGGING - nsRefPtr uri; - proxy->GetURI(getter_AddRefs(uri)); nsAutoCString spec; - uri->GetSpec(spec); + if (mImage && mImage->GetURI()) { + mImage->GetURI()->GetSpec(spec); + } LOG_FUNC_WITH_PARAM(GetImgLog(), "ProgressTracker::NotifyCurrentState", "uri", spec.get()); #endif - proxy->SetNotificationsDeferred(true); + aObserver->SetNotificationsDeferred(true); - nsCOMPtr ev = new AsyncNotifyCurrentStateRunnable(this, proxy); + nsCOMPtr ev = new AsyncNotifyCurrentStateRunnable(this, aObserver); NS_DispatchToCurrentThread(ev); } -#define NOTIFY_IMAGE_OBSERVERS(PROXIES, FUNC) \ +#define NOTIFY_IMAGE_OBSERVERS(OBSERVERS, FUNC) \ do { \ - ProxyArray::ForwardIterator iter(PROXIES); \ + ObserverArray::ForwardIterator iter(OBSERVERS); \ while (iter.HasMore()) { \ - nsRefPtr proxy = iter.GetNext().get(); \ - if (proxy && !proxy->NotificationsDeferred()) { \ - proxy->FUNC; \ + nsRefPtr observer = iter.GetNext().get(); \ + if (observer && !observer->NotificationsDeferred()) { \ + observer->FUNC; \ } \ } \ } while (false); /* static */ void -ProgressTracker::SyncNotifyInternal(ProxyArray& aProxies, +ProgressTracker::SyncNotifyInternal(ObserverArray& aObservers, bool aHasImage, Progress aProgress, const nsIntRect& aDirtyRect) { MOZ_ASSERT(NS_IsMainThread()); + typedef imgINotificationObserver I; + if (aProgress & FLAG_SIZE_AVAILABLE) { - NOTIFY_IMAGE_OBSERVERS(aProxies, OnSizeAvailable()); + NOTIFY_IMAGE_OBSERVERS(aObservers, Notify(I::SIZE_AVAILABLE)); } if (aProgress & FLAG_DECODE_STARTED) { - NOTIFY_IMAGE_OBSERVERS(aProxies, OnStartDecode()); + NOTIFY_IMAGE_OBSERVERS(aObservers, OnStartDecode()); } if (aProgress & FLAG_ONLOAD_BLOCKED) { - NOTIFY_IMAGE_OBSERVERS(aProxies, BlockOnload()); + NOTIFY_IMAGE_OBSERVERS(aObservers, BlockOnload()); } if (aHasImage) { @@ -333,19 +313,19 @@ // vector images, true for raster images that have decoded at // least one frame) then send OnFrameUpdate. if (!aDirtyRect.IsEmpty()) { - NOTIFY_IMAGE_OBSERVERS(aProxies, OnFrameUpdate(&aDirtyRect)); + NOTIFY_IMAGE_OBSERVERS(aObservers, Notify(I::FRAME_UPDATE, &aDirtyRect)); } if (aProgress & FLAG_FRAME_COMPLETE) { - NOTIFY_IMAGE_OBSERVERS(aProxies, OnFrameComplete()); + NOTIFY_IMAGE_OBSERVERS(aObservers, Notify(I::FRAME_COMPLETE)); } if (aProgress & FLAG_HAS_TRANSPARENCY) { - NOTIFY_IMAGE_OBSERVERS(aProxies, OnImageHasTransparency()); + NOTIFY_IMAGE_OBSERVERS(aObservers, Notify(I::HAS_TRANSPARENCY)); } if (aProgress & FLAG_IS_ANIMATED) { - NOTIFY_IMAGE_OBSERVERS(aProxies, OnImageIsAnimated()); + NOTIFY_IMAGE_OBSERVERS(aObservers, Notify(I::IS_ANIMATED)); } } @@ -353,16 +333,16 @@ // observers that can fire events when they receive those notifications to do // so then, instead of being forced to wait for UnblockOnload. if (aProgress & FLAG_ONLOAD_UNBLOCKED) { - NOTIFY_IMAGE_OBSERVERS(aProxies, UnblockOnload()); + NOTIFY_IMAGE_OBSERVERS(aObservers, UnblockOnload()); } if (aProgress & FLAG_DECODE_COMPLETE) { MOZ_ASSERT(aHasImage, "Stopped decoding without ever having an image?"); - NOTIFY_IMAGE_OBSERVERS(aProxies, OnDecodeComplete()); + NOTIFY_IMAGE_OBSERVERS(aObservers, Notify(I::DECODE_COMPLETE)); } if (aProgress & FLAG_LOAD_COMPLETE) { - NOTIFY_IMAGE_OBSERVERS(aProxies, + NOTIFY_IMAGE_OBSERVERS(aObservers, OnLoadComplete(aProgress & FLAG_LAST_PART_COMPLETE)); } } @@ -372,7 +352,7 @@ const nsIntRect& aInvalidRect /* = nsIntRect() */) { - MOZ_ASSERT(NS_IsMainThread(), "Use mConsumers on main thread only"); + MOZ_ASSERT(NS_IsMainThread(), "Use mObservers on main thread only"); // Don't unblock onload if we're not blocked. Progress progress = Difference(aProgress); @@ -386,7 +366,7 @@ CheckProgressConsistency(mProgress); // Send notifications. - SyncNotifyInternal(mConsumers, !!mImage, progress, aInvalidRect); + SyncNotifyInternal(mObservers, !!mImage, progress, aInvalidRect); if (progress & FLAG_HAS_ERROR) { FireFailureNotification(); @@ -394,90 +374,92 @@ } void -ProgressTracker::SyncNotify(imgRequestProxy* proxy) +ProgressTracker::SyncNotify(IProgressObserver* aObserver) { - MOZ_ASSERT(NS_IsMainThread(), "imgRequestProxy is not threadsafe"); + MOZ_ASSERT(NS_IsMainThread()); + #ifdef PR_LOGGING - nsRefPtr uri; - proxy->GetURI(getter_AddRefs(uri)); nsAutoCString spec; - uri->GetSpec(spec); + if (mImage && mImage->GetURI()) { + mImage->GetURI()->GetSpec(spec); + } LOG_SCOPE_WITH_PARAM(GetImgLog(), "ProgressTracker::SyncNotify", "uri", spec.get()); #endif - nsIntRect r; + nsIntRect rect; if (mImage) { - // XXX - Should only send partial rects here, but that needs to - // wait until we fix up the observer interface - r = mImage->FrameRect(imgIContainer::FRAME_CURRENT); + if (NS_FAILED(mImage->GetWidth(&rect.width)) || + NS_FAILED(mImage->GetHeight(&rect.height))) { + // Either the image has no intrinsic size, or it has an error. + rect = nsIntRect::GetMaxSizedIntRect(); + } } - ProxyArray array; - array.AppendElement(proxy); - SyncNotifyInternal(array, !!mImage, mProgress, r); + ObserverArray array; + array.AppendElement(aObserver); + SyncNotifyInternal(array, !!mImage, mProgress, rect); } void -ProgressTracker::EmulateRequestFinished(imgRequestProxy* aProxy, - nsresult aStatus) +ProgressTracker::EmulateRequestFinished(IProgressObserver* aObserver) { MOZ_ASSERT(NS_IsMainThread(), - "SyncNotifyState and mConsumers are not threadsafe"); - nsCOMPtr kungFuDeathGrip(aProxy); + "SyncNotifyState and mObservers are not threadsafe"); + nsRefPtr kungFuDeathGrip(aObserver); if (mProgress & FLAG_ONLOAD_BLOCKED && !(mProgress & FLAG_ONLOAD_UNBLOCKED)) { - aProxy->UnblockOnload(); + aObserver->UnblockOnload(); } if (!(mProgress & FLAG_LOAD_COMPLETE)) { - aProxy->OnLoadComplete(true); + aObserver->OnLoadComplete(true); } } void -ProgressTracker::AddConsumer(imgRequestProxy* aConsumer) +ProgressTracker::AddObserver(IProgressObserver* aObserver) { MOZ_ASSERT(NS_IsMainThread()); - mConsumers.AppendElementUnlessExists(aConsumer); + mObservers.AppendElementUnlessExists(aObserver); } -// XXX - The last argument should go away. bool -ProgressTracker::RemoveConsumer(imgRequestProxy* aConsumer, nsresult aStatus) +ProgressTracker::RemoveObserver(IProgressObserver* aObserver) { MOZ_ASSERT(NS_IsMainThread()); - // Remove the proxy from the list. - bool removed = mConsumers.RemoveElement(aConsumer); - // Consumers can get confused if they don't get all the proper teardown + // Remove the observer from the list. + bool removed = mObservers.RemoveElement(aObserver); + + // Observers can get confused if they don't get all the proper teardown // notifications. Part ways on good terms. - if (removed && !aConsumer->NotificationsDeferred()) { - EmulateRequestFinished(aConsumer, aStatus); + if (removed && !aObserver->NotificationsDeferred()) { + EmulateRequestFinished(aObserver); } - // Make sure we don't give callbacks to a consumer that isn't interested in + // Make sure we don't give callbacks to an observer that isn't interested in // them any more. AsyncNotifyRunnable* runnable = static_cast(mRunnable.get()); - if (aConsumer->NotificationsDeferred() && runnable) { - runnable->RemoveProxy(aConsumer); - aConsumer->SetNotificationsDeferred(false); + if (aObserver->NotificationsDeferred() && runnable) { + runnable->RemoveObserver(aObserver); + aObserver->SetNotificationsDeferred(false); } return removed; } bool -ProgressTracker::FirstConsumerIs(imgRequestProxy* aConsumer) +ProgressTracker::FirstObserverIs(IProgressObserver* aObserver) { - MOZ_ASSERT(NS_IsMainThread(), "Use mConsumers on main thread only"); - ProxyArray::ForwardIterator iter(mConsumers); + MOZ_ASSERT(NS_IsMainThread(), "Use mObservers on main thread only"); + ObserverArray::ForwardIterator iter(mObservers); while (iter.HasMore()) { - nsRefPtr proxy = iter.GetNext().get(); - if (proxy) { - return proxy.get() == aConsumer; + nsRefPtr observer = iter.GetNext().get(); + if (observer) { + return observer.get() == aObserver; } } return false; @@ -487,19 +469,15 @@ ProgressTracker::OnUnlockedDraw() { MOZ_ASSERT(NS_IsMainThread()); - NOTIFY_IMAGE_OBSERVERS(mConsumers, OnUnlockedDraw()); + NOTIFY_IMAGE_OBSERVERS(mObservers, + Notify(imgINotificationObserver::UNLOCKED_DRAW)); } void ProgressTracker::ResetForNewRequest() { MOZ_ASSERT(NS_IsMainThread()); - - // We're starting a new load (and if this is called more than once, this is a - // multipart request) so keep only the bits that carry over between loads. - mProgress &= FLAG_IS_MULTIPART | FLAG_HAS_ERROR | - FLAG_ONLOAD_BLOCKED | FLAG_ONLOAD_UNBLOCKED; - + mProgress = NoProgress; CheckProgressConsistency(mProgress); } @@ -507,7 +485,8 @@ ProgressTracker::OnDiscard() { MOZ_ASSERT(NS_IsMainThread()); - NOTIFY_IMAGE_OBSERVERS(mConsumers, OnDiscard()); + NOTIFY_IMAGE_OBSERVERS(mObservers, + Notify(imgINotificationObserver::DISCARD)); } void @@ -522,7 +501,7 @@ return; } - NOTIFY_IMAGE_OBSERVERS(mConsumers, SetHasImage()); + NOTIFY_IMAGE_OBSERVERS(mObservers, SetHasImage()); } void diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/ProgressTracker.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/ProgressTracker.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/ProgressTracker.h 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/ProgressTracker.h 2015-01-09 12:36:28.000000000 +0000 @@ -13,7 +13,7 @@ #include "nsTObserverArray.h" #include "nsThreadUtils.h" #include "nsRect.h" -#include "imgRequestProxy.h" +#include "IProgressObserver.h" class imgIContainer; class nsIRunnable; @@ -36,9 +36,8 @@ FLAG_ONLOAD_UNBLOCKED = 1u << 6, FLAG_IS_ANIMATED = 1u << 7, // STATUS_IS_ANIMATED FLAG_HAS_TRANSPARENCY = 1u << 8, // STATUS_HAS_TRANSPARENCY - FLAG_IS_MULTIPART = 1u << 9, - FLAG_LAST_PART_COMPLETE = 1u << 10, - FLAG_HAS_ERROR = 1u << 11 // STATUS_ERROR + FLAG_LAST_PART_COMPLETE = 1u << 9, + FLAG_HAS_ERROR = 1u << 10 // STATUS_ERROR }; typedef uint32_t Progress; @@ -62,11 +61,12 @@ /** * ProgressTracker is a class that records an Image's progress through the * loading and decoding process, and makes it possible to send notifications to - * imgRequestProxys, both synchronously and asynchronously. + * IProgressObservers, both synchronously and asynchronously. * - * When a new proxy needs to be notified of the current progress of an image, - * call the Notify() method on this class with the relevant proxy as its - * argument, and the notifications will be replayed to the proxy asynchronously. + * When a new observer needs to be notified of the current progress of an image, + * call the Notify() method on this class with the relevant observer as its + * argument, and the notifications will be replayed to the observer + * asynchronously. */ class ProgressTracker : public mozilla::SupportsWeakPtr { @@ -76,11 +76,8 @@ MOZ_DECLARE_REFCOUNTED_TYPENAME(ProgressTracker) NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ProgressTracker) - // aImage is the image that will be passed to the observers in SyncNotify() - // and EmulateRequestFinished(), and must be alive as long as this instance - // is, because we hold a weak reference to it. - explicit ProgressTracker(Image* aImage) - : mImage(aImage) + ProgressTracker() + : mImage(nullptr) , mProgress(NoProgress) { } @@ -91,9 +88,6 @@ return image.forget(); } - // Informs this ProgressTracker that it's associated with a multipart image. - void SetIsMultipart(); - // Returns whether we are in the process of loading; that is, whether we have // not received OnStopRequest from Necko. bool IsLoading() const; @@ -107,28 +101,28 @@ // Schedule an asynchronous "replaying" of all the notifications that would // have to happen to put us in the current state. // We will also take note of any notifications that happen between the time - // Notify() is called and when we call SyncNotify on |proxy|, and replay them - // as well. - // Should be called on the main thread only, since imgRequestProxy and GetURI - // are not threadsafe. - void Notify(imgRequestProxy* proxy); + // Notify() is called and when we call SyncNotify on |aObserver|, and replay + // them as well. + // Should be called on the main thread only, since observers and GetURI are + // not threadsafe. + void Notify(IProgressObserver* aObserver); // Schedule an asynchronous "replaying" of all the notifications that would // have to happen to put us in the state we are in right now. // Unlike Notify(), does *not* take into account future notifications. // This is only useful if you do not have an imgRequest, e.g., if you are a // static request returned from imgIRequest::GetStaticRequest(). - // Should be called on the main thread only, since imgRequestProxy and GetURI - // are not threadsafe. - void NotifyCurrentState(imgRequestProxy* proxy); + // Should be called on the main thread only, since observers and GetURI are + // not threadsafe. + void NotifyCurrentState(IProgressObserver* aObserver); // "Replay" all of the notifications that would have to happen to put us in // the state we're currently in. // Only use this if you're already servicing an asynchronous call (e.g. // OnStartRequest). - // Should be called on the main thread only, since imgRequestProxy and GetURI - // are not threadsafe. - void SyncNotify(imgRequestProxy* proxy); + // Should be called on the main thread only, since observers and GetURI are + // not threadsafe. + void SyncNotify(IProgressObserver* aObserver); // Get this ProgressTracker ready for a new request. This resets all the // state that doesn't persist between requests. @@ -155,28 +149,22 @@ void SyncNotifyProgress(Progress aProgress, const nsIntRect& aInvalidRect = nsIntRect()); - // We manage a set of consumers that are using an image and thus concerned + // We manage a set of observers that are using an image and thus concerned // with its loading progress. Weak pointers. - void AddConsumer(imgRequestProxy* aConsumer); - bool RemoveConsumer(imgRequestProxy* aConsumer, nsresult aStatus); - size_t ConsumerCount() const { - MOZ_ASSERT(NS_IsMainThread(), "Use mConsumers on main thread only"); - return mConsumers.Length(); + void AddObserver(IProgressObserver* aObserver); + bool RemoveObserver(IProgressObserver* aObserver); + size_t ObserverCount() const { + MOZ_ASSERT(NS_IsMainThread(), "Use mObservers on main thread only"); + return mObservers.Length(); } // This is intentionally non-general because its sole purpose is to support // some obscure network priority logic in imgRequest. That stuff could // probably be improved, but it's too scary to mess with at the moment. - bool FirstConsumerIs(imgRequestProxy* aConsumer); - - void AdoptConsumers(ProgressTracker* aTracker) { - MOZ_ASSERT(NS_IsMainThread(), "Use mConsumers on main thread only"); - MOZ_ASSERT(aTracker); - mConsumers = aTracker->mConsumers; - } + bool FirstObserverIs(IProgressObserver* aObserver); private: - typedef nsTObserverArray> ProxyArray; + typedef nsTObserverArray> ObserverArray; friend class AsyncNotifyRunnable; friend class AsyncNotifyCurrentStateRunnable; friend class ProgressTrackerInit; @@ -191,17 +179,17 @@ // of scope. ProgressTrackerInit automates this. void ResetImage(); - // Send some notifications that would be necessary to make |aProxy| believe + // Send some notifications that would be necessary to make |aObserver| believe // the request is finished downloading and decoding. We only send - // FLAG_REQUEST_* and FLAG_ONLOAD_UNBLOCKED, and only if necessary. - void EmulateRequestFinished(imgRequestProxy* aProxy, nsresult aStatus); + // FLAG_LOAD_COMPLETE and FLAG_ONLOAD_UNBLOCKED, and only if necessary. + void EmulateRequestFinished(IProgressObserver* aObserver); // Main thread only because it deals with the observer service. void FireFailureNotification(); - // Main thread only, since imgRequestProxy calls are expected on the main - // thread, and mConsumers is not threadsafe. - static void SyncNotifyInternal(ProxyArray& aProxies, + // Main thread only, since notifications are expected on the main thread, and + // mObservers is not threadsafe. + static void SyncNotifyInternal(ObserverArray& aObservers, bool aHasImage, Progress aProgress, const nsIntRect& aInvalidRect); @@ -210,10 +198,10 @@ // This weak ref should be set null when the image goes out of scope. Image* mImage; - // List of proxies attached to the image. Each proxy represents a consumer - // using the image. Array and/or individual elements should only be accessed - // on the main thread. - ProxyArray mConsumers; + // List of observers attached to the image. Each observer represents a + // consumer using the image. Array and/or individual elements should only be + // accessed on the main thread. + ObserverArray mObservers; Progress mProgress; }; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/RasterImage.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/RasterImage.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/RasterImage.cpp 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/RasterImage.cpp 2015-01-09 12:36:28.000000000 +0000 @@ -129,13 +129,6 @@ } \ PR_END_MACRO - - -static int num_containers; -static int num_discardable_containers; -static int64_t total_source_bytes; -static int64_t discardable_source_bytes; - class ScaleRunner : public nsRunnable { enum ScaleState @@ -189,7 +182,7 @@ // Insert the new surface into the cache immediately. We need to do this so // that we won't start multiple scaling jobs for the same size. SurfaceCache::Insert(mDstRef.get(), ImageKey(mImage.get()), - RasterSurfaceKey(mDstSize.ToIntSize(), mImageFlags), + RasterSurfaceKey(mDstSize.ToIntSize(), mImageFlags, 0), Lifetime::Transient); return true; @@ -199,18 +192,14 @@ { if (mState == eReady) { // Collect information from the frames that we need to scale. - uint8_t* srcData = mSrcRef->GetImageData(); - IntSize srcSize = mSrcRef->GetSize(); - uint32_t srcStride = mSrcRef->GetImageBytesPerRow(); - uint8_t* dstData = mDstRef->GetImageData(); - uint32_t dstStride = mDstRef->GetImageBytesPerRow(); - SurfaceFormat srcFormat = mSrcRef->GetFormat(); + ScalingData srcData = mSrcRef->GetScalingData(); + ScalingData dstData = mDstRef->GetScalingData(); // Actually do the scaling. bool succeeded = - gfx::Scale(srcData, srcSize.width, srcSize.height, srcStride, - dstData, mDstSize.width, mDstSize.height, dstStride, - srcFormat); + gfx::Scale(srcData.mRawData, srcData.mSize.width, srcData.mSize.height, + srcData.mBytesPerRow, dstData.mRawData, mDstSize.width, + mDstSize.height, dstData.mBytesPerRow, srcData.mFormat); if (succeeded) { // Mark the frame as complete and discardable. @@ -243,7 +232,7 @@ // Remove the frame from the cache since we know we don't need it. SurfaceCache::RemoveSurface(ImageKey(mImage.get()), RasterSurfaceKey(mDstSize.ToIntSize(), - mImageFlags)); + mImageFlags, 0)); // Release everything we're holding, too. mSrcRef.reset(); @@ -295,15 +284,15 @@ mDecodingMonitor("RasterImage Decoding Monitor"), mDecoder(nullptr), mDecodeStatus(DecodeStatus::INACTIVE), + mFrameCount(0), mNotifyProgress(NoProgress), mNotifying(false), mHasSize(false), mDecodeOnDraw(false), - mMultipart(false), + mTransient(false), mDiscardable(false), mHasSourceData(false), mDecoded(false), - mHasFirstFrame(false), mHasBeenDecoded(false), mPendingAnimation(false), mAnimationFinished(false), @@ -313,30 +302,11 @@ mProgressTrackerInit = new ProgressTrackerInit(this, aProgressTracker); Telemetry::GetHistogramById(Telemetry::IMAGE_DECODE_COUNT)->Add(0); - - // Statistics - num_containers++; } //****************************************************************************** RasterImage::~RasterImage() { - // Discardable statistics - if (mDiscardable) { - num_discardable_containers--; - discardable_source_bytes -= mSourceData.Length(); - - PR_LOG (GetCompressedImageAccountingLog(), PR_LOG_DEBUG, - ("CompressedImageAccounting: destroying RasterImage %p. " - "Total Containers: %d, Discardable containers: %d, " - "Total source bytes: %lld, Source bytes for discardable containers %lld", - this, - num_containers, - num_discardable_containers, - total_source_bytes, - discardable_source_bytes)); - } - if (mDecoder) { // Kill off our decode request, if it's pending. (If not, this call is // harmless.) @@ -349,10 +319,6 @@ SurfaceCache::RemoveImage(ImageKey(this)); mAnim = nullptr; - - // Total statistics - num_containers--; - total_source_bytes -= mSourceData.Length(); } /* static */ void @@ -378,23 +344,17 @@ NS_ENSURE_ARG_POINTER(aMimeType); // We must be non-discardable and non-decode-on-draw for - // multipart channels - NS_ABORT_IF_FALSE(!(aFlags & INIT_FLAG_MULTIPART) || - (!(aFlags & INIT_FLAG_DISCARDABLE) && - !(aFlags & INIT_FLAG_DECODE_ON_DRAW)), - "Can't be discardable or decode-on-draw for multipart"); + // transient images. + MOZ_ASSERT(!(aFlags & INIT_FLAG_TRANSIENT) || + (!(aFlags & INIT_FLAG_DISCARDABLE) && + !(aFlags & INIT_FLAG_DECODE_ON_DRAW)), + "Transient images can't be discardable or decode-on-draw"); // Store initialization data mSourceDataMimeType.Assign(aMimeType); mDiscardable = !!(aFlags & INIT_FLAG_DISCARDABLE); mDecodeOnDraw = !!(aFlags & INIT_FLAG_DECODE_ON_DRAW); - mMultipart = !!(aFlags & INIT_FLAG_MULTIPART); - - // Statistics - if (mDiscardable) { - num_discardable_containers++; - discardable_source_bytes += mSourceData.Length(); - } + mTransient = !!(aFlags & INIT_FLAG_TRANSIENT); // Lock this image's surfaces in the SurfaceCache if we're not discardable. if (!mDiscardable) { @@ -545,18 +505,22 @@ const nsIntSize& aSize, uint32_t aFlags) { - if (mAnim) { - MOZ_ASSERT(mFrameBlender, "mAnim but no mFrameBlender?"); - nsRefPtr frame = mFrameBlender->GetFrame(aFrameNum); - return frame->DrawableRef(); + if (!mAnim) { + NS_ASSERTION(aFrameNum == 0, + "Don't ask for a frame > 0 if we're not animated!"); + aFrameNum = 0; } - NS_ASSERTION(aFrameNum == 0, - "Don't ask for a frame > 0 if we're not animated!"); + if (mAnim && aFrameNum > 0) { + MOZ_ASSERT(DecodeFlags(aFlags) == DECODE_FLAGS_DEFAULT, + "Can't composite frames with non-default decode flags"); + return mAnim->GetCompositedFrame(aFrameNum); + } return SurfaceCache::Lookup(ImageKey(this), RasterSurfaceKey(aSize.ToIntSize(), - DecodeFlags(aFlags))); + DecodeFlags(aFlags), + aFrameNum)); } DrawableFrameRef @@ -567,18 +531,9 @@ { MOZ_ASSERT(NS_IsMainThread()); - if (mMultipart && - aFrameNum == GetCurrentFrameIndex() && - mMultipartDecodedFrame) { - // In the multipart case we prefer to use mMultipartDecodedFrame, which is - // the most recent one we completely decoded, rather than display the real - // current frame and risk severe tearing. - return mMultipartDecodedFrame->DrawableRef(); - } - DrawableFrameRef ref = LookupFrameInternal(aFrameNum, aSize, aFlags); - if (!ref && IsOpaque()) { + if (!ref && IsOpaque() && aFrameNum == 0) { // We can use non-premultiplied alpha frames when premultipled alpha is // requested, or vice versa, if this image is opaque. Try again with the bit // toggled. @@ -593,7 +548,7 @@ // Update our state so the decoder knows what to do. mFrameDecodeFlags = aFlags & DECODE_FLAGS_MASK; mDecoded = false; - mHasFirstFrame = false; + mFrameCount = 0; WantDecodedFrames(aFlags, aShouldSyncNotify); // See if we managed to redecode enough to get the frame we want. @@ -605,12 +560,12 @@ } } - // We will return a paletted frame if it's not marked as compositing failed - // so we can catch crashes for reasons we haven't investigated. if (ref->GetCompositingFailed()) { return DrawableFrameRef(); } + MOZ_ASSERT(!ref || !ref->GetIsPaletted(), "Should not have paletted frame"); + return ref; } @@ -659,55 +614,19 @@ return !(progress & FLAG_HAS_TRANSPARENCY); } -nsIntRect -RasterImage::FrameRect(uint32_t aWhichFrame) -{ - if (aWhichFrame > FRAME_MAX_VALUE) { - NS_WARNING("aWhichFrame outside valid range!"); - return nsIntRect(); - } - - if (!mHasFirstFrame) { - return nsIntRect(); - } - - if (GetNumFrames() == 1) { - return nsIntRect(0, 0, mSize.width, mSize.height); - } - - // We must be animated, so get the requested frame from our FrameBlender. - MOZ_ASSERT(mFrameBlender, "We should be animated here"); - nsRefPtr frame = - mFrameBlender->RawGetFrame(GetRequestedFrameIndex(aWhichFrame)); - - // If we have the frame, use that rectangle. - if (frame) { - return frame->GetRect(); - } - - // If the frame doesn't exist, we return the empty rectangle. It's not clear - // whether this is appropriate in general, but at the moment the only - // consumer of this method is ProgressTracker (when it wants to figure out - // dirty rectangles to send out batched observer updates). This should - // probably be revisited when we fix bug 503973. - return nsIntRect(); -} - void RasterImage::OnSurfaceDiscarded() { - if (mProgressTracker) { - mProgressTracker->OnDiscard(); + if (!NS_IsMainThread()) { + nsCOMPtr runnable = + NS_NewRunnableMethod(this, &RasterImage::OnSurfaceDiscarded); + NS_DispatchToMainThread(runnable); + return; } -} -uint32_t -RasterImage::GetNumFrames() const -{ - if (mFrameBlender) { - return mFrameBlender->GetNumFrames(); + if (mProgressTracker) { + mProgressTracker->OnDiscard(); } - return mHasFirstFrame ? 1 : 0; } //****************************************************************************** @@ -749,8 +668,8 @@ if (NS_FAILED(GetAnimated(&animated)) || !animated) return -1; - MOZ_ASSERT(mFrameBlender, "Animated images should have a FrameBlender"); - return mFrameBlender->GetTimeoutForFrame(0); + MOZ_ASSERT(mAnim, "Animated images should have a FrameAnimator"); + return mAnim->GetTimeoutForFrame(0); } TemporaryRef @@ -972,72 +891,58 @@ { size_t n = 0; n += SurfaceCache::SizeOfSurfaces(ImageKey(this), aLocation, aMallocSizeOf); - if (mFrameBlender) { - n += mFrameBlender->SizeOfDecoded(aLocation, aMallocSizeOf); + if (mAnim) { + n += mAnim->SizeOfCompositingFrames(aLocation, aMallocSizeOf); } return n; } -RawAccessFrameRef -RasterImage::InternalAddFrame(uint32_t aFrameNum, - const nsIntRect& aFrameRect, - uint32_t aDecodeFlags, - SurfaceFormat aFormat, - uint8_t aPaletteDepth, - imgFrame* aPreviousFrame) +class OnAddedFrameRunnable : public nsRunnable { - // We assume that we're in the middle of decoding because we unlock the - // previous frame when we create a new frame, and only when decoding do we - // lock frames. - MOZ_ASSERT(mDecoder, "Only decoders may add frames!"); - - MOZ_ASSERT(aFrameNum <= GetNumFrames(), "Invalid frame index!"); - if (aFrameNum > GetNumFrames()) { - return RawAccessFrameRef(); +public: + OnAddedFrameRunnable(RasterImage* aImage, + uint32_t aNewFrameCount, + const nsIntRect& aNewRefreshArea) + : mImage(aImage) + , mNewFrameCount(aNewFrameCount) + , mNewRefreshArea(aNewRefreshArea) + { + MOZ_ASSERT(aImage); } - if (mSize.width <= 0 || mSize.height <= 0) { - NS_WARNING("Trying to add frame with zero or negative size"); - return RawAccessFrameRef(); + NS_IMETHOD Run() + { + mImage->OnAddedFrame(mNewFrameCount, mNewRefreshArea); + return NS_OK; } - if (!SurfaceCache::CanHold(mSize.ToIntSize())) { - NS_WARNING("Trying to add frame that's too large for the SurfaceCache"); - return RawAccessFrameRef(); - } +private: + nsRefPtr mImage; + uint32_t mNewFrameCount; + nsIntRect mNewRefreshArea; +}; - nsRefPtr frame = new imgFrame(); - if (NS_FAILED(frame->InitForDecoder(mSize, aFrameRect, aFormat, - aPaletteDepth))) { - NS_WARNING("imgFrame::Init should succeed"); - return RawAccessFrameRef(); +void +RasterImage::OnAddedFrame(uint32_t aNewFrameCount, + const nsIntRect& aNewRefreshArea) +{ + if (!NS_IsMainThread()) { + nsCOMPtr runnable = + new OnAddedFrameRunnable(this, aNewFrameCount, aNewRefreshArea); + NS_DispatchToMainThread(runnable); + return; } - frame->SetAsNonPremult(aDecodeFlags & FLAG_DECODE_NO_PREMULTIPLY_ALPHA); - RawAccessFrameRef ref = frame->RawAccessRef(); - if (!ref) { - return RawAccessFrameRef(); - } + MOZ_ASSERT((mFrameCount == 1 && aNewFrameCount == 1) || + mFrameCount < aNewFrameCount, + "Frame count running backwards"); - if (GetNumFrames() == 0) { - bool succeeded = - SurfaceCache::Insert(frame, ImageKey(this), - RasterSurfaceKey(mSize.ToIntSize(), aDecodeFlags), - Lifetime::Persistent); - if (!succeeded) { - return RawAccessFrameRef(); - } - mHasFirstFrame = true; - return ref; - } + mFrameCount = aNewFrameCount; - if (GetNumFrames() == 1) { + if (aNewFrameCount == 2) { // We're becoming animated, so initialize animation stuff. - MOZ_ASSERT(!mFrameBlender, "Already have a FrameBlender?"); MOZ_ASSERT(!mAnim, "Already have animation state?"); - mFrameBlender.emplace(); - mFrameBlender->SetSize(mSize); - mAnim = MakeUnique(*mFrameBlender, mAnimationMode); + mAnim = MakeUnique(this, mSize.ToIntSize(), mAnimationMode); // We don't support discarding animated images (See bug 414259). // Lock the image and throw away the key. @@ -1049,43 +954,14 @@ // in the old world either, locking is acceptable for the moment. LockImage(); - // Insert the first frame into the FrameBlender. - MOZ_ASSERT(aPreviousFrame, "Must provide a previous frame when animated"); - RawAccessFrameRef ref = aPreviousFrame->RawAccessRef(); - if (!ref) { - return RawAccessFrameRef(); // Let's keep the FrameBlender consistent... - } - mFrameBlender->InsertFrame(0, Move(ref)); - - // Remove it from the SurfaceCache. (It's not really doing any harm there, - // but keeping it there could cause it to be counted twice in our memory - // statistics.) - SurfaceCache::RemoveSurface(ImageKey(this), - RasterSurfaceKey(mSize.ToIntSize(), - aDecodeFlags)); - - // If we dispose of the first frame by clearing it, then the first frame's - // refresh area is all of itself. - // RESTORE_PREVIOUS is invalid (assumed to be DISPOSE_CLEAR). - int32_t frameDisposalMethod = aPreviousFrame->GetFrameDisposalMethod(); - if (frameDisposalMethod == FrameBlender::kDisposeClear || - frameDisposalMethod == FrameBlender::kDisposeRestorePrevious) { - mAnim->SetFirstFrameRefreshArea(aPreviousFrame->GetRect()); - } - if (mPendingAnimation && ShouldAnimate()) { StartAnimation(); } } - // Some GIFs are huge but only have a small area that they animate. We only - // need to refresh that small area when frame 0 comes around again. - mAnim->UnionFirstFrameRefreshArea(frame->GetRect()); - - MOZ_ASSERT(mFrameBlender, "Should have a FrameBlender by now"); - mFrameBlender->InsertFrame(aFrameNum, frame->RawAccessRef()); - - return ref; + if (aNewFrameCount > 1) { + mAnim->UnionFirstFrameRefreshArea(aNewRefreshArea); + } } nsresult @@ -1103,7 +979,7 @@ return NS_ERROR_INVALID_ARG; // if we already have a size, check the new size against the old one - if (!mMultipart && mHasSize && + if (mHasSize && ((aWidth != mSize.width) || (aHeight != mSize.height) || (aOrientation != mOrientation))) { @@ -1126,59 +1002,6 @@ return NS_OK; } -RawAccessFrameRef -RasterImage::EnsureFrame(uint32_t aFrameNum, - const nsIntRect& aFrameRect, - uint32_t aDecodeFlags, - SurfaceFormat aFormat, - uint8_t aPaletteDepth, - imgFrame* aPreviousFrame) -{ - if (mError) { - return RawAccessFrameRef(); - } - - MOZ_ASSERT(aFrameNum <= GetNumFrames(), "Invalid frame index!"); - if (aFrameNum > GetNumFrames()) { - return RawAccessFrameRef(); - } - - // Adding a frame that doesn't already exist. This is the normal case. - if (aFrameNum == GetNumFrames()) { - return InternalAddFrame(aFrameNum, aFrameRect, aDecodeFlags, aFormat, - aPaletteDepth, aPreviousFrame); - } - - // We're replacing a frame. It must be the first frame; there's no reason to - // ever replace any other frame, since the first frame is the only one we - // speculatively allocate without knowing what the decoder really needs. - // XXX(seth): I'm not convinced there's any reason to support this at all. We - // should figure out how to avoid triggering this and rip it out. - MOZ_ASSERT(mHasFirstFrame, "Should have the first frame"); - MOZ_ASSERT(aFrameNum == 0, "Replacing a frame other than the first?"); - MOZ_ASSERT(GetNumFrames() == 1, "Should have only one frame"); - MOZ_ASSERT(aPreviousFrame, "Need the previous frame to replace"); - MOZ_ASSERT(!mFrameBlender && !mAnim, "Shouldn't be animated"); - if (aFrameNum != 0 || !aPreviousFrame || GetNumFrames() != 1) { - return RawAccessFrameRef(); - } - - MOZ_ASSERT(!aPreviousFrame->GetRect().IsEqualEdges(aFrameRect) || - aPreviousFrame->GetFormat() != aFormat || - aPreviousFrame->GetPaletteDepth() != aPaletteDepth, - "Replacing first frame with the same kind of frame?"); - - // Remove the old frame from the SurfaceCache. - IntSize prevFrameSize = aPreviousFrame->GetImageSize(); - SurfaceCache::RemoveSurface(ImageKey(this), - RasterSurfaceKey(prevFrameSize, aDecodeFlags)); - mHasFirstFrame = false; - - // Add the new frame as usual. - return InternalAddFrame(aFrameNum, aFrameRect, aDecodeFlags, aFormat, - aPaletteDepth, nullptr); -} - void RasterImage::DecodingComplete(imgFrame* aFinalFrame) { @@ -1194,32 +1017,12 @@ mDecoded = true; mHasBeenDecoded = true; - bool singleFrame = GetNumFrames() == 1; - // If there's only 1 frame, mark it as optimizable. Optimizing animated images - // is not supported. - // - // We don't optimize the frame for multipart images because we reuse - // the frame. - if (singleFrame && !mMultipart && aFinalFrame) { + // is not supported. Optimizing transient images isn't worth it. + if (GetNumFrames() == 1 && !mTransient && aFinalFrame) { aFinalFrame->SetOptimizable(); } - // Double-buffer our frame in the multipart case, since we'll start decoding - // into the first frame again immediately and this produces severe tearing. - if (mMultipart) { - if (singleFrame && aFinalFrame) { - // aFinalFrame must be the first frame since we only have one. - mMultipartDecodedFrame = aFinalFrame->DrawableRef(); - } else { - // Don't double buffer for animated multipart images. It entails more - // complexity and it's not really needed since we already are smart about - // not displaying the still-decoding frame of an animated image. We may - // have already stored an extra frame, though, so we'll release it here. - mMultipartDecodedFrame.reset(); - } - } - if (mAnim) { mAnim->SetDoneDecoding(true); } @@ -1253,17 +1056,14 @@ } // A timeout of -1 means we should display this frame forever. - MOZ_ASSERT(mFrameBlender, "Have an animation but no FrameBlender?"); - if (mFrameBlender->GetTimeoutForFrame(GetCurrentFrameIndex()) < 0) { + if (mAnim->GetTimeoutForFrame(GetCurrentFrameIndex()) < 0) { mAnimationFinished = true; return NS_ERROR_ABORT; } - if (mAnim) { - // We need to set the time that this initial frame was first displayed, as - // this is used in AdvanceFrame(). - mAnim->InitAnimationFrameTimeIfNecessary(); - } + // We need to set the time that this initial frame was first displayed, as + // this is used in AdvanceFrame(). + mAnim->InitAnimationFrameTimeIfNecessary(); return NS_OK; } @@ -1306,8 +1106,7 @@ if (mAnimating) StopAnimation(); - MOZ_ASSERT(mFrameBlender, "Should have a FrameBlender"); - mFrameBlender->ResetAnimation(); + MOZ_ASSERT(mAnim, "Should have a FrameAnimator"); mAnim->ResetAnimation(); UpdateImageContainer(); @@ -1354,10 +1153,9 @@ if (mError) return; + // No need to set this if we're not an animation. if (mAnim) { - // No need to set this if we're not an animation - MOZ_ASSERT(mFrameBlender, "Should have a FrameBlender"); - mFrameBlender->SetLoopCount(aLoopCount); + mAnim->SetLoopCount(aLoopCount); } } @@ -1392,37 +1190,11 @@ return NS_OK; } - // Starting a new part's frames, let's clean up before we add any - // This needs to happen just before we start getting EnsureFrame() call(s), - // so that there's no gap for anything to miss us. - if (mMultipart && (!mDecoder || mDecoder->BytesDecoded() == 0)) { - // Our previous state may have been animated, so let's clean up. - if (mAnimating) { - StopAnimation(); - } - mAnimationFinished = false; - mPendingAnimation = false; - if (mAnim) { - mAnim = nullptr; - } - - // If we had a FrameBlender, clean it up. We'll hold on to the first frame - // so we have something to draw until the next frame is decoded. - if (mFrameBlender) { - nsRefPtr firstFrame = mFrameBlender->RawGetFrame(0); - mMultipartDecodedFrame = firstFrame->DrawableRef(); - mFrameBlender.reset(); - } - - // Remove everything stored in the surface cache for this image. - SurfaceCache::RemoveImage(ImageKey(this)); - } - // If we're not storing source data and we've previously gotten the size, // write the data directly to the decoder. (If we haven't gotten the size, // we'll queue up the data and write it out when we do.) if (!StoringSourceData() && mHasSize) { - rv = WriteToDecoder(aBuffer, aCount, DecodeStrategy::SYNC); + rv = WriteToDecoder(aBuffer, aCount); CONTAINER_ENSURE_SUCCESS(rv); rv = FinishedSomeDecoding(); @@ -1442,21 +1214,6 @@ } } - // Statistics - total_source_bytes += aCount; - if (mDiscardable) - discardable_source_bytes += aCount; - PR_LOG (GetCompressedImageAccountingLog(), PR_LOG_DEBUG, - ("CompressedImageAccounting: Added compressed data to RasterImage %p (%s). " - "Total Containers: %d, Discardable containers: %d, " - "Total source bytes: %lld, Source bytes for discardable containers %lld", - this, - mSourceDataMimeType.get(), - num_containers, - num_discardable_containers, - total_source_bytes, - discardable_source_bytes)); - return NS_OK; } @@ -1565,59 +1322,6 @@ return rv; } -nsresult -RasterImage::OnNewSourceData() -{ - MOZ_ASSERT(NS_IsMainThread()); - - nsresult rv; - - if (mError) - return NS_ERROR_FAILURE; - - // The source data should be complete before calling this - NS_ABORT_IF_FALSE(mHasSourceData, - "Calling NewSourceData before SourceDataComplete!"); - if (!mHasSourceData) - return NS_ERROR_ILLEGAL_VALUE; - - // Only supported for multipart channels. It wouldn't be too hard to change this, - // but it would involve making sure that things worked for decode-on-draw and - // discarding. Presently there's no need for this, so we don't. - NS_ABORT_IF_FALSE(mMultipart, "NewSourceData only supported for multipart"); - if (!mMultipart) - return NS_ERROR_ILLEGAL_VALUE; - - // We're multipart, so we shouldn't be storing source data - NS_ABORT_IF_FALSE(!StoringSourceData(), - "Shouldn't be storing source data for multipart"); - - // We're not storing the source data and we got SourceDataComplete. We should - // have shut down the previous decoder - NS_ABORT_IF_FALSE(!mDecoder, "Shouldn't have a decoder in NewSourceData"); - - // The decoder was shut down and we didn't flag an error, so we should be decoded - NS_ABORT_IF_FALSE(mDecoded, "Should be decoded in NewSourceData"); - - // Reset some flags - mDecoded = false; - mHasSourceData = false; - mHasSize = false; - mHasFirstFrame = false; - mWantFullDecode = true; - mDecodeStatus = DecodeStatus::INACTIVE; - - if (mAnim) { - mAnim->SetDoneDecoding(false); - } - - // We always need the size first. - rv = InitDecoder(/* aDoSizeDecode = */ true); - CONTAINER_ENSURE_SUCCESS(rv); - - return NS_OK; -} - /* static */ already_AddRefed RasterImage::GetEventTarget() { @@ -1695,19 +1399,12 @@ // timers are cancelled. NS_ABORT_IF_FALSE(!mAnim, "Asked to discard for animated image!"); - // For post-operation logging - int old_frame_count = GetNumFrames(); - - // Delete all the decoded frames - mFrameBlender.reset(); + // Delete all the decoded frames. SurfaceCache::RemoveImage(ImageKey(this)); - // Clear the last decoded multipart frame. - mMultipartDecodedFrame.reset(); - // Flag that we no longer have decoded frames for this image mDecoded = false; - mHasFirstFrame = false; + mFrameCount = 0; // Notify that we discarded if (mProgressTracker) { @@ -1715,21 +1412,6 @@ } mDecodeStatus = DecodeStatus::INACTIVE; - - // Log - PR_LOG(GetCompressedImageAccountingLog(), PR_LOG_DEBUG, - ("CompressedImageAccounting: discarded uncompressed image " - "data from RasterImage %p (%s) - %d frames (cached count: %d); " - "Total Containers: %d, Discardable containers: %d, " - "Total source bytes: %lld, Source bytes for discardable containers %lld", - this, - mSourceDataMimeType.get(), - old_frame_count, - GetNumFrames(), - num_containers, - num_discardable_containers, - total_source_bytes, - discardable_source_bytes)); } bool @@ -1743,7 +1425,7 @@ // or just writing it directly to the decoder bool RasterImage::StoringSourceData() const { - return !mMultipart; + return !mTransient; } @@ -1802,6 +1484,7 @@ // We already have the size; tell the decoder so it can preallocate a // frame. By default, we create an ARGB frame with no offset. If decoders // need a different type, they need to ask for it themselves. + mDecoder->SetSize(mSize, mOrientation); mDecoder->NeedNewFrame(0, 0, 0, mSize.width, mSize.height, SurfaceFormat::B8G8R8A8); mDecoder->AllocateFrame(); @@ -1886,7 +1569,7 @@ // Writes the data to the decoder, updating the total number of bytes written. nsresult -RasterImage::WriteToDecoder(const char *aBuffer, uint32_t aCount, DecodeStrategy aStrategy) +RasterImage::WriteToDecoder(const char *aBuffer, uint32_t aCount) { mDecodingMonitor.AssertCurrentThreadIn(); @@ -1895,7 +1578,7 @@ // Write nsRefPtr kungFuDeathGrip = mDecoder; - mDecoder->Write(aBuffer, aCount, aStrategy); + mDecoder->Write(aBuffer, aCount); CONTAINER_ENSURE_SUCCESS(mDecoder->GetDecoderError()); @@ -1965,11 +1648,6 @@ if (mDecoded) return NS_OK; - // If we're currently waiting for a new frame, we can't do anything until - // that frame is allocated. - if (mDecoder && mDecoder->NeedsNewFrame()) - return NS_OK; - // If we have a size decoder open, make sure we get the size if (mDecoder && mDecoder->IsSizeDecode()) { nsresult rv = DecodePool::Singleton()->DecodeUntilSizeAvailable(this); @@ -2069,7 +1747,7 @@ PROFILER_LABEL_PRINTF("RasterImage", "DecodeABitOf", js::ProfileEntry::Category::GRAPHICS, "%s", GetURIString().get()); - DecodePool::Singleton()->DecodeABitOf(this, DecodeStrategy::SYNC); + DecodePool::Singleton()->DecodeABitOf(this); return NS_OK; } @@ -2137,11 +1815,6 @@ } } - // If we're currently waiting on a new frame for this image, create it now. - if (mDecoder && mDecoder->NeedsNewFrame()) { - mDecoder->AllocateFrame(); - } - // If we don't have a decoder, create one if (!mDecoder) { rv = InitDecoder(/* aDoSizeDecode = */ false); @@ -2151,8 +1824,7 @@ MOZ_ASSERT(mDecoder); // Write everything we have - rv = DecodeSomeData(mSourceData.Length() - mDecoder->BytesDecoded(), - DecodeStrategy::SYNC); + rv = DecodeSomeData(mSourceData.Length() - mDecoder->BytesDecoded()); CONTAINER_ENSURE_SUCCESS(rv); rv = FinishedSomeDecoding(); @@ -2187,9 +1859,9 @@ return false; } - // We don't use the scaler for animated or multipart images to avoid doing a + // We don't use the scaler for animated or transient images to avoid doing a // bunch of work on an image that just gets thrown away. - if (mAnim || mMultipart) { + if (mAnim || mTransient) { return false; } @@ -2280,7 +1952,8 @@ frameRef = SurfaceCache::Lookup(ImageKey(this), RasterSurfaceKey(aSize.ToIntSize(), - DecodeFlags(aFlags))); + DecodeFlags(aFlags), + 0)); if (!frameRef) { // We either didn't have a matching scaled frame or the OS threw it away. // Request a new one so we'll be ready next time. For now, we'll fall back @@ -2425,7 +2098,7 @@ mLockCount--; // Unlock this image's surfaces in the SurfaceCache. - if (mLockCount == 0) { + if (mLockCount == 0 ) { SurfaceCache::UnlockImage(ImageKey(this)); } @@ -2462,22 +2135,12 @@ // Flushes up to aMaxBytes to the decoder. nsresult -RasterImage::DecodeSomeData(size_t aMaxBytes, DecodeStrategy aStrategy) +RasterImage::DecodeSomeData(size_t aMaxBytes) { MOZ_ASSERT(mDecoder, "Should have a decoder"); mDecodingMonitor.AssertCurrentThreadIn(); - // First, if we've just been called because we allocated a frame on the main - // thread, let the decoder deal with the data it set aside at that time by - // passing it a null buffer. - if (mDecoder->NeedsToFlushData()) { - nsresult rv = WriteToDecoder(nullptr, 0, aStrategy); - if (NS_FAILED(rv) || mDecoder->NeedsNewFrame()) { - return rv; - } - } - // If we have nothing else to decode, return. if (mDecoder->BytesDecoded() == mSourceData.Length()) { return NS_OK; @@ -2489,8 +2152,7 @@ size_t bytesToDecode = min(aMaxBytes, mSourceData.Length() - mDecoder->BytesDecoded()); return WriteToDecoder(mSourceData.Elements() + mDecoder->BytesDecoded(), - bytesToDecode, - aStrategy); + bytesToDecode); } @@ -2514,13 +2176,6 @@ return true; } - // If the decoder returned because it needed a new frame and we haven't - // written to it since then, the decoder may be storing data that it hasn't - // decoded yet. - if (mDecoder->NeedsNewFrame() || mDecoder->NeedsToFlushData()) { - return false; - } - // Otherwise, if we have all the source data and wrote all the source data, // we're done. // @@ -2809,7 +2464,8 @@ DrawableFrameRef frameRef = SurfaceCache::Lookup(ImageKey(this), RasterSurfaceKey(destSize.ToIntSize(), - DecodeFlags(aFlags))); + DecodeFlags(aFlags), + 0)); if (frameRef && frameRef->ImageComplete()) { return destSize; // We have an existing HQ scale for this size. diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/RasterImage.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/RasterImage.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/RasterImage.h 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/RasterImage.h 2015-01-09 12:36:28.000000000 +0000 @@ -18,7 +18,6 @@ #define mozilla_imagelib_RasterImage_h_ #include "Image.h" -#include "FrameBlender.h" #include "nsCOMPtr.h" #include "imgIContainer.h" #include "nsIProperties.h" @@ -159,7 +158,7 @@ // Methods inherited from Image nsresult Init(const char* aMimeType, uint32_t aFlags) MOZ_OVERRIDE; - virtual nsIntRect FrameRect(uint32_t aWhichFrame) MOZ_OVERRIDE; + virtual void OnSurfaceDiscarded() MOZ_OVERRIDE; // Raster-specific methods @@ -169,7 +168,7 @@ uint32_t* aWriteCount); /* The total number of frames in this image. */ - uint32_t GetNumFrames() const; + uint32_t GetNumFrames() const { return mFrameCount; } virtual size_t SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE; virtual size_t SizeOfDecoded(gfxMemoryLocation aLocation, @@ -178,7 +177,13 @@ /* Triggers discarding. */ void Discard(); - /* Callbacks for decoders */ + + ////////////////////////////////////////////////////////////////////////////// + // Decoder callbacks. + ////////////////////////////////////////////////////////////////////////////// + + void OnAddedFrame(uint32_t aNewFrameCount, const nsIntRect& aNewRefreshArea); + /** Sets the size and inherent orientation of the container. This should only * be called by the decoder. This function may be called multiple times, but * will throw an error if subsequent calls do not match the first. @@ -186,28 +191,18 @@ nsresult SetSize(int32_t aWidth, int32_t aHeight, Orientation aOrientation); /** - * Ensures that a given frame number exists with the given parameters, and - * returns a RawAccessFrameRef for that frame. - * It is not possible to create sparse frame arrays; you can only append - * frames to the current frame array, or if there is only one frame in the - * array, replace that frame. - * If a non-paletted frame is desired, pass 0 for aPaletteDepth. + * Number of times to loop the image. + * @note -1 means forever. */ - RawAccessFrameRef EnsureFrame(uint32_t aFrameNum, - const nsIntRect& aFrameRect, - uint32_t aDecodeFlags, - gfx::SurfaceFormat aFormat, - uint8_t aPaletteDepth, - imgFrame* aPreviousFrame); + void SetLoopCount(int32_t aLoopCount); /* notification that the entire image has been decoded */ void DecodingComplete(imgFrame* aFinalFrame); - /** - * Number of times to loop the image. - * @note -1 means forever. - */ - void SetLoopCount(int32_t aLoopCount); + + ////////////////////////////////////////////////////////////////////////////// + // Network callbacks. + ////////////////////////////////////////////////////////////////////////////// /* Add compressed source data to the imgContainer. * @@ -228,7 +223,6 @@ nsISupports* aContext, nsresult aStatus, bool aLastPart) MOZ_OVERRIDE; - virtual nsresult OnNewSourceData() MOZ_OVERRIDE; static already_AddRefed GetEventTarget(); @@ -310,12 +304,6 @@ size_t SizeOfDecodedWithComputedFallbackIfHeap(gfxMemoryLocation aLocation, MallocSizeOf aMallocSizeOf) const; - RawAccessFrameRef InternalAddFrame(uint32_t aFrameNum, - const nsIntRect& aFrameRect, - uint32_t aDecodeFlags, - gfx::SurfaceFormat aFormat, - uint8_t aPaletteDepth, - imgFrame* aPreviousFrame); nsresult DoImageDataComplete(); already_AddRefed GetCurrentImage(); @@ -348,14 +336,9 @@ // and imgIContainer::FLAG_DECODE_NO_COLORSPACE_CONVERSION. uint32_t mFrameDecodeFlags; - //! All the frames of the image. - Maybe mFrameBlender; - - //! The last frame we decoded for multipart images. - DrawableFrameRef mMultipartDecodedFrame; - nsCOMPtr mProperties; + //! All the frames of the image. // IMPORTANT: if you use mAnim in a method, call EnsureImageIsDecoded() first to ensure // that the frames actually exist (they may have been discarded to save memory, or // we maybe decoding on draw). @@ -400,6 +383,9 @@ DecodeStatus mDecodeStatus; // END LOCKED MEMBER VARIABLES + // The number of frames this image has. + uint32_t mFrameCount; + // Notification state. Used to avoid recursive notifications. Progress mNotifyProgress; nsIntRect mNotifyInvalidRect; @@ -408,13 +394,12 @@ // Boolean flags (clustered together to conserve space): bool mHasSize:1; // Has SetSize() been called? bool mDecodeOnDraw:1; // Decoding on draw? - bool mMultipart:1; // Multipart? + bool mTransient:1; // Is the image short-lived? bool mDiscardable:1; // Is container discardable? bool mHasSourceData:1; // Do we have source data? // Do we have the frames in decoded form? bool mDecoded:1; - bool mHasFirstFrame:1; bool mHasBeenDecoded:1; // Whether we're waiting to start animation. If we get a StartAnimation() call @@ -441,8 +426,8 @@ nsresult WantDecodedFrames(uint32_t aFlags, bool aShouldSyncNotify); nsresult SyncDecode(); nsresult InitDecoder(bool aDoSizeDecode); - nsresult WriteToDecoder(const char *aBuffer, uint32_t aCount, DecodeStrategy aStrategy); - nsresult DecodeSomeData(size_t aMaxBytes, DecodeStrategy aStrategy); + nsresult WriteToDecoder(const char *aBuffer, uint32_t aCount); + nsresult DecodeSomeData(size_t aMaxBytes); bool IsDecodeFinished(); TimeStamp mDrawStartTime; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/SurfaceCache.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/SurfaceCache.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/SurfaceCache.cpp 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/SurfaceCache.cpp 2015-01-09 12:36:28.000000000 +0000 @@ -15,6 +15,7 @@ #include "mozilla/DebugOnly.h" #include "mozilla/Likely.h" #include "mozilla/Move.h" +#include "mozilla/Mutex.h" #include "mozilla/RefPtr.h" #include "mozilla/StaticPtr.h" #include "nsIMemoryReporter.h" @@ -119,7 +120,8 @@ { ~CachedSurface() {} public: - NS_INLINE_DECL_REFCOUNTING(CachedSurface) + MOZ_DECLARE_REFCOUNTED_TYPENAME(CachedSurface) + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CachedSurface) CachedSurface(imgFrame* aSurface, const Cost aCost, @@ -215,7 +217,8 @@ public: ImageSurfaceCache() : mLocked(false) { } - NS_INLINE_DECL_REFCOUNTING(ImageSurfaceCache) + MOZ_DECLARE_REFCOUNTED_TYPENAME(ImageSurfaceCache) + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageSurfaceCache) typedef nsRefPtrHashtable, CachedSurface> SurfaceTable; @@ -277,6 +280,7 @@ : mExpirationTracker(MOZ_THIS_IN_INITIALIZER_LIST(), aSurfaceCacheExpirationTimeMS) , mMemoryPressureObserver(new MemoryPressureObserver) + , mMutex("SurfaceCache") , mDiscardFactor(aSurfaceCacheDiscardFactor) , mMaxCost(aSurfaceCacheSize) , mAvailableCost(aSurfaceCacheSize) @@ -298,9 +302,9 @@ } public: - void InitMemoryReporter() { - RegisterWeakMemoryReporter(this); - } + void InitMemoryReporter() { RegisterWeakMemoryReporter(this); } + + Mutex& GetMutex() { return mMutex; } bool Insert(imgFrame* aSurface, const Cost aCost, @@ -705,6 +709,7 @@ nsRefPtrHashtable, ImageSurfaceCache> mImageCaches; SurfaceTracker mExpirationTracker; nsRefPtr mMemoryPressureObserver; + Mutex mMutex; const uint32_t mDiscardFactor; const Cost mMaxCost; Cost mAvailableCost; @@ -722,6 +727,7 @@ SurfaceCache::Initialize() { // Initialize preferences. + MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!sInstance, "Shouldn't initialize more than once"); // See gfxPrefs for the default values of these preferences. @@ -775,6 +781,7 @@ /* static */ void SurfaceCache::Shutdown() { + MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(sInstance, "No singleton - was Shutdown() called twice?"); sInstance = nullptr; } @@ -783,11 +790,11 @@ SurfaceCache::Lookup(const ImageKey aImageKey, const SurfaceKey& aSurfaceKey) { - MOZ_ASSERT(NS_IsMainThread()); if (!sInstance) { return DrawableFrameRef(); } + MutexAutoLock lock(sInstance->GetMutex()); return sInstance->Lookup(aImageKey, aSurfaceKey); } @@ -797,11 +804,11 @@ const SurfaceKey& aSurfaceKey, Lifetime aLifetime) { - MOZ_ASSERT(NS_IsMainThread()); if (!sInstance) { return false; } + MutexAutoLock lock(sInstance->GetMutex()); Cost cost = ComputeCost(aSurfaceKey.Size()); return sInstance->Insert(aSurface, cost, aImageKey, aSurfaceKey, aLifetime); } @@ -809,7 +816,6 @@ /* static */ bool SurfaceCache::CanHold(const IntSize& aSize) { - MOZ_ASSERT(NS_IsMainThread()); if (!sInstance) { return false; } @@ -821,8 +827,8 @@ /* static */ void SurfaceCache::LockImage(Image* aImageKey) { - MOZ_ASSERT(NS_IsMainThread()); if (sInstance) { + MutexAutoLock lock(sInstance->GetMutex()); return sInstance->LockImage(aImageKey); } } @@ -830,8 +836,8 @@ /* static */ void SurfaceCache::UnlockImage(Image* aImageKey) { - MOZ_ASSERT(NS_IsMainThread()); if (sInstance) { + MutexAutoLock lock(sInstance->GetMutex()); return sInstance->UnlockImage(aImageKey); } } @@ -840,8 +846,8 @@ SurfaceCache::RemoveSurface(const ImageKey aImageKey, const SurfaceKey& aSurfaceKey) { - MOZ_ASSERT(NS_IsMainThread()); if (sInstance) { + MutexAutoLock lock(sInstance->GetMutex()); sInstance->RemoveSurface(aImageKey, aSurfaceKey); } } @@ -849,8 +855,8 @@ /* static */ void SurfaceCache::RemoveImage(Image* aImageKey) { - MOZ_ASSERT(NS_IsMainThread()); if (sInstance) { + MutexAutoLock lock(sInstance->GetMutex()); sInstance->RemoveImage(aImageKey); } } @@ -858,8 +864,8 @@ /* static */ void SurfaceCache::DiscardAll() { - MOZ_ASSERT(NS_IsMainThread()); if (sInstance) { + MutexAutoLock lock(sInstance->GetMutex()); sInstance->DiscardAll(); } } @@ -869,11 +875,11 @@ gfxMemoryLocation aLocation, MallocSizeOf aMallocSizeOf) { - MOZ_ASSERT(NS_IsMainThread()); if (!sInstance) { return 0; } + MutexAutoLock lock(sInstance->GetMutex()); return sInstance->SizeOfSurfaces(aImageKey, aLocation, aMallocSizeOf); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/SurfaceCache.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/SurfaceCache.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/SurfaceCache.h 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/SurfaceCache.h 2015-01-09 12:36:28.000000000 +0000 @@ -79,10 +79,10 @@ return aSIC.Hash(); } - friend SurfaceKey RasterSurfaceKey(const IntSize&, const uint32_t); + friend SurfaceKey RasterSurfaceKey(const IntSize&, uint32_t, uint32_t); friend SurfaceKey VectorSurfaceKey(const IntSize&, const Maybe&, - const float); + float); IntSize mSize; Maybe mSVGContext; @@ -92,18 +92,16 @@ inline SurfaceKey RasterSurfaceKey(const gfx::IntSize& aSize, - const uint32_t aFlags) + uint32_t aFlags, + uint32_t aFrameNum) { - // We don't care about aAnimationTime for RasterImage because it's not - // currently possible to store anything but the first frame in the - // SurfaceCache. - return SurfaceKey(aSize, Nothing(), 0.0f, aFlags); + return SurfaceKey(aSize, Nothing(), float(aFrameNum), aFlags); } inline SurfaceKey VectorSurfaceKey(const gfx::IntSize& aSize, const Maybe& aSVGContext, - const float aAnimationTime) + float aAnimationTime) { // We don't care about aFlags for VectorImage because none of the flags we // have right now influence VectorImage's rendering. If we add a new flag that diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/VectorImage.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/VectorImage.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/VectorImage.cpp 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/VectorImage.cpp 2015-01-09 12:36:28.000000000 +0000 @@ -359,12 +359,6 @@ return NS_OK; } -nsIntRect -VectorImage::FrameRect(uint32_t aWhichFrame) -{ - return nsIntRect::GetMaxSizedIntRect(); -} - size_t VectorImage::SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const { @@ -429,12 +423,6 @@ } nsresult -VectorImage::OnNewSourceData() -{ - return NS_OK; -} - -nsresult VectorImage::StartAnimation() { if (mError) diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/VectorImage.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/VectorImage.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/src/VectorImage.h 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/src/VectorImage.h 2015-01-09 12:36:28.000000000 +0000 @@ -40,7 +40,6 @@ // Methods inherited from Image nsresult Init(const char* aMimeType, uint32_t aFlags) MOZ_OVERRIDE; - virtual nsIntRect FrameRect(uint32_t aWhichFrame) MOZ_OVERRIDE; virtual size_t SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE; virtual size_t SizeOfDecoded(gfxMemoryLocation aLocation, @@ -55,7 +54,6 @@ nsISupports* aContext, nsresult aResult, bool aLastPart) MOZ_OVERRIDE; - virtual nsresult OnNewSourceData() MOZ_OVERRIDE; /** * Callback for SVGRootRenderingObserver. diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/test/browser/browser.ini thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/test/browser/browser.ini --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/image/test/browser/browser.ini 2015-01-07 22:15:19.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/image/test/browser/browser.ini 2015-01-09 12:36:28.000000000 +0000 @@ -10,4 +10,4 @@ [browser_bug666317.js] skip-if = e10s # Bug 948194 - Decoded Images seem to not be discarded on memory-pressure notification with e10s enabled [browser_image.js] -skip-if = e10s || !debug # Test is only to run on debug builds +skip-if = true # Bug 987616 diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/ipc/chromium/src/base/logging.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/ipc/chromium/src/base/logging.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/ipc/chromium/src/base/logging.h 2015-01-07 22:15:22.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/ipc/chromium/src/base/logging.h 2015-01-09 12:36:37.000000000 +0000 @@ -108,6 +108,7 @@ #define DCHECK(condition) while (false && (condition)) mozilla::EmptyLog() #endif +#undef LOG_ASSERT #define LOG_ASSERT(cond) CHECK(0) #define DLOG_ASSERT(cond) DCHECK(0) diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/ipc/ril/Ril.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/ipc/ril/Ril.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/ipc/ril/Ril.cpp 2015-01-07 22:15:22.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/ipc/ril/Ril.cpp 2015-01-09 12:36:39.000000000 +0000 @@ -1,5 +1,5 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* vim: set sw=4 ts=8 et ft=cpp: */ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ /* 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/. */ @@ -21,6 +21,7 @@ #include "jsfriendapi.h" #include "mozilla/ArrayUtils.h" +#include "mozilla/ipc/UnixSocketConnector.h" #include "nsTArray.h" #include "nsThreadUtils.h" // For NS_IsMainThread. @@ -29,199 +30,191 @@ namespace { -const char* RIL_SOCKET_NAME = "/dev/socket/rilproxy"; +static const char RIL_SOCKET_NAME[] = "/dev/socket/rilproxy"; // Network port to connect to for adb forwarded sockets when doing // desktop development. -const uint32_t RIL_TEST_PORT = 6200; +static const uint32_t RIL_TEST_PORT = 6200; -nsTArray > sRilConsumers; +static nsTArray > sRilConsumers; -class ConnectWorkerToRIL : public WorkerTask +class ConnectWorkerToRIL MOZ_FINAL : public WorkerTask { public: - ConnectWorkerToRIL() - { } - - virtual bool RunTask(JSContext *aCx); + bool RunTask(JSContext* aCx) MOZ_OVERRIDE; }; -class SendRilSocketDataTask : public nsRunnable +class SendRilSocketDataTask MOZ_FINAL : public nsRunnable { public: - SendRilSocketDataTask(unsigned long aClientId, - UnixSocketRawData *aRawData) - : mRawData(aRawData) - , mClientId(aClientId) - { } - - NS_IMETHOD Run() - { - MOZ_ASSERT(NS_IsMainThread()); - - if (sRilConsumers.Length() <= mClientId || - !sRilConsumers[mClientId] || - sRilConsumers[mClientId]->GetConnectionStatus() != SOCKET_CONNECTED) { - // Probably shuting down. - delete mRawData; - return NS_OK; - } - - sRilConsumers[mClientId]->SendSocketData(mRawData); - return NS_OK; - } + SendRilSocketDataTask(unsigned long aClientId, + UnixSocketRawData* aRawData) + : mRawData(aRawData) + , mClientId(aClientId) + { } -private: - UnixSocketRawData *mRawData; - unsigned long mClientId; -}; + NS_IMETHOD Run() MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); -bool -PostToRIL(JSContext *aCx, - unsigned aArgc, - JS::Value *aVp) -{ - JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp); - NS_ASSERTION(!NS_IsMainThread(), "Expecting to be on the worker thread"); - - if (args.length() != 2) { - JS_ReportError(aCx, "Expecting two arguments with the RIL message"); - return false; + if (sRilConsumers.Length() <= mClientId || + !sRilConsumers[mClientId] || + sRilConsumers[mClientId]->GetConnectionStatus() != SOCKET_CONNECTED) { + // Probably shuting down. + delete mRawData; + return NS_OK; } - int clientId = args[0].toInt32(); - JS::Value v = args[1]; - - UnixSocketRawData* raw = nullptr; + sRilConsumers[mClientId]->SendSocketData(mRawData); + return NS_OK; + } - if (v.isString()) { - JSAutoByteString abs; - JS::Rooted str(aCx, v.toString()); - if (!abs.encodeUtf8(aCx, str)) { - return false; - } - - raw = new UnixSocketRawData(abs.ptr(), abs.length()); - } else if (!v.isPrimitive()) { - JSObject *obj = v.toObjectOrNull(); - if (!JS_IsTypedArrayObject(obj)) { - JS_ReportError(aCx, "Object passed in wasn't a typed array"); - return false; - } - - uint32_t type = JS_GetArrayBufferViewType(obj); - if (type != js::Scalar::Int8 && - type != js::Scalar::Uint8 && - type != js::Scalar::Uint8Clamped) { - JS_ReportError(aCx, "Typed array data is not octets"); - return false; - } - - JS::AutoCheckCannotGC nogc; - size_t size = JS_GetTypedArrayByteLength(obj); - void *data = JS_GetArrayBufferViewData(obj, nogc); - raw = new UnixSocketRawData(data, size); - } else { - JS_ReportError(aCx, - "Incorrect argument. Expecting a string or a typed array"); - return false; - } +private: + UnixSocketRawData* mRawData; + unsigned long mClientId; +}; - if (!raw) { - JS_ReportError(aCx, "Unable to post to RIL"); - return false; - } +static bool +PostToRIL(JSContext* aCx, unsigned aArgc, JS::Value* aVp) +{ + JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp); + NS_ASSERTION(!NS_IsMainThread(), "Expecting to be on the worker thread"); - nsRefPtr task = - new SendRilSocketDataTask(clientId, raw); - NS_DispatchToMainThread(task); - return true; + if (args.length() != 2) { + JS_ReportError(aCx, "Expecting two arguments with the RIL message"); + return false; + } + + int clientId = args[0].toInt32(); + JS::Value v = args[1]; + + UnixSocketRawData* raw = nullptr; + + if (v.isString()) { + JSAutoByteString abs; + JS::Rooted str(aCx, v.toString()); + if (!abs.encodeUtf8(aCx, str)) { + return false; + } + + raw = new UnixSocketRawData(abs.ptr(), abs.length()); + } else if (!v.isPrimitive()) { + JSObject* obj = v.toObjectOrNull(); + if (!JS_IsTypedArrayObject(obj)) { + JS_ReportError(aCx, "Object passed in wasn't a typed array"); + return false; + } + + uint32_t type = JS_GetArrayBufferViewType(obj); + if (type != js::Scalar::Int8 && + type != js::Scalar::Uint8 && + type != js::Scalar::Uint8Clamped) { + JS_ReportError(aCx, "Typed array data is not octets"); + return false; + } + + JS::AutoCheckCannotGC nogc; + size_t size = JS_GetTypedArrayByteLength(obj); + void* data = JS_GetArrayBufferViewData(obj, nogc); + raw = new UnixSocketRawData(data, size); + } else { + JS_ReportError( + aCx, "Incorrect argument. Expecting a string or a typed array"); + return false; + } + + if (!raw) { + JS_ReportError(aCx, "Unable to post to RIL"); + return false; + } + + nsRefPtr task = new SendRilSocketDataTask(clientId, + raw); + NS_DispatchToMainThread(task); + return true; } bool -ConnectWorkerToRIL::RunTask(JSContext *aCx) +ConnectWorkerToRIL::RunTask(JSContext* aCx) { - // Set up the postRILMessage on the function for worker -> RIL thread - // communication. - NS_ASSERTION(!NS_IsMainThread(), "Expecting to be on the worker thread"); - NS_ASSERTION(!JS_IsRunning(aCx), "Are we being called somehow?"); - JS::Rooted workerGlobal(aCx, JS::CurrentGlobalOrNull(aCx)); - - // Check whether |postRILMessage| has been defined. No one but this class - // should ever define |postRILMessage| in a RIL worker. - JS::Rooted val(aCx); - if (!JS_GetProperty(aCx, workerGlobal, "postRILMessage", &val)) { - JS_ReportPendingException(aCx); - return false; - } + // Set up the postRILMessage on the function for worker -> RIL thread + // communication. + NS_ASSERTION(!NS_IsMainThread(), "Expecting to be on the worker thread"); + NS_ASSERTION(!JS_IsRunning(aCx), "Are we being called somehow?"); + JS::Rooted workerGlobal(aCx, JS::CurrentGlobalOrNull(aCx)); + + // Check whether |postRILMessage| has been defined. No one but this class + // should ever define |postRILMessage| in a RIL worker. + JS::Rooted val(aCx); + if (!JS_GetProperty(aCx, workerGlobal, "postRILMessage", &val)) { + JS_ReportPendingException(aCx); + return false; + } - // Make sure that |postRILMessage| is a function. - if (JSTYPE_FUNCTION == JS_TypeOfValue(aCx, val)) { - return true; - } + // Make sure that |postRILMessage| is a function. + if (JSTYPE_FUNCTION == JS_TypeOfValue(aCx, val)) { + return true; + } - return !!JS_DefineFunction(aCx, workerGlobal, - "postRILMessage", PostToRIL, 2, 0); + return !!JS_DefineFunction(aCx, workerGlobal, "postRILMessage", + PostToRIL, 2, 0); } -class DispatchRILEvent : public WorkerTask +class DispatchRILEvent MOZ_FINAL : public WorkerTask { public: - DispatchRILEvent(unsigned long aClient, - UnixSocketRawData* aMessage) - : mClientId(aClient) - , mMessage(aMessage) - { } + DispatchRILEvent(unsigned long aClient, UnixSocketRawData* aMessage) + : mClientId(aClient) + , mMessage(aMessage) + { } - virtual bool RunTask(JSContext *aCx); + bool RunTask(JSContext* aCx) MOZ_OVERRIDE; private: - unsigned long mClientId; - nsAutoPtr mMessage; + unsigned long mClientId; + nsAutoPtr mMessage; }; bool -DispatchRILEvent::RunTask(JSContext *aCx) +DispatchRILEvent::RunTask(JSContext* aCx) { - JS::Rooted obj(aCx, JS::CurrentGlobalOrNull(aCx)); - - JS::Rooted array(aCx, - JS_NewUint8Array(aCx, mMessage->GetSize())); - if (!array) { - return false; - } - { - JS::AutoCheckCannotGC nogc; - memcpy(JS_GetArrayBufferViewData(array, nogc), - mMessage->GetData(), mMessage->GetSize()); - } + JS::Rooted obj(aCx, JS::CurrentGlobalOrNull(aCx)); - JS::AutoValueArray<2> args(aCx); - args[0].setNumber((uint32_t)mClientId); - args[1].setObject(*array); + JS::Rooted array(aCx, + JS_NewUint8Array(aCx, mMessage->GetSize())); + if (!array) { + return false; + } + { + JS::AutoCheckCannotGC nogc; + memcpy(JS_GetArrayBufferViewData(array, nogc), + mMessage->GetData(), mMessage->GetSize()); + } + + JS::AutoValueArray<2> args(aCx); + args[0].setNumber((uint32_t)mClientId); + args[1].setObject(*array); - JS::Rooted rval(aCx); - return JS_CallFunctionName(aCx, obj, "onRILMessage", args, &rval); + JS::Rooted rval(aCx); + return JS_CallFunctionName(aCx, obj, "onRILMessage", args, &rval); } -class RilConnector : public mozilla::ipc::UnixSocketConnector +class RilConnector MOZ_FINAL : public mozilla::ipc::UnixSocketConnector { public: - RilConnector(unsigned long aClientId) : mClientId(aClientId) - {} - - virtual ~RilConnector() - {} - - virtual int Create(); - virtual bool CreateAddr(bool aIsServer, - socklen_t& aAddrSize, - sockaddr_any& aAddr, - const char* aAddress); - virtual bool SetUp(int aFd); - virtual bool SetUpListenSocket(int aFd); - virtual void GetSocketAddr(const sockaddr_any& aAddr, - nsAString& aAddrStr); + RilConnector(unsigned long aClientId) + : mClientId(aClientId) + { } + + int Create() MOZ_OVERRIDE; + bool CreateAddr(bool aIsServer, + socklen_t& aAddrSize, + sockaddr_any& aAddr, + const char* aAddress) MOZ_OVERRIDE; + bool SetUp(int aFd) MOZ_OVERRIDE; + bool SetUpListenSocket(int aFd) MOZ_OVERRIDE; + void GetSocketAddr(const sockaddr_any& aAddr, + nsAString& aAddrStr) MOZ_OVERRIDE; private: unsigned long mClientId; @@ -230,26 +223,26 @@ int RilConnector::Create() { - MOZ_ASSERT(!NS_IsMainThread()); + MOZ_ASSERT(!NS_IsMainThread()); - int fd = -1; + int fd = -1; #if defined(MOZ_WIDGET_GONK) - fd = socket(AF_LOCAL, SOCK_STREAM, 0); + fd = socket(AF_LOCAL, SOCK_STREAM, 0); #else - // If we can't hit a local loopback, fail later in connect. - fd = socket(AF_INET, SOCK_STREAM, 0); + // If we can't hit a local loopback, fail later in connect. + fd = socket(AF_INET, SOCK_STREAM, 0); #endif - if (fd < 0) { - NS_WARNING("Could not open ril socket!"); - return -1; - } - - if (!SetUp(fd)) { - NS_WARNING("Could not set up socket!"); - } - return fd; + if (fd < 0) { + NS_WARNING("Could not open ril socket!"); + return -1; + } + + if (!SetUp(fd)) { + NS_WARNING("Could not set up socket!"); + } + return fd; } bool @@ -258,56 +251,55 @@ sockaddr_any& aAddr, const char* aAddress) { - // We never open ril socket as server. - MOZ_ASSERT(!aIsServer); - uint32_t af; + // We never open ril socket as server. + MOZ_ASSERT(!aIsServer); + uint32_t af; #if defined(MOZ_WIDGET_GONK) - af = AF_LOCAL; + af = AF_LOCAL; #else - af = AF_INET; + af = AF_INET; #endif - switch (af) { - case AF_LOCAL: - aAddr.un.sun_family = af; - if(strlen(aAddress) > sizeof(aAddr.un.sun_path)) { - NS_WARNING("Address too long for socket struct!"); - return false; - } - strcpy((char*)&aAddr.un.sun_path, aAddress); - aAddrSize = strlen(aAddress) + offsetof(struct sockaddr_un, sun_path) + 1; - break; - case AF_INET: - aAddr.in.sin_family = af; - aAddr.in.sin_port = htons(RIL_TEST_PORT + mClientId); - aAddr.in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - aAddrSize = sizeof(sockaddr_in); - break; - default: - NS_WARNING("Socket type not handled by connector!"); - return false; - } - return true; + switch (af) { + case AF_LOCAL: + aAddr.un.sun_family = af; + if(strlen(aAddress) > sizeof(aAddr.un.sun_path)) { + NS_WARNING("Address too long for socket struct!"); + return false; + } + strcpy((char*)&aAddr.un.sun_path, aAddress); + aAddrSize = strlen(aAddress) + offsetof(struct sockaddr_un, sun_path) + 1; + break; + case AF_INET: + aAddr.in.sin_family = af; + aAddr.in.sin_port = htons(RIL_TEST_PORT + mClientId); + aAddr.in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + aAddrSize = sizeof(sockaddr_in); + break; + default: + NS_WARNING("Socket type not handled by connector!"); + return false; + } + return true; } bool RilConnector::SetUp(int aFd) { - // Nothing to do here. - return true; + // Nothing to do here. + return true; } bool RilConnector::SetUpListenSocket(int aFd) { - // Nothing to do here. - return true; + // Nothing to do here. + return true; } void -RilConnector::GetSocketAddr(const sockaddr_any& aAddr, - nsAString& aAddrStr) +RilConnector::GetSocketAddr(const sockaddr_any& aAddr, nsAString& aAddrStr) { - MOZ_CRASH("This should never be called!"); + MOZ_CRASH("This should never be called!"); } } // anonymous namespace @@ -317,96 +309,102 @@ RilConsumer::RilConsumer(unsigned long aClientId, WorkerCrossThreadDispatcher* aDispatcher) - : mDispatcher(aDispatcher) - , mClientId(aClientId) - , mShutdown(false) -{ - // Only append client id after RIL_SOCKET_NAME when it's not connected to - // the first(0) rilproxy for compatibility. - if (!aClientId) { - mAddress = RIL_SOCKET_NAME; - } else { - struct sockaddr_un addr_un; - snprintf(addr_un.sun_path, sizeof addr_un.sun_path, "%s%lu", - RIL_SOCKET_NAME, aClientId); - mAddress = addr_un.sun_path; - } + : mDispatcher(aDispatcher) + , mClientId(aClientId) + , mShutdown(false) +{ + // Only append client id after RIL_SOCKET_NAME when it's not connected to + // the first(0) rilproxy for compatibility. + if (!aClientId) { + mAddress = RIL_SOCKET_NAME; + } else { + struct sockaddr_un addr_un; + snprintf(addr_un.sun_path, sizeof addr_un.sun_path, "%s%lu", + RIL_SOCKET_NAME, aClientId); + mAddress = addr_un.sun_path; + } - ConnectSocket(new RilConnector(mClientId), mAddress.get()); + Connect(new RilConnector(mClientId), mAddress.get()); } nsresult RilConsumer::Register(unsigned int aClientId, WorkerCrossThreadDispatcher* aDispatcher) { - MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(NS_IsMainThread()); - sRilConsumers.EnsureLengthAtLeast(aClientId + 1); + sRilConsumers.EnsureLengthAtLeast(aClientId + 1); - if (sRilConsumers[aClientId]) { - NS_WARNING("RilConsumer already registered"); - return NS_ERROR_FAILURE; - } - - nsRefPtr connection = new ConnectWorkerToRIL(); - if (!aDispatcher->PostTask(connection)) { - NS_WARNING("Failed to connect worker to ril"); - return NS_ERROR_UNEXPECTED; - } - - // Now that we're set up, connect ourselves to the RIL thread. - sRilConsumers[aClientId] = new RilConsumer(aClientId, aDispatcher); - return NS_OK; + if (sRilConsumers[aClientId]) { + NS_WARNING("RilConsumer already registered"); + return NS_ERROR_FAILURE; + } + + nsRefPtr connection = new ConnectWorkerToRIL(); + if (!aDispatcher->PostTask(connection)) { + NS_WARNING("Failed to connect worker to ril"); + return NS_ERROR_UNEXPECTED; + } + + // Now that we're set up, connect ourselves to the RIL thread. + sRilConsumers[aClientId] = new RilConsumer(aClientId, aDispatcher); + return NS_OK; } void RilConsumer::Shutdown() { - MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(NS_IsMainThread()); - for (unsigned long i = 0; i < sRilConsumers.Length(); i++) { - nsRefPtr& instance = sRilConsumers[i]; - if (!instance) { - continue; - } - - instance->mShutdown = true; - instance->CloseSocket(); - instance = nullptr; + for (unsigned long i = 0; i < sRilConsumers.Length(); i++) { + nsRefPtr& instance = sRilConsumers[i]; + if (!instance) { + continue; } + + instance->mShutdown = true; + instance->Close(); + instance = nullptr; + } } void RilConsumer::ReceiveSocketData(nsAutoPtr& aMessage) { - MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(NS_IsMainThread()); - nsRefPtr dre(new DispatchRILEvent(mClientId, aMessage.forget())); - mDispatcher->PostTask(dre); + nsRefPtr dre(new DispatchRILEvent(mClientId, aMessage.forget())); + mDispatcher->PostTask(dre); } void RilConsumer::OnConnectSuccess() { - // Nothing to do here. - CHROMIUM_LOG("RIL[%lu]: %s\n", mClientId, __FUNCTION__); + // Nothing to do here. + CHROMIUM_LOG("RIL[%lu]: %s\n", mClientId, __FUNCTION__); } void RilConsumer::OnConnectError() { - CHROMIUM_LOG("RIL[%lu]: %s\n", mClientId, __FUNCTION__); - CloseSocket(); + CHROMIUM_LOG("RIL[%lu]: %s\n", mClientId, __FUNCTION__); + Close(); } void RilConsumer::OnDisconnect() { - CHROMIUM_LOG("RIL[%lu]: %s\n", mClientId, __FUNCTION__); - if (!mShutdown) { - ConnectSocket(new RilConnector(mClientId), mAddress.get(), - GetSuggestedConnectDelayMs()); - } + CHROMIUM_LOG("RIL[%lu]: %s\n", mClientId, __FUNCTION__); + if (!mShutdown) { + Connect(new RilConnector(mClientId), mAddress.get(), + GetSuggestedConnectDelayMs()); + } +} + +ConnectionOrientedSocketIO* +RilConsumer::GetIO() +{ + return PrepareAccept(new RilConnector(mClientId)); } } // namespace ipc diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/ipc/ril/Ril.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/ipc/ril/Ril.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/ipc/ril/Ril.h 2015-01-07 22:15:22.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/ipc/ril/Ril.h 2015-01-09 12:36:39.000000000 +0000 @@ -1,5 +1,5 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set sw=2 ts=8 et ft=cpp: */ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ /* 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/. */ @@ -8,31 +8,31 @@ #define mozilla_ipc_Ril_h 1 #include -#include +#include namespace mozilla { namespace ipc { -class RilConsumer : public mozilla::ipc::UnixSocketConsumer +class RilConsumer MOZ_FINAL : public mozilla::ipc::StreamSocket { public: - virtual ~RilConsumer() { } - - static nsresult Register(unsigned int aClientId, - mozilla::dom::workers::WorkerCrossThreadDispatcher* aDispatcher); + static nsresult Register( + unsigned int aClientId, + mozilla::dom::workers::WorkerCrossThreadDispatcher* aDispatcher); static void Shutdown(); + ConnectionOrientedSocketIO* GetIO() MOZ_OVERRIDE; + private: RilConsumer(unsigned long aClientId, mozilla::dom::workers::WorkerCrossThreadDispatcher* aDispatcher); - virtual void ReceiveSocketData(nsAutoPtr& aMessage); + void ReceiveSocketData(nsAutoPtr& aMessage) MOZ_OVERRIDE; - virtual void OnConnectSuccess(); - virtual void OnConnectError(); - virtual void OnDisconnect(); + void OnConnectSuccess() MOZ_OVERRIDE; + void OnConnectError() MOZ_OVERRIDE; + void OnDisconnect() MOZ_OVERRIDE; -private: nsRefPtr mDispatcher; unsigned long mClientId; nsCString mAddress; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/public/GCAPI.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/public/GCAPI.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/public/GCAPI.h 2015-01-07 22:15:22.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/public/GCAPI.h 2015-01-09 12:36:39.000000000 +0000 @@ -31,6 +31,17 @@ JSGC_MODE_INCREMENTAL = 2 } JSGCMode; +/* + * Kinds of js_GC invocation. + */ +typedef enum JSGCInvocationKind { + /* Normal invocation. */ + GC_NORMAL = 0, + + /* Minimize GC triggers and release empty GC chunks right away. */ + GC_SHRINK = 1 +} JSGCInvocationKind; + namespace JS { #define GCREASONS(D) \ @@ -130,13 +141,13 @@ /* * Schedule the given zone to be collected as part of the next GC. */ -extern JS_FRIEND_API(void) +extern JS_PUBLIC_API(void) PrepareZoneForGC(Zone *zone); /* * Schedule all zones to be collected in the next GC. */ -extern JS_FRIEND_API(void) +extern JS_PUBLIC_API(void) PrepareForFullGC(JSRuntime *rt); /* @@ -144,21 +155,21 @@ * previous incremental slice must be selected in subsequent slices as well. * This function selects those slices automatically. */ -extern JS_FRIEND_API(void) +extern JS_PUBLIC_API(void) PrepareForIncrementalGC(JSRuntime *rt); /* * Returns true if any zone in the system has been scheduled for GC with one of * the functions above or by the JS engine. */ -extern JS_FRIEND_API(bool) +extern JS_PUBLIC_API(bool) IsGCScheduled(JSRuntime *rt); /* * Undoes the effect of the Prepare methods above. The given zone will not be * collected in the next GC. */ -extern JS_FRIEND_API(void) +extern JS_PUBLIC_API(void) SkipZoneForGC(Zone *zone); /* @@ -168,20 +179,16 @@ */ /* - * Performs a non-incremental collection of all selected zones. Some objects - * that are unreachable from the program may still be alive afterwards because - * of internal references. - */ -extern JS_FRIEND_API(void) -GCForReason(JSRuntime *rt, gcreason::Reason reason); - -/* - * Perform a non-incremental collection after clearing caches and other - * temporary references to objects. This will remove all unreferenced objects - * in the system. + * Performs a non-incremental collection of all selected zones. + * + * If the gckind argument is GC_NORMAL, then some objects that are unreachable + * from the program may still be alive afterwards because of internal + * references; if GC_SHRINK is passed then caches and other temporary references + * to objects will be cleared and all unreferenced objects will be removed from + * the system. */ -extern JS_FRIEND_API(void) -ShrinkingGC(JSRuntime *rt, gcreason::Reason reason); +extern JS_PUBLIC_API(void) +GCForReason(JSRuntime *rt, JSGCInvocationKind gckind, gcreason::Reason reason); /* * Incremental GC: @@ -207,16 +214,28 @@ */ /* - * Begin an incremental collection and perform one slice worth of work or - * perform a slice of an ongoing incremental collection. When this function - * returns, the collection is not complete. This function must be called - * repeatedly until !IsIncrementalGCInProgress(rt). + * Begin an incremental collection and perform one slice worth of work. When + * this function returns, the collection may not be complete. + * IncrementalGCSlice() must be called repeatedly until + * !IsIncrementalGCInProgress(rt). + * + * Note: SpiderMonkey's GC is not realtime. Slices in practice may be longer or + * shorter than the requested interval. + */ +extern JS_PUBLIC_API(void) +StartIncrementalGC(JSRuntime *rt, JSGCInvocationKind gckind, gcreason::Reason reason, + int64_t millis = 0); + +/* + * Perform a slice of an ongoing incremental collection. When this function + * returns, the collection may not be complete. It must be called repeatedly + * until !IsIncrementalGCInProgress(rt). * * Note: SpiderMonkey's GC is not realtime. Slices in practice may be longer or * shorter than the requested interval. */ -extern JS_FRIEND_API(void) -IncrementalGC(JSRuntime *rt, gcreason::Reason reason, int64_t millis = 0); +extern JS_PUBLIC_API(void) +IncrementalGCSlice(JSRuntime *rt, gcreason::Reason reason, int64_t millis = 0); /* * If IsIncrementalGCInProgress(rt), this call finishes the ongoing collection @@ -224,7 +243,7 @@ * this is equivalent to GCForReason. When this function returns, * IsIncrementalGCInProgress(rt) will always be false. */ -extern JS_FRIEND_API(void) +extern JS_PUBLIC_API(void) FinishIncrementalGC(JSRuntime *rt, gcreason::Reason reason); enum GCProgress { @@ -244,7 +263,7 @@ GC_CYCLE_END }; -struct JS_FRIEND_API(GCDescription) { +struct JS_PUBLIC_API(GCDescription) { bool isCompartment_; explicit GCDescription(bool isCompartment) @@ -262,7 +281,7 @@ * callback may be used for GC notifications as well as to perform additional * marking. */ -extern JS_FRIEND_API(GCSliceCallback) +extern JS_PUBLIC_API(GCSliceCallback) SetGCSliceCallback(JSRuntime *rt, GCSliceCallback callback); /* @@ -271,7 +290,7 @@ * There is not currently a way to re-enable incremental GC once it has been * disabled on the runtime. */ -extern JS_FRIEND_API(void) +extern JS_PUBLIC_API(void) DisableIncrementalGC(JSRuntime *rt); /* @@ -282,7 +301,7 @@ * GCDescription returned by GCSliceCallback may help narrow down the cause if * collections are not happening incrementally when expected. */ -extern JS_FRIEND_API(bool) +extern JS_PUBLIC_API(bool) IsIncrementalGCEnabled(JSRuntime *rt); /* @@ -291,20 +310,20 @@ * pointer callbacks. There is not currently a way to re-enable compacting GC * once it has been disabled on the runtime. */ -extern JS_FRIEND_API(void) +extern JS_PUBLIC_API(void) DisableCompactingGC(JSRuntime *rt); /* * Returns true if compacting GC is enabled. */ -extern JS_FRIEND_API(bool) +extern JS_PUBLIC_API(bool) IsCompactingGCEnabled(JSRuntime *rt); /* * Returns true while an incremental GC is ongoing, both when actively * collecting and between slices. */ -JS_FRIEND_API(bool) +extern JS_PUBLIC_API(bool) IsIncrementalGCInProgress(JSRuntime *rt); /* @@ -312,29 +331,29 @@ * This is generally only true when running mutator code in-between GC slices. * At other times, the barrier may be elided for performance. */ -extern JS_FRIEND_API(bool) +extern JS_PUBLIC_API(bool) IsIncrementalBarrierNeeded(JSRuntime *rt); -extern JS_FRIEND_API(bool) +extern JS_PUBLIC_API(bool) IsIncrementalBarrierNeeded(JSContext *cx); /* * Notify the GC that a reference to a GC thing is about to be overwritten. * These methods must be called if IsIncrementalBarrierNeeded. */ -extern JS_FRIEND_API(void) +extern JS_PUBLIC_API(void) IncrementalReferenceBarrier(GCCellPtr thing); -extern JS_FRIEND_API(void) +extern JS_PUBLIC_API(void) IncrementalValueBarrier(const Value &v); -extern JS_FRIEND_API(void) +extern JS_PUBLIC_API(void) IncrementalObjectBarrier(JSObject *obj); /* * Returns true if the most recent GC ran incrementally. */ -extern JS_FRIEND_API(bool) +extern JS_PUBLIC_API(bool) WasIncrementalGC(JSRuntime *rt); /* @@ -346,7 +365,7 @@ */ /* Ensure that generational GC is disabled within some scope. */ -class JS_FRIEND_API(AutoDisableGenerationalGC) +class JS_PUBLIC_API(AutoDisableGenerationalGC) { js::gc::GCRuntime *gc; #ifdef JS_GC_ZEAL @@ -362,7 +381,7 @@ * Returns true if generational allocation and collection is currently enabled * on the given runtime. */ -extern JS_FRIEND_API(bool) +extern JS_PUBLIC_API(bool) IsGenerationalGCEnabled(JSRuntime *rt); /* @@ -370,7 +389,7 @@ * of GCs that have been run, but is guaranteed to be monotonically increasing * with GC activity. */ -extern JS_FRIEND_API(size_t) +extern JS_PUBLIC_API(size_t) GetGCNumber(); /* @@ -378,7 +397,7 @@ * back to the system incase it is needed soon afterwards. This call forces the * GC to return this memory immediately. */ -extern JS_FRIEND_API(void) +extern JS_PUBLIC_API(void) ShrinkGCBuffers(JSRuntime *rt); /* diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/public/Utility.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/public/Utility.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/public/Utility.h 2015-01-07 22:15:22.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/public/Utility.h 2015-01-09 12:36:39.000000000 +0000 @@ -88,9 +88,18 @@ return nullptr; \ } \ } while (0) +# define JS_OOM_POSSIBLY_FAIL_BOOL() \ + do \ + { \ + if (++OOM_counter > OOM_maxAllocations) { \ + JS_OOM_CALL_BP_FUNC();\ + return false; \ + } \ + } while (0) # else # define JS_OOM_POSSIBLY_FAIL() do {} while(0) +# define JS_OOM_POSSIBLY_FAIL_BOOL() do {} while(0) # endif /* DEBUG || JS_OOM_BREAKPOINT */ static inline void* js_malloc(size_t bytes) diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/asmjs/AsmJSValidate.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/asmjs/AsmJSValidate.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/asmjs/AsmJSValidate.cpp 2015-01-07 22:15:22.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/asmjs/AsmJSValidate.cpp 2015-01-09 12:36:39.000000000 +0000 @@ -8492,7 +8492,7 @@ // 2.4. Load callee executable entry point masm.loadPtr(Address(callee, JSFunction::offsetOfNativeOrScript()), callee); - masm.loadBaselineOrIonNoArgCheck(callee, callee, SequentialExecution, nullptr); + masm.loadBaselineOrIonNoArgCheck(callee, callee, nullptr); // 3. Argc unsigned argc = exit.sig().args().length(); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/builtin/TestingFunctions.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/builtin/TestingFunctions.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/builtin/TestingFunctions.cpp 2015-01-07 22:15:22.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/builtin/TestingFunctions.cpp 2015-01-09 12:36:39.000000000 +0000 @@ -238,10 +238,8 @@ else JS::PrepareForFullGC(cx->runtime()); - if (shrinking) - JS::ShrinkingGC(cx->runtime(), JS::gcreason::API); - else - JS::GCForReason(cx->runtime(), JS::gcreason::API); + JSGCInvocationKind gckind = shrinking ? GC_SHRINK : GC_NORMAL; + JS::GCForReason(cx->runtime(), gckind, JS::gcreason::API); char buf[256] = { '\0' }; #ifndef JS_MORE_DETERMINISTIC diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/builtin/TypedArray.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/builtin/TypedArray.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/builtin/TypedArray.js 2015-01-07 22:15:22.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/builtin/TypedArray.js 2015-01-09 12:36:39.000000000 +0000 @@ -286,6 +286,84 @@ return -1; } +// ES6 draft rev30 (2014/12/24) 22.2.3.19 %TypedArray%.prototype.reduce(callbackfn[, initialValue]). +function TypedArrayReduce(callbackfn/*, initialValue*/) { + // This function is not generic. + if (!IsObject(this) || !IsTypedArray(this)) + return callFunction(CallTypedArrayMethodIfWrapped, this, callbackfn, "TypedArrayReduce"); + + // Steps 1-2. + var O = this; + + // Steps 3-5. + var len = TypedArrayLength(O); + + // Step 6. + if (arguments.length === 0) + ThrowError(JSMSG_MISSING_FUN_ARG, 0, "%TypedArray%.prototype.reduce"); + if (!IsCallable(callbackfn)) + ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn)); + + // Step 7. + if (len === 0 && arguments.length === 1) + ThrowError(JSMSG_EMPTY_ARRAY_REDUCE); + + // Step 8. + var k = 0; + + // Steps 9-10. + // Omit some steps, since 'accumulator' should always be O[0] in step 10 for typed arrays. + var accumulator = arguments.length > 1 ? arguments[1] : O[k++]; + + // Step 11. + // Omit steps 11.b-11.c and the 'if' clause in step 11.d, since there are no holes in typed arrays. + for (; k < len; k++) { + accumulator = callFunction(callbackfn, undefined, accumulator, O[k], k, O); + } + + // Step 12. + return accumulator; +} + +// ES6 draft rev30 (2014/12/24) 22.2.3.20 %TypedArray%.prototype.reduceRight(callbackfn[, initialValue]). +function TypedArrayReduceRight(callbackfn/*, initialValue*/) { + // This function is not generic. + if (!IsObject(this) || !IsTypedArray(this)) + return callFunction(CallTypedArrayMethodIfWrapped, this, callbackfn, "TypedArrayReduceRight"); + + // Steps 1-2. + var O = this; + + // Steps 3-5. + var len = TypedArrayLength(O); + + // Step 6. + if (arguments.length === 0) + ThrowError(JSMSG_MISSING_FUN_ARG, 0, "%TypedArray%.prototype.reduceRight"); + if (!IsCallable(callbackfn)) + ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn)); + + // Step 7. + if (len === 0 && arguments.length === 1) + ThrowError(JSMSG_EMPTY_ARRAY_REDUCE); + + // Step 8. + var k = len - 1; + + // Steps 9-10. + // Omit some steps, since 'accumulator' should always be O[len-1] in step 10 for typed arrays. + var accumulator = arguments.length > 1 ? arguments[1] : O[k--]; + + // Step 11. + // Omit steps 11.b-11.c and the 'if' clause in step 11.d, since there are no holes in typed arrays. + for (; k >= 0; k--) { + accumulator = callFunction(callbackfn, undefined, accumulator, O[k], k, O); + } + + // Step 12. + return accumulator; +} + // ES6 draft rev29 (2014/12/06) 22.2.3.21 %TypedArray%.prototype.reverse(). function TypedArrayReverse() { // This function is not generic. diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/builtin/TypedObject.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/builtin/TypedObject.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/builtin/TypedObject.cpp 2015-01-07 22:15:22.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/builtin/TypedObject.cpp 2015-01-09 12:36:39.000000000 +0000 @@ -517,15 +517,15 @@ const JSFunctionSpec ArrayMetaTypeDescr::typedObjectMethods[] = { {"forEach", {nullptr, nullptr}, 1, 0, "ArrayForEach"}, - {"redimension", {nullptr, nullptr}, 1, 0, "TypedArrayRedimension"}, - JS_SELF_HOSTED_FN("map", "TypedArrayMap", 2, 0), - JS_SELF_HOSTED_FN("mapPar", "TypedArrayMapPar", 2, 0), - JS_SELF_HOSTED_FN("reduce", "TypedArrayReduce", 2, 0), - JS_SELF_HOSTED_FN("reducePar", "TypedArrayReducePar", 2, 0), - JS_SELF_HOSTED_FN("scatter", "TypedArrayScatter", 4, 0), - JS_SELF_HOSTED_FN("scatterPar", "TypedArrayScatterPar", 4, 0), - JS_SELF_HOSTED_FN("filter", "TypedArrayFilter", 1, 0), - JS_SELF_HOSTED_FN("filterPar", "TypedArrayFilterPar", 1, 0), + {"redimension", {nullptr, nullptr}, 1, 0, "TypedObjectArrayRedimension"}, + JS_SELF_HOSTED_FN("map", "TypedObjectArrayMap", 2, 0), + JS_SELF_HOSTED_FN("mapPar", "TypedObjectArrayMapPar", 2, 0), + JS_SELF_HOSTED_FN("reduce", "TypedObjectArrayReduce", 2, 0), + JS_SELF_HOSTED_FN("reducePar", "TypedObjectArrayReducePar", 2, 0), + JS_SELF_HOSTED_FN("scatter", "TypedObjectArrayScatter", 4, 0), + JS_SELF_HOSTED_FN("scatterPar", "TypedObjectArrayScatterPar", 4, 0), + JS_SELF_HOSTED_FN("filter", "TypedObjectArrayFilter", 1, 0), + JS_SELF_HOSTED_FN("filterPar", "TypedObjectArrayFilterPar", 1, 0), JS_FS_END }; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/builtin/TypedObject.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/builtin/TypedObject.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/builtin/TypedObject.js 2015-01-07 22:15:22.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/builtin/TypedObject.js 2015-01-09 12:36:39.000000000 +0000 @@ -380,7 +380,7 @@ return DescrsEquiv(this, otherDescr); } -// TypedArray.redimension(newArrayType) +// TypedObjectArray.redimension(newArrayType) // // Method that "repackages" the data from this array into a new typed // object whose type is `newArrayType`. Once you strip away all the @@ -400,7 +400,7 @@ // if the base element types are not equivalent. // // Warning: user exposed! -function TypedArrayRedimension(newArrayType) { +function TypedObjectArrayRedimension(newArrayType) { if (!IsObject(this) || !ObjectIsTypedObject(this)) ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); @@ -631,7 +631,7 @@ } // Warning: user exposed! -function TypedArrayMap(a, b) { +function TypedObjectArrayMap(a, b) { if (!IsObject(this) || !ObjectIsTypedObject(this)) ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); var thisType = TypedObjectTypeDescr(this); @@ -647,26 +647,26 @@ } // Warning: user exposed! -function TypedArrayMapPar(a, b) { +function TypedObjectArrayMapPar(a, b) { // Arguments: [depth], func // Defer to the sequential variant for error cases or // when not working with typed objects. if (!IsObject(this) || !ObjectIsTypedObject(this)) - return callFunction(TypedArrayMap, this, a, b); + return callFunction(TypedObjectArrayMap, this, a, b); var thisType = TypedObjectTypeDescr(this); if (!TypeDescrIsArrayType(thisType)) - return callFunction(TypedArrayMap, this, a, b); + return callFunction(TypedObjectArrayMap, this, a, b); if (typeof a === "number" && IsCallable(b)) return MapTypedParImpl(this, a, thisType, b); else if (IsCallable(a)) return MapTypedParImpl(this, 1, thisType, a); - return callFunction(TypedArrayMap, this, a, b); + return callFunction(TypedObjectArrayMap, this, a, b); } // Warning: user exposed! -function TypedArrayReduce(a, b) { +function TypedObjectArrayReduce(a, b) { // Arguments: func, [initial] if (!IsObject(this) || !ObjectIsTypedObject(this)) ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); @@ -682,7 +682,7 @@ } // Warning: user exposed! -function TypedArrayScatter(a, b, c, d) { +function TypedObjectArrayScatter(a, b, c, d) { // Arguments: outputArrayType, indices, defaultValue, conflictFunction if (!IsObject(this) || !ObjectIsTypedObject(this)) ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); @@ -700,7 +700,7 @@ } // Warning: user exposed! -function TypedArrayFilter(func) { +function TypedObjectArrayFilter(func) { // Arguments: predicate if (!IsObject(this) || !ObjectIsTypedObject(this)) ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); @@ -741,18 +741,18 @@ } // Warning: user exposed! -function TypedArrayReducePar(a, b) { - return callFunction(TypedArrayReduce, this, a, b); +function TypedObjectArrayReducePar(a, b) { + return callFunction(TypedObjectArrayReduce, this, a, b); } // Warning: user exposed! -function TypedArrayScatterPar(a, b, c, d) { - return callFunction(TypedArrayScatter, this, a, b, c, d); +function TypedObjectArrayScatterPar(a, b, c, d) { + return callFunction(TypedObjectArrayScatter, this, a, b, c, d); } // Warning: user exposed! -function TypedArrayFilterPar(func) { - return callFunction(TypedArrayFilter, this, func); +function TypedObjectArrayFilterPar(func) { + return callFunction(TypedObjectArrayFilter, this, func); } // should eventually become macros diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/configure.in thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/configure.in --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/configure.in 2015-01-07 22:15:22.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/configure.in 2015-01-09 12:36:39.000000000 +0000 @@ -346,24 +346,21 @@ MOZ_METRO=) if test -n "$MOZ_METRO"; then AC_DEFINE(MOZ_METRO) - # Target the Windows 8 Kit - WINSDK_TARGETVER=602 - WINVER=502 -else - # Target the Windows 7 SDK by default - WINSDK_TARGETVER=601 - WINVER=502 fi +# Target the Windows 8.1 SDK by default +WINSDK_TARGETVER=603 +WINVER=502 + MOZ_ARG_WITH_STRING(windows-version, [ --with-windows-version=WINSDK_TARGETVER - Windows SDK version to target. Lowest version - currently allowed is 601, highest is 602], + Windows SDK version to target. Win8.1 (603) is + currently the minimum supported version.], WINSDK_TARGETVER=$withval) -# Currently only two sdk versions allowed, 601 and 602 +# Currently only version 603 is allowed case "$WINSDK_TARGETVER" in -601|602) +603) MOZ_WINSDK_TARGETVER=0${WINSDK_TARGETVER}0000 ;; @@ -495,7 +492,7 @@ AC_MSG_ERROR([windres version $WINDRES_VERSION or higher is required to build.]) fi - MOZ_WINSDK_MAXVER=0x06010000 + MOZ_WINSDK_MAXVER=0x06030000 fi # !GNU_CC AC_DEFINE_UNQUOTED(WINVER,0x$WINVER) @@ -2992,21 +2989,6 @@ fi dnl ======================================================== -dnl = Enable trace malloc -dnl ======================================================== -NS_TRACE_MALLOC=${MOZ_TRACE_MALLOC} -MOZ_ARG_ENABLE_BOOL(trace-malloc, -[ --enable-trace-malloc Enable malloc tracing], - NS_TRACE_MALLOC=1, - NS_TRACE_MALLOC= ) -if test "$NS_TRACE_MALLOC"; then - # Please, Mr. Linker Man, don't take away our symbol names - MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS= - AC_DEFINE(NS_TRACE_MALLOC) -fi -AC_SUBST(NS_TRACE_MALLOC) - -dnl ======================================================== dnl = Enable DMD dnl ======================================================== @@ -3015,9 +2997,6 @@ MOZ_DMD=1, MOZ_DMD= ) -if test "$NS_TRACE_MALLOC"; then # trace-malloc disables DMD - MOZ_DMD= -fi if test "$MOZ_DMD"; then AC_DEFINE(MOZ_DMD) @@ -3035,10 +3014,6 @@ MOZ_MEMORY=1, MOZ_MEMORY=) -if test "$NS_TRACE_MALLOC"; then - MOZ_MEMORY= -fi - if test "$MOZ_MEMORY"; then AC_DEFINE(MOZ_MEMORY) if test "x$MOZ_DEBUG" = "x1"; then @@ -3432,9 +3407,9 @@ AC_LANG_RESTORE fi -# Demangle only for debug or trace-malloc or DMD builds +# Demangle only for debug or DMD builds MOZ_DEMANGLE_SYMBOLS= -if test "$HAVE_DEMANGLE" && test "$MOZ_DEBUG" -o "$NS_TRACE_MALLOC" -o "$MOZ_DMD"; then +if test "$HAVE_DEMANGLE" && test "$MOZ_DEBUG" -o "$MOZ_DMD"; then MOZ_DEMANGLE_SYMBOLS=1 AC_DEFINE(MOZ_DEMANGLE_SYMBOLS) fi @@ -3674,7 +3649,7 @@ AC_DEFINE(JS_HAS_CTYPES) fi -if test "$MOZ_DEBUG" -o "$NS_TRACE_MALLOC" -o "$MOZ_DMD"; then +if test "$MOZ_DEBUG" -o "$MOZ_DMD"; then MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS= fi diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/ctypes/CTypes.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/ctypes/CTypes.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/ctypes/CTypes.cpp 2015-01-07 22:15:22.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/ctypes/CTypes.cpp 2015-01-09 12:36:39.000000000 +0000 @@ -2464,7 +2464,7 @@ } *static_cast(buffer) = ptr; break; - } if (val.isObject() && JS_IsTypedArrayObject(valObj)) { + } if (val.isObject() && JS_IsArrayBufferViewObject(valObj)) { // Same as ArrayBuffer, above, though note that this will take the offset // of the view into account. if(!CanConvertTypedArrayItemTo(baseType, valObj, cx)) { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/devtools/automation/arm-sim thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/devtools/automation/arm-sim --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/devtools/automation/arm-sim 2015-01-07 22:15:22.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/devtools/automation/arm-sim 2015-01-09 12:36:40.000000000 +0000 @@ -1,7 +1,6 @@ --enable-optimize --enable-debug --enable-stdcxx-compat ---enable-trace-malloc --disable-shared-js --enable-threadsafe --enable-arm-simulator diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/devtools/automation/generational thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/devtools/automation/generational --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/devtools/automation/generational 2015-01-07 22:15:22.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/devtools/automation/generational 2015-01-09 12:36:40.000000000 +0000 @@ -2,7 +2,6 @@ --enable-debug --enable-stdcxx-compat --enable-ctypes ---enable-trace-malloc --disable-shared-js --enable-exact-rooting --enable-gccompacting diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/devtools/automation/rootanalysis thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/devtools/automation/rootanalysis --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/devtools/automation/rootanalysis 2015-01-07 22:15:22.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/devtools/automation/rootanalysis 2015-01-09 12:36:40.000000000 +0000 @@ -2,7 +2,6 @@ --enable-debug --enable-stdcxx-compat --enable-ctypes ---enable-trace-malloc --disable-shared-js --enable-exact-rooting --enable-gcgenerational diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/devtools/rootAnalysis/loadCallgraph.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/devtools/rootAnalysis/loadCallgraph.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/devtools/rootAnalysis/loadCallgraph.js 2015-01-07 22:15:22.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/devtools/rootAnalysis/loadCallgraph.js 2015-01-09 12:36:40.000000000 +0000 @@ -160,7 +160,7 @@ suppressedFunctions[name] = true; } - for (var gcName of [ 'void js::gc::GCRuntime::collect(uint8, js::SliceBudget*, uint32, uint32)', + for (var gcName of [ 'void js::gc::GCRuntime::collect(uint8, js::SliceBudget, uint32)', 'void js::gc::GCRuntime::minorGC(uint32)', 'void js::gc::GCRuntime::minorGC(uint32)' ]) { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/gc/GCRuntime.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/gc/GCRuntime.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/gc/GCRuntime.h 2015-01-07 22:15:23.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/gc/GCRuntime.h 2015-01-09 12:36:41.000000000 +0000 @@ -317,8 +317,9 @@ } bool gcIfNeeded(JSContext *cx = nullptr); void gc(JSGCInvocationKind gckind, JS::gcreason::Reason reason); - void gcSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64_t millis = 0); - void gcFinalSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason); + void startGC(JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64_t millis = 0); + void gcSlice(JS::gcreason::Reason reason, int64_t millis = 0); + void finishGC(JS::gcreason::Reason reason); void gcDebugSlice(SliceBudget &budget); void runDebugGC(); @@ -550,7 +551,6 @@ ChunkPool expireEmptyChunkPool(bool shrinkBuffers, const AutoLockGC &lock); void freeEmptyChunks(JSRuntime *rt, const AutoLockGC &lock); void prepareToFreeChunk(ChunkInfo &info); - void releaseChunk(Chunk *chunk); friend class BackgroundAllocTask; friend class AutoMaybeStartBackgroundAllocation; @@ -558,10 +558,9 @@ void startBackgroundAllocTaskIfIdle(); void requestMajorGC(JS::gcreason::Reason reason); - void collect(bool incremental, SliceBudget &budget, JSGCInvocationKind gckind, - JS::gcreason::Reason reason); - bool gcCycle(bool incremental, SliceBudget &budget, JSGCInvocationKind gckind, - JS::gcreason::Reason reason); + SliceBudget defaultBudget(JS::gcreason::Reason reason, int64_t millis); + void collect(bool incremental, SliceBudget budget, JS::gcreason::Reason reason); + bool gcCycle(bool incremental, SliceBudget &budget, JS::gcreason::Reason reason); gcstats::ZoneGCStats scanZonesBeforeGC(); void budgetIncrementalGC(SliceBudget &budget); void resetIncrementalGC(const char *reason); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/gc/Marking.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/gc/Marking.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/gc/Marking.cpp 2015-01-07 22:15:23.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/gc/Marking.cpp 2015-01-09 12:36:41.000000000 +0000 @@ -1449,6 +1449,9 @@ if (type->newScript()) type->newScript()->trace(gcmarker); + if (TypeDescr *descr = type->maybeTypeDescr()) + PushMarkStack(gcmarker, descr); + if (type->interpretedFunction) PushMarkStack(gcmarker, type->interpretedFunction); } @@ -1472,6 +1475,11 @@ if (type->newScript()) type->newScript()->trace(trc); + if (JSObject *descr = type->maybeTypeDescr()) { + MarkObjectUnbarriered(trc, &descr, "type_descr"); + type->setTypeDescr(&descr->as()); + } + if (type->interpretedFunction) MarkObject(trc, &type->interpretedFunction, "type_function"); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/gc/Zone.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/gc/Zone.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/gc/Zone.cpp 2015-01-07 22:15:23.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/gc/Zone.cpp 2015-01-09 12:36:41.000000000 +0000 @@ -185,8 +185,7 @@ for (ZoneCellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) { JSScript *script = i.get(); - jit::FinishInvalidation(fop, script); - jit::FinishInvalidation(fop, script); + jit::FinishInvalidation(fop, script); /* * Discard baseline script if it's not marked as active. Note that diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/arm/Bailouts-arm.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/arm/Bailouts-arm.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/arm/Bailouts-arm.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/arm/Bailouts-arm.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -79,10 +79,7 @@ JSScript *script = ScriptFromCalleeToken(((JitFrameLayout *) framePointer_)->calleeToken()); JitActivation *activation = activations.activation()->asJit(); - if (activation->cx()->isForkJoinContext()) - topIonScript_ = script->parallelIonScript(); - else - topIonScript_ = script->ionScript(); + topIonScript_ = script->ionScript(); attachOnJitActivation(activations); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/arm/CodeGenerator-arm.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/arm/CodeGenerator-arm.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/arm/CodeGenerator-arm.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/arm/CodeGenerator-arm.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -60,10 +60,8 @@ masm.bind(&returnLabel_); #ifdef JS_TRACE_LOGGING - if (gen->info().executionMode() == SequentialExecution) { - emitTracelogStopEvent(TraceLogger_IonMonkey); - emitTracelogScriptStop(); - } + emitTracelogStopEvent(TraceLogger_IonMonkey); + emitTracelogScriptStop(); #endif masm.freeStack(frameSize()); @@ -150,7 +148,7 @@ // Push the frame size, so the handler can recover the IonScript. masm.ma_mov(Imm32(frameSize()), lr); - JitCode *handler = gen->jitRuntime()->getGenericBailoutHandler(gen->info().executionMode()); + JitCode *handler = gen->jitRuntime()->getGenericBailoutHandler(); masm.branch(handler); } @@ -2186,18 +2184,6 @@ } void -CodeGeneratorARM::visitForkJoinGetSlice(LForkJoinGetSlice *ins) -{ - MOZ_CRASH("NYI"); -} - -JitCode * -JitRuntime::generateForkJoinGetSliceStub(JSContext *cx) -{ - MOZ_CRASH("NYI"); -} - -void CodeGeneratorARM::memoryBarrier(MemoryBarrierBits barrier) { // On ARMv6 the optional argument (BarrierST, etc) is ignored. diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/arm/CodeGenerator-arm.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/arm/CodeGenerator-arm.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/arm/CodeGenerator-arm.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/arm/CodeGenerator-arm.h 2015-01-09 12:36:47.000000000 +0000 @@ -214,8 +214,6 @@ void visitAsmJSLoadFFIFunc(LAsmJSLoadFFIFunc *ins); void visitAsmJSPassStackArg(LAsmJSPassStackArg *ins); - void visitForkJoinGetSlice(LForkJoinGetSlice *ins); - void visitMemoryBarrier(LMemoryBarrier *ins); void generateInvalidateEpilogue(); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/arm/Lowering-arm.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/arm/Lowering-arm.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/arm/Lowering-arm.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/arm/Lowering-arm.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -551,12 +551,6 @@ } void -LIRGeneratorARM::visitForkJoinGetSlice(MForkJoinGetSlice *ins) -{ - MOZ_CRASH("NYI"); -} - -void LIRGeneratorARM::visitSimdBinaryArith(MSimdBinaryArith *ins) { MOZ_CRASH("NYI"); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/arm/Lowering-arm.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/arm/Lowering-arm.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/arm/Lowering-arm.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/arm/Lowering-arm.h 2015-01-09 12:36:47.000000000 +0000 @@ -38,12 +38,6 @@ bool needTempForPostBarrier() { return false; } - // x64 has a scratch register, so no need for another temp for dispatch - // ICs. - LDefinition tempForDispatchCache(MIRType outputType = MIRType_None) { - return LDefinition::BogusTemp(); - } - void lowerUntypedPhiInput(MPhi *phi, uint32_t inputPosition, LBlock *block, size_t lirIndex); void defineUntypedPhi(MPhi *phi, size_t lirIndex); void lowerForShift(LInstructionHelper<1, 2, 0> *ins, MDefinition *mir, MDefinition *lhs, @@ -106,7 +100,6 @@ void visitAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap *ins); void visitAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap *ins); void visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic *ins); - void visitForkJoinGetSlice(MForkJoinGetSlice *ins); void visitSimdBinaryArith(MSimdBinaryArith *ins); void visitSimdSelect(MSimdSelect *ins); void visitSimdSplatX4(MSimdSplatX4 *ins); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/arm/Trampoline-arm.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/arm/Trampoline-arm.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/arm/Trampoline-arm.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/arm/Trampoline-arm.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -15,11 +15,8 @@ #ifdef JS_ION_PERF # include "jit/PerfSpewer.h" #endif -#include "jit/ParallelFunctions.h" #include "jit/VMFunctions.h" -#include "jit/ExecutionMode-inl.h" - using namespace js; using namespace js::jit; @@ -416,7 +413,7 @@ } JitCode * -JitRuntime::generateArgumentsRectifier(JSContext *cx, ExecutionMode mode, void **returnAddrOut) +JitRuntime::generateArgumentsRectifier(JSContext *cx, void **returnAddrOut) { MacroAssembler masm(cx); masm.pushReturnAddress(); @@ -482,7 +479,7 @@ // Note that this code assumes the function is JITted. masm.andPtr(Imm32(CalleeTokenMask), r1); masm.ma_ldr(DTRAddr(r1, DtrOffImm(JSFunction::offsetOfNativeOrScript())), r3); - masm.loadBaselineOrIonRaw(r3, r3, mode, nullptr); + masm.loadBaselineOrIonRaw(r3, r3, nullptr); masm.ma_callJitHalfPush(r3); uint32_t returnOffset = masm.currentOffset(); @@ -642,33 +639,6 @@ masm.branch(bailoutTail); } -static void -GenerateParallelBailoutThunk(MacroAssembler &masm, uint32_t frameClass) -{ - // As GenerateBailoutThunk, except we return an error immediately. We do the - // bailout dance so that we can walk the stack and have accurate reporting - // of frame information. - - PushBailoutFrame(masm, frameClass, r0); - - // Parallel bailout is like parallel failure in that we unwind all the way - // to the entry frame. Reserve space for the frame pointer of the entry - // frame. - const int sizeOfEntryFramePointer = sizeof(uint8_t *) * 2; - masm.reserveStack(sizeOfEntryFramePointer); - masm.mov(sp, r1); - - masm.setupAlignedABICall(2); - masm.passABIArg(r0); - masm.passABIArg(r1); - masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, BailoutPar)); - - // Get the frame pointer of the entry frame and return. - masm.moveValue(MagicValue(JS_ION_ERROR), JSReturnOperand); - masm.ma_ldr(Address(sp, 0), sp); - masm.as_dtr(IsLoad, 32, PostIndex, pc, DTRAddr(sp, DtrOffImm(4))); -} - JitCode * JitRuntime::generateBailoutTable(JSContext *cx, uint32_t frameClass) { @@ -697,20 +667,10 @@ } JitCode * -JitRuntime::generateBailoutHandler(JSContext *cx, ExecutionMode mode) +JitRuntime::generateBailoutHandler(JSContext *cx) { MacroAssembler masm(cx); - - switch (mode) { - case SequentialExecution: - GenerateBailoutThunk(cx, masm, NO_FRAME_SIZE_CLASS_ID); - break; - case ParallelExecution: - GenerateParallelBailoutThunk(masm, NO_FRAME_SIZE_CLASS_ID); - break; - default: - MOZ_CRASH("No such execution mode"); - } + GenerateBailoutThunk(cx, masm, NO_FRAME_SIZE_CLASS_ID); Linker linker(masm); AutoFlushICache afc("BailoutHandler"); @@ -753,7 +713,8 @@ if (f.expectTailCall == NonTailCall) masm.pushReturnAddress(); - masm.enterExitFrameAndLoadContext(&f, cxreg, regs.getAny(), f.executionMode); + masm.enterExitFrame(&f); + masm.loadJSContext(cxreg); // Save the base of the argument set stored on the stack. Register argsBase = InvalidReg; @@ -841,10 +802,10 @@ // Test for failure. switch (f.failType()) { case Type_Object: - masm.branchTestPtr(Assembler::Zero, r0, r0, masm.failureLabel(f.executionMode)); + masm.branchTestPtr(Assembler::Zero, r0, r0, masm.failureLabel()); break; case Type_Bool: - masm.branchIfFalseBool(r0, masm.failureLabel(f.executionMode)); + masm.branchIfFalseBool(r0, masm.failureLabel()); break; default: MOZ_CRASH("unknown failure kind"); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/BaselineCompiler.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/BaselineCompiler.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/BaselineCompiler.cpp 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/BaselineCompiler.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -551,7 +551,7 @@ else if (needsEarlyStackCheck()) phase = CHECK_OVER_RECURSED; - if (!callVM(CheckOverRecursedWithExtraInfo, phase)) + if (!callVMNonOp(CheckOverRecursedWithExtraInfo, phase)) return false; masm.bind(&skipCall); @@ -626,7 +626,7 @@ masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg()); pushArg(R0.scratchReg()); - if (!callVM(HeavyweightFunPrologueInfo, phase)) + if (!callVMNonOp(HeavyweightFunPrologueInfo, phase)) return false; } } else { @@ -640,7 +640,7 @@ masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg()); pushArg(R0.scratchReg()); - if (!callVM(StrictEvalPrologueInfo, phase)) + if (!callVMNonOp(StrictEvalPrologueInfo, phase)) return false; } } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/BaselineDebugModeOSR.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/BaselineDebugModeOSR.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/BaselineDebugModeOSR.cpp 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/BaselineDebugModeOSR.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -350,8 +350,7 @@ // // Off to On: // A. From a "can call" stub. - // B. From a VM call (interrupt handler, debugger statement handler, - // throw). + // B. From a VM call. // H. From inside HandleExceptionBaseline. // // On to Off: @@ -473,25 +472,27 @@ bool popFrameReg; switch (kind) { - case ICEntry::Kind_CallVM: + case ICEntry::Kind_CallVM: { // Case B above. // - // Patching returns from an interrupt handler or the debugger - // statement handler is similar in that we can resume at the - // next op. + // Patching returns from a VM call. After fixing up the the + // continuation for unsynced values (the frame register is + // popped by the callVM trampoline), we resume at the + // return-from-callVM address. The assumption here is that all + // callVMs which can trigger debug mode OSR are the *only* + // callVMs generated for their respective pc locations in the + // baseline JIT code. // - // Throws are treated differently, as patching a throw means - // we are recompiling on-stack scripts from inside an - // onExceptionUnwind invocation. The resume address must be - // settled on the throwing pc and not its successor, so that - // Debugger.Frame may report the correct offset. Note we never - // actually resume execution there, and it is set for the sake - // of frame iterators. - if (!iter.baselineFrame()->isDebuggerHandlingException()) - pc += GetBytecodeLength(pc); - recompInfo->resumeAddr = bl->nativeCodeForPC(script, pc, &recompInfo->slotInfo); - popFrameReg = true; + // Get the slot info for the next pc, but ignore the code + // address. We get the code address from the + // return-from-callVM entry instead. + (void) bl->maybeNativeCodeForPC(script, pc + GetBytecodeLength(pc), + &recompInfo->slotInfo); + ICEntry &callVMEntry = bl->callVMEntryFromPCOffset(pcOffset); + recompInfo->resumeAddr = bl->returnAddressForIC(callVMEntry); + popFrameReg = false; break; + } case ICEntry::Kind_DebugTrap: // Case C above. @@ -906,12 +907,9 @@ return true; // |rv| is the value in ReturnReg. If true, in the case of the prologue, - // debug trap, and debugger statement handler, it means a forced return. - if (kind == ICEntry::Kind_DebugPrologue || - (kind == ICEntry::Kind_CallVM && JSOp(*info->pc) == JSOP_DEBUGGER)) - { + // it means a forced return. + if (kind == ICEntry::Kind_DebugPrologue) return rv; - } // N.B. The debug trap handler handles its own forced return, so no // need to deal with it here. @@ -934,13 +932,19 @@ return; } - // Read stack values and make sure R0 and R1 have the right values. - unsigned numUnsynced = info->slotInfo.numUnsynced(); - MOZ_ASSERT(numUnsynced <= 2); - if (numUnsynced > 0) - info->popValueInto(info->slotInfo.topSlotLocation(), vp); - if (numUnsynced > 1) - info->popValueInto(info->slotInfo.nextSlotLocation(), vp); + // Read stack values and make sure R0 and R1 have the right values if we + // aren't returning from a callVM. + // + // In the case of returning from a callVM, we don't need to restore R0 and + // R1 ourself since we'll return into code that does it if needed. + if (info->frameKind != ICEntry::Kind_CallVM) { + unsigned numUnsynced = info->slotInfo.numUnsynced(); + MOZ_ASSERT(numUnsynced <= 2); + if (numUnsynced > 0) + info->popValueInto(info->slotInfo.topSlotLocation(), vp); + if (numUnsynced > 1) + info->popValueInto(info->slotInfo.nextSlotLocation(), vp); + } // Scale stackAdjust. info->stackAdjust *= sizeof(Value); @@ -985,6 +989,53 @@ : baselineDebugModeOSRHandlerNoFrameRegPopAddr_; } +static void +EmitBaselineDebugModeOSRHandlerTail(MacroAssembler &masm, Register temp, bool returnFromCallVM) +{ + // Save real return address on the stack temporarily. + // + // If we're returning from a callVM, we don't need to worry about R0 and + // R1 but do need to propagate the original ReturnReg value. Otherwise we + // need to worry about R0 and R1 but can clobber ReturnReg. Indeed, on + // x86, R1 contains ReturnReg. + if (returnFromCallVM) { + masm.push(ReturnReg); + } else { + masm.pushValue(Address(temp, offsetof(BaselineDebugModeOSRInfo, valueR0))); + masm.pushValue(Address(temp, offsetof(BaselineDebugModeOSRInfo, valueR1))); + } + masm.push(BaselineFrameReg); + masm.push(Address(temp, offsetof(BaselineDebugModeOSRInfo, resumeAddr))); + + // Call a stub to free the allocated info. + masm.setupUnalignedABICall(1, temp); + masm.loadBaselineFramePtr(BaselineFrameReg, temp); + masm.passABIArg(temp); + masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, FinishBaselineDebugModeOSR)); + + // Restore saved values. + GeneralRegisterSet jumpRegs(GeneralRegisterSet::All()); + if (returnFromCallVM) { + jumpRegs.take(ReturnReg); + } else { + jumpRegs.take(R0); + jumpRegs.take(R1); + } + jumpRegs.take(BaselineFrameReg); + Register target = jumpRegs.takeAny(); + + masm.pop(target); + masm.pop(BaselineFrameReg); + if (returnFromCallVM) { + masm.pop(ReturnReg); + } else { + masm.popValue(R1); + masm.popValue(R0); + } + + masm.jump(target); +} + JitCode * JitRuntime::generateBaselineDebugModeOSRHandler(JSContext *cx, uint32_t *noFrameRegPopOffsetOut) { @@ -1005,6 +1056,7 @@ // Record the stack pointer for syncing. masm.movePtr(StackPointer, syncedStackStart); + masm.push(ReturnReg); masm.push(BaselineFrameReg); // Call a stub to fully initialize the info. @@ -1016,37 +1068,27 @@ masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, SyncBaselineDebugModeOSRInfo)); // Discard stack values depending on how many were unsynced, as we always - // have a fully synced stack in the recompile handler. See assert in - // DebugModeOSREntry constructor. + // have a fully synced stack in the recompile handler. We arrive here via + // a callVM, and prepareCallVM in BaselineCompiler always fully syncs the + // stack. masm.pop(BaselineFrameReg); + masm.pop(ReturnReg); masm.loadPtr(Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfScratchValue()), temp); masm.addPtr(Address(temp, offsetof(BaselineDebugModeOSRInfo, stackAdjust)), StackPointer); - // Save real return address on the stack temporarily. - masm.pushValue(Address(temp, offsetof(BaselineDebugModeOSRInfo, valueR0))); - masm.pushValue(Address(temp, offsetof(BaselineDebugModeOSRInfo, valueR1))); - masm.push(BaselineFrameReg); - masm.push(Address(temp, offsetof(BaselineDebugModeOSRInfo, resumeAddr))); - - // Call a stub to free the allocated info. - masm.setupUnalignedABICall(1, temp); - masm.loadBaselineFramePtr(BaselineFrameReg, temp); - masm.passABIArg(temp); - masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, FinishBaselineDebugModeOSR)); - - // Restore saved values. - GeneralRegisterSet jumpRegs(GeneralRegisterSet::All()); - jumpRegs.take(R0); - jumpRegs.take(R1); - jumpRegs.take(BaselineFrameReg); - Register target = jumpRegs.takeAny(); - - masm.pop(target); - masm.pop(BaselineFrameReg); - masm.popValue(R1); - masm.popValue(R0); - - masm.jump(target); + // Emit two tails for the case of returning from a callVM and all other + // cases, as the state we need to restore differs depending on the case. + Label returnFromCallVM, end; + masm.branch32(MacroAssembler::Equal, + Address(temp, offsetof(BaselineDebugModeOSRInfo, frameKind)), + Imm32(ICEntry::Kind_CallVM), + &returnFromCallVM); + + EmitBaselineDebugModeOSRHandlerTail(masm, temp, /* returnFromCallVM = */ false); + masm.jump(&end); + masm.bind(&returnFromCallVM); + EmitBaselineDebugModeOSRHandlerTail(masm, temp, /* returnFromCallVM = */ true); + masm.bind(&end); Linker linker(masm); AutoFlushICache afc("BaselineDebugModeOSRHandler"); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/BaselineIC.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/BaselineIC.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/BaselineIC.cpp 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/BaselineIC.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -4261,7 +4261,7 @@ Register code = regs.takeAnyExcluding(ArgumentsRectifierReg); masm.loadPtr(Address(callee, JSFunction::offsetOfNativeOrScript()), code); - masm.loadBaselineOrIonRaw(code, code, SequentialExecution, nullptr); + masm.loadBaselineOrIonRaw(code, code, nullptr); Register scratch = regs.takeAny(); @@ -4274,7 +4274,7 @@ MOZ_ASSERT(ArgumentsRectifierReg != code); JitCode *argumentsRectifier = - cx->runtime()->jitRuntime()->getArgumentsRectifier(SequentialExecution); + cx->runtime()->jitRuntime()->getArgumentsRectifier(); masm.movePtr(ImmGCPtr(argumentsRectifier), code); masm.loadPtr(Address(code, JitCode::offsetOfCode()), code); @@ -4494,8 +4494,7 @@ scratchReg); masm.branchIfFunctionHasNoScript(scratchReg, popR1 ? &failurePopR1 : &failure); masm.loadPtr(Address(scratchReg, JSFunction::offsetOfNativeOrScript()), scratchReg); - masm.loadBaselineOrIonRaw(scratchReg, scratchReg, SequentialExecution, - popR1 ? &failurePopR1 : &failure); + masm.loadBaselineOrIonRaw(scratchReg, scratchReg, popR1 ? &failurePopR1 : &failure); // At this point, we are guaranteed to successfully complete. if (popR1) @@ -7421,7 +7420,7 @@ masm.loadPtr(Address(BaselineStubReg, ICGetProp_CallScripted::offsetOfGetter()), callee); masm.branchIfFunctionHasNoScript(callee, &failureLeaveStubFrame); masm.loadPtr(Address(callee, JSFunction::offsetOfNativeOrScript()), code); - masm.loadBaselineOrIonRaw(code, code, SequentialExecution, &failureLeaveStubFrame); + masm.loadBaselineOrIonRaw(code, code, &failureLeaveStubFrame); // Getter is called with 0 arguments, just |obj| as thisv. // Note that we use Push, not push, so that callJit will align the stack @@ -7441,7 +7440,7 @@ MOZ_ASSERT(ArgumentsRectifierReg != code); JitCode *argumentsRectifier = - cx->runtime()->jitRuntime()->getArgumentsRectifier(SequentialExecution); + cx->runtime()->jitRuntime()->getArgumentsRectifier(); masm.movePtr(ImmGCPtr(argumentsRectifier), code); masm.loadPtr(Address(code, JitCode::offsetOfCode()), code); @@ -8793,7 +8792,7 @@ masm.loadPtr(Address(BaselineStubReg, ICSetProp_CallScripted::offsetOfSetter()), callee); masm.branchIfFunctionHasNoScript(callee, &failureLeaveStubFrame); masm.loadPtr(Address(callee, JSFunction::offsetOfNativeOrScript()), code); - masm.loadBaselineOrIonRaw(code, code, SequentialExecution, &failureLeaveStubFrame); + masm.loadBaselineOrIonRaw(code, code, &failureLeaveStubFrame); // Setter is called with the new value as the only argument, and |obj| as thisv. // Note that we use Push, not push, so that callJit will align the stack @@ -8818,7 +8817,7 @@ MOZ_ASSERT(ArgumentsRectifierReg != code); JitCode *argumentsRectifier = - cx->runtime()->jitRuntime()->getArgumentsRectifier(SequentialExecution); + cx->runtime()->jitRuntime()->getArgumentsRectifier(); masm.movePtr(ImmGCPtr(argumentsRectifier), code); masm.loadPtr(Address(code, JitCode::offsetOfCode()), code); @@ -9760,7 +9759,7 @@ masm.branchIfFunctionHasNoScript(target, failure); Register temp = regs.takeAny(); masm.loadPtr(Address(target, JSFunction::offsetOfNativeOrScript()), temp); - masm.loadBaselineOrIonRaw(temp, temp, SequentialExecution, failure); + masm.loadBaselineOrIonRaw(temp, temp, failure); regs.add(temp); } return target; @@ -9995,7 +9994,7 @@ Register code; if (!isConstructing_) { code = regs.takeAny(); - masm.loadBaselineOrIonRaw(callee, code, SequentialExecution, &failure); + masm.loadBaselineOrIonRaw(callee, code, &failure); } else { Address scriptCode(callee, JSScript::offsetOfBaselineOrIonRaw()); masm.branchPtr(Assembler::Equal, scriptCode, ImmPtr(nullptr), &failure); @@ -10079,7 +10078,7 @@ masm.loadPtr(Address(callee, JSFunction::offsetOfNativeOrScript()), callee); code = regs.takeAny(); - masm.loadBaselineOrIonRaw(callee, code, SequentialExecution, &failureLeaveStubFrame); + masm.loadBaselineOrIonRaw(callee, code, &failureLeaveStubFrame); // Release callee register, but don't add ExtractTemp0 back into the pool // ExtractTemp0 is used later, and if it's allocated to some other register at that @@ -10123,7 +10122,7 @@ MOZ_ASSERT(ArgumentsRectifierReg != argcReg); JitCode *argumentsRectifier = - cx->runtime()->jitRuntime()->getArgumentsRectifier(SequentialExecution); + cx->runtime()->jitRuntime()->getArgumentsRectifier(); masm.movePtr(ImmGCPtr(argumentsRectifier), code); masm.loadPtr(Address(code, JitCode::offsetOfCode()), code); @@ -10600,7 +10599,7 @@ // Load nargs into scratch for underflow check, and then load jitcode pointer into target. masm.load16ZeroExtend(Address(target, JSFunction::offsetOfNargs()), scratch); masm.loadPtr(Address(target, JSFunction::offsetOfNativeOrScript()), target); - masm.loadBaselineOrIonRaw(target, target, SequentialExecution, nullptr); + masm.loadBaselineOrIonRaw(target, target, nullptr); // Handle arguments underflow. Label noUnderflow; @@ -10611,7 +10610,7 @@ MOZ_ASSERT(ArgumentsRectifierReg != argcReg); JitCode *argumentsRectifier = - cx->runtime()->jitRuntime()->getArgumentsRectifier(SequentialExecution); + cx->runtime()->jitRuntime()->getArgumentsRectifier(); masm.movePtr(ImmGCPtr(argumentsRectifier), target); masm.loadPtr(Address(target, JitCode::offsetOfCode()), target); @@ -10701,7 +10700,7 @@ // Load nargs into scratch for underflow check, and then load jitcode pointer into target. masm.load16ZeroExtend(Address(target, JSFunction::offsetOfNargs()), scratch); masm.loadPtr(Address(target, JSFunction::offsetOfNativeOrScript()), target); - masm.loadBaselineOrIonRaw(target, target, SequentialExecution, nullptr); + masm.loadBaselineOrIonRaw(target, target, nullptr); // Handle arguments underflow. Label noUnderflow; @@ -10712,7 +10711,7 @@ MOZ_ASSERT(ArgumentsRectifierReg != argcReg); JitCode *argumentsRectifier = - cx->runtime()->jitRuntime()->getArgumentsRectifier(SequentialExecution); + cx->runtime()->jitRuntime()->getArgumentsRectifier(); masm.movePtr(ImmGCPtr(argumentsRectifier), target); masm.loadPtr(Address(target, JitCode::offsetOfCode()), target); @@ -10781,7 +10780,7 @@ // Load the start of the target JitCode. Register code = regs.takeAny(); - masm.loadBaselineOrIonRaw(callee, code, SequentialExecution, &failure); + masm.loadBaselineOrIonRaw(callee, code, &failure); // We no longer need R1. regs.add(R1); @@ -10834,7 +10833,7 @@ MOZ_ASSERT(ArgumentsRectifierReg != argcReg); JitCode *argumentsRectifier = - cx->runtime()->jitRuntime()->getArgumentsRectifier(SequentialExecution); + cx->runtime()->jitRuntime()->getArgumentsRectifier(); masm.movePtr(ImmGCPtr(argumentsRectifier), code); masm.loadPtr(Address(code, JitCode::offsetOfCode()), code); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/BaselineIC.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/BaselineIC.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/BaselineIC.h 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/BaselineIC.h 2015-01-09 12:36:47.000000000 +0000 @@ -222,9 +222,13 @@ // A non-op IC entry. Kind_NonOp, - // A fake IC entry for returning from a callVM. + // A fake IC entry for returning from a callVM for an op. Kind_CallVM, + // A fake IC entry for returning from a callVM not for an op (e.g., in + // the prologue). + Kind_NonOpCallVM, + // A fake IC entry for returning from DebugTrapHandler. Kind_DebugTrap, @@ -299,6 +303,10 @@ MOZ_ASSERT(kind() == Kind_CallVM); setKind(Kind_DebugEpilogue); } + void setForNonOpCallVM() { + MOZ_ASSERT(kind() == Kind_CallVM); + setKind(Kind_NonOpCallVM); + } bool hasStub() const { return firstStub_ != nullptr; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/BaselineJIT.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/BaselineJIT.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/BaselineJIT.cpp 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/BaselineJIT.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -563,16 +563,14 @@ return method()->raw() + ent.returnOffset().offset(); } -ICEntry & -BaselineScript::icEntryFromPCOffset(uint32_t pcOffset) +static inline size_t +ComputeBinarySearchMid(BaselineScript *baseline, uint32_t pcOffset) { - // Multiple IC entries can have the same PC offset, but this method only looks for - // those which have isForOp() set. size_t bottom = 0; - size_t top = numICEntries(); + size_t top = baseline->numICEntries(); size_t mid = bottom + (top - bottom) / 2; while (mid < top) { - ICEntry &midEntry = icEntry(mid); + ICEntry &midEntry = baseline->icEntry(mid); if (midEntry.pcOffset() < pcOffset) bottom = mid + 1; else if (midEntry.pcOffset() > pcOffset) @@ -581,6 +579,15 @@ break; mid = bottom + (top - bottom) / 2; } + return mid; +} + +ICEntry & +BaselineScript::icEntryFromPCOffset(uint32_t pcOffset) +{ + // Multiple IC entries can have the same PC offset, but this method only looks for + // those which have isForOp() set. + size_t mid = ComputeBinarySearchMid(this, pcOffset); // Found an IC entry with a matching PC offset. Search backward, and then // forward from this IC entry, looking for one with the same PC offset which @@ -619,6 +626,24 @@ return icEntryFromPCOffset(pcOffset); } +ICEntry & +BaselineScript::callVMEntryFromPCOffset(uint32_t pcOffset) +{ + // Like icEntryFromPCOffset, but only looks for the fake ICEntries + // inserted by VM calls. + size_t mid = ComputeBinarySearchMid(this, pcOffset); + + for (size_t i = mid; i < numICEntries() && icEntry(i).pcOffset() == pcOffset; i--) { + if (icEntry(i).kind() == ICEntry::Kind_CallVM) + return icEntry(i); + } + for (size_t i = mid+1; i < numICEntries() && icEntry(i).pcOffset() == pcOffset; i++) { + if (icEntry(i).kind() == ICEntry::Kind_CallVM) + return icEntry(i); + } + MOZ_CRASH("Invalid PC offset for callVM entry."); +} + ICEntry * BaselineScript::maybeICEntryFromReturnAddress(uint8_t *returnAddr) { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/BaselineJIT.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/BaselineJIT.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/BaselineJIT.h 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/BaselineJIT.h 2015-01-09 12:36:47.000000000 +0000 @@ -346,6 +346,7 @@ ICEntry &icEntryFromReturnOffset(CodeOffsetLabel returnOffset); ICEntry &icEntryFromPCOffset(uint32_t pcOffset); ICEntry &icEntryFromPCOffset(uint32_t pcOffset, ICEntry *prevLookedUpEntry); + ICEntry &callVMEntryFromPCOffset(uint32_t pcOffset); ICEntry *maybeICEntryFromReturnAddress(uint8_t *returnAddr); ICEntry &icEntryFromReturnAddress(uint8_t *returnAddr); uint8_t *returnAddressForIC(const ICEntry &ent); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/CodeGenerator.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/CodeGenerator.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/CodeGenerator.cpp 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/CodeGenerator.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -31,10 +31,7 @@ #include "jit/Lowering.h" #include "jit/MIRGenerator.h" #include "jit/MoveEmitter.h" -#include "jit/ParallelFunctions.h" -#include "jit/ParallelSafetyAnalysis.h" #include "jit/RangeAnalysis.h" -#include "vm/ForkJoin.h" #include "vm/MatchPairs.h" #include "vm/RegExpStatics.h" #include "vm/TraceLogging.h" @@ -167,10 +164,7 @@ } typedef bool (*StringToNumberFn)(ThreadSafeContext *, JSString *, double *); -typedef bool (*StringToNumberParFn)(ForkJoinContext *, JSString *, double *); -static const VMFunctionsModal StringToNumberInfo = VMFunctionsModal( - FunctionInfo(StringToNumber), - FunctionInfo(StringToNumberPar)); +static const VMFunction StringToNumberInfo = FunctionInfo(StringToNumber); void CodeGenerator::visitValueToInt32(LValueToInt32 *lir) @@ -821,10 +815,7 @@ } typedef JSFlatString *(*IntToStringFn)(ThreadSafeContext *, int); -typedef JSFlatString *(*IntToStringParFn)(ForkJoinContext *, int); -static const VMFunctionsModal IntToStringInfo = VMFunctionsModal( - FunctionInfo(Int32ToString), - FunctionInfo(IntToStringPar)); +static const VMFunction IntToStringInfo = FunctionInfo(Int32ToString); void CodeGenerator::visitIntToString(LIntToString *lir) @@ -841,10 +832,7 @@ } typedef JSString *(*DoubleToStringFn)(ThreadSafeContext *, double); -typedef JSString *(*DoubleToStringParFn)(ForkJoinContext *, double); -static const VMFunctionsModal DoubleToStringInfo = VMFunctionsModal( - FunctionInfo(NumberToString), - FunctionInfo(DoubleToStringPar)); +static const VMFunction DoubleToStringInfo = FunctionInfo(NumberToString); void CodeGenerator::visitDoubleToString(LDoubleToString *lir) @@ -864,10 +852,7 @@ } typedef JSString *(*PrimitiveToStringFn)(JSContext *, HandleValue); -typedef JSString *(*PrimitiveToStringParFn)(ForkJoinContext *, HandleValue); -static const VMFunctionsModal PrimitiveToStringInfo = VMFunctionsModal( - FunctionInfo(ToStringSlow), - FunctionInfo(PrimitiveToStringPar)); +static const VMFunction PrimitiveToStringInfo = FunctionInfo(ToStringSlow); void CodeGenerator::visitValueToString(LValueToString *lir) @@ -1766,22 +1751,6 @@ } void -CodeGenerator::visitLambdaPar(LLambdaPar *lir) -{ - Register resultReg = ToRegister(lir->output()); - Register cxReg = ToRegister(lir->forkJoinContext()); - Register scopeChainReg = ToRegister(lir->scopeChain()); - Register tempReg1 = ToRegister(lir->getTemp0()); - Register tempReg2 = ToRegister(lir->getTemp1()); - const LambdaFunctionInfo &info = lir->mir()->info(); - - MOZ_ASSERT(scopeChainReg != resultReg); - - emitAllocateGCThingPar(lir, resultReg, cxReg, tempReg1, tempReg2, info.fun); - emitLambdaInit(resultReg, scopeChainReg, info); -} - -void CodeGenerator::visitLabel(LLabel *lir) { } @@ -1853,10 +1822,7 @@ }; typedef bool (*InterruptCheckFn)(JSContext *); -typedef bool (*InterruptCheckParFn)(ForkJoinContext *); -static const VMFunctionsModal InterruptCheckInfo = VMFunctionsModal( - FunctionInfo(InterruptCheck), - FunctionInfo(InterruptCheckPar)); +static const VMFunction InterruptCheckInfo = FunctionInfo(InterruptCheck); void CodeGenerator::visitOutOfLineInterruptCheckImplicit(OutOfLineInterruptCheckImplicit *ool) @@ -2021,10 +1987,8 @@ setOsrEntryOffset(masm.size()); #ifdef JS_TRACE_LOGGING - if (gen->info().executionMode() == SequentialExecution) { - emitTracelogStopEvent(TraceLogger_Baseline); - emitTracelogStartEvent(TraceLogger_IonMonkey); - } + emitTracelogStopEvent(TraceLogger_Baseline); + emitTracelogStartEvent(TraceLogger_IonMonkey); #endif // Allocate the full frame for this function @@ -2453,30 +2417,6 @@ } void -CodeGenerator::visitForkJoinContext(LForkJoinContext *lir) -{ - const Register tempReg = ToRegister(lir->getTempReg()); - - masm.setupUnalignedABICall(0, tempReg); - masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, ForkJoinContextPar)); - MOZ_ASSERT(ToRegister(lir->output()) == ReturnReg); -} - -void -CodeGenerator::visitGuardThreadExclusive(LGuardThreadExclusive *lir) -{ - MOZ_ASSERT(gen->info().executionMode() == ParallelExecution); - - const Register tempReg = ToRegister(lir->getTempReg()); - masm.setupUnalignedABICall(2, tempReg); - masm.passABIArg(ToRegister(lir->forkJoinContext())); - masm.passABIArg(ToRegister(lir->object())); - masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, ParallelWriteGuard)); - - bailoutIfFalseBool(ReturnReg, lir->snapshot()); -} - -void CodeGenerator::visitGuardObjectIdentity(LGuardObjectIdentity *guard) { Register obj = ToRegister(guard->input()); @@ -2669,10 +2609,8 @@ masm.checkStackAlignment(); - // Sequential native functions have the signature: + // Native functions have the signature: // bool (*)(JSContext *, unsigned, Value *vp) - // and parallel native functions have the signature: - // ParallelResult (*)(ForkJoinContext *, unsigned, Value *vp) // Where vp[0] is space for an outparam, vp[1] is |this|, and vp[2] onward // are the function arguments. @@ -2684,12 +2622,7 @@ masm.Push(ObjectValue(*target)); // Preload arguments into registers. - // - // Note that for parallel execution, loadContext does an ABI call, so we - // need to do this before we load the other argument registers, otherwise - // we'll hose them. - ExecutionMode executionMode = gen->info().executionMode(); - masm.loadContext(argContextReg, tempReg, executionMode); + masm.loadJSContext(argContextReg); masm.move32(Imm32(call->numStackArgs()), argUintNReg); masm.movePtr(StackPointer, argVpReg); @@ -2698,8 +2631,7 @@ // Construct native exit frame. uint32_t safepointOffset; masm.buildFakeExitFrame(tempReg, &safepointOffset); - masm.enterFakeExitFrame(argContextReg, tempReg, executionMode, - NativeExitFrameLayout::Token()); + masm.enterFakeExitFrame(NativeExitFrameLayout::Token()); markSafepointAt(safepointOffset, call); @@ -2708,22 +2640,10 @@ masm.passABIArg(argContextReg); masm.passABIArg(argUintNReg); masm.passABIArg(argVpReg); - - switch (executionMode) { - case SequentialExecution: - masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, target->native())); - break; - - case ParallelExecution: - masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, target->parallelNative())); - break; - - default: - MOZ_CRASH("No such execution mode"); - } + masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, target->native())); // Test for failure. - masm.branchIfFalseBool(ReturnReg, masm.failureLabel(executionMode)); + masm.branchIfFalseBool(ReturnReg, masm.failureLabel()); // Load the outparam vp[0] into output register(s). masm.loadValue(Address(StackPointer, NativeExitFrameLayout::offsetOfResult()), JSReturnOperand); @@ -2908,14 +2828,13 @@ Register objreg = ToRegister(call->getTempObject()); Register nargsreg = ToRegister(call->getNargsReg()); uint32_t unusedStack = StackOffsetOfPassedArg(call->argslot()); - ExecutionMode executionMode = gen->info().executionMode(); Label invoke, thunk, makeCall, end; // Known-target case is handled by LCallKnown. MOZ_ASSERT(!call->hasSingleTarget()); // Generate an ArgumentsRectifier. - JitCode *argumentsRectifier = gen->jitRuntime()->getArgumentsRectifier(executionMode); + JitCode *argumentsRectifier = gen->jitRuntime()->getArgumentsRectifier(); masm.checkStackAlignment(); @@ -2934,7 +2853,7 @@ masm.loadPtr(Address(calleereg, JSFunction::offsetOfNativeOrScript()), objreg); // Load script jitcode. - masm.loadBaselineOrIonRaw(objreg, objreg, executionMode, &invoke); + masm.loadBaselineOrIonRaw(objreg, objreg, &invoke); // Nestle the StackPointer up to the argument vector. masm.freeStack(unusedStack); @@ -2972,18 +2891,7 @@ // Handle uncompiled or native functions. masm.bind(&invoke); - switch (executionMode) { - case SequentialExecution: - emitCallInvokeFunction(call, calleereg, call->numActualArgs(), unusedStack); - break; - - case ParallelExecution: - emitCallToUncompiledScriptPar(call, calleereg); - break; - - default: - MOZ_CRASH("No such execution mode"); - } + emitCallInvokeFunction(call, calleereg, call->numActualArgs(), unusedStack); masm.bind(&end); @@ -2999,20 +2907,6 @@ dropArguments(call->numStackArgs() + 1); } -typedef bool (*CallToUncompiledScriptParFn)(ForkJoinContext *, JSObject *); -static const VMFunction CallToUncompiledScriptParInfo = - FunctionInfo(CallToUncompiledScriptPar); - -// Generates a call to CallToUncompiledScriptPar() and then bails out. -// |calleeReg| should contain the JSFunction*. -void -CodeGenerator::emitCallToUncompiledScriptPar(LInstruction *lir, Register calleeReg) -{ - pushArg(calleeReg); - callVM(CallToUncompiledScriptParInfo, lir); - masm.assumeUnreachable("CallToUncompiledScriptParInfo always returns false."); -} - void CodeGenerator::visitCallKnown(LCallKnown *call) { @@ -3020,7 +2914,6 @@ Register objreg = ToRegister(call->getTempObject()); uint32_t unusedStack = StackOffsetOfPassedArg(call->argslot()); DebugOnly target = call->getSingleTarget(); - ExecutionMode executionMode = gen->info().executionMode(); Label end, uncompiled; // Native single targets are handled by LCallNative. @@ -3041,9 +2934,9 @@ // Load script jitcode. if (call->mir()->needsArgCheck()) - masm.loadBaselineOrIonRaw(objreg, objreg, executionMode, &uncompiled); + masm.loadBaselineOrIonRaw(objreg, objreg, &uncompiled); else - masm.loadBaselineOrIonNoArgCheck(objreg, objreg, executionMode, &uncompiled); + masm.loadBaselineOrIonNoArgCheck(objreg, objreg, &uncompiled); // Nestle the StackPointer up to the argument vector. masm.freeStack(unusedStack); @@ -3066,18 +2959,7 @@ // Handle uncompiled functions. masm.bind(&uncompiled); - switch (executionMode) { - case SequentialExecution: - emitCallInvokeFunction(call, calleereg, call->numActualArgs(), unusedStack); - break; - - case ParallelExecution: - emitCallToUncompiledScriptPar(call, calleereg); - break; - - default: - MOZ_CRASH("No such execution mode"); - } + emitCallInvokeFunction(call, calleereg, call->numActualArgs(), unusedStack); masm.bind(&end); @@ -3200,7 +3082,6 @@ masm.checkStackAlignment(); // If the function is known to be uncompilable, only emit the call to InvokeFunction. - ExecutionMode executionMode = gen->info().executionMode(); if (apply->hasSingleTarget()) { JSFunction *target = apply->getSingleTarget(); if (target->isNative()) { @@ -3224,7 +3105,7 @@ masm.loadPtr(Address(calleereg, JSFunction::offsetOfNativeOrScript()), objreg); // Load script jitcode. - masm.loadBaselineOrIonRaw(objreg, objreg, executionMode, &invoke); + masm.loadBaselineOrIonRaw(objreg, objreg, &invoke); // Call with an Ion frame or a rectifier frame. { @@ -3257,7 +3138,7 @@ masm.bind(&underflow); // Hardcode the address of the argumentsRectifier code. - JitCode *argumentsRectifier = gen->jitRuntime()->getArgumentsRectifier(executionMode); + JitCode *argumentsRectifier = gen->jitRuntime()->getArgumentsRectifier(); MOZ_ASSERT(ArgumentsRectifierReg != objreg); masm.movePtr(ImmGCPtr(argumentsRectifier), objreg); // Necessary for GC marking. @@ -3553,10 +3434,8 @@ } typedef bool (*CheckOverRecursedFn)(JSContext *); -typedef bool (*CheckOverRecursedParFn)(ForkJoinContext *); -static const VMFunctionsModal CheckOverRecursedInfo = VMFunctionsModal( - FunctionInfo(CheckOverRecursed), - FunctionInfo(CheckOverRecursedPar)); +static const VMFunction CheckOverRecursedInfo = + FunctionInfo(CheckOverRecursed); void CodeGenerator::visitCheckOverRecursedFailure(CheckOverRecursedFailure *ool) @@ -3575,42 +3454,6 @@ masm.jump(ool->rejoin()); } -void -CodeGenerator::visitCheckOverRecursedPar(LCheckOverRecursedPar *lir) -{ - // See above: unlike visitCheckOverRecursed(), this code runs in - // parallel mode and hence uses the jitStackLimit from the current - // thread state. Also, we must check the interrupt flags because - // on interrupt or abort, only the stack limit for the main thread - // is reset, not the worker threads. See comment in vm/ForkJoin.h - // for more details. - - Register cxReg = ToRegister(lir->forkJoinContext()); - Register tempReg = ToRegister(lir->getTempReg()); - - masm.loadPtr(Address(cxReg, offsetof(ForkJoinContext, perThreadData)), tempReg); - masm.loadPtr(Address(tempReg, PerThreadData::offsetOfJitStackLimit()), tempReg); - - // Conditional forward (unlikely) branch to failure. - CheckOverRecursedFailure *ool = new(alloc()) CheckOverRecursedFailure(lir); - addOutOfLineCode(ool, lir->mir()); - - masm.branchPtr(Assembler::BelowOrEqual, StackPointer, tempReg, ool->entry()); - masm.checkInterruptFlagPar(tempReg, ool->entry()); - masm.bind(ool->rejoin()); -} - -void -CodeGenerator::visitInterruptCheckPar(LInterruptCheckPar *lir) -{ - // First check for cx->shared->interrupt_. - OutOfLineCode *ool = oolCallVM(InterruptCheckInfo, lir, (ArgList()), StoreNothing()); - - Register tempReg = ToRegister(lir->getTempReg()); - masm.checkInterruptFlagPar(tempReg, ool->entry()); - masm.bind(ool->rejoin()); -} - IonScriptCounts * CodeGenerator::maybeCreateScriptCounts() { @@ -3773,35 +3616,33 @@ } // Check that we have a valid GC pointer. - if (gen->info().executionMode() != ParallelExecution) { - saveVolatile(); - masm.setupUnalignedABICall(2, temp); - masm.loadJSContext(temp); - masm.passABIArg(temp); - masm.passABIArg(output); - - void *callee; - switch (mir->type()) { - case MIRType_Object: - callee = JS_FUNC_TO_DATA_PTR(void *, AssertValidObjectPtr); - break; - case MIRType_ObjectOrNull: - callee = JS_FUNC_TO_DATA_PTR(void *, AssertValidObjectOrNullPtr); - break; - case MIRType_String: - callee = JS_FUNC_TO_DATA_PTR(void *, AssertValidStringPtr); - break; - case MIRType_Symbol: - callee = JS_FUNC_TO_DATA_PTR(void *, AssertValidSymbolPtr); - break; - default: - MOZ_CRASH(); - } + saveVolatile(); + masm.setupUnalignedABICall(2, temp); + masm.loadJSContext(temp); + masm.passABIArg(temp); + masm.passABIArg(output); - masm.callWithABINoProfiling(callee); - restoreVolatile(); + void *callee; + switch (mir->type()) { + case MIRType_Object: + callee = JS_FUNC_TO_DATA_PTR(void *, AssertValidObjectPtr); + break; + case MIRType_ObjectOrNull: + callee = JS_FUNC_TO_DATA_PTR(void *, AssertValidObjectOrNullPtr); + break; + case MIRType_String: + callee = JS_FUNC_TO_DATA_PTR(void *, AssertValidStringPtr); + break; + case MIRType_Symbol: + callee = JS_FUNC_TO_DATA_PTR(void *, AssertValidSymbolPtr); + break; + default: + MOZ_CRASH(); } + masm.callWithABINoProfiling(callee); + restoreVolatile(); + masm.bind(&done); masm.pop(temp); } @@ -3844,20 +3685,18 @@ } // Check that we have a valid GC pointer. - if (gen->info().executionMode() != ParallelExecution) { - saveVolatile(); + saveVolatile(); - masm.pushValue(output); - masm.movePtr(StackPointer, temp1); + masm.pushValue(output); + masm.movePtr(StackPointer, temp1); - masm.setupUnalignedABICall(2, temp2); - masm.loadJSContext(temp2); - masm.passABIArg(temp2); - masm.passABIArg(temp1); - masm.callWithABINoProfiling(JS_FUNC_TO_DATA_PTR(void *, AssertValidValue)); - masm.popValue(output); - restoreVolatile(); - } + masm.setupUnalignedABICall(2, temp2); + masm.loadJSContext(temp2); + masm.passABIArg(temp2); + masm.passABIArg(temp1); + masm.callWithABINoProfiling(JS_FUNC_TO_DATA_PTR(void *, AssertValidValue)); + masm.popValue(output); + restoreVolatile(); masm.bind(&done); masm.pop(temp2); @@ -4013,8 +3852,6 @@ void CodeGenerator::visitNewArrayCallVM(LNewArray *lir) { - MOZ_ASSERT(gen->info().executionMode() == SequentialExecution); - Register objReg = ToRegister(lir->output()); MOZ_ASSERT(!lir->isCall()); @@ -4046,9 +3883,6 @@ void CodeGenerator::visitNewDerivedTypedObject(LNewDerivedTypedObject *lir) { - // Not yet made safe for par exec: - MOZ_ASSERT(gen->info().executionMode() == SequentialExecution); - pushArg(ToRegister(lir->offset())); pushArg(ToRegister(lir->owner())); pushArg(ToRegister(lir->type())); @@ -4088,7 +3922,6 @@ void CodeGenerator::visitNewArray(LNewArray *lir) { - MOZ_ASSERT(gen->info().executionMode() == SequentialExecution); Register objReg = ToRegister(lir->output()); Register tempReg = ToRegister(lir->temp()); ArrayObject *templateObject = lir->mir()->templateObject(); @@ -4204,8 +4037,6 @@ void CodeGenerator::visitNewObjectVMCall(LNewObject *lir) { - MOZ_ASSERT(gen->info().executionMode() == SequentialExecution); - Register objReg = ToRegister(lir->output()); MOZ_ASSERT(!lir->isCall()); @@ -4315,7 +4146,6 @@ void CodeGenerator::visitNewObject(LNewObject *lir) { - MOZ_ASSERT(gen->info().executionMode() == SequentialExecution); Register objReg = ToRegister(lir->output()); Register tempReg = ToRegister(lir->temp()); PlainObject *templateObject = lir->mir()->templateObject(); @@ -4442,45 +4272,6 @@ masm.bind(ool->rejoin()); } -void -CodeGenerator::visitNewCallObjectPar(LNewCallObjectPar *lir) -{ - Register resultReg = ToRegister(lir->output()); - Register cxReg = ToRegister(lir->forkJoinContext()); - Register tempReg1 = ToRegister(lir->getTemp0()); - Register tempReg2 = ToRegister(lir->getTemp1()); - CallObject *templateObj = lir->mir()->templateObj(); - - emitAllocateGCThingPar(lir, resultReg, cxReg, tempReg1, tempReg2, templateObj); -} - -typedef ArrayObject *(*ExtendArrayParFn)(ForkJoinContext*, ArrayObject*, uint32_t); -static const VMFunction ExtendArrayParInfo = - FunctionInfo(ExtendArrayPar); - -void -CodeGenerator::visitNewDenseArrayPar(LNewDenseArrayPar *lir) -{ - Register cxReg = ToRegister(lir->forkJoinContext()); - Register lengthReg = ToRegister(lir->length()); - Register tempReg0 = ToRegister(lir->getTemp0()); - Register tempReg1 = ToRegister(lir->getTemp1()); - Register tempReg2 = ToRegister(lir->getTemp2()); - ArrayObject *templateObj = lir->mir()->templateObject(); - - emitAllocateGCThingPar(lir, tempReg2, cxReg, tempReg0, tempReg1, templateObj); - - // Invoke a C helper to allocate the elements. The helper returns - // nullptr on allocation error or the array object. - - saveLive(lir); - pushArg(lengthReg); - pushArg(tempReg2); - callVM(ExtendArrayParInfo, lir); - storeResultTo(ToRegister(lir->output())); - restoreLive(lir); -} - typedef JSObject *(*NewStringObjectFn)(JSContext *, HandleString); static const VMFunction NewStringObjectInfo = FunctionInfo(NewStringObject); @@ -4506,76 +4297,6 @@ masm.bind(ool->rejoin()); } -void -CodeGenerator::visitNewPar(LNewPar *lir) -{ - Register objReg = ToRegister(lir->output()); - Register cxReg = ToRegister(lir->forkJoinContext()); - Register tempReg1 = ToRegister(lir->getTemp0()); - Register tempReg2 = ToRegister(lir->getTemp1()); - NativeObject *templateObject = lir->mir()->templateObject(); - emitAllocateGCThingPar(lir, objReg, cxReg, tempReg1, tempReg2, templateObject); -} - -class OutOfLineNewGCThingPar : public OutOfLineCodeBase -{ -public: - LInstruction *lir; - gc::AllocKind allocKind; - Register objReg; - Register cxReg; - - OutOfLineNewGCThingPar(LInstruction *lir, gc::AllocKind allocKind, Register objReg, - Register cxReg) - : lir(lir), allocKind(allocKind), objReg(objReg), cxReg(cxReg) - {} - - void accept(CodeGenerator *codegen) { - codegen->visitOutOfLineNewGCThingPar(this); - } -}; - -typedef JSObject *(*NewGCThingParFn)(ForkJoinContext *, js::gc::AllocKind allocKind); -static const VMFunction NewGCThingParInfo = - FunctionInfo(NewGCThingPar); - -void -CodeGenerator::emitAllocateGCThingPar(LInstruction *lir, Register objReg, Register cxReg, - Register tempReg1, Register tempReg2, NativeObject *templateObj) -{ - MOZ_ASSERT(lir->mirRaw()); - MOZ_ASSERT(lir->mirRaw()->isInstruction()); - - gc::AllocKind allocKind = templateObj->asTenured().getAllocKind(); - OutOfLineNewGCThingPar *ool = new(alloc()) OutOfLineNewGCThingPar(lir, allocKind, objReg, cxReg); - addOutOfLineCode(ool, lir->mirRaw()->toInstruction()); - - masm.newGCThingPar(objReg, cxReg, tempReg1, tempReg2, templateObj, ool->entry()); - masm.bind(ool->rejoin()); - masm.initGCThing(objReg, tempReg1, templateObj); -} - -void -CodeGenerator::visitOutOfLineNewGCThingPar(OutOfLineNewGCThingPar *ool) -{ - // As a fallback for allocation in par. exec. mode, we invoke the - // C helper NewGCThingPar(), which calls into the GC code. If it - // returns nullptr, we bail. If returns non-nullptr, we rejoin the - // original instruction. - Register out = ool->objReg; - - saveVolatile(out); - masm.setupUnalignedABICall(2, out); - masm.passABIArg(ool->cxReg); - masm.move32(Imm32(ool->allocKind), out); - masm.passABIArg(out); - masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, NewGCThingPar)); - masm.storeCallResult(out); - restoreVolatile(out); - - bailoutTestPtr(Assembler::Zero, out, out, ool->lir->snapshot()); -} - typedef bool(*InitElemFn)(JSContext *cx, HandleObject obj, HandleValue id, HandleValue value); static const VMFunction InitElemInfo = @@ -5187,16 +4908,13 @@ } typedef bool (*BinaryFn)(JSContext *, MutableHandleValue, MutableHandleValue, MutableHandleValue); -typedef bool (*BinaryParFn)(ForkJoinContext *, HandleValue, HandleValue, MutableHandleValue); static const VMFunction AddInfo = FunctionInfo(js::AddValues); static const VMFunction SubInfo = FunctionInfo(js::SubValues); static const VMFunction MulInfo = FunctionInfo(js::MulValues); static const VMFunction DivInfo = FunctionInfo(js::DivValues); static const VMFunction ModInfo = FunctionInfo(js::ModValues); -static const VMFunctionsModal UrshInfo = VMFunctionsModal( - FunctionInfo(js::UrshValues), - FunctionInfo(UrshValuesPar)); +static const VMFunction UrshInfo = FunctionInfo(js::UrshValues); void CodeGenerator::visitBinaryV(LBinaryV *lir) @@ -5235,13 +4953,10 @@ } typedef bool (*StringCompareFn)(JSContext *, HandleString, HandleString, bool *); -typedef bool (*StringCompareParFn)(ForkJoinContext *, HandleString, HandleString, bool *); -static const VMFunctionsModal StringsEqualInfo = VMFunctionsModal( - FunctionInfo(jit::StringsEqual), - FunctionInfo(jit::StringsEqualPar)); -static const VMFunctionsModal StringsNotEqualInfo = VMFunctionsModal( - FunctionInfo(jit::StringsEqual), - FunctionInfo(jit::StringsUnequalPar)); +static const VMFunction StringsEqualInfo = + FunctionInfo(jit::StringsEqual); +static const VMFunction StringsNotEqualInfo = + FunctionInfo(jit::StringsEqual); void CodeGenerator::emitCompareS(LInstruction *lir, JSOp op, Register left, Register right, @@ -5299,31 +5014,14 @@ } typedef bool (*CompareFn)(JSContext *, MutableHandleValue, MutableHandleValue, bool *); -typedef bool (*CompareParFn)(ForkJoinContext *, MutableHandleValue, MutableHandleValue, bool *); -static const VMFunctionsModal EqInfo = VMFunctionsModal( - FunctionInfo(jit::LooselyEqual), - FunctionInfo(jit::LooselyEqualPar)); -static const VMFunctionsModal NeInfo = VMFunctionsModal( - FunctionInfo(jit::LooselyEqual), - FunctionInfo(jit::LooselyUnequalPar)); -static const VMFunctionsModal StrictEqInfo = VMFunctionsModal( - FunctionInfo(jit::StrictlyEqual), - FunctionInfo(jit::StrictlyEqualPar)); -static const VMFunctionsModal StrictNeInfo = VMFunctionsModal( - FunctionInfo(jit::StrictlyEqual), - FunctionInfo(jit::StrictlyUnequalPar)); -static const VMFunctionsModal LtInfo = VMFunctionsModal( - FunctionInfo(jit::LessThan), - FunctionInfo(jit::LessThanPar)); -static const VMFunctionsModal LeInfo = VMFunctionsModal( - FunctionInfo(jit::LessThanOrEqual), - FunctionInfo(jit::LessThanOrEqualPar)); -static const VMFunctionsModal GtInfo = VMFunctionsModal( - FunctionInfo(jit::GreaterThan), - FunctionInfo(jit::GreaterThanPar)); -static const VMFunctionsModal GeInfo = VMFunctionsModal( - FunctionInfo(jit::GreaterThanOrEqual), - FunctionInfo(jit::GreaterThanOrEqualPar)); +static const VMFunction EqInfo = FunctionInfo(jit::LooselyEqual); +static const VMFunction NeInfo = FunctionInfo(jit::LooselyEqual); +static const VMFunction StrictEqInfo = FunctionInfo(jit::StrictlyEqual); +static const VMFunction StrictNeInfo = FunctionInfo(jit::StrictlyEqual); +static const VMFunction LtInfo = FunctionInfo(jit::LessThan); +static const VMFunction LeInfo = FunctionInfo(jit::LessThanOrEqual); +static const VMFunction GtInfo = FunctionInfo(jit::GreaterThan); +static const VMFunction GeInfo = FunctionInfo(jit::GreaterThanOrEqual); void CodeGenerator::visitCompareVM(LCompareVM *lir) @@ -5584,10 +5282,7 @@ } typedef JSString *(*ConcatStringsFn)(ThreadSafeContext *, HandleString, HandleString); -typedef JSString *(*ConcatStringsParFn)(ForkJoinContext *, HandleString, HandleString); -static const VMFunctionsModal ConcatStringsInfo = VMFunctionsModal( - FunctionInfo(ConcatStrings), - FunctionInfo(ConcatStringsPar)); +static const VMFunction ConcatStringsInfo = FunctionInfo(ConcatStrings); void CodeGenerator::emitConcat(LInstruction *lir, Register lhs, Register rhs, Register output) @@ -5595,8 +5290,7 @@ OutOfLineCode *ool = oolCallVM(ConcatStringsInfo, lir, (ArgList(), lhs, rhs), StoreRegisterTo(output)); - ExecutionMode mode = gen->info().executionMode(); - JitCode *stringConcatStub = gen->compartment->jitCompartment()->stringConcatStubNoBarrier(mode); + JitCode *stringConcatStub = gen->compartment->jitCompartment()->stringConcatStubNoBarrier(); masm.call(stringConcatStub); masm.branchTestPtr(Assembler::Zero, output, output, ool->entry()); @@ -5623,26 +5317,6 @@ emitConcat(lir, lhs, rhs, output); } -void -CodeGenerator::visitConcatPar(LConcatPar *lir) -{ - DebugOnly cx = ToRegister(lir->forkJoinContext()); - Register lhs = ToRegister(lir->lhs()); - Register rhs = ToRegister(lir->rhs()); - Register output = ToRegister(lir->output()); - - MOZ_ASSERT(lhs == CallTempReg0); - MOZ_ASSERT(rhs == CallTempReg1); - MOZ_ASSERT((Register)cx == CallTempReg4); - MOZ_ASSERT(ToRegister(lir->temp1()) == CallTempReg0); - MOZ_ASSERT(ToRegister(lir->temp2()) == CallTempReg1); - MOZ_ASSERT(ToRegister(lir->temp3()) == CallTempReg2); - MOZ_ASSERT(ToRegister(lir->temp4()) == CallTempReg3); - MOZ_ASSERT(output == CallTempReg5); - - emitConcat(lir, lhs, rhs, output); -} - static void CopyStringChars(MacroAssembler &masm, Register to, Register from, Register len, Register byteOpScratch, size_t fromWidth, size_t toWidth) @@ -5703,8 +5377,8 @@ static void ConcatFatInlineString(MacroAssembler &masm, Register lhs, Register rhs, Register output, - Register temp1, Register temp2, Register temp3, Register forkJoinContext, - ExecutionMode mode, Label *failure, Label *failurePopTemps, bool isTwoByte) + Register temp1, Register temp2, Register temp3, + Label *failure, Label *failurePopTemps, bool isTwoByte) { // State: result length in temp2. @@ -5713,20 +5387,7 @@ masm.branchIfRope(rhs, failure); // Allocate a JSFatInlineString. - switch (mode) { - case SequentialExecution: - masm.newGCFatInlineString(output, temp1, failure); - break; - case ParallelExecution: - masm.push(temp1); - masm.push(temp2); - masm.newGCFatInlineStringPar(output, forkJoinContext, temp1, temp2, failurePopTemps); - masm.pop(temp2); - masm.pop(temp1); - break; - default: - MOZ_CRASH("No such execution mode"); - } + masm.newGCFatInlineString(output, temp1, failure); // Store length and flags. uint32_t flags = JSString::INIT_FAT_INLINE_FLAGS; @@ -5739,12 +5400,6 @@ masm.computeEffectiveAddress(Address(output, JSInlineString::offsetOfInlineStorage()), temp2); { - // We use temp3 in this block, which in parallel execution also holds - // a live ForkJoinContext pointer. If we are compiling for parallel - // execution, be sure to save and restore the ForkJoinContext. - if (mode == ParallelExecution) - masm.push(temp3); - // Copy lhs chars. Note that this advances temp2 to point to the next // char. This also clobbers the lhs register. if (isTwoByte) { @@ -5769,9 +5424,6 @@ masm.store16(Imm32(0), Address(temp2, 0)); else masm.store8(Imm32(0), Address(temp2, 0)); - - if (mode == ParallelExecution) - masm.pop(temp3); } masm.ret(); @@ -5896,7 +5548,7 @@ } JitCode * -JitCompartment::generateStringConcatStub(JSContext *cx, ExecutionMode mode) +JitCompartment::generateStringConcatStub(JSContext *cx) { MacroAssembler masm(cx); @@ -5907,11 +5559,6 @@ Register temp3 = CallTempReg4; Register output = CallTempReg5; - // In parallel execution, we pass in the ForkJoinContext in CallTempReg4, as - // by the time we need to use the temp3 we no longer have need of the - // cx. - Register forkJoinContext = CallTempReg4; - Label failure, failurePopTemps; #ifdef JS_USE_LINK_REGISTER masm.pushReturnAddress(); @@ -5954,20 +5601,7 @@ masm.branch32(Assembler::Above, temp2, Imm32(JSString::MAX_LENGTH), &failure); // Allocate a new rope. - switch (mode) { - case SequentialExecution: - masm.newGCString(output, temp3, &failure); - break; - case ParallelExecution: - masm.push(temp1); - masm.push(temp2); - masm.newGCStringPar(output, forkJoinContext, temp1, temp2, &failurePopTemps); - masm.pop(temp2); - masm.pop(temp1); - break; - default: - MOZ_CRASH("No such execution mode"); - } + masm.newGCString(output, temp3, &failure); // Store rope length and flags. temp1 still holds the result of AND'ing the // lhs and rhs flags, so we just have to clear the other flags to get our @@ -5991,12 +5625,12 @@ masm.ret(); masm.bind(&isFatInlineTwoByte); - ConcatFatInlineString(masm, lhs, rhs, output, temp1, temp2, temp3, forkJoinContext, - mode, &failure, &failurePopTemps, true); + ConcatFatInlineString(masm, lhs, rhs, output, temp1, temp2, temp3, + &failure, &failurePopTemps, true); masm.bind(&isFatInlineLatin1); - ConcatFatInlineString(masm, lhs, rhs, output, temp1, temp2, temp3, forkJoinContext, - mode, &failure, &failurePopTemps, false); + ConcatFatInlineString(masm, lhs, rhs, output, temp1, temp2, temp3, + &failure, &failurePopTemps, false); masm.bind(&failurePopTemps); masm.pop(temp2); @@ -6525,10 +6159,7 @@ typedef bool (*SetDenseElementFn)(JSContext *, HandleNativeObject, int32_t, HandleValue, bool strict); -typedef bool (*SetDenseElementParFn)(ForkJoinContext *, HandleObject, int32_t, HandleValue, bool); -static const VMFunctionsModal SetDenseElementInfo = VMFunctionsModal( - FunctionInfo(SetDenseElement), - FunctionInfo(SetDenseElementPar)); +static const VMFunction SetDenseElementInfo = FunctionInfo(SetDenseElement); void CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole *ool) @@ -7156,11 +6787,8 @@ typedef JSObject *(*InitRestParameterFn)(JSContext *, uint32_t, Value *, HandleObject, HandleObject); -typedef JSObject *(*InitRestParameterParFn)(ForkJoinContext *, uint32_t, Value *, - HandleObject, HandleArrayObject); -static const VMFunctionsModal InitRestParameterInfo = VMFunctionsModal( - FunctionInfo(InitRestParameter), - FunctionInfo(InitRestParameterPar)); +static const VMFunction InitRestParameterInfo = + FunctionInfo(InitRestParameter); void CodeGenerator::emitRest(LInstruction *lir, Register array, Register numActuals, @@ -7222,24 +6850,6 @@ emitRest(lir, temp2, numActuals, temp0, temp1, numFormals, templateObject, false, ToRegister(lir->output())); } -// LRestPar cannot derive from LCallInstructionHelper because emitAllocateGCThingPar may -// itself contain a VM call. Thus there's some manual work here and in emitRest(). - -void -CodeGenerator::visitRestPar(LRestPar *lir) -{ - Register numActuals = ToRegister(lir->numActuals()); - Register cx = ToRegister(lir->forkJoinContext()); - Register temp0 = ToRegister(lir->getTemp(0)); - Register temp1 = ToRegister(lir->getTemp(1)); - Register temp2 = ToRegister(lir->getTemp(2)); - unsigned numFormals = lir->mir()->numFormals(); - ArrayObject *templateObject = lir->mir()->templateObject(); - - emitAllocateGCThingPar(lir, temp2, cx, temp0, temp1, templateObject); - emitRest(lir, temp2, numActuals, temp0, temp1, numFormals, templateObject, true, ToRegister(lir->output())); -} - bool CodeGenerator::generateAsmJS(AsmJSFunctionLabels *labels) { @@ -7339,7 +6949,7 @@ masm.bind(&skipPrologue); #ifdef JS_TRACE_LOGGING - if (!gen->compilingAsmJS() && gen->info().executionMode() == SequentialExecution) { + if (!gen->compilingAsmJS()) { emitTracelogScriptStart(); emitTracelogStartEvent(TraceLogger_IonMonkey); } @@ -7423,19 +7033,14 @@ ExecutionMode executionMode = gen->info().executionMode(); OptimizationLevel optimizationLevel = gen->optimizationInfo().level(); - MOZ_ASSERT_IF(HasIonScript(script, executionMode), executionMode == SequentialExecution); - // We finished the new IonScript. Invalidate the current active IonScript, // so we can replace it with this new (probably higher optimized) version. if (HasIonScript(script, executionMode)) { MOZ_ASSERT(GetIonScript(script, executionMode)->isRecompiling()); // Do a normal invalidate, except don't cancel offThread compilations, // since that will cancel this compilation too. - if (!Invalidate(cx, script, SequentialExecution, - /* resetUses */ false, /* cancelOffThread*/ false)) - { + if (!Invalidate(cx, script, /* resetUses */ false, /* cancelOffThread*/ false)) return false; - } } if (scriptCounts_ && !script->hasScriptCounts() && !script->initScriptCounts(cx)) @@ -7462,12 +7067,6 @@ // We encode safepoints after the OSI-point offsets have been determined. encodeSafepoints(); - // List of possible scripts that this graph may call. Currently this is - // only tracked when compiling for parallel execution. - CallTargetVector callTargets(alloc()); - if (executionMode == ParallelExecution) - AddPossibleCallees(cx, graph.mir(), callTargets); - AutoDiscardIonCode discardIonCode(cx, &recompileInfo); IonScript *ionScript = @@ -7477,8 +7076,7 @@ recovers_.size(), bailouts_.length(), graph.numConstants(), safepointIndices_.length(), osiIndices_.length(), cacheList_.length(), runtimeData_.length(), - safepoints_.size(), callTargets.length(), - patchableBackedges_.length(), optimizationLevel); + safepoints_.size(), patchableBackedges_.length(), optimizationLevel); if (!ionScript) return false; discardIonCode.ionScript = ionScript; @@ -7488,9 +7086,7 @@ // read barriers which were skipped while compiling the script off thread. Linker linker(masm); AutoFlushICache afc("IonLink"); - JitCode *code = (executionMode == SequentialExecution) - ? linker.newCodeForIonScript(cx) - : linker.newCode(cx, ION_CODE); + JitCode *code = linker.newCodeForIonScript(cx); if (!code) return false; @@ -7550,12 +7146,6 @@ SetIonScript(cx, script, executionMode, ionScript); - // In parallel execution mode, when we first compile a script, we - // don't know that its potential callees are compiled, so set a - // flag warning that the callees may not be fully compiled. - if (!callTargets.empty()) - ionScript->setHasUncompiledCallTarget(); - invalidateEpilogueData_.fixup(&masm); Assembler::PatchDataWithValueCheck(CodeLocationLabel(code, invalidateEpilogueData_), ImmPtr(ionScript), @@ -7608,8 +7198,6 @@ ionScript->copyRecovers(&recovers_); if (graph.numConstants()) ionScript->copyConstants(graph.constantPool()); - if (callTargets.length() > 0) - ionScript->copyCallTargetEntries(callTargets.begin()); if (patchableBackedges_.length() > 0) ionScript->copyPatchableBackedges(cx, code, patchableBackedges_.begin(), masm); @@ -7636,21 +7224,11 @@ } #endif - switch (executionMode) { - case SequentialExecution: - // The correct state for prebarriers is unknown until the end of compilation, - // since a GC can occur during code generation. All barriers are emitted - // off-by-default, and are toggled on here if necessary. - if (cx->zone()->needsIncrementalBarrier()) - ionScript->toggleBarriers(true); - break; - case ParallelExecution: - // We don't run incremental GC during parallel execution; no need to - // turn on barriers. - break; - default: - MOZ_CRASH("No such execution mode"); - } + // The correct state for prebarriers is unknown until the end of compilation, + // since a GC can occur during code generation. All barriers are emitted + // off-by-default, and are toggled on here if necessary. + if (cx->zone()->needsIncrementalBarrier()) + ionScript->toggleBarriers(true); // Attach any generated script counts to the script. if (IonScriptCounts *counts = extractScriptCounts()) @@ -7753,10 +7331,7 @@ typedef bool (*SetObjectElementFn)(JSContext *, HandleObject, HandleValue, HandleValue, bool strict); -typedef bool (*SetElementParFn)(ForkJoinContext *, HandleObject, HandleValue, HandleValue, bool); -static const VMFunctionsModal SetObjectElementInfo = VMFunctionsModal( - FunctionInfo(SetObjectElement), - FunctionInfo(SetElementPar)); +static const VMFunction SetObjectElementInfo = FunctionInfo(SetObjectElement); void CodeGenerator::visitCallSetElement(LCallSetElement *lir) @@ -7904,22 +7479,9 @@ PropertyName *name, TypedOrValueRegister output, bool monitoredResult, jsbytecode *profilerLeavePc) { - switch (gen->info().executionMode()) { - case SequentialExecution: { - GetPropertyIC cache(liveRegs, objReg, name, output, monitoredResult); - cache.setProfilerLeavePC(profilerLeavePc); - addCache(ins, allocateCache(cache)); - break; - } - case ParallelExecution: { - GetPropertyParIC cache(objReg, name, output); - cache.setProfilerLeavePC(profilerLeavePc); - addCache(ins, allocateCache(cache)); - break; - } - default: - MOZ_CRASH("Bad execution mode"); - } + GetPropertyIC cache(liveRegs, objReg, name, output, monitoredResult); + cache.setProfilerLeavePC(profilerLeavePc); + addCache(ins, allocateCache(cache)); } void @@ -7927,22 +7489,9 @@ PropertyName *name, ConstantOrRegister value, bool strict, bool needsTypeBarrier, jsbytecode *profilerLeavePc) { - switch (gen->info().executionMode()) { - case SequentialExecution: { - SetPropertyIC cache(liveRegs, objReg, name, value, strict, needsTypeBarrier); - cache.setProfilerLeavePC(profilerLeavePc); - addCache(ins, allocateCache(cache)); - break; - } - case ParallelExecution: { - SetPropertyParIC cache(objReg, name, value, strict, needsTypeBarrier); - cache.setProfilerLeavePC(profilerLeavePc); - addCache(ins, allocateCache(cache)); - break; - } - default: - MOZ_CRASH("Bad execution mode"); - } + SetPropertyIC cache(liveRegs, objReg, name, value, strict, needsTypeBarrier); + cache.setProfilerLeavePC(profilerLeavePc); + addCache(ins, allocateCache(cache)); } void @@ -7952,24 +7501,10 @@ ConstantOrRegister value, bool strict, bool guardHoles, jsbytecode *profilerLeavePc) { - switch (gen->info().executionMode()) { - case SequentialExecution: { - SetElementIC cache(obj, unboxIndex, temp, tempDouble, tempFloat32, index, value, strict, - guardHoles); - cache.setProfilerLeavePC(profilerLeavePc); - addCache(ins, allocateCache(cache)); - break; - } - case ParallelExecution: { - SetElementParIC cache(obj, unboxIndex, temp, tempDouble, tempFloat32, index, value, strict, - guardHoles); - cache.setProfilerLeavePC(profilerLeavePc); - addCache(ins, allocateCache(cache)); - break; - } - default: - MOZ_CRASH("Bad execution mode"); - } + SetElementIC cache(obj, unboxIndex, temp, tempDouble, tempFloat32, index, value, strict, + guardHoles); + cache.setProfilerLeavePC(profilerLeavePc); + addCache(ins, allocateCache(cache)); } void @@ -8025,47 +7560,15 @@ masm.jump(ool->rejoin()); } -typedef bool (*GetPropertyParICFn)(ForkJoinContext *, size_t, HandleObject, MutableHandleValue); -const VMFunction GetPropertyParIC::UpdateInfo = - FunctionInfo(GetPropertyParIC::update); - -void -CodeGenerator::visitGetPropertyParIC(OutOfLineUpdateCache *ool, DataPtr &ic) -{ - LInstruction *lir = ool->lir(); - saveLive(lir); - - pushArg(ic->object()); - pushArg(Imm32(ool->getCacheIndex())); - callVM(GetPropertyParIC::UpdateInfo, lir); - StoreValueTo(ic->output()).generate(this); - restoreLiveIgnore(lir, StoreValueTo(ic->output()).clobbered()); - - masm.jump(ool->rejoin()); -} - void CodeGenerator::addGetElementCache(LInstruction *ins, Register obj, ConstantOrRegister index, TypedOrValueRegister output, bool monitoredResult, bool allowDoubleResult, jsbytecode *profilerLeavePc) { - switch (gen->info().executionMode()) { - case SequentialExecution: { - RegisterSet liveRegs = ins->safepoint()->liveRegs(); - GetElementIC cache(liveRegs, obj, index, output, monitoredResult, allowDoubleResult); - cache.setProfilerLeavePC(profilerLeavePc); - addCache(ins, allocateCache(cache)); - break; - } - case ParallelExecution: { - GetElementParIC cache(obj, index, output, monitoredResult, allowDoubleResult); - cache.setProfilerLeavePC(profilerLeavePc); - addCache(ins, allocateCache(cache)); - break; - } - default: - MOZ_CRASH("No such execution mode"); - } + RegisterSet liveRegs = ins->safepoint()->liveRegs(); + GetElementIC cache(liveRegs, obj, index, output, monitoredResult, allowDoubleResult); + cache.setProfilerLeavePC(profilerLeavePc); + addCache(ins, allocateCache(cache)); } void @@ -8169,47 +7672,6 @@ masm.jump(ool->rejoin()); } -typedef bool (*SetElementParICFn)(ForkJoinContext *, size_t, HandleObject, HandleValue, HandleValue); -const VMFunction SetElementParIC::UpdateInfo = - FunctionInfo(SetElementParIC::update); - -void -CodeGenerator::visitSetElementParIC(OutOfLineUpdateCache *ool, DataPtr &ic) -{ - LInstruction *lir = ool->lir(); - saveLive(lir); - - pushArg(ic->value()); - pushArg(ic->index()); - pushArg(ic->object()); - pushArg(Imm32(ool->getCacheIndex())); - callVM(SetElementParIC::UpdateInfo, lir); - restoreLive(lir); - - masm.jump(ool->rejoin()); -} - -typedef bool (*GetElementParICFn)(ForkJoinContext *, size_t, HandleObject, HandleValue, - MutableHandleValue); -const VMFunction GetElementParIC::UpdateInfo = - FunctionInfo(GetElementParIC::update); - -void -CodeGenerator::visitGetElementParIC(OutOfLineUpdateCache *ool, DataPtr &ic) -{ - LInstruction *lir = ool->lir(); - saveLive(lir); - - pushArg(ic->index()); - pushArg(ic->object()); - pushArg(Imm32(ool->getCacheIndex())); - callVM(GetElementParIC::UpdateInfo, lir); - StoreValueTo(ic->output()).generate(this); - restoreLiveIgnore(lir, StoreValueTo(ic->output()).clobbered()); - - masm.jump(ool->rejoin()); -} - void CodeGenerator::visitBindNameCache(LBindNameCache *ins) { @@ -8242,11 +7704,7 @@ typedef bool (*SetPropertyFn)(JSContext *, HandleObject, HandlePropertyName, const HandleValue, bool, jsbytecode *); -typedef bool (*SetPropertyParFn)(ForkJoinContext *, HandleObject, - HandlePropertyName, const HandleValue, bool, jsbytecode *); -static const VMFunctionsModal SetPropertyInfo = VMFunctionsModal( - FunctionInfo(SetProperty), - FunctionInfo(SetPropertyPar)); +static const VMFunction SetPropertyInfo = FunctionInfo(SetProperty); void CodeGenerator::visitCallSetProperty(LCallSetProperty *ins) @@ -8349,25 +7807,6 @@ masm.jump(ool->rejoin()); } -typedef bool (*SetPropertyParICFn)(ForkJoinContext *, size_t, HandleObject, HandleValue); -const VMFunction SetPropertyParIC::UpdateInfo = - FunctionInfo(SetPropertyParIC::update); - -void -CodeGenerator::visitSetPropertyParIC(OutOfLineUpdateCache *ool, DataPtr &ic) -{ - LInstruction *lir = ool->lir(); - saveLive(lir); - - pushArg(ic->value()); - pushArg(ic->object()); - pushArg(Imm32(ool->getCacheIndex())); - callVM(SetPropertyParIC::UpdateInfo, lir); - restoreLive(lir); - - masm.jump(ool->rejoin()); -} - typedef bool (*ThrowFn)(JSContext *, HandleValue); static const VMFunction ThrowInfoCodeGen = FunctionInfo(js::Throw); @@ -8379,10 +7818,7 @@ } typedef bool (*BitNotFn)(JSContext *, HandleValue, int *p); -typedef bool (*BitNotParFn)(ForkJoinContext *, HandleValue, int32_t *); -static const VMFunctionsModal BitNotInfo = VMFunctionsModal( - FunctionInfo(BitNot), - FunctionInfo(BitNotPar)); +static const VMFunction BitNotInfo = FunctionInfo(BitNot); void CodeGenerator::visitBitNotV(LBitNotV *lir) @@ -8392,22 +7828,11 @@ } typedef bool (*BitopFn)(JSContext *, HandleValue, HandleValue, int *p); -typedef bool (*BitopParFn)(ForkJoinContext *, HandleValue, HandleValue, int32_t *); -static const VMFunctionsModal BitAndInfo = VMFunctionsModal( - FunctionInfo(BitAnd), - FunctionInfo(BitAndPar)); -static const VMFunctionsModal BitOrInfo = VMFunctionsModal( - FunctionInfo(BitOr), - FunctionInfo(BitOrPar)); -static const VMFunctionsModal BitXorInfo = VMFunctionsModal( - FunctionInfo(BitXor), - FunctionInfo(BitXorPar)); -static const VMFunctionsModal BitLhsInfo = VMFunctionsModal( - FunctionInfo(BitLsh), - FunctionInfo(BitLshPar)); -static const VMFunctionsModal BitRhsInfo = VMFunctionsModal( - FunctionInfo(BitRsh), - FunctionInfo(BitRshPar)); +static const VMFunction BitAndInfo = FunctionInfo(BitAnd); +static const VMFunction BitOrInfo = FunctionInfo(BitOr); +static const VMFunction BitXorInfo = FunctionInfo(BitXor); +static const VMFunction BitLhsInfo = FunctionInfo(BitLsh); +static const VMFunction BitRhsInfo = FunctionInfo(BitRsh); void CodeGenerator::visitBitOpV(LBitOpV *lir) diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/CodeGenerator.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/CodeGenerator.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/CodeGenerator.h 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/CodeGenerator.h 2015-01-09 12:36:47.000000000 +0000 @@ -33,14 +33,11 @@ class OutOfLineNewArray; class OutOfLineNewObject; class CheckOverRecursedFailure; -class CheckOverRecursedFailurePar; -class OutOfLineInterruptCheckPar; class OutOfLineInterruptCheckImplicit; class OutOfLineUnboxFloatingPoint; class OutOfLineStoreElementHole; class OutOfLineTypeOfV; class OutOfLineLoadTypedArray; -class OutOfLineNewGCThingPar; class OutOfLineUpdateCache; class OutOfLineCallPostWriteBarrier; class OutOfLineIsCallable; @@ -113,7 +110,6 @@ void visitLambda(LLambda *lir); void visitLambdaArrow(LLambdaArrow *lir); void visitLambdaForSingleton(LLambdaForSingleton *lir); - void visitLambdaPar(LLambdaPar *lir); void visitPointer(LPointer *lir); void visitSlots(LSlots *lir); void visitLoadSlotT(LLoadSlotT *lir); @@ -162,10 +158,7 @@ void visitNewDeclEnvObject(LNewDeclEnvObject *lir); void visitNewCallObject(LNewCallObject *lir); void visitNewSingletonCallObject(LNewSingletonCallObject *lir); - void visitNewCallObjectPar(LNewCallObjectPar *lir); void visitNewStringObject(LNewStringObject *lir); - void visitNewPar(LNewPar *lir); - void visitNewDenseArrayPar(LNewDenseArrayPar *lir); void visitNewDerivedTypedObject(LNewDerivedTypedObject *lir); void visitInitElem(LInitElem *lir); void visitInitElemGetterSetter(LInitElemGetterSetter *lir); @@ -231,13 +224,10 @@ void visitEmulatesUndefinedAndBranch(LEmulatesUndefinedAndBranch *lir); void emitConcat(LInstruction *lir, Register lhs, Register rhs, Register output); void visitConcat(LConcat *lir); - void visitConcatPar(LConcatPar *lir); void visitCharCodeAt(LCharCodeAt *lir); void visitFromCharCode(LFromCharCode *lir); void visitStringSplit(LStringSplit *lir); void visitFunctionEnvironment(LFunctionEnvironment *lir); - void visitForkJoinContext(LForkJoinContext *lir); - void visitGuardThreadExclusive(LGuardThreadExclusive *lir); void visitCallGetProperty(LCallGetProperty *lir); void visitCallGetElement(LCallGetElement *lir); void visitCallSetElement(LCallSetElement *lir); @@ -291,7 +281,6 @@ Register temp0, Register temp1, unsigned numFormals, JSObject *templateObject, bool saveAndRestore, Register resultreg); void visitRest(LRest *lir); - void visitRestPar(LRestPar *lir); void visitCallSetProperty(LCallSetProperty *ins); void visitCallDeleteProperty(LCallDeleteProperty *lir); void visitCallDeleteElement(LCallDeleteElement *lir); @@ -325,11 +314,6 @@ void visitCheckOverRecursed(LCheckOverRecursed *lir); void visitCheckOverRecursedFailure(CheckOverRecursedFailure *ool); - void visitCheckOverRecursedPar(LCheckOverRecursedPar *lir); - - void visitInterruptCheckPar(LInterruptCheckPar *lir); - void visitOutOfLineInterruptCheckPar(OutOfLineInterruptCheckPar *ool); - void visitInterruptCheckImplicit(LInterruptCheckImplicit *ins); void visitOutOfLineInterruptCheckImplicit(OutOfLineInterruptCheckImplicit *ins); @@ -337,7 +321,6 @@ void visitOutOfLineUnboxFloatingPoint(OutOfLineUnboxFloatingPoint *ool); void visitOutOfLineStoreElementHole(OutOfLineStoreElementHole *ool); - void visitOutOfLineNewGCThingPar(OutOfLineNewGCThingPar *ool); void loadJSScriptForBlock(MBasicBlock *block, Register reg); void loadOutermostJSScript(Register reg); @@ -358,13 +341,9 @@ void visitCallsiteCloneCache(LCallsiteCloneCache *ins); void visitGetPropertyIC(OutOfLineUpdateCache *ool, DataPtr &ic); - void visitGetPropertyParIC(OutOfLineUpdateCache *ool, DataPtr &ic); void visitSetPropertyIC(OutOfLineUpdateCache *ool, DataPtr &ic); - void visitSetPropertyParIC(OutOfLineUpdateCache *ool, DataPtr &ic); void visitGetElementIC(OutOfLineUpdateCache *ool, DataPtr &ic); - void visitGetElementParIC(OutOfLineUpdateCache *ool, DataPtr &ic); void visitSetElementIC(OutOfLineUpdateCache *ool, DataPtr &ic); - void visitSetElementParIC(OutOfLineUpdateCache *ool, DataPtr &ic); void visitBindNameIC(OutOfLineUpdateCache *ool, DataPtr &ic); void visitNameIC(OutOfLineUpdateCache *ool, DataPtr &ic); void visitCallsiteCloneIC(OutOfLineUpdateCache *ool, DataPtr &ic); @@ -401,12 +380,6 @@ bool generateBranchV(const ValueOperand &value, Label *ifTrue, Label *ifFalse, FloatRegister fr); - void emitAllocateGCThingPar(LInstruction *lir, Register objReg, Register cxReg, - Register tempReg1, Register tempReg2, - NativeObject *templateObj); - - void emitCallToUncompiledScriptPar(LInstruction *lir, Register calleeReg); - void emitLambdaInit(Register resultReg, Register scopeChainReg, const LambdaFunctionInfo &info); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/CompileInfo.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/CompileInfo.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/CompileInfo.h 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/CompileInfo.h 2015-01-09 12:36:47.000000000 +0000 @@ -431,10 +431,6 @@ return executionMode_ == DefinitePropertiesAnalysis || executionMode_ == ArgumentsUsageAnalysis; } - bool isParallelExecution() const { - return executionMode_ == ParallelExecution; - } - // Returns true if a slot can be observed out-side the current frame while // the frame is active on the stack. This implies that these definitions // would have to be executed and that they cannot be removed even if they diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/IonAnalysis.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/IonAnalysis.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/IonAnalysis.cpp 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/IonAnalysis.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -2065,7 +2065,6 @@ case MIRType_Pointer: case MIRType_Shape: case MIRType_TypeObject: - case MIRType_ForkJoinContext: case MIRType_Float32x4: case MIRType_Int32x4: case MIRType_Doublex2: diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/IonBuilder.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/IonBuilder.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/IonBuilder.cpp 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/IonBuilder.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -6262,11 +6262,6 @@ needsBarrier = false; } - // In parallel execution, we never require write barriers. See - // forkjoin.cpp for more information. - if (info().executionMode() == ParallelExecution) - needsBarrier = false; - if (templateObject->isFixedSlot(shape->slot())) { MStoreFixedSlot *store = MStoreFixedSlot::New(alloc(), obj, shape->slot(), value); if (needsBarrier) @@ -7148,7 +7143,7 @@ { if (!GetJitContext()->runtime->gcNursery().exists()) return false; - return info.executionMode() != ParallelExecution && value->mightBeType(MIRType_Object); + return value->mightBeType(MIRType_Object); } bool @@ -7957,10 +7952,6 @@ if (index->mightBeType(MIRType_String) || index->mightBeType(MIRType_Symbol)) barrier = BarrierKind::TypeSet; - // See note about always needing a barrier in jsop_getprop. - if (needsToMonitorMissingProperties(types)) - barrier = BarrierKind::TypeSet; - MInstruction *ins = MGetElementCache::New(alloc(), obj, index, barrier == BarrierKind::TypeSet); current->add(ins); @@ -8030,14 +8021,8 @@ // If we can load the element as a definite double, make sure to check that // the array has been converted to homogenous doubles first. - // - // NB: We disable this optimization in parallel execution mode - // because it is inherently not threadsafe (how do you convert the - // array atomically when there might be concurrent readers)? types::TemporaryTypeSet *objTypes = obj->resultTypeSet(); - ExecutionMode executionMode = info().executionMode(); bool loadDouble = - executionMode == SequentialExecution && barrier == BarrierKind::NoBarrier && loopDepth_ && !readOutOfBounds && @@ -8072,37 +8057,6 @@ MOZ_ASSERT(knownType == MIRType_Value); } - // If the array is being converted to doubles, but we've observed - // just int, substitute a type set of int+double into the observed - // type set. The reason for this is that, in the - // interpreter+baseline, such arrays may consist of mixed - // ints/doubles, but when we enter ion code, we will be coercing - // all inputs to doubles. Therefore, the type barrier checking for - // just int is highly likely (*almost* guaranteed) to fail sooner - // or later. Essentially, by eagerly coercing to double, ion is - // making the observed types outdated. To compensate for this, we - // substitute a broader observed type set consisting of both ints - // and doubles. There is perhaps a tradeoff here, so we limit this - // optimization to parallel code, where it is needed to prevent - // perpetual bailouts in some extreme cases. (Bug 977853) - // - // NB: we have not added a MConvertElementsToDoubles MIR, so we - // cannot *assume* the result is a double. - if (executionMode == ParallelExecution && - barrier != BarrierKind::NoBarrier && - types->getKnownMIRType() == MIRType_Int32 && - objTypes && - objTypes->convertDoubleElements(constraints()) == types::TemporaryTypeSet::AlwaysConvertToDoubles) - { - // Note: double implies int32 as well for typesets - LifoAlloc *lifoAlloc = alloc().lifoAlloc(); - types = lifoAlloc->new_(lifoAlloc, types::Type::DoubleType()); - if (!types) - return false; - - barrier = BarrierKind::NoBarrier; // Don't need a barrier anymore - } - if (knownType != MIRType_Value) load->setResultType(knownType); @@ -10025,9 +9979,6 @@ if (inspector->hasSeenAccessedGetter(pc)) barrier = BarrierKind::TypeSet; - if (needsToMonitorMissingProperties(types)) - barrier = BarrierKind::TypeSet; - // Caches can read values from prototypes, so update the barrier to // reflect such possible values. if (barrier != BarrierKind::TypeSet) { @@ -10043,14 +9994,7 @@ barrier == BarrierKind::TypeSet); // Try to mark the cache as idempotent. - // - // In parallel execution, idempotency of caches is ignored, since we - // repeat the entire ForkJoin workload if we bail out. Note that it's - // overly restrictive to mark everything as idempotent, because we can - // treat non-idempotent caches in parallel as repeatable. - if (obj->type() == MIRType_Object && !invalidatedIdempotentCache() && - info().executionMode() != ParallelExecution) - { + if (obj->type() == MIRType_Object && !invalidatedIdempotentCache()) { if (PropertyReadIsIdempotent(constraints(), obj, name)) load->setIdempotent(); } @@ -10163,17 +10107,6 @@ } bool -IonBuilder::needsToMonitorMissingProperties(types::TemporaryTypeSet *types) -{ - // GetPropertyParIC and GetElementParIC cannot safely call - // TypeScript::Monitor to ensure that the observed type set contains - // undefined. To account for possible missing properties, which property - // types do not track, we must always insert a type barrier. - return info().executionMode() == ParallelExecution && - !types->hasType(types::Type::UndefinedType()); -} - -bool IonBuilder::jsop_setprop(PropertyName *name) { MDefinition *value = current->pop(); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/IonBuilder.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/IonBuilder.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/IonBuilder.h 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/IonBuilder.h 2015-01-09 12:36:47.000000000 +0000 @@ -439,7 +439,6 @@ types::TemporaryTypeSet *types); bool getPropTryCache(bool *emitted, MDefinition *obj, PropertyName *name, BarrierKind barrier, types::TemporaryTypeSet *types); - bool needsToMonitorMissingProperties(types::TemporaryTypeSet *types); // jsop_setprop() helpers. bool setPropTryCommonSetter(bool *emitted, MDefinition *obj, @@ -770,18 +769,12 @@ ScalarTypeDescr::Type arrayType); bool inlineUnsafeSetTypedObjectArrayElement(CallInfo &callInfo, uint32_t base, ScalarTypeDescr::Type arrayType); - InliningStatus inlineNewDenseArray(CallInfo &callInfo); - InliningStatus inlineNewDenseArrayForSequentialExecution(CallInfo &callInfo); - InliningStatus inlineNewDenseArrayForParallelExecution(CallInfo &callInfo); // Slot intrinsics. InliningStatus inlineUnsafeSetReservedSlot(CallInfo &callInfo); InliningStatus inlineUnsafeGetReservedSlot(CallInfo &callInfo, MIRType knownValueType); - // ForkJoin intrinsics - InliningStatus inlineForkJoinGetSlice(CallInfo &callInfo); - // TypedArray intrinsics. InliningStatus inlineIsTypedArray(CallInfo &callInfo); InliningStatus inlineTypedArrayLength(CallInfo &callInfo); @@ -808,7 +801,6 @@ InliningStatus inlineSubstringKernel(CallInfo &callInfo); // Testing functions. - InliningStatus inlineForceSequentialOrInParallelSection(CallInfo &callInfo); InliningStatus inlineBailout(CallInfo &callInfo); InliningStatus inlineAssertFloat32(CallInfo &callInfo); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/IonCaches.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/IonCaches.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/IonCaches.cpp 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/IonCaches.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -21,7 +21,6 @@ #ifdef JS_ION_PERF # include "jit/PerfSpewer.h" #endif -#include "jit/ParallelFunctions.h" #include "jit/VMFunctions.h" #include "vm/Shape.h" @@ -396,9 +395,7 @@ // MarkJitExitFrame). attacher.patchStubCodePointer(masm, code); - // Update the failure path. Note it is this patch that makes the stub - // accessible for parallel ICs so it should not be moved unless you really - // know what is going on. + // Update the failure path. attacher.patchNextStubJump(masm, code); } @@ -1205,8 +1202,8 @@ (IsCacheableGetPropCallNative(obj, holder, shape) || IsCacheableGetPropCallPropertyOp(obj, holder, shape))) { - // Don't enable getter call if cache is parallel or idempotent, since - // they can be effectful. This is handled by allowGetters() + // Don't enable getter call if cache is idempotent, since they can be + // effectful. This is handled by allowGetters() return GetPropertyIC::CanAttachCallGetter; } @@ -1800,154 +1797,6 @@ hasGenericProxyStub_ = false; } -bool -ParallelIonCache::initStubbedShapes(JSContext *cx) -{ - MOZ_ASSERT(isAllocated()); - if (!stubbedShapes_) { - stubbedShapes_ = cx->new_(cx); - return stubbedShapes_ && stubbedShapes_->init(); - } - return true; -} - -bool -ParallelIonCache::hasOrAddStubbedShape(LockedJSContext &cx, Shape *shape, bool *alreadyStubbed) -{ - // Check if we have already stubbed the current object to avoid - // attaching a duplicate stub. - if (!initStubbedShapes(cx)) - return false; - ShapeSet::AddPtr p = stubbedShapes_->lookupForAdd(shape); - if ((*alreadyStubbed = !!p)) - return true; - return stubbedShapes_->add(p, shape); -} - -void -ParallelIonCache::reset() -{ - DispatchIonCache::reset(); - if (stubbedShapes_) - stubbedShapes_->clear(); -} - -void -ParallelIonCache::destroy() -{ - DispatchIonCache::destroy(); - js_delete(stubbedShapes_); -} - -void -GetPropertyParIC::reset() -{ - ParallelIonCache::reset(); - hasTypedArrayLengthStub_ = false; - hasSharedTypedArrayLengthStub_ = false; -} - -bool -GetPropertyParIC::attachReadSlot(LockedJSContext &cx, IonScript *ion, HandleObject obj, - HandleNativeObject holder, HandleShape shape) -{ - // Ready to generate the read slot stub. - DispatchStubPrepender attacher(*this); - MacroAssembler masm(cx, ion); - GenerateReadSlot(cx, ion, masm, attacher, obj, holder, shape, object(), output()); - - return linkAndAttachStub(cx, masm, attacher, ion, "parallel reading"); -} - -bool -GetPropertyParIC::attachArrayLength(LockedJSContext &cx, IonScript *ion, HandleObject obj) -{ - MacroAssembler masm(cx, ion); - DispatchStubPrepender attacher(*this); - if (!GenerateArrayLength(cx, masm, attacher, obj, object(), output())) - return false; - - return linkAndAttachStub(cx, masm, attacher, ion, "parallel array length"); -} - -bool -GetPropertyParIC::attachTypedArrayLength(LockedJSContext &cx, IonScript *ion, HandleObject obj) -{ - MacroAssembler masm(cx, ion); - DispatchStubPrepender attacher(*this); - GenerateTypedArrayLength(cx, masm, attacher, AnyTypedArrayLayout(obj), object(), output()); - - setHasTypedArrayLengthStub(obj); - return linkAndAttachStub(cx, masm, attacher, ion, "parallel typed array length"); -} - -bool -GetPropertyParIC::update(ForkJoinContext *cx, size_t cacheIndex, - HandleObject obj, MutableHandleValue vp) -{ - IonScript *ion = GetTopJitJSScript(cx)->parallelIonScript(); - GetPropertyParIC &cache = ion->getCache(cacheIndex).toGetPropertyPar(); - - // Grab the property early, as the pure path is fast anyways and doesn't - // need a lock. If we can't do it purely, bail out of parallel execution. - if (!GetPropertyPure(cx, obj, NameToId(cache.name()), vp.address())) - return false; - - // Avoid unnecessary locking if cannot attach stubs. - if (!cache.canAttachStub()) - return true; - - { - // Lock the context before mutating the cache. Ideally we'd like to do - // finer-grained locking, with one lock per cache. However, generating - // new jitcode uses a global ExecutableAllocator tied to the runtime. - LockedJSContext ncx(cx); - - if (cache.canAttachStub()) { - bool alreadyStubbed; - if (!cache.hasOrAddStubbedShape(ncx, obj->lastProperty(), &alreadyStubbed)) - return cx->setPendingAbortFatal(ParallelBailoutOutOfMemory); - if (alreadyStubbed) - return true; - - // See note about the stub limit in GetPropertyCache. - bool attachedStub = false; - - { - RootedShape shape(ncx); - RootedNativeObject holder(ncx); - RootedPropertyName name(ncx, cache.name()); - - GetPropertyIC::NativeGetPropCacheability canCache = - CanAttachNativeGetProp(ncx, cache, obj, name, &holder, &shape); - - if (canCache == GetPropertyIC::CanAttachReadSlot) { - if (!cache.attachReadSlot(ncx, ion, obj, holder, shape)) - return cx->setPendingAbortFatal(ParallelBailoutOutOfMemory); - attachedStub = true; - } - - if (!attachedStub && canCache == GetPropertyIC::CanAttachArrayLength) { - if (!cache.attachArrayLength(ncx, ion, obj)) - return cx->setPendingAbortFatal(ParallelBailoutOutOfMemory); - attachedStub = true; - } - } - - if (!attachedStub && !cache.hasAnyTypedArrayLengthStub(obj) && - IsAnyTypedArray(obj) && cx->names().length == cache.name() && - (cache.output().type() == MIRType_Value || cache.output().type() == MIRType_Int32)) - { - if (!cache.attachTypedArrayLength(ncx, ion, obj)) - return cx->setPendingAbortFatal(ParallelBailoutOutOfMemory); - attachedStub = true; - } - } - } - - return true; -} - void IonCache::disable() { @@ -2909,112 +2758,6 @@ hasGenericProxyStub_ = false; } -bool -SetPropertyParIC::update(ForkJoinContext *cx, size_t cacheIndex, HandleObject obj, - HandleValue value) -{ - MOZ_ASSERT(cx->isThreadLocal(obj)); - - IonScript *ion = GetTopJitJSScript(cx)->parallelIonScript(); - SetPropertyParIC &cache = ion->getCache(cacheIndex).toSetPropertyPar(); - - RootedValue v(cx, value); - RootedId id(cx, AtomToId(cache.name())); - - if (!obj->isNative()) - return false; - RootedNativeObject nobj(cx, &obj->as()); - - // Avoid unnecessary locking if cannot attach stubs. - if (!cache.canAttachStub()) { - return baseops::SetPropertyHelper( - cx, nobj, nobj, id, baseops::Qualified, &v, cache.strict()); - } - - SetPropertyIC::NativeSetPropCacheability canCache = SetPropertyIC::CanAttachNone; - bool attachedStub = false; - - { - // See note about locking context in GetPropertyParIC::update. - LockedJSContext ncx(cx); - - if (cache.canAttachStub()) { - bool alreadyStubbed; - if (!cache.hasOrAddStubbedShape(ncx, nobj->lastProperty(), &alreadyStubbed)) - return cx->setPendingAbortFatal(ParallelBailoutOutOfMemory); - if (alreadyStubbed) { - return baseops::SetPropertyHelper( - cx, nobj, nobj, id, baseops::Qualified, &v, cache.strict()); - } - - // If the object has a lazy type, we need to de-lazify it, but - // this is not safe in parallel. - if (nobj->hasLazyType()) - return false; - - { - RootedShape shape(cx); - RootedNativeObject holder(cx); - bool checkTypeset; - canCache = CanAttachNativeSetProp(cx, nobj, id, cache.value(), cache.needsTypeBarrier(), - &holder, &shape, &checkTypeset); - - if (canCache == SetPropertyIC::CanAttachSetSlot) { - if (!cache.attachSetSlot(ncx, ion, nobj, shape, checkTypeset)) - return cx->setPendingAbortFatal(ParallelBailoutOutOfMemory); - attachedStub = true; - } - } - } - } - - uint32_t oldSlots = nobj->numDynamicSlots(); - RootedShape oldShape(cx, nobj->lastProperty()); - RootedTypeObject oldType(cx, nobj->type()); - - if (!baseops::SetPropertyHelper(cx, nobj, nobj, id, baseops::Qualified, &v, - cache.strict())) - { - return false; - } - - bool checkTypeset; - if (!attachedStub && canCache == SetPropertyIC::MaybeCanAttachAddSlot && - IsPropertyAddInlineable(nobj, id, - cache.value(), oldSlots, oldShape, cache.needsTypeBarrier(), - &checkTypeset)) - { - LockedJSContext ncx(cx); - if (cache.canAttachStub() && !cache.attachAddSlot(ncx, ion, nobj, oldShape, oldType, checkTypeset)) - return cx->setPendingAbortFatal(ParallelBailoutOutOfMemory); - } - - return true; -} - -bool -SetPropertyParIC::attachSetSlot(LockedJSContext &cx, IonScript *ion, HandleNativeObject obj, - HandleShape shape, bool checkTypeset) -{ - MacroAssembler masm(cx, ion); - DispatchStubPrepender attacher(*this); - GenerateSetSlot(cx, masm, attacher, obj, shape, object(), value(), needsTypeBarrier(), - checkTypeset); - return linkAndAttachStub(cx, masm, attacher, ion, "parallel setting"); -} - -bool -SetPropertyParIC::attachAddSlot(LockedJSContext &cx, IonScript *ion, HandleNativeObject obj, - HandleShape oldShape, HandleTypeObject oldType, bool checkTypeset) -{ - MOZ_ASSERT_IF(!needsTypeBarrier(), !checkTypeset); - - MacroAssembler masm(cx, ion); - DispatchStubPrepender attacher(*this); - GenerateAddSlot(cx, masm, attacher, obj, oldShape, oldType, object(), value(), checkTypeset); - return linkAndAttachStub(cx, masm, attacher, ion, "parallel adding"); -} - const size_t GetElementIC::MAX_FAILED_UPDATES = 16; /* static */ bool @@ -3899,191 +3642,6 @@ } bool -SetElementParIC::attachDenseElement(LockedJSContext &cx, IonScript *ion, HandleObject obj, - const Value &idval) -{ - MacroAssembler masm(cx, ion); - DispatchStubPrepender attacher(*this); - if (!GenerateSetDenseElement(cx, masm, attacher, obj, idval, - guardHoles(), object(), index(), - value(), tempToUnboxIndex(), - temp())) - { - return false; - } - - const char *message = guardHoles() ? - "parallel dense array (holes)" : - "parallel dense array"; - - return linkAndAttachStub(cx, masm, attacher, ion, message); -} - -bool -SetElementParIC::attachTypedArrayElement(LockedJSContext &cx, IonScript *ion, - HandleObject tarr) -{ - MacroAssembler masm(cx, ion); - DispatchStubPrepender attacher(*this); - if (!GenerateSetTypedArrayElement(cx, masm, attacher, tarr, - object(), index(), value(), - tempToUnboxIndex(), temp(), tempDouble(), tempFloat32())) - { - return false; - } - - return linkAndAttachStub(cx, masm, attacher, ion, "parallel typed array"); -} - -bool -SetElementParIC::update(ForkJoinContext *cx, size_t cacheIndex, HandleObject obj, - HandleValue idval, HandleValue value) -{ - IonScript *ion = GetTopJitJSScript(cx)->parallelIonScript(); - SetElementParIC &cache = ion->getCache(cacheIndex).toSetElementPar(); - - // Avoid unnecessary locking if cannot attach stubs. - if (!cache.canAttachStub()) - return SetElementPar(cx, obj, idval, value, cache.strict()); - - { - LockedJSContext ncx(cx); - - if (cache.canAttachStub()) { - bool alreadyStubbed; - if (!cache.hasOrAddStubbedShape(ncx, obj->lastProperty(), &alreadyStubbed)) - return cx->setPendingAbortFatal(ParallelBailoutOutOfMemory); - if (alreadyStubbed) - return SetElementPar(cx, obj, idval, value, cache.strict()); - - bool attachedStub = false; - if (IsDenseElementSetInlineable(obj, idval)) { - if (!cache.attachDenseElement(ncx, ion, obj, idval)) - return cx->setPendingAbortFatal(ParallelBailoutOutOfMemory); - attachedStub = true; - } - if (!attachedStub && IsTypedArrayElementSetInlineable(obj, idval, value)) { - if (!cache.attachTypedArrayElement(ncx, ion, obj)) - return cx->setPendingAbortFatal(ParallelBailoutOutOfMemory); - } - } - } - - return SetElementPar(cx, obj, idval, value, cache.strict()); -} - -bool -GetElementParIC::attachReadSlot(LockedJSContext &cx, IonScript *ion, HandleObject obj, - const Value &idval, HandlePropertyName name, HandleNativeObject holder, - HandleShape shape) -{ - MacroAssembler masm(cx, ion); - DispatchStubPrepender attacher(*this); - - // Guard on the index value. - Label failures; - ValueOperand val = index().reg().valueReg(); - masm.branchTestValue(Assembler::NotEqual, val, idval, &failures); - - GenerateReadSlot(cx, ion, masm, attacher, obj, holder, shape, object(), output(), - &failures); - - return linkAndAttachStub(cx, masm, attacher, ion, "parallel getelem reading"); -} - -bool -GetElementParIC::attachDenseElement(LockedJSContext &cx, IonScript *ion, HandleObject obj, - const Value &idval) -{ - MacroAssembler masm(cx, ion); - DispatchStubPrepender attacher(*this); - if (!GenerateDenseElement(cx, masm, attacher, obj, idval, object(), index(), output())) - return false; - - return linkAndAttachStub(cx, masm, attacher, ion, "parallel dense element"); -} - -bool -GetElementParIC::attachTypedArrayElement(LockedJSContext &cx, IonScript *ion, - HandleObject tarr, const Value &idval) -{ - MacroAssembler masm(cx, ion); - DispatchStubPrepender attacher(*this); - GenerateGetTypedArrayElement(cx, masm, attacher, tarr, idval, object(), index(), output(), - allowDoubleResult()); - return linkAndAttachStub(cx, masm, attacher, ion, "parallel typed array"); -} - -bool -GetElementParIC::update(ForkJoinContext *cx, size_t cacheIndex, HandleObject obj, - HandleValue idval, MutableHandleValue vp) -{ - IonScript *ion = GetTopJitJSScript(cx)->parallelIonScript(); - GetElementParIC &cache = ion->getCache(cacheIndex).toGetElementPar(); - - // Try to get the element early, as the pure path doesn't need a lock. If - // we can't do it purely, bail out of parallel execution. - if (!GetObjectElementOperationPure(cx, obj, idval, vp.address())) - return false; - - // Avoid unnecessary locking if cannot attach stubs. - if (!cache.canAttachStub()) - return true; - - { - // See note about locking context in GetPropertyParIC::update. - LockedJSContext ncx(cx); - - if (cache.canAttachStub()) { - bool alreadyStubbed; - if (!cache.hasOrAddStubbedShape(ncx, obj->lastProperty(), &alreadyStubbed)) - return cx->setPendingAbortFatal(ParallelBailoutOutOfMemory); - if (alreadyStubbed) - return true; - - jsid id; - if (!ValueToIdPure(idval, &id)) - return false; - - bool attachedStub = false; - if (cache.monitoredResult() && - GetElementIC::canAttachGetProp(obj, idval, id)) - { - RootedShape shape(ncx); - RootedNativeObject holder(ncx); - RootedPropertyName name(ncx, JSID_TO_ATOM(id)->asPropertyName()); - - GetPropertyIC::NativeGetPropCacheability canCache = - CanAttachNativeGetProp(ncx, cache, obj, name, &holder, &shape); - - if (canCache == GetPropertyIC::CanAttachReadSlot) - { - if (!cache.attachReadSlot(ncx, ion, obj, idval, name, holder, shape)) - return cx->setPendingAbortFatal(ParallelBailoutOutOfMemory); - attachedStub = true; - } - } - if (!attachedStub && - GetElementIC::canAttachDenseElement(obj, idval)) - { - if (!cache.attachDenseElement(ncx, ion, obj, idval)) - return cx->setPendingAbortFatal(ParallelBailoutOutOfMemory); - attachedStub = true; - } - if (!attachedStub && - GetElementIC::canAttachTypedArrayElement(obj, idval, cache.output())) - { - if (!cache.attachTypedArrayElement(ncx, ion, obj, idval)) - return cx->setPendingAbortFatal(ParallelBailoutOutOfMemory); - attachedStub = true; - } - } - } - - return true; -} - -bool BindNameIC::attachGlobal(JSContext *cx, HandleScript outerScript, IonScript *ion, HandleObject scopeChain) { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/IonCaches.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/IonCaches.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/IonCaches.h 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/IonCaches.h 2015-01-09 12:36:47.000000000 +0000 @@ -31,11 +31,7 @@ _(SetElement) \ _(BindName) \ _(Name) \ - _(CallsiteClone) \ - _(GetPropertyPar) \ - _(GetElementPar) \ - _(SetPropertyPar) \ - _(SetElementPar) + _(CallsiteClone) // Forward declarations of Cache kinds. #define FORWARD_DECLARE(kind) class kind##IC; @@ -420,7 +416,8 @@ // not have to worry about aligning the exit jumps to ensure atomic patching, // at the expense of an extra memory read to load the very first stub. // -// ICs that need to work in parallel execution need to be dispatch style. +// ICs that need to work in parallel execution need to be dispatch +// style. Since PJS's removal, nothing else yet uses this style of ICs. // // Control flow Pointers Memory load // =======# ----. .----> ****** @@ -1079,284 +1076,6 @@ static JSObject *update(JSContext *cx, size_t cacheIndex, HandleObject callee); }; -class ParallelIonCache : public DispatchIonCache -{ - protected: - // A set of all objects that are stubbed. Used to detect duplicates in - // parallel execution. - ShapeSet *stubbedShapes_; - - ParallelIonCache() - : stubbedShapes_(nullptr) - { - } - - bool initStubbedShapes(JSContext *cx); - - public: - void reset(); - void destroy(); - - bool hasOrAddStubbedShape(LockedJSContext &cx, Shape *shape, bool *alreadyStubbed); -}; - -class GetPropertyParIC : public ParallelIonCache -{ - protected: - Register object_; - PropertyName *name_; - TypedOrValueRegister output_; - bool hasTypedArrayLengthStub_ : 1; - bool hasSharedTypedArrayLengthStub_ : 1; - - public: - GetPropertyParIC(Register object, PropertyName *name, TypedOrValueRegister output) - : object_(object), - name_(name), - output_(output), - hasTypedArrayLengthStub_(false), - hasSharedTypedArrayLengthStub_(false) - { - } - - CACHE_HEADER(GetPropertyPar) - -#ifdef JS_CODEGEN_X86 - // x86 lacks a general purpose scratch register for dispatch caches and - // must be given one manually. - void initializeAddCacheState(LInstruction *ins, AddCacheState *addState); -#endif - - void reset(); - - Register object() const { - return object_; - } - PropertyName *name() const { - return name_; - } - TypedOrValueRegister output() const { - return output_; - } - bool hasAnyTypedArrayLengthStub(HandleObject obj) const { - return obj->is() ? hasTypedArrayLengthStub_ : hasSharedTypedArrayLengthStub_; - } - - void setHasTypedArrayLengthStub(HandleObject obj) { - if (obj->is()) { - MOZ_ASSERT(!hasTypedArrayLengthStub_); - hasTypedArrayLengthStub_ = true; - } else { - MOZ_ASSERT(!hasSharedTypedArrayLengthStub_); - hasSharedTypedArrayLengthStub_ = true; - } - } - - // CanAttachNativeGetProp Helpers - typedef LockedJSContext & Context; - bool canMonitorSingletonUndefinedSlot(HandleObject, HandleShape) const { return true; } - bool allowGetters() const { return false; } - bool allowArrayLength(Context, HandleObject) const { return true; } - - bool attachReadSlot(LockedJSContext &cx, IonScript *ion, - HandleObject obj, HandleNativeObject holder, - HandleShape shape); - bool attachArrayLength(LockedJSContext &cx, IonScript *ion, HandleObject obj); - bool attachTypedArrayLength(LockedJSContext &cx, IonScript *ion, HandleObject obj); - - static bool update(ForkJoinContext *cx, size_t cacheIndex, HandleObject obj, - MutableHandleValue vp); -}; - -class GetElementParIC : public ParallelIonCache -{ - protected: - Register object_; - ConstantOrRegister index_; - TypedOrValueRegister output_; - - bool monitoredResult_ : 1; - bool allowDoubleResult_ : 1; - - public: - GetElementParIC(Register object, ConstantOrRegister index, - TypedOrValueRegister output, bool monitoredResult, bool allowDoubleResult) - : object_(object), - index_(index), - output_(output), - monitoredResult_(monitoredResult), - allowDoubleResult_(allowDoubleResult) - { - } - - CACHE_HEADER(GetElementPar) - -#ifdef JS_CODEGEN_X86 - // x86 lacks a general purpose scratch register for dispatch caches and - // must be given one manually. - void initializeAddCacheState(LInstruction *ins, AddCacheState *addState); -#endif - - Register object() const { - return object_; - } - ConstantOrRegister index() const { - return index_; - } - TypedOrValueRegister output() const { - return output_; - } - bool monitoredResult() const { - return monitoredResult_; - } - bool allowDoubleResult() const { - return allowDoubleResult_; - } - - // CanAttachNativeGetProp Helpers - typedef LockedJSContext & Context; - bool canMonitorSingletonUndefinedSlot(HandleObject, HandleShape) const { return true; } - bool allowGetters() const { return false; } - bool allowArrayLength(Context, HandleObject) const { return false; } - - bool attachReadSlot(LockedJSContext &cx, IonScript *ion, HandleObject obj, const Value &idval, - HandlePropertyName name, HandleNativeObject holder, HandleShape shape); - bool attachDenseElement(LockedJSContext &cx, IonScript *ion, HandleObject obj, - const Value &idval); - bool attachTypedArrayElement(LockedJSContext &cx, IonScript *ion, HandleObject tarr, - const Value &idval); - - static bool update(ForkJoinContext *cx, size_t cacheIndex, HandleObject obj, HandleValue idval, - MutableHandleValue vp); - -}; - -class SetPropertyParIC : public ParallelIonCache -{ - protected: - Register object_; - PropertyName *name_; - ConstantOrRegister value_; - bool strict_; - bool needsTypeBarrier_; - - public: - SetPropertyParIC(Register object, PropertyName *name, ConstantOrRegister value, - bool strict, bool needsTypeBarrier) - : object_(object), - name_(name), - value_(value), - strict_(strict), - needsTypeBarrier_(needsTypeBarrier) - { - } - - CACHE_HEADER(SetPropertyPar) - -#ifdef JS_CODEGEN_X86 - // x86 lacks a general purpose scratch register for dispatch caches and - // must be given one manually. - void initializeAddCacheState(LInstruction *ins, AddCacheState *addState); -#endif - - Register object() const { - return object_; - } - PropertyName *name() const { - return name_; - } - ConstantOrRegister value() const { - return value_; - } - bool strict() const { - return strict_; - } - bool needsTypeBarrier() const { - return needsTypeBarrier_; - } - - bool attachSetSlot(LockedJSContext &cx, IonScript *ion, HandleNativeObject obj, HandleShape shape, - bool checkTypeset); - bool attachAddSlot(LockedJSContext &cx, IonScript *ion, HandleNativeObject obj, - HandleShape oldShape, HandleTypeObject oldType, bool checkTypeset); - - static bool update(ForkJoinContext *cx, size_t cacheIndex, HandleObject obj, - HandleValue value); -}; - -class SetElementParIC : public ParallelIonCache -{ - protected: - Register object_; - Register tempToUnboxIndex_; - Register temp_; - FloatRegister tempDouble_; - FloatRegister tempFloat32_; - ValueOperand index_; - ConstantOrRegister value_; - bool strict_; - bool guardHoles_; - - public: - SetElementParIC(Register object, Register tempToUnboxIndex, Register temp, - FloatRegister tempDouble, FloatRegister tempFloat32, ValueOperand index, ConstantOrRegister value, - bool strict, bool guardHoles) - : object_(object), - tempToUnboxIndex_(tempToUnboxIndex), - temp_(temp), - tempDouble_(tempDouble), - tempFloat32_(tempFloat32), - index_(index), - value_(value), - strict_(strict), - guardHoles_(guardHoles) - { - } - - CACHE_HEADER(SetElementPar) - -#ifdef JS_CODEGEN_X86 - // x86 lacks a general purpose scratch register for dispatch caches and - // must be given one manually. - void initializeAddCacheState(LInstruction *ins, AddCacheState *addState); -#endif - - Register object() const { - return object_; - } - Register tempToUnboxIndex() const { - return tempToUnboxIndex_; - } - Register temp() const { - return temp_; - } - FloatRegister tempDouble() const { - return tempDouble_; - } - FloatRegister tempFloat32() const { - return tempFloat32_; - } - ValueOperand index() const { - return index_; - } - ConstantOrRegister value() const { - return value_; - } - bool strict() const { - return strict_; - } - bool guardHoles() const { - return guardHoles_; - } - - bool attachDenseElement(LockedJSContext &cx, IonScript *ion, HandleObject obj, - const Value &idval); - bool attachTypedArrayElement(LockedJSContext &cx, IonScript *ion, HandleObject tarr); - - static bool update(ForkJoinContext *cx, size_t cacheIndex, HandleObject obj, - HandleValue idval, HandleValue value); -}; - #undef CACHE_HEADER // Implement cache casts now that the compiler can see the inheritance. diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/IonCode.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/IonCode.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/IonCode.h 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/IonCode.h 2015-01-09 12:36:47.000000000 +0000 @@ -256,12 +256,6 @@ uint32_t constantTable_; uint32_t constantEntries_; - // List of scripts that we call. - // - // Currently this is only non-nullptr for parallel IonScripts. - uint32_t callTargetList_; - uint32_t callTargetEntries_; - // List of patchable backedges which are threaded into the runtime's list. uint32_t backedgeList_; uint32_t backedgeEntries_; @@ -333,9 +327,6 @@ uint8_t *runtimeData() { return &bottomBuffer()[runtimeData_]; } - JSScript **callTargetList() { - return (JSScript **) &bottomBuffer()[callTargetList_]; - } PatchableBackedge *backedgeList() { return (PatchableBackedge *) &bottomBuffer()[backedgeList_]; } @@ -354,8 +345,7 @@ size_t constants, size_t safepointIndexEntries, size_t osiIndexEntries, size_t cacheEntries, size_t runtimeSize, size_t safepointsSize, - size_t callTargetEntries, size_t backedgeEntries, - OptimizationLevel optimizationLevel); + size_t backedgeEntries, OptimizationLevel optimizationLevel); static void Trace(JSTracer *trc, IonScript *script); static void Destroy(FreeOp *fop, IonScript *script); @@ -490,9 +480,6 @@ size_t safepointsSize() const { return safepointsSize_; } - size_t callTargetEntries() const { - return callTargetEntries_; - } size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const { return mallocSizeOf(this); } @@ -552,7 +539,6 @@ void copyRuntimeData(const uint8_t *data); void copyCacheEntries(const uint32_t *caches, MacroAssembler &masm); void copySafepoints(const SafepointWriter *writer); - void copyCallTargetEntries(JSScript **callTargets); void copyPatchableBackedges(JSContext *cx, JitCode *code, PatchableBackedgeInfo *backedges, MacroAssembler &masm); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/Ion.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/Ion.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/Ion.cpp 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/Ion.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -33,14 +33,12 @@ #include "jit/LIR.h" #include "jit/LoopUnroller.h" #include "jit/Lowering.h" -#include "jit/ParallelSafetyAnalysis.h" #include "jit/PerfSpewer.h" #include "jit/RangeAnalysis.h" #include "jit/ScalarReplacement.h" #include "jit/Sink.h" #include "jit/StupidAllocator.h" #include "jit/ValueNumbering.h" -#include "vm/ForkJoin.h" #include "vm/HelperThreads.h" #include "vm/TraceLogging.h" @@ -154,16 +152,13 @@ : execAlloc_(nullptr), ionAlloc_(nullptr), exceptionTail_(nullptr), - exceptionTailParallel_(nullptr), bailoutTail_(nullptr), enterJIT_(nullptr), bailoutHandler_(nullptr), argumentsRectifier_(nullptr), argumentsRectifierReturnAddr_(nullptr), - parallelArgumentsRectifier_(nullptr), invalidator_(nullptr), debugTrapHandler_(nullptr), - forkJoinGetSliceStub_(nullptr), baselineDebugModeOSRHandler_(nullptr), functionWrappers_(nullptr), osrTempData_(nullptr), @@ -210,16 +205,11 @@ JitSpew(JitSpew_Codegen, "# Emitting exception tail stub"); void *handler = JS_FUNC_TO_DATA_PTR(void *, jit::HandleException); - void *handlerParallel = JS_FUNC_TO_DATA_PTR(void *, jit::HandleParallelFailure); exceptionTail_ = generateExceptionTailStub(cx, handler); if (!exceptionTail_) return false; - exceptionTailParallel_ = generateExceptionTailStub(cx, handlerParallel); - if (!exceptionTailParallel_) - return false; - JitSpew(JitSpew_Codegen, "# Emitting bailout tail stub"); bailoutTail_ = generateBailoutTailStub(cx); if (!bailoutTail_) @@ -243,15 +233,10 @@ } JitSpew(JitSpew_Codegen, "# Emitting bailout handler"); - bailoutHandler_ = generateBailoutHandler(cx, SequentialExecution); + bailoutHandler_ = generateBailoutHandler(cx); if (!bailoutHandler_) return false; - JitSpew(JitSpew_Codegen, "# Emitting parallel bailout handler"); - parallelBailoutHandler_ = generateBailoutHandler(cx, ParallelExecution); - if (!parallelBailoutHandler_) - return false; - JitSpew(JitSpew_Codegen, "# Emitting invalidator"); invalidator_ = generateInvalidator(cx); if (!invalidator_) @@ -259,15 +244,10 @@ } JitSpew(JitSpew_Codegen, "# Emitting sequential arguments rectifier"); - argumentsRectifier_ = generateArgumentsRectifier(cx, SequentialExecution, &argumentsRectifierReturnAddr_); + argumentsRectifier_ = generateArgumentsRectifier(cx, &argumentsRectifierReturnAddr_); if (!argumentsRectifier_) return false; - JitSpew(JitSpew_Codegen, "# Emitting parallel arguments rectifier"); - parallelArgumentsRectifier_ = generateArgumentsRectifier(cx, ParallelExecution, nullptr); - if (!parallelArgumentsRectifier_) - return false; - JitSpew(JitSpew_Codegen, "# Emitting EnterJIT sequence"); enterJIT_ = generateEnterJIT(cx, EnterJitOptimized); if (!enterJIT_) @@ -344,18 +324,6 @@ return debugTrapHandler_; } -bool -JitRuntime::ensureForkJoinGetSliceStubExists(JSContext *cx) -{ - if (!forkJoinGetSliceStub_) { - JitSpew(JitSpew_Codegen, "# Emitting ForkJoinGetSlice stub"); - AutoLockForExclusiveAccess lock(cx); - AutoCompartment ac(cx, cx->runtime()->atomsCompartment()); - forkJoinGetSliceStub_ = generateForkJoinGetSliceStub(cx); - } - return !!forkJoinGetSliceStub_; -} - uint8_t * JitRuntime::allocateOsrTempData(size_t size) { @@ -405,7 +373,6 @@ baselineGetPropReturnAddr_(nullptr), baselineSetPropReturnAddr_(nullptr), stringConcatStub_(nullptr), - parallelStringConcatStub_(nullptr), regExpExecStub_(nullptr), regExpTestStub_(nullptr), activeParallelEntryScripts_(nullptr) @@ -432,17 +399,11 @@ JitCompartment::ensureIonStubsExist(JSContext *cx) { if (!stringConcatStub_) { - stringConcatStub_ = generateStringConcatStub(cx, SequentialExecution); + stringConcatStub_ = generateStringConcatStub(cx); if (!stringConcatStub_) return false; } - if (!parallelStringConcatStub_) { - parallelStringConcatStub_ = generateStringConcatStub(cx, ParallelExecution); - if (!parallelStringConcatStub_) - return false; - } - return true; } @@ -490,7 +451,7 @@ // Clear the recompiling flag of the old ionScript, since we continue to // use the old ionScript if recompiling fails. - if (executionMode == SequentialExecution && builder->script()->hasIonScript()) + if (builder->script()->hasIonScript()) builder->script()->ionScript()->clearRecompiling(); // Clean up if compilation did not succeed. @@ -650,9 +611,6 @@ if (stringConcatStub_ && !IsJitCodeMarked(&stringConcatStub_)) stringConcatStub_ = nullptr; - if (parallelStringConcatStub_ && !IsJitCodeMarked(¶llelStringConcatStub_)) - parallelStringConcatStub_ = nullptr; - if (regExpExecStub_ && !IsJitCodeMarked(®ExpExecStub_)) regExpExecStub_ = nullptr; @@ -845,8 +803,6 @@ snapshotsRVATableSize_(0), constantTable_(0), constantEntries_(0), - callTargetList_(0), - callTargetEntries_(0), backedgeList_(0), backedgeEntries_(0), invalidationCount_(0), @@ -865,8 +821,7 @@ size_t constants, size_t safepointIndices, size_t osiIndices, size_t cacheEntries, size_t runtimeSize, size_t safepointsSize, - size_t callTargetEntries, size_t backedgeEntries, - OptimizationLevel optimizationLevel) + size_t backedgeEntries, OptimizationLevel optimizationLevel) { static const int DataAlignment = sizeof(void *); @@ -889,7 +844,6 @@ size_t paddedCacheEntriesSize = AlignBytes(cacheEntries * sizeof(uint32_t), DataAlignment); size_t paddedRuntimeSize = AlignBytes(runtimeSize, DataAlignment); size_t paddedSafepointSize = AlignBytes(safepointsSize, DataAlignment); - size_t paddedCallTargetSize = AlignBytes(callTargetEntries * sizeof(JSScript *), DataAlignment); size_t paddedBackedgeSize = AlignBytes(backedgeEntries * sizeof(PatchableBackedge), DataAlignment); size_t bytes = paddedSnapshotsSize + paddedRecoversSize + @@ -900,7 +854,6 @@ paddedCacheEntriesSize + paddedRuntimeSize + paddedSafepointSize + - paddedCallTargetSize + paddedBackedgeSize; IonScript *script = cx->zone()->pod_malloc_with_extra(bytes); if (!script) @@ -946,10 +899,6 @@ script->constantEntries_ = constants; offsetCursor += paddedConstantsSize; - script->callTargetList_ = offsetCursor; - script->callTargetEntries_ = callTargetEntries; - offsetCursor += paddedCallTargetSize; - script->backedgeList_ = offsetCursor; script->backedgeEntries_ = backedgeEntries; offsetCursor += paddedBackedgeSize; @@ -974,11 +923,6 @@ for (size_t i = 0; i < numConstants(); i++) gc::MarkValue(trc, &getConstant(i), "constant"); - - // No write barrier is needed for the call target list, as it's attached - // at compilation time and is read only. - for (size_t i = 0; i < callTargetEntries(); i++) - gc::MarkScriptUnbarriered(trc, &callTargetList()[i], "callTarget"); } /* static */ void @@ -1029,13 +973,6 @@ } void -IonScript::copyCallTargetEntries(JSScript **callTargets) -{ - for (size_t i = 0; i < callTargetEntries_; i++) - callTargetList()[i] = callTargets[i]; -} - -void IonScript::copyPatchableBackedges(JSContext *cx, JitCode *code, PatchableBackedgeInfo *backedges, MacroAssembler &masm) @@ -1380,21 +1317,6 @@ return false; } - // Parallel Safety Analysis. Note that this may delete blocks containing - // instructions pointed to by the dependency() field of instructions which - // are not deleted, leaving them dangling. This is ok, since we'll rerun - // AliasAnalysis, which recomputes them, before they're needed. - if (graph.entryBlock()->info().executionMode() == ParallelExecution) { - AutoTraceLog log(logger, TraceLogger_ParallelSafetyAnalysis); - ParallelSafetyAnalysis analysis(mir, graph); - if (!analysis.analyze()) - return false; - IonSpewPass("Parallel Safety Analysis"); - AssertExtendedGraphCoherency(graph); - if (mir->shouldCancel("Parallel Safety Analysis")) - return false; - } - ValueNumberer gvn(mir, graph); if (!gvn.init()) return false; @@ -1767,9 +1689,7 @@ // Try to defer linking if the script is on the stack, to postpone // invalidating them. - if (builder->info().executionMode() == SequentialExecution && - builder->script()->hasIonScript()) - { + if (builder->script()->hasIonScript()) { bool onStack = false; for (JitActivationIterator iter(cx->runtime()); !iter.done(); ++iter) { for (JitFrameIterator it(iter); !it.done(); ++it) { @@ -1875,8 +1795,7 @@ static AbortReason IonCompile(JSContext *cx, JSScript *script, BaselineFrame *baselineFrame, jsbytecode *osrPc, bool constructing, - ExecutionMode executionMode, bool recompile, - OptimizationLevel optimizationLevel) + bool recompile, OptimizationLevel optimizationLevel) { TraceLoggerThread *logger = TraceLoggerForMainThread(cx->runtime()); TraceLoggerEvent event(logger, TraceLogger_AnnotateScripts, script); @@ -1911,13 +1830,6 @@ if (!cx->compartment()->jitCompartment()->ensureIonStubsExist(cx)) return AbortReason_Alloc; - if (executionMode == ParallelExecution && - LIRGenerator::allowInlineForkJoinGetSlice() && - !cx->runtime()->jitRuntime()->ensureForkJoinGetSliceStubExists(cx)) - { - return AbortReason_Alloc; - } - MIRGraph *graph = alloc->new_(temp); if (!graph) return AbortReason_Alloc; @@ -1927,7 +1839,7 @@ return AbortReason_Alloc; CompileInfo *info = alloc->new_(script, script->functionNonDelazifying(), osrPc, - constructing, executionMode, + constructing, SequentialExecution, script->needsArgsObj(), inlineScriptTree); if (!info) return AbortReason_Alloc; @@ -1958,15 +1870,13 @@ if (!builder) return AbortReason_Alloc; - MOZ_ASSERT(recompile == HasIonScript(builder->script(), executionMode)); - MOZ_ASSERT(CanIonCompile(builder->script(), executionMode)); + MOZ_ASSERT(recompile == builder->script()->hasIonScript()); + MOZ_ASSERT(CanIonCompile(builder->script(), SequentialExecution)); RootedScript builderScript(cx, builder->script()); - if (recompile) { - MOZ_ASSERT(executionMode == SequentialExecution); + if (recompile) builderScript->ionScript()->setRecompiling(); - } #ifdef DEBUG IonSpewFunction ionSpewFunction(graph, builderScript); @@ -1993,7 +1903,7 @@ // If possible, compile the script off thread. if (OffThreadCompilationAvailable(cx)) { if (!recompile) - SetIonScript(cx, builderScript, executionMode, ION_COMPILING_SCRIPT); + builderScript->setIonScript(cx, ION_COMPILING_SCRIPT); JitSpew(JitSpew_IonLogs, "Can't log script %s:%d. (Compiled on background thread.)", builderScript->filename(), builderScript->lineno()); @@ -2105,25 +2015,18 @@ } static OptimizationLevel -GetOptimizationLevel(HandleScript script, jsbytecode *pc, ExecutionMode executionMode) +GetOptimizationLevel(HandleScript script, jsbytecode *pc) { - if (executionMode == ParallelExecution) - return Optimization_Normal; - - MOZ_ASSERT(executionMode == SequentialExecution); - return js_IonOptimizations.levelForScript(script, pc); } static MethodStatus Compile(JSContext *cx, HandleScript script, BaselineFrame *osrFrame, jsbytecode *osrPc, - bool constructing, ExecutionMode executionMode, bool forceRecompile = false) + bool constructing, bool forceRecompile = false) { MOZ_ASSERT(jit::IsIonEnabled(cx)); MOZ_ASSERT(jit::IsBaselineEnabled(cx)); MOZ_ASSERT_IF(osrPc != nullptr, LoopEntryCanIonOsr(osrPc)); - MOZ_ASSERT_IF(executionMode == ParallelExecution, !osrFrame && !osrPc); - MOZ_ASSERT_IF(executionMode == ParallelExecution, !HasIonScript(script, executionMode)); if (!script->hasBaselineScript()) return Method_Skipped; @@ -2145,11 +2048,11 @@ } bool recompile = false; - OptimizationLevel optimizationLevel = GetOptimizationLevel(script, osrPc, executionMode); + OptimizationLevel optimizationLevel = GetOptimizationLevel(script, osrPc); if (optimizationLevel == Optimization_DontCompile) return Method_Skipped; - IonScript *scriptIon = GetIonScript(script, executionMode); + IonScript *scriptIon = script->maybeIonScript(); if (scriptIon) { if (!scriptIon->method()) return Method_CantCompile; @@ -2169,7 +2072,7 @@ recompile = true; } - AbortReason reason = IonCompile(cx, script, osrFrame, osrPc, constructing, executionMode, + AbortReason reason = IonCompile(cx, script, osrFrame, osrPc, constructing, recompile, optimizationLevel); if (reason == AbortReason_Error) return Method_Error; @@ -2183,7 +2086,7 @@ } // Compilation succeeded or we invalidated right away or an inlining/alloc abort - if (HasIonScript(script, executionMode)) + if (script->hasIonScript()) return Method_Compiled; return Method_Skipped; } @@ -2239,7 +2142,7 @@ // (This means a background thread compilation with that pc could have started or not.) RootedScript rscript(cx, script); MethodStatus status = Compile(cx, rscript, osrFrame, pc, osrFrame->isConstructing(), - SequentialExecution, force); + force); if (status != Method_Compiled) { if (status == Method_CantCompile) ForbidCompilation(cx, script); @@ -2309,8 +2212,7 @@ // Attempt compilation. Returns Method_Compiled if already compiled. bool constructing = state.isInvoke() && state.asInvoke()->constructing(); - MethodStatus status = - Compile(cx, rscript, nullptr, nullptr, constructing, SequentialExecution); + MethodStatus status = Compile(cx, rscript, nullptr, nullptr, constructing); if (status != Method_Compiled) { if (status == Method_CantCompile) ForbidCompilation(cx, rscript); @@ -2336,8 +2238,7 @@ } // Attempt compilation. Returns Method_Compiled if already compiled. - MethodStatus status = - Compile(cx, script, frame, nullptr, frame->isConstructing(), SequentialExecution); + MethodStatus status = Compile(cx, script, frame, nullptr, frame->isConstructing()); if (status != Method_Compiled) { if (status == Method_CantCompile) ForbidCompilation(cx, script); @@ -2355,8 +2256,7 @@ if (script->ionScript()->isRecompiling()) return Method_Compiled; - MethodStatus status = - Compile(cx, script, osrFrame, osrPc, constructing, SequentialExecution, force); + MethodStatus status = Compile(cx, script, osrFrame, osrPc, constructing, force); if (status != Method_Compiled) { if (status == Method_CantCompile) ForbidCompilation(cx, script); @@ -2367,49 +2267,6 @@ } MethodStatus -jit::CanEnterInParallel(JSContext *cx, HandleScript script) -{ - // Skip if the script has been disabled. - // - // Note: We return Method_Skipped in this case because the other - // CanEnter() methods do so. However, ForkJoin.cpp detects this - // condition differently treats it more like an error. - if (!script->canParallelIonCompile()) - return Method_Skipped; - - // Skip if the script is being compiled off thread. - if (script->isParallelIonCompilingOffThread()) - return Method_Skipped; - - MethodStatus status = Compile(cx, script, nullptr, nullptr, false, ParallelExecution); - if (status != Method_Compiled) { - if (status == Method_CantCompile) - ForbidCompilation(cx, script, ParallelExecution); - return status; - } - - // This can GC, so afterward, script->parallelIon is - // not guaranteed to be valid. - if (!cx->runtime()->jitRuntime()->enterIon()) - return Method_Error; - - // Subtle: it is possible for GC to occur during - // compilation of one of the invoked functions, which - // would cause the earlier functions (such as the - // kernel itself) to be collected. In this event, we - // give up and fallback to sequential for now. - if (!script->hasParallelIonScript()) { - parallel::Spew( - parallel::SpewCompile, - "Script %p:%s:%u was garbage-collected or invalidated", - script.get(), script->filename(), script->lineno()); - return Method_Skipped; - } - - return Method_Compiled; -} - -MethodStatus jit::CanEnterUsingFastInvoke(JSContext *cx, HandleScript script, uint32_t numActualArgs) { MOZ_ASSERT(jit::IsIonEnabled(cx)); @@ -2805,17 +2662,9 @@ numInvalidations--; // Wait for the scripts to get warm again before doing another - // compile, unless either: - // (1) we are recompiling *because* a script got hot; - // (resetUses is false); or, - // (2) we are invalidating a parallel script. This is because - // the warmUpCounter only applies to sequential uses. Parallel - // execution *requires* ion, and so we don't limit it to - // methods with a high usage count (though we do check that - // the warmUpCount is at least 1 when compiling the transitive - // closure of potential callees, to avoid compiling things - // that are never run at all). - if (resetUses && executionMode != ParallelExecution) + // compile, unless we are recompiling *because* a script got hot + // (resetUses is false). + if (resetUses) script->resetWarmUpCounter(); } @@ -2844,8 +2693,7 @@ } bool -jit::Invalidate(JSContext *cx, JSScript *script, ExecutionMode mode, bool resetUses, - bool cancelOffThread) +jit::Invalidate(JSContext *cx, JSScript *script, bool resetUses, bool cancelOffThread) { MOZ_ASSERT(script->hasIonScript()); @@ -2871,32 +2719,14 @@ } types::RecompileInfoVector scripts; - - switch (mode) { - case SequentialExecution: - MOZ_ASSERT(script->hasIonScript()); - if (!scripts.append(script->ionScript()->recompileInfo())) - return false; - break; - case ParallelExecution: - MOZ_ASSERT(script->hasParallelIonScript()); - if (!scripts.append(script->parallelIonScript()->recompileInfo())) - return false; - break; - default: - MOZ_CRASH("No such execution mode"); - } + MOZ_ASSERT(script->hasIonScript()); + if (!scripts.append(script->ionScript()->recompileInfo())) + return false; Invalidate(cx, scripts, resetUses, cancelOffThread); return true; } -bool -jit::Invalidate(JSContext *cx, JSScript *script, bool resetUses, bool cancelOffThread) -{ - return Invalidate(cx, script, SequentialExecution, resetUses, cancelOffThread); -} - static void FinishInvalidationOf(FreeOp *fop, JSScript *script, IonScript *ionScript) { @@ -2913,83 +2743,36 @@ jit::IonScript::Destroy(fop, ionScript); } -template void jit::FinishInvalidation(FreeOp *fop, JSScript *script) { - // In all cases, nullptr out script->ion or script->parallelIon to avoid - // re-entry. - switch (mode) { - case SequentialExecution: - if (script->hasIonScript()) { - IonScript *ion = script->ionScript(); - script->setIonScript(nullptr, nullptr); - FinishInvalidationOf(fop, script, ion); - } - return; - - case ParallelExecution: - if (script->hasParallelIonScript()) { - IonScript *parallelIon = script->parallelIonScript(); - script->setParallelIonScript(nullptr); - FinishInvalidationOf(fop, script, parallelIon); - } - return; - - default: - MOZ_CRASH("bad execution mode"); + // In all cases, nullptr out script->ion to avoid re-entry. + if (script->hasIonScript()) { + IonScript *ion = script->ionScript(); + script->setIonScript(nullptr, nullptr); + FinishInvalidationOf(fop, script, ion); } } -template void -jit::FinishInvalidation(FreeOp *fop, JSScript *script); - -template void -jit::FinishInvalidation(FreeOp *fop, JSScript *script); - void jit::ForbidCompilation(JSContext *cx, JSScript *script) { - ForbidCompilation(cx, script, SequentialExecution); -} - -void -jit::ForbidCompilation(JSContext *cx, JSScript *script, ExecutionMode mode) -{ - JitSpew(JitSpew_IonAbort, "Disabling Ion mode %d compilation of script %s:%d", - mode, script->filename(), script->lineno()); + JitSpew(JitSpew_IonAbort, "Disabling Ion compilation of script %s:%d", + script->filename(), script->lineno()); CancelOffThreadIonCompile(cx->compartment(), script); - switch (mode) { - case SequentialExecution: - if (script->hasIonScript()) { - // It is only safe to modify script->ion if the script is not currently - // running, because JitFrameIterator needs to tell what ionScript to - // use (either the one on the JSScript, or the one hidden in the - // breadcrumbs Invalidation() leaves). Therefore, if invalidation - // fails, we cannot disable the script. - if (!Invalidate(cx, script, mode, false)) - return; - } - - script->setIonScript(cx, ION_DISABLED_SCRIPT); - return; - - case ParallelExecution: - if (script->hasParallelIonScript()) { - if (!Invalidate(cx, script, mode, false)) - return; - } - - script->setParallelIonScript(ION_DISABLED_SCRIPT); - return; - - default: - MOZ_CRASH("No such execution mode"); + if (script->hasIonScript()) { + // It is only safe to modify script->ion if the script is not currently + // running, because JitFrameIterator needs to tell what ionScript to + // use (either the one on the JSScript, or the one hidden in the + // breadcrumbs Invalidation() leaves). Therefore, if invalidation + // fails, we cannot disable the script. + if (!Invalidate(cx, script, false)) + return; } - MOZ_CRASH("No such execution mode"); + script->setIonScript(cx, ION_DISABLED_SCRIPT); } AutoFlushICache * @@ -3139,9 +2922,6 @@ { if (script->hasIonScript()) script->ionScript()->purgeCaches(); - - if (script->hasParallelIonScript()) - script->parallelIonScript()->purgeCaches(); } size_t @@ -3152,9 +2932,6 @@ if (script->hasIonScript()) result += script->ionScript()->sizeOfIncludingThis(mallocSizeOf); - if (script->hasParallelIonScript()) - result += script->parallelIonScript()->sizeOfIncludingThis(mallocSizeOf); - return result; } @@ -3164,9 +2941,6 @@ if (script->hasIonScript()) jit::IonScript::Destroy(fop, script->ionScript()); - if (script->hasParallelIonScript()) - jit::IonScript::Destroy(fop, script->parallelIonScript()); - if (script->hasBaselineScript()) jit::BaselineScript::Destroy(fop, script->baselineScript()); } @@ -3177,9 +2951,6 @@ if (script->hasIonScript()) jit::IonScript::Trace(trc, script->ionScript()); - if (script->hasParallelIonScript()) - jit::IonScript::Trace(trc, script->parallelIonScript()); - if (script->hasBaselineScript()) jit::BaselineScript::Trace(trc, script->baselineScript()); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/Ion.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/Ion.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/Ion.h 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/Ion.h 2015-01-09 12:36:47.000000000 +0000 @@ -88,8 +88,6 @@ MethodStatus CompileFunctionForBaseline(JSContext *cx, HandleScript script, BaselineFrame *frame); MethodStatus CanEnterUsingFastInvoke(JSContext *cx, HandleScript script, uint32_t numActualArgs); -MethodStatus CanEnterInParallel(JSContext *cx, HandleScript script); - MethodStatus Recompile(JSContext *cx, HandleScript script, BaselineFrame *osrFrame, jsbytecode *osrPc, bool constructing, bool force); @@ -129,8 +127,6 @@ bool cancelOffThread = true); void Invalidate(JSContext *cx, const types::RecompileInfoVector &invalid, bool resetUses = true, bool cancelOffThread = true); -bool Invalidate(JSContext *cx, JSScript *script, ExecutionMode mode, bool resetUses = true, - bool cancelOffThread = true); bool Invalidate(JSContext *cx, JSScript *script, bool resetUses = true, bool cancelOffThread = true); @@ -194,7 +190,6 @@ } void ForbidCompilation(JSContext *cx, JSScript *script); -void ForbidCompilation(JSContext *cx, JSScript *script, ExecutionMode mode); void PurgeCaches(JSScript *script); size_t SizeOfIonData(JSScript *script, mozilla::MallocSizeOf mallocSizeOf); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/IonTypes.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/IonTypes.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/IonTypes.h 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/IonTypes.h 2015-01-09 12:36:47.000000000 +0000 @@ -381,8 +381,7 @@ MIRType_Pointer, // An opaque pointer that receives no special treatment MIRType_Shape, // A Shape pointer. MIRType_TypeObject, // A TypeObject pointer. - MIRType_ForkJoinContext, // js::ForkJoinContext* - MIRType_Last = MIRType_ForkJoinContext, + MIRType_Last = MIRType_TypeObject, MIRType_Float32x4 = MIRType_Float32 | (2 << VECTOR_SCALE_SHIFT), MIRType_Int32x4 = MIRType_Int32 | (2 << VECTOR_SCALE_SHIFT), MIRType_Doublex2 = MIRType_Double | (1 << VECTOR_SCALE_SHIFT) @@ -496,8 +495,6 @@ return "Elements"; case MIRType_Pointer: return "Pointer"; - case MIRType_ForkJoinContext: - return "ForkJoinContext"; case MIRType_Int32x4: return "Int32x4"; case MIRType_Float32x4: diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/JitCompartment.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/JitCompartment.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/JitCompartment.h 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/JitCompartment.h 2015-01-09 12:36:47.000000000 +0000 @@ -154,7 +154,6 @@ // Shared exception-handler tail. JitCode *exceptionTail_; - JitCode *exceptionTailParallel_; // Shared post-bailout-handler tail. JitCode *bailoutTail_; @@ -171,17 +170,11 @@ // Generic bailout table; used if the bailout table overflows. JitCode *bailoutHandler_; - // Bailout handler for parallel execution. - JitCode *parallelBailoutHandler_; - // Argument-rectifying thunk, in the case of insufficient arguments passed // to a function call site. JitCode *argumentsRectifier_; void *argumentsRectifierReturnAddr_; - // Arguments-rectifying thunk which loads |parallelIon| instead of |ion|. - JitCode *parallelArgumentsRectifier_; - // Thunk that invalides an (Ion compiled) caller on the Ion stack. JitCode *invalidator_; @@ -202,9 +195,6 @@ // Thunk used by the debugger for breakpoint and step mode. JitCode *debugTrapHandler_; - // Stub used to inline the ForkJoinGetSlice intrinsic. - JitCode *forkJoinGetSliceStub_; - // Thunk used to fix up on-stack recompile of baseline scripts. JitCode *baselineDebugModeOSRHandler_; void *baselineDebugModeOSRHandlerNoFrameRegPopAddr_; @@ -247,15 +237,14 @@ JitCode *generateExceptionTailStub(JSContext *cx, void *handler); JitCode *generateBailoutTailStub(JSContext *cx); JitCode *generateEnterJIT(JSContext *cx, EnterJitType type); - JitCode *generateArgumentsRectifier(JSContext *cx, ExecutionMode mode, void **returnAddrOut); + JitCode *generateArgumentsRectifier(JSContext *cx, void **returnAddrOut); JitCode *generateBailoutTable(JSContext *cx, uint32_t frameClass); - JitCode *generateBailoutHandler(JSContext *cx, ExecutionMode mode); + JitCode *generateBailoutHandler(JSContext *cx); JitCode *generateInvalidator(JSContext *cx); JitCode *generatePreBarrier(JSContext *cx, MIRType type); JitCode *generateMallocStub(JSContext *cx); JitCode *generateFreeStub(JSContext *cx); JitCode *generateDebugTrapHandler(JSContext *cx); - JitCode *generateForkJoinGetSliceStub(JSContext *cx); JitCode *generateBaselineDebugModeOSRHandler(JSContext *cx, uint32_t *noFrameRegPopOffsetOut); JitCode *generateVMWrapper(JSContext *cx, const VMFunction &f); @@ -322,20 +311,13 @@ JitCode *getBaselineDebugModeOSRHandler(JSContext *cx); void *getBaselineDebugModeOSRHandlerAddress(JSContext *cx, bool popFrameReg); - JitCode *getGenericBailoutHandler(ExecutionMode mode) const { - switch (mode) { - case SequentialExecution: return bailoutHandler_; - case ParallelExecution: return parallelBailoutHandler_; - default: MOZ_CRASH("No such execution mode"); - } + JitCode *getGenericBailoutHandler() const { + return bailoutHandler_; } JitCode *getExceptionTail() const { return exceptionTail_; } - JitCode *getExceptionTailParallel() const { - return exceptionTailParallel_; - } JitCode *getBailoutTail() const { return bailoutTail_; @@ -343,12 +325,8 @@ JitCode *getBailoutTable(const FrameSizeClass &frameClass) const; - JitCode *getArgumentsRectifier(ExecutionMode mode) const { - switch (mode) { - case SequentialExecution: return argumentsRectifier_; - case ParallelExecution: return parallelArgumentsRectifier_; - default: MOZ_CRASH("No such execution mode"); - } + JitCode *getArgumentsRectifier() const { + return argumentsRectifier_; } void *getArgumentsRectifierReturnAddr() const { @@ -390,11 +368,6 @@ return lazyLinkStub_; } - bool ensureForkJoinGetSliceStubExists(JSContext *cx); - JitCode *forkJoinGetSliceStub() const { - return forkJoinGetSliceStub_; - } - bool hasIonReturnOverride() const { return !ionReturnOverride_.isMagic(JS_ARG_POISON); } @@ -459,7 +432,6 @@ // which may occur off thread and whose barriers are captured during // CodeGenerator::link. JitCode *stringConcatStub_; - JitCode *parallelStringConcatStub_; JitCode *regExpExecStub_; JitCode *regExpTestStub_; @@ -470,7 +442,7 @@ ScriptSet; ScriptSet *activeParallelEntryScripts_; - JitCode *generateStringConcatStub(JSContext *cx, ExecutionMode mode); + JitCode *generateStringConcatStub(JSContext *cx); JitCode *generateRegExpExecStub(JSContext *cx); JitCode *generateRegExpTestStub(JSContext *cx); @@ -533,12 +505,8 @@ void mark(JSTracer *trc, JSCompartment *compartment); void sweep(FreeOp *fop, JSCompartment *compartment); - JitCode *stringConcatStubNoBarrier(ExecutionMode mode) const { - switch (mode) { - case SequentialExecution: return stringConcatStub_; - case ParallelExecution: return parallelStringConcatStub_; - default: MOZ_CRASH("No such execution mode"); - } + JitCode *stringConcatStubNoBarrier() const { + return stringConcatStub_; } JitCode *regExpExecStubNoBarrier() const { @@ -566,7 +534,6 @@ // Called from JSCompartment::discardJitCode(). void InvalidateAll(FreeOp *fop, JS::Zone *zone); -template void FinishInvalidation(FreeOp *fop, JSScript *script); // On windows systems, really large frames need to be incrementally touched. diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/JitFrames.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/JitFrames.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/JitFrames.cpp 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/JitFrames.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -21,7 +21,6 @@ #include "jit/JitCompartment.h" #include "jit/JitSpewer.h" #include "jit/MacroAssembler.h" -#include "jit/ParallelFunctions.h" #include "jit/PcScriptCache.h" #include "jit/Recover.h" #include "jit/Safepoints.h" @@ -873,29 +872,6 @@ } void -HandleParallelFailure(ResumeFromException *rfe) -{ - parallel::Spew(parallel::SpewBailouts, "Bailing from VM reentry"); - - ForkJoinContext *cx = ForkJoinContext::current(); - JitFrameIterator frameIter(cx); - - // Advance to the first Ion frame so we can pull out the BailoutKind. - while (!frameIter.isIonJS()) - ++frameIter; - SnapshotIterator snapIter(frameIter); - - cx->bailoutRecord->setIonBailoutKind(snapIter.bailoutKind()); - while (!frameIter.done()) - ++frameIter; - - rfe->kind = ResumeFromException::RESUME_ENTRY_FRAME; - - MOZ_ASSERT(frameIter.done()); - rfe->stackPointer = frameIter.fp(); -} - -void EnsureExitFrame(CommonFrameLayout *frame) { if (frame->prevType() == JitFrame_Unwound_IonJS || diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/JitFrames.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/JitFrames.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/JitFrames.h 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/JitFrames.h 2015-01-09 12:36:47.000000000 +0000 @@ -269,7 +269,6 @@ }; void HandleException(ResumeFromException *rfe); -void HandleParallelFailure(ResumeFromException *rfe); void EnsureExitFrame(CommonFrameLayout *frame); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/LIR-Common.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/LIR-Common.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/LIR-Common.h 2015-01-07 22:15:24.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/LIR-Common.h 2015-01-09 12:36:47.000000000 +0000 @@ -801,74 +801,6 @@ } }; -class LNewPar : public LInstructionHelper<1, 1, 2> -{ - public: - LIR_HEADER(NewPar); - - LNewPar(const LAllocation &cx, const LDefinition &temp1, const LDefinition &temp2) { - setOperand(0, cx); - setTemp(0, temp1); - setTemp(1, temp2); - } - - MNewPar *mir() const { - return mir_->toNewPar(); - } - - const LAllocation *forkJoinContext() { - return getOperand(0); - } - - const LDefinition *getTemp0() { - return getTemp(0); - } - - const LDefinition *getTemp1() { - return getTemp(1); - } -}; - -class LNewDenseArrayPar : public LInstructionHelper<1, 2, 3> -{ - public: - LIR_HEADER(NewDenseArrayPar); - - LNewDenseArrayPar(const LAllocation &cx, const LAllocation &length, - const LDefinition &temp1, const LDefinition &temp2, const LDefinition &temp3) - { - setOperand(0, cx); - setOperand(1, length); - setTemp(0, temp1); - setTemp(1, temp2); - setTemp(2, temp3); - } - - MNewDenseArrayPar *mir() const { - return mir_->toNewDenseArrayPar(); - } - - const LAllocation *forkJoinContext() { - return getOperand(0); - } - - const LAllocation *length() { - return getOperand(1); - } - - const LDefinition *getTemp0() { - return getTemp(0); - } - - const LDefinition *getTemp1() { - return getTemp(1); - } - - const LDefinition *getTemp2() { - return getTemp(2); - } -}; - // Allocates a new DeclEnvObject. // // This instruction generates two possible instruction sets: @@ -945,40 +877,6 @@ } }; -class LNewCallObjectPar : public LInstructionHelper<1, 1, 2> -{ - LNewCallObjectPar(const LAllocation &cx, const LDefinition &temp1, const LDefinition &temp2) { - setOperand(0, cx); - setTemp(0, temp1); - setTemp(1, temp2); - } - -public: - LIR_HEADER(NewCallObjectPar); - - static LNewCallObjectPar *New(TempAllocator &alloc, const LAllocation &cx, - const LDefinition &temp1, const LDefinition &temp2) - { - return new(alloc) LNewCallObjectPar(cx, temp1, temp2); - } - - const LAllocation *forkJoinContext() { - return getOperand(0); - } - - const MNewCallObjectPar *mir() const { - return mir_->toNewCallObjectPar(); - } - - const LDefinition *getTemp0() { - return getTemp(0); - } - - const LDefinition *getTemp1() { - return getTemp(1); - } -}; - class LNewDerivedTypedObject : public LCallInstructionHelper<1, 3, 0> { public: @@ -1148,29 +1046,6 @@ } }; -class LCheckOverRecursedPar : public LInstructionHelper<0, 1, 1> -{ - public: - LIR_HEADER(CheckOverRecursedPar); - - LCheckOverRecursedPar(const LAllocation &cx, const LDefinition &tempReg) { - setOperand(0, cx); - setTemp(0, tempReg); - } - - const LAllocation *forkJoinContext() { - return getOperand(0); - } - - const LDefinition *getTempReg() { - return getTemp(0); - } - - MCheckOverRecursedPar *mir() const { - return mir_->toCheckOverRecursedPar(); - } -}; - class LAsmJSInterruptCheck : public LInstructionHelper<0, 0, 0> { Label *interruptExit_; @@ -1228,28 +1103,6 @@ } }; -class LInterruptCheckPar : public LInstructionHelper<0, 1, 1> -{ - public: - LIR_HEADER(InterruptCheckPar); - - LInterruptCheckPar(const LAllocation &cx, const LDefinition &tempReg) { - setOperand(0, cx); - setTemp(0, tempReg); - } - - const LAllocation *forkJoinContext() { - return getOperand(0); - } - - const LDefinition *getTempReg() { - return getTemp(0); - } - MInterruptCheckPar *mir() const { - return mir_->toInterruptCheckPar(); - } -}; - class LDefVar : public LCallInstructionHelper<0, 1, 0> { public: @@ -3379,47 +3232,6 @@ } }; -class LConcatPar : public LInstructionHelper<1, 3, 4> -{ - public: - LIR_HEADER(ConcatPar) - - LConcatPar(const LAllocation &cx, const LAllocation &lhs, const LAllocation &rhs, - const LDefinition &temp1, const LDefinition &temp2, const LDefinition &temp3, - const LDefinition &temp4) - { - setOperand(0, cx); - setOperand(1, lhs); - setOperand(2, rhs); - setTemp(0, temp1); - setTemp(1, temp2); - setTemp(2, temp3); - setTemp(3, temp4); - } - - const LAllocation *forkJoinContext() { - return this->getOperand(0); - } - const LAllocation *lhs() { - return this->getOperand(1); - } - const LAllocation *rhs() { - return this->getOperand(2); - } - const LDefinition *temp1() { - return this->getTemp(0); - } - const LDefinition *temp2() { - return this->getTemp(1); - } - const LDefinition *temp3() { - return this->getTemp(2); - } - const LDefinition *temp4() { - return this->getTemp(3); - } -}; - // Get uint16 character code from a string. class LCharCodeAt : public LInstructionHelper<1, 2, 0> { @@ -4091,36 +3903,6 @@ } }; -class LLambdaPar : public LInstructionHelper<1, 2, 2> -{ - public: - LIR_HEADER(LambdaPar); - - LLambdaPar(const LAllocation &cx, const LAllocation &scopeChain, - const LDefinition &temp1, const LDefinition &temp2) - { - setOperand(0, cx); - setOperand(1, scopeChain); - setTemp(0, temp1); - setTemp(1, temp2); - } - const LAllocation *forkJoinContext() { - return getOperand(0); - } - const LAllocation *scopeChain() { - return getOperand(1); - } - const MLambdaPar *mir() const { - return mir_->toLambdaPar(); - } - const LDefinition *getTemp0() { - return getTemp(0); - } - const LDefinition *getTemp1() { - return getTemp(1); - } -}; - // Load the "slots" member out of a JSObject. // Input: JSObject pointer // Output: slots pointer @@ -5303,17 +5085,13 @@ // Patchable jump to stubs generated for a GetProperty cache, which loads a // value of a known type, possibly into an FP register. -class LGetPropertyCacheT : public LInstructionHelper<1, 1, 1> +class LGetPropertyCacheT : public LInstructionHelper<1, 1, 0> { public: LIR_HEADER(GetPropertyCacheT) - LGetPropertyCacheT(const LAllocation &object, const LDefinition &temp) { + explicit LGetPropertyCacheT(const LAllocation &object) { setOperand(0, object); - setTemp(0, temp); - } - const LDefinition *temp() { - return getTemp(0); } const MGetPropertyCache *mir() const { return mir_->toGetPropertyCache(); @@ -5441,16 +5219,14 @@ } }; -class LGetElementCacheT : public LInstructionHelper<1, 2, 1> +class LGetElementCacheT : public LInstructionHelper<1, 2, 0> { public: LIR_HEADER(GetElementCacheT) - LGetElementCacheT(const LAllocation &object, const LAllocation &index, - const LDefinition &temp) { + LGetElementCacheT(const LAllocation &object, const LAllocation &index) { setOperand(0, object); setOperand(1, index); - setTemp(0, temp); } const LAllocation *object() { return getOperand(0); @@ -5461,9 +5237,6 @@ const LDefinition *output() { return getDef(0); } - const LDefinition *temp() { - return getTemp(0); - } const MGetElementCache *mir() const { return mir_->toGetElementCache(); } @@ -5678,52 +5451,6 @@ } }; -class LForkJoinContext : public LCallInstructionHelper<1, 0, 1> -{ - public: - LIR_HEADER(ForkJoinContext); - - explicit LForkJoinContext(const LDefinition &temp1) { - setTemp(0, temp1); - } - - const LDefinition *getTempReg() { - return getTemp(0); - } -}; - -class LForkJoinGetSlice : public LInstructionHelper<1, 1, 4> -{ - public: - LIR_HEADER(ForkJoinGetSlice); - - LForkJoinGetSlice(const LAllocation &cx, - const LDefinition &temp1, const LDefinition &temp2, - const LDefinition &temp3, const LDefinition &temp4) { - setOperand(0, cx); - setTemp(0, temp1); - setTemp(1, temp2); - setTemp(2, temp3); - setTemp(3, temp4); - } - - const LAllocation *forkJoinContext() { - return getOperand(0); - } - const LDefinition *temp1() { - return getTemp(0); - } - const LDefinition *temp2() { - return getTemp(1); - } - const LDefinition *temp3() { - return getTemp(2); - } - const LDefinition *temp4() { - return getTemp(3); - } -}; - class LCallGetProperty : public LCallInstructionHelper { public: @@ -5821,16 +5548,14 @@ // Patchable jump to stubs generated for a SetProperty cache, which stores a // boxed value. -class LSetPropertyCacheV : public LInstructionHelper<0, 1 + BOX_PIECES, 2> +class LSetPropertyCacheV : public LInstructionHelper<0, 1 + BOX_PIECES, 1> { public: LIR_HEADER(SetPropertyCacheV) - LSetPropertyCacheV(const LAllocation &object, const LDefinition &slots, - const LDefinition &temp) { + LSetPropertyCacheV(const LAllocation &object, const LDefinition &slots) { setOperand(0, object); setTemp(0, slots); - setTemp(1, temp); } static const size_t Value = 1; @@ -5838,15 +5563,11 @@ const MSetPropertyCache *mir() const { return mir_->toSetPropertyCache(); } - - const LDefinition *tempForDispatchCache() { - return getTemp(1); - } }; // Patchable jump to stubs generated for a SetProperty cache, which stores a // value of a known type. -class LSetPropertyCacheT : public LInstructionHelper<0, 2, 2> +class LSetPropertyCacheT : public LInstructionHelper<0, 2, 1> { MIRType valueType_; @@ -5854,14 +5575,12 @@ LIR_HEADER(SetPropertyCacheT) LSetPropertyCacheT(const LAllocation &object, const LDefinition &slots, - const LAllocation &value, const LDefinition &temp, - MIRType valueType) + const LAllocation &value, MIRType valueType) : valueType_(valueType) { setOperand(0, object); setOperand(1, value); setTemp(0, slots); - setTemp(1, temp); } const MSetPropertyCache *mir() const { @@ -5873,10 +5592,6 @@ const char *extraName() const { return StringFromMIRType(valueType_); } - - const LDefinition *tempForDispatchCache() { - return getTemp(1); - } }; class LSetElementCacheV : public LInstructionHelper<0, 1 + 2 * BOX_PIECES, 4> @@ -6184,55 +5899,6 @@ } }; -class LRestPar : public LInstructionHelper<1, 2, 3> -{ - public: - LIR_HEADER(RestPar); - - LRestPar(const LAllocation &cx, const LAllocation &numActuals, - const LDefinition &temp1, const LDefinition &temp2, const LDefinition &temp3) - { - setOperand(0, cx); - setOperand(1, numActuals); - setTemp(0, temp1); - setTemp(1, temp2); - setTemp(2, temp3); - } - const LAllocation *forkJoinContext() { - return getOperand(0); - } - const LAllocation *numActuals() { - return getOperand(1); - } - MRestPar *mir() const { - return mir_->toRestPar(); - } -}; - -class LGuardThreadExclusive : public LCallInstructionHelper<0, 2, 1> -{ - public: - LIR_HEADER(GuardThreadExclusive); - - LGuardThreadExclusive(const LAllocation &cx, const LAllocation &object, const LDefinition &temp1) { - setOperand(0, cx); - setOperand(1, object); - setTemp(0, temp1); - } - - const LAllocation *forkJoinContext() { - return getOperand(0); - } - - const LAllocation *object() { - return getOperand(1); - } - - const LDefinition *getTempReg() { - return getTemp(0); - } -}; - class LGuardShapePolymorphic : public LInstructionHelper<0, 1, 1> { public: diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/LIR.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/LIR.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/LIR.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/LIR.h 2015-01-09 12:36:47.000000000 +0000 @@ -569,8 +569,6 @@ return LDefinition::SLOTS; case MIRType_Pointer: return LDefinition::GENERAL; - case MIRType_ForkJoinContext: - return LDefinition::GENERAL; case MIRType_Int32x4: return LDefinition::INT32X4; case MIRType_Float32x4: diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/LOpcodes.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/LOpcodes.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/LOpcodes.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/LOpcodes.h 2015-01-09 12:36:47.000000000 +0000 @@ -55,9 +55,6 @@ _(NewCallObject) \ _(NewSingletonCallObject) \ _(NewStringObject) \ - _(NewPar) \ - _(NewDenseArrayPar) \ - _(NewCallObjectPar) \ _(NewDerivedTypedObject) \ _(InitElem) \ _(InitElemGetterSetter) \ @@ -65,7 +62,6 @@ _(InitProp) \ _(InitPropGetterSetter) \ _(CheckOverRecursed) \ - _(CheckOverRecursedPar) \ _(DefVar) \ _(DefFun) \ _(CallKnown) \ @@ -156,7 +152,6 @@ _(ModD) \ _(BinaryV) \ _(Concat) \ - _(ConcatPar) \ _(CharCodeAt) \ _(FromCharCode) \ _(StringSplit) \ @@ -193,7 +188,6 @@ _(Lambda) \ _(LambdaArrow) \ _(LambdaForSingleton) \ - _(LambdaPar) \ _(Slots) \ _(Elements) \ _(ConvertElementsToDoubles) \ @@ -208,7 +202,6 @@ _(GuardObjectType) \ _(GuardObjectIdentity) \ _(GuardClass) \ - _(GuardThreadExclusive) \ _(TypeBarrierV) \ _(TypeBarrierO) \ _(MonitorTypes) \ @@ -252,8 +245,6 @@ _(StoreFixedSlotV) \ _(StoreFixedSlotT) \ _(FunctionEnvironment) \ - _(ForkJoinContext) \ - _(ForkJoinGetSlice) \ _(GetPropertyCacheV) \ _(GetPropertyCacheT) \ _(GetPropertyPolymorphicV) \ @@ -297,7 +288,6 @@ _(SetFrameArgumentV) \ _(RunOncePrologue) \ _(Rest) \ - _(RestPar) \ _(TypeOfV) \ _(ToIdV) \ _(Floor) \ @@ -336,7 +326,6 @@ _(AsmJSCall) \ _(AsmJSCompareExchangeHeap) \ _(AsmJSAtomicBinopHeap) \ - _(InterruptCheckPar) \ _(RecompileCheck) \ _(MemoryBarrier) \ _(AssertRangeI) \ diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/Lowering.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/Lowering.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/Lowering.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/Lowering.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -131,15 +131,6 @@ } void -LIRGenerator::visitCheckOverRecursedPar(MCheckOverRecursedPar *ins) -{ - LCheckOverRecursedPar *lir = - new(alloc()) LCheckOverRecursedPar(useRegister(ins->forkJoinContext()), temp()); - add(lir, ins); - assignSafepoint(lir, ins); -} - -void LIRGenerator::visitDefVar(MDefVar *ins) { LDefVar *lir = new(alloc()) LDefVar(useRegisterAtStart(ins->scopeChain())); @@ -243,15 +234,6 @@ } void -LIRGenerator::visitNewCallObjectPar(MNewCallObjectPar *ins) -{ - const LAllocation &parThreadContext = useRegister(ins->forkJoinContext()); - LNewCallObjectPar *lir = LNewCallObjectPar::New(alloc(), parThreadContext, temp(), temp()); - define(lir, ins); - assignSafepoint(lir, ins); -} - -void LIRGenerator::visitNewStringObject(MNewStringObject *ins) { MOZ_ASSERT(ins->input()->type() == MIRType_String); @@ -1600,28 +1582,6 @@ } void -LIRGenerator::visitConcatPar(MConcatPar *ins) -{ - MDefinition *cx = ins->forkJoinContext(); - MDefinition *lhs = ins->lhs(); - MDefinition *rhs = ins->rhs(); - - MOZ_ASSERT(lhs->type() == MIRType_String); - MOZ_ASSERT(rhs->type() == MIRType_String); - MOZ_ASSERT(ins->type() == MIRType_String); - - LConcatPar *lir = new(alloc()) LConcatPar(useFixed(cx, CallTempReg4), - useFixedAtStart(lhs, CallTempReg0), - useFixedAtStart(rhs, CallTempReg1), - tempFixed(CallTempReg0), - tempFixed(CallTempReg1), - tempFixed(CallTempReg2), - tempFixed(CallTempReg3)); - defineFixed(lir, ins, LAllocation(AnyRegister(CallTempReg5))); - assignSafepoint(lir, ins); -} - -void LIRGenerator::visitCharCodeAt(MCharCodeAt *ins) { MDefinition *str = ins->getOperand(0); @@ -2172,18 +2132,6 @@ } void -LIRGenerator::visitLambdaPar(MLambdaPar *ins) -{ - MOZ_ASSERT(!ins->info().singletonType); - MOZ_ASSERT(!ins->info().useNewTypeForClone); - LLambdaPar *lir = new(alloc()) LLambdaPar(useRegister(ins->forkJoinContext()), - useRegister(ins->scopeChain()), - temp(), temp()); - define(lir, ins); - assignSafepoint(lir, ins); -} - -void LIRGenerator::visitSlots(MSlots *ins) { define(new(alloc()) LSlots(useRegisterAtStart(ins->object())), ins); @@ -2254,29 +2202,6 @@ } void -LIRGenerator::visitForkJoinContext(MForkJoinContext *ins) -{ - LForkJoinContext *lir = new(alloc()) LForkJoinContext(tempFixed(CallTempReg0)); - defineReturn(lir, ins); -} - -void -LIRGenerator::visitGuardThreadExclusive(MGuardThreadExclusive *ins) -{ - // FIXME (Bug 956281) -- For now, we always generate the most - // general form of write guard check. we could employ TI feedback - // to optimize this if we know that the object being tested is a - // typed object or know that it is definitely NOT a typed object. - LGuardThreadExclusive *lir = - new(alloc()) LGuardThreadExclusive(useFixed(ins->forkJoinContext(), CallTempReg0), - useFixed(ins->object(), CallTempReg1), - tempFixed(CallTempReg2)); - lir->setMir(ins); - assignSnapshot(lir, Bailout_GuardThreadExclusive); - add(lir, ins); -} - -void LIRGenerator::visitInterruptCheck(MInterruptCheck *ins) { // Implicit interrupt checks require asm.js signal handlers to be installed. @@ -2300,40 +2225,6 @@ } void -LIRGenerator::visitInterruptCheckPar(MInterruptCheckPar *ins) -{ - LInterruptCheckPar *lir = - new(alloc()) LInterruptCheckPar(useRegister(ins->forkJoinContext()), temp()); - add(lir, ins); - assignSafepoint(lir, ins); -} - -void -LIRGenerator::visitNewPar(MNewPar *ins) -{ - LNewPar *lir = new(alloc()) LNewPar(useRegister(ins->forkJoinContext()), temp(), temp()); - define(lir, ins); - assignSafepoint(lir, ins); -} - -void -LIRGenerator::visitNewDenseArrayPar(MNewDenseArrayPar *ins) -{ - MOZ_ASSERT(ins->forkJoinContext()->type() == MIRType_ForkJoinContext); - MOZ_ASSERT(ins->length()->type() == MIRType_Int32); - MOZ_ASSERT(ins->type() == MIRType_Object); - - LNewDenseArrayPar *lir = - new(alloc()) LNewDenseArrayPar(useRegister(ins->forkJoinContext()), - useRegister(ins->length()), - temp(), - temp(), - temp()); - define(lir, ins); - assignSafepoint(lir, ins); -} - -void LIRGenerator::visitStoreSlot(MStoreSlot *ins) { LInstruction *lir; @@ -3155,8 +3046,7 @@ defineBox(lir, ins); assignSafepoint(lir, ins); } else { - LGetPropertyCacheT *lir = new(alloc()) LGetPropertyCacheT(useRegister(ins->object()), - tempForDispatchCache(ins->type())); + LGetPropertyCacheT *lir = new(alloc()) LGetPropertyCacheT(useRegister(ins->object())); define(lir, ins); assignSafepoint(lir, ins); } @@ -3216,8 +3106,7 @@ } else { MOZ_ASSERT(ins->index()->type() == MIRType_Int32); LGetElementCacheT *lir = new(alloc()) LGetElementCacheT(useRegister(ins->object()), - useRegister(ins->index()), - tempForDispatchCache(ins->type())); + useRegister(ins->index())); define(lir, ins); assignSafepoint(lir, ins); } @@ -3373,15 +3262,14 @@ { LUse obj = useRegisterAtStart(ins->object()); LDefinition slots = tempCopy(ins->object(), 0); - LDefinition dispatchTemp = tempForDispatchCache(); LInstruction *lir; if (ins->value()->type() == MIRType_Value) { - lir = new(alloc()) LSetPropertyCacheV(obj, slots, dispatchTemp); + lir = new(alloc()) LSetPropertyCacheV(obj, slots); useBox(lir, LSetPropertyCacheV::Value, ins->value()); } else { LAllocation value = useRegisterOrConstant(ins->value()); - lir = new(alloc()) LSetPropertyCacheT(obj, slots, value, dispatchTemp, ins->value()->type()); + lir = new(alloc()) LSetPropertyCacheT(obj, slots, value, ins->value()->type()); } add(lir, ins); @@ -3543,20 +3431,6 @@ assignSafepoint(lir, ins); } -void -LIRGenerator::visitRestPar(MRestPar *ins) -{ - MOZ_ASSERT(ins->numActuals()->type() == MIRType_Int32); - - LRestPar *lir = new(alloc()) LRestPar(useRegister(ins->forkJoinContext()), - useRegister(ins->numActuals()), - temp(), - temp(), - temp()); - define(lir, ins); - assignSafepoint(lir, ins); -} - void LIRGenerator::visitThrow(MThrow *ins) { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/Lowering.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/Lowering.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/Lowering.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/Lowering.h 2015-01-09 12:36:47.000000000 +0000 @@ -80,16 +80,12 @@ void visitNewRunOnceCallObject(MNewRunOnceCallObject *ins); void visitNewStringObject(MNewStringObject *ins); void visitNewDerivedTypedObject(MNewDerivedTypedObject *ins); - void visitNewPar(MNewPar *ins); - void visitNewCallObjectPar(MNewCallObjectPar *ins); - void visitNewDenseArrayPar(MNewDenseArrayPar *ins); void visitInitElem(MInitElem *ins); void visitInitElemGetterSetter(MInitElemGetterSetter *ins); void visitMutateProto(MMutateProto *ins); void visitInitProp(MInitProp *ins); void visitInitPropGetterSetter(MInitPropGetterSetter *ins); void visitCheckOverRecursed(MCheckOverRecursed *ins); - void visitCheckOverRecursedPar(MCheckOverRecursedPar *ins); void visitDefVar(MDefVar *ins); void visitDefFun(MDefFun *ins); void visitCreateThisWithTemplate(MCreateThisWithTemplate *ins); @@ -142,7 +138,6 @@ void visitDiv(MDiv *ins); void visitMod(MMod *ins); void visitConcat(MConcat *ins); - void visitConcatPar(MConcatPar *ins); void visitCharCodeAt(MCharCodeAt *ins); void visitFromCharCode(MFromCharCode *ins); void visitStringSplit(MStringSplit *ins); @@ -167,7 +162,6 @@ void visitStringReplace(MStringReplace *ins); void visitLambda(MLambda *ins); void visitLambdaArrow(MLambdaArrow *ins); - void visitLambdaPar(MLambdaPar *ins); void visitSlots(MSlots *ins); void visitElements(MElements *ins); void visitConstantElements(MConstantElements *ins); @@ -176,11 +170,8 @@ void visitMaybeCopyElementsForWrite(MMaybeCopyElementsForWrite *ins); void visitLoadSlot(MLoadSlot *ins); void visitFunctionEnvironment(MFunctionEnvironment *ins); - void visitForkJoinContext(MForkJoinContext *ins); - void visitGuardThreadExclusive(MGuardThreadExclusive *ins); void visitInterruptCheck(MInterruptCheck *ins); void visitAsmJSInterruptCheck(MAsmJSInterruptCheck *ins); - void visitInterruptCheckPar(MInterruptCheckPar *ins); void visitStoreSlot(MStoreSlot *ins); void visitFilterTypeSet(MFilterTypeSet *ins); void visitTypeBarrier(MTypeBarrier *ins); @@ -252,7 +243,6 @@ void visitSetFrameArgument(MSetFrameArgument *ins); void visitRunOncePrologue(MRunOncePrologue *ins); void visitRest(MRest *ins); - void visitRestPar(MRestPar *ins); void visitThrow(MThrow *ins); void visitIn(MIn *ins); void visitInArray(MInArray *ins); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/MacroAssembler.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/MacroAssembler.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/MacroAssembler.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/MacroAssembler.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -18,9 +18,7 @@ #include "jit/BaselineJIT.h" #include "jit/Lowering.h" #include "jit/MIR.h" -#include "jit/ParallelFunctions.h" #include "js/Conversions.h" -#include "vm/ForkJoin.h" #include "vm/TraceLogging.h" #include "jsgcinlines.h" @@ -836,86 +834,6 @@ } void -MacroAssembler::newGCThingPar(Register result, Register cx, Register tempReg1, Register tempReg2, - gc::AllocKind allocKind, Label *fail) -{ - return newGCTenuredThingPar(result, cx, tempReg1, tempReg2, allocKind, fail); -} - -void -MacroAssembler::newGCTenuredThingPar(Register result, Register cx, - Register tempReg1, Register tempReg2, - gc::AllocKind allocKind, Label *fail) -{ - // Similar to ::newGCThing(), except that it allocates from a custom - // Allocator in the ForkJoinContext*, rather than being hardcoded to the - // compartment allocator. This requires two temporary registers. - // - // Subtle: I wanted to reuse `result` for one of the temporaries, but the - // register allocator was assigning it to the same register as `cx`. - // Then we overwrite that register which messed up the OOL code. - - uint32_t thingSize = (uint32_t)gc::Arena::thingSize(allocKind); - - // Load the allocator: - // tempReg1 = (Allocator*) forkJoinCx->allocator() - loadPtr(Address(cx, ThreadSafeContext::offsetOfAllocator()), - tempReg1); - - // Get a pointer to the relevant free list: - // tempReg1 = (FreeList*) &tempReg1->arenas.freeLists[(allocKind)] - uint32_t offset = (offsetof(Allocator, arenas) + - js::gc::ArenaLists::getFreeListOffset(allocKind)); - addPtr(Imm32(offset), tempReg1); - - // Load first item on the list - // tempReg2 = tempReg1->head.first - loadPtr(Address(tempReg1, gc::FreeList::offsetOfFirst()), tempReg2); - - // Check whether bump-allocation is possible. - // if tempReg1->head.last <= tempReg2, fail - branchPtr(Assembler::BelowOrEqual, - Address(tempReg1, gc::FreeList::offsetOfLast()), - tempReg2, - fail); - - // If so, take |first| and advance pointer by thingSize bytes. - // result = tempReg2; - // tempReg2 += thingSize; - movePtr(tempReg2, result); - addPtr(Imm32(thingSize), tempReg2); - - // Update |first|. - // tempReg1->head.first = tempReg2; - storePtr(tempReg2, Address(tempReg1, gc::FreeList::offsetOfFirst())); -} - -void -MacroAssembler::newGCThingPar(Register result, Register cx, Register tempReg1, Register tempReg2, - NativeObject *templateObject, Label *fail) -{ - gc::AllocKind allocKind = templateObject->asTenured().getAllocKind(); - MOZ_ASSERT(allocKind >= gc::FINALIZE_OBJECT0 && allocKind <= gc::FINALIZE_OBJECT_LAST); - MOZ_ASSERT(!templateObject->numDynamicSlots()); - - newGCThingPar(result, cx, tempReg1, tempReg2, allocKind, fail); -} - -void -MacroAssembler::newGCStringPar(Register result, Register cx, Register tempReg1, Register tempReg2, - Label *fail) -{ - newGCTenuredThingPar(result, cx, tempReg1, tempReg2, js::gc::FINALIZE_STRING, fail); -} - -void -MacroAssembler::newGCFatInlineStringPar(Register result, Register cx, Register tempReg1, - Register tempReg2, Label *fail) -{ - newGCTenuredThingPar(result, cx, tempReg1, tempReg2, js::gc::FINALIZE_FAT_INLINE_STRING, fail); -} - -void MacroAssembler::copySlotsFromTemplate(Register obj, const NativeObject *templateObj, uint32_t start, uint32_t end) { @@ -1203,13 +1121,6 @@ bind(&done); } -void -MacroAssembler::checkInterruptFlagPar(Register tempReg, Label *fail) -{ - movePtr(ImmPtr(GetJitContext()->runtime->addressOfInterruptParUint32()), tempReg); - branch32(Assembler::NonZero, Address(tempReg, 0), Imm32(0), fail); -} - // Save an exit frame (which must be aligned to the stack pointer) to // PerThreadData::jitTop of the main thread. void @@ -1219,15 +1130,6 @@ storePtr(StackPointer, jitTop); } -// Save an exit frame to the thread data of the current thread, given a -// register that holds a PerThreadData *. -void -MacroAssembler::linkParallelExitFrame(Register pt) -{ - Address jitTop(pt, offsetof(PerThreadData, jitTop)); - storePtr(StackPointer, jitTop); -} - static void ReportOverRecursed(JSContext *cx) { @@ -1384,52 +1286,19 @@ } void -MacroAssembler::loadBaselineOrIonRaw(Register script, Register dest, ExecutionMode mode, - Label *failure) +MacroAssembler::loadBaselineOrIonRaw(Register script, Register dest, Label *failure) { - if (mode == SequentialExecution) { - loadPtr(Address(script, JSScript::offsetOfBaselineOrIonRaw()), dest); - if (failure) - branchTestPtr(Assembler::Zero, dest, dest, failure); - } else { - loadPtr(Address(script, JSScript::offsetOfParallelIonScript()), dest); - if (failure) - branchPtr(Assembler::BelowOrEqual, dest, ImmPtr(ION_COMPILING_SCRIPT), failure); - loadPtr(Address(dest, IonScript::offsetOfMethod()), dest); - loadPtr(Address(dest, JitCode::offsetOfCode()), dest); - } + loadPtr(Address(script, JSScript::offsetOfBaselineOrIonRaw()), dest); + if (failure) + branchTestPtr(Assembler::Zero, dest, dest, failure); } void -MacroAssembler::loadBaselineOrIonNoArgCheck(Register script, Register dest, ExecutionMode mode, - Label *failure) +MacroAssembler::loadBaselineOrIonNoArgCheck(Register script, Register dest, Label *failure) { - if (mode == SequentialExecution) { - loadPtr(Address(script, JSScript::offsetOfBaselineOrIonSkipArgCheck()), dest); - if (failure) - branchTestPtr(Assembler::Zero, dest, dest, failure); - } else { - // Find second register to get the offset to skip argument check - Register offset = script; - if (script == dest) { - GeneralRegisterSet regs(GeneralRegisterSet::All()); - regs.take(dest); - offset = regs.takeAny(); - } - - loadPtr(Address(script, JSScript::offsetOfParallelIonScript()), dest); - if (failure) - branchPtr(Assembler::BelowOrEqual, dest, ImmPtr(ION_COMPILING_SCRIPT), failure); - - Push(offset); - load32(Address(script, IonScript::offsetOfSkipArgCheckEntryOffset()), offset); - - loadPtr(Address(dest, IonScript::offsetOfMethod()), dest); - loadPtr(Address(dest, JitCode::offsetOfCode()), dest); - addPtr(offset, dest); - - Pop(offset); - } + loadPtr(Address(script, JSScript::offsetOfBaselineOrIonSkipArgCheck()), dest); + if (failure) + branchTestPtr(Assembler::Zero, dest, dest, failure); } void @@ -1441,96 +1310,7 @@ } void -MacroAssembler::loadForkJoinContext(Register cx, Register scratch) -{ - // Load the current ForkJoinContext *. If we need a parallel exit frame, - // chances are we are about to do something very slow anyways, so just - // call ForkJoinContextPar again instead of using the cached version. - setupUnalignedABICall(0, scratch); - callWithABI(JS_FUNC_TO_DATA_PTR(void *, ForkJoinContextPar)); - if (ReturnReg != cx) - movePtr(ReturnReg, cx); -} - -void -MacroAssembler::loadContext(Register cxReg, Register scratch, ExecutionMode executionMode) -{ - switch (executionMode) { - case SequentialExecution: - // The scratch register is not used for sequential execution. - loadJSContext(cxReg); - break; - case ParallelExecution: - loadForkJoinContext(cxReg, scratch); - break; - default: - MOZ_CRASH("No such execution mode"); - } -} - -void -MacroAssembler::enterParallelExitFrameAndLoadContext(const VMFunction *f, Register cx, - Register scratch) -{ - loadForkJoinContext(cx, scratch); - // Load the PerThreadData from from the cx. - loadPtr(Address(cx, offsetof(ForkJoinContext, perThreadData)), scratch); - linkParallelExitFrame(scratch); - // Push the ioncode. - exitCodePatch_ = PushWithPatch(ImmWord(-1)); - // Push the VMFunction pointer, to mark arguments. - Push(ImmPtr(f)); -} - -void -MacroAssembler::enterFakeParallelExitFrame(Register cx, Register scratch, - JitCode *codeVal) -{ - // Load the PerThreadData from from the cx. - loadPtr(Address(cx, offsetof(ForkJoinContext, perThreadData)), scratch); - linkParallelExitFrame(scratch); - Push(ImmPtr(codeVal)); - Push(ImmPtr(nullptr)); -} - -void -MacroAssembler::enterExitFrameAndLoadContext(const VMFunction *f, Register cxReg, Register scratch, - ExecutionMode executionMode) -{ - switch (executionMode) { - case SequentialExecution: - // The scratch register is not used for sequential execution. - enterExitFrame(f); - loadJSContext(cxReg); - break; - case ParallelExecution: - enterParallelExitFrameAndLoadContext(f, cxReg, scratch); - break; - default: - MOZ_CRASH("No such execution mode"); - } -} - -void -MacroAssembler::enterFakeExitFrame(Register cxReg, Register scratch, - ExecutionMode executionMode, - JitCode *codeVal) -{ - switch (executionMode) { - case SequentialExecution: - // The cx and scratch registers are not used for sequential execution. - enterFakeExitFrame(codeVal); - break; - case ParallelExecution: - enterFakeParallelExitFrame(cxReg, scratch, codeVal); - break; - default: - MOZ_CRASH("No such execution mode"); - } -} - -void -MacroAssembler::handleFailure(ExecutionMode executionMode) +MacroAssembler::handleFailure() { // Re-entry code is irrelevant because the exception will leave the // running function and never come back @@ -1538,17 +1318,7 @@ sps_->skipNextReenter(); leaveSPSFrame(); - JitCode *excTail; - switch (executionMode) { - case SequentialExecution: - excTail = GetJitContext()->runtime->jitRuntime()->getExceptionTail(); - break; - case ParallelExecution: - excTail = GetJitContext()->runtime->jitRuntime()->getExceptionTailParallel(); - break; - default: - MOZ_CRASH("No such execution mode"); - } + JitCode *excTail = GetJitContext()->runtime->jitRuntime()->getExceptionTail(); jump(excTail); // Doesn't actually emit code, but balances the leave() @@ -2147,13 +1917,9 @@ void MacroAssembler::finish() { - if (sequentialFailureLabel_.used()) { - bind(&sequentialFailureLabel_); - handleFailure(SequentialExecution); - } - if (parallelFailureLabel_.used()) { - bind(¶llelFailureLabel_); - handleFailure(ParallelExecution); + if (failureLabel_.used()) { + bind(&failureLabel_); + handleFailure(); } MacroAssemblerSpecific::finish(); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/MacroAssembler.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/MacroAssembler.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/MacroAssembler.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/MacroAssembler.h 2015-01-09 12:36:47.000000000 +0000 @@ -198,8 +198,7 @@ IonInstrumentation *sps_; // Labels for handling exceptions and failures. - NonAssertingLabel sequentialFailureLabel_; - NonAssertingLabel parallelFailureLabel_; + NonAssertingLabel failureLabel_; public: // If instrumentation should be emitted, then the sps parameter should be @@ -830,27 +829,11 @@ void newGCString(Register result, Register temp, Label *fail); void newGCFatInlineString(Register result, Register temp, Label *fail); - void newGCThingPar(Register result, Register cx, Register tempReg1, Register tempReg2, - gc::AllocKind allocKind, Label *fail); - void newGCTenuredThingPar(Register result, Register cx, Register tempReg1, Register tempReg2, - gc::AllocKind allocKind, Label *fail); - void newGCThingPar(Register result, Register cx, Register tempReg1, Register tempReg2, - NativeObject *templateObject, Label *fail); - void newGCStringPar(Register result, Register cx, Register tempReg1, Register tempReg2, - Label *fail); - void newGCFatInlineStringPar(Register result, Register cx, Register tempReg1, Register tempReg2, - Label *fail); - - // Compares two strings for equality based on the JSOP. // This checks for identical pointers, atoms and length and fails for everything else. void compareStrings(JSOp op, Register left, Register right, Register result, Label *fail); - // Checks the flags that signal that parallel code may need to interrupt or - // abort. Branches to fail in that case. - void checkInterruptFlagPar(Register tempReg, Label *fail); - // If the JitCode that created this assembler needs to transition into the VM, // we want to store the JitCode on the stack in order to mark it during a GC. // This is a reference to a patch location where the JitCode* will be written. @@ -859,7 +842,6 @@ private: void linkExitFrame(); - void linkParallelExitFrame(Register pt); public: void enterExitFrame(const VMFunction *f = nullptr) { @@ -884,20 +866,6 @@ movePtr(ImmPtr(GetJitContext()->runtime->addressOfThreadPool()), pool); } - void loadForkJoinContext(Register cx, Register scratch); - void loadContext(Register cxReg, Register scratch, ExecutionMode executionMode); - - void enterParallelExitFrameAndLoadContext(const VMFunction *f, Register cx, - Register scratch); - - void enterExitFrameAndLoadContext(const VMFunction *f, Register cxReg, Register scratch, - ExecutionMode executionMode); - - void enterFakeParallelExitFrame(Register cx, Register scratch, JitCode *codeVal); - - void enterFakeExitFrame(Register cxReg, Register scratch, ExecutionMode executionMode, - JitCode *codeVal); - void leaveExitFrame() { freeStack(ExitFooterFrame::Size()); } @@ -1169,8 +1137,8 @@ void spsMarkJit(SPSProfiler *p, Register framePtr, Register temp); void spsUnmarkJit(SPSProfiler *p, Register temp); - void loadBaselineOrIonRaw(Register script, Register dest, ExecutionMode mode, Label *failure); - void loadBaselineOrIonNoArgCheck(Register callee, Register dest, ExecutionMode mode, Label *failure); + void loadBaselineOrIonRaw(Register script, Register dest, Label *failure); + void loadBaselineOrIonNoArgCheck(Register callee, Register dest, Label *failure); void loadBaselineFramePtr(Register framePtr, Register dest); @@ -1180,20 +1148,16 @@ } private: - void handleFailure(ExecutionMode executionMode); + void handleFailure(); public: Label *exceptionLabel() { // Exceptions are currently handled the same way as sequential failures. - return &sequentialFailureLabel_; + return &failureLabel_; } - Label *failureLabel(ExecutionMode executionMode) { - switch (executionMode) { - case SequentialExecution: return &sequentialFailureLabel_; - case ParallelExecution: return ¶llelFailureLabel_; - default: MOZ_CRASH("Unexpected execution mode"); - } + Label *failureLabel() { + return &failureLabel_; } void finish(); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/MCallOptimize.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/MCallOptimize.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/MCallOptimize.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/MCallOptimize.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -166,8 +166,6 @@ // Array intrinsics. if (native == intrinsic_UnsafePutElements) return inlineUnsafePutElements(callInfo); - if (native == intrinsic_NewDenseArray) - return inlineNewDenseArray(callInfo); // Slot intrinsics. if (native == intrinsic_UnsafeSetReservedSlot) @@ -183,13 +181,6 @@ if (native == intrinsic_UnsafeGetBooleanFromReservedSlot) return inlineUnsafeGetReservedSlot(callInfo, MIRType_Boolean); - // Parallel intrinsics. - if (native == intrinsic_ShouldForceSequential || - native == intrinsic_InParallelSection) - return inlineForceSequentialOrInParallelSection(callInfo); - if (native == intrinsic_ForkJoinGetSlice) - return inlineForkJoinGetSlice(callInfo); - // Utility intrinsics. if (native == intrinsic_IsCallable) return inlineIsCallable(callInfo); @@ -242,8 +233,6 @@ return inlineSetTypedObjectOffset(callInfo); // Testing Functions - if (native == testingFunc_inParallelSection) - return inlineForceSequentialOrInParallelSection(callInfo); if (native == testingFunc_bailout) return inlineBailout(callInfo); if (native == testingFunc_assertFloat32) @@ -1777,129 +1766,6 @@ } IonBuilder::InliningStatus -IonBuilder::inlineForceSequentialOrInParallelSection(CallInfo &callInfo) -{ - if (callInfo.constructing()) - return InliningStatus_NotInlined; - - ExecutionMode executionMode = info().executionMode(); - switch (executionMode) { - case ParallelExecution: { - // During Parallel Exec, we always force sequential, so - // replace with true. This permits UCE to eliminate the - // entire path as dead, which is important. - callInfo.setImplicitlyUsedUnchecked(); - MConstant *ins = MConstant::New(alloc(), BooleanValue(true)); - current->add(ins); - current->push(ins); - return InliningStatus_Inlined; - } - - default: - // In sequential mode, leave as is, because we'd have to - // access the "in warmup" flag of the runtime. - return InliningStatus_NotInlined; - } - - MOZ_CRASH("Invalid execution mode"); -} - -IonBuilder::InliningStatus -IonBuilder::inlineForkJoinGetSlice(CallInfo &callInfo) -{ - if (info().executionMode() != ParallelExecution) - return InliningStatus_NotInlined; - - // Assert the way the function is used instead of testing, as it is a - // self-hosted function which must be used in a particular fashion. - MOZ_ASSERT(callInfo.argc() == 1 && !callInfo.constructing()); - MOZ_ASSERT(callInfo.getArg(0)->type() == MIRType_Int32); - - // Test this, as we might have not executed the native despite knowing the - // target here. - if (getInlineReturnType() != MIRType_Int32) - return InliningStatus_NotInlined; - - callInfo.setImplicitlyUsedUnchecked(); - - switch (info().executionMode()) { - case ParallelExecution: - if (LIRGenerator::allowInlineForkJoinGetSlice()) { - MForkJoinGetSlice *getSlice = MForkJoinGetSlice::New(alloc(), - graph().forkJoinContext()); - current->add(getSlice); - current->push(getSlice); - return InliningStatus_Inlined; - } - return InliningStatus_NotInlined; - - default: - // ForkJoinGetSlice acts as identity for sequential execution. - current->push(callInfo.getArg(0)); - return InliningStatus_Inlined; - } - - MOZ_CRASH("Invalid execution mode"); -} - -IonBuilder::InliningStatus -IonBuilder::inlineNewDenseArray(CallInfo &callInfo) -{ - if (callInfo.constructing() || callInfo.argc() != 1) - return InliningStatus_NotInlined; - - // For now, in seq. mode we just call the C function. In - // par. mode we use inlined MIR. - ExecutionMode executionMode = info().executionMode(); - switch (executionMode) { - case ParallelExecution: - return inlineNewDenseArrayForParallelExecution(callInfo); - default: - return inlineNewDenseArrayForSequentialExecution(callInfo); - } - - MOZ_CRASH("unknown ExecutionMode"); -} - -IonBuilder::InliningStatus -IonBuilder::inlineNewDenseArrayForSequentialExecution(CallInfo &callInfo) -{ - // not yet implemented; in seq. mode the C function is not so bad - return InliningStatus_NotInlined; -} - -IonBuilder::InliningStatus -IonBuilder::inlineNewDenseArrayForParallelExecution(CallInfo &callInfo) -{ - // Create the new parallel array object. Parallel arrays have specially - // constructed type objects, so we can only perform the inlining if we - // already have one of these type objects. - types::TemporaryTypeSet *returnTypes = getInlineReturnTypeSet(); - if (returnTypes->getKnownMIRType() != MIRType_Object) - return InliningStatus_NotInlined; - if (returnTypes->unknownObject() || returnTypes->getObjectCount() != 1) - return InliningStatus_NotInlined; - if (callInfo.getArg(0)->type() != MIRType_Int32) - return InliningStatus_NotInlined; - types::TypeObject *typeObject = returnTypes->getTypeObject(0); - - NativeObject *templateObject = inspector->getTemplateObjectForNative(pc, intrinsic_NewDenseArray); - if (!templateObject || templateObject->type() != typeObject) - return InliningStatus_NotInlined; - - callInfo.setImplicitlyUsedUnchecked(); - - MNewDenseArrayPar *newObject = MNewDenseArrayPar::New(alloc(), - graph().forkJoinContext(), - callInfo.getArg(0), - &templateObject->as()); - current->add(newObject); - current->push(newObject); - - return InliningStatus_Inlined; -} - -IonBuilder::InliningStatus IonBuilder::inlineHasClass(CallInfo &callInfo, const Class *clasp1, const Class *clasp2, const Class *clasp3, const Class *clasp4) diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/mips/Bailouts-mips.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/mips/Bailouts-mips.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/mips/Bailouts-mips.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/mips/Bailouts-mips.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -22,10 +22,7 @@ JSScript *script = ScriptFromCalleeToken(((JitFrameLayout *) framePointer_)->calleeToken()); JitActivation *activation = activations.activation()->asJit(); - if (activation->cx()->isForkJoinContext()) - topIonScript_ = script->parallelIonScript(); - else - topIonScript_ = script->ionScript(); + topIonScript_ = script->ionScript(); attachOnJitActivation(activations); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/mips/CodeGenerator-mips.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/mips/CodeGenerator-mips.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/mips/CodeGenerator-mips.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/mips/CodeGenerator-mips.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -168,7 +168,7 @@ // the same. masm.move32(Imm32(frameSize()), ra); - JitCode *handler = gen->jitRuntime()->getGenericBailoutHandler(gen->info().executionMode()); + JitCode *handler = gen->jitRuntime()->getGenericBailoutHandler(); masm.branch(handler); } @@ -2151,15 +2151,3 @@ masm.as_negs(output, input); } - -void -CodeGeneratorMIPS::visitForkJoinGetSlice(LForkJoinGetSlice *ins) -{ - MOZ_CRASH("NYI"); -} - -JitCode * -JitRuntime::generateForkJoinGetSliceStub(JSContext *cx) -{ - MOZ_CRASH("NYI"); -} diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/mips/CodeGenerator-mips.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/mips/CodeGenerator-mips.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/mips/CodeGenerator-mips.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/mips/CodeGenerator-mips.h 2015-01-09 12:36:47.000000000 +0000 @@ -264,8 +264,6 @@ void visitAsmJSPassStackArg(LAsmJSPassStackArg *ins); - void visitForkJoinGetSlice(LForkJoinGetSlice *ins); - void generateInvalidateEpilogue(); protected: diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/mips/Lowering-mips.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/mips/Lowering-mips.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/mips/Lowering-mips.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/mips/Lowering-mips.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -541,12 +541,6 @@ } void -LIRGeneratorMIPS::visitForkJoinGetSlice(MForkJoinGetSlice *ins) -{ - MOZ_CRASH("NYI"); -} - -void LIRGeneratorMIPS::visitSimdBinaryArith(MSimdBinaryArith *ins) { MOZ_CRASH("NYI"); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/mips/Lowering-mips.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/mips/Lowering-mips.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/mips/Lowering-mips.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/mips/Lowering-mips.h 2015-01-09 12:36:47.000000000 +0000 @@ -38,12 +38,6 @@ bool needTempForPostBarrier() { return false; } - // MIPS has a scratch register, so no need for another temp for dispatch - // ICs. - LDefinition tempForDispatchCache(MIRType outputType = MIRType_None) { - return LDefinition::BogusTemp(); - } - void lowerUntypedPhiInput(MPhi *phi, uint32_t inputPosition, LBlock *block, size_t lirIndex); void defineUntypedPhi(MPhi *phi, size_t lirIndex); void lowerForShift(LInstructionHelper<1, 2, 0> *ins, MDefinition *mir, MDefinition *lhs, @@ -106,7 +100,6 @@ void visitAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap *ins); void visitAsmJSLoadFuncPtr(MAsmJSLoadFuncPtr *ins); void visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic *ins); - void visitForkJoinGetSlice(MForkJoinGetSlice *ins); void visitSimdBinaryArith(MSimdBinaryArith *ins); void visitSimdSelect(MSimdSelect *ins); void visitSimdSplatX4(MSimdSplatX4 *ins); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/mips/Trampoline-mips.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/mips/Trampoline-mips.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/mips/Trampoline-mips.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/mips/Trampoline-mips.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -16,11 +16,8 @@ #ifdef JS_ION_PERF # include "jit/PerfSpewer.h" #endif -#include "jit/ParallelFunctions.h" #include "jit/VMFunctions.h" -#include "jit/ExecutionMode-inl.h" - using namespace js; using namespace js::jit; @@ -386,7 +383,7 @@ } JitCode * -JitRuntime::generateArgumentsRectifier(JSContext *cx, ExecutionMode mode, void **returnAddrOut) +JitRuntime::generateArgumentsRectifier(JSContext *cx, void **returnAddrOut) { MacroAssembler masm(cx); @@ -475,7 +472,7 @@ // Note that this code assumes the function is JITted. masm.andPtr(Imm32(CalleeTokenMask), calleeTokenReg); masm.loadPtr(Address(calleeTokenReg, JSFunction::offsetOfNativeOrScript()), t1); - masm.loadBaselineOrIonRaw(t1, t1, mode, nullptr); + masm.loadBaselineOrIonRaw(t1, t1, nullptr); masm.ma_callJitHalfPush(t1); uint32_t returnOffset = masm.currentOffset(); @@ -618,32 +615,6 @@ masm.branch(bailoutTail); } -static void -GenerateParallelBailoutThunk(MacroAssembler &masm, uint32_t frameClass) -{ - // As GenerateBailoutThunk, except we return an error immediately. We do - // the bailout dance so that we can walk the stack and have accurate - // reporting of frame information. - - PushBailoutFrame(masm, frameClass, a0); - - // Parallel bailout is like parallel failure in that we unwind all the way - // to the entry frame. Reserve space for the frame pointer of the entry frame. - const int sizeOfEntryFramePointer = sizeof(uint8_t *) * 2; - masm.reserveStack(sizeOfEntryFramePointer); - masm.movePtr(sp, a1); - - masm.setupAlignedABICall(2); - masm.passABIArg(a0); - masm.passABIArg(a1); - masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, BailoutPar)); - - // Get the frame pointer of the entry frame and return. - masm.moveValue(MagicValue(JS_ION_ERROR), JSReturnOperand); - masm.loadPtr(Address(sp, 0), sp); - masm.ret(); -} - JitCode * JitRuntime::generateBailoutTable(JSContext *cx, uint32_t frameClass) { @@ -674,20 +645,10 @@ } JitCode * -JitRuntime::generateBailoutHandler(JSContext *cx, ExecutionMode mode) +JitRuntime::generateBailoutHandler(JSContext *cx) { MacroAssembler masm(cx); - - switch (mode) { - case SequentialExecution: - GenerateBailoutThunk(cx, masm, NO_FRAME_SIZE_CLASS_ID); - break; - case ParallelExecution: - GenerateParallelBailoutThunk(masm, NO_FRAME_SIZE_CLASS_ID); - break; - default: - MOZ_CRASH("No such execution mode"); - } + GenerateBailoutThunk(cx, masm, NO_FRAME_SIZE_CLASS_ID); Linker linker(masm); AutoFlushICache afc("BailoutHandler"); @@ -721,7 +682,8 @@ regs.take(cxreg); // We're aligned to an exit frame, so link it up. - masm.enterExitFrameAndLoadContext(&f, cxreg, regs.getAny(), f.executionMode); + masm.enterExitFrame(&f); + masm.loadJSContext(cxreg); // Save the base of the argument set stored on the stack. Register argsBase = InvalidReg; @@ -832,11 +794,11 @@ // Test for failure. switch (f.failType()) { case Type_Object: - masm.branchTestPtr(Assembler::Zero, v0, v0, masm.failureLabel(f.executionMode)); + masm.branchTestPtr(Assembler::Zero, v0, v0, masm.failureLabel()); break; case Type_Bool: // Called functions return bools, which are 0/false and non-zero/true - masm.branchIfFalseBool(v0, masm.failureLabel(f.executionMode)); + masm.branchIfFalseBool(v0, masm.failureLabel()); break; default: MOZ_CRASH("unknown failure kind"); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/MIR.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/MIR.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/MIR.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/MIR.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -2271,17 +2271,6 @@ return; } - // In parallel execution, for now anyhow, we *only* support adding - // and manipulating numbers (not strings or objects). So no - // matter what we can specialize to double...if the result ought - // to have been something else, we'll fail in the various type - // guards that get inserted later. - if (block()->info().executionMode() == ParallelExecution) { - specialization_ = MIRType_Double; - setResultType(MIRType_Double); - return; - } - // If we can't specialize because we have no type information at all for // the lhs or rhs, mark the binary instruction as having no possible types // either to avoid degrading subsequent analysis. diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/MIRGraph.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/MIRGraph.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/MIRGraph.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/MIRGraph.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -202,37 +202,6 @@ i->unmark(); } -MDefinition * -MIRGraph::forkJoinContext() -{ - // Search the entry block to find a ForkJoinContext instruction. If we do - // not find one, add one after the Start instruction. - // - // Note: the original design used a field in MIRGraph to cache the - // forkJoinContext rather than searching for it again. However, this - // could become out of date due to DCE. Given that we do not generally - // have to search very far to find the ForkJoinContext instruction if it - // exists, and that we don't look for it that often, I opted to simply - // eliminate the cache and search anew each time, so that it is that much - // easier to keep the IR coherent. - nmatsakis - - MBasicBlock *entry = entryBlock(); - MOZ_ASSERT(entry->info().executionMode() == ParallelExecution); - - MInstruction *start = nullptr; - for (MInstructionIterator ins(entry->begin()); ins != entry->end(); ins++) { - if (ins->isForkJoinContext()) - return *ins; - else if (ins->isStart()) - start = *ins; - } - MOZ_ASSERT(start); - - MForkJoinContext *cx = MForkJoinContext::New(alloc()); - entry->insertAfter(start, cx); - return cx; -} - MBasicBlock * MBasicBlock::New(MIRGraph &graph, BytecodeAnalysis *analysis, CompileInfo &info, MBasicBlock *pred, const BytecodeSite *site, Kind kind) @@ -807,7 +776,6 @@ : begin(ins->toInstruction()); while (insertIter->isBeta() || insertIter->isInterruptCheck() || - insertIter->isInterruptCheckPar() || insertIter->isConstant() || (!(ignore & IgnoreRecover) && insertIter->isRecoveredOnBailout())) { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/MIRGraph.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/MIRGraph.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/MIRGraph.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/MIRGraph.h 2015-01-09 12:36:47.000000000 +0000 @@ -807,12 +807,6 @@ hasTryBlock_ = true; } - // The per-thread context. So as not to modify the calling convention for - // parallel code, we obtain the current ForkJoinContext from thread-local - // storage. This helper method will lazilly insert an MForkJoinContext - // instruction in the entry block and return the definition. - MDefinition *forkJoinContext(); - void dump(FILE *fp); void dump(); }; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/MIR.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/MIR.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/MIR.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/MIR.h 2015-01-09 12:36:47.000000000 +0000 @@ -2836,40 +2836,6 @@ } }; -// Could be allocating either a new array or a new object. -class MNewPar - : public MUnaryInstruction, - public NoTypePolicy::Data -{ - AlwaysTenuredNativeObject templateObject_; - - MNewPar(MDefinition *cx, NativeObject *templateObject) - : MUnaryInstruction(cx), - templateObject_(templateObject) - { - setResultType(MIRType_Object); - } - - public: - INSTRUCTION_HEADER(NewPar); - - static MNewPar *New(TempAllocator &alloc, MDefinition *cx, NativeObject *templateObject) { - return new(alloc) MNewPar(cx, templateObject); - } - - MDefinition *forkJoinContext() const { - return getOperand(0); - } - - NativeObject *templateObject() const { - return templateObject_; - } - - AliasSet getAliasSet() const { - return AliasSet::None(); - } -}; - class MNewTypedObject : public MNullaryInstruction { AlwaysTenured templateObject_; @@ -6075,46 +6041,6 @@ ALLOW_CLONE(MConcat) }; -class MConcatPar - : public MTernaryInstruction, - public NoTypePolicy::Data -{ - MConcatPar(MDefinition *cx, MDefinition *left, MDefinition *right) - : MTernaryInstruction(cx, left, right) - { - // Type analysis has already run, before replacing with the parallel - // variant. - MOZ_ASSERT(left->type() == MIRType_String && right->type() == MIRType_String); - - setMovable(); - setResultType(MIRType_String); - } - - public: - INSTRUCTION_HEADER(ConcatPar) - - static MConcatPar *New(TempAllocator &alloc, MDefinition *cx, MConcat *concat) { - return new(alloc) MConcatPar(cx, concat->lhs(), concat->rhs()); - } - - MDefinition *forkJoinContext() const { - return getOperand(0); - } - MDefinition *lhs() const { - return getOperand(1); - } - MDefinition *rhs() const { - return getOperand(2); - } - - bool congruentTo(const MDefinition *ins) const { - return congruentIfOperandsEqual(ins); - } - AliasSet getAliasSet() const { - return AliasSet::None(); - } -}; - class MCharCodeAt : public MBinaryInstruction, public MixPolicy, IntPolicy<1> >::Data @@ -6628,59 +6554,6 @@ } }; -// Check the current frame for over-recursion past the global stack limit. -// Uses the per-thread recursion limit. -class MCheckOverRecursedPar - : public MUnaryInstruction, - public NoTypePolicy::Data -{ - explicit MCheckOverRecursedPar(MDefinition *cx) - : MUnaryInstruction(cx) - { - setResultType(MIRType_None); - setGuard(); - setMovable(); - } - - public: - INSTRUCTION_HEADER(CheckOverRecursedPar); - - static MCheckOverRecursedPar *New(TempAllocator &alloc, MDefinition *cx) { - return new(alloc) MCheckOverRecursedPar(cx); - } - - MDefinition *forkJoinContext() const { - return getOperand(0); - } -}; - -// Check for an interrupt (or rendezvous) in parallel mode. -class MInterruptCheckPar - : public MUnaryInstruction, - public NoTypePolicy::Data -{ - explicit MInterruptCheckPar(MDefinition *cx) - : MUnaryInstruction(cx) - { - setResultType(MIRType_None); - setGuard(); - } - - public: - INSTRUCTION_HEADER(InterruptCheckPar); - - static MInterruptCheckPar *New(TempAllocator &alloc, MDefinition *cx) { - return new(alloc) MInterruptCheckPar(cx); - } - - MDefinition *forkJoinContext() const { - return getOperand(0); - } - AliasSet getAliasSet() const { - return AliasSet::None(); - } -}; - // Check whether we need to fire the interrupt handler. class MInterruptCheck : public MNullaryInstruction { @@ -7196,43 +7069,6 @@ } }; -class MLambdaPar - : public MBinaryInstruction, - public SingleObjectPolicy::Data -{ - LambdaFunctionInfo info_; - - MLambdaPar(MDefinition *cx, MDefinition *scopeChain, JSFunction *fun, - types::TemporaryTypeSet *resultTypes, const LambdaFunctionInfo &info) - : MBinaryInstruction(cx, scopeChain), info_(info) - { - MOZ_ASSERT(!info_.singletonType); - MOZ_ASSERT(!info_.useNewTypeForClone); - setResultType(MIRType_Object); - setResultTypeSet(resultTypes); - } - - public: - INSTRUCTION_HEADER(LambdaPar); - - static MLambdaPar *New(TempAllocator &alloc, MDefinition *cx, MLambda *lambda) { - return new(alloc) MLambdaPar(cx, lambda->scopeChain(), lambda->info().fun, - lambda->resultTypeSet(), lambda->info()); - } - - MDefinition *forkJoinContext() const { - return getOperand(0); - } - - MDefinition *scopeChain() const { - return getOperand(1); - } - - const LambdaFunctionInfo &info() const { - return info_; - } -}; - // Returns obj->slots. class MSlots : public MUnaryInstruction, @@ -10002,63 +9838,6 @@ } }; -// Loads the current js::ForkJoinContext*. -// Only applicable in ParallelExecution. -class MForkJoinContext - : public MNullaryInstruction -{ - MForkJoinContext() - : MNullaryInstruction() - { - setResultType(MIRType_ForkJoinContext); - } - - public: - INSTRUCTION_HEADER(ForkJoinContext); - - static MForkJoinContext *New(TempAllocator &alloc) { - return new(alloc) MForkJoinContext(); - } - - AliasSet getAliasSet() const { - // Indicate that this instruction reads nothing, stores nothing. - // (For all intents and purposes) - return AliasSet::None(); - } - - bool possiblyCalls() const { - return true; - } -}; - -// Calls the ForkJoinGetSlice stub, used for inlining the eponymous intrinsic. -// Only applicable in ParallelExecution. -class MForkJoinGetSlice - : public MUnaryInstruction, - public NoTypePolicy::Data -{ - explicit MForkJoinGetSlice(MDefinition *cx) - : MUnaryInstruction(cx) - { - setResultType(MIRType_Int32); - } - - public: - INSTRUCTION_HEADER(ForkJoinGetSlice); - - static MForkJoinGetSlice *New(TempAllocator &alloc, MDefinition *cx) { - return new(alloc) MForkJoinGetSlice(cx); - } - - MDefinition *forkJoinContext() { - return getOperand(0); - } - - bool possiblyCalls() const { - return true; - } -}; - // Store to vp[slot] (slots that are not inline in an object). class MStoreSlot : public MBinaryInstruction, @@ -11323,82 +11102,6 @@ } }; -class MRestPar - : public MBinaryInstruction, - public MRestCommon, - public IntPolicy<1>::Data -{ - MRestPar(MDefinition *cx, MDefinition *numActuals, unsigned numFormals, - ArrayObject *templateObject, types::TemporaryTypeSet *resultTypes) - : MBinaryInstruction(cx, numActuals), - MRestCommon(numFormals, templateObject) - { - setResultType(MIRType_Object); - setResultTypeSet(resultTypes); - } - - public: - INSTRUCTION_HEADER(RestPar); - - static MRestPar *New(TempAllocator &alloc, MDefinition *cx, MRest *rest) { - return new(alloc) MRestPar(cx, rest->numActuals(), rest->numFormals(), - rest->templateObject(), rest->resultTypeSet()); - } - - MDefinition *forkJoinContext() const { - return getOperand(0); - } - MDefinition *numActuals() const { - return getOperand(1); - } - - AliasSet getAliasSet() const { - return AliasSet::None(); - } - bool possiblyCalls() const { - return true; - } -}; - -// Guard on an object being safe for writes by current parallel cx. -// Must be either thread-local or else a handle into the destination array. -class MGuardThreadExclusive - : public MBinaryInstruction, - public ObjectPolicy<1>::Data -{ - MGuardThreadExclusive(MDefinition *cx, MDefinition *obj) - : MBinaryInstruction(cx, obj) - { - setResultType(MIRType_None); - setGuard(); - } - - public: - INSTRUCTION_HEADER(GuardThreadExclusive); - - static MGuardThreadExclusive *New(TempAllocator &alloc, MDefinition *cx, MDefinition *obj) { - return new(alloc) MGuardThreadExclusive(cx, obj); - } - MDefinition *forkJoinContext() const { - return getOperand(0); - } - MDefinition *object() const { - return getOperand(1); - } - BailoutKind bailoutKind() const { - return Bailout_GuardThreadExclusive; - } - bool congruentTo(const MDefinition *ins) const { - return congruentIfOperandsEqual(ins); - } - AliasSet getAliasSet() const { - return AliasSet::None(); - } - bool possiblyCalls() const { - return true; - } -}; - class MFilterTypeSet : public MUnaryInstruction, public FilterTypeSetPolicy::Data @@ -11646,39 +11349,6 @@ } }; -class MNewCallObjectPar - : public MUnaryInstruction, - public NoTypePolicy::Data -{ - AlwaysTenured templateObj_; - - MNewCallObjectPar(MDefinition *cx, CallObject *templateObj) - : MUnaryInstruction(cx), - templateObj_(templateObj) - { - setResultType(MIRType_Object); - } - - public: - INSTRUCTION_HEADER(NewCallObjectPar); - - static MNewCallObjectPar *New(TempAllocator &alloc, MDefinition *cx, MNewCallObjectBase *callObj) { - return new(alloc) MNewCallObjectPar(cx, callObj->templateObject()); - } - - MDefinition *forkJoinContext() const { - return getOperand(0); - } - - CallObject *templateObj() const { - return templateObj_; - } - - AliasSet getAliasSet() const { - return AliasSet::None(); - } -}; - class MNewStringObject : public MUnaryInstruction, public ConvertToStringPolicy<0>::Data @@ -11763,53 +11433,6 @@ return AliasSet::None(); } }; - -// Creates a dense array of the given length. -// -// Note: the template object should be an *empty* dense array! -class MNewDenseArrayPar - : public MBinaryInstruction, - public NoTypePolicy::Data -{ - AlwaysTenured templateObject_; - - MNewDenseArrayPar(MDefinition *cx, MDefinition *length, ArrayObject *templateObject) - : MBinaryInstruction(cx, length), - templateObject_(templateObject) - { - MOZ_ASSERT(length->type() == MIRType_Int32); - setResultType(MIRType_Object); - } - - public: - INSTRUCTION_HEADER(NewDenseArrayPar); - - static MNewDenseArrayPar *New(TempAllocator &alloc, MDefinition *cx, MDefinition *length, - ArrayObject *templateObject) - { - return new(alloc) MNewDenseArrayPar(cx, length, templateObject); - } - - MDefinition *forkJoinContext() const { - return getOperand(0); - } - - MDefinition *length() const { - return getOperand(1); - } - - ArrayObject *templateObject() const { - return templateObject_; - } - - bool possiblyCalls() const { - return true; - } - - AliasSet getAliasSet() const { - return AliasSet::None(); - } -}; // This is an element of a spaghetti stack which is used to represent the memory // context which has to be restored in case of a bailout. diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/MOpcodes.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/MOpcodes.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/MOpcodes.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/MOpcodes.h 2015-01-09 12:36:47.000000000 +0000 @@ -91,7 +91,6 @@ _(Div) \ _(Mod) \ _(Concat) \ - _(ConcatPar) \ _(CharCodeAt) \ _(FromCharCode) \ _(StringSplit) \ @@ -247,17 +246,7 @@ _(AsmJSVoidReturn) \ _(AsmJSPassStackArg) \ _(AsmJSCall) \ - _(CheckOverRecursedPar) \ - _(NewCallObjectPar) \ - _(NewPar) \ - _(NewDenseArrayPar) \ _(NewDerivedTypedObject) \ - _(LambdaPar) \ - _(RestPar) \ - _(ForkJoinContext) \ - _(ForkJoinGetSlice) \ - _(GuardThreadExclusive) \ - _(InterruptCheckPar) \ _(RecompileCheck) \ _(MemoryBarrier) \ _(AsmJSCompareExchangeHeap) \ diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/none/Lowering-none.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/none/Lowering-none.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/none/Lowering-none.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/none/Lowering-none.h 2015-01-09 12:36:47.000000000 +0000 @@ -32,7 +32,6 @@ LDefinition tempByteOpRegister() { MOZ_CRASH(); } LDefinition tempToUnbox() { MOZ_CRASH(); } bool needTempForPostBarrier() { MOZ_CRASH(); } - LDefinition tempForDispatchCache(MIRType v = MIRType_None) { MOZ_CRASH(); } void lowerUntypedPhiInput(MPhi *, uint32_t, LBlock *, size_t) { MOZ_CRASH(); } void defineUntypedPhi(MPhi *, size_t) { MOZ_CRASH(); } void lowerForShift(LInstructionHelper<1, 2, 0> *, MDefinition *, MDefinition *, MDefinition *) { @@ -78,7 +77,6 @@ void visitAsmJSStoreHeap(MAsmJSStoreHeap *ins) { MOZ_CRASH(); } void visitAsmJSLoadFuncPtr(MAsmJSLoadFuncPtr *ins) { MOZ_CRASH(); } void visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic *ins) { MOZ_CRASH(); } - void visitForkJoinGetSlice(MForkJoinGetSlice *ins) { MOZ_CRASH(); } void visitAtomicTypedArrayElementBinop(MAtomicTypedArrayElementBinop *ins) { MOZ_CRASH(); } void visitCompareExchangeTypedArrayElement(MCompareExchangeTypedArrayElement *ins) { MOZ_CRASH(); } void visitAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap *ins) { MOZ_CRASH(); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/none/Trampoline-none.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/none/Trampoline-none.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/none/Trampoline-none.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/none/Trampoline-none.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -19,15 +19,14 @@ JitCode *JitRuntime::generateEnterJIT(JSContext *, EnterJitType) { MOZ_CRASH(); } JitCode *JitRuntime::generateInvalidator(JSContext *) { MOZ_CRASH(); } -JitCode *JitRuntime::generateArgumentsRectifier(JSContext *, ExecutionMode, void **) { MOZ_CRASH(); } +JitCode *JitRuntime::generateArgumentsRectifier(JSContext *, void **) { MOZ_CRASH(); } JitCode *JitRuntime::generateBailoutTable(JSContext *, uint32_t) { MOZ_CRASH(); } -JitCode *JitRuntime::generateBailoutHandler(JSContext *, ExecutionMode) { MOZ_CRASH(); } +JitCode *JitRuntime::generateBailoutHandler(JSContext *) { MOZ_CRASH(); } JitCode *JitRuntime::generateVMWrapper(JSContext *, const VMFunction &) { MOZ_CRASH(); } JitCode *JitRuntime::generatePreBarrier(JSContext *, MIRType) { MOZ_CRASH(); } JitCode *JitRuntime::generateDebugTrapHandler(JSContext *) { MOZ_CRASH(); } JitCode *JitRuntime::generateExceptionTailStub(JSContext *, void *) { MOZ_CRASH(); } JitCode *JitRuntime::generateBailoutTailStub(JSContext *) { MOZ_CRASH(); } -JitCode *JitRuntime::generateForkJoinGetSliceStub(JSContext *) { MOZ_CRASH(); } FrameSizeClass FrameSizeClass::FromDepth(uint32_t) { MOZ_CRASH(); } FrameSizeClass FrameSizeClass::ClassLimit() { MOZ_CRASH(); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/ParallelFunctions.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/ParallelFunctions.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/ParallelFunctions.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/ParallelFunctions.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,620 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sts=4 et sw=4 tw=99: - * 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 "jit/ParallelFunctions.h" - -#include "builtin/TypedObject.h" -#include "jit/arm/Simulator-arm.h" -#include "jit/mips/Simulator-mips.h" -#include "jit/RematerializedFrame.h" -#include "vm/ArrayObject.h" - -#include "jsgcinlines.h" -#include "jsobjinlines.h" - -#include "vm/NativeObject-inl.h" - -using namespace js; -using namespace jit; - -using mozilla::IsInRange; - -using JS::AutoCheckCannotGC; - -using parallel::Spew; -using parallel::SpewOps; -using parallel::SpewBailouts; - -// Load the current thread context. -ForkJoinContext * -jit::ForkJoinContextPar() -{ - return ForkJoinContext::current(); -} - -// NewGCThingPar() is called in place of NewGCThing() when executing -// parallel code. It uses the ArenaLists for the current thread and -// allocates from there. -JSObject * -jit::NewGCThingPar(ForkJoinContext *cx, gc::AllocKind allocKind) -{ - MOZ_ASSERT(ForkJoinContext::current() == cx); - return js::NewGCObject(cx, allocKind, 0, gc::TenuredHeap); -} - -bool -jit::ParallelWriteGuard(ForkJoinContext *cx, JSObject *object) -{ - // Implements the most general form of the write guard, which is - // suitable for writes to any object O. There are two cases to - // consider and test for: - // - // 1. Writes to thread-local memory are safe. Thread-local memory - // is defined as memory allocated by the current thread. - // The definition of the PJS API guarantees that such memory - // cannot have escaped to other parallel threads. - // - // 2. Writes into the output buffer are safe. Some PJS operations - // supply an out pointer into the final target buffer. The design - // of the API ensures that this out pointer is always pointing - // at a fresh region of the buffer that is not accessible to - // other threads. Thus, even though this output buffer has not - // been created by the current thread, it is writable. - // - // There are some subtleties to consider: - // - // A. Typed objects and typed arrays are just views onto a base buffer. - // For the purposes of guarding parallel writes, it is not important - // whether the *view* is thread-local -- what matters is whether - // the *underlying buffer* is thread-local. - // - // B. With regard to the output buffer, we have to be careful - // because of the potential for sequential iterations to be - // intermingled with parallel ones. During a sequential - // iteration, the out pointer could escape into global - // variables and so forth, and thus be used during later - // parallel operations. However, those out pointers must be - // pointing to distinct regions of the final output buffer than - // the ones that are currently being written, so there is no - // harm done in letting them be read (but not written). - // - // In order to be able to distinguish escaped out pointers from - // prior iterations and the proper out pointers from the - // current iteration, we always track a *target memory region* - // (which is a span of bytes within the output buffer) and not - // just the output buffer itself. - - MOZ_ASSERT(ForkJoinContext::current() == cx); - - if (object->is()) { - TypedObject &typedObj = object->as(); - - // Note: check target region based on `typedObj`, not the owner. - // This is because `typedObj` may point to some subregion of the - // owner and we only care if that *subregion* is within the - // target region, not the entire owner. - if (IsInTargetRegion(cx, &typedObj)) - return true; - - // Check whether the object which owns the memory is thread-local. - if (typedObj.is()) - return cx->isThreadLocal(&typedObj.as().owner()); - return cx->isThreadLocal(&typedObj); - } - - // For other kinds of writable objects, must be thread-local. - return cx->isThreadLocal(object); -} - -// Check that |object| (which must be a typed typedObj) maps -// to memory in the target region. -// -// For efficiency, we assume that all handles which the user has -// access to are either entirely within the target region or entirely -// without, but not straddling the target region nor encompassing -// it. This invariant is maintained by the PJS APIs, where the target -// region and handles are always elements of the same output array. -bool -jit::IsInTargetRegion(ForkJoinContext *cx, TypedObject *typedObj) -{ - MOZ_ASSERT(typedObj->is()); // in case JIT supplies something bogus - uint8_t *typedMem = typedObj->typedMem(); - return typedMem >= cx->targetRegionStart && - typedMem < cx->targetRegionEnd; -} - -bool -jit::CheckOverRecursedPar(ForkJoinContext *cx) -{ - MOZ_ASSERT(ForkJoinContext::current() == cx); - int stackDummy_; - - // In PJS, unlike sequential execution, we don't overwrite the stack limit - // on interrupt, but we do still call into this routine if the interrupt - // flag is set, so we still need to double check. - -#if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR) - if (Simulator::Current()->overRecursed()) { - cx->bailoutRecord->joinCause(ParallelBailoutOverRecursed); - return false; - } -#endif - - if (!JS_CHECK_STACK_SIZE(cx->perThreadData->jitStackLimit(), &stackDummy_)) { - cx->bailoutRecord->joinCause(ParallelBailoutOverRecursed); - return false; - } - - return InterruptCheckPar(cx); -} - -bool -jit::InterruptCheckPar(ForkJoinContext *cx) -{ - MOZ_ASSERT(ForkJoinContext::current() == cx); - bool result = cx->check(); - if (!result) { - cx->bailoutRecord->joinCause(ParallelBailoutInterrupt); - return false; - } - return true; -} - -ArrayObject * -jit::ExtendArrayPar(ForkJoinContext *cx, ArrayObject *array, uint32_t length) -{ - NativeObject::EnsureDenseResult res = - array->ensureDenseElementsPreservePackedFlag(cx, 0, length); - if (res != NativeObject::ED_OK) - return nullptr; - return array; -} - -bool -jit::SetPropertyPar(ForkJoinContext *cx, HandleObject obj, HandlePropertyName name, - HandleValue value, bool strict, jsbytecode *pc) -{ - MOZ_ASSERT(cx->isThreadLocal(obj)); - - if (*pc == JSOP_SETALIASEDVAR) { - // See comment in jit::SetProperty. - Shape *shape = obj->as().lookupPure(name); - MOZ_ASSERT(shape && shape->hasSlot()); - return obj->as().setSlotIfHasType(shape, value); - } - - // Fail early on hooks. - if (obj->getOps()->setProperty) - return TP_RETRY_SEQUENTIALLY; - - RootedValue v(cx, value); - RootedId id(cx, NameToId(name)); - return baseops::SetPropertyHelper(cx, - obj.as(), - obj.as(), - id, baseops::Qualified, &v, - strict); -} - -bool -jit::SetElementPar(ForkJoinContext *cx, HandleObject obj, HandleValue index, HandleValue value, - bool strict) -{ - RootedId id(cx); - if (!ValueToIdPure(index, id.address())) - return false; - - if (!obj->isNative()) - return false; - - // SetObjectElementOperation, the sequential version, has several checks - // for certain deoptimizing behaviors, such as marking having written to - // holes and non-indexed element accesses. We don't do that here, as we - // can't modify any TI state anyways. If we need to add a new type, we - // would bail out. - RootedValue v(cx, value); - return baseops::SetPropertyHelper(cx, - obj.as(), - obj.as(), - id, baseops::Qualified, &v, - strict); -} - -bool -jit::SetDenseElementPar(ForkJoinContext *cx, HandleObject obj, int32_t index, HandleValue value, - bool strict) -{ - RootedValue indexVal(cx, Int32Value(index)); - return SetElementPar(cx, obj, indexVal, value, strict); -} - -JSString * -jit::ConcatStringsPar(ForkJoinContext *cx, HandleString left, HandleString right) -{ - return ConcatStrings(cx, left, right); -} - -JSFlatString * -jit::IntToStringPar(ForkJoinContext *cx, int i) -{ - return Int32ToString(cx, i); -} - -JSString * -jit::DoubleToStringPar(ForkJoinContext *cx, double d) -{ - return NumberToString(cx, d); -} - -JSString * -jit::PrimitiveToStringPar(ForkJoinContext *cx, HandleValue input) -{ - // All other cases are handled in assembly. - MOZ_ASSERT(input.isDouble() || input.isInt32()); - - if (input.isInt32()) - return Int32ToString(cx, input.toInt32()); - - return NumberToString(cx, input.toDouble()); -} - -bool -jit::StringToNumberPar(ForkJoinContext *cx, JSString *str, double *out) -{ - return StringToNumber(cx, str, out); -} - -#define PAR_RELATIONAL_OP(OP, EXPECTED) \ -do { \ - /* Optimize for two int-tagged operands (typical loop control). */ \ - if (lhs.isInt32() && rhs.isInt32()) { \ - *res = (lhs.toInt32() OP rhs.toInt32()) == EXPECTED; \ - } else if (lhs.isNumber() && rhs.isNumber()) { \ - double l = lhs.toNumber(), r = rhs.toNumber(); \ - *res = (l OP r) == EXPECTED; \ - } else if (lhs.isBoolean() && rhs.isBoolean()) { \ - int l = lhs.toBoolean() ? 1 : 0; \ - int r = rhs.toBoolean() ? 1 : 0; \ - *res = (l OP r) == EXPECTED; \ - } else if (lhs.isBoolean() && rhs.isNumber()) { \ - double l = lhs.toBoolean() ? 1.0 : 0.0; \ - double r = rhs.toNumber(); \ - *res = (l OP r) == EXPECTED; \ - } else if (lhs.isNumber() && rhs.isBoolean()) { \ - double l = lhs.toNumber(); \ - double r = rhs.toBoolean() ? 1.0 : 0.0; \ - *res = (l OP r) == EXPECTED; \ - } else { \ - int32_t vsZero; \ - if (!CompareMaybeStringsPar(cx, lhs, rhs, &vsZero)) \ - return false; \ - *res = (vsZero OP 0) == EXPECTED; \ - } \ - return true; \ -} while(0) - -static bool -CompareStringsPar(ForkJoinContext *cx, JSString *left, JSString *right, int32_t *res) -{ - ScopedThreadSafeStringInspector leftInspector(left); - ScopedThreadSafeStringInspector rightInspector(right); - AutoCheckCannotGC nogc; - if (!leftInspector.ensureChars(cx, nogc) || !rightInspector.ensureChars(cx, nogc)) - return false; - - if (leftInspector.hasLatin1Chars()) { - if (rightInspector.hasLatin1Chars()) { - *res = CompareChars(leftInspector.latin1Chars(), left->length(), - rightInspector.latin1Chars(), right->length()); - } else { - *res = CompareChars(leftInspector.latin1Chars(), left->length(), - rightInspector.twoByteChars(), right->length()); - } - } else { - if (rightInspector.hasLatin1Chars()) { - *res = CompareChars(leftInspector.twoByteChars(), left->length(), - rightInspector.latin1Chars(), right->length()); - } else { - *res = CompareChars(leftInspector.twoByteChars(), left->length(), - rightInspector.twoByteChars(), right->length()); - } - } - - return true; -} - -static bool -CompareMaybeStringsPar(ForkJoinContext *cx, HandleValue v1, HandleValue v2, int32_t *res) -{ - if (!v1.isString()) - return false; - if (!v2.isString()) - return false; - return CompareStringsPar(cx, v1.toString(), v2.toString(), res); -} - -template -bool -LooselyEqualImplPar(ForkJoinContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res) -{ - PAR_RELATIONAL_OP(==, Equal); -} - -bool -js::jit::LooselyEqualPar(ForkJoinContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res) -{ - return LooselyEqualImplPar(cx, lhs, rhs, res); -} - -bool -js::jit::LooselyUnequalPar(ForkJoinContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res) -{ - return LooselyEqualImplPar(cx, lhs, rhs, res); -} - -template -bool -StrictlyEqualImplPar(ForkJoinContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res) -{ - if (lhs.isNumber()) { - if (rhs.isNumber()) { - *res = (lhs.toNumber() == rhs.toNumber()) == Equal; - return true; - } - } else if (lhs.isBoolean()) { - if (rhs.isBoolean()) { - *res = (lhs.toBoolean() == rhs.toBoolean()) == Equal; - return true; - } - } else if (lhs.isNull()) { - if (rhs.isNull()) { - *res = Equal; - return true; - } - } else if (lhs.isUndefined()) { - if (rhs.isUndefined()) { - *res = Equal; - return true; - } - } else if (lhs.isObject()) { - if (rhs.isObject()) { - *res = (lhs.toObjectOrNull() == rhs.toObjectOrNull()) == Equal; - return true; - } - } else if (lhs.isString()) { - if (rhs.isString()) - return LooselyEqualImplPar(cx, lhs, rhs, res); - } - - *res = !Equal; - return true; -} - -bool -js::jit::StrictlyEqualPar(ForkJoinContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res) -{ - return StrictlyEqualImplPar(cx, lhs, rhs, res); -} - -bool -js::jit::StrictlyUnequalPar(ForkJoinContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res) -{ - return StrictlyEqualImplPar(cx, lhs, rhs, res); -} - -bool -js::jit::LessThanPar(ForkJoinContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res) -{ - PAR_RELATIONAL_OP(<, true); -} - -bool -js::jit::LessThanOrEqualPar(ForkJoinContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res) -{ - PAR_RELATIONAL_OP(<=, true); -} - -bool -js::jit::GreaterThanPar(ForkJoinContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res) -{ - PAR_RELATIONAL_OP(>, true); -} - -bool -js::jit::GreaterThanOrEqualPar(ForkJoinContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, bool *res) -{ - PAR_RELATIONAL_OP(>=, true); -} - -template -bool -StringsEqualImplPar(ForkJoinContext *cx, HandleString lhs, HandleString rhs, bool *res) -{ - int32_t vsZero; - bool ret = CompareStringsPar(cx, lhs, rhs, &vsZero); - if (ret != true) - return ret; - *res = (vsZero == 0) == Equal; - return true; -} - -bool -js::jit::StringsEqualPar(ForkJoinContext *cx, HandleString v1, HandleString v2, bool *res) -{ - return StringsEqualImplPar(cx, v1, v2, res); -} - -bool -js::jit::StringsUnequalPar(ForkJoinContext *cx, HandleString v1, HandleString v2, bool *res) -{ - return StringsEqualImplPar(cx, v1, v2, res); -} - -bool -jit::BitNotPar(ForkJoinContext *cx, HandleValue in, int32_t *out) -{ - if (in.isObject()) - return false; - int i; - if (!NonObjectToInt32(cx, in, &i)) - return false; - *out = ~i; - return true; -} - -#define BIT_OP(OP) \ - JS_BEGIN_MACRO \ - int32_t left, right; \ - if (lhs.isObject() || rhs.isObject()) \ - return false; \ - if (!NonObjectToInt32(cx, lhs, &left) || \ - !NonObjectToInt32(cx, rhs, &right)) \ - { \ - return false; \ - } \ - *out = (OP); \ - return true; \ - JS_END_MACRO - -bool -jit::BitXorPar(ForkJoinContext *cx, HandleValue lhs, HandleValue rhs, int32_t *out) -{ - BIT_OP(left ^ right); -} - -bool -jit::BitOrPar(ForkJoinContext *cx, HandleValue lhs, HandleValue rhs, int32_t *out) -{ - BIT_OP(left | right); -} - -bool -jit::BitAndPar(ForkJoinContext *cx, HandleValue lhs, HandleValue rhs, int32_t *out) -{ - BIT_OP(left & right); -} - -bool -jit::BitLshPar(ForkJoinContext *cx, HandleValue lhs, HandleValue rhs, int32_t *out) -{ - BIT_OP(uint32_t(left) << (right & 31)); -} - -bool -jit::BitRshPar(ForkJoinContext *cx, HandleValue lhs, HandleValue rhs, int32_t *out) -{ - BIT_OP(left >> (right & 31)); -} - -#undef BIT_OP - -bool -jit::UrshValuesPar(ForkJoinContext *cx, HandleValue lhs, HandleValue rhs, - MutableHandleValue out) -{ - uint32_t left; - int32_t right; - if (lhs.isObject() || rhs.isObject()) - return false; - if (!NonObjectToUint32(cx, lhs, &left) || !NonObjectToInt32(cx, rhs, &right)) - return false; - left >>= right & 31; - out.setNumber(uint32_t(left)); - return true; -} - -void -jit::BailoutPar(BailoutStack *sp, uint8_t **entryFramePointer) -{ - parallel::Spew(parallel::SpewBailouts, "Bailing"); - - ForkJoinContext *cx = ForkJoinContext::current(); - - // We don't have an exit frame. - MOZ_ASSERT(IsInRange(FAKE_JIT_TOP_FOR_BAILOUT, 0, 0x1000) && - IsInRange(FAKE_JIT_TOP_FOR_BAILOUT + sizeof(CommonFrameLayout), 0, 0x1000), - "Fake jitTop pointer should be within the first page."); - cx->perThreadData->jitTop = FAKE_JIT_TOP_FOR_BAILOUT; - - JitActivationIterator jitActivations(cx->perThreadData); - BailoutFrameInfo bailoutData(jitActivations, sp); - JitFrameIterator frameIter(jitActivations); - SnapshotIterator snapIter(frameIter); - - cx->bailoutRecord->setIonBailoutKind(snapIter.bailoutKind()); - while (!frameIter.done()) - ++frameIter; - - MOZ_ASSERT(frameIter.done()); - *entryFramePointer = frameIter.fp(); -} - -bool -jit::CallToUncompiledScriptPar(ForkJoinContext *cx, JSObject *obj) -{ -#ifdef DEBUG - static const int max_bound_function_unrolling = 5; - - if (!obj->is()) { - Spew(SpewBailouts, "Call to non-function"); - return false; - } - - JSFunction *func = &obj->as(); - if (func->hasScript()) { - JSScript *script = func->nonLazyScript(); - Spew(SpewBailouts, "Call to uncompiled script: %p:%s:%d", - script, script->filename(), script->lineno()); - } else if (func->isInterpretedLazy()) { - Spew(SpewBailouts, "Call to uncompiled lazy script"); - } else if (func->isBoundFunction()) { - int depth = 0; - JSFunction *target = &func->getBoundFunctionTarget()->as(); - while (depth < max_bound_function_unrolling) { - if (target->hasScript()) - break; - if (target->isBoundFunction()) - target = &target->getBoundFunctionTarget()->as(); - depth--; - } - if (target->hasScript()) { - JSScript *script = target->nonLazyScript(); - Spew(SpewBailouts, "Call to bound function leading (depth: %d) to script: %p:%s:%d", - depth, script, script->filename(), script->lineno()); - } else { - Spew(SpewBailouts, "Call to bound function (excessive depth: %d)", depth); - } - } else { - MOZ_ASSERT(func->isNative()); - Spew(SpewBailouts, "Call to native function"); - } -#endif - - return false; -} - -JSObject * -jit::InitRestParameterPar(ForkJoinContext *cx, uint32_t length, Value *rest, - HandleObject templateObj, HandleArrayObject res) -{ - // In parallel execution, we should always have succeeded in allocation - // before this point. We can do the allocation here like in the sequential - // path, but duplicating the initGCThing logic is too tedious. - MOZ_ASSERT(res); - MOZ_ASSERT(!res->getDenseInitializedLength()); - MOZ_ASSERT(res->type() == templateObj->type()); - - if (length > 0) { - NativeObject::EnsureDenseResult edr = - res->ensureDenseElementsPreservePackedFlag(cx, 0, length); - if (edr != NativeObject::ED_OK) - return nullptr; - res->initDenseElementsUnbarriered(0, rest, length); - res->setLengthInt32(length); - } - - return res; -} diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/ParallelFunctions.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/ParallelFunctions.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/ParallelFunctions.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/ParallelFunctions.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,81 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sts=4 et sw=4 tw=99: - * 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 jit_ParallelFunctions_h -#define jit_ParallelFunctions_h - -#include "gc/Heap.h" -#include "vm/ForkJoin.h" - -namespace js { - -class TypedObject; // subclass of JSObject* defined in builtin/TypedObject.h - -namespace jit { - -ForkJoinContext *ForkJoinContextPar(); -JSObject *NewGCThingPar(ForkJoinContext *cx, gc::AllocKind allocKind); -bool ParallelWriteGuard(ForkJoinContext *cx, JSObject *object); -bool IsInTargetRegion(ForkJoinContext *cx, TypedObject *object); -bool CheckOverRecursedPar(ForkJoinContext *cx); -bool InterruptCheckPar(ForkJoinContext *cx); - -// Extends the given array with `length` new holes. Returns nullptr on -// failure or else `array`, which is convenient during code -// generation. -ArrayObject *ExtendArrayPar(ForkJoinContext *cx, ArrayObject *array, uint32_t length); - -// Set properties and elements on thread local objects. -bool SetPropertyPar(ForkJoinContext *cx, HandleObject obj, HandlePropertyName name, - HandleValue value, bool strict, jsbytecode *pc); -bool SetElementPar(ForkJoinContext *cx, HandleObject obj, HandleValue index, - HandleValue value, bool strict); -bool SetDenseElementPar(ForkJoinContext *cx, HandleObject obj, int32_t index, - HandleValue value, bool strict); - -// String related parallel functions. These tend to call existing VM functions -// that take a ThreadSafeContext. -JSString *ConcatStringsPar(ForkJoinContext *cx, HandleString left, HandleString right); -JSFlatString *IntToStringPar(ForkJoinContext *cx, int i); -JSString *DoubleToStringPar(ForkJoinContext *cx, double d); -JSString *PrimitiveToStringPar(ForkJoinContext *cx, HandleValue input); -bool StringToNumberPar(ForkJoinContext *cx, JSString *str, double *out); - -// Binary and unary operator functions on values. These tend to return -// RETRY_SEQUENTIALLY if the values are objects. -bool StrictlyEqualPar(ForkJoinContext *cx, MutableHandleValue v1, MutableHandleValue v2, bool *); -bool StrictlyUnequalPar(ForkJoinContext *cx, MutableHandleValue v1, MutableHandleValue v2, bool *); -bool LooselyEqualPar(ForkJoinContext *cx, MutableHandleValue v1, MutableHandleValue v2, bool *); -bool LooselyUnequalPar(ForkJoinContext *cx, MutableHandleValue v1, MutableHandleValue v2, bool *); -bool LessThanPar(ForkJoinContext *cx, MutableHandleValue v1, MutableHandleValue v2, bool *); -bool LessThanOrEqualPar(ForkJoinContext *cx, MutableHandleValue v1, MutableHandleValue v2, bool *); -bool GreaterThanPar(ForkJoinContext *cx, MutableHandleValue v1, MutableHandleValue v2, bool *); -bool GreaterThanOrEqualPar(ForkJoinContext *cx, MutableHandleValue v1, MutableHandleValue v2, bool *); - -bool StringsEqualPar(ForkJoinContext *cx, HandleString v1, HandleString v2, bool *); -bool StringsUnequalPar(ForkJoinContext *cx, HandleString v1, HandleString v2, bool *); - -bool BitNotPar(ForkJoinContext *cx, HandleValue in, int32_t *out); -bool BitXorPar(ForkJoinContext *cx, HandleValue lhs, HandleValue rhs, int32_t *out); -bool BitOrPar(ForkJoinContext *cx, HandleValue lhs, HandleValue rhs, int32_t *out); -bool BitAndPar(ForkJoinContext *cx, HandleValue lhs, HandleValue rhs, int32_t *out); -bool BitLshPar(ForkJoinContext *cx, HandleValue lhs, HandleValue rhs, int32_t *out); -bool BitRshPar(ForkJoinContext *cx, HandleValue lhs, HandleValue rhs, int32_t *out); - -bool UrshValuesPar(ForkJoinContext *cx, HandleValue lhs, HandleValue rhs, MutableHandleValue out); - -// Make a new rest parameter in parallel. -JSObject *InitRestParameterPar(ForkJoinContext *cx, uint32_t length, Value *rest, - HandleObject templateObj, HandleArrayObject res); - -// Abort and debug tracing functions. -void BailoutPar(BailoutStack *sp, uint8_t **entryFramePointer); -bool CallToUncompiledScriptPar(ForkJoinContext *cx, JSObject *obj); - -} // namespace jit -} // namespace js - -#endif /* jit_ParallelFunctions_h */ diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/ParallelSafetyAnalysis.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/ParallelSafetyAnalysis.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/ParallelSafetyAnalysis.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/ParallelSafetyAnalysis.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,913 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sts=4 et sw=4 tw=99: - * 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 "jit/ParallelSafetyAnalysis.h" - -#include "jit/Ion.h" -#include "jit/IonAnalysis.h" -#include "jit/JitSpewer.h" -#include "jit/MIR.h" -#include "jit/MIRGenerator.h" -#include "jit/MIRGraph.h" - -#include "jsinferinlines.h" -#include "jsobjinlines.h" - -using namespace js; -using namespace jit; - -using parallel::Spew; -using parallel::SpewMIR; -using parallel::SpewCompile; - -#define SAFE_OP(op) \ - virtual void visit##op(M##op *prop) { } - -#define CUSTOM_OP(op) \ - virtual void visit##op(M##op *prop); - -#define DROP_OP(op) \ - virtual void visit##op(M##op *ins) { \ - MBasicBlock *block = ins->block(); \ - block->discard(ins); \ - } - -#define PERMIT(T) (1 << T) - -#define PERMIT_INT32 (PERMIT(MIRType_Int32)) -#define PERMIT_NUMERIC (PERMIT(MIRType_Int32) | PERMIT(MIRType_Double)) - -#define SPECIALIZED_OP(op, flags) \ - virtual void visit##op(M##op *ins) { \ - visitSpecializedInstruction(ins, ins->specialization(), flags); \ - } - -#define UNSAFE_OP(op) \ - virtual void visit##op(M##op *ins) { \ - SpewMIR(ins, "Unsafe"); \ - markUnsafe(); \ - } - -#define WRITE_GUARDED_OP(op, obj) \ - virtual void visit##op(M##op *prop) { \ - insertWriteGuard(prop, prop->obj()); \ - } - -#define MAYBE_WRITE_GUARDED_OP(op, obj) \ - virtual void visit##op(M##op *prop) { \ - if (!prop->racy()) \ - insertWriteGuard(prop, prop->obj()); \ - } - -class ParallelSafetyVisitor : public MDefinitionVisitor -{ - MIRGraph &graph_; - bool unsafe_; - MDefinition *cx_; - - void insertWriteGuard(MInstruction *writeInstruction, MDefinition *valueBeingWritten); - - void replaceWithNewPar(MInstruction *newInstruction, NativeObject *templateObject); - void replace(MInstruction *oldInstruction, MInstruction *replacementInstruction); - - void visitSpecializedInstruction(MInstruction *ins, MIRType spec, uint32_t flags); - - // Intended for use in a visitXyz() instruction. - void markUnsafe() { - MOZ_ASSERT(!unsafe_); - unsafe_ = true; - } - - TempAllocator &alloc() const { - return graph_.alloc(); - } - - public: - explicit ParallelSafetyVisitor(MIRGraph &graph) - : graph_(graph), - unsafe_(false), - cx_(nullptr) - { } - - void clearUnsafe() { unsafe_ = false; } - bool unsafe() { return unsafe_; } - MDefinition *ForkJoinContext() { - if (!cx_) - cx_ = graph_.forkJoinContext(); - return cx_; - } - - bool convertToBailout(MInstructionIterator &iter); - - // I am taking the policy of blacklisting everything that's not - // obviously safe for now. We can loosen as we need. - - SAFE_OP(Constant) - SAFE_OP(SimdValueX4) - SAFE_OP(SimdSplatX4) - SAFE_OP(SimdConstant) - SAFE_OP(SimdConvert) - SAFE_OP(SimdReinterpretCast) - SAFE_OP(SimdExtractElement) - SAFE_OP(SimdInsertElement) - SAFE_OP(SimdSignMask) - SAFE_OP(SimdSwizzle) - SAFE_OP(SimdShuffle) - SAFE_OP(SimdUnaryArith) - SAFE_OP(SimdBinaryComp) - SAFE_OP(SimdBinaryArith) - SAFE_OP(SimdBinaryBitwise) - SAFE_OP(SimdShift) - SAFE_OP(SimdSelect) - UNSAFE_OP(CloneLiteral) - SAFE_OP(Parameter) - SAFE_OP(Callee) - SAFE_OP(IsConstructing) - SAFE_OP(TableSwitch) - SAFE_OP(Goto) - SAFE_OP(Test) - SAFE_OP(GotoWithFake) - SAFE_OP(Compare) - SAFE_OP(Phi) - SAFE_OP(Beta) - UNSAFE_OP(OsrValue) - UNSAFE_OP(OsrScopeChain) - UNSAFE_OP(OsrReturnValue) - UNSAFE_OP(OsrArgumentsObject) - UNSAFE_OP(ReturnFromCtor) - CUSTOM_OP(CheckOverRecursed) - UNSAFE_OP(DefVar) - UNSAFE_OP(DefFun) - UNSAFE_OP(CreateThis) - CUSTOM_OP(CreateThisWithTemplate) - UNSAFE_OP(CreateThisWithProto) - UNSAFE_OP(CreateArgumentsObject) - UNSAFE_OP(GetArgumentsObjectArg) - UNSAFE_OP(SetArgumentsObjectArg) - UNSAFE_OP(ComputeThis) - UNSAFE_OP(LoadArrowThis) - CUSTOM_OP(Call) - UNSAFE_OP(ApplyArgs) - UNSAFE_OP(ArraySplice) - SAFE_OP(Bail) - SAFE_OP(Unreachable) - UNSAFE_OP(AssertFloat32) - UNSAFE_OP(GetDynamicName) - UNSAFE_OP(FilterArgumentsOrEval) - UNSAFE_OP(CallDirectEval) - SAFE_OP(BitNot) - SAFE_OP(TypeOf) - UNSAFE_OP(ToId) - SAFE_OP(BitAnd) - SAFE_OP(BitOr) - SAFE_OP(BitXor) - SAFE_OP(Lsh) - SAFE_OP(Rsh) - SAFE_OP(Ursh) - SPECIALIZED_OP(MinMax, PERMIT_NUMERIC) - SAFE_OP(Abs) - SAFE_OP(Clz) - SAFE_OP(Sqrt) - UNSAFE_OP(Atan2) - UNSAFE_OP(Hypot) - CUSTOM_OP(MathFunction) - SPECIALIZED_OP(Add, PERMIT_NUMERIC) - SPECIALIZED_OP(Sub, PERMIT_NUMERIC) - SPECIALIZED_OP(Mul, PERMIT_NUMERIC) - SPECIALIZED_OP(Div, PERMIT_NUMERIC) - SPECIALIZED_OP(Mod, PERMIT_NUMERIC) - CUSTOM_OP(Concat) - SAFE_OP(ConcatPar) - UNSAFE_OP(CharCodeAt) - UNSAFE_OP(FromCharCode) - UNSAFE_OP(StringSplit) - SAFE_OP(Return) - CUSTOM_OP(Throw) - SAFE_OP(Box) // Boxing just creates a JSVal, doesn't alloc. - SAFE_OP(Unbox) - SAFE_OP(GuardObject) - SAFE_OP(ToDouble) - SAFE_OP(ToFloat32) - SAFE_OP(ToInt32) - SAFE_OP(TruncateToInt32) - SAFE_OP(MaybeToDoubleElement) - CUSTOM_OP(ToString) - UNSAFE_OP(ToObjectOrNull) - CUSTOM_OP(NewArray) - UNSAFE_OP(NewArrayCopyOnWrite) - UNSAFE_OP(NewArrayDynamicLength) - UNSAFE_OP(NewTypedObject) - CUSTOM_OP(NewObject) - CUSTOM_OP(NewCallObject) - CUSTOM_OP(NewRunOnceCallObject) - CUSTOM_OP(NewDerivedTypedObject) - SAFE_OP(ObjectState) - SAFE_OP(ArrayState) - UNSAFE_OP(InitElem) - UNSAFE_OP(InitElemGetterSetter) - UNSAFE_OP(MutateProto) - UNSAFE_OP(InitProp) - UNSAFE_OP(InitPropGetterSetter) - SAFE_OP(Start) - UNSAFE_OP(OsrEntry) - SAFE_OP(Nop) - SAFE_OP(LimitedTruncate) - UNSAFE_OP(RegExp) - CUSTOM_OP(Lambda) - UNSAFE_OP(LambdaArrow) - SAFE_OP(Slots) - SAFE_OP(Elements) - SAFE_OP(ConstantElements) - SAFE_OP(LoadSlot) - WRITE_GUARDED_OP(StoreSlot, slots) - SAFE_OP(FunctionEnvironment) // just a load of func env ptr - SAFE_OP(FilterTypeSet) - SAFE_OP(TypeBarrier) // causes a bailout if the type is not found: a-ok with us - SAFE_OP(MonitorTypes) // causes a bailout if the type is not found: a-ok with us - UNSAFE_OP(PostWriteBarrier) - SAFE_OP(GetPropertyCache) - SAFE_OP(GetPropertyPolymorphic) - UNSAFE_OP(SetPropertyPolymorphic) - SAFE_OP(GetElementCache) - WRITE_GUARDED_OP(SetElementCache, object) - UNSAFE_OP(BindNameCache) - SAFE_OP(GuardShape) - SAFE_OP(GuardShapePolymorphic) - SAFE_OP(GuardObjectType) - SAFE_OP(GuardObjectIdentity) - SAFE_OP(GuardClass) - SAFE_OP(AssertRange) - SAFE_OP(ArrayLength) - WRITE_GUARDED_OP(SetArrayLength, elements) - SAFE_OP(TypedArrayLength) - SAFE_OP(TypedArrayElements) - SAFE_OP(TypedObjectDescr) - SAFE_OP(TypedObjectElements) - SAFE_OP(SetTypedObjectOffset) - SAFE_OP(InitializedLength) - WRITE_GUARDED_OP(SetInitializedLength, elements) - SAFE_OP(Not) - SAFE_OP(BoundsCheck) - SAFE_OP(BoundsCheckLower) - SAFE_OP(LoadElement) - SAFE_OP(LoadElementHole) - SAFE_OP(LoadUnboxedObjectOrNull) - SAFE_OP(LoadUnboxedString) - MAYBE_WRITE_GUARDED_OP(StoreElement, elements) - WRITE_GUARDED_OP(StoreElementHole, elements) - UNSAFE_OP(StoreUnboxedObjectOrNull) - UNSAFE_OP(StoreUnboxedString) - UNSAFE_OP(ArrayPopShift) - UNSAFE_OP(ArrayPush) - SAFE_OP(LoadTypedArrayElement) - SAFE_OP(LoadTypedArrayElementHole) - SAFE_OP(LoadTypedArrayElementStatic) - MAYBE_WRITE_GUARDED_OP(StoreTypedArrayElement, elements) - WRITE_GUARDED_OP(StoreTypedArrayElementHole, elements) - UNSAFE_OP(StoreTypedArrayElementStatic) - UNSAFE_OP(ClampToUint8) - SAFE_OP(LoadFixedSlot) - WRITE_GUARDED_OP(StoreFixedSlot, object) - UNSAFE_OP(CallGetProperty) - UNSAFE_OP(GetNameCache) - UNSAFE_OP(CallGetIntrinsicValue) - UNSAFE_OP(CallsiteCloneCache) - UNSAFE_OP(CallGetElement) - WRITE_GUARDED_OP(CallSetElement, object) - UNSAFE_OP(CallInitElementArray) - WRITE_GUARDED_OP(CallSetProperty, object) - UNSAFE_OP(DeleteProperty) - UNSAFE_OP(DeleteElement) - WRITE_GUARDED_OP(SetPropertyCache, object) - UNSAFE_OP(IteratorStart) - UNSAFE_OP(IteratorMore) - UNSAFE_OP(IsNoIter) - UNSAFE_OP(IteratorEnd) - SAFE_OP(StringLength) - SAFE_OP(ArgumentsLength) - SAFE_OP(GetFrameArgument) - UNSAFE_OP(SetFrameArgument) - UNSAFE_OP(RunOncePrologue) - CUSTOM_OP(Rest) - SAFE_OP(RestPar) - SAFE_OP(Floor) - SAFE_OP(Ceil) - SAFE_OP(Round) - UNSAFE_OP(InstanceOf) - CUSTOM_OP(InterruptCheck) - UNSAFE_OP(AsmJSInterruptCheck) - SAFE_OP(ForkJoinContext) - SAFE_OP(ForkJoinGetSlice) - SAFE_OP(NewPar) - SAFE_OP(NewDenseArrayPar) - SAFE_OP(NewCallObjectPar) - SAFE_OP(LambdaPar) - UNSAFE_OP(ArrayConcat) - UNSAFE_OP(ArrayJoin) - UNSAFE_OP(GetDOMProperty) - UNSAFE_OP(GetDOMMember) - UNSAFE_OP(SetDOMProperty) - UNSAFE_OP(NewStringObject) - UNSAFE_OP(Random) - SAFE_OP(Pow) - SAFE_OP(PowHalf) - UNSAFE_OP(RegExpTest) - UNSAFE_OP(RegExpExec) - UNSAFE_OP(RegExpReplace) - UNSAFE_OP(StringReplace) - UNSAFE_OP(CallInstanceOf) - UNSAFE_OP(ProfilerStackOp) - UNSAFE_OP(GuardString) - UNSAFE_OP(Substr) - UNSAFE_OP(NewDeclEnvObject) - UNSAFE_OP(In) - UNSAFE_OP(InArray) - SAFE_OP(GuardThreadExclusive) - SAFE_OP(InterruptCheckPar) - SAFE_OP(CheckOverRecursedPar) - SAFE_OP(FunctionDispatch) - SAFE_OP(TypeObjectDispatch) - SAFE_OP(IsCallable) - SAFE_OP(IsObject) - SAFE_OP(HasClass) - UNSAFE_OP(EffectiveAddress) - UNSAFE_OP(AsmJSUnsignedToDouble) - UNSAFE_OP(AsmJSUnsignedToFloat32) - UNSAFE_OP(AsmJSNeg) - UNSAFE_OP(AsmJSLoadHeap) - UNSAFE_OP(AsmJSStoreHeap) - UNSAFE_OP(AsmJSLoadGlobalVar) - UNSAFE_OP(AsmJSStoreGlobalVar) - UNSAFE_OP(AsmJSLoadFuncPtr) - UNSAFE_OP(AsmJSLoadFFIFunc) - UNSAFE_OP(AsmJSReturn) - UNSAFE_OP(AsmJSVoidReturn) - UNSAFE_OP(AsmJSPassStackArg) - UNSAFE_OP(AsmJSParameter) - UNSAFE_OP(AsmJSCall) - DROP_OP(RecompileCheck) - UNSAFE_OP(CompareExchangeTypedArrayElement) - UNSAFE_OP(AtomicTypedArrayElementBinop) - UNSAFE_OP(MemoryBarrier) - UNSAFE_OP(AsmJSCompareExchangeHeap) - UNSAFE_OP(AsmJSAtomicBinopHeap) - UNSAFE_OP(UnknownValue) - UNSAFE_OP(LexicalCheck) - UNSAFE_OP(ThrowUninitializedLexical) - UNSAFE_OP(Debugger) - - // It looks like these could easily be made safe: - UNSAFE_OP(ConvertElementsToDoubles) - UNSAFE_OP(MaybeCopyElementsForWrite) -}; - -static void -TransplantResumePoint(MInstruction *oldInstruction, MInstruction *replacementInstruction) -{ - MOZ_ASSERT(!oldInstruction->isDiscarded()); - if (oldInstruction->resumePoint()) - replacementInstruction->stealResumePoint(oldInstruction); -} - -bool -ParallelSafetyAnalysis::analyze() -{ - // Walk the basic blocks in a DFS. When we encounter a block with an - // unsafe instruction, then we know that this block will bailout when - // executed. Therefore, we replace the block. - // - // We don't need a worklist, though, because the graph is sorted - // in RPO. Therefore, we just use the marked flags to tell us - // when we visited some predecessor of the current block. - ParallelSafetyVisitor visitor(graph_); - graph_.entryBlock()->mark(); // Note: in par. exec., we never enter from OSR. - uint32_t marked = 0; - for (ReversePostorderIterator block(graph_.rpoBegin()); block != graph_.rpoEnd(); block++) { - if (mir_->shouldCancel("ParallelSafetyAnalysis")) - return false; - - if (block->isMarked()) { - // Count the number of reachable blocks. - marked++; - - // Iterate through and transform the instructions. Stop - // if we encounter an inherently unsafe operation, in - // which case we will transform this block into a bailout - // block. - MInstruction *ins = nullptr; - MInstructionIterator iter(block->begin()); - while (iter != block->end() && !visitor.unsafe()) { - if (mir_->shouldCancel("ParallelSafetyAnalysis")) - return false; - - // We may be removing or replacing the current - // instruction, so advance `iter` now. Remember the - // last instr. we looked at for use later if it should - // prove unsafe. - ins = *iter++; - - ins->accept(&visitor); - } - - if (!visitor.unsafe()) { - // Block consists of only safe instructions. Visit its successors. - for (uint32_t i = 0; i < block->numSuccessors(); i++) - block->getSuccessor(i)->markUnchecked(); - } else { - // Block contains an unsafe instruction. That means that once - // we enter this block, we are guaranteed to bailout. - - // If this is the entry block, then there is no point - // in even trying to execute this function as it will - // always bailout. - if (*block == graph_.entryBlock()) { - Spew(SpewCompile, "Entry block contains unsafe MIR"); - mir_->disable(); - return false; - } - - // Otherwise, create a replacement that will. We seek back one - // position on the instruction iterator, as we will be - // discarding all instructions starting at the unsafe - // instruction. - if (!visitor.convertToBailout(--iter)) - return false; - } - } - } - - Spew(SpewCompile, "Safe"); - IonSpewPass("ParallelSafetyAnalysis"); - - // Sweep away any unmarked blocks. Note that this doesn't preserve - // AliasAnalysis dependencies, but we're not expected to at this point. - if (!RemoveUnmarkedBlocks(mir_, graph_, marked)) - return false; - IonSpewPass("UCEAfterParallelSafetyAnalysis"); - AssertExtendedGraphCoherency(graph_); - - return true; -} - -bool -ParallelSafetyVisitor::convertToBailout(MInstructionIterator &iter) -{ - // We expect iter to be settled on the unsafe instruction. - MInstruction *ins = *iter; - MBasicBlock *block = ins->block(); - MOZ_ASSERT(unsafe()); // `block` must have contained unsafe items - MOZ_ASSERT(block->isMarked()); // `block` must have been reachable to get here - - clearUnsafe(); - - // Allocate a new bailout instruction. - MBail *bail = MBail::New(graph_.alloc(), Bailout_ParallelUnsafe); - - // Discard the rest of the block and sever its link to its successors in - // the CFG. - for (size_t i = 0; i < block->numSuccessors(); i++) - block->getSuccessor(i)->removePredecessor(block); - block->discardAllInstructionsStartingAt(iter); - - // No more successors are reachable, so the current block can no longer be - // the parent of an inlined function. - if (block->outerResumePoint()) - block->clearOuterResumePoint(); - - // End the block in a bail. - block->add(bail); - block->end(MUnreachable::New(alloc())); - return true; -} - -///////////////////////////////////////////////////////////////////////////// -// Memory allocation -// -// Simple memory allocation opcodes---those which ultimately compile -// down to a (possibly inlined) invocation of NewGCThing()---are -// replaced with MNewPar, which is supplied with the thread context. -// These allocations will take place using per-helper-thread arenas. - -void -ParallelSafetyVisitor::visitCreateThisWithTemplate(MCreateThisWithTemplate *ins) -{ - replaceWithNewPar(ins, ins->templateObject()); -} - -void -ParallelSafetyVisitor::visitNewCallObject(MNewCallObject *ins) -{ - if (ins->templateObject()->hasDynamicSlots()) { - SpewMIR(ins, "call with dynamic slots"); - markUnsafe(); - } else { - replace(ins, MNewCallObjectPar::New(alloc(), ForkJoinContext(), ins)); - } -} - -void -ParallelSafetyVisitor::visitNewRunOnceCallObject(MNewRunOnceCallObject *ins) -{ - if (ins->templateObject()->hasDynamicSlots()) { - SpewMIR(ins, "call with dynamic slots"); - markUnsafe(); - } else { - replace(ins, MNewCallObjectPar::New(alloc(), ForkJoinContext(), ins)); - } -} - -void -ParallelSafetyVisitor::visitLambda(MLambda *ins) -{ - if (ins->info().singletonType || ins->info().useNewTypeForClone) { - // slow path: bail on parallel execution. - markUnsafe(); - } else { - // fast path: replace with LambdaPar op - replace(ins, MLambdaPar::New(alloc(), ForkJoinContext(), ins)); - } -} - -void -ParallelSafetyVisitor::visitNewObject(MNewObject *newInstruction) -{ - if (newInstruction->shouldUseVM()) { - SpewMIR(newInstruction, "should use VM"); - markUnsafe(); - } else { - replaceWithNewPar(newInstruction, newInstruction->templateObject()); - } -} - -void -ParallelSafetyVisitor::visitNewArray(MNewArray *newInstruction) -{ - if (newInstruction->shouldUseVM()) { - SpewMIR(newInstruction, "should use VM"); - markUnsafe(); - } else { - replaceWithNewPar(newInstruction, newInstruction->templateObject()); - } -} - -void -ParallelSafetyVisitor::visitNewDerivedTypedObject(MNewDerivedTypedObject *ins) -{ - // FIXME(Bug 984090) -- There should really be a parallel-safe - // version of NewDerivedTypedObject. However, until that is - // implemented, let's just ignore those with 0 uses, since they - // will be stripped out by DCE later. - if (!ins->hasUses()) - return; - - SpewMIR(ins, "visitNewDerivedTypedObject"); - markUnsafe(); -} - -void -ParallelSafetyVisitor::visitRest(MRest *ins) -{ - replace(ins, MRestPar::New(alloc(), ForkJoinContext(), ins)); -} - -void -ParallelSafetyVisitor::visitMathFunction(MMathFunction *ins) -{ - replace(ins, MMathFunction::New(alloc(), ins->input(), ins->function(), nullptr)); -} - -void -ParallelSafetyVisitor::visitConcat(MConcat *ins) -{ - replace(ins, MConcatPar::New(alloc(), ForkJoinContext(), ins)); -} - -void -ParallelSafetyVisitor::visitToString(MToString *ins) -{ - MIRType inputType = ins->input()->type(); - if (inputType != MIRType_Int32 && inputType != MIRType_Double) - markUnsafe(); -} - -void -ParallelSafetyVisitor::replaceWithNewPar(MInstruction *newInstruction, - NativeObject *templateObject) -{ - replace(newInstruction, MNewPar::New(alloc(), ForkJoinContext(), templateObject)); -} - -void -ParallelSafetyVisitor::replace(MInstruction *oldInstruction, - MInstruction *replacementInstruction) -{ - TransplantResumePoint(oldInstruction, replacementInstruction); - - MBasicBlock *block = oldInstruction->block(); - block->insertBefore(oldInstruction, replacementInstruction); - oldInstruction->replaceAllUsesWith(replacementInstruction); - block->discard(oldInstruction); - - // We may have replaced a specialized Float32 instruction by its - // non-specialized version, so just retry to specialize it. This relies on - // the fact that Phis' types don't change during the ParallelSafetyAnalysis; - // otherwise we'd have to run the entire TypeAnalyzer Float32 analysis once - // instructions have been replaced. - if (replacementInstruction->isFloat32Commutative() && - replacementInstruction->type() != MIRType_Float32) - { - replacementInstruction->trySpecializeFloat32(alloc()); - } - MOZ_ASSERT(oldInstruction->type() == replacementInstruction->type()); -} - -///////////////////////////////////////////////////////////////////////////// -// Write Guards -// -// We only want to permit writes to locally guarded objects. -// Furthermore, we want to avoid PICs and other non-thread-safe things -// (though perhaps we should support PICs at some point). If we -// cannot determine the origin of an object, we can insert a write -// guard which will check whether the object was allocated from the -// per-thread-arena or not. - -void -ParallelSafetyVisitor::insertWriteGuard(MInstruction *writeInstruction, - MDefinition *valueBeingWritten) -{ - // Many of the write operations do not take the JS object - // but rather something derived from it, such as the elements. - // So we need to identify the JS object: - MDefinition *object; - switch (valueBeingWritten->type()) { - case MIRType_Object: - object = valueBeingWritten; - break; - - case MIRType_Slots: - switch (valueBeingWritten->op()) { - case MDefinition::Op_Slots: - object = valueBeingWritten->toSlots()->object(); - break; - - default: - SpewMIR(writeInstruction, "cannot insert write guard for %s", - valueBeingWritten->opName()); - markUnsafe(); - return; - } - break; - - case MIRType_Elements: - switch (valueBeingWritten->op()) { - case MDefinition::Op_Elements: - object = valueBeingWritten->toElements()->object(); - break; - - case MDefinition::Op_TypedArrayElements: - object = valueBeingWritten->toTypedArrayElements()->object(); - break; - - case MDefinition::Op_TypedObjectElements: - object = valueBeingWritten->toTypedObjectElements()->object(); - break; - - default: - SpewMIR(writeInstruction, "cannot insert write guard for %s", - valueBeingWritten->opName()); - markUnsafe(); - return; - } - break; - - default: - SpewMIR(writeInstruction, "cannot insert write guard for MIR Type %d", - valueBeingWritten->type()); - markUnsafe(); - return; - } - - if (object->isUnbox()) - object = object->toUnbox()->input(); - - switch (object->op()) { - case MDefinition::Op_NewPar: - // MNewPar will always be creating something thread-local, omit the guard - SpewMIR(writeInstruction, "write to NewPar prop does not require guard"); - return; - default: - break; - } - - MBasicBlock *block = writeInstruction->block(); - MGuardThreadExclusive *writeGuard = - MGuardThreadExclusive::New(alloc(), ForkJoinContext(), object); - block->insertBefore(writeInstruction, writeGuard); - writeGuard->typePolicy()->adjustInputs(alloc(), writeGuard); -} - -///////////////////////////////////////////////////////////////////////////// -// Calls -// -// We only support calls to interpreted functions that that have already been -// Ion compiled. If a function has no IonScript, we bail out. - -void -ParallelSafetyVisitor::visitCall(MCall *ins) -{ - // DOM? Scary. - if (ins->isCallDOMNative()) { - SpewMIR(ins, "call to dom function"); - markUnsafe(); - return; - } - - JSFunction *target = ins->getSingleTarget(); - if (target) { - // Non-parallel native? Scary - if (target->isNative() && !target->hasParallelNative()) { - SpewMIR(ins, "call to non-parallel native function"); - markUnsafe(); - } - return; - } - - if (ins->isConstructing()) { - SpewMIR(ins, "call to unknown constructor"); - markUnsafe(); - } -} - -///////////////////////////////////////////////////////////////////////////// -// Stack limit, interrupts -// -// In sequential Ion code, the stack limit is stored in the JSRuntime. -// We store it in the thread context. We therefore need a separate -// instruction to access it, one parameterized by the thread context. -// Similar considerations apply to checking for interrupts. - -void -ParallelSafetyVisitor::visitCheckOverRecursed(MCheckOverRecursed *ins) -{ - replace(ins, MCheckOverRecursedPar::New(alloc(), ForkJoinContext())); -} - -void -ParallelSafetyVisitor::visitInterruptCheck(MInterruptCheck *ins) -{ - replace(ins, MInterruptCheckPar::New(alloc(), ForkJoinContext())); -} - -///////////////////////////////////////////////////////////////////////////// -// Specialized ops -// -// Some ops, like +, can be specialized to ints/doubles. Anything -// else is terrifying. -// -// TODO---Eventually, we should probably permit arbitrary + but bail -// if the operands are not both integers/floats. - -void -ParallelSafetyVisitor::visitSpecializedInstruction(MInstruction *ins, MIRType spec, - uint32_t flags) -{ - uint32_t flag = 1 << spec; - if (flags & flag) - return; - - SpewMIR(ins, "specialized to unacceptable type %d", spec); - markUnsafe(); -} - -///////////////////////////////////////////////////////////////////////////// -// Throw - -void -ParallelSafetyVisitor::visitThrow(MThrow *thr) -{ - MBasicBlock *block = thr->block(); - MOZ_ASSERT(block->lastIns() == thr); - MBail *bail = MBail::New(alloc(), Bailout_ParallelUnsafe); - block->discardLastIns(); - block->add(bail); - block->end(MUnreachable::New(alloc())); -} - -/////////////////////////////////////////////////////////////////////////// -// Callee extraction -// -// See comments in header file. - -static bool -GetPossibleCallees(JSContext *cx, HandleScript script, jsbytecode *pc, - types::TemporaryTypeSet *calleeTypes, CallTargetVector &targets); - -static bool -AddCallTarget(HandleScript script, CallTargetVector &targets); - -bool -jit::AddPossibleCallees(JSContext *cx, MIRGraph &graph, CallTargetVector &targets) -{ - for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) { - for (MInstructionIterator ins(block->begin()); ins != block->end(); ins++) - { - if (!ins->isCall()) - continue; - - MCall *callIns = ins->toCall(); - - RootedFunction target(cx, callIns->getSingleTarget()); - if (target) { - MOZ_ASSERT_IF(!target->isInterpreted(), target->hasParallelNative()); - - if (target->isInterpreted()) { - RootedScript script(cx, target->getOrCreateScript(cx)); - if (!script || !AddCallTarget(script, targets)) - return false; - } - - continue; - } - - types::TemporaryTypeSet *calleeTypes = callIns->getFunction()->resultTypeSet(); - RootedScript script(cx, callIns->block()->info().script()); - if (!GetPossibleCallees(cx, - script, - callIns->resumePoint()->pc(), - calleeTypes, - targets)) - return false; - } - } - - return true; -} - -static bool -GetPossibleCallees(JSContext *cx, - HandleScript script, - jsbytecode *pc, - types::TemporaryTypeSet *calleeTypes, - CallTargetVector &targets) -{ - if (!calleeTypes || calleeTypes->baseFlags() != 0) - return true; - - unsigned objCount = calleeTypes->getObjectCount(); - - if (objCount == 0) - return true; - - RootedFunction rootedFun(cx); - RootedScript rootedScript(cx); - for (unsigned i = 0; i < objCount; i++) { - JSObject *obj = calleeTypes->getSingleObject(i); - if (obj && obj->is()) { - rootedFun = &obj->as(); - } else { - types::TypeObject *typeObj = calleeTypes->getTypeObject(i); - if (!typeObj) - continue; - rootedFun = typeObj->interpretedFunction; - if (!rootedFun) - continue; - } - - if (!rootedFun->isInterpreted()) - continue; - - rootedScript = rootedFun->getOrCreateScript(cx); - if (!rootedScript) - return false; - - if (rootedScript->shouldCloneAtCallsite()) { - rootedFun = CloneFunctionAtCallsite(cx, rootedFun, script, pc); - if (!rootedFun) - return false; - rootedScript = rootedFun->nonLazyScript(); - } - - // check if this call target is already known - if (!AddCallTarget(rootedScript, targets)) - return false; - } - - return true; -} - -static bool -AddCallTarget(HandleScript script, CallTargetVector &targets) -{ - for (size_t i = 0; i < targets.length(); i++) { - if (targets[i] == script) - return true; - } - - if (!targets.append(script)) - return false; - - return true; -} diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/ParallelSafetyAnalysis.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/ParallelSafetyAnalysis.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/ParallelSafetyAnalysis.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/ParallelSafetyAnalysis.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sts=4 et sw=4 tw=99: - * 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 jit_ParallelSafetyAnalysis_h -#define jit_ParallelSafetyAnalysis_h - -#include "jit/MIR.h" - -namespace js { - -class InterpreterFrame; - -namespace jit { - -class MIRGraph; -class AutoDestroyAllocator; - -// Determines whether a function is compatible for parallel execution. -// Removes basic blocks containing unsafe MIR operations from the -// graph and replaces them with MBail blocks. -class ParallelSafetyAnalysis -{ - MIRGenerator *mir_; - MIRGraph &graph_; - - public: - ParallelSafetyAnalysis(MIRGenerator *mir, - MIRGraph &graph) - : mir_(mir), - graph_(graph) - {} - - bool analyze(); -}; - -// Code to collect list of possible call targets by scraping through -// TI and baseline data. Used to permit speculative transitive -// compilation in vm/ForkJoin. -// -// This code may clone scripts and thus may invoke the GC. Hence only -// run from the link phase, which executes on the main thread. -typedef Vector CallTargetVector; -bool AddPossibleCallees(JSContext *cx, MIRGraph &graph, CallTargetVector &targets); - -} // namespace jit -} // namespace js - -#endif /* jit_ParallelSafetyAnalysis_h */ diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/shared/BaselineCompiler-shared.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/shared/BaselineCompiler-shared.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/shared/BaselineCompiler-shared.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/shared/BaselineCompiler-shared.h 2015-01-09 12:36:47.000000000 +0000 @@ -140,6 +140,13 @@ }; bool callVM(const VMFunction &fun, CallVMPhase phase=POST_INITIALIZE); + bool callVMNonOp(const VMFunction &fun, CallVMPhase phase=POST_INITIALIZE) { + if (!callVM(fun, phase)) + return false; + icEntries_.back().setForNonOpCallVM(); + return true; + } + public: BytecodeAnalysis &analysis() { return analysis_; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/shared/CodeGenerator-shared.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/shared/CodeGenerator-shared.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/shared/CodeGenerator-shared.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/shared/CodeGenerator-shared.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -15,7 +15,6 @@ #include "jit/MacroAssembler.h" #include "jit/MIR.h" #include "jit/MIRGenerator.h" -#include "jit/ParallelFunctions.h" #include "js/Conversions.h" #include "vm/TraceLogging.h" @@ -494,13 +493,6 @@ if (!deoptTable_) return false; - // We do not generate a bailout table for parallel code. - switch (gen->info().executionMode()) { - case SequentialExecution: break; - case ParallelExecution: return false; - default: MOZ_CRASH("No such execution mode"); - } - MOZ_ASSERT(frameClass_ != FrameSizeClass::None()); if (snapshot->bailoutId() != INVALID_BAILOUT_ID) @@ -974,9 +966,6 @@ if (!checkOsiPointRegisters) return false; - if (gen->info().executionMode() != SequentialExecution) - return false; - if (safepoint->liveRegs().empty(true) && safepoint->liveRegs().empty(false)) return false; // No registers to check. @@ -1259,7 +1248,7 @@ } else { // The interrupt check should be the first instruction in the // loop header other than the initial label and move groups. - MOZ_ASSERT(iter->isInterruptCheck() || iter->isInterruptCheckPar()); + MOZ_ASSERT(iter->isInterruptCheck()); return nullptr; } } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/shared/CodeGenerator-shared.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/shared/CodeGenerator-shared.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/shared/CodeGenerator-shared.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/shared/CodeGenerator-shared.h 2015-01-09 12:36:47.000000000 +0000 @@ -17,7 +17,6 @@ #include "jit/Safepoints.h" #include "jit/Snapshots.h" #include "jit/VMFunctions.h" -#include "vm/ForkJoin.h" namespace js { namespace jit { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/shared/CodeGenerator-x86-shared.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/shared/CodeGenerator-x86-shared.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/shared/CodeGenerator-x86-shared.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/shared/CodeGenerator-x86-shared.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -370,7 +370,7 @@ // Push the frame size, so the handler can recover the IonScript. masm.push(Imm32(frameSize())); - JitCode *handler = gen->jitRuntime()->getGenericBailoutHandler(gen->info().executionMode()); + JitCode *handler = gen->jitRuntime()->getGenericBailoutHandler(); masm.jmp(ImmPtr(handler->raw()), Relocation::JITCODE); } @@ -3002,177 +3002,6 @@ } void -CodeGeneratorX86Shared::visitForkJoinGetSlice(LForkJoinGetSlice *ins) -{ - MOZ_ASSERT(gen->info().executionMode() == ParallelExecution); - MOZ_ASSERT(ToRegister(ins->forkJoinContext()) == ForkJoinGetSliceReg_cx); - MOZ_ASSERT(ToRegister(ins->temp1()) == eax); - MOZ_ASSERT(ToRegister(ins->temp2()) == edx); - MOZ_ASSERT(ToRegister(ins->temp3()) == ForkJoinGetSliceReg_temp0); - MOZ_ASSERT(ToRegister(ins->temp4()) == ForkJoinGetSliceReg_temp1); - MOZ_ASSERT(ToRegister(ins->output()) == ForkJoinGetSliceReg_output); - - masm.call(gen->jitRuntime()->forkJoinGetSliceStub()); -} - -JitCode * -JitRuntime::generateForkJoinGetSliceStub(JSContext *cx) -{ - MacroAssembler masm(cx); - - // We need two fixed temps. We need to fix eax for cmpxchg, and edx for - // div. - Register cxReg = ForkJoinGetSliceReg_cx, worker = cxReg; - Register pool = ForkJoinGetSliceReg_temp0; - Register bounds = ForkJoinGetSliceReg_temp1; - Register output = ForkJoinGetSliceReg_output; - - MOZ_ASSERT(worker != eax && worker != edx); - MOZ_ASSERT(pool != eax && pool != edx); - MOZ_ASSERT(bounds != eax && bounds != edx); - MOZ_ASSERT(output != eax && output != edx); - - Label stealWork, noMoreWork, gotSlice; - Operand workerSliceBounds(Address(worker, ThreadPoolWorker::offsetOfSliceBounds())); - - // Clobber cx to load the worker. - masm.push(cxReg); - masm.loadPtr(Address(cxReg, ForkJoinContext::offsetOfWorker()), worker); - - // Load the thread pool, which is used in all cases below. - masm.loadThreadPool(pool); - - { - // Try to get a slice from the current thread. - Label getOwnSliceLoopHead; - masm.bind(&getOwnSliceLoopHead); - - // Load the slice bounds for the current thread. - masm.loadSliceBounds(worker, bounds); - - // The slice bounds is a uint32 composed from two uint16s: - // [ from , to ] - // ^~~~ ^~ - // upper 16 bits | lower 16 bits - masm.move32(bounds, output); - masm.shrl(Imm32(16), output); - - // If we don't have any slices left ourselves, move on to stealing. - masm.branch16(Assembler::Equal, output, bounds, &stealWork); - - // If we still have work, try to CAS [ from+1, to ]. - masm.move32(bounds, edx); - masm.add32(Imm32(0x10000), edx); - masm.move32(bounds, eax); - masm.atomic_cmpxchg32(edx, workerSliceBounds, eax); - masm.j(Assembler::NonZero, &getOwnSliceLoopHead); - - // If the CAS succeeded, return |from| in output. - masm.jump(&gotSlice); - } - - // Try to steal work. - masm.bind(&stealWork); - - // It's not technically correct to test whether work-stealing is turned on - // only during stub-generation time, but it's a DEBUG only thing. - // - // If stealing is off, stealWork falls through to noMoreWork. - if (cx->runtime()->threadPool.workStealing()) { - Label stealWorkLoopHead; - masm.bind(&stealWorkLoopHead); - - // Check if we have work. - masm.branch32(Assembler::Equal, - Address(pool, ThreadPool::offsetOfPendingSlices()), - Imm32(0), &noMoreWork); - - // Get an id at random. The following is an inline of - // the 32-bit xorshift in ThreadPoolWorker::randomWorker(). - { - // Reload the current worker. - masm.loadPtr(Address(StackPointer, 0), cxReg); - masm.loadPtr(Address(cxReg, ForkJoinContext::offsetOfWorker()), worker); - - // Perform the xorshift to get a random number in eax, using edx - // as a temp. - Address rngState(worker, ThreadPoolWorker::offsetOfSchedulerRNGState()); - masm.load32(rngState, eax); - masm.move32(eax, edx); - masm.shll(Imm32(ThreadPoolWorker::XORSHIFT_A), eax); - masm.xor32(edx, eax); - masm.move32(eax, edx); - masm.shrl(Imm32(ThreadPoolWorker::XORSHIFT_B), eax); - masm.xor32(edx, eax); - masm.move32(eax, edx); - masm.shll(Imm32(ThreadPoolWorker::XORSHIFT_C), eax); - masm.xor32(edx, eax); - masm.store32(eax, rngState); - - // Compute the random worker id by computing % numWorkers. Reuse - // output as a temp. - masm.move32(Imm32(0), edx); - masm.move32(Imm32(cx->runtime()->threadPool.numWorkers()), output); - masm.udiv(output); - } - - // Load the worker from the workers array. - masm.loadPtr(Address(pool, ThreadPool::offsetOfWorkers()), worker); - masm.loadPtr(BaseIndex(worker, edx, ScalePointer), worker); - - // Try to get a slice from the designated victim worker. - Label stealSliceFromWorkerLoopHead; - masm.bind(&stealSliceFromWorkerLoopHead); - - // Load the slice bounds and decompose for the victim worker. - masm.loadSliceBounds(worker, bounds); - masm.move32(bounds, eax); - masm.shrl(Imm32(16), eax); - - // If the victim worker has no more slices left, find another worker. - masm.branch16(Assembler::Equal, eax, bounds, &stealWorkLoopHead); - - // If the victim worker still has work, try to CAS [ from, to-1 ]. - masm.move32(bounds, output); - masm.sub32(Imm32(1), output); - masm.move32(bounds, eax); - masm.atomic_cmpxchg32(output, workerSliceBounds, eax); - masm.j(Assembler::NonZero, &stealSliceFromWorkerLoopHead); - - // If the CAS succeeded, return |to-1| in output. -#ifdef DEBUG - masm.atomic_inc32(Operand(Address(pool, ThreadPool::offsetOfStolenSlices()))); -#endif - // Copies lower 16 bits only. - masm.movzwl(output, output); - } else { - masm.jump(&noMoreWork); - } - - // If we successfully got a slice, decrement pool->pendingSlices_ and - // return the slice. - masm.bind(&gotSlice); - masm.atomic_dec32(Operand(Address(pool, ThreadPool::offsetOfPendingSlices()))); - masm.pop(cxReg); - masm.ret(); - - // There's no more slices to give out, return a sentinel value. - masm.bind(&noMoreWork); - masm.move32(Imm32(ThreadPool::MAX_SLICE_ID), output); - masm.pop(cxReg); - masm.ret(); - - Linker linker(masm); - JitCode *code = linker.newCode(cx, OTHER_CODE); - -#ifdef JS_ION_PERF - writePerfSpewerJitCodeProfile(code, "ForkJoinGetSliceStub"); -#endif - - return code; -} - -void CodeGeneratorX86Shared::visitMemoryBarrier(LMemoryBarrier *ins) { if (ins->type() & MembarStoreLoad) diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/shared/CodeGenerator-x86-shared.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/shared/CodeGenerator-x86-shared.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/shared/CodeGenerator-x86-shared.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/shared/CodeGenerator-x86-shared.h 2015-01-09 12:36:47.000000000 +0000 @@ -207,8 +207,6 @@ void visitOutOfLineLoadTypedArrayOutOfBounds(OutOfLineLoadTypedArrayOutOfBounds *ool); - void visitForkJoinGetSlice(LForkJoinGetSlice *ins); - void visitNegI(LNegI *lir); void visitNegD(LNegD *lir); void visitNegF(LNegF *lir); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/shared/Lowering-shared.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/shared/Lowering-shared.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/shared/Lowering-shared.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/shared/Lowering-shared.h 2015-01-09 12:36:48.000000000 +0000 @@ -166,8 +166,11 @@ uint32_t getVirtualRegister() { uint32_t vreg = lirGraph_.getVirtualRegister(); - if (vreg >= MAX_VIRTUAL_REGISTERS) { - // Mark code generation as having failed, and return a dummy vreg. + + // If we run out of virtual registers, mark code generation as having + // failed and return a dummy vreg. Include a + 1 here for NUNBOX32 + // platforms that expect Value vregs to be adjacent. + if (vreg + 1 >= MAX_VIRTUAL_REGISTERS) { gen->abort("max virtual registers"); return 1; } @@ -215,11 +218,6 @@ return false; } - // Whether we can inline ForkJoinGetSlice. - static bool allowInlineForkJoinGetSlice() { - return false; - } - }; } // namespace jit diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/shared/Lowering-x86-shared.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/shared/Lowering-x86-shared.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/shared/Lowering-x86-shared.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/shared/Lowering-x86-shared.cpp 2015-01-09 12:36:48.000000000 +0000 @@ -359,19 +359,6 @@ } void -LIRGeneratorX86Shared::visitForkJoinGetSlice(MForkJoinGetSlice *ins) -{ - // We fix eax and edx for cmpxchg and div. - LForkJoinGetSlice *lir = new(alloc()) - LForkJoinGetSlice(useFixed(ins->forkJoinContext(), ForkJoinGetSliceReg_cx), - tempFixed(eax), - tempFixed(edx), - tempFixed(ForkJoinGetSliceReg_temp0), - tempFixed(ForkJoinGetSliceReg_temp1)); - defineFixed(lir, ins, LAllocation(AnyRegister(ForkJoinGetSliceReg_output))); -} - -void LIRGeneratorX86Shared::visitCompareExchangeTypedArrayElement(MCompareExchangeTypedArrayElement *ins) { MOZ_ASSERT(ins->arrayType() != Scalar::Float32); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/shared/Lowering-x86-shared.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/shared/Lowering-x86-shared.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/shared/Lowering-x86-shared.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/shared/Lowering-x86-shared.h 2015-01-09 12:36:48.000000000 +0000 @@ -52,7 +52,6 @@ void lowerConstantFloat32(float d, MInstruction *ins); void lowerTruncateDToInt32(MTruncateToInt32 *ins); void lowerTruncateFToInt32(MTruncateToInt32 *ins); - void visitForkJoinGetSlice(MForkJoinGetSlice *ins); void visitSimdBinaryArith(MSimdBinaryArith *ins); void visitSimdSelect(MSimdSelect *ins); void visitSimdSplatX4(MSimdSplatX4 *ins); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/TypedObjectPrediction.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/TypedObjectPrediction.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/TypedObjectPrediction.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/TypedObjectPrediction.cpp 2015-01-09 12:36:47.000000000 +0000 @@ -136,7 +136,7 @@ switch (predictionKind()) { case TypedObjectPrediction::Empty: case TypedObjectPrediction::Inconsistent: - break; + return false; case TypedObjectPrediction::Descr: *out = descr().size(); @@ -146,9 +146,10 @@ // We only know a prefix of the struct fields, hence we do not // know its complete size. return false; - } - MOZ_CRASH("Bad prediction kind"); + default: + MOZ_CRASH("Bad prediction kind"); + } } const TypedProto * @@ -168,9 +169,10 @@ // We only know a prefix of the struct fields, hence we cannot // say for certain what its prototype will be. return nullptr; - } - MOZ_CRASH("Bad prediction kind"); + default: + MOZ_CRASH("Bad prediction kind"); + } } template @@ -214,11 +216,10 @@ bool TypedObjectPrediction::hasKnownArrayLength(int32_t *length) const { - MOZ_ASSERT(ofArrayKind()); switch (predictionKind()) { case TypedObjectPrediction::Empty: case TypedObjectPrediction::Inconsistent: - break; + return false; case TypedObjectPrediction::Descr: // In later patches, this condition will always be true @@ -230,9 +231,12 @@ return false; case TypedObjectPrediction::Prefix: - break; // Prefixes are always structs, never arrays + // Prefixes are always structs, never arrays + return false; + + default: + MOZ_CRASH("Bad prediction kind"); } - MOZ_CRASH("Bad prediction kind"); } TypedObjectPrediction @@ -286,7 +290,7 @@ switch (predictionKind()) { case TypedObjectPrediction::Empty: case TypedObjectPrediction::Inconsistent: - break; + return false; case TypedObjectPrediction::Descr: return hasFieldNamedPrefix( @@ -297,6 +301,8 @@ return hasFieldNamedPrefix( *prefix().descr, prefix().fields, id, fieldOffset, fieldType, fieldIndex); + + default: + MOZ_CRASH("Bad prediction kind"); } - MOZ_CRASH("Bad prediction kind"); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/VMFunctions.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/VMFunctions.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/VMFunctions.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/VMFunctions.h 2015-01-09 12:36:47.000000000 +0000 @@ -15,7 +15,6 @@ namespace js { class DeclEnvObject; -class ForkJoinContext; class StaticWithObject; class InlineTypedObject; @@ -468,9 +467,6 @@ template <> struct MatchContext { static const ExecutionMode execMode = SequentialExecution; }; -template <> struct MatchContext { - static const ExecutionMode execMode = ParallelExecution; -}; template <> struct MatchContext { // ThreadSafeContext functions can be called from either mode, but for // calling from parallel they should be wrapped first, so we default to diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/x64/Assembler-x64.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/x64/Assembler-x64.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/x64/Assembler-x64.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/x64/Assembler-x64.h 2015-01-09 12:36:48.000000000 +0000 @@ -134,13 +134,6 @@ static MOZ_CONSTEXPR_VAR FloatRegister FloatArgRegs[NumFloatArgRegs] = { xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7 }; #endif -// The convention used by the ForkJoinGetSlice stub. None of these can be rax -// or rdx, which the stub also needs for cmpxchg and div, respectively. -static MOZ_CONSTEXPR_VAR Register ForkJoinGetSliceReg_cx = rdi; -static MOZ_CONSTEXPR_VAR Register ForkJoinGetSliceReg_temp0 = rbx; -static MOZ_CONSTEXPR_VAR Register ForkJoinGetSliceReg_temp1 = rcx; -static MOZ_CONSTEXPR_VAR Register ForkJoinGetSliceReg_output = rsi; - // Registers used in the GenerateFFIIonExit Enable Activation block. static MOZ_CONSTEXPR_VAR Register AsmJSIonExitRegCallee = r10; static MOZ_CONSTEXPR_VAR Register AsmJSIonExitRegE0 = rax; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/x64/Bailouts-x64.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/x64/Bailouts-x64.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/x64/Bailouts-x64.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/x64/Bailouts-x64.cpp 2015-01-09 12:36:48.000000000 +0000 @@ -54,11 +54,7 @@ topFrameSize_ = framePointer_ - sp; JSScript *script = ScriptFromCalleeToken(((JitFrameLayout *) framePointer_)->calleeToken()); - JitActivation *activation = activations.activation()->asJit(); - if (activation->cx()->isForkJoinContext()) - topIonScript_ = script->parallelIonScript(); - else - topIonScript_ = script->ionScript(); + topIonScript_ = script->ionScript(); attachOnJitActivation(activations); snapshotOffset_ = bailout->snapshotOffset(); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/x64/Lowering-x64.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/x64/Lowering-x64.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/x64/Lowering-x64.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/x64/Lowering-x64.h 2015-01-09 12:36:48.000000000 +0000 @@ -38,12 +38,6 @@ bool needTempForPostBarrier() { return false; } - // x64 has a scratch register, so no need for another temp for dispatch - // ICs. - LDefinition tempForDispatchCache(MIRType outputType = MIRType_None) { - return LDefinition::BogusTemp(); - } - public: void visitBox(MBox *box); void visitUnbox(MUnbox *unbox); @@ -55,10 +49,6 @@ void visitAsmJSLoadFuncPtr(MAsmJSLoadFuncPtr *ins); void visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic *ins); void visitSubstr(MSubstr *ins); - - static bool allowInlineForkJoinGetSlice() { - return true; - } }; typedef LIRGeneratorX64 LIRGeneratorSpecific; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/x64/Trampoline-x64.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/x64/Trampoline-x64.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/x64/Trampoline-x64.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/x64/Trampoline-x64.cpp 2015-01-09 12:36:48.000000000 +0000 @@ -11,7 +11,6 @@ #ifdef JS_ION_PERF # include "jit/PerfSpewer.h" #endif -#include "jit/ParallelFunctions.h" #include "jit/VMFunctions.h" #include "jit/x64/BaselineHelpers-x64.h" @@ -358,7 +357,7 @@ } JitCode * -JitRuntime::generateArgumentsRectifier(JSContext *cx, ExecutionMode mode, void **returnAddrOut) +JitRuntime::generateArgumentsRectifier(JSContext *cx, void **returnAddrOut) { // Do not erase the frame pointer in this function. @@ -421,7 +420,7 @@ // Note that this code assumes the function is JITted. masm.andq(Imm32(uint32_t(CalleeTokenMask)), rax); masm.loadPtr(Address(rax, JSFunction::offsetOfNativeOrScript()), rax); - masm.loadBaselineOrIonRaw(rax, rax, mode, nullptr); + masm.loadBaselineOrIonRaw(rax, rax, nullptr); masm.call(rax); uint32_t returnOffset = masm.currentOffset(); @@ -493,31 +492,6 @@ masm.jmp(bailoutTail); } -static void -GenerateParallelBailoutThunk(MacroAssembler &masm) -{ - // As GenerateBailoutThunk, except we return an error immediately. We do - // the bailout dance so that we can walk the stack and have accurate - // reporting of frame information. - - PushBailoutFrame(masm, r8); - - // Parallel bailout is like parallel failure in that we unwind all the way - // to the entry frame. Reserve space for the frame pointer of the entry frame. - masm.reserveStack(sizeof(uint8_t *)); - masm.movePtr(rsp, r9); - - masm.setupUnalignedABICall(2, rax); - masm.passABIArg(r8); - masm.passABIArg(r9); - masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, BailoutPar)); - - // Get the frame pointer of the entry frame and return. - masm.moveValue(MagicValue(JS_ION_ERROR), JSReturnOperand); - masm.loadPtr(Address(rsp, 0), rsp); - masm.ret(); -} - JitCode * JitRuntime::generateBailoutTable(JSContext *cx, uint32_t frameClass) { @@ -525,20 +499,10 @@ } JitCode * -JitRuntime::generateBailoutHandler(JSContext *cx, ExecutionMode mode) +JitRuntime::generateBailoutHandler(JSContext *cx) { MacroAssembler masm; - - switch (mode) { - case SequentialExecution: - GenerateBailoutThunk(cx, masm, NO_FRAME_SIZE_CLASS_ID); - break; - case ParallelExecution: - GenerateParallelBailoutThunk(masm); - break; - default: - MOZ_CRASH("No such execution mode"); - } + GenerateBailoutThunk(cx, masm, NO_FRAME_SIZE_CLASS_ID); Linker linker(masm); JitCode *code = linker.newCode(cx, OTHER_CODE); @@ -580,7 +544,8 @@ // +0 returnAddress // // We're aligned to an exit frame, so link it up. - masm.enterExitFrameAndLoadContext(&f, cxreg, regs.getAny(), f.executionMode); + masm.enterExitFrame(&f); + masm.loadJSContext(cxreg); // Save the current stack pointer as the base for copying arguments. Register argsBase = InvalidReg; @@ -665,11 +630,11 @@ // Test for failure. switch (f.failType()) { case Type_Object: - masm.branchTestPtr(Assembler::Zero, rax, rax, masm.failureLabel(f.executionMode)); + masm.branchTestPtr(Assembler::Zero, rax, rax, masm.failureLabel()); break; case Type_Bool: masm.testb(rax, rax); - masm.j(Assembler::Zero, masm.failureLabel(f.executionMode)); + masm.j(Assembler::Zero, masm.failureLabel()); break; default: MOZ_CRASH("unknown failure kind"); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/x86/Assembler-x86.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/x86/Assembler-x86.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/x86/Assembler-x86.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/x86/Assembler-x86.h 2015-01-09 12:36:48.000000000 +0000 @@ -60,13 +60,6 @@ static MOZ_CONSTEXPR_VAR Register CallTempReg4 = esi; static MOZ_CONSTEXPR_VAR Register CallTempReg5 = edx; -// The convention used by the ForkJoinGetSlice stub. None of these can be eax -// or edx, which the stub also needs for cmpxchg and div, respectively. -static MOZ_CONSTEXPR_VAR Register ForkJoinGetSliceReg_cx = edi; -static MOZ_CONSTEXPR_VAR Register ForkJoinGetSliceReg_temp0 = ebx; -static MOZ_CONSTEXPR_VAR Register ForkJoinGetSliceReg_temp1 = ecx; -static MOZ_CONSTEXPR_VAR Register ForkJoinGetSliceReg_output = esi; - // We have no arg regs, so our NonArgRegs are just our CallTempReg* static MOZ_CONSTEXPR_VAR Register CallTempNonArgRegs[] = { edi, eax, ebx, ecx, esi, edx }; static const uint32_t NumCallTempNonArgRegs = diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/x86/Bailouts-x86.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/x86/Bailouts-x86.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/x86/Bailouts-x86.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/x86/Bailouts-x86.cpp 2015-01-09 12:36:48.000000000 +0000 @@ -75,10 +75,7 @@ JSScript *script = ScriptFromCalleeToken(((JitFrameLayout *) framePointer_)->calleeToken()); JitActivation *activation = activations.activation()->asJit(); - if (activation->cx()->isForkJoinContext()) - topIonScript_ = script->parallelIonScript(); - else - topIonScript_ = script->ionScript(); + topIonScript_ = script->ionScript(); attachOnJitActivation(activations); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/x86/CodeGenerator-x86.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/x86/CodeGenerator-x86.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/x86/CodeGenerator-x86.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/x86/CodeGenerator-x86.cpp 2015-01-09 12:36:48.000000000 +0000 @@ -691,53 +691,6 @@ MOZ_CRASH("x86 needs manual assignment of dispatchScratch"); } -void -GetPropertyParIC::initializeAddCacheState(LInstruction *ins, AddCacheState *addState) -{ - // We don't have a scratch register, but only use the temp if we needed - // one, it's BogusTemp otherwise. - MOZ_ASSERT(ins->isGetPropertyCacheV() || ins->isGetPropertyCacheT()); - if (ins->isGetPropertyCacheV() || ins->toGetPropertyCacheT()->temp()->isBogusTemp()) - addState->dispatchScratch = output_.scratchReg().gpr(); - else - addState->dispatchScratch = ToRegister(ins->toGetPropertyCacheT()->temp()); -} - -void -GetElementParIC::initializeAddCacheState(LInstruction *ins, AddCacheState *addState) -{ - // We don't have a scratch register, but only use the temp if we needed - // one, it's BogusTemp otherwise. - MOZ_ASSERT(ins->isGetElementCacheV() || ins->isGetElementCacheT()); - if (ins->isGetElementCacheV() || ins->toGetElementCacheT()->temp()->isBogusTemp()) - addState->dispatchScratch = output_.scratchReg().gpr(); - else - addState->dispatchScratch = ToRegister(ins->toGetElementCacheT()->temp()); -} - -void -SetPropertyParIC::initializeAddCacheState(LInstruction *ins, AddCacheState *addState) -{ - // We don't have an output register to reuse, so we always need a temp. - MOZ_ASSERT(ins->isSetPropertyCacheV() || ins->isSetPropertyCacheT()); - if (ins->isSetPropertyCacheV()) - addState->dispatchScratch = ToRegister(ins->toSetPropertyCacheV()->tempForDispatchCache()); - else - addState->dispatchScratch = ToRegister(ins->toSetPropertyCacheT()->tempForDispatchCache()); -} - -void -SetElementParIC::initializeAddCacheState(LInstruction *ins, AddCacheState *addState) -{ - // We don't have an output register to reuse, but luckily SetElementCache - // already needs a temp. - MOZ_ASSERT(ins->isSetElementCacheV() || ins->isSetElementCacheT()); - if (ins->isSetElementCacheV()) - addState->dispatchScratch = ToRegister(ins->toSetElementCacheV()->temp()); - else - addState->dispatchScratch = ToRegister(ins->toSetElementCacheT()->temp()); -} - namespace js { namespace jit { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/x86/Lowering-x86.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/x86/Lowering-x86.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/x86/Lowering-x86.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/x86/Lowering-x86.cpp 2015-01-09 12:36:48.000000000 +0000 @@ -14,29 +14,6 @@ using namespace js; using namespace js::jit; -LDefinition -LIRGeneratorX86::tempForDispatchCache(MIRType outputType) -{ - // x86 doesn't have a scratch register and we need one for the - // indirect jump for dispatch-style ICs. - // - // Note that currently we only install dispatch-style ICs for parallel - // execution. If this assumption changes, please change it here. - if (gen->info().executionMode() != ParallelExecution) - return LDefinition::BogusTemp(); - - // If we don't have an output register, we need a temp. - if (outputType == MIRType_None) - return temp(); - - // If we have a double output register, we need a temp. - if (outputType == MIRType_Double) - return temp(); - - // Otherwise we have a non-double output register and we can reuse it. - return LDefinition::BogusTemp(); -} - void LIRGeneratorX86::useBox(LInstruction *lir, size_t n, MDefinition *mir, LUse::Policy policy, bool useAtStart) diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/x86/Lowering-x86.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/x86/Lowering-x86.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/x86/Lowering-x86.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/x86/Lowering-x86.h 2015-01-09 12:36:48.000000000 +0000 @@ -41,8 +41,6 @@ bool needTempForPostBarrier() { return true; } - LDefinition tempForDispatchCache(MIRType outputType = MIRType_None); - void lowerUntypedPhiInput(MPhi *phi, uint32_t inputPosition, LBlock *block, size_t lirIndex); void defineUntypedPhi(MPhi *phi, size_t lirIndex); @@ -66,9 +64,6 @@ static bool allowStaticTypedArrayAccesses() { return true; } - static bool allowInlineForkJoinGetSlice() { - return true; - } }; typedef LIRGeneratorX86 LIRGeneratorSpecific; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/x86/Trampoline-x86.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/x86/Trampoline-x86.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit/x86/Trampoline-x86.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit/x86/Trampoline-x86.cpp 2015-01-09 12:36:48.000000000 +0000 @@ -15,14 +15,11 @@ #ifdef JS_ION_PERF # include "jit/PerfSpewer.h" #endif -#include "jit/ParallelFunctions.h" #include "jit/VMFunctions.h" #include "jit/x86/BaselineHelpers-x86.h" #include "jsscriptinlines.h" -#include "jit/ExecutionMode-inl.h" - using namespace js; using namespace js::jit; @@ -354,7 +351,7 @@ } JitCode * -JitRuntime::generateArgumentsRectifier(JSContext *cx, ExecutionMode mode, void **returnAddrOut) +JitRuntime::generateArgumentsRectifier(JSContext *cx, void **returnAddrOut) { MacroAssembler masm(cx); @@ -425,7 +422,7 @@ // Note that this assumes the function is JITted. masm.andl(Imm32(CalleeTokenMask), eax); masm.loadPtr(Address(eax, JSFunction::offsetOfNativeOrScript()), eax); - masm.loadBaselineOrIonRaw(eax, eax, mode, nullptr); + masm.loadBaselineOrIonRaw(eax, eax, nullptr); masm.call(eax); uint32_t returnOffset = masm.currentOffset(); @@ -516,31 +513,6 @@ masm.jmp(bailoutTail); } -static void -GenerateParallelBailoutThunk(MacroAssembler &masm, uint32_t frameClass) -{ - // As GenerateBailoutThunk, except we return an error immediately. We do - // the bailout dance so that we can walk the stack and have accurate - // reporting of frame information. - - PushBailoutFrame(masm, frameClass, eax); - - // Parallel bailout is like parallel failure in that we unwind all the way - // to the entry frame. Reserve space for the frame pointer of the entry frame. - masm.reserveStack(sizeof(uint8_t *)); - masm.movePtr(esp, ebx); - - masm.setupUnalignedABICall(2, ecx); - masm.passABIArg(eax); - masm.passABIArg(ebx); - masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, BailoutPar)); - - // Get the frame pointer of the entry frame and return. - masm.moveValue(MagicValue(JS_ION_ERROR), JSReturnOperand); - masm.loadPtr(Address(esp, 0), esp); - masm.ret(); -} - JitCode * JitRuntime::generateBailoutTable(JSContext *cx, uint32_t frameClass) { @@ -564,20 +536,10 @@ } JitCode * -JitRuntime::generateBailoutHandler(JSContext *cx, ExecutionMode mode) +JitRuntime::generateBailoutHandler(JSContext *cx) { MacroAssembler masm; - - switch (mode) { - case SequentialExecution: - GenerateBailoutThunk(cx, masm, NO_FRAME_SIZE_CLASS_ID); - break; - case ParallelExecution: - GenerateParallelBailoutThunk(masm, NO_FRAME_SIZE_CLASS_ID); - break; - default: - MOZ_CRASH("No such execution mode"); - } + GenerateBailoutThunk(cx, masm, NO_FRAME_SIZE_CLASS_ID); Linker linker(masm); JitCode *code = linker.newCode(cx, OTHER_CODE); @@ -618,7 +580,8 @@ // +0 returnAddress // // We're aligned to an exit frame, so link it up. - masm.enterExitFrameAndLoadContext(&f, cxreg, regs.getAny(), f.executionMode); + masm.enterExitFrame(&f); + masm.loadJSContext(cxreg); // Save the current stack pointer as the base for copying arguments. Register argsBase = InvalidReg; @@ -704,11 +667,11 @@ // Test for failure. switch (f.failType()) { case Type_Object: - masm.branchTestPtr(Assembler::Zero, eax, eax, masm.failureLabel(f.executionMode)); + masm.branchTestPtr(Assembler::Zero, eax, eax, masm.failureLabel()); break; case Type_Bool: masm.testb(eax, eax); - masm.j(Assembler::Zero, masm.failureLabel(f.executionMode)); + masm.j(Assembler::Zero, masm.failureLabel()); break; default: MOZ_CRASH("unknown failure kind"); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit-test/tests/debug/execution-observability-03.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit-test/tests/debug/execution-observability-03.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit-test/tests/debug/execution-observability-03.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit-test/tests/debug/execution-observability-03.js 2015-01-09 12:36:45.000000000 +0000 @@ -0,0 +1,17 @@ +// Tests that bare callVMs (in the delprop below) are patched correctly. + +var o = {}; +var global = this; +var p = new Proxy(o, { + "deleteProperty": function (target, key) { + var g = newGlobal(); + g.parent = global; + g.eval("var dbg = new Debugger(parent); dbg.onEnterFrame = function(frame) {};"); + return true; + } +}); +function test() { + for (var i=0; i<100; i++) {} + assertEq(delete p.foo, true); +} +test(); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit-test/tests/TypedObject/bug1109911.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit-test/tests/TypedObject/bug1109911.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jit-test/tests/TypedObject/bug1109911.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jit-test/tests/TypedObject/bug1109911.js 2015-01-09 12:36:41.000000000 +0000 @@ -0,0 +1,12 @@ + +if (typeof TypedObject === "undefined") + quit(); + +var int32x4 = SIMD.int32x4; +var a = int32x4((4294967295), 200, 300, 400); +addCase( new Array(Math.pow(2,12)) ); +for ( var arg = "", i = 0; i < Math.pow(2,12); i++ ) {} +addCase( a ); +function addCase(object) { + object.length +} diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jsapi-tests/testGCFinalizeCallback.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jsapi-tests/testGCFinalizeCallback.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jsapi-tests/testGCFinalizeCallback.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jsapi-tests/testGCFinalizeCallback.cpp 2015-01-09 12:36:48.000000000 +0000 @@ -24,7 +24,7 @@ /* Full GC, incremental. */ FinalizeCalls = 0; JS::PrepareForFullGC(rt); - JS::IncrementalGC(rt, JS::gcreason::API, 1000000); + JS::StartIncrementalGC(rt, GC_NORMAL, JS::gcreason::API, 1000000); CHECK(!rt->gc.isIncrementalGCInProgress()); CHECK(rt->gc.isFullGc()); CHECK(checkMultipleGroups()); @@ -41,7 +41,7 @@ /* Compartment GC, non-incremental, single compartment. */ FinalizeCalls = 0; JS::PrepareZoneForGC(global1->zone()); - JS::GCForReason(rt, JS::gcreason::API); + JS::GCForReason(rt, GC_NORMAL, JS::gcreason::API); CHECK(!rt->gc.isFullGc()); CHECK(checkSingleGroup()); CHECK(checkFinalizeStatus()); @@ -52,7 +52,7 @@ JS::PrepareZoneForGC(global1->zone()); JS::PrepareZoneForGC(global2->zone()); JS::PrepareZoneForGC(global3->zone()); - JS::GCForReason(rt, JS::gcreason::API); + JS::GCForReason(rt, GC_NORMAL, JS::gcreason::API); CHECK(!rt->gc.isFullGc()); CHECK(checkSingleGroup()); CHECK(checkFinalizeStatus()); @@ -61,7 +61,7 @@ /* Compartment GC, incremental, single compartment. */ FinalizeCalls = 0; JS::PrepareZoneForGC(global1->zone()); - JS::IncrementalGC(rt, JS::gcreason::API, 1000000); + JS::StartIncrementalGC(rt, GC_NORMAL, JS::gcreason::API, 1000000); CHECK(!rt->gc.isIncrementalGCInProgress()); CHECK(!rt->gc.isFullGc()); CHECK(checkSingleGroup()); @@ -73,7 +73,7 @@ JS::PrepareZoneForGC(global1->zone()); JS::PrepareZoneForGC(global2->zone()); JS::PrepareZoneForGC(global3->zone()); - JS::IncrementalGC(rt, JS::gcreason::API, 1000000); + JS::StartIncrementalGC(rt, GC_NORMAL, JS::gcreason::API, 1000000); CHECK(!rt->gc.isIncrementalGCInProgress()); CHECK(!rt->gc.isFullGc()); CHECK(checkMultipleGroups()); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jsapi-tests/testPreserveJitCode.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jsapi-tests/testPreserveJitCode.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jsapi-tests/testPreserveJitCode.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jsapi-tests/testPreserveJitCode.cpp 2015-01-09 12:36:48.000000000 +0000 @@ -65,10 +65,10 @@ CHECK_EQUAL(value.toInt32(), 45); CHECK_EQUAL(countIonScripts(global), 1u); - GCForReason(rt, gcreason::API); + GCForReason(rt, GC_NORMAL, gcreason::API); CHECK_EQUAL(countIonScripts(global), remainingIonScripts); - ShrinkingGC(rt, gcreason::API); + GCForReason(rt, GC_SHRINK, gcreason::API); CHECK_EQUAL(countIonScripts(global), 0u); return true; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jsapi-tests/tests.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jsapi-tests/tests.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jsapi-tests/tests.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jsapi-tests/tests.h 2015-01-09 12:36:48.000000000 +0000 @@ -428,7 +428,7 @@ JS_GetGCZeal(cx_, &zeal_, &frequency_); JS_SetGCZeal(cx_, 0, 0); JS::PrepareForFullGC(JS_GetRuntime(cx_)); - JS::ShrinkingGC(JS_GetRuntime(cx_), JS::gcreason::DEBUG_GC); + JS::GCForReason(JS_GetRuntime(cx_), GC_SHRINK, JS::gcreason::DEBUG_GC); } ~AutoLeaveZeal() { JS_SetGCZeal(cx_, zeal_, frequency_); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jscntxt.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jscntxt.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jscntxt.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jscntxt.cpp 2015-01-09 12:36:48.000000000 +0000 @@ -1007,8 +1007,6 @@ if (maybecx->isExceptionPending()) { MOZ_ASSERT(maybecx->isThrowingOutOfMemory()); maybecx->clearPendingException(); - } else { - MOZ_ASSERT(maybecx->runtime()->hadOutOfMemory); } } } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jsfriendapi.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jsfriendapi.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jsfriendapi.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jsfriendapi.cpp 2015-01-09 12:36:48.000000000 +0000 @@ -153,72 +153,6 @@ return obj; } -JS_FRIEND_API(void) -JS::PrepareZoneForGC(Zone *zone) -{ - zone->scheduleGC(); -} - -JS_FRIEND_API(void) -JS::PrepareForFullGC(JSRuntime *rt) -{ - for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) - zone->scheduleGC(); -} - -JS_FRIEND_API(void) -JS::PrepareForIncrementalGC(JSRuntime *rt) -{ - if (!JS::IsIncrementalGCInProgress(rt)) - return; - - for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) { - if (zone->wasGCStarted()) - PrepareZoneForGC(zone); - } -} - -JS_FRIEND_API(bool) -JS::IsGCScheduled(JSRuntime *rt) -{ - for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) { - if (zone->isGCScheduled()) - return true; - } - - return false; -} - -JS_FRIEND_API(void) -JS::SkipZoneForGC(Zone *zone) -{ - zone->unscheduleGC(); -} - -JS_FRIEND_API(void) -JS::GCForReason(JSRuntime *rt, gcreason::Reason reason) -{ - rt->gc.gc(GC_NORMAL, reason); -} - -JS_FRIEND_API(void) -JS::ShrinkingGC(JSRuntime *rt, gcreason::Reason reason) -{ - rt->gc.gc(GC_SHRINK, reason); -} - -JS_FRIEND_API(void) -JS::IncrementalGC(JSRuntime *rt, gcreason::Reason reason, int64_t millis) -{ - rt->gc.gcSlice(GC_NORMAL, reason, millis); -} - -JS_FRIEND_API(void) -JS::FinishIncrementalGC(JSRuntime *rt, gcreason::Reason reason) -{ - rt->gc.gcFinalSlice(GC_NORMAL, reason); -} - JS_FRIEND_API(JSPrincipals *) JS_GetCompartmentPrincipals(JSCompartment *compartment) { @@ -1063,12 +997,6 @@ return cx->currentlyRunning(); } -JS_FRIEND_API(JS::GCSliceCallback) -JS::SetGCSliceCallback(JSRuntime *rt, GCSliceCallback callback) -{ - return rt->gc.setSliceCallback(callback); -} - JS_FRIEND_API(int64_t) GetMaxGCPauseSinceClear(JSRuntime *rt) { @@ -1081,160 +1009,12 @@ return rt->gc.stats.clearMaxGCPauseAccumulator(); } -JS_FRIEND_API(bool) -JS::WasIncrementalGC(JSRuntime *rt) -{ - return rt->gc.isIncrementalGc(); -} - -char16_t * -JS::GCDescription::formatMessage(JSRuntime *rt) const -{ - return rt->gc.stats.formatMessage(); -} - -char16_t * -JS::GCDescription::formatJSON(JSRuntime *rt, uint64_t timestamp) const -{ - return rt->gc.stats.formatJSON(timestamp); -} - JS_FRIEND_API(void) JS::NotifyDidPaint(JSRuntime *rt) { rt->gc.notifyDidPaint(); } -JS_FRIEND_API(bool) -JS::IsIncrementalGCEnabled(JSRuntime *rt) -{ - return rt->gc.isIncrementalGCEnabled(); -} - -JS_FRIEND_API(bool) -JS::IsIncrementalGCInProgress(JSRuntime *rt) -{ - return rt->gc.isIncrementalGCInProgress() && !rt->gc.isVerifyPreBarriersEnabled(); -} - -JS_FRIEND_API(void) -JS::DisableIncrementalGC(JSRuntime *rt) -{ - rt->gc.disallowIncrementalGC(); -} - -JS_FRIEND_API(void) -JS::DisableCompactingGC(JSRuntime *rt) -{ -#ifdef JSGC_COMPACTING - rt->gc.disableCompactingGC(); -#endif -} - -JS_FRIEND_API(bool) -JS::IsCompactingGCEnabled(JSRuntime *rt) -{ -#ifdef JSGC_COMPACTING - return rt->gc.isCompactingGCEnabled(); -#else - return false; -#endif -} - -JS::AutoDisableGenerationalGC::AutoDisableGenerationalGC(JSRuntime *rt) - : gc(&rt->gc) -#ifdef JS_GC_ZEAL - , restartVerifier(false) -#endif -{ -#ifdef JS_GC_ZEAL - restartVerifier = gc->endVerifyPostBarriers(); -#endif - gc->disableGenerationalGC(); -} - -JS::AutoDisableGenerationalGC::~AutoDisableGenerationalGC() -{ - gc->enableGenerationalGC(); -#ifdef JS_GC_ZEAL - if (restartVerifier) { - MOZ_ASSERT(gc->isGenerationalGCEnabled()); - gc->startVerifyPostBarriers(); - } -#endif -} - -extern JS_FRIEND_API(bool) -JS::IsGenerationalGCEnabled(JSRuntime *rt) -{ - return rt->gc.isGenerationalGCEnabled(); -} - -JS_FRIEND_API(bool) -JS::IsIncrementalBarrierNeeded(JSRuntime *rt) -{ - return rt->gc.state() == gc::MARK && !rt->isHeapBusy(); -} - -JS_FRIEND_API(bool) -JS::IsIncrementalBarrierNeeded(JSContext *cx) -{ - return IsIncrementalBarrierNeeded(cx->runtime()); -} - -JS_FRIEND_API(void) -JS::IncrementalObjectBarrier(JSObject *obj) -{ - if (!obj) - return; - - MOZ_ASSERT(!obj->zone()->runtimeFromMainThread()->isHeapMajorCollecting()); - - JSObject::writeBarrierPre(obj); -} - -JS_FRIEND_API(void) -JS::IncrementalReferenceBarrier(GCCellPtr thing) -{ - if (!thing) - return; - - if (thing.isString() && StringIsPermanentAtom(thing.toString())) - return; - -#ifdef DEBUG - Zone *zone = thing.isObject() - ? thing.toObject()->zone() - : thing.asCell()->asTenured().zone(); - MOZ_ASSERT(!zone->runtimeFromMainThread()->isHeapMajorCollecting()); -#endif - - switch(thing.kind()) { - case JSTRACE_OBJECT: return JSObject::writeBarrierPre(thing.toObject()); - case JSTRACE_STRING: return JSString::writeBarrierPre(thing.toString()); - case JSTRACE_SCRIPT: return JSScript::writeBarrierPre(thing.toScript()); - case JSTRACE_SYMBOL: return JS::Symbol::writeBarrierPre(thing.toSymbol()); - case JSTRACE_LAZY_SCRIPT: - return LazyScript::writeBarrierPre(static_cast(thing.asCell())); - case JSTRACE_JITCODE: - return jit::JitCode::writeBarrierPre(static_cast(thing.asCell())); - case JSTRACE_SHAPE: - return Shape::writeBarrierPre(static_cast(thing.asCell())); - case JSTRACE_BASE_SHAPE: - return BaseShape::writeBarrierPre(static_cast(thing.asCell())); - case JSTRACE_TYPE_OBJECT: - return types::TypeObject::writeBarrierPre(static_cast(thing.asCell())); - default: - MOZ_CRASH("Invalid trace kind in IncrementalReferenceBarrier."); - } -} - -JS_FRIEND_API(void) -JS::IncrementalValueBarrier(const Value &v) -{ - js::HeapValue::writeBarrierPre(v); -} - JS_FRIEND_API(void) JS::PokeGC(JSRuntime *rt) { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jsgc.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jsgc.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jsgc.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jsgc.cpp 2015-01-09 12:36:49.000000000 +0000 @@ -631,18 +631,6 @@ } } -static inline Chunk * -AllocChunk(JSRuntime *rt) -{ - return static_cast(MapAlignedPages(ChunkSize, ChunkSize)); -} - -static inline void -FreeChunk(JSRuntime *rt, Chunk *p) -{ - UnmapPages(static_cast(p), ChunkSize); -} - Chunk * ChunkPool::pop() { @@ -767,7 +755,7 @@ iter.next(); pool.remove(chunk); MOZ_ASSERT(!chunk->info.numArenasFreeCommitted); - FreeChunk(rt, chunk); + UnmapPages(static_cast(chunk), ChunkSize); } MOZ_ASSERT(pool.count() == 0); } @@ -781,7 +769,7 @@ /* static */ Chunk * Chunk::allocate(JSRuntime *rt) { - Chunk *chunk = AllocChunk(rt); + Chunk *chunk = static_cast(MapAlignedPages(ChunkSize, ChunkSize)); if (!chunk) return nullptr; chunk->init(rt); @@ -789,15 +777,6 @@ return chunk; } -/* Must be called with the GC lock taken. */ -void -GCRuntime::releaseChunk(Chunk *chunk) -{ - MOZ_ASSERT(chunk); - prepareToFreeChunk(chunk->info); - FreeChunk(rt, chunk); -} - inline void GCRuntime::prepareToFreeChunk(ChunkInfo &info) { @@ -3324,7 +3303,7 @@ !isBackgroundSweeping()) { PrepareZoneForGC(zone); - gcSlice(GC_NORMAL, JS::gcreason::MAYBEGC); + startGC(GC_NORMAL, JS::gcreason::MAYBEGC); return true; } @@ -3345,12 +3324,12 @@ */ #ifndef JS_MORE_DETERMINISTIC int64_t now = PRMJ_Now(); - if (nextFullGCTime && nextFullGCTime <= now) { + if (nextFullGCTime && nextFullGCTime <= now && !isIncrementalGCInProgress()) { if (chunkAllocationSinceLastGC || numArenasFreeCommitted > decommitThreshold) { JS::PrepareForFullGC(rt); - gcSlice(GC_SHRINK, JS::gcreason::MAYBEGC); + startGC(GC_SHRINK, JS::gcreason::MAYBEGC); } else { nextFullGCTime = now + GC_IDLE_FULL_SPAN; } @@ -5773,9 +5752,16 @@ /* Finish sweeping the current zone group, then abort. */ abortSweepAfterCurrentGroup = true; + + /* Don't perform any compaction after sweeping. */ + JSGCInvocationKind oldInvocationKind = invocationKind; + invocationKind = GC_NORMAL; + SliceBudget budget; incrementalCollectSlice(budget, JS::gcreason::RESET); + invocationKind = oldInvocationKind; + { gcstats::AutoPhase ap(stats, gcstats::PHASE_WAIT_BACKGROUND_THREAD); rt->gc.waitBackgroundSweepOrAllocEnd(); @@ -6098,8 +6084,7 @@ * to run another cycle. */ MOZ_NEVER_INLINE bool -GCRuntime::gcCycle(bool incremental, SliceBudget &budget, JSGCInvocationKind gckind, - JS::gcreason::Reason reason) +GCRuntime::gcCycle(bool incremental, SliceBudget &budget, JS::gcreason::Reason reason) { evictNursery(reason); @@ -6162,10 +6147,6 @@ TraceMajorGCStart(); - /* Set the invocation kind in the first slice. */ - if (!isIncrementalGCInProgress()) - invocationKind = gckind; - incrementalCollectSlice(budget, reason); #ifndef JS_MORE_DETERMINISTIC @@ -6250,8 +6231,7 @@ } void -GCRuntime::collect(bool incremental, SliceBudget &budget, JSGCInvocationKind gckind, - JS::gcreason::Reason reason) +GCRuntime::collect(bool incremental, SliceBudget budget, JS::gcreason::Reason reason) { /* GC shouldn't be running in parallel execution mode */ MOZ_ALWAYS_TRUE(!InParallelSection()); @@ -6278,9 +6258,9 @@ AutoStopVerifyingBarriers av(rt, reason == JS::gcreason::SHUTDOWN_CC || reason == JS::gcreason::DESTROY_RUNTIME); - gcstats::AutoGCSlice agc(stats, scanZonesBeforeGC(), gckind, reason); + gcstats::AutoGCSlice agc(stats, scanZonesBeforeGC(), invocationKind, reason); - cleanUpEverything = ShouldCleanUpEverything(reason, gckind); + cleanUpEverything = ShouldCleanUpEverything(reason, invocationKind); bool repeat = false; do { @@ -6295,7 +6275,7 @@ } poked = false; - bool wasReset = gcCycle(incremental, budget, gckind, reason); + bool wasReset = gcCycle(incremental, budget, reason); if (!isIncrementalGCInProgress()) { gcstats::AutoPhase ap(stats, gcstats::PHASE_GC_END); @@ -6337,34 +6317,48 @@ EnqueuePendingParseTasksAfterGC(rt); } +SliceBudget +GCRuntime::defaultBudget(JS::gcreason::Reason reason, int64_t millis) +{ + if (millis == 0) { + if (reason == JS::gcreason::ALLOC_TRIGGER) + millis = sliceBudget; + else if (schedulingState.inHighFrequencyGCMode() && tunables.isDynamicMarkSliceEnabled()) + millis = sliceBudget * IGC_MARK_SLICE_MULTIPLIER; + else + millis = sliceBudget; + } + + return SliceBudget(TimeBudget(millis)); +} + void GCRuntime::gc(JSGCInvocationKind gckind, JS::gcreason::Reason reason) { - SliceBudget budget; - collect(false, budget, gckind, reason); + invocationKind = gckind; + collect(false, SliceBudget(), reason); } void -GCRuntime::gcSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64_t millis) +GCRuntime::startGC(JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64_t millis) { - SliceBudget budget; - if (millis) - budget = SliceBudget(TimeBudget(millis)); - else if (reason == JS::gcreason::ALLOC_TRIGGER) - budget = SliceBudget(TimeBudget(sliceBudget)); - else if (schedulingState.inHighFrequencyGCMode() && tunables.isDynamicMarkSliceEnabled()) - budget = SliceBudget(TimeBudget(sliceBudget * IGC_MARK_SLICE_MULTIPLIER)); - else - budget = SliceBudget(TimeBudget(sliceBudget)); + MOZ_ASSERT(!isIncrementalGCInProgress()); + invocationKind = gckind; + collect(true, defaultBudget(reason, millis), reason); +} - collect(true, budget, gckind, reason); +void +GCRuntime::gcSlice(JS::gcreason::Reason reason, int64_t millis) +{ + MOZ_ASSERT(isIncrementalGCInProgress()); + collect(true, defaultBudget(reason, millis), reason); } void -GCRuntime::gcFinalSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason) +GCRuntime::finishGC(JS::gcreason::Reason reason) { - SliceBudget budget; - collect(true, budget, gckind, reason); + MOZ_ASSERT(isIncrementalGCInProgress()); + collect(true, SliceBudget(), reason); } void @@ -6383,14 +6377,14 @@ if (zealMode == ZealFrameGCValue) { JS::PrepareForFullGC(rt); - gcSlice(GC_NORMAL, JS::gcreason::REFRESH_FRAME); + gc(GC_NORMAL, JS::gcreason::REFRESH_FRAME); return; } #endif - if (JS::IsIncrementalGCInProgress(rt) && !interFrameGC) { + if (isIncrementalGCInProgress() && !interFrameGC) { JS::PrepareForIncrementalGC(rt); - gcSlice(GC_NORMAL, JS::gcreason::REFRESH_FRAME); + gcSlice(JS::gcreason::REFRESH_FRAME); } interFrameGC = false; @@ -6410,12 +6404,14 @@ GCRuntime::gcDebugSlice(SliceBudget &budget) { if (!ZonesSelected(rt)) { - if (JS::IsIncrementalGCInProgress(rt)) + if (isIncrementalGCInProgress()) JS::PrepareForIncrementalGC(rt); else JS::PrepareForFullGC(rt); } - collect(true, budget, GC_NORMAL, JS::gcreason::DEBUG_GC); + if (!isIncrementalGCInProgress()) + invocationKind = GC_NORMAL; + collect(true, budget, JS::gcreason::DEBUG_GC); } /* Schedule a full GC unless a zone will already be collected. */ @@ -6426,7 +6422,7 @@ JS::PrepareForFullGC(rt); } -JS_FRIEND_API(void) +JS_PUBLIC_API(void) JS::ShrinkGCBuffers(JSRuntime *rt) { rt->gc.shrinkBuffers(); @@ -6534,7 +6530,10 @@ } if (majorGCRequested) { - gcSlice(GC_NORMAL, rt->gc.majorGCTriggerReason); + if (!isIncrementalGCInProgress()) + startGC(GC_NORMAL, majorGCTriggerReason); + else + gcSlice(majorGCTriggerReason); return true; } @@ -6699,7 +6698,9 @@ budget = SliceBudget(WorkBudget(1)); } - collect(true, budget, GC_NORMAL, JS::gcreason::DEBUG_GC); + if (!isIncrementalGCInProgress()) + invocationKind = GC_NORMAL; + collect(true, budget, JS::gcreason::DEBUG_GC); /* * For multi-slice zeal, reset the slice size when we get to the sweep @@ -6711,9 +6712,9 @@ incrementalLimit = zealFrequency / 2; } } else if (type == ZealCompactValue) { - collect(false, budget, GC_SHRINK, JS::gcreason::DEBUG_GC); + gc(GC_SHRINK, JS::gcreason::DEBUG_GC); } else { - collect(false, budget, GC_NORMAL, JS::gcreason::DEBUG_GC); + gc(GC_NORMAL, JS::gcreason::DEBUG_GC); } #endif @@ -6793,8 +6794,7 @@ for (ZoneCellIter i(zone, FINALIZE_SCRIPT); !i.done(); i.next()) { JSScript *script = i.get(); - jit::FinishInvalidation(fop, script); - jit::FinishInvalidation(fop, script); + jit::FinishInvalidation(fop, script); /* * Discard baseline script if it's not marked as active. Note that @@ -6940,7 +6940,7 @@ MOZ_ASSERT(MapAllocToTraceKind(cell->asTenured().getAllocKind()) == kind); } -JS_FRIEND_API(size_t) +JS_PUBLIC_API(size_t) JS::GetGCNumber() { JSRuntime *rt = js::TlsPerThreadData.get()->runtimeFromMainThread(); @@ -7078,3 +7078,225 @@ } } #endif + +JS_PUBLIC_API(void) +JS::PrepareZoneForGC(Zone *zone) +{ + zone->scheduleGC(); +} + +JS_PUBLIC_API(void) +JS::PrepareForFullGC(JSRuntime *rt) +{ + for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) + zone->scheduleGC(); +} + +JS_PUBLIC_API(void) +JS::PrepareForIncrementalGC(JSRuntime *rt) +{ + if (!JS::IsIncrementalGCInProgress(rt)) + return; + + for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) { + if (zone->wasGCStarted()) + PrepareZoneForGC(zone); + } +} + +JS_PUBLIC_API(bool) +JS::IsGCScheduled(JSRuntime *rt) +{ + for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) { + if (zone->isGCScheduled()) + return true; + } + + return false; +} + +JS_PUBLIC_API(void) +JS::SkipZoneForGC(Zone *zone) +{ + zone->unscheduleGC(); +} + +JS_PUBLIC_API(void) +JS::GCForReason(JSRuntime *rt, JSGCInvocationKind gckind, gcreason::Reason reason) +{ + MOZ_ASSERT(gckind == GC_NORMAL || gckind == GC_SHRINK); + rt->gc.gc(gckind, reason); +} + +JS_PUBLIC_API(void) +JS::StartIncrementalGC(JSRuntime *rt, JSGCInvocationKind gckind, gcreason::Reason reason, int64_t millis) +{ + MOZ_ASSERT(gckind == GC_NORMAL || gckind == GC_SHRINK); + rt->gc.startGC(gckind, reason, millis); +} + +JS_PUBLIC_API(void) +JS::IncrementalGCSlice(JSRuntime *rt, gcreason::Reason reason, int64_t millis) +{ + rt->gc.gcSlice(reason, millis); +} + +JS_PUBLIC_API(void) +JS::FinishIncrementalGC(JSRuntime *rt, gcreason::Reason reason) +{ + rt->gc.finishGC(reason); +} + +char16_t * +JS::GCDescription::formatMessage(JSRuntime *rt) const +{ + return rt->gc.stats.formatMessage(); +} + +char16_t * +JS::GCDescription::formatJSON(JSRuntime *rt, uint64_t timestamp) const +{ + return rt->gc.stats.formatJSON(timestamp); +} + +JS_PUBLIC_API(JS::GCSliceCallback) +JS::SetGCSliceCallback(JSRuntime *rt, GCSliceCallback callback) +{ + return rt->gc.setSliceCallback(callback); +} + +JS_PUBLIC_API(void) +JS::DisableIncrementalGC(JSRuntime *rt) +{ + rt->gc.disallowIncrementalGC(); +} + +JS_PUBLIC_API(bool) +JS::IsIncrementalGCEnabled(JSRuntime *rt) +{ + return rt->gc.isIncrementalGCEnabled(); +} + +JS_PUBLIC_API(void) +JS::DisableCompactingGC(JSRuntime *rt) +{ +#ifdef JSGC_COMPACTING + rt->gc.disableCompactingGC(); +#endif +} + +JS_PUBLIC_API(bool) +JS::IsCompactingGCEnabled(JSRuntime *rt) +{ +#ifdef JSGC_COMPACTING + return rt->gc.isCompactingGCEnabled(); +#else + return false; +#endif +} + +JS_PUBLIC_API(bool) +JS::IsIncrementalGCInProgress(JSRuntime *rt) +{ + return rt->gc.isIncrementalGCInProgress() && !rt->gc.isVerifyPreBarriersEnabled(); +} + +JS_PUBLIC_API(bool) +JS::IsIncrementalBarrierNeeded(JSRuntime *rt) +{ + return rt->gc.state() == gc::MARK && !rt->isHeapBusy(); +} + +JS_PUBLIC_API(bool) +JS::IsIncrementalBarrierNeeded(JSContext *cx) +{ + return IsIncrementalBarrierNeeded(cx->runtime()); +} + +JS_PUBLIC_API(void) +JS::IncrementalReferenceBarrier(GCCellPtr thing) +{ + if (!thing) + return; + + if (thing.isString() && StringIsPermanentAtom(thing.toString())) + return; + +#ifdef DEBUG + Zone *zone = thing.isObject() + ? thing.toObject()->zone() + : thing.asCell()->asTenured().zone(); + MOZ_ASSERT(!zone->runtimeFromMainThread()->isHeapMajorCollecting()); +#endif + + switch(thing.kind()) { + case JSTRACE_OBJECT: return JSObject::writeBarrierPre(thing.toObject()); + case JSTRACE_STRING: return JSString::writeBarrierPre(thing.toString()); + case JSTRACE_SCRIPT: return JSScript::writeBarrierPre(thing.toScript()); + case JSTRACE_SYMBOL: return JS::Symbol::writeBarrierPre(thing.toSymbol()); + case JSTRACE_LAZY_SCRIPT: + return LazyScript::writeBarrierPre(static_cast(thing.asCell())); + case JSTRACE_JITCODE: + return jit::JitCode::writeBarrierPre(static_cast(thing.asCell())); + case JSTRACE_SHAPE: + return Shape::writeBarrierPre(static_cast(thing.asCell())); + case JSTRACE_BASE_SHAPE: + return BaseShape::writeBarrierPre(static_cast(thing.asCell())); + case JSTRACE_TYPE_OBJECT: + return types::TypeObject::writeBarrierPre(static_cast(thing.asCell())); + default: + MOZ_CRASH("Invalid trace kind in IncrementalReferenceBarrier."); + } +} + +JS_PUBLIC_API(void) +JS::IncrementalValueBarrier(const Value &v) +{ + js::HeapValue::writeBarrierPre(v); +} + +JS_PUBLIC_API(void) +JS::IncrementalObjectBarrier(JSObject *obj) +{ + if (!obj) + return; + + MOZ_ASSERT(!obj->zone()->runtimeFromMainThread()->isHeapMajorCollecting()); + + JSObject::writeBarrierPre(obj); +} + +JS_PUBLIC_API(bool) +JS::WasIncrementalGC(JSRuntime *rt) +{ + return rt->gc.isIncrementalGc(); +} + +JS::AutoDisableGenerationalGC::AutoDisableGenerationalGC(JSRuntime *rt) + : gc(&rt->gc) +#ifdef JS_GC_ZEAL + , restartVerifier(false) +#endif +{ +#ifdef JS_GC_ZEAL + restartVerifier = gc->endVerifyPostBarriers(); +#endif + gc->disableGenerationalGC(); +} + +JS::AutoDisableGenerationalGC::~AutoDisableGenerationalGC() +{ + gc->enableGenerationalGC(); +#ifdef JS_GC_ZEAL + if (restartVerifier) { + MOZ_ASSERT(gc->isGenerationalGCEnabled()); + gc->startVerifyPostBarriers(); + } +#endif +} + +JS_PUBLIC_API(bool) +JS::IsGenerationalGCEnabled(JSRuntime *rt) +{ + return rt->gc.isGenerationalGCEnabled(); +} diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jsgc.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jsgc.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jsgc.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jsgc.h 2015-01-09 12:36:49.000000000 +0000 @@ -903,17 +903,6 @@ extern void ReleaseAllJITCode(FreeOp *op); -/* - * Kinds of js_GC invocation. - */ -typedef enum JSGCInvocationKind { - /* Normal invocation. */ - GC_NORMAL = 0, - - /* Minimize GC triggers and release empty GC chunks right away. */ - GC_SHRINK = 1 -} JSGCInvocationKind; - extern void PrepareForDebugGC(JSRuntime *rt); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jsgcinlines.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jsgcinlines.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jsgcinlines.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jsgcinlines.h 2015-01-09 12:36:49.000000000 +0000 @@ -444,7 +444,7 @@ static inline bool PossiblyFail() { - JS_OOM_POSSIBLY_FAIL(); + JS_OOM_POSSIBLY_FAIL_BOOL(); return true; } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jsinfer.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jsinfer.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jsinfer.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jsinfer.cpp 2015-01-09 12:36:49.000000000 +0000 @@ -4653,7 +4653,9 @@ bool TypeObject::needsSweep() { - return generation() != zone()->types.generation; + // Note: this can be called off thread during compacting GCs, in which case + // nothing will be running on the main thread. + return generation() != zoneFromAnyThread()->types.generation; } #endif @@ -5267,11 +5269,11 @@ { MOZ_ASSERT(!needsSweep()); MOZ_ASSERT(kind <= (OBJECT_FLAG_ADDENDUM_MASK >> OBJECT_FLAG_ADDENDUM_SHIFT)); - MOZ_ASSERT(!(flags_ & OBJECT_FLAG_ADDENDUM_MASK)); + MOZ_ASSERT(addendumKind() == 0 || addendumKind() == kind); // Manually trigger barriers if we are clearing a TypeNewScript. Other // kinds of addendums are immutable. - if (addendum_) { + if (newScript()) { MOZ_ASSERT(kind == Addendum_NewScript); TypeNewScript::writeBarrierPre(newScript()); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jsinfer.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jsinfer.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jsinfer.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jsinfer.h 2015-01-09 12:36:49.000000000 +0000 @@ -1155,11 +1155,17 @@ setAddendum(Addendum_NewScript, newScript); } - TypeDescr &typeDescr() { + TypeDescr *maybeTypeDescr() { // Note: there is no need to sweep when accessing the type descriptor // of an object, as it is strongly held and immutable. + if (addendumKind() == Addendum_TypeDescr) + return reinterpret_cast(addendum_); + return nullptr; + } + + TypeDescr &typeDescr() { MOZ_ASSERT(addendumKind() == Addendum_TypeDescr); - return *reinterpret_cast(addendum_); + return *maybeTypeDescr(); } void setTypeDescr(TypeDescr *descr) { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jsiter.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jsiter.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jsiter.cpp 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jsiter.cpp 2015-01-09 12:36:49.000000000 +0000 @@ -9,6 +9,7 @@ #include "jsiter.h" #include "mozilla/ArrayUtils.h" +#include "mozilla/Maybe.h" #include "mozilla/MemoryReporting.h" #include "mozilla/PodOperations.h" @@ -45,6 +46,7 @@ using JS::ForOfIterator; using mozilla::ArrayLength; +using mozilla::Maybe; #ifdef JS_MORE_DETERMINISTIC using mozilla::PodCopy; #endif @@ -96,7 +98,7 @@ static inline bool Enumerate(JSContext *cx, HandleObject pobj, jsid id, - bool enumerable, unsigned flags, IdSet& ht, AutoIdVector *props) + bool enumerable, unsigned flags, Maybe& ht, AutoIdVector *props) { // We implement __proto__ using a property on |Object.prototype|, but // because __proto__ is highly deserving of removal, we don't want it to @@ -108,15 +110,22 @@ return true; if (!(flags & JSITER_OWNONLY) || pobj->is() || pobj->getOps()->enumerate) { + if (!ht) { + ht.emplace(cx); + // Most of the time there are only a handful of entries. + if (!ht->init(5)) + return false; + } + // If we've already seen this, we definitely won't add it. - IdSet::AddPtr p = ht.lookupForAdd(id); + IdSet::AddPtr p = ht->lookupForAdd(id); if (MOZ_UNLIKELY(!!p)) return true; // It's not necessary to add properties to the hash table at the end of // the prototype chain, but custom enumeration behaviors might return // duplicated properties, so always add in such cases. - if ((pobj->is() || pobj->getProto() || pobj->getOps()->enumerate) && !ht.add(p, id)) + if ((pobj->is() || pobj->getProto() || pobj->getOps()->enumerate) && !ht->add(p, id)) return false; } @@ -132,7 +141,7 @@ } static bool -EnumerateNativeProperties(JSContext *cx, HandleNativeObject pobj, unsigned flags, IdSet &ht, +EnumerateNativeProperties(JSContext *cx, HandleNativeObject pobj, unsigned flags, Maybe &ht, AutoIdVector *props) { bool enumerateSymbols; @@ -273,11 +282,9 @@ static bool Snapshot(JSContext *cx, HandleObject pobj_, unsigned flags, AutoIdVector *props) { - // ~90% of the time this table ends up with 3 or fewer elements. - IdSet ht(cx); - if (!ht.init(3)) - return false; - + // We initialize |ht| lazily (in Enumerate()) because it ends up unused + // anywhere from 67--99.9% of the time. + Maybe ht; RootedObject pobj(cx, pobj_); do { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jspubtd.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jspubtd.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/jspubtd.h 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/jspubtd.h 2015-01-09 12:36:49.000000000 +0000 @@ -146,9 +146,9 @@ js::gc::StoreBuffer *gcStoreBufferPtr_; public: - explicit Runtime(js::gc::StoreBuffer *storeBuffer) + Runtime() : needsIncrementalBarrier_(false) - , gcStoreBufferPtr_(storeBuffer) + , gcStoreBufferPtr_(nullptr) {} bool needsIncrementalBarrier() const { @@ -161,6 +161,11 @@ return reinterpret_cast(rt); } + protected: + void setGCStoreBufferPtr(js::gc::StoreBuffer *storeBuffer) { + gcStoreBufferPtr_ = storeBuffer; + } + /* Allow inlining of PersistentRooted constructors and destructors. */ private: template friend class JS::PersistentRooted; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/moz.build thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/moz.build --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/moz.build 2015-01-07 22:15:25.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/moz.build 2015-01-09 12:36:49.000000000 +0000 @@ -178,8 +178,6 @@ 'jit/MIR.cpp', 'jit/MIRGraph.cpp', 'jit/MoveResolver.cpp', - 'jit/ParallelFunctions.cpp', - 'jit/ParallelSafetyAnalysis.cpp', 'jit/PerfSpewer.cpp', 'jit/RangeAnalysis.cpp', 'jit/Recover.cpp', diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/tests/browser.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/tests/browser.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/tests/browser.js 2015-01-07 22:15:26.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/tests/browser.js 2015-01-09 12:36:49.000000000 +0000 @@ -552,6 +552,16 @@ } } +function newGlobal() { + var iframe = document.createElement("iframe"); + document.documentElement.appendChild(iframe); + var win = iframe.contentWindow; + iframe.remove(); + // Shim in "evaluate" + win.evaluate = win.eval; + return win; +} + registerDialogCloser(); window.addEventListener('unload', unregisterDialogCloser, true); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/tests/ecma_5/extensions/reviver-mutates-holder-array-ccw.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/tests/ecma_5/extensions/reviver-mutates-holder-array-ccw.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/tests/ecma_5/extensions/reviver-mutates-holder-array-ccw.js 2015-01-07 22:15:26.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/tests/ecma_5/extensions/reviver-mutates-holder-array-ccw.js 2015-01-09 12:36:51.000000000 +0000 @@ -15,14 +15,6 @@ * BEGIN TEST * **************/ -if (typeof newGlobal !== "function") -{ - var newGlobal = function() - { - return { evaluate: eval }; - }; -} - var proxyObj = null; var arr = JSON.parse('[0, 1]', function(prop, v) { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/tests/ecma_5/extensions/reviver-mutates-holder-object-ccw.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/tests/ecma_5/extensions/reviver-mutates-holder-object-ccw.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/tests/ecma_5/extensions/reviver-mutates-holder-object-ccw.js 2015-01-07 22:15:26.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/tests/ecma_5/extensions/reviver-mutates-holder-object-ccw.js 2015-01-09 12:36:51.000000000 +0000 @@ -15,14 +15,6 @@ * BEGIN TEST * **************/ -if (typeof newGlobal !== "function") -{ - var newGlobal = function() - { - return { evaluate: eval }; - }; -} - // A little trickiness to account for the undefined-ness of property // enumeration order. var first = "unset"; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/tests/ecma_6/Array/from_realms.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/tests/ecma_6/Array/from_realms.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/tests/ecma_6/Array/from_realms.js 2015-01-07 22:15:26.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/tests/ecma_6/Array/from_realms.js 2015-01-09 12:36:52.000000000 +0000 @@ -25,11 +25,12 @@ h.mainGlobal = this; h.eval("function f() { mainGlobal.result = this; }"); g.Array.from.call(Array, [5, 6, 7], h.f); - // (Give each global in the test a name, for better error messages.) - this.name = "main"; - g.name = "g"; - h.name = "h"; - assertEq(result.name, "h"); + // (Give each global in the test a name, for better error messages. But use + // globalName, because window.name is complicated.) + this.globalName = "main"; + g.globalName = "g"; + h.globalName = "h"; + assertEq(result.globalName, "h"); } if (typeof reportCompare === 'function') diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/tests/ecma_6/TypedArray/reduce-and-reduceRight.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/tests/ecma_6/TypedArray/reduce-and-reduceRight.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/tests/ecma_6/TypedArray/reduce-and-reduceRight.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/tests/ecma_6/TypedArray/reduce-and-reduceRight.js 2015-01-09 12:36:52.000000000 +0000 @@ -0,0 +1,202 @@ +const constructors = [ + Int8Array, + Uint8Array, + Uint8ClampedArray, + Int16Array, + Uint16Array, + Int32Array, + Uint32Array, + Float32Array, + Float64Array +]; + +// Tests for TypedArray#reduce. +for (var constructor of constructors) { + assertEq(constructor.prototype.reduce.length, 1); + + // Basic tests. + var arr = new constructor([1, 2, 3, 4, 5]); + + assertEq(arr.reduce((previous, current) => previous + current), 15); + assertEq(arr.reduce((previous, current) => current - previous), 3); + + var count = 0; + var sum = 0; + assertEq(arr.reduce((previous, current, index, array) => { + count++; + sum += current; + assertEq(current - 1, index); + assertEq(current, arr[index]); + assertEq(array, arr); + return previous * current; + }), 120); + assertEq(count, 4); + assertEq(sum, 14); + + // Tests for `initialValue` argument. + assertEq(arr.reduce((previous, current) => previous + current, -15), 0); + assertEq(arr.reduce((previous, current) => previous + current, ""), "12345"); + assertDeepEq(arr.reduce((previous, current) => previous.concat(current), []), [1, 2, 3, 4, 5]); + + // Tests for `this` value. + var global = this; + arr.reduce(function(){ + assertEq(this, global); + }); + arr.reduce(function(){ + "use strict"; + assertEq(this, undefined); + }); + arr.reduce(() => assertEq(this, global)); + + // Throw an exception in the callback. + var count = 0; + var sum = 0; + assertThrowsInstanceOf(() => { + arr.reduce((previous, current, index, array) => { + count++; + sum += current; + if (index === 3) { + throw TypeError("reduce"); + } + }) + }, TypeError); + assertEq(count, 3); + assertEq(sum, 9); + + // There is no callback or callback is not a function. + assertThrowsInstanceOf(() => { + arr.reduce(); + }, TypeError); + var invalidCallbacks = [undefined, null, 1, false, "", Symbol(), [], {}, /./]; + invalidCallbacks.forEach(callback => { + assertThrowsInstanceOf(() => { + arr.reduce(callback); + }, TypeError); + }) + + // Callback is a generator. + arr.reduce(function*(){ + throw "This line will not be executed"; + }); + + // Called from other globals. + if (typeof newGlobal === "function") { + var reduce = newGlobal()[constructor.name].prototype.reduce; + assertEq(reduce.call(arr, (previous, current) => Math.min(previous, current)), 1); + } + + // Throws if `this` isn't a TypedArray. + var invalidReceivers = [undefined, null, 1, false, "", Symbol(), [], {}, /./]; + invalidReceivers.forEach(invalidReceiver => { + assertThrowsInstanceOf(() => { + constructor.prototype.reduce.call(invalidReceiver, () => {}); + }, TypeError, "Assert that reduce fails if this value is not a TypedArray"); + }); + // FIXME: Should throw exception if `this` is a proxy, see bug 1115361. + constructor.prototype.reduce.call(new Proxy(new constructor(3), {}), () => {}); + + // Test that the length getter is never called. + assertEq(Object.defineProperty(arr, "length", { + get() { + throw new Error("length accessor called"); + } + }).reduce((previous, current) => Math.max(previous, current)), 5); +} + +// Tests for TypedArray#reduceRight. +for (var constructor of constructors) { + assertEq(constructor.prototype.reduceRight.length, 1); + + // Basic tests. + var arr = new constructor([1, 2, 3, 4, 5]); + + assertEq(arr.reduceRight((previous, current) => previous + current), 15); + assertEq(arr.reduceRight((previous, current) => current - previous), 3); + + var count = 0; + var sum = 0; + assertEq(arr.reduceRight((previous, current, index, array) => { + count++; + sum += current; + assertEq(current - 1, index); + assertEq(current, arr[index]); + assertEq(array, arr); + return previous * current; + }), 120); + assertEq(count, 4); + assertEq(sum, 10); + + // Tests for `initialValue` argument. + assertEq(arr.reduceRight((previous, current) => previous + current, -15), 0); + assertEq(arr.reduceRight((previous, current) => previous + current, ""), "54321"); + assertDeepEq(arr.reduceRight((previous, current) => previous.concat(current), []), [5, 4, 3, 2, 1]); + + // Tests for `this` value. + var global = this; + arr.reduceRight(function(){ + assertEq(this, global); + }); + arr.reduceRight(function(){ + "use strict"; + assertEq(this, undefined); + }); + arr.reduceRight(() => assertEq(this, global)); + + // Throw an exception in the callback. + var count = 0; + var sum = 0; + assertThrowsInstanceOf(() => { + arr.reduceRight((previous, current, index, array) => { + count++; + sum += current; + if (index === 1) { + throw TypeError("reduceRight"); + } + }) + }, TypeError); + assertEq(count, 3); + assertEq(sum, 9); + + // There is no callback or callback is not a function. + assertThrowsInstanceOf(() => { + arr.reduceRight(); + }, TypeError); + var invalidCallbacks = [undefined, null, 1, false, "", Symbol(), [], {}, /./]; + invalidCallbacks.forEach(callback => { + assertThrowsInstanceOf(() => { + arr.reduceRight(callback); + }, TypeError); + }) + + // Callback is a generator. + arr.reduceRight(function*(){ + throw "This line will not be executed"; + }); + + // Called from other globals. + if (typeof newGlobal === "function") { + var reduceRight = newGlobal()[constructor.name].prototype.reduceRight; + assertEq(reduceRight.call(arr, (previous, current) => Math.min(previous, current)), 1); + } + + // Throws if `this` isn't a TypedArray. + var invalidReceivers = [undefined, null, 1, false, "", Symbol(), [], {}, /./]; + invalidReceivers.forEach(invalidReceiver => { + assertThrowsInstanceOf(() => { + constructor.prototype.reduceRight.call(invalidReceiver, () => {}); + }, TypeError, "Assert that reduceRight fails if this value is not a TypedArray"); + }); + // FIXME: Should throw exception if `this` is a proxy, see bug 1115361. + constructor.prototype.reduceRight.call(new Proxy(new constructor(3), {}), () => {}); + + // Test that the length getter is never called. + assertEq(Object.defineProperty(arr, "length", { + get() { + throw new Error("length accessor called"); + } + }).reduceRight((previous, current) => Math.max(previous, current)), 5); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); \ No newline at end of file diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/tests/lib/jittests.py thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/tests/lib/jittests.py --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/tests/lib/jittests.py 2015-01-07 22:15:27.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/tests/lib/jittests.py 2015-01-09 12:36:55.000000000 +0000 @@ -703,9 +703,17 @@ return ok def get_remote_results(tests, device, prefix, options): - for i in xrange(0, options.repeat): - for test in tests: - yield run_test_remote(test, device, prefix, options) + from mozdevice import devicemanager + + try: + for i in xrange(0, options.repeat): + for test in tests: + yield run_test_remote(test, device, prefix, options) + except devicemanager.DMError as e: + # After a devicemanager error, the device is typically in a + # state where all further tests will fail so there is no point in + # continuing here. + sys.stderr.write("Error running remote tests: %s" % e.message) def push_libs(options, device): # This saves considerable time in pushing unnecessary libraries diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/vm/ForkJoin.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/vm/ForkJoin.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/vm/ForkJoin.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/vm/ForkJoin.cpp 2015-01-09 12:37:00.000000000 +0000 @@ -206,8 +206,6 @@ bool invalidateBailedOutScripts(); ExecutionStatus sequentialExecution(bool disqualified); - TrafficLight appendCallTargetsToWorklist(uint32_t index, ExecutionStatus *status); - TrafficLight appendCallTargetToWorklist(HandleScript script, ExecutionStatus *status); bool addToWorklist(HandleScript script); inline bool hasScript(const types::RecompileInfoVector &scripts, JSScript *script); }; // class ForkJoinOperation @@ -677,7 +675,7 @@ if (!script->hasParallelIonScript()) { // Script has not yet been compiled. Attempt to compile it. SpewBeginCompile(script); - MethodStatus mstatus = CanEnterInParallel(cx_, script); + MethodStatus mstatus = Method_Error; SpewEndCompile(mstatus); switch (mstatus) { @@ -727,8 +725,6 @@ // worklist if so. Clear the flag after that, since we // will be compiling the call targets. MOZ_ASSERT(script->hasParallelIonScript()); - if (appendCallTargetsToWorklist(i, status) == RedLight) - return RedLight; } // If there is compilation occurring in a helper thread, then @@ -794,65 +790,6 @@ return GreenLight; } -ForkJoinOperation::TrafficLight -ForkJoinOperation::appendCallTargetsToWorklist(uint32_t index, ExecutionStatus *status) -{ - // GreenLight: call targets appended - // RedLight: fatal error or completed work via warmups or fallback - - MOZ_ASSERT(worklist_[index]->hasParallelIonScript()); - - // Check whether we have already enqueued the targets for - // this entry and avoid doing it again if so. - if (worklistData_[index].calleesEnqueued) - return GreenLight; - worklistData_[index].calleesEnqueued = true; - - // Iterate through the callees and enqueue them. - RootedScript target(cx_); - IonScript *ion = worklist_[index]->parallelIonScript(); - for (uint32_t i = 0; i < ion->callTargetEntries(); i++) { - target = ion->callTargetList()[i]; - parallel::Spew(parallel::SpewCompile, - "Adding call target %s:%u", - target->filename(), target->lineno()); - if (appendCallTargetToWorklist(target, status) == RedLight) - return RedLight; - } - - return GreenLight; -} - -ForkJoinOperation::TrafficLight -ForkJoinOperation::appendCallTargetToWorklist(HandleScript script, ExecutionStatus *status) -{ - // GreenLight: call target appended if necessary - // RedLight: fatal error or completed work via warmups or fallback - - MOZ_ASSERT(script); - - // Fallback to sequential if disabled. - if (!script->canParallelIonCompile()) { - Spew(SpewCompile, "Skipping %p:%s:%u, canParallelIonCompile() is false", - script.get(), script->filename(), script->lineno()); - return sequentialExecution(true, status); - } - - if (script->hasParallelIonScript()) { - // Skip if the code is expected to result in a bailout. - if (script->parallelIonScript()->bailoutExpected()) { - Spew(SpewCompile, "Skipping %p:%s:%u, bailout expected", - script.get(), script->filename(), script->lineno()); - return sequentialExecution(false, status); - } - } - - if (!addToWorklist(script)) - return fatalError(status); - - return GreenLight; -} - bool ForkJoinOperation::addToWorklist(HandleScript script) { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/vm/HelperThreads.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/vm/HelperThreads.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/vm/HelperThreads.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/vm/HelperThreads.cpp 2015-01-09 12:37:00.000000000 +0000 @@ -469,7 +469,7 @@ threads(nullptr), asmJSCompilationInProgress(false), helperLock(nullptr), -#ifdef DEbUG +#ifdef DEBUG lockOwner(nullptr), #endif consumerWakeup(nullptr), diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/vm/Runtime.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/vm/Runtime.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/vm/Runtime.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/vm/Runtime.cpp 2015-01-09 12:37:00.000000000 +0000 @@ -130,8 +130,7 @@ } JSRuntime::JSRuntime(JSRuntime *parentRuntime) - : JS::shadow::Runtime(&gc.storeBuffer), - mainThread(this), + : mainThread(this), parentRuntime(parentRuntime), interrupt_(false), interruptPar_(false), @@ -230,6 +229,8 @@ oomCallback(nullptr), debuggerMallocSizeOf(ReturnZeroSize) { + setGCStoreBufferPtr(&gc.storeBuffer); + liveRuntimesCount++; /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */ diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/vm/String.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/vm/String.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/vm/String.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/vm/String.cpp 2015-01-09 12:37:00.000000000 +0000 @@ -485,7 +485,11 @@ ? JSFatInlineString::latin1LengthFits(wholeLength) : JSFatInlineString::twoByteLengthFits(wholeLength); if (canUseFatInline && cx->isJSContext()) { - JSFatInlineString *str = NewGCFatInlineString(cx); + Latin1Char *latin1Buf; + char16_t *twoByteBuf; + JSInlineString *str = isLatin1 + ? AllocateFatInlineString(cx, wholeLength, &latin1Buf) + : AllocateFatInlineString(cx, wholeLength, &twoByteBuf); if (!str) return nullptr; @@ -496,21 +500,19 @@ return nullptr; if (isLatin1) { - Latin1Char *buf = str->initLatin1(wholeLength); - PodCopy(buf, leftInspector.latin1Chars(), leftLen); - PodCopy(buf + leftLen, rightInspector.latin1Chars(), rightLen); - buf[wholeLength] = 0; + PodCopy(latin1Buf, leftInspector.latin1Chars(), leftLen); + PodCopy(latin1Buf + leftLen, rightInspector.latin1Chars(), rightLen); + latin1Buf[wholeLength] = 0; } else { - char16_t *buf = str->initTwoByte(wholeLength); if (leftInspector.hasTwoByteChars()) - PodCopy(buf, leftInspector.twoByteChars(), leftLen); + PodCopy(twoByteBuf, leftInspector.twoByteChars(), leftLen); else - CopyAndInflateChars(buf, leftInspector.latin1Chars(), leftLen); + CopyAndInflateChars(twoByteBuf, leftInspector.latin1Chars(), leftLen); if (rightInspector.hasTwoByteChars()) - PodCopy(buf + leftLen, rightInspector.twoByteChars(), rightLen); + PodCopy(twoByteBuf + leftLen, rightInspector.twoByteChars(), rightLen); else - CopyAndInflateChars(buf + leftLen, rightInspector.latin1Chars(), rightLen); - buf[wholeLength] = 0; + CopyAndInflateChars(twoByteBuf + leftLen, rightInspector.latin1Chars(), rightLen); + twoByteBuf[wholeLength] = 0; } return str; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/vm/TraceLogging.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/vm/TraceLogging.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/vm/TraceLogging.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/vm/TraceLogging.cpp 2015-01-09 12:37:00.000000000 +0000 @@ -887,32 +887,44 @@ TraceLoggerEvent::TraceLoggerEvent(TraceLoggerThread *logger, TraceLoggerTextId textId) { - payload_ = logger->getOrCreateEventPayload(textId); - if (payload_) - payload_->use(); + payload_ = nullptr; + if (logger) { + payload_ = logger->getOrCreateEventPayload(textId); + if (payload_) + payload_->use(); + } } TraceLoggerEvent::TraceLoggerEvent(TraceLoggerThread *logger, TraceLoggerTextId type, JSScript *script) { - payload_ = logger->getOrCreateEventPayload(type, script); - if (payload_) - payload_->use(); + payload_ = nullptr; + if (logger) { + payload_ = logger->getOrCreateEventPayload(type, script); + if (payload_) + payload_->use(); + } } TraceLoggerEvent::TraceLoggerEvent(TraceLoggerThread *logger, TraceLoggerTextId type, const JS::ReadOnlyCompileOptions &compileOptions) { - payload_ = logger->getOrCreateEventPayload(type, compileOptions); - if (payload_) - payload_->use(); + payload_ = nullptr; + if (logger) { + payload_ = logger->getOrCreateEventPayload(type, compileOptions); + if (payload_) + payload_->use(); + } } TraceLoggerEvent::TraceLoggerEvent(TraceLoggerThread *logger, const char *text) { - payload_ = logger->getOrCreateEventPayload(text); - if (payload_) - payload_->use(); + payload_ = nullptr; + if (logger) { + payload_ = logger->getOrCreateEventPayload(text); + if (payload_) + payload_->use(); + } } TraceLoggerEvent::~TraceLoggerEvent() diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/vm/TypedArrayObject.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/vm/TypedArrayObject.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/src/vm/TypedArrayObject.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/src/vm/TypedArrayObject.cpp 2015-01-09 12:37:00.000000000 +0000 @@ -790,6 +790,8 @@ JS_SELF_HOSTED_FN("indexOf", "TypedArrayIndexOf", 2, 0), JS_SELF_HOSTED_FN("join", "TypedArrayJoin", 1, 0), JS_SELF_HOSTED_FN("lastIndexOf", "TypedArrayLastIndexOf", 2, 0), + JS_SELF_HOSTED_FN("reduce", "TypedArrayReduce", 1, 0), + JS_SELF_HOSTED_FN("reduceRight", "TypedArrayReduceRight", 1, 0), JS_SELF_HOSTED_FN("reverse", "TypedArrayReverse", 0, 0), JS_SELF_HOSTED_FN("some", "TypedArraySome", 2, 0), #ifdef NIGHTLY_BUILD diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/xpconnect/src/Sandbox.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/xpconnect/src/Sandbox.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/xpconnect/src/Sandbox.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/xpconnect/src/Sandbox.cpp 2015-01-09 12:37:00.000000000 +0000 @@ -206,7 +206,7 @@ nsCOMPtr xhr = new nsXMLHttpRequest(); nsresult rv = xhr->Init(nsContentUtils::SubjectPrincipal(), nullptr, - iglobal, nullptr); + iglobal, nullptr, nullptr); if (NS_FAILED(rv)) return false; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/xpconnect/src/XPCComponents.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/xpconnect/src/XPCComponents.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/xpconnect/src/XPCComponents.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/xpconnect/src/XPCComponents.cpp 2015-01-09 12:37:00.000000000 +0000 @@ -2750,7 +2750,7 @@ { JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->Runtime(); PrepareForFullGC(rt); - GCForReason(rt, gcreason::COMPONENT_UTILS); + GCForReason(rt, GC_NORMAL, gcreason::COMPONENT_UTILS); return NS_OK; } @@ -2800,7 +2800,7 @@ { JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->Runtime(); PrepareForFullGC(rt); - ShrinkingGC(rt, gcreason::COMPONENT_UTILS); + GCForReason(rt, GC_SHRINK, gcreason::COMPONENT_UTILS); return NS_OK; } @@ -2823,10 +2823,8 @@ } PrepareForFullGC(rt); - if (mShrinking) - ShrinkingGC(rt, gcreason::COMPONENT_UTILS); - else - GCForReason(rt, gcreason::COMPONENT_UTILS); + JSGCInvocationKind gckind = mShrinking ? GC_SHRINK : GC_NORMAL; + GCForReason(rt, gckind, gcreason::COMPONENT_UTILS); mCallback->Callback(); return NS_OK; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/xpconnect/src/XPCMaps.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/xpconnect/src/XPCMaps.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/xpconnect/src/XPCMaps.cpp 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/xpconnect/src/XPCMaps.cpp 2015-01-09 12:37:00.000000000 +0000 @@ -644,8 +644,7 @@ NS_PRECONDITION(si,"bad param"); XPCNativeScriptableShared key(flags, name); - Entry* entry = (Entry*) - PL_DHashTableOperate(mTable, &key, PL_DHASH_ADD); + Entry* entry = (Entry*) PL_DHashTableAdd(mTable, &key); if (!entry) return false; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/xpconnect/src/XPCMaps.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/xpconnect/src/XPCMaps.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/xpconnect/src/XPCMaps.h 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/xpconnect/src/XPCMaps.h 2015-01-09 12:37:00.000000000 +0000 @@ -111,8 +111,7 @@ inline XPCWrappedNative* Find(nsISupports* Obj) { NS_PRECONDITION(Obj,"bad param"); - Entry* entry = (Entry*) - PL_DHashTableOperate(mTable, Obj, PL_DHASH_LOOKUP); + Entry* entry = (Entry*) PL_DHashTableLookup(mTable, Obj); if (PL_DHASH_ENTRY_IS_FREE(entry)) return nullptr; return entry->value; @@ -123,8 +122,7 @@ NS_PRECONDITION(wrapper,"bad param"); nsISupports* obj = wrapper->GetIdentityObject(); MOZ_ASSERT(!Find(obj), "wrapper already in new scope!"); - Entry* entry = (Entry*) - PL_DHashTableOperate(mTable, obj, PL_DHASH_ADD); + Entry* entry = (Entry*) PL_DHashTableAdd(mTable, obj); if (!entry) return nullptr; if (entry->key) @@ -144,7 +142,7 @@ "nsISupports identity! This will most likely cause serious " "problems!"); #endif - PL_DHashTableOperate(mTable, wrapper->GetIdentityObject(), PL_DHASH_REMOVE); + PL_DHashTableRemove(mTable, wrapper->GetIdentityObject()); } inline uint32_t Count() { return mTable->EntryCount(); } @@ -181,8 +179,7 @@ inline nsXPCWrappedJSClass* Find(REFNSIID iid) { - Entry* entry = (Entry*) - PL_DHashTableOperate(mTable, &iid, PL_DHASH_LOOKUP); + Entry* entry = (Entry*) PL_DHashTableLookup(mTable, &iid); if (PL_DHASH_ENTRY_IS_FREE(entry)) return nullptr; return entry->value; @@ -192,8 +189,7 @@ { NS_PRECONDITION(clazz,"bad param"); const nsIID* iid = &clazz->GetIID(); - Entry* entry = (Entry*) - PL_DHashTableOperate(mTable, iid, PL_DHASH_ADD); + Entry* entry = (Entry*) PL_DHashTableAdd(mTable, iid); if (!entry) return nullptr; if (entry->key) @@ -206,7 +202,7 @@ inline void Remove(nsXPCWrappedJSClass* clazz) { NS_PRECONDITION(clazz,"bad param"); - PL_DHashTableOperate(mTable, &clazz->GetIID(), PL_DHASH_REMOVE); + PL_DHashTableRemove(mTable, &clazz->GetIID()); } inline uint32_t Count() { return mTable->EntryCount(); } @@ -238,8 +234,7 @@ inline XPCNativeInterface* Find(REFNSIID iid) { - Entry* entry = (Entry*) - PL_DHashTableOperate(mTable, &iid, PL_DHASH_LOOKUP); + Entry* entry = (Entry*) PL_DHashTableLookup(mTable, &iid); if (PL_DHASH_ENTRY_IS_FREE(entry)) return nullptr; return entry->value; @@ -249,8 +244,7 @@ { NS_PRECONDITION(iface,"bad param"); const nsIID* iid = iface->GetIID(); - Entry* entry = (Entry*) - PL_DHashTableOperate(mTable, iid, PL_DHASH_ADD); + Entry* entry = (Entry*) PL_DHashTableAdd(mTable, iid); if (!entry) return nullptr; if (entry->key) @@ -263,7 +257,7 @@ inline void Remove(XPCNativeInterface* iface) { NS_PRECONDITION(iface,"bad param"); - PL_DHashTableOperate(mTable, iface->GetIID(), PL_DHASH_REMOVE); + PL_DHashTableRemove(mTable, iface->GetIID()); } inline uint32_t Count() { return mTable->EntryCount(); } @@ -298,8 +292,7 @@ inline XPCNativeSet* Find(nsIClassInfo* info) { - Entry* entry = (Entry*) - PL_DHashTableOperate(mTable, info, PL_DHASH_LOOKUP); + Entry* entry = (Entry*) PL_DHashTableLookup(mTable, info); if (PL_DHASH_ENTRY_IS_FREE(entry)) return nullptr; return entry->value; @@ -308,8 +301,7 @@ inline XPCNativeSet* Add(nsIClassInfo* info, XPCNativeSet* set) { NS_PRECONDITION(info,"bad param"); - Entry* entry = (Entry*) - PL_DHashTableOperate(mTable, info, PL_DHASH_ADD); + Entry* entry = (Entry*) PL_DHashTableAdd(mTable, info); if (!entry) return nullptr; if (entry->key) @@ -322,7 +314,7 @@ inline void Remove(nsIClassInfo* info) { NS_PRECONDITION(info,"bad param"); - PL_DHashTableOperate(mTable, info, PL_DHASH_REMOVE); + PL_DHashTableRemove(mTable, info); } inline uint32_t Count() { return mTable->EntryCount(); } @@ -358,8 +350,7 @@ inline XPCWrappedNativeProto* Find(nsIClassInfo* info) { - Entry* entry = (Entry*) - PL_DHashTableOperate(mTable, info, PL_DHASH_LOOKUP); + Entry* entry = (Entry*) PL_DHashTableLookup(mTable, info); if (PL_DHASH_ENTRY_IS_FREE(entry)) return nullptr; return entry->value; @@ -368,8 +359,7 @@ inline XPCWrappedNativeProto* Add(nsIClassInfo* info, XPCWrappedNativeProto* proto) { NS_PRECONDITION(info,"bad param"); - Entry* entry = (Entry*) - PL_DHashTableOperate(mTable, info, PL_DHASH_ADD); + Entry* entry = (Entry*) PL_DHashTableAdd(mTable, info); if (!entry) return nullptr; if (entry->key) @@ -382,7 +372,7 @@ inline void Remove(nsIClassInfo* info) { NS_PRECONDITION(info,"bad param"); - PL_DHashTableOperate(mTable, info, PL_DHASH_REMOVE); + PL_DHashTableRemove(mTable, info); } inline uint32_t Count() { return mTable->EntryCount(); } @@ -423,8 +413,7 @@ inline XPCNativeSet* Find(XPCNativeSetKey* key) { - Entry* entry = (Entry*) - PL_DHashTableOperate(mTable, key, PL_DHASH_LOOKUP); + Entry* entry = (Entry*) PL_DHashTableLookup(mTable, key); if (PL_DHASH_ENTRY_IS_FREE(entry)) return nullptr; return entry->key_value; @@ -434,8 +423,7 @@ { NS_PRECONDITION(key,"bad param"); NS_PRECONDITION(set,"bad param"); - Entry* entry = (Entry*) - PL_DHashTableOperate(mTable, key, PL_DHASH_ADD); + Entry* entry = (Entry*) PL_DHashTableAdd(mTable, key); if (!entry) return nullptr; if (entry->key_value) @@ -455,7 +443,7 @@ NS_PRECONDITION(set,"bad param"); XPCNativeSetKey key(set, nullptr, 0); - PL_DHashTableOperate(mTable, &key, PL_DHASH_REMOVE); + PL_DHashTableRemove(mTable, &key); } inline uint32_t Count() { return mTable->EntryCount(); } @@ -500,8 +488,7 @@ inline nsIXPCFunctionThisTranslator* Find(REFNSIID iid) { - Entry* entry = (Entry*) - PL_DHashTableOperate(mTable, &iid, PL_DHASH_LOOKUP); + Entry* entry = (Entry*) PL_DHashTableLookup(mTable, &iid); if (PL_DHASH_ENTRY_IS_FREE(entry)) return nullptr; return entry->value; @@ -511,8 +498,7 @@ nsIXPCFunctionThisTranslator* obj) { - Entry* entry = (Entry*) - PL_DHashTableOperate(mTable, &iid, PL_DHASH_ADD); + Entry* entry = (Entry*) PL_DHashTableAdd(mTable, &iid); if (!entry) return nullptr; entry->value = obj; @@ -522,7 +508,7 @@ inline void Remove(REFNSIID iid) { - PL_DHashTableOperate(mTable, &iid, PL_DHASH_REMOVE); + PL_DHashTableRemove(mTable, &iid); } inline uint32_t Count() { return mTable->EntryCount(); } @@ -584,7 +570,7 @@ { NS_PRECONDITION(proto,"bad param"); PLDHashEntryStub* entry = (PLDHashEntryStub*) - PL_DHashTableOperate(mTable, proto, PL_DHASH_ADD); + PL_DHashTableAdd(mTable, proto); if (!entry) return nullptr; if (entry->key) @@ -596,7 +582,7 @@ inline void Remove(XPCWrappedNativeProto* proto) { NS_PRECONDITION(proto,"bad param"); - PL_DHashTableOperate(mTable, proto, PL_DHASH_REMOVE); + PL_DHashTableRemove(mTable, proto); } inline uint32_t Count() { return mTable->EntryCount(); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/xpconnect/tests/chrome/test_xrayToJS.xul thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/xpconnect/tests/chrome/test_xrayToJS.xul --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/js/xpconnect/tests/chrome/test_xrayToJS.xul 2015-01-07 22:15:28.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/js/xpconnect/tests/chrome/test_xrayToJS.xul 2015-01-09 12:37:01.000000000 +0000 @@ -179,7 +179,7 @@ gPrototypeProperties['TypedArray'] = ["length", "buffer", "byteLength", "byteOffset", kIteratorSymbol, "subarray", "set", "copyWithin", "find", "findIndex", "indexOf", "lastIndexOf", "reverse", - "join", "every", "some"]; + "join", "every", "some", "reduce", "reduceRight"]; if (isNightlyBuild) { gPrototypeProperties['TypedArray'].push('includes'); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/base/nsDisplayList.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/base/nsDisplayList.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/base/nsDisplayList.cpp 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/base/nsDisplayList.cpp 2015-01-09 12:37:02.000000000 +0000 @@ -1579,6 +1579,8 @@ // Root is being scaled up by the X/Y resolution. Scale it back down. root->SetPostScale(1.0f/containerParameters.mXScale, 1.0f/containerParameters.mYScale); + root->SetScaleToResolution(presShell->ScaleToResolution(), + containerParameters.mXScale); if (gfxPrefs::LayoutUseContainersForRootFrames()) { bool isRoot = presContext->IsRootContentDocument(); @@ -4153,6 +4155,8 @@ aBuilder, aManager, containerParameters); layer->SetPostScale(1.0f / presShell->GetXResolution(), 1.0f / presShell->GetYResolution()); + layer->AsContainerLayer()->SetScaleToResolution( + presShell->ScaleToResolution(), presShell->GetXResolution()); return layer.forget(); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/base/nsDisplayList.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/base/nsDisplayList.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/base/nsDisplayList.h 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/base/nsDisplayList.h 2015-01-09 12:37:02.000000000 +0000 @@ -100,8 +100,8 @@ // All types are defined in nsDisplayItemTypes.h #define NS_DISPLAY_DECL_NAME(n, e) \ - virtual const char* Name() { return n; } \ - virtual Type GetType() { return e; } + virtual const char* Name() MOZ_OVERRIDE { return n; } \ + virtual Type GetType() MOZ_OVERRIDE { return e; } /** * This manages a display list and is passed as a parameter to @@ -2710,7 +2710,7 @@ { aFrames->AppendElements(mMergedFrames); } - virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) { + virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE { return true; } virtual bool IsInvalid(nsRect& aRect) MOZ_OVERRIDE diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/base/nsFrameManager.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/base/nsFrameManager.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/base/nsFrameManager.cpp 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/base/nsFrameManager.cpp 2015-01-09 12:37:02.000000000 +0000 @@ -158,8 +158,8 @@ if (mPlaceholderMap.ops) { PlaceholderMapEntry *entry = static_cast - (PL_DHashTableOperate(const_cast(&mPlaceholderMap), - aFrame, PL_DHASH_LOOKUP)); + (PL_DHashTableLookup(const_cast(&mPlaceholderMap), + aFrame)); if (PL_DHASH_ENTRY_IS_BUSY(entry)) { return entry->placeholderFrame; } @@ -178,9 +178,8 @@ PL_DHashTableInit(&mPlaceholderMap, &PlaceholderMapOps, nullptr, sizeof(PlaceholderMapEntry)); } - PlaceholderMapEntry *entry = static_cast(PL_DHashTableOperate(&mPlaceholderMap, - aPlaceholderFrame->GetOutOfFlowFrame(), - PL_DHASH_ADD)); + PlaceholderMapEntry *entry = static_cast(PL_DHashTableAdd(&mPlaceholderMap, + aPlaceholderFrame->GetOutOfFlowFrame())); if (!entry) return NS_ERROR_OUT_OF_MEMORY; @@ -198,9 +197,8 @@ "unexpected frame type"); if (mPlaceholderMap.ops) { - PL_DHashTableOperate(&mPlaceholderMap, - aPlaceholderFrame->GetOutOfFlowFrame(), - PL_DHASH_REMOVE); + PL_DHashTableRemove(&mPlaceholderMap, + aPlaceholderFrame->GetOutOfFlowFrame()); } } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/base/nsIDocumentViewerPrint.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/base/nsIDocumentViewerPrint.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/base/nsIDocumentViewerPrint.h 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/base/nsIDocumentViewerPrint.h 2015-01-09 12:37:02.000000000 +0000 @@ -68,18 +68,18 @@ /* Use this macro when declaring classes that implement this interface. */ #define NS_DECL_NSIDOCUMENTVIEWERPRINT \ - virtual void SetIsPrinting(bool aIsPrinting); \ - virtual bool GetIsPrinting(); \ - virtual void SetIsPrintPreview(bool aIsPrintPreview); \ - virtual bool GetIsPrintPreview(); \ - virtual nsresult CreateStyleSet(nsIDocument* aDocument, nsStyleSet** aStyleSet); \ - virtual void IncrementDestroyRefCount(); \ - virtual void ReturnToGalleyPresentation(); \ - virtual void OnDonePrinting(); \ - virtual bool IsInitializedForPrintPreview(); \ - virtual void InitializeForPrintPreview(); \ + virtual void SetIsPrinting(bool aIsPrinting) MOZ_OVERRIDE; \ + virtual bool GetIsPrinting() MOZ_OVERRIDE; \ + virtual void SetIsPrintPreview(bool aIsPrintPreview) MOZ_OVERRIDE; \ + virtual bool GetIsPrintPreview() MOZ_OVERRIDE; \ + virtual nsresult CreateStyleSet(nsIDocument* aDocument, nsStyleSet** aStyleSet) MOZ_OVERRIDE; \ + virtual void IncrementDestroyRefCount() MOZ_OVERRIDE; \ + virtual void ReturnToGalleyPresentation() MOZ_OVERRIDE; \ + virtual void OnDonePrinting() MOZ_OVERRIDE; \ + virtual bool IsInitializedForPrintPreview() MOZ_OVERRIDE; \ + virtual void InitializeForPrintPreview() MOZ_OVERRIDE; \ virtual void SetPrintPreviewPresentation(nsViewManager* aViewManager, \ nsPresContext* aPresContext, \ - nsIPresShell* aPresShell); + nsIPresShell* aPresShell) MOZ_OVERRIDE; #endif /* nsIDocumentViewerPrint_h___ */ diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/base/nsIPresShell.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/base/nsIPresShell.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/base/nsIPresShell.h 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/base/nsIPresShell.h 2015-01-09 12:37:02.000000000 +0000 @@ -139,10 +139,10 @@ nsIContent* mContent; } CapturingContentInfo; -// 79c0f49f-77f1-4cc5-80d1-6552e85ccb0c +// 9d010f90-2d90-471c-b640-038cc350c187 #define NS_IPRESSHELL_IID \ - { 0xa0a4b515, 0x0b91, 0x4f13, \ - { 0xa0, 0x60, 0x4b, 0xfb, 0x35, 0x00, 0xdc, 0x00 } } + { 0x9d010f90, 0x2d90, 0x471c, \ + { 0xb6, 0x40, 0x03, 0x8c, 0xc3, 0x50, 0xc1, 0x87 } } // debug VerifyReflow flags #define VERIFY_REFLOW_ON 0x01 @@ -1403,6 +1403,19 @@ virtual gfxSize GetCumulativeResolution() = 0; /** + * Similar to SetResolution() but also increases the scale of the content + * by the same amount. + */ + virtual nsresult SetResolutionAndScaleTo(float aXResolution, float aYResolution) = 0; + + /** + * Return whether we are scaling to the set resolution. + * This is initially false; it's set to true by a call to + * SetResolutionAndScaleTo(), and set to false by a call to SetResolution(). + */ + virtual bool ScaleToResolution() const = 0; + + /** * Returns whether we are in a DrawWindow() call that used the * DRAWWINDOW_DO_NOT_FLUSH flag. */ diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/base/nsPresShell.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/base/nsPresShell.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/base/nsPresShell.cpp 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/base/nsPresShell.cpp 2015-01-09 12:37:02.000000000 +0000 @@ -5545,7 +5545,7 @@ SetRenderingState(state); } -nsresult PresShell::SetResolution(float aXResolution, float aYResolution) +nsresult PresShell::SetResolutionImpl(float aXResolution, float aYResolution, bool aScaleToResolution) { if (!(aXResolution > 0.0 && aYResolution > 0.0)) { return NS_ERROR_ILLEGAL_VALUE; @@ -5557,9 +5557,16 @@ state.mXResolution = aXResolution; state.mYResolution = aYResolution; SetRenderingState(state); + mScaleToResolution = aScaleToResolution; + return NS_OK; } +bool PresShell::ScaleToResolution() const +{ + return mScaleToResolution; +} + gfxSize PresShell::GetCumulativeResolution() { gfxSize resolution = GetResolution(); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/base/nsPresShell.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/base/nsPresShell.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/base/nsPresShell.h 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/base/nsPresShell.h 2015-01-09 12:37:02.000000000 +0000 @@ -87,7 +87,7 @@ virtual nsresult SetPreferenceStyleRules(bool aForceReflow) MOZ_OVERRIDE; - NS_IMETHOD GetSelection(SelectionType aType, nsISelection** aSelection); + NS_IMETHOD GetSelection(SelectionType aType, nsISelection** aSelection) MOZ_OVERRIDE; virtual mozilla::dom::Selection* GetCurrentSelection(SelectionType aType) MOZ_OVERRIDE; NS_IMETHOD SetDisplaySelection(int16_t aToggle) MOZ_OVERRIDE; @@ -129,7 +129,7 @@ virtual void CancelReflowCallback(nsIReflowCallback* aCallback) MOZ_OVERRIDE; virtual void ClearFrameRefs(nsIFrame* aFrame) MOZ_OVERRIDE; - virtual already_AddRefed CreateReferenceRenderingContext(); + virtual already_AddRefed CreateReferenceRenderingContext() MOZ_OVERRIDE; virtual nsresult GoToAnchor(const nsAString& aAnchorName, bool aScroll, uint32_t aAdditionalScrollFlags = 0) MOZ_OVERRIDE; virtual nsresult ScrollToAnchor() MOZ_OVERRIDE; @@ -169,7 +169,7 @@ virtual already_AddRefed GetEventTargetContent( mozilla::WidgetEvent* aEvent) MOZ_OVERRIDE; - virtual void NotifyCounterStylesAreDirty(); + virtual void NotifyCounterStylesAreDirty() MOZ_OVERRIDE; virtual nsresult ReconstructFrames(void) MOZ_OVERRIDE; virtual void Freeze() MOZ_OVERRIDE; @@ -197,7 +197,13 @@ virtual void SetIgnoreViewportScrolling(bool aIgnore) MOZ_OVERRIDE; - virtual nsresult SetResolution(float aXResolution, float aYResolution) MOZ_OVERRIDE; + virtual nsresult SetResolution(float aXResolution, float aYResolution) MOZ_OVERRIDE { + return SetResolutionImpl(aXResolution, aYResolution, /* aScaleToResolution = */ false); + } + virtual nsresult SetResolutionAndScaleTo(float aXResolution, float aYResolution) MOZ_OVERRIDE { + return SetResolutionImpl(aXResolution, aYResolution, /* aScaleToResolution = */ true); + } + virtual bool ScaleToResolution() const MOZ_OVERRIDE; virtual gfxSize GetCumulativeResolution() MOZ_OVERRIDE; //nsIViewObserver interface @@ -376,7 +382,7 @@ virtual bool AssumeAllImagesVisible() MOZ_OVERRIDE; - virtual void RecordShadowStyleChange(mozilla::dom::ShadowRoot* aShadowRoot); + virtual void RecordShadowStyleChange(mozilla::dom::ShadowRoot* aShadowRoot) MOZ_OVERRIDE; virtual void DispatchAfterKeyboardEvent(nsINode* aTarget, const mozilla::WidgetKeyboardEvent& aEvent, @@ -622,7 +628,7 @@ } public: - NS_INLINE_DECL_REFCOUNTING(nsSynthMouseMoveEvent) + NS_INLINE_DECL_REFCOUNTING(nsSynthMouseMoveEvent, MOZ_OVERRIDE) void Revoke() { if (mPresShell) { @@ -753,6 +759,8 @@ // A list of images that are visible or almost visible. nsTHashtable< nsRefPtrHashKey > mVisibleImages; + nsresult SetResolutionImpl(float aXResolution, float aYResolution, bool aScaleToResolution); + #ifdef DEBUG // The reflow root under which we're currently reflowing. Null when // not in reflow. @@ -855,6 +863,11 @@ bool mHasCSSBackgroundColor : 1; + // Whether content should be scaled by the resolution amount. If this is + // not set, a transform that scales by the inverse of the resolution is + // applied to rendered layers. + bool mScaleToResolution : 1; + static bool sDisableNonTestMouseEvents; }; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/base/nsPresState.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/base/nsPresState.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/base/nsPresState.h 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/base/nsPresState.h 2015-01-09 12:37:02.000000000 +0000 @@ -22,6 +22,7 @@ : mContentData(nullptr) , mScrollState(0, 0) , mResolution(1.0, 1.0) + , mScaleToResolution(false) , mDisabledSet(false) , mDisabled(false) {} @@ -46,6 +47,16 @@ return mResolution; } + void SetScaleToResolution(bool aScaleToResolution) + { + mScaleToResolution = aScaleToResolution; + } + + bool GetScaleToResolution() const + { + return mScaleToResolution; + } + void ClearNonScrollState() { mContentData = nullptr; @@ -83,6 +94,7 @@ nsCOMPtr mContentData; nsPoint mScrollState; gfxSize mResolution; + bool mScaleToResolution; bool mDisabledSet; bool mDisabled; }; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/base/nsRefreshDriver.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/base/nsRefreshDriver.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/base/nsRefreshDriver.h 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/base/nsRefreshDriver.h 2015-01-09 12:37:02.000000000 +0000 @@ -280,9 +280,9 @@ bool IsWaitingForPaint(mozilla::TimeStamp aTime); // nsARefreshObserver - NS_IMETHOD_(MozExternalRefCountType) AddRef(void) { return TransactionIdAllocator::AddRef(); } - NS_IMETHOD_(MozExternalRefCountType) Release(void) { return TransactionIdAllocator::Release(); } - virtual void WillRefresh(mozilla::TimeStamp aTime); + NS_IMETHOD_(MozExternalRefCountType) AddRef(void) MOZ_OVERRIDE { return TransactionIdAllocator::AddRef(); } + NS_IMETHOD_(MozExternalRefCountType) Release(void) MOZ_OVERRIDE { return TransactionIdAllocator::Release(); } + virtual void WillRefresh(mozilla::TimeStamp aTime) MOZ_OVERRIDE; private: typedef nsTObserverArray ObserverArray; typedef nsTHashtable RequestTable; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/base/SelectionCarets.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/base/SelectionCarets.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/base/SelectionCarets.cpp 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/base/SelectionCarets.cpp 2015-01-09 12:37:01.000000000 +0000 @@ -1111,6 +1111,7 @@ void SelectionCarets::NotifyBlur(bool aIsLeavingDocument) { + SELECTIONCARETS_LOG("Send out the blur event"); SetVisibility(false); if (aIsLeavingDocument) { CancelLongTapDetector(); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/base/UnitTransforms.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/base/UnitTransforms.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/base/UnitTransforms.h 2015-01-07 22:15:29.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/base/UnitTransforms.h 2015-01-09 12:37:01.000000000 +0000 @@ -24,6 +24,9 @@ ScreenIsParentLayerForRoot, // For the root composition size we want to view it as layer pixels in any layer ParentLayerToLayerForRootComposition, + // The Layer coordinate space for one layer is the ParentLayer coordinate + // space for its children + MovingDownToChildren, // The transform that is usually used to convert between two coordinate // systems is not available (for example, because the object that stores it // is being destroyed), so fall back to the identity. diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/forms/nsComboboxControlFrame.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/forms/nsComboboxControlFrame.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/forms/nsComboboxControlFrame.cpp 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/forms/nsComboboxControlFrame.cpp 2015-01-09 12:37:03.000000000 +0000 @@ -396,7 +396,7 @@ NS_RELEASE_THIS(); } - NS_IMETHODIMP Run() + NS_IMETHODIMP Run() MOZ_OVERRIDE { if (mFrame.IsAlive()) { static_cast(mFrame.GetFrame())-> @@ -1392,7 +1392,8 @@ //nsIRollupListener //---------------------------------------------------------------------- bool -nsComboboxControlFrame::Rollup(uint32_t aCount, const nsIntPoint* pos, nsIContent** aLastRolledUp) +nsComboboxControlFrame::Rollup(uint32_t aCount, bool aFlush, + const nsIntPoint* pos, nsIContent** aLastRolledUp) { if (!mDroppedDown) { return false; @@ -1411,6 +1412,14 @@ if (weakFrame.IsAlive()) { mListControlFrame->CaptureMouseEvents(false); } + + if (aFlush && weakFrame.IsAlive()) { + // The popup's visibility doesn't update until the minimize animation has + // finished, so call UpdateWidgetGeometry to update it right away. + nsViewManager* viewManager = mDropdownFrame->GetView()->GetViewManager(); + viewManager->UpdateWidgetGeometry(); + } + return consume; } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/forms/nsComboboxControlFrame.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/forms/nsComboboxControlFrame.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/forms/nsComboboxControlFrame.h 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/forms/nsComboboxControlFrame.h 2015-01-09 12:37:03.000000000 +0000 @@ -166,7 +166,8 @@ * Hide the dropdown menu and stop capturing mouse events. * @note This method might destroy |this|. */ - virtual bool Rollup(uint32_t aCount, const nsIntPoint* pos, nsIContent** aLastRolledUp) MOZ_OVERRIDE; + virtual bool Rollup(uint32_t aCount, bool aFlush, + const nsIntPoint* pos, nsIContent** aLastRolledUp) MOZ_OVERRIDE; virtual void NotifyGeometryChange() MOZ_OVERRIDE; /** diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/forms/nsSelectsAreaFrame.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/forms/nsSelectsAreaFrame.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/forms/nsSelectsAreaFrame.cpp 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/forms/nsSelectsAreaFrame.cpp 2015-01-09 12:37:03.000000000 +0000 @@ -36,7 +36,7 @@ nsIFrame* aFrame, nsDisplayList* aList) : nsDisplayWrapList(aBuilder, aFrame, aList) {} virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, - HitTestState* aState, nsTArray *aOutFrames); + HitTestState* aState, nsTArray *aOutFrames) MOZ_OVERRIDE; virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE { return false; } @@ -103,7 +103,7 @@ } #endif - virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) { + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE { *aSnap = false; // override bounds because the list item focus ring may extend outside // the nsSelectsAreaFrame @@ -112,7 +112,7 @@ listFrame->GetOffsetToCrossDoc(ReferenceFrame()); } virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx) { + nsRenderingContext* aCtx) MOZ_OVERRIDE { nsListControlFrame* listFrame = GetEnclosingListFrame(Frame()); // listFrame must be non-null or we wouldn't get called. listFrame->PaintFocus(*aCtx, aBuilder->ToReferenceFrame(listFrame)); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/moz.build thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/moz.build --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/moz.build 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/moz.build 2015-01-09 12:37:04.000000000 +0000 @@ -82,6 +82,7 @@ 'nsPlaceholderFrame.cpp', 'nsRubyBaseContainerFrame.cpp', 'nsRubyBaseFrame.cpp', + 'nsRubyContentFrame.cpp', 'nsRubyFrame.cpp', 'nsRubyTextContainerFrame.cpp', 'nsRubyTextFrame.cpp', diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsBlockReflowContext.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsBlockReflowContext.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsBlockReflowContext.cpp 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsBlockReflowContext.cpp 2015-01-09 12:37:05.000000000 +0000 @@ -354,7 +354,7 @@ aBEndMarginResult.Include(aReflowState.ComputedLogicalMargin(). ConvertTo(parentWM, wm).BEnd(parentWM)); } else { - // The used bottom-margin is set to zero above a break. + // The used block-end-margin is set to zero before a break. aBEndMarginResult.Zero(); } @@ -406,7 +406,7 @@ // See if the frame fit. If it's the first frame or empty then it // always fits. If the block-size is unconstrained then it always fits, // even if there's some sort of integer overflow that makes bCoord + - // mMetrics.BSize() appear to go beyond the available height. + // mMetrics.BSize() appear to go beyond the available block size. if (!empty && !aForceFit && mSpace.BSize(mWritingMode) != NS_UNCONSTRAINEDSIZE) { nscoord bEnd = mBCoord - diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsFrame.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsFrame.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsFrame.h 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsFrame.h 2015-01-09 12:37:06.000000000 +0000 @@ -86,7 +86,7 @@ #define NS_DECL_FRAMEARENA_HELPERS \ void* operator new(size_t, nsIPresShell*) MOZ_MUST_OVERRIDE; \ - virtual nsQueryFrame::FrameIID GetFrameId() MOZ_MUST_OVERRIDE; + virtual nsQueryFrame::FrameIID GetFrameId() MOZ_OVERRIDE MOZ_MUST_OVERRIDE; #define NS_IMPL_FRAMEARENA_HELPERS(class) \ void* class::operator new(size_t sz, nsIPresShell* aShell) \ @@ -138,7 +138,8 @@ // nsQueryFrame NS_DECL_QUERYFRAME - NS_DECL_FRAMEARENA_HELPERS + void* operator new(size_t, nsIPresShell*) MOZ_MUST_OVERRIDE; + virtual nsQueryFrame::FrameIID GetFrameId() MOZ_MUST_OVERRIDE; // nsIFrame virtual void Init(nsIContent* aContent, diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsFrameIdList.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsFrameIdList.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsFrameIdList.h 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsFrameIdList.h 2015-01-09 12:37:06.000000000 +0000 @@ -116,6 +116,7 @@ FRAME_ID(nsRootBoxFrame) FRAME_ID(nsRubyBaseContainerFrame) FRAME_ID(nsRubyBaseFrame) +FRAME_ID(nsRubyContentFrame) FRAME_ID(nsRubyFrame) FRAME_ID(nsRubyTextContainerFrame) FRAME_ID(nsRubyTextFrame) diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsFrameUtil.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsFrameUtil.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsFrameUtil.cpp 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsFrameUtil.cpp 2015-01-09 12:37:06.000000000 +0000 @@ -23,8 +23,8 @@ NS_DECL_ISUPPORTS - NS_IMETHOD CompareRegressionData(FILE* aFile1, FILE* aFile2,int32_t aRegressionOutput=0); - NS_IMETHOD DumpRegressionData(FILE* aInputFile, FILE* aOutputFile); + NS_IMETHOD CompareRegressionData(FILE* aFile1, FILE* aFile2,int32_t aRegressionOutput=0) MOZ_OVERRIDE; + NS_IMETHOD DumpRegressionData(FILE* aInputFile, FILE* aOutputFile) MOZ_OVERRIDE; struct Node; struct Tag; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsGfxScrollFrame.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsGfxScrollFrame.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsGfxScrollFrame.cpp 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsGfxScrollFrame.cpp 2015-01-09 12:37:06.000000000 +0000 @@ -1428,7 +1428,7 @@ { } - NS_INLINE_DECL_REFCOUNTING(AsyncSmoothMSDScroll) + NS_INLINE_DECL_REFCOUNTING(AsyncSmoothMSDScroll, MOZ_OVERRIDE) nsSize GetVelocity() { // In nscoords per second @@ -1620,7 +1620,7 @@ // The next section is observer/callback management // Bodies of WillRefresh and RefreshDriver contain ScrollFrameHelper specific code. public: - NS_INLINE_DECL_REFCOUNTING(AsyncScroll) + NS_INLINE_DECL_REFCOUNTING(AsyncScroll, MOZ_OVERRIDE) /* * Set a refresh observer for smooth scroll iterations (and start observing). @@ -1895,6 +1895,7 @@ , mShouldBuildScrollableLayer(false) , mHasBeenScrolled(false) , mIsResolutionSet(false) + , mScaleToResolution(false) { if (LookAndFeel::GetInt(LookAndFeel::eIntID_UseOverlayScrollbars) != 0) { mScrollbarActivity = new ScrollbarActivity(do_QueryFrame(aOuter)); @@ -3264,6 +3265,16 @@ { mResolution = aResolution; mIsResolutionSet = true; + mScaleToResolution = false; +} + +void +ScrollFrameHelper::SetResolutionAndScaleTo(const gfxSize& aResolution) +{ + MOZ_ASSERT(mIsRoot); // This API should only be called on root scroll frames. + mResolution = aResolution; + mIsResolutionSet = true; + mScaleToResolution = true; } static void @@ -5061,6 +5072,7 @@ } state->SetScrollState(pt); state->SetResolution(mResolution); + state->SetScaleToResolution(mScaleToResolution); return state; } @@ -5072,9 +5084,18 @@ mLastPos = mScrolledFrame ? GetLogicalScrollPosition() : nsPoint(0,0); mResolution = aState->GetResolution(); mIsResolutionSet = true; + mScaleToResolution = aState->GetScaleToResolution(); + + // Scaling-to-resolution should only be used on root scroll frames. + MOZ_ASSERT(mIsRoot || !mScaleToResolution); if (mIsRoot) { - mOuter->PresContext()->PresShell()->SetResolution(mResolution.width, mResolution.height); + nsIPresShell* presShell = mOuter->PresContext()->PresShell(); + if (mScaleToResolution) { + presShell->SetResolutionAndScaleTo(mResolution.width, mResolution.height); + } else { + presShell->SetResolution(mResolution.width, mResolution.height); + } } } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsGfxScrollFrame.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsGfxScrollFrame.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsGfxScrollFrame.h 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsGfxScrollFrame.h 2015-01-09 12:37:06.000000000 +0000 @@ -177,6 +177,7 @@ nsSize GetScrollPositionClampingScrollPortSize() const; gfxSize GetResolution() const; void SetResolution(const gfxSize& aResolution); + void SetResolutionAndScaleTo(const gfxSize& aResolution); protected: nsRect GetScrollRangeForClamping() const; @@ -457,10 +458,14 @@ // True if this frame has been scrolled at least once bool mHasBeenScrolled:1; - // True if the frame's resolution has been set via SetResolution or restored - // via RestoreState. + // True if the frame's resolution has been set via SetResolution or + // SetResolutionAndScaleTo or restored via RestoreState. bool mIsResolutionSet:1; + // True if the frame's resolution has been set via SetResolutionAndScaleTo. + // Only meaningful for root scroll frames. + bool mScaleToResolution:1; + protected: /** * @note This method might destroy the frame, pres shell and other objects. @@ -643,6 +648,9 @@ virtual void SetResolution(const gfxSize& aResolution) MOZ_OVERRIDE { return mHelper.SetResolution(aResolution); } + virtual void SetResolutionAndScaleTo(const gfxSize& aResolution) MOZ_OVERRIDE { + return mHelper.SetResolutionAndScaleTo(aResolution); + } virtual nsSize GetLineScrollAmount() const MOZ_OVERRIDE { return mHelper.GetLineScrollAmount(); } @@ -797,7 +805,7 @@ nscoord aNewPos) MOZ_OVERRIDE { mHelper.ThumbMoved(aScrollbar, aOldPos, aNewPos); } - virtual void VisibilityChanged(bool aVisible) {} + virtual void VisibilityChanged(bool aVisible) MOZ_OVERRIDE {} virtual nsIFrame* GetScrollbarBox(bool aVertical) MOZ_OVERRIDE { return mHelper.GetScrollbarBox(aVertical); } @@ -1004,6 +1012,9 @@ virtual void SetResolution(const gfxSize& aResolution) MOZ_OVERRIDE { return mHelper.SetResolution(aResolution); } + virtual void SetResolutionAndScaleTo(const gfxSize& aResolution) MOZ_OVERRIDE { + return mHelper.SetResolutionAndScaleTo(aResolution); + } virtual nsSize GetLineScrollAmount() const MOZ_OVERRIDE { return mHelper.GetLineScrollAmount(); } @@ -1162,7 +1173,7 @@ nscoord aNewPos) MOZ_OVERRIDE { mHelper.ThumbMoved(aScrollbar, aOldPos, aNewPos); } - virtual void VisibilityChanged(bool aVisible) {} + virtual void VisibilityChanged(bool aVisible) MOZ_OVERRIDE {} virtual nsIFrame* GetScrollbarBox(bool aVertical) MOZ_OVERRIDE { return mHelper.GetScrollbarBox(aVertical); } diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsIScrollableFrame.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsIScrollableFrame.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsIScrollableFrame.h 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsIScrollableFrame.h 2015-01-09 12:37:06.000000000 +0000 @@ -154,6 +154,12 @@ */ virtual void SetResolution(const gfxSize& aResolution) = 0; /** + * Set the element resolution and specify that content should be scaled by + * the amount of the resolution. This is only meaningful for root scroll + * frames. See nsIDOMWindowUtils.setResolutionAndScaleTo(). + */ + virtual void SetResolutionAndScaleTo(const gfxSize& aResolution) = 0; + /** * Return how much we would try to scroll by in each direction if * asked to scroll by one "line" vertically and horizontally. */ diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsLineLayout.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsLineLayout.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsLineLayout.cpp 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsLineLayout.cpp 2015-01-09 12:37:06.000000000 +0000 @@ -24,6 +24,7 @@ #include "nsTextFrame.h" #include "nsStyleStructInlines.h" #include "nsBidiPresUtils.h" +#include "nsRubyFrame.h" #include "RubyUtils.h" #include @@ -1826,6 +1827,29 @@ psd->mBStartLeading = leading / 2; psd->mBEndLeading = leading - psd->mBStartLeading; psd->mLogicalBSize = logicalBSize; + if (spanFrame->GetType() == nsGkAtoms::rubyFrame) { + // We may need to extend leadings here for ruby annotations as + // required by section Line Spacing in the CSS Ruby spec. + // See http://dev.w3.org/csswg/css-ruby/#line-height + auto rubyFrame = static_cast(spanFrame); + nscoord startLeading, endLeading; + rubyFrame->GetBlockLeadings(startLeading, endLeading); + nscoord deltaLeading = startLeading + endLeading - leading; + if (deltaLeading > 0) { + // If the total leading is not wide enough for ruby annotations, + // extend the side which is not enough. If both sides are not + // wide enough, replace the leadings with the requested values. + if (startLeading < psd->mBStartLeading) { + psd->mBEndLeading += deltaLeading; + } else if (endLeading < psd->mBEndLeading) { + psd->mBStartLeading += deltaLeading; + } else { + psd->mBStartLeading = startLeading; + psd->mBEndLeading = endLeading; + } + psd->mLogicalBSize += deltaLeading; + } + } if (zeroEffectiveSpanBox) { // When the span-box is to be ignored, zero out the initial diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsQueryFrame.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsQueryFrame.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsQueryFrame.h 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsQueryFrame.h 2015-01-09 12:37:07.000000000 +0000 @@ -17,7 +17,7 @@ typedef classname Has_NS_DECL_QUERYFRAME_TARGET; #define NS_DECL_QUERYFRAME \ - virtual void* QueryFrame(FrameIID id); + virtual void* QueryFrame(FrameIID id) MOZ_OVERRIDE; #define NS_QUERYFRAME_HEAD(class) \ void* class::QueryFrame(FrameIID id) { switch (id) { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsRubyBaseContainerFrame.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsRubyBaseContainerFrame.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsRubyBaseContainerFrame.cpp 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsRubyBaseContainerFrame.cpp 2015-01-09 12:37:07.000000000 +0000 @@ -14,6 +14,8 @@ #include "nsStyleStructInlines.h" #include "WritingModes.h" #include "RubyUtils.h" +#include "mozilla/Maybe.h" +#include "mozilla/DebugOnly.h" using namespace mozilla; @@ -62,9 +64,10 @@ */ struct MOZ_STACK_CLASS mozilla::RubyColumn { - nsIFrame* mBaseFrame; - nsAutoTArray mTextFrames; - RubyColumn() : mBaseFrame(nullptr) { } + nsRubyBaseFrame* mBaseFrame; + nsAutoTArray mTextFrames; + bool mIsIntraLevelWhitespace; + RubyColumn() : mBaseFrame(nullptr), mIsIntraLevelWhitespace(false) { } }; class MOZ_STACK_CLASS RubyColumnEnumerator @@ -77,40 +80,83 @@ bool AtEnd() const; uint32_t GetLevelCount() const { return mFrames.Length(); } - nsIFrame* GetFrame(uint32_t aIndex) const { return mFrames[aIndex]; } - nsIFrame* GetBaseFrame() const { return GetFrame(0); } - nsIFrame* GetTextFrame(uint32_t aIndex) const { return GetFrame(aIndex + 1); } + nsRubyContentFrame* GetFrameAtLevel(uint32_t aIndex) const; void GetColumn(RubyColumn& aColumn) const; private: - nsAutoTArray mFrames; + // Frames in this array are NOT necessary part of the current column. + // When in doubt, use GetFrameAtLevel to access it. + // See GetFrameAtLevel() and Next() for more info. + nsAutoTArray mFrames; + // Whether we are on a column for intra-level whitespaces + bool mAtIntraLevelWhitespace; }; RubyColumnEnumerator::RubyColumnEnumerator( nsRubyBaseContainerFrame* aBaseContainer, const nsTArray& aTextContainers) + : mAtIntraLevelWhitespace(false) { const uint32_t rtcCount = aTextContainers.Length(); mFrames.SetCapacity(rtcCount + 1); - mFrames.AppendElement(aBaseContainer->GetFirstPrincipalChild()); + + nsIFrame* rbFrame = aBaseContainer->GetFirstPrincipalChild(); + MOZ_ASSERT(!rbFrame || rbFrame->GetType() == nsGkAtoms::rubyBaseFrame); + mFrames.AppendElement(static_cast(rbFrame)); for (uint32_t i = 0; i < rtcCount; i++) { nsRubyTextContainerFrame* container = aTextContainers[i]; // If the container is for span, leave a nullptr here. // Spans do not take part in pairing. nsIFrame* rtFrame = !container->IsSpanContainer() ? - aTextContainers[i]->GetFirstPrincipalChild() : nullptr; - mFrames.AppendElement(rtFrame); + container->GetFirstPrincipalChild() : nullptr; + MOZ_ASSERT(!rtFrame || rtFrame->GetType() == nsGkAtoms::rubyTextFrame); + mFrames.AppendElement(static_cast(rtFrame)); + } + + // We have to init mAtIntraLevelWhitespace to be correct for the + // first column. There are two ways we could end up with intra-level + // whitespace in our first colum: + // 1. The current segment itself is an inter-segment whitespace; + // 2. If our ruby segment is split across multiple lines, and some + // intra-level whitespace happens to fall right after a line-break. + // Each line will get its own nsRubyBaseContainerFrame, and the + // container right after the line-break will end up with its first + // column containing that intra-level whitespace. + for (uint32_t i = 0, iend = mFrames.Length(); i < iend; i++) { + nsRubyContentFrame* frame = mFrames[i]; + if (frame && frame->IsIntraLevelWhitespace()) { + mAtIntraLevelWhitespace = true; + break; + } } } void RubyColumnEnumerator::Next() { + bool advancingToIntraLevelWhitespace = false; for (uint32_t i = 0, iend = mFrames.Length(); i < iend; i++) { - if (mFrames[i]) { - mFrames[i] = mFrames[i]->GetNextSibling(); + nsRubyContentFrame* frame = mFrames[i]; + // If we've got intra-level whitespace frames at some levels in the + // current ruby column, we "faked" an anonymous box for all other + // levels for this column. So when we advance off this column, we + // don't advance any of the frames in those levels, because we're + // just advancing across the "fake" frames. + if (frame && (!mAtIntraLevelWhitespace || + frame->IsIntraLevelWhitespace())) { + nsIFrame* nextSibling = frame->GetNextSibling(); + MOZ_ASSERT(!nextSibling || nextSibling->GetType() == frame->GetType(), + "Frame type should be identical among a level"); + mFrames[i] = frame = static_cast(nextSibling); + if (!advancingToIntraLevelWhitespace && + frame && frame->IsIntraLevelWhitespace()) { + advancingToIntraLevelWhitespace = true; + } } } + MOZ_ASSERT(!advancingToIntraLevelWhitespace || !mAtIntraLevelWhitespace, + "Should never have adjacent intra-level whitespace columns"); + mAtIntraLevelWhitespace = advancingToIntraLevelWhitespace; } bool @@ -124,14 +170,33 @@ return true; } +nsRubyContentFrame* +RubyColumnEnumerator::GetFrameAtLevel(uint32_t aIndex) const +{ + // If the current ruby column is for intra-level whitespaces, we + // return nullptr for any levels that do not have an actual intra- + // level whitespace frame in this column. This nullptr represents + // an anonymous empty intra-level whitespace box. (In this case, + // it's important that we NOT return mFrames[aIndex], because it's + // really part of the next column, not the current one.) + nsRubyContentFrame* frame = mFrames[aIndex]; + return !mAtIntraLevelWhitespace || + (frame && frame->IsIntraLevelWhitespace()) ? frame : nullptr; +} + void RubyColumnEnumerator::GetColumn(RubyColumn& aColumn) const { - aColumn.mBaseFrame = mFrames[0]; + nsRubyContentFrame* rbFrame = GetFrameAtLevel(0); + MOZ_ASSERT(!rbFrame || rbFrame->GetType() == nsGkAtoms::rubyBaseFrame); + aColumn.mBaseFrame = static_cast(rbFrame); aColumn.mTextFrames.ClearAndRetainStorage(); for (uint32_t i = 1, iend = mFrames.Length(); i < iend; i++) { - aColumn.mTextFrames.AppendElement(mFrames[i]); + nsRubyContentFrame* rtFrame = GetFrameAtLevel(i); + MOZ_ASSERT(!rtFrame || rtFrame->GetType() == nsGkAtoms::rubyTextFrame); + aColumn.mTextFrames.AppendElement(static_cast(rtFrame)); } + aColumn.mIsIntraLevelWhitespace = mAtIntraLevelWhitespace; } static nscoord @@ -141,7 +206,7 @@ nscoord max = 0; uint32_t levelCount = aEnumerator.GetLevelCount(); for (uint32_t i = 0; i < levelCount; i++) { - nsIFrame* frame = aEnumerator.GetFrame(i); + nsIFrame* frame = aEnumerator.GetFrameAtLevel(i); if (frame) { max = std::max(max, frame->GetPrefISize(aRenderingContext)); } @@ -520,11 +585,30 @@ aStatus = NS_INLINE_LINE_BREAK_AFTER(aStatus); MOZ_ASSERT(NS_FRAME_IS_COMPLETE(aStatus) || aReflowState.mAllowLineBreak); - if (column.mBaseFrame) { - PushChildren(column.mBaseFrame, column.mBaseFrame->GetPrevSibling()); + // If we are on an intra-level whitespace column, null values in + // column.mBaseFrame and column.mTextFrames don't represent the + // end of the frame-sibling-chain at that level -- instead, they + // represent an anonymous empty intra-level whitespace box. It is + // likely that there are frames in the next column (which can't be + // intra-level whitespace). Those frames should be pushed as well. + Maybe nextColumn; + if (column.mIsIntraLevelWhitespace && !e.AtEnd()) { + e.Next(); + nextColumn.emplace(); + e.GetColumn(nextColumn.ref()); + } + nsIFrame* baseFrame = column.mBaseFrame; + if (!baseFrame & nextColumn.isSome()) { + baseFrame = nextColumn->mBaseFrame; + } + if (baseFrame) { + PushChildren(baseFrame, baseFrame->GetPrevSibling()); } for (uint32_t i = 0; i < rtcCount; i++) { - nsIFrame* textFrame = column.mTextFrames[i]; + nsRubyTextFrame* textFrame = column.mTextFrames[i]; + if (!textFrame && nextColumn.isSome()) { + textFrame = nextColumn->mTextFrames[i]; + } if (textFrame) { aReflowState.mTextContainers[i]->PushChildren( textFrame, textFrame->GetPrevSibling()); @@ -568,9 +652,8 @@ // Reflow text frames for (uint32_t i = 0; i < rtcCount; i++) { - nsIFrame* textFrame = aColumn.mTextFrames[i]; + nsRubyTextFrame* textFrame = aColumn.mTextFrames[i]; if (textFrame) { - MOZ_ASSERT(textFrame->GetType() == nsGkAtoms::rubyTextFrame); nsAutoString annotationText; if (!nsContentUtils::GetNodeTextContent(textFrame->GetContent(), true, annotationText)) { @@ -610,7 +693,6 @@ // Reflow the base frame if (aColumn.mBaseFrame) { - MOZ_ASSERT(aColumn.mBaseFrame->GetType() == nsGkAtoms::rubyBaseFrame); nsReflowStatus reflowStatus; nsHTMLReflowMetrics metrics(baseReflowState); RubyUtils::ClearReservedISize(aColumn.mBaseFrame); @@ -637,7 +719,7 @@ continue; } nsLineLayout* lineLayout = textReflowStates[i]->mLineLayout; - nsIFrame* textFrame = aColumn.mTextFrames[i]; + nsRubyTextFrame* textFrame = aColumn.mTextFrames[i]; nscoord deltaISize = icoord - lineLayout->GetCurrentICoord(); if (deltaISize > 0) { lineLayout->AdvanceICoord(deltaISize); @@ -681,17 +763,55 @@ const TextContainerArray& textContainers = aPullFrameState.mTextContainers; const uint32_t rtcCount = textContainers.Length(); - aColumn.mBaseFrame = PullNextInFlowChild(aPullFrameState.mBase); + nsIFrame* nextBase = GetNextInFlowChild(aPullFrameState.mBase); + MOZ_ASSERT(!nextBase || nextBase->GetType() == nsGkAtoms::rubyBaseFrame); + aColumn.mBaseFrame = static_cast(nextBase); aIsComplete = !aColumn.mBaseFrame; + bool pullingIntraLevelWhitespace = + aColumn.mBaseFrame && aColumn.mBaseFrame->IsIntraLevelWhitespace(); aColumn.mTextFrames.ClearAndRetainStorage(); for (uint32_t i = 0; i < rtcCount; i++) { nsIFrame* nextText = - textContainers[i]->PullNextInFlowChild(aPullFrameState.mTexts[i]); - aColumn.mTextFrames.AppendElement(nextText); + textContainers[i]->GetNextInFlowChild(aPullFrameState.mTexts[i]); + MOZ_ASSERT(!nextText || nextText->GetType() == nsGkAtoms::rubyTextFrame); + nsRubyTextFrame* textFrame = static_cast(nextText); + aColumn.mTextFrames.AppendElement(textFrame); // If there exists any frame in continations, we haven't // completed the reflow process. aIsComplete = aIsComplete && !nextText; + if (nextText && !pullingIntraLevelWhitespace) { + pullingIntraLevelWhitespace = textFrame->IsIntraLevelWhitespace(); + } + } + + aColumn.mIsIntraLevelWhitespace = pullingIntraLevelWhitespace; + if (pullingIntraLevelWhitespace) { + // We are pulling an intra-level whitespace. Drop all frames which + // are not part of this intra-level whitespace column. (Those frames + // are really part of the *next* column, after the pulled one.) + if (aColumn.mBaseFrame && !aColumn.mBaseFrame->IsIntraLevelWhitespace()) { + aColumn.mBaseFrame = nullptr; + } + for (uint32_t i = 0; i < rtcCount; i++) { + nsRubyTextFrame*& textFrame = aColumn.mTextFrames[i]; + if (textFrame && !textFrame->IsIntraLevelWhitespace()) { + textFrame = nullptr; + } + } + } + + // Pull the frames of this column. + if (aColumn.mBaseFrame) { + DebugOnly pulled = PullNextInFlowChild(aPullFrameState.mBase); + MOZ_ASSERT(pulled == aColumn.mBaseFrame, "pulled a wrong frame?"); + } + for (uint32_t i = 0; i < rtcCount; i++) { + if (aColumn.mTextFrames[i]) { + DebugOnly pulled = + textContainers[i]->PullNextInFlowChild(aPullFrameState.mTexts[i]); + MOZ_ASSERT(pulled == aColumn.mTextFrames[i], "pulled a wrong frame?"); + } } if (!aIsComplete) { diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsRubyBaseFrame.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsRubyBaseFrame.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsRubyBaseFrame.cpp 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsRubyBaseFrame.cpp 2015-01-09 12:37:07.000000000 +0000 @@ -21,7 +21,7 @@ NS_QUERYFRAME_HEAD(nsRubyBaseFrame) NS_QUERYFRAME_ENTRY(nsRubyBaseFrame) -NS_QUERYFRAME_TAIL_INHERITING(nsInlineFrame) +NS_QUERYFRAME_TAIL_INHERITING(nsRubyBaseFrameSuper) NS_IMPL_FRAMEARENA_HELPERS(nsRubyBaseFrame) @@ -51,12 +51,3 @@ return MakeFrameName(NS_LITERAL_STRING("RubyBase"), aResult); } #endif - -/* virtual */ bool -nsRubyBaseFrame::IsFrameOfType(uint32_t aFlags) const -{ - if (aFlags & eBidiInlineContainer) { - return false; - } - return nsRubyBaseFrameSuper::IsFrameOfType(aFlags); -} diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsRubyBaseFrame.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsRubyBaseFrame.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsRubyBaseFrame.h 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsRubyBaseFrame.h 2015-01-09 12:37:07.000000000 +0000 @@ -9,9 +9,9 @@ #ifndef nsRubyBaseFrame_h___ #define nsRubyBaseFrame_h___ -#include "nsInlineFrame.h" +#include "nsRubyContentFrame.h" -typedef nsInlineFrame nsRubyBaseFrameSuper; +typedef nsRubyContentFrame nsRubyBaseFrameSuper; /** * Factory function. @@ -29,7 +29,6 @@ // nsIFrame overrides virtual nsIAtom* GetType() const MOZ_OVERRIDE; - virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE; #ifdef DEBUG_FRAME_DUMP virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsRubyContentFrame.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsRubyContentFrame.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsRubyContentFrame.cpp 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsRubyContentFrame.cpp 2015-01-09 12:37:07.000000000 +0000 @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code is subject to the terms of the Mozilla Public License + * version 2.0 (the "License"). You can obtain a copy of the License at + * http://mozilla.org/MPL/2.0/. */ + +/* base class for ruby rendering objects that directly contain content */ + +#include "nsRubyContentFrame.h" +#include "nsPresContext.h" +#include "nsStyleContext.h" +#include "nsCSSAnonBoxes.h" + +using namespace mozilla; + +//---------------------------------------------------------------------- + +// Frame class boilerplate +// ======================= + +NS_IMPL_FRAMEARENA_HELPERS(nsRubyContentFrame) + +//---------------------------------------------------------------------- + +// nsRubyContentFrame Method Implementations +// ====================================== + +/* virtual */ bool +nsRubyContentFrame::IsFrameOfType(uint32_t aFlags) const +{ + if (aFlags & eBidiInlineContainer) { + return false; + } + return nsRubyContentFrameSuper::IsFrameOfType(aFlags); +} + +bool +nsRubyContentFrame::IsIntraLevelWhitespace() const +{ + nsIAtom* pseudoType = StyleContext()->GetPseudo(); + if (pseudoType != nsCSSAnonBoxes::rubyBase && + pseudoType != nsCSSAnonBoxes::rubyText) { + return false; + } + + nsIFrame* child = mFrames.OnlyChild(); + return child && child->GetContent()->TextIsOnlyWhitespace(); +} diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsRubyContentFrame.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsRubyContentFrame.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsRubyContentFrame.h 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsRubyContentFrame.h 2015-01-09 12:37:07.000000000 +0000 @@ -0,0 +1,36 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code is subject to the terms of the Mozilla Public License + * version 2.0 (the "License"). You can obtain a copy of the License at + * http://mozilla.org/MPL/2.0/. */ + +/* base class for ruby rendering objects that directly contain content */ + +#ifndef nsRubyContentFrame_h___ +#define nsRubyContentFrame_h___ + +#include "nsInlineFrame.h" + +typedef nsInlineFrame nsRubyContentFrameSuper; + +class nsRubyContentFrame : public nsRubyContentFrameSuper +{ +public: + NS_DECL_FRAMEARENA_HELPERS + + // nsIFrame overrides + virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE; + + // Indicates whether this is an "intra-level whitespace" frame, i.e. + // an anonymous frame that was created to contain non-droppable + // whitespaces directly inside a ruby level container. This impacts + // ruby pairing behavior. + // See http://dev.w3.org/csswg/css-ruby/#anon-gen-interpret-space + bool IsIntraLevelWhitespace() const; + +protected: + explicit nsRubyContentFrame(nsStyleContext* aContext) + : nsRubyContentFrameSuper(aContext) {} +}; + +#endif /* nsRubyContentFrame_h___ */ diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsRubyFrame.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsRubyFrame.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsRubyFrame.cpp 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsRubyFrame.cpp 2015-01-09 12:37:07.000000000 +0000 @@ -167,6 +167,9 @@ // Grab overflow frames from prev-in-flow and its own. MoveOverflowToChildList(); + // Clear leadings + mBStartLeading = mBEndLeading = 0; + // Begin the span for the ruby frame WritingMode frameWM = aReflowState.GetWritingMode(); WritingMode lineWM = aReflowState.mLineLayout->GetWritingMode(); @@ -394,6 +397,14 @@ RubyUtils::SetReservedISize(aBaseContainer, deltaISize); aReflowState.mLineLayout->AdvanceICoord(deltaISize); } + + // Set block leadings of the base container + LogicalMargin leadings(lineWM, offsetRect - baseRect); + NS_ASSERTION(leadings.BStart(lineWM) >= 0 && leadings.BEnd(lineWM) >= 0, + "Leadings should be non-negative (because adding " + "ruby annotation can only increase the size)"); + mBStartLeading = std::max(mBStartLeading, leadings.BStart(lineWM)); + mBEndLeading = std::max(mBEndLeading, leadings.BEnd(lineWM)); } nsRubyBaseContainerFrame* diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsRubyFrame.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsRubyFrame.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsRubyFrame.h 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsRubyFrame.h 2015-01-09 12:37:07.000000000 +0000 @@ -56,6 +56,12 @@ virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; #endif + void GetBlockLeadings(nscoord& aStartLeading, nscoord& aEndLeading) + { + aStartLeading = mBStartLeading; + aEndLeading = mBEndLeading; + } + protected: friend nsContainerFrame* NS_NewRubyFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); @@ -68,7 +74,13 @@ nsRubyBaseContainerFrame* PullOneSegment(ContinuationTraversingState& aState); + // The three members below are not initialized until the first reflow. + nscoord mBaseline; + + // The leadings required to put the annotations. + nscoord mBStartLeading; + nscoord mBEndLeading; }; #endif /* nsRubyFrame_h___ */ diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsRubyTextFrame.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsRubyTextFrame.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsRubyTextFrame.cpp 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsRubyTextFrame.cpp 2015-01-09 12:37:07.000000000 +0000 @@ -21,7 +21,7 @@ NS_QUERYFRAME_HEAD(nsRubyTextFrame) NS_QUERYFRAME_ENTRY(nsRubyTextFrame) -NS_QUERYFRAME_TAIL_INHERITING(nsInlineFrame) +NS_QUERYFRAME_TAIL_INHERITING(nsRubyTextFrameSuper) NS_IMPL_FRAMEARENA_HELPERS(nsRubyTextFrame) @@ -52,14 +52,6 @@ } #endif -/* virtual */ bool -nsRubyTextFrame::IsFrameOfType(uint32_t aFlags) const -{ - if (aFlags & eBidiInlineContainer) { - return false; - } - return nsRubyTextFrameSuper::IsFrameOfType(aFlags); -} /* virtual */ void diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsRubyTextFrame.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsRubyTextFrame.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsRubyTextFrame.h 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsRubyTextFrame.h 2015-01-09 12:37:07.000000000 +0000 @@ -9,9 +9,9 @@ #ifndef nsRubyTextFrame_h___ #define nsRubyTextFrame_h___ -#include "nsInlineFrame.h" +#include "nsRubyContentFrame.h" -typedef nsInlineFrame nsRubyTextFrameSuper; +typedef nsRubyContentFrame nsRubyTextFrameSuper; /** * Factory function. @@ -29,7 +29,6 @@ // nsIFrame overrides virtual nsIAtom* GetType() const MOZ_OVERRIDE; - virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE; #ifdef DEBUG_FRAME_DUMP virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsTextFrame.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsTextFrame.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/generic/nsTextFrame.h 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/generic/nsTextFrame.h 2015-01-09 12:37:07.000000000 +0000 @@ -15,6 +15,11 @@ #include "nsDisplayList.h" #include "JustificationUtils.h" +// Undo the windows.h damage +#if defined(XP_WIN) && defined(DrawText) +#undef DrawText +#endif + class nsTextPaintStyle; class PropertyProvider; struct SelectionDetails; diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/ipc/RenderFrameParent.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/ipc/RenderFrameParent.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/ipc/RenderFrameParent.cpp 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/ipc/RenderFrameParent.cpp 2015-01-09 12:37:07.000000000 +0000 @@ -217,7 +217,7 @@ MessageLoop::current()->PostDelayedTask(FROM_HERE, aTask, aDelayMs); } - virtual bool GetRootZoomConstraints(ZoomConstraints* aOutConstraints) + virtual bool GetRootZoomConstraints(ZoomConstraints* aOutConstraints) MOZ_OVERRIDE { if (mHaveZoomConstraints && aOutConstraints) { *aOutConstraints = mZoomConstraints; @@ -225,7 +225,7 @@ return mHaveZoomConstraints; } - virtual bool GetTouchSensitiveRegion(CSSRect* aOutRegion) + virtual bool GetTouchSensitiveRegion(CSSRect* aOutRegion) MOZ_OVERRIDE { if (mTouchSensitiveRegion.IsEmpty()) return false; @@ -236,7 +236,7 @@ virtual void NotifyAPZStateChange(const ScrollableLayerGuid& aGuid, APZStateChange aChange, - int aArg) + int aArg) MOZ_OVERRIDE { if (MessageLoop::current() != mUILoop) { mUILoop->PostTask( diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/mathml/nsMathMLChar.cpp thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/mathml/nsMathMLChar.cpp --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/mathml/nsMathMLChar.cpp 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/mathml/nsMathMLChar.cpp 2015-01-09 12:37:07.000000000 +0000 @@ -1850,7 +1850,7 @@ #endif virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx); + nsRenderingContext* aCtx) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("MathMLSelectionRect", TYPE_MATHML_SELECTION_RECT) private: nsRect mRect; @@ -1889,7 +1889,7 @@ const nsDisplayItemGeometry* aGeometry, nsRegion *aInvalidRegion) MOZ_OVERRIDE; virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx); + nsRenderingContext* aCtx) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("MathMLCharBackground", TYPE_MATHML_CHAR_BACKGROUND) private: nsStyleContext* mStyleContext; @@ -1932,7 +1932,7 @@ } #endif - virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) { + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE { *aSnap = false; nsRect rect; mChar->GetRect(rect); @@ -1947,7 +1947,7 @@ } virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx) + nsRenderingContext* aCtx) MOZ_OVERRIDE { mChar->PaintForeground(mFrame->PresContext(), *aCtx, ToReferenceFrame(), mIsSelected); @@ -1955,13 +1955,13 @@ NS_DISPLAY_DECL_NAME("MathMLCharForeground", TYPE_MATHML_CHAR_FOREGROUND) - virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) + virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE { bool snap; return GetBounds(aBuilder, &snap); } - virtual uint32_t GetPerFrameKey() { + virtual uint32_t GetPerFrameKey() MOZ_OVERRIDE { return (mIndex << nsDisplayItem::TYPE_BITS) | nsDisplayItem::GetPerFrameKey(); } @@ -1987,7 +1987,7 @@ #endif virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx); + nsRenderingContext* aCtx) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("MathMLCharDebug", TYPE_MATHML_CHAR_DEBUG) private: diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/mathml/nsMathMLSelectedFrame.h thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/mathml/nsMathMLSelectedFrame.h --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/mathml/nsMathMLSelectedFrame.h 2015-01-07 22:15:30.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/mathml/nsMathMLSelectedFrame.h 2015-01-09 12:37:07.000000000 +0000 @@ -40,7 +40,7 @@ const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) MOZ_OVERRIDE; - virtual nsQueryFrame::FrameIID GetFrameId() = 0; + virtual nsQueryFrame::FrameIID GetFrameId() MOZ_OVERRIDE = 0; protected: explicit nsMathMLSelectedFrame(nsStyleContext* aContext) : diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/bugs/1062108-1.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/bugs/1062108-1.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/bugs/1062108-1.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/bugs/1062108-1.html 2015-01-09 12:37:09.000000000 +0000 @@ -0,0 +1,16 @@ + + + + +Bug 1062108 + + + +10 spaces: "          " + + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/bugs/1062108-1-ref.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/bugs/1062108-1-ref.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/bugs/1062108-1-ref.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/bugs/1062108-1-ref.html 2015-01-09 12:37:09.000000000 +0000 @@ -0,0 +1,16 @@ + + + + +Bug 1062108 + + + +10 spaces: "xxxxxxxxxx" + + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/bugs/reftest.list thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/bugs/reftest.list --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/bugs/reftest.list 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/bugs/reftest.list 2015-01-09 12:36:24.000000000 +0000 @@ -1194,7 +1194,7 @@ == 455105-2.html 455105-ref.html == 455171-5.html 455171-5-ref.html == 455280-1.xhtml 455280-1-ref.xhtml -skip-if(B2G) fails-if(Android) == 455826-1.html 455826-1-ref.html +skip-if(B2G) == 455826-1.html 455826-1-ref.html skip-if(B2G) fails-if(cocoaWidget) fails-if(Android) == 456147.xul 456147-ref.html # bug 458047 fuzzy-if(Android,11,40) fuzzy-if(B2G,11,35) fuzzy-if(d2d&&/^Windows\x20NT\x206\.2/.test(http.oscpu),1,69) == 456219-1a.html 456219-1-ref.html # bug 853273 fuzzy-if(Android,11,40) fuzzy-if(B2G,11,35) fuzzy-if(d2d&&/^Windows\x20NT\x206\.2/.test(http.oscpu),1,69) == 456219-1b.html 456219-1-ref.html # bug 853273 @@ -1841,6 +1841,7 @@ == 1059498-1.html 1059498-1-ref.html == 1059498-2.html 1059498-1-ref.html == 1059498-3.html 1059498-1-ref.html +== 1062108-1.html 1062108-1-ref.html fails-if(Android) == 1062792-1.html 1062792-1-ref.html == 1062963-floatmanager-reflow.html 1062963-floatmanager-reflow-ref.html test-pref(dom.webcomponents.enabled,true) == 1066554-1.html 1066554-1-ref.html diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/intra-level-whitespace-1.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/intra-level-whitespace-1.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/intra-level-whitespace-1.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/intra-level-whitespace-1.html 2015-01-09 12:36:26.000000000 +0000 @@ -0,0 +1,22 @@ + + + + + Bug 1099807 - Intra-level whitespace pairing + + + +

+ a b + x y +

+

+ a b + xy +

+

+ ab + x y +

+ + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/intra-level-whitespace-1-ref.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/intra-level-whitespace-1-ref.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/intra-level-whitespace-1-ref.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/intra-level-whitespace-1-ref.html 2015-01-09 12:36:26.000000000 +0000 @@ -0,0 +1,22 @@ + + + + + Bug 1099807 - Intra-level whitespace pairing + + + +

+ a b + x y +

+

+ a b + xy +

+

+ ab + x y +

+ + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/intra-level-whitespace-2.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/intra-level-whitespace-2.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/intra-level-whitespace-2.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/intra-level-whitespace-2.html 2015-01-09 12:36:26.000000000 +0000 @@ -0,0 +1,33 @@ + + + + + Bug 1099807 - Intra-level whitespace pairing + + + + + + 12345 12345 67890 +
12345 678900987654321
+
123456789009876 54321
+
12345 6789009876 54321
+ + + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/intra-level-whitespace-2-ref.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/intra-level-whitespace-2-ref.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/intra-level-whitespace-2-ref.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/intra-level-whitespace-2-ref.html 2015-01-09 12:36:26.000000000 +0000 @@ -0,0 +1,28 @@ + + + + + Bug 1099807 - Intra-level whitespace pairing + + + + + + 12345 12345 67890 +
12345 678900987654321
+
123456789009876 54321
+
12345 6789009876 54321
+ + + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/intra-level-whitespace-3.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/intra-level-whitespace-3.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/intra-level-whitespace-3.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/intra-level-whitespace-3.html 2015-01-09 12:36:26.000000000 +0000 @@ -0,0 +1,34 @@ + + + + + Bug 1099807 - Intra-level whitespace pairing + + + + + + | + base + text + | + + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/intra-level-whitespace-3-ref.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/intra-level-whitespace-3-ref.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/intra-level-whitespace-3-ref.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/intra-level-whitespace-3-ref.html 2015-01-09 12:36:26.000000000 +0000 @@ -0,0 +1,14 @@ + + + + + Bug 1099807 - Intra-level whitespace pairing + + + + | + beforebase + textafter + | + + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/justification-1.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/justification-1.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/justification-1.html 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/justification-1.html 2015-01-09 12:36:26.000000000 +0000 @@ -5,13 +5,13 @@ Bug 1116631 - Justification with ruby span
ab -
+
diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/justification-1-ref.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/justification-1-ref.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/justification-1-ref.html 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/justification-1-ref.html 2015-01-09 12:36:26.000000000 +0000 @@ -5,7 +5,7 @@ Bug 1116631 - Justification with ruby span diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/line-height-1.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/line-height-1.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/line-height-1.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/line-height-1.html 2015-01-09 12:36:26.000000000 +0000 @@ -0,0 +1,14 @@ + + + + + Bug 1069519 - Ruby line height calculation + + + + + base + text + + + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/line-height-1-ref.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/line-height-1-ref.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/line-height-1-ref.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/line-height-1-ref.html 2015-01-09 12:36:26.000000000 +0000 @@ -0,0 +1,17 @@ + + + + + Bug 1069519 - Ruby line height calculation + + + + +
base
+ + + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/line-height-2.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/line-height-2.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/line-height-2.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/line-height-2.html 2015-01-09 12:36:26.000000000 +0000 @@ -0,0 +1,15 @@ + + + + + Bug 1069519 - Ruby line height calculation + + + + + base + text +
+ next line + + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/line-height-2-ref.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/line-height-2-ref.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/line-height-2-ref.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/line-height-2-ref.html 2015-01-09 12:36:26.000000000 +0000 @@ -0,0 +1,18 @@ + + + + + Bug 1069519 - Ruby line height calculation + + + + +
base
+ next line + + + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/line-height-3.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/line-height-3.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/line-height-3.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/line-height-3.html 2015-01-09 12:36:26.000000000 +0000 @@ -0,0 +1,16 @@ + + + + + Bug 1069519 - Ruby line height calculation + + + + + base + text + text +
+ next line + + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/line-height-3-ref.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/line-height-3-ref.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/line-height-3-ref.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/line-height-3-ref.html 2015-01-09 12:36:26.000000000 +0000 @@ -0,0 +1,18 @@ + + + + + Bug 1069519 - Ruby line height calculation + + + + +
base
+ next line + + + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/reftest.list thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/reftest.list --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/reftest.list 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/reftest.list 2015-01-09 12:36:26.000000000 +0000 @@ -20,8 +20,14 @@ == inlinize-blocks-3.html inlinize-blocks-3-ref.html == inlinize-blocks-4.html inlinize-blocks-4-ref.html == inlinize-blocks-5.html inlinize-blocks-5-ref.html +== intra-level-whitespace-1.html intra-level-whitespace-1-ref.html +== intra-level-whitespace-2.html intra-level-whitespace-2-ref.html +== intra-level-whitespace-3.html intra-level-whitespace-3-ref.html == justification-1.html justification-1-ref.html == justification-2.html justification-2-ref.html +== line-height-1.html line-height-1-ref.html +== line-height-2.html line-height-2-ref.html +== line-height-3.html line-height-3-ref.html == ruby-span-1.html ruby-span-1-ref.html == ruby-whitespace-1.html ruby-whitespace-1-ref.html == ruby-whitespace-2.html ruby-whitespace-2-ref.html diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/ruby-reflow-1-noruby.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/ruby-reflow-1-noruby.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/ruby-reflow-1-noruby.html 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/ruby-reflow-1-noruby.html 2015-01-09 12:36:26.000000000 +0000 @@ -6,14 +6,9 @@ + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/ruby-reflow-1-opaqueruby.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/ruby-reflow-1-opaqueruby.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/ruby-reflow-1-opaqueruby.html 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/ruby-reflow-1-opaqueruby.html 2015-01-09 12:36:26.000000000 +0000 @@ -6,14 +6,9 @@ + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/ruby-reflow-1-transparentruby.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/ruby-reflow-1-transparentruby.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/ruby-reflow-1-transparentruby.html 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/ruby-reflow-1-transparentruby.html 2015-01-09 12:36:26.000000000 +0000 @@ -6,14 +6,10 @@ + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/ruby-whitespace-1.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/ruby-whitespace-1.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/ruby-whitespace-1.html 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/ruby-whitespace-1.html 2015-01-09 12:36:26.000000000 +0000 @@ -1,15 +1,9 @@ + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/ruby-whitespace-1-ref.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/ruby-whitespace-1-ref.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/ruby-whitespace-1-ref.html 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/ruby-whitespace-1-ref.html 2015-01-09 12:36:26.000000000 +0000 @@ -1,15 +1,9 @@ + @@ -25,7 +19,7 @@

Base one Base threeText one Text three + >Text one Text three

@@ -35,7 +29,7 @@ > Text three Base one Base threeText oneText two/three + >Text oneText two/three

diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/ruby-whitespace-2.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/ruby-whitespace-2.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/ruby-whitespace-2.html 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/ruby-whitespace-2.html 2015-01-09 12:36:26.000000000 +0000 @@ -2,15 +2,7 @@ - + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/ruby-whitespace-2-ref.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/ruby-whitespace-2-ref.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/ruby-whitespace-2-ref.html 2015-01-07 22:15:18.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/ruby-whitespace-2-ref.html 2015-01-09 12:36:26.000000000 +0000 @@ -2,25 +2,17 @@ - + -abcd BASETEXT +abcd BASETEXT -abcdBASETEXT +abcdBASETEXT -abcd BASETEXT +abcd BASETEXT diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/utils.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/utils.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/css-ruby/utils.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/css-ruby/utils.js 2015-01-09 12:36:26.000000000 +0000 @@ -0,0 +1,5 @@ +function makeHeightMatchInlineBox(block, inline) { + var height = inline.getBoundingClientRect().height + 'px'; + block.style.height = height; + block.style.lineHeight = height; +} diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/svg/svg-integration/reftest.list thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/svg/svg-integration/reftest.list --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/svg/svg-integration/reftest.list 2015-01-07 22:15:21.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/svg/svg-integration/reftest.list 2015-01-09 12:36:35.000000000 +0000 @@ -27,7 +27,7 @@ == mask-html-01.xhtml mask-html-01-ref.svg == mask-html-01-extref-01.xhtml mask-html-01-ref.svg random == mask-html-01-extref-02.xhtml mask-html-01-ref.svg # random due to bug 877661 -fuzzy-if(B2G&&browserIsRemote,1,2000) == mask-html-zoomed-01.xhtml mask-html-01-ref.svg +fuzzy-if(B2G&&browserIsRemote,1,2300) == mask-html-zoomed-01.xhtml mask-html-01-ref.svg # Skil XBL test case on B2G skip-if(B2G) == mask-html-xbl-bound-01.html mask-html-01-ref.svg == mask-transformed-html-01.xhtml ../pass.svg diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/text/synthetic-bold-metrics-01.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/text/synthetic-bold-metrics-01.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/layout/reftests/text/synthetic-bold-metrics-01.html 2015-01-07 22:15:21.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/layout/reftests/text/synthetic-bold-metrics-01.html 2015-01-09 12:36:37.000000000 +0000 @@ -3,12 +3,12 @@ + +

This document should have text color 'Blue' using the RGB Hexadecimal color value of "0000ff".

+

This test passes if the color of text above matches the image below.

+

+ diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/html/rendering/non-replaced-elements/the-page/body_text_00ffff.xhtml thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/html/rendering/non-replaced-elements/the-page/body_text_00ffff.xhtml --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/html/rendering/non-replaced-elements/the-page/body_text_00ffff.xhtml 2015-01-07 22:15:26.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/html/rendering/non-replaced-elements/the-page/body_text_00ffff.xhtml 2015-01-09 12:36:47.000000000 +0000 @@ -1,13 +1,12 @@ body - TEXT=00ffff + +

This document should have text color 'Blue' using the RGB Hexadecimal color value of "0000ff".

This test passes if the color of text above matches the image below.

-

+

-

-Note - This test checks for User Agent requirement as per HTML5 spec NOT the author requirement. (This text is not inside body, so text color is default - black) -

diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/html/semantics/document-metadata/the-style-element/html_style_in_comment-ref.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/html/semantics/document-metadata/the-style-element/html_style_in_comment-ref.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/html/semantics/document-metadata/the-style-element/html_style_in_comment-ref.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/html/semantics/document-metadata/the-style-element/html_style_in_comment-ref.html 2015-01-09 12:36:47.000000000 +0000 @@ -0,0 +1,18 @@ + + +[style] Reference file + + + +

+ This page tests that Style written inside HTML comment is not applied +

+ This test passes if the text below is Green. NOT Red. +

+ This is some text. +

+ diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/html/semantics/document-metadata/the-style-element/html_style_in_comment.xhtml thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/html/semantics/document-metadata/the-style-element/html_style_in_comment.xhtml --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/html/semantics/document-metadata/the-style-element/html_style_in_comment.xhtml 2015-01-07 22:15:26.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/html/semantics/document-metadata/the-style-element/html_style_in_comment.xhtml 2015-01-09 12:36:47.000000000 +0000 @@ -1,5 +1,6 @@ + + + +

Click on the boxes below (using a pointing device).

+
+

quirks: + +

almost: + +

standards: + + + + + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/quirks-mode/blocks-ignore-line-height.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/quirks-mode/blocks-ignore-line-height.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/quirks-mode/blocks-ignore-line-height.html 2015-01-07 22:15:27.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/quirks-mode/blocks-ignore-line-height.html 2015-01-09 12:36:49.000000000 +0000 @@ -13,22 +13,22 @@ + + + +

Callbacks From Tests Running In An IFRAME

+

A test is run inside an iframe with a same origin document. The +containing document should receive callbacks as the tests progress inside the +iframe. A single passing test is expected in the summary below. +

+ + + +
+
+ diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/resources/apisample12.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/resources/apisample12.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/resources/apisample12.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/resources/apisample12.html 2015-01-09 12:36:50.000000000 +0000 @@ -0,0 +1,67 @@ + + + +Example with iframe that notifies containing document via cross document messaging + + + + +

Notifications From Tests Running In An IFRAME

+

A test is run inside an iframe with a same origin document. The +containing document should receive messages via postMessage/ +onmessage as the tests progress inside the iframe. A single +passing test is expected in the summary below. +

+
+ + + + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/resources/apisample13.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/resources/apisample13.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/resources/apisample13.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/resources/apisample13.html 2015-01-09 12:36:50.000000000 +0000 @@ -0,0 +1,132 @@ + + + +Promise Tests + + +

Promise Tests

+

This test demonstrates the use of promise_test. Assumes ECMAScript 6 +Promise support. Some failures are expected.

+
+ + + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/resources/apisample14.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/resources/apisample14.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/resources/apisample14.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/resources/apisample14.html 2015-01-09 12:36:50.000000000 +0000 @@ -0,0 +1,29 @@ + + + +Dedicated Worker Tests + + + + +

Dedicated Web Worker Tests

+

Demonstrates running testharness based tests inside a dedicated web worker. +

The test harness is expected to fail due to an uncaught exception in one worker.

+
+ + + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/resources/apisample15.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/resources/apisample15.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/resources/apisample15.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/resources/apisample15.html 2015-01-09 12:36:50.000000000 +0000 @@ -0,0 +1,26 @@ + + + +Example with a shared worker + + + + +

Shared Web Worker Tests

+

Demonstrates running testharness based tests inside a shared worker. +

The test harness should time out due to one of the tests in the worker timing out. +

This test assumes that the browser supports shared web workers. +

+ + + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/resources/apisample16.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/resources/apisample16.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/resources/apisample16.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/resources/apisample16.html 2015-01-09 12:36:50.000000000 +0000 @@ -0,0 +1,62 @@ + + + +Example with a service worker + + + + +

Service Worker Tests

+

Demonstrates running testharness based tests inside a service worker. +

The test harness should time out due to one of the tests inside the worker timing out. +

This test assumes that the browser supports ServiceWorkers. +

+ + + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/resources/apisample-error-worker.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/resources/apisample-error-worker.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/resources/apisample-error-worker.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/resources/apisample-error-worker.js 2015-01-09 12:36:50.000000000 +0000 @@ -0,0 +1,3 @@ +importScripts("testharness.js"); + +throw new Error("This failure is expected."); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/resources/apisample-worker.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/resources/apisample-worker.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/resources/apisample-worker.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/resources/apisample-worker.js 2015-01-09 12:36:50.000000000 +0000 @@ -0,0 +1,34 @@ +importScripts("testharness.js"); + +test( + function(test) { + assert_true(true, "True is true"); + }, + "Worker test that completes successfully"); + +test( + function(test) { + assert_true(false, "Failing test"); + }, + "Worker test that fails ('FAIL')"); + +async_test( + function(test) { + assert_true(true, "True is true"); + }, + "Worker test that times out ('TIMEOUT')"); + +async_test("Worker test that doesn't run ('NOT RUN')"); + +async_test( + function(test) { + self.setTimeout( + function() { + test.done(); + }, + 0); + }, + "Worker async_test that completes successfully"); + +// An explicit done() is required for dedicated and shared web workers. +done(); diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/resources/docs/api.md thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/resources/docs/api.md --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/resources/docs/api.md 2015-01-07 22:15:27.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/resources/docs/api.md 2015-01-09 12:36:50.000000000 +0000 @@ -7,25 +7,31 @@ ## Basic Usage ## -To use this file, import the script and the testharnessreport script into -the test document: +The test harness script can be used from HTML or SVG documents and web worker +scripts. + +From an HTML or SVG document, start by importing both `testharness.js` and +`testharnessreport.js` scripts into the document: -Within each file one may define one or more tests. Each test is atomic -in the sense that a single test has a single result (`PASS`/`FAIL`/`TIMEOUT`). -Within each test one may have a number of asserts. The test fails at the -first failing assert, and the remainder of the test is (typically) not run. +Refer to the [Web Workers](#web-workers) section for details and an example on +testing within a web worker. + +Within each file one may define one or more tests. Each test is atomic in the +sense that a single test has a single result (`PASS`/`FAIL`/`TIMEOUT`/`NOTRUN`). +Within each test one may have a number of asserts. The test fails at the first +failing assert, and the remainder of the test is (typically) not run. If the file containing the tests is a HTML file, a table containing the test results will be added to the document after all tests have run. By default this -will be added to a div element with id=log if it exists, or a new div element -appended to document.body if it does not. +will be added to a `div` element with `id=log` if it exists, or a new `div` +element appended to `document.body` if it does not. NOTE: By default tests must be created before the load event fires. For ways to create tests after the load event, see "Determining when all tests -are complete", below +are complete", below. ## Synchronous Tests ## @@ -38,7 +44,7 @@ test(function() {assert_true(true)}, "assert_true with true") -The function passed in is run in the test() call. +The function passed in is run in the `test()` call. `properties` is a javascript object for passing extra options to the test. Currently it is only used to provide test-specific @@ -93,6 +99,53 @@ object.some_event = t.unreached_func("some_event should not fire"); +## Promise Tests ## + +`promise_test` can be used to test APIs that are based on Promises: + + promise_test(test_function, name, properties) + +`test_function` is a function that receives a test as an argument and returns a +promise. The test completes when the returned promise resolves. The test fails +if the returned promise rejects. + +E.g.: + + function foo() { + return Promise.resolve("foo"); + } + + promise_test(function() { + return foo() + .then(function(result) { + assert_equals(result, "foo", "foo should return 'foo'"); + }); + }, "Simple example"); + +In the example above, `foo()` returns a Promise that resolves with the string +"foo". The `test_function` passed into `promise_test` invokes `foo` and attaches +a resolve reaction that verifies the returned value. + +Note that in the promise chain constructed in `test_function` assertions don't +need to wrapped in `step` or `step_func` calls. + +Here's another example where the `test_function` uses the provided `test` +parameter to test a Promise that is expected to reject. Note that it's important +to handle all expected rejections since an unhandled rejection causes the test +to fail. + + function bar() { + return Promise.reject("bar"); + } + + promise_test(function(t) { + return bar() + .then(t.unreached_func("bar() should not accept"), + function(result) { + assert_equals(result, "bar", "bar should return 'bar'"); + }); + }, "Another example"); + ## Single Page Tests ## Sometimes, particularly when dealing with asynchronous behaviour, @@ -186,7 +239,6 @@ any tests have returned results. Properties are global properties of the test harness. Currently recognised properties are: - `explicit_done` - Wait for an explicit call to done() before declaring all tests complete (see below; implicitly true for single page tests) @@ -216,6 +268,13 @@ not assume it is done until the global `done()` function is called. Once `done()` is called, the two conditions above apply like normal. +Dedicated and shared workers don't have an event that corresponds to the `load` +event in a document. Therefore these worker tests always behave as if the +`explicit_done` property is set to true. Service workers depend on the +[install](https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#service-worker-global-scope-install-event) +event which is fired following the completion of [running the +worker](https://html.spec.whatwg.org/multipage/workers.html#run-a-worker). + ## Generating tests ## There are scenarios in which is is desirable to create a large number of @@ -245,17 +304,20 @@ ## Callback API ## -The framework provides callbacks corresponding to 3 events: +The framework provides callbacks corresponding to 4 events: - * `start` - happens when the first Test is created - * `result` - happens when a test result is recieved - * `complete` - happens when all results are recieved + * `start` - triggered when the first Test is created + * `test_state` - triggered when a test state changes + * `result` - triggered when a test result is recieved + * `complete` - triggered when all results are recieved The page defining the tests may add callbacks for these events by calling the following methods: `add_start_callback(callback)` - callback called with no arguments + `add_test_state_callback(callback)` - callback called with a test argument + `add_result_callback(callback)` - callback called with a test argument `add_completion_callback(callback)` - callback called with an array of tests @@ -263,11 +325,11 @@ tests have the following properties: - * `status` - A status code. This can be compared to the `PASS`, `FAIL`, `TIMEOUT` and - `NOTRUN` properties on the test object + * `status` - A status code. This can be compared to the `PASS`, `FAIL`, + `TIMEOUT` and `NOTRUN` properties on the test object * `message` - A message indicating the reason for failure. In the future this - will always be a string + will always be a string The status object gives the overall status of the harness. It has the following properties: @@ -283,6 +345,7 @@ certain functions in each ancestor and opener browsing context: * start - `start_callback` + * test\_state - `test_state_callback` * result - `result_callback` * complete - `completion_callback` @@ -291,20 +354,89 @@ ## External API through cross-document messaging ## -Where supported, the test harness will also send messages using -cross-document messaging to each ancestor and opener browsing context. Since -it uses the wildcard keyword (*), cross-origin communication is enabled and -script on different origins can collect the results. +Where supported, the test harness will also send messages using cross-document +messaging to each ancestor and opener browsing context. Since it uses the +wildcard keyword (\*), cross-origin communication is enabled and script on +different origins can collect the results. This API follows similar conventions as those described above only slightly modified to accommodate message event API. Each message is sent by the harness -is passed a single vanilla object, available as the `data` property of the -event object. These objects are structures as follows: +is passed a single vanilla object, available as the `data` property of the event +object. These objects are structures as follows: * start - `{ type: "start" }` + * test\_state - `{ type: "test_state", test: Test }` * result - `{ type: "result", test: Test }` * complete - `{ type: "complete", tests: [Test, ...], status: TestsStatus }` +## Web Workers ## + +The `testharness.js` script can be used from within [dedicated workers, shared +workers](https://html.spec.whatwg.org/multipage/workers.html) and [service +workers](https://slightlyoff.github.io/ServiceWorker/spec/service_worker/). + +Testing from a worker script is different from testing from an HTML document in +several ways: + +* Workers have no reporting capability since they are runing in the background. + Hence they rely on `testharness.js` running in a companion client HTML document + for reporting. + +* Shared and service workers do not have a unique client document since there + could be more than one document that communicates with these workers. So a + client document needs to explicitly connect to a worker and fetch test results + from it using `fetch_tests_from_worker`. This is true even for a dedicated + worker. Once connected, the individual tests running in the worker (or those + that have already run to completion) will be automatically reflected in the + client document. + +* The client document controls the timeout of the tests. All worker scripts act + as if they were started with the `explicit_timeout` option (see the [Harness + timeout](#harness-timeout) section). + +* Dedicated and shared workers don't have an equivalent of an `onload` event. + Thus the test harness has no way to know when all tests have completed (see + [Determining when all tests are + complete](#determining-when-all-tests-are-complete)). So these worker tests + behave as if they were started with the `explicit_done` option. Service + workers depend on the + [oninstall](https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#service-worker-global-scope-install-event) + event and don't require an explicit `done` call. + +Here's an example that uses a dedicated worker. + +`worker.js`: + + importScripts("/resources/testharness.js"); + + test(function(t) { + assert_true(true, "true is true"); + }, "Simple test"); + + // done() is needed because the testharness is running as if explicit_done + // was specified. + done(); + +`test.html`: + + + Simple test + + +
+ + +The argument to the `fetch_tests_from_worker` function can be a +[`Worker`](https://html.spec.whatwg.org/multipage/workers.html#dedicated-workers-and-the-worker-interface), +a [`SharedWorker`](https://html.spec.whatwg.org/multipage/workers.html#shared-workers-and-the-sharedworker-interface) +or a [`ServiceWorker`](https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-obj). +Once called, the containing document fetches all the tests from the worker and +behaves as if those tests were running in the containing document itself. + ## List of Assertions ## ### `assert_true(actual, description)` diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/resources/idlharness.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/resources/idlharness.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/resources/idlharness.js 2015-01-07 22:15:27.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/resources/idlharness.js 2015-01-09 12:36:50.000000000 +0000 @@ -413,12 +413,14 @@ return; case "unsigned long long": + case "DOMTimeStamp": assert_equals(typeof value, "number"); assert_true(0 <= value, "unsigned long long is negative"); return; case "float": case "double": + case "DOMHighResTimeStamp": case "unrestricted float": case "unrestricted double": // TODO: distinguish these cases diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/resources/testharness.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/resources/testharness.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/resources/testharness.js 2015-01-07 22:15:27.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/resources/testharness.js 2015-01-09 12:36:50.000000000 +0000 @@ -27,47 +27,402 @@ var xhtml_ns = "http://www.w3.org/1999/xhtml"; - // script_prefix is used by Output.prototype.show_results() to figure out - // where to get testharness.css from. It's enclosed in an extra closure to - // not pollute the library's namespace with variables like "src". - var script_prefix = null; - (function () - { - var scripts = document.getElementsByTagName("script"); - for (var i = 0; i < scripts.length; i++) { - var src; - if (scripts[i].src) { - src = scripts[i].src; - } else if (scripts[i].href) { - //SVG case - src = scripts[i].href.baseVal; - } + /* + * TestEnvironment is an abstraction for the environment in which the test + * harness is used. Each implementation of a test environment has to provide + * the following interface: + * + * interface TestEnvironment { + * // Invoked after the global 'tests' object has been created and it's + * // safe to call add_*_callback() to register event handlers. + * void on_tests_ready(); + * + * // Invoked after setup() has been called to notify the test environment + * // of changes to the test harness properties. + * void on_new_harness_properties(object properties); + * + * // Should return a new unique default test name. + * DOMString next_default_test_name(); + * + * // Should return the test harness timeout duration in milliseconds. + * float test_timeout(); + * + * // Should return the global scope object. + * object global_scope(); + * }; + */ - if (src && src.slice(src.length - "testharness.js".length) === "testharness.js") { - script_prefix = src.slice(0, src.length - "testharness.js".length); - break; + /* + * A test environment with a DOM. The global object is 'window'. By default + * test results are displayed in a table. Any parent windows receive + * callbacks or messages via postMessage() when test events occur. See + * apisample11.html and apisample12.html. + */ + function WindowTestEnvironment() { + this.name_counter = 0; + this.window_cache = null; + this.output_handler = null; + this.all_loaded = false; + var this_obj = this; + on_event(window, 'load', function() { + this_obj.all_loaded = true; + }); + } + + WindowTestEnvironment.prototype._dispatch = function(selector, callback_args, message_arg) { + this._forEach_windows( + function(w, is_same_origin) { + if (is_same_origin && selector in w) { + try { + w[selector].apply(undefined, callback_args); + } catch (e) { + if (debug) { + throw e; + } + } + } + if (supports_post_message(w) && w !== self) { + w.postMessage(message_arg, "*"); + } + }); + }; + + WindowTestEnvironment.prototype._forEach_windows = function(callback) { + // Iterate of the the windows [self ... top, opener]. The callback is passed + // two objects, the first one is the windows object itself, the second one + // is a boolean indicating whether or not its on the same origin as the + // current window. + var cache = this.window_cache; + if (!cache) { + cache = [[self, true]]; + var w = self; + var i = 0; + var so; + var origins = location.ancestorOrigins; + while (w != w.parent) { + w = w.parent; + // In WebKit, calls to parent windows' properties that aren't on the same + // origin cause an error message to be displayed in the error console but + // don't throw an exception. This is a deviation from the current HTML5 + // spec. See: https://bugs.webkit.org/show_bug.cgi?id=43504 + // The problem with WebKit's behavior is that it pollutes the error console + // with error messages that can't be caught. + // + // This issue can be mitigated by relying on the (for now) proprietary + // `location.ancestorOrigins` property which returns an ordered list of + // the origins of enclosing windows. See: + // http://trac.webkit.org/changeset/113945. + if (origins) { + so = (location.origin == origins[i]); + } else { + so = is_same_origin(w); + } + cache.push([w, so]); + i++; } + w = window.opener; + if (w) { + // window.opener isn't included in the `location.ancestorOrigins` prop. + // We'll just have to deal with a simple check and an error msg on WebKit + // browsers in this case. + cache.push([w, is_same_origin(w)]); + } + this.window_cache = cache; } - })(); - /* - * API functions - */ + forEach(cache, + function(a) { + callback.apply(null, a); + }); + }; - var name_counter = 0; - function next_default_name() - { + WindowTestEnvironment.prototype.on_tests_ready = function() { + var output = new Output(); + this.output_handler = output; + + var this_obj = this; + add_start_callback(function (properties) { + this_obj.output_handler.init(properties); + this_obj._dispatch("start_callback", [properties], + { type: "start", properties: properties }); + }); + add_test_state_callback(function(test) { + this_obj.output_handler.show_status(); + this_obj._dispatch("test_state_callback", [test], + { type: "test_state", test: test.structured_clone() }); + }); + add_result_callback(function (test) { + this_obj.output_handler.show_status(); + this_obj._dispatch("result_callback", [test], + { type: "result", test: test.structured_clone() }); + }); + add_completion_callback(function (tests, harness_status) { + this_obj.output_handler.show_results(tests, harness_status); + var cloned_tests = map(tests, function(test) { return test.structured_clone(); }); + this_obj._dispatch("completion_callback", [tests, harness_status], + { type: "complete", tests: cloned_tests, + status: harness_status.structured_clone() }); + }); + }; + + WindowTestEnvironment.prototype.next_default_test_name = function() { //Don't use document.title to work around an Opera bug in XHTML documents var title = document.getElementsByTagName("title")[0]; var prefix = (title && title.firstChild && title.firstChild.data) || "Untitled"; - var suffix = name_counter > 0 ? " " + name_counter : ""; - name_counter++; + var suffix = this.name_counter > 0 ? " " + this.name_counter : ""; + this.name_counter++; return prefix + suffix; + }; + + WindowTestEnvironment.prototype.on_new_harness_properties = function(properties) { + this.output_handler.setup(properties); + }; + + WindowTestEnvironment.prototype.add_on_loaded_callback = function(callback) { + on_event(window, 'load', callback); + }; + + WindowTestEnvironment.prototype.test_timeout = function() { + var metas = document.getElementsByTagName("meta"); + for (var i = 0; i < metas.length; i++) { + if (metas[i].name == "timeout") { + if (metas[i].content == "long") { + return settings.harness_timeout.long; + } + break; + } + } + return settings.harness_timeout.normal; + }; + + WindowTestEnvironment.prototype.global_scope = function() { + return window; + }; + + /* + * Base TestEnvironment implementation for a generic web worker. + * + * Workers accumulate test results. One or more clients can connect and + * retrieve results from a worker at any time. + * + * WorkerTestEnvironment supports communicating with a client via a + * MessagePort. The mechanism for determining the appropriate MessagePort + * for communicating with a client depends on the type of worker and is + * implemented by the various specializations of WorkerTestEnvironment + * below. + * + * A client document using testharness can use fetch_tests_from_worker() to + * retrieve results from a worker. See apisample16.html. + */ + function WorkerTestEnvironment() { + this.name_counter = 0; + this.all_loaded = true; + this.message_list = []; + this.message_ports = []; + } + + WorkerTestEnvironment.prototype._dispatch = function(message) { + this.message_list.push(message); + for (var i = 0; i < this.message_ports.length; ++i) + { + this.message_ports[i].postMessage(message); + } + }; + + // The only requirement is that port has a postMessage() method. It doesn't + // have to be an instance of a MessagePort, and often isn't. + WorkerTestEnvironment.prototype._add_message_port = function(port) { + this.message_ports.push(port); + for (var i = 0; i < this.message_list.length; ++i) + { + port.postMessage(this.message_list[i]); + } + }; + + WorkerTestEnvironment.prototype.next_default_test_name = function() { + var suffix = this.name_counter > 0 ? " " + this.name_counter : ""; + this.name_counter++; + return "Untitled" + suffix; + }; + + WorkerTestEnvironment.prototype.on_new_harness_properties = function() {}; + + WorkerTestEnvironment.prototype.on_tests_ready = function() { + var this_obj = this; + add_start_callback( + function(properties) { + this_obj._dispatch({ + type: "start", + properties: properties, + }); + }); + add_test_state_callback( + function(test) { + this_obj._dispatch({ + type: "test_state", + test: test.structured_clone() + }); + }); + add_result_callback( + function(test) { + this_obj._dispatch({ + type: "result", + test: test.structured_clone() + }); + }); + add_completion_callback( + function(tests, harness_status) { + this_obj._dispatch({ + type: "complete", + tests: map(tests, + function(test) { + return test.structured_clone(); + }), + status: harness_status.structured_clone() + }); + }); + }; + + WorkerTestEnvironment.prototype.add_on_loaded_callback = function() {}; + + WorkerTestEnvironment.prototype.test_timeout = function() { + // Tests running in a worker don't have a default timeout. I.e. all + // worker tests behave as if settings.explicit_timeout is true. + return null; + }; + + WorkerTestEnvironment.prototype.global_scope = function() { + return self; + }; + + /* + * Dedicated web workers. + * https://html.spec.whatwg.org/multipage/workers.html#dedicatedworkerglobalscope + * + * This class is used as the test_environment when testharness is running + * inside a dedicated worker. + */ + function DedicatedWorkerTestEnvironment() { + WorkerTestEnvironment.call(this); + // self is an instance of DedicatedWorkerGlobalScope which exposes + // a postMessage() method for communicating via the message channel + // established when the worker is created. + this._add_message_port(self); + } + DedicatedWorkerTestEnvironment.prototype = Object.create(WorkerTestEnvironment.prototype); + + DedicatedWorkerTestEnvironment.prototype.on_tests_ready = function() { + WorkerTestEnvironment.prototype.on_tests_ready.call(this); + // In the absence of an onload notification, we a require dedicated + // workers to explicitly signal when the tests are done. + tests.wait_for_finish = true; + }; + + /* + * Shared web workers. + * https://html.spec.whatwg.org/multipage/workers.html#sharedworkerglobalscope + * + * This class is used as the test_environment when testharness is running + * inside a shared web worker. + */ + function SharedWorkerTestEnvironment() { + WorkerTestEnvironment.call(this); + var this_obj = this; + // Shared workers receive message ports via the 'onconnect' event for + // each connection. + self.addEventListener("connect", + function(message_event) { + this_obj._add_message_port(message_event.source); + }); + } + SharedWorkerTestEnvironment.prototype = Object.create(WorkerTestEnvironment.prototype); + + SharedWorkerTestEnvironment.prototype.on_tests_ready = function() { + WorkerTestEnvironment.prototype.on_tests_ready.call(this); + // In the absence of an onload notification, we a require shared + // workers to explicitly signal when the tests are done. + tests.wait_for_finish = true; + }; + + /* + * Service workers. + * http://www.w3.org/TR/service-workers/ + * + * This class is used as the test_environment when testharness is running + * inside a service worker. + */ + function ServiceWorkerTestEnvironment() { + WorkerTestEnvironment.call(this); + this.all_loaded = false; + this.on_loaded_callback = null; + var this_obj = this; + self.addEventListener("message", + function(event) { + if (event.data.type && event.data.type === "connect") { + this_obj._add_message_port(event.ports[0]); + event.ports[0].start(); + } + }); + + // The oninstall event is received after the service worker script and + // all imported scripts have been fetched and executed. It's the + // equivalent of an onload event for a document. All tests should have + // been added by the time this event is received, thus it's not + // necessary to wait until the onactivate event. + on_event(self, "install", + function(event) { + this_obj.all_loaded = true; + if (this_obj.on_loaded_callback) { + this_obj.on_loaded_callback(); + } + }); + } + ServiceWorkerTestEnvironment.prototype = Object.create(WorkerTestEnvironment.prototype); + + ServiceWorkerTestEnvironment.prototype.add_on_loaded_callback = function(callback) { + if (this.all_loaded) { + callback(); + } else { + this.on_loaded_callback = callback; + } + }; + + function create_test_environment() { + if ('document' in self) { + return new WindowTestEnvironment(); + } + if ('DedicatedWorkerGlobalScope' in self && + self instanceof DedicatedWorkerGlobalScope) { + return new DedicatedWorkerTestEnvironment(); + } + if ('SharedWorkerGlobalScope' in self && + self instanceof SharedWorkerGlobalScope) { + return new SharedWorkerTestEnvironment(); + } + if ('ServiceWorkerGlobalScope' in self && + self instanceof ServiceWorkerGlobalScope) { + return new ServiceWorkerTestEnvironment(); + } + throw new Error("Unsupported test environment"); } + var test_environment = create_test_environment(); + + function is_shared_worker(worker) { + return 'SharedWorker' in self && worker instanceof SharedWorker; + } + + function is_service_worker(worker) { + return 'ServiceWorker' in self && worker instanceof ServiceWorker; + } + + /* + * API functions + */ + function test(func, name, properties) { - var test_name = name ? name : next_default_name(); + var test_name = name ? name : test_environment.next_default_test_name(); properties = properties ? properties : {}; var test_obj = new Test(test_name, properties); test_obj.step(func, test_obj, test_obj); @@ -83,7 +438,7 @@ name = func; func = null; } - var test_name = name ? name : next_default_name(); + var test_name = name ? name : test_environment.next_default_test_name(); properties = properties ? properties : {}; var test_obj = new Test(test_name, properties); if (func) { @@ -92,6 +447,23 @@ return test_obj; } + function promise_test(func, name, properties) { + var test = async_test(name, properties); + Promise.resolve(test.step(func, test, test)) + .then( + function() { + test.done(); + }) + .catch(test.step_func( + function(value) { + if (value instanceof AssertionError) { + throw value; + } + assert(false, "promise_test", null, + "Unhandled rejection with value: ${value}", {value:value}); + })); + } + function setup(func_or_properties, maybe_properties) { var func = null; @@ -105,7 +477,7 @@ properties = func_or_properties; } tests.setup(func, properties); - output.setup(properties); + test_environment.on_new_harness_properties(properties); } function done() { @@ -138,6 +510,7 @@ expose(test, 'test'); expose(async_test, 'async_test'); + expose(promise_test, 'promise_test'); expose(generate_tests, 'generate_tests'); expose(setup, 'setup'); expose(done, 'done'); @@ -401,7 +774,7 @@ for (var i = 0; i < actual.length; i++) { assert(actual.hasOwnProperty(i) === expected.hasOwnProperty(i), "assert_array_equals", description, - "property ${i}, property expected to be $expected but was $actual", + "property ${i}, property expected to be ${expected} but was ${actual}", {i:i, expected:expected.hasOwnProperty(i) ? "present" : "missing", actual:actual.hasOwnProperty(i) ? "present" : "missing"}); assert(same_value(expected[i], actual[i]), @@ -722,20 +1095,15 @@ } this.name = name; - this.phases = { - INITIAL:0, - STARTED:1, - HAS_RESULT:2, - COMPLETE:3 - }; this.phase = this.phases.INITIAL; this.status = this.NOTRUN; this.timeout_id = null; + this.index = null; this.properties = properties; var timeout = properties.timeout ? properties.timeout : settings.test_timeout; - if (timeout != null) { + if (timeout !== null) { this.timeout_length = timeout * tests.timeout_multiplier; } else { this.timeout_length = null; @@ -759,6 +1127,13 @@ Test.prototype = merge({}, Test.statuses); + Test.prototype.phases = { + INITIAL:0, + STARTED:1, + HAS_RESULT:2, + COMPLETE:3 + }; + Test.prototype.structured_clone = function() { if (!this._structured_clone) { @@ -766,10 +1141,12 @@ msg = msg ? String(msg) : msg; this._structured_clone = merge({ name:String(this.name), - status:this.status, - message:msg + properties:merge({}, this.properties), }, Test.statuses); } + this._structured_clone.status = this.status; + this._structured_clone.message = this.message; + this._structured_clone.index = this.index; return this._structured_clone; }; @@ -783,6 +1160,7 @@ this.set_status(this.TIMEOUT, "Test timed out"); tests.started = true; + tests.notify_test_state(this); if (this.timeout_id === null) { this.set_timeout(); @@ -861,7 +1239,7 @@ Test.prototype.force_timeout = function() { this.set_status(this.TIMEOUT); this.phase = this.phases.HAS_RESULT; - } + }; Test.prototype.set_timeout = function() { @@ -898,10 +1276,6 @@ this.set_status(this.PASS, null); } - if (this.status == this.NOTRUN) { - alert(this.phase); - } - this.phase = this.phases.COMPLETE; clearTimeout(this.timeout_id); @@ -917,6 +1291,145 @@ }; /* + * A RemoteTest object mirrors a Test object on a remote worker. The + * associated RemoteWorker updates the RemoteTest object in response to + * received events. In turn, the RemoteTest object replicates these events + * on the local document. This allows listeners (test result reporting + * etc..) to transparently handle local and remote events. + */ + function RemoteTest(clone) { + var this_obj = this; + Object.keys(clone).forEach( + function(key) { + this_obj[key] = clone[key]; + }); + this.index = null; + this.phase = this.phases.INITIAL; + this.update_state_from(clone); + tests.push(this); + } + + RemoteTest.prototype.structured_clone = function() { + var clone = {}; + Object.keys(this).forEach( + function(key) { + if (typeof(this[key]) === "object") { + clone[key] = merge({}, this[key]); + } else { + clone[key] = this[key]; + } + }); + clone.phases = merge({}, this.phases); + return clone; + }; + + RemoteTest.prototype.cleanup = function() {}; + RemoteTest.prototype.phases = Test.prototype.phases; + RemoteTest.prototype.update_state_from = function(clone) { + this.status = clone.status; + this.message = clone.message; + if (this.phase === this.phases.INITIAL) { + this.phase = this.phases.STARTED; + } + }; + RemoteTest.prototype.done = function() { + this.phase = this.phases.COMPLETE; + } + + /* + * A RemoteWorker listens for test events from a worker. These events are + * then used to construct and maintain RemoteTest objects that mirror the + * tests running on the remote worker. + */ + function RemoteWorker(worker) { + this.running = true; + this.tests = new Array(); + + var this_obj = this; + worker.onerror = function(error) { this_obj.worker_error(error); }; + + var message_port; + + if (is_service_worker(worker)) { + // The ServiceWorker's implicit MessagePort is currently not + // reliably accessible from the ServiceWorkerGlobalScope due to + // Blink setting MessageEvent.source to null for messages sent via + // ServiceWorker.postMessage(). Until that's resolved, create an + // explicit MessageChannel and pass one end to the worker. + var message_channel = new MessageChannel(); + message_port = message_channel.port1; + message_port.start(); + worker.postMessage({type: "connect"}, [message_channel.port2]); + } else if (is_shared_worker(worker)) { + message_port = worker.port; + } else { + message_port = worker; + } + + // Keeping a reference to the worker until worker_done() is seen + // prevents the Worker object and its MessageChannel from going away + // before all the messages are dispatched. + this.worker = worker; + + message_port.onmessage = + function(message) { + if (this_obj.running && (message.data.type in this_obj.message_handlers)) { + this_obj.message_handlers[message.data.type].call(this_obj, message.data); + } + }; + } + + RemoteWorker.prototype.worker_error = function(error) { + var message = error.message || String(error); + var filename = (error.filename ? " " + error.filename: ""); + // FIXME: Display worker error states separately from main document + // error state. + this.worker_done({ + status: { + status: tests.status.ERROR, + message: "Error in worker" + filename + ": " + message + } + }); + error.preventDefault(); + }; + + RemoteWorker.prototype.test_state = function(data) { + var remote_test = this.tests[data.test.index]; + if (!remote_test) { + remote_test = new RemoteTest(data.test); + this.tests[data.test.index] = remote_test; + } + remote_test.update_state_from(data.test); + tests.notify_test_state(remote_test); + }; + + RemoteWorker.prototype.test_done = function(data) { + var remote_test = this.tests[data.test.index]; + remote_test.update_state_from(data.test); + remote_test.done(); + tests.result(remote_test); + }; + + RemoteWorker.prototype.worker_done = function(data) { + if (tests.status.status === null && + data.status.status !== data.status.OK) { + tests.status.status = data.status.status; + tests.status.message = data.status.message; + } + this.running = false; + this.worker = null; + if (tests.all_done()) { + tests.complete(); + } + }; + + RemoteWorker.prototype.message_handlers = { + test_state: RemoteWorker.prototype.test_state, + result: RemoteWorker.prototype.test_done, + complete: RemoteWorker.prototype.worker_done + }; + + /* * Harness */ @@ -963,8 +1476,6 @@ this.properties = {}; - //All tests can't be done until the load event fires - this.all_loaded = false; this.wait_for_finish = false; this.processing_callbacks = false; @@ -973,26 +1484,25 @@ this.file_is_test = false; this.timeout_multiplier = 1; - this.timeout_length = this.get_timeout(); + this.timeout_length = test_environment.test_timeout(); this.timeout_id = null; this.start_callbacks = []; + this.test_state_callbacks = []; this.test_done_callbacks = []; this.all_done_callbacks = []; + this.pending_workers = []; + this.status = new TestsStatus(); var this_obj = this; - on_event(window, "load", - function() - { - this_obj.all_loaded = true; - if (this_obj.all_done()) - { - this_obj.complete(); - } - }); + test_environment.add_on_loaded_callback(function() { + if (this_obj.all_done()) { + this_obj.complete(); + } + }); this.set_timeout(); } @@ -1049,19 +1559,6 @@ async_test(); }; - Tests.prototype.get_timeout = function() { - var metas = document.getElementsByTagName("meta"); - for (var i = 0; i < metas.length; i++) { - if (metas[i].name == "timeout") { - if (metas[i].content == "long") { - return settings.harness_timeout.long; - } - break; - } - } - return settings.harness_timeout.normal; - }; - Tests.prototype.set_timeout = function() { var this_obj = this; clearTimeout(this.timeout_id); @@ -1093,12 +1590,23 @@ this.start(); } this.num_pending++; - this.tests.push(test); + test.index = this.tests.push(test); + this.notify_test_state(test); + }; + + Tests.prototype.notify_test_state = function(test) { + var this_obj = this; + forEach(this.test_state_callbacks, + function(callback) { + callback(test, this_obj); + }); }; Tests.prototype.all_done = function() { - return (this.tests.length > 0 && this.all_loaded && this.num_pending === 0 && - !this.wait_for_finish && !this.processing_callbacks); + return (this.tests.length > 0 && test_environment.all_loaded && + this.num_pending === 0 && !this.wait_for_finish && + !this.processing_callbacks && + !this.pending_workers.some(function(w) { return w.running; })); }; Tests.prototype.start = function() { @@ -1113,25 +1621,6 @@ { callback(this_obj.properties); }); - forEach_windows( - function(w, is_same_origin) - { - if (is_same_origin && w.start_callback) { - try { - w.start_callback(this_obj.properties); - } catch (e) { - if (debug) { - throw e; - } - } - } - if (supports_post_message(w) && w !== self) { - w.postMessage({ - type: "start", - properties: this_obj.properties - }, "*"); - } - }); }; Tests.prototype.result = function(test) @@ -1152,26 +1641,6 @@ { callback(test, this_obj); }); - - forEach_windows( - function(w, is_same_origin) - { - if (is_same_origin && w.result_callback) { - try { - w.result_callback(test); - } catch (e) { - if (debug) { - throw e; - } - } - } - if (supports_post_message(w) && w !== self) { - w.postMessage({ - type: "result", - test: test.structured_clone() - }, "*"); - } - }); this.processing_callbacks = false; if (this_obj.all_done()) { this_obj.complete(); @@ -1187,24 +1656,18 @@ this.tests.forEach( function(x) { - if (x.status === x.NOTRUN) { + if (x.phase < x.phases.COMPLETE) { this_obj.notify_result(x); x.cleanup(); + x.phase = x.phases.COMPLETE; } } ); this.notify_complete(); }; - Tests.prototype.notify_complete = function() - { - clearTimeout(this.timeout_id); + Tests.prototype.notify_complete = function() { var this_obj = this; - var tests = map(this_obj.tests, - function(test) - { - return test.structured_clone(); - }); if (this.status.status === null) { this.status.status = this.status.OK; } @@ -1214,47 +1677,20 @@ { callback(this_obj.tests, this_obj.status); }); - - forEach_windows( - function(w, is_same_origin) - { - if (is_same_origin && w.completion_callback) { - try { - w.completion_callback(this_obj.tests, this_obj.status); - } catch (e) { - if (debug) { - throw e; - } - } - } - if (supports_post_message(w) && w !== self) { - w.postMessage({ - type: "complete", - tests: tests, - status: this_obj.status.structured_clone() - }, "*"); - } - }); }; - var tests = new Tests(); - - addEventListener("error", function(e) { - if (tests.file_is_test) { - var test = tests.tests[0]; - if (test.phase >= test.phases.HAS_RESULT) { - return; - } - var message = e.message; - test.set_status(test.FAIL, message); - test.phase = test.phases.HAS_RESULT; - test.done(); - done(); - } else if (!tests.allow_uncaught_exception) { - tests.status.status = tests.status.ERROR; - tests.status.message = e.message; + Tests.prototype.fetch_tests_from_worker = function(worker) { + if (this.phase >= this.phases.COMPLETE) { + return; } - }); + + this.pending_workers.push(new RemoteWorker(worker)); + }; + + function fetch_tests_from_worker(port) { + tests.fetch_tests_from_worker(port); + } + expose(fetch_tests_from_worker, 'fetch_tests_from_worker'); function timeout() { if (tests.timeout_length === null) { @@ -1267,6 +1703,10 @@ tests.start_callbacks.push(callback); } + function add_test_state_callback(callback) { + tests.test_state_callbacks.push(callback); + } + function add_result_callback(callback) { tests.test_done_callbacks.push(callback); @@ -1278,6 +1718,7 @@ } expose(add_start_callback, 'add_start_callback'); + expose(add_test_state_callback, 'add_test_state_callback'); expose(add_result_callback, 'add_result_callback'); expose(add_completion_callback, 'add_completion_callback'); @@ -1288,7 +1729,6 @@ function Output() { this.output_document = document; this.output_node = null; - this.done_count = 0; this.enabled = settings.output; this.phase = this.INITIAL; } @@ -1355,13 +1795,13 @@ this.resolve_log(); this.phase = this.HAVE_RESULTS; } - this.done_count++; + var done_count = tests.tests.length - tests.num_pending; if (this.output_node) { - if (this.done_count < 100 || - (this.done_count < 1000 && this.done_count % 100 === 0) || - this.done_count % 1000 === 0) { + if (done_count < 100 || + (done_count < 1000 && done_count % 100 === 0) || + done_count % 1000 === 0) { this.output_node.textContent = "Running, " + - this.done_count + " complete, " + + done_count + " complete, " + tests.num_pending + " remain"; } } @@ -1389,7 +1829,25 @@ log.removeChild(log.lastChild); } - if (script_prefix != null) { + var script_prefix = null; + var scripts = document.getElementsByTagName("script"); + for (var i = 0; i < scripts.length; i++) { + var src; + if (scripts[i].src) { + src = scripts[i].src; + } else if (scripts[i].href) { + //SVG case + src = scripts[i].href.baseVal; + } + + var matches = src && src.match(/^(.*\/|)testharness\.js$/); + if (matches) { + script_prefix = matches[1]; + break; + } + } + + if (script_prefix !== null) { var stylesheet = output_document.createElementNS(xhtml_ns, "link"); stylesheet.setAttribute("rel", "stylesheet"); stylesheet.setAttribute("href", script_prefix + "testharness.css"); @@ -1553,11 +2011,6 @@ } }; - var output = new Output(); - add_start_callback(function (properties) {output.init(properties);}); - add_result_callback(function () {output.show_status();}); - add_completion_callback(function (tests, harness_status) {output.show_results(tests, harness_status);}); - /* * Template code * @@ -1706,8 +2159,6 @@ return element; } - - function make_dom(template, substitutions, output_document) { if (is_single_node(template)) { @@ -1817,7 +2268,7 @@ function expose(object, name) { var components = name.split("."); - var target = window; + var target = test_environment.global_scope(); for (var i = 0; i < components.length - 1; i++) { if (!(components[i] in target)) { target[components[i]] = {}; @@ -1827,56 +2278,6 @@ target[components[components.length - 1]] = object; } - function forEach_windows(callback) { - // Iterate of the the windows [self ... top, opener]. The callback is passed - // two objects, the first one is the windows object itself, the second one - // is a boolean indicating whether or not its on the same origin as the - // current window. - var cache = forEach_windows.result_cache; - if (!cache) { - cache = [[self, true]]; - var w = self; - var i = 0; - var so; - var origins = location.ancestorOrigins; - while (w != w.parent) { - w = w.parent; - // In WebKit, calls to parent windows' properties that aren't on the same - // origin cause an error message to be displayed in the error console but - // don't throw an exception. This is a deviation from the current HTML5 - // spec. See: https://bugs.webkit.org/show_bug.cgi?id=43504 - // The problem with WebKit's behavior is that it pollutes the error console - // with error messages that can't be caught. - // - // This issue can be mitigated by relying on the (for now) proprietary - // `location.ancestorOrigins` property which returns an ordered list of - // the origins of enclosing windows. See: - // http://trac.webkit.org/changeset/113945. - if (origins) { - so = (location.origin == origins[i]); - } else { - so = is_same_origin(w); - } - cache.push([w, so]); - i++; - } - w = window.opener; - if (w) { - // window.opener isn't included in the `location.ancestorOrigins` prop. - // We'll just have to deal with a simple check and an error msg on WebKit - // browsers in this case. - cache.push([w, is_same_origin(w)]); - } - forEach_windows.result_cache = cache; - } - - forEach(cache, - function(a) - { - callback.apply(null, a); - }); - } - function is_same_origin(w) { try { 'random_prop' in w; @@ -1922,5 +2323,31 @@ } return supports; } + + /** + * Setup globals + */ + + var tests = new Tests(); + + addEventListener("error", function(e) { + if (tests.file_is_test) { + var test = tests.tests[0]; + if (test.phase >= test.phases.HAS_RESULT) { + return; + } + var message = e.message; + test.set_status(test.FAIL, message); + test.phase = test.phases.HAS_RESULT; + test.done(); + done(); + } else if (!tests.allow_uncaught_exception) { + tests.status.status = tests.status.ERROR; + tests.status.message = e.message; + } + }); + + test_environment.on_tests_ready(); + })(); // vim: set expandtab shiftwidth=4 tabstop=4: diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/serve.py thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/serve.py --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/serve.py 2015-01-07 22:15:27.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/serve.py 2015-01-09 12:36:50.000000000 +0000 @@ -13,19 +13,18 @@ from collections import defaultdict from multiprocessing import Process, Event -repo_root = os.path.abspath(os.path.split(__file__)[0]) - -sys.path.insert(1, os.path.join(repo_root, "tools", "wptserve")) +from tools.scripts import _env +repo_root = _env.repo_root from wptserve import server as wptserve, handlers from wptserve.router import any_method from wptserve.logger import set_logger -sys.path.insert(1, os.path.join(repo_root, "tools", "pywebsocket", "src")) from mod_pywebsocket import standalone as pywebsocket routes = [("GET", "/tools/runner/*", handlers.file_handler), ("POST", "/tools/runner/update_manifest.py", handlers.python_script_handler), (any_method, "/tools/*", handlers.ErrorHandler(404)), + (any_method, "{spec}/tools/*", handlers.ErrorHandler(404)), (any_method, "/serve.py", handlers.ErrorHandler(404)), (any_method, "*.py", handlers.python_script_handler), ("GET", "*.asis", handlers.as_is_handler), @@ -69,15 +68,17 @@ self.daemon = None self.stop = Event() - def start(self, init_func, host, port, paths, bind_hostname, external_config): + def start(self, init_func, host, port, paths, bind_hostname, external_config, **kwargs): self.proc = Process(target=self.create_daemon, - args=(init_func, host, port, paths, bind_hostname, external_config)) + args=(init_func, host, port, paths, bind_hostname, + external_config), kwargs=kwargs) self.proc.daemon = True self.proc.start() - def create_daemon(self, init_func, host, port, paths, bind_hostname, external_config): + def create_daemon(self, init_func, host, port, paths, bind_hostname, external_config, + **kwargs): try: - self.daemon = init_func(host, port, paths, bind_hostname, external_config) + self.daemon = init_func(host, port, paths, bind_hostname, external_config, **kwargs) except socket.error: print >> sys.stderr, "Socket error on port %s" % port raise @@ -139,9 +140,8 @@ return {subdomain: (subdomain.encode("idna"), host) for subdomain in subdomains} -def start_servers(host, ports, paths, bind_hostname, external_config): +def start_servers(host, ports, paths, bind_hostname, external_config, **kwargs): servers = defaultdict(list) - for scheme, ports in ports.iteritems(): assert len(ports) == {"http":2}.get(scheme, 1) @@ -152,12 +152,13 @@ "wss":start_wss_server}[scheme] server_proc = ServerProc() - server_proc.start(init_func, host, port, paths, bind_hostname, external_config) + server_proc.start(init_func, host, port, paths, bind_hostname, + external_config, **kwargs) servers[scheme].append((port, server_proc)) return servers -def start_http_server(host, port, paths, bind_hostname, external_config): +def start_http_server(host, port, paths, bind_hostname, external_config, **kwargs): return wptserve.WebTestHttpd(host=host, port=port, doc_root=paths["doc_root"], @@ -166,9 +167,10 @@ bind_hostname=bind_hostname, config=external_config, use_ssl=False, - certificate=None) + certificate=None, + latency=kwargs.get("latency")) -def start_https_server(host, port, paths, bind_hostname): +def start_https_server(host, port, paths, bind_hostname, external_config, **kwargs): return class WebSocketDaemon(object): @@ -216,7 +218,7 @@ self.started = False self.server = None -def start_ws_server(host, port, paths, bind_hostname, external_config): +def start_ws_server(host, port, paths, bind_hostname, external_config, **kwargs): return WebSocketDaemon(host, str(port), repo_root, @@ -224,7 +226,7 @@ "debug", bind_hostname) -def start_wss_server(host, port, path, bind_hostname, external_config): +def start_wss_server(host, port, path, bind_hostname, external_config, **kwargs): return def get_ports(config): @@ -255,7 +257,7 @@ "domains": domains, "ports": ports_} -def start(config): +def start(config, **kwargs): host = config["host"] domains = get_subdomains(host) ports = get_ports(config) @@ -269,7 +271,7 @@ external_config = normalise_config(config, ports) - servers = start_servers(host, ports, paths, bind_hostname, external_config) + servers = start_servers(host, ports, paths, bind_hostname, external_config, **kwargs) return external_config, servers @@ -306,7 +308,7 @@ rv[key] = override_obj[key] return rv -def load_config(default_path, override_path=None): +def load_config(default_path, override_path=None, **kwargs): if os.path.exists(default_path): with open(default_path) as f: base_obj = json.load(f) @@ -320,16 +322,37 @@ override_obj = {} rv = merge_json(base_obj, override_obj) + if kwargs.get("config_path"): + other_path = os.path.abspath(os.path.expanduser(kwargs.get("config_path"))) + if os.path.exists(other_path): + base_obj = rv + with open(other_path) as f: + override_obj = json.load(f) + rv = merge_json(base_obj, override_obj) + else: + raise ValueError("Config path %s does not exist" % other_path) + set_computed_defaults(rv) return rv + +def get_parser(): + parser = argparse.ArgumentParser() + parser.add_argument("--latency", type=int, + help="Artificial latency to add before sending http responses, in ms") + parser.add_argument("--config", action="store", dest="config_path", + help="Path to external config file") + return parser + def main(): + kwargs = vars(get_parser().parse_args()) config = load_config("config.default.json", - "config.json") + "config.json", + **kwargs) setup_logger(config["log_level"]) - config_, servers = start(config) + config_, servers = start(config, **kwargs) try: while any(item.is_alive() for item in iter_procs(servers)): diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-base64-encoded-sha-digests.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-base64-encoded-sha-digests.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-base64-encoded-sha-digests.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-base64-encoded-sha-digests.js 2015-01-09 12:36:51.000000000 +0000 @@ -0,0 +1 @@ +loads_scripts_with_base64_encoded_sha_digests=true; \ No newline at end of file diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-correct-content-type.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-correct-content-type.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-correct-content-type.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-correct-content-type.js 2015-01-09 12:36:51.000000000 +0000 @@ -0,0 +1 @@ +loads_scripts_with_correct_content_type=true; \ No newline at end of file diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-improper-integrity-uri-scheme.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-improper-integrity-uri-scheme.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-improper-integrity-uri-scheme.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-improper-integrity-uri-scheme.js 2015-01-09 12:36:51.000000000 +0000 @@ -0,0 +1 @@ +loads_scripts_with_improper_integrity_uri_scheme=true; \ No newline at end of file diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-incorrect-content-type.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-incorrect-content-type.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-incorrect-content-type.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-incorrect-content-type.js 2015-01-09 12:36:51.000000000 +0000 @@ -0,0 +1 @@ +loads_scripts_with_incorrect_content_type=true; \ No newline at end of file diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-matching-digest.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-matching-digest.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-matching-digest.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-matching-digest.js 2015-01-09 12:36:51.000000000 +0000 @@ -0,0 +1 @@ +loads_scripts_with_matching_digest=true; \ No newline at end of file diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-non-matching-digest.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-non-matching-digest.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-non-matching-digest.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-non-matching-digest.js 2015-01-09 12:36:51.000000000 +0000 @@ -0,0 +1 @@ +loads_scripts_with_non_matching_digest=true; \ No newline at end of file diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-unhyphenated-digest-name.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-unhyphenated-digest-name.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-unhyphenated-digest-name.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-unhyphenated-digest-name.js 2015-01-09 12:36:51.000000000 +0000 @@ -0,0 +1 @@ +loads_scripts_with_unhyphenated_digest_name=true; \ No newline at end of file diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-weak-digest-algorithms.js thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-weak-digest-algorithms.js --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-weak-digest-algorithms.js 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/subresource-integrity/loads-scripts-with-weak-digest-algorithms.js 2015-01-09 12:36:51.000000000 +0000 @@ -0,0 +1 @@ +loads_scripts_with_weak_digest_algorithms=true; \ No newline at end of file diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/subresource-integrity/subresource-integrity.html thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/subresource-integrity/subresource-integrity.html --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/subresource-integrity/subresource-integrity.html 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/subresource-integrity/subresource-integrity.html 2015-01-09 12:36:51.000000000 +0000 @@ -0,0 +1,79 @@ + + +Subresource Integrity + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/subresource-integrity/tools/generate_javascript.py thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/subresource-integrity/tools/generate_javascript.py --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/subresource-integrity/tools/generate_javascript.py 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/subresource-integrity/tools/generate_javascript.py 2015-01-09 12:36:51.000000000 +0000 @@ -0,0 +1,45 @@ +from os import path, listdir +from hashlib import sha256, md5 +from base64 import urlsafe_b64encode +import re + +JS_DIR = path.normpath(path.join(__file__, "..", "..")) + +''' +Yield each file in the javascript directory +''' +def js_files(): + for f in listdir(JS_DIR): + if path.isfile(f) and f.endswith(".js"): + yield f + +''' +URL-safe base64 encode a binary digest and strip any padding. +''' +def format_digest(digest): + return urlsafe_b64encode(digest).rstrip("=") + +''' +Generate an encoded sha256 URI. +''' +def sha256_uri(content): + return "ni:///sha-256;%s" % format_digest(sha256(content).digest()) + +''' +Generate an encoded md5 digest URI. +''' +def md5_uri(content): + return "ni:///md5;%s" % format_digest(md5(content).digest()) + +def main(): + for file in js_files(): + print "Generating content for %s" % file + base = path.splitext(path.basename(file))[0] + var_name = re.sub(r"[^a-z0-9]", "_", base) + content = "%s=true;" % var_name + with open(file, "w") as f: f.write(content) + print "\tSHA256 integrity: %s" % sha256_uri(content) + print "\tMD5 integrity: %s" % md5_uri(content) + +if __name__ == "__main__": + main() diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/tools/html5lib/AUTHORS.rst thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/tools/html5lib/AUTHORS.rst --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/tools/html5lib/AUTHORS.rst 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/tools/html5lib/AUTHORS.rst 2015-01-09 12:36:51.000000000 +0000 @@ -0,0 +1,34 @@ +Credits +======= + +``html5lib`` is written and maintained by: + +- James Graham +- Geoffrey Sneddon +- Åukasz Langa + + +Patches and suggestions +----------------------- +(In chronological order, by first commit:) + +- Anne van Kesteren +- Lachlan Hunt +- lantis63 +- Sam Ruby +- Tim Fletcher +- Thomas Broyer +- Mark Pilgrim +- Philip Taylor +- Ryan King +- Edward Z. Yang +- fantasai +- Philip Jägenstedt +- Ms2ger +- Andy Wingo +- Andreas Madsack +- Karim Valiev +- Mohammad Taha Jahangir +- Juan Carlos Garcia Segovia +- Mike West +- Marc DM diff -Nru thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/tools/html5lib/CHANGES.rst thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/tools/html5lib/CHANGES.rst --- thunderbird-trunk-37.0~a1~hg20150107r17323.222415/mozilla/testing/web-platform/tests/tools/html5lib/CHANGES.rst 1970-01-01 00:00:00.000000000 +0000 +++ thunderbird-trunk-37.0~a1~hg20150108r17327.222808/mozilla/testing/web-platform/tests/tools/html5lib/CHANGES.rst 2015-01-09 12:36:51.000000000 +0000 @@ -0,0 +1,171 @@ +Change Log +---------- + +0.9999 +~~~~~~ + +Released on XXX, 2014 + +* XXX + + +0.999 +~~~~~ + +Released on December 23, 2013 + +* Fix #127: add work-around for CPython issue #20007: .read(0) on + http.client.HTTPResponse drops the rest of the content. + +* Fix #115: lxml treewalker can now deal with fragments containing, at + their root level, text nodes with non-ASCII characters on Python 2. + + +0.99 +~~~~ + +Released on September 10, 2013 + +* No library changes from 1.0b3; released as 0.99 as pip has changed + behaviour from 1.4 to avoid installing pre-release versions per + PEP 440. + + +1.0b3 +~~~~~ + +Released on July 24, 2013 + +* Removed ``RecursiveTreeWalker`` from ``treewalkers._base``. Any + implementation using it should be moved to + ``NonRecursiveTreeWalker``, as everything bundled with html5lib has + for years. + +* Fix #67 so that ``BufferedStream`` to correctly returns a bytes + object, thereby fixing any case where html5lib is passed a + non-seekable RawIOBase-like object. + + +1.0b2 +~~~~~ + +Released on June 27, 2013 + +* Removed reordering of attributes within the serializer. There is now + an ``alphabetical_attributes`` option which preserves the previous + behaviour through a new filter. This allows attribute order to be + preserved through html5lib if the tree builder preserves order. + +* Removed ``dom2sax`` from DOM treebuilders. It has been replaced by + ``treeadapters.sax.to_sax`` which is generic and supports any + treewalker; it also resolves all known bugs with ``dom2sax``. + +* Fix treewalker assertions on hitting bytes strings on + Python 2. Previous to 1.0b1, treewalkers coped with mixed + bytes/unicode data on Python 2; this reintroduces this prior + behaviour on Python 2. Behaviour is unchanged on Python 3. + + +1.0b1 +~~~~~ + +Released on May 17, 2013 + +* Implementation updated to implement the `HTML specification + `_ as of 5th May + 2013 (`SVN `_ revision r7867). + +* Python 3.2+ supported in a single codebase using the ``six`` library. + +* Removed support for Python 2.5 and older. + +* Removed the deprecated Beautiful Soup 3 treebuilder. + ``beautifulsoup4`` can use ``html5lib`` as a parser instead. Note that + since it doesn't support namespaces, foreign content like SVG and + MathML is parsed incorrectly. + +* Removed ``simpletree`` from the package. The default tree builder is + now ``etree`` (using the ``xml.etree.cElementTree`` implementation if + available, and ``xml.etree.ElementTree`` otherwise). + +* Removed the ``XHTMLSerializer`` as it never actually guaranteed its + output was well-formed XML, and hence provided little of use. + +* Removed default DOM treebuilder, so ``html5lib.treebuilders.dom`` is no + longer supported. ``html5lib.treebuilders.getTreeBuilder("dom")`` will + return the default DOM treebuilder, which uses ``xml.dom.minidom``. + +* Optional heuristic character encoding detection now based on + ``charade`` for Python 2.6 - 3.3 compatibility. + +* Optional ``Genshi`` treewalker support fixed. + +* Many bugfixes, including: + + * #33: null in attribute value breaks XML AttValue; + + * #4: nested, indirect descendant,