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) { |