chore: bump chromium to 133.0.6920.0 (main) (#45055)
* chore: bump chromium in DEPS to 133.0.6902.0 * chore: bump chromium in DEPS to 133.0.6903.0 * chore: update patches * Update PdfViewer Save File Picker to use showSaveFilePicker. Refs6074308
* Code Health: Clean up stale MacWebContentsOcclusion Refs6078344
* Change RenderProcessHost::GetID to RenderProcessHost::GetDeprecatedID Refs6065543
* [WebRTC] Make WebRTC IP Handling policy a mojo enum Refs6063620
* chore: gen filenames.libcxx.gni * Remove allow_unsafe_buffers pragma in //printing Refs6092280
* refactor: to use ChildProcessId where possible Refs https://issues.chromium.org/issues/379869738 * [Win] Update TabletMode detection code Refs6003486
* chore: bump chromium in DEPS to 133.0.6905.0 * chore: update patches * Reland "Move global shortcut listener to //ui/base" Refs6099035
* [shared storage] Implement the batch `with_lock` option for response header Refs6072742
* chore: bump chromium in DEPS to 133.0.6907.0 * chore: bump chromium in DEPS to 133.0.6909.0 * chore: bump chromium in DEPS to 133.0.6911.0 * chore: bump chromium in DEPS to 133.0.6912.0 * chore: update patches * WebUI: Reveal hidden deps to ui/webui/resources. Refs6096291
* chore: bump chromium in DEPS to 133.0.6913.0 * chore: bump chromium in DEPS to 133.0.6915.0 * Code Health: Clean up stale base::Feature "AccessibilityTreeForViews" Refs6104174
Co-authored-by: David Sanders <dsanders11@ucsbalum.com> * fix: remove fastapitypedarray usage * chore: update patches * chore: script/gen-libc++-filenames.js * Code Health: Clean up stale base::Feature "WinRetrieveSuggestionsOnlyOnDemand" Refs6109477
* fix: empty suggestions with windows platform checker Amends the fix from https://github.com/electron/electron/pull/29690 since the feature flag is no longer available. We follow the same pattern as //chrome/browser/renderer_context_menu/spelling_menu_observer.cc to generate the suggestion list on demand when context menu action is invoked. Co-authored-by: David Sanders <dsanders11@ucsbalum.com> * fixup! fix: empty suggestions with windows platform checker * fixup! fix: empty suggestions with windows platform checker * revert: 6078344: Code Health: Clean up stale MacWebContentsOcclusion |6078344
* Revert "revert: 6078344: Code Health: Clean up stale MacWebContentsOcclusion |6078344
" This reverts commit 9cacda452ed5a072351e8f5a35b009d91843a08c. * chore: bump to 133.0.6920.0, update patches * Revert "6078344: Code Health: Clean up stale MacWebContentsOcclusion" Refs:6078344
* fixup! Update PdfViewer Save File Picker to use showSaveFilePicker. --------- Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> Co-authored-by: deepak1556 <hop2deep@gmail.com> Co-authored-by: David Sanders <dsanders11@ucsbalum.com> Co-authored-by: Keeley Hammond <khammond@slack-corp.com>
This commit is contained in:
parent
062d14e553
commit
7d05b78479
120 changed files with 1167 additions and 2629 deletions
|
@ -1,5 +1,2 @@
|
|||
chore_allow_customizing_microtask_policy_per_context.patch
|
||||
deps_add_v8_object_setinternalfieldfornodecore.patch
|
||||
revert_fastapi_add_support_for_attribute_setters.patch
|
||||
revert_fastapi_remove_dynamic_overload_resolution.patch
|
||||
revert_api_delete_deprecated_struct_fastapitypedarray.patch
|
||||
|
|
|
@ -46,10 +46,10 @@ index 3e57ae8efe33f326ef0e5d609c311d4be5b8afd6..dc521d39c2280dfc3217e97c1e413b2b
|
|||
V8_INLINE static void* GetAlignedPointerFromInternalField(
|
||||
const BasicTracedReference<Object>& object, int index) {
|
||||
diff --git a/src/api/api.cc b/src/api/api.cc
|
||||
index 311cd9f1c289c2c5aea234fab64ee200dd0c2a8d..af1f0f3ad6ad0f2f0e7cb0123f9cd1ad0d1c80cb 100644
|
||||
index c0ff2001df718c89bd1fdf06e95d51e56aa23f03..35ab90bc743acce711c5f499363e40e55bf2a0e1 100644
|
||||
--- a/src/api/api.cc
|
||||
+++ b/src/api/api.cc
|
||||
@@ -6471,14 +6471,33 @@ Local<Data> v8::Object::SlowGetInternalField(int index) {
|
||||
@@ -6487,14 +6487,33 @@ Local<Data> v8::Object::SlowGetInternalField(int index) {
|
||||
i::Cast<i::JSObject>(*obj)->GetEmbedderField(index), isolate));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,419 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: John Kleinschmidt <jkleinsc@electronjs.org>
|
||||
Date: Fri, 15 Nov 2024 10:49:33 -0500
|
||||
Subject: Revert "[api] Delete deprecated struct FastApiTypedArray"
|
||||
|
||||
Revert this until Node.js decides how to proceed and then pick up their fix.
|
||||
|
||||
Refs: https://github.com/nodejs/node/issues/55452
|
||||
Refs: https://chromium-review.googlesource.com/c/v8/v8/+/5956408
|
||||
Refs: https://chromium-review.googlesource.com/c/v8/v8/+/5982984
|
||||
|
||||
This reverts commit 35a6781f783f037404869f6c9ec22f147dba1c5e.
|
||||
|
||||
diff --git a/include/v8-fast-api-calls.h b/include/v8-fast-api-calls.h
|
||||
index 12ef5e4f7e66f1bfe2ff3f46ebfa8f47c86e313c..9796601c287c0bb83a2fd85f7735678219c2cd5d 100644
|
||||
--- a/include/v8-fast-api-calls.h
|
||||
+++ b/include/v8-fast-api-calls.h
|
||||
@@ -271,7 +271,7 @@ class CTypeInfo {
|
||||
enum class SequenceType : uint8_t {
|
||||
kScalar,
|
||||
kIsSequence, // sequence<T>
|
||||
- kIsTypedArray V8_DEPRECATED(
|
||||
+ kIsTypedArray V8_DEPRECATE_SOON(
|
||||
"TypedArrays are not supported directly anymore."),
|
||||
// is void
|
||||
kIsArrayBuffer // ArrayBuffer
|
||||
@@ -326,7 +326,7 @@ class CTypeInfo {
|
||||
Flags flags_;
|
||||
};
|
||||
|
||||
-struct V8_DEPRECATED(
|
||||
+struct V8_DEPRECATE_SOON(
|
||||
"With the removal of FastApiTypedArray this type is not needed "
|
||||
"anymore.") FastApiTypedArrayBase {
|
||||
public:
|
||||
@@ -339,6 +339,42 @@ struct V8_DEPRECATED(
|
||||
size_t length_ = 0;
|
||||
};
|
||||
|
||||
+template <typename T>
|
||||
+struct V8_DEPRECATE_SOON(
|
||||
+ "When an API function expects a TypedArray as a parameter, the type in the "
|
||||
+ "signature should be `v8::Local<v8::Value>` instead of "
|
||||
+ "FastApiTypedArray<>. The API function then has to type-check the "
|
||||
+ "parameter and convert it to a `v8::Local<v8::TypedArray` to access the "
|
||||
+ "data. In essence, the parameter should be handled the same as for a "
|
||||
+ "regular API call.") FastApiTypedArray : public FastApiTypedArrayBase {
|
||||
+ public:
|
||||
+ V8_INLINE T get(size_t index) const {
|
||||
+#ifdef DEBUG
|
||||
+ ValidateIndex(index);
|
||||
+#endif // DEBUG
|
||||
+ T tmp;
|
||||
+ memcpy(&tmp, static_cast<void*>(reinterpret_cast<T*>(data_) + index),
|
||||
+ sizeof(T));
|
||||
+ return tmp;
|
||||
+ }
|
||||
+
|
||||
+ bool getStorageIfAligned(T** elements) const {
|
||||
+ if (reinterpret_cast<uintptr_t>(data_) % alignof(T) != 0) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ *elements = reinterpret_cast<T*>(data_);
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ 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_;
|
||||
+};
|
||||
+
|
||||
struct V8_DEPRECATED("This API is dead within V8") FastApiArrayBufferView {
|
||||
void* data;
|
||||
size_t byte_length;
|
||||
@@ -664,6 +700,32 @@ PRIMITIVE_C_TYPES(DEFINE_TYPE_INFO_TRAITS)
|
||||
#undef PRIMITIVE_C_TYPES
|
||||
#undef ALL_C_TYPES
|
||||
|
||||
+#define SPECIALIZE_GET_TYPE_INFO_HELPER_FOR_TA(T, Enum) \
|
||||
+ template <> \
|
||||
+ struct V8_DEPRECATE_SOON( \
|
||||
+ "This struct is unnecessary now, because FastApiTypedArray has already " \
|
||||
+ "been deprecated as well") TypeInfoHelper<const FastApiTypedArray<T>&> { \
|
||||
+ static constexpr CTypeInfo::Flags Flags() { \
|
||||
+ return CTypeInfo::Flags::kNone; \
|
||||
+ } \
|
||||
+ \
|
||||
+ static constexpr CTypeInfo::Type Type() { return CTypeInfo::Type::Enum; } \
|
||||
+ static constexpr CTypeInfo::SequenceType SequenceType() { \
|
||||
+ return CTypeInfo::SequenceType::kIsTypedArray; \
|
||||
+ } \
|
||||
+ };
|
||||
+
|
||||
+#define TYPED_ARRAY_C_TYPES(V) \
|
||||
+ V(uint8_t, kUint8) \
|
||||
+ V(int32_t, kInt32) \
|
||||
+ V(uint32_t, kUint32) \
|
||||
+ V(int64_t, kInt64) \
|
||||
+ V(uint64_t, kUint64) \
|
||||
+ V(float, kFloat32) \
|
||||
+ V(double, kFloat64)
|
||||
+
|
||||
+TYPED_ARRAY_C_TYPES(SPECIALIZE_GET_TYPE_INFO_HELPER_FOR_TA)
|
||||
+
|
||||
#undef TYPED_ARRAY_C_TYPES
|
||||
|
||||
template <>
|
||||
diff --git a/src/compiler/turboshaft/fast-api-call-lowering-reducer.h b/src/compiler/turboshaft/fast-api-call-lowering-reducer.h
|
||||
index dc27e91ad0da93a5b68053f132f219f95f641ca1..38ba1110da3f77df4681ccb0ebcee78d1500fbd7 100644
|
||||
--- a/src/compiler/turboshaft/fast-api-call-lowering-reducer.h
|
||||
+++ b/src/compiler/turboshaft/fast-api-call-lowering-reducer.h
|
||||
@@ -188,8 +188,20 @@ class FastApiCallLoweringReducer : public Next {
|
||||
break;
|
||||
}
|
||||
START_ALLOW_USE_DEPRECATED()
|
||||
- case CTypeInfo::SequenceType::kIsTypedArray:
|
||||
- UNREACHABLE();
|
||||
+ case CTypeInfo::SequenceType::kIsTypedArray: {
|
||||
+ // Check that the value is a TypedArray with a type that matches the
|
||||
+ // type declared in the c-function.
|
||||
+ OpIndex stack_slot = AdaptFastCallTypedArrayArgument(
|
||||
+ argument,
|
||||
+ fast_api_call::GetTypedArrayElementsKind(
|
||||
+ resolution_result.element_type),
|
||||
+ next);
|
||||
+ OpIndex target_address = __ ExternalConstant(
|
||||
+ ExternalReference::Create(c_functions[func_index].address,
|
||||
+ ExternalReference::FAST_C_CALL));
|
||||
+ GOTO(done, target_address, stack_slot);
|
||||
+ break;
|
||||
+ }
|
||||
END_ALLOW_USE_DEPRECATED()
|
||||
|
||||
default: {
|
||||
@@ -328,8 +340,15 @@ class FastApiCallLoweringReducer : public Next {
|
||||
return __ AdaptLocalArgument(argument);
|
||||
}
|
||||
START_ALLOW_USE_DEPRECATED()
|
||||
- case CTypeInfo::SequenceType::kIsTypedArray:
|
||||
- UNREACHABLE();
|
||||
+ case CTypeInfo::SequenceType::kIsTypedArray: {
|
||||
+ // Check that the value is a HeapObject.
|
||||
+ GOTO_IF(__ ObjectIsSmi(argument), handle_error);
|
||||
+
|
||||
+ return AdaptFastCallTypedArrayArgument(
|
||||
+ argument,
|
||||
+ fast_api_call::GetTypedArrayElementsKind(arg_type.GetType()),
|
||||
+ handle_error);
|
||||
+ }
|
||||
END_ALLOW_USE_DEPRECATED()
|
||||
default: {
|
||||
UNREACHABLE();
|
||||
@@ -387,6 +406,94 @@ class FastApiCallLoweringReducer : public Next {
|
||||
}
|
||||
}
|
||||
|
||||
+ OpIndex AdaptFastCallTypedArrayArgument(V<HeapObject> argument,
|
||||
+ ElementsKind expected_elements_kind,
|
||||
+ Label<>& bailout) {
|
||||
+ V<Map> map = __ LoadMapField(argument);
|
||||
+ V<Word32> instance_type = __ LoadInstanceTypeField(map);
|
||||
+ GOTO_IF_NOT(LIKELY(__ Word32Equal(instance_type, JS_TYPED_ARRAY_TYPE)),
|
||||
+ bailout);
|
||||
+
|
||||
+ V<Word32> bitfield2 =
|
||||
+ __ template LoadField<Word32>(map, AccessBuilder::ForMapBitField2());
|
||||
+ V<Word32> kind = __ Word32ShiftRightLogical(
|
||||
+ __ Word32BitwiseAnd(bitfield2, Map::Bits2::ElementsKindBits::kMask),
|
||||
+ Map::Bits2::ElementsKindBits::kShift);
|
||||
+ GOTO_IF_NOT(LIKELY(__ Word32Equal(kind, expected_elements_kind)), bailout);
|
||||
+
|
||||
+ V<HeapObject> buffer = __ template LoadField<HeapObject>(
|
||||
+ argument, AccessBuilder::ForJSArrayBufferViewBuffer());
|
||||
+ V<Word32> buffer_bitfield = __ template LoadField<Word32>(
|
||||
+ buffer, AccessBuilder::ForJSArrayBufferBitField());
|
||||
+
|
||||
+ // Go to the slow path if the {buffer} was detached.
|
||||
+ GOTO_IF(UNLIKELY(__ Word32BitwiseAnd(buffer_bitfield,
|
||||
+ JSArrayBuffer::WasDetachedBit::kMask)),
|
||||
+ bailout);
|
||||
+
|
||||
+ // Go to the slow path if the {buffer} is shared.
|
||||
+ GOTO_IF(UNLIKELY(__ Word32BitwiseAnd(buffer_bitfield,
|
||||
+ JSArrayBuffer::IsSharedBit::kMask)),
|
||||
+ bailout);
|
||||
+
|
||||
+ // Unpack the store and length, and store them to a struct
|
||||
+ // FastApiTypedArray.
|
||||
+ OpIndex external_pointer =
|
||||
+ __ LoadField(argument, AccessBuilder::ForJSTypedArrayExternalPointer());
|
||||
+
|
||||
+ // Load the base pointer for the buffer. This will always be Smi
|
||||
+ // zero unless we allow on-heap TypedArrays, which is only the case
|
||||
+ // for Chrome. Node and Electron both set this limit to 0. Setting
|
||||
+ // the base to Smi zero here allows the BuildTypedArrayDataPointer
|
||||
+ // to optimize away the tricky part of the access later.
|
||||
+ V<WordPtr> data_ptr;
|
||||
+ if constexpr (JSTypedArray::kMaxSizeInHeap == 0) {
|
||||
+ data_ptr = external_pointer;
|
||||
+ } else {
|
||||
+ V<Object> base_pointer = __ template LoadField<Object>(
|
||||
+ argument, AccessBuilder::ForJSTypedArrayBasePointer());
|
||||
+ V<WordPtr> base = __ BitcastTaggedToWordPtr(base_pointer);
|
||||
+ if (COMPRESS_POINTERS_BOOL) {
|
||||
+ // Zero-extend Tagged_t to UintPtr according to current compression
|
||||
+ // scheme so that the addition with |external_pointer| (which already
|
||||
+ // contains compensated offset value) will decompress the tagged value.
|
||||
+ // See JSTypedArray::ExternalPointerCompensationForOnHeapArray() for
|
||||
+ // details.
|
||||
+ base = __ ChangeUint32ToUintPtr(__ TruncateWordPtrToWord32(base));
|
||||
+ }
|
||||
+ data_ptr = __ WordPtrAdd(base, external_pointer);
|
||||
+ }
|
||||
+
|
||||
+ V<WordPtr> length_in_bytes = __ template LoadField<WordPtr>(
|
||||
+ argument, AccessBuilder::ForJSTypedArrayLength());
|
||||
+
|
||||
+ // We hard-code int32_t here, because all specializations of
|
||||
+ // FastApiTypedArray have the same size.
|
||||
+ START_ALLOW_USE_DEPRECATED()
|
||||
+ constexpr int kAlign = alignof(FastApiTypedArray<int32_t>);
|
||||
+ constexpr int kSize = sizeof(FastApiTypedArray<int32_t>);
|
||||
+ static_assert(kAlign == alignof(FastApiTypedArray<double>),
|
||||
+ "Alignment mismatch between different specializations of "
|
||||
+ "FastApiTypedArray");
|
||||
+ static_assert(kSize == sizeof(FastApiTypedArray<double>),
|
||||
+ "Size mismatch between different specializations of "
|
||||
+ "FastApiTypedArray");
|
||||
+ END_ALLOW_USE_DEPRECATED()
|
||||
+ static_assert(
|
||||
+ kSize == sizeof(uintptr_t) + sizeof(size_t),
|
||||
+ "The size of "
|
||||
+ "FastApiTypedArray isn't equal to the sum of its expected members.");
|
||||
+ OpIndex stack_slot = __ StackSlot(kSize, kAlign);
|
||||
+ __ StoreOffHeap(stack_slot, length_in_bytes,
|
||||
+ MemoryRepresentation::UintPtr());
|
||||
+ __ StoreOffHeap(stack_slot, data_ptr, MemoryRepresentation::UintPtr(),
|
||||
+ sizeof(size_t));
|
||||
+ static_assert(sizeof(uintptr_t) == sizeof(size_t),
|
||||
+ "The buffer length can't "
|
||||
+ "fit the PointerRepresentation used to store it.");
|
||||
+ return stack_slot;
|
||||
+ }
|
||||
+
|
||||
V<Any> DefaultReturnValue(const CFunctionInfo* c_signature) {
|
||||
switch (c_signature->ReturnInfo().GetType()) {
|
||||
case CTypeInfo::Type::kVoid:
|
||||
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
|
||||
index 3898b51a1eab680c34102fea473f111cf8024b8b..0d6a0ef6516e25b2bb65b262b4d6495a268cd4d8 100644
|
||||
--- a/test/cctest/test-api.cc
|
||||
+++ b/test/cctest/test-api.cc
|
||||
@@ -29772,6 +29772,16 @@ static Trivial* UnwrapTrivialObject(Local<Object> object) {
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
+START_ALLOW_USE_DEPRECATED()
|
||||
+void FastCallback1TypedArray(v8::Local<v8::Object> receiver, int arg0,
|
||||
+ const v8::FastApiTypedArray<int32_t>& arg1) {
|
||||
+ Trivial* self = UnwrapTrivialObject(receiver);
|
||||
+ CHECK_NOT_NULL(self);
|
||||
+ CHECK_EQ(arg0, arg1.length());
|
||||
+ self->set_x(arg0);
|
||||
+}
|
||||
+END_ALLOW_USE_DEPRECATED()
|
||||
+
|
||||
void FastCallback2JSArray(v8::Local<v8::Object> receiver, int arg0,
|
||||
v8::Local<v8::Array> arg1) {
|
||||
Trivial* self = UnwrapTrivialObject(receiver);
|
||||
@@ -29789,10 +29799,103 @@ void FastCallback4Scalar(v8::Local<v8::Object> receiver, int arg0, float arg1) {
|
||||
void FastCallback5DifferentArity(v8::Local<v8::Object> receiver, int arg0,
|
||||
v8::Local<v8::Array> arg1, float arg2) {}
|
||||
|
||||
+void SequenceSlowCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
|
||||
+ CHECK(i::ValidateCallbackInfo(info));
|
||||
+ v8::Isolate* isolate = info.GetIsolate();
|
||||
+ Trivial* self = UnwrapTrivialObject(info.This());
|
||||
+ if (!self) {
|
||||
+ isolate->ThrowError("This method is not defined on the given receiver.");
|
||||
+ return;
|
||||
+ }
|
||||
+ self->set_x(1337);
|
||||
+
|
||||
+ HandleScope handle_scope(isolate);
|
||||
+
|
||||
+ if (info.Length() < 2 || !info[0]->IsNumber()) {
|
||||
+ isolate->ThrowError(
|
||||
+ "This method expects at least 2 arguments,"
|
||||
+ " first one a number.");
|
||||
+ return;
|
||||
+ }
|
||||
+ int64_t len = info[0]->IntegerValue(isolate->GetCurrentContext()).FromJust();
|
||||
+ if (info[1]->IsTypedArray()) {
|
||||
+ v8::Local<v8::TypedArray> typed_array_arg = info[1].As<v8::TypedArray>();
|
||||
+ size_t length = typed_array_arg->Length();
|
||||
+ CHECK_EQ(len, length);
|
||||
+ return;
|
||||
+ }
|
||||
+ if (!info[1]->IsArray()) {
|
||||
+ isolate->ThrowError("This method expects an array as a second argument.");
|
||||
+ return;
|
||||
+ }
|
||||
+ v8::Local<v8::Array> seq_arg = info[1].As<v8::Array>();
|
||||
+ uint32_t length = seq_arg->Length();
|
||||
+ CHECK_EQ(len, length);
|
||||
+ return;
|
||||
+}
|
||||
} // namespace
|
||||
#endif // !defined(V8_LITE_MODE) && defined(V8_ENABLE_TURBOFAN)
|
||||
|
||||
START_ALLOW_USE_DEPRECATED()
|
||||
+TEST(FastApiSequenceOverloads) {
|
||||
+#if !defined(V8_LITE_MODE) && defined(V8_ENABLE_TURBOFAN)
|
||||
+ if (i::v8_flags.jitless) return;
|
||||
+ if (i::v8_flags.disable_optimizing_compilers) return;
|
||||
+
|
||||
+ i::v8_flags.turbofan = true;
|
||||
+ i::v8_flags.turbo_fast_api_calls = true;
|
||||
+ i::v8_flags.allow_natives_syntax = true;
|
||||
+ // Disable --always_turbofan, otherwise we haven't generated the necessary
|
||||
+ // feedback to go down the "best optimization" path for the fast call.
|
||||
+ i::v8_flags.always_turbofan = false;
|
||||
+ i::FlagList::EnforceFlagImplications();
|
||||
+
|
||||
+ v8::Isolate* isolate = CcTest::isolate();
|
||||
+ HandleScope handle_scope(isolate);
|
||||
+ LocalContext env;
|
||||
+
|
||||
+ v8::CFunction typed_array_callback =
|
||||
+ v8::CFunctionBuilder().Fn(FastCallback1TypedArray).Build();
|
||||
+ v8::CFunction js_array_callback =
|
||||
+ v8::CFunctionBuilder().Fn(FastCallback2JSArray).Build();
|
||||
+ const v8::CFunction sequece_overloads[] = {
|
||||
+ typed_array_callback,
|
||||
+ js_array_callback,
|
||||
+ };
|
||||
+
|
||||
+ Local<v8::FunctionTemplate> sequence_callback_templ =
|
||||
+ v8::FunctionTemplate::NewWithCFunctionOverloads(
|
||||
+ isolate, SequenceSlowCallback, v8::Number::New(isolate, 42),
|
||||
+ v8::Local<v8::Signature>(), 1, v8::ConstructorBehavior::kThrow,
|
||||
+ v8::SideEffectType::kHasSideEffect, {sequece_overloads, 2});
|
||||
+
|
||||
+ v8::Local<v8::ObjectTemplate> object_template =
|
||||
+ v8::ObjectTemplate::New(isolate);
|
||||
+ object_template->SetInternalFieldCount(kV8WrapperObjectIndex + 1);
|
||||
+ object_template->Set(isolate, "api_func", sequence_callback_templ);
|
||||
+
|
||||
+ std::unique_ptr<Trivial> rcv(new Trivial(42));
|
||||
+ v8::Local<v8::Object> object =
|
||||
+ object_template->NewInstance(env.local()).ToLocalChecked();
|
||||
+ object->SetAlignedPointerInInternalField(kV8WrapperObjectIndex, rcv.get());
|
||||
+
|
||||
+ CHECK(
|
||||
+ (env)->Global()->Set(env.local(), v8_str("receiver"), object).FromJust());
|
||||
+ USE(CompileRun(
|
||||
+ "function func(num, arr) { return receiver.api_func(num, arr); }"
|
||||
+ "%PrepareFunctionForOptimization(func);"
|
||||
+ "func(3, [1,2,3]);"
|
||||
+ "%OptimizeFunctionOnNextCall(func);"
|
||||
+ "func(3, [1,2,3]);"));
|
||||
+ CHECK_EQ(3, rcv->x());
|
||||
+
|
||||
+ USE(
|
||||
+ CompileRun("const ta = new Int32Array([1, 2, 3, 4]);"
|
||||
+ "func(4, ta);"));
|
||||
+ CHECK_EQ(4, rcv->x());
|
||||
+#endif // !defined(V8_LITE_MODE) && defined(V8_ENABLE_TURBOFAN)
|
||||
+}
|
||||
+
|
||||
TEST(FastApiOverloadResolution) {
|
||||
#if !defined(V8_LITE_MODE) && defined(V8_ENABLE_TURBOFAN)
|
||||
if (i::v8_flags.jitless) return;
|
||||
@@ -29806,15 +29909,22 @@ TEST(FastApiOverloadResolution) {
|
||||
i::v8_flags.always_turbofan = false;
|
||||
i::FlagList::EnforceFlagImplications();
|
||||
|
||||
+ v8::CFunction typed_array_callback =
|
||||
+ v8::CFunctionBuilder().Fn(FastCallback1TypedArray).Build();
|
||||
v8::CFunction js_array_callback =
|
||||
v8::CFunctionBuilder().Fn(FastCallback2JSArray).Build();
|
||||
|
||||
+ // Check that a general runtime overload resolution is possible.
|
||||
+ CHECK_EQ(v8::CFunction::OverloadResolution::kAtRuntime,
|
||||
+ typed_array_callback.GetOverloadResolution(&js_array_callback));
|
||||
+
|
||||
v8::CFunction swapped_params_callback =
|
||||
v8::CFunctionBuilder().Fn(FastCallback3SwappedParams).Build();
|
||||
|
||||
// Check that difference in > 1 position is not possible.
|
||||
- CHECK_EQ(v8::CFunction::OverloadResolution::kImpossible,
|
||||
- js_array_callback.GetOverloadResolution(&swapped_params_callback));
|
||||
+ CHECK_EQ(
|
||||
+ v8::CFunction::OverloadResolution::kImpossible,
|
||||
+ typed_array_callback.GetOverloadResolution(&swapped_params_callback));
|
||||
|
||||
v8::CFunction scalar_callback =
|
||||
v8::CFunctionBuilder().Fn(FastCallback4Scalar).Build();
|
||||
@@ -29822,7 +29932,7 @@ TEST(FastApiOverloadResolution) {
|
||||
// Check that resolving when there is a scalar at the difference position
|
||||
// is not possible.
|
||||
CHECK_EQ(v8::CFunction::OverloadResolution::kImpossible,
|
||||
- js_array_callback.GetOverloadResolution(&scalar_callback));
|
||||
+ typed_array_callback.GetOverloadResolution(&scalar_callback));
|
||||
|
||||
v8::CFunction diff_arity_callback =
|
||||
v8::CFunctionBuilder().Fn(FastCallback5DifferentArity).Build();
|
||||
@@ -29830,7 +29940,7 @@ TEST(FastApiOverloadResolution) {
|
||||
// Check that overload resolution between different number of arguments
|
||||
// is possible.
|
||||
CHECK_EQ(v8::CFunction::OverloadResolution::kAtCompileTime,
|
||||
- js_array_callback.GetOverloadResolution(&diff_arity_callback));
|
||||
+ typed_array_callback.GetOverloadResolution(&diff_arity_callback));
|
||||
|
||||
#endif // !defined(V8_LITE_MODE) && defined(V8_ENABLE_TURBOFAN)
|
||||
}
|
|
@ -1,525 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Calvin Watford <cwatford@slack-corp.com>
|
||||
Date: Tue, 26 Nov 2024 16:06:53 -0700
|
||||
Subject: Revert "[fastapi] Add support for attribute setters"
|
||||
|
||||
Revert this until Node.js decides how to proceed and then pick up their fix.
|
||||
|
||||
Refs: https://github.com/nodejs/node/issues/55452
|
||||
Refs: https://chromium-review.googlesource.com/c/v8/v8/+/5956408
|
||||
Refs: https://chromium-review.googlesource.com/c/v8/v8/+/5982984
|
||||
Refs: https://chromium-review.googlesource.com/c/v8/v8/+/5979766
|
||||
Refs: https://chromium-review.googlesource.com/c/v8/v8/+/6023139
|
||||
|
||||
This reverts commit 6520094871895fbafe91403ceb700ff97fdfd413.
|
||||
|
||||
diff --git a/src/compiler/fast-api-calls.cc b/src/compiler/fast-api-calls.cc
|
||||
index 5da23c3d55bc105ed380762dd515f8856cbe5933..2dc99dc83e0f78d2bbb0875cc04064b565deaf06 100644
|
||||
--- a/src/compiler/fast-api-calls.cc
|
||||
+++ b/src/compiler/fast-api-calls.cc
|
||||
@@ -379,46 +379,6 @@ Node* BuildFastApiCall(Isolate* isolate, Graph* graph,
|
||||
return builder.Build(c_function, data_argument);
|
||||
}
|
||||
|
||||
-FastApiCallFunction GetFastApiCallTarget(
|
||||
- JSHeapBroker* broker, FunctionTemplateInfoRef function_template_info,
|
||||
- size_t arg_count) {
|
||||
- if (!v8_flags.turbo_fast_api_calls) return {0, nullptr};
|
||||
-
|
||||
- static constexpr int kReceiver = 1;
|
||||
-
|
||||
- const ZoneVector<const CFunctionInfo*>& signatures =
|
||||
- function_template_info.c_signatures(broker);
|
||||
- const size_t overloads_count = signatures.size();
|
||||
-
|
||||
- // Only considers entries whose type list length matches arg_count.
|
||||
- for (size_t i = 0; i < overloads_count; i++) {
|
||||
- const CFunctionInfo* c_signature = signatures[i];
|
||||
- const size_t len = c_signature->ArgumentCount() - kReceiver;
|
||||
- bool optimize_to_fast_call =
|
||||
- (len == arg_count) &&
|
||||
- fast_api_call::CanOptimizeFastSignature(c_signature);
|
||||
-
|
||||
- if (optimize_to_fast_call) {
|
||||
- // TODO(nicohartmann@): {Flags::kEnforceRangeBit} is currently only
|
||||
- // supported on 64 bit architectures. We should support this on 32 bit
|
||||
- // architectures.
|
||||
-#if defined(V8_TARGET_ARCH_32_BIT)
|
||||
- for (unsigned int i = 0; i < c_signature->ArgumentCount(); ++i) {
|
||||
- const uint8_t flags =
|
||||
- static_cast<uint8_t>(c_signature->ArgumentInfo(i).GetFlags());
|
||||
- if (flags & static_cast<uint8_t>(CTypeInfo::Flags::kEnforceRangeBit)) {
|
||||
- // Bailout
|
||||
- return {0, nullptr};
|
||||
- }
|
||||
- }
|
||||
-#endif
|
||||
- return {function_template_info.c_functions(broker)[i], c_signature};
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- return {0, nullptr};
|
||||
-}
|
||||
-
|
||||
} // namespace fast_api_call
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
diff --git a/src/compiler/fast-api-calls.h b/src/compiler/fast-api-calls.h
|
||||
index b49322d91d06b7fed34fe41b6ac7d31dcc7783c4..171e66c427991bfe7db5c2875d12559767a24b55 100644
|
||||
--- a/src/compiler/fast-api-calls.h
|
||||
+++ b/src/compiler/fast-api-calls.h
|
||||
@@ -55,10 +55,6 @@ Node* BuildFastApiCall(Isolate* isolate, Graph* graph,
|
||||
const InitializeOptions& initialize_options,
|
||||
const GenerateSlowApiCall& generate_slow_api_call);
|
||||
|
||||
-FastApiCallFunction GetFastApiCallTarget(
|
||||
- JSHeapBroker* broker, FunctionTemplateInfoRef function_template_info,
|
||||
- size_t arg_count);
|
||||
-
|
||||
} // namespace fast_api_call
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
diff --git a/src/compiler/js-call-reducer.cc b/src/compiler/js-call-reducer.cc
|
||||
index 48663a4fcc284b7d832849e0c467019b384a31ff..d75a38769d582cd6e5a807f9670732dc92d77b7e 100644
|
||||
--- a/src/compiler/js-call-reducer.cc
|
||||
+++ b/src/compiler/js-call-reducer.cc
|
||||
@@ -3877,6 +3877,58 @@ Reduction JSCallReducer::ReduceCallWasmFunction(Node* node,
|
||||
}
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
|
||||
+// 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
|
||||
+// arguments of size arg_count:
|
||||
+// 1. Remove from the set all entries whose type list is not of length
|
||||
+// arg_count.
|
||||
+// Returns an array with the indexes of the remaining entries in S, which
|
||||
+// represents the set of "optimizable" function overloads.
|
||||
+
|
||||
+FastApiCallFunction GetFastApiCallTarget(
|
||||
+ JSHeapBroker* broker, FunctionTemplateInfoRef function_template_info,
|
||||
+ size_t arg_count) {
|
||||
+ if (!v8_flags.turbo_fast_api_calls) return {0, nullptr};
|
||||
+
|
||||
+ static constexpr int kReceiver = 1;
|
||||
+
|
||||
+ ZoneVector<Address> functions = function_template_info.c_functions(broker);
|
||||
+ ZoneVector<const CFunctionInfo*> signatures =
|
||||
+ function_template_info.c_signatures(broker);
|
||||
+ const size_t overloads_count = signatures.size();
|
||||
+
|
||||
+ // Only considers entries whose type list length matches arg_count.
|
||||
+ for (size_t i = 0; i < overloads_count; i++) {
|
||||
+ const CFunctionInfo* c_signature = signatures[i];
|
||||
+ const size_t len = c_signature->ArgumentCount() - kReceiver;
|
||||
+ bool optimize_to_fast_call = (len == arg_count);
|
||||
+
|
||||
+ optimize_to_fast_call =
|
||||
+ optimize_to_fast_call &&
|
||||
+ fast_api_call::CanOptimizeFastSignature(c_signature);
|
||||
+
|
||||
+ if (optimize_to_fast_call) {
|
||||
+ // TODO(nicohartmann@): {Flags::kEnforceRangeBit} is currently only
|
||||
+ // supported on 64 bit architectures. We should support this on 32 bit
|
||||
+ // architectures.
|
||||
+#if defined(V8_TARGET_ARCH_32_BIT)
|
||||
+ for (unsigned int i = 0; i < c_signature->ArgumentCount(); ++i) {
|
||||
+ const uint8_t flags =
|
||||
+ static_cast<uint8_t>(c_signature->ArgumentInfo(i).GetFlags());
|
||||
+ if (flags & static_cast<uint8_t>(CTypeInfo::Flags::kEnforceRangeBit)) {
|
||||
+ // Bailout
|
||||
+ return {0, nullptr};
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
+ return {functions[i], c_signature};
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return {0, nullptr};
|
||||
+}
|
||||
+
|
||||
Reduction JSCallReducer::ReduceCallApiFunction(Node* node,
|
||||
SharedFunctionInfoRef shared) {
|
||||
JSCallNode n(node);
|
||||
@@ -4057,8 +4109,8 @@ Reduction JSCallReducer::ReduceCallApiFunction(Node* node,
|
||||
}
|
||||
|
||||
// Handles overloaded functions.
|
||||
- FastApiCallFunction c_function = fast_api_call::GetFastApiCallTarget(
|
||||
- broker(), function_template_info, argc);
|
||||
+ FastApiCallFunction c_function =
|
||||
+ GetFastApiCallTarget(broker(), function_template_info, argc);
|
||||
|
||||
if (c_function.address) {
|
||||
FastApiCallReducerAssembler a(this, node, function_template_info,
|
||||
diff --git a/src/compiler/js-native-context-specialization.cc b/src/compiler/js-native-context-specialization.cc
|
||||
index 5b9a78e7a9a728842148eebe733501174c0c94a1..95c44eb81f9eba481b7c795d0a8becb1aa757a90 100644
|
||||
--- a/src/compiler/js-native-context-specialization.cc
|
||||
+++ b/src/compiler/js-native-context-specialization.cc
|
||||
@@ -16,7 +16,6 @@
|
||||
#include "src/compiler/allocation-builder.h"
|
||||
#include "src/compiler/common-operator.h"
|
||||
#include "src/compiler/compilation-dependencies.h"
|
||||
-#include "src/compiler/fast-api-calls.h"
|
||||
#include "src/compiler/frame-states.h"
|
||||
#include "src/compiler/graph-assembler.h"
|
||||
#include "src/compiler/js-graph.h"
|
||||
@@ -1463,7 +1462,7 @@ Reduction JSNativeContextSpecialization::ReduceMegaDOMPropertyAccess(
|
||||
|
||||
value = InlineApiCall(lookup_start_object, lookup_start_object, frame_state,
|
||||
nullptr /*value*/, &effect, &control,
|
||||
- function_template_info, source);
|
||||
+ function_template_info);
|
||||
ReplaceWithValue(node, value, effect, control);
|
||||
return Replace(value);
|
||||
}
|
||||
@@ -2835,8 +2834,7 @@ Node* JSNativeContextSpecialization::InlinePropertyGetterCall(
|
||||
access_info.api_holder().value(), broker())
|
||||
: receiver;
|
||||
value = InlineApiCall(receiver, api_holder, frame_state, nullptr, effect,
|
||||
- control, constant.AsFunctionTemplateInfo(),
|
||||
- FeedbackSource());
|
||||
+ control, constant.AsFunctionTemplateInfo());
|
||||
}
|
||||
// Remember to rewire the IfException edge if this is inside a try-block.
|
||||
if (if_exceptions != nullptr) {
|
||||
@@ -2871,7 +2869,7 @@ void JSNativeContextSpecialization::InlinePropertySetterCall(
|
||||
access_info.api_holder().value(), broker())
|
||||
: receiver;
|
||||
InlineApiCall(receiver, api_holder, frame_state, value, effect, control,
|
||||
- constant.AsFunctionTemplateInfo(), FeedbackSource());
|
||||
+ constant.AsFunctionTemplateInfo());
|
||||
}
|
||||
// Remember to rewire the IfException edge if this is inside a try-block.
|
||||
if (if_exceptions != nullptr) {
|
||||
@@ -2884,66 +2882,10 @@ void JSNativeContextSpecialization::InlinePropertySetterCall(
|
||||
}
|
||||
}
|
||||
|
||||
-namespace {
|
||||
-CallDescriptor* PushRegularApiCallInputs(
|
||||
- JSGraph* jsgraph, JSHeapBroker* broker, Node* receiver, Node* api_holder,
|
||||
- Node* frame_state, Node* value, Node** effect, Node** control,
|
||||
- FunctionTemplateInfoRef function_template_info, Node** inputs,
|
||||
- int& cursor) {
|
||||
- // Only setters have a value.
|
||||
- int const argc = value == nullptr ? 0 : 1;
|
||||
-
|
||||
- // The builtin always expects the receiver as the first param on the stack.
|
||||
- bool no_profiling = broker->dependencies()->DependOnNoProfilingProtector();
|
||||
- Callable call_api_callback = Builtins::CallableFor(
|
||||
- jsgraph->isolate(), no_profiling
|
||||
- ? Builtin::kCallApiCallbackOptimizedNoProfiling
|
||||
- : Builtin::kCallApiCallbackOptimized);
|
||||
-
|
||||
- Node* func_templ =
|
||||
- jsgraph->HeapConstantNoHole(function_template_info.object());
|
||||
- ApiFunction function(function_template_info.callback(broker));
|
||||
- Node* function_reference = jsgraph->graph()->NewNode(
|
||||
- jsgraph->common()->ExternalConstant(ExternalReference::Create(
|
||||
- jsgraph->isolate(), &function, ExternalReference::DIRECT_API_CALL,
|
||||
- function_template_info.c_functions(broker).data(),
|
||||
- function_template_info.c_signatures(broker).data(),
|
||||
- static_cast<uint32_t>(
|
||||
- function_template_info.c_functions(broker).size()))));
|
||||
- Node* code = jsgraph->HeapConstantNoHole(call_api_callback.code());
|
||||
-
|
||||
- // Add CallApiCallbackStub's register argument as well.
|
||||
- Node* context =
|
||||
- jsgraph->ConstantNoHole(broker->target_native_context(), broker);
|
||||
- inputs[cursor++] = code;
|
||||
- inputs[cursor++] = function_reference;
|
||||
- inputs[cursor++] = jsgraph->ConstantNoHole(argc);
|
||||
- inputs[cursor++] = func_templ;
|
||||
- inputs[cursor++] = api_holder;
|
||||
- inputs[cursor++] = receiver;
|
||||
- if (value) {
|
||||
- inputs[cursor++] = value;
|
||||
- }
|
||||
- inputs[cursor++] = context;
|
||||
- inputs[cursor++] = frame_state;
|
||||
- inputs[cursor++] = *effect;
|
||||
- inputs[cursor++] = *control;
|
||||
-
|
||||
- CallInterfaceDescriptor call_interface_descriptor =
|
||||
- call_api_callback.descriptor();
|
||||
- return Linkage::GetStubCallDescriptor(
|
||||
- jsgraph->zone(), call_interface_descriptor,
|
||||
- call_interface_descriptor.GetStackParameterCount() + argc +
|
||||
- 1 /* implicit receiver */,
|
||||
- CallDescriptor::kNeedsFrameState);
|
||||
-}
|
||||
-} // namespace
|
||||
-
|
||||
Node* JSNativeContextSpecialization::InlineApiCall(
|
||||
Node* receiver, Node* api_holder, Node* frame_state, Node* value,
|
||||
Node** effect, Node** control,
|
||||
- FunctionTemplateInfoRef function_template_info,
|
||||
- const FeedbackSource& feedback) {
|
||||
+ FunctionTemplateInfoRef function_template_info) {
|
||||
compiler::OptionalObjectRef maybe_callback_data =
|
||||
function_template_info.callback_data(broker());
|
||||
// Check if the function has an associated C++ code to execute.
|
||||
@@ -2957,44 +2899,45 @@ Node* JSNativeContextSpecialization::InlineApiCall(
|
||||
|
||||
// Only setters have a value.
|
||||
int const argc = value == nullptr ? 0 : 1;
|
||||
+ // The builtin always expects the receiver as the first param on the stack.
|
||||
+ bool no_profiling = broker()->dependencies()->DependOnNoProfilingProtector();
|
||||
+ Callable call_api_callback = Builtins::CallableFor(
|
||||
+ isolate(), no_profiling ? Builtin::kCallApiCallbackOptimizedNoProfiling
|
||||
+ : Builtin::kCallApiCallbackOptimized);
|
||||
+ CallInterfaceDescriptor call_interface_descriptor =
|
||||
+ call_api_callback.descriptor();
|
||||
+ auto call_descriptor = Linkage::GetStubCallDescriptor(
|
||||
+ graph()->zone(), call_interface_descriptor,
|
||||
+ call_interface_descriptor.GetStackParameterCount() + argc +
|
||||
+ 1 /* implicit receiver */,
|
||||
+ CallDescriptor::kNeedsFrameState);
|
||||
|
||||
- // Handles overloaded functions.
|
||||
- FastApiCallFunction c_function = fast_api_call::GetFastApiCallTarget(
|
||||
- broker(), function_template_info, argc);
|
||||
-
|
||||
- if (c_function.address) {
|
||||
- const int input_count = 14;
|
||||
- Node* inputs[input_count];
|
||||
-
|
||||
- int cursor = 0;
|
||||
- inputs[cursor++] = receiver;
|
||||
- if (value) {
|
||||
- inputs[cursor++] = value;
|
||||
- }
|
||||
- inputs[cursor++] =
|
||||
- jsgraph()->ConstantNoHole(maybe_callback_data.value(), broker());
|
||||
-
|
||||
- auto call_descriptor = PushRegularApiCallInputs(
|
||||
- jsgraph(), broker(), receiver, api_holder, frame_state, value, effect,
|
||||
- control, function_template_info, inputs, cursor);
|
||||
-
|
||||
- // The input_count is constant, but getters have less parameters than
|
||||
- // setters.
|
||||
- DCHECK_LE(cursor, input_count);
|
||||
+ Node* func_templ =
|
||||
+ jsgraph()->HeapConstantNoHole(function_template_info.object());
|
||||
+ ApiFunction function(function_template_info.callback(broker()));
|
||||
+ Node* function_reference =
|
||||
+ graph()->NewNode(common()->ExternalConstant(ExternalReference::Create(
|
||||
+ &function, ExternalReference::DIRECT_API_CALL)));
|
||||
+ Node* code = jsgraph()->HeapConstantNoHole(call_api_callback.code());
|
||||
|
||||
- return *effect = *control = graph()->NewNode(
|
||||
- simplified()->FastApiCall(c_function, feedback, call_descriptor),
|
||||
- cursor, inputs);
|
||||
+ // Add CallApiCallbackStub's register argument as well.
|
||||
+ Node* context = jsgraph()->ConstantNoHole(native_context(), broker());
|
||||
+ Node* inputs[11] = {
|
||||
+ code, function_reference, jsgraph()->ConstantNoHole(argc),
|
||||
+ func_templ, api_holder, receiver};
|
||||
+ int index = 6 + argc;
|
||||
+ inputs[index++] = context;
|
||||
+ inputs[index++] = frame_state;
|
||||
+ inputs[index++] = *effect;
|
||||
+ inputs[index++] = *control;
|
||||
+ // This needs to stay here because of the edge case described in
|
||||
+ // http://crbug.com/675648.
|
||||
+ if (value != nullptr) {
|
||||
+ inputs[6] = value;
|
||||
}
|
||||
|
||||
- Node* inputs[11];
|
||||
- int cursor = 0;
|
||||
- CallDescriptor* call_descriptor = PushRegularApiCallInputs(
|
||||
- jsgraph(), broker(), receiver, api_holder, frame_state, value, effect,
|
||||
- control, function_template_info, inputs, cursor);
|
||||
-
|
||||
return *effect = *control =
|
||||
- graph()->NewNode(common()->Call(call_descriptor), cursor, inputs);
|
||||
+ graph()->NewNode(common()->Call(call_descriptor), index, inputs);
|
||||
}
|
||||
|
||||
std::optional<JSNativeContextSpecialization::ValueEffectControl>
|
||||
diff --git a/src/compiler/js-native-context-specialization.h b/src/compiler/js-native-context-specialization.h
|
||||
index 8761637df00ed1a717ca581ef5faf8c78ec3336b..c74b59b6cc4c742fa5c50df2cc89794c8bd0f23d 100644
|
||||
--- a/src/compiler/js-native-context-specialization.h
|
||||
+++ b/src/compiler/js-native-context-specialization.h
|
||||
@@ -185,8 +185,7 @@ class V8_EXPORT_PRIVATE JSNativeContextSpecialization final
|
||||
PropertyAccessInfo const& access_info);
|
||||
Node* InlineApiCall(Node* receiver, Node* api_holder, Node* frame_state,
|
||||
Node* value, Node** effect, Node** control,
|
||||
- FunctionTemplateInfoRef function_template_info,
|
||||
- const FeedbackSource& feedback);
|
||||
+ FunctionTemplateInfoRef function_template_info);
|
||||
|
||||
// Construct the appropriate subgraph for element access.
|
||||
ValueEffectControl BuildElementAccess(Node* receiver, Node* index,
|
||||
diff --git a/src/d8/d8-test.cc b/src/d8/d8-test.cc
|
||||
index 77e3b3d71d552fdb50e47b75ca8d1bc7296bb9d4..6467930fbb39a67a10d6822545e985965ced83ad 100644
|
||||
--- a/src/d8/d8-test.cc
|
||||
+++ b/src/d8/d8-test.cc
|
||||
@@ -1305,67 +1305,6 @@ class FastCApiObject {
|
||||
info.GetReturnValue().Set(BigInt::NewFromUnsigned(isolate, a + b));
|
||||
}
|
||||
|
||||
- static void AttributeGetterSlowCallback(
|
||||
- const FunctionCallbackInfo<Value>& info) {
|
||||
- FastCApiObject* self = UnwrapObject(info.This());
|
||||
- self->slow_call_count_++;
|
||||
- info.GetReturnValue().Set(self->attribute_value_);
|
||||
- }
|
||||
-
|
||||
- static int AttributeGetterFastCallback(Local<Object> receiver,
|
||||
- FastApiCallbackOptions& options) {
|
||||
- FastCApiObject* self = UnwrapObject(receiver);
|
||||
- CHECK_SELF_OR_THROW_FAST_OPTIONS(0);
|
||||
- self->fast_call_count_++;
|
||||
- return self->attribute_value_;
|
||||
- }
|
||||
-
|
||||
-#ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
|
||||
- static AnyCType AttributeGetterFastCallbackPatch(AnyCType receiver,
|
||||
- AnyCType options) {
|
||||
- AnyCType ret;
|
||||
- ret.int32_value = AttributeGetterFastCallback(receiver.object_value,
|
||||
- *options.options_value);
|
||||
- return ret;
|
||||
- }
|
||||
-#endif // V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
|
||||
-
|
||||
- static void AttributeSetterSlowCallback(
|
||||
- const FunctionCallbackInfo<Value>& info) {
|
||||
- FastCApiObject* self = UnwrapObject(info.This());
|
||||
- self->slow_call_count_++;
|
||||
- if (info.Length() < 1 || !info[0]->IsNumber()) {
|
||||
- info.GetIsolate()->ThrowError(
|
||||
- "The attribute requires a number as a new value");
|
||||
- return;
|
||||
- }
|
||||
- double double_val =
|
||||
- info[0]->NumberValue(info.GetIsolate()->GetCurrentContext()).FromJust();
|
||||
- if (!base::IsValueInRangeForNumericType<int>(double_val)) {
|
||||
- info.GetIsolate()->ThrowError(
|
||||
- "New value of attribute is not within int32 range");
|
||||
- return;
|
||||
- }
|
||||
- self->attribute_value_ = static_cast<int>(double_val);
|
||||
- }
|
||||
-
|
||||
- static void AttributeSetterFastCallback(Local<Object> receiver, int32_t value,
|
||||
- FastApiCallbackOptions& options) {
|
||||
- FastCApiObject* self = UnwrapObject(receiver);
|
||||
- CHECK_SELF_OR_THROW_FAST_OPTIONS();
|
||||
- self->fast_call_count_++;
|
||||
- self->attribute_value_ = value;
|
||||
- }
|
||||
-
|
||||
-#ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
|
||||
- static void AttributeSetterFastCallbackPatch(AnyCType receiver,
|
||||
- AnyCType value,
|
||||
- AnyCType options) {
|
||||
- AttributeSetterFastCallback(receiver.object_value, value.int32_value,
|
||||
- *options.options_value);
|
||||
- }
|
||||
-#endif // V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
|
||||
-
|
||||
static void FastCallCount(const FunctionCallbackInfo<Value>& info) {
|
||||
FastCApiObject* self = UnwrapObject(info.This());
|
||||
CHECK_SELF_OR_THROW_SLOW();
|
||||
@@ -1500,25 +1439,6 @@ Local<FunctionTemplate> Shell::CreateTestFastCApiTemplate(Isolate* isolate) {
|
||||
ConstructorBehavior::kThrow,
|
||||
SideEffectType::kHasSideEffect, &add_all_c_func));
|
||||
|
||||
- CFunction fast_setter = CFunction::Make(
|
||||
- FastCApiObject::AttributeSetterFastCallback V8_IF_USE_SIMULATOR(
|
||||
- FastCApiObject::AttributeSetterFastCallback));
|
||||
- CFunction fast_getter = CFunction::Make(
|
||||
- FastCApiObject::AttributeGetterFastCallback V8_IF_USE_SIMULATOR(
|
||||
- FastCApiObject::AttributeGetterFastCallback));
|
||||
-
|
||||
- api_obj_ctor->PrototypeTemplate()->SetAccessorProperty(
|
||||
- String::NewFromUtf8(isolate, "fast_attribute").ToLocalChecked(),
|
||||
- FunctionTemplate::New(
|
||||
- isolate, FastCApiObject::AttributeGetterSlowCallback,
|
||||
- Local<Value>(), signature, 1, ConstructorBehavior::kThrow,
|
||||
- SideEffectType::kHasSideEffect, &fast_getter),
|
||||
- FunctionTemplate::New(
|
||||
- isolate, FastCApiObject::AttributeSetterSlowCallback,
|
||||
- Local<Value>(), signature, 1, ConstructorBehavior::kThrow,
|
||||
- SideEffectType::kHasSideEffect, &fast_setter),
|
||||
- v8::PropertyAttribute::None);
|
||||
-
|
||||
CFunction add_all_seq_c_func = CFunction::Make(
|
||||
FastCApiObject::AddAllSequenceFastCallback V8_IF_USE_SIMULATOR(
|
||||
FastCApiObject::AddAllSequenceFastCallbackPatch));
|
||||
diff --git a/test/mjsunit/compiler/fast-api-attributes.js b/test/mjsunit/compiler/fast-api-attributes.js
|
||||
deleted file mode 100644
|
||||
index 137e5c917cf7a56c89e70ed49d07e3134d1c8eac..0000000000000000000000000000000000000000
|
||||
--- a/test/mjsunit/compiler/fast-api-attributes.js
|
||||
+++ /dev/null
|
||||
@@ -1,45 +0,0 @@
|
||||
-// Copyright 2021 the V8 project authors. All rights reserved.
|
||||
-// Use of this source code is governed by a BSD-style license that can be
|
||||
-// found in the LICENSE file.
|
||||
-
|
||||
-// This file excercises basic fast API calls and enables fuzzing of this
|
||||
-// functionality.
|
||||
-
|
||||
-// Flags: --turbo-fast-api-calls --expose-fast-api --allow-natives-syntax --turbofan
|
||||
-// --always-turbofan is disabled because we rely on particular feedback for
|
||||
-// optimizing to the fastest path.
|
||||
-// Flags: --no-always-turbofan
|
||||
-// The test relies on optimizing/deoptimizing at predictable moments, so
|
||||
-// it's not suitable for deoptimization fuzzing.
|
||||
-// Flags: --deopt-every-n-times=0
|
||||
-// Flags: --fast-api-allow-float-in-sim
|
||||
-
|
||||
-const fast_c_api = new d8.test.FastCAPI();
|
||||
-
|
||||
-function get() {
|
||||
- return fast_c_api.fast_attribute;
|
||||
-}
|
||||
-
|
||||
-function set(value) {
|
||||
- fast_c_api.fast_attribute = value;
|
||||
-}
|
||||
-
|
||||
-%PrepareFunctionForOptimization(set);
|
||||
-set(12);
|
||||
-%OptimizeFunctionOnNextCall(set);
|
||||
-%PrepareFunctionForOptimization(get);
|
||||
-assertEquals(12, get());
|
||||
-%OptimizeFunctionOnNextCall(get);
|
||||
-
|
||||
-
|
||||
-fast_c_api.reset_counts();
|
||||
-set(21);
|
||||
-assertOptimized(set);
|
||||
-assertEquals(1, fast_c_api.fast_call_count());
|
||||
-assertEquals(0, fast_c_api.slow_call_count());
|
||||
-
|
||||
-fast_c_api.reset_counts();
|
||||
-assertEquals(21, get());
|
||||
-assertOptimized(get);
|
||||
-assertEquals(1, fast_c_api.fast_call_count());
|
||||
-assertEquals(0, fast_c_api.slow_call_count());
|
||||
diff --git a/test/mjsunit/mjsunit.status b/test/mjsunit/mjsunit.status
|
||||
index 93fe36a988be33f1eab1e814c8f0ad62bfbcbb53..632a8f4f0475076f82f66c73a29d92d3e9fc8c50 100644
|
||||
--- a/test/mjsunit/mjsunit.status
|
||||
+++ b/test/mjsunit/mjsunit.status
|
||||
@@ -757,7 +757,6 @@
|
||||
# These tests rely on TurboFan being enabled.
|
||||
'compiler/call-with-arraylike-or-spread*': [SKIP],
|
||||
'compiler/fast-api-calls': [SKIP],
|
||||
- 'compiler/fast-api-attributes': [SKIP],
|
||||
'compiler/fast-api-interface-types': [SKIP],
|
||||
'compiler/regress-crbug-1201011': [SKIP],
|
||||
'compiler/regress-crbug-1201057': [SKIP],
|
||||
@@ -2358,7 +2357,6 @@
|
||||
'regress/regress-1049982-2': [FAIL],
|
||||
# Maglev doesn't support fast API calls.
|
||||
'compiler/fast-api-annotations': [FAIL],
|
||||
- 'compiler/fast-api-attributes': [FAIL],
|
||||
'compiler/fast-api-calls': [FAIL],
|
||||
'compiler/fast-api-calls-8args': [FAIL],
|
||||
'compiler/fast-api-calls-string': [FAIL],
|
|
@ -1,853 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: John Kleinschmidt <jkleinsc@electronjs.org>
|
||||
Date: Fri, 15 Nov 2024 10:46:43 -0500
|
||||
Subject: Revert "[fastapi] Remove dynamic overload resolution"
|
||||
|
||||
Revert this until Node.js decides how to proceed and then pick up their fix.
|
||||
|
||||
Refs: https://github.com/nodejs/node/issues/55452
|
||||
Refs: https://chromium-review.googlesource.com/c/v8/v8/+/5956408
|
||||
Refs: https://chromium-review.googlesource.com/c/v8/v8/+/5982984
|
||||
Refs: https://chromium-review.googlesource.com/c/v8/v8/+/5979766
|
||||
|
||||
This reverts commit c41f7a0ef99bd1c9752ee79923f634145ebc4153.
|
||||
|
||||
diff --git a/src/api/api.cc b/src/api/api.cc
|
||||
index af1f0f3ad6ad0f2f0e7cb0123f9cd1ad0d1c80cb..b6a8bd3dfe53494502f13dbbfdfad1d79f621d40 100644
|
||||
--- a/src/api/api.cc
|
||||
+++ b/src/api/api.cc
|
||||
@@ -1349,16 +1349,6 @@ Local<FunctionTemplate> FunctionTemplate::NewWithCFunctionOverloads(
|
||||
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
|
||||
API_RCS_SCOPE(i_isolate, FunctionTemplate, New);
|
||||
|
||||
- // Check that all overloads of the fast API callback have different numbers of
|
||||
- // parameters. Since the number of overloads is supposed to be small, just
|
||||
- // comparing them with each other should be fine.
|
||||
- for (size_t i = 0; i < c_function_overloads.size(); ++i) {
|
||||
- for (size_t j = i + 1; j < c_function_overloads.size(); ++j) {
|
||||
- CHECK_NE(c_function_overloads.data()[i].ArgumentCount(),
|
||||
- c_function_overloads.data()[j].ArgumentCount());
|
||||
- }
|
||||
- }
|
||||
-
|
||||
if (!Utils::ApiCheck(
|
||||
c_function_overloads.empty() ||
|
||||
behavior == ConstructorBehavior::kThrow,
|
||||
diff --git a/src/compiler/fast-api-calls.cc b/src/compiler/fast-api-calls.cc
|
||||
index 2dc99dc83e0f78d2bbb0875cc04064b565deaf06..d560afa2ee9f4384738cddf659a51d4c42b4fe67 100644
|
||||
--- a/src/compiler/fast-api-calls.cc
|
||||
+++ b/src/compiler/fast-api-calls.cc
|
||||
@@ -62,6 +62,52 @@ ElementsKind GetTypedArrayElementsKind(CTypeInfo::Type type) {
|
||||
}
|
||||
}
|
||||
|
||||
+OverloadsResolutionResult ResolveOverloads(
|
||||
+ const FastApiCallFunctionVector& candidates, unsigned int arg_count) {
|
||||
+ DCHECK_GT(arg_count, 0);
|
||||
+
|
||||
+ static constexpr int kReceiver = 1;
|
||||
+
|
||||
+ // Only the case of the overload resolution of two functions, one with a
|
||||
+ // JSArray param and the other with a typed array param is currently
|
||||
+ // supported.
|
||||
+ DCHECK_EQ(candidates.size(), 2);
|
||||
+
|
||||
+ for (unsigned int arg_index = kReceiver; arg_index < arg_count; arg_index++) {
|
||||
+ int index_of_func_with_js_array_arg = -1;
|
||||
+ int index_of_func_with_typed_array_arg = -1;
|
||||
+ CTypeInfo::Type element_type = CTypeInfo::Type::kVoid;
|
||||
+
|
||||
+ for (size_t i = 0; i < candidates.size(); i++) {
|
||||
+ const CTypeInfo& type_info =
|
||||
+ candidates[i].signature->ArgumentInfo(arg_index);
|
||||
+ CTypeInfo::SequenceType sequence_type = type_info.GetSequenceType();
|
||||
+
|
||||
+ START_ALLOW_USE_DEPRECATED()
|
||||
+ if (sequence_type == CTypeInfo::SequenceType::kIsSequence) {
|
||||
+ DCHECK_LT(index_of_func_with_js_array_arg, 0);
|
||||
+ index_of_func_with_js_array_arg = static_cast<int>(i);
|
||||
+ } else if (sequence_type == CTypeInfo::SequenceType::kIsTypedArray) {
|
||||
+ DCHECK_LT(index_of_func_with_typed_array_arg, 0);
|
||||
+ index_of_func_with_typed_array_arg = static_cast<int>(i);
|
||||
+ element_type = type_info.GetType();
|
||||
+ } else {
|
||||
+ DCHECK_LT(index_of_func_with_js_array_arg, 0);
|
||||
+ DCHECK_LT(index_of_func_with_typed_array_arg, 0);
|
||||
+ }
|
||||
+ END_ALLOW_USE_DEPRECATED()
|
||||
+ }
|
||||
+
|
||||
+ if (index_of_func_with_js_array_arg >= 0 &&
|
||||
+ index_of_func_with_typed_array_arg >= 0) {
|
||||
+ return {static_cast<int>(arg_index), element_type};
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // No overload found with a JSArray and a typed array as i-th argument.
|
||||
+ return OverloadsResolutionResult::Invalid();
|
||||
+}
|
||||
+
|
||||
bool CanOptimizeFastSignature(const CFunctionInfo* c_signature) {
|
||||
USE(c_signature);
|
||||
|
||||
@@ -149,7 +195,8 @@ class FastApiCallBuilder {
|
||||
initialize_options_(initialize_options),
|
||||
generate_slow_api_call_(generate_slow_api_call) {}
|
||||
|
||||
- Node* Build(FastApiCallFunction c_function, Node* data_argument);
|
||||
+ Node* Build(const FastApiCallFunctionVector& c_functions,
|
||||
+ const CFunctionInfo* c_signature, Node* data_argument);
|
||||
|
||||
private:
|
||||
Node* WrapFastCall(const CallDescriptor* call_descriptor, int inputs_size,
|
||||
@@ -230,15 +277,35 @@ void FastApiCallBuilder::PropagateException() {
|
||||
__ Call(call_descriptor, count, inputs);
|
||||
}
|
||||
|
||||
-Node* FastApiCallBuilder::Build(FastApiCallFunction c_function,
|
||||
+Node* FastApiCallBuilder::Build(const FastApiCallFunctionVector& c_functions,
|
||||
+ const CFunctionInfo* c_signature,
|
||||
Node* data_argument) {
|
||||
- const CFunctionInfo* c_signature = c_function.signature;
|
||||
const int c_arg_count = c_signature->ArgumentCount();
|
||||
|
||||
// Hint to fast path.
|
||||
auto if_success = __ MakeLabel();
|
||||
auto if_error = __ MakeDeferredLabel();
|
||||
|
||||
+ // Overload resolution
|
||||
+ bool generate_fast_call = false;
|
||||
+ OverloadsResolutionResult overloads_resolution_result =
|
||||
+ OverloadsResolutionResult::Invalid();
|
||||
+
|
||||
+ if (c_functions.size() == 1) {
|
||||
+ generate_fast_call = true;
|
||||
+ } else {
|
||||
+ DCHECK_EQ(c_functions.size(), 2);
|
||||
+ overloads_resolution_result = ResolveOverloads(c_functions, c_arg_count);
|
||||
+ if (overloads_resolution_result.is_valid()) {
|
||||
+ generate_fast_call = true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!generate_fast_call) {
|
||||
+ // Only generate the slow call.
|
||||
+ return generate_slow_api_call_();
|
||||
+ }
|
||||
+
|
||||
// Generate fast call.
|
||||
|
||||
const int kFastTargetAddressInputIndex = 0;
|
||||
@@ -263,11 +330,18 @@ Node* FastApiCallBuilder::Build(FastApiCallFunction c_function,
|
||||
// address associated to the first and only element in the c_functions vector.
|
||||
// If there are multiple overloads the value of this input will be set later
|
||||
// with a Phi node created by AdaptOverloadedFastCallArgument.
|
||||
- inputs[kFastTargetAddressInputIndex] = __ ExternalConstant(
|
||||
- ExternalReference::Create(c_function.address, ref_type));
|
||||
+ inputs[kFastTargetAddressInputIndex] =
|
||||
+ (c_functions.size() == 1) ? __ ExternalConstant(ExternalReference::Create(
|
||||
+ c_functions[0].address, ref_type))
|
||||
+ : nullptr;
|
||||
|
||||
for (int i = 0; i < c_arg_count; ++i) {
|
||||
- inputs[i + kFastTargetAddressInputCount] = get_parameter_(i, &if_error);
|
||||
+ inputs[i + kFastTargetAddressInputCount] =
|
||||
+ get_parameter_(i, overloads_resolution_result, &if_error);
|
||||
+ if (overloads_resolution_result.target_address) {
|
||||
+ inputs[kFastTargetAddressInputIndex] =
|
||||
+ overloads_resolution_result.target_address;
|
||||
+ }
|
||||
}
|
||||
DCHECK_NOT_NULL(inputs[kFastTargetAddressInputIndex]);
|
||||
|
||||
@@ -368,7 +442,8 @@ Node* FastApiCallBuilder::Build(FastApiCallFunction c_function,
|
||||
|
||||
Node* BuildFastApiCall(Isolate* isolate, Graph* graph,
|
||||
GraphAssembler* graph_assembler,
|
||||
- FastApiCallFunction c_function, Node* data_argument,
|
||||
+ const FastApiCallFunctionVector& c_functions,
|
||||
+ const CFunctionInfo* c_signature, Node* data_argument,
|
||||
const GetParameter& get_parameter,
|
||||
const ConvertReturnValue& convert_return_value,
|
||||
const InitializeOptions& initialize_options,
|
||||
@@ -376,7 +451,7 @@ Node* BuildFastApiCall(Isolate* isolate, Graph* graph,
|
||||
FastApiCallBuilder builder(isolate, graph, graph_assembler, get_parameter,
|
||||
convert_return_value, initialize_options,
|
||||
generate_slow_api_call);
|
||||
- return builder.Build(c_function, data_argument);
|
||||
+ return builder.Build(c_functions, c_signature, data_argument);
|
||||
}
|
||||
|
||||
} // namespace fast_api_call
|
||||
diff --git a/src/compiler/fast-api-calls.h b/src/compiler/fast-api-calls.h
|
||||
index 171e66c427991bfe7db5c2875d12559767a24b55..b97b37e5746433d3801de19d4666a19afc223cdc 100644
|
||||
--- a/src/compiler/fast-api-calls.h
|
||||
+++ b/src/compiler/fast-api-calls.h
|
||||
@@ -40,16 +40,21 @@ struct OverloadsResolutionResult {
|
||||
|
||||
ElementsKind GetTypedArrayElementsKind(CTypeInfo::Type type);
|
||||
|
||||
+OverloadsResolutionResult ResolveOverloads(
|
||||
+ const FastApiCallFunctionVector& candidates, unsigned int arg_count);
|
||||
+
|
||||
bool CanOptimizeFastSignature(const CFunctionInfo* c_signature);
|
||||
|
||||
-using GetParameter = std::function<Node*(int, GraphAssemblerLabel<0>*)>;
|
||||
+using GetParameter = std::function<Node*(int, OverloadsResolutionResult&,
|
||||
+ GraphAssemblerLabel<0>*)>;
|
||||
using ConvertReturnValue = std::function<Node*(const CFunctionInfo*, Node*)>;
|
||||
using InitializeOptions = std::function<void(Node*)>;
|
||||
using GenerateSlowApiCall = std::function<Node*()>;
|
||||
|
||||
Node* BuildFastApiCall(Isolate* isolate, Graph* graph,
|
||||
GraphAssembler* graph_assembler,
|
||||
- FastApiCallFunction c_function, Node* data_argument,
|
||||
+ const FastApiCallFunctionVector& c_functions,
|
||||
+ const CFunctionInfo* c_signature, Node* data_argument,
|
||||
const GetParameter& get_parameter,
|
||||
const ConvertReturnValue& convert_return_value,
|
||||
const InitializeOptions& initialize_options,
|
||||
diff --git a/src/compiler/js-call-reducer.cc b/src/compiler/js-call-reducer.cc
|
||||
index d75a38769d582cd6e5a807f9670732dc92d77b7e..a29bd4a5be0c9a268386898f8a52e98933211b6c 100644
|
||||
--- a/src/compiler/js-call-reducer.cc
|
||||
+++ b/src/compiler/js-call-reducer.cc
|
||||
@@ -631,11 +631,11 @@ class FastApiCallReducerAssembler : public JSCallReducerAssembler {
|
||||
FastApiCallReducerAssembler(
|
||||
JSCallReducer* reducer, Node* node,
|
||||
const FunctionTemplateInfoRef function_template_info,
|
||||
- FastApiCallFunction c_function, Node* receiver, Node* holder,
|
||||
- const SharedFunctionInfoRef shared, Node* target, const int arity,
|
||||
- Node* effect)
|
||||
+ const FastApiCallFunctionVector& c_candidate_functions, Node* receiver,
|
||||
+ Node* holder, const SharedFunctionInfoRef shared, Node* target,
|
||||
+ const int arity, Node* effect)
|
||||
: JSCallReducerAssembler(reducer, node),
|
||||
- c_function_(c_function),
|
||||
+ c_candidate_functions_(c_candidate_functions),
|
||||
function_template_info_(function_template_info),
|
||||
receiver_(receiver),
|
||||
holder_(holder),
|
||||
@@ -643,6 +643,7 @@ class FastApiCallReducerAssembler : public JSCallReducerAssembler {
|
||||
target_(target),
|
||||
arity_(arity) {
|
||||
DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
|
||||
+ CHECK_GT(c_candidate_functions.size(), 0);
|
||||
InitializeEffectControl(effect, NodeProperties::GetControlInput(node));
|
||||
}
|
||||
|
||||
@@ -654,7 +655,7 @@ class FastApiCallReducerAssembler : public JSCallReducerAssembler {
|
||||
// All functions in c_candidate_functions_ have the same number of
|
||||
// arguments, so extract c_argument_count from the first function.
|
||||
const int c_argument_count =
|
||||
- static_cast<int>(c_function_.signature->ArgumentCount());
|
||||
+ static_cast<int>(c_candidate_functions_[0].signature->ArgumentCount());
|
||||
CHECK_GE(c_argument_count, kReceiver);
|
||||
|
||||
const int slow_arg_count =
|
||||
@@ -755,12 +756,13 @@ class FastApiCallReducerAssembler : public JSCallReducerAssembler {
|
||||
|
||||
TNode<Object> FastApiCall(CallDescriptor* descriptor, Node** inputs,
|
||||
size_t inputs_size) {
|
||||
- return AddNode<Object>(graph()->NewNode(
|
||||
- simplified()->FastApiCall(c_function_, feedback(), descriptor),
|
||||
- static_cast<int>(inputs_size), inputs));
|
||||
+ return AddNode<Object>(
|
||||
+ graph()->NewNode(simplified()->FastApiCall(c_candidate_functions_,
|
||||
+ feedback(), descriptor),
|
||||
+ static_cast<int>(inputs_size), inputs));
|
||||
}
|
||||
|
||||
- FastApiCallFunction c_function_;
|
||||
+ const FastApiCallFunctionVector c_candidate_functions_;
|
||||
const FunctionTemplateInfoRef function_template_info_;
|
||||
Node* const receiver_;
|
||||
Node* const holder_;
|
||||
@@ -3886,10 +3888,11 @@ Reduction JSCallReducer::ReduceCallWasmFunction(Node* node,
|
||||
// Returns an array with the indexes of the remaining entries in S, which
|
||||
// represents the set of "optimizable" function overloads.
|
||||
|
||||
-FastApiCallFunction GetFastApiCallTarget(
|
||||
- JSHeapBroker* broker, FunctionTemplateInfoRef function_template_info,
|
||||
- size_t arg_count) {
|
||||
- if (!v8_flags.turbo_fast_api_calls) return {0, nullptr};
|
||||
+FastApiCallFunctionVector CanOptimizeFastCall(
|
||||
+ JSHeapBroker* broker, Zone* zone,
|
||||
+ FunctionTemplateInfoRef function_template_info, size_t arg_count) {
|
||||
+ FastApiCallFunctionVector result(zone);
|
||||
+ if (!v8_flags.turbo_fast_api_calls) return result;
|
||||
|
||||
static constexpr int kReceiver = 1;
|
||||
|
||||
@@ -3918,15 +3921,15 @@ FastApiCallFunction GetFastApiCallTarget(
|
||||
static_cast<uint8_t>(c_signature->ArgumentInfo(i).GetFlags());
|
||||
if (flags & static_cast<uint8_t>(CTypeInfo::Flags::kEnforceRangeBit)) {
|
||||
// Bailout
|
||||
- return {0, nullptr};
|
||||
+ return FastApiCallFunctionVector(zone);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
- return {functions[i], c_signature};
|
||||
+ result.push_back({functions[i], c_signature});
|
||||
}
|
||||
}
|
||||
|
||||
- return {0, nullptr};
|
||||
+ return result;
|
||||
}
|
||||
|
||||
Reduction JSCallReducer::ReduceCallApiFunction(Node* node,
|
||||
@@ -4109,13 +4112,15 @@ Reduction JSCallReducer::ReduceCallApiFunction(Node* node,
|
||||
}
|
||||
|
||||
// Handles overloaded functions.
|
||||
- FastApiCallFunction c_function =
|
||||
- GetFastApiCallTarget(broker(), function_template_info, argc);
|
||||
|
||||
- if (c_function.address) {
|
||||
+ FastApiCallFunctionVector c_candidate_functions = CanOptimizeFastCall(
|
||||
+ broker(), graph()->zone(), function_template_info, argc);
|
||||
+ DCHECK_LE(c_candidate_functions.size(), 2);
|
||||
+
|
||||
+ if (!c_candidate_functions.empty()) {
|
||||
FastApiCallReducerAssembler a(this, node, function_template_info,
|
||||
- c_function, receiver, holder, shared, target,
|
||||
- argc, effect);
|
||||
+ c_candidate_functions, receiver, holder,
|
||||
+ shared, target, argc, effect);
|
||||
Node* fast_call_subgraph = a.ReduceFastApiCall();
|
||||
|
||||
return Replace(fast_call_subgraph);
|
||||
diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc
|
||||
index 377d36b1d880892d0d446ee386d21028d3ffec16..ebb8bcd585f6b185e355922fd97c94bd0136d968 100644
|
||||
--- a/src/compiler/simplified-lowering.cc
|
||||
+++ b/src/compiler/simplified-lowering.cc
|
||||
@@ -2015,7 +2015,7 @@ class RepresentationSelector {
|
||||
// argument, which must be a JSArray in one function and a TypedArray in the
|
||||
// other function, and both JSArrays and TypedArrays have the same UseInfo
|
||||
// UseInfo::AnyTagged(). All the other argument types must match.
|
||||
- const CFunctionInfo* c_signature = op_params.c_function().signature;
|
||||
+ const CFunctionInfo* c_signature = op_params.c_functions()[0].signature;
|
||||
const int c_arg_count = c_signature->ArgumentCount();
|
||||
CallDescriptor* call_descriptor = op_params.descriptor();
|
||||
// Arguments for CallApiCallbackOptimizedXXX builtin (including context)
|
||||
@@ -2057,8 +2057,12 @@ class RepresentationSelector {
|
||||
|
||||
// Effect and Control.
|
||||
ProcessRemainingInputs<T>(node, value_input_count);
|
||||
+ if (op_params.c_functions().empty()) {
|
||||
+ SetOutput<T>(node, MachineRepresentation::kTagged);
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
- CTypeInfo return_type = op_params.c_function().signature->ReturnInfo();
|
||||
+ CTypeInfo return_type = op_params.c_functions()[0].signature->ReturnInfo();
|
||||
switch (return_type.GetType()) {
|
||||
case CTypeInfo::Type::kBool:
|
||||
SetOutput<T>(node, MachineRepresentation::kBit);
|
||||
diff --git a/src/compiler/simplified-operator.cc b/src/compiler/simplified-operator.cc
|
||||
index d0405cf5bc25d47b7cf8bfd03b0bb639df4eddd4..f5810d72d99f4ecfe668d9e1fd9b3ad2ea123875 100644
|
||||
--- a/src/compiler/simplified-operator.cc
|
||||
+++ b/src/compiler/simplified-operator.cc
|
||||
@@ -2096,21 +2096,26 @@ FastApiCallParameters const& FastApiCallParametersOf(const Operator* op) {
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, FastApiCallParameters const& p) {
|
||||
- FastApiCallFunction c_function = p.c_function();
|
||||
- os << c_function.address << ":" << c_function.signature << ", ";
|
||||
+ const auto& c_functions = p.c_functions();
|
||||
+ for (size_t i = 0; i < c_functions.size(); i++) {
|
||||
+ os << c_functions[i].address << ":" << c_functions[i].signature << ", ";
|
||||
+ }
|
||||
return os << p.feedback() << ", " << p.descriptor();
|
||||
}
|
||||
|
||||
size_t hash_value(FastApiCallParameters const& p) {
|
||||
- FastApiCallFunction c_function = p.c_function();
|
||||
- size_t hash = base::hash_combine(c_function.address, c_function.signature);
|
||||
+ const auto& c_functions = p.c_functions();
|
||||
+ size_t hash = 0;
|
||||
+ for (size_t i = 0; i < c_functions.size(); i++) {
|
||||
+ hash = base::hash_combine(c_functions[i].address, c_functions[i].signature);
|
||||
+ }
|
||||
return base::hash_combine(hash, FeedbackSource::Hash()(p.feedback()),
|
||||
p.descriptor());
|
||||
}
|
||||
|
||||
bool operator==(FastApiCallParameters const& lhs,
|
||||
FastApiCallParameters const& rhs) {
|
||||
- return lhs.c_function() == rhs.c_function() &&
|
||||
+ return lhs.c_functions() == rhs.c_functions() &&
|
||||
lhs.feedback() == rhs.feedback() &&
|
||||
lhs.descriptor() == rhs.descriptor();
|
||||
}
|
||||
@@ -2320,11 +2325,19 @@ const Operator* SimplifiedOperatorBuilder::TransitionAndStoreNonNumberElement(
|
||||
}
|
||||
|
||||
const Operator* SimplifiedOperatorBuilder::FastApiCall(
|
||||
- FastApiCallFunction c_function, FeedbackSource const& feedback,
|
||||
- CallDescriptor* descriptor) {
|
||||
- CHECK_NOT_NULL(c_function.signature);
|
||||
- const CFunctionInfo* signature = c_function.signature;
|
||||
+ const FastApiCallFunctionVector& c_functions,
|
||||
+ FeedbackSource const& feedback, CallDescriptor* descriptor) {
|
||||
+ DCHECK(!c_functions.empty());
|
||||
+
|
||||
+ // All function overloads have the same number of arguments and options.
|
||||
+ const CFunctionInfo* signature = c_functions[0].signature;
|
||||
const int c_arg_count = signature->ArgumentCount();
|
||||
+ for (size_t i = 1; i < c_functions.size(); i++) {
|
||||
+ CHECK_NOT_NULL(c_functions[i].signature);
|
||||
+ DCHECK_EQ(c_functions[i].signature->ArgumentCount(), c_arg_count);
|
||||
+ DCHECK_EQ(c_functions[i].signature->HasOptions(),
|
||||
+ c_functions[0].signature->HasOptions());
|
||||
+ }
|
||||
// Arguments for CallApiCallbackOptimizedXXX builtin (including context)
|
||||
// plus JS arguments (including receiver).
|
||||
int slow_arg_count = static_cast<int>(descriptor->ParameterCount());
|
||||
@@ -2334,13 +2347,13 @@ const Operator* SimplifiedOperatorBuilder::FastApiCall(
|
||||
return zone()->New<Operator1<FastApiCallParameters>>(
|
||||
IrOpcode::kFastApiCall, Operator::kNoProperties, "FastApiCall",
|
||||
value_input_count, 1, 1, 1, 1, 2,
|
||||
- FastApiCallParameters(c_function, feedback, descriptor));
|
||||
+ FastApiCallParameters(c_functions, feedback, descriptor));
|
||||
}
|
||||
|
||||
// static
|
||||
int FastApiCallNode::FastCallArgumentCount(Node* node) {
|
||||
FastApiCallParameters p = FastApiCallParametersOf(node->op());
|
||||
- const CFunctionInfo* signature = p.c_function().signature;
|
||||
+ const CFunctionInfo* signature = p.c_functions()[0].signature;
|
||||
CHECK_NOT_NULL(signature);
|
||||
return signature->ArgumentCount();
|
||||
}
|
||||
diff --git a/src/compiler/simplified-operator.h b/src/compiler/simplified-operator.h
|
||||
index 5cb305f8db8419bcaedc89dbd9d68226bcf90551..19cc23394d5dd729974ff4faf0e4f7cf54c4710e 100644
|
||||
--- a/src/compiler/simplified-operator.h
|
||||
+++ b/src/compiler/simplified-operator.h
|
||||
@@ -742,25 +742,35 @@ struct FastApiCallFunction {
|
||||
return address == rhs.address && signature == rhs.signature;
|
||||
}
|
||||
};
|
||||
+typedef ZoneVector<FastApiCallFunction> FastApiCallFunctionVector;
|
||||
|
||||
class FastApiCallParameters {
|
||||
public:
|
||||
- explicit FastApiCallParameters(FastApiCallFunction c_function,
|
||||
+ explicit FastApiCallParameters(const FastApiCallFunctionVector& c_functions,
|
||||
FeedbackSource const& feedback,
|
||||
CallDescriptor* descriptor)
|
||||
- : c_function_(c_function), feedback_(feedback), descriptor_(descriptor) {}
|
||||
+ : c_functions_(c_functions),
|
||||
+ feedback_(feedback),
|
||||
+ descriptor_(descriptor) {}
|
||||
|
||||
- FastApiCallFunction c_function() const { return c_function_; }
|
||||
+ const FastApiCallFunctionVector& c_functions() const { return c_functions_; }
|
||||
FeedbackSource const& feedback() const { return feedback_; }
|
||||
CallDescriptor* descriptor() const { return descriptor_; }
|
||||
- const CFunctionInfo* signature() const { return c_function_.signature; }
|
||||
+ const CFunctionInfo* signature() const {
|
||||
+ DCHECK(!c_functions_.empty());
|
||||
+ return c_functions_[0].signature;
|
||||
+ }
|
||||
unsigned int argument_count() const {
|
||||
const unsigned int count = signature()->ArgumentCount();
|
||||
+ DCHECK(base::all_of(c_functions_, [count](const auto& f) {
|
||||
+ return f.signature->ArgumentCount() == count;
|
||||
+ }));
|
||||
return count;
|
||||
}
|
||||
|
||||
private:
|
||||
- FastApiCallFunction c_function_;
|
||||
+ // A single FastApiCall node can represent multiple overloaded functions.
|
||||
+ const FastApiCallFunctionVector c_functions_;
|
||||
|
||||
const FeedbackSource feedback_;
|
||||
CallDescriptor* descriptor_;
|
||||
@@ -1233,9 +1243,9 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
|
||||
const Operator* Unsigned32Divide();
|
||||
|
||||
// Represents the inputs necessary to construct a fast and a slow API call.
|
||||
- const Operator* FastApiCall(FastApiCallFunction c_function,
|
||||
- FeedbackSource const& feedback,
|
||||
- CallDescriptor* descriptor);
|
||||
+ const Operator* FastApiCall(
|
||||
+ const FastApiCallFunctionVector& c_candidate_functions,
|
||||
+ FeedbackSource const& feedback, CallDescriptor* descriptor);
|
||||
|
||||
#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA
|
||||
const Operator* GetContinuationPreservedEmbedderData();
|
||||
diff --git a/src/compiler/turbofan-typer.cc b/src/compiler/turbofan-typer.cc
|
||||
index 811c9c5ab82ebbdf6ca14a2fd99c3b154609d506..f36916c1a0d39293f01eca84cac6ef83096cd25e 100644
|
||||
--- a/src/compiler/turbofan-typer.cc
|
||||
+++ b/src/compiler/turbofan-typer.cc
|
||||
@@ -1190,8 +1190,11 @@ Type Typer::Visitor::TypeCall(Node* node) { return Type::Any(); }
|
||||
|
||||
Type Typer::Visitor::TypeFastApiCall(Node* node) {
|
||||
FastApiCallParameters const& op_params = FastApiCallParametersOf(node->op());
|
||||
+ if (op_params.c_functions().empty()) {
|
||||
+ return Type::Undefined();
|
||||
+ }
|
||||
|
||||
- const CFunctionInfo* c_signature = op_params.c_function().signature;
|
||||
+ const CFunctionInfo* c_signature = op_params.c_functions()[0].signature;
|
||||
CTypeInfo return_type = c_signature->ReturnInfo();
|
||||
|
||||
switch (return_type.GetType()) {
|
||||
diff --git a/src/compiler/turboshaft/fast-api-call-lowering-reducer.h b/src/compiler/turboshaft/fast-api-call-lowering-reducer.h
|
||||
index 2dec266f9e648391fe61a62931cca1ad20de719c..dc27e91ad0da93a5b68053f132f219f95f641ca1 100644
|
||||
--- a/src/compiler/turboshaft/fast-api-call-lowering-reducer.h
|
||||
+++ b/src/compiler/turboshaft/fast-api-call-lowering-reducer.h
|
||||
@@ -29,23 +29,41 @@ class FastApiCallLoweringReducer : public Next {
|
||||
base::Vector<const OpIndex> arguments,
|
||||
const FastApiCallParameters* parameters,
|
||||
base::Vector<const RegisterRepresentation> out_reps) {
|
||||
- FastApiCallFunction c_function = parameters->c_function;
|
||||
+ const auto& c_functions = parameters->c_functions;
|
||||
const auto& c_signature = parameters->c_signature();
|
||||
const int c_arg_count = c_signature->ArgumentCount();
|
||||
DCHECK_EQ(c_arg_count, arguments.size());
|
||||
+ const auto& resolution_result = parameters->resolution_result;
|
||||
|
||||
Label<> handle_error(this);
|
||||
Label<Word32> done(this);
|
||||
Variable result = __ NewVariable(RegisterRepresentation::FromCTypeInfo(
|
||||
c_signature->ReturnInfo(), c_signature->GetInt64Representation()));
|
||||
|
||||
- OpIndex callee = __ ExternalConstant(ExternalReference::Create(
|
||||
- c_function.address, ExternalReference::FAST_C_CALL));
|
||||
-
|
||||
+ OpIndex callee;
|
||||
base::SmallVector<OpIndex, 16> args;
|
||||
for (int i = 0; i < c_arg_count; ++i) {
|
||||
+ // Check if this is the argument on which we need to perform overload
|
||||
+ // resolution.
|
||||
+ if (i == resolution_result.distinguishable_arg_index) {
|
||||
+ DCHECK_GT(c_functions.size(), 1);
|
||||
+ // This only happens when the FastApiCall node represents multiple
|
||||
+ // overloaded functions and {i} is the index of the distinguishable
|
||||
+ // argument.
|
||||
+ OpIndex arg_i;
|
||||
+ std::tie(callee, arg_i) = AdaptOverloadedFastCallArgument(
|
||||
+ arguments[i], c_functions, resolution_result, handle_error);
|
||||
+ args.push_back(arg_i);
|
||||
+ } else {
|
||||
CTypeInfo type = c_signature->ArgumentInfo(i);
|
||||
args.push_back(AdaptFastCallArgument(arguments[i], type, handle_error));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (c_functions.size() == 1) {
|
||||
+ DCHECK(!callee.valid());
|
||||
+ callee = __ ExternalConstant(ExternalReference::Create(
|
||||
+ c_functions[0].address, ExternalReference::FAST_C_CALL));
|
||||
}
|
||||
|
||||
// While adapting the arguments, we might have noticed an inconsistency that
|
||||
@@ -137,6 +155,56 @@ class FastApiCallLoweringReducer : public Next {
|
||||
}
|
||||
|
||||
private:
|
||||
+ std::pair<OpIndex, OpIndex> AdaptOverloadedFastCallArgument(
|
||||
+ OpIndex argument, const FastApiCallFunctionVector& c_functions,
|
||||
+ const fast_api_call::OverloadsResolutionResult& resolution_result,
|
||||
+ Label<>& handle_error) {
|
||||
+ Label<WordPtr, WordPtr> done(this);
|
||||
+
|
||||
+ for (size_t func_index = 0; func_index < c_functions.size(); ++func_index) {
|
||||
+ const CFunctionInfo* c_signature = c_functions[func_index].signature;
|
||||
+ CTypeInfo arg_type = c_signature->ArgumentInfo(
|
||||
+ resolution_result.distinguishable_arg_index);
|
||||
+
|
||||
+ Label<> next(this);
|
||||
+
|
||||
+ // Check that the value is a HeapObject.
|
||||
+ GOTO_IF(__ ObjectIsSmi(argument), handle_error);
|
||||
+
|
||||
+ switch (arg_type.GetSequenceType()) {
|
||||
+ case CTypeInfo::SequenceType::kIsSequence: {
|
||||
+ CHECK_EQ(arg_type.GetType(), CTypeInfo::Type::kVoid);
|
||||
+
|
||||
+ // Check that the value is a JSArray.
|
||||
+ V<Map> map = __ LoadMapField(argument);
|
||||
+ V<Word32> instance_type = __ LoadInstanceTypeField(map);
|
||||
+ GOTO_IF_NOT(__ Word32Equal(instance_type, JS_ARRAY_TYPE), next);
|
||||
+
|
||||
+ OpIndex argument_to_pass = __ AdaptLocalArgument(argument);
|
||||
+ OpIndex target_address = __ ExternalConstant(
|
||||
+ ExternalReference::Create(c_functions[func_index].address,
|
||||
+ ExternalReference::FAST_C_CALL));
|
||||
+ GOTO(done, target_address, argument_to_pass);
|
||||
+ break;
|
||||
+ }
|
||||
+ START_ALLOW_USE_DEPRECATED()
|
||||
+ case CTypeInfo::SequenceType::kIsTypedArray:
|
||||
+ UNREACHABLE();
|
||||
+ END_ALLOW_USE_DEPRECATED()
|
||||
+
|
||||
+ default: {
|
||||
+ UNREACHABLE();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ BIND(next);
|
||||
+ }
|
||||
+ GOTO(handle_error);
|
||||
+
|
||||
+ BIND(done, callee, arg);
|
||||
+ return {callee, arg};
|
||||
+ }
|
||||
+
|
||||
template <typename T>
|
||||
V<T> Checked(V<Tuple<T, Word32>> result, Label<>& otherwise) {
|
||||
V<Word32> result_state = __ template Projection<1>(result);
|
||||
diff --git a/src/compiler/turboshaft/graph-builder.cc b/src/compiler/turboshaft/graph-builder.cc
|
||||
index f24cd884bf7810aaed5e58b2044c2770653266f1..d79f6c801d2562a3cd65597d79050791fee3ad08 100644
|
||||
--- a/src/compiler/turboshaft/graph-builder.cc
|
||||
+++ b/src/compiler/turboshaft/graph-builder.cc
|
||||
@@ -1974,7 +1974,7 @@ OpIndex GraphBuilder::Process(
|
||||
DCHECK(dominating_frame_state.valid());
|
||||
FastApiCallNode n(node);
|
||||
const auto& params = n.Parameters();
|
||||
- FastApiCallFunction c_function = params.c_function();
|
||||
+ const FastApiCallFunctionVector& c_functions = params.c_functions();
|
||||
const int c_arg_count = params.argument_count();
|
||||
|
||||
base::SmallVector<OpIndex, 16> slow_call_arguments;
|
||||
@@ -2141,6 +2141,40 @@ OpIndex GraphBuilder::Process(
|
||||
Block* catch_block = Map(block->SuccessorAt(1));
|
||||
catch_scope.emplace(assembler, catch_block);
|
||||
}
|
||||
+ // Overload resolution.
|
||||
+ auto resolution_result =
|
||||
+ fast_api_call::OverloadsResolutionResult::Invalid();
|
||||
+ if (c_functions.size() != 1) {
|
||||
+ DCHECK_EQ(c_functions.size(), 2);
|
||||
+ resolution_result =
|
||||
+ fast_api_call::ResolveOverloads(c_functions, c_arg_count);
|
||||
+ if (!resolution_result.is_valid()) {
|
||||
+ V<Object> fallback_result = V<Object>::Cast(__ Call(
|
||||
+ slow_call_callee, dominating_frame_state,
|
||||
+ base::VectorOf(slow_call_arguments),
|
||||
+ TSCallDescriptor::Create(params.descriptor(), CanThrow::kYes,
|
||||
+ LazyDeoptOnThrow::kNo,
|
||||
+ __ graph_zone())));
|
||||
+ Variable result =
|
||||
+ __ NewVariable(RegisterRepresentation::FromCTypeInfo(
|
||||
+ c_functions[0].signature->ReturnInfo(),
|
||||
+ c_functions[0].signature->GetInt64Representation()));
|
||||
+ convert_fallback_return(
|
||||
+ result, c_functions[0].signature->GetInt64Representation(),
|
||||
+ c_functions[0].signature->ReturnInfo().GetType(),
|
||||
+ fallback_result);
|
||||
+ V<Any> value = __ GetVariable(result);
|
||||
+ if (is_final_control) {
|
||||
+ // The `__ Call()` before has already created exceptional
|
||||
+ // control flow and bound a new block for the success case. So we
|
||||
+ // can just `Goto` the block that Turbofan designated as the
|
||||
+ // `IfSuccess` successor.
|
||||
+ __ Goto(Map(block->SuccessorAt(0)));
|
||||
+ }
|
||||
+ return value;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
// Prepare FastCallApiOp parameters.
|
||||
base::SmallVector<OpIndex, 16> arguments;
|
||||
for (int i = 0; i < c_arg_count; ++i) {
|
||||
@@ -2150,8 +2184,8 @@ OpIndex GraphBuilder::Process(
|
||||
|
||||
V<Context> context = Map(n.Context());
|
||||
|
||||
- const FastApiCallParameters* parameters =
|
||||
- FastApiCallParameters::Create(c_function, __ graph_zone());
|
||||
+ const FastApiCallParameters* parameters = FastApiCallParameters::Create(
|
||||
+ c_functions, resolution_result, __ graph_zone());
|
||||
|
||||
// There is one return in addition to the return value of the C function,
|
||||
// which indicates if a fast API call actually happened.
|
||||
diff --git a/src/compiler/turboshaft/operations.h b/src/compiler/turboshaft/operations.h
|
||||
index 1977d4d57a34781ae925d4f0ad0d09192b937dbe..d258f4b10f09b79c4aaf54ebff5e55cf8227aecc 100644
|
||||
--- a/src/compiler/turboshaft/operations.h
|
||||
+++ b/src/compiler/turboshaft/operations.h
|
||||
@@ -6403,16 +6403,24 @@ struct Float64SameValueOp : FixedArityOperationT<2, Float64SameValueOp> {
|
||||
};
|
||||
|
||||
struct FastApiCallParameters : public NON_EXPORTED_BASE(ZoneObject) {
|
||||
- FastApiCallFunction c_function;
|
||||
+ const FastApiCallFunctionVector c_functions;
|
||||
+ fast_api_call::OverloadsResolutionResult resolution_result;
|
||||
|
||||
- const CFunctionInfo* c_signature() const { return c_function.signature; }
|
||||
+ const CFunctionInfo* c_signature() const { return c_functions[0].signature; }
|
||||
|
||||
- explicit FastApiCallParameters(FastApiCallFunction c_function)
|
||||
- : c_function(c_function) {}
|
||||
+ FastApiCallParameters(
|
||||
+ const FastApiCallFunctionVector& c_functions,
|
||||
+ const fast_api_call::OverloadsResolutionResult& resolution_result)
|
||||
+ : c_functions(c_functions), resolution_result(resolution_result) {
|
||||
+ DCHECK_LT(0, c_functions.size());
|
||||
+ }
|
||||
|
||||
- static const FastApiCallParameters* Create(FastApiCallFunction c_function,
|
||||
- Zone* graph_zone) {
|
||||
- return graph_zone->New<FastApiCallParameters>(c_function);
|
||||
+ static const FastApiCallParameters* Create(
|
||||
+ const FastApiCallFunctionVector& c_functions,
|
||||
+ const fast_api_call::OverloadsResolutionResult& resolution_result,
|
||||
+ Zone* graph_zone) {
|
||||
+ return graph_zone->New<FastApiCallParameters>(std::move(c_functions),
|
||||
+ resolution_result);
|
||||
}
|
||||
};
|
||||
|
||||
diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc
|
||||
index 2a1edc79d000801b21e89304eefc27d6ea6f4675..79b2e0b010609acbf0e0b8ac6835364a6448ff03 100644
|
||||
--- a/src/compiler/wasm-compiler.cc
|
||||
+++ b/src/compiler/wasm-compiler.cc
|
||||
@@ -8356,13 +8356,19 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
|
||||
wasm::ObjectAccess::ToTagged(
|
||||
FunctionTemplateInfo::kCallbackDataOffset));
|
||||
|
||||
- FastApiCallFunction c_function{c_address, c_signature};
|
||||
+ FastApiCallFunctionVector fast_api_call_function_vector(mcgraph()->zone());
|
||||
+ fast_api_call_function_vector.push_back({c_address, c_signature});
|
||||
Node* call = fast_api_call::BuildFastApiCall(
|
||||
- target->GetIsolate(), graph(), gasm_.get(), c_function,
|
||||
- api_data_argument,
|
||||
+ target->GetIsolate(), graph(), gasm_.get(),
|
||||
+ fast_api_call_function_vector, c_signature, api_data_argument,
|
||||
// Load and convert parameters passed to C function
|
||||
- [this, c_signature, receiver_node](int param_index,
|
||||
- GraphAssemblerLabel<0>*) {
|
||||
+ [this, c_signature, receiver_node](
|
||||
+ int param_index,
|
||||
+ fast_api_call::OverloadsResolutionResult& overloads,
|
||||
+ GraphAssemblerLabel<0>*) {
|
||||
+ // Wasm does not currently support overloads
|
||||
+ CHECK(!overloads.is_valid());
|
||||
+
|
||||
if (param_index == 0) {
|
||||
return gasm_->AdaptLocalArgument(receiver_node);
|
||||
}
|
||||
diff --git a/src/d8/d8-test.cc b/src/d8/d8-test.cc
|
||||
index 6467930fbb39a67a10d6822545e985965ced83ad..1c99e4d89cbc605c6c1b75ce31b09b67334a10ee 100644
|
||||
--- a/src/d8/d8-test.cc
|
||||
+++ b/src/d8/d8-test.cc
|
||||
@@ -443,6 +443,20 @@ class FastCApiObject {
|
||||
}
|
||||
}
|
||||
|
||||
+ static int32_t AddAllIntInvalidCallback(Local<Object> receiver,
|
||||
+ int32_t arg_i32,
|
||||
+ FastApiCallbackOptions& options) {
|
||||
+ // This should never be called
|
||||
+ UNREACHABLE();
|
||||
+ }
|
||||
+
|
||||
+ static int32_t AddAllIntInvalidOverloadCallback(
|
||||
+ Local<Object> receiver, Local<Object> seq_arg,
|
||||
+ FastApiCallbackOptions& options) {
|
||||
+ // This should never be called
|
||||
+ UNREACHABLE();
|
||||
+ }
|
||||
+
|
||||
#ifdef V8_USE_SIMULATOR_WITH_GENERIC_C_CALLS
|
||||
static AnyCType Add32BitIntFastCallbackPatch(AnyCType receiver,
|
||||
AnyCType arg_i32,
|
||||
@@ -1553,6 +1567,22 @@ Local<FunctionTemplate> Shell::CreateTestFastCApiTemplate(Isolate* isolate) {
|
||||
signature, 1, ConstructorBehavior::kThrow,
|
||||
SideEffectType::kHasSideEffect, {add_all_overloads, 2}));
|
||||
|
||||
+ CFunction add_all_int_invalid_func =
|
||||
+ CFunction::Make(FastCApiObject::AddAllIntInvalidCallback);
|
||||
+ CFunction add_all_int_invalid_overload =
|
||||
+ CFunction::Make(FastCApiObject::AddAllIntInvalidOverloadCallback);
|
||||
+
|
||||
+ const CFunction add_all_invalid_overloads[] = {
|
||||
+ add_all_int_invalid_func,
|
||||
+ add_all_int_invalid_overload,
|
||||
+ };
|
||||
+ api_obj_ctor->PrototypeTemplate()->Set(
|
||||
+ isolate, "add_all_invalid_overload",
|
||||
+ FunctionTemplate::NewWithCFunctionOverloads(
|
||||
+ isolate, FastCApiObject::AddAllSequenceSlowCallback, Local<Value>(),
|
||||
+ signature, 1, ConstructorBehavior::kThrow,
|
||||
+ SideEffectType::kHasSideEffect, {add_all_invalid_overloads, 2}));
|
||||
+
|
||||
CFunction add_all_32bit_int_8args_c_func = CFunction::Make(
|
||||
FastCApiObject::AddAll32BitIntFastCallback_8Args V8_IF_USE_SIMULATOR(
|
||||
FastCApiObject::AddAll32BitIntFastCallback_8ArgsPatch));
|
||||
diff --git a/test/mjsunit/compiler/fast-api-sequences.js b/test/mjsunit/compiler/fast-api-sequences.js
|
||||
index 6a982bbbfe13ae792a3d3a1d3376f71b6b00d38a..4318f60fc70f0a2684c6f233861e513063f8e542 100644
|
||||
--- a/test/mjsunit/compiler/fast-api-sequences.js
|
||||
+++ b/test/mjsunit/compiler/fast-api-sequences.js
|
||||
@@ -81,6 +81,30 @@ for (let i = 0; i < 100; i++) {
|
||||
ExpectFastCall(overloaded_test, 62);
|
||||
})();
|
||||
|
||||
+// Test function with invalid overloads.
|
||||
+(function () {
|
||||
+ function overloaded_test() {
|
||||
+ return fast_c_api.add_all_invalid_overload(
|
||||
+ [26, -6, 42]);
|
||||
+ }
|
||||
+
|
||||
+ %PrepareFunctionForOptimization(overloaded_test);
|
||||
+ result = overloaded_test();
|
||||
+ assertEquals(62, result);
|
||||
+
|
||||
+ fast_c_api.reset_counts();
|
||||
+ %OptimizeFunctionOnNextCall(overloaded_test);
|
||||
+ result = overloaded_test();
|
||||
+ assertEquals(62, result);
|
||||
+ // Here we deopt because with this invalid overload:
|
||||
+ // - add_all_int_invalid_func(Receiver, Bool, Int32, Options)
|
||||
+ // - add_all_seq_c_func(Receiver, Bool, JSArray, Options)
|
||||
+ // we expect that a number will be passed as 3rd argument
|
||||
+ // (SimplifiedLowering takes the type from the first overloaded function).
|
||||
+ assertUnoptimized(overloaded_test);
|
||||
+ assertEquals(0, fast_c_api.fast_call_count());
|
||||
+})();
|
||||
+
|
||||
// ----------- Test different TypedArray functions. -----------
|
||||
// ----------- add_all_<TYPE>_typed_array -----------
|
||||
// `add_all_<TYPE>_typed_array` have the following signature:
|
||||
diff --git a/test/mjsunit/regress/regress-335548148.js b/test/mjsunit/regress/regress-335548148.js
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..4725c48990767fc2a469a5ab3c04ba96e11bf54c
|
||||
--- /dev/null
|
||||
+++ b/test/mjsunit/regress/regress-335548148.js
|
||||
@@ -0,0 +1,29 @@
|
||||
+// Copyright 2024 the V8 project authors. All rights reserved.
|
||||
+// Use of this source code is governed by a BSD-style license that can be
|
||||
+// found in the LICENSE file.
|
||||
+
|
||||
+// Flags: --turbo-fast-api-calls --expose-fast-api --allow-natives-syntax --turbofan
|
||||
+// --always-turbofan is disabled because we rely on particular feedback for
|
||||
+// optimizing to the fastest path.
|
||||
+// Flags: --no-always-turbofan
|
||||
+// The test relies on optimizing/deoptimizing at predictable moments, so
|
||||
+// it's not suitable for deoptimization fuzzing.
|
||||
+// Flags: --deopt-every-n-times=0
|
||||
+// Flags: --fast-api-allow-float-in-sim
|
||||
+
|
||||
+const __v_0 = new d8.test.FastCAPI();
|
||||
+
|
||||
+function __f_0(__v_4, __v_5) {
|
||||
+ try {
|
||||
+ // Call the API function with an invalid parameter. Because of the invalid
|
||||
+ // parameter the overload resolution of the fast API cannot figure out
|
||||
+ // which function should be called, and therefore emits code for a normal
|
||||
+ // API call.
|
||||
+ __v_0.add_all_invalid_overload(__v_5, Object.prototype);
|
||||
+ } catch (e) {}
|
||||
+}
|
||||
+
|
||||
+%PrepareFunctionForOptimization(__f_0);
|
||||
+__f_0(Number.MIN_VALUE, Number.MIN_VALUE);
|
||||
+%OptimizeFunctionOnNextCall(__f_0);
|
||||
+__f_0(Number.MIN_VALUE, Number.MIN_VALUE);
|
Loading…
Add table
Add a link
Reference in a new issue