| Index: src/elements.cc
|
| diff --git a/src/elements.cc b/src/elements.cc
|
| index 3c6e2726ce4f8803b2d23a8313aeb3ba57806dfe..2082543a2473a7ccde8db3f562669cd38e6102f7 100644
|
| --- a/src/elements.cc
|
| +++ b/src/elements.cc
|
| @@ -548,10 +548,7 @@ void CheckArrayAbuse(Handle<JSObject> obj, const char* op, uint32_t key,
|
| template <typename ElementsAccessorSubclass,
|
| typename ElementsTraitsParam>
|
| class ElementsAccessorBase : public ElementsAccessor {
|
| - protected:
|
| - template <typename SloppyArgumentsElementsAccessorSubclass,
|
| - typename ArgumentsAccessor, typename KindTraits>
|
| - friend class SloppyArgumentsElementsAccessor;
|
| + public:
|
| explicit ElementsAccessorBase(const char* name)
|
| : ElementsAccessor(name) { }
|
|
|
| @@ -864,7 +861,6 @@ class ElementsAccessorBase : public ElementsAccessor {
|
| return result;
|
| }
|
|
|
| - protected:
|
| static uint32_t GetCapacityImpl(JSObject* holder,
|
| FixedArrayBase* backing_store) {
|
| return backing_store->length();
|
| @@ -924,11 +920,200 @@ class ElementsAccessorBase : public ElementsAccessor {
|
| };
|
|
|
|
|
| -class FastSloppyArgumentsElementsAccessor;
|
| -class FastHoleyObjectElementsAccessor;
|
| -template <typename SloppyArgumentsElementsAccessorSubclass,
|
| - typename ArgumentsAccessor, typename KindTraits>
|
| -class SloppyArgumentsElementsAccessor;
|
| +class DictionaryElementsAccessor
|
| + : public ElementsAccessorBase<DictionaryElementsAccessor,
|
| + ElementsKindTraits<DICTIONARY_ELEMENTS> > {
|
| + public:
|
| + explicit DictionaryElementsAccessor(const char* name)
|
| + : ElementsAccessorBase<DictionaryElementsAccessor,
|
| + ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {}
|
| +
|
| + static void SetLengthImpl(Handle<JSArray> array, uint32_t length,
|
| + Handle<FixedArrayBase> backing_store) {
|
| + Handle<SeededNumberDictionary> dict =
|
| + Handle<SeededNumberDictionary>::cast(backing_store);
|
| + Isolate* isolate = array->GetIsolate();
|
| + int capacity = dict->Capacity();
|
| + uint32_t old_length = 0;
|
| + CHECK(array->length()->ToArrayLength(&old_length));
|
| + if (length < old_length) {
|
| + if (dict->requires_slow_elements()) {
|
| + // Find last non-deletable element in range of elements to be
|
| + // deleted and adjust range accordingly.
|
| + for (int i = 0; i < capacity; i++) {
|
| + DisallowHeapAllocation no_gc;
|
| + Object* key = dict->KeyAt(i);
|
| + if (key->IsNumber()) {
|
| + uint32_t number = static_cast<uint32_t>(key->Number());
|
| + if (length <= number && number < old_length) {
|
| + PropertyDetails details = dict->DetailsAt(i);
|
| + if (!details.IsConfigurable()) length = number + 1;
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + if (length == 0) {
|
| + // Flush the backing store.
|
| + JSObject::ResetElements(array);
|
| + } else {
|
| + DisallowHeapAllocation no_gc;
|
| + // Remove elements that should be deleted.
|
| + int removed_entries = 0;
|
| + Handle<Object> the_hole_value = isolate->factory()->the_hole_value();
|
| + for (int i = 0; i < capacity; i++) {
|
| + Object* key = dict->KeyAt(i);
|
| + if (key->IsNumber()) {
|
| + uint32_t number = static_cast<uint32_t>(key->Number());
|
| + if (length <= number && number < old_length) {
|
| + dict->SetEntry(i, the_hole_value, the_hole_value);
|
| + removed_entries++;
|
| + }
|
| + }
|
| + }
|
| +
|
| + // Update the number of elements.
|
| + dict->ElementsRemoved(removed_entries);
|
| + }
|
| + }
|
| +
|
| + Handle<Object> length_obj = isolate->factory()->NewNumberFromUint(length);
|
| + array->set_length(*length_obj);
|
| + }
|
| +
|
| + static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
|
| + FixedArrayBase* to, ElementsKind from_kind,
|
| + uint32_t to_start, int packed_size,
|
| + int copy_size) {
|
| + UNREACHABLE();
|
| + }
|
| +
|
| +
|
| + 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 Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key,
|
| + Handle<FixedArrayBase> store) {
|
| + Handle<SeededNumberDictionary> backing_store =
|
| + Handle<SeededNumberDictionary>::cast(store);
|
| + Isolate* isolate = backing_store->GetIsolate();
|
| + int entry = backing_store->FindEntry(key);
|
| + if (entry != SeededNumberDictionary::kNotFound) {
|
| + return handle(backing_store->ValueAt(entry), isolate);
|
| + }
|
| + return isolate->factory()->the_hole_value();
|
| + }
|
| +
|
| + static void SetImpl(FixedArrayBase* store, uint32_t key, Object* value) {
|
| + SeededNumberDictionary* dictionary = SeededNumberDictionary::cast(store);
|
| + int entry = dictionary->FindEntry(key);
|
| + DCHECK_NE(SeededNumberDictionary::kNotFound, entry);
|
| + dictionary->ValueAtPut(entry, value);
|
| + }
|
| +
|
| + static void ReconfigureImpl(Handle<JSObject> object,
|
| + Handle<FixedArrayBase> store, uint32_t index,
|
| + Handle<Object> value,
|
| + PropertyAttributes attributes) {
|
| + SeededNumberDictionary* dictionary = SeededNumberDictionary::cast(*store);
|
| + if (attributes != NONE) dictionary->set_requires_slow_elements();
|
| + dictionary->ValueAtPut(index, *value);
|
| + PropertyDetails details = dictionary->DetailsAt(index);
|
| + details = PropertyDetails(attributes, DATA, details.dictionary_index(),
|
| + PropertyCellType::kNoCell);
|
| + dictionary->DetailsAtPut(index, details);
|
| + }
|
| +
|
| + static void AddImpl(Handle<JSObject> object, uint32_t index,
|
| + Handle<Object> value, PropertyAttributes attributes,
|
| + uint32_t new_capacity) {
|
| + PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
|
| + Handle<SeededNumberDictionary> dictionary =
|
| + object->HasFastElements()
|
| + ? JSObject::NormalizeElements(object)
|
| + : handle(SeededNumberDictionary::cast(object->elements()));
|
| + Handle<SeededNumberDictionary> new_dictionary =
|
| + SeededNumberDictionary::AddNumberEntry(dictionary, index, value,
|
| + details);
|
| + if (attributes != NONE) new_dictionary->set_requires_slow_elements();
|
| + if (dictionary.is_identical_to(new_dictionary)) return;
|
| + object->set_elements(*new_dictionary);
|
| + }
|
| +
|
| + static MaybeHandle<AccessorPair> GetAccessorPairImpl(
|
| + Handle<JSObject> obj, uint32_t key, Handle<FixedArrayBase> store) {
|
| + Handle<SeededNumberDictionary> backing_store =
|
| + Handle<SeededNumberDictionary>::cast(store);
|
| + int entry = backing_store->FindEntry(key);
|
| + if (entry != SeededNumberDictionary::kNotFound &&
|
| + backing_store->DetailsAt(entry).type() == ACCESSOR_CONSTANT &&
|
| + backing_store->ValueAt(entry)->IsAccessorPair()) {
|
| + return handle(AccessorPair::cast(backing_store->ValueAt(entry)));
|
| + }
|
| + return MaybeHandle<AccessorPair>();
|
| + }
|
| +
|
| + static bool HasIndexImpl(FixedArrayBase* store, uint32_t index) {
|
| + DisallowHeapAllocation no_gc;
|
| + SeededNumberDictionary* dict = SeededNumberDictionary::cast(store);
|
| + Object* key = dict->KeyAt(index);
|
| + return !key->IsTheHole();
|
| + }
|
| +
|
| + static uint32_t GetKeyForIndexImpl(FixedArrayBase* store, uint32_t index) {
|
| + DisallowHeapAllocation no_gc;
|
| + SeededNumberDictionary* dict = SeededNumberDictionary::cast(store);
|
| + uint32_t result = 0;
|
| + CHECK(dict->KeyAt(index)->ToArrayIndex(&result));
|
| + return result;
|
| + }
|
| +
|
| + static uint32_t GetIndexForKeyImpl(JSObject* holder, FixedArrayBase* store,
|
| + uint32_t key) {
|
| + DisallowHeapAllocation no_gc;
|
| + SeededNumberDictionary* dict = SeededNumberDictionary::cast(store);
|
| + int entry = dict->FindEntry(key);
|
| + return entry == SeededNumberDictionary::kNotFound
|
| + ? kMaxUInt32
|
| + : static_cast<uint32_t>(entry);
|
| + }
|
| +
|
| + static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store,
|
| + uint32_t index) {
|
| + return SeededNumberDictionary::cast(backing_store)->DetailsAt(index);
|
| + }
|
| +};
|
| +
|
|
|
| // Super class for all fast element arrays.
|
| template<typename FastElementsAccessorSubclass,
|
| @@ -940,12 +1125,6 @@ class FastElementsAccessor
|
| : ElementsAccessorBase<FastElementsAccessorSubclass,
|
| KindTraits>(name) {}
|
|
|
| - protected:
|
| - friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>;
|
| - friend class SloppyArgumentsElementsAccessor<
|
| - FastSloppyArgumentsElementsAccessor, FastHoleyObjectElementsAccessor,
|
| - ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >;
|
| -
|
| typedef typename KindTraits::BackingStore BackingStore;
|
|
|
| static void DeleteCommon(Handle<JSObject> obj, uint32_t key,
|
| @@ -1011,8 +1190,8 @@ class FastElementsAccessor
|
| Handle<SeededNumberDictionary> dictionary =
|
| JSObject::NormalizeElements(object);
|
| index = dictionary->FindEntry(index);
|
| - object->GetElementsAccessor()->Reconfigure(object, dictionary, index, value,
|
| - attributes);
|
| + DictionaryElementsAccessor::ReconfigureImpl(object, dictionary, index,
|
| + value, attributes);
|
| }
|
|
|
| static void AddImpl(Handle<JSObject> object, uint32_t index,
|
| @@ -1186,7 +1365,6 @@ class FastDoubleElementsAccessor
|
| : FastElementsAccessor<FastElementsAccessorSubclass,
|
| KindTraits>(name) {}
|
|
|
| - protected:
|
| static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
|
| FixedArrayBase* to, ElementsKind from_kind,
|
| uint32_t to_start, int packed_size,
|
| @@ -1232,8 +1410,6 @@ class FastPackedDoubleElementsAccessor
|
| FastPackedDoubleElementsAccessor,
|
| ElementsKindTraits<FAST_DOUBLE_ELEMENTS> > {
|
| public:
|
| - friend class ElementsAccessorBase<FastPackedDoubleElementsAccessor,
|
| - ElementsKindTraits<FAST_DOUBLE_ELEMENTS> >;
|
| explicit FastPackedDoubleElementsAccessor(const char* name)
|
| : FastDoubleElementsAccessor<
|
| FastPackedDoubleElementsAccessor,
|
| @@ -1246,9 +1422,6 @@ class FastHoleyDoubleElementsAccessor
|
| FastHoleyDoubleElementsAccessor,
|
| ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> > {
|
| public:
|
| - friend class ElementsAccessorBase<
|
| - FastHoleyDoubleElementsAccessor,
|
| - ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> >;
|
| explicit FastHoleyDoubleElementsAccessor(const char* name)
|
| : FastDoubleElementsAccessor<
|
| FastHoleyDoubleElementsAccessor,
|
| @@ -1266,13 +1439,9 @@ class TypedElementsAccessor
|
| : ElementsAccessorBase<AccessorClass,
|
| ElementsKindTraits<Kind> >(name) {}
|
|
|
| - protected:
|
| typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore;
|
| typedef TypedElementsAccessor<Kind> AccessorClass;
|
|
|
| - friend class ElementsAccessorBase<AccessorClass,
|
| - ElementsKindTraits<Kind> >;
|
| -
|
| static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key,
|
| Handle<FixedArrayBase> backing_store) {
|
| if (key < AccessorClass::GetCapacityImpl(*obj, *backing_store)) {
|
| @@ -1331,268 +1500,58 @@ TYPED_ARRAYS(FIXED_ELEMENTS_ACCESSOR)
|
| #undef FIXED_ELEMENTS_ACCESSOR
|
|
|
|
|
| -class SlowSloppyArgumentsElementsAccessor;
|
| +template <typename SloppyArgumentsElementsAccessorSubclass,
|
| + typename ArgumentsAccessor, typename KindTraits>
|
| +class SloppyArgumentsElementsAccessor
|
| + : public ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass,
|
| + KindTraits> {
|
| + public:
|
| + explicit SloppyArgumentsElementsAccessor(const char* name)
|
| + : ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass,
|
| + KindTraits>(name) {}
|
|
|
| + static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key,
|
| + Handle<FixedArrayBase> parameters) {
|
| + Isolate* isolate = obj->GetIsolate();
|
| + Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters);
|
| + Handle<Object> probe(GetParameterMapArg(*parameter_map, key), isolate);
|
| + if (!probe->IsTheHole()) {
|
| + DisallowHeapAllocation no_gc;
|
| + Context* context = Context::cast(parameter_map->get(0));
|
| + int context_index = Handle<Smi>::cast(probe)->value();
|
| + DCHECK(!context->get(context_index)->IsTheHole());
|
| + return handle(context->get(context_index), isolate);
|
| + } else {
|
| + // Object is not mapped, defer to the arguments.
|
| + Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)),
|
| + isolate);
|
| + Handle<Object> result = ArgumentsAccessor::GetImpl(obj, key, arguments);
|
| + // Elements of the arguments object in slow mode might be slow aliases.
|
| + if (result->IsAliasedArgumentsEntry()) {
|
| + DisallowHeapAllocation no_gc;
|
| + AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(*result);
|
| + Context* context = Context::cast(parameter_map->get(0));
|
| + int context_index = entry->aliased_context_slot();
|
| + DCHECK(!context->get(context_index)->IsTheHole());
|
| + return handle(context->get(context_index), isolate);
|
| + } else {
|
| + return result;
|
| + }
|
| + }
|
| + }
|
|
|
| -class DictionaryElementsAccessor
|
| - : public ElementsAccessorBase<DictionaryElementsAccessor,
|
| - ElementsKindTraits<DICTIONARY_ELEMENTS> > {
|
| - public:
|
| - explicit DictionaryElementsAccessor(const char* name)
|
| - : ElementsAccessorBase<DictionaryElementsAccessor,
|
| - ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {}
|
| -
|
| - static void SetLengthImpl(Handle<JSArray> array, uint32_t length,
|
| - Handle<FixedArrayBase> backing_store) {
|
| - Handle<SeededNumberDictionary> dict =
|
| - Handle<SeededNumberDictionary>::cast(backing_store);
|
| - Isolate* isolate = array->GetIsolate();
|
| - int capacity = dict->Capacity();
|
| - uint32_t old_length = 0;
|
| - CHECK(array->length()->ToArrayLength(&old_length));
|
| - if (length < old_length) {
|
| - if (dict->requires_slow_elements()) {
|
| - // Find last non-deletable element in range of elements to be
|
| - // deleted and adjust range accordingly.
|
| - for (int i = 0; i < capacity; i++) {
|
| - DisallowHeapAllocation no_gc;
|
| - Object* key = dict->KeyAt(i);
|
| - if (key->IsNumber()) {
|
| - uint32_t number = static_cast<uint32_t>(key->Number());
|
| - if (length <= number && number < old_length) {
|
| - PropertyDetails details = dict->DetailsAt(i);
|
| - if (!details.IsConfigurable()) length = number + 1;
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - if (length == 0) {
|
| - // Flush the backing store.
|
| - JSObject::ResetElements(array);
|
| - } else {
|
| - DisallowHeapAllocation no_gc;
|
| - // Remove elements that should be deleted.
|
| - int removed_entries = 0;
|
| - Handle<Object> the_hole_value = isolate->factory()->the_hole_value();
|
| - for (int i = 0; i < capacity; i++) {
|
| - Object* key = dict->KeyAt(i);
|
| - if (key->IsNumber()) {
|
| - uint32_t number = static_cast<uint32_t>(key->Number());
|
| - if (length <= number && number < old_length) {
|
| - dict->SetEntry(i, the_hole_value, the_hole_value);
|
| - removed_entries++;
|
| - }
|
| - }
|
| - }
|
| -
|
| - // Update the number of elements.
|
| - dict->ElementsRemoved(removed_entries);
|
| - }
|
| - }
|
| -
|
| - Handle<Object> length_obj = isolate->factory()->NewNumberFromUint(length);
|
| - array->set_length(*length_obj);
|
| - }
|
| -
|
| - static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
|
| - FixedArrayBase* to, ElementsKind from_kind,
|
| - uint32_t to_start, int packed_size,
|
| - int copy_size) {
|
| - UNREACHABLE();
|
| - }
|
| -
|
| -
|
| - protected:
|
| - friend class ElementsAccessorBase<DictionaryElementsAccessor,
|
| - ElementsKindTraits<DICTIONARY_ELEMENTS> >;
|
| - friend class SlowSloppyArgumentsElementsAccessor;
|
| - friend class SloppyArgumentsElementsAccessor<
|
| - SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor,
|
| - ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >;
|
| -
|
| - 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 Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key,
|
| - Handle<FixedArrayBase> store) {
|
| - Handle<SeededNumberDictionary> backing_store =
|
| - Handle<SeededNumberDictionary>::cast(store);
|
| - Isolate* isolate = backing_store->GetIsolate();
|
| - int entry = backing_store->FindEntry(key);
|
| - if (entry != SeededNumberDictionary::kNotFound) {
|
| - return handle(backing_store->ValueAt(entry), isolate);
|
| - }
|
| - return isolate->factory()->the_hole_value();
|
| - }
|
| -
|
| - static void SetImpl(FixedArrayBase* store, uint32_t key, Object* value) {
|
| - SeededNumberDictionary* dictionary = SeededNumberDictionary::cast(store);
|
| - int entry = dictionary->FindEntry(key);
|
| - DCHECK_NE(SeededNumberDictionary::kNotFound, entry);
|
| - dictionary->ValueAtPut(entry, value);
|
| - }
|
| -
|
| - static void ReconfigureImpl(Handle<JSObject> object,
|
| - Handle<FixedArrayBase> store, uint32_t index,
|
| - Handle<Object> value,
|
| - PropertyAttributes attributes) {
|
| - SeededNumberDictionary* dictionary = SeededNumberDictionary::cast(*store);
|
| - if (attributes != NONE) dictionary->set_requires_slow_elements();
|
| - dictionary->ValueAtPut(index, *value);
|
| - PropertyDetails details = dictionary->DetailsAt(index);
|
| - details = PropertyDetails(attributes, DATA, details.dictionary_index(),
|
| - PropertyCellType::kNoCell);
|
| - dictionary->DetailsAtPut(index, details);
|
| - }
|
| -
|
| - static void AddImpl(Handle<JSObject> object, uint32_t index,
|
| - Handle<Object> value, PropertyAttributes attributes,
|
| - uint32_t new_capacity) {
|
| - PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
|
| - Handle<SeededNumberDictionary> dictionary =
|
| - object->HasFastElements()
|
| - ? JSObject::NormalizeElements(object)
|
| - : handle(SeededNumberDictionary::cast(object->elements()));
|
| - Handle<SeededNumberDictionary> new_dictionary =
|
| - SeededNumberDictionary::AddNumberEntry(dictionary, index, value,
|
| - details);
|
| - if (attributes != NONE) new_dictionary->set_requires_slow_elements();
|
| - if (dictionary.is_identical_to(new_dictionary)) return;
|
| - object->set_elements(*new_dictionary);
|
| - }
|
| -
|
| - static MaybeHandle<AccessorPair> GetAccessorPairImpl(
|
| - Handle<JSObject> obj, uint32_t key, Handle<FixedArrayBase> store) {
|
| - Handle<SeededNumberDictionary> backing_store =
|
| - Handle<SeededNumberDictionary>::cast(store);
|
| - int entry = backing_store->FindEntry(key);
|
| - if (entry != SeededNumberDictionary::kNotFound &&
|
| - backing_store->DetailsAt(entry).type() == ACCESSOR_CONSTANT &&
|
| - backing_store->ValueAt(entry)->IsAccessorPair()) {
|
| - return handle(AccessorPair::cast(backing_store->ValueAt(entry)));
|
| - }
|
| - return MaybeHandle<AccessorPair>();
|
| - }
|
| -
|
| - static bool HasIndexImpl(FixedArrayBase* store, uint32_t index) {
|
| - DisallowHeapAllocation no_gc;
|
| - SeededNumberDictionary* dict = SeededNumberDictionary::cast(store);
|
| - Object* key = dict->KeyAt(index);
|
| - return !key->IsTheHole();
|
| - }
|
| -
|
| - static uint32_t GetKeyForIndexImpl(FixedArrayBase* store, uint32_t index) {
|
| - DisallowHeapAllocation no_gc;
|
| - SeededNumberDictionary* dict = SeededNumberDictionary::cast(store);
|
| - uint32_t result = 0;
|
| - CHECK(dict->KeyAt(index)->ToArrayIndex(&result));
|
| - return result;
|
| - }
|
| -
|
| - static uint32_t GetIndexForKeyImpl(JSObject* holder, FixedArrayBase* store,
|
| - uint32_t key) {
|
| - DisallowHeapAllocation no_gc;
|
| - SeededNumberDictionary* dict = SeededNumberDictionary::cast(store);
|
| - int entry = dict->FindEntry(key);
|
| - return entry == SeededNumberDictionary::kNotFound
|
| - ? kMaxUInt32
|
| - : static_cast<uint32_t>(entry);
|
| - }
|
| -
|
| - static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store,
|
| - uint32_t index) {
|
| - return SeededNumberDictionary::cast(backing_store)->DetailsAt(index);
|
| - }
|
| -};
|
| -
|
| -
|
| -template <typename SloppyArgumentsElementsAccessorSubclass,
|
| - typename ArgumentsAccessor, typename KindTraits>
|
| -class SloppyArgumentsElementsAccessor
|
| - : public ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass,
|
| - KindTraits> {
|
| - public:
|
| - explicit SloppyArgumentsElementsAccessor(const char* name)
|
| - : ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass,
|
| - KindTraits>(name) {}
|
| -
|
| - protected:
|
| - friend class ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass,
|
| - KindTraits>;
|
| -
|
| - static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key,
|
| - Handle<FixedArrayBase> parameters) {
|
| - Isolate* isolate = obj->GetIsolate();
|
| - Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters);
|
| - Handle<Object> probe(GetParameterMapArg(*parameter_map, key), isolate);
|
| - if (!probe->IsTheHole()) {
|
| - DisallowHeapAllocation no_gc;
|
| - Context* context = Context::cast(parameter_map->get(0));
|
| - int context_index = Handle<Smi>::cast(probe)->value();
|
| - DCHECK(!context->get(context_index)->IsTheHole());
|
| - return handle(context->get(context_index), isolate);
|
| - } else {
|
| - // Object is not mapped, defer to the arguments.
|
| - Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)),
|
| - isolate);
|
| - Handle<Object> result = ArgumentsAccessor::GetImpl(obj, key, arguments);
|
| - // Elements of the arguments object in slow mode might be slow aliases.
|
| - if (result->IsAliasedArgumentsEntry()) {
|
| - DisallowHeapAllocation no_gc;
|
| - AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(*result);
|
| - Context* context = Context::cast(parameter_map->get(0));
|
| - int context_index = entry->aliased_context_slot();
|
| - DCHECK(!context->get(context_index)->IsTheHole());
|
| - return handle(context->get(context_index), isolate);
|
| - } else {
|
| - return result;
|
| - }
|
| - }
|
| - }
|
| -
|
| - 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);
|
| - }
|
| - }
|
| + 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) {
|
| @@ -1696,24 +1655,84 @@ class SloppyArgumentsElementsAccessor
|
| };
|
|
|
|
|
| +class SlowSloppyArgumentsElementsAccessor
|
| + : public SloppyArgumentsElementsAccessor<
|
| + SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor,
|
| + ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> > {
|
| + public:
|
| + explicit SlowSloppyArgumentsElementsAccessor(const char* name)
|
| + : SloppyArgumentsElementsAccessor<
|
| + SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor,
|
| + ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >(name) {}
|
| +
|
| + static void AddImpl(Handle<JSObject> object, uint32_t key,
|
| + Handle<Object> value, PropertyAttributes attributes,
|
| + uint32_t new_capacity) {
|
| + Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
|
| + Handle<FixedArrayBase> old_elements(
|
| + FixedArrayBase::cast(parameter_map->get(1)));
|
| + Handle<SeededNumberDictionary> dictionary =
|
| + old_elements->IsSeededNumberDictionary()
|
| + ? Handle<SeededNumberDictionary>::cast(old_elements)
|
| + : JSObject::NormalizeElements(object);
|
| + PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
|
| + Handle<SeededNumberDictionary> new_dictionary =
|
| + SeededNumberDictionary::AddNumberEntry(dictionary, key, value, details);
|
| + if (attributes != NONE) new_dictionary->set_requires_slow_elements();
|
| + if (*dictionary != *new_dictionary) {
|
| + FixedArray::cast(object->elements())->set(1, *new_dictionary);
|
| + }
|
| + }
|
| +
|
| + static void ReconfigureImpl(Handle<JSObject> object,
|
| + Handle<FixedArrayBase> store, uint32_t index,
|
| + Handle<Object> value,
|
| + PropertyAttributes attributes) {
|
| + Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(store);
|
| + uint32_t length = parameter_map->length() - 2;
|
| + if (index < length) {
|
| + Object* probe = parameter_map->get(index + 2);
|
| + DCHECK(!probe->IsTheHole());
|
| + Context* context = Context::cast(parameter_map->get(0));
|
| + int context_index = Smi::cast(probe)->value();
|
| + DCHECK(!context->get(context_index)->IsTheHole());
|
| + context->set(context_index, *value);
|
| +
|
| + // Redefining attributes of an aliased element destroys fast aliasing.
|
| + parameter_map->set_the_hole(index + 2);
|
| + // For elements that are still writable we re-establish slow aliasing.
|
| + if ((attributes & READ_ONLY) == 0) {
|
| + Isolate* isolate = store->GetIsolate();
|
| + value = isolate->factory()->NewAliasedArgumentsEntry(context_index);
|
| + }
|
| +
|
| + PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
|
| + Handle<SeededNumberDictionary> arguments(
|
| + SeededNumberDictionary::cast(parameter_map->get(1)));
|
| + arguments = SeededNumberDictionary::AddNumberEntry(arguments, index,
|
| + value, details);
|
| + parameter_map->set(1, *arguments);
|
| + } else {
|
| + Handle<FixedArrayBase> arguments(
|
| + FixedArrayBase::cast(parameter_map->get(1)));
|
| + DictionaryElementsAccessor::ReconfigureImpl(
|
| + object, arguments, index - length, value, attributes);
|
| + }
|
| + }
|
| +};
|
| +
|
| +
|
| class FastSloppyArgumentsElementsAccessor
|
| : public SloppyArgumentsElementsAccessor<
|
| FastSloppyArgumentsElementsAccessor, FastHoleyObjectElementsAccessor,
|
| ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> > {
|
| public:
|
| - friend class SloppyArgumentsElementsAccessor<
|
| - FastSloppyArgumentsElementsAccessor, FastHoleyObjectElementsAccessor,
|
| - ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >;
|
| - friend class ElementsAccessorBase<
|
| - FastSloppyArgumentsElementsAccessor,
|
| - ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >;
|
| explicit FastSloppyArgumentsElementsAccessor(const char* name)
|
| : SloppyArgumentsElementsAccessor<
|
| FastSloppyArgumentsElementsAccessor,
|
| FastHoleyObjectElementsAccessor,
|
| ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >(name) {}
|
|
|
| - protected:
|
| static void AddImpl(Handle<JSObject> object, uint32_t key,
|
| Handle<Object> value, PropertyAttributes attributes,
|
| uint32_t new_capacity) {
|
| @@ -1739,8 +1758,8 @@ class FastSloppyArgumentsElementsAccessor
|
| if (index >= length) {
|
| index = dictionary->FindEntry(index - length) + length;
|
| }
|
| - object->GetElementsAccessor()->Reconfigure(object, store, index, value,
|
| - attributes);
|
| + SlowSloppyArgumentsElementsAccessor::ReconfigureImpl(object, store, index,
|
| + value, attributes);
|
| }
|
|
|
| static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
|
| @@ -1778,80 +1797,6 @@ class FastSloppyArgumentsElementsAccessor
|
| };
|
|
|
|
|
| -class SlowSloppyArgumentsElementsAccessor
|
| - : public SloppyArgumentsElementsAccessor<
|
| - SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor,
|
| - ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> > {
|
| - public:
|
| - friend class ElementsAccessorBase<
|
| - SlowSloppyArgumentsElementsAccessor,
|
| - ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >;
|
| - friend class SloppyArgumentsElementsAccessor<
|
| - SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor,
|
| - ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >;
|
| - explicit SlowSloppyArgumentsElementsAccessor(const char* name)
|
| - : SloppyArgumentsElementsAccessor<
|
| - SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor,
|
| - ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >(name) {}
|
| -
|
| - protected:
|
| - static void AddImpl(Handle<JSObject> object, uint32_t key,
|
| - Handle<Object> value, PropertyAttributes attributes,
|
| - uint32_t new_capacity) {
|
| - Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
|
| - Handle<FixedArrayBase> old_elements(
|
| - FixedArrayBase::cast(parameter_map->get(1)));
|
| - Handle<SeededNumberDictionary> dictionary =
|
| - old_elements->IsSeededNumberDictionary()
|
| - ? Handle<SeededNumberDictionary>::cast(old_elements)
|
| - : JSObject::NormalizeElements(object);
|
| - PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
|
| - Handle<SeededNumberDictionary> new_dictionary =
|
| - SeededNumberDictionary::AddNumberEntry(dictionary, key, value, details);
|
| - if (attributes != NONE) new_dictionary->set_requires_slow_elements();
|
| - if (*dictionary != *new_dictionary) {
|
| - FixedArray::cast(object->elements())->set(1, *new_dictionary);
|
| - }
|
| - }
|
| -
|
| - static void ReconfigureImpl(Handle<JSObject> object,
|
| - Handle<FixedArrayBase> store, uint32_t index,
|
| - Handle<Object> value,
|
| - PropertyAttributes attributes) {
|
| - Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(store);
|
| - uint32_t length = parameter_map->length() - 2;
|
| - if (index < length) {
|
| - Object* probe = parameter_map->get(index + 2);
|
| - DCHECK(!probe->IsTheHole());
|
| - Context* context = Context::cast(parameter_map->get(0));
|
| - int context_index = Smi::cast(probe)->value();
|
| - DCHECK(!context->get(context_index)->IsTheHole());
|
| - context->set(context_index, *value);
|
| -
|
| - // Redefining attributes of an aliased element destroys fast aliasing.
|
| - parameter_map->set_the_hole(index + 2);
|
| - // For elements that are still writable we re-establish slow aliasing.
|
| - if ((attributes & READ_ONLY) == 0) {
|
| - Isolate* isolate = store->GetIsolate();
|
| - value = isolate->factory()->NewAliasedArgumentsEntry(context_index);
|
| - }
|
| -
|
| - PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
|
| - Handle<SeededNumberDictionary> arguments(
|
| - SeededNumberDictionary::cast(parameter_map->get(1)));
|
| - arguments = SeededNumberDictionary::AddNumberEntry(arguments, index,
|
| - value, details);
|
| - parameter_map->set(1, *arguments);
|
| - } else {
|
| - Handle<FixedArrayBase> arguments(
|
| - FixedArrayBase::cast(parameter_map->get(1)));
|
| - DictionaryElementsAccessor::ReconfigureImpl(
|
| - object, arguments, index - length, value, attributes);
|
| - }
|
| - }
|
| -};
|
| -
|
| -
|
| void ElementsAccessor::InitializeOncePerProcess() {
|
| static ElementsAccessor* accessor_array[] = {
|
| #define ACCESSOR_ARRAY(Class, Kind, Store) new Class(#Kind),
|
|
|