Lazily initialize the target map list in IC.

This makes sure that we keep the target map list alive in the handle scope during IC computation.

BUG=
R=verwaest@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20426 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
ulan@chromium.org 2014-04-02 07:59:54 +00:00
parent eba6cb49c1
commit 65bae6c652
4 changed files with 46 additions and 44 deletions

View File

@ -121,7 +121,8 @@ void IC::TraceIC(const char* type,
IC::IC(FrameDepth depth, Isolate* isolate)
: isolate_(isolate),
target_set_(false) {
target_set_(false),
target_maps_set_(false) {
// To improve the performance of the (much used) IC code, we unfold a few
// levels of the stack frame iteration code. This yields a ~35% speedup when
// running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag.
@ -293,7 +294,7 @@ bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
// If the IC is shared between multiple receivers (slow dictionary mode), then
// the map cannot be deprecated and the stub invalidated.
if (cache_holder == OWN_MAP) {
Map* old_map = target()->FindFirstMap();
Map* old_map = FirstTargetMap();
if (old_map == *map) return true;
if (old_map != NULL) {
if (old_map->is_deprecated()) return true;
@ -632,7 +633,7 @@ bool IC::UpdatePolymorphicIC(Handle<HeapType> type,
TypeHandleList types;
CodeHandleList handlers;
target()->FindAllTypes(&types);
TargetTypes(&types);
int number_of_types = types.length();
int deprecated_types = 0;
int handler_to_overwrite = -1;
@ -735,7 +736,7 @@ void IC::UpdateMonomorphicIC(Handle<HeapType> type,
void IC::CopyICToMegamorphicCache(Handle<String> name) {
TypeHandleList types;
CodeHandleList handlers;
target()->FindAllTypes(&types);
TargetTypes(&types);
if (!target()->FindHandlers(&handlers, types.length())) return;
for (int i = 0; i < types.length(); i++) {
UpdateMegamorphicCache(*types.at(i), *name, *handlers.at(i));
@ -1036,19 +1037,13 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<JSObject> receiver) {
Handle<Map> receiver_map(receiver->map(), isolate());
MapHandleList target_receiver_maps;
if (state() == UNINITIALIZED || state() == PREMONOMORPHIC) {
// Optimistically assume that ICs that haven't reached the MONOMORPHIC state
// yet will do so and stay there.
return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map);
}
if (target().is_identical_to(string_stub())) {
target_receiver_maps.Add(isolate()->factory()->string_map());
} else {
target()->FindAllMaps(&target_receiver_maps);
if (target_receiver_maps.length() == 0) {
return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map);
}
TargetMaps(&target_receiver_maps);
}
if (target_receiver_maps.length() == 0) {
return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map);
}
// The first time a receiver is seen that is a transitioned version of the
@ -1435,24 +1430,15 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver,
}
Handle<Map> receiver_map(receiver->map(), isolate());
if (state() == UNINITIALIZED || state() == PREMONOMORPHIC) {
// Optimistically assume that ICs that haven't reached the MONOMORPHIC state
// yet will do so and stay there.
MapHandleList target_receiver_maps;
TargetMaps(&target_receiver_maps);
if (target_receiver_maps.length() == 0) {
Handle<Map> monomorphic_map = ComputeTransitionedMap(receiver, store_mode);
store_mode = GetNonTransitioningStoreMode(store_mode);
return isolate()->stub_cache()->ComputeKeyedStoreElement(
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
// transition to a different GetNonTransitioningStoreMode IC that handles a
// superset of the original IC. Handle those here if the receiver map hasn't
@ -2754,8 +2740,8 @@ MaybeObject* CompareNilIC::CompareNil(Handle<Object> object) {
// Find or create the specialized stub to support the new set of types.
Handle<Code> code;
if (stub.IsMonomorphic()) {
Handle<Map> monomorphic_map(already_monomorphic
? target()->FindFirstMap()
Handle<Map> monomorphic_map(already_monomorphic && FirstTargetMap() != NULL
? FirstTargetMap()
: HeapObject::cast(*object)->map());
code = isolate()->stub_cache()->ComputeCompareNil(monomorphic_map, stub);
} else {

View File

@ -253,6 +253,25 @@ class IC {
extra_ic_state_ = state;
}
void TargetMaps(MapHandleList* list) {
FindTargetMaps();
for (int i = 0; i < target_maps_.length(); i++) {
list->Add(target_maps_.at(i));
}
}
void TargetTypes(TypeHandleList* list) {
FindTargetMaps();
for (int i = 0; i < target_maps_.length(); i++) {
list->Add(IC::MapToType<HeapType>(target_maps_.at(i), isolate_));
}
}
Map* FirstTargetMap() {
FindTargetMaps();
return target_maps_.length() > 0 ? *target_maps_.at(0) : NULL;
}
protected:
void UpdateTarget() {
target_ = handle(raw_target(), isolate_);
@ -265,6 +284,17 @@ class IC {
inline ConstantPoolArray* constant_pool() const;
inline ConstantPoolArray* raw_constant_pool() const;
void FindTargetMaps() {
if (target_maps_set_) return;
target_maps_set_ = true;
if (state_ == MONOMORPHIC) {
Map* map = target_->FindFirstMap();
if (map != NULL) target_maps_.Add(handle(map));
} else if (state_ != UNINITIALIZED && state_ != PREMONOMORPHIC) {
target_->FindAllMaps(&target_maps_);
}
}
// Frame pointer for the frame that uses (calls) the IC.
Address fp_;
@ -286,6 +316,8 @@ class IC {
bool target_set_;
ExtraICState extra_ic_state_;
MapHandleList target_maps_;
bool target_maps_set_;
DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
};

View File

@ -10540,21 +10540,6 @@ void Code::FindAllMaps(MapHandleList* maps) {
}
void Code::FindAllTypes(TypeHandleList* types) {
ASSERT(is_inline_cache_stub());
DisallowHeapAllocation no_allocation;
int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
for (RelocIterator it(this, mask); !it.done(); it.next()) {
RelocInfo* info = it.rinfo();
Object* object = info->target_object();
if (object->IsMap()) {
Handle<Map> map(Map::cast(object));
types->Add(IC::MapToType<HeapType>(map, map->GetIsolate()));
}
}
}
Code* Code::FindFirstHandler() {
ASSERT(is_inline_cache_stub());
DisallowHeapAllocation no_allocation;

View File

@ -5407,7 +5407,6 @@ class Code: public HeapObject {
// Find the first map in an IC stub.
Map* FindFirstMap();
void FindAllMaps(MapHandleList* maps);
void FindAllTypes(TypeHandleList* types);
// Find the first handler in an IC stub.
Code* FindFirstHandler();