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:
parent
b8568ec86c
commit
c906efd5d1
@ -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
|
||||
|
||||
|
26
test/mjsunit/regress/regress-crbug-513602.js
Normal file
26
test/mjsunit/regress/regress-crbug-513602.js
Normal 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();
|
Loading…
Reference in New Issue
Block a user