[csa][cleanup] TNodify AtomicLoad and thereby all uses of Projection.
Introduces an AtomicUint64 type and a seperate AtomicLoad64 due to the different types returned by loading 64-bit atomic values on 32-bit vs 64-bit architectures. BUG=v8:6949,v8:11074 Change-Id: I95de994df9639847cd6b5fd56ea2a6585189ed3a Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2529455 Commit-Queue: Ross McIlroy <rmcilroy@chromium.org> Reviewed-by: Santiago Aboy Solanes <solanes@chromium.org> Auto-Submit: Ross McIlroy <rmcilroy@chromium.org> Cr-Commit-Position: refs/heads/master@{#71110}
This commit is contained in:
parent
3658a43156
commit
b0329614fe
@ -43,8 +43,8 @@ class SharedArrayBufferBuiltinsAssembler : public CodeStubAssembler {
|
|||||||
|
|
||||||
// Create a BigInt from the result of a 64-bit atomic operation, using
|
// Create a BigInt from the result of a 64-bit atomic operation, using
|
||||||
// projections on 32-bit platforms.
|
// projections on 32-bit platforms.
|
||||||
TNode<BigInt> BigIntFromSigned64(Node* signed64);
|
TNode<BigInt> BigIntFromSigned64(SloppyTNode<AtomicInt64> signed64);
|
||||||
TNode<BigInt> BigIntFromUnsigned64(Node* unsigned64);
|
TNode<BigInt> BigIntFromUnsigned64(SloppyTNode<AtomicUint64> unsigned64);
|
||||||
};
|
};
|
||||||
|
|
||||||
// https://tc39.es/ecma262/#sec-validateintegertypedarray
|
// https://tc39.es/ecma262/#sec-validateintegertypedarray
|
||||||
@ -142,25 +142,25 @@ void SharedArrayBufferBuiltinsAssembler::DebugCheckAtomicIndex(
|
|||||||
}
|
}
|
||||||
|
|
||||||
TNode<BigInt> SharedArrayBufferBuiltinsAssembler::BigIntFromSigned64(
|
TNode<BigInt> SharedArrayBufferBuiltinsAssembler::BigIntFromSigned64(
|
||||||
Node* signed64) {
|
SloppyTNode<AtomicInt64> signed64) {
|
||||||
if (Is64()) {
|
#if defined(V8_HOST_ARCH_32_BIT)
|
||||||
return BigIntFromInt64(UncheckedCast<IntPtrT>(signed64));
|
TNode<IntPtrT> low = Projection<0>(signed64);
|
||||||
} else {
|
TNode<IntPtrT> high = Projection<1>(signed64);
|
||||||
TNode<IntPtrT> low = UncheckedCast<IntPtrT>(Projection(0, signed64));
|
return BigIntFromInt32Pair(low, high);
|
||||||
TNode<IntPtrT> high = UncheckedCast<IntPtrT>(Projection(1, signed64));
|
#else
|
||||||
return BigIntFromInt32Pair(low, high);
|
return BigIntFromInt64(signed64);
|
||||||
}
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
TNode<BigInt> SharedArrayBufferBuiltinsAssembler::BigIntFromUnsigned64(
|
TNode<BigInt> SharedArrayBufferBuiltinsAssembler::BigIntFromUnsigned64(
|
||||||
Node* unsigned64) {
|
SloppyTNode<AtomicUint64> unsigned64) {
|
||||||
if (Is64()) {
|
#if defined(V8_HOST_ARCH_32_BIT)
|
||||||
return BigIntFromUint64(UncheckedCast<UintPtrT>(unsigned64));
|
TNode<UintPtrT> low = Projection<0>(unsigned64);
|
||||||
} else {
|
TNode<UintPtrT> high = Projection<1>(unsigned64);
|
||||||
TNode<UintPtrT> low = UncheckedCast<UintPtrT>(Projection(0, unsigned64));
|
return BigIntFromUint32Pair(low, high);
|
||||||
TNode<UintPtrT> high = UncheckedCast<UintPtrT>(Projection(1, unsigned64));
|
#else
|
||||||
return BigIntFromUint32Pair(low, high);
|
return BigIntFromUint64(unsigned64);
|
||||||
}
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://tc39.es/ecma262/#sec-atomicload
|
// https://tc39.es/ecma262/#sec-atomicload
|
||||||
@ -201,28 +201,26 @@ TF_BUILTIN(AtomicsLoad, SharedArrayBufferBuiltinsAssembler) {
|
|||||||
arraysize(case_labels));
|
arraysize(case_labels));
|
||||||
|
|
||||||
BIND(&i8);
|
BIND(&i8);
|
||||||
Return(
|
Return(SmiFromInt32(AtomicLoad<Int8T>(backing_store, index_word)));
|
||||||
SmiFromInt32(AtomicLoad(MachineType::Int8(), backing_store, index_word)));
|
|
||||||
|
|
||||||
BIND(&u8);
|
BIND(&u8);
|
||||||
Return(SmiFromInt32(
|
Return(SmiFromInt32(AtomicLoad<Uint8T>(backing_store, index_word)));
|
||||||
AtomicLoad(MachineType::Uint8(), backing_store, index_word)));
|
|
||||||
|
|
||||||
BIND(&i16);
|
BIND(&i16);
|
||||||
Return(SmiFromInt32(
|
Return(
|
||||||
AtomicLoad(MachineType::Int16(), backing_store, WordShl(index_word, 1))));
|
SmiFromInt32(AtomicLoad<Int16T>(backing_store, WordShl(index_word, 1))));
|
||||||
|
|
||||||
BIND(&u16);
|
BIND(&u16);
|
||||||
Return(SmiFromInt32(AtomicLoad(MachineType::Uint16(), backing_store,
|
Return(
|
||||||
WordShl(index_word, 1))));
|
SmiFromInt32(AtomicLoad<Uint16T>(backing_store, WordShl(index_word, 1))));
|
||||||
|
|
||||||
BIND(&i32);
|
BIND(&i32);
|
||||||
Return(ChangeInt32ToTagged(
|
Return(ChangeInt32ToTagged(
|
||||||
AtomicLoad(MachineType::Int32(), backing_store, WordShl(index_word, 2))));
|
AtomicLoad<Int32T>(backing_store, WordShl(index_word, 2))));
|
||||||
|
|
||||||
BIND(&u32);
|
BIND(&u32);
|
||||||
Return(ChangeUint32ToTagged(AtomicLoad(MachineType::Uint32(), backing_store,
|
Return(ChangeUint32ToTagged(
|
||||||
WordShl(index_word, 2))));
|
AtomicLoad<Uint32T>(backing_store, WordShl(index_word, 2))));
|
||||||
#if V8_TARGET_ARCH_MIPS && !_MIPS_ARCH_MIPS32R6
|
#if V8_TARGET_ARCH_MIPS && !_MIPS_ARCH_MIPS32R6
|
||||||
BIND(&i64);
|
BIND(&i64);
|
||||||
Goto(&u64);
|
Goto(&u64);
|
||||||
@ -234,15 +232,12 @@ TF_BUILTIN(AtomicsLoad, SharedArrayBufferBuiltinsAssembler) {
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
BIND(&i64);
|
BIND(&i64);
|
||||||
// This uses Uint64() intentionally: AtomicLoad is not implemented for
|
Return(BigIntFromSigned64(
|
||||||
// Int64(), which is fine because the machine instruction only cares
|
AtomicLoad64<AtomicInt64>(backing_store, WordShl(index_word, 3))));
|
||||||
// about words.
|
|
||||||
Return(BigIntFromSigned64(AtomicLoad(MachineType::Uint64(), backing_store,
|
|
||||||
WordShl(index_word, 3))));
|
|
||||||
|
|
||||||
BIND(&u64);
|
BIND(&u64);
|
||||||
Return(BigIntFromUnsigned64(AtomicLoad(MachineType::Uint64(), backing_store,
|
Return(BigIntFromUnsigned64(
|
||||||
WordShl(index_word, 3))));
|
AtomicLoad64<AtomicUint64>(backing_store, WordShl(index_word, 3))));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// This shouldn't happen, we've already validated the type.
|
// This shouldn't happen, we've already validated the type.
|
||||||
|
@ -667,10 +667,22 @@ TNode<Object> CodeAssembler::LoadFullTagged(Node* base, Node* offset,
|
|||||||
Load(MachineType::Pointer(), base, offset, needs_poisoning));
|
Load(MachineType::Pointer(), base, offset, needs_poisoning));
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* CodeAssembler::AtomicLoad(MachineType type, Node* base, Node* offset) {
|
Node* CodeAssembler::AtomicLoad(MachineType type, TNode<RawPtrT> base,
|
||||||
|
TNode<WordT> offset) {
|
||||||
return raw_assembler()->AtomicLoad(type, base, offset);
|
return raw_assembler()->AtomicLoad(type, base, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class Type>
|
||||||
|
TNode<Type> CodeAssembler::AtomicLoad64(TNode<RawPtrT> base,
|
||||||
|
TNode<WordT> offset) {
|
||||||
|
return UncheckedCast<Type>(raw_assembler()->AtomicLoad64(base, offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
template TNode<AtomicInt64> CodeAssembler::AtomicLoad64<AtomicInt64>(
|
||||||
|
TNode<RawPtrT> base, TNode<WordT> offset);
|
||||||
|
template TNode<AtomicUint64> CodeAssembler::AtomicLoad64<AtomicUint64>(
|
||||||
|
TNode<RawPtrT> base, TNode<WordT> offset);
|
||||||
|
|
||||||
Node* CodeAssembler::LoadFromObject(MachineType type, TNode<HeapObject> object,
|
Node* CodeAssembler::LoadFromObject(MachineType type, TNode<HeapObject> object,
|
||||||
TNode<IntPtrT> offset) {
|
TNode<IntPtrT> offset) {
|
||||||
return raw_assembler()->LoadFromObject(type, object, offset);
|
return raw_assembler()->LoadFromObject(type, object, offset);
|
||||||
|
@ -178,6 +178,20 @@ HEAP_OBJECT_TEMPLATE_TYPE_LIST(OBJECT_TYPE_TEMPLATE_CASE)
|
|||||||
#undef OBJECT_TYPE_STRUCT_CASE
|
#undef OBJECT_TYPE_STRUCT_CASE
|
||||||
#undef OBJECT_TYPE_TEMPLATE_CASE
|
#undef OBJECT_TYPE_TEMPLATE_CASE
|
||||||
|
|
||||||
|
#if defined(V8_HOST_ARCH_32_BIT)
|
||||||
|
#define BINT_IS_SMI
|
||||||
|
using BInt = Smi;
|
||||||
|
using AtomicInt64 = PairT<IntPtrT, IntPtrT>;
|
||||||
|
using AtomicUint64 = PairT<UintPtrT, UintPtrT>;
|
||||||
|
#elif defined(V8_HOST_ARCH_64_BIT)
|
||||||
|
#define BINT_IS_INTPTR
|
||||||
|
using BInt = IntPtrT;
|
||||||
|
using AtomicInt64 = IntPtrT;
|
||||||
|
using AtomicUint64 = UintPtrT;
|
||||||
|
#else
|
||||||
|
#error Unknown architecture.
|
||||||
|
#endif
|
||||||
|
|
||||||
// {raw_value} must be a tagged Object.
|
// {raw_value} must be a tagged Object.
|
||||||
// {raw_type} must be a tagged Smi.
|
// {raw_type} must be a tagged Smi.
|
||||||
// {raw_location} must be a tagged String.
|
// {raw_location} must be a tagged String.
|
||||||
@ -731,7 +745,13 @@ class V8_EXPORT_PRIVATE CodeAssembler {
|
|||||||
return UncheckedCast<Type>(
|
return UncheckedCast<Type>(
|
||||||
Load(MachineTypeOf<Type>::value, base, offset, needs_poisoning));
|
Load(MachineTypeOf<Type>::value, base, offset, needs_poisoning));
|
||||||
}
|
}
|
||||||
Node* AtomicLoad(MachineType type, Node* base, Node* offset);
|
template <class Type>
|
||||||
|
TNode<Type> AtomicLoad(TNode<RawPtrT> base, TNode<WordT> offset) {
|
||||||
|
return UncheckedCast<Type>(
|
||||||
|
AtomicLoad(MachineTypeOf<Type>::value, base, offset));
|
||||||
|
}
|
||||||
|
template <class Type>
|
||||||
|
TNode<Type> AtomicLoad64(TNode<RawPtrT> base, TNode<WordT> offset);
|
||||||
// Load uncompressed tagged value from (most likely off JS heap) memory
|
// Load uncompressed tagged value from (most likely off JS heap) memory
|
||||||
// location.
|
// location.
|
||||||
TNode<Object> LoadFullTagged(
|
TNode<Object> LoadFullTagged(
|
||||||
@ -992,8 +1012,6 @@ class V8_EXPORT_PRIVATE CodeAssembler {
|
|||||||
TNode<Int32T> TruncateFloat32ToInt32(SloppyTNode<Float32T> value);
|
TNode<Int32T> TruncateFloat32ToInt32(SloppyTNode<Float32T> value);
|
||||||
|
|
||||||
// Projections
|
// Projections
|
||||||
Node* Projection(int index, Node* value);
|
|
||||||
|
|
||||||
template <int index, class T1, class T2>
|
template <int index, class T1, class T2>
|
||||||
TNode<typename std::tuple_element<index, std::tuple<T1, T2>>::type>
|
TNode<typename std::tuple_element<index, std::tuple<T1, T2>>::type>
|
||||||
Projection(TNode<PairT<T1, T2>> value) {
|
Projection(TNode<PairT<T1, T2>> value) {
|
||||||
@ -1232,11 +1250,15 @@ class V8_EXPORT_PRIVATE CodeAssembler {
|
|||||||
const CallInterfaceDescriptor& descriptor, int input_count,
|
const CallInterfaceDescriptor& descriptor, int input_count,
|
||||||
Node* const* inputs);
|
Node* const* inputs);
|
||||||
|
|
||||||
|
Node* AtomicLoad(MachineType type, TNode<RawPtrT> base, TNode<WordT> offset);
|
||||||
|
|
||||||
// These two don't have definitions and are here only for catching use cases
|
// These two don't have definitions and are here only for catching use cases
|
||||||
// where the cast is not necessary.
|
// where the cast is not necessary.
|
||||||
TNode<Int32T> Signed(TNode<Int32T> x);
|
TNode<Int32T> Signed(TNode<Int32T> x);
|
||||||
TNode<Uint32T> Unsigned(TNode<Uint32T> x);
|
TNode<Uint32T> Unsigned(TNode<Uint32T> x);
|
||||||
|
|
||||||
|
Node* Projection(int index, Node* value);
|
||||||
|
|
||||||
RawMachineAssembler* raw_assembler() const;
|
RawMachineAssembler* raw_assembler() const;
|
||||||
JSGraph* jsgraph() const;
|
JSGraph* jsgraph() const;
|
||||||
|
|
||||||
@ -1533,17 +1555,6 @@ class V8_EXPORT_PRIVATE ScopedExceptionHandler {
|
|||||||
};
|
};
|
||||||
|
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
|
|
||||||
#if defined(V8_HOST_ARCH_32_BIT)
|
|
||||||
#define BINT_IS_SMI
|
|
||||||
using BInt = Smi;
|
|
||||||
#elif defined(V8_HOST_ARCH_64_BIT)
|
|
||||||
#define BINT_IS_INTPTR
|
|
||||||
using BInt = IntPtrT;
|
|
||||||
#else
|
|
||||||
#error Unknown architecture.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
|
||||||
|
@ -221,16 +221,22 @@ class V8_EXPORT_PRIVATE RawMachineAssembler {
|
|||||||
|
|
||||||
// Atomic memory operations.
|
// Atomic memory operations.
|
||||||
Node* AtomicLoad(MachineType type, Node* base, Node* index) {
|
Node* AtomicLoad(MachineType type, Node* base, Node* index) {
|
||||||
if (type.representation() == MachineRepresentation::kWord64) {
|
DCHECK_NE(type.representation(), MachineRepresentation::kWord64);
|
||||||
if (machine()->Is64()) {
|
|
||||||
return AddNode(machine()->Word64AtomicLoad(type), base, index);
|
|
||||||
} else {
|
|
||||||
return AddNode(machine()->Word32AtomicPairLoad(), base, index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return AddNode(machine()->Word32AtomicLoad(type), base, index);
|
return AddNode(machine()->Word32AtomicLoad(type), base, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node* AtomicLoad64(Node* base, Node* index) {
|
||||||
|
if (machine()->Is64()) {
|
||||||
|
// This uses Uint64() intentionally: AtomicLoad is not implemented for
|
||||||
|
// Int64(), which is fine because the machine instruction only cares
|
||||||
|
// about words.
|
||||||
|
return AddNode(machine()->Word64AtomicLoad(MachineType::Uint64()), base,
|
||||||
|
index);
|
||||||
|
} else {
|
||||||
|
return AddNode(machine()->Word32AtomicPairLoad(), base, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(V8_TARGET_BIG_ENDIAN)
|
#if defined(V8_TARGET_BIG_ENDIAN)
|
||||||
#define VALUE_HALVES value_high, value
|
#define VALUE_HALVES value_high, value
|
||||||
#else
|
#else
|
||||||
|
Loading…
Reference in New Issue
Block a user