Commit dafb11f8 authored by ulan@chromium.org's avatar ulan@chromium.org

Load target types and handlers before IC computation.

BUG=
R=verwaest@chromium.org

Review URL: https://codereview.chromium.org/170563002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19455 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 8bdf7c29
...@@ -149,6 +149,8 @@ IC::IC(FrameDepth depth, Isolate* isolate) ...@@ -149,6 +149,8 @@ IC::IC(FrameDepth depth, Isolate* isolate)
target_ = handle(raw_target(), isolate); target_ = handle(raw_target(), isolate);
state_ = target_->ic_state(); state_ = target_->ic_state();
extra_ic_state_ = target_->extra_ic_state(); extra_ic_state_ = target_->extra_ic_state();
target()->FindAllTypes(&types_);
target()->FindHandlers(&handlers_);
} }
...@@ -281,7 +283,7 @@ bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver, ...@@ -281,7 +283,7 @@ bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
// If the IC is shared between multiple receivers (slow dictionary mode), then // If the IC is shared between multiple receivers (slow dictionary mode), then
// the map cannot be deprecated and the stub invalidated. // the map cannot be deprecated and the stub invalidated.
if (cache_holder == OWN_MAP) { if (cache_holder == OWN_MAP) {
Map* old_map = target()->FindFirstMap(); Map* old_map = first_map();
if (old_map == *map) return true; if (old_map == *map) return true;
if (old_map != NULL) { if (old_map != NULL) {
if (old_map->is_deprecated()) return true; if (old_map->is_deprecated()) return true;
...@@ -306,10 +308,8 @@ bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver, ...@@ -306,10 +308,8 @@ bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
void IC::TryRemoveInvalidHandlers(Handle<Map> map, Handle<String> name) { void IC::TryRemoveInvalidHandlers(Handle<Map> map, Handle<String> name) {
CodeHandleList handlers; for (int i = 0; i < handlers()->length(); i++) {
target()->FindHandlers(&handlers); Handle<Code> handler = handlers()->at(i);
for (int i = 0; i < handlers.length(); i++) {
Handle<Code> handler = handlers.at(i);
int index = map->IndexInCodeCache(*name, *handler); int index = map->IndexInCodeCache(*name, *handler);
if (index >= 0) { if (index >= 0) {
map->RemoveFromCodeCache(*name, *handler, index); map->RemoveFromCodeCache(*name, *handler, index);
...@@ -605,18 +605,14 @@ bool IC::UpdatePolymorphicIC(Handle<HeapType> type, ...@@ -605,18 +605,14 @@ bool IC::UpdatePolymorphicIC(Handle<HeapType> type,
Handle<String> name, Handle<String> name,
Handle<Code> code) { Handle<Code> code) {
if (!code->is_handler()) return false; if (!code->is_handler()) return false;
TypeHandleList types;
CodeHandleList handlers;
int number_of_valid_types; int number_of_valid_types;
int handler_to_overwrite = -1; int handler_to_overwrite = -1;
target()->FindAllTypes(&types); int number_of_types = types()->length();
int number_of_types = types.length();
number_of_valid_types = number_of_types; number_of_valid_types = number_of_types;
for (int i = 0; i < number_of_types; i++) { for (int i = 0; i < number_of_types; i++) {
Handle<HeapType> current_type = types.at(i); Handle<HeapType> current_type = types()->at(i);
// Filter out deprecated maps to ensure their instances get migrated. // Filter out deprecated maps to ensure their instances get migrated.
if (current_type->IsClass() && current_type->AsClass()->is_deprecated()) { if (current_type->IsClass() && current_type->AsClass()->is_deprecated()) {
number_of_valid_types--; number_of_valid_types--;
...@@ -632,18 +628,19 @@ bool IC::UpdatePolymorphicIC(Handle<HeapType> type, ...@@ -632,18 +628,19 @@ bool IC::UpdatePolymorphicIC(Handle<HeapType> type,
if (number_of_valid_types >= 4) return false; if (number_of_valid_types >= 4) return false;
if (number_of_types == 0) return false; if (number_of_types == 0) return false;
if (!target()->FindHandlers(&handlers, types.length())) return false; if (handlers()->length() < types()->length()) return false;
number_of_valid_types++; number_of_valid_types++;
if (handler_to_overwrite >= 0) { if (handler_to_overwrite >= 0) {
handlers.Set(handler_to_overwrite, code); handlers()->Set(handler_to_overwrite, code);
} else { } else {
types.Add(type); types()->Add(type);
handlers.Add(code); handlers()->Add(code);
} }
Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC( Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC(
kind(), &types, &handlers, number_of_valid_types, name, extra_ic_state()); kind(), types(), handlers(), number_of_valid_types,
name, extra_ic_state());
set_target(*ic); set_target(*ic);
return true; return true;
} }
...@@ -701,29 +698,23 @@ void IC::UpdateMonomorphicIC(Handle<HeapType> type, ...@@ -701,29 +698,23 @@ void IC::UpdateMonomorphicIC(Handle<HeapType> type,
void IC::CopyICToMegamorphicCache(Handle<String> name) { void IC::CopyICToMegamorphicCache(Handle<String> name) {
TypeHandleList types; if (handlers()->length() < types()->length()) return;
CodeHandleList handlers; for (int i = 0; i < types()->length(); i++) {
target()->FindAllTypes(&types); UpdateMegamorphicCache(*types()->at(i), *name, *handlers()->at(i));
if (!target()->FindHandlers(&handlers, types.length())) return;
for (int i = 0; i < types.length(); i++) {
UpdateMegamorphicCache(*types.at(i), *name, *handlers.at(i));
} }
} }
bool IC::IsTransitionOfMonomorphicTarget(Handle<HeapType> type) { bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) {
if (!type->IsClass()) return false; if (source_map == NULL) return true;
Map* receiver_map = *type->AsClass(); if (target_map == NULL) return false;
Map* current_map = target()->FindFirstMap(); ElementsKind target_elements_kind = target_map->elements_kind();
ElementsKind receiver_elements_kind = receiver_map->elements_kind(); bool more_general_transition = IsMoreGeneralElementsKindTransition(
bool more_general_transition = source_map->elements_kind(), target_elements_kind);
IsMoreGeneralElementsKindTransition(
current_map->elements_kind(), receiver_elements_kind);
Map* transitioned_map = more_general_transition Map* transitioned_map = more_general_transition
? current_map->LookupElementsTransitionMap(receiver_elements_kind) ? source_map->LookupElementsTransitionMap(target_elements_kind)
: NULL; : NULL;
return transitioned_map == target_map;
return transitioned_map == receiver_map;
} }
...@@ -740,8 +731,11 @@ void IC::PatchCache(Handle<HeapType> type, ...@@ -740,8 +731,11 @@ void IC::PatchCache(Handle<HeapType> type,
// For now, call stubs are allowed to rewrite to the same stub. This // For now, call stubs are allowed to rewrite to the same stub. This
// happens e.g., when the field does not contain a function. // happens e.g., when the field does not contain a function.
ASSERT(!target().is_identical_to(code)); ASSERT(!target().is_identical_to(code));
Code* old_handler = target()->FindFirstHandler(); Map* old_map = first_map();
if (old_handler == *code && IsTransitionOfMonomorphicTarget(type)) { Code* old_handler = first_handler();
Map* map = type->IsClass() ? *type->AsClass() : NULL;
if (old_handler == *code &&
IsTransitionOfMonomorphicTarget(old_map, map)) {
UpdateMonomorphicIC(type, code, name); UpdateMonomorphicIC(type, code, name);
break; break;
} }
...@@ -1010,7 +1004,7 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<JSObject> receiver) { ...@@ -1010,7 +1004,7 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<JSObject> receiver) {
if (target().is_identical_to(string_stub())) { if (target().is_identical_to(string_stub())) {
target_receiver_maps.Add(isolate()->factory()->string_map()); target_receiver_maps.Add(isolate()->factory()->string_map());
} else { } else {
target()->FindAllMaps(&target_receiver_maps); GetMapsFromTypes(&target_receiver_maps);
if (target_receiver_maps.length() == 0) { if (target_receiver_maps.length() == 0) {
return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map);
} }
...@@ -1414,37 +1408,25 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, ...@@ -1414,37 +1408,25 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver,
monomorphic_map, strict_mode(), store_mode); monomorphic_map, strict_mode(), store_mode);
} }
MapHandleList target_receiver_maps;
target()->FindAllMaps(&target_receiver_maps);
if (target_receiver_maps.length() == 0) {
// In the case that there is a non-map-specific IC is installed (e.g. keyed
// stores into properties in dictionary mode), then there will be not
// receiver maps in the target.
return generic_stub();
}
// There are several special cases where an IC that is MONOMORPHIC can still // There are several special cases where an IC that is MONOMORPHIC can still
// transition to a different GetNonTransitioningStoreMode IC that handles a // transition to a different GetNonTransitioningStoreMode IC that handles a
// superset of the original IC. Handle those here if the receiver map hasn't // superset of the original IC. Handle those here if the receiver map hasn't
// changed or it has transitioned to a more general kind. // changed or it has transitioned to a more general kind.
KeyedAccessStoreMode old_store_mode = KeyedAccessStoreMode old_store_mode =
KeyedStoreIC::GetKeyedAccessStoreMode(target()->extra_ic_state()); KeyedStoreIC::GetKeyedAccessStoreMode(target()->extra_ic_state());
Handle<Map> previous_receiver_map = target_receiver_maps.at(0);
if (state() == MONOMORPHIC) { if (state() == MONOMORPHIC) {
// If the "old" and "new" maps are in the same elements map family, stay // If the "old" and "new" maps are in the same elements map family, stay
// MONOMORPHIC and use the map for the most generic ElementsKind. // MONOMORPHIC and use the map for the most generic ElementsKind.
Handle<Map> transitioned_receiver_map = receiver_map; Handle<Map> transitioned_map = receiver_map;
if (IsTransitionStoreMode(store_mode)) { if (IsTransitionStoreMode(store_mode)) {
transitioned_receiver_map = transitioned_map = ComputeTransitionedMap(receiver, store_mode);
ComputeTransitionedMap(receiver, store_mode);
} }
if (IsTransitionOfMonomorphicTarget( if (IsTransitionOfMonomorphicTarget(first_map(), *transitioned_map)) {
MapToType<HeapType>(transitioned_receiver_map, isolate()))) {
// Element family is the same, use the "worst" case map. // Element family is the same, use the "worst" case map.
store_mode = GetNonTransitioningStoreMode(store_mode); store_mode = GetNonTransitioningStoreMode(store_mode);
return isolate()->stub_cache()->ComputeKeyedStoreElement( return isolate()->stub_cache()->ComputeKeyedStoreElement(
transitioned_receiver_map, strict_mode(), store_mode); transitioned_map, strict_mode(), store_mode);
} else if (*previous_receiver_map == receiver->map() && } else if (first_map() == receiver->map() &&
old_store_mode == STANDARD_STORE && old_store_mode == STANDARD_STORE &&
(IsGrowStoreMode(store_mode) || (IsGrowStoreMode(store_mode) ||
store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
...@@ -1459,6 +1441,9 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, ...@@ -1459,6 +1441,9 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver,
ASSERT(state() != GENERIC); ASSERT(state() != GENERIC);
MapHandleList target_receiver_maps;
GetMapsFromTypes(&target_receiver_maps);
bool map_added = bool map_added =
AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map); AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map);
...@@ -2715,8 +2700,8 @@ MaybeObject* CompareNilIC::CompareNil(Handle<Object> object) { ...@@ -2715,8 +2700,8 @@ MaybeObject* CompareNilIC::CompareNil(Handle<Object> object) {
// Find or create the specialized stub to support the new set of types. // Find or create the specialized stub to support the new set of types.
Handle<Code> code; Handle<Code> code;
if (stub.IsMonomorphic()) { if (stub.IsMonomorphic()) {
Handle<Map> monomorphic_map(already_monomorphic Handle<Map> monomorphic_map(already_monomorphic && (first_map() != NULL)
? target()->FindFirstMap() ? first_map()
: HeapObject::cast(*object)->map()); : HeapObject::cast(*object)->map());
code = isolate()->stub_cache()->ComputeCompareNil(monomorphic_map, stub); code = isolate()->stub_cache()->ComputeCompareNil(monomorphic_map, stub);
} else { } else {
......
...@@ -150,6 +150,19 @@ class IC { ...@@ -150,6 +150,19 @@ class IC {
// Get the call-site target; used for determining the state. // Get the call-site target; used for determining the state.
Handle<Code> target() const { return target_; } Handle<Code> target() const { return target_; }
TypeHandleList* types() { return &types_; }
CodeHandleList* handlers() { return &handlers_; }
Map* first_map() {
return types_.length() == 0 ? NULL : *TypeToMap(*types_.at(0), isolate_);
}
Code* first_handler() {
return handlers_.length() == 0 ? NULL : *handlers_.at(0);
}
void GetMapsFromTypes(MapHandleList* maps) {
for (int i = 0; i < types_.length(); ++i) {
maps->Add(TypeToMap(*types_.at(i), isolate_));
}
}
Address fp() const { return fp_; } Address fp() const { return fp_; }
Address pc() const { return *pc_address_; } Address pc() const { return *pc_address_; }
Isolate* isolate() const { return isolate_; } Isolate* isolate() const { return isolate_; }
...@@ -209,7 +222,7 @@ class IC { ...@@ -209,7 +222,7 @@ class IC {
virtual void UpdateMegamorphicCache(HeapType* type, Name* name, Code* code); virtual void UpdateMegamorphicCache(HeapType* type, Name* name, Code* code);
void CopyICToMegamorphicCache(Handle<String> name); void CopyICToMegamorphicCache(Handle<String> name);
bool IsTransitionOfMonomorphicTarget(Handle<HeapType> type); bool IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map);
void PatchCache(Handle<HeapType> type, void PatchCache(Handle<HeapType> type,
Handle<String> name, Handle<String> name,
Handle<Code> code); Handle<Code> code);
...@@ -260,6 +273,9 @@ class IC { ...@@ -260,6 +273,9 @@ class IC {
ExtraICState extra_ic_state_; ExtraICState extra_ic_state_;
TypeHandleList types_;
CodeHandleList handlers_;
DISALLOW_IMPLICIT_CONSTRUCTORS(IC); DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment