| Index: src/runtime/runtime-array.cc
|
| diff --git a/src/runtime/runtime-array.cc b/src/runtime/runtime-array.cc
|
| index 3c5e817de9a5e124c7a58827a771b76a3d2b1c36..4b7cd398359fb6bdb2e6e07b88555361c3573d2a 100644
|
| --- a/src/runtime/runtime-array.cc
|
| +++ b/src/runtime/runtime-array.cc
|
| @@ -70,6 +70,7 @@ RUNTIME_FUNCTION(Runtime_SpecialArrayFunctions) {
|
| InstallBuiltin(isolate, holder, "slice", Builtins::kArraySlice);
|
| InstallBuiltin(isolate, holder, "splice", Builtins::kArraySplice);
|
| InstallBuiltin(isolate, holder, "includes", Builtins::kArrayIncludes, 2);
|
| + InstallBuiltin(isolate, holder, "indexOf", Builtins::kArrayIndexOf, 2);
|
|
|
| return *holder;
|
| }
|
| @@ -544,5 +545,105 @@ RUNTIME_FUNCTION(Runtime_ArrayIncludes_Slow) {
|
| return isolate->heap()->false_value();
|
| }
|
|
|
| +RUNTIME_FUNCTION(Runtime_ArrayIndexOf) {
|
| + HandleScope shs(isolate);
|
| + DCHECK(args.length() == 3);
|
| + CONVERT_ARG_HANDLE_CHECKED(Object, search_element, 1);
|
| + CONVERT_ARG_HANDLE_CHECKED(Object, from_index, 2);
|
| +
|
| + // Let O be ? ToObject(this value).
|
| + Handle<Object> receiver_obj = args.at<Object>(0);
|
| + if (receiver_obj->IsNull(isolate) || receiver_obj->IsUndefined(isolate)) {
|
| + THROW_NEW_ERROR_RETURN_FAILURE(
|
| + isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
|
| + isolate->factory()->NewStringFromAsciiChecked(
|
| + "Array.prototype.indexOf")));
|
| + }
|
| + Handle<JSReceiver> object;
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
| + isolate, object, Object::ToObject(isolate, args.at<Object>(0)));
|
| +
|
| + // Let len be ? ToLength(? Get(O, "length")).
|
| + int64_t len;
|
| + {
|
| + if (object->IsJSArray()) {
|
| + uint32_t len32 = 0;
|
| + bool success = JSArray::cast(*object)->length()->ToArrayLength(&len32);
|
| + DCHECK(success);
|
| + USE(success);
|
| + len = len32;
|
| + } else {
|
| + Handle<Object> len_;
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
| + isolate, len_,
|
| + Object::GetProperty(object, isolate->factory()->length_string()));
|
| +
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, len_,
|
| + Object::ToLength(isolate, len_));
|
| + len = static_cast<int64_t>(len_->Number());
|
| + DCHECK_EQ(len, len_->Number());
|
| + }
|
| + }
|
| +
|
| + if (len == 0) return Smi::FromInt(-1);
|
| +
|
| + // Let n be ? ToInteger(fromIndex). (If fromIndex is undefined, this step
|
| + // produces the value 0.)
|
| + int64_t start_from;
|
| + {
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, from_index,
|
| + Object::ToInteger(isolate, from_index));
|
| + double fp = from_index->Number();
|
| + if (fp > len) return Smi::FromInt(-1);
|
| + start_from = static_cast<int64_t>(fp);
|
| + }
|
| +
|
| + int64_t index;
|
| + if (start_from >= 0) {
|
| + index = start_from;
|
| + } else {
|
| + index = len + start_from;
|
| + if (index < 0) {
|
| + index = 0;
|
| + }
|
| + }
|
| +
|
| + // If the receiver is not a special receiver type, and the length is a valid
|
| + // element index, perform fast operation tailored to specific ElementsKinds.
|
| + if (object->map()->instance_type() > LAST_SPECIAL_RECEIVER_TYPE &&
|
| + len < kMaxUInt32 &&
|
| + JSObject::PrototypeHasNoElements(isolate, JSObject::cast(*object))) {
|
| + Handle<JSObject> obj = Handle<JSObject>::cast(object);
|
| + ElementsAccessor* elements = obj->GetElementsAccessor();
|
| + Maybe<int64_t> result = elements->IndexOfValue(isolate, obj, search_element,
|
| + static_cast<uint32_t>(index),
|
| + static_cast<uint32_t>(len));
|
| + MAYBE_RETURN(result, isolate->heap()->exception());
|
| + return *isolate->factory()->NewNumberFromInt64(result.FromJust());
|
| + }
|
| +
|
| + // Otherwise, perform slow lookups for special receiver types
|
| + for (; index < len; ++index) {
|
| + // Let elementK be the result of ? Get(O, ! ToString(k)).
|
| + Handle<Object> element_k;
|
| + {
|
| + Handle<Object> index_obj = isolate->factory()->NewNumberFromInt64(index);
|
| + bool success;
|
| + LookupIterator it = LookupIterator::PropertyOrElement(
|
| + isolate, object, index_obj, &success);
|
| + DCHECK(success);
|
| + if (!JSReceiver::HasProperty(&it).FromJust()) {
|
| + continue;
|
| + }
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, element_k,
|
| + Object::GetProperty(&it));
|
| + if (search_element->StrictEquals(*element_k)) {
|
| + return *index_obj;
|
| + }
|
| + }
|
| + }
|
| + return Smi::FromInt(-1);
|
| +}
|
| +
|
| } // namespace internal
|
| } // namespace v8
|
|
|