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