From 7fe2913bfc3c19a8b7c3a7beabeb9c8bb0bfb980 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Tue, 27 May 2014 14:08:30 -0400 Subject: [PATCH] Backed out changeset 2c631967ab9e (bug 999651) for B2G crashes. CLOSED TREE --- content/base/src/DOMParser.cpp | 2 - content/base/src/WebSocket.cpp | 10 +- content/base/src/nsDOMDataChannel.cpp | 10 +- content/base/src/nsXMLHttpRequest.cpp | 11 +- .../canvas/src/CanvasRenderingContext2D.cpp | 14 +-- content/canvas/src/CanvasRenderingContext2D.h | 2 +- content/canvas/src/ImageData.cpp | 2 - content/canvas/src/WebGLContext.h | 15 --- content/canvas/src/WebGLContextBuffers.cpp | 16 +-- content/canvas/src/WebGLContextGL.cpp | 46 ++------ content/media/mediasource/SourceBuffer.cpp | 4 - content/media/webaudio/AnalyserNode.cpp | 8 -- content/media/webaudio/AudioBuffer.cpp | 4 - content/media/webaudio/AudioContext.cpp | 5 - content/media/webaudio/AudioParam.h | 1 - content/media/webaudio/BiquadFilterNode.cpp | 4 - content/media/webaudio/WaveShaperNode.cpp | 10 +- dom/base/Crypto.cpp | 1 - dom/base/Navigator.cpp | 6 +- dom/bindings/TypedArray.h | 108 ++++++----------- dom/crypto/CryptoBuffer.cpp | 2 - dom/crypto/CryptoBuffer.h | 8 +- dom/encoding/TextDecoder.h | 1 - dom/filehandle/LockedFile.cpp | 1 - dom/filesystem/Directory.cpp | 2 - js/src/builtin/SIMD.cpp | 8 +- js/src/builtin/TypedObject.cpp | 8 +- js/src/builtin/TypedObject.js | 8 +- js/src/jit/AsmJSLink.cpp | 29 +++-- js/src/jit/IonBuilder.cpp | 98 +++++++--------- js/src/jit/IonBuilder.h | 24 +--- js/src/jit/MIR.h | 14 +-- js/src/js.msg | 4 +- js/src/jsfriendapi.h | 88 -------------- js/src/jsinfer.cpp | 25 ++-- js/src/jsinfer.h | 2 +- js/src/vm/ArrayBufferObject.cpp | 51 +------- js/src/vm/TypedArrayObject.cpp | 111 +++++++----------- js/src/vm/TypedArrayObject.h | 10 +- netwerk/base/src/ArrayBufferInputStream.cpp | 11 -- xpcom/io/nsBinaryStream.cpp | 56 ++------- 41 files changed, 211 insertions(+), 629 deletions(-) diff --git a/content/base/src/DOMParser.cpp b/content/base/src/DOMParser.cpp index a868a1c8c47..36ed0484bff 100644 --- a/content/base/src/DOMParser.cpp +++ b/content/base/src/DOMParser.cpp @@ -143,8 +143,6 @@ already_AddRefed DOMParser::ParseFromBuffer(const Uint8Array& aBuf, uint32_t aBufLen, SupportedType aType, ErrorResult& rv) { - aBuf.ComputeLengthAndData(); - if (aBufLen > aBuf.Length()) { rv.Throw(NS_ERROR_XPC_NOT_ENOUGH_ELEMENTS_IN_ARRAY); return nullptr; diff --git a/content/base/src/WebSocket.cpp b/content/base/src/WebSocket.cpp index 7aecf06725f..7124bb2edfd 100644 --- a/content/base/src/WebSocket.cpp +++ b/content/base/src/WebSocket.cpp @@ -1212,10 +1212,7 @@ WebSocket::Send(const ArrayBuffer& aData, { NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread"); - aData.ComputeLengthAndData(); - - static_assert(sizeof(*aData.Data()) == 1, "byte-sized data required"); - + MOZ_ASSERT(sizeof(*aData.Data()) == 1); uint32_t len = aData.Length(); char* data = reinterpret_cast(aData.Data()); @@ -1229,10 +1226,7 @@ WebSocket::Send(const ArrayBufferView& aData, { NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread"); - aData.ComputeLengthAndData(); - - static_assert(sizeof(*aData.Data()) == 1, "byte-sized data required"); - + MOZ_ASSERT(sizeof(*aData.Data()) == 1); uint32_t len = aData.Length(); char* data = reinterpret_cast(aData.Data()); diff --git a/content/base/src/nsDOMDataChannel.cpp b/content/base/src/nsDOMDataChannel.cpp index 7bc847a93dc..91126476c1c 100644 --- a/content/base/src/nsDOMDataChannel.cpp +++ b/content/base/src/nsDOMDataChannel.cpp @@ -303,10 +303,7 @@ nsDOMDataChannel::Send(const ArrayBuffer& aData, ErrorResult& aRv) { NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread"); - aData.ComputeLengthAndData(); - - static_assert(sizeof(*aData.Data()) == 1, "byte-sized data required"); - + MOZ_ASSERT(sizeof(*aData.Data()) == 1); uint32_t len = aData.Length(); char* data = reinterpret_cast(aData.Data()); @@ -319,10 +316,7 @@ nsDOMDataChannel::Send(const ArrayBufferView& aData, ErrorResult& aRv) { NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread"); - aData.ComputeLengthAndData(); - - static_assert(sizeof(*aData.Data()) == 1, "byte-sized data required"); - + MOZ_ASSERT(sizeof(*aData.Data()) == 1); uint32_t len = aData.Length(); char* data = reinterpret_cast(aData.Data()); diff --git a/content/base/src/nsXMLHttpRequest.cpp b/content/base/src/nsXMLHttpRequest.cpp index 7976290b03d..23f4217ea0b 100644 --- a/content/base/src/nsXMLHttpRequest.cpp +++ b/content/base/src/nsXMLHttpRequest.cpp @@ -2529,7 +2529,6 @@ GetRequestBody(nsIVariant* aBody, nsIInputStream** aResult, uint64_t* aContentLe JS::Rooted obj(cx, realVal.toObjectOrNull()); if (JS_IsArrayBufferObject(obj)) { ArrayBuffer buf(obj); - buf.ComputeLengthAndData(); return GetRequestBody(buf.Data(), buf.Length(), aResult, aContentLength, aContentType, aCharset); } @@ -2573,16 +2572,14 @@ nsXMLHttpRequest::GetRequestBody(nsIVariant* aVariant, switch (body.GetType()) { case nsXMLHttpRequest::RequestBody::ArrayBuffer: { - const ArrayBuffer* buffer = value.mArrayBuffer; - buffer->ComputeLengthAndData(); - return ::GetRequestBody(buffer->Data(), buffer->Length(), aResult, + return ::GetRequestBody(value.mArrayBuffer->Data(), + value.mArrayBuffer->Length(), aResult, aContentLength, aContentType, aCharset); } case nsXMLHttpRequest::RequestBody::ArrayBufferView: { - const ArrayBufferView* view = value.mArrayBufferView; - view->ComputeLengthAndData(); - return ::GetRequestBody(view->Data(), view->Length(), aResult, + return ::GetRequestBody(value.mArrayBufferView->Data(), + value.mArrayBufferView->Length(), aResult, aContentLength, aContentType, aCharset); } case nsXMLHttpRequest::RequestBody::Blob: diff --git a/content/canvas/src/CanvasRenderingContext2D.cpp b/content/canvas/src/CanvasRenderingContext2D.cpp index b4eaca58873..f081cfcde97 100644 --- a/content/canvas/src/CanvasRenderingContext2D.cpp +++ b/content/canvas/src/CanvasRenderingContext2D.cpp @@ -4010,7 +4010,7 @@ CanvasRenderingContext2D::PutImageData(ImageData& imageData, double dx, error = PutImageData_explicit(JS_DoubleToInt32(dx), JS_DoubleToInt32(dy), imageData.Width(), imageData.Height(), - &arr, false, 0, 0, 0, 0); + arr.Data(), arr.Length(), false, 0, 0, 0, 0); } void @@ -4024,7 +4024,7 @@ CanvasRenderingContext2D::PutImageData(ImageData& imageData, double dx, error = PutImageData_explicit(JS_DoubleToInt32(dx), JS_DoubleToInt32(dy), imageData.Width(), imageData.Height(), - &arr, true, + arr.Data(), arr.Length(), true, JS_DoubleToInt32(dirtyX), JS_DoubleToInt32(dirtyY), JS_DoubleToInt32(dirtyWidth), @@ -4036,7 +4036,7 @@ CanvasRenderingContext2D::PutImageData(ImageData& imageData, double dx, nsresult CanvasRenderingContext2D::PutImageData_explicit(int32_t x, int32_t y, uint32_t w, uint32_t h, - dom::Uint8ClampedArray* aArray, + unsigned char *aData, uint32_t aDataLen, bool hasDirtyRect, int32_t dirtyX, int32_t dirtyY, int32_t dirtyWidth, int32_t dirtyHeight) { @@ -4089,12 +4089,8 @@ CanvasRenderingContext2D::PutImageData_explicit(int32_t x, int32_t y, uint32_t w return NS_OK; } - aArray->ComputeLengthAndData(); - - uint32_t dataLen = aArray->Length(); - uint32_t len = w * h * 4; - if (dataLen != len) { + if (aDataLen != len) { return NS_ERROR_DOM_SYNTAX_ERR; } @@ -4105,7 +4101,7 @@ CanvasRenderingContext2D::PutImageData_explicit(int32_t x, int32_t y, uint32_t w return NS_ERROR_FAILURE; } - uint8_t *src = aArray->Data(); + uint8_t *src = aData; uint8_t *dst = imgsurf->Data(); for (uint32_t j = 0; j < h; j++) { diff --git a/content/canvas/src/CanvasRenderingContext2D.h b/content/canvas/src/CanvasRenderingContext2D.h index a8357b6b64e..14d29dab249 100644 --- a/content/canvas/src/CanvasRenderingContext2D.h +++ b/content/canvas/src/CanvasRenderingContext2D.h @@ -551,7 +551,7 @@ protected: JSObject** aRetval); nsresult PutImageData_explicit(int32_t x, int32_t y, uint32_t w, uint32_t h, - dom::Uint8ClampedArray* aArray, + unsigned char *aData, uint32_t aDataLen, bool hasDirtyRect, int32_t dirtyX, int32_t dirtyY, int32_t dirtyWidth, int32_t dirtyHeight); diff --git a/content/canvas/src/ImageData.cpp b/content/canvas/src/ImageData.cpp index ebb10219a3d..3e331b4b249 100644 --- a/content/canvas/src/ImageData.cpp +++ b/content/canvas/src/ImageData.cpp @@ -70,8 +70,6 @@ ImageData::Constructor(const GlobalObject& aGlobal, const Optional& aHeight, ErrorResult& aRv) { - aData.ComputeLengthAndData(); - uint32_t length = aData.Length(); if (length == 0 || length % 4) { aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); diff --git a/content/canvas/src/WebGLContext.h b/content/canvas/src/WebGLContext.h index 37127ea7519..e3c127bc7ee 100644 --- a/content/canvas/src/WebGLContext.h +++ b/content/canvas/src/WebGLContext.h @@ -511,7 +511,6 @@ public: void Uniform1iv(WebGLUniformLocation* location, const dom::Int32Array& arr) { - arr.ComputeLengthAndData(); Uniform1iv_base(location, arr.Length(), arr.Data()); } void Uniform1iv(WebGLUniformLocation* location, @@ -523,7 +522,6 @@ public: void Uniform2iv(WebGLUniformLocation* location, const dom::Int32Array& arr) { - arr.ComputeLengthAndData(); Uniform2iv_base(location, arr.Length(), arr.Data()); } void Uniform2iv(WebGLUniformLocation* location, @@ -535,7 +533,6 @@ public: void Uniform3iv(WebGLUniformLocation* location, const dom::Int32Array& arr) { - arr.ComputeLengthAndData(); Uniform3iv_base(location, arr.Length(), arr.Data()); } void Uniform3iv(WebGLUniformLocation* location, @@ -547,7 +544,6 @@ public: void Uniform4iv(WebGLUniformLocation* location, const dom::Int32Array& arr) { - arr.ComputeLengthAndData(); Uniform4iv_base(location, arr.Length(), arr.Data()); } void Uniform4iv(WebGLUniformLocation* location, @@ -559,7 +555,6 @@ public: void Uniform1fv(WebGLUniformLocation* location, const dom::Float32Array& arr) { - arr.ComputeLengthAndData(); Uniform1fv_base(location, arr.Length(), arr.Data()); } void Uniform1fv(WebGLUniformLocation* location, @@ -571,7 +566,6 @@ public: void Uniform2fv(WebGLUniformLocation* location, const dom::Float32Array& arr) { - arr.ComputeLengthAndData(); Uniform2fv_base(location, arr.Length(), arr.Data()); } void Uniform2fv(WebGLUniformLocation* location, @@ -583,7 +577,6 @@ public: void Uniform3fv(WebGLUniformLocation* location, const dom::Float32Array& arr) { - arr.ComputeLengthAndData(); Uniform3fv_base(location, arr.Length(), arr.Data()); } void Uniform3fv(WebGLUniformLocation* location, @@ -595,7 +588,6 @@ public: void Uniform4fv(WebGLUniformLocation* location, const dom::Float32Array& arr) { - arr.ComputeLengthAndData(); Uniform4fv_base(location, arr.Length(), arr.Data()); } void Uniform4fv(WebGLUniformLocation* location, @@ -608,7 +600,6 @@ public: void UniformMatrix2fv(WebGLUniformLocation* location, WebGLboolean transpose, const dom::Float32Array &value) { - value.ComputeLengthAndData(); UniformMatrix2fv_base(location, transpose, value.Length(), value.Data()); } void UniformMatrix2fv(WebGLUniformLocation* location, @@ -624,7 +615,6 @@ public: void UniformMatrix3fv(WebGLUniformLocation* location, WebGLboolean transpose, const dom::Float32Array &value) { - value.ComputeLengthAndData(); UniformMatrix3fv_base(location, transpose, value.Length(), value.Data()); } void UniformMatrix3fv(WebGLUniformLocation* location, @@ -640,7 +630,6 @@ public: void UniformMatrix4fv(WebGLUniformLocation* location, WebGLboolean transpose, const dom::Float32Array &value) { - value.ComputeLengthAndData(); UniformMatrix4fv_base(location, transpose, value.Length(), value.Data()); } void UniformMatrix4fv(WebGLUniformLocation* location, @@ -764,7 +753,6 @@ public: GLfloat x2, GLfloat x3); void VertexAttrib1fv(GLuint idx, const dom::Float32Array &arr) { - arr.ComputeLengthAndData(); VertexAttrib1fv_base(idx, arr.Length(), arr.Data()); } void VertexAttrib1fv(GLuint idx, const dom::Sequence& arr) { @@ -772,7 +760,6 @@ public: } void VertexAttrib2fv(GLuint idx, const dom::Float32Array &arr) { - arr.ComputeLengthAndData(); VertexAttrib2fv_base(idx, arr.Length(), arr.Data()); } void VertexAttrib2fv(GLuint idx, const dom::Sequence& arr) { @@ -780,7 +767,6 @@ public: } void VertexAttrib3fv(GLuint idx, const dom::Float32Array &arr) { - arr.ComputeLengthAndData(); VertexAttrib3fv_base(idx, arr.Length(), arr.Data()); } void VertexAttrib3fv(GLuint idx, const dom::Sequence& arr) { @@ -788,7 +774,6 @@ public: } void VertexAttrib4fv(GLuint idx, const dom::Float32Array &arr) { - arr.ComputeLengthAndData(); VertexAttrib4fv_base(idx, arr.Length(), arr.Data()); } void VertexAttrib4fv(GLuint idx, const dom::Sequence& arr) { diff --git a/content/canvas/src/WebGLContextBuffers.cpp b/content/canvas/src/WebGLContextBuffers.cpp index 680bd6df0e6..73b1d16e449 100644 --- a/content/canvas/src/WebGLContextBuffers.cpp +++ b/content/canvas/src/WebGLContextBuffers.cpp @@ -203,10 +203,8 @@ WebGLContext::BufferData(GLenum target, } const ArrayBuffer& data = maybeData.Value(); - data.ComputeLengthAndData(); - // Careful: data.Length() could conceivably be any uint32_t, but GLsizeiptr - // is like intptr_t. + // careful: data.Length() could conceivably be any size_t, but GLsizeiptr is like intptr_t. if (!CheckedInt(data.Length()).isValid()) return ErrorOutOfMemory("bufferData: bad size"); @@ -255,10 +253,7 @@ WebGLContext::BufferData(GLenum target, const ArrayBufferView& data, if (!boundBuffer) return ErrorInvalidOperation("bufferData: no buffer bound!"); - data.ComputeLengthAndData(); - - // Careful: data.Length() could conceivably be any uint32_t, but GLsizeiptr - // is like intptr_t. + // careful: data.Length() could conceivably be any size_t, but GLsizeiptr is like intptr_t. if (!CheckedInt(data.Length()).isValid()) return ErrorOutOfMemory("bufferData: bad size"); @@ -295,6 +290,8 @@ WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset, return; } + const ArrayBuffer& data = maybeData.Value(); + if (byteOffset < 0) return ErrorInvalidValue("bufferSubData: negative offset"); @@ -303,9 +300,6 @@ WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset, if (!boundBuffer) return ErrorInvalidOperation("bufferData: no buffer bound!"); - const ArrayBuffer& data = maybeData.Value(); - data.ComputeLengthAndData(); - CheckedInt checked_neededByteLength = CheckedInt(byteOffset) + data.Length(); if (!checked_neededByteLength.isValid()) return ErrorInvalidValue("bufferSubData: integer overflow computing the needed byte length"); @@ -342,8 +336,6 @@ WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset, if (!boundBuffer) return ErrorInvalidOperation("bufferSubData: no buffer bound!"); - data.ComputeLengthAndData(); - CheckedInt checked_neededByteLength = CheckedInt(byteOffset) + data.Length(); if (!checked_neededByteLength.isValid()) return ErrorInvalidValue("bufferSubData: integer overflow computing the needed byte length"); diff --git a/content/canvas/src/WebGLContextGL.cpp b/content/canvas/src/WebGLContextGL.cpp index 3ef14e968eb..4d9dc17c52d 100644 --- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -2126,8 +2126,7 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width, if (!isReadTypeValid) return ErrorInvalidEnum("readPixels: Bad type", type); - const ArrayBufferView& pixbuf = pixels.Value(); - int dataType = JS_GetArrayBufferViewType(pixbuf.Obj()); + int dataType = JS_GetArrayBufferViewType(pixels.Value().Obj()); // Check the pixels param type if (dataType != requiredDataType) @@ -2145,15 +2144,11 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width, if (!checked_neededByteLength.isValid()) return ErrorInvalidOperation("readPixels: integer overflow computing the needed buffer size"); - // Compute length and data. Don't reenter after this point, lest the - // precomputed go out of sync with the instant length/data. - pixbuf.ComputeLengthAndData(); - - uint32_t dataByteLen = pixbuf.Length(); + uint32_t dataByteLen = JS_GetTypedArrayByteLength(pixels.Value().Obj()); if (checked_neededByteLength.value() > dataByteLen) return ErrorInvalidOperation("readPixels: buffer too small"); - void* data = pixbuf.Data(); + void* data = pixels.Value().Data(); if (!data) { ErrorOutOfMemory("readPixels: buffer storage is null. Did we run out of memory?"); return rv.Throw(NS_ERROR_OUT_OF_MEMORY); @@ -3266,8 +3261,6 @@ WebGLContext::CompressedTexImage2D(GLenum target, GLint level, GLenum internalfo return; } - view.ComputeLengthAndData(); - uint32_t byteLength = view.Length(); if (!ValidateCompTexImageDataSize(target, internalformat, width, height, byteLength, func)) { return; @@ -3311,8 +3304,6 @@ WebGLContext::CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, MOZ_ASSERT(tex); WebGLTexture::ImageInfo& levelInfo = tex->ImageInfoAt(target, level); - view.ComputeLengthAndData(); - uint32_t byteLength = view.Length(); if (!ValidateCompTexImageDataSize(target, format, width, height, byteLength, func)) return; @@ -3679,24 +3670,10 @@ WebGLContext::TexImage2D(GLenum target, GLint level, if (IsContextLost()) return; - void* data; - uint32_t length; - int jsArrayType; - if (pixels.IsNull()) { - data = nullptr; - length = 0; - jsArrayType = -1; - } else { - const ArrayBufferView& view = pixels.Value(); - view.ComputeLengthAndData(); - - data = view.Data(); - length = view.Length(); - jsArrayType = int(JS_GetArrayBufferViewType(view.Obj())); - } - return TexImage2D_base(target, level, internalformat, width, height, 0, border, format, type, - data, length, jsArrayType, + pixels.IsNull() ? 0 : pixels.Value().Data(), + pixels.IsNull() ? 0 : pixels.Value().Length(), + pixels.IsNull() ? -1 : (int)JS_GetArrayBufferViewType(pixels.Value().Obj()), WebGLTexelFormat::Auto, false); } @@ -3714,8 +3691,6 @@ WebGLContext::TexImage2D(GLenum target, GLint level, } Uint8ClampedArray arr(pixels->GetDataObject()); - arr.ComputeLengthAndData(); - return TexImage2D_base(target, level, internalformat, pixels->Width(), pixels->Height(), 4*pixels->Width(), 0, format, type, arr.Data(), arr.Length(), -1, @@ -3824,13 +3799,10 @@ WebGLContext::TexSubImage2D(GLenum target, GLint level, if (pixels.IsNull()) return ErrorInvalidValue("texSubImage2D: pixels must not be null!"); - const ArrayBufferView& view = pixels.Value(); - view.ComputeLengthAndData(); - return TexSubImage2D_base(target, level, xoffset, yoffset, width, height, 0, format, type, - view.Data(), view.Length(), - JS_GetArrayBufferViewType(view.Obj()), + pixels.Value().Data(), pixels.Value().Length(), + JS_GetArrayBufferViewType(pixels.Value().Obj()), WebGLTexelFormat::Auto, false); } @@ -3847,8 +3819,6 @@ WebGLContext::TexSubImage2D(GLenum target, GLint level, return ErrorInvalidValue("texSubImage2D: pixels must not be null!"); Uint8ClampedArray arr(pixels->GetDataObject()); - arr.ComputeLengthAndData(); - return TexSubImage2D_base(target, level, xoffset, yoffset, pixels->Width(), pixels->Height(), 4*pixels->Width(), format, type, diff --git a/content/media/mediasource/SourceBuffer.cpp b/content/media/mediasource/SourceBuffer.cpp index d2eac2f29fa..8896b3420bf 100644 --- a/content/media/mediasource/SourceBuffer.cpp +++ b/content/media/mediasource/SourceBuffer.cpp @@ -250,16 +250,12 @@ SourceBuffer::SetAppendWindowEnd(double aAppendWindowEnd, ErrorResult& aRv) void SourceBuffer::AppendBuffer(const ArrayBuffer& aData, ErrorResult& aRv) { - aData.ComputeLengthAndData(); - AppendData(aData.Data(), aData.Length(), aRv); } void SourceBuffer::AppendBuffer(const ArrayBufferView& aData, ErrorResult& aRv) { - aData.ComputeLengthAndData(); - AppendData(aData.Data(), aData.Length(), aRv); } diff --git a/content/media/webaudio/AnalyserNode.cpp b/content/media/webaudio/AnalyserNode.cpp index 99bf0a70f4e..87140beca92 100644 --- a/content/media/webaudio/AnalyserNode.cpp +++ b/content/media/webaudio/AnalyserNode.cpp @@ -171,8 +171,6 @@ AnalyserNode::GetFloatFrequencyData(const Float32Array& aArray) return; } - aArray.ComputeLengthAndData(); - float* buffer = aArray.Data(); size_t length = std::min(size_t(aArray.Length()), mOutputBuffer.Length()); @@ -191,8 +189,6 @@ AnalyserNode::GetByteFrequencyData(const Uint8Array& aArray) const double rangeScaleFactor = 1.0 / (mMaxDecibels - mMinDecibels); - aArray.ComputeLengthAndData(); - unsigned char* buffer = aArray.Data(); size_t length = std::min(size_t(aArray.Length()), mOutputBuffer.Length()); @@ -208,8 +204,6 @@ AnalyserNode::GetByteFrequencyData(const Uint8Array& aArray) void AnalyserNode::GetFloatTimeDomainData(const Float32Array& aArray) { - aArray.ComputeLengthAndData(); - float* buffer = aArray.Data(); size_t length = std::min(size_t(aArray.Length()), mBuffer.Length()); @@ -221,8 +215,6 @@ AnalyserNode::GetFloatTimeDomainData(const Float32Array& aArray) void AnalyserNode::GetByteTimeDomainData(const Uint8Array& aArray) { - aArray.ComputeLengthAndData(); - unsigned char* buffer = aArray.Data(); size_t length = std::min(size_t(aArray.Length()), mBuffer.Length()); diff --git a/content/media/webaudio/AudioBuffer.cpp b/content/media/webaudio/AudioBuffer.cpp index 0e5adc2f918..cd3c29ab955 100644 --- a/content/media/webaudio/AudioBuffer.cpp +++ b/content/media/webaudio/AudioBuffer.cpp @@ -130,8 +130,6 @@ void AudioBuffer::CopyFromChannel(const Float32Array& aDestination, uint32_t aChannelNumber, uint32_t aStartInChannel, ErrorResult& aRv) { - aDestination.ComputeLengthAndData(); - uint32_t length = aDestination.Length(); CheckedInt end = aStartInChannel; end += length; @@ -158,8 +156,6 @@ AudioBuffer::CopyToChannel(JSContext* aJSContext, const Float32Array& aSource, uint32_t aChannelNumber, uint32_t aStartInChannel, ErrorResult& aRv) { - aSource.ComputeLengthAndData(); - uint32_t length = aSource.Length(); CheckedInt end = aStartInChannel; end += length; diff --git a/content/media/webaudio/AudioContext.cpp b/content/media/webaudio/AudioContext.cpp index 62ccd3d1b39..5cb293f8ef7 100644 --- a/content/media/webaudio/AudioContext.cpp +++ b/content/media/webaudio/AudioContext.cpp @@ -400,9 +400,6 @@ AudioContext::CreatePeriodicWave(const Float32Array& aRealData, const Float32Array& aImagData, ErrorResult& aRv) { - aRealData.ComputeLengthAndData(); - aImagData.ComputeLengthAndData(); - if (aRealData.Length() != aImagData.Length() || aRealData.Length() == 0 || aRealData.Length() > 4096) { @@ -437,8 +434,6 @@ AudioContext::DecodeAudioData(const ArrayBuffer& aBuffer, JSContext* cx = jsapi.cx(); JSAutoCompartment ac(cx, aBuffer.Obj()); - aBuffer.ComputeLengthAndData(); - // Neuter the array buffer size_t length = aBuffer.Length(); JS::RootedObject obj(cx, aBuffer.Obj()); diff --git a/content/media/webaudio/AudioParam.h b/content/media/webaudio/AudioParam.h index e3869f27a14..30045251132 100644 --- a/content/media/webaudio/AudioParam.h +++ b/content/media/webaudio/AudioParam.h @@ -55,7 +55,6 @@ public: aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); return; } - aValues.ComputeLengthAndData(); AudioParamTimeline::SetValueCurveAtTime(aValues.Data(), aValues.Length(), DOMTimeToStreamTime(aStartTime), aDuration, aRv); mCallback(mNode); diff --git a/content/media/webaudio/BiquadFilterNode.cpp b/content/media/webaudio/BiquadFilterNode.cpp index 42da4074ccf..341620dd056 100644 --- a/content/media/webaudio/BiquadFilterNode.cpp +++ b/content/media/webaudio/BiquadFilterNode.cpp @@ -308,10 +308,6 @@ BiquadFilterNode::GetFrequencyResponse(const Float32Array& aFrequencyHz, const Float32Array& aMagResponse, const Float32Array& aPhaseResponse) { - aFrequencyHz.ComputeLengthAndData(); - aMagResponse.ComputeLengthAndData(); - aPhaseResponse.ComputeLengthAndData(); - uint32_t length = std::min(std::min(aFrequencyHz.Length(), aMagResponse.Length()), aPhaseResponse.Length()); if (!length) { diff --git a/content/media/webaudio/WaveShaperNode.cpp b/content/media/webaudio/WaveShaperNode.cpp index 9a28a587a83..292f456f75a 100644 --- a/content/media/webaudio/WaveShaperNode.cpp +++ b/content/media/webaudio/WaveShaperNode.cpp @@ -313,14 +313,10 @@ WaveShaperNode::SetCurve(const Nullable& aCurve) { nsTArray curve; if (!aCurve.IsNull()) { - const Float32Array& floats = aCurve.Value(); + mCurve = aCurve.Value().Obj(); - mCurve = floats.Obj(); - - floats.ComputeLengthAndData(); - - curve.SetLength(floats.Length()); - PodCopy(curve.Elements(), floats.Data(), floats.Length()); + curve.SetLength(aCurve.Value().Length()); + PodCopy(curve.Elements(), aCurve.Value().Data(), aCurve.Value().Length()); } else { mCurve = nullptr; } diff --git a/dom/base/Crypto.cpp b/dom/base/Crypto.cpp index 5233bb715c7..9cf78ced0ee 100644 --- a/dom/base/Crypto.cpp +++ b/dom/base/Crypto.cpp @@ -79,7 +79,6 @@ Crypto::GetRandomValues(JSContext* aCx, const ArrayBufferView& aArray, return nullptr; } - aArray.ComputeLengthAndData(); uint32_t dataLen = aArray.Length(); if (dataLen == 0) { NS_WARNING("ArrayBufferView length is 0, cannot continue"); diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index b78017228bc..cdad021ccdb 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -1243,10 +1243,8 @@ Navigator::SendBeacon(const nsAString& aUrl, return false; } - ArrayBufferView& view = aData.Value().GetAsArrayBufferView(); - view.ComputeLengthAndData(); - rv = strStream->SetData(reinterpret_cast(view.Data()), - view.Length()); + rv = strStream->SetData(reinterpret_cast(aData.Value().GetAsArrayBufferView().Data()), + aData.Value().GetAsArrayBufferView().Length()); if (NS_FAILED(rv)) { aRv.Throw(NS_ERROR_FAILURE); diff --git a/dom/bindings/TypedArray.h b/dom/bindings/TypedArray.h index d1b1d416313..20a81117936 100644 --- a/dom/bindings/TypedArray.h +++ b/dom/bindings/TypedArray.h @@ -26,7 +26,7 @@ struct TypedArrayObjectStorage : AllTypedArraysBase { protected: JSObject* mObj; - TypedArrayObjectStorage(JSObject *obj) : mObj(obj) + TypedArrayObjectStorage() { } @@ -55,43 +55,32 @@ private: * or array buffer object. */ template + JSObject* UnboxArray(JSObject*, uint32_t*, T**)> struct TypedArray_base : public TypedArrayObjectStorage { typedef T element_type; TypedArray_base(JSObject* obj) - : TypedArrayObjectStorage(obj), - mData(nullptr), - mLength(0), - mComputed(false) { - MOZ_ASSERT(obj != nullptr); + DoInit(obj); } TypedArray_base() - : TypedArrayObjectStorage(nullptr), - mData(nullptr), - mLength(0), - mComputed(false) { + mObj = nullptr; } explicit TypedArray_base(TypedArray_base&& aOther) : TypedArrayObjectStorage(Move(aOther)), mData(aOther.mData), - mLength(aOther.mLength), - mComputed(aOther.mComputed) + mLength(aOther.mLength) { aOther.mData = nullptr; aOther.mLength = 0; - aOther.mComputed = false; } private: - mutable T* mData; - mutable uint32_t mLength; - mutable bool mComputed; + T* mData; + uint32_t mLength; public: inline bool Init(JSObject* obj) @@ -106,12 +95,12 @@ public: } inline T *Data() const { - MOZ_ASSERT(mComputed); + MOZ_ASSERT(inited()); return mData; } inline uint32_t Length() const { - MOZ_ASSERT(mComputed); + MOZ_ASSERT(inited()); return mLength; } @@ -126,26 +115,10 @@ public: JS::MutableHandle::fromMarkedLocation(&mObj)); } - inline void ComputeLengthAndData() const - { - MOZ_ASSERT(inited()); - MOZ_ASSERT(!mComputed); - GetLengthAndData(mObj, &mLength, &mData); - mComputed = true; - } - protected: inline void DoInit(JSObject* obj) { - mObj = UnwrapArray(obj); - } - - inline void ComputeData() const { - MOZ_ASSERT(inited()); - if (!mComputed) { - GetLengthAndData(mObj, &mLength, &mData); - mComputed = true; - } + mObj = UnboxArray(obj, &mLength, &mData); } private: @@ -154,25 +127,20 @@ private: template -struct TypedArray : public TypedArray_base { -private: - typedef TypedArray_base Base; - -public: - TypedArray(JSObject* obj) - : Base(obj) +struct TypedArray : public TypedArray_base { + TypedArray(JSObject* obj) : + TypedArray_base(obj) {} - TypedArray() - : Base() + TypedArray() : + TypedArray_base() {} explicit TypedArray(TypedArray&& aOther) - : Base(Move(aOther)) + : TypedArray_base(Move(aOther)) { } @@ -210,37 +178,37 @@ private: TypedArray(const TypedArray&) MOZ_DELETE; }; -typedef TypedArray +typedef TypedArray Int8Array; -typedef TypedArray +typedef TypedArray Uint8Array; -typedef TypedArray +typedef TypedArray Uint8ClampedArray; -typedef TypedArray +typedef TypedArray Int16Array; -typedef TypedArray +typedef TypedArray Uint16Array; -typedef TypedArray +typedef TypedArray Int32Array; -typedef TypedArray +typedef TypedArray Uint32Array; -typedef TypedArray +typedef TypedArray Float32Array; -typedef TypedArray +typedef TypedArray Float64Array; -typedef TypedArray_base +typedef TypedArray_base ArrayBufferView; -typedef TypedArray +typedef TypedArray ArrayBuffer; // A class for converting an nsTArray to a TypedArray diff --git a/dom/crypto/CryptoBuffer.cpp b/dom/crypto/CryptoBuffer.cpp index 24d8dac16d7..f63570fe532 100644 --- a/dom/crypto/CryptoBuffer.cpp +++ b/dom/crypto/CryptoBuffer.cpp @@ -26,14 +26,12 @@ CryptoBuffer::Assign(const SECItem* aItem) uint8_t* CryptoBuffer::Assign(const ArrayBuffer& aData) { - aData.ComputeLengthAndData(); return Assign(aData.Data(), aData.Length()); } uint8_t* CryptoBuffer::Assign(const ArrayBufferView& aData) { - aData.ComputeLengthAndData(); return Assign(aData.Data(), aData.Length()); } diff --git a/dom/crypto/CryptoBuffer.h b/dom/crypto/CryptoBuffer.h index 5a763cc6ac1..754a5063690 100644 --- a/dom/crypto/CryptoBuffer.h +++ b/dom/crypto/CryptoBuffer.h @@ -28,12 +28,10 @@ public: uint8_t* Assign(const OwningArrayBufferViewOrArrayBuffer& aData); template - uint8_t* Assign(const TypedArray_base& aArray) + JSObject* UnboxArray(JSObject*, uint32_t*, T**)> + uint8_t* Assign(const TypedArray_base& aData) { - aArray.ComputeLengthAndData(); - return Assign(aArray.Data(), aArray.Length()); + return Assign(aData.Data(), aData.Length()); } diff --git a/dom/encoding/TextDecoder.h b/dom/encoding/TextDecoder.h index af40306ac8e..dc122503cfb 100644 --- a/dom/encoding/TextDecoder.h +++ b/dom/encoding/TextDecoder.h @@ -107,7 +107,6 @@ public: const TextDecodeOptions& aOptions, nsAString& aOutDecodedString, ErrorResult& aRv) { - aView.ComputeLengthAndData(); Decode(reinterpret_cast(aView.Data()), aView.Length(), aOptions.mStream, aOutDecodedString, aRv); } diff --git a/dom/filehandle/LockedFile.cpp b/dom/filehandle/LockedFile.cpp index 4f91e60fd46..eeb2fc42257 100644 --- a/dom/filehandle/LockedFile.cpp +++ b/dom/filehandle/LockedFile.cpp @@ -756,7 +756,6 @@ already_AddRefed LockedFile::GetInputStream(const ArrayBuffer& aValue, uint64_t* aInputLength, ErrorResult& aRv) { - aValue.ComputeLengthAndData(); const char* data = reinterpret_cast(aValue.Data()); uint32_t length = aValue.Length(); diff --git a/dom/filesystem/Directory.cpp b/dom/filesystem/Directory.cpp index e2d5316d26d..23a2df0fc12 100644 --- a/dom/filesystem/Directory.cpp +++ b/dom/filesystem/Directory.cpp @@ -112,11 +112,9 @@ Directory::CreateFile(const nsAString& aPath, const CreateFileOptions& aOptions) str.Length()); } else if (data.IsArrayBuffer()) { ArrayBuffer& buffer = data.GetAsArrayBuffer(); - buffer.ComputeLengthAndData(); arrayData.AppendElements(buffer.Data(), buffer.Length()); } else if (data.IsArrayBufferView()){ ArrayBufferView& view = data.GetAsArrayBufferView(); - view.ComputeLengthAndData(); arrayData.AppendElements(view.Data(), view.Length()); } else { blobData = data.GetAsBlob(); diff --git a/js/src/builtin/SIMD.cpp b/js/src/builtin/SIMD.cpp index 63a403e1698..e71645ace04 100644 --- a/js/src/builtin/SIMD.cpp +++ b/js/src/builtin/SIMD.cpp @@ -58,7 +58,6 @@ static bool GetX4Lane(JSContext *cx, unsigned argc, Value *vp) { return false; } - MOZ_ASSERT(!typedObj.owner().isNeutered()); Elem *data = reinterpret_cast(typedObj.typedMem()); Type32x4::setReturn(args, data[lane]); return true; @@ -101,7 +100,6 @@ static bool SignMask(JSContext *cx, unsigned argc, Value *vp) { return false; } - MOZ_ASSERT(!typedObj.owner().isNeutered()); Elem *data = reinterpret_cast(typedObj.typedMem()); int32_t mx = data[0] < 0.0 ? 1 : 0; int32_t my = data[1] < 0.0 ? 1 : 0; @@ -276,7 +274,6 @@ X4TypeDescr::call(JSContext *cx, unsigned argc, Value *vp) if (!result) return false; - MOZ_ASSERT(!result->owner().isNeutered()); switch (descr->type()) { #define STORE_LANES(_constant, _type, _name) \ case _constant: \ @@ -409,9 +406,7 @@ template static Elem TypedObjectMemory(HandleValue v) { - TypedObject &obj = v.toObject().as(); - MOZ_ASSERT(!obj.owner().isNeutered()); - return reinterpret_cast(obj.typedMem()); + return reinterpret_cast(v.toObject().as().typedMem()); } template @@ -426,7 +421,6 @@ js::Create(JSContext *cx, typename V::Elem *data) if (!result) return nullptr; - MOZ_ASSERT(!result->owner().isNeutered()); Elem *resultMem = reinterpret_cast(result->typedMem()); memcpy(resultMem, data, sizeof(Elem) * V::lanes); return result; diff --git a/js/src/builtin/TypedObject.cpp b/js/src/builtin/TypedObject.cpp index 3816acb30ba..6e773aa2d7f 100644 --- a/js/src/builtin/TypedObject.cpp +++ b/js/src/builtin/TypedObject.cpp @@ -2480,7 +2480,7 @@ TypedObject::constructUnsized(JSContext *cx, unsigned int argc, Value *vp) Rooted buffer(cx); buffer = &args[0].toObject().as(); - if (callee->opaque()) { + if (callee->opaque() || buffer->isNeutered()) { JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS); return false; @@ -2533,12 +2533,6 @@ TypedObject::constructUnsized(JSContext *cx, unsigned int argc, Value *vp) length = maximumLength; } - if (buffer->isNeutered()) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, - nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS); - return false; - } - Rooted obj(cx); obj = TypedObject::createUnattached(cx, callee, length); if (!obj) diff --git a/js/src/builtin/TypedObject.js b/js/src/builtin/TypedObject.js index a9f18d31407..f4afbd0bf5d 100644 --- a/js/src/builtin/TypedObject.js +++ b/js/src/builtin/TypedObject.js @@ -58,9 +58,8 @@ function TypedObjectGet(descr, typedObj, offset) { assert(IsObject(descr) && ObjectIsTypeDescr(descr), "get() called with bad type descr"); - - if (!TypedObjectIsAttached(typedObj)) - ThrowError(JSMSG_TYPEDOBJECT_HANDLE_UNATTACHED); + assert(TypedObjectIsAttached(typedObj), + "get() called with unattached typedObj"); switch (DESCR_KIND(descr)) { case JS_TYPEREPR_SCALAR_KIND: @@ -187,8 +186,7 @@ function TypedObjectGetX4(descr, typedObj, offset) { // it to `descr` as needed. This is the most general entry point // and works for any type. function TypedObjectSet(descr, typedObj, offset, fromValue) { - if (!TypedObjectIsAttached(typedObj)) - ThrowError(JSMSG_TYPEDOBJECT_HANDLE_UNATTACHED); + assert(TypedObjectIsAttached(typedObj), "set() called with unattached typedObj"); // Fast path: `fromValue` is a typed object with same type // representation as the destination. In that case, we can just do a diff --git a/js/src/jit/AsmJSLink.cpp b/js/src/jit/AsmJSLink.cpp index 82b050eadb9..35560961bee 100644 --- a/js/src/jit/AsmJSLink.cpp +++ b/js/src/jit/AsmJSLink.cpp @@ -327,25 +327,24 @@ ValidateConstant(JSContext *cx, AsmJSModule::Global &global, HandleValue globalV static bool LinkModuleToHeap(JSContext *cx, AsmJSModule &module, Handle heap) { - uint32_t heapLength = heap->byteLength(); - if (!IsValidAsmJSHeapLength(heapLength)) { + if (!IsValidAsmJSHeapLength(heap->byteLength())) { ScopedJSFreePtr msg( JS_smprintf("ArrayBuffer byteLength 0x%x is not a valid heap length. The next " "valid length is 0x%x", - heapLength, - RoundUpToNextValidAsmJSHeapLength(heapLength))); + heap->byteLength(), + RoundUpToNextValidAsmJSHeapLength(heap->byteLength()))); return LinkFail(cx, msg.get()); } // This check is sufficient without considering the size of the loaded datum because heap // loads and stores start on an aligned boundary and the heap byteLength has larger alignment. JS_ASSERT((module.minHeapLength() - 1) <= INT32_MAX); - if (heapLength < module.minHeapLength()) { + if (heap->byteLength() < module.minHeapLength()) { ScopedJSFreePtr msg( JS_smprintf("ArrayBuffer byteLength of 0x%x is less than 0x%x (which is the" "largest constant heap access offset rounded up to the next valid " "heap size).", - heapLength, + heap->byteLength(), module.minHeapLength())); return LinkFail(cx, msg.get()); } @@ -461,6 +460,15 @@ CallAsmJS(JSContext *cx, unsigned argc, Value *vp) // the arguments. const AsmJSModule::ExportedFunction &func = FunctionToExportedFunction(callee, module); + // An asm.js module is specialized to its heap's base address and length + // which is normally immutable except for the neuter operation that occurs + // when an ArrayBuffer is transfered. Throw an internal error if we try to + // run with a neutered heap. + if (module.maybeHeapBufferObject() && module.maybeHeapBufferObject()->isNeutered()) { + js_ReportOverRecursed(cx); + return false; + } + // The calling convention for an external call into asm.js is to pass an // array of 8-byte values where each value contains either a coerced int32 // (in the low word) or double value, with the coercions specified by the @@ -492,15 +500,6 @@ CallAsmJS(JSContext *cx, unsigned argc, Value *vp) } } - // An asm.js module is specialized to its heap's base address and length - // which is normally immutable except for the neuter operation that occurs - // when an ArrayBuffer is transfered. Throw an internal error if we're - // about to run with a neutered heap. - if (module.maybeHeapBufferObject() && module.maybeHeapBufferObject()->isNeutered()) { - js_ReportOverRecursed(cx); - return false; - } - { // Push an AsmJSActivation to describe the asm.js frames we're about to // push when running this module. Additionally, push a JitActivation so diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index b8a293d76db..9fbf2be9a6d 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -35,7 +35,6 @@ using namespace js::jit; using mozilla::DebugOnly; using mozilla::Maybe; -using mozilla::SafeCast; class jit::BaselineFrameInspector { @@ -7081,13 +7080,9 @@ IonBuilder::getElemTryTypedStatic(bool *emitted, MDefinition *obj, MDefinition * return true; TypedArrayObject *tarr = &tarrObj->as(); - - types::TypeObjectKey *tarrType = types::TypeObjectKey::get(tarr); - if (tarrType->unknownProperties()) - return true; + ArrayBufferView::ViewType viewType = (ArrayBufferView::ViewType) tarr->type(); // LoadTypedArrayElementStatic currently treats uint32 arrays as int32. - ArrayBufferView::ViewType viewType = (ArrayBufferView::ViewType) tarr->type(); if (viewType == ArrayBufferView::TYPE_UINT32) return true; @@ -7096,7 +7091,6 @@ IonBuilder::getElemTryTypedStatic(bool *emitted, MDefinition *obj, MDefinition * return true; // Emit LoadTypedArrayElementStatic. - tarrType->watchStateChangeForTypedArrayData(constraints()); obj->setImplicitlyUsedUnchecked(); index->setImplicitlyUsedUnchecked(); @@ -7439,14 +7433,21 @@ IonBuilder::jsop_getelem_dense(MDefinition *obj, MDefinition *index) return pushTypeBarrier(load, types, barrier); } -void -IonBuilder::addTypedArrayLengthAndData(MDefinition *obj, - BoundsChecking checking, - MDefinition **index, - MInstruction **length, MInstruction **elements) +MInstruction * +IonBuilder::getTypedArrayLength(MDefinition *obj) { - MOZ_ASSERT((index != nullptr) == (elements != nullptr)); + if (obj->isConstant() && obj->toConstant()->value().isObject()) { + TypedArrayObject *tarr = &obj->toConstant()->value().toObject().as(); + int32_t length = (int32_t) tarr->length(); + obj->setImplicitlyUsedUnchecked(); + return MConstant::New(alloc(), Int32Value(length)); + } + return MTypedArrayLength::New(alloc(), obj); +} +MInstruction * +IonBuilder::getTypedArrayElements(MDefinition *obj) +{ if (obj->isConstant() && obj->toConstant()->value().isObject()) { TypedArrayObject *tarr = &obj->toConstant()->value().toObject().as(); void *data = tarr->viewData(); @@ -7462,36 +7463,14 @@ IonBuilder::addTypedArrayLengthAndData(MDefinition *obj, // (ArrayBufferObject::changeContents). types::TypeObjectKey *tarrType = types::TypeObjectKey::get(tarr); if (!tarrType->unknownProperties()) { - tarrType->watchStateChangeForTypedArrayData(constraints()); + tarrType->watchStateChangeForTypedArrayBuffer(constraints()); obj->setImplicitlyUsedUnchecked(); - - int32_t len = SafeCast(tarr->length()); - *length = MConstant::New(alloc(), Int32Value(len)); - current->add(*length); - - if (index) { - if (checking == DoBoundsCheck) - *index = addBoundsCheck(*index, *length); - - *elements = MConstantElements::New(alloc(), data); - current->add(*elements); - } - return; + return MConstantElements::New(alloc(), data); } } } - - *length = MTypedArrayLength::New(alloc(), obj); - current->add(*length); - - if (index) { - if (checking == DoBoundsCheck) - *index = addBoundsCheck(*index, *length); - - *elements = MTypedArrayElements::New(alloc(), obj); - current->add(*elements); - } + return MTypedArrayElements::New(alloc(), obj); } MDefinition * @@ -7583,10 +7562,16 @@ IonBuilder::jsop_getelem_typed(MDefinition *obj, MDefinition *index, // uint32 reads that may produce either doubles or integers. MIRType knownType = MIRTypeForTypedArrayRead(arrayType, allowDouble); - // Get length, bounds-check, then get elements, and add all instructions. - MInstruction *length; - MInstruction *elements; - addTypedArrayLengthAndData(obj, DoBoundsCheck, &index, &length, &elements); + // Get the length. + MInstruction *length = getTypedArrayLength(obj); + current->add(length); + + // Bounds check. + index = addBoundsCheck(index, length); + + // Get the elements vector. + MInstruction *elements = getTypedArrayElements(obj); + current->add(elements); // Load the element. MLoadTypedArrayElement *load = MLoadTypedArrayElement::New(alloc(), elements, index, arrayType); @@ -7785,18 +7770,13 @@ IonBuilder::setElemTryTypedStatic(bool *emitted, MDefinition *object, return true; #endif - types::TypeObjectKey *tarrType = types::TypeObjectKey::get(tarr); - if (tarrType->unknownProperties()) - return true; - ArrayBufferView::ViewType viewType = (ArrayBufferView::ViewType) tarr->type(); + MDefinition *ptr = convertShiftToMaskForStaticTypedArray(index, viewType); if (!ptr) return true; // Emit StoreTypedArrayElementStatic. - tarrType->watchStateChangeForTypedArrayData(constraints()); - object->setImplicitlyUsedUnchecked(); index->setImplicitlyUsedUnchecked(); @@ -8064,13 +8044,18 @@ IonBuilder::jsop_setelem_typed(ScalarTypeDescr::Type arrayType, current->add(idInt32); id = idInt32; - // Get length, bounds-check, then get elements, and add all instructions. - MInstruction *length; - MInstruction *elements; - BoundsChecking checking = (!expectOOB && safety == SetElem_Normal) - ? DoBoundsCheck - : SkipBoundsCheck; - addTypedArrayLengthAndData(obj, checking, &id, &length, &elements); + // Get the length. + MInstruction *length = getTypedArrayLength(obj); + current->add(length); + + if (!expectOOB && safety == SetElem_Normal) { + // Bounds check. + id = addBoundsCheck(id, length); + } + + // Get the elements vector. + MInstruction *elements = getTypedArrayElements(obj); + current->add(elements); // Clamp value to [0, 255] for Uint8ClampedArray. MDefinition *toWrite = value; @@ -8171,7 +8156,8 @@ IonBuilder::jsop_length_fastPath() if (objTypes && objTypes->getTypedArrayType() != ScalarTypeDescr::TYPE_MAX) { current->pop(); - MInstruction *length = addTypedArrayLength(obj); + MInstruction *length = getTypedArrayLength(obj); + current->add(length); current->push(length); return true; } diff --git a/js/src/jit/IonBuilder.h b/js/src/jit/IonBuilder.h index 3ccc8f8f483..885d03be310 100644 --- a/js/src/jit/IonBuilder.h +++ b/js/src/jit/IonBuilder.h @@ -542,27 +542,9 @@ class IonBuilder : public MIRGenerator TypeDescrSet elemTypeReprs, int32_t elemSize); - enum BoundsChecking { DoBoundsCheck, SkipBoundsCheck }; - - // Add instructions to compute a typed array's length and data. Also - // optionally convert |*index| into a bounds-checked definition, if - // requested. - // - // If you only need the array's length, use addTypedArrayLength below. - void addTypedArrayLengthAndData(MDefinition *obj, - BoundsChecking checking, - MDefinition **index, - MInstruction **length, MInstruction **elements); - - // Add an instruction to compute a typed array's length to the current - // block. If you also need the typed array's data, use the above method - // instead. - MInstruction *addTypedArrayLength(MDefinition *obj) { - MInstruction *length; - addTypedArrayLengthAndData(obj, SkipBoundsCheck, nullptr, &length, nullptr); - return length; - } - + // Typed array helpers. + MInstruction *getTypedArrayLength(MDefinition *obj); + MInstruction *getTypedArrayElements(MDefinition *obj); MDefinition *getCallee(); diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index fda8f0e4d95..013e38c6178 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -248,22 +248,18 @@ class AliasSet { FrameArgument = 1 << 6, // An argument kept on the stack frame AsmJSGlobalVar = 1 << 7, // An asm.js global var AsmJSHeap = 1 << 8, // An asm.js heap load - TypedArrayLength = 1 << 9,// A typed array's length - Last = TypedArrayLength, + Last = AsmJSHeap, Any = Last | (Last - 1), - NumCategories = 10, + NumCategories = 9, // Indicates load or store. Store_ = 1 << 31 }; - - static_assert((1 << NumCategories) - 1 == Any, - "NumCategories must include all flags present in Any"); - explicit AliasSet(uint32_t flags) : flags_(flags) { + JS_STATIC_ASSERT((1 << NumCategories) - 1 == Any); } public: @@ -5894,7 +5890,9 @@ class MTypedArrayLength return congruentIfOperandsEqual(ins); } AliasSet getAliasSet() const { - return AliasSet::Load(AliasSet::TypedArrayLength); + // The typed array |length| property is immutable, so there is no + // implicit dependency. + return AliasSet::None(); } void computeRange(TempAllocator &alloc); diff --git a/js/src/js.msg b/js/src/js.msg index 41c8aff1c27..cde21d77952 100644 --- a/js/src/js.msg +++ b/js/src/js.msg @@ -241,11 +241,11 @@ MSG_DEF(JSMSG_UNUSED187, 187, 0, JSEXN_NONE, "") MSG_DEF(JSMSG_INCOMPATIBLE_METHOD, 188, 3, JSEXN_TYPEERR, "{0} {1} called on incompatible {2}") MSG_DEF(JSMSG_UNUSED189, 189, 0, JSEXN_NONE, "") MSG_DEF(JSMSG_UNUSED190, 190, 0, JSEXN_NONE, "") -MSG_DEF(JSMSG_BAD_INDEX, 191, 0, JSEXN_RANGEERR, "invalid or out-of-range index") +MSG_DEF(JSMSG_UNUSED191, 191, 0, JSEXN_NONE, "") MSG_DEF(JSMSG_UNUSED192, 192, 0, JSEXN_NONE, "") MSG_DEF(JSMSG_BAD_FOR_EACH_LOOP, 193, 0, JSEXN_SYNTAXERR, "invalid for each loop") MSG_DEF(JSMSG_OBJECT_WATCH_DEPRECATED,194, 0, JSEXN_TYPEERR, "Object.prototype.watch and unwatch are very slow, non-standard, and deprecated; use a getter/setter instead") -MSG_DEF(JSMSG_TYPE_ERR_BAD_ARGS, 195, 0, JSEXN_TYPEERR, "invalid arguments") +MSG_DEF(JSMSG_UNUSED195, 195, 0, JSEXN_NONE, "") MSG_DEF(JSMSG_UNUSED196, 196, 0, JSEXN_NONE, "") MSG_DEF(JSMSG_INTERNAL_INTL_ERROR, 197, 0, JSEXN_ERR, "internal error while computing Intl data") MSG_DEF(JSMSG_DEFAULT_LOCALE_ERROR, 198, 0, JSEXN_ERR, "internal error getting the default locale") diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index e4613c9d60e..9efa179655f 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -7,7 +7,6 @@ #ifndef jsfriendapi_h #define jsfriendapi_h -#include "mozilla/Casting.h" #include "mozilla/MemoryReporting.h" #include "mozilla/TypedEnum.h" @@ -1296,93 +1295,6 @@ JS_IsFloat32Array(JSObject *obj); extern JS_FRIEND_API(bool) JS_IsFloat64Array(JSObject *obj); -/* - * Test for specific typed array types (ArrayBufferView subtypes) and return - * the unwrapped object if so, else nullptr. Never throws. - */ - -namespace js { - -extern JS_FRIEND_API(JSObject *) -UnwrapInt8Array(JSObject *obj); -extern JS_FRIEND_API(JSObject *) -UnwrapUint8Array(JSObject *obj); -extern JS_FRIEND_API(JSObject *) -UnwrapUint8ClampedArray(JSObject *obj); -extern JS_FRIEND_API(JSObject *) -UnwrapInt16Array(JSObject *obj); -extern JS_FRIEND_API(JSObject *) -UnwrapUint16Array(JSObject *obj); -extern JS_FRIEND_API(JSObject *) -UnwrapInt32Array(JSObject *obj); -extern JS_FRIEND_API(JSObject *) -UnwrapUint32Array(JSObject *obj); -extern JS_FRIEND_API(JSObject *) -UnwrapFloat32Array(JSObject *obj); -extern JS_FRIEND_API(JSObject *) -UnwrapFloat64Array(JSObject *obj); - -extern JS_FRIEND_API(JSObject *) -UnwrapArrayBuffer(JSObject *obj); - -extern JS_FRIEND_API(JSObject *) -UnwrapArrayBufferView(JSObject *obj); - -namespace detail { - -extern JS_FRIEND_DATA(const Class* const) Int8ArrayClassPtr; -extern JS_FRIEND_DATA(const Class* const) Uint8ArrayClassPtr; -extern JS_FRIEND_DATA(const Class* const) Uint8ClampedArrayClassPtr; -extern JS_FRIEND_DATA(const Class* const) Int16ArrayClassPtr; -extern JS_FRIEND_DATA(const Class* const) Uint16ArrayClassPtr; -extern JS_FRIEND_DATA(const Class* const) Int32ArrayClassPtr; -extern JS_FRIEND_DATA(const Class* const) Uint32ArrayClassPtr; -extern JS_FRIEND_DATA(const Class* const) Float32ArrayClassPtr; -extern JS_FRIEND_DATA(const Class* const) Float64ArrayClassPtr; - -const size_t TypedArrayLengthSlot = 4; - -} // namespace detail - -/* - * Test for specific typed array types (ArrayBufferView subtypes) and return - * the unwrapped object if so, else nullptr. Never throws. - */ - -#define JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Type, type) \ -inline void \ -Get ## Type ## ArrayLengthAndData(JSObject *obj, uint32_t *length, type **data) \ -{ \ - JS_ASSERT(GetObjectClass(obj) == detail::Type ## ArrayClassPtr); \ - const JS::Value &slot = GetReservedSlot(obj, detail::TypedArrayLengthSlot); \ - *length = mozilla::SafeCast(slot.toInt32()); \ - *data = static_cast(GetObjectPrivate(obj)); \ -} - -JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int8, int8_t) -JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint8, uint8_t) -JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint8Clamped, uint8_t) -JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int16, int16_t) -JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint16, uint16_t) -JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int32, int32_t) -JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint32, uint32_t) -JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Float32, float) -JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Float64, double) - -#undef JS_DEFINE_DATA_AND_LENGTH_ACCESSOR - -// This one isn't inlined because it's rather tricky (by dint of having to deal -// with a dozen-plus classes and varying slot layouts. -extern JS_FRIEND_API(void) -GetArrayBufferViewLengthAndData(JSObject *obj, uint32_t *length, uint8_t **data); - -// This one isn't inlined because there are a bunch of different ArrayBuffer -// classes that would have to be individually handled here. -extern JS_FRIEND_API(void) -GetArrayBufferLengthAndData(JSObject *obj, uint32_t *length, uint8_t **data); - -} // namespace js - /* * Unwrap Typed arrays all at once. Return nullptr without throwing if the * object cannot be viewed as the correct typed array, or the typed array diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp index 8027dcb9920..4a8144f002b 100644 --- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -1596,26 +1596,23 @@ class ConstraintDataFreezeObjectForNewScriptTemplate } }; -// Constraint which triggers recompilation when a typed array's data becomes -// invalid. -class ConstraintDataFreezeObjectForTypedArrayData +// Constraint which triggers recompilation when the underlying data pointer for +// a typed array changes. +class ConstraintDataFreezeObjectForTypedArrayBuffer { void *viewData; - uint32_t length; public: - explicit ConstraintDataFreezeObjectForTypedArrayData(TypedArrayObject &tarray) - : viewData(tarray.viewData()), - length(tarray.length()) + explicit ConstraintDataFreezeObjectForTypedArrayBuffer(void *viewData) + : viewData(viewData) {} - const char *kind() { return "freezeObjectForTypedArrayData"; } + const char *kind() { return "freezeObjectForTypedArrayBuffer"; } bool invalidateOnNewType(Type type) { return false; } bool invalidateOnNewPropertyState(TypeSet *property) { return false; } bool invalidateOnNewObjectState(TypeObject *object) { - TypedArrayObject &tarray = object->singleton()->as(); - return tarray.viewData() != viewData || tarray.length() != length; + return object->singleton()->as().viewData() != viewData; } bool constraintHolds(JSContext *cx, @@ -1655,15 +1652,15 @@ TypeObjectKey::watchStateChangeForNewScriptTemplate(CompilerConstraintList *cons } void -TypeObjectKey::watchStateChangeForTypedArrayData(CompilerConstraintList *constraints) +TypeObjectKey::watchStateChangeForTypedArrayBuffer(CompilerConstraintList *constraints) { - TypedArrayObject &tarray = asSingleObject()->as(); + void *viewData = asSingleObject()->as().viewData(); HeapTypeSetKey objectProperty = property(JSID_EMPTY); LifoAlloc *alloc = constraints->alloc(); - typedef CompilerConstraintInstance T; + typedef CompilerConstraintInstance T; constraints->add(alloc->new_(alloc, objectProperty, - ConstraintDataFreezeObjectForTypedArrayData(tarray))); + ConstraintDataFreezeObjectForTypedArrayBuffer(viewData))); } static void diff --git a/js/src/jsinfer.h b/js/src/jsinfer.h index 78cb8f47e59..cee67c7a5a4 100644 --- a/js/src/jsinfer.h +++ b/js/src/jsinfer.h @@ -1423,7 +1423,7 @@ struct TypeObjectKey bool hasFlags(CompilerConstraintList *constraints, TypeObjectFlags flags); void watchStateChangeForInlinedCall(CompilerConstraintList *constraints); void watchStateChangeForNewScriptTemplate(CompilerConstraintList *constraints); - void watchStateChangeForTypedArrayData(CompilerConstraintList *constraints); + void watchStateChangeForTypedArrayBuffer(CompilerConstraintList *constraints); HeapTypeSetKey property(jsid id); void ensureTrackedProperty(JSContext *cx, jsid id); diff --git a/js/src/vm/ArrayBufferObject.cpp b/js/src/vm/ArrayBufferObject.cpp index 062fa44b49a..3982a56b142 100644 --- a/js/src/vm/ArrayBufferObject.cpp +++ b/js/src/vm/ArrayBufferObject.cpp @@ -675,21 +675,18 @@ JSObject * ArrayBufferObject::createSlice(JSContext *cx, Handle arrayBuffer, uint32_t begin, uint32_t end) { - uint32_t bufLength = arrayBuffer->byteLength(); - if (begin > bufLength || end > bufLength || begin > end) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPE_ERR_BAD_ARGS); - return nullptr; - } - + JS_ASSERT(begin <= arrayBuffer->byteLength()); + JS_ASSERT(end <= arrayBuffer->byteLength()); + JS_ASSERT(begin <= end); uint32_t length = end - begin; if (!arrayBuffer->hasData()) return create(cx, 0); - ArrayBufferObject *slice = create(cx, length); + JSObject *slice = create(cx, length); if (!slice) return nullptr; - memcpy(slice->dataPointer(), arrayBuffer->dataPointer() + begin, length); + memcpy(slice->as().dataPointer(), arrayBuffer->dataPointer() + begin, length); return slice; } @@ -988,14 +985,6 @@ JS_IsArrayBufferViewObject(JSObject *obj) return obj ? obj->is() : false; } -JS_FRIEND_API(JSObject *) -js::UnwrapArrayBufferView(JSObject *obj) -{ - if (JSObject *unwrapped = CheckedUnwrap(obj)) - return unwrapped->is() ? unwrapped : nullptr; - return nullptr; -} - JS_FRIEND_API(uint32_t) JS_GetArrayBufferByteLength(JSObject *obj) { @@ -1100,14 +1089,6 @@ JS_IsArrayBufferObject(JSObject *obj) return obj ? obj->is() : false; } -JS_FRIEND_API(JSObject *) -js::UnwrapArrayBuffer(JSObject *obj) -{ - if (JSObject *unwrapped = CheckedUnwrap(obj)) - return unwrapped->is() ? unwrapped : nullptr; - return nullptr; -} - JS_PUBLIC_API(void *) JS_StealArrayBufferContents(JSContext *cx, HandleObject objArg) { @@ -1204,20 +1185,6 @@ JS_GetObjectAsArrayBufferView(JSObject *obj, uint32_t *length, uint8_t **data) return obj; } -JS_FRIEND_API(void) -js::GetArrayBufferViewLengthAndData(JSObject *obj, uint32_t *length, uint8_t **data) -{ - MOZ_ASSERT(obj->is()); - - *length = obj->is() - ? obj->as().byteLength() - : obj->as().byteLength(); - - *data = static_cast(obj->is() - ? obj->as().dataPointer() - : obj->as().viewData()); -} - JS_FRIEND_API(JSObject *) JS_GetObjectAsArrayBuffer(JSObject *obj, uint32_t *length, uint8_t **data) { @@ -1231,11 +1198,3 @@ JS_GetObjectAsArrayBuffer(JSObject *obj, uint32_t *length, uint8_t **data) return obj; } - -JS_FRIEND_API(void) -js::GetArrayBufferLengthAndData(JSObject *obj, uint32_t *length, uint8_t **data) -{ - MOZ_ASSERT(IsArrayBuffer(obj)); - *length = AsArrayBuffer(obj).byteLength(); - *data = AsArrayBuffer(obj).dataPointer(); -} diff --git a/js/src/vm/TypedArrayObject.cpp b/js/src/vm/TypedArrayObject.cpp index 83a6a10b326..c76c94785f9 100644 --- a/js/src/vm/TypedArrayObject.cpp +++ b/js/src/vm/TypedArrayObject.cpp @@ -556,25 +556,20 @@ class TypedArrayObjectTemplate : public TypedArrayObject uint32_t srcEnd; uint32_t dest; - uint32_t originalLength = tarray->length(); - if (!ToClampedIndex(cx, args[0], originalLength, &srcBegin) || - !ToClampedIndex(cx, args[1], originalLength, &srcEnd) || - !ToClampedIndex(cx, args[2], originalLength, &dest)) + uint32_t length = tarray->length(); + if (!ToClampedIndex(cx, args[0], length, &srcBegin) || + !ToClampedIndex(cx, args[1], length, &srcEnd) || + !ToClampedIndex(cx, args[2], length, &dest) || + srcBegin > srcEnd) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS); return false; } - if (srcBegin > srcEnd) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_INDEX); - return false; - } - - uint32_t lengthDuringMove = tarray->length(); // beware ToClampedIndex uint32_t nelts = srcEnd - srcBegin; - MOZ_ASSERT(dest <= INT32_MAX, "size limited to 2**31"); - MOZ_ASSERT(nelts <= INT32_MAX, "size limited to 2**31"); - if (dest + nelts > lengthDuringMove || srcEnd > lengthDuringMove) { + JS_ASSERT(dest + nelts >= dest); + if (dest + nelts > length) { JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS); return false; } @@ -654,7 +649,8 @@ class TypedArrayObjectTemplate : public TypedArrayObject if (!GetLengthProperty(cx, arg0, &len)) return false; - if (uint32_t(offset) > tarray->length() || len > tarray->length() - offset) { + // avoid overflow; we know that offset <= length + if (len > tarray->length() - offset) { JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_ARRAY_LENGTH); return false; } @@ -831,9 +827,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject static const NativeType getIndex(JSObject *obj, uint32_t index) { - TypedArrayObject &tarray = obj->as(); - MOZ_ASSERT(index < tarray.length()); - return static_cast(tarray.viewData())[index]; + return *(static_cast(obj->as().viewData()) + index); } static void @@ -850,10 +844,8 @@ class TypedArrayObjectTemplate : public TypedArrayObject { Rooted tarray(cx, &tarrayArg->as()); - if (begin > tarray->length() || end > tarray->length() || begin > end) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_INDEX); - return nullptr; - } + JS_ASSERT(begin <= tarray->length()); + JS_ASSERT(end <= tarray->length()); if (!ensureHasBuffer(cx, tarray)) return nullptr; @@ -861,6 +853,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject Rooted bufobj(cx, tarray->buffer()); JS_ASSERT(bufobj); + JS_ASSERT(begin <= end); uint32_t length = end - begin; JS_ASSERT(begin < UINT32_MAX / sizeof(NativeType)); @@ -1084,54 +1077,53 @@ class TypedArrayObjectTemplate : public TypedArrayObject return false; js_memcpy(srcbuf, tarray->viewData(), byteLength); - uint32_t len = tarray->length(); switch (tarray->type()) { case ScalarTypeDescr::TYPE_INT8: { int8_t *src = (int8_t*) srcbuf; - for (unsigned i = 0; i < len; ++i) + for (unsigned i = 0; i < tarray->length(); ++i) *dest++ = NativeType(*src++); break; } case ScalarTypeDescr::TYPE_UINT8: case ScalarTypeDescr::TYPE_UINT8_CLAMPED: { uint8_t *src = (uint8_t*) srcbuf; - for (unsigned i = 0; i < len; ++i) + for (unsigned i = 0; i < tarray->length(); ++i) *dest++ = NativeType(*src++); break; } case ScalarTypeDescr::TYPE_INT16: { int16_t *src = (int16_t*) srcbuf; - for (unsigned i = 0; i < len; ++i) + for (unsigned i = 0; i < tarray->length(); ++i) *dest++ = NativeType(*src++); break; } case ScalarTypeDescr::TYPE_UINT16: { uint16_t *src = (uint16_t*) srcbuf; - for (unsigned i = 0; i < len; ++i) + for (unsigned i = 0; i < tarray->length(); ++i) *dest++ = NativeType(*src++); break; } case ScalarTypeDescr::TYPE_INT32: { int32_t *src = (int32_t*) srcbuf; - for (unsigned i = 0; i < len; ++i) + for (unsigned i = 0; i < tarray->length(); ++i) *dest++ = NativeType(*src++); break; } case ScalarTypeDescr::TYPE_UINT32: { uint32_t *src = (uint32_t*) srcbuf; - for (unsigned i = 0; i < len; ++i) + for (unsigned i = 0; i < tarray->length(); ++i) *dest++ = NativeType(*src++); break; } case ScalarTypeDescr::TYPE_FLOAT32: { float *src = (float*) srcbuf; - for (unsigned i = 0; i < len; ++i) + for (unsigned i = 0; i < tarray->length(); ++i) *dest++ = NativeType(*src++); break; } case ScalarTypeDescr::TYPE_FLOAT64: { double *src = (double*) srcbuf; - for (unsigned i = 0; i < len; ++i) + for (unsigned i = 0; i < tarray->length(); ++i) *dest++ = NativeType(*src++); break; } @@ -1321,13 +1313,6 @@ DataViewObject::create(JSContext *cx, uint32_t byteOffset, uint32_t byteLength, RootedObject proto(cx, protoArg); RootedObject obj(cx); - // This is overflow-safe: 2 * INT32_MAX is still a valid uint32_t. - if (byteOffset + byteLength > arrayBuffer->byteLength()) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_ARG_INDEX_OUT_OF_RANGE, "1"); - return nullptr; - - } - NewObjectKind newKind = DataViewNewObjectKind(cx, byteLength, proto); obj = NewBuiltinClassInstance(cx, &class_, newKind); if (!obj) @@ -1454,17 +1439,21 @@ DataViewObject::class_constructor(JSContext *cx, unsigned argc, Value *vp) return construct(cx, bufobj, args, NullPtr()); } -template -/* static */ uint8_t * -DataViewObject::getDataPointer(JSContext *cx, Handle obj, uint32_t offset) +/* static */ bool +DataViewObject::getDataPointer(JSContext *cx, Handle obj, + CallArgs args, size_t typeSize, uint8_t **data) { - const size_t TypeSize = sizeof(NativeType); - if (offset > UINT32_MAX - TypeSize || offset + TypeSize > obj->byteLength()) { + uint32_t offset; + JS_ASSERT(args.length() > 0); + if (!ToUint32(cx, args[0], &offset)) + return false; + if (offset > UINT32_MAX - typeSize || offset + typeSize > obj->byteLength()) { JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_ARG_INDEX_OUT_OF_RANGE, "1"); - return nullptr; + return false; } - return static_cast(obj->dataPointer()) + offset; + *data = static_cast(obj->dataPointer()) + offset; + return true; } static inline bool @@ -1552,16 +1541,11 @@ DataViewObject::read(JSContext *cx, Handle obj, return false; } - uint32_t offset; - if (!ToUint32(cx, args[0], &offset)) + uint8_t *data; + if (!getDataPointer(cx, obj, args, sizeof(NativeType), &data)) return false; bool fromLittleEndian = args.length() >= 2 && ToBoolean(args[1]); - - uint8_t *data = DataViewObject::getDataPointer(cx, obj, offset); - if (!data) - return false; - DataViewIO::fromBuffer(val, data, needToSwapBytes(fromLittleEndian)); return true; } @@ -1609,8 +1593,8 @@ DataViewObject::write(JSContext *cx, Handle obj, return false; } - uint32_t offset; - if (!ToUint32(cx, args[0], &offset)) + uint8_t *data; + if (!getDataPointer(cx, obj, args, sizeof(NativeType), &data)) return false; NativeType value; @@ -1618,11 +1602,6 @@ DataViewObject::write(JSContext *cx, Handle obj, return false; bool toLittleEndian = args.length() >= 3 && ToBoolean(args[2]); - - uint8_t *data = DataViewObject::getDataPointer(cx, obj, offset); - if (!data) - return false; - DataViewIO::toBuffer(data, &value, needToSwapBytes(toLittleEndian)); return true; } @@ -1960,6 +1939,8 @@ DataViewObject::fun_setFloat64(JSContext *cx, unsigned argc, Value *vp) Value TypedArrayObject::getElement(uint32_t index) { + JS_ASSERT(index < length()); + switch (type()) { case ScalarTypeDescr::TYPE_INT8: return TypedArrayObjectTemplate::getIndexValue(this, index); @@ -2081,19 +2062,7 @@ const JSFunctionSpec _typedArray##Object::jsfuncs[] = { return false; \ const Class *clasp = obj->getClass(); \ return clasp == &TypedArrayObject::classes[TypedArrayObjectTemplate::ArrayTypeID()]; \ - } \ - JS_FRIEND_API(JSObject *) js::Unwrap ## Name ## Array(JSObject *obj) \ - { \ - obj = CheckedUnwrap(obj); \ - if (!obj) \ - return nullptr; \ - const Class *clasp = obj->getClass(); \ - if (clasp == &TypedArrayObject::classes[TypedArrayObjectTemplate::ArrayTypeID()]) \ - return obj; \ - return nullptr; \ - } \ - JS_FRIEND_DATA(const js::Class* const) js::detail::Name ## ArrayClassPtr = \ - &js::TypedArrayObject::classes[TypedArrayObjectTemplate::ArrayTypeID()]; + } IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Int8, int8_t) IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Uint8, uint8_t) diff --git a/js/src/vm/TypedArrayObject.h b/js/src/vm/TypedArrayObject.h index a7809124488..bc07337566c 100644 --- a/js/src/vm/TypedArrayObject.h +++ b/js/src/vm/TypedArrayObject.h @@ -36,9 +36,6 @@ class TypedArrayObject : public ArrayBufferViewObject static const size_t RESERVED_SLOTS = JS_TYPEDOBJ_SLOTS; static const size_t DATA_SLOT = JS_TYPEDOBJ_SLOT_DATA; - static_assert(js::detail::TypedArrayLengthSlot == LENGTH_SLOT, - "bad inlined constant in jsfriendapi.h"); - public: static const Class classes[ScalarTypeDescr::TYPE_MAX]; static const Class protoClasses[ScalarTypeDescr::TYPE_MAX]; @@ -99,7 +96,6 @@ class TypedArrayObject : public ArrayBufferViewObject return getFixedSlot(TYPE_SLOT).toInt32(); } void *viewData() const { - // Keep synced with js::GetArrayLengthAndData in jsfriendapi.h! return static_cast(getPrivate(DATA_SLOT)); } @@ -227,10 +223,6 @@ class DataViewObject : public ArrayBufferViewObject return v.isObject() && v.toObject().hasClass(&class_); } - template - static uint8_t * - getDataPointer(JSContext *cx, Handle obj, uint32_t offset); - template static bool getterImpl(JSContext *cx, CallArgs args); @@ -337,6 +329,8 @@ class DataViewObject : public ArrayBufferViewObject static bool initClass(JSContext *cx); static void neuter(JSObject *view); + static bool getDataPointer(JSContext *cx, Handle obj, + CallArgs args, size_t typeSize, uint8_t **data); template static bool read(JSContext *cx, Handle obj, CallArgs &args, NativeType *val, const char *method); diff --git a/netwerk/base/src/ArrayBufferInputStream.cpp b/netwerk/base/src/ArrayBufferInputStream.cpp index d35973bb63f..617bdf98bb4 100644 --- a/netwerk/base/src/ArrayBufferInputStream.cpp +++ b/netwerk/base/src/ArrayBufferInputStream.cpp @@ -81,17 +81,6 @@ ArrayBufferInputStream::ReadSegments(nsWriteSegmentFun writer, void *closure, } uint32_t remaining = mBufferLength - mPos; - if (!mArrayBuffer.empty()) { - JSObject* buf = &mArrayBuffer.ref().get().toObject(); - uint32_t byteLength = JS_GetArrayBufferByteLength(buf); - if (byteLength == 0 && remaining != 0) { - mClosed = true; - return NS_BASE_STREAM_CLOSED; - } - } else { - MOZ_ASSERT(remaining == 0, "stream inited incorrectly"); - } - if (!remaining) { *result = 0; return NS_OK; diff --git a/xpcom/io/nsBinaryStream.cpp b/xpcom/io/nsBinaryStream.cpp index fc6d7fe354c..9d3199eb734 100644 --- a/xpcom/io/nsBinaryStream.cpp +++ b/xpcom/io/nsBinaryStream.cpp @@ -18,27 +18,18 @@ * @See nsIBinaryInputStream * @See nsIBinaryOutputStream */ -#include #include - #include "nsBinaryStream.h" - -#include "mozilla/Endian.h" -#include "mozilla/PodOperations.h" -#include "mozilla/Scoped.h" - #include "nsCRT.h" #include "nsString.h" #include "nsISerializable.h" #include "nsIClassInfo.h" #include "nsComponentManagerUtils.h" #include "nsIURI.h" // for NS_IURI_IID +#include "mozilla/Endian.h" #include "jsfriendapi.h" -using mozilla::PodCopy; -using mozilla::ScopedDeleteArray; - NS_IMPL_ISUPPORTS(nsBinaryOutputStream, nsIObjectOutputStream, nsIBinaryOutputStream, @@ -831,50 +822,19 @@ nsBinaryInputStream::ReadArrayBuffer(uint32_t aLength, return NS_ERROR_FAILURE; } JS::RootedObject buffer(aCx, &aBuffer.toObject()); - if (!JS_IsArrayBufferObject(buffer)) { + if (!JS_IsArrayBufferObject(buffer) || + JS_GetArrayBufferByteLength(buffer) < aLength) { return NS_ERROR_FAILURE; } - - uint32_t bufferLength = JS_GetArrayBufferByteLength(buffer); - if (bufferLength < aLength) { - return NS_ERROR_FAILURE; - } - - char* data = reinterpret_cast(JS_GetStableArrayBufferData(aCx, buffer)); + uint8_t* data = JS_GetStableArrayBufferData(aCx, buffer); if (!data) { return NS_ERROR_FAILURE; } - uint32_t bufSize = std::min(aLength, 4096); - ScopedDeleteArray buf(new char[bufSize]); - - uint32_t remaining = aLength; - *rLength = 0; - do { - // Read data into temporary buffer. - uint32_t bytesRead; - uint32_t amount = std::min(remaining, bufSize); - nsresult rv = Read(buf, amount, &bytesRead); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - MOZ_ASSERT(bytesRead <= amount); - - if (bytesRead == 0) { - break; - } - - // Copy data into actual buffer. - if (bufferLength != JS_GetArrayBufferByteLength(buffer)) { - return NS_ERROR_FAILURE; - } - - *rLength += bytesRead; - PodCopy(data, buf.get(), bytesRead); - - remaining -= bytesRead; - data += bytesRead; - } while (remaining > 0); + nsresult rv = Read(reinterpret_cast(data), aLength, rLength); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } return NS_OK; }