deps: V8: revert 6d6c1e680c7b

It depends on `std::atomic_ref`, which is not available in Xcode 16.1.

Refs: 6d6c1e680c
PR-URL: https://github.com/nodejs/node/pull/58064
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Richard Lau <rlau@redhat.com>
Reviewed-By: Darshan Sen <raisinten@gmail.com>
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
This commit is contained in:
Michaël Zasso 2025-04-29 07:58:11 +02:00 committed by Node.js GitHub Bot
parent 8c508b9399
commit 754d28e34f
6 changed files with 39 additions and 187 deletions

View File

@ -38,7 +38,7 @@
# Reset this number to 0 on major V8 upgrades. # Reset this number to 0 on major V8 upgrades.
# Increment by one for each non-official patch applied to deps/v8. # 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 ##### ##### V8 defaults for Node.js #####

View File

@ -883,14 +883,14 @@ BUILTIN(Uint8ArrayFromHex) {
base::Vector<const uint8_t> input_vector = base::Vector<const uint8_t> input_vector =
input_content.ToOneByteVector(); input_content.ToOneByteVector();
result = ArrayBufferFromHex( result = ArrayBufferFromHex(
input_vector, /*is_shared*/ false, input_vector, static_cast<uint8_t*>(buffer->backing_store()),
static_cast<uint8_t*>(buffer->backing_store()), output_length); output_length);
} else { } else {
base::Vector<const base::uc16> input_vector = base::Vector<const base::uc16> input_vector =
input_content.ToUC16Vector(); input_content.ToUC16Vector();
result = ArrayBufferFromHex( result = ArrayBufferFromHex(
input_vector, /*is_shared*/ false, input_vector, static_cast<uint8_t*>(buffer->backing_store()),
static_cast<uint8_t*>(buffer->backing_store()), output_length); output_length);
} }
} }
@ -959,6 +959,11 @@ BUILTIN(Uint8ArrayPrototypeSetFromHex) {
size_t output_length = (input_length / 2); size_t output_length = (input_length / 2);
output_length = std::min(output_length, array_length); 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). // 7. Let result be FromHex(string, byteLength).
// 8. Let bytes be result.[[Bytes]]. // 8. Let bytes be result.[[Bytes]].
// 9. Let written be the length of bytes. // 9. Let written be the length of bytes.
@ -974,15 +979,15 @@ BUILTIN(Uint8ArrayPrototypeSetFromHex) {
if (input_content.IsOneByte()) { if (input_content.IsOneByte()) {
base::Vector<const uint8_t> input_vector = base::Vector<const uint8_t> input_vector =
input_content.ToOneByteVector(); input_content.ToOneByteVector();
result = ArrayBufferFromHex( result = ArrayBufferFromHex(input_vector,
input_vector, uint8array->buffer()->is_shared(), static_cast<uint8_t*>(uint8array->DataPtr()),
static_cast<uint8_t*>(uint8array->DataPtr()), output_length); output_length);
} else { } else {
base::Vector<const base::uc16> input_vector = base::Vector<const base::uc16> input_vector =
input_content.ToUC16Vector(); input_content.ToUC16Vector();
result = ArrayBufferFromHex( result = ArrayBufferFromHex(input_vector,
input_vector, uint8array->buffer()->is_shared(), static_cast<uint8_t*>(uint8array->DataPtr()),
static_cast<uint8_t*>(uint8array->DataPtr()), output_length); output_length);
} }
} }
@ -1052,8 +1057,7 @@ BUILTIN(Uint8ArrayPrototypeToHex) {
// b. Set hex to StringPad(hex, 2, "0", start). // b. Set hex to StringPad(hex, 2, "0", start).
// c. Set out to the string-concatenation of out and hex. // c. Set out to the string-concatenation of out and hex.
// 6. Return out. // 6. Return out.
return Uint8ArrayToHex(bytes, length, uint8array->buffer()->is_shared(), return Uint8ArrayToHex(bytes, length, output);
output);
} }
} // namespace internal } // namespace internal

View File

@ -458,38 +458,16 @@ char NibbleToHex(uint8_t nibble) {
return c + (mask & correction); return c + (mask & correction);
} }
void PerformNibbleToHexAndWriteIntoStringOutPut(
uint8_t byte, int index, DirectHandle<SeqOneByteString> 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, void Uint8ArrayToHexSlow(const char* bytes, size_t length,
DirectHandle<SeqOneByteString> string_output) { DirectHandle<SeqOneByteString> string_output) {
int index = 0; int index = 0;
for (size_t i = 0; i < length; i++) { for (size_t i = 0; i < length; i++) {
uint8_t byte = bytes[i]; uint8_t byte = bytes[i];
PerformNibbleToHexAndWriteIntoStringOutPut(byte, index, string_output); uint8_t high = byte >> 4;
index += 2; uint8_t low = byte & 0x0F;
}
}
void AtomicUint8ArrayToHexSlow(const char* bytes, size_t length, string_output->SeqOneByteStringSet(index++, NibbleToHex(high));
DirectHandle<SeqOneByteString> string_output) { string_output->SeqOneByteStringSet(index++, NibbleToHex(low));
int index = 0;
// std::atomic_ref<T> 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<char*>(bytes);
for (size_t i = 0; i < length; i++) {
uint8_t byte =
std::atomic_ref<char>(mutable_bytes[i]).load(std::memory_order_relaxed);
PerformNibbleToHexAndWriteIntoStringOutPut(byte, index, string_output);
index += 2;
} }
} }
@ -618,14 +596,11 @@ void Uint8ArrayToHexFastWithNeon(const char* bytes, uint8_t* output,
#endif #endif
} // namespace } // namespace
Tagged<Object> Uint8ArrayToHex(const char* bytes, size_t length, bool is_shared, Tagged<Object> Uint8ArrayToHex(const char* bytes, size_t length,
DirectHandle<SeqOneByteString> string_output) { DirectHandle<SeqOneByteString> string_output) {
// TODO(rezvan): Add relaxed version for simd methods to handle shared array
// buffers.
#ifdef __SSE3__ #ifdef __SSE3__
if (!is_shared && (get_vectorization_kind() == SimdKinds::kAVX2 || if (get_vectorization_kind() == SimdKinds::kAVX2 ||
get_vectorization_kind() == SimdKinds::kSSE)) { get_vectorization_kind() == SimdKinds::kSSE) {
{ {
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
Uint8ArrayToHexFastWithSSE(bytes, string_output->GetChars(no_gc), length); Uint8ArrayToHexFastWithSSE(bytes, string_output->GetChars(no_gc), length);
@ -635,7 +610,7 @@ Tagged<Object> Uint8ArrayToHex(const char* bytes, size_t length, bool is_shared,
#endif #endif
#ifdef NEON64 #ifdef NEON64
if (!is_shared && get_vectorization_kind() == SimdKinds::kNeon) { if (get_vectorization_kind() == SimdKinds::kNeon) {
{ {
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
Uint8ArrayToHexFastWithNeon(bytes, string_output->GetChars(no_gc), Uint8ArrayToHexFastWithNeon(bytes, string_output->GetChars(no_gc),
@ -645,11 +620,7 @@ Tagged<Object> Uint8ArrayToHex(const char* bytes, size_t length, bool is_shared,
} }
#endif #endif
if (is_shared) { Uint8ArrayToHexSlow(bytes, length, string_output);
AtomicUint8ArrayToHexSlow(bytes, length, string_output);
} else {
Uint8ArrayToHexSlow(bytes, length, string_output);
}
return *string_output; return *string_output;
} }
@ -1055,23 +1026,20 @@ bool Uint8ArrayFromHexWithNeon(const base::Vector<T>& input_vector,
} // namespace } // namespace
template <typename T> template <typename T>
bool ArrayBufferFromHex(const base::Vector<T>& input_vector, bool is_shared, bool ArrayBufferFromHex(const base::Vector<T>& input_vector, uint8_t* buffer,
uint8_t* buffer, size_t output_length) { size_t output_length) {
size_t input_length = input_vector.size(); size_t input_length = input_vector.size();
DCHECK_LE(output_length, input_length / 2); DCHECK_LE(output_length, input_length / 2);
// TODO(rezvan): Add relaxed version for simd methods to handle shared array
// buffers.
#ifdef __SSE3__ #ifdef __SSE3__
if (!is_shared && (get_vectorization_kind() == SimdKinds::kAVX2 || if (get_vectorization_kind() == SimdKinds::kAVX2 ||
get_vectorization_kind() == SimdKinds::kSSE)) { get_vectorization_kind() == SimdKinds::kSSE) {
return Uint8ArrayFromHexWithSSE(input_vector, buffer, output_length); return Uint8ArrayFromHexWithSSE(input_vector, buffer, output_length);
} }
#endif #endif
#ifdef NEON64 #ifdef NEON64
if (!is_shared && get_vectorization_kind() == SimdKinds::kNeon) { if (get_vectorization_kind() == SimdKinds::kNeon) {
return Uint8ArrayFromHexWithNeon(input_vector, buffer, output_length); return Uint8ArrayFromHexWithNeon(input_vector, buffer, output_length);
} }
#endif #endif
@ -1081,12 +1049,7 @@ bool ArrayBufferFromHex(const base::Vector<T>& input_vector, bool is_shared,
for (uint32_t i = 0; i < input_length; i += 2) { for (uint32_t i = 0; i < input_length; i += 2) {
result = HandleRemainingHexValues(input_vector, i); result = HandleRemainingHexValues(input_vector, i);
if (result.has_value()) { if (result.has_value()) {
if (is_shared) { buffer[index++] = result.value();
std::atomic_ref<uint8_t>(buffer[index++])
.store(result.value(), std::memory_order_relaxed);
} else {
buffer[index++] = result.value();
}
} else { } else {
return false; return false;
} }
@ -1095,11 +1058,11 @@ bool ArrayBufferFromHex(const base::Vector<T>& input_vector, bool is_shared,
} }
template bool ArrayBufferFromHex( template bool ArrayBufferFromHex(
const base::Vector<const uint8_t>& input_vector, bool is_shared, const base::Vector<const uint8_t>& input_vector, uint8_t* buffer,
uint8_t* buffer, size_t output_length); size_t output_length);
template bool ArrayBufferFromHex( template bool ArrayBufferFromHex(
const base::Vector<const base::uc16>& input_vector, bool is_shared, const base::Vector<const base::uc16>& input_vector, uint8_t* buffer,
uint8_t* buffer, size_t output_length); size_t output_length);
#ifdef NEON64 #ifdef NEON64
#undef NEON64 #undef NEON64

View File

@ -20,11 +20,11 @@ uintptr_t ArrayIndexOfIncludesSmiOrObject(Address array_start,
uintptr_t ArrayIndexOfIncludesDouble(Address array_start, uintptr_t array_len, uintptr_t ArrayIndexOfIncludesDouble(Address array_start, uintptr_t array_len,
uintptr_t from_index, uintptr_t from_index,
Address search_element); Address search_element);
Tagged<Object> Uint8ArrayToHex(const char* bytes, size_t length, bool is_shared, Tagged<Object> Uint8ArrayToHex(const char* bytes, size_t length,
DirectHandle<SeqOneByteString> string_output); DirectHandle<SeqOneByteString> string_output);
template <typename T> template <typename T>
bool ArrayBufferFromHex(const base::Vector<T>& input_vector, bool is_shared, bool ArrayBufferFromHex(const base::Vector<T>& input_vector, uint8_t* buffer,
uint8_t* buffer, size_t output_length); size_t output_length);
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8

View File

@ -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();

View File

@ -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();