Fix prototype registration upon SlowToFast migration

When a prototype object migrates from a slow to a fast map, where the slow map
was registered as a user of its own prototype, then the registration must be
transferred to the new map (just like MigrateToMap does for all other cases).

BUG=chromium:513602
LOG=y
NOTREECHECKS=true

Review URL: https://codereview.chromium.org/1263543004

Cr-Commit-Position: refs/heads/master@{#29898}
This commit is contained in:
jkummerow 2015-07-28 08:41:20 -07:00 committed by Commit bot
parent b8568ec86c
commit c906efd5d1
2 changed files with 46 additions and 8 deletions

View File

@ -4644,20 +4644,32 @@ void JSObject::MigrateSlowToFast(Handle<JSObject> object,
}
}
int inobject_props = object->map()->inobject_properties();
Handle<Map> old_map(object->map(), isolate);
int inobject_props = old_map->inobject_properties();
// Allocate new map.
Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map()));
Handle<Map> new_map = Map::CopyDropDescriptors(old_map);
new_map->set_dictionary_map(false);
if (object->map()->is_prototype_map()) {
if (old_map->is_prototype_map() && FLAG_track_prototype_users) {
DCHECK(new_map->is_prototype_map());
new_map->set_prototype_info(object->map()->prototype_info());
object->map()->set_prototype_info(Smi::FromInt(0));
Object* maybe_old_prototype = old_map->prototype();
if (maybe_old_prototype->IsJSObject()) {
Handle<JSObject> old_prototype(JSObject::cast(maybe_old_prototype));
bool was_registered =
JSObject::UnregisterPrototypeUser(old_prototype, old_map);
if (was_registered) {
JSObject::LazyRegisterPrototypeUser(new_map, isolate);
}
}
new_map->set_prototype_info(old_map->prototype_info());
old_map->set_prototype_info(Smi::FromInt(0));
if (FLAG_trace_prototype_users) {
PrintF("Moving prototype_info %p from map %p to map %p.\n",
reinterpret_cast<void*>(new_map->prototype_info()),
reinterpret_cast<void*>(object->map()),
reinterpret_cast<void*>(*old_map),
reinterpret_cast<void*>(*new_map));
}
}
@ -4665,8 +4677,8 @@ void JSObject::MigrateSlowToFast(Handle<JSObject> object,
#if TRACE_MAPS
if (FLAG_trace_maps) {
PrintF("[TraceMaps: SlowToFast from= %p to= %p reason= %s ]\n",
reinterpret_cast<void*>(object->map()),
reinterpret_cast<void*>(*new_map), reason);
reinterpret_cast<void*>(*old_map), reinterpret_cast<void*>(*new_map),
reason);
}
#endif

View File

@ -0,0 +1,26 @@
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function Parent() {}
function Child() {}
Child.prototype = new Parent();
var child = new Child();
function crash() {
return child.__proto__;
}
crash();
crash();
// Trigger a fast->slow->fast dance of Parent.prototype's map...
Parent.prototype.__defineSetter__("foo", function() { print("A"); });
Parent.prototype.__defineSetter__("foo", function() { print("B"); });
// ...and collect more type feedback.
crash();
// Now modify the prototype chain. The right cell fails to get invalidated.
delete Object.prototype.__proto__;
crash();