Commit e210b196 authored by Ross McIlroy's avatar Ross McIlroy Committed by Commit Bot

[csa][cleanup] TNodify Atomic Compare Exchange.

Splits the 64bit operation to a seperate function since there are different
return types depending upon whether the architecture is 64-bit or 32-bit.

BUG=v8:6949,v8:11074

Change-Id: I47c84a0104f71ec8865f12cbfa201f2f76cf08bc
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2529911
Commit-Queue: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarSantiago Aboy Solanes <solanes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71128}
parent 8d611a87
......@@ -10,8 +10,6 @@
namespace v8 {
namespace internal {
using compiler::Node;
class SharedArrayBufferBuiltinsAssembler : public CodeStubAssembler {
public:
explicit SharedArrayBufferBuiltinsAssembler(
......@@ -47,8 +45,8 @@ class SharedArrayBufferBuiltinsAssembler : public CodeStubAssembler {
// Create a BigInt from the result of a 64-bit atomic operation, using
// projections on 32-bit platforms.
TNode<BigInt> BigIntFromSigned64(SloppyTNode<AtomicInt64> signed64);
TNode<BigInt> BigIntFromUnsigned64(SloppyTNode<AtomicUint64> unsigned64);
TNode<BigInt> BigIntFromSigned64(TNode<AtomicInt64> signed64);
TNode<BigInt> BigIntFromUnsigned64(TNode<AtomicUint64> unsigned64);
};
// https://tc39.es/ecma262/#sec-validateintegertypedarray
......@@ -146,7 +144,7 @@ void SharedArrayBufferBuiltinsAssembler::DebugCheckAtomicIndex(
}
TNode<BigInt> SharedArrayBufferBuiltinsAssembler::BigIntFromSigned64(
SloppyTNode<AtomicInt64> signed64) {
TNode<AtomicInt64> signed64) {
#if defined(V8_HOST_ARCH_32_BIT)
TNode<IntPtrT> low = Projection<0>(signed64);
TNode<IntPtrT> high = Projection<1>(signed64);
......@@ -157,7 +155,7 @@ TNode<BigInt> SharedArrayBufferBuiltinsAssembler::BigIntFromSigned64(
}
TNode<BigInt> SharedArrayBufferBuiltinsAssembler::BigIntFromUnsigned64(
SloppyTNode<AtomicUint64> unsigned64) {
TNode<AtomicUint64> unsigned64) {
#if defined(V8_HOST_ARCH_32_BIT)
TNode<UintPtrT> low = Projection<0>(unsigned64);
TNode<UintPtrT> high = Projection<1>(unsigned64);
......@@ -559,34 +557,34 @@ TF_BUILTIN(AtomicsCompareExchange, SharedArrayBufferBuiltinsAssembler) {
arraysize(case_labels));
BIND(&i8);
Return(SmiFromInt32(AtomicCompareExchange(MachineType::Int8(), backing_store,
index_word, old_value_word32,
new_value_word32)));
Return(SmiFromInt32(Signed(
AtomicCompareExchange(MachineType::Int8(), backing_store, index_word,
old_value_word32, new_value_word32))));
BIND(&u8);
Return(SmiFromInt32(AtomicCompareExchange(MachineType::Uint8(), backing_store,
index_word, old_value_word32,
new_value_word32)));
Return(SmiFromInt32(Signed(
AtomicCompareExchange(MachineType::Uint8(), backing_store, index_word,
old_value_word32, new_value_word32))));
BIND(&i16);
Return(SmiFromInt32(AtomicCompareExchange(
Return(SmiFromInt32(Signed(AtomicCompareExchange(
MachineType::Int16(), backing_store, WordShl(index_word, 1),
old_value_word32, new_value_word32)));
old_value_word32, new_value_word32))));
BIND(&u16);
Return(SmiFromInt32(AtomicCompareExchange(
Return(SmiFromInt32(Signed(AtomicCompareExchange(
MachineType::Uint16(), backing_store, WordShl(index_word, 1),
old_value_word32, new_value_word32)));
old_value_word32, new_value_word32))));
BIND(&i32);
Return(ChangeInt32ToTagged(AtomicCompareExchange(
Return(ChangeInt32ToTagged(Signed(AtomicCompareExchange(
MachineType::Int32(), backing_store, WordShl(index_word, 2),
old_value_word32, new_value_word32)));
old_value_word32, new_value_word32))));
BIND(&u32);
Return(ChangeUint32ToTagged(AtomicCompareExchange(
Return(ChangeUint32ToTagged(Unsigned(AtomicCompareExchange(
MachineType::Uint32(), backing_store, WordShl(index_word, 2),
old_value_word32, new_value_word32)));
old_value_word32, new_value_word32))));
BIND(&big);
// 4. If typedArray.[[ContentType]] is BigInt, then
......@@ -616,14 +614,14 @@ TF_BUILTIN(AtomicsCompareExchange, SharedArrayBufferBuiltinsAssembler) {
// This uses Uint64() intentionally: AtomicCompareExchange is not implemented
// for Int64(), which is fine because the machine instruction only cares
// about words.
Return(BigIntFromSigned64(AtomicCompareExchange(
MachineType::Uint64(), backing_store, WordShl(index_word, 3),
var_old_low.value(), var_new_low.value(), old_high, new_high)));
Return(BigIntFromSigned64(AtomicCompareExchange64<AtomicInt64>(
backing_store, WordShl(index_word, 3), var_old_low.value(),
var_new_low.value(), old_high, new_high)));
BIND(&u64);
Return(BigIntFromUnsigned64(AtomicCompareExchange(
MachineType::Uint64(), backing_store, WordShl(index_word, 3),
var_old_low.value(), var_new_low.value(), old_high, new_high)));
Return(BigIntFromUnsigned64(AtomicCompareExchange64<AtomicUint64>(
backing_store, WordShl(index_word, 3), var_old_low.value(),
var_new_low.value(), old_high, new_high)));
// This shouldn't happen, we've already validated the type.
BIND(&other);
......
......@@ -843,15 +843,37 @@ ATOMIC_FUNCTION(Xor)
ATOMIC_FUNCTION(Exchange)
#undef ATOMIC_FUNCTION
Node* CodeAssembler::AtomicCompareExchange(MachineType type, Node* base,
Node* offset, Node* old_value,
Node* new_value,
Node* old_value_high,
Node* new_value_high) {
return raw_assembler()->AtomicCompareExchange(
type, base, offset, old_value, old_value_high, new_value, new_value_high);
TNode<Word32T> CodeAssembler::AtomicCompareExchange(MachineType type,
TNode<RawPtrT> base,
TNode<WordT> offset,
TNode<Word32T> old_value,
TNode<Word32T> new_value) {
return UncheckedCast<Word32T>(raw_assembler()->AtomicCompareExchange(
type, base, offset, old_value, new_value));
}
template <class Type>
TNode<Type> CodeAssembler::AtomicCompareExchange64(
TNode<RawPtrT> base, TNode<WordT> offset, TNode<UintPtrT> old_value,
TNode<UintPtrT> new_value, TNode<UintPtrT> old_value_high,
TNode<UintPtrT> new_value_high) {
// This uses Uint64() intentionally: AtomicCompareExchange is not implemented
// for Int64(), which is fine because the machine instruction only cares
// about words.
return UncheckedCast<Type>(raw_assembler()->AtomicCompareExchange64(
base, offset, old_value, old_value_high, new_value, new_value_high));
}
template TNode<AtomicInt64> CodeAssembler::AtomicCompareExchange64<AtomicInt64>(
TNode<RawPtrT> base, TNode<WordT> offset, TNode<UintPtrT> old_value,
TNode<UintPtrT> new_value, TNode<UintPtrT> old_value_high,
TNode<UintPtrT> new_value_high);
template TNode<AtomicUint64>
CodeAssembler::AtomicCompareExchange64<AtomicUint64>(
TNode<RawPtrT> base, TNode<WordT> offset, TNode<UintPtrT> old_value,
TNode<UintPtrT> new_value, TNode<UintPtrT> old_value_high,
TNode<UintPtrT> new_value_high);
Node* CodeAssembler::StoreRoot(RootIndex root_index, Node* value) {
DCHECK(!RootsTable::IsImmortalImmovable(root_index));
TNode<ExternalReference> isolate_root =
......
......@@ -844,10 +844,18 @@ class V8_EXPORT_PRIVATE CodeAssembler {
TNode<UintPtrT> value_high);
// Compare and Exchange value at raw memory location
Node* AtomicCompareExchange(MachineType type, Node* base, Node* offset,
Node* old_value, Node* new_value,
Node* old_value_high = nullptr,
Node* new_value_high = nullptr);
TNode<Word32T> AtomicCompareExchange(MachineType type, TNode<RawPtrT> base,
TNode<WordT> offset,
TNode<Word32T> old_value,
TNode<Word32T> new_value);
template <class Type>
TNode<Type> AtomicCompareExchange64(TNode<RawPtrT> base, TNode<WordT> offset,
TNode<UintPtrT> old_value,
TNode<UintPtrT> new_value,
TNode<UintPtrT> old_value_high,
TNode<UintPtrT> new_value_high);
// Store a value to the root array.
Node* StoreRoot(RootIndex root_index, Node* value);
......
......@@ -286,26 +286,30 @@ class V8_EXPORT_PRIVATE RawMachineAssembler {
#undef VALUE_HALVES
Node* AtomicCompareExchange(MachineType type, Node* base, Node* index,
Node* old_value, Node* old_value_high,
Node* new_value, Node* new_value_high) {
if (type.representation() == MachineRepresentation::kWord64) {
if (machine()->Is64()) {
DCHECK_NULL(old_value_high);
DCHECK_NULL(new_value_high);
return AddNode(machine()->Word64AtomicCompareExchange(type), base,
index, old_value, new_value);
} else {
return AddNode(machine()->Word32AtomicPairCompareExchange(), base,
index, old_value, old_value_high, new_value,
new_value_high);
}
}
DCHECK_NULL(old_value_high);
DCHECK_NULL(new_value_high);
Node* old_value, Node* new_value) {
DCHECK_NE(type.representation(), MachineRepresentation::kWord64);
return AddNode(machine()->Word32AtomicCompareExchange(type), base, index,
old_value, new_value);
}
Node* AtomicCompareExchange64(Node* base, Node* index, Node* old_value,
Node* old_value_high, Node* new_value,
Node* new_value_high) {
if (machine()->Is64()) {
DCHECK_NULL(old_value_high);
DCHECK_NULL(new_value_high);
// This uses Uint64() intentionally: AtomicCompareExchange is not
// implemented for Int64(), which is fine because the machine instruction
// only cares about words.
return AddNode(
machine()->Word64AtomicCompareExchange(MachineType::Uint64()), base,
index, old_value, new_value);
} else {
return AddNode(machine()->Word32AtomicPairCompareExchange(), base, index,
old_value, old_value_high, new_value, new_value_high);
}
}
// Arithmetic Operations.
Node* WordAnd(Node* a, Node* b) {
return AddNode(machine()->WordAnd(), a, b);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment