| // 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 |
| generates 'static_cast<int>(DynamicCheckMapsStatus::kSuccess)'; |
| const kBailout: constexpr int32 |
| generates 'static_cast<int>(DynamicCheckMapsStatus::kBailout)'; |
| const kDeopt: constexpr int32 |
| generates 'static_cast<int>(DynamicCheckMapsStatus::kDeopt)'; |
| extern macro LoadFeedbackVectorForStubWithTrampoline(): FeedbackVector; |
| |
| macro PerformPolymorphicCheck( |
| expectedPolymorphicArray: HeapObject, actualMap: Map, |
| actualHandler: Smi|DataHandler): int32 { |
| if (!Is<WeakFixedArray>(expectedPolymorphicArray)) { |
| return kDeopt; |
| } |
| |
| 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; |
| } |
| } |
| } |
| |
| return kBailout; |
| } |
| |
| macro PerformMonomorphicCheck( |
| feedbackVector: FeedbackVector, slotIndex: intptr, expectedMap: HeapObject, |
| actualMap: Map, actualHandler: Smi|DataHandler): int32 { |
| if (TaggedEqual(expectedMap, actualMap)) { |
| 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 |
| // against the map and handler in the feedback vector. |
| // |
| // 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 |
| // 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 |
| macro DynamicCheckMaps( |
| actualMap: Map, slotIndex: intptr, actualHandler: Smi|DataHandler): int32 { |
| const feedbackVector = LoadFeedbackVectorForStubWithTrampoline(); |
| return DynamicCheckMapsWithFeedbackVector( |
| actualMap, slotIndex, actualHandler, feedbackVector); |
| } |
| |
| @export |
| macro DynamicCheckMapsWithFeedbackVector( |
| actualMap: Map, slotIndex: intptr, actualHandler: Smi|DataHandler, |
| feedbackVector: FeedbackVector): int32 { |
| const feedback = feedbackVector[slotIndex]; |
| try { |
| const maybePolymorphicArray = |
| GetHeapObjectIfStrong(feedback) otherwise MigrateAndDoMonomorphicCheck; |
| return PerformPolymorphicCheck( |
| maybePolymorphicArray, actualMap, actualHandler); |
| } label MigrateAndDoMonomorphicCheck { |
| const expectedMap = GetHeapObjectAssumeWeak(feedback) otherwise Deopt; |
| return PerformMonomorphicCheck( |
| feedbackVector, slotIndex, expectedMap, actualMap, actualHandler); |
| } label Deopt { |
| return kDeopt; |
| } |
| } |
| |
| } // namespace ic |