Commit 89f02d78 authored by jameslahm's avatar jameslahm Committed by V8 LUCI CQ

[builtins] add fast path GetProperty for function template

having cached_property_name

When call function_template accessor in Generic/NoFeedback,
if the function template has cached_property_name,
the holder will have data property with the cached_property_name,
we can use GetProperty to get it rather than bailout.

Bug: v8:10179
Change-Id: I8b878fff969d05eeab1c95fc4b73df6079496840
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3492396Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/main@{#79343}
parent 28371a57
...@@ -9170,7 +9170,7 @@ void CodeStubAssembler::ForEachEnumerableOwnProperty( ...@@ -9170,7 +9170,7 @@ void CodeStubAssembler::ForEachEnumerableOwnProperty(
var_value = CallGetterIfAccessor( var_value = CallGetterIfAccessor(
var_value.value(), object, var_details.value(), context, object, var_value.value(), object, var_details.value(), context, object,
next_key, &slow_load, kCallJSGetter); next_key, &slow_load, kCallJSGetterUseCachedName);
Goto(&callback); Goto(&callback);
BIND(&slow_load); BIND(&slow_load);
...@@ -9705,7 +9705,8 @@ TNode<Object> CodeStubAssembler::CallGetterIfAccessor( ...@@ -9705,7 +9705,8 @@ TNode<Object> CodeStubAssembler::CallGetterIfAccessor(
// AccessorPair case. // AccessorPair case.
{ {
if (mode == kCallJSGetter) { if (mode == kCallJSGetterUseCachedName ||
mode == kCallJSGetterDontUseCachedName) {
Label if_callable(this), if_function_template_info(this); Label if_callable(this), if_function_template_info(this);
TNode<AccessorPair> accessor_pair = CAST(value); TNode<AccessorPair> accessor_pair = CAST(value);
TNode<HeapObject> getter = TNode<HeapObject> getter =
...@@ -9730,10 +9731,15 @@ TNode<Object> CodeStubAssembler::CallGetterIfAccessor( ...@@ -9730,10 +9731,15 @@ TNode<Object> CodeStubAssembler::CallGetterIfAccessor(
BIND(&if_function_template_info); BIND(&if_function_template_info);
{ {
Label runtime(this, Label::kDeferred); Label runtime(this, Label::kDeferred);
Label use_cached_property(this);
GotoIf(IsSideEffectFreeDebuggingActive(), &runtime); GotoIf(IsSideEffectFreeDebuggingActive(), &runtime);
TNode<HeapObject> cached_property_name = LoadObjectField<HeapObject>( TNode<HeapObject> cached_property_name = LoadObjectField<HeapObject>(
getter, FunctionTemplateInfo::kCachedPropertyNameOffset); getter, FunctionTemplateInfo::kCachedPropertyNameOffset);
GotoIfNot(IsTheHole(cached_property_name), if_bailout);
Label* has_cached_property = mode == kCallJSGetterUseCachedName
? &use_cached_property
: if_bailout;
GotoIfNot(IsTheHole(cached_property_name), has_cached_property);
TNode<NativeContext> creation_context = TNode<NativeContext> creation_context =
GetCreationContext(CAST(holder), if_bailout); GetCreationContext(CAST(holder), if_bailout);
...@@ -9743,6 +9749,14 @@ TNode<Object> CodeStubAssembler::CallGetterIfAccessor( ...@@ -9743,6 +9749,14 @@ TNode<Object> CodeStubAssembler::CallGetterIfAccessor(
receiver); receiver);
Goto(&done); Goto(&done);
if (mode == kCallJSGetterUseCachedName) {
Bind(&use_cached_property);
var_value = GetProperty(context, holder, cached_property_name);
Goto(&done);
}
BIND(&runtime); BIND(&runtime);
{ {
var_value = CallRuntime(Runtime::kGetProperty, context, holder, name, var_value = CallRuntime(Runtime::kGetProperty, context, holder, name,
...@@ -9751,6 +9765,7 @@ TNode<Object> CodeStubAssembler::CallGetterIfAccessor( ...@@ -9751,6 +9765,7 @@ TNode<Object> CodeStubAssembler::CallGetterIfAccessor(
} }
} }
} else { } else {
DCHECK_EQ(mode, kReturnAccessorPair);
Goto(&done); Goto(&done);
} }
} }
...@@ -9822,7 +9837,7 @@ void CodeStubAssembler::TryGetOwnProperty( ...@@ -9822,7 +9837,7 @@ void CodeStubAssembler::TryGetOwnProperty(
Label* if_bailout) { Label* if_bailout) {
TryGetOwnProperty(context, receiver, object, map, instance_type, unique_name, TryGetOwnProperty(context, receiver, object, map, instance_type, unique_name,
if_found_value, var_value, nullptr, nullptr, if_not_found, if_found_value, var_value, nullptr, nullptr, if_not_found,
if_bailout, kCallJSGetter); if_bailout, kCallJSGetterUseCachedName);
} }
void CodeStubAssembler::TryGetOwnProperty( void CodeStubAssembler::TryGetOwnProperty(
......
...@@ -3178,8 +3178,21 @@ class V8_EXPORT_PRIVATE CodeStubAssembler ...@@ -3178,8 +3178,21 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
Label* if_bailout); Label* if_bailout);
// Operating mode for TryGetOwnProperty and CallGetterIfAccessor // Operating mode for TryGetOwnProperty and CallGetterIfAccessor
// kReturnAccessorPair is used when we're only getting the property descriptor enum GetOwnPropertyMode {
enum GetOwnPropertyMode { kCallJSGetter, kReturnAccessorPair }; // kCallJSGetterDontUseCachedName is used when we want to get the result of
// the getter call, and don't use cached_name_property when the getter is
// the function template and it has cached_property_name, which would just
// bailout for the IC system to create a named property handler
kCallJSGetterDontUseCachedName,
// kCallJSGetterUseCachedName is used when we want to get the result of
// the getter call, and use cached_name_property when the getter is
// the function template and it has cached_property_name, which would call
// GetProperty rather than bailout for Generic/NoFeedback load
kCallJSGetterUseCachedName,
// kReturnAccessorPair is used when we're only getting the property
// descriptor
kReturnAccessorPair
};
// Tries to get {object}'s own {unique_name} property value. If the property // Tries to get {object}'s own {unique_name} property value. If the property
// is an accessor then it also calls a getter. If the property is a double // is an accessor then it also calls a getter. If the property is a double
// field it re-wraps value in an immutable heap number. {unique_name} must be // field it re-wraps value in an immutable heap number. {unique_name} must be
...@@ -3999,7 +4012,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler ...@@ -3999,7 +4012,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<Object> CallGetterIfAccessor( TNode<Object> CallGetterIfAccessor(
TNode<Object> value, TNode<HeapObject> holder, TNode<Uint32T> details, TNode<Object> value, TNode<HeapObject> holder, TNode<Uint32T> details,
TNode<Context> context, TNode<Object> receiver, TNode<Object> name, TNode<Context> context, TNode<Object> receiver, TNode<Object> name,
Label* if_bailout, GetOwnPropertyMode mode = kCallJSGetter); Label* if_bailout,
GetOwnPropertyMode mode = kCallJSGetterDontUseCachedName);
TNode<IntPtrT> TryToIntptr(TNode<Object> key, Label* if_not_intptr, TNode<IntPtrT> TryToIntptr(TNode<Object> key, Label* if_not_intptr,
TVariable<Int32T>* var_instance_type = nullptr); TVariable<Int32T>* var_instance_type = nullptr);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment