Commit 4ec41c35 authored by cbruni's avatar cbruni Committed by Commit bot

[elements] Add CreateFromArrayLike fast-path for JS_ARRAY_TYPE

Make apply calls with double array arguments such as
Math.min.apply(Math, [1.1, 2.2]) 1.6x faster.

Drive-by-fix: pass in the isolate to ElementsAccessor::GetImpl.

BUG=v8:4826

Review-Url: https://codereview.chromium.org/2521043005
Cr-Commit-Position: refs/heads/master@{#41268}
parent 9d0f5ab7
......@@ -604,7 +604,7 @@ class ElementsAccessorBase : public ElementsAccessor {
static bool HasElementImpl(Isolate* isolate, Handle<JSObject> holder,
uint32_t index,
Handle<FixedArrayBase> backing_store,
PropertyFilter filter) {
PropertyFilter filter = ALL_PROPERTIES) {
return Subclass::GetEntryForIndexImpl(isolate, *holder, *backing_store,
index, filter) != kMaxUInt32;
}
......@@ -619,15 +619,16 @@ class ElementsAccessorBase : public ElementsAccessor {
}
Handle<Object> Get(Handle<JSObject> holder, uint32_t entry) final {
return Subclass::GetImpl(holder, entry);
return Subclass::GetInternalImpl(holder, entry);
}
static Handle<Object> GetImpl(Handle<JSObject> holder, uint32_t entry) {
return Subclass::GetImpl(holder->elements(), entry);
static Handle<Object> GetInternalImpl(Handle<JSObject> holder,
uint32_t entry) {
return Subclass::GetImpl(holder->GetIsolate(), holder->elements(), entry);
}
static Handle<Object> GetImpl(FixedArrayBase* backing_store, uint32_t entry) {
Isolate* isolate = backing_store->GetIsolate();
static Handle<Object> GetImpl(Isolate* isolate, FixedArrayBase* backing_store,
uint32_t entry) {
uint32_t index = GetIndexForEntryImpl(backing_store, entry);
return handle(BackingStore::cast(backing_store)->get(index), isolate);
}
......@@ -1032,7 +1033,7 @@ class ElementsAccessorBase : public ElementsAccessor {
PropertyDetails details = Subclass::GetDetailsImpl(*object, entry);
if (details.kind() == kData) {
value = Subclass::GetImpl(object, entry);
value = Subclass::GetImpl(isolate, object->elements(), entry);
} else {
LookupIterator it(isolate, object, index, LookupIterator::OWN);
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
......@@ -1257,6 +1258,17 @@ class ElementsAccessorBase : public ElementsAccessor {
return Subclass::GetDetailsImpl(holder, entry);
}
Handle<FixedArray> CreateListFromArray(Isolate* isolate,
Handle<JSArray> array) final {
return Subclass::CreateListFromArrayImpl(isolate, array);
};
static Handle<FixedArray> CreateListFromArrayImpl(Isolate* isolate,
Handle<JSArray> array) {
UNREACHABLE();
return Handle<FixedArray>();
}
private:
DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase);
};
......@@ -1382,12 +1394,9 @@ class DictionaryElementsAccessor
return backing_store->ValueAt(entry);
}
static Handle<Object> GetImpl(Handle<JSObject> holder, uint32_t entry) {
return GetImpl(holder->elements(), entry);
}
static Handle<Object> GetImpl(FixedArrayBase* backing_store, uint32_t entry) {
return handle(GetRaw(backing_store, entry), backing_store->GetIsolate());
static Handle<Object> GetImpl(Isolate* isolate, FixedArrayBase* backing_store,
uint32_t entry) {
return handle(GetRaw(backing_store, entry), isolate);
}
static inline void SetImpl(Handle<JSObject> holder, uint32_t entry,
......@@ -1770,7 +1779,7 @@ class FastElementsAccessor : public ElementsAccessorBase<Subclass, KindTraits> {
if (IsHoleyElementsKind(kind)) {
if (BackingStore::cast(*store)->is_the_hole(isolate, i)) continue;
}
Handle<Object> value = Subclass::GetImpl(*store, i);
Handle<Object> value = Subclass::GetImpl(isolate, *store, i);
dictionary = SeededNumberDictionary::AddNumberEntry(
dictionary, i, value, details, used_as_prototype);
j++;
......@@ -1931,7 +1940,7 @@ class FastElementsAccessor : public ElementsAccessorBase<Subclass, KindTraits> {
for (uint32_t i = 0; i < length; i++) {
if (IsFastPackedElementsKind(KindTraits::Kind) ||
HasEntryImpl(isolate, *elements, i)) {
accumulator->AddKey(Subclass::GetImpl(*elements, i), convert);
accumulator->AddKey(Subclass::GetImpl(isolate, *elements, i), convert);
}
}
}
......@@ -2072,7 +2081,7 @@ class FastElementsAccessor : public ElementsAccessorBase<Subclass, KindTraits> {
uint32_t length = elements->length();
for (uint32_t index = 0; index < length; ++index) {
if (!HasEntryImpl(isolate, *elements, index)) continue;
Handle<Object> value = Subclass::GetImpl(*elements, index);
Handle<Object> value = Subclass::GetImpl(isolate, *elements, index);
if (get_entries) {
value = MakeEntryPair(isolate, index, value);
}
......@@ -2262,6 +2271,24 @@ class FastElementsAccessor : public ElementsAccessorBase<Subclass, KindTraits> {
}
}
static Handle<FixedArray> CreateListFromArrayImpl(Isolate* isolate,
Handle<JSArray> array) {
uint32_t length = 0;
array->length()->ToArrayLength(&length);
Handle<FixedArray> result = isolate->factory()->NewFixedArray(length);
Handle<FixedArrayBase> elements(array->elements(), isolate);
for (uint32_t i = 0; i < length; i++) {
if (!Subclass::HasElementImpl(isolate, array, i, elements)) continue;
Handle<Object> value;
value = Subclass::GetImpl(isolate, *elements, i);
if (value->IsName()) {
value = isolate->factory()->InternalizeName(Handle<Name>::cast(value));
}
result->set(i, *value);
}
return result;
}
private:
// SpliceShrinkStep might modify the backing_store.
static void SpliceShrinkStep(Isolate* isolate, Handle<JSArray> receiver,
......@@ -2320,7 +2347,8 @@ class FastElementsAccessor : public ElementsAccessorBase<Subclass, KindTraits> {
DCHECK(length > 0);
int new_length = length - 1;
int remove_index = remove_position == AT_START ? 0 : new_length;
Handle<Object> result = Subclass::GetImpl(*backing_store, remove_index);
Handle<Object> result =
Subclass::GetImpl(isolate, *backing_store, remove_index);
if (remove_position == AT_START) {
Subclass::MoveElements(isolate, receiver, backing_store, 0, 1, new_length,
0, 0);
......@@ -2541,12 +2569,8 @@ class FastDoubleElementsAccessor
explicit FastDoubleElementsAccessor(const char* name)
: FastElementsAccessor<Subclass, KindTraits>(name) {}
static Handle<Object> GetImpl(Handle<JSObject> holder, uint32_t entry) {
return GetImpl(holder->elements(), entry);
}
static Handle<Object> GetImpl(FixedArrayBase* backing_store, uint32_t entry) {
Isolate* isolate = backing_store->GetIsolate();
static Handle<Object> GetImpl(Isolate* isolate, FixedArrayBase* backing_store,
uint32_t entry) {
return FixedDoubleArray::get(FixedDoubleArray::cast(backing_store), entry,
isolate);
}
......@@ -2693,11 +2717,8 @@ class TypedElementsAccessor
BackingStore::cast(backing_store)->SetValue(entry, value);
}
static Handle<Object> GetImpl(Handle<JSObject> holder, uint32_t entry) {
return GetImpl(holder->elements(), entry);
}
static Handle<Object> GetImpl(FixedArrayBase* backing_store, uint32_t entry) {
static Handle<Object> GetImpl(Isolate* isolate, FixedArrayBase* backing_store,
uint32_t entry) {
return BackingStore::get(BackingStore::cast(backing_store), entry);
}
......@@ -2761,10 +2782,11 @@ class TypedElementsAccessor
static void AddElementsToKeyAccumulatorImpl(Handle<JSObject> receiver,
KeyAccumulator* accumulator,
AddKeyConversion convert) {
Isolate* isolate = receiver->GetIsolate();
Handle<FixedArrayBase> elements(receiver->elements());
uint32_t length = AccessorClass::GetCapacityImpl(*receiver, *elements);
for (uint32_t i = 0; i < length; i++) {
Handle<Object> value = AccessorClass::GetImpl(*elements, i);
Handle<Object> value = AccessorClass::GetImpl(isolate, *elements, i);
accumulator->AddKey(value, convert);
}
}
......@@ -2778,7 +2800,8 @@ class TypedElementsAccessor
Handle<FixedArrayBase> elements(object->elements());
uint32_t length = AccessorClass::GetCapacityImpl(*object, *elements);
for (uint32_t index = 0; index < length; ++index) {
Handle<Object> value = AccessorClass::GetImpl(*elements, index);
Handle<Object> value =
AccessorClass::GetImpl(isolate, *elements, index);
if (get_entries) {
value = MakeEntryPair(isolate, index, value);
}
......@@ -2901,12 +2924,8 @@ class SloppyArgumentsElementsAccessor
USE(KindTraits::Kind);
}
static Handle<Object> GetImpl(Handle<JSObject> holder, uint32_t entry) {
return GetImpl(holder->elements(), entry);
}
static Handle<Object> GetImpl(FixedArrayBase* parameters, uint32_t entry) {
Isolate* isolate = parameters->GetIsolate();
static Handle<Object> GetImpl(Isolate* isolate, FixedArrayBase* parameters,
uint32_t entry) {
Handle<FixedArray> parameter_map(FixedArray::cast(parameters), isolate);
uint32_t length = parameter_map->length() - 2;
if (entry < length) {
......@@ -2919,7 +2938,7 @@ class SloppyArgumentsElementsAccessor
} else {
// Object is not mapped, defer to the arguments.
Handle<Object> result = ArgumentsAccessor::GetImpl(
FixedArray::cast(parameter_map->get(1)), entry - length);
isolate, FixedArray::cast(parameter_map->get(1)), entry - length);
// Elements of the arguments object in slow mode might be slow aliases.
if (result->IsAliasedArgumentsEntry()) {
DisallowHeapAllocation no_gc;
......@@ -3017,7 +3036,7 @@ class SloppyArgumentsElementsAccessor
uint32_t length = GetCapacityImpl(*receiver, *elements);
for (uint32_t entry = 0; entry < length; entry++) {
if (!HasEntryImpl(isolate, *elements, entry)) continue;
Handle<Object> value = GetImpl(*elements, entry);
Handle<Object> value = GetImpl(isolate, *elements, entry);
accumulator->AddKey(value, convert);
}
}
......@@ -3153,7 +3172,8 @@ class SloppyArgumentsElementsAccessor
continue;
}
Handle<Object> element_k = GetImpl(*parameter_map, entry);
Handle<Object> element_k =
Subclass::GetImpl(isolate, *parameter_map, entry);
if (element_k->IsAccessorPair()) {
LookupIterator it(isolate, object, k, LookupIterator::OWN);
......@@ -3192,7 +3212,8 @@ class SloppyArgumentsElementsAccessor
continue;
}
Handle<Object> element_k = GetImpl(*parameter_map, entry);
Handle<Object> element_k =
Subclass::GetImpl(isolate, *parameter_map, entry);
if (element_k->IsAccessorPair()) {
LookupIterator it(isolate, object, k, LookupIterator::OWN);
......@@ -3337,7 +3358,7 @@ class FastSloppyArgumentsElementsAccessor
uint32_t entry = GetEntryForIndexImpl(isolate, *receiver, parameters, i,
ALL_PROPERTIES);
if (entry != kMaxUInt32 && HasEntryImpl(isolate, parameters, entry)) {
elements->set(insertion_index, *GetImpl(parameters, entry));
elements->set(insertion_index, *GetImpl(isolate, parameters, entry));
} else {
elements->set_the_hole(isolate, insertion_index);
}
......@@ -3437,6 +3458,11 @@ class StringWrapperElementsAccessor
USE(KindTraits::Kind);
}
static Handle<Object> GetInternalImpl(Handle<JSObject> holder,
uint32_t entry) {
return GetImpl(holder, entry);
}
static Handle<Object> GetImpl(Handle<JSObject> holder, uint32_t entry) {
Isolate* isolate = holder->GetIsolate();
Handle<String> string(GetString(*holder), isolate);
......@@ -3445,7 +3471,14 @@ class StringWrapperElementsAccessor
return isolate->factory()->LookupSingleCharacterStringFromCode(
String::Flatten(string)->Get(entry));
}
return BackingStoreAccessor::GetImpl(holder, entry - length);
return BackingStoreAccessor::GetImpl(isolate, holder->elements(),
entry - length);
}
static Handle<Object> GetImpl(Isolate* isolate, FixedArrayBase* elements,
uint32_t entry) {
UNREACHABLE();
return Handle<Object>();
}
static PropertyDetails GetDetailsImpl(JSObject* holder, uint32_t entry) {
......
......@@ -175,6 +175,9 @@ class ElementsAccessor {
ElementsKind source_kind,
Handle<FixedArrayBase> destination, int size) = 0;
virtual Handle<FixedArray> CreateListFromArray(Isolate* isolate,
Handle<JSArray> array) = 0;
protected:
friend class LookupIterator;
......
......@@ -858,10 +858,30 @@ MaybeHandle<Object> Object::GetMethod(Handle<JSReceiver> receiver,
return func;
}
namespace {
MaybeHandle<FixedArray> CreateListFromArrayLikeFastPath(
Isolate* isolate, Handle<Object> object, ElementTypes element_types) {
if (element_types != ElementTypes::kAll || !object->IsJSArray()) {
return MaybeHandle<FixedArray>();
}
Handle<JSArray> array = Handle<JSArray>::cast(object);
uint32_t length;
if (!array->HasArrayPrototype(isolate) ||
!array->length()->ToUint32(&length) || !array->HasFastElements() ||
!JSObject::PrototypeHasNoElements(isolate, *array)) {
return MaybeHandle<FixedArray>();
}
return array->GetElementsAccessor()->CreateListFromArray(isolate, array);
}
} // namespace
// static
MaybeHandle<FixedArray> Object::CreateListFromArrayLike(
Isolate* isolate, Handle<Object> object, ElementTypes element_types) {
// Fast-path for JS_ARRAY_TYPE.
MaybeHandle<FixedArray> fast_result =
CreateListFromArrayLikeFastPath(isolate, object, element_types);
if (!fast_result.is_null()) return fast_result;
// 1. ReturnIfAbrupt(object).
// 2. (default elementTypes -- not applicable.)
// 3. If Type(obj) is not Object, throw a TypeError exception.
......@@ -872,6 +892,7 @@ MaybeHandle<FixedArray> Object::CreateListFromArrayLike(
"CreateListFromArrayLike")),
FixedArray);
}
// 4. Let len be ? ToLength(? Get(obj, "length")).
Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
Handle<Object> raw_length_number;
......
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