Vector ICs: Adapting store ic classes for vectors.
BUG= Review URL: https://codereview.chromium.org/1326483002 Cr-Commit-Position: refs/heads/master@{#30512}
This commit is contained in:
parent
390853482b
commit
e1b46f7a18
@ -49,5 +49,25 @@ Register* PropertyAccessCompiler::GetCallingConvention(Code::Kind kind) {
|
||||
DCHECK(kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC);
|
||||
return store_calling_convention();
|
||||
}
|
||||
|
||||
|
||||
Register PropertyAccessCompiler::slot() const {
|
||||
if (kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC) {
|
||||
return LoadDescriptor::SlotRegister();
|
||||
}
|
||||
DCHECK(FLAG_vector_stores &&
|
||||
(kind() == Code::STORE_IC || kind() == Code::KEYED_STORE_IC));
|
||||
return VectorStoreICDescriptor::SlotRegister();
|
||||
}
|
||||
|
||||
|
||||
Register PropertyAccessCompiler::vector() const {
|
||||
if (kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC) {
|
||||
return LoadWithVectorDescriptor::VectorRegister();
|
||||
}
|
||||
DCHECK(FLAG_vector_stores &&
|
||||
(kind() == Code::STORE_IC || kind() == Code::KEYED_STORE_IC));
|
||||
return VectorStoreICDescriptor::VectorRegister();
|
||||
}
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -54,8 +54,8 @@ class PropertyAccessCompiler BASE_EMBEDDED {
|
||||
|
||||
Register receiver() const { return registers_[0]; }
|
||||
Register name() const { return registers_[1]; }
|
||||
Register slot() const { return LoadDescriptor::SlotRegister(); }
|
||||
Register vector() const { return LoadWithVectorDescriptor::VectorRegister(); }
|
||||
Register slot() const;
|
||||
Register vector() const;
|
||||
Register scratch1() const { return registers_[2]; }
|
||||
Register scratch2() const { return registers_[3]; }
|
||||
Register scratch3() const { return registers_[4]; }
|
||||
|
@ -424,6 +424,8 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition(
|
||||
Handle<Map> transition, Handle<Name> name) {
|
||||
Label miss;
|
||||
|
||||
if (FLAG_vector_stores) PushVectorAndSlot();
|
||||
|
||||
// Check that we are allowed to write this.
|
||||
bool is_nonexistent = holder()->map() == transition->GetBackPointer();
|
||||
if (is_nonexistent) {
|
||||
@ -454,16 +456,19 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition(
|
||||
DCHECK(!transition->is_access_check_needed());
|
||||
|
||||
// Call to respective StoreTransitionStub.
|
||||
Register transition_map_reg = StoreTransitionDescriptor::MapRegister();
|
||||
bool push_map_on_stack = transition_map_reg.is(no_reg);
|
||||
Register map_reg = push_map_on_stack ? scratch1() : transition_map_reg;
|
||||
Register transition_map_reg = StoreTransitionHelper::MapRegister();
|
||||
bool stack_args = StoreTransitionHelper::UsesStackArgs();
|
||||
Register map_reg = stack_args ? scratch1() : transition_map_reg;
|
||||
|
||||
if (details.type() == DATA_CONSTANT) {
|
||||
DCHECK(descriptors->GetValue(descriptor)->IsJSFunction());
|
||||
GenerateRestoreMap(transition, map_reg, scratch2(), &miss);
|
||||
GenerateConstantCheck(map_reg, descriptor, value(), scratch2(), &miss);
|
||||
if (push_map_on_stack) {
|
||||
if (stack_args) {
|
||||
// Also pushes vector and slot.
|
||||
GeneratePushMap(map_reg, scratch2());
|
||||
} else if (FLAG_vector_stores) {
|
||||
PopVectorAndSlot();
|
||||
}
|
||||
GenerateRestoreName(name);
|
||||
StoreTransitionStub stub(isolate());
|
||||
@ -480,8 +485,11 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition(
|
||||
: StoreTransitionStub::StoreMapAndValue;
|
||||
|
||||
GenerateRestoreMap(transition, map_reg, scratch2(), &miss);
|
||||
if (push_map_on_stack) {
|
||||
if (stack_args) {
|
||||
// Also pushes vector and slot.
|
||||
GeneratePushMap(map_reg, scratch2());
|
||||
} else if (FLAG_vector_stores) {
|
||||
PopVectorAndSlot();
|
||||
}
|
||||
GenerateRestoreName(name);
|
||||
StoreTransitionStub stub(isolate(),
|
||||
@ -491,21 +499,37 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition(
|
||||
}
|
||||
|
||||
GenerateRestoreName(&miss, name);
|
||||
if (FLAG_vector_stores) PopVectorAndSlot();
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
|
||||
return GetCode(kind(), Code::FAST, name);
|
||||
}
|
||||
|
||||
|
||||
bool NamedStoreHandlerCompiler::RequiresFieldTypeChecks(
|
||||
HeapType* field_type) const {
|
||||
return !field_type->Classes().Done();
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> NamedStoreHandlerCompiler::CompileStoreField(LookupIterator* it) {
|
||||
Label miss;
|
||||
DCHECK(it->representation().IsHeapObject());
|
||||
|
||||
GenerateFieldTypeChecks(*it->GetFieldType(), value(), &miss);
|
||||
HeapType* field_type = *it->GetFieldType();
|
||||
bool need_save_restore = false;
|
||||
if (RequiresFieldTypeChecks(field_type)) {
|
||||
need_save_restore = IC::ICUseVector(kind());
|
||||
if (need_save_restore) PushVectorAndSlot();
|
||||
GenerateFieldTypeChecks(field_type, value(), &miss);
|
||||
if (need_save_restore) PopVectorAndSlot();
|
||||
}
|
||||
|
||||
StoreFieldStub stub(isolate(), it->GetFieldIndex(), it->representation());
|
||||
GenerateTailCall(masm(), stub.GetCode());
|
||||
|
||||
__ bind(&miss);
|
||||
if (need_save_restore) PopVectorAndSlot();
|
||||
TailCallBuiltin(masm(), MissBuiltin(kind()));
|
||||
return GetCode(kind(), Code::FAST, it->name());
|
||||
}
|
||||
|
@ -262,6 +262,7 @@ class NamedStoreHandlerCompiler : public PropertyHandlerCompiler {
|
||||
Register value_reg, Register scratch,
|
||||
Label* miss_label);
|
||||
|
||||
bool RequiresFieldTypeChecks(HeapType* field_type) const;
|
||||
void GenerateFieldTypeChecks(HeapType* field_type, Register value_reg,
|
||||
Label* miss_label);
|
||||
|
||||
|
@ -119,6 +119,25 @@ Handle<Code> PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler(
|
||||
Handle<Map> receiver_map, LanguageMode language_mode,
|
||||
KeyedAccessStoreMode store_mode) {
|
||||
Isolate* isolate = receiver_map->GetIsolate();
|
||||
ExtraICState extra_state =
|
||||
KeyedStoreIC::ComputeExtraICState(language_mode, store_mode);
|
||||
|
||||
DCHECK(store_mode == STANDARD_STORE ||
|
||||
store_mode == STORE_AND_GROW_NO_TRANSITION ||
|
||||
store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
|
||||
store_mode == STORE_NO_TRANSITION_HANDLE_COW);
|
||||
|
||||
PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state);
|
||||
Handle<Code> code =
|
||||
compiler.CompileKeyedStoreMonomorphicHandler(receiver_map, store_mode);
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> PropertyICCompiler::ComputeKeyedStoreMonomorphic(
|
||||
Handle<Map> receiver_map, LanguageMode language_mode,
|
||||
KeyedAccessStoreMode store_mode) {
|
||||
@ -220,31 +239,6 @@ Handle<Code> PropertyICCompiler::ComputeCompareNil(Handle<Map> receiver_map,
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> PropertyICCompiler::ComputeKeyedLoadPolymorphic(
|
||||
MapHandleList* receiver_maps, LanguageMode language_mode) {
|
||||
Isolate* isolate = receiver_maps->at(0)->GetIsolate();
|
||||
DCHECK(KeyedLoadIC::GetKeyType(kNoExtraICState) == ELEMENT);
|
||||
Code::Flags flags = Code::ComputeFlags(Code::KEYED_LOAD_IC, POLYMORPHIC);
|
||||
Handle<PolymorphicCodeCache> cache =
|
||||
isolate->factory()->polymorphic_code_cache();
|
||||
Handle<Object> probe = cache->Lookup(receiver_maps, flags);
|
||||
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||
|
||||
CodeHandleList handlers(receiver_maps->length());
|
||||
ElementHandlerCompiler compiler(isolate);
|
||||
compiler.CompileElementHandlers(receiver_maps, &handlers, language_mode);
|
||||
PropertyICCompiler ic_compiler(isolate, Code::KEYED_LOAD_IC);
|
||||
Handle<Code> code = ic_compiler.CompilePolymorphic(
|
||||
receiver_maps, &handlers, isolate->factory()->empty_string(),
|
||||
Code::NORMAL, ELEMENT);
|
||||
|
||||
isolate->counters()->keyed_load_polymorphic_stubs()->Increment();
|
||||
|
||||
PolymorphicCodeCache::Update(cache, receiver_maps, flags, code);
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> PropertyICCompiler::ComputePolymorphic(
|
||||
Code::Kind kind, MapHandleList* maps, CodeHandleList* handlers,
|
||||
int valid_maps, Handle<Name> name, ExtraICState extra_ic_state) {
|
||||
@ -256,6 +250,23 @@ Handle<Code> PropertyICCompiler::ComputePolymorphic(
|
||||
}
|
||||
|
||||
|
||||
void PropertyICCompiler::ComputeKeyedStorePolymorphicHandlers(
|
||||
MapHandleList* receiver_maps, MapHandleList* transitioned_maps,
|
||||
CodeHandleList* handlers, KeyedAccessStoreMode store_mode,
|
||||
LanguageMode language_mode) {
|
||||
Isolate* isolate = receiver_maps->at(0)->GetIsolate();
|
||||
DCHECK(store_mode == STANDARD_STORE ||
|
||||
store_mode == STORE_AND_GROW_NO_TRANSITION ||
|
||||
store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
|
||||
store_mode == STORE_NO_TRANSITION_HANDLE_COW);
|
||||
ExtraICState extra_state =
|
||||
KeyedStoreIC::ComputeExtraICState(language_mode, store_mode);
|
||||
PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state);
|
||||
compiler.CompileKeyedStorePolymorphicHandlers(
|
||||
receiver_maps, transitioned_maps, handlers, store_mode);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> PropertyICCompiler::ComputeKeyedStorePolymorphic(
|
||||
MapHandleList* receiver_maps, KeyedAccessStoreMode store_mode,
|
||||
LanguageMode language_mode) {
|
||||
@ -338,11 +349,9 @@ Handle<Code> PropertyICCompiler::GetCode(Code::Kind kind, Code::StubType type,
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic(
|
||||
MapHandleList* receiver_maps, KeyedAccessStoreMode store_mode) {
|
||||
// Collect MONOMORPHIC stubs for all |receiver_maps|.
|
||||
CodeHandleList handlers(receiver_maps->length());
|
||||
MapHandleList transitioned_maps(receiver_maps->length());
|
||||
void PropertyICCompiler::CompileKeyedStorePolymorphicHandlers(
|
||||
MapHandleList* receiver_maps, MapHandleList* transitioned_maps,
|
||||
CodeHandleList* handlers, KeyedAccessStoreMode store_mode) {
|
||||
for (int i = 0; i < receiver_maps->length(); ++i) {
|
||||
Handle<Map> receiver_map(receiver_maps->at(i));
|
||||
Handle<Code> cached_stub;
|
||||
@ -379,9 +388,19 @@ Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic(
|
||||
}
|
||||
}
|
||||
DCHECK(!cached_stub.is_null());
|
||||
handlers.Add(cached_stub);
|
||||
transitioned_maps.Add(transitioned_map);
|
||||
handlers->Add(cached_stub);
|
||||
transitioned_maps->Add(transitioned_map);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic(
|
||||
MapHandleList* receiver_maps, KeyedAccessStoreMode store_mode) {
|
||||
// Collect MONOMORPHIC stubs for all |receiver_maps|.
|
||||
CodeHandleList handlers(receiver_maps->length());
|
||||
MapHandleList transitioned_maps(receiver_maps->length());
|
||||
CompileKeyedStorePolymorphicHandlers(receiver_maps, &transitioned_maps,
|
||||
&handlers, store_mode);
|
||||
|
||||
Handle<Code> code = CompileKeyedStorePolymorphic(receiver_maps, &handlers,
|
||||
&transitioned_maps);
|
||||
@ -394,7 +413,7 @@ Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic(
|
||||
#define __ ACCESS_MASM(masm())
|
||||
|
||||
|
||||
Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphic(
|
||||
Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphicHandler(
|
||||
Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) {
|
||||
ElementsKind elements_kind = receiver_map->elements_kind();
|
||||
bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
|
||||
@ -408,6 +427,14 @@ Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphic(
|
||||
} else {
|
||||
stub = StoreElementStub(isolate(), elements_kind, store_mode).GetCode();
|
||||
}
|
||||
return stub;
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphic(
|
||||
Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) {
|
||||
Handle<Code> stub =
|
||||
CompileKeyedStoreMonomorphicHandler(receiver_map, store_mode);
|
||||
|
||||
Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
|
||||
|
||||
|
@ -34,11 +34,16 @@ class PropertyICCompiler : public PropertyAccessCompiler {
|
||||
static Handle<Code> ComputeKeyedLoadMonomorphicHandler(
|
||||
Handle<Map> receiver_map, ExtraICState extra_ic_state);
|
||||
|
||||
static Handle<Code> ComputeKeyedStoreMonomorphicHandler(
|
||||
Handle<Map> receiver_map, LanguageMode language_mode,
|
||||
KeyedAccessStoreMode store_mode);
|
||||
static Handle<Code> ComputeKeyedStoreMonomorphic(
|
||||
Handle<Map> receiver_map, LanguageMode language_mode,
|
||||
KeyedAccessStoreMode store_mode);
|
||||
static Handle<Code> ComputeKeyedLoadPolymorphic(MapHandleList* receiver_maps,
|
||||
LanguageMode language_mode);
|
||||
static void ComputeKeyedStorePolymorphicHandlers(
|
||||
MapHandleList* receiver_maps, MapHandleList* transitioned_maps,
|
||||
CodeHandleList* handlers, KeyedAccessStoreMode store_mode,
|
||||
LanguageMode language_mode);
|
||||
static Handle<Code> ComputeKeyedStorePolymorphic(
|
||||
MapHandleList* receiver_maps, KeyedAccessStoreMode store_mode,
|
||||
LanguageMode language_mode);
|
||||
@ -78,10 +83,16 @@ class PropertyICCompiler : public PropertyAccessCompiler {
|
||||
Handle<Name> name, Code::StubType type,
|
||||
IcCheckType check);
|
||||
|
||||
Handle<Code> CompileKeyedStoreMonomorphicHandler(
|
||||
Handle<Map> receiver_map, KeyedAccessStoreMode store_mode);
|
||||
Handle<Code> CompileKeyedStoreMonomorphic(Handle<Map> receiver_map,
|
||||
KeyedAccessStoreMode store_mode);
|
||||
Handle<Code> CompileKeyedStorePolymorphic(MapHandleList* receiver_maps,
|
||||
KeyedAccessStoreMode store_mode);
|
||||
void CompileKeyedStorePolymorphicHandlers(MapHandleList* receiver_maps,
|
||||
MapHandleList* transitioned_maps,
|
||||
CodeHandleList* handlers,
|
||||
KeyedAccessStoreMode store_mode);
|
||||
Handle<Code> CompileKeyedStorePolymorphic(MapHandleList* receiver_maps,
|
||||
CodeHandleList* handler_stubs,
|
||||
MapHandleList* transitioned_maps);
|
||||
|
113
src/ic/ic.cc
113
src/ic/ic.cc
@ -123,8 +123,11 @@ void IC::TraceIC(const char* type, Handle<Object> name, State old_state,
|
||||
ExtraICState extra_state = new_target->extra_ic_state();
|
||||
const char* modifier = "";
|
||||
if (new_target->kind() == Code::KEYED_STORE_IC) {
|
||||
modifier = GetTransitionMarkModifier(
|
||||
KeyedStoreIC::GetKeyedAccessStoreMode(extra_state));
|
||||
KeyedAccessStoreMode mode =
|
||||
FLAG_vector_stores
|
||||
? casted_nexus<KeyedStoreICNexus>()->GetKeyedAccessStoreMode()
|
||||
: KeyedStoreIC::GetKeyedAccessStoreMode(extra_state);
|
||||
modifier = GetTransitionMarkModifier(mode);
|
||||
}
|
||||
PrintF(" (%c->%c%s) ", TransitionMarkFromState(old_state),
|
||||
TransitionMarkFromState(new_state), modifier);
|
||||
@ -666,6 +669,20 @@ void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps,
|
||||
}
|
||||
|
||||
|
||||
void IC::ConfigureVectorState(MapHandleList* maps,
|
||||
MapHandleList* transitioned_maps,
|
||||
CodeHandleList* handlers) {
|
||||
DCHECK(UseVector());
|
||||
DCHECK(kind() == Code::KEYED_STORE_IC);
|
||||
KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>();
|
||||
nexus->ConfigurePolymorphic(maps, transitioned_maps, handlers);
|
||||
|
||||
vector_set_ = true;
|
||||
OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(),
|
||||
POLYMORPHIC);
|
||||
}
|
||||
|
||||
|
||||
MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) {
|
||||
// If the object is undefined or null it's illegal to try to get any
|
||||
// of its properties; throw a TypeError in that case.
|
||||
@ -967,7 +984,7 @@ static Handle<Code> KeyedStoreICInitializeStubHelper(
|
||||
Handle<Code> KeyedStoreIC::initialize_stub(Isolate* isolate,
|
||||
LanguageMode language_mode,
|
||||
State initialization_state) {
|
||||
if (FLAG_vector_stores) {
|
||||
if (FLAG_vector_stores && initialization_state != MEGAMORPHIC) {
|
||||
VectorKeyedStoreICTrampolineStub stub(isolate, StoreICState(language_mode));
|
||||
return stub.GetCode();
|
||||
}
|
||||
@ -989,6 +1006,13 @@ Handle<Code> KeyedStoreIC::initialize_stub_in_optimized_code(
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> KeyedStoreIC::ChooseMegamorphicStub(Isolate* isolate,
|
||||
ExtraICState extra_state) {
|
||||
LanguageMode mode = StoreICState::GetLanguageMode(extra_state);
|
||||
return KeyedStoreICInitializeStubHelper(isolate, mode, MEGAMORPHIC);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> LoadIC::megamorphic_stub() {
|
||||
DCHECK_EQ(Code::KEYED_LOAD_IC, kind());
|
||||
return KeyedLoadIC::ChooseMegamorphicStub(isolate(), extra_ic_state());
|
||||
@ -1854,6 +1878,7 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
|
||||
|
||||
Handle<Code> KeyedStoreIC::StoreElementStub(Handle<Map> receiver_map,
|
||||
KeyedAccessStoreMode store_mode) {
|
||||
Handle<Code> null_handle;
|
||||
// Don't handle megamorphic property accesses for INTERCEPTORS or
|
||||
// ACCESSOR_CONSTANT
|
||||
// via megamorphic stubs, since they don't have a map in their relocation info
|
||||
@ -1869,6 +1894,13 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<Map> receiver_map,
|
||||
Handle<Map> monomorphic_map =
|
||||
ComputeTransitionedMap(receiver_map, store_mode);
|
||||
store_mode = GetNonTransitioningStoreMode(store_mode);
|
||||
if (FLAG_vector_stores) {
|
||||
Handle<Code> handler =
|
||||
PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler(
|
||||
monomorphic_map, language_mode(), store_mode);
|
||||
ConfigureVectorState(Handle<Name>::null(), monomorphic_map, handler);
|
||||
return null_handle;
|
||||
}
|
||||
return PropertyICCompiler::ComputeKeyedStoreMonomorphic(
|
||||
monomorphic_map, language_mode(), store_mode);
|
||||
}
|
||||
@ -1878,7 +1910,9 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<Map> receiver_map,
|
||||
// superset of the original IC. Handle those here if the receiver map hasn't
|
||||
// changed or it has transitioned to a more general kind.
|
||||
KeyedAccessStoreMode old_store_mode =
|
||||
KeyedStoreIC::GetKeyedAccessStoreMode(target()->extra_ic_state());
|
||||
FLAG_vector_stores
|
||||
? GetKeyedAccessStoreMode()
|
||||
: KeyedStoreIC::GetKeyedAccessStoreMode(target()->extra_ic_state());
|
||||
Handle<Map> previous_receiver_map = target_receiver_maps.at(0);
|
||||
if (state() == MONOMORPHIC) {
|
||||
Handle<Map> transitioned_receiver_map = receiver_map;
|
||||
@ -1894,6 +1928,14 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<Map> receiver_map,
|
||||
// if they at least come from the same origin for a transitioning store,
|
||||
// stay MONOMORPHIC and use the map for the most generic ElementsKind.
|
||||
store_mode = GetNonTransitioningStoreMode(store_mode);
|
||||
if (FLAG_vector_stores) {
|
||||
Handle<Code> handler =
|
||||
PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler(
|
||||
transitioned_receiver_map, language_mode(), store_mode);
|
||||
ConfigureVectorState(Handle<Name>::null(), transitioned_receiver_map,
|
||||
handler);
|
||||
return null_handle;
|
||||
}
|
||||
return PropertyICCompiler::ComputeKeyedStoreMonomorphic(
|
||||
transitioned_receiver_map, language_mode(), store_mode);
|
||||
} else if (receiver_map.is_identical_to(previous_receiver_map) &&
|
||||
@ -1904,6 +1946,13 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<Map> receiver_map,
|
||||
// A "normal" IC that handles stores can switch to a version that can
|
||||
// grow at the end of the array, handle OOB accesses or copy COW arrays
|
||||
// and still stay MONOMORPHIC.
|
||||
if (FLAG_vector_stores) {
|
||||
Handle<Code> handler =
|
||||
PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler(
|
||||
receiver_map, language_mode(), store_mode);
|
||||
ConfigureVectorState(Handle<Name>::null(), receiver_map, handler);
|
||||
return null_handle;
|
||||
}
|
||||
return PropertyICCompiler::ComputeKeyedStoreMonomorphic(
|
||||
receiver_map, language_mode(), store_mode);
|
||||
}
|
||||
@ -1964,6 +2013,16 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<Map> receiver_map,
|
||||
}
|
||||
}
|
||||
|
||||
if (FLAG_vector_stores) {
|
||||
MapHandleList transitioned_maps(target_receiver_maps.length());
|
||||
CodeHandleList handlers(target_receiver_maps.length());
|
||||
PropertyICCompiler::ComputeKeyedStorePolymorphicHandlers(
|
||||
&target_receiver_maps, &transitioned_maps, &handlers, store_mode,
|
||||
language_mode());
|
||||
ConfigureVectorState(&target_receiver_maps, &transitioned_maps, &handlers);
|
||||
return null_handle;
|
||||
}
|
||||
|
||||
return PropertyICCompiler::ComputeKeyedStorePolymorphic(
|
||||
&target_receiver_maps, store_mode, language_mode());
|
||||
}
|
||||
@ -2200,7 +2259,7 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
|
||||
|
||||
// Validate that the store_mode in the stub can also be derived
|
||||
// from peeking in the code bits of the handlers.
|
||||
ValidateStoreMode(stub);
|
||||
if (!FLAG_vector_stores) ValidateStoreMode(stub);
|
||||
} else {
|
||||
TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "dictionary prototype");
|
||||
}
|
||||
@ -2467,7 +2526,7 @@ RUNTIME_FUNCTION(Runtime_StoreIC_Miss) {
|
||||
Handle<Object> result;
|
||||
|
||||
if (FLAG_vector_stores) {
|
||||
DCHECK(args.length() == 5);
|
||||
DCHECK(args.length() == 5 || args.length() == 6);
|
||||
Handle<Smi> slot = args.at<Smi>(3);
|
||||
Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4);
|
||||
FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value());
|
||||
@ -2595,12 +2654,19 @@ RUNTIME_FUNCTION(Runtime_KeyedStoreIC_MissFromStubFailure) {
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_StoreIC_Slow) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK(args.length() == 3);
|
||||
StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
|
||||
DCHECK(args.length() == (FLAG_vector_stores ? 5 : 3));
|
||||
Handle<Object> object = args.at<Object>(0);
|
||||
Handle<Object> key = args.at<Object>(1);
|
||||
Handle<Object> value = args.at<Object>(2);
|
||||
LanguageMode language_mode = ic.language_mode();
|
||||
LanguageMode language_mode;
|
||||
if (FLAG_vector_stores) {
|
||||
StoreICNexus nexus(isolate);
|
||||
StoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
|
||||
language_mode = ic.language_mode();
|
||||
} else {
|
||||
StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
|
||||
language_mode = ic.language_mode();
|
||||
}
|
||||
Handle<Object> result;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, result,
|
||||
@ -2611,12 +2677,19 @@ RUNTIME_FUNCTION(Runtime_StoreIC_Slow) {
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Slow) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK(args.length() == 3);
|
||||
KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
|
||||
DCHECK(args.length() == (FLAG_vector_stores ? 5 : 3));
|
||||
Handle<Object> object = args.at<Object>(0);
|
||||
Handle<Object> key = args.at<Object>(1);
|
||||
Handle<Object> value = args.at<Object>(2);
|
||||
LanguageMode language_mode = ic.language_mode();
|
||||
LanguageMode language_mode;
|
||||
if (FLAG_vector_stores) {
|
||||
KeyedStoreICNexus nexus(isolate);
|
||||
KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
|
||||
language_mode = ic.language_mode();
|
||||
} else {
|
||||
KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
|
||||
language_mode = ic.language_mode();
|
||||
}
|
||||
Handle<Object> result;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, result,
|
||||
@ -2628,14 +2701,20 @@ RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Slow) {
|
||||
RUNTIME_FUNCTION(Runtime_ElementsTransitionAndStoreIC_Miss) {
|
||||
TimerEventScope<TimerEventIcMiss> timer(isolate);
|
||||
HandleScope scope(isolate);
|
||||
DCHECK(args.length() == 4);
|
||||
KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
|
||||
DCHECK(args.length() == (FLAG_vector_stores ? 6 : 4));
|
||||
Handle<Object> object = args.at<Object>(0);
|
||||
Handle<Object> key = args.at<Object>(1);
|
||||
Handle<Object> value = args.at<Object>(2);
|
||||
Handle<Map> map = args.at<Map>(3);
|
||||
|
||||
LanguageMode language_mode = ic.language_mode();
|
||||
Handle<Map> map = args.at<Map>(FLAG_vector_stores ? 5 : 3);
|
||||
LanguageMode language_mode;
|
||||
if (FLAG_vector_stores) {
|
||||
KeyedStoreICNexus nexus(isolate);
|
||||
KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
|
||||
language_mode = ic.language_mode();
|
||||
} else {
|
||||
KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
|
||||
language_mode = ic.language_mode();
|
||||
}
|
||||
if (object->IsJSObject()) {
|
||||
JSObject::TransitionElementsKind(Handle<JSObject>::cast(object),
|
||||
map->elements_kind());
|
||||
|
14
src/ic/ic.h
14
src/ic/ic.h
@ -122,6 +122,11 @@ class IC {
|
||||
// Configure the vector for POLYMORPHIC.
|
||||
void ConfigureVectorState(Handle<Name> name, MapHandleList* maps,
|
||||
CodeHandleList* handlers);
|
||||
// Configure the vector for POLYMORPHIC with transitions (only for element
|
||||
// keyed stores).
|
||||
void ConfigureVectorState(MapHandleList* maps,
|
||||
MapHandleList* transitioned_maps,
|
||||
CodeHandleList* handlers);
|
||||
|
||||
char TransitionMarkFromState(IC::State state);
|
||||
void TraceIC(const char* type, Handle<Object> name);
|
||||
@ -538,10 +543,17 @@ class KeyedStoreIC : public StoreIC {
|
||||
|
||||
static KeyedAccessStoreMode GetKeyedAccessStoreMode(
|
||||
ExtraICState extra_state) {
|
||||
DCHECK(!FLAG_vector_stores);
|
||||
return ExtraICStateKeyedAccessStoreMode::decode(extra_state);
|
||||
}
|
||||
|
||||
KeyedAccessStoreMode GetKeyedAccessStoreMode() {
|
||||
DCHECK(FLAG_vector_stores);
|
||||
return casted_nexus<KeyedStoreICNexus>()->GetKeyedAccessStoreMode();
|
||||
}
|
||||
|
||||
static IcCheckType GetKeyType(ExtraICState extra_state) {
|
||||
DCHECK(!FLAG_vector_stores);
|
||||
return IcCheckTypeField::decode(extra_state);
|
||||
}
|
||||
|
||||
@ -571,6 +583,8 @@ class KeyedStoreIC : public StoreIC {
|
||||
|
||||
static Handle<Code> initialize_stub_in_optimized_code(
|
||||
Isolate* isolate, LanguageMode language_mode, State initialization_state);
|
||||
static Handle<Code> ChooseMegamorphicStub(Isolate* isolate,
|
||||
ExtraICState extra_state);
|
||||
|
||||
static void Clear(Isolate* isolate, Code* host, KeyedStoreICNexus* nexus);
|
||||
|
||||
|
@ -407,6 +407,10 @@ class KeyedStoreICNexus : public FeedbackNexus {
|
||||
: FeedbackNexus(vector, slot) {
|
||||
DCHECK(vector->GetKind(slot) == Code::KEYED_STORE_IC);
|
||||
}
|
||||
explicit KeyedStoreICNexus(Isolate* isolate)
|
||||
: FeedbackNexus(TypeFeedbackVector::DummyVector(isolate),
|
||||
TypeFeedbackVector::DummySlot(
|
||||
TypeFeedbackVector::kDummyKeyedStoreICSlot)) {}
|
||||
KeyedStoreICNexus(TypeFeedbackVector* vector, FeedbackVectorICSlot slot)
|
||||
: FeedbackNexus(vector, slot) {
|
||||
DCHECK(vector->GetKind(slot) == Code::KEYED_STORE_IC);
|
||||
|
Loading…
Reference in New Issue
Block a user