Move reconfiguration into the elements accessor
BUG=v8:4137 LOG=n Review URL: https://codereview.chromium.org/1207613005 Cr-Commit-Position: refs/heads/master@{#29289}
This commit is contained in:
parent
35eb3a0260
commit
f461c7a67a
@ -623,6 +623,21 @@ class ElementsAccessorBase : public ElementsAccessor {
|
||||
BackingStore::cast(backing_store)->SetValue(key, value);
|
||||
}
|
||||
|
||||
virtual void Reconfigure(Handle<JSObject> object,
|
||||
Handle<FixedArrayBase> store, uint32_t index,
|
||||
Handle<Object> value,
|
||||
PropertyAttributes attributes) final {
|
||||
ElementsAccessorSubclass::ReconfigureImpl(object, store, index, value,
|
||||
attributes);
|
||||
}
|
||||
|
||||
static void ReconfigureImpl(Handle<JSObject> object,
|
||||
Handle<FixedArrayBase> store, uint32_t index,
|
||||
Handle<Object> value,
|
||||
PropertyAttributes attributes) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
virtual MaybeHandle<AccessorPair> GetAccessorPair(
|
||||
Handle<JSObject> holder, uint32_t key,
|
||||
Handle<FixedArrayBase> backing_store) final {
|
||||
@ -903,6 +918,18 @@ class FastElementsAccessor
|
||||
explicit FastElementsAccessor(const char* name)
|
||||
: ElementsAccessorBase<FastElementsAccessorSubclass,
|
||||
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:
|
||||
friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>;
|
||||
friend class SloppyArgumentsElementsAccessor;
|
||||
@ -1409,10 +1436,23 @@ class DictionaryElementsAccessor
|
||||
}
|
||||
|
||||
static void SetImpl(FixedArrayBase* store, uint32_t key, Object* value) {
|
||||
SeededNumberDictionary* backing_store = SeededNumberDictionary::cast(store);
|
||||
int entry = backing_store->FindEntry(key);
|
||||
SeededNumberDictionary* dictionary = SeededNumberDictionary::cast(store);
|
||||
int entry = dictionary->FindEntry(key);
|
||||
DCHECK_NE(SeededNumberDictionary::kNotFound, entry);
|
||||
backing_store->ValueAtPut(entry, value);
|
||||
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 MaybeHandle<AccessorPair> GetAccessorPairImpl(
|
||||
@ -1533,6 +1573,44 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
|
||||
}
|
||||
}
|
||||
|
||||
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 =
|
||||
parameter_map->get(1)->IsSeededNumberDictionary()
|
||||
? handle(SeededNumberDictionary::cast(parameter_map->get(1)))
|
||||
: JSObject::NormalizeElements(object);
|
||||
arguments = SeededNumberDictionary::AddNumberEntry(arguments, index,
|
||||
value, details);
|
||||
parameter_map->set(1, *arguments);
|
||||
} else {
|
||||
Handle<FixedArrayBase> arguments(
|
||||
FixedArrayBase::cast(parameter_map->get(1)));
|
||||
ElementsAccessor::ForArray(arguments)
|
||||
->Reconfigure(object, arguments, index - length, value, attributes);
|
||||
}
|
||||
}
|
||||
|
||||
static MaybeHandle<AccessorPair> GetAccessorPairImpl(
|
||||
Handle<JSObject> obj, uint32_t key, Handle<FixedArrayBase> parameters) {
|
||||
Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters);
|
||||
|
@ -140,6 +140,10 @@ class ElementsAccessor {
|
||||
|
||||
virtual void Set(FixedArrayBase* backing_store, uint32_t key,
|
||||
Object* value) = 0;
|
||||
virtual void Reconfigure(Handle<JSObject> object,
|
||||
Handle<FixedArrayBase> backing_store, uint32_t index,
|
||||
Handle<Object> value,
|
||||
PropertyAttributes attributes) = 0;
|
||||
|
||||
protected:
|
||||
friend class SloppyArgumentsElementsAccessor;
|
||||
|
@ -156,19 +156,12 @@ void LookupIterator::ReconfigureDataProperty(Handle<Object> value,
|
||||
DCHECK(HolderIsReceiverOrHiddenPrototype());
|
||||
Handle<JSObject> holder = GetHolder<JSObject>();
|
||||
if (IsElement()) {
|
||||
// TODO(verwaest): Clean up.
|
||||
DCHECK(holder->HasFastElements() || holder->HasDictionaryElements() ||
|
||||
holder->HasSloppyArgumentsElements());
|
||||
DCHECK(!holder->HasExternalArrayElements());
|
||||
DCHECK(!holder->HasFixedTypedArrayElements());
|
||||
DCHECK(attributes != NONE || !holder->HasFastElements());
|
||||
Handle<SeededNumberDictionary> d = JSObject::NormalizeElements(holder);
|
||||
// TODO(verwaest): Move this into NormalizeElements.
|
||||
d->set_requires_slow_elements();
|
||||
if (holder->HasDictionaryElements()) {
|
||||
JSObject::SetDictionaryElement(holder, index(), value, attributes);
|
||||
} else {
|
||||
JSObject::SetDictionaryArgumentsElement(holder, index(), value,
|
||||
attributes);
|
||||
}
|
||||
Handle<FixedArrayBase> elements(holder->elements());
|
||||
holder->GetElementsAccessor()->Reconfigure(holder, elements, number_, value,
|
||||
attributes);
|
||||
} else if (holder_map_->is_dictionary_map()) {
|
||||
PropertyDetails details(attributes, v8::internal::DATA, 0,
|
||||
PropertyCellType::kMutable);
|
||||
|
@ -12292,89 +12292,6 @@ static void AddDictionaryElement(Handle<JSObject> object,
|
||||
}
|
||||
|
||||
|
||||
void JSObject::SetDictionaryArgumentsElement(Handle<JSObject> object,
|
||||
uint32_t index,
|
||||
Handle<Object> value,
|
||||
PropertyAttributes attributes) {
|
||||
// TODO(verwaest): Handle with the elements accessor.
|
||||
Isolate* isolate = object->GetIsolate();
|
||||
|
||||
DCHECK(object->HasDictionaryArgumentsElements());
|
||||
|
||||
Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
|
||||
uint32_t length = parameter_map->length();
|
||||
Handle<Object> probe =
|
||||
index < length - 2
|
||||
? handle(parameter_map->get(index + 2), isolate)
|
||||
: Handle<Object>::cast(isolate->factory()->the_hole_value());
|
||||
if (!probe->IsTheHole()) {
|
||||
Handle<Context> context(Context::cast(parameter_map->get(0)));
|
||||
int context_index = Handle<Smi>::cast(probe)->value();
|
||||
DCHECK(!context->get(context_index)->IsTheHole());
|
||||
context->set(context_index, *value);
|
||||
|
||||
DCHECK_NE(NONE, attributes);
|
||||
|
||||
// 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) {
|
||||
value = isolate->factory()->NewAliasedArgumentsEntry(context_index);
|
||||
}
|
||||
Handle<SeededNumberDictionary> dictionary(
|
||||
SeededNumberDictionary::cast(parameter_map->get(1)));
|
||||
AddDictionaryElement(object, dictionary, index, value, attributes);
|
||||
} else {
|
||||
SetDictionaryElement(object, index, value, attributes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void JSObject::SetDictionaryElement(Handle<JSObject> object, uint32_t index,
|
||||
Handle<Object> value,
|
||||
PropertyAttributes attributes) {
|
||||
// TODO(verwaest): Handle with the elements accessor.
|
||||
Isolate* isolate = object->GetIsolate();
|
||||
|
||||
// Insert element in the dictionary.
|
||||
Handle<FixedArray> elements(FixedArray::cast(object->elements()));
|
||||
bool is_arguments =
|
||||
(elements->map() == isolate->heap()->sloppy_arguments_elements_map());
|
||||
|
||||
DCHECK(object->HasDictionaryElements() ||
|
||||
object->HasDictionaryArgumentsElements());
|
||||
|
||||
Handle<SeededNumberDictionary> dictionary(is_arguments
|
||||
? SeededNumberDictionary::cast(elements->get(1))
|
||||
: SeededNumberDictionary::cast(*elements));
|
||||
|
||||
int entry = dictionary->FindEntry(index);
|
||||
DCHECK_NE(SeededNumberDictionary::kNotFound, entry);
|
||||
|
||||
PropertyDetails details = dictionary->DetailsAt(entry);
|
||||
details = PropertyDetails(attributes, DATA, details.dictionary_index(),
|
||||
PropertyCellType::kNoCell);
|
||||
dictionary->DetailsAtPut(entry, details);
|
||||
|
||||
// Elements of the arguments object in slow mode might be slow aliases.
|
||||
if (is_arguments) {
|
||||
Handle<Object> element(dictionary->ValueAt(entry), isolate);
|
||||
if (element->IsAliasedArgumentsEntry()) {
|
||||
Handle<AliasedArgumentsEntry> entry =
|
||||
Handle<AliasedArgumentsEntry>::cast(element);
|
||||
Handle<Context> context(Context::cast(elements->get(0)));
|
||||
int context_index = entry->aliased_context_slot();
|
||||
DCHECK(!context->get(context_index)->IsTheHole());
|
||||
context->set(context_index, *value);
|
||||
// For elements that are still writable we keep slow aliasing.
|
||||
if (!details.IsReadOnly()) value = element;
|
||||
}
|
||||
}
|
||||
|
||||
dictionary->ValueAtPut(entry, *value);
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
MaybeHandle<Object> JSReceiver::SetElement(Handle<JSReceiver> object,
|
||||
uint32_t index, Handle<Object> value,
|
||||
|
Loading…
Reference in New Issue
Block a user