Fix Object.freeze on dictionary-backed arrays to properly freeze elements
authoradamk@chromium.org <adamk@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 22 May 2013 20:40:04 +0000 (20:40 +0000)
committeradamk@chromium.org <adamk@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 22 May 2013 20:40:04 +0000 (20:40 +0000)
Follow-up to r14758: slightly rearranges JSObject::Freeze() to avoid duplicating
code while still retaining proper dictionary elements storage behavior.

Also fix a lint error.

R=verwaest@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14759 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/objects.cc
test/mjsunit/object-freeze.js

index 375034c..2c8c339 100644 (file)
@@ -5408,17 +5408,12 @@ MUST_USE_RESULT MaybeObject* JSObject::Freeze(Isolate* isolate) {
       GetElementsCapacityAndUsage(&capacity, &used);
       MaybeObject* maybe_dict = SeededNumberDictionary::Allocate(heap, used);
       if (!maybe_dict->To(&new_element_dictionary)) return maybe_dict;
-      // Make sure that we never go back to fast case.
-      new_element_dictionary->set_requires_slow_elements();
 
       // Move elements to a dictionary; avoid calling NormalizeElements to avoid
       // unnecessary transitions.
       maybe_dict = CopyFastElementsToDictionary(isolate, elements(), length,
                                                 new_element_dictionary);
       if (!maybe_dict->To(&new_element_dictionary)) return maybe_dict;
-
-      // Freeze all the elements in the dictionary.
-      FreezeDictionary(new_element_dictionary);
     } else {
       // No existing elements, use a pre-allocated empty backing store
       new_element_dictionary = heap->empty_slow_element_dictionary();
@@ -5470,8 +5465,17 @@ MUST_USE_RESULT MaybeObject* JSObject::Freeze(Isolate* isolate) {
   }
 
   ASSERT(map()->has_dictionary_elements());
-  if (new_element_dictionary != NULL)
+  if (new_element_dictionary != NULL) {
     set_elements(new_element_dictionary);
+  }
+
+  if (elements() != heap->empty_slow_element_dictionary()) {
+    SeededNumberDictionary* dictionary = element_dictionary();
+    // Make sure we never go back to the fast case
+    dictionary->set_requires_slow_elements();
+    // Freeze all elements in the dictionary
+    FreezeDictionary(dictionary);
+  }
 
   return this;
 }
index 6a177a4..619ada0 100644 (file)
@@ -253,3 +253,9 @@ var func = function(arg) {
 };
 func('hello', 'world');
 func('goodbye', 'world');
+
+// Freezing sparse arrays
+var sparseArr = [0, 1];
+sparseArr[10000] = 10000;
+Object.freeze(sparseArr);
+assertTrue(Object.isFrozen(sparseArr));