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:
parent
eba6cb49c1
commit
65bae6c652
42
src/ic.cc
42
src/ic.cc
@ -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 {
|
||||
|
32
src/ic.h
32
src/ic.h
@ -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);
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user