Commit 4eed4970 authored by verwaest's avatar verwaest Committed by Commit bot

Move Add to the elements accessor for everything but dictionary-arguments

BUG=v8:4137
LOG=n

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

Cr-Commit-Position: refs/heads/master@{#29295}
parent 1d73a81a
...@@ -638,6 +638,19 @@ class ElementsAccessorBase : public ElementsAccessor { ...@@ -638,6 +638,19 @@ class ElementsAccessorBase : public ElementsAccessor {
UNREACHABLE(); UNREACHABLE();
} }
virtual void Add(Handle<JSObject> object, uint32_t index,
Handle<Object> value, PropertyAttributes attributes,
uint32_t new_capacity) final {
ElementsAccessorSubclass::AddImpl(object, index, value, attributes,
new_capacity);
}
static void AddImpl(Handle<JSObject> object, uint32_t index,
Handle<Object> value, PropertyAttributes attributes,
uint32_t new_capacity) {
UNREACHABLE();
}
virtual MaybeHandle<AccessorPair> GetAccessorPair( virtual MaybeHandle<AccessorPair> GetAccessorPair(
Handle<JSObject> holder, uint32_t key, Handle<JSObject> holder, uint32_t key,
Handle<FixedArrayBase> backing_store) final { Handle<FixedArrayBase> backing_store) final {
...@@ -919,17 +932,6 @@ class FastElementsAccessor ...@@ -919,17 +932,6 @@ class FastElementsAccessor
: ElementsAccessorBase<FastElementsAccessorSubclass, : ElementsAccessorBase<FastElementsAccessorSubclass,
KindTraits>(name) {} KindTraits>(name) {}
static void ReconfigureImpl(Handle<JSObject> object,
Handle<FixedArrayBase> store, uint32_t index,
Handle<Object> value,
PropertyAttributes attributes) {
Handle<SeededNumberDictionary> dictionary =
JSObject::NormalizeElements(object);
index = dictionary->FindEntry(index);
object->GetElementsAccessor()->Reconfigure(object, dictionary, index, value,
attributes);
}
protected: protected:
friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>; friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>;
friend class SloppyArgumentsElementsAccessor; friend class SloppyArgumentsElementsAccessor;
...@@ -992,6 +994,42 @@ class FastElementsAccessor ...@@ -992,6 +994,42 @@ class FastElementsAccessor
} }
} }
static void ReconfigureImpl(Handle<JSObject> object,
Handle<FixedArrayBase> store, uint32_t index,
Handle<Object> value,
PropertyAttributes attributes) {
Handle<SeededNumberDictionary> dictionary =
JSObject::NormalizeElements(object);
index = dictionary->FindEntry(index);
object->GetElementsAccessor()->Reconfigure(object, dictionary, index, value,
attributes);
}
static void AddImpl(Handle<JSObject> object, uint32_t index,
Handle<Object> value, PropertyAttributes attributes,
uint32_t new_capacity) {
DCHECK_EQ(NONE, attributes);
ElementsKind from_kind = object->GetElementsKind();
ElementsKind to_kind = FastElementsAccessorSubclass::kind();
if (IsDictionaryElementsKind(from_kind) ||
IsFastDoubleElementsKind(from_kind) !=
IsFastDoubleElementsKind(to_kind) ||
FastElementsAccessorSubclass::GetCapacityImpl(
*object, object->elements()) != new_capacity) {
FastElementsAccessorSubclass::GrowCapacityAndConvertImpl(object,
new_capacity);
} else {
if (from_kind != to_kind) {
JSObject::TransitionElementsKind(object, to_kind);
}
if (IsFastSmiOrObjectElementsKind(from_kind)) {
DCHECK(IsFastSmiOrObjectElementsKind(to_kind));
JSObject::EnsureWritableFastElements(object);
}
}
FastElementsAccessorSubclass::SetImpl(object->elements(), index, *value);
}
virtual void Delete(Handle<JSObject> obj, uint32_t key, virtual void Delete(Handle<JSObject> obj, uint32_t key,
LanguageMode language_mode) final { LanguageMode language_mode) final {
DeleteCommon(obj, key, language_mode); DeleteCommon(obj, key, language_mode);
...@@ -1455,6 +1493,22 @@ class DictionaryElementsAccessor ...@@ -1455,6 +1493,22 @@ class DictionaryElementsAccessor
dictionary->DetailsAtPut(index, details); 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( static MaybeHandle<AccessorPair> GetAccessorPairImpl(
Handle<JSObject> obj, uint32_t key, Handle<FixedArrayBase> store) { Handle<JSObject> obj, uint32_t key, Handle<FixedArrayBase> store) {
Handle<SeededNumberDictionary> backing_store = Handle<SeededNumberDictionary> backing_store =
...@@ -1478,8 +1532,9 @@ class DictionaryElementsAccessor ...@@ -1478,8 +1532,9 @@ class DictionaryElementsAccessor
static uint32_t GetKeyForIndexImpl(FixedArrayBase* store, uint32_t index) { static uint32_t GetKeyForIndexImpl(FixedArrayBase* store, uint32_t index) {
DisallowHeapAllocation no_gc; DisallowHeapAllocation no_gc;
SeededNumberDictionary* dict = SeededNumberDictionary::cast(store); SeededNumberDictionary* dict = SeededNumberDictionary::cast(store);
Object* key = dict->KeyAt(index); uint32_t result = 0;
return Smi::cast(key)->value(); CHECK(dict->KeyAt(index)->ToArrayIndex(&result));
return result;
} }
static uint32_t GetIndexForKeyImpl(JSObject* holder, FixedArrayBase* store, static uint32_t GetIndexForKeyImpl(JSObject* holder, FixedArrayBase* store,
...@@ -1611,6 +1666,20 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase< ...@@ -1611,6 +1666,20 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
} }
} }
static void AddImpl(Handle<JSObject> object, uint32_t key,
Handle<Object> value, PropertyAttributes attributes,
uint32_t new_capacity) {
DCHECK_EQ(NONE, attributes);
Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
Handle<FixedArrayBase> old_elements(
FixedArrayBase::cast(parameter_map->get(1)));
if (old_elements->IsSeededNumberDictionary() ||
static_cast<uint32_t>(old_elements->length()) < new_capacity) {
GrowCapacityAndConvertImpl(object, new_capacity);
}
SetImpl(object->elements(), key, *value);
}
static MaybeHandle<AccessorPair> GetAccessorPairImpl( static MaybeHandle<AccessorPair> GetAccessorPairImpl(
Handle<JSObject> obj, uint32_t key, Handle<FixedArrayBase> parameters) { Handle<JSObject> obj, uint32_t key, Handle<FixedArrayBase> parameters) {
Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters); Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters);
......
...@@ -144,6 +144,9 @@ class ElementsAccessor { ...@@ -144,6 +144,9 @@ class ElementsAccessor {
Handle<FixedArrayBase> backing_store, uint32_t index, Handle<FixedArrayBase> backing_store, uint32_t index,
Handle<Object> value, Handle<Object> value,
PropertyAttributes attributes) = 0; PropertyAttributes attributes) = 0;
virtual void Add(Handle<JSObject> object, uint32_t index,
Handle<Object> value, PropertyAttributes attributes,
uint32_t new_capacity) = 0;
protected: protected:
friend class SloppyArgumentsElementsAccessor; friend class SloppyArgumentsElementsAccessor;
......
...@@ -12316,31 +12316,6 @@ void JSObject::ValidateElements(Handle<JSObject> object) { ...@@ -12316,31 +12316,6 @@ void JSObject::ValidateElements(Handle<JSObject> object) {
} }
static void AddDictionaryElement(Handle<JSObject> object,
Handle<SeededNumberDictionary> dictionary,
uint32_t index, Handle<Object> value,
PropertyAttributes attributes) {
// TODO(verwaest): Handle with the elements accessor.
// Insert element in the dictionary.
#ifdef DEBUG
int entry = dictionary->FindEntry(index);
DCHECK_EQ(SeededNumberDictionary::kNotFound, entry);
#endif
PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
Handle<SeededNumberDictionary> new_dictionary =
SeededNumberDictionary::AddNumberEntry(dictionary, index, value, details);
if (*dictionary == *new_dictionary) return;
if (object->HasSloppyArgumentsElements()) {
FixedArray::cast(object->elements())->set(1, *new_dictionary);
} else {
object->set_elements(*new_dictionary);
}
}
// static // static
MaybeHandle<Object> JSReceiver::SetElement(Handle<JSReceiver> object, MaybeHandle<Object> JSReceiver::SetElement(Handle<JSReceiver> object,
uint32_t index, Handle<Object> value, uint32_t index, Handle<Object> value,
...@@ -12351,36 +12326,6 @@ MaybeHandle<Object> JSReceiver::SetElement(Handle<JSReceiver> object, ...@@ -12351,36 +12326,6 @@ MaybeHandle<Object> JSReceiver::SetElement(Handle<JSReceiver> object,
} }
static void AddFastElement(Handle<JSObject> object, uint32_t index,
Handle<Object> value, ElementsKind from_kind,
uint32_t array_length, uint32_t capacity,
uint32_t new_capacity) {
bool introduces_holes = !object->IsJSArray() || index > array_length;
ElementsKind to_kind = value->OptimalElementsKind();
if (IsHoleyElementsKind(from_kind)) to_kind = GetHoleyElementsKind(to_kind);
to_kind = IsMoreGeneralElementsKindTransition(from_kind, to_kind) ? to_kind
: from_kind;
if (introduces_holes) to_kind = GetHoleyElementsKind(to_kind);
ElementsAccessor* accessor = ElementsAccessor::ForKind(to_kind);
// Increase backing store capacity if that's been decided previously.
// The capacity is indicated as 0 if the incoming object was dictionary or
// slow-mode sloppy arguments.
if (capacity != new_capacity ||
IsFastDoubleElementsKind(from_kind) !=
IsFastDoubleElementsKind(to_kind)) {
accessor->GrowCapacityAndConvert(object, new_capacity);
} else if (from_kind != to_kind) {
JSObject::TransitionElementsKind(object, to_kind);
}
accessor->Set(object->elements(), index, *value);
}
// Do we want to keep fast elements when adding an element at |index|? Returns
// |new_capacity| indicating to which capacity the object should be increased.
static bool ShouldConvertToSlowElements(JSObject* object, uint32_t capacity, static bool ShouldConvertToSlowElements(JSObject* object, uint32_t capacity,
uint32_t index, uint32_t index,
uint32_t* new_capacity) { uint32_t* new_capacity) {
...@@ -12476,10 +12421,7 @@ MaybeHandle<Object> JSObject::AddDataElement(Handle<JSObject> object, ...@@ -12476,10 +12421,7 @@ MaybeHandle<Object> JSObject::AddDataElement(Handle<JSObject> object,
Isolate* isolate = object->GetIsolate(); Isolate* isolate = object->GetIsolate();
ElementsKind kind = object->GetElementsKind();
bool handle_slow;
uint32_t old_length = 0; uint32_t old_length = 0;
uint32_t old_capacity = 0;
uint32_t new_capacity = 0; uint32_t new_capacity = 0;
Handle<Object> old_length_handle; Handle<Object> old_length_handle;
...@@ -12490,38 +12432,50 @@ MaybeHandle<Object> JSObject::AddDataElement(Handle<JSObject> object, ...@@ -12490,38 +12432,50 @@ MaybeHandle<Object> JSObject::AddDataElement(Handle<JSObject> object,
} }
} }
Handle<SeededNumberDictionary> dictionary; ElementsKind kind = object->GetElementsKind();
FixedArrayBase* elements = object->elements(); FixedArrayBase* elements = object->elements();
if (IsSloppyArgumentsElements(kind)) { if (IsSloppyArgumentsElements(kind)) {
elements = FixedArrayBase::cast(FixedArray::cast(elements)->get(1)); elements = FixedArrayBase::cast(FixedArray::cast(elements)->get(1));
} }
if (elements->IsSeededNumberDictionary()) { if (attributes != NONE) {
dictionary = handle(SeededNumberDictionary::cast(elements)); kind = DICTIONARY_ELEMENTS;
handle_slow = attributes != NONE || } else if (elements->IsSeededNumberDictionary()) {
!ShouldConvertToFastElements(*object, *dictionary, index, kind = ShouldConvertToFastElements(*object,
&new_capacity); SeededNumberDictionary::cast(elements),
if (!handle_slow) kind = BestFittingFastElementsKind(*object); index, &new_capacity)
} else { ? BestFittingFastElementsKind(*object)
old_capacity = static_cast<uint32_t>(elements->length()); : DICTIONARY_ELEMENTS; // Overwrite in case of arguments.
handle_slow = } else if (ShouldConvertToSlowElements(
attributes != NONE || ShouldConvertToSlowElements(*object, old_capacity, *object, static_cast<uint32_t>(elements->length()), index,
index, &new_capacity); &new_capacity)) {
if (handle_slow) { kind = DICTIONARY_ELEMENTS;
dictionary = NormalizeElements(object); }
} else if (IsFastSmiOrObjectElementsKind(kind)) {
EnsureWritableFastElements(object); if (kind == DICTIONARY_ELEMENTS && object->HasSloppyArgumentsElements()) {
} // TODO(verwaest): Distinguish fast/slow sloppy elements in ElementsKind.
Handle<SeededNumberDictionary> dictionary =
elements->IsSeededNumberDictionary()
? handle(SeededNumberDictionary::cast(elements))
: NormalizeElements(object);
PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
Handle<SeededNumberDictionary> new_dictionary =
SeededNumberDictionary::AddNumberEntry(dictionary, index, value,
details);
if (attributes != NONE) new_dictionary->set_requires_slow_elements();
if (*dictionary != *new_dictionary) {
FixedArray::cast(object->elements())->set(1, *new_dictionary);
} }
if (handle_slow) {
if (attributes != NONE) dictionary->set_requires_slow_elements();
DCHECK(object->HasDictionaryElements() ||
object->HasDictionaryArgumentsElements());
AddDictionaryElement(object, dictionary, index, value, attributes);
} else { } else {
AddFastElement(object, index, value, kind, old_length, old_capacity, ElementsKind to = value->OptimalElementsKind();
new_capacity); if (IsHoleyElementsKind(kind) || !object->IsJSArray() ||
index > old_length) {
to = GetHoleyElementsKind(to);
kind = GetHoleyElementsKind(kind);
}
to = IsMoreGeneralElementsKindTransition(kind, to) ? to : kind;
ElementsAccessor* accessor = ElementsAccessor::ForKind(to);
accessor->Add(object, index, value, attributes, new_capacity);
} }
uint32_t new_length = old_length; uint32_t new_length = old_length;
......
...@@ -394,24 +394,6 @@ RUNTIME_FUNCTION(Runtime_GetProperty) { ...@@ -394,24 +394,6 @@ RUNTIME_FUNCTION(Runtime_GetProperty) {
} }
MUST_USE_RESULT static MaybeHandle<Object> TransitionElements(
Handle<Object> object, ElementsKind to_kind, Isolate* isolate) {
HandleScope scope(isolate);
if (!object->IsJSObject()) {
isolate->ThrowIllegalOperation();
return MaybeHandle<Object>();
}
ElementsKind from_kind =
Handle<JSObject>::cast(object)->map()->elements_kind();
if (Map::IsValidElementsTransition(from_kind, to_kind)) {
JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), to_kind);
return object;
}
isolate->ThrowIllegalOperation();
return MaybeHandle<Object>();
}
// KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric. // KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
RUNTIME_FUNCTION(Runtime_KeyedGetProperty) { RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
HandleScope scope(isolate); HandleScope scope(isolate);
...@@ -470,15 +452,11 @@ RUNTIME_FUNCTION(Runtime_KeyedGetProperty) { ...@@ -470,15 +452,11 @@ RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
Handle<JSObject> js_object = Handle<JSObject>::cast(receiver_obj); Handle<JSObject> js_object = Handle<JSObject>::cast(receiver_obj);
ElementsKind elements_kind = js_object->GetElementsKind(); ElementsKind elements_kind = js_object->GetElementsKind();
if (IsFastDoubleElementsKind(elements_kind)) { if (IsFastDoubleElementsKind(elements_kind)) {
Handle<Smi> key = Handle<Smi>::cast(key_obj); if (Smi::cast(*key_obj)->value() >= js_object->elements()->length()) {
if (key->value() >= js_object->elements()->length()) { elements_kind = IsFastHoleyElementsKind(elements_kind)
if (IsFastHoleyElementsKind(elements_kind)) { ? FAST_HOLEY_ELEMENTS
elements_kind = FAST_HOLEY_ELEMENTS; : FAST_ELEMENTS;
} else { JSObject::TransitionElementsKind(js_object, elements_kind);
elements_kind = FAST_ELEMENTS;
}
RETURN_FAILURE_ON_EXCEPTION(
isolate, TransitionElements(js_object, elements_kind, isolate));
} }
} else { } else {
DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) || DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment