Chromium Code Reviews| 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; |
| } |