Revision: 8826
Author:   [email protected]
Date:     Thu Aug  4 04:42:14 2011
Log:      Move element deletion into element handlers

BUG=none
TEST=none

Review URL: http://codereview.chromium.org/7566004
http://code.google.com/p/v8/source/detail?r=8826

Modified:
 /branches/bleeding_edge/src/elements.cc
 /branches/bleeding_edge/src/elements.h
 /branches/bleeding_edge/src/objects.cc
 /branches/bleeding_edge/src/objects.h

=======================================
--- /branches/bleeding_edge/src/elements.cc     Wed Aug  3 04:12:46 2011
+++ /branches/bleeding_edge/src/elements.cc     Thu Aug  4 04:42:14 2011
@@ -68,6 +68,10 @@
     }
     return obj->GetHeap()->the_hole_value();
   }
+
+  virtual MaybeObject* Delete(JSObject* obj,
+                              uint32_t index,
+                              JSReceiver::DeleteMode mode) = 0;

  protected:
   static BackingStoreClass* GetBackingStore(JSObject* obj) {
@@ -85,12 +89,73 @@

 class FastElementsAccessor
     : public ElementsAccessorBase<FastElementsAccessor, FixedArray> {
+ public:
+  static MaybeObject* DeleteCommon(JSObject* obj,
+                                   uint32_t index) {
+    ASSERT(obj->HasFastElements() || obj->HasFastArgumentsElements());
+    Heap* heap = obj->GetHeap();
+    FixedArray* backing_store = FixedArray::cast(obj->elements());
+ if (backing_store->map() == heap->non_strict_arguments_elements_map()) {
+      backing_store = FixedArray::cast(backing_store->get(1));
+    } else {
+      Object* writable;
+      MaybeObject* maybe = obj->EnsureWritableFastElements();
+      if (!maybe->ToObject(&writable)) return maybe;
+      backing_store = FixedArray::cast(writable);
+    }
+    uint32_t length = static_cast<uint32_t>(
+        obj->IsJSArray()
+        ? Smi::cast(JSArray::cast(obj)->length())->value()
+        : backing_store->length());
+    if (index < length) {
+      backing_store->set_the_hole(index);
+      // If an old space backing store is larger than a certain size and
+      // has too few used values, normalize it.
+      // To avoid doing the check on every delete we require at least
+      // one adjacent hole to the value being deleted.
+      Object* hole = heap->the_hole_value();
+      const int kMinLengthForSparsenessCheck = 64;
+      if (backing_store->length() >= kMinLengthForSparsenessCheck &&
+          !heap->InNewSpace(backing_store) &&
+          ((index > 0 && backing_store->get(index - 1) == hole) ||
+ (index + 1 < length && backing_store->get(index + 1) == hole))) {
+        int num_used = 0;
+        for (int i = 0; i < backing_store->length(); ++i) {
+          if (backing_store->get(i) != hole) ++num_used;
+          // Bail out early if more than 1/4 is used.
+          if (4 * num_used > backing_store->length()) break;
+        }
+        if (4 * num_used <= backing_store->length()) {
+          MaybeObject* result = obj->NormalizeElements();
+          if (result->IsFailure()) return result;
+        }
+      }
+    }
+    return heap->true_value();
+  }
+
+  virtual MaybeObject* Delete(JSObject* obj,
+                              uint32_t index,
+                              JSReceiver::DeleteMode mode) {
+    return DeleteCommon(obj, index);
+  }
 };


 class FastDoubleElementsAccessor
     : public ElementsAccessorBase<FastDoubleElementsAccessor,
                                   FixedDoubleArray> {
+  virtual MaybeObject* Delete(JSObject* obj,
+                              uint32_t index,
+                              JSReceiver::DeleteMode mode) {
+    int length = obj->IsJSArray()
+        ? Smi::cast(JSArray::cast(obj)->length())->value()
+        : FixedDoubleArray::cast(obj->elements())->length();
+    if (index < static_cast<uint32_t>(length)) {
+      FixedDoubleArray::cast(obj->elements())->set_the_hole(index);
+    }
+    return obj->GetHeap()->true_value();
+  }
 };


@@ -112,6 +177,13 @@
       return obj->GetHeap()->undefined_value();
     }
   }
+
+  virtual MaybeObject* Delete(JSObject* obj,
+                              uint32_t index,
+                              JSReceiver::DeleteMode mode) {
+    // External arrays always ignore deletes.
+    return obj->GetHeap()->true_value();
+  }
 };


@@ -193,6 +265,57 @@
     }
     return obj->GetHeap()->the_hole_value();
   }
+
+
+  static MaybeObject* DeleteCommon(JSObject* obj,
+                                   uint32_t index,
+                                   JSReceiver::DeleteMode mode) {
+    Isolate* isolate = obj->GetIsolate();
+    Heap* heap = isolate->heap();
+    FixedArray* backing_store = FixedArray::cast(obj->elements());
+    bool is_arguments =
+ (obj->GetElementsKind() == JSObject::NON_STRICT_ARGUMENTS_ELEMENTS);
+    if (is_arguments) {
+      backing_store = FixedArray::cast(backing_store->get(1));
+    }
+    NumberDictionary* dictionary = NumberDictionary::cast(backing_store);
+    int entry = dictionary->FindEntry(index);
+    if (entry != NumberDictionary::kNotFound) {
+      Object* result = dictionary->DeleteProperty(entry, mode);
+      if (result == heap->true_value()) {
+        MaybeObject* maybe_elements = dictionary->Shrink(index);
+        FixedArray* new_elements = NULL;
+        if (!maybe_elements->To(&new_elements)) {
+          return maybe_elements;
+        }
+        if (is_arguments) {
+          FixedArray::cast(obj->elements())->set(1, new_elements);
+        } else {
+          obj->set_elements(new_elements);
+        }
+      }
+      if (mode == JSObject::STRICT_DELETION &&
+          result == heap->false_value()) {
+        // In strict mode, attempting to delete a non-configurable property
+        // throws an exception.
+        HandleScope scope(isolate);
+        Handle<Object> holder(obj);
+        Handle<Object> name = isolate->factory()->NewNumberFromUint(index);
+        Handle<Object> args[2] = { name, holder };
+        Handle<Object> error =
+            isolate->factory()->NewTypeError("strict_delete_property",
+                                             HandleVector(args, 2));
+        return isolate->Throw(*error);
+      }
+    }
+    return heap->true_value();
+  }
+
+  virtual MaybeObject* Delete(JSObject* obj,
+                              uint32_t index,
+                              JSReceiver::DeleteMode mode) {
+    return DeleteCommon(obj, index, mode);
+  }

   virtual MaybeObject* GetWithReceiver(JSObject* obj,
                                        Object* receiver,
@@ -236,6 +359,29 @@
     }
     return obj->GetHeap()->the_hole_value();
   }
+
+  virtual MaybeObject* Delete(JSObject* obj,
+                              uint32_t index,
+                              JSReceiver::DeleteMode mode) {
+    FixedArray* parameter_map = FixedArray::cast(obj->elements());
+    uint32_t length = parameter_map->length();
+    Object* probe =
+        index < (length - 2) ? parameter_map->get(index + 2) : NULL;
+    if (probe != NULL && !probe->IsTheHole()) {
+      // TODO(kmillikin): We could check if this was the last aliased
+      // parameter, and revert to normal elements in that case.  That
+      // would enable GC of the context.
+      parameter_map->set_the_hole(index + 2);
+    } else {
+      FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
+      if (arguments->IsDictionary()) {
+        return DictionaryElementsAccessor::DeleteCommon(obj, index, mode);
+      } else {
+        return FastElementsAccessor::DeleteCommon(obj, index);
+      }
+    }
+    return obj->GetHeap()->true_value();
+  }
 };


=======================================
--- /branches/bleeding_edge/src/elements.h      Wed Aug  3 04:12:46 2011
+++ /branches/bleeding_edge/src/elements.h      Thu Aug  4 04:42:14 2011
@@ -43,6 +43,10 @@
                                        Object* receiver,
                                        uint32_t index) = 0;

+  virtual MaybeObject* Delete(JSObject* obj,
+                              uint32_t index,
+                              JSReceiver::DeleteMode mode) = 0;
+
   // Returns a shared ElementsAccessor for the specified ElementsKind.
   static ElementsAccessor* ForKind(JSObject::ElementsKind elements_kind) {
     ASSERT(elements_kind < JSObject::kElementsKindCount);
=======================================
--- /branches/bleeding_edge/src/objects.cc      Thu Aug  4 02:23:25 2011
+++ /branches/bleeding_edge/src/objects.cc      Thu Aug  4 04:42:14 2011
@@ -3138,48 +3138,6 @@
   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   return raw_result;
 }
-
-
-MaybeObject* JSObject::DeleteElementPostInterceptor(uint32_t index,
-                                                    DeleteMode mode) {
-  ASSERT(!HasExternalArrayElements());
-  switch (GetElementsKind()) {
-    case FAST_ELEMENTS: {
-      Object* obj;
-      { MaybeObject* maybe_obj = EnsureWritableFastElements();
-        if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-      }
-      uint32_t length = IsJSArray() ?
- static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) :
-      static_cast<uint32_t>(FixedArray::cast(elements())->length());
-      if (index < length) {
-        FixedArray::cast(elements())->set_the_hole(index);
-      }
-      break;
-    }
-    case DICTIONARY_ELEMENTS: {
-      NumberDictionary* dictionary = element_dictionary();
-      int entry = dictionary->FindEntry(index);
-      if (entry != NumberDictionary::kNotFound) {
-        Object* deleted = dictionary->DeleteProperty(entry, mode);
-        if (deleted == GetHeap()->true_value()) {
-          MaybeObject* maybe_elements = dictionary->Shrink(index);
-          FixedArray* new_elements = NULL;
-          if (!maybe_elements->To(&new_elements)) {
-            return maybe_elements;
-          }
-          set_elements(new_elements);
-        }
-        return deleted;
-      }
-      break;
-    }
-    default:
-      UNREACHABLE();
-      break;
-  }
-  return GetHeap()->true_value();
-}


 MaybeObject* JSObject::DeleteElementWithInterceptor(uint32_t index) {
@@ -3209,98 +3167,12 @@
     ASSERT(result->IsBoolean());
     return *v8::Utils::OpenHandle(*result);
   }
-  MaybeObject* raw_result =
-      this_handle->DeleteElementPostInterceptor(index, NORMAL_DELETION);
+  MaybeObject* raw_result = GetElementsAccessor()->Delete(*this_handle,
+                                                          index,
+                                                          NORMAL_DELETION);
   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   return raw_result;
 }
-
-
-MaybeObject* JSObject::DeleteFastElement(uint32_t index) {
-  ASSERT(HasFastElements() || HasFastArgumentsElements());
-  Heap* heap = GetHeap();
-  FixedArray* backing_store = FixedArray::cast(elements());
-  if (backing_store->map() == heap->non_strict_arguments_elements_map()) {
-    backing_store = FixedArray::cast(backing_store->get(1));
-  } else {
-    Object* writable;
-    MaybeObject* maybe = EnsureWritableFastElements();
-    if (!maybe->ToObject(&writable)) return maybe;
-    backing_store = FixedArray::cast(writable);
-  }
-  uint32_t length = static_cast<uint32_t>(
-      IsJSArray()
-      ? Smi::cast(JSArray::cast(this)->length())->value()
-      : backing_store->length());
-  if (index < length) {
-    backing_store->set_the_hole(index);
-    // If an old space backing store is larger than a certain size and
-    // has too few used values, normalize it.
-    // To avoid doing the check on every delete we require at least
-    // one adjacent hole to the value being deleted.
-    Object* hole = heap->the_hole_value();
-    const int kMinLengthForSparsenessCheck = 64;
-    if (backing_store->length() >= kMinLengthForSparsenessCheck &&
-        !heap->InNewSpace(backing_store) &&
-        ((index > 0 && backing_store->get(index - 1) == hole) ||
-         (index + 1 < length && backing_store->get(index + 1) == hole))) {
-      int num_used = 0;
-      for (int i = 0; i < backing_store->length(); ++i) {
-        if (backing_store->get(i) != hole) ++num_used;
-        // Bail out early if more than 1/4 is used.
-        if (4 * num_used > backing_store->length()) break;
-      }
-      if (4 * num_used <= backing_store->length()) {
-        MaybeObject* result = NormalizeElements();
-        if (result->IsFailure()) return result;
-      }
-    }
-  }
-  return heap->true_value();
-}
-
-
-MaybeObject* JSObject::DeleteDictionaryElement(uint32_t index,
-                                               DeleteMode mode) {
-  Isolate* isolate = GetIsolate();
-  Heap* heap = isolate->heap();
-  FixedArray* backing_store = FixedArray::cast(elements());
-  bool is_arguments =
-      (GetElementsKind() == JSObject::NON_STRICT_ARGUMENTS_ELEMENTS);
-  if (is_arguments) {
-    backing_store = FixedArray::cast(backing_store->get(1));
-  }
-  NumberDictionary* dictionary = NumberDictionary::cast(backing_store);
-  int entry = dictionary->FindEntry(index);
-  if (entry != NumberDictionary::kNotFound) {
-    Object* result = dictionary->DeleteProperty(entry, mode);
-    if (result == heap->true_value()) {
-      MaybeObject* maybe_elements = dictionary->Shrink(index);
-      FixedArray* new_elements = NULL;
-      if (!maybe_elements->To(&new_elements)) {
-        return maybe_elements;
-      }
-      if (is_arguments) {
-        FixedArray::cast(elements())->set(1, new_elements);
-      } else {
-        set_elements(new_elements);
-      }
-    }
-    if (mode == STRICT_DELETION && result == heap->false_value()) {
-      // In strict mode, attempting to delete a non-configurable property
-      // throws an exception.
-      HandleScope scope(isolate);
-      Handle<Object> holder(this);
-      Handle<Object> name = isolate->factory()->NewNumberFromUint(index);
-      Handle<Object> args[2] = { name, holder };
-      Handle<Object> error =
-          isolate->factory()->NewTypeError("strict_delete_property",
-                                           HandleVector(args, 2));
-      return isolate->Throw(*error);
-    }
-  }
-  return heap->true_value();
-}


 MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) {
@@ -3321,62 +3193,13 @@

   if (HasIndexedInterceptor()) {
     // Skip interceptor if forcing deletion.
-    return (mode == FORCE_DELETION)
-        ? DeleteElementPostInterceptor(index, FORCE_DELETION)
-        : DeleteElementWithInterceptor(index);
-  }
-
-  switch (GetElementsKind()) {
-    case FAST_ELEMENTS:
-      return DeleteFastElement(index);
-
-    case DICTIONARY_ELEMENTS:
-      return DeleteDictionaryElement(index, mode);
-
-    case FAST_DOUBLE_ELEMENTS: {
-      int length = IsJSArray()
-          ? Smi::cast(JSArray::cast(this)->length())->value()
-          : FixedDoubleArray::cast(elements())->length();
-      if (index < static_cast<uint32_t>(length)) {
-        FixedDoubleArray::cast(elements())->set_the_hole(index);
-      }
-      break;
-    }
-    case EXTERNAL_PIXEL_ELEMENTS:
-    case EXTERNAL_BYTE_ELEMENTS:
-    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
-    case EXTERNAL_SHORT_ELEMENTS:
-    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
-    case EXTERNAL_INT_ELEMENTS:
-    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
-    case EXTERNAL_FLOAT_ELEMENTS:
-    case EXTERNAL_DOUBLE_ELEMENTS:
-      // Pixel and external array elements cannot be deleted. Just
-      // silently ignore here.
-      break;
-
-    case NON_STRICT_ARGUMENTS_ELEMENTS: {
-      FixedArray* parameter_map = FixedArray::cast(elements());
-      uint32_t length = parameter_map->length();
-      Object* probe =
-          index < (length - 2) ? parameter_map->get(index + 2) : NULL;
-      if (probe != NULL && !probe->IsTheHole()) {
-        // TODO(kmillikin): We could check if this was the last aliased
-        // parameter, and revert to normal elements in that case.  That
-        // would enable GC of the context.
-        parameter_map->set_the_hole(index + 2);
-      } else {
-        FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
-        if (arguments->IsDictionary()) {
-          return DeleteDictionaryElement(index, mode);
-        } else {
-          return DeleteFastElement(index);
-        }
-      }
-      break;
-    }
-  }
-  return isolate->heap()->true_value();
+    if (mode != FORCE_DELETION) {
+      return DeleteElementWithInterceptor(index);
+    }
+    mode = JSReceiver::FORCE_DELETION;
+  }
+
+  return GetElementsAccessor()->Delete(this, index, mode);
 }


=======================================
--- /branches/bleeding_edge/src/objects.h       Thu Aug  4 02:23:25 2011
+++ /branches/bleeding_edge/src/objects.h       Thu Aug  4 04:42:14 2011
@@ -2030,8 +2030,6 @@
DeleteMode mode);
   MUST_USE_RESULT MaybeObject* DeletePropertyWithInterceptor(String* name);

-  MUST_USE_RESULT MaybeObject* DeleteElementPostInterceptor(uint32_t index,
- DeleteMode mode); MUST_USE_RESULT MaybeObject* DeleteElementWithInterceptor(uint32_t index);

   MUST_USE_RESULT MaybeObject* DeleteFastElement(uint32_t index);

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

Reply via email to