Commit fd9c82a6 authored by verwaest@chromium.org's avatar verwaest@chromium.org

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
parent 8b25614a
...@@ -277,6 +277,14 @@ class SmallMapList { ...@@ -277,6 +277,14 @@ class SmallMapList {
bool is_empty() const { return list_.is_empty(); } bool is_empty() const { return list_.is_empty(); }
int length() const { return list_.length(); } 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) { void Add(Handle<Map> handle, Zone* zone) {
list_.Add(handle.location(), zone); list_.Add(handle.location(), zone);
} }
......
...@@ -3610,6 +3610,12 @@ bool Map::CanBeDeprecated() { ...@@ -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() { void Map::NotifyLeafMapLayoutChange() {
dependent_code()->DeoptimizeDependentCodeGroup( dependent_code()->DeoptimizeDependentCodeGroup(
GetIsolate(), GetIsolate(),
......
...@@ -7280,7 +7280,7 @@ MaybeObject* DescriptorArray::Merge(int verbatim, ...@@ -7280,7 +7280,7 @@ MaybeObject* DescriptorArray::Merge(int verbatim,
// Allocate a new descriptor array large enough to hold the required // Allocate a new descriptor array large enough to hold the required
// descriptors, with minimally the exact same size as this descriptor array. // descriptors, with minimally the exact same size as this descriptor array.
MaybeObject* maybe_descriptors = DescriptorArray::Allocate( 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; if (!maybe_descriptors->To(&result)) return maybe_descriptors;
ASSERT(result->length() > length() || ASSERT(result->length() > length() ||
result->NumberOfSlackDescriptors() > 0 || result->NumberOfSlackDescriptors() > 0 ||
......
...@@ -5344,6 +5344,12 @@ class Map: public HeapObject { ...@@ -5344,6 +5344,12 @@ class Map: public HeapObject {
inline void deprecate(); inline void deprecate();
inline bool is_deprecated(); inline bool is_deprecated();
inline bool CanBeDeprecated(); 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* RawCopy(int instance_size);
MUST_USE_RESULT MaybeObject* CopyWithPreallocatedFieldDescriptors(); MUST_USE_RESULT MaybeObject* CopyWithPreallocatedFieldDescriptors();
......
...@@ -1059,45 +1059,40 @@ void StubCache::Clear() { ...@@ -1059,45 +1059,40 @@ void StubCache::Clear() {
void StubCache::CollectMatchingMaps(SmallMapList* types, void StubCache::CollectMatchingMaps(SmallMapList* types,
Name* name, Handle<Name> name,
Code::Flags flags, Code::Flags flags,
Handle<Context> native_context, Handle<Context> native_context,
Zone* zone) { Zone* zone) {
for (int i = 0; i < kPrimaryTableSize; i++) { for (int i = 0; i < kPrimaryTableSize; i++) {
if (primary_[i].key == name) { if (primary_[i].key == *name) {
Map* map = primary_[i].map; Map* map = primary_[i].map;
// Map can be NULL, if the stub is constant function call // Map can be NULL, if the stub is constant function call
// with a primitive receiver. // with a primitive receiver.
if (map == NULL) continue; if (map == NULL) continue;
int offset = PrimaryOffset(name, flags, map); int offset = PrimaryOffset(*name, flags, map);
if (entry(primary_, offset) == &primary_[i] && if (entry(primary_, offset) == &primary_[i] &&
!TypeFeedbackOracle::CanRetainOtherContext(map, *native_context)) { !TypeFeedbackOracle::CanRetainOtherContext(map, *native_context)) {
types->Add(Handle<Map>(map), zone); types->AddMapIfMissing(Handle<Map>(map), zone);
} }
} }
} }
for (int i = 0; i < kSecondaryTableSize; i++) { for (int i = 0; i < kSecondaryTableSize; i++) {
if (secondary_[i].key == name) { if (secondary_[i].key == *name) {
Map* map = secondary_[i].map; Map* map = secondary_[i].map;
// Map can be NULL, if the stub is constant function call // Map can be NULL, if the stub is constant function call
// with a primitive receiver. // with a primitive receiver.
if (map == NULL) continue; if (map == NULL) continue;
// Lookup in primary table and skip duplicates. // Lookup in primary table and skip duplicates.
int primary_offset = PrimaryOffset(name, flags, map); 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;
}
// Lookup in secondary table and add matches. // 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] && if (entry(secondary_, offset) == &secondary_[i] &&
!TypeFeedbackOracle::CanRetainOtherContext(map, *native_context)) { !TypeFeedbackOracle::CanRetainOtherContext(map, *native_context)) {
types->Add(Handle<Map>(map), zone); types->AddMapIfMissing(Handle<Map>(map), zone);
} }
} }
} }
......
...@@ -311,7 +311,7 @@ class StubCache { ...@@ -311,7 +311,7 @@ class StubCache {
// Collect all maps that match the name and flags. // Collect all maps that match the name and flags.
void CollectMatchingMaps(SmallMapList* types, void CollectMatchingMaps(SmallMapList* types,
Name* name, Handle<Name> name,
Code::Flags flags, Code::Flags flags,
Handle<Context> native_context, Handle<Context> native_context,
Zone* zone); Zone* zone);
......
...@@ -539,15 +539,6 @@ TypeInfo TypeFeedbackOracle::IncrementType(CountOperation* expr) { ...@@ -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, void TypeFeedbackOracle::CollectPolymorphicMaps(Handle<Code> code,
SmallMapList* types) { SmallMapList* types) {
MapHandleList maps; MapHandleList maps;
...@@ -556,7 +547,7 @@ void TypeFeedbackOracle::CollectPolymorphicMaps(Handle<Code> code, ...@@ -556,7 +547,7 @@ void TypeFeedbackOracle::CollectPolymorphicMaps(Handle<Code> code,
for (int i = 0; i < maps.length(); i++) { for (int i = 0; i < maps.length(); i++) {
Handle<Map> map(maps.at(i)); Handle<Map> map(maps.at(i));
if (!CanRetainOtherContext(*map, *native_context_)) { if (!CanRetainOtherContext(*map, *native_context_)) {
AddMapIfMissing(map, types, zone()); types->AddMapIfMissing(map, zone());
} }
} }
} }
...@@ -574,7 +565,7 @@ void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id, ...@@ -574,7 +565,7 @@ void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id,
// we need a generic store (or load) here. // we need a generic store (or load) here.
ASSERT(Handle<Code>::cast(object)->ic_state() == GENERIC); ASSERT(Handle<Code>::cast(object)->ic_state() == GENERIC);
} else if (object->IsMap()) { } 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) { } else if (Handle<Code>::cast(object)->ic_state() == POLYMORPHIC) {
CollectPolymorphicMaps(Handle<Code>::cast(object), types); CollectPolymorphicMaps(Handle<Code>::cast(object), types);
} else if (FLAG_collect_megamorphic_maps_from_stub_cache && } else if (FLAG_collect_megamorphic_maps_from_stub_cache &&
...@@ -582,7 +573,7 @@ void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id, ...@@ -582,7 +573,7 @@ void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id,
types->Reserve(4, zone()); types->Reserve(4, zone());
ASSERT(object->IsCode()); ASSERT(object->IsCode());
isolate_->stub_cache()->CollectMatchingMaps(types, isolate_->stub_cache()->CollectMatchingMaps(types,
*name, name,
flags, flags,
native_context_, native_context_,
zone()); zone());
......
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