Commit 30ae0d76 authored by Ross McIlroy's avatar Ross McIlroy Committed by Commit Bot

[csa][cleanup] TNodify Atomic binary ops.

Splits the 64bit operations 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: I13cc576a26f60288281c42df3326ba902fd36dbb
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2529910
Commit-Queue: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarSantiago Aboy Solanes <solanes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71120}
parent b13cb747
......@@ -19,10 +19,13 @@ class SharedArrayBufferBuiltinsAssembler : public CodeStubAssembler {
: CodeStubAssembler(state) {}
protected:
using AssemblerFunction =
Node* (CodeAssembler::*)(MachineType type, TNode<RawPtrT> base,
TNode<UintPtrT> offset, Node* value,
base::Optional<TNode<UintPtrT>> value_high);
using AssemblerFunction = TNode<Word32T> (CodeAssembler::*)(
MachineType type, TNode<RawPtrT> base, TNode<UintPtrT> offset,
TNode<Word32T> value);
template <class Type>
using AssemblerFunction64 = TNode<Type> (CodeAssembler::*)(
TNode<RawPtrT> base, TNode<UintPtrT> offset, TNode<UintPtrT> value,
TNode<UintPtrT> value_high);
TNode<JSArrayBuffer> ValidateIntegerTypedArray(
TNode<Object> maybe_array, TNode<Context> context,
TNode<Int32T>* out_elements_kind, TNode<RawPtrT>* out_backing_store,
......@@ -35,11 +38,12 @@ class SharedArrayBufferBuiltinsAssembler : public CodeStubAssembler {
inline void DebugCheckAtomicIndex(TNode<JSTypedArray> array,
TNode<UintPtrT> index);
void AtomicBinopBuiltinCommon(TNode<Object> maybe_array, TNode<Object> index,
TNode<Object> value, TNode<Context> context,
AssemblerFunction function,
Runtime::FunctionId runtime_function,
const char* method_name);
void AtomicBinopBuiltinCommon(
TNode<Object> maybe_array, TNode<Object> index, TNode<Object> value,
TNode<Context> context, AssemblerFunction function,
AssemblerFunction64<AtomicInt64> function_int_64,
AssemblerFunction64<AtomicUint64> function_uint_64,
Runtime::FunctionId runtime_function, const char* method_name);
// Create a BigInt from the result of a 64-bit atomic operation, using
// projections on 32-bit platforms.
......@@ -418,32 +422,32 @@ TF_BUILTIN(AtomicsExchange, SharedArrayBufferBuiltinsAssembler) {
arraysize(case_labels));
BIND(&i8);
Return(SmiFromInt32(AtomicExchange(MachineType::Int8(), backing_store,
index_word, value_word32, base::nullopt)));
Return(SmiFromInt32(Signed(AtomicExchange(MachineType::Int8(), backing_store,
index_word, value_word32))));
BIND(&u8);
Return(SmiFromInt32(AtomicExchange(MachineType::Uint8(), backing_store,
index_word, value_word32, base::nullopt)));
Return(SmiFromInt32(Signed(AtomicExchange(MachineType::Uint8(), backing_store,
index_word, value_word32))));
BIND(&i16);
Return(SmiFromInt32(AtomicExchange(MachineType::Int16(), backing_store,
WordShl(index_word, UintPtrConstant(1)),
value_word32, base::nullopt)));
Return(SmiFromInt32(Signed(
AtomicExchange(MachineType::Int16(), backing_store,
WordShl(index_word, UintPtrConstant(1)), value_word32))));
BIND(&u16);
Return(SmiFromInt32(AtomicExchange(MachineType::Uint16(), backing_store,
WordShl(index_word, UintPtrConstant(1)),
value_word32, base::nullopt)));
Return(SmiFromInt32(Signed(
AtomicExchange(MachineType::Uint16(), backing_store,
WordShl(index_word, UintPtrConstant(1)), value_word32))));
BIND(&i32);
Return(ChangeInt32ToTagged(AtomicExchange(
MachineType::Int32(), backing_store,
WordShl(index_word, UintPtrConstant(2)), value_word32, base::nullopt)));
Return(ChangeInt32ToTagged(Signed(
AtomicExchange(MachineType::Int32(), backing_store,
WordShl(index_word, UintPtrConstant(2)), value_word32))));
BIND(&u32);
Return(ChangeUint32ToTagged(AtomicExchange(
MachineType::Uint32(), backing_store,
WordShl(index_word, UintPtrConstant(2)), value_word32, base::nullopt)));
Return(ChangeUint32ToTagged(Unsigned(
AtomicExchange(MachineType::Uint32(), backing_store,
WordShl(index_word, UintPtrConstant(2)), value_word32))));
BIND(&big);
// 4. If typedArray.[[ContentType]] is BigInt, let v be ? ToBigInt(value).
......@@ -463,17 +467,14 @@ TF_BUILTIN(AtomicsExchange, SharedArrayBufferBuiltinsAssembler) {
Unreachable();
BIND(&i64);
// This uses Uint64() intentionally: AtomicExchange is not implemented for
// Int64(), which is fine because the machine instruction only cares
// about words.
Return(BigIntFromSigned64(AtomicExchange(
MachineType::Uint64(), backing_store,
WordShl(index_word, UintPtrConstant(3)), var_low.value(), high)));
Return(BigIntFromSigned64(AtomicExchange64<AtomicInt64>(
backing_store, WordShl(index_word, UintPtrConstant(3)), var_low.value(),
high)));
BIND(&u64);
Return(BigIntFromUnsigned64(AtomicExchange(
MachineType::Uint64(), backing_store,
WordShl(index_word, UintPtrConstant(3)), var_low.value(), high)));
Return(BigIntFromUnsigned64(AtomicExchange64<AtomicUint64>(
backing_store, WordShl(index_word, UintPtrConstant(3)), var_low.value(),
high)));
// This shouldn't happen, we've already validated the type.
BIND(&other);
......@@ -645,6 +646,8 @@ TF_BUILTIN(AtomicsCompareExchange, SharedArrayBufferBuiltinsAssembler) {
auto context = Parameter<Context>(Descriptor::kContext); \
AtomicBinopBuiltinCommon(array, index, value, context, \
&CodeAssembler::Atomic##op, \
&CodeAssembler::Atomic##op##64 < AtomicInt64 >, \
&CodeAssembler::Atomic##op##64 < AtomicUint64 >, \
Runtime::kAtomics##op, method_name); \
}
// https://tc39.es/ecma262/#sec-atomics.add
......@@ -663,6 +666,8 @@ BINOP_BUILTIN(Xor, "Atomics.xor")
void SharedArrayBufferBuiltinsAssembler::AtomicBinopBuiltinCommon(
TNode<Object> maybe_array, TNode<Object> index, TNode<Object> value,
TNode<Context> context, AssemblerFunction function,
AssemblerFunction64<AtomicInt64> function_int_64,
AssemblerFunction64<AtomicUint64> function_uint_64,
Runtime::FunctionId runtime_function, const char* method_name) {
// 1. Let buffer be ? ValidateIntegerTypedArray(typedArray).
Label detached(this);
......@@ -718,29 +723,27 @@ void SharedArrayBufferBuiltinsAssembler::AtomicBinopBuiltinCommon(
arraysize(case_labels));
BIND(&i8);
Return(
SmiFromInt32((this->*function)(MachineType::Int8(), backing_store,
index_word, value_word32, base::nullopt)));
Return(SmiFromInt32(Signed((this->*function)(
MachineType::Int8(), backing_store, index_word, value_word32))));
BIND(&u8);
Return(
SmiFromInt32((this->*function)(MachineType::Uint8(), backing_store,
index_word, value_word32, base::nullopt)));
Return(SmiFromInt32(Signed((this->*function)(
MachineType::Uint8(), backing_store, index_word, value_word32))));
BIND(&i16);
Return(SmiFromInt32((this->*function)(MachineType::Int16(), backing_store,
WordShl(index_word, UintPtrConstant(1)),
value_word32, base::nullopt)));
Return(SmiFromInt32(Signed((this->*function)(
MachineType::Int16(), backing_store,
WordShl(index_word, UintPtrConstant(1)), value_word32))));
BIND(&u16);
Return(SmiFromInt32((this->*function)(MachineType::Uint16(), backing_store,
WordShl(index_word, UintPtrConstant(1)),
value_word32, base::nullopt)));
Return(SmiFromInt32(Signed((this->*function)(
MachineType::Uint16(), backing_store,
WordShl(index_word, UintPtrConstant(1)), value_word32))));
BIND(&i32);
Return(ChangeInt32ToTagged((this->*function)(
Return(ChangeInt32ToTagged(Signed((this->*function)(
MachineType::Int32(), backing_store,
WordShl(index_word, UintPtrConstant(2)), value_word32, base::nullopt)));
WordShl(index_word, UintPtrConstant(2)), value_word32))));
BIND(&u32);
Return(ChangeUint32ToTagged((this->*function)(
Return(ChangeUint32ToTagged(Unsigned((this->*function)(
MachineType::Uint32(), backing_store,
WordShl(index_word, UintPtrConstant(2)), value_word32, base::nullopt)));
WordShl(index_word, UintPtrConstant(2)), value_word32))));
BIND(&big);
// 4. If typedArray.[[ContentType]] is BigInt, let v be ? ToBigInt(value).
TNode<BigInt> value_bigint = ToBigInt(context, value);
......@@ -759,17 +762,14 @@ void SharedArrayBufferBuiltinsAssembler::AtomicBinopBuiltinCommon(
Unreachable();
BIND(&i64);
// This uses Uint64() intentionally: Atomic* ops are not implemented for
// Int64(), which is fine because the machine instructions only care
// about words.
Return(BigIntFromSigned64((this->*function)(
MachineType::Uint64(), backing_store,
WordShl(index_word, UintPtrConstant(3)), var_low.value(), high)));
Return(BigIntFromSigned64((this->*function_int_64)(
backing_store, WordShl(index_word, UintPtrConstant(3)), var_low.value(),
high)));
BIND(&u64);
Return(BigIntFromUnsigned64((this->*function)(
MachineType::Uint64(), backing_store,
WordShl(index_word, UintPtrConstant(3)), var_low.value(), high)));
// This shouldn't happen, we've already validated the type.
Return(BigIntFromUnsigned64((this->*function_uint_64)(
backing_store, WordShl(index_word, UintPtrConstant(3)), var_low.value(),
high)));
// // This shouldn't happen, we've already validated the type.
BIND(&other);
Unreachable();
#endif // V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_PPC64
......
......@@ -816,14 +816,25 @@ Node* CodeAssembler::AtomicStore(MachineRepresentation rep, Node* base,
}
#define ATOMIC_FUNCTION(name) \
Node* CodeAssembler::Atomic##name( \
TNode<Word32T> CodeAssembler::Atomic##name( \
MachineType type, TNode<RawPtrT> base, TNode<UintPtrT> offset, \
Node* value, base::Optional<TNode<UintPtrT>> value_high) { \
Node* value_high_node = nullptr; \
if (value_high) value_high_node = *value_high; \
return raw_assembler()->Atomic##name(type, base, offset, value, \
value_high_node); \
}
TNode<Word32T> value) { \
return UncheckedCast<Word32T>( \
raw_assembler()->Atomic##name(type, base, offset, value)); \
} \
template <class Type> \
TNode<Type> CodeAssembler::Atomic##name##64( \
TNode<RawPtrT> base, TNode<UintPtrT> offset, TNode<UintPtrT> value, \
TNode<UintPtrT> value_high) { \
return UncheckedCast<Type>( \
raw_assembler()->Atomic##name##64(base, offset, value, value_high)); \
} \
template TNode<AtomicInt64> CodeAssembler::Atomic##name##64 < AtomicInt64 > \
(TNode<RawPtrT> base, TNode<UintPtrT> offset, TNode<UintPtrT> value, \
TNode<UintPtrT> value_high); \
template TNode<AtomicUint64> CodeAssembler::Atomic##name##64 < \
AtomicUint64 > (TNode<RawPtrT> base, TNode<UintPtrT> offset, \
TNode<UintPtrT> value, TNode<UintPtrT> value_high);
ATOMIC_FUNCTION(Add)
ATOMIC_FUNCTION(Sub)
ATOMIC_FUNCTION(And)
......
......@@ -805,25 +805,43 @@ class V8_EXPORT_PRIVATE CodeAssembler {
Node* AtomicStore(MachineRepresentation rep, Node* base, Node* offset,
Node* value, Node* value_high = nullptr);
Node* AtomicAdd(MachineType type, TNode<RawPtrT> base, TNode<UintPtrT> offset,
Node* value, base::Optional<TNode<UintPtrT>> value_high);
TNode<Word32T> AtomicAdd(MachineType type, TNode<RawPtrT> base,
TNode<UintPtrT> offset, TNode<Word32T> value);
template <class Type>
TNode<Type> AtomicAdd64(TNode<RawPtrT> base, TNode<UintPtrT> offset,
TNode<UintPtrT> value, TNode<UintPtrT> value_high);
Node* AtomicSub(MachineType type, TNode<RawPtrT> base, TNode<UintPtrT> offset,
Node* value, base::Optional<TNode<UintPtrT>> value_high);
TNode<Word32T> AtomicSub(MachineType type, TNode<RawPtrT> base,
TNode<UintPtrT> offset, TNode<Word32T> value);
template <class Type>
TNode<Type> AtomicSub64(TNode<RawPtrT> base, TNode<UintPtrT> offset,
TNode<UintPtrT> value, TNode<UintPtrT> value_high);
Node* AtomicAnd(MachineType type, TNode<RawPtrT> base, TNode<UintPtrT> offset,
Node* value, base::Optional<TNode<UintPtrT>> value_high);
TNode<Word32T> AtomicAnd(MachineType type, TNode<RawPtrT> base,
TNode<UintPtrT> offset, TNode<Word32T> value);
template <class Type>
TNode<Type> AtomicAnd64(TNode<RawPtrT> base, TNode<UintPtrT> offset,
TNode<UintPtrT> value, TNode<UintPtrT> value_high);
Node* AtomicOr(MachineType type, TNode<RawPtrT> base, TNode<UintPtrT> offset,
Node* value, base::Optional<TNode<UintPtrT>> value_high);
TNode<Word32T> AtomicOr(MachineType type, TNode<RawPtrT> base,
TNode<UintPtrT> offset, TNode<Word32T> value);
template <class Type>
TNode<Type> AtomicOr64(TNode<RawPtrT> base, TNode<UintPtrT> offset,
TNode<UintPtrT> value, TNode<UintPtrT> value_high);
Node* AtomicXor(MachineType type, TNode<RawPtrT> base, TNode<UintPtrT> offset,
Node* value, base::Optional<TNode<UintPtrT>> value_high);
TNode<Word32T> AtomicXor(MachineType type, TNode<RawPtrT> base,
TNode<UintPtrT> offset, TNode<Word32T> value);
template <class Type>
TNode<Type> AtomicXor64(TNode<RawPtrT> base, TNode<UintPtrT> offset,
TNode<UintPtrT> value, TNode<UintPtrT> value_high);
// Exchange value at raw memory location
Node* AtomicExchange(MachineType type, TNode<RawPtrT> base,
TNode<UintPtrT> offset, Node* value,
base::Optional<TNode<UintPtrT>> value_high);
TNode<Word32T> AtomicExchange(MachineType type, TNode<RawPtrT> base,
TNode<UintPtrT> offset, TNode<Word32T> value);
template <class Type>
TNode<Type> AtomicExchange64(TNode<RawPtrT> base, TNode<UintPtrT> offset,
TNode<UintPtrT> value,
TNode<UintPtrT> value_high);
// Compare and Exchange value at raw memory location
Node* AtomicCompareExchange(MachineType type, Node* base, Node* offset,
......
......@@ -258,20 +258,23 @@ class V8_EXPORT_PRIVATE RawMachineAssembler {
return AddNode(machine()->Word32AtomicStore(rep), base, index, value);
}
#define ATOMIC_FUNCTION(name) \
Node* Atomic##name(MachineType type, Node* base, Node* index, Node* value, \
Node* value_high) { \
if (type.representation() == MachineRepresentation::kWord64) { \
Node* Atomic##name(MachineType type, Node* base, Node* index, Node* value) { \
DCHECK_NE(type.representation(), MachineRepresentation::kWord64); \
return AddNode(machine()->Word32Atomic##name(type), base, index, value); \
} \
Node* Atomic##name##64(Node * base, Node * index, Node * value, \
Node * value_high) { \
if (machine()->Is64()) { \
DCHECK_NULL(value_high); \
return AddNode(machine()->Word64Atomic##name(type), base, index, \
value); \
/* This uses Uint64() intentionally: Atomic operations are not */ \
/* implemented for Int64(), which is fine because the machine */ \
/* instruction only cares about words. */ \
return AddNode(machine()->Word64Atomic##name(MachineType::Uint64()), \
base, index, value); \
} else { \
return AddNode(machine()->Word32AtomicPair##name(), base, index, \
VALUE_HALVES); \
} \
} \
DCHECK_NULL(value_high); \
return AddNode(machine()->Word32Atomic##name(type), base, index, value); \
}
ATOMIC_FUNCTION(Exchange)
ATOMIC_FUNCTION(Add)
......
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