Empty Array prototype elements protection needs to alert on length change.
authormvstanton <mvstanton@chromium.org>
Thu, 23 Apr 2015 16:09:09 +0000 (09:09 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 23 Apr 2015 16:08:51 +0000 (16:08 +0000)
If the length of the array prototype is changed, be sure to turn off the
guarantee that it's elements are empty.

This case was missed in https://codereview.chromium.org/1092043002
("Protect the emptiness of Array prototype elements with a PropertyCell")

R=jkummerow@chromium.org
BUG=479781
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#28033}

src/isolate.cc
src/isolate.h
src/objects.cc
test/cctest/test-api.cc

index f7a2740..5427a8c 100644 (file)
@@ -2374,16 +2374,18 @@ bool Isolate::use_crankshaft() const {
 
 
 bool Isolate::IsFastArrayConstructorPrototypeChainIntact() {
-  Handle<PropertyCell> no_elements_cell =
-      handle(heap()->array_protector(), this);
+  PropertyCell* no_elements_cell = heap()->array_protector();
   bool cell_reports_intact = no_elements_cell->value()->IsSmi() &&
                              Smi::cast(no_elements_cell->value())->value() == 1;
 
 #ifdef DEBUG
   Map* root_array_map =
       get_initial_js_array_map(GetInitialFastElementsKind());
-  JSObject* initial_array_proto = JSObject::cast(*initial_array_prototype());
-  JSObject* initial_object_proto = JSObject::cast(*initial_object_prototype());
+  Context* native_context = context()->native_context();
+  JSObject* initial_array_proto = JSObject::cast(
+      native_context->get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX));
+  JSObject* initial_object_proto = JSObject::cast(
+      native_context->get(Context::INITIAL_OBJECT_PROTOTYPE_INDEX));
 
   if (root_array_map == NULL || initial_array_proto == initial_object_proto) {
     // We are in the bootstrapping process, and the entire check sequence
@@ -2426,7 +2428,6 @@ bool Isolate::IsFastArrayConstructorPrototypeChainIntact() {
 
 
 void Isolate::UpdateArrayProtectorOnSetElement(Handle<JSObject> object) {
-  Handle<PropertyCell> array_protector = factory()->array_protector();
   if (IsFastArrayConstructorPrototypeChainIntact() &&
       object->map()->is_prototype_map()) {
     Object* context = heap()->native_contexts_list();
@@ -2436,7 +2437,7 @@ void Isolate::UpdateArrayProtectorOnSetElement(Handle<JSObject> object) {
               *object ||
           current_context->get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX) ==
               *object) {
-        PropertyCell::SetValueWithInvalidation(array_protector,
+        PropertyCell::SetValueWithInvalidation(factory()->array_protector(),
                                                handle(Smi::FromInt(0), this));
         break;
       }
index fb4e069..d10e64b 100644 (file)
@@ -1021,6 +1021,9 @@ class Isolate {
   // object prototype. Also ensure that changes to prototype chain between
   // Array and Object fire notifications.
   void UpdateArrayProtectorOnSetElement(Handle<JSObject> object);
+  void UpdateArrayProtectorOnSetLength(Handle<JSObject> object) {
+    UpdateArrayProtectorOnSetElement(object);
+  }
   void UpdateArrayProtectorOnSetPrototype(Handle<JSObject> object) {
     UpdateArrayProtectorOnSetElement(object);
   }
index 9a7dcb0..f373329 100644 (file)
@@ -11911,8 +11911,11 @@ Handle<FixedArray> JSObject::SetFastElementsCapacityAndLength(
   DCHECK(!object->HasExternalArrayElements());
 
   // Allocate a new fast elements backing store.
+  Isolate* isolate = object->GetIsolate();
   Handle<FixedArray> new_elements =
-      object->GetIsolate()->factory()->NewUninitializedFixedArray(capacity);
+      isolate->factory()->NewUninitializedFixedArray(capacity);
+
+  isolate->UpdateArrayProtectorOnSetLength(object);
 
   ElementsKind elements_kind = object->GetElementsKind();
   ElementsKind new_elements_kind;
index 9ad8281..4206736 100644 (file)
@@ -16682,6 +16682,8 @@ TEST(VerifyArrayPrototypeGuarantees) {
   BreakArrayGuarantees("Object.prototype[3] = 'three';");
   BreakArrayGuarantees("Array.prototype.push(1);");
   BreakArrayGuarantees("Array.prototype.unshift(1);");
+  // Break fast array hole handling by changing length.
+  BreakArrayGuarantees("Array.prototype.length = 30;");
   // Break fast array hole handling by prototype structure changes.
   BreakArrayGuarantees("[].__proto__.__proto__ = { funny: true };");
   // By sending elements to dictionary mode.