From 2071ba46809dacd05777a30167c0b89451720bc0 Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Fri, 22 Sep 2017 07:18:14 +0200 Subject: [PATCH 01/37] Bug 1397145 - Remove the support for moz-blob type in XHR, r=smaug --- dom/base/crashtests/crashtests.list | 1 - dom/base/crashtests/xhr_abortinprogress.html | 23 --- dom/webidl/XMLHttpRequest.webidl | 1 - dom/xhr/XMLHttpRequestMainThread.cpp | 91 ++-------- dom/xhr/XMLHttpRequestMainThread.h | 3 - dom/xhr/tests/test_XHR.html | 156 +++++++++--------- dom/xhr/tests/test_xhr_progressevents.html | 1 - .../meta/XMLHttpRequest/historical.html.ini | 3 - toolkit/components/telemetry/Histograms.json | 9 - 9 files changed, 87 insertions(+), 201 deletions(-) delete mode 100644 dom/base/crashtests/xhr_abortinprogress.html diff --git a/dom/base/crashtests/crashtests.list b/dom/base/crashtests/crashtests.list index 7f34a77f6433..4f46c2950c35 100644 --- a/dom/base/crashtests/crashtests.list +++ b/dom/base/crashtests/crashtests.list @@ -217,7 +217,6 @@ pref(clipboard.autocopy,true) load 1370737.html pref(dom.IntersectionObserver.enabled,true) load 1370968.html load 1377826.html skip-if(stylo&&isDebugBuild&&winWidget) load structured_clone_container_throws.html # Bug 1383845 -HTTP(..) load xhr_abortinprogress.html load xhr_empty_datauri.html load xhr_html_nullresponse.html load 1383478.html diff --git a/dom/base/crashtests/xhr_abortinprogress.html b/dom/base/crashtests/xhr_abortinprogress.html deleted file mode 100644 index 5345e9bf2539..000000000000 --- a/dom/base/crashtests/xhr_abortinprogress.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - diff --git a/dom/webidl/XMLHttpRequest.webidl b/dom/webidl/XMLHttpRequest.webidl index 4b2006e358d3..d903cd1088aa 100644 --- a/dom/webidl/XMLHttpRequest.webidl +++ b/dom/webidl/XMLHttpRequest.webidl @@ -25,7 +25,6 @@ enum XMLHttpRequestResponseType { // Mozilla-specific stuff "moz-chunked-text", "moz-chunked-arraybuffer", - "moz-blob" }; /** diff --git a/dom/xhr/XMLHttpRequestMainThread.cpp b/dom/xhr/XMLHttpRequestMainThread.cpp index 9a54e6e0987e..1ab885668405 100644 --- a/dom/xhr/XMLHttpRequestMainThread.cpp +++ b/dom/xhr/XMLHttpRequestMainThread.cpp @@ -315,7 +315,6 @@ XMLHttpRequestMainThread::ResetResponse() TruncateResponseText(); mResponseBlob = nullptr; mBlobStorage = nullptr; - mBlobSet = nullptr; mResultArrayBuffer = nullptr; mArrayBufferBuilder.reset(); mResultJSON.setUndefined(); @@ -682,31 +681,6 @@ XMLHttpRequestMainThread::CreateResponseParsedJSON(JSContext* aCx) return NS_OK; } -void -XMLHttpRequestMainThread::CreatePartialBlob(ErrorResult& aRv) -{ - // mBlobSet can be null if the request has been canceled - if (!mBlobSet) { - return; - } - - nsAutoCString contentType; - if (mState == State::done) { - mChannel->GetContentType(contentType); - } - - nsTArray> subImpls(mBlobSet->GetBlobImpls()); - RefPtr blobImpl = - MultipartBlobImpl::Create(Move(subImpls), - NS_ConvertASCIItoUTF16(contentType), - aRv); - if (NS_WARN_IF(aRv.Failed())) { - return; - } - - mResponseBlob = Blob::Create(GetOwner(), blobImpl); -} - NS_IMETHODIMP XMLHttpRequestMainThread::GetResponseType(nsAString& aResponseType) { MOZ_ASSERT(mResponseType < XMLHttpRequestResponseType::EndGuard_); @@ -755,9 +729,7 @@ XMLHttpRequestMainThread::SetResponseType(XMLHttpRequestResponseType aResponseTy } // We want to get rid of this moz-only types. Bug 1335365. - if (aResponseType == XMLHttpRequestResponseType::Moz_blob) { - Telemetry::Accumulate(Telemetry::MOZ_BLOB_IN_XHR, 1); - } else if (aResponseType == XMLHttpRequestResponseType::Moz_chunked_text) { + if (aResponseType == XMLHttpRequestResponseType::Moz_chunked_text) { Telemetry::Accumulate(Telemetry::MOZ_CHUNKED_TEXT_IN_XHR, 1); } else if (aResponseType == XMLHttpRequestResponseType::Moz_chunked_arraybuffer) { Telemetry::Accumulate(Telemetry::MOZ_CHUNKED_ARRAYBUFFER_IN_XHR, 1); @@ -818,17 +790,10 @@ XMLHttpRequestMainThread::GetResponse(JSContext* aCx, return; } case XMLHttpRequestResponseType::Blob: - case XMLHttpRequestResponseType::Moz_blob: { if (mState != State::done) { - if (mResponseType != XMLHttpRequestResponseType::Moz_blob) { - aResponse.setNull(); - return; - } - - if (!mResponseBlob) { - CreatePartialBlob(aRv); - } + aResponse.setNull(); + return; } if (!mResponseBlob) { @@ -1715,13 +1680,6 @@ XMLHttpRequestMainThread::StreamReaderFunc(nsIInputStream* in, if (xmlHttpRequest->mResponseType == XMLHttpRequestResponseType::Blob) { xmlHttpRequest->MaybeCreateBlobStorage(); rv = xmlHttpRequest->mBlobStorage->Append(fromRawSegment, count); - } else if (xmlHttpRequest->mResponseType == XMLHttpRequestResponseType::Moz_blob) { - if (!xmlHttpRequest->mBlobSet) { - xmlHttpRequest->mBlobSet = new BlobSet(); - } - rv = xmlHttpRequest->mBlobSet->AppendVoidPtr(fromRawSegment, count); - // Clear the cache so that the blob size is updated. - xmlHttpRequest->mResponseBlob = nullptr; } else if ((xmlHttpRequest->mResponseType == XMLHttpRequestResponseType::Arraybuffer && !xmlHttpRequest->mIsMappedArrayBuffer) || xmlHttpRequest->mResponseType == XMLHttpRequestResponseType::Moz_chunked_arraybuffer) { @@ -1885,7 +1843,6 @@ XMLHttpRequestMainThread::LocalFileToBlobCompleted(Blob* aBlob) mResponseBlob = aBlob; mBlobStorage = nullptr; - mBlobSet = nullptr; NS_ASSERTION(mResponseBody.IsEmpty(), "mResponseBody should be empty"); ChangeStateToDone(); @@ -1908,8 +1865,7 @@ XMLHttpRequestMainThread::OnDataAvailable(nsIRequest *request, nsresult rv; nsCOMPtr localFile; - if ((mResponseType == XMLHttpRequestResponseType::Blob || - mResponseType == XMLHttpRequestResponseType::Moz_blob)) { + if (mResponseType == XMLHttpRequestResponseType::Blob) { rv = GetLocalFileFromChannel(request, getter_AddRefs(localFile)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; @@ -1917,7 +1873,6 @@ XMLHttpRequestMainThread::OnDataAvailable(nsIRequest *request, if (localFile) { mBlobStorage = nullptr; - mBlobSet = nullptr; NS_ASSERTION(mResponseBody.IsEmpty(), "mResponseBody should be empty"); // The nsIStreamListener contract mandates us to read from the stream @@ -2271,8 +2226,7 @@ XMLHttpRequestMainThread::OnStopRequest(nsIRequest *request, nsISupports *ctxt, // blob. We have this error because we canceled the channel. The status will // be set to NS_OK. if (status == NS_ERROR_FILE_ALREADY_EXISTS && - (mResponseType == XMLHttpRequestResponseType::Blob || - mResponseType == XMLHttpRequestResponseType::Moz_blob)) { + mResponseType == XMLHttpRequestResponseType::Blob) { nsCOMPtr file; nsresult rv = GetLocalFileFromChannel(request, getter_AddRefs(file)); if (NS_WARN_IF(NS_FAILED(rv))) { @@ -2308,41 +2262,18 @@ XMLHttpRequestMainThread::OnStopRequest(nsIRequest *request, nsISupports *ctxt, } if (NS_SUCCEEDED(status) && - (mResponseType == XMLHttpRequestResponseType::Blob || - mResponseType == XMLHttpRequestResponseType::Moz_blob) && + mResponseType == XMLHttpRequestResponseType::Blob && !waitingForBlobCreation) { // Smaller files may be written in cache map instead of separate files. // Also, no-store response cannot be written in persistent cache. nsAutoCString contentType; mChannel->GetContentType(contentType); - if (mResponseType == XMLHttpRequestResponseType::Blob) { - // mBlobStorage can be null if the channel is non-file non-cacheable - // and if the response length is zero. - MaybeCreateBlobStorage(); - mBlobStorage->GetBlobWhenReady(GetOwner(), contentType, this); - waitingForBlobCreation = true; - } else { - // mBlobSet can be null if the channel is non-file non-cacheable - // and if the response length is zero. - if (!mBlobSet) { - mBlobSet = new BlobSet(); - } - - ErrorResult error; - nsTArray> subImpls(mBlobSet->GetBlobImpls()); - RefPtr blobImpl = - MultipartBlobImpl::Create(Move(subImpls), - NS_ConvertASCIItoUTF16(contentType), - error); - mBlobSet = nullptr; - - if (NS_WARN_IF(error.Failed())) { - return error.StealNSResult(); - } - - mResponseBlob = Blob::Create(GetOwner(), blobImpl); - } + // mBlobStorage can be null if the channel is non-file non-cacheable + // and if the response length is zero. + MaybeCreateBlobStorage(); + mBlobStorage->GetBlobWhenReady(GetOwner(), contentType, this); + waitingForBlobCreation = true; NS_ASSERTION(mResponseBody.IsEmpty(), "mResponseBody should be empty"); NS_ASSERTION(mResponseText.IsEmpty(), "mResponseText should be empty"); diff --git a/dom/xhr/XMLHttpRequestMainThread.h b/dom/xhr/XMLHttpRequestMainThread.h index d12a92700fe3..a684b0c06f64 100644 --- a/dom/xhr/XMLHttpRequestMainThread.h +++ b/dom/xhr/XMLHttpRequestMainThread.h @@ -526,7 +526,6 @@ protected: uint32_t count, uint32_t *writeCount); nsresult CreateResponseParsedJSON(JSContext* aCx); - void CreatePartialBlob(ErrorResult& aRv); // Change the state of the object with this. The broadcast argument // determines if the onreadystatechange listener should be called. nsresult ChangeState(State aState, bool aBroadcast = true); @@ -666,8 +665,6 @@ protected: RefPtr mResponseBlob; // We stream data to mBlobStorage when response type is "blob". RefPtr mBlobStorage; - // We stream data to mBlobSet when response type is "moz-blob". - nsAutoPtr mBlobSet; nsString mOverrideMimeType; diff --git a/dom/xhr/tests/test_XHR.html b/dom/xhr/tests/test_XHR.html index a39b1839ad06..15c29c7ca72f 100644 --- a/dom/xhr/tests/test_XHR.html +++ b/dom/xhr/tests/test_XHR.html @@ -276,92 +276,88 @@ while (xhr.readyState != 4) { checkXHRStatus(); // test response (responseType='blob') -var responseTypes = ['blob', 'moz-blob']; -for (var i = 0; i < responseTypes.length; i++) { - var t = responseTypes[i]; - // with a simple text file - xhr = new XMLHttpRequest(); - xhr.open("GET", 'file_XHR_pass2.txt'); - xhr.responseType = t; - xhr.onloadend = continueTest; - xhr.send(null); - yield undefined; - is(xhr.status, 200, "wrong status"); - checkResponseTextAccessThrows(xhr); - checkResponseXMLAccessThrows(xhr); - var b = xhr.response; - ok(b, "should have a non-null blob"); - ok(b instanceof Blob, "should be a Blob"); - ok(!(b instanceof File), "should not be a File"); - is(b.size, "hello pass\n".length, "wrong blob size"); +// with a simple text file +xhr = new XMLHttpRequest(); +xhr.open("GET", 'file_XHR_pass2.txt'); +xhr.responseType = 'blob'; +xhr.onloadend = continueTest; +xhr.send(null); +yield undefined; +is(xhr.status, 200, "wrong status"); +checkResponseTextAccessThrows(xhr); +checkResponseXMLAccessThrows(xhr); +var b = xhr.response; +ok(b, "should have a non-null blob"); +ok(b instanceof Blob, "should be a Blob"); +ok(!(b instanceof File), "should not be a File"); +is(b.size, "hello pass\n".length, "wrong blob size"); - var fr = new FileReader(); - fr.onload = continueTest; - fr.readAsBinaryString(b); - yield undefined; - ok(fr.result, "hello pass\n", "wrong values"); +var fr = new FileReader(); +fr.onload = continueTest; +fr.readAsBinaryString(b); +yield undefined; +ok(fr.result, "hello pass\n", "wrong values"); - // with a binary file - xhr = new XMLHttpRequest(); - xhr.open("GET", 'file_XHR_binary1.bin', true); - xhr.send(null); - xhr.onreadystatechange = continueTest; - while(xhr.readyState != 2) - yield undefined; - - is(xhr.status, 200, "wrong status"); - xhr.responseType = t; - - while(xhr.readyState != 4) - yield undefined; - - xhr.onreadystatechange = null; - - b = xhr.response; - ok(b != null, "should have a non-null blob"); - is(b.size, 12, "wrong blob size"); - - fr = new FileReader(); - fr.readAsBinaryString(b); - xhr = null; // kill the XHR object - b = null; - SpecialPowers.gc(); - fr.onload = continueTest; - yield undefined; - is(fr.result, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb", "wrong values"); - - // with a larger binary file - xhr = new XMLHttpRequest(); - xhr.open("GET", 'file_XHR_binary2.bin', true); - xhr.responseType = t; - xhr.send(null); - xhr.onreadystatechange = continueTest; - - while (xhr.readyState != 4) - yield undefined; - - xhr.onreadystatechange = null; - - var b = xhr.response; - ok(b != null, "should have a non-null blob"); - is(b.size, 65536, "wrong blob size"); - - fr = new FileReader(); - fr.readAsArrayBuffer(b); - fr.onload = continueTest; - xhr = null; // kill the XHR object - b = null; - SpecialPowers.gc(); +// with a binary file +xhr = new XMLHttpRequest(); +xhr.open("GET", 'file_XHR_binary1.bin', true); +xhr.send(null); +xhr.onreadystatechange = continueTest; +while(xhr.readyState != 2) yield undefined; - var u8 = new Uint8Array(fr.result); - for (var i = 0; i < 65536; i++) { - if (u8[i] !== (i & 255)) { - break; - } +is(xhr.status, 200, "wrong status"); +xhr.responseType = 'blob'; + +while(xhr.readyState != 4) + yield undefined; + +xhr.onreadystatechange = null; + +b = xhr.response; +ok(b != null, "should have a non-null blob"); +is(b.size, 12, "wrong blob size"); + +fr = new FileReader(); +fr.readAsBinaryString(b); +xhr = null; // kill the XHR object +b = null; +SpecialPowers.gc(); +fr.onload = continueTest; +yield undefined; +is(fr.result, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb", "wrong values"); + +// with a larger binary file +xhr = new XMLHttpRequest(); +xhr.open("GET", 'file_XHR_binary2.bin', true); +xhr.responseType = 'blob'; +xhr.send(null); +xhr.onreadystatechange = continueTest; + +while (xhr.readyState != 4) + yield undefined; + +xhr.onreadystatechange = null; + +var b = xhr.response; +ok(b != null, "should have a non-null blob"); +is(b.size, 65536, "wrong blob size"); + +fr = new FileReader(); +fr.readAsArrayBuffer(b); +fr.onload = continueTest; +xhr = null; // kill the XHR object +b = null; +SpecialPowers.gc(); +yield undefined; + +var u8 = new Uint8Array(fr.result); +for (var i = 0; i < 65536; i++) { + if (u8[i] !== (i & 255)) { + break; } - is(i, 65536, "wrong value at offset " + i); } +is(i, 65536, "wrong value at offset " + i); var client = new XMLHttpRequest(); client.open("GET", "file_XHR_pass1.xml", true); diff --git a/dom/xhr/tests/test_xhr_progressevents.html b/dom/xhr/tests/test_xhr_progressevents.html index 7d02b76cf439..c1b43c345602 100644 --- a/dom/xhr/tests/test_xhr_progressevents.html +++ b/dom/xhr/tests/test_xhr_progressevents.html @@ -132,7 +132,6 @@ function* runTests() { var responseTypes = [{ type: "text", text: true }, { type: "arraybuffer", text: false, nodata: true }, { type: "blob", text: false, nodata: true, blob: true }, - { type: "moz-blob", text: false, nodata: false, blob: true }, { type: "document", text: true, nodata: true }, { type: "json", text: true, nodata: true }, { type: "", text: true }, diff --git a/testing/web-platform/meta/XMLHttpRequest/historical.html.ini b/testing/web-platform/meta/XMLHttpRequest/historical.html.ini index 71a18b28698f..ad3e49b967c0 100644 --- a/testing/web-platform/meta/XMLHttpRequest/historical.html.ini +++ b/testing/web-platform/meta/XMLHttpRequest/historical.html.ini @@ -1,8 +1,5 @@ [historical.html] type: testharness - [Support for responseType = moz-blob] - expected: FAIL - [Support for responseType = moz-chunked-text] expected: FAIL diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index 6406815bf7e8..fc95df148393 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -12963,15 +12963,6 @@ "bug_numbers": [1331804], "description": "The time a given main thread runnable took to run (in milliseconds). The key comes from the runnables nsINamed::name value." }, - "MOZ_BLOB_IN_XHR": { - "record_in_processes": ["main", "content"], - "alert_emails": ["amarchesini@mozilla.com"], - "expires_in_version": "58", - "kind": "boolean", - "bug_numbers": [1335365], - "releaseChannelCollection": "opt-out", - "description": "XMLHttpRequest.responseType set to moz-blob" - }, "MOZ_CHUNKED_TEXT_IN_XHR": { "record_in_processes": ["main", "content"], "alert_emails": ["amarchesini@mozilla.com"], From b49b5f31c9183d0f512d00867b8b406fab0289fc Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Fri, 22 Sep 2017 07:18:49 +0200 Subject: [PATCH 02/37] Bug 1397151 - Remove the support for moz-chunk-text type in XHR, r=smaug --- dom/base/domerr.msg | 4 +- dom/webidl/XMLHttpRequest.webidl | 1 - dom/xhr/XMLHttpRequestMainThread.cpp | 26 ++------ dom/xhr/tests/test_XHR.html | 2 - dom/xhr/tests/test_html_in_xhr.html | 17 +---- dom/xhr/tests/test_xhr_progressevents.html | 1 - dom/xhr/tests/xhr2_worker.js | 65 +------------------ .../meta/XMLHttpRequest/historical.html.ini | 3 - toolkit/components/telemetry/Histograms.json | 9 --- 9 files changed, 10 insertions(+), 118 deletions(-) diff --git a/dom/base/domerr.msg b/dom/base/domerr.msg index 42ac0fb62117..63508791d5f9 100644 --- a/dom/base/domerr.msg +++ b/dom/base/domerr.msg @@ -161,6 +161,6 @@ DOM4_MSG_DEF(InvalidStateError, "XMLHttpRequest state must be OPENED.", NS_ERROR DOM4_MSG_DEF(InvalidStateError, "XMLHttpRequest must not be sending.", NS_ERROR_DOM_INVALID_STATE_XHR_MUST_NOT_BE_SENDING) DOM4_MSG_DEF(InvalidStateError, "XMLHttpRequest state must not be LOADING or DONE.", NS_ERROR_DOM_INVALID_STATE_XHR_MUST_NOT_BE_LOADING_OR_DONE) DOM4_MSG_DEF(InvalidStateError, "responseXML is only available if responseType is '' or 'document'.", NS_ERROR_DOM_INVALID_STATE_XHR_HAS_WRONG_RESPONSETYPE_FOR_RESPONSEXML) -DOM4_MSG_DEF(InvalidStateError, "responseText is only available if responseType is '', 'document', or 'moz-chunked-text'.", NS_ERROR_DOM_INVALID_STATE_XHR_HAS_WRONG_RESPONSETYPE_FOR_RESPONSETEXT) -DOM4_MSG_DEF(InvalidStateError, "synchronous XMLHttpRequests do not support 'moz-chunked-text' or 'moz-chunked-arraybuffer' responseType.", NS_ERROR_DOM_INVALID_STATE_XHR_CHUNKED_RESPONSETYPES_UNSUPPORTED_FOR_SYNC) +DOM4_MSG_DEF(InvalidStateError, "responseText is only available if responseType is '' or 'document'.", NS_ERROR_DOM_INVALID_STATE_XHR_HAS_WRONG_RESPONSETYPE_FOR_RESPONSETEXT) +DOM4_MSG_DEF(InvalidStateError, "synchronous XMLHttpRequests do not support 'moz-chunked-arraybuffer' responseType.", NS_ERROR_DOM_INVALID_STATE_XHR_CHUNKED_RESPONSETYPES_UNSUPPORTED_FOR_SYNC) DOM4_MSG_DEF(InvalidAccessError, "synchronous XMLHttpRequests do not support timeout and responseType.", NS_ERROR_DOM_INVALID_ACCESS_XHR_TIMEOUT_AND_RESPONSETYPE_UNSUPPORTED_FOR_SYNC) diff --git a/dom/webidl/XMLHttpRequest.webidl b/dom/webidl/XMLHttpRequest.webidl index d903cd1088aa..569e3e28d3cf 100644 --- a/dom/webidl/XMLHttpRequest.webidl +++ b/dom/webidl/XMLHttpRequest.webidl @@ -23,7 +23,6 @@ enum XMLHttpRequestResponseType { "text", // Mozilla-specific stuff - "moz-chunked-text", "moz-chunked-arraybuffer", }; diff --git a/dom/xhr/XMLHttpRequestMainThread.cpp b/dom/xhr/XMLHttpRequestMainThread.cpp index 1ab885668405..7531cb189ec6 100644 --- a/dom/xhr/XMLHttpRequestMainThread.cpp +++ b/dom/xhr/XMLHttpRequestMainThread.cpp @@ -501,8 +501,7 @@ XMLHttpRequestMainThread::DetectCharset() if (mResponseType != XMLHttpRequestResponseType::_empty && mResponseType != XMLHttpRequestResponseType::Text && - mResponseType != XMLHttpRequestResponseType::Json && - mResponseType != XMLHttpRequestResponseType::Moz_chunked_text) { + mResponseType != XMLHttpRequestResponseType::Json) { return NS_OK; } @@ -607,18 +606,11 @@ XMLHttpRequestMainThread::GetResponseText(XMLHttpRequestStringSnapshot& aSnapsho aSnapshot.Reset(); if (mResponseType != XMLHttpRequestResponseType::_empty && - mResponseType != XMLHttpRequestResponseType::Text && - mResponseType != XMLHttpRequestResponseType::Moz_chunked_text) { + mResponseType != XMLHttpRequestResponseType::Text) { aRv.Throw(NS_ERROR_DOM_INVALID_STATE_XHR_HAS_WRONG_RESPONSETYPE_FOR_RESPONSETEXT); return; } - if (mResponseType == XMLHttpRequestResponseType::Moz_chunked_text && - !mInLoadProgressEvent) { - aSnapshot.SetVoid(); - return; - } - if (mState != State::loading && mState != State::done) { return; } @@ -722,16 +714,13 @@ XMLHttpRequestMainThread::SetResponseType(XMLHttpRequestResponseType aResponseTy } if (mFlagSynchronous && - (aResponseType == XMLHttpRequestResponseType::Moz_chunked_text || - aResponseType == XMLHttpRequestResponseType::Moz_chunked_arraybuffer)) { + aResponseType == XMLHttpRequestResponseType::Moz_chunked_arraybuffer) { aRv.Throw(NS_ERROR_DOM_INVALID_STATE_XHR_CHUNKED_RESPONSETYPES_UNSUPPORTED_FOR_SYNC); return; } // We want to get rid of this moz-only types. Bug 1335365. - if (aResponseType == XMLHttpRequestResponseType::Moz_chunked_text) { - Telemetry::Accumulate(Telemetry::MOZ_CHUNKED_TEXT_IN_XHR, 1); - } else if (aResponseType == XMLHttpRequestResponseType::Moz_chunked_arraybuffer) { + if (aResponseType == XMLHttpRequestResponseType::Moz_chunked_arraybuffer) { Telemetry::Accumulate(Telemetry::MOZ_CHUNKED_ARRAYBUFFER_IN_XHR, 1); } @@ -755,7 +744,6 @@ XMLHttpRequestMainThread::GetResponse(JSContext* aCx, switch (mResponseType) { case XMLHttpRequestResponseType::_empty: case XMLHttpRequestResponseType::Text: - case XMLHttpRequestResponseType::Moz_chunked_text: { DOMString str; GetResponseText(str, aRv); @@ -1396,8 +1384,7 @@ XMLHttpRequestMainThread::DispatchProgressEvent(DOMEventTargetHelper* aTarget, mInLoadProgressEvent = false; // clear chunked responses after every progress event - if (mResponseType == XMLHttpRequestResponseType::Moz_chunked_text || - mResponseType == XMLHttpRequestResponseType::Moz_chunked_arraybuffer) { + if (mResponseType == XMLHttpRequestResponseType::Moz_chunked_arraybuffer) { mResponseBody.Truncate(); TruncateResponseText(); mResultArrayBuffer = nullptr; @@ -1703,8 +1690,7 @@ XMLHttpRequestMainThread::StreamReaderFunc(nsIInputStream* in, } } else if (xmlHttpRequest->mResponseType == XMLHttpRequestResponseType::_empty || xmlHttpRequest->mResponseType == XMLHttpRequestResponseType::Text || - xmlHttpRequest->mResponseType == XMLHttpRequestResponseType::Json || - xmlHttpRequest->mResponseType == XMLHttpRequestResponseType::Moz_chunked_text) { + xmlHttpRequest->mResponseType == XMLHttpRequestResponseType::Json) { NS_ASSERTION(!xmlHttpRequest->mResponseXML, "We shouldn't be parsing a doc here"); rv = xmlHttpRequest->AppendToResponseText(fromRawSegment, count); diff --git a/dom/xhr/tests/test_XHR.html b/dom/xhr/tests/test_XHR.html index 15c29c7ca72f..58a34f578eac 100644 --- a/dom/xhr/tests/test_XHR.html +++ b/dom/xhr/tests/test_XHR.html @@ -129,7 +129,6 @@ checkSetResponseType(xhr, "document"); checkSetResponseType(xhr, "arraybuffer"); checkSetResponseType(xhr, "blob"); checkSetResponseType(xhr, "json"); -checkSetResponseType(xhr, "moz-chunked-text"); checkSetResponseType(xhr, "moz-chunked-arraybuffer"); checkOpenThrows(xhr, "GET", "file_XHR_pass2.txt", false); @@ -142,7 +141,6 @@ checkSetResponseTypeThrows(xhr, "document"); checkSetResponseTypeThrows(xhr, "arraybuffer"); checkSetResponseTypeThrows(xhr, "blob"); checkSetResponseTypeThrows(xhr, "json"); -checkSetResponseTypeThrows(xhr, "moz-chunked-text"); checkSetResponseTypeThrows(xhr, "moz-chunked-arraybuffer"); xhr.send(null); checkSetResponseTypeThrows(xhr, "document"); diff --git a/dom/xhr/tests/test_html_in_xhr.html b/dom/xhr/tests/test_html_in_xhr.html index ccfb719474d6..33864e44ed0f 100644 --- a/dom/xhr/tests/test_html_in_xhr.html +++ b/dom/xhr/tests/test_html_in_xhr.html @@ -74,26 +74,11 @@ function testNonParsingText() { if (this.readyState == 4) { is(this.responseText.indexOf("\u042E"), -1, "Honored meta in text mode."); is(this.responseText.indexOf("\uFFFD"), 29, "Honored meta in text mode 2."); - testChunkedText(); - } - } - xhr.open("GET", "file_html_in_xhr2.html"); - xhr.responseType = "text"; - xhr.send(); -} - -function testChunkedText() { - xhr = new XMLHttpRequest(); - xhr.onprogress = function() { - is(this.responseText.indexOf("\u042E"), -1, "Honored meta in chunked text mode."); - } - xhr.onreadystatechange = function() { - if (this.readyState == 4) { testSyncXHR(); } } xhr.open("GET", "file_html_in_xhr2.html"); - xhr.responseType = "moz-chunked-text"; + xhr.responseType = "text"; xhr.send(); } diff --git a/dom/xhr/tests/test_xhr_progressevents.html b/dom/xhr/tests/test_xhr_progressevents.html index c1b43c345602..2586a3a90129 100644 --- a/dom/xhr/tests/test_xhr_progressevents.html +++ b/dom/xhr/tests/test_xhr_progressevents.html @@ -135,7 +135,6 @@ function* runTests() { { type: "document", text: true, nodata: true }, { type: "json", text: true, nodata: true }, { type: "", text: true }, - { type: "moz-chunked-text", text: true, chunked: true }, { type: "moz-chunked-arraybuffer", text: false, chunked: true }, ]; var responseType; diff --git a/dom/xhr/tests/xhr2_worker.js b/dom/xhr/tests/xhr2_worker.js index d355020c93b1..93dab612fa19 100644 --- a/dom/xhr/tests/xhr2_worker.js +++ b/dom/xhr/tests/xhr2_worker.js @@ -96,68 +96,5 @@ onmessage = function(event) { throw new Error("'document' type not working correctly"); } - // Make sure setting responseType before open or after send fails. - var exception; - - xhr = new XMLHttpRequest(); - xhr.open("GET", url); - xhr.responseType = "text"; - xhr.onload = function(event) { - if (event.target.response != refText) { - throw new Error("Bad response!"); - } - - xhr = new XMLHttpRequest(); - xhr.open("GET", url); - xhr.responseType = "moz-chunked-text"; - - var lastIndex = 0; - xhr.onprogress = function(event) { - if (refText.substr(lastIndex, xhr.response.length) != xhr.response) { - throw new Error("Bad chunk!"); - } - - lastIndex += xhr.response.length; - }; - - xhr.onload = function(event) { - if (lastIndex != refText.length) { - throw new Error("Didn't see all the data!"); - } - - setTimeout(function() { - if (xhr.response !== null) { - throw new Error("Should have gotten null response outside of event!"); - } - postMessage("done"); - }, 0); - } - - xhr.send(null); - }; - xhr.send(); - - exception = null; - - try { - xhr.responseType = "arraybuffer"; - } - catch(e) { - exception = e; - } - - if (!exception) { - throw new Error("Failed to throw when setting responseType after " + - "calling send()"); - } - - if (exception.name != "InvalidStateError") { - throw new Error("Unexpected error when setting responseType after " + - "calling send()"); - } - - if (exception.code != DOMException.INVALID_STATE_ERR) { - throw new Error("Unexpected error code when setting responseType after " + - "calling send()"); - } + postMessage("done"); } diff --git a/testing/web-platform/meta/XMLHttpRequest/historical.html.ini b/testing/web-platform/meta/XMLHttpRequest/historical.html.ini index ad3e49b967c0..10ee7f520b69 100644 --- a/testing/web-platform/meta/XMLHttpRequest/historical.html.ini +++ b/testing/web-platform/meta/XMLHttpRequest/historical.html.ini @@ -1,8 +1,5 @@ [historical.html] type: testharness - [Support for responseType = moz-chunked-text] - expected: FAIL - [Support for responseType = moz-chunked-arraybuffer] expected: FAIL diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index fc95df148393..3748905116e0 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -12963,15 +12963,6 @@ "bug_numbers": [1331804], "description": "The time a given main thread runnable took to run (in milliseconds). The key comes from the runnables nsINamed::name value." }, - "MOZ_CHUNKED_TEXT_IN_XHR": { - "record_in_processes": ["main", "content"], - "alert_emails": ["amarchesini@mozilla.com"], - "expires_in_version": "58", - "kind": "boolean", - "bug_numbers": [1335365], - "releaseChannelCollection": "opt-out", - "description": "XMLHttpRequest.responseType set to moz-chunked-text" - }, "MOZ_CHUNKED_ARRAYBUFFER_IN_XHR": { "record_in_processes": ["main", "content"], "alert_emails": ["amarchesini@mozilla.com"], From 0e67001f675552c01e364cb705d81acd066a1667 Mon Sep 17 00:00:00 2001 From: Stone Shih Date: Mon, 4 Sep 2017 17:34:52 +0800 Subject: [PATCH 03/37] Bug 1344108 Part1: Fire lostpointercapture event immediately after pointerup/pointercancel. r=smaug. MozReview-Commit-ID: DlSqgyWqQrV --- layout/base/PresShell.cpp | 48 +++++++++------------------------------ 1 file changed, 11 insertions(+), 37 deletions(-) diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp index 4ca35ffe1466..5472cd84eb69 100644 --- a/layout/base/PresShell.cpp +++ b/layout/base/PresShell.cpp @@ -7109,32 +7109,6 @@ DispatchPointerFromMouseOrTouch(PresShell* aShell, return NS_OK; } -class ReleasePointerCaptureCaller final -{ -public: - ReleasePointerCaptureCaller() - : mPointerEvent(nullptr) - { - } - ~ReleasePointerCaptureCaller() - { - if (mPointerEvent) { - nsIPresShell::ReleasePointerCapturingContent(mPointerEvent->pointerId); - nsIPresShell::CheckPointerCaptureState(mPointerEvent); - } - } - - void SetTarget(const WidgetPointerEvent* aPointerEvent) - { - MOZ_ASSERT(aPointerEvent); - mPointerEvent = aPointerEvent; - } - -private: - // This is synchronously used inside PresShell::HandleEvent. - const WidgetPointerEvent* mPointerEvent; -}; - bool PresShell::CanDispatchEvent(const WidgetGUIEvent* aEvent) const { @@ -7351,7 +7325,6 @@ PresShell::HandleEvent(nsIFrame* aFrame, nsIFrame* frame = aFrame; if (aEvent->IsUsingCoordinates()) { - ReleasePointerCaptureCaller releasePointerCaptureCaller; if (mDocument) { if (aEvent->mClass == eTouchEventClass) { nsIDocument::UnlockPointer(); @@ -7621,16 +7594,6 @@ PresShell::HandleEvent(nsIFrame* aFrame, if (nsIFrame* capturingFrame = pointerCapturingContent->GetPrimaryFrame()) { frame = capturingFrame; } - - if (aEvent->mMessage == ePointerUp || - aEvent->mMessage == ePointerCancel) { - // Implicitly releasing capture for given pointer. - // ePointerLostCapture should be send after ePointerUp or - // ePointerCancel. - WidgetPointerEvent* pointerEvent = aEvent->AsPointerEvent(); - MOZ_ASSERT(pointerEvent); - releasePointerCaptureCaller.SetTarget(pointerEvent); - } } } } @@ -8193,6 +8156,17 @@ PresShell::HandleEventInternal(WidgetEvent* aEvent, nsContentUtils::SetIsHandlingKeyBoardEvent(wasHandlingKeyBoardEvent); + if (aEvent->mMessage == ePointerUp || + aEvent->mMessage == ePointerCancel) { + // Implicitly releasing capture for given pointer. + // ePointerLostCapture should be send after ePointerUp or + // ePointerCancel. + WidgetPointerEvent* pointerEvent = aEvent->AsPointerEvent(); + MOZ_ASSERT(pointerEvent); + nsIPresShell::ReleasePointerCapturingContent(pointerEvent->pointerId); + nsIPresShell::CheckPointerCaptureState(pointerEvent); + } + // 3. Give event to event manager for post event state changes and // generation of synthetic events. if (!mIsDestroying && NS_SUCCEEDED(rv)) { From 3d3f2e373224c80886fd87810db83c3f42f2af0c Mon Sep 17 00:00:00 2001 From: Stone Shih Date: Tue, 5 Sep 2017 10:37:14 +0800 Subject: [PATCH 04/37] Bug 1344108 Part2: Only prevent drag when capturing the pointer events by content. r=smaug. MozReview-Commit-ID: FENTYwMYdZr --- layout/base/PresShell.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp index 5472cd84eb69..fbe0d4a66ba0 100644 --- a/layout/base/PresShell.cpp +++ b/layout/base/PresShell.cpp @@ -6528,12 +6528,11 @@ nsIPresShell::GetPointerCaptureInfo(uint32_t aPointerId) /* static */ void nsIPresShell::ReleasePointerCapturingContent(uint32_t aPointerId) { - if (nsIDOMMouseEvent::MOZ_SOURCE_MOUSE == GetPointerType(aPointerId)) { - SetCapturingContent(nullptr, CAPTURE_PREVENTDRAG); - } - PointerCaptureInfo* pointerCaptureInfo = GetPointerCaptureInfo(aPointerId); - if (pointerCaptureInfo) { + if (pointerCaptureInfo && pointerCaptureInfo->mPendingContent) { + if (nsIDOMMouseEvent::MOZ_SOURCE_MOUSE == GetPointerType(aPointerId)) { + SetCapturingContent(nullptr, CAPTURE_PREVENTDRAG); + } pointerCaptureInfo->mPendingContent = nullptr; } } From 580c8e42f69fad211c1e0f4c8419f37d9273db21 Mon Sep 17 00:00:00 2001 From: Stone Shih Date: Thu, 9 Feb 2017 17:01:03 +0800 Subject: [PATCH 05/37] Bug 1344108 Part3: Enable pointerevent_sequence_at_implicit_release_on_drag-manual.html. r=smaug. MozReview-Commit-ID: AsMJc5Hpu3X --- dom/events/test/pointerevents/mochitest.ini | 2 ++ .../mochitest_support_external.js | 1 + ...ce_at_implicit_release_on_drag-manual.html | 27 +++++++++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 dom/events/test/pointerevents/test_pointerevent_sequence_at_implicit_release_on_drag-manual.html diff --git a/dom/events/test/pointerevents/mochitest.ini b/dom/events/test/pointerevents/mochitest.ini index 52e1905c883e..d53aa3450887 100644 --- a/dom/events/test/pointerevents/mochitest.ini +++ b/dom/events/test/pointerevents/mochitest.ini @@ -87,6 +87,8 @@ support-files = support-files = pointerevent_releasepointercapture_onpointerup_mouse-manual.html [test_pointerevent_releasepointercapture_release_right_after_capture-manual.html] support-files = pointerevent_releasepointercapture_release_right_after_capture-manual.html +[test_pointerevent_sequence_at_implicit_release_on_drag-manual.html] + support-files = pointerevent_sequence_at_implicit_release_on_drag-manual.html [test_pointerevent_setpointercapture_disconnected-manual.html] support-files = pointerevent_setpointercapture_disconnected-manual.html [test_pointerevent_setpointercapture_inactive_button_mouse-manual.html] diff --git a/dom/events/test/pointerevents/mochitest_support_external.js b/dom/events/test/pointerevents/mochitest_support_external.js index 9aa61627f07d..115a38caea59 100644 --- a/dom/events/test/pointerevents/mochitest_support_external.js +++ b/dom/events/test/pointerevents/mochitest_support_external.js @@ -186,6 +186,7 @@ function sendTouchEvent(int_win, elemId, touchEventType, params) { TouchEventHelper.TOUCH_STATE = true; // Set touch flag. break; case "touchend": + case "touchcancel": TouchEventHelper.TOUCH_STATE = false; // Clear touch flag. break; } diff --git a/dom/events/test/pointerevents/test_pointerevent_sequence_at_implicit_release_on_drag-manual.html b/dom/events/test/pointerevents/test_pointerevent_sequence_at_implicit_release_on_drag-manual.html new file mode 100644 index 000000000000..d98b91b5a1cc --- /dev/null +++ b/dom/events/test/pointerevents/test_pointerevent_sequence_at_implicit_release_on_drag-manual.html @@ -0,0 +1,27 @@ + + + + + W3C pointerevent_sequence_at_implicit_release_on_drag-manual.html in Mochitest form + + + + + + + + + From 3a42475049298792815677bd51c10e922325b922 Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Fri, 22 Sep 2017 08:10:41 +0200 Subject: [PATCH 06/37] Bug 1398733 - nsIDocShell::internalLoad should know the size of the post data inputStream, r=smaug --- docshell/base/nsDocShell.cpp | 41 ++++++++++++++++++++++------------- docshell/base/nsDocShell.h | 1 + docshell/base/nsIDocShell.idl | 3 +++ 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index d566bdde944d..7ac57aa834ad 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -1611,6 +1611,7 @@ nsDocShell::LoadURI(nsIURI* aURI, nullptr, // No type hint VoidString(), // No forced download postStream, + -1, // XXXbaku headersStream, loadType, nullptr, // No SHEntry @@ -5488,9 +5489,9 @@ nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL, mozilla::net::RP_Unset, nsContentUtils::GetSystemPrincipal(), nullptr, INTERNAL_LOAD_FLAGS_NONE, EmptyString(), - nullptr, VoidString(), nullptr, nullptr, LOAD_ERROR_PAGE, - nullptr, true, VoidString(), this, nullptr, false, - nullptr, nullptr); + nullptr, VoidString(), nullptr, -1, nullptr, + LOAD_ERROR_PAGE, nullptr, true, VoidString(), this, + nullptr, false, nullptr, nullptr); } NS_IMETHODIMP @@ -5591,6 +5592,7 @@ nsDocShell::Reload(uint32_t aReloadFlags) NS_LossyConvertUTF16toASCII(contentTypeHint).get(), VoidString(), // No forced download nullptr, // No post data + -1, // No post data length nullptr, // No headers data loadType, // Load type nullptr, // No SHEntry @@ -9709,6 +9711,7 @@ public: uint32_t aFlags, const char* aTypeHint, nsIInputStream* aPostData, + int64_t aPostDataLength, nsIInputStream* aHeadersData, uint32_t aLoadType, nsISHEntry* aSHEntry, @@ -9729,6 +9732,7 @@ public: , mTriggeringPrincipal(aTriggeringPrincipal) , mPrincipalToInherit(aPrincipalToInherit) , mPostData(aPostData) + , mPostDataLength(aPostDataLength) , mHeadersData(aHeadersData) , mSHEntry(aSHEntry) , mFlags(aFlags) @@ -9757,10 +9761,11 @@ public: mFlags, EmptyString(), mTypeHint.IsVoid() ? nullptr : mTypeHint.get(), - VoidString(), mPostData, mHeadersData, - mLoadType, mSHEntry, mFirstParty, - mSrcdoc, mSourceDocShell, mBaseURI, - mCheckForPrerender, nullptr, nullptr); + VoidString(), mPostData, mPostDataLength, + mHeadersData, mLoadType, mSHEntry, + mFirstParty, mSrcdoc, mSourceDocShell, + mBaseURI, mCheckForPrerender, nullptr, + nullptr); } private: @@ -9777,6 +9782,7 @@ private: nsCOMPtr mTriggeringPrincipal; nsCOMPtr mPrincipalToInherit; nsCOMPtr mPostData; + int64_t mPostDataLength; nsCOMPtr mHeadersData; nsCOMPtr mSHEntry; uint32_t mFlags; @@ -9828,6 +9834,7 @@ nsDocShell::InternalLoad(nsIURI* aURI, const char* aTypeHint, const nsAString& aFileName, nsIInputStream* aPostData, + int64_t aPostDataLength, nsIInputStream* aHeadersData, uint32_t aLoadType, nsISHEntry* aSHEntry, @@ -10228,6 +10235,7 @@ nsDocShell::InternalLoad(nsIURI* aURI, aTypeHint, VoidString(), // No forced download aPostData, + aPostDataLength, aHeadersData, aLoadType, aSHEntry, @@ -10319,9 +10327,9 @@ nsDocShell::InternalLoad(nsIURI* aURI, new InternalLoadEvent(this, aURI, aOriginalURI, aResultPrincipalURI, aLoadReplace, aReferrer, aReferrerPolicy, aTriggeringPrincipal, principalToInherit, - aFlags, aTypeHint, aPostData, aHeadersData, - aLoadType, aSHEntry, aFirstParty, aSrcdoc, - aSourceDocShell, aBaseURI, false); + aFlags, aTypeHint, aPostData, aPostDataLength, + aHeadersData, aLoadType, aSHEntry, aFirstParty, + aSrcdoc, aSourceDocShell, aBaseURI, false); return DispatchToTabGroup(TaskCategory::Other, ev.forget()); } @@ -10705,9 +10713,9 @@ nsDocShell::InternalLoad(nsIURI* aURI, new InternalLoadEvent(this, aURI, aOriginalURI, aResultPrincipalURI, aLoadReplace, aReferrer, aReferrerPolicy, aTriggeringPrincipal, principalToInherit, - aFlags, aTypeHint, aPostData, aHeadersData, - aLoadType, aSHEntry, aFirstParty, aSrcdoc, - aSourceDocShell, aBaseURI, false); + aFlags, aTypeHint, aPostData, aPostDataLength, + aHeadersData, aLoadType, aSHEntry, aFirstParty, + aSrcdoc, aSourceDocShell, aBaseURI, false); // We don't need any success handler since in that case // OnPartialSHistoryDeactive would be called, and it would ensure // docshell loads about:blank. @@ -10858,7 +10866,7 @@ nsDocShell::InternalLoad(nsIURI* aURI, !(aFlags & INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER), aReferrerPolicy, aTriggeringPrincipal, principalToInherit, aTypeHint, - aFileName, aPostData, aHeadersData, + aFileName, aPostData, aPostDataLength, aHeadersData, aFirstParty, aDocShell, getter_AddRefs(req), (aFlags & INTERNAL_LOAD_FLAGS_FIRST_LOAD) != 0, (aFlags & INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER) != 0, @@ -11000,6 +11008,7 @@ nsDocShell::DoURILoad(nsIURI* aURI, const char* aTypeHint, const nsAString& aFileName, nsIInputStream* aPostData, + int64_t aPostDataLength, nsIInputStream* aHeadersData, bool aFirstParty, nsIDocShell** aDocShell, @@ -11426,7 +11435,7 @@ nsDocShell::DoURILoad(nsIURI* aURI, } // we really need to have a content type associated with this stream!! - postChannel->SetUploadStream(aPostData, EmptyCString(), -1); + postChannel->SetUploadStream(aPostData, EmptyCString(), aPostDataLength); } /* If there is a valid postdata *and* it is a History Load, @@ -12886,6 +12895,7 @@ nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType) contentType.get(), // Type hint VoidString(), // No forced file download postData, // Post data stream + -1, // Post data stream length nullptr, // No headers stream aLoadType, // Load type aEntry, // SHEntry @@ -14450,6 +14460,7 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent, NS_LossyConvertUTF16toASCII(typeHint).get(), aFileName, // Download as file aPostDataStream, // Post data stream + -1, // Post data stream length XXXbaku aHeadersDataStream, // Headers stream LOAD_LINK, // Load type nullptr, // No SHEntry diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h index f8c54034870f..813bbc5bc249 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -435,6 +435,7 @@ protected: const char* aTypeHint, const nsAString& aFileName, nsIInputStream* aPostData, + int64_t aPostDataLength, nsIInputStream* aHeadersData, bool aFirstParty, nsIDocShell** aDocShell, diff --git a/docshell/base/nsIDocShell.idl b/docshell/base/nsIDocShell.idl index 6f93e2140d05..ebc99aa9a5ab 100644 --- a/docshell/base/nsIDocShell.idl +++ b/docshell/base/nsIDocShell.idl @@ -173,6 +173,8 @@ interface nsIDocShell : nsIDocShellTreeItem * @param aFileName - Non-null when the link should be downloaded as the given filename. * @param aPostDataStream - Post data stream (if POSTing) + * @param aPostDataStreamLength - Post data stream length. Use -1 if the length + of the stream is unknown. * @param aHeadersStream - Stream containing "extra" request headers... * @param aLoadFlags - Flags to modify load behaviour. Flags are defined * in nsIWebNavigation. @@ -198,6 +200,7 @@ interface nsIDocShell : nsIDocShellTreeItem in string aTypeHint, in AString aFileName, in nsIInputStream aPostDataStream, + in long long aPostDataStreamLength, in nsIInputStream aHeadersStream, in unsigned long aLoadFlags, in nsISHEntry aSHEntry, From cee83bc9688dd04e7dc5b6ee24300bf1810fa57e Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Fri, 22 Sep 2017 08:11:18 +0200 Subject: [PATCH 07/37] Bug 1398733 - nsILinkHandler::OnLinkClick and OnLinkClickSync should know the post data inputStream length, r=smaug --- docshell/base/nsDocShell.cpp | 15 +++++++++++---- docshell/base/nsDocShell.h | 2 ++ docshell/base/nsILinkHandler.h | 7 ++++++- dom/base/nsContentUtils.cpp | 3 ++- dom/html/HTMLFormElement.cpp | 3 ++- dom/plugins/base/nsPluginInstanceOwner.cpp | 2 +- 6 files changed, 24 insertions(+), 8 deletions(-) diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 7ac57aa834ad..f74651a9c9e6 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -14185,6 +14185,7 @@ public: const char16_t* aTargetSpec, const nsAString& aFileName, nsIInputStream* aPostDataStream, + int64_t aPostDataStreamLength, nsIInputStream* aHeadersDataStream, bool aNoOpenerImplied, bool aIsTrusted, @@ -14203,8 +14204,8 @@ public: if (mIsTrusted || jsapi.Init(mContent->OwnerDoc()->GetScopeObject())) { mHandler->OnLinkClickSync(mContent, mURI, mTargetSpec.get(), mFileName, - mPostDataStream, mHeadersDataStream, - mNoOpenerImplied, + mPostDataStream, mPostDataStreamLength, + mHeadersDataStream, mNoOpenerImplied, nullptr, nullptr, mTriggeringPrincipal); } return NS_OK; @@ -14216,6 +14217,7 @@ private: nsString mTargetSpec; nsString mFileName; nsCOMPtr mPostDataStream; + int64_t mPostDataStreamLength; nsCOMPtr mHeadersDataStream; nsCOMPtr mContent; PopupControlState mPopupState; @@ -14230,6 +14232,7 @@ OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler, const char16_t* aTargetSpec, const nsAString& aFileName, nsIInputStream* aPostDataStream, + int64_t aPostDataStreamLength, nsIInputStream* aHeadersDataStream, bool aNoOpenerImplied, bool aIsTrusted, @@ -14240,6 +14243,7 @@ OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler, , mTargetSpec(aTargetSpec) , mFileName(aFileName) , mPostDataStream(aPostDataStream) + , mPostDataStreamLength(aPostDataStreamLength) , mHeadersDataStream(aHeadersDataStream) , mContent(aContent) , mPopupState(mHandler->mScriptGlobal->GetPopupControlState()) @@ -14255,6 +14259,7 @@ nsDocShell::OnLinkClick(nsIContent* aContent, const char16_t* aTargetSpec, const nsAString& aFileName, nsIInputStream* aPostDataStream, + int64_t aPostDataStreamLength, nsIInputStream* aHeadersDataStream, bool aIsTrusted, nsIPrincipal* aTriggeringPrincipal) @@ -14300,7 +14305,8 @@ nsDocShell::OnLinkClick(nsIContent* aContent, nsCOMPtr ev = new OnLinkClickEvent(this, aContent, aURI, target.get(), aFileName, - aPostDataStream, aHeadersDataStream, noOpenerImplied, + aPostDataStream, aPostDataStreamLength, + aHeadersDataStream, noOpenerImplied, aIsTrusted, aTriggeringPrincipal); return DispatchToTabGroup(TaskCategory::UI, ev.forget()); } @@ -14311,6 +14317,7 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent, const char16_t* aTargetSpec, const nsAString& aFileName, nsIInputStream* aPostDataStream, + int64_t aPostDataStreamLength, nsIInputStream* aHeadersDataStream, bool aNoOpenerImplied, nsIDocShell** aDocShell, @@ -14460,7 +14467,7 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent, NS_LossyConvertUTF16toASCII(typeHint).get(), aFileName, // Download as file aPostDataStream, // Post data stream - -1, // Post data stream length XXXbaku + aPostDataStreamLength, // Post data stream length aHeadersDataStream, // Headers stream LOAD_LINK, // Load type nullptr, // No SHEntry diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h index 813bbc5bc249..42f703f58b01 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -210,6 +210,7 @@ public: const char16_t* aTargetSpec, const nsAString& aFileName, nsIInputStream* aPostDataStream, + int64_t aPostDataStreamLength, nsIInputStream* aHeadersDataStream, bool aIsTrusted, nsIPrincipal* aTriggeringPrincipal) override; @@ -218,6 +219,7 @@ public: const char16_t* aTargetSpec, const nsAString& aFileName, nsIInputStream* aPostDataStream = 0, + int64_t aPostDataStreamLength = -1, nsIInputStream* aHeadersDataStream = 0, bool aNoOpenerImplied = false, nsIDocShell** aDocShell = 0, diff --git a/docshell/base/nsILinkHandler.h b/docshell/base/nsILinkHandler.h index 5f76328e9d13..d28f0b487fb4 100644 --- a/docshell/base/nsILinkHandler.h +++ b/docshell/base/nsILinkHandler.h @@ -33,8 +33,10 @@ public: * @param aURI a URI object that defines the destination for the link * @param aTargetSpec indicates where the link is targeted (may be an empty * string) - * @param aPostDataStream the POST data to send * @param aFileName non-null when the link should be downloaded as the given file + * @param aPostDataStream the POST data to send + * @param aPostDataStreamLength the POST data length. Use -1 if the length is + * unknown. * @param aHeadersDataStream ??? * @param aIsTrusted false if the triggerer is an untrusted DOM event. * @param aTriggeringPrincipal, if not passed explicitly we fall back to @@ -45,6 +47,7 @@ public: const char16_t* aTargetSpec, const nsAString& aFileName, nsIInputStream* aPostDataStream, + int64_t aPostDataStreamLength, nsIInputStream* aHeadersDataStream, bool aIsTrusted, nsIPrincipal* aTriggeringPrincipal) = 0; @@ -61,6 +64,7 @@ public: * string) * @param aFileName non-null when the link should be downloaded as the given file * @param aPostDataStream the POST data to send + * @param aPostDataStreamLength the POST data length * @param aHeadersDataStream ??? * @param aNoOpenerImplied if the link implies "noopener" * @param aDocShell (out-param) the DocShell that the request was opened on @@ -73,6 +77,7 @@ public: const char16_t* aTargetSpec, const nsAString& aFileName, nsIInputStream* aPostDataStream = 0, + int64_t aPostDataStreamLength = -1, nsIInputStream* aHeadersDataStream = 0, bool aNoOpenerImplied = false, nsIDocShell** aDocShell = 0, diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index 62356a436e8e..854d0855f91e 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -5550,7 +5550,8 @@ nsContentUtils::TriggerLink(nsIContent *aContent, nsPresContext *aPresContext, handler->OnLinkClick(aContent, aLinkURI, fileName.IsVoid() ? aTargetSpec.get() : EmptyString().get(), - fileName, nullptr, nullptr, aIsTrusted, aContent->NodePrincipal()); + fileName, nullptr, -1, nullptr, aIsTrusted, + aContent->NodePrincipal()); } } diff --git a/dom/html/HTMLFormElement.cpp b/dom/html/HTMLFormElement.cpp index 2afcfeea9432..703a68a1a240 100644 --- a/dom/html/HTMLFormElement.cpp +++ b/dom/html/HTMLFormElement.cpp @@ -803,7 +803,8 @@ HTMLFormElement::SubmitSubmission(HTMLFormSubmission* aFormSubmission) rv = linkHandler->OnLinkClickSync(this, actionURI, target.get(), VoidString(), - postDataStream, nullptr, false, + postDataStream, -1 /* XXXbaku */, + nullptr, false, getter_AddRefs(docShell), getter_AddRefs(mSubmittingRequest)); NS_ENSURE_SUBMIT_SUCCESS(rv); diff --git a/dom/plugins/base/nsPluginInstanceOwner.cpp b/dom/plugins/base/nsPluginInstanceOwner.cpp index 733c2396340d..3c1b4dee59d2 100644 --- a/dom/plugins/base/nsPluginInstanceOwner.cpp +++ b/dom/plugins/base/nsPluginInstanceOwner.cpp @@ -492,7 +492,7 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL, } rv = lh->OnLinkClick(content, uri, unitarget.get(), VoidString(), - aPostStream, headersDataStream, true, triggeringPrincipal); + aPostStream, -1, headersDataStream, true, triggeringPrincipal); return rv; } From 79eff427b5c7478a949e5c7699e9cfb1ce52bfb4 Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Fri, 22 Sep 2017 08:12:03 +0200 Subject: [PATCH 08/37] Bug 1398733 - HTMLFormSubmission should pass the size of the post data inputStream if known, r=smaug --- dom/base/FormData.cpp | 3 ++- dom/base/FormData.h | 3 ++- dom/html/HTMLFormElement.cpp | 6 ++++-- dom/html/HTMLFormSubmission.cpp | 29 ++++++++++++++++++++++------- dom/html/HTMLFormSubmission.h | 7 +++++-- 5 files changed, 35 insertions(+), 13 deletions(-) diff --git a/dom/base/FormData.cpp b/dom/base/FormData.cpp index 2370fb3bac44..947c6cce2d64 100644 --- a/dom/base/FormData.cpp +++ b/dom/base/FormData.cpp @@ -103,7 +103,8 @@ NS_INTERFACE_MAP_END // HTMLFormSubmission nsresult FormData::GetEncodedSubmission(nsIURI* aURI, - nsIInputStream** aPostDataStream) + nsIInputStream** aPostDataStream, + int64_t* aPostDataStreamLength) { NS_NOTREACHED("Shouldn't call FormData::GetEncodedSubmission"); return NS_OK; diff --git a/dom/base/FormData.h b/dom/base/FormData.h index e213db1646b4..373065b07e25 100644 --- a/dom/base/FormData.h +++ b/dom/base/FormData.h @@ -113,7 +113,8 @@ public: // HTMLFormSubmission virtual nsresult - GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream) override; + GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream, + int64_t* aPostDataStreamLength) override; virtual nsresult AddNameValuePair(const nsAString& aName, const nsAString& aValue) override diff --git a/dom/html/HTMLFormElement.cpp b/dom/html/HTMLFormElement.cpp index 703a68a1a240..936dada73d76 100644 --- a/dom/html/HTMLFormElement.cpp +++ b/dom/html/HTMLFormElement.cpp @@ -796,14 +796,16 @@ HTMLFormElement::SubmitSubmission(HTMLFormSubmission* aFormSubmission) nullptr, doc); nsCOMPtr postDataStream; + int64_t postDataStreamLength = -1; rv = aFormSubmission->GetEncodedSubmission(actionURI, - getter_AddRefs(postDataStream)); + getter_AddRefs(postDataStream), + &postDataStreamLength); NS_ENSURE_SUBMIT_SUCCESS(rv); rv = linkHandler->OnLinkClickSync(this, actionURI, target.get(), VoidString(), - postDataStream, -1 /* XXXbaku */, + postDataStream, postDataStreamLength, nullptr, false, getter_AddRefs(docShell), getter_AddRefs(mSubmittingRequest)); diff --git a/dom/html/HTMLFormSubmission.cpp b/dom/html/HTMLFormSubmission.cpp index a249282cf8e2..4b3e722ecf5c 100644 --- a/dom/html/HTMLFormSubmission.cpp +++ b/dom/html/HTMLFormSubmission.cpp @@ -112,7 +112,8 @@ public: AddNameDirectoryPair(const nsAString& aName, Directory* aDirectory) override; virtual nsresult - GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream) override; + GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream, + int64_t* aPostDataStreamLength) override; protected: @@ -266,11 +267,13 @@ HandleMailtoSubject(nsCString& aPath) nsresult FSURLEncoded::GetEncodedSubmission(nsIURI* aURI, - nsIInputStream** aPostDataStream) + nsIInputStream** aPostDataStream, + int64_t* aPostDataStreamLength) { nsresult rv = NS_OK; *aPostDataStream = nullptr; + *aPostDataStreamLength = -1; if (mMethod == NS_FORM_METHOD_POST) { @@ -313,6 +316,8 @@ FSURLEncoded::GetEncodedSubmission(nsIURI* aURI, *aPostDataStream = mimeStream; NS_ADDREF(*aPostDataStream); + + *aPostDataStreamLength = mQueryString.Length(); } } else { @@ -615,7 +620,8 @@ FSMultipartFormData::AddDataChunk(const nsACString& aName, nsresult FSMultipartFormData::GetEncodedSubmission(nsIURI* aURI, - nsIInputStream** aPostDataStream) + nsIInputStream** aPostDataStream, + int64_t* aPostDataStreamLength) { nsresult rv; @@ -627,8 +633,10 @@ FSMultipartFormData::GetEncodedSubmission(nsIURI* aURI, nsAutoCString contentType; GetContentType(contentType); mimeStream->AddHeader("Content-Type", contentType.get()); - uint64_t unused; - mimeStream->SetData(GetSubmissionBody(&unused)); + + uint64_t bodySize; + mimeStream->SetData(GetSubmissionBody(&bodySize)); + *aPostDataStreamLength = bodySize; mimeStream.forget(aPostDataStream); @@ -677,7 +685,8 @@ public: AddNameDirectoryPair(const nsAString& aName, Directory* aDirectory) override; virtual nsresult - GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream) override; + GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream, + int64_t* aPostDataStreaLength) override; private: nsString mBody; @@ -716,10 +725,14 @@ FSTextPlain::AddNameDirectoryPair(const nsAString& aName, nsresult FSTextPlain::GetEncodedSubmission(nsIURI* aURI, - nsIInputStream** aPostDataStream) + nsIInputStream** aPostDataStream, + int64_t* aPostDataStreamLength) { nsresult rv = NS_OK; + *aPostDataStream = nullptr; + *aPostDataStreamLength = -1; + // XXX HACK We are using the standard URL mechanism to give the body to the // mailer instead of passing the post data stream to it, since that sounds // hard. @@ -770,6 +783,8 @@ FSTextPlain::GetEncodedSubmission(nsIURI* aURI, mimeStream->AddHeader("Content-Type", "text/plain"); mimeStream->SetData(bodyStream); CallQueryInterface(mimeStream, aPostDataStream); + + *aPostDataStreamLength = cbody.Length(); } return rv; diff --git a/dom/html/HTMLFormSubmission.h b/dom/html/HTMLFormSubmission.h index 7eea8f3924a9..dcaebcdad33b 100644 --- a/dom/html/HTMLFormSubmission.h +++ b/dom/html/HTMLFormSubmission.h @@ -84,9 +84,11 @@ public: * * @param aURI the URI being submitted to [INOUT] * @param aPostDataStream a data stream for POST data [OUT] + * @param aPostDataStreamLength a data stream for POST data length [OUT] */ virtual nsresult - GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream) = 0; + GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream, + int64_t* aPostDataStreamLength) = 0; /** * Get the charset that will be used for submission. @@ -165,7 +167,8 @@ public: AddNameDirectoryPair(const nsAString& aName, Directory* aDirectory) override; virtual nsresult - GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream) override; + GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream, + int64_t* aPostDataStreamLength) override; void GetContentType(nsACString& aContentType) { From 260dbfe5b2f769ed553038a49a20413c704e02ca Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Fri, 22 Sep 2017 08:12:19 +0200 Subject: [PATCH 09/37] Bug 1398733 - IPCBlobInputStream::Available() should return 0 before any AsyncWait() call, r=smaug --- dom/file/ipc/IPCBlobInputStream.cpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/dom/file/ipc/IPCBlobInputStream.cpp b/dom/file/ipc/IPCBlobInputStream.cpp index d6ea87bcef46..6d94900a0db2 100644 --- a/dom/file/ipc/IPCBlobInputStream.cpp +++ b/dom/file/ipc/IPCBlobInputStream.cpp @@ -162,21 +162,13 @@ IPCBlobInputStream::Available(uint64_t* aLength) { // We don't have a remoteStream yet. Let's return the full known size. if (mState == eInit || mState == ePending) { - *aLength = mLength; + *aLength = 0; return NS_OK; } if (mState == eRunning) { MOZ_ASSERT(mRemoteStream || mAsyncRemoteStream); - // This will go away eventually: an async input stream can return 0 in - // Available(), but this is not currently fully supported in the rest of - // gecko. - if (!mAsyncRemoteStream) { - *aLength = mLength; - return NS_OK; - } - nsresult rv = EnsureAsyncRemoteStream(); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; From 694413186835067a61dbfcdc8d42cffc317ab009 Mon Sep 17 00:00:00 2001 From: Dragana Damjanovic Date: Fri, 22 Sep 2017 09:09:57 +0200 Subject: [PATCH 10/37] Bug 1397686 - The streams that cannot do 0RTT data need to be put in list and added to mReadyForWrite when 0RTT is done. r=hurley --- netwerk/protocol/http/Http2Session.cpp | 15 +++++++++++++++ netwerk/protocol/http/Http2Session.h | 3 +++ 2 files changed, 18 insertions(+) diff --git a/netwerk/protocol/http/Http2Session.cpp b/netwerk/protocol/http/Http2Session.cpp index 42dd829dc73d..c652189a0e16 100644 --- a/netwerk/protocol/http/Http2Session.cpp +++ b/netwerk/protocol/http/Http2Session.cpp @@ -2769,6 +2769,9 @@ Http2Session::ReadSegmentsAgain(nsAHttpSegmentReader *reader, this, stream, stream->StreamID())); FlushOutputQueue(); SetWriteCallbacks(); + if (!mCannotDo0RTTStreams.Contains(stream)) { + mCannotDo0RTTStreams.AppendElement(stream); + } // We can still send our preamble *countRead = mOutputQueueUsed - mOutputQueueSent; return *countRead ? NS_OK : NS_BASE_STREAM_WOULD_BLOCK; @@ -3393,15 +3396,27 @@ Http2Session::Finish0RTT(bool aRestart, bool aAlpnChanged) // This is the easy case - early data failed, but we're speaking h2, so // we just need to rewind to the beginning of the preamble and try again. mOutputQueueSent = 0; + + for (size_t i = 0; i < mCannotDo0RTTStreams.Length(); ++i) { + if (mCannotDo0RTTStreams[i] && VerifyStream(mCannotDo0RTTStreams[i])) { + TransactionHasDataToWrite(mCannotDo0RTTStreams[i]); + } + } } } else { // 0RTT succeeded + for (size_t i = 0; i < mCannotDo0RTTStreams.Length(); ++i) { + if (mCannotDo0RTTStreams[i] && VerifyStream(mCannotDo0RTTStreams[i])) { + TransactionHasDataToWrite(mCannotDo0RTTStreams[i]); + } + } // Make sure we look for any incoming data in repsonse to our early data. Unused << ResumeRecv(); } mAttemptingEarlyData = false; m0RTTStreams.Clear(); + mCannotDo0RTTStreams.Clear(); RealignOutputQueue(); return NS_OK; diff --git a/netwerk/protocol/http/Http2Session.h b/netwerk/protocol/http/Http2Session.h index 87c4e8b9fcb9..4fdc175ab166 100644 --- a/netwerk/protocol/http/Http2Session.h +++ b/netwerk/protocol/http/Http2Session.h @@ -529,6 +529,9 @@ private: bool mAttemptingEarlyData; // The ID(s) of the stream(s) that we are getting 0RTT data from. nsTArray> 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> mCannotDo0RTTStreams; bool RealJoinConnection(const nsACString &hostname, int32_t port, bool jk); bool TestOriginFrame(const nsACString &name, int32_t port); From f875e0fd37fe1e3f2fc61ed82590c0c8dd69eff7 Mon Sep 17 00:00:00 2001 From: Lars T Hansen Date: Thu, 31 Aug 2017 12:24:13 +0200 Subject: [PATCH 11/37] Bug 1380033 - Tiering policy with time estimation. r=luke --HG-- extra : rebase_source : 614f93ad77e6583f313c502daf6f053e0bfdea1b extra : amend_source : a0634599778e06ca6ff87289b430c9cc10f69fe2 --- js/src/jit/ProcessExecutableMemory.cpp | 7 + js/src/jit/ProcessExecutableMemory.h | 5 + js/src/jsapi.cpp | 10 + js/src/jsapi.h | 14 + js/src/shell/js.cpp | 72 +++++ js/src/wasm/WasmCompile.cpp | 407 ++++++++++++++++++++++++- js/src/wasm/WasmGenerator.h | 8 +- js/src/wasm/WasmValidate.cpp | 28 +- js/src/wasm/WasmValidate.h | 37 ++- 9 files changed, 558 insertions(+), 30 deletions(-) diff --git a/js/src/jit/ProcessExecutableMemory.cpp b/js/src/jit/ProcessExecutableMemory.cpp index 9224824c9166..5dd04def0522 100644 --- a/js/src/jit/ProcessExecutableMemory.cpp +++ b/js/src/jit/ProcessExecutableMemory.cpp @@ -619,6 +619,13 @@ js::jit::ReleaseProcessExecutableMemory() execMemory.release(); } +size_t +js::jit::LikelyAvailableExecutableMemory() +{ + // Round down available memory to the closest MB. + return MaxCodeBytesPerProcess - AlignBytes(execMemory.bytesAllocated(), 0x100000U); +} + bool js::jit::CanLikelyAllocateMoreExecutableMemory() { diff --git a/js/src/jit/ProcessExecutableMemory.h b/js/src/jit/ProcessExecutableMemory.h index c578becb80e6..26a997168c94 100644 --- a/js/src/jit/ProcessExecutableMemory.h +++ b/js/src/jit/ProcessExecutableMemory.h @@ -50,6 +50,11 @@ extern void DeallocateExecutableMemory(void* addr, size_t bytes); // function. extern bool CanLikelyAllocateMoreExecutableMemory(); +// Returns a rough guess of how much executable memory remains available, +// rounded down to MB limit. Note this can fluctuate as other threads within +// the process allocate executable memory. +extern size_t LikelyAvailableExecutableMemory(); + } // namespace jit } // namespace js diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 1907b5873eff..a87079b1c5e2 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -7659,6 +7659,16 @@ JS::SetProcessLargeAllocationFailureCallback(JS::LargeAllocationFailureCallback OnLargeAllocationFailure = lafc; } +namespace js { + JS::SystemInformation gSysinfo; +} + +JS_PUBLIC_API(void) +JS::SetSystemInformation(const JS::SystemInformation* info) +{ + gSysinfo = *info; +} + JS_PUBLIC_API(void) JS::SetOutOfMemoryCallback(JSContext* cx, OutOfMemoryCallback cb, void* data) { diff --git a/js/src/jsapi.h b/js/src/jsapi.h index c970ad6dbe15..ba2d03e8e85f 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -6710,6 +6710,20 @@ typedef void extern JS_PUBLIC_API(void) SetProcessLargeAllocationFailureCallback(LargeAllocationFailureCallback afc); +/** + * SetSystemInformation() must be called to set up system information that + * SpiderMonkey requires. Normally this is setup is performed at the same time + * as callbacks are set up. The function copies the pointed-to structure. + */ + +struct JS_PUBLIC_API(SystemInformation) +{ + uint32_t maxCpuClockMHz; // 0 means "no information" +}; + +extern JS_PUBLIC_API(void) +SetSystemInformation(const SystemInformation* info); + /** * Unlike the error reporter, which is only called if the exception for an OOM * bubbles up and is not caught, the OutOfMemoryCallback is called immediately diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 2bb7e97120a7..21e16d07dac6 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -44,6 +44,9 @@ # include # include #endif +#ifdef XP_DARWIN +# include +#endif #include "jsapi.h" #include "jsarray.h" @@ -1330,6 +1333,70 @@ my_LargeAllocFailCallback() cx->runtime()->gc.gc(GC_NORMAL, JS::gcreason::SHARED_MEMORY_LIMIT); } +// Most of the GetCPUSpeed code was pilfered from xpcom/base/nsSystemInfo.cpp. +// Returns 0 if no information is available. + +static uint32_t +GetCPUSpeed() +{ + uint32_t cpuSpeed = 0; + + if (getenv("JS_CPU_MHZ")) + return atoi(getenv("JS_CPU_MHZ")); + +#if defined(XP_WIN) + + HKEY key; + static const WCHAR keyName[] = L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"; + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName , 0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) { + DWORD len = sizeof(data); + DWORD data; + if (RegQueryValueEx(key, L"~Mhz", 0, 0, reinterpret_cast(&data), + &len) == ERROR_SUCCESS) + { + cpuSpeed = static_cast(data); + } + RegCloseKey(key); + } + +#elif defined(XP_DARWIN) + + uint64_t sysctlValue64 = 0; + size_t len = sizeof(sysctlValue64); + if (!sysctlbyname("hw.cpufrequency_max", &sysctlValue64, &len, NULL, 0)) + cpuSpeed = static_cast(sysctlValue64 / 1000000); + +#elif defined(XP_UNIX) // Including Android + + // A known file contains the CPU frequency in KHz. + // + // This file should be present also on Android, it is on all of lth's + // Android devices (none of which are rooted), and on those devices it can + // be read by an app using stdio from C++ code. (Not sure if that's + // conclusive; the app was installed over adb, so what about permissions?) + // + // On multicore devices where the cores are not all equal this may actually + // be the wrong value: lth sees some other cpuN values that are higher than + // the cpu0 values. But it's unclear if those are the "little" CPUs in a + // BIG.little configuration, for example. + + FILE* fp = fopen("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq", "r"); + if (fp) { + char buf[128]; + if (fgets(buf, sizeof(buf), fp)) + cpuSpeed = uint32_t(atol(buf)/1000); + fclose(fp); + } + +#else + +# error "What OS is this?" + +#endif + + return cpuSpeed; +} + static const uint32_t CacheEntry_SOURCE = 0; static const uint32_t CacheEntry_BYTECODE = 1; @@ -8628,6 +8695,11 @@ main(int argc, char** argv, char** envp) JS::SetProcessLargeAllocationFailureCallback(my_LargeAllocFailCallback); + JS::SystemInformation info; + info.maxCpuClockMHz = GetCPUSpeed(); + + JS::SetSystemInformation(&info); + // Set some parameters to allow incremental GC in low memory conditions, // as is done for the browser, except in more-deterministic builds or when // disabled by command line options. diff --git a/js/src/wasm/WasmCompile.cpp b/js/src/wasm/WasmCompile.cpp index 18bce76b9060..71d9dba014cc 100644 --- a/js/src/wasm/WasmCompile.cpp +++ b/js/src/wasm/WasmCompile.cpp @@ -23,6 +23,7 @@ #include "jsprf.h" +#include "jit/ProcessExecutableMemory.h" #include "wasm/WasmBaselineCompile.h" #include "wasm/WasmBinaryIterator.h" #include "wasm/WasmGenerator.h" @@ -33,6 +34,21 @@ using namespace js; using namespace js::jit; using namespace js::wasm; +#define WASM_POLICY_SPEW + +#ifdef WASM_POLICY_SPEW +static void +PolicySpew(const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); +} +#else +# define PolicySpew(...) (void)0 +#endif + static bool DecodeFunctionBody(Decoder& d, ModuleGenerator& mg, uint32_t funcIndex) { @@ -103,10 +119,340 @@ CompileArgs::initFromContext(JSContext* cx, ScriptedCaller&& scriptedCaller) return assumptions.initBuildIdFromContext(cx); } -static bool -BackgroundWorkPossible() +namespace js { + extern JS::SystemInformation gSysinfo; +} + +enum class SystemClass { - return CanUseExtraThreads() && HelperThreadState().cpuCount > 1; + DesktopX86, + DesktopX64, + DesktopUnknown32, + DesktopUnknown64, + MobileX86, + MobileArm32, + MobileArm64, + MobileUnknown32, + MobileUnknown64 +}; + +// Classify the current system as one among the known classes. This really +// needs to get our tier-1 systems right. In cases where there's doubt about +// desktop vs mobile we could also try to use physical memory, core +// configuration, OS details, CPU speed, CPU class, or CPU manufacturer to +// disambiguate. This would factor into an additional dimension such as +// {low,medium,high}-end. + +static SystemClass +Classify() +{ + bool isDesktop; + +#if defined(ANDROID) || defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) + isDesktop = false; +#else + isDesktop = true; +#endif + + if (isDesktop) { +#if defined(JS_CODEGEN_X64) + return SystemClass::DesktopX64; +#elif defined(JS_CODEGEN_X86) + return SystemClass::DesktopX86; +#elif defined(JS_64BIT) + return SystemClass::DesktopUnknown64; +#else + return SystemClass::DesktopUnknown32; +#endif + } else { +#if defined(JS_CODEGEN_X86) + return SystemClass::MobileX86; +#elif defined(JS_CODEGEN_ARM) + return SystemClass::MobileArm32; +#elif defined(JS_CODEGEN_ARM64) + return SystemClass::MobileArm64; +#elif defined(JS_64BIT) + return SystemClass::MobileUnknown64; +#else + return SystemClass::MobileUnknown32; +#endif + } +} + +static bool +IsDesktop(SystemClass cls) +{ + return cls <= SystemClass::DesktopUnknown64; +} + +// An estimate of the local performance relative to the reference system. +// "Performance" should be some measure of clock speed and CPI for a realistic +// instruction mix. +// +// On desktop the reference system is a 16GB late-2013 MacBook Pro; on mobile a +// 2GB late-2014 Nvidia Jetson TK1 Tegra board. Both remain high-end as of +// late-2017. + +static double +RelativePerformance(SystemClass cls) +{ + // Note, cpu max clock frequency is an extremely crude approximation of + // speed. The reference MacBook Pro has a significantly lower max frequency + // than my older AMD tower, but is still a much faster system; the MBP has a + // slightly lower max frequency than my new high-end Xeon too, but the Xeon + // can barely keep up, even when tuned to avoid NUMA effects. + + // These values were recorded by running on the respective systems. + + const double referenceDesktopMaxMHz = 2600; // Haswell i7-4850HQ + const double referenceMobileMaxMHz = 2300; // Tegra Cortex-A15 + + if (gSysinfo.maxCpuClockMHz == 0) + return 1; + + // Since the reference systems are both quite fast, and we only have CPU + // clock speed to guide us right now, we will assume no systems are faster + // than the reference systems, regardless of clock speed. + + double referenceMaxMHz = IsDesktop(cls) ? referenceDesktopMaxMHz : referenceMobileMaxMHz; + return Min(1.0, gSysinfo.maxCpuClockMHz / referenceMaxMHz); +} + +// Various factors for the reference systems. These are based on empirical +// measurements except where marked "Guess". Relationships have been found to +// be roughly linear across program sizes, so there's no need to make this +// complicated. +// +// For the "Unknown" classifications we just have to pick a plausible proxy. + +// Compilation rates in bytecodes per millisecond. +static const double x64DesktopBytecodesPerMs = 2100; +static const double x86DesktopBytecodesPerMs = x64DesktopBytecodesPerMs / 1.4; +static const double arm32MobileBytecodesPerMs = x64DesktopBytecodesPerMs / 3.3; +static const double x86MobileBytecodesPerMs = x86DesktopBytecodesPerMs / 2.0; // Guess +static const double arm64MobileBytecodesPerMs = x86MobileBytecodesPerMs; // Guess + +static double +BytecodesPerMs(SystemClass cls) +{ + switch (cls) { + case SystemClass::DesktopX86: + case SystemClass::DesktopUnknown32: + return x86DesktopBytecodesPerMs; + case SystemClass::DesktopX64: + case SystemClass::DesktopUnknown64: + return x64DesktopBytecodesPerMs; + case SystemClass::MobileX86: + return x86MobileBytecodesPerMs; + case SystemClass::MobileArm32: + case SystemClass::MobileUnknown32: + return arm32MobileBytecodesPerMs; + case SystemClass::MobileArm64: + case SystemClass::MobileUnknown64: + return arm64MobileBytecodesPerMs; + default: + MOZ_CRASH(); + } +}; + +#ifndef JS_64BIT + +// Code sizes in machine code bytes per bytecode byte, again empirical except +// where marked as "Guess". + +static const double x64Tox86Inflation = 1.25; + +static const double x64IonBytesPerBytecode = 2.45; +static const double x86IonBytesPerBytecode = x64IonBytesPerBytecode * x64Tox86Inflation; +static const double arm32IonBytesPerBytecode = 3.3; +static const double arm64IonBytesPerBytecode = 3.0; // Guess + +static const double x64BaselineBytesPerBytecode = x64IonBytesPerBytecode * 1.43; +static const double x86BaselineBytesPerBytecode = x64BaselineBytesPerBytecode * x64Tox86Inflation; +static const double arm32BaselineBytesPerBytecode = arm32IonBytesPerBytecode * 1.39; +static const double arm64BaselineBytesPerBytecode = arm64IonBytesPerBytecode * 1.39; // Guess + +static double +IonBytesPerBytecode(SystemClass cls) +{ + switch (cls) { + case SystemClass::DesktopX86: + case SystemClass::MobileX86: + case SystemClass::DesktopUnknown32: + return x86IonBytesPerBytecode; + case SystemClass::DesktopX64: + case SystemClass::DesktopUnknown64: + return x64IonBytesPerBytecode; + case SystemClass::MobileArm32: + case SystemClass::MobileUnknown32: + return arm32IonBytesPerBytecode; + case SystemClass::MobileArm64: + case SystemClass::MobileUnknown64: + return arm64IonBytesPerBytecode; + default: + MOZ_CRASH(); + } +} + +static double +BaselineBytesPerBytecode(SystemClass cls) +{ + switch (cls) { + case SystemClass::DesktopX86: + case SystemClass::MobileX86: + case SystemClass::DesktopUnknown32: + return x86BaselineBytesPerBytecode; + case SystemClass::DesktopX64: + case SystemClass::DesktopUnknown64: + return x64BaselineBytesPerBytecode; + case SystemClass::MobileArm32: + case SystemClass::MobileUnknown32: + return arm32BaselineBytesPerBytecode; + case SystemClass::MobileArm64: + case SystemClass::MobileUnknown64: + return arm64BaselineBytesPerBytecode; + default: + MOZ_CRASH(); + } +} +#endif // !JS_64BIT + +static uint32_t +MillisToIonCompileOnThisSystem(SystemClass cls, uint32_t codeSize) +{ + return Max(1U, uint32_t(codeSize / BytecodesPerMs(cls) / RelativePerformance(cls))); +} + +static double +EffectiveCores(SystemClass cls, uint32_t cores) +{ + // cores^0.667 is crude but more realistic than cores^1, and probably not + // far off for the systems that run browsers (most have 2-4 hyperthreaded + // cores). + // + // To do better, we could examine the actual architecture: hyperthreads vs + // real cores, sizes of caches, architecture class. + + return pow(cores, 2.0/3.0); +} + +// Figure out whether we should use tiered compilation or not. +static bool +GetTieringEnabled(uint32_t codeSize) +{ + // If we can reasonably compile in less than 250ms, don't enable tiering. + const uint32_t timeCutoffMs = 250; + +#ifndef JS_64BIT + // If tiering will fill code memory to more than 90%, don't enable it. + const double spaceCutoffPct = 0.9; +#endif + + if (!CanUseExtraThreads()) { + PolicySpew("Tiering disabled : background-work-disabled\n"); + return false; + } + + uint32_t cpuCount = HelperThreadState().cpuCount; + MOZ_ASSERT(cpuCount > 0); + + // TODO: Investigate the multicore-required limitation. "It's always been + // this way" is insufficient justification. + // + // It's mostly sensible not to background compile when there's only one + // hardware thread as we want foreground computation to have access to that, + // but if wasm background compilation helper threads can be given lower + // priority then background compilation on single-core systems still makes + // some kind of sense. + // + // On desktop this is really a non-problem though, as of September 2017 + // 1-core was down to 3.5% of our population and falling. + + if (cpuCount == 1) { + PolicySpew("Tiering disabled : single-core\n"); + return false; + } + + DebugOnly threadCount = HelperThreadState().threadCount; + MOZ_ASSERT(threadCount >= cpuCount); + + // Compute the max number of threads available to do actual background + // compilation work. + // + // TODO: Here we can play around with the threadCount we /need/ rather than + // the threadCount we /have/, and feed the number we need into the + // scheduler. That requires a more sophisticated scheduler, though. + // + // TODO: Here we might also worry about the threadCount that is currently + // available, given what is going on elsewhere in the pipeline. In + // principle maxWasmCompilationThreads can encapsulate that, but it doesn't. + + uint32_t workers = HelperThreadState().maxWasmCompilationThreads(); + + // The number of cores we will use is bounded both by the CPU count and the + // worker count. + + uint32_t cores = Min(cpuCount, workers); + + SystemClass cls = Classify(); + + PolicySpew("Tiering system-info : class %d code-size %u bytecodes-per-ms %g relative-speed %g clock-mhz %u\n", + uint32_t(cls), codeSize, BytecodesPerMs(cls), RelativePerformance(cls), + gSysinfo.maxCpuClockMHz); + + // Ion compilation on available cores must take long enough to be worth the + // bother. Keep it simple and divide estimated ion time by the number of + // cores, don't worry about sequential sections or parallel overhead. + + uint32_t ms = MillisToIonCompileOnThisSystem(cls, codeSize); + + // Sadly, linear speedup is not a reality, so try to get a grip on what + // speedup is realistic on this system. + + double effective_cores = EffectiveCores(cls, cores); + + PolicySpew("Tiering estimation : single-core-ion-est %u num-cores %u effective-cores %g parallel-est %g\n", + ms, cores, effective_cores, ms / effective_cores); + + if ((ms / effective_cores) < timeCutoffMs) { + PolicySpew("Tiering disabled : ion-fast-enough\n"); + return false; + } + + // Do not implement a size cutoff for 64-bit systems since the code size + // budget for 64 bit is so large that it will hardly ever be an issue. + // (Also the cutoff percentage might be different on 64-bit.) + +#ifndef JS_64BIT + // If the amount of executable code for baseline compilation jeopardizes the + // availability of executable memory for ion code then do not tier, for now. + // + // TODO: For now we consider this module in isolation. We should really + // worry about what else is going on in this process and might be filling up + // the code memory. + + double ionRatio = IonBytesPerBytecode(cls); + double baselineRatio = BaselineBytesPerBytecode(cls); + uint64_t needMemory = codeSize * (ionRatio + baselineRatio); + uint64_t availMemory = LikelyAvailableExecutableMemory(); + double cutoff = spaceCutoffPct * MaxCodeBytesPerProcess; + + PolicySpew("Tiering memory-info : code-bytes %u ion-blowup %g baseline-blowup %g need %" PRIu64 + " max %" PRIu64 " avail %" PRIu64 " cutoff %" PRIu64 "\n", + codeSize, ionRatio, baselineRatio, needMemory, uint64_t(MaxCodeBytesPerProcess), + availMemory, uint64_t(cutoff)); + + // If the sum of baseline and ion code makes us exceeds some set percentage + // of the executable memory then disable tiering. + + if ((MaxCodeBytesPerProcess - availMemory) + needMemory > cutoff) { + PolicySpew("Tiering disabled : memory-budget\n"); + return false; + } +#endif + + PolicySpew("Tiering enabled : all-tests-pass\n"); + return true; } SharedModule @@ -118,32 +464,52 @@ wasm::CompileInitialTier(const ShareableBytes& bytecode, const CompileArgs& args bool debugEnabled = BaselineCanCompile() && args.debugEnabled; bool ionEnabled = args.ionEnabled || !baselineEnabled; - CompileMode mode; - Tier tier; - DebugEnabled debug; - if (BackgroundWorkPossible() && baselineEnabled && ionEnabled && !debugEnabled) { - mode = CompileMode::Tier1; - tier = Tier::Baseline; - debug = DebugEnabled::False; - } else { - mode = CompileMode::Once; - tier = debugEnabled || !ionEnabled ? Tier::Baseline : Tier::Ion; - debug = debugEnabled ? DebugEnabled::True : DebugEnabled::False; - } + DebugEnabled debug = debugEnabled ? DebugEnabled::True : DebugEnabled::False; - ModuleEnvironment env(mode, tier, debug); + ModuleEnvironment env(ModuleEnvironment::UnknownMode, ModuleEnvironment::UnknownTier, debug); Decoder d(bytecode.bytes, error); if (!DecodeModuleEnvironment(d, &env)) return nullptr; + uint32_t codeSize; + if (!d.peekSectionSize(SectionId::Code, &env, "code", &codeSize)) + codeSize = 0; + + CompileMode mode; + Tier tier; + if (baselineEnabled && ionEnabled && !debugEnabled && GetTieringEnabled(codeSize)) { + mode = CompileMode::Tier1; + tier = Tier::Baseline; + } else { + mode = CompileMode::Once; + tier = debugEnabled || !ionEnabled ? Tier::Baseline : Tier::Ion; + } + + env.setModeAndTier(mode, tier); + ModuleGenerator mg(args, &env, nullptr, error); if (!mg.init()) return nullptr; +#ifdef WASM_POLICY_SPEW + uint64_t before = PRMJ_Now(); +#endif + if (!DecodeCodeSection(d, mg, &env)) return nullptr; +#ifdef WASM_POLICY_SPEW + uint64_t after = PRMJ_Now(); + if (mode == CompileMode::Tier1) { + PolicySpew("Tiering tier-1 : baseline-parallel-time %" PRIu64 "\n", (after - before) / PRMJ_USEC_PER_MSEC); + } else { + PolicySpew("Tiering once : %s-parallel-time %" PRIu64 "\n", + tier == Tier::Baseline ? "baseline" : "ion", + (after - before) / PRMJ_USEC_PER_MSEC); + } +#endif + if (!DecodeModuleTail(d, &env)) return nullptr; @@ -166,9 +532,18 @@ wasm::CompileTier2(Module& module, const CompileArgs& args, Atomic* cancel if (!mg.init()) return false; +#ifdef WASM_POLICY_SPEW + uint64_t before = PRMJ_Now(); +#endif + if (!DecodeCodeSection(d, mg, &env)) return false; +#ifdef WASM_POLICY_SPEW + uint64_t after = PRMJ_Now(); + PolicySpew("Tiering tier-2 : ion-background-time %" PRIu64 "\n", (after - before) / PRMJ_USEC_PER_MSEC); +#endif + if (!DecodeModuleTail(d, &env)) return false; diff --git a/js/src/wasm/WasmGenerator.h b/js/src/wasm/WasmGenerator.h index 9b83114e2ed8..a6a1707612e4 100644 --- a/js/src/wasm/WasmGenerator.h +++ b/js/src/wasm/WasmGenerator.h @@ -144,10 +144,10 @@ class CompileTask return units_; } Tier tier() const { - return env_.tier; + return env_.tier(); } CompileMode mode() const { - return env_.mode; + return env_.mode(); } bool debugEnabled() const { return env_.debug == DebugEnabled::True; @@ -243,8 +243,8 @@ class MOZ_STACK_CLASS ModuleGenerator MOZ_MUST_USE bool initWasm(); bool isAsmJS() const { return env_->isAsmJS(); } - Tier tier() const { return env_->tier; } - CompileMode mode() const { return env_->mode; } + Tier tier() const { return env_->tier(); } + CompileMode mode() const { return env_->mode(); } bool debugEnabled() const { return env_->debugEnabled(); } public: diff --git a/js/src/wasm/WasmValidate.cpp b/js/src/wasm/WasmValidate.cpp index 31bb3143c43a..f08e0b11b6a3 100644 --- a/js/src/wasm/WasmValidate.cpp +++ b/js/src/wasm/WasmValidate.cpp @@ -60,7 +60,7 @@ Decoder::fail(size_t errorOffset, const char* msg) bool Decoder::startSection(SectionId id, ModuleEnvironment* env, uint32_t* sectionStart, - uint32_t* sectionSize, const char* sectionName) + uint32_t* sectionSize, const char* sectionName, bool peeking) { // Record state at beginning of section to allow rewinding to this point // if, after skipping through several custom sections, we don't find the @@ -85,8 +85,11 @@ Decoder::startSection(SectionId id, ModuleEnvironment* env, uint32_t* sectionSta // Rewind to the beginning of the current section since this is what // skipCustomSection() assumes. cur_ = currentSectionStart; - if (!skipCustomSection(env)) + if (!skipCustomSection(env)) { + if (peeking) + goto rewind; return false; + } // Having successfully skipped a custom section, consider the next // section. @@ -97,22 +100,39 @@ Decoder::startSection(SectionId id, ModuleEnvironment* env, uint32_t* sectionSta // Found it, now start the section. - if (!readVarU32(sectionSize) || bytesRemain() < *sectionSize) + if (!readVarU32(sectionSize) || bytesRemain() < *sectionSize) { + if (peeking) + goto rewind; goto fail; + } *sectionStart = cur_ - beg_; + if (peeking) + goto rewind_peeking; return true; rewind: + peeking = false; + rewind_peeking: cur_ = initialCur; env->customSections.shrinkTo(initialCustomSectionsLength); - *sectionStart = NotStarted; + if (!peeking) + *sectionStart = NotStarted; return true; fail: return failf("failed to start %s section", sectionName); } +bool +Decoder::peekSectionSize(SectionId id, ModuleEnvironment* env, const char* sectionName, uint32_t* sectionSize) +{ + uint32_t sectionStart; + if (!startSection(id, env, §ionStart, sectionSize, sectionName, /*peeking=*/true)) + return false; + return sectionStart != NotStarted; +} + bool Decoder::finishSection(uint32_t sectionStart, uint32_t sectionSize, const char* sectionName) { diff --git a/js/src/wasm/WasmValidate.h b/js/src/wasm/WasmValidate.h index 48dfeb1004b1..684eddd58a86 100644 --- a/js/src/wasm/WasmValidate.h +++ b/js/src/wasm/WasmValidate.h @@ -36,11 +36,14 @@ namespace wasm { struct ModuleEnvironment { // Constant parameters for the entire compilation: - const CompileMode mode; - const Tier tier; const DebugEnabled debug; const ModuleKind kind; + // Constant parameters determined no later than at the start of the code + // section: + CompileMode mode_; + Tier tier_; + // Module fields filled out incrementally during decoding: MemoryUsage memoryUsage; Atomic minMemoryLength; @@ -59,18 +62,35 @@ struct ModuleEnvironment NameInBytecodeVector funcNames; CustomSectionVector customSections; + static const CompileMode UnknownMode = (CompileMode)-1; + static const Tier UnknownTier = (Tier)-1; + explicit ModuleEnvironment(CompileMode mode = CompileMode::Once, Tier tier = Tier::Ion, DebugEnabled debug = DebugEnabled::False, ModuleKind kind = ModuleKind::Wasm) - : mode(mode), - tier(tier), - debug(debug), + : debug(debug), kind(kind), + mode_(mode), + tier_(tier), memoryUsage(MemoryUsage::None), minMemoryLength(0) {} + CompileMode mode() const { + MOZ_ASSERT(mode_ != UnknownMode); + return mode_; + } + Tier tier() const { + MOZ_ASSERT(tier_ != UnknownTier); + return tier_; + } + void setModeAndTier(CompileMode mode, Tier tier) { + MOZ_ASSERT(mode_ == UnknownMode); + MOZ_ASSERT(tier_ == UnknownTier); + mode_ = mode; + tier_ = tier; + } size_t numTables() const { return tables.length(); } @@ -546,10 +566,15 @@ class Decoder ModuleEnvironment* env, uint32_t* sectionStart, uint32_t* sectionSize, - const char* sectionName); + const char* sectionName, + bool peeking = false); MOZ_MUST_USE bool finishSection(uint32_t sectionStart, uint32_t sectionSize, const char* sectionName); + MOZ_MUST_USE bool peekSectionSize(SectionId id, + ModuleEnvironment* env, + const char* sectionName, + uint32_t* sectionSize); // Custom sections do not cause validation errors unless the error is in // the section header itself. From 815fd0045295488e835e9c38b21e1971457d7842 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Fri, 22 Sep 2017 10:37:16 +0100 Subject: [PATCH 12/37] Bug 1402049 - Remove support for using legacy Gecko normalization in gfxHarfBuzzShaper, as ICU is always available. r=jrmuizel --- gfx/thebes/gfxHarfBuzzShaper.cpp | 32 +++----------------------------- gfx/thebes/moz.build | 10 ++++------ 2 files changed, 7 insertions(+), 35 deletions(-) diff --git a/gfx/thebes/gfxHarfBuzzShaper.cpp b/gfx/thebes/gfxHarfBuzzShaper.cpp index e84b53db9bab..d1f370f14e72 100644 --- a/gfx/thebes/gfxHarfBuzzShaper.cpp +++ b/gfx/thebes/gfxHarfBuzzShaper.cpp @@ -12,20 +12,14 @@ #include "mozilla/Sprintf.h" #include "nsUnicodeProperties.h" #include "nsUnicodeScriptCodes.h" -#include "nsUnicodeNormalizer.h" #include "harfbuzz/hb.h" #include "harfbuzz/hb-ot.h" -#if ENABLE_INTL_API // ICU is available: we'll use it for Unicode composition - // and decomposition in preference to nsUnicodeNormalizer. #include "unicode/unorm.h" #include "unicode/utext.h" -#define MOZ_HB_SHAPER_USE_ICU_NORMALIZATION 1 -static const UNormalizer2 * sNormalizer = nullptr; -#else -#undef MOZ_HB_SHAPER_USE_ICU_NORMALIZATION -#endif + +static const UNormalizer2* sNormalizer = nullptr; #include @@ -1106,8 +1100,6 @@ HBUnicodeCompose(hb_unicode_funcs_t *ufuncs, hb_codepoint_t *ab, void *user_data) { -#if MOZ_HB_SHAPER_USE_ICU_NORMALIZATION - if (sNormalizer) { UChar32 ch = unorm2_composePair(sNormalizer, a, b); if (ch >= 0) { @@ -1116,14 +1108,6 @@ HBUnicodeCompose(hb_unicode_funcs_t *ufuncs, } } -#else // no ICU available, use the old nsUnicodeNormalizer - - if (nsUnicodeNormalizer::Compose(a, b, ab)) { - return true; - } - -#endif - return false; } @@ -1144,8 +1128,6 @@ HBUnicodeDecompose(hb_unicode_funcs_t *ufuncs, } #endif -#if MOZ_HB_SHAPER_USE_ICU_NORMALIZATION - if (!sNormalizer) { return false; } @@ -1177,12 +1159,6 @@ HBUnicodeDecompose(hb_unicode_funcs_t *ufuncs, utext_close(&text); return *b != 0 || *a != ab; - -#else // no ICU available, use the old nsUnicodeNormalizer - - return nsUnicodeNormalizer::DecomposeNonRecursively(ab, a, b); - -#endif } static void @@ -1265,11 +1241,9 @@ gfxHarfBuzzShaper::Initialize() HBUnicodeDecompose, nullptr, nullptr); -#if MOZ_HB_SHAPER_USE_ICU_NORMALIZATION UErrorCode error = U_ZERO_ERROR; sNormalizer = unorm2_getNFCInstance(&error); - NS_ASSERTION(U_SUCCESS(error), "failed to get ICU normalizer"); -#endif + MOZ_ASSERT(U_SUCCESS(error), "failed to get ICU normalizer"); } gfxFontEntry *entry = mFont->GetFontEntry(); diff --git a/gfx/thebes/moz.build b/gfx/thebes/moz.build index 9e4233cb1ca8..901ccf9c7e0e 100644 --- a/gfx/thebes/moz.build +++ b/gfx/thebes/moz.build @@ -233,12 +233,10 @@ if CONFIG['MOZ_ENABLE_SKIA_PDF']: 'PrintTargetSkPDF.cpp', ] -# We prefer to use ICU for normalization functions, but currently it is only -# available if we're building with the Intl API enabled: -if CONFIG['ENABLE_INTL_API']: - USE_LIBS += [ - 'icu', - ] +# We use ICU for normalization functions: +USE_LIBS += [ + 'icu', +] include('/ipc/chromium/chromium-config.mozbuild') From cc79ecacc0bdf5548cd083153e272aac0399c073 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Fri, 22 Sep 2017 10:37:17 +0100 Subject: [PATCH 13/37] Bug 1402090 - Remove obsolete ucdata code/tools, no longer used in the mozilla build. r=m_kato --- intl/unicharutil/tools/MUTTUCData.txt | 208 ---- intl/unicharutil/tools/UCDATAREADME.txt | 207 ---- intl/unicharutil/tools/data/case.dat | Bin 16592 -> 0 bytes intl/unicharutil/tools/data/cmbcl.dat | Bin 1388 -> 0 bytes intl/unicharutil/tools/data/ctype.dat | Bin 19196 -> 0 bytes intl/unicharutil/tools/data/decomp.dat | Bin 16272 -> 0 bytes intl/unicharutil/tools/data/num.dat | Bin 2976 -> 0 bytes intl/unicharutil/tools/format.txt | 243 ---- intl/unicharutil/tools/moz.build | 12 - intl/unicharutil/tools/ucgendat.c | 1457 ----------------------- intl/unicharutil/ucdata.c | 1162 ------------------ intl/unicharutil/ucdata.h | 306 ----- 12 files changed, 3595 deletions(-) delete mode 100644 intl/unicharutil/tools/MUTTUCData.txt delete mode 100644 intl/unicharutil/tools/UCDATAREADME.txt delete mode 100644 intl/unicharutil/tools/data/case.dat delete mode 100644 intl/unicharutil/tools/data/cmbcl.dat delete mode 100644 intl/unicharutil/tools/data/ctype.dat delete mode 100644 intl/unicharutil/tools/data/decomp.dat delete mode 100644 intl/unicharutil/tools/data/num.dat delete mode 100644 intl/unicharutil/tools/format.txt delete mode 100644 intl/unicharutil/tools/moz.build delete mode 100644 intl/unicharutil/tools/ucgendat.c delete mode 100644 intl/unicharutil/ucdata.c delete mode 100644 intl/unicharutil/ucdata.h diff --git a/intl/unicharutil/tools/MUTTUCData.txt b/intl/unicharutil/tools/MUTTUCData.txt deleted file mode 100644 index 7d44e290ac7a..000000000000 --- a/intl/unicharutil/tools/MUTTUCData.txt +++ /dev/null @@ -1,208 +0,0 @@ -# -# $Id: MUTTUCData.txt,v 1.1 1999/01/08 00:19:19 ftang%netscape.com Exp $ -# -# Copyright 1996, 1997, 1998 Computing Research Labs, -# New Mexico State University -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY -# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT -# OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR -# THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -# -# Implementation specific character properties. -# -# -# Space, other. -# -0009;;Ss;;;;;;;;;;;; -000A;;Ss;;;;;;;;;;;; -000B;;Ss;;;;;;;;;;;; -000C;;Ss;;;;;;;;;;;; -000D;;Ss;;;;;;;;;;;; -# -# Non-breaking. -# -00A0;;Nb;;;;;;;;;;;; -2007;;Nb;;;;;;;;;;;; -2011;;Nb;;;;;;;;;;;; -FEFF;;Nb;;;;;;;;;;;; -# -# Symmetric. -# -0028;;Sy;;;;;;;;;;;; -0029;;Sy;;;;;;;;;;;; -005B;;Sy;;;;;;;;;;;; -005D;;Sy;;;;;;;;;;;; -007B;;Sy;;;;;;;;;;;; -007D;;Sy;;;;;;;;;;;; -00AB;;Sy;;;;;;;;;;;; -00BB;;Sy;;;;;;;;;;;; -0F3A;;Sy;;;;;;;;;;;; -0F3B;;Sy;;;;;;;;;;;; -0F3C;;Sy;;;;;;;;;;;; -0F3D;;Sy;;;;;;;;;;;; -0F3E;;Sy;;;;;;;;;;;; -0F3F;;Sy;;;;;;;;;;;; -2018;;Sy;;;;;;;;;;;; -2019;;Sy;;;;;;;;;;;; -201A;;Sy;;;;;;;;;;;; -201B;;Sy;;;;;;;;;;;; -201C;;Sy;;;;;;;;;;;; -201D;;Sy;;;;;;;;;;;; -201E;;Sy;;;;;;;;;;;; -201F;;Sy;;;;;;;;;;;; -2039;;Sy;;;;;;;;;;;; -203A;;Sy;;;;;;;;;;;; -2045;;Sy;;;;;;;;;;;; -2046;;Sy;;;;;;;;;;;; -207D;;Sy;;;;;;;;;;;; -207E;;Sy;;;;;;;;;;;; -208D;;Sy;;;;;;;;;;;; -208E;;Sy;;;;;;;;;;;; -2329;;Sy;;;;;;;;;;;; -232A;;Sy;;;;;;;;;;;; -3008;;Sy;;;;;;;;;;;; -3009;;Sy;;;;;;;;;;;; -300A;;Sy;;;;;;;;;;;; -300B;;Sy;;;;;;;;;;;; -300C;;Sy;;;;;;;;;;;; -300D;;Sy;;;;;;;;;;;; -300E;;Sy;;;;;;;;;;;; -300F;;Sy;;;;;;;;;;;; -3010;;Sy;;;;;;;;;;;; -3011;;Sy;;;;;;;;;;;; -3014;;Sy;;;;;;;;;;;; -3015;;Sy;;;;;;;;;;;; -3016;;Sy;;;;;;;;;;;; -3017;;Sy;;;;;;;;;;;; -3018;;Sy;;;;;;;;;;;; -3019;;Sy;;;;;;;;;;;; -301A;;Sy;;;;;;;;;;;; -301B;;Sy;;;;;;;;;;;; -301D;;Sy;;;;;;;;;;;; -301E;;Sy;;;;;;;;;;;; -FD3E;;Sy;;;;;;;;;;;; -FD3F;;Sy;;;;;;;;;;;; -FE35;;Sy;;;;;;;;;;;; -FE36;;Sy;;;;;;;;;;;; -FE37;;Sy;;;;;;;;;;;; -FE38;;Sy;;;;;;;;;;;; -FE39;;Sy;;;;;;;;;;;; -FE3A;;Sy;;;;;;;;;;;; -FE3B;;Sy;;;;;;;;;;;; -FE3C;;Sy;;;;;;;;;;;; -FE3D;;Sy;;;;;;;;;;;; -FE3E;;Sy;;;;;;;;;;;; -FE3F;;Sy;;;;;;;;;;;; -FE40;;Sy;;;;;;;;;;;; -FE41;;Sy;;;;;;;;;;;; -FE42;;Sy;;;;;;;;;;;; -FE43;;Sy;;;;;;;;;;;; -FE44;;Sy;;;;;;;;;;;; -FE59;;Sy;;;;;;;;;;;; -FE5A;;Sy;;;;;;;;;;;; -FE5B;;Sy;;;;;;;;;;;; -FE5C;;Sy;;;;;;;;;;;; -FE5D;;Sy;;;;;;;;;;;; -FE5E;;Sy;;;;;;;;;;;; -FF08;;Sy;;;;;;;;;;;; -FF09;;Sy;;;;;;;;;;;; -FF3B;;Sy;;;;;;;;;;;; -FF3D;;Sy;;;;;;;;;;;; -FF5B;;Sy;;;;;;;;;;;; -FF5D;;Sy;;;;;;;;;;;; -FF62;;Sy;;;;;;;;;;;; -FF63;;Sy;;;;;;;;;;;; -# -# Hex digit. -# -0030;;Hd;;;;;;;;;;;; -0031;;Hd;;;;;;;;;;;; -0032;;Hd;;;;;;;;;;;; -0033;;Hd;;;;;;;;;;;; -0034;;Hd;;;;;;;;;;;; -0035;;Hd;;;;;;;;;;;; -0036;;Hd;;;;;;;;;;;; -0037;;Hd;;;;;;;;;;;; -0038;;Hd;;;;;;;;;;;; -0039;;Hd;;;;;;;;;;;; -0041;;Hd;;;;;;;;;;;; -0042;;Hd;;;;;;;;;;;; -0043;;Hd;;;;;;;;;;;; -0044;;Hd;;;;;;;;;;;; -0045;;Hd;;;;;;;;;;;; -0046;;Hd;;;;;;;;;;;; -0061;;Hd;;;;;;;;;;;; -0062;;Hd;;;;;;;;;;;; -0063;;Hd;;;;;;;;;;;; -0064;;Hd;;;;;;;;;;;; -0065;;Hd;;;;;;;;;;;; -0066;;Hd;;;;;;;;;;;; -FF10;;Hd;;;;;;;;;;;; -FF11;;Hd;;;;;;;;;;;; -FF12;;Hd;;;;;;;;;;;; -FF13;;Hd;;;;;;;;;;;; -FF14;;Hd;;;;;;;;;;;; -FF15;;Hd;;;;;;;;;;;; -FF16;;Hd;;;;;;;;;;;; -FF17;;Hd;;;;;;;;;;;; -FF18;;Hd;;;;;;;;;;;; -FF19;;Hd;;;;;;;;;;;; -FF21;;Hd;;;;;;;;;;;; -FF22;;Hd;;;;;;;;;;;; -FF23;;Hd;;;;;;;;;;;; -FF24;;Hd;;;;;;;;;;;; -FF25;;Hd;;;;;;;;;;;; -FF26;;Hd;;;;;;;;;;;; -FF41;;Hd;;;;;;;;;;;; -FF42;;Hd;;;;;;;;;;;; -FF43;;Hd;;;;;;;;;;;; -FF44;;Hd;;;;;;;;;;;; -FF45;;Hd;;;;;;;;;;;; -FF46;;Hd;;;;;;;;;;;; -# -# Quote marks. -# -0022;;Qm;;;;;;;;;;;; -0027;;Qm;;;;;;;;;;;; -00AB;;Qm;;;;;;;;;;;; -00BB;;Qm;;;;;;;;;;;; -2018;;Qm;;;;;;;;;;;; -2019;;Qm;;;;;;;;;;;; -201A;;Qm;;;;;;;;;;;; -201B;;Qm;;;;;;;;;;;; -201C;;Qm;;;;;;;;;;;; -201D;;Qm;;;;;;;;;;;; -201E;;Qm;;;;;;;;;;;; -201F;;Qm;;;;;;;;;;;; -2039;;Qm;;;;;;;;;;;; -203A;;Qm;;;;;;;;;;;; -300C;;Qm;;;;;;;;;;;; -300D;;Qm;;;;;;;;;;;; -300E;;Qm;;;;;;;;;;;; -300F;;Qm;;;;;;;;;;;; -301D;;Qm;;;;;;;;;;;; -301E;;Qm;;;;;;;;;;;; -301F;;Qm;;;;;;;;;;;; -FE41;;Qm;;;;;;;;;;;; -FE42;;Qm;;;;;;;;;;;; -FE43;;Qm;;;;;;;;;;;; -FE44;;Qm;;;;;;;;;;;; -FF02;;Qm;;;;;;;;;;;; -FF07;;Qm;;;;;;;;;;;; -FF62;;Qm;;;;;;;;;;;; -FF63;;Qm;;;;;;;;;;;; diff --git a/intl/unicharutil/tools/UCDATAREADME.txt b/intl/unicharutil/tools/UCDATAREADME.txt deleted file mode 100644 index 012098fc0697..000000000000 --- a/intl/unicharutil/tools/UCDATAREADME.txt +++ /dev/null @@ -1,207 +0,0 @@ -# -# $Id: UCDATAREADME.txt,v 1.1 1999/01/08 00:19:20 ftang%netscape.com Exp $ -# - - MUTT UCData Package 1.9 - ----------------------- - -This is a package that supports ctype-like operations for Unicode UCS-2 text -(and surrogates), case mapping, and decomposition lookup. To use it, you will -need to get the "UnicodeData-2.0.14.txt" (or later) file from the Unicode Web -or FTP site. - -This package consists of two parts: - - 1. A program called "ucgendat" which generates five data files from the - UnicodeData-2.*.txt file. The files are: - - A. case.dat - the case mappings. - B. ctype.dat - the character property tables. - C. decomp.dat - the character decompositions. - D. cmbcl.dat - the non-zero combining classes. - E. num.dat - the codes representing numbers. - - 2. The "ucdata.[ch]" files which implement the functions needed to - check to see if a character matches groups of properties, to map between - upper, lower, and title case, to look up the decomposition of a - character, look up the combining class of a character, and get the number - value of a character. - -A short reference to the functions available is in the "api.txt" file. - -Techie Details -============== - -The "ucgendat" program parses files from the command line which are all in the -Unicode Character Database (UCDB) format. An additional properties file, -"MUTTUCData.txt", provides some extra properties for some characters. - -The program looks for the two character properties fields (2 and 4), the -combining class field (3), the decomposition field (5), the numeric value -field (8), and the case mapping fields (12, 13, and 14). The decompositions -are recursively expanded before being written out. - -The decomposition table contains all the canonical decompositions. This means -all decompositions that do not have tags such as "" or "". - -The data is almost all stored as unsigned longs (32-bits assumed) and the -routines that load the data take care of endian swaps when necessary. This -also means that surrogates (>= 0x10000) can be placed in the data files the -"ucgendat" program parses. - -The data is written as external files and broken into five parts so it can be -selectively updated at runtime if necessary. - -The data files currently generated from the "ucgendat" program total about 56K -in size all together. - -The format of the binary data files is documented in the "format.txt" file. - -Mark Leisher -13 December 1998 - -CHANGES -======= - -Version 1.9 ------------ -1. Fixed a problem with an incorrect amount of storage being allocated for the - combining class nodes. - -2. Fixed an invalid initialization in the number code. - -3. Changed the Java template file formatting a bit. - -4. Added tables and function for getting decompositions in the Java class. - -Version 1.8 ------------ -1. Fixed a problem with adding certain ranges. - -2. Added two more macros for testing for identifiers. - -3. Tested with the UnicodeData-2.1.5.txt file. - -Version 1.7 ------------ -1. Fixed a problem with looking up decompositions in "ucgendat." - -Version 1.6 ------------ -1. Added two new properties introduced with UnicodeData-2.1.4.txt. - -2. Changed the "ucgendat.c" program a little to automatically align the - property data on a 4-byte boundary when new properties are added. - -3. Changed the "ucgendat.c" programs to only generate canonical - decompositions. - -4. Added two new macros ucisinitialpunct() and ucisfinalpunct() to check for - initial and final punctuation characters. - -5. Minor additions and changes to the documentation. - -Version 1.5 ------------ -1. Changed all file open calls to include binary mode with "b" for DOS/WIN - platforms. - -2. Wrapped the unistd.h include so it won't be included when compiled under - Win32. - -3. Fixed a bad range check for hex digits in ucgendat.c. - -4. Fixed a bad endian swap for combining classes. - -5. Added code to make a number table and associated lookup functions. - Functions added are ucnumber(), ucdigit(), and ucgetnumber(). The last - function is to maintain compatibility with John Cowan's "uctype" package. - -Version 1.4 ------------ -1. Fixed a bug with adding a range. - -2. Fixed a bug with inserting a range in order. - -3. Fixed incorrectly specified ucisdefined() and ucisundefined() macros. - -4. Added the missing unload for the combining class data. - -5. Fixed a bad macro placement in ucisweak(). - -Version 1.3 ------------ -1. Bug with case mapping calculations fixed. - -2. Bug with empty character property entries fixed. - -3. Bug with incorrect type in the combining class lookup fixed. - -4. Some corrections done to api.txt. - -5. Bug in certain character property lookups fixed. - -6. Added a character property table that records the defined characters. - -7. Replaced ucisunknown() with ucisdefined() and ucisundefined(). - -Version 1.2 ------------ -1. Added code to ucgendat to generate a combining class table. - -2. Fixed an endian problem with the byte count of decompositions. - -3. Fixed some minor problems in the "format.txt" file. - -4. Removed some bogus "Ss" values from MUTTUCData.txt file. - -5. Added API function to get combining class. - -6. Changed the open mode to "rb" so binary data files will be opened correctly - on DOS/WIN as well as other platforms. - -7. Added the "api.txt" file. - -Version 1.1 ------------ -1. Added ucisxdigit() which I overlooked. - -2. Added UC_LT to the ucisalpha() macro which I overlooked. - -3. Change uciscntrl() to include UC_CF. - -4. Added ucisocntrl() and ucfntcntrl() macros. - -5. Added a ucisblank() which I overlooked. - -6. Added missing properties to ucissymbol() and ucisnumber(). - -7. Added ucisgraph() and ucisprint(). - -8. Changed the "Mr" property to "Sy" to mark this subset of mirroring - characters as symmetric to avoid trampling the Unicode/ISO10646 sense of - mirroring. - -9. Added another property called "Ss" which includes control characters - traditionally seen as spaces in the isspace() macro. - -10. Added a bunch of macros to be API compatible with John Cowan's package. - -ACKNOWLEDGEMENTS -================ - -Thanks go to John Cowan for pointing out lots of -missing things and giving me stuff, particularly a bunch of new macros. - -Thanks go to Bob Verbrugge for pointing out -various bugs. - -Thanks go to Christophe Pierret for pointing -out that file modes need to have "b" for DOS/WIN machines, pointing out -unistd.h is not a Win 32 header, and pointing out a problem with ucisalnum(). - -Thanks go to Kent Johnson for finding a bug that caused -incomplete decompositions to be generated by the "ucgendat" program. - -Thanks go to Valeriy E. Ushakov for spotting an allocation -error and an initialization error. diff --git a/intl/unicharutil/tools/data/case.dat b/intl/unicharutil/tools/data/case.dat deleted file mode 100644 index 3bf7f2c932e30fd5fc02265e230f03e915853bbb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16592 zcmYk?W7M5zyM^J{jg7{(ZQE`e+qRk}joL=FV%xTD+iIMC)z|KG?#_Gc{o@?Rwbpps zrmJr-`pkd+?ih7Pqg!JBr8#STNyi$tU?`aRqRBv8g;hSu?xu> z)YaC+ZX|0_cUv2KkgP*JZC&g|vL5xe^|24h2GrL!#C{|jQGeSQ2as$+18q|rM6wwT zw#{(}$rd!!?!sFnchhaV2k(&FOLy%)yhn0B-M0tu0m*~(&>q4^BoEVLdjy}5JW5aP zF?>eyIQ?Qz;B%5E>4iOoFG-%JSN06PCV7_L*mL-npD{+Hwp`rAf`7$HJLl94E~je=20Mx*F92F4^Ai(=b2_#Vl)6wk)T1SAtu zBAXbKkW5O+Y;sING9{(5sWA=7_bIJShv`XXpo}&XW+s`1vf6Bzon#KmX>(z2l6fev z&4>E=B@0kNTL=r2EJ8(XaV$ZyB$cwIu?)$wRL+*i3M4C1C0iM*kgQ78Yz?eQvKH00 zb+9hUdQ{&wz=k9nQDfT#o04os&20;8N%8~w(0+uiNVcXnwk@_J*`7Msj@XH0XX;|R zVmFfAsfX=}y-4<^KDICRBiWw@*nv2R7~%Ct?%cmy@U|x13B|z|t`*ImA zw<~Z0@5`06%C5#qyf4?#WNx{Z*4g#Af#gP-&ezCIwApUM?Iicn0oqRo=`bClBXo?8 z(s4RrPvR+(r|FD6i|0t5rwjHXULtv!uGp)1jpPlwX>Z|el6UB?y@&TnKA?y85k4mQ zgr3@G_zTJB^uoTvH}sm`(mVSH{z>vL`mg;P{~;NH&oUy(NEF#d!KfsoQFI#vW0H(T zv27fDk7QhmXX9f6k_jo1O^iuMCZ%L{d}O|FNKT;Tb|S7IIf+)TQ0L^3l~wpp+W$*fe> zX2WVEvr~1O18b1XNi}UQtVJ?6)wX%C4#~V!*S5wsB->Iu+a5cR>`0w#XY4||h*1awrY6!*K-3ku=JV#xW$P(lk3AXONspU)rzm zYm(p4xAr^yp5zboqx}hgCOL~{+c`Lwh7vMsYi)gW3f=fv*qvdu5t|YmNR@*hW zmgG8GZ#UpZlACC=-GW<5ZlmpX2ks=foA%hfxR2yPI%JRHF_Nd~v^|4oNuHzg_5xlc zd5JFDD|nUUHM(wZ;7yXZ=(fFscS+u(`}P4oB>9LQ+b8&xN_4RI{VM)ZkojN?c)q49QBe7;{v&Zg6L4xS-7 zm(JRGc#h84$Uw@9w0 z+jb4!A-R_B+I4u3!&By&(s zn+tQ3%tLu?KFm+D02Q=_urSFYRMZy3;v`E@Nm~j_lPp7JZ8+3whbWKZg4dt)DxeW{=Aj{`^!q(OEt4k0;|hS}jbg5*dVWk=%} zk{{Dp`w5OCIi5bX6L2EQNi^9`!Ouv3PG8umIF00Vnqg<+mn3J=Y&!?%lAK5L?E+j# zauF@IOK>U4WwhL`z?CFd(Q3N}*OFXE>+J^INOBWxwp(y3$!)aV?!cWSchPRU2ltZP zNBivoJV^2o9kxgCD9K}V+@8RbBu~+4dj`*vJV)p41-wY|5?!`e@G8k`blu*-njrlDtRv?E`#B@)13@Pw*+pXY`AGjxR{Qq*wMez9IRR-q~OAKO}#n-))Sv{Mt-1 zCPlQdFcQhw6xqhXC?wybs5UM}BN>mP+vFIZWC}`PQ({7rsVI?6jfqL7p(HjNrX!i1 z(%T%Efn-j~XmepElDR3f&4XD;=B2E*80I5cobuZeSb$_nDrie#A(Ex3uq}f{NS39d zwi=crS)Iz;8d!m3O{!>XVI`8asj_X3^+~p*hW0~jOtKX`1Z~b+Qw1G|7oH#!kYINlvD*b_#w%@-rG|KgaPTzo1X;H#n8#w=~Uu zhto-ZPc!TfIFsa$^rig?zasfFeQg)vERu_9wq1gANG_$hb{Wnixt!+P6}W)pN?K?) z;VP1wX|>&gy-9ARK6V?fC3%SY+QZn7L0yA2i(li6cn`$@-4X__)?EcN|W#2aT{jaU{uJG|Fzs#OF+MBb~OJ z@C?b#bk=Ucb0oLYdAkiSklaoe?GC&|awlE3yYLFh-E`IN!D}S<(sjEJZ;;$iH|+tu zMe-oswukTz$-{Kl9>IGgkJ5d63?Gm@P7mz~d_?jjJ+|rp;nzTt8K{EIh!sg@qDnS1 zRwkK+s@SYpm1H)mX0u~;k~ye`&51Qh=Av3QH`XSZhw9k8SeIlzs%P_KeUb&Jfh~v) zNfx3;wlFp(S%jL{qS%yVF=}RuV{?)vsD*9AZ`b8rTdd&PVMW&-E4dC>*>%J!t`k;u zVdGGZ*Lnt9-Gz-q4PJ+hgLV#K<4}t`Y#g+62pfkw++pLOokMS`=fcK8JBP4wXuusd z4%#_{jYA{uuyN4NA#5C)aEFb9b`D|V(2RQsHFsg-(1O>uXqUThb!D+9#w##rt>jN{^AT$cdjyF{4K zCBeil876fpFu6;GDP0;&?b71=Es;(y1aJ8|PtBZA9eXQpi zVguJ08@Z;~#5Koet|hi`AL0kD6@KK}U~AV7+qw?e-gUx`t_yZ{-LR|cf!$p%?CJVo zZ`Tj|x&heV4Z?wLC=PMMahMy4Bity|uUl#?_s4D=e&QzJr)~;PcGGd1`xd`(vvHQ2 zi*ww3oaYwdLbn{3xmCE*t;4l$1FmMzIzh+XDLm=U z;AwXb&$heh0B~Tu%<8IPHdh_9yBe6o)x?~x7UpubF}JIOd0bu0>*`}f*8n5Ah8Wp3 z!YHmWMs-avnrn*DT{Dc~nqy4Y0%N(B7~6e-aok53*R{fUt_`+!?Xa!ufbCr;?C82+ zXV(q8x*piw^}?R65B7Hbu&*0{{oNoO=!W26Hw=fm5jfn9!jWzaj&{>-HBv)o*quat{2-^znEW)-z`--rw(9R-kE3~f& z+Y0S0!nQ*DimC+Wv6w4~C0uDN<;r3iS02l`idex_#!9X#R&mv_nyZO5Ty3o7>S7&N zAM3e>*uXW$My@F~am}%rYl$t~hxmbOg&(;#*xI$jwyp!Vcb%}K>w=wKH|*+qV0YIG zd%8Z@+x5e~ZUFXogK(f5f`i>K9O_2ka5oA^x-mG~jm3}MIQ+zYisRixoZu$oB=;Fk zabMu)ZW>N?GjO{55@)*aF?@!zxo5e#ILFP$d2S&taEoz~TZ&8Ea$M$C;tIDKSGl#g z#;wP7ZX<4Rn{kudid)=v+~#)T4!0Y3xxKi@?ZZsHAh8*jP0c*otxd+s4VaF6kkdx}roFZj&8z~}B2 zzI1Q!wR?we-GA^`_dEXPBBcHI`FsqFNHJX`jO8L@Y!?ONxTyG^i-vJsbd2ZXV{(@O zQ@Dhf(j~%FE-|KdNidB|huK_u%xYM3e>~y_;88aaued>Y z)rDujzwvqq{qBb16E_T>y6{Z+4_=R;Kiz1Y;KtxY_c2a#V{x+k1gE%h_?a7zpSw@- z3pW+NantZyHyyuoGw^#i6Mt}D;*aht{KdNzt;Wr6EpBr=Q2)Bpb8ql3*E>DGXSqJu z#`VRvt{=8@{jt3pfF0aG?C1tzCpQ>7yCK-c4aKf*7r++#fH%K!84v-si+No=%;)N3e%AmCxQ1BJ zHNrx!F&1`Bu!w7lMO}DSUyRqyskm!_C7hn4=y}Qk(sL9&PdQ9_j-ux&dak194SMdN H=MVn_w4G#A diff --git a/intl/unicharutil/tools/data/cmbcl.dat b/intl/unicharutil/tools/data/cmbcl.dat deleted file mode 100644 index 9a7513d8f8ce72a9de6782941977cba3437b6800..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1388 zcmXYxNl4UT07t)Q-#0Z!%|?ax4JvYCx>W==m1bSK6a*c*L`4T72o*aQRA^nIL;Jod zO+?Wlih(vtY-p89te|^fz2|%|&-eK8%{c!3&-@!Y81{?~A&d;61PWv+mI1m9Cm>H( zU~#X+(o0w2BzUF<*TM_B4$qDIJUl<{3-F4#uf+8*g7Ybyj{91?4tziBvHYQT;oUGu zw~Y#+13Yt_zd?KtC-6ydKZV8pH13Rh7nV=#XRvtYEItQ5_dLE3_lx*a+%IGC{1tpP z?$@yRn%D7-xZlJwf&CViiS%tOlju8GCewGZOrh^#nM&WsGL3$KWjfuBWd_}YWhVU) zO9`FDQc6FB|$&K;x%a)Q>2pKL`xN&!7`iPjHR01f@Kc96-$zC z#8N{yVX39}W2vLx<2)4T&-h#H?^wM4{a6b04?GZi5Q}Gi;$Lz9jm14ZzQ|ZQLko}4 z$PX#dO;|j?4L8RWud`@nm7aQSuDfnaW3v@ZUh-Vk2B!;92R>6H;6RT z87%JGvAFNRvXjnX@l1vrO6+=Ws1)p_*I;qqh#O#^=dsw`xCai?&+$uWp>tU5a&F87 zczsr3@w%>%FpjSNTcmB;vGd^ZZOsir8 zi;XTer&#Oam&T5XogDjO?1tD)v0uaTk?E}+uT`qLp8ihFS%?#Ea>jwkFX z`U+-ZF6LQwJdZneSYlET)WlQx8!G*rC;mtfoP~lsW|E8)T#U9DjuBXdC0L17ScA3L zY{@)6DHvgk=n}kRYv@`O;QlX&WJ{rP5nAICv_)qdL1hsZV=0zl1y*4-)?%|oc#I0_ zaY73W#|SL4C3HDfVii_n4L-mo6yR|!h-9Ro6?1_g6pc#R2r;KIwRH$fq7r9isFbslsZ_9vR8F@_RO0PSDpjo-l>|$qa;}|ECCO@2scZGAG_=N4np!g| zsn(oIOS_0l8*5ADQfp78gLS0R$*!W()w)yZX=zk?+ci}B*!5KU+D%mcVi{C!u>n+W zw>#-w7-WN~48w5TYxmLn@gN?;7(9x{Fdl!!lXwQtVj?mz*`BBJB3{DFHl50=n1Pv? zjn{21eFF<@IhB>Rn#wwRkIH)6NaX|DOywi{n96p`p|aCP9_63!%EW){2EJ~p!(yTX?Ypf5I>#Z-9o9r)CGVB&A1MGGx zciKQIciRvuLv1XTaWP9_7#lb`18YR3i6v7>u?wlRuvS!BTN^5E?NTc3tpk;g)``kh)|Eq#Ze zdQ-W^`cS#v`ck>c{z4_gZlN;3Zl`jm4Wx3n4WTmBhEuuM?xXU6jiNHz#!wk+fXX6ULS>mPr?SFUQCV$ksl031R5sZA zR5sa%RJPbwD%&lG%1+x&Wv_ioWxstvsML>AY+W#8i8o%A58H{SKU32mJFO63J7LN?|KXrI?kV zQqoFOImyaWDQ~AxIn_?1a)wo=QpL`qa<)~cQp3)na-P+sQp@U4sb?3^254kWs3cno zl?$x}l~&f8UW`ku9hJ-Maw=EYl~g)g7b@MX2bEryPUUL5mdbT@1C<-?W-9%xKb2eU zHY#`6Kq`0J5IPhiY$TNjY&3ls+u0LVVCWpvd=!F^0|FU zuBLLWT}R~xyOGMx){jbmyOqjqb_bQaY!H>fb`O~Shj*i%%Vwr8nKv`JK+vlpnmWG_>hX0K40VKb@Bw%4i5wRu$L+d?XfZ5fs2wu;JH zTTf-9eL!WieMIGB+eYOR+d*ZQ?V+;IKBMxv9iZ~HeM9A2`;kgI=f?LVn{(su5aAdr z1+6fZqE?Jb2`fpZw4Fqytd*y7ik(X3G&_SzWvfEvEIXS@b*n+;96OInO{+zvj@6@b zfiSvr-g?OH0=*$q@~ zw415)v;I_WwcDuNVRum(WP_>PW5cM7u#r^mw+E>_WDiq$#2%&cm_1IP#w2@=$_w@q zm6vTAl~-&Am6D-WuYymvee$9^0uv{@{X;cvd-S4vfegQ`M@?)`N%$| zvduoBvcq;!*<<^td}g0h`O*$h`P#mr@~wSOddj5J(_ z3=GCl+>fz%0-1OTS$GX|Fc*t#8C{MQSczLVh zWvv30^HCFZEnt152+HCVq~g0XlEQ!o`-m}PV5 zJZ!}_e1aV~h_6wYwUOc|jX0D=0uqsg+NgtisE-C{h%V@ko^}fzfRT6z58EU3Q9Onz zn2IdS!fd>bd01%KRC25^YbLQMjX0D=0uqsg+Ngv2Xo#lPo%TR4q+=vTVGPD%93ID0 z_#2+F33MW!!}FMesdyEyV=m^QFl$D!D1|tbK>`v{2ldbpX-LONjK&y@#W+mCRLsWf zn1}6_LwBGsYf`Z&g*cQ!0us>>X-G$e=XDZlqYhHg62mYY_uBpR0gSSTsf@=HcnT9S z3D4mLdx^?aOv5Y4!Ys_jLR&(YV=J~HV6971a1k!X4R`<#AvlTW5_(}Wrr<}^tHN^) zMfhEmRE)e>{s!EW$FZ#A>{U4cLq=*ot1< zWN8-9eTAR-8Kn+ivo6}tgTbD@U~rqY=EN19rzc%DlbVq>Tz za=%D1ejX`dC8?CQlcdJ3r%|bd%4o)YBK7$hq=7Y}(!`Rfq}YX2T3A;q-K{5; zV*LEl)Ot|4+W1us__2bs!7_D_Xy;NnA2rbkjnND#=x&p!%(cZ-1{CD{7enlRDqT6Y z_QHd>#Z-n5s_RzAB9mA#VwXfDU?P< zoQBGXM-xk@a*dr6Fa|>tB;#%yLS?$mq@tHp`QBQ@^PIsz+>KEfjj=ot#$$uMPbD~$ z^9{tD#d99nbW}oj>q%v&eM-MTRlbEx#tS&aw_sO+*A`Tj5AWqXxMmd&9uyilIccz(-I+$WO3 zIgDJ!eIpT`*9B1)r=TJ#qpsDb(!c^9(+CQp2x3qS;oY zv=8Wh9DPyYc~SsH5sS(=6A3s61EB}MDpJq}&)_rY1?h2Q;sAnb{EVoGeu(g5RR~2; z46&$=8n^`Q>@wN`o$M;w6Y01PeCC*%*NK@JQ;t*LV zIUR{;jx-FyJvNGFVF}hC8%Ge-VI2*Funjplg55lCoU+^nZ`IN3m$3RTA{Oc1- z`1?)JKA-QPb&78zd3zQ#2O7?Q<{zi!@c%SE3tz{>aoRuHcM$G32}>G%H6j`zZSi228T z;Xb=?{1@(1{Ab32$J*bRe_R;u>kIci{+V&2_DcTVKFR#!NbMuk>t?ur@xswG?jm={hQ&qG~5Rn?&mz-aq98z`^-O{4fk7y`$2zieEWO*MZ@uL zxPS9l<6zDE=oqK-xc}66IGlG1_mxJEkHh1wjL8ZKT-Awu;g35XGjTPt_h(}AbMmw}eXLPY{RC<`!5Lod_*{JsCfy^8|I&v&~ZKbcplF&I{)$fj~vJU&pbyC=PsN> zhx4gbav5VG64@ohN9 z)j0P`iypUX>{`)^^L2znR8SJ9qY@J0`B}gz%uyw%RJM33nWhhlAOv{h+y?AsCG@$i@zw==p#v_{Ho6%_kk52jG|VB$R{Zk)r1X>gmOl z*W2jv|G#V8ulMC>?4N(!ulYW$FKX^vV}89)EPA}J_ls$MCw#w{=Cn0`8_(elTZZ3p*g~MG=}Dtx9__H zFcCYUc>~R}Mb8^7;Vyq0EAbxIL-PY4VH{_L3_-$V;A<~APysXzM=)MyP~`qM;Vn_GqeFzZnrzB479tcM31N5oH@F1pR26C_q`|%~(^4ckvT6-!TtRt09b`_Pb)}2aE zOQX`;uBCFF-9RM+{c$S>;C9@ByD$)UV=%_s1S-?*RVrCFi^^*@hsqoFCY1%Yh{_UM zM&)f=N#z~Ort7g0?_(1-<0EXrR&2vz`=0)UBc^ee{E_wZOZoSiyuORZ0CJLr$D;)P zUk!A#9#jU|U@FsWJ{7G+>-?xfJhuxC(FiTk3WG5O4`U3p4z2Z89f!4^S`Jz_)p~Lz zgvVX2CF^*rHDMiBV{&=!qp>xm(#?8M>5Z$wmpVFLOr@=mjy?#-e^vN5)sTu-;3<4m zbt?IP&ip^0*37jwtlO>iUae*8_Uf1}MJ>ENymTKOKau}++-qNe^(#MU^tfac$G_owjv(ew4k8b9e85BcXc!g1_Bn%~g%Akv`u4P6)FxAt{u zoE6R+M0jAdW)Q9yG~v&>CWO`qIzq=~tq%-?t`G1>*9R8xIihs}T|XlFx&peEM0j0+ z=;Qn@{$A?@S|13nFY#yB3Bv1AXuaTA*QLmRKB4sk?Hd~gtsVT?bpu`B;%(@<7P>Zq zu8W{+Tm06#L4@;^f+&nXvcIee|Gqh*udASIW9XU~y0${}`A|9^hwBBpUWV2TM&d;7 zL(_Ue{_8gAS{&hZ8~*G%K{DrSS||9e@$rdRKUmJ!Ux8K7^&)f~knnmDCt}?|*At1p z&V;Tl5?*KGSnCG5&WQF3{Hxaq!t0i3&s?})E?gf7uVZqob%N;qbDAH}{<-75Zb@bw zzaRK-S|13{U&H;zS_jbis`f!dpPyVn0!xI6z!Pd`{FN4ia^UFNjNsLqt8|OQJq;m}p2G zAuc1nCYli65Y33AL<{0uq80HS(S|riv?IPJIuJh)9f{*aC*mjKD&hpuh4`81Mw}#i z5Wf(;h~J4m#2-XI;!mPK@fR_W_?s9^{7VcWvSrVf?OMU%cnXfhEF6tFa4hD;@t6xI zVs4y_d2lM`#p^L2-hlaWIu^j2u^`@xg>VKI#+i63-igKVZafX|#o~BBmcZF~I?ll} z@F6UTbMZ`k6wkuPu@pXuXXDd&4nBkD;eM~_%>FJL@O!)pf5guC z6L!I$u`B+9-S9W;j(=be{0n>HKiCVsw|W!aQ+){UrM`ssP(Q+Z=W4=xra$4mGJx?J&R`v}j~e!_F}DdD;JjPTe$Cp^}Jgva&;;jtVdrW0QgHxoyQTZylU8N@fl zOyVeUC-E(DH}M^DFL8{RMSM@pA$}kpB7P+15n16Dd;)Q!ey8PU%{OCD(1r1FgL!AdGJlli*I8-dN#nEe30=-73qt~Wc)_>RJHvE))26`=K zqSxRK{1Wd(ufg5uxxW`Z=l7xK`hN5rzl6te0iM8x=($~lzv5#29hacz_+|9mZbHxH z2k1H6jGntK=sEikJy$!>bM!HKZnEe2@0?_z=OQhUI;zrl6VHz#WV2=EQMF% zIoK7?!(Lbh`(Qboi09)Zya3l=MO=%OaVu8EZCD+*<3+dwYvE3;gS+q&+>7;aAJ)hH z*bookW%wyJ!OyT6et|9U5VpcEu?-%^cK8)`z$4fZk76hM7O%qZu?zly-S9{3fyc2I z{)Bz-1op$9u|J-~f%qE^#@}%WUYM89K&*kou@;WRZa5md<5=v0 zgV$qUya8Xv>G%QOjGOUR+>bNx0M5kE@J{TWk9!e&;Jw%r@5f#^8~flKY?Ytq9oynu zY=@6xFMJ$(UaYUMzz7u_zYAQ?W1>!=iW^7Q^CL z0!v^?JRM8n8F((1#L{>smc_HMJeI-=cs5qVbFd1Yi`DQvtbwJmCYHh4SQanFa#$D3 zzeE_&9dLr|?RA z2Cu^Burt1ZUGPQhiVLtCF2e5UcTNvnial{T_QDm|8(+gd_y+dHx3C|s#;b7+_Q!W| z0ItJDN?;Us+-ic@9U3f0ujivD(EQ|MIdAtuR;Qe?Z z&caGK8>`?0SPkc34SW!5;zL*)AI6JuF8ZDS2wsYhVFP>`8{s@`jL%?G{2w;QXR#$d zhi&kAY>zKsN1TsW;)~b?U&8LV0DXs8h<$Mp_Q%CI2$$dxd>Mz~QXGlPa11WT@%Re* z&ancg;;T3fSK@Sh4R66!cpJWsx8oal2fm4S;ahkQzK!?cYMhPl;DfjZ=i*v?4By2k z@jaY}>+o4zk1yZ`dojra*}#+~>P?n2+OcH<|w2Y2IM+=u(ncc}e%5D%d5OrPQr{0x0Z`W%npLG+#I z3p{~`@E80Nf5*f4Cw_&0;}QH9zsBr2c@{AT9>v`FE#|}Tupl18BKSQP!ym8&{)i>< zIF`bn@LW8BrSWGhizl%>{(=?oSG*8^!%Fx&R>5rN@;qR6tbwOsP0YeNm;>u#POOi) zuo33QCYT4CV_s~D`LH$S$97l%FUNw|2@7FoER5Z-2=>IH*c(s9zE}+V<7qeui{lVH z1BYQr9D!%zC_D?tVkw+}XX9i%53j@0I1S6-jaU|M#&UQYmdBZRKHh~D@Ls$CXW@nT z09M2Yu@cV3%J>*o!6&gQ&ckZ>ELO)Cum-+}7vTb|iHoroF2&mT3f94ucrm_?m*87i z7gu9FT!WY5dsrVgU<2HQ4RH%L!mW52?!d|Sp$67c7FUFBr4@Y4G z9F3RZSZsphu^CRp7C0GO;Z$sc*JC@JjveqOyaI2=tMC@=hPPrbybb%|3>=8J;}D#Q z!|@Irg?HjuybCAd-8dER!5i>iyczGq8F)Y5iL>w?oQ?P612_lg;9PtVAIFFAX?z%; z#kn{iAHfCqC@#jwa2Y<1ui_K#g7xEcS4Tk%=^7@x!4_&n~% z7w~hOk6+@8cm!XJ+7th1@unexp^0)yj;QLq+H(_Pmj8$<9R>u$V zBK!zz;a04J+wc+=I<k9L1$M$O zu`?dVuJ{#p$0OJizs5fJ4feyM*dM>cfp`oD<4-sQPv9{88AsqRI2wP&vG^NKz&~&j z{)JO8M;Sh+F)vQT0(c{q!<+DYyagNMZP*NN$Ch{pw#K`#AKrug@je`Zvv4FnfTQq1 z9E}g-7<>fB<6}4hpTNoZ6i&f;I353oH{o-5E53lY;fpvE7vLSZ2p8fKT!c$;F)qg? zxB@@Nm3RTZqD6YnDaSeWl@8U6BhwZ9!k6{Pgh#m0*?1WqJD*On$;5O`r zJFo|Sg1vAT_Q5^a5BFhzJb;7nGrR^5;!r$;G z;t9MSPvSKE73bjZ_$2;`3-NDUjQ`@xm^}~AFJ|E@m=j;c-1r*i#n&-EzKI3#Z7huM zU{PF)#c&-K#|?NoZp4zf70<$LcsB09bMa#=jXSX{?!xl82P@!Syb$+eB|Lyt@Mo-s zzhVvi4Qt}>SR4Pqi}4?`UGWm^j&-po*2CU-DfY$scr`Y}0eBe>!p3+FHpQXX42NM09Dyxy z6t==K*c!)S8=Qb`aT2z}DcByb!wxtNZzLM?s*sI;V`}!~Daov4o@733O1}!&JdIPw zspHiCtq{{(XTsr}S`>h>wAuI7y~2fE*C zo-5^QenHB$DY^3wNSZspxtixrxtbS9xi(Arz+`iDUC)P_yRNyKJCC`VyC3Fi?!4yO z65Wq$lIG51uIA2TuI3d|uC2%&KP1^2J-=QLHFrPF)!cc_)!h9uS98~CgU)+xvMsva zuw*;*ybe#AyWL#PJw9{wKDWR3hnm~ZT+Qugu9u_x>;0nU?ytF;=TEtIB6r@gNpt5l zS99kz*DKNf>^JPDuKlOf5 z@1Gd2j#tO4<0E&!;#@@Aezx6L`$jwJF^BccdE&Ffx^4H*w)4A>(YEgKMm^f=sayLh z>GS3MK5y!Muip3S`MCf+K8@TtqGo$#_W%0(|92ecbEMAiF*?7xUtVw9?r*f+FKh0X z`gaWK-xH|g3ZrAxylBeR&l&4}&ZxO{bM?Ae_qwUMb#wK&tb0sqZrxmco~-*kskwD? z^}1R2TB^BqbM?A-9P`O_R>~htKAiOTbhrCEy88RM`n$QVB4RH4+P04_CG6vG=DITJ z7;}FUkFhaN)chSi`sl`#Z_m)N#rb_ri=q8;rTom4`#Z7E_Zi7clC{xsHPLbYE^A&d z<^I0wIDcRL|MQqEk?M7lMUvGsa_2Eu_s@A;PyPMT`ktionLD5QJGlCLw7TEk&+fOH zTQ}Epk`0qzC%;L0{EqW@)ZB6AYVPNoxmHN^mPvm{w_n@j1$lW-B&sKCCW|LaBu`J4 zN|sKRNmfc$OD@DWi4DZt$z3>)u>MSPNwNh0&$d2sda_iqbh1*iWqz(Lp$(H=u{2Si zD3h#~oQ=DP^~Br6hNQXm76q7(SWSFFtj};~%GYLSpBDUo+=fKUq%H#xk)OBGj=Jkd-L`edS&Q-2Q?73J*>x@ZM7srT_j_>C?-tkcyG4CBbi40{YVPrv ztGUmXxthC%xtdo^xwa;Ee}*Q_9p^Dvi*{Su)`lg`UC&(2J&)$vF4c!8Blj4hX4|^` zt;IOcm$|k_*By~G_qff~-1W`1L#mHVnp-!I?XF|4Zg(AXy&SX9HAiK%qwe{Lx^3$o zhxdi`Xh%Kfv2ME~eROov+~Y7;zjM{^+{oQ;b9K8qU({?{_js(S@3xNj-B!&VXRhY% zNA!udb>C^C9_<((b?30{JF@zY9J$-f)$Q(&xte>P&DD2^a_BpRntMN*tGWHmqkk5; z`)e)Q_VYY=O{_<|OX@Q*Y3_cRtMA-iJKwq0+_}xw+&RtF+~YJ?bLTPFZmB*wY3?|4 z^&Q@EzSFDk>b~3iuCC_JW3J|&H*@tlj`JD&<@=@c>5bX{o7c}($NRae=6O@D=C0>4 z+9%pk_gqBXcGP1I`)AIRmC@gJ^pAb8f9!{!b+K-=?Qc8Qjds*yUF)%~?N~S3(LdI; zZrjgW^|Ll|=P_5eXQf=tqa~J$GX;S``oL~eB{n!u5P!l`(-WKQFp(hZaeBRhy63>$;#+&JNm~y z#D4jlJD<;`n%l=*&7Id=&7IF&mlDO2r)A{MEK#@pFkydn-pHLRYSE5)qwc)XKjv}{+y2|s{%S39=ZadiW8SDcZ}gA3 zV%|sCW`DI7xpPG=+A(j`oj3YBZ`5u3Z)f|f^G5DmQHyrW8+GS>imb%kzAQvm0X=%m)w|ioa;0vY&&1HtvhGr zZp+ML|1!6`kCD6G{fs>J)jU31q8;l-J=QVLTsOAII#zge5@PWBlkMT@!F1cqaN$T zw#+1jHVq0dOxo&Kabz^+28`~pa%38h$s{by~nA>*T zi!q-y$A)n~I>#)+In+7S?ej?;vyzCpZO1(ob6bmkv44J#ImYW0I&L+8(_pTSSI7AL zx-aU!sQ(tQukGk#&GsXN{nh?z-+$8l>ilZ|b%g!Z{u=YIq3yL$ubse*^{Sxye^C!zD%O`JOnEjfjym_)! zvO(H@b;{c(>!*6d8 z&Q2~%E>FIaT#;;Bo%?`jpS(PIMe@pI=VaGp_hipx?_}TP)yaX$!O0=XQ5il;du+

zwx?XpKS{Zo?@qaz?@PIwKcDg+l0PPoCx1%*9eGYZdx&oc|E^QlCg04c*|zTAblP8E zOS)|vq1%)G&8PXtN&oiKd}nfZa!=B~1$FzrXKO9ER~{+Oks^+KOn5nL=rcF{akt7(T)?_JKjv?fWalEv{fLlZv1V5Dw_8%n)e@?w}9r{M00MTIk(ZAJ4>J6#Yg$O!B9pP<2)GW!8i}bd5~Aq%q7l) zaUP8GV4MdXvl!>WI1k2oFwTR#l6fw19*px~oCo81^Ka6T#ps9852GJOKjfCA8KWOY zKa758-YiBhj9wVMFnXam^BBD_dSUcJbFSfIcpV?d8<@ccZ(?LI`eO9O=!?-8qc8GG zTDU}CjJ_Dp(+?T57`-uiWAw)8jnNxf4jE>CW zeVyoiUFdz?=zTrteZA;?Bj^~-EcO^fdyJz!CeR*}XxH;v}y(7YKmZ&xX2!QEJf zd$1h$VkPdwCvZPLi3jj0d=IPeeXPb0(BJeA(ckiq(BJTn(dSjOWG&ja4()po?OTub zJ%sjcK>KFVzKv+#CiMTyVSE{n;49dSuVM@O|ELwWV;g3$9qn-x-TxT6|8aEx4s`!c zbpI}N|88{u9(4a+bpJkd|9*7;0d)UCbpIjTj>DM2ktIj*HU1vM*Rh6&Zm(LjR~^Q4 z!FVnh&jsVTU_2L$=YsKEFrEv>bHR8n_y)Nx_$IdETiAyFZnxvxcog5kW4Hs4<4){A z`*mUgcA@>c(SAK>zh1OoAKI@U?Kgn-8$|mJq5X!@ej{kVQMBI}+HV}~H-Yw>MEgyl z{ie}=Ikevl7T^iA-$}IJDYV~dwBH%D-&wTZIkew-wBH4^-$k_FCuqM<(SDzy{XR$g zT|)bPf%f|n?e`Vh?+QA)Di(WoV*!8npgnuho_%P~ezfNR+H(-?IfV8cMthE+=N?7# z#?ZWRG;adUn?&=b(7b6hFNfyMpm`_Iypw3&DKzgins)}xJB#L>L-Wp~c^A;Ui)h}8 zDlUvtG4_A5eji_zQ?H1{DicO#nnFq*pw&3y#Tb)=Yi%zS16a~X3va|LrHa}_hi z`+m!Bq?xOk^~|~ax%?FG`bmoW@>uySQ&MD@lp-UawTxxr8s=JNHFF`gkjfS3iqjS8 Vio&Fjj_Z>3%ni&UW-+sb`2dF80oMQk diff --git a/intl/unicharutil/tools/format.txt b/intl/unicharutil/tools/format.txt deleted file mode 100644 index ef4210be1cb9..000000000000 --- a/intl/unicharutil/tools/format.txt +++ /dev/null @@ -1,243 +0,0 @@ -# -# $Id: format.txt,v 1.1 1999/01/08 00:19:20 ftang%netscape.com Exp $ -# - -CHARACTER DATA -============== - -This package generates some data files that contain character properties useful -for text processing. - -CHARACTER PROPERTIES -==================== - -The first data file is called "ctype.dat" and contains a compressed form of -the character properties found in the Unicode Character Database (UCDB). -Additional properties can be specified in limited UCDB format in another file -to avoid modifying the original UCDB. - -The following is a property name and code table to be used with the character -data: - -NAME CODE DESCRIPTION ---------------------- -Mn 0 Mark, Non-Spacing -Mc 1 Mark, Spacing Combining -Me 2 Mark, Enclosing -Nd 3 Number, Decimal Digit -Nl 4 Number, Letter -No 5 Number, Other -Zs 6 Separator, Space -Zl 7 Separator, Line -Zp 8 Separator, Paragraph -Cc 9 Other, Control -Cf 10 Other, Format -Cs 11 Other, Surrogate -Co 12 Other, Private Use -Cn 13 Other, Not Assigned -Lu 14 Letter, Uppercase -Ll 15 Letter, Lowercase -Lt 16 Letter, Titlecase -Lm 17 Letter, Modifier -Lo 18 Letter, Other -Pc 19 Punctuation, Connector -Pd 20 Punctuation, Dash -Ps 21 Punctuation, Open -Pe 22 Punctuation, Close -Po 23 Punctuation, Other -Sm 24 Symbol, Math -Sc 25 Symbol, Currency -Sk 26 Symbol, Modifier -So 27 Symbol, Other -L 28 Left-To-Right -R 29 Right-To-Left -EN 30 European Number -ES 31 European Number Separator -ET 32 European Number Terminator -AN 33 Arabic Number -CS 34 Common Number Separator -B 35 Block Separator -S 36 Segment Separator -WS 37 Whitespace -ON 38 Other Neutrals -Pi 47 Punctuation, Initial -Pf 48 Punctuation, Final -# -# Implementation specific properties. -# -Cm 39 Composite -Nb 40 Non-Breaking -Sy 41 Symmetric (characters which are part of open/close pairs) -Hd 42 Hex Digit -Qm 43 Quote Mark -Mr 44 Mirroring -Ss 45 Space, Other (controls viewed as spaces in ctype isspace()) -Cp 46 Defined character - -The actual binary data is formatted as follows: - - Assumptions: unsigned short is at least 16-bits in size and unsigned long - is at least 32-bits in size. - - unsigned short ByteOrderMark - unsigned short OffsetArraySize - unsigned long Bytes - unsigned short Offsets[OffsetArraySize + 1] - unsigned long Ranges[N], N = value of Offsets[OffsetArraySize] - - The Bytes field provides the total byte count used for the Offsets[] and - Ranges[] arrays. The Offsets[] array is aligned on a 4-byte boundary and - there is always one extra node on the end to hold the final index of the - Ranges[] array. The Ranges[] array contains pairs of 4-byte values - representing a range of Unicode characters. The pairs are arranged in - increasing order by the first character code in the range. - - Determining if a particular character is in the property list requires a - simple binary search to determine if a character is in any of the ranges - for the property. - - If the ByteOrderMark is equal to 0xFFFE, then the data was generated on a - machine with a different endian order and the values must be byte-swapped. - - To swap a 16-bit value: - c = (c >> 8) | ((c & 0xff) << 8) - - To swap a 32-bit value: - c = ((c & 0xff) << 24) | (((c >> 8) & 0xff) << 16) | - (((c >> 16) & 0xff) << 8) | (c >> 24) - -CASE MAPPINGS -============= - -The next data file is called "case.dat" and contains three case mapping tables -in the following order: upper, lower, and title case. Each table is in -increasing order by character code and each mapping contains 3 unsigned longs -which represent the possible mappings. - -The format for the binary form of these tables is: - - unsigned short ByteOrderMark - unsigned short NumMappingNodes, count of all mapping nodes - unsigned short CaseTableSizes[2], upper and lower mapping node counts - unsigned long CaseTables[NumMappingNodes] - - The starting indexes of the case tables are calculated as following: - - UpperIndex = 0; - LowerIndex = CaseTableSizes[0] * 3; - TitleIndex = LowerIndex + CaseTableSizes[1] * 3; - - The order of the fields for the three tables are: - - Upper case - ---------- - unsigned long upper; - unsigned long lower; - unsigned long title; - - Lower case - ---------- - unsigned long lower; - unsigned long upper; - unsigned long title; - - Title case - ---------- - unsigned long title; - unsigned long upper; - unsigned long lower; - - If the ByteOrderMark is equal to 0xFFFE, endian swapping is required in the - same way as described in the CHARACTER PROPERTIES section. - - Because the tables are in increasing order by character code, locating a - mapping requires a simple binary search on one of the 3 codes that make up - each node. - - It is important to note that there can only be 65536 mapping nodes which - divided into 3 portions allows 21845 nodes for each case mapping table. The - distribution of mappings may be more or less than 21845 per table, but only - 65536 are allowed. - -DECOMPOSITIONS -============== - -The next data file is called "decomp.dat" and contains the decomposition data -for all characters with decompositions containing more than one character and -are *not* compatibility decompositions. Compatibility decompositions are -signaled in the UCDB format by the use of the tag in the -decomposition field. Each list of character codes represents a full -decomposition of a composite character. The nodes are arranged in increasing -order by character code. - -The format for the binary form of this table is: - - unsigned short ByteOrderMark - unsigned short NumDecompNodes, count of all decomposition nodes - unsigned long Bytes - unsigned long DecompNodes[(NumDecompNodes * 2) + 1] - unsigned long Decomp[N], N = sum of all counts in DecompNodes[] - - If the ByteOrderMark is equal to 0xFFFE, endian swapping is required in the - same way as described in the CHARACTER PROPERTIES section. - - The DecompNodes[] array consists of pairs of unsigned longs, the first of - which is the character code and the second is the initial index of the list - of character codes representing the decomposition. - - Locating the decomposition of a composite character requires a binary search - for a character code in the DecompNodes[] array and using its index to - locate the start of the decomposition. The length of the decomposition list - is the index in the following element in DecompNode[] minus the current - index. - -COMBINING CLASSES -================= - -The fourth data file is called "cmbcl.dat" and contains the characters with -non-zero combining classes. - -The format for the binary form of this table is: - - unsigned short ByteOrderMark - unsigned short NumCCLNodes - unsigned long Bytes - unsigned long CCLNodes[NumCCLNodes * 3] - - If the ByteOrderMark is equal to 0xFFFE, endian swapping is required in the - same way as described in the CHARACTER PROPERTIES section. - - The CCLNodes[] array consists of groups of three unsigned longs. The first - and second are the beginning and ending of a range and the third is the - combining class of that range. - - If a character is not found in this table, then the combining class is - assumed to be 0. - - It is important to note that only 65536 distinct ranges plus combining class - can be specified because the NumCCLNodes is usually a 16-bit number. - -NUMBER TABLE -============ - -The final data file is called "num.dat" and contains the characters that have -a numeric value associated with them. - -The format for the binary form of the table is: - - unsigned short ByteOrderMark - unsigned short NumNumberNodes - unsigned long Bytes - unsigned long NumberNodes[NumNumberNodes] - unsigned short ValueNodes[(Bytes - (NumNumberNodes * sizeof(unsigned long))) - / sizeof(short)] - - If the ByteOrderMark is equal to 0xFFFE, endian swapping is required in the - same way as described in the CHARACTER PROPERTIES section. - - The NumberNodes array contains pairs of values, the first of which is the - character code and the second an index into the ValueNodes array. The - ValueNodes array contains pairs of integers which represent the numerator - and denominator of the numeric value of the character. If the character - happens to map to an integer, both the values in ValueNodes will be the - same. diff --git a/intl/unicharutil/tools/moz.build b/intl/unicharutil/tools/moz.build deleted file mode 100644 index d2072d2aacbd..000000000000 --- a/intl/unicharutil/tools/moz.build +++ /dev/null @@ -1,12 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# 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/. - -Program('ucgendat') - -SOURCES += [ - 'ucgendat.c', -] - diff --git a/intl/unicharutil/tools/ucgendat.c b/intl/unicharutil/tools/ucgendat.c deleted file mode 100644 index 400359ad4c6b..000000000000 --- a/intl/unicharutil/tools/ucgendat.c +++ /dev/null @@ -1,1457 +0,0 @@ -/* - * Copyright 1996, 1997, 1998 Computing Research Labs, - * New Mexico State University - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT - * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -#ifndef lint -#ifdef __GNUC__ -static char rcsid[] __attribute__ ((unused)) = "$Id: ucgendat.c,v 1.1 1999/01/08 00:19:21 ftang%netscape.com Exp $"; -#else -static char rcsid[] = "$Id: ucgendat.c,v 1.1 1999/01/08 00:19:21 ftang%netscape.com Exp $"; -#endif -#endif - -#include -#include -#include -#ifndef WIN32 -#include -#endif - -#define ishdigit(cc) (((cc) >= '0' && (cc) <= '9') ||\ - ((cc) >= 'A' && (cc) <= 'F') ||\ - ((cc) >= 'a' && (cc) <= 'f')) - -/* - * A header written to the output file with the byte-order-mark and the number - * of property nodes. - */ -static unsigned short hdr[2] = {0xfeff, 0}; - -#define NUMPROPS 49 -#define NEEDPROPS (NUMPROPS + (4 - (NUMPROPS & 3))) - -typedef struct { - char *name; - int len; -} _prop_t; - -/* - * List of properties expected to be found in the Unicode Character Database - * including some implementation specific properties. - * - * The implementation specific properties are: - * Cm = Composed (can be decomposed) - * Nb = Non-breaking - * Sy = Symmetric (has left and right forms) - * Hd = Hex digit - * Qm = Quote marks - * Mr = Mirroring - * Ss = Space, other - * Cp = Defined character - */ -static _prop_t props[NUMPROPS] = { - {"Mn", 2}, {"Mc", 2}, {"Me", 2}, {"Nd", 2}, {"Nl", 2}, {"No", 2}, - {"Zs", 2}, {"Zl", 2}, {"Zp", 2}, {"Cc", 2}, {"Cf", 2}, {"Cs", 2}, - {"Co", 2}, {"Cn", 2}, {"Lu", 2}, {"Ll", 2}, {"Lt", 2}, {"Lm", 2}, - {"Lo", 2}, {"Pc", 2}, {"Pd", 2}, {"Ps", 2}, {"Pe", 2}, {"Po", 2}, - {"Sm", 2}, {"Sc", 2}, {"Sk", 2}, {"So", 2}, {"L", 1}, {"R", 1}, - {"EN", 2}, {"ES", 2}, {"ET", 2}, {"AN", 2}, {"CS", 2}, {"B", 1}, - {"S", 1}, {"WS", 2}, {"ON", 2}, - {"Cm", 2}, {"Nb", 2}, {"Sy", 2}, {"Hd", 2}, {"Qm", 2}, {"Mr", 2}, - {"Ss", 2}, {"Cp", 2}, {"Pi", 2}, {"Pf", 2} -}; - -typedef struct { - unsigned long *ranges; - unsigned short used; - unsigned short size; -} _ranges_t; - -static _ranges_t proptbl[NUMPROPS]; - -/* - * Make sure this array is sized to be on a 4-byte boundary at compile time. - */ -static unsigned short propcnt[NEEDPROPS]; - -/* - * Array used to collect a decomposition before adding it to the decomposition - * table. - */ -static unsigned long dectmp[64]; -static unsigned long dectmp_size; - -typedef struct { - unsigned long code; - unsigned short size; - unsigned short used; - unsigned long *decomp; -} _decomp_t; - -/* - * List of decomposition. Created and expanded in order as the characters are - * encountered. - */ -static _decomp_t *decomps; -static unsigned long decomps_used; -static unsigned long decomps_size; - -/* - * Types and lists for handling lists of case mappings. - */ -typedef struct { - unsigned long key; - unsigned long other1; - unsigned long other2; -} _case_t; - -static _case_t *upper; -static _case_t *lower; -static _case_t *title; -static unsigned long upper_used; -static unsigned long upper_size; -static unsigned long lower_used; -static unsigned long lower_size; -static unsigned long title_used; -static unsigned long title_size; - -/* - * Array used to collect case mappings before adding them to a list. - */ -static unsigned long cases[3]; - -/* - * An array to hold ranges for combining classes. - */ -static unsigned long *ccl; -static unsigned long ccl_used; -static unsigned long ccl_size; - -/* - * Structures for handling numbers. - */ -typedef struct { - unsigned long code; - unsigned long idx; -} _codeidx_t; - -typedef struct { - short numerator; - short denominator; -} _num_t; - -/* - * Arrays to hold the mapping of codes to numbers. - */ -static _codeidx_t *ncodes; -static unsigned long ncodes_used; -static unsigned long ncodes_size; - -static _num_t *nums; -static unsigned long nums_used; -static unsigned long nums_size; - -/* - * Array for holding numbers. - */ -static _num_t *nums; -static unsigned long nums_used; -static unsigned long nums_size; - -static void -#ifdef __STDC__ -add_range(unsigned long start, unsigned long end, char *p1, char *p2) -#else -add_range(start, end, p1, p2) -unsigned long start, end; -char *p1, *p2; -#endif -{ - int i, j, k, len; - _ranges_t *rlp; - char *name; - - for (k = 0; k < 2; k++) { - if (k == 0) { - name = p1; - len = 2; - } else { - if (p2 == 0) - break; - - name = p2; - len = 1; - } - - for (i = 0; i < NUMPROPS; i++) { - if (props[i].len == len && memcmp(props[i].name, name, len) == 0) - break; - } - - if (i == NUMPROPS) - continue; - - rlp = &proptbl[i]; - - /* - * Resize the range list if necessary. - */ - if (rlp->used == rlp->size) { - if (rlp->size == 0) - rlp->ranges = (unsigned long *) - malloc(sizeof(unsigned long) << 3); - else - rlp->ranges = (unsigned long *) - realloc((char *) rlp->ranges, - sizeof(unsigned long) * (rlp->size + 8)); - rlp->size += 8; - } - - /* - * If this is the first code for this property list, just add it - * and return. - */ - if (rlp->used == 0) { - rlp->ranges[0] = start; - rlp->ranges[1] = end; - rlp->used += 2; - continue; - } - - /* - * Optimize the case of adding the range to the end. - */ - j = rlp->used - 1; - if (start > rlp->ranges[j]) { - j = rlp->used; - rlp->ranges[j++] = start; - rlp->ranges[j++] = end; - rlp->used = j; - continue; - } - - /* - * Need to locate the insertion point. - */ - for (i = 0; - i < rlp->used && start > rlp->ranges[i + 1] + 1; i += 2) ; - - /* - * If the start value lies in the current range, then simply set the - * new end point of the range to the end value passed as a parameter. - */ - if (rlp->ranges[i] <= start && start <= rlp->ranges[i + 1] + 1) { - rlp->ranges[i + 1] = end; - return; - } - - /* - * Shift following values up by two. - */ - for (j = rlp->used; j > i; j -= 2) { - rlp->ranges[j] = rlp->ranges[j - 2]; - rlp->ranges[j + 1] = rlp->ranges[j - 1]; - } - - /* - * Add the new range at the insertion point. - */ - rlp->ranges[i] = start; - rlp->ranges[i + 1] = end; - rlp->used += 2; - } -} - -static void -#ifdef __STDC__ -ordered_range_insert(unsigned long c, char *name, int len) -#else -ordered_range_insert(c, name, len) -unsigned long c; -char *name; -int len; -#endif -{ - int i, j; - unsigned long s, e; - _ranges_t *rlp; - - if (len == 0) - return; - - for (i = 0; i < NUMPROPS; i++) { - if (props[i].len == len && memcmp(props[i].name, name, len) == 0) - break; - } - - if (i == NUMPROPS) - return; - - /* - * Have a match, so insert the code in order. - */ - rlp = &proptbl[i]; - - /* - * Resize the range list if necessary. - */ - if (rlp->used == rlp->size) { - if (rlp->size == 0) - rlp->ranges = (unsigned long *) - malloc(sizeof(unsigned long) << 3); - else - rlp->ranges = (unsigned long *) - realloc((char *) rlp->ranges, - sizeof(unsigned long) * (rlp->size + 8)); - rlp->size += 8; - } - - /* - * If this is the first code for this property list, just add it - * and return. - */ - if (rlp->used == 0) { - rlp->ranges[0] = rlp->ranges[1] = c; - rlp->used += 2; - return; - } - - /* - * Optimize the cases of extending the last range and adding new ranges to - * the end. - */ - j = rlp->used - 1; - e = rlp->ranges[j]; - s = rlp->ranges[j - 1]; - - if (c == e + 1) { - /* - * Extend the last range. - */ - rlp->ranges[j] = c; - return; - } - - if (c > e + 1) { - /* - * Start another range on the end. - */ - j = rlp->used; - rlp->ranges[j] = rlp->ranges[j + 1] = c; - rlp->used += 2; - return; - } - - if (c >= s) - /* - * The code is a duplicate of a code in the last range, so just return. - */ - return; - - /* - * The code should be inserted somewhere before the last range in the - * list. Locate the insertion point. - */ - for (i = 0; - i < rlp->used && c > rlp->ranges[i + 1] + 1; i += 2) ; - - s = rlp->ranges[i]; - e = rlp->ranges[i + 1]; - - if (c == e + 1) - /* - * Simply extend the current range. - */ - rlp->ranges[i + 1] = c; - else if (c < s) { - /* - * Add a new entry before the current location. Shift all entries - * before the current one up by one to make room. - */ - for (j = rlp->used; j > i; j -= 2) { - rlp->ranges[j] = rlp->ranges[j - 2]; - rlp->ranges[j + 1] = rlp->ranges[j - 1]; - } - rlp->ranges[i] = rlp->ranges[i + 1] = c; - - rlp->used += 2; - } -} - -static void -#ifdef __STDC__ -add_decomp(unsigned long code) -#else -add_decomp(code) -unsigned long code; -#endif -{ - unsigned long i, j, size; - - /* - * Add the code to the composite property. - */ - ordered_range_insert(code, "Cm", 2); - - /* - * Locate the insertion point for the code. - */ - for (i = 0; i < decomps_used && code > decomps[i].code; i++) ; - - /* - * Allocate space for a new decomposition. - */ - if (decomps_used == decomps_size) { - if (decomps_size == 0) - decomps = (_decomp_t *) malloc(sizeof(_decomp_t) << 3); - else - decomps = (_decomp_t *) - realloc((char *) decomps, - sizeof(_decomp_t) * (decomps_size + 8)); - (void) memset((char *) (decomps + decomps_size), 0, - sizeof(_decomp_t) << 3); - decomps_size += 8; - } - - if (i < decomps_used && code != decomps[i].code) { - /* - * Shift the decomps up by one if the codes don't match. - */ - for (j = decomps_used; j > i; j--) - (void) memcpy((char *) &decomps[j], (char *) &decomps[j - 1], - sizeof(_decomp_t)); - } - - /* - * Insert or replace a decomposition. - */ - size = dectmp_size + (4 - (dectmp_size & 3)); - if (decomps[i].size < size) { - if (decomps[i].size == 0) - decomps[i].decomp = (unsigned long *) - malloc(sizeof(unsigned long) * size); - else - decomps[i].decomp = (unsigned long *) - realloc((char *) decomps[i].decomp, - sizeof(unsigned long) * size); - decomps[i].size = size; - } - - if (decomps[i].code != code) - decomps_used++; - - decomps[i].code = code; - decomps[i].used = dectmp_size; - (void) memcpy((char *) decomps[i].decomp, (char *) dectmp, - sizeof(unsigned long) * dectmp_size); - -} - -static void -#ifdef __STDC__ -add_title(unsigned long code) -#else -add_title(code) -unsigned long code; -#endif -{ - unsigned long i, j; - - /* - * Always map the code to itself. - */ - cases[2] = code; - - if (title_used == title_size) { - if (title_size == 0) - title = (_case_t *) malloc(sizeof(_case_t) << 3); - else - title = (_case_t *) realloc((char *) title, - sizeof(_case_t) * (title_size + 8)); - title_size += 8; - } - - /* - * Locate the insertion point. - */ - for (i = 0; i < title_used && code > title[i].key; i++) ; - - if (i < title_used) { - /* - * Shift the array up by one. - */ - for (j = title_used; j > i; j--) - (void) memcpy((char *) &title[j], (char *) &title[j - 1], - sizeof(_case_t)); - } - - title[i].key = cases[2]; /* Title */ - title[i].other1 = cases[0]; /* Upper */ - title[i].other2 = cases[1]; /* Lower */ - - title_used++; -} - -static void -#ifdef __STDC__ -add_upper(unsigned long code) -#else -add_upper(code) -unsigned long code; -#endif -{ - unsigned long i, j; - - /* - * Always map the code to itself. - */ - cases[0] = code; - - /* - * If the title case character is not present, then make it the same as - * the upper case. - */ - if (cases[2] == 0) - cases[2] = code; - - if (upper_used == upper_size) { - if (upper_size == 0) - upper = (_case_t *) malloc(sizeof(_case_t) << 3); - else - upper = (_case_t *) realloc((char *) upper, - sizeof(_case_t) * (upper_size + 8)); - upper_size += 8; - } - - /* - * Locate the insertion point. - */ - for (i = 0; i < upper_used && code > upper[i].key; i++) ; - - if (i < upper_used) { - /* - * Shift the array up by one. - */ - for (j = upper_used; j > i; j--) - (void) memcpy((char *) &upper[j], (char *) &upper[j - 1], - sizeof(_case_t)); - } - - upper[i].key = cases[0]; /* Upper */ - upper[i].other1 = cases[1]; /* Lower */ - upper[i].other2 = cases[2]; /* Title */ - - upper_used++; -} - -static void -#ifdef __STDC__ -add_lower(unsigned long code) -#else -add_lower(code) -unsigned long code; -#endif -{ - unsigned long i, j; - - /* - * Always map the code to itself. - */ - cases[1] = code; - - /* - * If the title case character is empty, then make it the same as the - * upper case. - */ - if (cases[2] == 0) - cases[2] = cases[0]; - - if (lower_used == lower_size) { - if (lower_size == 0) - lower = (_case_t *) malloc(sizeof(_case_t) << 3); - else - lower = (_case_t *) realloc((char *) lower, - sizeof(_case_t) * (lower_size + 8)); - lower_size += 8; - } - - /* - * Locate the insertion point. - */ - for (i = 0; i < lower_used && code > lower[i].key; i++) ; - - if (i < lower_used) { - /* - * Shift the array up by one. - */ - for (j = lower_used; j > i; j--) - (void) memcpy((char *) &lower[j], (char *) &lower[j - 1], - sizeof(_case_t)); - } - - lower[i].key = cases[1]; /* Lower */ - lower[i].other1 = cases[0]; /* Upper */ - lower[i].other2 = cases[2]; /* Title */ - - lower_used++; -} - -static void -#ifdef __STDC__ -ordered_ccl_insert(unsigned long c, unsigned long ccl_code) -#else -ordered_ccl_insert(c, ccl_code) -unsigned long c, ccl_code; -#endif -{ - unsigned long i, j; - - if (ccl_used == ccl_size) { - if (ccl_size == 0) - ccl = (unsigned long *) malloc(sizeof(unsigned long) * 24); - else - ccl = (unsigned long *) - realloc((char *) ccl, sizeof(unsigned long) * (ccl_size + 24)); - ccl_size += 24; - } - - /* - * Optimize adding the first item. - */ - if (ccl_used == 0) { - ccl[0] = ccl[1] = c; - ccl[2] = ccl_code; - ccl_used += 3; - return; - } - - /* - * Handle the special case of extending the range on the end. This - * requires that the combining class codes are the same. - */ - if (ccl_code == ccl[ccl_used - 1] && c == ccl[ccl_used - 2] + 1) { - ccl[ccl_used - 2] = c; - return; - } - - /* - * Handle the special case of adding another range on the end. - */ - if (c > ccl[ccl_used - 2] + 1 || - (c == ccl[ccl_used - 2] + 1 && ccl_code != ccl[ccl_used - 1])) { - ccl[ccl_used++] = c; - ccl[ccl_used++] = c; - ccl[ccl_used++] = ccl_code; - return; - } - - /* - * Locate either the insertion point or range for the code. - */ - for (i = 0; i < ccl_used && c > ccl[i + 1] + 1; i += 3) ; - - if (ccl_code == ccl[i + 2] && c == ccl[i + 1] + 1) { - /* - * Extend an existing range. - */ - ccl[i + 1] = c; - return; - } else if (c < ccl[i]) { - /* - * Start a new range before the current location. - */ - for (j = ccl_used; j > i; j -= 3) { - ccl[j] = ccl[j - 3]; - ccl[j - 1] = ccl[j - 4]; - ccl[j - 2] = ccl[j - 5]; - } - ccl[i] = ccl[i + 1] = c; - ccl[i + 2] = ccl_code; - } -} - -/* - * Adds a number if it does not already exist and returns an index value - * multiplied by 2. - */ -static unsigned long -#ifdef __STDC__ -make_number(short num, short denom) -#else -make_number(num, denom) -short num, denom; -#endif -{ - unsigned long n; - - /* - * Determine if the number already exists. - */ - for (n = 0; n < nums_used; n++) { - if (nums[n].numerator == num && nums[n].denominator == denom) - return n << 1; - } - - if (nums_used == nums_size) { - if (nums_size == 0) - nums = (_num_t *) malloc(sizeof(_num_t) << 3); - else - nums = (_num_t *) realloc((char *) nums, - sizeof(_num_t) * (nums_size + 8)); - nums_size += 8; - } - - n = nums_used++; - nums[n].numerator = num; - nums[n].denominator = denom; - - return n << 1; -} - -static void -#ifdef __STDC__ -add_number(unsigned long code, short num, short denom) -#else -add_number(code, num, denom) -unsigned long code; -short num, denom; -#endif -{ - unsigned long i, j; - - /* - * Insert the code in order. - */ - for (i = 0; i < ncodes_used && code > ncodes[i].code; i++) ; - - /* - * Handle the case of the codes matching and simply replace the number - * that was there before. - */ - if (ncodes_used > 0 && code == ncodes[i].code) { - ncodes[i].idx = make_number(num, denom); - return; - } - - /* - * Resize the array if necessary. - */ - if (ncodes_used == ncodes_size) { - if (ncodes_size == 0) - ncodes = (_codeidx_t *) malloc(sizeof(_codeidx_t) << 3); - else - ncodes = (_codeidx_t *) - realloc((char *) ncodes, sizeof(_codeidx_t) * (ncodes_size + 8)); - - ncodes_size += 8; - } - - /* - * Shift things around to insert the code if necessary. - */ - if (i < ncodes_used) { - for (j = ncodes_used; j > i; j--) { - ncodes[j].code = ncodes[j - 1].code; - ncodes[j].idx = ncodes[j - 1].idx; - } - } - ncodes[i].code = code; - ncodes[i].idx = make_number(num, denom); - - ncodes_used++; -} - -/* - * This routine assumes that the line is a valid Unicode Character Database - * entry. - */ -static void -#ifdef __STDC__ -read_cdata(FILE *in) -#else -read_cdata(in) -FILE *in; -#endif -{ - unsigned long i, lineno, skip, code, ccl_code; - short wnum, neg, number[2]; - char line[512], *s, *e; - - lineno = skip = 0; - while (fscanf(in, "%[^\n]\n", line) != EOF) { - lineno++; - - /* - * Skip blank lines and lines that start with a '#'. - */ - if (line[0] == 0 || line[0] == '#') - continue; - - /* - * If lines need to be skipped, do it here. - */ - if (skip) { - skip--; - continue; - } - - /* - * Collect the code. The code can be up to 6 hex digits in length to - * allow surrogates to be specified. - */ - for (s = line, i = code = 0; *s != ';' && i < 6; i++, s++) { - code <<= 4; - if (*s >= '0' && *s <= '9') - code += *s - '0'; - else if (*s >= 'A' && *s <= 'F') - code += (*s - 'A') + 10; - else if (*s >= 'a' && *s <= 'f') - code += (*s - 'a') + 10; - } - - /* - * Handle the following special cases: - * 1. 4E00-9FA5 CJK Ideographs. - * 2. AC00-D7A3 Hangul Syllables. - * 3. D800-DFFF Surrogates. - * 4. E000-F8FF Private Use Area. - * 5. F900-FA2D Han compatibility. - */ - switch (code) { - case 0x4e00: - /* - * The Han ideographs. - */ - add_range(0x4e00, 0x9fff, "Lo", "L"); - - /* - * Add the characters to the defined category. - */ - add_range(0x4e00, 0x9fa5, "Cp", 0); - - skip = 1; - break; - case 0xac00: - /* - * The Hangul syllables. - */ - add_range(0xac00, 0xd7a3, "Lo", "L"); - - /* - * Add the characters to the defined category. - */ - add_range(0xac00, 0xd7a3, "Cp", 0); - - skip = 1; - break; - case 0xd800: - /* - * Make a range of all surrogates and assume some default - * properties. - */ - add_range(0x010000, 0x10ffff, "Cs", "L"); - skip = 5; - break; - case 0xe000: - /* - * The Private Use area. Add with a default set of properties. - */ - add_range(0xe000, 0xf8ff, "Co", "L"); - skip = 1; - break; - case 0xf900: - /* - * The CJK compatibility area. - */ - add_range(0xf900, 0xfaff, "Lo", "L"); - - /* - * Add the characters to the defined category. - */ - add_range(0xf900, 0xfaff, "Cp", 0); - - skip = 1; - } - - if (skip) - continue; - - /* - * Add the code to the defined category. - */ - ordered_range_insert(code, "Cp", 2); - - /* - * Locate the first character property field. - */ - for (i = 0; *s != 0 && i < 2; s++) { - if (*s == ';') - i++; - } - for (e = s; *e && *e != ';'; e++) ; - - ordered_range_insert(code, s, e - s); - - /* - * Locate the combining class code. - */ - for (s = e; *s != 0 && i < 3; s++) { - if (*s == ';') - i++; - } - - /* - * Convert the combining class code from decimal. - */ - for (ccl_code = 0, e = s; *e && *e != ';'; e++) - ccl_code = (ccl_code * 10) + (*e - '0'); - - /* - * Add the code if it not 0. - */ - if (ccl_code != 0) - ordered_ccl_insert(code, ccl_code); - - /* - * Locate the second character property field. - */ - for (s = e; *s != 0 && i < 4; s++) { - if (*s == ';') - i++; - } - for (e = s; *e && *e != ';'; e++) ; - - ordered_range_insert(code, s, e - s); - - /* - * Check for a decomposition. - */ - s = ++e; - if (*s != ';' && *s != '<') { - /* - * Collect the codes of the decomposition. - */ - for (dectmp_size = 0; *s != ';'; ) { - /* - * Skip all leading non-hex digits. - */ - while (!ishdigit(*s)) - s++; - - for (dectmp[dectmp_size] = 0; ishdigit(*s); s++) { - dectmp[dectmp_size] <<= 4; - if (*s >= '0' && *s <= '9') - dectmp[dectmp_size] += *s - '0'; - else if (*s >= 'A' && *s <= 'F') - dectmp[dectmp_size] += (*s - 'A') + 10; - else if (*s >= 'a' && *s <= 'f') - dectmp[dectmp_size] += (*s - 'a') + 10; - } - dectmp_size++; - } - - /* - * If there is more than one code in the temporary decomposition - * array, then add the character with its decomposition. - */ - if (dectmp_size > 1) - add_decomp(code); - } - - /* - * Skip to the number field. - */ - for (i = 0; i < 3 && *s; s++) { - if (*s == ';') - i++; - } - - /* - * Scan the number in. - */ - number[0] = number[1] = 0; - for (e = s, neg = wnum = 0; *e && *e != ';'; e++) { - if (*e == '-') { - neg = 1; - continue; - } - - if (*e == '/') { - /* - * Move the the denominator of the fraction. - */ - if (neg) - number[wnum] *= -1; - neg = 0; - e++; - wnum++; - } - number[wnum] = (number[wnum] * 10) + (*e - '0'); - } - - if (e > s) { - /* - * Adjust the denominator in case of integers and add the number. - */ - if (wnum == 0) - number[1] = number[0]; - - add_number(code, number[0], number[1]); - } - - /* - * Skip to the start of the possible case mappings. - */ - for (s = e, i = 0; i < 4 && *s; s++) { - if (*s == ';') - i++; - } - - /* - * Collect the case mappings. - */ - cases[0] = cases[1] = cases[2] = 0; - for (i = 0; i < 3; i++) { - while (ishdigit(*s)) { - cases[i] <<= 4; - if (*s >= '0' && *s <= '9') - cases[i] += *s - '0'; - else if (*s >= 'A' && *s <= 'F') - cases[i] += (*s - 'A') + 10; - else if (*s >= 'a' && *s <= 'f') - cases[i] += (*s - 'a') + 10; - s++; - } - if (*s == ';') - s++; - } - if (cases[0] && cases[1]) - /* - * Add the upper and lower mappings for a title case character. - */ - add_title(code); - else if (cases[1]) - /* - * Add the lower and title case mappings for the upper case - * character. - */ - add_upper(code); - else if (cases[0]) - /* - * Add the upper and title case mappings for the lower case - * character. - */ - add_lower(code); - } -} - -static _decomp_t * -#ifdef __STDC__ -find_decomp(unsigned long code) -#else -find_decomp(code) -unsigned long code; -#endif -{ - long l, r, m; - - l = 0; - r = decomps_used - 1; - while (l <= r) { - m = (l + r) >> 1; - if (code > decomps[m].code) - l = m + 1; - else if (code < decomps[m].code) - r = m - 1; - else - return &decomps[m]; - } - return 0; -} - -static void -#ifdef __STDC__ -decomp_it(_decomp_t *d) -#else -decomp_it(d) -_decomp_t *d; -#endif -{ - unsigned long i; - _decomp_t *dp; - - for (i = 0; i < d->used; i++) { - if ((dp = find_decomp(d->decomp[i])) != 0) - decomp_it(dp); - else - dectmp[dectmp_size++] = d->decomp[i]; - } -} - -/* - * Expand all decompositions by recursively decomposing each character - * in the decomposition. - */ -static void -#ifdef __STDC__ -expand_decomp(void) -#else -expand_decomp() -#endif -{ - unsigned long i; - - for (i = 0; i < decomps_used; i++) { - dectmp_size = 0; - decomp_it(&decomps[i]); - if (dectmp_size > 0) - add_decomp(decomps[i].code); - } -} - -static void -#ifdef __STDC__ -write_cdata(char *opath) -#else -write_cdata(opath) -char *opath; -#endif -{ - FILE *out; - unsigned long i, idx, bytes, nprops; - unsigned short casecnt[2]; - char path[BUFSIZ]; - - /***************************************************************** - * - * Generate the ctype data. - * - *****************************************************************/ - - /* - * Open the ctype.dat file. - */ - sprintf(path, "%s/ctype.dat", opath); - if ((out = fopen(path, "wb")) == 0) - return; - - /* - * Collect the offsets for the properties. The offsets array is - * on a 4-byte boundary to keep things efficient for architectures - * that need such a thing. - */ - for (i = idx = 0; i < NUMPROPS; i++) { - propcnt[i] = (proptbl[i].used != 0) ? idx : 0xffff; - idx += proptbl[i].used; - } - - /* - * Add the sentinel index which is used by the binary search as the upper - * bound for a search. - */ - propcnt[i] = idx; - - /* - * Record the actual number of property lists. This may be different than - * the number of offsets actually written because of aligning on a 4-byte - * boundary. - */ - hdr[1] = NUMPROPS; - - /* - * Calculate the byte count needed and pad the property counts array to a - * 4-byte boundary. - */ - if ((bytes = sizeof(unsigned short) * (NUMPROPS + 1)) & 3) - bytes += 4 - (bytes & 3); - nprops = bytes / sizeof(unsigned short); - bytes += sizeof(unsigned long) * idx; - - /* - * Write the header. - */ - fwrite((char *) hdr, sizeof(unsigned short), 2, out); - - /* - * Write the byte count. - */ - fwrite((char *) &bytes, sizeof(unsigned long), 1, out); - - /* - * Write the property list counts. - */ - fwrite((char *) propcnt, sizeof(unsigned short), nprops, out); - - /* - * Write the property lists. - */ - for (i = 0; i < NUMPROPS; i++) { - if (proptbl[i].used > 0) - fwrite((char *) proptbl[i].ranges, sizeof(unsigned long), - proptbl[i].used, out); - } - - fclose(out); - - /***************************************************************** - * - * Generate the case mapping data. - * - *****************************************************************/ - - /* - * Open the case.dat file. - */ - sprintf(path, "%s/case.dat", opath); - if ((out = fopen(path, "wb")) == 0) - return; - - /* - * Write the case mapping tables. - */ - hdr[1] = upper_used + lower_used + title_used; - casecnt[0] = upper_used; - casecnt[1] = lower_used; - - /* - * Write the header. - */ - fwrite((char *) hdr, sizeof(unsigned short), 2, out); - - /* - * Write the upper and lower case table sizes. - */ - fwrite((char *) casecnt, sizeof(unsigned short), 2, out); - - if (upper_used > 0) - /* - * Write the upper case table. - */ - fwrite((char *) upper, sizeof(_case_t), upper_used, out); - - if (lower_used > 0) - /* - * Write the lower case table. - */ - fwrite((char *) lower, sizeof(_case_t), lower_used, out); - - if (title_used > 0) - /* - * Write the title case table. - */ - fwrite((char *) title, sizeof(_case_t), title_used, out); - - fclose(out); - - /***************************************************************** - * - * Generate the decomposition data. - * - *****************************************************************/ - - /* - * Fully expand all decompositions before generating the output file. - */ - expand_decomp(); - - /* - * Open the decomp.dat file. - */ - sprintf(path, "%s/decomp.dat", opath); - if ((out = fopen(path, "wb")) == 0) - return; - - hdr[1] = decomps_used; - - /* - * Write the header. - */ - fwrite((char *) hdr, sizeof(unsigned short), 2, out); - - /* - * Write a temporary byte count which will be calculated as the - * decompositions are written out. - */ - bytes = 0; - fwrite((char *) &bytes, sizeof(unsigned long), 1, out); - - if (decomps_used) { - /* - * Write the list of decomp nodes. - */ - for (i = idx = 0; i < decomps_used; i++) { - fwrite((char *) &decomps[i].code, sizeof(unsigned long), 1, out); - fwrite((char *) &idx, sizeof(unsigned long), 1, out); - idx += decomps[i].used; - } - - /* - * Write the sentinel index as the last decomp node. - */ - fwrite((char *) &idx, sizeof(unsigned long), 1, out); - - /* - * Write the decompositions themselves. - */ - for (i = 0; i < decomps_used; i++) - fwrite((char *) decomps[i].decomp, sizeof(unsigned long), - decomps[i].used, out); - - /* - * Seek back to the beginning and write the byte count. - */ - bytes = (sizeof(unsigned long) * idx) + - (sizeof(unsigned long) * ((hdr[1] << 1) + 1)); - fseek(out, sizeof(unsigned short) << 1, 0L); - fwrite((char *) &bytes, sizeof(unsigned long), 1, out); - - fclose(out); - } - - /***************************************************************** - * - * Generate the combining class data. - * - *****************************************************************/ - - /* - * Open the cmbcl.dat file. - */ - sprintf(path, "%s/cmbcl.dat", opath); - if ((out = fopen(path, "wb")) == 0) - return; - - /* - * Set the number of ranges used. Each range has a combining class which - * means each entry is a 3-tuple. - */ - hdr[1] = ccl_used / 3; - - /* - * Write the header. - */ - fwrite((char *) hdr, sizeof(unsigned short), 2, out); - - /* - * Write out the byte count to maintain header size. - */ - bytes = ccl_used * sizeof(unsigned long); - fwrite((char *) &bytes, sizeof(unsigned long), 1, out); - - if (ccl_used > 0) - /* - * Write the combining class ranges out. - */ - fwrite((char *) ccl, sizeof(unsigned long), ccl_used, out); - - fclose(out); - - /***************************************************************** - * - * Generate the number data. - * - *****************************************************************/ - - /* - * Open the num.dat file. - */ - sprintf(path, "%s/num.dat", opath); - if ((out = fopen(path, "wb")) == 0) - return; - - /* - * The count part of the header will be the total number of codes that - * have numbers. - */ - hdr[1] = (unsigned short) (ncodes_used << 1); - bytes = (ncodes_used * sizeof(_codeidx_t)) + (nums_used * sizeof(_num_t)); - - /* - * Write the header. - */ - fwrite((char *) hdr, sizeof(unsigned short), 2, out); - - /* - * Write out the byte count to maintain header size. - */ - fwrite((char *) &bytes, sizeof(unsigned long), 1, out); - - /* - * Now, if number mappings exist, write them out. - */ - if (ncodes_used > 0) { - fwrite((char *) ncodes, sizeof(_codeidx_t), ncodes_used, out); - fwrite((char *) nums, sizeof(_num_t), nums_used, out); - } - - fclose(out); -} - -void -#ifdef __STDC__ -main(int argc, char *argv[]) -#else -main(argc, argv) -int argc; -char *argv[]; -#endif -{ - FILE *in; - char *prog, *opath; - - if ((prog = strrchr(argv[0], '/')) != 0) - prog++; - else - prog = argv[0]; - - opath = 0; - in = stdin; - - argc--; - argv++; - - while (argc > 0) { - if (argv[0][0] == '-' && argv[0][1] == 'o') { - argc--; - argv++; - opath = argv[0]; - } else { - if (in != stdin) - fclose(in); - if ((in = fopen(argv[0], "rb")) == 0) - fprintf(stderr, "%s: unable to open ctype file %s\n", - prog, argv[0]); - else { - read_cdata(in); - fclose(in); - in = 0; - } - } - argc--; - argv++; - } - - if (opath == 0) - opath = "."; - write_cdata(opath); - - exit(0); -} diff --git a/intl/unicharutil/ucdata.c b/intl/unicharutil/ucdata.c deleted file mode 100644 index 318cac8d5869..000000000000 --- a/intl/unicharutil/ucdata.c +++ /dev/null @@ -1,1162 +0,0 @@ -/* - * Copyright 1996, 1997, 1998 Computing Research Labs, - * New Mexico State University - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT - * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -#ifndef lint -#ifdef __GNUC__ -static char rcsid[] __attribute__ ((unused)) = "$Id: ucdata.c,v 1.1 1999/01/08 00:19:11 ftang%netscape.com Exp $"; -#else -static char rcsid[] = "$Id: ucdata.c,v 1.1 1999/01/08 00:19:11 ftang%netscape.com Exp $"; -#endif -#endif - -#include -#include -#include -#ifndef WIN32 -#include -#endif - -#include "ucdata.h" - -/************************************************************************** - * - * Miscellaneous types, data, and support functions. - * - **************************************************************************/ - -typedef struct { - unsigned short bom; - unsigned short cnt; - union { - unsigned long bytes; - unsigned short len[2]; - } size; -} _ucheader_t; - -/* - * A simple array of 32-bit masks for lookup. - */ -static unsigned long masks32[32] = { - 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, - 0x00000040, 0x00000080, 0x00000100, 0x00000200, 0x00000400, 0x00000800, - 0x00001000, 0x00002000, 0x00004000, 0x00008000, 0x00010000, 0x00020000, - 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000, 0x00800000, - 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, - 0x40000000, 0x80000000 -}; - -#define endian_short(cc) (((cc) >> 8) | (((cc) & 0xff) << 8)) -#define endian_long(cc) ((((cc) & 0xff) << 24)|((((cc) >> 8) & 0xff) << 16)|\ - ((((cc) >> 16) & 0xff) << 8)|((cc) >> 24)) - -static FILE * -#ifdef __STDC__ -_ucopenfile(char *paths, char *filename, char *mode) -#else -_ucopenfile(paths, filename, mode) -char *paths, *filename, *mode; -#endif -{ - FILE *f; - char *fp, *dp, *pp, path[BUFSIZ]; - - if (filename == 0 || *filename == 0) - return 0; - - dp = paths; - while (dp && *dp) { - pp = path; - while (*dp && *dp != ':') - *pp++ = *dp++; - *pp++ = '/'; - - fp = filename; - while (*fp) - *pp++ = *fp++; - *pp = 0; - - if ((f = fopen(path, mode)) != 0) - return f; - - if (*dp == ':') - dp++; - } - - return 0; -} - -/************************************************************************** - * - * Support for the character properties. - * - **************************************************************************/ - -static unsigned long _ucprop_size; -static unsigned short *_ucprop_offsets; -static unsigned long *_ucprop_ranges; - -static void -#ifdef __STDC__ -_ucprop_load(char *paths, int reload) -#else -_ucprop_load(paths, reload) -char *paths; -int reload; -#endif -{ - FILE *in; - unsigned long size, i; - _ucheader_t hdr; - - if (_ucprop_size > 0) { - if (!reload) - /* - * The character properties have already been loaded. - */ - return; - - /* - * Unload the current character property data in preparation for - * loading a new copy. Only the first array has to be deallocated - * because all the memory for the arrays is allocated as a single - * block. - */ - free((char *) _ucprop_offsets); - _ucprop_size = 0; - } - - if ((in = _ucopenfile(paths, "ctype.dat", "rb")) == 0) - return; - - /* - * Load the header. - */ - fread((char *) &hdr, sizeof(_ucheader_t), 1, in); - - if (hdr.bom == 0xfffe) { - hdr.cnt = endian_short(hdr.cnt); - hdr.size.bytes = endian_long(hdr.size.bytes); - } - - if ((_ucprop_size = hdr.cnt) == 0) { - fclose(in); - return; - } - - /* - * Allocate all the storage needed for the lookup table. - */ - _ucprop_offsets = (unsigned short *) malloc(hdr.size.bytes); - - /* - * Calculate the offset into the storage for the ranges. The offsets - * array is on a 4-byte boundary and one larger than the value provided in - * the header count field. This means the offset to the ranges must be - * calculated after aligning the count to a 4-byte boundary. - */ - if ((size = ((hdr.cnt + 1) * sizeof(unsigned short))) & 3) - size += 4 - (size & 3); - size >>= 1; - _ucprop_ranges = (unsigned long *) (_ucprop_offsets + size); - - /* - * Load the offset array. - */ - fread((char *) _ucprop_offsets, sizeof(unsigned short), size, in); - - /* - * Do an endian swap if necessary. Don't forget there is an extra node on - * the end with the final index. - */ - if (hdr.bom == 0xfffe) { - for (i = 0; i <= _ucprop_size; i++) - _ucprop_offsets[i] = endian_short(_ucprop_offsets[i]); - } - - /* - * Load the ranges. The number of elements is in the last array position - * of the offsets. - */ - fread((char *) _ucprop_ranges, sizeof(unsigned long), - _ucprop_offsets[_ucprop_size], in); - - fclose(in); - - /* - * Do an endian swap if necessary. - */ - if (hdr.bom == 0xfffe) { - for (i = 0; i < _ucprop_offsets[_ucprop_size]; i++) - _ucprop_ranges[i] = endian_long(_ucprop_ranges[i]); - } -} - -static void -#ifdef __STDC__ -_ucprop_unload(void) -#else -_ucprop_unload() -#endif -{ - if (_ucprop_size == 0) - return; - - /* - * Only need to free the offsets because the memory is allocated as a - * single block. - */ - free((char *) _ucprop_offsets); - _ucprop_size = 0; -} - -static int -#ifdef __STDC__ -_ucprop_lookup(unsigned long code, unsigned long n) -#else -_ucprop_lookup(code, n) -unsigned long code, n; -#endif -{ - long l, r, m; - - /* - * There is an extra node on the end of the offsets to allow this routine - * to work right. If the index is 0xffff, then there are no nodes for the - * property. - */ - if ((l = _ucprop_offsets[n]) == 0xffff) - return 0; - - /* - * Locate the next offset that is not 0xffff. The sentinel at the end of - * the array is the max index value. - */ - for (m = 1; - n + m < _ucprop_size && _ucprop_offsets[n + m] == 0xffff; m++) ; - - r = _ucprop_offsets[n + m] - 1; - - while (l <= r) { - /* - * Determine a "mid" point and adjust to make sure the mid point is at - * the beginning of a range pair. - */ - m = (l + r) >> 1; - m -= (m & 1); - if (code > _ucprop_ranges[m + 1]) - l = m + 2; - else if (code < _ucprop_ranges[m]) - r = m - 2; - else if (code >= _ucprop_ranges[m] && code <= _ucprop_ranges[m + 1]) - return 1; - } - return 0; -} - -int -#ifdef __STDC__ -ucisprop(unsigned long code, unsigned long mask1, unsigned long mask2) -#else -ucisprop(code, mask1, mask2) -unsigned long code, mask1, mask2; -#endif -{ - unsigned long i; - - if (mask1 == 0 && mask2 == 0) - return 0; - - for (i = 0; mask1 && i < 32; i++) { - if ((mask1 & masks32[i]) && _ucprop_lookup(code, i)) - return 1; - } - - for (i = 32; mask2 && i < _ucprop_size; i++) { - if ((mask2 & masks32[i & 31]) && _ucprop_lookup(code, i)) - return 1; - } - - return 0; -} - -/************************************************************************** - * - * Support for case mapping. - * - **************************************************************************/ - -static unsigned long _uccase_size; -static unsigned short _uccase_len[2]; -static unsigned long *_uccase_map; - -static void -#ifdef __STDC__ -_uccase_load(char *paths, int reload) -#else -_uccase_load(paths, reload) -char *paths; -int reload; -#endif -{ - FILE *in; - unsigned long i; - _ucheader_t hdr; - - if (_uccase_size > 0) { - if (!reload) - /* - * The case mappings have already been loaded. - */ - return; - - free((char *) _uccase_map); - _uccase_size = 0; - } - - if ((in = _ucopenfile(paths, "case.dat", "rb")) == 0) - return; - - /* - * Load the header. - */ - fread((char *) &hdr, sizeof(_ucheader_t), 1, in); - - if (hdr.bom == 0xfffe) { - hdr.cnt = endian_short(hdr.cnt); - hdr.size.len[0] = endian_short(hdr.size.len[0]); - hdr.size.len[1] = endian_short(hdr.size.len[1]); - } - - /* - * Set the node count and lengths of the upper and lower case mapping - * tables. - */ - _uccase_size = hdr.cnt * 3; - _uccase_len[0] = hdr.size.len[0] * 3; - _uccase_len[1] = hdr.size.len[1] * 3; - - _uccase_map = (unsigned long *) - malloc(_uccase_size * sizeof(unsigned long)); - - /* - * Load the case mapping table. - */ - fread((char *) _uccase_map, sizeof(unsigned long), _uccase_size, in); - - /* - * Do an endian swap if necessary. - */ - if (hdr.bom == 0xfffe) { - for (i = 0; i < _uccase_size; i++) - _uccase_map[i] = endian_long(_uccase_map[i]); - } -} - -static void -#ifdef __STDC__ -_uccase_unload(void) -#else -_uccase_unload() -#endif -{ - if (_uccase_size == 0) - return; - - free((char *) _uccase_map); - _uccase_size = 0; -} - -static unsigned long -#ifdef __STDC__ -_uccase_lookup(unsigned long code, long l, long r, int field) -#else -_uccase_lookup(code, l, r, field) -unsigned long code; -long l, r; -int field; -#endif -{ - long m; - - /* - * Do the binary search. - */ - while (l <= r) { - /* - * Determine a "mid" point and adjust to make sure the mid point is at - * the beginning of a case mapping triple. - */ - m = (l + r) >> 1; - m -= (m % 3); - if (code > _uccase_map[m]) - l = m + 3; - else if (code < _uccase_map[m]) - r = m - 3; - else if (code == _uccase_map[m]) - return _uccase_map[m + field]; - } - - return code; -} - -unsigned long -#ifdef __STDC__ -uctoupper(unsigned long code) -#else -uctoupper(code) -unsigned long code; -#endif -{ - int field; - long l, r; - - if (ucisupper(code)) - return code; - - if (ucislower(code)) { - /* - * The character is lower case. - */ - field = 1; - l = _uccase_len[0]; - r = (l + _uccase_len[1]) - 1; - } else { - /* - * The character is title case. - */ - field = 2; - l = _uccase_len[0] + _uccase_len[1]; - r = _uccase_size - 1; - } - return _uccase_lookup(code, l, r, field); -} - -unsigned long -#ifdef __STDC__ -uctolower(unsigned long code) -#else -uctolower(code) -unsigned long code; -#endif -{ - int field; - long l, r; - - if (ucislower(code)) - return code; - - if (ucisupper(code)) { - /* - * The character is upper case. - */ - field = 1; - l = 0; - r = _uccase_len[0] - 1; - } else { - /* - * The character is title case. - */ - field = 2; - l = _uccase_len[0] + _uccase_len[1]; - r = _uccase_size - 1; - } - return _uccase_lookup(code, l, r, field); -} - -unsigned long -#ifdef __STDC__ -uctotitle(unsigned long code) -#else -uctotitle(code) -unsigned long code; -#endif -{ - int field; - long l, r; - - if (ucistitle(code)) - return code; - - /* - * The offset will always be the same for converting to title case. - */ - field = 2; - - if (ucisupper(code)) { - /* - * The character is upper case. - */ - l = 0; - r = _uccase_len[0] - 1; - } else { - /* - * The character is lower case. - */ - l = _uccase_len[0]; - r = (l + _uccase_len[1]) - 1; - } - return _uccase_lookup(code, l, r, field); -} - -/************************************************************************** - * - * Support for decompositions. - * - **************************************************************************/ - -static unsigned long _ucdcmp_size; -static unsigned long *_ucdcmp_nodes; -static unsigned long *_ucdcmp_decomp; - -static void -#ifdef __STDC__ -_ucdcmp_load(char *paths, int reload) -#else -_ucdcmp_load(paths, reload) -char *paths; -int reload; -#endif -{ - FILE *in; - unsigned long size, i; - _ucheader_t hdr; - - if (_ucdcmp_size > 0) { - if (!reload) - /* - * The decompositions have already been loaded. - */ - return; - - free((char *) _ucdcmp_nodes); - _ucdcmp_size = 0; - } - - if ((in = _ucopenfile(paths, "decomp.dat", "rb")) == 0) - return; - - /* - * Load the header. - */ - fread((char *) &hdr, sizeof(_ucheader_t), 1, in); - - if (hdr.bom == 0xfffe) { - hdr.cnt = endian_short(hdr.cnt); - hdr.size.bytes = endian_long(hdr.size.bytes); - } - - _ucdcmp_size = hdr.cnt << 1; - _ucdcmp_nodes = (unsigned long *) malloc(hdr.size.bytes); - _ucdcmp_decomp = _ucdcmp_nodes + (_ucdcmp_size + 1); - - /* - * Read the decomposition data in. - */ - size = hdr.size.bytes / sizeof(unsigned long); - fread((char *) _ucdcmp_nodes, sizeof(unsigned long), size, in); - - /* - * Do an endian swap if necessary. - */ - if (hdr.bom == 0xfffe) { - for (i = 0; i < size; i++) - _ucdcmp_nodes[i] = endian_long(_ucdcmp_nodes[i]); - } -} - -static void -#ifdef __STDC__ -_ucdcmp_unload(void) -#else -_ucdcmp_unload() -#endif -{ - if (_ucdcmp_size == 0) - return; - - /* - * Only need to free the offsets because the memory is allocated as a - * single block. - */ - free((char *) _ucdcmp_nodes); - _ucdcmp_size = 0; -} - -int -#ifdef __STDC__ -ucdecomp(unsigned long code, unsigned long *num, unsigned long **decomp) -#else -ucdecomp(code, num, decomp) -unsigned long code, *num, **decomp; -#endif -{ - long l, r, m; - - l = 0; - r = _ucdcmp_nodes[_ucdcmp_size] - 1; - - while (l <= r) { - /* - * Determine a "mid" point and adjust to make sure the mid point is at - * the beginning of a code+offset pair. - */ - m = (l + r) >> 1; - m -= (m & 1); - if (code > _ucdcmp_nodes[m]) - l = m + 2; - else if (code < _ucdcmp_nodes[m]) - r = m - 2; - else if (code == _ucdcmp_nodes[m]) { - *num = _ucdcmp_nodes[m + 3] - _ucdcmp_nodes[m + 1]; - *decomp = &_ucdcmp_decomp[_ucdcmp_nodes[m + 1]]; - return 1; - } - } - return 0; -} - -int -#ifdef __STDC__ -ucdecomp_hangul(unsigned long code, unsigned long *num, unsigned long decomp[]) -#else -ucdecomp_hangul(code, num, decomp) -unsigned long code, *num, decomp[]; -#endif -{ - if (!ucishangul(code)) - return 0; - - code -= 0xac00; - decomp[0] = 0x1100 + (unsigned long) (code / 588); - decomp[1] = 0x1161 + (unsigned long) ((code % 588) / 28); - decomp[2] = 0x11a7 + (unsigned long) (code % 28); - *num = (decomp[2] != 0x11a7) ? 3 : 2; - - return 1; -} - -/************************************************************************** - * - * Support for combining classes. - * - **************************************************************************/ - -static unsigned long _uccmcl_size; -static unsigned long *_uccmcl_nodes; - -static void -#ifdef __STDC__ -_uccmcl_load(char *paths, int reload) -#else -_uccmcl_load(paths, reload) -char *paths; -int reload; -#endif -{ - FILE *in; - unsigned long i; - _ucheader_t hdr; - - if (_uccmcl_size > 0) { - if (!reload) - /* - * The combining classes have already been loaded. - */ - return; - - free((char *) _uccmcl_nodes); - _uccmcl_size = 0; - } - - if ((in = _ucopenfile(paths, "cmbcl.dat", "rb")) == 0) - return; - - /* - * Load the header. - */ - fread((char *) &hdr, sizeof(_ucheader_t), 1, in); - - if (hdr.bom == 0xfffe) { - hdr.cnt = endian_short(hdr.cnt); - hdr.size.bytes = endian_long(hdr.size.bytes); - } - - _uccmcl_size = hdr.cnt * 3; - _uccmcl_nodes = (unsigned long *) malloc(hdr.size.bytes); - - /* - * Read the combining classes in. - */ - fread((char *) _uccmcl_nodes, sizeof(unsigned long), _uccmcl_size, in); - - /* - * Do an endian swap if necessary. - */ - if (hdr.bom == 0xfffe) { - for (i = 0; i < _uccmcl_size; i++) - _uccmcl_nodes[i] = endian_long(_uccmcl_nodes[i]); - } -} - -static void -#ifdef __STDC__ -_uccmcl_unload(void) -#else -_uccmcl_unload() -#endif -{ - if (_uccmcl_size == 0) - return; - - free((char *) _uccmcl_nodes); - _uccmcl_size = 0; -} - -unsigned long -#ifdef __STDC__ -uccombining_class(unsigned long code) -#else -uccombining_class(code) -unsigned long code; -#endif -{ - long l, r, m; - - l = 0; - r = _uccmcl_size - 1; - - while (l <= r) { - m = (l + r) >> 1; - m -= (m % 3); - if (code > _uccmcl_nodes[m + 1]) - l = m + 3; - else if (code < _uccmcl_nodes[m]) - r = m - 3; - else if (code >= _uccmcl_nodes[m] && code <= _uccmcl_nodes[m + 1]) - return _uccmcl_nodes[m + 2]; - } - return 0; -} - -/************************************************************************** - * - * Support for numeric values. - * - **************************************************************************/ - -static unsigned long *_ucnum_nodes; -static unsigned long _ucnum_size; -static short *_ucnum_vals; - -static void -#ifdef __STDC__ -_ucnumb_load(char *paths, int reload) -#else -_ucnumb_load(paths, reload) -char *paths; -int reload; -#endif -{ - FILE *in; - unsigned long size, i; - _ucheader_t hdr; - - if (_ucnum_size > 0) { - if (!reload) - /* - * The numbers have already been loaded. - */ - return; - - free((char *) _ucnum_nodes); - _ucnum_size = 0; - } - - if ((in = _ucopenfile(paths, "num.dat", "rb")) == 0) - return; - - /* - * Load the header. - */ - fread((char *) &hdr, sizeof(_ucheader_t), 1, in); - - if (hdr.bom == 0xfffe) { - hdr.cnt = endian_short(hdr.cnt); - hdr.size.bytes = endian_long(hdr.size.bytes); - } - - _ucnum_size = hdr.cnt; - _ucnum_nodes = (unsigned long *) malloc(hdr.size.bytes); - _ucnum_vals = (short *) (_ucnum_nodes + _ucnum_size); - - /* - * Read the combining classes in. - */ - fread((char *) _ucnum_nodes, sizeof(unsigned char), hdr.size.bytes, in); - - /* - * Do an endian swap if necessary. - */ - if (hdr.bom == 0xfffe) { - for (i = 0; i < _ucnum_size; i++) - _ucnum_nodes[i] = endian_long(_ucnum_nodes[i]); - - /* - * Determine the number of values that have to be adjusted. - */ - size = (hdr.size.bytes - - (_ucnum_size * (sizeof(unsigned long) << 1))) / - sizeof(short); - - for (i = 0; i < size; i++) - _ucnum_vals[i] = endian_short(_ucnum_vals[i]); - } -} - -static void -#ifdef __STDC__ -_ucnumb_unload(void) -#else -_ucnumb_unload() -#endif -{ - if (_ucnum_size == 0) - return; - - free((char *) _ucnum_nodes); - _ucnum_size = 0; -} - -int -#ifdef __STDC__ -ucnumber_lookup(unsigned long code, struct ucnumber *num) -#else -ucnumber_lookup(code, num) -unsigned long code; -struct ucnumber *num; -#endif -{ - long l, r, m; - short *vp; - - l = 0; - r = _ucnum_size - 1; - while (l <= r) { - /* - * Determine a "mid" point and adjust to make sure the mid point is at - * the beginning of a code+offset pair. - */ - m = (l + r) >> 1; - m -= (m & 1); - if (code > _ucnum_nodes[m]) - l = m + 2; - else if (code < _ucnum_nodes[m]) - r = m - 2; - else { - vp = _ucnum_vals + _ucnum_nodes[m + 1]; - num->numerator = (int) *vp++; - num->denominator = (int) *vp; - return 1; - } - } - return 0; -} - -int -#ifdef __STDC__ -ucdigit_lookup(unsigned long code, int *digit) -#else -ucdigit_lookup(code, digit) -unsigned long code; -int *digit; -#endif -{ - long l, r, m; - short *vp; - - l = 0; - r = _ucnum_size - 1; - while (l <= r) { - /* - * Determine a "mid" point and adjust to make sure the mid point is at - * the beginning of a code+offset pair. - */ - m = (l + r) >> 1; - m -= (m & 1); - if (code > _ucnum_nodes[m]) - l = m + 2; - else if (code < _ucnum_nodes[m]) - r = m - 2; - else { - vp = _ucnum_vals + _ucnum_nodes[m + 1]; - if (*vp == *(vp + 1)) { - *digit = *vp; - return 1; - } - return 0; - } - } - return 0; -} - -struct ucnumber -#ifdef __STDC__ -ucgetnumber(unsigned long code) -#else -ucgetnumber(code) -unsigned long code; -#endif -{ - struct ucnumber num; - - /* - * Initialize with some arbitrary value, because the caller simply cannot - * tell for sure if the code is a number without calling the ucisnumber() - * macro before calling this function. - */ - num.numerator = num.denominator = -111; - - (void) ucnumber_lookup(code, &num); - - return num; -} - -int -#ifdef __STDC__ -ucgetdigit(unsigned long code) -#else -ucgetdigit(code) -unsigned long code; -#endif -{ - int dig; - - /* - * Initialize with some arbitrary value, because the caller simply cannot - * tell for sure if the code is a number without calling the ucisdigit() - * macro before calling this function. - */ - dig = -111; - - (void) ucdigit_lookup(code, &dig); - - return dig; -} - -/************************************************************************** - * - * Setup and cleanup routines. - * - **************************************************************************/ - -void -#ifdef __STDC__ -ucdata_load(char *paths, int masks) -#else -ucdata_load(paths, masks) -char *paths; -int masks; -#endif -{ - if (masks & UCDATA_CTYPE) - _ucprop_load(paths, 0); - if (masks & UCDATA_CASE) - _uccase_load(paths, 0); - if (masks & UCDATA_DECOMP) - _ucdcmp_load(paths, 0); - if (masks & UCDATA_CMBCL) - _uccmcl_load(paths, 0); - if (masks & UCDATA_NUM) - _ucnumb_load(paths, 0); -} - -void -#ifdef __STDC__ -ucdata_unload(int masks) -#else -ucdata_unload(masks) -int masks; -#endif -{ - if (masks & UCDATA_CTYPE) - _ucprop_unload(); - if (masks & UCDATA_CASE) - _uccase_unload(); - if (masks & UCDATA_DECOMP) - _ucdcmp_unload(); - if (masks & UCDATA_CMBCL) - _uccmcl_unload(); - if (masks & UCDATA_NUM) - _ucnumb_unload(); -} - -void -#ifdef __STDC__ -ucdata_reload(char *paths, int masks) -#else -ucdata_reload(paths, masks) -char *paths; -int masks; -#endif -{ - if (masks & UCDATA_CTYPE) - _ucprop_load(paths, 1); - if (masks & UCDATA_CASE) - _uccase_load(paths, 1); - if (masks & UCDATA_DECOMP) - _ucdcmp_load(paths, 1); - if (masks & UCDATA_CMBCL) - _uccmcl_load(paths, 1); - if (masks & UCDATA_NUM) - _ucnumb_load(paths, 1); -} - -#ifdef TEST - -void -#ifdef __STDC__ -main(void) -#else -main() -#endif -{ - int dig; - unsigned long i, lo, *dec; - struct ucnumber num; - - ucdata_setup("."); - - if (ucisweak(0x30)) - printf("WEAK\n"); - else - printf("NOT WEAK\n"); - - printf("LOWER 0x%04lX\n", uctolower(0xff3a)); - printf("UPPER 0x%04lX\n", uctoupper(0xff5a)); - - if (ucisalpha(0x1d5)) - printf("ALPHA\n"); - else - printf("NOT ALPHA\n"); - - if (ucisupper(0x1d5)) { - printf("UPPER\n"); - lo = uctolower(0x1d5); - printf("0x%04lx\n", lo); - lo = uctotitle(0x1d5); - printf("0x%04lx\n", lo); - } else - printf("NOT UPPER\n"); - - if (ucistitle(0x1d5)) - printf("TITLE\n"); - else - printf("NOT TITLE\n"); - - if (uciscomposite(0x1d5)) - printf("COMPOSITE\n"); - else - printf("NOT COMPOSITE\n"); - - if (ucdecomp(0x1d5, &lo, &dec)) { - for (i = 0; i < lo; i++) - printf("0x%04lx ", dec[i]); - putchar('\n'); - } - - if ((lo = uccombining_class(0x41)) != 0) - printf("0x41 CCL %ld\n", lo); - - if (ucisxdigit(0xfeff)) - printf("0xFEFF HEX DIGIT\n"); - else - printf("0xFEFF NOT HEX DIGIT\n"); - - if (ucisdefined(0x10000)) - printf("0x10000 DEFINED\n"); - else - printf("0x10000 NOT DEFINED\n"); - - if (ucnumber_lookup(0x30, &num)) { - if (num.numerator != num.denominator) - printf("UCNUMBER: 0x30 = %d/%d\n", num.numerator, num.denominator); - else - printf("UCNUMBER: 0x30 = %d\n", num.numerator); - } else - printf("UCNUMBER: 0x30 NOT A NUMBER\n"); - - if (ucnumber_lookup(0xbc, &num)) { - if (num.numerator != num.denominator) - printf("UCNUMBER: 0xbc = %d/%d\n", num.numerator, num.denominator); - else - printf("UCNUMBER: 0xbc = %d\n", num.numerator); - } else - printf("UCNUMBER: 0xbc NOT A NUMBER\n"); - - - if (ucnumber_lookup(0xff19, &num)) { - if (num.numerator != num.denominator) - printf("UCNUMBER: 0xff19 = %d/%d\n", num.numerator, num.denominator); - else - printf("UCNUMBER: 0xff19 = %d\n", num.numerator); - } else - printf("UCNUMBER: 0xff19 NOT A NUMBER\n"); - - if (ucnumber_lookup(0x4e00, &num)) { - if (num.numerator != num.denominator) - printf("UCNUMBER: 0x4e00 = %d/%d\n", num.numerator, num.denominator); - else - printf("UCNUMBER: 0x4e00 = %d\n", num.numerator); - } else - printf("UCNUMBER: 0x4e00 NOT A NUMBER\n"); - - if (ucdigit_lookup(0x06f9, &dig)) - printf("UCDIGIT: 0x6f9 = %d\n", dig); - else - printf("UCDIGIT: 0x6f9 NOT A NUMBER\n"); - - dig = ucgetdigit(0x0969); - printf("UCGETDIGIT: 0x969 = %d\n", dig); - - num = ucgetnumber(0x30); - if (num.numerator != num.denominator) - printf("UCGETNUMBER: 0x30 = %d/%d\n", num.numerator, num.denominator); - else - printf("UCGETNUMBER: 0x30 = %d\n", num.numerator); - - num = ucgetnumber(0xbc); - if (num.numerator != num.denominator) - printf("UCGETNUMBER: 0xbc = %d/%d\n", num.numerator, num.denominator); - else - printf("UCGETNUMBER: 0xbc = %d\n", num.numerator); - - num = ucgetnumber(0xff19); - if (num.numerator != num.denominator) - printf("UCGETNUMBER: 0xff19 = %d/%d\n", num.numerator, num.denominator); - else - printf("UCGETNUMBER: 0xff19 = %d\n", num.numerator); - - ucdata_cleanup(); - exit(0); -} - -#endif /* TEST */ diff --git a/intl/unicharutil/ucdata.h b/intl/unicharutil/ucdata.h deleted file mode 100644 index 4b765cbd38f5..000000000000 --- a/intl/unicharutil/ucdata.h +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright 1996, 1997, 1998 Computing Research Labs, - * New Mexico State University - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT - * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -#ifndef _h_ucdata -#define _h_ucdata - -/* - * $Id: ucdata.h,v 1.1 1999/01/08 00:19:12 ftang%netscape.com Exp $ - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#undef __ -#ifdef __STDC__ -#define __(x) x -#else -#define __(x) () -#endif - -#define UCDATA_VERSION "1.9" - -/************************************************************************** - * - * Masks and macros for character properties. - * - **************************************************************************/ - -/* - * Values that can appear in the `mask1' parameter of the ucisprop() - * function. - */ -#define UC_MN 0x00000001 /* Mark, Non-Spacing */ -#define UC_MC 0x00000002 /* Mark, Spacing Combining */ -#define UC_ME 0x00000004 /* Mark, Enclosing */ -#define UC_ND 0x00000008 /* Number, Decimal Digit */ -#define UC_NL 0x00000010 /* Number, Letter */ -#define UC_NO 0x00000020 /* Number, Other */ -#define UC_ZS 0x00000040 /* Separator, Space */ -#define UC_ZL 0x00000080 /* Separator, Line */ -#define UC_ZP 0x00000100 /* Separator, Paragraph */ -#define UC_CC 0x00000200 /* Other, Control */ -#define UC_CF 0x00000400 /* Other, Format */ -#define UC_OS 0x00000800 /* Other, Surrogate */ -#define UC_CO 0x00001000 /* Other, Private Use */ -#define UC_CN 0x00002000 /* Other, Not Assigned */ -#define UC_LU 0x00004000 /* Letter, Uppercase */ -#define UC_LL 0x00008000 /* Letter, Lowercase */ -#define UC_LT 0x00010000 /* Letter, Titlecase */ -#define UC_LM 0x00020000 /* Letter, Modifier */ -#define UC_LO 0x00040000 /* Letter, Other */ -#define UC_PC 0x00080000 /* Punctuation, Connector */ -#define UC_PD 0x00100000 /* Punctuation, Dash */ -#define UC_PS 0x00200000 /* Punctuation, Open */ -#define UC_PE 0x00400000 /* Punctuation, Close */ -#define UC_PO 0x00800000 /* Punctuation, Other */ -#define UC_SM 0x01000000 /* Symbol, Math */ -#define UC_SC 0x02000000 /* Symbol, Currency */ -#define UC_SK 0x04000000 /* Symbol, Modifier */ -#define UC_SO 0x08000000 /* Symbol, Other */ -#define UC_L 0x10000000 /* Left-To-Right */ -#define UC_R 0x20000000 /* Right-To-Left */ -#define UC_EN 0x40000000 /* European Number */ -#define UC_ES 0x80000000 /* European Number Separator */ - -/* - * Values that can appear in the `mask2' parameter of the ucisprop() - * function. - */ -#define UC_ET 0x00000001 /* European Number Terminator */ -#define UC_AN 0x00000002 /* Arabic Number */ -#define UC_CS 0x00000004 /* Common Number Separator */ -#define UC_B 0x00000008 /* Block Separator */ -#define UC_S 0x00000010 /* Segment Separator */ -#define UC_WS 0x00000020 /* Whitespace */ -#define UC_ON 0x00000040 /* Other Neutrals */ -/* - * Implementation specific character properties. - */ -#define UC_CM 0x00000080 /* Composite */ -#define UC_NB 0x00000100 /* Non-Breaking */ -#define UC_SY 0x00000200 /* Symmetric */ -#define UC_HD 0x00000400 /* Hex Digit */ -#define UC_QM 0x00000800 /* Quote Mark */ -#define UC_MR 0x00001000 /* Mirroring */ -#define UC_SS 0x00002000 /* Space, other */ - -#define UC_CP 0x00004000 /* Defined */ - -/* - * Added for UnicodeData-2.1.3. - */ -#define UC_PI 0x00008000 /* Punctuation, Initial */ -#define UC_PF 0x00010000 /* Punctuation, Final */ - -/* - * This is the primary function for testing to see if a character has some set - * of properties. The macros that test for various character properties all - * call this function with some set of masks. - */ -extern int ucisprop __((unsigned long code, unsigned long mask1, - unsigned long mask2)); - -#define ucisalpha(cc) ucisprop(cc, UC_LU|UC_LL|UC_LM|UC_LO|UC_LT, 0) -#define ucisdigit(cc) ucisprop(cc, UC_ND, 0) -#define ucisalnum(cc) ucisprop(cc, UC_LU|UC_LL|UC_LM|UC_LO|UC_LT|UC_ND, 0) -#define uciscntrl(cc) ucisprop(cc, UC_CC|UC_CF, 0) -#define ucisspace(cc) ucisprop(cc, UC_ZS|UC_SS, 0) -#define ucisblank(cc) ucisprop(cc, UC_ZS, 0) -#define ucispunct(cc) ucisprop(cc, UC_PD|UC_PS|UC_PE|UC_PO, UC_PI|UC_PF) -#define ucisgraph(cc) ucisprop(cc, UC_MN|UC_MC|UC_ME|UC_ND|UC_NL|UC_NO|\ - UC_LU|UC_LL|UC_LT|UC_LM|UC_LO|UC_PC|UC_PD|\ - UC_PS|UC_PE|UC_PO|UC_SM|UC_SM|UC_SC|UC_SK|\ - UC_SO, UC_PI|UC_PF) -#define ucisprint(cc) ucisprop(cc, UC_MN|UC_MC|UC_ME|UC_ND|UC_NL|UC_NO|\ - UC_LU|UC_LL|UC_LT|UC_LM|UC_LO|UC_PC|UC_PD|\ - UC_PS|UC_PE|UC_PO|UC_SM|UC_SM|UC_SC|UC_SK|\ - UC_SO|UC_ZS, UC_PI|UC_PF) -#define ucisupper(cc) ucisprop(cc, UC_LU, 0) -#define ucislower(cc) ucisprop(cc, UC_LL, 0) -#define ucistitle(cc) ucisprop(cc, UC_LT, 0) -#define ucisxdigit(cc) ucisprop(cc, 0, UC_HD) - -#define ucisisocntrl(cc) ucisprop(cc, UC_CC, 0) -#define ucisfmtcntrl(cc) ucisprop(cc, UC_CF, 0) - -#define ucissymbol(cc) ucisprop(cc, UC_SM|UC_SC|UC_SO|UC_SK, 0) -#define ucisnumber(cc) ucisprop(cc, UC_ND|UC_NO|UC_NL, 0) -#define ucisnonspacing(cc) ucisprop(cc, UC_MN, 0) -#define ucisopenpunct(cc) ucisprop(cc, UC_PS, 0) -#define ucisclosepunct(cc) ucisprop(cc, UC_PE, 0) -#define ucisinitialpunct(cc) ucisprop(cc, 0, UC_PI) -#define ucisfinalpunct(cc) ucisprop(cc, 0, UC_PF) - -#define uciscomposite(cc) ucisprop(cc, 0, UC_CM) -#define ucishex(cc) ucisprop(cc, 0, UC_HD) -#define ucisquote(cc) ucisprop(cc, 0, UC_QM) -#define ucissymmetric(cc) ucisprop(cc, 0, UC_SY) -#define ucismirroring(cc) ucisprop(cc, 0, UC_MR) -#define ucisnonbreaking(cc) ucisprop(cc, 0, UC_NB) - -/* - * Directionality macros. - */ -#define ucisrtl(cc) ucisprop(cc, UC_R, 0) -#define ucisltr(cc) ucisprop(cc, UC_L, 0) -#define ucisstrong(cc) ucisprop(cc, UC_L|UC_R, 0) -#define ucisweak(cc) ucisprop(cc, UC_EN|UC_ES, UC_ET|UC_AN|UC_CS) -#define ucisneutral(cc) ucisprop(cc, 0, UC_B|UC_S|UC_WS|UC_ON) -#define ucisseparator(cc) ucisprop(cc, 0, UC_B|UC_S) - -/* - * Other macros inspired by John Cowan. - */ -#define ucismark(cc) ucisprop(cc, UC_MN|UC_MC|UC_ME, 0) -#define ucismodif(cc) ucisprop(cc, UC_LM, 0) -#define ucisletnum(cc) ucisprop(cc, UC_NL, 0) -#define ucisconnect(cc) ucisprop(cc, UC_PC, 0) -#define ucisdash(cc) ucisprop(cc, UC_PD, 0) -#define ucismath(cc) ucisprop(cc, UC_SM, 0) -#define uciscurrency(cc) ucisprop(cc, UC_SC, 0) -#define ucismodifsymbol(cc) ucisprop(cc, UC_SK, 0) -#define ucisnsmark(cc) ucisprop(cc, UC_MN, 0) -#define ucisspmark(cc) ucisprop(cc, UC_MC, 0) -#define ucisenclosing(cc) ucisprop(cc, UC_ME, 0) -#define ucisprivate(cc) ucisprop(cc, UC_CO, 0) -#define ucissurrogate(cc) ucisprop(cc, UC_OS, 0) -#define ucislsep(cc) ucisprop(cc, UC_ZL, 0) -#define ucispsep(cc) ucisprop(cc, UC_ZP, 0) - -#define ucisidentstart(cc) ucisprop(cc, UC_LU|UC_LL|UC_LT|UC_LO|UC_NL, 0) -#define ucisidentpart(cc) ucisprop(cc, UC_LU|UC_LL|UC_LT|UC_LO|UC_NL|\ - UC_MN|UC_MC|UC_ND|UC_PC|UC_CF, 0) - -#define ucisdefined(cc) ucisprop(cc, 0, UC_CP) -#define ucisundefined(cc) !ucisprop(cc, 0, UC_CP) - -/* - * Other miscellaneous character property macros. - */ -#define ucishan(cc) (((cc) >= 0x4e00 && (cc) <= 0x9fff) ||\ - ((cc) >= 0xf900 && (cc) <= 0xfaff)) -#define ucishangul(cc) ((cc) >= 0xac00 && (cc) <= 0xd7ff) - -/************************************************************************** - * - * Functions for case conversion. - * - **************************************************************************/ - -extern unsigned long uctoupper __((unsigned long code)); -extern unsigned long uctolower __((unsigned long code)); -extern unsigned long uctotitle __((unsigned long code)); - -/************************************************************************** - * - * Functions for getting decompositions. - * - **************************************************************************/ - -/* - * This routine determines if the code has a decomposition. If it returns 0, - * there is no decomposition. Any other value indicates a decomposition was - * returned. - */ -extern int ucdecomp __((unsigned long code, unsigned long *num, - - unsigned long **decomp)); - -/* - * If the code is a Hangul syllable, this routine decomposes it into the array - * passed. The array size should be at least 3. - */ -extern int ucdecomp_hangul __((unsigned long code, unsigned long *num, - unsigned long decomp[])); - -/************************************************************************** - * - * Functions for getting combining classes. - * - **************************************************************************/ - -/* - * This will return the combining class for a character to be used with the - * Canonical Ordering algorithm. - */ -extern unsigned long uccombining_class __((unsigned long code)); - -/************************************************************************** - * - * Functions for getting numbers and digits. - * - **************************************************************************/ - -struct ucnumber { - int numerator; - int denominator; -}; - -extern int ucnumber_lookup __((unsigned long code, struct ucnumber *num)); -extern int ucdigit_lookup __((unsigned long code, int *digit)); - -/* - * For compatibility with John Cowan's "uctype" package. - */ -extern struct ucnumber ucgetnumber __((unsigned long code)); -extern int ucgetdigit __((unsigned long code)); - -/************************************************************************** - * - * Functions library initialization and cleanup. - * - **************************************************************************/ - -/* - * Macros for specifying the data tables to be loaded for ucdata_load(). - */ -#define UCDATA_CASE 0x01 -#define UCDATA_CTYPE 0x02 -#define UCDATA_DECOMP 0x04 -#define UCDATA_CMBCL 0x08 -#define UCDATA_NUM 0x10 - -#define UCDATA_ALL (UCDATA_CASE|UCDATA_CTYPE|UCDATA_DECOMP|\ - UCDATA_CMBCL|UCDATA_NUM) - -/* - * Functions to load, unload, and reload specific data files. - */ -extern void ucdata_load __((char *paths, int mask)); -extern void ucdata_unload __((int mask)); -extern void ucdata_reload __((char *paths, int mask)); - -/* - * Deprecated functions, now just compatibility macros. - */ -#define ucdata_setup(p) ucdata_load(p, UCDATA_ALL) -#define ucdata_cleanup() ucdata_unload(UCDATA_ALL) - -#undef __ - -#ifdef __cplusplus -} -#endif - -#endif /* _h_ucdata */ From f37ab68a2809accd583dc57c2cddff1bc4efecf7 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Fri, 22 Sep 2017 10:37:17 +0100 Subject: [PATCH 14/37] Bug 1308359 - patch 1 - Remove the nsBidi_noICU implementation of nsBidi, and rename the sources for the _ICU version to the base nsBidi.{h,cpp} filenames. r=xidorn --HG-- rename : layout/base/nsBidi_ICU.cpp => layout/base/nsBidi.cpp --- layout/base/moz.build | 16 +- layout/base/{nsBidi_ICU.cpp => nsBidi.cpp} | 2 +- layout/base/nsBidi.h | 188 +- layout/base/nsBidi_ICU.h | 194 -- layout/base/nsBidi_noICU.cpp | 2089 -------------------- layout/base/nsBidi_noICU.h | 712 ------- 6 files changed, 185 insertions(+), 3016 deletions(-) rename layout/base/{nsBidi_ICU.cpp => nsBidi.cpp} (98%) delete mode 100644 layout/base/nsBidi_ICU.h delete mode 100644 layout/base/nsBidi_noICU.cpp delete mode 100644 layout/base/nsBidi_noICU.h diff --git a/layout/base/moz.build b/layout/base/moz.build index b97cda11737e..093b946b365d 100644 --- a/layout/base/moz.build +++ b/layout/base/moz.build @@ -93,6 +93,7 @@ UNIFIED_SOURCES += [ 'GeometryUtils.cpp', 'LayoutLogging.cpp', 'MobileViewportManager.cpp', + 'nsBidi.cpp', 'nsBidiPresUtils.cpp', 'nsCaret.cpp', 'nsCounterManager.cpp', @@ -123,21 +124,6 @@ UNIFIED_SOURCES += [ 'ZoomConstraintsClient.cpp', ] -if CONFIG['ENABLE_INTL_API']: - EXPORTS += [ - 'nsBidi_ICU.h', - ] - UNIFIED_SOURCES += [ - 'nsBidi_ICU.cpp', - ] -else: - EXPORTS += [ - 'nsBidi_noICU.h', - ] - UNIFIED_SOURCES += [ - 'nsBidi_noICU.cpp', - ] - # nsRefreshDriver.cpp needs to be built separately because of name clashes in the OS X headers SOURCES += [ 'nsRefreshDriver.cpp', diff --git a/layout/base/nsBidi_ICU.cpp b/layout/base/nsBidi.cpp similarity index 98% rename from layout/base/nsBidi_ICU.cpp rename to layout/base/nsBidi.cpp index 482668e24027..1d6975869236 100644 --- a/layout/base/nsBidi_ICU.cpp +++ b/layout/base/nsBidi.cpp @@ -4,7 +4,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "nsBidi_ICU.h" +#include "nsBidi.h" #include "ICUUtils.h" nsBidi::nsBidi() diff --git a/layout/base/nsBidi.h b/layout/base/nsBidi.h index c7c3670921c3..28a2e39b1721 100644 --- a/layout/base/nsBidi.h +++ b/layout/base/nsBidi.h @@ -7,10 +7,188 @@ #ifndef nsBidi_h__ #define nsBidi_h__ -#if ENABLE_INTL_API -#include "nsBidi_ICU.h" -#else -#include "nsBidi_noICU.h" -#endif +#include "unicode/ubidi.h" +#include "nsIFrame.h" // for nsBidiLevel/nsBidiDirection declarations + +// nsBidi implemented as a simple wrapper around the bidi reordering engine +// from ICU. +// We could eliminate this and let callers use the ICU functions directly +// once we no longer care about building without ICU available. + +class nsBidi +{ +public: + /** @brief Default constructor. + * + * The nsBidi object is initially empty. It is assigned + * the Bidi properties of a paragraph by SetPara(). + */ + explicit nsBidi(); + + /** @brief Destructor. */ + virtual ~nsBidi(); + + + /** + * Perform the Unicode Bidi algorithm. + * + * @param aText is a pointer to the single-paragraph text that the + * Bidi algorithm will be performed on + * (step (P1) of the algorithm is performed externally). + * The text must be (at least) aLength long. + * + * @param aLength is the length of the text; if aLength==-1 then + * the text must be zero-terminated. + * + * @param aParaLevel specifies the default level for the paragraph; + * it is typically 0 (LTR) or 1 (RTL). + * If the function shall determine the paragraph level from the text, + * then aParaLevel can be set to + * either NSBIDI_DEFAULT_LTR + * or NSBIDI_DEFAULT_RTL; + * if there is no strongly typed character, then + * the desired default is used (0 for LTR or 1 for RTL). + * Any other value between 0 and NSBIDI_MAX_EXPLICIT_LEVEL + * is also valid, with odd levels indicating RTL. + */ + nsresult SetPara(const char16_t *aText, int32_t aLength, + nsBidiLevel aParaLevel); + + /** + * Get the directionality of the text. + * + * @param aDirection receives a NSBIDI_XXX value that indicates + * if the entire text represented by this object is unidirectional, + * and which direction, or if it is mixed-directional. + * + * @see nsBidiDirection + */ + nsresult GetDirection(nsBidiDirection* aDirection); + + /** + * Get the paragraph level of the text. + * + * @param aParaLevel receives a NSBIDI_XXX value indicating + * the paragraph level + * + * @see nsBidiLevel + */ + nsresult GetParaLevel(nsBidiLevel* aParaLevel); + + /** + * Get a logical run. + * This function returns information about a run and is used + * to retrieve runs in logical order.

+ * This is especially useful for line-breaking on a paragraph. + * + * @param aLogicalStart is the first character of the run. + * + * @param aLogicalLimit will receive the limit of the run. + * The l-value that you point to here may be the + * same expression (variable) as the one for + * aLogicalStart. + * This pointer can be nullptr if this + * value is not necessary. + * + * @param aLevel will receive the level of the run. + * This pointer can be nullptr if this + * value is not necessary. + */ + nsresult GetLogicalRun(int32_t aLogicalStart, int32_t* aLogicalLimit, + nsBidiLevel* aLevel); + + /** + * Get the number of runs. + * This function may invoke the actual reordering on the + * nsBidi object, after SetPara + * may have resolved only the levels of the text. Therefore, + * CountRuns may have to allocate memory, + * and may fail doing so. + * + * @param aRunCount will receive the number of runs. + */ + nsresult CountRuns(int32_t* aRunCount); + + /** + * Get one run's logical start, length, and directionality, + * which can be 0 for LTR or 1 for RTL. + * In an RTL run, the character at the logical start is + * visually on the right of the displayed run. + * The length is the number of characters in the run.

+ * CountRuns should be called + * before the runs are retrieved. + * + * @param aRunIndex is the number of the run in visual order, in the + * range [0..CountRuns-1]. + * + * @param aLogicalStart is the first logical character index in the text. + * The pointer may be nullptr if this index is not needed. + * + * @param aLength is the number of characters (at least one) in the run. + * The pointer may be nullptr if this is not needed. + * + * @param aDirection will receive the directionality of the run, + * NSBIDI_LTR==0 or NSBIDI_RTL==1, + * never NSBIDI_MIXED. + * + * @see CountRuns

+ * + * Example: + * @code + * int32_t i, count, logicalStart, visualIndex=0, length; + * nsBidiDirection dir; + * pBidi->CountRuns(&count); + * for(i=0; iGetVisualRun(i, &logicalStart, &length, &dir); + * if(NSBIDI_LTR==dir) { + * do { // LTR + * show_char(text[logicalStart++], visualIndex++); + * } while(--length>0); + * } else { + * logicalStart+=length; // logicalLimit + * do { // RTL + * show_char(text[--logicalStart], visualIndex++); + * } while(--length>0); + * } + * } + * @endcode + * + * Note that in right-to-left runs, code like this places + * modifier letters before base characters and second surrogates + * before first ones. + */ + nsresult GetVisualRun(int32_t aRunIndex, int32_t* aLogicalStart, + int32_t* aLength, nsBidiDirection* aDirection); + + /** + * This is a convenience function that does not use a nsBidi object. + * It is intended to be used for when an application has determined the levels + * of objects (character sequences) and just needs to have them reordered (L2). + * This is equivalent to using GetVisualMap on a + * nsBidi object. + * + * @param aLevels is an array with aLength levels that have been + * determined by the application. + * + * @param aLength is the number of levels in the array, or, semantically, + * the number of objects to be reordered. + * It must be aLength>0. + * + * @param aIndexMap is a pointer to an array of aLength + * indexes which will reflect the reordering of the characters. + * The array does not need to be initialized.

+ * The index map will result in + * aIndexMap[aVisualIndex]==aLogicalIndex. + */ + static nsresult ReorderVisual(const nsBidiLevel* aLevels, int32_t aLength, + int32_t* aIndexMap); + +private: + nsBidi(const nsBidi&) = delete; + void operator=(const nsBidi&) = delete; + +protected: + UBiDi* mBiDi; +}; #endif // _nsBidi_h_ diff --git a/layout/base/nsBidi_ICU.h b/layout/base/nsBidi_ICU.h deleted file mode 100644 index 587232e4d94b..000000000000 --- a/layout/base/nsBidi_ICU.h +++ /dev/null @@ -1,194 +0,0 @@ -/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef nsBidi_ICU_h__ -#define nsBidi_ICU_h__ - -#include "unicode/ubidi.h" -#include "nsIFrame.h" // for nsBidiLevel/nsBidiDirection declarations - -// nsBidi implemented as a simple wrapper around the bidi reordering engine -// from ICU. -// We could eliminate this and let callers use the ICU functions directly -// once we no longer care about building without ICU available. - -class nsBidi -{ -public: - /** @brief Default constructor. - * - * The nsBidi object is initially empty. It is assigned - * the Bidi properties of a paragraph by SetPara(). - */ - explicit nsBidi(); - - /** @brief Destructor. */ - virtual ~nsBidi(); - - - /** - * Perform the Unicode Bidi algorithm. - * - * @param aText is a pointer to the single-paragraph text that the - * Bidi algorithm will be performed on - * (step (P1) of the algorithm is performed externally). - * The text must be (at least) aLength long. - * - * @param aLength is the length of the text; if aLength==-1 then - * the text must be zero-terminated. - * - * @param aParaLevel specifies the default level for the paragraph; - * it is typically 0 (LTR) or 1 (RTL). - * If the function shall determine the paragraph level from the text, - * then aParaLevel can be set to - * either NSBIDI_DEFAULT_LTR - * or NSBIDI_DEFAULT_RTL; - * if there is no strongly typed character, then - * the desired default is used (0 for LTR or 1 for RTL). - * Any other value between 0 and NSBIDI_MAX_EXPLICIT_LEVEL - * is also valid, with odd levels indicating RTL. - */ - nsresult SetPara(const char16_t *aText, int32_t aLength, - nsBidiLevel aParaLevel); - - /** - * Get the directionality of the text. - * - * @param aDirection receives a NSBIDI_XXX value that indicates - * if the entire text represented by this object is unidirectional, - * and which direction, or if it is mixed-directional. - * - * @see nsBidiDirection - */ - nsresult GetDirection(nsBidiDirection* aDirection); - - /** - * Get the paragraph level of the text. - * - * @param aParaLevel receives a NSBIDI_XXX value indicating - * the paragraph level - * - * @see nsBidiLevel - */ - nsresult GetParaLevel(nsBidiLevel* aParaLevel); - - /** - * Get a logical run. - * This function returns information about a run and is used - * to retrieve runs in logical order.

- * This is especially useful for line-breaking on a paragraph. - * - * @param aLogicalStart is the first character of the run. - * - * @param aLogicalLimit will receive the limit of the run. - * The l-value that you point to here may be the - * same expression (variable) as the one for - * aLogicalStart. - * This pointer can be nullptr if this - * value is not necessary. - * - * @param aLevel will receive the level of the run. - * This pointer can be nullptr if this - * value is not necessary. - */ - nsresult GetLogicalRun(int32_t aLogicalStart, int32_t* aLogicalLimit, - nsBidiLevel* aLevel); - - /** - * Get the number of runs. - * This function may invoke the actual reordering on the - * nsBidi object, after SetPara - * may have resolved only the levels of the text. Therefore, - * CountRuns may have to allocate memory, - * and may fail doing so. - * - * @param aRunCount will receive the number of runs. - */ - nsresult CountRuns(int32_t* aRunCount); - - /** - * Get one run's logical start, length, and directionality, - * which can be 0 for LTR or 1 for RTL. - * In an RTL run, the character at the logical start is - * visually on the right of the displayed run. - * The length is the number of characters in the run.

- * CountRuns should be called - * before the runs are retrieved. - * - * @param aRunIndex is the number of the run in visual order, in the - * range [0..CountRuns-1]. - * - * @param aLogicalStart is the first logical character index in the text. - * The pointer may be nullptr if this index is not needed. - * - * @param aLength is the number of characters (at least one) in the run. - * The pointer may be nullptr if this is not needed. - * - * @param aDirection will receive the directionality of the run, - * NSBIDI_LTR==0 or NSBIDI_RTL==1, - * never NSBIDI_MIXED. - * - * @see CountRuns

- * - * Example: - * @code - * int32_t i, count, logicalStart, visualIndex=0, length; - * nsBidiDirection dir; - * pBidi->CountRuns(&count); - * for(i=0; iGetVisualRun(i, &logicalStart, &length, &dir); - * if(NSBIDI_LTR==dir) { - * do { // LTR - * show_char(text[logicalStart++], visualIndex++); - * } while(--length>0); - * } else { - * logicalStart+=length; // logicalLimit - * do { // RTL - * show_char(text[--logicalStart], visualIndex++); - * } while(--length>0); - * } - * } - * @endcode - * - * Note that in right-to-left runs, code like this places - * modifier letters before base characters and second surrogates - * before first ones. - */ - nsresult GetVisualRun(int32_t aRunIndex, int32_t* aLogicalStart, - int32_t* aLength, nsBidiDirection* aDirection); - - /** - * This is a convenience function that does not use a nsBidi object. - * It is intended to be used for when an application has determined the levels - * of objects (character sequences) and just needs to have them reordered (L2). - * This is equivalent to using GetVisualMap on a - * nsBidi object. - * - * @param aLevels is an array with aLength levels that have been - * determined by the application. - * - * @param aLength is the number of levels in the array, or, semantically, - * the number of objects to be reordered. - * It must be aLength>0. - * - * @param aIndexMap is a pointer to an array of aLength - * indexes which will reflect the reordering of the characters. - * The array does not need to be initialized.

- * The index map will result in - * aIndexMap[aVisualIndex]==aLogicalIndex. - */ - static nsresult ReorderVisual(const nsBidiLevel* aLevels, int32_t aLength, - int32_t* aIndexMap); - -private: - nsBidi(const nsBidi&) = delete; - void operator=(const nsBidi&) = delete; - -protected: - UBiDi* mBiDi; -}; - -#endif // _nsBidi_ICU_h_ diff --git a/layout/base/nsBidi_noICU.cpp b/layout/base/nsBidi_noICU.cpp deleted file mode 100644 index 0b9c58e55e6c..000000000000 --- a/layout/base/nsBidi_noICU.cpp +++ /dev/null @@ -1,2089 +0,0 @@ -/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsBidi.h" -#include "nsUnicodeProperties.h" -#include "nsCRTGlue.h" - -using namespace mozilla::unicode; - -static_assert(mozilla::kBidiLevelNone > NSBIDI_MAX_EXPLICIT_LEVEL + 1, - "The pseudo embedding level should be out-of-range"); - -// These are #defined in under Solaris 10 x86 -#undef CS -#undef ES - -/* Comparing the description of the Bidi algorithm with this implementation - is easier with the same names for the Bidi types in the code as there. -*/ -enum { - L = eCharType_LeftToRight, - R = eCharType_RightToLeft, - EN = eCharType_EuropeanNumber, - ES = eCharType_EuropeanNumberSeparator, - ET = eCharType_EuropeanNumberTerminator, - AN = eCharType_ArabicNumber, - CS = eCharType_CommonNumberSeparator, - B = eCharType_BlockSeparator, - S = eCharType_SegmentSeparator, - WS = eCharType_WhiteSpaceNeutral, - O_N = eCharType_OtherNeutral, - LRE = eCharType_LeftToRightEmbedding, - LRO = eCharType_LeftToRightOverride, - AL = eCharType_RightToLeftArabic, - RLE = eCharType_RightToLeftEmbedding, - RLO = eCharType_RightToLeftOverride, - PDF = eCharType_PopDirectionalFormat, - NSM = eCharType_DirNonSpacingMark, - BN = eCharType_BoundaryNeutral, - LRI = eCharType_LeftToRightIsolate, - RLI = eCharType_RightToLeftIsolate, - FSI = eCharType_FirstStrongIsolate, - PDI = eCharType_PopDirectionalIsolate, - ENL, /* EN after W7 */ /* 23 */ - ENR, /* EN not subject to W7 */ /* 24 */ - dirPropCount -}; - -#define IS_STRONG_TYPE(dirProp) ((dirProp) <= R || (dirProp) == AL) - -/* to avoid some conditional statements, use tiny constant arrays */ -static Flags flagLR[2]={ DIRPROP_FLAG(L), DIRPROP_FLAG(R) }; -static Flags flagE[2]={ DIRPROP_FLAG(LRE), DIRPROP_FLAG(RLE) }; -static Flags flagO[2]={ DIRPROP_FLAG(LRO), DIRPROP_FLAG(RLO) }; - -#define DIRPROP_FLAG_LR(level) flagLR[(level)&1] -#define DIRPROP_FLAG_E(level) flagE[(level)&1] -#define DIRPROP_FLAG_O(level) flagO[(level)&1] - -#define NO_OVERRIDE(level) ((level)&~NSBIDI_LEVEL_OVERRIDE) - -static inline uint8_t -DirFromStrong(uint8_t aDirProp) -{ - MOZ_ASSERT(IS_STRONG_TYPE(aDirProp)); - return aDirProp == L ? L : R; -} - -/* - * General implementation notes: - * - * Throughout the implementation, there are comments like (W2) that refer to - * rules of the Bidi algorithm in its version 5, in this example to the second - * rule of the resolution of weak types. - * - * For handling surrogate pairs, where two UChar's form one "abstract" (or UTF-32) - * character according to UTF-16, the second UChar gets the directional property of - * the entire character assigned, while the first one gets a BN, a boundary - * neutral, type, which is ignored by most of the algorithm according to - * rule (X9) and the implementation suggestions of the Bidi algorithm. - * - * Later, AdjustWSLevels() will set the level for each BN to that of the - * following character (UChar), which results in surrogate pairs getting the - * same level on each of their surrogates. - * - * In a UTF-8 implementation, the same thing could be done: the last byte of - * a multi-byte sequence would get the "real" property, while all previous - * bytes of that sequence would get BN. - * - * It is not possible to assign all those parts of a character the same real - * property because this would fail in the resolution of weak types with rules - * that look at immediately surrounding types. - * - * As a related topic, this implementation does not remove Boundary Neutral - * types from the input, but ignores them whenever this is relevant. - * For example, the loop for the resolution of the weak types reads - * types until it finds a non-BN. - * Also, explicit embedding codes are neither changed into BN nor removed. - * They are only treated the same way real BNs are. - * As stated before, AdjustWSLevels() takes care of them at the end. - * For the purpose of conformance, the levels of all these codes - * do not matter. - * - * Note that this implementation never modifies the dirProps - * after the initial setup, except for FSI which is changed to either - * LRI or RLI in GetDirProps(), and paired brackets which may be changed - * to L or R according to N0. - * - * - * In this implementation, the resolution of weak types (Wn), - * neutrals (Nn), and the assignment of the resolved level (In) - * are all done in one single loop, in ResolveImplicitLevels(). - * Changes of dirProp values are done on the fly, without writing - * them back to the dirProps array. - * - * - * This implementation contains code that allows to bypass steps of the - * algorithm that are not needed on the specific paragraph - * in order to speed up the most common cases considerably, - * like text that is entirely LTR, or RTL text without numbers. - * - * Most of this is done by setting a bit for each directional property - * in a flags variable and later checking for whether there are - * any LTR characters or any RTL characters, or both, whether - * there are any explicit embedding codes, etc. - * - * If the (Xn) steps are performed, then the flags are re-evaluated, - * because they will then not contain the embedding codes any more - * and will be adjusted for override codes, so that subsequently - * more bypassing may be possible than what the initial flags suggested. - * - * If the text is not mixed-directional, then the - * algorithm steps for the weak type resolution are not performed, - * and all levels are set to the paragraph level. - * - * If there are no explicit embedding codes, then the (Xn) steps - * are not performed. - * - * If embedding levels are supplied as a parameter, then all - * explicit embedding codes are ignored, and the (Xn) steps - * are not performed. - * - * White Space types could get the level of the run they belong to, - * and are checked with a test of (flags&MASK_EMBEDDING) to - * consider if the paragraph direction should be considered in - * the flags variable. - * - * If there are no White Space types in the paragraph, then - * (L1) is not necessary in AdjustWSLevels(). - */ -nsBidi::nsBidi() -{ - Init(); -} - -nsBidi::~nsBidi() -{ - Free(); -} - -void nsBidi::Init() -{ - /* reset the object, all pointers nullptr, all flags false, all sizes 0 */ - mLength = 0; - mParaLevel = 0; - mFlags = 0; - mDirection = NSBIDI_LTR; - mTrailingWSStart = 0; - - mDirPropsSize = 0; - mLevelsSize = 0; - mRunsSize = 0; - mIsolatesSize = 0; - - mRunCount = -1; - mIsolateCount = -1; - - mDirProps=nullptr; - mLevels=nullptr; - mRuns=nullptr; - mIsolates=nullptr; - - mDirPropsMemory=nullptr; - mLevelsMemory=nullptr; - mRunsMemory=nullptr; - mIsolatesMemory=nullptr; -} - -/* - * We are allowed to allocate memory if aMemory==nullptr - * for each array that we need. - * We also try to grow and shrink memory as needed if we - * allocate it. - * - * Assume aSizeNeeded>0. - * If *aMemory!=nullptr, then assume *aSize>0. - * - * ### this realloc() may unnecessarily copy the old data, - * which we know we don't need any more; - * is this the best way to do this?? - */ -/*static*/ -bool -nsBidi::GetMemory(void **aMemory, size_t *aSize, size_t aSizeNeeded) -{ - /* check for existing memory */ - if(*aMemory==nullptr) { - /* we need to allocate memory */ - *aMemory=malloc(aSizeNeeded); - if (*aMemory!=nullptr) { - *aSize=aSizeNeeded; - return true; - } else { - *aSize=0; - return false; - } - } else { - /* there is some memory, is it enough or too much? */ - if(aSizeNeeded!=*aSize) { - /* we may try to grow or shrink */ - void *memory=realloc(*aMemory, aSizeNeeded); - - if(memory!=nullptr) { - *aMemory=memory; - *aSize=aSizeNeeded; - return true; - } else { - /* we failed to grow */ - return false; - } - } else { - /* we have at least enough memory and must not allocate */ - return true; - } - } -} - -void nsBidi::Free() -{ - free(mDirPropsMemory); - mDirPropsMemory = nullptr; - free(mLevelsMemory); - mLevelsMemory = nullptr; - free(mRunsMemory); - mRunsMemory = nullptr; - free(mIsolatesMemory); - mIsolatesMemory = nullptr; -} - -/* SetPara ------------------------------------------------------------ */ - -nsresult nsBidi::SetPara(const char16_t *aText, int32_t aLength, - nsBidiLevel aParaLevel) -{ - nsBidiDirection direction; - - /* check the argument values */ - if(aText==nullptr || - ((NSBIDI_MAX_EXPLICIT_LEVEL= 0) { - if (stackLast <= NSBIDI_MAX_EXPLICIT_LEVEL) { - state = previousStateStack[stackLast]; - } - stackLast--; - } - break; - - case B: - // This shouldn't happen, since we don't support multiple paragraphs. - NS_NOTREACHED("Unexpected paragraph separator"); - break; - - default: - break; - } - } - - /* Ignore still open isolate sequences with overflow */ - if (stackLast > NSBIDI_MAX_EXPLICIT_LEVEL) { - stackLast = NSBIDI_MAX_EXPLICIT_LEVEL; - if (dirProps[previousStateStack[NSBIDI_MAX_EXPLICIT_LEVEL]] != FSI) { - state = LOOKING_FOR_PDI; - } - } - - /* Resolve direction of still unresolved open FSI sequences */ - while (stackLast >= 0) { - if (state == SEEKING_STRONG_FOR_FSI) { - dirProps[isolateStartStack[stackLast]] = LRI; - flags |= DIRPROP_FLAG(LRI); - } - state = previousStateStack[stackLast]; - stackLast--; - } - - flags|=DIRPROP_FLAG_LR(mParaLevel); - - mFlags = flags; -} - -/* Functions for handling paired brackets ----------------------------------- */ - -/* In the mIsoRuns array, the first entry is used for text outside of any - isolate sequence. Higher entries are used for each more deeply nested - isolate sequence. - mIsoRunLast is the index of the last used entry. - The mOpenings array is used to note the data of opening brackets not yet - matched by a closing bracket, or matched but still susceptible to change - level. - Each isoRun entry contains the index of the first and - one-after-last openings entries for pending opening brackets it - contains. The next mOpenings entry to use is the one-after-last of the - most deeply nested isoRun entry. - mIsoRuns entries also contain their current embedding level and the bidi - class of the last-encountered strong character, since these will be needed - to resolve the level of paired brackets. */ - -nsBidi::BracketData::BracketData(const nsBidi *aBidi) -{ - mIsoRunLast = 0; - mIsoRuns[0].start = 0; - mIsoRuns[0].limit = 0; - mIsoRuns[0].level = aBidi->mParaLevel; - mIsoRuns[0].lastStrong = mIsoRuns[0].lastBase = mIsoRuns[0].contextDir = - GET_LR_FROM_LEVEL(aBidi->mParaLevel); - mIsoRuns[0].contextPos = 0; - mOpenings = mSimpleOpenings; - mOpeningsCount = SIMPLE_OPENINGS_COUNT; - mOpeningsMemory = nullptr; -} - -nsBidi::BracketData::~BracketData() -{ - free(mOpeningsMemory); -} - -/* LRE, LRO, RLE, RLO, PDF */ -void -nsBidi::BracketData::ProcessBoundary(int32_t aLastDirControlCharPos, - nsBidiLevel aContextLevel, - nsBidiLevel aEmbeddingLevel, - const DirProp* aDirProps) -{ - IsoRun& lastIsoRun = mIsoRuns[mIsoRunLast]; - if (DIRPROP_FLAG(aDirProps[aLastDirControlCharPos]) & MASK_ISO) { /* after an isolate */ - return; - } - if (NO_OVERRIDE(aEmbeddingLevel) > NO_OVERRIDE(aContextLevel)) { /* not PDF */ - aContextLevel = aEmbeddingLevel; - } - lastIsoRun.limit = lastIsoRun.start; - lastIsoRun.level = aEmbeddingLevel; - lastIsoRun.lastStrong = lastIsoRun.lastBase = lastIsoRun.contextDir = - GET_LR_FROM_LEVEL(aContextLevel); - lastIsoRun.contextPos = aLastDirControlCharPos; -} - -/* LRI or RLI */ -void -nsBidi::BracketData::ProcessLRI_RLI(nsBidiLevel aLevel) -{ - MOZ_ASSERT(mIsoRunLast <= NSBIDI_MAX_EXPLICIT_LEVEL); - IsoRun& lastIsoRun = mIsoRuns[mIsoRunLast]; - lastIsoRun.lastBase = O_N; - IsoRun& currIsoRun = mIsoRuns[++mIsoRunLast]; - currIsoRun.start = currIsoRun.limit = lastIsoRun.limit; - currIsoRun.level = aLevel; - currIsoRun.lastStrong = currIsoRun.lastBase = currIsoRun.contextDir = - GET_LR_FROM_LEVEL(aLevel); - currIsoRun.contextPos = 0; -} - -/* PDI */ -void -nsBidi::BracketData::ProcessPDI() -{ - MOZ_ASSERT(mIsoRunLast > 0); - mIsoRuns[--mIsoRunLast].lastBase = O_N; -} - -/* newly found opening bracket: create an openings entry */ -bool /* return true if success */ -nsBidi::BracketData::AddOpening(char16_t aMatch, int32_t aPosition) -{ - IsoRun& lastIsoRun = mIsoRuns[mIsoRunLast]; - if (lastIsoRun.limit >= mOpeningsCount) { /* no available new entry */ - if (!GETOPENINGSMEMORY(lastIsoRun.limit * 2)) { - return false; - } - if (mOpenings == mSimpleOpenings) { - memcpy(mOpeningsMemory, mSimpleOpenings, - SIMPLE_OPENINGS_COUNT * sizeof(Opening)); - } - mOpenings = mOpeningsMemory; /* may have changed */ - mOpeningsCount = mOpeningsSize / sizeof(Opening); - } - Opening& o = mOpenings[lastIsoRun.limit]; - o.position = aPosition; - o.match = aMatch; - o.contextDir = lastIsoRun.contextDir; - o.contextPos = lastIsoRun.contextPos; - o.flags = 0; - lastIsoRun.limit++; - return true; -} - -/* change N0c1 to N0c2 when a preceding bracket is assigned the embedding level */ -void -nsBidi::BracketData::FixN0c(int32_t aOpeningIndex, int32_t aNewPropPosition, - DirProp aNewProp, DirProp* aDirProps) -{ - /* This function calls itself recursively */ - IsoRun& lastIsoRun = mIsoRuns[mIsoRunLast]; - for (int32_t k = aOpeningIndex + 1; k < lastIsoRun.limit; k++) { - Opening& o = mOpenings[k]; - if (o.match >= 0) { /* not an N0c match */ - continue; - } - if (aNewPropPosition < o.contextPos) { - break; - } - int32_t openingPosition = o.position; - if (aNewPropPosition >= openingPosition) { - continue; - } - if (aNewProp == o.contextDir) { - break; - } - aDirProps[openingPosition] = aNewProp; - int32_t closingPosition = -(o.match); - aDirProps[closingPosition] = aNewProp; - o.match = 0; /* prevent further changes */ - FixN0c(k, openingPosition, aNewProp, aDirProps); - FixN0c(k, closingPosition, aNewProp, aDirProps); - } -} - -/* process closing bracket */ -DirProp /* return L or R if N0b or N0c, ON if N0d */ -nsBidi::BracketData::ProcessClosing(int32_t aOpenIdx, int32_t aPosition, - DirProp* aDirProps) -{ - IsoRun& lastIsoRun = mIsoRuns[mIsoRunLast]; - Opening& o = mOpenings[aOpenIdx]; - DirProp newProp; - DirProp direction = GET_LR_FROM_LEVEL(lastIsoRun.level); - bool stable = true; // assume stable until proved otherwise - - /* The stable flag is set when brackets are paired and their - level is resolved and cannot be changed by what will be - found later in the source string. - An unstable match can occur only when applying N0c, where - the resolved level depends on the preceding context, and - this context may be affected by text occurring later. - Example: RTL paragraph containing: abc[(latin) HEBREW] - When the closing parenthesis is encountered, it appears - that N0c1 must be applied since 'abc' sets an opposite - direction context and both parentheses receive level 2. - However, when the closing square bracket is processed, - N0b applies because of 'HEBREW' being included within the - brackets, thus the square brackets are treated like R and - receive level 1. However, this changes the preceding - context of the opening parenthesis, and it now appears - that N0c2 must be applied to the parentheses rather than - N0c1. */ - - if ((direction == 0 && o.flags & FOUND_L) || - (direction == 1 && o.flags & FOUND_R)) { /* N0b */ - newProp = direction; - } else if (o.flags & (FOUND_L|FOUND_R)) { /* N0c */ - /* it is stable if there is no containing pair or in - conditions too complicated and not worth checking */ - stable = (aOpenIdx == lastIsoRun.start); - if (direction != o.contextDir) { - newProp = o.contextDir; /* N0c1 */ - } else { - newProp = direction; /* N0c2 */ - } - } else { - /* forget this and any brackets nested within this pair */ - lastIsoRun.limit = aOpenIdx; - return O_N; /* N0d */ - } - aDirProps[o.position] = newProp; - aDirProps[aPosition] = newProp; - /* Update nested N0c pairs that may be affected */ - FixN0c(aOpenIdx, o.position, newProp, aDirProps); - if (stable) { - /* forget any brackets nested within this pair */ - lastIsoRun.limit = aOpenIdx; - } else { - int32_t k; - o.match = -aPosition; - /* neutralize any unmatched opening between the current pair */ - for (k = aOpenIdx + 1; k < lastIsoRun.limit; k++) { - Opening& oo = mOpenings[k]; - if (oo.position > aPosition) { - break; - } - if (oo.match > 0) { - oo.match = 0; - } - } - } - return newProp; -} - -static inline bool -IsMatchingCloseBracket(char16_t aCh1, char16_t aCh2) -{ - // U+232A RIGHT-POINTING ANGLE BRACKET and U+3009 RIGHT ANGLE BRACKET - // are canonical equivalents, so we special-case them here. - return (aCh1 == aCh2) || - (aCh1 == 0x232A && aCh2 == 0x3009) || - (aCh2 == 0x232A && aCh1 == 0x3009); -} - -/* Handle strong characters, digits and candidates for closing brackets. */ -/* Returns true if success. (The only failure mode is an OOM when trying - to allocate memory for the Openings array.) */ -bool -nsBidi::BracketData::ProcessChar(int32_t aPosition, char16_t aCh, - DirProp* aDirProps, nsBidiLevel* aLevels) -{ - IsoRun& lastIsoRun = mIsoRuns[mIsoRunLast]; - DirProp newProp; - DirProp dirProp = aDirProps[aPosition]; - nsBidiLevel level = aLevels[aPosition]; - if (dirProp == O_N) { - /* First see if it is a matching closing bracket. Hopefully, this is - more efficient than checking if it is a closing bracket at all */ - for (int32_t idx = lastIsoRun.limit - 1; idx >= lastIsoRun.start; idx--) { - if (!IsMatchingCloseBracket(aCh, mOpenings[idx].match)) { - continue; - } - /* We have a match */ - newProp = ProcessClosing(idx, aPosition, aDirProps); - if (newProp == O_N) { /* N0d */ - aCh = 0; /* prevent handling as an opening */ - break; - } - lastIsoRun.lastBase = O_N; - lastIsoRun.contextDir = newProp; - lastIsoRun.contextPos = aPosition; - if (level & NSBIDI_LEVEL_OVERRIDE) { /* X4, X5 */ - newProp = GET_LR_FROM_LEVEL(level); - lastIsoRun.lastStrong = newProp; - uint16_t flag = DIRPROP_FLAG(newProp); - for (int32_t i = lastIsoRun.start; i < idx; i++) { - mOpenings[i].flags |= flag; - } - /* matching brackets are not overridden by LRO/RLO */ - aLevels[aPosition] &= ~NSBIDI_LEVEL_OVERRIDE; - } - /* matching brackets are not overridden by LRO/RLO */ - aLevels[mOpenings[idx].position] &= ~NSBIDI_LEVEL_OVERRIDE; - return true; - } - /* We get here only if the ON character is not a matching closing - bracket or it is a case of N0d */ - /* Now see if it is an opening bracket */ - char16_t match = GetPairedBracket(aCh); - if (match != aCh && /* has a matching char */ - GetPairedBracketType(aCh) == PAIRED_BRACKET_TYPE_OPEN) { /* opening bracket */ - if (!AddOpening(match, aPosition)) { - return false; - } - } - } - if (level & NSBIDI_LEVEL_OVERRIDE) { /* X4, X5 */ - newProp = GET_LR_FROM_LEVEL(level); - if (dirProp != S && dirProp != WS && dirProp != O_N) { - aDirProps[aPosition] = newProp; - } - lastIsoRun.lastBase = newProp; - lastIsoRun.lastStrong = newProp; - lastIsoRun.contextDir = newProp; - lastIsoRun.contextPos = aPosition; - } else if (IS_STRONG_TYPE(dirProp)) { - newProp = DirFromStrong(dirProp); - lastIsoRun.lastBase = dirProp; - lastIsoRun.lastStrong = dirProp; - lastIsoRun.contextDir = newProp; - lastIsoRun.contextPos = aPosition; - } else if (dirProp == EN) { - lastIsoRun.lastBase = EN; - if (lastIsoRun.lastStrong == L) { - newProp = L; /* W7 */ - aDirProps[aPosition] = ENL; - lastIsoRun.contextDir = L; - lastIsoRun.contextPos = aPosition; - } else { - newProp = R; /* N0 */ - if (lastIsoRun.lastStrong == AL) { - aDirProps[aPosition] = AN; /* W2 */ - } else { - aDirProps[aPosition] = ENR; - } - lastIsoRun.contextDir = R; - lastIsoRun.contextPos = aPosition; - } - } else if (dirProp == AN) { - newProp = R; /* N0 */ - lastIsoRun.lastBase = AN; - lastIsoRun.contextDir = R; - lastIsoRun.contextPos = aPosition; - } else if (dirProp == NSM) { - /* if the last real char was ON, change NSM to ON so that it - will stay ON even if the last real char is a bracket which - may be changed to L or R */ - newProp = lastIsoRun.lastBase; - if (newProp == O_N) { - aDirProps[aPosition] = newProp; - } - } else { - newProp = dirProp; - lastIsoRun.lastBase = dirProp; - } - if (IS_STRONG_TYPE(newProp)) { - uint16_t flag = DIRPROP_FLAG(DirFromStrong(newProp)); - for (int32_t i = lastIsoRun.start; i < lastIsoRun.limit; i++) { - if (aPosition > mOpenings[i].position) { - mOpenings[i].flags |= flag; - } - } - } - return true; -} - -/* perform (X1)..(X9) ------------------------------------------------------- */ - -/* - * Resolve the explicit levels as specified by explicit embedding codes. - * Recalculate the flags to have them reflect the real properties - * after taking the explicit embeddings into account. - * - * The Bidi algorithm is designed to result in the same behavior whether embedding - * levels are externally specified (from "styled text", supposedly the preferred - * method) or set by explicit embedding codes (LRx, RLx, PDF, FSI, PDI) in the plain text. - * That is why (X9) instructs to remove all not-isolate explicit codes (and BN). - * However, in a real implementation, this removal of these codes and their index - * positions in the plain text is undesirable since it would result in - * reallocated, reindexed text. - * Instead, this implementation leaves the codes in there and just ignores them - * in the subsequent processing. - * In order to get the same reordering behavior, positions with a BN or a not-isolate - * explicit embedding code just get the same level assigned as the last "real" - * character. - * - * Some implementations, not this one, then overwrite some of these - * directionality properties at "real" same-level-run boundaries by - * L or R codes so that the resolution of weak types can be performed on the - * entire paragraph at once instead of having to parse it once more and - * perform that resolution on same-level-runs. - * This limits the scope of the implicit rules in effectively - * the same way as the run limits. - * - * Instead, this implementation does not modify these codes. - * On one hand, the paragraph has to be scanned for same-level-runs, but - * on the other hand, this saves another loop to reset these codes, - * or saves making and modifying a copy of dirProps[]. - * - * - * Note that (Pn) and (Xn) changed significantly from version 4 of the Bidi algorithm. - * - * - * Handling the stack of explicit levels (Xn): - * - * With the Bidi stack of explicit levels, as pushed with each - * LRE, RLE, LRO, and RLO, LRI, RLI, and FSI and popped with each PDF and PDI, - * the explicit level must never exceed NSBIDI_MAX_EXPLICIT_LEVEL. - * - * In order to have a correct push-pop semantics even in the case of overflows, - * overflow counters and a valid isolate counter are used as described in UAX#9 - * section 3.3.2 "Explicit Levels and Direction". - * - * This implementation assumes that NSBIDI_MAX_EXPLICIT_LEVEL is odd. - */ - -void nsBidi::ResolveExplicitLevels(nsBidiDirection *aDirection, const char16_t *aText) -{ - DirProp *dirProps=mDirProps; - nsBidiLevel *levels=mLevels; - - int32_t i=0, length=mLength; - Flags flags=mFlags; /* collect all directionalities in the text */ - DirProp dirProp; - nsBidiLevel level=mParaLevel; - nsBidiDirection direction; - - mIsolateCount = 0; - - /* determine if the text is mixed-directional or single-directional */ - direction=DirectionFromFlags(flags); - - /* we may not need to resolve any explicit levels */ - if(direction!=NSBIDI_MIXED) { - /* not mixed directionality: levels don't matter - trailingWSStart will be 0 */ - } else if(!(flags&(MASK_EXPLICIT|MASK_ISO))) { - BracketData bracketData(this); - /* no embeddings, set all levels to the paragraph level */ - for(i=0; i=NSBIDI_MAX_EXPLICIT_LEVEL - but we need one more entry as base */ - int32_t stackLast = 0; - int32_t overflowIsolateCount = 0; - int32_t overflowEmbeddingCount = 0; - int32_t validIsolateCount = 0; - - BracketData bracketData(this); - - stack[0] = level; - - /* recalculate the flags */ - flags=0; - - /* since we assume that this is a single paragraph, we ignore (X8) */ - for(i=0; i 0 && stack[stackLast] < ISOLATE) { /* not an isolate entry */ - lastDirControlCharPos = i; - stackLast--; - embeddingLevel = stack[stackLast]; - } - break; - - case LRI: - case RLI: - flags |= DIRPROP_FLAG(O_N) | DIRPROP_FLAG_LR(embeddingLevel); - levels[i] = NO_OVERRIDE(embeddingLevel); - if (NO_OVERRIDE(embeddingLevel) != NO_OVERRIDE(previousLevel)) { - bracketData.ProcessBoundary(lastDirControlCharPos, previousLevel, - embeddingLevel, mDirProps); - flags |= DIRPROP_FLAG_MULTI_RUNS; - } - previousLevel = embeddingLevel; - /* (X5a, X5b) */ - if (dirProp == LRI) { - newLevel = (embeddingLevel + 2) & ~(NSBIDI_LEVEL_OVERRIDE | 1); /* least greater even level */ - } else { - newLevel = ((embeddingLevel & ~NSBIDI_LEVEL_OVERRIDE) + 1) | 1; /* least greater odd level */ - } - if (newLevel <= NSBIDI_MAX_EXPLICIT_LEVEL && overflowIsolateCount == 0 && overflowEmbeddingCount == 0) { - flags |= DIRPROP_FLAG(dirProp); - lastDirControlCharPos = i; - previousLevel = embeddingLevel; - validIsolateCount++; - if (validIsolateCount > mIsolateCount) { - mIsolateCount = validIsolateCount; - } - embeddingLevel = newLevel; - stackLast++; - stack[stackLast] = embeddingLevel + ISOLATE; - bracketData.ProcessLRI_RLI(embeddingLevel); - } else { - /* make it so that it is handled by AdjustWSLevels() */ - dirProps[i] = WS; - overflowIsolateCount++; - } - break; - - case PDI: - if (NO_OVERRIDE(embeddingLevel) != NO_OVERRIDE(previousLevel)) { - bracketData.ProcessBoundary(lastDirControlCharPos, previousLevel, - embeddingLevel, mDirProps); - flags |= DIRPROP_FLAG_MULTI_RUNS; - } - /* (X6a) */ - if (overflowIsolateCount) { - overflowIsolateCount--; - /* make it so that it is handled by AdjustWSLevels() */ - dirProps[i] = WS; - } else if (validIsolateCount) { - flags |= DIRPROP_FLAG(PDI); - lastDirControlCharPos = i; - overflowEmbeddingCount = 0; - while (stack[stackLast] < ISOLATE) { - /* pop embedding entries */ - /* until the last isolate entry */ - stackLast--; - - // Since validIsolateCount is true, there must be an isolate entry - // on the stack, so the stack is guaranteed to not be empty. - // Still, to eliminate a warning from coverity, we use an assertion. - MOZ_ASSERT(stackLast > 0); - } - stackLast--; /* pop also the last isolate entry */ - MOZ_ASSERT(stackLast >= 0); // For coverity - validIsolateCount--; - bracketData.ProcessPDI(); - } else { - /* make it so that it is handled by AdjustWSLevels() */ - dirProps[i] = WS; - } - embeddingLevel = stack[stackLast] & ~ISOLATE; - flags |= DIRPROP_FLAG(O_N) | DIRPROP_FLAG_LR(embeddingLevel); - previousLevel = embeddingLevel; - levels[i] = NO_OVERRIDE(embeddingLevel); - break; - - case B: - /* - * We do not expect to see a paragraph separator (B), - */ - NS_NOTREACHED("Unexpected paragraph separator"); - break; - - case BN: - /* BN, LRE, RLE, and PDF are supposed to be removed (X9) */ - /* they will get their levels set correctly in AdjustWSLevels() */ - levels[i] = previousLevel; - flags |= DIRPROP_FLAG(BN); - break; - - default: - /* all other types get the "real" level */ - if (NO_OVERRIDE(embeddingLevel) != NO_OVERRIDE(previousLevel)) { - bracketData.ProcessBoundary(lastDirControlCharPos, previousLevel, - embeddingLevel, mDirProps); - flags |= DIRPROP_FLAG_MULTI_RUNS; - if (embeddingLevel & NSBIDI_LEVEL_OVERRIDE) { - flags |= DIRPROP_FLAG_O(embeddingLevel); - } else { - flags |= DIRPROP_FLAG_E(embeddingLevel); - } - } - previousLevel = embeddingLevel; - levels[i] = embeddingLevel; - if (!bracketData.ProcessChar(i, aText[i], mDirProps, mLevels)) { - NS_WARNING("BracketData::ProcessChar failed, out of memory?"); - *aDirection = NSBIDI_LTR; - return; - } - flags |= DIRPROP_FLAG(dirProps[i]); - break; - } - } - - if(flags&MASK_EMBEDDING) { - flags|=DIRPROP_FLAG_LR(mParaLevel); - } - - /* subsequently, ignore the explicit codes and BN (X9) */ - - /* again, determine if the text is mixed-directional or single-directional */ - mFlags=flags; - direction=DirectionFromFlags(flags); - } - - *aDirection = direction; -} - -/* determine if the text is mixed-directional or single-directional */ -nsBidiDirection nsBidi::DirectionFromFlags(Flags aFlags) -{ - /* if the text contains AN and neutrals, then some neutrals may become RTL */ - if(!(aFlags&MASK_RTL || (aFlags&DIRPROP_FLAG(AN) && aFlags&MASK_POSSIBLE_N))) { - return NSBIDI_LTR; - } else if(!(aFlags&MASK_LTR)) { - return NSBIDI_RTL; - } else { - return NSBIDI_MIXED; - } -} - -/****************************************************************** - The Properties state machine table -******************************************************************* - - All table cells are 8 bits: - bits 0..4: next state - bits 5..7: action to perform (if > 0) - - Cells may be of format "n" where n represents the next state - (except for the rightmost column). - Cells may also be of format "s(x,y)" where x represents an action - to perform and y represents the next state. - -******************************************************************* - Definitions and type for properties state table -******************************************************************* -*/ -#define IMPTABPROPS_COLUMNS 16 -#define IMPTABPROPS_RES (IMPTABPROPS_COLUMNS - 1) -#define GET_STATEPROPS(cell) ((cell)&0x1f) -#define GET_ACTIONPROPS(cell) ((cell)>>5) -#undef s -#define s(action, newState) ((uint8_t)(newState+(action<<5))) - -static const uint8_t groupProp[] = /* dirProp regrouped */ -{ -/* L R EN ES ET AN CS B S WS ON LRE LRO AL RLE RLO PDF NSM BN FSI LRI RLI PDI ENL ENR */ - 0, 1, 2, 7, 8, 3, 9, 6, 5, 4, 4, 10, 10, 12, 10, 10, 10, 11, 10, 4, 4, 4, 4, 13, 14 -}; - -/****************************************************************** - - PROPERTIES STATE TABLE - - In table impTabProps, - - the ON column regroups ON and WS, FSI, RLI, LRI and PDI - - the BN column regroups BN, LRE, RLE, LRO, RLO, PDF - - the Res column is the reduced property assigned to a run - - Action 1: process current run1, init new run1 - 2: init new run2 - 3: process run1, process run2, init new run1 - 4: process run1, set run1=run2, init new run2 - - Notes: - 1) This table is used in ResolveImplicitLevels(). - 2) This table triggers actions when there is a change in the Bidi - property of incoming characters (action 1). - 3) Most such property sequences are processed immediately (in - fact, passed to ProcessPropertySeq(). - 4) However, numbers are assembled as one sequence. This means - that undefined situations (like CS following digits, until - it is known if the next char will be a digit) are held until - following chars define them. - Example: digits followed by CS, then comes another CS or ON; - the digits will be processed, then the CS assigned - as the start of an ON sequence (action 3). - 5) There are cases where more than one sequence must be - processed, for instance digits followed by CS followed by L: - the digits must be processed as one sequence, and the CS - must be processed as an ON sequence, all this before starting - assembling chars for the opening L sequence. - - -*/ -static const uint8_t impTabProps[][IMPTABPROPS_COLUMNS] = -{ -/* L , R , EN , AN , ON , S , B , ES , ET , CS , BN , NSM , AL , ENL , ENR , Res */ -/* 0 Init */ { 1 , 2 , 4 , 5 , 7 , 15 , 17 , 7 , 9 , 7 , 0 , 7 , 3 , 18 , 21 , DirProp_ON }, -/* 1 L */ { 1 , s(1,2), s(1,4), s(1,5), s(1,7),s(1,15),s(1,17), s(1,7), s(1,9), s(1,7), 1 , 1 , s(1,3),s(1,18),s(1,21), DirProp_L }, -/* 2 R */ { s(1,1), 2 , s(1,4), s(1,5), s(1,7),s(1,15),s(1,17), s(1,7), s(1,9), s(1,7), 2 , 2 , s(1,3),s(1,18),s(1,21), DirProp_R }, -/* 3 AL */ { s(1,1), s(1,2), s(1,6), s(1,6), s(1,8),s(1,16),s(1,17), s(1,8), s(1,8), s(1,8), 3 , 3 , 3 ,s(1,18),s(1,21), DirProp_R }, -/* 4 EN */ { s(1,1), s(1,2), 4 , s(1,5), s(1,7),s(1,15),s(1,17),s(2,10), 11 ,s(2,10), 4 , 4 , s(1,3), 18 , 21 , DirProp_EN }, -/* 5 AN */ { s(1,1), s(1,2), s(1,4), 5 , s(1,7),s(1,15),s(1,17), s(1,7), s(1,9),s(2,12), 5 , 5 , s(1,3),s(1,18),s(1,21), DirProp_AN }, -/* 6 AL:EN/AN */ { s(1,1), s(1,2), 6 , 6 , s(1,8),s(1,16),s(1,17), s(1,8), s(1,8),s(2,13), 6 , 6 , s(1,3), 18 , 21 , DirProp_AN }, -/* 7 ON */ { s(1,1), s(1,2), s(1,4), s(1,5), 7 ,s(1,15),s(1,17), 7 ,s(2,14), 7 , 7 , 7 , s(1,3),s(1,18),s(1,21), DirProp_ON }, -/* 8 AL:ON */ { s(1,1), s(1,2), s(1,6), s(1,6), 8 ,s(1,16),s(1,17), 8 , 8 , 8 , 8 , 8 , s(1,3),s(1,18),s(1,21), DirProp_ON }, -/* 9 ET */ { s(1,1), s(1,2), 4 , s(1,5), 7 ,s(1,15),s(1,17), 7 , 9 , 7 , 9 , 9 , s(1,3), 18 , 21 , DirProp_ON }, -/*10 EN+ES/CS */ { s(3,1), s(3,2), 4 , s(3,5), s(4,7),s(3,15),s(3,17), s(4,7),s(4,14), s(4,7), 10 , s(4,7), s(3,3), 18 , 21 , DirProp_EN }, -/*11 EN+ET */ { s(1,1), s(1,2), 4 , s(1,5), s(1,7),s(1,15),s(1,17), s(1,7), 11 , s(1,7), 11 , 11 , s(1,3), 18 , 21 , DirProp_EN }, -/*12 AN+CS */ { s(3,1), s(3,2), s(3,4), 5 , s(4,7),s(3,15),s(3,17), s(4,7),s(4,14), s(4,7), 12 , s(4,7), s(3,3),s(3,18),s(3,21), DirProp_AN }, -/*13 AL:EN/AN+CS */ { s(3,1), s(3,2), 6 , 6 , s(4,8),s(3,16),s(3,17), s(4,8), s(4,8), s(4,8), 13 , s(4,8), s(3,3), 18 , 21 , DirProp_AN }, -/*14 ON+ET */ { s(1,1), s(1,2), s(4,4), s(1,5), 7 ,s(1,15),s(1,17), 7 , 14 , 7 , 14 , 14 , s(1,3),s(4,18),s(4,21), DirProp_ON }, -/*15 S */ { s(1,1), s(1,2), s(1,4), s(1,5), s(1,7), 15 ,s(1,17), s(1,7), s(1,9), s(1,7), 15 , s(1,7), s(1,3),s(1,18),s(1,21), DirProp_S }, -/*16 AL:S */ { s(1,1), s(1,2), s(1,6), s(1,6), s(1,8), 16 ,s(1,17), s(1,8), s(1,8), s(1,8), 16 , s(1,8), s(1,3),s(1,18),s(1,21), DirProp_S }, -/*17 B */ { s(1,1), s(1,2), s(1,4), s(1,5), s(1,7),s(1,15), 17 , s(1,7), s(1,9), s(1,7), 17 , s(1,7), s(1,3),s(1,18),s(1,21), DirProp_B }, -/*18 ENL */ { s(1,1), s(1,2), 18 , s(1,5), s(1,7),s(1,15),s(1,17),s(2,19), 20 ,s(2,19), 18 , 18 , s(1,3), 18 , 21 , DirProp_L }, -/*19 ENL+ES/CS */ { s(3,1), s(3,2), 18 , s(3,5), s(4,7),s(3,15),s(3,17), s(4,7),s(4,14), s(4,7), 19 , s(4,7), s(3,3), 18 , 21 , DirProp_L }, -/*20 ENL+ET */ { s(1,1), s(1,2), 18 , s(1,5), s(1,7),s(1,15),s(1,17), s(1,7), 20 , s(1,7), 20 , 20 , s(1,3), 18 , 21 , DirProp_L }, -/*21 ENR */ { s(1,1), s(1,2), 21 , s(1,5), s(1,7),s(1,15),s(1,17),s(2,22), 23 ,s(2,22), 21 , 21 , s(1,3), 18 , 21 , DirProp_AN }, -/*22 ENR+ES/CS */ { s(3,1), s(3,2), 21 , s(3,5), s(4,7),s(3,15),s(3,17), s(4,7),s(4,14), s(4,7), 22 , s(4,7), s(3,3), 18 , 21 , DirProp_AN }, -/*23 ENR+ET */ { s(1,1), s(1,2), 21 , s(1,5), s(1,7),s(1,15),s(1,17), s(1,7), 23 , s(1,7), 23 , 23 , s(1,3), 18 , 21 , DirProp_AN } -}; - -/* we must undef macro s because the levels table have a different - * structure (4 bits for action and 4 bits for next state. - */ -#undef s - -/****************************************************************** - The levels state machine tables -******************************************************************* - - All table cells are 8 bits: - bits 0..3: next state - bits 4..7: action to perform (if > 0) - - Cells may be of format "n" where n represents the next state - (except for the rightmost column). - Cells may also be of format "s(x,y)" where x represents an action - to perform and y represents the next state. - - This format limits each table to 16 states each and to 15 actions. - -******************************************************************* - Definitions and type for levels state tables -******************************************************************* -*/ -#define IMPTABLEVELS_RES (IMPTABLEVELS_COLUMNS - 1) -#define GET_STATE(cell) ((cell)&0x0f) -#define GET_ACTION(cell) ((cell)>>4) -#define s(action, newState) ((uint8_t)(newState+(action<<4))) - -/****************************************************************** - - LEVELS STATE TABLES - - In all levels state tables, - - state 0 is the initial state - - the Res column is the increment to add to the text level - for this property sequence. - - The impAct arrays for each table of a pair map the local action - numbers of the table to the total list of actions. For instance, - action 2 in a given table corresponds to the action number which - appears in entry [2] of the impAct array for that table. - The first entry of all impAct arrays must be 0. - - Action 1: init conditional sequence - 2: prepend conditional sequence to current sequence - 3: set ON sequence to new level - 1 - 4: init EN/AN/ON sequence - 5: fix EN/AN/ON sequence followed by R - 6: set previous level sequence to level 2 - - Notes: - 1) These tables are used in ProcessPropertySeq(). The input - is property sequences as determined by ResolveImplicitLevels. - 2) Most such property sequences are processed immediately - (levels are assigned). - 3) However, some sequences cannot be assigned a final level till - one or more following sequences are received. For instance, - ON following an R sequence within an even-level paragraph. - If the following sequence is R, the ON sequence will be - assigned basic run level+1, and so will the R sequence. - 4) S is generally handled like ON, since its level will be fixed - to paragraph level in AdjustWSLevels(). - -*/ - -static const ImpTab impTabL = /* Even paragraph level */ -/* In this table, conditional sequences receive the higher possible level - until proven otherwise. -*/ -{ -/* L , R , EN , AN , ON , S , B , Res */ -/* 0 : init */ { 0 , 1 , 0 , 2 , 0 , 0 , 0 , 0 }, -/* 1 : R */ { 0 , 1 , 3 , 3 , s(1,4), s(1,4), 0 , 1 }, -/* 2 : AN */ { 0 , 1 , 0 , 2 , s(1,5), s(1,5), 0 , 2 }, -/* 3 : R+EN/AN */ { 0 , 1 , 3 , 3 , s(1,4), s(1,4), 0 , 2 }, -/* 4 : R+ON */ { s(2,0), 1 , 3 , 3 , 4 , 4 , s(2,0), 1 }, -/* 5 : AN+ON */ { s(2,0), 1 , s(2,0), 2 , 5 , 5 , s(2,0), 1 } -}; -static const ImpTab impTabR = /* Odd paragraph level */ -/* In this table, conditional sequences receive the lower possible level - until proven otherwise. -*/ -{ -/* L , R , EN , AN , ON , S , B , Res */ -/* 0 : init */ { 1 , 0 , 2 , 2 , 0 , 0 , 0 , 0 }, -/* 1 : L */ { 1 , 0 , 1 , 3 , s(1,4), s(1,4), 0 , 1 }, -/* 2 : EN/AN */ { 1 , 0 , 2 , 2 , 0 , 0 , 0 , 1 }, -/* 3 : L+AN */ { 1 , 0 , 1 , 3 , 5 , 5 , 0 , 1 }, -/* 4 : L+ON */ { s(2,1), 0 , s(2,1), 3 , 4 , 4 , 0 , 0 }, -/* 5 : L+AN+ON */ { 1 , 0 , 1 , 3 , 5 , 5 , 0 , 0 } -}; - -#undef s - -static ImpAct impAct0 = {0,1,2,3,4,5,6}; -static PImpTab impTab[2] = {impTabL, impTabR}; - -/*------------------------------------------------------------------------*/ - -/* perform rules (Wn), (Nn), and (In) on a run of the text ------------------ */ - -/* - * This implementation of the (Wn) rules applies all rules in one pass. - * In order to do so, it needs a look-ahead of typically 1 character - * (except for W5: sequences of ET) and keeps track of changes - * in a rule Wp that affect a later Wq (ppImpTab; - PImpAct pImpAct = pLevState->pImpAct; - nsBidiLevel* levels = mLevels; - nsBidiLevel level, addLevel; - int32_t start0, k; - - start0 = start; /* save original start position */ - oldStateSeq = (uint8_t)pLevState->state; - cell = pImpTab[oldStateSeq][_prop]; - pLevState->state = GET_STATE(cell); /* isolate the new state */ - actionSeq = pImpAct[GET_ACTION(cell)]; /* isolate the action */ - addLevel = pImpTab[pLevState->state][IMPTABLEVELS_RES]; - - if(actionSeq) { - switch(actionSeq) { - case 1: /* init ON seq */ - pLevState->startON = start0; - break; - - case 2: /* prepend ON seq to current seq */ - MOZ_ASSERT(pLevState->startON >= 0, "no valid ON sequence start!"); - start = pLevState->startON; - break; - - default: /* we should never get here */ - MOZ_ASSERT(false); - break; - } - } - if(addLevel || (start < start0)) { - level = pLevState->runLevel + addLevel; - if (start >= pLevState->runStart) { - for (k = start; k < limit; k++) { - levels[k] = level; - } - } else { - DirProp *dirProps = mDirProps, dirProp; - int32_t isolateCount = 0; - for (k = start; k < limit; k++) { - dirProp = dirProps[k]; - if (dirProp == PDI) { - isolateCount--; - } - if (isolateCount == 0) { - levels[k]=level; - } - if (dirProp == LRI || dirProp == RLI) { - isolateCount++; - } - } - } - } -} - -void nsBidi::ResolveImplicitLevels(int32_t aStart, int32_t aLimit, - DirProp aSOR, DirProp aEOR) -{ - const DirProp *dirProps = mDirProps; - DirProp dirProp; - LevState levState; - int32_t i, start1, start2; - uint16_t oldStateImp, stateImp, actionImp; - uint8_t gprop, resProp, cell; - - /* initialize for property and levels state tables */ - levState.runStart = aStart; - levState.runLevel = mLevels[aStart]; - levState.pImpTab = impTab[levState.runLevel & 1]; - levState.pImpAct = impAct0; - levState.startON = -1; /* initialize to invalid start position */ - - /* The isolates[] entries contain enough information to - resume the bidi algorithm in the same state as it was - when it was interrupted by an isolate sequence. */ - if (dirProps[aStart] == PDI && mIsolateCount >= 0) { - start1 = mIsolates[mIsolateCount].start1; - stateImp = mIsolates[mIsolateCount].stateImp; - levState.state = mIsolates[mIsolateCount].state; - mIsolateCount--; - } else { - levState.startON = -1; - start1 = aStart; - if (dirProps[aStart] == NSM) { - stateImp = 1 + aSOR; - } else { - stateImp = 0; - } - levState.state = 0; - ProcessPropertySeq(&levState, aSOR, aStart, aStart); - } - start2 = aStart; - - for (i = aStart; i <= aLimit; i++) { - if (i >= aLimit) { - int32_t k; - for (k = aLimit - 1; - k > aStart && (DIRPROP_FLAG(dirProps[k]) & MASK_BN_EXPLICIT); k--) { - // empty loop body - } - dirProp = mDirProps[k]; - if (dirProp == LRI || dirProp == RLI) { - break; /* no forced closing for sequence ending with LRI/RLI */ - } - gprop = aEOR; - } else { - DirProp prop; - prop = dirProps[i]; - gprop = groupProp[prop]; - } - oldStateImp = stateImp; - cell = impTabProps[oldStateImp][gprop]; - stateImp = GET_STATEPROPS(cell); /* isolate the new state */ - actionImp = GET_ACTIONPROPS(cell); /* isolate the action */ - if ((i == aLimit) && (actionImp == 0)) { - /* there is an unprocessed sequence if its property == eor */ - actionImp = 1; /* process the last sequence */ - } - if (actionImp) { - resProp = impTabProps[oldStateImp][IMPTABPROPS_RES]; - switch (actionImp) { - case 1: /* process current seq1, init new seq1 */ - ProcessPropertySeq(&levState, resProp, start1, i); - start1 = i; - break; - case 2: /* init new seq2 */ - start2 = i; - break; - case 3: /* process seq1, process seq2, init new seq1 */ - ProcessPropertySeq(&levState, resProp, start1, start2); - ProcessPropertySeq(&levState, DirProp_ON, start2, i); - start1 = i; - break; - case 4: /* process seq1, set seq1=seq2, init new seq2 */ - ProcessPropertySeq(&levState, resProp, start1, start2); - start1 = start2; - start2 = i; - break; - default: /* we should never get here */ - MOZ_ASSERT(false); - break; - } - } - } - - for (i = aLimit - 1; - i > aStart && (DIRPROP_FLAG(dirProps[i]) & MASK_BN_EXPLICIT); i--) { - // empty loop body - } - dirProp = dirProps[i]; - if ((dirProp == LRI || dirProp == RLI) && aLimit < mLength) { - mIsolateCount++; - mIsolates[mIsolateCount].stateImp = stateImp; - mIsolates[mIsolateCount].state = levState.state; - mIsolates[mIsolateCount].start1 = start1; - } else { - ProcessPropertySeq(&levState, aEOR, aLimit, aLimit); - } -} - - -/* perform (L1) and (X9) ---------------------------------------------------- */ - -/* - * Reset the embedding levels for some non-graphic characters (L1). - * This function also sets appropriate levels for BN, and - * explicit embedding types that are supposed to have been removed - * from the paragraph in (X9). - */ -void nsBidi::AdjustWSLevels() -{ - const DirProp *dirProps=mDirProps; - nsBidiLevel *levels=mLevels; - int32_t i; - - if(mFlags&MASK_WS) { - nsBidiLevel paraLevel=mParaLevel; - Flags flag; - - i=mTrailingWSStart; - while(i>0) { - /* reset a sequence of WS/BN before eop and B/S to the paragraph paraLevel */ - while (i > 0 && DIRPROP_FLAG(dirProps[--i]) & MASK_WS) { - levels[i]=paraLevel; - } - - /* reset BN to the next character's paraLevel until B/S, which restarts above loop */ - /* here, i+1 is guaranteed to be 0) { - flag = DIRPROP_FLAG(dirProps[--i]); - if(flag&MASK_BN_EXPLICIT) { - levels[i]=levels[i+1]; - } else if(flag&MASK_B_S) { - levels[i]=paraLevel; - break; - } - } - } - } -} - -nsresult nsBidi::GetDirection(nsBidiDirection* aDirection) -{ - *aDirection = mDirection; - return NS_OK; -} - -nsresult nsBidi::GetParaLevel(nsBidiLevel* aParaLevel) -{ - *aParaLevel = mParaLevel; - return NS_OK; -} - -nsresult nsBidi::GetLogicalRun(int32_t aLogicalStart, int32_t *aLogicalLimit, nsBidiLevel *aLevel) -{ - int32_t length = mLength; - - if(aLogicalStart<0 || length<=aLogicalStart) { - return NS_ERROR_INVALID_ARG; - } - - int32_t runCount, visualStart, logicalLimit, logicalFirst, i; - Run iRun; - - /* CountRuns will check VALID_PARA_OR_LINE */ - nsresult rv = CountRuns(&runCount); - if (NS_FAILED(rv)) { - return rv; - } - - visualStart = logicalLimit = 0; - iRun = mRuns[0]; - - for (i = 0; i < runCount; i++) { - iRun = mRuns[i]; - logicalFirst = GET_INDEX(iRun.logicalStart); - logicalLimit = logicalFirst + iRun.visualLimit - visualStart; - if ((aLogicalStart >= logicalFirst) && (aLogicalStart < logicalLimit)) { - break; - } - visualStart = iRun.visualLimit; - } - if (aLogicalLimit) { - *aLogicalLimit = logicalLimit; - } - if (aLevel) { - if (mDirection != NSBIDI_MIXED || aLogicalStart >= mTrailingWSStart) { - *aLevel = mParaLevel; - } else { - *aLevel = mLevels[aLogicalStart]; - } - } - return NS_OK; -} - -/* runs API functions ------------------------------------------------------- */ - -nsresult nsBidi::CountRuns(int32_t* aRunCount) -{ - if(mRunCount<0 && !GetRuns()) { - return NS_ERROR_OUT_OF_MEMORY; - } else { - if (aRunCount) - *aRunCount = mRunCount; - return NS_OK; - } -} - -nsresult nsBidi::GetVisualRun(int32_t aRunIndex, int32_t *aLogicalStart, int32_t *aLength, nsBidiDirection *aDirection) -{ - if( aRunIndex<0 || - (mRunCount==-1 && !GetRuns()) || - aRunIndex>=mRunCount - ) { - *aDirection = NSBIDI_LTR; - return NS_OK; - } else { - int32_t start=mRuns[aRunIndex].logicalStart; - if(aLogicalStart!=nullptr) { - *aLogicalStart=GET_INDEX(start); - } - if(aLength!=nullptr) { - if(aRunIndex>0) { - *aLength=mRuns[aRunIndex].visualLimit- - mRuns[aRunIndex-1].visualLimit; - } else { - *aLength=mRuns[0].visualLimit; - } - } - *aDirection = (nsBidiDirection)GET_ODD_BIT(start); - return NS_OK; - } -} - -/* compute the runs array --------------------------------------------------- */ - -/* - * Compute the runs array from the levels array. - * After GetRuns() returns true, runCount is guaranteed to be >0 - * and the runs are reordered. - * Odd-level runs have visualStart on their visual right edge and - * they progress visually to the left. - */ -bool nsBidi::GetRuns() -{ - /* - * This method returns immediately if the runs are already set. This - * includes the case of length==0 (handled in setPara).. - */ - if (mRunCount >= 0) { - return true; - } - - if(mDirection!=NSBIDI_MIXED) { - /* simple, single-run case - this covers length==0 */ - GetSingleRun(mParaLevel); - } else /* NSBIDI_MIXED, length>0 */ { - /* mixed directionality */ - int32_t length=mLength, limit=mTrailingWSStart; - - /* - * If there are WS characters at the end of the line - * and the run preceding them has a level different from - * paraLevel, then they will form their own run at paraLevel (L1). - * Count them separately. - * We need some special treatment for this in order to not - * modify the levels array which a line nsBidi object shares - * with its paragraph parent and its other line siblings. - * In other words, for the trailing WS, it may be - * levels[]!=paraLevel but we have to treat it like it were so. - */ - nsBidiLevel *levels=mLevels; - int32_t i, runCount; - nsBidiLevel level=NSBIDI_DEFAULT_LTR; /* initialize with no valid level */ - - /* count the runs, there is at least one non-WS run, and limit>0 */ - runCount=0; - for(i=0; i1 || limit1 */ - if(GETRUNSMEMORY(runCount)) { - runs=mRunsMemory; - } else { - return false; - } - - /* set the runs */ - /* this could be optimized, e.g.: 464->444, 484->444, 575->555, 595->555 */ - /* however, that would take longer and make other functions more complicated */ - runIndex=0; - - /* search for the run ends */ - i = 0; - do { - /* prepare this run */ - start = i; - level = levels[i]; - if(levelmaxLevel) { - maxLevel=level; - } - - /* look for the run limit */ - while (++i < limit && levels[i] == level) { - } - - /* i is another run limit */ - runs[runIndex].logicalStart = start; - runs[runIndex].visualLimit = i - start; - ++runIndex; - } while (i < limit); - - if(limit1 and maxLevel>=minLevel>=paraLevel. - * All the visualStart fields=logical start before reordering. - * The "odd" bits are not set yet. - * - * Reordering with this data structure lends itself to some handy shortcuts: - * - * Since each run is moved but not modified, and since at the initial maxLevel - * each sequence of same-level runs consists of only one run each, we - * don't need to do anything there and can predecrement maxLevel. - * In many simple cases, the reordering is thus done entirely in the - * index mapping. - * Also, reordering occurs only down to the lowest odd level that occurs, - * which is minLevel|1. However, if the lowest level itself is odd, then - * in the last reordering the sequence of the runs at this level or higher - * will be all runs, and we don't need the elaborate loop to search for them. - * This is covered by ++minLevel instead of minLevel|=1 followed - * by an extra reorder-all after the reorder-some loop. - * About a trailing WS run: - * Such a run would need special treatment because its level is not - * reflected in levels[] if this is not a paragraph object. - * Instead, all characters from trailingWSStart on are implicitly at - * paraLevel. - * However, for all maxLevel>paraLevel, this run will never be reordered - * and does not need to be taken into account. maxLevel==paraLevel is only reordered - * if minLevel==paraLevel is odd, which is done in the extra segment. - * This means that for the main reordering loop we don't need to consider - * this run and can --runCount. If it is later part of the all-runs - * reordering, then runCount is adjusted accordingly. - */ -void nsBidi::ReorderLine(nsBidiLevel aMinLevel, nsBidiLevel aMaxLevel) -{ - Run *runs, tempRun; - nsBidiLevel *levels; - int32_t firstRun, endRun, limitRun, runCount; - - /* nothing to do? */ - if(aMaxLevel<=(aMinLevel|1)) { - return; - } - - /* - * Reorder only down to the lowest odd level - * and reorder at an odd aMinLevel in a separate, simpler loop. - * See comments above for why aMinLevel is always incremented. - */ - ++aMinLevel; - - runs=mRuns; - levels=mLevels; - runCount=mRunCount; - - /* do not include the WS run at paraLevel<=old aMinLevel except in the simple loop */ - if(mTrailingWSStart=aMinLevel) { - firstRun=0; - - /* loop for all sequences of runs */ - for(;;) { - /* look for a sequence of runs that are all at >=aMaxLevel */ - /* look for the first run of such a sequence */ - while(firstRun=runCount) { - break; /* no more such runs */ - } - - /* look for the limit run of such a sequence (the run behind it) */ - for(limitRun=firstRun; ++limitRun=aMaxLevel;) {} - - /* Swap the entire sequence of runs from firstRun to limitRun-1. */ - endRun=limitRun-1; - while(firstRun=maxLevel */ - /* look for the first index of such a sequence */ - while(start=aLength) { - break; /* no more such runs */ - } - - /* look for the limit of such a sequence (the index behind it) */ - for(limit=start; ++limit=maxLevel;) {} - - /* - * Swap the entire interval of indexes from start to limit-1. - * We don't need to swap the levels for the purpose of this - * algorithm: the sequence of levels that we look at does not - * move anyway. - */ - end=limit-1; - while(start=minLevel); - - return NS_OK; -} - -bool nsBidi::PrepareReorder(const nsBidiLevel *aLevels, int32_t aLength, - int32_t *aIndexMap, - nsBidiLevel *aMinLevel, nsBidiLevel *aMaxLevel) -{ - int32_t start; - nsBidiLevel level, minLevel, maxLevel; - - if(aLevels==nullptr || aLength<=0) { - return false; - } - - /* determine minLevel and maxLevel */ - minLevel=NSBIDI_MAX_EXPLICIT_LEVEL+1; - maxLevel=0; - for(start=aLength; start>0;) { - level=aLevels[--start]; - if(level>NSBIDI_MAX_EXPLICIT_LEVEL+1) { - return false; - } - if(levelmaxLevel) { - maxLevel=level; - } - } - *aMinLevel=minLevel; - *aMaxLevel=maxLevel; - - /* initialize the index map */ - for(start=aLength; start>0;) { - --start; - aIndexMap[start]=start; - } - - return true; -} diff --git a/layout/base/nsBidi_noICU.h b/layout/base/nsBidi_noICU.h deleted file mode 100644 index 2ddfa8488835..000000000000 --- a/layout/base/nsBidi_noICU.h +++ /dev/null @@ -1,712 +0,0 @@ -/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef nsBidi_noICU_h__ -#define nsBidi_noICU_h__ - -#include "nsBidiUtils.h" -#include "nsIFrame.h" // for frame property declaration - -// Bidi reordering engine from ICU -/* - * javadoc-style comments are intended to be transformed into HTML - * using DOC++ - see - * http://www.zib.de/Visual/software/doc++/index.html . - * - * The HTML documentation is created with - * doc++ -H nsBidi.h - */ - -/** - * @mainpage BIDI algorithm for Mozilla (from ICU) - * - *

BIDI algorithm for Mozilla

- * - * This is an implementation of the Unicode Bidirectional algorithm. - * The algorithm is defined in the - * Unicode Technical Report 9, - * version 5, also described in The Unicode Standard, Version 3.0 .

- * - *

General remarks about the API:

- * - * The limit of a sequence of characters is the position just after their - * last character, i.e., one more than that position.

- * - * Some of the API functions provide access to runs. - * Such a run is defined as a sequence of characters - * that are at the same embedding level - * after performing the BIDI algorithm.

- * - * @author Markus W. Scherer. Ported to Mozilla by Simon Montagu - * @version 1.0 - */ - -/** - * Special value which can be returned by the mapping functions when a logical - * index has no corresponding visual index or vice-versa. - * @see GetVisualIndex - * @see GetVisualMap - * @see GetLogicalIndex - * @see GetLogicalMap - */ -#define NSBIDI_MAP_NOWHERE (-1) - -/* miscellaneous definitions ------------------------------------------------ */ - -/* helper macros for each allocated array member */ -#define GETDIRPROPSMEMORY(length) nsBidi::GetMemory((void **)&mDirPropsMemory, \ - &mDirPropsSize, \ - (length)) - -#define GETLEVELSMEMORY(length) nsBidi::GetMemory((void **)&mLevelsMemory, \ - &mLevelsSize, \ - (length)) - -#define GETRUNSMEMORY(length) nsBidi::GetMemory((void **)&mRunsMemory, \ - &mRunsSize, \ - (length)*sizeof(Run)) - -#define GETISOLATESMEMORY(length) nsBidi::GetMemory((void **)&mIsolatesMemory, \ - &mIsolatesSize, \ - (length)*sizeof(Isolate)) - -#define GETOPENINGSMEMORY(length) nsBidi::GetMemory((void **)&mOpeningsMemory, \ - &mOpeningsSize, \ - (length)*sizeof(Opening)) - -/* - * Sometimes, bit values are more appropriate - * to deal with directionality properties. - * Abbreviations in these macro names refer to names - * used in the Bidi algorithm. - */ -typedef uint8_t DirProp; - -#define DIRPROP_FLAG(dir) (1UL<<(dir)) - -/* special flag for multiple runs from explicit embedding codes */ -#define DIRPROP_FLAG_MULTI_RUNS (1UL<<31) - -/* are there any characters that are LTR or RTL? */ -#define MASK_LTR (DIRPROP_FLAG(L)|DIRPROP_FLAG(EN)|DIRPROP_FLAG(ENL)| \ - DIRPROP_FLAG(ENR)|DIRPROP_FLAG(AN)|DIRPROP_FLAG(LRE)| \ - DIRPROP_FLAG(LRO)|DIRPROP_FLAG(LRI)) -#define MASK_RTL (DIRPROP_FLAG(R)|DIRPROP_FLAG(AL)|DIRPROP_FLAG(RLE)| \ - DIRPROP_FLAG(RLO)|DIRPROP_FLAG(RLI)) -#define MASK_R_AL (DIRPROP_FLAG(R)|DIRPROP_FLAG(AL)) - -/* explicit embedding codes */ -#define MASK_EXPLICIT (DIRPROP_FLAG(LRE)|DIRPROP_FLAG(LRO)|DIRPROP_FLAG(RLE)|DIRPROP_FLAG(RLO)|DIRPROP_FLAG(PDF)) - -/* explicit isolate codes */ -#define MASK_ISO (DIRPROP_FLAG(LRI)|DIRPROP_FLAG(RLI)|DIRPROP_FLAG(FSI)|DIRPROP_FLAG(PDI)) - -#define MASK_BN_EXPLICIT (DIRPROP_FLAG(BN)|MASK_EXPLICIT) - -/* paragraph and segment separators */ -#define MASK_B_S (DIRPROP_FLAG(B)|DIRPROP_FLAG(S)) - -/* all types that are counted as White Space or Neutral in some steps */ -#define MASK_WS (MASK_B_S|DIRPROP_FLAG(WS)|MASK_BN_EXPLICIT|MASK_ISO) - -/* types that are neutrals or could becomes neutrals in (Wn) */ -#define MASK_POSSIBLE_N (DIRPROP_FLAG(O_N)|DIRPROP_FLAG(CS)|DIRPROP_FLAG(ES)|DIRPROP_FLAG(ET)|MASK_WS) - -/* - * These types may be changed to "e", - * the embedding type (L or R) of the run, - * in the Bidi algorithm (N2) - */ -#define MASK_EMBEDDING (DIRPROP_FLAG(NSM)|MASK_POSSIBLE_N) - -/* the dirProp's L and R are defined to 0 and 1 values in nsCharType */ -#define GET_LR_FROM_LEVEL(level) ((DirProp)((level)&1)) - -#define IS_DEFAULT_LEVEL(level) (((level)&0xfe)==0xfe) - -/* - * The following bit is used for the directional isolate status. - * Stack entries corresponding to isolate sequences are greater than ISOLATE. - */ -#define ISOLATE 0x0100 - -/* number of isolate entries allocated initially without malloc */ -#define SIMPLE_ISOLATES_SIZE 5 - -/* number of isolate run entries for paired brackets allocated initially without malloc */ -#define SIMPLE_OPENINGS_COUNT 8 - -/* handle surrogate pairs --------------------------------------------------- */ - -#define IS_FIRST_SURROGATE(uchar) (((uchar)&0xfc00)==0xd800) -#define IS_SECOND_SURROGATE(uchar) (((uchar)&0xfc00)==0xdc00) - -/* get the UTF-32 value directly from the surrogate pseudo-characters */ -#define SURROGATE_OFFSET ((0xd800<<10UL)+0xdc00-0x10000) -#define GET_UTF_32(first, second) (((first)<<10UL)+(second)-SURROGATE_OFFSET) - -#if !ENABLE_INTL_API // these are provided by ICU if present in the build - -#define UTF_ERROR_VALUE 0xffff -/* definitions with forward iteration --------------------------------------- */ - -/* - * all the macros that go forward assume that - * the initial offset is 0<=i>10)+0xd7c0; \ - (s)[(i)++]=(char16_t)(c)&0x3ff|0xdc00; \ - } \ -} - -/* safe versions with error-checking and optional regularity-checking */ - -#define UTF16_APPEND_CHAR_SAFE(s, i, length, c) { \ - if((PRUInt32)(c)<=0xffff) { \ - (s)[(i)++]=(char16_t)(c); \ - } else if((PRUInt32)(c)<=0x10ffff) { \ - if((i)+1<(length)) { \ - (s)[(i)++]=(char16_t)((c)>>10)+0xd7c0; \ - (s)[(i)++]=(char16_t)(c)&0x3ff|0xdc00; \ - } else /* not enough space */ { \ - (s)[(i)++]=UTF_ERROR_VALUE; \ - } \ - } else /* c>0x10ffff, write error value */ { \ - (s)[(i)++]=UTF_ERROR_VALUE; \ - } \ -} - -/* definitions with backward iteration -------------------------------------- */ - -/* - * all the macros that go backward assume that - * the valid buffer range starts at offset 0 - * and that the initial offset is 00) { \ - UTF16_BACK_1_UNSAFE(s, i); \ - --__N; \ - } \ -} - -/* safe versions with error-checking and optional regularity-checking */ - -#define UTF16_PREV_CHAR_SAFE(s, start, i, c, strict) { \ - (c)=(s)[--(i)]; \ - if(IS_SECOND_SURROGATE(c)) { \ - char16_t __c2; \ - if((i)>(start) && IS_FIRST_SURROGATE(__c2=(s)[(i)-1])) { \ - --(i); \ - (c)=GET_UTF_32(__c2, (c)); \ - /* strict: ((c)&0xfffe)==0xfffe is caught by UTF_IS_ERROR() */ \ - } else if(strict) {\ - /* unmatched second surrogate */ \ - (c)=UTF_ERROR_VALUE; \ - } \ - } else if(strict && IS_FIRST_SURROGATE(c)) { \ - /* unmatched first surrogate */ \ - (c)=UTF_ERROR_VALUE; \ - /* else strict: (c)==0xfffe is caught by UTF_IS_ERROR() */ \ - } \ -} - -#define UTF16_BACK_1_SAFE(s, start, i) { \ - if(IS_SECOND_SURROGATE((s)[--(i)]) && (i)>(start) && IS_FIRST_SURROGATE((s)[(i)-1])) { \ - --(i); \ - } \ -} - -#define UTF16_BACK_N_SAFE(s, start, i, n) { \ - int32_t __N=(n); \ - while(__N>0 && (i)>(start)) { \ - UTF16_BACK_1_SAFE(s, start, i); \ - --__N; \ - } \ -} - -#define UTF_PREV_CHAR_UNSAFE(s, i, c) UTF16_PREV_CHAR_UNSAFE(s, i, c) -#define UTF_PREV_CHAR_SAFE(s, start, i, c, strict) UTF16_PREV_CHAR_SAFE(s, start, i, c, strict) -#define UTF_BACK_1_UNSAFE(s, i) UTF16_BACK_1_UNSAFE(s, i) -#define UTF_BACK_1_SAFE(s, start, i) UTF16_BACK_1_SAFE(s, start, i) -#define UTF_BACK_N_UNSAFE(s, i, n) UTF16_BACK_N_UNSAFE(s, i, n) -#define UTF_BACK_N_SAFE(s, start, i, n) UTF16_BACK_N_SAFE(s, start, i, n) -#define UTF_APPEND_CHAR_UNSAFE(s, i, c) UTF16_APPEND_CHAR_UNSAFE(s, i, c) -#define UTF_APPEND_CHAR_SAFE(s, i, length, c) UTF16_APPEND_CHAR_SAFE(s, i, length, c) - -#define UTF_PREV_CHAR(s, start, i, c) UTF_PREV_CHAR_SAFE(s, start, i, c, false) -#define UTF_BACK_1(s, start, i) UTF_BACK_1_SAFE(s, start, i) -#define UTF_BACK_N(s, start, i, n) UTF_BACK_N_SAFE(s, start, i, n) -#define UTF_APPEND_CHAR(s, i, length, c) UTF_APPEND_CHAR_SAFE(s, i, length, c) - -#endif // !ENABLE_INTL_API - -struct Isolate { - int32_t start1; - int16_t stateImp; - int16_t state; -}; - -// For bracket matching - -#define FOUND_L DIRPROP_FLAG(L) -#define FOUND_R DIRPROP_FLAG(R) - -struct Opening { - int32_t position; /* position of opening bracket */ - int32_t match; /* matching char or -position of closing bracket */ - int32_t contextPos; /* position of last strong char found before opening */ - uint16_t flags; /* bits for L or R/AL found within the pair */ - DirProp contextDir; /* L or R according to last strong char before opening */ - uint8_t filler; /* to complete a nice multiple of 4 chars */ -}; - -struct IsoRun { - int32_t contextPos; /* position of char determining context */ - uint16_t start; /* index of first opening entry for this run */ - uint16_t limit; /* index after last opening entry for this run */ - nsBidiLevel level; /* level of this run */ - DirProp lastStrong; /* bidi class of last strong char found in this run */ - DirProp lastBase; /* bidi class of last base char found in this run */ - DirProp contextDir; /* L or R to use as context for following openings */ -}; - -class nsBidi; - -/* Run structure for reordering --------------------------------------------- */ - -typedef struct Run { - int32_t logicalStart; /* first character of the run; b31 indicates even/odd level */ - int32_t visualLimit; /* last visual position of the run +1 */ -} Run; - -/* in a Run, logicalStart will get this bit set if the run level is odd */ -#define INDEX_ODD_BIT (1UL<<31) - -#define MAKE_INDEX_ODD_PAIR(index, level) (index|((uint32_t)level<<31)) -#define ADD_ODD_BIT_FROM_LEVEL(x, level) ((x)|=((uint32_t)level<<31)) -#define REMOVE_ODD_BIT(x) ((x)&=~INDEX_ODD_BIT) - -#define GET_INDEX(x) ((x)&~INDEX_ODD_BIT) -#define GET_ODD_BIT(x) ((uint32_t)(x)>>31) -#define IS_ODD_RUN(x) (((x)&INDEX_ODD_BIT)!=0) -#define IS_EVEN_RUN(x) (((x)&INDEX_ODD_BIT)==0) - -typedef uint32_t Flags; - -enum { DirProp_L=0, DirProp_R=1, DirProp_EN=2, DirProp_AN=3, DirProp_ON=4, DirProp_S=5, DirProp_B=6 }; /* reduced dirProp */ - -#define IMPTABLEVELS_COLUMNS (DirProp_B + 2) -typedef const uint8_t ImpTab[][IMPTABLEVELS_COLUMNS]; -typedef const uint8_t (*PImpTab)[IMPTABLEVELS_COLUMNS]; - -typedef const uint8_t ImpAct[]; -typedef const uint8_t *PImpAct; - -struct LevState { - PImpTab pImpTab; /* level table pointer */ - PImpAct pImpAct; /* action map array */ - int32_t startON; /* start of ON sequence */ - int32_t state; /* current state */ - int32_t runStart; /* start position of the run */ - nsBidiLevel runLevel; /* run level before implicit solving */ -}; - -/** - * This class holds information about a paragraph of text - * with Bidi-algorithm-related details, or about one line of - * such a paragraph.

- * Reordering can be done on a line, or on a paragraph which is - * then interpreted as one single line.

- * - * On construction, the class is initially empty. It is assigned - * the Bidi properties of a paragraph by SetPara - * or the Bidi properties of a line of a paragraph by - * SetLine.

- * A Bidi class can be reused for as long as it is not deallocated - * by calling its destructor.

- * SetPara will allocate additional memory for - * internal structures as necessary. - */ -class nsBidi -{ -public: - /** @brief Default constructor. - * - * The nsBidi object is initially empty. It is assigned - * the Bidi properties of a paragraph by SetPara() - * or the Bidi properties of a line of a paragraph by - * GetLine().

- * This object can be reused for as long as it is not destroyed.

- * SetPara() will allocate additional memory for - * internal structures as necessary. - * - */ - nsBidi(); - - /** @brief Destructor. */ - virtual ~nsBidi(); - - - /** - * Perform the Unicode Bidi algorithm. It is defined in the - * Unicode Technical Report 9, - * version 5, - * also described in The Unicode Standard, Version 3.0 .

- * - * This function takes a single plain text paragraph with or without - * externally specified embedding levels from styled text - * and computes the left-right-directionality of each character.

- * - * If the entire paragraph consists of text of only one direction, then - * the function may not perform all the steps described by the algorithm, - * i.e., some levels may not be the same as if all steps were performed. - * This is not relevant for unidirectional text.
- * For example, in pure LTR text with numbers the numbers would get - * a resolved level of 2 higher than the surrounding text according to - * the algorithm. This implementation may set all resolved levels to - * the same value in such a case.

- * - * The text must be externally split into separate paragraphs (rule P1). - * Paragraph separators (B) should appear at most at the very end. - * - * @param aText is a pointer to the single-paragraph text that the - * Bidi algorithm will be performed on - * (step (P1) of the algorithm is performed externally). - * The text must be (at least) aLength long. - * - * @param aLength is the length of the text; if aLength==-1 then - * the text must be zero-terminated. - * - * @param aParaLevel specifies the default level for the paragraph; - * it is typically 0 (LTR) or 1 (RTL). - * If the function shall determine the paragraph level from the text, - * then aParaLevel can be set to - * either NSBIDI_DEFAULT_LTR - * or NSBIDI_DEFAULT_RTL; - * if there is no strongly typed character, then - * the desired default is used (0 for LTR or 1 for RTL). - * Any other value between 0 and NSBIDI_MAX_EXPLICIT_LEVEL is also valid, - * with odd levels indicating RTL. - */ - nsresult SetPara(const char16_t *aText, int32_t aLength, nsBidiLevel aParaLevel); - - /** - * Get the directionality of the text. - * - * @param aDirection receives a NSBIDI_XXX value that indicates if the entire text - * represented by this object is unidirectional, - * and which direction, or if it is mixed-directional. - * - * @see nsBidiDirection - */ - nsresult GetDirection(nsBidiDirection* aDirection); - - /** - * Get the paragraph level of the text. - * - * @param aParaLevel receives a NSBIDI_XXX value indicating the paragraph level - * - * @see nsBidiLevel - */ - nsresult GetParaLevel(nsBidiLevel* aParaLevel); - - /** - * Get a logical run. - * This function returns information about a run and is used - * to retrieve runs in logical order.

- * This is especially useful for line-breaking on a paragraph. - * - * @param aLogicalStart is the first character of the run. - * - * @param aLogicalLimit will receive the limit of the run. - * The l-value that you point to here may be the - * same expression (variable) as the one for - * aLogicalStart. - * This pointer can be nullptr if this - * value is not necessary. - * - * @param aLevel will receive the level of the run. - * This pointer can be nullptr if this - * value is not necessary. - */ - nsresult GetLogicalRun(int32_t aLogicalStart, int32_t* aLogicalLimit, nsBidiLevel* aLevel); - - /** - * Get the number of runs. - * This function may invoke the actual reordering on the - * nsBidi object, after SetPara - * may have resolved only the levels of the text. Therefore, - * CountRuns may have to allocate memory, - * and may fail doing so. - * - * @param aRunCount will receive the number of runs. - */ - nsresult CountRuns(int32_t* aRunCount); - - /** - * Get one run's logical start, length, and directionality, - * which can be 0 for LTR or 1 for RTL. - * In an RTL run, the character at the logical start is - * visually on the right of the displayed run. - * The length is the number of characters in the run.

- * CountRuns should be called - * before the runs are retrieved. - * - * @param aRunIndex is the number of the run in visual order, in the - * range [0..CountRuns-1]. - * - * @param aLogicalStart is the first logical character index in the text. - * The pointer may be nullptr if this index is not needed. - * - * @param aLength is the number of characters (at least one) in the run. - * The pointer may be nullptr if this is not needed. - * - * @param aDirection will receive the directionality of the run, - * NSBIDI_LTR==0 or NSBIDI_RTL==1, - * never NSBIDI_MIXED. - * - * @see CountRuns

- * - * Example: - * @code - * int32_t i, count, logicalStart, visualIndex=0, length; - * nsBidiDirection dir; - * pBidi->CountRuns(&count); - * for(i=0; iGetVisualRun(i, &logicalStart, &length, &dir); - * if(NSBIDI_LTR==dir) { - * do { // LTR - * show_char(text[logicalStart++], visualIndex++); - * } while(--length>0); - * } else { - * logicalStart+=length; // logicalLimit - * do { // RTL - * show_char(text[--logicalStart], visualIndex++); - * } while(--length>0); - * } - * } - * @endcode - * - * Note that in right-to-left runs, code like this places - * modifier letters before base characters and second surrogates - * before first ones. - */ - nsresult GetVisualRun(int32_t aRunIndex, int32_t* aLogicalStart, int32_t* aLength, nsBidiDirection* aDirection); - - /** - * This is a convenience function that does not use a nsBidi object. - * It is intended to be used for when an application has determined the levels - * of objects (character sequences) and just needs to have them reordered (L2). - * This is equivalent to using GetVisualMap on a - * nsBidi object. - * - * @param aLevels is an array with aLength levels that have been determined by - * the application. - * - * @param aLength is the number of levels in the array, or, semantically, - * the number of objects to be reordered. - * It must be aLength>0. - * - * @param aIndexMap is a pointer to an array of aLength - * indexes which will reflect the reordering of the characters. - * The array does not need to be initialized.

- * The index map will result in aIndexMap[aVisualIndex]==aLogicalIndex. - */ - static nsresult ReorderVisual(const nsBidiLevel *aLevels, int32_t aLength, int32_t *aIndexMap); - - /** - * Reverse a Right-To-Left run of Unicode text. - * - * This function preserves the integrity of characters with multiple - * code units and (optionally) modifier letters. - * Characters can be replaced by mirror-image characters - * in the destination buffer. Note that "real" mirroring has - * to be done in a rendering engine by glyph selection - * and that for many "mirrored" characters there are no - * Unicode characters as mirror-image equivalents. - * There are also options to insert or remove Bidi control - * characters; see the description of the aDestSize - * and aOptions parameters and of the option bit flags. - * - * Since no Bidi controls are inserted here, this function will never - * write more than aSrcLength characters to aDest. - * - * @param aSrc A pointer to the RTL run text. - * - * @param aSrcLength The length of the RTL run. - * If the NSBIDI_REMOVE_BIDI_CONTROLS option - * is set, then the destination length may be less than - * aSrcLength. - * If this option is not set, then the destination length - * will be exactly aSrcLength. - * - * @param aDest A pointer to where the reordered text is to be copied. - * aSrc[aSrcLength] and aDest[aSrcLength] - * must not overlap. - * - * @param aOptions A bit set of options for the reordering that control - * how the reordered text is written. - * - * @param aDestSize will receive the number of characters that were written to aDest. - */ - nsresult WriteReverse(const char16_t *aSrc, int32_t aSrcLength, char16_t *aDest, uint16_t aOptions, int32_t *aDestSize); - -protected: - friend class nsBidiPresUtils; - - class BracketData { - public: - explicit BracketData(const nsBidi* aBidi); - ~BracketData(); - - void ProcessBoundary(int32_t aLastDirControlCharPos, - nsBidiLevel aContextLevel, - nsBidiLevel aEmbeddingLevel, - const DirProp* aDirProps); - void ProcessLRI_RLI(nsBidiLevel aLevel); - void ProcessPDI(); - bool AddOpening(char16_t aMatch, int32_t aPosition); - void FixN0c(int32_t aOpeningIndex, int32_t aNewPropPosition, - DirProp aNewProp, DirProp* aDirProps); - DirProp ProcessClosing(int32_t aOpenIdx, int32_t aPosition, - DirProp* aDirProps); - bool ProcessChar(int32_t aPosition, char16_t aCh, DirProp* aDirProps, - nsBidiLevel* aLevels); - - private: - // array of opening entries which should be enough in most cases; - // no malloc() needed - Opening mSimpleOpenings[SIMPLE_OPENINGS_COUNT]; - Opening* mOpenings; // pointer to current array of entries, - // either mSimpleOpenings or malloced array - - Opening* mOpeningsMemory; - size_t mOpeningsSize; - - // array of nested isolated sequence entries; can never exceed - // UBIDI_MAX_EXPLICIT_LEVEL - // + 1 for index 0 - // + 1 for before the first isolated sequence - IsoRun mIsoRuns[NSBIDI_MAX_EXPLICIT_LEVEL+2]; - int32_t mIsoRunLast; // index of last used entry in mIsoRuns - - int32_t mOpeningsCount; // number of allocated entries in mOpenings - }; - - /** length of the current text */ - int32_t mLength; - - /** memory sizes in bytes */ - size_t mDirPropsSize, mLevelsSize, mRunsSize; - size_t mIsolatesSize; - - /** allocated memory */ - DirProp* mDirPropsMemory; - nsBidiLevel* mLevelsMemory; - Run* mRunsMemory; - Isolate* mIsolatesMemory; - - DirProp* mDirProps; - nsBidiLevel* mLevels; - - /** the paragraph level */ - nsBidiLevel mParaLevel; - - /** flags is a bit set for which directional properties are in the text */ - Flags mFlags; - - /** the overall paragraph or line directionality - see nsBidiDirection */ - nsBidiDirection mDirection; - - /** characters after trailingWSStart are WS and are */ - /* implicitly at the paraLevel (rule (L1)) - levels may not reflect that */ - int32_t mTrailingWSStart; - - /** fields for line reordering */ - int32_t mRunCount; /* ==-1: runs not set up yet */ - Run* mRuns; - - /** for non-mixed text, we only need a tiny array of runs (no malloc()) */ - Run mSimpleRuns[1]; - - /* maxium of current nesting depth of isolate sequences */ - /* Within ResolveExplicitLevels() and checkExpicitLevels(), this is the maximal - nesting encountered. - Within ResolveImplicitLevels(), this is the index of the current isolates - stack entry. */ - int32_t mIsolateCount; - Isolate* mIsolates; - - /** for simple text, have a small stack (no malloc()) */ - Isolate mSimpleIsolates[SIMPLE_ISOLATES_SIZE]; - -private: - - void Init(); - - static bool GetMemory(void **aMemory, size_t* aSize, size_t aSizeNeeded); - - void Free(); - - void GetDirProps(const char16_t *aText); - - void ResolveExplicitLevels(nsBidiDirection *aDirection, const char16_t *aText); - - nsBidiDirection DirectionFromFlags(Flags aFlags); - - void ProcessPropertySeq(LevState *pLevState, uint8_t _prop, int32_t start, int32_t limit); - - void ResolveImplicitLevels(int32_t aStart, int32_t aLimit, DirProp aSOR, DirProp aEOR); - - void AdjustWSLevels(); - - void SetTrailingWSStart(); - - bool GetRuns(); - - void GetSingleRun(nsBidiLevel aLevel); - - void ReorderLine(nsBidiLevel aMinLevel, nsBidiLevel aMaxLevel); - - static bool PrepareReorder(const nsBidiLevel *aLevels, int32_t aLength, int32_t *aIndexMap, nsBidiLevel *aMinLevel, nsBidiLevel *aMaxLevel); - - nsBidi(const nsBidi&) = delete; - void operator=(const nsBidi&) = delete; -}; - -#endif // _nsBidi_noICU_h_ From cfe79f23f56dcf8a7ff4ee310ba8fbb44987f1b7 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Fri, 22 Sep 2017 10:37:17 +0100 Subject: [PATCH 15/37] Bug 1308359 - patch 2 - Move trivial ICU-wrapper nsBidi methods to the header file as inlines, and remove unnecessary nsresult return values from methods that cannot fail. r=xidorn --- layout/base/moz.build | 1 - layout/base/nsBidi.cpp | 68 --------------------------------- layout/base/nsBidi.h | 66 +++++++++++++++++++++++--------- layout/base/nsBidiPresUtils.cpp | 35 ++++++----------- 4 files changed, 61 insertions(+), 109 deletions(-) delete mode 100644 layout/base/nsBidi.cpp diff --git a/layout/base/moz.build b/layout/base/moz.build index 093b946b365d..f8dd64499e1d 100644 --- a/layout/base/moz.build +++ b/layout/base/moz.build @@ -93,7 +93,6 @@ UNIFIED_SOURCES += [ 'GeometryUtils.cpp', 'LayoutLogging.cpp', 'MobileViewportManager.cpp', - 'nsBidi.cpp', 'nsBidiPresUtils.cpp', 'nsCaret.cpp', 'nsCounterManager.cpp', diff --git a/layout/base/nsBidi.cpp b/layout/base/nsBidi.cpp deleted file mode 100644 index 1d6975869236..000000000000 --- a/layout/base/nsBidi.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsBidi.h" -#include "ICUUtils.h" - -nsBidi::nsBidi() -{ - mBiDi = ubidi_open(); -} - -nsBidi::~nsBidi() -{ - ubidi_close(mBiDi); -} - -nsresult nsBidi::SetPara(const char16_t *aText, int32_t aLength, - nsBidiLevel aParaLevel) -{ - UErrorCode error = U_ZERO_ERROR; - ubidi_setPara(mBiDi, reinterpret_cast(aText), aLength, - aParaLevel, nullptr, &error); - return ICUUtils::UErrorToNsResult(error); -} - -nsresult nsBidi::GetDirection(nsBidiDirection* aDirection) -{ - *aDirection = nsBidiDirection(ubidi_getDirection(mBiDi)); - return NS_OK; -} - -nsresult nsBidi::GetParaLevel(nsBidiLevel* aParaLevel) -{ - *aParaLevel = ubidi_getParaLevel(mBiDi); - return NS_OK; -} - -nsresult nsBidi::GetLogicalRun(int32_t aLogicalStart, int32_t* aLogicalLimit, - nsBidiLevel* aLevel) -{ - ubidi_getLogicalRun(mBiDi, aLogicalStart, aLogicalLimit, aLevel); - return NS_OK; -} - -nsresult nsBidi::CountRuns(int32_t* aRunCount) -{ - UErrorCode errorCode = U_ZERO_ERROR; - *aRunCount = ubidi_countRuns(mBiDi, &errorCode); - return ICUUtils::UErrorToNsResult(errorCode); -} - -nsresult nsBidi::GetVisualRun(int32_t aRunIndex, int32_t* aLogicalStart, - int32_t* aLength, nsBidiDirection* aDirection) -{ - *aDirection = nsBidiDirection(ubidi_getVisualRun(mBiDi, aRunIndex, - aLogicalStart, aLength)); - return NS_OK; -} - -nsresult nsBidi::ReorderVisual(const nsBidiLevel* aLevels, int32_t aLength, - int32_t* aIndexMap) -{ - ubidi_reorderVisual(aLevels, aLength, aIndexMap); - return NS_OK; -} diff --git a/layout/base/nsBidi.h b/layout/base/nsBidi.h index 28a2e39b1721..3a59435fe36b 100644 --- a/layout/base/nsBidi.h +++ b/layout/base/nsBidi.h @@ -8,6 +8,7 @@ #define nsBidi_h__ #include "unicode/ubidi.h" +#include "ICUUtils.h" #include "nsIFrame.h" // for nsBidiLevel/nsBidiDirection declarations // nsBidi implemented as a simple wrapper around the bidi reordering engine @@ -23,11 +24,16 @@ public: * The nsBidi object is initially empty. It is assigned * the Bidi properties of a paragraph by SetPara(). */ - explicit nsBidi(); + nsBidi() + { + mBiDi = ubidi_open(); + } /** @brief Destructor. */ - virtual ~nsBidi(); - + ~nsBidi() + { + ubidi_close(mBiDi); + } /** * Perform the Unicode Bidi algorithm. @@ -51,8 +57,14 @@ public: * Any other value between 0 and NSBIDI_MAX_EXPLICIT_LEVEL * is also valid, with odd levels indicating RTL. */ - nsresult SetPara(const char16_t *aText, int32_t aLength, - nsBidiLevel aParaLevel); + nsresult SetPara(const char16_t* aText, int32_t aLength, + nsBidiLevel aParaLevel) + { + UErrorCode error = U_ZERO_ERROR; + ubidi_setPara(mBiDi, reinterpret_cast(aText), aLength, + aParaLevel, nullptr, &error); + return ICUUtils::UErrorToNsResult(error); + } /** * Get the directionality of the text. @@ -63,7 +75,10 @@ public: * * @see nsBidiDirection */ - nsresult GetDirection(nsBidiDirection* aDirection); + nsBidiDirection GetDirection() + { + return nsBidiDirection(ubidi_getDirection(mBiDi)); + } /** * Get the paragraph level of the text. @@ -73,7 +88,10 @@ public: * * @see nsBidiLevel */ - nsresult GetParaLevel(nsBidiLevel* aParaLevel); + nsBidiLevel GetParaLevel() + { + return ubidi_getParaLevel(mBiDi); + } /** * Get a logical run. @@ -94,8 +112,11 @@ public: * This pointer can be nullptr if this * value is not necessary. */ - nsresult GetLogicalRun(int32_t aLogicalStart, int32_t* aLogicalLimit, - nsBidiLevel* aLevel); + void GetLogicalRun(int32_t aLogicalStart, int32_t* aLogicalLimit, + nsBidiLevel* aLevel) + { + ubidi_getLogicalRun(mBiDi, aLogicalStart, aLogicalLimit, aLevel); + } /** * Get the number of runs. @@ -107,7 +128,12 @@ public: * * @param aRunCount will receive the number of runs. */ - nsresult CountRuns(int32_t* aRunCount); + nsresult CountRuns(int32_t* aRunCount) + { + UErrorCode errorCode = U_ZERO_ERROR; + *aRunCount = ubidi_countRuns(mBiDi, &errorCode); + return ICUUtils::UErrorToNsResult(errorCode); + } /** * Get one run's logical start, length, and directionality, @@ -127,7 +153,7 @@ public: * @param aLength is the number of characters (at least one) in the run. * The pointer may be nullptr if this is not needed. * - * @param aDirection will receive the directionality of the run, + * @returns the directionality of the run, * NSBIDI_LTR==0 or NSBIDI_RTL==1, * never NSBIDI_MIXED. * @@ -139,7 +165,7 @@ public: * nsBidiDirection dir; * pBidi->CountRuns(&count); * for(i=0; iGetVisualRun(i, &logicalStart, &length, &dir); + * dir = pBidi->GetVisualRun(i, &logicalStart, &length); * if(NSBIDI_LTR==dir) { * do { // LTR * show_char(text[logicalStart++], visualIndex++); @@ -157,8 +183,12 @@ public: * modifier letters before base characters and second surrogates * before first ones. */ - nsresult GetVisualRun(int32_t aRunIndex, int32_t* aLogicalStart, - int32_t* aLength, nsBidiDirection* aDirection); + nsBidiDirection GetVisualRun(int32_t aRunIndex, + int32_t* aLogicalStart, int32_t* aLength) + { + return nsBidiDirection(ubidi_getVisualRun(mBiDi, aRunIndex, + aLogicalStart, aLength)); + } /** * This is a convenience function that does not use a nsBidi object. @@ -180,14 +210,16 @@ public: * The index map will result in * aIndexMap[aVisualIndex]==aLogicalIndex. */ - static nsresult ReorderVisual(const nsBidiLevel* aLevels, int32_t aLength, - int32_t* aIndexMap); + static void ReorderVisual(const nsBidiLevel* aLevels, int32_t aLength, + int32_t* aIndexMap) + { + ubidi_reorderVisual(aLevels, aLength, aIndexMap); + } private: nsBidi(const nsBidi&) = delete; void operator=(const nsBidi&) = delete; -protected: UBiDi* mBiDi; }; diff --git a/layout/base/nsBidiPresUtils.cpp b/layout/base/nsBidiPresUtils.cpp index 06b357b6ba57..035ba9fa5dd2 100644 --- a/layout/base/nsBidiPresUtils.cpp +++ b/layout/base/nsBidiPresUtils.cpp @@ -203,16 +203,14 @@ struct MOZ_STACK_CLASS BidiParagraphData { nsBidiLevel paraLevel = mParaLevel; if (paraLevel == NSBIDI_DEFAULT_LTR || paraLevel == NSBIDI_DEFAULT_RTL) { - mPresContext->GetBidiEngine().GetParaLevel(¶Level); + paraLevel = mPresContext->GetBidiEngine().GetParaLevel(); } return paraLevel; } nsBidiDirection GetDirection() { - nsBidiDirection dir; - mPresContext->GetBidiEngine().GetDirection(&dir); - return dir; + return mPresContext->GetBidiEngine().GetDirection(); } nsresult CountRuns(int32_t *runCount) @@ -220,16 +218,15 @@ struct MOZ_STACK_CLASS BidiParagraphData return mPresContext->GetBidiEngine().CountRuns(runCount); } - nsresult GetLogicalRun(int32_t aLogicalStart, - int32_t* aLogicalLimit, - nsBidiLevel* aLevel) + void GetLogicalRun(int32_t aLogicalStart, + int32_t* aLogicalLimit, + nsBidiLevel* aLevel) { - nsresult rv = - mPresContext->GetBidiEngine().GetLogicalRun(aLogicalStart, - aLogicalLimit, aLevel); - if (mIsVisual || NS_FAILED(rv)) + mPresContext->GetBidiEngine().GetLogicalRun(aLogicalStart, + aLogicalLimit, aLevel); + if (mIsVisual) { *aLevel = GetParaLevel(); - return rv; + } } void ResetData() @@ -893,10 +890,7 @@ nsBidiPresUtils::ResolveParagraph(BidiParagraphData* aBpd) break; } int32_t lineOffset = logicalLimit; - if (NS_FAILED(aBpd->GetLogicalRun( - lineOffset, &logicalLimit, &embeddingLevel) ) ) { - break; - } + aBpd->GetLogicalRun(lineOffset, &logicalLimit, &embeddingLevel); runLength = logicalLimit - lineOffset; } // if (runLength <= 0) @@ -2125,15 +2119,10 @@ nsresult nsBidiPresUtils::ProcessText(const char16_t* aText, } for (i = 0; i < runCount; i++) { - nsBidiDirection dir; - rv = aBidiEngine->GetVisualRun(i, &start, &length, &dir); - if (NS_FAILED(rv)) - return rv; + nsBidiDirection dir = aBidiEngine->GetVisualRun(i, &start, &length); nsBidiLevel level; - rv = aBidiEngine->GetLogicalRun(start, &limit, &level); - if (NS_FAILED(rv)) - return rv; + aBidiEngine->GetLogicalRun(start, &limit, &level); dir = DIRECTION_FROM_LEVEL(level); int32_t subRunLength = limit - start; From 3bcb820ee64d02773f6c3b79897ff52a0b4236b5 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Fri, 22 Sep 2017 10:37:17 +0100 Subject: [PATCH 16/37] Bug 1402053 - Remove our obsolete implementation of Unicode normalization, now that we can use ICU on all platforms. r=m_kato --- intl/unicharutil/moz.build | 11 +- intl/unicharutil/normalization_data.h | 5247 ------------------ intl/unicharutil/nsUnicodeNormalizer.cpp | 767 +-- intl/unicharutil/nsUnicodeNormalizer.h | 11 +- intl/unicharutil/nsUnicodeNormalizer_ICU.cpp | 99 - 5 files changed, 82 insertions(+), 6053 deletions(-) delete mode 100644 intl/unicharutil/normalization_data.h delete mode 100644 intl/unicharutil/nsUnicodeNormalizer_ICU.cpp diff --git a/intl/unicharutil/moz.build b/intl/unicharutil/moz.build index 8a99232a2e37..8944c94536ca 100644 --- a/intl/unicharutil/moz.build +++ b/intl/unicharutil/moz.build @@ -18,14 +18,9 @@ EXPORTS += [ 'nsUnicodeNormalizer.h', ] -if CONFIG['ENABLE_INTL_API']: - UNIFIED_SOURCES += [ - 'nsUnicodeNormalizer_ICU.cpp', - ] -else: - UNIFIED_SOURCES += [ - 'nsUnicodeNormalizer.cpp', - ] +UNIFIED_SOURCES += [ + 'nsUnicodeNormalizer.cpp', +] FINAL_LIBRARY = 'xul' diff --git a/intl/unicharutil/normalization_data.h b/intl/unicharutil/normalization_data.h deleted file mode 100644 index c78337a28cfe..000000000000 --- a/intl/unicharutil/normalization_data.h +++ /dev/null @@ -1,5247 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ - -/* This file is modified from JPNIC's mDNKit, it is under both MPL and - * JPNIC's license. - */ - -/* 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/. */ - -/* - * Copyright (c) 2000,2002 Japan Network Information Center. - * All rights reserved. - * - * By using this file, you agree to the terms and conditions set forth bellow. - * - * LICENSE TERMS AND CONDITIONS - * - * The following License Terms and Conditions apply, unless a different - * license is obtained from Japan Network Information Center ("JPNIC"), - * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda, - * Chiyoda-ku, Tokyo 101-0047, Japan. - * - * 1. Use, Modification and Redistribution (including distribution of any - * modified or derived work) in source and/or binary forms is permitted - * under this License Terms and Conditions. - * - * 2. Redistribution of source code must retain the copyright notices as they - * appear in each source code file, this License Terms and Conditions. - * - * 3. Redistribution in binary form must reproduce the Copyright Notice, - * this License Terms and Conditions, in the documentation and/or other - * materials provided with the distribution. For the purposes of binary - * distribution the "Copyright Notice" refers to the following language: - * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved." - * - * 4. The name of JPNIC may not be used to endorse or promote products - * derived from this Software without specific prior written approval of - * JPNIC. - * - * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - */ - -/* $Id: normalization_data.h,v 1.1 2005/04/05 23:00:13 jshin%mailaps.org Exp $ */ -/* $-Id: generate_normalize_data.pl,v 1.9 2002/11/29 09:08:13 ishisone Exp -$ */ -/* - * Do not edit this file! - * This file is generated from UnicodeData.txt, CompositionExclusions-1.txt, - * SpecialCasing.txt and CaseFolding.txt. - */ - - -/* - * Canonical Class - */ - -#define CANON_CLASS_BITS_0 9 -#define CANON_CLASS_BITS_1 7 -#define CANON_CLASS_BITS_2 5 - -static const char16_t canon_class_imap[] = { - 272, 400, 528, 656, 784, 784, 784, 784, - 784, 784, 912, 784, 784, 784, 784, 1040, - 1168, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 1296, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 3, 4, 0, 0, 0, 0, - 0, 0, 0, 0, 5, 0, 0, 0, - 0, 0, 0, 0, 6, 7, 8, 0, - 9, 0, 10, 11, 0, 0, 12, 13, - 14, 15, 16, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 17, 18, 0, 0, 17, 19, 0, - 0, 17, 19, 0, 0, 17, 19, 0, - 0, 17, 19, 0, 0, 0, 19, 0, - 0, 0, 20, 0, 0, 17, 19, 0, - 0, 0, 19, 0, 0, 0, 21, 0, - 0, 22, 23, 0, 0, 24, 25, 0, - 26, 27, 0, 28, 29, 0, 30, 0, - 0, 31, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 32, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 33, 33, 0, 0, 0, 0, 34, 0, - 0, 0, 0, 0, 0, 35, 0, 0, - 0, 36, 0, 0, 0, 0, 0, 0, - 37, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 38, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 39, 40, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 41, 0, 0, 42, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 43, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 44, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 45, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 46, 47, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 48, 49, 50, 0, 0, - 0, 0, 51, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; - -static const struct { - unsigned char tbl[32]; -} canon_class_table[] = { - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, - 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 232, - 220, 220, 220, 220, 232, 216, 220, 220, 220, 220, - }}, - {{ - 220, 202, 202, 220, 220, 220, 220, 202, 202, 220, 220, - 220, 220, 220, 220, 220, 220, 220, 220, 220, 1, 1, - 1, 1, 1, 220, 220, 220, 220, 230, 230, 230, - }}, - {{ - 230, 230, 230, 230, 230, 240, 230, 220, 220, 220, 230, - 230, 230, 220, 220, 0, 230, 230, 230, 220, 220, 220, - 220, 230, 232, 220, 220, 230, 233, 234, 234, 233, - }}, - {{ - 234, 234, 233, 230, 230, 230, 230, 230, 230, 230, 230, - 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 230, 230, 230, 230, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 220, 230, 230, 230, 230, - 220, 230, 230, 230, 222, 220, 230, 230, 230, 230, - }}, - {{ - 230, 230, 220, 220, 220, 220, 220, 220, 230, 230, 220, - 230, 230, 222, 228, 230, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 0, 20, 21, 22, 0, 23, - }}, - {{ - 0, 24, 25, 0, 230, 220, 0, 18, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 27, 28, 29, 30, 31, 32, 33, 34, 230, 230, 220, - 220, 230, 230, 230, 230, 230, 220, 230, 230, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 35, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 230, 230, 230, 230, 230, 230, 230, 0, 0, 230, - }}, - {{ - 230, 230, 230, 220, 230, 0, 0, 230, 230, 0, 220, - 230, 230, 220, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 230, 220, 230, 230, 220, 230, - 230, 220, 220, 220, 230, 220, 220, 230, 220, 230, - }}, - {{ - 230, 230, 220, 230, 220, 230, 220, 230, 220, 230, 230, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 9, 0, 0, 0, 230, 220, 230, 230, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 84, - 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 103, 103, 9, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 107, 107, 107, - 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 118, 118, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 122, 122, 122, - 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 220, 220, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, - 0, 220, 0, 216, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 129, 130, 0, 132, 0, - 0, 0, 0, 0, 130, 130, 130, 130, 0, 0, - }}, - {{ - 130, 0, 230, 230, 9, 0, 230, 230, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 220, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 7, 0, 9, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 222, 230, 220, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 230, 220, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 230, 230, 220, 230, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 230, 230, 1, 1, 230, 230, - 230, 230, 1, 1, 1, 230, 230, 0, 0, 0, - }}, - {{ - 0, 230, 0, 0, 0, 1, 1, 230, 220, 230, 1, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, - 228, 232, 222, 224, 224, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, - }}, - {{ - 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 220, 0, 230, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 230, 1, 220, 0, 0, 0, 0, 9, - }}, - {{ - 0, 0, 0, 0, 0, 216, 216, 1, 1, 1, 0, - 0, 0, 226, 216, 216, 216, 216, 216, 0, 0, 0, - 0, 0, 0, 0, 0, 220, 220, 220, 220, 220, - }}, - {{ - 220, 220, 220, 0, 0, 230, 230, 230, 230, 230, 220, - 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, - 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 230, 230, 230, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }}, -}; - -/* - * Canonical Composition - */ - -#define CANON_COMPOSE_BITS_0 9 -#define CANON_COMPOSE_BITS_1 7 -#define CANON_COMPOSE_BITS_2 5 - -static const char16_t compose_imap[] = { - 272, 400, 528, 656, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 0, 1, 2, 3, 0, 4, 5, 6, - 7, 0, 8, 9, 0, 10, 0, 11, - 0, 12, 0, 0, 13, 0, 0, 0, - 0, 0, 0, 0, 14, 15, 16, 0, - 17, 18, 19, 20, 0, 0, 21, 22, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 23, 24, 0, 0, 0, 25, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 26, 0, 0, 0, 0, 27, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 28, 0, 29, 0, 30, 0, - 0, 0, 31, 0, 0, 32, 33, 0, - 0, 0, 34, 0, 0, 0, 35, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 36, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 37, 38, 39, 0, 40, 41, 0, - 42, 43, 44, 45, 0, 46, 47, 48, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 49, 0, 50, 0, - 51, 52, 53, 54, 55, 56, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 57, 58, 59, 60, 61, 62, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; - -static const struct { - uint32_t tbl[32]; -} compose_table[] = { - {{ - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 65537, 65538, 65539, 0, - }}, - {{ - 0, 1048580, 196628, 327703, 393244, 1114146, 65587, - 458804, 458811, 983106, 65617, 327762, 393303, 196701, - 589920, 1048681, 131193, 0, 524411, 458883, 458890, - 1245329, 131236, 393382, 131244, 589998, 393399, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 1048765, 196813, 327888, 393429, 1114331, 65772, - 458989, 524532, 917756, 131338, 327948, 393489, 196887, - 590106, 1048867, 131379, 0, 524597, 459069, 524612, - 1245516, 131423, 459105, 131432, 655722, 393588, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, - 0, 196986, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 262525, 0, 65921, 65922, 131459, - 65925, 0, 0, 262534, 0, 0, 0, - 0, 65930, 0, 0, 0, 0, 262539, - 197007, 65938, 0, 65939, 0, 0, 0, - 262548, 0, 0, 0, - }}, - {{ - 0, 0, 262552, 0, 65948, 65949, 131486, - 65952, 0, 0, 262561, 0, 0, 0, - 0, 65957, 0, 0, 0, 0, 262566, - 197034, 65965, 0, 65966, 0, 0, 0, - 262575, 0, 0, 0, - }}, - {{ - 0, 0, 262579, 262583, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 131515, 131517, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 131519, 131521, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 65987, 65988, - 0, 0, 0, 0, - }}, - {{ - 65989, 65990, 0, 0, 0, 0, 0, - 0, 65991, 65992, 65993, 65994, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 65995, - }}, - {{ - 328140, 328145, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 328150, 328155, 0, 0, 0, 0, - 0, 0, 66016, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 66017, 66018, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 66019, - 66020, 66021, 66022, 0, 0, 0, 0, - 66023, 66024, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 66025, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 459242, 0, 0, 0, - 262641, 0, 328181, 0, 459258, 0, 0, - 0, 0, 0, 262657, - }}, - {{ - 0, 66053, 0, 0, 0, 393734, 0, - 0, 0, 328204, 0, 0, 66065, 0, - 66066, 0, 0, 524819, 0, 0, 0, - 262683, 0, 393759, 0, 524837, 0, 0, - 0, 0, 0, 262701, - }}, - {{ - 0, 131633, 0, 0, 0, 524851, 0, - 0, 0, 393787, 197185, 197188, 0, 0, - 66119, 0, 0, 0, 131656, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 66122, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 131659, 0, 0, 66125, 0, - 197198, 131665, 66131, 262740, 0, 66136, 0, - 0, 0, 66137, 0, - }}, - {{ - 0, 0, 0, 262746, 0, 0, 0, - 66142, 0, 0, 0, 66143, 0, 66144, - 0, 0, 131681, 0, 0, 66147, 0, - 197220, 131687, 66153, 262762, 0, 66158, 0, - 0, 0, 66159, 0, - }}, - {{ - 0, 0, 0, 262768, 0, 0, 0, - 66164, 0, 0, 0, 66165, 0, 66166, - 0, 0, 0, 0, 0, 0, 0, - 0, 66167, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 66168, - 66169, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 66170, 66171, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, - 0, 66172, 66173, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, - 197246, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, - 0, 66177, 0, 66178, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 66179, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 66180, 0, 0, - 66181, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, - 0, 66182, 0, 0, 0, 0, 0, - 0, 0, 66183, 0, 0, 66184, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, - 131721, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, - 197259, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 66190, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 131727, - 66193, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 66194, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 66195, - }}, - {{ - 0, 0, 0, 0, 0, 0, 197268, - 0, 0, 0, 66199, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 131736, - 66202, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 197275, 0, 0, - 66206, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 66207, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 66208, 66209, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 66210, 66211, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 66212, 66213, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 131750, 131752, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 66218, 66219, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 66220, 66221, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 262830, 262834, 66230, 66231, 66232, 66233, 66234, - 66235, 262844, 262848, 66244, 66245, 66246, 66247, - 66248, 66249, 131786, 131788, 0, 0, 0, - 0, 0, 0, 131790, 131792, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 262866, 262870, 66266, 66267, 66268, 66269, 66270, - 66271, 262880, 262884, 66280, 66281, 66282, 66283, - 66284, 66285, 197358, 197361, 0, 0, 0, - 0, 0, 0, 197364, 197367, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 131834, 131836, 0, 0, 0, 0, 0, - 0, 131838, 131840, 0, 0, 0, 0, - 0, 0, 197378, 197381, 0, 0, 0, - 0, 0, 0, 0, 197384, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 262923, 262927, 66323, 66324, 66325, 66326, 66327, - 66328, 262937, 262941, 66337, 66338, 66339, 66340, - 66341, 66342, 66343, 0, 0, 0, 66344, - 0, 0, 0, 0, 0, 0, 0, - 66345, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 66346, 0, 0, 0, 0, 0, - 0, 0, 0, 197419, - }}, - {{ - 0, 0, 0, 0, 0, 0, 66350, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 66351, 0, 0, 0, 0, 0, - 0, 0, 197424, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 66355, 0, 66356, 0, 66357, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 66358, 0, 66359, 0, 66360, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 66361, 0, 0, 0, - 0, 66362, 0, 0, 66363, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 66364, 0, 66365, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 66366, 0, 0, 0, - }}, - {{ - 0, 0, 0, 66367, 0, 66368, 0, - 0, 66369, 0, 0, 0, 0, 66370, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 66371, 0, 0, 66372, 66373, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 66374, 66375, 0, - 0, 66376, 66377, 0, 0, 66378, 66379, - 66380, 66381, 0, 0, - }}, - {{ - 0, 0, 66382, 66383, 0, 0, 66384, - 66385, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 66386, 66387, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 66388, 0, 0, 0, 0, - 0, 66389, 66390, 0, 66391, 0, 0, - 0, 0, 0, 0, 66392, 66393, 66394, - 66395, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 66396, - 0, 0, 0, 0, 66397, 0, 66398, - 0, 66399, 0, 66400, 0, 66401, 0, - 66402, 0, 66403, 0, 66404, 0, 66405, - 0, 66406, 0, 66407, - }}, - {{ - 0, 66408, 0, 0, 66409, 0, 66410, - 0, 66411, 0, 0, 0, 0, 0, - 0, 131948, 0, 0, 131950, 0, 0, - 131952, 0, 0, 131954, 0, 0, 131956, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 66422, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 66423, - 0, 0, 0, 0, 66424, 0, 66425, - 0, 66426, 0, 66427, 0, 66428, 0, - 66429, 0, 66430, 0, 66431, 0, 66432, - 0, 66433, 0, 66434, - }}, - {{ - 0, 66435, 0, 0, 66436, 0, 66437, - 0, 66438, 0, 0, 0, 0, 0, - 0, 131975, 0, 0, 131977, 0, 0, - 131979, 0, 0, 131981, 0, 0, 131983, - 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 66449, 66450, 66451, 66452, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 66453, 0, 0, - }}, -}; - -static const struct composition compose_seq[] = { - { 0x00000000, 0x00000000 }, { 0x00000338, 0x0000226e }, - { 0x00000338, 0x00002260 }, { 0x00000338, 0x0000226f }, - { 0x00000300, 0x000000c0 }, { 0x00000301, 0x000000c1 }, - { 0x00000302, 0x000000c2 }, { 0x00000303, 0x000000c3 }, - { 0x00000304, 0x00000100 }, { 0x00000306, 0x00000102 }, - { 0x00000307, 0x00000226 }, { 0x00000308, 0x000000c4 }, - { 0x00000309, 0x00001ea2 }, { 0x0000030a, 0x000000c5 }, - { 0x0000030c, 0x000001cd }, { 0x0000030f, 0x00000200 }, - { 0x00000311, 0x00000202 }, { 0x00000323, 0x00001ea0 }, - { 0x00000325, 0x00001e00 }, { 0x00000328, 0x00000104 }, - { 0x00000307, 0x00001e02 }, { 0x00000323, 0x00001e04 }, - { 0x00000331, 0x00001e06 }, { 0x00000301, 0x00000106 }, - { 0x00000302, 0x00000108 }, { 0x00000307, 0x0000010a }, - { 0x0000030c, 0x0000010c }, { 0x00000327, 0x000000c7 }, - { 0x00000307, 0x00001e0a }, { 0x0000030c, 0x0000010e }, - { 0x00000323, 0x00001e0c }, { 0x00000327, 0x00001e10 }, - { 0x0000032d, 0x00001e12 }, { 0x00000331, 0x00001e0e }, - { 0x00000300, 0x000000c8 }, { 0x00000301, 0x000000c9 }, - { 0x00000302, 0x000000ca }, { 0x00000303, 0x00001ebc }, - { 0x00000304, 0x00000112 }, { 0x00000306, 0x00000114 }, - { 0x00000307, 0x00000116 }, { 0x00000308, 0x000000cb }, - { 0x00000309, 0x00001eba }, { 0x0000030c, 0x0000011a }, - { 0x0000030f, 0x00000204 }, { 0x00000311, 0x00000206 }, - { 0x00000323, 0x00001eb8 }, { 0x00000327, 0x00000228 }, - { 0x00000328, 0x00000118 }, { 0x0000032d, 0x00001e18 }, - { 0x00000330, 0x00001e1a }, { 0x00000307, 0x00001e1e }, - { 0x00000301, 0x000001f4 }, { 0x00000302, 0x0000011c }, - { 0x00000304, 0x00001e20 }, { 0x00000306, 0x0000011e }, - { 0x00000307, 0x00000120 }, { 0x0000030c, 0x000001e6 }, - { 0x00000327, 0x00000122 }, { 0x00000302, 0x00000124 }, - { 0x00000307, 0x00001e22 }, { 0x00000308, 0x00001e26 }, - { 0x0000030c, 0x0000021e }, { 0x00000323, 0x00001e24 }, - { 0x00000327, 0x00001e28 }, { 0x0000032e, 0x00001e2a }, - { 0x00000300, 0x000000cc }, { 0x00000301, 0x000000cd }, - { 0x00000302, 0x000000ce }, { 0x00000303, 0x00000128 }, - { 0x00000304, 0x0000012a }, { 0x00000306, 0x0000012c }, - { 0x00000307, 0x00000130 }, { 0x00000308, 0x000000cf }, - { 0x00000309, 0x00001ec8 }, { 0x0000030c, 0x000001cf }, - { 0x0000030f, 0x00000208 }, { 0x00000311, 0x0000020a }, - { 0x00000323, 0x00001eca }, { 0x00000328, 0x0000012e }, - { 0x00000330, 0x00001e2c }, { 0x00000302, 0x00000134 }, - { 0x00000301, 0x00001e30 }, { 0x0000030c, 0x000001e8 }, - { 0x00000323, 0x00001e32 }, { 0x00000327, 0x00000136 }, - { 0x00000331, 0x00001e34 }, { 0x00000301, 0x00000139 }, - { 0x0000030c, 0x0000013d }, { 0x00000323, 0x00001e36 }, - { 0x00000327, 0x0000013b }, { 0x0000032d, 0x00001e3c }, - { 0x00000331, 0x00001e3a }, { 0x00000301, 0x00001e3e }, - { 0x00000307, 0x00001e40 }, { 0x00000323, 0x00001e42 }, - { 0x00000300, 0x000001f8 }, { 0x00000301, 0x00000143 }, - { 0x00000303, 0x000000d1 }, { 0x00000307, 0x00001e44 }, - { 0x0000030c, 0x00000147 }, { 0x00000323, 0x00001e46 }, - { 0x00000327, 0x00000145 }, { 0x0000032d, 0x00001e4a }, - { 0x00000331, 0x00001e48 }, { 0x00000300, 0x000000d2 }, - { 0x00000301, 0x000000d3 }, { 0x00000302, 0x000000d4 }, - { 0x00000303, 0x000000d5 }, { 0x00000304, 0x0000014c }, - { 0x00000306, 0x0000014e }, { 0x00000307, 0x0000022e }, - { 0x00000308, 0x000000d6 }, { 0x00000309, 0x00001ece }, - { 0x0000030b, 0x00000150 }, { 0x0000030c, 0x000001d1 }, - { 0x0000030f, 0x0000020c }, { 0x00000311, 0x0000020e }, - { 0x0000031b, 0x000001a0 }, { 0x00000323, 0x00001ecc }, - { 0x00000328, 0x000001ea }, { 0x00000301, 0x00001e54 }, - { 0x00000307, 0x00001e56 }, { 0x00000301, 0x00000154 }, - { 0x00000307, 0x00001e58 }, { 0x0000030c, 0x00000158 }, - { 0x0000030f, 0x00000210 }, { 0x00000311, 0x00000212 }, - { 0x00000323, 0x00001e5a }, { 0x00000327, 0x00000156 }, - { 0x00000331, 0x00001e5e }, { 0x00000301, 0x0000015a }, - { 0x00000302, 0x0000015c }, { 0x00000307, 0x00001e60 }, - { 0x0000030c, 0x00000160 }, { 0x00000323, 0x00001e62 }, - { 0x00000326, 0x00000218 }, { 0x00000327, 0x0000015e }, - { 0x00000307, 0x00001e6a }, { 0x0000030c, 0x00000164 }, - { 0x00000323, 0x00001e6c }, { 0x00000326, 0x0000021a }, - { 0x00000327, 0x00000162 }, { 0x0000032d, 0x00001e70 }, - { 0x00000331, 0x00001e6e }, { 0x00000300, 0x000000d9 }, - { 0x00000301, 0x000000da }, { 0x00000302, 0x000000db }, - { 0x00000303, 0x00000168 }, { 0x00000304, 0x0000016a }, - { 0x00000306, 0x0000016c }, { 0x00000308, 0x000000dc }, - { 0x00000309, 0x00001ee6 }, { 0x0000030a, 0x0000016e }, - { 0x0000030b, 0x00000170 }, { 0x0000030c, 0x000001d3 }, - { 0x0000030f, 0x00000214 }, { 0x00000311, 0x00000216 }, - { 0x0000031b, 0x000001af }, { 0x00000323, 0x00001ee4 }, - { 0x00000324, 0x00001e72 }, { 0x00000328, 0x00000172 }, - { 0x0000032d, 0x00001e76 }, { 0x00000330, 0x00001e74 }, - { 0x00000303, 0x00001e7c }, { 0x00000323, 0x00001e7e }, - { 0x00000300, 0x00001e80 }, { 0x00000301, 0x00001e82 }, - { 0x00000302, 0x00000174 }, { 0x00000307, 0x00001e86 }, - { 0x00000308, 0x00001e84 }, { 0x00000323, 0x00001e88 }, - { 0x00000307, 0x00001e8a }, { 0x00000308, 0x00001e8c }, - { 0x00000300, 0x00001ef2 }, { 0x00000301, 0x000000dd }, - { 0x00000302, 0x00000176 }, { 0x00000303, 0x00001ef8 }, - { 0x00000304, 0x00000232 }, { 0x00000307, 0x00001e8e }, - { 0x00000308, 0x00000178 }, { 0x00000309, 0x00001ef6 }, - { 0x00000323, 0x00001ef4 }, { 0x00000301, 0x00000179 }, - { 0x00000302, 0x00001e90 }, { 0x00000307, 0x0000017b }, - { 0x0000030c, 0x0000017d }, { 0x00000323, 0x00001e92 }, - { 0x00000331, 0x00001e94 }, { 0x00000300, 0x000000e0 }, - { 0x00000301, 0x000000e1 }, { 0x00000302, 0x000000e2 }, - { 0x00000303, 0x000000e3 }, { 0x00000304, 0x00000101 }, - { 0x00000306, 0x00000103 }, { 0x00000307, 0x00000227 }, - { 0x00000308, 0x000000e4 }, { 0x00000309, 0x00001ea3 }, - { 0x0000030a, 0x000000e5 }, { 0x0000030c, 0x000001ce }, - { 0x0000030f, 0x00000201 }, { 0x00000311, 0x00000203 }, - { 0x00000323, 0x00001ea1 }, { 0x00000325, 0x00001e01 }, - { 0x00000328, 0x00000105 }, { 0x00000307, 0x00001e03 }, - { 0x00000323, 0x00001e05 }, { 0x00000331, 0x00001e07 }, - { 0x00000301, 0x00000107 }, { 0x00000302, 0x00000109 }, - { 0x00000307, 0x0000010b }, { 0x0000030c, 0x0000010d }, - { 0x00000327, 0x000000e7 }, { 0x00000307, 0x00001e0b }, - { 0x0000030c, 0x0000010f }, { 0x00000323, 0x00001e0d }, - { 0x00000327, 0x00001e11 }, { 0x0000032d, 0x00001e13 }, - { 0x00000331, 0x00001e0f }, { 0x00000300, 0x000000e8 }, - { 0x00000301, 0x000000e9 }, { 0x00000302, 0x000000ea }, - { 0x00000303, 0x00001ebd }, { 0x00000304, 0x00000113 }, - { 0x00000306, 0x00000115 }, { 0x00000307, 0x00000117 }, - { 0x00000308, 0x000000eb }, { 0x00000309, 0x00001ebb }, - { 0x0000030c, 0x0000011b }, { 0x0000030f, 0x00000205 }, - { 0x00000311, 0x00000207 }, { 0x00000323, 0x00001eb9 }, - { 0x00000327, 0x00000229 }, { 0x00000328, 0x00000119 }, - { 0x0000032d, 0x00001e19 }, { 0x00000330, 0x00001e1b }, - { 0x00000307, 0x00001e1f }, { 0x00000301, 0x000001f5 }, - { 0x00000302, 0x0000011d }, { 0x00000304, 0x00001e21 }, - { 0x00000306, 0x0000011f }, { 0x00000307, 0x00000121 }, - { 0x0000030c, 0x000001e7 }, { 0x00000327, 0x00000123 }, - { 0x00000302, 0x00000125 }, { 0x00000307, 0x00001e23 }, - { 0x00000308, 0x00001e27 }, { 0x0000030c, 0x0000021f }, - { 0x00000323, 0x00001e25 }, { 0x00000327, 0x00001e29 }, - { 0x0000032e, 0x00001e2b }, { 0x00000331, 0x00001e96 }, - { 0x00000300, 0x000000ec }, { 0x00000301, 0x000000ed }, - { 0x00000302, 0x000000ee }, { 0x00000303, 0x00000129 }, - { 0x00000304, 0x0000012b }, { 0x00000306, 0x0000012d }, - { 0x00000308, 0x000000ef }, { 0x00000309, 0x00001ec9 }, - { 0x0000030c, 0x000001d0 }, { 0x0000030f, 0x00000209 }, - { 0x00000311, 0x0000020b }, { 0x00000323, 0x00001ecb }, - { 0x00000328, 0x0000012f }, { 0x00000330, 0x00001e2d }, - { 0x00000302, 0x00000135 }, { 0x0000030c, 0x000001f0 }, - { 0x00000301, 0x00001e31 }, { 0x0000030c, 0x000001e9 }, - { 0x00000323, 0x00001e33 }, { 0x00000327, 0x00000137 }, - { 0x00000331, 0x00001e35 }, { 0x00000301, 0x0000013a }, - { 0x0000030c, 0x0000013e }, { 0x00000323, 0x00001e37 }, - { 0x00000327, 0x0000013c }, { 0x0000032d, 0x00001e3d }, - { 0x00000331, 0x00001e3b }, { 0x00000301, 0x00001e3f }, - { 0x00000307, 0x00001e41 }, { 0x00000323, 0x00001e43 }, - { 0x00000300, 0x000001f9 }, { 0x00000301, 0x00000144 }, - { 0x00000303, 0x000000f1 }, { 0x00000307, 0x00001e45 }, - { 0x0000030c, 0x00000148 }, { 0x00000323, 0x00001e47 }, - { 0x00000327, 0x00000146 }, { 0x0000032d, 0x00001e4b }, - { 0x00000331, 0x00001e49 }, { 0x00000300, 0x000000f2 }, - { 0x00000301, 0x000000f3 }, { 0x00000302, 0x000000f4 }, - { 0x00000303, 0x000000f5 }, { 0x00000304, 0x0000014d }, - { 0x00000306, 0x0000014f }, { 0x00000307, 0x0000022f }, - { 0x00000308, 0x000000f6 }, { 0x00000309, 0x00001ecf }, - { 0x0000030b, 0x00000151 }, { 0x0000030c, 0x000001d2 }, - { 0x0000030f, 0x0000020d }, { 0x00000311, 0x0000020f }, - { 0x0000031b, 0x000001a1 }, { 0x00000323, 0x00001ecd }, - { 0x00000328, 0x000001eb }, { 0x00000301, 0x00001e55 }, - { 0x00000307, 0x00001e57 }, { 0x00000301, 0x00000155 }, - { 0x00000307, 0x00001e59 }, { 0x0000030c, 0x00000159 }, - { 0x0000030f, 0x00000211 }, { 0x00000311, 0x00000213 }, - { 0x00000323, 0x00001e5b }, { 0x00000327, 0x00000157 }, - { 0x00000331, 0x00001e5f }, { 0x00000301, 0x0000015b }, - { 0x00000302, 0x0000015d }, { 0x00000307, 0x00001e61 }, - { 0x0000030c, 0x00000161 }, { 0x00000323, 0x00001e63 }, - { 0x00000326, 0x00000219 }, { 0x00000327, 0x0000015f }, - { 0x00000307, 0x00001e6b }, { 0x00000308, 0x00001e97 }, - { 0x0000030c, 0x00000165 }, { 0x00000323, 0x00001e6d }, - { 0x00000326, 0x0000021b }, { 0x00000327, 0x00000163 }, - { 0x0000032d, 0x00001e71 }, { 0x00000331, 0x00001e6f }, - { 0x00000300, 0x000000f9 }, { 0x00000301, 0x000000fa }, - { 0x00000302, 0x000000fb }, { 0x00000303, 0x00000169 }, - { 0x00000304, 0x0000016b }, { 0x00000306, 0x0000016d }, - { 0x00000308, 0x000000fc }, { 0x00000309, 0x00001ee7 }, - { 0x0000030a, 0x0000016f }, { 0x0000030b, 0x00000171 }, - { 0x0000030c, 0x000001d4 }, { 0x0000030f, 0x00000215 }, - { 0x00000311, 0x00000217 }, { 0x0000031b, 0x000001b0 }, - { 0x00000323, 0x00001ee5 }, { 0x00000324, 0x00001e73 }, - { 0x00000328, 0x00000173 }, { 0x0000032d, 0x00001e77 }, - { 0x00000330, 0x00001e75 }, { 0x00000303, 0x00001e7d }, - { 0x00000323, 0x00001e7f }, { 0x00000300, 0x00001e81 }, - { 0x00000301, 0x00001e83 }, { 0x00000302, 0x00000175 }, - { 0x00000307, 0x00001e87 }, { 0x00000308, 0x00001e85 }, - { 0x0000030a, 0x00001e98 }, { 0x00000323, 0x00001e89 }, - { 0x00000307, 0x00001e8b }, { 0x00000308, 0x00001e8d }, - { 0x00000300, 0x00001ef3 }, { 0x00000301, 0x000000fd }, - { 0x00000302, 0x00000177 }, { 0x00000303, 0x00001ef9 }, - { 0x00000304, 0x00000233 }, { 0x00000307, 0x00001e8f }, - { 0x00000308, 0x000000ff }, { 0x00000309, 0x00001ef7 }, - { 0x0000030a, 0x00001e99 }, { 0x00000323, 0x00001ef5 }, - { 0x00000301, 0x0000017a }, { 0x00000302, 0x00001e91 }, - { 0x00000307, 0x0000017c }, { 0x0000030c, 0x0000017e }, - { 0x00000323, 0x00001e93 }, { 0x00000331, 0x00001e95 }, - { 0x00000300, 0x00001fed }, { 0x00000301, 0x00000385 }, - { 0x00000342, 0x00001fc1 }, { 0x00000300, 0x00001ea6 }, - { 0x00000301, 0x00001ea4 }, { 0x00000303, 0x00001eaa }, - { 0x00000309, 0x00001ea8 }, { 0x00000304, 0x000001de }, - { 0x00000301, 0x000001fa }, { 0x00000301, 0x000001fc }, - { 0x00000304, 0x000001e2 }, { 0x00000301, 0x00001e08 }, - { 0x00000300, 0x00001ec0 }, { 0x00000301, 0x00001ebe }, - { 0x00000303, 0x00001ec4 }, { 0x00000309, 0x00001ec2 }, - { 0x00000301, 0x00001e2e }, { 0x00000300, 0x00001ed2 }, - { 0x00000301, 0x00001ed0 }, { 0x00000303, 0x00001ed6 }, - { 0x00000309, 0x00001ed4 }, { 0x00000301, 0x00001e4c }, - { 0x00000304, 0x0000022c }, { 0x00000308, 0x00001e4e }, - { 0x00000304, 0x0000022a }, { 0x00000301, 0x000001fe }, - { 0x00000300, 0x000001db }, { 0x00000301, 0x000001d7 }, - { 0x00000304, 0x000001d5 }, { 0x0000030c, 0x000001d9 }, - { 0x00000300, 0x00001ea7 }, { 0x00000301, 0x00001ea5 }, - { 0x00000303, 0x00001eab }, { 0x00000309, 0x00001ea9 }, - { 0x00000304, 0x000001df }, { 0x00000301, 0x000001fb }, - { 0x00000301, 0x000001fd }, { 0x00000304, 0x000001e3 }, - { 0x00000301, 0x00001e09 }, { 0x00000300, 0x00001ec1 }, - { 0x00000301, 0x00001ebf }, { 0x00000303, 0x00001ec5 }, - { 0x00000309, 0x00001ec3 }, { 0x00000301, 0x00001e2f }, - { 0x00000300, 0x00001ed3 }, { 0x00000301, 0x00001ed1 }, - { 0x00000303, 0x00001ed7 }, { 0x00000309, 0x00001ed5 }, - { 0x00000301, 0x00001e4d }, { 0x00000304, 0x0000022d }, - { 0x00000308, 0x00001e4f }, { 0x00000304, 0x0000022b }, - { 0x00000301, 0x000001ff }, { 0x00000300, 0x000001dc }, - { 0x00000301, 0x000001d8 }, { 0x00000304, 0x000001d6 }, - { 0x0000030c, 0x000001da }, { 0x00000300, 0x00001eb0 }, - { 0x00000301, 0x00001eae }, { 0x00000303, 0x00001eb4 }, - { 0x00000309, 0x00001eb2 }, { 0x00000300, 0x00001eb1 }, - { 0x00000301, 0x00001eaf }, { 0x00000303, 0x00001eb5 }, - { 0x00000309, 0x00001eb3 }, { 0x00000300, 0x00001e14 }, - { 0x00000301, 0x00001e16 }, { 0x00000300, 0x00001e15 }, - { 0x00000301, 0x00001e17 }, { 0x00000300, 0x00001e50 }, - { 0x00000301, 0x00001e52 }, { 0x00000300, 0x00001e51 }, - { 0x00000301, 0x00001e53 }, { 0x00000307, 0x00001e64 }, - { 0x00000307, 0x00001e65 }, { 0x00000307, 0x00001e66 }, - { 0x00000307, 0x00001e67 }, { 0x00000301, 0x00001e78 }, - { 0x00000301, 0x00001e79 }, { 0x00000308, 0x00001e7a }, - { 0x00000308, 0x00001e7b }, { 0x00000307, 0x00001e9b }, - { 0x00000300, 0x00001edc }, { 0x00000301, 0x00001eda }, - { 0x00000303, 0x00001ee0 }, { 0x00000309, 0x00001ede }, - { 0x00000323, 0x00001ee2 }, { 0x00000300, 0x00001edd }, - { 0x00000301, 0x00001edb }, { 0x00000303, 0x00001ee1 }, - { 0x00000309, 0x00001edf }, { 0x00000323, 0x00001ee3 }, - { 0x00000300, 0x00001eea }, { 0x00000301, 0x00001ee8 }, - { 0x00000303, 0x00001eee }, { 0x00000309, 0x00001eec }, - { 0x00000323, 0x00001ef0 }, { 0x00000300, 0x00001eeb }, - { 0x00000301, 0x00001ee9 }, { 0x00000303, 0x00001eef }, - { 0x00000309, 0x00001eed }, { 0x00000323, 0x00001ef1 }, - { 0x0000030c, 0x000001ee }, { 0x00000304, 0x000001ec }, - { 0x00000304, 0x000001ed }, { 0x00000304, 0x000001e0 }, - { 0x00000304, 0x000001e1 }, { 0x00000306, 0x00001e1c }, - { 0x00000306, 0x00001e1d }, { 0x00000304, 0x00000230 }, - { 0x00000304, 0x00000231 }, { 0x0000030c, 0x000001ef }, - { 0x00000300, 0x00001fba }, { 0x00000301, 0x00000386 }, - { 0x00000304, 0x00001fb9 }, { 0x00000306, 0x00001fb8 }, - { 0x00000313, 0x00001f08 }, { 0x00000314, 0x00001f09 }, - { 0x00000345, 0x00001fbc }, { 0x00000300, 0x00001fc8 }, - { 0x00000301, 0x00000388 }, { 0x00000313, 0x00001f18 }, - { 0x00000314, 0x00001f19 }, { 0x00000300, 0x00001fca }, - { 0x00000301, 0x00000389 }, { 0x00000313, 0x00001f28 }, - { 0x00000314, 0x00001f29 }, { 0x00000345, 0x00001fcc }, - { 0x00000300, 0x00001fda }, { 0x00000301, 0x0000038a }, - { 0x00000304, 0x00001fd9 }, { 0x00000306, 0x00001fd8 }, - { 0x00000308, 0x000003aa }, { 0x00000313, 0x00001f38 }, - { 0x00000314, 0x00001f39 }, { 0x00000300, 0x00001ff8 }, - { 0x00000301, 0x0000038c }, { 0x00000313, 0x00001f48 }, - { 0x00000314, 0x00001f49 }, { 0x00000314, 0x00001fec }, - { 0x00000300, 0x00001fea }, { 0x00000301, 0x0000038e }, - { 0x00000304, 0x00001fe9 }, { 0x00000306, 0x00001fe8 }, - { 0x00000308, 0x000003ab }, { 0x00000314, 0x00001f59 }, - { 0x00000300, 0x00001ffa }, { 0x00000301, 0x0000038f }, - { 0x00000313, 0x00001f68 }, { 0x00000314, 0x00001f69 }, - { 0x00000345, 0x00001ffc }, { 0x00000345, 0x00001fb4 }, - { 0x00000345, 0x00001fc4 }, { 0x00000300, 0x00001f70 }, - { 0x00000301, 0x000003ac }, { 0x00000304, 0x00001fb1 }, - { 0x00000306, 0x00001fb0 }, { 0x00000313, 0x00001f00 }, - { 0x00000314, 0x00001f01 }, { 0x00000342, 0x00001fb6 }, - { 0x00000345, 0x00001fb3 }, { 0x00000300, 0x00001f72 }, - { 0x00000301, 0x000003ad }, { 0x00000313, 0x00001f10 }, - { 0x00000314, 0x00001f11 }, { 0x00000300, 0x00001f74 }, - { 0x00000301, 0x000003ae }, { 0x00000313, 0x00001f20 }, - { 0x00000314, 0x00001f21 }, { 0x00000342, 0x00001fc6 }, - { 0x00000345, 0x00001fc3 }, { 0x00000300, 0x00001f76 }, - { 0x00000301, 0x000003af }, { 0x00000304, 0x00001fd1 }, - { 0x00000306, 0x00001fd0 }, { 0x00000308, 0x000003ca }, - { 0x00000313, 0x00001f30 }, { 0x00000314, 0x00001f31 }, - { 0x00000342, 0x00001fd6 }, { 0x00000300, 0x00001f78 }, - { 0x00000301, 0x000003cc }, { 0x00000313, 0x00001f40 }, - { 0x00000314, 0x00001f41 }, { 0x00000313, 0x00001fe4 }, - { 0x00000314, 0x00001fe5 }, { 0x00000300, 0x00001f7a }, - { 0x00000301, 0x000003cd }, { 0x00000304, 0x00001fe1 }, - { 0x00000306, 0x00001fe0 }, { 0x00000308, 0x000003cb }, - { 0x00000313, 0x00001f50 }, { 0x00000314, 0x00001f51 }, - { 0x00000342, 0x00001fe6 }, { 0x00000300, 0x00001f7c }, - { 0x00000301, 0x000003ce }, { 0x00000313, 0x00001f60 }, - { 0x00000314, 0x00001f61 }, { 0x00000342, 0x00001ff6 }, - { 0x00000345, 0x00001ff3 }, { 0x00000300, 0x00001fd2 }, - { 0x00000301, 0x00000390 }, { 0x00000342, 0x00001fd7 }, - { 0x00000300, 0x00001fe2 }, { 0x00000301, 0x000003b0 }, - { 0x00000342, 0x00001fe7 }, { 0x00000345, 0x00001ff4 }, - { 0x00000301, 0x000003d3 }, { 0x00000308, 0x000003d4 }, - { 0x00000308, 0x00000407 }, { 0x00000306, 0x000004d0 }, - { 0x00000308, 0x000004d2 }, { 0x00000301, 0x00000403 }, - { 0x00000300, 0x00000400 }, { 0x00000306, 0x000004d6 }, - { 0x00000308, 0x00000401 }, { 0x00000306, 0x000004c1 }, - { 0x00000308, 0x000004dc }, { 0x00000308, 0x000004de }, - { 0x00000300, 0x0000040d }, { 0x00000304, 0x000004e2 }, - { 0x00000306, 0x00000419 }, { 0x00000308, 0x000004e4 }, - { 0x00000301, 0x0000040c }, { 0x00000308, 0x000004e6 }, - { 0x00000304, 0x000004ee }, { 0x00000306, 0x0000040e }, - { 0x00000308, 0x000004f0 }, { 0x0000030b, 0x000004f2 }, - { 0x00000308, 0x000004f4 }, { 0x00000308, 0x000004f8 }, - { 0x00000308, 0x000004ec }, { 0x00000306, 0x000004d1 }, - { 0x00000308, 0x000004d3 }, { 0x00000301, 0x00000453 }, - { 0x00000300, 0x00000450 }, { 0x00000306, 0x000004d7 }, - { 0x00000308, 0x00000451 }, { 0x00000306, 0x000004c2 }, - { 0x00000308, 0x000004dd }, { 0x00000308, 0x000004df }, - { 0x00000300, 0x0000045d }, { 0x00000304, 0x000004e3 }, - { 0x00000306, 0x00000439 }, { 0x00000308, 0x000004e5 }, - { 0x00000301, 0x0000045c }, { 0x00000308, 0x000004e7 }, - { 0x00000304, 0x000004ef }, { 0x00000306, 0x0000045e }, - { 0x00000308, 0x000004f1 }, { 0x0000030b, 0x000004f3 }, - { 0x00000308, 0x000004f5 }, { 0x00000308, 0x000004f9 }, - { 0x00000308, 0x000004ed }, { 0x00000308, 0x00000457 }, - { 0x0000030f, 0x00000476 }, { 0x0000030f, 0x00000477 }, - { 0x00000308, 0x000004da }, { 0x00000308, 0x000004db }, - { 0x00000308, 0x000004ea }, { 0x00000308, 0x000004eb }, - { 0x00000653, 0x00000622 }, { 0x00000654, 0x00000623 }, - { 0x00000655, 0x00000625 }, { 0x00000654, 0x00000624 }, - { 0x00000654, 0x00000626 }, { 0x00000654, 0x000006c2 }, - { 0x00000654, 0x000006d3 }, { 0x00000654, 0x000006c0 }, - { 0x0000093c, 0x00000929 }, { 0x0000093c, 0x00000931 }, - { 0x0000093c, 0x00000934 }, { 0x000009be, 0x000009cb }, - { 0x000009d7, 0x000009cc }, { 0x00000b3e, 0x00000b4b }, - { 0x00000b56, 0x00000b48 }, { 0x00000b57, 0x00000b4c }, - { 0x00000bd7, 0x00000b94 }, { 0x00000bbe, 0x00000bca }, - { 0x00000bd7, 0x00000bcc }, { 0x00000bbe, 0x00000bcb }, - { 0x00000c56, 0x00000c48 }, { 0x00000cd5, 0x00000cc0 }, - { 0x00000cc2, 0x00000cca }, { 0x00000cd5, 0x00000cc7 }, - { 0x00000cd6, 0x00000cc8 }, { 0x00000cd5, 0x00000ccb }, - { 0x00000d3e, 0x00000d4a }, { 0x00000d57, 0x00000d4c }, - { 0x00000d3e, 0x00000d4b }, { 0x00000dca, 0x00000dda }, - { 0x00000dcf, 0x00000ddc }, { 0x00000ddf, 0x00000dde }, - { 0x00000dca, 0x00000ddd }, { 0x0000102e, 0x00001026 }, - { 0x00000304, 0x00001e38 }, { 0x00000304, 0x00001e39 }, - { 0x00000304, 0x00001e5c }, { 0x00000304, 0x00001e5d }, - { 0x00000307, 0x00001e68 }, { 0x00000307, 0x00001e69 }, - { 0x00000302, 0x00001eac }, { 0x00000306, 0x00001eb6 }, - { 0x00000302, 0x00001ead }, { 0x00000306, 0x00001eb7 }, - { 0x00000302, 0x00001ec6 }, { 0x00000302, 0x00001ec7 }, - { 0x00000302, 0x00001ed8 }, { 0x00000302, 0x00001ed9 }, - { 0x00000300, 0x00001f02 }, { 0x00000301, 0x00001f04 }, - { 0x00000342, 0x00001f06 }, { 0x00000345, 0x00001f80 }, - { 0x00000300, 0x00001f03 }, { 0x00000301, 0x00001f05 }, - { 0x00000342, 0x00001f07 }, { 0x00000345, 0x00001f81 }, - { 0x00000345, 0x00001f82 }, { 0x00000345, 0x00001f83 }, - { 0x00000345, 0x00001f84 }, { 0x00000345, 0x00001f85 }, - { 0x00000345, 0x00001f86 }, { 0x00000345, 0x00001f87 }, - { 0x00000300, 0x00001f0a }, { 0x00000301, 0x00001f0c }, - { 0x00000342, 0x00001f0e }, { 0x00000345, 0x00001f88 }, - { 0x00000300, 0x00001f0b }, { 0x00000301, 0x00001f0d }, - { 0x00000342, 0x00001f0f }, { 0x00000345, 0x00001f89 }, - { 0x00000345, 0x00001f8a }, { 0x00000345, 0x00001f8b }, - { 0x00000345, 0x00001f8c }, { 0x00000345, 0x00001f8d }, - { 0x00000345, 0x00001f8e }, { 0x00000345, 0x00001f8f }, - { 0x00000300, 0x00001f12 }, { 0x00000301, 0x00001f14 }, - { 0x00000300, 0x00001f13 }, { 0x00000301, 0x00001f15 }, - { 0x00000300, 0x00001f1a }, { 0x00000301, 0x00001f1c }, - { 0x00000300, 0x00001f1b }, { 0x00000301, 0x00001f1d }, - { 0x00000300, 0x00001f22 }, { 0x00000301, 0x00001f24 }, - { 0x00000342, 0x00001f26 }, { 0x00000345, 0x00001f90 }, - { 0x00000300, 0x00001f23 }, { 0x00000301, 0x00001f25 }, - { 0x00000342, 0x00001f27 }, { 0x00000345, 0x00001f91 }, - { 0x00000345, 0x00001f92 }, { 0x00000345, 0x00001f93 }, - { 0x00000345, 0x00001f94 }, { 0x00000345, 0x00001f95 }, - { 0x00000345, 0x00001f96 }, { 0x00000345, 0x00001f97 }, - { 0x00000300, 0x00001f2a }, { 0x00000301, 0x00001f2c }, - { 0x00000342, 0x00001f2e }, { 0x00000345, 0x00001f98 }, - { 0x00000300, 0x00001f2b }, { 0x00000301, 0x00001f2d }, - { 0x00000342, 0x00001f2f }, { 0x00000345, 0x00001f99 }, - { 0x00000345, 0x00001f9a }, { 0x00000345, 0x00001f9b }, - { 0x00000345, 0x00001f9c }, { 0x00000345, 0x00001f9d }, - { 0x00000345, 0x00001f9e }, { 0x00000345, 0x00001f9f }, - { 0x00000300, 0x00001f32 }, { 0x00000301, 0x00001f34 }, - { 0x00000342, 0x00001f36 }, { 0x00000300, 0x00001f33 }, - { 0x00000301, 0x00001f35 }, { 0x00000342, 0x00001f37 }, - { 0x00000300, 0x00001f3a }, { 0x00000301, 0x00001f3c }, - { 0x00000342, 0x00001f3e }, { 0x00000300, 0x00001f3b }, - { 0x00000301, 0x00001f3d }, { 0x00000342, 0x00001f3f }, - { 0x00000300, 0x00001f42 }, { 0x00000301, 0x00001f44 }, - { 0x00000300, 0x00001f43 }, { 0x00000301, 0x00001f45 }, - { 0x00000300, 0x00001f4a }, { 0x00000301, 0x00001f4c }, - { 0x00000300, 0x00001f4b }, { 0x00000301, 0x00001f4d }, - { 0x00000300, 0x00001f52 }, { 0x00000301, 0x00001f54 }, - { 0x00000342, 0x00001f56 }, { 0x00000300, 0x00001f53 }, - { 0x00000301, 0x00001f55 }, { 0x00000342, 0x00001f57 }, - { 0x00000300, 0x00001f5b }, { 0x00000301, 0x00001f5d }, - { 0x00000342, 0x00001f5f }, { 0x00000300, 0x00001f62 }, - { 0x00000301, 0x00001f64 }, { 0x00000342, 0x00001f66 }, - { 0x00000345, 0x00001fa0 }, { 0x00000300, 0x00001f63 }, - { 0x00000301, 0x00001f65 }, { 0x00000342, 0x00001f67 }, - { 0x00000345, 0x00001fa1 }, { 0x00000345, 0x00001fa2 }, - { 0x00000345, 0x00001fa3 }, { 0x00000345, 0x00001fa4 }, - { 0x00000345, 0x00001fa5 }, { 0x00000345, 0x00001fa6 }, - { 0x00000345, 0x00001fa7 }, { 0x00000300, 0x00001f6a }, - { 0x00000301, 0x00001f6c }, { 0x00000342, 0x00001f6e }, - { 0x00000345, 0x00001fa8 }, { 0x00000300, 0x00001f6b }, - { 0x00000301, 0x00001f6d }, { 0x00000342, 0x00001f6f }, - { 0x00000345, 0x00001fa9 }, { 0x00000345, 0x00001faa }, - { 0x00000345, 0x00001fab }, { 0x00000345, 0x00001fac }, - { 0x00000345, 0x00001fad }, { 0x00000345, 0x00001fae }, - { 0x00000345, 0x00001faf }, { 0x00000345, 0x00001fb2 }, - { 0x00000345, 0x00001fc2 }, { 0x00000345, 0x00001ff2 }, - { 0x00000345, 0x00001fb7 }, { 0x00000300, 0x00001fcd }, - { 0x00000301, 0x00001fce }, { 0x00000342, 0x00001fcf }, - { 0x00000345, 0x00001fc7 }, { 0x00000345, 0x00001ff7 }, - { 0x00000300, 0x00001fdd }, { 0x00000301, 0x00001fde }, - { 0x00000342, 0x00001fdf }, { 0x00000338, 0x0000219a }, - { 0x00000338, 0x0000219b }, { 0x00000338, 0x000021ae }, - { 0x00000338, 0x000021cd }, { 0x00000338, 0x000021cf }, - { 0x00000338, 0x000021ce }, { 0x00000338, 0x00002204 }, - { 0x00000338, 0x00002209 }, { 0x00000338, 0x0000220c }, - { 0x00000338, 0x00002224 }, { 0x00000338, 0x00002226 }, - { 0x00000338, 0x00002241 }, { 0x00000338, 0x00002244 }, - { 0x00000338, 0x00002247 }, { 0x00000338, 0x00002249 }, - { 0x00000338, 0x0000226d }, { 0x00000338, 0x00002262 }, - { 0x00000338, 0x00002270 }, { 0x00000338, 0x00002271 }, - { 0x00000338, 0x00002274 }, { 0x00000338, 0x00002275 }, - { 0x00000338, 0x00002278 }, { 0x00000338, 0x00002279 }, - { 0x00000338, 0x00002280 }, { 0x00000338, 0x00002281 }, - { 0x00000338, 0x000022e0 }, { 0x00000338, 0x000022e1 }, - { 0x00000338, 0x00002284 }, { 0x00000338, 0x00002285 }, - { 0x00000338, 0x00002288 }, { 0x00000338, 0x00002289 }, - { 0x00000338, 0x000022e2 }, { 0x00000338, 0x000022e3 }, - { 0x00000338, 0x000022ac }, { 0x00000338, 0x000022ad }, - { 0x00000338, 0x000022ae }, { 0x00000338, 0x000022af }, - { 0x00000338, 0x000022ea }, { 0x00000338, 0x000022eb }, - { 0x00000338, 0x000022ec }, { 0x00000338, 0x000022ed }, - { 0x00003099, 0x00003094 }, { 0x00003099, 0x0000304c }, - { 0x00003099, 0x0000304e }, { 0x00003099, 0x00003050 }, - { 0x00003099, 0x00003052 }, { 0x00003099, 0x00003054 }, - { 0x00003099, 0x00003056 }, { 0x00003099, 0x00003058 }, - { 0x00003099, 0x0000305a }, { 0x00003099, 0x0000305c }, - { 0x00003099, 0x0000305e }, { 0x00003099, 0x00003060 }, - { 0x00003099, 0x00003062 }, { 0x00003099, 0x00003065 }, - { 0x00003099, 0x00003067 }, { 0x00003099, 0x00003069 }, - { 0x00003099, 0x00003070 }, { 0x0000309a, 0x00003071 }, - { 0x00003099, 0x00003073 }, { 0x0000309a, 0x00003074 }, - { 0x00003099, 0x00003076 }, { 0x0000309a, 0x00003077 }, - { 0x00003099, 0x00003079 }, { 0x0000309a, 0x0000307a }, - { 0x00003099, 0x0000307c }, { 0x0000309a, 0x0000307d }, - { 0x00003099, 0x0000309e }, { 0x00003099, 0x000030f4 }, - { 0x00003099, 0x000030ac }, { 0x00003099, 0x000030ae }, - { 0x00003099, 0x000030b0 }, { 0x00003099, 0x000030b2 }, - { 0x00003099, 0x000030b4 }, { 0x00003099, 0x000030b6 }, - { 0x00003099, 0x000030b8 }, { 0x00003099, 0x000030ba }, - { 0x00003099, 0x000030bc }, { 0x00003099, 0x000030be }, - { 0x00003099, 0x000030c0 }, { 0x00003099, 0x000030c2 }, - { 0x00003099, 0x000030c5 }, { 0x00003099, 0x000030c7 }, - { 0x00003099, 0x000030c9 }, { 0x00003099, 0x000030d0 }, - { 0x0000309a, 0x000030d1 }, { 0x00003099, 0x000030d3 }, - { 0x0000309a, 0x000030d4 }, { 0x00003099, 0x000030d6 }, - { 0x0000309a, 0x000030d7 }, { 0x00003099, 0x000030d9 }, - { 0x0000309a, 0x000030da }, { 0x00003099, 0x000030dc }, - { 0x0000309a, 0x000030dd }, { 0x00003099, 0x000030f7 }, - { 0x00003099, 0x000030f8 }, { 0x00003099, 0x000030f9 }, - { 0x00003099, 0x000030fa }, { 0x00003099, 0x000030fe }, -}; - - -/* - * Canonical/Compatibility Decomposition - */ - -#define DECOMP_BITS_0 9 -#define DECOMP_BITS_1 7 -#define DECOMP_BITS_2 5 -#define DECOMP_COMPAT 32768 - -static const char16_t decompose_imap[] = { - 272, 400, 528, 656, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 912, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 1040, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 1168, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 784, 784, 784, 784, 784, 784, 784, 784, - 0, 0, 0, 0, 0, 1, 2, 3, - 4, 5, 6, 7, 0, 8, 9, 10, - 11, 12, 0, 0, 0, 13, 14, 15, - 0, 0, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 0, 0, 26, 27, - 0, 0, 0, 0, 28, 0, 0, 0, - 0, 29, 0, 30, 0, 0, 31, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 32, 33, 0, 0, 0, 34, 0, - 0, 35, 36, 0, 0, 0, 0, 0, - 0, 0, 37, 0, 38, 0, 39, 0, - 0, 0, 40, 0, 0, 0, 41, 0, - 0, 0, 42, 0, 0, 0, 43, 0, - 0, 44, 0, 0, 0, 45, 46, 0, - 47, 0, 48, 49, 50, 51, 0, 0, - 0, 52, 0, 0, 0, 0, 0, 53, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 54, 55, 56, 57, 58, 0, 0, - 59, 60, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 0, 0, - 81, 82, 83, 84, 85, 86, 87, 0, - 88, 89, 90, 91, 92, 93, 0, 94, - 0, 95, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 96, 97, 98, 99, 100, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 101, 0, 0, 102, 0, 0, 103, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 104, 0, 0, 0, 0, - 0, 0, 0, 0, 105, 0, 0, 106, - 107, 108, 109, 110, 111, 112, 113, 0, - 114, 115, 116, 117, 118, 119, 120, 121, - 0, 122, 123, 124, 125, 0, 0, 0, - 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 142, 143, 144, 145, 146, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 0, - 157, 158, 159, 160, 161, 162, 163, 164, - 165, 166, 167, 168, 169, 170, 171, 172, - 173, 174, 175, 176, 177, 178, 179, 180, - 181, 182, 183, 184, 185, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 197, 198, 0, 199, 200, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 201, 202, 203, 204, 205, 206, 207, 208, - 209, 210, 211, 212, 213, 214, 215, 216, - 217, 218, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, 231, 232, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 233, 234, 235, 236, 237, 238, 239, 240, - 241, 242, 243, 244, 245, 246, 247, 248, - 249, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; - -static const struct { - char16_t tbl[32]; -} decompose_table[] = { - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 32769, 0, 0, 0, 0, 0, 0, 0, - 32770, 0, 32772, 0, 0, 0, 0, 32773, - 0, 0, 32775, 32776, 32777, 32779, 0, 0, - 32780, 32782, 32783, 0, 32784, 32787, 32790, 0, - }}, - {{ - 25, 27, 29, 31, 33, 35, 0, 37, - 39, 41, 43, 45, 47, 49, 51, 53, - 0, 55, 57, 59, 61, 63, 65, 0, - 0, 67, 69, 71, 73, 75, 0, 0, - }}, - {{ - 77, 79, 81, 83, 85, 87, 0, 89, - 91, 93, 95, 97, 99, 101, 103, 105, - 0, 107, 109, 111, 113, 115, 117, 0, - 0, 119, 121, 123, 125, 127, 0, 129, - }}, - {{ - 131, 133, 135, 137, 139, 141, 143, 145, - 147, 149, 151, 153, 155, 157, 159, 161, - 0, 0, 163, 165, 167, 169, 171, 173, - 175, 177, 179, 181, 183, 185, 187, 189, - }}, - {{ - 191, 193, 195, 197, 199, 201, 0, 0, - 203, 205, 207, 209, 211, 213, 215, 217, - 219, 0, 32989, 32991, 225, 227, 229, 231, - 0, 233, 235, 237, 239, 241, 243, 33013, - }}, - {{ - 33015, 0, 0, 249, 251, 253, 255, 257, - 259, 33029, 0, 0, 263, 265, 267, 269, - 271, 273, 0, 0, 275, 277, 279, 281, - 283, 285, 287, 289, 291, 293, 295, 297, - }}, - {{ - 299, 301, 303, 305, 307, 309, 0, 0, - 311, 313, 315, 317, 319, 321, 323, 325, - 327, 329, 331, 333, 335, 337, 339, 341, - 343, 345, 347, 349, 351, 353, 355, 33125, - }}, - {{ - 358, 360, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 362, - 364, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 33134, 33136, 33138, 33140, - 33142, 33144, 33146, 33148, 33150, 384, 386, 388, - 390, 392, 394, 396, 398, 400, 402, 404, - 406, 408, 410, 412, 414, 0, 416, 418, - }}, - {{ - 420, 422, 424, 426, 0, 0, 428, 430, - 432, 434, 436, 438, 440, 442, 444, 446, - 448, 33218, 33220, 33222, 456, 458, 0, 0, - 460, 462, 464, 466, 468, 470, 472, 474, - }}, - {{ - 476, 478, 480, 482, 484, 486, 488, 490, - 492, 494, 496, 498, 500, 502, 504, 506, - 508, 510, 512, 514, 516, 518, 520, 522, - 524, 526, 528, 530, 0, 0, 532, 534, - }}, - {{ - 0, 0, 0, 0, 0, 0, 536, 538, - 540, 542, 544, 546, 548, 550, 552, 554, - 556, 558, 560, 562, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 33332, 33333, 33334, 33335, 33336, 33337, 33338, 33339, - 33340, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 33341, 33343, 33345, 33347, 33349, 33351, 0, 0, - }}, - {{ - 33353, 33354, 33355, 33356, 33357, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 590, 591, 0, 592, 593, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 595, 0, 0, 0, - 0, 0, 33364, 0, 0, 0, 598, 0, - }}, - {{ - 0, 0, 0, 0, 33367, 601, 603, 605, - 606, 608, 610, 0, 612, 0, 614, 616, - 618, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 620, 622, 624, 626, 628, 630, - 632, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 634, 636, 638, 640, 642, 0, - 33412, 33413, 33414, 647, 649, 33419, 33420, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 33421, 33422, 33423, 0, 33424, 33425, 0, 0, - 0, 33426, 0, 0, 0, 0, 0, 0, - }}, - {{ - 659, 661, 0, 663, 0, 0, 0, 665, - 0, 0, 0, 0, 667, 669, 671, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 673, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 675, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 677, 679, 0, 681, 0, 0, 0, 683, - 0, 0, 0, 0, 685, 687, 689, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 691, 693, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 695, 697, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 699, 701, 703, 705, 0, 0, 707, 709, - 0, 0, 711, 713, 715, 717, 719, 721, - }}, - {{ - 0, 0, 723, 725, 727, 729, 731, 733, - 0, 0, 735, 737, 739, 741, 743, 745, - 747, 749, 751, 753, 755, 757, 0, 0, - 759, 761, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 33531, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 765, 767, 769, 771, 773, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 33543, 33545, 33547, - 33549, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 783, 0, 785, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 787, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 789, 0, 0, 0, 0, 0, 0, - 0, 791, 0, 0, 793, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 795, 797, 799, 801, 803, 805, 807, 809, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 811, 813, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 815, 817, 0, 819, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 821, 0, 0, 823, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 825, 827, 829, 0, 0, 831, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 833, 0, 0, 835, 837, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 839, 841, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 843, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 845, 847, 849, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 851, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 853, 0, 0, 0, 0, 0, 0, 855, - 857, 0, 859, 861, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 863, 865, 867, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 869, 0, 871, 873, 875, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 33645, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 33647, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 33649, 33651, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 33653, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 886, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 888, 0, 0, - 0, 0, 890, 0, 0, 0, 0, 892, - 0, 0, 0, 0, 894, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 896, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 898, 0, 900, 902, 33672, - 906, 33676, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 910, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 912, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 914, 0, 0, - }}, - {{ - 0, 0, 916, 0, 0, 0, 0, 918, - 0, 0, 0, 0, 920, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 922, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 924, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 33694, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 33695, 33696, 33697, 0, - 33698, 33699, 33700, 33701, 33702, 33703, 33704, 33705, - 33706, 33707, 33708, 0, 33709, 33710, 33711, 33712, - }}, - {{ - 33713, 33714, 33715, 33716, 33717, 33718, 33719, 33720, - 33721, 33722, 33723, 33724, 33725, 33726, 0, 33727, - 33728, 33729, 33730, 33731, 33732, 33733, 33734, 33735, - 33736, 33737, 33738, 33739, 33740, 33741, 33742, 33743, - }}, - {{ - 33744, 33745, 33746, 33747, 33748, 33749, 33750, 33751, - 33752, 33753, 33754, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 33755, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 33756, 33757, 33758, 33759, 33760, - }}, - {{ - 33761, 33762, 33763, 33764, 33765, 33766, 33767, 33768, - 33769, 33770, 33771, 33772, 33773, 33774, 33775, 33776, - 33777, 33778, 33779, 33780, 33781, 33782, 33783, 33784, - 33785, 33786, 33787, 33788, 33789, 33790, 33791, 33792, - }}, - {{ - 1025, 1027, 1029, 1031, 1033, 1035, 1037, 1039, - 1041, 1043, 1045, 1047, 1049, 1051, 1053, 1055, - 1057, 1059, 1061, 1063, 1065, 1067, 1069, 1071, - 1073, 1075, 1077, 1079, 1081, 1083, 1085, 1087, - }}, - {{ - 1089, 1091, 1093, 1095, 1097, 1099, 1101, 1103, - 1105, 1107, 1109, 1111, 1113, 1115, 1117, 1119, - 1121, 1123, 1125, 1127, 1129, 1131, 1133, 1135, - 1137, 1139, 1141, 1143, 1145, 1147, 1149, 1151, - }}, - {{ - 1153, 1155, 1157, 1159, 1161, 1163, 1165, 1167, - 1169, 1171, 1173, 1175, 1177, 1179, 1181, 1183, - 1185, 1187, 1189, 1191, 1193, 1195, 1197, 1199, - 1201, 1203, 1205, 1207, 1209, 1211, 1213, 1215, - }}, - {{ - 1217, 1219, 1221, 1223, 1225, 1227, 1229, 1231, - 1233, 1235, 1237, 1239, 1241, 1243, 1245, 1247, - 1249, 1251, 1253, 1255, 1257, 1259, 1261, 1263, - 1265, 1267, 1269, 1271, 1273, 1275, 1277, 1279, - }}, - {{ - 1281, 1283, 1285, 1287, 1289, 1291, 1293, 1295, - 1297, 1299, 1301, 1303, 1305, 1307, 1309, 1311, - 1313, 1315, 1317, 1319, 1321, 1323, 1325, 1327, - 1329, 1331, 34101, 1335, 0, 0, 0, 0, - }}, - {{ - 1337, 1339, 1341, 1343, 1345, 1347, 1349, 1351, - 1353, 1355, 1357, 1359, 1361, 1363, 1365, 1367, - 1369, 1371, 1373, 1375, 1377, 1379, 1381, 1383, - 1385, 1387, 1389, 1391, 1393, 1395, 1397, 1399, - }}, - {{ - 1401, 1403, 1405, 1407, 1409, 1411, 1413, 1415, - 1417, 1419, 1421, 1423, 1425, 1427, 1429, 1431, - 1433, 1435, 1437, 1439, 1441, 1443, 1445, 1447, - 1449, 1451, 1453, 1455, 1457, 1459, 1461, 1463, - }}, - {{ - 1465, 1467, 1469, 1471, 1473, 1475, 1477, 1479, - 1481, 1483, 1485, 1487, 1489, 1491, 1493, 1495, - 1497, 1499, 1501, 1503, 1505, 1507, 1509, 1511, - 1513, 1515, 0, 0, 0, 0, 0, 0, - }}, - {{ - 1517, 1519, 1521, 1523, 1525, 1527, 1529, 1531, - 1533, 1535, 1537, 1539, 1541, 1543, 1545, 1547, - 1549, 1551, 1553, 1555, 1557, 1559, 0, 0, - 1561, 1563, 1565, 1567, 1569, 1571, 0, 0, - }}, - {{ - 1573, 1575, 1577, 1579, 1581, 1583, 1585, 1587, - 1589, 1591, 1593, 1595, 1597, 1599, 1601, 1603, - 1605, 1607, 1609, 1611, 1613, 1615, 1617, 1619, - 1621, 1623, 1625, 1627, 1629, 1631, 1633, 1635, - }}, - {{ - 1637, 1639, 1641, 1643, 1645, 1647, 0, 0, - 1649, 1651, 1653, 1655, 1657, 1659, 0, 0, - 1661, 1663, 1665, 1667, 1669, 1671, 1673, 1675, - 0, 1677, 0, 1679, 0, 1681, 0, 1683, - }}, - {{ - 1685, 1687, 1689, 1691, 1693, 1695, 1697, 1699, - 1701, 1703, 1705, 1707, 1709, 1711, 1713, 1715, - 1717, 1719, 1720, 1722, 1723, 1725, 1726, 1728, - 1729, 1731, 1732, 1734, 1735, 1737, 0, 0, - }}, - {{ - 1738, 1740, 1742, 1744, 1746, 1748, 1750, 1752, - 1754, 1756, 1758, 1760, 1762, 1764, 1766, 1768, - 1770, 1772, 1774, 1776, 1778, 1780, 1782, 1784, - 1786, 1788, 1790, 1792, 1794, 1796, 1798, 1800, - }}, - {{ - 1802, 1804, 1806, 1808, 1810, 1812, 1814, 1816, - 1818, 1820, 1822, 1824, 1826, 1828, 1830, 1832, - 1834, 1836, 1838, 1840, 1842, 0, 1844, 1846, - 1848, 1850, 1852, 1854, 1855, 34625, 1859, 34628, - }}, - {{ - 34630, 1864, 1866, 1868, 1870, 0, 1872, 1874, - 1876, 1878, 1879, 1881, 1882, 1884, 1886, 1888, - 1890, 1892, 1894, 1896, 0, 0, 1897, 1899, - 1901, 1903, 1905, 1907, 0, 1908, 1910, 1912, - }}, - {{ - 1914, 1916, 1918, 1920, 1921, 1923, 1925, 1927, - 1929, 1931, 1933, 1935, 1936, 1938, 1940, 1941, - 0, 0, 1942, 1944, 1946, 0, 1948, 1950, - 1952, 1954, 1955, 1957, 1958, 1960, 34729, 0, - }}, - {{ - 1963, 1964, 34733, 34734, 34735, 34736, 34737, 34738, - 34739, 34740, 34741, 0, 0, 0, 0, 0, - 0, 34742, 0, 0, 0, 0, 0, 34743, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 34745, 34746, 34748, 0, - 0, 0, 0, 0, 0, 0, 0, 34751, - 0, 0, 0, 34752, 34754, 0, 34757, 34759, - 0, 0, 0, 0, 34762, 0, 34764, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 34766, - 34768, 34770, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 34772, - 0, 0, 0, 0, 0, 0, 0, 34776, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 34777, 34778, 0, 0, 34779, 34780, 34781, 34782, - 34783, 34784, 34785, 34786, 34787, 34788, 34789, 34790, - }}, - {{ - 34791, 34792, 34793, 34794, 34795, 34796, 34797, 34798, - 34799, 34800, 34801, 34802, 34803, 34804, 34805, 0, - 34806, 34807, 34808, 34809, 34810, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 34811, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 34813, 34816, 34819, 34820, 0, 34822, 34825, 34828, - 0, 34829, 34831, 34832, 34833, 34834, 34835, 34836, - 34837, 34838, 34839, 34840, 0, 34841, 34842, 0, - 0, 34844, 34845, 34846, 34847, 34848, 0, 0, - }}, - {{ - 34849, 34851, 34854, 0, 34856, 0, 2089, 0, - 34858, 0, 2091, 2092, 34861, 34862, 0, 34863, - 34864, 34865, 0, 34866, 34867, 34868, 34869, 34870, - 34871, 34872, 0, 34873, 34876, 34877, 34878, 34879, - }}, - {{ - 34880, 0, 0, 0, 0, 34881, 34882, 34883, - 34884, 34885, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 34886, 34889, 34892, 34895, 34898, - 34901, 34904, 34907, 34910, 34913, 34916, 34919, 34922, - }}, - {{ - 34924, 34925, 34927, 34930, 34932, 34933, 34935, 34938, - 34942, 34944, 34945, 34947, 34950, 34951, 34952, 34953, - 34954, 34955, 34957, 34960, 34962, 34963, 34965, 34968, - 34972, 34974, 34975, 34977, 34980, 34981, 34982, 34983, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2216, 2218, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 2220, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2222, 2224, 2226, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 2228, 0, 0, 0, - 0, 2230, 0, 0, 2232, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 2234, 0, 2236, 0, - 0, 0, 0, 0, 35006, 35008, 0, 35011, - 35013, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 2248, 0, 0, 2250, 0, 0, 2252, - 0, 2254, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 2256, 0, 2258, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2260, 2262, 2264, - 2266, 2268, 0, 0, 2270, 2272, 0, 0, - 2274, 2276, 0, 0, 0, 0, 0, 0, - }}, - {{ - 2278, 2280, 0, 0, 2282, 2284, 0, 0, - 2286, 2288, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2290, 2292, 2294, 2296, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 2298, 2300, 2302, 2304, 0, 0, 0, 0, - 0, 0, 2306, 2308, 2310, 2312, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2314, 2315, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 35084, 35085, 35086, 35087, 35088, 35089, 35090, 35091, - 35092, 35093, 35095, 35097, 35099, 35101, 35103, 35105, - 35107, 35109, 35111, 35113, 35115, 35118, 35121, 35124, - 35127, 35130, 35133, 35136, 35139, 35142, 35146, 35150, - }}, - {{ - 35154, 35158, 35162, 35166, 35170, 35174, 35178, 35182, - 35186, 35188, 35190, 35192, 35194, 35196, 35198, 35200, - 35202, 35204, 35207, 35210, 35213, 35216, 35219, 35222, - 35225, 35228, 35231, 35234, 35237, 35240, 35243, 35246, - }}, - {{ - 35249, 35252, 35255, 35258, 35261, 35264, 35267, 35270, - 35273, 35276, 35279, 35282, 35285, 35288, 35291, 35294, - 35297, 35300, 35303, 35306, 35309, 35312, 35315, 35316, - 35317, 35318, 35319, 35320, 35321, 35322, 35323, 35324, - }}, - {{ - 35325, 35326, 35327, 35328, 35329, 35330, 35331, 35332, - 35333, 35334, 35335, 35336, 35337, 35338, 35339, 35340, - 35341, 35342, 35343, 35344, 35345, 35346, 35347, 35348, - 35349, 35350, 35351, 35352, 35353, 35354, 35355, 35356, - }}, - {{ - 35357, 35358, 35359, 35360, 35361, 35362, 35363, 35364, - 35365, 35366, 35367, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 35368, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 35372, 35375, 35377, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2612, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 35382, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 35383, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 35384, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 35385, 35386, 35387, 35388, 35389, 35390, 35391, 35392, - 35393, 35394, 35395, 35396, 35397, 35398, 35399, 35400, - 35401, 35402, 35403, 35404, 35405, 35406, 35407, 35408, - 35409, 35410, 35411, 35412, 35413, 35414, 35415, 35416, - }}, - {{ - 35417, 35418, 35419, 35420, 35421, 35422, 35423, 35424, - 35425, 35426, 35427, 35428, 35429, 35430, 35431, 35432, - 35433, 35434, 35435, 35436, 35437, 35438, 35439, 35440, - 35441, 35442, 35443, 35444, 35445, 35446, 35447, 35448, - }}, - {{ - 35449, 35450, 35451, 35452, 35453, 35454, 35455, 35456, - 35457, 35458, 35459, 35460, 35461, 35462, 35463, 35464, - 35465, 35466, 35467, 35468, 35469, 35470, 35471, 35472, - 35473, 35474, 35475, 35476, 35477, 35478, 35479, 35480, - }}, - {{ - 35481, 35482, 35483, 35484, 35485, 35486, 35487, 35488, - 35489, 35490, 35491, 35492, 35493, 35494, 35495, 35496, - 35497, 35498, 35499, 35500, 35501, 35502, 35503, 35504, - 35505, 35506, 35507, 35508, 35509, 35510, 35511, 35512, - }}, - {{ - 35513, 35514, 35515, 35516, 35517, 35518, 35519, 35520, - 35521, 35522, 35523, 35524, 35525, 35526, 35527, 35528, - 35529, 35530, 35531, 35532, 35533, 35534, 35535, 35536, - 35537, 35538, 35539, 35540, 35541, 35542, 35543, 35544, - }}, - {{ - 35545, 35546, 35547, 35548, 35549, 35550, 35551, 35552, - 35553, 35554, 35555, 35556, 35557, 35558, 35559, 35560, - 35561, 35562, 35563, 35564, 35565, 35566, 35567, 35568, - 35569, 35570, 35571, 35572, 35573, 35574, 35575, 35576, - }}, - {{ - 35577, 35578, 35579, 35580, 35581, 35582, 35583, 35584, - 35585, 35586, 35587, 35588, 35589, 35590, 35591, 35592, - 35593, 35594, 35595, 35596, 35597, 35598, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 35599, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 35600, 0, - 35601, 35602, 35603, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2836, 0, 2838, 0, - 2840, 0, 2842, 0, 2844, 0, 2846, 0, - 2848, 0, 2850, 0, 2852, 0, 2854, 0, - }}, - {{ - 2856, 0, 2858, 0, 0, 2860, 0, 2862, - 0, 2864, 0, 0, 0, 0, 0, 0, - 2866, 2868, 0, 2870, 2872, 0, 2874, 2876, - 0, 2878, 2880, 0, 2882, 2884, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2886, 0, 0, 0, - 0, 0, 0, 35656, 35658, 0, 2892, 35662, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2896, 0, 2898, 0, - 2900, 0, 2902, 0, 2904, 0, 2906, 0, - 2908, 0, 2910, 0, 2912, 0, 2914, 0, - }}, - {{ - 2916, 0, 2918, 0, 0, 2920, 0, 2922, - 0, 2924, 0, 0, 0, 0, 0, 0, - 2926, 2928, 0, 2930, 2932, 0, 2934, 2936, - 0, 2938, 2940, 0, 2942, 2944, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2946, 0, 0, 2948, - 2950, 2952, 2954, 0, 0, 0, 2956, 35726, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 35728, 35729, 35730, 35731, 35732, 35733, 35734, - 35735, 35736, 35737, 35738, 35739, 35740, 35741, 35742, - }}, - {{ - 35743, 35744, 35745, 35746, 35747, 35748, 35749, 35750, - 35751, 35752, 35753, 35754, 35755, 35756, 35757, 35758, - 35759, 35760, 35761, 35762, 35763, 35764, 35765, 35766, - 35767, 35768, 35769, 35770, 35771, 35772, 35773, 35774, - }}, - {{ - 35775, 35776, 35777, 35778, 35779, 35780, 35781, 35782, - 35783, 35784, 35785, 35786, 35787, 35788, 35789, 35790, - 35791, 35792, 35793, 35794, 35795, 35796, 35797, 35798, - 35799, 35800, 35801, 35802, 35803, 35804, 35805, 35806, - }}, - {{ - 35807, 35808, 35809, 35810, 35811, 35812, 35813, 35814, - 35815, 35816, 35817, 35818, 35819, 35820, 35821, 0, - 0, 0, 35822, 35823, 35824, 35825, 35826, 35827, - 35828, 35829, 35830, 35831, 35832, 35833, 35834, 35835, - }}, - {{ - 35836, 35839, 35842, 35845, 35848, 35851, 35854, 35857, - 35860, 35863, 35866, 35869, 35872, 35875, 35878, 35882, - 35886, 35890, 35894, 35898, 35902, 35906, 35910, 35914, - 35918, 35922, 35926, 35930, 35934, 35938, 35945, 0, - }}, - {{ - 35951, 35954, 35957, 35960, 35963, 35966, 35969, 35972, - 35975, 35978, 35981, 35984, 35987, 35990, 35993, 35996, - 35999, 36002, 36005, 36008, 36011, 36014, 36017, 36020, - 36023, 36026, 36029, 36032, 36035, 36038, 36041, 36044, - }}, - {{ - 36047, 36050, 36053, 36056, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 36059, 36062, 36064, 36066, 36068, 36070, 36072, 36074, - 36076, 36078, 36080, 36082, 36084, 36086, 36088, 36090, - }}, - {{ - 36092, 36093, 36094, 36095, 36096, 36097, 36098, 36099, - 36100, 36101, 36102, 36103, 36104, 36105, 36106, 36108, - 36110, 36112, 36114, 36116, 36118, 36120, 36122, 36124, - 36126, 36128, 36130, 36132, 36134, 36139, 36143, 0, - }}, - {{ - 36145, 36146, 36147, 36148, 36149, 36150, 36151, 36152, - 36153, 36154, 36155, 36156, 36157, 36158, 36159, 36160, - 36161, 36162, 36163, 36164, 36165, 36166, 36167, 36168, - 36169, 36170, 36171, 36172, 36173, 36174, 36175, 36176, - }}, - {{ - 36177, 36178, 36179, 36180, 36181, 36182, 36183, 36184, - 36185, 36186, 36187, 36188, 36189, 36190, 36191, 36192, - 36193, 36194, 36196, 36198, 36200, 36202, 36204, 36206, - 36208, 36210, 36212, 36214, 36216, 36218, 36220, 36222, - }}, - {{ - 36224, 36226, 36228, 36230, 36232, 36234, 36236, 36238, - 36240, 36242, 36245, 36248, 36251, 36253, 36256, 36258, - 36261, 36262, 36263, 36264, 36265, 36266, 36267, 36268, - 36269, 36270, 36271, 36272, 36273, 36274, 36275, 36276, - }}, - {{ - 36277, 36278, 36279, 36280, 36281, 36282, 36283, 36284, - 36285, 36286, 36287, 36288, 36289, 36290, 36291, 36292, - 36293, 36294, 36295, 36296, 36297, 36298, 36299, 36300, - 36301, 36302, 36303, 36304, 36305, 36306, 36307, 0, - }}, - {{ - 36308, 36312, 36316, 36320, 36323, 36327, 36330, 36333, - 36338, 36342, 36345, 36348, 36351, 36355, 36359, 36362, - 36365, 36367, 36370, 36374, 36378, 36380, 36385, 36391, - 36396, 36399, 36404, 36409, 36413, 36416, 36419, 36422, - }}, - {{ - 36426, 36431, 36435, 36438, 36441, 36444, 36446, 36448, - 36450, 36452, 36455, 36458, 36463, 36466, 36470, 36475, - 36478, 36480, 36482, 36487, 36491, 36496, 36499, 36504, - 36506, 36509, 36512, 36515, 36518, 36521, 36525, 36528, - }}, - {{ - 36530, 36533, 36536, 36539, 36543, 36546, 36549, 36552, - 36557, 36561, 36563, 36568, 36570, 36574, 36578, 36581, - 36584, 36587, 36591, 36593, 36596, 36600, 36602, 36607, - 36610, 36612, 36614, 36616, 36618, 36620, 36622, 36624, - }}, - {{ - 36626, 36628, 36630, 36633, 36636, 36639, 36642, 36645, - 36648, 36651, 36654, 36657, 36660, 36663, 36666, 36669, - 36672, 36675, 36678, 36680, 36682, 36685, 36687, 36689, - 36691, 36694, 36697, 36699, 36701, 36703, 36705, 36707, - }}, - {{ - 36711, 36713, 36715, 36717, 36719, 36721, 36723, 36725, - 36727, 36730, 36734, 36736, 36738, 36740, 36742, 36744, - 36746, 36748, 36751, 36754, 36757, 36760, 36762, 36764, - 36766, 36768, 36770, 36772, 36774, 36776, 36778, 36780, - }}, - {{ - 36783, 36786, 36788, 36791, 36794, 36797, 36799, 36802, - 36805, 36809, 36811, 36814, 36817, 36820, 36823, 36828, - 36834, 36836, 36838, 36840, 36842, 36844, 36846, 36848, - 36850, 36852, 36854, 36856, 36858, 36860, 36862, 36864, - }}, - {{ - 36866, 36868, 36870, 36874, 36876, 36878, 36880, 36884, - 36887, 36889, 36891, 36893, 36895, 36897, 36899, 36901, - 36903, 36905, 36907, 36910, 36912, 36914, 36917, 36920, - 36922, 36926, 36929, 36931, 36933, 36935, 36937, 36940, - }}, - {{ - 36943, 36945, 36947, 36949, 36951, 36953, 36955, 36957, - 36959, 36961, 36964, 36967, 36970, 36973, 36976, 36979, - 36982, 36985, 36988, 36991, 36994, 36997, 37000, 37003, - 37006, 37009, 37012, 37015, 37018, 37021, 37024, 37027, - }}, - {{ - 4262, 4263, 4264, 4265, 4266, 4267, 4268, 4269, - 4270, 4271, 4272, 4273, 4274, 4275, 4276, 4277, - 4278, 4279, 4280, 4281, 4282, 4283, 4284, 4285, - 4286, 4287, 4288, 4289, 4290, 4291, 4292, 4293, - }}, - {{ - 4294, 4295, 4296, 4297, 4298, 4299, 4300, 4301, - 4302, 4303, 4304, 4305, 4306, 4307, 4308, 4309, - 4310, 4311, 4312, 4313, 4314, 4315, 4316, 4317, - 4318, 4319, 4320, 4321, 4322, 4323, 4324, 4325, - }}, - {{ - 4326, 4327, 4328, 4329, 4330, 4331, 4332, 4333, - 4334, 4335, 4336, 4337, 4338, 4339, 4340, 4341, - 4342, 4343, 4344, 4345, 4346, 4347, 4348, 4349, - 4350, 4351, 4352, 4353, 4354, 4355, 4356, 4357, - }}, - {{ - 4358, 4359, 4360, 4361, 4362, 4363, 4364, 4365, - 4366, 4367, 4368, 4369, 4370, 4371, 4372, 4373, - 4374, 4375, 4376, 4377, 4378, 4379, 4380, 4381, - 4382, 4383, 4384, 4385, 4386, 4387, 4388, 4389, - }}, - {{ - 4390, 4391, 4392, 4393, 4394, 4395, 4396, 4397, - 4398, 4399, 4400, 4401, 4402, 4403, 4404, 4405, - 4406, 4407, 4408, 4409, 4410, 4411, 4412, 4413, - 4414, 4415, 4416, 4417, 4418, 4419, 4420, 4421, - }}, - {{ - 4422, 4423, 4424, 4425, 4426, 4427, 4428, 4429, - 4430, 4431, 4432, 4433, 4434, 4435, 4436, 4437, - 4438, 4439, 4440, 4441, 4442, 4443, 4444, 4445, - 4446, 4447, 4448, 4449, 4450, 4451, 4452, 4453, - }}, - {{ - 4454, 4455, 4456, 4457, 4458, 4459, 4460, 4461, - 4462, 4463, 4464, 4465, 4466, 4467, 4468, 4469, - 4470, 4471, 4472, 4473, 4474, 4475, 4476, 4477, - 4478, 4479, 4480, 4481, 4482, 4483, 4484, 4485, - }}, - {{ - 4486, 4487, 4488, 4489, 4490, 4491, 4492, 4493, - 4494, 4495, 4496, 4497, 4498, 4499, 4500, 4501, - 4502, 4503, 4504, 4505, 4506, 4507, 4508, 4509, - 4510, 4511, 4512, 4513, 4514, 4515, 4516, 4517, - }}, - {{ - 4518, 4519, 4520, 4521, 4522, 4523, 4524, 4525, - 4526, 4527, 4528, 4529, 4530, 4531, 0, 0, - 4532, 0, 4533, 0, 0, 4534, 4535, 4536, - 4537, 4538, 4539, 4540, 4541, 4542, 4543, 0, - }}, - {{ - 4544, 0, 4545, 0, 0, 4546, 4547, 0, - 0, 0, 4548, 4549, 4550, 4551, 0, 0, - 4552, 4553, 4554, 4555, 4556, 4557, 4558, 4559, - 4560, 4561, 4562, 4563, 4564, 4565, 4566, 4567, - }}, - {{ - 4568, 4569, 4570, 4571, 4572, 4573, 4574, 4575, - 4576, 4577, 4578, 4579, 4580, 4581, 4582, 4583, - 4584, 4585, 4586, 4587, 4588, 4589, 4590, 4591, - 4592, 4593, 4594, 4595, 4596, 4597, 4598, 4599, - }}, - {{ - 4600, 4601, 4602, 4603, 4604, 4605, 4606, 4607, - 4608, 4609, 4610, 0, 0, 0, 0, 0, - 4611, 4612, 4613, 4614, 4615, 4616, 4617, 4618, - 4619, 4620, 4621, 4622, 4623, 4624, 4625, 4626, - }}, - {{ - 4627, 4628, 4629, 4630, 4631, 4632, 4633, 4634, - 4635, 4636, 4637, 4638, 4639, 4640, 4641, 4642, - 4643, 4644, 4645, 4646, 4647, 4648, 4649, 4650, - 4651, 4652, 4653, 4654, 4655, 4656, 4657, 4658, - }}, - {{ - 4659, 4660, 4661, 4662, 4663, 4664, 4665, 4666, - 4667, 4668, 4669, 4670, 4671, 4672, 4673, 4674, - 4675, 4676, 4677, 4678, 4679, 4680, 4681, 4682, - 4683, 4684, 4685, 4686, 4687, 4688, 4689, 4690, - }}, - {{ - 4691, 4692, 4693, 4694, 4695, 4696, 4697, 4698, - 4699, 4700, 4701, 4702, 4703, 4704, 4705, 4706, - 4707, 4708, 4709, 4710, 4711, 4712, 4713, 4714, - 4715, 4716, 0, 0, 0, 0, 0, 0, - }}, - {{ - 37485, 37487, 37489, 37491, 37494, 37497, 37499, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 37501, 37503, 37505, 37507, 37509, - 0, 0, 0, 0, 0, 4743, 0, 4745, - }}, - {{ - 37515, 37516, 37517, 37518, 37519, 37520, 37521, 37522, - 37523, 37524, 4757, 4759, 4761, 4763, 4765, 4767, - 4769, 4771, 4773, 4775, 4777, 4779, 4781, 0, - 4783, 4785, 4787, 4789, 4791, 0, 4793, 0, - }}, - {{ - 4795, 4797, 0, 4799, 4801, 0, 4803, 4805, - 4807, 4809, 4811, 4813, 4815, 4817, 4819, 37589, - 37591, 37592, 37593, 37594, 37595, 37596, 37597, 37598, - 37599, 37600, 37601, 37602, 37603, 37604, 37605, 37606, - }}, - {{ - 37607, 37608, 37609, 37610, 37611, 37612, 37613, 37614, - 37615, 37616, 37617, 37618, 37619, 37620, 37621, 37622, - 37623, 37624, 37625, 37626, 37627, 37628, 37629, 37630, - 37631, 37632, 37633, 37634, 37635, 37636, 37637, 37638, - }}, - {{ - 37639, 37640, 37641, 37642, 37643, 37644, 37645, 37646, - 37647, 37648, 37649, 37650, 37651, 37652, 37653, 37654, - 37655, 37656, 37657, 37658, 37659, 37660, 37661, 37662, - 37663, 37664, 37665, 37666, 37667, 37668, 37669, 37670, - }}, - {{ - 37671, 37672, 37673, 37674, 37675, 37676, 37677, 37678, - 37679, 37680, 37681, 37682, 37683, 37684, 37685, 37686, - 37687, 37688, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 37689, 37690, 37691, 37692, 37693, - 37694, 37695, 37696, 37697, 37698, 37699, 37700, 37701, - }}, - {{ - 37702, 37703, 37704, 37705, 37706, 37707, 37708, 37709, - 37710, 37711, 37712, 37714, 37716, 37718, 37720, 37722, - 37724, 37726, 37728, 37730, 37732, 37734, 37736, 37738, - 37740, 37742, 37744, 37746, 37748, 37749, 37750, 37751, - }}, - {{ - 37752, 37754, 37756, 37758, 37760, 37762, 37764, 37766, - 37768, 37770, 37772, 37774, 37776, 37778, 37780, 37782, - 37784, 37786, 37788, 37790, 37792, 37794, 37796, 37798, - 37800, 37802, 37804, 37806, 37808, 37810, 37812, 37814, - }}, - {{ - 37816, 37818, 37820, 37822, 37824, 37826, 37828, 37830, - 37832, 37834, 37836, 37838, 37840, 37842, 37844, 37846, - 37848, 37850, 37852, 37854, 37856, 37858, 37860, 37862, - 37864, 37866, 37868, 37870, 37872, 37874, 37876, 37878, - }}, - {{ - 37880, 37882, 37884, 37886, 37888, 37890, 37892, 37894, - 37896, 37898, 37900, 37902, 37904, 37906, 37908, 37910, - 37912, 37914, 37916, 37918, 37920, 37922, 37924, 37926, - 37928, 37930, 37932, 37934, 37936, 37938, 37940, 37943, - }}, - {{ - 37946, 37949, 37952, 37955, 37958, 37960, 37962, 37964, - 37966, 37968, 37970, 37972, 37974, 37976, 37978, 37980, - 37982, 37984, 37986, 37988, 37990, 37992, 37994, 37996, - 37998, 38000, 38002, 38004, 38006, 38008, 38010, 38012, - }}, - {{ - 38014, 38016, 38018, 38020, 38022, 38024, 38026, 38028, - 38030, 38032, 38034, 38036, 38038, 38040, 38042, 38044, - 38046, 38048, 38050, 38052, 38054, 38056, 38058, 38060, - 38062, 38064, 38066, 38068, 38070, 38072, 38074, 38076, - }}, - {{ - 38078, 38080, 38082, 38084, 38086, 38088, 38090, 38092, - 38094, 38096, 38098, 38100, 38102, 38104, 38106, 38108, - 38110, 38112, 38114, 38116, 38118, 38120, 38122, 38124, - 38126, 38128, 38130, 38132, 38134, 38136, 38138, 38140, - }}, - {{ - 38142, 38144, 38146, 38148, 38150, 38152, 38154, 38156, - 38158, 38160, 38162, 38164, 38166, 38168, 38170, 38172, - 38174, 38176, 38178, 38180, 38182, 38184, 38186, 38188, - 38190, 38192, 38194, 38196, 38198, 38200, 38202, 38204, - }}, - {{ - 38206, 38208, 38210, 38212, 38214, 38216, 38218, 38220, - 38222, 38224, 38226, 38228, 38230, 38232, 38234, 38236, - 38238, 38240, 38242, 38245, 38248, 38251, 38253, 38255, - 38257, 38259, 38261, 38263, 38265, 38267, 38269, 38271, - }}, - {{ - 38273, 38275, 38277, 38279, 38281, 38283, 38285, 38287, - 38289, 38291, 38293, 38295, 38297, 38299, 38301, 38303, - 38305, 38307, 38309, 38311, 38313, 38315, 38317, 38319, - 38321, 38323, 38325, 38327, 38329, 38331, 38333, 38335, - }}, - {{ - 38337, 38339, 38341, 38343, 38345, 38347, 38349, 38351, - 38353, 38355, 38357, 38359, 38361, 38363, 38365, 38367, - 38369, 38371, 38373, 38375, 38377, 38379, 38381, 38383, - 38385, 38387, 38389, 38391, 38393, 38395, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 38397, 38400, 38403, 38406, 38409, 38412, 38415, 38418, - 38421, 38424, 38427, 38430, 38433, 38436, 38439, 38442, - }}, - {{ - 38445, 38448, 38451, 38454, 38457, 38460, 38463, 38466, - 38469, 38472, 38475, 38478, 38481, 38484, 38487, 38490, - 38493, 38496, 38499, 38502, 38505, 38508, 38511, 38514, - 38517, 38520, 38523, 38526, 38529, 38532, 38535, 38538, - }}, - {{ - 38541, 38544, 38547, 38550, 38553, 38556, 38559, 38562, - 38565, 38568, 38571, 38574, 38577, 38580, 38583, 38586, - 0, 0, 38589, 38592, 38595, 38598, 38601, 38604, - 38607, 38610, 38613, 38616, 38619, 38622, 38625, 38628, - }}, - {{ - 38631, 38634, 38637, 38640, 38643, 38646, 38649, 38652, - 38655, 38658, 38661, 38664, 38667, 38670, 38673, 38676, - 38679, 38682, 38685, 38688, 38691, 38694, 38697, 38700, - 38703, 38706, 38709, 38712, 38715, 38718, 38721, 38724, - }}, - {{ - 38727, 38730, 38733, 38736, 38739, 38742, 38745, 38748, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 38751, 38754, 38757, 38761, 38765, 38769, 38773, 38777, - 38781, 38785, 38788, 38806, 38814, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 38818, 38819, 38820, 38821, 38822, 38823, 38824, 38825, - 38826, 38827, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 38828, 38829, 38830, 38831, 38832, 38833, 38834, 38835, - 38836, 38837, 38838, 38839, 38840, 38841, 38842, 38843, - }}, - {{ - 38844, 38845, 38846, 38847, 38848, 0, 0, 38849, - 38850, 38851, 38852, 38853, 38854, 38855, 38856, 38857, - 38858, 38859, 38860, 0, 38861, 38862, 38863, 38864, - 38865, 38866, 38867, 38868, 38869, 38870, 38871, 38872, - }}, - {{ - 38873, 38874, 38875, 38876, 38877, 38878, 38879, 0, - 38880, 38881, 38882, 38883, 0, 0, 0, 0, - 38884, 38886, 38888, 0, 38890, 0, 38892, 38894, - 38896, 38898, 38900, 38902, 38904, 38906, 38908, 38910, - }}, - {{ - 38912, 38913, 38914, 38915, 38916, 38917, 38918, 38919, - 38920, 38921, 38922, 38923, 38924, 38925, 38926, 38927, - 38928, 38929, 38930, 38931, 38932, 38933, 38934, 38935, - 38936, 38937, 38938, 38939, 38940, 38941, 38942, 38943, - }}, - {{ - 38944, 38945, 38946, 38947, 38948, 38949, 38950, 38951, - 38952, 38953, 38954, 38955, 38956, 38957, 38958, 38959, - 38960, 38961, 38962, 38963, 38964, 38965, 38966, 38967, - 38968, 38969, 38970, 38971, 38972, 38973, 38974, 38975, - }}, - {{ - 38976, 38977, 38978, 38979, 38980, 38981, 38982, 38983, - 38984, 38985, 38986, 38987, 38988, 38989, 38990, 38991, - 38992, 38993, 38994, 38995, 38996, 38997, 38998, 38999, - 39000, 39001, 39002, 39003, 39004, 39005, 39006, 39007, - }}, - {{ - 39008, 39009, 39010, 39011, 39012, 39013, 39014, 39015, - 39016, 39017, 39018, 39019, 39020, 39021, 39022, 39023, - 39024, 39025, 39026, 39027, 39028, 39029, 39031, 39033, - 39035, 39037, 39039, 39041, 39043, 0, 0, 0, - }}, - {{ - 0, 39045, 39046, 39047, 39048, 39049, 39050, 39051, - 39052, 39053, 39054, 39055, 39056, 39057, 39058, 39059, - 39060, 39061, 39062, 39063, 39064, 39065, 39066, 39067, - 39068, 39069, 39070, 39071, 39072, 39073, 39074, 39075, - }}, - {{ - 39076, 39077, 39078, 39079, 39080, 39081, 39082, 39083, - 39084, 39085, 39086, 39087, 39088, 39089, 39090, 39091, - 39092, 39093, 39094, 39095, 39096, 39097, 39098, 39099, - 39100, 39101, 39102, 39103, 39104, 39105, 39106, 39107, - }}, - {{ - 39108, 39109, 39110, 39111, 39112, 39113, 39114, 39115, - 39116, 39117, 39118, 39119, 39120, 39121, 39122, 39123, - 39124, 39125, 39126, 39127, 39128, 39129, 39130, 39131, - 39132, 39133, 39134, 39135, 39136, 39137, 39138, 39139, - }}, - {{ - 39140, 39141, 39142, 39143, 39144, 39145, 39146, 39147, - 39148, 39149, 39150, 39151, 39152, 39153, 39154, 39155, - 39156, 39157, 39158, 39159, 39160, 39161, 39162, 39163, - 39164, 39165, 39166, 39167, 39168, 39169, 39170, 39171, - }}, - {{ - 39172, 39173, 39174, 39175, 39176, 39177, 39178, 39179, - 39180, 39181, 39182, 39183, 39184, 39185, 39186, 39187, - 39188, 39189, 39190, 39191, 39192, 39193, 39194, 39195, - 39196, 39197, 39198, 39199, 39200, 39201, 39202, 39203, - }}, - {{ - 39204, 39205, 39206, 39207, 39208, 39209, 39210, 39211, - 39212, 39213, 39214, 39215, 39216, 39217, 39218, 39219, - 39220, 39221, 39222, 39223, 39224, 39225, 39226, 39227, - 39228, 39229, 39230, 39231, 39232, 39233, 39234, 0, - }}, - {{ - 0, 0, 39235, 39236, 39237, 39238, 39239, 39240, - 0, 0, 39241, 39242, 39243, 39244, 39245, 39246, - 0, 0, 39247, 39248, 39249, 39250, 39251, 39252, - 0, 0, 39253, 39254, 39255, 0, 0, 0, - }}, - {{ - 39256, 39257, 39258, 39259, 39260, 39261, 39262, 0, - 39263, 39264, 39265, 39266, 39267, 39268, 39269, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 6502, 6504, - }}, - {{ - 6506, 6508, 6510, 6512, 6514, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 6516, 6518, 6520, 6522, 6524, - }}, - {{ - 6526, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }}, - {{ - 39296, 39297, 39298, 39299, 39300, 39301, 39302, 39303, - 39304, 39305, 39306, 39307, 39308, 39309, 39310, 39311, - 39312, 39313, 39314, 39315, 39316, 39317, 39318, 39319, - 39320, 39321, 39322, 39323, 39324, 39325, 39326, 39327, - }}, - {{ - 39328, 39329, 39330, 39331, 39332, 39333, 39334, 39335, - 39336, 39337, 39338, 39339, 39340, 39341, 39342, 39343, - 39344, 39345, 39346, 39347, 39348, 39349, 39350, 39351, - 39352, 39353, 39354, 39355, 39356, 39357, 39358, 39359, - }}, - {{ - 39360, 39361, 39362, 39363, 39364, 39365, 39366, 39367, - 39368, 39369, 39370, 39371, 39372, 39373, 39374, 39375, - 39376, 39377, 39378, 39379, 39380, 0, 39381, 39382, - 39383, 39384, 39385, 39386, 39387, 39388, 39389, 39390, - }}, - {{ - 39391, 39392, 39393, 39394, 39395, 39396, 39397, 39398, - 39399, 39400, 39401, 39402, 39403, 39404, 39405, 39406, - 39407, 39408, 39409, 39410, 39411, 39412, 39413, 39414, - 39415, 39416, 39417, 39418, 39419, 39420, 39421, 39422, - }}, - {{ - 39423, 39424, 39425, 39426, 39427, 39428, 39429, 39430, - 39431, 39432, 39433, 39434, 39435, 39436, 39437, 39438, - 39439, 39440, 39441, 39442, 39443, 39444, 39445, 39446, - 39447, 39448, 39449, 39450, 39451, 0, 39452, 39453, - }}, - {{ - 0, 0, 39454, 0, 0, 39455, 39456, 0, - 0, 39457, 39458, 39459, 39460, 0, 39461, 39462, - 39463, 39464, 39465, 39466, 39467, 39468, 39469, 39470, - 39471, 39472, 0, 39473, 0, 39474, 39475, 39476, - }}, - {{ - 39477, 39478, 39479, 39480, 0, 39481, 39482, 39483, - 39484, 39485, 39486, 39487, 39488, 39489, 39490, 39491, - 39492, 39493, 39494, 39495, 39496, 39497, 39498, 39499, - 39500, 39501, 39502, 39503, 39504, 39505, 39506, 39507, - }}, - {{ - 39508, 39509, 39510, 39511, 39512, 39513, 39514, 39515, - 39516, 39517, 39518, 39519, 39520, 39521, 39522, 39523, - 39524, 39525, 39526, 39527, 39528, 39529, 39530, 39531, - 39532, 39533, 39534, 39535, 39536, 39537, 39538, 39539, - }}, - {{ - 39540, 39541, 39542, 39543, 39544, 39545, 0, 39546, - 39547, 39548, 39549, 0, 0, 39550, 39551, 39552, - 39553, 39554, 39555, 39556, 39557, 0, 39558, 39559, - 39560, 39561, 39562, 39563, 39564, 0, 39565, 39566, - }}, - {{ - 39567, 39568, 39569, 39570, 39571, 39572, 39573, 39574, - 39575, 39576, 39577, 39578, 39579, 39580, 39581, 39582, - 39583, 39584, 39585, 39586, 39587, 39588, 39589, 39590, - 39591, 39592, 0, 39593, 39594, 39595, 39596, 0, - }}, - {{ - 39597, 39598, 39599, 39600, 39601, 0, 39602, 0, - 0, 0, 39603, 39604, 39605, 39606, 39607, 39608, - 39609, 0, 39610, 39611, 39612, 39613, 39614, 39615, - 39616, 39617, 39618, 39619, 39620, 39621, 39622, 39623, - }}, - {{ - 39624, 39625, 39626, 39627, 39628, 39629, 39630, 39631, - 39632, 39633, 39634, 39635, 39636, 39637, 39638, 39639, - 39640, 39641, 39642, 39643, 39644, 39645, 39646, 39647, - 39648, 39649, 39650, 39651, 39652, 39653, 39654, 39655, - }}, - {{ - 39656, 39657, 39658, 39659, 39660, 39661, 39662, 39663, - 39664, 39665, 39666, 39667, 39668, 39669, 39670, 39671, - 39672, 39673, 39674, 39675, 39676, 39677, 39678, 39679, - 39680, 39681, 39682, 39683, 39684, 39685, 39686, 39687, - }}, - {{ - 39688, 39689, 39690, 39691, 39692, 39693, 39694, 39695, - 39696, 39697, 39698, 39699, 39700, 39701, 39702, 39703, - 39704, 39705, 39706, 39707, 39708, 39709, 39710, 39711, - 39712, 39713, 39714, 39715, 39716, 39717, 39718, 39719, - }}, - {{ - 39720, 39721, 39722, 39723, 39724, 39725, 39726, 39727, - 39728, 39729, 39730, 39731, 39732, 39733, 39734, 39735, - 39736, 39737, 39738, 39739, 39740, 39741, 39742, 39743, - 39744, 39745, 39746, 39747, 39748, 39749, 39750, 39751, - }}, - {{ - 39752, 39753, 39754, 39755, 39756, 39757, 39758, 39759, - 39760, 39761, 39762, 39763, 39764, 39765, 39766, 39767, - 39768, 39769, 39770, 39771, 39772, 39773, 39774, 39775, - 39776, 39777, 39778, 39779, 39780, 39781, 39782, 39783, - }}, - {{ - 39784, 39785, 39786, 39787, 39788, 39789, 39790, 39791, - 39792, 39793, 39794, 39795, 39796, 39797, 39798, 39799, - 39800, 39801, 39802, 39803, 39804, 39805, 39806, 39807, - 39808, 39809, 39810, 39811, 39812, 39813, 39814, 39815, - }}, - {{ - 39816, 39817, 39818, 39819, 39820, 39821, 39822, 39823, - 39824, 39825, 39826, 39827, 39828, 39829, 39830, 39831, - 39832, 39833, 39834, 39835, 39836, 39837, 39838, 39839, - 39840, 39841, 39842, 39843, 39844, 39845, 39846, 39847, - }}, - {{ - 39848, 39849, 39850, 39851, 39852, 39853, 39854, 39855, - 39856, 39857, 39858, 39859, 39860, 39861, 39862, 39863, - 39864, 39865, 39866, 39867, 39868, 39869, 39870, 39871, - 39872, 39873, 39874, 39875, 39876, 39877, 39878, 39879, - }}, - {{ - 39880, 39881, 39882, 39883, 39884, 39885, 39886, 39887, - 39888, 39889, 39890, 39891, 39892, 39893, 39894, 39895, - 39896, 39897, 39898, 39899, 39900, 39901, 39902, 39903, - 39904, 39905, 39906, 39907, 39908, 39909, 39910, 39911, - }}, - {{ - 39912, 39913, 39914, 39915, 39916, 39917, 39918, 39919, - 39920, 39921, 39922, 39923, 39924, 39925, 39926, 39927, - 39928, 39929, 39930, 39931, 39932, 39933, 39934, 39935, - 39936, 39937, 39938, 39939, 39940, 39941, 39942, 39943, - }}, - {{ - 39944, 39945, 39946, 39947, 39948, 39949, 0, 0, - 39950, 39951, 39952, 39953, 39954, 39955, 39956, 39957, - 39958, 39959, 39960, 39961, 39962, 39963, 39964, 39965, - 39966, 39967, 39968, 39969, 39970, 39971, 39972, 39973, - }}, - {{ - 39974, 39975, 39976, 39977, 39978, 39979, 39980, 39981, - 39982, 39983, 39984, 39985, 39986, 39987, 39988, 39989, - 39990, 39991, 39992, 39993, 39994, 39995, 39996, 39997, - 39998, 39999, 40000, 40001, 40002, 40003, 40004, 40005, - }}, - {{ - 40006, 40007, 40008, 40009, 40010, 40011, 40012, 40013, - 40014, 40015, 40016, 40017, 40018, 40019, 40020, 40021, - 40022, 40023, 40024, 40025, 40026, 40027, 40028, 40029, - 40030, 40031, 40032, 40033, 40034, 40035, 40036, 40037, - }}, - {{ - 40038, 40039, 40040, 40041, 40042, 40043, 40044, 40045, - 40046, 40047, 40048, 40049, 40050, 40051, 40052, 40053, - 40054, 40055, 40056, 40057, 40058, 40059, 40060, 40061, - 40062, 40063, 40064, 40065, 40066, 40067, 40068, 40069, - }}, - {{ - 40070, 40071, 40072, 40073, 40074, 40075, 40076, 40077, - 40078, 40079, 40080, 40081, 40082, 40083, 40084, 40085, - 40086, 40087, 40088, 40089, 40090, 40091, 40092, 40093, - 40094, 40095, 40096, 40097, 40098, 40099, 40100, 40101, - }}, - {{ - 40102, 40103, 40104, 40105, 40106, 40107, 40108, 40109, - 40110, 40111, 40112, 40113, 40114, 40115, 40116, 40117, - 40118, 40119, 40120, 40121, 40122, 40123, 40124, 40125, - 40126, 40127, 40128, 40129, 40130, 40131, 40132, 40133, - }}, - {{ - 40134, 40135, 40136, 40137, 40138, 40139, 40140, 40141, - 40142, 40143, 40144, 40145, 40146, 40147, 40148, 40149, - 40150, 40151, 40152, 40153, 40154, 40155, 40156, 40157, - 40158, 40159, 40160, 40161, 40162, 40163, 40164, 40165, - }}, - {{ - 40166, 40167, 40168, 40169, 40170, 40171, 40172, 40173, - 40174, 40175, 40176, 40177, 40178, 40179, 40180, 40181, - 40182, 40183, 40184, 40185, 40186, 40187, 40188, 40189, - 40190, 40191, 40192, 40193, 40194, 40195, 40196, 40197, - }}, - {{ - 40198, 40199, 40200, 40201, 40202, 40203, 40204, 40205, - 40206, 40207, 40208, 40209, 40210, 40211, 40212, 40213, - 40214, 40215, 40216, 40217, 40218, 40219, 40220, 40221, - 40222, 40223, 40224, 40225, 40226, 40227, 40228, 40229, - }}, - {{ - 40230, 40231, 40232, 40233, 40234, 40235, 40236, 40237, - 40238, 40239, 0, 0, 0, 0, 40240, 40241, - 40242, 40243, 40244, 40245, 40246, 40247, 40248, 40249, - 40250, 40251, 40252, 40253, 40254, 40255, 40256, 40257, - }}, - {{ - 40258, 40259, 40260, 40261, 40262, 40263, 40264, 40265, - 40266, 40267, 40268, 40269, 40270, 40271, 40272, 40273, - 40274, 40275, 40276, 40277, 40278, 40279, 40280, 40281, - 40282, 40283, 40284, 40285, 40286, 40287, 40288, 40289, - }}, - {{ - 7522, 7523, 7524, 7525, 7526, 7527, 7528, 7529, - 7530, 7531, 7532, 7533, 7534, 7535, 7536, 7537, - 7538, 7539, 7540, 7541, 7542, 7543, 7544, 7545, - 7546, 7547, 7548, 7549, 7550, 7551, 7552, 7553, - }}, - {{ - 7554, 7555, 7556, 7557, 7558, 7559, 7560, 7561, - 7562, 7563, 7564, 7565, 7566, 7567, 7568, 7569, - 7570, 7571, 7572, 7573, 7574, 7575, 7576, 7577, - 7578, 7579, 7580, 7581, 7582, 7583, 7584, 7585, - }}, - {{ - 7586, 7587, 7588, 7589, 7590, 7591, 7592, 7593, - 7594, 7595, 7596, 7597, 7598, 7599, 7600, 7601, - 7602, 7603, 7604, 7605, 7606, 7607, 7608, 7609, - 7610, 7611, 7612, 7613, 7614, 7615, 7616, 7617, - }}, - {{ - 7618, 7619, 7620, 7621, 7622, 7623, 7624, 7625, - 7626, 7627, 7628, 7629, 7630, 7631, 7632, 7633, - 7634, 7635, 7636, 7637, 7638, 7639, 7640, 7641, - 7642, 7643, 7644, 7645, 7646, 7647, 7648, 7649, - }}, - {{ - 7650, 7651, 7652, 7653, 7654, 7655, 7656, 7657, - 7658, 7659, 7660, 7661, 7662, 7663, 7664, 7665, - 7666, 7667, 7668, 7669, 7670, 7671, 7672, 7673, - 7674, 7675, 7676, 7677, 7678, 7679, 7680, 7681, - }}, - {{ - 7682, 7683, 7684, 7685, 7686, 7687, 7688, 7689, - 7690, 7691, 7692, 7693, 7694, 7695, 7696, 7697, - 7698, 7699, 7700, 7701, 7702, 7703, 7704, 7705, - 7706, 7707, 7708, 7709, 7710, 7711, 7712, 7713, - }}, - {{ - 7714, 7715, 7716, 7717, 7718, 7719, 7720, 7721, - 7722, 7723, 7724, 7725, 7726, 7727, 7728, 7729, - 7730, 7731, 7732, 7733, 7734, 7735, 7736, 7737, - 7738, 7739, 7740, 7741, 7742, 7743, 7744, 7745, - }}, - {{ - 7746, 7747, 7748, 7749, 7750, 7751, 7752, 7753, - 7754, 7755, 7756, 7757, 7758, 7759, 7760, 7761, - 7762, 7763, 7764, 7765, 7766, 7767, 7768, 7769, - 7770, 7771, 7772, 7773, 7774, 7775, 7776, 7777, - }}, - {{ - 7778, 7779, 7780, 7781, 7782, 7783, 7784, 7785, - 7786, 7787, 7788, 7789, 7790, 7791, 7792, 7793, - 7794, 7795, 7796, 7797, 7798, 7799, 7800, 7801, - 7802, 7803, 7804, 7805, 7806, 7807, 7808, 7809, - }}, - {{ - 7810, 7811, 7812, 7813, 7814, 7815, 7816, 7817, - 7818, 7819, 7820, 7821, 7822, 7823, 7824, 7825, - 7826, 7827, 7828, 7829, 7830, 7831, 7832, 7833, - 7834, 7835, 7836, 7837, 7838, 7839, 7840, 7841, - }}, - {{ - 7842, 7843, 7844, 7845, 7846, 7847, 7848, 7849, - 7850, 7851, 7852, 7853, 7854, 7855, 7856, 7857, - 7858, 7859, 7860, 7861, 7862, 7863, 7864, 7865, - 7866, 7867, 7868, 7869, 7870, 7871, 7872, 7873, - }}, - {{ - 7874, 7875, 7876, 7877, 7878, 7879, 7880, 7881, - 7882, 7883, 7884, 7885, 7886, 7887, 7888, 7889, - 7890, 7891, 7892, 7893, 7894, 7895, 7896, 7897, - 7898, 7899, 7900, 7901, 7902, 7903, 7904, 7905, - }}, - {{ - 7906, 7907, 7908, 7909, 7910, 7911, 7912, 7913, - 7914, 7915, 7916, 7917, 7918, 7919, 7920, 7921, - 7922, 7923, 7924, 7925, 7926, 7927, 7928, 7929, - 7930, 7931, 7932, 7933, 7934, 7935, 7936, 7937, - }}, - {{ - 7938, 7939, 7940, 7941, 7942, 7943, 7944, 7945, - 7946, 7947, 7948, 7949, 7950, 7951, 7952, 7953, - 7954, 7955, 7956, 7957, 7958, 7959, 7960, 7961, - 7962, 7963, 7964, 7965, 7966, 7967, 7968, 7969, - }}, - {{ - 7970, 7971, 7972, 7973, 7974, 7975, 7976, 7977, - 7978, 7979, 7980, 7981, 7982, 7983, 7984, 7985, - 7986, 7987, 7988, 7989, 7990, 7991, 7992, 7993, - 7994, 7995, 7996, 7997, 7998, 7999, 8000, 8001, - }}, - {{ - 8002, 8003, 8004, 8005, 8006, 8007, 8008, 8009, - 8010, 8011, 8012, 8013, 8014, 8015, 8016, 8017, - 8018, 8019, 8020, 8021, 8022, 8023, 8024, 8025, - 8026, 8027, 8028, 8029, 8030, 8031, 8032, 8033, - }}, - {{ - 8034, 8035, 8036, 8037, 8038, 8039, 8040, 8041, - 8042, 8043, 8044, 8045, 8046, 8047, 8048, 8049, - 8050, 8051, 8052, 8053, 8054, 8055, 8056, 8057, - 8058, 8059, 8060, 8061, 8062, 8063, 0, 0, - }}, -}; -static const uint32_t decompose_seq[] = { - 0x00000000, 0x80000020, 0x00000020, 0x80000308, - 0x80000061, 0x00000020, 0x80000304, 0x80000032, - 0x80000033, 0x00000020, 0x80000301, 0x800003bc, - 0x00000020, 0x80000327, 0x80000031, 0x8000006f, - 0x00000031, 0x00002044, 0x80000034, 0x00000031, - 0x00002044, 0x80000032, 0x00000033, 0x00002044, - 0x80000034, 0x00000041, 0x80000300, 0x00000041, - 0x80000301, 0x00000041, 0x80000302, 0x00000041, - 0x80000303, 0x00000041, 0x80000308, 0x00000041, - 0x8000030a, 0x00000043, 0x80000327, 0x00000045, - 0x80000300, 0x00000045, 0x80000301, 0x00000045, - 0x80000302, 0x00000045, 0x80000308, 0x00000049, - 0x80000300, 0x00000049, 0x80000301, 0x00000049, - 0x80000302, 0x00000049, 0x80000308, 0x0000004e, - 0x80000303, 0x0000004f, 0x80000300, 0x0000004f, - 0x80000301, 0x0000004f, 0x80000302, 0x0000004f, - 0x80000303, 0x0000004f, 0x80000308, 0x00000055, - 0x80000300, 0x00000055, 0x80000301, 0x00000055, - 0x80000302, 0x00000055, 0x80000308, 0x00000059, - 0x80000301, 0x00000061, 0x80000300, 0x00000061, - 0x80000301, 0x00000061, 0x80000302, 0x00000061, - 0x80000303, 0x00000061, 0x80000308, 0x00000061, - 0x8000030a, 0x00000063, 0x80000327, 0x00000065, - 0x80000300, 0x00000065, 0x80000301, 0x00000065, - 0x80000302, 0x00000065, 0x80000308, 0x00000069, - 0x80000300, 0x00000069, 0x80000301, 0x00000069, - 0x80000302, 0x00000069, 0x80000308, 0x0000006e, - 0x80000303, 0x0000006f, 0x80000300, 0x0000006f, - 0x80000301, 0x0000006f, 0x80000302, 0x0000006f, - 0x80000303, 0x0000006f, 0x80000308, 0x00000075, - 0x80000300, 0x00000075, 0x80000301, 0x00000075, - 0x80000302, 0x00000075, 0x80000308, 0x00000079, - 0x80000301, 0x00000079, 0x80000308, 0x00000041, - 0x80000304, 0x00000061, 0x80000304, 0x00000041, - 0x80000306, 0x00000061, 0x80000306, 0x00000041, - 0x80000328, 0x00000061, 0x80000328, 0x00000043, - 0x80000301, 0x00000063, 0x80000301, 0x00000043, - 0x80000302, 0x00000063, 0x80000302, 0x00000043, - 0x80000307, 0x00000063, 0x80000307, 0x00000043, - 0x8000030c, 0x00000063, 0x8000030c, 0x00000044, - 0x8000030c, 0x00000064, 0x8000030c, 0x00000045, - 0x80000304, 0x00000065, 0x80000304, 0x00000045, - 0x80000306, 0x00000065, 0x80000306, 0x00000045, - 0x80000307, 0x00000065, 0x80000307, 0x00000045, - 0x80000328, 0x00000065, 0x80000328, 0x00000045, - 0x8000030c, 0x00000065, 0x8000030c, 0x00000047, - 0x80000302, 0x00000067, 0x80000302, 0x00000047, - 0x80000306, 0x00000067, 0x80000306, 0x00000047, - 0x80000307, 0x00000067, 0x80000307, 0x00000047, - 0x80000327, 0x00000067, 0x80000327, 0x00000048, - 0x80000302, 0x00000068, 0x80000302, 0x00000049, - 0x80000303, 0x00000069, 0x80000303, 0x00000049, - 0x80000304, 0x00000069, 0x80000304, 0x00000049, - 0x80000306, 0x00000069, 0x80000306, 0x00000049, - 0x80000328, 0x00000069, 0x80000328, 0x00000049, - 0x80000307, 0x00000049, 0x8000004a, 0x00000069, - 0x8000006a, 0x0000004a, 0x80000302, 0x0000006a, - 0x80000302, 0x0000004b, 0x80000327, 0x0000006b, - 0x80000327, 0x0000004c, 0x80000301, 0x0000006c, - 0x80000301, 0x0000004c, 0x80000327, 0x0000006c, - 0x80000327, 0x0000004c, 0x8000030c, 0x0000006c, - 0x8000030c, 0x0000004c, 0x800000b7, 0x0000006c, - 0x800000b7, 0x0000004e, 0x80000301, 0x0000006e, - 0x80000301, 0x0000004e, 0x80000327, 0x0000006e, - 0x80000327, 0x0000004e, 0x8000030c, 0x0000006e, - 0x8000030c, 0x000002bc, 0x8000006e, 0x0000004f, - 0x80000304, 0x0000006f, 0x80000304, 0x0000004f, - 0x80000306, 0x0000006f, 0x80000306, 0x0000004f, - 0x8000030b, 0x0000006f, 0x8000030b, 0x00000052, - 0x80000301, 0x00000072, 0x80000301, 0x00000052, - 0x80000327, 0x00000072, 0x80000327, 0x00000052, - 0x8000030c, 0x00000072, 0x8000030c, 0x00000053, - 0x80000301, 0x00000073, 0x80000301, 0x00000053, - 0x80000302, 0x00000073, 0x80000302, 0x00000053, - 0x80000327, 0x00000073, 0x80000327, 0x00000053, - 0x8000030c, 0x00000073, 0x8000030c, 0x00000054, - 0x80000327, 0x00000074, 0x80000327, 0x00000054, - 0x8000030c, 0x00000074, 0x8000030c, 0x00000055, - 0x80000303, 0x00000075, 0x80000303, 0x00000055, - 0x80000304, 0x00000075, 0x80000304, 0x00000055, - 0x80000306, 0x00000075, 0x80000306, 0x00000055, - 0x8000030a, 0x00000075, 0x8000030a, 0x00000055, - 0x8000030b, 0x00000075, 0x8000030b, 0x00000055, - 0x80000328, 0x00000075, 0x80000328, 0x00000057, - 0x80000302, 0x00000077, 0x80000302, 0x00000059, - 0x80000302, 0x00000079, 0x80000302, 0x00000059, - 0x80000308, 0x0000005a, 0x80000301, 0x0000007a, - 0x80000301, 0x0000005a, 0x80000307, 0x0000007a, - 0x80000307, 0x0000005a, 0x8000030c, 0x0000007a, - 0x8000030c, 0x80000073, 0x0000004f, 0x8000031b, - 0x0000006f, 0x8000031b, 0x00000055, 0x8000031b, - 0x00000075, 0x8000031b, 0x00000044, 0x8000017d, - 0x00000044, 0x8000017e, 0x00000064, 0x8000017e, - 0x0000004c, 0x8000004a, 0x0000004c, 0x8000006a, - 0x0000006c, 0x8000006a, 0x0000004e, 0x8000004a, - 0x0000004e, 0x8000006a, 0x0000006e, 0x8000006a, - 0x00000041, 0x8000030c, 0x00000061, 0x8000030c, - 0x00000049, 0x8000030c, 0x00000069, 0x8000030c, - 0x0000004f, 0x8000030c, 0x0000006f, 0x8000030c, - 0x00000055, 0x8000030c, 0x00000075, 0x8000030c, - 0x000000dc, 0x80000304, 0x000000fc, 0x80000304, - 0x000000dc, 0x80000301, 0x000000fc, 0x80000301, - 0x000000dc, 0x8000030c, 0x000000fc, 0x8000030c, - 0x000000dc, 0x80000300, 0x000000fc, 0x80000300, - 0x000000c4, 0x80000304, 0x000000e4, 0x80000304, - 0x00000226, 0x80000304, 0x00000227, 0x80000304, - 0x000000c6, 0x80000304, 0x000000e6, 0x80000304, - 0x00000047, 0x8000030c, 0x00000067, 0x8000030c, - 0x0000004b, 0x8000030c, 0x0000006b, 0x8000030c, - 0x0000004f, 0x80000328, 0x0000006f, 0x80000328, - 0x000001ea, 0x80000304, 0x000001eb, 0x80000304, - 0x000001b7, 0x8000030c, 0x00000292, 0x8000030c, - 0x0000006a, 0x8000030c, 0x00000044, 0x8000005a, - 0x00000044, 0x8000007a, 0x00000064, 0x8000007a, - 0x00000047, 0x80000301, 0x00000067, 0x80000301, - 0x0000004e, 0x80000300, 0x0000006e, 0x80000300, - 0x000000c5, 0x80000301, 0x000000e5, 0x80000301, - 0x000000c6, 0x80000301, 0x000000e6, 0x80000301, - 0x000000d8, 0x80000301, 0x000000f8, 0x80000301, - 0x00000041, 0x8000030f, 0x00000061, 0x8000030f, - 0x00000041, 0x80000311, 0x00000061, 0x80000311, - 0x00000045, 0x8000030f, 0x00000065, 0x8000030f, - 0x00000045, 0x80000311, 0x00000065, 0x80000311, - 0x00000049, 0x8000030f, 0x00000069, 0x8000030f, - 0x00000049, 0x80000311, 0x00000069, 0x80000311, - 0x0000004f, 0x8000030f, 0x0000006f, 0x8000030f, - 0x0000004f, 0x80000311, 0x0000006f, 0x80000311, - 0x00000052, 0x8000030f, 0x00000072, 0x8000030f, - 0x00000052, 0x80000311, 0x00000072, 0x80000311, - 0x00000055, 0x8000030f, 0x00000075, 0x8000030f, - 0x00000055, 0x80000311, 0x00000075, 0x80000311, - 0x00000053, 0x80000326, 0x00000073, 0x80000326, - 0x00000054, 0x80000326, 0x00000074, 0x80000326, - 0x00000048, 0x8000030c, 0x00000068, 0x8000030c, - 0x00000041, 0x80000307, 0x00000061, 0x80000307, - 0x00000045, 0x80000327, 0x00000065, 0x80000327, - 0x000000d6, 0x80000304, 0x000000f6, 0x80000304, - 0x000000d5, 0x80000304, 0x000000f5, 0x80000304, - 0x0000004f, 0x80000307, 0x0000006f, 0x80000307, - 0x0000022e, 0x80000304, 0x0000022f, 0x80000304, - 0x00000059, 0x80000304, 0x00000079, 0x80000304, - 0x80000068, 0x80000266, 0x8000006a, 0x80000072, - 0x80000279, 0x8000027b, 0x80000281, 0x80000077, - 0x80000079, 0x00000020, 0x80000306, 0x00000020, - 0x80000307, 0x00000020, 0x8000030a, 0x00000020, - 0x80000328, 0x00000020, 0x80000303, 0x00000020, - 0x8000030b, 0x80000263, 0x8000006c, 0x80000073, - 0x80000078, 0x80000295, 0x80000300, 0x80000301, - 0x80000313, 0x00000308, 0x80000301, 0x800002b9, - 0x00000020, 0x80000345, 0x8000003b, 0x00000020, - 0x80000301, 0x000000a8, 0x80000301, 0x00000391, - 0x80000301, 0x800000b7, 0x00000395, 0x80000301, - 0x00000397, 0x80000301, 0x00000399, 0x80000301, - 0x0000039f, 0x80000301, 0x000003a5, 0x80000301, - 0x000003a9, 0x80000301, 0x000003ca, 0x80000301, - 0x00000399, 0x80000308, 0x000003a5, 0x80000308, - 0x000003b1, 0x80000301, 0x000003b5, 0x80000301, - 0x000003b7, 0x80000301, 0x000003b9, 0x80000301, - 0x000003cb, 0x80000301, 0x000003b9, 0x80000308, - 0x000003c5, 0x80000308, 0x000003bf, 0x80000301, - 0x000003c5, 0x80000301, 0x000003c9, 0x80000301, - 0x800003b2, 0x800003b8, 0x800003a5, 0x000003d2, - 0x80000301, 0x000003d2, 0x80000308, 0x800003c6, - 0x800003c0, 0x800003ba, 0x800003c1, 0x800003c2, - 0x80000398, 0x800003b5, 0x800003a3, 0x00000415, - 0x80000300, 0x00000415, 0x80000308, 0x00000413, - 0x80000301, 0x00000406, 0x80000308, 0x0000041a, - 0x80000301, 0x00000418, 0x80000300, 0x00000423, - 0x80000306, 0x00000418, 0x80000306, 0x00000438, - 0x80000306, 0x00000435, 0x80000300, 0x00000435, - 0x80000308, 0x00000433, 0x80000301, 0x00000456, - 0x80000308, 0x0000043a, 0x80000301, 0x00000438, - 0x80000300, 0x00000443, 0x80000306, 0x00000474, - 0x8000030f, 0x00000475, 0x8000030f, 0x00000416, - 0x80000306, 0x00000436, 0x80000306, 0x00000410, - 0x80000306, 0x00000430, 0x80000306, 0x00000410, - 0x80000308, 0x00000430, 0x80000308, 0x00000415, - 0x80000306, 0x00000435, 0x80000306, 0x000004d8, - 0x80000308, 0x000004d9, 0x80000308, 0x00000416, - 0x80000308, 0x00000436, 0x80000308, 0x00000417, - 0x80000308, 0x00000437, 0x80000308, 0x00000418, - 0x80000304, 0x00000438, 0x80000304, 0x00000418, - 0x80000308, 0x00000438, 0x80000308, 0x0000041e, - 0x80000308, 0x0000043e, 0x80000308, 0x000004e8, - 0x80000308, 0x000004e9, 0x80000308, 0x0000042d, - 0x80000308, 0x0000044d, 0x80000308, 0x00000423, - 0x80000304, 0x00000443, 0x80000304, 0x00000423, - 0x80000308, 0x00000443, 0x80000308, 0x00000423, - 0x8000030b, 0x00000443, 0x8000030b, 0x00000427, - 0x80000308, 0x00000447, 0x80000308, 0x0000042b, - 0x80000308, 0x0000044b, 0x80000308, 0x00000565, - 0x80000582, 0x00000627, 0x80000653, 0x00000627, - 0x80000654, 0x00000648, 0x80000654, 0x00000627, - 0x80000655, 0x0000064a, 0x80000654, 0x00000627, - 0x80000674, 0x00000648, 0x80000674, 0x000006c7, - 0x80000674, 0x0000064a, 0x80000674, 0x000006d5, - 0x80000654, 0x000006c1, 0x80000654, 0x000006d2, - 0x80000654, 0x00000928, 0x8000093c, 0x00000930, - 0x8000093c, 0x00000933, 0x8000093c, 0x00000915, - 0x8000093c, 0x00000916, 0x8000093c, 0x00000917, - 0x8000093c, 0x0000091c, 0x8000093c, 0x00000921, - 0x8000093c, 0x00000922, 0x8000093c, 0x0000092b, - 0x8000093c, 0x0000092f, 0x8000093c, 0x000009c7, - 0x800009be, 0x000009c7, 0x800009d7, 0x000009a1, - 0x800009bc, 0x000009a2, 0x800009bc, 0x000009af, - 0x800009bc, 0x00000a32, 0x80000a3c, 0x00000a38, - 0x80000a3c, 0x00000a16, 0x80000a3c, 0x00000a17, - 0x80000a3c, 0x00000a1c, 0x80000a3c, 0x00000a2b, - 0x80000a3c, 0x00000b47, 0x80000b56, 0x00000b47, - 0x80000b3e, 0x00000b47, 0x80000b57, 0x00000b21, - 0x80000b3c, 0x00000b22, 0x80000b3c, 0x00000b92, - 0x80000bd7, 0x00000bc6, 0x80000bbe, 0x00000bc7, - 0x80000bbe, 0x00000bc6, 0x80000bd7, 0x00000c46, - 0x80000c56, 0x00000cbf, 0x80000cd5, 0x00000cc6, - 0x80000cd5, 0x00000cc6, 0x80000cd6, 0x00000cc6, - 0x80000cc2, 0x00000cca, 0x80000cd5, 0x00000d46, - 0x80000d3e, 0x00000d47, 0x80000d3e, 0x00000d46, - 0x80000d57, 0x00000dd9, 0x80000dca, 0x00000dd9, - 0x80000dcf, 0x00000ddc, 0x80000dca, 0x00000dd9, - 0x80000ddf, 0x00000e4d, 0x80000e32, 0x00000ecd, - 0x80000eb2, 0x00000eab, 0x80000e99, 0x00000eab, - 0x80000ea1, 0x80000f0b, 0x00000f42, 0x80000fb7, - 0x00000f4c, 0x80000fb7, 0x00000f51, 0x80000fb7, - 0x00000f56, 0x80000fb7, 0x00000f5b, 0x80000fb7, - 0x00000f40, 0x80000fb5, 0x00000f71, 0x80000f72, - 0x00000f71, 0x80000f74, 0x00000fb2, 0x80000f80, - 0x00000fb2, 0x80000f81, 0x00000fb3, 0x80000f80, - 0x00000fb3, 0x80000f81, 0x00000f71, 0x80000f80, - 0x00000f92, 0x80000fb7, 0x00000f9c, 0x80000fb7, - 0x00000fa1, 0x80000fb7, 0x00000fa6, 0x80000fb7, - 0x00000fab, 0x80000fb7, 0x00000f90, 0x80000fb5, - 0x00001025, 0x8000102e, 0x800010dc, 0x80000041, - 0x800000c6, 0x80000042, 0x80000044, 0x80000045, - 0x8000018e, 0x80000047, 0x80000048, 0x80000049, - 0x8000004a, 0x8000004b, 0x8000004c, 0x8000004d, - 0x8000004e, 0x8000004f, 0x80000222, 0x80000050, - 0x80000052, 0x80000054, 0x80000055, 0x80000057, - 0x80000061, 0x80000250, 0x80000251, 0x80001d02, - 0x80000062, 0x80000064, 0x80000065, 0x80000259, - 0x8000025b, 0x8000025c, 0x80000067, 0x8000006b, - 0x8000006d, 0x8000014b, 0x8000006f, 0x80000254, - 0x80001d16, 0x80001d17, 0x80000070, 0x80000074, - 0x80000075, 0x80001d1d, 0x8000026f, 0x80000076, - 0x80001d25, 0x800003b2, 0x800003b3, 0x800003b4, - 0x800003c6, 0x800003c7, 0x80000069, 0x80000072, - 0x80000075, 0x80000076, 0x800003b2, 0x800003b3, - 0x800003c1, 0x800003c6, 0x800003c7, 0x8000043d, - 0x80000252, 0x80000063, 0x80000255, 0x800000f0, - 0x8000025c, 0x80000066, 0x8000025f, 0x80000261, - 0x80000265, 0x80000268, 0x80000269, 0x8000026a, - 0x80001d7b, 0x8000029d, 0x8000026d, 0x80001d85, - 0x8000029f, 0x80000271, 0x80000270, 0x80000272, - 0x80000273, 0x80000274, 0x80000275, 0x80000278, - 0x80000282, 0x80000283, 0x800001ab, 0x80000289, - 0x8000028a, 0x80001d1c, 0x8000028b, 0x8000028c, - 0x8000007a, 0x80000290, 0x80000291, 0x80000292, - 0x800003b8, 0x00000041, 0x80000325, 0x00000061, - 0x80000325, 0x00000042, 0x80000307, 0x00000062, - 0x80000307, 0x00000042, 0x80000323, 0x00000062, - 0x80000323, 0x00000042, 0x80000331, 0x00000062, - 0x80000331, 0x000000c7, 0x80000301, 0x000000e7, - 0x80000301, 0x00000044, 0x80000307, 0x00000064, - 0x80000307, 0x00000044, 0x80000323, 0x00000064, - 0x80000323, 0x00000044, 0x80000331, 0x00000064, - 0x80000331, 0x00000044, 0x80000327, 0x00000064, - 0x80000327, 0x00000044, 0x8000032d, 0x00000064, - 0x8000032d, 0x00000112, 0x80000300, 0x00000113, - 0x80000300, 0x00000112, 0x80000301, 0x00000113, - 0x80000301, 0x00000045, 0x8000032d, 0x00000065, - 0x8000032d, 0x00000045, 0x80000330, 0x00000065, - 0x80000330, 0x00000228, 0x80000306, 0x00000229, - 0x80000306, 0x00000046, 0x80000307, 0x00000066, - 0x80000307, 0x00000047, 0x80000304, 0x00000067, - 0x80000304, 0x00000048, 0x80000307, 0x00000068, - 0x80000307, 0x00000048, 0x80000323, 0x00000068, - 0x80000323, 0x00000048, 0x80000308, 0x00000068, - 0x80000308, 0x00000048, 0x80000327, 0x00000068, - 0x80000327, 0x00000048, 0x8000032e, 0x00000068, - 0x8000032e, 0x00000049, 0x80000330, 0x00000069, - 0x80000330, 0x000000cf, 0x80000301, 0x000000ef, - 0x80000301, 0x0000004b, 0x80000301, 0x0000006b, - 0x80000301, 0x0000004b, 0x80000323, 0x0000006b, - 0x80000323, 0x0000004b, 0x80000331, 0x0000006b, - 0x80000331, 0x0000004c, 0x80000323, 0x0000006c, - 0x80000323, 0x00001e36, 0x80000304, 0x00001e37, - 0x80000304, 0x0000004c, 0x80000331, 0x0000006c, - 0x80000331, 0x0000004c, 0x8000032d, 0x0000006c, - 0x8000032d, 0x0000004d, 0x80000301, 0x0000006d, - 0x80000301, 0x0000004d, 0x80000307, 0x0000006d, - 0x80000307, 0x0000004d, 0x80000323, 0x0000006d, - 0x80000323, 0x0000004e, 0x80000307, 0x0000006e, - 0x80000307, 0x0000004e, 0x80000323, 0x0000006e, - 0x80000323, 0x0000004e, 0x80000331, 0x0000006e, - 0x80000331, 0x0000004e, 0x8000032d, 0x0000006e, - 0x8000032d, 0x000000d5, 0x80000301, 0x000000f5, - 0x80000301, 0x000000d5, 0x80000308, 0x000000f5, - 0x80000308, 0x0000014c, 0x80000300, 0x0000014d, - 0x80000300, 0x0000014c, 0x80000301, 0x0000014d, - 0x80000301, 0x00000050, 0x80000301, 0x00000070, - 0x80000301, 0x00000050, 0x80000307, 0x00000070, - 0x80000307, 0x00000052, 0x80000307, 0x00000072, - 0x80000307, 0x00000052, 0x80000323, 0x00000072, - 0x80000323, 0x00001e5a, 0x80000304, 0x00001e5b, - 0x80000304, 0x00000052, 0x80000331, 0x00000072, - 0x80000331, 0x00000053, 0x80000307, 0x00000073, - 0x80000307, 0x00000053, 0x80000323, 0x00000073, - 0x80000323, 0x0000015a, 0x80000307, 0x0000015b, - 0x80000307, 0x00000160, 0x80000307, 0x00000161, - 0x80000307, 0x00001e62, 0x80000307, 0x00001e63, - 0x80000307, 0x00000054, 0x80000307, 0x00000074, - 0x80000307, 0x00000054, 0x80000323, 0x00000074, - 0x80000323, 0x00000054, 0x80000331, 0x00000074, - 0x80000331, 0x00000054, 0x8000032d, 0x00000074, - 0x8000032d, 0x00000055, 0x80000324, 0x00000075, - 0x80000324, 0x00000055, 0x80000330, 0x00000075, - 0x80000330, 0x00000055, 0x8000032d, 0x00000075, - 0x8000032d, 0x00000168, 0x80000301, 0x00000169, - 0x80000301, 0x0000016a, 0x80000308, 0x0000016b, - 0x80000308, 0x00000056, 0x80000303, 0x00000076, - 0x80000303, 0x00000056, 0x80000323, 0x00000076, - 0x80000323, 0x00000057, 0x80000300, 0x00000077, - 0x80000300, 0x00000057, 0x80000301, 0x00000077, - 0x80000301, 0x00000057, 0x80000308, 0x00000077, - 0x80000308, 0x00000057, 0x80000307, 0x00000077, - 0x80000307, 0x00000057, 0x80000323, 0x00000077, - 0x80000323, 0x00000058, 0x80000307, 0x00000078, - 0x80000307, 0x00000058, 0x80000308, 0x00000078, - 0x80000308, 0x00000059, 0x80000307, 0x00000079, - 0x80000307, 0x0000005a, 0x80000302, 0x0000007a, - 0x80000302, 0x0000005a, 0x80000323, 0x0000007a, - 0x80000323, 0x0000005a, 0x80000331, 0x0000007a, - 0x80000331, 0x00000068, 0x80000331, 0x00000074, - 0x80000308, 0x00000077, 0x8000030a, 0x00000079, - 0x8000030a, 0x00000061, 0x800002be, 0x0000017f, - 0x80000307, 0x00000041, 0x80000323, 0x00000061, - 0x80000323, 0x00000041, 0x80000309, 0x00000061, - 0x80000309, 0x000000c2, 0x80000301, 0x000000e2, - 0x80000301, 0x000000c2, 0x80000300, 0x000000e2, - 0x80000300, 0x000000c2, 0x80000309, 0x000000e2, - 0x80000309, 0x000000c2, 0x80000303, 0x000000e2, - 0x80000303, 0x00001ea0, 0x80000302, 0x00001ea1, - 0x80000302, 0x00000102, 0x80000301, 0x00000103, - 0x80000301, 0x00000102, 0x80000300, 0x00000103, - 0x80000300, 0x00000102, 0x80000309, 0x00000103, - 0x80000309, 0x00000102, 0x80000303, 0x00000103, - 0x80000303, 0x00001ea0, 0x80000306, 0x00001ea1, - 0x80000306, 0x00000045, 0x80000323, 0x00000065, - 0x80000323, 0x00000045, 0x80000309, 0x00000065, - 0x80000309, 0x00000045, 0x80000303, 0x00000065, - 0x80000303, 0x000000ca, 0x80000301, 0x000000ea, - 0x80000301, 0x000000ca, 0x80000300, 0x000000ea, - 0x80000300, 0x000000ca, 0x80000309, 0x000000ea, - 0x80000309, 0x000000ca, 0x80000303, 0x000000ea, - 0x80000303, 0x00001eb8, 0x80000302, 0x00001eb9, - 0x80000302, 0x00000049, 0x80000309, 0x00000069, - 0x80000309, 0x00000049, 0x80000323, 0x00000069, - 0x80000323, 0x0000004f, 0x80000323, 0x0000006f, - 0x80000323, 0x0000004f, 0x80000309, 0x0000006f, - 0x80000309, 0x000000d4, 0x80000301, 0x000000f4, - 0x80000301, 0x000000d4, 0x80000300, 0x000000f4, - 0x80000300, 0x000000d4, 0x80000309, 0x000000f4, - 0x80000309, 0x000000d4, 0x80000303, 0x000000f4, - 0x80000303, 0x00001ecc, 0x80000302, 0x00001ecd, - 0x80000302, 0x000001a0, 0x80000301, 0x000001a1, - 0x80000301, 0x000001a0, 0x80000300, 0x000001a1, - 0x80000300, 0x000001a0, 0x80000309, 0x000001a1, - 0x80000309, 0x000001a0, 0x80000303, 0x000001a1, - 0x80000303, 0x000001a0, 0x80000323, 0x000001a1, - 0x80000323, 0x00000055, 0x80000323, 0x00000075, - 0x80000323, 0x00000055, 0x80000309, 0x00000075, - 0x80000309, 0x000001af, 0x80000301, 0x000001b0, - 0x80000301, 0x000001af, 0x80000300, 0x000001b0, - 0x80000300, 0x000001af, 0x80000309, 0x000001b0, - 0x80000309, 0x000001af, 0x80000303, 0x000001b0, - 0x80000303, 0x000001af, 0x80000323, 0x000001b0, - 0x80000323, 0x00000059, 0x80000300, 0x00000079, - 0x80000300, 0x00000059, 0x80000323, 0x00000079, - 0x80000323, 0x00000059, 0x80000309, 0x00000079, - 0x80000309, 0x00000059, 0x80000303, 0x00000079, - 0x80000303, 0x000003b1, 0x80000313, 0x000003b1, - 0x80000314, 0x00001f00, 0x80000300, 0x00001f01, - 0x80000300, 0x00001f00, 0x80000301, 0x00001f01, - 0x80000301, 0x00001f00, 0x80000342, 0x00001f01, - 0x80000342, 0x00000391, 0x80000313, 0x00000391, - 0x80000314, 0x00001f08, 0x80000300, 0x00001f09, - 0x80000300, 0x00001f08, 0x80000301, 0x00001f09, - 0x80000301, 0x00001f08, 0x80000342, 0x00001f09, - 0x80000342, 0x000003b5, 0x80000313, 0x000003b5, - 0x80000314, 0x00001f10, 0x80000300, 0x00001f11, - 0x80000300, 0x00001f10, 0x80000301, 0x00001f11, - 0x80000301, 0x00000395, 0x80000313, 0x00000395, - 0x80000314, 0x00001f18, 0x80000300, 0x00001f19, - 0x80000300, 0x00001f18, 0x80000301, 0x00001f19, - 0x80000301, 0x000003b7, 0x80000313, 0x000003b7, - 0x80000314, 0x00001f20, 0x80000300, 0x00001f21, - 0x80000300, 0x00001f20, 0x80000301, 0x00001f21, - 0x80000301, 0x00001f20, 0x80000342, 0x00001f21, - 0x80000342, 0x00000397, 0x80000313, 0x00000397, - 0x80000314, 0x00001f28, 0x80000300, 0x00001f29, - 0x80000300, 0x00001f28, 0x80000301, 0x00001f29, - 0x80000301, 0x00001f28, 0x80000342, 0x00001f29, - 0x80000342, 0x000003b9, 0x80000313, 0x000003b9, - 0x80000314, 0x00001f30, 0x80000300, 0x00001f31, - 0x80000300, 0x00001f30, 0x80000301, 0x00001f31, - 0x80000301, 0x00001f30, 0x80000342, 0x00001f31, - 0x80000342, 0x00000399, 0x80000313, 0x00000399, - 0x80000314, 0x00001f38, 0x80000300, 0x00001f39, - 0x80000300, 0x00001f38, 0x80000301, 0x00001f39, - 0x80000301, 0x00001f38, 0x80000342, 0x00001f39, - 0x80000342, 0x000003bf, 0x80000313, 0x000003bf, - 0x80000314, 0x00001f40, 0x80000300, 0x00001f41, - 0x80000300, 0x00001f40, 0x80000301, 0x00001f41, - 0x80000301, 0x0000039f, 0x80000313, 0x0000039f, - 0x80000314, 0x00001f48, 0x80000300, 0x00001f49, - 0x80000300, 0x00001f48, 0x80000301, 0x00001f49, - 0x80000301, 0x000003c5, 0x80000313, 0x000003c5, - 0x80000314, 0x00001f50, 0x80000300, 0x00001f51, - 0x80000300, 0x00001f50, 0x80000301, 0x00001f51, - 0x80000301, 0x00001f50, 0x80000342, 0x00001f51, - 0x80000342, 0x000003a5, 0x80000314, 0x00001f59, - 0x80000300, 0x00001f59, 0x80000301, 0x00001f59, - 0x80000342, 0x000003c9, 0x80000313, 0x000003c9, - 0x80000314, 0x00001f60, 0x80000300, 0x00001f61, - 0x80000300, 0x00001f60, 0x80000301, 0x00001f61, - 0x80000301, 0x00001f60, 0x80000342, 0x00001f61, - 0x80000342, 0x000003a9, 0x80000313, 0x000003a9, - 0x80000314, 0x00001f68, 0x80000300, 0x00001f69, - 0x80000300, 0x00001f68, 0x80000301, 0x00001f69, - 0x80000301, 0x00001f68, 0x80000342, 0x00001f69, - 0x80000342, 0x000003b1, 0x80000300, 0x800003ac, - 0x000003b5, 0x80000300, 0x800003ad, 0x000003b7, - 0x80000300, 0x800003ae, 0x000003b9, 0x80000300, - 0x800003af, 0x000003bf, 0x80000300, 0x800003cc, - 0x000003c5, 0x80000300, 0x800003cd, 0x000003c9, - 0x80000300, 0x800003ce, 0x00001f00, 0x80000345, - 0x00001f01, 0x80000345, 0x00001f02, 0x80000345, - 0x00001f03, 0x80000345, 0x00001f04, 0x80000345, - 0x00001f05, 0x80000345, 0x00001f06, 0x80000345, - 0x00001f07, 0x80000345, 0x00001f08, 0x80000345, - 0x00001f09, 0x80000345, 0x00001f0a, 0x80000345, - 0x00001f0b, 0x80000345, 0x00001f0c, 0x80000345, - 0x00001f0d, 0x80000345, 0x00001f0e, 0x80000345, - 0x00001f0f, 0x80000345, 0x00001f20, 0x80000345, - 0x00001f21, 0x80000345, 0x00001f22, 0x80000345, - 0x00001f23, 0x80000345, 0x00001f24, 0x80000345, - 0x00001f25, 0x80000345, 0x00001f26, 0x80000345, - 0x00001f27, 0x80000345, 0x00001f28, 0x80000345, - 0x00001f29, 0x80000345, 0x00001f2a, 0x80000345, - 0x00001f2b, 0x80000345, 0x00001f2c, 0x80000345, - 0x00001f2d, 0x80000345, 0x00001f2e, 0x80000345, - 0x00001f2f, 0x80000345, 0x00001f60, 0x80000345, - 0x00001f61, 0x80000345, 0x00001f62, 0x80000345, - 0x00001f63, 0x80000345, 0x00001f64, 0x80000345, - 0x00001f65, 0x80000345, 0x00001f66, 0x80000345, - 0x00001f67, 0x80000345, 0x00001f68, 0x80000345, - 0x00001f69, 0x80000345, 0x00001f6a, 0x80000345, - 0x00001f6b, 0x80000345, 0x00001f6c, 0x80000345, - 0x00001f6d, 0x80000345, 0x00001f6e, 0x80000345, - 0x00001f6f, 0x80000345, 0x000003b1, 0x80000306, - 0x000003b1, 0x80000304, 0x00001f70, 0x80000345, - 0x000003b1, 0x80000345, 0x000003ac, 0x80000345, - 0x000003b1, 0x80000342, 0x00001fb6, 0x80000345, - 0x00000391, 0x80000306, 0x00000391, 0x80000304, - 0x00000391, 0x80000300, 0x80000386, 0x00000391, - 0x80000345, 0x00000020, 0x80000313, 0x800003b9, - 0x00000020, 0x80000313, 0x00000020, 0x80000342, - 0x000000a8, 0x80000342, 0x00001f74, 0x80000345, - 0x000003b7, 0x80000345, 0x000003ae, 0x80000345, - 0x000003b7, 0x80000342, 0x00001fc6, 0x80000345, - 0x00000395, 0x80000300, 0x80000388, 0x00000397, - 0x80000300, 0x80000389, 0x00000397, 0x80000345, - 0x00001fbf, 0x80000300, 0x00001fbf, 0x80000301, - 0x00001fbf, 0x80000342, 0x000003b9, 0x80000306, - 0x000003b9, 0x80000304, 0x000003ca, 0x80000300, - 0x80000390, 0x000003b9, 0x80000342, 0x000003ca, - 0x80000342, 0x00000399, 0x80000306, 0x00000399, - 0x80000304, 0x00000399, 0x80000300, 0x8000038a, - 0x00001ffe, 0x80000300, 0x00001ffe, 0x80000301, - 0x00001ffe, 0x80000342, 0x000003c5, 0x80000306, - 0x000003c5, 0x80000304, 0x000003cb, 0x80000300, - 0x800003b0, 0x000003c1, 0x80000313, 0x000003c1, - 0x80000314, 0x000003c5, 0x80000342, 0x000003cb, - 0x80000342, 0x000003a5, 0x80000306, 0x000003a5, - 0x80000304, 0x000003a5, 0x80000300, 0x8000038e, - 0x000003a1, 0x80000314, 0x000000a8, 0x80000300, - 0x80000385, 0x80000060, 0x00001f7c, 0x80000345, - 0x000003c9, 0x80000345, 0x000003ce, 0x80000345, - 0x000003c9, 0x80000342, 0x00001ff6, 0x80000345, - 0x0000039f, 0x80000300, 0x8000038c, 0x000003a9, - 0x80000300, 0x8000038f, 0x000003a9, 0x80000345, - 0x800000b4, 0x00000020, 0x80000314, 0x80002002, - 0x80002003, 0x80000020, 0x80000020, 0x80000020, - 0x80000020, 0x80000020, 0x80000020, 0x80000020, - 0x80000020, 0x80000020, 0x80002010, 0x00000020, - 0x80000333, 0x8000002e, 0x0000002e, 0x8000002e, - 0x0000002e, 0x0000002e, 0x8000002e, 0x80000020, - 0x00002032, 0x80002032, 0x00002032, 0x00002032, - 0x80002032, 0x00002035, 0x80002035, 0x00002035, - 0x00002035, 0x80002035, 0x00000021, 0x80000021, - 0x00000020, 0x80000305, 0x0000003f, 0x8000003f, - 0x0000003f, 0x80000021, 0x00000021, 0x8000003f, - 0x00002032, 0x00002032, 0x00002032, 0x80002032, - 0x80000020, 0x80000030, 0x80000069, 0x80000034, - 0x80000035, 0x80000036, 0x80000037, 0x80000038, - 0x80000039, 0x8000002b, 0x80002212, 0x8000003d, - 0x80000028, 0x80000029, 0x8000006e, 0x80000030, - 0x80000031, 0x80000032, 0x80000033, 0x80000034, - 0x80000035, 0x80000036, 0x80000037, 0x80000038, - 0x80000039, 0x8000002b, 0x80002212, 0x8000003d, - 0x80000028, 0x80000029, 0x80000061, 0x80000065, - 0x8000006f, 0x80000078, 0x80000259, 0x00000052, - 0x80000073, 0x00000061, 0x0000002f, 0x80000063, - 0x00000061, 0x0000002f, 0x80000073, 0x80000043, - 0x000000b0, 0x80000043, 0x00000063, 0x0000002f, - 0x8000006f, 0x00000063, 0x0000002f, 0x80000075, - 0x80000190, 0x000000b0, 0x80000046, 0x80000067, - 0x80000048, 0x80000048, 0x80000048, 0x80000068, - 0x80000127, 0x80000049, 0x80000049, 0x8000004c, - 0x8000006c, 0x8000004e, 0x0000004e, 0x8000006f, - 0x80000050, 0x80000051, 0x80000052, 0x80000052, - 0x80000052, 0x00000053, 0x8000004d, 0x00000054, - 0x00000045, 0x8000004c, 0x00000054, 0x8000004d, - 0x8000005a, 0x800003a9, 0x8000005a, 0x8000004b, - 0x800000c5, 0x80000042, 0x80000043, 0x80000065, - 0x80000045, 0x80000046, 0x8000004d, 0x8000006f, - 0x800005d0, 0x800005d1, 0x800005d2, 0x800005d3, - 0x80000069, 0x00000046, 0x00000041, 0x80000058, - 0x800003c0, 0x800003b3, 0x80000393, 0x800003a0, - 0x80002211, 0x80000044, 0x80000064, 0x80000065, - 0x80000069, 0x8000006a, 0x00000031, 0x00002044, - 0x80000033, 0x00000032, 0x00002044, 0x80000033, - 0x00000031, 0x00002044, 0x80000035, 0x00000032, - 0x00002044, 0x80000035, 0x00000033, 0x00002044, - 0x80000035, 0x00000034, 0x00002044, 0x80000035, - 0x00000031, 0x00002044, 0x80000036, 0x00000035, - 0x00002044, 0x80000036, 0x00000031, 0x00002044, - 0x80000038, 0x00000033, 0x00002044, 0x80000038, - 0x00000035, 0x00002044, 0x80000038, 0x00000037, - 0x00002044, 0x80000038, 0x00000031, 0x80002044, - 0x80000049, 0x00000049, 0x80000049, 0x00000049, - 0x00000049, 0x80000049, 0x00000049, 0x80000056, - 0x80000056, 0x00000056, 0x80000049, 0x00000056, - 0x00000049, 0x80000049, 0x00000056, 0x00000049, - 0x00000049, 0x80000049, 0x00000049, 0x80000058, - 0x80000058, 0x00000058, 0x80000049, 0x00000058, - 0x00000049, 0x80000049, 0x8000004c, 0x80000043, - 0x80000044, 0x8000004d, 0x80000069, 0x00000069, - 0x80000069, 0x00000069, 0x00000069, 0x80000069, - 0x00000069, 0x80000076, 0x80000076, 0x00000076, - 0x80000069, 0x00000076, 0x00000069, 0x80000069, - 0x00000076, 0x00000069, 0x00000069, 0x80000069, - 0x00000069, 0x80000078, 0x80000078, 0x00000078, - 0x80000069, 0x00000078, 0x00000069, 0x80000069, - 0x8000006c, 0x80000063, 0x80000064, 0x8000006d, - 0x00002190, 0x80000338, 0x00002192, 0x80000338, - 0x00002194, 0x80000338, 0x000021d0, 0x80000338, - 0x000021d4, 0x80000338, 0x000021d2, 0x80000338, - 0x00002203, 0x80000338, 0x00002208, 0x80000338, - 0x0000220b, 0x80000338, 0x00002223, 0x80000338, - 0x00002225, 0x80000338, 0x0000222b, 0x8000222b, - 0x0000222b, 0x0000222b, 0x8000222b, 0x0000222e, - 0x8000222e, 0x0000222e, 0x0000222e, 0x8000222e, - 0x0000223c, 0x80000338, 0x00002243, 0x80000338, - 0x00002245, 0x80000338, 0x00002248, 0x80000338, - 0x0000003d, 0x80000338, 0x00002261, 0x80000338, - 0x0000224d, 0x80000338, 0x0000003c, 0x80000338, - 0x0000003e, 0x80000338, 0x00002264, 0x80000338, - 0x00002265, 0x80000338, 0x00002272, 0x80000338, - 0x00002273, 0x80000338, 0x00002276, 0x80000338, - 0x00002277, 0x80000338, 0x0000227a, 0x80000338, - 0x0000227b, 0x80000338, 0x00002282, 0x80000338, - 0x00002283, 0x80000338, 0x00002286, 0x80000338, - 0x00002287, 0x80000338, 0x000022a2, 0x80000338, - 0x000022a8, 0x80000338, 0x000022a9, 0x80000338, - 0x000022ab, 0x80000338, 0x0000227c, 0x80000338, - 0x0000227d, 0x80000338, 0x00002291, 0x80000338, - 0x00002292, 0x80000338, 0x000022b2, 0x80000338, - 0x000022b3, 0x80000338, 0x000022b4, 0x80000338, - 0x000022b5, 0x80000338, 0x80003008, 0x80003009, - 0x80000031, 0x80000032, 0x80000033, 0x80000034, - 0x80000035, 0x80000036, 0x80000037, 0x80000038, - 0x80000039, 0x00000031, 0x80000030, 0x00000031, - 0x80000031, 0x00000031, 0x80000032, 0x00000031, - 0x80000033, 0x00000031, 0x80000034, 0x00000031, - 0x80000035, 0x00000031, 0x80000036, 0x00000031, - 0x80000037, 0x00000031, 0x80000038, 0x00000031, - 0x80000039, 0x00000032, 0x80000030, 0x00000028, - 0x00000031, 0x80000029, 0x00000028, 0x00000032, - 0x80000029, 0x00000028, 0x00000033, 0x80000029, - 0x00000028, 0x00000034, 0x80000029, 0x00000028, - 0x00000035, 0x80000029, 0x00000028, 0x00000036, - 0x80000029, 0x00000028, 0x00000037, 0x80000029, - 0x00000028, 0x00000038, 0x80000029, 0x00000028, - 0x00000039, 0x80000029, 0x00000028, 0x00000031, - 0x00000030, 0x80000029, 0x00000028, 0x00000031, - 0x00000031, 0x80000029, 0x00000028, 0x00000031, - 0x00000032, 0x80000029, 0x00000028, 0x00000031, - 0x00000033, 0x80000029, 0x00000028, 0x00000031, - 0x00000034, 0x80000029, 0x00000028, 0x00000031, - 0x00000035, 0x80000029, 0x00000028, 0x00000031, - 0x00000036, 0x80000029, 0x00000028, 0x00000031, - 0x00000037, 0x80000029, 0x00000028, 0x00000031, - 0x00000038, 0x80000029, 0x00000028, 0x00000031, - 0x00000039, 0x80000029, 0x00000028, 0x00000032, - 0x00000030, 0x80000029, 0x00000031, 0x8000002e, - 0x00000032, 0x8000002e, 0x00000033, 0x8000002e, - 0x00000034, 0x8000002e, 0x00000035, 0x8000002e, - 0x00000036, 0x8000002e, 0x00000037, 0x8000002e, - 0x00000038, 0x8000002e, 0x00000039, 0x8000002e, - 0x00000031, 0x00000030, 0x8000002e, 0x00000031, - 0x00000031, 0x8000002e, 0x00000031, 0x00000032, - 0x8000002e, 0x00000031, 0x00000033, 0x8000002e, - 0x00000031, 0x00000034, 0x8000002e, 0x00000031, - 0x00000035, 0x8000002e, 0x00000031, 0x00000036, - 0x8000002e, 0x00000031, 0x00000037, 0x8000002e, - 0x00000031, 0x00000038, 0x8000002e, 0x00000031, - 0x00000039, 0x8000002e, 0x00000032, 0x00000030, - 0x8000002e, 0x00000028, 0x00000061, 0x80000029, - 0x00000028, 0x00000062, 0x80000029, 0x00000028, - 0x00000063, 0x80000029, 0x00000028, 0x00000064, - 0x80000029, 0x00000028, 0x00000065, 0x80000029, - 0x00000028, 0x00000066, 0x80000029, 0x00000028, - 0x00000067, 0x80000029, 0x00000028, 0x00000068, - 0x80000029, 0x00000028, 0x00000069, 0x80000029, - 0x00000028, 0x0000006a, 0x80000029, 0x00000028, - 0x0000006b, 0x80000029, 0x00000028, 0x0000006c, - 0x80000029, 0x00000028, 0x0000006d, 0x80000029, - 0x00000028, 0x0000006e, 0x80000029, 0x00000028, - 0x0000006f, 0x80000029, 0x00000028, 0x00000070, - 0x80000029, 0x00000028, 0x00000071, 0x80000029, - 0x00000028, 0x00000072, 0x80000029, 0x00000028, - 0x00000073, 0x80000029, 0x00000028, 0x00000074, - 0x80000029, 0x00000028, 0x00000075, 0x80000029, - 0x00000028, 0x00000076, 0x80000029, 0x00000028, - 0x00000077, 0x80000029, 0x00000028, 0x00000078, - 0x80000029, 0x00000028, 0x00000079, 0x80000029, - 0x00000028, 0x0000007a, 0x80000029, 0x80000041, - 0x80000042, 0x80000043, 0x80000044, 0x80000045, - 0x80000046, 0x80000047, 0x80000048, 0x80000049, - 0x8000004a, 0x8000004b, 0x8000004c, 0x8000004d, - 0x8000004e, 0x8000004f, 0x80000050, 0x80000051, - 0x80000052, 0x80000053, 0x80000054, 0x80000055, - 0x80000056, 0x80000057, 0x80000058, 0x80000059, - 0x8000005a, 0x80000061, 0x80000062, 0x80000063, - 0x80000064, 0x80000065, 0x80000066, 0x80000067, - 0x80000068, 0x80000069, 0x8000006a, 0x8000006b, - 0x8000006c, 0x8000006d, 0x8000006e, 0x8000006f, - 0x80000070, 0x80000071, 0x80000072, 0x80000073, - 0x80000074, 0x80000075, 0x80000076, 0x80000077, - 0x80000078, 0x80000079, 0x8000007a, 0x80000030, - 0x0000222b, 0x0000222b, 0x0000222b, 0x8000222b, - 0x0000003a, 0x0000003a, 0x8000003d, 0x0000003d, - 0x8000003d, 0x0000003d, 0x0000003d, 0x8000003d, - 0x00002add, 0x80000338, 0x80002d61, 0x80006bcd, - 0x80009f9f, 0x80004e00, 0x80004e28, 0x80004e36, - 0x80004e3f, 0x80004e59, 0x80004e85, 0x80004e8c, - 0x80004ea0, 0x80004eba, 0x8000513f, 0x80005165, - 0x8000516b, 0x80005182, 0x80005196, 0x800051ab, - 0x800051e0, 0x800051f5, 0x80005200, 0x8000529b, - 0x800052f9, 0x80005315, 0x8000531a, 0x80005338, - 0x80005341, 0x8000535c, 0x80005369, 0x80005382, - 0x800053b6, 0x800053c8, 0x800053e3, 0x800056d7, - 0x8000571f, 0x800058eb, 0x80005902, 0x8000590a, - 0x80005915, 0x80005927, 0x80005973, 0x80005b50, - 0x80005b80, 0x80005bf8, 0x80005c0f, 0x80005c22, - 0x80005c38, 0x80005c6e, 0x80005c71, 0x80005ddb, - 0x80005de5, 0x80005df1, 0x80005dfe, 0x80005e72, - 0x80005e7a, 0x80005e7f, 0x80005ef4, 0x80005efe, - 0x80005f0b, 0x80005f13, 0x80005f50, 0x80005f61, - 0x80005f73, 0x80005fc3, 0x80006208, 0x80006236, - 0x8000624b, 0x8000652f, 0x80006534, 0x80006587, - 0x80006597, 0x800065a4, 0x800065b9, 0x800065e0, - 0x800065e5, 0x800066f0, 0x80006708, 0x80006728, - 0x80006b20, 0x80006b62, 0x80006b79, 0x80006bb3, - 0x80006bcb, 0x80006bd4, 0x80006bdb, 0x80006c0f, - 0x80006c14, 0x80006c34, 0x8000706b, 0x8000722a, - 0x80007236, 0x8000723b, 0x8000723f, 0x80007247, - 0x80007259, 0x8000725b, 0x800072ac, 0x80007384, - 0x80007389, 0x800074dc, 0x800074e6, 0x80007518, - 0x8000751f, 0x80007528, 0x80007530, 0x8000758b, - 0x80007592, 0x80007676, 0x8000767d, 0x800076ae, - 0x800076bf, 0x800076ee, 0x800077db, 0x800077e2, - 0x800077f3, 0x8000793a, 0x800079b8, 0x800079be, - 0x80007a74, 0x80007acb, 0x80007af9, 0x80007c73, - 0x80007cf8, 0x80007f36, 0x80007f51, 0x80007f8a, - 0x80007fbd, 0x80008001, 0x8000800c, 0x80008012, - 0x80008033, 0x8000807f, 0x80008089, 0x800081e3, - 0x800081ea, 0x800081f3, 0x800081fc, 0x8000820c, - 0x8000821b, 0x8000821f, 0x8000826e, 0x80008272, - 0x80008278, 0x8000864d, 0x8000866b, 0x80008840, - 0x8000884c, 0x80008863, 0x8000897e, 0x8000898b, - 0x800089d2, 0x80008a00, 0x80008c37, 0x80008c46, - 0x80008c55, 0x80008c78, 0x80008c9d, 0x80008d64, - 0x80008d70, 0x80008db3, 0x80008eab, 0x80008eca, - 0x80008f9b, 0x80008fb0, 0x80008fb5, 0x80009091, - 0x80009149, 0x800091c6, 0x800091cc, 0x800091d1, - 0x80009577, 0x80009580, 0x8000961c, 0x800096b6, - 0x800096b9, 0x800096e8, 0x80009751, 0x8000975e, - 0x80009762, 0x80009769, 0x800097cb, 0x800097ed, - 0x800097f3, 0x80009801, 0x800098a8, 0x800098db, - 0x800098df, 0x80009996, 0x80009999, 0x800099ac, - 0x80009aa8, 0x80009ad8, 0x80009adf, 0x80009b25, - 0x80009b2f, 0x80009b32, 0x80009b3c, 0x80009b5a, - 0x80009ce5, 0x80009e75, 0x80009e7f, 0x80009ea5, - 0x80009ebb, 0x80009ec3, 0x80009ecd, 0x80009ed1, - 0x80009ef9, 0x80009efd, 0x80009f0e, 0x80009f13, - 0x80009f20, 0x80009f3b, 0x80009f4a, 0x80009f52, - 0x80009f8d, 0x80009f9c, 0x80009fa0, 0x80000020, - 0x80003012, 0x80005341, 0x80005344, 0x80005345, - 0x0000304b, 0x80003099, 0x0000304d, 0x80003099, - 0x0000304f, 0x80003099, 0x00003051, 0x80003099, - 0x00003053, 0x80003099, 0x00003055, 0x80003099, - 0x00003057, 0x80003099, 0x00003059, 0x80003099, - 0x0000305b, 0x80003099, 0x0000305d, 0x80003099, - 0x0000305f, 0x80003099, 0x00003061, 0x80003099, - 0x00003064, 0x80003099, 0x00003066, 0x80003099, - 0x00003068, 0x80003099, 0x0000306f, 0x80003099, - 0x0000306f, 0x8000309a, 0x00003072, 0x80003099, - 0x00003072, 0x8000309a, 0x00003075, 0x80003099, - 0x00003075, 0x8000309a, 0x00003078, 0x80003099, - 0x00003078, 0x8000309a, 0x0000307b, 0x80003099, - 0x0000307b, 0x8000309a, 0x00003046, 0x80003099, - 0x00000020, 0x80003099, 0x00000020, 0x8000309a, - 0x0000309d, 0x80003099, 0x00003088, 0x8000308a, - 0x000030ab, 0x80003099, 0x000030ad, 0x80003099, - 0x000030af, 0x80003099, 0x000030b1, 0x80003099, - 0x000030b3, 0x80003099, 0x000030b5, 0x80003099, - 0x000030b7, 0x80003099, 0x000030b9, 0x80003099, - 0x000030bb, 0x80003099, 0x000030bd, 0x80003099, - 0x000030bf, 0x80003099, 0x000030c1, 0x80003099, - 0x000030c4, 0x80003099, 0x000030c6, 0x80003099, - 0x000030c8, 0x80003099, 0x000030cf, 0x80003099, - 0x000030cf, 0x8000309a, 0x000030d2, 0x80003099, - 0x000030d2, 0x8000309a, 0x000030d5, 0x80003099, - 0x000030d5, 0x8000309a, 0x000030d8, 0x80003099, - 0x000030d8, 0x8000309a, 0x000030db, 0x80003099, - 0x000030db, 0x8000309a, 0x000030a6, 0x80003099, - 0x000030ef, 0x80003099, 0x000030f0, 0x80003099, - 0x000030f1, 0x80003099, 0x000030f2, 0x80003099, - 0x000030fd, 0x80003099, 0x000030b3, 0x800030c8, - 0x80001100, 0x80001101, 0x800011aa, 0x80001102, - 0x800011ac, 0x800011ad, 0x80001103, 0x80001104, - 0x80001105, 0x800011b0, 0x800011b1, 0x800011b2, - 0x800011b3, 0x800011b4, 0x800011b5, 0x8000111a, - 0x80001106, 0x80001107, 0x80001108, 0x80001121, - 0x80001109, 0x8000110a, 0x8000110b, 0x8000110c, - 0x8000110d, 0x8000110e, 0x8000110f, 0x80001110, - 0x80001111, 0x80001112, 0x80001161, 0x80001162, - 0x80001163, 0x80001164, 0x80001165, 0x80001166, - 0x80001167, 0x80001168, 0x80001169, 0x8000116a, - 0x8000116b, 0x8000116c, 0x8000116d, 0x8000116e, - 0x8000116f, 0x80001170, 0x80001171, 0x80001172, - 0x80001173, 0x80001174, 0x80001175, 0x80001160, - 0x80001114, 0x80001115, 0x800011c7, 0x800011c8, - 0x800011cc, 0x800011ce, 0x800011d3, 0x800011d7, - 0x800011d9, 0x8000111c, 0x800011dd, 0x800011df, - 0x8000111d, 0x8000111e, 0x80001120, 0x80001122, - 0x80001123, 0x80001127, 0x80001129, 0x8000112b, - 0x8000112c, 0x8000112d, 0x8000112e, 0x8000112f, - 0x80001132, 0x80001136, 0x80001140, 0x80001147, - 0x8000114c, 0x800011f1, 0x800011f2, 0x80001157, - 0x80001158, 0x80001159, 0x80001184, 0x80001185, - 0x80001188, 0x80001191, 0x80001192, 0x80001194, - 0x8000119e, 0x800011a1, 0x80004e00, 0x80004e8c, - 0x80004e09, 0x800056db, 0x80004e0a, 0x80004e2d, - 0x80004e0b, 0x80007532, 0x80004e59, 0x80004e19, - 0x80004e01, 0x80005929, 0x80005730, 0x80004eba, - 0x00000028, 0x00001100, 0x80000029, 0x00000028, - 0x00001102, 0x80000029, 0x00000028, 0x00001103, - 0x80000029, 0x00000028, 0x00001105, 0x80000029, - 0x00000028, 0x00001106, 0x80000029, 0x00000028, - 0x00001107, 0x80000029, 0x00000028, 0x00001109, - 0x80000029, 0x00000028, 0x0000110b, 0x80000029, - 0x00000028, 0x0000110c, 0x80000029, 0x00000028, - 0x0000110e, 0x80000029, 0x00000028, 0x0000110f, - 0x80000029, 0x00000028, 0x00001110, 0x80000029, - 0x00000028, 0x00001111, 0x80000029, 0x00000028, - 0x00001112, 0x80000029, 0x00000028, 0x00001100, - 0x00001161, 0x80000029, 0x00000028, 0x00001102, - 0x00001161, 0x80000029, 0x00000028, 0x00001103, - 0x00001161, 0x80000029, 0x00000028, 0x00001105, - 0x00001161, 0x80000029, 0x00000028, 0x00001106, - 0x00001161, 0x80000029, 0x00000028, 0x00001107, - 0x00001161, 0x80000029, 0x00000028, 0x00001109, - 0x00001161, 0x80000029, 0x00000028, 0x0000110b, - 0x00001161, 0x80000029, 0x00000028, 0x0000110c, - 0x00001161, 0x80000029, 0x00000028, 0x0000110e, - 0x00001161, 0x80000029, 0x00000028, 0x0000110f, - 0x00001161, 0x80000029, 0x00000028, 0x00001110, - 0x00001161, 0x80000029, 0x00000028, 0x00001111, - 0x00001161, 0x80000029, 0x00000028, 0x00001112, - 0x00001161, 0x80000029, 0x00000028, 0x0000110c, - 0x0000116e, 0x80000029, 0x00000028, 0x0000110b, - 0x00001169, 0x0000110c, 0x00001165, 0x000011ab, - 0x80000029, 0x00000028, 0x0000110b, 0x00001169, - 0x00001112, 0x0000116e, 0x80000029, 0x00000028, - 0x00004e00, 0x80000029, 0x00000028, 0x00004e8c, - 0x80000029, 0x00000028, 0x00004e09, 0x80000029, - 0x00000028, 0x000056db, 0x80000029, 0x00000028, - 0x00004e94, 0x80000029, 0x00000028, 0x0000516d, - 0x80000029, 0x00000028, 0x00004e03, 0x80000029, - 0x00000028, 0x0000516b, 0x80000029, 0x00000028, - 0x00004e5d, 0x80000029, 0x00000028, 0x00005341, - 0x80000029, 0x00000028, 0x00006708, 0x80000029, - 0x00000028, 0x0000706b, 0x80000029, 0x00000028, - 0x00006c34, 0x80000029, 0x00000028, 0x00006728, - 0x80000029, 0x00000028, 0x000091d1, 0x80000029, - 0x00000028, 0x0000571f, 0x80000029, 0x00000028, - 0x000065e5, 0x80000029, 0x00000028, 0x0000682a, - 0x80000029, 0x00000028, 0x00006709, 0x80000029, - 0x00000028, 0x0000793e, 0x80000029, 0x00000028, - 0x0000540d, 0x80000029, 0x00000028, 0x00007279, - 0x80000029, 0x00000028, 0x00008ca1, 0x80000029, - 0x00000028, 0x0000795d, 0x80000029, 0x00000028, - 0x000052b4, 0x80000029, 0x00000028, 0x00004ee3, - 0x80000029, 0x00000028, 0x0000547c, 0x80000029, - 0x00000028, 0x00005b66, 0x80000029, 0x00000028, - 0x000076e3, 0x80000029, 0x00000028, 0x00004f01, - 0x80000029, 0x00000028, 0x00008cc7, 0x80000029, - 0x00000028, 0x00005354, 0x80000029, 0x00000028, - 0x0000796d, 0x80000029, 0x00000028, 0x00004f11, - 0x80000029, 0x00000028, 0x000081ea, 0x80000029, - 0x00000028, 0x000081f3, 0x80000029, 0x00000050, - 0x00000054, 0x80000045, 0x00000032, 0x80000031, - 0x00000032, 0x80000032, 0x00000032, 0x80000033, - 0x00000032, 0x80000034, 0x00000032, 0x80000035, - 0x00000032, 0x80000036, 0x00000032, 0x80000037, - 0x00000032, 0x80000038, 0x00000032, 0x80000039, - 0x00000033, 0x80000030, 0x00000033, 0x80000031, - 0x00000033, 0x80000032, 0x00000033, 0x80000033, - 0x00000033, 0x80000034, 0x00000033, 0x80000035, - 0x80001100, 0x80001102, 0x80001103, 0x80001105, - 0x80001106, 0x80001107, 0x80001109, 0x8000110b, - 0x8000110c, 0x8000110e, 0x8000110f, 0x80001110, - 0x80001111, 0x80001112, 0x00001100, 0x80001161, - 0x00001102, 0x80001161, 0x00001103, 0x80001161, - 0x00001105, 0x80001161, 0x00001106, 0x80001161, - 0x00001107, 0x80001161, 0x00001109, 0x80001161, - 0x0000110b, 0x80001161, 0x0000110c, 0x80001161, - 0x0000110e, 0x80001161, 0x0000110f, 0x80001161, - 0x00001110, 0x80001161, 0x00001111, 0x80001161, - 0x00001112, 0x80001161, 0x0000110e, 0x00001161, - 0x000011b7, 0x00001100, 0x80001169, 0x0000110c, - 0x0000116e, 0x0000110b, 0x80001174, 0x0000110b, - 0x8000116e, 0x80004e00, 0x80004e8c, 0x80004e09, - 0x800056db, 0x80004e94, 0x8000516d, 0x80004e03, - 0x8000516b, 0x80004e5d, 0x80005341, 0x80006708, - 0x8000706b, 0x80006c34, 0x80006728, 0x800091d1, - 0x8000571f, 0x800065e5, 0x8000682a, 0x80006709, - 0x8000793e, 0x8000540d, 0x80007279, 0x80008ca1, - 0x8000795d, 0x800052b4, 0x800079d8, 0x80007537, - 0x80005973, 0x80009069, 0x8000512a, 0x80005370, - 0x80006ce8, 0x80009805, 0x80004f11, 0x80005199, - 0x80006b63, 0x80004e0a, 0x80004e2d, 0x80004e0b, - 0x80005de6, 0x800053f3, 0x8000533b, 0x80005b97, - 0x80005b66, 0x800076e3, 0x80004f01, 0x80008cc7, - 0x80005354, 0x8000591c, 0x00000033, 0x80000036, - 0x00000033, 0x80000037, 0x00000033, 0x80000038, - 0x00000033, 0x80000039, 0x00000034, 0x80000030, - 0x00000034, 0x80000031, 0x00000034, 0x80000032, - 0x00000034, 0x80000033, 0x00000034, 0x80000034, - 0x00000034, 0x80000035, 0x00000034, 0x80000036, - 0x00000034, 0x80000037, 0x00000034, 0x80000038, - 0x00000034, 0x80000039, 0x00000035, 0x80000030, - 0x00000031, 0x80006708, 0x00000032, 0x80006708, - 0x00000033, 0x80006708, 0x00000034, 0x80006708, - 0x00000035, 0x80006708, 0x00000036, 0x80006708, - 0x00000037, 0x80006708, 0x00000038, 0x80006708, - 0x00000039, 0x80006708, 0x00000031, 0x00000030, - 0x80006708, 0x00000031, 0x00000031, 0x80006708, - 0x00000031, 0x00000032, 0x80006708, 0x00000048, - 0x80000067, 0x00000065, 0x00000072, 0x80000067, - 0x00000065, 0x80000056, 0x0000004c, 0x00000054, - 0x80000044, 0x800030a2, 0x800030a4, 0x800030a6, - 0x800030a8, 0x800030aa, 0x800030ab, 0x800030ad, - 0x800030af, 0x800030b1, 0x800030b3, 0x800030b5, - 0x800030b7, 0x800030b9, 0x800030bb, 0x800030bd, - 0x800030bf, 0x800030c1, 0x800030c4, 0x800030c6, - 0x800030c8, 0x800030ca, 0x800030cb, 0x800030cc, - 0x800030cd, 0x800030ce, 0x800030cf, 0x800030d2, - 0x800030d5, 0x800030d8, 0x800030db, 0x800030de, - 0x800030df, 0x800030e0, 0x800030e1, 0x800030e2, - 0x800030e4, 0x800030e6, 0x800030e8, 0x800030e9, - 0x800030ea, 0x800030eb, 0x800030ec, 0x800030ed, - 0x800030ef, 0x800030f0, 0x800030f1, 0x800030f2, - 0x000030a2, 0x000030d1, 0x000030fc, 0x800030c8, - 0x000030a2, 0x000030eb, 0x000030d5, 0x800030a1, - 0x000030a2, 0x000030f3, 0x000030da, 0x800030a2, - 0x000030a2, 0x000030fc, 0x800030eb, 0x000030a4, - 0x000030cb, 0x000030f3, 0x800030b0, 0x000030a4, - 0x000030f3, 0x800030c1, 0x000030a6, 0x000030a9, - 0x800030f3, 0x000030a8, 0x000030b9, 0x000030af, - 0x000030fc, 0x800030c9, 0x000030a8, 0x000030fc, - 0x000030ab, 0x800030fc, 0x000030aa, 0x000030f3, - 0x800030b9, 0x000030aa, 0x000030fc, 0x800030e0, - 0x000030ab, 0x000030a4, 0x800030ea, 0x000030ab, - 0x000030e9, 0x000030c3, 0x800030c8, 0x000030ab, - 0x000030ed, 0x000030ea, 0x800030fc, 0x000030ac, - 0x000030ed, 0x800030f3, 0x000030ac, 0x000030f3, - 0x800030de, 0x000030ae, 0x800030ac, 0x000030ae, - 0x000030cb, 0x800030fc, 0x000030ad, 0x000030e5, - 0x000030ea, 0x800030fc, 0x000030ae, 0x000030eb, - 0x000030c0, 0x800030fc, 0x000030ad, 0x800030ed, - 0x000030ad, 0x000030ed, 0x000030b0, 0x000030e9, - 0x800030e0, 0x000030ad, 0x000030ed, 0x000030e1, - 0x000030fc, 0x000030c8, 0x800030eb, 0x000030ad, - 0x000030ed, 0x000030ef, 0x000030c3, 0x800030c8, - 0x000030b0, 0x000030e9, 0x800030e0, 0x000030b0, - 0x000030e9, 0x000030e0, 0x000030c8, 0x800030f3, - 0x000030af, 0x000030eb, 0x000030bc, 0x000030a4, - 0x800030ed, 0x000030af, 0x000030ed, 0x000030fc, - 0x800030cd, 0x000030b1, 0x000030fc, 0x800030b9, - 0x000030b3, 0x000030eb, 0x800030ca, 0x000030b3, - 0x000030fc, 0x800030dd, 0x000030b5, 0x000030a4, - 0x000030af, 0x800030eb, 0x000030b5, 0x000030f3, - 0x000030c1, 0x000030fc, 0x800030e0, 0x000030b7, - 0x000030ea, 0x000030f3, 0x800030b0, 0x000030bb, - 0x000030f3, 0x800030c1, 0x000030bb, 0x000030f3, - 0x800030c8, 0x000030c0, 0x000030fc, 0x800030b9, - 0x000030c7, 0x800030b7, 0x000030c9, 0x800030eb, - 0x000030c8, 0x800030f3, 0x000030ca, 0x800030ce, - 0x000030ce, 0x000030c3, 0x800030c8, 0x000030cf, - 0x000030a4, 0x800030c4, 0x000030d1, 0x000030fc, - 0x000030bb, 0x000030f3, 0x800030c8, 0x000030d1, - 0x000030fc, 0x800030c4, 0x000030d0, 0x000030fc, - 0x000030ec, 0x800030eb, 0x000030d4, 0x000030a2, - 0x000030b9, 0x000030c8, 0x800030eb, 0x000030d4, - 0x000030af, 0x800030eb, 0x000030d4, 0x800030b3, - 0x000030d3, 0x800030eb, 0x000030d5, 0x000030a1, - 0x000030e9, 0x000030c3, 0x800030c9, 0x000030d5, - 0x000030a3, 0x000030fc, 0x800030c8, 0x000030d6, - 0x000030c3, 0x000030b7, 0x000030a7, 0x800030eb, - 0x000030d5, 0x000030e9, 0x800030f3, 0x000030d8, - 0x000030af, 0x000030bf, 0x000030fc, 0x800030eb, - 0x000030da, 0x800030bd, 0x000030da, 0x000030cb, - 0x800030d2, 0x000030d8, 0x000030eb, 0x800030c4, - 0x000030da, 0x000030f3, 0x800030b9, 0x000030da, - 0x000030fc, 0x800030b8, 0x000030d9, 0x000030fc, - 0x800030bf, 0x000030dd, 0x000030a4, 0x000030f3, - 0x800030c8, 0x000030dc, 0x000030eb, 0x800030c8, - 0x000030db, 0x800030f3, 0x000030dd, 0x000030f3, - 0x800030c9, 0x000030db, 0x000030fc, 0x800030eb, - 0x000030db, 0x000030fc, 0x800030f3, 0x000030de, - 0x000030a4, 0x000030af, 0x800030ed, 0x000030de, - 0x000030a4, 0x800030eb, 0x000030de, 0x000030c3, - 0x800030cf, 0x000030de, 0x000030eb, 0x800030af, - 0x000030de, 0x000030f3, 0x000030b7, 0x000030e7, - 0x800030f3, 0x000030df, 0x000030af, 0x000030ed, - 0x800030f3, 0x000030df, 0x800030ea, 0x000030df, - 0x000030ea, 0x000030d0, 0x000030fc, 0x800030eb, - 0x000030e1, 0x800030ac, 0x000030e1, 0x000030ac, - 0x000030c8, 0x800030f3, 0x000030e1, 0x000030fc, - 0x000030c8, 0x800030eb, 0x000030e4, 0x000030fc, - 0x800030c9, 0x000030e4, 0x000030fc, 0x800030eb, - 0x000030e6, 0x000030a2, 0x800030f3, 0x000030ea, - 0x000030c3, 0x000030c8, 0x800030eb, 0x000030ea, - 0x800030e9, 0x000030eb, 0x000030d4, 0x800030fc, - 0x000030eb, 0x000030fc, 0x000030d6, 0x800030eb, - 0x000030ec, 0x800030e0, 0x000030ec, 0x000030f3, - 0x000030c8, 0x000030b2, 0x800030f3, 0x000030ef, - 0x000030c3, 0x800030c8, 0x00000030, 0x800070b9, - 0x00000031, 0x800070b9, 0x00000032, 0x800070b9, - 0x00000033, 0x800070b9, 0x00000034, 0x800070b9, - 0x00000035, 0x800070b9, 0x00000036, 0x800070b9, - 0x00000037, 0x800070b9, 0x00000038, 0x800070b9, - 0x00000039, 0x800070b9, 0x00000031, 0x00000030, - 0x800070b9, 0x00000031, 0x00000031, 0x800070b9, - 0x00000031, 0x00000032, 0x800070b9, 0x00000031, - 0x00000033, 0x800070b9, 0x00000031, 0x00000034, - 0x800070b9, 0x00000031, 0x00000035, 0x800070b9, - 0x00000031, 0x00000036, 0x800070b9, 0x00000031, - 0x00000037, 0x800070b9, 0x00000031, 0x00000038, - 0x800070b9, 0x00000031, 0x00000039, 0x800070b9, - 0x00000032, 0x00000030, 0x800070b9, 0x00000032, - 0x00000031, 0x800070b9, 0x00000032, 0x00000032, - 0x800070b9, 0x00000032, 0x00000033, 0x800070b9, - 0x00000032, 0x00000034, 0x800070b9, 0x00000068, - 0x00000050, 0x80000061, 0x00000064, 0x80000061, - 0x00000041, 0x80000055, 0x00000062, 0x00000061, - 0x80000072, 0x0000006f, 0x80000056, 0x00000070, - 0x80000063, 0x00000064, 0x8000006d, 0x00000064, - 0x0000006d, 0x800000b2, 0x00000064, 0x0000006d, - 0x800000b3, 0x00000049, 0x80000055, 0x00005e73, - 0x80006210, 0x0000662d, 0x8000548c, 0x00005927, - 0x80006b63, 0x0000660e, 0x80006cbb, 0x0000682a, - 0x00005f0f, 0x00004f1a, 0x8000793e, 0x00000070, - 0x80000041, 0x0000006e, 0x80000041, 0x000003bc, - 0x80000041, 0x0000006d, 0x80000041, 0x0000006b, - 0x80000041, 0x0000004b, 0x80000042, 0x0000004d, - 0x80000042, 0x00000047, 0x80000042, 0x00000063, - 0x00000061, 0x8000006c, 0x0000006b, 0x00000063, - 0x00000061, 0x8000006c, 0x00000070, 0x80000046, - 0x0000006e, 0x80000046, 0x000003bc, 0x80000046, - 0x000003bc, 0x80000067, 0x0000006d, 0x80000067, - 0x0000006b, 0x80000067, 0x00000048, 0x8000007a, - 0x0000006b, 0x00000048, 0x8000007a, 0x0000004d, - 0x00000048, 0x8000007a, 0x00000047, 0x00000048, - 0x8000007a, 0x00000054, 0x00000048, 0x8000007a, - 0x000003bc, 0x80002113, 0x0000006d, 0x80002113, - 0x00000064, 0x80002113, 0x0000006b, 0x80002113, - 0x00000066, 0x8000006d, 0x0000006e, 0x8000006d, - 0x000003bc, 0x8000006d, 0x0000006d, 0x8000006d, - 0x00000063, 0x8000006d, 0x0000006b, 0x8000006d, - 0x0000006d, 0x0000006d, 0x800000b2, 0x00000063, - 0x0000006d, 0x800000b2, 0x0000006d, 0x800000b2, - 0x0000006b, 0x0000006d, 0x800000b2, 0x0000006d, - 0x0000006d, 0x800000b3, 0x00000063, 0x0000006d, - 0x800000b3, 0x0000006d, 0x800000b3, 0x0000006b, - 0x0000006d, 0x800000b3, 0x0000006d, 0x00002215, - 0x80000073, 0x0000006d, 0x00002215, 0x00000073, - 0x800000b2, 0x00000050, 0x80000061, 0x0000006b, - 0x00000050, 0x80000061, 0x0000004d, 0x00000050, - 0x80000061, 0x00000047, 0x00000050, 0x80000061, - 0x00000072, 0x00000061, 0x80000064, 0x00000072, - 0x00000061, 0x00000064, 0x00002215, 0x80000073, - 0x00000072, 0x00000061, 0x00000064, 0x00002215, - 0x00000073, 0x800000b2, 0x00000070, 0x80000073, - 0x0000006e, 0x80000073, 0x000003bc, 0x80000073, - 0x0000006d, 0x80000073, 0x00000070, 0x80000056, - 0x0000006e, 0x80000056, 0x000003bc, 0x80000056, - 0x0000006d, 0x80000056, 0x0000006b, 0x80000056, - 0x0000004d, 0x80000056, 0x00000070, 0x80000057, - 0x0000006e, 0x80000057, 0x000003bc, 0x80000057, - 0x0000006d, 0x80000057, 0x0000006b, 0x80000057, - 0x0000004d, 0x80000057, 0x0000006b, 0x800003a9, - 0x0000004d, 0x800003a9, 0x00000061, 0x0000002e, - 0x0000006d, 0x8000002e, 0x00000042, 0x80000071, - 0x00000063, 0x80000063, 0x00000063, 0x80000064, - 0x00000043, 0x00002215, 0x0000006b, 0x80000067, - 0x00000043, 0x0000006f, 0x8000002e, 0x00000064, - 0x80000042, 0x00000047, 0x80000079, 0x00000068, - 0x80000061, 0x00000048, 0x80000050, 0x00000069, - 0x8000006e, 0x0000004b, 0x8000004b, 0x0000004b, - 0x8000004d, 0x0000006b, 0x80000074, 0x0000006c, - 0x8000006d, 0x0000006c, 0x8000006e, 0x0000006c, - 0x0000006f, 0x80000067, 0x0000006c, 0x80000078, - 0x0000006d, 0x80000062, 0x0000006d, 0x00000069, - 0x8000006c, 0x0000006d, 0x0000006f, 0x8000006c, - 0x00000050, 0x80000048, 0x00000070, 0x0000002e, - 0x0000006d, 0x8000002e, 0x00000050, 0x00000050, - 0x8000004d, 0x00000050, 0x80000052, 0x00000073, - 0x80000072, 0x00000053, 0x80000076, 0x00000057, - 0x80000062, 0x00000056, 0x00002215, 0x8000006d, - 0x00000041, 0x00002215, 0x8000006d, 0x00000031, - 0x800065e5, 0x00000032, 0x800065e5, 0x00000033, - 0x800065e5, 0x00000034, 0x800065e5, 0x00000035, - 0x800065e5, 0x00000036, 0x800065e5, 0x00000037, - 0x800065e5, 0x00000038, 0x800065e5, 0x00000039, - 0x800065e5, 0x00000031, 0x00000030, 0x800065e5, - 0x00000031, 0x00000031, 0x800065e5, 0x00000031, - 0x00000032, 0x800065e5, 0x00000031, 0x00000033, - 0x800065e5, 0x00000031, 0x00000034, 0x800065e5, - 0x00000031, 0x00000035, 0x800065e5, 0x00000031, - 0x00000036, 0x800065e5, 0x00000031, 0x00000037, - 0x800065e5, 0x00000031, 0x00000038, 0x800065e5, - 0x00000031, 0x00000039, 0x800065e5, 0x00000032, - 0x00000030, 0x800065e5, 0x00000032, 0x00000031, - 0x800065e5, 0x00000032, 0x00000032, 0x800065e5, - 0x00000032, 0x00000033, 0x800065e5, 0x00000032, - 0x00000034, 0x800065e5, 0x00000032, 0x00000035, - 0x800065e5, 0x00000032, 0x00000036, 0x800065e5, - 0x00000032, 0x00000037, 0x800065e5, 0x00000032, - 0x00000038, 0x800065e5, 0x00000032, 0x00000039, - 0x800065e5, 0x00000033, 0x00000030, 0x800065e5, - 0x00000033, 0x00000031, 0x800065e5, 0x00000067, - 0x00000061, 0x8000006c, 0x80008c48, 0x800066f4, - 0x80008eca, 0x80008cc8, 0x80006ed1, 0x80004e32, - 0x800053e5, 0x80009f9c, 0x80009f9c, 0x80005951, - 0x800091d1, 0x80005587, 0x80005948, 0x800061f6, - 0x80007669, 0x80007f85, 0x8000863f, 0x800087ba, - 0x800088f8, 0x8000908f, 0x80006a02, 0x80006d1b, - 0x800070d9, 0x800073de, 0x8000843d, 0x8000916a, - 0x800099f1, 0x80004e82, 0x80005375, 0x80006b04, - 0x8000721b, 0x8000862d, 0x80009e1e, 0x80005d50, - 0x80006feb, 0x800085cd, 0x80008964, 0x800062c9, - 0x800081d8, 0x8000881f, 0x80005eca, 0x80006717, - 0x80006d6a, 0x800072fc, 0x800090ce, 0x80004f86, - 0x800051b7, 0x800052de, 0x800064c4, 0x80006ad3, - 0x80007210, 0x800076e7, 0x80008001, 0x80008606, - 0x8000865c, 0x80008def, 0x80009732, 0x80009b6f, - 0x80009dfa, 0x8000788c, 0x8000797f, 0x80007da0, - 0x800083c9, 0x80009304, 0x80009e7f, 0x80008ad6, - 0x800058df, 0x80005f04, 0x80007c60, 0x8000807e, - 0x80007262, 0x800078ca, 0x80008cc2, 0x800096f7, - 0x800058d8, 0x80005c62, 0x80006a13, 0x80006dda, - 0x80006f0f, 0x80007d2f, 0x80007e37, 0x8000964b, - 0x800052d2, 0x8000808b, 0x800051dc, 0x800051cc, - 0x80007a1c, 0x80007dbe, 0x800083f1, 0x80009675, - 0x80008b80, 0x800062cf, 0x80006a02, 0x80008afe, - 0x80004e39, 0x80005be7, 0x80006012, 0x80007387, - 0x80007570, 0x80005317, 0x800078fb, 0x80004fbf, - 0x80005fa9, 0x80004e0d, 0x80006ccc, 0x80006578, - 0x80007d22, 0x800053c3, 0x8000585e, 0x80007701, - 0x80008449, 0x80008aaa, 0x80006bba, 0x80008fb0, - 0x80006c88, 0x800062fe, 0x800082e5, 0x800063a0, - 0x80007565, 0x80004eae, 0x80005169, 0x800051c9, - 0x80006881, 0x80007ce7, 0x8000826f, 0x80008ad2, - 0x800091cf, 0x800052f5, 0x80005442, 0x80005973, - 0x80005eec, 0x800065c5, 0x80006ffe, 0x8000792a, - 0x800095ad, 0x80009a6a, 0x80009e97, 0x80009ece, - 0x8000529b, 0x800066c6, 0x80006b77, 0x80008f62, - 0x80005e74, 0x80006190, 0x80006200, 0x8000649a, - 0x80006f23, 0x80007149, 0x80007489, 0x800079ca, - 0x80007df4, 0x8000806f, 0x80008f26, 0x800084ee, - 0x80009023, 0x8000934a, 0x80005217, 0x800052a3, - 0x800054bd, 0x800070c8, 0x800088c2, 0x80008aaa, - 0x80005ec9, 0x80005ff5, 0x8000637b, 0x80006bae, - 0x80007c3e, 0x80007375, 0x80004ee4, 0x800056f9, - 0x80005be7, 0x80005dba, 0x8000601c, 0x800073b2, - 0x80007469, 0x80007f9a, 0x80008046, 0x80009234, - 0x800096f6, 0x80009748, 0x80009818, 0x80004f8b, - 0x800079ae, 0x800091b4, 0x800096b8, 0x800060e1, - 0x80004e86, 0x800050da, 0x80005bee, 0x80005c3f, - 0x80006599, 0x80006a02, 0x800071ce, 0x80007642, - 0x800084fc, 0x8000907c, 0x80009f8d, 0x80006688, - 0x8000962e, 0x80005289, 0x8000677b, 0x800067f3, - 0x80006d41, 0x80006e9c, 0x80007409, 0x80007559, - 0x8000786b, 0x80007d10, 0x8000985e, 0x8000516d, - 0x8000622e, 0x80009678, 0x8000502b, 0x80005d19, - 0x80006dea, 0x80008f2a, 0x80005f8b, 0x80006144, - 0x80006817, 0x80007387, 0x80009686, 0x80005229, - 0x8000540f, 0x80005c65, 0x80006613, 0x8000674e, - 0x800068a8, 0x80006ce5, 0x80007406, 0x800075e2, - 0x80007f79, 0x800088cf, 0x800088e1, 0x800091cc, - 0x800096e2, 0x8000533f, 0x80006eba, 0x8000541d, - 0x800071d0, 0x80007498, 0x800085fa, 0x800096a3, - 0x80009c57, 0x80009e9f, 0x80006797, 0x80006dcb, - 0x800081e8, 0x80007acb, 0x80007b20, 0x80007c92, - 0x800072c0, 0x80007099, 0x80008b58, 0x80004ec0, - 0x80008336, 0x8000523a, 0x80005207, 0x80005ea6, - 0x800062d3, 0x80007cd6, 0x80005b85, 0x80006d1e, - 0x800066b4, 0x80008f3b, 0x8000884c, 0x8000964d, - 0x8000898b, 0x80005ed3, 0x80005140, 0x800055c0, - 0x8000585a, 0x80006674, 0x800051de, 0x8000732a, - 0x800076ca, 0x8000793c, 0x8000795e, 0x80007965, - 0x8000798f, 0x80009756, 0x80007cbe, 0x80007fbd, - 0x80008612, 0x80008af8, 0x80009038, 0x800090fd, - 0x800098ef, 0x800098fc, 0x80009928, 0x80009db4, - 0x80004fae, 0x800050e7, 0x8000514d, 0x800052c9, - 0x800052e4, 0x80005351, 0x8000559d, 0x80005606, - 0x80005668, 0x80005840, 0x800058a8, 0x80005c64, - 0x80005c6e, 0x80006094, 0x80006168, 0x8000618e, - 0x800061f2, 0x8000654f, 0x800065e2, 0x80006691, - 0x80006885, 0x80006d77, 0x80006e1a, 0x80006f22, - 0x8000716e, 0x8000722b, 0x80007422, 0x80007891, - 0x8000793e, 0x80007949, 0x80007948, 0x80007950, - 0x80007956, 0x8000795d, 0x8000798d, 0x8000798e, - 0x80007a40, 0x80007a81, 0x80007bc0, 0x80007df4, - 0x80007e09, 0x80007e41, 0x80007f72, 0x80008005, - 0x800081ed, 0x80008279, 0x80008279, 0x80008457, - 0x80008910, 0x80008996, 0x80008b01, 0x80008b39, - 0x80008cd3, 0x80008d08, 0x80008fb6, 0x80009038, - 0x800096e3, 0x800097ff, 0x8000983b, 0x80004e26, - 0x800051b5, 0x80005168, 0x80004f80, 0x80005145, - 0x80005180, 0x800052c7, 0x800052fa, 0x8000559d, - 0x80005555, 0x80005599, 0x800055e2, 0x8000585a, - 0x800058b3, 0x80005944, 0x80005954, 0x80005a62, - 0x80005b28, 0x80005ed2, 0x80005ed9, 0x80005f69, - 0x80005fad, 0x800060d8, 0x8000614e, 0x80006108, - 0x8000618e, 0x80006160, 0x800061f2, 0x80006234, - 0x800063c4, 0x8000641c, 0x80006452, 0x80006556, - 0x80006674, 0x80006717, 0x8000671b, 0x80006756, - 0x80006b79, 0x80006bba, 0x80006d41, 0x80006edb, - 0x80006ecb, 0x80006f22, 0x8000701e, 0x8000716e, - 0x800077a7, 0x80007235, 0x800072af, 0x8000732a, - 0x80007471, 0x80007506, 0x8000753b, 0x8000761d, - 0x8000761f, 0x800076ca, 0x800076db, 0x800076f4, - 0x8000774a, 0x80007740, 0x800078cc, 0x80007ab1, - 0x80007bc0, 0x80007c7b, 0x80007d5b, 0x80007df4, - 0x80007f3e, 0x80008005, 0x80008352, 0x800083ef, - 0x80008779, 0x80008941, 0x80008986, 0x80008996, - 0x80008abf, 0x80008af8, 0x80008acb, 0x80008b01, - 0x80008afe, 0x80008aed, 0x80008b39, 0x80008b8a, - 0x80008d08, 0x80008f38, 0x80009072, 0x80009199, - 0x80009276, 0x8000967c, 0x800096e3, 0x80009756, - 0x800097db, 0x800097ff, 0x8000980b, 0x8000983b, - 0x80009b12, 0x80009f9c, 0x8002284a, 0x80022844, - 0x800233d5, 0x80003b9d, 0x80004018, 0x80004039, - 0x80025249, 0x80025cd0, 0x80027ed3, 0x80009f43, - 0x80009f8e, 0x00000066, 0x80000066, 0x00000066, - 0x80000069, 0x00000066, 0x8000006c, 0x00000066, - 0x00000066, 0x80000069, 0x00000066, 0x00000066, - 0x8000006c, 0x0000017f, 0x80000074, 0x00000073, - 0x80000074, 0x00000574, 0x80000576, 0x00000574, - 0x80000565, 0x00000574, 0x8000056b, 0x0000057e, - 0x80000576, 0x00000574, 0x8000056d, 0x000005d9, - 0x800005b4, 0x000005f2, 0x800005b7, 0x800005e2, - 0x800005d0, 0x800005d3, 0x800005d4, 0x800005db, - 0x800005dc, 0x800005dd, 0x800005e8, 0x800005ea, - 0x8000002b, 0x000005e9, 0x800005c1, 0x000005e9, - 0x800005c2, 0x0000fb49, 0x800005c1, 0x0000fb49, - 0x800005c2, 0x000005d0, 0x800005b7, 0x000005d0, - 0x800005b8, 0x000005d0, 0x800005bc, 0x000005d1, - 0x800005bc, 0x000005d2, 0x800005bc, 0x000005d3, - 0x800005bc, 0x000005d4, 0x800005bc, 0x000005d5, - 0x800005bc, 0x000005d6, 0x800005bc, 0x000005d8, - 0x800005bc, 0x000005d9, 0x800005bc, 0x000005da, - 0x800005bc, 0x000005db, 0x800005bc, 0x000005dc, - 0x800005bc, 0x000005de, 0x800005bc, 0x000005e0, - 0x800005bc, 0x000005e1, 0x800005bc, 0x000005e3, - 0x800005bc, 0x000005e4, 0x800005bc, 0x000005e6, - 0x800005bc, 0x000005e7, 0x800005bc, 0x000005e8, - 0x800005bc, 0x000005e9, 0x800005bc, 0x000005ea, - 0x800005bc, 0x000005d5, 0x800005b9, 0x000005d1, - 0x800005bf, 0x000005db, 0x800005bf, 0x000005e4, - 0x800005bf, 0x000005d0, 0x800005dc, 0x80000671, - 0x80000671, 0x8000067b, 0x8000067b, 0x8000067b, - 0x8000067b, 0x8000067e, 0x8000067e, 0x8000067e, - 0x8000067e, 0x80000680, 0x80000680, 0x80000680, - 0x80000680, 0x8000067a, 0x8000067a, 0x8000067a, - 0x8000067a, 0x8000067f, 0x8000067f, 0x8000067f, - 0x8000067f, 0x80000679, 0x80000679, 0x80000679, - 0x80000679, 0x800006a4, 0x800006a4, 0x800006a4, - 0x800006a4, 0x800006a6, 0x800006a6, 0x800006a6, - 0x800006a6, 0x80000684, 0x80000684, 0x80000684, - 0x80000684, 0x80000683, 0x80000683, 0x80000683, - 0x80000683, 0x80000686, 0x80000686, 0x80000686, - 0x80000686, 0x80000687, 0x80000687, 0x80000687, - 0x80000687, 0x8000068d, 0x8000068d, 0x8000068c, - 0x8000068c, 0x8000068e, 0x8000068e, 0x80000688, - 0x80000688, 0x80000698, 0x80000698, 0x80000691, - 0x80000691, 0x800006a9, 0x800006a9, 0x800006a9, - 0x800006a9, 0x800006af, 0x800006af, 0x800006af, - 0x800006af, 0x800006b3, 0x800006b3, 0x800006b3, - 0x800006b3, 0x800006b1, 0x800006b1, 0x800006b1, - 0x800006b1, 0x800006ba, 0x800006ba, 0x800006bb, - 0x800006bb, 0x800006bb, 0x800006bb, 0x800006c0, - 0x800006c0, 0x800006c1, 0x800006c1, 0x800006c1, - 0x800006c1, 0x800006be, 0x800006be, 0x800006be, - 0x800006be, 0x800006d2, 0x800006d2, 0x800006d3, - 0x800006d3, 0x800006ad, 0x800006ad, 0x800006ad, - 0x800006ad, 0x800006c7, 0x800006c7, 0x800006c6, - 0x800006c6, 0x800006c8, 0x800006c8, 0x80000677, - 0x800006cb, 0x800006cb, 0x800006c5, 0x800006c5, - 0x800006c9, 0x800006c9, 0x800006d0, 0x800006d0, - 0x800006d0, 0x800006d0, 0x80000649, 0x80000649, - 0x00000626, 0x80000627, 0x00000626, 0x80000627, - 0x00000626, 0x800006d5, 0x00000626, 0x800006d5, - 0x00000626, 0x80000648, 0x00000626, 0x80000648, - 0x00000626, 0x800006c7, 0x00000626, 0x800006c7, - 0x00000626, 0x800006c6, 0x00000626, 0x800006c6, - 0x00000626, 0x800006c8, 0x00000626, 0x800006c8, - 0x00000626, 0x800006d0, 0x00000626, 0x800006d0, - 0x00000626, 0x800006d0, 0x00000626, 0x80000649, - 0x00000626, 0x80000649, 0x00000626, 0x80000649, - 0x800006cc, 0x800006cc, 0x800006cc, 0x800006cc, - 0x00000626, 0x8000062c, 0x00000626, 0x8000062d, - 0x00000626, 0x80000645, 0x00000626, 0x80000649, - 0x00000626, 0x8000064a, 0x00000628, 0x8000062c, - 0x00000628, 0x8000062d, 0x00000628, 0x8000062e, - 0x00000628, 0x80000645, 0x00000628, 0x80000649, - 0x00000628, 0x8000064a, 0x0000062a, 0x8000062c, - 0x0000062a, 0x8000062d, 0x0000062a, 0x8000062e, - 0x0000062a, 0x80000645, 0x0000062a, 0x80000649, - 0x0000062a, 0x8000064a, 0x0000062b, 0x8000062c, - 0x0000062b, 0x80000645, 0x0000062b, 0x80000649, - 0x0000062b, 0x8000064a, 0x0000062c, 0x8000062d, - 0x0000062c, 0x80000645, 0x0000062d, 0x8000062c, - 0x0000062d, 0x80000645, 0x0000062e, 0x8000062c, - 0x0000062e, 0x8000062d, 0x0000062e, 0x80000645, - 0x00000633, 0x8000062c, 0x00000633, 0x8000062d, - 0x00000633, 0x8000062e, 0x00000633, 0x80000645, - 0x00000635, 0x8000062d, 0x00000635, 0x80000645, - 0x00000636, 0x8000062c, 0x00000636, 0x8000062d, - 0x00000636, 0x8000062e, 0x00000636, 0x80000645, - 0x00000637, 0x8000062d, 0x00000637, 0x80000645, - 0x00000638, 0x80000645, 0x00000639, 0x8000062c, - 0x00000639, 0x80000645, 0x0000063a, 0x8000062c, - 0x0000063a, 0x80000645, 0x00000641, 0x8000062c, - 0x00000641, 0x8000062d, 0x00000641, 0x8000062e, - 0x00000641, 0x80000645, 0x00000641, 0x80000649, - 0x00000641, 0x8000064a, 0x00000642, 0x8000062d, - 0x00000642, 0x80000645, 0x00000642, 0x80000649, - 0x00000642, 0x8000064a, 0x00000643, 0x80000627, - 0x00000643, 0x8000062c, 0x00000643, 0x8000062d, - 0x00000643, 0x8000062e, 0x00000643, 0x80000644, - 0x00000643, 0x80000645, 0x00000643, 0x80000649, - 0x00000643, 0x8000064a, 0x00000644, 0x8000062c, - 0x00000644, 0x8000062d, 0x00000644, 0x8000062e, - 0x00000644, 0x80000645, 0x00000644, 0x80000649, - 0x00000644, 0x8000064a, 0x00000645, 0x8000062c, - 0x00000645, 0x8000062d, 0x00000645, 0x8000062e, - 0x00000645, 0x80000645, 0x00000645, 0x80000649, - 0x00000645, 0x8000064a, 0x00000646, 0x8000062c, - 0x00000646, 0x8000062d, 0x00000646, 0x8000062e, - 0x00000646, 0x80000645, 0x00000646, 0x80000649, - 0x00000646, 0x8000064a, 0x00000647, 0x8000062c, - 0x00000647, 0x80000645, 0x00000647, 0x80000649, - 0x00000647, 0x8000064a, 0x0000064a, 0x8000062c, - 0x0000064a, 0x8000062d, 0x0000064a, 0x8000062e, - 0x0000064a, 0x80000645, 0x0000064a, 0x80000649, - 0x0000064a, 0x8000064a, 0x00000630, 0x80000670, - 0x00000631, 0x80000670, 0x00000649, 0x80000670, - 0x00000020, 0x0000064c, 0x80000651, 0x00000020, - 0x0000064d, 0x80000651, 0x00000020, 0x0000064e, - 0x80000651, 0x00000020, 0x0000064f, 0x80000651, - 0x00000020, 0x00000650, 0x80000651, 0x00000020, - 0x00000651, 0x80000670, 0x00000626, 0x80000631, - 0x00000626, 0x80000632, 0x00000626, 0x80000645, - 0x00000626, 0x80000646, 0x00000626, 0x80000649, - 0x00000626, 0x8000064a, 0x00000628, 0x80000631, - 0x00000628, 0x80000632, 0x00000628, 0x80000645, - 0x00000628, 0x80000646, 0x00000628, 0x80000649, - 0x00000628, 0x8000064a, 0x0000062a, 0x80000631, - 0x0000062a, 0x80000632, 0x0000062a, 0x80000645, - 0x0000062a, 0x80000646, 0x0000062a, 0x80000649, - 0x0000062a, 0x8000064a, 0x0000062b, 0x80000631, - 0x0000062b, 0x80000632, 0x0000062b, 0x80000645, - 0x0000062b, 0x80000646, 0x0000062b, 0x80000649, - 0x0000062b, 0x8000064a, 0x00000641, 0x80000649, - 0x00000641, 0x8000064a, 0x00000642, 0x80000649, - 0x00000642, 0x8000064a, 0x00000643, 0x80000627, - 0x00000643, 0x80000644, 0x00000643, 0x80000645, - 0x00000643, 0x80000649, 0x00000643, 0x8000064a, - 0x00000644, 0x80000645, 0x00000644, 0x80000649, - 0x00000644, 0x8000064a, 0x00000645, 0x80000627, - 0x00000645, 0x80000645, 0x00000646, 0x80000631, - 0x00000646, 0x80000632, 0x00000646, 0x80000645, - 0x00000646, 0x80000646, 0x00000646, 0x80000649, - 0x00000646, 0x8000064a, 0x00000649, 0x80000670, - 0x0000064a, 0x80000631, 0x0000064a, 0x80000632, - 0x0000064a, 0x80000645, 0x0000064a, 0x80000646, - 0x0000064a, 0x80000649, 0x0000064a, 0x8000064a, - 0x00000626, 0x8000062c, 0x00000626, 0x8000062d, - 0x00000626, 0x8000062e, 0x00000626, 0x80000645, - 0x00000626, 0x80000647, 0x00000628, 0x8000062c, - 0x00000628, 0x8000062d, 0x00000628, 0x8000062e, - 0x00000628, 0x80000645, 0x00000628, 0x80000647, - 0x0000062a, 0x8000062c, 0x0000062a, 0x8000062d, - 0x0000062a, 0x8000062e, 0x0000062a, 0x80000645, - 0x0000062a, 0x80000647, 0x0000062b, 0x80000645, - 0x0000062c, 0x8000062d, 0x0000062c, 0x80000645, - 0x0000062d, 0x8000062c, 0x0000062d, 0x80000645, - 0x0000062e, 0x8000062c, 0x0000062e, 0x80000645, - 0x00000633, 0x8000062c, 0x00000633, 0x8000062d, - 0x00000633, 0x8000062e, 0x00000633, 0x80000645, - 0x00000635, 0x8000062d, 0x00000635, 0x8000062e, - 0x00000635, 0x80000645, 0x00000636, 0x8000062c, - 0x00000636, 0x8000062d, 0x00000636, 0x8000062e, - 0x00000636, 0x80000645, 0x00000637, 0x8000062d, - 0x00000638, 0x80000645, 0x00000639, 0x8000062c, - 0x00000639, 0x80000645, 0x0000063a, 0x8000062c, - 0x0000063a, 0x80000645, 0x00000641, 0x8000062c, - 0x00000641, 0x8000062d, 0x00000641, 0x8000062e, - 0x00000641, 0x80000645, 0x00000642, 0x8000062d, - 0x00000642, 0x80000645, 0x00000643, 0x8000062c, - 0x00000643, 0x8000062d, 0x00000643, 0x8000062e, - 0x00000643, 0x80000644, 0x00000643, 0x80000645, - 0x00000644, 0x8000062c, 0x00000644, 0x8000062d, - 0x00000644, 0x8000062e, 0x00000644, 0x80000645, - 0x00000644, 0x80000647, 0x00000645, 0x8000062c, - 0x00000645, 0x8000062d, 0x00000645, 0x8000062e, - 0x00000645, 0x80000645, 0x00000646, 0x8000062c, - 0x00000646, 0x8000062d, 0x00000646, 0x8000062e, - 0x00000646, 0x80000645, 0x00000646, 0x80000647, - 0x00000647, 0x8000062c, 0x00000647, 0x80000645, - 0x00000647, 0x80000670, 0x0000064a, 0x8000062c, - 0x0000064a, 0x8000062d, 0x0000064a, 0x8000062e, - 0x0000064a, 0x80000645, 0x0000064a, 0x80000647, - 0x00000626, 0x80000645, 0x00000626, 0x80000647, - 0x00000628, 0x80000645, 0x00000628, 0x80000647, - 0x0000062a, 0x80000645, 0x0000062a, 0x80000647, - 0x0000062b, 0x80000645, 0x0000062b, 0x80000647, - 0x00000633, 0x80000645, 0x00000633, 0x80000647, - 0x00000634, 0x80000645, 0x00000634, 0x80000647, - 0x00000643, 0x80000644, 0x00000643, 0x80000645, - 0x00000644, 0x80000645, 0x00000646, 0x80000645, - 0x00000646, 0x80000647, 0x0000064a, 0x80000645, - 0x0000064a, 0x80000647, 0x00000640, 0x0000064e, - 0x80000651, 0x00000640, 0x0000064f, 0x80000651, - 0x00000640, 0x00000650, 0x80000651, 0x00000637, - 0x80000649, 0x00000637, 0x8000064a, 0x00000639, - 0x80000649, 0x00000639, 0x8000064a, 0x0000063a, - 0x80000649, 0x0000063a, 0x8000064a, 0x00000633, - 0x80000649, 0x00000633, 0x8000064a, 0x00000634, - 0x80000649, 0x00000634, 0x8000064a, 0x0000062d, - 0x80000649, 0x0000062d, 0x8000064a, 0x0000062c, - 0x80000649, 0x0000062c, 0x8000064a, 0x0000062e, - 0x80000649, 0x0000062e, 0x8000064a, 0x00000635, - 0x80000649, 0x00000635, 0x8000064a, 0x00000636, - 0x80000649, 0x00000636, 0x8000064a, 0x00000634, - 0x8000062c, 0x00000634, 0x8000062d, 0x00000634, - 0x8000062e, 0x00000634, 0x80000645, 0x00000634, - 0x80000631, 0x00000633, 0x80000631, 0x00000635, - 0x80000631, 0x00000636, 0x80000631, 0x00000637, - 0x80000649, 0x00000637, 0x8000064a, 0x00000639, - 0x80000649, 0x00000639, 0x8000064a, 0x0000063a, - 0x80000649, 0x0000063a, 0x8000064a, 0x00000633, - 0x80000649, 0x00000633, 0x8000064a, 0x00000634, - 0x80000649, 0x00000634, 0x8000064a, 0x0000062d, - 0x80000649, 0x0000062d, 0x8000064a, 0x0000062c, - 0x80000649, 0x0000062c, 0x8000064a, 0x0000062e, - 0x80000649, 0x0000062e, 0x8000064a, 0x00000635, - 0x80000649, 0x00000635, 0x8000064a, 0x00000636, - 0x80000649, 0x00000636, 0x8000064a, 0x00000634, - 0x8000062c, 0x00000634, 0x8000062d, 0x00000634, - 0x8000062e, 0x00000634, 0x80000645, 0x00000634, - 0x80000631, 0x00000633, 0x80000631, 0x00000635, - 0x80000631, 0x00000636, 0x80000631, 0x00000634, - 0x8000062c, 0x00000634, 0x8000062d, 0x00000634, - 0x8000062e, 0x00000634, 0x80000645, 0x00000633, - 0x80000647, 0x00000634, 0x80000647, 0x00000637, - 0x80000645, 0x00000633, 0x8000062c, 0x00000633, - 0x8000062d, 0x00000633, 0x8000062e, 0x00000634, - 0x8000062c, 0x00000634, 0x8000062d, 0x00000634, - 0x8000062e, 0x00000637, 0x80000645, 0x00000638, - 0x80000645, 0x00000627, 0x8000064b, 0x00000627, - 0x8000064b, 0x0000062a, 0x0000062c, 0x80000645, - 0x0000062a, 0x0000062d, 0x8000062c, 0x0000062a, - 0x0000062d, 0x8000062c, 0x0000062a, 0x0000062d, - 0x80000645, 0x0000062a, 0x0000062e, 0x80000645, - 0x0000062a, 0x00000645, 0x8000062c, 0x0000062a, - 0x00000645, 0x8000062d, 0x0000062a, 0x00000645, - 0x8000062e, 0x0000062c, 0x00000645, 0x8000062d, - 0x0000062c, 0x00000645, 0x8000062d, 0x0000062d, - 0x00000645, 0x8000064a, 0x0000062d, 0x00000645, - 0x80000649, 0x00000633, 0x0000062d, 0x8000062c, - 0x00000633, 0x0000062c, 0x8000062d, 0x00000633, - 0x0000062c, 0x80000649, 0x00000633, 0x00000645, - 0x8000062d, 0x00000633, 0x00000645, 0x8000062d, - 0x00000633, 0x00000645, 0x8000062c, 0x00000633, - 0x00000645, 0x80000645, 0x00000633, 0x00000645, - 0x80000645, 0x00000635, 0x0000062d, 0x8000062d, - 0x00000635, 0x0000062d, 0x8000062d, 0x00000635, - 0x00000645, 0x80000645, 0x00000634, 0x0000062d, - 0x80000645, 0x00000634, 0x0000062d, 0x80000645, - 0x00000634, 0x0000062c, 0x8000064a, 0x00000634, - 0x00000645, 0x8000062e, 0x00000634, 0x00000645, - 0x8000062e, 0x00000634, 0x00000645, 0x80000645, - 0x00000634, 0x00000645, 0x80000645, 0x00000636, - 0x0000062d, 0x80000649, 0x00000636, 0x0000062e, - 0x80000645, 0x00000636, 0x0000062e, 0x80000645, - 0x00000637, 0x00000645, 0x8000062d, 0x00000637, - 0x00000645, 0x8000062d, 0x00000637, 0x00000645, - 0x80000645, 0x00000637, 0x00000645, 0x8000064a, - 0x00000639, 0x0000062c, 0x80000645, 0x00000639, - 0x00000645, 0x80000645, 0x00000639, 0x00000645, - 0x80000645, 0x00000639, 0x00000645, 0x80000649, - 0x0000063a, 0x00000645, 0x80000645, 0x0000063a, - 0x00000645, 0x8000064a, 0x0000063a, 0x00000645, - 0x80000649, 0x00000641, 0x0000062e, 0x80000645, - 0x00000641, 0x0000062e, 0x80000645, 0x00000642, - 0x00000645, 0x8000062d, 0x00000642, 0x00000645, - 0x80000645, 0x00000644, 0x0000062d, 0x80000645, - 0x00000644, 0x0000062d, 0x8000064a, 0x00000644, - 0x0000062d, 0x80000649, 0x00000644, 0x0000062c, - 0x8000062c, 0x00000644, 0x0000062c, 0x8000062c, - 0x00000644, 0x0000062e, 0x80000645, 0x00000644, - 0x0000062e, 0x80000645, 0x00000644, 0x00000645, - 0x8000062d, 0x00000644, 0x00000645, 0x8000062d, - 0x00000645, 0x0000062d, 0x8000062c, 0x00000645, - 0x0000062d, 0x80000645, 0x00000645, 0x0000062d, - 0x8000064a, 0x00000645, 0x0000062c, 0x8000062d, - 0x00000645, 0x0000062c, 0x80000645, 0x00000645, - 0x0000062e, 0x8000062c, 0x00000645, 0x0000062e, - 0x80000645, 0x00000645, 0x0000062c, 0x8000062e, - 0x00000647, 0x00000645, 0x8000062c, 0x00000647, - 0x00000645, 0x80000645, 0x00000646, 0x0000062d, - 0x80000645, 0x00000646, 0x0000062d, 0x80000649, - 0x00000646, 0x0000062c, 0x80000645, 0x00000646, - 0x0000062c, 0x80000645, 0x00000646, 0x0000062c, - 0x80000649, 0x00000646, 0x00000645, 0x8000064a, - 0x00000646, 0x00000645, 0x80000649, 0x0000064a, - 0x00000645, 0x80000645, 0x0000064a, 0x00000645, - 0x80000645, 0x00000628, 0x0000062e, 0x8000064a, - 0x0000062a, 0x0000062c, 0x8000064a, 0x0000062a, - 0x0000062c, 0x80000649, 0x0000062a, 0x0000062e, - 0x8000064a, 0x0000062a, 0x0000062e, 0x80000649, - 0x0000062a, 0x00000645, 0x8000064a, 0x0000062a, - 0x00000645, 0x80000649, 0x0000062c, 0x00000645, - 0x8000064a, 0x0000062c, 0x0000062d, 0x80000649, - 0x0000062c, 0x00000645, 0x80000649, 0x00000633, - 0x0000062e, 0x80000649, 0x00000635, 0x0000062d, - 0x8000064a, 0x00000634, 0x0000062d, 0x8000064a, - 0x00000636, 0x0000062d, 0x8000064a, 0x00000644, - 0x0000062c, 0x8000064a, 0x00000644, 0x00000645, - 0x8000064a, 0x0000064a, 0x0000062d, 0x8000064a, - 0x0000064a, 0x0000062c, 0x8000064a, 0x0000064a, - 0x00000645, 0x8000064a, 0x00000645, 0x00000645, - 0x8000064a, 0x00000642, 0x00000645, 0x8000064a, - 0x00000646, 0x0000062d, 0x8000064a, 0x00000642, - 0x00000645, 0x8000062d, 0x00000644, 0x0000062d, - 0x80000645, 0x00000639, 0x00000645, 0x8000064a, - 0x00000643, 0x00000645, 0x8000064a, 0x00000646, - 0x0000062c, 0x8000062d, 0x00000645, 0x0000062e, - 0x8000064a, 0x00000644, 0x0000062c, 0x80000645, - 0x00000643, 0x00000645, 0x80000645, 0x00000644, - 0x0000062c, 0x80000645, 0x00000646, 0x0000062c, - 0x8000062d, 0x0000062c, 0x0000062d, 0x8000064a, - 0x0000062d, 0x0000062c, 0x8000064a, 0x00000645, - 0x0000062c, 0x8000064a, 0x00000641, 0x00000645, - 0x8000064a, 0x00000628, 0x0000062d, 0x8000064a, - 0x00000643, 0x00000645, 0x80000645, 0x00000639, - 0x0000062c, 0x80000645, 0x00000635, 0x00000645, - 0x80000645, 0x00000633, 0x0000062e, 0x8000064a, - 0x00000646, 0x0000062c, 0x8000064a, 0x00000635, - 0x00000644, 0x800006d2, 0x00000642, 0x00000644, - 0x800006d2, 0x00000627, 0x00000644, 0x00000644, - 0x80000647, 0x00000627, 0x00000643, 0x00000628, - 0x80000631, 0x00000645, 0x0000062d, 0x00000645, - 0x8000062f, 0x00000635, 0x00000644, 0x00000639, - 0x80000645, 0x00000631, 0x00000633, 0x00000648, - 0x80000644, 0x00000639, 0x00000644, 0x0000064a, - 0x80000647, 0x00000648, 0x00000633, 0x00000644, - 0x80000645, 0x00000635, 0x00000644, 0x80000649, - 0x00000635, 0x00000644, 0x00000649, 0x00000020, - 0x00000627, 0x00000644, 0x00000644, 0x00000647, - 0x00000020, 0x00000639, 0x00000644, 0x0000064a, - 0x00000647, 0x00000020, 0x00000648, 0x00000633, - 0x00000644, 0x80000645, 0x0000062c, 0x00000644, - 0x00000020, 0x0000062c, 0x00000644, 0x00000627, - 0x00000644, 0x80000647, 0x00000631, 0x000006cc, - 0x00000627, 0x80000644, 0x8000002c, 0x80003001, - 0x80003002, 0x8000003a, 0x8000003b, 0x80000021, - 0x8000003f, 0x80003016, 0x80003017, 0x80002026, - 0x80002025, 0x80002014, 0x80002013, 0x8000005f, - 0x8000005f, 0x80000028, 0x80000029, 0x8000007b, - 0x8000007d, 0x80003014, 0x80003015, 0x80003010, - 0x80003011, 0x8000300a, 0x8000300b, 0x80003008, - 0x80003009, 0x8000300c, 0x8000300d, 0x8000300e, - 0x8000300f, 0x8000005b, 0x8000005d, 0x8000203e, - 0x8000203e, 0x8000203e, 0x8000203e, 0x8000005f, - 0x8000005f, 0x8000005f, 0x8000002c, 0x80003001, - 0x8000002e, 0x8000003b, 0x8000003a, 0x8000003f, - 0x80000021, 0x80002014, 0x80000028, 0x80000029, - 0x8000007b, 0x8000007d, 0x80003014, 0x80003015, - 0x80000023, 0x80000026, 0x8000002a, 0x8000002b, - 0x8000002d, 0x8000003c, 0x8000003e, 0x8000003d, - 0x8000005c, 0x80000024, 0x80000025, 0x80000040, - 0x00000020, 0x8000064b, 0x00000640, 0x8000064b, - 0x00000020, 0x8000064c, 0x00000020, 0x8000064d, - 0x00000020, 0x8000064e, 0x00000640, 0x8000064e, - 0x00000020, 0x8000064f, 0x00000640, 0x8000064f, - 0x00000020, 0x80000650, 0x00000640, 0x80000650, - 0x00000020, 0x80000651, 0x00000640, 0x80000651, - 0x00000020, 0x80000652, 0x00000640, 0x80000652, - 0x80000621, 0x80000622, 0x80000622, 0x80000623, - 0x80000623, 0x80000624, 0x80000624, 0x80000625, - 0x80000625, 0x80000626, 0x80000626, 0x80000626, - 0x80000626, 0x80000627, 0x80000627, 0x80000628, - 0x80000628, 0x80000628, 0x80000628, 0x80000629, - 0x80000629, 0x8000062a, 0x8000062a, 0x8000062a, - 0x8000062a, 0x8000062b, 0x8000062b, 0x8000062b, - 0x8000062b, 0x8000062c, 0x8000062c, 0x8000062c, - 0x8000062c, 0x8000062d, 0x8000062d, 0x8000062d, - 0x8000062d, 0x8000062e, 0x8000062e, 0x8000062e, - 0x8000062e, 0x8000062f, 0x8000062f, 0x80000630, - 0x80000630, 0x80000631, 0x80000631, 0x80000632, - 0x80000632, 0x80000633, 0x80000633, 0x80000633, - 0x80000633, 0x80000634, 0x80000634, 0x80000634, - 0x80000634, 0x80000635, 0x80000635, 0x80000635, - 0x80000635, 0x80000636, 0x80000636, 0x80000636, - 0x80000636, 0x80000637, 0x80000637, 0x80000637, - 0x80000637, 0x80000638, 0x80000638, 0x80000638, - 0x80000638, 0x80000639, 0x80000639, 0x80000639, - 0x80000639, 0x8000063a, 0x8000063a, 0x8000063a, - 0x8000063a, 0x80000641, 0x80000641, 0x80000641, - 0x80000641, 0x80000642, 0x80000642, 0x80000642, - 0x80000642, 0x80000643, 0x80000643, 0x80000643, - 0x80000643, 0x80000644, 0x80000644, 0x80000644, - 0x80000644, 0x80000645, 0x80000645, 0x80000645, - 0x80000645, 0x80000646, 0x80000646, 0x80000646, - 0x80000646, 0x80000647, 0x80000647, 0x80000647, - 0x80000647, 0x80000648, 0x80000648, 0x80000649, - 0x80000649, 0x8000064a, 0x8000064a, 0x8000064a, - 0x8000064a, 0x00000644, 0x80000622, 0x00000644, - 0x80000622, 0x00000644, 0x80000623, 0x00000644, - 0x80000623, 0x00000644, 0x80000625, 0x00000644, - 0x80000625, 0x00000644, 0x80000627, 0x00000644, - 0x80000627, 0x80000021, 0x80000022, 0x80000023, - 0x80000024, 0x80000025, 0x80000026, 0x80000027, - 0x80000028, 0x80000029, 0x8000002a, 0x8000002b, - 0x8000002c, 0x8000002d, 0x8000002e, 0x8000002f, - 0x80000030, 0x80000031, 0x80000032, 0x80000033, - 0x80000034, 0x80000035, 0x80000036, 0x80000037, - 0x80000038, 0x80000039, 0x8000003a, 0x8000003b, - 0x8000003c, 0x8000003d, 0x8000003e, 0x8000003f, - 0x80000040, 0x80000041, 0x80000042, 0x80000043, - 0x80000044, 0x80000045, 0x80000046, 0x80000047, - 0x80000048, 0x80000049, 0x8000004a, 0x8000004b, - 0x8000004c, 0x8000004d, 0x8000004e, 0x8000004f, - 0x80000050, 0x80000051, 0x80000052, 0x80000053, - 0x80000054, 0x80000055, 0x80000056, 0x80000057, - 0x80000058, 0x80000059, 0x8000005a, 0x8000005b, - 0x8000005c, 0x8000005d, 0x8000005e, 0x8000005f, - 0x80000060, 0x80000061, 0x80000062, 0x80000063, - 0x80000064, 0x80000065, 0x80000066, 0x80000067, - 0x80000068, 0x80000069, 0x8000006a, 0x8000006b, - 0x8000006c, 0x8000006d, 0x8000006e, 0x8000006f, - 0x80000070, 0x80000071, 0x80000072, 0x80000073, - 0x80000074, 0x80000075, 0x80000076, 0x80000077, - 0x80000078, 0x80000079, 0x8000007a, 0x8000007b, - 0x8000007c, 0x8000007d, 0x8000007e, 0x80002985, - 0x80002986, 0x80003002, 0x8000300c, 0x8000300d, - 0x80003001, 0x800030fb, 0x800030f2, 0x800030a1, - 0x800030a3, 0x800030a5, 0x800030a7, 0x800030a9, - 0x800030e3, 0x800030e5, 0x800030e7, 0x800030c3, - 0x800030fc, 0x800030a2, 0x800030a4, 0x800030a6, - 0x800030a8, 0x800030aa, 0x800030ab, 0x800030ad, - 0x800030af, 0x800030b1, 0x800030b3, 0x800030b5, - 0x800030b7, 0x800030b9, 0x800030bb, 0x800030bd, - 0x800030bf, 0x800030c1, 0x800030c4, 0x800030c6, - 0x800030c8, 0x800030ca, 0x800030cb, 0x800030cc, - 0x800030cd, 0x800030ce, 0x800030cf, 0x800030d2, - 0x800030d5, 0x800030d8, 0x800030db, 0x800030de, - 0x800030df, 0x800030e0, 0x800030e1, 0x800030e2, - 0x800030e4, 0x800030e6, 0x800030e8, 0x800030e9, - 0x800030ea, 0x800030eb, 0x800030ec, 0x800030ed, - 0x800030ef, 0x800030f3, 0x80003099, 0x8000309a, - 0x80003164, 0x80003131, 0x80003132, 0x80003133, - 0x80003134, 0x80003135, 0x80003136, 0x80003137, - 0x80003138, 0x80003139, 0x8000313a, 0x8000313b, - 0x8000313c, 0x8000313d, 0x8000313e, 0x8000313f, - 0x80003140, 0x80003141, 0x80003142, 0x80003143, - 0x80003144, 0x80003145, 0x80003146, 0x80003147, - 0x80003148, 0x80003149, 0x8000314a, 0x8000314b, - 0x8000314c, 0x8000314d, 0x8000314e, 0x8000314f, - 0x80003150, 0x80003151, 0x80003152, 0x80003153, - 0x80003154, 0x80003155, 0x80003156, 0x80003157, - 0x80003158, 0x80003159, 0x8000315a, 0x8000315b, - 0x8000315c, 0x8000315d, 0x8000315e, 0x8000315f, - 0x80003160, 0x80003161, 0x80003162, 0x80003163, - 0x800000a2, 0x800000a3, 0x800000ac, 0x800000af, - 0x800000a6, 0x800000a5, 0x800020a9, 0x80002502, - 0x80002190, 0x80002191, 0x80002192, 0x80002193, - 0x800025a0, 0x800025cb, 0x0001d157, 0x8001d165, - 0x0001d158, 0x8001d165, 0x0001d15f, 0x8001d16e, - 0x0001d15f, 0x8001d16f, 0x0001d15f, 0x8001d170, - 0x0001d15f, 0x8001d171, 0x0001d15f, 0x8001d172, - 0x0001d1b9, 0x8001d165, 0x0001d1ba, 0x8001d165, - 0x0001d1bb, 0x8001d16e, 0x0001d1bc, 0x8001d16e, - 0x0001d1bb, 0x8001d16f, 0x0001d1bc, 0x8001d16f, - 0x80000041, 0x80000042, 0x80000043, 0x80000044, - 0x80000045, 0x80000046, 0x80000047, 0x80000048, - 0x80000049, 0x8000004a, 0x8000004b, 0x8000004c, - 0x8000004d, 0x8000004e, 0x8000004f, 0x80000050, - 0x80000051, 0x80000052, 0x80000053, 0x80000054, - 0x80000055, 0x80000056, 0x80000057, 0x80000058, - 0x80000059, 0x8000005a, 0x80000061, 0x80000062, - 0x80000063, 0x80000064, 0x80000065, 0x80000066, - 0x80000067, 0x80000068, 0x80000069, 0x8000006a, - 0x8000006b, 0x8000006c, 0x8000006d, 0x8000006e, - 0x8000006f, 0x80000070, 0x80000071, 0x80000072, - 0x80000073, 0x80000074, 0x80000075, 0x80000076, - 0x80000077, 0x80000078, 0x80000079, 0x8000007a, - 0x80000041, 0x80000042, 0x80000043, 0x80000044, - 0x80000045, 0x80000046, 0x80000047, 0x80000048, - 0x80000049, 0x8000004a, 0x8000004b, 0x8000004c, - 0x8000004d, 0x8000004e, 0x8000004f, 0x80000050, - 0x80000051, 0x80000052, 0x80000053, 0x80000054, - 0x80000055, 0x80000056, 0x80000057, 0x80000058, - 0x80000059, 0x8000005a, 0x80000061, 0x80000062, - 0x80000063, 0x80000064, 0x80000065, 0x80000066, - 0x80000067, 0x80000069, 0x8000006a, 0x8000006b, - 0x8000006c, 0x8000006d, 0x8000006e, 0x8000006f, - 0x80000070, 0x80000071, 0x80000072, 0x80000073, - 0x80000074, 0x80000075, 0x80000076, 0x80000077, - 0x80000078, 0x80000079, 0x8000007a, 0x80000041, - 0x80000042, 0x80000043, 0x80000044, 0x80000045, - 0x80000046, 0x80000047, 0x80000048, 0x80000049, - 0x8000004a, 0x8000004b, 0x8000004c, 0x8000004d, - 0x8000004e, 0x8000004f, 0x80000050, 0x80000051, - 0x80000052, 0x80000053, 0x80000054, 0x80000055, - 0x80000056, 0x80000057, 0x80000058, 0x80000059, - 0x8000005a, 0x80000061, 0x80000062, 0x80000063, - 0x80000064, 0x80000065, 0x80000066, 0x80000067, - 0x80000068, 0x80000069, 0x8000006a, 0x8000006b, - 0x8000006c, 0x8000006d, 0x8000006e, 0x8000006f, - 0x80000070, 0x80000071, 0x80000072, 0x80000073, - 0x80000074, 0x80000075, 0x80000076, 0x80000077, - 0x80000078, 0x80000079, 0x8000007a, 0x80000041, - 0x80000043, 0x80000044, 0x80000047, 0x8000004a, - 0x8000004b, 0x8000004e, 0x8000004f, 0x80000050, - 0x80000051, 0x80000053, 0x80000054, 0x80000055, - 0x80000056, 0x80000057, 0x80000058, 0x80000059, - 0x8000005a, 0x80000061, 0x80000062, 0x80000063, - 0x80000064, 0x80000066, 0x80000068, 0x80000069, - 0x8000006a, 0x8000006b, 0x8000006c, 0x8000006d, - 0x8000006e, 0x80000070, 0x80000071, 0x80000072, - 0x80000073, 0x80000074, 0x80000075, 0x80000076, - 0x80000077, 0x80000078, 0x80000079, 0x8000007a, - 0x80000041, 0x80000042, 0x80000043, 0x80000044, - 0x80000045, 0x80000046, 0x80000047, 0x80000048, - 0x80000049, 0x8000004a, 0x8000004b, 0x8000004c, - 0x8000004d, 0x8000004e, 0x8000004f, 0x80000050, - 0x80000051, 0x80000052, 0x80000053, 0x80000054, - 0x80000055, 0x80000056, 0x80000057, 0x80000058, - 0x80000059, 0x8000005a, 0x80000061, 0x80000062, - 0x80000063, 0x80000064, 0x80000065, 0x80000066, - 0x80000067, 0x80000068, 0x80000069, 0x8000006a, - 0x8000006b, 0x8000006c, 0x8000006d, 0x8000006e, - 0x8000006f, 0x80000070, 0x80000071, 0x80000072, - 0x80000073, 0x80000074, 0x80000075, 0x80000076, - 0x80000077, 0x80000078, 0x80000079, 0x8000007a, - 0x80000041, 0x80000042, 0x80000044, 0x80000045, - 0x80000046, 0x80000047, 0x8000004a, 0x8000004b, - 0x8000004c, 0x8000004d, 0x8000004e, 0x8000004f, - 0x80000050, 0x80000051, 0x80000053, 0x80000054, - 0x80000055, 0x80000056, 0x80000057, 0x80000058, - 0x80000059, 0x80000061, 0x80000062, 0x80000063, - 0x80000064, 0x80000065, 0x80000066, 0x80000067, - 0x80000068, 0x80000069, 0x8000006a, 0x8000006b, - 0x8000006c, 0x8000006d, 0x8000006e, 0x8000006f, - 0x80000070, 0x80000071, 0x80000072, 0x80000073, - 0x80000074, 0x80000075, 0x80000076, 0x80000077, - 0x80000078, 0x80000079, 0x8000007a, 0x80000041, - 0x80000042, 0x80000044, 0x80000045, 0x80000046, - 0x80000047, 0x80000049, 0x8000004a, 0x8000004b, - 0x8000004c, 0x8000004d, 0x8000004f, 0x80000053, - 0x80000054, 0x80000055, 0x80000056, 0x80000057, - 0x80000058, 0x80000059, 0x80000061, 0x80000062, - 0x80000063, 0x80000064, 0x80000065, 0x80000066, - 0x80000067, 0x80000068, 0x80000069, 0x8000006a, - 0x8000006b, 0x8000006c, 0x8000006d, 0x8000006e, - 0x8000006f, 0x80000070, 0x80000071, 0x80000072, - 0x80000073, 0x80000074, 0x80000075, 0x80000076, - 0x80000077, 0x80000078, 0x80000079, 0x8000007a, - 0x80000041, 0x80000042, 0x80000043, 0x80000044, - 0x80000045, 0x80000046, 0x80000047, 0x80000048, - 0x80000049, 0x8000004a, 0x8000004b, 0x8000004c, - 0x8000004d, 0x8000004e, 0x8000004f, 0x80000050, - 0x80000051, 0x80000052, 0x80000053, 0x80000054, - 0x80000055, 0x80000056, 0x80000057, 0x80000058, - 0x80000059, 0x8000005a, 0x80000061, 0x80000062, - 0x80000063, 0x80000064, 0x80000065, 0x80000066, - 0x80000067, 0x80000068, 0x80000069, 0x8000006a, - 0x8000006b, 0x8000006c, 0x8000006d, 0x8000006e, - 0x8000006f, 0x80000070, 0x80000071, 0x80000072, - 0x80000073, 0x80000074, 0x80000075, 0x80000076, - 0x80000077, 0x80000078, 0x80000079, 0x8000007a, - 0x80000041, 0x80000042, 0x80000043, 0x80000044, - 0x80000045, 0x80000046, 0x80000047, 0x80000048, - 0x80000049, 0x8000004a, 0x8000004b, 0x8000004c, - 0x8000004d, 0x8000004e, 0x8000004f, 0x80000050, - 0x80000051, 0x80000052, 0x80000053, 0x80000054, - 0x80000055, 0x80000056, 0x80000057, 0x80000058, - 0x80000059, 0x8000005a, 0x80000061, 0x80000062, - 0x80000063, 0x80000064, 0x80000065, 0x80000066, - 0x80000067, 0x80000068, 0x80000069, 0x8000006a, - 0x8000006b, 0x8000006c, 0x8000006d, 0x8000006e, - 0x8000006f, 0x80000070, 0x80000071, 0x80000072, - 0x80000073, 0x80000074, 0x80000075, 0x80000076, - 0x80000077, 0x80000078, 0x80000079, 0x8000007a, - 0x80000041, 0x80000042, 0x80000043, 0x80000044, - 0x80000045, 0x80000046, 0x80000047, 0x80000048, - 0x80000049, 0x8000004a, 0x8000004b, 0x8000004c, - 0x8000004d, 0x8000004e, 0x8000004f, 0x80000050, - 0x80000051, 0x80000052, 0x80000053, 0x80000054, - 0x80000055, 0x80000056, 0x80000057, 0x80000058, - 0x80000059, 0x8000005a, 0x80000061, 0x80000062, - 0x80000063, 0x80000064, 0x80000065, 0x80000066, - 0x80000067, 0x80000068, 0x80000069, 0x8000006a, - 0x8000006b, 0x8000006c, 0x8000006d, 0x8000006e, - 0x8000006f, 0x80000070, 0x80000071, 0x80000072, - 0x80000073, 0x80000074, 0x80000075, 0x80000076, - 0x80000077, 0x80000078, 0x80000079, 0x8000007a, - 0x80000041, 0x80000042, 0x80000043, 0x80000044, - 0x80000045, 0x80000046, 0x80000047, 0x80000048, - 0x80000049, 0x8000004a, 0x8000004b, 0x8000004c, - 0x8000004d, 0x8000004e, 0x8000004f, 0x80000050, - 0x80000051, 0x80000052, 0x80000053, 0x80000054, - 0x80000055, 0x80000056, 0x80000057, 0x80000058, - 0x80000059, 0x8000005a, 0x80000061, 0x80000062, - 0x80000063, 0x80000064, 0x80000065, 0x80000066, - 0x80000067, 0x80000068, 0x80000069, 0x8000006a, - 0x8000006b, 0x8000006c, 0x8000006d, 0x8000006e, - 0x8000006f, 0x80000070, 0x80000071, 0x80000072, - 0x80000073, 0x80000074, 0x80000075, 0x80000076, - 0x80000077, 0x80000078, 0x80000079, 0x8000007a, - 0x80000041, 0x80000042, 0x80000043, 0x80000044, - 0x80000045, 0x80000046, 0x80000047, 0x80000048, - 0x80000049, 0x8000004a, 0x8000004b, 0x8000004c, - 0x8000004d, 0x8000004e, 0x8000004f, 0x80000050, - 0x80000051, 0x80000052, 0x80000053, 0x80000054, - 0x80000055, 0x80000056, 0x80000057, 0x80000058, - 0x80000059, 0x8000005a, 0x80000061, 0x80000062, - 0x80000063, 0x80000064, 0x80000065, 0x80000066, - 0x80000067, 0x80000068, 0x80000069, 0x8000006a, - 0x8000006b, 0x8000006c, 0x8000006d, 0x8000006e, - 0x8000006f, 0x80000070, 0x80000071, 0x80000072, - 0x80000073, 0x80000074, 0x80000075, 0x80000076, - 0x80000077, 0x80000078, 0x80000079, 0x8000007a, - 0x80000041, 0x80000042, 0x80000043, 0x80000044, - 0x80000045, 0x80000046, 0x80000047, 0x80000048, - 0x80000049, 0x8000004a, 0x8000004b, 0x8000004c, - 0x8000004d, 0x8000004e, 0x8000004f, 0x80000050, - 0x80000051, 0x80000052, 0x80000053, 0x80000054, - 0x80000055, 0x80000056, 0x80000057, 0x80000058, - 0x80000059, 0x8000005a, 0x80000061, 0x80000062, - 0x80000063, 0x80000064, 0x80000065, 0x80000066, - 0x80000067, 0x80000068, 0x80000069, 0x8000006a, - 0x8000006b, 0x8000006c, 0x8000006d, 0x8000006e, - 0x8000006f, 0x80000070, 0x80000071, 0x80000072, - 0x80000073, 0x80000074, 0x80000075, 0x80000076, - 0x80000077, 0x80000078, 0x80000079, 0x8000007a, - 0x80000131, 0x80000237, 0x80000391, 0x80000392, - 0x80000393, 0x80000394, 0x80000395, 0x80000396, - 0x80000397, 0x80000398, 0x80000399, 0x8000039a, - 0x8000039b, 0x8000039c, 0x8000039d, 0x8000039e, - 0x8000039f, 0x800003a0, 0x800003a1, 0x800003f4, - 0x800003a3, 0x800003a4, 0x800003a5, 0x800003a6, - 0x800003a7, 0x800003a8, 0x800003a9, 0x80002207, - 0x800003b1, 0x800003b2, 0x800003b3, 0x800003b4, - 0x800003b5, 0x800003b6, 0x800003b7, 0x800003b8, - 0x800003b9, 0x800003ba, 0x800003bb, 0x800003bc, - 0x800003bd, 0x800003be, 0x800003bf, 0x800003c0, - 0x800003c1, 0x800003c2, 0x800003c3, 0x800003c4, - 0x800003c5, 0x800003c6, 0x800003c7, 0x800003c8, - 0x800003c9, 0x80002202, 0x800003f5, 0x800003d1, - 0x800003f0, 0x800003d5, 0x800003f1, 0x800003d6, - 0x80000391, 0x80000392, 0x80000393, 0x80000394, - 0x80000395, 0x80000396, 0x80000397, 0x80000398, - 0x80000399, 0x8000039a, 0x8000039b, 0x8000039c, - 0x8000039d, 0x8000039e, 0x8000039f, 0x800003a0, - 0x800003a1, 0x800003f4, 0x800003a3, 0x800003a4, - 0x800003a5, 0x800003a6, 0x800003a7, 0x800003a8, - 0x800003a9, 0x80002207, 0x800003b1, 0x800003b2, - 0x800003b3, 0x800003b4, 0x800003b5, 0x800003b6, - 0x800003b7, 0x800003b8, 0x800003b9, 0x800003ba, - 0x800003bb, 0x800003bc, 0x800003bd, 0x800003be, - 0x800003bf, 0x800003c0, 0x800003c1, 0x800003c2, - 0x800003c3, 0x800003c4, 0x800003c5, 0x800003c6, - 0x800003c7, 0x800003c8, 0x800003c9, 0x80002202, - 0x800003f5, 0x800003d1, 0x800003f0, 0x800003d5, - 0x800003f1, 0x800003d6, 0x80000391, 0x80000392, - 0x80000393, 0x80000394, 0x80000395, 0x80000396, - 0x80000397, 0x80000398, 0x80000399, 0x8000039a, - 0x8000039b, 0x8000039c, 0x8000039d, 0x8000039e, - 0x8000039f, 0x800003a0, 0x800003a1, 0x800003f4, - 0x800003a3, 0x800003a4, 0x800003a5, 0x800003a6, - 0x800003a7, 0x800003a8, 0x800003a9, 0x80002207, - 0x800003b1, 0x800003b2, 0x800003b3, 0x800003b4, - 0x800003b5, 0x800003b6, 0x800003b7, 0x800003b8, - 0x800003b9, 0x800003ba, 0x800003bb, 0x800003bc, - 0x800003bd, 0x800003be, 0x800003bf, 0x800003c0, - 0x800003c1, 0x800003c2, 0x800003c3, 0x800003c4, - 0x800003c5, 0x800003c6, 0x800003c7, 0x800003c8, - 0x800003c9, 0x80002202, 0x800003f5, 0x800003d1, - 0x800003f0, 0x800003d5, 0x800003f1, 0x800003d6, - 0x80000391, 0x80000392, 0x80000393, 0x80000394, - 0x80000395, 0x80000396, 0x80000397, 0x80000398, - 0x80000399, 0x8000039a, 0x8000039b, 0x8000039c, - 0x8000039d, 0x8000039e, 0x8000039f, 0x800003a0, - 0x800003a1, 0x800003f4, 0x800003a3, 0x800003a4, - 0x800003a5, 0x800003a6, 0x800003a7, 0x800003a8, - 0x800003a9, 0x80002207, 0x800003b1, 0x800003b2, - 0x800003b3, 0x800003b4, 0x800003b5, 0x800003b6, - 0x800003b7, 0x800003b8, 0x800003b9, 0x800003ba, - 0x800003bb, 0x800003bc, 0x800003bd, 0x800003be, - 0x800003bf, 0x800003c0, 0x800003c1, 0x800003c2, - 0x800003c3, 0x800003c4, 0x800003c5, 0x800003c6, - 0x800003c7, 0x800003c8, 0x800003c9, 0x80002202, - 0x800003f5, 0x800003d1, 0x800003f0, 0x800003d5, - 0x800003f1, 0x800003d6, 0x80000391, 0x80000392, - 0x80000393, 0x80000394, 0x80000395, 0x80000396, - 0x80000397, 0x80000398, 0x80000399, 0x8000039a, - 0x8000039b, 0x8000039c, 0x8000039d, 0x8000039e, - 0x8000039f, 0x800003a0, 0x800003a1, 0x800003f4, - 0x800003a3, 0x800003a4, 0x800003a5, 0x800003a6, - 0x800003a7, 0x800003a8, 0x800003a9, 0x80002207, - 0x800003b1, 0x800003b2, 0x800003b3, 0x800003b4, - 0x800003b5, 0x800003b6, 0x800003b7, 0x800003b8, - 0x800003b9, 0x800003ba, 0x800003bb, 0x800003bc, - 0x800003bd, 0x800003be, 0x800003bf, 0x800003c0, - 0x800003c1, 0x800003c2, 0x800003c3, 0x800003c4, - 0x800003c5, 0x800003c6, 0x800003c7, 0x800003c8, - 0x800003c9, 0x80002202, 0x800003f5, 0x800003d1, - 0x800003f0, 0x800003d5, 0x800003f1, 0x800003d6, - 0x80000030, 0x80000031, 0x80000032, 0x80000033, - 0x80000034, 0x80000035, 0x80000036, 0x80000037, - 0x80000038, 0x80000039, 0x80000030, 0x80000031, - 0x80000032, 0x80000033, 0x80000034, 0x80000035, - 0x80000036, 0x80000037, 0x80000038, 0x80000039, - 0x80000030, 0x80000031, 0x80000032, 0x80000033, - 0x80000034, 0x80000035, 0x80000036, 0x80000037, - 0x80000038, 0x80000039, 0x80000030, 0x80000031, - 0x80000032, 0x80000033, 0x80000034, 0x80000035, - 0x80000036, 0x80000037, 0x80000038, 0x80000039, - 0x80000030, 0x80000031, 0x80000032, 0x80000033, - 0x80000034, 0x80000035, 0x80000036, 0x80000037, - 0x80000038, 0x80000039, 0x80004e3d, 0x80004e38, - 0x80004e41, 0x80020122, 0x80004f60, 0x80004fae, - 0x80004fbb, 0x80005002, 0x8000507a, 0x80005099, - 0x800050e7, 0x800050cf, 0x8000349e, 0x8002063a, - 0x8000514d, 0x80005154, 0x80005164, 0x80005177, - 0x8002051c, 0x800034b9, 0x80005167, 0x8000518d, - 0x8002054b, 0x80005197, 0x800051a4, 0x80004ecc, - 0x800051ac, 0x800051b5, 0x800291df, 0x800051f5, - 0x80005203, 0x800034df, 0x8000523b, 0x80005246, - 0x80005272, 0x80005277, 0x80003515, 0x800052c7, - 0x800052c9, 0x800052e4, 0x800052fa, 0x80005305, - 0x80005306, 0x80005317, 0x80005349, 0x80005351, - 0x8000535a, 0x80005373, 0x8000537d, 0x8000537f, - 0x8000537f, 0x8000537f, 0x80020a2c, 0x80007070, - 0x800053ca, 0x800053df, 0x80020b63, 0x800053eb, - 0x800053f1, 0x80005406, 0x8000549e, 0x80005438, - 0x80005448, 0x80005468, 0x800054a2, 0x800054f6, - 0x80005510, 0x80005553, 0x80005563, 0x80005584, - 0x80005584, 0x80005599, 0x800055ab, 0x800055b3, - 0x800055c2, 0x80005716, 0x80005606, 0x80005717, - 0x80005651, 0x80005674, 0x80005207, 0x800058ee, - 0x800057ce, 0x800057f4, 0x8000580d, 0x8000578b, - 0x80005832, 0x80005831, 0x800058ac, 0x800214e4, - 0x800058f2, 0x800058f7, 0x80005906, 0x8000591a, - 0x80005922, 0x80005962, 0x800216a8, 0x800216ea, - 0x800059ec, 0x80005a1b, 0x80005a27, 0x800059d8, - 0x80005a66, 0x800036ee, 0x800036fc, 0x80005b08, - 0x80005b3e, 0x80005b3e, 0x800219c8, 0x80005bc3, - 0x80005bd8, 0x80005be7, 0x80005bf3, 0x80021b18, - 0x80005bff, 0x80005c06, 0x80005f53, 0x80005c22, - 0x80003781, 0x80005c60, 0x80005c6e, 0x80005cc0, - 0x80005c8d, 0x80021de4, 0x80005d43, 0x80021de6, - 0x80005d6e, 0x80005d6b, 0x80005d7c, 0x80005de1, - 0x80005de2, 0x8000382f, 0x80005dfd, 0x80005e28, - 0x80005e3d, 0x80005e69, 0x80003862, 0x80022183, - 0x8000387c, 0x80005eb0, 0x80005eb3, 0x80005eb6, - 0x80005eca, 0x8002a392, 0x80005efe, 0x80022331, - 0x80022331, 0x80008201, 0x80005f22, 0x80005f22, - 0x800038c7, 0x800232b8, 0x800261da, 0x80005f62, - 0x80005f6b, 0x800038e3, 0x80005f9a, 0x80005fcd, - 0x80005fd7, 0x80005ff9, 0x80006081, 0x8000393a, - 0x8000391c, 0x80006094, 0x800226d4, 0x800060c7, - 0x80006148, 0x8000614c, 0x8000614e, 0x8000614c, - 0x8000617a, 0x8000618e, 0x800061b2, 0x800061a4, - 0x800061af, 0x800061de, 0x800061f2, 0x800061f6, - 0x80006210, 0x8000621b, 0x8000625d, 0x800062b1, - 0x800062d4, 0x80006350, 0x80022b0c, 0x8000633d, - 0x800062fc, 0x80006368, 0x80006383, 0x800063e4, - 0x80022bf1, 0x80006422, 0x800063c5, 0x800063a9, - 0x80003a2e, 0x80006469, 0x8000647e, 0x8000649d, - 0x80006477, 0x80003a6c, 0x8000654f, 0x8000656c, - 0x8002300a, 0x800065e3, 0x800066f8, 0x80006649, - 0x80003b19, 0x80006691, 0x80003b08, 0x80003ae4, - 0x80005192, 0x80005195, 0x80006700, 0x8000669c, - 0x800080ad, 0x800043d9, 0x80006717, 0x8000671b, - 0x80006721, 0x8000675e, 0x80006753, 0x800233c3, - 0x80003b49, 0x800067fa, 0x80006785, 0x80006852, - 0x80006885, 0x8002346d, 0x8000688e, 0x8000681f, - 0x80006914, 0x80003b9d, 0x80006942, 0x800069a3, - 0x800069ea, 0x80006aa8, 0x800236a3, 0x80006adb, - 0x80003c18, 0x80006b21, 0x800238a7, 0x80006b54, - 0x80003c4e, 0x80006b72, 0x80006b9f, 0x80006bba, - 0x80006bbb, 0x80023a8d, 0x80021d0b, 0x80023afa, - 0x80006c4e, 0x80023cbc, 0x80006cbf, 0x80006ccd, - 0x80006c67, 0x80006d16, 0x80006d3e, 0x80006d77, - 0x80006d41, 0x80006d69, 0x80006d78, 0x80006d85, - 0x80023d1e, 0x80006d34, 0x80006e2f, 0x80006e6e, - 0x80003d33, 0x80006ecb, 0x80006ec7, 0x80023ed1, - 0x80006df9, 0x80006f6e, 0x80023f5e, 0x80023f8e, - 0x80006fc6, 0x80007039, 0x8000701e, 0x8000701b, - 0x80003d96, 0x8000704a, 0x8000707d, 0x80007077, - 0x800070ad, 0x80020525, 0x80007145, 0x80024263, - 0x8000719c, 0x800243ab, 0x80007228, 0x80007235, - 0x80007250, 0x80024608, 0x80007280, 0x80007295, - 0x80024735, 0x80024814, 0x8000737a, 0x8000738b, - 0x80003eac, 0x800073a5, 0x80003eb8, 0x80003eb8, - 0x80007447, 0x8000745c, 0x80007471, 0x80007485, - 0x800074ca, 0x80003f1b, 0x80007524, 0x80024c36, - 0x8000753e, 0x80024c92, 0x80007570, 0x8002219f, - 0x80007610, 0x80024fa1, 0x80024fb8, 0x80025044, - 0x80003ffc, 0x80004008, 0x800076f4, 0x800250f3, - 0x800250f2, 0x80025119, 0x80025133, 0x8000771e, - 0x8000771f, 0x8000771f, 0x8000774a, 0x80004039, - 0x8000778b, 0x80004046, 0x80004096, 0x8002541d, - 0x8000784e, 0x8000788c, 0x800078cc, 0x800040e3, - 0x80025626, 0x80007956, 0x8002569a, 0x800256c5, - 0x8000798f, 0x800079eb, 0x8000412f, 0x80007a40, - 0x80007a4a, 0x80007a4f, 0x8002597c, 0x80025aa7, - 0x80025aa7, 0x80007aee, 0x80004202, 0x80025bab, - 0x80007bc6, 0x80007bc9, 0x80004227, 0x80025c80, - 0x80007cd2, 0x800042a0, 0x80007ce8, 0x80007ce3, - 0x80007d00, 0x80025f86, 0x80007d63, 0x80004301, - 0x80007dc7, 0x80007e02, 0x80007e45, 0x80004334, - 0x80026228, 0x80026247, 0x80004359, 0x800262d9, - 0x80007f7a, 0x8002633e, 0x80007f95, 0x80007ffa, - 0x80008005, 0x800264da, 0x80026523, 0x80008060, - 0x800265a8, 0x80008070, 0x8002335f, 0x800043d5, - 0x800080b2, 0x80008103, 0x8000440b, 0x8000813e, - 0x80005ab5, 0x800267a7, 0x800267b5, 0x80023393, - 0x8002339c, 0x80008201, 0x80008204, 0x80008f9e, - 0x8000446b, 0x80008291, 0x8000828b, 0x8000829d, - 0x800052b3, 0x800082b1, 0x800082b3, 0x800082bd, - 0x800082e6, 0x80026b3c, 0x800082e5, 0x8000831d, - 0x80008363, 0x800083ad, 0x80008323, 0x800083bd, - 0x800083e7, 0x80008457, 0x80008353, 0x800083ca, - 0x800083cc, 0x800083dc, 0x80026c36, 0x80026d6b, - 0x80026cd5, 0x8000452b, 0x800084f1, 0x800084f3, - 0x80008516, 0x800273ca, 0x80008564, 0x80026f2c, - 0x8000455d, 0x80004561, 0x80026fb1, 0x800270d2, - 0x8000456b, 0x80008650, 0x8000865c, 0x80008667, - 0x80008669, 0x800086a9, 0x80008688, 0x8000870e, - 0x800086e2, 0x80008779, 0x80008728, 0x8000876b, - 0x80008786, 0x800045d7, 0x800087e1, 0x80008801, - 0x800045f9, 0x80008860, 0x80008863, 0x80027667, - 0x800088d7, 0x800088de, 0x80004635, 0x800088fa, - 0x800034bb, 0x800278ae, 0x80027966, 0x800046be, - 0x800046c7, 0x80008aa0, 0x80008aed, 0x80008b8a, - 0x80008c55, 0x80027ca8, 0x80008cab, 0x80008cc1, - 0x80008d1b, 0x80008d77, 0x80027f2f, 0x80020804, - 0x80008dcb, 0x80008dbc, 0x80008df0, 0x800208de, - 0x80008ed4, 0x80008f38, 0x800285d2, 0x800285ed, - 0x80009094, 0x800090f1, 0x80009111, 0x8002872e, - 0x8000911b, 0x80009238, 0x800092d7, 0x800092d8, - 0x8000927c, 0x800093f9, 0x80009415, 0x80028bfa, - 0x8000958b, 0x80004995, 0x800095b7, 0x80028d77, - 0x800049e6, 0x800096c3, 0x80005db2, 0x80009723, - 0x80029145, 0x8002921a, 0x80004a6e, 0x80004a76, - 0x800097e0, 0x8002940a, 0x80004ab2, 0x80029496, - 0x8000980b, 0x8000980b, 0x80009829, 0x800295b6, - 0x800098e2, 0x80004b33, 0x80009929, 0x800099a7, - 0x800099c2, 0x800099fe, 0x80004bce, 0x80029b30, - 0x80009b12, 0x80009c40, 0x80009cfd, 0x80004cce, - 0x80004ced, 0x80009d67, 0x8002a0ce, 0x80004cf8, - 0x8002a105, 0x8002a20e, 0x8002a291, 0x80009ebb, - 0x80004d56, 0x80009ef9, 0x80009efe, 0x80009f05, - 0x80009f0f, 0x80009f16, 0x80009f3b, 0x8002a600, -}; - diff --git a/intl/unicharutil/nsUnicodeNormalizer.cpp b/intl/unicharutil/nsUnicodeNormalizer.cpp index 8fe5d8435f7c..275728717afe 100644 --- a/intl/unicharutil/nsUnicodeNormalizer.cpp +++ b/intl/unicharutil/nsUnicodeNormalizer.cpp @@ -1,704 +1,91 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* This file is modified from JPNIC's mDNKit, it is under both MPL and - * JPNIC's license. - */ - /* 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/. */ -/* - * Copyright (c) 2000,2002 Japan Network Information Center. - * All rights reserved. - * - * By using this file, you agree to the terms and conditions set forth bellow. - * - * LICENSE TERMS AND CONDITIONS - * - * The following License Terms and Conditions apply, unless a different - * license is obtained from Japan Network Information Center ("JPNIC"), - * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda, - * Chiyoda-ku, Tokyo 101-0047, Japan. - * - * 1. Use, Modification and Redistribution (including distribution of any - * modified or derived work) in source and/or binary forms is permitted - * under this License Terms and Conditions. - * - * 2. Redistribution of source code must retain the copyright notices as they - * appear in each source code file, this License Terms and Conditions. - * - * 3. Redistribution in binary form must reproduce the Copyright Notice, - * this License Terms and Conditions, in the documentation and/or other - * materials provided with the distribution. For the purposes of binary - * distribution the "Copyright Notice" refers to the following language: - * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved." - * - * 4. The name of JPNIC may not be used to endorse or promote products - * derived from this Software without specific prior written approval of - * JPNIC. - * - * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - */ - -#include - -#include "nsMemory.h" #include "nsUnicodeNormalizer.h" -#include "nsString.h" -#include "mozilla/BinarySearch.h" +#include "ICUUtils.h" +#include "unicode/unorm2.h" +#include "unicode/utext.h" NS_IMPL_ISUPPORTS(nsUnicodeNormalizer, nsIUnicodeNormalizer) - -nsUnicodeNormalizer::nsUnicodeNormalizer() -{ -} - -nsUnicodeNormalizer::~nsUnicodeNormalizer() -{ -} - - - -#define END_BIT 0x80000000 - - -/* - * Some constants for Hangul decomposition/composition. - * These things were taken from unicode book. - */ -#define SBase 0xac00 -#define LBase 0x1100 -#define VBase 0x1161 -#define TBase 0x11a7 -#define LCount 19 -#define VCount 21 -#define TCount 28 -#define SLast (SBase + LCount * VCount * TCount) - -struct composition { - uint32_t c2; /* 2nd character */ - uint32_t comp; /* composed character */ -}; - - -#include "normalization_data.h" - -/* - * Macro for multi-level index table. - */ -#define LOOKUPTBL(vprefix, mprefix, v) \ - DMAP(vprefix)[\ - IMAP(vprefix)[\ - IMAP(vprefix)[IDX0(mprefix, v)] + IDX1(mprefix, v)\ - ]\ - ].tbl[IDX2(mprefix, v)] - -#define IDX0(mprefix, v) IDX_0(v, BITS1(mprefix), BITS2(mprefix)) -#define IDX1(mprefix, v) IDX_1(v, BITS1(mprefix), BITS2(mprefix)) -#define IDX2(mprefix, v) IDX_2(v, BITS1(mprefix), BITS2(mprefix)) - -#define IDX_0(v, bits1, bits2) ((v) >> ((bits1) + (bits2))) -#define IDX_1(v, bits1, bits2) (((v) >> (bits2)) & ((1 << (bits1)) - 1)) -#define IDX_2(v, bits1, bits2) ((v) & ((1 << (bits2)) - 1)) - -#define BITS1(mprefix) mprefix ## _BITS_1 -#define BITS2(mprefix) mprefix ## _BITS_2 - -#define IMAP(vprefix) vprefix ## _imap -#define DMAP(vprefix) vprefix ## _table -#define SEQ(vprefix) vprefix ## _seq - -static int32_t -canonclass(uint32_t c) { - /* Look up canonicalclass table. */ - return (LOOKUPTBL(canon_class, CANON_CLASS, c)); -} - -static int32_t -decompose_char(uint32_t c, const uint32_t **seqp) -{ - /* Look up decomposition table. */ - int32_t seqidx = LOOKUPTBL(decompose, DECOMP, c); - *seqp = SEQ(decompose) + (seqidx & ~DECOMP_COMPAT); - return (seqidx); -} - -static int32_t -compose_char(uint32_t c, - const struct composition **compp) -{ - /* Look up composition table. */ - int32_t seqidx = LOOKUPTBL(compose, CANON_COMPOSE, c); - *compp = SEQ(compose) + (seqidx & 0xffff); - return (seqidx >> 16); -} - static nsresult -mdn__unicode_decompose(int32_t compat, uint32_t *v, size_t vlen, - uint32_t c, int32_t *decomp_lenp) +DoNormalization(const UNormalizer2* aNorm, const nsAString& aSrc, + nsAString& aDest) { - uint32_t *vorg = v; - int32_t seqidx; - const uint32_t *seq; - - //assert(v != nullptr && vlen >= 0 && decomp_lenp != nullptr); - - /* - * First, check for Hangul. - */ - if (SBase <= c && c < SLast) { - int32_t idx, t_offset, v_offset, l_offset; - - idx = c - SBase; - t_offset = idx % TCount; - idx /= TCount; - v_offset = idx % VCount; - l_offset = idx / VCount; - if ((t_offset == 0 && vlen < 2) || (t_offset > 0 && vlen < 3)) - return (NS_ERROR_UNORM_MOREOUTPUT); - *v++ = LBase + l_offset; - *v++ = VBase + v_offset; - if (t_offset > 0) - *v++ = TBase + t_offset; - *decomp_lenp = v - vorg; - return (NS_OK); - } - - /* - * Look up decomposition table. If no decomposition is defined - * or if it is a compatibility decomosition when canonical - * decomposition requested, return 'NS_SUCCESS_UNORM_NOTFOUND'. - */ - seqidx = decompose_char(c, &seq); - if (seqidx == 0 || (compat == 0 && (seqidx & DECOMP_COMPAT) != 0)) - return (NS_SUCCESS_UNORM_NOTFOUND); - - /* - * Copy the decomposed sequence. The end of the sequence are - * marked with END_BIT. - */ - do { - uint32_t c; - int32_t dlen; - nsresult r; - - c = *seq & ~END_BIT; - - /* Decompose recursively. */ - r = mdn__unicode_decompose(compat, v, vlen, c, &dlen); - if (r == NS_OK) { - v += dlen; - vlen -= dlen; - } else if (r == NS_SUCCESS_UNORM_NOTFOUND) { - if (vlen < 1) - return (NS_ERROR_UNORM_MOREOUTPUT); - *v++ = c; - vlen--; - } else { - return (r); - } - - } while ((*seq++ & END_BIT) == 0); - - *decomp_lenp = v - vorg; - - return (NS_OK); -} - -static int32_t -mdn__unicode_iscompositecandidate(uint32_t c) -{ - const struct composition *dummy; - - /* Check for Hangul */ - if ((LBase <= c && c < LBase + LCount) || (SBase <= c && c < SLast)) - return (1); - - /* - * Look up composition table. If there are no composition - * that begins with the given character, it is not a - * composition candidate. - */ - if (compose_char(c, &dummy) == 0) - return (0); - else - return (1); -} - -namespace { - -struct SequenceAdaptor -{ - const composition* const mSequence; - explicit SequenceAdaptor(const composition* aSequence) : mSequence(aSequence) {} - uint32_t operator[](size_t aIdx) const { - return mSequence[aIdx].c2; - } -}; - -} // namespace - -static nsresult -mdn__unicode_compose(uint32_t c1, uint32_t c2, uint32_t *compp) -{ - int32_t n; - const struct composition *cseq; - - //assert(compp != nullptr); - - /* - * Check for Hangul. - */ - if (LBase <= c1 && c1 < LBase + LCount && - VBase <= c2 && c2 < VBase + VCount) { - /* - * Hangul L and V. - */ - *compp = SBase + - ((c1 - LBase) * VCount + (c2 - VBase)) * TCount; - return (NS_OK); - } else if (SBase <= c1 && c1 < SLast && - TBase <= c2 && c2 < TBase + TCount && - (c1 - SBase) % TCount == 0) { - /* - * Hangul LV and T. - */ - *compp = c1 + (c2 - TBase); - return (NS_OK); - } - - /* - * Look up composition table. If the result is 0, no composition - * is defined. Otherwise, upper 16bits of the result contains - * the number of composition that begins with 'c1', and the lower - * 16bits is the offset in 'compose_seq'. - */ - if ((n = compose_char(c1, &cseq)) == 0) - return (NS_SUCCESS_UNORM_NOTFOUND); - - /* - * The composite sequences are sorted by the 2nd character 'c2'. - * So we can use binary search. - */ - size_t idx; - if (mozilla::BinarySearch(SequenceAdaptor(cseq), 0, n, c2, &idx)) { - *compp = cseq[idx].comp; - return (NS_OK); - } - - return (NS_SUCCESS_UNORM_NOTFOUND); -} - - -#define WORKBUF_SIZE 128 -#define WORKBUF_SIZE_MAX 10000 - -typedef struct { - int32_t cur; /* pointing now processing character */ - int32_t last; /* pointing just after the last character */ - int32_t size; /* size of UCS and CLASS array */ - uint32_t *ucs; /* UCS-4 characters */ - int32_t *cclass; /* and their canonical classes */ - uint32_t ucs_buf[WORKBUF_SIZE]; /* local buffer */ - int32_t class_buf[WORKBUF_SIZE]; /* ditto */ -} workbuf_t; - -static nsresult decompose(workbuf_t *wb, uint32_t c, int32_t compat); -static void get_class(workbuf_t *wb); -static void reorder(workbuf_t *wb); -static void compose(workbuf_t *wb); -static nsresult flush_before_cur(workbuf_t *wb, nsAString& aToStr); -static void workbuf_init(workbuf_t *wb); -static void workbuf_free(workbuf_t *wb); -static nsresult workbuf_extend(workbuf_t *wb); -static nsresult workbuf_append(workbuf_t *wb, uint32_t c); -static void workbuf_shift(workbuf_t *wb, int32_t shift); -static void workbuf_removevoid(workbuf_t *wb); - - -static nsresult -mdn_normalize(bool do_composition, bool compat, - const nsAString& aSrcStr, nsAString& aToStr) -{ - workbuf_t wb; - nsresult r = NS_OK; - /* - * Initialize working buffer. - */ - workbuf_init(&wb); - - nsAString::const_iterator start, end; - aSrcStr.BeginReading(start); - aSrcStr.EndReading(end); - - while (start != end) { - uint32_t c; - char16_t curChar; - - //assert(wb.cur == wb.last); - - /* - * Get one character from 'from'. - */ - curChar= *start++; - - if (NS_IS_HIGH_SURROGATE(curChar) && start != end && NS_IS_LOW_SURROGATE(*(start)) ) { - c = SURROGATE_TO_UCS4(curChar, *start); - ++start; - } else { - c = curChar; - } - - /* - * Decompose it. - */ - if ((r = decompose(&wb, c, compat)) != NS_OK) - break; - - /* - * Get canonical class. - */ - get_class(&wb); - - /* - * Reorder & compose. - */ - for (; wb.cur < wb.last; wb.cur++) { - if (wb.cur == 0) { - continue; - } else if (wb.cclass[wb.cur] > 0) { - /* - * This is not a starter. Try reordering. - * Note that characters up to it are - * already in canonical order. - */ - reorder(&wb); - continue; - } - - /* - * This is a starter character, and there are - * some characters before it. Those characters - * have been reordered properly, and - * ready for composition. - */ - if (do_composition && wb.cclass[0] == 0) - compose(&wb); - - /* - * If CUR points to a starter character, - * then process of characters before CUR are - * already finished, because any further - * reordering/composition for them are blocked - * by the starter CUR points. - */ - if (wb.cur > 0 && wb.cclass[wb.cur] == 0) { - /* Flush everything before CUR. */ - r = flush_before_cur(&wb, aToStr); - if (r != NS_OK) - break; - } - } - } - - if (r == NS_OK) { - if (do_composition && wb.cur > 0 && wb.cclass[0] == 0) { - /* - * There is some characters left in WB. - * They are ordered, but not composed yet. - * Now CUR points just after the last character in WB, - * and since compose() tries to compose characters - * between top and CUR inclusive, we must make CUR - * one character back during compose(). - */ - wb.cur--; - compose(&wb); - wb.cur++; - } - /* - * Call this even when WB.CUR == 0, to make TO - * NUL-terminated. - */ - r = flush_before_cur(&wb, aToStr); - } - - workbuf_free(&wb); - - return (r); -} - -static nsresult -decompose(workbuf_t *wb, uint32_t c, int32_t compat) { - nsresult r; - int32_t dec_len; - -again: - r = mdn__unicode_decompose(compat, wb->ucs + wb->last, - wb->size - wb->last, c, &dec_len); - switch (r) { - case NS_OK: - wb->last += dec_len; - return (NS_OK); - case NS_SUCCESS_UNORM_NOTFOUND: - return (workbuf_append(wb, c)); - case NS_ERROR_UNORM_MOREOUTPUT: - if ((r = workbuf_extend(wb)) != NS_OK) - return (r); - if (wb->size > WORKBUF_SIZE_MAX) { - // "mdn__unormalize_form*: " "working buffer too large\n" - return (NS_ERROR_FAILURE); - } - goto again; - default: - return (r); - } - /* NOTREACHED */ -} - -static void -get_class(workbuf_t *wb) { - int32_t i; - - for (i = wb->cur; i < wb->last; i++) - wb->cclass[i] = canonclass(wb->ucs[i]); -} - -static void -reorder(workbuf_t *wb) { - uint32_t c; - int32_t i; - int32_t cclass; - - //assert(wb != nullptr); - - i = wb->cur; - c = wb->ucs[i]; - cclass = wb->cclass[i]; - - while (i > 0 && wb->cclass[i - 1] > cclass) { - wb->ucs[i] = wb->ucs[i - 1]; - wb->cclass[i] =wb->cclass[i - 1]; - i--; - wb->ucs[i] = c; - wb->cclass[i] = cclass; - } -} - -static void -compose(workbuf_t *wb) { - int32_t cur; - uint32_t *ucs; - int32_t *cclass; - int32_t last_class; - int32_t nvoids; - int32_t i; - - //assert(wb != nullptr && wb->cclass[0] == 0); - - cur = wb->cur; - ucs = wb->ucs; - cclass = wb->cclass; - - /* - * If there are no decomposition sequence that begins with - * the top character, composition is impossible. - */ - if (!mdn__unicode_iscompositecandidate(ucs[0])) - return; - - last_class = 0; - nvoids = 0; - for (i = 1; i <= cur; i++) { - uint32_t c; - int32_t cl = cclass[i]; - - if ((last_class < cl || cl == 0) && - mdn__unicode_compose(ucs[0], ucs[i], - &c) == NS_OK) { - /* - * Replace the top character with the composed one. - */ - ucs[0] = c; - cclass[0] = canonclass(c); - - cclass[i] = -1; /* void this character */ - nvoids++; - } else { - last_class = cl; - } - } - - /* Purge void characters, if any. */ - if (nvoids > 0) - workbuf_removevoid(wb); -} - -static nsresult -flush_before_cur(workbuf_t *wb, nsAString& aToStr) -{ - int32_t i; - - for (i = 0; i < wb->cur; i++) { - if (!IS_IN_BMP(wb->ucs[i])) { - aToStr.Append((char16_t)H_SURROGATE(wb->ucs[i])); - aToStr.Append((char16_t)L_SURROGATE(wb->ucs[i])); - } else { - aToStr.Append((char16_t)(wb->ucs[i])); - } - } - - workbuf_shift(wb, wb->cur); - - return (NS_OK); -} - -static void -workbuf_init(workbuf_t *wb) { - wb->cur = 0; - wb->last = 0; - wb->size = WORKBUF_SIZE; - wb->ucs = wb->ucs_buf; - wb->cclass = wb->class_buf; -} - -static void -workbuf_free(workbuf_t *wb) { - if (wb->ucs != wb->ucs_buf) { - free(wb->ucs); - free(wb->cclass); - } -} - -static nsresult -workbuf_extend(workbuf_t *wb) { - int32_t newsize = wb->size * 3; - - if (wb->ucs == wb->ucs_buf) { - wb->ucs = (uint32_t*)moz_xmalloc(sizeof(wb->ucs[0]) * newsize); - if (!wb->ucs) - return NS_ERROR_OUT_OF_MEMORY; - wb->cclass = (int32_t*)moz_xmalloc(sizeof(wb->cclass[0]) * newsize); - if (!wb->cclass) { - free(wb->ucs); - wb->ucs = nullptr; - return NS_ERROR_OUT_OF_MEMORY; - } - } else { - void* buf = moz_xrealloc(wb->ucs, sizeof(wb->ucs[0]) * newsize); - if (!buf) - return NS_ERROR_OUT_OF_MEMORY; - wb->ucs = (uint32_t*)buf; - buf = moz_xrealloc(wb->cclass, sizeof(wb->cclass[0]) * newsize); - if (!buf) - return NS_ERROR_OUT_OF_MEMORY; - wb->cclass = (int32_t*)buf; - } - return (NS_OK); -} - -static nsresult -workbuf_append(workbuf_t *wb, uint32_t c) { - nsresult r; - - if (wb->last >= wb->size && (r = workbuf_extend(wb)) != NS_OK) - return (r); - wb->ucs[wb->last++] = c; - return (NS_OK); -} - -static void -workbuf_shift(workbuf_t *wb, int32_t shift) { - int32_t nmove; - - //assert(wb != nullptr && wb->cur >= shift); - - nmove = wb->last - shift; - memmove(&wb->ucs[0], &wb->ucs[shift], - nmove * sizeof(wb->ucs[0])); - memmove(&wb->cclass[0], &wb->cclass[shift], - nmove * sizeof(wb->cclass[0])); - wb->cur -= shift; - wb->last -= shift; -} - -static void -workbuf_removevoid(workbuf_t *wb) { - int32_t i, j; - int32_t last = wb->last; - - for (i = j = 0; i < last; i++) { - if (wb->cclass[i] >= 0) { - if (j < i) { - wb->ucs[j] = wb->ucs[i]; - wb->cclass[j] = wb->cclass[i]; - } - j++; - } - } - wb->cur -= last - j; - wb->last = j; -} - -nsresult -nsUnicodeNormalizer::NormalizeUnicodeNFD( const nsAString& aSrc, nsAString& aDest) -{ - return mdn_normalize(false, false, aSrc, aDest); -} - -nsresult -nsUnicodeNormalizer::NormalizeUnicodeNFC( const nsAString& aSrc, nsAString& aDest) -{ - return mdn_normalize(true, false, aSrc, aDest); -} - -nsresult -nsUnicodeNormalizer::NormalizeUnicodeNFKD( const nsAString& aSrc, nsAString& aDest) -{ - return mdn_normalize(false, true, aSrc, aDest); -} - -nsresult -nsUnicodeNormalizer::NormalizeUnicodeNFKC( const nsAString& aSrc, nsAString& aDest) -{ - return mdn_normalize(true, true, aSrc, aDest); -} - -bool -nsUnicodeNormalizer::Compose(uint32_t a, uint32_t b, uint32_t *ab) -{ - return mdn__unicode_compose(a, b, ab) == NS_OK; -} - -bool -nsUnicodeNormalizer::DecomposeNonRecursively(uint32_t c, uint32_t *c1, uint32_t *c2) -{ - // We can't use mdn__unicode_decompose here, because that does a recursive - // decomposition that may yield more than two characters, but the harfbuzz - // callback wants just a single-step decomp that is guaranteed to produce - // no more than two characters. So we do a low-level lookup in the table - // of decomp sequences. - const uint32_t *seq; - uint32_t seqidx = decompose_char(c, &seq); - if (seqidx == 0 || ((seqidx & DECOMP_COMPAT) != 0)) { - return false; + UErrorCode errorCode = U_ZERO_ERROR; + const int32_t length = aSrc.Length(); + const UChar* src = reinterpret_cast(aSrc.BeginReading()); + // Initial guess for a capacity that is likely to be enough for most cases. + int32_t capacity = length + (length >> 8) + 8; + while (true) { + aDest.SetLength(capacity); + UChar* dest = reinterpret_cast(aDest.BeginWriting()); + int32_t len = unorm2_normalize(aNorm, src, aSrc.Length(), dest, capacity, + &errorCode); + if (U_SUCCESS(errorCode)) { + aDest.SetLength(len); + break; + } + if (errorCode != U_BUFFER_OVERFLOW_ERROR) { + // Some other error that we don't handle + break; + } + // Buffer wasn't big enough; adjust to the reported size and try again. + capacity = len; + errorCode = U_ZERO_ERROR; } - *c1 = *seq & ~END_BIT; - if (*seq & END_BIT) { - *c2 = 0; - } else { - *c2 = *++seq & ~END_BIT; - } - return true; + return ICUUtils::UErrorToNsResult(errorCode); +} + +nsresult +nsUnicodeNormalizer::NormalizeUnicodeNFD(const nsAString& aSrc, + nsAString& aDest) +{ + // The unorm2_getNF*Instance functions return static singletons that should + // not be deleted, so we just get them once on first use. + static UErrorCode errorCode = U_ZERO_ERROR; + static const UNormalizer2* norm = unorm2_getNFDInstance(&errorCode); + if (U_SUCCESS(errorCode)) { + return DoNormalization(norm, aSrc, aDest); + } + return ICUUtils::UErrorToNsResult(errorCode); +} + +nsresult +nsUnicodeNormalizer::NormalizeUnicodeNFC(const nsAString& aSrc, + nsAString& aDest) +{ + static UErrorCode errorCode = U_ZERO_ERROR; + static const UNormalizer2* norm = unorm2_getNFCInstance(&errorCode); + if (U_SUCCESS(errorCode)) { + return DoNormalization(norm, aSrc, aDest); + } + return ICUUtils::UErrorToNsResult(errorCode); +} + +nsresult +nsUnicodeNormalizer::NormalizeUnicodeNFKD(const nsAString& aSrc, + nsAString& aDest) +{ + static UErrorCode errorCode = U_ZERO_ERROR; + static const UNormalizer2* norm = unorm2_getNFKDInstance(&errorCode); + if (U_SUCCESS(errorCode)) { + return DoNormalization(norm, aSrc, aDest); + } + return ICUUtils::UErrorToNsResult(errorCode); +} + +nsresult +nsUnicodeNormalizer::NormalizeUnicodeNFKC(const nsAString& aSrc, + nsAString& aDest) +{ + static UErrorCode errorCode = U_ZERO_ERROR; + static const UNormalizer2* norm = unorm2_getNFKCInstance(&errorCode); + if (U_SUCCESS(errorCode)) { + return DoNormalization(norm, aSrc, aDest); + } + return ICUUtils::UErrorToNsResult(errorCode); } diff --git a/intl/unicharutil/nsUnicodeNormalizer.h b/intl/unicharutil/nsUnicodeNormalizer.h index 347c703c2d1d..f4d905c1352e 100644 --- a/intl/unicharutil/nsUnicodeNormalizer.h +++ b/intl/unicharutil/nsUnicodeNormalizer.h @@ -16,7 +16,7 @@ nsresult NS_NewUnicodeNormalizer(nsISupports** oResult); class nsUnicodeNormalizer : public nsIUnicodeNormalizer { public: - nsUnicodeNormalizer(); + nsUnicodeNormalizer() { } NS_DECL_ISUPPORTS @@ -25,15 +25,8 @@ public: NS_IMETHOD NormalizeUnicodeNFKD( const nsAString& aSrc, nsAString& aDest) override; NS_IMETHOD NormalizeUnicodeNFKC( const nsAString& aSrc, nsAString& aDest) override; -#if !ENABLE_INTL_API - // Low-level access to the composition data needed for HarfBuzz callbacks; - // only required when ICU is not available in the build. - static bool Compose(uint32_t a, uint32_t b, uint32_t *ab); - static bool DecomposeNonRecursively(uint32_t comp, uint32_t *c1, uint32_t *c2); -#endif - private: - virtual ~nsUnicodeNormalizer(); + virtual ~nsUnicodeNormalizer() { } }; #endif //nsUnicodeNormalizer_h__ diff --git a/intl/unicharutil/nsUnicodeNormalizer_ICU.cpp b/intl/unicharutil/nsUnicodeNormalizer_ICU.cpp deleted file mode 100644 index 9f852e28cd34..000000000000 --- a/intl/unicharutil/nsUnicodeNormalizer_ICU.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsUnicodeNormalizer.h" -#include "ICUUtils.h" -#include "unicode/unorm2.h" -#include "unicode/utext.h" - -NS_IMPL_ISUPPORTS(nsUnicodeNormalizer, nsIUnicodeNormalizer) - -nsUnicodeNormalizer::nsUnicodeNormalizer() -{ -} - -nsUnicodeNormalizer::~nsUnicodeNormalizer() -{ -} - -static nsresult -DoNormalization(const UNormalizer2* aNorm, const nsAString& aSrc, - nsAString& aDest) -{ - UErrorCode errorCode = U_ZERO_ERROR; - const int32_t length = aSrc.Length(); - const UChar* src = reinterpret_cast(aSrc.BeginReading()); - // Initial guess for a capacity that is likely to be enough for most cases. - int32_t capacity = length + (length >> 8) + 8; - while (true) { - aDest.SetLength(capacity); - UChar* dest = reinterpret_cast(aDest.BeginWriting()); - int32_t len = unorm2_normalize(aNorm, src, aSrc.Length(), dest, capacity, - &errorCode); - if (U_SUCCESS(errorCode)) { - aDest.SetLength(len); - break; - } - if (errorCode != U_BUFFER_OVERFLOW_ERROR) { - // Some other error that we don't handle - break; - } - // Buffer wasn't big enough; adjust to the reported size and try again. - capacity = len; - errorCode = U_ZERO_ERROR; - } - return ICUUtils::UErrorToNsResult(errorCode); -} - -nsresult -nsUnicodeNormalizer::NormalizeUnicodeNFD(const nsAString& aSrc, - nsAString& aDest) -{ - // The unorm2_getNF*Instance functions return static singletons that should - // not be deleted, so we just get them once on first use. - static UErrorCode errorCode = U_ZERO_ERROR; - static const UNormalizer2* norm = unorm2_getNFDInstance(&errorCode); - if (U_SUCCESS(errorCode)) { - return DoNormalization(norm, aSrc, aDest); - } - return ICUUtils::UErrorToNsResult(errorCode); -} - -nsresult -nsUnicodeNormalizer::NormalizeUnicodeNFC(const nsAString& aSrc, - nsAString& aDest) -{ - static UErrorCode errorCode = U_ZERO_ERROR; - static const UNormalizer2* norm = unorm2_getNFCInstance(&errorCode); - if (U_SUCCESS(errorCode)) { - return DoNormalization(norm, aSrc, aDest); - } - return ICUUtils::UErrorToNsResult(errorCode); -} - -nsresult -nsUnicodeNormalizer::NormalizeUnicodeNFKD(const nsAString& aSrc, - nsAString& aDest) -{ - static UErrorCode errorCode = U_ZERO_ERROR; - static const UNormalizer2* norm = unorm2_getNFKDInstance(&errorCode); - if (U_SUCCESS(errorCode)) { - return DoNormalization(norm, aSrc, aDest); - } - return ICUUtils::UErrorToNsResult(errorCode); -} - -nsresult -nsUnicodeNormalizer::NormalizeUnicodeNFKC(const nsAString& aSrc, - nsAString& aDest) -{ - static UErrorCode errorCode = U_ZERO_ERROR; - static const UNormalizer2* norm = unorm2_getNFKCInstance(&errorCode); - if (U_SUCCESS(errorCode)) { - return DoNormalization(norm, aSrc, aDest); - } - return ICUUtils::UErrorToNsResult(errorCode); -} From 6ad441ca989de7bb883e0d4994436334b4d6881a Mon Sep 17 00:00:00 2001 From: Bevis Tseng Date: Tue, 19 Sep 2017 15:52:48 +0800 Subject: [PATCH 17/37] Bug 1401105 - Fix the failure of keypath-special-identifiers.htm. r=baku --HG-- extra : rebase_source : 5b741f3c061c2e07cc7e4dc2caa7f772b513ad4c --- dom/indexedDB/KeyPath.cpp | 4 ++-- .../meta/IndexedDB/keypath-special-identifiers.htm.ini | 5 ----- 2 files changed, 2 insertions(+), 7 deletions(-) delete mode 100644 testing/web-platform/meta/IndexedDB/keypath-special-identifiers.htm.ini diff --git a/dom/indexedDB/KeyPath.cpp b/dom/indexedDB/KeyPath.cpp index 272f6d4027d3..7e0a98cdc766 100644 --- a/dom/indexedDB/KeyPath.cpp +++ b/dom/indexedDB/KeyPath.cpp @@ -104,10 +104,10 @@ GetJSValFromKeyPathString(JSContext* aCx, bool hasProp; if (!targetObject) { // We're still walking the chain of existing objects - // http://w3c.github.io/IndexedDB/#dfn-evaluate-a-key-path-on-a-value + // http://w3c.github.io/IndexedDB/#evaluate-a-key-path-on-a-value // step 4 substep 1: check for .length on a String value. if (currentVal.isString() && !tokenizer.hasMoreTokens() && - token.EqualsLiteral("length") && aOptions == DoNotCreateProperties) { + token.EqualsLiteral("length")) { aKeyJSVal->setNumber(double(JS_GetStringLength(currentVal.toString()))); break; } diff --git a/testing/web-platform/meta/IndexedDB/keypath-special-identifiers.htm.ini b/testing/web-platform/meta/IndexedDB/keypath-special-identifiers.htm.ini deleted file mode 100644 index 45a15808f673..000000000000 --- a/testing/web-platform/meta/IndexedDB/keypath-special-identifiers.htm.ini +++ /dev/null @@ -1,5 +0,0 @@ -[keypath-special-identifiers.htm] - type: testharness - [Type: String, identifier: length] - expected: FAIL - From d2b7163264c07a3c4c8fb2527ff4e2b9bb527240 Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Fri, 22 Sep 2017 11:52:48 +0200 Subject: [PATCH 18/37] Bug 1402270 - Sanitizer and BrowsingData should delete QuotaManager storages using the origin directly and not the origin as pattern, r=janv --- browser/base/content/sanitize.js | 2 +- browser/components/extensions/ext-browsingData.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/browser/base/content/sanitize.js b/browser/base/content/sanitize.js index faafaa686299..174d51c72282 100644 --- a/browser/base/content/sanitize.js +++ b/browser/base/content/sanitize.js @@ -313,7 +313,7 @@ Sanitizer.prototype = { let uri = principal.URI; if (uri.scheme == "http" || uri.scheme == "https" || uri.scheme == "file") { promises.push(new Promise(r => { - let req = quotaManagerService.clearStoragesForPrincipal(principal, null, true); + let req = quotaManagerService.clearStoragesForPrincipal(principal, null, false); req.callback = () => { r(); }; })); } diff --git a/browser/components/extensions/ext-browsingData.js b/browser/components/extensions/ext-browsingData.js index 0424d415d48d..b3dc24eff64e 100644 --- a/browser/components/extensions/ext-browsingData.js +++ b/browser/components/extensions/ext-browsingData.js @@ -93,7 +93,7 @@ const clearIndexedDB = async function(options) { let uri = principal.URI; if (uri.scheme == "http" || uri.scheme == "https" || uri.scheme == "file") { promises.push(new Promise(r => { - let req = quotaManagerService.clearStoragesForPrincipal(principal, null, true); + let req = quotaManagerService.clearStoragesForPrincipal(principal, null, false); req.callback = () => { r(); }; })); } From abf683608c88b8a61bb51b662d66168d1b7c08e9 Mon Sep 17 00:00:00 2001 From: sotaro Date: Fri, 22 Sep 2017 19:07:15 +0900 Subject: [PATCH 19/37] Bug 1294788 - Disable AssumeThemePartAndStateAreTransparent() on high contrast mode since Win8.1 r=jrmuizel The problem happened only on themed widget. The problem was triggered by Bug 888870. It just added Windows 8.1 support. When high contrast mode was enabled on Win 10, background color problem happend on themed widgets. There were 2 patterns. - After hover the menu item, its background color remained highlighted - After hover the menu item, its background color became black From it, the problem seemed to be caused by background color drawing of themed widgets. nsNativeThemeWin::DrawWidgetBackground() does the background color drawing. AssumeThemePartAndStateAreTransparent() controls skipping background color drawing of themed widgets. If AssumeThemePartAndStateAreTransparent() was removed, the problem was addressed. From it, how DrawThemeBackground() works seems to be changed on high contrast mode since since Win8.1. To address the problem, the patch remove the skipping on high contrast mode since since Win8.1 --- widget/windows/nsNativeThemeWin.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/widget/windows/nsNativeThemeWin.cpp b/widget/windows/nsNativeThemeWin.cpp index 3f32074d365c..139417b20612 100644 --- a/widget/windows/nsNativeThemeWin.cpp +++ b/widget/windows/nsNativeThemeWin.cpp @@ -1492,7 +1492,8 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, uint8_t aWidgetType, static bool AssumeThemePartAndStateAreTransparent(int32_t aPart, int32_t aState) { - if (aPart == MENU_POPUPITEM && aState == MBI_NORMAL) { + if (!(IsWin8Point1OrLater() && nsUXThemeData::IsHighContrastOn()) && + aPart == MENU_POPUPITEM && aState == MBI_NORMAL) { return true; } return false; From f2339cc31cdc21aa79e3c6e213fdae22cb08451e Mon Sep 17 00:00:00 2001 From: Sebastian Hengst Date: Fri, 22 Sep 2017 12:35:00 +0200 Subject: [PATCH 20/37] Backed out changeset be26c0a0a56f (bug 1380033) for build bustage on Windows at js/src/shell/js.cpp(1351). r=backout on a CLOSED TREE --- js/src/jit/ProcessExecutableMemory.cpp | 7 - js/src/jit/ProcessExecutableMemory.h | 5 - js/src/jsapi.cpp | 10 - js/src/jsapi.h | 14 - js/src/shell/js.cpp | 72 ----- js/src/wasm/WasmCompile.cpp | 405 +------------------------ js/src/wasm/WasmGenerator.h | 8 +- js/src/wasm/WasmValidate.cpp | 28 +- js/src/wasm/WasmValidate.h | 37 +-- 9 files changed, 29 insertions(+), 557 deletions(-) diff --git a/js/src/jit/ProcessExecutableMemory.cpp b/js/src/jit/ProcessExecutableMemory.cpp index 5dd04def0522..9224824c9166 100644 --- a/js/src/jit/ProcessExecutableMemory.cpp +++ b/js/src/jit/ProcessExecutableMemory.cpp @@ -619,13 +619,6 @@ js::jit::ReleaseProcessExecutableMemory() execMemory.release(); } -size_t -js::jit::LikelyAvailableExecutableMemory() -{ - // Round down available memory to the closest MB. - return MaxCodeBytesPerProcess - AlignBytes(execMemory.bytesAllocated(), 0x100000U); -} - bool js::jit::CanLikelyAllocateMoreExecutableMemory() { diff --git a/js/src/jit/ProcessExecutableMemory.h b/js/src/jit/ProcessExecutableMemory.h index 26a997168c94..c578becb80e6 100644 --- a/js/src/jit/ProcessExecutableMemory.h +++ b/js/src/jit/ProcessExecutableMemory.h @@ -50,11 +50,6 @@ extern void DeallocateExecutableMemory(void* addr, size_t bytes); // function. extern bool CanLikelyAllocateMoreExecutableMemory(); -// Returns a rough guess of how much executable memory remains available, -// rounded down to MB limit. Note this can fluctuate as other threads within -// the process allocate executable memory. -extern size_t LikelyAvailableExecutableMemory(); - } // namespace jit } // namespace js diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index a87079b1c5e2..1907b5873eff 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -7659,16 +7659,6 @@ JS::SetProcessLargeAllocationFailureCallback(JS::LargeAllocationFailureCallback OnLargeAllocationFailure = lafc; } -namespace js { - JS::SystemInformation gSysinfo; -} - -JS_PUBLIC_API(void) -JS::SetSystemInformation(const JS::SystemInformation* info) -{ - gSysinfo = *info; -} - JS_PUBLIC_API(void) JS::SetOutOfMemoryCallback(JSContext* cx, OutOfMemoryCallback cb, void* data) { diff --git a/js/src/jsapi.h b/js/src/jsapi.h index ba2d03e8e85f..c970ad6dbe15 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -6710,20 +6710,6 @@ typedef void extern JS_PUBLIC_API(void) SetProcessLargeAllocationFailureCallback(LargeAllocationFailureCallback afc); -/** - * SetSystemInformation() must be called to set up system information that - * SpiderMonkey requires. Normally this is setup is performed at the same time - * as callbacks are set up. The function copies the pointed-to structure. - */ - -struct JS_PUBLIC_API(SystemInformation) -{ - uint32_t maxCpuClockMHz; // 0 means "no information" -}; - -extern JS_PUBLIC_API(void) -SetSystemInformation(const SystemInformation* info); - /** * Unlike the error reporter, which is only called if the exception for an OOM * bubbles up and is not caught, the OutOfMemoryCallback is called immediately diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 21e16d07dac6..2bb7e97120a7 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -44,9 +44,6 @@ # include # include #endif -#ifdef XP_DARWIN -# include -#endif #include "jsapi.h" #include "jsarray.h" @@ -1333,70 +1330,6 @@ my_LargeAllocFailCallback() cx->runtime()->gc.gc(GC_NORMAL, JS::gcreason::SHARED_MEMORY_LIMIT); } -// Most of the GetCPUSpeed code was pilfered from xpcom/base/nsSystemInfo.cpp. -// Returns 0 if no information is available. - -static uint32_t -GetCPUSpeed() -{ - uint32_t cpuSpeed = 0; - - if (getenv("JS_CPU_MHZ")) - return atoi(getenv("JS_CPU_MHZ")); - -#if defined(XP_WIN) - - HKEY key; - static const WCHAR keyName[] = L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"; - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName , 0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) { - DWORD len = sizeof(data); - DWORD data; - if (RegQueryValueEx(key, L"~Mhz", 0, 0, reinterpret_cast(&data), - &len) == ERROR_SUCCESS) - { - cpuSpeed = static_cast(data); - } - RegCloseKey(key); - } - -#elif defined(XP_DARWIN) - - uint64_t sysctlValue64 = 0; - size_t len = sizeof(sysctlValue64); - if (!sysctlbyname("hw.cpufrequency_max", &sysctlValue64, &len, NULL, 0)) - cpuSpeed = static_cast(sysctlValue64 / 1000000); - -#elif defined(XP_UNIX) // Including Android - - // A known file contains the CPU frequency in KHz. - // - // This file should be present also on Android, it is on all of lth's - // Android devices (none of which are rooted), and on those devices it can - // be read by an app using stdio from C++ code. (Not sure if that's - // conclusive; the app was installed over adb, so what about permissions?) - // - // On multicore devices where the cores are not all equal this may actually - // be the wrong value: lth sees some other cpuN values that are higher than - // the cpu0 values. But it's unclear if those are the "little" CPUs in a - // BIG.little configuration, for example. - - FILE* fp = fopen("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq", "r"); - if (fp) { - char buf[128]; - if (fgets(buf, sizeof(buf), fp)) - cpuSpeed = uint32_t(atol(buf)/1000); - fclose(fp); - } - -#else - -# error "What OS is this?" - -#endif - - return cpuSpeed; -} - static const uint32_t CacheEntry_SOURCE = 0; static const uint32_t CacheEntry_BYTECODE = 1; @@ -8695,11 +8628,6 @@ main(int argc, char** argv, char** envp) JS::SetProcessLargeAllocationFailureCallback(my_LargeAllocFailCallback); - JS::SystemInformation info; - info.maxCpuClockMHz = GetCPUSpeed(); - - JS::SetSystemInformation(&info); - // Set some parameters to allow incremental GC in low memory conditions, // as is done for the browser, except in more-deterministic builds or when // disabled by command line options. diff --git a/js/src/wasm/WasmCompile.cpp b/js/src/wasm/WasmCompile.cpp index 71d9dba014cc..18bce76b9060 100644 --- a/js/src/wasm/WasmCompile.cpp +++ b/js/src/wasm/WasmCompile.cpp @@ -23,7 +23,6 @@ #include "jsprf.h" -#include "jit/ProcessExecutableMemory.h" #include "wasm/WasmBaselineCompile.h" #include "wasm/WasmBinaryIterator.h" #include "wasm/WasmGenerator.h" @@ -34,21 +33,6 @@ using namespace js; using namespace js::jit; using namespace js::wasm; -#define WASM_POLICY_SPEW - -#ifdef WASM_POLICY_SPEW -static void -PolicySpew(const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - vfprintf(stderr, fmt, args); - va_end(args); -} -#else -# define PolicySpew(...) (void)0 -#endif - static bool DecodeFunctionBody(Decoder& d, ModuleGenerator& mg, uint32_t funcIndex) { @@ -119,340 +103,10 @@ CompileArgs::initFromContext(JSContext* cx, ScriptedCaller&& scriptedCaller) return assumptions.initBuildIdFromContext(cx); } -namespace js { - extern JS::SystemInformation gSysinfo; -} - -enum class SystemClass -{ - DesktopX86, - DesktopX64, - DesktopUnknown32, - DesktopUnknown64, - MobileX86, - MobileArm32, - MobileArm64, - MobileUnknown32, - MobileUnknown64 -}; - -// Classify the current system as one among the known classes. This really -// needs to get our tier-1 systems right. In cases where there's doubt about -// desktop vs mobile we could also try to use physical memory, core -// configuration, OS details, CPU speed, CPU class, or CPU manufacturer to -// disambiguate. This would factor into an additional dimension such as -// {low,medium,high}-end. - -static SystemClass -Classify() -{ - bool isDesktop; - -#if defined(ANDROID) || defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) - isDesktop = false; -#else - isDesktop = true; -#endif - - if (isDesktop) { -#if defined(JS_CODEGEN_X64) - return SystemClass::DesktopX64; -#elif defined(JS_CODEGEN_X86) - return SystemClass::DesktopX86; -#elif defined(JS_64BIT) - return SystemClass::DesktopUnknown64; -#else - return SystemClass::DesktopUnknown32; -#endif - } else { -#if defined(JS_CODEGEN_X86) - return SystemClass::MobileX86; -#elif defined(JS_CODEGEN_ARM) - return SystemClass::MobileArm32; -#elif defined(JS_CODEGEN_ARM64) - return SystemClass::MobileArm64; -#elif defined(JS_64BIT) - return SystemClass::MobileUnknown64; -#else - return SystemClass::MobileUnknown32; -#endif - } -} - static bool -IsDesktop(SystemClass cls) +BackgroundWorkPossible() { - return cls <= SystemClass::DesktopUnknown64; -} - -// An estimate of the local performance relative to the reference system. -// "Performance" should be some measure of clock speed and CPI for a realistic -// instruction mix. -// -// On desktop the reference system is a 16GB late-2013 MacBook Pro; on mobile a -// 2GB late-2014 Nvidia Jetson TK1 Tegra board. Both remain high-end as of -// late-2017. - -static double -RelativePerformance(SystemClass cls) -{ - // Note, cpu max clock frequency is an extremely crude approximation of - // speed. The reference MacBook Pro has a significantly lower max frequency - // than my older AMD tower, but is still a much faster system; the MBP has a - // slightly lower max frequency than my new high-end Xeon too, but the Xeon - // can barely keep up, even when tuned to avoid NUMA effects. - - // These values were recorded by running on the respective systems. - - const double referenceDesktopMaxMHz = 2600; // Haswell i7-4850HQ - const double referenceMobileMaxMHz = 2300; // Tegra Cortex-A15 - - if (gSysinfo.maxCpuClockMHz == 0) - return 1; - - // Since the reference systems are both quite fast, and we only have CPU - // clock speed to guide us right now, we will assume no systems are faster - // than the reference systems, regardless of clock speed. - - double referenceMaxMHz = IsDesktop(cls) ? referenceDesktopMaxMHz : referenceMobileMaxMHz; - return Min(1.0, gSysinfo.maxCpuClockMHz / referenceMaxMHz); -} - -// Various factors for the reference systems. These are based on empirical -// measurements except where marked "Guess". Relationships have been found to -// be roughly linear across program sizes, so there's no need to make this -// complicated. -// -// For the "Unknown" classifications we just have to pick a plausible proxy. - -// Compilation rates in bytecodes per millisecond. -static const double x64DesktopBytecodesPerMs = 2100; -static const double x86DesktopBytecodesPerMs = x64DesktopBytecodesPerMs / 1.4; -static const double arm32MobileBytecodesPerMs = x64DesktopBytecodesPerMs / 3.3; -static const double x86MobileBytecodesPerMs = x86DesktopBytecodesPerMs / 2.0; // Guess -static const double arm64MobileBytecodesPerMs = x86MobileBytecodesPerMs; // Guess - -static double -BytecodesPerMs(SystemClass cls) -{ - switch (cls) { - case SystemClass::DesktopX86: - case SystemClass::DesktopUnknown32: - return x86DesktopBytecodesPerMs; - case SystemClass::DesktopX64: - case SystemClass::DesktopUnknown64: - return x64DesktopBytecodesPerMs; - case SystemClass::MobileX86: - return x86MobileBytecodesPerMs; - case SystemClass::MobileArm32: - case SystemClass::MobileUnknown32: - return arm32MobileBytecodesPerMs; - case SystemClass::MobileArm64: - case SystemClass::MobileUnknown64: - return arm64MobileBytecodesPerMs; - default: - MOZ_CRASH(); - } -}; - -#ifndef JS_64BIT - -// Code sizes in machine code bytes per bytecode byte, again empirical except -// where marked as "Guess". - -static const double x64Tox86Inflation = 1.25; - -static const double x64IonBytesPerBytecode = 2.45; -static const double x86IonBytesPerBytecode = x64IonBytesPerBytecode * x64Tox86Inflation; -static const double arm32IonBytesPerBytecode = 3.3; -static const double arm64IonBytesPerBytecode = 3.0; // Guess - -static const double x64BaselineBytesPerBytecode = x64IonBytesPerBytecode * 1.43; -static const double x86BaselineBytesPerBytecode = x64BaselineBytesPerBytecode * x64Tox86Inflation; -static const double arm32BaselineBytesPerBytecode = arm32IonBytesPerBytecode * 1.39; -static const double arm64BaselineBytesPerBytecode = arm64IonBytesPerBytecode * 1.39; // Guess - -static double -IonBytesPerBytecode(SystemClass cls) -{ - switch (cls) { - case SystemClass::DesktopX86: - case SystemClass::MobileX86: - case SystemClass::DesktopUnknown32: - return x86IonBytesPerBytecode; - case SystemClass::DesktopX64: - case SystemClass::DesktopUnknown64: - return x64IonBytesPerBytecode; - case SystemClass::MobileArm32: - case SystemClass::MobileUnknown32: - return arm32IonBytesPerBytecode; - case SystemClass::MobileArm64: - case SystemClass::MobileUnknown64: - return arm64IonBytesPerBytecode; - default: - MOZ_CRASH(); - } -} - -static double -BaselineBytesPerBytecode(SystemClass cls) -{ - switch (cls) { - case SystemClass::DesktopX86: - case SystemClass::MobileX86: - case SystemClass::DesktopUnknown32: - return x86BaselineBytesPerBytecode; - case SystemClass::DesktopX64: - case SystemClass::DesktopUnknown64: - return x64BaselineBytesPerBytecode; - case SystemClass::MobileArm32: - case SystemClass::MobileUnknown32: - return arm32BaselineBytesPerBytecode; - case SystemClass::MobileArm64: - case SystemClass::MobileUnknown64: - return arm64BaselineBytesPerBytecode; - default: - MOZ_CRASH(); - } -} -#endif // !JS_64BIT - -static uint32_t -MillisToIonCompileOnThisSystem(SystemClass cls, uint32_t codeSize) -{ - return Max(1U, uint32_t(codeSize / BytecodesPerMs(cls) / RelativePerformance(cls))); -} - -static double -EffectiveCores(SystemClass cls, uint32_t cores) -{ - // cores^0.667 is crude but more realistic than cores^1, and probably not - // far off for the systems that run browsers (most have 2-4 hyperthreaded - // cores). - // - // To do better, we could examine the actual architecture: hyperthreads vs - // real cores, sizes of caches, architecture class. - - return pow(cores, 2.0/3.0); -} - -// Figure out whether we should use tiered compilation or not. -static bool -GetTieringEnabled(uint32_t codeSize) -{ - // If we can reasonably compile in less than 250ms, don't enable tiering. - const uint32_t timeCutoffMs = 250; - -#ifndef JS_64BIT - // If tiering will fill code memory to more than 90%, don't enable it. - const double spaceCutoffPct = 0.9; -#endif - - if (!CanUseExtraThreads()) { - PolicySpew("Tiering disabled : background-work-disabled\n"); - return false; - } - - uint32_t cpuCount = HelperThreadState().cpuCount; - MOZ_ASSERT(cpuCount > 0); - - // TODO: Investigate the multicore-required limitation. "It's always been - // this way" is insufficient justification. - // - // It's mostly sensible not to background compile when there's only one - // hardware thread as we want foreground computation to have access to that, - // but if wasm background compilation helper threads can be given lower - // priority then background compilation on single-core systems still makes - // some kind of sense. - // - // On desktop this is really a non-problem though, as of September 2017 - // 1-core was down to 3.5% of our population and falling. - - if (cpuCount == 1) { - PolicySpew("Tiering disabled : single-core\n"); - return false; - } - - DebugOnly threadCount = HelperThreadState().threadCount; - MOZ_ASSERT(threadCount >= cpuCount); - - // Compute the max number of threads available to do actual background - // compilation work. - // - // TODO: Here we can play around with the threadCount we /need/ rather than - // the threadCount we /have/, and feed the number we need into the - // scheduler. That requires a more sophisticated scheduler, though. - // - // TODO: Here we might also worry about the threadCount that is currently - // available, given what is going on elsewhere in the pipeline. In - // principle maxWasmCompilationThreads can encapsulate that, but it doesn't. - - uint32_t workers = HelperThreadState().maxWasmCompilationThreads(); - - // The number of cores we will use is bounded both by the CPU count and the - // worker count. - - uint32_t cores = Min(cpuCount, workers); - - SystemClass cls = Classify(); - - PolicySpew("Tiering system-info : class %d code-size %u bytecodes-per-ms %g relative-speed %g clock-mhz %u\n", - uint32_t(cls), codeSize, BytecodesPerMs(cls), RelativePerformance(cls), - gSysinfo.maxCpuClockMHz); - - // Ion compilation on available cores must take long enough to be worth the - // bother. Keep it simple and divide estimated ion time by the number of - // cores, don't worry about sequential sections or parallel overhead. - - uint32_t ms = MillisToIonCompileOnThisSystem(cls, codeSize); - - // Sadly, linear speedup is not a reality, so try to get a grip on what - // speedup is realistic on this system. - - double effective_cores = EffectiveCores(cls, cores); - - PolicySpew("Tiering estimation : single-core-ion-est %u num-cores %u effective-cores %g parallel-est %g\n", - ms, cores, effective_cores, ms / effective_cores); - - if ((ms / effective_cores) < timeCutoffMs) { - PolicySpew("Tiering disabled : ion-fast-enough\n"); - return false; - } - - // Do not implement a size cutoff for 64-bit systems since the code size - // budget for 64 bit is so large that it will hardly ever be an issue. - // (Also the cutoff percentage might be different on 64-bit.) - -#ifndef JS_64BIT - // If the amount of executable code for baseline compilation jeopardizes the - // availability of executable memory for ion code then do not tier, for now. - // - // TODO: For now we consider this module in isolation. We should really - // worry about what else is going on in this process and might be filling up - // the code memory. - - double ionRatio = IonBytesPerBytecode(cls); - double baselineRatio = BaselineBytesPerBytecode(cls); - uint64_t needMemory = codeSize * (ionRatio + baselineRatio); - uint64_t availMemory = LikelyAvailableExecutableMemory(); - double cutoff = spaceCutoffPct * MaxCodeBytesPerProcess; - - PolicySpew("Tiering memory-info : code-bytes %u ion-blowup %g baseline-blowup %g need %" PRIu64 - " max %" PRIu64 " avail %" PRIu64 " cutoff %" PRIu64 "\n", - codeSize, ionRatio, baselineRatio, needMemory, uint64_t(MaxCodeBytesPerProcess), - availMemory, uint64_t(cutoff)); - - // If the sum of baseline and ion code makes us exceeds some set percentage - // of the executable memory then disable tiering. - - if ((MaxCodeBytesPerProcess - availMemory) + needMemory > cutoff) { - PolicySpew("Tiering disabled : memory-budget\n"); - return false; - } -#endif - - PolicySpew("Tiering enabled : all-tests-pass\n"); - return true; + return CanUseExtraThreads() && HelperThreadState().cpuCount > 1; } SharedModule @@ -464,52 +118,32 @@ wasm::CompileInitialTier(const ShareableBytes& bytecode, const CompileArgs& args bool debugEnabled = BaselineCanCompile() && args.debugEnabled; bool ionEnabled = args.ionEnabled || !baselineEnabled; - DebugEnabled debug = debugEnabled ? DebugEnabled::True : DebugEnabled::False; + CompileMode mode; + Tier tier; + DebugEnabled debug; + if (BackgroundWorkPossible() && baselineEnabled && ionEnabled && !debugEnabled) { + mode = CompileMode::Tier1; + tier = Tier::Baseline; + debug = DebugEnabled::False; + } else { + mode = CompileMode::Once; + tier = debugEnabled || !ionEnabled ? Tier::Baseline : Tier::Ion; + debug = debugEnabled ? DebugEnabled::True : DebugEnabled::False; + } - ModuleEnvironment env(ModuleEnvironment::UnknownMode, ModuleEnvironment::UnknownTier, debug); + ModuleEnvironment env(mode, tier, debug); Decoder d(bytecode.bytes, error); if (!DecodeModuleEnvironment(d, &env)) return nullptr; - uint32_t codeSize; - if (!d.peekSectionSize(SectionId::Code, &env, "code", &codeSize)) - codeSize = 0; - - CompileMode mode; - Tier tier; - if (baselineEnabled && ionEnabled && !debugEnabled && GetTieringEnabled(codeSize)) { - mode = CompileMode::Tier1; - tier = Tier::Baseline; - } else { - mode = CompileMode::Once; - tier = debugEnabled || !ionEnabled ? Tier::Baseline : Tier::Ion; - } - - env.setModeAndTier(mode, tier); - ModuleGenerator mg(args, &env, nullptr, error); if (!mg.init()) return nullptr; -#ifdef WASM_POLICY_SPEW - uint64_t before = PRMJ_Now(); -#endif - if (!DecodeCodeSection(d, mg, &env)) return nullptr; -#ifdef WASM_POLICY_SPEW - uint64_t after = PRMJ_Now(); - if (mode == CompileMode::Tier1) { - PolicySpew("Tiering tier-1 : baseline-parallel-time %" PRIu64 "\n", (after - before) / PRMJ_USEC_PER_MSEC); - } else { - PolicySpew("Tiering once : %s-parallel-time %" PRIu64 "\n", - tier == Tier::Baseline ? "baseline" : "ion", - (after - before) / PRMJ_USEC_PER_MSEC); - } -#endif - if (!DecodeModuleTail(d, &env)) return nullptr; @@ -532,18 +166,9 @@ wasm::CompileTier2(Module& module, const CompileArgs& args, Atomic* cancel if (!mg.init()) return false; -#ifdef WASM_POLICY_SPEW - uint64_t before = PRMJ_Now(); -#endif - if (!DecodeCodeSection(d, mg, &env)) return false; -#ifdef WASM_POLICY_SPEW - uint64_t after = PRMJ_Now(); - PolicySpew("Tiering tier-2 : ion-background-time %" PRIu64 "\n", (after - before) / PRMJ_USEC_PER_MSEC); -#endif - if (!DecodeModuleTail(d, &env)) return false; diff --git a/js/src/wasm/WasmGenerator.h b/js/src/wasm/WasmGenerator.h index a6a1707612e4..9b83114e2ed8 100644 --- a/js/src/wasm/WasmGenerator.h +++ b/js/src/wasm/WasmGenerator.h @@ -144,10 +144,10 @@ class CompileTask return units_; } Tier tier() const { - return env_.tier(); + return env_.tier; } CompileMode mode() const { - return env_.mode(); + return env_.mode; } bool debugEnabled() const { return env_.debug == DebugEnabled::True; @@ -243,8 +243,8 @@ class MOZ_STACK_CLASS ModuleGenerator MOZ_MUST_USE bool initWasm(); bool isAsmJS() const { return env_->isAsmJS(); } - Tier tier() const { return env_->tier(); } - CompileMode mode() const { return env_->mode(); } + Tier tier() const { return env_->tier; } + CompileMode mode() const { return env_->mode; } bool debugEnabled() const { return env_->debugEnabled(); } public: diff --git a/js/src/wasm/WasmValidate.cpp b/js/src/wasm/WasmValidate.cpp index f08e0b11b6a3..31bb3143c43a 100644 --- a/js/src/wasm/WasmValidate.cpp +++ b/js/src/wasm/WasmValidate.cpp @@ -60,7 +60,7 @@ Decoder::fail(size_t errorOffset, const char* msg) bool Decoder::startSection(SectionId id, ModuleEnvironment* env, uint32_t* sectionStart, - uint32_t* sectionSize, const char* sectionName, bool peeking) + uint32_t* sectionSize, const char* sectionName) { // Record state at beginning of section to allow rewinding to this point // if, after skipping through several custom sections, we don't find the @@ -85,11 +85,8 @@ Decoder::startSection(SectionId id, ModuleEnvironment* env, uint32_t* sectionSta // Rewind to the beginning of the current section since this is what // skipCustomSection() assumes. cur_ = currentSectionStart; - if (!skipCustomSection(env)) { - if (peeking) - goto rewind; + if (!skipCustomSection(env)) return false; - } // Having successfully skipped a custom section, consider the next // section. @@ -100,39 +97,22 @@ Decoder::startSection(SectionId id, ModuleEnvironment* env, uint32_t* sectionSta // Found it, now start the section. - if (!readVarU32(sectionSize) || bytesRemain() < *sectionSize) { - if (peeking) - goto rewind; + if (!readVarU32(sectionSize) || bytesRemain() < *sectionSize) goto fail; - } *sectionStart = cur_ - beg_; - if (peeking) - goto rewind_peeking; return true; rewind: - peeking = false; - rewind_peeking: cur_ = initialCur; env->customSections.shrinkTo(initialCustomSectionsLength); - if (!peeking) - *sectionStart = NotStarted; + *sectionStart = NotStarted; return true; fail: return failf("failed to start %s section", sectionName); } -bool -Decoder::peekSectionSize(SectionId id, ModuleEnvironment* env, const char* sectionName, uint32_t* sectionSize) -{ - uint32_t sectionStart; - if (!startSection(id, env, §ionStart, sectionSize, sectionName, /*peeking=*/true)) - return false; - return sectionStart != NotStarted; -} - bool Decoder::finishSection(uint32_t sectionStart, uint32_t sectionSize, const char* sectionName) { diff --git a/js/src/wasm/WasmValidate.h b/js/src/wasm/WasmValidate.h index 684eddd58a86..48dfeb1004b1 100644 --- a/js/src/wasm/WasmValidate.h +++ b/js/src/wasm/WasmValidate.h @@ -36,14 +36,11 @@ namespace wasm { struct ModuleEnvironment { // Constant parameters for the entire compilation: + const CompileMode mode; + const Tier tier; const DebugEnabled debug; const ModuleKind kind; - // Constant parameters determined no later than at the start of the code - // section: - CompileMode mode_; - Tier tier_; - // Module fields filled out incrementally during decoding: MemoryUsage memoryUsage; Atomic minMemoryLength; @@ -62,35 +59,18 @@ struct ModuleEnvironment NameInBytecodeVector funcNames; CustomSectionVector customSections; - static const CompileMode UnknownMode = (CompileMode)-1; - static const Tier UnknownTier = (Tier)-1; - explicit ModuleEnvironment(CompileMode mode = CompileMode::Once, Tier tier = Tier::Ion, DebugEnabled debug = DebugEnabled::False, ModuleKind kind = ModuleKind::Wasm) - : debug(debug), + : mode(mode), + tier(tier), + debug(debug), kind(kind), - mode_(mode), - tier_(tier), memoryUsage(MemoryUsage::None), minMemoryLength(0) {} - CompileMode mode() const { - MOZ_ASSERT(mode_ != UnknownMode); - return mode_; - } - Tier tier() const { - MOZ_ASSERT(tier_ != UnknownTier); - return tier_; - } - void setModeAndTier(CompileMode mode, Tier tier) { - MOZ_ASSERT(mode_ == UnknownMode); - MOZ_ASSERT(tier_ == UnknownTier); - mode_ = mode; - tier_ = tier; - } size_t numTables() const { return tables.length(); } @@ -566,15 +546,10 @@ class Decoder ModuleEnvironment* env, uint32_t* sectionStart, uint32_t* sectionSize, - const char* sectionName, - bool peeking = false); + const char* sectionName); MOZ_MUST_USE bool finishSection(uint32_t sectionStart, uint32_t sectionSize, const char* sectionName); - MOZ_MUST_USE bool peekSectionSize(SectionId id, - ModuleEnvironment* env, - const char* sectionName, - uint32_t* sectionSize); // Custom sections do not cause validation errors unless the error is in // the section header itself. From ba64ef47170db67fcd2e66e78e63218d2f88cbd7 Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Fri, 22 Sep 2017 13:09:44 +0100 Subject: [PATCH 21/37] Bug 1401804 - Fix IsMarkedBlack check used in gray marking asserts r=sfink --- js/src/gc/Barrier.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/js/src/gc/Barrier.cpp b/js/src/gc/Barrier.cpp index 5a5dfbe9bed0..0c42d16e7117 100644 --- a/js/src/gc/Barrier.cpp +++ b/js/src/gc/Barrier.cpp @@ -33,15 +33,8 @@ RuntimeFromActiveCooperatingThreadIsHeapMajorCollecting(JS::shadow::Zone* shadow bool IsMarkedBlack(JSObject* obj) { - // Note: we assume conservatively that Nursery things will be live. - if (!obj->isTenured()) - return true; - - gc::TenuredCell& tenured = obj->asTenured(); - if (tenured.isMarkedAny() || tenured.arena()->allocatedDuringIncremental) - return true; - - return false; + return obj->isMarkedBlack() || + (obj->isTenured() && obj->asTenured().arena()->allocatedDuringIncremental); } bool From 71a8cbdccfbdac4b9945f46629ed0c3ea171d7be Mon Sep 17 00:00:00 2001 From: Lars T Hansen Date: Thu, 31 Aug 2017 12:24:13 +0200 Subject: [PATCH 22/37] Bug 1380033 - Tiering policy with space proxy. r=luke --HG-- extra : rebase_source : df238cefe35aae6d90e1ad29c8768389a7bdf9a6 extra : amend_source : b7c5abf772eeab5a8f46491c0dc7748b1ad521f2 --- js/src/jit/ProcessExecutableMemory.cpp | 7 + js/src/jit/ProcessExecutableMemory.h | 5 + js/src/wasm/WasmCompile.cpp | 305 +++++++++++++++++++++++-- js/src/wasm/WasmGenerator.h | 8 +- js/src/wasm/WasmValidate.cpp | 28 ++- js/src/wasm/WasmValidate.h | 37 ++- 6 files changed, 360 insertions(+), 30 deletions(-) diff --git a/js/src/jit/ProcessExecutableMemory.cpp b/js/src/jit/ProcessExecutableMemory.cpp index 9224824c9166..5dd04def0522 100644 --- a/js/src/jit/ProcessExecutableMemory.cpp +++ b/js/src/jit/ProcessExecutableMemory.cpp @@ -619,6 +619,13 @@ js::jit::ReleaseProcessExecutableMemory() execMemory.release(); } +size_t +js::jit::LikelyAvailableExecutableMemory() +{ + // Round down available memory to the closest MB. + return MaxCodeBytesPerProcess - AlignBytes(execMemory.bytesAllocated(), 0x100000U); +} + bool js::jit::CanLikelyAllocateMoreExecutableMemory() { diff --git a/js/src/jit/ProcessExecutableMemory.h b/js/src/jit/ProcessExecutableMemory.h index c578becb80e6..26a997168c94 100644 --- a/js/src/jit/ProcessExecutableMemory.h +++ b/js/src/jit/ProcessExecutableMemory.h @@ -50,6 +50,11 @@ extern void DeallocateExecutableMemory(void* addr, size_t bytes); // function. extern bool CanLikelyAllocateMoreExecutableMemory(); +// Returns a rough guess of how much executable memory remains available, +// rounded down to MB limit. Note this can fluctuate as other threads within +// the process allocate executable memory. +extern size_t LikelyAvailableExecutableMemory(); + } // namespace jit } // namespace js diff --git a/js/src/wasm/WasmCompile.cpp b/js/src/wasm/WasmCompile.cpp index 18bce76b9060..0cc473b6f92f 100644 --- a/js/src/wasm/WasmCompile.cpp +++ b/js/src/wasm/WasmCompile.cpp @@ -23,6 +23,7 @@ #include "jsprf.h" +#include "jit/ProcessExecutableMemory.h" #include "wasm/WasmBaselineCompile.h" #include "wasm/WasmBinaryIterator.h" #include "wasm/WasmGenerator.h" @@ -103,10 +104,277 @@ CompileArgs::initFromContext(JSContext* cx, ScriptedCaller&& scriptedCaller) return assumptions.initBuildIdFromContext(cx); } -static bool -BackgroundWorkPossible() +// Classify the current system as one of a set of recognizable classes. This +// really needs to get our tier-1 systems right. +// +// TODO: We don't yet have a good measure of how fast a system is. We +// distinguish between mobile and desktop because these are very different kinds +// of systems, but we could further distinguish between low / medium / high end +// within those major classes. If we do so, then constants below would be +// provided for each (class, architecture, system-tier) combination, not just +// (class, architecture) as now. +// +// CPU clock speed is not by itself a good predictor of system performance, as +// there are high-performance systems with slow clocks (recent Intel) and +// low-performance systems with fast clocks (older AMD). We can also use +// physical memory, core configuration, OS details, CPU class and family, and +// CPU manufacturer to disambiguate. + +enum class SystemClass { - return CanUseExtraThreads() && HelperThreadState().cpuCount > 1; + DesktopX86, + DesktopX64, + DesktopUnknown32, + DesktopUnknown64, + MobileX86, + MobileArm32, + MobileArm64, + MobileUnknown32, + MobileUnknown64 +}; + +static SystemClass +Classify() +{ + bool isDesktop; + +#if defined(ANDROID) || defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) + isDesktop = false; +#else + isDesktop = true; +#endif + + if (isDesktop) { +#if defined(JS_CODEGEN_X64) + return SystemClass::DesktopX64; +#elif defined(JS_CODEGEN_X86) + return SystemClass::DesktopX86; +#elif defined(JS_64BIT) + return SystemClass::DesktopUnknown64; +#else + return SystemClass::DesktopUnknown32; +#endif + } else { +#if defined(JS_CODEGEN_X86) + return SystemClass::MobileX86; +#elif defined(JS_CODEGEN_ARM) + return SystemClass::MobileArm32; +#elif defined(JS_CODEGEN_ARM64) + return SystemClass::MobileArm64; +#elif defined(JS_64BIT) + return SystemClass::MobileUnknown64; +#else + return SystemClass::MobileUnknown32; +#endif + } +} + +#ifndef JS_64BIT + +// Code sizes in machine code bytes per bytecode byte, again empirical except +// where marked as "Guess". + +static const double x64Tox86Inflation = 1.25; + +static const double x64IonBytesPerBytecode = 2.45; +static const double x86IonBytesPerBytecode = x64IonBytesPerBytecode * x64Tox86Inflation; +static const double arm32IonBytesPerBytecode = 3.3; +static const double arm64IonBytesPerBytecode = 3.0; // Guess + +static const double x64BaselineBytesPerBytecode = x64IonBytesPerBytecode * 1.43; +static const double x86BaselineBytesPerBytecode = x64BaselineBytesPerBytecode * x64Tox86Inflation; +static const double arm32BaselineBytesPerBytecode = arm32IonBytesPerBytecode * 1.39; +static const double arm64BaselineBytesPerBytecode = arm64IonBytesPerBytecode * 1.39; // Guess + +static double +IonBytesPerBytecode(SystemClass cls) +{ + switch (cls) { + case SystemClass::DesktopX86: + case SystemClass::MobileX86: + case SystemClass::DesktopUnknown32: + return x86IonBytesPerBytecode; + case SystemClass::DesktopX64: + case SystemClass::DesktopUnknown64: + return x64IonBytesPerBytecode; + case SystemClass::MobileArm32: + case SystemClass::MobileUnknown32: + return arm32IonBytesPerBytecode; + case SystemClass::MobileArm64: + case SystemClass::MobileUnknown64: + return arm64IonBytesPerBytecode; + default: + MOZ_CRASH(); + } +} + +static double +BaselineBytesPerBytecode(SystemClass cls) +{ + switch (cls) { + case SystemClass::DesktopX86: + case SystemClass::MobileX86: + case SystemClass::DesktopUnknown32: + return x86BaselineBytesPerBytecode; + case SystemClass::DesktopX64: + case SystemClass::DesktopUnknown64: + return x64BaselineBytesPerBytecode; + case SystemClass::MobileArm32: + case SystemClass::MobileUnknown32: + return arm32BaselineBytesPerBytecode; + case SystemClass::MobileArm64: + case SystemClass::MobileUnknown64: + return arm64BaselineBytesPerBytecode; + default: + MOZ_CRASH(); + } +} + +#endif // !JS_64BIT + +// If parallel Ion compilation is going to take longer than this, we should tier. + +static const double tierCutoffMs = 250; + +// Compilation rate values are empirical except when noted, the reference +// systems are: +// +// Late-2013 MacBook Pro (2.6GHz quad hyperthreaded Haswell) +// Late-2015 Nexus 5X (1.4GHz quad Cortex-A53 + 1.8GHz dual Cortex-A57) + +static const double x64BytecodesPerMs = 2100; +static const double x86BytecodesPerMs = 1500; +static const double arm32BytecodesPerMs = 450; +static const double arm64BytecodesPerMs = 650; // Guess + +// Tiering cutoff values: if code section sizes are below these values (when +// divided by the effective number of cores) we do not tier, because we guess +// that parallel Ion compilation will be fast enough. + +static const double x64DesktopTierCutoff = x64BytecodesPerMs * tierCutoffMs; +static const double x86DesktopTierCutoff = x86BytecodesPerMs * tierCutoffMs; +static const double x86MobileTierCutoff = x86DesktopTierCutoff / 2; // Guess +static const double arm32MobileTierCutoff = arm32BytecodesPerMs * tierCutoffMs; +static const double arm64MobileTierCutoff = arm64BytecodesPerMs * tierCutoffMs; + +static double +CodesizeCutoff(SystemClass cls, uint32_t codeSize) +{ + switch (cls) { + case SystemClass::DesktopX86: + case SystemClass::DesktopUnknown32: + return x86DesktopTierCutoff; + case SystemClass::DesktopX64: + case SystemClass::DesktopUnknown64: + return x64DesktopTierCutoff; + case SystemClass::MobileX86: + return x86MobileTierCutoff; + case SystemClass::MobileArm32: + case SystemClass::MobileUnknown32: + return arm32MobileTierCutoff; + case SystemClass::MobileArm64: + case SystemClass::MobileUnknown64: + return arm64MobileTierCutoff; + default: + MOZ_CRASH(); + } +} + +// As the number of cores grows the effectiveness of each core dwindles (on the +// systems we care about for SpiderMonkey). +// +// The data are empirical, computed from the observed compilation time of the +// Tanks demo code on a variable number of cores. +// +// The heuristic may fail on NUMA systems where the core count is high but the +// performance increase is nil or negative once the program moves beyond one +// socket. However, few browser users have such systems. + +static double +EffectiveCores(SystemClass cls, uint32_t cores) +{ + if (cores <= 3) + return pow(cores, 0.9); + return pow(cores, 0.75); +} + +#ifndef JS_64BIT +// Don't tier if tiering will fill code memory to more to more than this +// fraction. + +static const double spaceCutoffPct = 0.9; +#endif + +// Figure out whether we should use tiered compilation or not. +static bool +GetTieringEnabled(uint32_t codeSize) +{ + if (!CanUseExtraThreads()) + return false; + + uint32_t cpuCount = HelperThreadState().cpuCount; + MOZ_ASSERT(cpuCount > 0); + + // It's mostly sensible not to background compile when there's only one + // hardware thread as we want foreground computation to have access to that. + // However, if wasm background compilation helper threads can be given lower + // priority then background compilation on single-core systems still makes + // some kind of sense. That said, this is a non-issue: as of September 2017 + // 1-core was down to 3.5% of our population and falling. + + if (cpuCount == 1) + return false; + + MOZ_ASSERT(HelperThreadState().threadCount >= cpuCount); + + // Compute the max number of threads available to do actual background + // compilation work. + + uint32_t workers = HelperThreadState().maxWasmCompilationThreads(); + + // The number of cores we will use is bounded both by the CPU count and the + // worker count. + + uint32_t cores = Min(cpuCount, workers); + + SystemClass cls = Classify(); + + // Ion compilation on available cores must take long enough to be worth the + // bother. + + double cutoffSize = CodesizeCutoff(cls, codeSize); + double effectiveCores = EffectiveCores(cls, cores); + + if ((codeSize / effectiveCores) < cutoffSize) + return false; + + // Do not implement a size cutoff for 64-bit systems since the code size + // budget for 64 bit is so large that it will hardly ever be an issue. + // (Also the cutoff percentage might be different on 64-bit.) + +#ifndef JS_64BIT + // If the amount of executable code for baseline compilation jeopardizes the + // availability of executable memory for ion code then do not tier, for now. + // + // TODO: For now we consider this module in isolation. We should really + // worry about what else is going on in this process and might be filling up + // the code memory. It's like we need some kind of code memory reservation + // system or JIT compilation for large modules. + + double ionRatio = IonBytesPerBytecode(cls); + double baselineRatio = BaselineBytesPerBytecode(cls); + double needMemory = codeSize * (ionRatio + baselineRatio); + double availMemory = LikelyAvailableExecutableMemory(); + double cutoff = spaceCutoffPct * MaxCodeBytesPerProcess; + + // If the sum of baseline and ion code makes us exceeds some set percentage + // of the executable memory then disable tiering. + + if ((MaxCodeBytesPerProcess - availMemory) + needMemory > cutoff) + return false; +#endif + + return true; } SharedModule @@ -118,25 +386,30 @@ wasm::CompileInitialTier(const ShareableBytes& bytecode, const CompileArgs& args bool debugEnabled = BaselineCanCompile() && args.debugEnabled; bool ionEnabled = args.ionEnabled || !baselineEnabled; - CompileMode mode; - Tier tier; - DebugEnabled debug; - if (BackgroundWorkPossible() && baselineEnabled && ionEnabled && !debugEnabled) { - mode = CompileMode::Tier1; - tier = Tier::Baseline; - debug = DebugEnabled::False; - } else { - mode = CompileMode::Once; - tier = debugEnabled || !ionEnabled ? Tier::Baseline : Tier::Ion; - debug = debugEnabled ? DebugEnabled::True : DebugEnabled::False; - } + DebugEnabled debug = debugEnabled ? DebugEnabled::True : DebugEnabled::False; - ModuleEnvironment env(mode, tier, debug); + ModuleEnvironment env(ModuleEnvironment::UnknownMode, ModuleEnvironment::UnknownTier, debug); Decoder d(bytecode.bytes, error); if (!DecodeModuleEnvironment(d, &env)) return nullptr; + uint32_t codeSize; + if (!d.peekSectionSize(SectionId::Code, &env, "code", &codeSize)) + codeSize = 0; + + CompileMode mode; + Tier tier; + if (baselineEnabled && ionEnabled && !debugEnabled && GetTieringEnabled(codeSize)) { + mode = CompileMode::Tier1; + tier = Tier::Baseline; + } else { + mode = CompileMode::Once; + tier = debugEnabled || !ionEnabled ? Tier::Baseline : Tier::Ion; + } + + env.setModeAndTier(mode, tier); + ModuleGenerator mg(args, &env, nullptr, error); if (!mg.init()) return nullptr; diff --git a/js/src/wasm/WasmGenerator.h b/js/src/wasm/WasmGenerator.h index 9b83114e2ed8..a6a1707612e4 100644 --- a/js/src/wasm/WasmGenerator.h +++ b/js/src/wasm/WasmGenerator.h @@ -144,10 +144,10 @@ class CompileTask return units_; } Tier tier() const { - return env_.tier; + return env_.tier(); } CompileMode mode() const { - return env_.mode; + return env_.mode(); } bool debugEnabled() const { return env_.debug == DebugEnabled::True; @@ -243,8 +243,8 @@ class MOZ_STACK_CLASS ModuleGenerator MOZ_MUST_USE bool initWasm(); bool isAsmJS() const { return env_->isAsmJS(); } - Tier tier() const { return env_->tier; } - CompileMode mode() const { return env_->mode; } + Tier tier() const { return env_->tier(); } + CompileMode mode() const { return env_->mode(); } bool debugEnabled() const { return env_->debugEnabled(); } public: diff --git a/js/src/wasm/WasmValidate.cpp b/js/src/wasm/WasmValidate.cpp index 31bb3143c43a..f08e0b11b6a3 100644 --- a/js/src/wasm/WasmValidate.cpp +++ b/js/src/wasm/WasmValidate.cpp @@ -60,7 +60,7 @@ Decoder::fail(size_t errorOffset, const char* msg) bool Decoder::startSection(SectionId id, ModuleEnvironment* env, uint32_t* sectionStart, - uint32_t* sectionSize, const char* sectionName) + uint32_t* sectionSize, const char* sectionName, bool peeking) { // Record state at beginning of section to allow rewinding to this point // if, after skipping through several custom sections, we don't find the @@ -85,8 +85,11 @@ Decoder::startSection(SectionId id, ModuleEnvironment* env, uint32_t* sectionSta // Rewind to the beginning of the current section since this is what // skipCustomSection() assumes. cur_ = currentSectionStart; - if (!skipCustomSection(env)) + if (!skipCustomSection(env)) { + if (peeking) + goto rewind; return false; + } // Having successfully skipped a custom section, consider the next // section. @@ -97,22 +100,39 @@ Decoder::startSection(SectionId id, ModuleEnvironment* env, uint32_t* sectionSta // Found it, now start the section. - if (!readVarU32(sectionSize) || bytesRemain() < *sectionSize) + if (!readVarU32(sectionSize) || bytesRemain() < *sectionSize) { + if (peeking) + goto rewind; goto fail; + } *sectionStart = cur_ - beg_; + if (peeking) + goto rewind_peeking; return true; rewind: + peeking = false; + rewind_peeking: cur_ = initialCur; env->customSections.shrinkTo(initialCustomSectionsLength); - *sectionStart = NotStarted; + if (!peeking) + *sectionStart = NotStarted; return true; fail: return failf("failed to start %s section", sectionName); } +bool +Decoder::peekSectionSize(SectionId id, ModuleEnvironment* env, const char* sectionName, uint32_t* sectionSize) +{ + uint32_t sectionStart; + if (!startSection(id, env, §ionStart, sectionSize, sectionName, /*peeking=*/true)) + return false; + return sectionStart != NotStarted; +} + bool Decoder::finishSection(uint32_t sectionStart, uint32_t sectionSize, const char* sectionName) { diff --git a/js/src/wasm/WasmValidate.h b/js/src/wasm/WasmValidate.h index 48dfeb1004b1..684eddd58a86 100644 --- a/js/src/wasm/WasmValidate.h +++ b/js/src/wasm/WasmValidate.h @@ -36,11 +36,14 @@ namespace wasm { struct ModuleEnvironment { // Constant parameters for the entire compilation: - const CompileMode mode; - const Tier tier; const DebugEnabled debug; const ModuleKind kind; + // Constant parameters determined no later than at the start of the code + // section: + CompileMode mode_; + Tier tier_; + // Module fields filled out incrementally during decoding: MemoryUsage memoryUsage; Atomic minMemoryLength; @@ -59,18 +62,35 @@ struct ModuleEnvironment NameInBytecodeVector funcNames; CustomSectionVector customSections; + static const CompileMode UnknownMode = (CompileMode)-1; + static const Tier UnknownTier = (Tier)-1; + explicit ModuleEnvironment(CompileMode mode = CompileMode::Once, Tier tier = Tier::Ion, DebugEnabled debug = DebugEnabled::False, ModuleKind kind = ModuleKind::Wasm) - : mode(mode), - tier(tier), - debug(debug), + : debug(debug), kind(kind), + mode_(mode), + tier_(tier), memoryUsage(MemoryUsage::None), minMemoryLength(0) {} + CompileMode mode() const { + MOZ_ASSERT(mode_ != UnknownMode); + return mode_; + } + Tier tier() const { + MOZ_ASSERT(tier_ != UnknownTier); + return tier_; + } + void setModeAndTier(CompileMode mode, Tier tier) { + MOZ_ASSERT(mode_ == UnknownMode); + MOZ_ASSERT(tier_ == UnknownTier); + mode_ = mode; + tier_ = tier; + } size_t numTables() const { return tables.length(); } @@ -546,10 +566,15 @@ class Decoder ModuleEnvironment* env, uint32_t* sectionStart, uint32_t* sectionSize, - const char* sectionName); + const char* sectionName, + bool peeking = false); MOZ_MUST_USE bool finishSection(uint32_t sectionStart, uint32_t sectionSize, const char* sectionName); + MOZ_MUST_USE bool peekSectionSize(SectionId id, + ModuleEnvironment* env, + const char* sectionName, + uint32_t* sectionSize); // Custom sections do not cause validation errors unless the error is in // the section header itself. From fd98ed2e4768c7d06adb562d008d9ba6a77584a2 Mon Sep 17 00:00:00 2001 From: Nicolas Silva Date: Fri, 22 Sep 2017 14:51:42 +0200 Subject: [PATCH 23/37] Bug 1383786 - Simplify generating image keys for TextureHosts. r=sotaro --- gfx/layers/composite/GPUVideoTextureHost.cpp | 9 ++---- gfx/layers/composite/GPUVideoTextureHost.h | 3 +- gfx/layers/composite/TextureHost.cpp | 21 ++++-------- gfx/layers/composite/TextureHost.h | 17 +++------- gfx/layers/d3d11/TextureD3D11.cpp | 32 ++++--------------- gfx/layers/d3d11/TextureD3D11.h | 6 +--- .../opengl/MacIOSurfaceTextureHostOGL.cpp | 26 ++++----------- .../opengl/MacIOSurfaceTextureHostOGL.h | 3 +- gfx/layers/wr/AsyncImagePipelineManager.cpp | 5 ++- gfx/layers/wr/WebRenderTextureHost.cpp | 9 ++---- gfx/layers/wr/WebRenderTextureHost.h | 3 +- 11 files changed, 36 insertions(+), 98 deletions(-) diff --git a/gfx/layers/composite/GPUVideoTextureHost.cpp b/gfx/layers/composite/GPUVideoTextureHost.cpp index cdf300bb0120..7a33d05d72ea 100644 --- a/gfx/layers/composite/GPUVideoTextureHost.cpp +++ b/gfx/layers/composite/GPUVideoTextureHost.cpp @@ -111,14 +111,11 @@ GPUVideoTextureHost::CreateRenderTexture(const wr::ExternalImageId& aExternalIma mWrappedTextureHost->CreateRenderTexture(aExternalImageId); } -void -GPUVideoTextureHost::GetWRImageKeys(nsTArray& aImageKeys, - const std::function& aImageKeyAllocator) +uint32_t +GPUVideoTextureHost::NumSubTextures() const { MOZ_ASSERT(mWrappedTextureHost); - MOZ_ASSERT(aImageKeys.IsEmpty()); - - mWrappedTextureHost->GetWRImageKeys(aImageKeys, aImageKeyAllocator); + return mWrappedTextureHost->NumSubTextures(); } void diff --git a/gfx/layers/composite/GPUVideoTextureHost.h b/gfx/layers/composite/GPUVideoTextureHost.h index 4a65e63ca315..bad3dfea4951 100644 --- a/gfx/layers/composite/GPUVideoTextureHost.h +++ b/gfx/layers/composite/GPUVideoTextureHost.h @@ -48,8 +48,7 @@ public: virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override; - virtual void GetWRImageKeys(nsTArray& aImageKeys, - const std::function& aImageKeyAllocator) override; + virtual uint32_t NumSubTextures() const override; virtual void AddWRImage(wr::ResourceUpdateQueue& aResources, Range& aImageKeys, diff --git a/gfx/layers/composite/TextureHost.cpp b/gfx/layers/composite/TextureHost.cpp index 1105837fc23b..e20e74532126 100644 --- a/gfx/layers/composite/TextureHost.cpp +++ b/gfx/layers/composite/TextureHost.cpp @@ -566,23 +566,14 @@ BufferTextureHost::CreateRenderTexture(const wr::ExternalImageId& aExternalImage wr::RenderThread::Get()->RegisterExternalImage(wr::AsUint64(aExternalImageId), texture.forget()); } -void -BufferTextureHost::GetWRImageKeys(nsTArray& aImageKeys, - const std::function& aImageKeyAllocator) +uint32_t +BufferTextureHost::NumSubTextures() const { - MOZ_ASSERT(aImageKeys.IsEmpty()); - - if (GetFormat() != gfx::SurfaceFormat::YUV) { - // 1 image key - aImageKeys.AppendElement(aImageKeyAllocator()); - MOZ_ASSERT(aImageKeys.Length() == 1); - } else { - // 3 image key - aImageKeys.AppendElement(aImageKeyAllocator()); - aImageKeys.AppendElement(aImageKeyAllocator()); - aImageKeys.AppendElement(aImageKeyAllocator()); - MOZ_ASSERT(aImageKeys.Length() == 3); + if (GetFormat() == gfx::SurfaceFormat::YUV) { + return 3; } + + return 1; } void diff --git a/gfx/layers/composite/TextureHost.h b/gfx/layers/composite/TextureHost.h index 7d7d950fd2a4..9bc06766469e 100644 --- a/gfx/layers/composite/TextureHost.h +++ b/gfx/layers/composite/TextureHost.h @@ -621,17 +621,9 @@ public: MOZ_RELEASE_ASSERT(false, "No CreateRenderTexture() implementation for this TextureHost type."); } - // Create all necessary image keys for this textureHost rendering. - // @param aImageKeys - [out] The set of ImageKeys used for this textureHost - // composing. - // @param aImageKeyAllocator - [in] The function which is used for creating - // the new ImageKey. - virtual void GetWRImageKeys(nsTArray& aImageKeys, - const std::function& aImageKeyAllocator) - { - MOZ_ASSERT(aImageKeys.IsEmpty()); - MOZ_ASSERT_UNREACHABLE("No GetWRImageKeys() implementation for this TextureHost type."); - } + /// Returns the number of actual textures that will be used to render this. + /// For example in a lot of YUV cases it will be 3 + virtual uint32_t NumSubTextures() const { return 1; } // Add all necessary TextureHost informations to the resource update queue. // Then, WR will use this informations to read from the TextureHost. @@ -747,8 +739,7 @@ public: virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override; - virtual void GetWRImageKeys(nsTArray& aImageKeys, - const std::function& aImageKeyAllocator) override; + virtual uint32_t NumSubTextures() const override; virtual void AddWRImage(wr::ResourceUpdateQueue& aResources, Range& aImageKeys, diff --git a/gfx/layers/d3d11/TextureD3D11.cpp b/gfx/layers/d3d11/TextureD3D11.cpp index 6f7ee8a4bc1d..8ff7c4cd81c1 100644 --- a/gfx/layers/d3d11/TextureD3D11.cpp +++ b/gfx/layers/d3d11/TextureD3D11.cpp @@ -1042,31 +1042,22 @@ DXGITextureHostD3D11::CreateRenderTexture(const wr::ExternalImageId& aExternalIm wr::RenderThread::Get()->RegisterExternalImage(wr::AsUint64(aExternalImageId), texture.forget()); } -void -DXGITextureHostD3D11::GetWRImageKeys(nsTArray& aImageKeys, - const std::function& aImageKeyAllocator) +uint32_t +DXGITextureHostD3D11::NumSubTextures() const { - MOZ_ASSERT(aImageKeys.IsEmpty()); - switch (GetFormat()) { case gfx::SurfaceFormat::R8G8B8X8: case gfx::SurfaceFormat::R8G8B8A8: case gfx::SurfaceFormat::B8G8R8A8: case gfx::SurfaceFormat::B8G8R8X8: { - // 1 image key - aImageKeys.AppendElement(aImageKeyAllocator()); - MOZ_ASSERT(aImageKeys.Length() == 1); - break; + return 1; } case gfx::SurfaceFormat::NV12: { - // 2 image key - aImageKeys.AppendElement(aImageKeyAllocator()); - aImageKeys.AppendElement(aImageKeyAllocator()); - MOZ_ASSERT(aImageKeys.Length() == 2); - break; + return 2; } default: { - MOZ_ASSERT_UNREACHABLE("unexpected to be called"); + MOZ_ASSERT_UNREACHABLE("unexpected format"); + return 1; } } } @@ -1311,17 +1302,6 @@ DXGIYCbCrTextureHostD3D11::CreateRenderTexture(const wr::ExternalImageId& aExter // We use AddImage() directly. It's no corresponding RenderTextureHost. } -void -DXGIYCbCrTextureHostD3D11::GetWRImageKeys(nsTArray& aImageKeys, - const std::function& aImageKeyAllocator) -{ - MOZ_ASSERT(aImageKeys.IsEmpty()); - - // 1 image key - aImageKeys.AppendElement(aImageKeyAllocator()); - MOZ_ASSERT(aImageKeys.Length() == 1); -} - void DXGIYCbCrTextureHostD3D11::AddWRImage(wr::ResourceUpdateQueue& aResources, Range& aImageKeys, diff --git a/gfx/layers/d3d11/TextureD3D11.h b/gfx/layers/d3d11/TextureD3D11.h index f13ef4ad8e04..ca7fd6355d48 100644 --- a/gfx/layers/d3d11/TextureD3D11.h +++ b/gfx/layers/d3d11/TextureD3D11.h @@ -335,8 +335,7 @@ public: virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override; - virtual void GetWRImageKeys(nsTArray& aImageKeys, - const std::function& aImageKeyAllocator) override; + virtual uint32_t NumSubTextures() const override; virtual void AddWRImage(wr::ResourceUpdateQueue& aAPI, Range& aImageKeys, @@ -398,9 +397,6 @@ public: virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override; - virtual void GetWRImageKeys(nsTArray& aImageKeys, - const std::function& aImageKeyAllocator) override; - virtual void AddWRImage(wr::ResourceUpdateQueue& aResources, Range& aImageKeys, const wr::ExternalImageId& aExtID) override; diff --git a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp index 74bbae005f3b..671d0edb5f16 100644 --- a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp +++ b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp @@ -125,37 +125,23 @@ MacIOSurfaceTextureHostOGL::CreateRenderTexture(const wr::ExternalImageId& aExte wr::RenderThread::Get()->RegisterExternalImage(wr::AsUint64(aExternalImageId), texture.forget()); } -void -MacIOSurfaceTextureHostOGL::GetWRImageKeys(nsTArray& aImageKeys, - const std::function& aImageKeyAllocator) +uint32_t +MacIOSurfaceTextureHostOGL::NumSubTextures() const { - MOZ_ASSERT(aImageKeys.IsEmpty()); - switch (GetFormat()) { case gfx::SurfaceFormat::R8G8B8X8: case gfx::SurfaceFormat::R8G8B8A8: case gfx::SurfaceFormat::B8G8R8A8: case gfx::SurfaceFormat::B8G8R8X8: { - // 1 image key - aImageKeys.AppendElement(aImageKeyAllocator()); - MOZ_ASSERT(aImageKeys.Length() == 1); - break; - } case gfx::SurfaceFormat::YUV422: { - // 1 image key - aImageKeys.AppendElement(aImageKeyAllocator()); - MOZ_ASSERT(aImageKeys.Length() == 1); - break; + return 1; } case gfx::SurfaceFormat::NV12: { - // 2 image key - aImageKeys.AppendElement(aImageKeyAllocator()); - aImageKeys.AppendElement(aImageKeyAllocator()); - MOZ_ASSERT(aImageKeys.Length() == 2); - break; + return 2; } default: { - MOZ_ASSERT_UNREACHABLE("unexpected to be called"); + MOZ_ASSERT_UNREACHABLE("unexpected format"); + return 1; } } } diff --git a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h index 1ecc7e0089e3..9a23106cae31 100644 --- a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h +++ b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h @@ -64,8 +64,7 @@ public: virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override; - virtual void GetWRImageKeys(nsTArray& aImageKeys, - const std::function& aImageKeyAllocator) override; + virtual uint32_t NumSubTextures() const override; virtual void AddWRImage(wr::ResourceUpdateQueue& aResources, Range& aImageKeys, diff --git a/gfx/layers/wr/AsyncImagePipelineManager.cpp b/gfx/layers/wr/AsyncImagePipelineManager.cpp index 79eca3d28e54..f2482c6087af 100644 --- a/gfx/layers/wr/AsyncImagePipelineManager.cpp +++ b/gfx/layers/wr/AsyncImagePipelineManager.cpp @@ -173,7 +173,10 @@ AsyncImagePipelineManager::GenerateImageKeyForTextureHost(wr::ResourceUpdateQueu WebRenderTextureHost* wrTexture = aTexture->AsWebRenderTextureHost(); if (!gfxEnv::EnableWebRenderRecording() && wrTexture) { - wrTexture->GetWRImageKeys(aKeys, std::bind(&AsyncImagePipelineManager::GenerateImageKey, this)); + auto numKeys = wrTexture->NumSubTextures(); + for (uint32_t i = 0; i < numKeys; ++i) { + aKeys.AppendElement(GenerateImageKey()); + } MOZ_ASSERT(!aKeys.IsEmpty()); Range keys(&aKeys[0], aKeys.Length()); wrTexture->AddWRImage(aResources, keys, wrTexture->GetExternalImageKey()); diff --git a/gfx/layers/wr/WebRenderTextureHost.cpp b/gfx/layers/wr/WebRenderTextureHost.cpp index 78f479a4d75d..ec50a3bbfdcc 100644 --- a/gfx/layers/wr/WebRenderTextureHost.cpp +++ b/gfx/layers/wr/WebRenderTextureHost.cpp @@ -134,14 +134,11 @@ WebRenderTextureHost::GetRGBStride() return ImageDataSerializer::ComputeRGBStride(format, GetSize().width); } -void -WebRenderTextureHost::GetWRImageKeys(nsTArray& aImageKeys, - const std::function& aImageKeyAllocator) +uint32_t +WebRenderTextureHost::NumSubTextures() const { MOZ_ASSERT(mWrappedTextureHost); - MOZ_ASSERT(aImageKeys.IsEmpty()); - - mWrappedTextureHost->GetWRImageKeys(aImageKeys, aImageKeyAllocator); + return mWrappedTextureHost->NumSubTextures(); } void diff --git a/gfx/layers/wr/WebRenderTextureHost.h b/gfx/layers/wr/WebRenderTextureHost.h index 5f235c7675d6..ea92aec83165 100644 --- a/gfx/layers/wr/WebRenderTextureHost.h +++ b/gfx/layers/wr/WebRenderTextureHost.h @@ -63,8 +63,7 @@ public: int32_t GetRGBStride(); - virtual void GetWRImageKeys(nsTArray& aImageKeys, - const std::function& aImageKeyAllocator) override; + virtual uint32_t NumSubTextures() const override; virtual void AddWRImage(wr::ResourceUpdateQueue& aResources, Range& aImageKeys, From 782273998131e16ca4795de005a1fc4b3041570b Mon Sep 17 00:00:00 2001 From: Nicolas Silva Date: Fri, 22 Sep 2017 14:51:46 +0200 Subject: [PATCH 24/37] Bug 1383786 - Make it possible to update TextureHost image keys. r=sotaro --- gfx/layers/composite/GPUVideoTextureHost.cpp | 10 ++--- gfx/layers/composite/GPUVideoTextureHost.h | 7 ++-- gfx/layers/composite/TextureHost.cpp | 31 ++++++-------- gfx/layers/composite/TextureHost.h | 22 ++++++---- gfx/layers/d3d11/TextureD3D11.cpp | 41 +++++++++---------- gfx/layers/d3d11/TextureD3D11.h | 14 ++++--- .../opengl/MacIOSurfaceTextureHostOGL.cpp | 35 ++++++---------- .../opengl/MacIOSurfaceTextureHostOGL.h | 7 ++-- gfx/layers/wr/AsyncImagePipelineManager.cpp | 5 ++- gfx/layers/wr/WebRenderBridgeParent.cpp | 5 ++- gfx/layers/wr/WebRenderTextureHost.cpp | 9 ++-- gfx/layers/wr/WebRenderTextureHost.h | 7 ++-- 12 files changed, 93 insertions(+), 100 deletions(-) diff --git a/gfx/layers/composite/GPUVideoTextureHost.cpp b/gfx/layers/composite/GPUVideoTextureHost.cpp index 7a33d05d72ea..252fa46349cf 100644 --- a/gfx/layers/composite/GPUVideoTextureHost.cpp +++ b/gfx/layers/composite/GPUVideoTextureHost.cpp @@ -119,13 +119,13 @@ GPUVideoTextureHost::NumSubTextures() const } void -GPUVideoTextureHost::AddWRImage(wr::ResourceUpdateQueue& aResources, - Range& aImageKeys, - const wr::ExternalImageId& aExtID) +GPUVideoTextureHost::PushResourceUpdates(wr::ResourceUpdateQueue& aResources, + ResourceUpdateOp aOp, + const Range& aImageKeys, + const wr::ExternalImageId& aExtID) { MOZ_ASSERT(mWrappedTextureHost); - - mWrappedTextureHost->AddWRImage(aResources, aImageKeys, aExtID); + mWrappedTextureHost->PushResourceUpdates(aResources, aOp, aImageKeys, aExtID); } void diff --git a/gfx/layers/composite/GPUVideoTextureHost.h b/gfx/layers/composite/GPUVideoTextureHost.h index bad3dfea4951..aabccc33a063 100644 --- a/gfx/layers/composite/GPUVideoTextureHost.h +++ b/gfx/layers/composite/GPUVideoTextureHost.h @@ -50,9 +50,10 @@ public: virtual uint32_t NumSubTextures() const override; - virtual void AddWRImage(wr::ResourceUpdateQueue& aResources, - Range& aImageKeys, - const wr::ExternalImageId& aExtID) override; + virtual void PushResourceUpdates(wr::ResourceUpdateQueue& aResources, + ResourceUpdateOp aOp, + const Range& aImageKeys, + const wr::ExternalImageId& aExtID) override; virtual void PushExternalImage(wr::DisplayListBuilder& aBuilder, const wr::LayoutRect& aBounds, diff --git a/gfx/layers/composite/TextureHost.cpp b/gfx/layers/composite/TextureHost.cpp index e20e74532126..bb4f34b9bb5e 100644 --- a/gfx/layers/composite/TextureHost.cpp +++ b/gfx/layers/composite/TextureHost.cpp @@ -577,38 +577,31 @@ BufferTextureHost::NumSubTextures() const } void -BufferTextureHost::AddWRImage(wr::ResourceUpdateQueue& aResources, - Range& aImageKeys, - const wr::ExternalImageId& aExtID) +BufferTextureHost::PushResourceUpdates(wr::ResourceUpdateQueue& aResources, + ResourceUpdateOp aOp, + const Range& aImageKeys, + const wr::ExternalImageId& aExtID) { + auto method = aOp == TextureHost::ADD_IMAGE ? &wr::ResourceUpdateQueue::AddExternalImage + : &wr::ResourceUpdateQueue::UpdateExternalImage; + auto bufferType = wr::WrExternalImageBufferType::ExternalBuffer; + if (GetFormat() != gfx::SurfaceFormat::YUV) { MOZ_ASSERT(aImageKeys.length() == 1); wr::ImageDescriptor descriptor(GetSize(), ImageDataSerializer::ComputeRGBStride(GetFormat(), GetSize().width), GetFormat()); - aResources.AddExternalImageBuffer(aImageKeys[0], descriptor, aExtID); + (aResources.*method)(aImageKeys[0], descriptor, aExtID, bufferType, 0); } else { MOZ_ASSERT(aImageKeys.length() == 3); const layers::YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor(); wr::ImageDescriptor yDescriptor(desc.ySize(), desc.ySize().width, gfx::SurfaceFormat::A8); wr::ImageDescriptor cbcrDescriptor(desc.cbCrSize(), desc.cbCrSize().width, gfx::SurfaceFormat::A8); - aResources.AddExternalImage(aImageKeys[0], - yDescriptor, - aExtID, - wr::WrExternalImageBufferType::ExternalBuffer, - 0); - aResources.AddExternalImage(aImageKeys[1], - cbcrDescriptor, - aExtID, - wr::WrExternalImageBufferType::ExternalBuffer, - 1); - aResources.AddExternalImage(aImageKeys[2], - cbcrDescriptor, - aExtID, - wr::WrExternalImageBufferType::ExternalBuffer, - 2); + (aResources.*method)(aImageKeys[0], yDescriptor, aExtID, bufferType, 0); + (aResources.*method)(aImageKeys[1], cbcrDescriptor, aExtID, bufferType, 1); + (aResources.*method)(aImageKeys[2], cbcrDescriptor, aExtID, bufferType, 2); } } diff --git a/gfx/layers/composite/TextureHost.h b/gfx/layers/composite/TextureHost.h index 9bc06766469e..76f3ef64231a 100644 --- a/gfx/layers/composite/TextureHost.h +++ b/gfx/layers/composite/TextureHost.h @@ -625,13 +625,18 @@ public: /// For example in a lot of YUV cases it will be 3 virtual uint32_t NumSubTextures() const { return 1; } + enum ResourceUpdateOp { + ADD_IMAGE, + UPDATE_IMAGE, + }; + // Add all necessary TextureHost informations to the resource update queue. - // Then, WR will use this informations to read from the TextureHost. - virtual void AddWRImage(wr::ResourceUpdateQueue& aResources, - Range& aImageKeys, - const wr::ExternalImageId& aExtID) + virtual void PushResourceUpdates(wr::ResourceUpdateQueue& aResources, + ResourceUpdateOp aOp, + const Range& aImageKeys, + const wr::ExternalImageId& aExtID) { - MOZ_ASSERT_UNREACHABLE("No AddWRImage() implementation for this TextureHost type."); + MOZ_ASSERT_UNREACHABLE("Unimplemented"); } // Put all necessary WR commands into DisplayListBuilder for this textureHost rendering. @@ -741,9 +746,10 @@ public: virtual uint32_t NumSubTextures() const override; - virtual void AddWRImage(wr::ResourceUpdateQueue& aResources, - Range& aImageKeys, - const wr::ExternalImageId& aExtID) override; + virtual void PushResourceUpdates(wr::ResourceUpdateQueue& aResources, + ResourceUpdateOp aOp, + const Range& aImageKeys, + const wr::ExternalImageId& aExtID) override; virtual void PushExternalImage(wr::DisplayListBuilder& aBuilder, const wr::LayoutRect& aBounds, diff --git a/gfx/layers/d3d11/TextureD3D11.cpp b/gfx/layers/d3d11/TextureD3D11.cpp index 8ff7c4cd81c1..d82a8da37f7c 100644 --- a/gfx/layers/d3d11/TextureD3D11.cpp +++ b/gfx/layers/d3d11/TextureD3D11.cpp @@ -1063,11 +1063,15 @@ DXGITextureHostD3D11::NumSubTextures() const } void -DXGITextureHostD3D11::AddWRImage(wr::ResourceUpdateQueue& aResources, - Range& aImageKeys, - const wr::ExternalImageId& aExtID) +DXGITextureHostD3D11::PushResourceUpdates(wr::ResourceUpdateQueue& aResources, + ResourceUpdateOp aOp, + const Range& aImageKeys, + const wr::ExternalImageId& aExtID) override; { MOZ_ASSERT(mHandle); + auto method = aOp == TextureHost::ADD_IMAGE ? &wr::ResourceUpdateQueue::AddExternalImage + : &wr::ResourceUpdateQueue::UpdateExternalImage; + auto bufferType = wr::WrExternalImageBufferType::TextureExternalHandle; switch (mFormat) { case gfx::SurfaceFormat::R8G8B8X8: @@ -1077,11 +1081,7 @@ DXGITextureHostD3D11::AddWRImage(wr::ResourceUpdateQueue& aResources, MOZ_ASSERT(aImageKeys.length() == 1); wr::ImageDescriptor descriptor(GetSize(), GetFormat()); - aResources.AddExternalImage(aImageKeys[0], - descriptor, - aExtID, - wr::WrExternalImageBufferType::Texture2DHandle, - 0); + (aResources.*method)(aImageKeys[0], descriptor, aExtID, bufferType, 0); break; } case gfx::SurfaceFormat::NV12: { @@ -1089,16 +1089,8 @@ DXGITextureHostD3D11::AddWRImage(wr::ResourceUpdateQueue& aResources, wr::ImageDescriptor descriptor0(GetSize(), gfx::SurfaceFormat::A8); wr::ImageDescriptor descriptor1(GetSize() / 2, gfx::SurfaceFormat::R8G8); - aResources.AddExternalImage(aImageKeys[0], - descriptor0, - aExtID, - wr::WrExternalImageBufferType::TextureExternalHandle, - 0); - aResources.AddExternalImage(aImageKeys[1], - descriptor1, - aExtID, - wr::WrExternalImageBufferType::TextureExternalHandle, - 1); + (aResources.*method)(aImageKeys[0], descriptor0, aExtID, bufferType, 0); + (aResources.*method)(aImageKeys[1], descriptor1, aExtID, bufferType, 1); break; } default: { @@ -1303,9 +1295,10 @@ DXGIYCbCrTextureHostD3D11::CreateRenderTexture(const wr::ExternalImageId& aExter } void -DXGIYCbCrTextureHostD3D11::AddWRImage(wr::ResourceUpdateQueue& aResources, - Range& aImageKeys, - const wr::ExternalImageId& aExtID) +DXGIYCbCrTextureHostD3D11::PushResourceUpdates(wr::ResourceUpdateQueue& aResources, + ResourceUpdateOp aOp, + const Range& aImageKeys, + const wr::ExternalImageId& aExtID) override; { // TODO - This implementation is very slow (read-back, copy on the copy and re-upload). @@ -1331,7 +1324,11 @@ DXGIYCbCrTextureHostD3D11::AddWRImage(wr::ResourceUpdateQueue& aResources, wr::ImageDescriptor descriptor(size, map.mStride, dataSourceSurface->GetFormat()); wr::Vec_u8 imgBytes; imgBytes.PushBytes(Range(map.mData, size.height * map.mStride)); - aResources.AddImage(aImageKeys[0], descriptor, imgBytes); + if (aOp == TextureHost::ADD_IMAGE) { + aResources.AddImage(aImageKeys[0], descriptor, imgBytes); + } else { + aResource.UpdateImage(aImageKeys[0], descriptor, imgBytes); + } dataSourceSurface->Unmap(); } diff --git a/gfx/layers/d3d11/TextureD3D11.h b/gfx/layers/d3d11/TextureD3D11.h index ca7fd6355d48..3d4b3b3d9826 100644 --- a/gfx/layers/d3d11/TextureD3D11.h +++ b/gfx/layers/d3d11/TextureD3D11.h @@ -337,9 +337,10 @@ public: virtual uint32_t NumSubTextures() const override; - virtual void AddWRImage(wr::ResourceUpdateQueue& aAPI, - Range& aImageKeys, - const wr::ExternalImageId& aExtID) override; + virtual void PushResourceUpdates(wr::ResourceUpdateQueue& aResources, + ResourceUpdateOp aOp, + const Range& aImageKeys, + const wr::ExternalImageId& aExtID) override; virtual void PushExternalImage(wr::DisplayListBuilder& aBuilder, const wr::LayoutRect& aBounds, @@ -397,9 +398,10 @@ public: virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override; - virtual void AddWRImage(wr::ResourceUpdateQueue& aResources, - Range& aImageKeys, - const wr::ExternalImageId& aExtID) override; + virtual void PushResourceUpdates(wr::ResourceUpdateQueue& aResources, + ResourceUpdateOp aOp, + const Range& aImageKeys, + const wr::ExternalImageId& aExtID) override; virtual void PushExternalImage(wr::DisplayListBuilder& aBuilder, const wr::LayoutRect& aBounds, diff --git a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp index 671d0edb5f16..aa01f897837f 100644 --- a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp +++ b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp @@ -147,12 +147,17 @@ MacIOSurfaceTextureHostOGL::NumSubTextures() const } void -MacIOSurfaceTextureHostOGL::AddWRImage(wr::ResourceUpdateQueue& aResources, - Range& aImageKeys, - const wr::ExternalImageId& aExtID) +MacIOSurfaceTextureHostOGL::PushResourceUpdates(wr::ResourceUpdateQueue& aResources, + ResourceUpdateOp aOp, + const Range& aImageKeys, + const wr::ExternalImageId& aExtID) override; { MOZ_ASSERT(mSurface); + auto method = aOp == TextureHost::ADD_IMAGE ? &wr::ResourceUpdateQueue::AddExternalImage + : &wr::ResourceUpdateQueue::UpdateExternalImage; + auto bufferType = wr::WrExternalImageBufferType::TextureRectHandle; + switch (GetFormat()) { case gfx::SurfaceFormat::R8G8B8X8: case gfx::SurfaceFormat::R8G8B8A8: @@ -161,11 +166,7 @@ MacIOSurfaceTextureHostOGL::AddWRImage(wr::ResourceUpdateQueue& aResources, MOZ_ASSERT(aImageKeys.length() == 1); MOZ_ASSERT(mSurface->GetPlaneCount() == 0); wr::ImageDescriptor descriptor(GetSize(), GetFormat()); - aResources.AddExternalImage(aImageKeys[0], - descriptor, - aExtID, - wr::WrExternalImageBufferType::TextureRectHandle, - 0); + (aResources.*method)(aImageKeys[0], descriptor, aExtID, bufferType, 0); break; } case gfx::SurfaceFormat::YUV422: { @@ -176,11 +177,7 @@ MacIOSurfaceTextureHostOGL::AddWRImage(wr::ResourceUpdateQueue& aResources, MOZ_ASSERT(aImageKeys.length() == 1); MOZ_ASSERT(mSurface->GetPlaneCount() == 0); wr::ImageDescriptor descriptor(GetSize(), gfx::SurfaceFormat::R8G8B8X8); - aResources.AddExternalImage(aImageKeys[0], - descriptor, - aExtID, - wr::WrExternalImageBufferType::TextureRectHandle, - 0); + (aResources.*method)(aImageKeys[0], descriptor, aExtID, bufferType, 0); break; } case gfx::SurfaceFormat::NV12: { @@ -190,16 +187,8 @@ MacIOSurfaceTextureHostOGL::AddWRImage(wr::ResourceUpdateQueue& aResources, gfx::SurfaceFormat::A8); wr::ImageDescriptor descriptor1(gfx::IntSize(mSurface->GetDevicePixelWidth(1), mSurface->GetDevicePixelHeight(1)), gfx::SurfaceFormat::R8G8); - aResources.AddExternalImage(aImageKeys[0], - descriptor0, - aExtID, - wr::WrExternalImageBufferType::TextureRectHandle, - 0); - aResources.AddExternalImage(aImageKeys[1], - descriptor1, - aExtID, - wr::WrExternalImageBufferType::TextureRectHandle, - 1); + (aResources.*method)(aImageKeys[0], descriptor0, aExtID, bufferType, 0); + (aResources.*method)(aImageKeys[1], descriptor1, aExtID, bufferType, 1); break; } default: { diff --git a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h index 9a23106cae31..8254fe25b2ae 100644 --- a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h +++ b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h @@ -66,9 +66,10 @@ public: virtual uint32_t NumSubTextures() const override; - virtual void AddWRImage(wr::ResourceUpdateQueue& aResources, - Range& aImageKeys, - const wr::ExternalImageId& aExtID) override; + virtual void PushResourceUpdates(wr::ResourceUpdateQueue& aResources, + ResourceUpdateOp aOp, + const Range& aImageKeys, + const wr::ExternalImageId& aExtID) override; virtual void PushExternalImage(wr::DisplayListBuilder& aBuilder, const wr::LayoutRect& aBounds, diff --git a/gfx/layers/wr/AsyncImagePipelineManager.cpp b/gfx/layers/wr/AsyncImagePipelineManager.cpp index f2482c6087af..6f2cca32ab44 100644 --- a/gfx/layers/wr/AsyncImagePipelineManager.cpp +++ b/gfx/layers/wr/AsyncImagePipelineManager.cpp @@ -178,8 +178,9 @@ AsyncImagePipelineManager::GenerateImageKeyForTextureHost(wr::ResourceUpdateQueu aKeys.AppendElement(GenerateImageKey()); } MOZ_ASSERT(!aKeys.IsEmpty()); - Range keys(&aKeys[0], aKeys.Length()); - wrTexture->AddWRImage(aResources, keys, wrTexture->GetExternalImageKey()); + Range keys(&aKeys[0], aKeys.Length()); + wrTexture->PushResourceUpdates(aResources, TextureHost::ADD_IMAGE, + keys, wrTexture->GetExternalImageKey()); return true; } else { RefPtr dSurf = aTexture->GetAsSurface(); diff --git a/gfx/layers/wr/WebRenderBridgeParent.cpp b/gfx/layers/wr/WebRenderBridgeParent.cpp index a516521285a6..044018d5c842 100644 --- a/gfx/layers/wr/WebRenderBridgeParent.cpp +++ b/gfx/layers/wr/WebRenderBridgeParent.cpp @@ -329,7 +329,7 @@ bool WebRenderBridgeParent::AddExternalImage(wr::ExternalImageId aExtId, wr::ImageKey aKey, wr::ResourceUpdateQueue& aResources) { - Range keys(&aKey, 1); + Range keys(&aKey, 1); // Check if key is obsoleted. if (keys[0].mNamespace != mIdNamespace) { return true; @@ -349,7 +349,8 @@ WebRenderBridgeParent::AddExternalImage(wr::ExternalImageId aExtId, wr::ImageKey } WebRenderTextureHost* wrTexture = texture->AsWebRenderTextureHost(); if (wrTexture) { - wrTexture->AddWRImage(aResources, keys, wrTexture->GetExternalImageKey()); + wrTexture->PushResourceUpdates(aResources, TextureHost::ADD_IMAGE, keys, + wrTexture->GetExternalImageKey()); return true; } } diff --git a/gfx/layers/wr/WebRenderTextureHost.cpp b/gfx/layers/wr/WebRenderTextureHost.cpp index ec50a3bbfdcc..0425eb34a8e2 100644 --- a/gfx/layers/wr/WebRenderTextureHost.cpp +++ b/gfx/layers/wr/WebRenderTextureHost.cpp @@ -142,14 +142,15 @@ WebRenderTextureHost::NumSubTextures() const } void -WebRenderTextureHost::AddWRImage(wr::ResourceUpdateQueue& aResources, - Range& aImageKeys, - const wr::ExternalImageId& aExtID) +WebRenderTextureHost::PushResourceUpdates(wr::ResourceUpdateQueue& aResources, + ResourceUpdateOp aOp, + const Range& aImageKeys, + const wr::ExternalImageId& aExtID) { MOZ_ASSERT(mWrappedTextureHost); MOZ_ASSERT(mExternalImageId == aExtID); - mWrappedTextureHost->AddWRImage(aResources, aImageKeys, aExtID); + mWrappedTextureHost->PushResourceUpdates(aResources, aOp, aImageKeys, aExtID); } void diff --git a/gfx/layers/wr/WebRenderTextureHost.h b/gfx/layers/wr/WebRenderTextureHost.h index ea92aec83165..f9af8696f657 100644 --- a/gfx/layers/wr/WebRenderTextureHost.h +++ b/gfx/layers/wr/WebRenderTextureHost.h @@ -65,9 +65,10 @@ public: virtual uint32_t NumSubTextures() const override; - virtual void AddWRImage(wr::ResourceUpdateQueue& aResources, - Range& aImageKeys, - const wr::ExternalImageId& aExtID) override; + virtual void PushResourceUpdates(wr::ResourceUpdateQueue& aResources, + ResourceUpdateOp aOp, + const Range& aImageKeys, + const wr::ExternalImageId& aExtID) override; virtual void PushExternalImage(wr::DisplayListBuilder& aBuilder, const wr::LayoutRect& aBounds, From 3dcc626dd10c4fd743034fb1bcbec6e53a855a5a Mon Sep 17 00:00:00 2001 From: Paul Adenot Date: Tue, 19 Sep 2017 15:18:17 +0200 Subject: [PATCH 25/37] Bug 1400912 - Don't keep references to stack variables in camera child code. r=jib MozReview-Commit-ID: 8FbUFdkcVtx --HG-- extra : rebase_source : c7d9f0d9b786d4a1941d6bb0ceffa9030685432d extra : source : c2b8b044c915434077caddd9d1322bd8353336d9 --- dom/media/systemservices/CamerasChild.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dom/media/systemservices/CamerasChild.cpp b/dom/media/systemservices/CamerasChild.cpp index 18f92356b911..f7ded4636fa5 100644 --- a/dom/media/systemservices/CamerasChild.cpp +++ b/dom/media/systemservices/CamerasChild.cpp @@ -256,8 +256,8 @@ private: MonitorAutoLock mReplyLock; MutexAutoLock mRequestLock; bool mSuccess; - const T& mFailureValue; - const T& mSuccessValue; + const T mFailureValue; + const T mSuccessValue; }; bool From fa3031e45f2726bc5f5e885592d32df9f4a26a4c Mon Sep 17 00:00:00 2001 From: Sebastian Hengst Date: Fri, 22 Sep 2017 16:21:46 +0200 Subject: [PATCH 26/37] Backed out changeset 6b52ab7a62ed (bug 1400912) for mda failures, e.g. in dom/media/tests/mochitest/test_peerConnection_addSecondVideoStreamNoBundle.html and media related mochitest failures. r=backout on a CLOSED TREE --- dom/media/systemservices/CamerasChild.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dom/media/systemservices/CamerasChild.cpp b/dom/media/systemservices/CamerasChild.cpp index f7ded4636fa5..18f92356b911 100644 --- a/dom/media/systemservices/CamerasChild.cpp +++ b/dom/media/systemservices/CamerasChild.cpp @@ -256,8 +256,8 @@ private: MonitorAutoLock mReplyLock; MutexAutoLock mRequestLock; bool mSuccess; - const T mFailureValue; - const T mSuccessValue; + const T& mFailureValue; + const T& mSuccessValue; }; bool From c2765f570f7f0fc07e692d4e2dc1c6bcbf34e9b2 Mon Sep 17 00:00:00 2001 From: Sebastian Hengst Date: Fri, 22 Sep 2017 16:22:40 +0200 Subject: [PATCH 27/37] Backed out changeset fa524e77ef3e (bug 1383786) --- gfx/layers/composite/GPUVideoTextureHost.cpp | 10 ++--- gfx/layers/composite/GPUVideoTextureHost.h | 7 ++-- gfx/layers/composite/TextureHost.cpp | 31 ++++++++------ gfx/layers/composite/TextureHost.h | 22 ++++------ gfx/layers/d3d11/TextureD3D11.cpp | 41 ++++++++++--------- gfx/layers/d3d11/TextureD3D11.h | 14 +++---- .../opengl/MacIOSurfaceTextureHostOGL.cpp | 35 ++++++++++------ .../opengl/MacIOSurfaceTextureHostOGL.h | 7 ++-- gfx/layers/wr/AsyncImagePipelineManager.cpp | 5 +-- gfx/layers/wr/WebRenderBridgeParent.cpp | 5 +-- gfx/layers/wr/WebRenderTextureHost.cpp | 9 ++-- gfx/layers/wr/WebRenderTextureHost.h | 7 ++-- 12 files changed, 100 insertions(+), 93 deletions(-) diff --git a/gfx/layers/composite/GPUVideoTextureHost.cpp b/gfx/layers/composite/GPUVideoTextureHost.cpp index 252fa46349cf..7a33d05d72ea 100644 --- a/gfx/layers/composite/GPUVideoTextureHost.cpp +++ b/gfx/layers/composite/GPUVideoTextureHost.cpp @@ -119,13 +119,13 @@ GPUVideoTextureHost::NumSubTextures() const } void -GPUVideoTextureHost::PushResourceUpdates(wr::ResourceUpdateQueue& aResources, - ResourceUpdateOp aOp, - const Range& aImageKeys, - const wr::ExternalImageId& aExtID) +GPUVideoTextureHost::AddWRImage(wr::ResourceUpdateQueue& aResources, + Range& aImageKeys, + const wr::ExternalImageId& aExtID) { MOZ_ASSERT(mWrappedTextureHost); - mWrappedTextureHost->PushResourceUpdates(aResources, aOp, aImageKeys, aExtID); + + mWrappedTextureHost->AddWRImage(aResources, aImageKeys, aExtID); } void diff --git a/gfx/layers/composite/GPUVideoTextureHost.h b/gfx/layers/composite/GPUVideoTextureHost.h index aabccc33a063..bad3dfea4951 100644 --- a/gfx/layers/composite/GPUVideoTextureHost.h +++ b/gfx/layers/composite/GPUVideoTextureHost.h @@ -50,10 +50,9 @@ public: virtual uint32_t NumSubTextures() const override; - virtual void PushResourceUpdates(wr::ResourceUpdateQueue& aResources, - ResourceUpdateOp aOp, - const Range& aImageKeys, - const wr::ExternalImageId& aExtID) override; + virtual void AddWRImage(wr::ResourceUpdateQueue& aResources, + Range& aImageKeys, + const wr::ExternalImageId& aExtID) override; virtual void PushExternalImage(wr::DisplayListBuilder& aBuilder, const wr::LayoutRect& aBounds, diff --git a/gfx/layers/composite/TextureHost.cpp b/gfx/layers/composite/TextureHost.cpp index bb4f34b9bb5e..e20e74532126 100644 --- a/gfx/layers/composite/TextureHost.cpp +++ b/gfx/layers/composite/TextureHost.cpp @@ -577,31 +577,38 @@ BufferTextureHost::NumSubTextures() const } void -BufferTextureHost::PushResourceUpdates(wr::ResourceUpdateQueue& aResources, - ResourceUpdateOp aOp, - const Range& aImageKeys, - const wr::ExternalImageId& aExtID) +BufferTextureHost::AddWRImage(wr::ResourceUpdateQueue& aResources, + Range& aImageKeys, + const wr::ExternalImageId& aExtID) { - auto method = aOp == TextureHost::ADD_IMAGE ? &wr::ResourceUpdateQueue::AddExternalImage - : &wr::ResourceUpdateQueue::UpdateExternalImage; - auto bufferType = wr::WrExternalImageBufferType::ExternalBuffer; - if (GetFormat() != gfx::SurfaceFormat::YUV) { MOZ_ASSERT(aImageKeys.length() == 1); wr::ImageDescriptor descriptor(GetSize(), ImageDataSerializer::ComputeRGBStride(GetFormat(), GetSize().width), GetFormat()); - (aResources.*method)(aImageKeys[0], descriptor, aExtID, bufferType, 0); + aResources.AddExternalImageBuffer(aImageKeys[0], descriptor, aExtID); } else { MOZ_ASSERT(aImageKeys.length() == 3); const layers::YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor(); wr::ImageDescriptor yDescriptor(desc.ySize(), desc.ySize().width, gfx::SurfaceFormat::A8); wr::ImageDescriptor cbcrDescriptor(desc.cbCrSize(), desc.cbCrSize().width, gfx::SurfaceFormat::A8); - (aResources.*method)(aImageKeys[0], yDescriptor, aExtID, bufferType, 0); - (aResources.*method)(aImageKeys[1], cbcrDescriptor, aExtID, bufferType, 1); - (aResources.*method)(aImageKeys[2], cbcrDescriptor, aExtID, bufferType, 2); + aResources.AddExternalImage(aImageKeys[0], + yDescriptor, + aExtID, + wr::WrExternalImageBufferType::ExternalBuffer, + 0); + aResources.AddExternalImage(aImageKeys[1], + cbcrDescriptor, + aExtID, + wr::WrExternalImageBufferType::ExternalBuffer, + 1); + aResources.AddExternalImage(aImageKeys[2], + cbcrDescriptor, + aExtID, + wr::WrExternalImageBufferType::ExternalBuffer, + 2); } } diff --git a/gfx/layers/composite/TextureHost.h b/gfx/layers/composite/TextureHost.h index 76f3ef64231a..9bc06766469e 100644 --- a/gfx/layers/composite/TextureHost.h +++ b/gfx/layers/composite/TextureHost.h @@ -625,18 +625,13 @@ public: /// For example in a lot of YUV cases it will be 3 virtual uint32_t NumSubTextures() const { return 1; } - enum ResourceUpdateOp { - ADD_IMAGE, - UPDATE_IMAGE, - }; - // Add all necessary TextureHost informations to the resource update queue. - virtual void PushResourceUpdates(wr::ResourceUpdateQueue& aResources, - ResourceUpdateOp aOp, - const Range& aImageKeys, - const wr::ExternalImageId& aExtID) + // Then, WR will use this informations to read from the TextureHost. + virtual void AddWRImage(wr::ResourceUpdateQueue& aResources, + Range& aImageKeys, + const wr::ExternalImageId& aExtID) { - MOZ_ASSERT_UNREACHABLE("Unimplemented"); + MOZ_ASSERT_UNREACHABLE("No AddWRImage() implementation for this TextureHost type."); } // Put all necessary WR commands into DisplayListBuilder for this textureHost rendering. @@ -746,10 +741,9 @@ public: virtual uint32_t NumSubTextures() const override; - virtual void PushResourceUpdates(wr::ResourceUpdateQueue& aResources, - ResourceUpdateOp aOp, - const Range& aImageKeys, - const wr::ExternalImageId& aExtID) override; + virtual void AddWRImage(wr::ResourceUpdateQueue& aResources, + Range& aImageKeys, + const wr::ExternalImageId& aExtID) override; virtual void PushExternalImage(wr::DisplayListBuilder& aBuilder, const wr::LayoutRect& aBounds, diff --git a/gfx/layers/d3d11/TextureD3D11.cpp b/gfx/layers/d3d11/TextureD3D11.cpp index d82a8da37f7c..8ff7c4cd81c1 100644 --- a/gfx/layers/d3d11/TextureD3D11.cpp +++ b/gfx/layers/d3d11/TextureD3D11.cpp @@ -1063,15 +1063,11 @@ DXGITextureHostD3D11::NumSubTextures() const } void -DXGITextureHostD3D11::PushResourceUpdates(wr::ResourceUpdateQueue& aResources, - ResourceUpdateOp aOp, - const Range& aImageKeys, - const wr::ExternalImageId& aExtID) override; +DXGITextureHostD3D11::AddWRImage(wr::ResourceUpdateQueue& aResources, + Range& aImageKeys, + const wr::ExternalImageId& aExtID) { MOZ_ASSERT(mHandle); - auto method = aOp == TextureHost::ADD_IMAGE ? &wr::ResourceUpdateQueue::AddExternalImage - : &wr::ResourceUpdateQueue::UpdateExternalImage; - auto bufferType = wr::WrExternalImageBufferType::TextureExternalHandle; switch (mFormat) { case gfx::SurfaceFormat::R8G8B8X8: @@ -1081,7 +1077,11 @@ DXGITextureHostD3D11::PushResourceUpdates(wr::ResourceUpdateQueue& aResources, MOZ_ASSERT(aImageKeys.length() == 1); wr::ImageDescriptor descriptor(GetSize(), GetFormat()); - (aResources.*method)(aImageKeys[0], descriptor, aExtID, bufferType, 0); + aResources.AddExternalImage(aImageKeys[0], + descriptor, + aExtID, + wr::WrExternalImageBufferType::Texture2DHandle, + 0); break; } case gfx::SurfaceFormat::NV12: { @@ -1089,8 +1089,16 @@ DXGITextureHostD3D11::PushResourceUpdates(wr::ResourceUpdateQueue& aResources, wr::ImageDescriptor descriptor0(GetSize(), gfx::SurfaceFormat::A8); wr::ImageDescriptor descriptor1(GetSize() / 2, gfx::SurfaceFormat::R8G8); - (aResources.*method)(aImageKeys[0], descriptor0, aExtID, bufferType, 0); - (aResources.*method)(aImageKeys[1], descriptor1, aExtID, bufferType, 1); + aResources.AddExternalImage(aImageKeys[0], + descriptor0, + aExtID, + wr::WrExternalImageBufferType::TextureExternalHandle, + 0); + aResources.AddExternalImage(aImageKeys[1], + descriptor1, + aExtID, + wr::WrExternalImageBufferType::TextureExternalHandle, + 1); break; } default: { @@ -1295,10 +1303,9 @@ DXGIYCbCrTextureHostD3D11::CreateRenderTexture(const wr::ExternalImageId& aExter } void -DXGIYCbCrTextureHostD3D11::PushResourceUpdates(wr::ResourceUpdateQueue& aResources, - ResourceUpdateOp aOp, - const Range& aImageKeys, - const wr::ExternalImageId& aExtID) override; +DXGIYCbCrTextureHostD3D11::AddWRImage(wr::ResourceUpdateQueue& aResources, + Range& aImageKeys, + const wr::ExternalImageId& aExtID) { // TODO - This implementation is very slow (read-back, copy on the copy and re-upload). @@ -1324,11 +1331,7 @@ DXGIYCbCrTextureHostD3D11::PushResourceUpdates(wr::ResourceUpdateQueue& aResourc wr::ImageDescriptor descriptor(size, map.mStride, dataSourceSurface->GetFormat()); wr::Vec_u8 imgBytes; imgBytes.PushBytes(Range(map.mData, size.height * map.mStride)); - if (aOp == TextureHost::ADD_IMAGE) { - aResources.AddImage(aImageKeys[0], descriptor, imgBytes); - } else { - aResource.UpdateImage(aImageKeys[0], descriptor, imgBytes); - } + aResources.AddImage(aImageKeys[0], descriptor, imgBytes); dataSourceSurface->Unmap(); } diff --git a/gfx/layers/d3d11/TextureD3D11.h b/gfx/layers/d3d11/TextureD3D11.h index 3d4b3b3d9826..ca7fd6355d48 100644 --- a/gfx/layers/d3d11/TextureD3D11.h +++ b/gfx/layers/d3d11/TextureD3D11.h @@ -337,10 +337,9 @@ public: virtual uint32_t NumSubTextures() const override; - virtual void PushResourceUpdates(wr::ResourceUpdateQueue& aResources, - ResourceUpdateOp aOp, - const Range& aImageKeys, - const wr::ExternalImageId& aExtID) override; + virtual void AddWRImage(wr::ResourceUpdateQueue& aAPI, + Range& aImageKeys, + const wr::ExternalImageId& aExtID) override; virtual void PushExternalImage(wr::DisplayListBuilder& aBuilder, const wr::LayoutRect& aBounds, @@ -398,10 +397,9 @@ public: virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override; - virtual void PushResourceUpdates(wr::ResourceUpdateQueue& aResources, - ResourceUpdateOp aOp, - const Range& aImageKeys, - const wr::ExternalImageId& aExtID) override; + virtual void AddWRImage(wr::ResourceUpdateQueue& aResources, + Range& aImageKeys, + const wr::ExternalImageId& aExtID) override; virtual void PushExternalImage(wr::DisplayListBuilder& aBuilder, const wr::LayoutRect& aBounds, diff --git a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp index aa01f897837f..671d0edb5f16 100644 --- a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp +++ b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp @@ -147,17 +147,12 @@ MacIOSurfaceTextureHostOGL::NumSubTextures() const } void -MacIOSurfaceTextureHostOGL::PushResourceUpdates(wr::ResourceUpdateQueue& aResources, - ResourceUpdateOp aOp, - const Range& aImageKeys, - const wr::ExternalImageId& aExtID) override; +MacIOSurfaceTextureHostOGL::AddWRImage(wr::ResourceUpdateQueue& aResources, + Range& aImageKeys, + const wr::ExternalImageId& aExtID) { MOZ_ASSERT(mSurface); - auto method = aOp == TextureHost::ADD_IMAGE ? &wr::ResourceUpdateQueue::AddExternalImage - : &wr::ResourceUpdateQueue::UpdateExternalImage; - auto bufferType = wr::WrExternalImageBufferType::TextureRectHandle; - switch (GetFormat()) { case gfx::SurfaceFormat::R8G8B8X8: case gfx::SurfaceFormat::R8G8B8A8: @@ -166,7 +161,11 @@ MacIOSurfaceTextureHostOGL::PushResourceUpdates(wr::ResourceUpdateQueue& aResour MOZ_ASSERT(aImageKeys.length() == 1); MOZ_ASSERT(mSurface->GetPlaneCount() == 0); wr::ImageDescriptor descriptor(GetSize(), GetFormat()); - (aResources.*method)(aImageKeys[0], descriptor, aExtID, bufferType, 0); + aResources.AddExternalImage(aImageKeys[0], + descriptor, + aExtID, + wr::WrExternalImageBufferType::TextureRectHandle, + 0); break; } case gfx::SurfaceFormat::YUV422: { @@ -177,7 +176,11 @@ MacIOSurfaceTextureHostOGL::PushResourceUpdates(wr::ResourceUpdateQueue& aResour MOZ_ASSERT(aImageKeys.length() == 1); MOZ_ASSERT(mSurface->GetPlaneCount() == 0); wr::ImageDescriptor descriptor(GetSize(), gfx::SurfaceFormat::R8G8B8X8); - (aResources.*method)(aImageKeys[0], descriptor, aExtID, bufferType, 0); + aResources.AddExternalImage(aImageKeys[0], + descriptor, + aExtID, + wr::WrExternalImageBufferType::TextureRectHandle, + 0); break; } case gfx::SurfaceFormat::NV12: { @@ -187,8 +190,16 @@ MacIOSurfaceTextureHostOGL::PushResourceUpdates(wr::ResourceUpdateQueue& aResour gfx::SurfaceFormat::A8); wr::ImageDescriptor descriptor1(gfx::IntSize(mSurface->GetDevicePixelWidth(1), mSurface->GetDevicePixelHeight(1)), gfx::SurfaceFormat::R8G8); - (aResources.*method)(aImageKeys[0], descriptor0, aExtID, bufferType, 0); - (aResources.*method)(aImageKeys[1], descriptor1, aExtID, bufferType, 1); + aResources.AddExternalImage(aImageKeys[0], + descriptor0, + aExtID, + wr::WrExternalImageBufferType::TextureRectHandle, + 0); + aResources.AddExternalImage(aImageKeys[1], + descriptor1, + aExtID, + wr::WrExternalImageBufferType::TextureRectHandle, + 1); break; } default: { diff --git a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h index 8254fe25b2ae..9a23106cae31 100644 --- a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h +++ b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h @@ -66,10 +66,9 @@ public: virtual uint32_t NumSubTextures() const override; - virtual void PushResourceUpdates(wr::ResourceUpdateQueue& aResources, - ResourceUpdateOp aOp, - const Range& aImageKeys, - const wr::ExternalImageId& aExtID) override; + virtual void AddWRImage(wr::ResourceUpdateQueue& aResources, + Range& aImageKeys, + const wr::ExternalImageId& aExtID) override; virtual void PushExternalImage(wr::DisplayListBuilder& aBuilder, const wr::LayoutRect& aBounds, diff --git a/gfx/layers/wr/AsyncImagePipelineManager.cpp b/gfx/layers/wr/AsyncImagePipelineManager.cpp index 6f2cca32ab44..f2482c6087af 100644 --- a/gfx/layers/wr/AsyncImagePipelineManager.cpp +++ b/gfx/layers/wr/AsyncImagePipelineManager.cpp @@ -178,9 +178,8 @@ AsyncImagePipelineManager::GenerateImageKeyForTextureHost(wr::ResourceUpdateQueu aKeys.AppendElement(GenerateImageKey()); } MOZ_ASSERT(!aKeys.IsEmpty()); - Range keys(&aKeys[0], aKeys.Length()); - wrTexture->PushResourceUpdates(aResources, TextureHost::ADD_IMAGE, - keys, wrTexture->GetExternalImageKey()); + Range keys(&aKeys[0], aKeys.Length()); + wrTexture->AddWRImage(aResources, keys, wrTexture->GetExternalImageKey()); return true; } else { RefPtr dSurf = aTexture->GetAsSurface(); diff --git a/gfx/layers/wr/WebRenderBridgeParent.cpp b/gfx/layers/wr/WebRenderBridgeParent.cpp index 044018d5c842..a516521285a6 100644 --- a/gfx/layers/wr/WebRenderBridgeParent.cpp +++ b/gfx/layers/wr/WebRenderBridgeParent.cpp @@ -329,7 +329,7 @@ bool WebRenderBridgeParent::AddExternalImage(wr::ExternalImageId aExtId, wr::ImageKey aKey, wr::ResourceUpdateQueue& aResources) { - Range keys(&aKey, 1); + Range keys(&aKey, 1); // Check if key is obsoleted. if (keys[0].mNamespace != mIdNamespace) { return true; @@ -349,8 +349,7 @@ WebRenderBridgeParent::AddExternalImage(wr::ExternalImageId aExtId, wr::ImageKey } WebRenderTextureHost* wrTexture = texture->AsWebRenderTextureHost(); if (wrTexture) { - wrTexture->PushResourceUpdates(aResources, TextureHost::ADD_IMAGE, keys, - wrTexture->GetExternalImageKey()); + wrTexture->AddWRImage(aResources, keys, wrTexture->GetExternalImageKey()); return true; } } diff --git a/gfx/layers/wr/WebRenderTextureHost.cpp b/gfx/layers/wr/WebRenderTextureHost.cpp index 0425eb34a8e2..ec50a3bbfdcc 100644 --- a/gfx/layers/wr/WebRenderTextureHost.cpp +++ b/gfx/layers/wr/WebRenderTextureHost.cpp @@ -142,15 +142,14 @@ WebRenderTextureHost::NumSubTextures() const } void -WebRenderTextureHost::PushResourceUpdates(wr::ResourceUpdateQueue& aResources, - ResourceUpdateOp aOp, - const Range& aImageKeys, - const wr::ExternalImageId& aExtID) +WebRenderTextureHost::AddWRImage(wr::ResourceUpdateQueue& aResources, + Range& aImageKeys, + const wr::ExternalImageId& aExtID) { MOZ_ASSERT(mWrappedTextureHost); MOZ_ASSERT(mExternalImageId == aExtID); - mWrappedTextureHost->PushResourceUpdates(aResources, aOp, aImageKeys, aExtID); + mWrappedTextureHost->AddWRImage(aResources, aImageKeys, aExtID); } void diff --git a/gfx/layers/wr/WebRenderTextureHost.h b/gfx/layers/wr/WebRenderTextureHost.h index f9af8696f657..ea92aec83165 100644 --- a/gfx/layers/wr/WebRenderTextureHost.h +++ b/gfx/layers/wr/WebRenderTextureHost.h @@ -65,10 +65,9 @@ public: virtual uint32_t NumSubTextures() const override; - virtual void PushResourceUpdates(wr::ResourceUpdateQueue& aResources, - ResourceUpdateOp aOp, - const Range& aImageKeys, - const wr::ExternalImageId& aExtID) override; + virtual void AddWRImage(wr::ResourceUpdateQueue& aResources, + Range& aImageKeys, + const wr::ExternalImageId& aExtID) override; virtual void PushExternalImage(wr::DisplayListBuilder& aBuilder, const wr::LayoutRect& aBounds, From a2d2f547b1ee5d07217da5a471c7e4f40986be75 Mon Sep 17 00:00:00 2001 From: Sebastian Hengst Date: Fri, 22 Sep 2017 16:23:31 +0200 Subject: [PATCH 28/37] Backed out changeset 3d11e27057a3 (bug 1383786) for build bustage on OS X and Windows at gfx/layers/d3d11/TextureD3D11.cpp(1069). r=backout on a CLOSED TREE --- gfx/layers/composite/GPUVideoTextureHost.cpp | 9 ++++-- gfx/layers/composite/GPUVideoTextureHost.h | 3 +- gfx/layers/composite/TextureHost.cpp | 21 ++++++++---- gfx/layers/composite/TextureHost.h | 17 +++++++--- gfx/layers/d3d11/TextureD3D11.cpp | 32 +++++++++++++++---- gfx/layers/d3d11/TextureD3D11.h | 6 +++- .../opengl/MacIOSurfaceTextureHostOGL.cpp | 26 +++++++++++---- .../opengl/MacIOSurfaceTextureHostOGL.h | 3 +- gfx/layers/wr/AsyncImagePipelineManager.cpp | 5 +-- gfx/layers/wr/WebRenderTextureHost.cpp | 9 ++++-- gfx/layers/wr/WebRenderTextureHost.h | 3 +- 11 files changed, 98 insertions(+), 36 deletions(-) diff --git a/gfx/layers/composite/GPUVideoTextureHost.cpp b/gfx/layers/composite/GPUVideoTextureHost.cpp index 7a33d05d72ea..cdf300bb0120 100644 --- a/gfx/layers/composite/GPUVideoTextureHost.cpp +++ b/gfx/layers/composite/GPUVideoTextureHost.cpp @@ -111,11 +111,14 @@ GPUVideoTextureHost::CreateRenderTexture(const wr::ExternalImageId& aExternalIma mWrappedTextureHost->CreateRenderTexture(aExternalImageId); } -uint32_t -GPUVideoTextureHost::NumSubTextures() const +void +GPUVideoTextureHost::GetWRImageKeys(nsTArray& aImageKeys, + const std::function& aImageKeyAllocator) { MOZ_ASSERT(mWrappedTextureHost); - return mWrappedTextureHost->NumSubTextures(); + MOZ_ASSERT(aImageKeys.IsEmpty()); + + mWrappedTextureHost->GetWRImageKeys(aImageKeys, aImageKeyAllocator); } void diff --git a/gfx/layers/composite/GPUVideoTextureHost.h b/gfx/layers/composite/GPUVideoTextureHost.h index bad3dfea4951..4a65e63ca315 100644 --- a/gfx/layers/composite/GPUVideoTextureHost.h +++ b/gfx/layers/composite/GPUVideoTextureHost.h @@ -48,7 +48,8 @@ public: virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override; - virtual uint32_t NumSubTextures() const override; + virtual void GetWRImageKeys(nsTArray& aImageKeys, + const std::function& aImageKeyAllocator) override; virtual void AddWRImage(wr::ResourceUpdateQueue& aResources, Range& aImageKeys, diff --git a/gfx/layers/composite/TextureHost.cpp b/gfx/layers/composite/TextureHost.cpp index e20e74532126..1105837fc23b 100644 --- a/gfx/layers/composite/TextureHost.cpp +++ b/gfx/layers/composite/TextureHost.cpp @@ -566,14 +566,23 @@ BufferTextureHost::CreateRenderTexture(const wr::ExternalImageId& aExternalImage wr::RenderThread::Get()->RegisterExternalImage(wr::AsUint64(aExternalImageId), texture.forget()); } -uint32_t -BufferTextureHost::NumSubTextures() const +void +BufferTextureHost::GetWRImageKeys(nsTArray& aImageKeys, + const std::function& aImageKeyAllocator) { - if (GetFormat() == gfx::SurfaceFormat::YUV) { - return 3; - } + MOZ_ASSERT(aImageKeys.IsEmpty()); - return 1; + if (GetFormat() != gfx::SurfaceFormat::YUV) { + // 1 image key + aImageKeys.AppendElement(aImageKeyAllocator()); + MOZ_ASSERT(aImageKeys.Length() == 1); + } else { + // 3 image key + aImageKeys.AppendElement(aImageKeyAllocator()); + aImageKeys.AppendElement(aImageKeyAllocator()); + aImageKeys.AppendElement(aImageKeyAllocator()); + MOZ_ASSERT(aImageKeys.Length() == 3); + } } void diff --git a/gfx/layers/composite/TextureHost.h b/gfx/layers/composite/TextureHost.h index 9bc06766469e..7d7d950fd2a4 100644 --- a/gfx/layers/composite/TextureHost.h +++ b/gfx/layers/composite/TextureHost.h @@ -621,9 +621,17 @@ public: MOZ_RELEASE_ASSERT(false, "No CreateRenderTexture() implementation for this TextureHost type."); } - /// Returns the number of actual textures that will be used to render this. - /// For example in a lot of YUV cases it will be 3 - virtual uint32_t NumSubTextures() const { return 1; } + // Create all necessary image keys for this textureHost rendering. + // @param aImageKeys - [out] The set of ImageKeys used for this textureHost + // composing. + // @param aImageKeyAllocator - [in] The function which is used for creating + // the new ImageKey. + virtual void GetWRImageKeys(nsTArray& aImageKeys, + const std::function& aImageKeyAllocator) + { + MOZ_ASSERT(aImageKeys.IsEmpty()); + MOZ_ASSERT_UNREACHABLE("No GetWRImageKeys() implementation for this TextureHost type."); + } // Add all necessary TextureHost informations to the resource update queue. // Then, WR will use this informations to read from the TextureHost. @@ -739,7 +747,8 @@ public: virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override; - virtual uint32_t NumSubTextures() const override; + virtual void GetWRImageKeys(nsTArray& aImageKeys, + const std::function& aImageKeyAllocator) override; virtual void AddWRImage(wr::ResourceUpdateQueue& aResources, Range& aImageKeys, diff --git a/gfx/layers/d3d11/TextureD3D11.cpp b/gfx/layers/d3d11/TextureD3D11.cpp index 8ff7c4cd81c1..6f7ee8a4bc1d 100644 --- a/gfx/layers/d3d11/TextureD3D11.cpp +++ b/gfx/layers/d3d11/TextureD3D11.cpp @@ -1042,22 +1042,31 @@ DXGITextureHostD3D11::CreateRenderTexture(const wr::ExternalImageId& aExternalIm wr::RenderThread::Get()->RegisterExternalImage(wr::AsUint64(aExternalImageId), texture.forget()); } -uint32_t -DXGITextureHostD3D11::NumSubTextures() const +void +DXGITextureHostD3D11::GetWRImageKeys(nsTArray& aImageKeys, + const std::function& aImageKeyAllocator) { + MOZ_ASSERT(aImageKeys.IsEmpty()); + switch (GetFormat()) { case gfx::SurfaceFormat::R8G8B8X8: case gfx::SurfaceFormat::R8G8B8A8: case gfx::SurfaceFormat::B8G8R8A8: case gfx::SurfaceFormat::B8G8R8X8: { - return 1; + // 1 image key + aImageKeys.AppendElement(aImageKeyAllocator()); + MOZ_ASSERT(aImageKeys.Length() == 1); + break; } case gfx::SurfaceFormat::NV12: { - return 2; + // 2 image key + aImageKeys.AppendElement(aImageKeyAllocator()); + aImageKeys.AppendElement(aImageKeyAllocator()); + MOZ_ASSERT(aImageKeys.Length() == 2); + break; } default: { - MOZ_ASSERT_UNREACHABLE("unexpected format"); - return 1; + MOZ_ASSERT_UNREACHABLE("unexpected to be called"); } } } @@ -1302,6 +1311,17 @@ DXGIYCbCrTextureHostD3D11::CreateRenderTexture(const wr::ExternalImageId& aExter // We use AddImage() directly. It's no corresponding RenderTextureHost. } +void +DXGIYCbCrTextureHostD3D11::GetWRImageKeys(nsTArray& aImageKeys, + const std::function& aImageKeyAllocator) +{ + MOZ_ASSERT(aImageKeys.IsEmpty()); + + // 1 image key + aImageKeys.AppendElement(aImageKeyAllocator()); + MOZ_ASSERT(aImageKeys.Length() == 1); +} + void DXGIYCbCrTextureHostD3D11::AddWRImage(wr::ResourceUpdateQueue& aResources, Range& aImageKeys, diff --git a/gfx/layers/d3d11/TextureD3D11.h b/gfx/layers/d3d11/TextureD3D11.h index ca7fd6355d48..f13ef4ad8e04 100644 --- a/gfx/layers/d3d11/TextureD3D11.h +++ b/gfx/layers/d3d11/TextureD3D11.h @@ -335,7 +335,8 @@ public: virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override; - virtual uint32_t NumSubTextures() const override; + virtual void GetWRImageKeys(nsTArray& aImageKeys, + const std::function& aImageKeyAllocator) override; virtual void AddWRImage(wr::ResourceUpdateQueue& aAPI, Range& aImageKeys, @@ -397,6 +398,9 @@ public: virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override; + virtual void GetWRImageKeys(nsTArray& aImageKeys, + const std::function& aImageKeyAllocator) override; + virtual void AddWRImage(wr::ResourceUpdateQueue& aResources, Range& aImageKeys, const wr::ExternalImageId& aExtID) override; diff --git a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp index 671d0edb5f16..74bbae005f3b 100644 --- a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp +++ b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp @@ -125,23 +125,37 @@ MacIOSurfaceTextureHostOGL::CreateRenderTexture(const wr::ExternalImageId& aExte wr::RenderThread::Get()->RegisterExternalImage(wr::AsUint64(aExternalImageId), texture.forget()); } -uint32_t -MacIOSurfaceTextureHostOGL::NumSubTextures() const +void +MacIOSurfaceTextureHostOGL::GetWRImageKeys(nsTArray& aImageKeys, + const std::function& aImageKeyAllocator) { + MOZ_ASSERT(aImageKeys.IsEmpty()); + switch (GetFormat()) { case gfx::SurfaceFormat::R8G8B8X8: case gfx::SurfaceFormat::R8G8B8A8: case gfx::SurfaceFormat::B8G8R8A8: case gfx::SurfaceFormat::B8G8R8X8: { + // 1 image key + aImageKeys.AppendElement(aImageKeyAllocator()); + MOZ_ASSERT(aImageKeys.Length() == 1); + break; + } case gfx::SurfaceFormat::YUV422: { - return 1; + // 1 image key + aImageKeys.AppendElement(aImageKeyAllocator()); + MOZ_ASSERT(aImageKeys.Length() == 1); + break; } case gfx::SurfaceFormat::NV12: { - return 2; + // 2 image key + aImageKeys.AppendElement(aImageKeyAllocator()); + aImageKeys.AppendElement(aImageKeyAllocator()); + MOZ_ASSERT(aImageKeys.Length() == 2); + break; } default: { - MOZ_ASSERT_UNREACHABLE("unexpected format"); - return 1; + MOZ_ASSERT_UNREACHABLE("unexpected to be called"); } } } diff --git a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h index 9a23106cae31..1ecc7e0089e3 100644 --- a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h +++ b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h @@ -64,7 +64,8 @@ public: virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override; - virtual uint32_t NumSubTextures() const override; + virtual void GetWRImageKeys(nsTArray& aImageKeys, + const std::function& aImageKeyAllocator) override; virtual void AddWRImage(wr::ResourceUpdateQueue& aResources, Range& aImageKeys, diff --git a/gfx/layers/wr/AsyncImagePipelineManager.cpp b/gfx/layers/wr/AsyncImagePipelineManager.cpp index f2482c6087af..79eca3d28e54 100644 --- a/gfx/layers/wr/AsyncImagePipelineManager.cpp +++ b/gfx/layers/wr/AsyncImagePipelineManager.cpp @@ -173,10 +173,7 @@ AsyncImagePipelineManager::GenerateImageKeyForTextureHost(wr::ResourceUpdateQueu WebRenderTextureHost* wrTexture = aTexture->AsWebRenderTextureHost(); if (!gfxEnv::EnableWebRenderRecording() && wrTexture) { - auto numKeys = wrTexture->NumSubTextures(); - for (uint32_t i = 0; i < numKeys; ++i) { - aKeys.AppendElement(GenerateImageKey()); - } + wrTexture->GetWRImageKeys(aKeys, std::bind(&AsyncImagePipelineManager::GenerateImageKey, this)); MOZ_ASSERT(!aKeys.IsEmpty()); Range keys(&aKeys[0], aKeys.Length()); wrTexture->AddWRImage(aResources, keys, wrTexture->GetExternalImageKey()); diff --git a/gfx/layers/wr/WebRenderTextureHost.cpp b/gfx/layers/wr/WebRenderTextureHost.cpp index ec50a3bbfdcc..78f479a4d75d 100644 --- a/gfx/layers/wr/WebRenderTextureHost.cpp +++ b/gfx/layers/wr/WebRenderTextureHost.cpp @@ -134,11 +134,14 @@ WebRenderTextureHost::GetRGBStride() return ImageDataSerializer::ComputeRGBStride(format, GetSize().width); } -uint32_t -WebRenderTextureHost::NumSubTextures() const +void +WebRenderTextureHost::GetWRImageKeys(nsTArray& aImageKeys, + const std::function& aImageKeyAllocator) { MOZ_ASSERT(mWrappedTextureHost); - return mWrappedTextureHost->NumSubTextures(); + MOZ_ASSERT(aImageKeys.IsEmpty()); + + mWrappedTextureHost->GetWRImageKeys(aImageKeys, aImageKeyAllocator); } void diff --git a/gfx/layers/wr/WebRenderTextureHost.h b/gfx/layers/wr/WebRenderTextureHost.h index ea92aec83165..5f235c7675d6 100644 --- a/gfx/layers/wr/WebRenderTextureHost.h +++ b/gfx/layers/wr/WebRenderTextureHost.h @@ -63,7 +63,8 @@ public: int32_t GetRGBStride(); - virtual uint32_t NumSubTextures() const override; + virtual void GetWRImageKeys(nsTArray& aImageKeys, + const std::function& aImageKeyAllocator) override; virtual void AddWRImage(wr::ResourceUpdateQueue& aResources, Range& aImageKeys, From 9269f6c8a48ea7c17b8338dafd401db606f31da2 Mon Sep 17 00:00:00 2001 From: Ryan Hunt Date: Wed, 20 Sep 2017 12:23:01 -0500 Subject: [PATCH 29/37] Bug 1401638 - Set and reset mPermitSubpixelAA in push and pop layer for DrawTargetCapture. r=bas MozReview-Commit-ID: DxeNaiAYJvb --HG-- extra : rebase_source : ea799e4f4d48b52702423d726304b1a5a96fbb65 --- gfx/2d/DrawTargetCapture.cpp | 11 +++++++++++ gfx/2d/DrawTargetCapture.h | 8 ++++++++ 2 files changed, 19 insertions(+) diff --git a/gfx/2d/DrawTargetCapture.cpp b/gfx/2d/DrawTargetCapture.cpp index 813252517e3a..87630f15d84a 100644 --- a/gfx/2d/DrawTargetCapture.cpp +++ b/gfx/2d/DrawTargetCapture.cpp @@ -227,6 +227,13 @@ DrawTargetCaptureImpl::PushLayer(bool aOpaque, const IntRect& aBounds, bool aCopyBackground) { + // Have to update mPermitSubpixelAA for this DT + // because some code paths query the current setting + // to determine subpixel AA eligibility. + PushedLayer layer(GetPermitSubpixelAA()); + mPushedLayers.push_back(layer); + DrawTarget::SetPermitSubpixelAA(aOpaque); + AppendCommand(PushLayerCommand)(aOpaque, aOpacity, aMask, @@ -238,6 +245,10 @@ DrawTargetCaptureImpl::PushLayer(bool aOpaque, void DrawTargetCaptureImpl::PopLayer() { + MOZ_ASSERT(mPushedLayers.size()); + DrawTarget::SetPermitSubpixelAA(mPushedLayers.back().mOldPermitSubpixelAA); + mPushedLayers.pop_back(); + AppendCommand(PopLayerCommand)(); } diff --git a/gfx/2d/DrawTargetCapture.h b/gfx/2d/DrawTargetCapture.h index 4f53eaa859c3..02fad72cf032 100644 --- a/gfx/2d/DrawTargetCapture.h +++ b/gfx/2d/DrawTargetCapture.h @@ -168,6 +168,14 @@ private: RefPtr mRefDT; IntSize mSize; + struct PushedLayer + { + PushedLayer(bool aOldPermitSubpixelAA) + : mOldPermitSubpixelAA(aOldPermitSubpixelAA) + {} + bool mOldPermitSubpixelAA; + }; + std::vector mPushedLayers; std::vector mDrawCommandStorage; }; From 21b23600b724718d00fc032936910c6121a31483 Mon Sep 17 00:00:00 2001 From: Ryan Hunt Date: Fri, 22 Sep 2017 11:25:17 -0400 Subject: [PATCH 30/37] Bug 1401638 - Fixup implicit constructor bustage. r=me on a CLOSED TREE --- gfx/2d/DrawTargetCapture.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx/2d/DrawTargetCapture.h b/gfx/2d/DrawTargetCapture.h index 02fad72cf032..e23388fefcd6 100644 --- a/gfx/2d/DrawTargetCapture.h +++ b/gfx/2d/DrawTargetCapture.h @@ -170,7 +170,7 @@ private: struct PushedLayer { - PushedLayer(bool aOldPermitSubpixelAA) + explicit PushedLayer(bool aOldPermitSubpixelAA) : mOldPermitSubpixelAA(aOldPermitSubpixelAA) {} bool mOldPermitSubpixelAA; From acefcfd58a7043803b6a999905f41bcebebc9e54 Mon Sep 17 00:00:00 2001 From: Bob Owen Date: Fri, 22 Sep 2017 16:27:13 +0100 Subject: [PATCH 31/37] Bug 1402340: On non-Nightly revert back to Windows content process sandbox level 3 to fix suspected top crashes. r=jimm --- browser/app/profile/firefox.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index 4ed20f25f0f7..9f247d8c3ff7 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1030,7 +1030,11 @@ pref("dom.ipc.plugins.sandbox-level.flash", 0); // On windows these levels are: // See - security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp // SetSecurityLevelForContentProcess() for what the different settings mean. +#if defined(NIGHTLY_BUILD) pref("security.sandbox.content.level", 4); +#else +pref("security.sandbox.content.level", 3); +#endif // This controls the depth of stack trace that is logged when Windows sandbox // logging is turned on. This is only currently available for the content From 42179d24726135ba939b2d3c29df0b6bd1cd4f05 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Fri, 22 Sep 2017 10:32:27 -0500 Subject: [PATCH 32/37] Bug 1329019 - Baldr: simplify InternalLink code (r=lth) MozReview-Commit-ID: HGpmFpyKit8 --- js/src/jit/arm/Assembler-arm.cpp | 6 ++-- js/src/jit/arm/Assembler-arm.h | 11 +------- js/src/jit/arm64/Assembler-arm64.cpp | 6 ---- js/src/jit/arm64/Assembler-arm64.h | 11 ++------ .../jit/mips-shared/Assembler-mips-shared.cpp | 2 +- .../jit/mips-shared/Assembler-mips-shared.h | 5 +--- js/src/jit/mips32/Assembler-mips32.cpp | 15 +++------- js/src/jit/mips32/Assembler-mips32.h | 3 +- js/src/jit/mips64/Assembler-mips64.cpp | 15 +++------- js/src/jit/mips64/Assembler-mips64.h | 3 +- js/src/jit/none/MacroAssembler-none.h | 2 -- .../jit/x86-shared/Assembler-x86-shared.cpp | 2 +- js/src/jit/x86-shared/Assembler-x86-shared.h | 17 +++-------- js/src/wasm/WasmCode.cpp | 18 ++++-------- js/src/wasm/WasmGenerator.cpp | 4 +-- js/src/wasm/WasmModule.cpp | 28 ------------------- js/src/wasm/WasmModule.h | 13 ++------- 17 files changed, 34 insertions(+), 127 deletions(-) diff --git a/js/src/jit/arm/Assembler-arm.cpp b/js/src/jit/arm/Assembler-arm.cpp index 0507015e162b..988dc96c700e 100644 --- a/js/src/jit/arm/Assembler-arm.cpp +++ b/js/src/jit/arm/Assembler-arm.cpp @@ -948,7 +948,7 @@ Assembler::processCodeLabels(uint8_t* rawCode) { for (size_t i = 0; i < codeLabels_.length(); i++) { CodeLabel label = codeLabels_[i]; - Bind(rawCode, label.patchAt(), rawCode + label.target()->offset()); + Bind(rawCode, *label.patchAt(), *label.target()); } } @@ -960,9 +960,9 @@ Assembler::writeCodePointer(CodeOffset* label) } void -Assembler::Bind(uint8_t* rawCode, CodeOffset* label, const void* address) +Assembler::Bind(uint8_t* rawCode, CodeOffset label, CodeOffset target) { - *reinterpret_cast(rawCode + label->offset()) = address; + *reinterpret_cast(rawCode + label.offset()) = rawCode + target.offset(); } Assembler::Condition diff --git a/js/src/jit/arm/Assembler-arm.h b/js/src/jit/arm/Assembler-arm.h index bc9a06d9f302..59bdb9311cb5 100644 --- a/js/src/jit/arm/Assembler-arm.h +++ b/js/src/jit/arm/Assembler-arm.h @@ -1712,12 +1712,7 @@ class Assembler : public AssemblerShared // I'm going to pretend this doesn't exist for now. void retarget(Label* label, void* target, Relocation::Kind reloc); - void Bind(uint8_t* rawCode, CodeOffset* label, const void* address); - - // See Bind - size_t labelToPatchOffset(CodeOffset label) { - return label.offset(); - } + static void Bind(uint8_t* rawCode, CodeOffset label, CodeOffset target); void as_bkpt(); @@ -1919,10 +1914,6 @@ class Assembler : public AssemblerShared ImmPtr expectedValue); static void PatchWrite_Imm32(CodeLocationLabel label, Imm32 imm); - static void PatchInstructionImmediate(uint8_t* code, PatchedImmPtr imm) { - MOZ_CRASH("Unused."); - } - static uint32_t AlignDoubleArg(uint32_t offset) { return (offset + 1) & ~1; } diff --git a/js/src/jit/arm64/Assembler-arm64.cpp b/js/src/jit/arm64/Assembler-arm64.cpp index 014646822d9a..b11ba617e804 100644 --- a/js/src/jit/arm64/Assembler-arm64.cpp +++ b/js/src/jit/arm64/Assembler-arm64.cpp @@ -631,12 +631,6 @@ Assembler::FixupNurseryObjects(JSContext* cx, JitCode* code, CompactBufferReader cx->zone()->group()->storeBuffer().putWholeCell(code); } -void -Assembler::PatchInstructionImmediate(uint8_t* code, PatchedImmPtr imm) -{ - MOZ_CRASH("PatchInstructionImmediate()"); -} - void Assembler::retarget(Label* label, Label* target) { diff --git a/js/src/jit/arm64/Assembler-arm64.h b/js/src/jit/arm64/Assembler-arm64.h index e20f5734bec9..f1b1d6bfcf46 100644 --- a/js/src/jit/arm64/Assembler-arm64.h +++ b/js/src/jit/arm64/Assembler-arm64.h @@ -245,12 +245,12 @@ class Assembler : public vixl::Assembler void processCodeLabels(uint8_t* rawCode) { for (size_t i = 0; i < codeLabels_.length(); i++) { CodeLabel label = codeLabels_[i]; - Bind(rawCode, label.patchAt(), rawCode + label.target()->offset()); + Bind(rawCode, *label.patchAt(), *label.target()); } } - void Bind(uint8_t* rawCode, CodeOffset* label, const void* address) { - *reinterpret_cast(rawCode + label->offset()) = address; + static void Bind(uint8_t* rawCode, CodeOffset label, CodeOffset address) { + *reinterpret_cast(rawCode + label.offset()) = rawCode + address.offset(); } void retarget(Label* cur, Label* next); @@ -270,9 +270,6 @@ class Assembler : public vixl::Assembler ARMBuffer::PoolEntry pe(curOffset); return armbuffer_.poolEntryOffset(pe); } - size_t labelToPatchOffset(CodeOffset label) { - return label.offset(); - } static uint8_t* PatchableJumpAddress(JitCode* code, uint32_t index) { return code->raw() + index; } @@ -344,8 +341,6 @@ class Assembler : public vixl::Assembler static void TraceJumpRelocations(JSTracer* trc, JitCode* code, CompactBufferReader& reader); static void TraceDataRelocations(JSTracer* trc, JitCode* code, CompactBufferReader& reader); - static void PatchInstructionImmediate(uint8_t* code, PatchedImmPtr imm); - static void FixupNurseryObjects(JSContext* cx, JitCode* code, CompactBufferReader& reader, const ObjectVector& nurseryObjects); diff --git a/js/src/jit/mips-shared/Assembler-mips-shared.cpp b/js/src/jit/mips-shared/Assembler-mips-shared.cpp index 8c643d315aff..d0589cb6f217 100644 --- a/js/src/jit/mips-shared/Assembler-mips-shared.cpp +++ b/js/src/jit/mips-shared/Assembler-mips-shared.cpp @@ -138,7 +138,7 @@ AssemblerMIPSShared::processCodeLabels(uint8_t* rawCode) { for (size_t i = 0; i < codeLabels_.length(); i++) { CodeLabel label = codeLabels_[i]; - Bind(rawCode, label.patchAt(), rawCode + label.target()->offset()); + Bind(rawCode, *label.patchAt(), *label.target()); } } diff --git a/js/src/jit/mips-shared/Assembler-mips-shared.h b/js/src/jit/mips-shared/Assembler-mips-shared.h index df162d4c8665..65014730b271 100644 --- a/js/src/jit/mips-shared/Assembler-mips-shared.h +++ b/js/src/jit/mips-shared/Assembler-mips-shared.h @@ -1233,7 +1233,7 @@ class AssemblerMIPSShared : public AssemblerShared void bind(Label* label, BufferOffset boff = BufferOffset()); void bindLater(Label* label, wasm::TrapDesc target); virtual void bind(InstImm* inst, uintptr_t branch, uintptr_t target) = 0; - virtual void Bind(uint8_t* rawCode, CodeOffset* label, const void* address) = 0; + virtual void Bind(uint8_t* rawCode, CodeOffset label, CodeOffset target) = 0; void bind(CodeOffset* label) { label->bind(currentOffset()); } @@ -1245,9 +1245,6 @@ class AssemblerMIPSShared : public AssemblerShared } void retarget(Label* label, Label* target); - // See Bind - size_t labelToPatchOffset(CodeOffset label) { return label.offset(); } - void call(Label* label); void call(void* target); diff --git a/js/src/jit/mips32/Assembler-mips32.cpp b/js/src/jit/mips32/Assembler-mips32.cpp index e2e571c83042..3cd4fa60dabb 100644 --- a/js/src/jit/mips32/Assembler-mips32.cpp +++ b/js/src/jit/mips32/Assembler-mips32.cpp @@ -302,12 +302,12 @@ Assembler::trace(JSTracer* trc) } void -Assembler::Bind(uint8_t* rawCode, CodeOffset* label, const void* address) +Assembler::Bind(uint8_t* rawCode, CodeOffset label, CodeOffset target) { - if (label->bound()) { - intptr_t offset = label->offset(); + if (label.bound()) { + intptr_t offset = label.offset(); Instruction* inst = (Instruction*) (rawCode + offset); - AssemblerMIPSShared::UpdateLuiOriValue(inst, inst->next(), (uint32_t)address); + AssemblerMIPSShared::UpdateLuiOriValue(inst, inst->next(), (uint32_t)(rawCode + target.offset())); } } @@ -499,13 +499,6 @@ Assembler::PatchDataWithValueCheck(CodeLocationLabel label, PatchedImmPtr newVal AutoFlushICache::flush(uintptr_t(inst), 8); } -void -Assembler::PatchInstructionImmediate(uint8_t* code, PatchedImmPtr imm) -{ - InstImm* inst = (InstImm*)code; - AssemblerMIPSShared::UpdateLuiOriValue(inst, inst->next(), (uint32_t)imm.value); -} - uint32_t Assembler::ExtractInstructionImmediate(uint8_t* code) { diff --git a/js/src/jit/mips32/Assembler-mips32.h b/js/src/jit/mips32/Assembler-mips32.h index 00c42c8e510b..54aad92f9fa6 100644 --- a/js/src/jit/mips32/Assembler-mips32.h +++ b/js/src/jit/mips32/Assembler-mips32.h @@ -155,7 +155,7 @@ class Assembler : public AssemblerMIPSShared using AssemblerMIPSShared::bind; void bind(RepatchLabel* label); - void Bind(uint8_t* rawCode, CodeOffset* label, const void* address); + static void Bind(uint8_t* rawCode, CodeOffset label, CodeOffset target); static void TraceJumpRelocations(JSTracer* trc, JitCode* code, CompactBufferReader& reader); static void TraceDataRelocations(JSTracer* trc, JitCode* code, CompactBufferReader& reader); @@ -178,7 +178,6 @@ class Assembler : public AssemblerMIPSShared static void PatchDataWithValueCheck(CodeLocationLabel label, PatchedImmPtr newValue, PatchedImmPtr expectedValue); - static void PatchInstructionImmediate(uint8_t* code, PatchedImmPtr imm); static uint32_t ExtractInstructionImmediate(uint8_t* code); static void ToggleCall(CodeLocationLabel inst_, bool enabled); diff --git a/js/src/jit/mips64/Assembler-mips64.cpp b/js/src/jit/mips64/Assembler-mips64.cpp index f618294a65eb..f5531b7d428d 100644 --- a/js/src/jit/mips64/Assembler-mips64.cpp +++ b/js/src/jit/mips64/Assembler-mips64.cpp @@ -235,12 +235,12 @@ Assembler::trace(JSTracer* trc) } void -Assembler::Bind(uint8_t* rawCode, CodeOffset* label, const void* address) +Assembler::Bind(uint8_t* rawCode, CodeOffset label, CodeOffset target) { - if (label->bound()) { - intptr_t offset = label->offset(); + if (label.bound()) { + intptr_t offset = label.offset(); Instruction* inst = (Instruction*) (rawCode + offset); - Assembler::UpdateLoad64Value(inst, (uint64_t)address); + Assembler::UpdateLoad64Value(inst, (uint64_t)(rawCode + target.offset())); } } @@ -490,13 +490,6 @@ Assembler::PatchDataWithValueCheck(CodeLocationLabel label, PatchedImmPtr newVal AutoFlushICache::flush(uintptr_t(inst), 6 * sizeof(uint32_t)); } -void -Assembler::PatchInstructionImmediate(uint8_t* code, PatchedImmPtr imm) -{ - InstImm* inst = (InstImm*)code; - Assembler::UpdateLoad64Value(inst, (uint64_t)imm.value); -} - uint64_t Assembler::ExtractInstructionImmediate(uint8_t* code) { diff --git a/js/src/jit/mips64/Assembler-mips64.h b/js/src/jit/mips64/Assembler-mips64.h index f9884b9e5063..8f5ad9fa1a73 100644 --- a/js/src/jit/mips64/Assembler-mips64.h +++ b/js/src/jit/mips64/Assembler-mips64.h @@ -147,7 +147,7 @@ class Assembler : public AssemblerMIPSShared using AssemblerMIPSShared::bind; void bind(RepatchLabel* label); - void Bind(uint8_t* rawCode, CodeOffset* label, const void* address); + static void Bind(uint8_t* rawCode, CodeOffset label, CodeOffset target); static void TraceJumpRelocations(JSTracer* trc, JitCode* code, CompactBufferReader& reader); static void TraceDataRelocations(JSTracer* trc, JitCode* code, CompactBufferReader& reader); @@ -171,7 +171,6 @@ class Assembler : public AssemblerMIPSShared static void PatchDataWithValueCheck(CodeLocationLabel label, PatchedImmPtr newValue, PatchedImmPtr expectedValue); - static void PatchInstructionImmediate(uint8_t* code, PatchedImmPtr imm); static uint64_t ExtractInstructionImmediate(uint8_t* code); static void ToggleCall(CodeLocationLabel inst_, bool enabled); diff --git a/js/src/jit/none/MacroAssembler-none.h b/js/src/jit/none/MacroAssembler-none.h index 59fcfa474520..fd25bc1207e4 100644 --- a/js/src/jit/none/MacroAssembler-none.h +++ b/js/src/jit/none/MacroAssembler-none.h @@ -145,7 +145,6 @@ class Assembler : public AssemblerShared static void PatchWrite_NearCall(CodeLocationLabel, CodeLocationLabel) { MOZ_CRASH(); } static uint32_t PatchWrite_NearCallSize() { MOZ_CRASH(); } - static void PatchInstructionImmediate(uint8_t*, PatchedImmPtr) { MOZ_CRASH(); } static void ToggleToJmp(CodeLocationLabel) { MOZ_CRASH(); } static void ToggleToCmp(CodeLocationLabel) { MOZ_CRASH(); } @@ -215,7 +214,6 @@ class MacroAssemblerNone : public Assembler void nopAlign(size_t) { MOZ_CRASH(); } void checkStackAlignment() { MOZ_CRASH(); } uint32_t currentOffset() { MOZ_CRASH(); } - uint32_t labelToPatchOffset(CodeOffset) { MOZ_CRASH(); } CodeOffset labelForPatch() { MOZ_CRASH(); } void nop() { MOZ_CRASH(); } diff --git a/js/src/jit/x86-shared/Assembler-x86-shared.cpp b/js/src/jit/x86-shared/Assembler-x86-shared.cpp index 99056b8b7e05..e280085b2d32 100644 --- a/js/src/jit/x86-shared/Assembler-x86-shared.cpp +++ b/js/src/jit/x86-shared/Assembler-x86-shared.cpp @@ -137,7 +137,7 @@ AssemblerX86Shared::processCodeLabels(uint8_t* rawCode) { for (size_t i = 0; i < codeLabels_.length(); i++) { CodeLabel label = codeLabels_[i]; - Bind(rawCode, label.patchAt(), rawCode + label.target()->offset()); + Bind(rawCode, *label.patchAt(), *label.target()); } } diff --git a/js/src/jit/x86-shared/Assembler-x86-shared.h b/js/src/jit/x86-shared/Assembler-x86-shared.h index e3e1a5399887..3ccc168ad551 100644 --- a/js/src/jit/x86-shared/Assembler-x86-shared.h +++ b/js/src/jit/x86-shared/Assembler-x86-shared.h @@ -1012,18 +1012,13 @@ class AssemblerX86Shared : public AssemblerShared label->reset(); } - static void Bind(uint8_t* raw, CodeOffset* label, const void* address) { - if (label->bound()) { - intptr_t offset = label->offset(); - X86Encoding::SetPointer(raw + offset, address); + static void Bind(uint8_t* raw, CodeOffset label, CodeOffset target) { + if (label.bound()) { + intptr_t offset = label.offset(); + X86Encoding::SetPointer(raw + offset, raw + target.offset()); } } - // See Bind and X86Encoding::setPointer. - size_t labelToPatchOffset(CodeOffset label) { - return label.offset() - sizeof(void*); - } - void ret() { masm.ret(); } @@ -3656,10 +3651,6 @@ class AssemblerX86Shared : public AssemblerShared PatchDataWithValueCheck(data, PatchedImmPtr(newData.value), PatchedImmPtr(expectedData.value)); } - static void PatchInstructionImmediate(uint8_t* code, PatchedImmPtr imm) { - MOZ_CRASH("Unused."); - } - static uint32_t NopSize() { return 1; } diff --git a/js/src/wasm/WasmCode.cpp b/js/src/wasm/WasmCode.cpp index db247e2934a5..12fc7f87f6d8 100644 --- a/js/src/wasm/WasmCode.cpp +++ b/js/src/wasm/WasmCode.cpp @@ -89,12 +89,9 @@ static bool StaticallyLink(const CodeSegment& cs, const LinkDataTier& linkData) { for (LinkDataTier::InternalLink link : linkData.internalLinks) { - uint8_t* patchAt = cs.base() + link.patchAtOffset; - void* target = cs.base() + link.targetOffset; - if (link.isRawPointerPatch()) - *(void**)(patchAt) = target; - else - Assembler::PatchInstructionImmediate(patchAt, PatchedImmPtr(target)); + CodeOffset patchAt(link.patchAtOffset); + CodeOffset target(link.targetOffset); + Assembler::Bind(cs.base(), patchAt, target); } if (!EnsureBuiltinThunksInitialized()) @@ -121,12 +118,9 @@ static void StaticallyUnlink(uint8_t* base, const LinkDataTier& linkData) { for (LinkDataTier::InternalLink link : linkData.internalLinks) { - uint8_t* patchAt = base + link.patchAtOffset; - void* target = 0; - if (link.isRawPointerPatch()) - *(void**)(patchAt) = target; - else - Assembler::PatchInstructionImmediate(patchAt, PatchedImmPtr(target)); + CodeOffset patchAt(link.patchAtOffset); + CodeOffset target(-size_t(base)); // to reset immediate to null + Assembler::Bind(base, patchAt, target); } for (auto imm : MakeEnumeratedRange(SymbolicAddress::Limit)) { diff --git a/js/src/wasm/WasmGenerator.cpp b/js/src/wasm/WasmGenerator.cpp index a91480b84ef6..b3e26eea3b8a 100644 --- a/js/src/wasm/WasmGenerator.cpp +++ b/js/src/wasm/WasmGenerator.cpp @@ -629,8 +629,8 @@ ModuleGenerator::finishLinkData() // SIMD values in the constant pool. for (size_t i = 0; i < masm_.numCodeLabels(); i++) { CodeLabel cl = masm_.codeLabel(i); - LinkDataTier::InternalLink inLink(LinkDataTier::InternalLink::CodeLabel); - inLink.patchAtOffset = masm_.labelToPatchOffset(*cl.patchAt()); + LinkDataTier::InternalLink inLink; + inLink.patchAtOffset = cl.patchAt()->offset(); inLink.targetOffset = cl.target()->offset(); if (!linkDataTier_->internalLinks.append(inLink)) return false; diff --git a/js/src/wasm/WasmModule.cpp b/js/src/wasm/WasmModule.cpp index 353ca312d012..09301e7f080b 100644 --- a/js/src/wasm/WasmModule.cpp +++ b/js/src/wasm/WasmModule.cpp @@ -41,34 +41,6 @@ using namespace js::wasm; using mozilla::IsNaN; -#if defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) -// On MIPS, CodeLabels are instruction immediates so InternalLinks only -// patch instruction immediates. -LinkDataTier::InternalLink::InternalLink(Kind kind) -{ - MOZ_ASSERT(kind == CodeLabel || kind == InstructionImmediate); -} - -bool -LinkDataTier::InternalLink::isRawPointerPatch() -{ - return false; -} -#else -// On the rest, CodeLabels are raw pointers so InternalLinks only patch -// raw pointers. -LinkDataTier::InternalLink::InternalLink(Kind kind) -{ - MOZ_ASSERT(kind == CodeLabel || kind == RawPointer); -} - -bool -LinkDataTier::InternalLink::isRawPointerPatch() -{ - return true; -} -#endif - size_t LinkDataTier::SymbolicLinkArray::serializedSize() const { diff --git a/js/src/wasm/WasmModule.h b/js/src/wasm/WasmModule.h index 9d32d0393f22..f5b9adf1bf82 100644 --- a/js/src/wasm/WasmModule.h +++ b/js/src/wasm/WasmModule.h @@ -58,17 +58,8 @@ struct LinkDataTier : LinkDataTierCacheablePod const LinkDataTierCacheablePod& pod() const { return *this; } struct InternalLink { - enum Kind { - RawPointer, - CodeLabel, - InstructionImmediate - }; - MOZ_INIT_OUTSIDE_CTOR uint32_t patchAtOffset; - MOZ_INIT_OUTSIDE_CTOR uint32_t targetOffset; - - InternalLink() = default; - explicit InternalLink(Kind kind); - bool isRawPointerPatch(); + uint32_t patchAtOffset; + uint32_t targetOffset; }; typedef Vector InternalLinkVector; From 231c33a9fe1712ba0fbf2e10bec80bafb3dd83e4 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Fri, 22 Sep 2017 10:33:36 -0500 Subject: [PATCH 33/37] Bug 1329019 - Vector::podResizeToFit should update reserved (r=froydnj) MozReview-Commit-ID: CkoNRjxmjom --- mfbt/Vector.h | 12 ++++++++++++ mfbt/tests/TestVector.cpp | 30 ++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/mfbt/Vector.h b/mfbt/Vector.h index a4c9d99adfda..83c370fbc8ca 100644 --- a/mfbt/Vector.h +++ b/mfbt/Vector.h @@ -243,6 +243,15 @@ struct VectorImpl if (aV.usingInlineStorage() || aV.mLength == aV.mTail.mCapacity) { return; } + if (!aV.mLength) { + aV.free_(aV.mBegin); + aV.mBegin = aV.inlineStorage(); + aV.mTail.mCapacity = aV.kInlineCapacity; +#ifdef DEBUG + aV.mTail.mReserved = 0; +#endif + return; + } T* newbuf = aV.template pod_realloc(aV.mBegin, aV.mTail.mCapacity, aV.mLength); if (MOZ_UNLIKELY(!newbuf)) { @@ -250,6 +259,9 @@ struct VectorImpl } aV.mBegin = newbuf; aV.mTail.mCapacity = aV.mLength; +#ifdef DEBUG + aV.mTail.mReserved = aV.mLength; +#endif } }; diff --git a/mfbt/tests/TestVector.cpp b/mfbt/tests/TestVector.cpp index eb16d7e39059..90b7531fc8f1 100644 --- a/mfbt/tests/TestVector.cpp +++ b/mfbt/tests/TestVector.cpp @@ -23,6 +23,7 @@ struct mozilla::detail::VectorTesting static void testExtractRawBuffer(); static void testExtractOrCopyRawBuffer(); static void testInsert(); + static void testPodResizeToFit(); }; void @@ -397,6 +398,34 @@ mozilla::detail::VectorTesting::testInsert() MOZ_RELEASE_ASSERT(S::destructCount == 1); } +void +mozilla::detail::VectorTesting::testPodResizeToFit() +{ + // Vectors not using inline storage realloc capacity to exact length. + Vector v1; + MOZ_RELEASE_ASSERT(v1.reserve(10)); + v1.infallibleAppend(1); + MOZ_ASSERT(v1.length() == 1); + MOZ_ASSERT(v1.reserved() == 10); + MOZ_ASSERT(v1.capacity() >= 10); + v1.podResizeToFit(); + MOZ_ASSERT(v1.length() == 1); + MOZ_ASSERT(v1.reserved() == 1); + MOZ_ASSERT(v1.capacity() == 1); + + // Vectors using inline storage do nothing. + Vector v2; + MOZ_RELEASE_ASSERT(v2.reserve(2)); + v2.infallibleAppend(1); + MOZ_ASSERT(v2.length() == 1); + MOZ_ASSERT(v2.reserved() == 2); + MOZ_ASSERT(v2.capacity() == 2); + v2.podResizeToFit(); + MOZ_ASSERT(v2.length() == 1); + MOZ_ASSERT(v2.reserved() == 2); + MOZ_ASSERT(v2.capacity() == 2); +} + // Declare but leave (permanently) incomplete. struct Incomplete; @@ -450,4 +479,5 @@ main() VectorTesting::testExtractRawBuffer(); VectorTesting::testExtractOrCopyRawBuffer(); VectorTesting::testInsert(); + VectorTesting::testPodResizeToFit(); } From bb375a16d491915835032f95faa3b7533fa4c14b Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Fri, 22 Sep 2017 10:34:24 -0500 Subject: [PATCH 34/37] Bug 1329019 - Allow specifying capacity to Vector::replaceRawBuffer (r=froydnj) MozReview-Commit-ID: 9Eq6PR53n4i --- mfbt/Vector.h | 26 ++++++++++++--- mfbt/tests/TestVector.cpp | 70 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 4 deletions(-) diff --git a/mfbt/Vector.h b/mfbt/Vector.h index 83c370fbc8ca..f413e4c78b52 100644 --- a/mfbt/Vector.h +++ b/mfbt/Vector.h @@ -778,6 +778,17 @@ public: */ MOZ_MUST_USE T* extractOrCopyRawBuffer(); + /** + * Transfer ownership of an array of objects into the vector. The caller + * must have allocated the array in accordance with this vector's + * AllocPolicy. + * + * N.B. This call assumes that there are no uninitialized elements in the + * passed range [aP, aP + aLength). The range [aP + aLength, aP + + * aCapacity) must be allocated uninitialized memory. + */ + void replaceRawBuffer(T* aP, size_t aLength, size_t aCapacity); + /** * Transfer ownership of an array of objects into the vector. The caller * must have allocated the array in accordance with this vector's @@ -1493,7 +1504,7 @@ Vector::extractOrCopyRawBuffer() template inline void -Vector::replaceRawBuffer(T* aP, size_t aLength) +Vector::replaceRawBuffer(T* aP, size_t aLength, size_t aCapacity) { MOZ_REENTRANCY_GUARD_ET_AL; @@ -1504,7 +1515,7 @@ Vector::replaceRawBuffer(T* aP, size_t aLength) } /* Take in the new buffer. */ - if (aLength <= kInlineCapacity) { + if (aCapacity <= kInlineCapacity) { /* * We convert to inline storage if possible, even though aP might * otherwise be acceptable. Maybe this behaviour should be @@ -1519,13 +1530,20 @@ Vector::replaceRawBuffer(T* aP, size_t aLength) } else { mBegin = aP; mLength = aLength; - mTail.mCapacity = aLength; + mTail.mCapacity = aCapacity; } #ifdef DEBUG - mTail.mReserved = aLength; + mTail.mReserved = aCapacity; #endif } +template +inline void +Vector::replaceRawBuffer(T* aP, size_t aLength) +{ + replaceRawBuffer(aP, aLength, aLength); +} + template inline size_t Vector::sizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const diff --git a/mfbt/tests/TestVector.cpp b/mfbt/tests/TestVector.cpp index 90b7531fc8f1..53ba2ffc7c8b 100644 --- a/mfbt/tests/TestVector.cpp +++ b/mfbt/tests/TestVector.cpp @@ -22,6 +22,7 @@ struct mozilla::detail::VectorTesting static void testReverse(); static void testExtractRawBuffer(); static void testExtractOrCopyRawBuffer(); + static void testReplaceRawBuffer(); static void testInsert(); static void testPodResizeToFit(); }; @@ -357,6 +358,74 @@ mozilla::detail::VectorTesting::testExtractOrCopyRawBuffer() free(buf); } +void +mozilla::detail::VectorTesting::testReplaceRawBuffer() +{ + S::resetCounts(); + + S* s = nullptr; + + { + Vector v; + MOZ_RELEASE_ASSERT(v.reserve(4)); + v.infallibleEmplaceBack(1, 2); + v.infallibleEmplaceBack(3, 4); + MOZ_ASSERT(S::constructCount == 2); + s = v.extractRawBuffer(); + } + + MOZ_ASSERT(S::constructCount == 2); + MOZ_ASSERT(S::moveCount == 0); + MOZ_ASSERT(S::destructCount == 0); + + { + Vector v; + v.replaceRawBuffer(s, 2); + MOZ_ASSERT(v.length() == 2); + MOZ_ASSERT(v.reserved() == 2); + MOZ_ASSERT(v.capacity() == 10); + MOZ_ASSERT(v[0].j == 1); + MOZ_ASSERT(v[1].j == 3); + MOZ_ASSERT(S::destructCount == 2); + } + + MOZ_ASSERT(S::constructCount == 2); + MOZ_ASSERT(S::moveCount == 2); + MOZ_ASSERT(S::destructCount == 4); + + S::resetCounts(); + + { + Vector v; + MOZ_RELEASE_ASSERT(v.reserve(4)); + v.infallibleEmplaceBack(9, 10); + MOZ_ASSERT(S::constructCount == 1); + s = v.extractRawBuffer(); + MOZ_ASSERT(S::constructCount == 1); + MOZ_ASSERT(S::moveCount == 0); + } + + MOZ_ASSERT(S::destructCount == 0); + + { + Vector v; + v.replaceRawBuffer(s, 1, 4); + MOZ_ASSERT(v.length() == 1); + MOZ_ASSERT(v.reserved() == 4); + MOZ_ASSERT(v.capacity() == 4); + MOZ_ASSERT(v[0].j == 9); + for (size_t i = 0; i < 5; i++) + MOZ_RELEASE_ASSERT(v.emplaceBack(i, i)); + MOZ_ASSERT(v.length() == 6); + MOZ_ASSERT(v.reserved() == 6); + MOZ_ASSERT(S::constructCount == 6); + MOZ_ASSERT(S::moveCount == 4); + MOZ_ASSERT(S::destructCount == 4); + } + + MOZ_ASSERT(S::destructCount == 10); +} + void mozilla::detail::VectorTesting::testInsert() { @@ -478,6 +547,7 @@ main() VectorTesting::testReverse(); VectorTesting::testExtractRawBuffer(); VectorTesting::testExtractOrCopyRawBuffer(); + VectorTesting::testReplaceRawBuffer(); VectorTesting::testInsert(); VectorTesting::testPodResizeToFit(); } From bbe32a26fdf8388e537b6d590b5165cc0a9e22b9 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Fri, 22 Sep 2017 11:05:05 -0500 Subject: [PATCH 35/37] Bug 1329019 - Baldr: Only compute bytecode hash in debug mode (r=yury) MozReview-Commit-ID: GKxQzBznHJh --- js/src/jit-test/tests/debug/wasm-12.js | 2 +- js/src/wasm/WasmCode.cpp | 7 ++----- js/src/wasm/WasmCode.h | 5 +++-- js/src/wasm/WasmDebug.cpp | 22 +++++++++++++++------- js/src/wasm/WasmGenerator.cpp | 5 ++++- 5 files changed, 25 insertions(+), 16 deletions(-) diff --git a/js/src/jit-test/tests/debug/wasm-12.js b/js/src/jit-test/tests/debug/wasm-12.js index c6d782d15531..2b0b27d42ee7 100644 --- a/js/src/jit-test/tests/debug/wasm-12.js +++ b/js/src/jit-test/tests/debug/wasm-12.js @@ -5,6 +5,7 @@ if (!wasmDebuggingIsSupported()) quit(); var g = newGlobal(); +var dbg = new Debugger(g); g.eval(` function initWasm(s) { return new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(s))); } o1 = initWasm('(module (func) (export "" 0))'); @@ -19,7 +20,6 @@ function isValidWasmURL(url) { return /^wasm:(?:[^:]*:)*?[0-9a-f]{16}$/.test(url); } -var dbg = new Debugger(g); var foundScripts = dbg.findScripts().filter(isWasm); assertEq(foundScripts.length, 2); assertEq(isValidWasmURL(foundScripts[0].source.url), true); diff --git a/js/src/wasm/WasmCode.cpp b/js/src/wasm/WasmCode.cpp index 12fc7f87f6d8..3e01edae7841 100644 --- a/js/src/wasm/WasmCode.cpp +++ b/js/src/wasm/WasmCode.cpp @@ -559,8 +559,7 @@ Metadata::serializedSize() const SerializedPodVectorSize(tables) + SerializedPodVectorSize(funcNames) + SerializedPodVectorSize(customSections) + - filename.serializedSize() + - sizeof(hash); + filename.serializedSize(); } size_t @@ -592,7 +591,6 @@ Metadata::serialize(uint8_t* cursor) const cursor = SerializePodVector(cursor, funcNames); cursor = SerializePodVector(cursor, customSections); cursor = filename.serialize(cursor); - cursor = WriteBytes(cursor, hash, sizeof(hash)); return cursor; } @@ -606,8 +604,7 @@ Metadata::deserialize(const uint8_t* cursor) (cursor = DeserializePodVector(cursor, &tables)) && (cursor = DeserializePodVector(cursor, &funcNames)) && (cursor = DeserializePodVector(cursor, &customSections)) && - (cursor = filename.deserialize(cursor)) && - (cursor = ReadBytes(cursor, hash, sizeof(hash))); + (cursor = filename.deserialize(cursor)); debugEnabled = false; debugFuncArgTypes.clear(); debugFuncReturnTypes.clear(); diff --git a/js/src/wasm/WasmCode.h b/js/src/wasm/WasmCode.h index 7720b6ca3503..59950ba2e715 100644 --- a/js/src/wasm/WasmCode.h +++ b/js/src/wasm/WasmCode.h @@ -379,7 +379,8 @@ class Metadata : public ShareableBase, public MetadataCacheablePod explicit Metadata(UniqueMetadataTier tier, ModuleKind kind = ModuleKind::Wasm) : MetadataCacheablePod(kind), metadata1_(Move(tier)), - debugEnabled(false) + debugEnabled(false), + debugHash() {} virtual ~Metadata() {} @@ -406,12 +407,12 @@ class Metadata : public ShareableBase, public MetadataCacheablePod NameInBytecodeVector funcNames; CustomSectionVector customSections; CacheableChars filename; - ModuleHash hash; // Debug-enabled code is not serialized. bool debugEnabled; FuncArgTypesVector debugFuncArgTypes; FuncReturnTypesVector debugFuncReturnTypes; + ModuleHash debugHash; bool usesMemory() const { return UsesMemory(memoryUsage); } bool hasSharedMemory() const { return memoryUsage == MemoryUsage::Shared; } diff --git a/js/src/wasm/WasmDebug.cpp b/js/src/wasm/WasmDebug.cpp index acedc7e68a32..6a669c6a459b 100644 --- a/js/src/wasm/WasmDebug.cpp +++ b/js/src/wasm/WasmDebug.cpp @@ -612,9 +612,11 @@ DebugState::debugDisplayURL(JSContext* cx) const // - "wasm:" as protocol; // - URI encoded filename from metadata (if can be encoded), plus ":"; // - 64-bit hash of the module bytes (as hex dump). + js::StringBuffer result(cx); if (!result.append("wasm:")) return nullptr; + if (const char* filename = metadata().filename.get()) { js::StringBuffer filenamePrefix(cx); // EncodeURI returns false due to invalid chars or OOM -- fail only @@ -623,19 +625,25 @@ DebugState::debugDisplayURL(JSContext* cx) const if (!cx->isExceptionPending()) return nullptr; cx->clearPendingException(); // ignore invalid URI - } else if (!result.append(filenamePrefix.finishString()) || !result.append(":")) { + } else if (!result.append(filenamePrefix.finishString())) { return nullptr; } } - const ModuleHash& hash = metadata().hash; - for (size_t i = 0; i < sizeof(ModuleHash); i++) { - char digit1 = hash[i] / 16, digit2 = hash[i] % 16; - if (!result.append((char)(digit1 < 10 ? digit1 + '0' : digit1 + 'a' - 10))) - return nullptr; - if (!result.append((char)(digit2 < 10 ? digit2 + '0' : digit2 + 'a' - 10))) + if (metadata().debugEnabled) { + if (!result.append(":")) return nullptr; + + const ModuleHash& hash = metadata().debugHash; + for (size_t i = 0; i < sizeof(ModuleHash); i++) { + char digit1 = hash[i] / 16, digit2 = hash[i] % 16; + if (!result.append((char)(digit1 < 10 ? digit1 + '0' : digit1 + 'a' - 10))) + return nullptr; + if (!result.append((char)(digit2 < 10 ? digit2 + '0' : digit2 + 'a' - 10))) + return nullptr; + } } + return result.finishString(); } diff --git a/js/src/wasm/WasmGenerator.cpp b/js/src/wasm/WasmGenerator.cpp index b3e26eea3b8a..ff8c6d86e765 100644 --- a/js/src/wasm/WasmGenerator.cpp +++ b/js/src/wasm/WasmGenerator.cpp @@ -1100,11 +1100,14 @@ static_assert(sizeof(ModuleHash) <= sizeof(mozilla::SHA1Sum::Hash), void ModuleGenerator::generateBytecodeHash(const ShareableBytes& bytecode) { + if (!env_->debugEnabled()) + return; + mozilla::SHA1Sum::Hash hash; mozilla::SHA1Sum sha1Sum; sha1Sum.update(bytecode.begin(), bytecode.length()); sha1Sum.finish(hash); - memcpy(metadata_->hash, hash, sizeof(ModuleHash)); + memcpy(metadata_->debugHash, hash, sizeof(ModuleHash)); } bool From 65f6c844dc3e3013a6cd3f262ea20c54507f8e73 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Fri, 22 Sep 2017 11:05:25 -0500 Subject: [PATCH 36/37] Bug 1329019 - Baldr: Split CallSiteAndTarget into CallSite and CallSiteTarget (r=lth) MozReview-Commit-ID: 8pBMZHnHcIf --- js/src/jit/shared/Assembler-shared.h | 43 +++++++++++++++----- js/src/wasm/WasmGenerator.cpp | 32 +++++++-------- js/src/wasm/WasmTypes.h | 60 ++++++++++++++++++---------- 3 files changed, 87 insertions(+), 48 deletions(-) diff --git a/js/src/jit/shared/Assembler-shared.h b/js/src/jit/shared/Assembler-shared.h index 50445ff7edee..a3b0499c1b56 100644 --- a/js/src/jit/shared/Assembler-shared.h +++ b/js/src/jit/shared/Assembler-shared.h @@ -807,7 +807,8 @@ namespace jit { // The base class of all Assemblers for all archs. class AssemblerShared { - wasm::CallSiteAndTargetVector callSites_; + wasm::CallSiteVector callSites_; + wasm::CallSiteTargetVector callSiteTargets_; wasm::CallFarJumpVector callFarJumps_; wasm::TrapSiteVector trapSites_; wasm::TrapFarJumpVector trapFarJumps_; @@ -843,31 +844,48 @@ class AssemblerShared } template - void append(const wasm::CallSiteDesc& desc, CodeOffset retAddr, Args&&... args) - { - wasm::CallSite cs(desc, retAddr.offset()); - enoughMemory_ &= callSites_.emplaceBack(cs, mozilla::Forward(args)...); + void append(const wasm::CallSiteDesc& desc, CodeOffset retAddr, Args&&... args) { + enoughMemory_ &= callSites_.emplaceBack(desc, retAddr.offset()); + enoughMemory_ &= callSiteTargets_.emplaceBack(mozilla::Forward(args)...); + } + const wasm::CallSiteVector& callSites() const { + return callSites_; + } + const wasm::CallSiteTargetVector& callSiteTargets() const { + return callSiteTargets_; + } + wasm::CallSiteVector&& extractCallSites() { + return Move(callSites_); } - wasm::CallSiteAndTargetVector& callSites() { return callSites_; } void append(wasm::CallFarJump jmp) { enoughMemory_ &= callFarJumps_.append(jmp); } - const wasm::CallFarJumpVector& callFarJumps() const { return callFarJumps_; } + const wasm::CallFarJumpVector& callFarJumps() const { + return callFarJumps_; + } void append(wasm::TrapSite trapSite) { enoughMemory_ &= trapSites_.append(trapSite); } - const wasm::TrapSiteVector& trapSites() const { return trapSites_; } + const wasm::TrapSiteVector& trapSites() const { + return trapSites_; + } void clearTrapSites() { trapSites_.clear(); } void append(wasm::TrapFarJump jmp) { enoughMemory_ &= trapFarJumps_.append(jmp); } - const wasm::TrapFarJumpVector& trapFarJumps() const { return trapFarJumps_; } + const wasm::TrapFarJumpVector& trapFarJumps() const { + return trapFarJumps_; + } - void append(wasm::MemoryAccess access) { enoughMemory_ &= memoryAccesses_.append(access); } - wasm::MemoryAccessVector&& extractMemoryAccesses() { return Move(memoryAccesses_); } + void append(wasm::MemoryAccess access) { + enoughMemory_ &= memoryAccesses_.append(access); + } + wasm::MemoryAccessVector&& extractMemoryAccesses() { + return Move(memoryAccesses_); + } void append(const wasm::MemoryAccessDesc& access, size_t codeOffset, size_t framePushed) { if (access.hasTrap()) { @@ -912,6 +930,9 @@ class AssemblerShared for (; i < callSites_.length(); i++) callSites_[i].offsetReturnAddressBy(delta); + enoughMemory_ &= callSiteTargets_.appendAll(other.callSiteTargets_); + // Nothing to offset. + MOZ_ASSERT(other.trapSites_.empty(), "should have been cleared by wasmEmitTrapOutOfLineCode"); i = callFarJumps_.length(); diff --git a/js/src/wasm/WasmGenerator.cpp b/js/src/wasm/WasmGenerator.cpp index ff8c6d86e765..4a80a2eda85c 100644 --- a/js/src/wasm/WasmGenerator.cpp +++ b/js/src/wasm/WasmGenerator.cpp @@ -289,17 +289,19 @@ ModuleGenerator::patchCallSites() EnumeratedArray> existingTrapFarJumps; for (; lastPatchedCallsite_ < masm_.callSites().length(); lastPatchedCallsite_++) { - const CallSiteAndTarget& cs = masm_.callSites()[lastPatchedCallsite_]; - uint32_t callerOffset = cs.returnAddressOffset(); + const CallSite& callSite = masm_.callSites()[lastPatchedCallsite_]; + const CallSiteTarget& target = masm_.callSiteTargets()[lastPatchedCallsite_]; + + uint32_t callerOffset = callSite.returnAddressOffset(); MOZ_RELEASE_ASSERT(callerOffset < INT32_MAX); - switch (cs.kind()) { + switch (callSite.kind()) { case CallSiteDesc::Dynamic: case CallSiteDesc::Symbolic: break; case CallSiteDesc::Func: { - if (funcIsCompiled(cs.funcIndex())) { - uint32_t calleeOffset = funcCodeRange(cs.funcIndex()).funcNormalEntry(); + if (funcIsCompiled(target.funcIndex())) { + uint32_t calleeOffset = funcCodeRange(target.funcIndex()).funcNormalEntry(); MOZ_RELEASE_ASSERT(calleeOffset < INT32_MAX); if (uint32_t(abs(int32_t(calleeOffset) - int32_t(callerOffset))) < JumpRange()) { @@ -308,18 +310,18 @@ ModuleGenerator::patchCallSites() } } - OffsetMap::AddPtr p = existingCallFarJumps.lookupForAdd(cs.funcIndex()); + OffsetMap::AddPtr p = existingCallFarJumps.lookupForAdd(target.funcIndex()); if (!p) { Offsets offsets; offsets.begin = masm_.currentOffset(); - masm_.append(CallFarJump(cs.funcIndex(), masm_.farJumpWithPatch())); + masm_.append(CallFarJump(target.funcIndex(), masm_.farJumpWithPatch())); offsets.end = masm_.currentOffset(); if (masm_.oom()) return false; if (!metadataTier_->codeRanges.emplaceBack(CodeRange::FarJumpIsland, offsets)) return false; - if (!existingCallFarJumps.add(p, cs.funcIndex(), offsets.begin)) + if (!existingCallFarJumps.add(p, target.funcIndex(), offsets.begin)) return false; } @@ -327,23 +329,23 @@ ModuleGenerator::patchCallSites() break; } case CallSiteDesc::TrapExit: { - if (!existingTrapFarJumps[cs.trap()]) { + if (!existingTrapFarJumps[target.trap()]) { // See MacroAssembler::wasmEmitTrapOutOfLineCode for why we must // reload the TLS register on this path. Offsets offsets; offsets.begin = masm_.currentOffset(); masm_.loadPtr(Address(FramePointer, offsetof(Frame, tls)), WasmTlsReg); - masm_.append(TrapFarJump(cs.trap(), masm_.farJumpWithPatch())); + masm_.append(TrapFarJump(target.trap(), masm_.farJumpWithPatch())); offsets.end = masm_.currentOffset(); if (masm_.oom()) return false; if (!metadataTier_->codeRanges.emplaceBack(CodeRange::FarJumpIsland, offsets)) return false; - existingTrapFarJumps[cs.trap()] = Some(offsets.begin); + existingTrapFarJumps[target.trap()] = Some(offsets.begin); } - masm_.patchCall(callerOffset, *existingTrapFarJumps[cs.trap()]); + masm_.patchCall(callerOffset, *existingTrapFarJumps[target.trap()]); break; } case CallSiteDesc::Breakpoint: @@ -1113,11 +1115,6 @@ ModuleGenerator::generateBytecodeHash(const ShareableBytes& bytecode) bool ModuleGenerator::finishMetadata(const ShareableBytes& bytecode) { - // Convert the CallSiteAndTargetVector (needed during generation) to a - // CallSiteVector (what is stored in the Module). - if (!metadataTier_->callSites.appendAll(masm_.callSites())) - return false; - // The MacroAssembler has accumulated all the memory accesses during codegen. metadataTier_->memoryAccesses = masm_.extractMemoryAccesses(); @@ -1148,6 +1145,7 @@ ModuleGenerator::finishMetadata(const ShareableBytes& bytecode) // These Vectors can get large and the excess capacity can be significant, // so realloc them down to size. + metadataTier_->callSites = masm_.extractCallSites(); metadataTier_->memoryAccesses.podResizeToFit(); metadataTier_->codeRanges.podResizeToFit(); metadataTier_->callSites.podResizeToFit(); diff --git a/js/src/wasm/WasmTypes.h b/js/src/wasm/WasmTypes.h index 4b4270e36ce2..429e4f3da56e 100644 --- a/js/src/wasm/WasmTypes.h +++ b/js/src/wasm/WasmTypes.h @@ -1156,33 +1156,53 @@ class CallSite : public CallSiteDesc WASM_DECLARE_POD_VECTOR(CallSite, CallSiteVector) -class CallSiteAndTarget : public CallSite +// A CallSiteTarget describes the callee of a CallSite, either a function or a +// trap exit. Although checked in debug builds, a CallSiteTarget doesn't +// officially know whether it targets a function or trap, relying on the Kind of +// the CallSite to discriminate. + +class CallSiteTarget { - uint32_t index_; + uint32_t packed_; +#ifdef DEBUG + enum Kind { None, FuncIndex, TrapExit } kind_; +#endif public: - explicit CallSiteAndTarget(CallSite cs) - : CallSite(cs) - { - MOZ_ASSERT(cs.kind() != Func); - } - CallSiteAndTarget(CallSite cs, uint32_t funcIndex) - : CallSite(cs), index_(funcIndex) - { - MOZ_ASSERT(cs.kind() == Func); - } - CallSiteAndTarget(CallSite cs, Trap trap) - : CallSite(cs), - index_(uint32_t(trap)) - { - MOZ_ASSERT(cs.kind() == TrapExit); + explicit CallSiteTarget() + : packed_(UINT32_MAX) +#ifdef DEBUG + , kind_(None) +#endif + {} + + explicit CallSiteTarget(uint32_t funcIndex) + : packed_(funcIndex) +#ifdef DEBUG + , kind_(FuncIndex) +#endif + {} + + explicit CallSiteTarget(Trap trap) + : packed_(uint32_t(trap)) +#ifdef DEBUG + , kind_(TrapExit) +#endif + {} + + uint32_t funcIndex() const { + MOZ_ASSERT(kind_ == FuncIndex); + return packed_; } - uint32_t funcIndex() const { MOZ_ASSERT(kind() == Func); return index_; } - Trap trap() const { MOZ_ASSERT(kind() == TrapExit); return Trap(index_); } + Trap trap() const { + MOZ_ASSERT(kind_ == TrapExit); + MOZ_ASSERT(packed_ < uint32_t(Trap::Limit)); + return Trap(packed_); + } }; -typedef Vector CallSiteAndTargetVector; +typedef Vector CallSiteTargetVector; // A wasm::SymbolicAddress represents a pointer to a well-known function that is // embedded in wasm code. Since wasm code is serialized and later deserialized From c5588947460ce3aa857db144ce8f1db1b0f5cc23 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Fri, 22 Sep 2017 11:05:38 -0500 Subject: [PATCH 37/37] Bug 1329019 - Baldr: don't transport MacroAssemblers between helper and ModuleGenerator threads (r=lth) MozReview-Commit-ID: 7OAc188WmzB --- js/src/jit/CodeGenerator.cpp | 1 - js/src/jit/Linker.cpp | 1 - js/src/jit/MacroAssembler-inl.h | 4 +- js/src/jit/MacroAssembler.cpp | 2 +- js/src/jit/arm/Assembler-arm.cpp | 28 +- js/src/jit/arm/Assembler-arm.h | 4 +- js/src/jit/arm/Simulator-arm.cpp | 12 +- js/src/jit/arm64/Assembler-arm64.h | 8 +- js/src/jit/arm64/vixl/MozSimulator-vixl.cpp | 21 +- .../jit/mips-shared/Assembler-mips-shared.cpp | 10 +- .../jit/mips-shared/Assembler-mips-shared.h | 13 +- js/src/jit/none/MacroAssembler-none.h | 2 +- js/src/jit/shared/Assembler-shared.h | 129 +--- .../IonAssemblerBufferWithConstantPools.h | 13 +- js/src/jit/x86-shared/Assembler-x86-shared.h | 12 +- .../x86-shared/AssemblerBuffer-x86-shared.cpp | 33 + .../x86-shared/AssemblerBuffer-x86-shared.h | 7 + .../jit/x86-shared/BaseAssembler-x86-shared.h | 10 +- .../x86-shared/MacroAssembler-x86-shared.cpp | 44 -- .../x86-shared/MacroAssembler-x86-shared.h | 4 +- js/src/vm/HelperThreads.h | 2 +- js/src/vm/Stack.cpp | 2 +- js/src/wasm/AsmJS.cpp | 2 +- js/src/wasm/WasmBaselineCompile.cpp | 85 +- js/src/wasm/WasmBaselineCompile.h | 10 +- js/src/wasm/WasmBuiltins.cpp | 22 +- js/src/wasm/WasmCode.cpp | 32 +- js/src/wasm/WasmCode.h | 42 +- js/src/wasm/WasmCompile.cpp | 23 +- js/src/wasm/WasmCompile.h | 6 + js/src/wasm/WasmFrameIter.cpp | 16 +- js/src/wasm/WasmGenerator.cpp | 729 +++++++++--------- js/src/wasm/WasmGenerator.h | 238 +++--- js/src/wasm/WasmIonCompile.cpp | 132 ++-- js/src/wasm/WasmIonCompile.h | 9 +- js/src/wasm/WasmModule.h | 7 +- js/src/wasm/WasmSignalHandlers.cpp | 28 +- js/src/wasm/WasmStubs.cpp | 229 ++++-- js/src/wasm/WasmStubs.h | 51 +- js/src/wasm/WasmTypes.cpp | 65 +- js/src/wasm/WasmTypes.h | 391 +++++----- 41 files changed, 1267 insertions(+), 1212 deletions(-) mode change 100755 => 100644 js/src/wasm/WasmSignalHandlers.cpp diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index ac123edf2ec9..f40573dd28d7 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -332,7 +332,6 @@ CodeGenerator::CodeGenerator(MIRGenerator* gen, LIRGraph* graph, MacroAssembler* CodeGenerator::~CodeGenerator() { - MOZ_ASSERT_IF(!gen->compilingWasm(), masm.numSymbolicAccesses() == 0); js_delete(scriptCounts_); } diff --git a/js/src/jit/Linker.cpp b/js/src/jit/Linker.cpp index 6038687f7d47..dc1f37c51b64 100644 --- a/js/src/jit/Linker.cpp +++ b/js/src/jit/Linker.cpp @@ -15,7 +15,6 @@ template JitCode* Linker::newCode(JSContext* cx, CodeKind kind, bool hasPatchableBackedges /* = false */) { - MOZ_ASSERT(masm.numSymbolicAccesses() == 0); MOZ_ASSERT_IF(hasPatchableBackedges, kind == ION_CODE); gc::AutoSuppressGC suppressGC(cx); diff --git a/js/src/jit/MacroAssembler-inl.h b/js/src/jit/MacroAssembler-inl.h index c48e6168901f..9d0acbfb4002 100644 --- a/js/src/jit/MacroAssembler-inl.h +++ b/js/src/jit/MacroAssembler-inl.h @@ -90,10 +90,10 @@ MacroAssembler::call(const wasm::CallSiteDesc& desc, const Register reg) } void -MacroAssembler::call(const wasm::CallSiteDesc& desc, uint32_t funcDefIndex) +MacroAssembler::call(const wasm::CallSiteDesc& desc, uint32_t funcIndex) { CodeOffset l = callWithPatch(); - append(desc, l, funcDefIndex); + append(desc, l, funcIndex); } void diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp index 6cab73f2e9e9..19cfce01cfa0 100644 --- a/js/src/jit/MacroAssembler.cpp +++ b/js/src/jit/MacroAssembler.cpp @@ -3136,7 +3136,7 @@ MacroAssembler::wasmEmitTrapOutOfLineCode() // iterator to find the right CodeRange while walking the stack. breakpoint(); - clearTrapSites(); + trapSites().clear(); } void diff --git a/js/src/jit/arm/Assembler-arm.cpp b/js/src/jit/arm/Assembler-arm.cpp index 988dc96c700e..c0cb7dfb450e 100644 --- a/js/src/jit/arm/Assembler-arm.cpp +++ b/js/src/jit/arm/Assembler-arm.cpp @@ -659,15 +659,31 @@ Assembler::finish() } bool -Assembler::asmMergeWith(Assembler& other) +Assembler::appendRawCode(const uint8_t* code, size_t numBytes) { flush(); - other.flush(); - if (other.oom()) + return m_buffer.appendRawCode(code, numBytes); +} + +bool +Assembler::reserve(size_t size) +{ + // This buffer uses fixed-size chunks so there's no point in reserving + // now vs. on-demand. + return !oom(); +} + +bool +Assembler::swapBuffer(wasm::Bytes& bytes) +{ + // For now, specialize to the one use case. As long as wasm::Bytes is a + // Vector, not a linked-list of chunks, there's not much we can do other + // than copy. + MOZ_ASSERT(bytes.empty()); + if (!bytes.resize(bytesNeeded())) return false; - if (!AssemblerShared::asmMergeWith(size(), other)) - return false; - return m_buffer.appendBuffer(other.m_buffer); + m_buffer.executableCopy(bytes.begin()); + return true; } void diff --git a/js/src/jit/arm/Assembler-arm.h b/js/src/jit/arm/Assembler-arm.h index 59bdb9311cb5..fc892eb0b669 100644 --- a/js/src/jit/arm/Assembler-arm.h +++ b/js/src/jit/arm/Assembler-arm.h @@ -1402,7 +1402,9 @@ class Assembler : public AssemblerShared bool isFinished; public: void finish(); - bool asmMergeWith(Assembler& other); + bool appendRawCode(const uint8_t* code, size_t numBytes); + bool reserve(size_t size); + bool swapBuffer(wasm::Bytes& bytes); void copyJumpRelocationTable(uint8_t* dest); void copyDataRelocationTable(uint8_t* dest); diff --git a/js/src/jit/arm/Simulator-arm.cpp b/js/src/jit/arm/Simulator-arm.cpp index e183e63c9379..096e066ef53f 100644 --- a/js/src/jit/arm/Simulator-arm.cpp +++ b/js/src/jit/arm/Simulator-arm.cpp @@ -1565,21 +1565,19 @@ Simulator::startInterrupt(WasmActivation* activation) void Simulator::handleWasmInterrupt() { - void* pc = (void*)get_pc(); + uint8_t* pc = (uint8_t*)get_pc(); uint8_t* fp = (uint8_t*)get_register(r11); - WasmActivation* activation = wasm::ActivationIfInnermost(cx_); - const wasm::CodeSegment* segment; - const wasm::Code* code = activation->compartment()->wasm.lookupCode(pc, &segment); - if (!code || !segment->containsFunctionPC(pc)) + const wasm::CodeSegment* cs = nullptr; + if (!wasm::InInterruptibleCode(cx_, pc, &cs)) return; // fp can be null during the prologue/epilogue of the entry function. if (!fp) return; - startInterrupt(activation); - set_pc(int32_t(segment->interruptCode())); + startInterrupt(wasm::ActivationIfInnermost(cx_)); + set_pc(int32_t(cs->interruptCode())); } // WebAssembly memories contain an extra region of guard pages (see diff --git a/js/src/jit/arm64/Assembler-arm64.h b/js/src/jit/arm64/Assembler-arm64.h index f1b1d6bfcf46..943b88527f3b 100644 --- a/js/src/jit/arm64/Assembler-arm64.h +++ b/js/src/jit/arm64/Assembler-arm64.h @@ -189,7 +189,13 @@ class Assembler : public vixl::Assembler typedef vixl::Condition Condition; void finish(); - bool asmMergeWith(const Assembler& other) { + bool appendRawCode(const uint8_t* code, size_t numBytes) { + MOZ_CRASH("NYI"); + } + bool reserve(size_t size) { + MOZ_CRASH("NYI"); + } + bool swapBuffer(wasm::Bytes& bytes) { MOZ_CRASH("NYI"); } void trace(JSTracer* trc); diff --git a/js/src/jit/arm64/vixl/MozSimulator-vixl.cpp b/js/src/jit/arm64/vixl/MozSimulator-vixl.cpp index 42f773e39580..ec8616ff4aef 100644 --- a/js/src/jit/arm64/vixl/MozSimulator-vixl.cpp +++ b/js/src/jit/arm64/vixl/MozSimulator-vixl.cpp @@ -32,7 +32,8 @@ #include "js/Utility.h" #include "threading/LockGuard.h" #include "vm/Runtime.h" -#include "wasm/WasmCode.h" +#include "wasm/WasmInstance.h" +#include "wasm/WasmSignalHandlers.h" js::jit::SimulatorProcess* js::jit::SimulatorProcess::singleton_ = nullptr; @@ -240,23 +241,25 @@ void Simulator::trigger_wasm_interrupt() { // the current PC may have advanced once since the signal handler's guard. So we // re-check here. void Simulator::handle_wasm_interrupt() { - void* pc = (void*)get_pc(); + uint8_t* pc = (uint8_t*)get_pc(); uint8_t* fp = (uint8_t*)xreg(30); - js::WasmActivation* activation = js::wasm::ActivationIfInnermost(cx_); - const js::wasm::CodeSegment* segment; - const js::wasm::Code* code = activation->compartment()->wasm.lookupCode(pc, &segment); - if (!code || !segment->containsFunctionPC(pc)) - return; + const js::wasm::CodeSegment* cs = nullptr; + if (!js::wasm::InInterruptibleCode(cx_, pc, &cs)) + return; + + // fp can be null during the prologue/epilogue of the entry function. + if (!fp) + return; JS::ProfilingFrameIterator::RegisterState state; state.pc = pc; state.fp = fp; state.lr = (uint8_t*) xreg(30); state.sp = (uint8_t*) xreg(31); - activation->startInterrupt(state); + js::wasm::ActivationIfInnermost(cx_)->startInterrupt(state); - set_pc((Instruction*)segment->interruptCode()); + set_pc((Instruction*)cs->interruptCode()); } diff --git a/js/src/jit/mips-shared/Assembler-mips-shared.cpp b/js/src/jit/mips-shared/Assembler-mips-shared.cpp index d0589cb6f217..44589526730b 100644 --- a/js/src/jit/mips-shared/Assembler-mips-shared.cpp +++ b/js/src/jit/mips-shared/Assembler-mips-shared.cpp @@ -96,15 +96,9 @@ AssemblerMIPSShared::finish() } bool -AssemblerMIPSShared::asmMergeWith(const AssemblerMIPSShared& other) +AssemblerMIPSShared::appendRawCode(const uint8_t* code, size_t numBytes) { - if (!AssemblerShared::asmMergeWith(size(), other)) - return false; - for (size_t i = 0; i < other.numLongJumps(); i++) { - size_t off = other.longJumps_[i]; - addLongJump(BufferOffset(size() + off)); - } - return m_buffer.appendBuffer(other.m_buffer); + return m_buffer.appendRawCode(code, numBytes); } uint32_t diff --git a/js/src/jit/mips-shared/Assembler-mips-shared.h b/js/src/jit/mips-shared/Assembler-mips-shared.h index 65014730b271..92791fe2cef5 100644 --- a/js/src/jit/mips-shared/Assembler-mips-shared.h +++ b/js/src/jit/mips-shared/Assembler-mips-shared.h @@ -748,16 +748,11 @@ class MIPSBufferWithExecutableCopy : public MIPSBuffer } } - bool appendBuffer(const MIPSBufferWithExecutableCopy& other) { + bool appendRawCode(const uint8_t* code, size_t numBytes) { if (this->oom()) return false; - - for (Slice* cur = other.head; cur != nullptr; cur = cur->getNext()) { - this->putBytes(cur->length(), &cur->instructions); - if (this->oom()) - return false; - } - return true; + this->putBytes(numBytes, code); + return !this->oom(); } }; @@ -958,7 +953,7 @@ class AssemblerMIPSShared : public AssemblerShared bool isFinished; public: void finish(); - bool asmMergeWith(const AssemblerMIPSShared& other); + bool appendRawCode(const uint8_t* code, size_t numBytes); void executableCopy(void* buffer, bool flushICache = true); void copyJumpRelocationTable(uint8_t* dest); void copyDataRelocationTable(uint8_t* dest); diff --git a/js/src/jit/none/MacroAssembler-none.h b/js/src/jit/none/MacroAssembler-none.h index fd25bc1207e4..f03a5a30e65d 100644 --- a/js/src/jit/none/MacroAssembler-none.h +++ b/js/src/jit/none/MacroAssembler-none.h @@ -187,7 +187,7 @@ class MacroAssemblerNone : public Assembler size_t numCodeLabels() const { MOZ_CRASH(); } CodeLabel codeLabel(size_t) { MOZ_CRASH(); } - bool asmMergeWith(const MacroAssemblerNone&) { MOZ_CRASH(); } + bool appendRawCode(const uint8_t* code, size_t numBytes) { MOZ_CRASH(); } void trace(JSTracer*) { MOZ_CRASH(); } static void TraceJumpRelocations(JSTracer*, JitCode*, CompactBufferReader&) { MOZ_CRASH(); } diff --git a/js/src/jit/shared/Assembler-shared.h b/js/src/jit/shared/Assembler-shared.h index a3b0499c1b56..fbb65820ac64 100644 --- a/js/src/jit/shared/Assembler-shared.h +++ b/js/src/jit/shared/Assembler-shared.h @@ -461,12 +461,16 @@ class CodeLabel CodeOffset* target() { return &target_; } - void offsetBy(size_t delta) { - patchAt_.offsetBy(delta); - target_.offsetBy(delta); + CodeOffset patchAt() const { + return patchAt_; + } + CodeOffset target() const { + return target_; } }; +typedef Vector CodeLabelVector; + // Location of a jump or label in a generated JitCode block, relative to the // start of the block. @@ -809,14 +813,14 @@ class AssemblerShared { wasm::CallSiteVector callSites_; wasm::CallSiteTargetVector callSiteTargets_; - wasm::CallFarJumpVector callFarJumps_; wasm::TrapSiteVector trapSites_; wasm::TrapFarJumpVector trapFarJumps_; + wasm::CallFarJumpVector callFarJumps_; wasm::MemoryAccessVector memoryAccesses_; wasm::SymbolicAccessVector symbolicAccesses_; protected: - Vector codeLabels_; + CodeLabelVector codeLabels_; bool enoughMemory_; bool embedsNurseryPointers_; @@ -843,50 +847,43 @@ class AssemblerShared return embedsNurseryPointers_; } + static bool canUseInSingleByteInstruction(Register reg) { + return true; + } + + void addCodeLabel(CodeLabel label) { + propagateOOM(codeLabels_.append(label)); + } + size_t numCodeLabels() const { + return codeLabels_.length(); + } + CodeLabel codeLabel(size_t i) { + return codeLabels_[i]; + } + CodeLabelVector& codeLabels() { + return codeLabels_; + } + + // WebAssembly metadata emitted by masm operations accumulated on the + // MacroAssembler, and swapped into a wasm::CompiledCode after finish(). + template void append(const wasm::CallSiteDesc& desc, CodeOffset retAddr, Args&&... args) { enoughMemory_ &= callSites_.emplaceBack(desc, retAddr.offset()); enoughMemory_ &= callSiteTargets_.emplaceBack(mozilla::Forward(args)...); } - const wasm::CallSiteVector& callSites() const { - return callSites_; - } - const wasm::CallSiteTargetVector& callSiteTargets() const { - return callSiteTargets_; - } - wasm::CallSiteVector&& extractCallSites() { - return Move(callSites_); - } - - void append(wasm::CallFarJump jmp) { - enoughMemory_ &= callFarJumps_.append(jmp); - } - const wasm::CallFarJumpVector& callFarJumps() const { - return callFarJumps_; - } - void append(wasm::TrapSite trapSite) { enoughMemory_ &= trapSites_.append(trapSite); } - const wasm::TrapSiteVector& trapSites() const { - return trapSites_; - } - void clearTrapSites() { trapSites_.clear(); } - void append(wasm::TrapFarJump jmp) { enoughMemory_ &= trapFarJumps_.append(jmp); } - const wasm::TrapFarJumpVector& trapFarJumps() const { - return trapFarJumps_; + void append(wasm::CallFarJump jmp) { + enoughMemory_ &= callFarJumps_.append(jmp); } - void append(wasm::MemoryAccess access) { enoughMemory_ &= memoryAccesses_.append(access); } - wasm::MemoryAccessVector&& extractMemoryAccesses() { - return Move(memoryAccesses_); - } - void append(const wasm::MemoryAccessDesc& access, size_t codeOffset, size_t framePushed) { if (access.hasTrap()) { // If a memory access is trapping (wasm, SIMD.js, Atomics), create a @@ -905,63 +902,17 @@ class AssemblerShared #endif } } - - void append(wasm::SymbolicAccess access) { enoughMemory_ &= symbolicAccesses_.append(access); } - size_t numSymbolicAccesses() const { return symbolicAccesses_.length(); } - wasm::SymbolicAccess symbolicAccess(size_t i) const { return symbolicAccesses_[i]; } - - static bool canUseInSingleByteInstruction(Register reg) { return true; } - - void addCodeLabel(CodeLabel label) { - propagateOOM(codeLabels_.append(label)); - } - size_t numCodeLabels() const { - return codeLabels_.length(); - } - CodeLabel codeLabel(size_t i) { - return codeLabels_[i]; + void append(wasm::SymbolicAccess access) { + enoughMemory_ &= symbolicAccesses_.append(access); } - // Merge this assembler with the other one, invalidating it, by shifting all - // offsets by a delta. - bool asmMergeWith(size_t delta, const AssemblerShared& other) { - size_t i = callSites_.length(); - enoughMemory_ &= callSites_.appendAll(other.callSites_); - for (; i < callSites_.length(); i++) - callSites_[i].offsetReturnAddressBy(delta); - - enoughMemory_ &= callSiteTargets_.appendAll(other.callSiteTargets_); - // Nothing to offset. - - MOZ_ASSERT(other.trapSites_.empty(), "should have been cleared by wasmEmitTrapOutOfLineCode"); - - i = callFarJumps_.length(); - enoughMemory_ &= callFarJumps_.appendAll(other.callFarJumps_); - for (; i < callFarJumps_.length(); i++) - callFarJumps_[i].offsetBy(delta); - - i = trapFarJumps_.length(); - enoughMemory_ &= trapFarJumps_.appendAll(other.trapFarJumps_); - for (; i < trapFarJumps_.length(); i++) - trapFarJumps_[i].offsetBy(delta); - - i = memoryAccesses_.length(); - enoughMemory_ &= memoryAccesses_.appendAll(other.memoryAccesses_); - for (; i < memoryAccesses_.length(); i++) - memoryAccesses_[i].offsetBy(delta); - - i = symbolicAccesses_.length(); - enoughMemory_ &= symbolicAccesses_.appendAll(other.symbolicAccesses_); - for (; i < symbolicAccesses_.length(); i++) - symbolicAccesses_[i].patchAt.offsetBy(delta); - - i = codeLabels_.length(); - enoughMemory_ &= codeLabels_.appendAll(other.codeLabels_); - for (; i < codeLabels_.length(); i++) - codeLabels_[i].offsetBy(delta); - - return !oom(); - } + wasm::CallSiteVector& callSites() { return callSites_; } + wasm::CallSiteTargetVector& callSiteTargets() { return callSiteTargets_; } + wasm::TrapSiteVector& trapSites() { return trapSites_; } + wasm::TrapFarJumpVector& trapFarJumps() { return trapFarJumps_; } + wasm::CallFarJumpVector& callFarJumps() { return callFarJumps_; } + wasm::MemoryAccessVector& memoryAccesses() { return memoryAccesses_; } + wasm::SymbolicAccessVector& symbolicAccesses() { return symbolicAccesses_; } }; } // namespace jit diff --git a/js/src/jit/shared/IonAssemblerBufferWithConstantPools.h b/js/src/jit/shared/IonAssemblerBufferWithConstantPools.h index 755ff136321a..a4b24834d92f 100644 --- a/js/src/jit/shared/IonAssemblerBufferWithConstantPools.h +++ b/js/src/jit/shared/IonAssemblerBufferWithConstantPools.h @@ -1126,17 +1126,18 @@ struct AssemblerBufferWithConstantPools : public AssemblerBufferoom()) return false; // The pools should have all been flushed, check. MOZ_ASSERT(pool_.numEntries() == 0); - for (Slice* cur = other.getHead(); cur != nullptr; cur = cur->getNext()) { - this->putBytes(cur->length(), &cur->instructions[0]); - if (this->oom()) - return false; + while (numBytes > SliceSize) { + this->putBytes(SliceSize, code); + numBytes -= SliceSize; + code += SliceSize; } - return true; + this->putBytes(numBytes, code); + return !this->oom(); } public: diff --git a/js/src/jit/x86-shared/Assembler-x86-shared.h b/js/src/jit/x86-shared/Assembler-x86-shared.h index 3ccc168ad551..cde3aa657b4f 100644 --- a/js/src/jit/x86-shared/Assembler-x86-shared.h +++ b/js/src/jit/x86-shared/Assembler-x86-shared.h @@ -403,6 +403,12 @@ class AssemblerX86Shared : public AssemblerShared jumpRelocations_.oom() || dataRelocations_.oom(); } + bool reserve(size_t size) { + return masm.reserve(size); + } + bool swapBuffer(wasm::Bytes& other) { + return masm.swapBuffer(other); + } void setPrinter(Sprinter* sp) { masm.setPrinter(sp); @@ -413,12 +419,6 @@ class AssemblerX86Shared : public AssemblerShared } void executableCopy(void* buffer); - bool asmMergeWith(const AssemblerX86Shared& other) { - MOZ_ASSERT(other.jumps_.length() == 0); - if (!AssemblerShared::asmMergeWith(masm.size(), other)) - return false; - return masm.appendBuffer(other.masm); - } void processCodeLabels(uint8_t* rawCode); void copyJumpRelocationTable(uint8_t* dest); void copyDataRelocationTable(uint8_t* dest); diff --git a/js/src/jit/x86-shared/AssemblerBuffer-x86-shared.cpp b/js/src/jit/x86-shared/AssemblerBuffer-x86-shared.cpp index 4c99a6a14a8c..5ca091070d12 100644 --- a/js/src/jit/x86-shared/AssemblerBuffer-x86-shared.cpp +++ b/js/src/jit/x86-shared/AssemblerBuffer-x86-shared.cpp @@ -10,6 +10,39 @@ #include "jsopcode.h" +using namespace js; +using namespace jit; + +bool +AssemblerBuffer::swap(Vector& bytes) +{ + // For now, specialize to the one use case. + MOZ_ASSERT(bytes.empty()); + + if (m_buffer.empty()) { + if (bytes.capacity() > m_buffer.capacity()) { + size_t newCapacity = bytes.capacity(); + uint8_t* newBuffer = bytes.extractRawBuffer(); + MOZ_ASSERT(newBuffer); + m_buffer.replaceRawBuffer((unsigned char*)newBuffer, 0, newCapacity); + } + return true; + } + + size_t newLength = m_buffer.length(); + size_t newCapacity = m_buffer.capacity(); + unsigned char* newBuffer = m_buffer.extractRawBuffer(); + + // NB: extractRawBuffer() only returns null if the Vector is using + // inline storage and thus a malloc would be needed. In this case, + // just make a simple copy. + if (!newBuffer) + return bytes.append(m_buffer.begin(), m_buffer.end()); + + bytes.replaceRawBuffer((uint8_t*)newBuffer, newLength, newCapacity); + return true; +} + #ifdef JS_JITSPEW void js::jit::GenericAssembler::spew(const char* fmt, va_list va) diff --git a/js/src/jit/x86-shared/AssemblerBuffer-x86-shared.h b/js/src/jit/x86-shared/AssemblerBuffer-x86-shared.h index 8ca9113530a9..fa921d91db26 100644 --- a/js/src/jit/x86-shared/AssemblerBuffer-x86-shared.h +++ b/js/src/jit/x86-shared/AssemblerBuffer-x86-shared.h @@ -125,6 +125,13 @@ namespace jit { return m_oom; } + bool reserve(size_t size) + { + return !m_oom && m_buffer.reserve(size); + } + + bool swap(Vector& bytes); + const unsigned char* buffer() const { MOZ_RELEASE_ASSERT(!m_oom); diff --git a/js/src/jit/x86-shared/BaseAssembler-x86-shared.h b/js/src/jit/x86-shared/BaseAssembler-x86-shared.h index 956619c033e1..7ef90882acbd 100644 --- a/js/src/jit/x86-shared/BaseAssembler-x86-shared.h +++ b/js/src/jit/x86-shared/BaseAssembler-x86-shared.h @@ -57,6 +57,8 @@ public: const unsigned char* buffer() const { return m_formatter.buffer(); } unsigned char* data() { return m_formatter.data(); } bool oom() const { return m_formatter.oom(); } + bool reserve(size_t size) { return m_formatter.reserve(size); } + bool swapBuffer(wasm::Bytes& other) { return m_formatter.swapBuffer(other); } void nop() { @@ -3873,11 +3875,9 @@ threeByteOpImmSimd("vblendps", VEX_PD, OP3_BLENDPS_VpsWpsIb, ESCAPE_3A, imm, off const unsigned char* src = m_formatter.buffer(); memcpy(dst, src, size()); } - MOZ_MUST_USE bool appendBuffer(const BaseAssembler& other) + MOZ_MUST_USE bool appendRawCode(const uint8_t* code, size_t numBytes) { - const unsigned char* buf = other.m_formatter.buffer(); - bool ret = m_formatter.append(buf, other.size()); - return ret; + return m_formatter.append(code, numBytes); } protected: @@ -5144,6 +5144,8 @@ threeByteOpImmSimd("vblendps", VEX_PD, OP3_BLENDPS_VpsWpsIb, ESCAPE_3A, imm, off const unsigned char* buffer() const { return m_buffer.buffer(); } unsigned char* data() { return m_buffer.data(); } bool oom() const { return m_buffer.oom(); } + bool reserve(size_t size) { return m_buffer.reserve(size); } + bool swapBuffer(wasm::Bytes& other) { return m_buffer.swap(other); } bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); } MOZ_MUST_USE bool append(const unsigned char* values, size_t size) diff --git a/js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp b/js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp index f2ae9467d0c1..2f321070f994 100644 --- a/js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp +++ b/js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp @@ -271,50 +271,6 @@ MacroAssemblerX86Shared::getSimdData(const SimdConstant& v) return getConstant(v, simdMap_, simds_); } -template -static bool -MergeConstants(size_t delta, const Vector& other, - Map& map, Vector& vec) -{ - typedef typename Map::AddPtr AddPtr; - if (!map.initialized() && !map.init()) - return false; - - for (const T& c : other) { - size_t index; - if (AddPtr p = map.lookupForAdd(c.value)) { - index = p->value(); - } else { - index = vec.length(); - if (!vec.append(T(c.value)) || !map.add(p, c.value, index)) - return false; - } - MacroAssemblerX86Shared::UsesVector& uses = vec[index].uses; - for (CodeOffset use : c.uses) { - use.offsetBy(delta); - if (!uses.append(use)) - return false; - } - } - - return true; -} - -bool -MacroAssemblerX86Shared::asmMergeWith(const MacroAssemblerX86Shared& other) -{ - size_t sizeBefore = masm.size(); - if (!Assembler::asmMergeWith(other)) - return false; - if (!MergeConstants(sizeBefore, other.doubles_, doubleMap_, doubles_)) - return false; - if (!MergeConstants(sizeBefore, other.floats_, floatMap_, floats_)) - return false; - if (!MergeConstants(sizeBefore, other.simds_, simdMap_, simds_)) - return false; - return true; -} - void MacroAssemblerX86Shared::minMaxDouble(FloatRegister first, FloatRegister second, bool canBeNaN, bool isMax) diff --git a/js/src/jit/x86-shared/MacroAssembler-x86-shared.h b/js/src/jit/x86-shared/MacroAssembler-x86-shared.h index 4471da75a91b..81fa34f0555f 100644 --- a/js/src/jit/x86-shared/MacroAssembler-x86-shared.h +++ b/js/src/jit/x86-shared/MacroAssembler-x86-shared.h @@ -100,7 +100,9 @@ class MacroAssemblerX86Shared : public Assembler MacroAssemblerX86Shared() { } - bool asmMergeWith(const MacroAssemblerX86Shared& other); + bool appendRawCode(const uint8_t* code, size_t numBytes) { + return masm.appendRawCode(code, numBytes); + } // Evaluate srcDest = minmax{Float32,Double}(srcDest, second). // Checks for NaN if canBeNaN is true. diff --git a/js/src/vm/HelperThreads.h b/js/src/vm/HelperThreads.h index 82f9ecaf97a3..899bdaf9b04c 100644 --- a/js/src/vm/HelperThreads.h +++ b/js/src/vm/HelperThreads.h @@ -56,7 +56,7 @@ enum class ParseTaskKind namespace wasm { -class CompileTask; +struct CompileTask; typedef Vector CompileTaskPtrVector; struct Tier2GeneratorTask diff --git a/js/src/vm/Stack.cpp b/js/src/vm/Stack.cpp index 0406195abd56..9916b0532449 100644 --- a/js/src/vm/Stack.cpp +++ b/js/src/vm/Stack.cpp @@ -1786,7 +1786,7 @@ WasmActivation::interrupted() const return false; DebugOnly fp = act->asWasm()->exitFP(); - MOZ_ASSERT(fp && fp->instance()->code().containsFunctionPC(pc)); + MOZ_ASSERT(fp && fp->instance()->code().containsCodePC(pc)); return true; } diff --git a/js/src/wasm/AsmJS.cpp b/js/src/wasm/AsmJS.cpp index 9e3b449ea3f9..b4510cee7666 100644 --- a/js/src/wasm/AsmJS.cpp +++ b/js/src/wasm/AsmJS.cpp @@ -1865,7 +1865,7 @@ class MOZ_STACK_CLASS ModuleValidator return false; } - return mg_.init(asmJSMetadata_.get()); + return mg_.init(/* codeSectionSize (ignored) = */ 0, asmJSMetadata_.get()); } JSContext* cx() const { return cx_; } diff --git a/js/src/wasm/WasmBaselineCompile.cpp b/js/src/wasm/WasmBaselineCompile.cpp index bf83cbb3f818..24355bdce4fb 100644 --- a/js/src/wasm/WasmBaselineCompile.cpp +++ b/js/src/wasm/WasmBaselineCompile.cpp @@ -570,7 +570,7 @@ class BaseCompiler const ModuleEnvironment& env_; BaseOpIter iter_; - const FuncCompileUnit& func_; + const FuncCompileInput& func_; size_t lastReadCallSite_; TempAllocator& alloc_; const ValTypeVector& locals_; // Types of parameters and locals @@ -645,7 +645,7 @@ class BaseCompiler public: BaseCompiler(const ModuleEnvironment& env, Decoder& decoder, - const FuncCompileUnit& func, + const FuncCompileInput& input, const ValTypeVector& locals, bool debugEnabled, TempAllocator* alloc, @@ -659,7 +659,7 @@ class BaseCompiler MOZ_MUST_USE bool emitFunction(); void emitInitStackLocals(); - const SigWithId& sig() const { return *env_.funcSigs[func_.index()]; } + const SigWithId& sig() const { return *env_.funcSigs[func_.index]; } // Used by some of the ScratchRegister implementations. operator MacroAssembler&() const { return masm; } @@ -2196,7 +2196,7 @@ class BaseCompiler void insertBreakablePoint(CallSiteDesc::Kind kind) { // The debug trap exit requires WasmTlsReg be loaded. However, since we // are emitting millions of these breakable points inline, we push this - // loading of TLS into the FarJumpIsland created by patchCallSites. + // loading of TLS into the FarJumpIsland created by linkCallSites. masm.nopPatchableToCall(CallSiteDesc(iter_.lastOpcodeOffset(), kind)); } @@ -2207,9 +2207,9 @@ class BaseCompiler void beginFunction() { JitSpew(JitSpew_Codegen, "# Emitting wasm baseline code"); - SigIdDesc sigId = env_.funcSigs[func_.index()]->id; + SigIdDesc sigId = env_.funcSigs[func_.index]->id; if (mode_ == CompileMode::Tier1) - GenerateFunctionPrologue(masm, localSize_, sigId, &offsets_, mode_, func_.index()); + GenerateFunctionPrologue(masm, localSize_, sigId, &offsets_, mode_, func_.index); else GenerateFunctionPrologue(masm, localSize_, sigId, &offsets_); @@ -2220,7 +2220,7 @@ class BaseCompiler if (debugEnabled_) { // Initialize funcIndex and flag fields of DebugFrame. size_t debugFrame = masm.framePushed() - DebugFrame::offsetOfFrame(); - masm.store32(Imm32(func_.index()), + masm.store32(Imm32(func_.index), Address(masm.getStackPointer(), debugFrame + DebugFrame::offsetOfFuncIndex())); masm.storePtr(ImmWord(0), Address(masm.getStackPointer(), debugFrame + DebugFrame::offsetOfFlagsWord())); @@ -2345,7 +2345,7 @@ class BaseCompiler MOZ_ASSERT(localSize_ >= debugFrameReserved); if (localSize_ > debugFrameReserved) masm.addToStackPtr(Imm32(localSize_ - debugFrameReserved)); - BytecodeOffset prologueTrapOffset(func_.lineOrBytecode()); + BytecodeOffset prologueTrapOffset(func_.lineOrBytecode); masm.jump(TrapDesc(prologueTrapOffset, Trap::StackOverflow, debugFrameReserved)); masm.bind(&returnLabel_); @@ -3663,8 +3663,8 @@ class BaseCompiler // Sundry helpers. uint32_t readCallSiteLineOrBytecode() { - if (!func_.callSiteLineNums().empty()) - return func_.callSiteLineNums()[lastReadCallSite_++]; + if (!func_.callSiteLineNums.empty()) + return func_.callSiteLineNums[lastReadCallSite_++]; return iter_.lastOpcodeOffset(); } @@ -7586,7 +7586,7 @@ BaseCompiler::emitInitStackLocals() BaseCompiler::BaseCompiler(const ModuleEnvironment& env, Decoder& decoder, - const FuncCompileUnit& func, + const FuncCompileInput& func, const ValTypeVector& locals, bool debugEnabled, TempAllocator* alloc, @@ -7707,7 +7707,7 @@ FuncOffsets BaseCompiler::finish() { MOZ_ASSERT(done(), "all bytes must be consumed"); - MOZ_ASSERT(func_.callSiteLineNums().length() == lastReadCallSite_); + MOZ_ASSERT(func_.callSiteLineNums.length() == lastReadCallSite_); masm.flushBuffer(); @@ -7743,37 +7743,54 @@ js::wasm::BaselineCanCompile() } bool -js::wasm::BaselineCompileFunction(CompileTask* task, FuncCompileUnit* func, UniqueChars* error) +js::wasm::BaselineCompileFunctions(const ModuleEnvironment& env, LifoAlloc& lifo, + const FuncCompileInputVector& inputs, CompiledCode* code, + UniqueChars* error) { - MOZ_ASSERT(task->tier() == Tier::Baseline); - MOZ_ASSERT(task->env().kind == ModuleKind::Wasm); - - Decoder d(func->begin(), func->end(), func->lineOrBytecode(), error); - - // Build the local types vector. - - ValTypeVector locals; - if (!locals.appendAll(task->env().funcSigs[func->index()]->args())) - return false; - if (!DecodeLocalEntries(d, task->env().kind, &locals)) - return false; + MOZ_ASSERT(env.tier() == Tier::Baseline); + MOZ_ASSERT(env.kind == ModuleKind::Wasm); // The MacroAssembler will sometimes access the jitContext. - JitContext jitContext(&task->alloc()); + TempAllocator alloc(&lifo); + JitContext jitContext(&alloc); + MOZ_ASSERT(IsCompilingWasm()); + MacroAssembler masm(MacroAssembler::WasmToken(), alloc); - // One-pass baseline compilation. - - BaseCompiler f(task->env(), d, *func, locals, task->debugEnabled(), &task->alloc(), - &task->masm(), task->mode()); - if (!f.init()) + // Swap in already-allocated empty vectors to avoid malloc/free. + MOZ_ASSERT(code->empty()); + if (!code->swap(masm)) return false; - if (!f.emitFunction()) + for (const FuncCompileInput& func : inputs) { + Decoder d(func.begin, func.end, func.lineOrBytecode, error); + + // Build the local types vector. + + ValTypeVector locals; + if (!locals.appendAll(env.funcSigs[func.index]->args())) + return false; + if (!DecodeLocalEntries(d, env.kind, &locals)) + return false; + + // One-pass baseline compilation. + + BaseCompiler f(env, d, func, locals, env.debugEnabled(), &alloc, &masm, env.mode()); + if (!f.init()) + return false; + + if (!f.emitFunction()) + return false; + + if (!code->codeRanges.emplaceBack(func.index, func.lineOrBytecode, f.finish())) + return false; + } + + masm.finish(); + if (masm.oom()) return false; - func->finish(f.finish()); - return true; + return code->swap(masm); } #undef INT_DIV_I64_CALLOUT diff --git a/js/src/wasm/WasmBaselineCompile.h b/js/src/wasm/WasmBaselineCompile.h index 9e621d8ccec6..db8ae7f42a94 100644 --- a/js/src/wasm/WasmBaselineCompile.h +++ b/js/src/wasm/WasmBaselineCompile.h @@ -20,22 +20,20 @@ #define asmjs_wasm_baseline_compile_h #include "wasm/WasmGenerator.h" -#include "wasm/WasmTypes.h" namespace js { namespace wasm { -class CompileTask; -class FuncCompileUnit; - // Return whether BaselineCompileFunction can generate code on the current device. // Note: asm.js is also currently not supported due to Atomics and SIMD. bool BaselineCanCompile(); // Generate adequate code quickly. -bool -BaselineCompileFunction(CompileTask* task, FuncCompileUnit* unit, UniqueChars* error); +MOZ_MUST_USE bool +BaselineCompileFunctions(const ModuleEnvironment& env, LifoAlloc& lifo, + const FuncCompileInputVector& inputs, CompiledCode* code, + UniqueChars* error); class BaseLocalIter { diff --git a/js/src/wasm/WasmBuiltins.cpp b/js/src/wasm/WasmBuiltins.cpp index d94e9181e350..8b114120b12d 100644 --- a/js/src/wasm/WasmBuiltins.cpp +++ b/js/src/wasm/WasmBuiltins.cpp @@ -833,9 +833,13 @@ wasm::EnsureBuiltinThunksInitialized() ABIFunctionType abiType; void* funcPtr = AddressOf(sym, &abiType); + ExitReason exitReason(sym); - CallableOffsets offset = GenerateBuiltinThunk(masm, abiType, exitReason, funcPtr); - if (masm.oom() || !thunks->codeRanges.emplaceBack(CodeRange::BuiltinThunk, offset)) + + CallableOffsets offsets; + if (!GenerateBuiltinThunk(masm, abiType, exitReason, funcPtr, &offsets)) + return false; + if (!thunks->codeRanges.emplaceBack(CodeRange::BuiltinThunk, offsets)) return false; } @@ -855,9 +859,13 @@ wasm::EnsureBuiltinThunksInitialized() ABIFunctionType abiType = typedNative.abiType; void* funcPtr = r.front().value(); + ExitReason exitReason = ExitReason::Fixed::BuiltinNative; - CallableOffsets offset = GenerateBuiltinThunk(masm, abiType, exitReason, funcPtr); - if (masm.oom() || !thunks->codeRanges.emplaceBack(CodeRange::BuiltinThunk, offset)) + + CallableOffsets offsets; + if (!GenerateBuiltinThunk(masm, abiType, exitReason, funcPtr, &offsets)) + return false; + if (!thunks->codeRanges.emplaceBack(CodeRange::BuiltinThunk, offsets)) return false; } @@ -878,11 +886,13 @@ wasm::EnsureBuiltinThunksInitialized() masm.processCodeLabels(thunks->codeBase); #ifdef DEBUG MOZ_ASSERT(masm.callSites().empty()); + MOZ_ASSERT(masm.callSiteTargets().empty()); MOZ_ASSERT(masm.callFarJumps().empty()); MOZ_ASSERT(masm.trapSites().empty()); MOZ_ASSERT(masm.trapFarJumps().empty()); - MOZ_ASSERT(masm.extractMemoryAccesses().empty()); - MOZ_ASSERT(!masm.numSymbolicAccesses()); + MOZ_ASSERT(masm.callFarJumps().empty()); + MOZ_ASSERT(masm.memoryAccesses().empty()); + MOZ_ASSERT(masm.symbolicAccesses().empty()); #endif ExecutableAllocator::cacheFlush(thunks->codeBase, thunks->codeSize); diff --git a/js/src/wasm/WasmCode.cpp b/js/src/wasm/WasmCode.cpp index 3e01edae7841..dbbd018a2030 100644 --- a/js/src/wasm/WasmCode.cpp +++ b/js/src/wasm/WasmCode.cpp @@ -197,8 +197,6 @@ CodeSegment::create(Tier tier, uint32_t padding = ComputeByteAlignment(bytesNeeded, gc::SystemPageSize()); uint32_t codeLength = bytesNeeded + padding; - MOZ_ASSERT(linkData.functionCodeLength < codeLength); - UniqueCodeBytes codeBytes = AllocateCodeBytes(codeLength); if (!codeBytes) return nullptr; @@ -266,10 +264,12 @@ CodeSegment::initialize(Tier tier, const Metadata& metadata) { MOZ_ASSERT(bytes_ == nullptr); + MOZ_ASSERT(linkData.interruptOffset); + MOZ_ASSERT(linkData.outOfBoundsOffset); + MOZ_ASSERT(linkData.unalignedAccessOffset); tier_ = tier; bytes_ = Move(codeBytes); - functionLength_ = linkData.functionCodeLength; length_ = codeLength; interruptCode_ = bytes_.get() + linkData.interruptOffset; outOfBoundsCode_ = bytes_.get() + linkData.outOfBoundsOffset; @@ -623,8 +623,8 @@ struct ProjectFuncIndex } }; -const FuncExport& -MetadataTier::lookupFuncExport(uint32_t funcIndex) const +FuncExport& +MetadataTier::lookupFuncExport(uint32_t funcIndex) { size_t match; if (!BinarySearch(ProjectFuncIndex(funcExports), 0, funcExports.length(), funcIndex, &match)) @@ -633,6 +633,12 @@ MetadataTier::lookupFuncExport(uint32_t funcIndex) const return funcExports[match]; } +const FuncExport& +MetadataTier::lookupFuncExport(uint32_t funcIndex) const +{ + return const_cast(this)->lookupFuncExport(funcIndex); +} + bool Metadata::getFuncName(const Bytes* maybeBytecode, uint32_t funcIndex, UTF8Bytes* name) const { @@ -730,20 +736,6 @@ Code::segment(Tier tier) const } } -bool -Code::containsFunctionPC(const void* pc, const CodeSegment** segmentp) const -{ - for (auto t : tiers()) { - const CodeSegment& cs = segment(t); - if (cs.containsFunctionPC(pc)) { - if (segmentp) - *segmentp = &cs; - return true; - } - } - return false; -} - bool Code::containsCodePC(const void* pc, const CodeSegment** segmentp) const { @@ -866,7 +858,7 @@ Code::lookupMemoryAccess(void* pc, const CodeSegment** segmentp) const if (BinarySearch(MemoryAccessOffset(memoryAccesses), lowerBound, upperBound, target, &match)) { - MOZ_ASSERT(segment(t).containsFunctionPC(pc)); + MOZ_ASSERT(segment(t).containsCodePC(pc)); if (segmentp) *segmentp = &segment(t); return &memoryAccesses[match]; diff --git a/js/src/wasm/WasmCode.h b/js/src/wasm/WasmCode.h index 59950ba2e715..d4e8cb4c4cfd 100644 --- a/js/src/wasm/WasmCode.h +++ b/js/src/wasm/WasmCode.h @@ -69,21 +69,15 @@ class CodeSegment typedef UniquePtr UniqueCodeBytes; static UniqueCodeBytes AllocateCodeBytes(uint32_t codeLength); - // How this code was compiled. - Tier tier_; - - // bytes_ points to a single allocation of executable machine code in - // the range [0, length_). The range [0, functionLength_) is - // the subrange of [0, length_) which contains function code. + Tier tier_; UniqueCodeBytes bytes_; - uint32_t functionLength_; uint32_t length_; // These are pointers into code for stubs used for asynchronous // signal-handler control-flow transfer. - uint8_t* interruptCode_; - uint8_t* outOfBoundsCode_; - uint8_t* unalignedAccessCode_; + uint8_t* interruptCode_; + uint8_t* outOfBoundsCode_; + uint8_t* unalignedAccessCode_; bool initialize(Tier tier, UniqueCodeBytes bytes, @@ -104,7 +98,6 @@ class CodeSegment CodeSegment() : tier_(Tier(-1)), - functionLength_(0), length_(0), interruptCode_(nullptr), outOfBoundsCode_(nullptr), @@ -132,15 +125,6 @@ class CodeSegment uint8_t* outOfBoundsCode() const { return outOfBoundsCode_; } uint8_t* unalignedAccessCode() const { return unalignedAccessCode_; } - // The range [0, functionBytes) is a subrange of [0, codeBytes) that - // contains only function body code, not the stub code. This distinction is - // used by the async interrupt handler to only interrupt when the pc is in - // function code which, in turn, simplifies reasoning about how stubs - // enter/exit. - - bool containsFunctionPC(const void* pc) const { - return pc >= base() && pc < (base() + functionLength_); - } bool containsCodePC(const void* pc) const { return pc >= base() && pc < (base() + length_); } @@ -173,19 +157,21 @@ class FuncExport public: FuncExport() = default; - explicit FuncExport(Sig&& sig, - uint32_t funcIndex, - uint32_t codeRangeIndex) + explicit FuncExport(Sig&& sig, uint32_t funcIndex) : sig_(Move(sig)) { pod.funcIndex_ = funcIndex; - pod.codeRangeIndex_ = codeRangeIndex; + pod.codeRangeIndex_ = UINT32_MAX; pod.entryOffset_ = UINT32_MAX; } void initEntryOffset(uint32_t entryOffset) { MOZ_ASSERT(pod.entryOffset_ == UINT32_MAX); pod.entryOffset_ = entryOffset; } + void initCodeRangeIndex(uint32_t codeRangeIndex) { + MOZ_ASSERT(pod.codeRangeIndex_ == UINT32_MAX); + pod.codeRangeIndex_ = codeRangeIndex; + } const Sig& sig() const { return sig_; @@ -194,6 +180,7 @@ class FuncExport return pod.funcIndex_; } uint32_t codeRangeIndex() const { + MOZ_ASSERT(pod.codeRangeIndex_ != UINT32_MAX); return pod.codeRangeIndex_; } uint32_t entryOffset() const { @@ -362,6 +349,7 @@ struct MetadataTier Uint32Vector debugTrapFarJumpOffsets; Uint32Vector debugFuncToCodeRange; + FuncExport& lookupFuncExport(uint32_t funcIndex); const FuncExport& lookupFuncExport(uint32_t funcIndex) const; WASM_DECLARE_SERIALIZABLE(MetadataTier); @@ -479,15 +467,11 @@ class Code : public ShareableBase const MetadataTier& metadata(Tier tier) const { return metadata_->metadata(tier); } const Metadata& metadata() const { return *metadata_; } - // Frame iterator support: + // Metadata lookup functions: const CallSite* lookupCallSite(void* returnAddress, const CodeSegment** segment = nullptr) const; const CodeRange* lookupRange(void* pc, const CodeSegment** segment = nullptr) const; const MemoryAccess* lookupMemoryAccess(void* pc, const CodeSegment** segment = nullptr) const; - - // Signal handling support: - - bool containsFunctionPC(const void* pc, const CodeSegment** segmentp = nullptr) const; bool containsCodePC(const void* pc, const CodeSegment** segmentp = nullptr) const; // To save memory, profilingLabels_ are generated lazily when profiling mode diff --git a/js/src/wasm/WasmCompile.cpp b/js/src/wasm/WasmCompile.cpp index 0cc473b6f92f..3a482f393055 100644 --- a/js/src/wasm/WasmCompile.cpp +++ b/js/src/wasm/WasmCompile.cpp @@ -134,7 +134,7 @@ enum class SystemClass }; static SystemClass -Classify() +ClassifySystem() { bool isDesktop; @@ -169,8 +169,6 @@ Classify() } } -#ifndef JS_64BIT - // Code sizes in machine code bytes per bytecode byte, again empirical except // where marked as "Guess". @@ -230,7 +228,18 @@ BaselineBytesPerBytecode(SystemClass cls) } } -#endif // !JS_64BIT +double +wasm::EstimateCompiledCodeSize(Tier tier, size_t bytecodeSize) +{ + SystemClass cls = ClassifySystem(); + switch (tier) { + case Tier::Baseline: + return double(bytecodeSize) * BaselineBytesPerBytecode(cls); + case Tier::Ion: + return double(bytecodeSize) * IonBytesPerBytecode(cls); + } + MOZ_CRASH("bad tier"); +} // If parallel Ion compilation is going to take longer than this, we should tier. @@ -337,7 +346,7 @@ GetTieringEnabled(uint32_t codeSize) uint32_t cores = Min(cpuCount, workers); - SystemClass cls = Classify(); + SystemClass cls = ClassifySystem(); // Ion compilation on available cores must take long enough to be worth the // bother. @@ -411,7 +420,7 @@ wasm::CompileInitialTier(const ShareableBytes& bytecode, const CompileArgs& args env.setModeAndTier(mode, tier); ModuleGenerator mg(args, &env, nullptr, error); - if (!mg.init()) + if (!mg.init(bytecode.length())) return nullptr; if (!DecodeCodeSection(d, mg, &env)) @@ -436,7 +445,7 @@ wasm::CompileTier2(Module& module, const CompileArgs& args, Atomic* cancel return false; ModuleGenerator mg(args, &env, cancelled, &error); - if (!mg.init()) + if (!mg.init(module.bytecode().length())) return false; if (!DecodeCodeSection(d, mg, &env)) diff --git a/js/src/wasm/WasmCompile.h b/js/src/wasm/WasmCompile.h index 1828af72ff09..1d0707cc7481 100644 --- a/js/src/wasm/WasmCompile.h +++ b/js/src/wasm/WasmCompile.h @@ -60,6 +60,12 @@ struct CompileArgs : ShareableBase typedef RefPtr MutableCompileArgs; typedef RefPtr SharedCompileArgs; +// Return the estimated compiled (machine) code size for the given bytecode size +// compiled at the given tier. + +double +EstimateCompiledCodeSize(Tier tier, size_t bytecodeSize); + // Compile the given WebAssembly bytecode with the given arguments into a // wasm::Module. On success, the Module is returned. On failure, the returned // SharedModule pointer is null and either: diff --git a/js/src/wasm/WasmFrameIter.cpp b/js/src/wasm/WasmFrameIter.cpp index 2ef886213a5e..439b729593f3 100644 --- a/js/src/wasm/WasmFrameIter.cpp +++ b/js/src/wasm/WasmFrameIter.cpp @@ -606,7 +606,8 @@ ProfilingFrameIterator::initFromExitFP() case CodeRange::BuiltinThunk: case CodeRange::TrapExit: case CodeRange::DebugTrap: - case CodeRange::Inline: + case CodeRange::OutOfBoundsExit: + case CodeRange::UnalignedExit: case CodeRange::Throw: case CodeRange::Interrupt: case CodeRange::FarJumpIsland: @@ -678,6 +679,7 @@ js::wasm::StartUnwinding(const WasmActivation& activation, const RegisterState& case CodeRange::ImportInterpExit: case CodeRange::BuiltinThunk: case CodeRange::TrapExit: + case CodeRange::DebugTrap: #if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) || defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) if (offsetFromEntry == BeforePushRetAddr || codeRange->isThunk()) { // The return address is still in lr and fp holds the caller's fp. @@ -737,9 +739,9 @@ js::wasm::StartUnwinding(const WasmActivation& activation, const RegisterState& break; } break; - case CodeRange::DebugTrap: - case CodeRange::Inline: - // Inline code stubs execute after the prologue/epilogue have completed + case CodeRange::OutOfBoundsExit: + case CodeRange::UnalignedExit: + // These code stubs execute after the prologue/epilogue have completed // so pc/fp contains the right values here. fixedPC = pc; fixedFP = fp; @@ -846,7 +848,8 @@ ProfilingFrameIterator::operator++() case CodeRange::BuiltinThunk: case CodeRange::TrapExit: case CodeRange::DebugTrap: - case CodeRange::Inline: + case CodeRange::OutOfBoundsExit: + case CodeRange::UnalignedExit: case CodeRange::FarJumpIsland: stackAddress_ = callerFP_; callerPC_ = callerFP_->returnAddress; @@ -1014,7 +1017,8 @@ ProfilingFrameIterator::label() const case CodeRange::ImportInterpExit: return importInterpDescription; case CodeRange::TrapExit: return trapDescription; case CodeRange::DebugTrap: return debugTrapDescription; - case CodeRange::Inline: return "inline stub (in wasm)"; + case CodeRange::OutOfBoundsExit: return "out-of-bounds stub (in wasm)"; + case CodeRange::UnalignedExit: return "unaligned trap stub (in wasm)"; case CodeRange::FarJumpIsland: return "interstitial (in wasm)"; case CodeRange::Throw: MOZ_FALLTHROUGH; case CodeRange::Interrupt: MOZ_CRASH("does not have a frame"); diff --git a/js/src/wasm/WasmGenerator.cpp b/js/src/wasm/WasmGenerator.cpp index 4a80a2eda85c..f9ae93fc47dd 100644 --- a/js/src/wasm/WasmGenerator.cpp +++ b/js/src/wasm/WasmGenerator.cpp @@ -38,6 +38,24 @@ using namespace js::wasm; using mozilla::CheckedInt; using mozilla::MakeEnumeratedRange; +bool +CompiledCode::swap(MacroAssembler& masm) +{ + MOZ_ASSERT(bytes.empty()); + if (!masm.swapBuffer(bytes)) + return false; + + callSites.swap(masm.callSites()); + callSiteTargets.swap(masm.callSiteTargets()); + trapSites.swap(masm.trapSites()); + callFarJumps.swap(masm.callFarJumps()); + trapFarJumps.swap(masm.trapFarJumps()); + memoryAccesses.swap(masm.memoryAccesses()); + symbolicAccesses.swap(masm.symbolicAccesses()); + codeLabels.swap(masm.codeLabels()); + return true; +} + // **************************************************************************** // ModuleGenerator @@ -54,22 +72,25 @@ ModuleGenerator::ModuleGenerator(const CompileArgs& args, ModuleEnvironment* env linkDataTier_(nullptr), metadataTier_(nullptr), taskState_(mutexid::WasmCompileTaskState), + numFuncDefs_(0), numSigs_(0), numTables_(0), lifo_(GENERATOR_LIFO_DEFAULT_CHUNK_SIZE), masmAlloc_(&lifo_), masm_(MacroAssembler::WasmToken(), masmAlloc_), - lastPatchedCallsite_(0), + trapCodeOffsets_(), + debugTrapCodeOffset_(), + lastPatchedCallSite_(0), startOfUnpatchedCallsites_(0), parallel_(false), outstanding_(0), currentTask_(nullptr), batchedBytecode_(0), startedFuncDefs_(false), - finishedFuncDefs_(false), - numFinishedFuncDefs_(0) + finishedFuncDefs_(false) { MOZ_ASSERT(IsCompilingWasm()); + std::fill(trapCodeOffsets_.begin(), trapCodeOffsets_.end(), 0); } ModuleGenerator::~ModuleGenerator() @@ -83,7 +104,7 @@ ModuleGenerator::~ModuleGenerator() { AutoLockHelperThreadState lock; CompileTaskPtrVector& worklist = HelperThreadState().wasmWorklist(lock, mode()); - auto pred = [this](CompileTask* task) { return &task->state() == &taskState_; }; + auto pred = [this](CompileTask* task) { return &task->state == &taskState_; }; size_t removed = EraseIf(worklist, pred); MOZ_ASSERT(outstanding_ >= removed); outstanding_ -= removed; @@ -142,7 +163,7 @@ ModuleGenerator::initAsmJS(Metadata* asmJSMetadata) } bool -ModuleGenerator::initWasm() +ModuleGenerator::initWasm(size_t codeSectionSize) { MOZ_ASSERT(!env_->isAsmJS()); @@ -162,11 +183,38 @@ ModuleGenerator::initWasm() MOZ_ASSERT(!isAsmJS()); - // For wasm, the Vectors are correctly-sized and already initialized. + // For wasm, the amount of code, functions, signatures, imports, exports, + // etc are known a priori. numSigs_ = env_->sigs.length(); numTables_ = env_->tables.length(); + // When estimating the MacroAssembler buffer size, be extra conservative + // since the price is low and the cost of an extra resize is high. + + if (!masm_.reserve(size_t(1.2 * EstimateCompiledCodeSize(tier(), codeSectionSize)))) + return false; + + // Although we could compute it more precisely (only the number of far jumps + // is unknown), 2x number of functions is a good conservative estimate and + // podResizeToFit will remove waste at the end. + + if (!metadataTier_->codeRanges.reserve(2 * env_->numFuncDefs())) + return false; + + // Code can vary a lot, so use a conservative estimate of 1 load/store/call/trap + // per 10 bytes of bytecode and rely on podResizeToFit() to remove waste. + + const size_t CallSitesPerByteCode = 10; + if (!metadataTier_->callSites.reserve(codeSectionSize / CallSitesPerByteCode)) + return false; + + const size_t MemoryAccessesPerByteCode = 10; + if (!metadataTier_->memoryAccesses.reserve(codeSectionSize / MemoryAccessesPerByteCode)) + return false; + + // Allocate space in TlsData for declarations that need it. + for (size_t i = 0; i < env_->funcImportGlobalDataOffsets.length(); i++) { env_->funcImportGlobalDataOffsets[i] = metadata_->globalDataLength; metadata_->globalDataLength += sizeof(FuncImportTls); @@ -206,6 +254,10 @@ ModuleGenerator::initWasm() return false; } + // Build a HashSet of all exported functions, whether by explicit export of + // the function, or implicitly by being an element of an external (imported + // or exported) table, or being the start function. + for (const Export& exp : env_->exports) { if (exp.kind() == DefinitionKind::Function) { if (!exportedFuncs_.put(exp.funcIndex())) @@ -223,7 +275,7 @@ ModuleGenerator::initWasm() } bool -ModuleGenerator::init(Metadata* maybeAsmJSMetadata) +ModuleGenerator::init(size_t codeSectionSize, Metadata* maybeAsmJSMetadata) { if (!funcToCodeRange_.appendN(BAD_CODE_RANGE, env_->funcSigs.length())) return false; @@ -234,7 +286,7 @@ ModuleGenerator::init(Metadata* maybeAsmJSMetadata) if (!exportedFuncs_.init()) return false; - if (env_->isAsmJS() ? !initAsmJS(maybeAsmJSMetadata) : !initWasm()) + if (env_->isAsmJS() ? !initAsmJS(maybeAsmJSMetadata) : !initWasm(codeSectionSize)) return false; if (compileArgs_->scriptedCaller.filename) { @@ -261,16 +313,24 @@ ModuleGenerator::funcCodeRange(uint32_t funcIndex) const return cr; } -static uint32_t -JumpRange() +static bool +InRange(uint32_t caller, uint32_t callee) { - return Min(JitOptions.jumpThreshold, JumpImmediateRange); + // We assume JumpImmediateRange is defined conservatively enough that the + // slight difference between 'caller' (which is really the return address + // offset) and the actual base of the relative displacement computation + // isn't significant. + uint32_t range = Min(JitOptions.jumpThreshold, JumpImmediateRange); + if (caller < callee) + return callee - caller < range; + return caller - callee < range; } typedef HashMap, SystemAllocPolicy> OffsetMap; +typedef EnumeratedArray> TrapOffsetArray; bool -ModuleGenerator::patchCallSites() +ModuleGenerator::linkCallSites() { masm_.haltingAlign(CodeAlignment); @@ -286,15 +346,12 @@ ModuleGenerator::patchCallSites() if (!existingCallFarJumps.init()) return false; - EnumeratedArray> existingTrapFarJumps; - - for (; lastPatchedCallsite_ < masm_.callSites().length(); lastPatchedCallsite_++) { - const CallSite& callSite = masm_.callSites()[lastPatchedCallsite_]; - const CallSiteTarget& target = masm_.callSiteTargets()[lastPatchedCallsite_]; + TrapOffsetArray existingTrapFarJumps; + for (; lastPatchedCallSite_ < metadataTier_->callSites.length(); lastPatchedCallSite_++) { + const CallSite& callSite = metadataTier_->callSites[lastPatchedCallSite_]; + const CallSiteTarget& target = callSiteTargets_[lastPatchedCallSite_]; uint32_t callerOffset = callSite.returnAddressOffset(); - MOZ_RELEASE_ASSERT(callerOffset < INT32_MAX); - switch (callSite.kind()) { case CallSiteDesc::Dynamic: case CallSiteDesc::Symbolic: @@ -302,9 +359,7 @@ ModuleGenerator::patchCallSites() case CallSiteDesc::Func: { if (funcIsCompiled(target.funcIndex())) { uint32_t calleeOffset = funcCodeRange(target.funcIndex()).funcNormalEntry(); - MOZ_RELEASE_ASSERT(calleeOffset < INT32_MAX); - - if (uint32_t(abs(int32_t(calleeOffset) - int32_t(callerOffset))) < JumpRange()) { + if (InRange(callerOffset, calleeOffset)) { masm_.patchCall(callerOffset, calleeOffset); break; } @@ -314,11 +369,11 @@ ModuleGenerator::patchCallSites() if (!p) { Offsets offsets; offsets.begin = masm_.currentOffset(); - masm_.append(CallFarJump(target.funcIndex(), masm_.farJumpWithPatch())); + if (!callFarJumps_.emplaceBack(target.funcIndex(), masm_.farJumpWithPatch())) + return false; offsets.end = masm_.currentOffset(); if (masm_.oom()) return false; - if (!metadataTier_->codeRanges.emplaceBack(CodeRange::FarJumpIsland, offsets)) return false; if (!existingCallFarJumps.add(p, target.funcIndex(), offsets.begin)) @@ -335,11 +390,11 @@ ModuleGenerator::patchCallSites() Offsets offsets; offsets.begin = masm_.currentOffset(); masm_.loadPtr(Address(FramePointer, offsetof(Frame, tls)), WasmTlsReg); - masm_.append(TrapFarJump(target.trap(), masm_.farJumpWithPatch())); + if (!trapFarJumps_.emplaceBack(target.trap(), masm_.farJumpWithPatch())) + return false; offsets.end = masm_.currentOffset(); if (masm_.oom()) return false; - if (!metadataTier_->codeRanges.emplaceBack(CodeRange::FarJumpIsland, offsets)) return false; existingTrapFarJumps[target.trap()] = Some(offsets.begin); @@ -352,19 +407,16 @@ ModuleGenerator::patchCallSites() case CallSiteDesc::EnterFrame: case CallSiteDesc::LeaveFrame: { Uint32Vector& jumps = metadataTier_->debugTrapFarJumpOffsets; - if (jumps.empty() || - uint32_t(abs(int32_t(jumps.back()) - int32_t(callerOffset))) >= JumpRange()) - { + if (jumps.empty() || !InRange(jumps.back(), callerOffset)) { // See BaseCompiler::insertBreakablePoint for why we must // reload the TLS register on this path. Offsets offsets; offsets.begin = masm_.currentOffset(); masm_.loadPtr(Address(FramePointer, offsetof(Frame, tls)), WasmTlsReg); - uint32_t jumpOffset = masm_.farJumpWithPatch().offset(); + CodeOffset jumpOffset = masm_.farJumpWithPatch(); offsets.end = masm_.currentOffset(); if (masm_.oom()) return false; - if (!metadataTier_->codeRanges.emplaceBack(CodeRange::FarJumpIsland, offsets)) return false; if (!debugTrapFarJumps_.emplaceBack(jumpOffset)) @@ -378,20 +430,130 @@ ModuleGenerator::patchCallSites() } masm_.flushBuffer(); + return !masm_.oom(); +} + +void +ModuleGenerator::noteCodeRange(uint32_t codeRangeIndex, const CodeRange& codeRange) +{ + switch (codeRange.kind()) { + case CodeRange::Function: + MOZ_ASSERT(funcToCodeRange_[codeRange.funcIndex()] == BAD_CODE_RANGE); + funcToCodeRange_[codeRange.funcIndex()] = codeRangeIndex; + break; + case CodeRange::Entry: + metadataTier_->lookupFuncExport(codeRange.funcIndex()).initEntryOffset(codeRange.begin()); + break; + case CodeRange::ImportJitExit: + metadataTier_->funcImports[codeRange.funcIndex()].initJitExitOffset(codeRange.begin()); + break; + case CodeRange::ImportInterpExit: + metadataTier_->funcImports[codeRange.funcIndex()].initInterpExitOffset(codeRange.begin()); + break; + case CodeRange::TrapExit: + MOZ_ASSERT(!trapCodeOffsets_[codeRange.trap()]); + trapCodeOffsets_[codeRange.trap()] = codeRange.begin(); + break; + case CodeRange::DebugTrap: + MOZ_ASSERT(!debugTrapCodeOffset_); + debugTrapCodeOffset_ = codeRange.begin(); + break; + case CodeRange::OutOfBoundsExit: + MOZ_ASSERT(!linkDataTier_->outOfBoundsOffset); + linkDataTier_->outOfBoundsOffset = codeRange.begin(); + break; + case CodeRange::UnalignedExit: + MOZ_ASSERT(!linkDataTier_->unalignedAccessOffset); + linkDataTier_->unalignedAccessOffset = codeRange.begin(); + break; + case CodeRange::Interrupt: + MOZ_ASSERT(!linkDataTier_->interruptOffset); + linkDataTier_->interruptOffset = codeRange.begin(); + break; + case CodeRange::Throw: + // Jumped to by other stubs, so nothing to do. + break; + case CodeRange::FarJumpIsland: + case CodeRange::BuiltinThunk: + MOZ_CRASH("Unexpected CodeRange kind"); + } +} + +template +static bool +AppendForEach(Vec* dstVec, const Vec& srcVec, Op op) +{ + if (!dstVec->growByUninitialized(srcVec.length())) + return false; + + typedef typename Vec::ElementType T; + + const T* src = srcVec.begin(); + + T* dstBegin = dstVec->begin(); + T* dstEnd = dstVec->end(); + T* dstStart = dstEnd - srcVec.length(); + + for (T* dst = dstStart; dst != dstEnd; dst++, src++) { + new(dst) T(*src); + op(dst - dstBegin, dst); + } + return true; } bool -ModuleGenerator::patchFarJumps(const TrapExitOffsetArray& trapExits, const Offsets& debugTrapStub) +ModuleGenerator::linkCompiledCode(const CompiledCode& code) { - for (const CallFarJump& farJump : masm_.callFarJumps()) - masm_.patchFarJump(farJump.jump, funcCodeRange(farJump.funcIndex).funcNormalEntry()); + // All code offsets in 'code' must be incremented by their position in the + // overall module when the code was appended. - for (const TrapFarJump& farJump : masm_.trapFarJumps()) - masm_.patchFarJump(farJump.jump, trapExits[farJump.trap].begin); + masm_.haltingAlign(CodeAlignment); + const size_t offsetInModule = masm_.size(); + if (!masm_.appendRawCode(code.bytes.begin(), code.bytes.length())) + return false; - for (uint32_t debugTrapFarJump : debugTrapFarJumps_) - masm_.patchFarJump(CodeOffset(debugTrapFarJump), debugTrapStub.begin); + auto codeRangeOp = [=](uint32_t codeRangeIndex, CodeRange* codeRange) { + codeRange->offsetBy(offsetInModule); + noteCodeRange(codeRangeIndex, *codeRange); + }; + if (!AppendForEach(&metadataTier_->codeRanges, code.codeRanges, codeRangeOp)) + return false; + + auto callSiteOp = [=](uint32_t, CallSite* cs) { cs->offsetBy(offsetInModule); }; + if (!AppendForEach(&metadataTier_->callSites, code.callSites, callSiteOp)) + return false; + + if (!callSiteTargets_.appendAll(code.callSiteTargets)) + return false; + + MOZ_ASSERT(code.trapSites.empty()); + + auto trapFarJumpOp = [=](uint32_t, TrapFarJump* tfj) { tfj->offsetBy(offsetInModule); }; + if (!AppendForEach(&trapFarJumps_, code.trapFarJumps, trapFarJumpOp)) + return false; + + auto callFarJumpOp = [=](uint32_t, CallFarJump* cfj) { cfj->offsetBy(offsetInModule); }; + if (!AppendForEach(&callFarJumps_, code.callFarJumps, callFarJumpOp)) + return false; + + auto memoryOp = [=](uint32_t, MemoryAccess* ma) { ma->offsetBy(offsetInModule); }; + if (!AppendForEach(&metadataTier_->memoryAccesses, code.memoryAccesses, memoryOp)) + return false; + + for (const SymbolicAccess& access : code.symbolicAccesses) { + uint32_t patchAt = offsetInModule + access.patchAt.offset(); + if (!linkDataTier_->symbolicLinks[access.target].append(patchAt)) + return false; + } + + for (const CodeLabel& codeLabel : code.codeLabels) { + LinkDataTier::InternalLink link; + link.patchAtOffset = offsetInModule + codeLabel.patchAt().offset(); + link.targetOffset = offsetInModule + codeLabel.target().offset(); + if (!linkDataTier_->internalLinks.append(link)) + return false; + } return true; } @@ -401,39 +563,22 @@ ModuleGenerator::finishTask(CompileTask* task) { masm_.haltingAlign(CodeAlignment); - // Before merging in the new function's code, if calls in a prior function - // body might go out of range, insert far jumps to extend the range. - if ((masm_.size() - startOfUnpatchedCallsites_) + task->masm().size() > JumpRange()) { + // Before merging in the new function's code, if calls in a prior code range + // might go out of range, insert far jumps to extend the range. + if (!InRange(startOfUnpatchedCallsites_, masm_.size() + task->output.bytes.length())) { startOfUnpatchedCallsites_ = masm_.size(); - if (!patchCallSites()) + if (!linkCallSites()) return false; } - uint32_t offsetInWhole = masm_.size(); - for (const FuncCompileUnit& func : task->units()) { - // Offset the recorded FuncOffsets by the offset of the function in the - // whole module's code segment. - FuncOffsets offsets = func.offsets(); - offsets.offsetBy(offsetInWhole); - - // Add the CodeRange for this function. - uint32_t funcCodeRangeIndex = metadataTier_->codeRanges.length(); - if (!metadataTier_->codeRanges.emplaceBack(func.index(), func.lineOrBytecode(), offsets)) - return false; - - MOZ_ASSERT(!funcIsCompiled(func.index())); - funcToCodeRange_[func.index()] = funcCodeRangeIndex; - } - - // Merge the compiled results into the whole-module masm. - mozilla::DebugOnly sizeBefore = masm_.size(); - if (!masm_.asmMergeWith(task->masm())) - return false; - MOZ_ASSERT(masm_.size() == offsetInWhole + task->masm().size()); - - if (!task->reset()) + if (!linkCompiledCode(task->output)) return false; + task->output.clear(); + + MOZ_ASSERT(task->inputs.empty()); + MOZ_ASSERT(task->output.empty()); + MOZ_ASSERT(task->lifo.isEmpty()); freeTasks_.infallibleAppend(task); return true; } @@ -475,167 +620,7 @@ ModuleGenerator::finishFuncExports() if (!sig.clone(funcSig(funcIndex))) return false; - uint32_t codeRangeIndex = funcToCodeRange_[funcIndex]; - metadataTier_->funcExports.infallibleEmplaceBack(Move(sig), funcIndex, codeRangeIndex); - } - - return true; -} - -typedef Vector OffsetVector; -typedef Vector CallableOffsetVector; - -bool -ModuleGenerator::finishCodegen() -{ - masm_.haltingAlign(CodeAlignment); - uint32_t offsetInWhole = masm_.size(); - - uint32_t numFuncExports = metadataTier_->funcExports.length(); - MOZ_ASSERT(numFuncExports == exportedFuncs_.count()); - - // Generate stubs in a separate MacroAssembler since, otherwise, for modules - // larger than the JumpImmediateRange, even local uses of Label will fail - // due to the large absolute offsets temporarily stored by Label::bind(). - - OffsetVector entries; - CallableOffsetVector interpExits; - CallableOffsetVector jitExits; - TrapExitOffsetArray trapExits; - Offsets outOfBoundsExit; - Offsets unalignedAccessExit; - Offsets interruptExit; - Offsets throwStub; - Offsets debugTrapStub; - - { - TempAllocator alloc(&lifo_); - MacroAssembler masm(MacroAssembler::WasmToken(), alloc); - Label throwLabel; - - if (!entries.resize(numFuncExports)) - return false; - for (uint32_t i = 0; i < numFuncExports; i++) - entries[i] = GenerateEntry(masm, metadataTier_->funcExports[i]); - - if (!interpExits.resize(numFuncImports())) - return false; - if (!jitExits.resize(numFuncImports())) - return false; - for (uint32_t i = 0; i < numFuncImports(); i++) { - interpExits[i] = GenerateImportInterpExit(masm, metadataTier_->funcImports[i], i, &throwLabel); - jitExits[i] = GenerateImportJitExit(masm, metadataTier_->funcImports[i], &throwLabel); - } - - for (Trap trap : MakeEnumeratedRange(Trap::Limit)) - trapExits[trap] = GenerateTrapExit(masm, trap, &throwLabel); - - outOfBoundsExit = GenerateOutOfBoundsExit(masm, &throwLabel); - unalignedAccessExit = GenerateUnalignedExit(masm, &throwLabel); - interruptExit = GenerateInterruptExit(masm, &throwLabel); - throwStub = GenerateThrowStub(masm, &throwLabel); - debugTrapStub = GenerateDebugTrapStub(masm, &throwLabel); - - if (masm.oom() || !masm_.asmMergeWith(masm)) - return false; - } - - // Adjust each of the resulting Offsets (to account for being merged into - // masm_) and then create code ranges for all the stubs. - - for (uint32_t i = 0; i < numFuncExports; i++) { - entries[i].offsetBy(offsetInWhole); - metadataTier_->funcExports[i].initEntryOffset(entries[i].begin); - if (!metadataTier_->codeRanges.emplaceBack(CodeRange::Entry, entries[i])) - return false; - } - - for (uint32_t i = 0; i < numFuncImports(); i++) { - interpExits[i].offsetBy(offsetInWhole); - metadataTier_->funcImports[i].initInterpExitOffset(interpExits[i].begin); - if (!metadataTier_->codeRanges.emplaceBack(CodeRange::ImportInterpExit, interpExits[i])) - return false; - - jitExits[i].offsetBy(offsetInWhole); - metadataTier_->funcImports[i].initJitExitOffset(jitExits[i].begin); - if (!metadataTier_->codeRanges.emplaceBack(CodeRange::ImportJitExit, jitExits[i])) - return false; - } - - for (Trap trap : MakeEnumeratedRange(Trap::Limit)) { - trapExits[trap].offsetBy(offsetInWhole); - if (!metadataTier_->codeRanges.emplaceBack(CodeRange::TrapExit, trapExits[trap])) - return false; - } - - outOfBoundsExit.offsetBy(offsetInWhole); - if (!metadataTier_->codeRanges.emplaceBack(CodeRange::Inline, outOfBoundsExit)) - return false; - - unalignedAccessExit.offsetBy(offsetInWhole); - if (!metadataTier_->codeRanges.emplaceBack(CodeRange::Inline, unalignedAccessExit)) - return false; - - interruptExit.offsetBy(offsetInWhole); - if (!metadataTier_->codeRanges.emplaceBack(CodeRange::Interrupt, interruptExit)) - return false; - - throwStub.offsetBy(offsetInWhole); - if (!metadataTier_->codeRanges.emplaceBack(CodeRange::Throw, throwStub)) - return false; - - debugTrapStub.offsetBy(offsetInWhole); - if (!metadataTier_->codeRanges.emplaceBack(CodeRange::DebugTrap, debugTrapStub)) - return false; - - // Fill in LinkData with the offsets of these stubs. - - linkDataTier_->unalignedAccessOffset = unalignedAccessExit.begin; - linkDataTier_->outOfBoundsOffset = outOfBoundsExit.begin; - linkDataTier_->interruptOffset = interruptExit.begin; - - // Now that all other code has been emitted, patch all remaining callsites - // then far jumps. Patching callsites can generate far jumps so there is an - // ordering dependency. - - if (!patchCallSites()) - return false; - - if (!patchFarJumps(trapExits, debugTrapStub)) - return false; - - // Code-generation is complete! - - masm_.finish(); - return !masm_.oom(); -} - -bool -ModuleGenerator::finishLinkData() -{ - // Inflate the global bytes up to page size so that the total bytes are a - // page size (as required by the allocator functions). - metadata_->globalDataLength = AlignBytes(metadata_->globalDataLength, gc::SystemPageSize()); - - // Add links to absolute addresses identified symbolically. - for (size_t i = 0; i < masm_.numSymbolicAccesses(); i++) { - SymbolicAccess src = masm_.symbolicAccess(i); - if (!linkDataTier_->symbolicLinks[src.target].append(src.patchAt.offset())) - return false; - } - - // Relative link metadata: absolute addresses that refer to another point within - // the asm.js module. - - // CodeLabels are used for switch cases and loads from floating-point / - // SIMD values in the constant pool. - for (size_t i = 0; i < masm_.numCodeLabels(); i++) { - CodeLabel cl = masm_.codeLabel(i); - LinkDataTier::InternalLink inLink; - inLink.patchAtOffset = cl.patchAt()->offset(); - inLink.targetOffset = cl.target()->offset(); - if (!linkDataTier_->internalLinks.append(inLink)) - return false; + metadataTier_->funcExports.infallibleEmplaceBack(Move(sig), funcIndex); } return true; @@ -791,15 +776,6 @@ ModuleGenerator::initImport(uint32_t funcIndex, uint32_t sigIndex) return addFuncImport(sig(sigIndex), globalDataOffset); } -uint32_t -ModuleGenerator::numFuncImports() const -{ - // Until all functions have been validated, asm.js doesn't know the total - // number of imports. - MOZ_ASSERT_IF(isAsmJS(), finishedFuncDefs_); - return metadataTier_->funcImports.length(); -} - const SigWithId& ModuleGenerator::funcSig(uint32_t funcIndex) const { @@ -842,20 +818,23 @@ ModuleGenerator::startFuncDefs() static bool ExecuteCompileTask(CompileTask* task, UniqueChars* error) { - switch (task->tier()) { + MOZ_ASSERT(task->lifo.isEmpty()); + MOZ_ASSERT(task->output.empty()); + + switch (task->env.tier()) { case Tier::Ion: - for (FuncCompileUnit& unit : task->units()) { - if (!IonCompileFunction(task, &unit, error)) - return false; - } + if (!IonCompileFunctions(task->env, task->lifo, task->inputs, &task->output, error)) + return false; break; case Tier::Baseline: - for (FuncCompileUnit& unit : task->units()) { - if (!BaselineCompileFunction(task, &unit, error)) - return false; - } + if (!BaselineCompileFunctions(task->env, task->lifo, task->inputs, &task->output, error)) + return false; break; } + + MOZ_ASSERT(task->lifo.isEmpty()); + MOZ_ASSERT(task->inputs.length() == task->output.codeRanges.length()); + task->inputs.clear(); return true; } @@ -868,7 +847,7 @@ wasm::ExecuteCompileTaskFromHelperThread(CompileTask* task) UniqueChars error; bool ok = ExecuteCompileTask(task, &error); - auto taskState = task->state().lock(); + auto taskState = task->state.lock(); if (!ok || !taskState->finished.append(task)) { taskState->numFailed++; @@ -887,9 +866,6 @@ ModuleGenerator::launchBatchCompile() if (cancelled_ && *cancelled_) return false; - size_t numBatchedFuncs = currentTask_->units().length(); - MOZ_ASSERT(numBatchedFuncs); - if (parallel_) { if (!StartOffThreadWasmCompile(currentTask_, mode())) return false; @@ -903,8 +879,6 @@ ModuleGenerator::launchBatchCompile() currentTask_ = nullptr; batchedBytecode_ = 0; - - numFinishedFuncDefs_ += numBatchedFuncs; return true; } @@ -945,6 +919,8 @@ ModuleGenerator::compileFuncDef(uint32_t funcIndex, uint32_t lineOrBytecode, MOZ_ASSERT(!finishedFuncDefs_); MOZ_ASSERT_IF(mode() == CompileMode::Tier1, funcIndex < env_->numFuncs()); + numFuncDefs_++; + if (!currentTask_) { if (freeTasks_.empty() && !finishOutstandingTask()) return false; @@ -953,8 +929,8 @@ ModuleGenerator::compileFuncDef(uint32_t funcIndex, uint32_t lineOrBytecode, uint32_t funcBytecodeLength = end - begin; - FuncCompileUnitVector& units = currentTask_->units(); - if (!units.emplaceBack(funcIndex, lineOrBytecode, Move(bytes), begin, end, Move(lineNums))) + FuncCompileInputVector& inputs = currentTask_->inputs; + if (!inputs.emplaceBack(funcIndex, lineOrBytecode, Move(bytes), begin, end, Move(lineNums))) return false; uint32_t threshold; @@ -997,62 +973,8 @@ ModuleGenerator::finishFuncDefs() return false; } - linkDataTier_->functionCodeLength = masm_.size(); + MOZ_ASSERT_IF(!isAsmJS(), numFuncDefs_ == env_->numFuncDefs()); finishedFuncDefs_ = true; - - // Generate wrapper functions for every import. These wrappers turn imports - // into plain functions so they can be put into tables and re-exported. - // asm.js cannot do either and so no wrappers are generated. - - if (!isAsmJS()) { - for (size_t funcIndex = 0; funcIndex < numFuncImports(); funcIndex++) { - const FuncImport& funcImport = metadataTier_->funcImports[funcIndex]; - const SigWithId& sig = funcSig(funcIndex); - - FuncOffsets offsets = GenerateImportFunction(masm_, funcImport, sig.id); - if (masm_.oom()) - return false; - - uint32_t codeRangeIndex = metadataTier_->codeRanges.length(); - if (!metadataTier_->codeRanges.emplaceBack(funcIndex, /* bytecodeOffset = */ 0, offsets)) - return false; - - MOZ_ASSERT(!funcIsCompiled(funcIndex)); - funcToCodeRange_[funcIndex] = codeRangeIndex; - } - } - - // All function indices should have an associated code range at this point - // (except in asm.js, which doesn't have import wrapper functions). - -#ifdef DEBUG - if (isAsmJS()) { - MOZ_ASSERT(numFuncImports() < AsmJSFirstDefFuncIndex); - for (uint32_t i = 0; i < AsmJSFirstDefFuncIndex; i++) - MOZ_ASSERT(funcToCodeRange_[i] == BAD_CODE_RANGE); - for (uint32_t i = AsmJSFirstDefFuncIndex; i < numFinishedFuncDefs_; i++) - MOZ_ASSERT(funcCodeRange(i).funcIndex() == i); - } else { - MOZ_ASSERT(numFinishedFuncDefs_ == env_->numFuncDefs()); - for (uint32_t i = 0; i < env_->numFuncs(); i++) - MOZ_ASSERT(funcCodeRange(i).funcIndex() == i); - } -#endif - - // Complete element segments with the code range index of every element, now - // that all functions have been compiled. - - for (ElemSegment& elems : env_->elemSegments) { - Uint32Vector& codeRangeIndices = elems.elemCodeRangeIndices(tier()); - - MOZ_ASSERT(codeRangeIndices.empty()); - if (!codeRangeIndices.reserve(elems.elemFuncIndices.length())) - return false; - - for (uint32_t funcIndex : elems.elemFuncIndices) - codeRangeIndices.infallibleAppend(funcToCodeRange_[funcIndex]); - } - return true; } @@ -1082,43 +1004,80 @@ ModuleGenerator::initSigTableElems(uint32_t sigIndex, Uint32Vector&& elemFuncInd uint32_t tableIndex = env_->asmJSSigToTableIndex[sigIndex]; MOZ_ASSERT(env_->tables[tableIndex].limits.initial == elemFuncIndices.length()); - Uint32Vector codeRangeIndices; - if (!codeRangeIndices.resize(elemFuncIndices.length())) - return false; - for (size_t i = 0; i < elemFuncIndices.length(); i++) - codeRangeIndices[i] = funcToCodeRange_[elemFuncIndices[i]]; - InitExpr offset(Val(uint32_t(0))); - if (!env_->elemSegments.emplaceBack(tableIndex, offset, Move(elemFuncIndices))) - return false; - - env_->elemSegments.back().elemCodeRangeIndices(tier()) = Move(codeRangeIndices); - return true; + return env_->elemSegments.emplaceBack(tableIndex, offset, Move(elemFuncIndices)); } -static_assert(sizeof(ModuleHash) <= sizeof(mozilla::SHA1Sum::Hash), - "The ModuleHash size shall not exceed the SHA1 hash size."); - -void -ModuleGenerator::generateBytecodeHash(const ShareableBytes& bytecode) +bool +ModuleGenerator::finishLinking() { - if (!env_->debugEnabled()) - return; + // All functions and traps CodeRanges should have been processed. - mozilla::SHA1Sum::Hash hash; - mozilla::SHA1Sum sha1Sum; - sha1Sum.update(bytecode.begin(), bytecode.length()); - sha1Sum.finish(hash); - memcpy(metadata_->debugHash, hash, sizeof(ModuleHash)); +#ifdef DEBUG + if (isAsmJS()) { + for (uint32_t i = 0; i < AsmJSFirstDefFuncIndex; i++) + MOZ_ASSERT(funcToCodeRange_[i] == BAD_CODE_RANGE); + for (uint32_t i = AsmJSFirstDefFuncIndex; i < AsmJSFirstDefFuncIndex + numFuncDefs_; i++) + MOZ_ASSERT(funcToCodeRange_[i] != BAD_CODE_RANGE); + for (uint32_t i = AsmJSFirstDefFuncIndex + numFuncDefs_; i < funcToCodeRange_.length(); i++) + MOZ_ASSERT(funcToCodeRange_[i] == BAD_CODE_RANGE); + } else { + for (uint32_t codeRangeIndex : funcToCodeRange_) + MOZ_ASSERT(codeRangeIndex != BAD_CODE_RANGE); + } +#endif + + // Now that all functions and stubs are generated and their CodeRanges + // known, patch all calls (which can emit far jumps) and far jumps. + + if (!linkCallSites()) + return false; + + for (CallFarJump far : callFarJumps_) + masm_.patchFarJump(far.jump, funcCodeRange(far.funcIndex).funcNormalEntry()); + + for (TrapFarJump far : trapFarJumps_) + masm_.patchFarJump(far.jump, trapCodeOffsets_[far.trap]); + + for (CodeOffset farJump : debugTrapFarJumps_) + masm_.patchFarJump(farJump, debugTrapCodeOffset_); + + // None of the linking or far-jump operations should emit masm metadata. + + MOZ_ASSERT(masm_.callSites().empty()); + MOZ_ASSERT(masm_.callSiteTargets().empty()); + MOZ_ASSERT(masm_.trapSites().empty()); + MOZ_ASSERT(masm_.trapFarJumps().empty()); + MOZ_ASSERT(masm_.callFarJumps().empty()); + MOZ_ASSERT(masm_.memoryAccesses().empty()); + MOZ_ASSERT(masm_.symbolicAccesses().empty()); + MOZ_ASSERT(masm_.codeLabels().empty()); + + masm_.finish(); + return !masm_.oom(); } bool ModuleGenerator::finishMetadata(const ShareableBytes& bytecode) { - // The MacroAssembler has accumulated all the memory accesses during codegen. - metadataTier_->memoryAccesses = masm_.extractMemoryAccesses(); +#ifdef DEBUG + // Assert CodeRanges are sorted. + uint32_t lastEnd = 0; + for (const CodeRange& codeRange : metadataTier_->codeRanges) { + MOZ_ASSERT(codeRange.begin() >= lastEnd); + lastEnd = codeRange.end(); + } + + // Assert debugTrapFarJumpOffsets are sorted. + uint32_t lastOffset = 0; + for (uint32_t debugTrapFarJumpOffset : metadataTier_->debugTrapFarJumpOffsets) { + MOZ_ASSERT(debugTrapFarJumpOffset >= lastOffset); + lastOffset = debugTrapFarJumpOffset; + } +#endif // Copy over data from the ModuleEnvironment. + metadata_->memoryUsage = env_->memoryUsage; metadata_->minMemoryLength = env_->minMemoryLength; metadata_->maxMemoryLength = env_->maxMemoryLength; @@ -1127,9 +1086,46 @@ ModuleGenerator::finishMetadata(const ShareableBytes& bytecode) metadata_->funcNames = Move(env_->funcNames); metadata_->customSections = Move(env_->customSections); + // Inflate the global bytes up to page size so that the total bytes are a + // page size (as required by the allocator functions). + + metadata_->globalDataLength = AlignBytes(metadata_->globalDataLength, gc::SystemPageSize()); + + // These Vectors can get large and the excess capacity can be significant, + // so realloc them down to size. + + metadataTier_->memoryAccesses.podResizeToFit(); + metadataTier_->codeRanges.podResizeToFit(); + metadataTier_->callSites.podResizeToFit(); + metadataTier_->debugTrapFarJumpOffsets.podResizeToFit(); + metadataTier_->debugFuncToCodeRange.podResizeToFit(); + + // For asm.js, the tables vector is over-allocated (to avoid resize during + // parallel copilation). Shrink it back down to fit. + + if (isAsmJS() && !metadata_->tables.resize(numTables_)) + return false; + + // Complete function exports and element segments with code range indices, + // now that every function has a code range. + + for (FuncExport& fe : metadataTier_->funcExports) + fe.initCodeRangeIndex(funcToCodeRange_[fe.funcIndex()]); + + for (ElemSegment& elems : env_->elemSegments) { + Uint32Vector& codeRangeIndices = elems.elemCodeRangeIndices(tier()); + MOZ_ASSERT(codeRangeIndices.empty()); + if (!codeRangeIndices.reserve(elems.elemFuncIndices.length())) + return false; + for (uint32_t funcIndex : elems.elemFuncIndices) + codeRangeIndices.infallibleAppend(funcToCodeRange_[funcIndex]); + } + // Copy over additional debug information. + if (env_->debugEnabled()) { metadata_->debugEnabled = true; + const size_t numSigs = env_->funcSigs.length(); if (!metadata_->debugFuncArgTypes.resize(numSigs)) return false; @@ -1141,24 +1137,16 @@ ModuleGenerator::finishMetadata(const ShareableBytes& bytecode) metadata_->debugFuncReturnTypes[i] = env_->funcSigs[i]->ret(); } metadataTier_->debugFuncToCodeRange = Move(funcToCodeRange_); + + static_assert(sizeof(ModuleHash) <= sizeof(mozilla::SHA1Sum::Hash), + "The ModuleHash size shall not exceed the SHA1 hash size."); + mozilla::SHA1Sum::Hash hash; + mozilla::SHA1Sum sha1Sum; + sha1Sum.update(bytecode.begin(), bytecode.length()); + sha1Sum.finish(hash); + memcpy(metadata_->debugHash, hash, sizeof(ModuleHash)); } - // These Vectors can get large and the excess capacity can be significant, - // so realloc them down to size. - metadataTier_->callSites = masm_.extractCallSites(); - metadataTier_->memoryAccesses.podResizeToFit(); - metadataTier_->codeRanges.podResizeToFit(); - metadataTier_->callSites.podResizeToFit(); - metadataTier_->debugTrapFarJumpOffsets.podResizeToFit(); - metadataTier_->debugFuncToCodeRange.podResizeToFit(); - - // For asm.js, the tables vector is over-allocated (to avoid resize during - // parallel copilation). Shrink it back down to fit. - if (isAsmJS() && !metadata_->tables.resize(numTables_)) - return false; - - generateBytecodeHash(bytecode); - return true; } @@ -1167,36 +1155,35 @@ ModuleGenerator::finishCodeSegment(const ShareableBytes& bytecode) { MOZ_ASSERT(finishedFuncDefs_); + // Because of asm.js, we can only generate the FuncExportVector at the end + // of module generation (after we've seen the end of the exports object at + // the end of the asm.js module). + if (!finishFuncExports()) return nullptr; - if (!finishCodegen()) + // Now that all imports/exports are known, we can generate a special + // CompiledCode containing stubs. + + CompiledCode& stubCode = tasks_[0].output; + MOZ_ASSERT(stubCode.empty()); + + if (!GenerateStubs(*env_, metadataTier_->funcImports, metadataTier_->funcExports, &stubCode)) + return nullptr; + + if (!linkCompiledCode(stubCode)) + return nullptr; + + // Now that all code is linked in masm_, patch calls and far jumps and + // finish the metadata. Linking can emit tiny far-jump stubs, so there is an + // ordering dependency here. + + if (!finishLinking()) return nullptr; if (!finishMetadata(bytecode)) return nullptr; - // Assert CodeRanges are sorted. -#ifdef DEBUG - uint32_t lastEnd = 0; - for (const CodeRange& codeRange : metadataTier_->codeRanges) { - MOZ_ASSERT(codeRange.begin() >= lastEnd); - lastEnd = codeRange.end(); - } -#endif - - // Assert debugTrapFarJumpOffsets are sorted. -#ifdef DEBUG - uint32_t lastOffset = 0; - for (uint32_t debugTrapFarJumpOffset : metadataTier_->debugTrapFarJumpOffsets) { - MOZ_ASSERT(debugTrapFarJumpOffset >= lastOffset); - lastOffset = debugTrapFarJumpOffset; - } -#endif - - if (!finishLinkData()) - return nullptr; - return CodeSegment::create(tier(), masm_, bytecode, *linkDataTier_, *metadata_); } @@ -1206,7 +1193,7 @@ ModuleGenerator::createJumpTable(const CodeSegment& codeSegment) MOZ_ASSERT(mode() == CompileMode::Tier1); MOZ_ASSERT(!isAsmJS()); - uint32_t tableSize = env_->numFuncImports() + env_->numFuncDefs(); + uint32_t tableSize = env_->numFuncs(); UniqueJumpTable jumpTable(js_pod_calloc(tableSize)); if (!jumpTable) return nullptr; diff --git a/js/src/wasm/WasmGenerator.h b/js/src/wasm/WasmGenerator.h index a6a1707612e4..73939f8b1c53 100644 --- a/js/src/wasm/WasmGenerator.h +++ b/js/src/wasm/WasmGenerator.h @@ -27,55 +27,79 @@ namespace js { namespace wasm { -struct CompileArgs; -struct ModuleEnvironment; +// FuncCompileInput contains the input for compiling a single function. -// FuncCompileUnit contains all the data necessary to produce and store the -// results of a single function's compilation. - -class FuncCompileUnit +struct FuncCompileInput { - // Input: - Bytes bytesToDelete_; - const uint8_t* begin_; - const uint8_t* end_; - uint32_t index_; - uint32_t lineOrBytecode_; - Uint32Vector callSiteLineNums_; + Bytes bytesToDelete; + const uint8_t* begin; + const uint8_t* end; + uint32_t index; + uint32_t lineOrBytecode; + Uint32Vector callSiteLineNums; - // Output: - FuncOffsets offsets_; - DebugOnly finished_; - - public: - explicit FuncCompileUnit(uint32_t index, uint32_t lineOrBytecode, - Bytes&& bytesToDelete, const uint8_t* begin, const uint8_t* end, - Uint32Vector&& callSiteLineNums) - : bytesToDelete_(Move(bytesToDelete)), - begin_(begin), - end_(end), - index_(index), - lineOrBytecode_(lineOrBytecode), - callSiteLineNums_(Move(callSiteLineNums)), - finished_(false) + FuncCompileInput(uint32_t index, + uint32_t lineOrBytecode, + Bytes&& bytesToDelete, + const uint8_t* begin, + const uint8_t* end, + Uint32Vector&& callSiteLineNums) + : bytesToDelete(Move(bytesToDelete)), + begin(begin), + end(end), + index(index), + lineOrBytecode(lineOrBytecode), + callSiteLineNums(Move(callSiteLineNums)) {} - - const uint8_t* begin() const { return begin_; } - const uint8_t* end() const { return end_; } - uint32_t index() const { return index_; } - uint32_t lineOrBytecode() const { return lineOrBytecode_; } - const Uint32Vector& callSiteLineNums() const { return callSiteLineNums_; } - - FuncOffsets offsets() const { MOZ_ASSERT(finished_); return offsets_; } - - void finish(FuncOffsets offsets) { - MOZ_ASSERT(!finished_); - offsets_ = offsets; - finished_ = true; - } }; -typedef Vector FuncCompileUnitVector; +typedef Vector FuncCompileInputVector; + +// CompiledCode contains the resulting code and metadata for a set of compiled +// input functions or stubs. + +struct CompiledCode +{ + Bytes bytes; + CodeRangeVector codeRanges; + CallSiteVector callSites; + CallSiteTargetVector callSiteTargets; + TrapSiteVector trapSites; + TrapFarJumpVector trapFarJumps; + CallFarJumpVector callFarJumps; + MemoryAccessVector memoryAccesses; + SymbolicAccessVector symbolicAccesses; + jit::CodeLabelVector codeLabels; + + MOZ_MUST_USE bool swap(jit::MacroAssembler& masm); + + void clear() { + bytes.clear(); + codeRanges.clear(); + callSites.clear(); + callSiteTargets.clear(); + trapSites.clear(); + trapFarJumps.clear(); + callFarJumps.clear(); + memoryAccesses.clear(); + symbolicAccesses.clear(); + codeLabels.clear(); + MOZ_ASSERT(empty()); + } + + bool empty() { + return bytes.empty() && + codeRanges.empty() && + callSites.empty() && + callSiteTargets.empty() && + trapSites.empty() && + trapFarJumps.empty() && + callFarJumps.empty() && + memoryAccesses.empty() && + symbolicAccesses.empty() && + codeLabels.empty(); + } +}; // The CompileTaskState of a ModuleGenerator contains the mutable state shared // between helper threads executing CompileTasks. Each CompileTask started on a @@ -95,71 +119,22 @@ struct CompileTaskState typedef ExclusiveData ExclusiveCompileTaskState; -// A CompileTask represents the task of compiling a batch of functions. It is -// filled with a certain number of function's bodies that are sent off to a -// compilation helper thread, which fills in the resulting code offsets, and -// finally sent back to the validation thread. +// A CompileTask holds a batch of input functions that are to be compiled on a +// helper thread as well as, eventually, the results of compilation. -class CompileTask +struct CompileTask { - const ModuleEnvironment& env_; - ExclusiveCompileTaskState& state_; - LifoAlloc lifo_; - Maybe alloc_; - Maybe masm_; - FuncCompileUnitVector units_; + const ModuleEnvironment& env; + ExclusiveCompileTaskState& state; + LifoAlloc lifo; + FuncCompileInputVector inputs; + CompiledCode output; - CompileTask(const CompileTask&) = delete; - CompileTask& operator=(const CompileTask&) = delete; - - void init() { - alloc_.emplace(&lifo_); - masm_.emplace(jit::MacroAssembler::WasmToken(), *alloc_); - } - - public: CompileTask(const ModuleEnvironment& env, ExclusiveCompileTaskState& state, size_t defaultChunkSize) - : env_(env), - state_(state), - lifo_(defaultChunkSize) - { - init(); - } - LifoAlloc& lifo() { - return lifo_; - } - jit::TempAllocator& alloc() { - return *alloc_; - } - const ModuleEnvironment& env() const { - return env_; - } - const ExclusiveCompileTaskState& state() const { - return state_; - } - jit::MacroAssembler& masm() { - return *masm_; - } - FuncCompileUnitVector& units() { - return units_; - } - Tier tier() const { - return env_.tier(); - } - CompileMode mode() const { - return env_.mode(); - } - bool debugEnabled() const { - return env_.debug == DebugEnabled::True; - } - bool reset() { - units_.clear(); - masm_.reset(); - alloc_.reset(); - lifo_.releaseAll(); - init(); - return true; - } + : env(env), + state(state), + lifo(defaultChunkSize) + {} }; // A ModuleGenerator encapsulates the creation of a wasm module. During the @@ -173,7 +148,8 @@ class MOZ_STACK_CLASS ModuleGenerator typedef HashSet, SystemAllocPolicy> Uint32Set; typedef Vector CompileTaskVector; typedef Vector CompileTaskPtrVector; - typedef EnumeratedArray TrapExitOffsetArray; + typedef EnumeratedArray Uint32TrapArray; + typedef Vector CodeOffsetVector; // Constant parameters SharedCompileArgs const compileArgs_; @@ -191,6 +167,7 @@ class MOZ_STACK_CLASS ModuleGenerator // Data scoped to the ModuleGenerator's lifetime ExclusiveCompileTaskState taskState_; + uint32_t numFuncDefs_; uint32_t numSigs_; uint32_t numTables_; LifoAlloc lifo_; @@ -198,10 +175,15 @@ class MOZ_STACK_CLASS ModuleGenerator jit::TempAllocator masmAlloc_; jit::MacroAssembler masm_; Uint32Vector funcToCodeRange_; + Uint32TrapArray trapCodeOffsets_; + uint32_t debugTrapCodeOffset_; + TrapFarJumpVector trapFarJumps_; + CallFarJumpVector callFarJumps_; + CallSiteTargetVector callSiteTargets_; Uint32Set exportedFuncs_; - uint32_t lastPatchedCallsite_; + uint32_t lastPatchedCallSite_; uint32_t startOfUnpatchedCallsites_; - Uint32Vector debugTrapFarJumps_; + CodeOffsetVector debugTrapFarJumps_; // Parallel compilation bool parallel_; @@ -214,33 +196,31 @@ class MOZ_STACK_CLASS ModuleGenerator // Assertions DebugOnly startedFuncDefs_; DebugOnly finishedFuncDefs_; - DebugOnly numFinishedFuncDefs_; bool funcIsCompiled(uint32_t funcIndex) const; const CodeRange& funcCodeRange(uint32_t funcIndex) const; - uint32_t numFuncImports() const; - MOZ_MUST_USE bool patchCallSites(); - MOZ_MUST_USE bool patchFarJumps(const TrapExitOffsetArray& trapExits, const Offsets& debugTrapStub); - MOZ_MUST_USE bool finishTask(CompileTask* task); - MOZ_MUST_USE bool finishOutstandingTask(); - MOZ_MUST_USE bool finishFuncExports(); - MOZ_MUST_USE bool finishCodegen(); - MOZ_MUST_USE bool finishLinkData(); - void generateBytecodeHash(const ShareableBytes& bytecode); - MOZ_MUST_USE bool finishMetadata(const ShareableBytes& bytecode); - MOZ_MUST_USE UniqueConstCodeSegment finishCodeSegment(const ShareableBytes& bytecode); + + bool linkCallSites(); + void noteCodeRange(uint32_t codeRangeIndex, const CodeRange& codeRange); + bool linkCompiledCode(const CompiledCode& code); + bool finishTask(CompileTask* task); + bool finishOutstandingTask(); + bool finishFuncExports(); + bool finishLinking(); + bool finishMetadata(const ShareableBytes& bytecode); + UniqueConstCodeSegment finishCodeSegment(const ShareableBytes& bytecode); UniqueJumpTable createJumpTable(const CodeSegment& codeSegment); - MOZ_MUST_USE bool addFuncImport(const Sig& sig, uint32_t globalDataOffset); - MOZ_MUST_USE bool allocateGlobalBytes(uint32_t bytes, uint32_t align, uint32_t* globalDataOff); - MOZ_MUST_USE bool allocateGlobal(GlobalDesc* global); + bool addFuncImport(const Sig& sig, uint32_t globalDataOffset); + bool allocateGlobalBytes(uint32_t bytes, uint32_t align, uint32_t* globalDataOff); + bool allocateGlobal(GlobalDesc* global); - MOZ_MUST_USE bool launchBatchCompile(); - MOZ_MUST_USE bool compileFuncDef(uint32_t funcIndex, uint32_t lineOrBytecode, - Bytes&& bytes, const uint8_t* begin, const uint8_t* end, - Uint32Vector&& lineNums); + bool launchBatchCompile(); + bool compileFuncDef(uint32_t funcIndex, uint32_t lineOrBytecode, + Bytes&& bytes, const uint8_t* begin, const uint8_t* end, + Uint32Vector&& lineNums); - MOZ_MUST_USE bool initAsmJS(Metadata* asmJSMetadata); - MOZ_MUST_USE bool initWasm(); + bool initAsmJS(Metadata* asmJSMetadata); + bool initWasm(size_t codeLength); bool isAsmJS() const { return env_->isAsmJS(); } Tier tier() const { return env_->tier(); } @@ -252,7 +232,7 @@ class MOZ_STACK_CLASS ModuleGenerator Atomic* cancelled, UniqueChars* error); ~ModuleGenerator(); - MOZ_MUST_USE bool init(Metadata* maybeAsmJSMetadata = nullptr); + MOZ_MUST_USE bool init(size_t codeSectionSize, Metadata* maybeAsmJSMetadata = nullptr); // Function definitions: MOZ_MUST_USE bool startFuncDefs(); diff --git a/js/src/wasm/WasmIonCompile.cpp b/js/src/wasm/WasmIonCompile.cpp index 892580504ed6..aa04a521f5f2 100644 --- a/js/src/wasm/WasmIonCompile.cpp +++ b/js/src/wasm/WasmIonCompile.cpp @@ -126,7 +126,7 @@ class FunctionCompiler const ModuleEnvironment& env_; IonOpIter iter_; - const FuncCompileUnit& func_; + const FuncCompileInput& func_; const ValTypeVector& locals_; size_t lastReadCallSite_; @@ -149,7 +149,7 @@ class FunctionCompiler public: FunctionCompiler(const ModuleEnvironment& env, Decoder& decoder, - const FuncCompileUnit& func, + const FuncCompileInput& func, const ValTypeVector& locals, MIRGenerator& mirGen) : env_(env), @@ -171,7 +171,7 @@ class FunctionCompiler const ModuleEnvironment& env() const { return env_; } IonOpIter& iter() { return iter_; } TempAllocator& alloc() const { return alloc_; } - const Sig& sig() const { return *env_.funcSigs[func_.index()]; } + const Sig& sig() const { return *env_.funcSigs[func_.index]; } BytecodeOffset bytecodeOffset() const { return iter_.bytecodeOffset(); @@ -270,7 +270,7 @@ class FunctionCompiler #endif MOZ_ASSERT(inDeadCode()); MOZ_ASSERT(done(), "all bytes must be consumed"); - MOZ_ASSERT(func_.callSiteLineNums().length() == lastReadCallSite_); + MOZ_ASSERT(func_.callSiteLineNums.length() == lastReadCallSite_); } /************************* Read-only interface (after local scope setup) */ @@ -1574,8 +1574,8 @@ class FunctionCompiler /************************************************************ DECODING ***/ uint32_t readCallSiteLineOrBytecode() { - if (!func_.callSiteLineNums().empty()) - return func_.callSiteLineNums()[lastReadCallSite_++]; + if (!func_.callSiteLineNums.empty()) + return func_.callSiteLineNums[lastReadCallSite_++]; return iter_.lastOpcodeOffset(); } @@ -3852,70 +3852,86 @@ EmitBodyExprs(FunctionCompiler& f) } bool -wasm::IonCompileFunction(CompileTask* task, FuncCompileUnit* func, UniqueChars* error) +wasm::IonCompileFunctions(const ModuleEnvironment& env, LifoAlloc& lifo, + const FuncCompileInputVector& inputs, CompiledCode* code, + UniqueChars* error) { - MOZ_ASSERT(task->tier() == Tier::Ion); + MOZ_ASSERT(env.tier() == Tier::Ion); - const ModuleEnvironment& env = task->env(); + TempAllocator alloc(&lifo); + JitContext jitContext(&alloc); + MOZ_ASSERT(IsCompilingWasm()); + MacroAssembler masm(MacroAssembler::WasmToken(), alloc); - Decoder d(func->begin(), func->end(), func->lineOrBytecode(), error); - - // Build the local types vector. - - ValTypeVector locals; - if (!locals.appendAll(task->env().funcSigs[func->index()]->args())) - return false; - if (!DecodeLocalEntries(d, env.kind, &locals)) + // Swap in already-allocated empty vectors to avoid malloc/free. + MOZ_ASSERT(code->empty()); + if (!code->swap(masm)) return false; - // Set up for Ion compilation. + for (const FuncCompileInput& func : inputs) { + Decoder d(func.begin, func.end, func.lineOrBytecode, error); - JitContext jitContext(&task->alloc()); - const JitCompileOptions options; - MIRGraph graph(&task->alloc()); - CompileInfo compileInfo(locals.length()); - MIRGenerator mir(nullptr, options, &task->alloc(), &graph, &compileInfo, - IonOptimizations.get(OptimizationLevel::Wasm)); - mir.initMinWasmHeapLength(env.minMemoryLength); + // Build the local types vector. - // Build MIR graph - { - FunctionCompiler f(env, d, *func, locals, mir); - if (!f.init()) + ValTypeVector locals; + if (!locals.appendAll(env.funcSigs[func.index]->args())) + return false; + if (!DecodeLocalEntries(d, env.kind, &locals)) return false; - if (!f.startBlock()) - return false; + // Set up for Ion compilation. - if (!EmitBodyExprs(f)) - return false; + const JitCompileOptions options; + MIRGraph graph(&alloc); + CompileInfo compileInfo(locals.length()); + MIRGenerator mir(nullptr, options, &alloc, &graph, &compileInfo, + IonOptimizations.get(OptimizationLevel::Wasm)); + mir.initMinWasmHeapLength(env.minMemoryLength); - f.finish(); + // Build MIR graph + { + FunctionCompiler f(env, d, func, locals, mir); + if (!f.init()) + return false; + + if (!f.startBlock()) + return false; + + if (!EmitBodyExprs(f)) + return false; + + f.finish(); + } + + // Compile MIR graph + { + jit::SpewBeginFunction(&mir, nullptr); + jit::AutoSpewEndFunction spewEndFunction(&mir); + + if (!OptimizeMIR(&mir)) + return false; + + LIRGraph* lir = GenerateLIR(&mir); + if (!lir) + return false; + + SigIdDesc sigId = env.funcSigs[func.index]->id; + + CodeGenerator codegen(&mir, lir, &masm); + + BytecodeOffset prologueTrapOffset(func.lineOrBytecode); + FuncOffsets offsets; + if (!codegen.generateWasm(sigId, prologueTrapOffset, &offsets)) + return false; + + if (!code->codeRanges.emplaceBack(func.index, func.lineOrBytecode, offsets)) + return false; + } } - // Compile MIR graph - { - jit::SpewBeginFunction(&mir, nullptr); - jit::AutoSpewEndFunction spewEndFunction(&mir); + masm.finish(); + if (masm.oom()) + return false; - if (!OptimizeMIR(&mir)) - return false; - - LIRGraph* lir = GenerateLIR(&mir); - if (!lir) - return false; - - SigIdDesc sigId = env.funcSigs[func->index()]->id; - - CodeGenerator codegen(&mir, lir, &task->masm()); - - BytecodeOffset prologueTrapOffset(func->lineOrBytecode()); - FuncOffsets offsets; - if (!codegen.generateWasm(sigId, prologueTrapOffset, &offsets)) - return false; - - func->finish(offsets); - } - - return true; + return code->swap(masm); } diff --git a/js/src/wasm/WasmIonCompile.h b/js/src/wasm/WasmIonCompile.h index f2165d9be83f..81d53a0fd263 100644 --- a/js/src/wasm/WasmIonCompile.h +++ b/js/src/wasm/WasmIonCompile.h @@ -21,17 +21,16 @@ #include "mozilla/Attributes.h" -#include "wasm/WasmTypes.h" +#include "wasm/WasmGenerator.h" namespace js { namespace wasm { -class CompileTask; -class FuncCompileUnit; - // Generates very fast code at the expense of compilation time. MOZ_MUST_USE bool -IonCompileFunction(CompileTask* task, FuncCompileUnit* unit, UniqueChars* error); +IonCompileFunctions(const ModuleEnvironment& env, LifoAlloc& lifo, + const FuncCompileInputVector& inputs, CompiledCode* code, + UniqueChars* error); } // namespace wasm } // namespace js diff --git a/js/src/wasm/WasmModule.h b/js/src/wasm/WasmModule.h index f5b9adf1bf82..e5de4863d8ec 100644 --- a/js/src/wasm/WasmModule.h +++ b/js/src/wasm/WasmModule.h @@ -35,12 +35,13 @@ struct CompileArgs; // LinkData contains all the metadata necessary to patch all the locations // that depend on the absolute address of a CodeSegment. // -// LinkData is built incrementing by ModuleGenerator and then stored immutably -// in Module. +// LinkData is built incrementally by ModuleGenerator and then stored immutably +// in Module. LinkData is distinct from Metadata in that LinkData is owned and +// destroyed by the Module since it is not needed after instantiation; Metadata +// is needed at runtime. struct LinkDataTierCacheablePod { - uint32_t functionCodeLength; uint32_t interruptOffset; uint32_t outOfBoundsOffset; uint32_t unalignedAccessOffset; diff --git a/js/src/wasm/WasmSignalHandlers.cpp b/js/src/wasm/WasmSignalHandlers.cpp old mode 100755 new mode 100644 index b14d4734695e..8447d49e6dae --- a/js/src/wasm/WasmSignalHandlers.cpp +++ b/js/src/wasm/WasmSignalHandlers.cpp @@ -783,7 +783,7 @@ MOZ_COLD static void HandleMemoryAccess(EMULATOR_CONTEXT* context, uint8_t* pc, uint8_t* faultingAddress, const Instance& instance, WasmActivation* activation, uint8_t** ppc) { - MOZ_RELEASE_ASSERT(instance.code().containsFunctionPC(pc)); + MOZ_RELEASE_ASSERT(instance.code().containsCodePC(pc)); const CodeSegment* segment; const MemoryAccess* memoryAccess = instance.code().lookupMemoryAccess(pc, &segment); @@ -819,7 +819,7 @@ HandleMemoryAccess(EMULATOR_CONTEXT* context, uint8_t* pc, uint8_t* faultingAddr uint8_t* end = Disassembler::DisassembleHeapAccess(pc, &access); const Disassembler::ComplexAddress& address = access.address(); MOZ_RELEASE_ASSERT(end > pc); - MOZ_RELEASE_ASSERT(segment->containsFunctionPC(end)); + MOZ_RELEASE_ASSERT(segment->containsCodePC(end)); // Check x64 asm.js heap access invariants. MOZ_RELEASE_ASSERT(address.disp() >= 0); @@ -932,7 +932,7 @@ MOZ_COLD static void HandleMemoryAccess(EMULATOR_CONTEXT* context, uint8_t* pc, uint8_t* faultingAddress, const Instance& instance, WasmActivation* activation, uint8_t** ppc) { - MOZ_RELEASE_ASSERT(instance.code().containsFunctionPC(pc)); + MOZ_RELEASE_ASSERT(instance.code().containsCodePC(pc)); const CodeSegment* segment; const MemoryAccess* memoryAccess = instance.code().lookupMemoryAccess(pc, &segment); @@ -999,7 +999,8 @@ HandleFault(PEXCEPTION_POINTERS exception) if (!code) return false; - if (!codeSegment->containsFunctionPC(pc)) { + const Instance* instance = LookupFaultingInstance(*code, pc, ContextToFP(context)); + if (!instance) { // On Windows, it is possible for InterruptRunningJitCode to execute // between a faulting heap access and the handling of the fault due // to InterruptRunningJitCode's use of SuspendThread. When this happens, @@ -1013,7 +1014,7 @@ HandleFault(PEXCEPTION_POINTERS exception) for (auto t : code->tiers()) { if (pc == code->segment(t).interruptCode() && activation->interrupted() && - code->segment(t).containsFunctionPC(activation->resumePC())) + code->segment(t).containsCodePC(activation->resumePC())) { return true; } @@ -1021,10 +1022,6 @@ HandleFault(PEXCEPTION_POINTERS exception) return false; } - const Instance* instance = LookupFaultingInstance(*code, pc, ContextToFP(context)); - if (!instance) - return false; - uint8_t* faultingAddress = reinterpret_cast(record->ExceptionInformation[1]); // This check isn't necessary, but, since we can, check anyway to make @@ -1145,7 +1142,7 @@ HandleMachException(JSContext* cx, const ExceptionRequest& request) return false; const Instance* instance = LookupFaultingInstance(*code, pc, ContextToFP(&context)); - if (!instance || !instance->code().containsFunctionPC(pc)) + if (!instance) return false; uint8_t* faultingAddress = reinterpret_cast(request.body.code[1]); @@ -1357,7 +1354,7 @@ HandleFault(int signum, siginfo_t* info, void* ctx) return false; const Instance* instance = LookupFaultingInstance(*code, pc, ContextToFP(context)); - if (!instance || !instance->code().containsFunctionPC(pc, &segment)) + if (!instance) return false; uint8_t* faultingAddress = reinterpret_cast(info->si_addr); @@ -1457,11 +1454,16 @@ wasm::InInterruptibleCode(JSContext* cx, uint8_t* pc, const CodeSegment** cs) // Only interrupt in function code so that the frame iterators have the // invariant that resumePC always has a function CodeRange and we can't // get into any weird interrupt-during-interrupt-stub cases. + if (!cx->compartment()) return false; - const Code* code = cx->compartment()->wasm.lookupCode(pc, cs); - return code && (*cs)->containsFunctionPC(pc); + const Code* code = cx->compartment()->wasm.lookupCode(pc); + if (!code) + return false; + + const CodeRange* codeRange = code->lookupRange(pc, cs); + return codeRange && codeRange->isFunction(); } // The return value indicates whether the PC was changed, not whether there was diff --git a/js/src/wasm/WasmStubs.cpp b/js/src/wasm/WasmStubs.cpp index db3f29f4015e..be7df8a83fb4 100644 --- a/js/src/wasm/WasmStubs.cpp +++ b/js/src/wasm/WasmStubs.cpp @@ -19,6 +19,7 @@ #include "wasm/WasmStubs.h" #include "mozilla/ArrayUtils.h" +#include "mozilla/EnumeratedRange.h" #include "wasm/WasmCode.h" #include "wasm/WasmGenerator.h" @@ -30,18 +31,20 @@ using namespace js::jit; using namespace js::wasm; using mozilla::ArrayLength; +using mozilla::MakeEnumeratedRange; typedef Vector MIRTypeVector; typedef jit::ABIArgIter ABIArgMIRTypeIter; typedef jit::ABIArgIter ABIArgValTypeIter; -static void +static bool FinishOffsets(MacroAssembler& masm, Offsets* offsets) { // On old ARM hardware, constant pools could be inserted and they need to // be flushed before considering the size of the masm. masm.flushBuffer(); offsets->end = masm.size(); + return !masm.oom(); } static void @@ -252,13 +255,12 @@ static const unsigned FailFP = 0xbad; // signature of the entry point is Module::ExportFuncPtr. The exported wasm // function has an ABI derived from its specific signature, so this function // must map from the ABI of ExportFuncPtr to the export's signature's ABI. -Offsets -wasm::GenerateEntry(MacroAssembler& masm, const FuncExport& fe) +static bool +GenerateEntry(MacroAssembler& masm, const FuncExport& fe, Offsets* offsets) { masm.haltingAlign(CodeAlignment); - Offsets offsets; - offsets.begin = masm.currentOffset(); + offsets->begin = masm.currentOffset(); // Save the return address if it wasn't already saved by the call insn. #if defined(JS_CODEGEN_ARM) @@ -371,8 +373,7 @@ wasm::GenerateEntry(MacroAssembler& masm, const FuncExport& fe) masm.ret(); - FinishOffsets(masm, &offsets); - return offsets; + return FinishOffsets(masm, offsets); } static void @@ -500,15 +501,15 @@ FillArgumentArray(MacroAssembler& masm, const ValTypeVector& args, unsigned argO // - a table entry, so JS imports can be put into tables // - normal entries, so that, if the import is re-exported, an entry stub can // be generated and called without any special cases -FuncOffsets -wasm::GenerateImportFunction(jit::MacroAssembler& masm, const FuncImport& fi, SigIdDesc sigId) +static bool +GenerateImportFunction(jit::MacroAssembler& masm, const FuncImport& fi, SigIdDesc sigId, + FuncOffsets* offsets) { masm.setFramePushed(0); unsigned framePushed = StackDecrementForCall(masm, WasmStackAlignment, fi.sig().args()); - FuncOffsets offsets; - GenerateFunctionPrologue(masm, framePushed, sigId, &offsets); + GenerateFunctionPrologue(masm, framePushed, sigId, offsets); // The argument register state is already setup by our caller. We just need // to be sure not to clobber it before the call. @@ -534,20 +535,19 @@ wasm::GenerateImportFunction(jit::MacroAssembler& masm, const FuncImport& fi, Si masm.loadWasmTlsRegFromFrame(); masm.loadWasmPinnedRegsFromTls(); - GenerateFunctionEpilogue(masm, framePushed, &offsets); + GenerateFunctionEpilogue(masm, framePushed, offsets); masm.wasmEmitTrapOutOfLineCode(); - FinishOffsets(masm, &offsets); - return offsets; + return FinishOffsets(masm, offsets); } // Generate a stub that is called via the internal ABI derived from the // signature of the import and calls into an appropriate callImport C++ // function, having boxed all the ABI arguments into a homogeneous Value array. -CallableOffsets -wasm::GenerateImportInterpExit(MacroAssembler& masm, const FuncImport& fi, uint32_t funcImportIndex, - Label* throwLabel) +static bool +GenerateImportInterpExit(MacroAssembler& masm, const FuncImport& fi, uint32_t funcImportIndex, + Label* throwLabel, CallableOffsets* offsets) { masm.setFramePushed(0); @@ -567,8 +567,7 @@ wasm::GenerateImportInterpExit(MacroAssembler& masm, const FuncImport& fi, uint3 unsigned argBytes = Max(1, fi.sig().args().length()) * sizeof(Value); unsigned framePushed = StackDecrementForCall(masm, ABIStackAlignment, argOffset + argBytes); - CallableOffsets offsets; - GenerateExitPrologue(masm, framePushed, ExitReason::Fixed::ImportInterp, &offsets); + GenerateExitPrologue(masm, framePushed, ExitReason::Fixed::ImportInterp, offsets); // Fill the argument array. unsigned offsetToCallerStackArgs = sizeof(Frame) + masm.framePushed(); @@ -663,17 +662,17 @@ wasm::GenerateImportInterpExit(MacroAssembler& masm, const FuncImport& fi, uint3 MOZ_ASSERT(NonVolatileRegs.has(HeapReg)); #endif - GenerateExitEpilogue(masm, framePushed, ExitReason::Fixed::ImportInterp, &offsets); + GenerateExitEpilogue(masm, framePushed, ExitReason::Fixed::ImportInterp, offsets); - FinishOffsets(masm, &offsets); - return offsets; + return FinishOffsets(masm, offsets); } // Generate a stub that is called via the internal ABI derived from the // signature of the import and calls into a compatible JIT function, // having boxed all the ABI arguments into the JIT stack frame layout. -CallableOffsets -wasm::GenerateImportJitExit(MacroAssembler& masm, const FuncImport& fi, Label* throwLabel) +static bool +GenerateImportJitExit(MacroAssembler& masm, const FuncImport& fi, Label* throwLabel, + CallableOffsets* offsets) { masm.setFramePushed(0); @@ -690,8 +689,7 @@ wasm::GenerateImportJitExit(MacroAssembler& masm, const FuncImport& fi, Label* t unsigned jitFramePushed = StackDecrementForCall(masm, JitStackAlignment, totalJitFrameBytes) - sizeOfRetAddr; - CallableOffsets offsets; - GenerateExitPrologue(masm, jitFramePushed, ExitReason::Fixed::ImportJit, &offsets); + GenerateExitPrologue(masm, jitFramePushed, ExitReason::Fixed::ImportJit, offsets); // 1. Descriptor size_t argOffset = 0; @@ -838,7 +836,7 @@ wasm::GenerateImportJitExit(MacroAssembler& masm, const FuncImport& fi, Label* t Label done; masm.bind(&done); - GenerateExitEpilogue(masm, masm.framePushed(), ExitReason::Fixed::ImportJit, &offsets); + GenerateExitEpilogue(masm, masm.framePushed(), ExitReason::Fixed::ImportJit, offsets); if (oolConvert.used()) { masm.bind(&oolConvert); @@ -896,8 +894,7 @@ wasm::GenerateImportJitExit(MacroAssembler& masm, const FuncImport& fi, Label* t MOZ_ASSERT(masm.framePushed() == 0); - FinishOffsets(masm, &offsets); - return offsets; + return FinishOffsets(masm, offsets); } struct ABIFunctionArgs @@ -927,17 +924,16 @@ struct ABIFunctionArgs } }; -CallableOffsets +bool wasm::GenerateBuiltinThunk(MacroAssembler& masm, ABIFunctionType abiType, ExitReason exitReason, - void* funcPtr) + void* funcPtr, CallableOffsets* offsets) { masm.setFramePushed(0); ABIFunctionArgs args(abiType); uint32_t framePushed = StackDecrementForCall(masm, ABIStackAlignment, args); - CallableOffsets offsets; - GenerateExitPrologue(masm, framePushed, exitReason, &offsets); + GenerateExitPrologue(masm, framePushed, exitReason, offsets); // Copy out and convert caller arguments, if needed. unsigned offsetToCallerStackArgs = sizeof(Frame) + masm.framePushed(); @@ -985,17 +981,16 @@ wasm::GenerateBuiltinThunk(MacroAssembler& masm, ABIFunctionType abiType, ExitRe masm.ma_vxfer(r0, r1, d0); #endif - GenerateExitEpilogue(masm, framePushed, exitReason, &offsets); - offsets.end = masm.currentOffset(); - return offsets; + GenerateExitEpilogue(masm, framePushed, exitReason, offsets); + return FinishOffsets(masm, offsets); } // Generate a stub that calls into ReportTrap with the right trap reason. // This stub is called with ABIStackAlignment by a trap out-of-line path. An // exit prologue/epilogue is used so that stack unwinding picks up the // current WasmActivation. Unwinding will begin at the caller of this trap exit. -CallableOffsets -wasm::GenerateTrapExit(MacroAssembler& masm, Trap trap, Label* throwLabel) +static bool +GenerateTrapExit(MacroAssembler& masm, Trap trap, Label* throwLabel, CallableOffsets* offsets) { masm.haltingAlign(CodeAlignment); @@ -1006,8 +1001,7 @@ wasm::GenerateTrapExit(MacroAssembler& masm, Trap trap, Label* throwLabel) uint32_t framePushed = StackDecrementForCall(masm, ABIStackAlignment, args); - CallableOffsets offsets; - GenerateExitPrologue(masm, framePushed, ExitReason::Fixed::Trap, &offsets); + GenerateExitPrologue(masm, framePushed, ExitReason::Fixed::Trap, offsets); ABIArgMIRTypeIter i(args); if (i->kind() == ABIArg::GPR) @@ -1022,10 +1016,9 @@ wasm::GenerateTrapExit(MacroAssembler& masm, Trap trap, Label* throwLabel) masm.jump(throwLabel); - GenerateExitEpilogue(masm, framePushed, ExitReason::Fixed::Trap, &offsets); + GenerateExitEpilogue(masm, framePushed, ExitReason::Fixed::Trap, offsets); - FinishOffsets(masm, &offsets); - return offsets; + return FinishOffsets(masm, offsets); } // Generate a stub which is only used by the signal handlers to handle out of @@ -1036,13 +1029,13 @@ wasm::GenerateTrapExit(MacroAssembler& masm, Trap trap, Label* throwLabel) // be lost. This stub should be removed when SIMD.js and Atomics are moved to // wasm and given proper traps and when we use a non-faulting strategy for // unaligned ARM access. -static Offsets -GenerateGenericMemoryAccessTrap(MacroAssembler& masm, SymbolicAddress reporter, Label* throwLabel) +static bool +GenerateGenericMemoryAccessTrap(MacroAssembler& masm, SymbolicAddress reporter, Label* throwLabel, + Offsets* offsets) { masm.haltingAlign(CodeAlignment); - Offsets offsets; - offsets.begin = masm.currentOffset(); + offsets->begin = masm.currentOffset(); // sp can be anything at this point, so ensure it is aligned when calling // into C++. We unconditionally jump to throw so don't worry about @@ -1054,20 +1047,21 @@ GenerateGenericMemoryAccessTrap(MacroAssembler& masm, SymbolicAddress reporter, masm.call(reporter); masm.jump(throwLabel); - FinishOffsets(masm, &offsets); - return offsets; + return FinishOffsets(masm, offsets); } -Offsets -wasm::GenerateOutOfBoundsExit(MacroAssembler& masm, Label* throwLabel) +static bool +GenerateOutOfBoundsExit(MacroAssembler& masm, Label* throwLabel, Offsets* offsets) { - return GenerateGenericMemoryAccessTrap(masm, SymbolicAddress::ReportOutOfBounds, throwLabel); + return GenerateGenericMemoryAccessTrap(masm, SymbolicAddress::ReportOutOfBounds, throwLabel, + offsets); } -Offsets -wasm::GenerateUnalignedExit(MacroAssembler& masm, Label* throwLabel) +static bool +GenerateUnalignedExit(MacroAssembler& masm, Label* throwLabel, Offsets* offsets) { - return GenerateGenericMemoryAccessTrap(masm, SymbolicAddress::ReportUnalignedAccess, throwLabel); + return GenerateGenericMemoryAccessTrap(masm, SymbolicAddress::ReportUnalignedAccess, throwLabel, + offsets); } #if defined(JS_CODEGEN_ARM) @@ -1089,13 +1083,12 @@ static const LiveRegisterSet AllRegsExceptSP( // preserve *all* register state. If execution is interrupted, the entire // activation will be popped by the throw stub, so register state does not need // to be restored. -Offsets -wasm::GenerateInterruptExit(MacroAssembler& masm, Label* throwLabel) +static bool +GenerateInterruptExit(MacroAssembler& masm, Label* throwLabel, Offsets* offsets) { masm.haltingAlign(CodeAlignment); - Offsets offsets; - offsets.begin = masm.currentOffset(); + offsets->begin = masm.currentOffset(); #if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64) // Be very careful here not to perturb the machine state before saving it @@ -1236,8 +1229,7 @@ wasm::GenerateInterruptExit(MacroAssembler& masm, Label* throwLabel) # error "Unknown architecture!" #endif - FinishOffsets(masm, &offsets); - return offsets; + return FinishOffsets(masm, offsets); } // Generate a stub that restores the stack pointer to what it was on entry to @@ -1245,15 +1237,14 @@ wasm::GenerateInterruptExit(MacroAssembler& masm, Label* throwLabel) // return which will return from this wasm activation to the caller. This stub // should only be called after the caller has reported an error (or, in the case // of the interrupt stub, intends to interrupt execution). -Offsets -wasm::GenerateThrowStub(MacroAssembler& masm, Label* throwLabel) +static bool +GenerateThrowStub(MacroAssembler& masm, Label* throwLabel, Offsets* offsets) { masm.haltingAlign(CodeAlignment); masm.bind(throwLabel); - Offsets offsets; - offsets.begin = masm.currentOffset(); + offsets->begin = masm.currentOffset(); // The throw stub can be jumped to from an async interrupt that is halting // execution. Thus the stack pointer can be unaligned and we must align it @@ -1270,8 +1261,7 @@ wasm::GenerateThrowStub(MacroAssembler& masm, Label* throwLabel) masm.move32(Imm32(FailFP), FramePointer); masm.ret(); - FinishOffsets(masm, &offsets); - return offsets; + return FinishOffsets(masm, offsets); } static const LiveRegisterSet AllAllocatableRegs = LiveRegisterSet( @@ -1281,15 +1271,14 @@ static const LiveRegisterSet AllAllocatableRegs = LiveRegisterSet( // Generate a stub that handle toggable enter/leave frame traps or breakpoints. // The trap records frame pointer (via GenerateExitPrologue) and saves most of // registers to not affect the code generated by WasmBaselineCompile. -Offsets -wasm::GenerateDebugTrapStub(MacroAssembler& masm, Label* throwLabel) +static bool +GenerateDebugTrapStub(MacroAssembler& masm, Label* throwLabel, CallableOffsets* offsets) { masm.haltingAlign(CodeAlignment); masm.setFramePushed(0); - CallableOffsets offsets; - GenerateExitPrologue(masm, 0, ExitReason::Fixed::DebugTrap, &offsets); + GenerateExitPrologue(masm, 0, ExitReason::Fixed::DebugTrap, offsets); // Save all registers used between baseline compiler operations. masm.PushRegsInMask(AllAllocatableRegs); @@ -1319,8 +1308,100 @@ wasm::GenerateDebugTrapStub(MacroAssembler& masm, Label* throwLabel) masm.setFramePushed(framePushed); masm.PopRegsInMask(AllAllocatableRegs); - GenerateExitEpilogue(masm, 0, ExitReason::Fixed::DebugTrap, &offsets); + GenerateExitEpilogue(masm, 0, ExitReason::Fixed::DebugTrap, offsets); - FinishOffsets(masm, &offsets); - return offsets; + return FinishOffsets(masm, offsets); +} + +static const unsigned STUBS_LIFO_DEFAULT_CHUNK_SIZE = 4 * 1024; + +bool +wasm::GenerateStubs(const ModuleEnvironment& env, const FuncImportVector& imports, + const FuncExportVector& exports, CompiledCode* code) +{ + LifoAlloc lifo(STUBS_LIFO_DEFAULT_CHUNK_SIZE); + TempAllocator alloc(&lifo); + MacroAssembler masm(MacroAssembler::WasmToken(), alloc); + + // Swap in already-allocated empty vectors to avoid malloc/free. + if (!code->swap(masm)) + return false; + + Label throwLabel; + + for (uint32_t funcIndex = 0; funcIndex < imports.length(); funcIndex++) { + const FuncImport& fi = imports[funcIndex]; + + CallableOffsets offsets; + + if (!GenerateImportInterpExit(masm, fi, funcIndex, &throwLabel, &offsets)) + return false; + if (!code->codeRanges.emplaceBack(CodeRange::ImportInterpExit, funcIndex, offsets)) + return false; + + if (!GenerateImportJitExit(masm, fi, &throwLabel, &offsets)) + return false; + if (!code->codeRanges.emplaceBack(CodeRange::ImportJitExit, funcIndex, offsets)) + return false; + + if (!env.isAsmJS()) { + FuncOffsets offsets; + if (!GenerateImportFunction(masm, fi, env.funcSigs[funcIndex]->id, &offsets)) + return false; + if (!code->codeRanges.emplaceBack(funcIndex, /* bytecodeOffset = */ 0, offsets)) + return false; + } + } + + for (const FuncExport& fe : exports) { + Offsets offsets; + if (!GenerateEntry(masm, fe, &offsets)) + return false; + if (!code->codeRanges.emplaceBack(CodeRange::Entry, fe.funcIndex(), offsets)) + return false; + } + + for (Trap trap : MakeEnumeratedRange(Trap::Limit)) { + CallableOffsets offsets; + if (!GenerateTrapExit(masm, trap, &throwLabel, &offsets)) + return false; + if (!code->codeRanges.emplaceBack(trap, offsets)) + return false; + } + + Offsets offsets; + + if (!GenerateOutOfBoundsExit(masm, &throwLabel, &offsets)) + return false; + if (!code->codeRanges.emplaceBack(CodeRange::OutOfBoundsExit, offsets)) + return false; + + if (!GenerateUnalignedExit(masm, &throwLabel, &offsets)) + return false; + if (!code->codeRanges.emplaceBack(CodeRange::UnalignedExit, offsets)) + return false; + + if (!GenerateInterruptExit(masm, &throwLabel, &offsets)) + return false; + if (!code->codeRanges.emplaceBack(CodeRange::Interrupt, offsets)) + return false; + + { + CallableOffsets offsets; + if (!GenerateDebugTrapStub(masm, &throwLabel, &offsets)) + return false; + if (!code->codeRanges.emplaceBack(CodeRange::DebugTrap, offsets)) + return false; + } + + if (!GenerateThrowStub(masm, &throwLabel, &offsets)) + return false; + if (!code->codeRanges.emplaceBack(CodeRange::Throw, offsets)) + return false; + + masm.finish(); + if (masm.oom()) + return false; + + return code->swap(masm); } diff --git a/js/src/wasm/WasmStubs.h b/js/src/wasm/WasmStubs.h index 80a6d0121448..94c546644e1c 100644 --- a/js/src/wasm/WasmStubs.h +++ b/js/src/wasm/WasmStubs.h @@ -19,57 +19,18 @@ #ifndef wasm_stubs_h #define wasm_stubs_h -#include "wasm/WasmTypes.h" +#include "wasm/WasmGenerator.h" namespace js { - -namespace jit { - class MacroAssembler; - class Label; - enum ABIFunctionType; -} - namespace wasm { -class ExitReason; -class FuncExport; -class FuncImport; - -extern Offsets -GenerateEntry(jit::MacroAssembler& masm, const FuncExport& fe); - -extern FuncOffsets -GenerateImportFunction(jit::MacroAssembler& masm, const FuncImport& fi, SigIdDesc sigId); - -extern CallableOffsets -GenerateImportInterpExit(jit::MacroAssembler& masm, const FuncImport& fi, uint32_t funcImportIndex, - jit::Label* throwLabel); - -extern CallableOffsets -GenerateImportJitExit(jit::MacroAssembler& masm, const FuncImport& fi, jit::Label* throwLabel); - -extern CallableOffsets +extern bool GenerateBuiltinThunk(jit::MacroAssembler& masm, jit::ABIFunctionType abiType, ExitReason exitReason, - void* func); - -extern CallableOffsets -GenerateTrapExit(jit::MacroAssembler& masm, Trap trap, jit::Label* throwLabel); - -extern Offsets -GenerateOutOfBoundsExit(jit::MacroAssembler& masm, jit::Label* throwLabel); - -extern Offsets -GenerateUnalignedExit(jit::MacroAssembler& masm, jit::Label* throwLabel); - -extern Offsets -GenerateInterruptExit(jit::MacroAssembler& masm, jit::Label* throwLabel); - -extern Offsets -GenerateThrowStub(jit::MacroAssembler& masm, jit::Label* throwLabel); - -extern Offsets -GenerateDebugTrapStub(jit::MacroAssembler& masm, jit::Label* throwLabel); + void* funcPtr, CallableOffsets* offsets); +extern bool +GenerateStubs(const ModuleEnvironment& env, const FuncImportVector& imports, + const FuncExportVector& exports, CompiledCode* code); } // namespace wasm } // namespace js diff --git a/js/src/wasm/WasmTypes.cpp b/js/src/wasm/WasmTypes.cpp index 4b04e2a6dfd6..af742fbf26b6 100644 --- a/js/src/wasm/WasmTypes.cpp +++ b/js/src/wasm/WasmTypes.cpp @@ -681,23 +681,32 @@ CodeRange::CodeRange(Kind kind, Offsets offsets) MOZ_ASSERT(begin_ <= end_); #ifdef DEBUG switch (kind_) { - case Entry: - case DebugTrap: case FarJumpIsland: - case Inline: + case OutOfBoundsExit: + case UnalignedExit: case Throw: case Interrupt: break; - case Function: - case TrapExit: - case ImportJitExit: - case ImportInterpExit: - case BuiltinThunk: + default: MOZ_CRASH("should use more specific constructor"); } #endif } +CodeRange::CodeRange(Kind kind, uint32_t funcIndex, Offsets offsets) + : begin_(offsets.begin), + ret_(0), + end_(offsets.end), + funcIndex_(funcIndex), + funcLineOrBytecode_(0), + funcBeginToNormalEntry_(0), + funcBeginToTierEntry_(0), + kind_(kind) +{ + MOZ_ASSERT(kind == Entry); + MOZ_ASSERT(begin_ <= end_); +} + CodeRange::CodeRange(Kind kind, CallableOffsets offsets) : begin_(offsets.begin), ret_(offsets.ret), @@ -713,22 +722,44 @@ CodeRange::CodeRange(Kind kind, CallableOffsets offsets) #ifdef DEBUG switch (kind_) { case TrapExit: - case ImportJitExit: - case ImportInterpExit: + case DebugTrap: case BuiltinThunk: break; - case Entry: - case DebugTrap: - case FarJumpIsland: - case Inline: - case Throw: - case Interrupt: - case Function: + default: MOZ_CRASH("should use more specific constructor"); } #endif } +CodeRange::CodeRange(Kind kind, uint32_t funcIndex, CallableOffsets offsets) + : begin_(offsets.begin), + ret_(offsets.ret), + end_(offsets.end), + funcIndex_(funcIndex), + funcLineOrBytecode_(0), + funcBeginToNormalEntry_(0), + funcBeginToTierEntry_(0), + kind_(kind) +{ + MOZ_ASSERT(isImportExit()); + MOZ_ASSERT(begin_ < ret_); + MOZ_ASSERT(ret_ < end_); +} + +CodeRange::CodeRange(Trap trap, CallableOffsets offsets) + : begin_(offsets.begin), + ret_(offsets.ret), + end_(offsets.end), + trap_(trap), + funcLineOrBytecode_(0), + funcBeginToNormalEntry_(0), + funcBeginToTierEntry_(0), + kind_(TrapExit) +{ + MOZ_ASSERT(begin_ < ret_); + MOZ_ASSERT(ret_ < end_); +} + CodeRange::CodeRange(uint32_t funcIndex, uint32_t funcLineOrBytecode, FuncOffsets offsets) : begin_(offsets.begin), ret_(offsets.ret), diff --git a/js/src/wasm/WasmTypes.h b/js/src/wasm/WasmTypes.h index 429e4f3da56e..be07e3069061 100644 --- a/js/src/wasm/WasmTypes.h +++ b/js/src/wasm/WasmTypes.h @@ -864,193 +864,6 @@ struct SigWithId : Sig typedef Vector SigWithIdVector; typedef Vector SigWithIdPtrVector; -// The (,Callable,Func)Offsets classes are used to record the offsets of -// different key points in a CodeRange during compilation. - -struct Offsets -{ - explicit Offsets(uint32_t begin = 0, uint32_t end = 0) - : begin(begin), end(end) - {} - - // These define a [begin, end) contiguous range of instructions compiled - // into a CodeRange. - uint32_t begin; - uint32_t end; - - void offsetBy(uint32_t offset) { - begin += offset; - end += offset; - } -}; - -struct CallableOffsets : Offsets -{ - MOZ_IMPLICIT CallableOffsets(uint32_t ret = 0) - : Offsets(), ret(ret) - {} - - // The offset of the return instruction precedes 'end' by a variable number - // of instructions due to out-of-line codegen. - uint32_t ret; - - void offsetBy(uint32_t offset) { - Offsets::offsetBy(offset); - ret += offset; - } -}; - -struct FuncOffsets : CallableOffsets -{ - MOZ_IMPLICIT FuncOffsets() - : CallableOffsets(), - normalEntry(0), - tierEntry(0) - {} - - // Function CodeRanges have a table entry which takes an extra signature - // argument which is checked against the callee's signature before falling - // through to the normal prologue. The table entry is thus at the beginning - // of the CodeRange and the normal entry is at some offset after the table - // entry. - uint32_t normalEntry; - - // The tierEntry is the point within a function to which the patching code - // within a Tier-1 function jumps. It could be the instruction following - // the jump in the Tier-1 function, or the point following the standard - // prologue within a Tier-2 function. - uint32_t tierEntry; - - void offsetBy(uint32_t offset) { - CallableOffsets::offsetBy(offset); - normalEntry += offset; - tierEntry += offset; - } -}; - -// A CodeRange describes a single contiguous range of code within a wasm -// module's code segment. A CodeRange describes what the code does and, for -// function bodies, the name and source coordinates of the function. - -class CodeRange -{ - public: - enum Kind { - Function, // function definition - Entry, // calls into wasm from C++ - ImportJitExit, // fast-path calling from wasm into JIT code - ImportInterpExit, // slow-path calling from wasm into C++ interp - BuiltinThunk, // fast-path calling from wasm into a C++ native - TrapExit, // calls C++ to report and jumps to throw stub - DebugTrap, // calls C++ to handle debug event - FarJumpIsland, // inserted to connect otherwise out-of-range insns - Inline, // stub that is jumped-to within prologue/epilogue - Throw, // special stack-unwinding stub - Interrupt // stub executes asynchronously to interrupt wasm - }; - - private: - // All fields are treated as cacheable POD: - uint32_t begin_; - uint32_t ret_; - uint32_t end_; - uint32_t funcIndex_; - uint32_t funcLineOrBytecode_; - uint8_t funcBeginToNormalEntry_; - uint8_t funcBeginToTierEntry_; - Kind kind_ : 8; - - public: - CodeRange() = default; - CodeRange(Kind kind, Offsets offsets); - CodeRange(Kind kind, CallableOffsets offsets); - CodeRange(uint32_t funcIndex, uint32_t lineOrBytecode, FuncOffsets offsets); - - // All CodeRanges have a begin and end. - - uint32_t begin() const { - return begin_; - } - uint32_t end() const { - return end_; - } - - // Other fields are only available for certain CodeRange::Kinds. - - Kind kind() const { - return kind_; - } - - bool isFunction() const { - return kind() == Function; - } - bool isImportExit() const { - return kind() == ImportJitExit || kind() == ImportInterpExit || kind() == BuiltinThunk; - } - bool isTrapExit() const { - return kind() == TrapExit; - } - bool isInline() const { - return kind() == Inline; - } - bool isThunk() const { - return kind() == FarJumpIsland; - } - - // Every CodeRange except entry and inline stubs are callable and have a - // return statement. Asynchronous frame iteration needs to know the offset - // of the return instruction to calculate the frame pointer. - - uint32_t ret() const { - MOZ_ASSERT(isFunction() || isImportExit() || isTrapExit()); - return ret_; - } - - // Function CodeRanges have two entry points: one for normal calls (with a - // known signature) and one for table calls (which involves dynamic - // signature checking). - - uint32_t funcTableEntry() const { - MOZ_ASSERT(isFunction()); - return begin_; - } - uint32_t funcNormalEntry() const { - MOZ_ASSERT(isFunction()); - return begin_ + funcBeginToNormalEntry_; - } - uint32_t funcTierEntry() const { - MOZ_ASSERT(isFunction()); - return begin_ + funcBeginToTierEntry_; - } - uint32_t funcIndex() const { - MOZ_ASSERT(isFunction()); - return funcIndex_; - } - uint32_t funcLineOrBytecode() const { - MOZ_ASSERT(isFunction()); - return funcLineOrBytecode_; - } - - // A sorted array of CodeRanges can be looked up via BinarySearch and - // OffsetInCode. - - struct OffsetInCode { - size_t offset; - explicit OffsetInCode(size_t offset) : offset(offset) {} - bool operator==(const CodeRange& rhs) const { - return offset >= rhs.begin() && offset < rhs.end(); - } - bool operator<(const CodeRange& rhs) const { - return offset < rhs.begin(); - } - }; -}; - -WASM_DECLARE_POD_VECTOR(CodeRange, CodeRangeVector) - -extern const CodeRange* -LookupInSorted(const CodeRangeVector& codeRanges, CodeRange::OffsetInCode target); - // A wasm::Trap represents a wasm-defined trap that can occur during execution // which triggers a WebAssembly.RuntimeError. Generated code may jump to a Trap // symbolically, passing the bytecode offset to report as the trap offset. The @@ -1085,6 +898,207 @@ enum class Trap Limit }; +// The (,Callable,Func)Offsets classes are used to record the offsets of +// different key points in a CodeRange during compilation. + +struct Offsets +{ + explicit Offsets(uint32_t begin = 0, uint32_t end = 0) + : begin(begin), end(end) + {} + + // These define a [begin, end) contiguous range of instructions compiled + // into a CodeRange. + uint32_t begin; + uint32_t end; +}; + +struct CallableOffsets : Offsets +{ + MOZ_IMPLICIT CallableOffsets(uint32_t ret = 0) + : Offsets(), ret(ret) + {} + + // The offset of the return instruction precedes 'end' by a variable number + // of instructions due to out-of-line codegen. + uint32_t ret; +}; + +struct FuncOffsets : CallableOffsets +{ + MOZ_IMPLICIT FuncOffsets() + : CallableOffsets(), + normalEntry(0), + tierEntry(0) + {} + + // Function CodeRanges have a table entry which takes an extra signature + // argument which is checked against the callee's signature before falling + // through to the normal prologue. The table entry is thus at the beginning + // of the CodeRange and the normal entry is at some offset after the table + // entry. + uint32_t normalEntry; + + // The tierEntry is the point within a function to which the patching code + // within a Tier-1 function jumps. It could be the instruction following + // the jump in the Tier-1 function, or the point following the standard + // prologue within a Tier-2 function. + uint32_t tierEntry; +}; + +typedef Vector FuncOffsetsVector; + +// A CodeRange describes a single contiguous range of code within a wasm +// module's code segment. A CodeRange describes what the code does and, for +// function bodies, the name and source coordinates of the function. + +class CodeRange +{ + public: + enum Kind { + Function, // function definition + Entry, // calls into wasm from C++ + ImportJitExit, // fast-path calling from wasm into JIT code + ImportInterpExit, // slow-path calling from wasm into C++ interp + BuiltinThunk, // fast-path calling from wasm into a C++ native + TrapExit, // calls C++ to report and jumps to throw stub + DebugTrap, // calls C++ to handle debug event + FarJumpIsland, // inserted to connect otherwise out-of-range insns + OutOfBoundsExit, // stub jumped to by non-standard asm.js SIMD/Atomics + UnalignedExit, // stub jumped to by non-standard ARM unaligned trap + Interrupt, // stub executes asynchronously to interrupt wasm + Throw // special stack-unwinding stub jumped to by other stubs + }; + + private: + // All fields are treated as cacheable POD: + uint32_t begin_; + uint32_t ret_; + uint32_t end_; + union { + uint32_t funcIndex_; + Trap trap_; + }; + uint32_t funcLineOrBytecode_; + uint8_t funcBeginToNormalEntry_; + uint8_t funcBeginToTierEntry_; + Kind kind_ : 8; + + public: + CodeRange() = default; + CodeRange(Kind kind, Offsets offsets); + CodeRange(Kind kind, uint32_t funcIndex, Offsets offsets); + CodeRange(Kind kind, CallableOffsets offsets); + CodeRange(Kind kind, uint32_t funcIndex, CallableOffsets); + CodeRange(Trap trap, CallableOffsets offsets); + CodeRange(uint32_t funcIndex, uint32_t lineOrBytecode, FuncOffsets offsets); + + void offsetBy(uint32_t offset) { + begin_ += offset; + end_ += offset; + if (hasReturn()) + ret_ += offset; + } + + // All CodeRanges have a begin and end. + + uint32_t begin() const { + return begin_; + } + uint32_t end() const { + return end_; + } + + // Other fields are only available for certain CodeRange::Kinds. + + Kind kind() const { + return kind_; + } + + bool isFunction() const { + return kind() == Function; + } + bool isImportExit() const { + return kind() == ImportJitExit || kind() == ImportInterpExit || kind() == BuiltinThunk; + } + bool isTrapExit() const { + return kind() == TrapExit; + } + bool isThunk() const { + return kind() == FarJumpIsland; + } + + // Function, import exits and trap exits have standard callable prologues + // and epilogues. Asynchronous frame iteration needs to know the offset of + // the return instruction to calculate the frame pointer. + + bool hasReturn() const { + return isFunction() || isImportExit() || isTrapExit(); + } + uint32_t ret() const { + MOZ_ASSERT(hasReturn()); + return ret_; + } + + // Functions, export stubs and import stubs all have an associated function + // index. + + bool hasFuncIndex() const { + return isFunction() || isImportExit() || kind() == Entry; + } + uint32_t funcIndex() const { + MOZ_ASSERT(hasFuncIndex()); + return funcIndex_; + } + + // TrapExit CodeRanges have a Trap field. + + Trap trap() const { + MOZ_ASSERT(isTrapExit()); + return trap_; + } + + // Function CodeRanges have two entry points: one for normal calls (with a + // known signature) and one for table calls (which involves dynamic + // signature checking). + + uint32_t funcTableEntry() const { + MOZ_ASSERT(isFunction()); + return begin_; + } + uint32_t funcNormalEntry() const { + MOZ_ASSERT(isFunction()); + return begin_ + funcBeginToNormalEntry_; + } + uint32_t funcTierEntry() const { + MOZ_ASSERT(isFunction()); + return begin_ + funcBeginToTierEntry_; + } + uint32_t funcLineOrBytecode() const { + MOZ_ASSERT(isFunction()); + return funcLineOrBytecode_; + } + + // A sorted array of CodeRanges can be looked up via BinarySearch and + // OffsetInCode. + + struct OffsetInCode { + size_t offset; + explicit OffsetInCode(size_t offset) : offset(offset) {} + bool operator==(const CodeRange& rhs) const { + return offset >= rhs.begin() && offset < rhs.end(); + } + bool operator<(const CodeRange& rhs) const { + return offset < rhs.begin(); + } + }; +}; + +WASM_DECLARE_POD_VECTOR(CodeRange, CodeRangeVector) + +extern const CodeRange* +LookupInSorted(const CodeRangeVector& codeRanges, CodeRange::OffsetInCode target); + // A wrapper around the bytecode offset of a wasm instruction within a whole // module, used for trap offsets or call offsets. These offsets should refer to // the first byte of the instruction that triggered the trap / did the call and @@ -1149,8 +1163,7 @@ class CallSite : public CallSiteDesc returnAddressOffset_(returnAddressOffset) { } - void setReturnAddressOffset(uint32_t r) { returnAddressOffset_ = r; } - void offsetReturnAddressBy(int32_t o) { returnAddressOffset_ += o; } + void offsetBy(int32_t delta) { returnAddressOffset_ += delta; } uint32_t returnAddressOffset() const { return returnAddressOffset_; } };