Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index c02cdd944934dbefdd02b5872735526e5a2f3f20..bbbc8f92796272eeab7ff93d97beebdff015d318 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -7902,6 +7902,31 @@ String* SeqString::Truncate(int new_length) { |
} |
+AllocationSiteInfo* AllocationSiteInfo::FindForJSObject(JSObject* object) { |
+ // Currently, AllocationSiteInfo objects are only allocated immediately |
+ // after JSArrays in NewSpace, and detecting whether a JSArray has one |
+ // involves carefully checking the object immediately after the JSArray |
+ // (if there is one) to see if it's an AllocationSiteInfo. |
+ if (FLAG_track_allocation_sites && object->GetHeap()->InNewSpace(object)) { |
+ Address ptr_end = (reinterpret_cast<Address>(object) - kHeapObjectTag) + |
+ object->Size(); |
+ if ((ptr_end + AllocationSiteInfo::kSize) <= |
+ object->GetHeap()->NewSpaceTop()) { |
+ // There is room in newspace for allocation info. Do we have some? |
+ Map** possible_allocation_site_info_map = |
+ reinterpret_cast<Map**>(ptr_end); |
+ if (*possible_allocation_site_info_map == |
+ object->GetHeap()->allocation_site_info_map()) { |
+ AllocationSiteInfo* info = AllocationSiteInfo::cast( |
+ reinterpret_cast<Object*>(ptr_end + 1)); |
+ return info; |
+ } |
+ } |
+ } |
+ return NULL; |
+} |
+ |
+ |
uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) { |
// For array indexes mix the length into the hash as an array index could |
// be zero. |
@@ -10248,6 +10273,14 @@ MaybeObject* JSObject::SetFastElement(uint32_t index, |
} |
// Convert to fast double elements if appropriate. |
if (HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) { |
+ // Consider fixing the boilerplate as well if we have one. |
+ ElementsKind to_kind = IsHoleyElementsKind(elements_kind) |
+ ? FAST_HOLEY_DOUBLE_ELEMENTS |
+ : FAST_DOUBLE_ELEMENTS; |
+ |
+ MaybeObject* trans = PossiblyTransitionArrayBoilerplate(to_kind); |
+ if (trans != NULL && trans->IsFailure()) return trans; |
+ |
MaybeObject* maybe = |
SetFastDoubleElementsCapacityAndLength(new_capacity, array_length); |
if (maybe->IsFailure()) return maybe; |
@@ -10789,6 +10822,24 @@ Handle<Object> JSObject::TransitionElementsKind(Handle<JSObject> object, |
} |
+MaybeObject* JSObject::PossiblyTransitionArrayBoilerplate( |
+ ElementsKind to_kind) { |
+ ASSERT(IsJSArray()); |
+ MaybeObject* ret = NULL; |
+ AllocationSiteInfo* info = AllocationSiteInfo::FindForJSObject(this); |
+ if (info != NULL) { |
+ JSObject* payload = JSObject::cast(info->payload()); |
+ if (payload->GetElementsKind() != to_kind) { |
+ if (IsMoreGeneralElementsKindTransition(payload->GetElementsKind(), |
+ to_kind)) { |
+ ret = payload->TransitionElementsKind(to_kind); |
+ } |
+ } |
+ } |
+ return ret; |
+} |
+ |
+ |
MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { |
ASSERT(!map()->is_observed()); |
ElementsKind from_kind = map()->elements_kind(); |
@@ -10799,6 +10850,9 @@ MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { |
if (from_kind == to_kind) return this; |
+ MaybeObject* trans = PossiblyTransitionArrayBoilerplate(to_kind); |
+ if (trans != NULL && trans->IsFailure()) return trans; |
+ |
Isolate* isolate = GetIsolate(); |
if (elements() == isolate->heap()->empty_fixed_array() || |
(IsFastSmiOrObjectElementsKind(from_kind) && |