Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(588)

Unified Diff: src/objects.cc

Issue 6685073: Remember and reuse derived map for external arrays (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: fix handling of empty property name Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index da751477338fefbb40ac95ab22a8e658fd21a687..3c05985a66f5f9636e460d50eb68f2c64e728d8f 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -1282,12 +1282,23 @@ MaybeObject* JSObject::AddFastProperty(String* name,
}
}
- // Only allow map transition if the object's map is NOT equal to the
- // global object_function's map and there is not a transition for name.
+ // Only allow map transition if the object isn't the global object and there
+ // is not a transition for the name, or there's a transition for the name but
+ // it's unrelated to properties.
+ int descriptor_index = old_descriptors->Search(name);
+
+ // External array transitions are stored in the descriptor for property "",
+ // which is not a identifier and should have forced a switch to slow
+ // properties above.
+ ASSERT(
Mads Ager (chromium) 2011/03/22 18:57:25 Move fist disjunct of the assert to the first line
danno 2011/03/23 09:56:52 Done.
+ descriptor_index == DescriptorArray::kNotFound ||
+ old_descriptors->GetType(descriptor_index) != EXTERNAL_ARRAY_TRANSITION);
+ bool can_insert_transition =
+ (descriptor_index == DescriptorArray::kNotFound ||
+ old_descriptors->GetType(descriptor_index) == EXTERNAL_ARRAY_TRANSITION);
bool allow_map_transition =
- !old_descriptors->Contains(name) &&
- (isolate->context()->global_context()->object_function()->
- map() != map());
+ can_insert_transition &&
+ (isolate->context()->global_context()->object_function()->map() != map());
ASSERT(index < map()->inobject_properties() ||
(index - map()->inobject_properties()) < properties()->length() ||
@@ -1819,6 +1830,78 @@ void Map::LookupInDescriptors(JSObject* holder,
}
+MaybeObject* Map::GetExternalArrayElementsMap(ExternalArrayType array_type,
+ bool safe_to_add_transition) {
+ DescriptorArray* descriptors = instance_descriptors();
+ String* external_array_sentinel_name = HEAP->empty_symbol();
Mads Ager (chromium) 2011/03/22 18:57:25 Let's replace HEAP with GetIsolate()->heap() here
danno 2011/03/23 09:56:52 Done.
+
+ if (safe_to_add_transition) {
+ // It's only safe to manipulate the descriptor array if it would be
+ // safe to add a transition.
+
+ ASSERT(!is_shared()); // no transitions can be added to shared maps.
+ // Check if the external array transition already exists.
+ DescriptorLookupCache* cache = heap()->isolate()->descriptor_lookup_cache();
+ int index = cache->Lookup(descriptors, external_array_sentinel_name);
+ if (index == DescriptorLookupCache::kAbsent) {
+ index = descriptors->Search(external_array_sentinel_name);
+ cache->Update(descriptors,
+ external_array_sentinel_name,
+ index);
+ }
+
+ // If the transition already exists, check the type. If there is a match,
+ // return it.
+ if (index != DescriptorArray::kNotFound) {
+ PropertyDetails details(PropertyDetails(descriptors->GetDetails(index)));
+ if (details.type() == EXTERNAL_ARRAY_TRANSITION &&
+ details.array_type() == array_type) {
+ return descriptors->GetValue(index);
+ } else {
+ safe_to_add_transition = false;
+ }
+ }
+ }
+
+ // No transition to an existing external array map. Make a new one.
+ Object* obj;
+ { MaybeObject* maybe_map = CopyDropTransitions();
+ if (!maybe_map->ToObject(&obj)) return maybe_map;
+ }
+ Map* new_map = Map::cast(obj);
+
+ new_map->set_has_fast_elements(false);
+ new_map->set_has_external_array_elements(true);
+ COUNTERS->map_to_external_array_elements()->Increment();
Mads Ager (chromium) 2011/03/22 18:57:25 GetIsolate()->counters() instead of COUNTERS.
danno 2011/03/23 09:56:52 Done.
+
+ // Only remember the map transition if the object's map is NOT equal to the
+ // global object_function's map and there is not an already existing
+ // non-matching external array transition.
+ Heap* heap = GetHeap();
+ bool allow_map_transition =
+ safe_to_add_transition &&
+ (heap->isolate()->context()->global_context()->object_function()->map() !=
Mads Ager (chromium) 2011/03/22 18:57:25 Instead of getting the heap and using heap->isolat
danno 2011/03/23 09:56:52 Done.
+ map());
+ if (allow_map_transition) {
+ // Allocate new instance descriptors for the old map with map transition.
+ ExternalArrayTransitionDescriptor desc(external_array_sentinel_name,
+ Map::cast(new_map),
+ array_type);
+ Object* new_descriptors;
+ MaybeObject* maybe_new_descriptors = descriptors->CopyInsert(
+ &desc,
+ KEEP_TRANSITIONS);
+ if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
+ return maybe_new_descriptors;
+ }
+ descriptors = DescriptorArray::cast(new_descriptors);
+ set_instance_descriptors(descriptors);
+ }
+
+ return new_map;
+}
+
+
void JSObject::LocalLookupRealNamedProperty(String* name,
LookupResult* result) {
if (IsJSGlobalProxy()) {
@@ -2051,6 +2134,7 @@ MaybeObject* JSObject::SetProperty(LookupResult* result,
return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
}
case NULL_DESCRIPTOR:
+ case EXTERNAL_ARRAY_TRANSITION:
return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
default:
UNREACHABLE();
@@ -2130,6 +2214,7 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
// if the value is a function.
return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
case NULL_DESCRIPTOR:
+ case EXTERNAL_ARRAY_TRANSITION:
return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
default:
UNREACHABLE();
@@ -5486,6 +5571,7 @@ void Map::CreateBackPointers() {
DescriptorArray* descriptors = instance_descriptors();
for (int i = 0; i < descriptors->number_of_descriptors(); i++) {
if (descriptors->GetType(i) == MAP_TRANSITION ||
+ descriptors->GetType(i) == EXTERNAL_ARRAY_TRANSITION ||
descriptors->GetType(i) == CONSTANT_TRANSITION) {
// Get target.
Map* target = Map::cast(descriptors->GetValue(i));
@@ -5528,6 +5614,7 @@ void Map::ClearNonLiveTransitions(Heap* heap, Object* real_prototype) {
// non-live object.
PropertyDetails details(Smi::cast(contents->get(i + 1)));
if (details.type() == MAP_TRANSITION ||
+ details.type() == EXTERNAL_ARRAY_TRANSITION ||
details.type() == CONSTANT_TRANSITION) {
Map* target = reinterpret_cast<Map*>(contents->get(i));
ASSERT(target->IsHeapObject());
@@ -6401,6 +6488,7 @@ const char* Code::PropertyType2String(PropertyType type) {
case CALLBACKS: return "CALLBACKS";
case INTERCEPTOR: return "INTERCEPTOR";
case MAP_TRANSITION: return "MAP_TRANSITION";
+ case EXTERNAL_ARRAY_TRANSITION: return "EXTERNAL_ARRAY_TRANSITION";
case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION";
case NULL_DESCRIPTOR: return "NULL_DESCRIPTOR";
}

Powered by Google App Engine
This is Rietveld 408576698