diff options
Diffstat (limited to 'REVERT-use-v8-Array-Iterate-for-converting-script-wrappables.patch')
-rw-r--r-- | REVERT-use-v8-Array-Iterate-for-converting-script-wrappables.patch | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/REVERT-use-v8-Array-Iterate-for-converting-script-wrappables.patch b/REVERT-use-v8-Array-Iterate-for-converting-script-wrappables.patch new file mode 100644 index 000000000000..8db4a848aed4 --- /dev/null +++ b/REVERT-use-v8-Array-Iterate-for-converting-script-wrappables.patch @@ -0,0 +1,174 @@ +From ce71348a09f6689dd01a68db64b172191d0182d8 Mon Sep 17 00:00:00 2001 +From: Andrey Kosyakov <caseq@chromium.org> +Date: Thu, 21 Dec 2023 18:38:38 +0000 +Subject: [PATCH] [bindings] Use v8::Array::Iterate for converting script + wrappables + +This changes CreateIDLSequenceFromV8Array to use the new +v8::Array::Iterate() operation. +This speeds up the "execBundles" part of the microbenchmark +at crbug.com/dawn/1858 by around 3x. +This depends on crrev.com/c/4846594 landing (and rolling) first. + +This is a slight re-work of https://crrev.com/c/4847447/3, +originally by jkummerow@chromium.org + +Bug: v8:14218, dawn:1858, 1511239 +Change-Id: Ia266556d05b4d53e6942e12609d1c08882b4ff0f +Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5132129 +Commit-Queue: Andrey Kosyakov <caseq@chromium.org> +Reviewed-by: Yuki Shiino <yukishiino@chromium.org> +Cr-Commit-Position: refs/heads/main@{#1240236} +--- + .../bindings/core/v8/native_value_traits.h | 6 ++ + .../core/v8/native_value_traits_impl.h | 91 ++++++++++++++++++- + 2 files changed, 95 insertions(+), 2 deletions(-) + +diff --git a/third_party/blink/renderer/bindings/core/v8/native_value_traits.h b/third_party/blink/renderer/bindings/core/v8/native_value_traits.h +index 1e5a0790df6d..a5c28b37e945 100644 +--- a/third_party/blink/renderer/bindings/core/v8/native_value_traits.h ++++ b/third_party/blink/renderer/bindings/core/v8/native_value_traits.h +@@ -84,6 +84,12 @@ struct NativeValueTraitsBase { + std::is_pointer_v<ImplType> || + requires(ImplType value) { value.IsNull(); }; + ++ // This should only be true for certain subclasses of ScriptWrappable ++ // that satisfy the assumptions of CreateIDLSequenceFromV8ArraySlow() with ++ // regards to how NativeValue() is implemented for the underlying type. ++ static constexpr bool supports_scriptwrappable_specific_fast_array_iteration = ++ false; ++ + template <typename... ExtraArgs> + static decltype(auto) ArgumentValue(v8::Isolate* isolate, + int argument_index, +diff --git a/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h b/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h +index 5011503dcf1c..f085b6e90516 100644 +--- a/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h ++++ b/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h +@@ -1037,10 +1037,86 @@ CreateIDLSequenceFromV8ArraySlow(v8::Isolate* isolate, + return {}; + } + +- typename NativeValueTraits<IDLSequence<T>>::ImplType result; ++ using ResultType = typename NativeValueTraits<IDLSequence<T>>::ImplType; ++ ResultType result; + result.ReserveInitialCapacity(length); + v8::Local<v8::Context> current_context = isolate->GetCurrentContext(); + v8::TryCatch try_block(isolate); ++ ++ // Fast path -- we're creating a sequence of script wrappables, which can be ++ // done by directly getting underlying object as long as array types are ++ // homogeneous. With ScriptWrappables, we don't expect to enter JS during ++ // iteration, so we can rely on v8::Array::Iterate() which is much faster than ++ // iterating an array on the client side of the v8. Additionally, for most ++ // subsptyes of ScriptWrappables, we can speed up type checks (see more on ++ // that below next to supports_scriptwrappable_specific_fast_array_iteration ++ // check. ++ if constexpr (std::is_base_of_v<ScriptWrappable, T>) { ++ struct CallbackData { ++ STACK_ALLOCATED(); ++ ++ public: ++ v8::Isolate* isolate; ++ v8::TypecheckWitness witness; ++ ResultType& result; ++ ExceptionState& exception_state; ++ CallbackData(v8::Isolate* isolate, ++ ResultType& result, ++ ExceptionState& exception_state) ++ : isolate(isolate), ++ witness(isolate), ++ result(result), ++ exception_state(exception_state) {} ++ }; ++ ++ CallbackData callback_data(isolate, result, exception_state); ++ v8::Array::IterationCallback callback = [](uint32_t index, ++ v8::Local<v8::Value> v8_element, ++ void* data) { ++ CallbackData* callback_data = reinterpret_cast<CallbackData*>(data); ++ // 3.4. Initialize Si to the result of converting nextItem to an IDL value ++ // of type T. ++ v8::TypecheckWitness& witness = callback_data->witness; ++ // We can speed up type check by taking advantage of V8's type witness, ++ // provided traits' NativeValue implementation doesn't have additional ++ // logic beyond checking the type and calling ToScriptWrappable(). ++ if constexpr ( ++ NativeValueTraits< ++ T>::supports_scriptwrappable_specific_fast_array_iteration) { ++ if (witness.Matches(v8_element)) { ++ auto&& value = ToScriptWrappable(v8_element.As<v8::Object>()) ++ ->template ToImpl<T>(); ++ callback_data->result.push_back(std::move(value)); ++ return v8::Array::CallbackResult::kContinue; ++ } ++ } ++ auto&& element = NativeValueTraits<T>::NativeValue( ++ callback_data->isolate, v8_element, callback_data->exception_state); ++ if (callback_data->exception_state.HadException()) { ++ // It doesn't matter whether we return `kException` or `kBreak` here, ++ // as that only affects the return value of `v8_array->Iterate()`, ++ // which we are ignoring. ++ return v8::Array::CallbackResult::kException; ++ } ++ if constexpr ( ++ NativeValueTraits< ++ T>::supports_scriptwrappable_specific_fast_array_iteration) { ++ witness.Update(v8_element); ++ } ++ callback_data->result.push_back(std::move(element)); ++ return v8::Array::CallbackResult::kContinue; ++ }; ++ if (!v8_array->Iterate(current_context, callback, &callback_data) ++ .IsJust()) { ++ if (try_block.HasCaught()) { ++ exception_state.RethrowV8Exception(try_block.Exception()); ++ } ++ DCHECK(exception_state.HadException()); ++ return {}; ++ } ++ return result; ++ } ++ + // Array length may change if array is mutated during iteration. + for (uint32_t i = 0; i < v8_array->Length(); ++i) { + v8::Local<v8::Value> v8_element; +@@ -1056,6 +1132,7 @@ CreateIDLSequenceFromV8ArraySlow(v8::Isolate* isolate, + return {}; + result.push_back(std::move(element)); + } ++ + // 3.2. If next is false, then return an IDL sequence value of type + // sequence<T> of length i, where the value of the element at index j is Sj. + return result; +@@ -1398,6 +1475,7 @@ struct NativeValueTraits<T> : public NativeValueTraitsBase<T*> { + } + }; + ++// Interface types + template <typename T> + requires std::derived_from<T, CallbackInterfaceBase> + struct NativeValueTraits<IDLNullable<T>> +@@ -1470,12 +1548,21 @@ struct NativeValueTraits<T> : public NativeValueTraitsBase<T> { + template <typename T> + requires std::derived_from<T, ScriptWrappable> + struct NativeValueTraits<T> : public NativeValueTraitsBase<T*> { ++ // This signifies that CreateIDLSequenceFromV8ArraySlow() may apply ++ // certain optimization based on assumptions about `NativeValue()` ++ // implementation below. For subclasses of ScriptWrappable that have ++ // different implementation of NativeValue(), this should remain false. ++ static constexpr bool supports_scriptwrappable_specific_fast_array_iteration = ++ true; ++ + static inline T* NativeValue(v8::Isolate* isolate, + v8::Local<v8::Value> value, + ExceptionState& exception_state) { + const WrapperTypeInfo* wrapper_type_info = T::GetStaticWrapperTypeInfo(); +- if (V8PerIsolateData::From(isolate)->HasInstance(wrapper_type_info, value)) ++ if (V8PerIsolateData::From(isolate)->HasInstance(wrapper_type_info, ++ value)) { + return ToScriptWrappable(value.As<v8::Object>())->template ToImpl<T>(); ++ } + + bindings::NativeValueTraitsInterfaceNotOfType(wrapper_type_info, + exception_state); |