[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: Camillo Bruni <cbruni@chromium.org>
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#76207}
This commit is contained in:
Maya Lekova 2021-08-10 16:03:58 +02:00 committed by V8 LUCI CQ
parent 12d112163b
commit 22f326b8af
6 changed files with 45 additions and 47 deletions

View File

@ -299,10 +299,42 @@ class CTypeInfo {
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>
struct FastApiTypedArray {
T* data; // should include the typed array offset applied
size_t length; // length in number of elements
struct FastApiTypedArray : public FastApiTypedArrayBase {
public:
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

View File

@ -10045,6 +10045,10 @@ const CTypeInfo& CFunctionInfo::ArgumentInfo(unsigned int index) const {
return arg_info_[index];
}
void FastApiTypedArrayBase::ValidateIndex(size_t index) const {
DCHECK_LT(index, length_);
}
RegisterState::RegisterState()
: pc(nullptr), sp(nullptr), fp(nullptr), lr(nullptr) {}
RegisterState::~RegisterState() = default;
@ -10332,18 +10336,6 @@ bool ConvertDouble(double d) {
} // 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
#undef TRACE_BS

View File

@ -5083,10 +5083,10 @@ Node* EffectControlLinearizer::AdaptFastCallTypedArrayArgument(
__ Store(StoreRepresentation(MachineType::PointerRepresentation(),
kNoWriteBarrier),
stack_slot, 0, data_ptr);
stack_slot, 0, length_in_bytes);
__ Store(StoreRepresentation(MachineType::PointerRepresentation(),
kNoWriteBarrier),
stack_slot, sizeof(uintptr_t), length_in_bytes);
stack_slot, sizeof(size_t), data_ptr);
static_assert(sizeof(uintptr_t) == sizeof(size_t),
"The buffer length can't "
"fit the PointerRepresentation used to store it.");

View File

@ -3549,23 +3549,6 @@ bool Has64BitIntegerParamsInSignature(const CFunctionInfo* c_signature) {
} // namespace
#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
// optimized, applying the initial step of the overload resolution algorithm:
// Given an overload set function_template_info.c_signatures, and a list of
@ -3620,10 +3603,6 @@ FastApiCallFunctionVector CanOptimizeFastCall(
optimize_to_fast_call =
optimize_to_fast_call && !Has64BitIntegerParamsInSignature(c_signature);
#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) {
result.push_back({functions[i], c_signature});

View File

@ -206,14 +206,9 @@ class FastCApiObject {
return 0;
}
if (!typed_array_arg.data) {
options.fallback = 1;
return 0;
}
T sum = 0;
for (unsigned i = 0; i < typed_array_arg.length; ++i) {
sum += typed_array_arg.data[i];
for (unsigned i = 0; i < typed_array_arg.length(); ++i) {
sum += typed_array_arg.get(i);
}
return static_cast<Type>(sum);
}

View File

@ -41,7 +41,7 @@ const max_safe_as_bigint = BigInt(Number.MAX_SAFE_INTEGER);
typed_array);
}
const expected = Number(BigInt.asIntN(64, -42n + 1n + max_safe_as_bigint));
ExpectSlowCall(int64_test, expected);
ExpectFastCall(int64_test, expected);
})();
(function () {
@ -51,5 +51,5 @@ const max_safe_as_bigint = BigInt(Number.MAX_SAFE_INTEGER);
typed_array);
}
const expected = Number(BigInt.asUintN(64, max_safe_as_bigint + 1n + 2n));
ExpectSlowCall(uint64_test, expected);
ExpectFastCall(uint64_test, expected);
})();