| Index: src/objects.cc
|
| ===================================================================
|
| --- src/objects.cc (revision 11720)
|
| +++ src/objects.cc (working copy)
|
| @@ -1580,7 +1580,7 @@
|
| }
|
|
|
| if (map()->unused_property_fields() == 0) {
|
| - if (properties()->length() > MaxFastProperties()) {
|
| + if (TooManyFastProperties(properties()->length())) {
|
| Object* obj;
|
| { MaybeObject* maybe_obj =
|
| NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
|
| @@ -1830,7 +1830,7 @@
|
| Object* new_value,
|
| PropertyAttributes attributes) {
|
| if (map()->unused_property_fields() == 0 &&
|
| - properties()->length() > MaxFastProperties()) {
|
| + TooManyFastProperties(properties()->length())) {
|
| Object* obj;
|
| { MaybeObject* maybe_obj =
|
| NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
|
| @@ -5042,6 +5042,7 @@
|
| return new_map;
|
| }
|
|
|
| +
|
| void Map::UpdateCodeCache(Handle<Map> map,
|
| Handle<String> name,
|
| Handle<Code> code) {
|
| @@ -7612,9 +7613,57 @@
|
| }
|
|
|
|
|
| +MaybeObject* JSObject::OptimizeAsPrototype() {
|
| + if (IsGlobalObject()) return this;
|
| +
|
| + // Make sure prototypes are fast objects and their maps have the bit set
|
| + // so they remain fast.
|
| + Map* proto_map = map();
|
| + if (!proto_map->used_for_prototype()) {
|
| + if (!HasFastProperties()) {
|
| + MaybeObject* new_proto = TransformToFastProperties(0);
|
| + if (new_proto->IsFailure()) return new_proto;
|
| + ASSERT(new_proto == this);
|
| + proto_map = map();
|
| + if (!proto_map->is_shared()) {
|
| + proto_map->set_used_for_prototype(true);
|
| + }
|
| + } else {
|
| + Heap* heap = GetHeap();
|
| + // We use the hole value as a singleton key in the prototype transition
|
| + // map so that we don't multiply the number of maps unnecessarily.
|
| + Map* new_map =
|
| + proto_map->GetPrototypeTransition(heap->the_hole_value());
|
| + if (new_map == NULL) {
|
| + MaybeObject* maybe_new_map = proto_map->CopyDropTransitions();
|
| + if (!maybe_new_map->To<Map>(&new_map)) return maybe_new_map;
|
| + new_map->set_used_for_prototype(true);
|
| + MaybeObject* ok =
|
| + proto_map->PutPrototypeTransition(heap->the_hole_value(),
|
| + new_map);
|
| + if (ok->IsFailure()) return ok;
|
| + }
|
| + ASSERT(!proto_map->is_shared() && !new_map->is_shared());
|
| + set_map(new_map);
|
| + }
|
| + }
|
| + return this;
|
| +}
|
| +
|
| +
|
| MaybeObject* JSFunction::SetInstancePrototype(Object* value) {
|
| ASSERT(value->IsJSReceiver());
|
| Heap* heap = GetHeap();
|
| +
|
| + // First some logic for the map of the prototype to make sure the
|
| + // used_for_prototype flag is set.
|
| + 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.
|
| if (has_initial_map()) {
|
| // If the function has allocated the initial map
|
| // replace it with a copy containing the new prototype.
|
| @@ -8786,7 +8835,7 @@
|
| }
|
|
|
|
|
| -Object* Map::GetPrototypeTransition(Object* prototype) {
|
| +Map* Map::GetPrototypeTransition(Object* prototype) {
|
| FixedArray* cache = prototype_transitions();
|
| int number_of_transitions = NumberOfProtoTransitions();
|
| const int proto_offset =
|
| @@ -8796,8 +8845,7 @@
|
| for (int i = 0; i < number_of_transitions; i++) {
|
| if (cache->get(proto_offset + i * step) == prototype) {
|
| Object* map = cache->get(map_offset + i * step);
|
| - ASSERT(map->IsMap());
|
| - return map;
|
| + return Map::cast(map);
|
| }
|
| }
|
| return NULL;
|
| @@ -8905,21 +8953,26 @@
|
| // Nothing to do if prototype is already set.
|
| if (map->prototype() == value) return value;
|
|
|
| - Object* new_map = map->GetPrototypeTransition(value);
|
| + if (value->IsJSObject()) {
|
| + MaybeObject* ok = JSObject::cast(value)->OptimizeAsPrototype();
|
| + if (ok->IsFailure()) return ok;
|
| + }
|
| +
|
| + Map* new_map = map->GetPrototypeTransition(value);
|
| if (new_map == NULL) {
|
| { MaybeObject* maybe_new_map = map->CopyDropTransitions();
|
| - if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
|
| + if (!maybe_new_map->To<Map>(&new_map)) return maybe_new_map;
|
| }
|
|
|
| { MaybeObject* maybe_new_cache =
|
| - map->PutPrototypeTransition(value, Map::cast(new_map));
|
| + map->PutPrototypeTransition(value, new_map);
|
| if (maybe_new_cache->IsFailure()) return maybe_new_cache;
|
| }
|
|
|
| - Map::cast(new_map)->set_prototype(value);
|
| + new_map->set_prototype(value);
|
| }
|
| - ASSERT(Map::cast(new_map)->prototype() == value);
|
| - real_receiver->set_map(Map::cast(new_map));
|
| + ASSERT(new_map->prototype() == value);
|
| + real_receiver->set_map(new_map);
|
|
|
| heap->ClearInstanceofCache();
|
| ASSERT(size == Size());
|
|
|