Commit 9d0cd81d authored by verwaest's avatar verwaest Committed by Commit bot

Move slow classes above fast to directly call ReconfigureImpl, remove friends, make things public

BUG=v8:4137
LOG=n

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

Cr-Commit-Position: refs/heads/master@{#29455}
parent bef1cbfd
......@@ -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),
......
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