| 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
 | 
| 
 |