Update deprecated maps before generating optimized code.

Review URL: https://chromiumcodereview.appspot.com/14847008

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14522 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
verwaest@chromium.org 2013-05-02 15:40:07 +00:00
parent 8b25614aa9
commit fd9c82a618
7 changed files with 33 additions and 27 deletions

View File

@ -277,6 +277,14 @@ class SmallMapList {
bool is_empty() const { return list_.is_empty(); }
int length() const { return list_.length(); }
void AddMapIfMissing(Handle<Map> map, Zone* zone) {
map = Map::CurrentMapForDeprecated(map);
for (int i = 0; i < length(); ++i) {
if (at(i).is_identical_to(map)) return;
}
Add(map, zone);
}
void Add(Handle<Map> handle, Zone* zone) {
list_.Add(handle.location(), zone);
}

View File

@ -3610,6 +3610,12 @@ bool Map::CanBeDeprecated() {
}
Handle<Map> Map::CurrentMapForDeprecated(Handle<Map> map) {
if (!map->is_deprecated()) return map;
return GeneralizeRepresentation(map, 0, Representation::Smi());
}
void Map::NotifyLeafMapLayoutChange() {
dependent_code()->DeoptimizeDependentCodeGroup(
GetIsolate(),

View File

@ -7280,7 +7280,7 @@ MaybeObject* DescriptorArray::Merge(int verbatim,
// Allocate a new descriptor array large enough to hold the required
// descriptors, with minimally the exact same size as this descriptor array.
MaybeObject* maybe_descriptors = DescriptorArray::Allocate(
new_size, Max(new_size, number_of_descriptors()) - new_size);
new_size, Max(new_size, other->number_of_descriptors()) - new_size);
if (!maybe_descriptors->To(&result)) return maybe_descriptors;
ASSERT(result->length() > length() ||
result->NumberOfSlackDescriptors() > 0 ||

View File

@ -5344,6 +5344,12 @@ class Map: public HeapObject {
inline void deprecate();
inline bool is_deprecated();
inline bool CanBeDeprecated();
// Returns a non-deprecated version of the input. If the input was not
// deprecated, it is directly returned. Otherwise, the non-deprecated version
// is found by re-transitioning from the root of the transition tree using the
// descriptor array of the map. New maps (and transitions) may be created if
// no new (more general) version exists.
static inline Handle<Map> CurrentMapForDeprecated(Handle<Map> map);
MUST_USE_RESULT MaybeObject* RawCopy(int instance_size);
MUST_USE_RESULT MaybeObject* CopyWithPreallocatedFieldDescriptors();

View File

@ -1059,45 +1059,40 @@ void StubCache::Clear() {
void StubCache::CollectMatchingMaps(SmallMapList* types,
Name* name,
Handle<Name> name,
Code::Flags flags,
Handle<Context> native_context,
Zone* zone) {
for (int i = 0; i < kPrimaryTableSize; i++) {
if (primary_[i].key == name) {
if (primary_[i].key == *name) {
Map* map = primary_[i].map;
// Map can be NULL, if the stub is constant function call
// with a primitive receiver.
if (map == NULL) continue;
int offset = PrimaryOffset(name, flags, map);
int offset = PrimaryOffset(*name, flags, map);
if (entry(primary_, offset) == &primary_[i] &&
!TypeFeedbackOracle::CanRetainOtherContext(map, *native_context)) {
types->Add(Handle<Map>(map), zone);
types->AddMapIfMissing(Handle<Map>(map), zone);
}
}
}
for (int i = 0; i < kSecondaryTableSize; i++) {
if (secondary_[i].key == name) {
if (secondary_[i].key == *name) {
Map* map = secondary_[i].map;
// Map can be NULL, if the stub is constant function call
// with a primitive receiver.
if (map == NULL) continue;
// Lookup in primary table and skip duplicates.
int primary_offset = PrimaryOffset(name, flags, map);
Entry* primary_entry = entry(primary_, primary_offset);
if (primary_entry->key == name) {
Map* primary_map = primary_entry->map;
if (map == primary_map) continue;
}
int primary_offset = PrimaryOffset(*name, flags, map);
// Lookup in secondary table and add matches.
int offset = SecondaryOffset(name, flags, primary_offset);
int offset = SecondaryOffset(*name, flags, primary_offset);
if (entry(secondary_, offset) == &secondary_[i] &&
!TypeFeedbackOracle::CanRetainOtherContext(map, *native_context)) {
types->Add(Handle<Map>(map), zone);
types->AddMapIfMissing(Handle<Map>(map), zone);
}
}
}

View File

@ -311,7 +311,7 @@ class StubCache {
// Collect all maps that match the name and flags.
void CollectMatchingMaps(SmallMapList* types,
Name* name,
Handle<Name> name,
Code::Flags flags,
Handle<Context> native_context,
Zone* zone);

View File

@ -539,15 +539,6 @@ TypeInfo TypeFeedbackOracle::IncrementType(CountOperation* expr) {
}
static void AddMapIfMissing(Handle<Map> map, SmallMapList* list,
Zone* zone) {
for (int i = 0; i < list->length(); ++i) {
if (list->at(i).is_identical_to(map)) return;
}
list->Add(map, zone);
}
void TypeFeedbackOracle::CollectPolymorphicMaps(Handle<Code> code,
SmallMapList* types) {
MapHandleList maps;
@ -556,7 +547,7 @@ void TypeFeedbackOracle::CollectPolymorphicMaps(Handle<Code> code,
for (int i = 0; i < maps.length(); i++) {
Handle<Map> map(maps.at(i));
if (!CanRetainOtherContext(*map, *native_context_)) {
AddMapIfMissing(map, types, zone());
types->AddMapIfMissing(map, zone());
}
}
}
@ -574,7 +565,7 @@ void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id,
// we need a generic store (or load) here.
ASSERT(Handle<Code>::cast(object)->ic_state() == GENERIC);
} else if (object->IsMap()) {
types->Add(Handle<Map>::cast(object), zone());
types->AddMapIfMissing(Handle<Map>::cast(object), zone());
} else if (Handle<Code>::cast(object)->ic_state() == POLYMORPHIC) {
CollectPolymorphicMaps(Handle<Code>::cast(object), types);
} else if (FLAG_collect_megamorphic_maps_from_stub_cache &&
@ -582,7 +573,7 @@ void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id,
types->Reserve(4, zone());
ASSERT(object->IsCode());
isolate_->stub_cache()->CollectMatchingMaps(types,
*name,
name,
flags,
native_context_,
zone());