[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:
parent
fb86158a3b
commit
c37c4e8adf
@ -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) {
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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(
|
||||||
|
@ -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)));
|
||||||
}
|
}
|
||||||
|
@ -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") \
|
||||||
|
17
test/mjsunit/regress/regress-1232620.js
Normal file
17
test/mjsunit/regress/regress-1232620.js
Normal 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);
|
Loading…
Reference in New Issue
Block a user