[ic] Completely unroll polymorphic IC map checks
Polymorphic IC feedback can contain up to four (map, handler) pairs. HandlePolymorphicCase already unrolled checks for the first two pairs; these are guaranteed to exist and can omit bound checks. This CL unrolls checks against the final two pairs as well. BUG=v8:5917 Review-Url: https://codereview.chromium.org/2728293005 Cr-Commit-Position: refs/heads/master@{#43650}
This commit is contained in:
parent
c478a2298d
commit
3c246db781
@ -8,6 +8,7 @@
|
||||
#include "src/code-stubs.h"
|
||||
#include "src/counters.h"
|
||||
#include "src/ic/handler-configuration.h"
|
||||
#include "src/ic/ic.h"
|
||||
#include "src/ic/stub-cache.h"
|
||||
#include "src/objects-inl.h"
|
||||
|
||||
@ -57,7 +58,7 @@ void AccessorAssembler::HandlePolymorphicCase(Node* receiver_map,
|
||||
Node* feedback, Label* if_handler,
|
||||
Variable* var_handler,
|
||||
Label* if_miss,
|
||||
int unroll_count) {
|
||||
int min_feedback_capacity) {
|
||||
Comment("HandlePolymorphicCase");
|
||||
DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep());
|
||||
|
||||
@ -68,14 +69,31 @@ void AccessorAssembler::HandlePolymorphicCase(Node* receiver_map,
|
||||
// Iterate {feedback} array.
|
||||
const int kEntrySize = 2;
|
||||
|
||||
for (int i = 0; i < unroll_count; i++) {
|
||||
// Loading feedback's length is delayed until we need it when looking past
|
||||
// the first {min_feedback_capacity} (map, handler) pairs.
|
||||
Node* length = nullptr;
|
||||
CSA_ASSERT(this, SmiGreaterThanOrEqual(
|
||||
LoadFixedArrayBaseLength(feedback),
|
||||
SmiConstant(min_feedback_capacity * kEntrySize)));
|
||||
|
||||
const int kUnrolledIterations = IC::kMaxPolymorphicMapCount;
|
||||
for (int i = 0; i < kUnrolledIterations; i++) {
|
||||
int map_index = i * kEntrySize;
|
||||
int handler_index = i * kEntrySize + 1;
|
||||
|
||||
if (i >= min_feedback_capacity) {
|
||||
if (length == nullptr) length = LoadFixedArrayBaseLength(feedback);
|
||||
GotoIf(SmiGreaterThanOrEqual(SmiConstant(handler_index), length),
|
||||
if_miss);
|
||||
}
|
||||
|
||||
Label next_entry(this);
|
||||
Node* cached_map =
|
||||
LoadWeakCellValue(LoadFixedArrayElement(feedback, i * kEntrySize));
|
||||
LoadWeakCellValue(LoadFixedArrayElement(feedback, map_index));
|
||||
GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry);
|
||||
|
||||
// Found, now call handler.
|
||||
Node* handler = LoadFixedArrayElement(feedback, i * kEntrySize + 1);
|
||||
Node* handler = LoadFixedArrayElement(feedback, handler_index);
|
||||
var_handler->Bind(handler);
|
||||
Goto(if_handler);
|
||||
|
||||
@ -83,12 +101,12 @@ void AccessorAssembler::HandlePolymorphicCase(Node* receiver_map,
|
||||
}
|
||||
Goto(&loop);
|
||||
|
||||
// Loop from {unroll_count}*kEntrySize to {length}.
|
||||
// Loop from {kUnrolledIterations}*kEntrySize to {length}.
|
||||
Bind(&loop);
|
||||
Node* init = IntPtrConstant(unroll_count * kEntrySize);
|
||||
Node* length = LoadAndUntagFixedArrayBaseLength(feedback);
|
||||
Node* start_index = IntPtrConstant(kUnrolledIterations * kEntrySize);
|
||||
Node* end_index = LoadAndUntagFixedArrayBaseLength(feedback);
|
||||
BuildFastLoop(
|
||||
init, length,
|
||||
start_index, end_index,
|
||||
[this, receiver_map, feedback, if_handler, var_handler](Node* index) {
|
||||
Node* cached_map =
|
||||
LoadWeakCellValue(LoadFixedArrayElement(feedback, index));
|
||||
|
@ -123,7 +123,7 @@ class AccessorAssembler : public CodeStubAssembler {
|
||||
Label* if_miss);
|
||||
void HandlePolymorphicCase(Node* receiver_map, Node* feedback,
|
||||
Label* if_handler, Variable* var_handler,
|
||||
Label* if_miss, int unroll_count);
|
||||
Label* if_miss, int min_feedback_capacity);
|
||||
void HandleKeyedStorePolymorphicCase(Node* receiver_map, Node* feedback,
|
||||
Label* if_handler, Variable* var_handler,
|
||||
Label* if_transition_handler,
|
||||
|
@ -771,7 +771,7 @@ bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Object> handler) {
|
||||
int number_of_valid_maps =
|
||||
number_of_maps - deprecated_maps - (handler_to_overwrite != -1);
|
||||
|
||||
if (number_of_valid_maps >= 4) return false;
|
||||
if (number_of_valid_maps >= kMaxPolymorphicMapCount) return false;
|
||||
if (number_of_maps == 0 && state() != MONOMORPHIC && state() != POLYMORPHIC) {
|
||||
return false;
|
||||
}
|
||||
|
@ -26,6 +26,10 @@ class IC {
|
||||
// or with a single extra frame for supporting calls.
|
||||
enum FrameDepth { NO_EXTRA_FRAME = 0, EXTRA_CALL_FRAME = 1 };
|
||||
|
||||
// A polymorphic IC can handle at most 4 distinct maps before transitioning
|
||||
// to megamorphic state.
|
||||
static constexpr int kMaxPolymorphicMapCount = 4;
|
||||
|
||||
// Construct the IC structure with the given number of extra
|
||||
// JavaScript frames on the stack.
|
||||
IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus = NULL);
|
||||
|
Loading…
Reference in New Issue
Block a user