diff options
Diffstat (limited to 'chromium/v8/src/builtins/ic-callable.tq')
-rw-r--r-- | chromium/v8/src/builtins/ic-callable.tq | 73 |
1 files changed, 70 insertions, 3 deletions
diff --git a/chromium/v8/src/builtins/ic-callable.tq b/chromium/v8/src/builtins/ic-callable.tq index 85525c4c683..dd29e8bf5e2 100644 --- a/chromium/v8/src/builtins/ic-callable.tq +++ b/chromium/v8/src/builtins/ic-callable.tq @@ -6,6 +6,10 @@ namespace ic { namespace callable { extern macro IncrementCallCount(FeedbackVector, uintptr): void; +const kCallFeedbackContentFieldMask: constexpr int32 + generates 'FeedbackNexus::CallFeedbackContentField::kMask'; +const kCallFeedbackContentFieldShift: constexpr uint32 + generates 'FeedbackNexus::CallFeedbackContentField::kShift'; macro IsMonomorphic(feedback: MaybeObject, target: JSAny): bool { return IsWeakReferenceToObject(feedback, target); @@ -50,8 +54,42 @@ macro TransitionToMegamorphic(implicit context: Context)( ReportFeedbackUpdate(feedbackVector, slotId, 'Call:TransitionMegamorphic'); } +macro TaggedEqualPrototypeApplyFunction(implicit context: Context)( + target: JSAny): bool { + return TaggedEqual(target, GetPrototypeApplyFunction()); +} + +macro FeedbackValueIsReceiver(implicit context: Context)( + feedbackVector: FeedbackVector, slotId: uintptr): bool { + const callCount: intptr = SmiUntag(Cast<Smi>(LoadFeedbackVectorSlot( + feedbackVector, slotId, kTaggedSize)) otherwise return false); + return (callCount & IntPtrConstant(kCallFeedbackContentFieldMask)) != + IntPtrConstant(0); +} + +macro SetCallFeedbackContent(implicit context: Context)( + feedbackVector: FeedbackVector, slotId: uintptr, + callFeedbackContent: constexpr CallFeedbackContent): void { + // Load the call count field from the feecback vector. + const callCount: intptr = SmiUntag(Cast<Smi>(LoadFeedbackVectorSlot( + feedbackVector, slotId, kTaggedSize)) otherwise return ); + // The second lowest bits of the call count are used to state whether the + // feedback collected is a target or a receiver. Change that bit based on the + // callFeedbackContent input. + const callFeedbackContentFieldMask: intptr = + ~IntPtrConstant(kCallFeedbackContentFieldMask); + const newCount: intptr = (callCount & callFeedbackContentFieldMask) | + Convert<intptr>(Signed( + %RawConstexprCast<constexpr uint32>(callFeedbackContent) + << kCallFeedbackContentFieldShift)); + StoreFeedbackVectorSlot( + feedbackVector, slotId, SmiTag(newCount), SKIP_WRITE_BARRIER, + kTaggedSize); + ReportFeedbackUpdate(feedbackVector, slotId, 'Call:SetCallFeedbackContent'); +} + macro CollectCallFeedback( - maybeTarget: 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 @@ -72,7 +110,24 @@ macro CollectCallFeedback( // If cleared, we have a new chance to become monomorphic. const feedbackValue: HeapObject = - MaybeObjectToStrong(feedback) otherwise TryInitializeAsMonomorphic; + MaybeObjectToStrong(feedback) otherwise TryReinitializeAsMonomorphic; + + if (FeedbackValueIsReceiver(feedbackVector, slotId) && + 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, RunLazy(maybeReceiver))) { + return; + } else { + // If not, reinitialize the feedback with target. + SetCallFeedbackContent( + feedbackVector, slotId, CallFeedbackContent::kTarget); + TryInitializeAsMonomorphic(maybeTarget, feedbackVector, slotId) + otherwise TransitionToMegamorphic; + return; + } + } // Try transitioning to a feedback cell. // Check if {target}s feedback cell matches the {feedbackValue}. @@ -92,8 +147,20 @@ macro CollectCallFeedback( StoreWeakReferenceInFeedbackVector(feedbackVector, slotId, feedbackCell); ReportFeedbackUpdate(feedbackVector, slotId, 'Call:FeedbackVectorCell'); + } label TryReinitializeAsMonomorphic { + SetCallFeedbackContent( + feedbackVector, slotId, CallFeedbackContent::kTarget); + goto TryInitializeAsMonomorphic; } label TryInitializeAsMonomorphic { - TryInitializeAsMonomorphic(maybeTarget, feedbackVector, slotId) + let recordedFunction = maybeTarget; + if (TaggedEqualPrototypeApplyFunction(maybeTarget)) { + recordedFunction = RunLazy(maybeReceiver); + SetCallFeedbackContent( + feedbackVector, slotId, CallFeedbackContent::kReceiver); + } else { + assert(!FeedbackValueIsReceiver(feedbackVector, slotId)); + } + TryInitializeAsMonomorphic(recordedFunction, feedbackVector, slotId) otherwise TransitionToMegamorphic; } label TransitionToMegamorphic { TransitionToMegamorphic(feedbackVector, slotId); |