ic-dynamic-check-maps.tq 3.84 KB
Newer Older
1 2 3 4 5 6 7
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be:
// Context found in the LICENSE file.

namespace ic {

const kSuccess: constexpr int32
8
    generates 'static_cast<int>(DynamicCheckMapsStatus::kSuccess)';
9
const kBailout: constexpr int32
10
    generates 'static_cast<int>(DynamicCheckMapsStatus::kBailout)';
11
const kDeopt: constexpr int32
12
    generates 'static_cast<int>(DynamicCheckMapsStatus::kDeopt)';
13
extern macro LoadFeedbackVectorForStubWithTrampoline(): FeedbackVector;
14

15
macro PerformPolymorphicCheck(
16 17 18 19 20 21
    expectedPolymorphicArray: HeapObject, actualMap: Map,
    actualHandler: Smi|DataHandler): int32 {
  if (!Is<WeakFixedArray>(expectedPolymorphicArray)) {
    return kDeopt;
  }

22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
  const polymorphicArray = UnsafeCast<WeakFixedArray>(expectedPolymorphicArray);
  const weakActualMap = MakeWeak(actualMap);
  const length = polymorphicArray.length_intptr;
  assert(length > 0);

  for (let mapIndex: intptr = 0; mapIndex < length;
       mapIndex += FeedbackIteratorEntrySize()) {
    const maybeCachedMap =
        UnsafeCast<WeakHeapObject>(polymorphicArray[mapIndex]);
    if (maybeCachedMap == weakActualMap) {
      const handlerIndex = mapIndex + FeedbackIteratorHandlerOffset();
      assert(handlerIndex < length);
      const maybeHandler =
          Cast<Object>(polymorphicArray[handlerIndex]) otherwise unreachable;
      if (TaggedEqual(maybeHandler, actualHandler)) {
        return kSuccess;
      } else {
        return kDeopt;
      }
41 42
    }
  }
43 44

  return kBailout;
45
}
46 47

macro PerformMonomorphicCheck(
48
    feedbackVector: FeedbackVector, slotIndex: intptr, expectedMap: HeapObject,
49
    actualMap: Map, actualHandler: Smi|DataHandler): int32 {
50
  if (TaggedEqual(expectedMap, actualMap)) {
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
    const handlerIndex = slotIndex + 1;
    assert(handlerIndex < feedbackVector.length_intptr);
    const maybeHandler =
        Cast<Object>(feedbackVector[handlerIndex]) otherwise unreachable;
    if (TaggedEqual(actualHandler, maybeHandler)) {
      return kSuccess;
    }

    return kDeopt;
  }

  return kBailout;
}

// This builtin performs map checks by dynamically looking at the
// feedback in the feedback vector.
//
// There are two major cases handled by this builtin:
// (a) Monormorphic check
// (b) Polymorphic check
//
// For the monormophic check, the incoming map is migrated and checked
73
// against the map and handler in the feedback vector.
74 75 76 77 78 79
//
// For the polymorphic check, the feedback vector is iterated over and
// each of the maps & handers are compared against the incoming map and
// handler.
//
// If any of the map and associated handler checks pass then we return
80 81 82 83
// kSuccess status. If we have never seen the map before, we return kBailout
// status to bailout to the interpreter and update the feedback. If we have seen
// the map, but the associated handler check fails then we return kDeopt status.
@export
84
macro DynamicCheckMaps(
85
    actualMap: Map, slotIndex: intptr, actualHandler: Smi|DataHandler): int32 {
86
  const feedbackVector = LoadFeedbackVectorForStubWithTrampoline();
87 88 89 90 91 92 93 94
  return DynamicCheckMapsWithFeedbackVector(
      actualMap, slotIndex, actualHandler, feedbackVector);
}

@export
macro DynamicCheckMapsWithFeedbackVector(
    actualMap: Map, slotIndex: intptr, actualHandler: Smi|DataHandler,
    feedbackVector: FeedbackVector): int32 {
95 96 97 98 99 100 101
  const feedback = feedbackVector[slotIndex];
  try {
    const maybePolymorphicArray =
        GetHeapObjectIfStrong(feedback) otherwise MigrateAndDoMonomorphicCheck;
    return PerformPolymorphicCheck(
        maybePolymorphicArray, actualMap, actualHandler);
  } label MigrateAndDoMonomorphicCheck {
102
    const expectedMap = GetHeapObjectAssumeWeak(feedback) otherwise Deopt;
103
    return PerformMonomorphicCheck(
104 105 106
        feedbackVector, slotIndex, expectedMap, actualMap, actualHandler);
  } label Deopt {
    return kDeopt;
107
  }
108
}
109 110

}  // namespace ic