Chromium Code Reviews| Index: src/objects.cc |
| diff --git a/src/objects.cc b/src/objects.cc |
| index 906f7feef6bb30f5bf9f3787e568f1b7f9405a30..fd3e8b73e80d3c51eb6872047aad375c2667b16a 100644 |
| --- a/src/objects.cc |
| +++ b/src/objects.cc |
| @@ -7699,28 +7699,72 @@ 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(); |
| - // First some logic for the map of the prototype to make sure it is in fast |
| - // mode. |
| + // First some logic for the map of the prototype to make sure it is in |
|
danno
2012/11/07 17:26:47
nit: unnecessary whitespace change
Michael Starzinger
2012/11/08 11:23:33
Done. My mental "break at 72 chars" algorithm kick
|
| + // fast mode. |
| if (value->IsJSObject()) { |
| MaybeObject* ok = JSObject::cast(value)->OptimizeAsPrototype(); |
| if (ok->IsFailure()) return ok; |
| } |
| - // Now some logic for the maps of the objects that are created by using this |
| - // function as a constructor. |
| + // Now some logic for the maps of the objects that are created by |
|
danno
2012/11/07 17:26:47
nit: unnecessary whitespace change
Michael Starzinger
2012/11/08 11:23:33
Done. Likewise.
|
| + // 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 inobject |
|
danno
2012/11/07 17:26:47
nit: "in object"
Michael Starzinger
2012/11/08 11:23:33
Done. Used "in-object" as discussed offline.
|
| + // 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 |