Commit 22f326b8 authored by Maya Lekova's avatar Maya Lekova Committed by V8 LUCI CQ

[fastcall] Add 8-byte element types support for TypedArrays

This CL adds back the 8-byte element types and extends the fast API
by hiding the unaligned memory reads performed for them.

Bug: chromium:1052746
Change-Id: Ide49ce6bd2c77b9d2d544ca2df47b5f95c93eaa9
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3056988
Commit-Queue: Maya Lekova <mslekova@chromium.org>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#76207}
parent 12d11216
...@@ -299,10 +299,42 @@ class CTypeInfo { ...@@ -299,10 +299,42 @@ class CTypeInfo {
Flags flags_; Flags flags_;
}; };
struct FastApiTypedArrayBase {
public:
// Returns the length in number of elements.
size_t V8_EXPORT length() const { return length_; }
// Checks whether the given index is within the bounds of the collection.
void V8_EXPORT ValidateIndex(size_t index) const;
protected:
size_t length_ = 0;
};
template <typename T> template <typename T>
struct FastApiTypedArray { struct FastApiTypedArray : public FastApiTypedArrayBase {
T* data; // should include the typed array offset applied public:
size_t length; // length in number of elements V8_INLINE T get(size_t index) const {
#ifdef DEBUG
ValidateIndex(index);
#endif // DEBUG
static_assert(offsetof(FastApiTypedArray<T>, length_) <
offsetof(FastApiTypedArray<T>, data_),
"length_ should be "
"stored in memory before data_, initializing the "
"FastApiTypedArray struct will fail.");
T tmp;
memcpy(&tmp, reinterpret_cast<T*>(data_) + index, sizeof(T));
return tmp;
}
private:
// This pointer should include the typed array offset applied.
// It's not guaranteed that it's aligned to sizeof(T), it's only
// guaranteed that it's 4-byte aligned, so for 8-byte types we need to
// provide a special implementation for reading from it, which hides
// the possibly unaligned read in the `get` method.
void* data_;
}; };
// Any TypedArray. It uses kTypedArrayBit with base type void // Any TypedArray. It uses kTypedArrayBit with base type void
......
...@@ -10045,6 +10045,10 @@ const CTypeInfo& CFunctionInfo::ArgumentInfo(unsigned int index) const { ...@@ -10045,6 +10045,10 @@ const CTypeInfo& CFunctionInfo::ArgumentInfo(unsigned int index) const {
return arg_info_[index]; return arg_info_[index];
} }
void FastApiTypedArrayBase::ValidateIndex(size_t index) const {
DCHECK_LT(index, length_);
}
RegisterState::RegisterState() RegisterState::RegisterState()
: pc(nullptr), sp(nullptr), fp(nullptr), lr(nullptr) {} : pc(nullptr), sp(nullptr), fp(nullptr), lr(nullptr) {}
RegisterState::~RegisterState() = default; RegisterState::~RegisterState() = default;
...@@ -10332,18 +10336,6 @@ bool ConvertDouble(double d) { ...@@ -10332,18 +10336,6 @@ bool ConvertDouble(double d) {
} // namespace internal } // namespace internal
bool CopyAndConvertArrayToCppBufferInt32(Local<Array> src, int32_t* dst,
uint32_t max_length) {
return CopyAndConvertArrayToCppBuffer<&v8::kTypeInfoInt32, int32_t>(
src, dst, max_length);
}
bool CopyAndConvertArrayToCppBufferFloat64(Local<Array> src, double* dst,
uint32_t max_length) {
return CopyAndConvertArrayToCppBuffer<&v8::kTypeInfoFloat64, double>(
src, dst, max_length);
}
} // namespace v8 } // namespace v8
#undef TRACE_BS #undef TRACE_BS
......
...@@ -5083,10 +5083,10 @@ Node* EffectControlLinearizer::AdaptFastCallTypedArrayArgument( ...@@ -5083,10 +5083,10 @@ Node* EffectControlLinearizer::AdaptFastCallTypedArrayArgument(
__ Store(StoreRepresentation(MachineType::PointerRepresentation(), __ Store(StoreRepresentation(MachineType::PointerRepresentation(),
kNoWriteBarrier), kNoWriteBarrier),
stack_slot, 0, data_ptr); stack_slot, 0, length_in_bytes);
__ Store(StoreRepresentation(MachineType::PointerRepresentation(), __ Store(StoreRepresentation(MachineType::PointerRepresentation(),
kNoWriteBarrier), kNoWriteBarrier),
stack_slot, sizeof(uintptr_t), length_in_bytes); stack_slot, sizeof(size_t), data_ptr);
static_assert(sizeof(uintptr_t) == sizeof(size_t), static_assert(sizeof(uintptr_t) == sizeof(size_t),
"The buffer length can't " "The buffer length can't "
"fit the PointerRepresentation used to store it."); "fit the PointerRepresentation used to store it.");
......
...@@ -3549,23 +3549,6 @@ bool Has64BitIntegerParamsInSignature(const CFunctionInfo* c_signature) { ...@@ -3549,23 +3549,6 @@ bool Has64BitIntegerParamsInSignature(const CFunctionInfo* c_signature) {
} // namespace } // namespace
#endif #endif
namespace {
bool Has64BitTypedArraysInSignature(const CFunctionInfo* c_signature) {
for (unsigned int i = 0; i < c_signature->ArgumentCount(); ++i) {
if (c_signature->ArgumentInfo(i).GetSequenceType() !=
CTypeInfo::SequenceType::kIsTypedArray) {
continue;
}
if (c_signature->ArgumentInfo(i).GetType() == CTypeInfo::Type::kInt64 ||
c_signature->ArgumentInfo(i).GetType() == CTypeInfo::Type::kUint64 ||
c_signature->ArgumentInfo(i).GetType() == CTypeInfo::Type::kFloat64) {
return true;
}
}
return false;
}
} // namespace
// Given a FunctionTemplateInfo, checks whether the fast API call can be // Given a FunctionTemplateInfo, checks whether the fast API call can be
// optimized, applying the initial step of the overload resolution algorithm: // optimized, applying the initial step of the overload resolution algorithm:
// Given an overload set function_template_info.c_signatures, and a list of // Given an overload set function_template_info.c_signatures, and a list of
...@@ -3620,10 +3603,6 @@ FastApiCallFunctionVector CanOptimizeFastCall( ...@@ -3620,10 +3603,6 @@ FastApiCallFunctionVector CanOptimizeFastCall(
optimize_to_fast_call = optimize_to_fast_call =
optimize_to_fast_call && !Has64BitIntegerParamsInSignature(c_signature); optimize_to_fast_call && !Has64BitIntegerParamsInSignature(c_signature);
#endif #endif
// TODO(mslekova): Add back support for 64-bit TA params when the API is
// changed to disallow raw access to unaligned data.
optimize_to_fast_call =
optimize_to_fast_call && !Has64BitTypedArraysInSignature(c_signature);
if (optimize_to_fast_call) { if (optimize_to_fast_call) {
result.push_back({functions[i], c_signature}); result.push_back({functions[i], c_signature});
......
...@@ -206,14 +206,9 @@ class FastCApiObject { ...@@ -206,14 +206,9 @@ class FastCApiObject {
return 0; return 0;
} }
if (!typed_array_arg.data) {
options.fallback = 1;
return 0;
}
T sum = 0; T sum = 0;
for (unsigned i = 0; i < typed_array_arg.length; ++i) { for (unsigned i = 0; i < typed_array_arg.length(); ++i) {
sum += typed_array_arg.data[i]; sum += typed_array_arg.get(i);
} }
return static_cast<Type>(sum); return static_cast<Type>(sum);
} }
......
...@@ -41,7 +41,7 @@ const max_safe_as_bigint = BigInt(Number.MAX_SAFE_INTEGER); ...@@ -41,7 +41,7 @@ const max_safe_as_bigint = BigInt(Number.MAX_SAFE_INTEGER);
typed_array); typed_array);
} }
const expected = Number(BigInt.asIntN(64, -42n + 1n + max_safe_as_bigint)); const expected = Number(BigInt.asIntN(64, -42n + 1n + max_safe_as_bigint));
ExpectSlowCall(int64_test, expected); ExpectFastCall(int64_test, expected);
})(); })();
(function () { (function () {
...@@ -51,5 +51,5 @@ const max_safe_as_bigint = BigInt(Number.MAX_SAFE_INTEGER); ...@@ -51,5 +51,5 @@ const max_safe_as_bigint = BigInt(Number.MAX_SAFE_INTEGER);
typed_array); typed_array);
} }
const expected = Number(BigInt.asUintN(64, max_safe_as_bigint + 1n + 2n)); const expected = Number(BigInt.asUintN(64, max_safe_as_bigint + 1n + 2n));
ExpectSlowCall(uint64_test, expected); ExpectFastCall(uint64_test, expected);
})(); })();
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