Commit 530fd795 authored by Paolo Severini's avatar Paolo Severini Committed by V8 LUCI CQ

[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: 's avatarCamillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Cr-Commit-Position: refs/heads/master@{#76016}
parent 3a44f269
...@@ -225,8 +225,9 @@ ...@@ -225,8 +225,9 @@
#include <tuple> #include <tuple>
#include <type_traits> #include <type_traits>
#include "v8.h" // NOLINT(build/include_directory) #include "v8-internal.h" // NOLINT(build/include_directory)
#include "v8config.h" // NOLINT(build/include_directory) #include "v8.h" // NOLINT(build/include_directory)
#include "v8config.h" // NOLINT(build/include_directory)
namespace v8 { namespace v8 {
...@@ -770,6 +771,10 @@ CFunction CFunction::ArgUnwrap<R (*)(Args...)>::Make(R (*func)(Args...)) { ...@@ -770,6 +771,10 @@ CFunction CFunction::ArgUnwrap<R (*)(Args...)>::Make(R (*func)(Args...)) {
using CFunctionBuilder = internal::CFunctionBuilder; 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 * Copies the contents of this JavaScript array to a C++ buffer with
* a given max_length. A CTypeInfo is passed as an argument, * a given max_length. A CTypeInfo is passed as an argument,
...@@ -783,8 +788,20 @@ using CFunctionBuilder = internal::CFunctionBuilder; ...@@ -783,8 +788,20 @@ using CFunctionBuilder = internal::CFunctionBuilder;
* returns true on success. `type_info` will be used for conversions. * returns true on success. `type_info` will be used for conversions.
*/ */
template <const CTypeInfo* type_info, typename T> template <const CTypeInfo* type_info, typename T>
bool CopyAndConvertArrayToCppBuffer(Local<Array> src, T* dst, bool V8_EXPORT TryCopyAndConvertArrayToCppBuffer(Local<Array> src, T* dst,
uint32_t max_length); 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 } // namespace v8
......
...@@ -15,9 +15,12 @@ ...@@ -15,9 +15,12 @@
namespace v8 { namespace v8 {
class Array;
class Context; class Context;
class Data; class Data;
class Isolate; class Isolate;
template <typename T>
class Local;
namespace internal { namespace internal {
...@@ -505,6 +508,15 @@ V8_INLINE void PerformCastCheck(T* data) { ...@@ -505,6 +508,15 @@ V8_INLINE void PerformCastCheck(T* data) {
class BackingStoreBase {}; class BackingStoreBase {};
} // namespace internal } // 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 } // namespace v8
#endif // INCLUDE_V8_INTERNAL_H_ #endif // INCLUDE_V8_INTERNAL_H_
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "src/api/api.h" #include "src/api/api.h"
#include "src/execution/interrupts-scope.h" #include "src/execution/interrupts-scope.h"
#include "src/execution/microtask-queue.h" #include "src/execution/microtask-queue.h"
#include "src/execution/protectors.h"
#include "src/handles/handles-inl.h" #include "src/handles/handles-inl.h"
#include "src/heap/heap-inl.h" #include "src/heap/heap-inl.h"
#include "src/objects/foreign-inl.h" #include "src/objects/foreign-inl.h"
...@@ -279,6 +280,10 @@ bool CopyAndConvertArrayToCppBuffer(Local<Array> src, T* dst, ...@@ -279,6 +280,10 @@ bool CopyAndConvertArrayToCppBuffer(Local<Array> src, T* dst,
i::DisallowGarbageCollection no_gc; i::DisallowGarbageCollection no_gc;
i::JSArray obj = *reinterpret_cast<i::JSArray*>(*src); i::JSArray obj = *reinterpret_cast<i::JSArray*>(*src);
if (obj.IterationHasObservableEffects()) {
// The array has a custom iterator.
return false;
}
i::FixedArrayBase elements = obj.elements(); i::FixedArrayBase elements = obj.elements();
switch (obj.GetElementsKind()) { switch (obj.GetElementsKind()) {
...@@ -294,6 +299,13 @@ bool CopyAndConvertArrayToCppBuffer(Local<Array> src, T* dst, ...@@ -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 { namespace internal {
Handle<Context> HandleScopeImplementer::LastEnteredContext() { Handle<Context> HandleScopeImplementer::LastEnteredContext() {
......
...@@ -10315,6 +10315,19 @@ bool ConvertDouble(double d) { ...@@ -10315,6 +10315,19 @@ bool ConvertDouble(double d) {
#undef CALLBACK_SETTER #undef CALLBACK_SETTER
} // 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
......
...@@ -119,8 +119,8 @@ class FastCApiObject { ...@@ -119,8 +119,8 @@ class FastCApiObject {
} }
Type buffer[1024]; Type buffer[1024];
bool result = bool result = TryCopyAndConvertArrayToCppBuffer<&type_info, Type>(
CopyAndConvertArrayToCppBuffer<&type_info, Type>(seq_arg, buffer, 1024); seq_arg, buffer, 1024);
if (!result) { if (!result) {
options.fallback = 1; options.fallback = 1;
return 0; return 0;
......
...@@ -1767,9 +1767,14 @@ bool Object::IterationHasObservableEffects() { ...@@ -1767,9 +1767,14 @@ bool Object::IterationHasObservableEffects() {
#endif #endif
// Check that we have the original ArrayPrototype. // 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; if (!array.map().prototype().IsJSObject()) return true;
JSObject array_proto = JSObject::cast(array.map().prototype()); 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 // Check that the ArrayPrototype hasn't been modified in a way that would
// affect iteration. // affect iteration.
......
...@@ -592,7 +592,7 @@ class Object : public TaggedImpl<HeapObjectReferenceType::STRONG, Address> { ...@@ -592,7 +592,7 @@ class Object : public TaggedImpl<HeapObjectReferenceType::STRONG, Address> {
// Returns true if the result of iterating over the object is the same // Returns true if the result of iterating over the object is the same
// (including observable effects) as simply accessing the properties between 0 // (including observable effects) as simply accessing the properties between 0
// and length. // and length.
bool IterationHasObservableEffects(); V8_EXPORT_PRIVATE bool IterationHasObservableEffects();
// TC39 "Dynamic Code Brand Checks" // TC39 "Dynamic Code Brand Checks"
bool IsCodeLike(Isolate* isolate) const; bool IsCodeLike(Isolate* isolate) const;
......
...@@ -11,6 +11,9 @@ ...@@ -11,6 +11,9 @@
// The test relies on optimizing/deoptimizing at predictable moments, so // The test relies on optimizing/deoptimizing at predictable moments, so
// it's not suitable for deoptimization fuzzing. // it's not suitable for deoptimization fuzzing.
// Flags: --deopt-every-n-times=0 // 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'); d8.file.execute('test/mjsunit/compiler/fast-api-helpers.js');
......
...@@ -11,6 +11,9 @@ ...@@ -11,6 +11,9 @@
// The test relies on optimizing/deoptimizing at predictable moments, so // The test relies on optimizing/deoptimizing at predictable moments, so
// it's not suitable for deoptimization fuzzing. // it's not suitable for deoptimization fuzzing.
// Flags: --deopt-every-n-times=0 // 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'); d8.file.execute('test/mjsunit/compiler/fast-api-helpers.js');
......
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