Author: [email protected]
Date: Wed Jul  8 04:32:03 2009
New Revision: 2390

Modified:
    branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
    branches/bleeding_edge/src/objects.cc
    branches/bleeding_edge/test/cctest/test-api.cc

Log:
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

Modified: branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/ia32/stub-cache-ia32.cc  (original)
+++ branches/bleeding_edge/src/ia32/stub-cache-ia32.cc  Wed Jul  8 04:32:03  
2009
@@ -1149,6 +1149,9 @@
    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);

Modified: branches/bleeding_edge/src/objects.cc
==============================================================================
--- branches/bleeding_edge/src/objects.cc       (original)
+++ branches/bleeding_edge/src/objects.cc       Wed Jul  8 04:32:03 2009
@@ -467,8 +467,15 @@
      // 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 @@
    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);

Modified: branches/bleeding_edge/test/cctest/test-api.cc
==============================================================================
--- branches/bleeding_edge/test/cctest/test-api.cc      (original)
+++ branches/bleeding_edge/test/cctest/test-api.cc      Wed Jul  8 04:32:03 2009
@@ -6962,6 +6962,28 @@
  }


+// 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;

--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to