Fix crash that occurs when we're forced to delete a global
property that used to be DontDelete and we still have an IC that reads from the cell. Review URL: http://codereview.chromium.org/149322 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2390 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
ef4f04bd54
commit
9aa9458933
@ -1149,6 +1149,9 @@ Object* LoadStubCompiler::CompileLoadGlobal(GlobalObject* object,
|
||||
if (!is_dont_delete) {
|
||||
__ cmp(eax, Factory::the_hole_value());
|
||||
__ j(equal, &miss, not_taken);
|
||||
} else if (FLAG_debug_code) {
|
||||
__ cmp(eax, Factory::the_hole_value());
|
||||
__ Check(not_equal, "DontDelete cells can't contain the hole");
|
||||
}
|
||||
|
||||
__ ret(0);
|
||||
|
@ -467,8 +467,15 @@ Object* JSObject::DeleteNormalizedProperty(String* name, DeleteMode mode) {
|
||||
// If we have a global object set the cell to the hole.
|
||||
if (IsGlobalObject()) {
|
||||
PropertyDetails details = dictionary->DetailsAt(entry);
|
||||
if (details.IsDontDelete() && mode != FORCE_DELETION) {
|
||||
return Heap::false_value();
|
||||
if (details.IsDontDelete()) {
|
||||
if (mode != FORCE_DELETION) return Heap::false_value();
|
||||
// When forced to delete global properties, we have to make a
|
||||
// map change to invalidate any ICs that think they can load
|
||||
// from the DontDelete cell without checking if it contains
|
||||
// the hole value.
|
||||
Object* new_map = map()->CopyDropDescriptors();
|
||||
if (new_map->IsFailure()) return new_map;
|
||||
set_map(Map::cast(new_map));
|
||||
}
|
||||
JSGlobalPropertyCell* cell =
|
||||
JSGlobalPropertyCell::cast(dictionary->ValueAt(entry));
|
||||
@ -1932,7 +1939,7 @@ Object* JSObject::IgnoreAttributesAndSetLocalProperty(
|
||||
if (!result->IsLoaded()) {
|
||||
return SetLazyProperty(result, name, value, attributes);
|
||||
}
|
||||
// Check of IsReadOnly removed from here in clone.
|
||||
// Check of IsReadOnly removed from here in clone.
|
||||
switch (result->type()) {
|
||||
case NORMAL:
|
||||
return SetNormalizedProperty(result, value);
|
||||
|
@ -6962,6 +6962,28 @@ THREADED_TEST(ForceDeleteWithInterceptor) {
|
||||
}
|
||||
|
||||
|
||||
// Make sure that forcing a delete invalidates any IC stubs, so we
|
||||
// don't read the hole value.
|
||||
THREADED_TEST(ForceDeleteIC) {
|
||||
v8::HandleScope scope;
|
||||
LocalContext context;
|
||||
// Create a DontDelete variable on the global object.
|
||||
CompileRun("this.__proto__ = { foo: 'horse' };"
|
||||
"var foo = 'fish';"
|
||||
"function f() { return foo.length; }");
|
||||
// Initialize the IC for foo in f.
|
||||
CompileRun("for (var i = 0; i < 4; i++) f();");
|
||||
// Make sure the value of foo is correct before the deletion.
|
||||
CHECK_EQ(4, CompileRun("f()")->Int32Value());
|
||||
// Force the deletion of foo.
|
||||
CHECK(context->Global()->ForceDelete(v8_str("foo")));
|
||||
// Make sure the value for foo is read from the prototype, and that
|
||||
// we don't get in trouble with reading the deleted cell value
|
||||
// sentinel.
|
||||
CHECK_EQ(5, CompileRun("f()")->Int32Value());
|
||||
}
|
||||
|
||||
|
||||
v8::Persistent<Context> calling_context0;
|
||||
v8::Persistent<Context> calling_context1;
|
||||
v8::Persistent<Context> calling_context2;
|
||||
|
Loading…
Reference in New Issue
Block a user