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

Unified Diff: src/objects.cc

Issue 9050001: Ensure newly allocated empty Arrays are transitioned to FAST_ELEMENT (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: fix existing and add new tests Created 9 years 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 f3a543f0774788c6176b743e0f23d32c1f5e034f..8c379157c933b36d2bd2ed9fbdbff3e5e4af4836 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -1177,20 +1177,93 @@ void JSObject::JSObjectShortPrint(StringStream* accumulator) {
void JSObject::PrintElementsTransition(
FILE* file, ElementsKind from_kind, FixedArrayBase* from_elements,
ElementsKind to_kind, FixedArrayBase* to_elements) {
+ PrintF(file, "elements transition [");
+ PrintElementsKind(file, from_kind);
+ PrintF(file, " -> ");
+ PrintElementsKind(file, to_kind);
+ PrintF(file, "] in ");
+ JavaScriptFrame::PrintTop(file, false, true);
+ PrintF(file, " for ");
+ ShortPrint(file);
+ PrintF(file, " from ");
+ from_elements->ShortPrint(file);
+ PrintF(file, " to ");
+ to_elements->ShortPrint(file);
+ PrintF(file, "\n");
+}
+
+enum {
+ kFastElementArrayBiasIncrement = 1,
+ kFastElementArrayBiasThreshold = 3,
+ kFastSmiOnlyElementArrayBiasIncrement = -10,
+ kFastSmiOnlyElementArrayBiasThreshold = -30
+};
+
+
+void JSObject::RecordElementsTransition(
+ ElementsKind from_kind, FixedArrayBase* from_elements,
+ ElementsKind to_kind, FixedArrayBase* to_elements) {
if (from_kind != to_kind) {
- PrintF(file, "elements transition [");
- PrintElementsKind(file, from_kind);
- PrintF(file, " -> ");
- PrintElementsKind(file, to_kind);
- PrintF(file, "] in ");
- JavaScriptFrame::PrintTop(file, false, true);
- PrintF(file, " for ");
- ShortPrint(file);
- PrintF(file, " from ");
- from_elements->ShortPrint(file);
- PrintF(file, " to ");
- to_elements->ShortPrint(file);
- PrintF(file, "\n");
+ if (FLAG_trace_elements_transitions) {
+ PrintElementsTransition(stdout, from_kind, from_elements,
+ to_kind, to_elements);
+ }
+ }
+
+ // Use elements transitions to determine whether Array() should by default
+ // return an array of type FAST_SMI_ONLY_ELEMENTS or FAST_ELEMENTS. Defaulting
+ // to FAST_ELEMENTS save the expense of element transition for code that
+ // doesn't make use of double arrays. More FAST_ELEMENTS transitions than
+ // FAST_DOUBLE_ELEMENTS transitions suggest that Array() should always return
+ // elements kinds of FAST_ELEMENTS. However, FAST_DOUBLE_ELEMENTS
+ // transitions are weighted an order of magnitude heavier than FAST_ELEMENT
+ // transitions, since the savings is in general much greater if the runtime
+ // can recognize and exploit FAST_DOUBLE_ELEMENTS, even at the expense of
+ // extra transitions.
+ Context* global_context = GetIsolate()->context()->global_context();
+ if (global_context->untransitioned_js_array_map() != NULL &&
Jakob Kummerow 2012/01/04 20:55:17 Don't you mean s/NULL/GetHeap()->undefined_value()
+ IsJSArray() && from_kind == FAST_SMI_ONLY_ELEMENTS) {
+ Object* bias_object = global_context->fast_array_element_bias();
+ if (!bias_object->IsUndefined()) {
+ int bias = Smi::cast(bias_object)->value();
+ if (to_kind == FAST_ELEMENTS) {
+ bias += kFastElementArrayBiasIncrement;
+ } else {
+ ASSERT(to_kind == FAST_DOUBLE_ELEMENTS);
+ bias += kFastSmiOnlyElementArrayBiasIncrement;
+ }
+ global_context->set_fast_array_element_bias(Smi::FromInt(bias));
+ if (bias > kFastElementArrayBiasThreshold) {
+ JSFunction* array_function = global_context->array_function();
+ Map* untransitioned_map = Map::cast(
+ global_context->untransitioned_js_array_map());
+ if (untransitioned_map == array_function->initial_map()) {
+ if (untransitioned_map->elements_kind() == FAST_SMI_ONLY_ELEMENTS) {
+ bool dummy;
+ Map* transitioned_map =
+ untransitioned_map->LookupElementsTransitionMap(FAST_ELEMENTS,
+ &dummy);
Jakob Kummerow 2012/01/04 20:55:17 nit: indentation
+ if (transitioned_map != NULL) {
+ array_function->set_initial_map(transitioned_map);
+ }
+ }
+ }
+ } else if (bias < kFastSmiOnlyElementArrayBiasThreshold) {
+ JSFunction* array_function = global_context->array_function();
+ Map* untransitioned_map = Map::cast(
+ global_context->untransitioned_js_array_map());
+ if (!untransitioned_map->IsUndefined() &&
+ untransitioned_map != array_function->initial_map()) {
+ bool dummy;
+ Map* transitioned_map =
+ untransitioned_map->LookupElementsTransitionMap(FAST_ELEMENTS,
+ &dummy);
+ if (transitioned_map == array_function->initial_map()) {
+ array_function->set_initial_map(untransitioned_map);
+ }
+ }
+ }
+ }
}
}
@@ -2183,13 +2256,7 @@ void Map::LookupInDescriptors(JSObject* holder,
String* name,
LookupResult* result) {
DescriptorArray* descriptors = instance_descriptors();
- DescriptorLookupCache* cache =
- GetHeap()->isolate()->descriptor_lookup_cache();
- int number = cache->Lookup(descriptors, name);
- if (number == DescriptorLookupCache::kAbsent) {
- number = descriptors->Search(name);
- cache->Update(descriptors, name, number);
- }
+ int number = descriptors->SearchWithCache(name);
if (number != DescriptorArray::kNotFound) {
result->DescriptorResult(holder, descriptors->GetDetails(number), number);
} else {
@@ -2330,12 +2397,7 @@ Object* Map::GetDescriptorContents(String* sentinel_name,
bool* safe_to_add_transition) {
// Get the cached index for the descriptors lookup, or find and cache it.
DescriptorArray* descriptors = instance_descriptors();
- DescriptorLookupCache* cache = GetIsolate()->descriptor_lookup_cache();
- int index = cache->Lookup(descriptors, sentinel_name);
- if (index == DescriptorLookupCache::kAbsent) {
- index = descriptors->Search(sentinel_name);
- cache->Update(descriptors, sentinel_name, index);
- }
+ int index = descriptors->SearchWithCache(sentinel_name);
// If the transition already exists, return its descriptor.
if (index != DescriptorArray::kNotFound) {
PropertyDetails details(descriptors->GetDetails(index));
@@ -8280,10 +8342,8 @@ MaybeObject* JSObject::SetFastElementsCapacityAndLength(
break;
}
- if (FLAG_trace_elements_transitions) {
- PrintElementsTransition(stdout, elements_kind, old_elements_raw,
- FAST_ELEMENTS, new_elements);
- }
+ RecordElementsTransition(elements_kind, old_elements_raw,
+ FAST_ELEMENTS, new_elements);
// Update the length if necessary.
if (IsJSArray()) {
@@ -8336,10 +8396,8 @@ MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength(
break;
}
- if (FLAG_trace_elements_transitions) {
- PrintElementsTransition(stdout, elements_kind, old_elements,
- FAST_DOUBLE_ELEMENTS, elems);
- }
+ RecordElementsTransition(elements_kind, old_elements,
+ FAST_DOUBLE_ELEMENTS, elems);
ASSERT(new_map->has_fast_double_elements());
set_map(new_map);
@@ -9118,14 +9176,8 @@ MaybeObject* JSObject::SetFastElement(uint32_t index,
}
// Change elements kind from SMI_ONLY to generic FAST if necessary.
if (HasFastSmiOnlyElements() && !value->IsSmi()) {
- MaybeObject* maybe_new_map = GetElementsTransitionMap(FAST_ELEMENTS);
- Map* new_map;
- if (!maybe_new_map->To<Map>(&new_map)) return maybe_new_map;
- set_map(new_map);
- if (FLAG_trace_elements_transitions) {
- PrintElementsTransition(stdout, FAST_SMI_ONLY_ELEMENTS, elements(),
- FAST_ELEMENTS, elements());
- }
+ MaybeObject* maybe = TransitionElementsKind(FAST_ELEMENTS);
+ if (maybe->IsFailure()) return maybe;
}
// Increase backing store capacity if that's been decided previously.
if (new_capacity != capacity) {
@@ -9494,6 +9546,8 @@ MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
MUST_USE_RESULT MaybeObject* JSObject::TransitionElementsKind(
ElementsKind to_kind) {
ElementsKind from_kind = map()->elements_kind();
+ if (from_kind == to_kind) return this;
+
FixedArrayBase* elms = FixedArrayBase::cast(elements());
uint32_t capacity = static_cast<uint32_t>(elms->length());
uint32_t length = capacity;
@@ -9514,9 +9568,7 @@ MUST_USE_RESULT MaybeObject* JSObject::TransitionElementsKind(
MaybeObject* maybe_new_map = GetElementsTransitionMap(to_kind);
Map* new_map;
if (!maybe_new_map->To(&new_map)) return maybe_new_map;
- if (FLAG_trace_elements_transitions) {
- PrintElementsTransition(stdout, from_kind, elms, to_kind, elms);
- }
+ RecordElementsTransition(from_kind, elms, to_kind, elms);
set_map(new_map);
return this;
}

Powered by Google App Engine
This is Rietveld 408576698