[fastcall] Type-specialize CopyAndConvertArrayToCppBuffer
Rename CopyAndConvertArrayToCppBuffer as TryCopyAndConvertArrayToCppBuffer and implement type specialization for int32_t and double in order to speed up V8 bindings with sequences. This API is used by Blink code, for example see https://chromium-review.googlesource.com/c/chromium/src/+/3027405. Bug: v8:11739 Change-Id: I026a7f5e7833fb1afcc2ea9c296b66c7f733cbb1 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3036407 Commit-Queue: Paolo Severini <paolosev@microsoft.com> Reviewed-by: Camillo Bruni <cbruni@chromium.org> Reviewed-by: Maya Lekova <mslekova@chromium.org> Cr-Commit-Position: refs/heads/master@{#76016}
This commit is contained in:
parent
3a44f269c5
commit
530fd795a9
@ -225,8 +225,9 @@
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
#include "v8.h" // NOLINT(build/include_directory)
|
||||
#include "v8config.h" // NOLINT(build/include_directory)
|
||||
#include "v8-internal.h" // NOLINT(build/include_directory)
|
||||
#include "v8.h" // NOLINT(build/include_directory)
|
||||
#include "v8config.h" // NOLINT(build/include_directory)
|
||||
|
||||
namespace v8 {
|
||||
|
||||
@ -770,6 +771,10 @@ CFunction CFunction::ArgUnwrap<R (*)(Args...)>::Make(R (*func)(Args...)) {
|
||||
|
||||
using CFunctionBuilder = internal::CFunctionBuilder;
|
||||
|
||||
static constexpr CTypeInfo kTypeInfoInt32 = CTypeInfo(CTypeInfo::Type::kInt32);
|
||||
static constexpr CTypeInfo kTypeInfoFloat64 =
|
||||
CTypeInfo(CTypeInfo::Type::kFloat64);
|
||||
|
||||
/**
|
||||
* Copies the contents of this JavaScript array to a C++ buffer with
|
||||
* a given max_length. A CTypeInfo is passed as an argument,
|
||||
@ -783,8 +788,20 @@ using CFunctionBuilder = internal::CFunctionBuilder;
|
||||
* returns true on success. `type_info` will be used for conversions.
|
||||
*/
|
||||
template <const CTypeInfo* type_info, typename T>
|
||||
bool CopyAndConvertArrayToCppBuffer(Local<Array> src, T* dst,
|
||||
uint32_t max_length);
|
||||
bool V8_EXPORT TryCopyAndConvertArrayToCppBuffer(Local<Array> src, T* dst,
|
||||
uint32_t max_length);
|
||||
|
||||
template <>
|
||||
inline bool TryCopyAndConvertArrayToCppBuffer<&kTypeInfoInt32, int32_t>(
|
||||
Local<Array> src, int32_t* dst, uint32_t max_length) {
|
||||
return CopyAndConvertArrayToCppBufferInt32(src, dst, max_length);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool TryCopyAndConvertArrayToCppBuffer<&kTypeInfoFloat64, double>(
|
||||
Local<Array> src, double* dst, uint32_t max_length) {
|
||||
return CopyAndConvertArrayToCppBufferFloat64(src, dst, max_length);
|
||||
}
|
||||
|
||||
} // namespace v8
|
||||
|
||||
|
@ -15,9 +15,12 @@
|
||||
|
||||
namespace v8 {
|
||||
|
||||
class Array;
|
||||
class Context;
|
||||
class Data;
|
||||
class Isolate;
|
||||
template <typename T>
|
||||
class Local;
|
||||
|
||||
namespace internal {
|
||||
|
||||
@ -505,6 +508,15 @@ V8_INLINE void PerformCastCheck(T* data) {
|
||||
class BackingStoreBase {};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
V8_EXPORT bool CopyAndConvertArrayToCppBufferInt32(Local<Array> src,
|
||||
int32_t* dst,
|
||||
uint32_t max_length);
|
||||
|
||||
V8_EXPORT bool CopyAndConvertArrayToCppBufferFloat64(Local<Array> src,
|
||||
double* dst,
|
||||
uint32_t max_length);
|
||||
|
||||
} // namespace v8
|
||||
|
||||
#endif // INCLUDE_V8_INTERNAL_H_
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "src/api/api.h"
|
||||
#include "src/execution/interrupts-scope.h"
|
||||
#include "src/execution/microtask-queue.h"
|
||||
#include "src/execution/protectors.h"
|
||||
#include "src/handles/handles-inl.h"
|
||||
#include "src/heap/heap-inl.h"
|
||||
#include "src/objects/foreign-inl.h"
|
||||
@ -279,6 +280,10 @@ bool CopyAndConvertArrayToCppBuffer(Local<Array> src, T* dst,
|
||||
|
||||
i::DisallowGarbageCollection no_gc;
|
||||
i::JSArray obj = *reinterpret_cast<i::JSArray*>(*src);
|
||||
if (obj.IterationHasObservableEffects()) {
|
||||
// The array has a custom iterator.
|
||||
return false;
|
||||
}
|
||||
|
||||
i::FixedArrayBase elements = obj.elements();
|
||||
switch (obj.GetElementsKind()) {
|
||||
@ -294,6 +299,13 @@ bool CopyAndConvertArrayToCppBuffer(Local<Array> src, T* dst,
|
||||
}
|
||||
}
|
||||
|
||||
template <const CTypeInfo* type_info, typename T>
|
||||
inline bool V8_EXPORT TryCopyAndConvertArrayToCppBuffer(Local<Array> src,
|
||||
T* dst,
|
||||
uint32_t max_length) {
|
||||
return CopyAndConvertArrayToCppBuffer<type_info, T>(src, dst, max_length);
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
Handle<Context> HandleScopeImplementer::LastEnteredContext() {
|
||||
|
@ -10315,6 +10315,19 @@ bool ConvertDouble(double d) {
|
||||
#undef CALLBACK_SETTER
|
||||
|
||||
} // 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
|
||||
|
@ -119,8 +119,8 @@ class FastCApiObject {
|
||||
}
|
||||
|
||||
Type buffer[1024];
|
||||
bool result =
|
||||
CopyAndConvertArrayToCppBuffer<&type_info, Type>(seq_arg, buffer, 1024);
|
||||
bool result = TryCopyAndConvertArrayToCppBuffer<&type_info, Type>(
|
||||
seq_arg, buffer, 1024);
|
||||
if (!result) {
|
||||
options.fallback = 1;
|
||||
return 0;
|
||||
|
@ -1767,9 +1767,14 @@ bool Object::IterationHasObservableEffects() {
|
||||
#endif
|
||||
|
||||
// Check that we have the original ArrayPrototype.
|
||||
i::HandleScope handle_scope(isolate);
|
||||
i::Handle<i::Context> context;
|
||||
if (!array.GetCreationContext().ToHandle(&context)) return false;
|
||||
if (!array.map().prototype().IsJSObject()) return true;
|
||||
JSObject array_proto = JSObject::cast(array.map().prototype());
|
||||
if (!isolate->is_initial_array_prototype(array_proto)) return true;
|
||||
auto initial_array_prototype =
|
||||
context->native_context().initial_array_prototype();
|
||||
if (initial_array_prototype != array_proto) return true;
|
||||
|
||||
// Check that the ArrayPrototype hasn't been modified in a way that would
|
||||
// affect iteration.
|
||||
|
@ -592,7 +592,7 @@ class Object : public TaggedImpl<HeapObjectReferenceType::STRONG, Address> {
|
||||
// Returns true if the result of iterating over the object is the same
|
||||
// (including observable effects) as simply accessing the properties between 0
|
||||
// and length.
|
||||
bool IterationHasObservableEffects();
|
||||
V8_EXPORT_PRIVATE bool IterationHasObservableEffects();
|
||||
|
||||
// TC39 "Dynamic Code Brand Checks"
|
||||
bool IsCodeLike(Isolate* isolate) const;
|
||||
|
@ -11,6 +11,9 @@
|
||||
// The test relies on optimizing/deoptimizing at predictable moments, so
|
||||
// it's not suitable for deoptimization fuzzing.
|
||||
// Flags: --deopt-every-n-times=0
|
||||
// The test relies on TryCopyAndConvertArrayToCppBuffer that fails with
|
||||
// --force-slow-path.
|
||||
// Flags: --no-force-slow-path
|
||||
|
||||
d8.file.execute('test/mjsunit/compiler/fast-api-helpers.js');
|
||||
|
||||
|
@ -11,6 +11,9 @@
|
||||
// The test relies on optimizing/deoptimizing at predictable moments, so
|
||||
// it's not suitable for deoptimization fuzzing.
|
||||
// Flags: --deopt-every-n-times=0
|
||||
// The test relies on TryCopyAndConvertArrayToCppBuffer that fails with
|
||||
// --force-slow-path.
|
||||
// Flags: --no-force-slow-path
|
||||
|
||||
d8.file.execute('test/mjsunit/compiler/fast-api-helpers.js');
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user