summaryrefslogtreecommitdiff
path: root/chromium/v8/src/builtins/ic-callable.tq
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/v8/src/builtins/ic-callable.tq')
-rw-r--r--chromium/v8/src/builtins/ic-callable.tq73
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);