Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index 906f7feef6bb30f5bf9f3787e568f1b7f9405a30..fa0ab0fd1ea82be7a1123972df97f0fa97ebf34f 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -7699,6 +7699,35 @@ MaybeObject* JSObject::OptimizeAsPrototype() { |
} |
+MUST_USE_RESULT static MaybeObject* CacheInitialJSArrayMaps( |
+ Context* native_context, Map* initial_map) { |
+ // Replace all of the cached initial array maps in the native context with |
+ // the appropriate transitioned elements kind maps. |
+ Heap* heap = native_context->GetHeap(); |
+ MaybeObject* maybe_maps = |
+ heap->AllocateFixedArrayWithHoles(kElementsKindCount); |
+ FixedArray* maps; |
+ if (!maybe_maps->To(&maps)) return maybe_maps; |
+ |
+ Map* current_map = initial_map; |
+ ElementsKind kind = current_map->elements_kind(); |
+ ASSERT(kind == GetInitialFastElementsKind()); |
+ maps->set(kind, current_map); |
+ for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1; |
+ i < kFastElementsKindCount; ++i) { |
+ Map* new_map; |
+ ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i); |
+ MaybeObject* maybe_new_map = |
+ current_map->CopyAsElementsKind(next_kind, INSERT_TRANSITION); |
+ if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
+ maps->set(next_kind, new_map); |
+ current_map = new_map; |
+ } |
+ native_context->set_js_array_maps(maps); |
+ return initial_map; |
+} |
+ |
+ |
MaybeObject* JSFunction::SetInstancePrototype(Object* value) { |
ASSERT(value->IsJSReceiver()); |
Heap* heap = GetHeap(); |
@@ -7713,14 +7742,29 @@ MaybeObject* JSFunction::SetInstancePrototype(Object* value) { |
// Now some logic for the maps of the objects that are created by using this |
// function as a constructor. |
if (has_initial_map()) { |
- // If the function has allocated the initial map |
- // replace it with a copy containing the new prototype. |
+ // If the function has allocated the initial map replace it with a |
+ // copy containing the new prototype. Also complete any in-object |
+ // slack tracking that is in progress at this point because it is |
+ // still tracking the old copy. |
+ if (shared()->IsInobjectSlackTrackingInProgress()) { |
+ shared()->CompleteInobjectSlackTracking(); |
+ } |
Map* new_map; |
- MaybeObject* maybe_new_map = initial_map()->Copy(); |
- if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
+ MaybeObject* maybe_object = initial_map()->Copy(); |
+ if (!maybe_object->To(&new_map)) return maybe_object; |
new_map->set_prototype(value); |
- MaybeObject* maybe_object = set_initial_map_and_cache_transitions(new_map); |
- if (maybe_object->IsFailure()) return maybe_object; |
+ |
+ // If the function is used as the global Array function, cache the |
+ // initial map (and transitioned versions) in the native context. |
+ Context* native_context = context()->native_context(); |
+ Object* array_function = native_context->get(Context::ARRAY_FUNCTION_INDEX); |
+ if (array_function->IsJSFunction() && |
+ this == JSFunction::cast(array_function)) { |
+ MaybeObject* ok = CacheInitialJSArrayMaps(native_context, new_map); |
+ if (ok->IsFailure()) return ok; |
+ } |
+ |
+ set_initial_map(new_map); |
} else { |
// Put the value in the initial map field until an initial map is |
// needed. At that point, a new initial map is created and the |