diff --git a/common.gypi b/common.gypi index ae8fd5fe38..278ce94eb5 100644 --- a/common.gypi +++ b/common.gypi @@ -38,7 +38,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.7', + 'v8_embedder_string': '-node.8', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/builtins/builtins-typed-array.cc b/deps/v8/src/builtins/builtins-typed-array.cc index ec788e51ff..5804f154bf 100644 --- a/deps/v8/src/builtins/builtins-typed-array.cc +++ b/deps/v8/src/builtins/builtins-typed-array.cc @@ -883,14 +883,14 @@ BUILTIN(Uint8ArrayFromHex) { base::Vector input_vector = input_content.ToOneByteVector(); result = ArrayBufferFromHex( - input_vector, /*is_shared*/ false, - static_cast(buffer->backing_store()), output_length); + input_vector, static_cast(buffer->backing_store()), + output_length); } else { base::Vector input_vector = input_content.ToUC16Vector(); result = ArrayBufferFromHex( - input_vector, /*is_shared*/ false, - static_cast(buffer->backing_store()), output_length); + input_vector, static_cast(buffer->backing_store()), + output_length); } } @@ -959,6 +959,11 @@ BUILTIN(Uint8ArrayPrototypeSetFromHex) { size_t output_length = (input_length / 2); output_length = std::min(output_length, array_length); + // TODO(rezvan): Add path for typed arrays backed by SharedArrayBuffer + if (uint8array->buffer()->is_shared()) { + UNIMPLEMENTED(); + } + // 7. Let result be FromHex(string, byteLength). // 8. Let bytes be result.[[Bytes]]. // 9. Let written be the length of bytes. @@ -974,15 +979,15 @@ BUILTIN(Uint8ArrayPrototypeSetFromHex) { if (input_content.IsOneByte()) { base::Vector input_vector = input_content.ToOneByteVector(); - result = ArrayBufferFromHex( - input_vector, uint8array->buffer()->is_shared(), - static_cast(uint8array->DataPtr()), output_length); + result = ArrayBufferFromHex(input_vector, + static_cast(uint8array->DataPtr()), + output_length); } else { base::Vector input_vector = input_content.ToUC16Vector(); - result = ArrayBufferFromHex( - input_vector, uint8array->buffer()->is_shared(), - static_cast(uint8array->DataPtr()), output_length); + result = ArrayBufferFromHex(input_vector, + static_cast(uint8array->DataPtr()), + output_length); } } @@ -1052,8 +1057,7 @@ BUILTIN(Uint8ArrayPrototypeToHex) { // b. Set hex to StringPad(hex, 2, "0", start). // c. Set out to the string-concatenation of out and hex. // 6. Return out. - return Uint8ArrayToHex(bytes, length, uint8array->buffer()->is_shared(), - output); + return Uint8ArrayToHex(bytes, length, output); } } // namespace internal diff --git a/deps/v8/src/objects/simd.cc b/deps/v8/src/objects/simd.cc index 3202e51e4f..690326b95b 100644 --- a/deps/v8/src/objects/simd.cc +++ b/deps/v8/src/objects/simd.cc @@ -458,38 +458,16 @@ char NibbleToHex(uint8_t nibble) { return c + (mask & correction); } -void PerformNibbleToHexAndWriteIntoStringOutPut( - uint8_t byte, int index, DirectHandle string_output) { - uint8_t high = byte >> 4; - uint8_t low = byte & 0x0F; - - string_output->SeqOneByteStringSet(index++, NibbleToHex(high)); - string_output->SeqOneByteStringSet(index, NibbleToHex(low)); -} - void Uint8ArrayToHexSlow(const char* bytes, size_t length, DirectHandle string_output) { int index = 0; for (size_t i = 0; i < length; i++) { uint8_t byte = bytes[i]; - PerformNibbleToHexAndWriteIntoStringOutPut(byte, index, string_output); - index += 2; - } -} + uint8_t high = byte >> 4; + uint8_t low = byte & 0x0F; -void AtomicUint8ArrayToHexSlow(const char* bytes, size_t length, - DirectHandle string_output) { - int index = 0; - // std::atomic_ref must not have a const T, see - // https://cplusplus.github.io/LWG/issue3508 - // we instead provide a mutable input, which is ok since we are only reading - // from it. - char* mutable_bytes = const_cast(bytes); - for (size_t i = 0; i < length; i++) { - uint8_t byte = - std::atomic_ref(mutable_bytes[i]).load(std::memory_order_relaxed); - PerformNibbleToHexAndWriteIntoStringOutPut(byte, index, string_output); - index += 2; + string_output->SeqOneByteStringSet(index++, NibbleToHex(high)); + string_output->SeqOneByteStringSet(index++, NibbleToHex(low)); } } @@ -618,14 +596,11 @@ void Uint8ArrayToHexFastWithNeon(const char* bytes, uint8_t* output, #endif } // namespace -Tagged Uint8ArrayToHex(const char* bytes, size_t length, bool is_shared, +Tagged Uint8ArrayToHex(const char* bytes, size_t length, DirectHandle string_output) { - // TODO(rezvan): Add relaxed version for simd methods to handle shared array - // buffers. - #ifdef __SSE3__ - if (!is_shared && (get_vectorization_kind() == SimdKinds::kAVX2 || - get_vectorization_kind() == SimdKinds::kSSE)) { + if (get_vectorization_kind() == SimdKinds::kAVX2 || + get_vectorization_kind() == SimdKinds::kSSE) { { DisallowGarbageCollection no_gc; Uint8ArrayToHexFastWithSSE(bytes, string_output->GetChars(no_gc), length); @@ -635,7 +610,7 @@ Tagged Uint8ArrayToHex(const char* bytes, size_t length, bool is_shared, #endif #ifdef NEON64 - if (!is_shared && get_vectorization_kind() == SimdKinds::kNeon) { + if (get_vectorization_kind() == SimdKinds::kNeon) { { DisallowGarbageCollection no_gc; Uint8ArrayToHexFastWithNeon(bytes, string_output->GetChars(no_gc), @@ -645,11 +620,7 @@ Tagged Uint8ArrayToHex(const char* bytes, size_t length, bool is_shared, } #endif - if (is_shared) { - AtomicUint8ArrayToHexSlow(bytes, length, string_output); - } else { - Uint8ArrayToHexSlow(bytes, length, string_output); - } + Uint8ArrayToHexSlow(bytes, length, string_output); return *string_output; } @@ -1055,23 +1026,20 @@ bool Uint8ArrayFromHexWithNeon(const base::Vector& input_vector, } // namespace template -bool ArrayBufferFromHex(const base::Vector& input_vector, bool is_shared, - uint8_t* buffer, size_t output_length) { +bool ArrayBufferFromHex(const base::Vector& input_vector, uint8_t* buffer, + size_t output_length) { size_t input_length = input_vector.size(); DCHECK_LE(output_length, input_length / 2); - // TODO(rezvan): Add relaxed version for simd methods to handle shared array - // buffers. - #ifdef __SSE3__ - if (!is_shared && (get_vectorization_kind() == SimdKinds::kAVX2 || - get_vectorization_kind() == SimdKinds::kSSE)) { + if (get_vectorization_kind() == SimdKinds::kAVX2 || + get_vectorization_kind() == SimdKinds::kSSE) { return Uint8ArrayFromHexWithSSE(input_vector, buffer, output_length); } #endif #ifdef NEON64 - if (!is_shared && get_vectorization_kind() == SimdKinds::kNeon) { + if (get_vectorization_kind() == SimdKinds::kNeon) { return Uint8ArrayFromHexWithNeon(input_vector, buffer, output_length); } #endif @@ -1081,12 +1049,7 @@ bool ArrayBufferFromHex(const base::Vector& input_vector, bool is_shared, for (uint32_t i = 0; i < input_length; i += 2) { result = HandleRemainingHexValues(input_vector, i); if (result.has_value()) { - if (is_shared) { - std::atomic_ref(buffer[index++]) - .store(result.value(), std::memory_order_relaxed); - } else { - buffer[index++] = result.value(); - } + buffer[index++] = result.value(); } else { return false; } @@ -1095,11 +1058,11 @@ bool ArrayBufferFromHex(const base::Vector& input_vector, bool is_shared, } template bool ArrayBufferFromHex( - const base::Vector& input_vector, bool is_shared, - uint8_t* buffer, size_t output_length); + const base::Vector& input_vector, uint8_t* buffer, + size_t output_length); template bool ArrayBufferFromHex( - const base::Vector& input_vector, bool is_shared, - uint8_t* buffer, size_t output_length); + const base::Vector& input_vector, uint8_t* buffer, + size_t output_length); #ifdef NEON64 #undef NEON64 diff --git a/deps/v8/src/objects/simd.h b/deps/v8/src/objects/simd.h index 256718568d..f7aab77b23 100644 --- a/deps/v8/src/objects/simd.h +++ b/deps/v8/src/objects/simd.h @@ -20,11 +20,11 @@ uintptr_t ArrayIndexOfIncludesSmiOrObject(Address array_start, uintptr_t ArrayIndexOfIncludesDouble(Address array_start, uintptr_t array_len, uintptr_t from_index, Address search_element); -Tagged Uint8ArrayToHex(const char* bytes, size_t length, bool is_shared, +Tagged Uint8ArrayToHex(const char* bytes, size_t length, DirectHandle string_output); template -bool ArrayBufferFromHex(const base::Vector& input_vector, bool is_shared, - uint8_t* buffer, size_t output_length); +bool ArrayBufferFromHex(const base::Vector& input_vector, uint8_t* buffer, + size_t output_length); } // namespace internal } // namespace v8 diff --git a/deps/v8/test/mjsunit/harmony/uint8-array-set-from-hex-on-shared-array-buffer.js b/deps/v8/test/mjsunit/harmony/uint8-array-set-from-hex-on-shared-array-buffer.js deleted file mode 100644 index 570e7be269..0000000000 --- a/deps/v8/test/mjsunit/harmony/uint8-array-set-from-hex-on-shared-array-buffer.js +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2025 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Flags: --js-base-64 --allow-natives-syntax - -const workerScript = ` - onmessage = function(event) { - const sab = event.data.buffer; - const uint8Array = new Uint8Array(sab); - - const dataToWrite = [102, 111, 111, 98, 97, 114, 255, 255]; - - for (let i = 0; i < dataToWrite.length; ++i) { - uint8Array[i] = dataToWrite[i]; - } - - postMessage("started"); - - while (true) { - for (let i = 0; i < dataToWrite.length; ++i) { - uint8Array[i] = dataToWrite[i]; - } - } - }; -`; - -function testConcurrentSharedArrayBufferUint8ArraySetFromHex() { - const sab = new SharedArrayBuffer(8); - const uint8ArrayMain = new Uint8Array(sab); - - // Create a worker - const worker = new Worker(workerScript, {type: 'string'}); - - // Send the SharedArrayBuffer - worker.postMessage({buffer: sab}); - assertEquals('started', worker.getMessage()); - - // Give the worker a little time to write - for (let i = 0; i < 10000; ++i) { - } - - // Call setFromHex on the main thread's view of the SAB - for (let i = 0; i < 100; i++) { - const result = uint8ArrayMain.setFromHex('666f6f626172'); - - const actual = Array.from(uint8ArrayMain); - - assertEquals( - actual, [102, 111, 111, 98, 97, 114, 255, 255], - 'setFromHex result mismatch with concurrent writes'); - } - - // Terminate the worker (now it should exit its loop) - worker.terminate(); -} - -// Run the test function -testConcurrentSharedArrayBufferUint8ArraySetFromHex(); diff --git a/deps/v8/test/mjsunit/harmony/uint8-array-to-hex-on-shared-array-buffer.js b/deps/v8/test/mjsunit/harmony/uint8-array-to-hex-on-shared-array-buffer.js deleted file mode 100644 index f2a22b0ea3..0000000000 --- a/deps/v8/test/mjsunit/harmony/uint8-array-to-hex-on-shared-array-buffer.js +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2025 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Flags: --js-base-64 --allow-natives-syntax - -const workerScript = ` - onmessage = function(event) { - const sab = event.data.buffer; - const uint8Array = new Uint8Array(sab); - - const dataToWrite = [102, 111, 111, 98, 97, 114]; - - for (let i = 0; i < dataToWrite.length; ++i) { - uint8Array[i] = dataToWrite[i]; - } - - postMessage("started"); - - while (true) { - for (let i = 0; i < dataToWrite.length; ++i) { - uint8Array[i] = dataToWrite[i]; - } - } - }; -`; - -function testConcurrentSharedArrayBufferUint8ArrayToHex() { - const sab = new SharedArrayBuffer(6); - const uint8ArrayMain = new Uint8Array(sab); - - // Create a worker - const worker = new Worker(workerScript, {type: 'string'}); - - // Send the SharedArrayBuffer - worker.postMessage({buffer: sab}); - assertEquals('started', worker.getMessage()); - - // Give the worker a little time to write - for (let i = 0; i < 10000; ++i) { - } - - // Call toHex on the main thread's view of the SAB - for (let i = 0; i < 100; i++) { - const hexString = uint8ArrayMain.toHex(); - assertEquals( - '666f6f626172', hexString, - 'toHex result mismatch with concurrent writes'); - } - - // Terminate the worker (now it should exit its loop) - worker.terminate(); -} - -// Run the test function -testConcurrentSharedArrayBufferUint8ArrayToHex();