[sab] Make TypedArray#set atomic for SABs

Bug: chromium:1232620
Change-Id: Ie19fe8839966a1abb3d0a01fee1fb4b105fb6bf1
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3070702
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#76085}
This commit is contained in:
Leszek Swirski 2021-08-04 11:05:45 +02:00 committed by V8 LUCI CQ
parent fb86158a3b
commit c37c4e8adf
7 changed files with 47 additions and 1 deletions

View File

@ -270,6 +270,17 @@ void TypedArrayBuiltinsAssembler::CallCMemmove(TNode<RawPtrT> dest_ptr,
std::make_pair(MachineType::UintPtr(), byte_length)); std::make_pair(MachineType::UintPtr(), byte_length));
} }
void TypedArrayBuiltinsAssembler::CallCRelaxedMemmove(
TNode<RawPtrT> dest_ptr, TNode<RawPtrT> src_ptr,
TNode<UintPtrT> byte_length) {
TNode<ExternalReference> memmove =
ExternalConstant(ExternalReference::relaxed_memmove_function());
CallCFunction(memmove, MachineType::AnyTagged(),
std::make_pair(MachineType::Pointer(), dest_ptr),
std::make_pair(MachineType::Pointer(), src_ptr),
std::make_pair(MachineType::UintPtr(), byte_length));
}
void TypedArrayBuiltinsAssembler::CallCMemcpy(TNode<RawPtrT> dest_ptr, void TypedArrayBuiltinsAssembler::CallCMemcpy(TNode<RawPtrT> dest_ptr,
TNode<RawPtrT> src_ptr, TNode<RawPtrT> src_ptr,
TNode<UintPtrT> byte_length) { TNode<UintPtrT> byte_length) {

View File

@ -52,6 +52,9 @@ class TypedArrayBuiltinsAssembler : public CodeStubAssembler {
void CallCMemmove(TNode<RawPtrT> dest_ptr, TNode<RawPtrT> src_ptr, void CallCMemmove(TNode<RawPtrT> dest_ptr, TNode<RawPtrT> src_ptr,
TNode<UintPtrT> byte_length); TNode<UintPtrT> byte_length);
void CallCRelaxedMemmove(TNode<RawPtrT> dest_ptr, TNode<RawPtrT> src_ptr,
TNode<UintPtrT> byte_length);
void CallCMemcpy(TNode<RawPtrT> dest_ptr, TNode<RawPtrT> src_ptr, void CallCMemcpy(TNode<RawPtrT> dest_ptr, TNode<RawPtrT> src_ptr,
TNode<UintPtrT> byte_length); TNode<UintPtrT> byte_length);

View File

@ -281,7 +281,12 @@ TypedArrayPrototypeSetTypedArray(implicit context: Context, receiver: JSAny)(
// value, true, Unordered). // value, true, Unordered).
// iii. Set srcByteIndex to srcByteIndex + 1. // iii. Set srcByteIndex to srcByteIndex + 1.
// iv. Set targetByteIndex to targetByteIndex + 1. // iv. Set targetByteIndex to targetByteIndex + 1.
CallCMemmove(dstPtr, typedArray.data_ptr, countBytes); if (IsSharedArrayBuffer(target.buffer)) {
// SABs need a relaxed memmove to preserve atomicity.
CallCRelaxedMemmove(dstPtr, typedArray.data_ptr, countBytes);
} else {
CallCMemmove(dstPtr, typedArray.data_ptr, countBytes);
}
} label IfSlow deferred { } label IfSlow deferred {
// 22. If target.[[ContentType]] is not equal to // 22. If target.[[ContentType]] is not equal to
// typedArray.[[ContentType]], throw a TypeError exception. // typedArray.[[ContentType]], throw a TypeError exception.

View File

@ -65,6 +65,8 @@ extern macro TypedArrayBuiltinsAssembler::CallCMemset(
RawPtr, intptr, uintptr): void; RawPtr, intptr, uintptr): void;
extern macro TypedArrayBuiltinsAssembler::CallCRelaxedMemcpy( extern macro TypedArrayBuiltinsAssembler::CallCRelaxedMemcpy(
RawPtr, RawPtr, uintptr): void; RawPtr, RawPtr, uintptr): void;
extern macro TypedArrayBuiltinsAssembler::CallCRelaxedMemmove(
RawPtr, RawPtr, uintptr): void;
extern macro GetTypedArrayBuffer(implicit context: Context)(JSTypedArray): extern macro GetTypedArrayBuffer(implicit context: Context)(JSTypedArray):
JSArrayBuffer; JSArrayBuffer;
extern macro TypedArrayBuiltinsAssembler::GetTypedArrayElementsInfo( extern macro TypedArrayBuiltinsAssembler::GetTypedArrayElementsInfo(

View File

@ -813,6 +813,13 @@ void relaxed_memcpy(volatile base::Atomic8* dest,
FUNCTION_REFERENCE(relaxed_memcpy_function, relaxed_memcpy) FUNCTION_REFERENCE(relaxed_memcpy_function, relaxed_memcpy)
void relaxed_memmove(volatile base::Atomic8* dest,
volatile const base::Atomic8* src, size_t n) {
base::Relaxed_Memmove(dest, src, n);
}
FUNCTION_REFERENCE(relaxed_memmove_function, relaxed_memmove)
ExternalReference ExternalReference::printf_function() { ExternalReference ExternalReference::printf_function() {
return ExternalReference(Redirect(FUNCTION_ADDR(std::printf))); return ExternalReference(Redirect(FUNCTION_ADDR(std::printf)));
} }

View File

@ -175,6 +175,7 @@ class StatsCounter;
V(libc_memmove_function, "libc_memmove") \ V(libc_memmove_function, "libc_memmove") \
V(libc_memset_function, "libc_memset") \ V(libc_memset_function, "libc_memset") \
V(relaxed_memcpy_function, "relaxed_memcpy") \ V(relaxed_memcpy_function, "relaxed_memcpy") \
V(relaxed_memmove_function, "relaxed_memmove") \
V(mod_two_doubles_operation, "mod_two_doubles") \ V(mod_two_doubles_operation, "mod_two_doubles") \
V(mutable_big_int_absolute_add_and_canonicalize_function, \ V(mutable_big_int_absolute_add_and_canonicalize_function, \
"MutableBigInt_AbsoluteAddAndCanonicalize") \ "MutableBigInt_AbsoluteAddAndCanonicalize") \

View File

@ -0,0 +1,17 @@
// Copyright 2021 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.
// Try to catch TSAN issues with access to SharedArrayBuffer.
function onmessage([buf]) {
const arr = new Int32Array(buf);
for (let val = 1; val < 100; ++val) arr.fill(val);
}
const arr = new Int32Array(new SharedArrayBuffer(4));
const worker = new Worker(`onmessage = ${onmessage}`, {type: 'string'});
worker.postMessage([arr.buffer]);
// Wait until the worker starts filling the array.
while (Atomics.load(arr) == 0) { }
// Try setting a value on the shared array buffer that races with the fill.
arr.set(arr);