Commit ed73693d authored by Fanchen Kong's avatar Fanchen Kong Committed by V8 LUCI CQ

Change CollectCallFeedback to take the receiver as LazyNode

This CL makes a call to CollectCallFeedback from Ignition load the receiver lazily, which may improve the performance of Octane/{Richards, Delta-Blue} with --no-opt for 1-3%.

Bug: chromium:1207349
Change-Id: I5fb09d5c5662ef8714acf71dd7341d3164b44f93
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2895358Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Commit-Queue: Fanchen Kong <fanchen.kong@intel.com>
Cr-Commit-Position: refs/heads/master@{#74580}
parent c1ea685e
...@@ -141,6 +141,7 @@ intrinsic %MakeLazy<T: type, A1: type, A2: type, A3: type>( ...@@ -141,6 +141,7 @@ intrinsic %MakeLazy<T: type, A1: type, A2: type, A3: type>(
// template, but Torque doesn't understand how to use templates for extern // template, but Torque doesn't understand how to use templates for extern
// macros, so just add whatever overload definitions you need here. // macros, so just add whatever overload definitions you need here.
extern macro RunLazy(Lazy<Smi>): Smi; extern macro RunLazy(Lazy<Smi>): Smi;
extern macro RunLazy(Lazy<JSAny>): JSAny;
// A Smi value containing a bitfield struct as its integer data. // A Smi value containing a bitfield struct as its integer data.
@useParentTypeChecker type SmiTagged<T : type extends uint31> extends Smi; @useParentTypeChecker type SmiTagged<T : type extends uint31> extends Smi;
......
...@@ -113,7 +113,8 @@ TF_BUILTIN(Call_ReceiverIsNullOrUndefined_WithFeedback, ...@@ -113,7 +113,8 @@ TF_BUILTIN(Call_ReceiverIsNullOrUndefined_WithFeedback,
auto feedback_vector = Parameter<FeedbackVector>(Descriptor::kFeedbackVector); auto feedback_vector = Parameter<FeedbackVector>(Descriptor::kFeedbackVector);
auto slot = UncheckedParameter<UintPtrT>(Descriptor::kSlot); auto slot = UncheckedParameter<UintPtrT>(Descriptor::kSlot);
auto receiver = Parameter<Object>(Descriptor::kReceiver); auto receiver = Parameter<Object>(Descriptor::kReceiver);
CollectCallFeedback(target, receiver, context, feedback_vector, slot); CollectCallFeedback(
target, [=] { return receiver; }, context, feedback_vector, slot);
TailCallBuiltin(Builtins::kCall_ReceiverIsNullOrUndefined, context, target, TailCallBuiltin(Builtins::kCall_ReceiverIsNullOrUndefined, context, target,
argc); argc);
} }
...@@ -126,7 +127,8 @@ TF_BUILTIN(Call_ReceiverIsNotNullOrUndefined_WithFeedback, ...@@ -126,7 +127,8 @@ TF_BUILTIN(Call_ReceiverIsNotNullOrUndefined_WithFeedback,
auto feedback_vector = Parameter<FeedbackVector>(Descriptor::kFeedbackVector); auto feedback_vector = Parameter<FeedbackVector>(Descriptor::kFeedbackVector);
auto slot = UncheckedParameter<UintPtrT>(Descriptor::kSlot); auto slot = UncheckedParameter<UintPtrT>(Descriptor::kSlot);
auto receiver = Parameter<Object>(Descriptor::kReceiver); auto receiver = Parameter<Object>(Descriptor::kReceiver);
CollectCallFeedback(target, receiver, context, feedback_vector, slot); CollectCallFeedback(
target, [=] { return receiver; }, context, feedback_vector, slot);
TailCallBuiltin(Builtins::kCall_ReceiverIsNotNullOrUndefined, context, target, TailCallBuiltin(Builtins::kCall_ReceiverIsNotNullOrUndefined, context, target,
argc); argc);
} }
...@@ -138,7 +140,8 @@ TF_BUILTIN(Call_ReceiverIsAny_WithFeedback, CallOrConstructBuiltinsAssembler) { ...@@ -138,7 +140,8 @@ TF_BUILTIN(Call_ReceiverIsAny_WithFeedback, CallOrConstructBuiltinsAssembler) {
auto feedback_vector = Parameter<FeedbackVector>(Descriptor::kFeedbackVector); auto feedback_vector = Parameter<FeedbackVector>(Descriptor::kFeedbackVector);
auto slot = UncheckedParameter<UintPtrT>(Descriptor::kSlot); auto slot = UncheckedParameter<UintPtrT>(Descriptor::kSlot);
auto receiver = Parameter<Object>(Descriptor::kReceiver); auto receiver = Parameter<Object>(Descriptor::kReceiver);
CollectCallFeedback(target, receiver, context, feedback_vector, slot); CollectCallFeedback(
target, [=] { return receiver; }, context, feedback_vector, slot);
TailCallBuiltin(Builtins::kCall_ReceiverIsAny, context, target, argc); TailCallBuiltin(Builtins::kCall_ReceiverIsAny, context, target, argc);
} }
...@@ -483,13 +486,15 @@ void CallOrConstructBuiltinsAssembler::CallReceiver( ...@@ -483,13 +486,15 @@ void CallOrConstructBuiltinsAssembler::CallReceiver(
auto target = Parameter<Object>(Descriptor::kFunction); auto target = Parameter<Object>(Descriptor::kFunction);
auto context = LoadContextFromBaseline(); auto context = LoadContextFromBaseline();
auto feedback_vector = LoadFeedbackVectorFromBaseline(); auto feedback_vector = LoadFeedbackVectorFromBaseline();
TNode<Object> receiver; LazyNode<Object> receiver = [=] {
if (maybe_receiver) { if (maybe_receiver) {
receiver = *maybe_receiver; return *maybe_receiver;
} else { } else {
CodeStubArguments args(this, argc); CodeStubArguments args(this, argc);
receiver = args.GetReceiver(); return args.GetReceiver();
} }
};
CollectCallFeedback(target, receiver, context, feedback_vector, slot); CollectCallFeedback(target, receiver, context, feedback_vector, slot);
TailCallBuiltin(id, context, target, argc); TailCallBuiltin(id, context, target, argc);
} }
...@@ -510,7 +515,8 @@ TF_BUILTIN(CallWithArrayLike_WithFeedback, CallOrConstructBuiltinsAssembler) { ...@@ -510,7 +515,8 @@ TF_BUILTIN(CallWithArrayLike_WithFeedback, CallOrConstructBuiltinsAssembler) {
auto feedback_vector = Parameter<FeedbackVector>(Descriptor::kFeedbackVector); auto feedback_vector = Parameter<FeedbackVector>(Descriptor::kFeedbackVector);
auto slot = UncheckedParameter<UintPtrT>(Descriptor::kSlot); auto slot = UncheckedParameter<UintPtrT>(Descriptor::kSlot);
auto receiver = Parameter<Object>(Descriptor::kReceiver); auto receiver = Parameter<Object>(Descriptor::kReceiver);
CollectCallFeedback(target, receiver, context, feedback_vector, slot); CollectCallFeedback(
target, [=] { return receiver; }, context, feedback_vector, slot);
CallOrConstructWithArrayLike(target, new_target, arguments_list, context); CallOrConstructWithArrayLike(target, new_target, arguments_list, context);
} }
...@@ -532,8 +538,9 @@ TF_BUILTIN(CallWithSpread_Baseline, CallOrConstructBuiltinsAssembler) { ...@@ -532,8 +538,9 @@ TF_BUILTIN(CallWithSpread_Baseline, CallOrConstructBuiltinsAssembler) {
auto feedback_vector = LoadFeedbackVectorFromBaseline(); auto feedback_vector = LoadFeedbackVectorFromBaseline();
auto slot = UncheckedParameter<UintPtrT>(Descriptor::kSlot); auto slot = UncheckedParameter<UintPtrT>(Descriptor::kSlot);
CodeStubArguments args(this, args_count); CodeStubArguments args(this, args_count);
auto receiver = args.GetReceiver(); CollectCallFeedback(
CollectCallFeedback(target, receiver, context, feedback_vector, slot); target, [=] { return args.GetReceiver(); }, context, feedback_vector,
slot);
CallOrConstructWithSpread(target, new_target, spread, args_count, context); CallOrConstructWithSpread(target, new_target, spread, args_count, context);
} }
...@@ -546,7 +553,8 @@ TF_BUILTIN(CallWithSpread_WithFeedback, CallOrConstructBuiltinsAssembler) { ...@@ -546,7 +553,8 @@ TF_BUILTIN(CallWithSpread_WithFeedback, CallOrConstructBuiltinsAssembler) {
auto feedback_vector = Parameter<FeedbackVector>(Descriptor::kFeedbackVector); auto feedback_vector = Parameter<FeedbackVector>(Descriptor::kFeedbackVector);
auto slot = UncheckedParameter<UintPtrT>(Descriptor::kSlot); auto slot = UncheckedParameter<UintPtrT>(Descriptor::kSlot);
auto receiver = Parameter<Object>(Descriptor::kReceiver); auto receiver = Parameter<Object>(Descriptor::kReceiver);
CollectCallFeedback(target, receiver, context, feedback_vector, slot); CollectCallFeedback(
target, [=] { return receiver; }, context, feedback_vector, slot);
CallOrConstructWithSpread(target, new_target, spread, args_count, context); CallOrConstructWithSpread(target, new_target, spread, args_count, context);
} }
......
...@@ -89,7 +89,7 @@ macro SetCallFeedbackContent(implicit context: Context)( ...@@ -89,7 +89,7 @@ macro SetCallFeedbackContent(implicit context: Context)(
} }
macro CollectCallFeedback( macro CollectCallFeedback(
maybeTarget: JSAny, maybeReceiver: JSAny, context: Context, maybeTarget: JSAny, maybeReceiver: Lazy<JSAny>, context: Context,
maybeFeedbackVector: Undefined|FeedbackVector, slotId: uintptr): void { maybeFeedbackVector: Undefined|FeedbackVector, slotId: uintptr): void {
// TODO(v8:9891): Remove this assert once all callers are ported to Torque. // TODO(v8:9891): Remove this assert once all callers are ported to Torque.
// This assert ensures correctness of maybeFeedbackVector's type which can // This assert ensures correctness of maybeFeedbackVector's type which can
...@@ -112,7 +112,7 @@ macro CollectCallFeedback( ...@@ -112,7 +112,7 @@ macro CollectCallFeedback(
TaggedEqualPrototypeApplyFunction(maybeTarget)) { TaggedEqualPrototypeApplyFunction(maybeTarget)) {
// If the Receiver is recorded and the target is Function.prototype.apply, // If the Receiver is recorded and the target is Function.prototype.apply,
// check whether we can stay monomorphic based on the receiver. // check whether we can stay monomorphic based on the receiver.
if (IsMonomorphic(feedback, maybeReceiver)) { if (IsMonomorphic(feedback, RunLazy(maybeReceiver))) {
return; return;
} else { } else {
// If not, reinitialize the feedback with target. // If not, reinitialize the feedback with target.
...@@ -149,7 +149,7 @@ macro CollectCallFeedback( ...@@ -149,7 +149,7 @@ macro CollectCallFeedback(
} label TryInitializeAsMonomorphic { } label TryInitializeAsMonomorphic {
let recordedFunction = maybeTarget; let recordedFunction = maybeTarget;
if (TaggedEqualPrototypeApplyFunction(maybeTarget)) { if (TaggedEqualPrototypeApplyFunction(maybeTarget)) {
recordedFunction = maybeReceiver; recordedFunction = RunLazy(maybeReceiver);
SetCallFeedbackContent( SetCallFeedbackContent(
feedbackVector, slotId, CallFeedbackContent::kReceiver); feedbackVector, slotId, CallFeedbackContent::kReceiver);
} else { } else {
......
...@@ -8,7 +8,7 @@ namespace ic { ...@@ -8,7 +8,7 @@ namespace ic {
@export @export
macro CollectCallFeedback( macro CollectCallFeedback(
maybeTarget: JSAny, maybeReceiver: JSAny, context: Context, maybeTarget: JSAny, maybeReceiver: Lazy<JSAny>, context: Context,
maybeFeedbackVector: Undefined|FeedbackVector, slotId: uintptr): void { maybeFeedbackVector: Undefined|FeedbackVector, slotId: uintptr): void {
callable::CollectCallFeedback( callable::CollectCallFeedback(
maybeTarget, maybeReceiver, context, maybeFeedbackVector, slotId); maybeTarget, maybeReceiver, context, maybeFeedbackVector, slotId);
......
...@@ -97,13 +97,18 @@ transitioning builtin CreateAsyncFromSyncIteratorBaseline(syncIterator: JSAny): ...@@ -97,13 +97,18 @@ transitioning builtin CreateAsyncFromSyncIteratorBaseline(syncIterator: JSAny):
return CreateAsyncFromSyncIterator(context, syncIterator); return CreateAsyncFromSyncIterator(context, syncIterator);
} }
macro GetLazyReceiver(receiver: JSAny): JSAny {
return receiver;
}
transitioning builtin CallIteratorWithFeedback( transitioning builtin CallIteratorWithFeedback(
context: Context, receiver: JSAny, iteratorMethod: JSAny, callSlot: Smi, context: Context, receiver: JSAny, iteratorMethod: JSAny, callSlot: Smi,
feedback: Undefined|FeedbackVector): JSAny { feedback: Undefined|FeedbackVector): JSAny {
// TODO(v8:10047): Use TaggedIndex here once TurboFan supports it. // TODO(v8:10047): Use TaggedIndex here once TurboFan supports it.
const callSlotUnTagged: uintptr = Unsigned(SmiUntag(callSlot)); const callSlotUnTagged: uintptr = Unsigned(SmiUntag(callSlot));
ic::CollectCallFeedback( ic::CollectCallFeedback(
iteratorMethod, receiver, context, feedback, callSlotUnTagged); iteratorMethod, %MakeLazy<JSAny, JSAny>('GetLazyReceiver', receiver),
context, feedback, callSlotUnTagged);
const iteratorCallable: Callable = Cast<Callable>(iteratorMethod) const iteratorCallable: Callable = Cast<Callable>(iteratorMethod)
otherwise ThrowCalledNonCallable(iteratorMethod); otherwise ThrowCalledNonCallable(iteratorMethod);
return Call(context, iteratorCallable, receiver); return Call(context, iteratorCallable, receiver);
......
...@@ -803,7 +803,7 @@ void InterpreterAssembler::CallJSWithSpreadAndDispatch( ...@@ -803,7 +803,7 @@ void InterpreterAssembler::CallJSWithSpreadAndDispatch(
TNode<UintPtrT> slot_id, TNode<HeapObject> maybe_feedback_vector) { TNode<UintPtrT> slot_id, TNode<HeapObject> maybe_feedback_vector) {
DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_)); DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_));
DCHECK_EQ(Bytecodes::GetReceiverMode(bytecode_), ConvertReceiverMode::kAny); DCHECK_EQ(Bytecodes::GetReceiverMode(bytecode_), ConvertReceiverMode::kAny);
TNode<Object> receiver = LoadRegisterAtOperandIndex(1); LazyNode<Object> receiver = [=] { return LoadRegisterAtOperandIndex(1); };
CollectCallFeedback(function, receiver, context, maybe_feedback_vector, CollectCallFeedback(function, receiver, context, maybe_feedback_vector,
slot_id); slot_id);
Comment("call using CallWithSpread builtin"); Comment("call using CallWithSpread builtin");
......
...@@ -1365,10 +1365,11 @@ class InterpreterJSCallAssembler : public InterpreterAssembler { ...@@ -1365,10 +1365,11 @@ class InterpreterJSCallAssembler : public InterpreterAssembler {
// Generates code to perform a JS call that collects type feedback. // Generates code to perform a JS call that collects type feedback.
void JSCall(ConvertReceiverMode receiver_mode) { void JSCall(ConvertReceiverMode receiver_mode) {
TNode<Object> function = LoadRegisterAtOperandIndex(0); TNode<Object> function = LoadRegisterAtOperandIndex(0);
TNode<Object> receiver = LazyNode<Object> receiver = [=] {
receiver_mode == ConvertReceiverMode::kNullOrUndefined return receiver_mode == ConvertReceiverMode::kNullOrUndefined
? UndefinedConstant() ? UndefinedConstant()
: LoadRegisterAtOperandIndex(1); : LoadRegisterAtOperandIndex(1);
};
RegListNodePair args = GetRegisterListAtOperandIndex(1); RegListNodePair args = GetRegisterListAtOperandIndex(1);
TNode<UintPtrT> slot_id = BytecodeOperandIdx(3); TNode<UintPtrT> slot_id = BytecodeOperandIdx(3);
TNode<HeapObject> maybe_feedback_vector = LoadFeedbackVector(); TNode<HeapObject> maybe_feedback_vector = LoadFeedbackVector();
...@@ -1404,10 +1405,11 @@ class InterpreterJSCallAssembler : public InterpreterAssembler { ...@@ -1404,10 +1405,11 @@ class InterpreterJSCallAssembler : public InterpreterAssembler {
kFirstArgumentOperandIndex + kReceiverAndArgOperandCount; kFirstArgumentOperandIndex + kReceiverAndArgOperandCount;
TNode<Object> function = LoadRegisterAtOperandIndex(0); TNode<Object> function = LoadRegisterAtOperandIndex(0);
TNode<Object> receiver = LazyNode<Object> receiver = [=] {
receiver_mode == ConvertReceiverMode::kNullOrUndefined return receiver_mode == ConvertReceiverMode::kNullOrUndefined
? UndefinedConstant() ? UndefinedConstant()
: LoadRegisterAtOperandIndex(1); : LoadRegisterAtOperandIndex(1);
};
TNode<UintPtrT> slot_id = BytecodeOperandIdx(kSlotOperandIndex); TNode<UintPtrT> slot_id = BytecodeOperandIdx(kSlotOperandIndex);
TNode<HeapObject> maybe_feedback_vector = LoadFeedbackVector(); TNode<HeapObject> maybe_feedback_vector = LoadFeedbackVector();
TNode<Context> context = GetContext(); TNode<Context> context = GetContext();
......
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