Merge autoland to mozilla-central. a=merge

This commit is contained in:
Marian-Vasile Laza 2022-07-29 00:52:31 +03:00
Родитель 38c47158ac b6903c8b87
Коммит 4a15041348
251 изменённых файлов: 30469 добавлений и 18624 удалений

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

@ -205,7 +205,6 @@ module.exports = {
excludedFiles: [
// These are suitable as good first bugs, take one or two related lines
// per bug.
"caps/tests/unit/test_origin.js",
"extensions/permissions/**",
"image/test/unit/**",
"intl/uconv/tests/unit/test_bug340714.js",

28
Cargo.lock сгенерированный
Просмотреть файл

@ -1598,6 +1598,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "flagset"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cda653ca797810c02f7ca4b804b40b8b95ae046eb989d356bce17919a8c25499"
[[package]]
name = "flate2"
version = "1.0.24"
@ -5780,40 +5786,46 @@ version = "0.2.100"
[[package]]
name = "wasm-encoder"
version = "0.7.0"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49cfbd7c23474849807ecde008c82eb38d303b07ec61d48f45b65f3c8cdd2770"
checksum = "f76068e87fe9b837a6bc2ccded66784173eadb828c4168643e9fddf6f9ed2e61"
dependencies = [
"leb128",
]
[[package]]
name = "wasm-smith"
version = "0.8.0"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "440458e050ee2731e85af3368ee58e23d4728d597809a88f841a24778876f2b6"
checksum = "b73250e61e41d0e467b78559c7d761841005d724384bb0b78d52ff974acf5520"
dependencies = [
"arbitrary",
"flagset",
"indexmap",
"leb128",
"wasm-encoder",
"wasmparser",
]
[[package]]
name = "wasmparser"
version = "0.78.2"
version = "0.87.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52144d4c78e5cf8b055ceab8e5fa22814ce4315d6002ad32cfd914f37c12fd65"
checksum = "5c04e207cd2e8ecb6f9bd28a2cf3119b4c6bfeee6fe3a25cc1daf8041d00a875"
dependencies = [
"indexmap",
]
[[package]]
name = "wast"
version = "41.0.0"
version = "44.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f882898b8b817cc4edc16aa3692fdc087b356edc8cc0c2164f5b5181e31c3870"
checksum = "5f474d1b1cb7d92e5360b293f28e8bc9b2d115197a5bbf76bdbfba9161cf9cdc"
dependencies = [
"leb128",
"memchr",
"unicode-width",
"wasm-encoder",
]
[[package]]

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

@ -5,17 +5,19 @@
:root {
height: 100%;
--body-columns: 1fr;
--body-rows: auto 2fr 1fr 40px;
--body-rows: auto 2fr 1fr auto;
--colorway-name-font-size: 1.5em;
--colorway-selector-align: center;
--figure-height: 200px;
--figure-width: 200px;
--homepage-reset-column: 1;
--homepage-reset-align: space-between;
}
@media (min-width: 50em) {
:root {
--body-columns: 24px repeat(2, 1fr);
--body-rows: auto 1fr 64px;
--body-rows: auto 1fr auto;
--colorway-name-font-size: 2.5em;
--colorway-selector-align: start;
--customization-panel-column: 3;
@ -25,6 +27,8 @@
--figure-row: 2;
--figure-width: 288px;
--header-column: 2/4;
--homepage-reset-column: 1/4;
--homepage-reset-align: end;
}
#colorway-name,
@ -38,7 +42,8 @@ body {
display: grid;
grid-template-columns: var(--body-columns);
grid-template-rows: var(--body-rows);
padding: 0 24px;
padding: 0 2em 1em;
box-sizing: border-box;
}
fieldset {
@ -54,6 +59,7 @@ body > header {
}
figure {
align-items: center;
margin: 0;
display: flex;
justify-content: center;
@ -69,6 +75,7 @@ figure > img {
}
#colorway-customization-panel {
align-self: center;
padding-inline: var(--customization-panel-padding-inline);
grid-column: var(--customization-panel-column);
}
@ -101,9 +108,22 @@ figure > img {
#homepage-reset-container:not([hidden]) {
display: flex;
align-items: flex-end;
justify-content: flex-end;
padding: 2em;
grid-column: var(--homepage-reset-column);
text-align: end;
}
.reset-prompt,
.success-prompt {
width: 100%;
display: flex;
flex-flow: row wrap;
align-items: center;
justify-content: var(--homepage-reset-align);
}
.reset-prompt > span,
.success-prompt > span {
padding-inline-end: 1em;
}
#homepage-reset-container:not(.success) > .success-prompt,
@ -111,7 +131,7 @@ figure > img {
display: none;
}
#homepage-reset-container > .success-prompt::before {
#homepage-reset-container > .success-prompt span::before {
display: inline-block;
content: "";
background: var(--green-50) url('chrome://global/skin/icons/check.svg') center center no-repeat;

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

@ -38,6 +38,13 @@ var gFxaPairDeviceDialog = {
},
uninit() {
// When the modal closes we want to remove any query params
// To prevent refreshes/restores from reopening the dialog
const browser = window.docShell.chromeEventHandler;
browser.loadURI("about:preferences#sync", {
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
});
this.teardownListeners();
this._emitter.emit("view:Closed");
},

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

@ -27,13 +27,15 @@ browser.engagement:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1545172 # Telemetry
- https://bugzilla.mozilla.org/show_bug.cgi?id=1741674
- https://bugzilla.mozilla.org/show_bug.cgi?id=1755050
- https://bugzilla.mozilla.org/show_bug.cgi?id=1781578
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1545172#c8
- https://bugzilla.mozilla.org/show_bug.cgi?id=1781578
data_sensitivity:
- interaction
notification_emails:
- loines@mozilla.com
expires: 106
expires: 112
send_in_pings:
- baseline
- metrics
@ -53,13 +55,15 @@ browser.engagement:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1535169 # Telemetry
- https://bugzilla.mozilla.org/show_bug.cgi?id=1741674
- https://bugzilla.mozilla.org/show_bug.cgi?id=1755050
- https://bugzilla.mozilla.org/show_bug.cgi?id=1781578
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1535169#c14
- https://bugzilla.mozilla.org/show_bug.cgi?id=1781578
data_sensitivity:
- interaction
notification_emails:
- loines@mozilla.com
expires: 106
expires: 112
send_in_pings:
- baseline
- metrics

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

@ -462,7 +462,7 @@ const BuiltInThemeConfig = new Map([
[
"innovator-balanced-colorway@mozilla.org",
{
version: "1.1",
version: "1.1.1",
path: "resource://builtin-themes/colorways/2022innovator/balanced/",
collection: "independent-voices",
l10nId: {

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

@ -7,7 +7,7 @@
},
"name": "Innovator – Balanced",
"author": "Mozilla",
"version": "1.1",
"version": "1.1.1",
"icons": {
"32": "icon.svg"
},
@ -26,7 +26,7 @@
"popup_highlight": "hsla(17, 89%, 79%, 0.3)",
"popup_highlight_text": "hsl(0, 0%, 0%)",
"toolbar": "hsl(14, 93%, 83%)",
"toolbar_text": "hsl(0, 0%, 100%)",
"toolbar_text": "hsl(0, 0%, 0%)",
"toolbar_field": "hsl(12, 100%, 91%)",
"toolbar_field_text": "hsl(0, 0%, 0%)",
"toolbar_field_focus": "hsl(0, 0%, 100%)",

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

@ -664,7 +664,7 @@ richlistitem[selected] .actionsMenu:focus-visible {
.fxaPairDeviceIcon .close-icon {
margin-top: 10px;
}
}
.close-icon {
border: none;

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

@ -51,6 +51,7 @@ function checkSandboxOriginAttributes(arr, attrs, options) {
}
// utility function useful for debugging
// eslint-disable-next-line no-unused-vars
function printAttrs(name, attrs) {
info(
name +

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

@ -2998,19 +2998,21 @@ void BrowsingContext::DidSet(FieldIndex<IDX_IsActiveBrowserWindowInternal>,
doc->UpdateDocumentStates(DocumentState::WINDOW_INACTIVE, true);
RefPtr<nsPIDOMWindowInner> win = doc->GetInnerWindow();
RefPtr<MediaDevices> devices;
if (isActivateEvent && (devices = win->GetExtantMediaDevices())) {
devices->BrowserWindowBecameActive();
}
if (win) {
RefPtr<MediaDevices> devices;
if (isActivateEvent && (devices = win->GetExtantMediaDevices())) {
devices->BrowserWindowBecameActive();
}
if (XRE_IsContentProcess() &&
(!aContext->GetParent() || !aContext->GetParent()->IsInProcess())) {
// Send the inner window an activate/deactivate event if
// the context is the top of a sub-tree of in-process
// contexts.
nsContentUtils::DispatchEventOnlyToChrome(
doc, win, isActivateEvent ? u"activate"_ns : u"deactivate"_ns,
CanBubble::eYes, Cancelable::eYes, nullptr);
if (XRE_IsContentProcess() &&
(!aContext->GetParent() || !aContext->GetParent()->IsInProcess())) {
// Send the inner window an activate/deactivate event if
// the context is the top of a sub-tree of in-process
// contexts.
nsContentUtils::DispatchEventOnlyToChrome(
doc, win, isActivateEvent ? u"activate"_ns : u"deactivate"_ns,
CanBubble::eYes, Cancelable::eYes, nullptr);
}
}
}
});

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

@ -1534,14 +1534,14 @@ class Document : public nsINode,
void DoNotifyPossibleTitleChange();
nsresult InitFeaturePolicy(nsIChannel* aChannel);
protected:
friend class nsUnblockOnloadEvent;
nsresult InitCSP(nsIChannel* aChannel);
nsresult InitCOEP(nsIChannel* aChannel);
nsresult InitFeaturePolicy(nsIChannel* aChannel);
nsresult InitReferrerInfo(nsIChannel* aChannel);
void PostUnblockOnloadEvent();

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

@ -323,22 +323,23 @@ nsXMLContentSink::DidBuildModel(bool aTerminated) {
return NS_OK;
}
NS_IMETHODIMP
nsXMLContentSink::OnDocumentCreated(Document* aResultDocument) {
NS_ENSURE_ARG(aResultDocument);
nsresult nsXMLContentSink::OnDocumentCreated(Document* aSourceDocument,
Document* aResultDocument) {
aResultDocument->SetDocWriteDisabled(true);
nsCOMPtr<nsIContentViewer> contentViewer;
mDocShell->GetContentViewer(getter_AddRefs(contentViewer));
if (contentViewer) {
// Make sure that we haven't loaded a new document into the contentviewer
// after starting the XSLT transform.
if (contentViewer && contentViewer->GetDocument() == aSourceDocument) {
return contentViewer->SetDocumentInternal(aResultDocument, true);
}
return NS_OK;
}
NS_IMETHODIMP
nsXMLContentSink::OnTransformDone(nsresult aResult, Document* aResultDocument) {
nsresult nsXMLContentSink::OnTransformDone(Document* aSourceDocument,
nsresult aResult,
Document* aResultDocument) {
MOZ_ASSERT(aResultDocument,
"Don't notify about transform end without a document.");
@ -347,42 +348,49 @@ nsXMLContentSink::OnTransformDone(nsresult aResult, Document* aResultDocument) {
nsCOMPtr<nsIContentViewer> contentViewer;
mDocShell->GetContentViewer(getter_AddRefs(contentViewer));
if (NS_FAILED(aResult) && contentViewer) {
// Transform failed.
aResultDocument->SetMayStartLayout(false);
// We have an error document.
contentViewer->SetDocument(aResultDocument);
}
RefPtr<Document> originalDocument = mDocument;
bool blockingOnload = mIsBlockingOnload;
if (!mRunsToCompletion) {
// This BlockOnload call corresponds to the UnblockOnload call in
// nsContentSink::DropParserAndPerfHint.
aResultDocument->BlockOnload();
mIsBlockingOnload = true;
// Make sure that we haven't loaded a new document into the contentviewer
// after starting the XSLT transform.
if (contentViewer && (contentViewer->GetDocument() == aSourceDocument ||
contentViewer->GetDocument() == aResultDocument)) {
if (NS_FAILED(aResult)) {
// Transform failed.
aResultDocument->SetMayStartLayout(false);
// We have an error document.
contentViewer->SetDocument(aResultDocument);
}
if (!mRunsToCompletion) {
// This BlockOnload call corresponds to the UnblockOnload call in
// nsContentSink::DropParserAndPerfHint.
aResultDocument->BlockOnload();
mIsBlockingOnload = true;
}
// Transform succeeded, or it failed and we have an error document to
// display.
mDocument = aResultDocument;
aResultDocument->SetDocWriteDisabled(false);
// Notify document observers that all the content has been stuck
// into the document.
// XXX do we need to notify for things like PIs? Or just the
// documentElement?
nsIContent* rootElement = mDocument->GetRootElement();
if (rootElement) {
NS_ASSERTION(mDocument->ComputeIndexOf(rootElement).isSome(),
"rootElement not in doc?");
mDocument->BeginUpdate();
MutationObservers::NotifyContentInserted(mDocument, rootElement);
mDocument->EndUpdate();
}
// Start the layout process
StartLayout(false);
ScrollToRef();
}
// Transform succeeded, or it failed and we have an error document to display.
mDocument = aResultDocument;
aResultDocument->SetDocWriteDisabled(false);
// Notify document observers that all the content has been stuck
// into the document.
// XXX do we need to notify for things like PIs? Or just the
// documentElement?
nsIContent* rootElement = mDocument->GetRootElement();
if (rootElement) {
NS_ASSERTION(mDocument->ComputeIndexOf(rootElement).isSome(),
"rootElement not in doc?");
mDocument->BeginUpdate();
MutationObservers::NotifyContentInserted(mDocument, rootElement);
mDocument->EndUpdate();
}
// Start the layout process
StartLayout(false);
ScrollToRef();
originalDocument->EndLoad();
if (blockingOnload) {

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

@ -76,10 +76,11 @@ class nsXMLContentSink : public nsContentSink,
}
// nsITransformObserver
NS_IMETHOD OnDocumentCreated(
mozilla::dom::Document* aResultDocument) override;
NS_IMETHOD OnTransformDone(nsresult aResult,
nsresult OnDocumentCreated(mozilla::dom::Document* aSourceDocument,
mozilla::dom::Document* aResultDocument) override;
nsresult OnTransformDone(mozilla::dom::Document* aSourceDocument,
nsresult aResult,
mozilla::dom::Document* aResultDocument) override;
// nsICSSLoaderObserver
NS_IMETHOD StyleSheetLoaded(mozilla::StyleSheet* aSheet, bool aWasDeferred,

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

@ -33,10 +33,13 @@ class nsITransformObserver : public nsISupports {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ITRANSFORMOBSERVER_IID)
NS_IMETHOD OnDocumentCreated(mozilla::dom::Document* aResultDocument) = 0;
virtual nsresult OnDocumentCreated(
mozilla::dom::Document* aSourceDocument,
mozilla::dom::Document* aResultDocument) = 0;
NS_IMETHOD OnTransformDone(nsresult aResult,
mozilla::dom::Document* aResultDocument) = 0;
virtual nsresult OnTransformDone(mozilla::dom::Document* aSourceDocument,
nsresult aResult,
mozilla::dom::Document* aResultDocument) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsITransformObserver, NS_ITRANSFORMOBSERVER_IID)

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

@ -21,8 +21,11 @@
using namespace mozilla;
using namespace mozilla::dom;
txMozillaTextOutput::txMozillaTextOutput(nsITransformObserver* aObserver)
: mObserver(do_GetWeakReference(aObserver)), mCreatedDocument(false) {
txMozillaTextOutput::txMozillaTextOutput(Document* aSourceDocument,
nsITransformObserver* aObserver)
: mSourceDocument(aSourceDocument),
mObserver(do_GetWeakReference(aObserver)),
mCreatedDocument(false) {
MOZ_COUNT_CTOR(txMozillaTextOutput);
}
@ -86,7 +89,7 @@ nsresult txMozillaTextOutput::endDocument(nsresult aResult) {
if (NS_SUCCEEDED(aResult)) {
nsCOMPtr<nsITransformObserver> observer = do_QueryReferent(mObserver);
if (observer) {
observer->OnTransformDone(aResult, mDocument);
observer->OnTransformDone(mSourceDocument, aResult, mDocument);
}
}
@ -102,8 +105,7 @@ nsresult txMozillaTextOutput::processingInstruction(const nsString& aTarget,
nsresult txMozillaTextOutput::startDocument() { return NS_OK; }
nsresult txMozillaTextOutput::createResultDocument(Document* aSourceDocument,
bool aLoadedAsData) {
nsresult txMozillaTextOutput::createResultDocument(bool aLoadedAsData) {
/*
* Create an XHTML document to hold the text.
*
@ -131,13 +133,13 @@ nsresult txMozillaTextOutput::createResultDocument(Document* aSourceDocument,
mDocument->SetReadyStateInternal(Document::READYSTATE_LOADING);
bool hasHadScriptObject = false;
nsIScriptGlobalObject* sgo =
aSourceDocument->GetScriptHandlingObject(hasHadScriptObject);
mSourceDocument->GetScriptHandlingObject(hasHadScriptObject);
NS_ENSURE_STATE(sgo || !hasHadScriptObject);
NS_ASSERTION(mDocument, "Need document");
// Reset and set up document
URIUtils::ResetWithSource(mDocument, aSourceDocument);
URIUtils::ResetWithSource(mDocument, mSourceDocument);
// Only do this after resetting the document to ensure we have the
// correct principal.
mDocument->SetScriptHandlingObject(sgo);
@ -154,7 +156,7 @@ nsresult txMozillaTextOutput::createResultDocument(Document* aSourceDocument,
// Notify the contentsink that the document is created
nsCOMPtr<nsITransformObserver> observer = do_QueryReferent(mObserver);
if (observer) {
rv = observer->OnDocumentCreated(mDocument);
rv = observer->OnDocumentCreated(mSourceDocument, mDocument);
NS_ENSURE_SUCCESS(rv, rv);
}

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

@ -22,19 +22,20 @@ class Element;
class txMozillaTextOutput : public txAOutputXMLEventHandler {
public:
explicit txMozillaTextOutput(nsITransformObserver* aObserver);
explicit txMozillaTextOutput(mozilla::dom::Document* aSourceDocument,
nsITransformObserver* aObserver);
explicit txMozillaTextOutput(mozilla::dom::DocumentFragment* aDest);
virtual ~txMozillaTextOutput();
TX_DECL_TXAXMLEVENTHANDLER
TX_DECL_TXAOUTPUTXMLEVENTHANDLER
nsresult createResultDocument(mozilla::dom::Document* aSourceDocument,
bool aLoadedAsData);
nsresult createResultDocument(bool aLoadedAsData);
private:
nsresult createXHTMLElement(nsAtom* aName, mozilla::dom::Element** aResult);
nsCOMPtr<mozilla::dom::Document> mSourceDocument;
nsCOMPtr<nsIContent> mTextParent;
nsWeakPtr mObserver;
RefPtr<mozilla::dom::Document> mDocument;

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

@ -50,7 +50,8 @@ using namespace mozilla::dom;
NS_ASSERTION(mCurrentNode, "mCurrentNode is nullptr"); \
if (!mCurrentNode) return NS_ERROR_UNEXPECTED
txMozillaXMLOutput::txMozillaXMLOutput(txOutputFormat* aFormat,
txMozillaXMLOutput::txMozillaXMLOutput(Document* aSourceDocument,
txOutputFormat* aFormat,
nsITransformObserver* aObserver)
: mTreeDepth(0),
mBadChildLevel(0),
@ -61,7 +62,7 @@ txMozillaXMLOutput::txMozillaXMLOutput(txOutputFormat* aFormat,
mNoFixup(false) {
MOZ_COUNT_CTOR(txMozillaXMLOutput);
if (aObserver) {
mNotifier = new txTransformNotifier();
mNotifier = new txTransformNotifier(aSourceDocument);
if (mNotifier) {
mNotifier->Init(aObserver);
}
@ -776,6 +777,9 @@ nsresult txMozillaXMLOutput::createResultDocument(const nsAString& aName,
if (mNotifier) {
rv = mNotifier->SetOutputDocument(mDocument);
NS_ENSURE_SUCCESS(rv, rv);
rv = mDocument->InitFeaturePolicy(mDocument->GetChannel());
NS_ENSURE_SUCCESS(rv, rv);
}
// Do this after calling OnDocumentCreated to ensure that the
@ -835,8 +839,10 @@ nsresult txMozillaXMLOutput::createHTMLElement(nsAtom* aName,
return rv;
}
txTransformNotifier::txTransformNotifier()
: mPendingStylesheetCount(0), mInTransform(false) {}
txTransformNotifier::txTransformNotifier(Document* aSourceDocument)
: mSourceDocument(aSourceDocument),
mPendingStylesheetCount(0),
mInTransform(false) {}
txTransformNotifier::~txTransformNotifier() = default;
@ -906,7 +912,7 @@ nsresult txTransformNotifier::SetOutputDocument(Document* aDocument) {
mDocument = aDocument;
// Notify the contentsink that the document is created
return mObserver->OnDocumentCreated(mDocument);
return mObserver->OnDocumentCreated(mSourceDocument, mDocument);
}
void txTransformNotifier::SignalTransformEnd(nsresult aResult) {
@ -937,6 +943,6 @@ void txTransformNotifier::SignalTransformEnd(nsresult aResult) {
}
if (NS_SUCCEEDED(aResult)) {
mObserver->OnTransformDone(aResult, mDocument);
mObserver->OnTransformDone(mSourceDocument, aResult, mDocument);
}
}

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

@ -30,7 +30,7 @@ class Element;
class txTransformNotifier final : public nsIScriptLoaderObserver,
public nsICSSLoaderObserver {
public:
txTransformNotifier();
explicit txTransformNotifier(mozilla::dom::Document* aSourceDocument);
NS_DECL_ISUPPORTS
NS_DECL_NSISCRIPTLOADEROBSERVER
@ -50,6 +50,7 @@ class txTransformNotifier final : public nsIScriptLoaderObserver,
~txTransformNotifier();
void SignalTransformEnd(nsresult aResult = NS_OK);
nsCOMPtr<mozilla::dom::Document> mSourceDocument;
nsCOMPtr<mozilla::dom::Document> mDocument;
nsCOMPtr<nsITransformObserver> mObserver;
nsTArray<nsCOMPtr<nsIScriptElement>> mScriptElements;
@ -59,7 +60,8 @@ class txTransformNotifier final : public nsIScriptLoaderObserver,
class txMozillaXMLOutput : public txAOutputXMLEventHandler {
public:
txMozillaXMLOutput(txOutputFormat* aFormat, nsITransformObserver* aObserver);
txMozillaXMLOutput(mozilla::dom::Document* aSourceDocument,
txOutputFormat* aFormat, nsITransformObserver* aObserver);
txMozillaXMLOutput(txOutputFormat* aFormat,
mozilla::dom::DocumentFragment* aFragment, bool aNoFixup);
~txMozillaXMLOutput();

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

@ -80,7 +80,7 @@ nsresult txToDocHandlerFactory::createHandlerWith(
case eHTMLOutput: {
UniquePtr<txMozillaXMLOutput> handler(
new txMozillaXMLOutput(aFormat, mObserver));
new txMozillaXMLOutput(mSourceDocument, aFormat, mObserver));
nsresult rv = handler->createResultDocument(
u""_ns, kNameSpaceID_None, mSourceDocument, mDocumentIsData);
@ -93,10 +93,9 @@ nsresult txToDocHandlerFactory::createHandlerWith(
case eTextOutput: {
UniquePtr<txMozillaTextOutput> handler(
new txMozillaTextOutput(mObserver));
new txMozillaTextOutput(mSourceDocument, mObserver));
nsresult rv =
handler->createResultDocument(mSourceDocument, mDocumentIsData);
nsresult rv = handler->createResultDocument(mDocumentIsData);
if (NS_SUCCEEDED(rv)) {
*aHandler = handler.release();
}
@ -123,7 +122,7 @@ nsresult txToDocHandlerFactory::createHandlerWith(
case eXMLOutput:
case eHTMLOutput: {
UniquePtr<txMozillaXMLOutput> handler(
new txMozillaXMLOutput(aFormat, mObserver));
new txMozillaXMLOutput(mSourceDocument, aFormat, mObserver));
nsresult rv = handler->createResultDocument(aName, aNsID, mSourceDocument,
mDocumentIsData);
@ -136,10 +135,9 @@ nsresult txToDocHandlerFactory::createHandlerWith(
case eTextOutput: {
UniquePtr<txMozillaTextOutput> handler(
new txMozillaTextOutput(mObserver));
new txMozillaTextOutput(mSourceDocument, mObserver));
nsresult rv =
handler->createResultDocument(mSourceDocument, mDocumentIsData);
nsresult rv = handler->createResultDocument(mDocumentIsData);
if (NS_SUCCEEDED(rv)) {
*aHandler = handler.release();
}
@ -1024,8 +1022,7 @@ void txMozillaXSLTProcessor::notifyError() {
MOZ_ASSERT(document->GetReadyStateEnum() == Document::READYSTATE_LOADING,
"Bad readyState.");
document->SetReadyStateInternal(Document::READYSTATE_INTERACTIVE);
mObserver->OnTransformDone(mTransformResult, document);
mObserver->OnTransformDone(mSource->OwnerDoc(), mTransformResult, document);
}
nsresult txMozillaXSLTProcessor::ensureStylesheet() {

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

@ -231,6 +231,7 @@ ScopedSaveMultiTex::ScopedSaveMultiTex(GLContext* const gl,
break;
default:
gfxCriticalError() << "Unhandled texTarget: " << texTarget;
MOZ_CRASH();
}
for (uint8_t i = 0; i < mTexCount; i++) {

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

@ -5,6 +5,6 @@ authors = ["Christian Holler"]
license = "MPL 2.0"
[dependencies]
wasm-smith = "0.8.0"
wasm-smith = "0.11.2"
arbitrary = { version = "1.0.0", features = ["derive"] }
libc = "0.2"

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

@ -152,6 +152,7 @@ void TenuringTracer::traverse(JS::Value* thingp) {
} else if (value.isBigInt()) {
post = JS::BigIntValue(onBigIntEdge(value.toBigInt()));
} else {
MOZ_ASSERT_IF(value.isGCThing(), !IsInsideNursery(value.toGCThing()));
return;
}

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

@ -427,8 +427,7 @@ if (wasmGcEnabled()) {
(module
(type $s (struct))
(func (export "newStruct") (result eqref)
rtt.canon $s
struct.new_with_rtt $s)
struct.new $s)
)`).exports;
WasmNonNullEqrefValues.push(newStruct());
WasmEqrefValues.push(null, ...WasmNonNullEqrefValues);

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

@ -0,0 +1,28 @@
function getStack() {
enableGeckoProfiling();
let stack = readGeckoProfilingStack();
// The number of frames depends on JIT flags, but there must be at least
// one frame for the caller and at most 3 total (the global script, 'testFun'
// and 'getStack').
assertEq(stack.length > 0, true);
assertEq(stack.length <= 3, true);
assertEq(JSON.stringify(stack).includes('"testFun ('), true);
disableGeckoProfiling();
}
function testFun() {
// Loop until this is a JIT frame.
while (true) {
let isJitFrame = inJit();
if (typeof isJitFrame === "string") {
return; // JIT disabled.
}
if (isJitFrame) {
break;
}
}
// Now call getStack to check this frame is on the profiler's JIT stack.
getStack();
getStack();
}
testFun();

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

@ -7,7 +7,7 @@
(type $p (struct (field f64) (field (mut i32))))
(func (export "mkp") (result eqref)
(struct.new_with_rtt $p (f64.const 1.5) (i32.const 33) (rtt.canon $p))))`).exports;
(struct.new $p (f64.const 1.5) (i32.const 33))))`).exports;
let p = ins.mkp();
assertEq(p[0], 1.5);
@ -22,7 +22,7 @@
(type $p (struct (field f64)))
(func (export "mkp") (result eqref)
(struct.new_with_rtt $p (f64.const 1.5) (rtt.canon $p))))`).exports;
(struct.new $p (f64.const 1.5))))`).exports;
let p = ins.mkp();
assertErrorMessage(() => p[0] = 5.7,
@ -40,10 +40,10 @@
(type $r (struct (field (mut eqref))))
(func (export "mkp") (result eqref)
(struct.new_with_rtt $p (ref.null $q) (rtt.canon $p)))
(struct.new $p (ref.null $q)))
(func (export "mkr") (result eqref)
(struct.new_with_rtt $r (ref.null eq) (rtt.canon $r))))`).exports;
(struct.new $r (ref.null eq))))`).exports;
assertEq(Object.getPrototypeOf(ins.mkp()), null);
assertEq(Object.getPrototypeOf(ins.mkr()), null);
@ -57,10 +57,10 @@
(type $p (struct (field (mut (ref null $q))) (field (mut eqref))))
(func (export "mkq") (result eqref)
(struct.new_with_rtt $q (f64.const 1.5) (rtt.canon $q)))
(struct.new $q (f64.const 1.5)))
(func (export "mkp") (result eqref)
(struct.new_with_rtt $p (ref.null $q) (ref.null eq) (rtt.canon $p))))`).exports;
(struct.new $p (ref.null $q) (ref.null eq))))`).exports;
let q = ins.mkq();
assertEq(typeof q, "object");
assertEq(q[0], 1.5);
@ -85,7 +85,7 @@
let ins = wasmEvalText(`(module
(type $p (struct (field (mut i64))))
(func (export "mkp") (result eqref)
(struct.new_with_rtt $p (i64.const 0x1234567887654321) (rtt.canon $p))))`).exports;
(struct.new $p (i64.const 0x1234567887654321))))`).exports;
let p = ins.mkp();
assertEq(typeof p, "object");
@ -106,18 +106,16 @@
(type $q (struct (field i32) (field i32)))
(func $f (param eqref) (result i32)
local.get 0
rtt.canon $q
ref.test
ref.test $q
)
(func $g (param eqref) (result i32)
local.get 0
rtt.canon $p
ref.test
ref.test $p
)
(func (export "t1") (result i32)
(call $f (struct.new_with_rtt $p (i64.const 0) (rtt.canon $p))))
(call $f (struct.new $p (i64.const 0))))
(func (export "t2") (result i32)
(call $g (struct.new_with_rtt $q (i32.const 0) (i32.const 0) (rtt.canon $q)))))`).exports;
(call $g (struct.new $q (i32.const 0) (i32.const 0)))))`).exports;
assertEq(ins.t1(), 0);
assertEq(ins.t2(), 0);
}

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

@ -34,22 +34,19 @@ for (let [valtype, def, nondef] of GENERAL_TESTS) {
(func (export "create") (param i32 ${valtype}) (result eqref)
local.get 1
local.get 0
rtt.canon $a
array.new_with_rtt $a
array.new $a
)
(; new T[0] ;)
(func (export "createDefault") (param i32) (result eqref)
local.get 0
rtt.canon $a
array.new_default_with_rtt $a
array.new_default $a
)
(; 0[1] ;)
(func (export "get") (param eqref i32) (result ${valtype})
local.get 0
rtt.canon $a
ref.cast
ref.cast $a
local.get 1
array.get $a
)
@ -57,8 +54,7 @@ for (let [valtype, def, nondef] of GENERAL_TESTS) {
(; 0[1] = 2 ;)
(func (export "set") (param eqref i32 ${valtype})
local.get 0
rtt.canon $a
ref.cast
ref.cast $a
local.get 1
local.get 2
array.set $a
@ -67,8 +63,7 @@ for (let [valtype, def, nondef] of GENERAL_TESTS) {
(; len(a) ;)
(func (export "len") (param eqref) (result i32)
local.get 0
rtt.canon $a
ref.cast
ref.cast $a
array.len $a
)
)`).exports;
@ -130,15 +125,13 @@ for (let [fieldtype, max] of [
(func (export "create") (param i32 i32) (result eqref)
local.get 1
local.get 0
rtt.canon $a
array.new_with_rtt $a
array.new $a
)
(; 0[1] ;)
(func (export "getS") (param eqref i32) (result i32)
local.get 0
rtt.canon $a
ref.cast
ref.cast $a
local.get 1
array.get_s $a
)
@ -146,8 +139,7 @@ for (let [fieldtype, max] of [
(; 0[1] ;)
(func (export "getU") (param eqref i32) (result i32)
local.get 0
rtt.canon $a
ref.cast
ref.cast $a
local.get 1
array.get_u $a
)
@ -155,8 +147,7 @@ for (let [fieldtype, max] of [
(; 0[1] = 2 ;)
(func (export "set") (param eqref i32 i32)
local.get 0
rtt.canon $a
ref.cast
ref.cast $a
local.get 1
local.get 2
array.set $a
@ -193,10 +184,9 @@ assertErrorMessage(() => wasmEvalText(`(module
(type $a (array i32))
(func
(array.set $a
(array.new_with_rtt $a
(array.new $a
i32.const 0xff
i32.const 10
rtt.canon $a)
i32.const 10)
i32.const 0
i32.const 0
)

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

@ -10,8 +10,7 @@ function typingModule(types, castToTypeIndex, brParams, blockResults) {
(; push params onto the stack in the same order as they appear, leaving
the last param at the top of the stack. ;)
${brParams.map((_, i) => `local.get ${i}`).join('\n')}
rtt.canon ${castToTypeIndex}
br_on_cast 0
br_on_cast 0 ${castToTypeIndex}
unreachable
)
)`;
@ -56,20 +55,17 @@ invalidTyping('(type $a (struct))', '$a', ['i32', 'f32', 'eqref'], ['f32', 'i32'
(type $b (struct (field i32)))
(func (export "makeA") (result eqref)
rtt.canon $a
struct.new_default_with_rtt $a
struct.new_default $a
)
(func (export "makeB") (result eqref)
rtt.canon $b
struct.new_default_with_rtt $b
struct.new_default $b
)
(func (export "isA") (param eqref) (result i32)
(block (result (ref $a))
local.get 0
rtt.canon $a
br_on_cast 0
br_on_cast 0 $a
i32.const 0
br 1
@ -81,8 +77,7 @@ invalidTyping('(type $a (struct))', '$a', ['i32', 'f32', 'eqref'], ['f32', 'i32'
(func (export "isB") (param eqref) (result i32)
(block (result (ref $a))
local.get 0
rtt.canon $b
br_on_cast 0
br_on_cast 0 $b
i32.const 0
br 1
@ -128,19 +123,16 @@ invalidTyping('(type $a (struct))', '$a', ['i32', 'f32', 'eqref'], ['f32', 'i32'
(type $f (struct (field i32)))
(func (export "makeT") (result eqref)
rtt.canon $t
struct.new_default_with_rtt $t
struct.new_default $t
)
(func (export "makeF") (result eqref)
rtt.canon $f
struct.new_default_with_rtt $f
struct.new_default $f
)
(func (export "select") (param eqref) (result ${values.map((type) => type).join(" ")})
(block (result (ref $t))
local.get 0
rtt.canon $t
br_on_cast 0
br_on_cast 0 $t
${values.map((type, i) => `${type}.const ${values.length + i}`).join("\n")}
br 1

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

@ -12,7 +12,7 @@
// Struct fields of externref type can receive their value in these ways:
//
// - the struct.new_with_rtt and struct.set instructions
// - the struct.new and struct.set instructions
// - storing into mutable fields from JS
// - from a constructor called from JS
//
@ -25,7 +25,7 @@
// into a field, in this case there should be boxing; and where JS reads a
// non-pointer value from a field, in this case there should be unboxing.
// Write with struct.new_with_rtt, read with the JS getter
// Write with struct.new, read with the JS getter
for (let v of WasmExternrefValues)
{
@ -33,7 +33,7 @@ for (let v of WasmExternrefValues)
`(module
(type $S (struct (field $S.x (mut externref))))
(func (export "make") (param $v externref) (result eqref)
(struct.new_with_rtt $S (local.get $v) (rtt.canon $S))))`);
(struct.new $S (local.get $v))))`);
let x = ins.exports.make(v);
assertEq(x[0], v);
}
@ -47,7 +47,7 @@ for (let v of WasmExternrefValues)
let txt = `(module
(type $S (struct ${fields}))
(func (export "make") ${params} (result eqref)
(struct.new_with_rtt $S ${args} (rtt.canon $S))))`;
(struct.new $S ${args})))`;
let ins = wasmEvalText(txt);
let x = ins.exports.make({x:0}, {x:1}, {x:2}, {x:3}, {x:4}, {x:5}, {x:6}, {x:7}, {x:8}, {x:9})
gc('shrinking');

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

@ -5,7 +5,7 @@
let { exports: { make, ref_eq, ref_eq_for_control } } = wasmEvalText(`(module
(type $s (struct))
(func (export "make") (result eqref) rtt.canon $s struct.new_with_rtt $s)
(func (export "make") (result eqref) struct.new $s)
(func (export "ref_eq") (param $a eqref) (param $b eqref) (result i32)
(ref.eq (local.get $a) (local.get $b)))

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

@ -47,10 +47,10 @@
(global $glob (mut (ref null $point)) (ref.null $point))
(func (export "init")
(global.set $glob (struct.new_with_rtt $point (f64.const 0.5) (f64.const 2.75) (rtt.canon $point))))
(global.set $glob (struct.new $point (f64.const 0.5) (f64.const 2.75))))
(func (export "change")
(global.set $glob (struct.new_with_rtt $point (f64.const 3.5) (f64.const 37.25) (rtt.canon $point))))
(global.set $glob (struct.new $point (f64.const 3.5) (f64.const 37.25))))
(func (export "clear")
(global.set $glob (ref.null $point)))

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

@ -15,7 +15,7 @@ function checkInvalid(body, errorMessage) {
errorMessage);
}
// General test case for struct.new_with_rtt, struct.get, and struct.set: binary tree
// General test case for struct.new, struct.get, and struct.set: binary tree
// manipulation.
{
@ -42,13 +42,12 @@ function checkInvalid(body, errorMessage) {
(local.set $tmp (global.get $k))
(global.set $k (i32.add (local.get $tmp) (i32.const 1)))
(if (result (ref null $wabbit)) (i32.le_s (local.get $n) (i32.const 2))
(struct.new_with_rtt $wabbit (local.get $tmp) (ref.null $wabbit) (ref.null $wabbit) (rtt.canon $wabbit))
(struct.new $wabbit (local.get $tmp) (ref.null $wabbit) (ref.null $wabbit))
(block (result (ref null $wabbit))
(struct.new_with_rtt $wabbit
(struct.new $wabbit
(local.get $tmp)
(call $make (i32.sub (local.get $n) (i32.const 1)))
(call $make (i32.sub (local.get $n) (i32.const 2)))
(rtt.canon $wabbit)))))
(call $make (i32.sub (local.get $n) (i32.const 2)))))))
(func (export "accumulate") (result i32)
(call $accum (global.get $g)))
@ -129,7 +128,7 @@ assertErrorMessage(() => wasmEvalText(
(type $node (struct (field i32)))
(type $node2 (struct (field i32) (field f32)))
(func $f (param $p (ref null $node)) (result (ref null $node2))
(ref.cast (local.get $p) rtt.canon $node2))
(ref.cast $node2 (local.get $p)))
(func (export "test") (result eqref)
(call $f (ref.null $node))))`).exports.test(),
WebAssembly.RuntimeError,
@ -142,10 +141,10 @@ assertEq(wasmEvalText(
(type $node (struct (field i32)))
(type $node2 (struct (field i32) (field f32)))
(func $f (param $p (ref null $node)) (result (ref null $node2))
(ref.cast (local.get $p) rtt.canon $node2))
(ref.cast $node2 (local.get $p)))
(func (export "test") (result i32)
(local $n (ref null $node))
(local.set $n (struct.new_with_rtt $node2 (i32.const 0) (f32.const 12) (rtt.canon $node2)))
(local.set $n (struct.new $node2 (i32.const 0) (f32.const 12)))
(ref.eq (call $f (local.get $n)) (local.get $n))))`).exports.test(),
1);
@ -156,10 +155,10 @@ assertEq(wasmEvalText(
(type $node (struct (field (mut i32))))
(type $node2 (struct (field (mut i32)) (field f32)))
(func $f (param $p (ref null $node)) (result (ref null $node2))
(ref.cast (local.get $p) rtt.canon $node2))
(ref.cast $node2 (local.get $p)))
(func (export "test") (result i32)
(local $n (ref null $node))
(local.set $n (struct.new_with_rtt $node2 (i32.const 0) (f32.const 12) (rtt.canon $node2)))
(local.set $n (struct.new $node2 (i32.const 0) (f32.const 12)))
(ref.eq (call $f (local.get $n)) (local.get $n))))`).exports.test(),
1);
@ -170,10 +169,10 @@ assertEq(wasmEvalText(
`(module
(type $node (struct (field i32)))
(func $f (param $p eqref) (result (ref null $node))
(ref.cast (local.get $p) rtt.canon $node))
(ref.cast $node (local.get $p)))
(func (export "test") (result i32)
(local $n (ref null $node))
(local.set $n (struct.new_with_rtt $node (i32.const 0) (rtt.canon $node)))
(local.set $n (struct.new $node (i32.const 0)))
(ref.eq (call $f (local.get $n)) (local.get $n))))`).exports.test(),
1);
@ -187,16 +186,13 @@ assertEq(wasmEvalText(
(type $c (struct (field eqref)))
(func (export "makeA") (result eqref)
rtt.canon $a
struct.new_default_with_rtt $a
struct.new_default $a
)
(func (export "makeB") (result eqref)
rtt.canon $b
struct.new_default_with_rtt $b
struct.new_default $b
)
(func (export "makeC") (result eqref)
rtt.canon $c
struct.new_default_with_rtt $c
struct.new_default $c
)
)`).exports;
let a = makeA();
@ -209,21 +205,19 @@ assertEq(wasmEvalText(
assertEq(c[0], null);
}
// struct.new_default_with_rtt: valid if all struct fields are defaultable
// struct.new_default: valid if all struct fields are defaultable
wasmFailValidateText(`(module
(type $a (struct (field (ref $a))))
(func
rtt.canon $a
struct.new_default_with_rtt $a
struct.new_default $a
)
)`, /defaultable/);
wasmFailValidateText(`(module
(type $a (struct (field i32) (field i32) (field (ref $a))))
(func
rtt.canon $a
struct.new_default_with_rtt $a
struct.new_default $a
)
)`, /defaultable/);

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

@ -20,7 +20,7 @@ let bin = wasmTextToBinary(`
)
(func $make (param $n i32) (result (ref null $wabbit))
(local $tmp i32)
(struct.new_with_rtt $wabbit (local.get $tmp) (ref.null $wabbit) (ref.null $wabbit) (rtt.canon $wabbit))
(struct.new $wabbit (local.get $tmp) (ref.null $wabbit) (ref.null $wabbit))
)
`);
let mod = new WebAssembly.Module(bin);

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

@ -12,8 +12,7 @@ try {
(type $e (struct))
(func (export "newStruct")
(result eqref)
rtt.canon $e
struct.new_with_rtt $e
struct.new $e
)
`).exports
d.push(newStruct());

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

@ -1,21 +0,0 @@
// |jit-test| skip-if: !wasmGcEnabled()
function processWat(c) {
binary = wasmTextToBinary(c)
d = new WebAssembly.Module(binary)
return new WebAssembly.Instance(d)
}
gczeal(14,10)
let { createA } = processWat(`
(module (type $a (array i32))
(global $e (rtt $a) rtt.canon $a)
(func
(export "createA")
(result eqref)
i32.const 0
i32.const 0
global.get $e
array.new_with_rtt $a
))
`).exports;
createA();

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

@ -1,19 +0,0 @@
// |jit-test| skip-if: !wasmGcEnabled()
function processWat(c) {
binary = wasmTextToBinary(c)
d = new WebAssembly.Module(binary)
return new WebAssembly.Instance(d)
}
gczeal(14,10)
let { createA } = processWat(`
(module (type $a (struct))
(global $e (rtt $a) rtt.canon $a)
(func
(export "createA")
(result eqref)
global.get $e
struct.new_with_rtt $a
))
`).exports;
createA();

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

@ -4,8 +4,7 @@ let { createDefault } = wasmEvalText(`
(module (type $a (array (mut i32)))
(func (export "createDefault") (param i32) (result eqref)
local.get 0
rtt.canon $a
array.new_default_with_rtt $a
array.new_default $a
)
)
`).exports;

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

@ -32,7 +32,7 @@ const wat = `
(func $main
(struct.set $S 18
(struct.new_with_rtt $S
(struct.new $S
(i64.const 0)
(i64.const 0)
(i64.const 0)
@ -51,9 +51,8 @@ const wat = `
(i64.const 0)
(i64.const 0)
(i64.const 0)
(ref.null eq)
(rtt.canon $S))
(struct.new_with_rtt $S2 (rtt.canon $S2))))
(ref.null eq))
(struct.new $S2)))
(start $main))
`
wasmEvalText(wat);
@ -97,7 +96,7 @@ wasmEvalText(`
(local $inline (ref null $inline))
(; create an outline object and acquire multiple views to it ;)
(struct.new_with_rtt $outline
(struct.new $outline
(i64.const 0xFF)
(i64.const 0)
(i64.const 0)
@ -116,8 +115,7 @@ wasmEvalText(`
(i64.const 0)
(i64.const 0)
(i64.const 0)
(i64.const 0)
(rtt.canon $outline))
(i64.const 0))
local.tee $outline
local.set $inline

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

@ -1,63 +0,0 @@
// |jit-test| skip-if: !wasmGcEnabled()
// Multiple invocations of rtt.sub are cached
{
let {createSubA, isSubA} = wasmEvalText(`(module
(type $a (struct))
(func (export "createSubA") (result eqref)
rtt.canon $a
rtt.sub $a
struct.new_with_rtt $a
)
(func (export "isSubA") (param eqref) (result i32)
local.get 0
rtt.canon $a
rtt.sub $a
ref.test
)
)`).exports;
assertEq(isSubA(createSubA()), 1);
}
// rtt.canon is a constant expression
{
let {createA, isA} = wasmEvalText(`(module
(; an immediate function type to cause renumbering ;)
(type (func))
(type $a (struct))
(global $aCanon (rtt $a) rtt.canon $a)
(func (export "createA") (result eqref)
global.get $aCanon
struct.new_with_rtt $a
)
(func (export "isA") (param eqref) (result i32)
local.get 0
global.get $aCanon
ref.test
)
)`).exports;
assertEq(isA(createA()), 1);
}
// rtt.sub is a constant expression
{
let {createSubA, isSubA} = wasmEvalText(`(module
(; an immediate function type to cause renumbering ;)
(type (func))
(type $a (struct))
(global $aSub (rtt $a) rtt.canon $a rtt.sub $a)
(func (export "createSubA") (result eqref)
global.get $aSub
struct.new_with_rtt $a
)
(func (export "isSubA") (param eqref) (result i32)
local.get 0
global.get $aSub
ref.test
)
)`).exports;
assertEq(isSubA(createSubA()), 1);
}

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

@ -59,10 +59,10 @@ var bin = wasmTextToBinary(
;; Useful for testing to ensure that the type is not type #0 here.
(func (export "mk_point") (result eqref)
(struct.new_with_rtt $point (i32.const 37) (i32.const 42) (rtt.canon $point)))
(struct.new $point (i32.const 37) (i32.const 42)))
(func (export "mk_int_node") (param i32) (param externref) (result eqref)
(struct.new_with_rtt $int_node (local.get 0) (local.get 1) (rtt.canon $int_node)))
(struct.new $int_node (local.get 0) (local.get 1)))
;; Too big to fit in an InlineTypedObject.
@ -121,7 +121,7 @@ var bin = wasmTextToBinary(
(field $az i32)))
(func (export "mk_bigger") (result eqref)
(struct.new_with_rtt $bigger
(struct.new $bigger
(i32.const 0)
(i32.const 1)
(i32.const 2)
@ -173,8 +173,7 @@ var bin = wasmTextToBinary(
(i32.const 48)
(i32.const 49)
(i32.const 50)
(i32.const 51)
(rtt.canon $bigger)))
(i32.const 51)))
(type $withfloats (struct
(field $f1 f32)
@ -186,7 +185,7 @@ var bin = wasmTextToBinary(
(func (export "mk_withfloats")
(param f32) (param f64) (param externref) (param f32) (param i32)
(result eqref)
(struct.new_with_rtt $withfloats (local.get 0) (local.get 1) (local.get 2) (local.get 3) (local.get 4) (rtt.canon $withfloats)))
(struct.new $withfloats (local.get 0) (local.get 1) (local.get 2) (local.get 3) (local.get 4)))
)`)
@ -231,7 +230,7 @@ var stress = wasmTextToBinary(
(block $exit
(loop $loop
(br_if $exit (i32.eqz (local.get $n)))
(local.set $list (struct.new_with_rtt $node (local.get $n) (local.get $list) (rtt.canon $node)))
(local.set $list (struct.new $node (local.get $n) (local.get $list)))
(local.set $n (i32.sub (local.get $n) (i32.const 1)))
(br $loop)))
(local.get $list)))`);
@ -259,24 +258,24 @@ assertEq(the_list, null);
(func (export "set") (param eqref)
(local (ref null $big))
(local.set 1 (ref.cast (local.get 0) rtt.canon $big))
(local.set 1 (ref.cast $big (local.get 0)))
(struct.set $big 1 (local.get 1) (i64.const 0x3333333376544567)))
(func (export "set2") (param $p eqref)
(struct.set $big 1
(ref.cast (local.get $p) rtt.canon $big)
(ref.cast $big (local.get $p))
(i64.const 0x3141592653589793)))
(func (export "low") (param $p eqref) (result i32)
(i32.wrap/i64 (struct.get $big 1 (ref.cast (local.get $p) rtt.canon $big))))
(i32.wrap/i64 (struct.get $big 1 (ref.cast $big (local.get $p)))))
(func (export "high") (param $p eqref) (result i32)
(i32.wrap/i64 (i64.shr_u
(struct.get $big 1 (ref.cast (local.get $p) rtt.canon $big))
(struct.get $big 1 (ref.cast $big (local.get $p)))
(i64.const 32))))
(func (export "mk") (result eqref)
(struct.new_with_rtt $big (i32.const 0x7aaaaaaa) (i64.const 0x4201020337) (i32.const 0x6bbbbbbb) (rtt.canon $big)))
(struct.new $big (i32.const 0x7aaaaaaa) (i64.const 0x4201020337) (i32.const 0x6bbbbbbb)))
)`;
@ -313,7 +312,7 @@ assertEq(the_list, null);
(func (export "make") (result eqref)
(global.set $g
(struct.new_with_rtt $big (i32.const 0x7aaaaaaa) (i64.const 0x4201020337) (i32.const 0x6bbbbbbb) (rtt.canon $big)))
(struct.new $big (i32.const 0x7aaaaaaa) (i64.const 0x4201020337) (i32.const 0x6bbbbbbb)))
(global.get $g))
(func (export "update0") (param $x i32)
@ -378,7 +377,7 @@ var bin = wasmTextToBinary(
(global $g (mut (ref null $cons)) (ref.null $cons))
(func (export "push") (param i32)
(global.set $g (struct.new_with_rtt $cons (local.get 0) (global.get $g) (rtt.canon $cons))))
(global.set $g (struct.new $cons (local.get 0) (global.get $g))))
(func (export "top") (result i32)
(struct.get $cons 0 (global.get $g)))
@ -416,9 +415,9 @@ assertErrorMessage(() => ins.pop(),
`(module
(type $Node (struct (field i32)))
(func (export "mk") (result eqref)
(struct.new_with_rtt $Node (i32.const 37) (rtt.canon $Node)))
(struct.new $Node (i32.const 37)))
(func (export "f") (param $n eqref) (result eqref)
(ref.cast (local.get $n) rtt.canon $Node)))`).exports;
(ref.cast $Node (local.get $n))))`).exports;
var n = ins.mk();
assertEq(ins.f(n), n);
assertErrorMessage(() => ins.f(wrapWithProto(n, {})), TypeError, /can only pass a TypedObject/);
@ -442,10 +441,10 @@ assertErrorMessage(() => ins.pop(),
(struct.get $s $y (local.get $p)))
(func (export "testf") (param $n i32) (result i32)
(call $f (struct.new_with_rtt $s (local.get $n) (i32.mul (local.get $n) (i32.const 2)) (rtt.canon $s))))
(call $f (struct.new $s (local.get $n) (i32.mul (local.get $n) (i32.const 2)))))
(func (export "testg") (param $n i32) (result i32)
(call $g (struct.new_with_rtt $s (local.get $n) (i32.mul (local.get $n) (i32.const 2)) (rtt.canon $s))))
(call $g (struct.new $s (local.get $n) (i32.mul (local.get $n) (i32.const 2)))))
)`))).exports;
@ -471,7 +470,7 @@ assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(`
(module
(type $r (struct (field i32)))
(func $f (param f64) (result eqref)
(struct.new_with_rtt $r (local.get 0) (rtt.canon $r)))
(struct.new $r (local.get 0)))
)`)),
WebAssembly.CompileError, /type mismatch/);
@ -481,7 +480,7 @@ assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(`
(module
(type $r (struct (field i32) (field i32)))
(func $f (result eqref)
(struct.new_with_rtt $r (i32.const 0) (rtt.canon $r)))
(struct.new $r (i32.const 0)))
)`)),
WebAssembly.CompileError, /popping value from empty stack/);
@ -494,8 +493,7 @@ assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(`
(i32.const 0)
(i32.const 1)
(i32.const 2)
(rtt.canon $r)
struct.new_with_rtt $r)
struct.new $r)
)`)),
WebAssembly.CompileError, /unused values/);
@ -505,7 +503,7 @@ assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(`
(module
(type (func (param i32) (result i32)))
(func $f (result eqref)
(struct.new_with_rtt 0))
(struct.new 0))
)`)),
WebAssembly.CompileError, /not a struct type/);
@ -517,7 +515,7 @@ wasmEvalText(`
(type $p (struct (field i32)))
(type $q (struct (field i32)))
(func $f (result (ref null $p))
(struct.new_with_rtt $q (i32.const 0) (rtt.canon $q))))
(struct.new $q (i32.const 0))))
`);
// The field name is optional, so this should work.
@ -594,7 +592,7 @@ WebAssembly.CompileError, /signature index references non-signature/);
(field i32)
(field (mut i64))))
(func (export "make") (result eqref)
(struct.new_with_rtt $s (i32.const 37) (i64.const 42) (rtt.canon $s))))`).exports;
(struct.new $s (i32.const 37) (i64.const 42))))`).exports;
let v = ins.make();
assertErrorMessage(() => v[0] = 12,
Error,

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

@ -211,45 +211,3 @@ assertSubtype(
'(array (ref 3))',
'(struct)',
'(struct (field i32))']);
// Rtt subtyping is equivalence
assertSubtype(
'(rtt 0 0)',
'(rtt 0 1)',
['(struct)',
'(struct)']);
assertNotSubtype(
'(rtt 0 0)',
'(rtt 0 1)',
['(struct)',
'(struct (field i32))']);
// An rtt with depth can be a subtype of rtt without depth
assertSubtype(
'(rtt $0)',
'(rtt 0 $0)',
['(struct)']);
// An rtt without depth is not a subtype of an rtt with depth
assertNotSubtype(
'(rtt 0 $0)',
'(rtt $0)',
['(struct)']);
// Rtts with depth must have the same depth
assertSubtype(
'(rtt 0 $0)',
'(rtt 0 $0)',
['(struct)']);
assertSubtype(
'(rtt 1 $0)',
'(rtt 1 $0)',
['(struct)']);
assertNotSubtype(
'(rtt 1 $0)',
'(rtt 0 $0)',
['(struct)']);
assertNotSubtype(
'(rtt 2 $0)',
'(rtt 1 $0)',
['(struct)']);

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

@ -15,9 +15,9 @@
(func (export "set_null") (param i32)
(table.set (local.get 0) (ref.null eq)))
(func (export "set_ref") (param i32) (param eqref)
(table.set (local.get 0) (ref.cast (local.get 1) (rtt.canon $dummy))))
(table.set (local.get 0) (ref.cast $dummy (local.get 1))))
(func (export "make_struct") (result eqref)
(struct.new_with_rtt $dummy (i32.const 37) (rtt.canon $dummy))))`);
(struct.new $dummy (i32.const 37))))`);
let a = ins.exports.make_struct();
ins.exports.set_eqref(3, a);
assertEq(ins.exports.t.get(3), a);
@ -39,7 +39,7 @@
(type $S (struct (field i32) (field f64)))
(table (export "t") 2 eqref)
(func (export "f") (result i32)
(table.grow (struct.new_with_rtt $S (i32.const 0) (f64.const 3.14) (rtt.canon $S)) (i32.const 1))))`);
(table.grow (struct.new $S (i32.const 0) (f64.const 3.14)) (i32.const 1))))`);
assertEq(ins.exports.t.length, 2);
assertEq(ins.exports.f(), 2);
assertEq(ins.exports.t.length, 3);

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

@ -9347,7 +9347,6 @@ AttachDecision CallIRGenerator::tryAttachWasmCall(HandleFunction calleeFunc) {
return AttachDecision::NoAction;
}
break;
case wasm::ValType::Rtt:
case wasm::ValType::V128:
MOZ_CRASH("Function should not have a Wasm JitEntry");
case wasm::ValType::Ref:

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

@ -16795,7 +16795,6 @@ void CodeGenerator::emitIonToWasmCallBase(LIonToWasmCallBase<NumDefs>* lir) {
case wasm::ValType::F64:
argMir = ToMIRType(sig.args()[i]);
break;
case wasm::ValType::Rtt:
case wasm::ValType::V128:
MOZ_CRASH("unexpected argument type when calling from ion to wasm");
case wasm::ValType::Ref:
@ -16870,7 +16869,6 @@ void CodeGenerator::emitIonToWasmCallBase(LIonToWasmCallBase<NumDefs>* lir) {
MOZ_ASSERT(lir->mir()->type() == MIRType::Double);
MOZ_ASSERT(ToFloatRegister(lir->output()) == ReturnDoubleReg);
break;
case wasm::ValType::Rtt:
case wasm::ValType::V128:
MOZ_CRASH("unexpected return type when calling from ion to wasm");
case wasm::ValType::Ref:

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

@ -4985,7 +4985,6 @@ MDefinition* WarpCacheIRTranspiler::convertWasmArg(MDefinition* arg,
case wasm::ValType::F64:
conversion = MToDouble::New(alloc(), arg);
break;
case wasm::ValType::Rtt:
case wasm::ValType::V128:
MOZ_CRASH("Unexpected type for Wasm JitEntry");
case wasm::ValType::Ref:

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

@ -18,5 +18,5 @@ gluesmith = ['jsrust_shared/gluesmith']
jsrust_shared = { path = "./shared" }
# Workaround for https://github.com/rust-lang/rust/issues/58393
mozglue-static = { path = "../../../mozglue/static/rust" }
wast = { version = "41.0.0" }
wasmparser = { version = "0.78.2" }
wast = { version = "44.0.0" }
wasmparser = { version = "0.87.0" }

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

@ -51,20 +51,14 @@ void GeckoProfilerRuntime::setEventMarker(void (*fn)(const char*,
}
// Get a pointer to the top-most profiling frame, given the exit frame pointer.
static jit::JitFrameLayout* GetTopProfilingJitFrame(Activation* act) {
if (!act || !act->isJit()) {
return nullptr;
}
jit::JitActivation* jitActivation = act->asJit();
static jit::JitFrameLayout* GetTopProfilingJitFrame(jit::JitActivation* act) {
// If there is no exit frame set, just return.
if (!jitActivation->hasExitFP()) {
if (!act->hasExitFP()) {
return nullptr;
}
// Skip wasm frames that might be in the way.
OnlyJSJitFrameIter iter(jitActivation);
OnlyJSJitFrameIter iter(act);
if (iter.done()) {
return nullptr;
}
@ -118,16 +112,12 @@ void GeckoProfilerRuntime::enable(bool enabled) {
// Walk through all activations, and set their lastProfilingFrame
// appropriately.
if (enabled) {
Activation* act = cx->activation();
auto* lastProfilingFrame = GetTopProfilingJitFrame(act);
jit::JitActivation* jitActivation = cx->jitActivation;
while (jitActivation) {
auto* lastProfilingFrame = GetTopProfilingJitFrame(jitActivation);
jitActivation->setLastProfilingFrame(lastProfilingFrame);
jitActivation->setLastProfilingCallSite(nullptr);
jitActivation = jitActivation->prevJitActivation();
lastProfilingFrame = GetTopProfilingJitFrame(jitActivation);
}
} else {
jit::JitActivation* jitActivation = cx->jitActivation;

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

@ -6589,8 +6589,6 @@ static bool ValidateGlobalVariable(JSContext* cx, const AsmJSGlobal& global,
MOZ_CRASH("int64");
case ValType::V128:
MOZ_CRASH("v128");
case ValType::Rtt:
MOZ_CRASH("rtt");
case ValType::F32: {
float f;
if (!RoundFloat32(cx, v, &f)) {

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

@ -1595,17 +1595,15 @@ struct BaseCompiler final {
[[nodiscard]] bool emitTableSetAnyRef(uint32_t tableIndex);
#ifdef ENABLE_WASM_GC
[[nodiscard]] bool emitStructNewWithRtt();
[[nodiscard]] bool emitStructNewDefaultWithRtt();
[[nodiscard]] bool emitStructNew();
[[nodiscard]] bool emitStructNewDefault();
[[nodiscard]] bool emitStructGet(FieldExtension extension);
[[nodiscard]] bool emitStructSet();
[[nodiscard]] bool emitArrayNewWithRtt();
[[nodiscard]] bool emitArrayNewDefaultWithRtt();
[[nodiscard]] bool emitArrayNew();
[[nodiscard]] bool emitArrayNewDefault();
[[nodiscard]] bool emitArrayGet(FieldExtension extension);
[[nodiscard]] bool emitArraySet();
[[nodiscard]] bool emitArrayLen();
[[nodiscard]] bool emitRttCanon();
[[nodiscard]] bool emitRttSub();
[[nodiscard]] bool emitRefTest();
[[nodiscard]] bool emitRefCast();
[[nodiscard]] bool emitBrOnCast();

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

@ -357,7 +357,6 @@ void BaseCompiler::needResultRegisters(ResultType type, ResultRegKind which) {
needF64(RegF64(result.fpr()));
}
break;
case ValType::Rtt:
case ValType::Ref:
needRef(RegRef(result.gpr()));
break;
@ -418,7 +417,6 @@ void BaseCompiler::freeResultRegisters(ResultType type, ResultRegKind which) {
freeF64(RegF64(result.fpr()));
}
break;
case ValType::Rtt:
case ValType::Ref:
freeRef(RegRef(result.gpr()));
break;

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

@ -151,7 +151,6 @@ struct Stk {
case ValType::F64:
k = Stk::MemF64;
break;
case ValType::Rtt:
case ValType::Ref:
k = Stk::MemRef;
break;

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

@ -814,7 +814,6 @@ void BaseCompiler::saveRegisterReturnValues(const ResultType& resultType) {
case ValType::F32:
masm.storeFloat32(RegF32(result.fpr()), dest);
break;
case ValType::Rtt:
case ValType::Ref: {
uint32_t flag =
DebugFrame::hasSpilledRegisterRefResultBitMask(registerResultIdx);
@ -867,7 +866,6 @@ void BaseCompiler::restoreRegisterReturnValues(const ResultType& resultType) {
case ValType::F32:
masm.loadFloat32(src, RegF32(result.fpr()));
break;
case ValType::Rtt:
case ValType::Ref:
masm.loadPtr(src, RegRef(result.gpr()));
break;
@ -934,7 +932,6 @@ void BaseCompiler::popRegisterResults(ABIResultIter& iter) {
case ValType::F64:
popF64(RegF64(result.fpr()));
break;
case ValType::Rtt:
case ValType::Ref:
popRef(RegRef(result.gpr()));
break;
@ -1201,7 +1198,6 @@ bool BaseCompiler::pushResults(ResultType type, StackHeight resultsBase) {
case ValType::F64:
pushF64(RegF64(result.fpr()));
break;
case ValType::Rtt:
case ValType::Ref:
pushRef(RegRef(result.gpr()));
break;
@ -1531,7 +1527,6 @@ void BaseCompiler::passArg(ValType type, const Stk& arg, FunctionCall* call) {
}
break;
}
case ValType::Rtt:
case ValType::Ref: {
ABIArg argLoc = call->abi.next(MIRType::RefOrNull);
if (argLoc.kind() == ABIArg::Stack) {
@ -4026,7 +4021,6 @@ bool BaseCompiler::emitCatch() {
MOZ_CRASH("No SIMD support");
#endif
}
case ValType::Rtt:
case ValType::Ref: {
// TODO/AnyRef-boxing: With boxed immediates and strings, this may need
// to handle other kinds of values.
@ -4379,7 +4373,6 @@ bool BaseCompiler::emitThrow() {
MOZ_CRASH("No SIMD support");
#endif
}
case ValType::Rtt:
case ValType::Ref: {
RegPtr valueAddr(PreBarrierReg);
needPtr(valueAddr);
@ -5059,7 +5052,6 @@ bool BaseCompiler::emitGetLocal() {
case ValType::F32:
pushLocalF32(slot);
break;
case ValType::Rtt:
case ValType::Ref:
pushLocalRef(slot);
break;
@ -5135,7 +5127,6 @@ bool BaseCompiler::emitSetOrTeeLocal(uint32_t slot) {
MOZ_CRASH("No SIMD support");
#endif
}
case ValType::Rtt:
case ValType::Ref: {
RegRef rv = popRef();
syncLocal(slot);
@ -5240,7 +5231,6 @@ bool BaseCompiler::emitGetGlobal() {
pushF64(rv);
break;
}
case ValType::Rtt:
case ValType::Ref: {
RegRef rv = needRef();
ScratchPtr tmp(*this);
@ -5306,7 +5296,6 @@ bool BaseCompiler::emitSetGlobal() {
freeF64(rv);
break;
}
case ValType::Rtt:
case ValType::Ref: {
RegPtr valueAddr(PreBarrierReg);
needPtr(valueAddr);
@ -6531,13 +6520,12 @@ bool BaseCompiler::emitGcArraySet(RegRef object, RegPtr data, RegI32 index,
return true;
}
bool BaseCompiler::emitStructNewWithRtt() {
bool BaseCompiler::emitStructNew() {
uint32_t lineOrBytecode = readCallSiteLineOrBytecode();
uint32_t typeIndex;
Nothing rtt;
BaseNothingVector args{};
if (!iter_.readStructNewWithRtt(&typeIndex, &rtt, &args)) {
if (!iter_.readStructNew(&typeIndex, &args)) {
return false;
}
@ -6547,10 +6535,9 @@ bool BaseCompiler::emitStructNewWithRtt() {
const StructType& structType = (*moduleEnv_.types)[typeIndex].structType();
// Allocate zeroed storage. The parameter to StructNew is a rtt value that is
// guaranteed to be at the top of the stack by validation.
//
// Traps on OOM.
// Allocate a default initialized struct. This requires the rtt value for the
// struct to be pushed on the stack. This will trap on OOM.
emitGcCanon(typeIndex);
if (!emitInstanceCall(lineOrBytecode, SASigStructNew)) {
return false;
}
@ -6611,18 +6598,21 @@ bool BaseCompiler::emitStructNewWithRtt() {
return true;
}
bool BaseCompiler::emitStructNewDefaultWithRtt() {
// Allocate zeroed storage. The parameter to StructNew is a rtt value that is
// guaranteed to be at the top of the stack by validation.
//
// Traps on OOM.
bool BaseCompiler::emitStructNewDefault() {
uint32_t lineOrBytecode = readCallSiteLineOrBytecode();
// (rtt) -> ref; the type index is just dropped on the floor
return emitInstanceCallOp(SASigStructNew, [this]() -> bool {
uint32_t unusedTypeIndex;
Nothing unusedRtt;
return iter_.readStructNewDefaultWithRtt(&unusedTypeIndex, &unusedRtt);
});
uint32_t typeIndex;
if (!iter_.readStructNewDefault(&typeIndex)) {
return false;
}
if (deadCode_) {
return true;
}
// Allocate a default initialized struct. This requires the rtt value for the
// struct to be pushed on the stack. This will trap on OOM.
emitGcCanon(typeIndex);
return emitInstanceCall(lineOrBytecode, SASigStructNew);
}
bool BaseCompiler::emitStructGet(FieldExtension extension) {
@ -6743,12 +6733,12 @@ bool BaseCompiler::emitStructSet() {
return true;
}
bool BaseCompiler::emitArrayNewWithRtt() {
bool BaseCompiler::emitArrayNew() {
uint32_t lineOrBytecode = readCallSiteLineOrBytecode();
uint32_t typeIndex;
Nothing nothing;
if (!iter_.readArrayNewWithRtt(&typeIndex, &nothing, &nothing, &nothing)) {
if (!iter_.readArrayNew(&typeIndex, &nothing, &nothing)) {
return false;
}
@ -6758,10 +6748,9 @@ bool BaseCompiler::emitArrayNewWithRtt() {
const ArrayType& arrayType = (*moduleEnv_.types)[typeIndex].arrayType();
// Allocate zeroed storage. The parameter to ArrayNew is a rtt value and
// length that are guaranteed to be at the top of the stack by validation.
//
// Traps on OOM.
// Allocate a default initialized array. This requires the rtt value for the
// array to be pushed on the stack. This will trap on OOM.
emitGcCanon(typeIndex);
if (!emitInstanceCall(lineOrBytecode, SASigArrayNew)) {
return false;
}
@ -6815,19 +6804,23 @@ bool BaseCompiler::emitArrayNewWithRtt() {
return true;
}
bool BaseCompiler::emitArrayNewDefaultWithRtt() {
// Allocate zeroed storage. The parameter to ArrayNew is a rtt value that is
// guaranteed to be at the top of the stack by validation.
//
// Traps on OOM.
bool BaseCompiler::emitArrayNewDefault() {
uint32_t lineOrBytecode = readCallSiteLineOrBytecode();
// (rtt) -> ref; the type index is dropped on the floor.
return emitInstanceCallOp(SASigArrayNew, [this]() -> bool {
uint32_t unusedTypeIndex;
Nothing nothing;
return iter_.readArrayNewDefaultWithRtt(&unusedTypeIndex, &nothing,
&nothing);
});
uint32_t typeIndex;
Nothing nothing;
if (!iter_.readArrayNewDefault(&typeIndex, &nothing)) {
return false;
}
if (deadCode_) {
return true;
}
// Allocate a default initialized array. This requires the rtt value for the
// array to be pushed on the stack. This will trap on OOM.
emitGcCanon(typeIndex);
return emitInstanceCall(lineOrBytecode, SASigArrayNew);
}
bool BaseCompiler::emitArrayGet(FieldExtension extension) {
@ -6969,26 +6962,12 @@ bool BaseCompiler::emitArrayLen() {
return true;
}
bool BaseCompiler::emitRttCanon() {
ValType rttType;
if (!iter_.readRttCanon(&rttType)) {
return false;
}
if (deadCode_) {
return true;
}
emitGcCanon(rttType.typeIndex());
return true;
}
bool BaseCompiler::emitRttSub() {
bool BaseCompiler::emitRefTest() {
uint32_t lineOrBytecode = readCallSiteLineOrBytecode();
Nothing nothing;
uint32_t rttSubTypeIndex;
if (!iter_.readRttSub(&nothing, &rttSubTypeIndex)) {
uint32_t typeIndex;
if (!iter_.readRefTest(&typeIndex, &nothing)) {
return false;
}
@ -6996,36 +6975,16 @@ bool BaseCompiler::emitRttSub() {
return true;
}
// rtt.sub $t; [(rtt $t' _)] -> [(rtt $t _)]
// Push (rtt.canon $t) so that we can cache the result and yield the
// same rtt value for the same $t operand.
emitGcCanon(rttSubTypeIndex);
if (!emitInstanceCall(lineOrBytecode, SASigRttSub)) {
return false;
}
return true;
}
bool BaseCompiler::emitRefTest() {
// refTest builtin has same signature as ref.test instruction, stack is
// guaranteed to be in the right condition due to validation.
return emitInstanceCallOp(SASigRefTest, [this]() -> bool {
Nothing nothing;
uint32_t unusedRttTypeIndex;
uint32_t unusedRttDepth;
return iter_.readRefTest(&nothing, &unusedRttTypeIndex, &unusedRttDepth,
&nothing);
});
emitGcCanon(typeIndex);
return emitInstanceCall(lineOrBytecode, SASigRefTest);
}
bool BaseCompiler::emitRefCast() {
uint32_t lineOrBytecode = readCallSiteLineOrBytecode();
Nothing nothing;
uint32_t rttTypeIndex;
uint32_t rttDepth;
if (!iter_.readRefCast(&nothing, &rttTypeIndex, &rttDepth, &nothing)) {
uint32_t typeIndex;
if (!iter_.readRefCast(&typeIndex, &nothing)) {
return false;
}
@ -7033,7 +6992,6 @@ bool BaseCompiler::emitRefCast() {
return true;
}
RegRef rttPtr = popRef();
RegRef refPtr = popRef();
// 1. duplicate and shuffle from [ref, rtt] to [ref, ref, rtt]
@ -7041,7 +6999,7 @@ bool BaseCompiler::emitRefCast() {
moveRef(refPtr, castedPtr);
pushRef(castedPtr);
pushRef(refPtr);
pushRef(rttPtr);
emitGcCanon(typeIndex);
// 2. ref.test : [ref, rtt] -> [i32]
if (!emitInstanceCall(lineOrBytecode, SASigRefTest)) {
@ -7064,13 +7022,11 @@ bool BaseCompiler::emitBrOnCast() {
uint32_t lineOrBytecode = readCallSiteLineOrBytecode();
uint32_t relativeDepth;
Nothing unused{};
BaseNothingVector unused_values{};
uint32_t rttTypeIndex;
uint32_t rttDepth;
uint32_t typeIndex;
ResultType branchTargetType;
if (!iter_.readBrOnCast(&relativeDepth, &unused, &rttTypeIndex, &rttDepth,
&branchTargetType, &unused_values)) {
if (!iter_.readBrOnCast(&relativeDepth, &typeIndex, &branchTargetType,
&unused_values)) {
return false;
}
@ -7081,7 +7037,6 @@ bool BaseCompiler::emitBrOnCast() {
Control& target = controlItem(relativeDepth);
target.bceSafeOnExit &= bceSafe_;
RegRef rttPtr = popRef();
RegRef refPtr = popRef();
// 1. duplicate and shuffle from [T*, ref, rtt] to [T*, ref, ref, rtt]
@ -7089,7 +7044,7 @@ bool BaseCompiler::emitBrOnCast() {
moveRef(refPtr, castedPtr);
pushRef(castedPtr);
pushRef(refPtr);
pushRef(rttPtr);
emitGcCanon(typeIndex);
// 2. ref.test : [ref, rtt] -> [i32]
if (!emitInstanceCall(lineOrBytecode, SASigRefTest)) {
@ -9200,10 +9155,10 @@ bool BaseCompiler::emitBody() {
return iter_.unrecognizedOpcode(&op);
}
switch (op.b1) {
case uint32_t(GcOp::StructNewWithRtt):
CHECK_NEXT(emitStructNewWithRtt());
case uint32_t(GcOp::StructNewDefaultWithRtt):
CHECK_NEXT(emitStructNewDefaultWithRtt());
case uint32_t(GcOp::StructNew):
CHECK_NEXT(emitStructNew());
case uint32_t(GcOp::StructNewDefault):
CHECK_NEXT(emitStructNewDefault());
case uint32_t(GcOp::StructGet):
CHECK_NEXT(emitStructGet(FieldExtension::None));
case uint32_t(GcOp::StructGetS):
@ -9212,10 +9167,10 @@ bool BaseCompiler::emitBody() {
CHECK_NEXT(emitStructGet(FieldExtension::Unsigned));
case uint32_t(GcOp::StructSet):
CHECK_NEXT(emitStructSet());
case uint32_t(GcOp::ArrayNewWithRtt):
CHECK_NEXT(emitArrayNewWithRtt());
case uint32_t(GcOp::ArrayNewDefaultWithRtt):
CHECK_NEXT(emitArrayNewDefaultWithRtt());
case uint32_t(GcOp::ArrayNew):
CHECK_NEXT(emitArrayNew());
case uint32_t(GcOp::ArrayNewDefault):
CHECK_NEXT(emitArrayNewDefault());
case uint32_t(GcOp::ArrayGet):
CHECK_NEXT(emitArrayGet(FieldExtension::None));
case uint32_t(GcOp::ArrayGetS):
@ -9226,10 +9181,6 @@ bool BaseCompiler::emitBody() {
CHECK_NEXT(emitArraySet());
case uint32_t(GcOp::ArrayLen):
CHECK_NEXT(emitArrayLen());
case uint32_t(GcOp::RttCanon):
CHECK_NEXT(emitRttCanon());
case uint32_t(GcOp::RttSub):
CHECK_NEXT(emitRttSub());
case uint32_t(GcOp::RefTest):
CHECK_NEXT(emitRefTest());
case uint32_t(GcOp::RefCast):
@ -10219,7 +10170,6 @@ void BaseCompiler::assertResultRegistersAvailable(ResultType type) {
case ValType::F64:
MOZ_ASSERT(isAvailableF64(RegF64(result.fpr())));
break;
case ValType::Rtt:
case ValType::Ref:
MOZ_ASSERT(isAvailableRef(RegRef(result.gpr())));
break;

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

@ -653,15 +653,6 @@ inline ValType Decoder::uncheckedReadValType() {
case uint8_t(TypeCode::FuncRef):
case uint8_t(TypeCode::ExternRef):
return RefType::fromTypeCode(TypeCode(code), true);
case uint8_t(TypeCode::RttWithDepth): {
uint32_t rttDepth = uncheckedReadVarU32();
int32_t typeIndex = uncheckedReadVarS32();
return ValType::fromRtt(typeIndex, rttDepth);
}
case uint8_t(TypeCode::Rtt): {
int32_t typeIndex = uncheckedReadVarS32();
return ValType::fromRtt(typeIndex, RttDepthNone);
}
case uint8_t(TypeCode::Ref):
case uint8_t(TypeCode::NullableRef): {
bool nullable = code == uint8_t(TypeCode::NullableRef);
@ -722,34 +713,6 @@ inline bool Decoder::readPackedType(uint32_t numTypes,
return true;
#else
break;
#endif
}
case uint8_t(TypeCode::Rtt):
case uint8_t(TypeCode::RttWithDepth): {
#ifdef ENABLE_WASM_GC
if (!features.gc) {
return fail("gc types not enabled");
}
uint32_t rttDepth = RttDepthNone;
if (code == uint8_t(TypeCode::RttWithDepth) &&
(!readVarU32(&rttDepth) || uint32_t(rttDepth) >= MaxRttDepth)) {
return fail("invalid rtt depth");
}
RefType heapType;
if (!readHeapType(numTypes, features, true, &heapType)) {
return false;
}
if (!heapType.isTypeIndex()) {
return fail("invalid heap type for rtt");
}
*type = T::fromRtt(heapType.typeIndex(), rttDepth);
return true;
#else
break;
#endif
}
case uint8_t(TypeCode::EqRef): {

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

@ -291,8 +291,6 @@ const SymbolicAddressSignature SASigArrayNew = {SymbolicAddress::ArrayNew,
{_PTR, _I32, _RoN, _END}};
const SymbolicAddressSignature SASigRefTest = {
SymbolicAddress::RefTest, _I32, _Infallible, 3, {_PTR, _RoN, _RoN, _END}};
const SymbolicAddressSignature SASigRttSub = {
SymbolicAddress::RttSub, _RoN, _FailOnNullPtr, 3, {_PTR, _RoN, _RoN, _END}};
#define DECL_SAS_FOR_INTRINSIC(op, export, sa_name, abitype, entry, idx) \
const SymbolicAddressSignature SASig##sa_name = { \
SymbolicAddress::sa_name, _VOID, _FailOnNegI32, \
@ -1267,10 +1265,6 @@ void* wasm::AddressOf(SymbolicAddress imm, ABIFunctionType* abiType) {
*abiType = Args_Int32_GeneralGeneralGeneral;
MOZ_ASSERT(*abiType == ToABIType(SASigRefTest));
return FuncCast(Instance::refTest, *abiType);
case SymbolicAddress::RttSub:
*abiType = Args_General3;
MOZ_ASSERT(*abiType == ToABIType(SASigRttSub));
return FuncCast(Instance::rttSub, *abiType);
case SymbolicAddress::InlineTypedObjectClass:
// The ABI type is not used here, but assigning one to avoid garbage.
*abiType = Args_General1;
@ -1453,7 +1447,6 @@ bool wasm::NeedsBuiltinThunk(SymbolicAddress sym) {
case SymbolicAddress::ThrowException:
case SymbolicAddress::ArrayNew:
case SymbolicAddress::RefTest:
case SymbolicAddress::RttSub:
#define OP(op, export, sa_name, abitype, entry, idx) \
case SymbolicAddress::sa_name:
FOR_EACH_INTRINSIC(OP)

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

@ -119,7 +119,6 @@ enum class SymbolicAddress {
TableSize,
RefFunc,
RefTest,
RttSub,
PreBarrierFiltering,
PostBarrier,
PostBarrierPrecise,
@ -250,7 +249,6 @@ extern const SymbolicAddressSignature SASigExceptionNew;
extern const SymbolicAddressSignature SASigThrowException;
extern const SymbolicAddressSignature SASigArrayNew;
extern const SymbolicAddressSignature SASigRefTest;
extern const SymbolicAddressSignature SASigRttSub;
#define EXT_INTR_SA_DECL(op, export, sa_name, abitype, entry, idx) \
extern const SymbolicAddressSignature SASig##sa_name;
FOR_EACH_INTRINSIC(EXT_INTR_SA_DECL)

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

@ -81,10 +81,6 @@ enum class TypeCode {
// Type constructor for non-nullable reference types.
Ref = 0x6b, // SLEB128(-0x15)
// Type constructors for rtt types.
RttWithDepth = 0x69, // SLEB128(-0x17)
Rtt = 0x68, // SLEB128(-0x18)
// Type constructor for function types
Func = 0x60, // SLEB128(-0x20)
@ -116,11 +112,6 @@ static constexpr TypeCode AbstractReferenceTypeCode = TypeCode::ExternRef;
static constexpr TypeCode AbstractReferenceTypeIndexCode = TypeCode::Ref;
// A type code used to represent (rtt depth? typeindex) whether or not the type
// is encoded with 'Rtt' or 'RttWithDepth'.
static constexpr TypeCode AbstractRttCode = TypeCode::Rtt;
enum class TypeIdDescKind { None, Immediate, Global };
// A wasm::Trap represents a wasm-defined trap that can occur during execution
@ -458,30 +449,26 @@ inline bool IsPrefixByte(uint8_t b) { return b >= uint8_t(Op::FirstPrefix); }
// Opcodes in the GC opcode space.
enum class GcOp {
// Structure operations
StructNewWithRtt = 0x1,
StructNewDefaultWithRtt = 0x2,
StructNew = 0x7,
StructNewDefault = 0x8,
StructGet = 0x03,
StructGetS = 0x04,
StructGetU = 0x05,
StructSet = 0x06,
// Array operations
ArrayNewWithRtt = 0x11,
ArrayNewDefaultWithRtt = 0x12,
ArrayNew = 0x1b,
ArrayNewDefault = 0x1c,
ArrayGet = 0x13,
ArrayGetS = 0x14,
ArrayGetU = 0x15,
ArraySet = 0x16,
ArrayLen = 0x17,
// Rtt operations
RttCanon = 0x30,
RttSub = 0x31,
// Ref operations
RefTest = 0x40,
RefCast = 0x41,
BrOnCast = 0x42,
RefTest = 0x44,
RefCast = 0x45,
BrOnCast = 0x46,
Limit
};
@ -1019,10 +1006,8 @@ static const unsigned MaxFunctionBytes = 7654321;
// platform
#ifdef JS_64BIT
static const unsigned MaxTypeIndex = 1000000;
static const unsigned MaxRttDepth = 1000;
#else
static const unsigned MaxTypeIndex = 15000;
static const unsigned MaxRttDepth = 100;
#endif
static const unsigned MaxTags = 1000000;
@ -1043,10 +1028,6 @@ static const unsigned MaxCodeSectionBytes = MaxModuleBytes;
static const unsigned MaxFrameSize = 512 * 1024;
// A magic value of rtt depth to signify that it was not specified.
static const uint32_t RttDepthNone = MaxRttDepth + 1;
// Asserted by Decoder::readVarU32.
static const unsigned MaxVarU32DecodedBytes = 5;

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

@ -69,7 +69,6 @@ class DebugFrame {
case ValType::F32:
case ValType::F64:
case ValType::V128:
case ValType::Rtt:
return;
case ValType::Ref:
switch (type.refTypeKind()) {

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

@ -1620,8 +1620,6 @@ static const char* ThunkedNativeToDescription(SymbolicAddress func) {
return "call to native array.new (in wasm)";
case SymbolicAddress::RefTest:
return "call to native ref.test (in wasm)";
case SymbolicAddress::RttSub:
return "call to native rtt.sub (in wasm)";
case SymbolicAddress::InlineTypedObjectClass:
MOZ_CRASH();
#define OP(op, export, sa_name, abitype, entry, idx) \

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

@ -175,35 +175,6 @@ static bool ValidateInitExpr(Decoder& d, ModuleEnvironment* env,
*literal = Nothing();
break;
}
#endif
#ifdef ENABLE_WASM_GC
case uint16_t(Op::GcPrefix): {
if (!env->gcEnabled()) {
return iter.unrecognizedOpcode(&op);
}
switch (op.b1) {
case uint16_t(GcOp::RttCanon): {
ValType unusedTy;
if (!iter.readRttCanon(&unusedTy)) {
return false;
}
*literal = Nothing();
break;
}
case uint16_t(GcOp::RttSub): {
uint32_t unusedRttTypeIndex;
if (!iter.readRttSub(&nothing, &unusedRttTypeIndex)) {
return false;
}
*literal = Nothing();
break;
}
default: {
return iter.unrecognizedOpcode(&op);
}
}
break;
}
#endif
default: {
return iter.unrecognizedOpcode(&op);
@ -248,10 +219,6 @@ class MOZ_STACK_CLASS InitExprInterpreter {
bool pushFuncRef(HandleFuncRef ref) {
return stack.append(Val(RefType::func(), ref));
}
bool pushRtt(Handle<RttValue*> rtt) {
// The exact rtt type is not important, evaluation won't use it
return stack.append(Val(ValType::fromRtt(0, 0), AnyRef::fromJSObject(rtt)));
}
#ifdef ENABLE_WASM_EXTENDED_CONST
int32_t popI32() {
@ -265,13 +232,6 @@ class MOZ_STACK_CLASS InitExprInterpreter {
return int64_t(result);
}
#endif
#ifdef ENABLE_WASM_GC
RttValue* popRtt(JSContext* cx) {
RootedAnyRef result(cx, stack.back().ref());
stack.popBack();
return &result.get().asJSObject()->as<RttValue>();
}
#endif
bool evalGetGlobal(uint32_t index) {
return stack.append(globalImportValues[index]);
@ -327,23 +287,6 @@ class MOZ_STACK_CLASS InitExprInterpreter {
return true;
}
#endif
#ifdef ENABLE_WASM_GC
bool evalRttCanon(JSContext* cx, uint32_t typeIndex) {
Rooted<RttValue*> result(cx, nullptr);
if (!instance().constantRttCanon(cx, typeIndex, &result)) {
return false;
}
return pushRtt(result);
}
bool evalRttSub(JSContext* cx, uint32_t typeIndex) {
Rooted<RttValue*> parentRtt(cx, popRtt(cx));
Rooted<RttValue*> result(cx, nullptr);
if (!instance().constantRttSub(cx, parentRtt, typeIndex, &result)) {
return false;
}
return pushRtt(result);
}
#endif
};
bool InitExprInterpreter::evaluate(JSContext* cx, Decoder& d) {
@ -457,32 +400,6 @@ bool InitExprInterpreter::evaluate(JSContext* cx, Decoder& d) {
}
CHECK(evalI64Mul());
}
#endif
#ifdef ENABLE_WASM_GC
case uint16_t(Op::GcPrefix): {
switch (op.b1) {
case uint16_t(GcOp::RttCanon): {
uint32_t typeIndex;
if (!d.readTypeIndex(&typeIndex)) {
return false;
}
CHECK(evalRttCanon(cx, typeIndex));
break;
}
case uint16_t(GcOp::RttSub): {
uint32_t typeIndex;
if (!d.readTypeIndex(&typeIndex)) {
return false;
}
CHECK(evalRttSub(cx, typeIndex));
break;
}
default: {
MOZ_CRASH();
}
}
break;
}
#endif
default: {
MOZ_CRASH();

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

@ -1266,22 +1266,6 @@ bool Instance::initElems(uint32_t tableIndex, const ElemSegment& seg,
return int32_t(ref->isRuntimeSubtype(rtt));
}
/* static */ void* Instance::rttSub(Instance* instance, void* rttParentPtr,
void* rttSubCanonPtr) {
MOZ_ASSERT(SASigRttSub.failureMode == FailureMode::FailOnNullPtr);
JSContext* cx = instance->cx();
ASSERT_ANYREF_IS_JSOBJECT;
Rooted<RttValue*> parentRtt(
cx, &AnyRef::fromCompiledCode(rttParentPtr).asJSObject()->as<RttValue>());
Rooted<RttValue*> subCanonRtt(
cx,
&AnyRef::fromCompiledCode(rttSubCanonPtr).asJSObject()->as<RttValue>());
Rooted<RttValue*> subRtt(cx, RttValue::rttSub(cx, parentRtt, subCanonRtt));
return AnyRef::fromJSObject(subRtt.get()).forCompiledCode();
}
/* static */ int32_t Instance::intrI8VecMul(Instance* instance, uint32_t dest,
uint32_t src1, uint32_t src2,
uint32_t len, uint8_t* memBase) {
@ -2241,38 +2225,6 @@ bool Instance::constantRefFunc(uint32_t funcIndex,
return true;
}
bool Instance::constantRttCanon(JSContext* cx, uint32_t sourceTypeIndex,
MutableHandle<RttValue*> result) {
// Get the renumbered type index from the source type index
uint32_t renumberedTypeIndex = metadata().typesRenumbering[sourceTypeIndex];
// The original type definition cannot have been a function type, so it
// could not have been an immediate type
MOZ_ASSERT(renumberedTypeIndex != UINT32_MAX);
// Get the TypeIdDesc to find the canonical RttValue
const TypeDefWithId& typeDef = metadata().types[renumberedTypeIndex];
MOZ_ASSERT(typeDef.isStructType() || typeDef.isArrayType());
// Cast from untyped storage to RttValue
result.set(*(RttValue**)addressOfTypeId(typeDef.id));
return true;
}
bool Instance::constantRttSub(JSContext* cx, Handle<RttValue*> parentRtt,
uint32_t sourceChildTypeIndex,
MutableHandle<RttValue*> result) {
Rooted<RttValue*> subCanonRtt(cx, nullptr);
// Get the canonical rtt value from the child type index, this is used to
// memoize results of rtt.sub
if (!constantRttCanon(cx, sourceChildTypeIndex, &subCanonRtt)) {
return false;
}
result.set(RttValue::rttSub(cx, parentRtt, subCanonRtt));
if (!result) {
ReportOutOfMemory(cx);
return false;
}
return true;
}
JSAtom* Instance::getFuncDisplayAtom(JSContext* cx, uint32_t funcIndex) const {
// The "display name" of a function is primarily shown in Error.stack which
// also includes location, so use getFuncNameBeforeLocation.

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

@ -339,11 +339,6 @@ class alignas(16) Instance {
[[nodiscard]] bool constantRefFunc(uint32_t funcIndex,
MutableHandleFuncRef result);
[[nodiscard]] bool constantRttCanon(JSContext* cx, uint32_t sourceTypeIndex,
MutableHandle<RttValue*> result);
[[nodiscard]] bool constantRttSub(JSContext* cx, Handle<RttValue*> parentRtt,
uint32_t sourceChildTypeIndex,
MutableHandle<RttValue*> result);
// Return the name associated with a given function index, or generate one
// if none was given by the module.
@ -455,8 +450,6 @@ class alignas(16) Instance {
static int32_t throwException(Instance* instance, JSObject* exn);
static void* arrayNew(Instance* instance, uint32_t length, void* arrayDescr);
static int32_t refTest(Instance* instance, void* refPtr, void* rttPtr);
static void* rttSub(Instance* instance, void* rttParentPtr,
void* rttSubCanonPtr);
static int32_t intrI8VecMul(Instance* instance, uint32_t dest, uint32_t src1,
uint32_t src2, uint32_t len, uint8_t* memBase);
};

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

@ -337,7 +337,6 @@ class FunctionCompiler {
case ValType::F64:
ins = MConstant::New(alloc(), DoubleValue(0.0), MIRType::Double);
break;
case ValType::Rtt:
case ValType::Ref:
ins = MWasmNullConstant::New(alloc());
break;
@ -1939,7 +1938,6 @@ class FunctionCompiler {
def = MWasmFloatRegisterResult::New(alloc(), MIRType::Double,
result.fpr());
break;
case wasm::ValType::Rtt:
case wasm::ValType::Ref:
def = MWasmRegisterResult::New(alloc(), MIRType::RefOrNull,
result.gpr());

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

@ -297,20 +297,20 @@ OpKind wasm::Classify(OpBytes op) {
case GcOp::Limit:
// Reject Limit for GcPrefix encoding
break;
case GcOp::StructNewWithRtt:
WASM_GC_OP(OpKind::StructNewWithRtt);
case GcOp::StructNewDefaultWithRtt:
WASM_GC_OP(OpKind::StructNewDefaultWithRtt);
case GcOp::StructNew:
WASM_GC_OP(OpKind::StructNew);
case GcOp::StructNewDefault:
WASM_GC_OP(OpKind::StructNewDefault);
case GcOp::StructGet:
case GcOp::StructGetS:
case GcOp::StructGetU:
WASM_GC_OP(OpKind::StructGet);
case GcOp::StructSet:
WASM_GC_OP(OpKind::StructSet);
case GcOp::ArrayNewWithRtt:
WASM_GC_OP(OpKind::ArrayNewWithRtt);
case GcOp::ArrayNewDefaultWithRtt:
WASM_GC_OP(OpKind::ArrayNewDefaultWithRtt);
case GcOp::ArrayNew:
WASM_GC_OP(OpKind::ArrayNew);
case GcOp::ArrayNewDefault:
WASM_GC_OP(OpKind::ArrayNewDefault);
case GcOp::ArrayGet:
case GcOp::ArrayGetS:
case GcOp::ArrayGetU:
@ -319,10 +319,6 @@ OpKind wasm::Classify(OpBytes op) {
WASM_GC_OP(OpKind::ArraySet);
case GcOp::ArrayLen:
WASM_GC_OP(OpKind::ArrayLen);
case GcOp::RttCanon:
WASM_GC_OP(OpKind::RttCanon);
case GcOp::RttSub:
WASM_GC_OP(OpKind::RttSub);
case GcOp::RefTest:
WASM_GC_OP(OpKind::RefTest);
case GcOp::RefCast:

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

@ -180,17 +180,15 @@ enum class OpKind {
RefFunc,
RefAsNonNull,
BrOnNull,
StructNewWithRtt,
StructNewDefaultWithRtt,
StructNew,
StructNewDefault,
StructGet,
StructSet,
ArrayNewWithRtt,
ArrayNewDefaultWithRtt,
ArrayNew,
ArrayNewDefault,
ArrayGet,
ArraySet,
ArrayLen,
RttCanon,
RttSub,
RefTest,
RefCast,
BrOnCast,
@ -368,10 +366,6 @@ class MOZ_STACK_CLASS OpIter : private Policy {
[[nodiscard]] bool popWithTypes(ValTypeSpanT expected, ValueVector* values);
[[nodiscard]] bool popWithRefType(Value* value, StackType* type);
[[nodiscard]] bool popWithFuncType(Value* value, FuncType** funcType);
[[nodiscard]] bool popWithRttType(Value* rtt, uint32_t* rttTypeIndex,
uint32_t* rttDepth);
[[nodiscard]] bool popWithRttType(Value* rtt, uint32_t rttTypeIndex,
uint32_t* rttDepth);
[[nodiscard]] bool popThenPushType(ResultType expected, ValueVector* values);
[[nodiscard]] bool topWithTypeAndPush(ResultType expected,
ValueVector* values);
@ -612,31 +606,23 @@ class MOZ_STACK_CLASS OpIter : private Policy {
[[nodiscard]] bool readTableSize(uint32_t* tableIndex);
#ifdef ENABLE_WASM_GC
[[nodiscard]] bool readStructNewWithRtt(uint32_t* typeIndex, Value* rtt,
ValueVector* argValues);
[[nodiscard]] bool readStructNewDefaultWithRtt(uint32_t* typeIndex,
Value* rtt);
[[nodiscard]] bool readStructNew(uint32_t* typeIndex, ValueVector* argValues);
[[nodiscard]] bool readStructNewDefault(uint32_t* typeIndex);
[[nodiscard]] bool readStructGet(uint32_t* typeIndex, uint32_t* fieldIndex,
FieldExtension extension, Value* ptr);
[[nodiscard]] bool readStructSet(uint32_t* typeIndex, uint32_t* fieldIndex,
Value* ptr, Value* val);
[[nodiscard]] bool readArrayNewWithRtt(uint32_t* typeIndex, Value* rtt,
Value* length, Value* argValue);
[[nodiscard]] bool readArrayNewDefaultWithRtt(uint32_t* typeIndex, Value* rtt,
Value* length);
[[nodiscard]] bool readArrayNew(uint32_t* typeIndex, Value* length,
Value* argValue);
[[nodiscard]] bool readArrayNewDefault(uint32_t* typeIndex, Value* length);
[[nodiscard]] bool readArrayGet(uint32_t* typeIndex, FieldExtension extension,
Value* index, Value* ptr);
[[nodiscard]] bool readArraySet(uint32_t* typeIndex, Value* val, Value* index,
Value* ptr);
[[nodiscard]] bool readArrayLen(uint32_t* typeIndex, Value* ptr);
[[nodiscard]] bool readRttCanon(ValType* rttType);
[[nodiscard]] bool readRttSub(Value* parentRtt, uint32_t* rttSubTypeIndex);
[[nodiscard]] bool readRefTest(Value* rtt, uint32_t* rttTypeIndex,
uint32_t* rttDepth, Value* ref);
[[nodiscard]] bool readRefCast(Value* rtt, uint32_t* rttTypeIndex,
uint32_t* rttDepth, Value* ref);
[[nodiscard]] bool readBrOnCast(uint32_t* relativeDepth, Value* rtt,
uint32_t* rttTypeIndex, uint32_t* rttDepth,
[[nodiscard]] bool readRefTest(uint32_t* typeIndex, Value* ref);
[[nodiscard]] bool readRefCast(uint32_t* typeIndex, Value* ref);
[[nodiscard]] bool readBrOnCast(uint32_t* relativeDepth, uint32_t* typeIndex,
ResultType* branchTargetType,
ValueVector* values);
#endif
@ -942,41 +928,6 @@ inline bool OpIter<Policy>::popWithFuncType(Value* value, FuncType** funcType) {
return true;
}
// This function pops exactly one value from the stack, checking that it is an
// rtt type with any type index or depth value.
template <typename Policy>
inline bool OpIter<Policy>::popWithRttType(Value* rtt, uint32_t* rttTypeIndex,
uint32_t* rttDepth) {
StackType type;
if (!popStackType(&type, rtt)) {
return false;
}
if (type.isBottom()) {
return fail("gc instruction temporarily not allowed in dead code");
}
if (type.valType().isRtt()) {
*rttTypeIndex = type.valType().typeIndex();
*rttDepth = type.valType().rttDepth();
return true;
}
UniqueChars actualText = ToString(type.valType());
if (!actualText) {
return false;
}
UniqueChars error(
JS_smprintf("type mismatch: expression has type %s but expected (rtt _)",
actualText.get()));
if (!error) {
return false;
}
return fail(error.get());
}
// This function is an optimization of the sequence:
// popWithType(ResultType, tmp)
// push(ResultType, tmp)
@ -2979,21 +2930,15 @@ inline bool OpIter<Policy>::readFieldIndex(uint32_t* fieldIndex,
#ifdef ENABLE_WASM_GC
template <typename Policy>
inline bool OpIter<Policy>::readStructNewWithRtt(uint32_t* typeIndex,
Value* rtt,
ValueVector* argValues) {
MOZ_ASSERT(Classify(op_) == OpKind::StructNewWithRtt);
inline bool OpIter<Policy>::readStructNew(uint32_t* typeIndex,
ValueVector* argValues) {
MOZ_ASSERT(Classify(op_) == OpKind::StructNew);
if (!readStructTypeIndex(typeIndex)) {
return false;
}
const StructType& str = env_.types->structType(*typeIndex);
const ValType rttType = ValType::fromRtt(*typeIndex, RttDepthNone);
if (!popWithType(rttType, rtt)) {
return false;
}
if (!argValues->resize(str.fields_.length())) {
return false;
@ -3011,20 +2956,14 @@ inline bool OpIter<Policy>::readStructNewWithRtt(uint32_t* typeIndex,
}
template <typename Policy>
inline bool OpIter<Policy>::readStructNewDefaultWithRtt(uint32_t* typeIndex,
Value* rtt) {
MOZ_ASSERT(Classify(op_) == OpKind::StructNewDefaultWithRtt);
inline bool OpIter<Policy>::readStructNewDefault(uint32_t* typeIndex) {
MOZ_ASSERT(Classify(op_) == OpKind::StructNewDefault);
if (!readStructTypeIndex(typeIndex)) {
return false;
}
const StructType& str = env_.types->structType(*typeIndex);
const ValType rttType = ValType::fromRtt(*typeIndex, RttDepthNone);
if (!popWithType(rttType, rtt)) {
return false;
}
if (!str.isDefaultable()) {
return fail("struct must be defaultable");
@ -3102,21 +3041,15 @@ inline bool OpIter<Policy>::readStructSet(uint32_t* typeIndex,
}
template <typename Policy>
inline bool OpIter<Policy>::readArrayNewWithRtt(uint32_t* typeIndex, Value* rtt,
Value* length,
Value* argValue) {
MOZ_ASSERT(Classify(op_) == OpKind::ArrayNewWithRtt);
inline bool OpIter<Policy>::readArrayNew(uint32_t* typeIndex, Value* length,
Value* argValue) {
MOZ_ASSERT(Classify(op_) == OpKind::ArrayNew);
if (!readArrayTypeIndex(typeIndex)) {
return false;
}
const ArrayType& arr = env_.types->arrayType(*typeIndex);
const ValType rttType = ValType::fromRtt(*typeIndex, RttDepthNone);
if (!popWithType(rttType, rtt)) {
return false;
}
if (!popWithType(ValType::I32, length)) {
return false;
@ -3130,21 +3063,15 @@ inline bool OpIter<Policy>::readArrayNewWithRtt(uint32_t* typeIndex, Value* rtt,
}
template <typename Policy>
inline bool OpIter<Policy>::readArrayNewDefaultWithRtt(uint32_t* typeIndex,
Value* rtt,
Value* length) {
MOZ_ASSERT(Classify(op_) == OpKind::ArrayNewDefaultWithRtt);
inline bool OpIter<Policy>::readArrayNewDefault(uint32_t* typeIndex,
Value* length) {
MOZ_ASSERT(Classify(op_) == OpKind::ArrayNewDefault);
if (!readArrayTypeIndex(typeIndex)) {
return false;
}
const ArrayType& arr = env_.types->arrayType(*typeIndex);
const ValType rttType = ValType::fromRtt(*typeIndex, RttDepthNone);
if (!popWithType(rttType, rtt)) {
return false;
}
if (!popWithType(ValType::I32, length)) {
return false;
@ -3236,81 +3163,38 @@ inline bool OpIter<Policy>::readArrayLen(uint32_t* typeIndex, Value* ptr) {
}
template <typename Policy>
inline bool OpIter<Policy>::readRttCanon(ValType* rttType) {
MOZ_ASSERT(Classify(op_) == OpKind::RttCanon);
uint32_t typeIndex;
if (!readGcTypeIndex(&typeIndex)) {
return false;
}
*rttType = ValType::fromRtt(typeIndex, 0);
return push(*rttType);
}
template <typename Policy>
inline bool OpIter<Policy>::readRttSub(Value* parentRtt,
uint32_t* rttSubTypeIndex) {
MOZ_ASSERT(Classify(op_) == OpKind::RttSub);
if (!readGcTypeIndex(rttSubTypeIndex)) {
return false;
}
uint32_t rttParentTypeIndex;
uint32_t rttParentDepth;
if (!popWithRttType(parentRtt, &rttParentTypeIndex, &rttParentDepth)) {
return false;
}
if (!checkIsSubtypeOf(*rttSubTypeIndex, rttParentTypeIndex)) {
return false;
}
uint32_t subRttDepth;
if (rttParentDepth == RttDepthNone) {
subRttDepth = RttDepthNone;
} else {
if (rttParentDepth >= MaxRttDepth) {
return fail("rtt depth is too deep");
}
subRttDepth = rttParentDepth + 1;
}
return push(ValType::fromRtt(*rttSubTypeIndex, subRttDepth));
}
template <typename Policy>
inline bool OpIter<Policy>::readRefTest(Value* rtt, uint32_t* rttTypeIndex,
uint32_t* rttDepth, Value* ref) {
inline bool OpIter<Policy>::readRefTest(uint32_t* typeIndex, Value* ref) {
MOZ_ASSERT(Classify(op_) == OpKind::RefTest);
if (!popWithRttType(rtt, rttTypeIndex, rttDepth)) {
if (!readGcTypeIndex(typeIndex)) {
return false;
}
if (!popWithType(RefType::eq(), ref)) {
return false;
}
return push(ValType(ValType::I32));
}
template <typename Policy>
inline bool OpIter<Policy>::readRefCast(Value* rtt, uint32_t* rttTypeIndex,
uint32_t* rttDepth, Value* ref) {
inline bool OpIter<Policy>::readRefCast(uint32_t* typeIndex, Value* ref) {
MOZ_ASSERT(Classify(op_) == OpKind::RefCast);
if (!popWithRttType(rtt, rttTypeIndex, rttDepth)) {
if (!readGcTypeIndex(typeIndex)) {
return false;
}
if (!popWithType(RefType::eq(), ref)) {
return false;
}
return push(RefType::fromTypeIndex(*rttTypeIndex, false));
return push(RefType::fromTypeIndex(*typeIndex, false));
}
template <typename Policy>
inline bool OpIter<Policy>::readBrOnCast(uint32_t* relativeDepth, Value* rtt,
uint32_t* rttTypeIndex,
uint32_t* rttDepth,
inline bool OpIter<Policy>::readBrOnCast(uint32_t* relativeDepth,
uint32_t* typeIndex,
ResultType* branchTargetType,
ValueVector* values) {
MOZ_ASSERT(Classify(op_) == OpKind::BrOnCast);
@ -3319,16 +3203,16 @@ inline bool OpIter<Policy>::readBrOnCast(uint32_t* relativeDepth, Value* rtt,
return fail("unable to read br_on_cast depth");
}
if (!popWithRttType(rtt, rttTypeIndex, rttDepth)) {
if (!readGcTypeIndex(typeIndex)) {
return false;
}
// The casted from type is any subtype of eqref
// The casted from type is any subtype of eqref.
ValType castedFromType(RefType::eq());
// The casted to type is a non-nullable reference to the type index specified
// by the input rtt on the stack
ValType castedToType(RefType::fromTypeIndex(*rttTypeIndex, false));
// The casted to type is a non-nullable reference to the type index
// specified as an immediate.
ValType castedToType(RefType::fromTypeIndex(*typeIndex, false));
return checkCastedBranchValueAndPush(*relativeDepth, castedFromType,
castedToType, branchTargetType, values);

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

@ -718,7 +718,7 @@ template <CoderMode mode>
CoderResult CodeSymbolicLinkArray(
Coder<mode>& coder,
CoderArg<mode, wasm::LinkData::SymbolicLinkArray> item) {
WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::LinkData::SymbolicLinkArray, 6984);
WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::LinkData::SymbolicLinkArray, 6912);
for (SymbolicAddress address :
mozilla::MakeEnumeratedRange(SymbolicAddress::Limit)) {
MOZ_TRY(CodePodVector(coder, &(*item)[address]));
@ -729,7 +729,7 @@ CoderResult CodeSymbolicLinkArray(
template <CoderMode mode>
CoderResult CodeLinkData(Coder<mode>& coder,
CoderArg<mode, wasm::LinkData> item) {
WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::LinkData, 7032);
WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::LinkData, 6960);
if constexpr (mode == MODE_ENCODE) {
MOZ_ASSERT(item->tier == Tier::Serialized);
}

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

@ -112,7 +112,6 @@ void ABIResultIter::settleRegister(ValType type) {
case ValType::F64:
cur_ = ABIResult(type, ReturnDoubleReg);
break;
case ValType::Rtt:
case ValType::Ref:
cur_ = ABIResult(type, ReturnReg);
break;
@ -519,7 +518,6 @@ static void StoreRegisterResult(MacroAssembler& masm, const FuncExport& fe,
masm.canonicalizeDouble(result.fpr());
masm.storeDouble(result.fpr(), Address(loc, 0));
break;
case ValType::Rtt:
case ValType::Ref:
masm.storePtr(result.gpr(), Address(loc, 0));
break;
@ -1344,7 +1342,6 @@ static bool GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex,
masm.setFramePushed(0);
break;
}
case ValType::Rtt:
case ValType::V128: {
MOZ_CRASH("unexpected return type when calling from ion to wasm");
}
@ -1647,7 +1644,6 @@ void wasm::GenerateDirectCallFromJit(MacroAssembler& masm, const FuncExport& fe,
MOZ_CRASH("unexpected return type when calling from ion to wasm");
}
break;
case wasm::ValType::Rtt:
case wasm::ValType::V128:
MOZ_CRASH("unexpected return type when calling from ion to wasm");
}
@ -2173,7 +2169,6 @@ static bool GenerateImportInterpExit(MacroAssembler& masm, const FuncImport& fi,
funcImportIndex);
GenPrintI64(DebugChannel::Import, masm, ReturnReg64);
break;
case ValType::Rtt:
case ValType::V128:
// Note, CallImport_Rtt/V128 currently always throws, so we should never
// reach this point.
@ -2383,7 +2378,6 @@ static bool GenerateImportJitExit(MacroAssembler& masm, const FuncImport& fi,
// No fastpath for now, go immediately to ool case
masm.jump(&oolConvert);
break;
case ValType::Rtt:
case ValType::V128:
// Unreachable as callImport should not call the stub.
masm.breakpoint();

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

@ -60,7 +60,6 @@ class ABIResult {
case ValType::F64:
MOZ_ASSERT(loc_ == Location::Fpr);
break;
case ValType::Rtt:
case ValType::Ref:
MOZ_ASSERT(loc_ == Location::Gpr);
break;

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

@ -465,8 +465,6 @@ static bool IsImmediateType(ValType vt) {
return false;
}
break;
case ValType::Rtt:
return false;
}
MOZ_CRASH("bad ValType");
}
@ -496,8 +494,6 @@ static unsigned EncodeImmediateType(ValType vt) {
break;
}
break;
case ValType::Rtt:
break;
}
MOZ_CRASH("bad ValType");
}

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

@ -653,22 +653,6 @@ class TypeContext : public AtomicRefCounted<TypeContext> {
return isRefEquivalent(first.refType(), second.refType(), cache);
}
#ifdef ENABLE_WASM_GC
// An rtt may be a equal to another rtt
if (first.isRtt() && second.isRtt()) {
// Equivalent rtts must both have depths or not have depths
if (first.hasRttDepth() != second.hasRttDepth()) {
return TypeResult::False;
}
// Equivalent rtts must have the same depth, if any
if (second.hasRttDepth() && first.rttDepth() != second.rttDepth()) {
return TypeResult::False;
}
return isTypeIndexEquivalent(first.typeIndex(), second.typeIndex(),
cache);
}
#endif
return TypeResult::False;
}
@ -705,23 +689,6 @@ class TypeContext : public AtomicRefCounted<TypeContext> {
return isRefSubtypeOf(subType.refType(), superType.refType(), cache);
}
// An rtt may be a subtype of another rtt
#ifdef ENABLE_WASM_GC
if (subType.isRtt() && superType.isRtt()) {
// A subtype must have a depth if the supertype has depth
if (!subType.hasRttDepth() && superType.hasRttDepth()) {
return TypeResult::False;
}
// A subtype must have the same depth as the supertype, if it has any
if (superType.hasRttDepth() &&
subType.rttDepth() != superType.rttDepth()) {
return TypeResult::False;
}
return isTypeIndexEquivalent(subType.typeIndex(), superType.typeIndex(),
cache);
}
#endif
return TypeResult::False;
}

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

@ -145,11 +145,6 @@ UniqueChars wasm::ToString(ValType type) {
break;
case ValType::Ref:
return ToString(type.refType());
case ValType::Rtt:
if (!type.hasRttDepth()) {
return JS_smprintf("(rtt %d)", type.typeIndex());
}
return JS_smprintf("(rtt %d %d)", type.rttDepth(), type.typeIndex());
}
return DuplicateString(literal);
}

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

@ -43,30 +43,24 @@ union PackedTypeCode {
static constexpr size_t TypeCodeBits = 8;
static constexpr size_t TypeIndexBits = 21;
static constexpr size_t NullableBits = 1;
static constexpr size_t RttDepthBits = 10;
static constexpr size_t PointerTagBits = 2;
#else
static constexpr size_t TypeCodeBits = 8;
static constexpr size_t TypeIndexBits = 14;
static constexpr size_t NullableBits = 1;
static constexpr size_t RttDepthBits = 7;
static constexpr size_t PointerTagBits = 2;
#endif
static_assert(TypeCodeBits + TypeIndexBits + NullableBits + RttDepthBits +
PointerTagBits <=
static_assert(TypeCodeBits + TypeIndexBits + NullableBits + PointerTagBits <=
(sizeof(PackedRepr) * 8),
"enough bits");
static_assert(MaxTypeIndex < (1 << TypeIndexBits), "enough bits");
static_assert(MaxRttDepth < (1 << RttDepthBits), "enough bits");
static_assert(RttDepthNone < (1 << RttDepthBits), "enough bits");
PackedRepr bits_;
struct {
PackedRepr typeCode_ : TypeCodeBits;
PackedRepr typeIndex_ : TypeIndexBits;
PackedRepr nullable_ : NullableBits;
PackedRepr rttDepth_ : RttDepthBits;
PackedRepr pointerTag_ : PointerTagBits;
};
@ -89,29 +83,25 @@ union PackedTypeCode {
}
static constexpr PackedTypeCode pack(TypeCode tc, uint32_t refTypeIndex,
bool isNullable, uint32_t rttDepth) {
bool isNullable) {
MOZ_ASSERT(uint32_t(tc) <= ((1 << TypeCodeBits) - 1));
MOZ_ASSERT_IF(tc != AbstractReferenceTypeIndexCode && tc != AbstractRttCode,
MOZ_ASSERT_IF(tc != AbstractReferenceTypeIndexCode,
refTypeIndex == NoTypeIndex);
MOZ_ASSERT_IF(tc == AbstractReferenceTypeIndexCode || tc == AbstractRttCode,
MOZ_ASSERT_IF(tc == AbstractReferenceTypeIndexCode,
refTypeIndex <= MaxTypeIndex);
MOZ_ASSERT_IF(tc != AbstractRttCode, rttDepth == 0);
MOZ_ASSERT_IF(tc == AbstractRttCode,
rttDepth <= MaxRttDepth || rttDepth == RttDepthNone);
PackedTypeCode ptc = {};
ptc.typeCode_ = PackedRepr(tc);
ptc.typeIndex_ = refTypeIndex;
ptc.nullable_ = isNullable;
ptc.rttDepth_ = rttDepth;
return ptc;
}
static constexpr PackedTypeCode pack(TypeCode tc, bool nullable) {
return pack(tc, PackedTypeCode::NoTypeIndex, nullable, 0);
return pack(tc, PackedTypeCode::NoTypeIndex, nullable);
}
static constexpr PackedTypeCode pack(TypeCode tc) {
return pack(tc, PackedTypeCode::NoTypeIndex, false, 0);
return pack(tc, PackedTypeCode::NoTypeIndex, false);
}
bool isValid() const { return typeCode_ != NoTypeCode; }
@ -136,14 +126,9 @@ union PackedTypeCode {
// what ValType needs, so that this decoding step is not necessary, but that
// moves complexity elsewhere, and the perf gain here would be only about 1%
// for baseline compilation throughput.
//
// TODO: with rtt types this is no longer a simple comparison, we should
// re-evaluate the performance of this function.
TypeCode typeCodeAbstracted() const {
TypeCode tc = typeCode();
return (tc < LowestPrimitiveTypeCode && tc != AbstractRttCode)
? AbstractReferenceTypeCode
: tc;
return tc < LowestPrimitiveTypeCode ? AbstractReferenceTypeCode : tc;
}
// Return whether this type is a reference type.
@ -151,8 +136,7 @@ union PackedTypeCode {
return typeCodeAbstracted() == AbstractReferenceTypeCode;
}
// Return whether this type is represented by a reference at runtime. This is
// any reference type along with rtts.
// Return whether this type is represented by a reference at runtime.
bool isRefRepr() const { return typeCode() < LowestPrimitiveTypeCode; }
uint32_t typeIndex() const {
@ -170,16 +154,6 @@ union PackedTypeCode {
return bool(nullable_);
}
bool hasRttDepth() const {
MOZ_ASSERT(isValid());
return uint32_t(rttDepth_) != RttDepthNone;
}
uint32_t rttDepth() const {
MOZ_ASSERT(isValid());
return uint32_t(rttDepth_);
}
PackedTypeCode asNonNullable() const {
MOZ_ASSERT(isRefType());
PackedTypeCode mutated = *this;
@ -246,7 +220,7 @@ class RefType {
RefType(uint32_t refTypeIndex, bool nullable)
: ptc_(PackedTypeCode::pack(AbstractReferenceTypeIndexCode, refTypeIndex,
nullable, 0)) {
nullable)) {
MOZ_ASSERT(isValid());
}
@ -310,7 +284,6 @@ class FieldTypeTraits {
F32 = uint8_t(TypeCode::F32),
F64 = uint8_t(TypeCode::F64),
V128 = uint8_t(TypeCode::V128),
Rtt = uint8_t(AbstractRttCode),
Ref = uint8_t(AbstractReferenceTypeCode),
};
@ -331,7 +304,6 @@ class FieldTypeTraits {
case TypeCode::ExternRef:
#ifdef ENABLE_WASM_GC
case TypeCode::EqRef:
case AbstractRttCode:
#endif
#ifdef ENABLE_WASM_FUNCTION_REFERENCES
case AbstractReferenceTypeIndexCode:
@ -351,7 +323,6 @@ class ValTypeTraits {
F32 = uint8_t(TypeCode::F32),
F64 = uint8_t(TypeCode::F64),
V128 = uint8_t(TypeCode::V128),
Rtt = uint8_t(AbstractRttCode),
Ref = uint8_t(AbstractReferenceTypeCode),
};
@ -368,7 +339,6 @@ class ValTypeTraits {
case TypeCode::ExternRef:
#ifdef ENABLE_WASM_GC
case TypeCode::EqRef:
case AbstractRttCode:
#endif
#ifdef ENABLE_WASM_FUNCTION_REFERENCES
case AbstractReferenceTypeIndexCode:
@ -458,11 +428,6 @@ class PackedType : public T {
return PackedType(tc);
}
static PackedType fromRtt(uint32_t typeIndex, uint32_t rttDepth) {
return PackedType(
PackedTypeCode::pack(AbstractRttCode, typeIndex, false, rttDepth));
}
static PackedType fromBitsUnsafe(uint64_t bits) {
return PackedType(PackedTypeCode::fromBits(bits));
}
@ -492,8 +457,6 @@ class PackedType : public T {
return tc_.bits();
}
bool isRtt() const { return tc_.typeCode() == AbstractRttCode; }
bool isRefType() const {
MOZ_ASSERT(isValid());
return tc_.isRefType();
@ -518,14 +481,14 @@ class PackedType : public T {
// Returns whether the type has a default value.
bool isDefaultable() const {
MOZ_ASSERT(isValid());
return !(isRtt() || (isRefType() && !isNullable()));
return !(isRefType() && !isNullable());
}
// Returns whether the type has a representation in JS.
bool isExposable() const {
MOZ_ASSERT(isValid());
#if defined(ENABLE_WASM_SIMD) || defined(ENABLE_WASM_GC)
return !(kind() == Kind::V128 || isRtt() || isTypeIndex());
return !(kind() == Kind::V128 || isTypeIndex());
#else
return true;
#endif
@ -541,16 +504,6 @@ class PackedType : public T {
return tc_.typeIndex();
}
bool hasRttDepth() const {
MOZ_ASSERT(isValid());
return tc_.hasRttDepth();
}
uint32_t rttDepth() const {
MOZ_ASSERT(isValid());
return tc_.rttDepth();
}
Kind kind() const {
MOZ_ASSERT(isValid());
return Kind(tc_.typeCodeAbstracted());
@ -607,7 +560,6 @@ class PackedType : public T {
return 8;
case TypeCode::V128:
return 16;
case AbstractRttCode:
case AbstractReferenceTypeCode:
return sizeof(void*);
default:
@ -701,7 +653,6 @@ static inline unsigned SizeOf(ValType vt) {
return 8;
case ValType::V128:
return 16;
case ValType::Rtt:
case ValType::Ref:
return sizeof(intptr_t);
}
@ -725,7 +676,6 @@ static inline jit::MIRType ToMIRType(ValType vt) {
return jit::MIRType::Double;
case ValType::V128:
return jit::MIRType::Simd128;
case ValType::Rtt:
case ValType::Ref:
return jit::MIRType::RefOrNull;
}

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

@ -555,15 +555,14 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env,
return iter.unrecognizedOpcode(&op);
}
switch (op.b1) {
case uint32_t(GcOp::StructNewWithRtt): {
case uint32_t(GcOp::StructNew): {
uint32_t unusedUint;
NothingVector unusedArgs{};
CHECK(
iter.readStructNewWithRtt(&unusedUint, &nothing, &unusedArgs));
CHECK(iter.readStructNew(&unusedUint, &unusedArgs));
}
case uint32_t(GcOp::StructNewDefaultWithRtt): {
case uint32_t(GcOp::StructNewDefault): {
uint32_t unusedUint;
CHECK(iter.readStructNewDefaultWithRtt(&unusedUint, &nothing));
CHECK(iter.readStructNewDefault(&unusedUint));
}
case uint32_t(GcOp::StructGet): {
uint32_t unusedUint1, unusedUint2;
@ -585,15 +584,13 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env,
CHECK(iter.readStructSet(&unusedUint1, &unusedUint2, &nothing,
&nothing));
}
case uint32_t(GcOp::ArrayNewWithRtt): {
case uint32_t(GcOp::ArrayNew): {
uint32_t unusedUint;
CHECK(iter.readArrayNewWithRtt(&unusedUint, &nothing, &nothing,
&nothing));
CHECK(iter.readArrayNew(&unusedUint, &nothing, &nothing));
}
case uint32_t(GcOp::ArrayNewDefaultWithRtt): {
case uint32_t(GcOp::ArrayNewDefault): {
uint32_t unusedUint;
CHECK(iter.readArrayNewDefaultWithRtt(&unusedUint, &nothing,
&nothing));
CHECK(iter.readArrayNewDefault(&unusedUint, &nothing));
}
case uint32_t(GcOp::ArrayGet): {
uint32_t unusedUint1;
@ -619,32 +616,18 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env,
uint32_t unusedUint1;
CHECK(iter.readArrayLen(&unusedUint1, &nothing));
}
case uint16_t(GcOp::RttCanon): {
ValType unusedTy;
CHECK(iter.readRttCanon(&unusedTy));
}
case uint16_t(GcOp::RttSub): {
uint32_t unusedRttTypeIndex;
CHECK(iter.readRttSub(&nothing, &unusedRttTypeIndex));
}
case uint16_t(GcOp::RefTest): {
uint32_t unusedRttTypeIndex;
uint32_t unusedRttDepth;
CHECK(iter.readRefTest(&nothing, &unusedRttTypeIndex,
&unusedRttDepth, &nothing));
uint32_t typeIndex;
CHECK(iter.readRefTest(&typeIndex, &nothing));
}
case uint16_t(GcOp::RefCast): {
uint32_t unusedRttTypeIndex;
uint32_t unusedRttDepth;
CHECK(iter.readRefCast(&nothing, &unusedRttTypeIndex,
&unusedRttDepth, &nothing));
uint32_t typeIndex;
CHECK(iter.readRefCast(&typeIndex, &nothing));
}
case uint16_t(GcOp::BrOnCast): {
uint32_t unusedRelativeDepth;
uint32_t unusedRttTypeIndex;
uint32_t unusedRttDepth;
CHECK(iter.readBrOnCast(&unusedRelativeDepth, &nothing,
&unusedRttTypeIndex, &unusedRttDepth,
uint32_t typeIndex;
CHECK(iter.readBrOnCast(&unusedRelativeDepth, &typeIndex,
&unusedType, &nothings));
}
default:

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

@ -53,7 +53,6 @@ Val::Val(const LitVal& val) {
case ValType::V128:
cell_.v128_ = val.v128();
return;
case ValType::Rtt:
case ValType::Ref:
cell_.ref_ = val.ref();
return;
@ -370,8 +369,6 @@ bool wasm::ToWebAssemblyValue(JSContext* cx, HandleValue val, FieldType type,
return ToWebAssemblyValue_f64<Debug>(cx, val, (double*)loc, mustWrite64);
case FieldType::V128:
break;
case FieldType::Rtt:
break;
case FieldType::Ref:
#ifdef ENABLE_WASM_FUNCTION_REFERENCES
if (!type.isNullable() && val.isNull()) {
@ -507,8 +504,6 @@ bool wasm::ToJSValue(JSContext* cx, const void* src, FieldType type,
dst);
case FieldType::V128:
break;
case FieldType::Rtt:
break;
case FieldType::Ref:
switch (type.refTypeKind()) {
case RefType::Func:

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

@ -321,9 +321,6 @@ class LitVal {
cell_.ref_ = AnyRef::null();
break;
}
case ValType::Kind::Rtt: {
MOZ_CRASH("not defaultable");
}
}
}
@ -416,7 +413,6 @@ class MOZ_NON_PARAM Val : public LitVal {
return cell_.f64_ == rhs.cell_.f64_;
case ValType::V128:
return cell_.v128_ == rhs.cell_.v128_;
case ValType::Rtt:
case ValType::Ref:
return cell_.ref_ == rhs.cell_.ref_;
}

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

@ -16,6 +16,7 @@
#include <algorithm>
#include "Http2Push.h"
#include "nsHttp.h"
#include "nsHttpHandler.h"
#include "nsHttpTransaction.h"
#include "nsIHttpPushListener.h"
@ -83,7 +84,7 @@ Http2PushedStreamWrapper::~Http2PushedStreamWrapper() {
Http2PushedStream* Http2PushedStreamWrapper::GetStream() {
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
if (mStream) {
Http2Stream* stream = mStream;
Http2StreamBase* stream = mStream;
return static_cast<Http2PushedStream*>(stream);
}
return nullptr;
@ -92,7 +93,7 @@ Http2PushedStream* Http2PushedStreamWrapper::GetStream() {
void Http2PushedStreamWrapper::OnPushFailed() {
if (OnSocketThread()) {
if (mStream) {
Http2Stream* stream = mStream;
Http2StreamBase* stream = mStream;
static_cast<Http2PushedStream*>(stream)->OnPushFailed();
}
} else {
@ -109,10 +110,10 @@ void Http2PushedStreamWrapper::OnPushFailed() {
Http2PushedStream::Http2PushedStream(
Http2PushTransactionBuffer* aTransaction, Http2Session* aSession,
Http2Stream* aAssociatedStream, uint32_t aID,
Http2StreamBase* aAssociatedStream, uint32_t aID,
uint64_t aCurrentForegroundTabOuterContentWindowId)
: Http2Stream(aTransaction, aSession, 0,
aCurrentForegroundTabOuterContentWindowId),
: Http2StreamBase(aTransaction, aSession, 0,
aCurrentForegroundTabOuterContentWindowId),
mAssociatedTransaction(aAssociatedStream->Transaction()),
mBufferedPush(aTransaction) {
LOG3(("Http2PushedStream ctor this=%p 0x%X\n", this, aID));
@ -140,7 +141,7 @@ bool Http2PushedStream::GetPushComplete() { return mPushCompleted; }
nsresult Http2PushedStream::WriteSegments(nsAHttpSegmentWriter* writer,
uint32_t count,
uint32_t* countWritten) {
nsresult rv = Http2Stream::WriteSegments(writer, count, countWritten);
nsresult rv = Http2StreamBase::WriteSegments(writer, count, countWritten);
if (NS_SUCCEEDED(rv) && *countWritten) {
mLastRead = TimeStamp::Now();
}
@ -196,9 +197,9 @@ bool Http2PushedStream::TryOnPush() {
return true;
}
// side effect free static method to determine if Http2Stream implements
// side effect free static method to determine if Http2StreamBase implements
// nsIHttpPushListener
bool Http2PushedStream::TestOnPush(Http2Stream* stream) {
bool Http2PushedStream::TestOnPush(Http2StreamBase* stream) {
if (!stream) {
return false;
}
@ -234,9 +235,9 @@ nsresult Http2PushedStream::ReadSegments(nsAHttpSegmentReader* reader, uint32_t,
// the write side of a pushed transaction just involves manipulating a
// little state
SetSentFin(true);
Http2Stream::mRequestHeadersDone = 1;
Http2Stream::mOpenGenerated = 1;
Http2Stream::ChangeState(UPSTREAM_COMPLETE);
Http2StreamBase::mRequestHeadersDone = 1;
Http2StreamBase::mOpenGenerated = 1;
Http2StreamBase::ChangeState(UPSTREAM_COMPLETE);
} break;
case UPSTREAM_COMPLETE:
@ -265,7 +266,7 @@ void Http2PushedStream::AdjustInitialWindow() {
("Http2PushStream::AdjustInitialWindow %p 0x%X "
"calling super consumer %p 0x%X\n",
this, mStreamID, mConsumerStream, mConsumerStream->StreamID()));
Http2Stream::AdjustInitialWindow();
Http2StreamBase::AdjustInitialWindow();
// Http2PushedStream::ReadSegments is needed to call TransmitFrame()
// and actually get this information into the session bytestream
RefPtr<Http2Session> session = Session();
@ -275,7 +276,7 @@ void Http2PushedStream::AdjustInitialWindow() {
// anyway, so we're good to go.
}
void Http2PushedStream::SetConsumerStream(Http2Stream* consumer) {
void Http2PushedStream::SetConsumerStream(Http2StreamBase* consumer) {
LOG3(("Http2PushedStream::SetConsumerStream this=%p consumer=%p", this,
consumer));
@ -290,7 +291,7 @@ bool Http2PushedStream::GetHashKey(nsCString& key) {
return true;
}
void Http2PushedStream::ConnectPushedStream(Http2Stream* stream) {
void Http2PushedStream::ConnectPushedStream(Http2StreamBase* stream) {
RefPtr<Http2Session> session = Session();
session->ConnectPushedStream(stream);
}
@ -359,6 +360,50 @@ void Http2PushedStream::TopBrowsingContextIdChanged(uint64_t id) {
}
}
// ConvertPushHeaders is used to convert the pushed request headers
// into HTTP/1 format and report some telemetry
nsresult Http2PushedStream::ConvertPushHeaders(Http2Decompressor* decompressor,
nsACString& aHeadersIn,
nsACString& aHeadersOut) {
nsresult rv = decompressor->DecodeHeaderBlock(
reinterpret_cast<const uint8_t*>(aHeadersIn.BeginReading()),
aHeadersIn.Length(), aHeadersOut, true);
if (NS_FAILED(rv)) {
LOG3(("Http2PushedStream::ConvertPushHeaders %p Error\n", this));
return rv;
}
nsCString method;
decompressor->GetHost(mHeaderHost);
decompressor->GetScheme(mHeaderScheme);
decompressor->GetPath(mHeaderPath);
if (mHeaderHost.IsEmpty() || mHeaderScheme.IsEmpty() ||
mHeaderPath.IsEmpty()) {
LOG3(
("Http2PushedStream::ConvertPushHeaders %p Error - missing required "
"host=%s scheme=%s path=%s\n",
this, mHeaderHost.get(), mHeaderScheme.get(), mHeaderPath.get()));
return NS_ERROR_ILLEGAL_VALUE;
}
decompressor->GetMethod(method);
if (!method.EqualsLiteral("GET")) {
LOG3(
("Http2PushedStream::ConvertPushHeaders %p Error - method not "
"supported: "
"%s\n",
this, method.get()));
return NS_ERROR_NOT_IMPLEMENTED;
}
aHeadersIn.Truncate();
LOG(("id 0x%X decoded push headers %s %s %s are:\n%s", mStreamID,
mHeaderScheme.get(), mHeaderHost.get(), mHeaderPath.get(),
aHeadersOut.BeginReading()));
return NS_OK;
}
//////////////////////////////////////////
// Http2PushTransactionBuffer
// This is the nsAHttpTransction owned by the stream when the pushed
@ -434,7 +479,7 @@ nsresult Http2PushTransactionBuffer::WriteSegments(nsAHttpSegmentWriter* writer,
}
if (Available() || mIsDone) {
Http2Stream* consumer = mPushStream->GetConsumerStream();
Http2StreamBase* consumer = mPushStream->GetConsumerStream();
if (consumer) {
LOG3(

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

@ -10,7 +10,7 @@
// https://www.rfc-editor.org/rfc/rfc7540.txt
#include "Http2Session.h"
#include "Http2Stream.h"
#include "Http2StreamBase.h"
#include "mozilla/Attributes.h"
#include "mozilla/TimeStamp.h"
@ -25,22 +25,23 @@ namespace net {
class Http2PushTransactionBuffer;
class Http2PushedStream final : public Http2Stream {
class Http2PushedStream final : public Http2StreamBase {
public:
Http2PushedStream(Http2PushTransactionBuffer* aTransaction,
Http2Session* aSession, Http2Stream* aAssociatedStream,
Http2Session* aSession, Http2StreamBase* aAssociatedStream,
uint32_t aID,
uint64_t aCurrentForegroundTabOuterContentWindowId);
Http2PushedStream* GetHttp2PushedStream() override { return this; }
bool GetPushComplete();
// The consumer stream is the synthetic pull stream hooked up to this push
virtual Http2Stream* GetConsumerStream() override { return mConsumerStream; };
Http2StreamBase* GetConsumerStream() { return mConsumerStream; };
void SetConsumerStream(Http2Stream* consumer);
void SetConsumerStream(Http2StreamBase* consumer);
[[nodiscard]] bool GetHashKey(nsCString& key);
// override of Http2Stream
// override of Http2StreamBase
[[nodiscard]] nsresult ReadSegments(nsAHttpSegmentReader*, uint32_t,
uint32_t*) override;
[[nodiscard]] nsresult WriteSegments(nsAHttpSegmentWriter*, uint32_t,
@ -48,10 +49,10 @@ class Http2PushedStream final : public Http2Stream {
void AdjustInitialWindow() override;
nsIRequestContext* RequestContext() override { return mRequestContext; };
void ConnectPushedStream(Http2Stream* stream);
void ConnectPushedStream(Http2StreamBase* stream);
[[nodiscard]] bool TryOnPush();
[[nodiscard]] static bool TestOnPush(Http2Stream* stream);
[[nodiscard]] static bool TestOnPush(Http2StreamBase* stream);
virtual bool DeferCleanup(nsresult status) override;
void SetDeferCleanupOnSuccess(bool val) { mDeferCleanupOnSuccess = val; }
@ -65,19 +66,22 @@ class Http2PushedStream final : public Http2Stream {
[[nodiscard]] nsresult GetBufferedData(char* buf, uint32_t count,
uint32_t* countWritten);
// overload of Http2Stream
// overload of Http2StreamBase
virtual bool HasSink() override { return !!mConsumerStream; }
virtual void SetPushComplete() override { mPushCompleted = true; }
void SetPushComplete() { mPushCompleted = true; }
virtual void TopBrowsingContextIdChanged(uint64_t) override;
nsCString& GetRequestString() { return mRequestString; }
nsCString& GetResourceUrl() { return mResourceUrl; }
nsresult ConvertPushHeaders(Http2Decompressor* decompressor,
nsACString& aHeadersIn, nsACString& aHeadersOut);
private:
virtual ~Http2PushedStream() = default;
// paired request stream that consumes from real http/2 one.. null until a
// match is made.
Http2Stream* mConsumerStream{nullptr};
Http2StreamBase* mConsumerStream{nullptr};
nsCOMPtr<nsIRequestContext> mRequestContext;
@ -152,7 +156,7 @@ class Http2PushedStreamWrapper : public nsISupports {
nsCString mRequestString;
nsCString mResourceUrl;
uint32_t mStreamID;
WeakPtr<Http2Stream> mStream;
WeakPtr<Http2StreamBase> mStream;
};
} // namespace net

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

@ -18,6 +18,9 @@
#include "AltServiceChild.h"
#include "Http2Session.h"
#include "Http2Stream.h"
#include "Http2StreamBase.h"
#include "Http2StreamTunnel.h"
#include "Http2StreamWebSocket.h"
#include "Http2Push.h"
#include "mozilla/EndianUtils.h"
@ -56,8 +59,8 @@ NS_INTERFACE_MAP_BEGIN(Http2Session)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsAHttpConnection)
NS_INTERFACE_MAP_END
static void RemoveStreamFromQueue(Http2Stream* aStream,
nsTArray<WeakPtr<Http2Stream>>& queue) {
static void RemoveStreamFromQueue(Http2StreamBase* aStream,
nsTArray<WeakPtr<Http2StreamBase>>& queue) {
for (const auto& stream : Reversed(queue)) {
if (stream == aStream) {
queue.RemoveElement(stream);
@ -65,15 +68,15 @@ static void RemoveStreamFromQueue(Http2Stream* aStream,
}
}
static void AddStreamToQueue(Http2Stream* aStream,
nsTArray<WeakPtr<Http2Stream>>& queue) {
static void AddStreamToQueue(Http2StreamBase* aStream,
nsTArray<WeakPtr<Http2StreamBase>>& queue) {
if (!queue.Contains(aStream)) {
queue.AppendElement(aStream);
}
}
static already_AddRefed<Http2Stream> GetNextStreamFromQueue(
nsTArray<WeakPtr<Http2Stream>>& queue) {
static already_AddRefed<Http2StreamBase> GetNextStreamFromQueue(
nsTArray<WeakPtr<Http2StreamBase>>& queue) {
while (!queue.IsEmpty() && !queue[0]) {
MOZ_ASSERT(false);
queue.RemoveElementAt(0);
@ -82,7 +85,7 @@ static already_AddRefed<Http2Stream> GetNextStreamFromQueue(
return nullptr;
}
RefPtr<Http2Stream> stream = queue[0].get();
RefPtr<Http2StreamBase> stream = queue[0].get();
queue.RemoveElementAt(0);
return stream.forget();
}
@ -257,7 +260,7 @@ inline nsresult Http2Session::SessionError(enum errorType reason) {
return NS_ERROR_NET_HTTP2_SENT_GOAWAY;
}
void Http2Session::LogIO(Http2Session* self, Http2Stream* stream,
void Http2Session::LogIO(Http2Session* self, Http2StreamBase* stream,
const char* label, const char* data,
uint32_t datalen) {
if (!LOG5_ENABLED()) return;
@ -401,7 +404,8 @@ uint32_t Http2Session::ReadTimeoutTick(PRIntervalTime now) {
return 1; // run the tick aggressively while ping is outstanding
}
uint32_t Http2Session::RegisterStreamID(Http2Stream* stream, uint32_t aNewID) {
uint32_t Http2Session::RegisterStreamID(Http2StreamBase* stream,
uint32_t aNewID) {
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
MOZ_ASSERT(mNextStreamID < 0xfffffff0,
"should have stopped admitting streams");
@ -568,14 +572,37 @@ bool Http2Session::AddStream(nsAHttpTransaction* aHttpTransaction,
return true;
}
RefPtr<Http2Stream> refStream = new Http2Stream(
aHttpTransaction, this, aPriority, mCurrentTopBrowsingContextId);
CreateStream(aHttpTransaction, aPriority, Http2StreamBaseType::Normal);
return true;
}
void Http2Session::CreateStream(nsAHttpTransaction* aHttpTransaction,
int32_t aPriority,
Http2StreamBaseType streamType) {
RefPtr<Http2StreamBase> refStream;
switch (streamType) {
case Http2StreamBaseType::Normal:
refStream = new Http2Stream(aHttpTransaction, this, aPriority,
mCurrentTopBrowsingContextId);
break;
case Http2StreamBaseType::Tunnel:
refStream = new Http2StreamTunnel(aHttpTransaction, this, aPriority,
mCurrentTopBrowsingContextId);
break;
case Http2StreamBaseType::WebSocket:
refStream = new Http2StreamWebSocket(aHttpTransaction, this, aPriority,
mCurrentTopBrowsingContextId);
break;
case Http2StreamBaseType::ServerPush:
MOZ_RELEASE_ASSERT(false);
return;
}
LOG3(("Http2Session::AddStream session=%p stream=%p serial=%" PRIu64 " "
"NextID=0x%X (tentative)",
this, refStream.get(), mSerial, mNextStreamID));
RefPtr<Http2Stream> stream = refStream;
RefPtr<Http2StreamBase> stream = refStream;
mStreamTransactionHash.InsertOrUpdate(aHttpTransaction, std::move(refStream));
AddStreamToQueue(stream, mReadyForWrite);
@ -595,11 +622,9 @@ bool Http2Session::AddStream(nsAHttpTransaction* aHttpTransaction,
this, aHttpTransaction));
DontReuse();
}
return true;
}
void Http2Session::QueueStream(Http2Stream* stream) {
void Http2Session::QueueStream(Http2StreamBase* stream) {
// will be removed via processpending or a shutdown path
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
MOZ_ASSERT(!stream->CountAsActive());
@ -621,7 +646,7 @@ void Http2Session::QueueStream(Http2Stream* stream) {
void Http2Session::ProcessPending() {
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
RefPtr<Http2Stream> stream;
RefPtr<Http2StreamBase> stream;
while (RoomForMoreConcurrent() &&
(stream = GetNextStreamFromQueue(mQueuedStreams))) {
LOG3(("Http2Session::ProcessPending %p stream %p woken from queue.", this,
@ -765,7 +790,7 @@ void Http2Session::ResetDownstreamState() {
// return true if activated (and counted against max)
// otherwise return false and queue
bool Http2Session::TryToActivate(Http2Stream* aStream) {
bool Http2Session::TryToActivate(Http2StreamBase* aStream) {
if (aStream->Queued()) {
LOG3(("Http2Session::TryToActivate %p stream=%p already queued.\n", this,
aStream));
@ -788,7 +813,7 @@ bool Http2Session::TryToActivate(Http2Stream* aStream) {
return true;
}
void Http2Session::IncrementConcurrent(Http2Stream* stream) {
void Http2Session::IncrementConcurrent(Http2StreamBase* stream) {
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
MOZ_ASSERT(!stream->StreamID() || (stream->StreamID() & 1),
"Do not activate pushed streams");
@ -849,7 +874,7 @@ template void Http2Session::CreateFrameHeader(uint8_t* dest,
uint8_t frameFlags,
uint32_t streamID);
void Http2Session::MaybeDecrementConcurrent(Http2Stream* aStream) {
void Http2Session::MaybeDecrementConcurrent(Http2StreamBase* aStream) {
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
LOG3(("MaybeDecrementConcurrent %p id=0x%X concurrent=%d active=%d\n", this,
aStream->StreamID(), mConcurrent, aStream->CountAsActive()));
@ -928,7 +953,7 @@ void Http2Session::GenerateRstStream(uint32_t aStatusCode, uint32_t aID) {
// make sure we don't do this twice for the same stream (at least if we
// have a stream entry for it)
Http2Stream* stream = mStreamIDHash.Get(aID);
Http2StreamBase* stream = mStreamIDHash.Get(aID);
if (stream) {
if (stream->SentReset()) return;
stream->SetSentReset(true);
@ -1143,7 +1168,7 @@ void Http2Session::CreatePriorityNode(uint32_t streamID, uint32_t dependsOn,
// perform a bunch of integrity checks on the stream.
// returns true if passed, false (plus LOG and ABORT) if failed.
bool Http2Session::VerifyStream(Http2Stream* aStream,
bool Http2Session::VerifyStream(Http2StreamBase* aStream,
uint32_t aOptionalID = 0) {
// This is annoying, but at least it is O(1)
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
@ -1169,7 +1194,7 @@ bool Http2Session::VerifyStream(Http2Stream* aStream,
if (mStreamTransactionHash.GetWeak(trans) != aStream) break;
if (aStream->StreamID()) {
Http2Stream* idStream = mStreamIDHash.Get(aStream->StreamID());
Http2StreamBase* idStream = mStreamIDHash.Get(aStream->StreamID());
test++;
if (idStream != aStream) break;
@ -1195,7 +1220,7 @@ bool Http2Session::VerifyStream(Http2Stream* aStream,
#endif // DEBUG
}
void Http2Session::CleanupStream(Http2Stream* aStream, nsresult aResult,
void Http2Session::CleanupStream(Http2StreamBase* aStream, nsresult aResult,
errorType aResetCode) {
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
LOG3(("Http2Session::CleanupStream %p %p 0x%X %" PRIX32 "\n", this, aStream,
@ -1204,13 +1229,17 @@ void Http2Session::CleanupStream(Http2Stream* aStream, nsresult aResult,
return;
}
Http2PushedStream* pushSource = aStream->PushSource();
if (pushSource) {
// aStream is a synthetic attached to an even push
MOZ_ASSERT(pushSource->GetConsumerStream() == aStream);
MOZ_ASSERT(!aStream->StreamID());
MOZ_ASSERT(!(pushSource->StreamID() & 0x1));
aStream->ClearPushSource();
Http2PushedStream* pushSource = nullptr;
Http2Stream* h2Stream = aStream->GetHttp2Stream();
if (h2Stream) {
pushSource = h2Stream->PushSource();
if (pushSource) {
// aStream is a synthetic attached to an even push
MOZ_ASSERT(pushSource->GetConsumerStream() == aStream);
MOZ_ASSERT(!aStream->StreamID());
MOZ_ASSERT(!(pushSource->StreamID() & 0x1));
h2Stream->ClearPushSource();
}
}
if (aStream->DeferCleanup(aResult)) {
@ -1265,7 +1294,7 @@ void Http2Session::CleanupStream(Http2Stream* aStream, nsresult aResult,
RemoveStreamFromQueues(aStream);
// removing from the stream transaction hash will
// delete the Http2Stream and drop the reference to
// delete the Http2StreamBase and drop the reference to
// its transaction
mStreamTransactionHash.Remove(aStream->Transaction());
@ -1280,7 +1309,7 @@ void Http2Session::CleanupStream(Http2Stream* aStream, nsresult aResult,
void Http2Session::CleanupStream(uint32_t aID, nsresult aResult,
errorType aResetCode) {
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
Http2Stream* stream = mStreamIDHash.Get(aID);
Http2StreamBase* stream = mStreamIDHash.Get(aID);
LOG3(("Http2Session::CleanupStream %p by ID 0x%X to stream %p\n", this, aID,
stream));
if (!stream) {
@ -1289,14 +1318,14 @@ void Http2Session::CleanupStream(uint32_t aID, nsresult aResult,
CleanupStream(stream, aResult, aResetCode);
}
void Http2Session::RemoveStreamFromQueues(Http2Stream* aStream) {
void Http2Session::RemoveStreamFromQueues(Http2StreamBase* aStream) {
RemoveStreamFromQueue(aStream, mReadyForWrite);
RemoveStreamFromQueue(aStream, mQueuedStreams);
RemoveStreamFromQueue(aStream, mPushesReadyForRead);
RemoveStreamFromQueue(aStream, mSlowConsumersReadyForRead);
}
void Http2Session::CloseStream(Http2Stream* aStream, nsresult aResult) {
void Http2Session::CloseStream(Http2StreamBase* aStream, nsresult aResult) {
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
LOG3(("Http2Session::CloseStream %p %p 0x%x %" PRIX32 "\n", this, aStream,
aStream->StreamID(), static_cast<uint32_t>(aResult)));
@ -1313,7 +1342,7 @@ void Http2Session::CloseStream(Http2Stream* aStream, nsresult aResult) {
RemoveStreamFromQueues(aStream);
if (aStream->IsTunnel()) {
UnRegisterTunnel(aStream);
UnRegisterTunnel(static_cast<Http2StreamTunnel*>(aStream));
}
// Send the stream the close() indication
@ -1533,7 +1562,7 @@ nsresult Http2Session::ResponseHeadersComplete() {
// The stream needs to see flattened http headers
// Uncompressed http/2 format headers currently live in
// Http2Stream::mDecompressBuffer - convert that to HTTP format in
// Http2StreamBase::mDecompressBuffer - convert that to HTTP format in
// mFlatHTTPResponseHeaders via ConvertHeaders()
nsresult rv;
@ -1822,7 +1851,7 @@ nsresult Http2Session::RecvPushPromise(Http2Session* self) {
nsresult rv = self->SetInputFrameDataStream(associatedID);
if (NS_FAILED(rv)) return rv;
Http2Stream* associatedStream = self->mInputFrameDataStream;
Http2StreamBase* associatedStream = self->mInputFrameDataStream;
++(self->mServerPushedResources);
// Anytime we start using the high bit of stream ID (either client or server)
@ -1964,7 +1993,7 @@ nsresult Http2Session::RecvPushPromise(Http2Session* self) {
// is for a client initiated stream. Errors that aren't fatal to the
// whole session must call cleanupStream() after this point in order
// to remove the stream from that hash.
WeakPtr<Http2Stream> pushedWeak = pushedStream.get();
WeakPtr<Http2StreamBase> pushedWeak = pushedStream.get();
self->mStreamTransactionHash.InsertOrUpdate(transactionBuffer,
std::move(pushedStream));
self->mPushedStreams.AppendElement(
@ -1999,7 +2028,7 @@ nsresult Http2Session::RecvPushPromise(Http2Session* self) {
LOG3(("Http2Session::RecvPushPromise %p origin check %s", self,
pushedWeak->Origin().get()));
nsCOMPtr<nsIURI> pushedOrigin;
rv = Http2Stream::MakeOriginURL(pushedWeak->Origin(), pushedOrigin);
rv = MakeOriginURL(pushedWeak->Origin(), pushedOrigin);
nsAutoCString pushedHostName;
int32_t pushedPort = -1;
if (NS_SUCCEEDED(rv)) {
@ -2060,7 +2089,7 @@ nsresult Http2Session::RecvPushPromise(Http2Session* self) {
// generally ok off the main thread), since we're not using the protocol
// handler to create any URIs, this will work just fine here. Don't try this
// at home, though, kids. I'm a trained professional.
if (NS_SUCCEEDED(Http2Stream::MakeOriginURL(spec, pushedURL))) {
if (NS_SUCCEEDED(MakeOriginURL(spec, pushedURL))) {
LOG3(("Http2Session::RecvPushPromise %p check disk cache for entry",
self));
mozilla::OriginAttributes oa;
@ -2094,8 +2123,8 @@ nsresult Http2Session::RecvPushPromise(Http2Session* self) {
return NS_OK;
}
pushedWeak->SetHTTPState(Http2Stream::RESERVED_BY_REMOTE);
static_assert(Http2Stream::kWorstPriority >= 0,
pushedWeak->SetHTTPState(Http2StreamBase::RESERVED_BY_REMOTE);
static_assert(Http2StreamBase::kWorstPriority >= 0,
"kWorstPriority out of range");
uint32_t priorityDependency = pushedWeak->PriorityDependency();
uint8_t priorityWeight = pushedWeak->PriorityWeight();
@ -2177,8 +2206,8 @@ nsresult Http2Session::RecvGoAway(Http2Session* self) {
// Process the streams marked for deletion and restart.
size_t size = self->mGoAwayStreamsToRestart.GetSize();
for (size_t count = 0; count < size; ++count) {
Http2Stream* stream =
static_cast<Http2Stream*>(self->mGoAwayStreamsToRestart.PopFront());
Http2StreamBase* stream =
static_cast<Http2StreamBase*>(self->mGoAwayStreamsToRestart.PopFront());
if (self->mPeerGoAwayReason == HTTP_1_1_REQUIRED) {
stream->Transaction()->DisableSpdy();
@ -2639,7 +2668,7 @@ nsresult Http2Session::RecvOrigin(Http2Session* self) {
self->mInputFrameBuffer.get() + kFrameHeaderBytes + offset + 2,
originLen);
offset += originLen + 2;
if (NS_FAILED(Http2Stream::MakeOriginURL(originString, originURL))) {
if (NS_FAILED(MakeOriginURL(originString, originURL))) {
LOG3(
("Http2Session::RecvOrigin %p origin frame string %s failed to "
"parse\n",
@ -2732,13 +2761,13 @@ void Http2Session::OnTransportStatus(nsITransport* aTransport, nsresult aStatus,
//
// There is no good way to map it to the right transaction in http/2,
// so it is ignored here and generated separately when the request
// is sent from Http2Stream::TransmitFrame
// is sent from Http2StreamBase::TransmitFrame
// NS_NET_STATUS_WAITING_FOR:
// Created by nsHttpConnection when the request has been totally sent.
// There is no good way to map it to the right transaction in http/2,
// so it is ignored here and generated separately when the same
// condition is complete in Http2Stream when there is no more
// condition is complete in Http2StreamBase when there is no more
// request body left to be transmitted.
// NS_NET_STATUS_RECEIVING_FROM
@ -2781,7 +2810,7 @@ nsresult Http2Session::ReadSegmentsAgain(nsAHttpSegmentReader* reader,
LOG3(("Http2Session::ReadSegments %p", this));
RefPtr<Http2Stream> stream = GetNextStreamFromQueue(mReadyForWrite);
RefPtr<Http2StreamBase> stream = GetNextStreamFromQueue(mReadyForWrite);
if (!stream) {
LOG3(("Http2Session %p could not identify a stream to write; suspending.",
@ -2807,8 +2836,10 @@ nsresult Http2Session::ReadSegmentsAgain(nsAHttpSegmentReader* reader,
uint32_t earlyDataUsed = 0;
if (mAttemptingEarlyData) {
if (!stream->Do0RTT()) {
LOG3(("Http2Session %p will not get early data from Http2Stream %p 0x%X",
this, stream.get(), stream->StreamID()));
LOG3(
("Http2Session %p will not get early data from Http2StreamBase %p "
"0x%X",
this, stream.get(), stream->StreamID()));
FlushOutputQueue();
SetWriteCallbacks();
if (!mCannotDo0RTTStreams.Contains(stream)) {
@ -2829,7 +2860,7 @@ nsresult Http2Session::ReadSegmentsAgain(nsAHttpSegmentReader* reader,
}
LOG3(
("Http2Session %p will write from Http2Stream %p 0x%X "
("Http2Session %p will write from Http2StreamBase %p 0x%X "
"block-input=%d block-output=%d\n",
this, stream.get(), stream->StreamID(), stream->RequestBlockedOnRead(),
stream->BlockedOnRwin()));
@ -3034,7 +3065,7 @@ nsresult Http2Session::WriteSegmentsAgain(nsAHttpSegmentWriter* writer,
// If there are http transactions attached to a push stream with filled
// buffers trigger that data pump here. This only reads from buffers (not the
// network) so mDownstreamState doesn't matter.
RefPtr<Http2Stream> pushConnectedStream =
RefPtr<Http2StreamBase> pushConnectedStream =
GetNextStreamFromQueue(mPushesReadyForRead);
if (pushConnectedStream) {
return ProcessConnectedPush(pushConnectedStream, writer, count,
@ -3043,7 +3074,7 @@ nsresult Http2Session::WriteSegmentsAgain(nsAHttpSegmentWriter* writer,
// feed gecko channels that previously stopped consuming data
// only take data from stored buffers
RefPtr<Http2Stream> slowConsumer =
RefPtr<Http2StreamBase> slowConsumer =
GetNextStreamFromQueue(mSlowConsumersReadyForRead);
if (slowConsumer) {
internalStateType savedState = mDownstreamState;
@ -3274,7 +3305,7 @@ nsresult Http2Session::WriteSegmentsAgain(nsAHttpSegmentWriter* writer,
}
// mInputFrameDataStream is reset by ChangeDownstreamState
Http2Stream* stream = mInputFrameDataStream;
Http2StreamBase* stream = mInputFrameDataStream;
ResetDownstreamState();
LOG3(
("Http2Session::WriteSegments cleanup stream on recv of rst "
@ -3382,7 +3413,7 @@ nsresult Http2Session::WriteSegmentsAgain(nsAHttpSegmentWriter* writer,
mInputFrameDataRead += *countWritten;
if (mInputFrameDataRead == mInputFrameDataSize) {
Http2Stream* streamToCleanup = nullptr;
Http2StreamBase* streamToCleanup = nullptr;
if (mInputFrameFinal) {
streamToCleanup = mInputFrameDataStream;
}
@ -3392,11 +3423,12 @@ nsresult Http2Session::WriteSegmentsAgain(nsAHttpSegmentWriter* writer,
ResetDownstreamState();
if (streamToCleanup) {
if (discardedPadding && !(streamToCleanup->StreamID() & 1)) {
Http2PushedStream* pushed = streamToCleanup->GetHttp2PushedStream();
if (discardedPadding && pushed) {
// Pushed streams are special on padding-only final data frames.
// See bug 1409570 comments 6-8 for details.
streamToCleanup->SetPushComplete();
Http2Stream* pushSink = streamToCleanup->GetConsumerStream();
pushed->SetPushComplete();
Http2StreamBase* pushSink = pushed->GetConsumerStream();
if (pushSink) {
bool enqueueSink = true;
for (const auto& s : mPushesReadyForRead) {
@ -3528,10 +3560,9 @@ nsresult Http2Session::Finish0RTT(bool aRestart, bool aAlpnChanged) {
return NS_OK;
}
nsresult Http2Session::ProcessConnectedPush(Http2Stream* pushConnectedStream,
nsAHttpSegmentWriter* writer,
uint32_t count,
uint32_t* countWritten) {
nsresult Http2Session::ProcessConnectedPush(
Http2StreamBase* pushConnectedStream, nsAHttpSegmentWriter* writer,
uint32_t count, uint32_t* countWritten) {
LOG3(("Http2Session::ProcessConnectedPush %p 0x%X\n", this,
pushConnectedStream->StreamID()));
mSegmentWriter = writer;
@ -3540,8 +3571,10 @@ nsresult Http2Session::ProcessConnectedPush(Http2Stream* pushConnectedStream,
// The pipe in nsHttpTransaction rewrites CLOSED error codes into OK
// so we need this check to determine the truth.
if (NS_SUCCEEDED(rv) && !*countWritten && pushConnectedStream->PushSource() &&
pushConnectedStream->PushSource()->GetPushComplete()) {
Http2Stream* h2Stream = pushConnectedStream->GetHttp2Stream();
MOZ_ASSERT(h2Stream);
if (NS_SUCCEEDED(rv) && !*countWritten && h2Stream &&
h2Stream->PushSource() && h2Stream->PushSource()->GetPushComplete()) {
rv = NS_BASE_STREAM_CLOSED;
}
@ -3560,7 +3593,7 @@ nsresult Http2Session::ProcessConnectedPush(Http2Stream* pushConnectedStream,
return rv;
}
nsresult Http2Session::ProcessSlowConsumer(Http2Stream* slowConsumer,
nsresult Http2Session::ProcessSlowConsumer(Http2StreamBase* slowConsumer,
nsAHttpSegmentWriter* writer,
uint32_t count,
uint32_t* countWritten) {
@ -3593,7 +3626,7 @@ nsresult Http2Session::ProcessSlowConsumer(Http2Stream* slowConsumer,
return rv;
}
void Http2Session::UpdateLocalStreamWindow(Http2Stream* stream,
void Http2Session::UpdateLocalStreamWindow(Http2StreamBase* stream,
uint32_t bytes) {
if (!stream) { // this is ok - it means there was a data frame for a rst
// stream
@ -3701,7 +3734,7 @@ void Http2Session::UpdateLocalSessionWindow(uint32_t bytes) {
// dont flush here, this write can commonly be coalesced with others
}
void Http2Session::UpdateLocalRwin(Http2Stream* stream, uint32_t bytes) {
void Http2Session::UpdateLocalRwin(Http2StreamBase* stream, uint32_t bytes) {
// make sure there is room for 2 window updates even though
// we may not generate any.
EnsureOutputBuffer(2 * (kFrameHeaderBytes + 4));
@ -3792,7 +3825,7 @@ void Http2Session::CloseTransaction(nsAHttpTransaction* aTransaction,
// Generally this arrives as a cancel event from the connection manager.
// need to find the stream and call CleanupStream() on it.
RefPtr<Http2Stream> stream = mStreamTransactionHash.Get(aTransaction);
RefPtr<Http2StreamBase> stream = mStreamTransactionHash.Get(aTransaction);
if (!stream) {
LOG3(("Http2Session::CloseTransaction %p %p %" PRIx32 " - not found.", this,
aTransaction, static_cast<uint32_t>(aResult)));
@ -4018,12 +4051,12 @@ void Http2Session::SetNeedsCleanup() {
ResetDownstreamState();
}
void Http2Session::ConnectPushedStream(Http2Stream* stream) {
void Http2Session::ConnectPushedStream(Http2StreamBase* stream) {
AddStreamToQueue(stream, mPushesReadyForRead);
Unused << ForceRecv();
}
void Http2Session::ConnectSlowConsumer(Http2Stream* stream) {
void Http2Session::ConnectSlowConsumer(Http2StreamBase* stream) {
LOG3(("Http2Session::ConnectSlowConsumer %p 0x%X\n", this,
stream->StreamID()));
AddStreamToQueue(stream, mSlowConsumersReadyForRead);
@ -4039,15 +4072,15 @@ uint32_t Http2Session::FindTunnelCount(nsCString const& aHashKey) {
return rv;
}
void Http2Session::RegisterTunnel(Http2Stream* aTunnel) {
void Http2Session::RegisterTunnel(Http2StreamTunnel* aTunnel) {
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
nsCString const& regKey = aTunnel->RegistrationKey();
const uint32_t newcount = ++mTunnelHash.LookupOrInsert(regKey, 0);
LOG3(("Http2Stream::RegisterTunnel %p stream=%p tunnels=%d [%s]", this,
LOG3(("Http2StreamBase::RegisterTunnel %p stream=%p tunnels=%d [%s]", this,
aTunnel, newcount, regKey.get()));
}
void Http2Session::UnRegisterTunnel(Http2Stream* aTunnel) {
void Http2Session::UnRegisterTunnel(Http2StreamTunnel* aTunnel) {
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
nsCString const& regKey = aTunnel->RegistrationKey();
auto entry = mTunnelHash.Lookup(regKey);
@ -4071,13 +4104,12 @@ void Http2Session::CreateTunnel(nsHttpTransaction* trans,
RefPtr<nsHttpConnectionInfo> clone(ci->Clone());
RefPtr<Http2ConnectTransaction> connectTrans = new Http2ConnectTransaction(
clone, aCallbacks, trans->Caps(), trans, this, false);
DebugOnly<bool> rv =
AddStream(connectTrans, nsISupportsPriority::PRIORITY_NORMAL, false,
false, nullptr);
MOZ_ASSERT(rv);
RefPtr<Http2Stream> tunnel = mStreamTransactionHash.Get(connectTrans);
CreateStream(connectTrans, nsISupportsPriority::PRIORITY_NORMAL,
Http2StreamBaseType::Tunnel);
RefPtr<Http2StreamBase> tunnel = mStreamTransactionHash.Get(connectTrans);
MOZ_ASSERT(tunnel);
RegisterTunnel(tunnel);
RegisterTunnel(static_cast<Http2StreamTunnel*>(tunnel.get()));
}
void Http2Session::DispatchOnTunnel(nsAHttpTransaction* aHttpTransaction,
@ -4279,7 +4311,7 @@ void Http2Session::TransactionHasDataToWrite(nsAHttpTransaction* caller) {
// a trapped signal from the http transaction to the connection that
// it is no longer blocked on read.
RefPtr<Http2Stream> stream = mStreamTransactionHash.Get(caller);
RefPtr<Http2StreamBase> stream = mStreamTransactionHash.Get(caller);
if (!stream || !VerifyStream(stream)) {
LOG3(("Http2Session::TransactionHasDataToWrite %p caller %p not found",
this, caller));
@ -4311,7 +4343,7 @@ void Http2Session::TransactionHasDataToRecv(nsAHttpTransaction* caller) {
// a signal from the http transaction to the connection that it will consume
// more
RefPtr<Http2Stream> stream = mStreamTransactionHash.Get(caller);
RefPtr<Http2StreamBase> stream = mStreamTransactionHash.Get(caller);
if (!stream || !VerifyStream(stream)) {
LOG3(("Http2Session::TransactionHasDataToRecv %p caller %p not found", this,
caller));
@ -4323,7 +4355,7 @@ void Http2Session::TransactionHasDataToRecv(nsAHttpTransaction* caller) {
ConnectSlowConsumer(stream);
}
void Http2Session::TransactionHasDataToWrite(Http2Stream* stream) {
void Http2Session::TransactionHasDataToWrite(Http2StreamBase* stream) {
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
LOG3(("Http2Session::TransactionHasDataToWrite %p stream=%p ID=0x%x", this,
stream, stream->StreamID()));
@ -4605,10 +4637,9 @@ void Http2Session::CreateWebsocketStream(
RefPtr<nsHttpConnectionInfo> clone(ci->Clone());
RefPtr<Http2ConnectTransaction> connectTrans = new Http2ConnectTransaction(
clone, aCallbacks, trans->Caps(), trans, this, true);
DebugOnly<bool> rv =
AddStream(connectTrans, nsISupportsPriority::PRIORITY_NORMAL, false,
false, nullptr);
MOZ_ASSERT(rv);
CreateStream(connectTrans, nsISupportsPriority::PRIORITY_NORMAL,
Http2StreamBaseType::WebSocket);
}
void Http2Session::ProcessWaitingWebsockets() {

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

@ -30,9 +30,12 @@ namespace mozilla {
namespace net {
class Http2PushedStream;
class Http2Stream;
class Http2StreamBase;
class Http2StreamTunnel;
class nsHttpTransaction;
enum Http2StreamBaseType { Normal, WebSocket, Tunnel, ServerPush };
// b23b147c-c4f8-4d6e-841a-09f29a010de7
#define NS_HTTP2SESSION_IID \
{ \
@ -78,7 +81,7 @@ class Http2Session final : public ASpdySession,
PRIntervalTime IdleTime() override;
// Registering with a newID of 0 means pick the next available odd ID
uint32_t RegisterStreamID(Http2Stream*, uint32_t aNewID = 0);
uint32_t RegisterStreamID(Http2StreamBase*, uint32_t aNewID = 0);
/*
HTTP/2 framing
@ -224,15 +227,15 @@ class Http2Session final : public ASpdySession,
uint8_t frameFlags, uint32_t streamID);
// For writing the data stream to LOG4
static void LogIO(Http2Session*, Http2Stream*, const char*, const char*,
static void LogIO(Http2Session*, Http2StreamBase*, const char*, const char*,
uint32_t);
// overload of nsAHttpConnection
void TransactionHasDataToWrite(nsAHttpTransaction*) override;
void TransactionHasDataToRecv(nsAHttpTransaction*) override;
// a similar version for Http2Stream
void TransactionHasDataToWrite(Http2Stream*);
// a similar version for Http2StreamBase
void TransactionHasDataToWrite(Http2StreamBase*);
// an overload of nsAHttpSegementReader
[[nodiscard]] virtual nsresult CommitToSegmentSize(
@ -245,9 +248,9 @@ class Http2Session final : public ASpdySession,
uint32_t GetServerInitialStreamWindow() { return mServerInitialStreamWindow; }
[[nodiscard]] bool TryToActivate(Http2Stream* stream);
void ConnectPushedStream(Http2Stream* stream);
void ConnectSlowConsumer(Http2Stream* stream);
[[nodiscard]] bool TryToActivate(Http2StreamBase* stream);
void ConnectPushedStream(Http2StreamBase* stream);
void ConnectSlowConsumer(Http2StreamBase* stream);
[[nodiscard]] nsresult ConfirmTLSProfile();
[[nodiscard]] static bool ALPNCallback(nsISupports* securityInfo);
@ -309,6 +312,9 @@ class Http2Session final : public ASpdySession,
static const uint8_t kMagicHello[24];
void CreateStream(nsAHttpTransaction* aHttpTransaction, int32_t aPriority,
Http2StreamBaseType streamType);
[[nodiscard]] nsresult ResponseHeadersComplete();
uint32_t GetWriteQueueSize();
void ChangeDownstreamState(enum internalStateType);
@ -320,38 +326,38 @@ class Http2Session final : public ASpdySession,
void GeneratePriority(uint32_t, uint8_t);
void GenerateRstStream(uint32_t, uint32_t);
void GenerateGoAway(uint32_t);
void CleanupStream(Http2Stream*, nsresult, errorType);
void CleanupStream(Http2StreamBase*, nsresult, errorType);
void CleanupStream(uint32_t, nsresult, errorType);
void CloseStream(Http2Stream*, nsresult);
void CloseStream(Http2StreamBase*, nsresult);
void SendHello();
void RemoveStreamFromQueues(Http2Stream*);
void RemoveStreamFromQueues(Http2StreamBase*);
[[nodiscard]] nsresult ParsePadding(uint8_t&, uint16_t&);
void SetWriteCallbacks();
void RealignOutputQueue();
void ProcessPending();
[[nodiscard]] nsresult ProcessConnectedPush(Http2Stream*,
[[nodiscard]] nsresult ProcessConnectedPush(Http2StreamBase*,
nsAHttpSegmentWriter*, uint32_t,
uint32_t*);
[[nodiscard]] nsresult ProcessSlowConsumer(Http2Stream*,
[[nodiscard]] nsresult ProcessSlowConsumer(Http2StreamBase*,
nsAHttpSegmentWriter*, uint32_t,
uint32_t*);
[[nodiscard]] nsresult SetInputFrameDataStream(uint32_t);
void CreatePriorityNode(uint32_t, uint32_t, uint8_t, const char*);
char* CreatePriorityFrame(uint32_t, uint32_t, uint8_t);
bool VerifyStream(Http2Stream*, uint32_t);
bool VerifyStream(Http2StreamBase*, uint32_t);
void SetNeedsCleanup();
void UpdateLocalRwin(Http2Stream* stream, uint32_t bytes);
void UpdateLocalStreamWindow(Http2Stream* stream, uint32_t bytes);
void UpdateLocalRwin(Http2StreamBase* stream, uint32_t bytes);
void UpdateLocalStreamWindow(Http2StreamBase* stream, uint32_t bytes);
void UpdateLocalSessionWindow(uint32_t bytes);
void MaybeDecrementConcurrent(Http2Stream* stream);
void MaybeDecrementConcurrent(Http2StreamBase* stream);
bool RoomForMoreConcurrent();
void IncrementConcurrent(Http2Stream* stream);
void QueueStream(Http2Stream* stream);
void IncrementConcurrent(Http2StreamBase* stream);
void QueueStream(Http2StreamBase* stream);
// a wrapper for all calls to the nshttpconnection level segment writer. Used
// to track network I/O for timeout purposes
@ -388,14 +394,14 @@ class Http2Session final : public ASpdySession,
// There are also several lists of streams: ready to write, queued due to
// max parallelism, streams that need to force a read for push, and the full
// set of pushed streams.
nsTHashMap<nsUint32HashKey, Http2Stream*> mStreamIDHash;
nsRefPtrHashtable<nsPtrHashKey<nsAHttpTransaction>, Http2Stream>
nsTHashMap<nsUint32HashKey, Http2StreamBase*> mStreamIDHash;
nsRefPtrHashtable<nsPtrHashKey<nsAHttpTransaction>, Http2StreamBase>
mStreamTransactionHash;
nsTArray<WeakPtr<Http2Stream>> mReadyForWrite;
nsTArray<WeakPtr<Http2Stream>> mQueuedStreams;
nsTArray<WeakPtr<Http2Stream>> mPushesReadyForRead;
nsTArray<WeakPtr<Http2Stream>> mSlowConsumersReadyForRead;
nsTArray<WeakPtr<Http2StreamBase>> mReadyForWrite;
nsTArray<WeakPtr<Http2StreamBase>> mQueuedStreams;
nsTArray<WeakPtr<Http2StreamBase>> mPushesReadyForRead;
nsTArray<WeakPtr<Http2StreamBase>> mSlowConsumersReadyForRead;
nsTArray<Http2PushedStream*> mPushedStreams;
// Compression contexts for header transport.
@ -430,14 +436,14 @@ class Http2Session final : public ASpdySession,
// When a frame has been received that is addressed to a particular stream
// (e.g. a data frame after the stream-id has been decoded), this points
// to the stream.
Http2Stream* mInputFrameDataStream;
Http2StreamBase* mInputFrameDataStream;
// mNeedsCleanup is a state variable to defer cleanup of a closed stream
// If needed, It is set in session::OnWriteSegments() and acted on and
// cleared when the stack returns to session::WriteSegments(). The stream
// cannot be destroyed directly out of OnWriteSegments because
// stream::writeSegments() is on the stack at that time.
Http2Stream* mNeedsCleanup;
Http2StreamBase* mNeedsCleanup;
// This reason code in the last processed RESET frame
uint32_t mDownstreamRstReason;
@ -538,7 +544,7 @@ class Http2Session final : public ASpdySession,
bool mPreviousUsed; // true when backup is used
// used as a temporary buffer while enumerating the stream hash during GoAway
nsDeque<Http2Stream> mGoAwayStreamsToRestart;
nsDeque<Http2StreamBase> mGoAwayStreamsToRestart;
// Each session gets a unique serial number because the push cache is
// correlated by the load group and the serial number can be used as part of
@ -559,10 +565,10 @@ class Http2Session final : public ASpdySession,
bool mAttemptingEarlyData;
// The ID(s) of the stream(s) that we are getting 0RTT data from.
nsTArray<WeakPtr<Http2Stream>> m0RTTStreams;
nsTArray<WeakPtr<Http2StreamBase>> m0RTTStreams;
// The ID(s) of the stream(s) that are not able to send 0RTT data. We need to
// remember them put them into mReadyForWrite queue when 0RTT finishes.
nsTArray<WeakPtr<Http2Stream>> mCannotDo0RTTStreams;
nsTArray<WeakPtr<Http2StreamBase>> mCannotDo0RTTStreams;
bool RealJoinConnection(const nsACString& hostname, int32_t port,
bool justKidding);
@ -589,8 +595,8 @@ class Http2Session final : public ASpdySession,
void DispatchOnTunnel(nsAHttpTransaction*, nsIInterfaceRequestor*);
void CreateTunnel(nsHttpTransaction*, nsHttpConnectionInfo*,
nsIInterfaceRequestor*);
void RegisterTunnel(Http2Stream*);
void UnRegisterTunnel(Http2Stream*);
void RegisterTunnel(Http2StreamTunnel*);
void UnRegisterTunnel(Http2StreamTunnel*);
uint32_t FindTunnelCount(nsHttpConnectionInfo*);
uint32_t FindTunnelCount(nsCString const&);
nsTHashMap<nsCStringHashKey, uint32_t> mTunnelHash;

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -1,4 +1,5 @@
/* -*- 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/. */
@ -6,387 +7,35 @@
#ifndef mozilla_net_Http2Stream_h
#define mozilla_net_Http2Stream_h
// HTTP/2 - RFC7540
// https://www.rfc-editor.org/rfc/rfc7540.txt
#include "mozilla/Attributes.h"
#include "mozilla/UniquePtr.h"
#include "nsAHttpTransaction.h"
#include "nsISupportsPriority.h"
#include "SimpleBuffer.h"
#include "nsISupportsImpl.h"
#include "nsIURI.h"
class nsIInputStream;
class nsIOutputStream;
namespace mozilla {
class OriginAttributes;
}
#include "Http2StreamBase.h"
namespace mozilla::net {
class nsStandardURL;
class Http2Session;
class Http2Decompressor;
class Http2Stream : public nsAHttpSegmentReader,
public nsAHttpSegmentWriter,
public SupportsWeakPtr {
class Http2Stream : public Http2StreamBase {
public:
NS_DECL_NSAHTTPSEGMENTREADER
NS_DECL_NSAHTTPSEGMENTWRITER
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Http2Stream, override)
Http2Stream(nsAHttpTransaction* httpTransaction, Http2Session* session,
int32_t priority, uint64_t bcId)
: Http2StreamBase(httpTransaction, session, priority, bcId) {}
enum stateType {
IDLE,
RESERVED_BY_REMOTE,
OPEN,
CLOSED_BY_LOCAL,
CLOSED_BY_REMOTE,
CLOSED
};
void Close(nsresult reason) override;
Http2Stream* GetHttp2Stream() override { return this; }
uint32_t GetWireStreamId() override;
const static int32_t kNormalPriority = 0x1000;
const static int32_t kWorstPriority =
kNormalPriority + nsISupportsPriority::PRIORITY_LOWEST;
const static int32_t kBestPriority =
kNormalPriority + nsISupportsPriority::PRIORITY_HIGHEST;
nsresult OnWriteSegment(char* buf, uint32_t count,
uint32_t* countWritten) override;
Http2Stream(nsAHttpTransaction*, Http2Session*, int32_t, uint64_t);
uint32_t StreamID() { return mStreamID; }
nsresult CheckPushCache();
Http2PushedStream* PushSource() { return mPushSource; }
bool IsReadingFromPushStream();
void ClearPushSource();
stateType HTTPState() { return mState; }
void SetHTTPState(stateType val) { mState = val; }
[[nodiscard]] virtual nsresult ReadSegments(nsAHttpSegmentReader*, uint32_t,
uint32_t*);
[[nodiscard]] virtual nsresult WriteSegments(nsAHttpSegmentWriter*, uint32_t,
uint32_t*);
virtual bool DeferCleanup(nsresult status);
// The consumer stream is the synthetic pull stream hooked up to this stream
// http2PushedStream overrides it
virtual Http2Stream* GetConsumerStream() { return nullptr; };
const nsCString& Origin() const { return mOrigin; }
const nsCString& Host() const { return mHeaderHost; }
const nsCString& Path() const { return mHeaderPath; }
bool RequestBlockedOnRead() {
return static_cast<bool>(mRequestBlockedOnRead);
}
bool HasRegisteredID() { return mStreamID != 0; }
nsAHttpTransaction* Transaction() { return mTransaction; }
virtual nsIRequestContext* RequestContext() {
return mTransaction ? mTransaction->RequestContext() : nullptr;
}
void Close(nsresult reason);
void SetResponseIsComplete();
void SetRecvdFin(bool aStatus);
bool RecvdFin() { return mRecvdFin; }
void SetRecvdData(bool aStatus) { mReceivedData = aStatus ? 1 : 0; }
bool RecvdData() { return mReceivedData; }
void SetSentFin(bool aStatus);
bool SentFin() { return mSentFin; }
void SetRecvdReset(bool aStatus);
bool RecvdReset() { return mRecvdReset; }
void SetSentReset(bool aStatus);
bool SentReset() { return mSentReset; }
void SetQueued(bool aStatus) { mQueued = aStatus ? 1 : 0; }
bool Queued() { return mQueued; }
void SetCountAsActive(bool aStatus) { mCountAsActive = aStatus ? 1 : 0; }
bool CountAsActive() { return mCountAsActive; }
void SetAllHeadersReceived();
void UnsetAllHeadersReceived() { mAllHeadersReceived = 0; }
bool AllHeadersReceived() { return mAllHeadersReceived; }
void UpdateTransportSendEvents(uint32_t count);
void UpdateTransportReadEvents(uint32_t count);
// NS_ERROR_ABORT terminates stream, other failure terminates session
[[nodiscard]] nsresult ConvertResponseHeaders(Http2Decompressor*, nsACString&,
nsACString&, int32_t&);
[[nodiscard]] nsresult ConvertPushHeaders(Http2Decompressor*, nsACString&,
nsACString&);
[[nodiscard]] nsresult ConvertResponseTrailers(Http2Decompressor*,
nsACString&);
bool AllowFlowControlledWrite();
void UpdateServerReceiveWindow(int32_t delta);
int64_t ServerReceiveWindow() { return mServerReceiveWindow; }
void DecrementClientReceiveWindow(uint32_t delta) {
mClientReceiveWindow -= delta;
mLocalUnacked += delta;
}
void IncrementClientReceiveWindow(uint32_t delta) {
mClientReceiveWindow += delta;
mLocalUnacked -= delta;
}
uint64_t LocalUnAcked();
int64_t ClientReceiveWindow() { return mClientReceiveWindow; }
bool BlockedOnRwin() { return mBlockedOnRwin; }
uint32_t Priority() { return mPriority; }
uint32_t PriorityDependency() { return mPriorityDependency; }
uint8_t PriorityWeight() { return mPriorityWeight; }
void SetPriority(uint32_t);
void SetPriorityDependency(uint32_t, uint32_t);
void UpdatePriorityDependency();
uint64_t TransactionTabId() { return mTransactionTabId; }
// A pull stream has an implicit sink, a pushed stream has a sink
// once it is matched to a pull stream.
virtual bool HasSink() { return true; }
// This is a no-op on pull streams. Pushed streams override this.
virtual void SetPushComplete(){};
already_AddRefed<Http2Session> Session();
[[nodiscard]] static nsresult MakeOriginURL(const nsACString& origin,
nsCOMPtr<nsIURI>& url);
[[nodiscard]] static nsresult MakeOriginURL(const nsACString& scheme,
const nsACString& origin,
nsCOMPtr<nsIURI>& url);
// Mirrors nsAHttpTransaction
bool Do0RTT();
nsresult Finish0RTT(bool aRestart, bool aAlpnChanged);
nsresult GetOriginAttributes(mozilla::OriginAttributes* oa);
virtual void TopBrowsingContextIdChanged(uint64_t id);
void TopBrowsingContextIdChangedInternal(
uint64_t id); // For use by pushed streams only
protected:
virtual ~Http2Stream();
static void CreatePushHashKey(
const nsCString& scheme, const nsCString& hostHeader,
const mozilla::OriginAttributes& originAttributes, uint64_t serial,
const nsACString& pathInfo, nsCString& outOrigin, nsCString& outKey);
// These internal states track request generation
enum upstreamStateType {
GENERATING_HEADERS,
GENERATING_BODY,
SENDING_BODY,
SENDING_FIN_STREAM,
UPSTREAM_COMPLETE
};
uint32_t mStreamID;
// The session that this stream is a subset of
nsWeakPtr mSession;
// These are temporary state variables to hold the argument to
// Read/WriteSegments so it can be accessed by On(read/write)segment
// further up the stack.
RefPtr<nsAHttpSegmentReader> mSegmentReader;
nsAHttpSegmentWriter* mSegmentWriter;
nsCString mOrigin;
nsCString mHeaderHost;
nsCString mHeaderScheme;
nsCString mHeaderPath;
// Each stream goes from generating_headers to upstream_complete, perhaps
// looping on multiple instances of generating_body and
// sending_body for each frame in the upload.
enum upstreamStateType mUpstreamState;
// The HTTP/2 state for the stream from section 5.1
enum stateType mState;
// Flag is set when all http request headers have been read ID is not stable
uint32_t mRequestHeadersDone : 1;
// Flag is set when ID is stable and concurrency limits are met
uint32_t mOpenGenerated : 1;
// Flag is set when all http response headers have been read
uint32_t mAllHeadersReceived : 1;
// Flag is set when stream is queued inside the session due to
// concurrency limits being exceeded
uint32_t mQueued : 1;
void ChangeState(enum upstreamStateType);
virtual void AdjustInitialWindow();
[[nodiscard]] nsresult TransmitFrame(const char*, uint32_t*,
bool forceCommitment);
// The underlying socket transport object is needed to propogate some events
nsISocketTransport* mSocketTransport;
uint8_t mPriorityWeight = 0; // h2 weight
uint32_t mPriorityDependency = 0; // h2 stream id this one depends on
uint64_t mCurrentTopBrowsingContextId;
uint64_t mTransactionTabId;
~Http2Stream();
private:
friend class mozilla::DefaultDelete<Http2Stream>;
[[nodiscard]] nsresult ParseHttpRequestHeaders(const char*, uint32_t,
uint32_t*);
[[nodiscard]] nsresult GenerateOpen();
void AdjustPushedPriority();
void GenerateDataFrameHeader(uint32_t, bool);
[[nodiscard]] nsresult BufferInput(uint32_t, uint32_t*);
// The underlying HTTP transaction. This pointer is used as the key
// in the Http2Session mStreamTransactionHash so it is important to
// keep a reference to it as long as this stream is a member of that hash.
// (i.e. don't change it or release it after it is set in the ctor).
RefPtr<nsAHttpTransaction> mTransaction;
// The quanta upstream data frames are chopped into
uint32_t mChunkSize;
// Flag is set when the HTTP processor has more data to send
// but has blocked in doing so.
uint32_t mRequestBlockedOnRead : 1;
// Flag is set after the response frame bearing the fin bit has
// been processed. (i.e. after the server has closed).
uint32_t mRecvdFin : 1;
// Flag is set after 1st DATA frame has been passed to stream
uint32_t mReceivedData : 1;
// Flag is set after RST_STREAM has been received for this stream
uint32_t mRecvdReset : 1;
// Flag is set after RST_STREAM has been generated for this stream
uint32_t mSentReset : 1;
// Flag is set when stream is counted towards MAX_CONCURRENT streams in
// session
uint32_t mCountAsActive : 1;
// Flag is set when a FIN has been placed on a data or header frame
// (i.e after the client has closed)
uint32_t mSentFin : 1;
// Flag is set after the WAITING_FOR Transport event has been generated
uint32_t mSentWaitingFor : 1;
// Flag is set after TCP send autotuning has been disabled
uint32_t mSetTCPSocketBuffer : 1;
// Flag is set when OnWriteSegment is being called directly from stream
// instead of transaction
uint32_t mBypassInputBuffer : 1;
// The InlineFrame and associated data is used for composing control
// frames and data frame headers.
UniquePtr<uint8_t[]> mTxInlineFrame;
uint32_t mTxInlineFrameSize;
uint32_t mTxInlineFrameUsed;
// mTxStreamFrameSize tracks the progress of
// transmitting a request body data frame. The data frame itself
// is never copied into the spdy layer.
uint32_t mTxStreamFrameSize;
// Buffer for request header compression.
nsCString mFlatHttpRequestHeaders;
// Track the content-length of a request body so that we can
// place the fin flag on the last data packet instead of waiting
// for a stream closed indication. Relying on stream close results
// in an extra 0-length runt packet and seems to have some interop
// problems with the google servers. Connect does rely on stream
// close by setting this to the max value.
int64_t mRequestBodyLenRemaining;
uint32_t mPriority = 0; // geckoish weight
// mClientReceiveWindow, mServerReceiveWindow, and mLocalUnacked are for flow
// control. *window are signed because the race conditions in asynchronous
// SETTINGS messages can force them temporarily negative.
// mClientReceiveWindow is how much data the server will send without getting
// a
// window update
int64_t mClientReceiveWindow;
// mServerReceiveWindow is how much data the client is allowed to send without
// getting a window update
int64_t mServerReceiveWindow;
// LocalUnacked is the number of bytes received by the client but not
// yet reflected in a window update. Sending that update will increment
// ClientReceiveWindow
uint64_t mLocalUnacked;
// True when sending is suspended becuase the server receive window is
// <= 0
bool mBlockedOnRwin;
// For Progress Events
uint64_t mTotalSent;
uint64_t mTotalRead;
// For Http2Push
Http2PushedStream* mPushSource;
// Used to store stream data when the transaction channel cannot keep up
// and flow control has not yet kicked in.
SimpleBuffer mSimpleBuffer;
bool mAttempting0RTT;
/// connect tunnels
public:
bool IsTunnel() { return mIsTunnel; }
// TODO - remove as part of bug 1564120 fix?
// This method saves the key the tunnel was registered under, so that when the
// associated transaction connection info hash key changes, we still find it
// and decrement the correct item in the session's tunnel hash table.
nsCString& RegistrationKey();
private:
void ClearTransactionsBlockedOnTunnel();
void MapStreamToPlainText();
bool MapStreamToHttpConnection(const nsACString& aFlat407Headers,
int32_t aHttpResponseCode = -1);
bool mIsTunnel;
bool mPlainTextTunnel;
nsCString mRegistrationKey;
/// websockets
public:
bool IsWebsocket() { return mIsWebsocket; }
private:
bool mIsWebsocket;
void AdjustPushedPriority();
Http2PushedStream* mPushSource{nullptr};
};
} // namespace mozilla::net

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -0,0 +1,357 @@
/* -*- Mode: C++; tab-width: 8; 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_net_Http2StreamBase_h
#define mozilla_net_Http2StreamBase_h
// HTTP/2 - RFC7540
// https://www.rfc-editor.org/rfc/rfc7540.txt
#include "mozilla/Attributes.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/WeakPtr.h"
#include "nsAHttpTransaction.h"
#include "nsISupportsPriority.h"
#include "SimpleBuffer.h"
#include "nsISupportsImpl.h"
#include "nsIURI.h"
class nsISocketTransport;
class nsIInputStream;
class nsIOutputStream;
namespace mozilla {
class OriginAttributes;
}
namespace mozilla::net {
class nsStandardURL;
class Http2Session;
class Http2Stream;
class Http2PushedStream;
class Http2Decompressor;
class Http2StreamBase : public nsAHttpSegmentReader,
public nsAHttpSegmentWriter,
public SupportsWeakPtr {
public:
NS_DECL_NSAHTTPSEGMENTREADER
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Http2StreamBase, override)
enum stateType {
IDLE,
RESERVED_BY_REMOTE,
OPEN,
CLOSED_BY_LOCAL,
CLOSED_BY_REMOTE,
CLOSED
};
const static int32_t kNormalPriority = 0x1000;
const static int32_t kWorstPriority =
kNormalPriority + nsISupportsPriority::PRIORITY_LOWEST;
const static int32_t kBestPriority =
kNormalPriority + nsISupportsPriority::PRIORITY_HIGHEST;
Http2StreamBase(nsAHttpTransaction*, Http2Session*, int32_t, uint64_t);
uint32_t StreamID() { return mStreamID; }
stateType HTTPState() { return mState; }
void SetHTTPState(stateType val) { mState = val; }
[[nodiscard]] virtual nsresult ReadSegments(nsAHttpSegmentReader*, uint32_t,
uint32_t*);
[[nodiscard]] virtual nsresult WriteSegments(nsAHttpSegmentWriter*, uint32_t,
uint32_t*);
virtual bool DeferCleanup(nsresult status);
const nsCString& Origin() const { return mOrigin; }
const nsCString& Host() const { return mHeaderHost; }
const nsCString& Path() const { return mHeaderPath; }
bool RequestBlockedOnRead() {
return static_cast<bool>(mRequestBlockedOnRead);
}
bool HasRegisteredID() { return mStreamID != 0; }
nsAHttpTransaction* Transaction() { return mTransaction; }
virtual nsIRequestContext* RequestContext() {
return mTransaction ? mTransaction->RequestContext() : nullptr;
}
virtual void Close(nsresult reason);
void SetResponseIsComplete();
void SetRecvdFin(bool aStatus);
bool RecvdFin() { return mRecvdFin; }
void SetRecvdData(bool aStatus) { mReceivedData = aStatus ? 1 : 0; }
bool RecvdData() { return mReceivedData; }
void SetSentFin(bool aStatus);
bool SentFin() { return mSentFin; }
void SetRecvdReset(bool aStatus);
bool RecvdReset() { return mRecvdReset; }
void SetSentReset(bool aStatus);
bool SentReset() { return mSentReset; }
void SetQueued(bool aStatus) { mQueued = aStatus ? 1 : 0; }
bool Queued() { return mQueued; }
void SetCountAsActive(bool aStatus) { mCountAsActive = aStatus ? 1 : 0; }
bool CountAsActive() { return mCountAsActive; }
void SetAllHeadersReceived();
void UnsetAllHeadersReceived() { mAllHeadersReceived = 0; }
bool AllHeadersReceived() { return mAllHeadersReceived; }
void UpdateTransportSendEvents(uint32_t count);
void UpdateTransportReadEvents(uint32_t count);
// NS_ERROR_ABORT terminates stream, other failure terminates session
[[nodiscard]] nsresult ConvertResponseHeaders(Http2Decompressor*, nsACString&,
nsACString&, int32_t&);
[[nodiscard]] nsresult ConvertResponseTrailers(Http2Decompressor*,
nsACString&);
bool AllowFlowControlledWrite();
void UpdateServerReceiveWindow(int32_t delta);
int64_t ServerReceiveWindow() { return mServerReceiveWindow; }
void DecrementClientReceiveWindow(uint32_t delta) {
mClientReceiveWindow -= delta;
mLocalUnacked += delta;
}
void IncrementClientReceiveWindow(uint32_t delta) {
mClientReceiveWindow += delta;
mLocalUnacked -= delta;
}
uint64_t LocalUnAcked();
int64_t ClientReceiveWindow() { return mClientReceiveWindow; }
bool BlockedOnRwin() { return mBlockedOnRwin; }
uint32_t Priority() { return mPriority; }
uint32_t PriorityDependency() { return mPriorityDependency; }
uint8_t PriorityWeight() { return mPriorityWeight; }
void SetPriority(uint32_t);
void SetPriorityDependency(uint32_t, uint32_t);
void UpdatePriorityDependency();
uint64_t TransactionTabId() { return mTransactionTabId; }
// A pull stream has an implicit sink, a pushed stream has a sink
// once it is matched to a pull stream.
virtual bool HasSink() { return true; }
already_AddRefed<Http2Session> Session();
// Mirrors nsAHttpTransaction
bool Do0RTT();
nsresult Finish0RTT(bool aRestart, bool aAlpnChanged);
nsresult GetOriginAttributes(mozilla::OriginAttributes* oa);
virtual void TopBrowsingContextIdChanged(uint64_t id);
void TopBrowsingContextIdChangedInternal(
uint64_t id); // For use by pushed streams only
virtual bool IsTunnel() { return false; }
virtual uint32_t GetWireStreamId() { return mStreamID; }
virtual Http2Stream* GetHttp2Stream() { return nullptr; }
virtual Http2PushedStream* GetHttp2PushedStream() { return nullptr; }
[[nodiscard]] virtual nsresult OnWriteSegment(char*, uint32_t,
uint32_t*) override;
protected:
virtual ~Http2StreamBase();
virtual void HandleResponseHeaders(nsACString& aHeadersOut,
int32_t httpResponseCode) {}
// These internal states track request generation
enum upstreamStateType {
GENERATING_HEADERS,
GENERATING_BODY,
SENDING_BODY,
SENDING_FIN_STREAM,
UPSTREAM_COMPLETE
};
uint32_t mStreamID{0};
// The session that this stream is a subset of
nsWeakPtr mSession;
// These are temporary state variables to hold the argument to
// Read/WriteSegments so it can be accessed by On(read/write)segment
// further up the stack.
RefPtr<nsAHttpSegmentReader> mSegmentReader;
nsAHttpSegmentWriter* mSegmentWriter{nullptr};
nsCString mOrigin;
nsCString mHeaderHost;
nsCString mHeaderScheme;
nsCString mHeaderPath;
// Each stream goes from generating_headers to upstream_complete, perhaps
// looping on multiple instances of generating_body and
// sending_body for each frame in the upload.
enum upstreamStateType mUpstreamState { GENERATING_HEADERS };
// The HTTP/2 state for the stream from section 5.1
enum stateType mState { IDLE };
// Flag is set when all http request headers have been read ID is not stable
uint32_t mRequestHeadersDone : 1;
// Flag is set when ID is stable and concurrency limits are met
uint32_t mOpenGenerated : 1;
// Flag is set when all http response headers have been read
uint32_t mAllHeadersReceived : 1;
// Flag is set when stream is queued inside the session due to
// concurrency limits being exceeded
uint32_t mQueued : 1;
void ChangeState(enum upstreamStateType);
virtual void AdjustInitialWindow();
[[nodiscard]] nsresult TransmitFrame(const char*, uint32_t*,
bool forceCommitment);
// The underlying socket transport object is needed to propogate some events
nsISocketTransport* mSocketTransport;
uint8_t mPriorityWeight = 0; // h2 weight
uint32_t mPriorityDependency = 0; // h2 stream id this one depends on
uint64_t mCurrentTopBrowsingContextId;
uint64_t mTransactionTabId{0};
// The underlying HTTP transaction. This pointer is used as the key
// in the Http2Session mStreamTransactionHash so it is important to
// keep a reference to it as long as this stream is a member of that hash.
// (i.e. don't change it or release it after it is set in the ctor).
RefPtr<nsAHttpTransaction> mTransaction;
// The InlineFrame and associated data is used for composing control
// frames and data frame headers.
UniquePtr<uint8_t[]> mTxInlineFrame;
uint32_t mTxInlineFrameSize{0};
uint32_t mTxInlineFrameUsed{0};
uint32_t mPriority = 0; // geckoish weight
private:
friend class mozilla::DefaultDelete<Http2StreamBase>;
[[nodiscard]] nsresult ParseHttpRequestHeaders(const char*, uint32_t,
uint32_t*);
[[nodiscard]] nsresult GenerateOpen();
void GenerateDataFrameHeader(uint32_t, bool);
[[nodiscard]] nsresult BufferInput(uint32_t, uint32_t*);
// The quanta upstream data frames are chopped into
uint32_t mChunkSize;
// Flag is set when the HTTP processor has more data to send
// but has blocked in doing so.
uint32_t mRequestBlockedOnRead : 1;
// Flag is set after the response frame bearing the fin bit has
// been processed. (i.e. after the server has closed).
uint32_t mRecvdFin : 1;
// Flag is set after 1st DATA frame has been passed to stream
uint32_t mReceivedData : 1;
// Flag is set after RST_STREAM has been received for this stream
uint32_t mRecvdReset : 1;
// Flag is set after RST_STREAM has been generated for this stream
uint32_t mSentReset : 1;
// Flag is set when stream is counted towards MAX_CONCURRENT streams in
// session
uint32_t mCountAsActive : 1;
// Flag is set when a FIN has been placed on a data or header frame
// (i.e after the client has closed)
uint32_t mSentFin : 1;
// Flag is set after the WAITING_FOR Transport event has been generated
uint32_t mSentWaitingFor : 1;
// Flag is set after TCP send autotuning has been disabled
uint32_t mSetTCPSocketBuffer : 1;
// Flag is set when OnWriteSegment is being called directly from stream
// instead of transaction
uint32_t mBypassInputBuffer : 1;
// mTxStreamFrameSize tracks the progress of
// transmitting a request body data frame. The data frame itself
// is never copied into the spdy layer.
uint32_t mTxStreamFrameSize{0};
// Buffer for request header compression.
nsCString mFlatHttpRequestHeaders;
// Track the content-length of a request body so that we can
// place the fin flag on the last data packet instead of waiting
// for a stream closed indication. Relying on stream close results
// in an extra 0-length runt packet and seems to have some interop
// problems with the google servers. Connect does rely on stream
// close by setting this to the max value.
int64_t mRequestBodyLenRemaining{0};
// mClientReceiveWindow, mServerReceiveWindow, and mLocalUnacked are for flow
// control. *window are signed because the race conditions in asynchronous
// SETTINGS messages can force them temporarily negative.
// mClientReceiveWindow is how much data the server will send without getting
// a
// window update
int64_t mClientReceiveWindow;
// mServerReceiveWindow is how much data the client is allowed to send without
// getting a window update
int64_t mServerReceiveWindow;
// LocalUnacked is the number of bytes received by the client but not
// yet reflected in a window update. Sending that update will increment
// ClientReceiveWindow
uint64_t mLocalUnacked{0};
// True when sending is suspended becuase the server receive window is
// <= 0
bool mBlockedOnRwin{false};
// For Progress Events
uint64_t mTotalSent{0};
uint64_t mTotalRead{0};
// Used to store stream data when the transaction channel cannot keep up
// and flow control has not yet kicked in.
SimpleBuffer mSimpleBuffer;
bool mAttempting0RTT{false};
};
} // namespace mozilla::net
#endif // mozilla_net_Http2StreamBase_h

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

@ -0,0 +1,92 @@
/* -*- 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/. */
// HttpLog.h should generally be included first
#include "HttpLog.h"
// Log on level :5, instead of default :4.
#undef LOG
#define LOG(args) LOG5(args)
#undef LOG_ENABLED
#define LOG_ENABLED() LOG5_ENABLED()
#include "nsHttpHandler.h"
#include "Http2StreamTunnel.h"
#include "Http2ConnectTransaction.h"
#include "nsHttpConnectionInfo.h"
namespace mozilla::net {
Http2StreamTunnel::~Http2StreamTunnel() { ClearTransactionsBlockedOnTunnel(); }
void Http2StreamTunnel::HandleResponseHeaders(nsACString& aHeadersOut,
int32_t httpResponseCode) {
LOG3(
("Http2StreamTunnel %p Tunnel Response code %d", this, httpResponseCode));
// 1xx response is simply skipeed and a final response is expected.
// 2xx response needs to be encrypted.
if ((httpResponseCode / 100) > 2) {
MapStreamToPlainText();
}
if (MapStreamToHttpConnection(aHeadersOut, httpResponseCode)) {
// Process transactions only if we have a final response, i.e., response
// code >= 200.
ClearTransactionsBlockedOnTunnel();
}
if (!mPlainTextTunnel) {
aHeadersOut.Truncate();
LOG(
("Http2StreamTunnel::ConvertHeaders %p 0x%X headers removed for "
"tunnel\n",
this, mStreamID));
}
}
bool Http2StreamTunnel::MapStreamToHttpConnection(
const nsACString& aFlat407Headers, int32_t aHttpResponseCode) {
RefPtr<Http2ConnectTransaction> qiTrans(
mTransaction->QueryHttp2ConnectTransaction());
MOZ_ASSERT(qiTrans);
return qiTrans->MapStreamToHttpConnection(mSocketTransport,
mTransaction->ConnectionInfo(),
aFlat407Headers, aHttpResponseCode);
}
void Http2StreamTunnel::MapStreamToPlainText() {
RefPtr<Http2ConnectTransaction> qiTrans(
mTransaction->QueryHttp2ConnectTransaction());
MOZ_ASSERT(qiTrans);
mPlainTextTunnel = true;
qiTrans->ForcePlainText();
}
nsCString& Http2StreamTunnel::RegistrationKey() {
if (mRegistrationKey.IsEmpty()) {
MOZ_ASSERT(Transaction());
MOZ_ASSERT(Transaction()->ConnectionInfo());
mRegistrationKey = Transaction()->ConnectionInfo()->HashKey();
}
return mRegistrationKey;
}
void Http2StreamTunnel::ClearTransactionsBlockedOnTunnel() {
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
nsresult rv =
gHttpHandler->ConnMgr()->ProcessPendingQ(mTransaction->ConnectionInfo());
if (NS_FAILED(rv)) {
LOG3(
("Http2StreamTunnel::ClearTransactionsBlockedOnTunnel %p\n"
" ProcessPendingQ failed: %08x\n",
this, static_cast<uint32_t>(rv)));
}
}
} // namespace mozilla::net

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

@ -0,0 +1,43 @@
/* -*- 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_net_Http2StreamTunnel_h
#define mozilla_net_Http2StreamTunnel_h
#include "Http2StreamBase.h"
namespace mozilla {
namespace net {
class Http2StreamTunnel : public Http2StreamBase {
public:
Http2StreamTunnel(nsAHttpTransaction* httpTransaction, Http2Session* session,
int32_t priority, uint64_t bcId)
: Http2StreamBase(httpTransaction, session, priority, bcId) {}
bool IsTunnel() override { return true; }
nsCString& RegistrationKey();
protected:
~Http2StreamTunnel();
void HandleResponseHeaders(nsACString& aHeadersOut,
int32_t httpResponseCode) override;
private:
void ClearTransactionsBlockedOnTunnel();
bool MapStreamToHttpConnection(const nsACString& aFlat407Headers,
int32_t aHttpResponseCode);
void MapStreamToPlainText();
bool mPlainTextTunnel{false};
nsCString mRegistrationKey;
};
} // namespace net
} // namespace mozilla
#endif // mozilla_net_Http2StreamTunnel_h

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

@ -0,0 +1,41 @@
/* -*- 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/. */
// HttpLog.h should generally be included first
#include "HttpLog.h"
// Log on level :5, instead of default :4.
#undef LOG
#define LOG(args) LOG5(args)
#undef LOG_ENABLED
#define LOG_ENABLED() LOG5_ENABLED()
#include "Http2StreamWebSocket.h"
#include "Http2ConnectTransaction.h"
namespace mozilla::net {
// ConvertResponseHeaders is used to convert the response headers
// into HTTP/1 format and report some telemetry
void Http2StreamWebSocket::HandleResponseHeaders(nsACString& aHeadersOut,
int32_t httpResponseCode) {
LOG3(("Http2StreamBase %p websocket response code %d", this,
httpResponseCode));
if (httpResponseCode == 200) {
MapStreamToHttpConnection(aHeadersOut);
}
}
bool Http2StreamWebSocket::MapStreamToHttpConnection(
const nsACString& aFlat407Headers) {
RefPtr<Http2ConnectTransaction> qiTrans(
mTransaction->QueryHttp2ConnectTransaction());
MOZ_ASSERT(qiTrans);
return qiTrans->MapStreamToHttpConnection(
mSocketTransport, mTransaction->ConnectionInfo(), aFlat407Headers, -1);
}
} // namespace mozilla::net

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

@ -0,0 +1,36 @@
/* -*- 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/. *//* -*- 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_net_Http2StreamWebSocket_h
#define mozilla_net_Http2StreamWebSocket_h
#include "Http2StreamBase.h"
namespace mozilla {
namespace net {
class Http2StreamWebSocket : public Http2StreamBase {
public:
Http2StreamWebSocket(nsAHttpTransaction* httpTransaction,
Http2Session* session, int32_t priority, uint64_t bcId)
: Http2StreamBase(httpTransaction, session, priority, bcId) {}
protected:
void HandleResponseHeaders(nsACString& aHeadersOut,
int32_t httpResponseCode) override;
private:
bool MapStreamToHttpConnection(const nsACString& aFlat407Headers);
};
} // namespace net
} // namespace mozilla
#endif // mozilla_net_Http2StreamWebSocket_h

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

@ -109,6 +109,9 @@ UNIFIED_SOURCES += [
"Http2Push.cpp",
"Http2Session.cpp",
"Http2Stream.cpp",
"Http2StreamBase.cpp",
"Http2StreamTunnel.cpp",
"Http2StreamWebSocket.cpp",
"Http3Session.cpp",
"Http3Stream.cpp",
"HttpAuthUtils.cpp",

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

@ -12,6 +12,7 @@
#include "PLDHashTable.h"
#include "mozilla/DataMutex.h"
#include "mozilla/HashFunctions.h"
#include "mozilla/OriginAttributes.h"
#include "mozilla/Preferences.h"
#include "mozilla/StaticPrefs_network.h"
#include "nsCRT.h"
@ -21,7 +22,9 @@
#include "nsHttpHandler.h"
#include "nsICacheEntry.h"
#include "nsIRequest.h"
#include "nsIStandardURL.h"
#include "nsJSUtils.h"
#include "nsStandardURL.h"
#include "sslerr.h"
#include <errno.h>
#include <functional>
@ -1028,5 +1031,55 @@ bool SecurityErrorThatMayNeedRestart(nsresult aReason) {
(aReason == psm::GetXPCOMFromNSSError(SSL_ERROR_BAD_MAC_ALERT));
}
nsresult MakeOriginURL(const nsACString& origin, nsCOMPtr<nsIURI>& url) {
nsAutoCString scheme;
nsresult rv = net_ExtractURLScheme(origin, scheme);
NS_ENSURE_SUCCESS(rv, rv);
return MakeOriginURL(scheme, origin, url);
}
nsresult MakeOriginURL(const nsACString& scheme, const nsACString& origin,
nsCOMPtr<nsIURI>& url) {
return NS_MutateURI(new nsStandardURL::Mutator())
.Apply(&nsIStandardURLMutator::Init, nsIStandardURL::URLTYPE_AUTHORITY,
scheme.EqualsLiteral("http") ? NS_HTTP_DEFAULT_PORT
: NS_HTTPS_DEFAULT_PORT,
origin, nullptr, nullptr, nullptr)
.Finalize(url);
}
void CreatePushHashKey(const nsCString& scheme, const nsCString& hostHeader,
const mozilla::OriginAttributes& originAttributes,
uint64_t serial, const nsACString& pathInfo,
nsCString& outOrigin, nsCString& outKey) {
nsCString fullOrigin = scheme;
fullOrigin.AppendLiteral("://");
fullOrigin.Append(hostHeader);
nsCOMPtr<nsIURI> origin;
nsresult rv = MakeOriginURL(scheme, fullOrigin, origin);
if (NS_SUCCEEDED(rv)) {
rv = origin->GetAsciiSpec(outOrigin);
outOrigin.Trim("/", false, true, false);
}
if (NS_FAILED(rv)) {
// Fallback to plain text copy - this may end up behaving poorly
outOrigin = fullOrigin;
}
outKey = outOrigin;
outKey.AppendLiteral("/[");
nsAutoCString suffix;
originAttributes.CreateSuffix(suffix);
outKey.Append(suffix);
outKey.Append(']');
outKey.AppendLiteral("/[http2.");
outKey.AppendInt(serial);
outKey.Append(']');
outKey.Append(pathInfo);
}
} // namespace net
} // namespace mozilla

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

@ -12,6 +12,7 @@
#include "nsString.h"
#include "nsError.h"
#include "nsTArray.h"
#include "mozilla/OriginAttributes.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/Tuple.h"
#include "mozilla/UniquePtr.h"
@ -418,6 +419,18 @@ static inline bool AllowedErrorForHTTPSRRFallback(nsresult aError) {
bool SecurityErrorThatMayNeedRestart(nsresult aReason);
[[nodiscard]] nsresult MakeOriginURL(const nsACString& origin,
nsCOMPtr<nsIURI>& url);
[[nodiscard]] nsresult MakeOriginURL(const nsACString& scheme,
const nsACString& origin,
nsCOMPtr<nsIURI>& url);
void CreatePushHashKey(const nsCString& scheme, const nsCString& hostHeader,
const mozilla::OriginAttributes& originAttributes,
uint64_t serial, const nsACString& pathInfo,
nsCString& outOrigin, nsCString& outKey);
} // namespace net
} // namespace mozilla

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

@ -273,9 +273,22 @@ FxAccountsWebChannel.prototype = {
break;
case COMMAND_PAIR_PREFERENCES:
if (lazy.pairingEnabled) {
browser.loadURI("about:preferences?action=pair#sync", {
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
});
let window = browser.ownerGlobal;
// We should close the FxA tab after we open our pref page
let selectedTab = window.gBrowser.selectedTab;
window.switchToTabHavingURI(
"about:preferences?action=pair#sync",
true,
{
ignoreQueryString: true,
replaceQueryString: true,
adoptIntoActiveWindow: true,
ignoreFragment: "whenComparing",
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
}
);
// close the tab
window.gBrowser.removeTab(selectedTab);
}
break;
case COMMAND_FIREFOX_VIEW:

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

@ -93,6 +93,12 @@ criteria = "safe-to-deploy"
delta = "0.4.0 -> 0.5.0"
notes = "The repository for this crate belongs in the Mozilla org."
[[audits.flagset]]
who = "Ryan Hunt <rhunt@eqrion.net>"
criteria = "safe-to-deploy"
version = "0.4.3"
notes = "Uses no ambient capabilities, vetted the one instance of unsafe."
[[audits.getrandom]]
who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-deploy"
@ -268,6 +274,36 @@ criteria = "safe-to-deploy"
version = "1.0.2"
notes = "Very small crate, just hosts the Void type for easier cross-crate interfacing."
[[audits.wasm-encoder]]
who = "Ryan Hunt <rhunt@eqrion.net>"
criteria = "safe-to-deploy"
version = "0.7.0"
notes = "Maintained by the Bytecode Alliance, with contributions from Mozilla. This has no unsafe code and uses no ambient capabilities."
[[audits.wasm-encoder]]
who = "Ryan Hunt <rhunt@eqrion.net>"
criteria = "safe-to-deploy"
delta = "0.7.0 -> 0.14.0"
notes = "wasm-encoder has no unsafe code and uses no ambient capabilities."
[[audits.wasm-smith]]
who = "Ryan Hunt <rhunt@eqrion.net>"
criteria = "safe-to-deploy"
version = "0.11.2"
notes = "Maintained by the Bytecode Alliance, with contributions from Mozilla. I've vetted the one instance of unsafe code."
[[audits.wasmparser]]
who = "Ryan Hunt <rhunt@eqrion.net>"
criteria = "safe-to-deploy"
version = "0.87.0"
notes = "Maintained by the Bytecode Alliance, with contributions from Mozilla. I've vetted the one instance of unsafe code."
[[audits.wast]]
who = "Ryan Hunt <rhunt@eqrion.net>"
criteria = "safe-to-deploy"
version = "44.0.0"
notes = "Maintained by the Bytecode Alliance, with contributions from Mozilla. wast has no unsafe code and the only ambient capability it uses is to read the full contents of a file that is given to it."
[[audits.webdriver]]
who = "Henrik Skupin <mail@hskupin.info>"
criteria = "safe-to-deploy"

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

@ -1693,22 +1693,10 @@ criteria = "safe-to-run"
version = "0.11.0+wasi-snapshot-preview1"
criteria = "safe-to-deploy"
[[exemptions.wasm-encoder]]
version = "0.7.0"
criteria = "safe-to-run"
[[exemptions.wasm-smith]]
version = "0.8.0"
criteria = "safe-to-run"
[[exemptions.wasmparser]]
version = "0.78.2"
criteria = "safe-to-deploy"
[[exemptions.wast]]
version = "41.0.0"
criteria = "safe-to-deploy"
[[exemptions.webrtc-sdp]]
version = "0.3.9"
criteria = "safe-to-deploy"

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

@ -325,6 +325,16 @@ merge-automation:
from-branch: 'central'
to-repo: 'https://hg.mozilla.org/releases/mozilla-beta'
to-branch: 'beta'
early-to-late-beta:
fetch-version-from: "browser/config/version.txt"
version-files: []
replacements:
- - build/defines.sh
- EARLY_BETA_OR_EARLIER=1
- EARLY_BETA_OR_EARLIER=
merge-old-head: false
to-repo: 'https://hg.mozilla.org/releases/mozilla-beta'
to-branch: 'beta'
beta-to-release:
fetch-version-from: "browser/config/version.txt"
version-files:

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

@ -441,7 +441,7 @@ function push_repo {
do
echo "Removing old request $diff"
# There is no 'arc abandon', see bug 1452082
echo '{"transactions": [{"type":"abandon", "value": true}], "objectIdentifier": "'"${diff}"'"}' | arc call-conduit differential.revision.edit
echo '{"transactions": [{"type":"abandon", "value": true}], "objectIdentifier": "'"${diff}"'"}' | $ARC call-conduit -- differential.revision.edit
done
$ARC diff --verbatim --reviewers "${REVIEWERS}"

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

@ -1,33 +0,0 @@
# 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/.
from __future__ import absolute_import
import os
ABS_WORK_DIR = os.path.join(os.getcwd(), "build")
config = {
"log_name": "beta_to_release",
"copy_files": [
{
"src": "browser/config/version.txt",
"dst": "browser/config/version_display.txt",
},
],
"replacements": [
# File, from, to
],
"vcs_share_base": os.path.join(ABS_WORK_DIR, "hg-shared"),
# "hg_share_base": None,
"from_repo_url": "https://hg.mozilla.org/releases/mozilla-beta",
"to_repo_url": "https://hg.mozilla.org/releases/mozilla-release",
"base_tag": "FIREFOX_RELEASE_%(major_version)s_BASE",
"end_tag": "FIREFOX_RELEASE_%(major_version)s_END",
"migration_behavior": "beta_to_release",
"require_remove_locales": False,
"pull_all_branches": True,
"virtualenv_modules": [
"requests==2.8.1",
],
}

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

@ -1,43 +0,0 @@
# 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/.
from __future__ import absolute_import
import os
ABS_WORK_DIR = os.path.join(os.getcwd(), "build")
config = {
"log_name": "central_to_beta",
"version_files": [
{"file": "browser/config/version.txt", "suffix": ""},
{"file": "browser/config/version_display.txt", "suffix": "b1"},
{"file": "config/milestone.txt", "suffix": ""},
],
"replacements": [
# File, from, to
(
f,
"ac_add_options --with-branding=browser/branding/nightly",
"ac_add_options --enable-official-branding",
)
for f in [
"browser/config/mozconfigs/linux32/l10n-mozconfig",
"browser/config/mozconfigs/linux64/l10n-mozconfig",
"browser/config/mozconfigs/win32/l10n-mozconfig",
"browser/config/mozconfigs/win64/l10n-mozconfig",
"browser/config/mozconfigs/win64-aarch64/l10n-mozconfig",
"browser/config/mozconfigs/macosx64/l10n-mozconfig",
]
],
"vcs_share_base": os.path.join(ABS_WORK_DIR, "hg-shared"),
# "hg_share_base": None,
"from_repo_url": "https://hg.mozilla.org/mozilla-central",
"to_repo_url": "https://hg.mozilla.org/releases/mozilla-beta",
"base_tag": "FIREFOX_BETA_%(major_version)s_BASE",
"end_tag": "FIREFOX_BETA_%(major_version)s_END",
"migration_behavior": "central_to_beta",
"virtualenv_modules": [
"requests==2.8.1",
],
}

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

@ -1,11 +0,0 @@
# 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/.
# This config is for `mach try release` to support beta simulations.
config = {
"replacements": [
("build/defines.sh", "EARLY_BETA_OR_EARLIER=1", "EARLY_BETA_OR_EARLIER="),
],
}

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

@ -1,27 +0,0 @@
# 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/.
from __future__ import absolute_import
import os
ABS_WORK_DIR = os.path.join(os.getcwd(), "build")
NEW_ESR_REPO = "https://hg.mozilla.org/releases/mozilla-esr68"
config = {
"log_name": "relese_to_esr",
"version_files": [
{"file": "browser/config/version_display.txt", "suffix": "esr"},
],
"replacements": [],
"vcs_share_base": os.path.join(ABS_WORK_DIR, "hg-shared"),
# Pull from ESR repo, since we have already branched it and have landed esr-specific patches on it
# We will need to manually merge mozilla-release into before runnning this.
"from_repo_url": NEW_ESR_REPO,
"to_repo_url": NEW_ESR_REPO,
"base_tag": "FIREFOX_ESR_%(major_version)s_BASE",
"migration_behavior": "release_to_esr",
"require_remove_locales": False,
"requires_head_merge": False,
"pull_all_branches": False,
}

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

@ -706,7 +706,10 @@ class Browsertime(Perftest):
# Double the timeouts on live sites and when running with Fenix
if self.config["live_sites"] or self.config["app"] in ("fenix",):
output_timeout *= 2
# Since output_timeout is None for benchmark tests we should
# not perform any operations on it.
if output_timeout is not None:
output_timeout *= 2
proc_timeout *= 2
proc = self.process_handler(cmd, processOutputLine=_line_handler, env=env)

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

@ -0,0 +1,150 @@
// META: title=IDB-backed composite blobs maintain coherency
// META: script=resources/support-promises.js
// This test file is intended to help validate browser handling of complex blob
// scenarios where one or more levels of multipart blobs are used and varying
// IPC serialization strategies may be used depending on various complexity
// heuristics.
//
// A variety of approaches of reading the blob's contents are attempted for
// completeness:
// - fetch of a URL created via URL.createObjectURL
// - Note that this is likely to involve multi-process behavior in a way that
// the next 2 currently will not unless their Blobs are round-tripped
// through a MessagePort.
// - FileReader
// - Blob.prototype.arrayBuffer()
function composite_blob_test({ blobCount, blobSize, name }) {
for (const mode of ["fetch-blob-url", "file-reader", "direct"]) {
promise_test(async testCase => {
const key = "the-blobs";
let memBlobs = [];
for (let iBlob = 0; iBlob < blobCount; iBlob++) {
memBlobs.push(new Blob([make_arraybuffer_contents(iBlob, blobSize)]));
}
const db = await createDatabase(testCase, db => {
db.createObjectStore("blobs");
});
const write_tx = db.transaction("blobs", "readwrite");
let store = write_tx.objectStore("blobs");
store.put(memBlobs, key);
// Make the blobs eligible for GC which is most realistic and most likely
// to cause problems.
memBlobs = null;
await promiseForTransaction(testCase, write_tx);
const read_tx = db.transaction("blobs");
store = read_tx.objectStore("blobs");
const read_req = store.get(key);
await promiseForTransaction(testCase, read_tx);
const diskBlobs = read_req.result;
const compositeBlob = new Blob(diskBlobs);
if (mode === "fetch-blob-url") {
const blobUrl = URL.createObjectURL(compositeBlob);
let urlResp = await fetch(blobUrl);
let urlFetchArrayBuffer = await urlResp.arrayBuffer();
urlResp = null;
URL.revokeObjectURL(blobUrl);
validate_arraybuffer_contents("fetched URL", urlFetchArrayBuffer, blobCount, blobSize);
urlFetchArrayBuffer = null;
} else if (mode === "file-reader") {
let reader = new FileReader();
let readerPromise = new Promise(resolve => {
reader.onload = () => {
resolve(reader.result);
}
})
reader.readAsArrayBuffer(compositeBlob);
let readArrayBuffer = await readerPromise;
readerPromise = null;
reader = null;
validate_arraybuffer_contents("FileReader", readArrayBuffer, blobCount, blobSize);
readArrayBuffer = null;
} else if (mode === "direct") {
let directArrayBuffer = await compositeBlob.arrayBuffer();
validate_arraybuffer_contents("arrayBuffer", directArrayBuffer, blobCount, blobSize);
}
}, `Composite Blob Handling: ${name}: ${mode}`);
}
}
// Create an ArrayBuffer whose even bytes are the index identifier and whose
// odd bytes are a sequence incremented by 3 (wrapping at 256) so that
// discontinuities at power-of-2 boundaries are more detectable.
function make_arraybuffer_contents(index, size) {
const arr = new Uint8Array(size);
for (let i = 0, counter = 0; i < size; i += 2, counter = (counter + 3) % 256) {
arr[i] = index;
arr[i + 1] = counter;
}
return arr.buffer;
}
function validate_arraybuffer_contents(source, buffer, blobCount, blobSize) {
// Accumulate a list of problems we perceive so we can report what seems to
// have happened all at once.
const problems = [];
const arr = new Uint8Array(buffer);
const expectedLength = blobCount * blobSize;
const actualCount = arr.length / blobSize;
if (arr.length !== expectedLength) {
problems.push(`ArrayBuffer only holds ${actualCount} blobs' worth instead of ${blobCount}.`);
problems.push(`Actual ArrayBuffer is ${arr.length} bytes but expected ${expectedLength}`);
}
const counterBlobStep = (blobSize / 2 * 3) % 256;
let expectedBlob = 0;
let blobSeenSoFar = 0;
let expectedCounter = 0;
let counterDrift = 0;
for (let i = 0; i < arr.length; i += 2) {
if (arr[i] !== expectedBlob || blobSeenSoFar >= blobSize) {
if (blobSeenSoFar !== blobSize) {
problems.push(`Truncated blob ${expectedBlob} after ${blobSeenSoFar} bytes.`);
} else {
expectedBlob++;
}
if (expectedBlob !== arr[i]) {
problems.push(`Expected blob ${expectedBlob} but found ${arr[i]}, compensating.`);
expectedBlob = arr[i];
}
blobSeenSoFar = 0;
expectedCounter = (expectedBlob * counterBlobStep) % 256;
counterDrift = 0;
}
if (arr[i + 1] !== (expectedCounter + counterDrift) % 256) {
const newDrift = expectedCounter - arr[i + 1];
problems.push(`In blob ${expectedBlob} at ${blobSeenSoFar + 1} bytes in, counter drift now ${newDrift} was ${counterDrift}`);
counterDrift = newDrift;
}
blobSeenSoFar += 2;
expectedCounter = (expectedCounter + 3) % 256;
}
if (problems.length) {
assert_true(false, `${source} blob payload problem: ${problems.join("\n")}`);
} else {
assert_true(true, `${source} blob payloads validated.`);
}
}
composite_blob_test({
blobCount: 16,
blobSize: 256 * 1024,
name: "Many blobs",
});

1
third_party/rust/flagset/.cargo-checksum.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
{"files":{"Cargo.toml":"5a87209bc98397121d9b710b6eb05559c5f2ddb7884e82fbfc706026a24fac13","LICENSE":"cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30","README.md":"391c693969a7cd5e1810d3fc4271f1b69f79ee1a26def1fc9b3f7c5df50920dd","src/lib.rs":"77804ee547d8723e603975d586deaf4fa8a58bf13a8c80d9416eed0298b39462"},"package":"cda653ca797810c02f7ca4b804b40b8b95ae046eb989d356bce17919a8c25499"}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше