| Index: src/elements.cc
|
| diff --git a/src/elements.cc b/src/elements.cc
|
| index 2b705091adeb385a1c78b2f8c78a87b0fa7e8a2d..9414c931206c14fdc59193e2909e6a5c44adec51 100644
|
| --- a/src/elements.cc
|
| +++ b/src/elements.cc
|
| @@ -718,8 +718,9 @@ class ElementsAccessorBase : public ElementsAccessor {
|
| ElementsAccessorSubclass::GrowCapacityAndConvertImpl(object, capacity);
|
| }
|
|
|
| - virtual void Delete(Handle<JSObject> obj, uint32_t key,
|
| - LanguageMode language_mode) override = 0;
|
| + virtual void Delete(Handle<JSObject> obj, uint32_t index) final {
|
| + ElementsAccessorSubclass::DeleteImpl(obj, index);
|
| + }
|
|
|
| static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
|
| FixedArrayBase* to, ElementsKind from_kind,
|
| @@ -976,37 +977,16 @@ class DictionaryElementsAccessor
|
| }
|
|
|
|
|
| - static void DeleteCommon(Handle<JSObject> obj, uint32_t key,
|
| - LanguageMode language_mode) {
|
| - Isolate* isolate = obj->GetIsolate();
|
| - Handle<FixedArray> backing_store(FixedArray::cast(obj->elements()),
|
| - isolate);
|
| - bool is_arguments = obj->HasSloppyArgumentsElements();
|
| - if (is_arguments) {
|
| - backing_store = handle(FixedArray::cast(backing_store->get(1)), isolate);
|
| - }
|
| - Handle<SeededNumberDictionary> dictionary =
|
| - Handle<SeededNumberDictionary>::cast(backing_store);
|
| - int entry = dictionary->FindEntry(key);
|
| - if (entry != SeededNumberDictionary::kNotFound) {
|
| - Handle<Object> result =
|
| - SeededNumberDictionary::DeleteProperty(dictionary, entry);
|
| - USE(result);
|
| - DCHECK(result->IsTrue());
|
| - Handle<FixedArray> new_elements =
|
| - SeededNumberDictionary::Shrink(dictionary, key);
|
| -
|
| - if (is_arguments) {
|
| - FixedArray::cast(obj->elements())->set(1, *new_elements);
|
| - } else {
|
| - obj->set_elements(*new_elements);
|
| - }
|
| - }
|
| - }
|
| -
|
| - virtual void Delete(Handle<JSObject> obj, uint32_t key,
|
| - LanguageMode language_mode) final {
|
| - DeleteCommon(obj, key, language_mode);
|
| + static void DeleteImpl(Handle<JSObject> obj, uint32_t index) {
|
| + // TODO(verwaest): Remove reliance on key in Shrink.
|
| + Handle<SeededNumberDictionary> dict(
|
| + SeededNumberDictionary::cast(obj->elements()));
|
| + uint32_t key = GetKeyForIndexImpl(*dict, index);
|
| + Handle<Object> result = SeededNumberDictionary::DeleteProperty(dict, index);
|
| + USE(result);
|
| + DCHECK(result->IsTrue());
|
| + Handle<FixedArray> new_elements = SeededNumberDictionary::Shrink(dict, key);
|
| + obj->set_elements(*new_elements);
|
| }
|
|
|
| static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key,
|
| @@ -1101,58 +1081,38 @@ class FastElementsAccessor
|
|
|
| typedef typename KindTraits::BackingStore BackingStore;
|
|
|
| - static void DeleteCommon(Handle<JSObject> obj, uint32_t key,
|
| - LanguageMode language_mode) {
|
| + static void DeleteCommon(Handle<JSObject> obj, uint32_t index,
|
| + Handle<FixedArrayBase> store) {
|
| DCHECK(obj->HasFastSmiOrObjectElements() ||
|
| obj->HasFastDoubleElements() ||
|
| obj->HasFastArgumentsElements());
|
| - Isolate* isolate = obj->GetIsolate();
|
| - Heap* heap = obj->GetHeap();
|
| - Handle<FixedArrayBase> elements(obj->elements());
|
| - if (*elements == heap->empty_fixed_array()) return;
|
| -
|
| - Handle<BackingStore> backing_store = Handle<BackingStore>::cast(elements);
|
| - bool is_sloppy_arguments_elements_map =
|
| - backing_store->map() == heap->sloppy_arguments_elements_map();
|
| - if (is_sloppy_arguments_elements_map) {
|
| - backing_store = handle(
|
| - BackingStore::cast(Handle<FixedArray>::cast(backing_store)->get(1)),
|
| - isolate);
|
| + Handle<BackingStore> backing_store = Handle<BackingStore>::cast(store);
|
| + backing_store->set_the_hole(index);
|
| +
|
| + // TODO(verwaest): Move this out of elements.cc.
|
| + // 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.
|
| + const int kMinLengthForSparsenessCheck = 64;
|
| + if (backing_store->length() < kMinLengthForSparsenessCheck) return;
|
| + if (backing_store->GetHeap()->InNewSpace(*backing_store)) return;
|
| + uint32_t length = 0;
|
| + if (obj->IsJSArray()) {
|
| + JSArray::cast(*obj)->length()->ToArrayLength(&length);
|
| + } else {
|
| + length = static_cast<uint32_t>(store->length());
|
| }
|
| - uint32_t length = static_cast<uint32_t>(
|
| - obj->IsJSArray()
|
| - ? Smi::cast(Handle<JSArray>::cast(obj)->length())->value()
|
| - : backing_store->length());
|
| - if (key < length) {
|
| - if (!is_sloppy_arguments_elements_map) {
|
| - ElementsKind kind = KindTraits::Kind;
|
| - if (IsFastPackedElementsKind(kind)) {
|
| - JSObject::TransitionElementsKind(obj, GetHoleyElementsKind(kind));
|
| - }
|
| - if (IsFastSmiOrObjectElementsKind(KindTraits::Kind)) {
|
| - Handle<Object> writable = JSObject::EnsureWritableFastElements(obj);
|
| - backing_store = Handle<BackingStore>::cast(writable);
|
| - }
|
| + if ((index > 0 && backing_store->is_the_hole(index - 1)) ||
|
| + (index + 1 < length && backing_store->is_the_hole(index + 1))) {
|
| + int num_used = 0;
|
| + for (int i = 0; i < backing_store->length(); ++i) {
|
| + if (!backing_store->is_the_hole(i)) ++num_used;
|
| + // Bail out early if more than 1/4 is used.
|
| + if (4 * num_used > backing_store->length()) break;
|
| }
|
| - backing_store->set_the_hole(key);
|
| - // 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.
|
| - const int kMinLengthForSparsenessCheck = 64;
|
| - if (backing_store->length() >= kMinLengthForSparsenessCheck &&
|
| - !heap->InNewSpace(*backing_store) &&
|
| - ((key > 0 && backing_store->is_the_hole(key - 1)) ||
|
| - (key + 1 < length && backing_store->is_the_hole(key + 1)))) {
|
| - int num_used = 0;
|
| - for (int i = 0; i < backing_store->length(); ++i) {
|
| - if (!backing_store->is_the_hole(i)) ++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()) {
|
| - JSObject::NormalizeElements(obj);
|
| - }
|
| + if (4 * num_used <= backing_store->length()) {
|
| + JSObject::NormalizeElements(obj);
|
| }
|
| }
|
| }
|
| @@ -1193,9 +1153,15 @@ class FastElementsAccessor
|
| FastElementsAccessorSubclass::SetImpl(object->elements(), index, *value);
|
| }
|
|
|
| - virtual void Delete(Handle<JSObject> obj, uint32_t key,
|
| - LanguageMode language_mode) final {
|
| - DeleteCommon(obj, key, language_mode);
|
| + static void DeleteImpl(Handle<JSObject> obj, uint32_t index) {
|
| + ElementsKind kind = KindTraits::Kind;
|
| + if (IsFastPackedElementsKind(kind)) {
|
| + JSObject::TransitionElementsKind(obj, GetHoleyElementsKind(kind));
|
| + }
|
| + if (IsFastSmiOrObjectElementsKind(KindTraits::Kind)) {
|
| + JSObject::EnsureWritableFastElements(obj);
|
| + }
|
| + DeleteCommon(obj, index, handle(obj->elements()));
|
| }
|
|
|
| static bool HasIndexImpl(FixedArrayBase* backing_store, uint32_t index) {
|
| @@ -1436,9 +1402,8 @@ class TypedElementsAccessor
|
| UNREACHABLE();
|
| }
|
|
|
| - virtual void Delete(Handle<JSObject> obj, uint32_t key,
|
| - LanguageMode language_mode) final {
|
| - // External arrays always ignore deletes.
|
| + static void DeleteImpl(Handle<JSObject> obj, uint32_t index) {
|
| + UNREACHABLE();
|
| }
|
|
|
| static uint32_t GetIndexForKeyImpl(JSObject* holder,
|
| @@ -1514,19 +1479,6 @@ class SloppyArgumentsElementsAccessor
|
| }
|
| }
|
|
|
| - virtual void Delete(Handle<JSObject> obj, uint32_t key,
|
| - LanguageMode language_mode) final {
|
| - FixedArray* parameter_map = FixedArray::cast(obj->elements());
|
| - if (!GetParameterMapArg(parameter_map, key)->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(key + 2);
|
| - } else {
|
| - ArgumentsAccessor::DeleteCommon(obj, key, language_mode);
|
| - }
|
| - }
|
| -
|
| static void GrowCapacityAndConvertImpl(Handle<JSObject> object,
|
| uint32_t capacity) {
|
| UNREACHABLE();
|
| @@ -1612,6 +1564,20 @@ class SloppyArgumentsElementsAccessor
|
| ? parameter_map->get(key + 2)
|
| : Object::cast(parameter_map->GetHeap()->the_hole_value());
|
| }
|
| +
|
| + static void DeleteImpl(Handle<JSObject> obj, uint32_t index) {
|
| + FixedArray* parameter_map = FixedArray::cast(obj->elements());
|
| + uint32_t length = static_cast<uint32_t>(parameter_map->length()) - 2;
|
| + if (index < length) {
|
| + // 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 {
|
| + SloppyArgumentsElementsAccessorSubclass::DeleteFromArguments(
|
| + obj, index - length);
|
| + }
|
| + }
|
| };
|
|
|
|
|
| @@ -1625,6 +1591,19 @@ class SlowSloppyArgumentsElementsAccessor
|
| SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor,
|
| ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >(name) {}
|
|
|
| + static void DeleteFromArguments(Handle<JSObject> obj, uint32_t index) {
|
| + Handle<FixedArray> parameter_map(FixedArray::cast(obj->elements()));
|
| + Handle<SeededNumberDictionary> dict(
|
| + SeededNumberDictionary::cast(parameter_map->get(1)));
|
| + // TODO(verwaest): Remove reliance on key in Shrink.
|
| + uint32_t key = GetKeyForIndexImpl(*dict, index);
|
| + Handle<Object> result = SeededNumberDictionary::DeleteProperty(dict, index);
|
| + USE(result);
|
| + DCHECK(result->IsTrue());
|
| + Handle<FixedArray> new_elements = SeededNumberDictionary::Shrink(dict, key);
|
| + parameter_map->set(1, *new_elements);
|
| + }
|
| +
|
| static void AddImpl(Handle<JSObject> object, uint32_t key,
|
| Handle<Object> value, PropertyAttributes attributes,
|
| uint32_t new_capacity) {
|
| @@ -1693,6 +1672,12 @@ class FastSloppyArgumentsElementsAccessor
|
| FastHoleyObjectElementsAccessor,
|
| ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >(name) {}
|
|
|
| + static void DeleteFromArguments(Handle<JSObject> obj, uint32_t index) {
|
| + FixedArray* parameter_map = FixedArray::cast(obj->elements());
|
| + Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
|
| + FastHoleyObjectElementsAccessor::DeleteCommon(obj, index, arguments);
|
| + }
|
| +
|
| static void AddImpl(Handle<JSObject> object, uint32_t key,
|
| Handle<Object> value, PropertyAttributes attributes,
|
| uint32_t new_capacity) {
|
|
|